Compare commits
127 Commits
R3.12.0-be
...
R3.12.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef12c444d8 | ||
|
|
cded07df78 | ||
|
|
81fb796c8d | ||
|
|
b3af9b389a | ||
|
|
9b76f9d9c0 | ||
|
|
302f4ef6c8 | ||
|
|
64b7a679a0 | ||
|
|
e9624769cb | ||
|
|
5ccee17d09 | ||
|
|
5e67b97e89 | ||
|
|
7cd16f8ad6 | ||
|
|
b5aa0e300c | ||
|
|
c27c38d531 | ||
|
|
b46166314f | ||
|
|
593df59742 | ||
|
|
561e2e9fb9 | ||
|
|
18b173eeb6 | ||
|
|
47b3da99a0 | ||
|
|
dd0ce8918a | ||
|
|
a655930baf | ||
|
|
84773e71a0 | ||
|
|
214b9ae5c1 | ||
|
|
420249caac | ||
|
|
17a0f487a8 | ||
|
|
bbfcd9ff78 | ||
|
|
b9dc0dad91 | ||
|
|
50be068a02 | ||
|
|
a90bdf0098 | ||
|
|
a58a2439cd | ||
|
|
962b520be8 | ||
|
|
6747d4e0e9 | ||
|
|
043eeb6a7c | ||
|
|
6b50908dd6 | ||
|
|
2d9514e8ad | ||
|
|
2e7e1416d3 | ||
|
|
ed2f5648b2 | ||
|
|
96da4b1121 | ||
|
|
3c6191cccd | ||
|
|
60a488940c | ||
|
|
1c1d8228c7 | ||
|
|
b2ee2f2347 | ||
|
|
2c2673dcea | ||
|
|
0e760bfc70 | ||
|
|
f0234af637 | ||
|
|
96f58790c4 | ||
|
|
2c1004fb41 | ||
|
|
f6025d2a1f | ||
|
|
4d046c8424 | ||
|
|
e7e17f07af | ||
|
|
8a23d381c4 | ||
|
|
46b9bb6e6a | ||
|
|
9ab85124d3 | ||
|
|
b8f07e873d | ||
|
|
0cfd58942f | ||
|
|
b75d3964d7 | ||
|
|
b9c8cd50e0 | ||
|
|
e7b8b42452 | ||
|
|
4cc62a1fce | ||
|
|
333c985399 | ||
|
|
f513681bc0 | ||
|
|
ddb459d08a | ||
|
|
6aa5ecfa0e | ||
|
|
9bdea89b06 | ||
|
|
3c8b4bf8c0 | ||
|
|
a912205614 | ||
|
|
3b094ac9ae | ||
|
|
13a7380a47 | ||
|
|
f1bc683bd4 | ||
|
|
5d3ded4397 | ||
|
|
4a5cb2a6e5 | ||
|
|
9300dded40 | ||
|
|
cb86cd03a7 | ||
|
|
cee91cb578 | ||
|
|
679e1b8a56 | ||
|
|
f6d91b8876 | ||
|
|
a86c813415 | ||
|
|
be2491bc51 | ||
|
|
1634c70c06 | ||
|
|
df876abf50 | ||
|
|
d5873d5e8a | ||
|
|
b6c87ce10e | ||
|
|
00d40d3e73 | ||
|
|
410e6d9c00 | ||
|
|
03944c94e3 | ||
|
|
b5f31b4b13 | ||
|
|
7bb7e8a884 | ||
|
|
d153387372 | ||
|
|
d4a4b23a55 | ||
|
|
14a152ba72 | ||
|
|
20b6539144 | ||
|
|
93b6da9b3c | ||
|
|
542c0115c5 | ||
|
|
15440b9b6c | ||
|
|
4cb9699c03 | ||
|
|
6460c2fc1d | ||
|
|
9b858b8a5f | ||
|
|
ed30327d93 | ||
|
|
35aba51c7f | ||
|
|
12fd359a3c | ||
|
|
e0b6ce3867 | ||
|
|
c5fce1bd6c | ||
|
|
2dfbf28c1b | ||
|
|
32add4c78f | ||
|
|
9ea5c86ab5 | ||
|
|
48efca8456 | ||
|
|
382c496b24 | ||
|
|
13173544a9 | ||
|
|
19bf9ec448 | ||
|
|
a08656090e | ||
|
|
7b03f77e30 | ||
|
|
80dbdf6814 | ||
|
|
103bd7492a | ||
|
|
e55693525c | ||
|
|
64bd8e03dc | ||
|
|
49b77d096f | ||
|
|
ae720e75af | ||
|
|
bca7b39ab6 | ||
|
|
3600bb9513 | ||
|
|
339d08b71d | ||
|
|
687e1a2c16 | ||
|
|
a53bffb128 | ||
|
|
4a7c1b1715 | ||
|
|
e75c3729b8 | ||
|
|
7cc6c1993d | ||
|
|
63a3b6827c | ||
|
|
b1f570f66d | ||
|
|
239e6cfa2e |
20
README
20
README
@@ -10,11 +10,13 @@ Notes:
|
||||
1. Before you can build or really use EPICS, you must set your
|
||||
path properly:
|
||||
|
||||
set path = ( $path EPICS/base/tools EPICS/base/bin/HOST_ARCH )
|
||||
set path = ( $path EPICS/base/tools EPICS/base/bin/HOST_ARCH \
|
||||
EPICS/extensions/bin HOST_ARCH )
|
||||
|
||||
e.g.:
|
||||
|
||||
set path = ( $path /home/epics/base/tools /home/epics/base/bin/sun4 )
|
||||
set path = ( $path /home/epics/base/tools /home/epics/base/bin/sun4 \
|
||||
/home/epics/extensions/bin/sun4 )
|
||||
|
||||
2. You must use GNU make (which is now THE supported make utility) for
|
||||
the build. A script, gmake, exists in the base/tools directory to invoke
|
||||
@@ -130,11 +132,16 @@ define compile and link flags.
|
||||
----------------------------------------------------------------------------
|
||||
CONFIG_COMMON - Contains definitions describing the layout of base.
|
||||
----------------------------------------------------------------------------
|
||||
HRULES - Rules for traversing hierarchical directories.
|
||||
CONFIG_BASE
|
||||
CONFIG_EXTENSIONS - Defines what subdirectories get built by default under
|
||||
base and extensions.
|
||||
----------------------------------------------------------------------------
|
||||
RULES.Vx - Rules for building with VxWorks makefiles.
|
||||
----------------------------------------------------------------------------
|
||||
RULES.Unix - Rules for building with Unix makefiles.
|
||||
----------------------------------------------------------------------------
|
||||
RULES_ARCHS
|
||||
RULES_DIRS - Allows top-level type command syntax in low-level directories.
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Table of files to change when building and adding architectures.
|
||||
@@ -149,10 +156,13 @@ CONFIG_SITE.Unix.ARCH_CLASS m - c* -
|
||||
CONFIG_SITE.Vx.ARCH_CLASS m c* - -
|
||||
CONFIG.Unix.ARCH_CLASS - - c* -
|
||||
CONFIG.Vx.ARCH_CLASS - c* - -
|
||||
CONFIG_COMMON - - - -
|
||||
HRULES - - - -
|
||||
RULES.Vx - - - -
|
||||
RULES.Unix - - - -
|
||||
CONFIG_BASE - - - -
|
||||
CONFIG_EXTENSIONS - - - -
|
||||
CONFIG_COMMON - - - -
|
||||
RULES_ARCHS - - - -
|
||||
RULES_DIRS - - - -
|
||||
|
||||
m - Modify an existing file.
|
||||
c - Create a new file.
|
||||
|
||||
@@ -52,6 +52,10 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
|
||||
* .01 10-15-93 mrk Initial Implementation
|
||||
*/
|
||||
|
||||
#ifdef vxWorks
|
||||
#include <vxWorks.h>
|
||||
#include <taskLib.h>
|
||||
#endif
|
||||
#include <dbDefs.h>
|
||||
#include <asLib.h>
|
||||
#include <string.h>
|
||||
@@ -60,9 +64,6 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
|
||||
#include <stdio.h>
|
||||
#include <gpHash.h>
|
||||
#include <freeList.h>
|
||||
#ifdef vxWorks
|
||||
#include <taskLib.h>
|
||||
#endif
|
||||
|
||||
/*Declare storage for Global Variables */
|
||||
ASBASE *pasbase=NULL;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
integer [0-9]
|
||||
name [a-zA-Z0-9_\.]
|
||||
pvname [a-zA-Z0-9_:\.\[\]<>]
|
||||
pvname [a-zA-Z0-9_:\.\[\]<>;]
|
||||
string [a-zA-Z0-9_\,\./\*#\[\]%: ;!|\'\-&\(\)@\?\+<>=\$]
|
||||
|
||||
%{
|
||||
|
||||
@@ -19,9 +19,27 @@ $! Arguments : optional source file name
|
||||
$!
|
||||
$! Created 16-NOV-1993 Mark L. Rivers
|
||||
$! 05-MAY-1994 Jeff O. Hill Updated for EPICS 3.12
|
||||
$! 07-MAR-1995 Jeff O. Hill Added FTP script
|
||||
$!
|
||||
$!========================================================================
|
||||
$!
|
||||
$! Example FTP script moves sources from UNIX to VMS
|
||||
$! (remove "$!" comment delimeters)
|
||||
$!
|
||||
$! user XXXXXXX
|
||||
$! cd [.ca]
|
||||
$! prompt
|
||||
$! lcd ~/epics/base/src/ca
|
||||
$! mput *.c
|
||||
$! mput *.h
|
||||
$! put BUILD_VMS.COM
|
||||
$! lcd ../libCom
|
||||
$! mput *.c
|
||||
$! mput *.h
|
||||
$! lcd ../../include
|
||||
$! mput *.h
|
||||
$!========================================================================
|
||||
$!
|
||||
$ define /nolog sys multinet_root:[multinet.include.sys]
|
||||
$ define /nolog vms multinet_root:[multinet.include.vms]
|
||||
$ define /nolog net multinet_root:[multinet.include.net]
|
||||
@@ -55,6 +73,7 @@ BUCKETLIB, -
|
||||
ENVSUBR, -
|
||||
TSSUBR, -
|
||||
NEXTFIELDSUBR, -
|
||||
ASSERTUNIX, -
|
||||
CATIME, -
|
||||
ACCTST
|
||||
$ endif
|
||||
@@ -78,6 +97,7 @@ BUCKETLIB, -
|
||||
TSSUBR, -
|
||||
ENVSUBR, -
|
||||
NEXTFIELDSUBR, -
|
||||
ASSERTUNIX, -
|
||||
ELLLIB
|
||||
$! Link the test programs
|
||||
$ call link acctst
|
||||
|
||||
@@ -2,7 +2,6 @@ EPICS = ../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_CFLAGS = -DACCESS_SECURITY -D_NO_PROTO
|
||||
USR_LDLIBS = -lca -lCom -lm
|
||||
USR_LDFLAGS = -L.
|
||||
|
||||
@@ -32,12 +31,14 @@ PROD = caRepeater
|
||||
|
||||
include $(EPICS)/config/RULES.Unix
|
||||
|
||||
acctst: acctst.o $(DEPLIBS_BASE)/libCom.a libca.a
|
||||
acctst: acctst.o $(LIBOBJS) $(DEPLIBS_BASE)/libCom.a
|
||||
$(LINK.c) -o $@ $< $(LIBOBJS) $(DEPLIBS_BASE)/libCom.a
|
||||
|
||||
acctst.o: ../acctst.c
|
||||
$(COMPILE.c) $<
|
||||
|
||||
catime: catime.o $(DEPLIBS_BASE)/libCom.a libca.a
|
||||
catime: catime.o $(LIBOBJS) $(DEPLIBS_BASE)/libCom.a
|
||||
$(LINK.c) -o $@ $< $(LIBOBJS) $(DEPLIBS_BASE)/libCom.a
|
||||
|
||||
catime.o: ../catime.c
|
||||
$(COMPILE.c) $<
|
||||
|
||||
@@ -2,12 +2,11 @@ EPICS = ../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_CFLAGS = -DACCESS_SECURITY -D_NO_PROTO
|
||||
|
||||
SRCS.c = \
|
||||
../iocinf.c ../access.c ../test_event.c ../service.c \
|
||||
../flow_control.c ../repeater.c ../conn.c ../syncgrp.c \
|
||||
../if_depen.c ../bsd_depen.c ../vxWorks_depen.c ../acctst.c
|
||||
../if_depen.c ../bsd_depen.c ../vxWorks_depen.c ../acctst.c \
|
||||
../catime.c
|
||||
|
||||
OBJS = \
|
||||
iocinf.o access.o test_event.o service.o flow_control.o \
|
||||
@@ -20,3 +19,10 @@ include $(EPICS)/config/RULES.Vx
|
||||
caLib: $(OBJS)
|
||||
$(RM) $@
|
||||
$(LINK.c) $@ $(OBJS) $(LDLIBS)
|
||||
|
||||
acctst.o: ../acctst.c
|
||||
$(COMPILE.c) $<
|
||||
|
||||
catime.o: ../catime.c
|
||||
$(COMPILE.c) $<
|
||||
|
||||
|
||||
234
src/ca/access.c
234
src/ca/access.c
@@ -249,12 +249,14 @@ void *pext
|
||||
unsigned bytesAvailable;
|
||||
unsigned actualextsize;
|
||||
unsigned extsize;
|
||||
unsigned msgsize;
|
||||
unsigned bytesSent;
|
||||
|
||||
msg = *pmsg;
|
||||
actualextsize = pmsg->m_postsize;
|
||||
extsize = CA_MESSAGE_ALIGN(pmsg->m_postsize);
|
||||
msg.m_postsize = htons((ca_uint16_t)extsize);
|
||||
msgsize = extsize+sizeof(msg);
|
||||
|
||||
|
||||
LOCK;
|
||||
@@ -271,13 +273,13 @@ void *pext
|
||||
* o Does not allow for messages larger than the
|
||||
* ring buffer size.
|
||||
*/
|
||||
if(extsize+sizeof(msg)>piiu->send.max_msg){
|
||||
if(msgsize>piiu->send.max_msg){
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
|
||||
bytesAvailable = cacRingBufferWriteSize(&piiu->send, FALSE);
|
||||
|
||||
if (bytesAvailable<extsize+sizeof(msg)) {
|
||||
if (bytesAvailable<msgsize) {
|
||||
/*
|
||||
* try to send first so that we avoid the
|
||||
* overhead of select() in high throughput
|
||||
@@ -287,7 +289,7 @@ void *pext
|
||||
bytesAvailable =
|
||||
cacRingBufferWriteSize(&piiu->send, FALSE);
|
||||
|
||||
while(bytesAvailable<extsize+sizeof(msg)){
|
||||
while(TRUE){
|
||||
struct timeval itimeout;
|
||||
|
||||
/*
|
||||
@@ -302,16 +304,28 @@ void *pext
|
||||
UNLOCK;
|
||||
|
||||
LD_CA_TIME (SELECT_POLL, &itimeout);
|
||||
cac_mux_io(&itimeout);
|
||||
cac_mux_io (&itimeout);
|
||||
|
||||
LOCK;
|
||||
|
||||
bytesAvailable = cacRingBufferWriteSize(
|
||||
&piiu->send,
|
||||
FALSE);
|
||||
if(bytesAvailable>=extsize+sizeof(msg)){
|
||||
/*
|
||||
* record the time if we end up blocking so that
|
||||
* we can time out
|
||||
*/
|
||||
if (bytesAvailable>=extsize+sizeof(msg)) {
|
||||
piiu->sendPending = FALSE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (!piiu->sendPending) {
|
||||
piiu->timeAtSendBlock =
|
||||
ca_static->currentTime;
|
||||
piiu->sendPending = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,79 +417,6 @@ struct extmsg **ppMsg
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* cac_alloc_msg()
|
||||
*
|
||||
* return a pointer to reserved message buffer space or
|
||||
* nill if the message will not fit
|
||||
*
|
||||
* LOCK should be on
|
||||
*
|
||||
*/
|
||||
#if 0
|
||||
LOCAL int cac_alloc_msg(
|
||||
struct ioc_in_use *piiu,
|
||||
unsigned extsize,
|
||||
struct extmsg **ppMsg
|
||||
)
|
||||
{
|
||||
unsigned msgsize;
|
||||
unsigned long bytesAvailable;
|
||||
struct extmsg *pmsg;
|
||||
|
||||
msgsize = sizeof(struct extmsg)+extsize;
|
||||
|
||||
/*
|
||||
* fail if max message size exceeded
|
||||
*/
|
||||
if(msgsize>=piiu->send.max_msg){
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
|
||||
bytesAvailable = cacRingBufferWriteSize(&piiu->send, TRUE);
|
||||
if (bytesAvailable<msgsize) {
|
||||
/*
|
||||
* try to send first so that we avoid the
|
||||
* overhead of select() in high throughput
|
||||
* situations
|
||||
*/
|
||||
(*piiu->sendBytes)(piiu);
|
||||
bytesAvailable = cacRingBufferWriteSize(
|
||||
&piiu->send,
|
||||
TRUE);
|
||||
|
||||
while (bytesAvailable<msgsize) {
|
||||
struct timeval itimeout;
|
||||
|
||||
/*
|
||||
* if connection drops request
|
||||
* cant be completed
|
||||
*/
|
||||
if(!piiu->conn_up){
|
||||
return ECA_BADCHID;
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
LD_CA_TIME (SELECT_POLL, &itimeout);
|
||||
cac_mux_io(&itimeout);
|
||||
LOCK;
|
||||
|
||||
bytesAvailable = cacRingBufferWriteSize(
|
||||
&piiu->send,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
pmsg = (struct extmsg *) &piiu->send.buf[piiu->send.wtix];
|
||||
pmsg->m_postsize = extsize;
|
||||
*ppMsg = pmsg;
|
||||
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* cac_add_msg ()
|
||||
@@ -549,6 +490,8 @@ int ca_os_independent_init (void)
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
|
||||
cac_gettimeval (&ca_static->currentTime);
|
||||
|
||||
/* init sync group facility */
|
||||
ca_sg_init();
|
||||
|
||||
@@ -556,6 +499,7 @@ int ca_os_independent_init (void)
|
||||
* init broadcasted search counters
|
||||
*/
|
||||
ca_static->ca_search_retry = 0;
|
||||
ca_static->ca_search_responses = 0;
|
||||
ca_static->ca_conn_next_retry = CA_CURRENT_TIME;
|
||||
sec = (unsigned) CA_RECAST_DELAY;
|
||||
ca_static->ca_conn_retry_delay.tv_sec = sec;
|
||||
@@ -811,8 +755,6 @@ void ca_process_exit()
|
||||
{
|
||||
chid chix;
|
||||
chid chixNext;
|
||||
evid monix;
|
||||
evid monixNext;
|
||||
IIU *piiu;
|
||||
int status;
|
||||
|
||||
@@ -873,20 +815,10 @@ void ca_process_exit()
|
||||
}
|
||||
|
||||
/* remove any pending read blocks */
|
||||
monix = (evid) ellFirst(&ca_static->ca_pend_read_list);
|
||||
while (monix) {
|
||||
monixNext = (evid) ellNext (&monix->node);
|
||||
caIOBlockFree (monix);
|
||||
monix = monixNext;
|
||||
}
|
||||
caIOBlockListFree (&ca_static->ca_pend_read_list, NULL, FALSE, ECA_INTERNAL);
|
||||
|
||||
/* remove any pending write blocks */
|
||||
monix = (evid) ellFirst(&ca_static->ca_pend_write_list);
|
||||
while (monix) {
|
||||
monixNext = (evid) ellNext (&monix->node);
|
||||
caIOBlockFree (monix);
|
||||
monix = monixNext;
|
||||
}
|
||||
caIOBlockListFree (&ca_static->ca_pend_write_list, NULL, FALSE, ECA_INTERNAL);
|
||||
|
||||
/* remove any pending io event blocks */
|
||||
ellFree(&ca_static->ca_ioeventlist);
|
||||
@@ -1407,6 +1339,46 @@ void caIOBlockFree(evid pIOBlock)
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free all io blocks on the list attached to the specified channel
|
||||
*/
|
||||
void caIOBlockListFree(
|
||||
ELLLIST *pList,
|
||||
chid chan,
|
||||
int cbRequired,
|
||||
int status)
|
||||
{
|
||||
evid monix;
|
||||
evid next;
|
||||
struct event_handler_args args;
|
||||
|
||||
for (monix = (evid) ellFirst (pList);
|
||||
monix;
|
||||
monix = next) {
|
||||
|
||||
next = (evid) ellNext (&monix->node);
|
||||
|
||||
if (chan == NULL || monix->chan == chan) {
|
||||
|
||||
ellDelete (pList, &monix->node);
|
||||
|
||||
args.usr = monix->usr_arg;
|
||||
args.chid = monix->chan;
|
||||
args.type = monix->type;
|
||||
args.count = monix->count;
|
||||
args.status = status;
|
||||
args.dbr = NULL;
|
||||
|
||||
caIOBlockFree (monix);
|
||||
|
||||
if (cbRequired && monix->usr_func) {
|
||||
(*monix->usr_func) (args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -1805,11 +1777,11 @@ void *pvalue
|
||||
break;
|
||||
|
||||
case DBR_FLOAT:
|
||||
htonf(pvalue, pdest);
|
||||
dbr_htonf(pvalue, pdest);
|
||||
break;
|
||||
|
||||
case DBR_DOUBLE:
|
||||
htond(pvalue, pdest);
|
||||
dbr_htond(pvalue, pdest);
|
||||
break;
|
||||
|
||||
case DBR_STRING:
|
||||
@@ -2227,10 +2199,11 @@ int ca_request_event(evid monix)
|
||||
p_delta = (ca_float32_t) monix->p_delta;
|
||||
n_delta = (ca_float32_t) monix->n_delta;
|
||||
tmo = (ca_float32_t) monix->timeout;
|
||||
htonf(&p_delta, &msg.m_info.m_hval);
|
||||
htonf(&n_delta, &msg.m_info.m_lval);
|
||||
htonf(&tmo, &msg.m_info.m_toval);
|
||||
dbr_htonf(&p_delta, &msg.m_info.m_hval);
|
||||
dbr_htonf(&n_delta, &msg.m_info.m_lval);
|
||||
dbr_htonf(&tmo, &msg.m_info.m_toval);
|
||||
msg.m_info.m_mask = htons(monix->mask);
|
||||
msg.m_info.m_pad = 0; /* allow future use */
|
||||
|
||||
status = cac_push_msg(piiu, &msg.m_header, &msg.m_info);
|
||||
|
||||
@@ -2333,7 +2306,7 @@ void *pfl
|
||||
* Call user's callback
|
||||
*/
|
||||
LOCKEVENTS;
|
||||
{
|
||||
if (monix->usr_func) {
|
||||
struct event_handler_args args;
|
||||
|
||||
args.usr = monix->usr_arg;
|
||||
@@ -2614,8 +2587,6 @@ void clearChannelResources(unsigned id)
|
||||
{
|
||||
struct ioc_in_use *piiu;
|
||||
chid chix;
|
||||
evid monix;
|
||||
evid next;
|
||||
int status;
|
||||
|
||||
LOCK;
|
||||
@@ -2626,27 +2597,20 @@ void clearChannelResources(unsigned id)
|
||||
piiu = chix->piiu;
|
||||
|
||||
/*
|
||||
* remove any orphaned get callbacks for this
|
||||
* channel
|
||||
* remove any orphaned get callbacks for this channel
|
||||
*/
|
||||
for (monix = (evid) ellFirst (&ca_static->ca_pend_read_list);
|
||||
monix;
|
||||
monix = next) {
|
||||
next = (evid) ellNext (&monix->node);
|
||||
if (monix->chan == chix) {
|
||||
ellDelete (
|
||||
&ca_static->ca_pend_read_list,
|
||||
&monix->node);
|
||||
caIOBlockFree (monix);
|
||||
}
|
||||
}
|
||||
for (monix = (evid) ellFirst (&chix->eventq);
|
||||
monix;
|
||||
monix = next){
|
||||
assert (monix->chan == chix);
|
||||
next = (evid) ellNext (&monix->node);
|
||||
caIOBlockFree(monix);
|
||||
}
|
||||
caIOBlockListFree (&ca_static->ca_pend_read_list, chix, FALSE, ECA_INTERNAL);
|
||||
|
||||
/*
|
||||
* remove any orphaned put callbacks for this channel
|
||||
*/
|
||||
caIOBlockListFree (&ca_static->ca_pend_write_list, chix, FALSE, ECA_INTERNAL);
|
||||
|
||||
/*
|
||||
* remove any monitors still attached to this channel
|
||||
*/
|
||||
caIOBlockListFree (&chix->eventq, NULL, FALSE, ECA_INTERNAL);
|
||||
|
||||
ellDelete (&piiu->chidlist, &chix->node);
|
||||
status = bucketRemoveItemUnsignedId (
|
||||
ca_static->ca_pSlowBucket, &chix->cid);
|
||||
@@ -2659,6 +2623,7 @@ void clearChannelResources(unsigned id)
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* This routine pends waiting for channel events and calls the */
|
||||
@@ -2671,7 +2636,6 @@ void clearChannelResources(unsigned id)
|
||||
int APIENTRY ca_pend(ca_real timeout, int early)
|
||||
{
|
||||
struct timeval beg_time;
|
||||
struct timeval cur_time;
|
||||
ca_real delay;
|
||||
|
||||
INITCHK;
|
||||
@@ -2686,6 +2650,8 @@ int APIENTRY ca_pend(ca_real timeout, int early)
|
||||
|
||||
/*
|
||||
* Flush the send buffers
|
||||
* (guarantees that we wait for all send buffer to be
|
||||
* flushed even if this requires blocking)
|
||||
*
|
||||
* Also takes care of outstanding recvs
|
||||
* for single threaded clients
|
||||
@@ -2696,22 +2662,24 @@ int APIENTRY ca_pend(ca_real timeout, int early)
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
cac_gettimeval(&beg_time);
|
||||
|
||||
/*
|
||||
* the current time set iderectly within ca_flush_io()
|
||||
* above.
|
||||
*/
|
||||
beg_time = ca_static->currentTime;
|
||||
delay = 0.0;
|
||||
while(TRUE){
|
||||
ca_real remaining;
|
||||
struct timeval tmo;
|
||||
|
||||
if(pndrecvcnt<1 && early)
|
||||
if (pndrecvcnt<1 && early) {
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
if(timeout == 0.0){
|
||||
remaining = SELECT_POLL;
|
||||
}
|
||||
else{
|
||||
|
||||
cac_gettimeval (&cur_time);
|
||||
delay = cac_time_diff (&cur_time, &beg_time);
|
||||
remaining = timeout-delay;
|
||||
if(remaining<=0.0){
|
||||
if(early){
|
||||
@@ -2729,6 +2697,14 @@ int APIENTRY ca_pend(ca_real timeout, int early)
|
||||
tmo.tv_sec = (long) remaining;
|
||||
tmo.tv_usec = (long) ((remaining-tmo.tv_sec)*USEC_PER_SEC);
|
||||
cac_block_for_io_completion(&tmo);
|
||||
|
||||
/*
|
||||
* the current time set within cac_block_for_io_completion()
|
||||
* above.
|
||||
*/
|
||||
if (timeout != 0.0) {
|
||||
delay = cac_time_diff (&ca_static->currentTime, &beg_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2740,13 +2716,13 @@ ca_real cac_time_diff (ca_time *pTVA, ca_time *pTVB)
|
||||
{
|
||||
ca_real delay;
|
||||
|
||||
delay = pTVA->tv_sec - pTVB->tv_sec;
|
||||
if(pTVA->tv_usec>pTVB->tv_usec){
|
||||
delay = pTVA->tv_sec - pTVB->tv_sec;
|
||||
delay += (pTVA->tv_usec - pTVB->tv_usec) /
|
||||
(ca_real)(USEC_PER_SEC);
|
||||
}
|
||||
else{
|
||||
delay -= 1.0;
|
||||
delay = pTVA->tv_sec - pTVB->tv_sec - 1L;
|
||||
delay += (USEC_PER_SEC - pTVB->tv_usec + pTVA->tv_usec) /
|
||||
(ca_real)(USEC_PER_SEC);
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ static char *sccsId = "@(#) $Id$";
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "os_depen.h"
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include <cadef.h>
|
||||
|
||||
#define EVENT_ROUTINE null_event
|
||||
@@ -562,8 +562,8 @@ void conn_cb(struct event_handler_args args)
|
||||
void test_sync_groups(chid chix)
|
||||
{
|
||||
int status;
|
||||
CA_SYNC_GID gid1;
|
||||
CA_SYNC_GID gid2;
|
||||
CA_SYNC_GID gid1=0;
|
||||
CA_SYNC_GID gid2=0;
|
||||
|
||||
printf("Performing sync group test...");
|
||||
fflush(stdout);
|
||||
|
||||
@@ -42,6 +42,11 @@
|
||||
*/
|
||||
int cac_select_io(struct timeval *ptimeout, int flags)
|
||||
{
|
||||
/*
|
||||
* Use auto timeout so there is no chance of
|
||||
* recursive reuse of ptimeout
|
||||
*/
|
||||
struct timeval autoTimeOut = *ptimeout;
|
||||
long status;
|
||||
IIU *piiu;
|
||||
unsigned long freespace;
|
||||
@@ -86,39 +91,32 @@ int cac_select_io(struct timeval *ptimeout, int flags)
|
||||
}
|
||||
|
||||
if (flags&CA_DO_SENDS) {
|
||||
if (cacRingBufferReadSize(&piiu->send, FALSE)>0) {
|
||||
if (cacRingBufferReadSize(&piiu->send, FALSE)>0) {
|
||||
maxfd = max (maxfd,piiu->sock_chan);
|
||||
FD_SET (piiu->sock_chan, &pfdi->writeMask);
|
||||
}
|
||||
FD_SET (piiu->sock_chan, &pfdi->writeMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
#if 0
|
||||
printf( "max fd=%d tv_usec=%d tv_sec=%d\n",
|
||||
maxfd,
|
||||
ptimeout->tv_usec,
|
||||
ptimeout->tv_sec);
|
||||
#endif
|
||||
# if defined(__hpux)
|
||||
status = select(
|
||||
maxfd+1,
|
||||
(int *)&pfdi->readMask,
|
||||
(int *)&pfdi->writeMask,
|
||||
(int *)NULL,
|
||||
&autoTimeOut);
|
||||
# else
|
||||
status = select(
|
||||
maxfd+1,
|
||||
&pfdi->readMask,
|
||||
&pfdi->writeMask,
|
||||
NULL,
|
||||
&autoTimeOut);
|
||||
# endif
|
||||
|
||||
#if defined(vxWorks) && 0
|
||||
if(client_lock->recurse>0){
|
||||
ca_printf("lock is on and we are going to sleep %d!",
|
||||
client_lock->recurse);
|
||||
taskSuspend(0);
|
||||
}
|
||||
#endif
|
||||
cac_gettimeval (&ca_static->currentTime);
|
||||
|
||||
status = select(
|
||||
maxfd+1,
|
||||
&pfdi->readMask,
|
||||
&pfdi->writeMask,
|
||||
NULL,
|
||||
ptimeout);
|
||||
|
||||
#if 0
|
||||
printf("leaving select stat=%d errno=%d \n", status, MYERRNO);
|
||||
#endif
|
||||
if (status<0) {
|
||||
if (MYERRNO == EINTR) {
|
||||
}
|
||||
@@ -144,13 +142,13 @@ printf("leaving select stat=%d errno=%d \n", status, MYERRNO);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(piiu->sock_chan,&pfdi->writeMask)) {
|
||||
(*piiu->sendBytes)(piiu);
|
||||
}
|
||||
|
||||
if (FD_ISSET(piiu->sock_chan,&pfdi->readMask)) {
|
||||
(*piiu->recvBytes)(piiu);
|
||||
}
|
||||
|
||||
if (FD_ISSET(piiu->sock_chan,&pfdi->writeMask)) {
|
||||
(*piiu->sendBytes)(piiu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <iocinf.h>
|
||||
|
||||
main()
|
||||
{
|
||||
ca_repeater();
|
||||
assert(0);
|
||||
ca_repeater ();
|
||||
assert (0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
235
src/ca/catime.c
235
src/ca/catime.c
@@ -11,10 +11,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <cadef.h>
|
||||
#include <epicsAssert.h>
|
||||
#include <cadef.h>
|
||||
|
||||
#ifndef LOCAL
|
||||
#define LOCAL static
|
||||
@@ -36,7 +36,7 @@
|
||||
#define NELEMENTS(A) (sizeof (A) / sizeof ((A) [0]))
|
||||
#endif
|
||||
|
||||
#define ITERATION_COUNT 10000
|
||||
#define ITERATION_COUNT 1000
|
||||
|
||||
#define WAIT_FOR_ACK
|
||||
|
||||
@@ -50,9 +50,9 @@ typedef struct testItem {
|
||||
|
||||
ti itemList[ITERATION_COUNT];
|
||||
|
||||
int catime(char *channelName);
|
||||
int catime (char *channelName);
|
||||
|
||||
typedef void tf (ti *pItems, unsigned iterations);
|
||||
typedef void tf (ti *pItems, unsigned iterations, unsigned *pInlineIter);
|
||||
|
||||
LOCAL void test (
|
||||
ti *pItems,
|
||||
@@ -95,8 +95,7 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
int catime (char *channelName)
|
||||
{
|
||||
long status;
|
||||
long i,j;
|
||||
long i;
|
||||
unsigned strsize;
|
||||
|
||||
SEVCHK (ca_task_initialize(),"Unable to initialize");
|
||||
@@ -144,6 +143,8 @@ int catime (char *channelName)
|
||||
printf ("free test\n");
|
||||
timeIt (test_free, itemList, NELEMENTS(itemList));
|
||||
|
||||
SEVCHK (ca_task_exit (), "Unable to free resources at exit");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -158,11 +159,11 @@ LOCAL void test (
|
||||
)
|
||||
{
|
||||
printf ("\tasync put test\n");
|
||||
timeIt(test_put, pItems, iterations);
|
||||
timeIt (test_put, pItems, iterations);
|
||||
printf ("\tasync get test\n");
|
||||
timeIt(test_get, pItems, iterations);
|
||||
timeIt (test_get, pItems, iterations);
|
||||
printf ("\tsynch get test\n");
|
||||
timeIt(test_wait, pItems, iterations);
|
||||
timeIt (test_wait, pItems, iterations);
|
||||
}
|
||||
|
||||
|
||||
@@ -179,14 +180,15 @@ void timeIt(
|
||||
TS_STAMP start_time;
|
||||
double delay;
|
||||
int status;
|
||||
unsigned inlineIter;
|
||||
|
||||
status = tsLocalTime(&start_time);
|
||||
assert (status == S_ts_OK);
|
||||
(*pfunc) (pItems, iterations);
|
||||
(*pfunc) (pItems, iterations, &inlineIter);
|
||||
status = tsLocalTime(&end_time);
|
||||
assert (status == S_ts_OK);
|
||||
TsDiffAsDouble(&delay,&end_time,&start_time);
|
||||
printf ("Elapsed Per Item = %f\n", delay/iterations);
|
||||
printf ("Elapsed Per Item = %f\n", delay/(iterations*inlineIter));
|
||||
}
|
||||
|
||||
|
||||
@@ -195,24 +197,23 @@ void timeIt(
|
||||
*/
|
||||
LOCAL void test_search(
|
||||
ti *pItems,
|
||||
unsigned iterations
|
||||
unsigned iterations,
|
||||
unsigned *pInlineIter
|
||||
)
|
||||
{
|
||||
int i;
|
||||
ti *pi;
|
||||
int status;
|
||||
chid chan;
|
||||
|
||||
status = ca_search (
|
||||
pItems[0].name,
|
||||
&chan);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_pend_io(0.0);
|
||||
|
||||
for (i=0; i< iterations;i++) {
|
||||
pItems[i].chix = chan;
|
||||
for (pi=pItems; pi<&pItems[iterations]; pi++) {
|
||||
status = ca_search (
|
||||
pi->name,
|
||||
&pi->chix);
|
||||
SEVCHK (status, NULL);
|
||||
}
|
||||
|
||||
status = ca_pend_io(0.0);
|
||||
SEVCHK (status, NULL);
|
||||
|
||||
*pInlineIter = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -221,29 +222,18 @@ unsigned iterations
|
||||
*/
|
||||
LOCAL void test_free(
|
||||
ti *pItems,
|
||||
unsigned iterations
|
||||
unsigned iterations,
|
||||
unsigned *pInlineIter
|
||||
)
|
||||
{
|
||||
int i;
|
||||
ti *pi;
|
||||
int status;
|
||||
dbr_int_t val;
|
||||
|
||||
status = ca_clear_channel (pItems[0].chix);
|
||||
SEVCHK (status, NULL);
|
||||
|
||||
#if 0
|
||||
#ifdef WAIT_FOR_ACK
|
||||
status = ca_array_get (DBR_INT, 1, pItems[0].chix, &val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_pend_io(100.0);
|
||||
SEVCHK (status, NULL);
|
||||
#endif
|
||||
|
||||
status = ca_clear_channel (pItems[0].chix);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_flush_io();
|
||||
SEVCHK (status, NULL);
|
||||
#endif
|
||||
for (pi=pItems; pi<&pItems[iterations]; pi++) {
|
||||
status = ca_clear_channel (pi->chix);
|
||||
SEVCHK (status, NULL);
|
||||
}
|
||||
*pInlineIter = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,19 +242,74 @@ unsigned iterations
|
||||
*/
|
||||
LOCAL void test_put(
|
||||
ti *pItems,
|
||||
unsigned iterations
|
||||
unsigned iterations,
|
||||
unsigned *pInlineIter
|
||||
)
|
||||
{
|
||||
int i;
|
||||
ti *pi;
|
||||
int status;
|
||||
dbr_int_t val;
|
||||
|
||||
for (i=1; i<iterations; i++) {
|
||||
for (pi=pItems; pi<&pItems[iterations]; pi++) {
|
||||
status = ca_array_put(
|
||||
pItems[i].type,
|
||||
pItems[i].count,
|
||||
pItems[i].chix,
|
||||
&pItems[i].val);
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_put(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
}
|
||||
#ifdef WAIT_FOR_ACK
|
||||
@@ -280,6 +325,8 @@ unsigned iterations
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_flush_io();
|
||||
SEVCHK (status, NULL);
|
||||
|
||||
*pInlineIter = 10;
|
||||
}
|
||||
|
||||
|
||||
@@ -288,22 +335,79 @@ unsigned iterations
|
||||
*/
|
||||
LOCAL void test_get(
|
||||
ti *pItems,
|
||||
unsigned iterations
|
||||
unsigned iterations,
|
||||
unsigned *pInlineIter
|
||||
)
|
||||
{
|
||||
int i;
|
||||
ti *pi;
|
||||
int status;
|
||||
|
||||
for (i=0; i<iterations; i++) {
|
||||
for (pi=pItems; pi<&pItems[iterations]; pi++) {
|
||||
status = ca_array_get(
|
||||
pItems[i].type,
|
||||
pItems[i].count,
|
||||
pItems[i].chix,
|
||||
&pItems[i].val);
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_array_get(
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
}
|
||||
status = ca_pend_io(100.0);
|
||||
SEVCHK (status, NULL);
|
||||
|
||||
*pInlineIter = 10;
|
||||
}
|
||||
|
||||
|
||||
@@ -313,21 +417,24 @@ unsigned iterations
|
||||
*/
|
||||
LOCAL void test_wait (
|
||||
ti *pItems,
|
||||
unsigned iterations
|
||||
unsigned iterations,
|
||||
unsigned *pInlineIter
|
||||
)
|
||||
{
|
||||
int i;
|
||||
ti *pi;
|
||||
int status;
|
||||
|
||||
for (i=1; i<iterations; i++) {
|
||||
for (pi=pItems; pi<&pItems[iterations]; pi++) {
|
||||
status = ca_array_get(
|
||||
pItems[i].type,
|
||||
pItems[i].count,
|
||||
pItems[i].chix,
|
||||
&pItems[i].val);
|
||||
pi->type,
|
||||
pi->count,
|
||||
pi->chix,
|
||||
&pi->val);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_pend_io(100.0);
|
||||
SEVCHK (status, NULL);
|
||||
}
|
||||
|
||||
*pInlineIter = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,11 +47,11 @@ static char *sccsId = "@(#) $Id$";
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOGRETRYINTERVAL logRetryInterval(__FILE__, __LINE__);
|
||||
LOCAL void logRetryInterval(char *pFN, unsigned lineno);
|
||||
#else
|
||||
#define LOGRETRYINTERVAL
|
||||
#endif
|
||||
|
||||
LOCAL void logRetryInterval(char *pFN, unsigned lineno);
|
||||
LOCAL void retrySearchRequest(int silent);
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ LOCAL void retrySearchRequest(int silent);
|
||||
void manage_conn(int silent)
|
||||
{
|
||||
IIU *piiu;
|
||||
ca_time current;
|
||||
ca_real delay;
|
||||
long idelay;
|
||||
|
||||
@@ -79,8 +78,6 @@ void manage_conn(int silent)
|
||||
|
||||
ca_static->ca_manage_conn_active = TRUE;
|
||||
|
||||
cac_gettimeval(¤t);
|
||||
|
||||
/*
|
||||
* issue connection heartbeat
|
||||
* (if we dont see a beacon)
|
||||
@@ -100,7 +97,7 @@ void manage_conn(int silent)
|
||||
*/
|
||||
if (piiu->sendPending) {
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&ca_static->currentTime,
|
||||
&piiu->timeAtSendBlock);
|
||||
if (delay>ca_static->ca_connectTMO) {
|
||||
TAG_CONN_DOWN(piiu);
|
||||
@@ -117,15 +114,15 @@ void manage_conn(int silent)
|
||||
int rtmo;
|
||||
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&ca_static->currentTime,
|
||||
&piiu->timeAtEchoRequest);
|
||||
stmo = delay > CA_RETRY_PERIOD;
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&ca_static->currentTime,
|
||||
&piiu->timeAtLastRecv);
|
||||
rtmo = delay > CA_RETRY_PERIOD;
|
||||
if(stmo && rtmo && !piiu->sendPending){
|
||||
piiu->timeAtEchoRequest = current;
|
||||
piiu->timeAtEchoRequest = ca_static->currentTime;
|
||||
noop_msg(piiu);
|
||||
}
|
||||
continue;
|
||||
@@ -133,7 +130,7 @@ void manage_conn(int silent)
|
||||
|
||||
if(piiu->echoPending){
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&ca_static->currentTime,
|
||||
&piiu->timeAtEchoRequest);
|
||||
if (delay > CA_ECHO_TIMEOUT) {
|
||||
/*
|
||||
@@ -144,10 +141,10 @@ void manage_conn(int silent)
|
||||
}
|
||||
else{
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&ca_static->currentTime,
|
||||
&piiu->timeAtLastRecv);
|
||||
if (delay>ca_static->ca_connectTMO) {
|
||||
echo_request(piiu, ¤t);
|
||||
echo_request(piiu, &ca_static->currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,10 +156,10 @@ void manage_conn(int silent)
|
||||
*/
|
||||
if (!ca_static->ca_repeater_contacted) {
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&ca_static->currentTime,
|
||||
&ca_static->ca_last_repeater_try);
|
||||
if (delay > REPEATER_TRY_PERIOD) {
|
||||
ca_static->ca_last_repeater_try = current;
|
||||
ca_static->ca_last_repeater_try = ca_static->currentTime;
|
||||
notify_ca_repeater();
|
||||
}
|
||||
}
|
||||
@@ -181,13 +178,13 @@ void manage_conn(int silent)
|
||||
|
||||
if(ca_static->ca_conn_next_retry.tv_sec == CA_CURRENT_TIME.tv_sec &&
|
||||
ca_static->ca_conn_next_retry.tv_usec == CA_CURRENT_TIME.tv_usec){
|
||||
ca_static->ca_conn_next_retry = current;
|
||||
ca_static->ca_conn_next_retry = ca_static->currentTime;
|
||||
LOGRETRYINTERVAL
|
||||
}
|
||||
|
||||
delay = cac_time_diff (
|
||||
&ca_static->ca_conn_next_retry,
|
||||
¤t);
|
||||
&ca_static->currentTime);
|
||||
|
||||
if (delay > 0.0) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
@@ -220,7 +217,7 @@ void manage_conn(int silent)
|
||||
(long) ((delay-idelay)*USEC_PER_SEC);
|
||||
ca_static->ca_conn_next_retry =
|
||||
cac_time_sum (
|
||||
¤t,
|
||||
&ca_static->currentTime,
|
||||
&ca_static->ca_conn_retry_delay);
|
||||
LOGRETRYINTERVAL
|
||||
|
||||
@@ -278,8 +275,10 @@ LOCAL void retrySearchRequest (int silent)
|
||||
if (chix==NULL) {
|
||||
/*
|
||||
* increment the retry sequence number
|
||||
* (only if we get no responses during a sequence)
|
||||
*/
|
||||
if (ca_static->ca_search_retry<MAXCONNTRIES) {
|
||||
if (ca_static->ca_search_retry<MAXCONNTRIES
|
||||
&& ca_static->ca_search_responses==0) {
|
||||
ca_static->ca_search_retry++;
|
||||
}
|
||||
|
||||
@@ -288,6 +287,7 @@ LOCAL void retrySearchRequest (int silent)
|
||||
*/
|
||||
if (ca_static->ca_search_retry<min_retry_num) {
|
||||
ca_static->ca_search_retry = min_retry_num;
|
||||
ca_static->ca_search_responses = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,7 +353,6 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
{
|
||||
chid chan;
|
||||
ca_real currentPeriod;
|
||||
ca_time currentTime;
|
||||
bhe *pBHE;
|
||||
unsigned port;
|
||||
int netChange = FALSE;
|
||||
@@ -368,8 +367,6 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
return;
|
||||
}
|
||||
|
||||
cac_gettimeval(¤tTime);
|
||||
|
||||
LOCK;
|
||||
/*
|
||||
* look for it in the hash table
|
||||
@@ -386,14 +383,14 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
* update time stamp and average period
|
||||
*/
|
||||
currentPeriod = cac_time_diff (
|
||||
¤tTime,
|
||||
&ca_static->currentTime,
|
||||
&pBHE->timeStamp);
|
||||
/*
|
||||
* update the average
|
||||
*/
|
||||
pBHE->averagePeriod += currentPeriod;
|
||||
pBHE->averagePeriod /= 2.0;
|
||||
pBHE->timeStamp = currentTime;
|
||||
pBHE->timeStamp = ca_static->currentTime;
|
||||
|
||||
if ((currentPeriod/4.0)>=pBHE->averagePeriod) {
|
||||
#ifdef DEBUG
|
||||
@@ -417,7 +414,7 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
netChange = TRUE;
|
||||
}
|
||||
if(pBHE->piiu){
|
||||
pBHE->piiu->timeAtLastRecv = currentTime;
|
||||
pBHE->piiu->timeAtLastRecv = ca_static->currentTime;
|
||||
}
|
||||
if(!netChange){
|
||||
UNLOCK;
|
||||
@@ -470,7 +467,7 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
idelay = (long) delay;
|
||||
ca_delay.tv_sec = idelay;
|
||||
ca_delay.tv_usec = (long) ((delay-idelay) * USEC_PER_SEC);
|
||||
next = cac_time_sum(¤tTime, &ca_delay);
|
||||
next = cac_time_sum(&ca_static->currentTime, &ca_delay);
|
||||
|
||||
diff = cac_time_diff(
|
||||
&ca_static->ca_conn_next_retry,
|
||||
|
||||
271
src/ca/convert.c
271
src/ca/convert.c
@@ -131,20 +131,11 @@ CACVRTFUNC *cac_dbr_cvrt[]
|
||||
cvrt_ctrl_double
|
||||
};
|
||||
|
||||
/*
|
||||
* Native types may not match EPICS types
|
||||
*/
|
||||
typedef short ca_short_tt;
|
||||
typedef float ca_float_tt;
|
||||
typedef short ca_enum_tt;
|
||||
typedef char ca_char_tt;
|
||||
typedef int ca_long_tt;
|
||||
typedef double ca_double_tt;
|
||||
|
||||
#define dbr_ntohs(A) ntohs(A)
|
||||
#define dbr_ntohl(A) ntohl(A)
|
||||
#define dbr_htons(A) htons(A)
|
||||
#define dbr_htonl(A) htonl(A)
|
||||
#define dbr_ntohs(A) (ntohs(A))
|
||||
#define dbr_ntohl(A) (ntohl(A))
|
||||
#define dbr_htons(A) (htons(A))
|
||||
#define dbr_htonl(A) (htonl(A))
|
||||
|
||||
|
||||
|
||||
@@ -162,8 +153,8 @@ int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
ca_char_tt *pSrc = s;
|
||||
ca_char_tt *pDest = d;
|
||||
char *pSrc = s;
|
||||
char *pDest = d;
|
||||
|
||||
if(num == 1){
|
||||
strcpy(pDest, pSrc);
|
||||
@@ -188,8 +179,8 @@ int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
ca_short_tt *pSrc = s;
|
||||
ca_short_tt *pDest = d;
|
||||
dbr_short_t *pSrc = s;
|
||||
dbr_short_t *pDest = d;
|
||||
unsigned long i;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
@@ -218,8 +209,8 @@ unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
ca_char_tt *pSrc = s;
|
||||
ca_char_tt *pDest = d;
|
||||
dbr_char_t *pSrc = s;
|
||||
dbr_char_t *pDest = d;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
*pDest++ = *pSrc++;
|
||||
@@ -242,8 +233,8 @@ unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
ca_long_tt *pSrc = s;
|
||||
ca_long_tt *pDest = d;
|
||||
dbr_long_t *pSrc = s;
|
||||
dbr_long_t *pDest = d;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
*pDest = dbr_ntohl( *pSrc );
|
||||
@@ -271,8 +262,8 @@ unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
ca_enum_tt *pSrc;
|
||||
ca_enum_tt *pDest;
|
||||
dbr_enum_t *pSrc;
|
||||
dbr_enum_t *pDest;
|
||||
|
||||
pSrc = s;
|
||||
pDest = d;
|
||||
@@ -304,15 +295,15 @@ unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
ca_float_tt *pSrc = s;
|
||||
ca_float_tt *pDest = d;
|
||||
dbr_float_t *pSrc = s;
|
||||
dbr_float_t *pDest = d;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
if(encode){
|
||||
htonf(pSrc, pDest);
|
||||
dbr_htonf(pSrc, pDest);
|
||||
}
|
||||
else{
|
||||
ntohf(pSrc, pDest);
|
||||
dbr_ntohf(pSrc, pDest);
|
||||
}
|
||||
/*
|
||||
* dont increment these inside the MACRO
|
||||
@@ -338,15 +329,15 @@ unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
ca_double_tt *pSrc = s;
|
||||
ca_double_tt *pDest = d;
|
||||
dbr_double_t *pSrc = s;
|
||||
dbr_double_t *pDest = d;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
if(encode){
|
||||
htond(pSrc,pDest);
|
||||
dbr_htond(pSrc,pDest);
|
||||
}
|
||||
else{
|
||||
ntohd(pSrc,pDest);
|
||||
dbr_ntohd(pSrc,pDest);
|
||||
}
|
||||
/*
|
||||
* dont increment these inside the MACRO
|
||||
@@ -697,32 +688,32 @@ unsigned long num /* number of values */
|
||||
if (encode) /* vax to ieee convert */
|
||||
{
|
||||
if (num == 1){
|
||||
htond(&pSrc->value, &pDest->value);
|
||||
dbr_htond(&pSrc->value, &pDest->value);
|
||||
}
|
||||
else {
|
||||
cvrt_double(&pSrc->value, &pDest->value, encode,num);
|
||||
}
|
||||
htond(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
htond(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
htond(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
htond(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
htond(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
htond(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
dbr_htond(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
dbr_htond(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
dbr_htond(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
dbr_htond(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
dbr_htond(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
dbr_htond(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
}
|
||||
else /* ieee to vax convert */
|
||||
{
|
||||
if (num == 1){
|
||||
ntohd(&pSrc->value, &pDest->value);
|
||||
dbr_ntohd(&pSrc->value, &pDest->value);
|
||||
}
|
||||
else {
|
||||
cvrt_double(&pSrc->value, &pDest->value, encode,num);
|
||||
}
|
||||
ntohd(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
ntohd(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
ntohd(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
ntohd(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
ntohd(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
ntohd(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
dbr_ntohd(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
dbr_ntohd(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
dbr_ntohd(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
dbr_ntohd(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
dbr_ntohd(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
dbr_ntohd(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,32 +751,32 @@ unsigned long num /* number of values */
|
||||
if (encode) /* vax to ieee convert */
|
||||
{
|
||||
if (num == 1){
|
||||
htonf(&pSrc->value, &pDest->value);
|
||||
dbr_htonf(&pSrc->value, &pDest->value);
|
||||
}
|
||||
else {
|
||||
cvrt_float(&pSrc->value, &pDest->value, encode,num);
|
||||
}
|
||||
htonf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
htonf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
htonf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
htonf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
htonf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
htonf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
dbr_htonf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
dbr_htonf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
dbr_htonf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
dbr_htonf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
dbr_htonf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
dbr_htonf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
}
|
||||
else /* ieee to vax convert */
|
||||
{
|
||||
if (num == 1){
|
||||
ntohf(&pSrc->value, &pDest->value);
|
||||
dbr_ntohf(&pSrc->value, &pDest->value);
|
||||
}
|
||||
else {
|
||||
cvrt_float(&pSrc->value, &pDest->value, encode,num);
|
||||
}
|
||||
ntohf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
ntohf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
ntohf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
ntohf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
ntohf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
ntohf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
dbr_ntohf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
dbr_ntohf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
dbr_ntohf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
dbr_ntohf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
dbr_ntohf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
dbr_ntohf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -934,7 +925,7 @@ unsigned long num /* number of values */
|
||||
struct dbr_ctrl_double *pSrc = s;
|
||||
struct dbr_ctrl_double *pDest = d;
|
||||
|
||||
/* these are the same for ieee to vaax or vax to ieee */
|
||||
/* these are the same for ieee to vax or vax to ieee */
|
||||
pDest->status = dbr_ntohs(pSrc->status);
|
||||
pDest->severity = dbr_ntohs(pSrc->severity);
|
||||
pDest->precision = dbr_ntohs(pSrc->precision);
|
||||
@@ -942,35 +933,36 @@ unsigned long num /* number of values */
|
||||
if (encode) /* vax to ieee convert */
|
||||
{
|
||||
if (num == 1){
|
||||
htond(&pSrc->value, &pDest->value);
|
||||
dbr_htond(&pSrc->value, &pDest->value);
|
||||
}
|
||||
else {
|
||||
cvrt_double(&pSrc->value, &pDest->value, encode, num);
|
||||
}
|
||||
htond(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
htond(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
htond(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
htond(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
htond(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
htond(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
htond(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit);
|
||||
htond(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit);
|
||||
dbr_htond(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
dbr_htond(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
dbr_htond(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
dbr_htond(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
dbr_htond(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
dbr_htond(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
dbr_htond(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit);
|
||||
dbr_htond(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit);
|
||||
}
|
||||
else /* ieee to vax convert */
|
||||
{
|
||||
if (num == 1){
|
||||
ntohd(&pSrc->value, &pDest->value);
|
||||
dbr_ntohd(&pSrc->value, &pDest->value);
|
||||
}
|
||||
else {
|
||||
cvrt_double(&pSrc->value, &pDest->value, encode, num);
|
||||
}
|
||||
ntohd(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
ntohd(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
ntohd(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
ntohd(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
ntohd(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
ntohd(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit);
|
||||
ntohd(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit);
|
||||
dbr_ntohd(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
dbr_ntohd(&pSrc->upper_disp_limit, &pDest->upper_disp_limit);
|
||||
dbr_ntohd(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
dbr_ntohd(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
dbr_ntohd(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
dbr_ntohd(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
dbr_ntohd(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit);
|
||||
dbr_ntohd(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1006,35 +998,36 @@ unsigned long num /* number of values */
|
||||
if (encode) /* vax to ieee convert */
|
||||
{
|
||||
if (num == 1){
|
||||
htonf(&pSrc->value, &pDest->value);
|
||||
dbr_htonf(&pSrc->value, &pDest->value);
|
||||
}
|
||||
else {
|
||||
cvrt_float(&pSrc->value, &pDest->value, encode, num);
|
||||
}
|
||||
htonf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
htonf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
htonf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
htonf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
htonf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
htonf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
htonf(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit);
|
||||
htonf(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit);
|
||||
dbr_htonf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit);
|
||||
dbr_htonf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
dbr_htonf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
dbr_htonf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
dbr_htonf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
dbr_htonf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
dbr_htonf(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit);
|
||||
dbr_htonf(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit);
|
||||
}
|
||||
else /* ieee to vax convert */
|
||||
{
|
||||
if (num == 1){
|
||||
ntohf(&pSrc->value, &pDest->value);
|
||||
dbr_ntohf(&pSrc->value, &pDest->value);
|
||||
}
|
||||
else {
|
||||
cvrt_float(&pSrc->value, &pDest->value, encode, num);
|
||||
}
|
||||
ntohf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
ntohf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
ntohf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
ntohf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
ntohf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
ntohf(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit);
|
||||
ntohf(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit);
|
||||
dbr_ntohf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit);
|
||||
dbr_ntohf(&pSrc->upper_disp_limit, &pDest->upper_disp_limit);
|
||||
dbr_ntohf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit);
|
||||
dbr_ntohf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit);
|
||||
dbr_ntohf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit);
|
||||
dbr_ntohf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit);
|
||||
dbr_ntohf(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit);
|
||||
dbr_ntohf(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1408,17 +1401,25 @@ struct mitdbl {
|
||||
#define DBLEXPMAXMIT 126 /* max MIT exponent */
|
||||
#define DBLEXPMINMIT -128 /* min MIT exponent */
|
||||
|
||||
void htond(double *pHost, double *pNet)
|
||||
/*
|
||||
* Converts VAX D floating point to IEEE double precision
|
||||
* (D floating is the VAX C default)
|
||||
*/
|
||||
void dbr_htond(dbr_double_t *pHost, dbr_double_t *pNet)
|
||||
{
|
||||
double copyin;
|
||||
dbr_double_t copyin;
|
||||
struct mitdbl *pMIT;
|
||||
struct ieeedbl *pIEEE;
|
||||
ca_uint32_t *ptmp;
|
||||
ca_uint32_t tmp;
|
||||
|
||||
/*
|
||||
* Use internal buffer so the src and dest ptr
|
||||
* can be identical
|
||||
*/
|
||||
copyin = *pHost;
|
||||
pMIT = (struct mitdbl *)©in;
|
||||
pIEEE = (struct ieeedbl *)pNet;
|
||||
pMIT = (struct mitdbl *) ©in;
|
||||
pIEEE = (struct ieeedbl *) pNet;
|
||||
|
||||
if( ((int)pMIT->exp) < (DBLEXPMINMIT+MIT_DBL_SB) ){
|
||||
pIEEE->mant1 = 0;
|
||||
@@ -1438,34 +1439,43 @@ void htond(double *pHost, double *pNet)
|
||||
* byte swap to net order
|
||||
*/
|
||||
ptmp = (ca_uint32_t *) pNet;
|
||||
tmp = htonl(ptmp[0]);
|
||||
ptmp[0] = htonl(ptmp[1]);
|
||||
tmp = dbr_htonl(ptmp[0]);
|
||||
ptmp[0] = dbr_htonl(ptmp[1]);
|
||||
ptmp[1] = tmp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Converts IEEE double precision to VAX D floating point
|
||||
* (D floating is the VAX default)
|
||||
*
|
||||
* sign must be forced to zero if the exponent is zero to prevent a reserved
|
||||
* operand fault- joh 9-13-90
|
||||
*/
|
||||
void ntohd(double *pNet, double *pHost)
|
||||
void dbr_ntohd(dbr_double_t *pNet, dbr_double_t *pHost)
|
||||
{
|
||||
double copyin;
|
||||
struct ieeedbl copyin;
|
||||
struct mitdbl *pMIT;
|
||||
struct ieeedbl *pIEEE;
|
||||
ca_uint32_t *ptmp;
|
||||
ca_uint32_t tmp;
|
||||
|
||||
copyin = *pNet;
|
||||
pIEEE = (struct ieeedbl *)pNet;
|
||||
pMIT = (struct mitdbl *)pHost;
|
||||
pIEEE = (struct ieeedbl *)©in;
|
||||
|
||||
/*
|
||||
* Use internal buffer so the src and dest ptr
|
||||
* can be identical
|
||||
*/
|
||||
copyin = *pIEEE;
|
||||
pIEEE = ©in;
|
||||
|
||||
/*
|
||||
* Byte swap from net order to host order
|
||||
*/
|
||||
ptmp = (ca_uint32_t *) pIEEE;
|
||||
tmp = htonl(ptmp[0]);
|
||||
ptmp[0] = htonl(ptmp[1]);
|
||||
tmp = dbr_htonl(ptmp[0]);
|
||||
ptmp[0] = dbr_htonl(ptmp[1]);
|
||||
ptmp[1] = tmp;
|
||||
|
||||
if( ((int)pIEEE->exp) > (DBLEXPMAXMIT + IEEE_DBL_SB) ){
|
||||
@@ -1527,10 +1537,14 @@ struct mitflt{
|
||||
# define EXPMAXMIT 126 /* max MIT exponent */
|
||||
# define EXPMINMIT -128 /* min MIT exponent */
|
||||
|
||||
/* (this includes mapping of fringe reals to zero or infinity) */
|
||||
/* (byte swaps included in conversion */
|
||||
|
||||
void htonf(float *pHost, float *pNet)
|
||||
/*
|
||||
* (this includes mapping of fringe reals to zero or infinity)
|
||||
* (byte swaps included in conversion
|
||||
*
|
||||
* Uses internal buffer so the src and dest ptr
|
||||
* can be identical
|
||||
*/
|
||||
void dbr_htonf(dbr_float_t *pHost, dbr_float_t *pNet)
|
||||
{
|
||||
struct mitflt *pMIT = (struct mitflt *) pHost;
|
||||
struct ieeeflt *pIEEE = (struct ieeeflt *) pNet;
|
||||
@@ -1550,21 +1564,24 @@ void htonf(float *pHost, float *pNet)
|
||||
pIEEE->mant = mant;
|
||||
pIEEE->exp = exp;
|
||||
pIEEE->sign = sign;
|
||||
*(ca_uint32_t *)pIEEE = htonl(*(ca_uint32_t *)pIEEE);
|
||||
*(ca_uint32_t *)pIEEE = dbr_htonl(*(ca_uint32_t *)pIEEE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sign must be forced to zero if the exponent is zero to prevent a reserved
|
||||
* operand fault- joh 9-13-90
|
||||
*
|
||||
* Uses internal buffer so the src and dest ptr
|
||||
* can be identical
|
||||
*/
|
||||
void ntohf(float *pNet, float *pHost)
|
||||
void dbr_ntohf(dbr_float_t *pNet, dbr_float_t *pHost)
|
||||
{
|
||||
struct mitflt *pMIT = (struct mitflt *) pHost;
|
||||
struct ieeeflt *pIEEE = (struct ieeeflt *) pNet;
|
||||
long exp,mant2,mant1,sign;
|
||||
|
||||
*(ca_uint32_t *)pIEEE = ntohl(*(ca_uint32_t *)pIEEE);
|
||||
*(ca_uint32_t *)pIEEE = dbr_ntohl(*(ca_uint32_t *)pIEEE);
|
||||
if( ((int)pIEEE->exp) > EXPMAXMIT + IEEE_SB){
|
||||
sign = pIEEE->sign;
|
||||
exp = EXPMAXMIT + MIT_SB;
|
||||
@@ -1595,10 +1612,10 @@ void ntohf(float *pNet, float *pHost)
|
||||
#if defined(CA_FLOAT_IEEE) && 0
|
||||
|
||||
/*
|
||||
* htond ()
|
||||
* dbr_htond ()
|
||||
* performs only byte swapping
|
||||
*/
|
||||
void htond (double *IEEEhost, double *IEEEnet)
|
||||
void dbr_htond (dbr_double_t *IEEEhost, dbr_double_t *IEEEnet)
|
||||
{
|
||||
#ifdef CA_LITTLE_ENDIAN
|
||||
ca_uint32_t *pHost = (ca_uint32_t *) IEEEhost;
|
||||
@@ -1611,18 +1628,18 @@ void htond (double *IEEEhost, double *IEEEnet)
|
||||
* may be identical)
|
||||
*/
|
||||
tmp = pHost[0];
|
||||
pNet[0] = htonl (pHost[1]);
|
||||
pNet[1] = htonl (tmp);
|
||||
pNet[0] = dbr_htonl (pHost[1]);
|
||||
pNet[1] = dbr_htonl (tmp);
|
||||
#else
|
||||
*IEEEnet = *IEEEhost;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ntohd ()
|
||||
* dbr_ntohd ()
|
||||
* performs only byte swapping
|
||||
*/
|
||||
void ntohd (double *IEEEnet, double *IEEEhost)
|
||||
void dbr_ntohd (dbr_double_t *IEEEnet, dbr_double_t *IEEEhost)
|
||||
{
|
||||
#ifdef CA_LITTLE_ENDIAN
|
||||
ca_uint32_t *pHost = (ca_uint32_t *) IEEEhost;
|
||||
@@ -1635,35 +1652,35 @@ void ntohd (double *IEEEnet, double *IEEEhost)
|
||||
* may be identical)
|
||||
*/
|
||||
tmp = pNet[0];
|
||||
pHost[0] = ntohl (pNet[1]);
|
||||
pHost[1] = htonl (tmp);
|
||||
pHost[0] = dbr_ntohl (pNet[1]);
|
||||
pHost[1] = dbr_htonl (tmp);
|
||||
#else
|
||||
*IEEEhost = *IEEEnet;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ntohf ()
|
||||
* dbr_ntohf ()
|
||||
* performs only byte swapping
|
||||
*/
|
||||
void ntohf (float *IEEEnet, float *IEEEhost)
|
||||
void dbr_ntohf (dbr_float_t *IEEEnet, dbr_float_t *IEEEhost)
|
||||
{
|
||||
ca_uint32_t *pHost = (ca_uint32_t *) IEEEhost;
|
||||
ca_uint32_t *pNet = (ca_uint32_t *) IEEEnet;
|
||||
|
||||
*pHost = ntohl (*pNet);
|
||||
*pHost = dbr_ntohl (*pNet);
|
||||
}
|
||||
|
||||
/*
|
||||
* htonf ()
|
||||
* dbr_htonf ()
|
||||
* performs only byte swapping
|
||||
*/
|
||||
void htonf (float *IEEEhost, float *IEEEnet)
|
||||
void dbr_htonf (dbr_float_t *IEEEhost, dbr_float_t *IEEEnet)
|
||||
{
|
||||
ca_uint32_t *pHost = (ca_uint32_t *) IEEEhost;
|
||||
ca_uint32_t *pNet = (ca_uint32_t *) IEEEnet;
|
||||
|
||||
*pNet = htonl (*pHost);
|
||||
*pNet = dbr_htonl (*pHost);
|
||||
}
|
||||
|
||||
#endif /* IEEE float and little endian */
|
||||
|
||||
@@ -95,6 +95,5 @@ void flow_control(struct ioc_in_use *piiu)
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
331
src/ca/iocinf.c
331
src/ca/iocinf.c
@@ -270,57 +270,53 @@ int net_proto
|
||||
#endif
|
||||
|
||||
#ifdef CA_SET_TCP_BUFFER_SIZES
|
||||
/* set TCP buffer sizes */
|
||||
i = MAX_MSG_SIZE;
|
||||
status = setsockopt(
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_SNDBUF,
|
||||
&i,
|
||||
sizeof(i));
|
||||
if(status < 0){
|
||||
free(piiu);
|
||||
status = socket_close(sock);
|
||||
if(status<0){
|
||||
SEVCHK(ECA_INTERNAL,NULL);
|
||||
}
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
}
|
||||
i = MAX_MSG_SIZE;
|
||||
status = setsockopt(
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_RCVBUF,
|
||||
&i,
|
||||
sizeof(i));
|
||||
if(status < 0){
|
||||
free(piiu);
|
||||
status = socket_close(sock);
|
||||
if(status<0){
|
||||
SEVCHK(ECA_INTERNAL,NULL);
|
||||
}
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
}
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
|
||||
/* fetch the TCP send buffer size */
|
||||
i = sizeof(piiu->tcp_send_buff_size);
|
||||
status = getsockopt(
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_SNDBUF,
|
||||
(char *)&piiu->tcp_send_buff_size,
|
||||
&i);
|
||||
if(status < 0 || i != sizeof(piiu->tcp_send_buff_size)){
|
||||
free(piiu);
|
||||
status = socket_close(sock);
|
||||
if(status<0){
|
||||
SEVCHK(ECA_INTERNAL,NULL);
|
||||
/* set TCP buffer sizes */
|
||||
i = MAX_MSG_SIZE;
|
||||
status = setsockopt(
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_SNDBUF,
|
||||
&i,
|
||||
sizeof(i));
|
||||
if(status < 0){
|
||||
free(piiu);
|
||||
socket_close(sock);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
}
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
}
|
||||
i = MAX_MSG_SIZE;
|
||||
status = setsockopt(
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_RCVBUF,
|
||||
&i,
|
||||
sizeof(i));
|
||||
if(status < 0){
|
||||
free(piiu);
|
||||
socket_close(sock);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
}
|
||||
|
||||
/* fetch the TCP send buffer size */
|
||||
i = sizeof(size);
|
||||
status = getsockopt(
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_SNDBUF,
|
||||
(char *)&size,
|
||||
&i);
|
||||
if(status < 0 || i != sizeof(size)){
|
||||
free(piiu);
|
||||
socket_close(sock);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* connect */
|
||||
@@ -342,20 +338,6 @@ int net_proto
|
||||
cacRingBufferInit(&piiu->recv, sizeof(piiu->send.buf));
|
||||
cacRingBufferInit(&piiu->send, sizeof(piiu->send.buf));
|
||||
|
||||
/*
|
||||
* Set non blocking IO
|
||||
* to prevent dead locks
|
||||
*/
|
||||
status = socket_ioctl(
|
||||
piiu->sock_chan,
|
||||
FIONBIO,
|
||||
&true);
|
||||
if(status<0){
|
||||
ca_printf(
|
||||
"Error setting non-blocking io: %s\n",
|
||||
strerror(MYERRNO));
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the Host name for efficient access in the
|
||||
* future.
|
||||
@@ -435,6 +417,7 @@ int net_proto
|
||||
sock,
|
||||
ca_static->ca_server_port);
|
||||
|
||||
|
||||
cacRingBufferInit(&piiu->recv, sizeof(piiu->send.buf));
|
||||
cacRingBufferInit(&piiu->send, min(MAX_UDP,
|
||||
sizeof(piiu->send.buf)));
|
||||
@@ -455,6 +438,20 @@ int net_proto
|
||||
return ECA_INTERNAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set non blocking IO
|
||||
* to prevent dead locks
|
||||
*/
|
||||
status = socket_ioctl(
|
||||
piiu->sock_chan,
|
||||
FIONBIO,
|
||||
&true);
|
||||
if(status<0){
|
||||
ca_printf(
|
||||
"Error setting non-blocking io: %s\n",
|
||||
strerror(MYERRNO));
|
||||
}
|
||||
|
||||
if(fd_register_func){
|
||||
LOCKEVENTS;
|
||||
(*fd_register_func)(fd_register_arg, sock, TRUE);
|
||||
@@ -570,21 +567,34 @@ void notify_ca_repeater()
|
||||
LOCK; /*MULTINET TCP/IP routines are not reentrant*/
|
||||
status = local_addr(piiuCast->sock_chan, &saddr);
|
||||
if (status == OK) {
|
||||
int len;
|
||||
|
||||
memset((char *)&msg, 0, sizeof(msg));
|
||||
msg.m_cmmd = htons(REPEATER_REGISTER);
|
||||
msg.m_available = saddr.sin_addr.s_addr;
|
||||
saddr.sin_port = htons(ca_static->ca_repeater_port);
|
||||
|
||||
/*
|
||||
* Intentionally sending a zero length message here
|
||||
* until most CA repeater daemons have been restarted
|
||||
* (and only then will accept the above protocol)
|
||||
* (repeaters began accepting this protocol
|
||||
* starting with EPICS 3.12)
|
||||
*
|
||||
* SOLARIS will not accept a zero length message
|
||||
* and we are just porting there for 3.12 so
|
||||
* we will use the new protocol for 3.12
|
||||
*/
|
||||
# ifdef SOLARIS
|
||||
len = sizeof(msg);
|
||||
# else /* SOLARIS */
|
||||
len = 0;
|
||||
# endif /* SOLARIS */
|
||||
|
||||
status = sendto(
|
||||
piiuCast->sock_chan,
|
||||
(char *)&msg, /* UCX requires a valid address here */
|
||||
0, /* <= sizeof(msg) ! see comment above ! */
|
||||
len,
|
||||
0,
|
||||
(struct sockaddr *)&saddr,
|
||||
sizeof(saddr));
|
||||
@@ -654,9 +664,13 @@ LOCAL void cac_udp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
|
||||
localErrno = MYERRNO;
|
||||
|
||||
if( localErrno != EWOULDBLOCK &&
|
||||
localErrno != ENOBUFS &&
|
||||
localErrno != EINTR){
|
||||
if( localErrno == EWOULDBLOCK &&
|
||||
localErrno == ENOBUFS &&
|
||||
localErrno == EINTR){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ca_printf(
|
||||
"CAC: error on socket send() %s\n",
|
||||
strerror(localErrno));
|
||||
@@ -704,34 +718,47 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
|
||||
LOCK;
|
||||
|
||||
sendCnt = cacRingBufferReadSize(&piiu->send, TRUE);
|
||||
|
||||
assert(sendCnt<=piiu->send.max_msg);
|
||||
|
||||
/*
|
||||
* return if nothing to send
|
||||
* Check at least twice to see if there is anything
|
||||
* in the ring buffer (in case the block of messages
|
||||
* isnt continuous). Always return if the send was
|
||||
* less bytes than requested.
|
||||
*/
|
||||
if(sendCnt == 0){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
while (TRUE) {
|
||||
sendCnt = cacRingBufferReadSize(&piiu->send, TRUE);
|
||||
assert(sendCnt<=piiu->send.max_msg);
|
||||
|
||||
status = send(
|
||||
piiu->sock_chan,
|
||||
&piiu->send.buf[piiu->send.rdix],
|
||||
sendCnt,
|
||||
0);
|
||||
if(status>=0){
|
||||
piiu->sendPending = FALSE;
|
||||
CAC_RING_BUFFER_READ_ADVANCE(&piiu->send, status);
|
||||
|
||||
sendCnt = cacRingBufferReadSize(&piiu->send, FALSE);
|
||||
if(sendCnt==0){
|
||||
/*
|
||||
* return if nothing to send
|
||||
*/
|
||||
if(sendCnt == 0){
|
||||
piiu->sendPending = FALSE;
|
||||
piiu->send_needed = FALSE;
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
return;
|
||||
status = send(
|
||||
piiu->sock_chan,
|
||||
&piiu->send.buf[piiu->send.rdix],
|
||||
sendCnt,
|
||||
0);
|
||||
if (status<0) {
|
||||
break;
|
||||
}
|
||||
else if (status==0) {
|
||||
TAG_CONN_DOWN(piiu);
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
CAC_RING_BUFFER_READ_ADVANCE(&piiu->send, status);
|
||||
|
||||
if (status != sendCnt) {
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
localError = MYERRNO;
|
||||
@@ -740,10 +767,6 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
localError == ENOBUFS ||
|
||||
localError == EINTR){
|
||||
UNLOCK;
|
||||
if(!piiu->sendPending){
|
||||
cac_gettimeval(&piiu->timeAtSendBlock);
|
||||
piiu->sendPending = TRUE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -788,7 +811,6 @@ void cac_flush_internal()
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* cac_clean_iiu_list()
|
||||
@@ -823,14 +845,16 @@ void ca_process_input_queue()
|
||||
{
|
||||
struct ioc_in_use *piiu;
|
||||
|
||||
LOCK;
|
||||
|
||||
/*
|
||||
* dont allow recursion
|
||||
* dont allow recursion
|
||||
*/
|
||||
if(post_msg_active){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
for( piiu=(IIU *)iiuList.node.next;
|
||||
piiu;
|
||||
piiu=(IIU *)piiu->node.next){
|
||||
@@ -841,6 +865,7 @@ void ca_process_input_queue()
|
||||
|
||||
(*piiu->procInput)(piiu);
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
cac_flush_internal();
|
||||
@@ -863,55 +888,59 @@ LOCAL void tcp_recv_msg(struct ioc_in_use *piiu)
|
||||
|
||||
LOCK;
|
||||
|
||||
writeSpace = cacRingBufferWriteSize(&piiu->recv, TRUE);
|
||||
if(writeSpace == 0){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Check at least twice to see if there is ana space left
|
||||
* in the ring buffer (in case the messages block
|
||||
* isnt continuous). Always return if the send was
|
||||
* less bytes than requested.
|
||||
*/
|
||||
while (TRUE) {
|
||||
|
||||
status = recv( piiu->sock_chan,
|
||||
&piiu->recv.buf[piiu->recv.wtix],
|
||||
writeSpace,
|
||||
0);
|
||||
if(status == 0){
|
||||
TAG_CONN_DOWN(piiu);
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
else if(status <0){
|
||||
/* try again on status of -1 and no luck this time */
|
||||
if(MYERRNO == EWOULDBLOCK || MYERRNO == EINTR){
|
||||
UNLOCK;
|
||||
return;
|
||||
writeSpace = cacRingBufferWriteSize(&piiu->recv, TRUE);
|
||||
if(writeSpace == 0){
|
||||
break;
|
||||
}
|
||||
|
||||
if( MYERRNO != EPIPE &&
|
||||
MYERRNO != ECONNRESET &&
|
||||
MYERRNO != ETIMEDOUT){
|
||||
ca_printf(
|
||||
"CAC: unexpected recv error (err=%s)\n",
|
||||
strerror(MYERRNO));
|
||||
status = recv( piiu->sock_chan,
|
||||
&piiu->recv.buf[piiu->recv.wtix],
|
||||
writeSpace,
|
||||
0);
|
||||
if(status == 0){
|
||||
TAG_CONN_DOWN(piiu);
|
||||
break;
|
||||
}
|
||||
TAG_CONN_DOWN(piiu);
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
else if(status <0){
|
||||
/* try again on status of -1 and no luck this time */
|
||||
if(MYERRNO == EWOULDBLOCK || MYERRNO == EINTR){
|
||||
break;
|
||||
}
|
||||
|
||||
if(status>MAX_MSG_SIZE){
|
||||
ca_printf( "CAC: recv_msg(): message overflow %l\n",
|
||||
status-MAX_MSG_SIZE);
|
||||
TAG_CONN_DOWN(piiu);
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
if( MYERRNO != EPIPE &&
|
||||
MYERRNO != ECONNRESET &&
|
||||
MYERRNO != ETIMEDOUT){
|
||||
ca_printf(
|
||||
"CAC: unexpected recv error (err=%s)\n",
|
||||
strerror(MYERRNO));
|
||||
}
|
||||
TAG_CONN_DOWN(piiu);
|
||||
break;
|
||||
}
|
||||
|
||||
CAC_RING_BUFFER_WRITE_ADVANCE(&piiu->recv, status);
|
||||
assert (status<=writeSpace);
|
||||
|
||||
CAC_RING_BUFFER_WRITE_ADVANCE(&piiu->recv, status);
|
||||
|
||||
/*
|
||||
* Record the time whenever we receive a message
|
||||
* from this IOC
|
||||
*/
|
||||
piiu->timeAtLastRecv = ca_static->currentTime;
|
||||
|
||||
if (status != writeSpace) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the time whenever we receive a message
|
||||
* from this IOC
|
||||
*/
|
||||
cac_gettimeval(&piiu->timeAtLastRecv);
|
||||
|
||||
UNLOCK;
|
||||
return;
|
||||
@@ -928,18 +957,20 @@ LOCAL void ca_process_tcp(struct ioc_in_use *piiu)
|
||||
int status;
|
||||
long bytesToProcess;
|
||||
|
||||
LOCK;
|
||||
|
||||
/*
|
||||
* dont allow recursion
|
||||
*/
|
||||
if(post_msg_active){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
pNode = (caAddrNode *) piiu->destAddr.node.next;
|
||||
|
||||
post_msg_active = TRUE;
|
||||
|
||||
LOCK;
|
||||
pNode = (caAddrNode *) piiu->destAddr.node.next;
|
||||
|
||||
while(TRUE){
|
||||
bytesToProcess = cacRingBufferReadSize(&piiu->recv, TRUE);
|
||||
if(bytesToProcess == 0){
|
||||
@@ -962,9 +993,9 @@ LOCAL void ca_process_tcp(struct ioc_in_use *piiu)
|
||||
&piiu->recv,
|
||||
bytesToProcess);
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
post_msg_active = FALSE;
|
||||
UNLOCK;
|
||||
|
||||
flow_control(piiu);
|
||||
|
||||
@@ -1065,17 +1096,18 @@ LOCAL void ca_process_udp(struct ioc_in_use *piiu)
|
||||
char *pBuf;
|
||||
unsigned long bytesAvailable;
|
||||
|
||||
LOCK;
|
||||
|
||||
/*
|
||||
* dont allow recursion
|
||||
*/
|
||||
if(post_msg_active){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
post_msg_active = TRUE;
|
||||
|
||||
LOCK;
|
||||
while(TRUE){
|
||||
|
||||
bytesAvailable = cacRingBufferReadSize(&piiu->recv, TRUE);
|
||||
@@ -1123,9 +1155,8 @@ LOCAL void ca_process_udp(struct ioc_in_use *piiu)
|
||||
bytesAvailable);
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
post_msg_active = FALSE;
|
||||
UNLOCK;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1195,6 +1226,16 @@ void close_ioc (struct ioc_in_use *piiu)
|
||||
ca_signal (ECA_DISCONN,piiu->host_name_str);
|
||||
}
|
||||
|
||||
/*
|
||||
* clear outstanding get call backs
|
||||
*/
|
||||
caIOBlockListFree (&pend_read_list, chix, TRUE, ECA_DISCONN);
|
||||
|
||||
/*
|
||||
* clear outstanding put call backs
|
||||
*/
|
||||
caIOBlockListFree (&pend_write_list, chix, TRUE, ECA_DISCONN);
|
||||
|
||||
/*
|
||||
* call their connection handler as required
|
||||
*/
|
||||
|
||||
@@ -80,7 +80,6 @@ HDRVERSIONID(iocinfh, "$Id$")
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
@@ -96,6 +95,7 @@ HDRVERSIONID(iocinfh, "$Id$")
|
||||
/*
|
||||
* EPICS includes
|
||||
*/
|
||||
#include <epicsAssert.h>
|
||||
#include <cadef.h>
|
||||
#include <bucketLib.h>
|
||||
#include <ellLib.h>
|
||||
@@ -120,8 +120,8 @@ HDRVERSIONID(iocinfh, "$Id$")
|
||||
# define NBBY 8 /* number of bits per byte */
|
||||
#endif
|
||||
|
||||
#define MSEC_PER_SEC 1000
|
||||
#define USEC_PER_SEC 1000000
|
||||
#define MSEC_PER_SEC 1000L
|
||||
#define USEC_PER_SEC 1000000L
|
||||
|
||||
/*
|
||||
* catch when they use really large strings
|
||||
@@ -171,7 +171,7 @@ typedef struct timeval ca_time;
|
||||
|
||||
#define LD_CA_TIME(FLOAT_TIME,PCATIME) \
|
||||
((PCATIME)->tv_sec = (long) (FLOAT_TIME), \
|
||||
(PCATIME)->tv_usec = (long) ((FLOAT_TIME)-(PCATIME)->tv_sec)*USEC_PER_SEC)
|
||||
(PCATIME)->tv_usec = (long) ( ((FLOAT_TIME)-(PCATIME)->tv_sec)*USEC_PER_SEC ))
|
||||
|
||||
/*
|
||||
* dont adjust
|
||||
@@ -190,8 +190,8 @@ extern const ca_time CA_CURRENT_TIME;
|
||||
*/
|
||||
#define MAXCONNTRIES 30 /* N conn retries on unchanged net */
|
||||
|
||||
#define SELECT_POLL (0.1) /* units sec - polls into recast */
|
||||
#define CA_RECAST_DELAY (0.1) /* initial delay to next recast (sec) */
|
||||
#define SELECT_POLL (0.05) /* units sec - polls into recast */
|
||||
#define CA_RECAST_DELAY (0.1) /* initial delay to next recast (sec) */
|
||||
#define CA_RECAST_PORT_MASK 0xff /* random retry interval off port */
|
||||
#define CA_RECAST_PERIOD (5.0) /* ul on retry period long term (sec) */
|
||||
|
||||
@@ -214,7 +214,7 @@ extern const ca_time CA_CURRENT_TIME;
|
||||
#define CA_RETRY_PERIOD 5 /* int sec to next keepalive */
|
||||
|
||||
#define N_REPEATER_TRIES_PRIOR_TO_MSG 50
|
||||
#define REPEATER_TRY_PERIOD (0.1)
|
||||
#define REPEATER_TRY_PERIOD (1.0)
|
||||
|
||||
#ifdef vxWorks
|
||||
typedef struct caclient_put_notify{
|
||||
@@ -318,7 +318,7 @@ struct ca_buffer{
|
||||
|
||||
#define TAG_CONN_DOWN(PIIU) \
|
||||
( \
|
||||
/*ca_printf("Tagging connection down at %d in %s\n", __LINE__, __FILE__),*/ \
|
||||
/* ca_printf("Tagging connection down at %d in %s\n", __LINE__, __FILE__), */ \
|
||||
(PIIU)->conn_up = FALSE \
|
||||
)
|
||||
|
||||
@@ -397,6 +397,7 @@ struct ca_static{
|
||||
ELLLIST putCvrtBuf;
|
||||
ELLLIST fdInfoFreeList;
|
||||
ELLLIST fdInfoList;
|
||||
ca_time currentTime;
|
||||
ca_time ca_conn_next_retry;
|
||||
ca_time ca_conn_retry_delay;
|
||||
ca_time ca_last_repeater_try;
|
||||
@@ -422,6 +423,7 @@ struct ca_static{
|
||||
bhe *ca_beaconHash[BHT_INET_ADDR_MASK+1];
|
||||
unsigned ca_repeater_tries;
|
||||
unsigned ca_search_retry; /* search retry seq number */
|
||||
unsigned ca_search_responses; /* num search resp within seq # */
|
||||
unsigned short ca_server_port;
|
||||
unsigned short ca_repeater_port;
|
||||
char ca_sprintf_buf[256];
|
||||
@@ -551,6 +553,12 @@ unsigned long cacRingBufferReadSize(
|
||||
struct ca_buffer *pBuf,
|
||||
int contiguous);
|
||||
|
||||
void caIOBlockListFree(
|
||||
ELLLIST *pList,
|
||||
chid chan,
|
||||
int cbRequired,
|
||||
int status);
|
||||
|
||||
char *localUserName(void);
|
||||
|
||||
char *localHostName(void);
|
||||
|
||||
@@ -134,7 +134,8 @@ typedef float ca_float32_t;
|
||||
* fields aligned on natural boundaries.
|
||||
*
|
||||
* NOTE: all structures declared in this file must have a
|
||||
* byte count which is evenly divisible by 8 for the SPARC.
|
||||
* byte count which is evenly divisible by 8 matching
|
||||
* the largest atomic data type in db_access.h.
|
||||
*/
|
||||
#define CA_MESSAGE_ALIGN(A) (OCT_ROUND(A)<<3)
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <db_access.h>
|
||||
|
||||
#ifdef CA_LITTLE_ENDIAN
|
||||
# ifndef ntohs
|
||||
# define ntohs(SHORT)\
|
||||
@@ -64,29 +66,29 @@
|
||||
#endif
|
||||
|
||||
#if defined(CA_FLOAT_IEEE) && !defined(CA_LITTLE_ENDIAN)
|
||||
# define htond(IEEEhost, IEEEnet) \
|
||||
(*(double *)(IEEEnet) = *(double *)(IEEEhost))
|
||||
# define ntohd(IEEEnet, IEEEhost) \
|
||||
(*(double *)(IEEEhost) = *(double *)(IEEEnet))
|
||||
# define htonf(IEEEhost, IEEEnet) \
|
||||
(*(float *)(IEEEnet) = *(float *)(IEEEhost))
|
||||
# define ntohf(IEEEnet, IEEEhost) \
|
||||
(*(float *)(IEEEhost) = *(float *)(IEEEnet))
|
||||
# define dbr_htond(IEEEhost, IEEEnet) \
|
||||
(*(dbr_double_t *)(IEEEnet) = *(dbr_double_t *)(IEEEhost))
|
||||
# define dbr_ntohd(IEEEnet, IEEEhost) \
|
||||
(*(dbr_double_t *)(IEEEhost) = *(dbr_double_t *)(IEEEnet))
|
||||
# define dbr_htonf(IEEEhost, IEEEnet) \
|
||||
(*(dbr_float_t *)(IEEEnet) = *(dbr_float_t *)(IEEEhost))
|
||||
# define dbr_ntohf(IEEEnet, IEEEhost) \
|
||||
(*(dbr_float_t *)(IEEEhost) = *(dbr_float_t *)(IEEEnet))
|
||||
#elif defined(CA_FLOAT_IEEE) && defined(CA_LITTLE_ENDIAN)
|
||||
# define ntohf(NET,HOST) \
|
||||
{*((u_long *)(HOST)) = ntohl(*((u_long *)(NET )));}
|
||||
# define htonf(HOST,NET) \
|
||||
{*((u_long *)(NET) ) = htonl(*((u_long *)(HOST)));}
|
||||
# define ntohd(NET,HOST) \
|
||||
{ ((u_long *)(HOST))[1] = ntohl(((u_long *)(NET))[0]) ; \
|
||||
((u_long *)(HOST))[0] = ntohl(((u_long *)(NET))[1]) ;}
|
||||
# define htond(HOST,NET) \
|
||||
{ ((u_long *)(NET))[1] = htonl(((u_long *)(HOST))[0]) ; \
|
||||
((u_long *)(NET))[0] = htonl(((u_long *)(HOST))[1]) ;}
|
||||
# define dbr_ntohf(NET,HOST) \
|
||||
{*((dbr_long_t *)(HOST)) = ntohl(*((dbr_long_t *)(NET )));}
|
||||
# define dbr_htonf(HOST,NET) \
|
||||
{*((dbr_long_t *)(NET) ) = htonl(*((dbr_long_t *)(HOST)));}
|
||||
# define dbr_ntohd(NET,HOST) \
|
||||
{ ((dbr_long_t *)(HOST))[1] = ntohl(((dbr_long_t *)(NET))[0]) ; \
|
||||
((dbr_long_t *)(HOST))[0] = ntohl(((dbr_long_t *)(NET))[1]) ;}
|
||||
# define dbr_htond(HOST,NET) \
|
||||
{ ((dbr_long_t *)(NET))[1] = htonl(((dbr_long_t *)(HOST))[0]) ; \
|
||||
((dbr_long_t *)(NET))[0] = htonl(((dbr_long_t *)(HOST))[1]) ;}
|
||||
#else
|
||||
void htond(double *pHost, double *pNet);
|
||||
void ntohd(double *pNet, double *pHost);
|
||||
void htonf(float *pHost, float *pNet);
|
||||
void ntohf(float *pNet, float *pHost);
|
||||
void dbr_htond(dbr_double_t *pHost, dbr_double_t *pNet);
|
||||
void dbr_ntohd(dbr_double_t *pNet, dbr_double_t *pHost);
|
||||
void dbr_htonf(dbr_float_t *pHost, dbr_float_t *pNet);
|
||||
void dbr_ntohf(dbr_float_t *pNet, dbr_float_t *pHost);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ static char *sccsId = "@(#) $Id$";
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
# include <winsock.h>
|
||||
@@ -49,6 +48,8 @@ static char *sccsId = "@(#) $Id$";
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <epicsAssert.h>
|
||||
|
||||
|
||||
/*
|
||||
* caHostFromInetAddr()
|
||||
|
||||
@@ -40,6 +40,7 @@ static char *os_depenhSccsId = "$Id$";
|
||||
* each socket library
|
||||
*/
|
||||
#ifdef UNIX
|
||||
# include <unistd.h>
|
||||
# include <errno.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/time.h>
|
||||
@@ -49,6 +50,7 @@ static char *os_depenhSccsId = "$Id$";
|
||||
# include <netinet/in.h>
|
||||
# include <netinet/tcp.h>
|
||||
# include <net/if.h>
|
||||
# include <arpa/inet.h>
|
||||
# define CA_OS_CONFIGURED
|
||||
#endif
|
||||
|
||||
|
||||
@@ -66,50 +66,27 @@ void cac_gettimeval(struct timeval *pt)
|
||||
void cac_mux_io(struct timeval *ptimeout)
|
||||
{
|
||||
int count;
|
||||
int newInput;
|
||||
struct timeval timeout;
|
||||
|
||||
cac_clean_iiu_list();
|
||||
|
||||
timeout = *ptimeout;
|
||||
do{
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_RECVS | CA_DO_SENDS);
|
||||
|
||||
newInput = FALSE;
|
||||
do{
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_RECVS | CA_DO_SENDS);
|
||||
if(count>0){
|
||||
newInput = TRUE;
|
||||
}
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 0;
|
||||
}
|
||||
while(count>0);
|
||||
ca_process_input_queue();
|
||||
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
}
|
||||
while(newInput);
|
||||
}
|
||||
|
||||
log_time(char *pStr)
|
||||
{
|
||||
static struct timeval time;
|
||||
struct timeval newtime;
|
||||
struct timezone tz;
|
||||
ca_real diff;
|
||||
int status;
|
||||
|
||||
status = gettimeofday(&newtime, &tz);
|
||||
assert(status==0);
|
||||
|
||||
diff = cac_time_diff(&newtime, &time);
|
||||
printf("Expired %f - %s\n", diff, pStr);
|
||||
time = newtime;
|
||||
while(count>0);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +223,7 @@ void ca_spawn_repeater()
|
||||
|
||||
/*
|
||||
* return to the caller
|
||||
* if its the in the initiating process
|
||||
* if its in the initiating process
|
||||
*/
|
||||
if (status){
|
||||
return;
|
||||
@@ -260,7 +237,8 @@ void ca_spawn_repeater()
|
||||
status = execlp(pImageName, NULL);
|
||||
if(status<0){
|
||||
ca_printf("!!WARNING!!\n");
|
||||
ca_printf("The executable \"%s\" couldnt be located.\n", pImageName);
|
||||
ca_printf("The executable \"%s\" couldnt be located\n", pImageName);
|
||||
ca_printf("because - %s\n", strerror(MYERRNO));
|
||||
ca_printf("You may need to modify your PATH environment variable.\n");
|
||||
ca_printf("Creating CA repeater with fork() system call.\n");
|
||||
ca_printf("Repeater will inherit parents process name and resources.\n");
|
||||
|
||||
@@ -242,7 +242,7 @@ void ca_repeater()
|
||||
/*
|
||||
* register_new_client()
|
||||
*/
|
||||
void register_new_client(
|
||||
LOCAL void register_new_client(
|
||||
SOCKET sock,
|
||||
struct sockaddr_in *pLocal,
|
||||
struct sockaddr_in *pFrom)
|
||||
|
||||
@@ -119,8 +119,8 @@ unsigned long blockSize
|
||||
if(piiu->curMsgBytes < sizeof(piiu->curMsg)){
|
||||
char *pHdr;
|
||||
|
||||
size = sizeof(piiu->curMsg) - piiu->curMsgBytes;
|
||||
size = min(size, blockSize);
|
||||
size = sizeof (piiu->curMsg) - piiu->curMsgBytes;
|
||||
size = min (size, blockSize);
|
||||
|
||||
pHdr = (char *) &piiu->curMsg;
|
||||
memcpy( pHdr + piiu->curMsgBytes,
|
||||
@@ -129,6 +129,10 @@ unsigned long blockSize
|
||||
|
||||
piiu->curMsgBytes += size;
|
||||
if(piiu->curMsgBytes < sizeof(piiu->curMsg)){
|
||||
#if 0
|
||||
printf ("waiting for %d msg hdr bytes\n",
|
||||
sizeof(piiu->curMsg)-piiu->curMsgBytes);
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -170,14 +174,14 @@ unsigned long blockSize
|
||||
/*
|
||||
* make sure we have a large enough message body cache
|
||||
*/
|
||||
if(piiu->curMsg.m_postsize>piiu->curDataMax){
|
||||
if (piiu->curMsg.m_postsize>piiu->curDataMax) {
|
||||
if(piiu->pCurData){
|
||||
free(piiu->pCurData);
|
||||
}
|
||||
piiu->curDataMax = 0;
|
||||
piiu->pCurData = (void *)
|
||||
malloc(piiu->curMsg.m_postsize);
|
||||
if(!piiu->pCurData){
|
||||
piiu->curDataMax = 0;
|
||||
piiu->curMsgBytes = 0;
|
||||
piiu->curDataBytes = 0;
|
||||
return ERROR;
|
||||
@@ -188,6 +192,8 @@ unsigned long blockSize
|
||||
|
||||
/*
|
||||
* Fetch a complete message body
|
||||
* (allows for arrays larger than than the
|
||||
* ring buffer size)
|
||||
*/
|
||||
if(piiu->curMsg.m_postsize>piiu->curDataBytes){
|
||||
char *pBdy;
|
||||
@@ -200,6 +206,10 @@ unsigned long blockSize
|
||||
size);
|
||||
piiu->curDataBytes += size;
|
||||
if(piiu->curDataBytes < piiu->curMsg.m_postsize){
|
||||
#if 0
|
||||
printf ("waiting for %d msg bdy bytes\n",
|
||||
piiu->curMsg.m_postsize-piiu->curDataBytes);
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
pInBuf += size;
|
||||
@@ -466,7 +476,6 @@ struct in_addr *pnet_addr
|
||||
* read seq
|
||||
*/
|
||||
if (VALID_MSG(piiu)){
|
||||
|
||||
/*
|
||||
* convert the data buffer from net
|
||||
* format to host format
|
||||
@@ -478,11 +487,19 @@ struct in_addr *pnet_addr
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
# else
|
||||
memcpy(
|
||||
(char *)pIOBlock->usr_arg,
|
||||
piiu->pCurData,
|
||||
dbr_size_n(piiu->curMsg.m_type,
|
||||
piiu->curMsg.m_count));
|
||||
if (piiu->curMsg.m_type == DBR_STRING) {
|
||||
strcpy ((char *)pIOBlock->usr_arg,
|
||||
piiu->pCurData);
|
||||
}
|
||||
else {
|
||||
memcpy(
|
||||
(char *)pIOBlock->usr_arg,
|
||||
piiu->pCurData,
|
||||
dbr_size_n (
|
||||
piiu->curMsg.m_type,
|
||||
piiu->curMsg.m_count)
|
||||
);
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
@@ -817,6 +834,7 @@ struct in_addr *pnet_addr
|
||||
ellDelete(&chpiiu->chidlist, &chan->node);
|
||||
chan->piiu = allocpiiu;
|
||||
ellAdd(&allocpiiu->chidlist, &chan->node);
|
||||
ca_static->ca_search_responses++;
|
||||
|
||||
/*
|
||||
* If this is the first channel to be
|
||||
|
||||
@@ -203,7 +203,6 @@ int APIENTRY ca_sg_delete(CA_SYNC_GID gid)
|
||||
int APIENTRY ca_sg_block(CA_SYNC_GID gid, ca_real timeout)
|
||||
{
|
||||
struct timeval beg_time;
|
||||
struct timeval cur_time;
|
||||
ca_real delay;
|
||||
int status;
|
||||
CASG *pcasg;
|
||||
@@ -244,7 +243,12 @@ int APIENTRY ca_sg_block(CA_SYNC_GID gid, ca_real timeout)
|
||||
*/
|
||||
ca_flush_io();
|
||||
|
||||
cac_gettimeval(&beg_time);
|
||||
/*
|
||||
* the current time set within ca_flush_io()
|
||||
* above.
|
||||
*/
|
||||
beg_time = ca_static->currentTime;
|
||||
delay = 0.0;
|
||||
|
||||
status = ECA_NORMAL;
|
||||
while(pcasg->opPendCount){
|
||||
@@ -254,8 +258,6 @@ int APIENTRY ca_sg_block(CA_SYNC_GID gid, ca_real timeout)
|
||||
/*
|
||||
* Exit if the timeout has expired
|
||||
*/
|
||||
cac_gettimeval (&cur_time);
|
||||
delay = cac_time_diff (&cur_time, &beg_time);
|
||||
remaining = timeout-delay;
|
||||
if (remaining<=0.0) {
|
||||
status = ECA_TIMEOUT;
|
||||
@@ -273,6 +275,12 @@ int APIENTRY ca_sg_block(CA_SYNC_GID gid, ca_real timeout)
|
||||
tmo.tv_sec = (long) remaining;
|
||||
tmo.tv_usec = (long) ((remaining-tmo.tv_sec)*USEC_PER_SEC);
|
||||
cac_block_for_sg_completion (pcasg, &tmo);
|
||||
|
||||
/*
|
||||
* the current time set within cac_block_for_sg_completion()
|
||||
* above.
|
||||
*/
|
||||
delay = cac_time_diff (&ca_static->currentTime, &beg_time);
|
||||
}
|
||||
pcasg->opPendCount = 0;
|
||||
pcasg->seqNo++;
|
||||
|
||||
@@ -68,35 +68,27 @@ void cac_gettimeval(struct timeval *pt)
|
||||
void cac_mux_io(struct timeval *ptimeout)
|
||||
{
|
||||
int count;
|
||||
int newInput;
|
||||
struct timeval timeout;
|
||||
|
||||
cac_clean_iiu_list();
|
||||
|
||||
timeout = *ptimeout;
|
||||
do{
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_RECVS | CA_DO_SENDS);
|
||||
|
||||
ca_process_input_queue();
|
||||
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
|
||||
newInput = FALSE;
|
||||
do{
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_RECVS | CA_DO_SENDS);
|
||||
if(count>0){
|
||||
newInput = TRUE;
|
||||
}
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 0;
|
||||
}
|
||||
while(count>0);
|
||||
|
||||
ca_process_input_queue();
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
}
|
||||
while(newInput);
|
||||
while(count>0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,6 @@ LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid);
|
||||
LOCAL int cac_add_task_variable (struct ca_static *ca_temp);
|
||||
LOCAL void deleteCallBack(CALLBACK *pcb);
|
||||
|
||||
#define USEC_PER_SEC 1000000
|
||||
|
||||
|
||||
/*
|
||||
* cac_gettimeval()
|
||||
@@ -104,7 +102,6 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
|
||||
#if NOASYNCRECV
|
||||
cac_clean_iiu_list();
|
||||
manage_conn(TRUE);
|
||||
#endif
|
||||
timeout = *ptimeout;
|
||||
do{
|
||||
@@ -118,6 +115,7 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
|
||||
#if NOASYNCRECV
|
||||
ca_process_input_queue();
|
||||
manage_conn(TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -756,7 +754,7 @@ void ca_spawn_repeater()
|
||||
/*
|
||||
* ca_repeater_task()
|
||||
*/
|
||||
void ca_repeater_task()
|
||||
LOCAL void ca_repeater_task()
|
||||
{
|
||||
taskwdInsert((int)taskIdCurrent, NULL, NULL);
|
||||
ca_repeater();
|
||||
@@ -847,6 +845,7 @@ void cac_recv_task(int tid)
|
||||
{
|
||||
struct timeval timeout;
|
||||
int status;
|
||||
int count;
|
||||
|
||||
taskwdInsert((int) taskIdCurrent, NULL, NULL);
|
||||
|
||||
@@ -861,18 +860,16 @@ void cac_recv_task(int tid)
|
||||
#if NOASYNCRECV
|
||||
taskDelay(60);
|
||||
#else
|
||||
manage_conn(TRUE);
|
||||
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 1;
|
||||
|
||||
cac_clean_iiu_list();
|
||||
|
||||
cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_RECVS);
|
||||
timeout.tv_usec = 50000;
|
||||
timeout.tv_sec = 0;
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_SENDS | CA_DO_RECVS);
|
||||
|
||||
ca_process_input_queue();
|
||||
ca_process_input_queue();
|
||||
manage_conn(TRUE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,35 +75,27 @@ void cac_gettimeval(struct timeval *pt)
|
||||
void cac_mux_io(struct timeval *ptimeout)
|
||||
{
|
||||
int count;
|
||||
int newInput;
|
||||
struct timeval timeout;
|
||||
|
||||
cac_clean_iiu_list();
|
||||
|
||||
timeout = *ptimeout;
|
||||
do{
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE); newInput = FALSE;
|
||||
|
||||
do{
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_RECVS | CA_DO_SENDS);
|
||||
if(count>0){
|
||||
newInput = TRUE;
|
||||
}
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 0;
|
||||
}
|
||||
while(count>0);
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_RECVS | CA_DO_SENDS);
|
||||
|
||||
ca_process_input_queue();
|
||||
|
||||
}
|
||||
while(newInput);
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
}
|
||||
while(count>0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,16 +4,16 @@ include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
SRCS.c = \
|
||||
../dbAccess.c ../dbBkpt.c ../dbFastLinkConv.c ../dbLink.c \
|
||||
../dbStaticLib.c ../iocInit.c ../drvTS.c ../dbScan.c \
|
||||
../dbNotify.c ../dbStaticLib.c ../iocInit.c ../drvTS.c ../dbScan.c \
|
||||
../dbEvent.c ../dbTest.c ../dbls.c ../db_access.c \
|
||||
../db_test.c ../recGbl.c ../callback.c ../taskwd.c \
|
||||
../dbCaLink.c ../dbCaDblink.c ../devLib.c ../initHooks.c
|
||||
|
||||
OBJSdbLib = \
|
||||
dbAccess.o dbBkpt.o dbFastLinkConv.o dbLink.o dbStaticLib.o \
|
||||
iocInit.o drvTS.o dbScan.o dbEvent.o dbTest.o dbls.o db_access.o \
|
||||
db_test.o recGbl.o callback.o taskwd.o dbCaLink.o dbCaDblink.o \
|
||||
devLib.o
|
||||
dbAccess.o dbBkpt.o dbFastLinkConv.o dbLink.o dbNotify.o \
|
||||
dbStaticLib.o iocInit.o drvTS.o dbScan.o dbEvent.o dbTest.o dbls.o \
|
||||
db_access.o db_test.o recGbl.o callback.o taskwd.o dbCaLink.o \
|
||||
dbCaDblink.o devLib.o
|
||||
|
||||
|
||||
PROD = initHooks.o dbLib
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <callback.h>
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <taskwd.h>
|
||||
#include <errMdef.h>
|
||||
#include <task_params.h>
|
||||
@@ -164,3 +166,22 @@ static void wdCallback(long ind)
|
||||
rngDelete(callbackQ[ind]);
|
||||
start(ind);
|
||||
}
|
||||
|
||||
static void ProcessCallback(CALLBACK *pCallback)
|
||||
{
|
||||
struct dbCommon *pRec;
|
||||
|
||||
callbackGetUser(pRec, pCallback);
|
||||
dbScanLock(pRec);
|
||||
((struct rset*)(pRec->rset))->process(pRec);
|
||||
dbScanUnlock(pRec);
|
||||
}
|
||||
void callbackRequestProcessCallback(CALLBACK *pCallback, int Priority, void *pRec)
|
||||
{
|
||||
callbackSetCallback(ProcessCallback, pCallback);
|
||||
callbackSetPriority(Priority, pCallback);
|
||||
callbackSetUser(pRec, pCallback);
|
||||
callbackRequest(pCallback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -117,12 +117,10 @@ long dbCommonInit();
|
||||
|
||||
/*
|
||||
* The lock structure for each database lock set. A lockset is the
|
||||
* connected graph of all adjacent nodes to a record. A record
|
||||
* is considered adjacent if the link connecting it to the lock
|
||||
* set causes that record to process. In other words, a record
|
||||
* is considered part of the lock set if the action of getting
|
||||
* or putting a value to that record (with a link) causes that
|
||||
* record to process.
|
||||
* connected graph of all adjacent nodes to a record (with one
|
||||
* exception, single-valued NPP NMS gets), where adjacent is defined
|
||||
* as a record connected by a get, put, or forward link to the current
|
||||
* record.
|
||||
*/
|
||||
struct scanLock {
|
||||
FAST_LOCK lock;
|
||||
@@ -263,64 +261,20 @@ long dbScanPassive(struct dbCommon *pfrom, struct dbCommon *pto)
|
||||
long status;
|
||||
|
||||
/* if not passive just return success */
|
||||
if (pto->scan != 0) return(0);
|
||||
if(pto->scan != 0) return(0);
|
||||
|
||||
if (pfrom && pfrom->ppn) {
|
||||
PUTNOTIFY *ppn = pfrom->ppn;
|
||||
|
||||
if (pto->ppn) { /*already being used. Abandon request*/
|
||||
ppn->status = S_db_Blocked;
|
||||
dbNotifyCompletion(ppn);
|
||||
} else {
|
||||
ppn->nwaiting++;
|
||||
pto->ppn = pfrom->ppn;
|
||||
/*If already active must redo*/
|
||||
if(pto->pact) ppn->rescan = TRUE;
|
||||
}
|
||||
}
|
||||
if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto);
|
||||
status = dbProcess(pto);
|
||||
if (pfrom && pfrom->ppn) {
|
||||
PUTNOTIFY *ppn = pfrom->ppn;
|
||||
|
||||
if (!pto->pact) {
|
||||
pto->ppn = NULL;
|
||||
} else { /*add to list of records for which to wait*/
|
||||
pto->ppnn = ppn->list;
|
||||
ppn->list = pto;
|
||||
}
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
|
||||
/*KLUDGE: Following needed so that dbPutLink to PROC field works correctly*/
|
||||
long dbScanLink(struct dbCommon *pfrom, struct dbCommon *pto)
|
||||
{
|
||||
long status;
|
||||
|
||||
if(pfrom && pfrom->ppn) {
|
||||
PUTNOTIFY *ppn = pfrom->ppn;
|
||||
|
||||
if(pto->ppn) { /*already being used. Abandon request*/
|
||||
ppn->status = S_db_Blocked;
|
||||
dbNotifyCompletion(ppn);
|
||||
} else {
|
||||
ppn->nwaiting++;
|
||||
pto->ppn = pfrom->ppn;
|
||||
/*If already active must redo*/
|
||||
if(pto->pact) ppn->rescan = TRUE;
|
||||
}
|
||||
}
|
||||
if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto);
|
||||
status = dbProcess(pto);
|
||||
if(pfrom && pfrom->ppn) {
|
||||
PUTNOTIFY *ppn = pfrom->ppn;
|
||||
|
||||
if(!pto->pact) {
|
||||
pto->ppn = NULL;
|
||||
} else { /*add to list of records for which to wait*/
|
||||
pto->ppnn = ppn->list;
|
||||
ppn->list = pto;
|
||||
}
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -64,7 +65,7 @@
|
||||
#include <vxLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <sysLib.h>
|
||||
|
||||
|
||||
#include <fast_lock.h>
|
||||
#include <alarm.h>
|
||||
#include <choice.h>
|
||||
@@ -681,7 +682,15 @@ int dbBkpt(struct dbCommon *precord)
|
||||
* breakpoint handler will not work as expected.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Take and give a semaphore to check for breakpoints
|
||||
* every time a record is processed. Slow. Thank
|
||||
* goodness breakpoint checking is turned off during
|
||||
* normal operation.
|
||||
*/
|
||||
semTake(bkpt_stack_sem, WAIT_FOREVER);
|
||||
FIND_LOCKSET(precord, pnode);
|
||||
semGive(bkpt_stack_sem);
|
||||
|
||||
if (pnode == NULL) {
|
||||
/* no breakpoints in precord's lockset */
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
* joh 21 080393 added task watch dog
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <epicsAssert.h>
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
|
||||
138
src/db/dbLink.c
138
src/db/dbLink.c
@@ -198,144 +198,6 @@ long dbPutField(
|
||||
return(status);
|
||||
}
|
||||
|
||||
static void notifyCallback(CALLBACK *pcallback)
|
||||
{
|
||||
PUTNOTIFY *ppn=NULL;
|
||||
long status;
|
||||
|
||||
callbackGetUser(ppn,pcallback);
|
||||
if(ppn->cmd==notifyCmdRepeat) {
|
||||
status = dbPutNotify(ppn);
|
||||
} else if(ppn->cmd==notifyCmdCallUser) {
|
||||
(ppn->userCallback)(ppn);
|
||||
} else {/*illegal request*/
|
||||
recGblRecordError(-1,ppn->paddr->precord,"dbNotifyCompletion: illegal callback request");
|
||||
}
|
||||
}
|
||||
|
||||
static void notifyCancel(PUTNOTIFY *ppn)
|
||||
{
|
||||
struct dbCommon *precord = ppn->list;
|
||||
|
||||
while(precord) {
|
||||
void *pnext;
|
||||
|
||||
if(precord->rpro) {
|
||||
precord->rpro = FALSE;
|
||||
scanOnce(precord);
|
||||
}
|
||||
precord->ppn = NULL;
|
||||
pnext = precord->ppnn;
|
||||
precord->ppnn = NULL;
|
||||
precord = pnext;
|
||||
}
|
||||
ppn->list = NULL;
|
||||
}
|
||||
|
||||
void dbNotifyCancel(PUTNOTIFY *ppn)
|
||||
{
|
||||
struct dbCommon *precord = ppn->list;
|
||||
|
||||
dbScanLock(precord);
|
||||
notifyCancel(ppn);
|
||||
dbScanUnlock(precord);
|
||||
}
|
||||
|
||||
long dbPutNotify(PUTNOTIFY *ppn)
|
||||
{
|
||||
struct dbAddr *paddr = ppn->paddr;
|
||||
short dbrType = ppn->dbrType;
|
||||
void *pbuffer = ppn->pbuffer;
|
||||
long nRequest = ppn->nRequest;
|
||||
long status=0;
|
||||
struct fldDes *pfldDes=(struct fldDes *)(paddr->pfldDes);
|
||||
struct dbCommon *precord = (struct dbCommon *)(paddr->precord);
|
||||
|
||||
callbackSetCallback(notifyCallback,&ppn->callback);
|
||||
callbackSetUser(ppn,&ppn->callback);
|
||||
callbackSetPriority(priorityLow,&ppn->callback);
|
||||
/*check for putField disabled*/
|
||||
if(precord->disp) {
|
||||
if((void *)(&precord->disp) != paddr->pfield) {
|
||||
ppn->cmd = notifyCmdCallUser;
|
||||
ppn->status = S_db_putDisabled;
|
||||
notifyCallback(&ppn->callback);
|
||||
return(S_db_putDisabled);
|
||||
}
|
||||
}
|
||||
dbScanLock(precord);
|
||||
status=dbPut(paddr,dbrType,pbuffer,nRequest);
|
||||
ppn->status = status;
|
||||
if(status==0){
|
||||
if((paddr->pfield==(void *)&precord->proc)
|
||||
||(pfldDes->process_passive && precord->scan==0)) {
|
||||
if(precord->ppn) {
|
||||
/*record already has attached ppn. Blocked*/
|
||||
|
||||
ppn->status = status = S_db_Blocked;
|
||||
return(status);
|
||||
}
|
||||
ppn->nwaiting = 1;
|
||||
ppn->rescan = FALSE;
|
||||
ppn->list = NULL;
|
||||
precord->ppn = ppn;
|
||||
precord->ppnn = NULL;
|
||||
if(precord->pact) {/*blocked wait for dbNotifyCompletion*/
|
||||
ppn->rescan = TRUE;
|
||||
ppn->status = status = S_db_Pending;
|
||||
return(status);
|
||||
}
|
||||
status=dbProcess(precord);
|
||||
if(status==0) {
|
||||
if(!precord->pact) {
|
||||
precord->ppn = NULL;
|
||||
} else {
|
||||
precord->ppnn = ppn->list;
|
||||
ppn->list = precord;
|
||||
}
|
||||
ppn->status = status = ((ppn->nwaiting == 0) ? 0 : S_db_Pending);
|
||||
} else {
|
||||
ppn->status = status;
|
||||
notifyCancel(ppn);
|
||||
}
|
||||
} else { /*Make callback immediately*/
|
||||
ppn->cmd = notifyCmdCallUser;
|
||||
ppn->status = 0;
|
||||
notifyCallback(&ppn->callback);
|
||||
}
|
||||
}
|
||||
dbScanUnlock(precord);
|
||||
return(status);
|
||||
}
|
||||
|
||||
void dbNotifyCompletion(PUTNOTIFY *ppn)
|
||||
{
|
||||
|
||||
if(ppn->status!=0 && ppn->status!=S_db_Pending) {
|
||||
ppn->cmd = notifyCmdCallUser;
|
||||
notifyCancel(ppn);
|
||||
callbackRequest(&ppn->callback);
|
||||
return;
|
||||
}
|
||||
/*decrement number of records being waited on*/
|
||||
if(ppn->nwaiting<=0) {
|
||||
recGblRecordError(-1,ppn->paddr->precord,"dbNotifyCompletion: nwaiting<-0 LOGIC");
|
||||
return;
|
||||
}
|
||||
if(--ppn->nwaiting == 0) {/*original request completed*/
|
||||
notifyCancel(ppn);
|
||||
if(ppn->rescan) {
|
||||
ppn->cmd = notifyCmdRepeat;
|
||||
callbackRequest(&ppn->callback);
|
||||
} else {
|
||||
/*issue completion callback*/
|
||||
ppn->cmd = notifyCmdCallUser;
|
||||
if(ppn->status==S_db_Pending) ppn->status = 0;
|
||||
callbackRequest(&ppn->callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long dbValueSize(
|
||||
short dbr_type
|
||||
)
|
||||
|
||||
229
src/db/dbNotify.c
Normal file
229
src/db/dbNotify.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/* dbNotify.c */
|
||||
/* base/src/db $Id$ */
|
||||
/*
|
||||
* Author: Marty Kraimer
|
||||
* Date: 03-30-95
|
||||
* Extracted from dbLink.c
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 03-30-95 mrk Extracted from dbLink.c
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <fast_lock.h>
|
||||
#include <dbBase.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbStaticLib.h>
|
||||
#include <dbScan.h>
|
||||
#include <dbCommon.h>
|
||||
#include <errMdef.h>
|
||||
|
||||
static void notifyCallback(CALLBACK *pcallback)
|
||||
{
|
||||
PUTNOTIFY *ppn=NULL;
|
||||
long status;
|
||||
|
||||
callbackGetUser(ppn,pcallback);
|
||||
if(ppn->cmd==notifyCmdRepeat) {
|
||||
status = dbPutNotify(ppn);
|
||||
} else if(ppn->cmd==notifyCmdCallUser) {
|
||||
ppn->cmd = notifyUserCalled;
|
||||
(ppn->userCallback)(ppn);
|
||||
} else {/*illegal request*/
|
||||
recGblRecordError(-1,ppn->paddr->precord,
|
||||
"dbNotifyCompletion: illegal callback request");
|
||||
}
|
||||
}
|
||||
|
||||
static void notifyCancel(PUTNOTIFY *ppn)
|
||||
{
|
||||
struct dbCommon *precord = ppn->list;
|
||||
|
||||
while(precord) {
|
||||
void *pnext;
|
||||
|
||||
if(precord->rpro) {
|
||||
precord->rpro = FALSE;
|
||||
scanOnce(precord);
|
||||
}
|
||||
precord->ppn = NULL;
|
||||
pnext = precord->ppnn;
|
||||
precord->ppnn = NULL;
|
||||
precord = pnext;
|
||||
}
|
||||
ppn->list = NULL;
|
||||
}
|
||||
|
||||
void dbNotifyCancel(PUTNOTIFY *ppn)
|
||||
{
|
||||
struct dbCommon *precord = ppn->list;
|
||||
|
||||
if(!precord) return;
|
||||
dbScanLock(precord);
|
||||
notifyCancel(ppn);
|
||||
if(ppn->cmd!=notifyCmdNull && ppn->cmd!=notifyUserCalled) {
|
||||
/*Bad lets try one time to wait*/
|
||||
dbScanUnlock(precord);
|
||||
taskDelay(10);
|
||||
dbScanLock(precord);
|
||||
}
|
||||
if(ppn->cmd!=notifyCmdNull && ppn->cmd!=notifyUserCalled) {
|
||||
epicsPrintf("dbNotifyCancel called while callback requested"
|
||||
" but not called\n");
|
||||
}
|
||||
dbScanUnlock(precord);
|
||||
}
|
||||
|
||||
static void issueCallback(PUTNOTIFY *ppn, notifyCmd cmd)
|
||||
{
|
||||
if(ppn->cmd!=notifyCmdNull) return;
|
||||
ppn->cmd = cmd;
|
||||
notifyCancel(ppn);
|
||||
callbackRequest(&ppn->callback);
|
||||
}
|
||||
|
||||
long dbPutNotify(PUTNOTIFY *ppn)
|
||||
{
|
||||
struct dbAddr *paddr = ppn->paddr;
|
||||
short dbrType = ppn->dbrType;
|
||||
void *pbuffer = ppn->pbuffer;
|
||||
long nRequest = ppn->nRequest;
|
||||
long status=0;
|
||||
struct fldDes *pfldDes=(struct fldDes *)(paddr->pfldDes);
|
||||
struct dbCommon *precord = (struct dbCommon *)(paddr->precord);
|
||||
|
||||
callbackSetCallback(notifyCallback,&ppn->callback);
|
||||
callbackSetUser(ppn,&ppn->callback);
|
||||
callbackSetPriority(priorityLow,&ppn->callback);
|
||||
/*check for putField disabled*/
|
||||
if(precord->disp) {
|
||||
if((void *)(&precord->disp) != paddr->pfield) {
|
||||
ppn->status = S_db_putDisabled;
|
||||
issueCallback(ppn,notifyCmdCallUser);
|
||||
return(S_db_putDisabled);
|
||||
}
|
||||
}
|
||||
ppn->status = 0;
|
||||
ppn->cmd = notifyCmdNull;
|
||||
ppn->nwaiting = 1;
|
||||
ppn->rescan = FALSE;
|
||||
dbScanLock(precord);
|
||||
status=dbPut(paddr,dbrType,pbuffer,nRequest);
|
||||
ppn->status = status;
|
||||
if(status==0){
|
||||
if((paddr->pfield==(void *)&precord->proc)
|
||||
||(pfldDes->process_passive && precord->scan==0)) {
|
||||
if(precord->ppn) {
|
||||
/*record already has attached ppn. Blocked*/
|
||||
|
||||
ppn->status = status = S_db_Blocked;
|
||||
dbScanUnlock(precord);
|
||||
return(status);
|
||||
}
|
||||
precord->ppn = ppn;
|
||||
precord->ppnn = NULL;
|
||||
ppn->list = precord;
|
||||
if(precord->pact) {/*blocked wait for dbNotifyCompletion*/
|
||||
ppn->rescan = TRUE;
|
||||
dbScanUnlock(precord);
|
||||
return(S_db_Pending);
|
||||
}
|
||||
status=dbProcess(precord);
|
||||
if(status!=0) {
|
||||
ppn->status = status;
|
||||
issueCallback(ppn,notifyCmdCallUser);
|
||||
}
|
||||
} else { /*Make callback immediately*/
|
||||
issueCallback(ppn,notifyCmdCallUser);
|
||||
}
|
||||
}
|
||||
dbScanUnlock(precord);
|
||||
return(S_db_Pending);
|
||||
}
|
||||
|
||||
void dbNotifyCompletion(PUTNOTIFY *ppn)
|
||||
{
|
||||
|
||||
if(ppn->status!=0) {
|
||||
issueCallback(ppn,notifyCmdCallUser);
|
||||
return;
|
||||
}
|
||||
/*decrement number of records being waited on*/
|
||||
if(ppn->nwaiting<=0) {
|
||||
recGblRecordError(-1,ppn->paddr->precord,"dbNotifyCompletion: nwaiting<-0 LOGIC");
|
||||
return;
|
||||
}
|
||||
if(--ppn->nwaiting == 0) {/*original request completed*/
|
||||
if(ppn->rescan) {
|
||||
issueCallback(ppn,notifyCmdRepeat);
|
||||
} else {
|
||||
issueCallback(ppn,notifyCmdCallUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Remove all nonactive records from put notify list*/
|
||||
void cleanPpList(PUTNOTIFY *ppn)
|
||||
{
|
||||
struct dbCommon *precord = ppn->list;
|
||||
struct dbCommon *pnext;
|
||||
struct dbCommon *pprev=NULL;
|
||||
|
||||
while(precord) {
|
||||
pnext = precord->ppnn;
|
||||
if(!precord->pact) {
|
||||
if(!pprev) ppn->list = pnext; else pprev->ppnn = pnext;
|
||||
precord->ppn = NULL;
|
||||
precord->ppnn = NULL;
|
||||
} else {
|
||||
pprev = precord;
|
||||
}
|
||||
precord = pnext;
|
||||
}
|
||||
}
|
||||
|
||||
void dbNotifyAdd(struct dbCommon *pfrom, struct dbCommon *pto)
|
||||
{
|
||||
PUTNOTIFY *ppn = pfrom->ppn;
|
||||
|
||||
if(pto->ppn) cleanPpList(pto->ppn); /* clean list before giving up*/
|
||||
if (pto->ppn) { /*already being used. Abandon request*/
|
||||
ppn->status = S_db_Blocked;
|
||||
dbNotifyCompletion(ppn);
|
||||
} else {
|
||||
ppn->nwaiting++;
|
||||
pto->ppn = pfrom->ppn;
|
||||
pto->ppnn = ppn->list;
|
||||
ppn->list = pto;
|
||||
/*If already active must redo*/
|
||||
if(pto->pact) ppn->rescan = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,11 @@ static char *promptCAMAC_IO[] = {
|
||||
"subaddress:",
|
||||
" function:",
|
||||
" parameter:"};
|
||||
static char *promptRF_IO[] = {
|
||||
" cryo:",
|
||||
" micro:",
|
||||
" dataset:",
|
||||
" element:"};
|
||||
static char *promptAB_IO[] = {
|
||||
" link:",
|
||||
" adapter:",
|
||||
@@ -149,6 +154,7 @@ static void initForms()
|
||||
promptAddr[PV_LINK] = promptPV_LINK; formlines[PV_LINK] = 4;
|
||||
promptAddr[VME_IO] = promptVME_IO; formlines[VME_IO] = 3;
|
||||
promptAddr[CAMAC_IO] = promptCAMAC_IO; formlines[CAMAC_IO] = 6;
|
||||
promptAddr[RF_IO] = promptRF_IO; formlines[RF_IO] = 4;
|
||||
promptAddr[AB_IO] = promptAB_IO; formlines[AB_IO] = 6;
|
||||
promptAddr[GPIB_IO] = promptGPIB_IO; formlines[GPIB_IO] = 3;
|
||||
promptAddr[BITBUS_IO]= promptBITBUS_IO;formlines[BITBUS_IO]= 5;
|
||||
@@ -1338,6 +1344,13 @@ DBENTRY *pdbentry;
|
||||
plink->value.camacio.n,plink->value.camacio.a,
|
||||
plink->value.camacio.f,plink->value.camacio.parm);
|
||||
break;
|
||||
case RF_IO:
|
||||
sprintf(message,"#R%d M%d D%d E%d",
|
||||
plink->value.rfio.cryo,
|
||||
plink->value.rfio.micro,
|
||||
plink->value.rfio.dataset,
|
||||
plink->value.rfio.element);
|
||||
break;
|
||||
case AB_IO:
|
||||
sprintf(message,"#L%d A%d C%d S%d F%d @%s",
|
||||
plink->value.abio.link,plink->value.abio.adapter,
|
||||
@@ -1595,6 +1608,7 @@ char *pstring;
|
||||
DBLINK *plink=(DBLINK *)pfield;
|
||||
char string[80];
|
||||
char *pstr=&string[0];
|
||||
int ind;
|
||||
|
||||
if(strlen(pstring)>=sizeof(string)) {
|
||||
status = S_dbLib_badField;
|
||||
@@ -1604,6 +1618,11 @@ char *pstring;
|
||||
strcpy(pstr,pstring);
|
||||
/*strip off leading blanks and tabs*/
|
||||
while(*pstr && (*pstr==' ' || *pstr=='\t')) pstr++;
|
||||
/*strip off trailing blanks and tabs*/
|
||||
if(pstr) for(ind = strlen(pstr)-1; ind>=0; ind--) {
|
||||
if(pstr[ind]!=' ' && pstr[ind]!='\t') break;
|
||||
pstr[ind] = '\0';
|
||||
}
|
||||
if(!pstr || strlen(pstr)<=0 ) {
|
||||
if(plink->type==PV_LINK) dbCvtLinkToConstant(pdbentry);
|
||||
if(plink->type!=CONSTANT) return(S_dbLib_badField);
|
||||
@@ -1615,14 +1634,15 @@ char *pstring;
|
||||
int pp=0;
|
||||
int ms=0;
|
||||
char *end;
|
||||
char chr;
|
||||
double tempval;
|
||||
|
||||
/* Check first to see if string is a constant*/
|
||||
chr = pstr[0];
|
||||
if(isdigit(chr) || chr=='.' || chr=='-' || chr=='+') {
|
||||
/*It is a double if strtod eats entire string*/
|
||||
/*Note that leading and trailing blanks have already been stripped*/
|
||||
tempval = strtod(pstr,&end);
|
||||
if(*end == 0) {
|
||||
if(plink->type==PV_LINK) dbCvtLinkToConstant(pdbentry);
|
||||
plink->value.value = strtod(pstr,&end);
|
||||
if(*end!=0) return(S_dbLib_badField);
|
||||
plink->value.value = tempval;
|
||||
return(0);
|
||||
}
|
||||
if(plink->type==CONSTANT) dbCvtLinkToPvlink(pdbentry);
|
||||
@@ -1669,18 +1689,12 @@ char *pstring;
|
||||
if(!(end = strchr(pstr,'N'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.camacio.n);
|
||||
if(!(end = strchr(pstr,'A'))) {
|
||||
plink->value.camacio.a = 0;
|
||||
} else {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.camacio.a);
|
||||
}
|
||||
if(!(end = strchr(pstr,'F'))) {
|
||||
plink->value.camacio.f = 0;
|
||||
} else {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.camacio.f);
|
||||
}
|
||||
if(!(end = strchr(pstr,'A'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.camacio.a);
|
||||
if(!(end = strchr(pstr,'F'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.camacio.f);
|
||||
plink->value.camacio.parm[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
@@ -1688,6 +1702,25 @@ char *pstring;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RF_IO: {
|
||||
char *end;
|
||||
|
||||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
if(!(end = strchr(pstr,'R'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.rfio.cryo);
|
||||
if(!(end = strchr(pstr,'M'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.rfio.micro);
|
||||
if(!(end = strchr(pstr,'D'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.rfio.dataset);
|
||||
if(!(end = strchr(pstr,'E'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%hd",&plink->value.rfio.element);
|
||||
}
|
||||
break;
|
||||
case AB_IO: {
|
||||
char *end;
|
||||
|
||||
@@ -2465,6 +2498,15 @@ DBENTRY *pdbentry;
|
||||
value++;
|
||||
strcpy(*value,plink->value.camacio.parm);
|
||||
break;
|
||||
case RF_IO:
|
||||
cvtShortToString(plink->value.rfio.cryo,*value);
|
||||
value++;
|
||||
cvtShortToString(plink->value.rfio.micro,*value);
|
||||
value++;
|
||||
cvtShortToString(plink->value.rfio.dataset,*value);
|
||||
value++;
|
||||
cvtShortToString(plink->value.rfio.element,*value);
|
||||
break;
|
||||
case AB_IO:
|
||||
cvtShortToString(plink->value.abio.link,*value);
|
||||
value++;
|
||||
@@ -2633,6 +2675,35 @@ char **value;
|
||||
value++; verify++;
|
||||
strncpy(plink->value.camacio.parm,*value,CAMAC_PARAM_SZ-1);
|
||||
break;
|
||||
case RF_IO:
|
||||
lvalue = strtol(*value,&endp,0);
|
||||
if(*endp==0) {
|
||||
plink->value.rfio.cryo = lvalue; **verify = 0;
|
||||
} else {
|
||||
strcpy(*verify,"Illegal. Must be number");
|
||||
}
|
||||
value++; verify++;
|
||||
lvalue = strtol(*value,&endp,0);
|
||||
if(*endp==0) {
|
||||
plink->value.rfio.micro = lvalue; **verify = 0;
|
||||
} else {
|
||||
strcpy(*verify,"Illegal. Must be number");
|
||||
}
|
||||
value++; verify++;
|
||||
lvalue = strtol(*value,&endp,0);
|
||||
if(*endp==0) {
|
||||
plink->value.rfio.dataset = lvalue; **verify = 0;
|
||||
} else {
|
||||
strcpy(*verify,"Illegal. Must be number");
|
||||
}
|
||||
value++; verify++;
|
||||
lvalue = strtol(*value,&endp,0);
|
||||
if(*endp==0) {
|
||||
plink->value.rfio.element = lvalue; **verify = 0;
|
||||
} else {
|
||||
strcpy(*verify,"Illegal. Must be number");
|
||||
}
|
||||
break;
|
||||
case AB_IO:
|
||||
lvalue = strtol(*value,&endp,0);
|
||||
if(*endp==0) {
|
||||
|
||||
156
src/db/devLib.c
156
src/db/devLib.c
@@ -45,6 +45,7 @@
|
||||
* .08 05-28-93 joh Added an argument to devRegisterAddress()
|
||||
* .09 05-28-93 joh Added devAddressMap()
|
||||
* .10 06-14-93 joh Added devAllocAddress()
|
||||
* .11 02-21-95 joh Fixed warning messages
|
||||
*
|
||||
* NOTES:
|
||||
* .01 06-14-93 joh needs devAllocInterruptVector() routine
|
||||
@@ -91,8 +92,8 @@ LOCAL char addrListInit;
|
||||
typedef struct{
|
||||
NODE node;
|
||||
const char *pOwnerName;
|
||||
void *pFirst;
|
||||
void *pLast;
|
||||
char *pFirst;
|
||||
char *pLast;
|
||||
}rangeItem;
|
||||
|
||||
/*
|
||||
@@ -103,7 +104,8 @@ LOCAL char *defaultHandlerNames[] = {
|
||||
"_excStub",
|
||||
"_excIntStub",
|
||||
"_unsolicitedHandlerEPICS"};
|
||||
LOCAL void *defaultHandlerAddr[NELEMENTS(defaultHandlerNames)];
|
||||
typedef void myISR (void *pParam);
|
||||
LOCAL myISR *defaultHandlerAddr[NELEMENTS(defaultHandlerNames)];
|
||||
|
||||
/*
|
||||
* These routines are not exported
|
||||
@@ -112,21 +114,21 @@ LOCAL void initHandlerAddrList(void);
|
||||
LOCAL int vectorInUse(unsigned vectorNumber);
|
||||
LOCAL long initAddrList(void);
|
||||
LOCAL long addrVerify(epicsAddressType addrType, void *address);
|
||||
LOCAL void (*isrFetch(unsigned vectorNumber))();
|
||||
LOCAL myISR *isrFetch(unsigned vectorNumber);
|
||||
LOCAL long blockFind(
|
||||
epicsAddressType addrType,
|
||||
void *pBlockFirst,
|
||||
void *pBlockLast,
|
||||
char *pBlockFirst,
|
||||
char *pBlockLast,
|
||||
/* size needed */
|
||||
unsigned long size,
|
||||
/* n ls bits zero in base addr */
|
||||
unsigned alignment,
|
||||
/* base address found */
|
||||
void **ppBase);
|
||||
char **ppBase);
|
||||
LOCAL long report_conflict(
|
||||
epicsAddressType addrType,
|
||||
void *pFirst,
|
||||
void *pLast,
|
||||
char *pFirst,
|
||||
char *pLast,
|
||||
const char *pOwnerName);
|
||||
LOCAL long devInsertAddress(
|
||||
LIST *pRangeList,
|
||||
@@ -140,25 +142,25 @@ LOCAL long devInstallAddr(
|
||||
rangeItem *pRange,
|
||||
const char *pOwnerName,
|
||||
epicsAddressType addrType,
|
||||
void *pFirst,
|
||||
void *pLast,
|
||||
char *pFirst,
|
||||
char *pLast,
|
||||
void **pLocalAddress);
|
||||
LOCAL long blockDivide(
|
||||
epicsAddressType addrType,
|
||||
void *pBlockFirst,
|
||||
void *pBlockLast,
|
||||
char *pBlockFirst,
|
||||
char *pBlockLast,
|
||||
/* base address found */
|
||||
void **ppBase,
|
||||
char **ppBase,
|
||||
unsigned long requestSize
|
||||
);
|
||||
LOCAL long blockProbe(
|
||||
epicsAddressType addrType,
|
||||
void *pFirst,
|
||||
void *pLast
|
||||
char *pFirst,
|
||||
char *pLast
|
||||
);
|
||||
long locationProbe(
|
||||
epicsAddressType addrType,
|
||||
void *pLocation
|
||||
char *pLocation
|
||||
);
|
||||
|
||||
/*
|
||||
@@ -336,8 +338,8 @@ void *baseAddress,
|
||||
unsigned long size,
|
||||
void **pLocalAddress)
|
||||
{
|
||||
void *pFirst;
|
||||
void *pLast;
|
||||
char *pFirst;
|
||||
char *pLast;
|
||||
rangeItem *pRange;
|
||||
long s;
|
||||
|
||||
@@ -357,7 +359,7 @@ void **pLocalAddress)
|
||||
return S_dev_lowValue;
|
||||
}
|
||||
|
||||
pFirst = baseAddress;
|
||||
pFirst = (char *) baseAddress;
|
||||
pLast = pFirst + size - 1;
|
||||
|
||||
FASTLOCK(&addrListLock);
|
||||
@@ -407,25 +409,26 @@ LOCAL long devInstallAddr(
|
||||
rangeItem *pRange, /* item on the free list to be split */
|
||||
const char *pOwnerName,
|
||||
epicsAddressType addrType,
|
||||
void *pFirst,
|
||||
void *pLast,
|
||||
void **pLocalAddress)
|
||||
char *pFirst,
|
||||
char *pLast,
|
||||
void **ppLocalAddress)
|
||||
{
|
||||
rangeItem *pNewRange;
|
||||
int s;
|
||||
|
||||
if(pLocalAddress){
|
||||
int s1;
|
||||
int s2;
|
||||
if(ppLocalAddress){
|
||||
char *pAddr;
|
||||
int s1;
|
||||
int s2;
|
||||
|
||||
s1 = sysBusToLocalAdrs(
|
||||
EPICStovxWorksAddrType[addrType],
|
||||
pLast,
|
||||
(char **)pLocalAddress);
|
||||
&pAddr);
|
||||
s2 = sysBusToLocalAdrs(
|
||||
EPICStovxWorksAddrType[addrType],
|
||||
pFirst,
|
||||
(char **)pLocalAddress);
|
||||
&pAddr);
|
||||
if(s1 || s2){
|
||||
errPrintf(
|
||||
S_dev_vxWorksAddrMapFail,
|
||||
@@ -437,6 +440,8 @@ void **pLocalAddress)
|
||||
pLast-pFirst+1);
|
||||
return S_dev_vxWorksAddrMapFail;
|
||||
}
|
||||
|
||||
*ppLocalAddress = (void *) pAddr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -505,8 +510,8 @@ void **pLocalAddress)
|
||||
*/
|
||||
LOCAL long report_conflict(
|
||||
epicsAddressType addrType,
|
||||
void *pFirst,
|
||||
void *pLast,
|
||||
char *pFirst,
|
||||
char *pLast,
|
||||
const char *pOwnerName
|
||||
)
|
||||
{
|
||||
@@ -567,6 +572,7 @@ epicsAddressType addrType,
|
||||
void *baseAddress,
|
||||
const char *pOwnerName)
|
||||
{
|
||||
char *charAddress = (char *) baseAddress;
|
||||
rangeItem *pRange;
|
||||
int s;
|
||||
|
||||
@@ -577,7 +583,7 @@ const char *pOwnerName)
|
||||
}
|
||||
}
|
||||
|
||||
s = addrVerify(addrType, baseAddress);
|
||||
s = addrVerify(addrType, charAddress);
|
||||
if(s != SUCCESS){
|
||||
return s;
|
||||
}
|
||||
@@ -585,10 +591,10 @@ const char *pOwnerName)
|
||||
FASTLOCK(&addrListLock);
|
||||
pRange = (rangeItem *) addrAlloc[addrType].node.next;
|
||||
while(pRange){
|
||||
if(pRange->pFirst == baseAddress){
|
||||
if(pRange->pFirst == charAddress){
|
||||
break;
|
||||
}
|
||||
if(pRange->pFirst > baseAddress){
|
||||
if(pRange->pFirst > charAddress){
|
||||
pRange = NULL;
|
||||
break;
|
||||
}
|
||||
@@ -608,7 +614,7 @@ const char *pOwnerName)
|
||||
__LINE__,
|
||||
"unregister address for %s at 0X %X failed because %s owns it",
|
||||
pOwnerName,
|
||||
baseAddress,
|
||||
charAddress,
|
||||
pRange->pOwnerName);
|
||||
return s;
|
||||
}
|
||||
@@ -730,7 +736,7 @@ void **pLocalAddress)
|
||||
{
|
||||
int s;
|
||||
rangeItem *pRange;
|
||||
void *pBase;
|
||||
char *pBase;
|
||||
|
||||
s = addrVerify(addrType, (void *)size);
|
||||
if(s){
|
||||
@@ -745,9 +751,6 @@ void **pLocalAddress)
|
||||
pRange = (rangeItem *) addrFree[addrType].node.next;
|
||||
while(pRange){
|
||||
if(pRange->pLast-pRange->pFirst>=size-1){
|
||||
void *pF;
|
||||
void *pL;
|
||||
|
||||
s = blockFind(
|
||||
addrType,
|
||||
pRange->pFirst,
|
||||
@@ -875,9 +878,11 @@ LOCAL long devListAddressMap(LIST *pRangeList)
|
||||
printf("%s Address Map\n", epicsAddressTypeName[i]);
|
||||
}
|
||||
while(pri){
|
||||
printf("0X %08X - %08X %s\n",
|
||||
pri->pFirst,
|
||||
pri->pLast,
|
||||
printf("0X %0*lX - %0*lX %s\n",
|
||||
(int) (sizeof (pri->pFirst) * 2U),
|
||||
(unsigned long) pri->pFirst,
|
||||
(int) (sizeof (pri->pFirst) * 2U),
|
||||
(unsigned long) pri->pLast,
|
||||
pri->pOwnerName);
|
||||
pri = (rangeItem *) lstNext(&pri->node);
|
||||
}
|
||||
@@ -923,9 +928,9 @@ void unsolicitedHandlerEPICS(int vectorNumber)
|
||||
LOCAL
|
||||
void initHandlerAddrList(void)
|
||||
{
|
||||
int i;
|
||||
UINT8 type;
|
||||
int status;
|
||||
int i;
|
||||
SYM_TYPE type;
|
||||
int status;
|
||||
|
||||
for(i=0; i<NELEMENTS(defaultHandlerNames); i++){
|
||||
status =
|
||||
@@ -951,18 +956,17 @@ void initHandlerAddrList(void)
|
||||
*
|
||||
*
|
||||
*/
|
||||
LOCAL
|
||||
void (*isrFetch(unsigned vectorNumber))()
|
||||
LOCAL myISR *isrFetch(unsigned vectorNumber)
|
||||
{
|
||||
void (*psub)();
|
||||
void (*pCISR)();
|
||||
myISR *psub;
|
||||
myISR *pCISR;
|
||||
void *pParam;
|
||||
int s;
|
||||
|
||||
/*
|
||||
* fetch the handler or C stub attached at this vector
|
||||
*/
|
||||
psub = (void (*)()) intVecGet((FUNCPTR *)INUM_TO_IVEC(vectorNumber));
|
||||
psub = (myISR *) intVecGet((FUNCPTR *)INUM_TO_IVEC(vectorNumber));
|
||||
|
||||
/*
|
||||
* from libvxWorks/veclist.c
|
||||
@@ -993,7 +997,7 @@ unsigned vectorNumber
|
||||
{
|
||||
static int init;
|
||||
int i;
|
||||
void (*psub)();
|
||||
myISR *psub;
|
||||
|
||||
if(!init){
|
||||
initHandlerAddrList();
|
||||
@@ -1026,11 +1030,11 @@ unsigned vectorNumber
|
||||
*/
|
||||
LOCAL long blockFind(
|
||||
epicsAddressType addrType,
|
||||
void *pBlockFirst,
|
||||
void *pBlockLast,
|
||||
char *pBlockFirst,
|
||||
char *pBlockLast,
|
||||
unsigned long size, /* size needed */
|
||||
unsigned alignment, /* n ls bits zero in base addr */
|
||||
void **ppBase /* base address found */
|
||||
char **ppBase /* base address found */
|
||||
)
|
||||
{
|
||||
int s;
|
||||
@@ -1041,7 +1045,7 @@ void **ppBase /* base address found */
|
||||
*/
|
||||
mask = devCreateMask(alignment);
|
||||
if(mask&(long)pBlockFirst){
|
||||
pBlockFirst = (void *) (mask | (unsigned long) pBlockFirst);
|
||||
pBlockFirst = (char *) (mask | (unsigned long) pBlockFirst);
|
||||
pBlockFirst++;
|
||||
}
|
||||
|
||||
@@ -1088,17 +1092,17 @@ void **ppBase /* base address found */
|
||||
*/
|
||||
LOCAL long blockDivide(
|
||||
epicsAddressType addrType,
|
||||
void *pBlockFirst,
|
||||
void *pBlockLast,
|
||||
void **ppBase, /* base address found */
|
||||
char *pBlockFirst,
|
||||
char *pBlockLast,
|
||||
char **ppBase, /* base address found */
|
||||
unsigned long requestSize
|
||||
)
|
||||
{
|
||||
void *pBlock;
|
||||
char *pBlock;
|
||||
unsigned long bs;
|
||||
int s;
|
||||
|
||||
s = blockProbe(addrType,pBlockFirst, pBlockFirst+(requestSize-1));
|
||||
s = blockProbe(addrType, pBlockFirst, pBlockFirst+(requestSize-1));
|
||||
if(!s){
|
||||
*ppBase = pBlockFirst;
|
||||
return SUCCESS;
|
||||
@@ -1137,11 +1141,11 @@ unsigned long requestSize
|
||||
*/
|
||||
LOCAL long blockProbe(
|
||||
epicsAddressType addrType,
|
||||
void *pFirst,
|
||||
void *pLast
|
||||
char *pFirst,
|
||||
char *pLast
|
||||
)
|
||||
{
|
||||
void *pProbe;
|
||||
char *pProbe;
|
||||
int s;
|
||||
|
||||
pProbe = pFirst;
|
||||
@@ -1161,10 +1165,10 @@ void *pLast
|
||||
*/
|
||||
long locationProbe(
|
||||
epicsAddressType addrType,
|
||||
void *pLocation
|
||||
char *pLocation
|
||||
)
|
||||
{
|
||||
void *pPhysical;
|
||||
char *pPhysical;
|
||||
int s;
|
||||
|
||||
/*
|
||||
@@ -1174,33 +1178,33 @@ void *pLocation
|
||||
s = sysBusToLocalAdrs(
|
||||
EPICStovxWorksAddrType[addrType],
|
||||
pLocation,
|
||||
(char **)&pPhysical);
|
||||
&pPhysical);
|
||||
if(s<0){
|
||||
return S_dev_vxWorksAddrMapFail;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
char *pChar;
|
||||
char byte;
|
||||
int8_t *pChar;
|
||||
int8_t byte;
|
||||
|
||||
pChar = pPhysical;
|
||||
pChar = (int8_t *) pPhysical;
|
||||
if(devPtrAlignTest(pChar)){
|
||||
s = vxMemProbe(
|
||||
pChar,
|
||||
(char *) pChar,
|
||||
READ,
|
||||
sizeof(byte),
|
||||
&byte);
|
||||
(char *) &byte);
|
||||
if(s!=ERROR){
|
||||
return S_dev_addressOverlap;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
short *pWord;
|
||||
short word;
|
||||
int16_t *pWord;
|
||||
int16_t word;
|
||||
|
||||
pWord = pPhysical;
|
||||
pWord = (int16_t *)pPhysical;
|
||||
if(devPtrAlignTest(pWord)){
|
||||
s = vxMemProbe(
|
||||
(char *)pWord,
|
||||
@@ -1213,10 +1217,10 @@ void *pLocation
|
||||
}
|
||||
}
|
||||
{
|
||||
long *pLongWord;
|
||||
long longWord;
|
||||
int32_t *pLongWord;
|
||||
int32_t longWord;
|
||||
|
||||
pLongWord = pPhysical;
|
||||
pLongWord = (int32_t *) pPhysical;
|
||||
if(devPtrAlignTest(pLongWord)){
|
||||
s = vxMemProbe(
|
||||
(char *)pLongWord,
|
||||
|
||||
@@ -61,13 +61,13 @@
|
||||
* .31 02-10-95 joh static => LOCAL
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <sysLib.h>
|
||||
#include <symLib.h>
|
||||
#include <sysSymTbl.h> /* for sysSymTbl*/
|
||||
|
||||
@@ -109,7 +109,6 @@ void recGblRecordError(long status,void *pdbc,char *pcaller_name)
|
||||
strcat(buffer," ");
|
||||
}
|
||||
if(pcaller_name) {
|
||||
strcat(buffer,"error detected in routine: ");
|
||||
strcat(buffer,pcaller_name);
|
||||
}
|
||||
errMessage(status,buffer);
|
||||
|
||||
@@ -79,45 +79,14 @@ extern struct dbBase *pdbBase;
|
||||
%%
|
||||
|
||||
database: DATABASE d_head d_body
|
||||
{
|
||||
#ifdef vxWorks
|
||||
dbFreeEntry(pdbentry);
|
||||
#endif
|
||||
}
|
||||
| DATABASE d_head /* jbk added for graphical thing */
|
||||
{
|
||||
#ifdef vxWorks
|
||||
dbFreeEntry(pdbentry);
|
||||
#endif
|
||||
}
|
||||
| db_components
|
||||
;
|
||||
|
||||
d_head: O_PAREN WORD C_PAREN
|
||||
{
|
||||
#ifdef vxWorks
|
||||
/*
|
||||
fprintf(stderr,"Warning: No EPICS version information in db file\n");
|
||||
*/
|
||||
pdbentry=dbAllocEntry(pdbBase);
|
||||
free($2);
|
||||
#endif
|
||||
}
|
||||
{ free($2); }
|
||||
| O_PAREN WORD COMMA VALUE C_PAREN
|
||||
{
|
||||
#ifdef vxWorks
|
||||
int version,revision;
|
||||
char* v;
|
||||
|
||||
v=strtok($4," ."); sscanf(v,"%d",&version);
|
||||
v=strtok(NULL," ."); sscanf(v,"%d",&revision);
|
||||
|
||||
if(version!=EPICS_VERSION || revision!=EPICS_REVISION)
|
||||
fprintf(stderr,"Warning: Database not created with same version\n");
|
||||
|
||||
pdbentry=dbAllocEntry(pdbBase);
|
||||
free($2); free($4);
|
||||
#endif
|
||||
}
|
||||
{ free($2); free($4); }
|
||||
;
|
||||
|
||||
d_body: O_BRACE nowhere_records db_components C_BRACE
|
||||
@@ -144,9 +113,7 @@ container: CONTAINER c_head c_body
|
||||
;
|
||||
|
||||
c_head: O_PAREN WORD C_PAREN
|
||||
{
|
||||
free($2);
|
||||
}
|
||||
{ free($2); }
|
||||
;
|
||||
|
||||
c_body: O_BRACE db_components C_BRACE
|
||||
@@ -159,7 +126,7 @@ records: /* null */
|
||||
record: RECORD r_head r_body
|
||||
{
|
||||
#ifndef vxWorks
|
||||
printf(" }\n");
|
||||
printf("}\n");
|
||||
#endif
|
||||
}
|
||||
;
|
||||
@@ -253,32 +220,24 @@ int dbLoadRecords(char* pfilename, char* pattern, char* container)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef vxWorks
|
||||
/* if(container) printf(" %s {\n",container); */
|
||||
#endif
|
||||
|
||||
if(is_not_inited)
|
||||
{
|
||||
#ifdef ERROR_STUFF
|
||||
fprintf(stderr,"initing parser\n");
|
||||
#endif
|
||||
yyin=fp;
|
||||
is_not_inited=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ERROR_STUFF
|
||||
fprintf(stderr,"restarting parser\n");
|
||||
#endif
|
||||
yyrestart(fp);
|
||||
}
|
||||
#ifdef ERROR_STUFF
|
||||
fprintf(stderr,"before parser startup\n");
|
||||
|
||||
#ifdef vxWorks
|
||||
pdbentry=dbAllocEntry(pdbBase);
|
||||
#endif
|
||||
|
||||
yyparse();
|
||||
|
||||
#ifndef vxWorks
|
||||
/* if(container) printf(" }\n"); */
|
||||
#ifdef vxWorks
|
||||
dbFreeEntry(pdbentry);
|
||||
#endif
|
||||
|
||||
if(subst_used) dbFreeSubst();
|
||||
@@ -303,7 +262,7 @@ static void sub_pvname(char* type, char* name)
|
||||
if( dbCreateRecord(pdbentry,subst_buffer) )
|
||||
fprintf(stderr,"Cannot create record %s\n",subst_buffer);
|
||||
#else
|
||||
printf("\trecord(%s, \"%s\") {",type,subst_buffer);
|
||||
printf("record(%s,\"%s\") {",type,subst_buffer);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -312,7 +271,7 @@ static void sub_pvname(char* type, char* name)
|
||||
if( dbCreateRecord(pdbentry,name) )
|
||||
fprintf(stderr,"Cannot create record %s\n",name);
|
||||
#else
|
||||
printf("\trecord(%s, \"%s\") {",type,name);
|
||||
printf("record(%s,\"%s\") {",type,name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
pvname [a-zA-Z0-9_\-:\.\[\]<>]
|
||||
pvname [a-zA-Z0-9_\-:\.\[\]<>;]
|
||||
value [a-zA-Z0-9_\,\^~\./\*#\[\]%: ;!|\'\-&\(\)@\?\+<>=\$\{\}]
|
||||
|
||||
%{
|
||||
@@ -7,7 +7,10 @@ value [a-zA-Z0-9_\,\^~\./\*#\[\]%: ;!|\'\-&\(\)@\?\+<>=\$\{\}]
|
||||
|
||||
%%
|
||||
|
||||
\#.*\n ;
|
||||
|
||||
"field" { return(FIELD); }
|
||||
"grecord" { return(RECORD); }
|
||||
"record" { return(RECORD); }
|
||||
"container" { return(CONTAINER); }
|
||||
"database" { return(DATABASE); }
|
||||
|
||||
@@ -89,6 +89,17 @@ templs: templs templ
|
||||
;
|
||||
|
||||
templ: templ_head O_BRACE subst C_BRACE
|
||||
| templ_head
|
||||
{
|
||||
#ifndef SUB_TOOL
|
||||
if(db_file_name)
|
||||
dbLoadRecords(db_file_name,NULL,NULL);
|
||||
else
|
||||
fprintf(stderr,"Error: no db file name given\n");
|
||||
#else
|
||||
sub_it();
|
||||
#endif
|
||||
}
|
||||
;
|
||||
|
||||
templ_head: DBFILE WORD
|
||||
@@ -118,9 +129,7 @@ vars: vars var
|
||||
;
|
||||
|
||||
var: WORD
|
||||
{
|
||||
vars[var_count++]=$1;
|
||||
}
|
||||
{ vars[var_count++]=$1; }
|
||||
;
|
||||
|
||||
subs: subs sub
|
||||
@@ -335,7 +344,7 @@ main(int argc, char** argv)
|
||||
}
|
||||
|
||||
/* use sub_collect and db_file_name to do work */
|
||||
int sub_it()
|
||||
static int sub_it()
|
||||
{
|
||||
FILE* fp;
|
||||
char var_buff[500];
|
||||
@@ -415,9 +424,7 @@ main(int argc, char** argv)
|
||||
|
||||
if(!name) name = "Composite";
|
||||
|
||||
printf("database(name,\"%d.%d\") {\n",EPICS_VERSION,EPICS_REVISION,name);
|
||||
dbLoadTemplate(argv[1]);
|
||||
printf("}\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,8 @@ par [\"\']
|
||||
|
||||
%%
|
||||
|
||||
\#.*\n ;
|
||||
|
||||
"pattern" { return(PATTERN); }
|
||||
"file" { return(DBFILE); }
|
||||
"=" { return(EQUALS); }
|
||||
@@ -16,8 +18,6 @@ par [\"\']
|
||||
|
||||
{word}+ { yylval.Str=(char *)malloc(strlen(yytext)+1); strcpy(yylval.Str,yytext); return(WORD); }
|
||||
|
||||
"(" { return(O_PAREN); }
|
||||
")" { return(C_PAREN); }
|
||||
"{" { return(O_BRACE); }
|
||||
"}" { return(C_BRACE); }
|
||||
|
||||
|
||||
@@ -2,195 +2,210 @@ EPICS = ../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_INCLUDES = -I../../drv
|
||||
USR_INCLUDES = -I../../drv/ansi -I../../drv/old
|
||||
|
||||
SRCS.c = \
|
||||
../devAiDvx2502.c\
|
||||
../devAiSoft.c\
|
||||
../devAiSoftRaw.c\
|
||||
../devAiSymb.c\
|
||||
../devAiTestAsyn.c\
|
||||
../devAiXy566Di.c\
|
||||
../devAiXy566DiL.c\
|
||||
../devAiXy566Se.c\
|
||||
../devAoSoft.c\
|
||||
../devApsEg.c\
|
||||
../devApsEr.c\
|
||||
../devAoSoftRaw.c\
|
||||
../devAoSymb.c\
|
||||
../devAoTestAsyn.c\
|
||||
../devAoVmiVme4100.c\
|
||||
../devBiMpv910.c\
|
||||
../devBiSoft.c\
|
||||
../devBiSoftRaw.c\
|
||||
../devBiTestAsyn.c\
|
||||
../devBiXVme210.c\
|
||||
../devBoMpv902.c\
|
||||
../devBoSoft.c\
|
||||
../devBoSoftRaw.c\
|
||||
../devBoTestAsyn.c\
|
||||
../devBoXVme220.c\
|
||||
../devCommonGpib.c\
|
||||
../devEventSoft.c\
|
||||
../devEventTestIoEvent.c\
|
||||
../devHistogramSoft.c\
|
||||
../devHistogramTestAsyn.c\
|
||||
../devLiSoft.c\
|
||||
../devLiSymb.c\
|
||||
../devLoSoft.c\
|
||||
../devLoSymb.c\
|
||||
../devMbbiMpv910.c\
|
||||
../devMbbiSoft.c\
|
||||
../devMbbiSoftRaw.c\
|
||||
../devMbbiTestAsyn.c\
|
||||
../devMbbiXVme210.c\
|
||||
../devMbboMpv902.c\
|
||||
../devMbboSoft.c\
|
||||
../devMbboSoftRaw.c\
|
||||
../devMbboTestAsyn.c\
|
||||
../devMbboXVme220.c\
|
||||
../devMbbiDirectMpv910.c\
|
||||
../devMbbiDirectSoft.c\
|
||||
../devMbbiDirectSoftRaw.c\
|
||||
../devMbbiDirectXVme210.c\
|
||||
../devMbboDirectMpv902.c\
|
||||
../devMbboDirectSoft.c\
|
||||
../devMbboDirectSoftRaw.c\
|
||||
../devMbboDirectXVme220.c\
|
||||
../devPtSoft.c\
|
||||
../devSmCompumotor1830.c\
|
||||
../devSmOms6Axis.c\
|
||||
../devSiSoft.c\
|
||||
../devSiSymb.c\
|
||||
../devSiTestAsyn.c\
|
||||
../devSoSoft.c\
|
||||
../devSASoft.c\
|
||||
../devSoSymb.c\
|
||||
../devSoTestAsyn.c\
|
||||
../devWfSoft.c\
|
||||
../devWfTestAsyn.c\
|
||||
../devWfXy566Sc.c\
|
||||
../devAllenBradley.c\
|
||||
../devAt5Vxi.c\
|
||||
../devMz8310.c\
|
||||
../devTimerMz8310.c\
|
||||
../devVxiTDM.c\
|
||||
../devAiKscV215.c\
|
||||
../devXy240.c\
|
||||
../devHpe1368a.c\
|
||||
../devAt8Fp.c\
|
||||
../devWfComet.c\
|
||||
../devWfDvx2502.c\
|
||||
../devWfJoergerVtr1.c\
|
||||
../devAvme9440.c\
|
||||
../devSysmon.c
|
||||
# ../devAiCamac.c\
|
||||
# ../devAaiCamac.c\
|
||||
# ../devBiCamac.c\
|
||||
# ../devLiCamac.c\
|
||||
# ../devMbbiCamac.c\
|
||||
# ../devMbbiDirectCamac.c\
|
||||
# ../devWfCamac.c\
|
||||
# ../devAoCamac.c\
|
||||
# ../devAaoCamac.c\
|
||||
# ../devBoCamac.c\
|
||||
# ../devLoCamac.c\
|
||||
# ../devMbboCamac.c\
|
||||
# ../devMbboDirectCamac.c
|
||||
# SRCS.c += ../devAaiCamac.c
|
||||
# SRCS.c += ../devAiCamac.c
|
||||
SRCS.c += ../devAiDvx2502.c
|
||||
SRCS.c += ../devAiKscV215.c
|
||||
SRCS.c += ../devAiSoft.c
|
||||
SRCS.c += ../devAiSoftRaw.c
|
||||
SRCS.c += ../devAiSymb.c
|
||||
SRCS.c += ../devAiTestAsyn.c
|
||||
SRCS.c += ../devAiXy566Di.c
|
||||
SRCS.c += ../devAiXy566DiL.c
|
||||
SRCS.c += ../devAiXy566Se.c
|
||||
# SRCS.c += ../devAaoCamac.c
|
||||
# SRCS.c += ../devAoCamac.c
|
||||
SRCS.c += ../devAoSoft.c
|
||||
SRCS.c += ../devAoSoftRaw.c
|
||||
SRCS.c += ../devAoSymb.c
|
||||
SRCS.c += ../devAoTestAsyn.c
|
||||
SRCS.c += ../devAoVmiVme4100.c
|
||||
SRCS.c += ../devApsEg.c
|
||||
SRCS.c += ../devApsEr.c
|
||||
SRCS.c += ../devAt5Vxi.c
|
||||
SRCS.c += ../devAt8Fp.c
|
||||
SRCS.c += ../devAvme9440.c
|
||||
# SRCS.c += ../devBiCamac.c
|
||||
SRCS.c += ../devBiMpv910.c
|
||||
SRCS.c += ../devBiSoft.c
|
||||
SRCS.c += ../devBiSoftRaw.c
|
||||
SRCS.c += ../devBiTestAsyn.c
|
||||
SRCS.c += ../devBiXVme210.c
|
||||
# SRCS.c += ../devBoCamac.c
|
||||
SRCS.c += ../devBoMpv902.c
|
||||
SRCS.c += ../devBoSoft.c
|
||||
SRCS.c += ../devBoSoftRaw.c
|
||||
SRCS.c += ../devBoTestAsyn.c
|
||||
SRCS.c += ../devBoXVme220.c
|
||||
SRCS.c += ../devCommonGpib.c
|
||||
SRCS.c += ../devEventSoft.c
|
||||
SRCS.c += ../devEventTestIoEvent.c
|
||||
SRCS.c += ../devHistogramSoft.c
|
||||
SRCS.c += ../devHistogramTestAsyn.c
|
||||
SRCS.c += ../devHpe1368a.c
|
||||
# OBJS += devLiCamac.c
|
||||
SRCS.c += ../devLiSoft.c
|
||||
SRCS.c += ../devLiSymb.c
|
||||
# OBJS += devLoCamac.c
|
||||
SRCS.c += ../devLoSoft.c
|
||||
SRCS.c += ../devLoSymb.c
|
||||
# SRCS.c += ../devMbbiCamac.c
|
||||
# SRCS.c += ../devMbbiDirectCamac.c
|
||||
SRCS.c += ../devMbbiDirectMpv910.c
|
||||
SRCS.c += ../devMbbiDirectSoft.c
|
||||
SRCS.c += ../devMbbiDirectSoftRaw.c
|
||||
SRCS.c += ../devMbbiDirectXVme210.c
|
||||
SRCS.c += ../devMbbiMpv910.c
|
||||
SRCS.c += ../devMbbiSoft.c
|
||||
SRCS.c += ../devMbbiSoftRaw.c
|
||||
SRCS.c += ../devMbbiTestAsyn.c
|
||||
SRCS.c += ../devMbbiXVme210.c
|
||||
# SRCS.c += ../devMbboCamac.c
|
||||
# SRCS.c += ../devMbboDirectCamac.c
|
||||
SRCS.c += ../devMbboDirectMpv902.c
|
||||
SRCS.c += ../devMbboDirectSoft.c
|
||||
SRCS.c += ../devMbboDirectSoftRaw.c
|
||||
SRCS.c += ../devMbboDirectXVme220.c
|
||||
SRCS.c += ../devMbboMpv902.c
|
||||
SRCS.c += ../devMbboSoft.c
|
||||
SRCS.c += ../devMbboSoftRaw.c
|
||||
SRCS.c += ../devMbboTestAsyn.c
|
||||
SRCS.c += ../devMbboXVme220.c
|
||||
SRCS.c += ../devMz8310.c
|
||||
SRCS.c += ../devPtSoft.c
|
||||
SRCS.c += ../devSASoft.c
|
||||
SRCS.c += ../devSiSoft.c
|
||||
SRCS.c += ../devSiSymb.c
|
||||
SRCS.c += ../devSiTestAsyn.c
|
||||
SRCS.c += ../devSmCompumotor1830.c
|
||||
SRCS.c += ../devSmOms6Axis.c
|
||||
SRCS.c += ../devSoSoft.c
|
||||
SRCS.c += ../devSoSymb.c
|
||||
SRCS.c += ../devSoTestAsyn.c
|
||||
SRCS.c += ../devSysmon.c
|
||||
SRCS.c += ../devTimerMz8310.c
|
||||
SRCS.c += ../devVxiTDM.c
|
||||
# SRCS.c += ../devWfCamac.c
|
||||
SRCS.c += ../devWfComet.c
|
||||
SRCS.c += ../devWfDvx2502.c
|
||||
SRCS.c += ../devWfJoergerVtr1.c
|
||||
SRCS.c += ../devWfSoft.c
|
||||
SRCS.c += ../devWfTestAsyn.c
|
||||
SRCS.c += ../devWfXy566Sc.c
|
||||
SRCS.c += ../devWfPentek4261.c
|
||||
SRCS.c += ../devXy240.c
|
||||
|
||||
OBJS = \
|
||||
devAiDvx2502.o\
|
||||
devAiSoft.o\
|
||||
devAiSoftRaw.o\
|
||||
devAiSymb.o\
|
||||
devAiTestAsyn.o\
|
||||
devAiXy566Di.o\
|
||||
devAiXy566DiL.o\
|
||||
devAiXy566Se.o\
|
||||
devAoSoft.o\
|
||||
devAoSoftRaw.o\
|
||||
devAoSymb.o\
|
||||
devAoTestAsyn.o\
|
||||
devAoVmiVme4100.o\
|
||||
devBiMpv910.o\
|
||||
devApsEg.o\
|
||||
devApsEr.o\
|
||||
devBiSoft.o\
|
||||
devBiSoftRaw.o\
|
||||
devBiTestAsyn.o\
|
||||
devBiXVme210.o\
|
||||
devBoMpv902.o\
|
||||
devBoSoft.o\
|
||||
devBoSoftRaw.o\
|
||||
devBoTestAsyn.o\
|
||||
devBoXVme220.o\
|
||||
devCommonGpib.o\
|
||||
devEventSoft.o\
|
||||
devEventTestIoEvent.o\
|
||||
devHistogramSoft.o\
|
||||
devHistogramTestAsyn.o\
|
||||
devLiSoft.o\
|
||||
devLiSymb.o\
|
||||
devLoSoft.o\
|
||||
devLoSymb.o\
|
||||
devMbbiMpv910.o\
|
||||
devMbbiSoft.o\
|
||||
devMbbiSoftRaw.o\
|
||||
devMbbiTestAsyn.o\
|
||||
devMbbiXVme210.o\
|
||||
devMbboMpv902.o\
|
||||
devMbboSoft.o\
|
||||
devMbboSoftRaw.o\
|
||||
devMbboTestAsyn.o\
|
||||
devMbboXVme220.o\
|
||||
devMbbiDirectMpv910.o\
|
||||
devMbbiDirectSoft.o\
|
||||
devMbbiDirectSoftRaw.o\
|
||||
devMbbiDirectXVme210.o\
|
||||
devMbboDirectMpv902.o\
|
||||
devMbboDirectSoft.o\
|
||||
devMbboDirectSoftRaw.o\
|
||||
devMbboDirectXVme220.o\
|
||||
devPtSoft.o\
|
||||
devSmCompumotor1830.o\
|
||||
devSmOms6Axis.o\
|
||||
devSASoft.o\
|
||||
devSiSoft.o\
|
||||
devSiSymb.o\
|
||||
devSiTestAsyn.o\
|
||||
devSoSoft.o\
|
||||
devSoSymb.o\
|
||||
devSoTestAsyn.o\
|
||||
devWfSoft.o\
|
||||
devWfTestAsyn.o\
|
||||
devWfXy566Sc.o\
|
||||
devAllenBradley.o\
|
||||
devAt5Vxi.o\
|
||||
devMz8310.o\
|
||||
devTimerMz8310.o\
|
||||
devVxiTDM.o\
|
||||
devAiKscV215.o\
|
||||
devXy240.o\
|
||||
devHpe1368a.o\
|
||||
devAt8Fp.o\
|
||||
devWfComet.o\
|
||||
devWfDvx2502.o\
|
||||
devWfJoergerVtr1.o\
|
||||
devAvme9440.o\
|
||||
devSysmon.o
|
||||
# devAiCamac.o\
|
||||
# devAaiCamac.o\
|
||||
# devBiCamac.o\
|
||||
# devLiCamac.o\
|
||||
# devMbbiCamac.o\
|
||||
# devMbbiDirectCamac.o\
|
||||
# devWfCamac.o\
|
||||
# devAoCamac.o\
|
||||
# devAaoCamac.o\
|
||||
# devBoCamac.o\
|
||||
# devLoCamac.o\
|
||||
# devMbboCamac.o\
|
||||
# devMbboDirectCamac.o
|
||||
SRCS.c += ../devAB1771IFE.c
|
||||
SRCS.c += ../devAB1771IL.c
|
||||
SRCS.c += ../devAB1771IR.c
|
||||
SRCS.c += ../devAB1771IXE.c
|
||||
SRCS.c += ../devAB1771OFE.c
|
||||
SRCS.c += ../devABBINARY.c
|
||||
SRCS.c += ../devABStatus.c
|
||||
SRCS.c += ../devMpc.c
|
||||
|
||||
# OBJS += devAaiCamac.o
|
||||
# OBJS += devAiCamac.o
|
||||
OBJS += devAiDvx2502.o
|
||||
OBJS += devAiKscV215.o
|
||||
OBJS += devAiSoft.o
|
||||
OBJS += devAiSoftRaw.o
|
||||
OBJS += devAiSymb.o
|
||||
OBJS += devAiTestAsyn.o
|
||||
OBJS += devAiXy566Di.o
|
||||
OBJS += devAiXy566DiL.o
|
||||
OBJS += devAiXy566Se.o
|
||||
# OBJS += devAaoCamac.o
|
||||
# OBJS += devAoCamac.o
|
||||
OBJS += devAoSoft.o
|
||||
OBJS += devAoSoftRaw.o
|
||||
OBJS += devAoSymb.o
|
||||
OBJS += devAoTestAsyn.o
|
||||
OBJS += devAoVmiVme4100.o
|
||||
OBJS += devApsEg.o
|
||||
OBJS += devApsEr.o
|
||||
OBJS += devAt5Vxi.o
|
||||
OBJS += devAt8Fp.o
|
||||
OBJS += devAvme9440.o
|
||||
# OBJS += devBiCamac.o
|
||||
OBJS += devBiMpv910.o
|
||||
OBJS += devBiSoft.o
|
||||
OBJS += devBiSoftRaw.o
|
||||
OBJS += devBiTestAsyn.o
|
||||
OBJS += devBiXVme210.o
|
||||
# OBJS += devBoCamac.o
|
||||
OBJS += devBoMpv902.o
|
||||
OBJS += devBoSoft.o
|
||||
OBJS += devBoSoftRaw.o
|
||||
OBJS += devBoTestAsyn.o
|
||||
OBJS += devBoXVme220.o
|
||||
OBJS += devCommonGpib.o
|
||||
OBJS += devEventSoft.o
|
||||
OBJS += devEventTestIoEvent.o
|
||||
OBJS += devHistogramSoft.o
|
||||
OBJS += devHistogramTestAsyn.o
|
||||
OBJS += devHpe1368a.o
|
||||
# OBJS += devLiCamac.o
|
||||
OBJS += devLiSoft.o
|
||||
OBJS += devLiSymb.o
|
||||
# OBJS += devLoCamac.o
|
||||
OBJS += devLoSoft.o
|
||||
OBJS += devLoSymb.o
|
||||
# OBJS += devMbbiCamac.o
|
||||
# OBJS += devMbbiDirectCamac.o
|
||||
OBJS += devMbbiDirectMpv910.o
|
||||
OBJS += devMbbiDirectSoft.o
|
||||
OBJS += devMbbiDirectSoftRaw.o
|
||||
OBJS += devMbbiDirectXVme210.o
|
||||
OBJS += devMbbiMpv910.o
|
||||
OBJS += devMbbiSoft.o
|
||||
OBJS += devMbbiSoftRaw.o
|
||||
OBJS += devMbbiTestAsyn.o
|
||||
OBJS += devMbbiXVme210.o
|
||||
# OBJS += devMbboCamac.o
|
||||
# OBJS += devMbboDirectCamac.o
|
||||
OBJS += devMbboDirectMpv902.o
|
||||
OBJS += devMbboDirectSoft.o
|
||||
OBJS += devMbboDirectSoftRaw.o
|
||||
OBJS += devMbboDirectXVme220.o
|
||||
OBJS += devMbboMpv902.o
|
||||
OBJS += devMbboSoft.o
|
||||
OBJS += devMbboSoftRaw.o
|
||||
OBJS += devMbboTestAsyn.o
|
||||
OBJS += devMbboXVme220.o
|
||||
OBJS += devMz8310.o
|
||||
OBJS += devPtSoft.o
|
||||
OBJS += devSASoft.o
|
||||
OBJS += devSiSoft.o
|
||||
OBJS += devSiSymb.o
|
||||
OBJS += devSiTestAsyn.o
|
||||
OBJS += devSmCompumotor1830.o
|
||||
OBJS += devSmOms6Axis.o
|
||||
OBJS += devSoSoft.o
|
||||
OBJS += devSoSymb.o
|
||||
OBJS += devSoTestAsyn.o
|
||||
OBJS += devSysmon.o
|
||||
OBJS += devTimerMz8310.o
|
||||
OBJS += devVxiTDM.o
|
||||
# OBJS += devWfCamac.o
|
||||
OBJS += devWfComet.o
|
||||
OBJS += devWfDvx2502.o
|
||||
OBJS += devWfJoergerVtr1.o
|
||||
OBJS += devWfSoft.o
|
||||
OBJS += devWfTestAsyn.o
|
||||
OBJS += devWfXy566Sc.o
|
||||
OBJS += devWfPentek4261.o
|
||||
OBJS += devXy240.o
|
||||
OBJS += devAB1771IFE.o
|
||||
OBJS += devAB1771IL.o
|
||||
OBJS += devAB1771IR.o
|
||||
OBJS += devAB1771IXE.o
|
||||
OBJS += devAB1771OFE.o
|
||||
OBJS += devABBINARY.o
|
||||
OBJS += devABStatus.o
|
||||
OBJS += devMpc.o
|
||||
|
||||
PROD = devSup
|
||||
|
||||
@@ -200,3 +215,4 @@ $(PROD): $(OBJS)
|
||||
$(RM) $@
|
||||
$(LINK.c) $@ $(OBJS) $(LDLIBS)
|
||||
|
||||
|
||||
|
||||
267
src/dev/devAB1771IFE.c
Normal file
267
src/dev/devAB1771IFE.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/* devAB1771IFE.c */
|
||||
/*
|
||||
* Original Author: Bob Dalesio
|
||||
* Current Author: Bob Dalesio, Marty Kraimer
|
||||
* Date: 3/6/91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 12-01-94 lrd combine the device support that was resident
|
||||
* in the driver and device support to
|
||||
significantly reduce the amount of code
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <link.h>
|
||||
#include <drvAb.h>
|
||||
#include <aiRecord.h>
|
||||
|
||||
/* Create the dsets*/
|
||||
LOCAL long ioinfo_ai(int cmd,struct aiRecord *prec,IOSCANPVT *ppvt);
|
||||
LOCAL long init_1771IfeDiff(struct aiRecord *prec);
|
||||
LOCAL long init_1771Ife0to5V(struct aiRecord *prec);
|
||||
LOCAL long init_1771IfeMa(struct aiRecord *prec);
|
||||
LOCAL long init_1771IfeSe(struct aiRecord *prec);
|
||||
LOCAL long linconv_1771Ife(struct aiRecord *prec, int after);
|
||||
LOCAL long read_1771Ife(struct aiRecord *prec);
|
||||
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;
|
||||
DEVSUPFUN special_linconv;} ABAIDSET;
|
||||
|
||||
ABAIDSET devAiAb1771Ife={6, 0, 0, init_1771IfeDiff,
|
||||
ioinfo_ai, read_1771Ife, linconv_1771Ife};
|
||||
ABAIDSET devAiAb1771Ife0to5V={6, 0, 0, init_1771Ife0to5V,
|
||||
ioinfo_ai, read_1771Ife, linconv_1771Ife};
|
||||
ABAIDSET devAiAb1771IfeMa={6, 0, 0, init_1771IfeMa,
|
||||
ioinfo_ai, read_1771Ife, linconv_1771Ife};
|
||||
ABAIDSET devAiAb1771IfeSe={6, 0, 0, init_1771IfeSe,
|
||||
ioinfo_ai, read_1771Ife, linconv_1771Ife};
|
||||
|
||||
#define IFE_SCAN_RATE 1
|
||||
#define IFE_INITMSG_LENGTH 37
|
||||
#define IFE_DIFF_READMSG_LENGTH 12
|
||||
#define IFE_SE_READMSG_LENGTH 20
|
||||
|
||||
struct ab1771Ife_read {
|
||||
unsigned short diag; /* diagnostic word */
|
||||
unsigned short urange; /* low byte - under range channels */
|
||||
unsigned short orange; /* low byte - over range channels */
|
||||
unsigned short sign; /* low byte - polarity 1 = negative */
|
||||
short data[16]; /* 16 data values (can be signed) */
|
||||
};
|
||||
|
||||
/* IFE Differential Initialization Message - from the IFE Manual */
|
||||
LOCAL short ab1771IfeDiff_initmsg[IFE_INITMSG_LENGTH] = {
|
||||
0xffff, 0xffff, /* -10 to 10 volts (signals 0 - 15) */
|
||||
0x0700, /* signed magnitude - differential */
|
||||
0xffff, 0x0000, /* scaled 0 - 4095 (12 bits) */
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095
|
||||
};
|
||||
/* 1771 - IFE 0 to 5 Volt */
|
||||
LOCAL short ab1771Ife0to5v_initmsg[IFE_INITMSG_LENGTH] = {
|
||||
0x5555, 0x5555, /* 0 to 5 volts (signals 0 - 15) */
|
||||
0x0700, /* signed magnitude - differential */
|
||||
0x0000, 0x0000, /* scaled 0 - 4095 (12 bits) */
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095
|
||||
};
|
||||
/* 1771 - IFE MilliAmp */
|
||||
LOCAL short ab1771IfeMa_initmsg[IFE_INITMSG_LENGTH] = {
|
||||
0x0000, 0x0000, /* 4 - 20 Ma (signals 0 - 15) */
|
||||
0x0700, /* signed magnitude - differential */
|
||||
0x0000, 0x0000, /* scaled 0 - 4095 (12 bits) */
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095
|
||||
};
|
||||
/* 1771 - IFE Single Ended (-10 to 10 Volts) */
|
||||
LOCAL short ab1771IfeSe_initmsg[IFE_INITMSG_LENGTH] = {
|
||||
0xffff, 0xffff, /* 0 to 5 volts (signals 0 - 15) */
|
||||
0x0600, /* signed magnitude - differential */
|
||||
0xffff, 0x0000, /* scaled 0 - 4095 (12 bits) */
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *drvPvt;
|
||||
IOSCANPVT ioscanpvt;
|
||||
unsigned short read_msg_len;
|
||||
unsigned short *pread_msg;
|
||||
} devPvt;
|
||||
|
||||
LOCAL void devCallback(void * drvPvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
if(!pdevPvt) return;
|
||||
scanIoRequest(pdevPvt->ioscanpvt);
|
||||
}
|
||||
|
||||
LOCAL long ioinfo_ai(int cmd,struct aiRecord *prec,IOSCANPVT *ppvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)prec->dpvt;
|
||||
if(!pdevPvt) return(0);
|
||||
*ppvt = pdevPvt->ioscanpvt;
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long read_1771Ife(struct aiRecord *prec)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt= (devPvt *)prec->dpvt;
|
||||
abStatus drvStatus;
|
||||
struct ab1771Ife_read *pdata;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
drvStatus = (*pabDrv->getStatus)(pdevPvt->drvPvt);
|
||||
pdata = (struct ab1771Ife_read *)pdevPvt->pread_msg;
|
||||
if(drvStatus != abSuccess) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}
|
||||
prec->rval = pdata->data[pabio->signal];
|
||||
if( (pdata->orange & (1 << pabio->signal))
|
||||
|| (pdata->urange & (1 << pabio->signal)) )
|
||||
recGblSetSevr(prec,HW_LIMIT_ALARM,INVALID_ALARM);
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long linconv_1771Ife(struct aiRecord *prec, int after)
|
||||
{
|
||||
|
||||
if(!after) return(0);
|
||||
/* set linear conversion slope*/
|
||||
prec->eslo = (prec->eguf -prec->egul)/4095.0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long init_1771Ife(struct aiRecord *prec, const char *card_type,
|
||||
unsigned short *pinit_msg, unsigned short read_size)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
|
||||
/* ai.inp must be an AB_IO */
|
||||
if (prec->inp.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"devAiAb1771Ife (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
prec->eslo = (prec->eguf -prec->egul)/4095.0;
|
||||
/* pointer to the data addess structure */
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeAi,card_type,devCallback,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
scanIoInit(&pdevPvt->ioscanpvt);
|
||||
pdevPvt->read_msg_len = read_size;
|
||||
pdevPvt->pread_msg = calloc(read_size,sizeof(unsigned short));
|
||||
drvStatus = (*pabDrv->startScan)(drvPvt,IFE_SCAN_RATE,
|
||||
pinit_msg,IFE_INITMSG_LENGTH,pdevPvt->pread_msg ,read_size);
|
||||
if(drvStatus!=abSuccess) {
|
||||
status = S_db_badField;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"devAiAb1771Ife (init_record) startScan");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Ife (init_record) registerCard");
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL long init_1771IfeDiff(struct aiRecord *prec)
|
||||
{
|
||||
return(init_1771Ife(prec,"IFEDIFF",&ab1771IfeDiff_initmsg[0],
|
||||
IFE_DIFF_READMSG_LENGTH));
|
||||
}
|
||||
|
||||
LOCAL long init_1771Ife0to5V(struct aiRecord *prec)
|
||||
{
|
||||
return(init_1771Ife(prec,"IFE0to5V",&ab1771Ife0to5v_initmsg[0],
|
||||
IFE_DIFF_READMSG_LENGTH));
|
||||
}
|
||||
|
||||
LOCAL long init_1771IfeMa(struct aiRecord *prec)
|
||||
{
|
||||
return(init_1771Ife(prec,"IFEMA",&ab1771IfeMa_initmsg[0],
|
||||
IFE_DIFF_READMSG_LENGTH));
|
||||
}
|
||||
|
||||
LOCAL long init_1771IfeSe(struct aiRecord *prec)
|
||||
{
|
||||
return(init_1771Ife(prec,"IFESE",&ab1771IfeSe_initmsg[0],
|
||||
IFE_SE_READMSG_LENGTH));
|
||||
}
|
||||
195
src/dev/devAB1771IL.c
Normal file
195
src/dev/devAB1771IL.c
Normal file
@@ -0,0 +1,195 @@
|
||||
/* devAB1771IL.c */
|
||||
/*
|
||||
* Original Author: Bob Dalesio
|
||||
* Current Author: Bob Dalesio, Marty Kraimer
|
||||
* Date: 3/6/91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 12-01-94 lrd combine the device support that was resident
|
||||
* in the driver and device support to
|
||||
significantly reduce the amount of code
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <link.h>
|
||||
#include <drvAb.h>
|
||||
#include <aiRecord.h>
|
||||
|
||||
/* Create the dsets*/
|
||||
LOCAL long ioinfo_ai(int cmd,struct aiRecord *prec,IOSCANPVT *ppvt);
|
||||
LOCAL long init_1771Il(struct aiRecord *prec);
|
||||
LOCAL long linconv_1771Il(struct aiRecord *prec, int after);
|
||||
LOCAL long read_1771Il(struct aiRecord *prec);
|
||||
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;
|
||||
DEVSUPFUN special_linconv;} ABAIDSET;
|
||||
|
||||
ABAIDSET devAiAb1771Il={6, 0, 0, init_1771Il,
|
||||
ioinfo_ai, read_1771Il, linconv_1771Il};
|
||||
|
||||
#define IL_SCAN_RATE 4
|
||||
#define IL_INITMSG_LENGTH 19
|
||||
#define IL_READMSG_LENGTH 12
|
||||
|
||||
#define IL_RANGE 0xffff /* volt inp for all channels -10 - 10V */
|
||||
#define IL_DATA_FORMAT 0x600 /* signed magnitude binary */
|
||||
struct ab1771il_read {
|
||||
unsigned short diag; /* diagnostic word */
|
||||
unsigned short urange; /* low byte - under range channels */
|
||||
unsigned short orange; /* low byte - over range channels */
|
||||
unsigned short sign; /* low byte - polarity 1 = negative */
|
||||
short data[8]; /* 8 data values (can be signed) */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *drvPvt;
|
||||
IOSCANPVT ioscanpvt;
|
||||
unsigned short read_msg[IL_READMSG_LENGTH];
|
||||
unsigned short *pinit_msg;
|
||||
} devPvt;
|
||||
|
||||
LOCAL unsigned short initMsg[IL_INITMSG_LENGTH] = {
|
||||
IL_RANGE,IL_DATA_FORMAT,0x0ff,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095,
|
||||
0, 0x4095, 0, 0x4095, 0, 0x4095, 0, 0x4095
|
||||
};
|
||||
|
||||
LOCAL void devCallback(void * drvPvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
if(!pdevPvt) return;
|
||||
scanIoRequest(pdevPvt->ioscanpvt);
|
||||
}
|
||||
|
||||
LOCAL long ioinfo_ai(int cmd,struct aiRecord *prec,IOSCANPVT *ppvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)prec->dpvt;
|
||||
if(!pdevPvt) return(0);
|
||||
*ppvt = pdevPvt->ioscanpvt;
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long read_1771Il(struct aiRecord *prec)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt= (devPvt *)prec->dpvt;
|
||||
abStatus drvStatus;
|
||||
struct ab1771il_read *pdata;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
drvStatus = (*pabDrv->getStatus)(pdevPvt->drvPvt);
|
||||
pdata = (struct ab1771il_read *)&pdevPvt->read_msg[0];
|
||||
if(drvStatus != abSuccess) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}
|
||||
prec->rval = pdata->data[pabio->signal];
|
||||
if((pdata->urange&(1<<pabio->signal))
|
||||
|| (pdata->orange&(1<<pabio->signal)) )
|
||||
recGblSetSevr(prec,HW_LIMIT_ALARM,INVALID_ALARM);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long linconv_1771Il(struct aiRecord *prec, int after)
|
||||
{
|
||||
|
||||
/* set linear conversion slope*/
|
||||
prec->eslo = (prec->eguf -prec->egul)/4095.0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long init_1771Il(struct aiRecord *prec)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
|
||||
/* ai.inp must be an AB_IO */
|
||||
if (prec->inp.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"devAiAb1771Il (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
prec->eslo = (prec->eguf -prec->egul)/4095.0;
|
||||
/* pointer to the data addess structure */
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeAi,"IL",devCallback,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
scanIoInit(&pdevPvt->ioscanpvt);
|
||||
pdevPvt->pinit_msg = initMsg;
|
||||
drvStatus = (*pabDrv->startScan)(drvPvt,IL_SCAN_RATE,
|
||||
pdevPvt->pinit_msg,IL_INITMSG_LENGTH,
|
||||
&pdevPvt->read_msg[0],IL_READMSG_LENGTH);
|
||||
if(drvStatus != abSuccess) {
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Il (init_record) startScan");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Il (init_record) registerCard");
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
216
src/dev/devAB1771IR.c
Normal file
216
src/dev/devAB1771IR.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/* devAB1771IR.c */
|
||||
/*
|
||||
* Original Author: Bob Dalesio
|
||||
* Current Author: Bob Dalesio, Marty Kraimer
|
||||
* Date: 3/6/91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 12-01-94 lrd combine the device support that was resident
|
||||
* in the driver and device support to
|
||||
significantly reduce the amount of code
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <link.h>
|
||||
#include <drvAb.h>
|
||||
#include <aiRecord.h>
|
||||
|
||||
/* Create the dsets*/
|
||||
LOCAL long init_1771Ir(struct aiRecord *prec, const char *card_type,
|
||||
unsigned short config);
|
||||
LOCAL long ioinfo_ai(int cmd,struct aiRecord *prec,IOSCANPVT *ppvt);
|
||||
LOCAL long init_1771IrPlatinum(struct aiRecord *prec);
|
||||
LOCAL long init_1771IrCopper(struct aiRecord *prec);
|
||||
LOCAL long read_1771Ir(struct aiRecord *prec);
|
||||
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;
|
||||
DEVSUPFUN special_linconv;} ABAIDSET;
|
||||
|
||||
ABAIDSET devAiAb1771IrPlatinum={6, 0, 0, init_1771IrPlatinum,
|
||||
ioinfo_ai, read_1771Ir, 0};
|
||||
ABAIDSET devAiAb1771IrCopper={6, 0, 0, init_1771IrCopper,
|
||||
ioinfo_ai, read_1771Ir, 0};
|
||||
|
||||
#define IR_SCAN_RATE 5
|
||||
#define IR_INITMSG_LENGTH 1
|
||||
#define IR_READMSG_LENGTH 8
|
||||
|
||||
/*Register definitions*/
|
||||
#define IR_UNITS_DEGF 0x40
|
||||
#define IR_UNITS_OHMS 0x80
|
||||
#define IR_COPPER 0x100
|
||||
#define IR_SIGNED 0x400
|
||||
|
||||
|
||||
struct ab1771Ir_read {
|
||||
unsigned short status; /* status and over/under range */
|
||||
unsigned short pol_over; /* polarity and overflow */
|
||||
short data[6]; /* current values */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *drvPvt;
|
||||
IOSCANPVT ioscanpvt;
|
||||
unsigned short read_msg[IR_READMSG_LENGTH];
|
||||
unsigned short write_msg;
|
||||
} devPvt;
|
||||
|
||||
LOCAL void devCallback(void * drvPvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
if(!pdevPvt) return;
|
||||
scanIoRequest(pdevPvt->ioscanpvt);
|
||||
}
|
||||
|
||||
LOCAL long ioinfo_ai(int cmd,struct aiRecord *prec,IOSCANPVT *ppvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)prec->dpvt;
|
||||
if(!pdevPvt) return(0);
|
||||
*ppvt = pdevPvt->ioscanpvt;
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long read_1771Ir(struct aiRecord *prec)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt= (devPvt *)prec->dpvt;
|
||||
abStatus drvStatus;
|
||||
struct ab1771Ir_read *pdata;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
drvStatus = (*pabDrv->getStatus)(pdevPvt->drvPvt);
|
||||
pdata = (struct ab1771Ir_read *)&pdevPvt->read_msg;
|
||||
if(drvStatus != abSuccess) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}else{
|
||||
unsigned short mask;
|
||||
short value;
|
||||
unsigned short signal = pabio->signal;
|
||||
|
||||
value = (short)pdata->data[signal];
|
||||
if(pdata->pol_over& (0x100<<signal)) value = - value;
|
||||
prec->rval = value;
|
||||
mask = (1 << pabio->signal);
|
||||
if((pdata->status & (1<<signal))
|
||||
||(pdata->status & (0x100<<signal))){
|
||||
recGblSetSevr(prec,HW_LIMIT_ALARM,INVALID_ALARM);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL long init_1771Ir(struct aiRecord *prec, const char *card_type,
|
||||
unsigned short config)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
|
||||
if (prec->inp.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"devAiAb1771Ir (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
prec->linr = 0;
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeAi,card_type,devCallback,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
scanIoInit(&pdevPvt->ioscanpvt);
|
||||
if(pabio->parm[0]=='C') {
|
||||
strcpy(prec->egu,"degC");
|
||||
} else if(pabio->parm[0]=='O') {
|
||||
config |= IR_UNITS_OHMS;
|
||||
strcpy(prec->egu,"ohms");
|
||||
} else {
|
||||
config |= IR_UNITS_DEGF;
|
||||
strcpy(prec->egu,"degF");
|
||||
}
|
||||
config |= IR_SIGNED;
|
||||
pdevPvt->write_msg = config;
|
||||
drvStatus = (*pabDrv->startScan)(drvPvt,IR_SCAN_RATE,
|
||||
&pdevPvt->write_msg,IR_INITMSG_LENGTH,
|
||||
pdevPvt->read_msg,IR_READMSG_LENGTH);
|
||||
if(drvStatus != abSuccess) {
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Ir (init_record) startScan");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Ir (init_record) registerCard");
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL long init_1771IrPlatinum(struct aiRecord *prec)
|
||||
{
|
||||
return(init_1771Ir(prec,"IRPLATINUM",0));
|
||||
}
|
||||
|
||||
LOCAL long init_1771IrCopper(struct aiRecord *prec)
|
||||
{
|
||||
return(init_1771Ir(prec,"IRCOPPER",IR_COPPER));
|
||||
}
|
||||
268
src/dev/devAB1771IXE.c
Normal file
268
src/dev/devAB1771IXE.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/* devAB1771IXE.c */
|
||||
/*
|
||||
* Original Author: Bob Dalesio
|
||||
* Current Author: Bob Dalesio, Marty Kraimer
|
||||
* Date: 3/6/91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 12-01-94 lrd combine the device support that was resident
|
||||
* in the driver and device support to
|
||||
significantly reduce the amount of code
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <link.h>
|
||||
#include <drvAb.h>
|
||||
#include <aiRecord.h>
|
||||
|
||||
/* Create the dsets*/
|
||||
LOCAL long ioinfo_ai(int cmd,struct aiRecord *prec,IOSCANPVT *ppvt);
|
||||
LOCAL long init_1771Ixe(struct aiRecord *prec);
|
||||
LOCAL long linconv_1771Ixe(struct aiRecord *prec, int after);
|
||||
LOCAL long read_1771Ixe(struct aiRecord *prec);
|
||||
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;
|
||||
DEVSUPFUN special_linconv;} ABAIDSET;
|
||||
|
||||
ABAIDSET devAiAb1771Ixe={6, 0, 0, init_1771Ixe,
|
||||
ioinfo_ai, read_1771Ixe, linconv_1771Ixe};
|
||||
|
||||
#define IXE_HALFSEC_RATE 5
|
||||
#define IXE_1SEC_RATE 10
|
||||
#define IXE_INITMSG_LENGTH 19
|
||||
#define IXE_READMSG_LENGTH 12
|
||||
#define IXE_NUM_CVTTYPES 14
|
||||
|
||||
typedef struct {
|
||||
void *drvPvt;
|
||||
IOSCANPVT ioscanpvt;
|
||||
unsigned short init_msg[IXE_INITMSG_LENGTH];
|
||||
unsigned short read_msg[IXE_READMSG_LENGTH];
|
||||
unsigned short indCvt;
|
||||
} devPvt;
|
||||
|
||||
/* xxxxxxxxxxxxxTTT - Thermocouple Types */
|
||||
#define IXE_MILLI 0x0000 /* Millivolt input */
|
||||
#define IXE_E 0x0001 /* "E" Thermocouple */
|
||||
#define IXE_J 0x0002 /* "J" Thermocouple */
|
||||
#define IXE_K 0x0003 /* "K" Thermocouple */
|
||||
#define IXE_T 0x0004 /* "T" Thermocouple */
|
||||
#define IXE_R 0x0005 /* "R" Thermocouple */
|
||||
#define IXE_S 0x0006 /* "S" Thermocouple */
|
||||
/* xxxxxxxCxxxxxxxx - Conversion into degrees F or C */
|
||||
#define IXE_DEGC 0x0000
|
||||
#define IXE_DEGF 0x0100
|
||||
/* xxxxxFFxxxxxxxxx - Data Format */
|
||||
#define IXE_SIGNED 0x0400 /* signed magnitude " " */
|
||||
/* SSSSSxxxxxxxxxxx - Scan Rate */
|
||||
#define IXE_HALFSEC 0x2800 /* sample time = 0.5 seconds */
|
||||
#define IXE_1SEC 0x5000 /* sample time = 1.0 seconds */
|
||||
#define IXE_2SECS 0xa000 /* sample time = 2.0 seconds */
|
||||
#define IXE_3SECS 0xf000 /* sample time = 3.0 seconds */
|
||||
|
||||
#define IXE_STATUS 0xff
|
||||
struct ab1771Ixe_read {
|
||||
unsigned short pol_stat; /* status - polarity word */
|
||||
unsigned short out_of_range; /* under - over range channels */
|
||||
unsigned short alarms; /* inputs outside alarm limits */
|
||||
short data[8]; /* current values */
|
||||
unsigned short cjcw; /* cold junction cal word */
|
||||
};
|
||||
|
||||
/*NOTE: The following degfinitions assumes that the allowed convert types
|
||||
are defined as follows:
|
||||
K_DGF=2, K_DGC=3, J_DGF=4, J_DGC=5, E_DGF=6, E_DGC=7, T_DGF=8,
|
||||
T_DGC=9, R_DGF=10, R_DGC=11, S_DGF=12, S_DGC=13,
|
||||
THIS IS A REAL KLUDGE. WE SHOULD FIND A BETTER WAY */
|
||||
LOCAL unsigned short ixe_cvt[IXE_NUM_CVTTYPES] = {
|
||||
IXE_MILLI | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_MILLI | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_K | IXE_DEGF | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_K | IXE_DEGC | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_J | IXE_DEGF | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_J | IXE_DEGC | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_E | IXE_DEGF | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_E | IXE_DEGC | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_T | IXE_DEGF | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_T | IXE_DEGC | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_R | IXE_DEGF | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_R | IXE_DEGC | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_S | IXE_DEGF | IXE_SIGNED | IXE_HALFSEC,
|
||||
IXE_S | IXE_DEGC | IXE_SIGNED | IXE_HALFSEC
|
||||
};
|
||||
LOCAL const char* cardName[IXE_NUM_CVTTYPES] = {
|
||||
"IXE_MV","IXE_MV","IXE_KDEGF","IXE_KDEGC",
|
||||
"IXE_JDEGF","IXE_JDEGC","IXE_EDEGF","IXE_EDEGC",
|
||||
"IXE_TDEGF","IXE_TDEGC","IXE_RDEGF","IXE_RDEGC",
|
||||
"IXS_TDEGF","IXE_SDEGC"
|
||||
};
|
||||
LOCAL unsigned short scanRate[IXE_NUM_CVTTYPES] = {
|
||||
IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,
|
||||
IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,
|
||||
IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,
|
||||
IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,IXE_HALFSEC_RATE,IXE_HALFSEC_RATE
|
||||
};
|
||||
|
||||
LOCAL void devCallback(void * drvPvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
if(!pdevPvt) return;
|
||||
scanIoRequest(pdevPvt->ioscanpvt);
|
||||
}
|
||||
|
||||
LOCAL long ioinfo_ai(int cmd,struct aiRecord *prec,IOSCANPVT *ppvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)prec->dpvt;
|
||||
if(!pdevPvt) return(0);
|
||||
*ppvt = pdevPvt->ioscanpvt;
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long read_1771Ixe(struct aiRecord *prec)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt= (devPvt *)prec->dpvt;
|
||||
abStatus drvStatus;
|
||||
struct ab1771Ixe_read *pdata;
|
||||
long status;
|
||||
unsigned short indCvt;
|
||||
short rval;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}
|
||||
indCvt = pdevPvt->indCvt;
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
drvStatus = (*pabDrv->getStatus)(pdevPvt->drvPvt);
|
||||
pdata = (struct ab1771Ixe_read *)&pdevPvt->read_msg[0];
|
||||
if(drvStatus != abSuccess) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}
|
||||
rval = pdata->data[pabio->signal];
|
||||
if((pdata->pol_stat&(0x100<<pabio->signal))) rval = -rval;
|
||||
if((pdata->out_of_range&(1<<pabio->signal))
|
||||
|| (pdata->out_of_range&(0x100<<pabio->signal)) ) {
|
||||
recGblSetSevr(prec,HW_LIMIT_ALARM,INVALID_ALARM);
|
||||
}
|
||||
if(indCvt!=0) {
|
||||
prec->val = prec->rval = rval;
|
||||
prec->udf = FALSE;
|
||||
status=2; /*don't convert*/
|
||||
} else {
|
||||
prec->rval = rval + 10000;
|
||||
status = 0;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
static long linconv_1771Ixe(struct aiRecord *prec, int after)
|
||||
{
|
||||
|
||||
/* set linear conversion slope*/
|
||||
prec->eslo = (prec->eguf -prec->egul)/20000.0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long init_1771Ixe(struct aiRecord *prec)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
unsigned short indCvt;
|
||||
|
||||
/* ai.inp must be an AB_IO */
|
||||
if (prec->inp.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"devAiAb1771Ixe (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
/*If conversion type is 2,...,IXE_NUM_CVTTYPES Ixe performs the conversion*/
|
||||
/* THIS SHOULD BE CHANGED */
|
||||
if(prec->linr>=2 && prec->linr <IXE_NUM_CVTTYPES) {
|
||||
indCvt = prec->linr;
|
||||
prec->linr = 0;
|
||||
} else {
|
||||
indCvt = 0;
|
||||
}
|
||||
prec->eslo = (prec->eguf -prec->egul)/20000.0;
|
||||
/* pointer to the data addess structure */
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeAi,cardName[indCvt],devCallback,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
pdevPvt->indCvt = indCvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
scanIoInit(&pdevPvt->ioscanpvt);
|
||||
pdevPvt->init_msg[0] = ixe_cvt[indCvt];
|
||||
drvStatus = (*pabDrv->startScan)(drvPvt,scanRate[indCvt],
|
||||
&pdevPvt->init_msg[0],IXE_INITMSG_LENGTH,
|
||||
&pdevPvt->read_msg[0],IXE_READMSG_LENGTH);
|
||||
if(drvStatus != abSuccess) {
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Ixe (init_record) startScan");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Ixe (init_record) registerCard");
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
196
src/dev/devAB1771OFE.c
Normal file
196
src/dev/devAB1771OFE.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/* devAB1771OFE.c */
|
||||
/*
|
||||
* Original Author: Bob Dalesio
|
||||
* Current Author: Bob Dalesio, Marty Kraimer
|
||||
* Date: 3/6/91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 12-01-94 lrd combine the device support that was resident in the driver and
|
||||
* device support to significantly reduce the amount of code
|
||||
* ...
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sysLib.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <link.h>
|
||||
#include <drvAb.h>
|
||||
#include <aoRecord.h>
|
||||
|
||||
/* Create the dsets*/
|
||||
LOCAL long init_1771Ofe(struct aoRecord *pao);
|
||||
LOCAL long write_1771Ofe(struct aoRecord *pao);
|
||||
LOCAL long linconv_1771Ofe(struct aoRecord *pao, int after);
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN write_ao;
|
||||
DEVSUPFUN special_linconv;
|
||||
}ABAODSET;
|
||||
|
||||
ABAODSET devAoAb1771Ofe={ 6, NULL, NULL, init_1771Ofe, NULL,
|
||||
write_1771Ofe, linconv_1771Ofe};
|
||||
|
||||
#define UPDATE_RATE 100
|
||||
#define READ_MSG_LEN 5
|
||||
#define WRITE_MSG_LEN 5
|
||||
|
||||
|
||||
/* defines and structures for analog outputs */
|
||||
/* configuration word 5 for the OFE module */
|
||||
/* FxxxHHHHLLLLPPPP */
|
||||
/* F - Data Format */
|
||||
/* 0x0 specifies BCD */
|
||||
/* 0x1 specifies Binary */
|
||||
/* HHHH - Max Scaling Polarity */
|
||||
/* LLLL - Min Scaling Polarity */
|
||||
/* PPPP - Value Polarity */
|
||||
#define OFE_BINARY 0x8000 /* talk binary instead of BCD */
|
||||
#define OFE_SCALING 0x0000 /* all positive */
|
||||
|
||||
typedef struct {
|
||||
void *drvPvt;
|
||||
unsigned short read_msg[READ_MSG_LEN];
|
||||
unsigned short write_msg[WRITE_MSG_LEN];
|
||||
}devPvt;
|
||||
|
||||
LOCAL long init_1771Ofe(struct aoRecord *prec)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
int failed;
|
||||
int i;
|
||||
|
||||
if (prec->out.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"devAiAb1771Ife (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
/* set linear conversion slope*/
|
||||
prec->eslo = (prec->eguf -prec->egul)/4095.0;
|
||||
/* pointer to the data addess structure */
|
||||
pabio = (struct abio *)&(prec->out.value);
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeAo,"OFE",NULL,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
drvStatus = (*pabDrv->getStatus)(drvPvt);
|
||||
if(drvStatus==abSuccess) {
|
||||
prec->rval = (unsigned short)pdevPvt->read_msg[pabio->signal];
|
||||
} else {
|
||||
status = 2;
|
||||
}
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
pdevPvt->write_msg[4] = OFE_BINARY | OFE_SCALING;
|
||||
drvStatus = (*pabDrv->startScan)(drvPvt,UPDATE_RATE,
|
||||
pdevPvt->write_msg,WRITE_MSG_LEN,
|
||||
pdevPvt->read_msg ,READ_MSG_LEN);
|
||||
if(drvStatus!=abSuccess) {
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Ife (init_record) startScan");
|
||||
break;
|
||||
}
|
||||
/*wait for up to 1 seconds*/
|
||||
for(failed=0; failed<10; failed++) {
|
||||
taskDelay(vxTicksPerSecond/10);
|
||||
drvStatus = (*pabDrv->getStatus)(drvPvt);
|
||||
if(drvStatus==abSuccess) {
|
||||
prec->rval=(unsigned short)pdevPvt->read_msg[pabio->signal];
|
||||
for(i=0;i<4;i++) {
|
||||
pdevPvt->write_msg[i] = pdevPvt->read_msg[i];
|
||||
}
|
||||
write_1771Ofe(prec);
|
||||
status = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = 0;
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,
|
||||
"devAiAb1771Ife (init_record) registerCard");
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL long write_1771Ofe(struct aoRecord *prec)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
abStatus drvStatus;
|
||||
void *drvPvt;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2); /*dont convert*/
|
||||
}
|
||||
drvPvt = pdevPvt->drvPvt;
|
||||
pabio = (struct abio *)&(prec->out.value);
|
||||
pdevPvt->write_msg[pabio->signal] = prec->rval;
|
||||
drvStatus = (*pabDrv->updateAo)(drvPvt);
|
||||
if(drvStatus!=abSuccess) {
|
||||
if(recGblSetSevr(prec,WRITE_ALARM,INVALID_ALARM) && errVerbose
|
||||
&& (prec->stat!=WRITE_ALARM || prec->sevr!=INVALID_ALARM))
|
||||
recGblRecordError(-1,(void *)prec,"abDrv(updateAo)");
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
LOCAL long linconv_1771Ofe(struct aoRecord *prec, int after)
|
||||
{
|
||||
|
||||
if(!after) return(0);
|
||||
/* set linear conversion slope*/
|
||||
prec->eslo = (prec->eguf -prec->egul)/4095.0;
|
||||
return(0);
|
||||
}
|
||||
617
src/dev/devABBINARY.c
Normal file
617
src/dev/devABBINARY.c
Normal file
@@ -0,0 +1,617 @@
|
||||
/* devABBINARY.c */
|
||||
/*
|
||||
* Original Author: Bob Dalesio
|
||||
* Current Author: Bob Dalesio, Marty Kraimer
|
||||
* Date: 3/6/91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 12-01-94 lrd combine the device support that was resident in the driver and
|
||||
* device support to significantly reduce the amount of code
|
||||
* ...
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <link.h>
|
||||
#include <drvAb.h>
|
||||
#include <dbCommon.h>
|
||||
#include <biRecord.h>
|
||||
#include <boRecord.h>
|
||||
#include <mbbiRecord.h>
|
||||
#include <mbboRecord.h>
|
||||
#include <mbbiDirectRecord.h>
|
||||
#include <mbboDirectRecord.h>
|
||||
|
||||
typedef struct {
|
||||
void *drvPvt;
|
||||
IOSCANPVT ioscanpvt;
|
||||
}devPvt;
|
||||
|
||||
|
||||
/* Create the dsets*/
|
||||
LOCAL long ioinfo(int cmd, struct dbCommon *prec, IOSCANPVT *ppvt);
|
||||
LOCAL long read_bi(struct biRecord *prec);
|
||||
LOCAL long init_bi08(struct biRecord *prec);
|
||||
LOCAL long init_bi16(struct biRecord *prec);
|
||||
LOCAL long init_bi32(struct biRecord *prec);
|
||||
LOCAL long init_bi(struct biRecord *prec,abNumBits nBits);
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_bi;} ABBIDSET;
|
||||
|
||||
ABBIDSET devBiAb= { 5, 0, 0, init_bi08, ioinfo, read_bi};
|
||||
ABBIDSET devBiAb16= { 5, 0, 0, init_bi16, ioinfo, read_bi};
|
||||
ABBIDSET devBiAb32= { 5, 0, 0, init_bi32, ioinfo, read_bi};
|
||||
|
||||
LOCAL long read_mbbi(struct mbbiRecord *prec);
|
||||
LOCAL long init_mbbi08(struct mbbiRecord *prec);
|
||||
LOCAL long init_mbbi16(struct mbbiRecord *prec);
|
||||
LOCAL long init_mbbi32(struct mbbiRecord *prec);
|
||||
LOCAL long init_mbbi(struct mbbiRecord *prec,abNumBits nBits);
|
||||
ABBIDSET devMbbiAb= { 5, 0, 0, init_mbbi08, ioinfo, read_mbbi};
|
||||
ABBIDSET devMbbiAb16={ 5, 0, 0, init_mbbi16, ioinfo, read_mbbi};
|
||||
ABBIDSET devMbbiAb32={ 5, 0, 0, init_mbbi32, ioinfo, read_mbbi};
|
||||
|
||||
LOCAL long read_mbbiDirect(struct mbbiDirectRecord *prec);
|
||||
LOCAL long init_mbbiDirect08(struct mbbiDirectRecord *prec);
|
||||
LOCAL long init_mbbiDirect16(struct mbbiDirectRecord *prec);
|
||||
LOCAL long init_mbbiDirect32(struct mbbiDirectRecord *prec);
|
||||
LOCAL long init_mbbiDirect(struct mbbiDirectRecord *prec,abNumBits nBits);
|
||||
ABBIDSET devMbbiDirectAb= { 5,0,0, init_mbbiDirect08,ioinfo, read_mbbiDirect};
|
||||
ABBIDSET devMbbiDirectAb16={ 5,0,0, init_mbbiDirect16,ioinfo, read_mbbiDirect};
|
||||
ABBIDSET devMbbiDirectAb32={ 5,0,0, init_mbbiDirect32,ioinfo, read_mbbiDirect};
|
||||
|
||||
LOCAL long write_bo(struct boRecord *prec);
|
||||
LOCAL long init_bo08(struct boRecord *prec);
|
||||
LOCAL long init_bo16(struct boRecord *prec);
|
||||
LOCAL long init_bo32(struct boRecord *prec);
|
||||
LOCAL long init_bo(struct boRecord *prec,abNumBits nBits);
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN write_bo;
|
||||
} ABBODSET;
|
||||
|
||||
ABBODSET devBoAb= { 5, 0, 0, init_bo08, 0, write_bo};
|
||||
ABBODSET devBoAb16= { 5, 0, 0, init_bo16, 0, write_bo};
|
||||
ABBODSET devBoAb32= { 5, 0, 0, init_bo32, 0, write_bo};
|
||||
|
||||
LOCAL long write_mbbo(struct mbboRecord *prec);
|
||||
LOCAL long init_mbbo08(struct mbboRecord *prec);
|
||||
LOCAL long init_mbbo16(struct mbboRecord *prec);
|
||||
LOCAL long init_mbbo32(struct mbboRecord *prec);
|
||||
LOCAL long init_mbbo(struct mbboRecord *prec,abNumBits nBits);
|
||||
ABBODSET devMbboAb= { 5, 0, 0, init_mbbo08, 0, write_mbbo};
|
||||
ABBODSET devMbboAb16={ 5, 0, 0, init_mbbo16, 0, write_mbbo};
|
||||
ABBODSET devMbboAb32={ 5, 0, 0, init_mbbo32, 0, write_mbbo};
|
||||
|
||||
LOCAL long write_mbboDirect(struct mbboDirectRecord *prec);
|
||||
LOCAL long init_mbboDirect08(struct mbboDirectRecord *prec);
|
||||
LOCAL long init_mbboDirect16(struct mbboDirectRecord *prec);
|
||||
LOCAL long init_mbboDirect32(struct mbboDirectRecord *prec);
|
||||
LOCAL long init_mbboDirect(struct mbboDirectRecord *prec,abNumBits nBits);
|
||||
ABBODSET devMbboDirectAb= { 5, 0, 0, init_mbboDirect08, 0, write_mbboDirect};
|
||||
ABBODSET devMbboDirectAb16={ 5, 0, 0, init_mbboDirect16, 0, write_mbboDirect};
|
||||
ABBODSET devMbboDirectAb32={ 5, 0, 0, init_mbboDirect32, 0, write_mbboDirect};
|
||||
|
||||
LOCAL void devCallback(void * drvPvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
if(!pdevPvt) return;
|
||||
if(!pdevPvt->ioscanpvt) return;
|
||||
scanIoRequest(pdevPvt->ioscanpvt);
|
||||
}
|
||||
|
||||
LOCAL long ioinfo(int cmd, struct dbCommon *prec, IOSCANPVT *ppvt)
|
||||
{
|
||||
devPvt *pdevPvt;
|
||||
|
||||
pdevPvt = prec->dpvt;
|
||||
if(!pdevPvt) return(0);
|
||||
*ppvt = pdevPvt->ioscanpvt;
|
||||
return(0);
|
||||
}
|
||||
LOCAL long init_bi08(struct biRecord *prec)
|
||||
{
|
||||
return(init_bi(prec, abBit8));
|
||||
}
|
||||
LOCAL long init_bi16(struct biRecord *prec)
|
||||
{
|
||||
return(init_bi(prec, abBit16));
|
||||
}
|
||||
LOCAL long init_bi32(struct biRecord *prec)
|
||||
{
|
||||
return(init_bi(prec, abBit32));
|
||||
}
|
||||
|
||||
LOCAL long init_mbbi08(struct mbbiRecord *prec)
|
||||
{
|
||||
return(init_mbbi(prec, abBit8));
|
||||
}
|
||||
LOCAL long init_mbbi16(struct mbbiRecord *prec)
|
||||
{
|
||||
return(init_mbbi(prec, abBit16));
|
||||
}
|
||||
LOCAL long init_mbbi32(struct mbbiRecord *prec)
|
||||
{
|
||||
return(init_mbbi(prec, abBit32));
|
||||
}
|
||||
|
||||
LOCAL long init_mbbiDirect08(struct mbbiDirectRecord *prec)
|
||||
{
|
||||
return(init_mbbiDirect(prec, abBit8));
|
||||
}
|
||||
LOCAL long init_mbbiDirect16(struct mbbiDirectRecord *prec)
|
||||
{
|
||||
return(init_mbbiDirect(prec, abBit16));
|
||||
}
|
||||
LOCAL long init_mbbiDirect32(struct mbbiDirectRecord *prec)
|
||||
{
|
||||
return(init_mbbiDirect(prec, abBit32));
|
||||
}
|
||||
|
||||
LOCAL long init_bo08(struct boRecord *prec)
|
||||
{
|
||||
return(init_bo(prec, abBit8));
|
||||
}
|
||||
LOCAL long init_bo16(struct boRecord *prec)
|
||||
{
|
||||
return(init_bo(prec, abBit16));
|
||||
}
|
||||
LOCAL long init_bo32(struct boRecord *prec)
|
||||
{
|
||||
return(init_bo(prec, abBit32));
|
||||
}
|
||||
|
||||
LOCAL long init_mbbo08(struct mbboRecord *prec)
|
||||
{
|
||||
return(init_mbbo(prec, abBit8));
|
||||
}
|
||||
LOCAL long init_mbbo16(struct mbboRecord *prec)
|
||||
{
|
||||
return(init_mbbo(prec, abBit16));
|
||||
}
|
||||
LOCAL long init_mbbo32(struct mbboRecord *prec)
|
||||
{
|
||||
return(init_mbbo(prec, abBit32));
|
||||
}
|
||||
|
||||
LOCAL long init_mbboDirect08(struct mbboDirectRecord *prec)
|
||||
{
|
||||
return(init_mbboDirect(prec, abBit8));
|
||||
}
|
||||
LOCAL long init_mbboDirect16(struct mbboDirectRecord *prec)
|
||||
{
|
||||
return(init_mbboDirect(prec, abBit16));
|
||||
}
|
||||
LOCAL long init_mbboDirect32(struct mbboDirectRecord *prec)
|
||||
{
|
||||
return(init_mbboDirect(prec, abBit32));
|
||||
}
|
||||
|
||||
LOCAL long read_bi(struct biRecord *prec)
|
||||
{
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
void *drvPvt;
|
||||
abStatus drvStatus;
|
||||
unsigned long value;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2);
|
||||
}
|
||||
drvPvt = pdevPvt->drvPvt;
|
||||
drvStatus = (*pabDrv->readBi)(drvPvt,&value,prec->mask);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2);
|
||||
}
|
||||
prec->rval = value;
|
||||
return(0);
|
||||
}
|
||||
LOCAL long init_bi(struct biRecord *prec,abNumBits nBits)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
|
||||
if (prec->inp.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"init_record: bad INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
prec->mask=1;
|
||||
prec->mask <<= pabio->signal;
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeBi,"BINARY",devCallback,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
scanIoInit(&pdevPvt->ioscanpvt);
|
||||
drvStatus = (*pabDrv->setNbits)(drvPvt,nBits);
|
||||
if(drvStatus!=abSuccess) {
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record setNbits");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record registerCard");
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL long read_mbbi(struct mbbiRecord *prec)
|
||||
{
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
void *drvPvt;
|
||||
abStatus drvStatus;
|
||||
unsigned long value;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2);
|
||||
}
|
||||
drvPvt = pdevPvt->drvPvt;
|
||||
drvStatus = (*pabDrv->readBi)(drvPvt,&value,prec->mask);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2);
|
||||
}
|
||||
prec->rval = value;
|
||||
return(0);
|
||||
}
|
||||
LOCAL long init_mbbi(struct mbbiRecord *prec,abNumBits nBits)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
|
||||
if (prec->inp.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec, "Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
prec->shft = prec->inp.value.abio.signal;
|
||||
prec->mask <<= prec->shft;
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeBi,"BINARY",devCallback,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
scanIoInit(&pdevPvt->ioscanpvt);
|
||||
drvStatus = (*pabDrv->setNbits)(drvPvt,nBits);
|
||||
if(drvStatus!=abSuccess) {
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record setNbits");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record registerCard");
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL long read_mbbiDirect(struct mbbiDirectRecord *prec)
|
||||
{
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
void *drvPvt;
|
||||
abStatus drvStatus;
|
||||
unsigned long value;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2);
|
||||
}
|
||||
drvPvt = pdevPvt->drvPvt;
|
||||
drvStatus = (*pabDrv->readBi)(drvPvt,&value,prec->mask);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblSetSevr(prec,READ_ALARM,INVALID_ALARM);
|
||||
return(2);
|
||||
}
|
||||
prec->rval = value;
|
||||
return(0);
|
||||
}
|
||||
LOCAL long init_mbbiDirect(struct mbbiDirectRecord *prec,abNumBits nBits)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
|
||||
if (prec->inp.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec, "Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
prec->shft = prec->inp.value.abio.signal;
|
||||
prec->mask <<= prec->shft;
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeBi,"BINARY",devCallback,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
scanIoInit(&pdevPvt->ioscanpvt);
|
||||
drvStatus = (*pabDrv->setNbits)(drvPvt,nBits);
|
||||
if(drvStatus!=abSuccess) {
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record setNbits");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record registerCard");
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL long write_bo(struct boRecord *prec)
|
||||
{
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
void *drvPvt;
|
||||
abStatus drvStatus;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,WRITE_ALARM,INVALID_ALARM);
|
||||
return(0);
|
||||
}
|
||||
drvPvt = pdevPvt->drvPvt;
|
||||
drvStatus = (*pabDrv->updateBo)(drvPvt,prec->rval,prec->mask);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblSetSevr(prec,WRITE_ALARM,INVALID_ALARM);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
LOCAL long init_bo(struct boRecord *prec,abNumBits nBits)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
unsigned long value;
|
||||
|
||||
if (prec->out.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec, "Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
pabio = (struct abio *)&(prec->out.value);
|
||||
prec->mask = 1;
|
||||
prec->mask <<= pabio->signal;
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeBo,"BINARY",NULL,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
drvStatus = (*pabDrv->setNbits)(drvPvt,nBits);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"init_record setNbits");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record registerCard");
|
||||
return(status);
|
||||
}
|
||||
drvStatus = (*pabDrv->readBo)(drvPvt,&value,prec->mask);
|
||||
if(drvStatus==abSuccess) {
|
||||
prec->rval = value;
|
||||
status = 0;
|
||||
} else {
|
||||
status = 2;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL long write_mbbo(struct mbboRecord *prec)
|
||||
{
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
void *drvPvt;
|
||||
abStatus drvStatus;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,WRITE_ALARM,INVALID_ALARM);
|
||||
return(0);
|
||||
}
|
||||
drvPvt = pdevPvt->drvPvt;
|
||||
drvStatus = (*pabDrv->updateBo)(drvPvt,prec->rval,prec->mask);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblSetSevr(prec,WRITE_ALARM,INVALID_ALARM);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
LOCAL long init_mbbo(struct mbboRecord *prec,abNumBits nBits)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
unsigned long value;
|
||||
|
||||
if (prec->out.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec, "Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
pabio = (struct abio *)&(prec->out.value);
|
||||
prec->shft = prec->out.value.abio.signal;
|
||||
prec->mask <<= prec->shft;
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeBo,"BINARY",NULL,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
drvStatus = (*pabDrv->setNbits)(drvPvt,nBits);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"init_record setNbits");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record registerCard");
|
||||
return(status);
|
||||
}
|
||||
drvStatus = (*pabDrv->readBo)(drvPvt,&value,prec->mask);
|
||||
if(drvStatus==abSuccess) {
|
||||
prec->rval = value;
|
||||
status = 0;
|
||||
} else {
|
||||
status = 2;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL long write_mbboDirect(struct mbboDirectRecord *prec)
|
||||
{
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
void *drvPvt;
|
||||
abStatus drvStatus;
|
||||
unsigned long value = prec->rval;
|
||||
|
||||
if(!pdevPvt) {
|
||||
recGblSetSevr(prec,WRITE_ALARM,INVALID_ALARM);
|
||||
return(0);
|
||||
}
|
||||
drvPvt = pdevPvt->drvPvt;
|
||||
drvStatus = (*pabDrv->updateBo)(drvPvt,value,prec->mask);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblSetSevr(prec,WRITE_ALARM,INVALID_ALARM);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
LOCAL long init_mbboDirect(struct mbboDirectRecord *prec,abNumBits nBits)
|
||||
{
|
||||
struct abio *pabio;
|
||||
devPvt *pdevPvt;
|
||||
abStatus drvStatus;
|
||||
long status=0;
|
||||
void *drvPvt;
|
||||
unsigned long value;
|
||||
|
||||
if (prec->out.type != AB_IO){
|
||||
recGblRecordError(S_db_badField,(void *)prec, "Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
pabio = (struct abio *)&(prec->out.value);
|
||||
prec->shft = prec->out.value.abio.signal;
|
||||
prec->mask <<= prec->shft;
|
||||
drvStatus = (*pabDrv->registerCard)(pabio->link,pabio->adapter,
|
||||
pabio->card,typeBo,"BINARY",NULL,&drvPvt);
|
||||
switch(drvStatus) {
|
||||
case abSuccess :
|
||||
pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt);
|
||||
prec->dpvt = pdevPvt;
|
||||
break;
|
||||
case abNewCard :
|
||||
pdevPvt = calloc(1,sizeof(devPvt));
|
||||
pdevPvt->drvPvt = drvPvt;
|
||||
prec->dpvt = pdevPvt;
|
||||
(*pabDrv->setUserPvt)(drvPvt,(void *)pdevPvt);
|
||||
drvStatus = (*pabDrv->setNbits)(drvPvt,nBits);
|
||||
if(drvStatus!=abSuccess) {
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"init_record setNbits");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_db_badField;
|
||||
recGblRecordError(status,(void *)prec,"init_record registerCard");
|
||||
return(status);
|
||||
}
|
||||
drvStatus = (*pabDrv->readBo)(drvPvt,&value,prec->mask);
|
||||
if(drvStatus==abSuccess) {
|
||||
prec->rval = value;
|
||||
status = 0;
|
||||
} else {
|
||||
status = 2;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
114
src/dev/devABStatus.c
Normal file
114
src/dev/devABStatus.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/* devABStatus.c */
|
||||
/*
|
||||
* Original Authors: Marty Kraimer (nagging by Ned Arnold,Bob dalesio)
|
||||
* Date: 3/6/91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 04-20-95 mrk Initial version
|
||||
* ...
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <link.h>
|
||||
#include <drvAb.h>
|
||||
#include <mbbiRecord.h>
|
||||
|
||||
typedef struct {
|
||||
void *drvPvt;
|
||||
IOSCANPVT ioscanpvt;
|
||||
}devPvt;
|
||||
|
||||
|
||||
/* Create the dsets*/
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_bi;} ABBIDSET;
|
||||
|
||||
LOCAL long init_common(struct mbbiRecord *prec);
|
||||
LOCAL long read_adapter_status(struct mbbiRecord *prec);
|
||||
LOCAL long read_card_status(struct mbbiRecord *prec);
|
||||
ABBIDSET devMbbiAbAdapterStat= { 5, 0, 0, init_common, 0, read_adapter_status};
|
||||
ABBIDSET devMbbiAbCardStat= { 5, 0, 0, init_common, 0, read_card_status};
|
||||
|
||||
LOCAL long init_common(struct mbbiRecord *prec)
|
||||
{
|
||||
unsigned long *pstate_values;
|
||||
char *pstate_string;
|
||||
unsigned short *palarm_sevr;
|
||||
short i;
|
||||
|
||||
if(abFailure>=16) {
|
||||
epicsPrintf("devMbbiAbLinkStat. > 16 error status values\n");
|
||||
taskSuspend(0);
|
||||
return(0);
|
||||
}
|
||||
pstate_values = &(prec->zrvl);
|
||||
pstate_string = prec->zrst;
|
||||
palarm_sevr = &prec->zrsv;
|
||||
/*Following code assumes that abFailure is last status value*/
|
||||
for(i=0; i<=abFailure; i++ ,pstate_string += sizeof(prec->zrst)){
|
||||
pstate_values[i] = 1<<i;
|
||||
if(pstate_string[0]=='\0')
|
||||
strncpy(pstate_string,abStatusMessage[i],sizeof(prec->zrst)-1);
|
||||
if(i>0) palarm_sevr[i] = MAJOR_ALARM;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
LOCAL long read_adapter_status(struct mbbiRecord *prec)
|
||||
{
|
||||
abStatus status;
|
||||
struct abio *pabio;
|
||||
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
status = (*pabDrv->adapterStatus)(pabio->link,pabio->adapter);
|
||||
prec->rval = 1 << status;;
|
||||
return(0);
|
||||
}
|
||||
LOCAL long read_card_status(struct mbbiRecord *prec)
|
||||
{
|
||||
abStatus status;
|
||||
struct abio *pabio;
|
||||
|
||||
pabio = (struct abio *)&(prec->inp.value);
|
||||
status = (*pabDrv->cardStatus)(pabio->link,pabio->adapter,pabio->card);
|
||||
prec->rval = 1 << status;;
|
||||
return(0);
|
||||
}
|
||||
1377
src/dev/devAllenBradleyOLD.c
Normal file
1377
src/dev/devAllenBradleyOLD.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -127,12 +127,14 @@ AT5VXIDSET_TM devTmAt5Vxi={6, NULL, NULL, NULL, NULL, read_timer, write_timer};
|
||||
* Values are converted to seconds.
|
||||
*/
|
||||
static double constants[] = {1e3,1e6,1e9,1e12};
|
||||
|
||||
static void localPostEvent (void *pParam);
|
||||
|
||||
static long read_timer(struct timerRecord *ptimer)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
int source;
|
||||
int ptst;
|
||||
unsigned source;
|
||||
unsigned ptst;
|
||||
double time_pulse[2]; /* delay and width */
|
||||
double constant;
|
||||
|
||||
@@ -164,22 +166,40 @@ static long read_timer(struct timerRecord *ptimer)
|
||||
|
||||
static long write_timer(struct timerRecord *ptimer)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
struct vmeio *pvmeio;
|
||||
void (*pCB)(void *);
|
||||
|
||||
pvmeio = (struct vmeio *)(&ptimer->out.value);
|
||||
|
||||
if (ptimer->tevt) {
|
||||
pCB = localPostEvent;
|
||||
}
|
||||
else {
|
||||
pCB = NULL;
|
||||
}
|
||||
|
||||
/* put the value to the ao driver */
|
||||
return at5vxi_one_shot(
|
||||
(int)ptimer->ptst, /* pre-trigger state */
|
||||
ptimer->t1dl, /* pulse offset */
|
||||
ptimer->t1wd, /* pulse width */
|
||||
(int)pvmeio->card, /* card number */
|
||||
(int)pvmeio->signal, /* signal number */
|
||||
(int)ptimer->tsrc, /* trigger source */
|
||||
((ptimer->tevt == 0)?0:post_event), /* addr of event post routine */
|
||||
(int)ptimer->tevt); /* event to post on trigger */
|
||||
ptimer->ptst, /* pre-trigger state */
|
||||
ptimer->t1dl, /* pulse offset */
|
||||
ptimer->t1wd, /* pulse width */
|
||||
pvmeio->card, /* card number */
|
||||
pvmeio->signal, /* signal number */
|
||||
ptimer->tsrc, /* trigger source */
|
||||
pCB, /* addr of event post routine */
|
||||
ptimer); /* event to post on trigger */
|
||||
}
|
||||
|
||||
|
||||
static void localPostEvent (void *pParam)
|
||||
{
|
||||
struct timerRecord *ptimer = pParam;
|
||||
|
||||
if (ptimer->tevt) {
|
||||
post_event(ptimer->tevt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static long init_ai( struct aiRecord *pai)
|
||||
{
|
||||
@@ -342,7 +362,7 @@ static long read_bi(struct biRecord *pbi)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
long status;
|
||||
long value;
|
||||
unsigned long value;
|
||||
|
||||
|
||||
pvmeio = (struct vmeio *)&(pbi->inp.value);
|
||||
@@ -357,9 +377,9 @@ static long read_bi(struct biRecord *pbi)
|
||||
|
||||
static long init_bo(struct boRecord *pbo)
|
||||
{
|
||||
unsigned int value;
|
||||
long status=0;
|
||||
struct vmeio *pvmeio;
|
||||
unsigned long value;
|
||||
long status=0;
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
/* bo.out must be an VME_IO */
|
||||
switch (pbo->out.type) {
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
/*
|
||||
* $Log$
|
||||
* Revision 1.23 1995/01/06 16:55:52 winans
|
||||
* Added the log parameter to the doc
|
||||
*
|
||||
*
|
||||
* Author: John Winans
|
||||
* Origional Author: Ned D. Arnold
|
||||
@@ -2464,6 +2467,7 @@ void (*process)();
|
||||
/* make sure the command type makes sendse for the record type */
|
||||
|
||||
if (parmBlock->gpibCmds[((struct gpibDpvt *)pwf->dpvt)->parm].type != GPIBREAD &&
|
||||
parmBlock->gpibCmds[((struct gpibDpvt *)pwf->dpvt)->parm].type != GPIBWRITE &&
|
||||
parmBlock->gpibCmds[((struct gpibDpvt *)pwf->dpvt)->parm].type != GPIBSOFT &&
|
||||
parmBlock->gpibCmds[((struct gpibDpvt *)pwf->dpvt)->parm].type != GPIBREADW)
|
||||
{
|
||||
@@ -2540,9 +2544,11 @@ int
|
||||
devGpibLib_wfGpibWork(pdpvt)
|
||||
struct gpibDpvt *pdpvt;
|
||||
{
|
||||
int OperationStatus;
|
||||
struct waveformRecord *pwf= ((struct waveformRecord *)(pdpvt->precord));
|
||||
struct gpibCmd *pCmd;
|
||||
struct devGpibParmBlock *parmBlock;
|
||||
short ibnode = pdpvt->head.device;
|
||||
|
||||
parmBlock = (struct devGpibParmBlock *)(((gDset*)(pwf->dset))->funPtr[pwf->dset->number]);
|
||||
|
||||
@@ -2553,31 +2559,60 @@ struct gpibDpvt *pdpvt;
|
||||
if(*(parmBlock->debugFlag))
|
||||
printf("devGpibLib_wfGpibWork: starting ...command type = %d\n",pCmd->type);
|
||||
|
||||
if (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR)
|
||||
{
|
||||
devGpibLib_setPvSevr(pwf,READ_ALARM,VALID_ALARM);
|
||||
|
||||
#if 1
|
||||
RegisterProcessCallback(&pdpvt->head.callback, priorityLow, pdpvt);
|
||||
#else
|
||||
pdpvt->head.header.callback.callback = devGpibLib_processCallback;
|
||||
pdpvt->head.header.callback.priority = priorityLow;
|
||||
callbackRequest(&pdpvt->head.header.callback);
|
||||
#endif
|
||||
/**** Handle writes internally... the generic routine will not work ****/
|
||||
if (pCmd->type == GPIBWRITE)
|
||||
{
|
||||
/*
|
||||
* check to see if this node has timed out within last 10 sec
|
||||
*/
|
||||
if(tickGet() < (pdpvt->phwpvt->tmoVal + parmBlock->timeWindow) )
|
||||
{
|
||||
if (*parmBlock->debugFlag)
|
||||
printf("devGpibLib_xxGpibWork(): timeout flush\n");
|
||||
|
||||
OperationStatus = ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
OperationStatus = (*(drvGpib.writeIb))(pdpvt->head.pibLink,
|
||||
ibnode, pdpvt->msg, pCmd->msgLen, pdpvt->head.dmaTimeout);
|
||||
|
||||
if(*parmBlock->debugFlag)
|
||||
printf("devGpibLib_xxGpibWork : done, status = %d\n",OperationStatus);
|
||||
|
||||
/* if error occurrs then mark it with time */
|
||||
if(OperationStatus == ERROR)
|
||||
{
|
||||
(pdpvt->phwpvt->tmoCount)++; /* count timeouts */
|
||||
pdpvt->phwpvt->tmoVal = tickGet(); /* set last timeout time */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OperationStatus = devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1);
|
||||
}
|
||||
|
||||
if (OperationStatus == ERROR)
|
||||
{
|
||||
devGpibLib_setPvSevr(pwf,READ_ALARM,VALID_ALARM);
|
||||
RegisterProcessCallback(&pdpvt->head.callback, priorityLow, pdpvt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pCmd->type != GPIBREADW)
|
||||
devGpibLib_wfGpibFinish(pdpvt); /* If not waiting on SRQ, finish */
|
||||
else
|
||||
{
|
||||
if (*(parmBlock->debugFlag) || ibSrqDebug)
|
||||
printf("%s: marking srq Handler for READW operation\n", parmBlock->name);
|
||||
pdpvt->phwpvt->srqCallback = (int (*)())(((gDset*)(pwf->dset))->funPtr[pwf->dset->number + 2]);
|
||||
pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */
|
||||
return(BUSY); /* indicate device still in use */
|
||||
else
|
||||
{
|
||||
if (*(parmBlock->debugFlag) || ibSrqDebug)
|
||||
printf("%s: marking srq Handler for READW operation\n", parmBlock->name);
|
||||
pdpvt->phwpvt->srqCallback = (int (*)())(((gDset*)(pwf->dset))->funPtr[pwf->dset->number + 2]);
|
||||
pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */
|
||||
return(BUSY); /* indicate device still in use */
|
||||
}
|
||||
}
|
||||
}
|
||||
return(IDLE); /* indicate device is now idle */
|
||||
}
|
||||
|
||||
@@ -2608,13 +2643,7 @@ int srqStatus;
|
||||
{
|
||||
devGpibLib_setPvSevr(pwf,READ_ALARM,VALID_ALARM);
|
||||
|
||||
#if 1
|
||||
RegisterProcessCallback(&pdpvt->head.callback, priorityLow, pdpvt);
|
||||
#else
|
||||
pdpvt->head.header.callback.callback = devGpibLib_processCallback;
|
||||
pdpvt->head.header.callback.priority = priorityLow;
|
||||
callbackRequest(&pdpvt->head.header.callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
devGpibLib_wfGpibFinish(pdpvt); /* and finish the processing */
|
||||
@@ -2651,13 +2680,7 @@ struct gpibDpvt *pdpvt;
|
||||
devGpibLib_setPvSevr(pwf,READ_ALARM,VALID_ALARM);
|
||||
}
|
||||
|
||||
#if 1
|
||||
RegisterProcessCallback(&pdpvt->head.callback, priorityLow, pdpvt);
|
||||
#else
|
||||
pdpvt->head.header.callback.callback = devGpibLib_processCallback;
|
||||
pdpvt->head.header.callback.priority = priorityLow;
|
||||
callbackRequest(&pdpvt->head.header.callback);
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -115,9 +115,9 @@ static long bi_ioinfo(
|
||||
|
||||
static long read_bi(struct biRecord *pbi)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
struct vmeio *pvmeio;
|
||||
long status;
|
||||
long value;
|
||||
unsigned value;
|
||||
|
||||
|
||||
pvmeio = (struct vmeio *)&(pbi->inp.value);
|
||||
@@ -198,7 +198,7 @@ static long read_mbbi(struct mbbiRecord *pmbbi)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
long status;
|
||||
unsigned long value;
|
||||
unsigned value;
|
||||
|
||||
|
||||
pvmeio = (struct vmeio *)&(pmbbi->inp.value);
|
||||
@@ -213,9 +213,9 @@ static long read_mbbi(struct mbbiRecord *pmbbi)
|
||||
|
||||
static long init_mbbo(struct mbboRecord *pmbbo)
|
||||
{
|
||||
unsigned long value;
|
||||
struct vmeio *pvmeio;
|
||||
long status = 0;
|
||||
unsigned value;
|
||||
struct vmeio *pvmeio;
|
||||
long status = 0;
|
||||
|
||||
/* mbbo.out must be an VME_IO */
|
||||
switch (pmbbo->out.type) {
|
||||
@@ -238,9 +238,9 @@ static long init_mbbo(struct mbboRecord *pmbbo)
|
||||
|
||||
static long write_mbbo(struct mbboRecord *pmbbo)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
struct vmeio *pvmeio;
|
||||
long status;
|
||||
unsigned long value;
|
||||
unsigned value;
|
||||
|
||||
|
||||
pvmeio = &(pmbbo->out.value.vmeio);
|
||||
|
||||
1121
src/dev/devMpc.c
Normal file
1121
src/dev/devMpc.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -74,6 +74,8 @@
|
||||
#include <choicePulseDelay.h>
|
||||
#include <pulseTrainRecord.h>
|
||||
#include <choicePulseTrain.h>
|
||||
#include <epicsPrint.h>
|
||||
|
||||
/* Create the dsets for devMz8310 */
|
||||
static long report();
|
||||
static long init();
|
||||
@@ -303,7 +305,7 @@ static long init(after)
|
||||
|
||||
if(after)return(0);
|
||||
if(sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO, 0, (void *)&shortaddr)) {
|
||||
logMsg("devMz8310: sysBusToLocalAdrs failed\n",0);
|
||||
epicsPrintf ("devMz8310: sysBusToLocalAdrs failed\n",0);
|
||||
exit(1);
|
||||
}
|
||||
memset((char *)&mz8310_info[0],0,MAXCARDS*sizeof(struct mz8310_info));
|
||||
@@ -344,7 +346,7 @@ static long init(after)
|
||||
}
|
||||
|
||||
if(rebootHookAdd(Mz8310_shutdown)<0)
|
||||
logMsg("Mz8310_shutdown: reboot hook add failed\n");
|
||||
epicsPrintf ("Mz8310_shutdown: reboot hook add failed\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
static long read_timer();
|
||||
static long write_timer();
|
||||
|
||||
static void localPostEvent (void *pParam);
|
||||
|
||||
struct tmdset {
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
@@ -83,22 +85,22 @@ static double constants[] = {1e3,1e6,1e9,1e12};
|
||||
|
||||
static long read_timer(struct timerRecord *ptimer)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
int source;
|
||||
int ptst;
|
||||
double time_pulse[2]; /* delay and width */
|
||||
double constant;
|
||||
struct vmeio *pvmeio;
|
||||
unsigned source;
|
||||
unsigned ptst;
|
||||
double time_pulse[2]; /* delay and width */
|
||||
double constant;
|
||||
|
||||
/* only supports a one channel VME timer module !!!! */
|
||||
pvmeio = (struct vmeio *)(&ptimer->out.value);
|
||||
|
||||
if (mz8310_one_shot_read(
|
||||
&ptst, /* pre-trigger state */
|
||||
&(time_pulse[0]), /* offset of pulse */
|
||||
&(time_pulse[1]), /* width of pulse */
|
||||
(int)pvmeio->card, /* card number */
|
||||
(int)pvmeio->signal, /* signal number */
|
||||
&source) != 0) { /* trigger source */
|
||||
&ptst, /* pre-trigger state */
|
||||
&(time_pulse[0]), /* offset of pulse */
|
||||
&(time_pulse[1]), /* width of pulse */
|
||||
pvmeio->card, /* card number */
|
||||
pvmeio->signal, /* signal number */
|
||||
&source) != 0) { /* trigger source */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -117,19 +119,36 @@ static long read_timer(struct timerRecord *ptimer)
|
||||
static long write_timer(struct timerRecord *ptimer)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
void (*pCB)(void *);
|
||||
|
||||
/* put the value to the ao driver */
|
||||
pvmeio = (struct vmeio *)(&ptimer->out.value);
|
||||
|
||||
if (ptimer->tevt) {
|
||||
pCB = localPostEvent;
|
||||
}
|
||||
else {
|
||||
pCB = NULL;
|
||||
}
|
||||
|
||||
/* put the value to the ao driver */
|
||||
return mz8310_one_shot(
|
||||
(int)ptimer->ptst, /* pre-trigger state */
|
||||
ptimer->t1dl, /* pulse offset */
|
||||
ptimer->t1wd, /* pulse width */
|
||||
(int)pvmeio->card, /* card number */
|
||||
(int)pvmeio->signal, /* signal number */
|
||||
(int)ptimer->tsrc, /* trigger source */
|
||||
((ptimer->tevt == 0)?0:post_event), /* addr of event post routine */
|
||||
(int)ptimer->tevt); /* event to post on trigger */
|
||||
ptimer->ptst, /* pre-trigger state */
|
||||
ptimer->t1dl, /* pulse offset */
|
||||
ptimer->t1wd, /* pulse width */
|
||||
pvmeio->card, /* card number */
|
||||
pvmeio->signal, /* signal number */
|
||||
ptimer->tsrc, /* trigger source */
|
||||
pCB, /* addr of event post routine */
|
||||
ptimer); /* event to post on trigger */
|
||||
}
|
||||
|
||||
static void localPostEvent (void *pParam)
|
||||
{
|
||||
struct timerRecord *ptimer = pParam;
|
||||
|
||||
if (ptimer->tevt) {
|
||||
post_event (ptimer->tevt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
758
src/dev/devWfPentek4261.c
Normal file
758
src/dev/devWfPentek4261.c
Normal file
@@ -0,0 +1,758 @@
|
||||
|
||||
/*
|
||||
*****************************************************************
|
||||
COPYRIGHT NOTIFICATION
|
||||
*****************************************************************
|
||||
|
||||
THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE,
|
||||
AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE
|
||||
AND IN ALL SOURCE LISTINGS OF THE CODE.
|
||||
|
||||
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
|
||||
|
||||
Argonne National Laboratory (ANL), with facilities in the States of
|
||||
Illinois and Idaho, is owned by the United States Government, and
|
||||
operated by the University of Chicago under provision of a contract
|
||||
with the Department of Energy.
|
||||
|
||||
Portions of this material resulted from work developed under a U.S.
|
||||
Government contract and are subject to the following license: For
|
||||
a period of five years from March 30, 1993, the Government is
|
||||
granted for itself and others acting on its behalf a paid-up,
|
||||
nonexclusive, irrevocable worldwide license in this computer
|
||||
software to reproduce, prepare derivative works, and perform
|
||||
publicly and display publicly. With the approval of DOE, this
|
||||
period may be renewed for two additional five year periods.
|
||||
Following the expiration of this period or periods, the Government
|
||||
is granted for itself and others acting on its behalf, a paid-up,
|
||||
nonexclusive, irrevocable worldwide license in this computer
|
||||
software to reproduce, prepare derivative works, distribute copies
|
||||
to the public, perform publicly and display publicly, and to permit
|
||||
others to do so.
|
||||
|
||||
*****************************************************************
|
||||
DISCLAIMER
|
||||
*****************************************************************
|
||||
|
||||
NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR
|
||||
THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS,
|
||||
MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL
|
||||
LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
|
||||
USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS
|
||||
DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY
|
||||
OWNED RIGHTS.
|
||||
|
||||
*****************************************************************
|
||||
LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY
|
||||
DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
|
||||
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <vme.h>
|
||||
#include <iv.h>
|
||||
#include <vxLib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <intLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <module_types.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <dbDefs.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <dbScan.h>
|
||||
#include <callback.h>
|
||||
#include <waveformRecord.h>
|
||||
|
||||
/*
|
||||
This is waveform record support for the Pentek 4261A 10MHz 12 bit ADC.
|
||||
All scan types are supported, including I/O interrupt scan. The ADC
|
||||
currently supports the edge trigger mode for starting the sampling
|
||||
operation. The ADC is programmed to record an array of samples the
|
||||
same size as the waveform record. The internal or an external clock
|
||||
may be used as the sampling clock. The sampling can be triggered by
|
||||
an external signal, or automatically by record support.
|
||||
|
||||
Using I/O interrupt scanning, the record is processed and the waveform
|
||||
record array is updated each time an external trigger signal is present.
|
||||
With the other scan types, the waveform array is updated each time the
|
||||
record is processed.
|
||||
|
||||
I could not get the continuous bank swapping feature to work with the
|
||||
trigger, I got a glitch in the data approximately 1 us into the sampling.
|
||||
After each round of sampling is done, the buffers are reset.
|
||||
|
||||
The function ConfigurePentekADC() must be run in the
|
||||
vxWorks startup.cmd file for every ADC board present. This function
|
||||
makes it easy to configure jumpers on the ADC and inform EPICS of them.
|
||||
|
||||
parameters:
|
||||
|
||||
ConfigurePentekADC(
|
||||
int card, - the ADC card number in the crate (0=first)
|
||||
unsigned long a16_base, - where the card exists in A16
|
||||
unsigned long a32_base, - where the card exists in A32 (not used)
|
||||
int irq_vector, - interrupt request vector number
|
||||
int irq_level, - interrupt request level number
|
||||
int word_clock, - the ADC word clock (see 4261 documentation)
|
||||
unsigned long clock_freq - clock frequency (see notes below)
|
||||
)
|
||||
|
||||
Good values to use for configuring the module:
|
||||
A16 base address = 0x0200
|
||||
A32 base address = 0xc0200000 (A32 not used in the support)
|
||||
IRQ vector = 121
|
||||
IRQ level = 3
|
||||
word clock = 32
|
||||
|
||||
The number of samples programed (size of waveform record) must be
|
||||
divisible by the word clock.
|
||||
|
||||
The operating mode the ADC is selected using the input field parm area.
|
||||
The user must supply two option, the clock type and the trigger type,
|
||||
in that order. Here are all the valid parm field entry and what they
|
||||
represent (all are entered as strings without the quotes):
|
||||
|
||||
"x_clock,x_trigger" = external clock and external trigger inputs.
|
||||
"i_clock,x_trigger" = internal clock and external trigger input.
|
||||
"x_clock,i_trigger" = external clock and internal trigger input.
|
||||
"i_clock,i_trigger" = internal clock and internal trigger input.
|
||||
|
||||
If external trigger is selected and scan type is not I/O interrupt scan,
|
||||
then sampling will start on the next external trigger input after device
|
||||
support completes.
|
||||
|
||||
If internal trigger is selected, the sampling will be started by software
|
||||
at the end of device support. Internal trigger only applied to scan
|
||||
types that are not I/O interrupt scanned.
|
||||
|
||||
Configuration function clock frequency note:
|
||||
The clock frequency specified in the configuration function is only
|
||||
applicable to the internal clock. When the external clock is used,
|
||||
the clock frequency parameter is meaningless, the sampling clock
|
||||
will be the external clock frequency. When the internal clock is
|
||||
used (10MHz), the clock frequency parameter will be the sampling
|
||||
frequency. The 10Mhz internal clock must be divisible by the clock
|
||||
frequency value.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Modify devSup.ascii and do a makesdr. Add devPentekADC
|
||||
device support to the waveform record.
|
||||
|
||||
Running ReportPentekADC() will print a report of configuration for
|
||||
the ADC.
|
||||
|
||||
Waveform data types of long, short, unsigned short, double, and float are
|
||||
supported.
|
||||
*/
|
||||
|
||||
long devWfPentek4261Debug=0;
|
||||
|
||||
#define CMD_ADDED 0
|
||||
#define CMD_DELETED 1
|
||||
|
||||
#define A16_SIZE 256
|
||||
#define A32_SIZE 256
|
||||
#define MAX_CARDS 4
|
||||
#define MAX_FILES_ALLOWED 20
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* IMPORTANT, LOOK HERE: test areas - good ones to use for jumpers */
|
||||
/* They are good setting for the jumpers for the first ADC card,
|
||||
none of these defines are actually used, are they parameters come
|
||||
from the ConfigurePentekADC().
|
||||
*/
|
||||
|
||||
#define A16_BASE 0xffff0200
|
||||
#define A32_BASE 0xc0200000 /* not really used currently */
|
||||
#define IRQ_VECTOR ((unsigned char)121)
|
||||
#define IRQ_LEVEL 3
|
||||
#define WORD_CLOCK 32 /* my default */
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
#define INTERNAL_CLOCK 10000000 /* 10MHz */
|
||||
|
||||
#define SAMPLE_CLOCK_SELECT 0x08
|
||||
#define EXT_TRIGGER_ENABLE 0x04
|
||||
#define RESET_RUN_FF 0x02
|
||||
#define SET_RUN_FF 0x01
|
||||
|
||||
#define START_MODE 0x20
|
||||
|
||||
#define EXTERNAL 0
|
||||
#define INTERNAL 1
|
||||
|
||||
struct card {
|
||||
int in_use;
|
||||
unsigned long a16_base;
|
||||
unsigned long a32_base;
|
||||
int irq_vector;
|
||||
int irq_level;
|
||||
int word_clock;
|
||||
unsigned long clock_freq;
|
||||
int soc;
|
||||
};
|
||||
typedef struct card CARD;
|
||||
|
||||
/* careful here: horrid looking structure -offset and access (rw=read/write) */
|
||||
struct adc {
|
||||
unsigned short ctc0_bs_a; /* 0x00 rw */
|
||||
unsigned short ctc1_bs_b; /* 0x02 rw */
|
||||
unsigned short ctc2_clock_div; /* 0x04 rw */
|
||||
unsigned short ctc_control; /*c0x06 rw */ /*char a;*/ short junk1[0x04];
|
||||
unsigned short int_id_status; /*c0x10 rw */ /*char b;*/
|
||||
unsigned short int_mask; /*c0x12 rw */ /*char c;*/
|
||||
unsigned short command; /*c0x14 rw */ /*char d;*/
|
||||
unsigned short trigger; /*c0x16 rw */ /*char e;*/
|
||||
unsigned short reserved; /* 0x18 -- */
|
||||
unsigned short tag_cmd; /*c0x1a rw */ /*char f;*/
|
||||
unsigned short tag_data; /* 0x1c rw */
|
||||
unsigned short int_status; /*c0x1e r- */ /*char g;*/ char junk2[0x10];
|
||||
unsigned short vme_fifo; /* 0x30 rw */
|
||||
};
|
||||
typedef struct adc ADC;
|
||||
|
||||
struct pvt_area {
|
||||
CALLBACK callback;
|
||||
int clock_mode;
|
||||
int trigger_mode;
|
||||
int last_int_status;
|
||||
int last_status;
|
||||
volatile ADC* adc_regs;
|
||||
unsigned short div;
|
||||
int card;
|
||||
int file_count;
|
||||
unsigned long total_count;
|
||||
};
|
||||
typedef struct pvt_area PVT_AREA;
|
||||
|
||||
static long dev_report(int level);
|
||||
static long dev_init(int after);
|
||||
static long dev_init_rec(struct waveformRecord* pr);
|
||||
static long dev_ioint_info(int cmd,struct waveformRecord* pr,IOSCANPVT* iopvt);
|
||||
static long dev_read(struct waveformRecord* pr);
|
||||
static long dev_complete_read(struct waveformRecord* pr);
|
||||
static long dev_other_read(struct waveformRecord* pr);
|
||||
static void irq_func(void*);
|
||||
static int full_reset(PVT_AREA* pvt);
|
||||
static int buffer_reset(PVT_AREA* pvt);
|
||||
static long setup(PVT_AREA* pvt);
|
||||
|
||||
void ConfigurePentekADC(int,unsigned long,unsigned long,int,int,int,unsigned long);
|
||||
|
||||
/* generic structure for device support */
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_write;
|
||||
DEVSUPFUN conv;
|
||||
} ADC_DSET;
|
||||
|
||||
ADC_DSET devWfPentek4261=
|
||||
{6,dev_report,dev_init,dev_init_rec,dev_ioint_info,dev_read,NULL};
|
||||
|
||||
static IOSCANPVT ioscanpvt;
|
||||
static CARD** cards=0;
|
||||
|
||||
static void callback(CALLBACK* cback)
|
||||
{
|
||||
struct dbCommon* pc;
|
||||
struct rset *prset;
|
||||
|
||||
callbackGetUser(pc,cback);
|
||||
prset=(struct rset *)(pc->rset);
|
||||
|
||||
/* process the record */
|
||||
dbScanLock(pc);
|
||||
(*prset->process)(pc);
|
||||
dbScanUnlock(pc);
|
||||
}
|
||||
|
||||
static long dev_report(int level)
|
||||
{
|
||||
int i;
|
||||
volatile ADC* adc_regs;
|
||||
|
||||
if(cards==0)
|
||||
printf("No Pentek ADC cards configured in system\n");
|
||||
else
|
||||
{
|
||||
for(i=0;i<MAX_CARDS;i++)
|
||||
{
|
||||
if(cards[i]!=0)
|
||||
{
|
||||
adc_regs=(ADC*)(i*A16_SIZE+cards[i]->a16_base);
|
||||
|
||||
printf("Pentek 4261A ADC card %d information:\n",i);
|
||||
printf(" a16 base=%8.8x",cards[i]->a16_base);
|
||||
printf(" a32 base=%8.8x\n",cards[i]->a32_base);
|
||||
printf(" irq vector=%d",cards[i]->irq_vector);
|
||||
printf(" irq level=%d\n",cards[i]->irq_level);
|
||||
printf(" word clock=%d",cards[i]->word_clock);
|
||||
printf(" clock frequency=%ld\n",cards[i]->clock_freq);
|
||||
|
||||
printf(" status=%4.4x\n", adc_regs->int_id_status);
|
||||
printf(" int mask=%4.4x\n", adc_regs->int_mask);
|
||||
printf(" command=%4.4x\n", adc_regs->command);
|
||||
printf(" trigger=%4.4x\n", adc_regs->trigger);
|
||||
printf(" int status=%4.4x\n", adc_regs->int_status);
|
||||
}
|
||||
else
|
||||
printf("Pentek 4261A ADC card %d not installed\n",i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dev_init(int after)
|
||||
{
|
||||
if(after) return(0);
|
||||
scanIoInit(&ioscanpvt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dev_init_rec(struct waveformRecord* pr)
|
||||
{
|
||||
volatile ADC* adc_regs;
|
||||
PVT_AREA* pvt;
|
||||
struct vmeio *pvmeio = (struct vmeio *)&(pr->inp.value);
|
||||
char *clock_type,*trigger_type;
|
||||
char parm[40];
|
||||
char** save_area=NULL;
|
||||
|
||||
if(pr->inp.type != VME_IO)
|
||||
{
|
||||
recGblRecordError(S_db_badField,(void *)pr,
|
||||
"devPentekADC (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
if(cards[pvmeio->card]==0)
|
||||
{
|
||||
recGblRecordError(S_dev_badCard,(void *)pr,
|
||||
"devPentekADC (init_record) Card not Configured!");
|
||||
return(S_dev_badCard);
|
||||
}
|
||||
if(cards[pvmeio->card]->in_use==1)
|
||||
{
|
||||
recGblRecordError(S_dev_badCard,(void *)pr,
|
||||
"devPentekADC (init_record) Card already in use");
|
||||
return(S_dev_badCard);
|
||||
}
|
||||
if(pr->nelm%cards[pvmeio->card]->word_clock!=0)
|
||||
{
|
||||
recGblRecordError(S_db_badField, (void *)pr,
|
||||
"devPentekADC (init_record) num of elements must be divisible by the word clock");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
pvt=(PVT_AREA*)malloc(sizeof(PVT_AREA));
|
||||
cards[pvmeio->card]->in_use=1;
|
||||
strcpy(parm,pvmeio->parm);
|
||||
|
||||
if((clock_type=strtok_r(parm,",",save_area))==NULL)
|
||||
{
|
||||
printf("Clock type parameter missing from parm field\n");
|
||||
printf(" Defaulting to i_clock,i_trigger (internal clock/trigger)\n");
|
||||
clock_type="i_clock";
|
||||
trigger_type="i_trigger";
|
||||
}
|
||||
else if((trigger_type=strtok_r(NULL,",",save_area))==NULL)
|
||||
{
|
||||
printf("Triggert type parameter missing from parm field\n");
|
||||
printf(" Defaulting to i_trigger (internal trigger)\n");
|
||||
trigger_type="i_trigger";
|
||||
}
|
||||
|
||||
if( strcmp(clock_type,"i_clock")==0 )
|
||||
pvt->clock_mode=INTERNAL;
|
||||
else if( strcmp(clock_type,"x_clock")==0 )
|
||||
pvt->clock_mode=EXTERNAL;
|
||||
else
|
||||
{
|
||||
printf("Invalid parm for clock type, must be i_clock or x_clock\n");
|
||||
pvt->clock_mode=INTERNAL;
|
||||
}
|
||||
|
||||
if( strcmp(trigger_type,"i_trigger")==0 )
|
||||
pvt->trigger_mode=INTERNAL;
|
||||
else if( strcmp(trigger_type,"x_trigger")==0 )
|
||||
pvt->trigger_mode=EXTERNAL;
|
||||
else
|
||||
{
|
||||
printf("Invalid parm for clock type, must be i_trigger or x_trigger\n");
|
||||
pvt->trigger_mode=INTERNAL;
|
||||
}
|
||||
|
||||
adc_regs=(ADC*)(pvmeio->card*A16_SIZE+cards[pvmeio->card]->a16_base);
|
||||
|
||||
callbackSetCallback(callback,&pvt->callback);
|
||||
callbackSetPriority(pr->prio,&pvt->callback);
|
||||
callbackSetUser(pr,&pvt->callback);
|
||||
|
||||
pvt->adc_regs=adc_regs;
|
||||
pvt->card=pvmeio->card;
|
||||
pvt->file_count=0;
|
||||
pr->dpvt=(void*)pvt;
|
||||
|
||||
/* program number of samples and sample clock */
|
||||
pvt->div=pr->nelm/cards[pvmeio->card]->word_clock;
|
||||
|
||||
/* install the interrupt handler */
|
||||
if(intConnect(INUM_TO_IVEC(cards[pvmeio->card]->irq_vector),
|
||||
(VOIDFUNCPTR)irq_func, (int)pr)!=OK)
|
||||
{ printf("intConnect failed\n"); return -1; }
|
||||
|
||||
sysIntEnable(cards[pvmeio->card]->irq_level);
|
||||
full_reset(pvt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buffer_reset(PVT_AREA* pvt)
|
||||
{
|
||||
pvt->adc_regs->command=0x00; /* reset the card */
|
||||
pvt->adc_regs->command=0x90; /* vme enable, no reset mode */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int full_reset(PVT_AREA* pvt)
|
||||
{
|
||||
unsigned long clock_div,clock_freq,sample_freq;
|
||||
unsigned short clock_div_short;
|
||||
unsigned char trig;
|
||||
|
||||
buffer_reset(pvt);
|
||||
|
||||
/* auto arm mode not enabled */
|
||||
trig=0x20; /* positive going edge */
|
||||
|
||||
if(pvt->clock_mode==EXTERNAL) trig|=0x08; /* ext clock */
|
||||
|
||||
pvt->adc_regs->trigger=trig; /* set the trigger reg */
|
||||
pvt->adc_regs->int_id_status=cards[pvt->card]->irq_vector;
|
||||
|
||||
/* program counter for bank A */
|
||||
pvt->adc_regs->ctc_control=0x00|0x30|0x04; /* CTC-0,LSB-MSB,mode */
|
||||
pvt->adc_regs->ctc0_bs_a=(unsigned short)(pvt->div&0x00ff);
|
||||
pvt->adc_regs->ctc0_bs_a=(unsigned short)(pvt->div>>8);
|
||||
/* program counter for bank B */
|
||||
pvt->adc_regs->ctc_control=0x40|0x30|0x04; /* CTC-1,LSB-MSB,mode */
|
||||
pvt->adc_regs->ctc1_bs_b=(unsigned short)(pvt->div&0x00ff);
|
||||
pvt->adc_regs->ctc1_bs_b=(unsigned short)(pvt->div>>8);
|
||||
|
||||
/* printf("bank div=%4.4x\n",pvt->div); */
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/*
|
||||
careful here, if changing code to use internal clock, use the
|
||||
code below to program the sample clock divisor, remember that if
|
||||
sample clock divisor is one, then the else portion of the code must
|
||||
be used.
|
||||
|
||||
SampleClock = InputClock / N
|
||||
|
||||
where:
|
||||
N is programmed divisor and 1<=N<=65535
|
||||
InputClock is 10MHz for internal clock or the external clock
|
||||
SampleClock if the effective sampling clock
|
||||
|
||||
We are given SampleClock, and need N, so
|
||||
|
||||
N = InputClock / SampleClock
|
||||
*/
|
||||
|
||||
/* internal clock type uses clock_freq from config as sample clock,
|
||||
external clock does not use clock divisor */
|
||||
|
||||
if(pvt->clock_mode==INTERNAL) /* internal clock */
|
||||
{
|
||||
clock_freq=INTERNAL_CLOCK;
|
||||
sample_freq=cards[pvt->card]->clock_freq;
|
||||
}
|
||||
else
|
||||
{
|
||||
clock_freq = cards[pvt->card]->clock_freq;
|
||||
sample_freq = clock_freq;
|
||||
}
|
||||
|
||||
if(clock_freq==sample_freq)
|
||||
{
|
||||
/* if clock divisor of one is to be used (10MHz) */
|
||||
pvt->adc_regs->ctc_control=0x80|0x10; /* CTC-2, LSB, mode 0 */
|
||||
}
|
||||
else
|
||||
{
|
||||
clock_div=clock_freq/sample_freq;
|
||||
/* printf("clock div=%8.8x\n",clock_div); */
|
||||
|
||||
if(clock_div>=1 && clock_div<=65535)
|
||||
{
|
||||
clock_div_short = clock_div;
|
||||
/* if clock divisor used, sample rate */
|
||||
pvt->adc_regs->ctc_control=0x80|0x30|0x04; /* CTC-2,LSB-MSB,mode */
|
||||
pvt->adc_regs->ctc2_clock_div=(clock_div_short&0x00ff);
|
||||
pvt->adc_regs->ctc2_clock_div=(clock_div_short>>8);
|
||||
}
|
||||
else
|
||||
{
|
||||
pvt->adc_regs->ctc_control=0x80|0x10; /* CTC-2, LSB, mode 0 */
|
||||
printf("Invalid clock/sample frequency: %ld/%ld\n",
|
||||
clock_freq,sample_freq);
|
||||
}
|
||||
}
|
||||
/* -------------------------------------------------------------- */
|
||||
|
||||
/* start mode = off at this point */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dev_ioint_info(int cmd,struct waveformRecord* pr,IOSCANPVT* iopvt)
|
||||
{
|
||||
PVT_AREA* pvt = (PVT_AREA*)pr->dpvt;
|
||||
|
||||
pr->pact=0;
|
||||
|
||||
if(cmd==CMD_ADDED)
|
||||
setup(pvt);
|
||||
else /* CMD_DELETED */
|
||||
buffer_reset(pvt); /* ensure that we are in a good state */
|
||||
|
||||
*iopvt=ioscanpvt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dev_read(struct waveformRecord* pr)
|
||||
{
|
||||
long rc;
|
||||
PVT_AREA* pvt = (PVT_AREA*)pr->dpvt;
|
||||
|
||||
if(pr->scan==SCAN_IO_EVENT)
|
||||
{
|
||||
pvt->adc_regs->command|=0x20; /* start mode */
|
||||
rc=dev_complete_read(pr);
|
||||
setup(pvt);
|
||||
}
|
||||
else
|
||||
rc=dev_other_read(pr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long setup(PVT_AREA* pvt)
|
||||
{
|
||||
unsigned char trig;
|
||||
volatile unsigned char istat;
|
||||
|
||||
buffer_reset(pvt);
|
||||
trig=pvt->adc_regs->trigger&0xf8; /* clear run FF,trigger */
|
||||
trig|=0x44; /* external trigger on, auto arm mode */
|
||||
istat=pvt->adc_regs->int_status; /* read int status */
|
||||
pvt->adc_regs->int_mask=0x10; /* bank swap interrupt */
|
||||
pvt->adc_regs->trigger=trig|0x02; /* trigger mode + reset run FF */
|
||||
pvt->adc_regs->command|=0x20; /* start mode */
|
||||
pvt->adc_regs->trigger=trig; /* trigger mode */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dev_other_read(struct waveformRecord* pr)
|
||||
{
|
||||
PVT_AREA* pvt = (PVT_AREA*)pr->dpvt;
|
||||
long rc=0;
|
||||
|
||||
if(pr->pact==TRUE)
|
||||
{
|
||||
/* i/o complete */
|
||||
|
||||
/* interrupt handler shut down everything already */
|
||||
pvt->adc_regs->command|=0x20; /* start mode on */
|
||||
rc=dev_complete_read(pr); /* process data in buffer */
|
||||
pvt->adc_regs->command&=~0x20; /* start mode off */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* start the i/o */
|
||||
|
||||
/* this sucks, with internal mode trigger, the board glitch
|
||||
every so often, I cannot get it to work correctly, so do full reset */
|
||||
if(pvt->trigger_mode==INTERNAL) full_reset(pvt);
|
||||
|
||||
callbackSetPriority(pr->prio,&pvt->callback);
|
||||
setup(pvt);
|
||||
pr->pact=TRUE;
|
||||
|
||||
if(pvt->trigger_mode==INTERNAL)
|
||||
pvt->adc_regs->trigger|=0x01; /* set run FF */
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long dev_complete_read(struct waveformRecord* pr)
|
||||
{
|
||||
int i;
|
||||
PVT_AREA* pvt = (PVT_AREA*)pr->dpvt;
|
||||
volatile unsigned short* source;
|
||||
volatile unsigned short samples;
|
||||
|
||||
source=&(pvt->adc_regs->vme_fifo);
|
||||
i=0;
|
||||
|
||||
switch(pr->ftvl)
|
||||
{
|
||||
case DBF_FLOAT:
|
||||
{
|
||||
float* f_thing = (float*)pr->bptr;
|
||||
|
||||
for(i=0;i<pr->nelm;i++)
|
||||
{
|
||||
samples=pvt->adc_regs->vme_fifo;
|
||||
f_thing[i]=(float)(((short)samples)>>4);
|
||||
}
|
||||
pr->nord=i;
|
||||
break;
|
||||
}
|
||||
case DBF_DOUBLE:
|
||||
{
|
||||
double* d_thing = (double*)pr->bptr;
|
||||
|
||||
for(i=0;i<pr->nelm;i++)
|
||||
{
|
||||
samples=pvt->adc_regs->vme_fifo;
|
||||
d_thing[i]=(double)(((short)samples)>>4);
|
||||
}
|
||||
pr->nord=i;
|
||||
break;
|
||||
}
|
||||
case DBF_ULONG:
|
||||
{
|
||||
unsigned long* ul_thing = (unsigned long*)pr->bptr;
|
||||
|
||||
for(i=0;i<pr->nelm;i++)
|
||||
{
|
||||
samples=pvt->adc_regs->vme_fifo;
|
||||
ul_thing[i]=(unsigned long)((samples>>4)&0x0fff);
|
||||
}
|
||||
pr->nord=i;
|
||||
break;
|
||||
}
|
||||
case DBF_LONG:
|
||||
{
|
||||
long* l_thing = (long*)pr->bptr;
|
||||
|
||||
for(i=0;i<pr->nelm;i++)
|
||||
{
|
||||
samples=pvt->adc_regs->vme_fifo;
|
||||
l_thing[i]=(long)(((long)samples)>>4);
|
||||
}
|
||||
pr->nord=i;
|
||||
break;
|
||||
}
|
||||
case DBF_USHORT:
|
||||
{
|
||||
unsigned short* s_thing = (unsigned short*)pr->bptr;
|
||||
|
||||
for(i=0;i<pr->nelm;i++)
|
||||
{
|
||||
samples=pvt->adc_regs->vme_fifo;
|
||||
s_thing[i]=(unsigned short)((samples>>4)&0x0fff);
|
||||
}
|
||||
pr->nord=i;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("devPentek4261: Invalid data type\n");
|
||||
case DBF_SHORT:
|
||||
{
|
||||
short* ss_thing = (unsigned short*)pr->bptr;
|
||||
|
||||
for(i=0;i<pr->nelm;i++)
|
||||
{
|
||||
samples=pvt->adc_regs->vme_fifo;
|
||||
ss_thing[i]=(short)(((short)(samples))>>4);
|
||||
}
|
||||
pr->nord=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear remaining samples if any */
|
||||
while(pvt->adc_regs->int_id_status&0x80)
|
||||
samples=pvt->adc_regs->vme_fifo;
|
||||
|
||||
/* pr->nelm, pr->bptr, &(pr->nord) */ /* three important fields */
|
||||
pr->udf=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* IRQ under vxWorks */
|
||||
static void irq_func(void* v)
|
||||
{
|
||||
struct waveformRecord* pr = (struct waveformRecord*)v;
|
||||
PVT_AREA* pvt = (PVT_AREA*)pr->dpvt;
|
||||
CALLBACK* cb = (CALLBACK*)pvt;
|
||||
unsigned char trig;
|
||||
|
||||
pvt->last_int_status=pvt->adc_regs->int_status; /* read status */
|
||||
|
||||
/* logMsg("in irq_func\n"); */
|
||||
/* if(pvt->last_int_status&0x02) logMsg("Overrun error\n"); */
|
||||
|
||||
pvt->adc_regs->command&=~0x20; /* start mode off - freeze all */
|
||||
pvt->adc_regs->int_mask=0x00; /* interrupts off */
|
||||
trig=pvt->adc_regs->trigger&0xfc; /* clear run FF bits */
|
||||
pvt->adc_regs->trigger=trig; /* clear run FF bits */
|
||||
pvt->adc_regs->trigger=trig|0x02; /* force reset run FF */
|
||||
|
||||
if(pr->scan==SCAN_IO_EVENT)
|
||||
scanIoRequest(ioscanpvt); /* scan EPICS record */
|
||||
else
|
||||
callbackRequest(cb);
|
||||
}
|
||||
|
||||
void ReportPentekADC() { dev_report(0); }
|
||||
|
||||
void ConfigurePentekADC( int card,
|
||||
unsigned long a16_base, unsigned long a32_base,
|
||||
int irq_vector, int irq_level,
|
||||
int word_clock, unsigned long clock_freq)
|
||||
{
|
||||
unsigned short dummy;
|
||||
|
||||
if(cards==0)
|
||||
{
|
||||
cards=(CARD**)malloc(sizeof(CARD*)*MAX_CARDS);
|
||||
memset((char*)cards,0,sizeof(CARD*)*MAX_CARDS);
|
||||
}
|
||||
|
||||
if(cards[card]!=0) printf("Overriding previous configuration\n");
|
||||
else cards[card]=(CARD*)malloc(sizeof(CARD));
|
||||
|
||||
cards[card]->in_use=0;
|
||||
if( sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,(char*)a16_base,(char**)&(cards[card]->a16_base))!=OK)
|
||||
{
|
||||
printf(" a16 base could not be converted\n");
|
||||
}
|
||||
if( sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA,(char*)a32_base,(char**)&(cards[card]->a32_base))!=OK)
|
||||
{
|
||||
printf(" a32 base could not be converted\n");
|
||||
}
|
||||
cards[card]->irq_vector=irq_vector;
|
||||
cards[card]->irq_level=irq_level;
|
||||
cards[card]->word_clock=word_clock;
|
||||
cards[card]->clock_freq=clock_freq;
|
||||
|
||||
if(vxMemProbe((char*)cards[card]->a16_base,READ,
|
||||
sizeof(unsigned short),(char*)&dummy)!=OK)
|
||||
{
|
||||
/* card not really present */
|
||||
cards[card]->in_use=1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,27 @@ include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_INCLUDES = -I../../drv
|
||||
|
||||
SRCS.c = \
|
||||
../devAnalytekGpib.c ../devXxDg535Gpib.c ../devBBInteract.c \
|
||||
../devGpibInteract.c ../devXxSr620Gpib.c ../devK486Gpib.c \
|
||||
../devXxK196Gpib.c ../devXxDc5009Gpib.c ../devXxK263Gpib.c \
|
||||
../devXxSkeletonGpib.c
|
||||
SRCS.c += ../devAnalytekGpib.c
|
||||
SRCS.c += ../devXxDg535Gpib.c
|
||||
SRCS.c += ../devBBInteract.c
|
||||
SRCS.c += ../devGpibInteract.c
|
||||
SRCS.c += ../devXxSr620Gpib.c
|
||||
SRCS.c += ../devK486Gpib.c
|
||||
SRCS.c += ../devXxK196Gpib.c
|
||||
SRCS.c += ../devXxDc5009Gpib.c
|
||||
SRCS.c += ../devXxK263Gpib.c
|
||||
SRCS.c += ../devXxSkeletonGpib.c
|
||||
|
||||
OBJS = \
|
||||
devAnalytekGpib.o devXxDg535Gpib.o devBBInteract.o \
|
||||
devGpibInteract.o devXxSr620Gpib.o devK486Gpib.o \
|
||||
devXxK196Gpib.o devXxDc5009Gpib.o devXxK263Gpib.o \
|
||||
devXxSkeletonGpib.o
|
||||
OBJS += devAnalytekGpib.o
|
||||
OBJS += devXxDg535Gpib.o
|
||||
OBJS += devBBInteract.o
|
||||
OBJS += devGpibInteract.o
|
||||
OBJS += devXxSr620Gpib.o
|
||||
OBJS += devK486Gpib.o
|
||||
OBJS += devXxK196Gpib.o
|
||||
OBJS += devXxDc5009Gpib.o
|
||||
OBJS += devXxK263Gpib.o
|
||||
OBJS += devXxSkeletonGpib.o
|
||||
|
||||
PROD = devLibOpt $(OBJS)
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Lowest Level Directroy Makefile
|
||||
# by Janet Anderson
|
||||
#
|
||||
# $Log$
|
||||
#
|
||||
|
||||
EPICS=../../..
|
||||
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
include $(EPICS)/config/RULES_ARCHS
|
||||
DIRS = ansi old combine
|
||||
|
||||
include $(EPICS)/config/RULES_DIRS
|
||||
|
||||
|
||||
@@ -4,75 +4,74 @@ include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_CFLAGS = -fshared-data -fvolatile -mnobitfield -traditional
|
||||
|
||||
SRCS.c = \
|
||||
../module_types.c\
|
||||
../drvXy010.c\
|
||||
../drvAb.c\
|
||||
../drvBb902.c\
|
||||
../drvBb910.c\
|
||||
../drvCompuSm.c\
|
||||
../drvDvx.c\
|
||||
../drvMz8310.c\
|
||||
../drvOms.c\
|
||||
../drvStc.c\
|
||||
../drvTime.c\
|
||||
../drvVmi4100.c\
|
||||
../drvXy210.c\
|
||||
../drvXy220.c\
|
||||
../drvXy240.c\
|
||||
../drvXy566.c\
|
||||
../drvAt5Vxi.c\
|
||||
../drvHp1404a.c\
|
||||
../drvEpvxi.c\
|
||||
../drvEpvxiMsg.c\
|
||||
../drvBitBus.c\
|
||||
../drvGpib.c\
|
||||
../drvMsg.c\
|
||||
../drvBB232.c\
|
||||
../drvHpe1368a.c\
|
||||
../drvHpe1445a.c\
|
||||
../drvKscV215.c\
|
||||
../drvComet.c\
|
||||
../drvJgvtr1.c\
|
||||
../drvFp.c\
|
||||
../drvFpm.c
|
||||
SRCS.c += ../module_types.c
|
||||
SRCS.c += ../drvAb.c
|
||||
SRCS.c += ../drvAt5Vxi.c
|
||||
SRCS.c += ../drvBB232.c
|
||||
SRCS.c += ../drvBb902.c
|
||||
SRCS.c += ../drvBb910.c
|
||||
SRCS.c += ../drvBitBus.c
|
||||
# SRCS.c += ../drvCaenV265.c
|
||||
SRCS.c += ../drvComet.c
|
||||
SRCS.c += ../drvCompuSm.c
|
||||
SRCS.c += ../drvDvx.c
|
||||
SRCS.c += ../drvEpvxi.c
|
||||
SRCS.c += ../drvEpvxiMsg.c
|
||||
SRCS.c += ../drvFp.c
|
||||
SRCS.c += ../drvFpm.c
|
||||
SRCS.c += ../drvGpib.c
|
||||
SRCS.c += ../drvHp1404a.c
|
||||
SRCS.c += ../drvHpe1368a.c
|
||||
SRCS.c += ../drvHpe1445a.c
|
||||
SRCS.c += ../drvJgvtr1.c
|
||||
SRCS.c += ../drvKscV215.c
|
||||
SRCS.c += ../drvMsg.c
|
||||
SRCS.c += ../drvMz8310.c
|
||||
SRCS.c += ../drvOms.c
|
||||
SRCS.c += ../drvStc.c
|
||||
SRCS.c += ../drvTime.c
|
||||
# SRCS.c += ../drvTranServ.c
|
||||
SRCS.c += ../drvVmi4100.c
|
||||
SRCS.c += ../drvXy010.c
|
||||
SRCS.c += ../drvXy210.c
|
||||
SRCS.c += ../drvXy220.c
|
||||
SRCS.c += ../drvXy240.c
|
||||
SRCS.c += ../drvXy566.c
|
||||
|
||||
# ../drvTranServ.c\
|
||||
OBJS += module_types.o
|
||||
OBJS += drvAb.o
|
||||
OBJS += drvAt5Vxi.o
|
||||
OBJS += drvBB232.o
|
||||
OBJS += drvBb902.o
|
||||
OBJS += drvBb910.o
|
||||
OBJS += drvBitBus.o
|
||||
# OBJS += drvCaenV265.o
|
||||
OBJS += drvComet.o
|
||||
OBJS += drvCompuSm.o
|
||||
OBJS += drvDvx.o
|
||||
OBJS += drvEpvxi.o
|
||||
OBJS += drvEpvxiMsg.o
|
||||
OBJS += drvFp.o
|
||||
OBJS += drvFpm.o
|
||||
OBJS += drvGpib.o
|
||||
OBJS += drvHp1404a.o
|
||||
OBJS += drvHpe1368a.o
|
||||
OBJS += drvHpe1445a.o
|
||||
OBJS += drvJgvtr1.o
|
||||
OBJS += drvKscV215.o
|
||||
OBJS += drvMsg.o
|
||||
OBJS += drvMz8310.o
|
||||
OBJS += drvOms.o
|
||||
OBJS += drvStc.o
|
||||
OBJS += drvTime.o
|
||||
# OBJS += drvTranServ.o
|
||||
OBJS += drvVmi4100.o
|
||||
OBJS += drvXy010.o
|
||||
OBJS += drvXy210.o
|
||||
OBJS += drvXy220.o
|
||||
OBJS += drvXy240.o
|
||||
OBJS += drvXy566.o
|
||||
|
||||
OBJS = \
|
||||
module_types.o\
|
||||
drvXy010.o\
|
||||
drvAb.o\
|
||||
drvBb902.o\
|
||||
drvBb910.o\
|
||||
drvCompuSm.o\
|
||||
drvDvx.o\
|
||||
drvMz8310.o\
|
||||
drvOms.o\
|
||||
drvStc.o\
|
||||
drvTime.o\
|
||||
drvVmi4100.o\
|
||||
drvXy210.o\
|
||||
drvXy220.o\
|
||||
drvXy240.o\
|
||||
drvXy566.o\
|
||||
drvAt5Vxi.o\
|
||||
drvHp1404a.o\
|
||||
drvEpvxi.o\
|
||||
drvEpvxiMsg.o\
|
||||
drvBitBus.o\
|
||||
drvGpib.o\
|
||||
drvMsg.o\
|
||||
drvBB232.o\
|
||||
drvHpe1368a.o\
|
||||
drvHpe1445a.o\
|
||||
drvKscV215.o\
|
||||
drvComet.o\
|
||||
drvJgvtr1.o\
|
||||
drvFp.o\
|
||||
drvFpm.o
|
||||
|
||||
# drvTranServ.o\
|
||||
|
||||
PROD = drvSup
|
||||
|
||||
@@ -83,5 +82,4 @@ $(PROD): $(OBJS)
|
||||
$(LINK.c) $@ $(OBJS) $(LDLIBS)
|
||||
|
||||
|
||||
# ../drvCaenV265.c\
|
||||
# drvCaenV265.o\
|
||||
|
||||
|
||||
12
src/drv/ansi/Makefile
Normal file
12
src/drv/ansi/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
EPICS=../../../..
|
||||
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
include $(EPICS)/config/RULES_ARCHS
|
||||
|
||||
40
src/drv/ansi/Makefile.Vx
Normal file
40
src/drv/ansi/Makefile.Vx
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
EPICS = ../../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_CFLAGS = -ansi
|
||||
|
||||
VX_WARN_YES = -Wall -pedantic
|
||||
|
||||
SRCS.c += ../drvAb.c
|
||||
SRCS.c += ../drvAt5Vxi.c
|
||||
SRCS.c += ../drvEpvxi.c
|
||||
SRCS.c += ../drvEpvxiMsg.c
|
||||
SRCS.c += ../drvHp1404a.c
|
||||
SRCS.c += ../drvHpe1368a.c
|
||||
SRCS.c += ../drvHpe1445a.c
|
||||
SRCS.c += ../drvKscV215.c
|
||||
SRCS.c += ../drvMz8310.c
|
||||
SRCS.c += ../drvStc.c
|
||||
SRCS.c += ../drvTime.c
|
||||
# SRCS.c += ../drvCaenV265.c
|
||||
|
||||
TARGETS += drvAb.o
|
||||
TARGETS += drvAt5Vxi.o
|
||||
TARGETS += drvEpvxi.o
|
||||
TARGETS += drvEpvxiMsg.o
|
||||
TARGETS += drvHp1404a.o
|
||||
TARGETS += drvHpe1368a.o
|
||||
TARGETS += drvHpe1445a.o
|
||||
TARGETS += drvKscV215.o
|
||||
TARGETS += drvMz8310.o
|
||||
TARGETS += drvStc.o
|
||||
TARGETS += drvTime.o
|
||||
# TARGETS += drvCaenV265.o
|
||||
|
||||
include $(EPICS)/config/RULES.Vx
|
||||
|
||||
30
src/drv/ansi/VXI_SETUP_README
Normal file
30
src/drv/ansi/VXI_SETUP_README
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
The CPU030 may need to have the nivxi path set correctly:
|
||||
From the vxWorks shell type "vxitedit"
|
||||
take option 2
|
||||
take option 3
|
||||
type list
|
||||
type modify 0
|
||||
type in the correct path when promped
|
||||
(the path should end in nivxi
|
||||
and should traverse the niCpu030
|
||||
directories shipped with the 030
|
||||
ie somethin of the form "???/config/niCPU030/nivxi"
|
||||
type save
|
||||
type exit
|
||||
.
|
||||
.
|
||||
.
|
||||
|
||||
|
||||
You may may need to setup front panel to backplane trigger
|
||||
routing:
|
||||
|
||||
To take a TTL input and map it to VXI backplane ECL trigger 0
|
||||
type in (to the vxWorks shell):
|
||||
|
||||
epvxiRouteTriggerECL(<logical address>, 1, 0)
|
||||
|
||||
where <logical address> specifies the card with the
|
||||
front panel trigger connection.
|
||||
|
||||
1751
src/drv/ansi/drvAb.c
Normal file
1751
src/drv/ansi/drvAb.c
Normal file
File diff suppressed because it is too large
Load Diff
91
src/drv/ansi/drvAb.h
Normal file
91
src/drv/ansi/drvAb.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* drvAb.h */
|
||||
/* header file for the Allen-Bradley Remote Serial IO
|
||||
* This defines interface between driver and device support
|
||||
*
|
||||
* Author: Marty Kraimer
|
||||
* Date: 03-06-95
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* 01 03-06-95 mrk Moved all driver specific code to drvAb.c
|
||||
*/
|
||||
|
||||
#ifndef INCdrvAbh
|
||||
#define INCdrvAbh 1
|
||||
#include "dbScan.h"
|
||||
|
||||
|
||||
/* interface types */
|
||||
typedef enum {typeNotAssigned,typeBi,typeBo,typeBiBo,typeAi,typeAo,typeBt}
|
||||
cardType;
|
||||
/* status values*/
|
||||
typedef enum{abSuccess,abNewCard,abCardConflict,abNoCard,abNotInitialized,
|
||||
abBtqueued,abBusy,abTimeout,abAdapterDown,abFailure} abStatus;
|
||||
extern char **abStatusMessage;
|
||||
|
||||
typedef enum{abBitNotdefined,abBit8,abBit16,abBit32} abNumBits;
|
||||
extern char **abNumBitsMessage;
|
||||
|
||||
/*entry table for dev to drv routines*/
|
||||
typedef struct {
|
||||
abStatus (*registerCard)
|
||||
(unsigned short link,unsigned short adapter, unsigned short card,
|
||||
cardType type, const char *card_name,
|
||||
void (*callback)(void *drvPvt),
|
||||
void **drvPvt);
|
||||
void (*getLocation)
|
||||
(void *drvPvt,
|
||||
unsigned short *link, unsigned short *adapter,unsigned short *card);
|
||||
abStatus (*setNbits)(void *drvPvt, abNumBits nbits);
|
||||
void (*setUserPvt)(void *drvPvt, void *userPvt);
|
||||
void *(*getUserPvt)(void *drvPvt);
|
||||
abStatus (*getStatus)(void *drvPvt);
|
||||
abStatus(*startScan)
|
||||
(void *drvPvt, unsigned short update_rate,
|
||||
unsigned short *pwrite_msg, unsigned short write_msg_len,
|
||||
unsigned short *pread_msg, unsigned short read_msg_len);
|
||||
abStatus(*updateAo)(void *drvPvt);
|
||||
abStatus(*updateBo) (void *drvPvt,unsigned long value,unsigned long mask);
|
||||
abStatus(*readBo) (void *drvPvt,unsigned long *value,unsigned long mask);
|
||||
abStatus(*readBi) (void *drvPvt,unsigned long *value,unsigned long mask);
|
||||
abStatus(*btRead)(void *drvPvt,unsigned short *pread_msg,
|
||||
unsigned short read_msg_len);
|
||||
abStatus(*btWrite)(void *drvPvt,unsigned short *pwrite_msg,
|
||||
unsigned short write_msg_len);
|
||||
abStatus (*adapterStatus)
|
||||
(unsigned short link,unsigned short adapter);
|
||||
abStatus (*cardStatus)
|
||||
(unsigned short link,unsigned short adapter, unsigned short card);
|
||||
}abDrv;
|
||||
|
||||
extern abDrv *pabDrv;
|
||||
|
||||
int ab_reset(void);
|
||||
int ab_reset_link(int link);
|
||||
int abConfigNlinks(int nlinks);
|
||||
int abConfigVme(int link, int base, int vector, int level);
|
||||
int abConfigBaud(int link, int baud);
|
||||
int abConfigScanList(int link, int scan_list_len, char *scan_list);
|
||||
|
||||
#endif /*INCdrvAbh*/
|
||||
1410
src/drv/ansi/drvAt5Vxi.c
Normal file
1410
src/drv/ansi/drvAt5Vxi.c
Normal file
File diff suppressed because it is too large
Load Diff
94
src/drv/ansi/drvAt5Vxi.h
Normal file
94
src/drv/ansi/drvAt5Vxi.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* base/src/drv $Id$ */
|
||||
|
||||
/*
|
||||
*
|
||||
* driver for at5 designed VXI modules
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 11-89
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <dbScan.h>
|
||||
|
||||
typedef long at5VxiStatus;
|
||||
|
||||
at5VxiStatus at5vxi_one_shot(
|
||||
unsigned preset, /* TRUE or COMPLEMENT logic */
|
||||
double edge0_delay, /* sec */
|
||||
double edge1_delay, /* set */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned int_source, /* (FALSE)External/(TRUE)Internal source */
|
||||
void (*event_rtn)(void *pParam), /* subroutine to run on events */
|
||||
void *event_rtn_param/* parameter to pass to above routine */
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_one_shot_read(
|
||||
unsigned *preset, /* TRUE or COMPLEMENT logic */
|
||||
double *edge0_delay, /* sec */
|
||||
double *edge1_delay, /* sec */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned *int_source /* (FALSE)External/(TRUE)Internal src */
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ai_driver(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *prval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ao_driver(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *prval,
|
||||
unsigned short *prbval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ao_read(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *pval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_bi_driver(
|
||||
unsigned card,
|
||||
unsigned long mask,
|
||||
unsigned long *prval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_bo_driver(
|
||||
unsigned card,
|
||||
unsigned long val,
|
||||
unsigned long mask
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_getioscanpvt(
|
||||
unsigned card,
|
||||
IOSCANPVT *scanpvt
|
||||
);
|
||||
|
||||
808
src/drv/ansi/drvCaenV265.c
Normal file
808
src/drv/ansi/drvCaenV265.c
Normal file
@@ -0,0 +1,808 @@
|
||||
/* share/src/drv @(#)drvCaenV265.c 1.1 9/2/94 */
|
||||
/* drvCaenV265.c - Driver/Device Support Routines for CAEN V265
|
||||
*
|
||||
* Author: Jeff Hill (johill@lanl.gov)
|
||||
* Date: 8-11-94
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* MIT Bates Lab
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* ANSI C Includes
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <types.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* vxWorks includes
|
||||
*/
|
||||
#include <vme.h>
|
||||
#include <iv.h>
|
||||
#include <sysLib.h>
|
||||
#include <intLib.h>
|
||||
#include <logLib.h>
|
||||
#include <vxLib.h>
|
||||
#include <rebootLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <wdLib.h>
|
||||
|
||||
/*
|
||||
* EPICS include
|
||||
*/
|
||||
#include <dbDefs.h>
|
||||
#include <dbScan.h>
|
||||
#include <drvSup.h>
|
||||
#include <devSup.h>
|
||||
#include <recSup.h>
|
||||
#include <devLib.h>
|
||||
#include <aiRecord.h>
|
||||
#include <errMdef.h>
|
||||
#include <epicsPrint.h>
|
||||
|
||||
|
||||
/*
|
||||
* base address, base interrupt vector,
|
||||
* number of cards, & interrupt level
|
||||
*/
|
||||
#define CAIN_V265_A24_BASE (0x000000)
|
||||
#define CAIN_V265_INTVEC_BASE (0xA0)
|
||||
#define CAIN_V265_MAX_CARD_COUNT (8)
|
||||
#define CAIN_V265_INT_LEVEL (6)
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* all device registers declared
|
||||
* ANSI C volatile so we dont need to
|
||||
* use the -fvolatile flag (and dont
|
||||
* limit the optimizer)
|
||||
*/
|
||||
typedef volatile int16_t devReg;
|
||||
|
||||
struct caenV265 {
|
||||
devReg csr;
|
||||
devReg clear;
|
||||
devReg DAC;
|
||||
devReg gate;
|
||||
const devReg data;
|
||||
const devReg pad1[(0xf8-0x8)/2];
|
||||
const devReg fixed;
|
||||
const devReg identifier;
|
||||
const devReg version;
|
||||
};
|
||||
#define CAENV265ID 0x0812
|
||||
|
||||
/*
|
||||
* Insert or extract a bit field using the standard
|
||||
* masks and shifts defined below
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
#define INSERT(FIELD,VALUE)\
|
||||
(((VALUE)&(FD_ ## FIELD ## _M))<<(FD_ ## FIELD ## _S))
|
||||
#define EXTRACT(FIELD,VALUE)\
|
||||
( ((VALUE)>>(FD_ ## FIELD ## _S)) &(FD_ ## FIELD ## _M))
|
||||
#else /*__STDC__*/
|
||||
#define INSERT(FIELD,VALUE)\
|
||||
(((VALUE)&(FD_/* */FIELD/* */_M))<<(FD_/* */FIELD/* */_S))
|
||||
#define EXTRACT(FIELD,VALUE)\
|
||||
( ((VALUE)>>(FD_/* */FIELD/* */_S)) &(FD_/* */FIELD/* */_M))
|
||||
#endif /*__STDC__*/
|
||||
|
||||
/*
|
||||
* in the constants below _M is a right justified mask
|
||||
* and _S is a shift required to right justify the field
|
||||
*/
|
||||
|
||||
/*
|
||||
* csr register
|
||||
*/
|
||||
#define FD_FULL_M (0x1)
|
||||
#define FD_FULL_S (14)
|
||||
#define FD_READY_M (0x1)
|
||||
#define FD_READY_S (15)
|
||||
#define FD_BUSY_FULL_M (0x3)
|
||||
#define FD_BUSY_FULL_S (14)
|
||||
#define FD_IVEC_M (0xff)
|
||||
#define FD_IVEC_S (0)
|
||||
#define FD_ILEVEL_M (0x7)
|
||||
#define FD_ILEVEL_S (8)
|
||||
|
||||
/*
|
||||
* series/version register
|
||||
*/
|
||||
#define FD_SERIES_M (0xfff)
|
||||
#define FD_SERIES_S (0)
|
||||
#define FD_VERSION_M (0xf)
|
||||
#define FD_VERSION_S (12)
|
||||
|
||||
/*
|
||||
* data register
|
||||
*/
|
||||
#define FD_CHANNEL_M (0x7)
|
||||
#define FD_CHANNEL_S (13)
|
||||
#define FD_RANGE_M (1)
|
||||
#define FD_RANGE_S (12)
|
||||
#define FD_DATA_M (0xfff)
|
||||
#define FD_DATA_S (0)
|
||||
|
||||
struct channel{
|
||||
int16_t signal;
|
||||
char newData;
|
||||
};
|
||||
|
||||
enum adc_range {adc_12, adc_15, NUMBER_OF_ADC_RANGES};
|
||||
#define NUMBER_OF_SIGNALS 8
|
||||
#define NUMBER_OF_FIFO_ENTRIES (16*NUMBER_OF_SIGNALS*NUMBER_OF_ADC_RANGES)
|
||||
LOCAL struct caenV265Config{
|
||||
struct caenV265 *pCaenV265; /* pointer to the card */
|
||||
struct channel chan[NUMBER_OF_SIGNALS][NUMBER_OF_ADC_RANGES];
|
||||
IOSCANPVT scanpvt;
|
||||
WDOG_ID wdid;
|
||||
}caenV265Info[CAIN_V265_MAX_CARD_COUNT];
|
||||
|
||||
#ifdef __STDC__
|
||||
#define SHOW_OFFSET(STRUCT,FIELD) \
|
||||
printf( "%s.%s is at 0x%X\n", \
|
||||
#STRUCT, \
|
||||
#FIELD, \
|
||||
offsetof(struct STRUCT, FIELD))
|
||||
#endif
|
||||
|
||||
LOCAL void caenV265ISR(unsigned card);
|
||||
LOCAL int caenV265Shutdown(void);
|
||||
LOCAL int caenV265IdTest(struct caenV265 *pCaenV265);
|
||||
int caenV265Test(unsigned card);
|
||||
LOCAL void caenV265ReadData(struct caenV265Config *pCaenV256Config);
|
||||
LOCAL int caenV265TestVal(unsigned card, unsigned dacVal);
|
||||
LOCAL int caenV265IntEnable(unsigned card);
|
||||
|
||||
/*
|
||||
* device support entry table
|
||||
*/
|
||||
LOCAL long caenV265InitRecord(struct aiRecord *pai);
|
||||
LOCAL long caenV265AiRead(struct aiRecord *pai);
|
||||
LOCAL long caenV265SpecialLinconv(struct aiRecord *pai, int after);
|
||||
LOCAL long caenV265GetIoIntInfo(int cmd, struct aiRecord *pai, IOSCANPVT *ppvt);
|
||||
struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;
|
||||
DEVSUPFUN special_linconv;
|
||||
} devCaenV265 ={
|
||||
6,
|
||||
NULL,
|
||||
NULL,
|
||||
caenV265InitRecord,
|
||||
caenV265GetIoIntInfo,
|
||||
caenV265AiRead,
|
||||
caenV265SpecialLinconv};
|
||||
|
||||
/*
|
||||
* driver support entry table
|
||||
*/
|
||||
LOCAL long caenV265Init(void);
|
||||
LOCAL long caenV265IOReport(int level);
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvCaenV265 ={
|
||||
2,
|
||||
caenV265IOReport,
|
||||
caenV265Init};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* verify that register
|
||||
* offsets match the doc.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
void offsettest()
|
||||
{
|
||||
SHOW_OFFSET(caenV265, version);
|
||||
SHOW_OFFSET(caenV265, identifier);
|
||||
SHOW_OFFSET(caenV265, fixed);
|
||||
SHOW_OFFSET(caenV265, data);
|
||||
SHOW_OFFSET(caenV265, gate);
|
||||
SHOW_OFFSET(caenV265, DAC);
|
||||
SHOW_OFFSET(caenV265, clear);
|
||||
SHOW_OFFSET(caenV265, csr);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* caenV265InitRecord()
|
||||
*/
|
||||
LOCAL long caenV265InitRecord(struct aiRecord *pai)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
/* ai.inp must be an VME_IO */
|
||||
switch (pai->inp.type) {
|
||||
case (VME_IO):
|
||||
break;
|
||||
default :
|
||||
recGblRecordError(S_db_badField,(void *)pai,
|
||||
"devAiXy566Se (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad signal or card number
|
||||
*/
|
||||
if ( pvmeio->signal >= NUMBER_OF_SIGNALS ||
|
||||
pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 bad card or signal number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!caenV265Info[pvmeio->card].pCaenV265){
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 card does not exist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
pai->eslo = (pai->eguf-pai->egul)/FD_DATA_M;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265AiRead()
|
||||
*/
|
||||
LOCAL long caenV265AiRead(struct aiRecord *pai)
|
||||
{
|
||||
int16_t value;
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad signal or card number
|
||||
*/
|
||||
if ( pvmeio->signal >= NUMBER_OF_SIGNALS ||
|
||||
pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
|
||||
recGblSetSevr(pai, READ_ALARM, INVALID_ALARM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* uninitialized data?
|
||||
*/
|
||||
if (!caenV265Info[pvmeio->card].chan[pvmeio->signal][adc_12].newData) {
|
||||
recGblSetSevr(pai, READ_ALARM, INVALID_ALARM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
value = caenV265Info[pvmeio->card].chan[pvmeio->signal][adc_12].signal;
|
||||
pai->rval = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265SpecialLinconv()
|
||||
*/
|
||||
LOCAL long caenV265SpecialLinconv(struct aiRecord *pai, int after)
|
||||
{
|
||||
if(!after) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
pai->eslo = (pai->eguf-pai->egul)/FD_DATA_M;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265GetIoIntInfo()
|
||||
*/
|
||||
LOCAL long caenV265GetIoIntInfo(
|
||||
int cmd,
|
||||
struct aiRecord *pai,
|
||||
IOSCANPVT *ppvt)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad card number
|
||||
*/
|
||||
if ( pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
epicsPrintf (
|
||||
"%s.%d:devCaenV265 bad card number %d %s\n",
|
||||
(int)__FILE__,
|
||||
__LINE__,
|
||||
pvmeio->card,
|
||||
(int)pai->name);
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 bad card number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ppvt = &caenV265Info[pvmeio->card].scanpvt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Init()
|
||||
*/
|
||||
LOCAL long caenV265Init(void)
|
||||
{
|
||||
unsigned card;
|
||||
struct caenV265 *pCaenV265;
|
||||
int status;
|
||||
|
||||
status = rebootHookAdd(caenV265Shutdown);
|
||||
if(status){
|
||||
errMessage(S_dev_internal,"reboot hook add failed");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
status = sysBusToLocalAdrs(
|
||||
VME_AM_STD_SUP_DATA,
|
||||
CAIN_V265_A24_BASE,
|
||||
(char **)&pCaenV265);
|
||||
if(status!=OK){
|
||||
errPrintf(
|
||||
S_dev_badA24,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"caenV265Init");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
for(card=0; card<CAIN_V265_MAX_CARD_COUNT; card++, pCaenV265++){
|
||||
unsigned vec;
|
||||
|
||||
if(!caenV265IdTest(pCaenV265)){
|
||||
continue;
|
||||
}
|
||||
|
||||
caenV265Info[card].wdid = wdCreate();
|
||||
if(!caenV265Info[card].wdid){
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* flag that we have found a caen V265
|
||||
*/
|
||||
caenV265Info[card].pCaenV265 = pCaenV265;
|
||||
|
||||
/*
|
||||
* init the EPICS db int event scan block
|
||||
*/
|
||||
scanIoInit(&caenV265Info[card].scanpvt);
|
||||
|
||||
/*
|
||||
* reset the device
|
||||
*/
|
||||
pCaenV265->clear = 0; /* any rw op resets the device */
|
||||
pCaenV265->DAC = 0; /* set test-signal "offset" to zero */
|
||||
|
||||
/*
|
||||
* attach ISR
|
||||
*/
|
||||
vec = CAIN_V265_INTVEC_BASE+card;
|
||||
status = intConnect(
|
||||
INUM_TO_IVEC(vec),
|
||||
caenV265ISR,
|
||||
card);
|
||||
assert(status>=0);
|
||||
|
||||
/*
|
||||
* Enable interrupts
|
||||
*/
|
||||
caenV265IntEnable(card);
|
||||
}
|
||||
status = sysIntEnable(CAIN_V265_INT_LEVEL);
|
||||
assert(status>=0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265ISR()
|
||||
*/
|
||||
LOCAL void caenV265ISR(unsigned card)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned signal;
|
||||
int16_t csr;
|
||||
static unsigned ticks;
|
||||
unsigned newTicks;
|
||||
|
||||
/*
|
||||
* If its full then its more efficient
|
||||
* to read it out without checking
|
||||
* in between each read
|
||||
*/
|
||||
csr = pCaenV265->csr;
|
||||
if (EXTRACT(FULL,csr)) {
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_FIFO_ENTRIES;
|
||||
signal++){
|
||||
|
||||
caenV265ReadData(pCaenV256Config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not full so check to see if its ready before
|
||||
* reading
|
||||
*/
|
||||
while (EXTRACT(READY, csr)) {
|
||||
caenV265ReadData(pCaenV256Config);
|
||||
csr = pCaenV265->csr;
|
||||
}
|
||||
|
||||
/*
|
||||
* limit the EPICS scan rate
|
||||
*/
|
||||
newTicks = tickGet();
|
||||
if(newTicks == ticks){
|
||||
/*
|
||||
* Disable Interrupts
|
||||
*/
|
||||
pCaenV265->csr = 0;
|
||||
|
||||
/*
|
||||
* start a watch dog after one tick
|
||||
* so that we limit the int rate to
|
||||
* the system tick rate.
|
||||
*/
|
||||
wdStart(pCaenV256Config->wdid,
|
||||
1,
|
||||
caenV265IntEnable,
|
||||
card);
|
||||
|
||||
return;
|
||||
}
|
||||
else{
|
||||
ticks = newTicks;
|
||||
}
|
||||
|
||||
/*
|
||||
* tell EPICS to scan on int
|
||||
*/
|
||||
scanIoRequest(&caenV265Info[card].scanpvt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IntEnable
|
||||
*/
|
||||
LOCAL int caenV265IntEnable(unsigned card)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned vec;
|
||||
int16_t newcsr;
|
||||
|
||||
|
||||
vec = CAIN_V265_INTVEC_BASE+card;
|
||||
newcsr = INSERT(IVEC, vec) | INSERT(ILEVEL, CAIN_V265_INT_LEVEL);
|
||||
pCaenV265->csr = newcsr;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265ReadData()
|
||||
*/
|
||||
LOCAL void caenV265ReadData(struct caenV265Config *pCaenV256Config)
|
||||
{
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
int16_t val = pCaenV265->data;
|
||||
int16_t data = EXTRACT(DATA, val);
|
||||
unsigned range = EXTRACT(RANGE, val);
|
||||
unsigned signal = EXTRACT(CHANNEL, val);
|
||||
|
||||
if(range>=NUMBER_OF_ADC_RANGES){
|
||||
epicsPrintf ("caenV265ReadData: bad range number\n");
|
||||
return;
|
||||
}
|
||||
if(signal>=NUMBER_OF_SIGNALS){
|
||||
epicsPrintf ("caenV265ReadData: bad signal number\n");
|
||||
return;
|
||||
}
|
||||
pCaenV256Config->chan[signal][range].signal=data;
|
||||
pCaenV256Config->chan[signal][range].newData=TRUE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IdTest()
|
||||
*/
|
||||
LOCAL int caenV265IdTest(struct caenV265 *pCaenV265)
|
||||
{
|
||||
int status;
|
||||
int16_t id;
|
||||
|
||||
/*
|
||||
* Is a card present
|
||||
*/
|
||||
status = vxMemProbe(
|
||||
(char *)&pCaenV265->identifier,
|
||||
READ,
|
||||
sizeof(id),
|
||||
(char *)&id);
|
||||
if(status!=OK){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the correct type of card present
|
||||
*/
|
||||
if(id!=CAENV265ID){
|
||||
errPrintf(
|
||||
S_dev_wrongDevice,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"caenV265IdTest");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Shutdown()
|
||||
* turns off interrupts so that dont foul up the boot
|
||||
*/
|
||||
LOCAL int caenV265Shutdown(void)
|
||||
{
|
||||
struct caenV265 *pCaenV265;
|
||||
unsigned card;
|
||||
|
||||
for(card=0; card<CAIN_V265_MAX_CARD_COUNT; card++){
|
||||
pCaenV265 = caenV265Info[card].pCaenV265;
|
||||
if(!pCaenV265){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(caenV265IdTest(pCaenV265)){
|
||||
/*
|
||||
* disable interrupts
|
||||
*/
|
||||
pCaenV265->csr=0;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Test()
|
||||
*/
|
||||
int caenV265Test(unsigned card)
|
||||
{
|
||||
unsigned dacVal;
|
||||
struct caenV265Config cofigCpy;
|
||||
unsigned range;
|
||||
unsigned signal;
|
||||
|
||||
|
||||
dacVal=0;
|
||||
caenV265TestVal(card, dacVal);
|
||||
while(dacVal<FD_DATA_M){
|
||||
|
||||
cofigCpy = caenV265Info[card];
|
||||
dacVal = dacVal+32;
|
||||
caenV265TestVal(card, dacVal);
|
||||
|
||||
for( range=0;
|
||||
range<NUMBER_OF_ADC_RANGES;
|
||||
range++){
|
||||
char *pRangeName[] = { "12 bit signal",
|
||||
"15 bit signal"};
|
||||
|
||||
printf( "\t%s with DAC = 0x%X\n",
|
||||
pRangeName[range],
|
||||
dacVal);
|
||||
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
unsigned newdata;
|
||||
unsigned olddata;
|
||||
|
||||
olddata = cofigCpy.chan[signal][range].signal;
|
||||
newdata = caenV265Info[card].
|
||||
chan[signal][range].signal;
|
||||
|
||||
printf( "\t\tchan=0x%1X diff = 0x%03X\n",
|
||||
signal,
|
||||
newdata-olddata);
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265TestVal()
|
||||
*/
|
||||
LOCAL int caenV265TestVal(unsigned card, unsigned dacVal)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned signal;
|
||||
|
||||
if(!pCaenV265){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if(!caenV265IdTest(pCaenV265)){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear the module
|
||||
*/
|
||||
pCaenV265->clear=0;
|
||||
|
||||
/*
|
||||
* generate a test signal
|
||||
*/
|
||||
pCaenV265->DAC=dacVal;
|
||||
|
||||
/*
|
||||
* generate a test gate
|
||||
*/
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
caenV265Info[card].chan[signal][adc_12].newData=FALSE;
|
||||
caenV265Info[card].chan[signal][adc_15].newData=FALSE;
|
||||
while(!caenV265Info[card].chan[signal][adc_15].newData){
|
||||
pCaenV265->gate=0;
|
||||
taskDelay(1);
|
||||
}
|
||||
while(!caenV265Info[card].chan[signal][adc_12].newData){
|
||||
pCaenV265->gate=0;
|
||||
taskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn off test signal
|
||||
*/
|
||||
pCaenV265->clear=0;
|
||||
pCaenV265->DAC=0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IOReport()
|
||||
*/
|
||||
LOCAL long caenV265IOReport(int level)
|
||||
{
|
||||
struct caenV265 *pCaenV265;
|
||||
unsigned card;
|
||||
unsigned signal;
|
||||
unsigned range;
|
||||
char *pVersion[] = {"NIM","ECL"};
|
||||
char *pState[] = {
|
||||
"FIFO empty",
|
||||
"FIFO full",
|
||||
"FIFO partially filled",
|
||||
"FIFO full"};
|
||||
|
||||
for (card=0; card<CAIN_V265_MAX_CARD_COUNT; card++) {
|
||||
pCaenV265 = caenV265Info[card].pCaenV265;
|
||||
if (!pCaenV265) {
|
||||
continue;
|
||||
}
|
||||
if (!caenV265IdTest(pCaenV265)) {
|
||||
continue;
|
||||
}
|
||||
printf("AI: caen V265:\tcard %d\n", card);
|
||||
if (level == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\tversion = %s\n",
|
||||
pVersion[EXTRACT(VERSION, pCaenV265->version)]);
|
||||
printf("\tseries = %d\n",
|
||||
EXTRACT(SERIES, pCaenV265->version));
|
||||
printf("\tstate = %s\n",
|
||||
pState[EXTRACT(BUSY_FULL,pCaenV265->csr)]);
|
||||
printf("\tint level = %d\n",
|
||||
EXTRACT(ILEVEL,pCaenV265->csr));
|
||||
printf("\tint vec = 0x%02X\n",
|
||||
EXTRACT(IVEC,pCaenV265->csr));
|
||||
printf( "\tbase addr= 0x%X on the %s\n",
|
||||
(unsigned)caenV265Info[card].pCaenV265,
|
||||
sysModel());
|
||||
|
||||
for( range=0;
|
||||
range<NUMBER_OF_ADC_RANGES;
|
||||
range++){
|
||||
char *pRangeName[] = { "12 bit signal",
|
||||
"15 bit signal"};
|
||||
|
||||
printf("\t%s\n", pRangeName[range]);
|
||||
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
int16_t data;
|
||||
|
||||
data = caenV265Info[card].
|
||||
chan[signal][range].signal;
|
||||
|
||||
if(caenV265Info[card].chan[signal][range].newData){
|
||||
printf( "\t\tchan=0x%1X val = 0x%03X\n",
|
||||
signal,
|
||||
data);
|
||||
}
|
||||
else{
|
||||
printf( "\t\tchan=0x%1X <NO GATE>\n",
|
||||
signal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
4620
src/drv/ansi/drvEpvxi.c
Normal file
4620
src/drv/ansi/drvEpvxi.c
Normal file
File diff suppressed because it is too large
Load Diff
1537
src/drv/ansi/drvEpvxiMsg.c
Normal file
1537
src/drv/ansi/drvEpvxiMsg.c
Normal file
File diff suppressed because it is too large
Load Diff
408
src/drv/ansi/drvHp1404a.c
Normal file
408
src/drv/ansi/drvHp1404a.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
*
|
||||
* HP E1404A VXI bus slot zero translator
|
||||
* device dependent routines
|
||||
*
|
||||
* share/src/drv/@(#)drvHp1404a.c 1.7 8/27/93
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* Date 030692
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 joh 073092 Added msg device support & interrupt shutdown for
|
||||
* soft reboots
|
||||
* .02 joh 082792 converted to ANSI C
|
||||
* .03 mgb 080493 Removed V5/V4 and EPICS_V2 conditionals
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
static char *sccsId = "@(#)drvHp1404a.c 1.7\t8/27/93";
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <iv.h>
|
||||
#include <intLib.h>
|
||||
#include <rebootLib.h>
|
||||
|
||||
#include <devLib.h>
|
||||
#include <drvEpvxi.h>
|
||||
#include <drvHp1404a.h>
|
||||
|
||||
LOCAL unsigned long hpE1404DriverID;
|
||||
|
||||
struct hpE1404_config{
|
||||
void (*pSignalCallback)(int16_t signal);
|
||||
};
|
||||
|
||||
#define TLTRIG(N) (1<<(N))
|
||||
#define ECLTRIG(N) (1<<((N)+8))
|
||||
|
||||
/*
|
||||
* enable int when signal register is written
|
||||
*/
|
||||
#define HP1404A_INT_ENABLE 0x0008
|
||||
#define HP1404A_INT_DISABLE 0x0000
|
||||
|
||||
/*
|
||||
*
|
||||
* tag the device dependent registers
|
||||
*/
|
||||
#define IRQ_enable dir.w.dd.reg.ddx1a
|
||||
#define MSG_status dir.w.dd.reg.ddx1e
|
||||
#define fp_trig_drive dir.w.dd.reg.ddx2a
|
||||
#define bp_trig_drive dir.w.dd.reg.ddx22
|
||||
#define signal_read dir.r.dd.reg.ddx10
|
||||
|
||||
#define hpE1404PConfig(LA, PC) \
|
||||
epvxiFetchPConfig((LA), hpE1404DriverID, (PC))
|
||||
|
||||
LOCAL void hpE1404InitLA(
|
||||
unsigned la
|
||||
);
|
||||
|
||||
LOCAL int hpE1404ShutDown(
|
||||
void
|
||||
);
|
||||
|
||||
LOCAL void hpE1404ShutDownLA(
|
||||
unsigned la
|
||||
);
|
||||
|
||||
LOCAL void hpE1404IOReport(
|
||||
unsigned la,
|
||||
unsigned level
|
||||
);
|
||||
|
||||
LOCAL void hpE1404Int(
|
||||
unsigned la
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404Init
|
||||
*
|
||||
*/
|
||||
hpE1404Stat hpE1404Init(void)
|
||||
{
|
||||
hpE1404Stat status;
|
||||
|
||||
status = rebootHookAdd(hpE1404ShutDown);
|
||||
if(status<0){
|
||||
status = S_dev_internal;
|
||||
errMessage(status, "rebootHookAdd() failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
hpE1404DriverID = epvxiUniqueDriverID();
|
||||
|
||||
status = epvxiRegisterMakeName(
|
||||
VXI_MAKE_HP,
|
||||
"Hewlett-Packard");
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
}
|
||||
status = epvxiRegisterModelName(
|
||||
VXI_MAKE_HP,
|
||||
VXI_HP_MODEL_E1404_REG_SLOT0,
|
||||
"Slot Zero Translator (reg)");
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
}
|
||||
status = epvxiRegisterModelName(
|
||||
VXI_MAKE_HP,
|
||||
VXI_HP_MODEL_E1404_REG,
|
||||
"Translator (reg)");
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
}
|
||||
status = epvxiRegisterModelName(
|
||||
VXI_MAKE_HP,
|
||||
VXI_HP_MODEL_E1404_MSG,
|
||||
"Translator (msg)");
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
}
|
||||
|
||||
{
|
||||
epvxiDeviceSearchPattern dsp;
|
||||
|
||||
dsp.flags = VXI_DSP_make | VXI_DSP_model;
|
||||
dsp.make = VXI_MAKE_HP;
|
||||
dsp.model = VXI_HP_MODEL_E1404_REG_SLOT0;
|
||||
status = epvxiLookupLA(&dsp, hpE1404InitLA, (void *)NULL);
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
dsp.model = VXI_HP_MODEL_E1404_REG;
|
||||
status = epvxiLookupLA(&dsp, hpE1404InitLA, (void *)NULL);
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404ShutDown()
|
||||
*
|
||||
*
|
||||
*/
|
||||
LOCAL int hpE1404ShutDown(void)
|
||||
{
|
||||
hpE1404Stat status;
|
||||
epvxiDeviceSearchPattern dsp;
|
||||
|
||||
dsp.flags = VXI_DSP_make | VXI_DSP_model;
|
||||
dsp.make = VXI_MAKE_HP;
|
||||
dsp.model = VXI_HP_MODEL_E1404_REG_SLOT0;
|
||||
status = epvxiLookupLA(&dsp, hpE1404ShutDownLA, (void *)NULL);
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
dsp.model = VXI_HP_MODEL_E1404_REG;
|
||||
status = epvxiLookupLA(&dsp, hpE1404ShutDownLA, (void *)NULL);
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
return ERROR;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404ShutDownLA()
|
||||
*
|
||||
*
|
||||
*/
|
||||
LOCAL
|
||||
void hpE1404ShutDownLA(
|
||||
unsigned la
|
||||
)
|
||||
{
|
||||
struct vxi_csr *pcsr;
|
||||
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pcsr->IRQ_enable = HP1404A_INT_DISABLE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404InitLA()
|
||||
*
|
||||
*/
|
||||
LOCAL
|
||||
void hpE1404InitLA(
|
||||
unsigned la
|
||||
)
|
||||
{
|
||||
struct hpE1404_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
hpE1404Stat status;
|
||||
|
||||
status = epvxiOpen(
|
||||
la,
|
||||
hpE1404DriverID,
|
||||
sizeof(*pc),
|
||||
hpE1404IOReport);
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
status = hpE1404PConfig(la, pc);
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
epvxiClose(la, hpE1404DriverID);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* set the self test status to passed for
|
||||
* the message based device
|
||||
*/
|
||||
pcsr->MSG_status = VXIPASS<<2;
|
||||
|
||||
intConnect(
|
||||
INUM_TO_IVEC(la),
|
||||
hpE1404Int,
|
||||
la);
|
||||
|
||||
/*
|
||||
* enable int when signal register is written
|
||||
*/
|
||||
pcsr->IRQ_enable = HP1404A_INT_ENABLE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404SignalConnect()
|
||||
*
|
||||
*/
|
||||
hpE1404Stat hpE1404SignalConnect(
|
||||
unsigned la,
|
||||
void (*pSignalCallback)(int16_t signal)
|
||||
)
|
||||
{
|
||||
hpE1404Stat s;
|
||||
struct hpE1404_config *pc;
|
||||
|
||||
s = hpE1404PConfig(la, pc);
|
||||
if(s){
|
||||
return s;
|
||||
}
|
||||
|
||||
pc->pSignalCallback = pSignalCallback;
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404Int()
|
||||
*
|
||||
*/
|
||||
LOCAL
|
||||
void hpE1404Int(
|
||||
unsigned la
|
||||
)
|
||||
{
|
||||
hpE1404Stat s;
|
||||
struct vxi_csr *pcsr;
|
||||
unsigned short signal;
|
||||
struct hpE1404_config *pc;
|
||||
|
||||
s = hpE1404PConfig(la, pc);
|
||||
if(s){
|
||||
errMessage(s, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* vector is only D8 so we cant check the cause of the int
|
||||
* (signal cause is assumed since that was all that was enabled)
|
||||
*/
|
||||
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
signal = pcsr->signal_read;
|
||||
|
||||
if(pc->pSignalCallback){
|
||||
(*pc->pSignalCallback)(signal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404RouteTriggerECL
|
||||
*
|
||||
*/
|
||||
hpE1404Stat hpE1404RouteTriggerECL(
|
||||
unsigned la, /* slot zero device logical address */
|
||||
unsigned enable_map, /* bits 0-5 correspond to trig 0-5 */
|
||||
/* a 1 enables a trigger */
|
||||
/* a 0 disables a trigger */
|
||||
unsigned io_map /* bits 0-5 correspond to trig 0-5 */
|
||||
/* a 1 sources the front panel */
|
||||
/* a 0 sources the back plane */
|
||||
)
|
||||
{
|
||||
struct vxi_csr *pcsr;
|
||||
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pcsr->fp_trig_drive = (io_map&enable_map)<<8;
|
||||
pcsr->bp_trig_drive = ((~io_map)&enable_map)<<8;
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* hpE1404RouteTriggerTTL
|
||||
*
|
||||
*
|
||||
*/
|
||||
hpE1404Stat hpE1404RouteTriggerTTL(
|
||||
unsigned la, /* slot zero device logical address */
|
||||
unsigned enable_map, /* bits 0-5 correspond to trig 0-5 */
|
||||
/* a 1 enables a trigger */
|
||||
/* a 0 disables a trigger */
|
||||
unsigned io_map /* bits 0-5 correspond to trig 0-5 */
|
||||
/* a 1 sources the front panel */
|
||||
/* a 0 sources the back plane */
|
||||
)
|
||||
{
|
||||
struct vxi_csr *pcsr;
|
||||
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pcsr->fp_trig_drive = io_map&enable_map;
|
||||
pcsr->bp_trig_drive = (~io_map)&enable_map;
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404IOReport()
|
||||
*
|
||||
*
|
||||
*/
|
||||
LOCAL
|
||||
void hpE1404IOReport(
|
||||
unsigned la,
|
||||
unsigned level
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
74
src/drv/ansi/drvHp1404a.h
Normal file
74
src/drv/ansi/drvHp1404a.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* drvHp1404a.h
|
||||
*
|
||||
* HP E1404A VXI bus slot zero translator
|
||||
* device dependent routines header file
|
||||
*
|
||||
* share/src/drv/@(#)drvHp1404a.h 1.1 8/27/93
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* Date 030692
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
typedef long hpE1404Stat;
|
||||
|
||||
hpE1404Stat hpE1404Init(void);
|
||||
|
||||
hpE1404Stat hpE1404SignalConnect(
|
||||
unsigned la,
|
||||
void (*pSignalCallback)(int16_t signal)
|
||||
);
|
||||
|
||||
hpE1404Stat hpE1404RouteTriggerECL(
|
||||
unsigned la, /* slot zero device logical address */
|
||||
unsigned enable_map, /* bits 0-5 correspond to trig 0-5 */
|
||||
/* a 1 enables a trigger */
|
||||
/* a 0 disables a trigger */
|
||||
unsigned io_map /* bits 0-5 correspond to trig 0-5 */
|
||||
/* a 1 sources the front panel */
|
||||
/* a 0 sources the back plane */
|
||||
);
|
||||
|
||||
hpE1404Stat hpE1404RouteTriggerTTL(
|
||||
unsigned la, /* slot zero device logical address */
|
||||
unsigned enable_map, /* bits 0-5 correspond to trig 0-5 */
|
||||
/* a 1 enables a trigger */
|
||||
/* a 0 disables a trigger */
|
||||
unsigned io_map /* bits 0-5 correspond to trig 0-5 */
|
||||
/* a 1 sources the front panel */
|
||||
/* a 0 sources the back plane */
|
||||
);
|
||||
|
||||
#define VXI_HP_MODEL_E1404_REG_SLOT0 0x10
|
||||
#define VXI_HP_MODEL_E1404_REG 0x110
|
||||
#define VXI_HP_MODEL_E1404_MSG 0x111
|
||||
|
||||
|
||||
359
src/drv/ansi/drvHpe1368a.c
Normal file
359
src/drv/ansi/drvHpe1368a.c
Normal file
@@ -0,0 +1,359 @@
|
||||
/* drvHpe1368a.c*/
|
||||
/* base/src/drv $Id$ */
|
||||
|
||||
/*
|
||||
* hpe1368a_driver.c
|
||||
*
|
||||
* driver for hpe1368a and hpe1369a microwave switch VXI modules
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 052192
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 071792 joh Added model name registration
|
||||
* .02 081992 joh vxiUniqueDriverID -> epvxiUniqueDriverID
|
||||
* .03 082692 mrk Added support for new I/O event scanning and DRVET
|
||||
* .04 080493 mgb Removed V5/V4 and EPICS_V2 conditionals
|
||||
*
|
||||
*/
|
||||
|
||||
static char *sccsId = "@(#)drvHpe1368a.c 1.14\t9/9/93";
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <iv.h>
|
||||
#include <types.h>
|
||||
#include <intLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <stdioLib.h>
|
||||
#include <vxLib.h>
|
||||
|
||||
#include <module_types.h>
|
||||
#include <task_params.h>
|
||||
#include <fast_lock.h>
|
||||
#include <drvEpvxi.h>
|
||||
#include <dbDefs.h>
|
||||
#include <drvSup.h>
|
||||
#include <dbScan.h>
|
||||
#include <devLib.h>
|
||||
|
||||
#include <drvHpe1368a.h>
|
||||
|
||||
|
||||
#define HPE1368A_PCONFIG(LA, PC) \
|
||||
epvxiFetchPConfig((LA), hpe1368aDriverId, (PC))
|
||||
|
||||
#define ChannelEnable(PCSR) ((PCSR)->dir.w.dd.reg.ddx08)
|
||||
#define ModuleStatus(PCSR) ((PCSR)->dir.r.status)
|
||||
|
||||
#define ALL_SWITCHES_OPEN 0
|
||||
|
||||
struct hpe1368a_config{
|
||||
FAST_LOCK lock; /* mutual exclusion */
|
||||
unsigned short pending; /* switch position pending int */
|
||||
unsigned short shadow; /* shadow of actual switch pos */
|
||||
int busy; /* relays active */
|
||||
IOSCANPVT ioscanpvt;
|
||||
};
|
||||
|
||||
#define HPE1368A_INT_LEVEL 1
|
||||
|
||||
LOCAL int hpe1368aDriverId;
|
||||
|
||||
LOCAL void hpe1368a_int_service(unsigned la);
|
||||
LOCAL void hpe1368a_init_card(unsigned la);
|
||||
LOCAL void hpe1368a_stat(unsigned la, int level);
|
||||
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvHpe1368a={
|
||||
2,
|
||||
NULL, /*VXI io report takes care of this */
|
||||
hpe1368a_init};
|
||||
|
||||
|
||||
/*
|
||||
* hpe1368a_init
|
||||
*
|
||||
* initialize all hpe1368a cards
|
||||
*
|
||||
*/
|
||||
hpe1368aStat hpe1368a_init(void)
|
||||
{
|
||||
hpe1368aStat r0;
|
||||
|
||||
/*
|
||||
* do nothing on crates without VXI
|
||||
*/
|
||||
if(!epvxiResourceMangerOK){
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
hpe1368aDriverId = epvxiUniqueDriverID();
|
||||
|
||||
{
|
||||
epvxiDeviceSearchPattern dsp;
|
||||
|
||||
dsp.flags = VXI_DSP_make | VXI_DSP_model;
|
||||
dsp.make = VXI_MAKE_HP;
|
||||
dsp.model = VXI_MODEL_HPE1368A;
|
||||
r0 = epvxiLookupLA(&dsp, hpe1368a_init_card, (void *)NULL);
|
||||
if(r0){
|
||||
errMessage(r0, NULL);
|
||||
return r0;
|
||||
}
|
||||
}
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* HPE1368A_INIT_CARD
|
||||
*
|
||||
* initialize single at5vxi card
|
||||
*
|
||||
*/
|
||||
LOCAL void hpe1368a_init_card(unsigned la)
|
||||
{
|
||||
hpe1368aStat r0;
|
||||
struct hpe1368a_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
int model;
|
||||
|
||||
r0 = epvxiOpen(
|
||||
la,
|
||||
hpe1368aDriverId,
|
||||
(unsigned long) sizeof(*pc),
|
||||
hpe1368a_stat);
|
||||
if(r0){
|
||||
errMessage(r0,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
r0 = HPE1368A_PCONFIG(la, pc);
|
||||
if(r0){
|
||||
errMessage(r0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
/*
|
||||
* we must reset the device to a known state since
|
||||
* we cant read back the current state
|
||||
*/
|
||||
pc->pending = ALL_SWITCHES_OPEN;
|
||||
pc->shadow = ALL_SWITCHES_OPEN;
|
||||
ChannelEnable(pcsr) = ALL_SWITCHES_OPEN;
|
||||
|
||||
FASTLOCKINIT(&pc->lock);
|
||||
scanIoInit(&pc->ioscanpvt);
|
||||
|
||||
r0 = intConnect(
|
||||
INUM_TO_IVEC(la),
|
||||
hpe1368a_int_service,
|
||||
la);
|
||||
if(r0 == ERROR){
|
||||
errMessage(S_dev_vxWorksVecInstlFail, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
sysIntEnable(HPE1368A_INT_LEVEL);
|
||||
|
||||
model = VXIMODEL(pcsr);
|
||||
r0 = epvxiRegisterModelName(
|
||||
VXIMAKE(pcsr),
|
||||
model,
|
||||
"E 1368A Microwave Switch\n");
|
||||
if(r0){
|
||||
errMessage(r0, NULL);
|
||||
}
|
||||
r0 = epvxiRegisterMakeName(VXIMAKE(pcsr), "Hewlett-Packard");
|
||||
if(r0){
|
||||
errMessage(r0,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpe1368a_int_service()
|
||||
*
|
||||
*
|
||||
* This device interrupts once the
|
||||
* switches have settled
|
||||
*
|
||||
*/
|
||||
LOCAL void
|
||||
hpe1368a_int_service(unsigned la)
|
||||
{
|
||||
hpe1368aStat s;
|
||||
struct hpe1368a_config *pc;
|
||||
|
||||
s = HPE1368A_PCONFIG(la,pc);
|
||||
if(s){
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* operation completed so we can update
|
||||
* the shadow value
|
||||
*/
|
||||
pc->shadow = pc->pending;
|
||||
pc->busy = FALSE;
|
||||
|
||||
/*
|
||||
* tell them that the switches have settled
|
||||
*/
|
||||
scanIoRequest(pc->ioscanpvt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* HPE1368A_STAT
|
||||
*
|
||||
* initialize single at5vxi card
|
||||
*
|
||||
*/
|
||||
LOCAL void hpe1368a_stat(
|
||||
unsigned la,
|
||||
int level
|
||||
)
|
||||
{
|
||||
hpe1368aStat s;
|
||||
struct hpe1368a_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
|
||||
s = HPE1368A_PCONFIG(la, pc);
|
||||
if(s){
|
||||
errMessage(s,NULL);
|
||||
return;
|
||||
}
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
if(level>0){
|
||||
printf("\tSwitch states %x\n", pc->shadow);
|
||||
printf("\tModule status %x\n", pcsr->dir.r.status);
|
||||
if(pc->busy){
|
||||
printf("\tModule is busy.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hpe1368a_getioscanpvt()
|
||||
*/
|
||||
hpe1368aStat hpe1368a_getioscanpvt(
|
||||
unsigned la,
|
||||
IOSCANPVT *scanpvt
|
||||
)
|
||||
{
|
||||
hpe1368aStat s;
|
||||
struct hpe1368a_config *pc;
|
||||
|
||||
s = HPE1368A_PCONFIG(la, pc);
|
||||
if(s){
|
||||
errMessage(s, NULL);
|
||||
return s;
|
||||
}
|
||||
*scanpvt = pc->ioscanpvt;
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* HPE1368A_BO_DRIVER
|
||||
*/
|
||||
hpe1368aStat hpe1368a_bo_driver(
|
||||
unsigned la,
|
||||
unsigned val,
|
||||
unsigned mask
|
||||
)
|
||||
{
|
||||
hpe1368aStat s;
|
||||
struct hpe1368a_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
unsigned int work;
|
||||
|
||||
s = HPE1368A_PCONFIG(la, pc);
|
||||
if(s){
|
||||
errMessage(s, NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
FASTLOCK(&pc->lock);
|
||||
|
||||
work = pc->pending;
|
||||
|
||||
/* alter specified bits */
|
||||
work = (work & ~mask) | (val & mask);
|
||||
|
||||
pc->pending = work;
|
||||
|
||||
ChannelEnable(pcsr) = work;
|
||||
|
||||
FASTUNLOCK(&pc->lock);
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* HPE1368A_BI_DRIVER
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
hpe1368aStat hpe1368a_bi_driver(
|
||||
unsigned la,
|
||||
unsigned mask,
|
||||
unsigned *pval
|
||||
)
|
||||
{
|
||||
hpe1368aStat s;
|
||||
struct hpe1368a_config *pc;
|
||||
|
||||
s = HPE1368A_PCONFIG(la, pc);
|
||||
if(s){
|
||||
errMessage(s, NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
FASTLOCK(&pc->lock);
|
||||
|
||||
*pval = pc->shadow & mask;
|
||||
|
||||
FASTUNLOCK(&pc->lock);
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
60
src/drv/ansi/drvHpe1368a.h
Normal file
60
src/drv/ansi/drvHpe1368a.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* drvHpe1368a.h*/
|
||||
/* base/src/drv $Id$ */
|
||||
|
||||
/*
|
||||
* hpe1368a_driver.h
|
||||
*
|
||||
* driver for hpe1368a and hpe1369a microwave switch VXI modules
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 052192
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*
|
||||
*/
|
||||
|
||||
#define VXI_MODEL_HPE1368A (0xf28)
|
||||
|
||||
typedef long hpe1368aStat;
|
||||
|
||||
hpe1368aStat hpe1368a_init(void);
|
||||
|
||||
hpe1368aStat hpe1368a_getioscanpvt(
|
||||
unsigned la,
|
||||
IOSCANPVT *scanpvt
|
||||
);
|
||||
|
||||
hpe1368aStat hpe1368a_bo_driver(
|
||||
unsigned la,
|
||||
unsigned val,
|
||||
unsigned mask
|
||||
);
|
||||
|
||||
hpe1368aStat hpe1368a_bi_driver(
|
||||
unsigned la,
|
||||
unsigned mask,
|
||||
unsigned *pval
|
||||
);
|
||||
|
||||
1185
src/drv/ansi/drvHpe1445a.c
Normal file
1185
src/drv/ansi/drvHpe1445a.c
Normal file
File diff suppressed because it is too large
Load Diff
484
src/drv/ansi/drvKscV215.c
Normal file
484
src/drv/ansi/drvKscV215.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/* drvKscV215.c*/
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* KscV215_driver.c
|
||||
*
|
||||
* driver for KscV215 VXI module
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 052192
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 071792 joh Added model name registration
|
||||
* .02 081992 joh vxiUniqueDriverID -> epvxiUniqueDriverID
|
||||
* .03 082692 mrk Added support for new I/O event scanning and DRVET
|
||||
* .04 012893 joh include file name change
|
||||
* .05 080493 mgb Removed V5/V4 and EPICS_V2 conditionals
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <dbDefs.h>
|
||||
#include <iv.h>
|
||||
#include <types.h>
|
||||
#include <stdioLib.h>
|
||||
|
||||
#include <module_types.h>
|
||||
#include <task_params.h>
|
||||
#include <fast_lock.h>
|
||||
#include <drvEpvxi.h>
|
||||
#include <drvSup.h>
|
||||
#include <dbScan.h>
|
||||
#include <devLib.h>
|
||||
|
||||
#include <drvKscV215.h>
|
||||
|
||||
|
||||
#define MAXTRIES 100
|
||||
|
||||
#define KSCV215_PCONFIG(LA, PC) \
|
||||
epvxiFetchPConfig((LA), KscV215DriverId, PC)
|
||||
|
||||
#define ChannelEnable(PCSR) ((PCSR)->dir.w.dd.reg.ddx08)
|
||||
#define ModuleStatus(PCSR) ((PCSR)->dir.r.status)
|
||||
|
||||
#define ALL_SWITCHES_OPEN 0
|
||||
|
||||
struct KscV215_config{
|
||||
FAST_LOCK lock; /* mutual exclusion */
|
||||
IOSCANPVT ioscanpvt;
|
||||
};
|
||||
|
||||
#define KSCV215_INT_LEVEL 1
|
||||
#define KscV215Handshake (0x0040)
|
||||
#define KscV215csrInit (0x9000)
|
||||
|
||||
LOCAL int KscV215DriverId;
|
||||
|
||||
|
||||
struct KscV215_A24{
|
||||
volatile uint16_t diag;
|
||||
volatile uint16_t isr;
|
||||
volatile uint16_t pad1[7];
|
||||
volatile uint16_t channels[64]; /* odd access causes a bus error ? */
|
||||
volatile uint16_t controlMemoryAddr;
|
||||
volatile uint16_t pad2;
|
||||
volatile uint16_t controlMemoryDataWrite;
|
||||
volatile uint16_t pad3;
|
||||
volatile uint16_t controlMemoryDataRead;
|
||||
volatile uint16_t pad4;
|
||||
volatile uint16_t lastChannel;
|
||||
volatile uint16_t pad5;
|
||||
volatile uint16_t singleScan;
|
||||
volatile uint16_t pad6;
|
||||
volatile uint16_t stopScan;
|
||||
volatile uint16_t pad7;
|
||||
volatile uint16_t clearControlMemoryAddr;
|
||||
volatile uint16_t pad8;
|
||||
volatile uint16_t enableContinuousScanning;
|
||||
volatile uint16_t pad9;
|
||||
volatile uint16_t disableContinuousScanning;
|
||||
volatile uint16_t pad10;
|
||||
volatile uint16_t enableDoneInt;
|
||||
volatile uint16_t pad11;
|
||||
volatile uint16_t disbaleDoneInt;
|
||||
volatile uint16_t pad12;
|
||||
volatile uint16_t clearDoneInt;
|
||||
volatile uint16_t pad13;
|
||||
volatile uint16_t testDoneInt;
|
||||
volatile uint16_t pad14;
|
||||
};
|
||||
|
||||
#ifdef INTERRUPTS
|
||||
LOCAL void KscV215_int_service(unsigned la);
|
||||
#endif
|
||||
LOCAL void KscV215_init_card(unsigned la);
|
||||
|
||||
LOCAL void KscV215_stat(
|
||||
unsigned la,
|
||||
int level
|
||||
);
|
||||
|
||||
LOCAL kscV215Stat KscV215WriteSync(
|
||||
struct KscV215_A24 *pA24,
|
||||
volatile uint16_t *preg,
|
||||
uint16_t val
|
||||
);
|
||||
|
||||
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvKscV215={
|
||||
2,
|
||||
NULL, /* VXI report takes care of this */
|
||||
KscV215Init};
|
||||
|
||||
/*
|
||||
* KscV215_init
|
||||
*
|
||||
* initialize all KscV215 cards
|
||||
*
|
||||
*/
|
||||
kscV215Stat KscV215Init(void)
|
||||
{
|
||||
kscV215Stat r0;
|
||||
|
||||
/*
|
||||
* do nothing on crates without VXI
|
||||
*/
|
||||
if(!epvxiResourceMangerOK){
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
KscV215DriverId = epvxiUniqueDriverID();
|
||||
|
||||
{
|
||||
epvxiDeviceSearchPattern dsp;
|
||||
|
||||
dsp.flags = VXI_DSP_make | VXI_DSP_model;
|
||||
dsp.make = VXI_MAKE_KSC;
|
||||
dsp.model = VXI_MODEL_KSCV215;
|
||||
r0 = epvxiLookupLA(&dsp, KscV215_init_card, (void *)NULL);
|
||||
if(r0){
|
||||
return r0;
|
||||
}
|
||||
}
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* KSCV215_INIT_CARD
|
||||
*
|
||||
* initialize single at5vxi card
|
||||
*
|
||||
*/
|
||||
LOCAL void KscV215_init_card(unsigned la)
|
||||
{
|
||||
kscV215Stat status;
|
||||
int i;
|
||||
struct KscV215_config *pc;
|
||||
struct KscV215_A24 *pA24;
|
||||
struct vxi_csr *pcsr;
|
||||
int model;
|
||||
|
||||
status = epvxiOpen(
|
||||
la,
|
||||
KscV215DriverId,
|
||||
(unsigned long) sizeof(*pc),
|
||||
KscV215_stat);
|
||||
if(status){
|
||||
errPrintf(
|
||||
status,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"AT5VXI: device open failed %d\n",
|
||||
la);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
status = KSCV215_PCONFIG(la, pc);
|
||||
if(status){
|
||||
errMessage(status,NULL);
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
return;
|
||||
}
|
||||
|
||||
pA24 = epvxiA24Base(la);
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pcsr->dir.w.control = KscV215csrInit;
|
||||
|
||||
status = KscV215WriteSync(pA24, &pA24->controlMemoryAddr, 0U);
|
||||
if(status){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
errMessage(status, "KscV215 init failed\n");
|
||||
return;
|
||||
}
|
||||
for(i=0; i<(NELEMENTS(pA24->channels)/2); i++){
|
||||
status = KscV215WriteSync(
|
||||
pA24,
|
||||
&pA24->controlMemoryDataWrite,
|
||||
0U);
|
||||
if(status){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
errMessage(status, "KscV215 init failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn on continuous scan mode
|
||||
*/
|
||||
status = KscV215WriteSync(
|
||||
pA24,
|
||||
&pA24->enableContinuousScanning,
|
||||
0U);
|
||||
if(status){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
errMessage(status, "KscV215 init failed- device left open\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FASTLOCKINIT(&pc->lock);
|
||||
scanIoInit(&pc->ioscanpvt);
|
||||
|
||||
#ifdef INTERRUPTS
|
||||
status = intConnect(
|
||||
(unsigned char) INUM_TO_IVEC(la),
|
||||
KscV215_int_service,
|
||||
(void *) la);
|
||||
if(status == ERROR){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
errMessage(S_dev_vxWorksVecInstlFail,
|
||||
"KscV215 init failed- device left open");
|
||||
return;
|
||||
}
|
||||
sysIntEnable(KSCV215_INT_LEVEL);
|
||||
#endif
|
||||
|
||||
status = epvxiRegisterMakeName(VXI_MAKE_KSC, "Kinetic Systems");
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
}
|
||||
|
||||
model = VXIMODEL(pcsr);
|
||||
status = epvxiRegisterModelName(
|
||||
VXIMAKE(pcsr),
|
||||
model,
|
||||
"V215 16 bit 32 channel ADC\n");
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* KscV215WriteSync
|
||||
*
|
||||
*
|
||||
*/
|
||||
LOCAL kscV215Stat KscV215WriteSync(
|
||||
struct KscV215_A24 *pA24,
|
||||
volatile uint16_t *preg,
|
||||
uint16_t val
|
||||
)
|
||||
{
|
||||
kscV215Stat status;
|
||||
int i;
|
||||
|
||||
for(i=0; i<MAXTRIES; i++){
|
||||
*preg = val;
|
||||
if(pA24->diag & KscV215Handshake){
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
taskDelay(1);
|
||||
}
|
||||
|
||||
status = S_dev_deviceTMO;
|
||||
errMessage(status, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* KscV215_int_service()
|
||||
*
|
||||
*
|
||||
* This device interrupts once the
|
||||
* switches have settled
|
||||
*
|
||||
*/
|
||||
#ifdef INTERRUPTS
|
||||
LOCAL void KscV215_int_service(unsigned la)
|
||||
{
|
||||
kscV215Stat s;
|
||||
struct KscV215_config *pc;
|
||||
|
||||
s = KSCV215_PCONFIG(la, pc);
|
||||
if(s){
|
||||
logMsg( "Int to ukn device %s line=%d\n",
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* tell them that the switches have settled
|
||||
*/
|
||||
scanIoRequest(pc->ioscanpvt);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* KSCV215_STAT
|
||||
*
|
||||
* initialize single at5vxi card
|
||||
*
|
||||
*/
|
||||
LOCAL void KscV215_stat(
|
||||
unsigned la,
|
||||
int level
|
||||
)
|
||||
{
|
||||
kscV215Stat s;
|
||||
struct KscV215_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
struct KscV215_A24 *pA24;
|
||||
int i;
|
||||
|
||||
s = KSCV215_PCONFIG(la, pc);
|
||||
if(s){
|
||||
errMessage(s, NULL);
|
||||
return;
|
||||
}
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pA24 = (struct KscV215_A24 *) epvxiA24Base(la);
|
||||
|
||||
if(level>0){
|
||||
printf ("KSC V215 32 CHANNEL 16 BIT ADC.\n");
|
||||
}
|
||||
if (level > 1) {
|
||||
for (i = 0; i < 32; i++)
|
||||
printf ("Channel %d Value %d\n",
|
||||
i,
|
||||
pA24->channels[i*2]);
|
||||
}
|
||||
if (level > 2) {
|
||||
printf ("\nGain Setting (Control Memory Data Register\n");
|
||||
pA24->controlMemoryAddr = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
switch (pA24->controlMemoryAddr) {
|
||||
case 0:
|
||||
printf ("+- 10V");
|
||||
break;
|
||||
case 1:
|
||||
printf ("+- 5V");
|
||||
break;
|
||||
case 3:
|
||||
printf ("+- 2.5V");
|
||||
break;
|
||||
case 5:
|
||||
printf ("+- 1.25V");
|
||||
break;
|
||||
case 6:
|
||||
printf ("+- 625mV");
|
||||
break;
|
||||
default:
|
||||
printf ("Unknown Gain Setting.");
|
||||
}
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* AT5VXI_AI_DRIVER
|
||||
*
|
||||
* analog input driver
|
||||
*/
|
||||
kscV215Stat KscV215_ai_driver(
|
||||
unsigned la,
|
||||
unsigned chan,
|
||||
unsigned short *prval
|
||||
)
|
||||
{
|
||||
struct KscV215_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
struct KscV215_A24 *pA24;
|
||||
long tmp;
|
||||
int i;
|
||||
kscV215Stat s;
|
||||
|
||||
s = KSCV215_PCONFIG(la, pc);
|
||||
if(s){
|
||||
return s;
|
||||
}
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pA24 = epvxiA24Base(la);
|
||||
|
||||
if(chan >= NELEMENTS(pA24->channels)/2){
|
||||
return S_dev_badSignalNumber;
|
||||
}
|
||||
|
||||
for(i=0; i<MAXTRIES; i++){
|
||||
tmp = pA24->channels[chan<<1];
|
||||
if(pA24->diag & KscV215Handshake){
|
||||
tmp = tmp + 0xffff;
|
||||
tmp = tmp >> 4;
|
||||
tmp &= 0xfff;
|
||||
*prval = tmp;
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
taskDelay(1);
|
||||
}
|
||||
|
||||
s = S_dev_deviceTMO;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* KscV215_getioscanpvt()
|
||||
*/
|
||||
kscV215Stat KscV215_getioscanpvt(
|
||||
unsigned la,
|
||||
IOSCANPVT *scanpvt
|
||||
)
|
||||
{
|
||||
kscV215Stat s;
|
||||
struct KscV215_config *pc;
|
||||
|
||||
s = KSCV215_PCONFIG(la, pc);
|
||||
if(s){
|
||||
errMessage(s, NULL);
|
||||
return s;
|
||||
}
|
||||
*scanpvt = pc->ioscanpvt;
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
56
src/drv/ansi/drvKscV215.h
Normal file
56
src/drv/ansi/drvKscV215.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* drvKscV215.c*/
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* KscV215_driver.c
|
||||
*
|
||||
* driver for KscV215 VXI module
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 052192
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*
|
||||
*/
|
||||
|
||||
#define VXI_MODEL_KSCV215 (0x215)
|
||||
|
||||
typedef long kscV215Stat;
|
||||
|
||||
kscV215Stat KscV215Init(void);
|
||||
|
||||
kscV215Stat KscV215_ai_driver(
|
||||
unsigned la,
|
||||
unsigned chan,
|
||||
unsigned short *prval
|
||||
);
|
||||
|
||||
kscV215Stat KscV215_getioscanpvt(
|
||||
unsigned la,
|
||||
IOSCANPVT *scanpvt
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
627
src/drv/ansi/drvMz8310.c
Normal file
627
src/drv/ansi/drvMz8310.c
Normal file
@@ -0,0 +1,627 @@
|
||||
|
||||
/* drvMz8310.c */
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* Routines specific to the MZ8310. Low level routines for the AMD STC in
|
||||
* stc_driver.c
|
||||
* Author: Jeff Hill
|
||||
* Date: Feb 1989
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification History
|
||||
* joh 02-20-89 Init Release
|
||||
* joh 04-28-89 Added read back
|
||||
* joh 11-17-89 added readback to io report
|
||||
* joh 12-10-89 DB defaults the internal/external clock
|
||||
* parameter to 0 or external clock. This was the opposite
|
||||
* of what this driver expected. Fix was made here.
|
||||
* joh 07-06-90 print channel number with channel value in IO report
|
||||
* joh 02-25-91 made ext/int clk IO report more readable
|
||||
* joh 09-05-91 converted to v5 vxWorks
|
||||
* bg 09-15-91 added sysBustoLocalAdrs() for addressing
|
||||
* bg 03-10-92 added the argument, level, to mz310_io_report().
|
||||
* bg 04-27-92 added rebootHookAdd and mz8310_reset so ioc will
|
||||
* not hang on ctl X reboot.
|
||||
* joh 04-28-92 added arguments to MACROS which had hidden
|
||||
* parameters
|
||||
* bg 06-25-92 combined drvMz8310.c and mz8310_driver.c
|
||||
* bg 06-26-92 Added level to mz8310_io_report.
|
||||
* joh 08-05-92 callable interface now conforms with epics standard
|
||||
* mgb 08-04-93 Removed V5/V4 and EPICS_V2 conditionals
|
||||
* joh 08-24-93 Include drvStc.h and ANSI C upgrade
|
||||
* joh 09-29-93 removed superfluous error message
|
||||
*/
|
||||
|
||||
/* drvMz8310.c - Driver Support Routines for Mz8310 */
|
||||
#include <vxWorks.h>
|
||||
#include <stdioLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <stdlib.h>
|
||||
#include <intLib.h>
|
||||
#include <rebootLib.h>
|
||||
#include <vxLib.h>
|
||||
#include <vme.h>
|
||||
#include <iv.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <drvSup.h>
|
||||
#include <module_types.h>
|
||||
#include <fast_lock.h>
|
||||
#include <devLib.h>
|
||||
#include <drvStc.h>
|
||||
|
||||
#include <drvMz8310.h>
|
||||
|
||||
#define MZ8310CHIPSIZE 0x20
|
||||
#define MZ8310SIZE 0x00000100
|
||||
#define MZ8310BASE(CARD) (shortaddr+tm_addrs[MZ8310]+(CARD)*MZ8310SIZE)
|
||||
|
||||
#define MZ8310DATA 0
|
||||
#define MZ8310CMD 3
|
||||
#define MZ8310CHANONCHIP 5
|
||||
#define MZ8310CHIPCOUNT 2
|
||||
#define MZ8310CHANCNT (MZ8310CHANONCHIP*MZ8310CHIPCOUNT)
|
||||
|
||||
/*
|
||||
NOTE: The mizar draftsman has labeled the chip at the
|
||||
highest address as one and the chip at the lowest address
|
||||
2 so I am reversing the chip number below.
|
||||
*/
|
||||
#define CHIP_REVERSE(CHIP) (MZ8310CHIPCOUNT-1-(CHIP))
|
||||
#define CHIP_ADDR(CARD,CHIP) (MZ8310BASE(CARD)+\
|
||||
(CHIP_REVERSE(CHIP)*MZ8310CHIPSIZE))
|
||||
|
||||
#define MZ8310_CMD_ADDR(CARD,CHIP)\
|
||||
((volatile uint8_t *) CHIP_ADDR(CARD,CHIP) + MZ8310CMD)
|
||||
#define MZ8310_DATA_ADDR(CARD,CHIP)\
|
||||
((volatile uint16_t *) CHIP_ADDR(CARD,CHIP) + MZ8310DATA)
|
||||
#if 0
|
||||
#define MZ8310VECBASE(CARD,CHIP)\
|
||||
((volatile uint8_t *) CHIP_ADDR(CARD,CHIP) + 0x41)
|
||||
#endif
|
||||
|
||||
#define MZ8310VECSIZE (0x20)
|
||||
#define MZ8310INTCNT 4
|
||||
#define MZ8310FIRSTINTCHAN 0
|
||||
#define MZ8310INTVEC(CARD,CHAN)\
|
||||
(MZ8310_INT_VEC_BASE + (CARD*MZ8310INTCNT) + mz8310_strap[CHAN].vec_num)
|
||||
|
||||
#define MZ8310_INTERUPTABLE(CHAN) (mz8310_strap[CHAN].vec_addr)
|
||||
|
||||
# define INT_TICKS 4.0e06 /* speed of F1 in Hz */
|
||||
# define EXT_TICKS 5.0e06 /* GTA std speed of SRC1 in Hz */
|
||||
|
||||
|
||||
struct mz8310_int_conf{
|
||||
void (*user_service)(void *user_param);
|
||||
void *user_param;
|
||||
unsigned int cnt;
|
||||
};
|
||||
|
||||
struct mz8310_conf{
|
||||
char init;
|
||||
FAST_LOCK lock;
|
||||
struct mz8310_int_conf icf[MZ8310CHANCNT];
|
||||
};
|
||||
|
||||
struct mz8310_strap_info{
|
||||
unsigned char irq; /* the level at which the chan gen ints */
|
||||
unsigned char vec_num; /* really a vec offset-see MZ8310INTVEC */
|
||||
unsigned char vec_addr;/* offset from card base address */
|
||||
};
|
||||
|
||||
static volatile char *shortaddr;
|
||||
|
||||
LOCAL struct mz8310_conf *mzconf;
|
||||
LOCAL unsigned int mz8310_card_count;
|
||||
|
||||
/*
|
||||
only 4 unique interrupts per card but any channel can potentially
|
||||
generate an interrupt depending on board strapping.
|
||||
|
||||
NOTE: existence of vec addr tells the driver that that channel is
|
||||
strapped for interrupts since the card can't be polled for this info.
|
||||
|
||||
In the MIZAR 8310 Documentation:
|
||||
|
||||
Designation vector reg offset
|
||||
IRQA 0x41
|
||||
IRQB 0x61
|
||||
IRQC 0x81
|
||||
IRQD 0xa1
|
||||
*/
|
||||
|
||||
LOCAL struct mz8310_strap_info mz8310_strap[MZ8310CHANCNT] =
|
||||
{
|
||||
{ NULL, NULL, NULL }, /* channel 0 */
|
||||
{ NULL, NULL, NULL }, /* channel 1 */
|
||||
{ NULL, NULL, NULL }, /* channel 2 */
|
||||
{ NULL, NULL, NULL }, /* channel 3 */
|
||||
{ NULL, NULL, NULL }, /* channel 4 */
|
||||
{ NULL, NULL, NULL }, /* channel 5 */
|
||||
{ 1, 0, 0x41 }, /* channel 6 */
|
||||
{ 3, 1, 0x61 }, /* channel 7 */
|
||||
{ 5, 2, 0x81 }, /* channel 8 */
|
||||
{ 6, 3, 0xa1 } /* channel 9 */
|
||||
};
|
||||
|
||||
/* forward reference. */
|
||||
LOCAL int mz8310_reset(void);
|
||||
LOCAL mz8310Stat mz8310_io_report_card(unsigned card, unsigned level);
|
||||
LOCAL mz8310Stat mz8310_init_card(unsigned card);
|
||||
LOCAL mz8310Stat mz8310_setup_int(unsigned card, unsigned channel);
|
||||
LOCAL mz8310Stat mz8310_io_report(unsigned level);
|
||||
LOCAL mz8310Stat mz8310_init(void);
|
||||
LOCAL mz8310Stat mz8310_read_test(unsigned card, unsigned channel);
|
||||
LOCAL void mz8310_int_service(struct mz8310_int_conf *icf);
|
||||
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvMz8310={
|
||||
2,
|
||||
mz8310_io_report,
|
||||
mz8310_init};
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_io_report()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_io_report(unsigned level)
|
||||
{
|
||||
unsigned card;
|
||||
|
||||
for(card=0; card<tm_num_cards[MZ8310]; card++)
|
||||
mz8310_io_report_card(card, level);
|
||||
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_io_report_card()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_io_report_card(unsigned card, unsigned level)
|
||||
{
|
||||
unsigned channel;
|
||||
unsigned chip;
|
||||
mz8310Stat status;
|
||||
|
||||
for(chip=0; chip<MZ8310CHIPCOUNT; chip++){
|
||||
status = stc_io_report(
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip));
|
||||
if(status){
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
printf("TM: MZ8310:\tcard %d\n", card);
|
||||
|
||||
|
||||
if (mzconf && card<mz8310_card_count && level){
|
||||
for(channel=0;channel<MZ8310CHANCNT;channel++){
|
||||
status = mz8310_read_test(card, channel);
|
||||
if(status){
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_init()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_init(void)
|
||||
{
|
||||
unsigned card;
|
||||
mz8310Stat status;
|
||||
struct mz8310_conf *temp_mzconf;
|
||||
unsigned card_count = tm_num_cards[MZ8310];
|
||||
|
||||
status = sysBusToLocalAdrs(
|
||||
VME_AM_SUP_SHORT_IO,
|
||||
0,
|
||||
(char **)&shortaddr);
|
||||
if (status != OK){
|
||||
status = S_dev_badA16;
|
||||
errMessage(status, "A16 Address map error mz8310 driver");
|
||||
return status;
|
||||
}
|
||||
|
||||
temp_mzconf = (struct mz8310_conf *) malloc(sizeof(*mzconf)*card_count);
|
||||
if(!temp_mzconf)
|
||||
return S_dev_noMemory;
|
||||
|
||||
for(card=0; card<card_count; card++){
|
||||
FASTLOCKINIT(&temp_mzconf[card].lock);
|
||||
}
|
||||
|
||||
if(mzconf){
|
||||
for(card=0; card<card_count; card++){
|
||||
if(FASTLOCKFREE(&mzconf[card].lock)<0){
|
||||
status = S_dev_internal;
|
||||
errMessage(status, "error freeing sem");
|
||||
}
|
||||
}
|
||||
free(mzconf);
|
||||
}
|
||||
|
||||
mzconf = temp_mzconf;
|
||||
|
||||
for(card=0; card<card_count; card++){
|
||||
status = mz8310_init_card(card);
|
||||
if(status){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mz8310_card_count = card;
|
||||
|
||||
rebootHookAdd(mz8310_reset);
|
||||
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* mz8310_init_card()
|
||||
*
|
||||
* Locking for this provided by mz8310_init()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_init_card(unsigned card)
|
||||
{
|
||||
unsigned chip;
|
||||
unsigned chan;
|
||||
mz8310Stat error;
|
||||
/*
|
||||
* binary division
|
||||
* data ptr seq enbl
|
||||
* 16 bit bus
|
||||
* FOUT on
|
||||
* FOUT divide by one
|
||||
* FOUT source (F1)
|
||||
* Time of day disabled
|
||||
*/
|
||||
unsigned short master_mode = 0x2100;
|
||||
|
||||
for(chip=0; chip< MZ8310CHIPCOUNT; chip++){
|
||||
error = stc_init(
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip),
|
||||
master_mode);
|
||||
if(error){
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
for(chan=0; chan<MZ8310CHANCNT; chan++)
|
||||
mz8310_setup_int(card,chan);
|
||||
|
||||
mzconf[card].init = TRUE;
|
||||
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_setup_int()
|
||||
*
|
||||
* (locked by calling routines)
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_setup_int(unsigned card, unsigned channel)
|
||||
{
|
||||
unsigned char vector;
|
||||
mz8310Stat status;
|
||||
|
||||
mzconf[card].icf[channel].user_service = NULL;
|
||||
mzconf[card].icf[channel].user_param = NULL;
|
||||
mzconf[card].icf[channel].cnt = 0;
|
||||
|
||||
/*
|
||||
* Is this channel strapped for interrupts
|
||||
*/
|
||||
if(!MZ8310_INTERUPTABLE(channel))
|
||||
return MZ8310_SUCCESS;
|
||||
|
||||
vector = MZ8310INTVEC(card,channel);
|
||||
status = vxMemProbe(
|
||||
(char *)MZ8310BASE(card) + mz8310_strap[channel].vec_addr,
|
||||
WRITE,
|
||||
sizeof(vector),
|
||||
(char *)&vector);
|
||||
if(status != OK){
|
||||
status = S_dev_noDevice;
|
||||
errMessage(status, NULL);
|
||||
return S_dev_noDevice;
|
||||
}
|
||||
|
||||
status = intConnect( INUM_TO_IVEC(vector),
|
||||
mz8310_int_service,
|
||||
(int)&mzconf[card].icf[channel]);
|
||||
if(status != OK)
|
||||
return S_dev_vxWorksVecInstlFail;
|
||||
|
||||
sysIntEnable(mz8310_strap[channel].irq);
|
||||
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_one_shot_read()
|
||||
*/
|
||||
mz8310Stat mz8310_one_shot_read(
|
||||
unsigned *preset, /* TRUE or COMPLEMENT logic */
|
||||
double *edge0_delay, /* sec */
|
||||
double *edge1_delay, /* sec */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned *int_source /* (FALSE)External/(TRUE)Internal src */
|
||||
)
|
||||
{
|
||||
int chip = channel/MZ8310CHANONCHIP;
|
||||
double ticks;
|
||||
unsigned short iedge0;
|
||||
unsigned short iedge1;
|
||||
mz8310Stat status;
|
||||
|
||||
if(channel >= MZ8310CHANONCHIP * MZ8310CHIPCOUNT)
|
||||
return S_dev_badSignalNumber;
|
||||
|
||||
if(card>=mz8310_card_count)
|
||||
return S_dev_badA16;
|
||||
|
||||
if(!mzconf)
|
||||
return S_dev_noDevice;
|
||||
|
||||
FASTLOCK(&mzconf[card].lock);
|
||||
|
||||
status =
|
||||
stc_one_shot_read(
|
||||
preset,
|
||||
&iedge0,
|
||||
&iedge1,
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip),
|
||||
channel % MZ8310CHANONCHIP,
|
||||
int_source);
|
||||
if(status==STC_SUCCESS){
|
||||
ticks = *int_source ? INT_TICKS : EXT_TICKS;
|
||||
*edge0_delay = iedge0 / ticks;
|
||||
*edge1_delay = iedge1 / ticks;
|
||||
}
|
||||
|
||||
FASTUNLOCK(&mzconf[card].lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_read_test()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_read_test(unsigned card, unsigned channel)
|
||||
{
|
||||
unsigned preset;
|
||||
double edge0_delay;
|
||||
double edge1_delay;
|
||||
unsigned int_source;
|
||||
mz8310Stat status;
|
||||
static char *pclktype[] = {"external-clk", "internal-clk"};
|
||||
static char *ppresettype[] = {"preset-FALSE", "preset-TRUE "};
|
||||
|
||||
status =
|
||||
mz8310_one_shot_read(
|
||||
&preset,
|
||||
&edge0_delay,
|
||||
&edge1_delay,
|
||||
card,
|
||||
channel,
|
||||
&int_source);
|
||||
if(status==MZ8310_SUCCESS){
|
||||
printf( "\tChannel %u %s delay=%f width=%f %s\n",
|
||||
channel,
|
||||
ppresettype[preset&1],
|
||||
edge0_delay,
|
||||
edge1_delay,
|
||||
pclktype[int_source&1]);
|
||||
if(mzconf[card].icf[channel].cnt)
|
||||
printf("\tChannel %u Interrupt count=%u\n",
|
||||
channel,
|
||||
mzconf[card].icf[channel].cnt);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_one_shot()
|
||||
*/
|
||||
mz8310Stat mz8310_one_shot(
|
||||
unsigned preset, /* TRUE or COMPLEMENT logic */
|
||||
double edge0_delay, /* sec */
|
||||
double edge1_delay, /* set */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned int_source, /* (FALSE)External/ (TRUE)Internal source */
|
||||
void (*event_rtn)(void *pParam), /* subroutine to run on events */
|
||||
void *event_rtn_param /* parameter to pass to above routine */
|
||||
)
|
||||
{
|
||||
int chip = channel/MZ8310CHANONCHIP;
|
||||
double ticks = int_source?INT_TICKS:EXT_TICKS;
|
||||
mz8310Stat status;
|
||||
|
||||
if(channel >= MZ8310CHANONCHIP * MZ8310CHIPCOUNT)
|
||||
return S_dev_badSignalNumber;
|
||||
|
||||
if(card>=mz8310_card_count)
|
||||
return S_dev_badA16;
|
||||
|
||||
if(!mzconf)
|
||||
return S_dev_noDevice;
|
||||
|
||||
/* dont overflow unsigned short in STC */
|
||||
if(edge0_delay >= 0xffff/ticks)
|
||||
return S_dev_highValue;
|
||||
if(edge1_delay >= 0xffff/ticks)
|
||||
return S_dev_highValue;
|
||||
if(edge0_delay < 0.0)
|
||||
return S_dev_lowValue;
|
||||
if(edge1_delay < 0.0)
|
||||
return S_dev_lowValue;
|
||||
|
||||
FASTLOCK(&mzconf[card].lock);
|
||||
|
||||
/* Enable calling of user routine */
|
||||
if(MZ8310_INTERUPTABLE(channel)){
|
||||
mzconf[card].icf[channel].user_service = event_rtn;
|
||||
mzconf[card].icf[channel].user_param = event_rtn_param;
|
||||
}
|
||||
|
||||
status =
|
||||
stc_one_shot(
|
||||
preset,
|
||||
(unsigned short) (edge0_delay * ticks),
|
||||
(unsigned short) (edge1_delay * ticks),
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip),
|
||||
channel % MZ8310CHANONCHIP,
|
||||
int_source);
|
||||
|
||||
FASTUNLOCK(&mzconf[card].lock);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_int_service()
|
||||
*/
|
||||
LOCAL void mz8310_int_service(struct mz8310_int_conf *icf)
|
||||
{
|
||||
icf->cnt++;
|
||||
|
||||
if(icf->user_service)
|
||||
(*icf->user_service)(icf->user_param);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following are provided for mz8310 access from the shell
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_cmd()
|
||||
*/
|
||||
int mz8310_cmd(
|
||||
unsigned value,
|
||||
unsigned card,
|
||||
unsigned chip
|
||||
)
|
||||
{
|
||||
volatile unsigned char *cmd = MZ8310_CMD_ADDR(card,chip);
|
||||
|
||||
*cmd = value;
|
||||
|
||||
return *cmd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_rdata()
|
||||
*/
|
||||
int mz8310_rdata(int card, int chip)
|
||||
{
|
||||
volatile unsigned short *data = MZ8310_DATA_ADDR(card,chip);
|
||||
|
||||
return *data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_wdata()
|
||||
*/
|
||||
int mz8310_wdata(
|
||||
unsigned value,
|
||||
unsigned card,
|
||||
unsigned chip
|
||||
)
|
||||
{
|
||||
volatile uint16_t *data = MZ8310_DATA_ADDR(card,chip);
|
||||
|
||||
*data = value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_reset
|
||||
*/
|
||||
LOCAL int mz8310_reset(void)
|
||||
{
|
||||
short card,channel,chip;
|
||||
|
||||
for (card = 0; card < mz8310_card_count; card++){
|
||||
FASTLOCK(&mzconf[card].lock);
|
||||
for ( channel = 0; channel < tm_num_channels[MZ8310]; channel++){
|
||||
if (mzconf[card].icf[channel].cnt){
|
||||
chip = channel/MZ8310CHANONCHIP;
|
||||
|
||||
stc_one_shot(
|
||||
0,
|
||||
10,
|
||||
0,
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip),
|
||||
channel % MZ8310CHANONCHIP,
|
||||
0);
|
||||
}
|
||||
}
|
||||
FASTUNLOCK(&mzconf[card].lock);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
74
src/drv/ansi/drvMz8310.h
Normal file
74
src/drv/ansi/drvMz8310.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* drvMz8310.c */
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* Routines specific to the MZ8310. Low level routines for the AMD STC in
|
||||
* stc_driver.c
|
||||
* Author: Jeff Hill
|
||||
* Date: Feb 1989
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification History
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#define MZ8310_SUCCESS 0
|
||||
|
||||
typedef long mz8310Stat;
|
||||
|
||||
mz8310Stat mz8310_one_shot_read(
|
||||
unsigned *preset, /* TRUE or COMPLEMENT logic */
|
||||
double *edge0_delay, /* sec */
|
||||
double *edge1_delay, /* sec */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned *int_source /* (FALSE)External/(TRUE)Internal src */
|
||||
);
|
||||
|
||||
mz8310Stat mz8310_one_shot(
|
||||
unsigned preset, /* TRUE or COMPLEMENT logic */
|
||||
double edge0_delay, /* sec */
|
||||
double edge1_delay, /* set */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned int_source, /* (FALSE)External/ (TRUE)Internal source */
|
||||
void (*event_rtn)(void *pParam), /* subroutine to run on events */
|
||||
void *event_rtn_param /* parameter to pass to above routine */
|
||||
);
|
||||
|
||||
int mz8310_cmd(
|
||||
unsigned value,
|
||||
unsigned card,
|
||||
unsigned chip
|
||||
);
|
||||
|
||||
int mz8310_rdata(int card, int chip);
|
||||
|
||||
int mz8310_wdata(
|
||||
unsigned value,
|
||||
unsigned card,
|
||||
unsigned chip
|
||||
);
|
||||
|
||||
|
||||
290
src/drv/ansi/drvStc.c
Normal file
290
src/drv/ansi/drvStc.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/* drvStc.c */
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* The following are specific driver routines for the AMD STC
|
||||
*
|
||||
* NOTE: if multiple threads use these routines at once you must provide locking
|
||||
* so command/data sequences are gauranteed. See mz8310_driver.c for examples.
|
||||
*
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: Feb 89
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*
|
||||
* joh 022089 Init Release
|
||||
* joh 042889 Added read back
|
||||
* joh 111789 Fixed reset goes to byte mode bug
|
||||
* joh 121090 Fixed confusion about the polarity of internal/external
|
||||
* clock between DB and the drivers.
|
||||
* joh 110791 Prevent the stc from generating tc prior to the trigger
|
||||
* in delayed pulse mode by forcing edge 0 delays of zero to be
|
||||
* a delay of one instead.
|
||||
* joh 010491 force all edge 0 delays less than two to two
|
||||
* joh 082493 ANSI C and EPICS return codes
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdioLib.h>
|
||||
#include <vxLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <drvSup.h>
|
||||
#include <module_types.h>
|
||||
#include <drvStc.h>
|
||||
#include <devLib.h>
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* stc_io_report()
|
||||
*/
|
||||
stcStat stc_io_report(
|
||||
volatile uint8_t *pcmd,
|
||||
volatile uint16_t *pdata
|
||||
)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint16_t data;
|
||||
|
||||
if(vxMemProbe((char *)pcmd, READ, sizeof(cmd), (char *)&cmd) != OK)
|
||||
return S_dev_noDevice;
|
||||
if(vxMemProbe((char *)pdata, READ, sizeof(data), (char *)&data) != OK)
|
||||
return S_dev_noDevice;
|
||||
|
||||
/*
|
||||
* addd AMD STC status here
|
||||
*/
|
||||
|
||||
return STC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* stc_init()
|
||||
*/
|
||||
stcStat stc_init(
|
||||
volatile uint8_t *pcmd,
|
||||
volatile uint16_t *pdata,
|
||||
unsigned master_mode
|
||||
)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint16_t data;
|
||||
unsigned channel;
|
||||
|
||||
if(vxMemProbe((char *)pcmd, READ, sizeof(cmd), (char *)&cmd) != OK)
|
||||
return S_dev_noDevice;
|
||||
if(vxMemProbe((char *)pdata, READ, sizeof(data), (char *)&data) != OK)
|
||||
return S_dev_noDevice;
|
||||
|
||||
/*
|
||||
* go to 16 bit mode in order to test the master mode register
|
||||
*/
|
||||
STC_BUS16;
|
||||
if(master_mode != STC_MASTER_MODE){
|
||||
|
||||
/*
|
||||
* start in a known state
|
||||
*/
|
||||
STC_RESET;
|
||||
|
||||
/*
|
||||
* required since the reset puts it in byte mode
|
||||
*/
|
||||
STC_BUS16;
|
||||
STC_SET_MASTER_MODE(master_mode);
|
||||
for(channel=0; channel<CHANONCHIP; channel++)
|
||||
STC_LOAD;
|
||||
}
|
||||
|
||||
return STC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* stc_one_shot_read()
|
||||
*/
|
||||
stcStat stc_one_shot_read(
|
||||
unsigned *preset,
|
||||
unsigned short *edge0_count,
|
||||
unsigned short *edge1_count,
|
||||
volatile uint8_t *pcmd,
|
||||
volatile uint16_t *pdata,
|
||||
unsigned channel,
|
||||
unsigned *int_source
|
||||
)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint16_t data;
|
||||
uint16_t mode;
|
||||
uint16_t edge0;
|
||||
uint16_t edge1;
|
||||
|
||||
if(vxMemProbe((char *)pcmd, READ, sizeof(cmd), (char *)&cmd) != OK)
|
||||
return S_dev_noDevice;
|
||||
if(vxMemProbe((char *)pdata, READ, sizeof(data), (char *)&data) != OK)
|
||||
return S_dev_noDevice;
|
||||
|
||||
if(channel>=CHANONCHIP)
|
||||
return S_dev_badSignalNumber;
|
||||
|
||||
STC_CTR_READ(mode, edge0, edge1);
|
||||
|
||||
/*
|
||||
* Only return values if the counter is in the proper mode
|
||||
* see stc_one_shot() for info on conversions and functions selected
|
||||
* by these bit fields
|
||||
*/
|
||||
if(mode == 0xc16a){
|
||||
*int_source = FALSE;
|
||||
*preset = TRUE;
|
||||
*edge0_count = ~edge0;
|
||||
*edge1_count = ~edge1+1;
|
||||
}
|
||||
else if(mode == 0xc162){
|
||||
*int_source = FALSE;
|
||||
*preset = FALSE;
|
||||
*edge0_count = edge0-1;
|
||||
*edge1_count = edge1;
|
||||
}
|
||||
else if(mode == 0xcb6a){
|
||||
*int_source = TRUE;
|
||||
*preset = TRUE;
|
||||
*edge0_count = ~edge0;
|
||||
*edge1_count = ~edge1+1;
|
||||
}
|
||||
else if(mode == 0xcb62){
|
||||
*int_source = TRUE;
|
||||
*preset = FALSE;
|
||||
*edge0_count = edge0-1;
|
||||
*edge1_count = edge1;
|
||||
}
|
||||
else
|
||||
return S_dev_internal;
|
||||
|
||||
return STC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* stc_one_shot()
|
||||
*/
|
||||
stcStat stc_one_shot(
|
||||
unsigned preset,
|
||||
unsigned edge0_count,
|
||||
unsigned edge1_count,
|
||||
volatile uint8_t *pcmd,
|
||||
volatile uint16_t *pdata,
|
||||
unsigned channel,
|
||||
unsigned int_source
|
||||
)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint16_t data;
|
||||
|
||||
if(vxMemProbe((char *)pcmd, READ, sizeof(cmd), (char *)&cmd) != OK)
|
||||
return S_dev_noDevice;
|
||||
if(vxMemProbe((char *)pdata, READ, sizeof(data), (char *)&data) != OK)
|
||||
return S_dev_noDevice;
|
||||
if(channel>=CHANONCHIP)
|
||||
return S_dev_badSignalNumber;
|
||||
|
||||
/*
|
||||
* joh 110791
|
||||
* Prevent the stc from generating tc prior to the trigger
|
||||
* in delayed pulse mode by forcing edge 0 delays of zero to be
|
||||
* a delay of one instead.
|
||||
*
|
||||
* 010492
|
||||
* Strange extra edges occur when the delay is 0 or 1
|
||||
* and the counter is reinitialized to a width of
|
||||
* zero so I have disabled a delay of one also
|
||||
*
|
||||
* These extra edges occur when TC is set
|
||||
*/
|
||||
|
||||
if(edge0_count < 2)
|
||||
edge0_count = 2;
|
||||
|
||||
STC_DISARM;
|
||||
|
||||
/*
|
||||
* active positive going edge (gate input)
|
||||
* count on the rising edge of source
|
||||
* ctr source: (F1- internal) (SRC1- external)
|
||||
* mode L - Hardware triggered delayed pulse one-shot
|
||||
* binary count
|
||||
* count down (count up if preset is TRUE)
|
||||
* TC toggled output
|
||||
*
|
||||
* see chapter 7 of the Am9513 STC tech man concerning count + 1
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: I must be able to read back the state of the preset later
|
||||
* so I encode this information in the count down/up bit.
|
||||
* count up on TRUE preset
|
||||
* count down on FALSE preset
|
||||
*
|
||||
* see stc_one_shot_read() above
|
||||
*/
|
||||
if(int_source){
|
||||
if(preset)
|
||||
STC_CTR_INIT(0xcb6a, ~edge0_count, ~edge1_count+1)
|
||||
else
|
||||
STC_CTR_INIT(0xcb62, edge0_count+1, edge1_count);
|
||||
}else{
|
||||
if(preset)
|
||||
STC_CTR_INIT(0xc16a, ~edge0_count, ~edge1_count+1)
|
||||
else
|
||||
STC_CTR_INIT(0xc162, edge0_count+1, edge1_count);
|
||||
}
|
||||
|
||||
STC_LOAD;
|
||||
/*
|
||||
*see chapter 7 of the Am9513 STC tech man concerning this step
|
||||
*/
|
||||
|
||||
STC_STEP;
|
||||
|
||||
STC_SET_TC(preset);
|
||||
|
||||
/*
|
||||
* Only arm counter if the pulse has a finite duration
|
||||
*/
|
||||
if(edge1_count != 0){
|
||||
STC_ARM;
|
||||
}
|
||||
|
||||
return STC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
107
src/drv/ansi/drvStc.h
Normal file
107
src/drv/ansi/drvStc.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* drvStc.h */
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* The following are specific driver routines for the AMD STC
|
||||
*
|
||||
* NOTE: if multiple threads use these routines at once you must provide locking
|
||||
* so command/data sequences are gauranteed. See mz8310_driver.c for examples.
|
||||
*
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: Feb 89
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*
|
||||
* joh 022089 Init Release
|
||||
* joh 082493 ANSI C and EPICS return codes
|
||||
*/
|
||||
|
||||
/*
|
||||
* AMD STC constants
|
||||
*/
|
||||
#define CHANONCHIP 5U
|
||||
#define CHIPCHAN (channel%CHANONCHIP)
|
||||
#define CHIPNUM (channel/CHANONCHIP)
|
||||
|
||||
#define STC_RESET *pcmd = 0xffU
|
||||
#define STC_BUS16 *pcmd = 0xefU
|
||||
#define STC_SET_MASTER_MODE(D) {*pcmd = 0x17U; *pdata=(D);}
|
||||
#define STC_MASTER_MODE (*pcmd = 0x17U, *pdata)
|
||||
|
||||
#define STC_CTR_INIT(MODE,LOAD,HOLD)\
|
||||
{*pcmd = CHIPCHAN+1; *pdata = (MODE); *pdata = (LOAD); *pdata= (HOLD);}
|
||||
|
||||
#define STC_CTR_READ(MODE,LOAD,HOLD)\
|
||||
{*pcmd = CHIPCHAN+1; (MODE) = *pdata; (LOAD) = *pdata; (HOLD) = *pdata;}
|
||||
|
||||
#define STC_SET_TC(D) *pcmd = 0xe0U | ((D)?8:0)|(CHIPCHAN+1U)
|
||||
|
||||
#define STC_LOAD *pcmd = 0x40U | 1<<(CHIPCHAN)
|
||||
#define STC_STEP *pcmd = 0xf0U | (CHIPCHAN+1U)
|
||||
#define STC_ARM *pcmd = 0x20U | 1<<CHIPCHAN
|
||||
#define STC_DISARM *pcmd = 0xc0U | 1<<CHIPCHAN
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* return type of the stc routines
|
||||
*/
|
||||
typedef long stcStat;
|
||||
#define STC_SUCCESS 0
|
||||
|
||||
|
||||
stcStat stc_io_report(
|
||||
volatile uint8_t *pcmd,
|
||||
volatile uint16_t *pdata
|
||||
);
|
||||
|
||||
|
||||
stcStat stc_init(
|
||||
volatile uint8_t *pcmd,
|
||||
volatile uint16_t *pdata,
|
||||
unsigned master_mode
|
||||
);
|
||||
|
||||
stcStat stc_one_shot_read(
|
||||
unsigned *preset,
|
||||
uint16_t *edge0_count,
|
||||
uint16_t *edge1_count,
|
||||
volatile uint8_t *pcmd,
|
||||
volatile uint16_t *pdata,
|
||||
unsigned channel,
|
||||
unsigned *int_source
|
||||
);
|
||||
|
||||
stcStat stc_one_shot(
|
||||
unsigned preset,
|
||||
unsigned edge0_count,
|
||||
unsigned edge1_count,
|
||||
volatile uint8_t *pcmd,
|
||||
volatile uint16_t *pdata,
|
||||
unsigned channel,
|
||||
unsigned int_source
|
||||
);
|
||||
|
||||
250
src/drv/ansi/drvTime.c
Normal file
250
src/drv/ansi/drvTime.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/* drvTime.c */
|
||||
/* base/src/drv $Id$ */
|
||||
/* Glue between timing_drivers and the GTA database
|
||||
* Author: Jeff Hill
|
||||
* Date: Feb 89
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos Natjonal Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* joh 02-20-89 Init Release
|
||||
* joh 11-16-89 added vxi timing
|
||||
* bg 11-18-91 added time_io_report
|
||||
* bg 02-24-91 added levels to time_io_report.
|
||||
* bg 06-26-92 Combined time_driver.c and drvTime.c
|
||||
* joh 08-05-92 removed report & init routines
|
||||
*/
|
||||
|
||||
static char *sccsID = "@(#)drvTime.c 1.10\t9/9/93";
|
||||
|
||||
/* drvTime.c - Driver Support Routines for Time */
|
||||
#include <vxWorks.h>
|
||||
#include <logLib.h>
|
||||
|
||||
#include <module_types.h>
|
||||
#include <epicsPrint.h>
|
||||
|
||||
#include <drvMz8310.h>
|
||||
#include <drvAt5Vxi.h>
|
||||
|
||||
struct pulse{
|
||||
double offset;
|
||||
double width;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* time_driver_read()
|
||||
*
|
||||
*
|
||||
*/
|
||||
int time_driver_read
|
||||
(
|
||||
card, /* 0 through ... */
|
||||
channel, /* 0 through chans on card */
|
||||
card_type, /* module type as stored in GTA DB */
|
||||
int_source, /* (TRUE)External/ (FALSE)Internal source */
|
||||
preset, /* TRUE or COMPLEMENT logic */
|
||||
pulses, /* ptr to array of structure describing pulses */
|
||||
npulses, /* N elements found */
|
||||
npulmax /* N elements in the caller's array */
|
||||
)
|
||||
unsigned card;
|
||||
unsigned channel;
|
||||
unsigned card_type;
|
||||
unsigned *int_source;
|
||||
unsigned *preset;
|
||||
struct pulse *pulses;
|
||||
unsigned *npulses;
|
||||
unsigned npulmax;
|
||||
{
|
||||
int status;
|
||||
|
||||
*npulses=0;
|
||||
|
||||
switch(card_type){
|
||||
case MZ8310:
|
||||
if(npulmax<1)
|
||||
return ERROR;
|
||||
status = mz8310_one_shot_read (
|
||||
preset,
|
||||
&pulses->offset,
|
||||
&pulses->width,
|
||||
card,
|
||||
channel,
|
||||
int_source
|
||||
);
|
||||
if(status==0)
|
||||
*npulses=1;
|
||||
|
||||
return status;
|
||||
case VXI_AT5_TIME:
|
||||
if(npulmax<1)
|
||||
return ERROR;
|
||||
status = at5vxi_one_shot_read (
|
||||
preset,
|
||||
&pulses->offset,
|
||||
&pulses->width,
|
||||
card,
|
||||
channel,
|
||||
int_source
|
||||
);
|
||||
if(status==0)
|
||||
*npulses=1;
|
||||
|
||||
return status;
|
||||
case DG535:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
epicsPrintf("time_driver: No support for that type of timing card\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
||||
int time_driver (
|
||||
card, /* 0 through ... */
|
||||
channel, /* 0 through chans on card */
|
||||
card_type, /* module type as stored in GTA DB */
|
||||
int_source, /* (TRUE)External/ (FALSE)Internal source */
|
||||
preset, /* TRUE or COMPLEMENT logic */
|
||||
pulses, /* ptr to array of structure describing pulses */
|
||||
npulses, /* N elements in this array */
|
||||
eventrtn, /* routine to run on events */
|
||||
eventrtnarg /* argument to above rtn */
|
||||
)
|
||||
unsigned int card;
|
||||
unsigned int channel;
|
||||
unsigned int card_type;
|
||||
unsigned int int_source;
|
||||
int preset;
|
||||
struct pulse *pulses;
|
||||
unsigned int npulses;
|
||||
void (*eventrtn)(void *pParam);
|
||||
void *eventrtnarg;
|
||||
{
|
||||
|
||||
switch(card_type){
|
||||
case MZ8310:
|
||||
if(npulses != 1)
|
||||
return ERROR;
|
||||
return mz8310_one_shot (
|
||||
preset,
|
||||
pulses->offset,
|
||||
pulses->width,
|
||||
card,
|
||||
channel,
|
||||
int_source,
|
||||
eventrtn,
|
||||
eventrtnarg
|
||||
);
|
||||
case VXI_AT5_TIME:
|
||||
if(npulses != 1)
|
||||
return ERROR;
|
||||
return at5vxi_one_shot (
|
||||
preset,
|
||||
pulses->offset,
|
||||
pulses->width,
|
||||
card,
|
||||
channel,
|
||||
int_source,
|
||||
eventrtn,
|
||||
eventrtnarg
|
||||
);
|
||||
case DG535:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
epicsPrintf("time_driver: No support for that type of timing card\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int time_test()
|
||||
{
|
||||
unsigned int card=0;
|
||||
unsigned int channel=0;
|
||||
unsigned int card_type=MZ8310;
|
||||
unsigned int int_source=1;
|
||||
int preset=1;
|
||||
static struct
|
||||
pulse pulses={.00001,.00001};
|
||||
unsigned int npulses = 1;
|
||||
|
||||
unsigned int t_int_source;
|
||||
int t_preset;
|
||||
struct pulse t_pulses;
|
||||
unsigned int t_npulses;
|
||||
|
||||
int status;
|
||||
|
||||
status =
|
||||
time_driver (
|
||||
card, /* 0 through ... */
|
||||
channel, /* 0 through chans on card */
|
||||
card_type, /* module type as stored in GTA DB */
|
||||
int_source, /* (TRUE)External/ (FALSE)Internal source */
|
||||
preset, /* TRUE or COMPLEMENT logic */
|
||||
&pulses, /* ptr to array of structure describing pulses */
|
||||
npulses, /* N elements in this array */
|
||||
NULL, /* routine to run on events */
|
||||
NULL /* argument to above rtn */
|
||||
);
|
||||
if(status==ERROR)
|
||||
return ERROR;
|
||||
|
||||
|
||||
status =
|
||||
time_driver_read(
|
||||
card, /* 0 through ... */
|
||||
channel, /* 0 through chans on card */
|
||||
card_type, /* module type as stored in GTA DB */
|
||||
&t_int_source, /* (TRUE)External/ (FALSE)Internal source */
|
||||
&t_preset, /* TRUE or COMPLEMENT logic */
|
||||
&t_pulses, /* ptr to array of structure describing pulses */
|
||||
&t_npulses, /* N elements found */
|
||||
1 /* max N elements in this array */
|
||||
);
|
||||
if(status==ERROR)
|
||||
return ERROR;
|
||||
|
||||
|
||||
epicsPrintf( "wrote: preset %x internal-clk %x delay %f width %f \n",
|
||||
preset,
|
||||
int_source,
|
||||
pulses.offset,
|
||||
pulses.width);
|
||||
epicsPrintf( "read: preset %x internal-clk %x delay %f width %f count %x\n",
|
||||
t_preset,
|
||||
t_int_source,
|
||||
t_pulses.offset,
|
||||
t_pulses.width,
|
||||
t_npulses);
|
||||
return OK;
|
||||
}
|
||||
@@ -1304,13 +1304,14 @@ abDoneTask(){
|
||||
*
|
||||
* simulate a change of state interrupt from the Allen-Bradley
|
||||
*/
|
||||
unsigned char ab_old_binary_ins[AB_MAX_LINKS*AB_MAX_ADAPTERS*AB_MAX_CARDS];
|
||||
unsigned short ab_old_binary_ins[AB_MAX_LINKS][AB_MAX_ADAPTERS][AB_MAX_CARDS];
|
||||
ab_bi_cos_simulator()
|
||||
{
|
||||
register struct ab_region *p6008;
|
||||
register unsigned short link;
|
||||
register unsigned short *pcard;
|
||||
unsigned short *ps_input,*ps_oldval;
|
||||
unsigned short new;
|
||||
unsigned short *pold;
|
||||
short adapter,card,inpinx;
|
||||
short first_scan,first_scan_complete;
|
||||
short adapter_status_change;
|
||||
@@ -1323,8 +1324,6 @@ ab_bi_cos_simulator()
|
||||
first_scan_complete = FALSE;
|
||||
first_scan = TRUE;
|
||||
for(;;){
|
||||
/* check each link */
|
||||
link = 0;
|
||||
for (link = 0; link < AB_MAX_LINKS; link++){
|
||||
if ((p6008 = p6008s[link]) == 0) continue;
|
||||
for (adapter = 0; adapter < AB_MAX_ADAPTERS; adapter++){
|
||||
@@ -1335,28 +1334,24 @@ ab_bi_cos_simulator()
|
||||
for (card = 0; card < AB_MAX_CARDS; card++){
|
||||
pcard = &ab_config[link][adapter][card];
|
||||
inpinx = (adapter * AB_CARD_ADAPTER) + card;
|
||||
pold = &ab_old_binary_ins[link][adapter][card];
|
||||
if ((*pcard & AB_INTERFACE_TYPE) != AB_BI_INTERFACE) continue;
|
||||
|
||||
if ((*pcard & AB_CARD_TYPE) == ABBI_16_BIT){
|
||||
/* sixteen bit byte ordering in dual ported memory */
|
||||
/* byte 0011 2233 4455 6677 8899 AABB */
|
||||
/* card 0000 2222 4444 6666 8888 AAAA */
|
||||
if (inpinx & 0x1) continue;
|
||||
ps_input = (unsigned short *)&(p6008->iit[inpinx]);
|
||||
ps_oldval = (unsigned short *)&(ab_old_binary_ins[inpinx]);
|
||||
if ((*ps_input != *ps_oldval) || first_scan || adapter_status_change){
|
||||
scanIoRequest(ioscanpvt[link][adapter][card]);
|
||||
*ps_oldval = *ps_input;
|
||||
}
|
||||
new = *(unsigned short *)&(p6008->iit[inpinx]);
|
||||
}else{
|
||||
/* eight bit byte ordering in dual ported memory */
|
||||
/* 1100 3322 5544 7766 9988 BBAA */
|
||||
if (inpinx & 0x1) inpinx--; /* shuffle those bytes */
|
||||
else inpinx++;
|
||||
if ((p6008->iit[inpinx] != ab_old_binary_ins[inpinx]) || first_scan || adapter_status_change){
|
||||
scanIoRequest(ioscanpvt[link][adapter][card]);
|
||||
ab_old_binary_ins[inpinx] = p6008->iit[inpinx];
|
||||
}
|
||||
new = (unsigned short)(p6008->iit[inpinx]);
|
||||
}
|
||||
if((new!=*pold) || first_scan || adapter_status_change){
|
||||
scanIoRequest(ioscanpvt[link][adapter][card]);
|
||||
*pold = new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,10 @@
|
||||
* This driver currently needs work on error message generation.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.36 1994/12/16 16:11:26 winans
|
||||
* Added debug flag guards to ALL printing. The default debug level is set
|
||||
* to 1 -- this provides the same output as the old version.
|
||||
*
|
||||
* Revision 1.35 1994/12/12 16:02:57 winans
|
||||
* Rewrote the init code so that it always returns a zero (don't kill the
|
||||
* startup.cmd file.) It is possible that this could cause some confusion
|
||||
@@ -2459,10 +2463,13 @@ STATIC int pepTxTask(int link)
|
||||
|
||||
/* Send the message in polled mode */
|
||||
txTCount = pnode->txMsg.length;
|
||||
|
||||
/* BUG -- would be nice if we verify the length >6 here */
|
||||
|
||||
txCCount = 0;
|
||||
txMsg = &(pnode->txMsg.length);
|
||||
|
||||
while ((txCCount < txTCount) && (pBBLink[link]->abortFlag == 0)) {
|
||||
while ((txCCount < txTCount -1) && (pBBLink[link]->abortFlag == 0)) {
|
||||
|
||||
stuck = 1000;
|
||||
while (((pBBLink[link]->l.PepLink.bbRegs->stat_ctl & PEP_BB_TFNF)
|
||||
@@ -2487,12 +2494,13 @@ STATIC int pepTxTask(int link)
|
||||
if (bbDebug>30)
|
||||
printf("pepTxTask(%d): outputting %2.2X\n",link,0x00);
|
||||
pBBLink[link]->l.PepLink.bbRegs->data = 0x00;
|
||||
}
|
||||
else if (txCCount == (txTCount -1)) { /* last byte of package */
|
||||
#if 0
|
||||
} else if (txCCount == (txTCount -1)) { /* last byte of package */
|
||||
pBBLink[link]->l.PepLink.bbRegs->stat_ctl = *txMsg;
|
||||
if (bbDebug>30)
|
||||
printf("pepTxTask(%d): outputting last byte %2.2X\n",
|
||||
link,*txMsg);
|
||||
#endif
|
||||
} else { /* regular ol' message byte */
|
||||
pBBLink[link]->l.PepLink.bbRegs->data = *txMsg;
|
||||
if (bbDebug>30)
|
||||
@@ -2536,6 +2544,11 @@ STATIC int pepTxTask(int link)
|
||||
{
|
||||
/* Lock the busy list */
|
||||
semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER);
|
||||
|
||||
pBBLink[link]->l.PepLink.bbRegs->stat_ctl = *txMsg;
|
||||
if (bbDebug>30)
|
||||
printf("pepTxTask(%d): outputting last byte %2.2X\n",
|
||||
link,*txMsg);
|
||||
|
||||
/* set the retire time */
|
||||
pnode->retire = tickGet();
|
||||
|
||||
10
src/drv/old/Makefile
Normal file
10
src/drv/old/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
EPICS=../../../..
|
||||
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
include $(EPICS)/config/RULES_ARCHS
|
||||
|
||||
56
src/drv/old/Makefile.Vx
Normal file
56
src/drv/old/Makefile.Vx
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
EPICS = ../../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_CFLAGS = -fshared-data -fvolatile -mnobitfield -traditional
|
||||
|
||||
SRCS.c += ../module_types.c
|
||||
SRCS.c += ../drvBB232.c
|
||||
SRCS.c += ../drvBb902.c
|
||||
SRCS.c += ../drvBb910.c
|
||||
SRCS.c += ../drvBitBus.c
|
||||
SRCS.c += ../drvComet.c
|
||||
SRCS.c += ../drvCompuSm.c
|
||||
SRCS.c += ../drvDvx.c
|
||||
SRCS.c += ../drvFp.c
|
||||
SRCS.c += ../drvFpm.c
|
||||
SRCS.c += ../drvGpib.c
|
||||
SRCS.c += ../drvJgvtr1.c
|
||||
SRCS.c += ../drvMsg.c
|
||||
SRCS.c += ../drvOms.c
|
||||
# SRCS.c += ../drvTranServ.c
|
||||
SRCS.c += ../drvVmi4100.c
|
||||
SRCS.c += ../drvXy010.c
|
||||
SRCS.c += ../drvXy210.c
|
||||
SRCS.c += ../drvXy220.c
|
||||
SRCS.c += ../drvXy240.c
|
||||
SRCS.c += ../drvXy566.c
|
||||
|
||||
TARGETS += module_types.o
|
||||
TARGETS += drvBB232.o
|
||||
TARGETS += drvBb902.o
|
||||
TARGETS += drvBb910.o
|
||||
TARGETS += drvBitBus.o
|
||||
TARGETS += drvComet.o
|
||||
TARGETS += drvCompuSm.o
|
||||
TARGETS += drvDvx.o
|
||||
TARGETS += drvFp.o
|
||||
TARGETS += drvFpm.o
|
||||
TARGETS += drvGpib.o
|
||||
TARGETS += drvJgvtr1.o
|
||||
TARGETS += drvMsg.o
|
||||
TARGETS += drvOms.o
|
||||
# TARGETS += drvTranServ.o
|
||||
TARGETS += drvVmi4100.o
|
||||
TARGETS += drvXy010.o
|
||||
TARGETS += drvXy210.o
|
||||
TARGETS += drvXy220.o
|
||||
TARGETS += drvXy240.o
|
||||
TARGETS += drvXy566.o
|
||||
|
||||
include $(EPICS)/config/RULES.Vx
|
||||
|
||||
30
src/drv/old/VXI_SETUP_README
Normal file
30
src/drv/old/VXI_SETUP_README
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
The CPU030 may need to have the nivxi path set correctly:
|
||||
From the vxWorks shell type "vxitedit"
|
||||
take option 2
|
||||
take option 3
|
||||
type list
|
||||
type modify 0
|
||||
type in the correct path when promped
|
||||
(the path should end in nivxi
|
||||
and should traverse the niCpu030
|
||||
directories shipped with the 030
|
||||
ie somethin of the form "???/config/niCPU030/nivxi"
|
||||
type save
|
||||
type exit
|
||||
.
|
||||
.
|
||||
.
|
||||
|
||||
|
||||
You may may need to setup front panel to backplane trigger
|
||||
routing:
|
||||
|
||||
To take a TTL input and map it to VXI backplane ECL trigger 0
|
||||
type in (to the vxWorks shell):
|
||||
|
||||
epvxiRouteTriggerECL(<logical address>, 1, 0)
|
||||
|
||||
where <logical address> specifies the card with the
|
||||
front panel trigger connection.
|
||||
|
||||
2505
src/drv/old/drvAbOLD.c
Normal file
2505
src/drv/old/drvAbOLD.c
Normal file
File diff suppressed because it is too large
Load Diff
348
src/drv/old/drvAbOLD.h
Normal file
348
src/drv/old/drvAbOLD.h
Normal file
@@ -0,0 +1,348 @@
|
||||
/* drvAb.h */
|
||||
/* base/src/drv $Id$ */
|
||||
/* header file for the Allen-Bradley Remote Serial IO
|
||||
*
|
||||
* Author: Bob Dalesio
|
||||
* Date: 6-21-88
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 02-01-89 lrd added IFE module support
|
||||
* changed max chan from 8 to 16
|
||||
* .02 04-24-89 lrd moved AB_* to module_types.h
|
||||
* added bit to config table for attempting
|
||||
* initialization
|
||||
* .03 01-30-90 lrd add plc/adapter distinction
|
||||
* .04 03-03-92 mrk added defs for Type E,T,R,S Tcs
|
||||
*
|
||||
*/
|
||||
/* NOTES:
|
||||
* 1. We are using double slot addressing which dictates that there is an
|
||||
* output slot for each input slot.
|
||||
* Slots 1,3,5,7,9,11 are input slots
|
||||
* Slots 2,4,6,8,10,12 are output slots
|
||||
* The database uses card numbers 0-11 to address slots 1-12
|
||||
* 2. This code has not been tested for more than one link (6008). More
|
||||
* extensive modifications are required to implement this
|
||||
*/
|
||||
|
||||
/* osw - operating status word definitions */
|
||||
#define PROGRAM_MODE 0x01 /* program/reset mode */
|
||||
#define TEST_MODE 0x02 /* test/reset mode */
|
||||
#define RUN_MODE 0x04 /* run mode */
|
||||
#define DEBUG_MODE 0x08 /* we are debugging */
|
||||
#define UNSOLICITED_BT 0x10 /* detected block xfer we didn't want */
|
||||
#define BTS_QUEUED 0x20 /* block xfers queued */
|
||||
#define ADAPTER_FAULT 0x40 /* at least one faulted adapter in scan
|
||||
list */
|
||||
#define ADAP_FLT_CHNG 0x80 /* a change has occurred in an adapter's
|
||||
status...do link status check */
|
||||
#define OSW_MASK 0xdf /* these are the bits of interest */
|
||||
|
||||
/* commands to the 6008 link controller */
|
||||
#define AUTO_CONF 0x10
|
||||
#define SCAN_LIST 0x11
|
||||
#define SET_UP 0x13
|
||||
#define SET_MODE 0x20
|
||||
#define LINK_STATUS 0x21
|
||||
|
||||
/* block transfer command definitions */
|
||||
#define AB_READ 0x01
|
||||
#define AB_WRITE 0x02
|
||||
|
||||
/* these are used for the SET_UP command */
|
||||
#define DEF_RATE 0x01 /* default baud rate 57.6K */
|
||||
#define FAST_RATE 0x02 /* 115.2 KB */
|
||||
#define NO_CHANGE 0xff /* no change */
|
||||
#define AB_IL 0x05 /* interrupt level */
|
||||
#define DEBUG 0x01 /* debug - turn off watchdog timer */
|
||||
#define AB_INT_ENABLE 0x00 /* interrupt enabled */
|
||||
#define AB_SYSFAIL_DISABLE 0x01 /* disable VMEbus SYSFAIL signal */
|
||||
|
||||
/* status returned through the dual ported memory */
|
||||
#define SCANNER_POWERUP 0x90 /* power up status */
|
||||
#define BT_ACCEPTED 0x2f /* block trans accepted by scanner */
|
||||
#define BT_TIMEOUT 0x23 /* block transfer timeout */
|
||||
|
||||
|
||||
/* DUAL PORTED MEMORY AREA DEFINITION */
|
||||
/* mail box definition */
|
||||
struct dp_mbox {
|
||||
unsigned short conf_stat; /* confirmation status word */
|
||||
unsigned short command; /* command word */
|
||||
unsigned short address; /* module address */
|
||||
unsigned short bt_tag; /* block transfer tag number */
|
||||
unsigned short resv[9]; /* 18 bytes reserved */
|
||||
unsigned char dummy;
|
||||
unsigned char fl_lock; /* semaphore word byte */
|
||||
unsigned short data_len; /* length of data sent/returned */
|
||||
union {
|
||||
unsigned short wd[64]; /* 64 words of data */
|
||||
unsigned char bd[128]; /* or 128 bytes of data */
|
||||
} da;
|
||||
};
|
||||
|
||||
/* entire region with the mailbox */
|
||||
struct ab_region {
|
||||
unsigned char oit[128]; /* output image table */
|
||||
unsigned char iit[128]; /* input image table */
|
||||
unsigned short osw; /* operating status word */
|
||||
struct dp_mbox mail; /* dual port mail box */
|
||||
unsigned short gda[1872-66]; /* unused part gen data area */
|
||||
unsigned short sys_fail_set1; /* first byte to set for recovering from SYSFAIL */
|
||||
unsigned short sys_fail_set2; /* second byte to set for recovering from SYSFAIL */
|
||||
unsigned char vmeid[60]; /* scanner id */
|
||||
unsigned short sc_intr; /* to interrupt the scanner */
|
||||
unsigned short sc_pad; /* last word in scanner shared mem */
|
||||
};
|
||||
|
||||
/* Allen-Bradley IO configuration array equates */
|
||||
#define AB_NOT_INIT 0x0000
|
||||
#define AB_NO_CARD 0xffff
|
||||
#define AB_CARD_TYPE 0x001f
|
||||
#define AB_INTERFACE_TYPE 0x00e0
|
||||
#define AB_CONVERSION 0x0f00
|
||||
#define AB_PLC 0x1000
|
||||
#define AB_SENT_INIT 0x2000
|
||||
#define AB_UPDATE 0x4000
|
||||
#define AB_INIT_BIT 0x8000
|
||||
|
||||
/* interface types */
|
||||
#define AB_NOT_ASSIGNED 0x0000
|
||||
#define AB_BI_INTERFACE 0x0020
|
||||
#define AB_BO_INTERFACE 0x0040
|
||||
#define AB_AI_INTERFACE 0x0060
|
||||
#define AB_AO_INTERFACE 0x0080
|
||||
#define AB_BT_READ 0x00A0
|
||||
#define AB_BT_WRITE 0x00C0
|
||||
|
||||
|
||||
/* scale data - 16 bit min and a 16 bit max */
|
||||
struct ascale {
|
||||
unsigned short a_min;
|
||||
unsigned short a_max;
|
||||
};
|
||||
|
||||
/* defines and structures for analog outputs */
|
||||
/* configuration word 5 for the OFE module */
|
||||
/* FxxxHHHHLLLLPPPP */
|
||||
/* F - Data Format */
|
||||
/* 0x0 specifies BCD */
|
||||
/* 0x1 specifies Binary */
|
||||
/* HHHH - Max Scaling Polarity */
|
||||
/* LLLL - Min Scaling Polarity */
|
||||
/* PPPP - Value Polarity */
|
||||
#define OFE_BINARY 0x8000 /* talk binary instead of BCD */
|
||||
#define OFE_SCALING 0x0000 /* all positive */
|
||||
|
||||
struct ab1771ofe_write{
|
||||
unsigned short data[4]; /* data to write */
|
||||
unsigned short conf; /* config word */
|
||||
struct ascale scales[4]; /* min & max scaling */
|
||||
};
|
||||
|
||||
/* defines and structures for analog inputs */
|
||||
/* confgiuration word 0 for the IL module: */
|
||||
/* 7766554433221100 */
|
||||
/* 00 - Signal Range for Channel 0 */
|
||||
/* 0x0 specifies 1 - 5 Volts DC */
|
||||
/* 0x1 specifies 0 - 5 Volts DC */
|
||||
/* 0x2 specifies -5 - +5 Volts DC */
|
||||
/* 0x3 specifies -10 - +10 Volts DC */
|
||||
/* 11-77 - Signal Ranges for Channels 1 - 7 */
|
||||
#define IL_RANGE 0xffff /* volt inp for all channels -10 - 10V */
|
||||
|
||||
/* configuration word 1 for the IL module */
|
||||
/* 00000DD000000000 */
|
||||
/* DD - Data Format */
|
||||
/* 0x0 specifiesBinary Coded Decimal */
|
||||
/* 0x2 specifies 2s compliment binary */
|
||||
/* 0x3 specifies signed magnitude binary */
|
||||
#define IL_DATA_FORMAT 0x600 /* signed magnitude binary */
|
||||
|
||||
/* configuration word 2 for the IL module */
|
||||
/* HHHHHHHHLLLLLLLL */
|
||||
/* HHHHHHHH - Sign Bits for each of the max scaling value */
|
||||
/* LLLLLLLL - Sign Bits for each of the min scaling value */
|
||||
#define IL_MAX_SCALING_SIGN 0 /* max scale is always positive */
|
||||
#define IL_MIN_SCALING_SIGN 0xff /* min scale is always negative */
|
||||
#define IL_MAX_SCALE itobcd(4095) /* max scale is +4095 */
|
||||
#define IL_MIN_SCALE itobcd(4095) /* min scale is -4095 */
|
||||
#define IL_SCALE_SIGN ((IL_MAX_SCALING_SIGN << 8) | IL_MIN_SCALING_SIGN)
|
||||
#define IL_SCALE ((IL_MAX_SCALE << 8) | IL_MIN_SCALE)
|
||||
|
||||
struct ab1771il_config {
|
||||
unsigned short ranges; /* range for all channels */
|
||||
unsigned short conf; /* config word */
|
||||
unsigned short signs; /* scaling bits for sign */
|
||||
struct ascale scales[8]; /* min & max for 8 channels */
|
||||
};
|
||||
|
||||
struct ab1771il_read {
|
||||
unsigned short diag; /* diagnostic word */
|
||||
unsigned short urange; /* low byte - under range channels */
|
||||
unsigned short orange; /* low byte - over range channels */
|
||||
unsigned short sign; /* low byte - polarity 1 = negative */
|
||||
short data[8]; /* 8 data values (can be signed) */
|
||||
};
|
||||
|
||||
/* confgiuration word 0 and 1 for the IFE module: */
|
||||
/* 7766554433221100 */
|
||||
/* 1514131211109988 */
|
||||
/* 00 - Signal Range for Channel 0 */
|
||||
/* 0x0 specifies 1 - 5 Volts DC */
|
||||
/* 0x1 specifies 0 - 5 Volts DC */
|
||||
/* 0x2 specifies -5 - +5 Volts DC */
|
||||
/* 0x3 specifies -10 - +10 Volts DC */
|
||||
/* 11-15 - Signal Ranges for Channels 1 - 15 */
|
||||
#define IFE_RANGE 0xffff /* volt inp for all channels -10 - 10V */
|
||||
|
||||
/* configuration word 2 for the IFE module */
|
||||
/* 00000DDT 00000000 */
|
||||
/* DD - Data Format */
|
||||
/* 0x0 specifiesBinary Coded Decimal */
|
||||
/* 0x2 specifies 2s compliment binary */
|
||||
/* 0x3 specifies signed magnitude binary */
|
||||
/* T - Input Type */
|
||||
/* 0x0 specifies single ended */
|
||||
/* 0x1 specifies differential */
|
||||
#define IFE_DATA_FORMAT 0x700 /* signed magnitude binary/ differential */
|
||||
#define IFE_SE_DATA_FORMAT 0x600 /* signed magnitude binary/ single-ended */
|
||||
|
||||
/* configuration word 3 for the IFE module */
|
||||
/* LLLLLLLLLLLLLLLL */
|
||||
/* LLLLLLLL - Sign Bits for each of the min scaling value */
|
||||
#define IFE_MAX_SCALING_SIGN 0 /* max scale is always positive */
|
||||
#define IFE_MIN_SCALING_SIGN 0xff /* min scale is always negative */
|
||||
#define IFE_MAX_SCALE itobcd(4095) /* max scale is +4095 */
|
||||
#define IFE_MIN_SCALE itobcd(4095) /* min scale is -4095 */
|
||||
#define IFE_SCALE_SIGN ((IFE_MAX_SCALING_SIGN << 8) | IFE_MIN_SCALING_SIGN)
|
||||
#define IFE_SCALE ((IFE_MAX_SCALE << 8) | IFE_MIN_SCALE)
|
||||
|
||||
struct ab1771ife_config {
|
||||
unsigned short range1; /* range for all channels */
|
||||
unsigned short range2; /* range for all channels */
|
||||
unsigned short conf; /* config word */
|
||||
unsigned short minsigns; /* scaling bits for sign */
|
||||
unsigned short maxsigns; /* scaling bits for sign */
|
||||
struct ascale scales[16]; /* min & max for up to 16 channels */
|
||||
};
|
||||
|
||||
struct ab1771ife_read {
|
||||
unsigned short diag; /* diagnostic word */
|
||||
unsigned short urange; /* low byte - under range channels */
|
||||
unsigned short orange; /* low byte - over range channels */
|
||||
unsigned short sign; /* low byte - polarity 1 = negative */
|
||||
short data[16]; /* 16 data values (can be signed) */
|
||||
};
|
||||
|
||||
|
||||
/* defines and structures for thermocouple inputs */
|
||||
/* configuration word 0 for the IXE module: */
|
||||
/* SSSSSFFCUxxxxTTT */
|
||||
/* TTT - Thermocouple Type */
|
||||
/* xxxx - Not Used */
|
||||
/* U - Update cold junction 3/sec to calibrate */
|
||||
/* C - Conversion into degrees F or C */
|
||||
/* FF - Data Format */
|
||||
/* SSSSS - Sample Time */
|
||||
|
||||
/* xxxxxxxxxxxxxTTT - Thermocouple Types */
|
||||
#define IXE_MILLI 0x0000 /* Millivolt input */
|
||||
#define IXE_E 0x0001 /* "E" Thermocouple */
|
||||
#define IXE_J 0x0002 /* "J" Thermocouple */
|
||||
#define IXE_K 0x0003 /* "K" Thermocouple */
|
||||
#define IXE_T 0x0004 /* "T" Thermocouple */
|
||||
#define IXE_R 0x0005 /* "R" Thermocouple */
|
||||
#define IXE_S 0x0006 /* "S" Thermocouple */
|
||||
|
||||
#define K_DGF 2
|
||||
#define K_DGC 3
|
||||
#define J_DGF 4
|
||||
#define J_DGC 5
|
||||
#define E_DGF 6
|
||||
#define E_DGC 7
|
||||
#define T_DGF 8
|
||||
#define T_DGC 9
|
||||
#define R_DGF 10
|
||||
#define R_DGC 11
|
||||
#define S_DGF 12
|
||||
#define S_DGC 13
|
||||
|
||||
|
||||
/* xxxxxxxCxxxxxxxx - Conversion into degrees F or C */
|
||||
#define IXE_DEGC 0x0000
|
||||
#define IXE_DEGF 0x0100
|
||||
|
||||
/* xxxxxFFxxxxxxxxx - Data Format */
|
||||
#define IXE_BCD 0x0000 /* data is BCD */
|
||||
#define IXE_2SCOMP 0x0200 /* twos complement binary data */
|
||||
#define IXE_SIGNED 0x0400 /* signed magnitude " " */
|
||||
|
||||
/* SSSSSxxxxxxxxxxx - Scan Rate */
|
||||
#define IXE_HALFSEC 0x2800 /* sample time = 0.5 seconds */
|
||||
#define IXE_1SEC 0x5000 /* sample time = 1.0 seconds */
|
||||
#define IXE_2SECS 0xa000 /* sample time = 2.0 seconds */
|
||||
#define IXE_3SECS 0xf000 /* sample time = 3.0 seconds */
|
||||
|
||||
/* configuration data transfer to the IXE card */
|
||||
struct ab1771ixe_config {
|
||||
unsigned short conv_rate; /* conversion and scan rate data */
|
||||
unsigned short alarm_enable; /* low byte = channel alarm enable */
|
||||
unsigned short limit_polarity; /* low & hi alarm polarity bits */
|
||||
struct ascale alarm_limits[8];/* low & hi alarm values */
|
||||
unsigned short calibration[8]; /* gain & zero correction values */
|
||||
};
|
||||
|
||||
#define IXE_STATUS 0xff
|
||||
struct ab1771ixe_read {
|
||||
unsigned short pol_stat; /* status - polarity word */
|
||||
unsigned short out_of_range; /* under - over range channels */
|
||||
unsigned short alarms; /* inputs outside alarm limits */
|
||||
short data[8]; /* current values */
|
||||
unsigned short cjcw; /* cold junction cal word */
|
||||
};
|
||||
|
||||
/*Conversion value passed to abb_ai_driver*/
|
||||
#define IR_degF 0
|
||||
#define IR_degC 1
|
||||
#define IR_Ohms 2
|
||||
/*Register definitions*/
|
||||
#define IR_UNITS_DEGF 0x40
|
||||
#define IR_UNITS_OHMS 0x80
|
||||
#define IR_COPPER 0x100
|
||||
#define IR_SIGNED 0x400
|
||||
/* configuration data transfer to the IR card */
|
||||
struct ab1771ir_config {
|
||||
unsigned short conv_rate; /* conversion and scan rate data */
|
||||
unsigned short resistance; /* 10ohm resiatance @25 degC */
|
||||
unsigned short bias[6]; /* bias */
|
||||
unsigned short calibration[6]; /* */
|
||||
};
|
||||
|
||||
struct ab1771ir_read {
|
||||
unsigned short status; /* status and over/under range */
|
||||
unsigned short pol_over; /* polarity and overflow */
|
||||
short data[6]; /* current values */
|
||||
};
|
||||
1482
src/drv/old/drvAt5Vxi.c
Normal file
1482
src/drv/old/drvAt5Vxi.c
Normal file
File diff suppressed because it is too large
Load Diff
93
src/drv/old/drvAt5Vxi.h
Normal file
93
src/drv/old/drvAt5Vxi.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* base/src/drv $Id$ */
|
||||
|
||||
/*
|
||||
*
|
||||
* driver for at5 designed VXI modules
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 11-89
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
typedef long at5VxiStatus;
|
||||
|
||||
at5VxiStatus at5vxi_one_shot(
|
||||
int preset, /* TRUE or COMPLEMENT logic */
|
||||
double edge0_delay, /* sec */
|
||||
double edge1_delay, /* set */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
int int_source, /* (FALSE)External/(TRUE)Internal source
|
||||
*/
|
||||
void *event_rtn, /* subroutine to run on events */
|
||||
int event_rtn_param /* parameter to pass to above routine */
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_one_shot_read(
|
||||
int *preset, /* TRUE or COMPLEMENT logic */
|
||||
double *edge0_delay, /* sec */
|
||||
double *edge1_delay, /* sec */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
int *int_source /* (FALSE)External/(TRUE)Internal src */
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ai_driver(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *prval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ao_driver(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *prval,
|
||||
unsigned short *prbval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ao_read(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *pval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_bi_driver(
|
||||
unsigned card,
|
||||
unsigned long mask,
|
||||
unsigned long *prval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_bo_driver(
|
||||
unsigned card,
|
||||
unsigned long val,
|
||||
unsigned long mask
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_getioscanpvt(
|
||||
unsigned card,
|
||||
IOSCANPVT *scanpvt
|
||||
);
|
||||
|
||||
598
src/drv/old/drvBB232.c
Normal file
598
src/drv/old/drvBB232.c
Normal file
@@ -0,0 +1,598 @@
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* Author: John Winans
|
||||
* Date: 05-21-92
|
||||
* EPICS BITBUS -> R/S-232 driver
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 09-30-91 jrw created
|
||||
*
|
||||
*/
|
||||
|
||||
#define DRVBB232_C
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
#if 0 /* COMMENTED OUT SOME INCLUDES */
|
||||
#include <iosLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <memLib.h>
|
||||
#include <semLib.h>
|
||||
#include <wdLib.h>
|
||||
#include <wdLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <vme.h>
|
||||
#endif /* COMMENTED OUT SOME INCLUDES */
|
||||
|
||||
|
||||
#include <task_params.h>
|
||||
#include <module_types.h>
|
||||
#include <drvSup.h>
|
||||
#include <devSup.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbCommon.h>
|
||||
#include <dbAccess.h>
|
||||
#include <link.h>
|
||||
#include <callback.h>
|
||||
#include <fast_lock.h>
|
||||
|
||||
#include <drvMsg.h>
|
||||
#include <drvBitBusInterface.h>
|
||||
#include <drvRs232.h>
|
||||
#include <drvBB232.h>
|
||||
|
||||
int drvBB232Debug = 0;
|
||||
int softBB232 = 0;
|
||||
|
||||
extern struct drvBitBusEt drvBitBus;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
******************************************************************************/
|
||||
#define BB232LINK_PRI 50
|
||||
#define BB232LINK_OPT VX_FP_TASK|VX_STDIO
|
||||
#define BB232LINK_STACK 5000
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
report()
|
||||
{
|
||||
printf("Report for BITBUS -> RS-232 driver\n");
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
init(pparms)
|
||||
msgDrvIniParm *pparms;
|
||||
{
|
||||
if (drvBB232Debug)
|
||||
printf("Init for BITBUS -> RS-232 driver\n");
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is called to allocate any structures needed to hold
|
||||
* device-specific data that is added to the msgXact structure.
|
||||
*
|
||||
* It is also responsible for filling in the msgXact.phwpvt pointer.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
genXact(p)
|
||||
msgDrvGenXParm *p;
|
||||
{
|
||||
long stat = -1;
|
||||
char message[100];
|
||||
drvBB232Link *pdrvBB232Link;
|
||||
struct dpvtBitBusHead *pdpvtBitBusHead;
|
||||
|
||||
if (p->plink->type != BITBUS_IO)
|
||||
{
|
||||
p->pmsgXact->prec->pact = TRUE;
|
||||
sprintf("%s: invalid device type in devSup.ascii (%d)\n", p->pmsgXact->prec->name, p->plink->type);
|
||||
errMessage(S_db_badField, message);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
if (drvBB232Debug)
|
||||
printf("BB232 genXact entered for link %d, bug %d, port %d, parm %s\n", p->plink->value.bitbusio.link, p->plink->value.bitbusio.node, p->plink->value.bitbusio.port, p->plink->value.bitbusio.parm);
|
||||
|
||||
p->pmsgXact->phwpvt = p->pmsgXact->pparmBlock->pmsgHwpvt;
|
||||
|
||||
/* try to find the hwpvt structure for the required link, bug, and port */
|
||||
while ((p->pmsgXact->phwpvt != NULL) && (stat == -1))
|
||||
{
|
||||
pdrvBB232Link = (drvBB232Link *)(p->pmsgXact->phwpvt->pmsgLink->p);
|
||||
|
||||
if ((pdrvBB232Link->link == p->plink->value.bitbusio.link)
|
||||
&& (pdrvBB232Link->node == p->plink->value.bitbusio.node)
|
||||
&& (pdrvBB232Link->port == p->plink->value.bitbusio.port))
|
||||
{
|
||||
if (pdrvBB232Link->pparmBlock != p->pmsgXact->pparmBlock)
|
||||
{
|
||||
sprintf(message, "%s: Two different devices on same BB232 port\n", p->pmsgXact->prec->name);
|
||||
errMessage(S_db_badField, message);
|
||||
return(ERROR);
|
||||
}
|
||||
else
|
||||
stat = 0; /* Found the correct hwpvt structure */
|
||||
}
|
||||
else
|
||||
p->pmsgXact->phwpvt = p->pmsgXact->phwpvt->next;
|
||||
}
|
||||
if (stat != 0)
|
||||
{ /* Could not find a msgHwpvt for the right link, create a new one */
|
||||
if ((p->pmsgXact->phwpvt = drvMsg_genHwpvt(p->pmsgXact->pparmBlock, p->plink)) == NULL)
|
||||
return(ERROR);
|
||||
}
|
||||
/* Set again in case hwpvt was just allocated (and to make compiler happy) */
|
||||
pdrvBB232Link = (drvBB232Link *)(p->pmsgXact->phwpvt->pmsgLink->p);
|
||||
|
||||
p->pmsgXact->callback.callback = NULL;
|
||||
p->pmsgXact->psyncSem = NULL;
|
||||
|
||||
/* Create the skeleton bitbus driver message */
|
||||
pdpvtBitBusHead = (struct dpvtBitBusHead *) malloc(sizeof(struct dpvtBitBusHead));
|
||||
(struct dpvtBitBusHead *)(p->pmsgXact->p) = pdpvtBitBusHead;
|
||||
|
||||
pdpvtBitBusHead->finishProc = NULL;
|
||||
pdpvtBitBusHead->psyncSem = malloc(sizeof(SEM_ID));
|
||||
*(pdpvtBitBusHead->psyncSem) = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
|
||||
pdpvtBitBusHead->link = pdrvBB232Link->link;
|
||||
|
||||
pdpvtBitBusHead->txMsg.route = BB_STANDARD_TX_ROUTE;
|
||||
pdpvtBitBusHead->txMsg.node = pdrvBB232Link->node;
|
||||
pdpvtBitBusHead->txMsg.tasks = BB_232_TASK;
|
||||
pdpvtBitBusHead->txMsg.cmd = 0xff;
|
||||
|
||||
pdpvtBitBusHead->rxMsg.data = (unsigned char *) malloc(BB_MAX_DAT_LEN);
|
||||
|
||||
/* in case I read before write */
|
||||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||||
pdpvtBitBusHead->rxMsg.length = BB_MSG_HEADER_SIZE;
|
||||
pdpvtBitBusHead->status = BB_OK;
|
||||
|
||||
pdpvtBitBusHead->rxMaxLen = 0;
|
||||
pdpvtBitBusHead->ageLimit = 0;
|
||||
|
||||
if (sscanf(p->plink->value.bitbusio.parm,"%d", &(p->pmsgXact->parm)) != 1)
|
||||
{
|
||||
p->pmsgXact->prec->pact = TRUE;
|
||||
sprintf("%s: invalid parameter string >%s<\n", p->pmsgXact->prec->name, p->plink->value.bitbusio.parm);
|
||||
errMessage(S_db_badField, message);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is called to allocate any structures needed to hold
|
||||
* device-specific data that is added to the msgHwpvt structure.
|
||||
*
|
||||
* It is also responsible for filling in the msgHwpvt.pmsgLink pointer.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
genHwpvt(p)
|
||||
msgDrvGenHParm *p;
|
||||
{
|
||||
int stat = ERROR;
|
||||
|
||||
if (drvBB232Debug)
|
||||
printf("BB232 genHwpvt entered\n");
|
||||
|
||||
p->pmsgHwpvt->pmsgLink = drvBB232Block.pmsgLink;
|
||||
while ((p->pmsgHwpvt->pmsgLink != NULL) && (stat == ERROR))
|
||||
{
|
||||
if ((((drvBB232Link *)(p->pmsgHwpvt->pmsgLink->p))->link == p->plink->value.bitbusio.link)
|
||||
&& (((drvBB232Link *)(p->pmsgHwpvt->pmsgLink->p))->node == p->plink->value.bitbusio.node)
|
||||
&& (((drvBB232Link *)(p->pmsgHwpvt->pmsgLink->p))->port == p->plink->value.bitbusio.port))
|
||||
stat = OK;
|
||||
else
|
||||
p->pmsgHwpvt->pmsgLink = p->pmsgHwpvt->pmsgLink->next;
|
||||
}
|
||||
if (stat != OK)
|
||||
{
|
||||
if ((p->pmsgHwpvt->pmsgLink = drvMsg_genLink(p->pparmBlock, p->plink)) == NULL)
|
||||
return(ERROR);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is called to allocate any structures needed to hold
|
||||
* device-specific data that is added to the msgLink structure.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
genLink(p)
|
||||
msgDrvGenLParm *p;
|
||||
{
|
||||
char name[20];
|
||||
char message[100];
|
||||
drvBB232Link *pdrvBB232Link;
|
||||
|
||||
if (drvBB232Debug)
|
||||
printf("BB232 genLink, link = %d, node = %d\n", p->plink->value.bitbusio.link, p->plink->value.bitbusio.node, p->plink->value.bitbusio.port);
|
||||
|
||||
switch (p->op) {
|
||||
case MSG_GENLINK_CREATE:
|
||||
|
||||
/* BUG -- verify that the link and node numbers are within range! */
|
||||
|
||||
if (p->plink->value.bitbusio.port & (~DD_232_PORT))
|
||||
{
|
||||
sprintf(message, "drvBB232: port number %d out of range\n", p->plink->value.bitbusio.port);
|
||||
errMessage(S_db_badField, message);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
if ((p->pmsgLink->p = malloc(sizeof(drvBB232Link))) == NULL)
|
||||
return(ERROR);
|
||||
|
||||
pdrvBB232Link = (drvBB232Link *)(p->pmsgLink->p);
|
||||
|
||||
pdrvBB232Link->link = p->plink->value.bitbusio.link;
|
||||
pdrvBB232Link->node = p->plink->value.bitbusio.node;
|
||||
pdrvBB232Link->port = p->plink->value.bitbusio.port;
|
||||
pdrvBB232Link->pparmBlock = p->pparmBlock;
|
||||
|
||||
|
||||
return(OK);
|
||||
|
||||
case MSG_GENLINK_ABORT:
|
||||
|
||||
if (drvBB232Debug)
|
||||
printf("BB232 genLink: called with abort status\n");
|
||||
|
||||
pdrvBB232Link = (drvBB232Link *)(p->pmsgLink->p);
|
||||
/* BUG - free(p->pmsgLink->p); Don't forget to take it out of the list */
|
||||
return(OK);
|
||||
}
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is called to allow the device to indicate that a device-related
|
||||
* event has occurred. If an event had occurred, it would have to place the
|
||||
* address of a valid transaction structure in pxact. This xact structure
|
||||
* will then be processed by the message link task as indicated by the
|
||||
* return code of this function.
|
||||
*
|
||||
* MSG_EVENT_NONE = no event has occurred, pxact not filled in.
|
||||
* MSG_EVENT_WRITE = event occurred, process the writeOp assoc'd w/pxact.
|
||||
* MSG_EVENT_READ = event occurred, process the readOp assoc'd w/pxact.
|
||||
*
|
||||
* Note that MSG_EVENT_READ only makes sense when returned with a transaction
|
||||
* that has deferred readback specified for its readOp function. Because if
|
||||
* it is NOT a deferred readback, it will be done immediately after the writeOp.
|
||||
* Even if that writeOp was due to a MSG_EVENT_WRITE from this function.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
checkEvent(p)
|
||||
msgChkEParm *p;
|
||||
{
|
||||
return(MSG_EVENT_NONE);
|
||||
}
|
||||
/******************************************************************************
|
||||
*
|
||||
* This IOCTL function is used to handle non-I/O related operations required
|
||||
* to operate the RS-232 interface.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
command(p)
|
||||
ioctlCommand *p;
|
||||
{
|
||||
msgXact *pxact;
|
||||
struct dpvtBitBusHead *pdpvtBitBusHead;
|
||||
drvBB232Link *pdrvBB232Link;
|
||||
|
||||
switch (p->cmd) {
|
||||
case IOCTL232_BREAK: /* send a BREAK signal to the serial port. */
|
||||
/* Build a break message to send */
|
||||
pxact = (msgXact *) (p->pparm);
|
||||
pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||||
pdrvBB232Link = (drvBB232Link *)(pxact->phwpvt->pmsgLink->p);
|
||||
pdpvtBitBusHead->status = BB_OK;
|
||||
pdpvtBitBusHead->rxMaxLen = 0;
|
||||
pdpvtBitBusHead->txMsg.length = BB_MSG_HEADER_SIZE;
|
||||
pdpvtBitBusHead->txMsg.cmd = BB_232_BREAK + pdrvBB232Link->port;
|
||||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||||
|
||||
if (drvBB232Debug > 7)
|
||||
{
|
||||
printf("drvBB232.control (tx L%d N%d P%d)\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
}
|
||||
|
||||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW);
|
||||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER);
|
||||
|
||||
if ((pdpvtBitBusHead->status == BB_OK) && !(pdpvtBitBusHead->rxMsg.cmd & 1))
|
||||
return(OK);
|
||||
else
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
if (drvBB232Debug)
|
||||
printf("drvBB232.control: bad command 0x%02.2X\n", p->cmd);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is used to write a string of characters out to an RS-232
|
||||
* device.
|
||||
*
|
||||
* Note that the BUGs reply to the write messages with the first 13 bytes
|
||||
* of the machine's response string (if there is one.) This response string
|
||||
* will be left in the pdpvtBitBusHead->rxMsg buffer when the drvRead()
|
||||
* function is called later.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
drvWrite(pxact, pwrParm)
|
||||
msgXact *pxact;
|
||||
msgStrParm *pwrParm;
|
||||
{
|
||||
int len;
|
||||
drvBB232Link *pdrvBB232Link = (drvBB232Link *)(pxact->phwpvt->pmsgLink->p);
|
||||
struct dpvtBitBusHead *pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||||
unsigned char loopLen;
|
||||
|
||||
/* build a bitbus message and call the bitbus driver */
|
||||
|
||||
if (pwrParm->len == -1)
|
||||
len = strlen(pwrParm->buf);
|
||||
else
|
||||
len = pwrParm->len;
|
||||
|
||||
pdpvtBitBusHead->txMsg.data = (unsigned char *) pwrParm->buf;
|
||||
pdpvtBitBusHead->status = BB_OK;
|
||||
pdpvtBitBusHead->rxMaxLen = BB_MAX_MSG_LENGTH;
|
||||
|
||||
pdpvtBitBusHead->txMsg.cmd = BB_232_CMD + pdrvBB232Link->port;
|
||||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||||
|
||||
while (len && (pdpvtBitBusHead->status == BB_OK) &&
|
||||
!(pdpvtBitBusHead->rxMsg.cmd & 1))
|
||||
{
|
||||
if (len > BB_MAX_DAT_LEN)
|
||||
loopLen = BB_MAX_DAT_LEN;
|
||||
else
|
||||
loopLen = len;
|
||||
|
||||
pdpvtBitBusHead->txMsg.length = loopLen + BB_MSG_HEADER_SIZE;
|
||||
if (softBB232)
|
||||
{
|
||||
printf("drvBB232.drvWrite(tx L%d N%d P%d):\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
}
|
||||
else
|
||||
{
|
||||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW); /* do it */
|
||||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER); /* wait for completion */
|
||||
if (drvBB232Debug > 10)
|
||||
{
|
||||
printf("drvBB232.drvWrite (tx L%d N%d P%d)\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
}
|
||||
}
|
||||
|
||||
pdpvtBitBusHead->txMsg.data += loopLen;
|
||||
len -= loopLen;
|
||||
}
|
||||
|
||||
if ((pdpvtBitBusHead->status != BB_OK) || (pdpvtBitBusHead->rxMsg.cmd & 1))
|
||||
{
|
||||
if (drvBB232Debug)
|
||||
printf("BB232 write error on link %d, node %d, port %d, driver %02.2X, message %02.2X\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port, pdpvtBitBusHead->status, pdpvtBitBusHead->rxMsg.cmd);
|
||||
|
||||
pxact->status = XACT_IOERR;
|
||||
}
|
||||
|
||||
return(pxact->status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is used to read a string of characters from an RS-232 device.
|
||||
*
|
||||
* It is assumed that pdpvtBitBusHead->rxMsg has already got up to 13
|
||||
* bytes of the response data already filled in (left there by the prior
|
||||
* call to drvWrite().) If a call to this function is made when there is
|
||||
* garbage in the initial pdpvtBitBusHead->rxMsg buffer, set the length field
|
||||
* to 0 and the status field to BB_OK.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
drvRead(pxact, prdParm)
|
||||
msgXact *pxact;
|
||||
msgStrParm *prdParm;
|
||||
{
|
||||
drvBB232Link *pdrvBB232Link = (drvBB232Link *)(pxact->phwpvt->pmsgLink->p);
|
||||
struct dpvtBitBusHead *pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||||
int len = prdParm->len;
|
||||
int loopLen = 0;
|
||||
unsigned char *tmp = pdpvtBitBusHead->rxMsg.data;
|
||||
|
||||
/* check if data already loaded into pdpvtBitBusHead->rxMsg */
|
||||
if ((pdpvtBitBusHead->rxMsg.length > BB_MSG_HEADER_SIZE) && (pdpvtBitBusHead->status == BB_OK))
|
||||
{
|
||||
loopLen = pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||||
|
||||
if (prdParm->len < loopLen)
|
||||
loopLen = prdParm->len;
|
||||
|
||||
if (drvBB232Debug > 9)
|
||||
{
|
||||
printf("drvBB232.drvRead (rx L%d N%d P%d)\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||||
}
|
||||
bcopy(pdpvtBitBusHead->rxMsg.data, prdParm->buf, loopLen);
|
||||
len -= loopLen;
|
||||
}
|
||||
|
||||
pdpvtBitBusHead->txMsg.length = BB_MSG_HEADER_SIZE;
|
||||
pdpvtBitBusHead->txMsg.cmd = BB_232_CMD + pdrvBB232Link->port;
|
||||
|
||||
pdpvtBitBusHead->rxMsg.data = (unsigned char *) (&(prdParm->buf[loopLen]));
|
||||
|
||||
if (!(pdpvtBitBusHead->rxMsg.cmd & BB_232_EOI))
|
||||
{ /* If we did not hit EOI yet, keep reading */
|
||||
|
||||
while (len && (pdpvtBitBusHead->status == BB_OK))
|
||||
{
|
||||
if (len > BB_MAX_DAT_LEN)
|
||||
loopLen = BB_MAX_DAT_LEN;
|
||||
else
|
||||
loopLen = len;
|
||||
|
||||
pdpvtBitBusHead->rxMaxLen = loopLen + BB_MSG_HEADER_SIZE;
|
||||
if (softBB232)
|
||||
{
|
||||
printf("drvBB232.drvRead(tx L%d N%d P%d)\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
pdpvtBitBusHead->status = BB_232_EOI;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (drvBB232Debug > 10)
|
||||
{
|
||||
printf("drvBB232.drvRead(tx L%d N%d P%d)\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
}
|
||||
|
||||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW); /* do it */
|
||||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER); /* wait for completion */
|
||||
|
||||
if (drvBB232Debug > 9)
|
||||
{
|
||||
printf("drvBB232.drvRead (rx L%d N%d P%d)\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||||
}
|
||||
}
|
||||
|
||||
if (pdpvtBitBusHead->rxMsg.cmd & (~BB_232_EOI))
|
||||
{ /* Something is wrong... */
|
||||
if (drvBB232Debug > 6)
|
||||
{
|
||||
printf("drvBB232.drvRead (rx L%d N%d P%d) Error response from BUG\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||||
}
|
||||
pxact->status = XACT_IOERR;
|
||||
break; /* note that we will fall thru to the null-term code */
|
||||
}
|
||||
if (pdpvtBitBusHead->rxMsg.cmd & BB_232_EOI)
|
||||
{
|
||||
pdpvtBitBusHead->rxMsg.data += pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||||
len -= pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
pdpvtBitBusHead->rxMsg.data += loopLen;
|
||||
len -= loopLen;
|
||||
}
|
||||
}
|
||||
/* Null-terminate the input string (if there is room) */
|
||||
if (len)
|
||||
*(pdpvtBitBusHead->rxMsg.data) = '\0';
|
||||
else
|
||||
pxact->status = XACT_LENGTH;
|
||||
|
||||
/* Note that the following error check, takes priority over a length error */
|
||||
if (pdpvtBitBusHead->status != BB_OK)
|
||||
{
|
||||
if (drvBB232Debug)
|
||||
printf("BB232 read error on link %d, node %d, port %d\n", pdrvBB232Link->link, pdrvBB232Link->node, pdrvBB232Link->port);
|
||||
pxact->status = XACT_IOERR;
|
||||
}
|
||||
|
||||
/* BUG -- this can print unterminated strings !! */
|
||||
if (drvBB232Debug > 7)
|
||||
printf("drvRead: got >%s<\n", prdParm->buf);
|
||||
|
||||
pdpvtBitBusHead->rxMsg.length = BB_MSG_HEADER_SIZE; /* in case keep reading */
|
||||
return(pxact->status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This handles any IOCTL calls made to BB-232 devices.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
drvIoctl(cmd, pparm)
|
||||
int cmd;
|
||||
void *pparm;
|
||||
{
|
||||
switch (cmd) {
|
||||
case MSGIOCTL_REPORT:
|
||||
return(report());
|
||||
case MSGIOCTL_INIT:
|
||||
return(init(pparm));
|
||||
case MSGIOCTL_INITREC:
|
||||
if (drvBB232Debug)
|
||||
printf("drvBB232Block.drvIoctl got a MSGIOCTL_INITREC request!\n");
|
||||
return(ERROR);
|
||||
case MSGIOCTL_GENXACT:
|
||||
return(genXact(pparm));
|
||||
case MSGIOCTL_GENHWPVT:
|
||||
return(genHwpvt(pparm));
|
||||
case MSGIOCTL_GENLINK:
|
||||
return(genLink(pparm));
|
||||
case MSGIOCTL_CHECKEVENT:
|
||||
return(checkEvent(pparm));
|
||||
case MSGIOCTL_COMMAND:
|
||||
return(command(pparm));
|
||||
}
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
|
||||
msgDrvBlock drvBB232Block = {
|
||||
"BB232", /* taskName */
|
||||
BB232LINK_PRI, /* taskPri */
|
||||
BB232LINK_OPT, /* taskOpt */
|
||||
BB232LINK_STACK, /* taskStack */
|
||||
NULL, /* pmsgLink (linked list header) */
|
||||
drvWrite, /* drvWrite */
|
||||
drvRead, /* drvRead */
|
||||
drvIoctl /* drvIoctl */
|
||||
};
|
||||
590
src/drv/old/drvBBMsg.c
Normal file
590
src/drv/old/drvBBMsg.c
Normal file
@@ -0,0 +1,590 @@
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* Author: John Winans
|
||||
* Date: 05-21-92
|
||||
* EPICS BITBUS driver for message based I/O
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 08-10-92 jrw created
|
||||
*
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
#include <iosLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <memLib.h>
|
||||
#include <semLib.h>
|
||||
#include <wdLib.h>
|
||||
#include <wdLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <vme.h>
|
||||
|
||||
#include <task_params.h>
|
||||
#include <module_types.h>
|
||||
#include <drvSup.h>
|
||||
#include <devSup.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbCommon.h>
|
||||
#include <dbAccess.h>
|
||||
#include <link.h>
|
||||
#include <callback.h>
|
||||
#include <fast_lock.h>
|
||||
|
||||
#include <drvMsg.h>
|
||||
#include <drvBitBusInterface.h>
|
||||
|
||||
int drvBBMsgDebug = 0;
|
||||
|
||||
extern struct drvBitBusEt drvBitBus;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
******************************************************************************/
|
||||
#define BBMSGLINK_PRI 50
|
||||
#define BBMSGLINK_OPT VX_FP_TASK|VX_STDIO
|
||||
#define BBMSGLINK_STACK 5000
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
report()
|
||||
{
|
||||
printf("Report for BITBUS message driver\n");
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
init(pparms)
|
||||
msgDrvIniParm *pparms;
|
||||
{
|
||||
if (drvBBMsgDebug)
|
||||
printf("Init for BITBUS message driver\n");
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is called to allocate any structures needed to hold
|
||||
* device-specific data that is added to the msgXact structure.
|
||||
*
|
||||
* It is also responsible for filling in the msgXact.phwpvt pointer.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
genXact(p)
|
||||
msgDrvGenXParm *p;
|
||||
{
|
||||
long stat = -1;
|
||||
char message[100];
|
||||
drvBBMsgLink *pdrvBBMsgLink;
|
||||
struct dpvtBitBusHead *pdpvtBitBusHead;
|
||||
|
||||
if (p->plink->type != BITBUS_IO)
|
||||
{
|
||||
p->pmsgXact->prec->pact = TRUE;
|
||||
sprintf("%s: invalid device type in devSup.ascii (%d)\n", p->pmsgXact->prec->name, p->plink->type);
|
||||
errMessage(S_db_badField, message);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
if (drvBBMsgDebug)
|
||||
printf("BBMsg genXact entered for link %d, bug %d, port %d, parm %s\n", p->plink->value.bitbusio.link, p->plink->value.bitbusio.node, p->plink->value.bitbusio.port, p->plink->value.bitbusio.parm);
|
||||
|
||||
p->pmsgXact->phwpvt = p->pmsgXact->pparmBlock->pmsgHwpvt;
|
||||
|
||||
/* try to find the hwpvt structure for the required link, bug, and port */
|
||||
while ((p->pmsgXact->phwpvt != NULL) && (stat == -1))
|
||||
{
|
||||
pdrvBBMsgLink = (drvBBMsgLink *)(p->pmsgXact->phwpvt->pmsgLink->p);
|
||||
|
||||
if ((pdrvBBMsgLink->link == p->plink->value.bitbusio.link)
|
||||
&& (pdrvBBMsgLink->node == p->plink->value.bitbusio.node)
|
||||
&& (pdrvBBMsgLink->port == p->plink->value.bitbusio.port))
|
||||
{
|
||||
if (pdrvBBMsgLink->pparmBlock != p->pmsgXact->pparmBlock)
|
||||
{
|
||||
sprintf(message, "%s: Two different devices on same BBMsg port\n", p->pmsgXact->prec->name);
|
||||
errMessage(S_db_badField, message);
|
||||
return(ERROR);
|
||||
}
|
||||
else
|
||||
stat = 0; /* Found the correct hwpvt structure */
|
||||
}
|
||||
else
|
||||
p->pmsgXact->phwpvt = p->pmsgXact->phwpvt->next;
|
||||
}
|
||||
if (stat != 0)
|
||||
{ /* Could not find a msgHwpvt for the right link, create a new one */
|
||||
if ((p->pmsgXact->phwpvt = drvMsg_genHwpvt(p->pmsgXact->pparmBlock, p->plink)) == NULL)
|
||||
return(ERROR);
|
||||
}
|
||||
/* Set again in case hwpvt was just allocated (and to make compiler happy) */
|
||||
pdrvBBMsgLink = (drvBBMsgLink *)(p->pmsgXact->phwpvt->pmsgLink->p);
|
||||
|
||||
p->pmsgXact->callback.callback = NULL;
|
||||
p->pmsgXact->psyncSem = NULL;
|
||||
|
||||
/* Create the skeleton bitbus driver message */
|
||||
pdpvtBitBusHead = (struct dpvtBitBusHead *) malloc(sizeof(struct dpvtBitBusHead));
|
||||
(struct dpvtBitBusHead *)(p->pmsgXact->p) = pdpvtBitBusHead;
|
||||
|
||||
pdpvtBitBusHead->finishProc = NULL;
|
||||
pdpvtBitBusHead->psyncSem = malloc(sizeof(SEM_ID));
|
||||
*(pdpvtBitBusHead->psyncSem) = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
|
||||
pdpvtBitBusHead->link = pdrvBBMsgLink->link;
|
||||
|
||||
pdpvtBitBusHead->txMsg.route = BB_STANDARD_TX_ROUTE;
|
||||
pdpvtBitBusHead->txMsg.node = pdrvBBMsgLink->node;
|
||||
pdpvtBitBusHead->txMsg.tasks = BB_MSG_TASK;
|
||||
pdpvtBitBusHead->txMsg.cmd = 0xff;
|
||||
|
||||
pdpvtBitBusHead->rxMsg.data = (unsigned char *) malloc(BB_MAX_DAT_LEN);
|
||||
|
||||
/* in case I read before write */
|
||||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||||
pdpvtBitBusHead->rxMsg.length = BB_MSG_HEADER_SIZE;
|
||||
pdpvtBitBusHead->status = BB_OK;
|
||||
|
||||
pdpvtBitBusHead->rxMaxLen = 0;
|
||||
pdpvtBitBusHead->ageLimit = 0;
|
||||
|
||||
if (sscanf(p->plink->value.bitbusio.parm,"%d", &(p->pmsgXact->parm)) != 1)
|
||||
{
|
||||
p->pmsgXact->prec->pact = TRUE;
|
||||
sprintf("%s: invalid parameter string >%s<\n", p->pmsgXact->prec->name, p->plink->value.bitbusio.parm);
|
||||
errMessage(S_db_badField, message);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is called to allocate any structures needed to hold
|
||||
* device-specific data that is added to the msgHwpvt structure.
|
||||
*
|
||||
* It is also responsible for filling in the msgHwpvt.pmsgLink pointer.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
genHwpvt(p)
|
||||
msgDrvGenHParm *p;
|
||||
{
|
||||
int stat = ERROR;
|
||||
|
||||
if (drvBBMsgDebug)
|
||||
printf("BBMSG genHwpvt entered\n");
|
||||
|
||||
p->pmsgHwpvt->pmsgLink = drvBBMSGBlock.pmsgLink;
|
||||
while ((p->pmsgHwpvt->pmsgLink != NULL) && (stat == ERROR))
|
||||
{
|
||||
if ((((drvBBMsgLink *)(p->pmsgHwpvt->pmsgLink->p))->link == p->plink->value.bitbusio.link)
|
||||
&& (((drvBBMsgLink *)(p->pmsgHwpvt->pmsgLink->p))->node == p->plink->value.bitbusio.node)
|
||||
&& (((drvBBMsgLink *)(p->pmsgHwpvt->pmsgLink->p))->port == p->plink->value.bitbusio.port))
|
||||
stat = OK;
|
||||
else
|
||||
p->pmsgHwpvt->pmsgLink = p->pmsgHwpvt->pmsgLink->next;
|
||||
}
|
||||
if (stat != OK)
|
||||
{
|
||||
if ((p->pmsgHwpvt->pmsgLink = drvMsg_genLink(p->pparmBlock, p->plink)) == NULL)
|
||||
return(ERROR);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is called to allocate any structures needed to hold
|
||||
* device-specific data that is added to the msgLink structure.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
genLink(p)
|
||||
msgDrvGenLParm *p;
|
||||
{
|
||||
char name[20];
|
||||
char message[100];
|
||||
drvBBMsgLink *pdrvBBMsgLink;
|
||||
|
||||
if (drvBBMsgDebug)
|
||||
printf("BBMsg genLink, link = %d, node = %d\n", p->plink->value.bitbusio.link, p->plink->value.bitbusio.node, p->plink->value.bitbusio.port);
|
||||
|
||||
switch (p->op) {
|
||||
case MSG_GENLINK_CREATE:
|
||||
|
||||
/* BUG -- verify that the link and node numbers are within range! */
|
||||
|
||||
if (p->plink->value.bitbusio.port & (~DD_MSG_PORT))
|
||||
{
|
||||
sprintf(message, "drvBBMsg: port number %d out of range\n", p->plink->value.bitbusio.port);
|
||||
errMessage(S_db_badField, message);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
if ((p->pmsgLink->p = malloc(sizeof(drvBBMsgLink))) == NULL)
|
||||
return(ERROR);
|
||||
|
||||
pdrvBBMsgLink = (drvBBMsgLink *)(p->pmsgLink->p);
|
||||
|
||||
pdrvBBMsgLink->link = p->plink->value.bitbusio.link;
|
||||
pdrvBBMsgLink->node = p->plink->value.bitbusio.node;
|
||||
pdrvBBMsgLink->port = p->plink->value.bitbusio.port;
|
||||
pdrvBBMsgLink->pparmBlock = p->pparmBlock;
|
||||
|
||||
|
||||
return(OK);
|
||||
|
||||
case MSG_GENLINK_ABORT:
|
||||
|
||||
if (drvBBMsgDebug)
|
||||
printf("BBMsg genLink: called with abort status\n");
|
||||
|
||||
pdrvBBMsgLink = (drvBBMsgLink *)(p->pmsgLink->p);
|
||||
/* BUG - free(p->pmsgLink->p); Don't forget to take it out of the list */
|
||||
return(OK);
|
||||
}
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is called to allow the device to indicate that a device-related
|
||||
* event has occurred. If an event had occurred, it would have to place the
|
||||
* address of a valid transaction structure in pxact. This xact structure
|
||||
* will then be processed by the message link task as indicated by the
|
||||
* return code of this function.
|
||||
*
|
||||
* MSG_EVENT_NONE = no event has occurred, pxact not filled in.
|
||||
* MSG_EVENT_WRITE = event occurred, process the writeOp assoc'd w/pxact.
|
||||
* MSG_EVENT_READ = event occurred, process the readOp assoc'd w/pxact.
|
||||
*
|
||||
* Note that MSG_EVENT_READ only makes sense when returned with a transaction
|
||||
* that has deferred readback specified for its readOp function. Because if
|
||||
* it is NOT a deferred readback, it will be done immediately after the writeOp.
|
||||
* Even if that writeOp was due to a MSG_EVENT_WRITE from this function.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
checkEvent(p)
|
||||
msgChkEParm *p;
|
||||
{
|
||||
return(MSG_EVENT_NONE);
|
||||
}
|
||||
/******************************************************************************
|
||||
*
|
||||
* This IOCTL function is used to handle non-I/O related operations required
|
||||
* to operate the RS-MSG interface.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
command(p)
|
||||
ioctlCommand *p;
|
||||
{
|
||||
msgXact *pxact;
|
||||
struct dpvtBitBusHead *pdpvtBitBusHead;
|
||||
drvBBMsgLink *pdrvBBMsgLink;
|
||||
|
||||
switch (p->cmd) {
|
||||
case IOCTLMSG_BREAK: /* send a BREAK signal to the serial port. */
|
||||
/* Build a break message to send */
|
||||
pxact = (msgXact *) (p->pparm);
|
||||
pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||||
pdrvBBMsgLink = (drvBBMsgLink *)(pxact->phwpvt->pmsgLink->p);
|
||||
pdpvtBitBusHead->status = BB_OK;
|
||||
pdpvtBitBusHead->rxMaxLen = 0;
|
||||
pdpvtBitBusHead->txMsg.length = BB_MSG_HEADER_SIZE;
|
||||
pdpvtBitBusHead->txMsg.cmd = BB_MSG_BREAK + pdrvBBMsgLink->port;
|
||||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||||
|
||||
if (drvBBMsgDebug > 7)
|
||||
{
|
||||
printf("drvBBMsg.control (tx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
}
|
||||
|
||||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW);
|
||||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER);
|
||||
|
||||
if ((pdpvtBitBusHead->status == BB_OK) && !(pdpvtBitBusHead->rxMsg.cmd & 1))
|
||||
return(OK);
|
||||
else
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
if (drvBBMsgDebug)
|
||||
printf("drvBBMsg.control: bad command 0x%02.2X\n", p->cmd);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is used to write a string of characters out to an BB_MSG
|
||||
* device.
|
||||
*
|
||||
* Note that the BUGs reply to the write messages with the first 13 bytes
|
||||
* of the machine's response string (if there is one.) This response string
|
||||
* will be left in the pdpvtBitBusHead->rxMsg buffer when the drvRead()
|
||||
* function is called later.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
drvWrite(pxact, pwrParm)
|
||||
msgXact *pxact;
|
||||
msgStrParm *pwrParm;
|
||||
{
|
||||
int len;
|
||||
drvBBMsgLink *pdrvBBMsgLink = (drvBBMsgLink *)(pxact->phwpvt->pmsgLink->p);
|
||||
struct dpvtBitBusHead *pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||||
unsigned char loopLen;
|
||||
|
||||
/* build a bitbus message and call the bitbus driver */
|
||||
|
||||
if (pwrParm->len == -1)
|
||||
len = strlen(pwrParm->buf);
|
||||
else
|
||||
len = pwrParm->len;
|
||||
|
||||
pdpvtBitBusHead->txMsg.data = (unsigned char *) pwrParm->buf;
|
||||
pdpvtBitBusHead->status = BB_OK;
|
||||
pdpvtBitBusHead->rxMaxLen = BB_MAX_MSG_LENGTH;
|
||||
|
||||
pdpvtBitBusHead->txMsg.cmd = BB_MSG_CMD + pdrvBBMsgLink->port;
|
||||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||||
|
||||
while (len && (pdpvtBitBusHead->status == BB_OK) &&
|
||||
!(pdpvtBitBusHead->rxMsg.cmd & 1))
|
||||
{
|
||||
if (len > BB_MAX_DAT_LEN)
|
||||
loopLen = BB_MAX_DAT_LEN;
|
||||
else
|
||||
loopLen = len;
|
||||
|
||||
pdpvtBitBusHead->txMsg.length = loopLen + BB_MSG_HEADER_SIZE;
|
||||
if (softBBMsg)
|
||||
{
|
||||
printf("drvBBMsg.drvWrite(tx L%d N%d P%d):\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
}
|
||||
else
|
||||
{
|
||||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW); /* do it */
|
||||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER); /* wait for completion */
|
||||
if (drvBBMsgDebug > 10)
|
||||
{
|
||||
printf("drvBBMsg.drvWrite (tx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
}
|
||||
}
|
||||
|
||||
pdpvtBitBusHead->txMsg.data += loopLen;
|
||||
len -= loopLen;
|
||||
}
|
||||
|
||||
if ((pdpvtBitBusHead->status != BB_OK) || (pdpvtBitBusHead->rxMsg.cmd & 1))
|
||||
{
|
||||
if (drvBBMsgDebug)
|
||||
printf("BBMsg write error on link %d, node %d, port %d, driver %02.2X, message %02.2X\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port, pdpvtBitBusHead->status, pdpvtBitBusHead->rxMsg.cmd);
|
||||
|
||||
pxact->status = XACT_IOERR;
|
||||
}
|
||||
|
||||
return(pxact->status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function is used to read a string of characters from an RS-Msg device.
|
||||
*
|
||||
* It is assumed that pdpvtBitBusHead->rxMsg has already got up to 13
|
||||
* bytes of the response data already filled in (left there by the prior
|
||||
* call to drvWrite().) If a call to this function is made when there is
|
||||
* garbage in the initial pdpvtBitBusHead->rxMsg buffer, set the length field
|
||||
* to 0 and the status field to BB_OK.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
drvRead(pxact, prdParm)
|
||||
msgXact *pxact;
|
||||
msgStrParm *prdParm;
|
||||
{
|
||||
drvBBMsgLink *pdrvBBMsgLink = (drvBBMsgLink *)(pxact->phwpvt->pmsgLink->p);
|
||||
struct dpvtBitBusHead *pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||||
int len = prdParm->len;
|
||||
int loopLen = 0;
|
||||
unsigned char *tmp = pdpvtBitBusHead->rxMsg.data;
|
||||
|
||||
/* check if data already loaded into pdpvtBitBusHead->rxMsg */
|
||||
if ((pdpvtBitBusHead->rxMsg.length > BB_MSG_HEADER_SIZE) && (pdpvtBitBusHead->status == BB_OK))
|
||||
{
|
||||
loopLen = pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||||
|
||||
if (prdParm->len < loopLen)
|
||||
loopLen = prdParm->len;
|
||||
|
||||
if (drvBBMsgDebug > 9)
|
||||
{
|
||||
printf("drvBBMsg.drvRead (rx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||||
}
|
||||
bcopy(pdpvtBitBusHead->rxMsg.data, prdParm->buf, loopLen);
|
||||
len -= loopLen;
|
||||
}
|
||||
|
||||
pdpvtBitBusHead->txMsg.length = BB_MSG_HEADER_SIZE;
|
||||
pdpvtBitBusHead->txMsg.cmd = BB_MSG_CMD + pdrvBBMsgLink->port;
|
||||
|
||||
pdpvtBitBusHead->rxMsg.data = (unsigned char *) (&(prdParm->buf[loopLen]));
|
||||
|
||||
if (!(pdpvtBitBusHead->rxMsg.cmd & BB_MSG_EOI))
|
||||
{ /* If we did not hit EOI yet, keep reading */
|
||||
|
||||
while (len && (pdpvtBitBusHead->status == BB_OK))
|
||||
{
|
||||
if (len > BB_MAX_DAT_LEN)
|
||||
loopLen = BB_MAX_DAT_LEN;
|
||||
else
|
||||
loopLen = len;
|
||||
|
||||
pdpvtBitBusHead->rxMaxLen = loopLen + BB_MSG_HEADER_SIZE;
|
||||
if (softBBMsg)
|
||||
{
|
||||
printf("drvBB232.drvRead(tx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
pdpvtBitBusHead->status = BB_232_EOI;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (drvBBMsgDebug > 10)
|
||||
{
|
||||
printf("drvBB232.drvRead(tx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||||
}
|
||||
|
||||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW); /* do it */
|
||||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER); /* wait for completion */
|
||||
|
||||
if (drvBBMsgDebug > 9)
|
||||
{
|
||||
printf("drvBB232.drvRead (rx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||||
}
|
||||
}
|
||||
|
||||
if (pdpvtBitBusHead->rxMsg.cmd & (~BB_232_EOI))
|
||||
{ /* Something is wrong... */
|
||||
if (drvBBMsgDebug > 6)
|
||||
{
|
||||
printf("drvBB232.drvRead (rx L%d N%d P%d) Error response from BUG\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||||
}
|
||||
pxact->status = XACT_IOERR;
|
||||
break; /* note that we will fall thru to the null-term code */
|
||||
}
|
||||
if (pdpvtBitBusHead->rxMsg.cmd & BB_232_EOI)
|
||||
{
|
||||
pdpvtBitBusHead->rxMsg.data += pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||||
len -= pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
pdpvtBitBusHead->rxMsg.data += loopLen;
|
||||
len -= loopLen;
|
||||
}
|
||||
}
|
||||
/* Null-terminate the input string (if there is room) */
|
||||
if (len)
|
||||
*(pdpvtBitBusHead->rxMsg.data) = '\0';
|
||||
else
|
||||
pxact->status = XACT_LENGTH;
|
||||
|
||||
/* Note that the following error check, takes priority over a length error */
|
||||
if (pdpvtBitBusHead->status != BB_OK)
|
||||
{
|
||||
if (drvBBMsgDebug)
|
||||
printf("BB232 read error on link %d, node %d, port %d\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||||
pxact->status = XACT_IOERR;
|
||||
}
|
||||
|
||||
/* BUG -- this can print unterminated strings !! */
|
||||
if (drvBBMsgDebug > 7)
|
||||
printf("drvRead: got >%s<\n", prdParm->buf);
|
||||
|
||||
pdpvtBitBusHead->rxMsg.length = BB_MSG_HEADER_SIZE; /* in case keep reading */
|
||||
return(pxact->status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This handles any IOCTL calls made to BB-MSG devices.
|
||||
*
|
||||
******************************************************************************/
|
||||
static long
|
||||
drvIoctl(cmd, pparm)
|
||||
int cmd;
|
||||
void *pparm;
|
||||
{
|
||||
switch (cmd) {
|
||||
case MSGIOCTL_REPORT:
|
||||
return(report());
|
||||
case MSGIOCTL_INIT:
|
||||
return(init(pparm));
|
||||
case MSGIOCTL_INITREC:
|
||||
if (drvBBMsgDebug)
|
||||
printf("drvBBMsgBlock.drvIoctl got a MSGIOCTL_INITREC request!\n");
|
||||
return(ERROR);
|
||||
case MSGIOCTL_GENXACT:
|
||||
return(genXact(pparm));
|
||||
case MSGIOCTL_GENHWPVT:
|
||||
return(genHwpvt(pparm));
|
||||
case MSGIOCTL_GENLINK:
|
||||
return(genLink(pparm));
|
||||
case MSGIOCTL_CHECKEVENT:
|
||||
return(checkEvent(pparm));
|
||||
case MSGIOCTL_COMMAND:
|
||||
return(command(pparm));
|
||||
}
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
|
||||
msgDrvBlock drvBBMsgBlock = {
|
||||
"BBMSG", /* taskName */
|
||||
BBMSGLINK_PRI, /* taskPri */
|
||||
BBMSGLINK_OPT, /* taskOpt */
|
||||
BBMSGLINK_STACK, /* taskStack */
|
||||
NULL, /* pmsgLink (linked list header) */
|
||||
drvWrite, /* drvWrite */
|
||||
drvRead, /* drvRead */
|
||||
drvIoctl /* drvIoctl */
|
||||
};
|
||||
202
src/drv/old/drvBb902.c
Normal file
202
src/drv/old/drvBb902.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* subroutines that are used to interface to the binary output cards
|
||||
*
|
||||
* Author: Bob Dalesio
|
||||
* Date: 5-26-88
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 10-31-91 bg broke bb902 code out of bo_driver.c
|
||||
* .02 02-20-92 bg Added level to io_report. Added ability
|
||||
* to read out raw values on card if level
|
||||
* > 0.
|
||||
* .03 08-10-92 joh made number of cards runtime configurable
|
||||
* .04 08-25-92 mrk made masks a macro
|
||||
* .05 09-14-93 mrk Let report just display one hex value
|
||||
*
|
||||
*/
|
||||
|
||||
static char SccsId[] = "@(#)drvBb902.c 1.6 9/14/92 ";
|
||||
|
||||
/*
|
||||
* Code Portions:
|
||||
*
|
||||
* bo_drv_init Finds and initializes all binary output cards present
|
||||
* bo_driver Interfaces to the binary output cards present
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <vme.h>
|
||||
#include <module_types.h>
|
||||
#include <drvSup.h>
|
||||
|
||||
static long report();
|
||||
static long init();
|
||||
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvBb902={
|
||||
2,
|
||||
report,
|
||||
init};
|
||||
|
||||
static long report(level)
|
||||
int level;
|
||||
{
|
||||
int i;
|
||||
|
||||
bb902_io_report(level);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long init()
|
||||
{
|
||||
int status;
|
||||
|
||||
bb902_driver_init();
|
||||
return(0);
|
||||
}
|
||||
|
||||
#define MAX_BB_BO_CARDS (bo_num_cards[BB902])
|
||||
|
||||
/* Burr-Brown 902 binary output memory structure */
|
||||
struct bo_bb902{
|
||||
short csr; /* control status register */
|
||||
unsigned short low_value; /* low order 16 bits value */
|
||||
unsigned short high_value; /* high order 16 bits value */
|
||||
char end_pad[0x100-6]; /* pad until next card */
|
||||
};
|
||||
|
||||
static char *bb902_shortaddr;
|
||||
|
||||
/* pointers to the binary output cards */
|
||||
struct bo_bb902 **pbo_bb902s; /* Burr-Brown 902s */
|
||||
|
||||
|
||||
/*
|
||||
* BO_DRIVER_INIT
|
||||
*
|
||||
* intialization for the binary output cards
|
||||
*/
|
||||
int bb902_driver_init(){
|
||||
int bomode;
|
||||
int status;
|
||||
short i;
|
||||
struct bo_bb902 *pbo_bb902;
|
||||
|
||||
pbo_bb902s = (struct bo_bb902 **)calloc(MAX_BB_BO_CARDS,
|
||||
sizeof(*pbo_bb902s));
|
||||
if(!pbo_bb902s){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* intialize the Burr-Brown 902 binary output cards */
|
||||
|
||||
/* base address of the burr-brown 902 binary output cards */
|
||||
|
||||
status = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,bo_addrs[BB902],&bb902_shortaddr);
|
||||
if (status != OK){
|
||||
printf("Addressing error in bb902 driver\n");
|
||||
return (ERROR);
|
||||
}
|
||||
pbo_bb902 = (struct bo_bb902 *)bb902_shortaddr;
|
||||
/* determine which cards are present */
|
||||
for (i = 0; i < bo_num_cards[BB902]; i++,pbo_bb902++){
|
||||
if (vxMemProbe(pbo_bb902,READ,sizeof(short),&bomode) == OK)
|
||||
pbo_bb902s[i] = pbo_bb902;
|
||||
else
|
||||
pbo_bb902s[i] = 0;
|
||||
}
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* BB902_DRIVER
|
||||
*
|
||||
* interface to the Burr-Brown binary outputs
|
||||
*/
|
||||
|
||||
int bb902_driver(card,val,mask)
|
||||
unsigned short card;
|
||||
unsigned long val;
|
||||
unsigned long mask;
|
||||
{
|
||||
unsigned int work;
|
||||
|
||||
/* verify card exists */
|
||||
if (!pbo_bb902s[card])
|
||||
return (-1);
|
||||
/* use structure to handle high and low short swap */
|
||||
/* get current output */
|
||||
work = (pbo_bb902s[card]->high_value << 16) /* high */
|
||||
+ pbo_bb902s[card]->low_value; /* low */
|
||||
/* alter specified bits */
|
||||
work = (work & ~mask) | (val & mask);
|
||||
|
||||
/* write new output */
|
||||
pbo_bb902s[card]->high_value = (unsigned short)(work >> 16);
|
||||
pbo_bb902s[card]->low_value = (unsigned short)work;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* bb902_read
|
||||
*
|
||||
* read the binary output
|
||||
*/
|
||||
int bb902_read(card,mask,pval)
|
||||
unsigned short card;
|
||||
unsigned int mask;
|
||||
unsigned int *pval;
|
||||
{
|
||||
unsigned int work;
|
||||
|
||||
/* verify card exists */
|
||||
if (!pbo_bb902s[card]) return (-1);
|
||||
/* readback */
|
||||
*pval = (pbo_bb902s[card]->high_value << 16) /* high */
|
||||
+ pbo_bb902s[card]->low_value; /* low */
|
||||
*pval &= mask;
|
||||
return(0);
|
||||
}
|
||||
|
||||
void bb902_io_report(level)
|
||||
short int level;
|
||||
{
|
||||
unsigned int value;
|
||||
int card;
|
||||
|
||||
for (card = 0; card < MAX_BB_BO_CARDS; card++){
|
||||
if (pbo_bb902s[card]){
|
||||
value = (pbo_bb902s[card]->high_value << 16)
|
||||
+ pbo_bb902s[card]->low_value;
|
||||
printf("BO: BB902: card %d value=0x%08.8x\n",card,value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
212
src/drv/old/drvBb910.c
Normal file
212
src/drv/old/drvBb910.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/* bb910_driver.c */
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* subroutines that are used to interface to the binary input cards
|
||||
*
|
||||
* Author: Bob Dalesio
|
||||
* Date: 6-13-88
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 02-09-89 lrd moved I/O addresses to module_types.h
|
||||
* .02 11-20-89 joh added call to at5vxi driver
|
||||
* .03 09-11-91 bg added bb910_io_report
|
||||
* .04 10-31-91 bg broke bb910 code out of bi_driver.c
|
||||
* .05 02-04-92 bg added the argument level to
|
||||
* bb910_io_report() and gave it the ability
|
||||
* to read raw values from card if level > 0
|
||||
* .06 08-10-92 joh made the number of cards runtime
|
||||
* .07 08-25-92 mrk made masks a macro
|
||||
*/
|
||||
|
||||
/*
|
||||
* Code Portions:
|
||||
*
|
||||
* bi_driver_init Finds and initializes all binary input cards present
|
||||
* bi_driver Interfaces to the binary input cards present
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <vme.h>
|
||||
#include <module_types.h>
|
||||
#include <drvSup.h>
|
||||
|
||||
static long report();
|
||||
static long init();
|
||||
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvBb910={
|
||||
2,
|
||||
report,
|
||||
init};
|
||||
|
||||
static long report(level)
|
||||
int level;
|
||||
{
|
||||
register int i;
|
||||
|
||||
bb910_io_report(level);
|
||||
return(0);
|
||||
}
|
||||
static long init()
|
||||
{
|
||||
int status;
|
||||
|
||||
bb910_driver_init();
|
||||
return(0);
|
||||
}
|
||||
|
||||
static char SccsId[] = "@(#)drvBb910.c 1.6\t6/3/93";
|
||||
|
||||
#define MAX_BB_BI_CARDS (bi_num_cards[BB910])
|
||||
|
||||
/* Burr-Brown 910 binary input memory structure */
|
||||
/* Note: the high and low order words are switched from the io card */
|
||||
struct bi_bb910{
|
||||
unsigned short csr; /* control status register */
|
||||
unsigned short low_value; /* low order 16 bits value */
|
||||
unsigned short high_value; /* high order 16 bits value */
|
||||
char end_pad[0x100-6]; /* pad until next card */
|
||||
};
|
||||
|
||||
/* pointers to the binary input cards */
|
||||
struct bi_bb910 **pbi_bb910s; /* Burr-Brown 910s */
|
||||
|
||||
/* test word for forcing bi_driver */
|
||||
int bi_test;
|
||||
|
||||
static char *bb910_shortaddr;
|
||||
|
||||
|
||||
/*
|
||||
* BI_DRIVER_INIT
|
||||
*
|
||||
* intialization for the binary input cards
|
||||
*/
|
||||
|
||||
bb910_driver_init(){
|
||||
int bimode;
|
||||
int status;
|
||||
register short i;
|
||||
struct bi_bb910 *pbi_bb910;
|
||||
|
||||
pbi_bb910s = (struct bi_bb910 **)
|
||||
calloc(MAX_BB_BI_CARDS, sizeof(*pbi_bb910s));
|
||||
if(!pbi_bb910s){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* intialize the Burr-Brown 910 binary input cards */
|
||||
/* base address of the burr-brown 910 binary input cards */
|
||||
|
||||
status=sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,bi_addrs[BB910],&bb910_shortaddr);
|
||||
if (status != OK){
|
||||
printf("Addressing error in bb910 driver\n");
|
||||
return ERROR;
|
||||
}
|
||||
pbi_bb910 = (struct bi_bb910 *)bb910_shortaddr;
|
||||
|
||||
/* determine which cards are present */
|
||||
for (i = 0; i < bi_num_cards[BB910]; i++,pbi_bb910++){
|
||||
if (vxMemProbe(pbi_bb910,READ,sizeof(short),&bimode) == OK){
|
||||
pbi_bb910s[i] = pbi_bb910;
|
||||
}
|
||||
else {
|
||||
pbi_bb910s[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bb910_driver(card,mask,prval)
|
||||
|
||||
register unsigned short card;
|
||||
unsigned int mask;
|
||||
register unsigned int *prval;
|
||||
{
|
||||
register unsigned int work;
|
||||
|
||||
if (!pbi_bb910s[card])
|
||||
return (-1);
|
||||
|
||||
/* read */
|
||||
|
||||
work = (pbi_bb910s[card]->high_value << 16) /* high */
|
||||
+ pbi_bb910s[card]->low_value; /* low */
|
||||
/* apply mask */
|
||||
*prval = work & mask;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define masks(K) ((1<<K))
|
||||
void bb910_io_report(level)
|
||||
short int level;
|
||||
{
|
||||
register short i,j,k,l,m,num_chans;
|
||||
unsigned int jval,kval,lval,mval;
|
||||
|
||||
for (i = 0; i < bi_num_cards[BB910]; i++){
|
||||
if (pbi_bb910s[i]){
|
||||
printf("BI: BB910: card %d\n",i);
|
||||
if (level > 0){
|
||||
num_chans = bi_num_channels[BB910];
|
||||
for(j=0,k=1,l=2,m=3;j < num_chans,k < num_chans, l < num_chans,m < num_chans;
|
||||
j+=IOR_MAX_COLS,k+= IOR_MAX_COLS,l+= IOR_MAX_COLS,m += IOR_MAX_COLS){
|
||||
if(j < num_chans){
|
||||
bb910_driver(i,masks(j),BB910,&jval);
|
||||
if (jval != 0)
|
||||
jval = 1;
|
||||
printf("Chan %d = %x\t ",j,jval);
|
||||
}
|
||||
if(k < num_chans){
|
||||
bb910_driver(i,masks(k),BB910,&kval);
|
||||
if (kval != 0)
|
||||
kval = 1;
|
||||
printf("Chan %d = %x\t ",k,kval);
|
||||
}
|
||||
if(l < num_chans){
|
||||
bb910_driver(i,masks(l),BB910,&lval);
|
||||
if (lval != 0)
|
||||
lval = 1;
|
||||
printf("Chan %d = %x \t",l,lval);
|
||||
}
|
||||
if(m < num_chans){
|
||||
bb910_driver(i,masks(m),BB910,&mval);
|
||||
if (mval != 0)
|
||||
mval = 1;
|
||||
printf("Chan %d = %x \n",m,mval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2624
src/drv/old/drvBitBus.c
Normal file
2624
src/drv/old/drvBitBus.c
Normal file
File diff suppressed because it is too large
Load Diff
306
src/drv/old/drvBitBus.h
Normal file
306
src/drv/old/drvBitBus.h
Normal file
@@ -0,0 +1,306 @@
|
||||
#ifndef EPICS_DRVBITBUS_H
|
||||
#define EPICS_DRVBITBUS_H
|
||||
|
||||
/* #define BB_SUPER_DEBUG */
|
||||
|
||||
/*
|
||||
* Author: John Winans
|
||||
* Date: 09-10-91
|
||||
* BitBus driver
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 09-30-91 jrw Written
|
||||
* .02 12-10-91 jrw moved some stuff over to drvBitBusInterface.h
|
||||
* .03 07-01-94 jrw Bigtime hacking... merged PEP and Xycom.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.9 1994/11/17 21:15:26 winans
|
||||
* Turned off the debugging system (it consumed an additional 30% of CPU)
|
||||
*
|
||||
* Revision 1.8 1994/10/04 18:42:44 winans
|
||||
* Added an extensive debugging facility.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* This history stuff below is used to save the recent history of operation.
|
||||
* This history includes dumps of messages that are queued, transmitted and
|
||||
* received. This information is saved along with the relative tick time.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef BB_SUPER_DEBUG
|
||||
#define BB_SUPER_DEBUG_HIST_SIZ 50 /* How many messages to save */
|
||||
|
||||
typedef struct XactHistStruct
|
||||
{
|
||||
struct dpvtBitBusHead Xact; /* BB message operated on */
|
||||
unsigned long Time; /* getTick() when operated on */
|
||||
int State; /* What was being done to the message */
|
||||
} XactHistStruct;
|
||||
|
||||
#define XACT_HIST_STATE_QUEUE 0 /* Some task queued a transaction */
|
||||
#define XACT_HIST_STATE_TX 1 /* Transmitter sent a transaction */
|
||||
#define XACT_HIST_STATE_RX 2 /* Receiver received a response */
|
||||
#define XACT_HIST_STATE_WD_TIMEOUT 3 /* Watchdog times out a transaction */
|
||||
#define XACT_HIST_STATE_RESET 4 /* No message... link was reset */
|
||||
#define XACT_HIST_STATE_RX_UNSOLICITED 5 /* RX'd message not solicited */
|
||||
#define XACT_HIST_STATE_RX_ABORT 6 /* RX task got a link about status */
|
||||
#define XACT_HIST_STATE_TX_ABORT 7 /* TX task got a link about status */
|
||||
#define XACT_HIST_STATE_RX_URCMD 8 /* RX task got unsolicited RCMD */
|
||||
#define XACT_HIST_STATE_TX_RESET 9 /* TX task got a link about status */
|
||||
#define XACT_HIST_STATE_TX_STUCK 10 /* TX fifo is stuck on the 8044 */
|
||||
|
||||
/* One of these is allocated for each bitbus link */
|
||||
typedef struct HistoryStruct
|
||||
{
|
||||
SEM_ID sem; /* Use when 'making' history */
|
||||
XactHistStruct Xact[BB_SUPER_DEBUG_HIST_SIZ];
|
||||
int Next; /* Next history slot to use */
|
||||
unsigned long Num; /* Total history messages */
|
||||
} HistoryStruct;
|
||||
|
||||
static int BBSetHistEvent(int link, struct dpvtBitBusHead *pXact, int State);
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* The BUSY/IDLE notion is used to count the number of outstanding
|
||||
* messages for a specific node. The idea is that up to BUSY messages
|
||||
* can be sent to a node before waiting before deciding not to send any more.
|
||||
* According to the BitBus specs, this value is 7. However, it also
|
||||
* states that responses can come back out of order. If this is even true
|
||||
* for messages sent to the SAME TASK ON THE SAME NODE, the received messages
|
||||
* CAN NOT be routed back to their initiators properly. Because the node#
|
||||
* and task# is all we have to identify what a response message is for,
|
||||
* I am limiting the per-node maximum to 1.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#define BB_BUSY 1 /* deviceStatus value if device is currently busy */
|
||||
#define BB_IDLE 0 /* deviceStatus value if device is currently idle */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This list structure is used in the bitbus driver to represent its queues.
|
||||
*
|
||||
******************************************************************************/
|
||||
struct bbList {
|
||||
struct dpvtBitBusHead *head; /* head of the linked list */
|
||||
struct dpvtBitBusHead *tail; /* tail of the linked list */
|
||||
int elements; /* holds number of elements on the list */
|
||||
SEM_ID sem; /* semaphore for the queue list */
|
||||
};
|
||||
/*****************************************************************************
|
||||
* Memory Map of XVME-402 BITBUS CARD
|
||||
*
|
||||
* This board is rather stupid in that it wastes a whole Kilo of space
|
||||
* for its 5 1-byte regs. So the dm* fields in the structure below are
|
||||
* for those filler locations.
|
||||
*
|
||||
*****************************************************************************/
|
||||
typedef struct XycomBBRegsStruct {
|
||||
unsigned char dm0;
|
||||
unsigned char stat_ctl;
|
||||
unsigned char dm2;
|
||||
unsigned char int_vec;
|
||||
unsigned char dm4;
|
||||
unsigned char data;
|
||||
unsigned char dm6;
|
||||
unsigned char cmnd;
|
||||
unsigned char dm8;
|
||||
unsigned char fifo_stat;
|
||||
unsigned char dmA[1014]; /* Board occupies 1024 bytes in memory*/
|
||||
} XycomBBRegsStruct;
|
||||
|
||||
#define XYCOM_BB_MAX_OUTSTAND_MSGS 4 /* per-link max pending messages */
|
||||
#define RESET_POLL_TIME 10 /* time to sleep when waiting on a link abort */
|
||||
|
||||
#define BB_SEND_CMD 0x0 /* command to initiate sending of msg */
|
||||
|
||||
#define XVME_ENABLE_INT 0x08 /* Allow xvme interupts */
|
||||
|
||||
#define XVME_TX_INT 0x20 /* int enable TX only */
|
||||
#define XVME_TX_PEND 0x10 /* transmit interrupt currently pending */
|
||||
|
||||
#define XVME_RX_INT 0x80 /* int exable RX only */
|
||||
#define XVME_RX_PEND 0x40 /* receive interrupt currently pending */
|
||||
|
||||
#define XVME_NO_INT 0 /* disable all interrupts */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Fifo status register format for Xycom board
|
||||
*
|
||||
* +----+----+----+----+----+----+----+----+
|
||||
* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Bits
|
||||
* +----+----+----+----+----+----+----+----+
|
||||
* "1" "1" RCMD RFNE "1" "1" "1" TFNF data
|
||||
*
|
||||
* RCMD = "1"= command received ( end of message )
|
||||
* "0"= No command
|
||||
*
|
||||
* RFNE = "1" = Receive Fifo Not Empty
|
||||
* "0" = Receive Fifo empty
|
||||
*
|
||||
* TFNF = "1" = Transmit Fifo Not Full
|
||||
* "0" = transmit fifo full
|
||||
*
|
||||
* NOTE:
|
||||
* A write to bit 7 of the Fifo status register can be used to reset the
|
||||
* xvme board.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define XVME_RCMD 0x20 /* Command has been received */
|
||||
#define XVME_RFNE 0x10 /* Receive Fifo is Not Empty */
|
||||
#define XVME_TFNF 0x01 /* Transmit FIFO is Not Full */
|
||||
#define XVME_FSVALID 0x31 /* these are the only valid status bits */
|
||||
#define XVME_FSIDLE 0x01 /* fifo_stat & FSVALID = 0x1 when it is idle */
|
||||
#define XVME_RESET 0x80 /* Write this and you reset the XVME card */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* The XycomBBLinkStruct structure holds all the xvme-card specific data
|
||||
* required for the operation of the link.
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef struct XycomBBLinkStruct {
|
||||
volatile XycomBBRegsStruct *bbRegs;/* pointer to board registers */
|
||||
SEM_ID rxInt; /* given when rx interrupts occur */
|
||||
} XycomBBLinkStruct;
|
||||
|
||||
/****************************************************************************
|
||||
* Memory Map of PEP Modular PB-BIT BITBUS CARD
|
||||
*
|
||||
* This board is rather stupid in that it wastes a bunch of bytes
|
||||
* for its regs. So the dm* fields in the structure below are
|
||||
* for those filler locations.
|
||||
*
|
||||
***************************************************************************/
|
||||
typedef struct PepBBRegsStruct {
|
||||
unsigned char dm0;
|
||||
unsigned char data;
|
||||
unsigned char dm2;
|
||||
unsigned char stat_ctl;
|
||||
unsigned char dm[29];
|
||||
unsigned char int_vec;
|
||||
} PepBBRegsStruct;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* status register format for PEP's PB-BIT board
|
||||
*
|
||||
* +----+----+----+----+----+----+----+----+
|
||||
* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Bits
|
||||
* +----+----+----+----+----+----+----+----+
|
||||
* X X X STF LBP TFF RFNE IRQP
|
||||
*
|
||||
* STF = "1"= self-test failed
|
||||
* "0"= passed
|
||||
*
|
||||
* LBP = "1"= last data byte was last of package
|
||||
* "0"= 1+ bytes left
|
||||
*
|
||||
* TFF = "1"= only one more byte may be written to TFIFO
|
||||
* "0"= 1+ more bytes may be written
|
||||
*
|
||||
* RFNE = "1"= Receive Fifo Not Empty
|
||||
* "0"= Receive Fifo empty
|
||||
*
|
||||
* IRQP = "1"= no irq pending
|
||||
* "0"= irq pending
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define PEP_BB_RCMD 0x08 /* Command has been received */
|
||||
#define PEP_BB_RFNE 0x02 /* Receive Fifo is Not Empty */
|
||||
#define PEP_BB_TFNF 0x04 /* Transmit FIFO is Not Full */
|
||||
#define PEP_BB_FSVALID 0x1f /* these are the only valid status bits */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* The PepBBLinkStruct structure holds all the card specific data required for
|
||||
* the operation of the link.
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef struct PepBBLinkStruct {
|
||||
|
||||
volatile PepBBRegsStruct *bbRegs; /* pointer to board registers */
|
||||
SEM_ID rxInt; /* given when rx interrupts occur */
|
||||
|
||||
} PepBBLinkStruct;
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Holds the user-configured board addresses etc. These MUST be set before
|
||||
* the driver is initialized. And may not be changed after the init phase.
|
||||
*
|
||||
* NOTE:
|
||||
* The setting of these items is intended to be done via records in the future.
|
||||
*
|
||||
* The busyList.sem is used to lock the busyList as well as the deviceStatus
|
||||
* table.
|
||||
*
|
||||
*****************************************************************************/
|
||||
typedef struct BitbusLinkStruct
|
||||
{
|
||||
unsigned long LinkType; /* Type of link (XYCOM, PEP,...) */
|
||||
unsigned long BaseAddr; /* Base address within A16 */
|
||||
unsigned long IrqVector; /* Irq vector base */
|
||||
unsigned long IrqLevel; /* Irq level */
|
||||
|
||||
WDOG_ID watchDogId; /* watchdog for timeouts */
|
||||
SEM_ID watchDogSem; /* set by the watch dog int handler */
|
||||
|
||||
unsigned char abortFlag; /* set to 1 if link is being reset by the dog */
|
||||
unsigned char txAbortAck; /* set to 1 by txTask to ack abort Sequence */
|
||||
unsigned char rxAbortAck; /* set to 1 by rxTask to ack abort Sequence */
|
||||
|
||||
int nukeEm; /* manual link restart flag */
|
||||
SEM_ID linkEventSem; /* given when this link requires service */
|
||||
struct bbList queue[BB_NUM_PRIO]; /* prioritized request queues */
|
||||
struct bbList busyList; /* messages waiting on a response */
|
||||
unsigned char deviceStatus[BB_APERLINK];/* mark a device as idle or busy */
|
||||
unsigned long syntheticDelay[BB_APERLINK]; /* holds the wakeup time for 91-delays */
|
||||
int DelayCount; /* holds total number of syntheticDelays in progress */
|
||||
|
||||
union
|
||||
{
|
||||
PepBBLinkStruct PepLink;
|
||||
XycomBBLinkStruct XycomLink;
|
||||
} l;
|
||||
|
||||
#ifdef BB_SUPER_DEBUG
|
||||
HistoryStruct History;
|
||||
#endif
|
||||
|
||||
} BitbusLinkStruct;
|
||||
|
||||
#define BB_CONF_HOSED 0 /* Link is not present */
|
||||
#define BB_CONF_TYPE_XYCOM 1 /* Link is a Xycom board */
|
||||
#define BB_CONF_TYPE_PEP 2 /* Link is a PEP board */
|
||||
|
||||
#endif
|
||||
807
src/drv/old/drvCaenV265.c
Normal file
807
src/drv/old/drvCaenV265.c
Normal file
@@ -0,0 +1,807 @@
|
||||
/* share/src/drv @(#)drvCaenV265.c 1.1 9/2/94 */
|
||||
/* drvCaenV265.c - Driver/Device Support Routines for CAEN V265
|
||||
*
|
||||
* Author: Jeff Hill (johill@lanl.gov)
|
||||
* Date: 8-11-94
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* MIT Bates Lab
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* ANSI C Includes
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <types.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* vxWorks includes
|
||||
*/
|
||||
#include <vme.h>
|
||||
#include <iv.h>
|
||||
#include <sysLib.h>
|
||||
#include <intLib.h>
|
||||
#include <logLib.h>
|
||||
#include <vxLib.h>
|
||||
#include <rebootLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <wdLib.h>
|
||||
|
||||
/*
|
||||
* EPICS include
|
||||
*/
|
||||
#include <dbDefs.h>
|
||||
#include <dbScan.h>
|
||||
#include <drvSup.h>
|
||||
#include <devSup.h>
|
||||
#include <recSup.h>
|
||||
#include <devLib.h>
|
||||
#include <aiRecord.h>
|
||||
#include <errMdef.h>
|
||||
|
||||
|
||||
/*
|
||||
* base address, base interrupt vector,
|
||||
* number of cards, & interrupt level
|
||||
*/
|
||||
#define CAIN_V265_A24_BASE (0x000000)
|
||||
#define CAIN_V265_INTVEC_BASE (0xA0)
|
||||
#define CAIN_V265_MAX_CARD_COUNT (8)
|
||||
#define CAIN_V265_INT_LEVEL (6)
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* all device registers declared
|
||||
* ANSI C volatile so we dont need to
|
||||
* use the -fvolatile flag (and dont
|
||||
* limit the optimizer)
|
||||
*/
|
||||
typedef volatile int16_t devReg;
|
||||
|
||||
struct caenV265 {
|
||||
devReg csr;
|
||||
devReg clear;
|
||||
devReg DAC;
|
||||
devReg gate;
|
||||
const devReg data;
|
||||
const devReg pad1[(0xf8-0x8)/2];
|
||||
const devReg fixed;
|
||||
const devReg identifier;
|
||||
const devReg version;
|
||||
};
|
||||
#define CAENV265ID 0x0812
|
||||
|
||||
/*
|
||||
* Insert or extract a bit field using the standard
|
||||
* masks and shifts defined below
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
#define INSERT(FIELD,VALUE)\
|
||||
(((VALUE)&(FD_ ## FIELD ## _M))<<(FD_ ## FIELD ## _S))
|
||||
#define EXTRACT(FIELD,VALUE)\
|
||||
( ((VALUE)>>(FD_ ## FIELD ## _S)) &(FD_ ## FIELD ## _M))
|
||||
#else /*__STDC__*/
|
||||
#define INSERT(FIELD,VALUE)\
|
||||
(((VALUE)&(FD_/* */FIELD/* */_M))<<(FD_/* */FIELD/* */_S))
|
||||
#define EXTRACT(FIELD,VALUE)\
|
||||
( ((VALUE)>>(FD_/* */FIELD/* */_S)) &(FD_/* */FIELD/* */_M))
|
||||
#endif /*__STDC__*/
|
||||
|
||||
/*
|
||||
* in the constants below _M is a right justified mask
|
||||
* and _S is a shift required to right justify the field
|
||||
*/
|
||||
|
||||
/*
|
||||
* csr register
|
||||
*/
|
||||
#define FD_FULL_M (0x1)
|
||||
#define FD_FULL_S (14)
|
||||
#define FD_READY_M (0x1)
|
||||
#define FD_READY_S (15)
|
||||
#define FD_BUSY_FULL_M (0x3)
|
||||
#define FD_BUSY_FULL_S (14)
|
||||
#define FD_IVEC_M (0xff)
|
||||
#define FD_IVEC_S (0)
|
||||
#define FD_ILEVEL_M (0x7)
|
||||
#define FD_ILEVEL_S (8)
|
||||
|
||||
/*
|
||||
* series/version register
|
||||
*/
|
||||
#define FD_SERIES_M (0xfff)
|
||||
#define FD_SERIES_S (0)
|
||||
#define FD_VERSION_M (0xf)
|
||||
#define FD_VERSION_S (12)
|
||||
|
||||
/*
|
||||
* data register
|
||||
*/
|
||||
#define FD_CHANNEL_M (0x7)
|
||||
#define FD_CHANNEL_S (13)
|
||||
#define FD_RANGE_M (1)
|
||||
#define FD_RANGE_S (12)
|
||||
#define FD_DATA_M (0xfff)
|
||||
#define FD_DATA_S (0)
|
||||
|
||||
struct channel{
|
||||
int16_t signal;
|
||||
char newData;
|
||||
};
|
||||
|
||||
enum adc_range {adc_12, adc_15, NUMBER_OF_ADC_RANGES};
|
||||
#define NUMBER_OF_SIGNALS 8
|
||||
#define NUMBER_OF_FIFO_ENTRIES (16*NUMBER_OF_SIGNALS*NUMBER_OF_ADC_RANGES)
|
||||
LOCAL struct caenV265Config{
|
||||
struct caenV265 *pCaenV265; /* pointer to the card */
|
||||
struct channel chan[NUMBER_OF_SIGNALS][NUMBER_OF_ADC_RANGES];
|
||||
IOSCANPVT scanpvt;
|
||||
WDOG_ID wdid;
|
||||
}caenV265Info[CAIN_V265_MAX_CARD_COUNT];
|
||||
|
||||
#ifdef __STDC__
|
||||
#define SHOW_OFFSET(STRUCT,FIELD) \
|
||||
printf( "%s.%s is at 0x%X\n", \
|
||||
#STRUCT, \
|
||||
#FIELD, \
|
||||
offsetof(struct STRUCT, FIELD))
|
||||
#endif
|
||||
|
||||
LOCAL void caenV265ISR(unsigned card);
|
||||
LOCAL int caenV265Shutdown(void);
|
||||
LOCAL int caenV265IdTest(struct caenV265 *pCaenV265);
|
||||
int caenV265Test(unsigned card);
|
||||
LOCAL void caenV265ReadData(struct caenV265Config *pCaenV256Config);
|
||||
LOCAL int caenV265TestVal(unsigned card, unsigned dacVal);
|
||||
LOCAL int caenV265IntEnable(unsigned card);
|
||||
|
||||
/*
|
||||
* device support entry table
|
||||
*/
|
||||
LOCAL long caenV265InitRecord(struct aiRecord *pai);
|
||||
LOCAL long caenV265AiRead(struct aiRecord *pai);
|
||||
LOCAL long caenV265SpecialLinconv(struct aiRecord *pai, int after);
|
||||
LOCAL long caenV265GetIoIntInfo(int cmd, struct aiRecord *pai, IOSCANPVT *ppvt);
|
||||
struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;
|
||||
DEVSUPFUN special_linconv;
|
||||
} devCaenV265 ={
|
||||
6,
|
||||
NULL,
|
||||
NULL,
|
||||
caenV265InitRecord,
|
||||
caenV265GetIoIntInfo,
|
||||
caenV265AiRead,
|
||||
caenV265SpecialLinconv};
|
||||
|
||||
/*
|
||||
* driver support entry table
|
||||
*/
|
||||
LOCAL long caenV265Init(void);
|
||||
LOCAL long caenV265IOReport(int level);
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvCaenV265 ={
|
||||
2,
|
||||
caenV265IOReport,
|
||||
caenV265Init};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* verify that register
|
||||
* offsets match the doc.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
void offsettest()
|
||||
{
|
||||
SHOW_OFFSET(caenV265, version);
|
||||
SHOW_OFFSET(caenV265, identifier);
|
||||
SHOW_OFFSET(caenV265, fixed);
|
||||
SHOW_OFFSET(caenV265, data);
|
||||
SHOW_OFFSET(caenV265, gate);
|
||||
SHOW_OFFSET(caenV265, DAC);
|
||||
SHOW_OFFSET(caenV265, clear);
|
||||
SHOW_OFFSET(caenV265, csr);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* caenV265InitRecord()
|
||||
*/
|
||||
LOCAL long caenV265InitRecord(struct aiRecord *pai)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
/* ai.inp must be an VME_IO */
|
||||
switch (pai->inp.type) {
|
||||
case (VME_IO):
|
||||
break;
|
||||
default :
|
||||
recGblRecordError(S_db_badField,(void *)pai,
|
||||
"devAiXy566Se (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad signal or card number
|
||||
*/
|
||||
if ( pvmeio->signal >= NUMBER_OF_SIGNALS ||
|
||||
pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 bad card or signal number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!caenV265Info[pvmeio->card].pCaenV265){
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 card does not exist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
pai->eslo = (pai->eguf-pai->egul)/FD_DATA_M;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265AiRead()
|
||||
*/
|
||||
LOCAL long caenV265AiRead(struct aiRecord *pai)
|
||||
{
|
||||
int16_t value;
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad signal or card number
|
||||
*/
|
||||
if ( pvmeio->signal >= NUMBER_OF_SIGNALS ||
|
||||
pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
|
||||
recGblSetSevr(pai, READ_ALARM, INVALID_ALARM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* uninitialized data?
|
||||
*/
|
||||
if (!caenV265Info[pvmeio->card].chan[pvmeio->signal][adc_12].newData) {
|
||||
recGblSetSevr(pai, READ_ALARM, INVALID_ALARM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
value = caenV265Info[pvmeio->card].chan[pvmeio->signal][adc_12].signal;
|
||||
pai->rval = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265SpecialLinconv()
|
||||
*/
|
||||
LOCAL long caenV265SpecialLinconv(struct aiRecord *pai, int after)
|
||||
{
|
||||
if(!after) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
pai->eslo = (pai->eguf-pai->egul)/FD_DATA_M;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265GetIoIntInfo()
|
||||
*/
|
||||
LOCAL long caenV265GetIoIntInfo(
|
||||
int cmd,
|
||||
struct aiRecord *pai,
|
||||
IOSCANPVT *ppvt)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad card number
|
||||
*/
|
||||
if ( pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
logMsg(
|
||||
"%s.%d:devCaenV265 bad card number %d %s\n",
|
||||
(int)__FILE__,
|
||||
__LINE__,
|
||||
pvmeio->card,
|
||||
(int)pai->name,0,0);
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 bad card number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ppvt = &caenV265Info[pvmeio->card].scanpvt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Init()
|
||||
*/
|
||||
LOCAL long caenV265Init(void)
|
||||
{
|
||||
unsigned card;
|
||||
struct caenV265 *pCaenV265;
|
||||
int status;
|
||||
|
||||
status = rebootHookAdd(caenV265Shutdown);
|
||||
if(status){
|
||||
errMessage(S_dev_internal,"reboot hook add failed");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
status = sysBusToLocalAdrs(
|
||||
VME_AM_STD_SUP_DATA,
|
||||
CAIN_V265_A24_BASE,
|
||||
(char **)&pCaenV265);
|
||||
if(status!=OK){
|
||||
errPrintf(
|
||||
S_dev_badA24,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"caenV265Init");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
for(card=0; card<CAIN_V265_MAX_CARD_COUNT; card++, pCaenV265++){
|
||||
unsigned vec;
|
||||
|
||||
if(!caenV265IdTest(pCaenV265)){
|
||||
continue;
|
||||
}
|
||||
|
||||
caenV265Info[card].wdid = wdCreate();
|
||||
if(!caenV265Info[card].wdid){
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* flag that we have found a caen V265
|
||||
*/
|
||||
caenV265Info[card].pCaenV265 = pCaenV265;
|
||||
|
||||
/*
|
||||
* init the EPICS db int event scan block
|
||||
*/
|
||||
scanIoInit(&caenV265Info[card].scanpvt);
|
||||
|
||||
/*
|
||||
* reset the device
|
||||
*/
|
||||
pCaenV265->clear = 0; /* any rw op resets the device */
|
||||
pCaenV265->DAC = 0; /* set test-signal "offset" to zero */
|
||||
|
||||
/*
|
||||
* attach ISR
|
||||
*/
|
||||
vec = CAIN_V265_INTVEC_BASE+card;
|
||||
status = intConnect(
|
||||
INUM_TO_IVEC(vec),
|
||||
caenV265ISR,
|
||||
card);
|
||||
assert(status>=0);
|
||||
|
||||
/*
|
||||
* Enable interrupts
|
||||
*/
|
||||
caenV265IntEnable(card);
|
||||
}
|
||||
status = sysIntEnable(CAIN_V265_INT_LEVEL);
|
||||
assert(status>=0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265ISR()
|
||||
*/
|
||||
LOCAL void caenV265ISR(unsigned card)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned signal;
|
||||
int16_t csr;
|
||||
static unsigned ticks;
|
||||
unsigned newTicks;
|
||||
|
||||
/*
|
||||
* If its full then its more efficient
|
||||
* to read it out without checking
|
||||
* in between each read
|
||||
*/
|
||||
csr = pCaenV265->csr;
|
||||
if (EXTRACT(FULL,csr)) {
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_FIFO_ENTRIES;
|
||||
signal++){
|
||||
|
||||
caenV265ReadData(pCaenV256Config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not full so check to see if its ready before
|
||||
* reading
|
||||
*/
|
||||
while (EXTRACT(READY, csr)) {
|
||||
caenV265ReadData(pCaenV256Config);
|
||||
csr = pCaenV265->csr;
|
||||
}
|
||||
|
||||
/*
|
||||
* limit the EPICS scan rate
|
||||
*/
|
||||
newTicks = tickGet();
|
||||
if(newTicks == ticks){
|
||||
/*
|
||||
* Disable Interrupts
|
||||
*/
|
||||
pCaenV265->csr = 0;
|
||||
|
||||
/*
|
||||
* start a watch dog after one tick
|
||||
* so that we limit the int rate to
|
||||
* the system tick rate.
|
||||
*/
|
||||
wdStart(pCaenV256Config->wdid,
|
||||
1,
|
||||
caenV265IntEnable,
|
||||
card);
|
||||
|
||||
return;
|
||||
}
|
||||
else{
|
||||
ticks = newTicks;
|
||||
}
|
||||
|
||||
/*
|
||||
* tell EPICS to scan on int
|
||||
*/
|
||||
scanIoRequest(&caenV265Info[card].scanpvt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IntEnable
|
||||
*/
|
||||
LOCAL int caenV265IntEnable(unsigned card)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned vec;
|
||||
int16_t newcsr;
|
||||
|
||||
|
||||
vec = CAIN_V265_INTVEC_BASE+card;
|
||||
newcsr = INSERT(IVEC, vec) | INSERT(ILEVEL, CAIN_V265_INT_LEVEL);
|
||||
pCaenV265->csr = newcsr;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265ReadData()
|
||||
*/
|
||||
LOCAL void caenV265ReadData(struct caenV265Config *pCaenV256Config)
|
||||
{
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
int16_t val = pCaenV265->data;
|
||||
int16_t data = EXTRACT(DATA, val);
|
||||
unsigned range = EXTRACT(RANGE, val);
|
||||
unsigned signal = EXTRACT(CHANNEL, val);
|
||||
|
||||
if(range>=NUMBER_OF_ADC_RANGES){
|
||||
logMsg("caenV265ReadData: bad range number\n",0,0,0,0,0,0);
|
||||
return;
|
||||
}
|
||||
if(signal>=NUMBER_OF_SIGNALS){
|
||||
logMsg("caenV265ReadData: bad signal number\n",0,0,0,0,0,0);
|
||||
return;
|
||||
}
|
||||
pCaenV256Config->chan[signal][range].signal=data;
|
||||
pCaenV256Config->chan[signal][range].newData=TRUE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IdTest()
|
||||
*/
|
||||
LOCAL int caenV265IdTest(struct caenV265 *pCaenV265)
|
||||
{
|
||||
int status;
|
||||
int16_t id;
|
||||
|
||||
/*
|
||||
* Is a card present
|
||||
*/
|
||||
status = vxMemProbe(
|
||||
(char *)&pCaenV265->identifier,
|
||||
READ,
|
||||
sizeof(id),
|
||||
(char *)&id);
|
||||
if(status!=OK){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the correct type of card present
|
||||
*/
|
||||
if(id!=CAENV265ID){
|
||||
errPrintf(
|
||||
S_dev_wrongDevice,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"caenV265IdTest");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Shutdown()
|
||||
* turns off interrupts so that dont foul up the boot
|
||||
*/
|
||||
LOCAL int caenV265Shutdown(void)
|
||||
{
|
||||
struct caenV265 *pCaenV265;
|
||||
unsigned card;
|
||||
|
||||
for(card=0; card<CAIN_V265_MAX_CARD_COUNT; card++){
|
||||
pCaenV265 = caenV265Info[card].pCaenV265;
|
||||
if(!pCaenV265){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(caenV265IdTest(pCaenV265)){
|
||||
/*
|
||||
* disable interrupts
|
||||
*/
|
||||
pCaenV265->csr=0;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Test()
|
||||
*/
|
||||
int caenV265Test(unsigned card)
|
||||
{
|
||||
unsigned dacVal;
|
||||
struct caenV265Config cofigCpy;
|
||||
unsigned range;
|
||||
unsigned signal;
|
||||
|
||||
|
||||
dacVal=0;
|
||||
caenV265TestVal(card, dacVal);
|
||||
while(dacVal<FD_DATA_M){
|
||||
|
||||
cofigCpy = caenV265Info[card];
|
||||
dacVal = dacVal+32;
|
||||
caenV265TestVal(card, dacVal);
|
||||
|
||||
for( range=0;
|
||||
range<NUMBER_OF_ADC_RANGES;
|
||||
range++){
|
||||
char *pRangeName[] = { "12 bit signal",
|
||||
"15 bit signal"};
|
||||
|
||||
printf( "\t%s with DAC = 0x%X\n",
|
||||
pRangeName[range],
|
||||
dacVal);
|
||||
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
unsigned newdata;
|
||||
unsigned olddata;
|
||||
|
||||
olddata = cofigCpy.chan[signal][range].signal;
|
||||
newdata = caenV265Info[card].
|
||||
chan[signal][range].signal;
|
||||
|
||||
printf( "\t\tchan=0x%1X diff = 0x%03X\n",
|
||||
signal,
|
||||
newdata-olddata);
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265TestVal()
|
||||
*/
|
||||
LOCAL int caenV265TestVal(unsigned card, unsigned dacVal)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned signal;
|
||||
|
||||
if(!pCaenV265){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if(!caenV265IdTest(pCaenV265)){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear the module
|
||||
*/
|
||||
pCaenV265->clear=0;
|
||||
|
||||
/*
|
||||
* generate a test signal
|
||||
*/
|
||||
pCaenV265->DAC=dacVal;
|
||||
|
||||
/*
|
||||
* generate a test gate
|
||||
*/
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
caenV265Info[card].chan[signal][adc_12].newData=FALSE;
|
||||
caenV265Info[card].chan[signal][adc_15].newData=FALSE;
|
||||
while(!caenV265Info[card].chan[signal][adc_15].newData){
|
||||
pCaenV265->gate=0;
|
||||
taskDelay(1);
|
||||
}
|
||||
while(!caenV265Info[card].chan[signal][adc_12].newData){
|
||||
pCaenV265->gate=0;
|
||||
taskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn off test signal
|
||||
*/
|
||||
pCaenV265->clear=0;
|
||||
pCaenV265->DAC=0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IOReport()
|
||||
*/
|
||||
LOCAL long caenV265IOReport(int level)
|
||||
{
|
||||
struct caenV265 *pCaenV265;
|
||||
unsigned card;
|
||||
unsigned signal;
|
||||
unsigned range;
|
||||
char *pVersion[] = {"NIM","ECL"};
|
||||
char *pState[] = {
|
||||
"FIFO empty",
|
||||
"FIFO full",
|
||||
"FIFO partially filled",
|
||||
"FIFO full"};
|
||||
|
||||
for (card=0; card<CAIN_V265_MAX_CARD_COUNT; card++) {
|
||||
pCaenV265 = caenV265Info[card].pCaenV265;
|
||||
if (!pCaenV265) {
|
||||
continue;
|
||||
}
|
||||
if (!caenV265IdTest(pCaenV265)) {
|
||||
continue;
|
||||
}
|
||||
printf("AI: caen V265:\tcard %d\n", card);
|
||||
if (level == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\tversion = %s\n",
|
||||
pVersion[EXTRACT(VERSION, pCaenV265->version)]);
|
||||
printf("\tseries = %d\n",
|
||||
EXTRACT(SERIES, pCaenV265->version));
|
||||
printf("\tstate = %s\n",
|
||||
pState[EXTRACT(BUSY_FULL,pCaenV265->csr)]);
|
||||
printf("\tint level = %d\n",
|
||||
EXTRACT(ILEVEL,pCaenV265->csr));
|
||||
printf("\tint vec = 0x%02X\n",
|
||||
EXTRACT(IVEC,pCaenV265->csr));
|
||||
printf( "\tbase addr= 0x%X on the %s\n",
|
||||
(unsigned)caenV265Info[card].pCaenV265,
|
||||
sysModel());
|
||||
|
||||
for( range=0;
|
||||
range<NUMBER_OF_ADC_RANGES;
|
||||
range++){
|
||||
char *pRangeName[] = { "12 bit signal",
|
||||
"15 bit signal"};
|
||||
|
||||
printf("\t%s\n", pRangeName[range]);
|
||||
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
int16_t data;
|
||||
|
||||
data = caenV265Info[card].
|
||||
chan[signal][range].signal;
|
||||
|
||||
if(caenV265Info[card].chan[signal][range].newData){
|
||||
printf( "\t\tchan=0x%1X val = 0x%03X\n",
|
||||
signal,
|
||||
data);
|
||||
}
|
||||
else{
|
||||
printf( "\t\tchan=0x%1X <NO GATE>\n",
|
||||
signal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
639
src/drv/old/drvComet.c
Normal file
639
src/drv/old/drvComet.c
Normal file
@@ -0,0 +1,639 @@
|
||||
/* comet_driver.c */
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* Author: Leo R. Dalesio
|
||||
* Date: 5-92
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 joh 071092 added argument to calloc()
|
||||
* .02 joh 071092 stripped the hkv2f specific portion off the comet
|
||||
* std addr base specification and left it at base
|
||||
* addr zero which is most likely wrong.
|
||||
* .03 joh 071492 use extended (A32) address space
|
||||
* instead of standard (A24) address space
|
||||
* for the base address of the waveform memory
|
||||
* (changed arg to sysBusToLocalAdrs()
|
||||
* .04 joh 071592 fixed to use correct size when incrementing
|
||||
* to the waveform memory of the second card
|
||||
* .05 joh 071592 modified A16 & A32 base addr to match AT8
|
||||
* address standard
|
||||
* .06 bg 071792 moved addresses to module_types.h
|
||||
* .07 joh 080592 added io report routines
|
||||
* .08 ms 080692 added comet_mode routine, modified comet_driver
|
||||
* and cometDoneTask to allow an external routine
|
||||
* to control hardware scan mode. Added variable
|
||||
* scan_control to flag operating mode.
|
||||
* .09 mrk 082692 added DSET
|
||||
* .10 joh 082792 fixed uninitialized csr pointer in comet_driver()
|
||||
* function
|
||||
* .11 lrd 091692 add signal support
|
||||
* .12 joh 092992 card number validation now based on module_types.h.
|
||||
* signal number checking now based on the array element
|
||||
* count.
|
||||
* .13 mrk 080293 Added call to taskwdInsert
|
||||
* .14 mgb 080493 Removed V5/V4 and EPICS_V2 conditionals
|
||||
*/
|
||||
|
||||
static char *sccsID = "@(#)drvComet.c 1.11\t9/16/92";
|
||||
|
||||
/*
|
||||
* Code Portions
|
||||
*
|
||||
* comet_init()
|
||||
* comet_driver(card, pcbroutine, parg)
|
||||
* cometDoneTask()
|
||||
* comet_io_report()
|
||||
* comet_mode(card,mode,arg,val)
|
||||
*
|
||||
*/
|
||||
#include <vxWorks.h>
|
||||
#include <iv.h>
|
||||
#include <types.h>
|
||||
#include <module_types.h>
|
||||
#include <task_params.h>
|
||||
#include <fast_lock.h>
|
||||
#include <vme.h>
|
||||
#include <drvSup.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbScan.h>
|
||||
#include <taskwd.h>
|
||||
|
||||
#define COMET_NCHAN 4
|
||||
#define COMET_CHANNEL_MEM_SIZE 0x20000 /* bytes */
|
||||
#define COMET_DATA_MEM_SIZE (COMET_CHANNEL_MEM_SIZE*COMET_NCHAN)
|
||||
static char *shortaddr;
|
||||
static short scan_control; /* scan type/rate (if >0 normal, <=0 external control) */
|
||||
|
||||
/* comet conrtol register map */
|
||||
struct comet_cr{
|
||||
unsigned char csrh; /* control and status register - high byte */
|
||||
unsigned char csrl; /* control and status register - low byte */
|
||||
unsigned char lcrh; /* location status register - high byte */
|
||||
unsigned char lcrl; /* location status register - low byte */
|
||||
unsigned char gdcrh; /* gate duration status register - high byte*/
|
||||
unsigned char gdcrl; /* gate duration status register - low byte */
|
||||
unsigned char cdr; /* channel delay register */
|
||||
unsigned char acr; /* auxiliary control register */
|
||||
char pad[0x100-8];
|
||||
};
|
||||
|
||||
|
||||
/* defines for the control status register - high byte */
|
||||
#define DIGITIZER_ACTIVE 0x80 /* 1- Active */
|
||||
#define ARM_DIGITIZER 0x40 /* 1- Arm the digitizer */
|
||||
#define CIRC_BUFFER_ENABLED 0x20 /* 0- Stop when memory is full */
|
||||
#define WRAP_MODE_ENABLED 0x10 /* 0- Disable wrap around */
|
||||
#define AUTO_RESET_LOC_CNT 0x08 /* 1- Reset addr to 0 on trigger */
|
||||
#define EXTERNAL_TRIG_ENABLED 0x04 /* 1- use external clk to trigger */
|
||||
#define EXTERNAL_GATE_ENABLED 0x02 /* 0- use pulse start conversion */
|
||||
#define EXTERNAL_CLK_ENABLED 0x01 /* 0- uses the internal clock */
|
||||
|
||||
|
||||
/* commands for the COMET digitizer */
|
||||
#define COMET_INIT_CSRH
|
||||
#define COMET_INIT_READ
|
||||
|
||||
/* mode commands for the COMET digitizer */
|
||||
#define READREG 0
|
||||
#define WRITEREG 1
|
||||
#define SCANCONTROL 2
|
||||
#define SCANSENSE 3
|
||||
#define SCANDONE 4
|
||||
|
||||
/* register selects */
|
||||
#define COMET_CSR 0
|
||||
#define COMET_LCR 1
|
||||
#define COMET_GDCR 2
|
||||
#define COMET_CDACR 3
|
||||
|
||||
/* defines for the control status register - low byte */
|
||||
#define SOFTWARE_TRIGGER 0x80 /* 1- generates a software trigger */
|
||||
#define UNUSED 0x60
|
||||
#define CHAN_DELAY_ENABLE 0x10 /* 0- digitize on trigger */
|
||||
#define DIG_RATE_SELECT 0x0f
|
||||
|
||||
/* digitizer rates - not defined but available for 250KHz to 122Hz */
|
||||
#define COMET_5MHZ 0x0000
|
||||
#define COMET_2MHZ 0x0001
|
||||
#define COMET_1MHZ 0x0002
|
||||
#define COMET_500KHZ 0x0003
|
||||
|
||||
/* defines for the auxiliary control register */
|
||||
#define ONE_SHOT 0x10
|
||||
#define ALL_CHANNEL_MODE 0x80
|
||||
|
||||
|
||||
/* comet configuration data */
|
||||
struct comet_config{
|
||||
struct comet_cr *pcomet_csr; /* pointer to the control/status register */
|
||||
unsigned short *pdata; /* pointer to data area for this COMET card */
|
||||
void (*psub)(); /* subroutine to call on end of conversion */
|
||||
void *parg[4]; /* argument to return to the arming routine */
|
||||
FAST_LOCK lock; /* mutual exclusion lock */
|
||||
IOSCANPVT ioscanpvt;
|
||||
unsigned long nelements; /* number of elements to digitize/read */
|
||||
|
||||
};
|
||||
|
||||
/* task ID for the comet done task */
|
||||
int cometDoneTaskId;
|
||||
struct comet_config *pcomet_config;
|
||||
|
||||
static long report();
|
||||
static long init();
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvComet={
|
||||
2,
|
||||
report,
|
||||
init};
|
||||
|
||||
|
||||
/*
|
||||
* cometDoneTask
|
||||
*
|
||||
* wait for comet waveform record cycle complete
|
||||
* and call back to the database with the waveform size and address
|
||||
*
|
||||
*/
|
||||
void
|
||||
cometDoneTask()
|
||||
{
|
||||
register unsigned card;
|
||||
register struct comet_config *pconfig;
|
||||
register long i;
|
||||
|
||||
while(TRUE)
|
||||
{
|
||||
|
||||
if (scan_control <= 0)
|
||||
taskDelay(2);
|
||||
else
|
||||
{
|
||||
taskDelay(scan_control);
|
||||
|
||||
/* printf("DoneTask: entering for loop...\n"); */
|
||||
|
||||
/* check each card for end of conversion */
|
||||
for(card=0, pconfig = pcomet_config; card < 2;card++, pconfig++)
|
||||
{
|
||||
/* is the card present */
|
||||
if (!pconfig->pcomet_csr)
|
||||
{
|
||||
if (card == 0)
|
||||
{
|
||||
/*
|
||||
printf("DoneTask: checking card present?...\n");
|
||||
printf("DoneTask: pconfig->pcomet_csr %x...\n",pconfig->pcomet_csr);
|
||||
*/
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* is the card armed */
|
||||
if (!pconfig->psub)
|
||||
{
|
||||
if (card == 0)
|
||||
{
|
||||
/* printf("DoneTask: checking card armed?...\n"); */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* is the digitizer finished conversion */
|
||||
/* printf("pconfig->pdata: %x \n", pconfig->pdata); */
|
||||
|
||||
if (*(pconfig->pdata+pconfig->nelements) == 0xffff)
|
||||
{
|
||||
if (card == 0)
|
||||
{
|
||||
/* printf("DoneTask: finished conversion?...\n"); */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* printf("DoneTask: pcomet_config->pcomet_csr %x...\n",pcomet_config->pcomet_csr); */
|
||||
/* printf("DoneTask: DONE\n"); */
|
||||
|
||||
|
||||
#if 0
|
||||
/* reset each of the control registers */
|
||||
pconfig->pcomet_csr->csrh = pconfig->pcomet_csr->csrl = 0;
|
||||
pconfig->pcomet_csr->lcrh = pconfig->pcomet_csr->lcrl = 0;
|
||||
pconfig->pcomet_csr->gdcrh = pconfig->pcomet_csr->gdcrl = 0;
|
||||
pconfig->pcomet_csr->acr = 0;
|
||||
#endif
|
||||
|
||||
/* clear the pointer to the subroutine to allow rearming */
|
||||
/* pconfig->psub = NULL; */
|
||||
|
||||
/* post the event */
|
||||
/* - is there a bus error for long references to this card?? copy into VME mem? */
|
||||
|
||||
if(pconfig->parg[0])
|
||||
{
|
||||
(*pconfig->psub)(pconfig->parg[0],pconfig->pdata);
|
||||
}
|
||||
if(pconfig->parg[1])
|
||||
{
|
||||
(*pconfig->psub)(pconfig->parg[1],(((char*)pconfig->pdata)+0x20000));
|
||||
}
|
||||
|
||||
if(pconfig->parg[2])
|
||||
{
|
||||
(*pconfig->psub)(pconfig->parg[2],(((char*)pconfig->pdata)+0x40000));
|
||||
}
|
||||
|
||||
if(pconfig->parg[3])
|
||||
{
|
||||
(*pconfig->psub)(pconfig->parg[3],(((char*)pconfig->pdata)+0x60000));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* COMET_INIT
|
||||
*
|
||||
* intialize the driver for the COMET digitizer from omnibyte
|
||||
*
|
||||
*/
|
||||
comet_init()
|
||||
{
|
||||
register struct comet_config *pconfig;
|
||||
short readback,got_one,card;
|
||||
int status;
|
||||
struct comet_cr *pcomet_cr;
|
||||
unsigned char *extaddr;
|
||||
|
||||
/* free memory and delete tasks from previous initialization */
|
||||
if (cometDoneTaskId)
|
||||
{
|
||||
taskwdRemove(cometDoneTaskId);
|
||||
if ((status = taskDelete(cometDoneTaskId)) < 0)
|
||||
logMsg("\nCOMET: Failed to delete cometDoneTask: %d",status);
|
||||
}
|
||||
else
|
||||
{
|
||||
pcomet_config = (struct comet_config *)calloc(wf_num_cards[COMET],sizeof(struct comet_config));
|
||||
if (pcomet_config == 0)
|
||||
{
|
||||
logMsg("\nCOMET: Couldn't allocate memory for the configuration data");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the standard and short address locations */
|
||||
if ((status = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,wf_addrs[COMET],&pcomet_cr)) != OK){
|
||||
logMsg("\nCOMET: failed to map VME A16 base address\n");
|
||||
return;
|
||||
}
|
||||
if ((status = sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA,wf_memaddrs[COMET],&extaddr)) != OK){
|
||||
logMsg("\nCOMET: failed to map VME A32 base address\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* determine which cards are present */
|
||||
got_one = FALSE;
|
||||
pconfig = pcomet_config;
|
||||
|
||||
for ( card = 0;
|
||||
card < 2;
|
||||
card++, pconfig++, pcomet_cr++, extaddr+= COMET_DATA_MEM_SIZE){
|
||||
|
||||
/* is the card present */
|
||||
if (vxMemProbe(pcomet_cr,READ,sizeof(readback),&readback) != OK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (vxMemProbe(extaddr,READ,sizeof(readback),&readback) != OK)
|
||||
{
|
||||
logMsg("\nCOMET: Found CSR but not data RAM %x\n",extaddr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* initialize the configuration data */
|
||||
pconfig->pcomet_csr = pcomet_cr;
|
||||
pconfig->pdata = (unsigned short *) extaddr;
|
||||
got_one = TRUE;
|
||||
|
||||
|
||||
FASTLOCKINIT(&pcomet_config[card].lock);
|
||||
|
||||
/* initialize the card */
|
||||
pcomet_cr->csrh = ARM_DIGITIZER | AUTO_RESET_LOC_CNT;
|
||||
pcomet_cr->csrl = COMET_1MHZ;
|
||||
pcomet_cr->lcrh = pcomet_cr->lcrl = 0;
|
||||
pcomet_cr->gdcrh = 0;
|
||||
pcomet_cr->gdcrl = 1;
|
||||
pcomet_cr->cdr = 0;
|
||||
|
||||
/* run it once */
|
||||
pcomet_cr->csrl |= SOFTWARE_TRIGGER;
|
||||
taskDelay(1);
|
||||
/* reset */
|
||||
pcomet_cr->csrl = COMET_5MHZ;
|
||||
pcomet_cr->acr = ONE_SHOT | ALL_CHANNEL_MODE;
|
||||
|
||||
scanIoInit(&pconfig->ioscanpvt);
|
||||
|
||||
} /*end of for loop*/
|
||||
|
||||
/* initialization for processing comet digitizers */
|
||||
if(got_one)
|
||||
{
|
||||
/* start the waveform readback task */
|
||||
scan_control = 2; /* scan rate in vxWorks clock ticks */
|
||||
cometDoneTaskId = taskSpawn("cometWFTask",WFDONE_PRI,WFDONE_OPT,WFDONE_STACK,(FUNCPTR) cometDoneTask);
|
||||
taskwdInsert(cometDoneTaskId,NULL,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static long report(level)
|
||||
int level;
|
||||
{
|
||||
comet_io_report(level);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long init()
|
||||
{
|
||||
|
||||
comet_init();
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* COMET_DRIVER
|
||||
*
|
||||
* initiate waveform read
|
||||
*
|
||||
*/
|
||||
comet_driver(card, signal, pcbroutine, parg, nelements)
|
||||
register short card;
|
||||
register unsigned short signal;
|
||||
unsigned int *pcbroutine;
|
||||
unsigned int *parg; /* pointer to the waveform record */
|
||||
unsigned long nelements;
|
||||
{
|
||||
register struct comet_cr *pcomet_csr;
|
||||
register struct comet_config *pconfig;
|
||||
register unsigned short *pcomet_data;
|
||||
register char *dummy;
|
||||
|
||||
/* printf("comet_driver: BEGIN...\n"); */
|
||||
/* printf("comet_driver: nelements: %d ...\n",nelements); */
|
||||
|
||||
/* check for valid card number */
|
||||
if(card >= wf_num_cards[COMET])
|
||||
return ERROR;
|
||||
pconfig = (pcomet_config+card);
|
||||
if(signal >= NELEMENTS(pconfig->parg))
|
||||
return ERROR;
|
||||
pconfig->nelements = nelements * 2;
|
||||
|
||||
/* printf("comet_driver: check for card present...\n"); */
|
||||
|
||||
/* check for card present */
|
||||
if(!pconfig->pcomet_csr) return ERROR;
|
||||
|
||||
/* mutual exclusion area */
|
||||
FASTLOCK(&pconfig->lock);
|
||||
|
||||
/* printf("comet_driver: mark the card as armed...\n"); */
|
||||
|
||||
/* mark the card as armed */
|
||||
/* if (pconfig->parg[signal] != 0) */
|
||||
pconfig->parg[signal] = parg;
|
||||
/* if (pconfig->psub) return; */
|
||||
pconfig->psub = (void (*)()) pcbroutine;
|
||||
|
||||
/* exit mutual exclusion area */
|
||||
FASTUNLOCK(&pconfig->lock);
|
||||
|
||||
pcomet_csr = pconfig->pcomet_csr;
|
||||
|
||||
/* reset each of the control registers */
|
||||
pcomet_csr->csrh = pcomet_csr->csrl = 0;
|
||||
pcomet_csr->lcrh = pcomet_csr->lcrl = 0;
|
||||
pcomet_csr->gdcrh = pcomet_csr->gdcrl = 0;
|
||||
pcomet_csr->acr = 0;
|
||||
|
||||
/* arm the card */
|
||||
*(pconfig->pdata+pconfig->nelements) = 0xffff;
|
||||
/* printf("comet_driver: pconfig->pcomet_csr %x...\n",pconfig->pcomet_csr); */
|
||||
|
||||
if (scan_control > 0)
|
||||
{
|
||||
#if 0 /* for debugging purposes */
|
||||
pcomet_csr->gdcrh = 0x03; /* # samples per channel */
|
||||
pcomet_csr->gdcrl = 0xe8; /* # samples per channel */
|
||||
#endif
|
||||
|
||||
pcomet_csr->gdcrh = (pconfig->nelements >> 8) & 0xff; /* # samples per channel */
|
||||
pcomet_csr->gdcrl = pconfig->nelements & 0xff; /* # samples per channel */
|
||||
pcomet_csr->acr = ONE_SHOT | ALL_CHANNEL_MODE; /* disarm after the trigger */
|
||||
pcomet_csr->csrl = COMET_5MHZ; /* sample at 5MhZ */
|
||||
|
||||
/* arm, reset location counter to 0 on trigger, use external trigger */
|
||||
pcomet_csr->csrh = ARM_DIGITIZER | AUTO_RESET_LOC_CNT | EXTERNAL_TRIG_ENABLED;
|
||||
/* printf("comet_driver: gdcrh: %x gdcrl: %x nelements: %x\n ",pcomet_csr->gdcrh,pcomet_csr->gdcrl, pconfig->nelements); */
|
||||
|
||||
}
|
||||
else
|
||||
pcomet_csr->csrh |= ARM_DIGITIZER;
|
||||
/* printf("comet_driver: pconfig->pcomet_csr %x...\n",pconfig->pcomet_csr); */
|
||||
|
||||
/* printf("comet_driver: END...\n"); */
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* COMET_IO_REPORT
|
||||
*
|
||||
* print status for all cards in the specified COMET address range
|
||||
*/
|
||||
comet_io_report(level)
|
||||
short int level;
|
||||
{
|
||||
struct comet_config *pconfig;
|
||||
unsigned card;
|
||||
unsigned nelements;
|
||||
int status;
|
||||
|
||||
pconfig = pcomet_config;
|
||||
for(card=0; card < wf_num_cards[COMET]; card++){
|
||||
|
||||
if(!pconfig->pcomet_csr)
|
||||
continue;
|
||||
|
||||
printf( "WF: COMET:\tcard=%d\n", card);
|
||||
if (level >= 2){
|
||||
printf("enter the number of elements to dump:");
|
||||
status = scanf("%d",&nelements);
|
||||
if(status == 1){
|
||||
comet_dump(card, nelements);
|
||||
}
|
||||
}
|
||||
pconfig++;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* comet_dump
|
||||
*
|
||||
*/
|
||||
int comet_dump(card, n)
|
||||
unsigned card;
|
||||
unsigned n;
|
||||
{
|
||||
unsigned short *pdata;
|
||||
unsigned short *psave;
|
||||
unsigned short *pbegin;
|
||||
unsigned short *pend;
|
||||
|
||||
if (card >= wf_num_cards[COMET])
|
||||
return ERROR;
|
||||
|
||||
pdata = pcomet_config[card].pdata;
|
||||
psave = (unsigned short *) malloc(n * sizeof(*psave));
|
||||
if(!psave){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
pbegin = psave;
|
||||
pend = &psave[n];
|
||||
for( pdata = pcomet_config[card].pdata;
|
||||
psave<pend;
|
||||
pdata++,psave++){
|
||||
*psave = *pdata;
|
||||
}
|
||||
|
||||
psave = pbegin;
|
||||
for( ;
|
||||
psave<pend;
|
||||
psave++){
|
||||
if((psave-pbegin)%8 == 0){
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("%04X ", *psave);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
free(pbegin);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* comet_mode
|
||||
*
|
||||
* controls and reports operating mode
|
||||
*
|
||||
*/
|
||||
comet_mode(card,mode,arg,val)
|
||||
short card;
|
||||
unsigned short mode, arg, val;
|
||||
{
|
||||
unsigned char *cptr;
|
||||
int i;
|
||||
|
||||
if (card >= wf_num_cards[COMET])
|
||||
return ERROR;
|
||||
if (!pcomet_config[card].pcomet_csr)
|
||||
return ERROR;
|
||||
switch (mode)
|
||||
{
|
||||
case READREG:
|
||||
/*cptr = (unsigned char *)pcomet_config[card].pcomet_csr;
|
||||
for (i = 0; i < 6; i++, cptr++)
|
||||
printf("%x %x\n",cptr,*cptr);*/
|
||||
cptr = (unsigned char *)pcomet_config[card].pcomet_csr; /* point to offset 0 */
|
||||
cptr += arg<<1; /* build new offset */
|
||||
val = (*cptr++)<<8; /* read value and return */
|
||||
val |= *cptr;
|
||||
return val;
|
||||
break;
|
||||
case WRITEREG:
|
||||
cptr = (unsigned char *)pcomet_config[card].pcomet_csr;
|
||||
cptr += arg<<1;
|
||||
*cptr++ = val>>8;
|
||||
*cptr = val;
|
||||
break;
|
||||
case SCANCONTROL:
|
||||
scan_control = val;
|
||||
break;
|
||||
case SCANSENSE:
|
||||
return scan_control;
|
||||
break;
|
||||
case SCANDONE:
|
||||
if (!pcomet_config[card].psub)
|
||||
return ERROR;
|
||||
/*pcomet_config[card].psub = NULL;*/ /* clear the pointer to subroutine to allow rearming */
|
||||
(*pcomet_config[card].psub)(pcomet_config[card].parg,0xffff,pcomet_config[card].pdata);
|
||||
break;
|
||||
default:
|
||||
return ERROR;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
cometGetioscanpvt(card,scanpvt)
|
||||
short card;
|
||||
IOSCANPVT *scanpvt;
|
||||
{
|
||||
register struct comet_config *pconfig;
|
||||
|
||||
pconfig=pcomet_config;
|
||||
pconfig+=card;
|
||||
|
||||
if ((card >= wf_num_cards[COMET]) || (card < 0)) /* make sure hardware exists */
|
||||
return(0);
|
||||
|
||||
/*
|
||||
This is present in the mix driver...I don't know if I really need it.
|
||||
if (!pconfig->present)
|
||||
return(0);
|
||||
*/
|
||||
|
||||
*scanpvt = pconfig->ioscanpvt;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user