Compare commits

...

127 Commits

Author SHA1 Message Date
Marty Kraimer
ef12c444d8 Added support for retrieving adapter and card status 1995-04-26 14:16:59 +00:00
Marty Kraimer
cded07df78 Allen Bradley: Add support for retrieving adapter/card status 1995-04-26 13:37:05 +00:00
Marty Kraimer
81fb796c8d Allow record names to start with a digit. 1995-04-26 13:34:33 +00:00
Jeff Hill
b3af9b389a moved ansi drivers 1995-04-26 03:20:39 +00:00
Jeff Hill
9b76f9d9c0 Fix alignment problem found by purify 1995-04-26 03:14:08 +00:00
Jeff Hill
302f4ef6c8 dont send exception msg to all serach requests when the server
runs out of memory (send exception resp only in reply to search
requests that find a match)
1995-04-26 03:12:53 +00:00
Jeff Hill
64b7a679a0 Use vxWorks sem for locks and free lists when fdmgr delete
(none of this is currently used under UNIX)
1995-04-26 03:11:02 +00:00
Jeff Hill
e9624769cb moved already ANSI drivers into the ANSI directory 1995-04-26 03:02:57 +00:00
Jeff Hill
5ccee17d09 ANSI C changes 1995-04-26 03:01:02 +00:00
Jeff Hill
5e67b97e89 reformatted statement and fixed doc 1995-04-26 02:53:11 +00:00
Jeff Hill
7cd16f8ad6 fixed comment 1995-04-26 02:51:02 +00:00
Jeff Hill
b5aa0e300c fixed bug where nill func ptr io block called for get cb at disconnect 1995-04-26 02:49:30 +00:00
Jim Kowalkowski
c27c38d531 New Pentek 4261 support added 1995-04-25 15:49:23 +00:00
Jim Kowalkowski
b46166314f New device support for the Pentek 4261 ADC. 1995-04-25 15:47:21 +00:00
John Winans
593df59742 Changed name of HiDEOS link configuration command/function. 1995-04-25 15:32:23 +00:00
Andrew Johnson
561e2e9fb9 Moved environment parameter defaults to config/CONFIG_ENV 1995-04-24 16:02:24 +00:00
Ned Arnold
18b173eeb6 If reassignable PV ends in .DESC, change to .VAL 1995-04-19 18:58:50 +00:00
John Winans
47b3da99a0 Added support for the HiDEOS system as a GPIB bus transport agent. 1995-04-12 19:31:41 +00:00
cvs2svn
dd0ce8918a This commit was manufactured by cvs2svn to create tag 'R3.12.0-beta12'. 1995-04-07 11:50:22 +00:00
Jim Kowalkowski
a655930baf added ability to include files without substitution in the pattern file. 1995-04-07 11:50:21 +00:00
Jeff Hill
84773e71a0 init unintialized (and unused) fields in the protocol 1995-04-06 17:11:02 +00:00
Jeff Hill
214b9ae5c1 Use copyin structure to avoid VAX fp except when ieee is in VAX fp type
- also use dbr_ types
1995-04-06 17:06:14 +00:00
Jeff Hill
420249caac removed USEC_PER_SEC def 1995-04-06 17:01:52 +00:00
Jeff Hill
17a0f487a8 Increment the search resp count 1995-04-06 16:53:28 +00:00
Jeff Hill
bbfcd9ff78 Use dbr_ types 1995-04-06 16:51:20 +00:00
Jeff Hill
b9dc0dad91 added caIOBlockListFree() declaration 1995-04-06 16:49:51 +00:00
Jeff Hill
50be068a02 free outstanding get/put cb requests when the IOC disconnects 1995-04-06 16:47:41 +00:00
Jeff Hill
a90bdf0098 exponentially increase delay between search requests only when we get
no responses
1995-04-06 16:33:02 +00:00
Jeff Hill
a58a2439cd removed debug code (that was already commented out) 1995-04-06 16:28:45 +00:00
Jeff Hill
962b520be8 removed unused variables 1995-04-06 16:25:09 +00:00
Jeff Hill
6747d4e0e9 restored call to ca_flush_io() in ca_pend_event()
also now uses caIOBlockListFree()
1995-04-06 16:00:31 +00:00
Jeff Hill
043eeb6a7c added ASSERTUNIX 1995-04-06 15:48:52 +00:00
Janet B. Anderson
6b50908dd6 Portability changes. 1995-04-05 15:52:30 +00:00
Jim Kowalkowski
2d9514e8ad updated to use the new db format without the database() section 1995-04-05 15:28:03 +00:00
John Winans
2e7e1416d3 Only do a sysIntEnable() for those cards that are found with the probe. 1995-04-05 14:13:43 +00:00
cvs2svn
ed2f5648b2 This commit was manufactured by cvs2svn to create tag 'R3.12.0-beta11'. 1995-03-31 15:05:08 +00:00
John Winans
96da4b1121 Added devMpc.c 1995-03-31 15:05:07 +00:00
John Winans
3c6191cccd Machine protection system interface card 1995-03-31 15:03:32 +00:00
Marty Kraimer
60a488940c Make include look at ansi before old 1995-03-31 13:54:27 +00:00
Marty Kraimer
1c1d8228c7 Allen Bradley completely rewritten and move to ansi 1995-03-31 13:49:52 +00:00
Marty Kraimer
b2ee2f2347 New version of Allen Bradlet driver 1995-03-31 13:48:59 +00:00
Marty Kraimer
2c2673dcea Allen Bradley support completele rewritten 1995-03-31 13:47:50 +00:00
Janet B. Anderson
0e760bfc70 Modified includes to reflect new drv subdirectories old and ansi 1995-03-31 00:05:46 +00:00
Janet B. Anderson
f0234af637 Added solaris scripts for starting caRepeater and iocLogServer - anj 1995-03-30 23:17:59 +00:00
Janet B. Anderson
96f58790c4 Seperated drv files into ansi and old dirs. Added combine dir. 1995-03-30 19:36:44 +00:00
Janet B. Anderson
2c1004fb41 Changed include location in drv directory 1995-03-30 19:13:13 +00:00
Marty Kraimer
f6025d2a1f Fixed bugs in dnNotify code. Move code to dbNotify.c from dbLink and dbAccess 1995-03-30 19:04:34 +00:00
cvs2svn
4d046c8424 This commit was manufactured by cvs2svn to create tag 'R3.12.0-beta10'. 1995-03-24 21:24:26 +00:00
John Winans
e7e17f07af Probable race condition in PEP TX task. Moved the final transmission
byte assignment into the point where the busy list is locked.  This
is how the Xycom TX task has worked all along.  This change fixed
seems to have fixed an apparant race condition where the receive task
gets a response to a transmitted message BEFORE the TX task gets
it on the busy list.
1995-03-24 21:24:25 +00:00
Janet B. Anderson
8a23d381c4 Added define for USG 1995-03-24 15:29:08 +00:00
Janet B. Anderson
46b9bb6e6a Changed bcopy to memcpy and added include for string.h 1995-03-24 15:28:20 +00:00
Marty Kraimer
9ab85124d3 Allow pvnames to contain ; 1995-03-24 13:42:21 +00:00
Ned Arnold
b8f07e873d Version 1.15 always fills in RxCV, even if RxPV's are not valid. 1995-03-17 17:51:55 +00:00
John Winans
0cfd58942f Added waveform writing support 1995-03-10 16:55:40 +00:00
Jeff Hill
b75d3964d7 more ANSI C changes and fixed send call back lost problem 1995-03-08 17:44:46 +00:00
cvs2svn
b9c8cd50e0 This commit was manufactured by cvs2svn to create tag 'R3.12.0-beta9'. 1995-03-08 13:48:39 +00:00
Marty Kraimer
e7b8b42452 Make sure errInit is called before epicsPrintf or errPrintf execute 1995-03-08 13:48:38 +00:00
Marty Kraimer
4cc62a1fce Take errInit out of dbLoad 1995-03-08 13:45:36 +00:00
Jeff Hill
333c985399 added FTP script 1995-03-07 23:19:44 +00:00
Jeff Hill
f513681bc0 no zero length message under SOLARIS 1995-03-07 22:56:45 +00:00
Jeff Hill
ddb459d08a ANSI C changes 1995-03-07 22:47:51 +00:00
Marty Kraimer
6aa5ecfa0e Allow errInit to be called multiple times 1995-03-07 21:18:56 +00:00
Marty Kraimer
9bdea89b06 errInit must be called before errPrintf 1995-03-07 21:17:16 +00:00
John Winans
3c8b4bf8c0 added assertion to misc.c for dealing with the '\a' character problem. 1995-03-07 19:23:12 +00:00
Janet B. Anderson
a912205614 Put static on sub_it() definition. 1995-03-07 17:27:58 +00:00
Janet B. Anderson
3b094ac9ae Removed CMPLR=OLD line 1995-03-07 17:18:43 +00:00
Ned Arnold
13a7380a47 Bug fix. Didn't update PxRA arrays if no readback PV's were specified. 1995-03-07 15:29:45 +00:00
Jeff Hill
f1bc683bd4 ssert => epicsAssert 1995-03-07 01:25:09 +00:00
Jeff Hill
5d3ded4397 ssert to epicsAssert.h 1995-03-07 01:21:16 +00:00
Jeff Hill
4a5cb2a6e5 assert.h => epicsAssert.h 1995-03-07 01:20:33 +00:00
Jeff Hill
9300dded40 sizeof A => sizeof(A) 1995-03-06 22:45:29 +00:00
Jeff Hill
cb86cd03a7 Compiler warnings fixed 1995-03-06 22:44:57 +00:00
Jeff Hill
cee91cb578 badd status map btw TScurrentTimeStamp() => tsLocalTime () fixed 1995-03-06 22:44:10 +00:00
Jeff Hill
679e1b8a56 added misssing includes 1995-03-06 22:43:19 +00:00
Jeff Hill
f6d91b8876 added missing includes 1995-03-06 22:42:55 +00:00
Jeff Hill
a86c813415 this time for sure 1995-03-06 22:42:03 +00:00
Jeff Hill
be2491bc51 created 1995-03-06 22:38:42 +00:00
Jeff Hill
1634c70c06 added assert stuff 1995-03-06 22:37:55 +00:00
Jeff Hill
df876abf50 fixed warning messages 1995-03-06 22:37:04 +00:00
Jeff Hill
d5873d5e8a add missing LOCAL 1995-03-06 22:35:49 +00:00
Jeff Hill
b6c87ce10e fetch time in one place only 1995-03-06 22:34:05 +00:00
Jeff Hill
00d40d3e73 debug stmnts 1995-03-06 22:33:37 +00:00
Jeff Hill
410e6d9c00 doc and clened up mux io 1995-03-06 22:32:33 +00:00
Jeff Hill
03944c94e3 cleaned up mux io 1995-03-06 22:32:07 +00:00
Jeff Hill
b5f31b4b13 doc and cleaned up mux io 1995-03-06 22:31:47 +00:00
Jeff Hill
7bb7e8a884 missing includes 1995-03-06 22:16:33 +00:00
Jeff Hill
d153387372 fix cast causes excess CPU consumption 1995-03-06 22:16:04 +00:00
Jeff Hill
d4a4b23a55 fetch time in only one place 1995-03-06 22:14:55 +00:00
Jeff Hill
14a152ba72 doc 1995-03-06 22:09:12 +00:00
Jeff Hill
20b6539144 fetch time only once 1995-03-06 22:08:41 +00:00
Jeff Hill
93b6da9b3c clean up 1995-03-06 22:07:34 +00:00
Jeff Hill
542c0115c5 de-lint 1995-03-06 22:06:53 +00:00
Jeff Hill
15440b9b6c Fetch current time in only one place 1995-03-06 22:06:21 +00:00
Jeff Hill
4cb9699c03 init conts var that will later be initialized by CA. 1995-03-06 21:53:23 +00:00
Jeff Hill
6460c2fc1d fetch time only once 1995-03-06 21:51:52 +00:00
Jeff Hill
9b858b8a5f better build for test codes 1995-03-06 21:46:25 +00:00
Ned Arnold
ed30327d93 added positioner readback arrays, PxRA. CHANGED scanRecord.ascii !!! Post monitor on .val at each point 1995-03-06 17:29:48 +00:00
John Winans
35aba51c7f Removed declaration of yylval. It caused problems for everyone and should
be defined by the yacc used to build parse.y anyway.
1995-03-06 17:15:11 +00:00
John Winans
12fd359a3c Forced antelope to compile under strict ANSI w/o any warnings. 1995-03-06 17:00:16 +00:00
Marty Kraimer
e0b6ce3867 tsLocalTime on vxWorks now returns S_ts_OK for success just like unix 1995-03-03 14:53:02 +00:00
Marty Kraimer
c5fce1bd6c Added callbackRequestProcessCallback 1995-03-03 14:50:06 +00:00
Janet B. Anderson
2dfbf28c1b Changed to += syntax 1995-03-02 19:21:09 +00:00
Janet B. Anderson
32add4c78f Changed to += syntax 1995-03-02 19:12:00 +00:00
Janet B. Anderson
9ea5c86ab5 changed to += syntax 1995-03-02 19:10:48 +00:00
Janet B. Anderson
48efca8456 Changes to += syntax 1995-03-02 18:53:37 +00:00
Janet B. Anderson
382c496b24 Changed to += syntax 1995-03-02 18:52:09 +00:00
Janet B. Anderson
13173544a9 Ansi c changes 1995-03-02 18:49:26 +00:00
Janet B. Anderson
19bf9ec448 Fixed call to inet_ntoa and added ifdef for free on HP 1995-03-01 19:43:56 +00:00
Ned Arnold
a08656090e Fixed bug in detecting a transition. Put .OVAL = .VAL statement at end of process() 1995-02-28 21:35:00 +00:00
Johnny Tang
7b03f77e30 to be compatible with select prototype on hp. 1995-02-28 00:57:23 +00:00
Johnny Tang
80dbdf6814 Adde LOCAL to register_new_client func. 1995-02-28 00:56:15 +00:00
Johnny Tang
103bd7492a added RF_IO data structure. 1995-02-28 00:51:55 +00:00
Marty Kraimer
e55693525c If on vxWorks add #include <vxWorks.h> 1995-02-27 15:36:56 +00:00
Marty Kraimer
64bd8e03dc Fixed COS task so it works for > 1 link. 1995-02-27 15:35:38 +00:00
Marty Kraimer
49b77d096f Add include #include <vxWorks.h> 1995-02-27 15:33:12 +00:00
Marty Kraimer
ae720e75af add include vxWorks.h 1995-02-27 15:29:55 +00:00
Marty Kraimer
bca7b39ab6 Fixed problem with adding,removing monitors 1995-02-24 19:06:05 +00:00
Ned Arnold
3600bb9513 Improved recWaitCaTask and associated record code 1995-02-24 16:52:51 +00:00
Matt Needes
339d08b71d Fixed locking error. OOPS. 1995-02-23 21:45:03 +00:00
Matt Needes
687e1a2c16 Fixed a comment. 1995-02-23 21:43:34 +00:00
Matt Needes
a53bffb128 Fixed some inaccuracies 1995-02-22 18:55:24 +00:00
Janet B. Anderson
4a7c1b1715 Added comments. 1995-02-21 17:53:22 +00:00
Janet B. Anderson
e75c3729b8 Fixed comment on #endif stmt 1995-02-21 17:52:42 +00:00
Janet B. Anderson
7cc6c1993d Fixed comments on #endif statements 1995-02-21 17:51:22 +00:00
Ned Arnold
63a3b6827c Added .RTST flag to (optionally) return the positioners to the start position after a scan 1995-02-21 17:10:10 +00:00
Ned Arnold
b1f570f66d Added queuing of input monitors (if IO_INTR scanned) so no transitions would be missed 1995-02-21 15:32:15 +00:00
cvs2svn
239e6cfa2e This commit was manufactured by cvs2svn to create tag 'R3.12.0-beta8'. 1995-02-18 01:51:39 +00:00
214 changed files with 63372 additions and 1982 deletions

20
README
View File

@@ -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.

View 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;

View File

@@ -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_\,\./\*#\[\]%: ;!|\'\-&\(\)@\?\+<>=\$]
%{

View File

@@ -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

View File

@@ -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) $<

View File

@@ -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) $<

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -19,11 +19,11 @@
*
*/
#include <assert.h>
#include <stdio.h>
#include <iocinf.h>
main()
{
ca_repeater();
assert(0);
ca_repeater ();
assert (0);
return (0);
}

View File

@@ -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;
}

View File

@@ -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(&current);
/*
* 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 (
&current,
&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 (
&current,
&ca_static->currentTime,
&piiu->timeAtEchoRequest);
stmo = delay > CA_RETRY_PERIOD;
delay = cac_time_diff (
&current,
&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 (
&current,
&ca_static->currentTime,
&piiu->timeAtEchoRequest);
if (delay > CA_ECHO_TIMEOUT) {
/*
@@ -144,10 +141,10 @@ void manage_conn(int silent)
}
else{
delay = cac_time_diff (
&current,
&ca_static->currentTime,
&piiu->timeAtLastRecv);
if (delay>ca_static->ca_connectTMO) {
echo_request(piiu, &current);
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 (
&current,
&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,
&current);
&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 (
&current,
&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(&currentTime);
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 (
&currentTime,
&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(&currentTime, &ca_delay);
next = cac_time_sum(&ca_static->currentTime, &ca_delay);
diff = cac_time_diff(
&ca_static->ca_conn_next_retry,

View File

@@ -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 *)&copyin;
pIEEE = (struct ieeedbl *)pNet;
pMIT = (struct mitdbl *) &copyin;
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 *)&copyin;
/*
* Use internal buffer so the src and dest ptr
* can be identical
*/
copyin = *pIEEE;
pIEEE = &copyin;
/*
* 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 */

View File

@@ -95,6 +95,5 @@ void flow_control(struct ioc_in_use *piiu)
}
UNLOCK;
return;
}

View File

@@ -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
*/

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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");

View File

@@ -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)

View File

@@ -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

View File

@@ -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++;

View File

@@ -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);
}

View File

@@ -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
}
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -62,7 +62,7 @@
* joh 21 080393 added task watch dog
*/
#include <assert.h>
#include <epicsAssert.h>
#include <vxWorks.h>
#include <types.h>

View File

@@ -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
View 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;
}
}

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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*/

View File

@@ -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);

View File

@@ -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
}
}

View File

@@ -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); }

View File

@@ -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

View File

@@ -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); }

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}

View File

@@ -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
View 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;
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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
View 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
View 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

View 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

File diff suppressed because it is too large Load Diff

91
src/drv/ansi/drvAb.h Normal file
View 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

File diff suppressed because it is too large Load Diff

94
src/drv/ansi/drvAt5Vxi.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

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
View 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
View 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
View 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;
}

View 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

File diff suppressed because it is too large Load Diff

484
src/drv/ansi/drvKscV215.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}

View File

@@ -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;
}
}
}

View File

@@ -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
View 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
View 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

View 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

File diff suppressed because it is too large Load Diff

348
src/drv/old/drvAbOLD.h Normal file
View 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

File diff suppressed because it is too large Load Diff

93
src/drv/old/drvAt5Vxi.h Normal file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

306
src/drv/old/drvBitBus.h Normal file
View 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
View 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
View 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