Seperated drv files into ansi and old dirs. Added combine dir.
This commit is contained in:
+3
-6
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
EPICS=../../../..
|
||||
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
include $(EPICS)/config/RULES_ARCHS
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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*/
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
EPICS=../../../..
|
||||
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
include $(EPICS)/config/RULES_ARCHS
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
);
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
@@ -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.
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user