Seperated drv files into ansi and old dirs. Added combine dir.

This commit is contained in:
Janet B. Anderson
1995-03-30 19:36:44 +00:00
parent 2c1004fb41
commit 96f58790c4
62 changed files with 38494 additions and 6 deletions
+3 -6
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
+12
View File
@@ -0,0 +1,12 @@
#
# $Id$
#
#
#
EPICS=../../../..
include $(EPICS)/config/CONFIG_BASE
include $(EPICS)/config/RULES_ARCHS
+18
View File
@@ -0,0 +1,18 @@
#
# $Id$
#
EPICS = ../../../../..
include Target.include
include $(EPICS)/config/CONFIG_BASE
USR_CFLAGS = -ansi
VX_WARN_YES = -Wall -pedantic
SRCS.c += ../drvAb.c
TARGETS += drvAb.o
include $(EPICS)/config/RULES.Vx
+1714
View File
File diff suppressed because it is too large Load Diff
+87
View File
@@ -0,0 +1,87 @@
/* 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,abLinkDown,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);
}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*/
+10
View File
@@ -0,0 +1,10 @@
#
# $Id$
#
EPICS=../../../..
include $(EPICS)/config/CONFIG_BASE
include $(EPICS)/config/RULES_ARCHS
+80
View File
@@ -0,0 +1,80 @@
#
# $Id$
#
EPICS = ../../../../..
include Target.include
include $(EPICS)/config/CONFIG_BASE
USR_CFLAGS = -fshared-data -fvolatile -mnobitfield -traditional
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
TARGETS += module_types.o
# TARGETS += drvAb.o
TARGETS += drvAt5Vxi.o
TARGETS += drvBB232.o
TARGETS += drvBb902.o
TARGETS += drvBb910.o
TARGETS += drvBitBus.o
# TARGETS += drvCaenV265.o
TARGETS += drvComet.o
TARGETS += drvCompuSm.o
TARGETS += drvDvx.o
TARGETS += drvEpvxi.o
TARGETS += drvEpvxiMsg.o
TARGETS += drvFp.o
TARGETS += drvFpm.o
TARGETS += drvGpib.o
TARGETS += drvHp1404a.o
TARGETS += drvHpe1368a.o
TARGETS += drvHpe1445a.o
TARGETS += drvJgvtr1.o
TARGETS += drvKscV215.o
TARGETS += drvMsg.o
TARGETS += drvMz8310.o
TARGETS += drvOms.o
TARGETS += drvStc.o
TARGETS += drvTime.o
# TARGETS += drvTranServ.o
TARGETS += drvVmi4100.o
TARGETS += drvXy010.o
TARGETS += drvXy210.o
TARGETS += drvXy220.o
TARGETS += drvXy240.o
TARGETS += drvXy566.o
include $(EPICS)/config/RULES.Vx
+30
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.
File diff suppressed because it is too large Load Diff
+348
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 */
};
File diff suppressed because it is too large Load Diff
+93
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
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
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
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
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);
}
}
}
}
}
}
File diff suppressed because it is too large Load Diff
+306
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
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
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);
}
+972
View File
@@ -0,0 +1,972 @@
/* drvCompuSm.c */
/* base/src/drv $Id$ */
/*
* subroutines and tasks that are used to interface to the Compumotor 1830
* stepper motor drivers
*
* Author: Bob Dalesio
* Date: 01-03-90
*
* 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-07-90 lrd add command to read the motor status
* .02 04-11-90 lrd made velocity mode motor go active
* .03 04-12-90 lrd only allow one connection to a motor
* .04 04-13-90 lrd add externally initiated motor motion monitoring
* .05 09-05-91 joh updated for v5 vxWorks
* .06 10-09-91 lrd monitor for external motion once every 2 seconds
* not at 30 Hz (.04 was not implemented correctly)
* .06 11-31-91 bg added compu_sm_io_report. Added sysBusToLocalAdrs()
* for addressing.
* .07 03-02-92 bg added level and ability to print raw values to
* compu_sm_io_report for level > 0.
* .08 05-04-92 bg added compu_sm_reset and rebootHookAdd so ioc can be
* rebooted with control X.
* .09 06-25-92 bg Combined drvCompuSm.c and compu_sm_driver.c
* .10 06-26-92 bg Added level to compu_sm_io_report in drvCompuSm
* structure
* .11 06-29-92 joh took file ptr arg out of io report
* .12 08-06-92 joh merged compu sm include file
* .13 08-27-92 joh silenced ANSI C function proto warning
* .14 08-27-92 joh fixed no epics init
* .15 08-02-93 mrk Added call to taskwdInsert
* .16 10-29-93 jba Fixed max number of cards to use module_types.c
* Fixed error in calculating card addresses
*/
#include <vxWorks.h>
#include <vme.h>
#include <sysLib.h>
#include <semLib.h> /* library for semaphore support */
#include <wdLib.h>
#include <rngLib.h> /* library for ring buffer support */
/* drvCompuSm.c - Driver Support Routines for CompuSm */
#include <dbDefs.h>
#include <drvSup.h>
#include <module_types.h>
#include <steppermotor.h>
#include <task_params.h>
#include <taskwd.h>
long compu_sm_io_report();
long compu_driver_init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvCompuSm={
2,
compu_sm_io_report,
compu_driver_init};
/* compumotor vme interface information */
#define MAX_COMPU_MOTORS 8
#define RESP_SZ 16 /* card returns 16 chars - cmd & resp */
#define RESPBUF_SZ (RESP_SZ+1) /* intr routine also passes motor no. */
/* Control Byte bit definitions for the Compumotor 1830 */
/* bits 0 and 1 are not used */
#define CBEND 0x04 /* end of command string */
#define CBLMR 0x08 /* last message byte read */
#define CBCR 0x10 /* command ready in cm_idb */
#define CBMA 0x20 /* message accepted from odb */
#define CBEI 0x40 /* enable interrupts */
#define CBBR 0x80 /* board reset */
#define SND_MORE CBCR | CBEI /* more chars to send */
#define SND_LAST CBEND | SND_MORE /* last char being sent */
#define RD_MORE CBMA | CBEI /* more chars to read */
#define RD_LAST CBLMR | RD_MORE /* last byte we need to read */
/* Status Byte bit definitions */
#define SBIRDY 0x10 /* idb is ready */
/* Structure used for communication with a Compumotor 1830
** Motor Controller. The data buffer is repeated 64 times
** on even word addresses (0xXXXXXX1,0xXXXXX5...) and the
** control location is repeated 64 times on odd word
** addresses (0xXXXXX3, 0xXXXXX7...). The registers must
** be read and written as bytes.
*/
struct compumotor {
char cm_d1; /* not accessable */
char cm_idb; /* input data buffer */
char cm_d2; /* not accessable */
char cm_cb; /* control byte */
char cm_d3[0x100-4]; /* fill to next standard address */
};
/* This file includes defines for all compumotor 1830 controller
** commands. */
#define SM_NULL 0x0 /* Null command */
#define SM_INT 0x1 /* Interrupt X */
#define SM_WRT_STAT 0x8 /* Write X to the user defined status bits */
#define SM_SET_STAT 0x9 /* Set user defined status bit number X */
#define SM_CLR_STAT 0xa /* Clear user defined status bit number X */
#define SM_SET_PROG 0xb /* Set programmable output bit X */
#define SM_CLR_PROG 0xc /* Clear programmable output bit X */
#define SM_WRT_PROG 0xd /* Write X to the programmable output bits */
#define SM_DEF_X_TO_Y 0xf /* Define bit X to indicate state Y */
#define SM_TOG_JOG 0x10 /* Disable/enable the JOG inputs */
#define SM_DEF_JOG 0x11 /* Define JOG input functions */
#define SM_TOG_REM_PWR 0x12 /* Turn off/on remote power shutdown */
#define SM_TOG_REM_SHUT 0x13 /* Disable/enable the "remote shutdown" bit */
#define SM_SET_CW_MOTN 0x14 /* Set CW motion equal to +- */
#define SM_TOG_POS_MTN 0x18 /* Turn off/on post-move position maintenance */
#define SM_TOG_STOP_STL 0x19 /* Turn off/on termination on stall detect */
#define SM_REP_X_Y 0x20 /* Repeat the following X commands Y times */
#define SM_REP_TIL_CONT 0x21 /* Repeat the following X commands
until a CONTINUE is received */
#define SM_WAIT_CONT 0x28 /* Wait for a CONTINUE */
#define SM_WAIT_MILLI 0x29 /* Wait X milliseconds */
#define SM_WAIT_SECOND 0x2a /* Wait X seconds */
#define SM_WAIT_MINUTE 0x2b /* Wait X minutes */
#define SM_WAIT_TRIGGER 0x2c /* Wait for trigger X to go active */
#define SM_DEF_A_OP_POS 0x2e /* Define the abs open-loop position as X */
#define SM_DEF_A_CL_POS 0x2f /* Define absolute closed-loop position */
#define SM_DEF_ABS_ZERO 0x30 /* Define the present position as the
absolute zero position */
#define SM_DEF_VEL_ACC 0x31 /* Define default velocity and acceleration */
#define SM_MOV_DEFAULT 0x32 /* Perform the default move (trapezoidal
continuous) */
#define SM_MOV_REL_POS 0x33 /* Go to relative position X at default
velocity and acceleration */
#define SM_MOV_ABS_POS 0x34 /* Go to absolute position X at default
velocity and acceleration */
#define SM_MOV_REL_ENC 0x35 /* Go to relative encoder position X */
#define SM_MOV_ABS_ENC 0x36 /* Go to absolute encoder position X */
#define SM_DEF_OP_HOME 0x38 /* Define HOME location (open loop */
#define SM_DEF_CL_HOME 0x38 /* Define HOME location (closed loop) */
#define SM_MOV_HOME_POS 0x39 /* Go HOME at the default velocity and
acceleration */
#define SM_MOV_HOME_ENC 0x3a /* Go to encoder HOME at the default
velocity and acceleration */
#define SM_DO_MOV_X 0x40 /* Perform move number X */
#define SM_DO_SEQ_X 0x41 /* Perform sequence buffer X */
#define SM_DO_VEL_STR 0x42 /* Perform the velocity streaming buffer */
#define SM_CONT 0x48 /* CONTINUE (perform next command) */
#define SM_OP_LOOP_MODE 0x50 /* Enter open loop indexer mode */
#define SM_VEL_DIS_MODE 0x51 /* Enter velocity-distance streaming mode */
#define SM_VEL_TIM_MODE 0x52 /* Enter velocity-time streaming mode */
#define SM_STOP 0x70 /* STOP motion */
#define SM_DSC_SEQ 0x71 /* Discontinue the sequence buffer */
#define SM_SSP_SEQ 0x72 /* Suspend the sequence buffer;
wait for a CONTINUE to resume */
#define SM_DSC_SNGL 0x73 /* Discontinue any singular command
currently being performed */
#define SM_STOP_ON_TRG 0x74 /* STOP motion when trigger X goes active */
#define SM_DSC_SEQ_TRG 0x75 /* Discontinue the sequence buffer when
trigger X goes active */
#define SM_SSP_SEQ_TRG 0x76 /* Suspend sequence buffer when trigger
X goes active */
#define SM_DSC_SNGL_TRG 0x77 /* Discontinue any singular command when
trigger X goes active */
#define SM_KILL 0x78 /* Kill motion */
#define SM_KILL_SEQ 0x79 /* Kill the sequence buffer */
#define SM_KILL_SEQ_SNGL 0x7a /* Kill current sequence singular command;
wait for CONTINUE */
#define SM_KILL_VEL_STR 0x7b /* Kill the velocity streaming buffer */
#define SM_KILL_ON_TRG 0x7c /* Kill motion when trigger X goes active */
#define SM_KILL_SEQ_TRG 0x7d /* Kill the sequence buffer when trigger
X goes active */
#define SM_KL_SQSNG_TRG 0x7e /* Kill current sequence singular command
when trigger X goes active; wait for
a continue */
#define SM_KL_VLSTR_TRG 0x7f /* Kill the velocity streaming buffer
when trigger X goes active */
#define SM_GET_B_REL_POS 0x80 /* Request position relative to the
beginning of the current move */
#define SM_GET_E_REL_POS 0x81 /* Request position relative to the
end of the current move */
#define SM_GET_H_REL_POS 0x82 /* Request position relative to the home
limit switch */
#define SM_GET_Z_REL_POS 0x83 /* Request position relative to the
absolute zero position */
#define SM_GET_CUR_DIR 0x84 /* Request current direction */
#define SM_GET_VEL 0x85 /* Request current velocity */
#define SM_GET_ACC 0x86 /* Request current acceleration */
#define SM_GET_MOV_STAT 0x88 /* Request current move status */
#define SM_GET_LIM_STAT 0x89 /* Request state of the limit switches */
#define SM_GET_HOME_STAT 0x8a /* Request state of the HOME switch */
#define SM_GET_TRV_DIR 0x8b /* Request direction of travel */
#define SM_GET_MOT_MOV 0x8c /* Request whether motor is moving or not */
#define SM_GET_MOT_CONST 0x8d /* Request whether motor is at constant,
nonzero velocity or not */
#define SM_GET_MOT_ACC 0x8e /* Request whether motor is or is not
accelerating */
#define SM_GET_MOT_DEC 0x8f /* Request whether motor is or is not
decelerating */
#define SM_GET_MODE 0x90 /* Request present mode */
#define SM_GET_MV_PARM 0x91 /* Request move parameters for move number X */
#define SM_GET_SEQ_CMMD 0x92 /* request commands stored in the
sequence buffer */
#define SM_GET_MVDEF_STAT 0x93 /* Request state of the move definitions */
#define SM_GET_TRG_STAT 0x94 /* Request state of trigger inputs */
#define SM_GET_JOG_STAT 0x95 /* Request state of JOG inputs */
#define SM_GET_Z_STAT 0x96 /* Request state of the Channel Z home input */
#define SM_GET_OUT_STAT 0x97 /* Request the state of the programmable
output bits */
#define SM_GET_REL_ENC 0x98 /* Request relative encoder count */
#define SM_GET_REL_ERR 0x99 /* Request relative error from desired
closed loop position */
#define SM_GET_ABS_ENC 0x9a /* Request absolute encoder count */
#define SM_GET_SLIP_STAT 0x9b /* Request slip detect status */
#define SM_GET_RATIO 0x9c /* Request motor pulse to encoder pulse ratio */
#define SM_GET_RESOLTN 0x9d /* Request motor resolution */
#define SM_GET_BACK_SIG 0x9e /* Request backlash sigma (motor steps)*/
#define SM_GET_ALG 0x9f /* Request position maintenance alg.
const, and max velocity */
#define SM_INT_NXT_MOV 0xa0 /* Interrupt at start of next move */
#define SM_INT_ALL_MOV 0xa1 /* Interrupt at the start of every move */
#define SM_INT_NXT_NZ 0xa2 /* Interrupt at constant nonzero velocity
of next move */
#define SM_INT_ALL_NZ 0xa3 /* Interrupt at constant nonzero velocity
of every move */
#define SM_INT_NXT_END 0xa4 /* Interrupt at next end of motion */
#define SM_INT_ALL_END 0xa5 /* Interrupt at every end of motion */
#define SM_INT_NXT_STL 0xa6 /* Interrupt on next stall detect */
#define SM_INT_ALL_STL 0xa7 /* Interrupt on every stall detect */
#define SM_INT_NXT_PLIM 0xa8 /* Interrupt the next time the motor
hits the positive limit */
#define SM_INT_ALL_PLIM 0xa9 /* Interrupt on every positive limit */
#define SM_INT_NXT_NLIM 0xaa /* Interrupt the next time the motor
hits the negative limit */
#define SM_INT_ALL_NLIM 0xab /* Interrupt on every negative limit */
#define SM_INT_TRG 0xac /* Interrupt on trigger X active */
#define SM_INT_INHBT 0xaf /* Inhibit all interrupts */
#define SM_DEF_RATIO 0xb0 /* Define motor pulse to encoder pulse ratio */
#define SM_DEF_RESOLTN 0xb1 /* Define motor resolution */
#define SM_DEF_BACK_SIG 0xb2 /* Define backlash sigma (motor steps)*/
#define SM_DEF_ALG 0xb3 /* Define position maintenance algorithm
const, and max velocity */
#define SM_DEF_TEETH 0xb4 /* Define the number of rotor teeth */
#define SM_DEF_DEADBAND 0xb5 /* Def the deadband region in encoder pulses */
#define SM_DEF_REL_TRP 0xc8 /* Define move X as a relative,
trapezoidal move */
#define SM_DEF_ABS_TRP 0xcb /* Define move X as an absolute
trapezoidal move */
#define SM_DEF_CONT 0xce /* Define move X as a continuous move */
#define SM_DEF_REL_CL 0xd4 /* Define move X, define it as relative,
closed-loop move */
#define SM_DEF_ABS_CL 0xd5 /* Def move X as an abs, closed- loop move */
#define SM_DEF_STSTP_VEL 0xd6 /* Define the start/stop velocity */
#define SM_DEL_MOV_X 0xd7 /* Delete move X */
#define SM_END_SEQ_DEF 0xd8 /* End definition of sequence buffer */
#define SM_BEG_SEQ_DEF 0xd9 /* Begin definition of sequence buffer */
#define SM_DEL_SEQ_X 0xda /* Delete sequence buffer X */
#define SM_LD_VD_DATA 0xe0 /* Place data into the velocity-distance buffer */
#define SM_LD_VT_DATA 0xe1 /* Place data into the velocity-time buffer */
#define SM_GET_FREE_BYT 0xe2 /* Request number of free bytes in vel-
streaming/sequence buffer */
#define SM_DEF_VS_CMMD 0xee /* Define command to be executed during
the velocity streaming buffer */
#define SM_GET_NUM_REV 0xfd /* Request software part number and revision */
#define SM_TEST_SWITCH 0xff /* Perform the test switch function */
#define VELOCITY_MODE 0
#define MAX_COMMANDS 256
#define COMPU_INT_LEVEL 5
/* array of pointers to stepper motor driver cards present in system */
struct compumotor *pcompu_motors[MAX_COMPU_MOTORS];
LOCAL SEM_ID compu_wakeup; /* compumotor data request task semaphore */
/* response variables */
LOCAL SEM_ID smRespSem; /* task semaphore */
LOCAL RING_ID smRespQ; /* ring buffer */
int smRespId; /* task id */
#define RESP_Q_SZ (RESPBUF_SZ * 50) /* response ring buffer size */
/* interrupt buffers */
unsigned char sm_responses[MAX_COMPU_MOTORS][RESPBUF_SZ];
unsigned short counts[MAX_COMPU_MOTORS];
/* VME memory Short Address Space is set up in gta_init */
static int *compu_addr;
/* motor information */
struct compu_motor{
short active; /* flag to tell the oms_task if the motor is moving */
int callback; /* routine in database library to call with status */
int callback_arg; /* argument to callback routine */
short update_count;
short mode;
short motor_resolution;
};
struct compu_motor compu_motor_array[MAX_COMPU_MOTORS];
/* Forward reference. */
VOID compu_sm_reset();
VOID compu_sm_stat();
/* motor status - returned to the database library routines */
struct motor_data compu_motor_data_array[MAX_COMPU_MOTORS];
/* moving status bit descriptions */
#define CW_LIMIT 0x01 /* clockwise???? limit */
#define CCW_LIMIT 0x02 /* counter-clockwise???? limit */
#define DIRECTION 0x08 /* direction bit */
#define MOVING 0x10 /* moving status bit */
#define CONSTANT_VEL 0x20 /* constant velocity */
/* directions in driver card-ese */
#define CLKW 0 /* clockwise direction */
#define CCLKW 1 /* counter clockwise direction */
/*
* Code Portions:
*
* smCmdTask Task which writes commands to the hardware
* smRespTask Task which places reponses from the hardware into resp buffers
* sm_intr Interrupt Handler - collects response data from the hardware
* sm_drv_init Initializes all motors, semaphores, ring buffers and interrupts
* sm_driver Subroutine for outside world to issue commands to motors
* motor_select Subroutine to setting callback arg and verifying no other user
* motor_deselect Subroutine to free the motor for other users
*
* Interaction Chart:
* -------------- -------------------
* / \ / \
* | smRespTask | | smCmdTask |
* \ / \ /
* --------------- -------------------
* ^ ^ |
* TAKES | | GETS |
* | | |
* -------------- --------------- |
* Resp Semaphore Response Queue |
* -------------- --------------- |
* ^ ^ |
* GIVES | | PUTS |
* | | |
* --------------- |
* / \ |
* | sm_intr | |
* \ / |
* --------------- |
* ^ reads responses writes commands |
* | from hardware to hardware V
*/
/*
* COMPU_RESP_TASK
*
* converts readback from the compumotor 1830 cards into a structure that
* is returned to the database library layer every .1 second while a motor
* is moving
*/
compu_resp_task()
{
unsigned char resp[RESPBUF_SZ];
register short i;
register struct motor_data *pmotor_data;
FOREVER {
/* wait for somebody to wake us up */
semTake (smRespSem, WAIT_FOREVER);
/* the response buffer contains: */
/* 0 - motor number */
/* 1 - the command which solicited this response */
/* 2 - the first byte of the response */
/* process requests in the command ring buffer */
while (rngBufGet(smRespQ,(char *)resp,RESPBUF_SZ) == RESPBUF_SZ){
pmotor_data = &compu_motor_data_array[resp[0]];
/* convert argument */
switch(resp[1]){
case (SM_GET_VEL):
{
register long *pvelocity = (long *)(&resp[3]);
pmotor_data->velocity = *pvelocity;
break;
}
case (SM_GET_MOV_STAT):
{
register struct compu_motor *pcompu_motor;
register int (*psmcb_routine)();
pcompu_motor = &compu_motor_array[resp[0]];
pmotor_data->moving = (resp[2] & MOVING)?1:0;
pmotor_data->constant_velocity = (resp[2] & CONSTANT_VEL)?1:0;
pmotor_data->cw_limit = (resp[2] & CW_LIMIT)?1:0;
pmotor_data->ccw_limit = (resp[2] & CCW_LIMIT)?1:0;
pmotor_data->direction = (resp[2] & DIRECTION)?1:0;
/* post every .1 second or not moving */
if ((pcompu_motor->update_count-- <= 0)
|| (pmotor_data->moving == 0)){
if (pcompu_motor->callback != 0){
(int)psmcb_routine = pcompu_motor->callback;
(*psmcb_routine)(pmotor_data,pcompu_motor->callback_arg);
}
if (pmotor_data->moving){
/* motors are reported at 10 Hz */
pcompu_motor->update_count = 3;
}else{
pcompu_motor->active = FALSE;
pcompu_motor->update_count = 0;
}
}
break;
}
case (SM_GET_ABS_ENC):
{
register long *pencoder = (long *)(&resp[2]);
pmotor_data->encoder_position = *pencoder;
break;
}
case (SM_GET_Z_REL_POS):
{
register long *pmotor = (long *)(&resp[4]);
pmotor_data->motor_position = *pmotor;
break;
}
case (SM_GET_CUR_DIR):
pmotor_data->direction = (resp[2] == 0xff)?CLKW:CCLKW;
break;
}
}
}
}
/* Data request commands for the positional and velocity mode motors */
char compu_velo_reqs[] = { SM_GET_VEL, SM_GET_MOV_STAT };
#define NUM_VEL_REQS 2
char compu_pos_reqs[] = { SM_GET_ABS_ENC, SM_GET_Z_REL_POS, SM_GET_MOV_STAT };
#define NUM_POS_REQS 3
/*
* COMPU_TASK
*
* task to solicit currnet status from the compumotor 1830 cards while they
* are active
*/
compu_task()
{
register short inactive_count;
register short card;
register short i;
register struct compumotor *pmotor;
register char *preqs;
/* inactive motors get monitored once every 2 seconds in case they are */
/* being moved manually */
inactive_count = 60;
while(1){
/* This task is run 30 times a second */
taskDelay(2);
for (card = 0; card < sm_num_cards[CM57_83E]; card++){
pmotor = pcompu_motors[card];
if (pmotor == 0) continue;
if ((compu_motor_array[card].active)
|| (inactive_count <=0)){
if (compu_motor_array[card].mode == VELOCITY_MODE){
preqs = &compu_velo_reqs[0];
/* request status data */
for (i = 0; i < NUM_VEL_REQS; i++,preqs++)
compu_send_msg(pmotor,preqs,1);
}else{
preqs = &compu_pos_reqs[0];
/* request status data */
for (i = 0; i < NUM_POS_REQS; i++,preqs++)
compu_send_msg(pmotor,preqs,1);
}
}
}
if (--inactive_count < 0) inactive_count = 60;
}
}
/*
* COMPU_INTR
*
* interrupt vector for the compumotor 1830 card
*/
compu_intr(mdnum)
register int mdnum;
{
register struct compumotor *pmtr; /* memory port to motor card */
register int key;
key = intLock();
/* pointer to the compumotor card interface */
pmtr = pcompu_motors[mdnum];
/* place the response byte into the appropriate response buffer */
sm_responses[mdnum][counts[mdnum]] = pmtr->cm_idb;
counts[mdnum]++;
/* when the buffer is full pass it onto the repsonse task */
if (counts[mdnum] == RESPBUF_SZ){
if (rngBufPut(smRespQ,(char *)sm_responses[mdnum],RESPBUF_SZ) != RESPBUF_SZ)
logMsg("smRespQ %d - Full\n",mdnum);
else
semGive (smRespSem);
/* the zero-th byte is the motor number */
counts[mdnum] = 1; /* start with command */
/* inform the hardware that the response is complete */
pmtr->cm_cb = RD_LAST;
}else{
/* inform the hardware there is more to send */
pmtr->cm_cb = RD_MORE;
}
intUnlock(key);
}
/*
* COMPU_DRIVER_INIT
*
* initialization for the compumotor 1830 card
*/
long
compu_driver_init(){
register short i;
int status;
struct compumotor *pmtr; /* memory port to motor card */
int cok = CBBR; /*to reset board */
short none_found; /* flags a steppermotor is present */
int taskId;
struct compumotor *pmtrb;
/* intialize each driver which is present */
none_found = TRUE;
rebootHookAdd((FUNCPTR)compu_sm_reset);
status = sysBusToLocalAdrs(
VME_AM_SUP_SHORT_IO,
sm_addrs[CM57_83E],
(int **)&compu_addr);
if (status != OK){
printf("%s: failed to map A16 base\n", __FILE__);
return ERROR;
}
pmtrb = (struct compumotor *)compu_addr;
for (i = 0; i < sm_num_cards[CM57_83E]; i++) {
pmtr = (struct compumotor *)((int)pmtrb + (i<<8));
/* initialize when card is present */
if (vxMemProbe(&pmtr->cm_cb,WRITE,1,&cok) != ERROR){
none_found = FALSE;
pcompu_motors[i] = pmtr; /* ptr to interface */
intConnect((MD_INT_BASE+i)*4,compu_intr,i); /* interrupt enable */
sysIntEnable(COMPU_INT_LEVEL);
/* init interrupt receive buffers */
sm_responses[i][0] = i; /* motor number */
counts[i] = 1; /* buffer index */
}else{
pcompu_motors[i] = 0; /* flags no board is present */
}
}
if (none_found) return(0);
/* initialize the response task ring buffer */
if ((smRespQ = rngCreate(RESP_Q_SZ)) == (RING_ID)NULL)
panic ("sm_init: cmRespQ\n");
/* intialize the semaphores which awakens the sleeping *
* stepper motor command task and the stepper motor response task */
if(!(smRespSem=semBCreate(SEM_Q_FIFO,SEM_EMPTY)))
errMessage(0,"semBcreate failed in compu_driver_init");
if(!(compu_wakeup=semBCreate(SEM_Q_FIFO,SEM_EMPTY)))
errMessage(0,"semBcreate failed in compu_driver_init");
/* spawn the sleeping motor driver command and response tasks */
smRespId =
taskSpawn("compu_resp_task",SMRESP_PRI,SMRESP_OPT,SMRESP_STACK,compu_resp_task);
taskwdInsert(smRespId,NULL,NULL);
taskId = taskSpawn("compu_task",SMRESP_PRI,SMRESP_OPT,2000,compu_task);
taskwdInsert(taskId,NULL,NULL);
return(0);
}
short trigger = 0;
/*
* COMPU_DRIVER
*
* driver interface to the database library layer
*/
compu_driver(card,value_flag,arg1,arg2)
register short card;
short value_flag;
register int arg1;
register int arg2;
{
register int *pint;
register short *pshort;
short j,i;
char compu_msg[20];
/* verify the stepper motor driver card is present */
if ((card < 0) || (card > sm_num_cards[CM57_83E]) || (!pcompu_motors[card]))
return (-1);
switch (value_flag){
case (SM_MODE):
/* set the motor mode */
compu_motor_array[card].mode = arg1;
break;
case (SM_VELOCITY):
compu_motor_data_array[card].velocity = arg1;
compu_motor_data_array[card].accel = arg2;
/* set the velocity */
compu_msg[0] = SM_DEF_VEL_ACC;
compu_msg[1] = 0; /* time is in seconds */
compu_msg[2] = 0;
pint = (int *)&compu_msg[3]; /* velocity */
*pint = arg1;
pint++; /* acceleration */
*pint = arg2;
compu_send_msg(pcompu_motors[card],compu_msg,11);
break;
case (SM_MOVE):
if (compu_motor_array[card].mode == VELOCITY_MODE)
return(0);
i = 0;
switch (trigger){
case (0):
/* move the motor */
compu_msg[i++] = SM_MOV_REL_POS;
pint = (int *)&compu_msg[i];
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
case (1): /* test sequnce buffer */
compu_msg[i++] = 0xda; /* delete sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd9; /* fill sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = SM_MOV_REL_POS;
pint = (int *)&compu_msg[i];
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd8; /* end sequence buffer */
compu_msg[i++] = 0x41; /* perform sequence buffer */
compu_msg[i++] = 0x01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
case (2): /* test move buffer */
compu_msg[i++] = 0xc8;
compu_msg[i++] = 0x12;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x04;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x04;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
pint = (int *)&compu_msg[i];
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x40;
compu_msg[i++] = 0x12;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
case (3): /* test sequence buffer with move buffer */
compu_msg[i++] = 0xc8;
compu_msg[i++] = 0x12;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x04;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x04;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
pint = (int *)&compu_msg[i];
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xda; /* delete sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd9; /* fill sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x40;
compu_msg[i++] = 0x12;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd8; /* end sequence buffer */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x41; /* perform sequence buffer */
compu_msg[i++] = 0x01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
case (4): /* test sequence buffer with move buffer and trigger */
compu_msg[i++] = 0xc8;
compu_msg[i++] = 0x12;
compu_msg[i++] = 0x00;
pint = (int *)&compu_msg[i];
*pint = compu_motor_data_array[card].velocity;
i += 4;
pint++;
*pint = compu_motor_data_array[card].accel;
i += 4;
pint++;
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xda; /* delete sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd9; /* fill sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x2c; /* wait for trigger */
compu_msg[i++] = 1; /*trigger 1 */
compu_msg[i++] = 1; /* don't care about state */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x40;
compu_msg[i++] = 0x12;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd8; /* end sequence buffer */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x41; /* perform sequence buffer */
compu_msg[i++] = 0x01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
}
for (j = 0; j < i; j++){
printf("%x ",compu_msg[j]);
}
/* compu_send_msg(pcompu_motors[card],compu_msg,i);
*/
/* set the motor to active */
compu_motor_array[card].active = TRUE;
/* wakeup the compu task */
semGive(compu_wakeup);
break;
case (SM_MOTION):
if (arg1 == 0){
compu_msg[0] = SM_STOP;
compu_send_msg(pcompu_motors[card],compu_msg,1);
}else if (compu_motor_array[card].mode == VELOCITY_MODE){
compu_msg[0] = SM_MOV_DEFAULT;
compu_msg[1] = arg2; /* direction */
compu_send_msg(pcompu_motors[card],compu_msg,2);
compu_motor_array[card].active = TRUE;
}
/* wakeup the compu task */
semGive(compu_wakeup);
break;
case (SM_CALLBACK):
/* put the callback routine and argument into the data array */
i = 0;
if (compu_motor_array[card].callback != 0) return(-1);
compu_motor_array[card].callback = arg1;
compu_motor_array[card].callback_arg = arg2;
break;
case (SM_SET_HOME):
if (compu_motor_array[card].mode == VELOCITY_MODE)
return(OK);
/* set the motor and encoder position to zero */
compu_msg[0] = SM_DEF_ABS_ZERO;
compu_send_msg(pcompu_motors[card],compu_msg,1);
break;
case (SM_ENCODER_RATIO):
compu_motor_array[card].motor_resolution = arg1;
/* set the encoder ratio */
compu_msg[0] = SM_DEF_RATIO;
pshort = (short *)&compu_msg[1];
*pshort = arg1; /* motor resolution */
pshort++;
*pshort = arg2; /* encoder resolution */
compu_send_msg(pcompu_motors[card],compu_msg,5);
/* set the motor resolution */
compu_msg[0] = SM_DEF_RESOLTN;
pshort = (short *)&compu_msg[1];
*pshort = 0;
pshort++;
*pshort = arg1; /* motor resolution */
compu_send_msg(pcompu_motors[card],compu_msg,5);
break;
case (SM_READ):
/* set the motor to active */
compu_motor_array[card].active = TRUE;
/* wakeup the compu task */
semGive(compu_wakeup);
break;
}
return (OK);
}
/*
* COMPU_SEND_MSG
*
* send a message to the compumotor 1830
*/
int wait_count;
compu_send_msg(pmotor,pmsg,count)
register struct compumotor *pmotor;
register char *pmsg;
register short count;
{
/* write out this command one byte at a time */
while (count){
/* wait for the driver to be ready */
while ((pmotor->cm_cb & SBIRDY) == 0){
taskDelay(0);
wait_count++;
}
/* next byte in the input data buffer of compumotor */
pmotor->cm_idb = *pmsg;
pmsg++;
count--;
/* tell compumotor more or complete */
if (count == 0){
pmotor->cm_cb = SND_LAST;
}else{
pmotor->cm_cb = SND_MORE;
}
}
}
/*
* COMPU_SM_IO_REPORT
*
* send a message to the compumotor 1830
*/
long compu_sm_io_report(level)
short int level;
{
register int i;
for (i = 0; i < sm_num_cards[CM57_83E]; i++){
if (pcompu_motors[i]){
printf("SM: CM1830: card %d\n",i);
if (level > 0)
compu_sm_stat(i);
}
}
return OK;
}
VOID compu_sm_stat(compu_num)
short int compu_num;
{
struct motor_data *pmotor_data;
printf("\tCW limit = %d\t,CCW limit = %d\tMoving = %d\tDirection = %d\n",
compu_motor_data_array[compu_num].cw_limit,
compu_motor_data_array[compu_num].ccw_limit,
compu_motor_data_array[compu_num].moving,
compu_motor_data_array[compu_num].direction);
printf("\tConstant Velocity = %d\t, Velocity = %d\t \n",
compu_motor_data_array[compu_num].constant_velocity,
compu_motor_data_array[compu_num].velocity);
printf("\tAcceleration = %d\tEncoder Position = %d\tMotor Position = %d\n",
compu_motor_data_array[compu_num].accel,
compu_motor_data_array[compu_num].encoder_position,
compu_motor_data_array[compu_num].motor_position);
}
/*
*
* Subroutine to be called during a CTL X reboot. Inhibits interrupts.
*
*/
VOID compu_sm_reset()
{
short int i;
char compu_msg[20];
for (i = 0; i < sm_num_cards[CM57_83E]; i++){
if (pcompu_motors[i]){
compu_msg[0] = SM_INT_INHBT;
compu_send_msg(pcompu_motors[i],compu_msg,1);
}
}
}
+1408
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+237
View File
@@ -0,0 +1,237 @@
/* base/src/drv $Id$ */
/*
* Author: John Winans
* Date: 09-09-92
*
* Skeleton VXI driver module.
*
* 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-09-92 jrw written
* .02 08-24-93 joh updated for EPICS format return codes
* .03 08-24-93 joh converted to ANSI C
* .04 08-24-93 joh ran through -Wall
*
*/
#include <vxWorks.h>
#include <stdioLib.h>
#include <rebootLib.h>
#include <drvEpvxi.h>
#include <drvSup.h>
#include <devLib.h>
typedef long exVxiStat;
exVxiStat vti(int make, int model);
LOCAL exVxiStat example_init(void);
LOCAL void example_stat(unsigned card, int level);
LOCAL void example_init_card(unsigned addr);
LOCAL int example_shutdown(void);
LOCAL void example_shutdown_card(unsigned la);
struct drvet drvExample={
2,
NULL, /* VXI I/O report takes care of this */
example_init
};
static unsigned long exampleDriverID; /* ID used to identify this driver */
struct examplePrivate {
int j;
/*
* Define all per-card private variables here.
*/
};
#define PRIVATE_SIZE sizeof(struct examplePrivate)
int vxi_make_example = 0x100; /* Set to proper make of the card */
int vxi_model_example = 0x100; /* Set to proper model of the card */
/*
* This is a test entry point that allows a user to do a pseudo-init of
* a make and model of VXI cards.
*/
exVxiStat vti(int make, int model)
{
vxi_make_example = make;
vxi_model_example = model;
example_init();
printf("Driver ID is 0x%08X\n", exampleDriverID);
return(VXI_SUCCESS);
}
/******************************************************************************
*
* Initialize all cards controlled by the example driver.
*
******************************************************************************/
LOCAL exVxiStat example_init(void)
{
exVxiStat s;
epvxiDeviceSearchPattern dsp;
/*
* do nothing on crates without VXI
*/
if(!epvxiResourceMangerOK)
return VXI_SUCCESS;
if (rebootHookAdd(example_shutdown) < 0){
s = S_dev_internal;
errMessage(s, "rebootHookAdd failed");
return(s);
}
exampleDriverID = epvxiUniqueDriverID();
dsp.flags = VXI_DSP_make;
dsp.make = vxi_make_example;
s = epvxiLookupLA(&dsp, example_init_card, (void *)NULL);
return s;
}
/******************************************************************************
*
* initialize single example card
*
******************************************************************************/
LOCAL void example_init_card(unsigned addr)
{
exVxiStat s;
struct examplePrivate *ep; /* Per-card private variable area */
struct exampleCard *ec; /* Physical address of the card */
/* Tell the VXI sub-system that this driver is in charge of this card */
s = epvxiOpen(addr, exampleDriverID, PRIVATE_SIZE, example_stat);
if (s)
{
errPrintf(s, __FILE__, __LINE__, "LA=0X%X", addr);
return;
}
printf("example_init_card entered for card at LA 0x%02X, make 0x%02X, model 0x%02X\n", addr, vxi_make_example, vxi_model_example);
/* Allocate a private variable area for the card */
s = epvxiFetchPConfig(addr, exampleDriverID, ep);
if(s){
errMessage(s, NULL);
epvxiClose(addr, exampleDriverID);
return;
}
/* Get physical base address of the card */
ec = (struct exampleCard *) VXIBASE(addr);
/***********************************************
*
* Perform card-specific initialization in here.
*
***********************************************/
/* Register the card's model and make names for reporting purposes */
s = epvxiRegisterModelName(
vxi_make_example,
vxi_model_example,
"Example Model Name");
if(s){
errMessage(s, NULL);
}
s = epvxiRegisterMakeName(
vxi_make_example,
"Example Make Name");
if(s){
errMessage(s, NULL);
}
return;
}
/******************************************************************************
*
* Shut the cards down beacuse a soft-boot will be taking place soon.
*
******************************************************************************/
LOCAL int example_shutdown(void)
{
exVxiStat s;
epvxiDeviceSearchPattern dsp;
dsp.flags = VXI_DSP_make;
dsp.make = vxi_make_example;
s = epvxiLookupLA(&dsp, example_shutdown_card, (void *)NULL);
if(s){
errMessage(s, NULL);
}
return OK;
}
LOCAL void example_shutdown_card(unsigned la)
{
/*
* Perform proper operations here to disable the VXI card from
* generating interrupts and/or other backplane bus activity that
* could cause the CPUs and controllers problems during a soft-boot.
*/
return;
}
/******************************************************************************
*
* Print status for a single card.
*
******************************************************************************/
LOCAL void example_stat(
unsigned card,
int level
)
{
/*
* Perform proper operations to evaluate the current operating mode
* of the card and print a summary.
*/
return;
}
/******************************************************************************
*
* Place any user-required functions here.
*
******************************************************************************/
+526
View File
@@ -0,0 +1,526 @@
/* drvFp.c */
/* base/src/drv $Id$
* routines which are used to test and interface with the
* FP10S fast protect module
*
* Author: Matthew Stettler
* Date: 6-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 070992 integrated into GTACS & added std header
* .02 joh 070992 merged in include file fp.h
* .03 joh 070992 converted some symbols to LOCAL so they stay out
* of the vxWorks global symbol table
* .04 joh 070992 took out sysSetBCL() and substituted
* sysIntEnable() so this will not be hkv2f
* specific.
* .05 joh 070992 added INUM_TO_IVEC so this will be less
* 68k dependence (added include of iv.h)
* .06 joh 070992 FP_ILEV passed to call sysIntEnable() so that the
* interrupt level can be easily changed
* .07 joh 070992 changed some printf() calls to logMsg()
* so that driver diagnostics will show up in
* the log
* .08 joh 071092 now fetches base addr from module_types.h
* .09 joh 071092 added io_report routine
* .10 joh 071092 added scan task wakeup from ISR
* .11 joh 071092 moved ivec allocation to module_types.h
* .12 joh 072792 added soft reboot int disable
* .13 joh 082792 converted to V5 vxorks
* .14 mrk 090192 support epics I/O event scan, and added DRVET
* .15 mrk 080293 Add call to taskwdInsert
* .16 mgb 080493 Removed V5/V4 and EPICS_V2 conditionals
*/
/*
*
* Routines:
*
* fp_init Finds and initializes fast protect cards
* fp_driver System interface to FP10S modules
* fp_int Interrupt service routine
* fp_en Enables/disables interrupts (toggles)
* fp_mode Sets interrupt reporting mode
* fp_reboot Clean up for soft reboots
*
* Diagnostic Routines:
*
* fp_srd Reads current local inputs and enables
* fp_frd Reads last failure register
* fp_csrd Reads control/status register
* fp_read Command line interface to fp_driver
* fp_dump Prints all fast protect status to console
* fp_monitor Monitor all cards and print failure data to
* console
*
* Routines Return:
*
* -1 No card present
* -2 Interrupt connection error
* -3 Semaphore creation error
* -4 addressing error
* -5 no memory
* 0-8 successfull completion, or # of cards found
*
*/
static char *sccsId = "@(#)drvFp.c 1.12\t6/4/93";
#include "vxWorks.h"
#include "vme.h"
#include "taskLib.h"
#include <iv.h> /* in h/68k if this is compiling for a 68xxx */
#include "module_types.h"
#include <dbDefs.h>
#include <drvSup.h>
#include <taskwd.h>
#include <dbScan.h>
static long report();
static long init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvFp={
2,
report,
init};
static long report()
{
fp_io_report();
}
static long init()
{
fp_init(0);
return(0);
}
/* general constants */
#define FP_INTLEV 5 /* interrupt level */
#define FP_BUFSIZ 8 /* input buffer size */
/* csr bit definitions */
#define CSR_RST 0x1 /* reset status */
#define CSR_CMD1 0x2 /* force local fail */
#define CSR_IEN 0x4 /* interrupt enable */
#define CSR_UDEF0 0x8 /* undefined */
#define CSR_I0 0x10 /* interrupt level bit #1 */
#define CSR_I1 0x20 /* interrupt level bit #2 */
#define CSR_I2 0x40 /* interrupt level bit #3 */
#define CSR_UDEF1 0x80 /* undefined */
#define CSR_CARM0_L 0x100 /* latched carrier monitor #0 (one shot) */
#define CSR_CARM1_L 0x200 /* latched carrier monitor #1 (freq mon) */
#define CSR_OPTIC 0x400 /* optical carrier input enabled */
#define CSR_CARM 0x800 /* carrier OK */
#define CSR_LFAIL0 0x1000 /* local fail #0 (pal monitor) */
#define CSR_LFAIL1 0x2000 /* local fail #1 (fpga monitor) */
#define CSR_CMON 0x4000 /* clock fail (one shot) */
#define CSR_CHNG 0x8000 /* enable switch configuration change */
/* csr mask definitions */
#define CSR_STM 0xff00 /* status mask */
#define CSR_IM 0x70 /* interrupt level mask */
/* driver status */
#define DRV_MOM 0x010000 /* momentary fault */
#define DRV_LOC 0x020000 /* local fault */
#define DRV_REM 0x040000 /* remote fault */
#define DRV_CLR 0x080000 /* fault cleared */
#define DRV_HWF 0x800000 /* hardware fault */
/* operating modes */
#define FP_NMSG 0 /* no messages to console */
#define FP_TMSG 1 /* terse messages to console */
#define FP_FMSG 2 /* full messages to console */
#define FP_RUN 3 /* normal operating mode */
/* register address map for FP10s */
struct fp1
{
unsigned short csr; /* control and status register */
unsigned short srd; /* current status */
unsigned short frd; /* latched status */
unsigned short ivec; /* interrupt vector */
char end_pad[0xff-0x8]; /* pad to 256 byte boundary */
};
/* fast protect control structure */
struct fp_rec
{
struct fp1 *fptr; /* pointer to device registers */
unsigned int drvstat; /* fast protect physical inputs */
unsigned short lastswitch; /* previous enable switch data */
short type; /* device type */
short num; /* device number */
short fp_vector; /* interrupt vector */
short mode; /* operating mode */
unsigned int int_num; /* interrupt number */
IOSCANPVT ioscanpvt;
};
static struct fp_rec *fp; /* fast protect control structure */
static int fp_num; /* # of fast protect cards found -1 */
static SEM_ID fp_semid; /* semaphore for monitor task */
static void fp_reboot();
/*
* fp_int
*
* interrupt service routine
*
*/
fp_int(card)
unsigned card;
{
register struct fp_rec *ptr = &fp[card];
register struct fp1 *regptr;
unsigned short temp0, temp1, temp2;
regptr = ptr->fptr;
temp0 = regptr->csr;
temp1 = regptr->frd;
temp2 = regptr->srd;
switch (ptr->mode)
{
case FP_TMSG:
logMsg("fast protect interrupt!\n");
logMsg("csr status = %x\n",temp0);
break;
case FP_FMSG:
logMsg("fast protect #%d fault! fault input = %x enable switches = %x\n",
ptr->num,temp1 & 0xff,temp2>>8);
logMsg("csr status = %x\n",temp0);
break;
case FP_RUN:
ptr->drvstat = temp2; /* save last switch data */
ptr->drvstat |= temp1<<16; /* save fault data */
ptr->drvstat |= (temp0 & 0xff00)<<16; /* csr status bits */
if ((temp1 ^ (temp2>>8)) || (temp0 & CSR_CHNG)) /* fault or enable change */
semGive(fp_semid); /* wake up monitor */
/*
* wakeup the interrupt driven scanner
*/
scanIoRequest(fp[card].ioscanpvt);
break;
}
ptr->int_num++; /* log interrupt */
regptr->csr |= CSR_RST; /* clear status and rearm */
regptr->csr ^= CSR_RST;
}
/*
* fp_init
*
* initialization routine for FP10s fast protect modules
*
*
*/
fp_init(addr)
unsigned int addr;
{
int i;
short junk;
short intvec = AT8FP_IVEC_BASE;
struct fp1 *ptr;
int status;
fp = (struct fp_rec *) calloc(bi_num_cards[AT8_FP10S_BI], sizeof(*fp));
if(!fp){
return -5;
}
if(!addr){
addr = bi_addrs[AT8_FP10S_BI];
}
status = sysBusToLocalAdrs( VME_AM_SUP_SHORT_IO, addr, &ptr);
if(status<0){
logMsg("VME shrt IO addr err in the slave fast protect driver\n");
return(-4);
}
status = rebootHookAdd(fp_reboot);
if(status<0){
logMsg("%s: reboot hook add failed\n", __FILE__);
}
for (i = 0;
(i < bi_num_cards[AT8_FP10S_BI]) && (vxMemProbe(ptr,READ,2,&junk) == OK);
i++,ptr++) {
/* register initialization */
ptr->csr = 0x0000; /* disable interface */
fp[i].fptr = ptr; /* hardware location */
fp[i].fp_vector = intvec++; /* interrupt vector */
ptr->ivec = fp[i].fp_vector; /* load vector */
fp[i].mode = FP_NMSG; /* set default mode (no messages) */
fp[i].int_num = 0; /* initialize interrupt number */
fp[i].type = 10; /* board type */
fp[i].num = i; /* board number */
/* initialize input buffer */
fp[i].drvstat = ptr->srd; /* initialize enable switch data */
fp[i].drvstat |= ptr->frd<<16; /* initialize fault data */
fp[i].drvstat |= (ptr->csr & 0xff00)<<16; /* csr status bits */
/* set up interrupt handler */
ptr->csr |= FP_INTLEV<<4; /* level 5 interrupt */
if (intConnect(INUM_TO_IVEC(fp[i].fp_vector),fp_int,i) != OK)
return(-2); /* abort if can't connect */
sysIntEnable(FP_INTLEV);
ptr->csr |= 0x0001;
ptr->csr ^= 0x0001; /* clear status bits */
if (ptr->csr & CSR_OPTIC)
logMsg("fast protect #%d optically coupled\n",i);
else
logMsg("fast protect #%d elecrically coupled\n",i);
/* start up module */
fp[i].fptr->csr |= CSR_IEN; /* enable interrupts */
fp[i].mode = FP_RUN; /* normal run mode */
scanIoInit(&fp[i].ioscanpvt);
}
fp_num = i - 1; /* record max card # */
/* create the semaphore */
fp_semid = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
if ((int)fp_semid == 0) /* abort if can't create semaphore */
return(-3);
return(i); /* return # found */
}
/*
*
* fp_reboot()
*
* turn off interrupts to avoid ctrl X reboot problems
*/
LOCAL
void fp_reboot()
{
int i;
if(!fp){
return;
}
for (i = 0; i < bi_num_cards[AT8_FP10S_BI]; i++){
if(!fp[i].fptr){
continue;
}
fp[i].fptr->csr &= ~CSR_IEN;
}
}
/*
* fp_en
*
* interrupt enable/disable
* (toggles the interrupt enable - joh)
*
*/
fp_en(card)
short card;
{
unsigned short temp;
if (card < 0 || (card > fp_num))
return -1;
fp[card].fptr->csr = fp[card].fptr->csr ^ CSR_IEN;
if (fp[card].fptr->csr & CSR_IEN)
printf("fast protect interrupts enabled\n");
else
printf("fast protect interrupts disabled\n");
return 0;
}
/*
* fp_mode
*
* set interrupt reporting mode
*
*/
fp_mode(card,mode)
short card, mode;
{
if (card < 0 || (card > fp_num))
return -1;
fp[card].mode = mode;
return 0;
}
/*
* fp_srd
*
* read current local inputs and enable switches
*
*/
fp_srd(card,option)
short card;
short option;
{
if (card > fp_num) return -1;
if (!option)
printf("local inputs = %x enable switches = %x\n",fp[card].fptr->srd & 0xff,
fp[card].fptr->srd>>8);
return fp[card].fptr->srd;
}
/*
* fp_frd
*
* read latched local inputs
*
*/
fp_frd(card)
short card;
{
if (card < 0 || (card > fp_num))
return -1;
return fp[card].fptr->frd & 0xff;
}
/*
* fp_csrd
*
* read csr contents
*
*/
fp_csrd(card)
short card;
{
if (card < 0 || (card > fp_num))
return -1;
return fp[card].fptr->csr & 0xff77;
}
/*
* fp_driver
*
* epics interface to fast protect
*
*/
fp_driver(card,mask,prval)
register unsigned short card;
unsigned int mask;
register unsigned int *prval;
{
register unsigned int temp;
if (card > fp_num) return -1;
temp = fp[card].drvstat & 0xffff0000; /* latched status info */
temp |= fp[card].fptr->srd; /* current switches & inputs */
*prval = temp & mask;
return 0;
}
/*
* fp_read
*
* command line interface to fp_driver
*
*/
fp_read(card)
short card;
{
unsigned int fpval,ret;
if ((ret = fp_driver(card,0xffffffff,&fpval)) != 0)
return ret;
printf("Card #%d enable switches = %x inputs = %x\n",card,(fpval & 0x0000ff00)>>8,
fpval & 0x000000ff);
printf("csr status = %x last fault = %x\n",fpval>>24,(fpval & 0x00ff0000)>>16);
printf("raw readback = %x\n",fpval);
return 0;
}
/*
* fp_dump
*
* dump fast protect status to console
*
*/
fp_dump()
{
int i;
printf("Fast protect status (fault and CSR are latched):\n");
printf("Card#\tenables\tinputs\tfault\tCSR status\n");
for(i = 0; i < (fp_num + 1); i++)
printf("%d\t%x\t%x\t%x\t%x\n",i,fp[i].fptr->srd>>8,fp[i].fptr->srd & 0xff,
(fp[i].drvstat & 0x00ff0000)>>16,fp[i].drvstat>>24);
return i;
}
/*
* fp_monitor
*
* monitor fast protect cards and report failures to console
*
*/
fp_mon()
{
for(semTake(fp_semid,WAIT_FOREVER);fp_dump() != 0;semTake(fp_semid,WAIT_FOREVER));
}
fp_monitor()
{
static char *name = "fpmon";
int tid;
if ((tid = taskNameToId(name)) != ERROR) {
taskwdRemove(tid);
taskDelete(tid);
}
if((tid = taskSpawn(name,25,VX_SUPERVISOR_MODE|VX_STDIO,
1000,fp_mon)) == ERROR) return -1;
taskwdInsert(tid,NULL,NULL);
return 0;
}
fp_io_report(level)
int level;
{
int i;
for(i=0; i<=fp_num; i++){
printf("BI: AT8-FP-S: card %d\n", i);
}
}
fp_getioscanpvt(card,scanpvt)
short card;
IOSCANPVT *scanpvt;
{
if ((card >= bi_num_cards[AT8_FP10S_BI])) return(0);
*scanpvt = fp[card].ioscanpvt;
return(0);
}
+432
View File
@@ -0,0 +1,432 @@
/* drvFpm.c */
/* base/src/drv $Id$ */
/*
* control routines for use with the FP10M fast protect master modules
*
* routines which are used to test and interface with the
* FP10S fast protect module
*
* Author: Matthew Stettler
* Date: 6-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 070992 integrated into GTACS & added std header
* .02 joh 070992 merged in include file fpm.h
* .03 joh 070992 converted some symbols to LOCAL so they stay out
* of the vxWorks global symbol table
* .04 joh 070992 took out sysSetBCL() and substituted
* sysIntEnable() so this will not be hkv2f
* specific.
* .05 joh 070992 added INUM_TO_IVEC so this will be less
* 68k dependence (added include of iv.h)
* .06 joh 070992 FP_ILEV passed to call sysIntEnable() so that the
* interrupt level can be easily changed
* .07 joh 071092 now fetches base addr from module_types.h
* .08 joh 071092 added io report routine
* .09 joh 071092 allocate config structure at run time so that
* the users can adjust the number of cards without
* recompilation
* .10 joh 071092 moved ivec allocation to module_types.h
* .11 joh 072792 added soft reboot int disable
* .12 mrk 090292 added DRVET
* .13 mgb 080493 Removed V5/V4 and EPICS_V2 conditionals
*
*
* Routines:
*
* fpm_init Finds and initializes FP10M cards
* fpm_driver System interface to FP10M modules
* fpm_read Carrier control readback
* fpm_reboot clean up before soft reboots
*
* Daignostic Routines
* fpm_en Enables/disables interrupts (diagnostic enable)
* fpm_mode Sets interrupt reporting mode (logs mode
* changes to console)
* fpm_cdis Disables carrier from console
* fpm_fail Sets carrier failure mode
* fpm_srd Reads current carrier status
* fpm_write Command line interface to fpm_driver
*
* Routines return:
*
* -1 Nonexistent card
* -2 Interrupt connection error
* -3 no memory
* -4 VME short IO bus nonexistent
* 0-2 Successfull completion, or # cards found
*
*/
static char *sccsId = "@(#)drvFpm.c 1.12\t8/4/93";
#include "vxWorks.h"
#include "vme.h"
#include <iv.h> /* in h/68k if this is compiling for a 68xxx */
#include "module_types.h"
#include <dbDefs.h>
#include <drvSup.h>
static long report();
static long init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvFpm={
2,
report,
init};
static long report()
{
fpm_io_report();
}
static long init()
{
fpm_init(0);
return(0);
}
/* general constants */
#define FPM_INTLEV 5 /* interrupt level */
/* control register bit definitions */
#define CR_CDIS 0x1 /* software carrier disable */
#define CR_FS0 0x2 /* fail select 0 */
#define CR_FS1 0x4 /* fail select 1 */
#define CR_FS2 0x8 /* fail select 2 */
#define CR_I0 0x10 /* interrupt level bit 0 */
#define CR_I1 0x20 /* interrupt level bit 1 */
#define CR_I2 0x40 /* interrupt level bit 2 */
#define CR_IEN 0x80 /* interrupt enable */
/* control register mask definitions */
#define CR_IM 0x70 /* interrupt level mask */
/* status register bit definitions */
#define SR_S0 0x1 /* error sequencer state bit 0 */
#define SR_S1 0x2 /* error sequencer state bit 1 */
#define SR_S2 0x3 /* error sequencer state bit 2 */
/* status register mask definitions */
#define SR_EM 0x7 /* error state mask */
/* operating modes */
#define FPM_NMSG 0 /* no messages to console */
#define FPM_TMSG 1 /* terse messages to console */
#define FPM_FMSG 2 /* full messages to console */
/* register address map for FP10M */
struct fp10m
{
unsigned short cr; /* control register */
unsigned short sr; /* status register */
unsigned short ivec; /* interrupt vector */
char end_pad[0xff-0x6]; /* pad to 256 byte boundary */
};
/* control structure */
struct fpm_rec
{
struct fp10m *fmptr; /* pointer to device registers */
short type; /* device type */
short num; /* board number */
short vector; /* interrupt vector */
short mode; /* operating mode */
unsigned int int_num; /* interrupt number */
};
static struct fpm_rec *fpm; /* fast protect control structure */
static int fpm_num; /* # cards found - 1 */
static void fpm_reboot();
/*
* fpm_int
*
* interrupt service routine
*
*/
fpm_int(ptr)
register struct fpm_rec *ptr;
{
register struct fp10m *regptr;
regptr = ptr->fmptr;
switch (ptr->mode)
{
case FPM_TMSG:
logMsg("fast protect master interrupt!\n");
break;
case FPM_FMSG:
logMsg("fast protect master interrupt!\n");
logMsg("cr = %x sr = %x\n",regptr->cr,regptr->sr & 0x7);
break;
}
ptr->int_num++;
}
/*
* fpm_init
*
* initialization for fp10m fast protect master modules
*
*/
fpm_init(addr)
unsigned int addr;
{
int i;
short junk;
short intvec = AT8FPM_IVEC_BASE;
struct fp10m *ptr;
int status;
fpm = (struct fpm_rec *) calloc(
bo_num_cards[AT8_FP10M_BO],
sizeof(*fpm));
if(!fpm){
return -3;
}
if(!addr){
addr = bo_addrs[AT8_FP10M_BO];
}
status = sysBusToLocalAdrs(
VME_AM_SUP_SHORT_IO,
addr,
&ptr);
if(status<0){
logMsg("VME shrt IO addr err in the master fast protect driver\n");
return -4;
}
status = rebootHookAdd(fpm_reboot);
if(status<0){
logMsg("%s: reboot hook add failed\n", __FILE__);
}
for (i = 0; (i < bo_num_cards[AT8_FP10M_BO]) && (vxMemProbe(ptr,READ,2,&junk) == OK);
i++,ptr++)
{
/*
register initialization
*/
ptr->cr = 0x00; /* disable interface */
fpm[i].fmptr = ptr; /* hardware location */
fpm[i].vector = intvec++; /* interrupt vector */
ptr->ivec = fpm[i].vector; /* load vector */
fpm[i].mode = FPM_NMSG; /* set default mode (no messages) */
fpm[i].int_num = 0; /* initialize interrupt number */
fpm[i].type = 2; /* board type */
fpm[i].num = i; /* board number */
/*
set up interrupt handler
*/
ptr->cr |= FPM_INTLEV<<4; /* set up board for level 5 interrupt */
if (intConnect(INUM_TO_IVEC(fpm[i].vector),fpm_int,&fpm[i]) != OK)
return -2; /* abort if can't connect */
sysIntEnable(FPM_INTLEV);
}
fpm_num = i - 1; /* record last card # */
return i; /* return # cards found */
}
/*
*
* fpm_reboot()
*
* turn off interrupts to avoid ctrl X reboot problems
*/
LOCAL
void fpm_reboot()
{
int i;
if(!fpm){
return;
}
for (i = 0; i < bo_num_cards[AT8_FP10M_BO]; i++){
if(!fpm[i].fmptr){
continue;
}
fpm[i].fmptr->cr &= ~CR_IEN;
}
}
/*
* fpm_en
*
* interrupt enable/disable
* (toggles the int enable state - joh)
*
*/
fpm_en(card)
short card;
{
if (card < 0 || (card > fpm_num))
return -1;
fpm[card].fmptr->cr ^= CR_IEN;
if (fpm[card].fmptr->cr & CR_IEN)
printf("fast protect master interrupts enabled\n");
else
printf("fast protect master interrupts disabled\n");
return 0;
}
/*
* fpm_mode
*
* set interrupt reporting mode
*
*/
fpm_mode(card,mode)
short card, mode;
{
if (card < 0 || (card > fpm_num))
return -1;
fpm[card].mode = mode;
return 0;
}
/*
* fpm_cdis
*
* carrier disable (1), enable (0)
*
*/
fpm_cdis(card,disable)
short card, disable;
{
unsigned short temp;
if (card < 0 || (card > fpm_num))
return -1;
temp = fpm[card].fmptr->cr;
temp &= 0xfe;
temp |= (disable & 0x01);
fpm[card].fmptr->cr = temp;
return 0;
}
/*
* fpm_fail
*
* set failure mode
*
*/
fpm_fail(card,mode)
short card, mode;
{
unsigned short temp;
if (card < 0 || (card > fpm_num))
return -1;
temp = fpm[card].fmptr->cr;
temp &= 0xf1;
temp |= (mode & 0x7)<<1;
fpm[card].fmptr->cr = temp;
return 0;
}
/*
* fpm_srd
*
* read status bits
*
*/
fpm_srd(card)
short card;
{
if (card < 0 || ( card > fpm_num))
return -1;
return fpm[card].fmptr->sr & 0x7;
}
/*
* fpm_driver
*
* epics interface to fast protect master
*
*/
fpm_driver(card,mask,prval)
register unsigned short card;
unsigned int mask;
register unsigned int prval;
{
register unsigned int temp;
if (card > fpm_num)
return -1;
temp = fpm[card].fmptr->cr;
fpm[card].fmptr->cr = (temp & (~mask | 0xf0)) | ((prval & mask) & 0xf);
return 0;
}
/*
* fpm_write
*
* command line interface to fpm_driver
*
*/
fpm_write(card,val)
short card;
unsigned int val;
{
return fpm_driver(card,0xffffffff,val);
}
/*
* fpm_read
*
* read the current control register contents (readback)
*
*/
fpm_read(card,mask,pval)
register unsigned short card;
unsigned int mask;
register unsigned int *pval;
{
if (card > fpm_num)
return -1;
*pval = fpm[card].fmptr->cr & 0x000f;
return 0;
}
/*
* fpm_io_report()
*
*/
fpm_io_report(level)
int level;
{
int i;
for(i=0; i<=fpm_num; i++){
printf("BO: AT8-FP-M: card %d\n", i);
}
}
File diff suppressed because it is too large Load Diff
+315
View File
@@ -0,0 +1,315 @@
/* drvGpib.h */
/* base/src/drv $Id$ */
/*
* Origional Author: Unknown, probably National Instruments
* Author: John Winans
* Date: 10-27-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 10-27-91 winans moved into epics area
*/
/* GPIB-1014 engineering software package UNIX include file */
/*
* The following structure dma_chan defines the memory map of a single
* channel on the Hitachi 68450.
*/
struct dma_chan {
char csr; /* +0 channel status register */
char cer; /* +1 channel error register */
char f0[2];
char dcr; /* +4 device control register */
char ocr; /* +5 operation control register */
char scr; /* +6 sequence control register */
char ccr; /* +7 channel control register */
char f1[2];
unsigned short mtc; /* +10 memory transfer counter */
long mar; /* +12 memory address register */
char f2[4];
long dar; /* +20 device address register */
char f3[2];
unsigned short btc; /* +26 base transfer counter */
long bar; /* +28 base address register */
char f4[5];
char niv; /* +37 normal interrupt vector */
char f5;
char eiv; /* +39 error interrupt vector */
char f6;
char mfc; /* +41 memory function codes */
char f7[3];
char cpr; /* +45 channel priority register */
char f8[3];
char dfc; /* +49 device function codes */
char f9[7];
char bfc; /* +57 base function codes */
char fA[6];
};
/*
* The structure ibregs defines the address space of the GPIB-1014.
*/
struct ibregs {
struct dma_chan ch0; /* +0 dma channel 0 */
struct dma_chan ch1; /* +64 dma channel 1 */
struct dma_chan ch2; /* +128 dma channel 2 */
struct dma_chan ch3; /* +192 dma channel 3 */
#define gcr ch3.fA[5] /* +255 general control register */
char fB;
char cfg1; /* +257 config reg 1 */
#define gsr cfg1 /* +257 GSR */
char fC[3];
char cfg2; /* +261 config reg 2 */
char fD[10];
char fE, cdor; /* +273 byte out register */
char fF, imr1; /* +275 interrupt mask register 1 */
char f10,imr2; /* +277 interrupt mask register 2 */
char f11,spmr; /* +279 serial poll mode register */
char f12,admr; /* +281 address mode register */
char f13,auxmr; /* +283 auxiliary mode register */
char f14,adr; /* +285 address register 0/1 */
char f15,eosr; /* +287 end of string register */
char f16[512-289]; /* +289 filler to rest of window */
};
/*
* The structure srqTable defines the srq status of each of 31 possible devices
*/
struct srqTable {
short active;
char lad;
char tad;
unsigned char status;
SEM_ID pSem;
} ;
/* 7210 readable registers */
#define dir cdor
#define isr1 imr1
#define isr2 imr2
#define spsr spmr
#define adsr admr
#define cptr auxmr
#define adr0 adr
#define adr1 eosr
/* GPIB status register */
#define GSR_EOI 0x80
#define GSR_ATN 0x40
#define GSR_SRQ 0x20
#define GSR_REN 0x10
#define GSR_IFC 0x08
#define GSR_NRFD 0x04
#define GSR_NDAC 0x02
#define GSR_DAV 0x01
/* 68450 DMAC register definitions */
/* Device Control Register (dcr) bits */
#define D_CS 0x80 /* cycle steal mode */
#define D_CSM 0x80 /* cycle steal mode,with bus Monitor*/
#define D_CSH 0xC0 /* cycle steal with hold */
#define D_CSHM 0xC0 /* cycle steal with hold,with bus Monitor */
#define D_IACK 0x20 /* device with DMAACK, implicitly addressed */
#define D_P16 0x08 /* 16 bit device port size */
#define D_IPCL 0x01 /* PCL set to status input with interrupt */
/* Operation Control Register (ocr) bits */
#define D_MTD 0x00 /* direction is from memory to device */
#define D_DTM 0x80 /* direction is from device to memory */
#define D_TW 0x10 /* transfer size is word */
#define D_TL 0x30 /* transfer size is long word */
#define D_ACH 0x08 /* array chaining */
#define D_LACH 0x0C /* linked array chaining */
#define D_ARQ 0x03 /* auto request first transfer, then external*/
#define D_XRQ 0x02 /* external request mode */
#define D_ARM 0x01 /* auto request at maximum rate */
/* Sequence Control Register (scr) bits */
#define D_MCD 0x08 /* memory address counts down */
#define D_MCU 0x04 /* memory address counts up */
#define D_DCD 0x02 /* device address counts down */
#define D_DCU 0x01 /* device address counts up */
/* Channel Control Register (ccr) bits */
#define D_SRT 0x80 /* start channel operation */
#define D_CON 0x40 /* continue */
#define D_HLT 0x20 /* halt channel operation */
#define D_SAB 0x10 /* software abort */
#define D_EINT 0x08 /* enable channel interrupts */
/* Channel Status Register (csr) bits */
#define D_CLEAR 0xFF /* clear all bits */
#define D_COC 0x80 /* channel operation complete */
#define D_BTC 0x40 /* block transfer complete */
#define D_NDT 0x20 /* normal device termination */
#define D_ERR 0x10 /* error as coded in cer */
#define D_ACT 0x08 /* channel active */
#define D_PCLT 0x02 /* PCL transition occurred */
#define D_PCLH 0x01 /* PCL line is high */
#define D_NSRQ 0x01 /* Not SRQ (gpib line) */
/* Channel Error Register (cer) bits */
#define D_ECF 0x01 /* configuration error */
#define D_ETM 0x02 /* operation timing error */
#define D_EMA 0x05 /* memory address error */
#define D_EDA 0x06 /* device address error */
#define D_EBA 0x07 /* base address error */
#define D_EBUS 0x08 /* bus error */
#define D_ECT 0x0C /* transfer count error */
#define D_EEAB 0x01 /* external abort */
#define D_ESAB 0x11 /* software abort */
/* Channel Priority Register (cpr) bits */
#define D_PR1 0x01 /* priority 1 */
#define D_PR2 0x02 /* priority 2 */
#define D_PR3 0x03 /* priority 3 */
/* Function Code Register (fcr) bits */
#define D_SUP 0x04 /* supervisor access */
#define D_S24 0x02 /* standard 24 bit addressing */
#define D_PSA 0x01 /* program space access */
/* Configuration Register 1 (cfg1) bits */
#define D_OUT 0 /* direction memory to GPIB */
#define D_IN (1<<0) /* direction GPIB to memory */
#define D_DBM (1<<1) /* disarm Bus Monitor mode */
#define D_ECC (1<<2) /* arm automatic carry cycle feature */
#define D_BRG0 (00<<3) /* select bus request/grant line 1 */
#define D_BRG1 (01<<3) /* select bus request/grant line 1 */
#define D_BRG2 (02<<3) /* select bus request/grant line 2 */
#define D_BRG3 (03<<3) /* select bus request/grant line 3 */
/* Configuration Register 2 (cfg2) bits */
#define D_SC (1<<0) /* set system controller (SC) bit */
#define D_LMR (1<<1) /* set local master reset bit */
#define D_SPAC (1<<2) /* set supervisor only access to board */
#define D_SFL (1<<3) /* clear SYSFAIL line */
/* Control masks for hidden registers (auxmr) */
#define ICR 0040
#define PPR 0140
#define AUXRA 0200
#define AUXRB 0240
#define AUXRE 0300
#define CNT 0340 /* OR of all of above */
/* 7210 bits: POSITION 7210 reg */
#define HR_DI (1<<0) /* ISR1 */
#define HR_DO (1<<1) /* , */
#define HR_ERR (1<<2) /* , */
#define HR_DEC (1<<3) /* , */
#define HR_END (1<<4) /* , */
#define HR_DET (1<<5) /* , */
#define HR_APT (1<<6) /* , */
#define HR_CPT (1<<7) /* , */
#define HR_DIIE (1<<0) /* IMR1 */
#define HR_DOIE (1<<1) /* , */
#define HR_ERRIE (1<<2) /* , */
#define HR_DECIE (1<<3) /* , */
#define HR_ENDIE (1<<4) /* , */
#define HR_DETIE (1<<5) /* , */
#define HR_ADSC (1<<0) /* ISR2 */
#define HR_REMC (1<<1) /* , */
#define HR_LOKC (1<<2) /* , */
#define HR_CO (1<<3) /* , */
#define HR_REM (1<<4) /* , */
#define HR_LOK (1<<5) /* , */
#define HR_SRQI (1<<6) /* , */
#define HR_INT (1<<7) /* , */
#define HR_ACIE (1<<0) /* IMR2 */
#define HR_REMIE (1<<1) /* , */
#define HR_LOKIE (1<<2) /* , */
#define HR_COIE (1<<3) /* , */
#define HR_DMAI (1<<4) /* , */
#define HR_DMAO (1<<5) /* , */
#define HR_SRQIE (1<<6) /* , */
#define HR_PEND (1<<6) /* SPSR */
#define HR_RSV (1<<6) /* SPMR */
#define HR_MJMN (1<<0) /* ADSR */
#define HR_TA (1<<1) /* , */
#define HR_LA (1<<2) /* , */
#define HR_TPAS (1<<3) /* , */
#define HR_LPAS (1<<4) /* , */
#define HR_SPMS (1<<5) /* , */
#define HR_NATN (1<<6) /* , */
#define HR_CIC (1<<7) /* , */
#define HR_ADM0 (1<<0) /* ADMR */
#define HR_ADM1 (1<<1) /* , */
#define HR_TRM0 (1<<4) /* , */
#define HR_TRM1 (1<<5) /* , */
#define HR_LON (1<<6) /* , */
#define HR_TON (1<<7) /* , */
#define HR_DL (1<<5) /* ADR */
#define HR_DT (1<<6) /* , */
#define HR_ARS (1<<7) /* , */
#define HR_HLDA (1<<0) /* auxra */
#define HR_HLDE (1<<1) /* , */
#define HR_REOS (1<<2) /* , */
#define HR_XEOS (1<<3) /* , */
#define HR_BIN (1<<4) /* , */
#define HR_CPTE (1<<0) /* auxrb */
#define HR_SPEOI (1<<1) /* , */
#define HR_TRI (1<<2) /* , */
#define HR_INV (1<<3) /* , */
#define HR_ISS (1<<4) /* , */
#define HR_PPS (1<<3) /* ppr */
#define HR_PPU (1<<4) /* , */
/* 7210 Auxiliary Commands */
#define AUX_PON 000 /* Immediate Execute pon */
#define AUX_CR 002 /* Chip Reset */
#define AUX_FH 003 /* Finish Handshake */
#define AUX_TRIG 004 /* Trigger */
#define AUX_RTL 005 /* Return to local */
#define AUX_SEOI 006 /* Send EOI */
#define AUX_NVAL 007 /* Non-Valid Secondary Command or Address */
#define AUX_VAL 017 /* Valid Secondary Command or Address */
#define AUX_CPPF 001 /* Clear Parallel Poll Flag */
#define AUX_SPPF 011 /* Set Parallel Poll Flag */
#define AUX_TCA 021 /* Take Control Asynchronously */
#define AUX_TCS 022 /* Take Control Synchronously */
#define AUX_TCSE 032 /* Take Control Synchronously on End */
#define AUX_GTS 020 /* Go To Standby */
#define AUX_LTN 023 /* Listen */
#define AUX_LTNC 033 /* Listen in Continuous Mode */
#define AUX_LUN 034 /* Local Unlisten */
#define AUX_EPP 035 /* Execute Parallel Poll */
#define AUX_SIFC 036 /* Set IFC */
#define AUX_CIFC 026 /* Clear IFC */
#define AUX_SREN 037 /* Set REN */
#define AUX_CREN 027 /* Clear REN */
#define AUX_DSC 024 /* Disable System Control */
+408
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
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
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;
}
+60
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
);
File diff suppressed because it is too large Load Diff
+641
View File
@@ -0,0 +1,641 @@
/* drvJgvtr1.c */
/* base/src/drv $Id$ */
/*
* Author: Jeff Hill
* Date: 5-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:
* -----------------
* 110689 joh print mem not full message only once
* 120789 joh temporary removal of memory full check
* 050190 joh clear ptr to callback prior to calling
* it so they can rearm from inside the callback
* 071190 joh check STD address after cycle complete detected
* to avoid erroneous card misaddressed messages
* 071190 joh internal sample rate status is bit reversed on the
* card- I added a lookup table to untwist it.
* 020491 ges Change taskDelay from 20 to 2 in "jgvtr1DoneTask".
* To allow rearm and data reads from succesive
* waveform scans up thru 10Hz rates.
* 031491 lrd move data into a local memory area for each card
* 090591 joh converted to V5 vxWorks
* 110591 lrd initialization of cards other than 0 not
* allocating data buffer correctly
* 013092 bg added sysBusToLocalAdrs. Added levels to io_report
* and the ability to read out the Joerger's raw values
* in io_report if level is > 1.
* 031992 joh Took the vxMemProbe out of each arm and checked
* the card present bit instead.
* 062592 bg Combined drvJgvtr1.c and jgvtr_driver.c
* 062992 joh removed file pointer argument added to io
* report by bg
* 082792 joh added ANSI C function prototypes
* 080293 mrk added call to taskwdInsert
* 080493 mgb Removed V5/V4 and EPICS_V2 conditionals
*/
static char *sccsID = "@(#)drvJgvtr1.c 1.17\t9/9/93";
/*
* Code Portions
*
* jgvtr1_init()
* jgvtr1_driver(card, pcbroutine, parg)
* jgvtr1_int_service()
* jgvtr1DoneTask()
* jgvtr1_io_report()
* jgvtr1_stat(card)
*
*/
/* drvJgvtr1.c - Driver Support Routines for Jgvtr1 */
#include <vxWorks.h>
#include <types.h>
#include <vme.h>
#include <iv.h>
#include <sysLib.h>
#include <stdioLib.h>
#include <dbDefs.h>
#include <drvSup.h>
#include <module_types.h>
#include <task_params.h>
#include <fast_lock.h>
#include <taskwd.h>
#include <devLib.h>
#include <drvJgvtr1.h>
LOCAL jgvtr1Stat jgvtr1_io_report(
unsigned level
);
LOCAL jgvtr1Stat jgvtr1_init(
void
);
#ifdef INTERRUPT_HARDWARE_FIXED
LOCAL void jgvtr1_int_service(
void
);
#endif
LOCAL void jgvtr1DoneTask(
void
);
LOCAL jgvtr1Stat jgvtr1_dump(
unsigned card,
unsigned n
);
LOCAL jgvtr1Stat jgvtr1_stat(
unsigned card,
int level
);
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvJgvtr1={
2,
jgvtr1_io_report,
jgvtr1_init};
static volatile char *stdaddr;
static volatile char *shortaddr;
#define JGVTR1MAXFREQ 25.0e6
/* NBBY - the number of bits per byte */
#define JGVTR1SHORTSIZE (1<<(NBBY*sizeof(uint8_t)))
#define JGVTR1STDSIZE (1<<(NBBY*sizeof(uint16_t)))
#define JGVTR1_INT_LEVEL 5
#define JGVTR1BASE(CARD)\
(shortaddr+wf_addrs[JGVTR1]+(CARD)*JGVTR1SHORTSIZE)
#define JGVTR1DATA(CARD)\
(stdaddr+wf_memaddrs[JGVTR1]+(CARD)*JGVTR1STDSIZE)
/*
Joerger fixed hardware bug by switching to an inverting tristate buffer
where these commands are read from the VME bus. As a result these commands
are complemented.
*/
#define JGVTR1ARM (~1)
#define JGVTR1START (~2)
#define JGVTR1STOP (~4)
/*
!! our compiler allocates bit fields starting from the ms bit !!
*/
struct jgvtr1_status{
volatile unsigned pad:8;
volatile unsigned internal_frequency:3;
volatile unsigned internal_clock:1;
volatile unsigned cycle_complete:1;
volatile unsigned interrupt:1;
volatile unsigned active:1;
volatile unsigned memory_full:1;
};
struct jgvtr1_config{
char present; /* card present */
char std_ok; /* std addr ok on first read */
void (*psub) /* call back routine */
(void *pprm, unsigned nbytes, uint16_t *pData);
void *pprm; /* call back parameter */
FAST_LOCK lock; /* mutual exclusion */
uint16_t *pdata; /* pointer to the data buffer */
};
/* amount of data to make available from the waveform */
#define JRG_MEM_SIZE 2048
LOCAL
struct jgvtr1_config *pjgvtr1_config;
LOCAL
int jgvtr1_max_card_count;
#ifdef INTERRUPT_HARDWARE_FIXED
LOCAL
SEM_ID jgvtr1_interrupt; /* interrupt event */
#endif
/*
* JGVTR1_INIT
*
* intialize the driver for the joerger vtr1
*
*/
jgvtr1Stat jgvtr1_init(void)
{
unsigned card;
unsigned card_count = 0;
struct jgvtr1_config *pconfig;
uint16_t readback;
jgvtr1Stat status;
status = sysBusToLocalAdrs(
VME_AM_SUP_SHORT_IO,
0,
(char **)&shortaddr);
if (status != OK){
status = S_dev_badA16;
errMessage(status,NULL);
return status;
}
status = sysBusToLocalAdrs(
VME_AM_STD_SUP_DATA,
0,
(char **)&stdaddr);
if (status != OK){
status = S_dev_badA24;
errMessage(status,NULL);
return status;
}
jgvtr1_max_card_count = wf_num_cards[JGVTR1];
if(pjgvtr1_config){
if(FASTLOCKFREE(&pjgvtr1_config->lock)<0)
return ERROR;
free(pjgvtr1_config);
}
pjgvtr1_config =
(struct jgvtr1_config *)
calloc(wf_num_cards[JGVTR1], sizeof(*pjgvtr1_config));
if(!pjgvtr1_config){
status = S_dev_noMemory;
errMessage(status,NULL);
return status;
}
for( card=0, pconfig=pjgvtr1_config;
card < wf_num_cards[JGVTR1];
pconfig++, card++){
FASTLOCKINIT(&pconfig->lock);
status = vxMemProbe( (char *)JGVTR1BASE(card),
READ,
sizeof(readback),
(char *)&readback);
if(status==ERROR)
continue;
pconfig->pdata =
(uint16_t *)malloc(JRG_MEM_SIZE);
/*
not easy to test for correct addressing in
standard address space since the module does
not respond if it has not clocked in data
- so I check this the first time data is ready
*/
pconfig->std_ok = FALSE; /* presumed guilty before tested */
pconfig->present = TRUE;
card_count++;
}
if(!card_count)
return OK;
# ifdef INTERRUPT_HARDWARE_FIXED
jgvtr1_interrupt = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
if(!jgvtr1_interrupt)
return ERROR;
# endif
/* start the waveform readback task */
status = taskSpawn( WFDONE_NAME,
WFDONE_PRI,
WFDONE_OPT,
WFDONE_STACK,
(FUNCPTR) jgvtr1DoneTask,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if(status < 0){
status = S_dev_internal;
errMessage(status, "vxWorks taskSpawn failed");
return status;
}
taskwdInsert(status, NULL, NULL);
# ifdef INTERRUPT_HARDWARE_FIXED
status = intConnect( INUM_TO_IVEC(JGVTR1_INT_VEC),
jgvtr1_int_service,
NULL);
if(status != OK)
return S_dev_internal;
sysIntEnable(JGVTR_INT_LEVEL);
# endif
return JGVTR1_SUCCESS;
}
/*
* JGVTR1_DRIVER
*
* initiate waveform read
*
*/
jgvtr1Stat jgvtr1_driver(
unsigned card,
void (*pcbroutine)(void *, unsigned, uint16_t *),
void *parg
)
{
if(card >= jgvtr1_max_card_count)
return S_dev_badSignalNumber;
if(!pjgvtr1_config[card].present)
return S_dev_noDevice;
if(pjgvtr1_config[card].psub)
return S_dev_badRequest;
FASTLOCK(&pjgvtr1_config[card].lock);
*(volatile uint16_t *)JGVTR1BASE(card) = JGVTR1ARM;
pjgvtr1_config[card].pprm = parg;
pjgvtr1_config[card].psub = pcbroutine;
FASTUNLOCK(&pjgvtr1_config[card].lock);
return JGVTR1_SUCCESS;
}
/*
* JGVTR1_INT_SERVICE
*
* signal via the RTK that an interrupt occured from the joerger vtr1
*
*/
#ifdef INTERRUPT_HARDWARE_FIXED
LOCAL void jgvtr1_int_service(void)
{
semGive(jgvtr1_interrupt);
}
#endif
/*
* JGVTR1DONETASK
*
* wait for joerger vtr1 waveform record cycle complete
* and call back to the database with the waveform size and address
*
*/
LOCAL void jgvtr1DoneTask(void)
{
unsigned card;
struct jgvtr1_config *pconfig;
struct jgvtr1_status stat;
static char started = FALSE;
volatile uint16_t *pdata;
volatile uint16_t *pjgdata;
long i;
/* dont allow two of this task */
if(started)
exit(0);
started = TRUE;
while(TRUE){
# ifdef INTERRUPT_HARDWARE_FIXED
semTake(jgvtr1_interrupt, WAIT_FOREVER);
# else
/* ges: changed from 20 ticks to 2 ticks 2/4/91 */
taskDelay(2);
# endif
for( card=0, pconfig = pjgvtr1_config;
card < jgvtr1_max_card_count;
card++, pconfig++){
if(!pconfig->present)
continue;
if(!pconfig->psub)
continue;
stat = *(struct jgvtr1_status *) JGVTR1BASE(card);
/*
* Wait for the module to finish filling its memory
* or a stop trigger
*/
if(!stat.cycle_complete)
continue;
/*
clear ptr to function here so they
can rearm in the callback
*/
pconfig->psub = NULL;
/*
check the first time for module
correctly addressed
card does not respond at STD address
until it has data
*/
if(!pconfig->std_ok){
uint16_t readback;
int status;
status = vxMemProbe(
(char *)JGVTR1DATA(card),
READ,
sizeof(readback),
(char *)&readback);
if(status==ERROR){
errPrintf(
S_dev_badA24,
__FILE__,
__LINE__,
"jgvtr1 card %d incorrectly addressed- use std addr 0X%X",
card,
JGVTR1DATA(card));
pconfig->present = FALSE;
continue;
}
pconfig->std_ok = TRUE;
}
/*
Test for full memory
( card designer does not give a sample count register )
( instead a bus error returned when on the last sample
to test every location is a lot of overhead so a test
for memory full is used for now )
*/
if(!stat.memory_full){
errMessage(S_dev_internal,
"jgvtr1 driver: proceeding with partial mem");
errMessage(S_dev_internal,
"jgvtr1 driver: beware of bus errors");
}
/* copy the data into a local memory buffer */
/* this is to avoid any bus errors */
for(i = 0,
pdata = pconfig->pdata,
pjgdata = (volatile uint16_t *)JGVTR1DATA(card);
i < JRG_MEM_SIZE/sizeof(uint16_t);
i++, pdata++, pjgdata++){
*pdata = *pjgdata;
}
/*
Post waveform to the database
perhaps the size must be the size below+1 ?
(Joerger's documentation is not clear here)
*/
(*pconfig->psub)(pconfig->pprm,JRG_MEM_SIZE,pconfig->pdata);
}
}
}
/*
*
* JGVTR1_IO_REPORT
*
* print status for all cards in the specified joerger
* vtr1 address range
*
*
*/
LOCAL jgvtr1Stat jgvtr1_io_report(unsigned level)
{
unsigned card;
unsigned nelements;
jgvtr1Stat status;
for(card=0; card < wf_num_cards[JGVTR1]; card++){
status = jgvtr1_stat(card,level);
if(status){
continue;
}
if (level >= 2){
printf("enter the number of elements to dump:");
status = scanf("%d",&nelements);
if(status == 1){
jgvtr1_dump(card, nelements);
}
}
}
return JGVTR1_SUCCESS;
}
/*
*
* JGVTR1_STAT
*
* print status for a single card in the joerger vtr1 address range
*
*
*/
jgvtr1Stat jgvtr1_stat(
unsigned card,
int level
)
{
struct jgvtr1_status stat;
jgvtr1Stat status;
/*
internal freq status is bit reversed so I
use a lookup table
*/
static float sample_rate[8] = {
JGVTR1MAXFREQ/(1<<7),
JGVTR1MAXFREQ/(1<<3),
JGVTR1MAXFREQ/(1<<5),
JGVTR1MAXFREQ/(1<<1),
JGVTR1MAXFREQ/(1<<6),
JGVTR1MAXFREQ/(1<<2),
JGVTR1MAXFREQ/(1<<4),
JGVTR1MAXFREQ/(1<<0)};
static char *clock_status[] =
{"ext-clock", "internal-clk"};
static char *cycle_status[] =
{"cycling", "done"};
static char *interrupt_status[] =
{"", "int-pending"};
static char *activity_status[] =
{"", "active"};
static char *memory_status[] =
{"", "mem-full"};
status = vxMemProbe( (char *)JGVTR1BASE(card),
READ,
sizeof(stat),
(char *)&stat);
if(status != OK)
return ERROR;
if (level == 0)
printf("WF: JGVTR1:\tcard=%d \n",card);
else if (level > 0)
printf( "WF: JGVTR1:\tcard=%d Sample rate=%g %s %s %s %s %s \n",
card,
sample_rate[stat.internal_frequency],
clock_status[ stat.internal_clock ],
cycle_status[ stat.cycle_complete ],
interrupt_status[ stat.interrupt ],
activity_status[ stat.active ],
memory_status[ stat.memory_full ]);
return JGVTR1_SUCCESS;
}
/*
* jgvtr1_dump
*
*/
LOCAL jgvtr1Stat jgvtr1_dump(
unsigned card,
unsigned n
)
{
volatile uint16_t *pjgdata;
uint16_t *pread;
uint16_t *pdata;
unsigned nread;
jgvtr1Stat status;
/* Print out the data if user requests it. */
n = min(JRG_MEM_SIZE,n);
pdata = (uint16_t *)malloc(n * (sizeof(*pdata)));
if(!pdata){
return S_dev_noMemory;
}
pread = pdata;
nread = 0;
pjgdata = (volatile uint16_t *)JGVTR1DATA(card);
while(nread <= (n>>1)){
status = vxMemProbe(
(char *)pjgdata,
READ,
sizeof(*pread),
(char *)pread);
if(status<0){
break;
}
nread++;
pread++;
pjgdata++;
}
for(pread=pdata; pread<&pdata[nread]; pread++){
if ((pread-pdata)%8 == 0){
printf("\n\t");
}
printf( "%02X %02X ",
(unsigned char) ((*pread)>>8),
(unsigned char) *pread);
}
printf("\n");
free(pdata);
return JGVTR1_SUCCESS;
}
+43
View File
@@ -0,0 +1,43 @@
/* drvJgvtr1.h */
/* base/src/drv $Id$ */
/*
* Author: Jeff Hill
* Date: 5-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 jgvtr1Stat;
#define JGVTR1_SUCCESS 0
jgvtr1Stat jgvtr1_driver(
unsigned card,
void (*pcbroutine)(void *, unsigned, uint16_t *),
void *parg
);
+484
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{
unsigned short diag;
unsigned short isr;
unsigned short pad1[7];
unsigned short channels[64]; /* odd access causes a bus error ? */
unsigned short controlMemoryAddr;
unsigned short pad2;
unsigned short controlMemoryDataWrite;
unsigned short pad3;
unsigned short controlMemoryDataRead;
unsigned short pad4;
unsigned short lastChannel;
unsigned short pad5;
unsigned short singleScan;
unsigned short pad6;
unsigned short stopScan;
unsigned short pad7;
unsigned short clearControlMemoryAddr;
unsigned short pad8;
unsigned short enableContinuousScanning;
unsigned short pad9;
unsigned short disableContinuousScanning;
unsigned short pad10;
unsigned short enableDoneInt;
unsigned short pad11;
unsigned short disbaleDoneInt;
unsigned short pad12;
unsigned short clearDoneInt;
unsigned short pad13;
unsigned short testDoneInt;
unsigned short 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,
unsigned short *preg,
unsigned 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, 0);
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,
0);
if(status){
epvxiClose(la, KscV215DriverId);
errMessage(status, "KscV215 init failed\n");
return;
}
}
/*
* turn on continuous scan mode
*/
status = KscV215WriteSync(
pA24,
&pA24->enableContinuousScanning,
0);
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,
unsigned short *preg,
unsigned 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
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
);
+1437
View File
File diff suppressed because it is too large Load Diff
+628
View File
@@ -0,0 +1,628 @@
/* 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 unsigned char *) CHIP_ADDR(CARD,CHIP) + MZ8310CMD)
#define MZ8310_DATA_ADDR(CARD,CHIP)\
((volatile unsigned short *) CHIP_ADDR(CARD,CHIP) + MZ8310DATA)
#if 0
#define MZ8310VECBASE(CARD,CHIP)\
((volatile unsigned char *) 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)();
int 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, int level);
LOCAL mz8310Stat mz8310_init_card(unsigned card);
LOCAL mz8310Stat mz8310_setup_int(unsigned card, unsigned channel);
LOCAL mz8310Stat mz8310_io_report(int level);
LOCAL mz8310Stat mz8310_init(void);
LOCAL mz8310Stat mz8310_read_test(int card, int 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(int 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, int 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),
&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(
int *preset, /* TRUE or COMPLEMENT logic */
double *edge0_delay, /* sec */
double *edge1_delay, /* sec */
int card, /* 0 through ... */
int channel, /* 0 through channels on a card */
int *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(int card, int channel)
{
int preset;
double edge0_delay;
double edge1_delay;
int 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 %d %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 %d Interrupt count=%u\n",
channel,
mzconf[card].icf[channel].cnt);
}
return status;
}
/*
* mz8310_one_shot()
*/
mz8310Stat mz8310_one_shot(
int preset, /* TRUE or COMPLEMENT logic */
double edge0_delay, /* sec */
double edge1_delay, /* set */
int card, /* 0 through ... */
int 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 */
)
{
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,
int card,
int chip
)
{
volatile unsigned short *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
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(
int *preset, /* TRUE or COMPLEMENT logic */
double *edge0_delay, /* sec */
double *edge1_delay, /* sec */
int card, /* 0 through ... */
int channel, /* 0 through channels on a card */
int *int_source /* (FALSE)External/(TRUE)Internal src */
);
mz8310Stat mz8310_one_shot(
int preset, /* TRUE or COMPLEMENT logic */
double edge0_delay, /* sec */
double edge1_delay, /* set */
int card, /* 0 through ... */
int 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 */
);
int mz8310_cmd(
unsigned value,
unsigned card,
unsigned chip
);
int mz8310_rdata(int card, int chip);
int mz8310_wdata(
unsigned value,
int card,
int chip
);
+685
View File
@@ -0,0 +1,685 @@
/* drvOms.c */
/* base/src/drv $Id$ */
/*
* subroutines and tasks that are used to interface to the
* Oregon Micro Systems six axis stepper motor drivers
*
* Author: Bob Dalesio
* Date: 12-28-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
* -----------------
* .01 02-07-90 lrd add command to read status
* .02 02-09-90 lrd removed the clamp on the MR command
* .03 03-22-90 lrd added the acceleration
* .04 04-12-90 lrd only allow one record to connect to each motor
* .05 04-28-90 lrd request motor data at 10 Hz. Needed delay to let
* motor start moving
* .06 04-30-90 lrd fix interrupt vectors for more than one motor
* .07 07-31-90 lrd lock the communication to the oms card for
* one user
* .08 08-01-90 lrd fix turn off of auxilary output when move is
* complete
* .09 08-01-90 lrd fix the initialization of the card to only
* enable the buffer full interrupt
* .10 10-23-90 lrd clamp the send value to something the motor
* driver can handle
* .11 11-13-90 lrd add intelligence in looking for an OMS card with
* an encoder
* .12 05-15-91 lrd add initialization of encoder and motor position
* .13 09-05-91 joh updated for v5 vxWorks
* .14 12-10-91 bg added sysBusToLocalAddrs(). Added
* compu_sm_driver.c.
* .15 03-10-92 bg Added level to io_report and gave
* compu_sm_io_report() the ability to print out
* contents of motor_data array if level > 1.
* .16 06-26-92 bg Combined drvOms.c with oms_driver.c
* .17 06-29-92 joh took file pointer arg out of io report
* .18 08-11-92 joh io report format cleanup
* .19 08-02-93 mrk Added call to taskwdInsert
* .20 08-05-93 jbk took out 200000 pulse limit
* .21 02-28-94 mrk Replaced itob by cvtLongToString
* .22 05-05-94 kornke Now supports VMEX-8 and VMEX-44E
* (8 axis s'motors and 4 encoded s'motors)
*/
/* data requests are made from the oms_task at
* a rate of 10Hz when a motor is active
* post every .1 second or not moving
* requests are sent at 10Hz in oms_task
*/
/* drvOms.c - Driver Support Routines for Oms */
#include <vxWorks.h>
#include <stdioLib.h>
#include <sysLib.h> /* library for task support */
#include <taskLib.h>
#include <rngLib.h> /* library for ring buffer support */
#include <semLib.h>
#include <vme.h> /* library to support sysBusToLocalAdrs. */
#include <dbDefs.h>
#include <drvSup.h>
#include <module_types.h>
#include <drvOms.h>
#include <steppermotor.h>
#include <taskwd.h>
#define OMS_INT_LEV 5
/* If any of the following does not exist replace it with #define <> NULL */
static long report();
static long init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvOms={
2,
report,
init};
static long report(level)
int level;
{
oms_io_report(level);
}
static long init()
{
int status;
oms_driver_init();
return(0);
}
/*
* a rate of 10Hz when a motor is active
* post every .1 second or not moving
* requests are sent at 10Hz in oms_task
*/
/* addresses of all motors present */
struct vmex_motor *oms_motor_present[MAX_OMS_CARDS];
char encoder_present[MAX_OMS_CARDS];
static char *localaddr; /* Local address used to address cards. */
/* motor information */
struct oms_motor oms_motor_array[MAX_OMS_CARDS][MAX_OMS_CHANNELS];
/* motor status - returned to the database library routines */
struct motor_data motor_data_array[MAX_OMS_CARDS][MAX_OMS_CHANNELS];
char oms_motor_specifier[MAX_OMS_CHANNELS+1] = {'X','Y','Z','T','U','V'};
/* scan task parameters */
LOCAL SEM_ID oms_wakeup; /* oms_task wakeup semaphore */
LOCAL SEM_ID oms_send_sem; /* oms_task wakeup semaphore */
/* response task variables */
LOCAL SEM_ID oms_resp_sem; /* wakeup semaphore for the resp task */
LOCAL RING_ID oms_resp_q; /* queue of responses */
/* interrupt routine message buffers */
int resp_inx[MAX_OMS_CARDS];
char read_buffer[MAX_OMS_CARDS][34];
/* forward reference. */
VOID oms_reset();
oms_intr(card)
register short card;
{
register struct vmex_motor *pmotor;
register int key;
register char inp_char;
register int *pinx;
key = intLock();
/* pointer to this motor */
if ((pmotor = oms_motor_present[card]) == 0){
intUnlock(key);
return(0);
}
pinx = &resp_inx[card];
/* get the next character */
if (pmotor->status & INPUT_BUFFER_FULL){
/* check for end of command */
inp_char = pmotor->data;
if (((inp_char == 0xa) || (inp_char == 0xd)) && (*pinx > 0)){
/* check if the encoder command caused an error */
if (pmotor->status & (OMS_ENCODER | OMS_CMD_ERROR))
encoder_present[card] = FALSE;
else encoder_present[card] = TRUE;
/* terminate and send the message */
read_buffer[card][*pinx] = 0;
if (rngBufPut(oms_resp_q,read_buffer[card],OMS_MSG_SZ)
!= OMS_MSG_SZ){
logMsg("oms_resp_q full\n");
}else{
semGive (oms_resp_sem);
}
*pinx = 0; /* reset buffer */
/* save printable ascii characters */
}else if ((inp_char >= 0x20) && (inp_char < 0x7f)){
if (*pinx == 0){
read_buffer[card][*pinx] = card;
*pinx += 1;
}
if (*pinx < OMS_MSG_SZ){
read_buffer[card][*pinx] = inp_char;
*pinx += 1;
}else{
logMsg("oms intr buffer full\n");
}
}
}
intUnlock(key);
return(0);
}
/*
* STEPPER MOTOR RESPONSE TASK - REMOVES RESPONSES FROM the INTERRUPT QUEUE
*/
short oms_channel[MAX_OMS_CARDS];
short oms_state[MAX_OMS_CARDS];
char off_msg[40];
int oms_debug = 0;
int oms_compare = 3;
oms_resp_task()
{
unsigned char resp[OMS_MSG_SZ*4];
register struct motor_data *pmotor_data_array;
register struct oms_motor *poms_motor_array;
short *pchannel;
int (*psmcb_routine)();
register short *pstate;
register short card,i;
int temp;
FOREVER {
/* wait for somebody to wake us up */
semTake (oms_resp_sem, WAIT_FOREVER);
/* process requests in the command ring buffer */
while (rngBufGet(oms_resp_q,resp,OMS_MSG_SZ) == OMS_MSG_SZ){
if (oms_debug)
printf("card: %d msg:%s\n",resp[0],&resp[1]);
/* get the card number and pointers to the state and channel */
card = resp[0];
pchannel = &oms_channel[card];
pstate = &oms_state[card];
pmotor_data_array = &motor_data_array[card][*pchannel];
poms_motor_array = &oms_motor_array[card][*pchannel];
/* motor selection */
if (resp[1] == 'A')
{
switch (resp[2])
{
case 'X':
*pchannel = 0;
break;
case 'Y':
*pchannel = 1;
break;
case 'Z':
*pchannel = 2;
break;
case 'T':
*pchannel = 3;
break;
case 'U':
*pchannel = 4;
break;
case 'V':
*pchannel = 5;
break;
case 'R':
*pchannel = 6;
break;
case 'S':
*pchannel = 7;
break;
}
*pstate = 0;
/* position readback */
}else if (resp[1] == 'R'){
if (resp[2] == 'E') *pstate = 1;
else if (resp[2] == 'P') *pstate = 2;
else if (resp[2] == 'A') *pstate = 3;
else *pstate = 0;
/* convert encoder position */
}else if (*pstate == 1){
sscanf(&resp[1],"%d",&temp);
pmotor_data_array->encoder_position = temp;
*pstate = 0;
/* convert motor position */
/* use the motor position for detecting end of motion because */
/* all motors use this, not all motors have encoders */
}else if (*pstate == 2){
sscanf(&resp[1],"%d",&temp);
if ((pmotor_data_array->motor_position == temp)
&& (poms_motor_array->active == TRUE)){
poms_motor_array->stop_count++;
if (poms_motor_array->stop_count >= oms_compare) {
poms_motor_array->active = FALSE;
strcpy(off_msg,"AB\nAN\n");
off_msg[1] = oms_motor_specifier[*pchannel];
oms_send_msg(oms_motor_present[card],off_msg);
poms_motor_array->stop_count = 0;
}
}else{
pmotor_data_array->motor_position = temp;
poms_motor_array->stop_count = 0;
}
*pstate = 0;
/* convert axis status */
}else if (*pstate == 3){
pmotor_data_array->ccw_limit = 0;
pmotor_data_array->cw_limit = 0;
if (resp[1] == 'P'){
pmotor_data_array->direction = 0;
if (resp[3] == 'L'){
pmotor_data_array->ccw_limit= 1;
}
}else{
pmotor_data_array->direction = 1;
if (resp[3] == 'L'){
pmotor_data_array->cw_limit = 1;
}
}
pmotor_data_array->moving = poms_motor_array->active;
*pstate = 0;
/* post every .1 second or not moving */
if ((poms_motor_array->update_count-- <= 0)
|| (pmotor_data_array->moving == 0)){
if (poms_motor_array->callback != 0){
(int)psmcb_routine = poms_motor_array->callback;
(*psmcb_routine)(pmotor_data_array,poms_motor_array->callback_arg);
}
if (pmotor_data_array->moving){
poms_motor_array->update_count = 2;
}else{
poms_motor_array->update_count = 0;
}
}
/* reset state */
}else{
*pstate = 0;
}
}
}
}
oms_task()
{
register short motor_active;
register short card,channel;
char oms_msg[40];
register struct vmex_motor *pmotor;
while(1){
semTake(oms_wakeup, WAIT_FOREVER);
motor_active = TRUE;
while (motor_active){
motor_active = FALSE;
taskDelay(2);
for (channel = 0; channel < MAX_OMS_CHANNELS; channel++){
pmotor = oms_motor_present[0];
for (card = 0; card < MAX_OMS_CARDS; card++,pmotor++){
if (pmotor == 0) continue;
if (oms_motor_array[card][channel].active){
motor_active = TRUE;
/* request status data */
if ((channel <= 3) && (encoder_present[card]))
strcpy(oms_msg,"A?\nRE\nRP\nRA\n");
else
strcpy(oms_msg,"A?\nRP\nRA\n");
oms_msg[1] = oms_motor_specifier[channel];
oms_send_msg(oms_motor_present[card],oms_msg);
}
}
}
}
}
}
/*
* OMS_DRIVER_INIT
*
* initialize all oms drivers present
*/
oms_driver_init(){
struct vmex_motor *pmotor;
short i,j,got_one;
int status;
short dummy;
char oms_init_msg[20];
int taskId;
for (i = 0; i < MAX_OMS_CARDS; i++){
resp_inx[i] = 0;
}
/* find all cards present */
got_one = FALSE;
status = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,sm_addrs[OMS_6AXIS], &localaddr);
if (status != OK){
logMsg("Addressing error in oms driver\n");
return(ERROR);
}
rebootHookAdd(oms_reset);
pmotor = (struct vmex_motor *)localaddr;
for (i = 0; i < MAX_OMS_CARDS; i++,pmotor++){
if (vxMemProbe(pmotor,READ,sizeof(short),&dummy) == OK){
got_one = TRUE;
/* intialize the motor */
pmotor->control = 0;
/* interrupt vector */
pmotor->vector = 0x80+i;
intConnect(((0x80+i)*4),oms_intr,i);
sysIntEnable(OMS_INT_LEV);
/* enable interrupt on input buffer full */
pmotor->control |= 0xa0;
/* mark the motor card as present */
oms_motor_present[i] = pmotor;
encoder_present[i] = TRUE;
}else{
/* mark the motor card as not present */
oms_motor_present[i] = 0;
}
for (j = 0; j < MAX_OMS_CHANNELS; j++){
oms_motor_array[i][j].active = FALSE;
oms_motor_array[i][j].callback = 0;
motor_data_array[i][j].encoder_position = 0;
motor_data_array[i][j].motor_position = 0;
}
}
if (got_one){
/* initialize the command task ring buffer */
if ((oms_resp_q = rngCreate(OMS_RESP_Q_SZ)) == (RING_ID)NULL)
panic ("oms_driver_init: oms_resp_q not created\n");
/* initialize the oms response task semaphore */
if(!(oms_resp_sem=semBCreate(SEM_Q_FIFO,SEM_EMPTY)))
errMessage(0,"semBcreate failed in oms_driver_init");
/* intialize the data request wakeup semaphore */
if(!(oms_wakeup=semBCreate(SEM_Q_FIFO,SEM_EMPTY)))
errMessage(0,"semBcreate failed in oms_driver_init");
/* oms card mutual exclusion semaphore */
if(!(oms_send_sem=semBCreate(SEM_Q_FIFO,SEM_FULL)))
errMessage(0,"semBcreate failed in oms_driver_init");
/* spawn the motor data request task */
taskId = taskSpawn("oms_task",42,VX_FP_TASK,8000,oms_task);
taskwdInsert(taskId,NULL,NULL);
/* spawn the motor data request task */
taskId = taskSpawn("oms_resp_task",42,VX_FP_TASK,8000,oms_resp_task);
taskwdInsert(taskId,NULL,NULL);
/* enable echo on each motor that is present */
pmotor = (struct vmex_motor *)localaddr;
for (i = 0; i < MAX_OMS_CARDS; i++,pmotor++){
if (oms_motor_present[i]){
/* give it the initialization commands */
oms_send_msg(pmotor,"EN\nWY\n");
}
}
}
return(0);
}
/*
* OMS_DRIVER
*
* interface routine called from the database library
*/
#define MOTOR_POS 1
oms_driver(card,channel,value_flag,arg1,arg2)
register short card;
register short channel;
short value_flag;
register int arg1;
int arg2;
{
char oms_move_msg[100];
short i,count;
if (!oms_motor_present[card]) return(-1);
switch (value_flag){
case (SM_MODE): /* only supports positional mode */
break;
case (SM_VELOCITY):
/* set the velocity */
motor_data_array[card][channel].velocity = arg1;
strcpy(oms_move_msg,"A?\nVL");
oms_move_msg[MOTOR_POS] = oms_motor_specifier[channel];
count = cvtLongToString(arg1,&oms_move_msg[5]);
strcat(oms_move_msg,"\n");
oms_send_msg(oms_motor_present[card],oms_move_msg);
/* set the acceleration */
strcpy(oms_move_msg,"A?\nAC");
oms_move_msg[MOTOR_POS] = oms_motor_specifier[channel];
count = cvtLongToString(arg2,&oms_move_msg[5]);
strcat(oms_move_msg,"\n");
oms_send_msg(oms_motor_present[card],oms_move_msg);
break;
case (SM_MOVE):
/* move the motor */
strcpy(oms_move_msg,"A?\nAF\nMR");
oms_move_msg[1] = oms_motor_specifier[channel];
count = cvtLongToString(arg1,&oms_move_msg[8]);
strcat(oms_move_msg,"\nGO\n");
oms_send_msg(oms_motor_present[card],oms_move_msg);
/* set the motor to active */
oms_motor_array[card][channel].active = TRUE;
/* wakeup the oms task */
semGive(oms_wakeup);
break;
case (SM_MOTION):
/* stop the motor */
strcpy(oms_move_msg,"A?ST\n");
if (arg1 == 0){
oms_move_msg[1] = oms_motor_specifier[channel];
}else{
return(0);
}
oms_send_msg(oms_motor_present[card],oms_move_msg);
/* wakeup the oms task */
semGive(oms_wakeup);
break;
case (SM_CALLBACK):
i = 0;
if (oms_motor_array[card][channel].callback != 0) return(-1);
oms_motor_array[card][channel].callback = arg1;
oms_motor_array[card][channel].callback_arg = arg2;
break;
/* reset encoder and motor positions to zero */
case (SM_SET_HOME):
/* load the position to be zero */
strcpy(oms_move_msg,"A?\nLP0\n");
oms_move_msg[1] = oms_motor_specifier[channel];
oms_send_msg(oms_motor_present[card],oms_move_msg);
/* set the motor to active */
oms_motor_array[card][channel].active = TRUE;
/* wakeup the oms task */
semGive(oms_wakeup);
break;
case (SM_ENCODER_RATIO):
/* set the encoder ratio */
/* The "ER" command changes how far a pulse will move the */
/* motor. */
/* As this is not the desired action this command is not */
/* implemented here. */
break;
case (SM_READ):
/* set the motor to active */
oms_motor_array[card][channel].active = TRUE;
/* wakeup the oms task */
semGive(oms_wakeup);
break;
}
return(0);
}
char last_msg[80];
int oms_count,oms_icount,oms_illcmd,oms_sleep,oms_isleep;
/*
* OMS_SEND_MSG
*
* Gives messages to the OMS card
*/
oms_send_msg(pmotor,pmsg)
struct vmex_motor *pmotor;
register char *pmsg;
{
int i;
i = 0;
/* take the mutual exclusion semaphore */
semTake(oms_send_sem, WAIT_FOREVER);
while (*pmsg){
if (pmotor->status & 0x01){
oms_illcmd++;
while ((pmotor->status & TRANSMIT_BUFFER_EMPTY) == 0){
oms_icount++;
if ((oms_icount % 5) == 0){
oms_isleep++;
/* A taskDelay makes a 68040 wait frequently */
/*taskDelay(1);*/
}
}
pmotor->data = 0x19; /* reset */
}else{
while ((pmotor->status & TRANSMIT_BUFFER_EMPTY) == 0){
oms_count++;
if ((oms_count % 5) == 0){
oms_sleep++;
/* A taskDelay makes a 68040 wait frequently */
/*taskDelay(1);*/
}
}
pmotor->data = *pmsg;
pmsg++;
}
}
/* release the mutual exclusion semaphore */
semGive(oms_send_sem);
}
oms_io_report(level)
short int level;
{
register short int i,j;
for (i = 0; i < MAX_OMS_CARDS; i++) {
if (oms_motor_present[i]){
printf("SM: OMS:\tcard %d\n",i);
for (j = 0; j < MAX_OMS_CHANNELS; j++){
if (level > 0)
oms_sm_stat(i,j);
}
}
}
}
VOID oms_sm_stat(card,channel)
short int card,channel;
{
printf("SM: OMS: Card = %d,channel = %d\n",card,channel);
printf("\tCW limit = %d\tCCW limit = %d\tMoving = %d\tDirection = %d\n",
motor_data_array[card][channel].cw_limit,
motor_data_array[card][channel].ccw_limit,
motor_data_array[card][channel].moving,
motor_data_array[card][channel].direction);
printf("\tConstant Velocity = %ld\tVelocity = %ld\t \n",
motor_data_array[card][channel].constant_velocity,
motor_data_array[card][channel].velocity);
printf("\tAcceleration = %ld\tEncoder Position = %ld\tMotor Position = %ld\n",
motor_data_array[card][channel].accel,
motor_data_array[card][channel] .encoder_position,
motor_data_array[card][channel].motor_position);
}
/*
*
* Disables interrupts. Called on CTL X reboot.
*
*/
VOID oms_reset(){
short card;
struct vmex_motor *pmotor;
short dummy;
pmotor = (struct vmex_motor *)localaddr;
for (card = 0; card < MAX_OMS_CARDS; card++,pmotor++){
if(vxMemProbe(pmotor,READ,sizeof(short),&dummy) == OK){
pmotor->control &= 0x5f;
}
}
}
+74
View File
@@ -0,0 +1,74 @@
/* oms_sm_driver.h */
/* base/src/drv $Id$ */
/*
* headers that are used to interface to the
* Oregon Micro Systems six axis stepper motor drivers
*
* Author: Bob Dalesio
* Date: 02-25-90
*
* 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-12-90 lrd only allow one connection to each motor
* .02 11-13-90 lrd add status bit definitions for encoder commands
* .03 05-05-94 kornke supports 8 OMS channels now
*/
#define MAX_OMS_CARDS 8
#define MAX_OMS_CHANNELS 8
/* motor information */
struct oms_motor{
short active; /* flag to tell the oms_task if the motor is moving */
int callback; /* routine in database library to call with status */
int callback_arg; /* argument to callback routine */
short update_count;
short stop_count;
};
#define MIRQE 0x80
#define TRANSMIT_BUFFER_EMPTY 0x40
#define INPUT_BUFFER_FULL 0x20
#define MDONE 0x10
#define OMS_ENCODER 0x04
#define OMS_CMD_ERROR 0x01
struct vmex_motor{
char unused0;
char data;
char unused1;
char done;
char unused2;
char control;
char unused3;
char status;
char unused4;
char vector;
char unused5[6];
};
/* oms message defines */
#define OMS_MSG_SZ 32 /* response message size */
#define OMS_RESP_Q_SZ (OMS_MSG_SZ*500) /* response ring buffer size */
+550
View File
@@ -0,0 +1,550 @@
/* base/src/drv $Id$ */
/*
* Author: John Winans
* Date: 04-13-92
* EPICS R/S-232 driver for the VxWorks's tty 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 DRVRS232_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 <drvRs232.h>
#include <drvTy232.h>
int drv232Debug = 0;
static void callbackAbortSerial();
static void dogAbortSerial();
/******************************************************************************
*
******************************************************************************/
#define RSLINK_PRI 50
#define RSLINK_OPT VX_FP_TASK|VX_STDIO
#define RSLINK_STACK 5000
/******************************************************************************
*
******************************************************************************/
static long
report()
{
printf("Report for RS-232 driver\n");
return(OK);
}
/******************************************************************************
*
******************************************************************************/
static long
init(pparms)
msgDrvIniParm *pparms;
{
if (drv232Debug)
printf("Init for 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];
devTy232Link *pdevTy232Link;
if (drv232Debug)
printf("RS-232 genXact entered for link %d, addr %d, parm %s\n", p->plink->value.gpibio.link, p->plink->value.gpibio.addr, p->plink->value.gpibio.parm);
p->pmsgXact->phwpvt = p->pmsgXact->pparmBlock->pmsgHwpvt;
while ((p->pmsgXact->phwpvt != NULL) && (stat == -1))
{
pdevTy232Link = (devTy232Link *)(p->pmsgXact->phwpvt->pmsgLink->p);
if ((pdevTy232Link->link == p->plink->value.gpibio.link)
&& (pdevTy232Link->port == p->plink->value.gpibio.addr))
{
if (pdevTy232Link->pparmBlock != p->pmsgXact->pparmBlock)
{
sprintf(message, "%s: Two different devices on same RS-232 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);
}
p->pmsgXact->callback.callback = NULL;
p->pmsgXact->psyncSem = NULL;
if (sscanf(p->plink->value.gpibio.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.gpibio.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 (drv232Debug)
printf("rs232-genHwpvt entered\n");
p->pmsgHwpvt->pmsgLink = drv232Block.pmsgLink;
while ((p->pmsgHwpvt->pmsgLink != NULL) && (stat == ERROR))
{
if ((((devTy232Link *)(p->pmsgHwpvt->pmsgLink->p))->link == p->plink->value.gpibio.link)
&& (((devTy232Link *)(p->pmsgHwpvt->pmsgLink->p))->port == p->plink->value.gpibio.addr))
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];
devTy232Link *pdevTy232Link;
if (drv232Debug)
printf("In RS-232's genLink, link = %d, addr = %d\n", p->plink->value.gpibio.link,p->plink->value.gpibio.addr);
switch (p->op) {
case MSG_GENLINK_CREATE:
if ((p->pmsgLink->p = malloc(sizeof(devTy232Link))) == NULL)
return(ERROR);
pdevTy232Link = (devTy232Link *)(p->pmsgLink->p);
pdevTy232Link->link = p->plink->value.gpibio.link;
pdevTy232Link->port = p->plink->value.gpibio.addr;
pdevTy232Link->pparmBlock = p->pparmBlock;
if ((pdevTy232Link->doggie = wdCreate()) == NULL)
{
printf("RS-232 driver can't create a watchdog\n");
/* errMessage(******, message); */
return(ERROR);
}
sprintf(name, "/tyCo/%d", p->plink->value.gpibio.addr);
if (drv232Debug)
printf ("in genlink opening >%s<, baud %d\n", name, ((devTy232ParmBlock *)(p->pparmBlock->p))->baud);
if ((((devTy232Link *)(p->pmsgLink->p))->ttyFd = open(name, O_RDWR, 0)) != -1)
{
if (drv232Debug)
printf("Successful open w/fd=%d\n", pdevTy232Link->ttyFd);
/* set baud rate and unbuffered mode */
(void) ioctl (pdevTy232Link->ttyFd, FIOBAUDRATE, ((devTy232ParmBlock *)(p->pparmBlock->p))->baud);
(void) ioctl (pdevTy232Link->ttyFd, FIOSETOPTIONS, ((devTy232ParmBlock *)(p->pparmBlock->p))->ttyOptions);
pdevTy232Link->callback.callback = callbackAbortSerial;
pdevTy232Link->callback.priority = priorityHigh;
pdevTy232Link->callback.user = (void *) pdevTy232Link;
return(OK);
}
else
{
printf("RS-232 genLink failed to open the tty port\n");
free(p->pmsgLink->p);
return(ERROR);
}
case MSG_GENLINK_ABORT:
if (drv232Debug)
printf("RS-232 genLink called with abort status\n");
pdevTy232Link = (devTy232Link *)(p->pmsgLink->p);
/* 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);
}
static void
dogAbortSerial(pdevTy232Link)
devTy232Link *pdevTy232Link;
{
logMsg("RS-232 driver watch-dog timeout on link %d, port %d, fd=%d\n", pdevTy232Link->link, pdevTy232Link->port, pdevTy232Link->ttyFd);
/* Annoying vxWorks implementation... can't IOCTL from here */
callbackRequest(&(pdevTy232Link->callback));
}
static void
callbackAbortSerial(p)
CALLBACK *p;
{
((devTy232Link *)(p->user))->dogAbort = TRUE;
ioctl(((devTy232Link *)(p->user))->ttyFd, FIOCANCEL);
/* I am not sure if I should really do this, but... */
ioctl(((devTy232Link *)(p->user))->ttyFd, FIOFLUSH);
}
/******************************************************************************
*
* This function is used to write a string of characters out to an RS-232
* device.
*
******************************************************************************/
static long
drvWrite(pxact, pwrParm)
msgXact *pxact;
msgStrParm *pwrParm;
{
devTy232Link *pdevTy232Link = (devTy232Link *)(pxact->phwpvt->pmsgLink->p);
int len;
char *out;
char in;
if (wdStart(pdevTy232Link->doggie, ((devTy232ParmBlock *)(pxact->pparmBlock->p))->dmaTimeout, dogAbortSerial, pdevTy232Link) == ERROR)
{
printf("RS-232 driver can not start watchdog timer\n");
/* errMessage(***,message); */
pxact->status = XACT_IOERR;
return(pxact->status);
}
if (((devTy232ParmBlock *)(pxact->pparmBlock->p))->flags & ECHO)
{ /* ping-pong the characters out */
/*BUG ??? This will only work if we are sure that the RX buffer is clean */
ioctl(pdevTy232Link->ttyFd, FIORFLUSH);
out = pwrParm->buf;
while ((*out != '\0') && (pxact->status == XACT_OK))
{
if (drv232Debug > 5)
printf("out >%c<\n", *out);
if (write(pdevTy232Link->ttyFd, out, 1) != 1)
{
printf("RS-232 write error on link %d, port %d\n", pdevTy232Link->link, pdevTy232Link->port);
pxact->status = XACT_IOERR;
}
else
{
if (read(pdevTy232Link->ttyFd, &in, 1) != 1)
{
printf("Read problem encountered in echo reading mode of a write operation\n");
if (pdevTy232Link->dogAbort)
pxact->status = XACT_TIMEOUT;
else
pxact->status = XACT_IOERR;
}
else
{
if (*out != in)
printf("echo response out of sync! sent >%c< got >%c<\n", *out, in);
if (drv232Debug > 5)
printf("in >%c<\n", in);
if ((*out == '\r') && (((devTy232ParmBlock *)(pxact->pparmBlock->p))->flags & CRLF))
{
if (read(pdevTy232Link->ttyFd, &in, 1) != 1)
{
printf("Read problem encountered in echo reading mode of a write operation\n");
if (pdevTy232Link->dogAbort)
pxact->status = XACT_TIMEOUT;
else
pxact->status = XACT_IOERR;
}
else
{
if (drv232Debug > 5)
printf("in >%c<\n", in);
}
}
}
}
out++;
}
}
else
{
if (pwrParm->len == -1)
len = strlen(pwrParm->buf);
else
len = pwrParm->len;
if (drv232Debug > 4)
printf("block-writing >%s<\n", pwrParm->buf);
if (write(pdevTy232Link->ttyFd, pwrParm->buf, len) != len)
{
printf("RS-232 write error on link %d, port %d\n", pdevTy232Link->link, pdevTy232Link->port);
pxact->status = XACT_IOERR;
}
}
if (wdCancel(pdevTy232Link->doggie) == ERROR)
printf("Can not cancel RS-232 watchdog timer\n");
return(pxact->status);
}
/******************************************************************************
*
* This function is used to read a string of characters from an RS-232 device.
*
******************************************************************************/
static long
drvRead(pxact, prdParm)
msgXact *pxact;
msgStrParm *prdParm;
{
devTy232Link *pdevTy232Link = (devTy232Link *)(pxact->phwpvt->pmsgLink->p);
int len;
int clen;
char *ch;
int flags;
int eoi;
devTy232ParmBlock *pdevTy232ParmBlock = (devTy232ParmBlock *)(pxact->pparmBlock->p);
pdevTy232Link->dogAbort = FALSE;
if (wdStart(pdevTy232Link->doggie, pdevTy232ParmBlock->dmaTimeout, dogAbortSerial, pdevTy232Link) == ERROR)
{
printf("RS-232 driver can not start watchdog timer\n");
/* errMessage(***,message); */
pxact->status = XACT_IOERR;
return(pxact->status);
}
ch = prdParm->buf;
len = prdParm->len - 1;
flags = pdevTy232ParmBlock->flags;
/* BUG -- This should have a timeout check specified in here */
if ((pdevTy232ParmBlock->eoi != -1) || (flags & KILL_CRLF))
{
eoi = 0;
while ((!eoi) && (len > 0))
{
if (read(pdevTy232Link->ttyFd, ch, 1) != 1)
{
printf("Read problem encountered in eoi/KILL_CRLF reading mode\n");
if (pdevTy232Link->dogAbort)
pxact->status = XACT_TIMEOUT;
else
pxact->status = XACT_IOERR;
eoi = 1;
}
else
{
if (drv232Debug > 6)
printf("in >%c<\n", *ch);
if (*ch == pdevTy232ParmBlock->eoi)
eoi = 1;
if (!(flags & KILL_CRLF) || ((*ch != '\n') && (*ch != '\r')))
{
ch++;
len--; /* To count the \n's and \r's or not to count... */
}
}
}
if (len == 0)
{
printf("buffer length overrun during read operation\n");
pxact->status = XACT_LENGTH;
}
*ch = '\0';
}
else
{ /* Read xact->rxLen bytes from the device */
while(len)
{
clen = read(pdevTy232Link->ttyFd, ch, len);
if (pdevTy232Link->dogAbort)
{
printf("Read problem encountered in raw mode\n");
pxact->status = XACT_TIMEOUT;
len = 0;
}
else
{
len -= clen;
ch += clen;
}
}
*ch = '\0';
}
if (drv232Debug)
printf("drvRead: got >%s<\n", prdParm->buf);
if (wdCancel(pdevTy232Link->doggie) == ERROR)
printf("Can not cancel RS-232 watchdog timer, dogAbort=%d \n", pdevTy232Link->dogAbort);
return(pxact->status);
}
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:
printf("drv232Block.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: /* BUG -- finish this routine! */
return(ERROR);
}
return(ERROR);
}
msgDrvBlock drv232Block = {
"RS232",
RSLINK_PRI,
RSLINK_OPT,
RSLINK_STACK,
NULL,
drvWrite,
drvRead,
drvIoctl
};
+290
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
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
);
+246
View File
@@ -0,0 +1,246 @@
/* 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 <module_types.h>
#include <drvMz8310.h>
struct pulse{
double offset;
double width;
};
/*
*
* time_driver_read()
*
*
*/
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 int card;
unsigned int channel;
unsigned int card_type;
unsigned int *int_source;
int *preset;
struct pulse *pulses;
unsigned int *npulses;
unsigned int 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;
}
logMsg("time_driver: No support for that type of timing card\n");
return ERROR;
}
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)();
unsigned int 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;
}
logMsg("time_driver: No support for that type of timing card\n");
return ERROR;
}
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;
logMsg( "wrote: preset %x internal-clk %x delay %f width %f \n",
preset,
int_source,
pulses.offset,
pulses.width);
logMsg( "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;
}
+203
View File
@@ -0,0 +1,203 @@
/* base/src/drv $Id$ */
/*
* subroutines that are used to interface to the vme analog output cards
*
* Author: Bob Dalesio
* Date: 9-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 11-09-88 lrd add LED light status to Ziomek-085
* .02 02-08-89 lrd addresses from module_types.h
* use 085 structure
* .03 03-17-89 lrd add ao_read routine
* .04 03-29-89 lrd return correct status on write
* .05 11-20-89 joh added call to the at5 vxi driver
* .06 06-08-90 mrk fixed bug (R Daly found) for VMI4100
* .07 10-31-91 bg broke vmi4100 driver out of ao_driver.c
* broke vmi4100 code out of io_report and
* created vmi400_io_report()
* .08 01-10-92 bg Added levels to io_report and warning message
* that raw values cannot be read from vmi4100
* card even it the level is 1.
* .09 08-05-92 joh arguments to init routine now conform with the
* standard
* .10 08-05-92 joh added EPICS driver dispatch table
* .11 08-05-92 joh moved parameters from ao_driver.h to here
* .12 08-11-92 joh num of cards now dyn configurable
* .13 08-24-93 mrk removed use of variable base_addr
*/
static char *sccsID = "@(#)drvVmi4100.c 1.5\t8/27/93";
#include <vxWorks.h>
#include <vme.h>
#include <dbDefs.h>
#include <drvSup.h>
#include "module_types.h"
/* VMIVME 4100 defines */
#define MAX_AO_VMI_CARDS (ao_num_cards[VMI4100])
#define VMI_MAXCHAN (ao_num_channels[VMI4100])
#define VMI_ENABLE_OUT 0xc100 /*Fail LED off, enable P3 output.*/
/* memory structure of the Xycom 4100 Interface */
union aoVMI{
unsigned short csr;
unsigned short data[16];
};
long vmi4100_io_report();
long vmi4100_init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvVmi4100={
2,
vmi4100_io_report,
vmi4100_init};
LOCAL
unsigned short **pao_vmi4100;
LOCAL
int vmi4100_addr;
/*
* vmi4100_init
*
* intialize the VMI analog outputs
*/
long vmi4100_init()
{
register unsigned short **pcards_present;
short shval;
int status;
register union aoVMI *pcard;
register short i;
pao_vmi4100 = (unsigned short **)
calloc(MAX_AO_VMI_CARDS, sizeof(*pao_vmi4100));
if(!pao_vmi4100){
return ERROR;
}
pcards_present = pao_vmi4100;
if ((status = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,ao_addrs[VMI4100], &vmi4100_addr)) != OK){
printf("Addressing error in vmi4100 driver\n");
return ERROR;
}
pcard = (union aoVMI *)((int)vmi4100_addr);
/* mark each card present into the card present array */
for (i = 0; i < ao_num_cards[VMI4100]; i++, pcard+= VMI_MAXCHAN, pcards_present += 1) {
if (vxMemProbe(pcard,READ,sizeof(short),&shval) == OK) {
*pcards_present = (unsigned short *)pcard;
pcard->csr = VMI_ENABLE_OUT;
}
else{
*pcards_present = 0;
}
}
return OK;
}
/*
* vmi4100_driver
*
* VMI4100 analog output driver
*/
vmi4100_driver(card,chan,prval,prbval)
register unsigned short card;
register unsigned short chan;
unsigned short *prval;
unsigned short *prbval;
{
register union aoVMI *paoVMI;
/* check on the card and channel number as kept in module_types.h */
if ((paoVMI= (union aoVMI *)pao_vmi4100[card]) == 0)
return(-1);
paoVMI->data[chan] = *prval;
return (0);
}
/*
* vmi4100_read
*
* VME analog output driver
*/
vmi4100_read(card,chan,pval)
register unsigned short card;
register unsigned short chan;
unsigned short *pval;
{
register unsigned short *pcard;
/* check on the card and channel number as kept in module_types.h */
*pval = 0; /* can't read the VMIC 4100 - good design! */
return (-1);
}
/*
* vmi4100_io_report
*
* VME analog output driver
*/
long vmi4100_io_report(level)
short int level;
{
register int i;
for (i = 0; i < MAX_AO_VMI_CARDS; i++){
if (pao_vmi4100[i]){
printf("AO: VMI4100: card %d ",i);
if(level >0){
printf("VMI4100 card cannot be read.\n");
}
else
printf("\n");
}
}
return OK;
}
+179
View File
@@ -0,0 +1,179 @@
/*
* initialize the Xycom SRM010 bus controller card
*/
/* base/src/drv $Id$ */
/* Author: Betty Ann Gunther
* Date: 06-30-29
* Initialize xy010 bus controller
*
* 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:
* -----------------
* .00 08-11-92 joh Verify the xy010's id to prevent confusion
* with the mv167's GCSR which with an unmodified
* sysLib.c will show up in the xy010's addr
* space
* .01 08-11-92 joh Moved base addr to module_types.h
* ...
*/
static char *sccsID = "@(#)drvXy010.c 1.3\t6/3/93";
#include <vxWorks.h>
#include <vme.h>
#include <drvSup.h>
#include <module_types.h>
/*
* These will hopefully go away
* as the drivers become more autonomous
*/
static long xy010_id_check(char *);
static long xy010_io_report(int);
static long xy010_init(void);
static long xy010_map(void);
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvXy010={
2,
xy010_io_report,
xy010_init};
#define CSR_ADDR 0x81
#define XY010_ID "VMEIDXYC010"
#define XY_LED 0x3 /* set the Xycom status LEDs to OK */
LOCAL char *xy010_addr;
/*
* initialize the Xycom SRM010 bus controller card
*/
long
xy010_init()
{
char *pctlreg;
if(xy010_map()<0){
return ERROR;
}
if(xy010_id_check(xy010_addr)<0){
return OK;
}
/* Pointer to status control register. */
pctlreg = xy010_addr + CSR_ADDR;
*pctlreg = XY_LED;
return OK;
}
/*
*
* xy010_map()
*
*
*/
LOCAL
long xy010_map()
{
int status;
status = sysBusToLocalAdrs(
VME_AM_SUP_SHORT_IO,
xy010ScA16Base,
&xy010_addr);
if (status < 0){
printf("%s: xy010 A16 base addr map failed\n", __FILE__);
return ERROR;
}
return OK;
}
/*
*
* xy010_id_check()
*
*
*/
LOCAL
long xy010_id_check(pBase)
char *pBase;
{
char *pID;
char *pCmp;
char ID;
int status;
pID = pBase;
pCmp = XY010_ID;
while(*pCmp){
pID++; /* ID chars stored at odd addr */
status = vxMemProbe(pID, READ, sizeof(ID), &ID);
if(status < 0){
return ERROR;
}
if(*pCmp != ID){
return ERROR;
}
pID++;
pCmp++;
}
return OK;
}
/*
*
* xy010_io_report()
*
*
*/
long xy010_io_report(int level)
{
char id;
if(xy010_map()<0){
return ERROR;
}
if (xy010_id_check(xy010_addr) == OK) {
printf("SC: XY010:\tcard 0\n");
}
return OK;
}
+185
View File
@@ -0,0 +1,185 @@
/* xy210_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 bi_io_report
* .04 03-09-92 bg added levels to xy210_io_report. Gave
* xy210_io_report the ability to read raw
* values from card if level > 1
* .05 08-10-92 joh merged include file
* .06 08-25-92 mrk made masks a macro
* .07 08-25-92 mrk replaced bi_driver by xy210_driver
* .08 09-15-93 mrk Made report shorter
*/
/*
* 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;
} drvXy210={
2,
report,
init};
static long report(level)
int level;
{
xy210_io_report(level);
return(0);
}
static long init()
{
xy210_driver_init();
return(0);
}
static char SccsId[] = "@(#)drvXy210.c 1.5\t9/20/93";
#define MAX_XY_BI_CARDS (bi_num_cards[XY210])
/* Xycom 210 binary input memory structure */
/* Note: the high and low order words are switched from the io card */
struct bi_xy210{
char begin_pad[0xc0]; /* nothing until 0xc0 */
/* unsigned short csr; */ /* control status register */
/* char pad[0xc0-0x82]; */ /* get to even 32 bit boundary */
unsigned short low_value; /* low order 16 bits value */
unsigned short high_value; /* high order 16 bits value */
char end_pad[0x400-0xc0-4]; /* pad until next card */
};
/* pointers to the binary input cards */
struct bi_xy210 **pbi_xy210s; /* Xycom 210s */
/* test word for forcing bi_driver */
int bi_test;
static char *xy210_addr;
/*
* BI_DRIVER_INIT
*
* intialization for the binary input cards
*/
xy210_driver_init(){
int bimode;
int status;
register short i;
struct bi_xy210 *pbi_xy210;
pbi_xy210s = (struct bi_xy210 **)
calloc(MAX_XY_BI_CARDS, sizeof(*pbi_xy210s));
if(!pbi_xy210s){
return ERROR;
}
/* initialize the Xycom 210 binary input cards */
/* base address of the xycom 210 binary input cards */
if ((status = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,bi_addrs[XY210],&xy210_addr)) != OK){
printf("Addressing error in xy210 driver\n");
return ERROR;
}
pbi_xy210 = (struct bi_xy210 *)xy210_addr;
/* determine which cards are present */
for (i = 0; i <bi_num_cards[XY210]; i++,pbi_xy210++){
if (vxMemProbe(pbi_xy210,READ,sizeof(short),&bimode) == OK){
pbi_xy210s[i] = pbi_xy210;
} else {
pbi_xy210s[i] = 0;
}
}
return (0);
}
/*
* XY210_DRIVER
*
* interface to the xy210 binary inputs
*/
xy210_driver(card, mask, prval)
register unsigned short card;
unsigned int mask;
register unsigned int *prval;
{
register unsigned int work;
/* verify card exists */
if (!pbi_xy210s[card]){
return (-1);
}
/* read */
work = (pbi_xy210s[card]->high_value << 16) /* high */
+ pbi_xy210s[card]->low_value; /* low */
/* apply mask */
*prval = work & mask;
return (0);
}
void xy210_io_report(level)
short int level;
{
int card;
unsigned int value;
for (card = 0; card < bi_num_cards[XY210]; card++){
if (pbi_xy210s[card]){
value = (pbi_xy210s[card]->high_value << 16) /* high */
+ pbi_xy210s[card]->low_value; /* low */
printf("BI: XY210: card %d value=0x%08.8x\n",card,value);
}
}
}
+220
View File
@@ -0,0 +1,220 @@
/* xy220_driver.c */
/* 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 xy220 driver out of bo_driver.c
* broke xy220 code out of io_report and
* created xy220_io_report().
* Added sysBusToLocalAdrs.
* .02 02-03-92 bg Gave xy220_io_report the ability to
* read raw values from card if level > 1.
* .03 08-10-92 joh merged potions of bo_driver.h
* .04 08-25-92 mrk made masks a macro
*/
static char SccsId[] = "@(#)drvXy220.c 1.6\t9/20/93";
/*
* 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;
} drvXy220={
2,
report,
init};
static long report(level)
int level;
{
xy220_io_report(level);
return(0);
}
static long init()
{
xy220_driver_init();
return(0);
}
#define XY_LED 0x3 /* set the Xycom status LEDs to OK */
#define XY_SOFTRESET 0x10 /* reset the IO card */
/* maximum number of VME binary output cards per IOC */
#define MAX_XY220_BO_CARDS bo_num_cards[XY220]
/* Xycom 220 binary output memory structure */
struct bo_xy220{
char begin_pad[0x80]; /* nothing until 0x80 */
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[0x400-0x80-6]; /* pad until next card */
};
/* pointers to the binary output cards */
struct bo_xy220 **pbo_xy220s; /* Xycom 220s */
/*
* XY220_DRIVER_INIT
*
* intialization for the xy220 binary output cards
*/
int xy220_driver_init(){
int bomode;
int status;
register short i;
struct bo_xy220 *pbo_xy220;
pbo_xy220s = (struct bo_xy220 **)
calloc(MAX_XY220_BO_CARDS, sizeof(*pbo_xy220s));
if(!pbo_xy220s){
return ERROR;
}
/* initialize the Xycom 220 binary output cards */
/* base address of the xycom 220 binary output cards */
status = sysBusToLocalAdrs(
VME_AM_SUP_SHORT_IO,
bo_addrs[XY220],
&pbo_xy220);
if (status != OK){
printf("%s: xy220 A16 base map failure\n", __FILE__);
return ERROR;
}
/* determine which cards are present */
for (i = 0; i < MAX_XY220_BO_CARDS; i++,pbo_xy220++){
if (vxMemProbe(pbo_xy220,READ,sizeof(short),&bomode) == OK){
pbo_xy220s[i] = pbo_xy220;
pbo_xy220s[i]->csr = XY_SOFTRESET;
pbo_xy220s[i]->csr = XY_LED;
}else{
pbo_xy220s[i] = 0;
}
}
return(0);
}
/*
* XY220_DRIVER
*
* interface to the xy220 binary outputs
*/
int xy220_driver(card,val,mask)
register unsigned short card;
register unsigned int *val;
unsigned int mask;
{
register unsigned int work;
/* verify card exists */
if (!pbo_xy220s[card])
return (-1);
/* use structure to handle high and low short swap */
/* get current output */
work = (pbo_xy220s[card]->high_value << 16)
+ pbo_xy220s[card]->low_value;
/* alter specified bits */
work = (work & ~mask) | ((*val) & mask);
/* write new output */
pbo_xy220s[card]->high_value = (unsigned short)(work >> 16);
pbo_xy220s[card]->low_value = (unsigned short)work;
return (0);
}
/*
* xy220_read
*
* read the binary output
*/
int xy220_read(card,mask,pval)
register unsigned short card;
unsigned int mask;
register unsigned int *pval;
{
register unsigned int work;
/* verify card exists */
if (!pbo_xy220s[card])
return (-1);
/* readback */
*pval = (pbo_xy220s[card]->high_value << 16) + pbo_xy220s[card]->low_value;
*pval &= mask;
return(0);
}
#define masks(K) ((1<<K))
/*
* XY220_IO_REPORT
*
*
*/
void xy220_io_report(level)
short int level;
{
int card;
unsigned int value;
for (card = 0; card < MAX_XY220_BO_CARDS; card++){
if (pbo_xy220s[card]){
value = (pbo_xy220s[card]->high_value << 16) /* high */
+ pbo_xy220s[card]->low_value; /* low */
printf("BO: XY220: card %d value=0x%08.8x\n",card,value);
}
}
}
+526
View File
@@ -0,0 +1,526 @@
/* xy240_driver.c */
/* base/src/drv $Id$ */
/*
* routines used to test and interface with Xycom240
* digital i/o module
*
* Author: B. Kornke
* Date: 11/20/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 06-25-92 bg Added driver to code. Added xy240_io_report
* to it. Added copyright disclaimer.
* .02 08-10-92 joh merged xy240_driver.h into this source
* .03 08-11-92 joh fixed use of XY240 where XY240_BI or XY240_BO
* should have been used
* .04 08-11-92 joh now allows for runtime reconfiguration of
* the addr map
* .05 08-25-92 mrk added DSET; made masks a macro
* .06 08-26-92 mrk support epics I/O event scan
* .07 08-26-92 joh task params from task params header
* .08 08-26-92 joh removed STDIO task option
* .09 08-26-92 joh increased stack size for V5
* .10 08-26-92 joh increased stack size for V5
* .11 08-27-92 joh fixed no status return from bo driver
* .12 09-03-92 joh fixed wrong index used when testing for card
* present
* .13 09-03-92 joh fixed structural problems in the io
* report routines which caused messages to
* be printed even when no xy240's are present
* .14 09-17-92 joh io report now tabs over detailed info
* .15 09-18-92 joh documentation
* .16 08-02-93 mrk Added call to taskwdInsert
* .17 08-04-93 mgb Removed V5/V4 and EPICS_V2 conditionals
*/
#include "vxWorks.h"
#include "taskLib.h"
#include "vme.h"
#include "module_types.h"
#include "task_params.h"
#include <drvSup.h>
#include <dbDefs.h>
#include <dbScan.h>
#include <taskwd.h>
#define XY240_ADDR0 (bi_addrs[XY240_BI])
#define XY240_MAX_CARDS (bi_num_cards[XY240_BI])
#define XY240_MAX_CHANS (bi_num_channels[XY240_BI])
#define masks(K) ((1<<K))
/*xy240 memory structure*/
struct dio_xy240{
char begin_pad[0x80]; /*go to interface block*/
unsigned short csr; /*control status register*/
unsigned short isr; /*interrupt service routine*/
unsigned short iclr_vec; /*interrupt clear/vector*/
unsigned short flg_dir; /*flag&port direction*/
unsigned short port0_1; /*port0&1 16 bits value*/
unsigned short port2_3; /*por2&3 16 bits value*/
unsigned short port4_5; /*port4&5 16 bits value*/
unsigned short port6_7; /*port6&7 16 bits value*/
char end_pad[0x400-0x80-16]; /*pad til next card*/
};
/*create dio control structure record*/
struct dio_rec
{
struct dio_xy240 *dptr; /*pointer to registers*/
short num; /*device number*/
short mode; /*operating mode*/
unsigned short sport0_1; /*saved inputs*/
unsigned short sport2_3; /*saved inputs*/
IOSCANPVT ioscanpvt;
/*short dio_vec;*/ /*interrupt vector*/
/*unsigned int intr_num;*/ /*interrupt count*/
};
LOCAL
struct dio_rec *dio; /*define array of control structures*/
static long report();
static long init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvXy240={
2,
report,
init};
static long report(level)
int level;
{
xy240_io_report(level);
return(0);
}
void xy240_bi_io_report(int card);
void xy240_bo_io_report(int card);
static long init()
{
xy240_init();
return(0);
}
/*dio_int
*
*interrupt service routine
*
*/
#if 0
dio_int(ptr)
register struct dio_rec *ptr;
{
register struct dio_xy240 *regptr;
regptr = ptr->dptr;
}
#endif
/*
*
*dio_scan
*
*task to check for change of state
*
*/
dio_scan()
{
int i;
int first_scan,first_scan_complete;
for(;;){
if(interruptAccept) break;
taskDelay(vxTicksPerSecond/30);
}
first_scan_complete = FALSE;
first_scan = TRUE;
for (;;)
{
for (i = 0; i < XY240_MAX_CARDS; i++)
{
if (dio[i].dptr)
if (((dio[i].dptr->port0_1) ^ (dio[i].sport0_1)) ||
((dio[i].dptr->port2_3) ^ (dio[i].sport2_3))
|| first_scan)
{
/* printf("io_scanner_wakeup for card no %d\n",i); */
scanIoRequest(dio[i].ioscanpvt);
dio[i].sport0_1 = dio[i].dptr->port0_1;
dio[i].sport2_3 = dio[i].dptr->port2_3;
}
}
if (first_scan){
first_scan = 0;
first_scan_complete = 1;
}
taskDelay(vxTicksPerSecond/30);
}
}
/*DIO DRIVER INIT
*
*initialize xy240 dig i/o card
*/
xy240_init()
{
short junk;
register short i;
struct dio_xy240 *pdio_xy240;
int tid;
int status;
int at_least_one_present = FALSE;
/*
* allow for runtime reconfiguration of the
* addr map
*/
dio = (struct dio_rec *) calloc(XY240_MAX_CARDS, sizeof(*dio));
if(!dio){
return ERROR;
}
status = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,XY240_ADDR0,&pdio_xy240);
if (status != OK){
printf("%s: Unable to map the XY240 A16 base addr\n", __FILE__);
return ERROR;
}
for (i = 0; i < XY240_MAX_CARDS; i++, pdio_xy240++){
if (vxMemProbe(pdio_xy240,READ,2,&junk) != OK){
dio[i].dptr = 0;
continue;
}
/*
* register initialization
*/
pdio_xy240->csr = 0x3;
pdio_xy240->iclr_vec = 0x00; /*clear interrupt input register latch*/
pdio_xy240->flg_dir = 0xf0; /*ports 0-3,input;ports 4-7,output*/
dio[i].sport2_3 = pdio_xy240->port2_3; /*read and save high values*/
dio[i].dptr = pdio_xy240;
at_least_one_present = TRUE;
scanIoInit(&dio[i].ioscanpvt);
}
if (at_least_one_present)
{
if ((tid = taskNameToId(XY240_NAME)) != ERROR){
taskwdRemove(tid);
taskDelete(tid);
}
status = taskSpawn(
XY240_NAME,
XY240_PRI,
XY_240_OPT,
XY_240_STACK,
dio_scan);
if (status == ERROR){
printf("Unable to create XY240 scan task\n");
}
else taskwdInsert(status,NULL,NULL);
}
return OK;
}
xy240_getioscanpvt(card,scanpvt)
short card;
IOSCANPVT *scanpvt;
{
if ((card >= XY240_MAX_CARDS) || (!dio[card].dptr)) return(0);
*scanpvt = dio[card].ioscanpvt;
return(0);
}
/*
* XY240_BI_DRIVER
*
*interface to binary inputs
*/
xy240_bi_driver(card,mask,prval)
register short card;
unsigned int mask;
register unsigned int *prval;
{
register unsigned int work;
if ((card >= XY240_MAX_CARDS) || (!dio[card].dptr))
return -1;
work = (dio[card].dptr->port0_1 << 16)
+ dio[card].dptr->port2_3;
*prval = work & mask;
return(0);
}
/*
*
*XY240_BO_READ
*
*interface to binary outputs
*/
xy240_bo_read(card,mask,prval)
register short card;
unsigned int mask;
register unsigned int *prval;
{
register unsigned int work;
if ((card >= XY240_MAX_CARDS) || (!dio[card].dptr)){
return -1;
}
/* printf("%d\n",dio[card].num); */
work = (dio[card].dptr->port4_5 << 16)
+ dio[card].dptr->port6_7;
*prval = work &= mask;
return(0);
}
/* XY240_DRIVER
*
*interface to binary outputs
*/
xy240_bo_driver(card,val,mask)
register short card;
unsigned int mask;
register unsigned int val;
{
register unsigned int work;
if ((card >= XY240_MAX_CARDS) || (!dio[card].dptr))
return ERROR;
/* use structure to handle high and low short swap */
/* get current output */
work = (dio[card].dptr->port6_7 << 16)
+ dio[card].dptr->port4_5;
work = (work & ~mask) | (val & mask);
dio[card].dptr->port6_7 = (unsigned short)(work >> 16);
dio[card].dptr->port4_5 = (unsigned short)work;
return OK;
}
/*dio_out
*
*test routine for xy240 output
*/
dio_out(card,port,val)
short card,port,val;
{
if ((card > XY240_MAX_CARDS-1)) /*test to see if card# is allowable*/
{
printf("card # out of range\n");
return -1;
}
else if (!dio[card].dptr) /*see if card exists*/
{
printf("can't find card %d\n", card);
return -2;
}
else if ((port >7) || (port <4)) /*make sure they're output ports*/
{
printf("use ports 4-7\n");
return -3;
}
else if (port == 4)
{
dio[card].dptr->port4_5 = val<< 8;
return -4;
}
else if (port == 5)
{
dio[card].dptr->port4_5 = val;
return -5;
}
else if (port == 6)
{
dio[card].dptr->port6_7 = val<< 8;
return -6;
}
else if (port == 7)
{
dio[card].dptr->port6_7 = val;
return -7;
}
else{
printf("use ports 4-7\n");
return -8;
}
}
/*XY240_WRITE
*
*command line interface to test bo driver
*
*/
xy240_write(card,val)
short card;
unsigned int val;
{
return xy240_bo_driver(card,val,0xffffffff);
}
long
xy240_io_report(level)
short int level;
{
int card;
for (card = 0; card < XY240_MAX_CARDS; card++){
if(dio[card].dptr){
printf("B*: XY240:\tcard %d\n",card);
if (level >= 1){
xy240_bi_io_report(card);
xy240_bo_io_report(card);
}
}
}
}
void xy240_bi_io_report(int card)
{
short int num_chans,j,k,l,m,status;
int ival,jval,kval,lval,mval;
unsigned int *prval;
num_chans = XY240_MAX_CHANS;
if(!dio[card].dptr){
return;
}
printf("\tXY240 BINARY IN CHANNELS:\n");
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){
xy240_bi_driver(card,masks(j),&jval);
if (jval != 0)
jval = 1;
printf("\tChan %d = %x\t ",j,jval);
}
if(k < num_chans){
xy240_bi_driver(card,masks(k),&kval);
if (kval != 0)
kval = 1;
printf("Chan %d = %x\t ",k,kval);
}
if(l < num_chans){
xy240_bi_driver(card,masks(l),&lval);
if (lval != 0)
lval = 1;
printf("Chan %d = %x \t",l,lval);
}
if(m < num_chans){
xy240_bi_driver(card,masks(m),&mval);
if (mval != 0)
mval = 1;
printf("Chan %d = %x \n",m,mval);
}
}
}
void xy240_bo_io_report(int card)
{
short int num_chans,j,k,l,m,status;
int ival,jval,kval,lval,mval;
unsigned int *prval;
num_chans = XY240_MAX_CHANS;
if(!dio[card].dptr){
return;
}
printf("\tXY240 BINARY OUT CHANNELS:\n");
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){
xy240_bo_read(card,masks(j),&jval);
if (jval != 0)
jval = 1;
printf("\tChan %d = %x\t ",j,jval);
}
if(k < num_chans){
xy240_bo_read(card,masks(k),&kval);
if (kval != 0)
kval = 1;
printf("Chan %d = %x\t ",k,kval);
}
if(l < num_chans){
xy240_bo_read(card,masks(l),&lval);
if (lval != 0)
lval = 1;
printf("Chan %d = %x \t",l,lval);
}
if(m < num_chans){
xy240_bo_read(card,masks(m),&mval);
if (mval != 0)
mval = 1;
printf("Chan %d = %x \n",m,mval);
}
}
}
File diff suppressed because it is too large Load Diff
+241
View File
@@ -0,0 +1,241 @@
/* module_types.c */
/* base/src/drv $Id$ */
/*
* Author: Marty Kraimer
* Date: 08-23-93
*
* 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-23-93 mrk Initial Version
*/
#include <module_types.h>
module_types()
{
ai_num_cards[AB1771IL] = 12;
ai_num_cards[AB1771IFE] = 12;
ai_num_cards[AB1771IXE] = 12;
ai_num_cards[XY566SE] = 2;
ai_num_cards[XY566DI] = 2;
ai_num_cards[XY566DIL] = 2;
ai_num_cards[VXI_AT5_AI] = 32;
ai_num_cards[AB1771IFE_SE] = 12;
ai_num_cards[AB1771IFE_4to20MA] = 12;
ai_num_cards[DVX2502] = 1;
ai_num_cards[AB1771IFE_0to5V] = 12;
ai_num_cards[KSCV215] = 32;
ai_num_channels[AB1771IL] = 8;
ai_num_channels[AB1771IFE] = 8;
ai_num_channels[AB1771IXE] = 8;
ai_num_channels[XY566SE] = 32;
ai_num_channels[XY566DI] = 16;
ai_num_channels[XY566DIL] = 16;
ai_num_channels[VXI_AT5_AI] = 8;
ai_num_channels[AB1771IFE_SE] = 16;
ai_num_channels[AB1771IFE_4to20MA] = 8;
ai_num_channels[DVX2502] = 127;
ai_num_channels[AB1771IFE_0to5V] = 8;
ai_num_channels[KSCV215] = 32;
ai_addrs[AB1771IL] = 0;
ai_addrs[AB1771IFE] = 0;
ai_addrs[AB1771IXE] = 0;
ai_addrs[XY566SE] = 0x6000;
ai_addrs[XY566DI] = 0x7000;
ai_addrs[XY566DIL] = 0x7800;
ai_addrs[VXI_AT5_AI] = 0xc014;
ai_addrs[AB1771IFE_SE] = 0;
ai_addrs[AB1771IFE_4to20MA] = 0;
ai_addrs[DVX2502] = 0xff00;
ai_addrs[AB1771IFE_0to5V] = 0;
ai_addrs[KSCV215] = 0;
ai_memaddrs[AB1771IL] = 0;
ai_memaddrs[AB1771IFE] = 0;
ai_memaddrs[AB1771IXE] = 0;
ai_memaddrs[XY566SE] = 0x000000;
ai_memaddrs[XY566DI] = 0x040000;
ai_memaddrs[XY566DIL] = 0x0c0000;
ai_memaddrs[VXI_AT5_AI] = 0;
ai_memaddrs[AB1771IFE_SE] = 0;
ai_memaddrs[AB1771IFE_4to20MA] = 0;
ai_memaddrs[DVX2502] = 0x100000;
ai_memaddrs[AB1771IFE_0to5V] = 0;
ai_memaddrs[KSCV215] = 0;
ao_num_cards[AB1771OFE] = 12;
ao_num_cards[VMI4100] = 4;
ao_num_cards[ZIO085] = 1;
ao_num_cards[VXI_AT5_AO] = 32;
ao_num_channels[AB1771OFE] = 4;
ao_num_channels[VMI4100] = 16;
ao_num_channels[ZIO085] = 32;
ao_num_channels[VXI_AT5_AO] = 16;
ao_addrs[AB1771OFE] = 0;
ao_addrs[VMI4100] = 0x4100;
ao_addrs[ZIO085] = 0x0800;
ao_addrs[VXI_AT5_AO] = 0xc000;
bi_num_cards[ABBI_08_BIT] = 12;
bi_num_cards[ABBI_16_BIT] = 12;
bi_num_cards[BB910] = 4;
bi_num_cards[XY210] = 2;
bi_num_cards[VXI_AT5_BI] = 32;
bi_num_cards[HPE1368A_BI] = 32;
bi_num_cards[AT8_FP10S_BI] = 8;
bi_num_cards[XY240_BI] = 2;
bi_num_channels[ABBI_08_BIT] = 8;
bi_num_channels[ABBI_16_BIT] = 16;
bi_num_channels[BB910] = 32;
bi_num_channels[XY210] = 32;
bi_num_channels[VXI_AT5_BI] = 32;
bi_num_channels[HPE1368A_BI] = 16;
bi_num_channels[AT8_FP10S_BI] = 32;
bi_num_channels[XY240_BI] = 32;
bi_addrs[ABBI_08_BIT] = 0;
bi_addrs[ABBI_16_BIT] = 0;
bi_addrs[BB910] = 0xb800;
bi_addrs[XY210] = 0xa000;
bi_addrs[VXI_AT5_BI] = 0xc000;
bi_addrs[HPE1368A_BI] = 0xc000;
bi_addrs[AT8_FP10S_BI] = 0x0e00;
bi_addrs[XY240_BI] = 0x3000;
bo_num_cards[ABBO_08_BIT] = 12;
bo_num_cards[ABBO_16_BIT] = 12;
bo_num_cards[BB902] = 4;
bo_num_cards[XY220] = 1;
bo_num_cards[VXI_AT5_BO] = 32;
bo_num_cards[HPE1368A_BO] = 32;
bo_num_cards[AT8_FP10M_BO] = 2;
bo_num_cards[XY240_BO] = 2;
bo_num_channels[ABBO_08_BIT] = 8;
bo_num_channels[ABBO_16_BIT] = 16;
bo_num_channels[BB902] = 32;
bo_num_channels[XY220] = 32;
bo_num_channels[VXI_AT5_BO] = 32;
bo_num_channels[HPE1368A_BO] = 16;
bo_num_channels[AT8_FP10M_BO] = 32;
bo_num_channels[XY240_BO] = 32;
bo_addrs[ABBO_08_BIT] = 0;
bo_addrs[ABBO_16_BIT] = 0;
bo_addrs[BB902] = 0x0400;
bo_addrs[XY220] = 0xa800;
bo_addrs[VXI_AT5_BO] = 0xc000;
bo_addrs[HPE1368A_BO] = 0xc000;
bo_addrs[AT8_FP10M_BO] = 0xc000;
bo_addrs[XY240_BO] = 0x3000;
sm_num_cards[CM57_83E] = 4;
sm_num_cards[OMS_6AXIS] = 4;
sm_num_channels[CM57_83E] = 1;
sm_num_channels[OMS_6AXIS] = 6;
sm_addrs[CM57_83E] = 0x8000;
sm_addrs[OMS_6AXIS] = 0x4000;
wf_num_cards[XY566WF] = 2;
wf_num_cards[CAMAC_THING] = 4;
wf_num_cards[JGVTR1] = 4;
wf_num_cards[COMET] = 4;
wf_num_channels[XY566WF] = 1;
wf_num_channels[CAMAC_THING] = 1;
wf_num_channels[JGVTR1] = 1;
wf_num_channels[COMET] = 4;
wf_addrs[XY566WF] = 0x9000;
wf_addrs[CAMAC_THING] = 0;
wf_addrs[JGVTR1] = 0xB000;
wf_addrs[COMET] = 0xbc00;
wf_armaddrs[XY566WF] = 0x5400;
wf_armaddrs[CAMAC_THING]= 0;
wf_armaddrs[JGVTR1] = 0;
wf_armaddrs[COMET] = 0;
wf_memaddrs[XY566WF] = 0x080000;
wf_memaddrs[CAMAC_THING]= 0;
wf_memaddrs[JGVTR1] = 0xb80000;
wf_memaddrs[COMET] = 0xe0000000;
tm_num_cards[MZ8310] = 4;
tm_num_cards[DG535] = 1;
tm_num_cards[VXI_AT5_TIME] = 32;
tm_num_channels[MZ8310] = 10;
tm_num_channels[DG535] = 1;
tm_num_channels[VXI_AT5_TIME] = 10;
tm_addrs[MZ8310] = 0x1000;
tm_addrs[DG535] = 0;
tm_addrs[VXI_AT5_TIME] = 0xc000;
AT830X_1_addrs = 0x0400;
AT830X_1_num_cards = 2;
AT830X_addrs = 0xaa0000;
AT830X_num_cards = 2;
xy010ScA16Base = 0x0000;
EPICS_VXI_LA_COUNT = 32;
EPICS_VXI_A24_BASE = (char *) 0x900000;
EPICS_VXI_A24_SIZE = 0x100000;
EPICS_VXI_A32_BASE = (char *) 0x90000000;
EPICS_VXI_A32_SIZE = 0x10000000;
AI566_VNUM = 0xf8;
DVX_IVEC0 = 0xd0;
MD_INT_BASE = 0xf0;
MZ8310_INT_VEC_BASE = 0xe8;
AB_VEC_BASE = 0x60;
JGVTR1_INT_VEC = 0xe0;
AT830X_1_IVEC0 = 0xd4;
AT830X_IVEC0 = 0xd6;
AT8FP_IVEC_BASE = 0xa2;
AT8FPM_IVEC_BASE= 0xaa;
BB_SHORT_OFF = 0x1800;
BB_IVEC_BASE = 0xa0;
BB_IRQ_LEVEL = 5;
PEP_BB_SHORT_OFF= 0x1c00;
PEP_BB_IVEC_BASE= 0xe8;
NIGPIB_SHORT_OFF = 0x5000;
NIGPIB_IVEC_BASE = 100;
NIGPIB_IRQ_LEVEL = 5;
return(0);
}
+64
View File
@@ -0,0 +1,64 @@
/* steppermotor.h */
/* base/src/drv $Id$ */
/*
* header file to support database library interface to motor drivers
*
* Author: Bob Dalesio
* Date: 12-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:
* -----------------
* .01 mm-dd-yy iii Comment
*/
/* readback data passed to the database library routine from the motor driver */
struct motor_data{
short cw_limit;
short ccw_limit;
short moving;
short direction;
short constant_velocity;
long velocity;
long encoder_position;
long motor_position;
long accel;
};
/*
* Sets values for the database library based on the value flag:
* 0 - set the mode of the motor (position/velocity)
* 1 - set the velocity of the motor
* 2 - set the poistion of the motor
* 3 - start motor rotating
* 4 - set the callback routine for a motor
*/
#define SM_MODE 0
#define SM_VELOCITY 1
#define SM_MOVE 2
#define SM_MOTION 3
#define SM_CALLBACK 4
#define SM_SET_HOME 5
#define SM_ENCODER_RATIO 6
#define SM_MOTOR_RESOLUTION 7
#define SM_READ 8
+639
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);
}
+972
View File
@@ -0,0 +1,972 @@
/* drvCompuSm.c */
/* base/src/drv $Id$ */
/*
* subroutines and tasks that are used to interface to the Compumotor 1830
* stepper motor drivers
*
* Author: Bob Dalesio
* Date: 01-03-90
*
* 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-07-90 lrd add command to read the motor status
* .02 04-11-90 lrd made velocity mode motor go active
* .03 04-12-90 lrd only allow one connection to a motor
* .04 04-13-90 lrd add externally initiated motor motion monitoring
* .05 09-05-91 joh updated for v5 vxWorks
* .06 10-09-91 lrd monitor for external motion once every 2 seconds
* not at 30 Hz (.04 was not implemented correctly)
* .06 11-31-91 bg added compu_sm_io_report. Added sysBusToLocalAdrs()
* for addressing.
* .07 03-02-92 bg added level and ability to print raw values to
* compu_sm_io_report for level > 0.
* .08 05-04-92 bg added compu_sm_reset and rebootHookAdd so ioc can be
* rebooted with control X.
* .09 06-25-92 bg Combined drvCompuSm.c and compu_sm_driver.c
* .10 06-26-92 bg Added level to compu_sm_io_report in drvCompuSm
* structure
* .11 06-29-92 joh took file ptr arg out of io report
* .12 08-06-92 joh merged compu sm include file
* .13 08-27-92 joh silenced ANSI C function proto warning
* .14 08-27-92 joh fixed no epics init
* .15 08-02-93 mrk Added call to taskwdInsert
* .16 10-29-93 jba Fixed max number of cards to use module_types.c
* Fixed error in calculating card addresses
*/
#include <vxWorks.h>
#include <vme.h>
#include <sysLib.h>
#include <semLib.h> /* library for semaphore support */
#include <wdLib.h>
#include <rngLib.h> /* library for ring buffer support */
/* drvCompuSm.c - Driver Support Routines for CompuSm */
#include <dbDefs.h>
#include <drvSup.h>
#include <module_types.h>
#include <steppermotor.h>
#include <task_params.h>
#include <taskwd.h>
long compu_sm_io_report();
long compu_driver_init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvCompuSm={
2,
compu_sm_io_report,
compu_driver_init};
/* compumotor vme interface information */
#define MAX_COMPU_MOTORS 8
#define RESP_SZ 16 /* card returns 16 chars - cmd & resp */
#define RESPBUF_SZ (RESP_SZ+1) /* intr routine also passes motor no. */
/* Control Byte bit definitions for the Compumotor 1830 */
/* bits 0 and 1 are not used */
#define CBEND 0x04 /* end of command string */
#define CBLMR 0x08 /* last message byte read */
#define CBCR 0x10 /* command ready in cm_idb */
#define CBMA 0x20 /* message accepted from odb */
#define CBEI 0x40 /* enable interrupts */
#define CBBR 0x80 /* board reset */
#define SND_MORE CBCR | CBEI /* more chars to send */
#define SND_LAST CBEND | SND_MORE /* last char being sent */
#define RD_MORE CBMA | CBEI /* more chars to read */
#define RD_LAST CBLMR | RD_MORE /* last byte we need to read */
/* Status Byte bit definitions */
#define SBIRDY 0x10 /* idb is ready */
/* Structure used for communication with a Compumotor 1830
** Motor Controller. The data buffer is repeated 64 times
** on even word addresses (0xXXXXXX1,0xXXXXX5...) and the
** control location is repeated 64 times on odd word
** addresses (0xXXXXX3, 0xXXXXX7...). The registers must
** be read and written as bytes.
*/
struct compumotor {
char cm_d1; /* not accessable */
char cm_idb; /* input data buffer */
char cm_d2; /* not accessable */
char cm_cb; /* control byte */
char cm_d3[0x100-4]; /* fill to next standard address */
};
/* This file includes defines for all compumotor 1830 controller
** commands. */
#define SM_NULL 0x0 /* Null command */
#define SM_INT 0x1 /* Interrupt X */
#define SM_WRT_STAT 0x8 /* Write X to the user defined status bits */
#define SM_SET_STAT 0x9 /* Set user defined status bit number X */
#define SM_CLR_STAT 0xa /* Clear user defined status bit number X */
#define SM_SET_PROG 0xb /* Set programmable output bit X */
#define SM_CLR_PROG 0xc /* Clear programmable output bit X */
#define SM_WRT_PROG 0xd /* Write X to the programmable output bits */
#define SM_DEF_X_TO_Y 0xf /* Define bit X to indicate state Y */
#define SM_TOG_JOG 0x10 /* Disable/enable the JOG inputs */
#define SM_DEF_JOG 0x11 /* Define JOG input functions */
#define SM_TOG_REM_PWR 0x12 /* Turn off/on remote power shutdown */
#define SM_TOG_REM_SHUT 0x13 /* Disable/enable the "remote shutdown" bit */
#define SM_SET_CW_MOTN 0x14 /* Set CW motion equal to +- */
#define SM_TOG_POS_MTN 0x18 /* Turn off/on post-move position maintenance */
#define SM_TOG_STOP_STL 0x19 /* Turn off/on termination on stall detect */
#define SM_REP_X_Y 0x20 /* Repeat the following X commands Y times */
#define SM_REP_TIL_CONT 0x21 /* Repeat the following X commands
until a CONTINUE is received */
#define SM_WAIT_CONT 0x28 /* Wait for a CONTINUE */
#define SM_WAIT_MILLI 0x29 /* Wait X milliseconds */
#define SM_WAIT_SECOND 0x2a /* Wait X seconds */
#define SM_WAIT_MINUTE 0x2b /* Wait X minutes */
#define SM_WAIT_TRIGGER 0x2c /* Wait for trigger X to go active */
#define SM_DEF_A_OP_POS 0x2e /* Define the abs open-loop position as X */
#define SM_DEF_A_CL_POS 0x2f /* Define absolute closed-loop position */
#define SM_DEF_ABS_ZERO 0x30 /* Define the present position as the
absolute zero position */
#define SM_DEF_VEL_ACC 0x31 /* Define default velocity and acceleration */
#define SM_MOV_DEFAULT 0x32 /* Perform the default move (trapezoidal
continuous) */
#define SM_MOV_REL_POS 0x33 /* Go to relative position X at default
velocity and acceleration */
#define SM_MOV_ABS_POS 0x34 /* Go to absolute position X at default
velocity and acceleration */
#define SM_MOV_REL_ENC 0x35 /* Go to relative encoder position X */
#define SM_MOV_ABS_ENC 0x36 /* Go to absolute encoder position X */
#define SM_DEF_OP_HOME 0x38 /* Define HOME location (open loop */
#define SM_DEF_CL_HOME 0x38 /* Define HOME location (closed loop) */
#define SM_MOV_HOME_POS 0x39 /* Go HOME at the default velocity and
acceleration */
#define SM_MOV_HOME_ENC 0x3a /* Go to encoder HOME at the default
velocity and acceleration */
#define SM_DO_MOV_X 0x40 /* Perform move number X */
#define SM_DO_SEQ_X 0x41 /* Perform sequence buffer X */
#define SM_DO_VEL_STR 0x42 /* Perform the velocity streaming buffer */
#define SM_CONT 0x48 /* CONTINUE (perform next command) */
#define SM_OP_LOOP_MODE 0x50 /* Enter open loop indexer mode */
#define SM_VEL_DIS_MODE 0x51 /* Enter velocity-distance streaming mode */
#define SM_VEL_TIM_MODE 0x52 /* Enter velocity-time streaming mode */
#define SM_STOP 0x70 /* STOP motion */
#define SM_DSC_SEQ 0x71 /* Discontinue the sequence buffer */
#define SM_SSP_SEQ 0x72 /* Suspend the sequence buffer;
wait for a CONTINUE to resume */
#define SM_DSC_SNGL 0x73 /* Discontinue any singular command
currently being performed */
#define SM_STOP_ON_TRG 0x74 /* STOP motion when trigger X goes active */
#define SM_DSC_SEQ_TRG 0x75 /* Discontinue the sequence buffer when
trigger X goes active */
#define SM_SSP_SEQ_TRG 0x76 /* Suspend sequence buffer when trigger
X goes active */
#define SM_DSC_SNGL_TRG 0x77 /* Discontinue any singular command when
trigger X goes active */
#define SM_KILL 0x78 /* Kill motion */
#define SM_KILL_SEQ 0x79 /* Kill the sequence buffer */
#define SM_KILL_SEQ_SNGL 0x7a /* Kill current sequence singular command;
wait for CONTINUE */
#define SM_KILL_VEL_STR 0x7b /* Kill the velocity streaming buffer */
#define SM_KILL_ON_TRG 0x7c /* Kill motion when trigger X goes active */
#define SM_KILL_SEQ_TRG 0x7d /* Kill the sequence buffer when trigger
X goes active */
#define SM_KL_SQSNG_TRG 0x7e /* Kill current sequence singular command
when trigger X goes active; wait for
a continue */
#define SM_KL_VLSTR_TRG 0x7f /* Kill the velocity streaming buffer
when trigger X goes active */
#define SM_GET_B_REL_POS 0x80 /* Request position relative to the
beginning of the current move */
#define SM_GET_E_REL_POS 0x81 /* Request position relative to the
end of the current move */
#define SM_GET_H_REL_POS 0x82 /* Request position relative to the home
limit switch */
#define SM_GET_Z_REL_POS 0x83 /* Request position relative to the
absolute zero position */
#define SM_GET_CUR_DIR 0x84 /* Request current direction */
#define SM_GET_VEL 0x85 /* Request current velocity */
#define SM_GET_ACC 0x86 /* Request current acceleration */
#define SM_GET_MOV_STAT 0x88 /* Request current move status */
#define SM_GET_LIM_STAT 0x89 /* Request state of the limit switches */
#define SM_GET_HOME_STAT 0x8a /* Request state of the HOME switch */
#define SM_GET_TRV_DIR 0x8b /* Request direction of travel */
#define SM_GET_MOT_MOV 0x8c /* Request whether motor is moving or not */
#define SM_GET_MOT_CONST 0x8d /* Request whether motor is at constant,
nonzero velocity or not */
#define SM_GET_MOT_ACC 0x8e /* Request whether motor is or is not
accelerating */
#define SM_GET_MOT_DEC 0x8f /* Request whether motor is or is not
decelerating */
#define SM_GET_MODE 0x90 /* Request present mode */
#define SM_GET_MV_PARM 0x91 /* Request move parameters for move number X */
#define SM_GET_SEQ_CMMD 0x92 /* request commands stored in the
sequence buffer */
#define SM_GET_MVDEF_STAT 0x93 /* Request state of the move definitions */
#define SM_GET_TRG_STAT 0x94 /* Request state of trigger inputs */
#define SM_GET_JOG_STAT 0x95 /* Request state of JOG inputs */
#define SM_GET_Z_STAT 0x96 /* Request state of the Channel Z home input */
#define SM_GET_OUT_STAT 0x97 /* Request the state of the programmable
output bits */
#define SM_GET_REL_ENC 0x98 /* Request relative encoder count */
#define SM_GET_REL_ERR 0x99 /* Request relative error from desired
closed loop position */
#define SM_GET_ABS_ENC 0x9a /* Request absolute encoder count */
#define SM_GET_SLIP_STAT 0x9b /* Request slip detect status */
#define SM_GET_RATIO 0x9c /* Request motor pulse to encoder pulse ratio */
#define SM_GET_RESOLTN 0x9d /* Request motor resolution */
#define SM_GET_BACK_SIG 0x9e /* Request backlash sigma (motor steps)*/
#define SM_GET_ALG 0x9f /* Request position maintenance alg.
const, and max velocity */
#define SM_INT_NXT_MOV 0xa0 /* Interrupt at start of next move */
#define SM_INT_ALL_MOV 0xa1 /* Interrupt at the start of every move */
#define SM_INT_NXT_NZ 0xa2 /* Interrupt at constant nonzero velocity
of next move */
#define SM_INT_ALL_NZ 0xa3 /* Interrupt at constant nonzero velocity
of every move */
#define SM_INT_NXT_END 0xa4 /* Interrupt at next end of motion */
#define SM_INT_ALL_END 0xa5 /* Interrupt at every end of motion */
#define SM_INT_NXT_STL 0xa6 /* Interrupt on next stall detect */
#define SM_INT_ALL_STL 0xa7 /* Interrupt on every stall detect */
#define SM_INT_NXT_PLIM 0xa8 /* Interrupt the next time the motor
hits the positive limit */
#define SM_INT_ALL_PLIM 0xa9 /* Interrupt on every positive limit */
#define SM_INT_NXT_NLIM 0xaa /* Interrupt the next time the motor
hits the negative limit */
#define SM_INT_ALL_NLIM 0xab /* Interrupt on every negative limit */
#define SM_INT_TRG 0xac /* Interrupt on trigger X active */
#define SM_INT_INHBT 0xaf /* Inhibit all interrupts */
#define SM_DEF_RATIO 0xb0 /* Define motor pulse to encoder pulse ratio */
#define SM_DEF_RESOLTN 0xb1 /* Define motor resolution */
#define SM_DEF_BACK_SIG 0xb2 /* Define backlash sigma (motor steps)*/
#define SM_DEF_ALG 0xb3 /* Define position maintenance algorithm
const, and max velocity */
#define SM_DEF_TEETH 0xb4 /* Define the number of rotor teeth */
#define SM_DEF_DEADBAND 0xb5 /* Def the deadband region in encoder pulses */
#define SM_DEF_REL_TRP 0xc8 /* Define move X as a relative,
trapezoidal move */
#define SM_DEF_ABS_TRP 0xcb /* Define move X as an absolute
trapezoidal move */
#define SM_DEF_CONT 0xce /* Define move X as a continuous move */
#define SM_DEF_REL_CL 0xd4 /* Define move X, define it as relative,
closed-loop move */
#define SM_DEF_ABS_CL 0xd5 /* Def move X as an abs, closed- loop move */
#define SM_DEF_STSTP_VEL 0xd6 /* Define the start/stop velocity */
#define SM_DEL_MOV_X 0xd7 /* Delete move X */
#define SM_END_SEQ_DEF 0xd8 /* End definition of sequence buffer */
#define SM_BEG_SEQ_DEF 0xd9 /* Begin definition of sequence buffer */
#define SM_DEL_SEQ_X 0xda /* Delete sequence buffer X */
#define SM_LD_VD_DATA 0xe0 /* Place data into the velocity-distance buffer */
#define SM_LD_VT_DATA 0xe1 /* Place data into the velocity-time buffer */
#define SM_GET_FREE_BYT 0xe2 /* Request number of free bytes in vel-
streaming/sequence buffer */
#define SM_DEF_VS_CMMD 0xee /* Define command to be executed during
the velocity streaming buffer */
#define SM_GET_NUM_REV 0xfd /* Request software part number and revision */
#define SM_TEST_SWITCH 0xff /* Perform the test switch function */
#define VELOCITY_MODE 0
#define MAX_COMMANDS 256
#define COMPU_INT_LEVEL 5
/* array of pointers to stepper motor driver cards present in system */
struct compumotor *pcompu_motors[MAX_COMPU_MOTORS];
LOCAL SEM_ID compu_wakeup; /* compumotor data request task semaphore */
/* response variables */
LOCAL SEM_ID smRespSem; /* task semaphore */
LOCAL RING_ID smRespQ; /* ring buffer */
int smRespId; /* task id */
#define RESP_Q_SZ (RESPBUF_SZ * 50) /* response ring buffer size */
/* interrupt buffers */
unsigned char sm_responses[MAX_COMPU_MOTORS][RESPBUF_SZ];
unsigned short counts[MAX_COMPU_MOTORS];
/* VME memory Short Address Space is set up in gta_init */
static int *compu_addr;
/* motor information */
struct compu_motor{
short active; /* flag to tell the oms_task if the motor is moving */
int callback; /* routine in database library to call with status */
int callback_arg; /* argument to callback routine */
short update_count;
short mode;
short motor_resolution;
};
struct compu_motor compu_motor_array[MAX_COMPU_MOTORS];
/* Forward reference. */
VOID compu_sm_reset();
VOID compu_sm_stat();
/* motor status - returned to the database library routines */
struct motor_data compu_motor_data_array[MAX_COMPU_MOTORS];
/* moving status bit descriptions */
#define CW_LIMIT 0x01 /* clockwise???? limit */
#define CCW_LIMIT 0x02 /* counter-clockwise???? limit */
#define DIRECTION 0x08 /* direction bit */
#define MOVING 0x10 /* moving status bit */
#define CONSTANT_VEL 0x20 /* constant velocity */
/* directions in driver card-ese */
#define CLKW 0 /* clockwise direction */
#define CCLKW 1 /* counter clockwise direction */
/*
* Code Portions:
*
* smCmdTask Task which writes commands to the hardware
* smRespTask Task which places reponses from the hardware into resp buffers
* sm_intr Interrupt Handler - collects response data from the hardware
* sm_drv_init Initializes all motors, semaphores, ring buffers and interrupts
* sm_driver Subroutine for outside world to issue commands to motors
* motor_select Subroutine to setting callback arg and verifying no other user
* motor_deselect Subroutine to free the motor for other users
*
* Interaction Chart:
* -------------- -------------------
* / \ / \
* | smRespTask | | smCmdTask |
* \ / \ /
* --------------- -------------------
* ^ ^ |
* TAKES | | GETS |
* | | |
* -------------- --------------- |
* Resp Semaphore Response Queue |
* -------------- --------------- |
* ^ ^ |
* GIVES | | PUTS |
* | | |
* --------------- |
* / \ |
* | sm_intr | |
* \ / |
* --------------- |
* ^ reads responses writes commands |
* | from hardware to hardware V
*/
/*
* COMPU_RESP_TASK
*
* converts readback from the compumotor 1830 cards into a structure that
* is returned to the database library layer every .1 second while a motor
* is moving
*/
compu_resp_task()
{
unsigned char resp[RESPBUF_SZ];
register short i;
register struct motor_data *pmotor_data;
FOREVER {
/* wait for somebody to wake us up */
semTake (smRespSem, WAIT_FOREVER);
/* the response buffer contains: */
/* 0 - motor number */
/* 1 - the command which solicited this response */
/* 2 - the first byte of the response */
/* process requests in the command ring buffer */
while (rngBufGet(smRespQ,(char *)resp,RESPBUF_SZ) == RESPBUF_SZ){
pmotor_data = &compu_motor_data_array[resp[0]];
/* convert argument */
switch(resp[1]){
case (SM_GET_VEL):
{
register long *pvelocity = (long *)(&resp[3]);
pmotor_data->velocity = *pvelocity;
break;
}
case (SM_GET_MOV_STAT):
{
register struct compu_motor *pcompu_motor;
register int (*psmcb_routine)();
pcompu_motor = &compu_motor_array[resp[0]];
pmotor_data->moving = (resp[2] & MOVING)?1:0;
pmotor_data->constant_velocity = (resp[2] & CONSTANT_VEL)?1:0;
pmotor_data->cw_limit = (resp[2] & CW_LIMIT)?1:0;
pmotor_data->ccw_limit = (resp[2] & CCW_LIMIT)?1:0;
pmotor_data->direction = (resp[2] & DIRECTION)?1:0;
/* post every .1 second or not moving */
if ((pcompu_motor->update_count-- <= 0)
|| (pmotor_data->moving == 0)){
if (pcompu_motor->callback != 0){
(int)psmcb_routine = pcompu_motor->callback;
(*psmcb_routine)(pmotor_data,pcompu_motor->callback_arg);
}
if (pmotor_data->moving){
/* motors are reported at 10 Hz */
pcompu_motor->update_count = 3;
}else{
pcompu_motor->active = FALSE;
pcompu_motor->update_count = 0;
}
}
break;
}
case (SM_GET_ABS_ENC):
{
register long *pencoder = (long *)(&resp[2]);
pmotor_data->encoder_position = *pencoder;
break;
}
case (SM_GET_Z_REL_POS):
{
register long *pmotor = (long *)(&resp[4]);
pmotor_data->motor_position = *pmotor;
break;
}
case (SM_GET_CUR_DIR):
pmotor_data->direction = (resp[2] == 0xff)?CLKW:CCLKW;
break;
}
}
}
}
/* Data request commands for the positional and velocity mode motors */
char compu_velo_reqs[] = { SM_GET_VEL, SM_GET_MOV_STAT };
#define NUM_VEL_REQS 2
char compu_pos_reqs[] = { SM_GET_ABS_ENC, SM_GET_Z_REL_POS, SM_GET_MOV_STAT };
#define NUM_POS_REQS 3
/*
* COMPU_TASK
*
* task to solicit currnet status from the compumotor 1830 cards while they
* are active
*/
compu_task()
{
register short inactive_count;
register short card;
register short i;
register struct compumotor *pmotor;
register char *preqs;
/* inactive motors get monitored once every 2 seconds in case they are */
/* being moved manually */
inactive_count = 60;
while(1){
/* This task is run 30 times a second */
taskDelay(2);
for (card = 0; card < sm_num_cards[CM57_83E]; card++){
pmotor = pcompu_motors[card];
if (pmotor == 0) continue;
if ((compu_motor_array[card].active)
|| (inactive_count <=0)){
if (compu_motor_array[card].mode == VELOCITY_MODE){
preqs = &compu_velo_reqs[0];
/* request status data */
for (i = 0; i < NUM_VEL_REQS; i++,preqs++)
compu_send_msg(pmotor,preqs,1);
}else{
preqs = &compu_pos_reqs[0];
/* request status data */
for (i = 0; i < NUM_POS_REQS; i++,preqs++)
compu_send_msg(pmotor,preqs,1);
}
}
}
if (--inactive_count < 0) inactive_count = 60;
}
}
/*
* COMPU_INTR
*
* interrupt vector for the compumotor 1830 card
*/
compu_intr(mdnum)
register int mdnum;
{
register struct compumotor *pmtr; /* memory port to motor card */
register int key;
key = intLock();
/* pointer to the compumotor card interface */
pmtr = pcompu_motors[mdnum];
/* place the response byte into the appropriate response buffer */
sm_responses[mdnum][counts[mdnum]] = pmtr->cm_idb;
counts[mdnum]++;
/* when the buffer is full pass it onto the repsonse task */
if (counts[mdnum] == RESPBUF_SZ){
if (rngBufPut(smRespQ,(char *)sm_responses[mdnum],RESPBUF_SZ) != RESPBUF_SZ)
logMsg("smRespQ %d - Full\n",mdnum);
else
semGive (smRespSem);
/* the zero-th byte is the motor number */
counts[mdnum] = 1; /* start with command */
/* inform the hardware that the response is complete */
pmtr->cm_cb = RD_LAST;
}else{
/* inform the hardware there is more to send */
pmtr->cm_cb = RD_MORE;
}
intUnlock(key);
}
/*
* COMPU_DRIVER_INIT
*
* initialization for the compumotor 1830 card
*/
long
compu_driver_init(){
register short i;
int status;
struct compumotor *pmtr; /* memory port to motor card */
int cok = CBBR; /*to reset board */
short none_found; /* flags a steppermotor is present */
int taskId;
struct compumotor *pmtrb;
/* intialize each driver which is present */
none_found = TRUE;
rebootHookAdd((FUNCPTR)compu_sm_reset);
status = sysBusToLocalAdrs(
VME_AM_SUP_SHORT_IO,
sm_addrs[CM57_83E],
(int **)&compu_addr);
if (status != OK){
printf("%s: failed to map A16 base\n", __FILE__);
return ERROR;
}
pmtrb = (struct compumotor *)compu_addr;
for (i = 0; i < sm_num_cards[CM57_83E]; i++) {
pmtr = (struct compumotor *)((int)pmtrb + (i<<8));
/* initialize when card is present */
if (vxMemProbe(&pmtr->cm_cb,WRITE,1,&cok) != ERROR){
none_found = FALSE;
pcompu_motors[i] = pmtr; /* ptr to interface */
intConnect((MD_INT_BASE+i)*4,compu_intr,i); /* interrupt enable */
sysIntEnable(COMPU_INT_LEVEL);
/* init interrupt receive buffers */
sm_responses[i][0] = i; /* motor number */
counts[i] = 1; /* buffer index */
}else{
pcompu_motors[i] = 0; /* flags no board is present */
}
}
if (none_found) return(0);
/* initialize the response task ring buffer */
if ((smRespQ = rngCreate(RESP_Q_SZ)) == (RING_ID)NULL)
panic ("sm_init: cmRespQ\n");
/* intialize the semaphores which awakens the sleeping *
* stepper motor command task and the stepper motor response task */
if(!(smRespSem=semBCreate(SEM_Q_FIFO,SEM_EMPTY)))
errMessage(0,"semBcreate failed in compu_driver_init");
if(!(compu_wakeup=semBCreate(SEM_Q_FIFO,SEM_EMPTY)))
errMessage(0,"semBcreate failed in compu_driver_init");
/* spawn the sleeping motor driver command and response tasks */
smRespId =
taskSpawn("compu_resp_task",SMRESP_PRI,SMRESP_OPT,SMRESP_STACK,compu_resp_task);
taskwdInsert(smRespId,NULL,NULL);
taskId = taskSpawn("compu_task",SMRESP_PRI,SMRESP_OPT,2000,compu_task);
taskwdInsert(taskId,NULL,NULL);
return(0);
}
short trigger = 0;
/*
* COMPU_DRIVER
*
* driver interface to the database library layer
*/
compu_driver(card,value_flag,arg1,arg2)
register short card;
short value_flag;
register int arg1;
register int arg2;
{
register int *pint;
register short *pshort;
short j,i;
char compu_msg[20];
/* verify the stepper motor driver card is present */
if ((card < 0) || (card > sm_num_cards[CM57_83E]) || (!pcompu_motors[card]))
return (-1);
switch (value_flag){
case (SM_MODE):
/* set the motor mode */
compu_motor_array[card].mode = arg1;
break;
case (SM_VELOCITY):
compu_motor_data_array[card].velocity = arg1;
compu_motor_data_array[card].accel = arg2;
/* set the velocity */
compu_msg[0] = SM_DEF_VEL_ACC;
compu_msg[1] = 0; /* time is in seconds */
compu_msg[2] = 0;
pint = (int *)&compu_msg[3]; /* velocity */
*pint = arg1;
pint++; /* acceleration */
*pint = arg2;
compu_send_msg(pcompu_motors[card],compu_msg,11);
break;
case (SM_MOVE):
if (compu_motor_array[card].mode == VELOCITY_MODE)
return(0);
i = 0;
switch (trigger){
case (0):
/* move the motor */
compu_msg[i++] = SM_MOV_REL_POS;
pint = (int *)&compu_msg[i];
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
case (1): /* test sequnce buffer */
compu_msg[i++] = 0xda; /* delete sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd9; /* fill sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = SM_MOV_REL_POS;
pint = (int *)&compu_msg[i];
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd8; /* end sequence buffer */
compu_msg[i++] = 0x41; /* perform sequence buffer */
compu_msg[i++] = 0x01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
case (2): /* test move buffer */
compu_msg[i++] = 0xc8;
compu_msg[i++] = 0x12;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x04;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x04;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
pint = (int *)&compu_msg[i];
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x40;
compu_msg[i++] = 0x12;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
case (3): /* test sequence buffer with move buffer */
compu_msg[i++] = 0xc8;
compu_msg[i++] = 0x12;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x04;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x04;
compu_msg[i++] = 0x00;
compu_msg[i++] = 0x00;
pint = (int *)&compu_msg[i];
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xda; /* delete sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd9; /* fill sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x40;
compu_msg[i++] = 0x12;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd8; /* end sequence buffer */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x41; /* perform sequence buffer */
compu_msg[i++] = 0x01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
case (4): /* test sequence buffer with move buffer and trigger */
compu_msg[i++] = 0xc8;
compu_msg[i++] = 0x12;
compu_msg[i++] = 0x00;
pint = (int *)&compu_msg[i];
*pint = compu_motor_data_array[card].velocity;
i += 4;
pint++;
*pint = compu_motor_data_array[card].accel;
i += 4;
pint++;
*pint = arg1;
i += 4;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xda; /* delete sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd9; /* fill sequence buffer */
compu_msg[i++] = 01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x2c; /* wait for trigger */
compu_msg[i++] = 1; /*trigger 1 */
compu_msg[i++] = 1; /* don't care about state */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x40;
compu_msg[i++] = 0x12;
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0xd8; /* end sequence buffer */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
compu_msg[i++] = 0x41; /* perform sequence buffer */
compu_msg[i++] = 0x01; /* buffer 1 */
compu_send_msg(pcompu_motors[card],compu_msg,i);
i = 0;
break;
}
for (j = 0; j < i; j++){
printf("%x ",compu_msg[j]);
}
/* compu_send_msg(pcompu_motors[card],compu_msg,i);
*/
/* set the motor to active */
compu_motor_array[card].active = TRUE;
/* wakeup the compu task */
semGive(compu_wakeup);
break;
case (SM_MOTION):
if (arg1 == 0){
compu_msg[0] = SM_STOP;
compu_send_msg(pcompu_motors[card],compu_msg,1);
}else if (compu_motor_array[card].mode == VELOCITY_MODE){
compu_msg[0] = SM_MOV_DEFAULT;
compu_msg[1] = arg2; /* direction */
compu_send_msg(pcompu_motors[card],compu_msg,2);
compu_motor_array[card].active = TRUE;
}
/* wakeup the compu task */
semGive(compu_wakeup);
break;
case (SM_CALLBACK):
/* put the callback routine and argument into the data array */
i = 0;
if (compu_motor_array[card].callback != 0) return(-1);
compu_motor_array[card].callback = arg1;
compu_motor_array[card].callback_arg = arg2;
break;
case (SM_SET_HOME):
if (compu_motor_array[card].mode == VELOCITY_MODE)
return(OK);
/* set the motor and encoder position to zero */
compu_msg[0] = SM_DEF_ABS_ZERO;
compu_send_msg(pcompu_motors[card],compu_msg,1);
break;
case (SM_ENCODER_RATIO):
compu_motor_array[card].motor_resolution = arg1;
/* set the encoder ratio */
compu_msg[0] = SM_DEF_RATIO;
pshort = (short *)&compu_msg[1];
*pshort = arg1; /* motor resolution */
pshort++;
*pshort = arg2; /* encoder resolution */
compu_send_msg(pcompu_motors[card],compu_msg,5);
/* set the motor resolution */
compu_msg[0] = SM_DEF_RESOLTN;
pshort = (short *)&compu_msg[1];
*pshort = 0;
pshort++;
*pshort = arg1; /* motor resolution */
compu_send_msg(pcompu_motors[card],compu_msg,5);
break;
case (SM_READ):
/* set the motor to active */
compu_motor_array[card].active = TRUE;
/* wakeup the compu task */
semGive(compu_wakeup);
break;
}
return (OK);
}
/*
* COMPU_SEND_MSG
*
* send a message to the compumotor 1830
*/
int wait_count;
compu_send_msg(pmotor,pmsg,count)
register struct compumotor *pmotor;
register char *pmsg;
register short count;
{
/* write out this command one byte at a time */
while (count){
/* wait for the driver to be ready */
while ((pmotor->cm_cb & SBIRDY) == 0){
taskDelay(0);
wait_count++;
}
/* next byte in the input data buffer of compumotor */
pmotor->cm_idb = *pmsg;
pmsg++;
count--;
/* tell compumotor more or complete */
if (count == 0){
pmotor->cm_cb = SND_LAST;
}else{
pmotor->cm_cb = SND_MORE;
}
}
}
/*
* COMPU_SM_IO_REPORT
*
* send a message to the compumotor 1830
*/
long compu_sm_io_report(level)
short int level;
{
register int i;
for (i = 0; i < sm_num_cards[CM57_83E]; i++){
if (pcompu_motors[i]){
printf("SM: CM1830: card %d\n",i);
if (level > 0)
compu_sm_stat(i);
}
}
return OK;
}
VOID compu_sm_stat(compu_num)
short int compu_num;
{
struct motor_data *pmotor_data;
printf("\tCW limit = %d\t,CCW limit = %d\tMoving = %d\tDirection = %d\n",
compu_motor_data_array[compu_num].cw_limit,
compu_motor_data_array[compu_num].ccw_limit,
compu_motor_data_array[compu_num].moving,
compu_motor_data_array[compu_num].direction);
printf("\tConstant Velocity = %d\t, Velocity = %d\t \n",
compu_motor_data_array[compu_num].constant_velocity,
compu_motor_data_array[compu_num].velocity);
printf("\tAcceleration = %d\tEncoder Position = %d\tMotor Position = %d\n",
compu_motor_data_array[compu_num].accel,
compu_motor_data_array[compu_num].encoder_position,
compu_motor_data_array[compu_num].motor_position);
}
/*
*
* Subroutine to be called during a CTL X reboot. Inhibits interrupts.
*
*/
VOID compu_sm_reset()
{
short int i;
char compu_msg[20];
for (i = 0; i < sm_num_cards[CM57_83E]; i++){
if (pcompu_motors[i]){
compu_msg[0] = SM_INT_INHBT;
compu_send_msg(pcompu_motors[i],compu_msg,1);
}
}
}
+526
View File
@@ -0,0 +1,526 @@
/* drvFp.c */
/* base/src/drv $Id$
* routines which are used to test and interface with the
* FP10S fast protect module
*
* Author: Matthew Stettler
* Date: 6-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 070992 integrated into GTACS & added std header
* .02 joh 070992 merged in include file fp.h
* .03 joh 070992 converted some symbols to LOCAL so they stay out
* of the vxWorks global symbol table
* .04 joh 070992 took out sysSetBCL() and substituted
* sysIntEnable() so this will not be hkv2f
* specific.
* .05 joh 070992 added INUM_TO_IVEC so this will be less
* 68k dependence (added include of iv.h)
* .06 joh 070992 FP_ILEV passed to call sysIntEnable() so that the
* interrupt level can be easily changed
* .07 joh 070992 changed some printf() calls to logMsg()
* so that driver diagnostics will show up in
* the log
* .08 joh 071092 now fetches base addr from module_types.h
* .09 joh 071092 added io_report routine
* .10 joh 071092 added scan task wakeup from ISR
* .11 joh 071092 moved ivec allocation to module_types.h
* .12 joh 072792 added soft reboot int disable
* .13 joh 082792 converted to V5 vxorks
* .14 mrk 090192 support epics I/O event scan, and added DRVET
* .15 mrk 080293 Add call to taskwdInsert
* .16 mgb 080493 Removed V5/V4 and EPICS_V2 conditionals
*/
/*
*
* Routines:
*
* fp_init Finds and initializes fast protect cards
* fp_driver System interface to FP10S modules
* fp_int Interrupt service routine
* fp_en Enables/disables interrupts (toggles)
* fp_mode Sets interrupt reporting mode
* fp_reboot Clean up for soft reboots
*
* Diagnostic Routines:
*
* fp_srd Reads current local inputs and enables
* fp_frd Reads last failure register
* fp_csrd Reads control/status register
* fp_read Command line interface to fp_driver
* fp_dump Prints all fast protect status to console
* fp_monitor Monitor all cards and print failure data to
* console
*
* Routines Return:
*
* -1 No card present
* -2 Interrupt connection error
* -3 Semaphore creation error
* -4 addressing error
* -5 no memory
* 0-8 successfull completion, or # of cards found
*
*/
static char *sccsId = "@(#)drvFp.c 1.12\t6/4/93";
#include "vxWorks.h"
#include "vme.h"
#include "taskLib.h"
#include <iv.h> /* in h/68k if this is compiling for a 68xxx */
#include "module_types.h"
#include <dbDefs.h>
#include <drvSup.h>
#include <taskwd.h>
#include <dbScan.h>
static long report();
static long init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvFp={
2,
report,
init};
static long report()
{
fp_io_report();
}
static long init()
{
fp_init(0);
return(0);
}
/* general constants */
#define FP_INTLEV 5 /* interrupt level */
#define FP_BUFSIZ 8 /* input buffer size */
/* csr bit definitions */
#define CSR_RST 0x1 /* reset status */
#define CSR_CMD1 0x2 /* force local fail */
#define CSR_IEN 0x4 /* interrupt enable */
#define CSR_UDEF0 0x8 /* undefined */
#define CSR_I0 0x10 /* interrupt level bit #1 */
#define CSR_I1 0x20 /* interrupt level bit #2 */
#define CSR_I2 0x40 /* interrupt level bit #3 */
#define CSR_UDEF1 0x80 /* undefined */
#define CSR_CARM0_L 0x100 /* latched carrier monitor #0 (one shot) */
#define CSR_CARM1_L 0x200 /* latched carrier monitor #1 (freq mon) */
#define CSR_OPTIC 0x400 /* optical carrier input enabled */
#define CSR_CARM 0x800 /* carrier OK */
#define CSR_LFAIL0 0x1000 /* local fail #0 (pal monitor) */
#define CSR_LFAIL1 0x2000 /* local fail #1 (fpga monitor) */
#define CSR_CMON 0x4000 /* clock fail (one shot) */
#define CSR_CHNG 0x8000 /* enable switch configuration change */
/* csr mask definitions */
#define CSR_STM 0xff00 /* status mask */
#define CSR_IM 0x70 /* interrupt level mask */
/* driver status */
#define DRV_MOM 0x010000 /* momentary fault */
#define DRV_LOC 0x020000 /* local fault */
#define DRV_REM 0x040000 /* remote fault */
#define DRV_CLR 0x080000 /* fault cleared */
#define DRV_HWF 0x800000 /* hardware fault */
/* operating modes */
#define FP_NMSG 0 /* no messages to console */
#define FP_TMSG 1 /* terse messages to console */
#define FP_FMSG 2 /* full messages to console */
#define FP_RUN 3 /* normal operating mode */
/* register address map for FP10s */
struct fp1
{
unsigned short csr; /* control and status register */
unsigned short srd; /* current status */
unsigned short frd; /* latched status */
unsigned short ivec; /* interrupt vector */
char end_pad[0xff-0x8]; /* pad to 256 byte boundary */
};
/* fast protect control structure */
struct fp_rec
{
struct fp1 *fptr; /* pointer to device registers */
unsigned int drvstat; /* fast protect physical inputs */
unsigned short lastswitch; /* previous enable switch data */
short type; /* device type */
short num; /* device number */
short fp_vector; /* interrupt vector */
short mode; /* operating mode */
unsigned int int_num; /* interrupt number */
IOSCANPVT ioscanpvt;
};
static struct fp_rec *fp; /* fast protect control structure */
static int fp_num; /* # of fast protect cards found -1 */
static SEM_ID fp_semid; /* semaphore for monitor task */
static void fp_reboot();
/*
* fp_int
*
* interrupt service routine
*
*/
fp_int(card)
unsigned card;
{
register struct fp_rec *ptr = &fp[card];
register struct fp1 *regptr;
unsigned short temp0, temp1, temp2;
regptr = ptr->fptr;
temp0 = regptr->csr;
temp1 = regptr->frd;
temp2 = regptr->srd;
switch (ptr->mode)
{
case FP_TMSG:
logMsg("fast protect interrupt!\n");
logMsg("csr status = %x\n",temp0);
break;
case FP_FMSG:
logMsg("fast protect #%d fault! fault input = %x enable switches = %x\n",
ptr->num,temp1 & 0xff,temp2>>8);
logMsg("csr status = %x\n",temp0);
break;
case FP_RUN:
ptr->drvstat = temp2; /* save last switch data */
ptr->drvstat |= temp1<<16; /* save fault data */
ptr->drvstat |= (temp0 & 0xff00)<<16; /* csr status bits */
if ((temp1 ^ (temp2>>8)) || (temp0 & CSR_CHNG)) /* fault or enable change */
semGive(fp_semid); /* wake up monitor */
/*
* wakeup the interrupt driven scanner
*/
scanIoRequest(fp[card].ioscanpvt);
break;
}
ptr->int_num++; /* log interrupt */
regptr->csr |= CSR_RST; /* clear status and rearm */
regptr->csr ^= CSR_RST;
}
/*
* fp_init
*
* initialization routine for FP10s fast protect modules
*
*
*/
fp_init(addr)
unsigned int addr;
{
int i;
short junk;
short intvec = AT8FP_IVEC_BASE;
struct fp1 *ptr;
int status;
fp = (struct fp_rec *) calloc(bi_num_cards[AT8_FP10S_BI], sizeof(*fp));
if(!fp){
return -5;
}
if(!addr){
addr = bi_addrs[AT8_FP10S_BI];
}
status = sysBusToLocalAdrs( VME_AM_SUP_SHORT_IO, addr, &ptr);
if(status<0){
logMsg("VME shrt IO addr err in the slave fast protect driver\n");
return(-4);
}
status = rebootHookAdd(fp_reboot);
if(status<0){
logMsg("%s: reboot hook add failed\n", __FILE__);
}
for (i = 0;
(i < bi_num_cards[AT8_FP10S_BI]) && (vxMemProbe(ptr,READ,2,&junk) == OK);
i++,ptr++) {
/* register initialization */
ptr->csr = 0x0000; /* disable interface */
fp[i].fptr = ptr; /* hardware location */
fp[i].fp_vector = intvec++; /* interrupt vector */
ptr->ivec = fp[i].fp_vector; /* load vector */
fp[i].mode = FP_NMSG; /* set default mode (no messages) */
fp[i].int_num = 0; /* initialize interrupt number */
fp[i].type = 10; /* board type */
fp[i].num = i; /* board number */
/* initialize input buffer */
fp[i].drvstat = ptr->srd; /* initialize enable switch data */
fp[i].drvstat |= ptr->frd<<16; /* initialize fault data */
fp[i].drvstat |= (ptr->csr & 0xff00)<<16; /* csr status bits */
/* set up interrupt handler */
ptr->csr |= FP_INTLEV<<4; /* level 5 interrupt */
if (intConnect(INUM_TO_IVEC(fp[i].fp_vector),fp_int,i) != OK)
return(-2); /* abort if can't connect */
sysIntEnable(FP_INTLEV);
ptr->csr |= 0x0001;
ptr->csr ^= 0x0001; /* clear status bits */
if (ptr->csr & CSR_OPTIC)
logMsg("fast protect #%d optically coupled\n",i);
else
logMsg("fast protect #%d elecrically coupled\n",i);
/* start up module */
fp[i].fptr->csr |= CSR_IEN; /* enable interrupts */
fp[i].mode = FP_RUN; /* normal run mode */
scanIoInit(&fp[i].ioscanpvt);
}
fp_num = i - 1; /* record max card # */
/* create the semaphore */
fp_semid = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
if ((int)fp_semid == 0) /* abort if can't create semaphore */
return(-3);
return(i); /* return # found */
}
/*
*
* fp_reboot()
*
* turn off interrupts to avoid ctrl X reboot problems
*/
LOCAL
void fp_reboot()
{
int i;
if(!fp){
return;
}
for (i = 0; i < bi_num_cards[AT8_FP10S_BI]; i++){
if(!fp[i].fptr){
continue;
}
fp[i].fptr->csr &= ~CSR_IEN;
}
}
/*
* fp_en
*
* interrupt enable/disable
* (toggles the interrupt enable - joh)
*
*/
fp_en(card)
short card;
{
unsigned short temp;
if (card < 0 || (card > fp_num))
return -1;
fp[card].fptr->csr = fp[card].fptr->csr ^ CSR_IEN;
if (fp[card].fptr->csr & CSR_IEN)
printf("fast protect interrupts enabled\n");
else
printf("fast protect interrupts disabled\n");
return 0;
}
/*
* fp_mode
*
* set interrupt reporting mode
*
*/
fp_mode(card,mode)
short card, mode;
{
if (card < 0 || (card > fp_num))
return -1;
fp[card].mode = mode;
return 0;
}
/*
* fp_srd
*
* read current local inputs and enable switches
*
*/
fp_srd(card,option)
short card;
short option;
{
if (card > fp_num) return -1;
if (!option)
printf("local inputs = %x enable switches = %x\n",fp[card].fptr->srd & 0xff,
fp[card].fptr->srd>>8);
return fp[card].fptr->srd;
}
/*
* fp_frd
*
* read latched local inputs
*
*/
fp_frd(card)
short card;
{
if (card < 0 || (card > fp_num))
return -1;
return fp[card].fptr->frd & 0xff;
}
/*
* fp_csrd
*
* read csr contents
*
*/
fp_csrd(card)
short card;
{
if (card < 0 || (card > fp_num))
return -1;
return fp[card].fptr->csr & 0xff77;
}
/*
* fp_driver
*
* epics interface to fast protect
*
*/
fp_driver(card,mask,prval)
register unsigned short card;
unsigned int mask;
register unsigned int *prval;
{
register unsigned int temp;
if (card > fp_num) return -1;
temp = fp[card].drvstat & 0xffff0000; /* latched status info */
temp |= fp[card].fptr->srd; /* current switches & inputs */
*prval = temp & mask;
return 0;
}
/*
* fp_read
*
* command line interface to fp_driver
*
*/
fp_read(card)
short card;
{
unsigned int fpval,ret;
if ((ret = fp_driver(card,0xffffffff,&fpval)) != 0)
return ret;
printf("Card #%d enable switches = %x inputs = %x\n",card,(fpval & 0x0000ff00)>>8,
fpval & 0x000000ff);
printf("csr status = %x last fault = %x\n",fpval>>24,(fpval & 0x00ff0000)>>16);
printf("raw readback = %x\n",fpval);
return 0;
}
/*
* fp_dump
*
* dump fast protect status to console
*
*/
fp_dump()
{
int i;
printf("Fast protect status (fault and CSR are latched):\n");
printf("Card#\tenables\tinputs\tfault\tCSR status\n");
for(i = 0; i < (fp_num + 1); i++)
printf("%d\t%x\t%x\t%x\t%x\n",i,fp[i].fptr->srd>>8,fp[i].fptr->srd & 0xff,
(fp[i].drvstat & 0x00ff0000)>>16,fp[i].drvstat>>24);
return i;
}
/*
* fp_monitor
*
* monitor fast protect cards and report failures to console
*
*/
fp_mon()
{
for(semTake(fp_semid,WAIT_FOREVER);fp_dump() != 0;semTake(fp_semid,WAIT_FOREVER));
}
fp_monitor()
{
static char *name = "fpmon";
int tid;
if ((tid = taskNameToId(name)) != ERROR) {
taskwdRemove(tid);
taskDelete(tid);
}
if((tid = taskSpawn(name,25,VX_SUPERVISOR_MODE|VX_STDIO,
1000,fp_mon)) == ERROR) return -1;
taskwdInsert(tid,NULL,NULL);
return 0;
}
fp_io_report(level)
int level;
{
int i;
for(i=0; i<=fp_num; i++){
printf("BI: AT8-FP-S: card %d\n", i);
}
}
fp_getioscanpvt(card,scanpvt)
short card;
IOSCANPVT *scanpvt;
{
if ((card >= bi_num_cards[AT8_FP10S_BI])) return(0);
*scanpvt = fp[card].ioscanpvt;
return(0);
}
+432
View File
@@ -0,0 +1,432 @@
/* drvFpm.c */
/* base/src/drv $Id$ */
/*
* control routines for use with the FP10M fast protect master modules
*
* routines which are used to test and interface with the
* FP10S fast protect module
*
* Author: Matthew Stettler
* Date: 6-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 070992 integrated into GTACS & added std header
* .02 joh 070992 merged in include file fpm.h
* .03 joh 070992 converted some symbols to LOCAL so they stay out
* of the vxWorks global symbol table
* .04 joh 070992 took out sysSetBCL() and substituted
* sysIntEnable() so this will not be hkv2f
* specific.
* .05 joh 070992 added INUM_TO_IVEC so this will be less
* 68k dependence (added include of iv.h)
* .06 joh 070992 FP_ILEV passed to call sysIntEnable() so that the
* interrupt level can be easily changed
* .07 joh 071092 now fetches base addr from module_types.h
* .08 joh 071092 added io report routine
* .09 joh 071092 allocate config structure at run time so that
* the users can adjust the number of cards without
* recompilation
* .10 joh 071092 moved ivec allocation to module_types.h
* .11 joh 072792 added soft reboot int disable
* .12 mrk 090292 added DRVET
* .13 mgb 080493 Removed V5/V4 and EPICS_V2 conditionals
*
*
* Routines:
*
* fpm_init Finds and initializes FP10M cards
* fpm_driver System interface to FP10M modules
* fpm_read Carrier control readback
* fpm_reboot clean up before soft reboots
*
* Daignostic Routines
* fpm_en Enables/disables interrupts (diagnostic enable)
* fpm_mode Sets interrupt reporting mode (logs mode
* changes to console)
* fpm_cdis Disables carrier from console
* fpm_fail Sets carrier failure mode
* fpm_srd Reads current carrier status
* fpm_write Command line interface to fpm_driver
*
* Routines return:
*
* -1 Nonexistent card
* -2 Interrupt connection error
* -3 no memory
* -4 VME short IO bus nonexistent
* 0-2 Successfull completion, or # cards found
*
*/
static char *sccsId = "@(#)drvFpm.c 1.12\t8/4/93";
#include "vxWorks.h"
#include "vme.h"
#include <iv.h> /* in h/68k if this is compiling for a 68xxx */
#include "module_types.h"
#include <dbDefs.h>
#include <drvSup.h>
static long report();
static long init();
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvFpm={
2,
report,
init};
static long report()
{
fpm_io_report();
}
static long init()
{
fpm_init(0);
return(0);
}
/* general constants */
#define FPM_INTLEV 5 /* interrupt level */
/* control register bit definitions */
#define CR_CDIS 0x1 /* software carrier disable */
#define CR_FS0 0x2 /* fail select 0 */
#define CR_FS1 0x4 /* fail select 1 */
#define CR_FS2 0x8 /* fail select 2 */
#define CR_I0 0x10 /* interrupt level bit 0 */
#define CR_I1 0x20 /* interrupt level bit 1 */
#define CR_I2 0x40 /* interrupt level bit 2 */
#define CR_IEN 0x80 /* interrupt enable */
/* control register mask definitions */
#define CR_IM 0x70 /* interrupt level mask */
/* status register bit definitions */
#define SR_S0 0x1 /* error sequencer state bit 0 */
#define SR_S1 0x2 /* error sequencer state bit 1 */
#define SR_S2 0x3 /* error sequencer state bit 2 */
/* status register mask definitions */
#define SR_EM 0x7 /* error state mask */
/* operating modes */
#define FPM_NMSG 0 /* no messages to console */
#define FPM_TMSG 1 /* terse messages to console */
#define FPM_FMSG 2 /* full messages to console */
/* register address map for FP10M */
struct fp10m
{
unsigned short cr; /* control register */
unsigned short sr; /* status register */
unsigned short ivec; /* interrupt vector */
char end_pad[0xff-0x6]; /* pad to 256 byte boundary */
};
/* control structure */
struct fpm_rec
{
struct fp10m *fmptr; /* pointer to device registers */
short type; /* device type */
short num; /* board number */
short vector; /* interrupt vector */
short mode; /* operating mode */
unsigned int int_num; /* interrupt number */
};
static struct fpm_rec *fpm; /* fast protect control structure */
static int fpm_num; /* # cards found - 1 */
static void fpm_reboot();
/*
* fpm_int
*
* interrupt service routine
*
*/
fpm_int(ptr)
register struct fpm_rec *ptr;
{
register struct fp10m *regptr;
regptr = ptr->fmptr;
switch (ptr->mode)
{
case FPM_TMSG:
logMsg("fast protect master interrupt!\n");
break;
case FPM_FMSG:
logMsg("fast protect master interrupt!\n");
logMsg("cr = %x sr = %x\n",regptr->cr,regptr->sr & 0x7);
break;
}
ptr->int_num++;
}
/*
* fpm_init
*
* initialization for fp10m fast protect master modules
*
*/
fpm_init(addr)
unsigned int addr;
{
int i;
short junk;
short intvec = AT8FPM_IVEC_BASE;
struct fp10m *ptr;
int status;
fpm = (struct fpm_rec *) calloc(
bo_num_cards[AT8_FP10M_BO],
sizeof(*fpm));
if(!fpm){
return -3;
}
if(!addr){
addr = bo_addrs[AT8_FP10M_BO];
}
status = sysBusToLocalAdrs(
VME_AM_SUP_SHORT_IO,
addr,
&ptr);
if(status<0){
logMsg("VME shrt IO addr err in the master fast protect driver\n");
return -4;
}
status = rebootHookAdd(fpm_reboot);
if(status<0){
logMsg("%s: reboot hook add failed\n", __FILE__);
}
for (i = 0; (i < bo_num_cards[AT8_FP10M_BO]) && (vxMemProbe(ptr,READ,2,&junk) == OK);
i++,ptr++)
{
/*
register initialization
*/
ptr->cr = 0x00; /* disable interface */
fpm[i].fmptr = ptr; /* hardware location */
fpm[i].vector = intvec++; /* interrupt vector */
ptr->ivec = fpm[i].vector; /* load vector */
fpm[i].mode = FPM_NMSG; /* set default mode (no messages) */
fpm[i].int_num = 0; /* initialize interrupt number */
fpm[i].type = 2; /* board type */
fpm[i].num = i; /* board number */
/*
set up interrupt handler
*/
ptr->cr |= FPM_INTLEV<<4; /* set up board for level 5 interrupt */
if (intConnect(INUM_TO_IVEC(fpm[i].vector),fpm_int,&fpm[i]) != OK)
return -2; /* abort if can't connect */
sysIntEnable(FPM_INTLEV);
}
fpm_num = i - 1; /* record last card # */
return i; /* return # cards found */
}
/*
*
* fpm_reboot()
*
* turn off interrupts to avoid ctrl X reboot problems
*/
LOCAL
void fpm_reboot()
{
int i;
if(!fpm){
return;
}
for (i = 0; i < bo_num_cards[AT8_FP10M_BO]; i++){
if(!fpm[i].fmptr){
continue;
}
fpm[i].fmptr->cr &= ~CR_IEN;
}
}
/*
* fpm_en
*
* interrupt enable/disable
* (toggles the int enable state - joh)
*
*/
fpm_en(card)
short card;
{
if (card < 0 || (card > fpm_num))
return -1;
fpm[card].fmptr->cr ^= CR_IEN;
if (fpm[card].fmptr->cr & CR_IEN)
printf("fast protect master interrupts enabled\n");
else
printf("fast protect master interrupts disabled\n");
return 0;
}
/*
* fpm_mode
*
* set interrupt reporting mode
*
*/
fpm_mode(card,mode)
short card, mode;
{
if (card < 0 || (card > fpm_num))
return -1;
fpm[card].mode = mode;
return 0;
}
/*
* fpm_cdis
*
* carrier disable (1), enable (0)
*
*/
fpm_cdis(card,disable)
short card, disable;
{
unsigned short temp;
if (card < 0 || (card > fpm_num))
return -1;
temp = fpm[card].fmptr->cr;
temp &= 0xfe;
temp |= (disable & 0x01);
fpm[card].fmptr->cr = temp;
return 0;
}
/*
* fpm_fail
*
* set failure mode
*
*/
fpm_fail(card,mode)
short card, mode;
{
unsigned short temp;
if (card < 0 || (card > fpm_num))
return -1;
temp = fpm[card].fmptr->cr;
temp &= 0xf1;
temp |= (mode & 0x7)<<1;
fpm[card].fmptr->cr = temp;
return 0;
}
/*
* fpm_srd
*
* read status bits
*
*/
fpm_srd(card)
short card;
{
if (card < 0 || ( card > fpm_num))
return -1;
return fpm[card].fmptr->sr & 0x7;
}
/*
* fpm_driver
*
* epics interface to fast protect master
*
*/
fpm_driver(card,mask,prval)
register unsigned short card;
unsigned int mask;
register unsigned int prval;
{
register unsigned int temp;
if (card > fpm_num)
return -1;
temp = fpm[card].fmptr->cr;
fpm[card].fmptr->cr = (temp & (~mask | 0xf0)) | ((prval & mask) & 0xf);
return 0;
}
/*
* fpm_write
*
* command line interface to fpm_driver
*
*/
fpm_write(card,val)
short card;
unsigned int val;
{
return fpm_driver(card,0xffffffff,val);
}
/*
* fpm_read
*
* read the current control register contents (readback)
*
*/
fpm_read(card,mask,pval)
register unsigned short card;
unsigned int mask;
register unsigned int *pval;
{
if (card > fpm_num)
return -1;
*pval = fpm[card].fmptr->cr & 0x000f;
return 0;
}
/*
* fpm_io_report()
*
*/
fpm_io_report(level)
int level;
{
int i;
for(i=0; i<=fpm_num; i++){
printf("BO: AT8-FP-M: card %d\n", i);
}
}
+641
View File
@@ -0,0 +1,641 @@
/* drvJgvtr1.c */
/* base/src/drv $Id$ */
/*
* Author: Jeff Hill
* Date: 5-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:
* -----------------
* 110689 joh print mem not full message only once
* 120789 joh temporary removal of memory full check
* 050190 joh clear ptr to callback prior to calling
* it so they can rearm from inside the callback
* 071190 joh check STD address after cycle complete detected
* to avoid erroneous card misaddressed messages
* 071190 joh internal sample rate status is bit reversed on the
* card- I added a lookup table to untwist it.
* 020491 ges Change taskDelay from 20 to 2 in "jgvtr1DoneTask".
* To allow rearm and data reads from succesive
* waveform scans up thru 10Hz rates.
* 031491 lrd move data into a local memory area for each card
* 090591 joh converted to V5 vxWorks
* 110591 lrd initialization of cards other than 0 not
* allocating data buffer correctly
* 013092 bg added sysBusToLocalAdrs. Added levels to io_report
* and the ability to read out the Joerger's raw values
* in io_report if level is > 1.
* 031992 joh Took the vxMemProbe out of each arm and checked
* the card present bit instead.
* 062592 bg Combined drvJgvtr1.c and jgvtr_driver.c
* 062992 joh removed file pointer argument added to io
* report by bg
* 082792 joh added ANSI C function prototypes
* 080293 mrk added call to taskwdInsert
* 080493 mgb Removed V5/V4 and EPICS_V2 conditionals
*/
static char *sccsID = "@(#)drvJgvtr1.c 1.17\t9/9/93";
/*
* Code Portions
*
* jgvtr1_init()
* jgvtr1_driver(card, pcbroutine, parg)
* jgvtr1_int_service()
* jgvtr1DoneTask()
* jgvtr1_io_report()
* jgvtr1_stat(card)
*
*/
/* drvJgvtr1.c - Driver Support Routines for Jgvtr1 */
#include <vxWorks.h>
#include <types.h>
#include <vme.h>
#include <iv.h>
#include <sysLib.h>
#include <stdioLib.h>
#include <dbDefs.h>
#include <drvSup.h>
#include <module_types.h>
#include <task_params.h>
#include <fast_lock.h>
#include <taskwd.h>
#include <devLib.h>
#include <drvJgvtr1.h>
LOCAL jgvtr1Stat jgvtr1_io_report(
unsigned level
);
LOCAL jgvtr1Stat jgvtr1_init(
void
);
#ifdef INTERRUPT_HARDWARE_FIXED
LOCAL void jgvtr1_int_service(
void
);
#endif
LOCAL void jgvtr1DoneTask(
void
);
LOCAL jgvtr1Stat jgvtr1_dump(
unsigned card,
unsigned n
);
LOCAL jgvtr1Stat jgvtr1_stat(
unsigned card,
int level
);
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvJgvtr1={
2,
jgvtr1_io_report,
jgvtr1_init};
static volatile char *stdaddr;
static volatile char *shortaddr;
#define JGVTR1MAXFREQ 25.0e6
/* NBBY - the number of bits per byte */
#define JGVTR1SHORTSIZE (1<<(NBBY*sizeof(uint8_t)))
#define JGVTR1STDSIZE (1<<(NBBY*sizeof(uint16_t)))
#define JGVTR1_INT_LEVEL 5
#define JGVTR1BASE(CARD)\
(shortaddr+wf_addrs[JGVTR1]+(CARD)*JGVTR1SHORTSIZE)
#define JGVTR1DATA(CARD)\
(stdaddr+wf_memaddrs[JGVTR1]+(CARD)*JGVTR1STDSIZE)
/*
Joerger fixed hardware bug by switching to an inverting tristate buffer
where these commands are read from the VME bus. As a result these commands
are complemented.
*/
#define JGVTR1ARM (~1)
#define JGVTR1START (~2)
#define JGVTR1STOP (~4)
/*
!! our compiler allocates bit fields starting from the ms bit !!
*/
struct jgvtr1_status{
volatile unsigned pad:8;
volatile unsigned internal_frequency:3;
volatile unsigned internal_clock:1;
volatile unsigned cycle_complete:1;
volatile unsigned interrupt:1;
volatile unsigned active:1;
volatile unsigned memory_full:1;
};
struct jgvtr1_config{
char present; /* card present */
char std_ok; /* std addr ok on first read */
void (*psub) /* call back routine */
(void *pprm, unsigned nbytes, uint16_t *pData);
void *pprm; /* call back parameter */
FAST_LOCK lock; /* mutual exclusion */
uint16_t *pdata; /* pointer to the data buffer */
};
/* amount of data to make available from the waveform */
#define JRG_MEM_SIZE 2048
LOCAL
struct jgvtr1_config *pjgvtr1_config;
LOCAL
int jgvtr1_max_card_count;
#ifdef INTERRUPT_HARDWARE_FIXED
LOCAL
SEM_ID jgvtr1_interrupt; /* interrupt event */
#endif
/*
* JGVTR1_INIT
*
* intialize the driver for the joerger vtr1
*
*/
jgvtr1Stat jgvtr1_init(void)
{
unsigned card;
unsigned card_count = 0;
struct jgvtr1_config *pconfig;
uint16_t readback;
jgvtr1Stat status;
status = sysBusToLocalAdrs(
VME_AM_SUP_SHORT_IO,
0,
(char **)&shortaddr);
if (status != OK){
status = S_dev_badA16;
errMessage(status,NULL);
return status;
}
status = sysBusToLocalAdrs(
VME_AM_STD_SUP_DATA,
0,
(char **)&stdaddr);
if (status != OK){
status = S_dev_badA24;
errMessage(status,NULL);
return status;
}
jgvtr1_max_card_count = wf_num_cards[JGVTR1];
if(pjgvtr1_config){
if(FASTLOCKFREE(&pjgvtr1_config->lock)<0)
return ERROR;
free(pjgvtr1_config);
}
pjgvtr1_config =
(struct jgvtr1_config *)
calloc(wf_num_cards[JGVTR1], sizeof(*pjgvtr1_config));
if(!pjgvtr1_config){
status = S_dev_noMemory;
errMessage(status,NULL);
return status;
}
for( card=0, pconfig=pjgvtr1_config;
card < wf_num_cards[JGVTR1];
pconfig++, card++){
FASTLOCKINIT(&pconfig->lock);
status = vxMemProbe( (char *)JGVTR1BASE(card),
READ,
sizeof(readback),
(char *)&readback);
if(status==ERROR)
continue;
pconfig->pdata =
(uint16_t *)malloc(JRG_MEM_SIZE);
/*
not easy to test for correct addressing in
standard address space since the module does
not respond if it has not clocked in data
- so I check this the first time data is ready
*/
pconfig->std_ok = FALSE; /* presumed guilty before tested */
pconfig->present = TRUE;
card_count++;
}
if(!card_count)
return OK;
# ifdef INTERRUPT_HARDWARE_FIXED
jgvtr1_interrupt = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
if(!jgvtr1_interrupt)
return ERROR;
# endif
/* start the waveform readback task */
status = taskSpawn( WFDONE_NAME,
WFDONE_PRI,
WFDONE_OPT,
WFDONE_STACK,
(FUNCPTR) jgvtr1DoneTask,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if(status < 0){
status = S_dev_internal;
errMessage(status, "vxWorks taskSpawn failed");
return status;
}
taskwdInsert(status, NULL, NULL);
# ifdef INTERRUPT_HARDWARE_FIXED
status = intConnect( INUM_TO_IVEC(JGVTR1_INT_VEC),
jgvtr1_int_service,
NULL);
if(status != OK)
return S_dev_internal;
sysIntEnable(JGVTR_INT_LEVEL);
# endif
return JGVTR1_SUCCESS;
}
/*
* JGVTR1_DRIVER
*
* initiate waveform read
*
*/
jgvtr1Stat jgvtr1_driver(
unsigned card,
void (*pcbroutine)(void *, unsigned, uint16_t *),
void *parg
)
{
if(card >= jgvtr1_max_card_count)
return S_dev_badSignalNumber;
if(!pjgvtr1_config[card].present)
return S_dev_noDevice;
if(pjgvtr1_config[card].psub)
return S_dev_badRequest;
FASTLOCK(&pjgvtr1_config[card].lock);
*(volatile uint16_t *)JGVTR1BASE(card) = JGVTR1ARM;
pjgvtr1_config[card].pprm = parg;
pjgvtr1_config[card].psub = pcbroutine;
FASTUNLOCK(&pjgvtr1_config[card].lock);
return JGVTR1_SUCCESS;
}
/*
* JGVTR1_INT_SERVICE
*
* signal via the RTK that an interrupt occured from the joerger vtr1
*
*/
#ifdef INTERRUPT_HARDWARE_FIXED
LOCAL void jgvtr1_int_service(void)
{
semGive(jgvtr1_interrupt);
}
#endif
/*
* JGVTR1DONETASK
*
* wait for joerger vtr1 waveform record cycle complete
* and call back to the database with the waveform size and address
*
*/
LOCAL void jgvtr1DoneTask(void)
{
unsigned card;
struct jgvtr1_config *pconfig;
struct jgvtr1_status stat;
static char started = FALSE;
volatile uint16_t *pdata;
volatile uint16_t *pjgdata;
long i;
/* dont allow two of this task */
if(started)
exit(0);
started = TRUE;
while(TRUE){
# ifdef INTERRUPT_HARDWARE_FIXED
semTake(jgvtr1_interrupt, WAIT_FOREVER);
# else
/* ges: changed from 20 ticks to 2 ticks 2/4/91 */
taskDelay(2);
# endif
for( card=0, pconfig = pjgvtr1_config;
card < jgvtr1_max_card_count;
card++, pconfig++){
if(!pconfig->present)
continue;
if(!pconfig->psub)
continue;
stat = *(struct jgvtr1_status *) JGVTR1BASE(card);
/*
* Wait for the module to finish filling its memory
* or a stop trigger
*/
if(!stat.cycle_complete)
continue;
/*
clear ptr to function here so they
can rearm in the callback
*/
pconfig->psub = NULL;
/*
check the first time for module
correctly addressed
card does not respond at STD address
until it has data
*/
if(!pconfig->std_ok){
uint16_t readback;
int status;
status = vxMemProbe(
(char *)JGVTR1DATA(card),
READ,
sizeof(readback),
(char *)&readback);
if(status==ERROR){
errPrintf(
S_dev_badA24,
__FILE__,
__LINE__,
"jgvtr1 card %d incorrectly addressed- use std addr 0X%X",
card,
JGVTR1DATA(card));
pconfig->present = FALSE;
continue;
}
pconfig->std_ok = TRUE;
}
/*
Test for full memory
( card designer does not give a sample count register )
( instead a bus error returned when on the last sample
to test every location is a lot of overhead so a test
for memory full is used for now )
*/
if(!stat.memory_full){
errMessage(S_dev_internal,
"jgvtr1 driver: proceeding with partial mem");
errMessage(S_dev_internal,
"jgvtr1 driver: beware of bus errors");
}
/* copy the data into a local memory buffer */
/* this is to avoid any bus errors */
for(i = 0,
pdata = pconfig->pdata,
pjgdata = (volatile uint16_t *)JGVTR1DATA(card);
i < JRG_MEM_SIZE/sizeof(uint16_t);
i++, pdata++, pjgdata++){
*pdata = *pjgdata;
}
/*
Post waveform to the database
perhaps the size must be the size below+1 ?
(Joerger's documentation is not clear here)
*/
(*pconfig->psub)(pconfig->pprm,JRG_MEM_SIZE,pconfig->pdata);
}
}
}
/*
*
* JGVTR1_IO_REPORT
*
* print status for all cards in the specified joerger
* vtr1 address range
*
*
*/
LOCAL jgvtr1Stat jgvtr1_io_report(unsigned level)
{
unsigned card;
unsigned nelements;
jgvtr1Stat status;
for(card=0; card < wf_num_cards[JGVTR1]; card++){
status = jgvtr1_stat(card,level);
if(status){
continue;
}
if (level >= 2){
printf("enter the number of elements to dump:");
status = scanf("%d",&nelements);
if(status == 1){
jgvtr1_dump(card, nelements);
}
}
}
return JGVTR1_SUCCESS;
}
/*
*
* JGVTR1_STAT
*
* print status for a single card in the joerger vtr1 address range
*
*
*/
jgvtr1Stat jgvtr1_stat(
unsigned card,
int level
)
{
struct jgvtr1_status stat;
jgvtr1Stat status;
/*
internal freq status is bit reversed so I
use a lookup table
*/
static float sample_rate[8] = {
JGVTR1MAXFREQ/(1<<7),
JGVTR1MAXFREQ/(1<<3),
JGVTR1MAXFREQ/(1<<5),
JGVTR1MAXFREQ/(1<<1),
JGVTR1MAXFREQ/(1<<6),
JGVTR1MAXFREQ/(1<<2),
JGVTR1MAXFREQ/(1<<4),
JGVTR1MAXFREQ/(1<<0)};
static char *clock_status[] =
{"ext-clock", "internal-clk"};
static char *cycle_status[] =
{"cycling", "done"};
static char *interrupt_status[] =
{"", "int-pending"};
static char *activity_status[] =
{"", "active"};
static char *memory_status[] =
{"", "mem-full"};
status = vxMemProbe( (char *)JGVTR1BASE(card),
READ,
sizeof(stat),
(char *)&stat);
if(status != OK)
return ERROR;
if (level == 0)
printf("WF: JGVTR1:\tcard=%d \n",card);
else if (level > 0)
printf( "WF: JGVTR1:\tcard=%d Sample rate=%g %s %s %s %s %s \n",
card,
sample_rate[stat.internal_frequency],
clock_status[ stat.internal_clock ],
cycle_status[ stat.cycle_complete ],
interrupt_status[ stat.interrupt ],
activity_status[ stat.active ],
memory_status[ stat.memory_full ]);
return JGVTR1_SUCCESS;
}
/*
* jgvtr1_dump
*
*/
LOCAL jgvtr1Stat jgvtr1_dump(
unsigned card,
unsigned n
)
{
volatile uint16_t *pjgdata;
uint16_t *pread;
uint16_t *pdata;
unsigned nread;
jgvtr1Stat status;
/* Print out the data if user requests it. */
n = min(JRG_MEM_SIZE,n);
pdata = (uint16_t *)malloc(n * (sizeof(*pdata)));
if(!pdata){
return S_dev_noMemory;
}
pread = pdata;
nread = 0;
pjgdata = (volatile uint16_t *)JGVTR1DATA(card);
while(nread <= (n>>1)){
status = vxMemProbe(
(char *)pjgdata,
READ,
sizeof(*pread),
(char *)pread);
if(status<0){
break;
}
nread++;
pread++;
pjgdata++;
}
for(pread=pdata; pread<&pdata[nread]; pread++){
if ((pread-pdata)%8 == 0){
printf("\n\t");
}
printf( "%02X %02X ",
(unsigned char) ((*pread)>>8),
(unsigned char) *pread);
}
printf("\n");
free(pdata);
return JGVTR1_SUCCESS;
}
+43
View File
@@ -0,0 +1,43 @@
/* drvJgvtr1.h */
/* base/src/drv $Id$ */
/*
* Author: Jeff Hill
* Date: 5-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 jgvtr1Stat;
#define JGVTR1_SUCCESS 0
jgvtr1Stat jgvtr1_driver(
unsigned card,
void (*pcbroutine)(void *, unsigned, uint16_t *),
void *parg
);
+241
View File
@@ -0,0 +1,241 @@
/* module_types.c */
/* base/src/drv $Id$ */
/*
* Author: Marty Kraimer
* Date: 08-23-93
*
* 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-23-93 mrk Initial Version
*/
#include <module_types.h>
module_types()
{
ai_num_cards[AB1771IL] = 12;
ai_num_cards[AB1771IFE] = 12;
ai_num_cards[AB1771IXE] = 12;
ai_num_cards[XY566SE] = 2;
ai_num_cards[XY566DI] = 2;
ai_num_cards[XY566DIL] = 2;
ai_num_cards[VXI_AT5_AI] = 32;
ai_num_cards[AB1771IFE_SE] = 12;
ai_num_cards[AB1771IFE_4to20MA] = 12;
ai_num_cards[DVX2502] = 1;
ai_num_cards[AB1771IFE_0to5V] = 12;
ai_num_cards[KSCV215] = 32;
ai_num_channels[AB1771IL] = 8;
ai_num_channels[AB1771IFE] = 8;
ai_num_channels[AB1771IXE] = 8;
ai_num_channels[XY566SE] = 32;
ai_num_channels[XY566DI] = 16;
ai_num_channels[XY566DIL] = 16;
ai_num_channels[VXI_AT5_AI] = 8;
ai_num_channels[AB1771IFE_SE] = 16;
ai_num_channels[AB1771IFE_4to20MA] = 8;
ai_num_channels[DVX2502] = 127;
ai_num_channels[AB1771IFE_0to5V] = 8;
ai_num_channels[KSCV215] = 32;
ai_addrs[AB1771IL] = 0;
ai_addrs[AB1771IFE] = 0;
ai_addrs[AB1771IXE] = 0;
ai_addrs[XY566SE] = 0x6000;
ai_addrs[XY566DI] = 0x7000;
ai_addrs[XY566DIL] = 0x7800;
ai_addrs[VXI_AT5_AI] = 0xc014;
ai_addrs[AB1771IFE_SE] = 0;
ai_addrs[AB1771IFE_4to20MA] = 0;
ai_addrs[DVX2502] = 0xff00;
ai_addrs[AB1771IFE_0to5V] = 0;
ai_addrs[KSCV215] = 0;
ai_memaddrs[AB1771IL] = 0;
ai_memaddrs[AB1771IFE] = 0;
ai_memaddrs[AB1771IXE] = 0;
ai_memaddrs[XY566SE] = 0x000000;
ai_memaddrs[XY566DI] = 0x040000;
ai_memaddrs[XY566DIL] = 0x0c0000;
ai_memaddrs[VXI_AT5_AI] = 0;
ai_memaddrs[AB1771IFE_SE] = 0;
ai_memaddrs[AB1771IFE_4to20MA] = 0;
ai_memaddrs[DVX2502] = 0x100000;
ai_memaddrs[AB1771IFE_0to5V] = 0;
ai_memaddrs[KSCV215] = 0;
ao_num_cards[AB1771OFE] = 12;
ao_num_cards[VMI4100] = 4;
ao_num_cards[ZIO085] = 1;
ao_num_cards[VXI_AT5_AO] = 32;
ao_num_channels[AB1771OFE] = 4;
ao_num_channels[VMI4100] = 16;
ao_num_channels[ZIO085] = 32;
ao_num_channels[VXI_AT5_AO] = 16;
ao_addrs[AB1771OFE] = 0;
ao_addrs[VMI4100] = 0x4100;
ao_addrs[ZIO085] = 0x0800;
ao_addrs[VXI_AT5_AO] = 0xc000;
bi_num_cards[ABBI_08_BIT] = 12;
bi_num_cards[ABBI_16_BIT] = 12;
bi_num_cards[BB910] = 4;
bi_num_cards[XY210] = 2;
bi_num_cards[VXI_AT5_BI] = 32;
bi_num_cards[HPE1368A_BI] = 32;
bi_num_cards[AT8_FP10S_BI] = 8;
bi_num_cards[XY240_BI] = 2;
bi_num_channels[ABBI_08_BIT] = 8;
bi_num_channels[ABBI_16_BIT] = 16;
bi_num_channels[BB910] = 32;
bi_num_channels[XY210] = 32;
bi_num_channels[VXI_AT5_BI] = 32;
bi_num_channels[HPE1368A_BI] = 16;
bi_num_channels[AT8_FP10S_BI] = 32;
bi_num_channels[XY240_BI] = 32;
bi_addrs[ABBI_08_BIT] = 0;
bi_addrs[ABBI_16_BIT] = 0;
bi_addrs[BB910] = 0xb800;
bi_addrs[XY210] = 0xa000;
bi_addrs[VXI_AT5_BI] = 0xc000;
bi_addrs[HPE1368A_BI] = 0xc000;
bi_addrs[AT8_FP10S_BI] = 0x0e00;
bi_addrs[XY240_BI] = 0x3000;
bo_num_cards[ABBO_08_BIT] = 12;
bo_num_cards[ABBO_16_BIT] = 12;
bo_num_cards[BB902] = 4;
bo_num_cards[XY220] = 1;
bo_num_cards[VXI_AT5_BO] = 32;
bo_num_cards[HPE1368A_BO] = 32;
bo_num_cards[AT8_FP10M_BO] = 2;
bo_num_cards[XY240_BO] = 2;
bo_num_channels[ABBO_08_BIT] = 8;
bo_num_channels[ABBO_16_BIT] = 16;
bo_num_channels[BB902] = 32;
bo_num_channels[XY220] = 32;
bo_num_channels[VXI_AT5_BO] = 32;
bo_num_channels[HPE1368A_BO] = 16;
bo_num_channels[AT8_FP10M_BO] = 32;
bo_num_channels[XY240_BO] = 32;
bo_addrs[ABBO_08_BIT] = 0;
bo_addrs[ABBO_16_BIT] = 0;
bo_addrs[BB902] = 0x0400;
bo_addrs[XY220] = 0xa800;
bo_addrs[VXI_AT5_BO] = 0xc000;
bo_addrs[HPE1368A_BO] = 0xc000;
bo_addrs[AT8_FP10M_BO] = 0xc000;
bo_addrs[XY240_BO] = 0x3000;
sm_num_cards[CM57_83E] = 4;
sm_num_cards[OMS_6AXIS] = 4;
sm_num_channels[CM57_83E] = 1;
sm_num_channels[OMS_6AXIS] = 6;
sm_addrs[CM57_83E] = 0x8000;
sm_addrs[OMS_6AXIS] = 0x4000;
wf_num_cards[XY566WF] = 2;
wf_num_cards[CAMAC_THING] = 4;
wf_num_cards[JGVTR1] = 4;
wf_num_cards[COMET] = 4;
wf_num_channels[XY566WF] = 1;
wf_num_channels[CAMAC_THING] = 1;
wf_num_channels[JGVTR1] = 1;
wf_num_channels[COMET] = 4;
wf_addrs[XY566WF] = 0x9000;
wf_addrs[CAMAC_THING] = 0;
wf_addrs[JGVTR1] = 0xB000;
wf_addrs[COMET] = 0xbc00;
wf_armaddrs[XY566WF] = 0x5400;
wf_armaddrs[CAMAC_THING]= 0;
wf_armaddrs[JGVTR1] = 0;
wf_armaddrs[COMET] = 0;
wf_memaddrs[XY566WF] = 0x080000;
wf_memaddrs[CAMAC_THING]= 0;
wf_memaddrs[JGVTR1] = 0xb80000;
wf_memaddrs[COMET] = 0xe0000000;
tm_num_cards[MZ8310] = 4;
tm_num_cards[DG535] = 1;
tm_num_cards[VXI_AT5_TIME] = 32;
tm_num_channels[MZ8310] = 10;
tm_num_channels[DG535] = 1;
tm_num_channels[VXI_AT5_TIME] = 10;
tm_addrs[MZ8310] = 0x1000;
tm_addrs[DG535] = 0;
tm_addrs[VXI_AT5_TIME] = 0xc000;
AT830X_1_addrs = 0x0400;
AT830X_1_num_cards = 2;
AT830X_addrs = 0xaa0000;
AT830X_num_cards = 2;
xy010ScA16Base = 0x0000;
EPICS_VXI_LA_COUNT = 32;
EPICS_VXI_A24_BASE = (char *) 0x900000;
EPICS_VXI_A24_SIZE = 0x100000;
EPICS_VXI_A32_BASE = (char *) 0x90000000;
EPICS_VXI_A32_SIZE = 0x10000000;
AI566_VNUM = 0xf8;
DVX_IVEC0 = 0xd0;
MD_INT_BASE = 0xf0;
MZ8310_INT_VEC_BASE = 0xe8;
AB_VEC_BASE = 0x60;
JGVTR1_INT_VEC = 0xe0;
AT830X_1_IVEC0 = 0xd4;
AT830X_IVEC0 = 0xd6;
AT8FP_IVEC_BASE = 0xa2;
AT8FPM_IVEC_BASE= 0xaa;
BB_SHORT_OFF = 0x1800;
BB_IVEC_BASE = 0xa0;
BB_IRQ_LEVEL = 5;
PEP_BB_SHORT_OFF= 0x1c00;
PEP_BB_IVEC_BASE= 0xe8;
NIGPIB_SHORT_OFF = 0x5000;
NIGPIB_IVEC_BASE = 100;
NIGPIB_IRQ_LEVEL = 5;
return(0);
}