unbundled or moved to /home/phoebus/MRK/epics/base/src/vxWorks/drv/ansi
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
|
||||
TOP=../../..
|
||||
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
include $(TOP)/config/RULES_ARCHS
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
TOP = ../../../..
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
INC += canBus.h
|
||||
INC += drvAb.h
|
||||
INC += drvAt5Vxi.h
|
||||
INC += drvEpvxi.h
|
||||
INC += drvHp1404a.h
|
||||
INC += drvHpe1368a.h
|
||||
INC += drvIpac.h
|
||||
INC += drvKscV215.h
|
||||
INC += drvMz8310.h
|
||||
INC += drvStc.h
|
||||
INC += drvTip810.h
|
||||
INC += epvxi.h
|
||||
INC += ipModules.h
|
||||
INC += ipic.h
|
||||
INC += pca82c200.h
|
||||
|
||||
SRCS.c += ../drvAb.c
|
||||
SRCS.c += ../drvAt5Vxi.c
|
||||
SRCS.c += ../drvEpvxi.c
|
||||
SRCS.c += ../drvEpvxiMsg.c
|
||||
SRCS.c += ../drvHp1404a.c
|
||||
SRCS.c += ../drvHpe1368a.c
|
||||
SRCS.c += ../drvHpe1445a.c
|
||||
SRCS.c += ../drvKscV215.c
|
||||
SRCS.c += ../drvMz8310.c
|
||||
SRCS.c += ../drvStc.c
|
||||
#SRCS.c += ../drvCaenV265.c
|
||||
|
||||
SRCS.c += ../drvVipc310.c
|
||||
SRCS.c += ../drvVipc610.c
|
||||
SRCS.c += ../drvIpMv162.c
|
||||
SRCS.c += ../drvIpac.c
|
||||
SRCS.c += ../drvTip810.c
|
||||
#SRCS.c += ../drvVmic2534.c
|
||||
|
||||
PROD = $(SRCS.c:../%.c=%.o)
|
||||
|
||||
MAN3 = drvEpvxi.3
|
||||
|
||||
include $(TOP)/config/RULES.Vx
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
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 something 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.
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
canBus.h
|
||||
|
||||
Description:
|
||||
CANBUS specific constants
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
25 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef INCcanBusH
|
||||
#define INCcanBusH
|
||||
|
||||
|
||||
#define CAN_IDENTIFIERS 2048
|
||||
#define CAN_DATA_SIZE 8
|
||||
|
||||
#define CAN_BUS_OK 0
|
||||
#define CAN_BUS_ERROR 1
|
||||
#define CAN_BUS_OFF 2
|
||||
|
||||
|
||||
#ifndef M_can
|
||||
#define M_can (811<<16)
|
||||
#endif
|
||||
|
||||
#define S_can_badMessage (M_can| 1) /*illegal CAN message contents*/
|
||||
#define S_can_badAddress (M_can| 2) /*CAN address syntax error*/
|
||||
#define S_can_noDevice (M_can| 3) /*CAN bus name does not exist*/
|
||||
|
||||
typedef struct {
|
||||
ushort_t identifier; /* 0 .. 2047 with holes! */
|
||||
enum {
|
||||
SEND = 0, RTR = 1
|
||||
} rtr; /* Remote Transmission Request */
|
||||
uchar_t length; /* 0 .. 8 */
|
||||
uchar_t data[CAN_DATA_SIZE];
|
||||
} canMessage_t;
|
||||
|
||||
typedef struct {
|
||||
char *busName;
|
||||
int timeout;
|
||||
ushort_t identifier;
|
||||
ushort_t offset;
|
||||
signed int parameter;
|
||||
void *canBusID;
|
||||
} canIo_t;
|
||||
|
||||
typedef void canMsgCallback_t(void *pprivate, canMessage_t *pmessage);
|
||||
typedef void canSigCallback_t(void *pprivate, int status);
|
||||
|
||||
extern int canOpen(char *busName, void **pcanBusID);
|
||||
extern int canRead(void *canBusID, canMessage_t *pmessage, int timeout);
|
||||
extern int canWrite(void *canBusID, canMessage_t *pmessage, int timeout);
|
||||
extern int canMessage(void *canBusID, ushort_t identifier,
|
||||
canMsgCallback_t callback, void *pprivate);
|
||||
extern int canSignal(void *canBusID, canSigCallback_t callback, void *pprivate);
|
||||
extern int canIoParse(char *canString, canIo_t *pcanIo);
|
||||
|
||||
|
||||
#endif /* INCcanBusH */
|
||||
|
||||
1891
src/drv/ansi/drvAb.c
1891
src/drv/ansi/drvAb.c
File diff suppressed because it is too large
Load Diff
@@ -1,93 +0,0 @@
|
||||
/* drvAb.h */
|
||||
/* header file for the Allen-Bradley Remote Serial IO
|
||||
* This defines interface between driver and device support
|
||||
*
|
||||
* Author: Marty Kraimer
|
||||
* Date: 03-06-95
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* 01 03-06-95 mrk Moved all driver specific code to drvAb.c
|
||||
*/
|
||||
|
||||
#ifndef INCdrvAbh
|
||||
#define INCdrvAbh 1
|
||||
#include "dbScan.h"
|
||||
|
||||
|
||||
/* interface types */
|
||||
typedef enum {typeNotAssigned,typeBi,typeBo,typeBiBo,typeAi,typeAo,typeBt}
|
||||
cardType;
|
||||
/* status values*/
|
||||
typedef enum{abSuccess,abNewCard,abCardConflict,abNoCard,abNotInitialized,
|
||||
abBtqueued,abBusy,abTimeout,abAdapterDown,abFailure} abStatus;
|
||||
extern char **abStatusMessage;
|
||||
|
||||
typedef enum{abBitNotdefined,abBit8,abBit16,abBit32} abNumBits;
|
||||
extern char **abNumBitsMessage;
|
||||
|
||||
/*entry table for dev to drv routines*/
|
||||
typedef struct {
|
||||
abStatus (*registerCard)
|
||||
(unsigned short link,unsigned short adapter, unsigned short card,
|
||||
cardType type, const char *card_name,
|
||||
void (*callback)(void *drvPvt),
|
||||
void **drvPvt);
|
||||
void (*getLocation)
|
||||
(void *drvPvt,
|
||||
unsigned short *link, unsigned short *adapter,unsigned short *card);
|
||||
abStatus (*setNbits)(void *drvPvt, abNumBits nbits);
|
||||
void (*setUserPvt)(void *drvPvt, void *userPvt);
|
||||
void *(*getUserPvt)(void *drvPvt);
|
||||
abStatus (*getStatus)(void *drvPvt);
|
||||
abStatus(*startScan)
|
||||
(void *drvPvt, unsigned short update_rate,
|
||||
unsigned short *pwrite_msg, unsigned short write_msg_len,
|
||||
unsigned short *pread_msg, unsigned short read_msg_len);
|
||||
abStatus(*updateAo)(void *drvPvt);
|
||||
abStatus(*updateBo) (void *drvPvt,unsigned long value,unsigned long mask);
|
||||
abStatus(*readBo) (void *drvPvt,unsigned long *value,unsigned long mask);
|
||||
abStatus(*readBi) (void *drvPvt,unsigned long *value,unsigned long mask);
|
||||
abStatus(*btRead)(void *drvPvt,unsigned short *pread_msg,
|
||||
unsigned short read_msg_len);
|
||||
abStatus(*btWrite)(void *drvPvt,unsigned short *pwrite_msg,
|
||||
unsigned short write_msg_len);
|
||||
abStatus (*adapterStatus)
|
||||
(unsigned short link,unsigned short adapter);
|
||||
abStatus (*cardStatus)
|
||||
(unsigned short link,unsigned short adapter, unsigned short card);
|
||||
}abDrv;
|
||||
|
||||
extern abDrv *pabDrv;
|
||||
|
||||
int ab_reset(void);
|
||||
int ab_reset_link(int link);
|
||||
int abConfigNlinks(int nlinks);
|
||||
int abConfigVme(int link, int base, int vector, int level);
|
||||
int abConfigBaud(int link, int baud);
|
||||
int abConfigScanList(int link, int scan_list_len, char *scan_list);
|
||||
int abConfigScanListAscii(int link, char *filename,int setRackSize);
|
||||
int abConfigAuto(int link);
|
||||
|
||||
#endif /*INCdrvAbh*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,94 +0,0 @@
|
||||
/* base/src/drv $Id$ */
|
||||
|
||||
/*
|
||||
*
|
||||
* driver for at5 designed VXI modules
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 11-89
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <dbScan.h>
|
||||
|
||||
typedef long at5VxiStatus;
|
||||
|
||||
at5VxiStatus at5vxi_one_shot(
|
||||
unsigned preset, /* TRUE or COMPLEMENT logic */
|
||||
double edge0_delay, /* sec */
|
||||
double edge1_delay, /* set */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned int_source, /* (FALSE)External/(TRUE)Internal source */
|
||||
void (*event_rtn)(void *pParam), /* subroutine to run on events */
|
||||
void *event_rtn_param/* parameter to pass to above routine */
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_one_shot_read(
|
||||
unsigned *preset, /* TRUE or COMPLEMENT logic */
|
||||
double *edge0_delay, /* sec */
|
||||
double *edge1_delay, /* sec */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned *int_source /* (FALSE)External/(TRUE)Internal src */
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ai_driver(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *prval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ao_driver(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *prval,
|
||||
unsigned short *prbval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_ao_read(
|
||||
unsigned card,
|
||||
unsigned chan,
|
||||
unsigned short *pval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_bi_driver(
|
||||
unsigned card,
|
||||
unsigned long mask,
|
||||
unsigned long *prval
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_bo_driver(
|
||||
unsigned card,
|
||||
unsigned long val,
|
||||
unsigned long mask
|
||||
);
|
||||
|
||||
at5VxiStatus at5vxi_getioscanpvt(
|
||||
unsigned card,
|
||||
IOSCANPVT *scanpvt
|
||||
);
|
||||
|
||||
@@ -1,808 +0,0 @@
|
||||
/* share/src/drv @(#)drvCaenV265.c 1.1 9/2/94 */
|
||||
/* drvCaenV265.c - Driver/Device Support Routines for CAEN V265
|
||||
*
|
||||
* Author: Jeff Hill (johill@lanl.gov)
|
||||
* Date: 8-11-94
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* MIT Bates Lab
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* ANSI C Includes
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <types.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* vxWorks includes
|
||||
*/
|
||||
#include <vme.h>
|
||||
#include <iv.h>
|
||||
#include <sysLib.h>
|
||||
#include <intLib.h>
|
||||
#include <logLib.h>
|
||||
#include <vxLib.h>
|
||||
#include <rebootLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <wdLib.h>
|
||||
|
||||
/*
|
||||
* EPICS include
|
||||
*/
|
||||
#include <dbDefs.h>
|
||||
#include <dbScan.h>
|
||||
#include <drvSup.h>
|
||||
#include <devSup.h>
|
||||
#include <recSup.h>
|
||||
#include <devLib.h>
|
||||
#include <aiRecord.h>
|
||||
#include <errMdef.h>
|
||||
#include <epicsPrint.h>
|
||||
|
||||
|
||||
/*
|
||||
* base address, base interrupt vector,
|
||||
* number of cards, & interrupt level
|
||||
*/
|
||||
#define CAIN_V265_A24_BASE (0x000000)
|
||||
#define CAIN_V265_INTVEC_BASE (0xA0)
|
||||
#define CAIN_V265_MAX_CARD_COUNT (8)
|
||||
#define CAIN_V265_INT_LEVEL (6)
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* all device registers declared
|
||||
* ANSI C volatile so we dont need to
|
||||
* use the -fvolatile flag (and dont
|
||||
* limit the optimizer)
|
||||
*/
|
||||
typedef volatile int16_t devReg;
|
||||
|
||||
struct caenV265 {
|
||||
devReg csr;
|
||||
devReg clear;
|
||||
devReg DAC;
|
||||
devReg gate;
|
||||
const devReg data;
|
||||
const devReg pad1[(0xf8-0x8)/2];
|
||||
const devReg fixed;
|
||||
const devReg identifier;
|
||||
const devReg version;
|
||||
};
|
||||
#define CAENV265ID 0x0812
|
||||
|
||||
/*
|
||||
* Insert or extract a bit field using the standard
|
||||
* masks and shifts defined below
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
#define INSERT(FIELD,VALUE)\
|
||||
(((VALUE)&(FD_ ## FIELD ## _M))<<(FD_ ## FIELD ## _S))
|
||||
#define EXTRACT(FIELD,VALUE)\
|
||||
( ((VALUE)>>(FD_ ## FIELD ## _S)) &(FD_ ## FIELD ## _M))
|
||||
#else /*__STDC__*/
|
||||
#define INSERT(FIELD,VALUE)\
|
||||
(((VALUE)&(FD_/* */FIELD/* */_M))<<(FD_/* */FIELD/* */_S))
|
||||
#define EXTRACT(FIELD,VALUE)\
|
||||
( ((VALUE)>>(FD_/* */FIELD/* */_S)) &(FD_/* */FIELD/* */_M))
|
||||
#endif /*__STDC__*/
|
||||
|
||||
/*
|
||||
* in the constants below _M is a right justified mask
|
||||
* and _S is a shift required to right justify the field
|
||||
*/
|
||||
|
||||
/*
|
||||
* csr register
|
||||
*/
|
||||
#define FD_FULL_M (0x1)
|
||||
#define FD_FULL_S (14)
|
||||
#define FD_READY_M (0x1)
|
||||
#define FD_READY_S (15)
|
||||
#define FD_BUSY_FULL_M (0x3)
|
||||
#define FD_BUSY_FULL_S (14)
|
||||
#define FD_IVEC_M (0xff)
|
||||
#define FD_IVEC_S (0)
|
||||
#define FD_ILEVEL_M (0x7)
|
||||
#define FD_ILEVEL_S (8)
|
||||
|
||||
/*
|
||||
* series/version register
|
||||
*/
|
||||
#define FD_SERIES_M (0xfff)
|
||||
#define FD_SERIES_S (0)
|
||||
#define FD_VERSION_M (0xf)
|
||||
#define FD_VERSION_S (12)
|
||||
|
||||
/*
|
||||
* data register
|
||||
*/
|
||||
#define FD_CHANNEL_M (0x7)
|
||||
#define FD_CHANNEL_S (13)
|
||||
#define FD_RANGE_M (1)
|
||||
#define FD_RANGE_S (12)
|
||||
#define FD_DATA_M (0xfff)
|
||||
#define FD_DATA_S (0)
|
||||
|
||||
struct channel{
|
||||
int16_t signal;
|
||||
char newData;
|
||||
};
|
||||
|
||||
enum adc_range {adc_12, adc_15, NUMBER_OF_ADC_RANGES};
|
||||
#define NUMBER_OF_SIGNALS 8
|
||||
#define NUMBER_OF_FIFO_ENTRIES (16*NUMBER_OF_SIGNALS*NUMBER_OF_ADC_RANGES)
|
||||
LOCAL struct caenV265Config{
|
||||
struct caenV265 *pCaenV265; /* pointer to the card */
|
||||
struct channel chan[NUMBER_OF_SIGNALS][NUMBER_OF_ADC_RANGES];
|
||||
IOSCANPVT scanpvt;
|
||||
WDOG_ID wdid;
|
||||
}caenV265Info[CAIN_V265_MAX_CARD_COUNT];
|
||||
|
||||
#ifdef __STDC__
|
||||
#define SHOW_OFFSET(STRUCT,FIELD) \
|
||||
printf( "%s.%s is at 0x%X\n", \
|
||||
#STRUCT, \
|
||||
#FIELD, \
|
||||
offsetof(struct STRUCT, FIELD))
|
||||
#endif
|
||||
|
||||
LOCAL void caenV265ISR(unsigned card);
|
||||
LOCAL int caenV265Shutdown(void);
|
||||
LOCAL int caenV265IdTest(struct caenV265 *pCaenV265);
|
||||
int caenV265Test(unsigned card);
|
||||
LOCAL void caenV265ReadData(struct caenV265Config *pCaenV256Config);
|
||||
LOCAL int caenV265TestVal(unsigned card, unsigned dacVal);
|
||||
LOCAL int caenV265IntEnable(unsigned card);
|
||||
|
||||
/*
|
||||
* device support entry table
|
||||
*/
|
||||
LOCAL long caenV265InitRecord(struct aiRecord *pai);
|
||||
LOCAL long caenV265AiRead(struct aiRecord *pai);
|
||||
LOCAL long caenV265SpecialLinconv(struct aiRecord *pai, int after);
|
||||
LOCAL long caenV265GetIoIntInfo(int cmd, struct aiRecord *pai, IOSCANPVT *ppvt);
|
||||
struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;
|
||||
DEVSUPFUN special_linconv;
|
||||
} devCaenV265 ={
|
||||
6,
|
||||
NULL,
|
||||
NULL,
|
||||
caenV265InitRecord,
|
||||
caenV265GetIoIntInfo,
|
||||
caenV265AiRead,
|
||||
caenV265SpecialLinconv};
|
||||
|
||||
/*
|
||||
* driver support entry table
|
||||
*/
|
||||
LOCAL long caenV265Init(void);
|
||||
LOCAL long caenV265IOReport(int level);
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvCaenV265 ={
|
||||
2,
|
||||
caenV265IOReport,
|
||||
caenV265Init};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* verify that register
|
||||
* offsets match the doc.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
void offsettest()
|
||||
{
|
||||
SHOW_OFFSET(caenV265, version);
|
||||
SHOW_OFFSET(caenV265, identifier);
|
||||
SHOW_OFFSET(caenV265, fixed);
|
||||
SHOW_OFFSET(caenV265, data);
|
||||
SHOW_OFFSET(caenV265, gate);
|
||||
SHOW_OFFSET(caenV265, DAC);
|
||||
SHOW_OFFSET(caenV265, clear);
|
||||
SHOW_OFFSET(caenV265, csr);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* caenV265InitRecord()
|
||||
*/
|
||||
LOCAL long caenV265InitRecord(struct aiRecord *pai)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
/* ai.inp must be an VME_IO */
|
||||
switch (pai->inp.type) {
|
||||
case (VME_IO):
|
||||
break;
|
||||
default :
|
||||
recGblRecordError(S_db_badField,(void *)pai,
|
||||
"devAiXy566Se (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad signal or card number
|
||||
*/
|
||||
if ( pvmeio->signal >= NUMBER_OF_SIGNALS ||
|
||||
pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 bad card or signal number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!caenV265Info[pvmeio->card].pCaenV265){
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 card does not exist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
pai->eslo = (pai->eguf-pai->egul)/FD_DATA_M;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265AiRead()
|
||||
*/
|
||||
LOCAL long caenV265AiRead(struct aiRecord *pai)
|
||||
{
|
||||
int16_t value;
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad signal or card number
|
||||
*/
|
||||
if ( pvmeio->signal >= NUMBER_OF_SIGNALS ||
|
||||
pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
|
||||
recGblSetSevr(pai, READ_ALARM, INVALID_ALARM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* uninitialized data?
|
||||
*/
|
||||
if (!caenV265Info[pvmeio->card].chan[pvmeio->signal][adc_12].newData) {
|
||||
recGblSetSevr(pai, READ_ALARM, INVALID_ALARM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
value = caenV265Info[pvmeio->card].chan[pvmeio->signal][adc_12].signal;
|
||||
pai->rval = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265SpecialLinconv()
|
||||
*/
|
||||
LOCAL long caenV265SpecialLinconv(struct aiRecord *pai, int after)
|
||||
{
|
||||
if(!after) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
pai->eslo = (pai->eguf-pai->egul)/FD_DATA_M;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265GetIoIntInfo()
|
||||
*/
|
||||
LOCAL long caenV265GetIoIntInfo(
|
||||
int cmd,
|
||||
struct aiRecord *pai,
|
||||
IOSCANPVT *ppvt)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad card number
|
||||
*/
|
||||
if ( pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
epicsPrintf (
|
||||
"%s.%d:devCaenV265 bad card number %d %s\n",
|
||||
(int)__FILE__,
|
||||
__LINE__,
|
||||
pvmeio->card,
|
||||
(int)pai->name);
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 bad card number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ppvt = caenV265Info[pvmeio->card].scanpvt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Init()
|
||||
*/
|
||||
LOCAL long caenV265Init(void)
|
||||
{
|
||||
unsigned card;
|
||||
struct caenV265 *pCaenV265;
|
||||
int status;
|
||||
|
||||
status = rebootHookAdd(caenV265Shutdown);
|
||||
if(status){
|
||||
errMessage(S_dev_internal,"reboot hook add failed");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
status = sysBusToLocalAdrs(
|
||||
VME_AM_STD_SUP_DATA,
|
||||
CAIN_V265_A24_BASE,
|
||||
(char **)&pCaenV265);
|
||||
if(status!=OK){
|
||||
errPrintf(
|
||||
S_dev_badA24,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"caenV265Init");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
for(card=0; card<CAIN_V265_MAX_CARD_COUNT; card++, pCaenV265++){
|
||||
unsigned vec;
|
||||
|
||||
if(!caenV265IdTest(pCaenV265)){
|
||||
continue;
|
||||
}
|
||||
|
||||
caenV265Info[card].wdid = wdCreate();
|
||||
if(!caenV265Info[card].wdid){
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* flag that we have found a caen V265
|
||||
*/
|
||||
caenV265Info[card].pCaenV265 = pCaenV265;
|
||||
|
||||
/*
|
||||
* init the EPICS db int event scan block
|
||||
*/
|
||||
scanIoInit(&caenV265Info[card].scanpvt);
|
||||
|
||||
/*
|
||||
* reset the device
|
||||
*/
|
||||
pCaenV265->clear = 0; /* any rw op resets the device */
|
||||
pCaenV265->DAC = 0; /* set test-signal "offset" to zero */
|
||||
|
||||
/*
|
||||
* attach ISR
|
||||
*/
|
||||
vec = CAIN_V265_INTVEC_BASE+card;
|
||||
status = intConnect(
|
||||
INUM_TO_IVEC(vec),
|
||||
caenV265ISR,
|
||||
card);
|
||||
assert(status>=0);
|
||||
|
||||
/*
|
||||
* Enable interrupts
|
||||
*/
|
||||
caenV265IntEnable(card);
|
||||
}
|
||||
status = sysIntEnable(CAIN_V265_INT_LEVEL);
|
||||
assert(status>=0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265ISR()
|
||||
*/
|
||||
LOCAL void caenV265ISR(unsigned card)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned signal;
|
||||
int16_t csr;
|
||||
static unsigned ticks;
|
||||
unsigned newTicks;
|
||||
|
||||
/*
|
||||
* If its full then its more efficient
|
||||
* to read it out without checking
|
||||
* in between each read
|
||||
*/
|
||||
csr = pCaenV265->csr;
|
||||
if (EXTRACT(FULL,csr)) {
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_FIFO_ENTRIES;
|
||||
signal++){
|
||||
|
||||
caenV265ReadData(pCaenV256Config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not full so check to see if its ready before
|
||||
* reading
|
||||
*/
|
||||
while (EXTRACT(READY, csr)) {
|
||||
caenV265ReadData(pCaenV256Config);
|
||||
csr = pCaenV265->csr;
|
||||
}
|
||||
|
||||
/*
|
||||
* limit the EPICS scan rate
|
||||
*/
|
||||
newTicks = tickGet();
|
||||
if(newTicks == ticks){
|
||||
/*
|
||||
* Disable Interrupts
|
||||
*/
|
||||
pCaenV265->csr = 0;
|
||||
|
||||
/*
|
||||
* start a watch dog after one tick
|
||||
* so that we limit the int rate to
|
||||
* the system tick rate.
|
||||
*/
|
||||
wdStart(pCaenV256Config->wdid,
|
||||
1,
|
||||
caenV265IntEnable,
|
||||
card);
|
||||
|
||||
return;
|
||||
}
|
||||
else{
|
||||
ticks = newTicks;
|
||||
}
|
||||
|
||||
/*
|
||||
* tell EPICS to scan on int
|
||||
*/
|
||||
scanIoRequest(caenV265Info[card].scanpvt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IntEnable
|
||||
*/
|
||||
LOCAL int caenV265IntEnable(unsigned card)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned vec;
|
||||
int16_t newcsr;
|
||||
|
||||
|
||||
vec = CAIN_V265_INTVEC_BASE+card;
|
||||
newcsr = INSERT(IVEC, vec) | INSERT(ILEVEL, CAIN_V265_INT_LEVEL);
|
||||
pCaenV265->csr = newcsr;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265ReadData()
|
||||
*/
|
||||
LOCAL void caenV265ReadData(struct caenV265Config *pCaenV256Config)
|
||||
{
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
int16_t val = pCaenV265->data;
|
||||
int16_t data = EXTRACT(DATA, val);
|
||||
unsigned range = EXTRACT(RANGE, val);
|
||||
unsigned signal = EXTRACT(CHANNEL, val);
|
||||
|
||||
if(range>=NUMBER_OF_ADC_RANGES){
|
||||
epicsPrintf ("caenV265ReadData: bad range number\n");
|
||||
return;
|
||||
}
|
||||
if(signal>=NUMBER_OF_SIGNALS){
|
||||
epicsPrintf ("caenV265ReadData: bad signal number\n");
|
||||
return;
|
||||
}
|
||||
pCaenV256Config->chan[signal][range].signal=data;
|
||||
pCaenV256Config->chan[signal][range].newData=TRUE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IdTest()
|
||||
*/
|
||||
LOCAL int caenV265IdTest(struct caenV265 *pCaenV265)
|
||||
{
|
||||
int status;
|
||||
int16_t id;
|
||||
|
||||
/*
|
||||
* Is a card present
|
||||
*/
|
||||
status = vxMemProbe(
|
||||
(char *)&pCaenV265->identifier,
|
||||
READ,
|
||||
sizeof(id),
|
||||
(char *)&id);
|
||||
if(status!=OK){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the correct type of card present
|
||||
*/
|
||||
if(id!=CAENV265ID){
|
||||
errPrintf(
|
||||
S_dev_wrongDevice,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"caenV265IdTest");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Shutdown()
|
||||
* turns off interrupts so that dont foul up the boot
|
||||
*/
|
||||
LOCAL int caenV265Shutdown(void)
|
||||
{
|
||||
struct caenV265 *pCaenV265;
|
||||
unsigned card;
|
||||
|
||||
for(card=0; card<CAIN_V265_MAX_CARD_COUNT; card++){
|
||||
pCaenV265 = caenV265Info[card].pCaenV265;
|
||||
if(!pCaenV265){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(caenV265IdTest(pCaenV265)){
|
||||
/*
|
||||
* disable interrupts
|
||||
*/
|
||||
pCaenV265->csr=0;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Test()
|
||||
*/
|
||||
int caenV265Test(unsigned card)
|
||||
{
|
||||
unsigned dacVal;
|
||||
struct caenV265Config cofigCpy;
|
||||
unsigned range;
|
||||
unsigned signal;
|
||||
|
||||
|
||||
dacVal=0;
|
||||
caenV265TestVal(card, dacVal);
|
||||
while(dacVal<FD_DATA_M){
|
||||
|
||||
cofigCpy = caenV265Info[card];
|
||||
dacVal = dacVal+32;
|
||||
caenV265TestVal(card, dacVal);
|
||||
|
||||
for( range=0;
|
||||
range<NUMBER_OF_ADC_RANGES;
|
||||
range++){
|
||||
char *pRangeName[] = { "12 bit signal",
|
||||
"15 bit signal"};
|
||||
|
||||
printf( "\t%s with DAC = 0x%X\n",
|
||||
pRangeName[range],
|
||||
dacVal);
|
||||
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
unsigned newdata;
|
||||
unsigned olddata;
|
||||
|
||||
olddata = cofigCpy.chan[signal][range].signal;
|
||||
newdata = caenV265Info[card].
|
||||
chan[signal][range].signal;
|
||||
|
||||
printf( "\t\tchan=0x%1X diff = 0x%03X\n",
|
||||
signal,
|
||||
newdata-olddata);
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265TestVal()
|
||||
*/
|
||||
LOCAL int caenV265TestVal(unsigned card, unsigned dacVal)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned signal;
|
||||
|
||||
if(!pCaenV265){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if(!caenV265IdTest(pCaenV265)){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear the module
|
||||
*/
|
||||
pCaenV265->clear=0;
|
||||
|
||||
/*
|
||||
* generate a test signal
|
||||
*/
|
||||
pCaenV265->DAC=dacVal;
|
||||
|
||||
/*
|
||||
* generate a test gate
|
||||
*/
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
caenV265Info[card].chan[signal][adc_12].newData=FALSE;
|
||||
caenV265Info[card].chan[signal][adc_15].newData=FALSE;
|
||||
while(!caenV265Info[card].chan[signal][adc_15].newData){
|
||||
pCaenV265->gate=0;
|
||||
taskDelay(1);
|
||||
}
|
||||
while(!caenV265Info[card].chan[signal][adc_12].newData){
|
||||
pCaenV265->gate=0;
|
||||
taskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn off test signal
|
||||
*/
|
||||
pCaenV265->clear=0;
|
||||
pCaenV265->DAC=0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IOReport()
|
||||
*/
|
||||
LOCAL long caenV265IOReport(int level)
|
||||
{
|
||||
struct caenV265 *pCaenV265;
|
||||
unsigned card;
|
||||
unsigned signal;
|
||||
unsigned range;
|
||||
char *pVersion[] = {"NIM","ECL"};
|
||||
char *pState[] = {
|
||||
"FIFO empty",
|
||||
"FIFO full",
|
||||
"FIFO partially filled",
|
||||
"FIFO full"};
|
||||
|
||||
for (card=0; card<CAIN_V265_MAX_CARD_COUNT; card++) {
|
||||
pCaenV265 = caenV265Info[card].pCaenV265;
|
||||
if (!pCaenV265) {
|
||||
continue;
|
||||
}
|
||||
if (!caenV265IdTest(pCaenV265)) {
|
||||
continue;
|
||||
}
|
||||
printf("AI: caen V265:\tcard %d\n", card);
|
||||
if (level == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\tversion = %s\n",
|
||||
pVersion[EXTRACT(VERSION, pCaenV265->version)]);
|
||||
printf("\tseries = %d\n",
|
||||
EXTRACT(SERIES, pCaenV265->version));
|
||||
printf("\tstate = %s\n",
|
||||
pState[EXTRACT(BUSY_FULL,pCaenV265->csr)]);
|
||||
printf("\tint level = %d\n",
|
||||
EXTRACT(ILEVEL,pCaenV265->csr));
|
||||
printf("\tint vec = 0x%02X\n",
|
||||
EXTRACT(IVEC,pCaenV265->csr));
|
||||
printf( "\tbase addr= 0x%X on the %s\n",
|
||||
(unsigned)caenV265Info[card].pCaenV265,
|
||||
sysModel());
|
||||
|
||||
for( range=0;
|
||||
range<NUMBER_OF_ADC_RANGES;
|
||||
range++){
|
||||
char *pRangeName[] = { "12 bit signal",
|
||||
"15 bit signal"};
|
||||
|
||||
printf("\t%s\n", pRangeName[range]);
|
||||
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
int16_t data;
|
||||
|
||||
data = caenV265Info[card].
|
||||
chan[signal][range].signal;
|
||||
|
||||
if(caenV265Info[card].chan[signal][range].newData){
|
||||
printf( "\t\tchan=0x%1X val = 0x%03X\n",
|
||||
signal,
|
||||
data);
|
||||
}
|
||||
else{
|
||||
printf( "\t\tchan=0x%1X <NO GATE>\n",
|
||||
signal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
@@ -1,766 +0,0 @@
|
||||
.TH epvxiMsgLib 1 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH VERSION @(#)drvEpvxi.nr 1.9 8/13/93
|
||||
.SH NAME
|
||||
epvxiMsgLib.c - the VXI message based device interface library
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
|
||||
epvxiCmd - deliver a command to a message based device
|
||||
epvxiQuery - fetch a response from a message based device
|
||||
epvxiCmdQuery - send a command and fetch a response
|
||||
epvxiRead - read a string of bytes from a device
|
||||
epvxiWrite - write a string of bytes to a device
|
||||
epvxiSetTimeout - change the message based transfer timeout
|
||||
epvxiSetTraceEnable - turn trace mode on or off
|
||||
|
||||
int epvxiCmd (la, command)
|
||||
int epvxiQuery (la, presponse)
|
||||
int epvxiCmdQuery (la, command, presponse)
|
||||
int epvxiRead (la, pbuffer, count, pactual_count, option)
|
||||
int epvxiWrite (la, pbuffer, pcount, pactual_count, option)
|
||||
int epvxiSetTimeout (la, timeout)
|
||||
int epvxiSetTraceEnable(la, enable)
|
||||
|
||||
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
This library provides a vendor independent interface to VXI message
|
||||
based devices. Device drivers which use this library may optionally
|
||||
open devices accessed by this library using epvxiOpen() prior to use.
|
||||
Opening a device prevents other drivers from using it.
|
||||
.SH RETURNS
|
||||
.nf
|
||||
less than zero- operation failed
|
||||
greater than zero- operation successful
|
||||
|
||||
#define VXI_SUCCESS 0 /* successful completion */
|
||||
#define VXI_NO_DEVICE (-1) /* device does not exist */
|
||||
#define VXI_NOT_SLOT0 (-2) /* not a slot zero device */
|
||||
#define VXI_UKN_DEVICE (-3) /* device not supported */
|
||||
#define VXI_BAD_TRIGGER (-4) /* no such trigger */
|
||||
#define VXI_BAD_TRIG_IO (-5) /* no such trigger io */
|
||||
#define VXI_DEVICE_OPEN (-6) /* device already open */
|
||||
#define VXI_NOT_OWNER (-7) /* dev in use by another drv */
|
||||
#define VXI_NO_MEMORY (-8) /* failed to allocate memory */
|
||||
#define VXI_NOT_OPEN (-9) /* device not open */
|
||||
#define VXI_NOT_MSG_DEVICE (-10) /* must be a message based dev */
|
||||
#define VXI_MSG_DEVICE_TMO (-11) /* message based dev timed out */
|
||||
#define VXI_MSG_DEVICE_FAILURE (-12) /* message based dev failed */
|
||||
#define VXI_BAD_LA (-13) /* logical addr out of range */
|
||||
#define VXI_MULTIPLE_QUERIES (-14) /* serial protocol error */
|
||||
#define VXI_UNSUPPORTED_CMD (-15) /* serial protocol error */
|
||||
#define VXI_DIR_VIOLATION (-16) /* serial protocol error */
|
||||
#define VXI_DOR_VIOLATION (-17) /* serial protocol error */
|
||||
#define VXI_RR_VIOLATION (-18) /* serial protocol error */
|
||||
#define VXI_WR_VIOLATION (-19) /* serial protocol error */
|
||||
#define VXI_ERR_FETCH_FAIL (-20) /* ukn serial protocol error */
|
||||
#define VXI_SELF_TEST_FAILED (-21) /* self test failed */
|
||||
|
||||
.SH INCLUDES
|
||||
epvxiLib.h
|
||||
.fi
|
||||
|
||||
|
||||
.TH epvxiCmd 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiCmd - deliver a command to a message based device
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiCmd (la, command)
|
||||
unsigned la; /* logical address */
|
||||
unsigned long command; /* command */
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
Delivers a command to a message based device.
|
||||
|
||||
.SH RETURNS
|
||||
See epvxiMsgLib(1) for a description of the return codes from this library.
|
||||
.SH SEE ALSO
|
||||
epvxiMsgLib(1), epvxiLib(1)
|
||||
|
||||
.TH epvxiQuery 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiQuery - fetch a response from a message based device
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiQuery (la, presponse)
|
||||
unsigned la; /* logical address */
|
||||
unsigned long *presponse; /* response pointer */
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
Fetch a response from a message based device.
|
||||
|
||||
.SH RETURNS
|
||||
See epvxiMsgLib(1) for a description of the returns from this library.
|
||||
.SH SEE ALSO
|
||||
epvxiMsgLib(1), epvxiLib(1)
|
||||
|
||||
.TH epvxiCmdQuery 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiCmdQuery - send a command and fetch a response from a message based device
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiCmdQuery (la, command, presponse)
|
||||
unsigned la; /* logical address */
|
||||
unsigned long command; /* command */
|
||||
unsigned long *presponse; /* response pointer */
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
Send a command and fetch a response from a message based device.
|
||||
|
||||
.SH RETURNS
|
||||
See epvxiMsgLib(1) for a description of the return codes from this library.
|
||||
.SH SEE ALSO
|
||||
epvxiMsgLib(1), epvxiLib(1)
|
||||
|
||||
.TH epvxiRead 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiRead - read a string of bytes from a device
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiRead (
|
||||
unsigned la, /* logical address */
|
||||
char *pbuffer, /* pointer to supplied buffer */
|
||||
unsigned long count, /* number of bytes to read */
|
||||
unsigned long *pactual_count, /* number of bytes read */
|
||||
unsigned long option /* read options */
|
||||
)
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
Read a string of bytes from a message based device using the
|
||||
byte transfer protocol. Copy bytes into the supplied buffer
|
||||
until the end of string terminator is received from the device
|
||||
or the end of the buffer is reached as determined by the supplied
|
||||
count. Returns the number of bytes read in *pactual_count.
|
||||
The options argument is a mask with each bit potentially
|
||||
representing a different option. If you need to specify more
|
||||
than one option then you must bit or together the option
|
||||
constants which apply. Currently, no read options are supported.
|
||||
The option argument should be set to epvxiReadOptNone.
|
||||
|
||||
.nf
|
||||
Option Bit Mask Purpose
|
||||
--------------- -------
|
||||
epvxiReadOptNon no options
|
||||
.fi
|
||||
|
||||
.SH RETURNS
|
||||
See epvxiMsgLib(1) for a description of the return codes from this library.
|
||||
.SH SEE ALSO
|
||||
epvxiMsgLib(1), epvxiLib(1)
|
||||
|
||||
|
||||
.TH epvxiWrite 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiWrite - write a string of bytes to a device
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiWrite (
|
||||
unsigned la, /* logical address */
|
||||
char *pbuffer, /* pointer to supplied buffer */
|
||||
unsigned long count, /* number of bytes to write */
|
||||
unsigned long *pactual_count, /* number of bytes written */
|
||||
unsigned long option /* write options */
|
||||
)
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
Write a string of bytes to a message based device using the
|
||||
byte transfer protocol. Copy count bytes from the supplied buffer
|
||||
to the device. Returns the number of bytes written in *pactual_count.
|
||||
The options argument is a mask with each bit potentially
|
||||
representing a different option. If you need to specify more
|
||||
than one option then you must bit or together the option
|
||||
constants which apply. Or in the constant epvxiWriteOptPartialMsg
|
||||
if the string sent is part of a larger message and it is
|
||||
not the last segment of the larger message.
|
||||
|
||||
.nf
|
||||
Option Bit Mask Purpose
|
||||
--------------- -------
|
||||
epvxiWriteOptNone no options
|
||||
epvxiWriteOptPartialMsg message continues after this transfer
|
||||
.fi
|
||||
|
||||
.SH RETURNS
|
||||
See epvxiMsgLib(1) for an description of the return codes from this library.
|
||||
.SH SEE ALSO
|
||||
epvxiMsgLib(1), epvxiLib(1)
|
||||
|
||||
|
||||
.TH epvxiSetTimeout 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiSetTimeout - change the message based transfer timeout
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiSetTimeout (la, timeout)
|
||||
unsigned la; /* logical address */
|
||||
unsigned long timeout; /* milli-seconds prior to timeout */
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
Set the delay prior to timeout for each portion of a message based
|
||||
VXI transfer. The default timeout is 10 seconds.
|
||||
|
||||
.SH RETURNS
|
||||
See epvxiMsgLib(1) for a description of the return codes from this library.
|
||||
.SH SEE ALSO
|
||||
epvxiMsgLib(1), epvxiLib(1)
|
||||
|
||||
|
||||
.TH epvxiSetTraceEnable 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiSetTraceEnable - set trace mode on or off
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiSetTraceEnable(la, enable)
|
||||
unsigned la; /* logical address */
|
||||
int enable; /* T=trace on, F=trace off */
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
Set trace mode on or off. If "enable" is true then trace mode is enabled.
|
||||
If "enable" is false then trace mode is turned off. Trace mode is enable
|
||||
for each VXI message based device independently.
|
||||
|
||||
.SH RETURNS
|
||||
See epvxiMsgLib(1) for a description of the return codes from this library.
|
||||
.SH SEE ALSO
|
||||
epvxiMsgLib(1), epvxiLib(1)
|
||||
|
||||
|
||||
|
||||
.TH epvxiLib 1 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiLib.c - the VXI driver support library
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
|
||||
epvxiLookupLA - find all devices matching a pattern
|
||||
epvxiUniqueDriverID - return a non zero unique identification for a VXI driver
|
||||
epvxiOpen - open a VXI device
|
||||
epvxiClose - close a VXI device
|
||||
epvxiPConfig - MACRO which returns a pointer to the drivers private structure
|
||||
epvxiFetchPConfig - similar to epvxiPConfig but with status
|
||||
epvxiRouteTriggerECL - route an ECL trigger to/from the front panel
|
||||
epvxiRouteTriggerTTL - route an TTL trigger to/from the front panel
|
||||
epvxiResman - perform VXI resource management and setup the MXI bus
|
||||
epvxiDeviceList - list which drivers own which devices
|
||||
epvxiCrateList - list all slot zero devices
|
||||
epvxiExtenderList - list all extender devices and there windows
|
||||
epvxiIOReport - list all VXI hardware in the system
|
||||
|
||||
|
||||
int epvxiLookupLA(pmatch_structure, pcallback, pargument)
|
||||
int epvxiUniqueDriverID()
|
||||
int epvxiOpen(la, driverID, structure_size, pioReportFunction)
|
||||
int epvxiClose(la, driverID)
|
||||
(<structure declaration> *) epvxiPConfig(la, driverID, <structure declaration>)
|
||||
int epvxiFetchPConfig(la, driverID, pConfig)
|
||||
int epvxiRouteTriggerECL (la, trigger, io)
|
||||
int epvxiRouteTriggerTTL(la, trigger, io)
|
||||
int epvxiResman()
|
||||
int epvxiDeviceList()
|
||||
int epvxiCrateList()
|
||||
int epvxiExtenderList()
|
||||
int epvxiIOReport(level)
|
||||
.fi
|
||||
|
||||
This is the structure used to specify search patterns for epvxiLookupLA().
|
||||
Set a bit in the flags member for each item that is to be a
|
||||
constraint on the search. All other items are ignored during
|
||||
the search. The call back routine will be called for all devices
|
||||
which exactly match all items specified in the flags field
|
||||
|
||||
.nf
|
||||
#define VXI_DSP_make (1<<0)
|
||||
#define VXI_DSP_model (1<<1)
|
||||
#define VXI_DSP_class (1<<2)
|
||||
#define VXI_DSP_slot (1<<3)
|
||||
#define VXI_DSP_slot_zero_la (1<<4)
|
||||
#define VXI_DSP_commander_la (1<<5)
|
||||
#define VXI_DSP_extender_la (1<<6) /* id crates that have one */
|
||||
|
||||
typedef struct {
|
||||
long flags; /* one bit enabling each field */
|
||||
unsigned short make; /* manufacture identification */
|
||||
unsigned short model; /* model code for the device */
|
||||
unsigned short class; /* VXI device class */
|
||||
unsigned char slot; /* slot where the device resides */
|
||||
unsigned char slot_zero_la; /* logical address of slot 0 device */
|
||||
unsigned char commander_la /* logical address of commander */
|
||||
unsigned char extender_la /* logical address of bus repeater */
|
||||
}epvxiDeviceSearchPattern;
|
||||
.fi
|
||||
|
||||
.SH DESCRIPTION
|
||||
.nf
|
||||
Low level support needed if you are writing a VXI driver:
|
||||
* Determine the logical address of all devices in a particular slot
|
||||
* Determine the logical address of all devices of a particular make or model
|
||||
* Prevent two drivers from accessing the same card
|
||||
* Prevent a driver from accessing a nonexistent card
|
||||
* Return a pointer to the driver's private variables given a logical address
|
||||
* Device independent front panel trigger routing on the slot zero device
|
||||
.fi
|
||||
|
||||
The message based device interface library epvxiMsgLib(1) is
|
||||
an example of a VXI driver which utilizes this core VXI driver support.
|
||||
|
||||
.SH INCLUDES
|
||||
epvxiLib.h
|
||||
|
||||
.SH RETURNS
|
||||
.nf
|
||||
less than zero- operation failed
|
||||
greater than zero- operation successful
|
||||
|
||||
#define VXI_SUCCESS 0 /* successful completion */
|
||||
#define VXI_NO_DEVICE (-1) /* device does not exist */
|
||||
#define VXI_NOT_SLOT0 (-2) /* not a slot zero device */
|
||||
#define VXI_UKN_DEVICE (-3) /* device not supported */
|
||||
#define VXI_BAD_TRIGGER (-4) /* no such trigger */
|
||||
#define VXI_BAD_TRIG_IO (-5) /* no such trigger io */
|
||||
#define VXI_DEVICE_OPEN (-6) /* device already open */
|
||||
#define VXI_NOT_OWNER (-7) /* dev in use by another drv */
|
||||
#define VXI_NO_MEMORY (-8) /* failed to allocate memory */
|
||||
#define VXI_NOT_OPEN (-9) /* device not open */
|
||||
#define VXI_NOT_MSG_DEVICE (-10) /* must be a message based dev */
|
||||
#define VXI_MSG_DEVICE_TMO (-11) /* message based dev timed out */
|
||||
#define VXI_MSG_DEVICE_FAILURE (-12) /* message based dev failed */
|
||||
#define VXI_BAD_LA (-13) /* logical addr out of range */
|
||||
#define VXI_MULTIPLE_QUERIES (-14) /* serial protocol error */
|
||||
#define VXI_UNSUPPORTED_CMD (-15) /* serial protocol error */
|
||||
#define VXI_DIR_VIOLATION (-16) /* serial protocol error */
|
||||
#define VXI_DOR_VIOLATION (-17) /* serial protocol error */
|
||||
#define VXI_RR_VIOLATION (-18) /* serial protocol error */
|
||||
#define VXI_WR_VIOLATION (-19) /* serial protocol error */
|
||||
#define VXI_ERR_FETCH_FAIL (-20) /* ukn serial protocol error */
|
||||
#define VXI_SELF_TEST_FAILED (-21) /* self test failed */
|
||||
#define VXI_TIMEOUT_TO_LARGE (-22) /* supplied timeout to long */
|
||||
#define VXI_PROTOCOL_ERROR (-23) /* protocol error */
|
||||
|
||||
|
||||
|
||||
.fi
|
||||
.SH SEE ALSO
|
||||
epvxiMsgLib(1)
|
||||
|
||||
.TH epvxiLookupLA 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiLookupLA - find all of the devices matching a search pattern
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiLookupLA(pmatch_structure, pcallback, pargument)
|
||||
epvxiDeviceSearchPattern *pmatch_structure;
|
||||
void (*pcallback)();
|
||||
void *pargument;
|
||||
|
||||
/*
|
||||
* your call back
|
||||
*/
|
||||
void callback(la, pargument)
|
||||
unsigned la;
|
||||
void *pargument;
|
||||
{
|
||||
}
|
||||
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
|
||||
Find all devices in the system matching the search pattern and call
|
||||
the specified call back for each of them. The search pattern is specified
|
||||
by filling fields in the structure epvxiDeviceSearchPattern and
|
||||
setting the flags field of the same structure to match. For example:
|
||||
|
||||
.nf
|
||||
epvxiDeviceSearchPattern dsp;
|
||||
dsp.make = VXI_MAKE_HP;
|
||||
dsp.model = 0xffc;
|
||||
dsp.flags = VXI_DSP_make | VXI_DSP_model;
|
||||
epvxiLookupLA(&dsp, pcallback, pargument);
|
||||
.fi
|
||||
|
||||
A list of these constants can be found in epvxiLib.h and
|
||||
device make codes can be found in epvxi.h
|
||||
|
||||
This is the structure used to specify search patterns for epvxiLookupLA().
|
||||
Set a bit in the flags member for each item that is to be a
|
||||
constraint on the search. All other items are ignored during
|
||||
the search. The call back routine will be called for all devices
|
||||
which exactly match all items specified in the flags field
|
||||
|
||||
.nf
|
||||
#define VXI_DSP_make (1<<0)
|
||||
#define VXI_DSP_model (1<<1)
|
||||
#define VXI_DSP_class (1<<2)
|
||||
#define VXI_DSP_slot (1<<3)
|
||||
#define VXI_DSP_slot_zero_la (1<<4)
|
||||
#define VXI_DSP_commander_la (1<<5)
|
||||
|
||||
typedef struct {
|
||||
long flags; /* one bit enabling each field */
|
||||
unsigned short make; /* manufacture identification */
|
||||
unsigned short model; /* model code for the device */
|
||||
unsigned short class; /* VXI device class */
|
||||
unsigned char slot; /* slot where the device resides */
|
||||
unsigned char slot_zero_la; /* logical address of slot 0 device */
|
||||
unsigned char commander_la /* logical address of commander */
|
||||
}epvxiDeviceSearchPattern;
|
||||
.fi
|
||||
|
||||
.SH RETURNS
|
||||
Returns a non zero unique constant to be used as a driver identification.
|
||||
|
||||
.SH SEE ALSO
|
||||
epvxiLib(1),
|
||||
|
||||
.TH epvxiUniqueDriverID 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiUniqueDriverID - return a non zero unique identification for a VXI driver
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiUniqueDriverID ()
|
||||
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
|
||||
Should be called once only
|
||||
by each type of VXI driver to uniquely identify itself. The routines
|
||||
in epvxiDrvLib.c use this constant to prevent a VXI device from being
|
||||
accessed by the wrong driver.
|
||||
|
||||
.SH RETURNS
|
||||
|
||||
.SH SEE ALSO
|
||||
epvxiLib(1),
|
||||
|
||||
.TH epvxiOpen 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiOpen - open a VXI device for a VXI driver
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiOpen (la, epvxiDriverID, structureSize, pio_report_func)
|
||||
unsigned la;
|
||||
int epvxiDriverID;
|
||||
unsigned long structureSize;
|
||||
void (*pio_report_func)();
|
||||
|
||||
void pio_report_func(la, level)
|
||||
unsigned la;
|
||||
int level;
|
||||
{
|
||||
}
|
||||
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
|
||||
Records this driver as the owner of the device at the specified logical
|
||||
address la and verifies that the device has passed it's self test.
|
||||
Allocates memory of size structureSize and saves a
|
||||
pointer to this memory with the logical address for future use by the
|
||||
driver with identification epvxiDriverID for its private configuration.
|
||||
Installs call back routine pio_report_func as an io report function to
|
||||
be called each time the user requests the status
|
||||
of VXI devices. This routine is called with the logical address
|
||||
and an integer specifying the detail level of the report
|
||||
as the first and second arguments respectively.
|
||||
The macro epvxiFetchPConfig returns a pointer to this block if the
|
||||
specified device has been opened by the specified driver.
|
||||
|
||||
.SH RETURNS
|
||||
|
||||
.SH SEE ALSO
|
||||
epvxiUniqueDriverID()
|
||||
epvxiFetchPConfig()
|
||||
epvxiLib(1),
|
||||
|
||||
.TH epvxiClose 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiClose - close a VXI device for a VXI driver
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiClose (la, vxiDriverID)
|
||||
unsigned la;
|
||||
int vxiDriverID;
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
|
||||
Releases driver ownership of the device at the specified logical
|
||||
address la. Deallocates memory in use for the driver's private
|
||||
configuration.
|
||||
|
||||
.SH RETURNS
|
||||
|
||||
.SH SEE ALSO
|
||||
epvxiLib(1),
|
||||
|
||||
|
||||
.TH epvxiFetchPConfig 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiFetchPConfig - macro which loads a pointer to the drivers private structure
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int evxiFetchPConfig (la, vxiDriverID, pConfig)
|
||||
unsigned la;
|
||||
int vxiDriverID;
|
||||
stuct XXXXXX *pConfig;
|
||||
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
|
||||
epvxiFetchPConfig() is a MACRO which loads a pointer to the devices
|
||||
private configuration block (ie pConfig above). This macro
|
||||
replaces the macro epvxiPConfig() which didnt return status.
|
||||
|
||||
This routine performs two functions:
|
||||
.nf
|
||||
1) Loads a pointer to the device's configuration block.
|
||||
2) Informs your driver if the specified device does not exist or has
|
||||
been opened by another driver.
|
||||
.fi
|
||||
|
||||
.SH RETURNS
|
||||
.SH SEE ALSO
|
||||
epvxiLib(1),
|
||||
|
||||
|
||||
|
||||
|
||||
.TH epvxiRouteTriggerECL 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiRouteTriggerECL - route an ECL trigger to/from the front panel
|
||||
of a supported VXI device
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiRouteTriggerECL (la, trigger, io)
|
||||
unsigned la; /* 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 */
|
||||
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
Route a VXI backplane trigger to or from the front panel of a slot zero
|
||||
device.
|
||||
The bits in argument enable_map correspond to an enable for triggers
|
||||
0-5 (1 enables the trigger and 0 disables the trigger). The bits
|
||||
in argument io_map set the direction for triggers 0-5 (1 sources
|
||||
the front panel and 0 sources the backplane).
|
||||
|
||||
Most VXI slot zero devices have one trigger output and one trigger input
|
||||
connector. The trigger input connector can drive multiple VXI backplane
|
||||
triggers. The trigger output connector should be driven by only one of
|
||||
the backplane triggers at a time.
|
||||
|
||||
.SH RETURNS
|
||||
.SH SEE ALSO
|
||||
epvxiLib(1),
|
||||
|
||||
|
||||
.TH epvxiRouteTriggerTTL 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiRouteTriggerTTL - route an TTL trigger to/from the front panel
|
||||
of a supported VXI device
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiRouteTriggerTTL (la, trigger, io)
|
||||
unsigned la; /* 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 */
|
||||
|
||||
.fi
|
||||
.CE
|
||||
.SH DESCRIPTION
|
||||
|
||||
Route a VXI backplane trigger to or from the front panel of a slot zero
|
||||
device.
|
||||
The bits in argument enable_map correspond to an enable for triggers
|
||||
0-5 (1 enables the trigger and 0 disables the trigger). The bits
|
||||
in argument io_map set the direction for triggers 0-5 (1 sources
|
||||
the front panel and 0 sources the backplane).
|
||||
|
||||
Most VXI slot zero devices have one trigger output and one trigger input
|
||||
connector. The trigger input connector can drive multiple VXI backplane
|
||||
triggers. The trigger output connector should be driven by only one of
|
||||
the backplane triggers at a time.
|
||||
|
||||
.SH RETURNS
|
||||
.SH SEE ALSO
|
||||
epvxiLib(1),
|
||||
|
||||
|
||||
|
||||
|
||||
.TH epvxiResman 2 "" "EPICS Reference Manual"
|
||||
.ad b
|
||||
.SH NAME
|
||||
epvxiResman - perform VXI resource management and MXI bus setup
|
||||
.SH SYNOPSIS
|
||||
.CS
|
||||
.nf
|
||||
#include <epvxiLib.h>
|
||||
int epvxiResman ()
|
||||
|
||||
.fi
|
||||
.CE
|
||||
.nf
|
||||
MXI bus background information
|
||||
|
||||
o A MXI bus extender facilitates bus communication between
|
||||
a VME bus master and a VME bus slave that are installed
|
||||
in different crates. MXI bus extenders can be joined
|
||||
together in a hierarchy interconnected by the MXI bus.
|
||||
|
||||
o A MXI bus extender's LA window determines the VXI LA range
|
||||
over which local VME bus master initiated requests are
|
||||
extended onto the MXI bus.
|
||||
|
||||
o A MXI bus extender's LA window also determines the MXI
|
||||
LA range over which MXI extended bus master requests
|
||||
are allowed to be further extended into the local VXI bus.
|
||||
|
||||
o MXI bus extenders are always SC devices. A MXI bus
|
||||
extenders are always accessible from the MXI bus
|
||||
invariant of the location of its LA window.
|
||||
Conclusion: the LA of a MXI does not constrain the
|
||||
location of its LA window.
|
||||
|
||||
o Each MXI's LA window must be large enough to contain all
|
||||
of the MXI bus extender LA windows beneath it in the
|
||||
hierarchy. A MXI's LA window may not overlap the windows of
|
||||
any other MXI'at the same level in the hierarchy.
|
||||
|
||||
o SC devices within one crate must be within a block
|
||||
which does not overlap the LA windows of other
|
||||
MXI bus extenders at the same level in the
|
||||
hierarchy. Likewise SC devices within one crate
|
||||
must not overlap the LA windows of MXI bus
|
||||
extenders at a lower level in the hierarchy.
|
||||
|
||||
|
||||
EPICS VXI resource manager background information
|
||||
|
||||
o The EPICS VXI resource manager will always successfully
|
||||
allocate all DC devices in a DC MXI bus system if
|
||||
the available LA address range is large enough and
|
||||
if all devices other than the resource manager and
|
||||
the MXIs are DC.
|
||||
|
||||
o Otherwise if some of the devices in the system
|
||||
(other than the MXIs and the resource manager) are
|
||||
SC then the burden is placed on the project
|
||||
engineer to guarantee that SC devices are located
|
||||
such that nonoverlapping MXI LA windows can
|
||||
be allocated by the resource manager. Additionally
|
||||
the project engineer must locate the SC devices
|
||||
so that there is sufficient space to allocate the LAs
|
||||
of DC devices into nonoverlapping MXI LA windows.
|
||||
If the project engineer locates SC devices
|
||||
correctly the resource manager will always find the
|
||||
corresponding window hierarchy that provides
|
||||
access to all devices. If the project engineer
|
||||
improperly locates SC devices the resource manager
|
||||
will detect it and print a message.
|
||||
|
||||
o The CPU running the EPICS VXI resource manager is at the
|
||||
root of the MXI hierarchy.
|
||||
|
||||
o The resource manager will never allocate a DC device
|
||||
at a LA overlapping an interrupt vector already
|
||||
allocated to another device (use "veclist()" to
|
||||
determine what vectors are in use).
|
||||
|
||||
|
||||
|
||||
Resource manager DC device allocation rules
|
||||
|
||||
o When DC devices are allocated they will be placed between
|
||||
existing SC devices (in the same extender) first.
|
||||
Next they will be placed after existing DC devices
|
||||
(in the same extender). If there isn't room above existing
|
||||
DC devices then the resource manager will attempt to
|
||||
allocate DC device beneath the existing SC devices.
|
||||
If devices in other extenders (the limits of other windows)
|
||||
bracket the upper and lower limits of an extender's
|
||||
window there may not be enough space to allocate
|
||||
all of the DC devices present in a crate.
|
||||
If so, a warning message will be printed and the DC
|
||||
device will not be allocated a valid LA.
|
||||
|
||||
o If the only SC device in a crate is the MXI granting access
|
||||
to the crate then the resource manager will be free to place
|
||||
any DC devices found in a contiguous block where there is room.
|
||||
The resource manager requires block allocation because the MXI
|
||||
address window must contain only the DC device LA assignments
|
||||
for the current crate. This contiguous block will be placed
|
||||
at the highest open LA block available. If a contiguous block
|
||||
of sufficient size is not found then none of the DC devices will
|
||||
be allocated (assigned) valid LAs and a warning message
|
||||
will be printed. This block will not be anchored in any way
|
||||
to the SC LA of the extender that provides access to the
|
||||
DC devices in the crate.
|
||||
|
||||
|
||||
.fi
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,473 +0,0 @@
|
||||
/* drvEpvxi.h */
|
||||
/* $Id$ */
|
||||
/*
|
||||
* parameter file supporting the VXI library
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 8-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 070792 joh Added MACROS to return the A24 and A32 base addr
|
||||
* .02 072992 joh Added sccs id
|
||||
* .03 081992 joh ANSI C func proto
|
||||
* .04 082592 joh added arg to epvxiRead() and epvxiWrite()
|
||||
* .05 090392 joh Now runtime links to NI trigger routing
|
||||
* .06 092392 joh New status from epvxiRead() - VXI_BUFFER_FULL
|
||||
* .07 033193 joh error codes converted to EPICS standard format
|
||||
* .08 071293 joh record task id when opening a device
|
||||
* .09 082793 joh -Wall cleanup and added drvEpvxiFetchPConfig()
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef INCepvxiLibh
|
||||
#define INCepvxiLibh
|
||||
|
||||
static char *epvxiLibhSccId = "$Id$";
|
||||
|
||||
#include <ellLib.h>
|
||||
#include <epvxi.h>
|
||||
#include <errMdef.h>
|
||||
|
||||
/*
|
||||
* Structure used to specify search patterns for epvxiLookupLA()
|
||||
*
|
||||
* Set a bit in the flags member for each item that is to be a
|
||||
* constraint on the search. All other items are ignored during
|
||||
* the search. The callback routine will be called for all devices
|
||||
* which exactly match all items specified in the flags field
|
||||
*/
|
||||
#define VXI_DSP_make (1<<0)
|
||||
#define VXI_DSP_model (1<<1)
|
||||
#define VXI_DSP_class (1<<2)
|
||||
#define VXI_DSP_slot (1<<3)
|
||||
#define VXI_DSP_slot_zero_la (1<<4)
|
||||
#define VXI_DSP_commander_la (1<<5)
|
||||
#define VXI_DSP_extender_la (1<<6) /* id crates that have one */
|
||||
|
||||
typedef struct {
|
||||
long flags; /* one bit enabling each field */
|
||||
unsigned short make; /* manufacture identification */
|
||||
unsigned short model; /* model code for the device */
|
||||
unsigned short class; /* vxi device class */
|
||||
unsigned char slot; /* slot where the device resides */
|
||||
unsigned char slot_zero_la; /* logical address of slot 0 dev */
|
||||
unsigned char commander_la; /* logical address of commander */
|
||||
unsigned char extender_la; /* logical address of bus repeater */
|
||||
}epvxiDeviceSearchPattern;
|
||||
|
||||
typedef long EPVXISTAT;
|
||||
|
||||
/*
|
||||
* functions from epvxiLib.c
|
||||
*/
|
||||
EPVXISTAT epvxiResman(
|
||||
void
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiIOReport(
|
||||
unsigned level
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiDeviceList(
|
||||
void
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiCrateList(
|
||||
void
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiExtenderList(
|
||||
void
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiUniqueDriverID(
|
||||
void
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiDeviceVerify(
|
||||
unsigned la
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiOpen(
|
||||
unsigned la,
|
||||
int vxiDriverID,
|
||||
unsigned long driverConfigSize,
|
||||
void (*pio_report_func)()
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiClose(
|
||||
unsigned la,
|
||||
int vxiDriverID
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiLookupLA(
|
||||
epvxiDeviceSearchPattern
|
||||
*pdsp,
|
||||
void (*pfunc)(unsigned, void *),
|
||||
void *parg
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiRouteTriggerECL(
|
||||
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 */
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiRouteTriggerTTL(
|
||||
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 */
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiRegisterModelName(
|
||||
unsigned int make,
|
||||
unsigned int model,
|
||||
char *pmodel_name
|
||||
);
|
||||
|
||||
EPVXISTAT epvxiRegisterMakeName(
|
||||
unsigned int make,
|
||||
char *pmake_name
|
||||
);
|
||||
|
||||
EPVXISTAT epuxiLookupModelName(
|
||||
unsigned int make, /* VXI manuf. */
|
||||
unsigned int model, /* VXI model code */
|
||||
char *pbuffer, /* model name return */
|
||||
unsigned int bufsize, /* size of supplied buf */
|
||||
unsigned int *preadcount /* n bytes written */
|
||||
);
|
||||
|
||||
EPVXISTAT epuxiLookupMakeName(
|
||||
unsigned int make, /* VXI manuf. */
|
||||
char *pbuffer, /* model name return */
|
||||
unsigned int bufsize, /* size of supplied buf */
|
||||
unsigned int *preadcount /* n bytes written */
|
||||
);
|
||||
|
||||
EPVXISTAT vxi_init( /* compatibility */
|
||||
void
|
||||
);
|
||||
|
||||
EPVXISTAT vxi_io_report( /* compatibility */
|
||||
unsigned level
|
||||
);
|
||||
|
||||
/*
|
||||
* functions from epvxiMsgLib.c
|
||||
*/
|
||||
EPVXISTAT epvxiCmd(
|
||||
unsigned la,
|
||||
unsigned long cmd
|
||||
);
|
||||
EPVXISTAT epvxiQuery(
|
||||
unsigned la,
|
||||
unsigned long *presp
|
||||
);
|
||||
EPVXISTAT epvxiCmdQuery(
|
||||
unsigned la,
|
||||
unsigned long cmd,
|
||||
unsigned long *presp
|
||||
);
|
||||
EPVXISTAT epvxiRead(
|
||||
unsigned la,
|
||||
char *pbuf,
|
||||
unsigned long count,
|
||||
unsigned long *pread_count,
|
||||
unsigned long option
|
||||
);
|
||||
#define epvxiReadOptNone 0
|
||||
|
||||
EPVXISTAT epvxiWrite(
|
||||
unsigned la,
|
||||
char *pbuf,
|
||||
unsigned long count,
|
||||
unsigned long *pwrite_count,
|
||||
unsigned long option
|
||||
);
|
||||
#define epvxiWriteOptNone 0
|
||||
#define epvxiWriteOptPartialMsg 1 /* message continues after this transfer */
|
||||
|
||||
EPVXISTAT epvxiSetTimeout(
|
||||
unsigned la,
|
||||
unsigned long timeout
|
||||
);
|
||||
|
||||
/*
|
||||
* epvxiLib return codes (also used by epvxiMsgLib)
|
||||
*
|
||||
* These codes changed to the EPICS standrd format on 033193
|
||||
*/
|
||||
#define VXI_SUCCESS 0 /* normal successful completion*/
|
||||
#define S_epvxi_noDevice (M_epvxi|1) /*device does not exist*/
|
||||
#define S_epvxi_notSlotZero (M_epvxi|2) /*not a slot zero devic*/
|
||||
#define S_epvxi_uknDevice (M_epvxi|3) /*device not supported*/
|
||||
#define S_epvxi_badTrigger (M_epvxi|4) /*specified trigger does not exist*/
|
||||
#define S_epvxi_badTrigIO (M_epvxi|5) /*specified trigger io does not exist*/
|
||||
#define S_epvxi_deviceOpen (M_epvxi|6) /*device already open*/
|
||||
#define S_epvxi_notOwner (M_epvxi|7) /*device in use by a different driver*/
|
||||
#define S_epvxi_noMemory (M_epvxi|8) /*memory allocation failed*/
|
||||
#define S_epvxi_notOpen (M_epvxi|9) /*device not open*/
|
||||
#define S_epvxi_notMsgDevice (M_epvxi|10) /*operation requires a message based device*/
|
||||
#define S_epvxi_deviceTMO (M_epvxi|11) /*message based dev timed out*/
|
||||
#define S_epvxi_msgDeviceFailure (M_epvxi|12) /*message based dev failed*/
|
||||
#define S_epvxi_badLA (M_epvxi|13) /*logical addr out of range*/
|
||||
#define S_epvxi_multipleQueries (M_epvxi|14) /*multiple queries serial protocol error*/
|
||||
#define S_epvxi_unsupportedCmd (M_epvxi|15) /*unsupported cmd serial protocol error*/
|
||||
#define S_epvxi_dirViolation (M_epvxi|16) /*DIR violation serial protocol error*/
|
||||
#define S_epvxi_dorViolation (M_epvxi|17) /*DOR violation serial protocol error*/
|
||||
#define S_epvxi_rrViolation (M_epvxi|18) /*RR violation serial protocol error*/
|
||||
#define S_epvxi_wrViolation (M_epvxi|19) /*WR violation serial protocol error*/
|
||||
#define S_epvxi_errFetchFailed (M_epvxi|20) /*unknown serial protocol error*/
|
||||
#define S_epvxi_selfTestFailed (M_epvxi|21) /*self test failed*/
|
||||
#define S_epvxi_timeoutToLarge (M_epvxi|22) /*specified timeout to long*/
|
||||
#define S_epvxi_protocolError (M_epvxi|23) /*protocol error*/
|
||||
#define S_epvxi_unreadData (M_epvxi|24) /*attempt to write when unread data from a previous command is present (RULE C.3.3)*/
|
||||
#define S_epvxi_nameMismatch (M_epvxi|25) /*make or model name already registered does not matchi supplied name*/
|
||||
#define S_epvxi_noMatch (M_epvxi|26) /*no name registered for the supplied make and or model*/
|
||||
#define S_epvxi_bufferFull (M_epvxi|27) /*read terminated with unread data remaining because the end of the supplied buffer was reached*/
|
||||
#define S_epvxi_noResman (M_epvxi|28) /*the VXI resource manager must run first*/
|
||||
#define S_epvxi_internal (M_epvxi|29) /*VXI internal failure*/
|
||||
#define S_epvxi_badConfig (M_epvxi|30) /*Incorrect system configuration*/
|
||||
#define S_epvxi_noCmdr (M_epvxi|31) /*No commander hardware support for message based comm - continuing*/
|
||||
#define S_epvxi_msgDeviceStatus (M_epvxi|32) /*VXI Message based device reporting error condition*/
|
||||
#define S_epvxi_slotNotFound (M_epvxi|33) /*VXI device's slot not found- MODID failure?*/
|
||||
#define S_epvxi_noMODID (M_epvxi|34) /*VXI device does not have MODID capability*/
|
||||
|
||||
|
||||
enum ext_type { ext_local_cpu, /* bus master constrained by module_types.h */
|
||||
ext_export_vxi_onto_mxi, /* VXI mapped into MXI addr space */
|
||||
ext_import_mxi_into_vxi /* MXI mapped into VXI addr space */
|
||||
/*
|
||||
.
|
||||
.
|
||||
other bus extender types could be inserted here
|
||||
.
|
||||
.
|
||||
*/
|
||||
};
|
||||
|
||||
#ifndef SRCepvxiLib
|
||||
extern
|
||||
#endif
|
||||
char *ext_type_name[]
|
||||
#ifdef SRCepvxiLib
|
||||
= {
|
||||
"VXI hosted VME bus master",
|
||||
"VXI mapped onto MXI addr space",
|
||||
"MXI mapped into VXI addr space"
|
||||
}
|
||||
#endif
|
||||
;
|
||||
|
||||
typedef struct extender_device{
|
||||
ELLNODE node;
|
||||
ELLLIST extenders; /* sub extenders */
|
||||
struct extender_device *pParent;
|
||||
struct slot_zero_device *pSZD;
|
||||
enum ext_type type;
|
||||
int la;
|
||||
int la_low; /* inclusive */
|
||||
int la_high; /* inclusive */
|
||||
unsigned long A24_base;
|
||||
unsigned long A24_size;
|
||||
unsigned long A32_base;
|
||||
unsigned long A32_size;
|
||||
unsigned la_mapped:1; /* device present */
|
||||
unsigned A24_mapped:1;
|
||||
unsigned A32_mapped:1;
|
||||
unsigned A24_ok:1;
|
||||
unsigned A32_ok:1;
|
||||
}VXIE;
|
||||
|
||||
/*
|
||||
* bits for the device type and a pointer
|
||||
* to its configuration registers if
|
||||
* available
|
||||
*/
|
||||
typedef struct slot_zero_device{
|
||||
ELLNODE node;
|
||||
void (*set_modid)(struct slot_zero_device *pvxisz, unsigned slot);
|
||||
void (*clear_modid)(struct slot_zero_device *pvxisz);
|
||||
EPVXISTAT (*report)(unsigned la, unsigned level);
|
||||
VXIE *pvxie;
|
||||
struct vxi_csr *pcsr;
|
||||
unsigned char la;
|
||||
unsigned reg:1;
|
||||
unsigned msg:1;
|
||||
}VXISZ;
|
||||
|
||||
typedef struct epvxiLibDeviceConfig{
|
||||
void (*pio_report_func)(); /* ptr to io report func */
|
||||
void *pDriverConfig; /* ptr to driver config */
|
||||
void *pMsgConfig; /* msg driver config area */
|
||||
void *pFatAddrBase;
|
||||
VXIE *pvxie; /* extender info */
|
||||
VXIE *pvxieSelf; /* extender info for self */
|
||||
VXISZ *pvxisz; /* ptr to slot zero info */
|
||||
unsigned long driverID; /* unique driver id */
|
||||
int taskID; /* opened by this id */
|
||||
unsigned short make;
|
||||
unsigned short model;
|
||||
short slot;
|
||||
short commander_la;
|
||||
short extender_la; /* logical address of bus repeater */
|
||||
unsigned char class;
|
||||
unsigned st_passed:1; /* self test passed */
|
||||
unsigned msg_dev_online:1;
|
||||
unsigned A24_mapped:1;
|
||||
unsigned A32_mapped:1;
|
||||
}VXIDI;
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* functions used from the nivxi library
|
||||
* (to support runtime linking)
|
||||
*
|
||||
*/
|
||||
enum nivxi_func_index {
|
||||
e_SetMODID,
|
||||
e_VXIinLR,
|
||||
e_InitVXIlibrary,
|
||||
e_vxiinit,
|
||||
e_MapTrigToTrig,
|
||||
e_GetMyLA,
|
||||
e_EnableSignalInt,
|
||||
e_SetSignalHandler,
|
||||
e_RouteSignal
|
||||
};
|
||||
#ifndef SRCepvxiLib
|
||||
extern
|
||||
#endif
|
||||
char *nivxi_func_names[]
|
||||
#ifdef SRCepvxiLib
|
||||
= {
|
||||
"_SetMODID",
|
||||
"_VXIinLR",
|
||||
"_InitVXIlibrary",
|
||||
"_vxiinit", /* WARNING this is different than vxiInit */
|
||||
"_MapTrigToTrig",
|
||||
"_GetMyLA",
|
||||
"_EnableSignalInt",
|
||||
"_SetSignalHandler",
|
||||
"_RouteSignal"
|
||||
}
|
||||
#endif
|
||||
;
|
||||
|
||||
#ifdef SRCepvxiLib
|
||||
int (*pnivxi_func[NELEMENTS(nivxi_func_names)])();
|
||||
#else
|
||||
extern
|
||||
int (*pnivxi_func[])();
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* typical usage
|
||||
*
|
||||
* struct freds_driver_info pfdi;
|
||||
*
|
||||
* pfdi = epvxiPConfig(14, driverID, (struct freds_driver_info *))
|
||||
*
|
||||
* RETURNS ptr to device config area or NULL
|
||||
*/
|
||||
#define PVXIDI(LA) (epvxiLibDeviceList[LA])
|
||||
#define epvxiPConfig(LA, ID, CAST) \
|
||||
( \
|
||||
PVXIDI(LA)? \
|
||||
PVXIDI(LA)->driverID==(ID)? \
|
||||
(CAST) PVXIDI(LA)->pDriverConfig \
|
||||
: \
|
||||
(CAST) NULL \
|
||||
: \
|
||||
(CAST) NULL \
|
||||
)
|
||||
|
||||
/*
|
||||
* epvxiFetchPConfig
|
||||
* (improved version of the above returns status)
|
||||
*/
|
||||
#define epvxiFetchPConfig(LA, ID, PTR) \
|
||||
( \
|
||||
PVXIDI(LA)!=NULL? \
|
||||
(PVXIDI(LA)->driverID==(ID)? \
|
||||
(((PTR) = PVXIDI(LA)->pDriverConfig), VXI_SUCCESS) \
|
||||
: \
|
||||
S_epvxi_notOwner) \
|
||||
: \
|
||||
S_epvxi_noDevice \
|
||||
)
|
||||
|
||||
/*
|
||||
* A24 and A32 base addressing
|
||||
*/
|
||||
#define epvxiA24Base(LA) (PVXIDI(LA)->pFatAddrBase)
|
||||
#define epvxiA32Base(LA) (PVXIDI(LA)->pFatAddrBase)
|
||||
|
||||
#ifndef SRCepvxiLib
|
||||
extern
|
||||
#endif
|
||||
VXIDI *epvxiLibDeviceList[NVXIADDR];
|
||||
|
||||
#define NO_DRIVER_ATTACHED_ID (0)
|
||||
#define UNINITIALIZED_DRIVER_ID (0xffff)
|
||||
#ifndef SRCepvxiLib
|
||||
extern
|
||||
#endif
|
||||
unsigned long epvxiNextDriverID
|
||||
#ifdef SRCepvxiLib
|
||||
= (NO_DRIVER_ATTACHED_ID+1)
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* set by the RM when it is done and VXI modules are present
|
||||
*/
|
||||
#ifndef SRCepvxiLib
|
||||
extern
|
||||
#endif
|
||||
int epvxiResourceMangerOK;
|
||||
|
||||
#ifndef SRCepvxiLib
|
||||
extern
|
||||
#endif
|
||||
volatile void *epvxi_local_base;
|
||||
|
||||
#define VXIBASE(LA) VXI_LA_TO_PA(LA, epvxi_local_base)
|
||||
|
||||
#endif /* INCepvxiLibh */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,414 +0,0 @@
|
||||
/* 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 "dbDefs.h"
|
||||
#include "errlog.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,
|
||||
void *pArg
|
||||
);
|
||||
|
||||
LOCAL int hpE1404ShutDown(
|
||||
void
|
||||
);
|
||||
|
||||
LOCAL void hpE1404ShutDownLA(
|
||||
unsigned la,
|
||||
void *pArg
|
||||
);
|
||||
|
||||
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,
|
||||
void *pArg
|
||||
)
|
||||
{
|
||||
struct vxi_csr *pcsr;
|
||||
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pcsr->IRQ_enable = HP1404A_INT_DISABLE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hpE1404InitLA()
|
||||
*
|
||||
*/
|
||||
LOCAL
|
||||
void hpE1404InitLA(
|
||||
unsigned la,
|
||||
void *pArg
|
||||
)
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/* 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
|
||||
|
||||
|
||||
@@ -1,361 +0,0 @@
|
||||
/* 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 "dbDefs.h"
|
||||
#include "errlog.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 */
|
||||
uint16_t pending; /* switch position pending int */
|
||||
uint16_t 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, void *pArg);
|
||||
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, void *pArg)
|
||||
{
|
||||
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_vecInstlFail, 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;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/* 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
@@ -1,341 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
drvIpMv162.c
|
||||
|
||||
Description:
|
||||
IPAC Carrier Driver for the IndustryPack carriers on the Motorola
|
||||
MVME162 CPU board, provides the interface between IPAC driver and the
|
||||
hardware.
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
6 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <vme.h>
|
||||
#include <sysLib.h>
|
||||
#include <vxLib.h>
|
||||
#include "drvIpac.h"
|
||||
#include "ipic.h"
|
||||
|
||||
|
||||
/* Characteristics of the card */
|
||||
|
||||
#define SLOTS 4
|
||||
#define IO_SPACES 2 /* Address spaces in A16 */
|
||||
#define IPAC_IRQS 2 /* Interrupts per module */
|
||||
#define IPIC_BASE 0xfffbc000
|
||||
|
||||
|
||||
/* Base Addresses of IO and ID spaces */
|
||||
|
||||
#define REGS_A 0xfff58000
|
||||
#define PROM_A 0xfff58080
|
||||
#define REGS_B 0xfff58100
|
||||
#define PROM_B 0xfff58180
|
||||
#define REGS_C 0xfff58200
|
||||
#define PROM_C 0xfff58280
|
||||
#define REGS_D 0xfff58300
|
||||
#define PROM_D 0xfff58380
|
||||
#define REGS_AB 0xfff58400
|
||||
#define REGS_CD 0xfff58500
|
||||
|
||||
|
||||
/* IPIC chip */
|
||||
|
||||
ipic_t *ipic = (ipic_t *) IPIC_BASE;
|
||||
|
||||
|
||||
/* IP Recovery Timers */
|
||||
|
||||
LOCAL const uchar_t recoveryTime[] = {
|
||||
IPIC_GEN_RT_0,
|
||||
IPIC_GEN_RT_2,
|
||||
IPIC_GEN_RT_2,
|
||||
IPIC_GEN_RT_4,
|
||||
IPIC_GEN_RT_4,
|
||||
IPIC_GEN_RT_8,
|
||||
IPIC_GEN_RT_8,
|
||||
IPIC_GEN_RT_8,
|
||||
IPIC_GEN_RT_8
|
||||
};
|
||||
|
||||
|
||||
/* Carrier Base Address structure, only one instance can exist! */
|
||||
|
||||
LOCAL long mBase[IPAC_ADDR_SPACES][SLOTS] = {
|
||||
PROM_A, PROM_B, PROM_C, PROM_D,
|
||||
REGS_A, REGS_B, REGS_C, REGS_D,
|
||||
REGS_AB, NULL, REGS_CD, NULL,
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
initialise
|
||||
|
||||
Purpose:
|
||||
Initialises the MVME162 IPIC chip with settings given in cardParams
|
||||
|
||||
Description:
|
||||
|
||||
|
||||
Parameters:
|
||||
|
||||
|
||||
Examples:
|
||||
"A:m=0x80000000,1024 l=4;B:l=2,2;C:m=0x80100000,64"
|
||||
|
||||
Returns:
|
||||
0 = OK,
|
||||
S_IPAC_tooMany = Carrier already registered
|
||||
S_IPAC_badDriver = IPIC chip not found
|
||||
S_IPAC_badAddress = Parameter string error, or address not reachable
|
||||
|
||||
*/
|
||||
|
||||
LOCAL int initialise (
|
||||
char *cardParams,
|
||||
void **pprivate
|
||||
) {
|
||||
static int initialised = FALSE;
|
||||
ushort_t slot;
|
||||
int count, p1, p2, next;
|
||||
char dummy, cmd;
|
||||
|
||||
if (initialised) {
|
||||
return S_IPAC_tooMany;
|
||||
}
|
||||
|
||||
if (vxMemProbe((void *)&ipic->chipId, READ, 1, &dummy) ||
|
||||
ipic->chipId != IPIC_CHIP_ID) {
|
||||
return S_IPAC_badDriver;
|
||||
}
|
||||
|
||||
/* Initialise the IPIC chip */
|
||||
for (slot = 0; slot < SLOTS; slot++) {
|
||||
ipic->intCtrl[slot][0] = IPIC_INT_ICLR;
|
||||
ipic->intCtrl[slot][1] = IPIC_INT_ICLR;
|
||||
ipic->genCtrl[slot] = IPIC_GEN_WIDTH_16 | IPIC_GEN_RT_0;
|
||||
}
|
||||
|
||||
/* Parse the parameter string */
|
||||
slot = 0;
|
||||
while ((cmd = *cardParams++) != '\0') {
|
||||
switch (cmd) {
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
slot = cmd - 'A';
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
p1 = p2 = 0;
|
||||
count = sscanf(cardParams, "=%p,%d%n",
|
||||
(void **) &p1, &p2, &next);
|
||||
if (count != 2 ||
|
||||
p1 < (long) sysMemTop() ||
|
||||
p1 & 0xffff != 0 ||
|
||||
p2 < 64 || p2 > 16384 ||
|
||||
p1 + (p2*1024) > 0xfff00000) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
|
||||
ipic->memBase[slot] = p1 >> 16;
|
||||
ipic->memSize[slot] = (p2 / 64) - 1;
|
||||
ipic->genCtrl[slot] |= IPIC_GEN_MEN;
|
||||
mBase[ipac_addrMem][slot] = p1;
|
||||
cardParams += next;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
p1 = p2 = 0;
|
||||
count = sscanf(cardParams, "=%d%n,%d%n", &p1, &next, &p2, &next);
|
||||
if (count < 1 || count > 2 ||
|
||||
p1 < 0 || p1 > 7 ||
|
||||
p2 < 0 || p2 > 7) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
|
||||
ipic->intCtrl[slot][0] = (p1 & IPIC_INT_LEVEL) |
|
||||
(ipic->intCtrl[slot][0] & ~IPIC_INT_LEVEL);
|
||||
ipic->intCtrl[slot][1] = (p2 & IPIC_INT_LEVEL) |
|
||||
(ipic->intCtrl[slot][1] & ~IPIC_INT_LEVEL);
|
||||
cardParams += next;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
p1 = 0;
|
||||
count = sscanf(cardParams, "=%d%n", &p1, &next);
|
||||
if (count != 1 ||
|
||||
p1 < 0 || p1 > 8) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
|
||||
ipic->genCtrl[slot] = (ipic->genCtrl[slot] & ~IPIC_GEN_RT) |
|
||||
recoveryTime[p1];
|
||||
cardParams += next;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
p1 = 0;
|
||||
count = sscanf(cardParams, "=%d%n", &p1, &next);
|
||||
if (count != 1) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
|
||||
switch (p1) {
|
||||
case 8:
|
||||
ipic->genCtrl[slot] = IPIC_GEN_WIDTH_8 |
|
||||
(ipic->genCtrl[slot] & ~IPIC_GEN_WIDTH);
|
||||
break;
|
||||
case 16:
|
||||
ipic->genCtrl[slot] = IPIC_GEN_WIDTH_16 |
|
||||
(ipic->genCtrl[slot] & ~IPIC_GEN_WIDTH);
|
||||
break;
|
||||
case 32:
|
||||
if (slot & 1) {
|
||||
/* Illegal for odd-numbered slots */
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
ipic->genCtrl[slot] = IPIC_GEN_WIDTH_32 |
|
||||
(ipic->genCtrl[slot] & ~IPIC_GEN_WIDTH);
|
||||
ipic->genCtrl[slot+1] &= ~(IPIC_GEN_WIDTH |
|
||||
IPIC_GEN_MEN);
|
||||
break;
|
||||
default:
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initialised = TRUE;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
baseAddr
|
||||
|
||||
Purpose:
|
||||
Returns the base address for the requested slot & address space
|
||||
|
||||
Description:
|
||||
This routine only has to do a table lookup in the mBase array.
|
||||
Note that no parameter checking is required - the IPAC driver which
|
||||
calls this routine handles that.
|
||||
|
||||
Returns:
|
||||
The requested address, or NULL if the slot has no memory in the
|
||||
requested address space.
|
||||
|
||||
*/
|
||||
|
||||
LOCAL void *baseAddr (
|
||||
void *private,
|
||||
ushort_t slot,
|
||||
ipac_addr_t space
|
||||
) {
|
||||
return (void *) mBase[space][slot];
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
irqCmd
|
||||
|
||||
Purpose:
|
||||
Handles interrupter commands and status requests
|
||||
|
||||
Description:
|
||||
The IPIC chip allows a lot of control over the IP interrupters, thus
|
||||
all commands perform the requested action.
|
||||
|
||||
Returns:
|
||||
ipac_irqGetLevel returns the current interrupt level,
|
||||
ipac_irqPoll returns >0 if interrupt line active else 0,
|
||||
other calls return 0 = OK.
|
||||
|
||||
*/
|
||||
|
||||
LOCAL int irqCmd (
|
||||
void *private,
|
||||
ushort_t slot,
|
||||
ushort_t irqNumber,
|
||||
ipac_irqCmd_t cmd
|
||||
) {
|
||||
switch (cmd) {
|
||||
case ipac_irqLevel0:
|
||||
case ipac_irqLevel1:
|
||||
case ipac_irqLevel2:
|
||||
case ipac_irqLevel3:
|
||||
case ipac_irqLevel4:
|
||||
case ipac_irqLevel5:
|
||||
case ipac_irqLevel6:
|
||||
case ipac_irqLevel7:
|
||||
ipic->intCtrl[slot][irqNumber] = (cmd & IPIC_INT_LEVEL) |
|
||||
(ipic->intCtrl[slot][irqNumber] & ~IPIC_INT_LEVEL);
|
||||
return OK;
|
||||
|
||||
case ipac_irqGetLevel:
|
||||
return ipic->intCtrl[slot][irqNumber] & IPIC_INT_LEVEL;
|
||||
|
||||
case ipac_irqEnable:
|
||||
ipic->intCtrl[slot][irqNumber] |= IPIC_INT_IEN;
|
||||
return OK;
|
||||
|
||||
case ipac_irqDisable:
|
||||
ipic->intCtrl[slot][irqNumber] &= ~IPIC_INT_IEN;
|
||||
return OK;
|
||||
|
||||
case ipac_irqPoll:
|
||||
return ipic->intCtrl[slot][irqNumber] & IPIC_INT_INT;
|
||||
|
||||
case ipac_irqSetEdge:
|
||||
ipic->intCtrl[slot][irqNumber] |= IPIC_INT_EDGE;
|
||||
return OK;
|
||||
|
||||
case ipac_irqSetLevel:
|
||||
ipic->intCtrl[slot][irqNumber] &= ~IPIC_INT_EDGE;
|
||||
return OK;
|
||||
|
||||
case ipac_irqClear:
|
||||
ipic->intCtrl[slot][irqNumber] |= IPIC_INT_ICLR;
|
||||
return OK;
|
||||
|
||||
default:
|
||||
return S_IPAC_notImplemented;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/* IPAC Carrier Table */
|
||||
|
||||
ipac_carrier_t ipmv162 = {
|
||||
"Motorola MVME162",
|
||||
SLOTS,
|
||||
initialise,
|
||||
NULL,
|
||||
baseAddr,
|
||||
irqCmd
|
||||
};
|
||||
|
||||
@@ -1,520 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
drvIpac.c
|
||||
|
||||
Description:
|
||||
IPAC Driver, provides a standard interface between IPAC Module
|
||||
drivers and the IPAC Carrier drivers.
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
3 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef NO_EPICS
|
||||
# include <drvSup.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vxLib.h>
|
||||
#include "drvIpac.h"
|
||||
|
||||
|
||||
#define IPAC_MAX_CARRIERS 21
|
||||
|
||||
|
||||
/* Private carrier data structures */
|
||||
struct carrierInfo {
|
||||
ipac_carrier_t *driver;
|
||||
void *cPrivate;
|
||||
};
|
||||
|
||||
LOCAL struct {
|
||||
ushort_t number;
|
||||
struct carrierInfo *info[IPAC_MAX_CARRIERS];
|
||||
} carriers = {
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/* Null carrier stuff */
|
||||
|
||||
LOCAL ipac_carrier_t nullCarrier = {
|
||||
"Null carrier (place holder)",
|
||||
0, /* No slots */
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
LOCAL struct carrierInfo nullInfo = {
|
||||
&nullCarrier,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#ifndef NO_EPICS
|
||||
|
||||
/* EPICS Driver Support Entry Table */
|
||||
|
||||
struct drvet drvIpac = {
|
||||
3,
|
||||
(DRVSUPFUN) ipacReport,
|
||||
(DRVSUPFUN) ipacInitialise,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
ipacAddCarrier
|
||||
|
||||
Purpose:
|
||||
Used to register a carrier board & carrier driver with the IPAC driver.
|
||||
|
||||
Description:
|
||||
Usually called from the vxWorks (EPICS) startup script. Some types of
|
||||
carrier may need additional initilisation before or after registering,
|
||||
but the card parameter string should be sufficient for most carriers.
|
||||
Note that only the carrier initialise routine is called at this stage.
|
||||
The order in which carriers are registered with this routine specifies
|
||||
the carrier number which they will be allocated, starting from zero.
|
||||
|
||||
Checks that the carrier descriptor table looks sensible, then calls the
|
||||
initialise routine with the given card parameters, and saves the carrier
|
||||
private pointer and carrier table address. The card number allows the
|
||||
same descriptor to be used for all carriers of the same type.
|
||||
|
||||
It may be necessary to remove a carrier temporarily from a system in
|
||||
some circumstances without wanting to have to change the carrier number
|
||||
allocated to higher numbered carriers. To allow this, it is legal to
|
||||
call this routine with a NULL (zero) carrier table address, which
|
||||
switches in the null carrier table instead.
|
||||
|
||||
Returns:
|
||||
0 = OK,
|
||||
S_IPAC_tooMany = Carrier Info Table full,
|
||||
S_IPAC_badTable = Carrier Table invalid.
|
||||
|
||||
Example:
|
||||
ipacAddCarrier(&vipc310, "0x6000");
|
||||
|
||||
*/
|
||||
|
||||
int ipacAddCarrier (
|
||||
ipac_carrier_t *pcarrierTable,
|
||||
char *cardParams
|
||||
) {
|
||||
void *cPrivate;
|
||||
int status;
|
||||
|
||||
if (carriers.number >= IPAC_MAX_CARRIERS) {
|
||||
return S_IPAC_tooMany;
|
||||
}
|
||||
|
||||
if (pcarrierTable == NULL) {
|
||||
carriers.info[carriers.number] = &nullInfo;
|
||||
carriers.number++;
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (pcarrierTable->numberSlots == 0 ||
|
||||
pcarrierTable->initialise == NULL ||
|
||||
pcarrierTable->baseAddr == NULL ||
|
||||
pcarrierTable->irqCmd == NULL) {
|
||||
return S_IPAC_badTable;
|
||||
}
|
||||
|
||||
status = pcarrierTable->initialise(cardParams, &cPrivate);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
carriers.info[carriers.number] = malloc(sizeof (struct carrierInfo));
|
||||
carriers.info[carriers.number]->driver = pcarrierTable;
|
||||
carriers.info[carriers.number]->cPrivate = cPrivate;
|
||||
carriers.number++;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
ipmCheck
|
||||
|
||||
Function:
|
||||
Check on presence of an IPAC module at the given carrier & slot number.
|
||||
|
||||
Description:
|
||||
Does a quick check to make sure the carrier and slot numbers are legal,
|
||||
probes the IDprom space to ensure an IPAC is installed, and checks that
|
||||
the IDprom starts with the "IPAC" identifier.
|
||||
|
||||
Returns:
|
||||
0 = OK,
|
||||
S_IPAC_badAddress = Bad carrier or slot number,
|
||||
S_IPAC_noModule = No module installed,
|
||||
S_IPAC_noIpacId = "IPAC" identifier not found
|
||||
|
||||
*/
|
||||
|
||||
int ipmCheck (
|
||||
ushort_t carrier,
|
||||
ushort_t slot
|
||||
) {
|
||||
ipac_idProm_t *id;
|
||||
char dummy;
|
||||
|
||||
if (carrier >= carriers.number ||
|
||||
slot >= carriers.info[carrier]->driver->numberSlots) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
|
||||
id = (ipac_idProm_t *) ipmBaseAddr(carrier, slot, ipac_addrID);
|
||||
if (id == NULL) {
|
||||
return S_IPAC_badDriver;
|
||||
}
|
||||
|
||||
if (vxMemProbe((void *)&id->asciiI, READ, 1, &dummy)) {
|
||||
return S_IPAC_noModule;
|
||||
}
|
||||
|
||||
if (id->asciiI != 'I' ||
|
||||
id->asciiP != 'P' ||
|
||||
id->asciiA != 'A' ||
|
||||
id->asciiC != 'C') {
|
||||
return S_IPAC_noIpacId; /* Not an IPAC */
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
checkCRC
|
||||
|
||||
Function:
|
||||
Calculate the CRC of the IDprom at the given address.
|
||||
|
||||
Description:
|
||||
Generates an industry standard CRC of the ID Prom data as described
|
||||
in the GreenSpring Industry Pack specification. The CRC byte in the
|
||||
Prom (at address 0x17) is set to zero for the purpose of calculating
|
||||
the CRC.
|
||||
|
||||
Returns:
|
||||
The low 8 bits of the calculated CRC value.
|
||||
|
||||
*/
|
||||
|
||||
LOCAL int checkCRC (
|
||||
uchar_t *data,
|
||||
ushort_t length
|
||||
) {
|
||||
uint_t i, crc = 0xffff;
|
||||
uchar_t mask;
|
||||
|
||||
for (i = 1; i < 2*length; i += 2) {
|
||||
mask = 0x80;
|
||||
while (mask) {
|
||||
if ((data[i] & mask) && (i != 0x17)) {
|
||||
crc ^= 0x8000;
|
||||
}
|
||||
crc += crc;
|
||||
if (crc > 0xffff) {
|
||||
crc = (crc & 0xffff) ^ 0x1021;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (~crc) & 0xff;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
ipmValidate
|
||||
|
||||
Function:
|
||||
Validate a particular IPAC module type at the given carrier & slot number.
|
||||
|
||||
Description:
|
||||
Uses ipmCheck to ensure the carrier and slot numbers are legal, probe the
|
||||
IDprom and check that the IDprom looks like an IPAC module. Calculates
|
||||
the CRC for the ID Prom, and compares the manufacturer and model ID values
|
||||
in the Prom to the ones given.
|
||||
|
||||
Returns:
|
||||
0 = OK,
|
||||
S_IPAC_badAddress = Bad carrier or slot number,
|
||||
S_IPAC_noModule = No module installed,
|
||||
S_IPAC_noIpacId = "IPAC" identifier not found
|
||||
S_IPAC_badCRC = CRC Check failed,
|
||||
S_IPAC_badModule = Manufacturer or model IDs wrong
|
||||
|
||||
*/
|
||||
|
||||
int ipmValidate (
|
||||
ushort_t carrier,
|
||||
ushort_t slot,
|
||||
uchar_t manufacturerId,
|
||||
uchar_t modelId
|
||||
) {
|
||||
ipac_idProm_t *id;
|
||||
int status;
|
||||
|
||||
status = ipmCheck(carrier, slot);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
id = (ipac_idProm_t *) ipmBaseAddr(carrier, slot, ipac_addrID);
|
||||
if (checkCRC((uchar_t *) id, id->bytesUsed) != id->CRC) {
|
||||
return S_IPAC_badCRC;
|
||||
}
|
||||
|
||||
if (id->manufacturerId != manufacturerId ||
|
||||
id->modelId != modelId) {
|
||||
return S_IPAC_badModule;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
ipmReport
|
||||
|
||||
Function:
|
||||
returns printable string giving status of module at given carrier/slot.
|
||||
|
||||
Description:
|
||||
Generates a report string describing the given IPAC slot. If a module
|
||||
is installed, it includes the manufacturer and model ID numbers. If
|
||||
the report function is supported by the carrier driver this report
|
||||
string is appended.
|
||||
|
||||
Returns:
|
||||
Pointer to static, printable string.
|
||||
|
||||
Sample Output:
|
||||
"C0 S1 : 0xB1/0x01 - M0 L4,5"
|
||||
|
||||
*/
|
||||
|
||||
char *ipmReport (
|
||||
ushort_t carrier,
|
||||
ushort_t slot
|
||||
) {
|
||||
static char report[80];
|
||||
int status;
|
||||
|
||||
sprintf(report, "C%hd S%hd : ", carrier, slot);
|
||||
|
||||
status = ipmCheck(carrier, slot);
|
||||
if (status == S_IPAC_badAddress) {
|
||||
strcat(report, "No such carrier/slot");
|
||||
return report;
|
||||
}
|
||||
|
||||
if (status == S_IPAC_noModule) {
|
||||
strcat(report, "No Module");
|
||||
} else {
|
||||
ipac_idProm_t *id;
|
||||
char module[16];
|
||||
|
||||
id = (ipac_idProm_t *) ipmBaseAddr(carrier, slot, ipac_addrID);
|
||||
sprintf(module, "0x%02hX/0x%02hX", (short) id->manufacturerId,
|
||||
(short) id->modelId);
|
||||
strcat(report, module);
|
||||
}
|
||||
|
||||
if (carriers.info[carrier]->driver->report != NULL) {
|
||||
strcat(report, " - ");
|
||||
strcat(report, carriers.info[carrier]->driver->report(
|
||||
carriers.info[carrier]->cPrivate, slot));
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
ipmBaseAddr
|
||||
|
||||
Function:
|
||||
Returns a pointer to the selected IP address space
|
||||
|
||||
Description:
|
||||
Checks its input parameters, then calls the carrier driver. This will
|
||||
return a pointer to the location of the address space indicated by the
|
||||
space parameter. All IP modules must provide an ID prom to indicate
|
||||
the module type (space = ipac_addrID). Most modules need register I/O
|
||||
locations, which are in the I/O space (space = ipac_addrIO). Some
|
||||
types of module also provide memory (space = ipac_addrMem), but if
|
||||
this is not required the carrier may allow it to be disabled, in which
|
||||
case the driver should return a NULL for this address space. Some
|
||||
carriers provide a 32-bit wide I/O space for Dual-slot IP modules;
|
||||
carriers which do not should return NULL for this space.
|
||||
|
||||
Returns:
|
||||
Base CPU address of IP address space, or NULL pointer.
|
||||
|
||||
*/
|
||||
|
||||
void *ipmBaseAddr (
|
||||
ushort_t carrier,
|
||||
ushort_t slot,
|
||||
ipac_addr_t space
|
||||
) {
|
||||
if (carrier >= carriers.number ||
|
||||
slot >= carriers.info[carrier]->driver->numberSlots) {
|
||||
return NULL;
|
||||
}
|
||||
return carriers.info[carrier]->driver->baseAddr(
|
||||
carriers.info[carrier]->cPrivate, slot, space);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
ipmIrqCmd
|
||||
|
||||
Function:
|
||||
Send command to slot interrupt controller.
|
||||
|
||||
Description:
|
||||
Checks input parameters, then passes the interrupt command request to
|
||||
the carrier driver routine. The driver is only required to support
|
||||
the command ipac_irqEnable; for other commands it may return the status
|
||||
code S_IPAC_notImplemented and do nothing.
|
||||
|
||||
Returns:
|
||||
0 = OK,
|
||||
S_IPAC_badAddress = illegal carrier, slot or irqNumber,
|
||||
S_IPAC_notImplemented = Driver does not support that command,
|
||||
other, depending on command.
|
||||
|
||||
*/
|
||||
|
||||
int ipmIrqCmd (
|
||||
ushort_t carrier,
|
||||
ushort_t slot,
|
||||
ushort_t irqNumber,
|
||||
ipac_irqCmd_t cmd
|
||||
) {
|
||||
if (irqNumber > 1 ||
|
||||
carrier >= carriers.number ||
|
||||
slot >= carriers.info[carrier]->driver->numberSlots) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
|
||||
return carriers.info[carrier]->driver->irqCmd(
|
||||
carriers.info[carrier]->cPrivate, slot, irqNumber, cmd);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
ipacReport
|
||||
|
||||
Function:
|
||||
Report status of all known IPAC carriers
|
||||
|
||||
Description:
|
||||
Prints information on each known carrier board and slot according to the
|
||||
specified interest level. Level 0 lists carriers only, with the number
|
||||
of slots it supports. Level 1 gives each slot, manufacturer & model ID
|
||||
of the installed module (if any), and the carrier driver report for that
|
||||
slot. Level 2 adds the address of each memory space for the slot.
|
||||
|
||||
Returns:
|
||||
OK.
|
||||
|
||||
*/
|
||||
|
||||
int ipacReport (
|
||||
int interest
|
||||
) {
|
||||
ushort_t carrier, slot;
|
||||
|
||||
for (carrier=0; carrier < carriers.number; carrier++) {
|
||||
printf(" IP Carrier %2d: %s, %d slots\n", carrier,
|
||||
carriers.info[carrier]->driver->carrierType,
|
||||
carriers.info[carrier]->driver->numberSlots);
|
||||
|
||||
if (interest > 0) {
|
||||
long memBase, io32Base;
|
||||
|
||||
for (slot=0; slot < carriers.info[carrier]->driver->numberSlots;
|
||||
slot++) {
|
||||
printf(" %s\n", ipmReport(carrier, slot));
|
||||
|
||||
if (interest > 1) {
|
||||
printf(" ID = 0x%lx, I/O = 0x%lx",
|
||||
(long) ipmBaseAddr(carrier, slot, ipac_addrID),
|
||||
(long) ipmBaseAddr(carrier, slot, ipac_addrIO));
|
||||
io32Base = (long) ipmBaseAddr(carrier, slot, ipac_addrIO32);
|
||||
if (io32Base != NULL) {
|
||||
printf(", I/O32 = 0x%lx", io32Base);
|
||||
}
|
||||
memBase = (long) ipmBaseAddr(carrier, slot, ipac_addrMem);
|
||||
if (memBase != NULL) {
|
||||
printf(", Mem = 0x%lx", memBase);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
ipacInitialise
|
||||
|
||||
Function:
|
||||
Initialise the IPAC driver
|
||||
|
||||
Description:
|
||||
Null routine.
|
||||
|
||||
Returns:
|
||||
OK.
|
||||
|
||||
*/
|
||||
|
||||
int ipacInitialise (
|
||||
int after
|
||||
) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
drvIpac.h
|
||||
|
||||
Description:
|
||||
IPAC Driver header file, defines the software interfaces:
|
||||
1. Upwards to the IPAC Module driver
|
||||
2. Downwards to the IPAC Carrier driver
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
1 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef INCdrvIpacH
|
||||
#define INCdrvIpacH
|
||||
|
||||
#include <types.h>
|
||||
#include "ipModules.h"
|
||||
|
||||
#ifndef NO_EPICS
|
||||
#include <errMdef.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Error numbers */
|
||||
|
||||
#ifndef OK
|
||||
#define OK 0
|
||||
#endif
|
||||
|
||||
#ifndef M_ipac
|
||||
#define M_ipac (600 << 16)
|
||||
#endif
|
||||
|
||||
#define S_IPAC_badTable (M_ipac| 1) /*IPAC Carrier Table invalid*/
|
||||
#define S_IPAC_tooMany (M_ipac| 2) /*Too many IPAC carriers, table full*/
|
||||
#define S_IPAC_badAddress (M_ipac| 3) /*Bad IPAC carrier or slot number*/
|
||||
#define S_IPAC_badDriver (M_ipac| 4) /*Bad value from IPAC carrier driver*/
|
||||
#define S_IPAC_noModule (M_ipac| 5) /*No IP module installed*/
|
||||
#define S_IPAC_noIpacId (M_ipac| 6) /*IPAC identifier not found*/
|
||||
#define S_IPAC_badCRC (M_ipac| 7) /*IPAC CRC Check failed*/
|
||||
#define S_IPAC_badModule (M_ipac| 8) /*IPAC Manufacturer or model ID wrong*/
|
||||
#define S_IPAC_notImplemented (M_ipac| 9) /*IPAC Driver command not available*/
|
||||
|
||||
|
||||
/* Structure of the IPAC ID Prom, located in the pack ID space. */
|
||||
|
||||
typedef struct {
|
||||
uchar_t pad00;
|
||||
uchar_t asciiI;
|
||||
uchar_t pad02;
|
||||
uchar_t asciiP;
|
||||
uchar_t pad04;
|
||||
uchar_t asciiA;
|
||||
uchar_t pad06;
|
||||
uchar_t asciiC;
|
||||
uchar_t pad08;
|
||||
uchar_t manufacturerId;
|
||||
uchar_t pad0a;
|
||||
uchar_t modelId;
|
||||
uchar_t pad0c;
|
||||
uchar_t revision;
|
||||
uchar_t pad0e;
|
||||
uchar_t reserved;
|
||||
uchar_t pad10;
|
||||
uchar_t driverIdLow;
|
||||
uchar_t pad12;
|
||||
uchar_t driverIdHigh;
|
||||
uchar_t pad14;
|
||||
uchar_t bytesUsed;
|
||||
uchar_t pad16;
|
||||
uchar_t CRC;
|
||||
uchar_t pad18;
|
||||
uchar_t packSpecific[0x3f-0x18];
|
||||
} ipac_idProm_t;
|
||||
|
||||
|
||||
/* These are the types of address space implemented in the IP
|
||||
specification. Some IP modules only use the ID and IO spaces. */
|
||||
|
||||
#define IPAC_ADDR_SPACES 4
|
||||
|
||||
typedef enum {
|
||||
ipac_addrID = 0, /* ID Prom space */
|
||||
ipac_addrIO = 1, /* Registers etc */
|
||||
ipac_addrIO32 = 2, /* Registers for 32-bit dual-slot */
|
||||
ipac_addrMem = 3 /* Memory space */
|
||||
} ipac_addr_t;
|
||||
|
||||
|
||||
/* The following are the possible commands to the carrier driver to
|
||||
handle interrupts from the IP modules. Some carriers will only be
|
||||
able to implement a subset of these commands. Note that irqEnable
|
||||
should call the vxWorks sysBusEnable routine if this is needed to
|
||||
pass the carrier interrupts through to the CPU. */
|
||||
|
||||
typedef enum {
|
||||
ipac_irqLevel0 = 0, /* Disables interrupts */
|
||||
ipac_irqLevel1 = 1, /* Lowest priority */
|
||||
ipac_irqLevel2 = 2,
|
||||
ipac_irqLevel3 = 3,
|
||||
ipac_irqLevel4 = 4,
|
||||
ipac_irqLevel5 = 5,
|
||||
ipac_irqLevel6 = 6, /* Highest priority */
|
||||
ipac_irqLevel7 = 7, /* Non-maskable, don't use */
|
||||
ipac_irqGetLevel, /* Returns level set (or hard-coded) */
|
||||
ipac_irqEnable, /* Required to use interrupts */
|
||||
ipac_irqDisable, /* Not necessarily supported */
|
||||
ipac_irqPoll, /* Returns interrupt state */
|
||||
ipac_irqSetEdge, /* Sets edge-triggered interrupts */
|
||||
ipac_irqSetLevel, /* Sets level-triggered (default) */
|
||||
ipac_irqClear /* Only needed if using edge-triggered */
|
||||
} ipac_irqCmd_t;
|
||||
|
||||
|
||||
/* This is a table which each IPAC carrier driver provides to allow
|
||||
it to be queried by the IPAC driver. One table is required for
|
||||
each type of carrier. The cPrivate pointer is returned by the
|
||||
carrier driver initialise routine, and passed to all of the other
|
||||
routines as a means of identification of the carrier board. */
|
||||
|
||||
typedef struct {
|
||||
char *carrierType;
|
||||
/* String containing carrier board type */
|
||||
ushort_t numberSlots;
|
||||
/* Number of IPAC devices this carrier can hold */
|
||||
int (*initialise)(char *cardParams, void **cPrivate);
|
||||
/* Initialise carrier and return *cPrivate */
|
||||
char *(*report)(void *cPrivate, ushort_t slot);
|
||||
/* Return string with giving status of this slot */
|
||||
void *(*baseAddr)(void *cPrivate, ushort_t slot, ipac_addr_t space);
|
||||
/* Return base addresses for this slot */
|
||||
int (*irqCmd)(void *cPrivate, ushort_t slot,
|
||||
ushort_t irqNumber, ipac_irqCmd_t cmd);
|
||||
/* interrupt manipulation */
|
||||
} ipac_carrier_t;
|
||||
|
||||
|
||||
/* Functions for startup and interactive use */
|
||||
|
||||
extern int ipacAddCarrier(ipac_carrier_t *pcarrier, char *cardParams);
|
||||
extern int ipacReport(int interest);
|
||||
extern int ipacInitialise(int after);
|
||||
|
||||
|
||||
/* Functions for use in IPAC module drivers */
|
||||
|
||||
extern int ipmCheck(ushort_t carrier, ushort_t slot);
|
||||
extern int ipmValidate(ushort_t carrier, ushort_t slot,
|
||||
uchar_t manufacturerId, uchar_t modelId);
|
||||
extern char *ipmReport(ushort_t carrier, ushort_t slot);
|
||||
extern void *ipmBaseAddr(ushort_t carrier, ushort_t slot, ipac_addr_t space);
|
||||
extern int ipmIrqCmd(ushort_t carrier, ushort_t slot,
|
||||
ushort_t irqNumber, ipac_irqCmd_t cmd);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INCipacH */
|
||||
|
||||
@@ -1,486 +0,0 @@
|
||||
/* 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 "dbDefs.h"
|
||||
#include "errlog.h"
|
||||
#include <module_types.h>
|
||||
#include <task_params.h>
|
||||
#include <fast_lock.h>
|
||||
#include <drvEpvxi.h>
|
||||
#include <drvSup.h>
|
||||
#include <dbScan.h>
|
||||
#include <devLib.h>
|
||||
|
||||
#include <drvKscV215.h>
|
||||
|
||||
|
||||
#define MAXTRIES 100
|
||||
|
||||
#define KSCV215_PCONFIG(LA, PC) \
|
||||
epvxiFetchPConfig((LA), KscV215DriverId, PC)
|
||||
|
||||
#define ChannelEnable(PCSR) ((PCSR)->dir.w.dd.reg.ddx08)
|
||||
#define ModuleStatus(PCSR) ((PCSR)->dir.r.status)
|
||||
|
||||
#define ALL_SWITCHES_OPEN 0
|
||||
|
||||
struct KscV215_config{
|
||||
FAST_LOCK lock; /* mutual exclusion */
|
||||
IOSCANPVT ioscanpvt;
|
||||
};
|
||||
|
||||
#define KSCV215_INT_LEVEL 1
|
||||
#define KscV215Handshake (0x0040)
|
||||
#define KscV215csrInit (0x9000)
|
||||
|
||||
LOCAL int KscV215DriverId;
|
||||
|
||||
|
||||
struct KscV215_A24{
|
||||
volatile uint16_t diag;
|
||||
volatile uint16_t isr;
|
||||
volatile uint16_t pad1[7];
|
||||
volatile uint16_t channels[64]; /* odd access causes a bus error ? */
|
||||
volatile uint16_t controlMemoryAddr;
|
||||
volatile uint16_t pad2;
|
||||
volatile uint16_t controlMemoryDataWrite;
|
||||
volatile uint16_t pad3;
|
||||
volatile uint16_t controlMemoryDataRead;
|
||||
volatile uint16_t pad4;
|
||||
volatile uint16_t lastChannel;
|
||||
volatile uint16_t pad5;
|
||||
volatile uint16_t singleScan;
|
||||
volatile uint16_t pad6;
|
||||
volatile uint16_t stopScan;
|
||||
volatile uint16_t pad7;
|
||||
volatile uint16_t clearControlMemoryAddr;
|
||||
volatile uint16_t pad8;
|
||||
volatile uint16_t enableContinuousScanning;
|
||||
volatile uint16_t pad9;
|
||||
volatile uint16_t disableContinuousScanning;
|
||||
volatile uint16_t pad10;
|
||||
volatile uint16_t enableDoneInt;
|
||||
volatile uint16_t pad11;
|
||||
volatile uint16_t disbaleDoneInt;
|
||||
volatile uint16_t pad12;
|
||||
volatile uint16_t clearDoneInt;
|
||||
volatile uint16_t pad13;
|
||||
volatile uint16_t testDoneInt;
|
||||
volatile uint16_t pad14;
|
||||
};
|
||||
|
||||
#ifdef INTERRUPTS
|
||||
LOCAL void KscV215_int_service(unsigned la);
|
||||
#endif
|
||||
LOCAL void KscV215_init_card(unsigned la, void *pArg);
|
||||
|
||||
LOCAL void KscV215_stat(
|
||||
unsigned la,
|
||||
int level
|
||||
);
|
||||
|
||||
LOCAL kscV215Stat KscV215WriteSync(
|
||||
struct KscV215_A24 *pA24,
|
||||
volatile uint16_t *preg,
|
||||
uint16_t val
|
||||
);
|
||||
|
||||
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvKscV215={
|
||||
2,
|
||||
NULL, /* VXI report takes care of this */
|
||||
KscV215Init};
|
||||
|
||||
/*
|
||||
* KscV215_init
|
||||
*
|
||||
* initialize all KscV215 cards
|
||||
*
|
||||
*/
|
||||
kscV215Stat KscV215Init(void)
|
||||
{
|
||||
kscV215Stat r0;
|
||||
|
||||
/*
|
||||
* do nothing on crates without VXI
|
||||
*/
|
||||
if(!epvxiResourceMangerOK){
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
KscV215DriverId = epvxiUniqueDriverID();
|
||||
|
||||
{
|
||||
epvxiDeviceSearchPattern dsp;
|
||||
|
||||
dsp.flags = VXI_DSP_make | VXI_DSP_model;
|
||||
dsp.make = VXI_MAKE_KSC;
|
||||
dsp.model = VXI_MODEL_KSCV215;
|
||||
r0 = epvxiLookupLA(&dsp, KscV215_init_card, (void *)NULL);
|
||||
if(r0){
|
||||
return r0;
|
||||
}
|
||||
}
|
||||
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* KSCV215_INIT_CARD
|
||||
*
|
||||
* initialize single at5vxi card
|
||||
*
|
||||
*/
|
||||
LOCAL void KscV215_init_card(unsigned la, void *pArg)
|
||||
{
|
||||
kscV215Stat status;
|
||||
int i;
|
||||
struct KscV215_config *pc;
|
||||
struct KscV215_A24 *pA24;
|
||||
struct vxi_csr *pcsr;
|
||||
int model;
|
||||
|
||||
status = epvxiOpen(
|
||||
la,
|
||||
KscV215DriverId,
|
||||
(unsigned long) sizeof(*pc),
|
||||
KscV215_stat);
|
||||
if(status){
|
||||
errPrintf(
|
||||
status,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"AT5VXI: device open failed %d\n",
|
||||
la);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
status = KSCV215_PCONFIG(la, pc);
|
||||
if(status){
|
||||
errMessage(status,NULL);
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
return;
|
||||
}
|
||||
|
||||
pA24 = epvxiA24Base(la);
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pcsr->dir.w.control = KscV215csrInit;
|
||||
|
||||
status = KscV215WriteSync(pA24, &pA24->controlMemoryAddr, 0U);
|
||||
if(status){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
errMessage(status, "KscV215 init failed\n");
|
||||
return;
|
||||
}
|
||||
for(i=0; i<(NELEMENTS(pA24->channels)/2); i++){
|
||||
status = KscV215WriteSync(
|
||||
pA24,
|
||||
&pA24->controlMemoryDataWrite,
|
||||
0U);
|
||||
if(status){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
errMessage(status, "KscV215 init failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn on continuous scan mode
|
||||
*/
|
||||
status = KscV215WriteSync(
|
||||
pA24,
|
||||
&pA24->enableContinuousScanning,
|
||||
0U);
|
||||
if(status){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
errMessage(status, "KscV215 init failed- device left open\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FASTLOCKINIT(&pc->lock);
|
||||
scanIoInit(&pc->ioscanpvt);
|
||||
|
||||
#ifdef INTERRUPTS
|
||||
status = intConnect(
|
||||
(unsigned char) INUM_TO_IVEC(la),
|
||||
KscV215_int_service,
|
||||
(void *) la);
|
||||
if(status == ERROR){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
errMessage(S_dev_vecInstlFail,
|
||||
"KscV215 init failed- device left open");
|
||||
return;
|
||||
}
|
||||
sysIntEnable(KSCV215_INT_LEVEL);
|
||||
#endif
|
||||
|
||||
status = epvxiRegisterMakeName(VXI_MAKE_KSC, "Kinetic Systems");
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
}
|
||||
|
||||
model = VXIMODEL(pcsr);
|
||||
status = epvxiRegisterModelName(
|
||||
VXIMAKE(pcsr),
|
||||
model,
|
||||
"V215 16 bit 32 channel ADC\n");
|
||||
if(status){
|
||||
errMessage(status, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* KscV215WriteSync
|
||||
*
|
||||
*
|
||||
*/
|
||||
LOCAL kscV215Stat KscV215WriteSync(
|
||||
struct KscV215_A24 *pA24,
|
||||
volatile uint16_t *preg,
|
||||
uint16_t val
|
||||
)
|
||||
{
|
||||
kscV215Stat status;
|
||||
int i;
|
||||
|
||||
for(i=0; i<MAXTRIES; i++){
|
||||
*preg = val;
|
||||
if(pA24->diag & KscV215Handshake){
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
taskDelay(1);
|
||||
}
|
||||
|
||||
status = S_dev_deviceTMO;
|
||||
errMessage(status, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* KscV215_int_service()
|
||||
*
|
||||
*
|
||||
* This device interrupts once the
|
||||
* switches have settled
|
||||
*
|
||||
*/
|
||||
#ifdef INTERRUPTS
|
||||
LOCAL void KscV215_int_service(unsigned la)
|
||||
{
|
||||
kscV215Stat s;
|
||||
struct KscV215_config *pc;
|
||||
|
||||
s = KSCV215_PCONFIG(la, pc);
|
||||
if(s){
|
||||
logMsg( "Int to ukn device %s line=%d\n",
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* tell them that the switches have settled
|
||||
*/
|
||||
scanIoRequest(pc->ioscanpvt);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* KSCV215_STAT
|
||||
*
|
||||
* initialize single at5vxi card
|
||||
*
|
||||
*/
|
||||
LOCAL void KscV215_stat(
|
||||
unsigned la,
|
||||
int level
|
||||
)
|
||||
{
|
||||
kscV215Stat s;
|
||||
struct KscV215_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
struct KscV215_A24 *pA24;
|
||||
int i;
|
||||
|
||||
s = KSCV215_PCONFIG(la, pc);
|
||||
if(s){
|
||||
errMessage(s, NULL);
|
||||
return;
|
||||
}
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pA24 = (struct KscV215_A24 *) epvxiA24Base(la);
|
||||
|
||||
if(level>0){
|
||||
printf ("KSC V215 32 CHANNEL 16 BIT ADC.\n");
|
||||
}
|
||||
if (level > 1) {
|
||||
for (i = 0; i < 32; i++)
|
||||
printf ("Channel %d Value %d\n",
|
||||
i,
|
||||
pA24->channels[i*2]);
|
||||
}
|
||||
if (level > 2) {
|
||||
printf ("\nGain Setting (Control Memory Data Register\n");
|
||||
pA24->controlMemoryAddr = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
switch (pA24->controlMemoryAddr) {
|
||||
case 0:
|
||||
printf ("+- 10V");
|
||||
break;
|
||||
case 1:
|
||||
printf ("+- 5V");
|
||||
break;
|
||||
case 3:
|
||||
printf ("+- 2.5V");
|
||||
break;
|
||||
case 5:
|
||||
printf ("+- 1.25V");
|
||||
break;
|
||||
case 6:
|
||||
printf ("+- 625mV");
|
||||
break;
|
||||
default:
|
||||
printf ("Unknown Gain Setting.");
|
||||
}
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* AT5VXI_AI_DRIVER
|
||||
*
|
||||
* analog input driver
|
||||
*/
|
||||
kscV215Stat KscV215_ai_driver(
|
||||
unsigned la,
|
||||
unsigned chan,
|
||||
unsigned short *prval
|
||||
)
|
||||
{
|
||||
struct KscV215_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
struct KscV215_A24 *pA24;
|
||||
long tmp;
|
||||
int i;
|
||||
kscV215Stat s;
|
||||
|
||||
s = KSCV215_PCONFIG(la, pc);
|
||||
if(s){
|
||||
return s;
|
||||
}
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pA24 = epvxiA24Base(la);
|
||||
|
||||
if(chan >= NELEMENTS(pA24->channels)/2){
|
||||
return S_dev_badSignalNumber;
|
||||
}
|
||||
|
||||
for(i=0; i<MAXTRIES; i++){
|
||||
tmp = pA24->channels[chan<<1];
|
||||
if(pA24->diag & KscV215Handshake){
|
||||
tmp = tmp + 0xffff;
|
||||
tmp = tmp >> 4;
|
||||
tmp &= 0xfff;
|
||||
*prval = tmp;
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
taskDelay(1);
|
||||
}
|
||||
|
||||
s = S_dev_deviceTMO;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* KscV215_getioscanpvt()
|
||||
*/
|
||||
kscV215Stat KscV215_getioscanpvt(
|
||||
unsigned la,
|
||||
IOSCANPVT *scanpvt
|
||||
)
|
||||
{
|
||||
kscV215Stat s;
|
||||
struct KscV215_config *pc;
|
||||
|
||||
s = KSCV215_PCONFIG(la, pc);
|
||||
if(s){
|
||||
errMessage(s, NULL);
|
||||
return s;
|
||||
}
|
||||
*scanpvt = pc->ioscanpvt;
|
||||
return VXI_SUCCESS;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/* 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
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,628 +0,0 @@
|
||||
|
||||
/* 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 "errlog.h"
|
||||
#include <drvSup.h>
|
||||
#include <module_types.h>
|
||||
#include <fast_lock.h>
|
||||
#include <devLib.h>
|
||||
#include <drvStc.h>
|
||||
|
||||
#include <drvMz8310.h>
|
||||
|
||||
#define MZ8310CHIPSIZE 0x20
|
||||
#define MZ8310SIZE 0x00000100
|
||||
#define MZ8310BASE(CARD) (shortaddr+tm_addrs[MZ8310]+(CARD)*MZ8310SIZE)
|
||||
|
||||
#define MZ8310DATA 0
|
||||
#define MZ8310CMD 3
|
||||
#define MZ8310CHANONCHIP 5
|
||||
#define MZ8310CHIPCOUNT 2
|
||||
#define MZ8310CHANCNT (MZ8310CHANONCHIP*MZ8310CHIPCOUNT)
|
||||
|
||||
/*
|
||||
NOTE: The mizar draftsman has labeled the chip at the
|
||||
highest address as one and the chip at the lowest address
|
||||
2 so I am reversing the chip number below.
|
||||
*/
|
||||
#define CHIP_REVERSE(CHIP) (MZ8310CHIPCOUNT-1-(CHIP))
|
||||
#define CHIP_ADDR(CARD,CHIP) (MZ8310BASE(CARD)+\
|
||||
(CHIP_REVERSE(CHIP)*MZ8310CHIPSIZE))
|
||||
|
||||
#define MZ8310_CMD_ADDR(CARD,CHIP)\
|
||||
((volatile uint8_t *) CHIP_ADDR(CARD,CHIP) + MZ8310CMD)
|
||||
#define MZ8310_DATA_ADDR(CARD,CHIP)\
|
||||
((volatile uint16_t *) CHIP_ADDR(CARD,CHIP) + MZ8310DATA)
|
||||
#if 0
|
||||
#define MZ8310VECBASE(CARD,CHIP)\
|
||||
((volatile uint8_t *) CHIP_ADDR(CARD,CHIP) + 0x41)
|
||||
#endif
|
||||
|
||||
#define MZ8310VECSIZE (0x20)
|
||||
#define MZ8310INTCNT 4
|
||||
#define MZ8310FIRSTINTCHAN 0
|
||||
#define MZ8310INTVEC(CARD,CHAN)\
|
||||
(MZ8310_INT_VEC_BASE + (CARD*MZ8310INTCNT) + mz8310_strap[CHAN].vec_num)
|
||||
|
||||
#define MZ8310_INTERUPTABLE(CHAN) (mz8310_strap[CHAN].vec_addr)
|
||||
|
||||
# define INT_TICKS 4.0e06 /* speed of F1 in Hz */
|
||||
# define EXT_TICKS 5.0e06 /* GTA std speed of SRC1 in Hz */
|
||||
|
||||
|
||||
struct mz8310_int_conf{
|
||||
void (*user_service)(void *user_param);
|
||||
void *user_param;
|
||||
unsigned int cnt;
|
||||
};
|
||||
|
||||
struct mz8310_conf{
|
||||
char init;
|
||||
FAST_LOCK lock;
|
||||
struct mz8310_int_conf icf[MZ8310CHANCNT];
|
||||
};
|
||||
|
||||
struct mz8310_strap_info{
|
||||
unsigned char irq; /* the level at which the chan gen ints */
|
||||
unsigned char vec_num; /* really a vec offset-see MZ8310INTVEC */
|
||||
unsigned char vec_addr;/* offset from card base address */
|
||||
};
|
||||
|
||||
static volatile char *shortaddr;
|
||||
|
||||
LOCAL struct mz8310_conf *mzconf;
|
||||
LOCAL unsigned int mz8310_card_count;
|
||||
|
||||
/*
|
||||
only 4 unique interrupts per card but any channel can potentially
|
||||
generate an interrupt depending on board strapping.
|
||||
|
||||
NOTE: existence of vec addr tells the driver that that channel is
|
||||
strapped for interrupts since the card can't be polled for this info.
|
||||
|
||||
In the MIZAR 8310 Documentation:
|
||||
|
||||
Designation vector reg offset
|
||||
IRQA 0x41
|
||||
IRQB 0x61
|
||||
IRQC 0x81
|
||||
IRQD 0xa1
|
||||
*/
|
||||
|
||||
LOCAL struct mz8310_strap_info mz8310_strap[MZ8310CHANCNT] =
|
||||
{
|
||||
{ NULL, NULL, NULL }, /* channel 0 */
|
||||
{ NULL, NULL, NULL }, /* channel 1 */
|
||||
{ NULL, NULL, NULL }, /* channel 2 */
|
||||
{ NULL, NULL, NULL }, /* channel 3 */
|
||||
{ NULL, NULL, NULL }, /* channel 4 */
|
||||
{ NULL, NULL, NULL }, /* channel 5 */
|
||||
{ 1, 0, 0x41 }, /* channel 6 */
|
||||
{ 3, 1, 0x61 }, /* channel 7 */
|
||||
{ 5, 2, 0x81 }, /* channel 8 */
|
||||
{ 6, 3, 0xa1 } /* channel 9 */
|
||||
};
|
||||
|
||||
/* forward reference. */
|
||||
LOCAL int mz8310_reset(void);
|
||||
LOCAL mz8310Stat mz8310_io_report_card(unsigned card, unsigned level);
|
||||
LOCAL mz8310Stat mz8310_init_card(unsigned card);
|
||||
LOCAL mz8310Stat mz8310_setup_int(unsigned card, unsigned channel);
|
||||
LOCAL mz8310Stat mz8310_io_report(unsigned level);
|
||||
LOCAL mz8310Stat mz8310_init(void);
|
||||
LOCAL mz8310Stat mz8310_read_test(unsigned card, unsigned channel);
|
||||
LOCAL void mz8310_int_service(struct mz8310_int_conf *icf);
|
||||
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvMz8310={
|
||||
2,
|
||||
mz8310_io_report,
|
||||
mz8310_init};
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_io_report()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_io_report(unsigned level)
|
||||
{
|
||||
unsigned card;
|
||||
|
||||
for(card=0; card<tm_num_cards[MZ8310]; card++)
|
||||
mz8310_io_report_card(card, level);
|
||||
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_io_report_card()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_io_report_card(unsigned card, unsigned level)
|
||||
{
|
||||
unsigned channel;
|
||||
unsigned chip;
|
||||
mz8310Stat status;
|
||||
|
||||
for(chip=0; chip<MZ8310CHIPCOUNT; chip++){
|
||||
status = stc_io_report(
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip));
|
||||
if(status){
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
printf("TM: MZ8310:\tcard %d\n", card);
|
||||
|
||||
|
||||
if (mzconf && card<mz8310_card_count && level){
|
||||
for(channel=0;channel<MZ8310CHANCNT;channel++){
|
||||
status = mz8310_read_test(card, channel);
|
||||
if(status){
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_init()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_init(void)
|
||||
{
|
||||
unsigned card;
|
||||
mz8310Stat status;
|
||||
struct mz8310_conf *temp_mzconf;
|
||||
unsigned card_count = tm_num_cards[MZ8310];
|
||||
|
||||
status = sysBusToLocalAdrs(
|
||||
VME_AM_SUP_SHORT_IO,
|
||||
0,
|
||||
(char **)&shortaddr);
|
||||
if (status != OK){
|
||||
status = S_dev_badA16;
|
||||
errMessage(status, "A16 Address map error mz8310 driver");
|
||||
return status;
|
||||
}
|
||||
|
||||
temp_mzconf = (struct mz8310_conf *) malloc(sizeof(*mzconf)*card_count);
|
||||
if(!temp_mzconf)
|
||||
return S_dev_noMemory;
|
||||
|
||||
for(card=0; card<card_count; card++){
|
||||
FASTLOCKINIT(&temp_mzconf[card].lock);
|
||||
}
|
||||
|
||||
if(mzconf){
|
||||
for(card=0; card<card_count; card++){
|
||||
if(FASTLOCKFREE(&mzconf[card].lock)<0){
|
||||
status = S_dev_internal;
|
||||
errMessage(status, "error freeing sem");
|
||||
}
|
||||
}
|
||||
free(mzconf);
|
||||
}
|
||||
|
||||
mzconf = temp_mzconf;
|
||||
|
||||
for(card=0; card<card_count; card++){
|
||||
status = mz8310_init_card(card);
|
||||
if(status){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mz8310_card_count = card;
|
||||
|
||||
rebootHookAdd(mz8310_reset);
|
||||
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* mz8310_init_card()
|
||||
*
|
||||
* Locking for this provided by mz8310_init()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_init_card(unsigned card)
|
||||
{
|
||||
unsigned chip;
|
||||
unsigned chan;
|
||||
mz8310Stat error;
|
||||
/*
|
||||
* binary division
|
||||
* data ptr seq enbl
|
||||
* 16 bit bus
|
||||
* FOUT on
|
||||
* FOUT divide by one
|
||||
* FOUT source (F1)
|
||||
* Time of day disabled
|
||||
*/
|
||||
unsigned short master_mode = 0x2100;
|
||||
|
||||
for(chip=0; chip< MZ8310CHIPCOUNT; chip++){
|
||||
error = stc_init(
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip),
|
||||
master_mode);
|
||||
if(error){
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
for(chan=0; chan<MZ8310CHANCNT; chan++)
|
||||
mz8310_setup_int(card,chan);
|
||||
|
||||
mzconf[card].init = TRUE;
|
||||
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_setup_int()
|
||||
*
|
||||
* (locked by calling routines)
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_setup_int(unsigned card, unsigned channel)
|
||||
{
|
||||
unsigned char vector;
|
||||
mz8310Stat status;
|
||||
|
||||
mzconf[card].icf[channel].user_service = NULL;
|
||||
mzconf[card].icf[channel].user_param = NULL;
|
||||
mzconf[card].icf[channel].cnt = 0;
|
||||
|
||||
/*
|
||||
* Is this channel strapped for interrupts
|
||||
*/
|
||||
if(!MZ8310_INTERUPTABLE(channel))
|
||||
return MZ8310_SUCCESS;
|
||||
|
||||
vector = MZ8310INTVEC(card,channel);
|
||||
status = vxMemProbe(
|
||||
(char *)MZ8310BASE(card) + mz8310_strap[channel].vec_addr,
|
||||
WRITE,
|
||||
sizeof(vector),
|
||||
(char *)&vector);
|
||||
if(status != OK){
|
||||
status = S_dev_noDevice;
|
||||
errMessage(status, NULL);
|
||||
return S_dev_noDevice;
|
||||
}
|
||||
|
||||
status = intConnect( INUM_TO_IVEC(vector),
|
||||
mz8310_int_service,
|
||||
(int)&mzconf[card].icf[channel]);
|
||||
if(status != OK)
|
||||
return S_dev_vecInstlFail;
|
||||
|
||||
sysIntEnable(mz8310_strap[channel].irq);
|
||||
|
||||
return MZ8310_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_one_shot_read()
|
||||
*/
|
||||
mz8310Stat mz8310_one_shot_read(
|
||||
unsigned *preset, /* TRUE or COMPLEMENT logic */
|
||||
double *edge0_delay, /* sec */
|
||||
double *edge1_delay, /* sec */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned *int_source /* (FALSE)External/(TRUE)Internal src */
|
||||
)
|
||||
{
|
||||
int chip = channel/MZ8310CHANONCHIP;
|
||||
double ticks;
|
||||
unsigned short iedge0;
|
||||
unsigned short iedge1;
|
||||
mz8310Stat status;
|
||||
|
||||
if(channel >= MZ8310CHANONCHIP * MZ8310CHIPCOUNT)
|
||||
return S_dev_badSignalNumber;
|
||||
|
||||
if(card>=mz8310_card_count)
|
||||
return S_dev_badA16;
|
||||
|
||||
if(!mzconf)
|
||||
return S_dev_noDevice;
|
||||
|
||||
FASTLOCK(&mzconf[card].lock);
|
||||
|
||||
status =
|
||||
stc_one_shot_read(
|
||||
preset,
|
||||
&iedge0,
|
||||
&iedge1,
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip),
|
||||
channel % MZ8310CHANONCHIP,
|
||||
int_source);
|
||||
if(status==STC_SUCCESS){
|
||||
ticks = *int_source ? INT_TICKS : EXT_TICKS;
|
||||
*edge0_delay = iedge0 / ticks;
|
||||
*edge1_delay = iedge1 / ticks;
|
||||
}
|
||||
|
||||
FASTUNLOCK(&mzconf[card].lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_read_test()
|
||||
*/
|
||||
LOCAL mz8310Stat mz8310_read_test(unsigned card, unsigned channel)
|
||||
{
|
||||
unsigned preset;
|
||||
double edge0_delay;
|
||||
double edge1_delay;
|
||||
unsigned int_source;
|
||||
mz8310Stat status;
|
||||
static char *pclktype[] = {"external-clk", "internal-clk"};
|
||||
static char *ppresettype[] = {"preset-FALSE", "preset-TRUE "};
|
||||
|
||||
status =
|
||||
mz8310_one_shot_read(
|
||||
&preset,
|
||||
&edge0_delay,
|
||||
&edge1_delay,
|
||||
card,
|
||||
channel,
|
||||
&int_source);
|
||||
if(status==MZ8310_SUCCESS){
|
||||
printf( "\tChannel %u %s delay=%f width=%f %s\n",
|
||||
channel,
|
||||
ppresettype[preset&1],
|
||||
edge0_delay,
|
||||
edge1_delay,
|
||||
pclktype[int_source&1]);
|
||||
if(mzconf[card].icf[channel].cnt)
|
||||
printf("\tChannel %u Interrupt count=%u\n",
|
||||
channel,
|
||||
mzconf[card].icf[channel].cnt);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_one_shot()
|
||||
*/
|
||||
mz8310Stat mz8310_one_shot(
|
||||
unsigned preset, /* TRUE or COMPLEMENT logic */
|
||||
double edge0_delay, /* sec */
|
||||
double edge1_delay, /* sec */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned int_source, /* (FALSE)External/ (TRUE)Internal source */
|
||||
void (*event_rtn)(void *pParam), /* subroutine to run on events */
|
||||
void *event_rtn_param /* parameter to pass to above routine */
|
||||
)
|
||||
{
|
||||
int chip = channel/MZ8310CHANONCHIP;
|
||||
double ticks = int_source?INT_TICKS:EXT_TICKS;
|
||||
mz8310Stat status;
|
||||
|
||||
if(channel >= MZ8310CHANONCHIP * MZ8310CHIPCOUNT)
|
||||
return S_dev_badSignalNumber;
|
||||
|
||||
if(card>=mz8310_card_count)
|
||||
return S_dev_badA16;
|
||||
|
||||
if(!mzconf)
|
||||
return S_dev_noDevice;
|
||||
|
||||
/* dont overflow unsigned short in STC */
|
||||
if(edge0_delay >= 0xffff/ticks)
|
||||
return S_dev_highValue;
|
||||
if(edge1_delay >= 0xffff/ticks)
|
||||
return S_dev_highValue;
|
||||
if(edge0_delay < 0.0)
|
||||
return S_dev_lowValue;
|
||||
if(edge1_delay < 0.0)
|
||||
return S_dev_lowValue;
|
||||
|
||||
FASTLOCK(&mzconf[card].lock);
|
||||
|
||||
/* Enable calling of user routine */
|
||||
if(MZ8310_INTERUPTABLE(channel)){
|
||||
mzconf[card].icf[channel].user_service = event_rtn;
|
||||
mzconf[card].icf[channel].user_param = event_rtn_param;
|
||||
}
|
||||
|
||||
status =
|
||||
stc_one_shot(
|
||||
preset,
|
||||
(unsigned short) (edge0_delay * ticks),
|
||||
(unsigned short) (edge1_delay * ticks),
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip),
|
||||
channel % MZ8310CHANONCHIP,
|
||||
int_source);
|
||||
|
||||
FASTUNLOCK(&mzconf[card].lock);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_int_service()
|
||||
*/
|
||||
LOCAL void mz8310_int_service(struct mz8310_int_conf *icf)
|
||||
{
|
||||
icf->cnt++;
|
||||
|
||||
if(icf->user_service)
|
||||
(*icf->user_service)(icf->user_param);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following are provided for mz8310 access from the shell
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_cmd()
|
||||
*/
|
||||
int mz8310_cmd(
|
||||
unsigned value,
|
||||
unsigned card,
|
||||
unsigned chip
|
||||
)
|
||||
{
|
||||
volatile unsigned char *cmd = MZ8310_CMD_ADDR(card,chip);
|
||||
|
||||
*cmd = value;
|
||||
|
||||
return *cmd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_rdata()
|
||||
*/
|
||||
int mz8310_rdata(int card, int chip)
|
||||
{
|
||||
volatile unsigned short *data = MZ8310_DATA_ADDR(card,chip);
|
||||
|
||||
return *data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_wdata()
|
||||
*/
|
||||
int mz8310_wdata(
|
||||
unsigned value,
|
||||
unsigned card,
|
||||
unsigned chip
|
||||
)
|
||||
{
|
||||
volatile uint16_t *data = MZ8310_DATA_ADDR(card,chip);
|
||||
|
||||
*data = value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* mz8310_reset
|
||||
*/
|
||||
LOCAL int mz8310_reset(void)
|
||||
{
|
||||
short card,channel,chip;
|
||||
|
||||
for (card = 0; card < mz8310_card_count; card++){
|
||||
FASTLOCK(&mzconf[card].lock);
|
||||
for ( channel = 0; channel < tm_num_channels[MZ8310]; channel++){
|
||||
if (mzconf[card].icf[channel].cnt){
|
||||
chip = channel/MZ8310CHANONCHIP;
|
||||
|
||||
stc_one_shot(
|
||||
0,
|
||||
10,
|
||||
0,
|
||||
MZ8310_CMD_ADDR(card,chip),
|
||||
MZ8310_DATA_ADDR(card,chip),
|
||||
channel % MZ8310CHANONCHIP,
|
||||
0);
|
||||
}
|
||||
}
|
||||
FASTUNLOCK(&mzconf[card].lock);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/* drvMz8310.c */
|
||||
/* base/src/drv $Id$ */
|
||||
/*
|
||||
* Routines specific to the MZ8310. Low level routines for the AMD STC in
|
||||
* stc_driver.c
|
||||
* Author: Jeff Hill
|
||||
* Date: Feb 1989
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification History
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#define MZ8310_SUCCESS 0
|
||||
|
||||
typedef long mz8310Stat;
|
||||
|
||||
mz8310Stat mz8310_one_shot_read(
|
||||
unsigned *preset, /* TRUE or COMPLEMENT logic */
|
||||
double *edge0_delay, /* sec */
|
||||
double *edge1_delay, /* sec */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned *int_source /* (FALSE)External/(TRUE)Internal src */
|
||||
);
|
||||
|
||||
mz8310Stat mz8310_one_shot(
|
||||
unsigned preset, /* TRUE or COMPLEMENT logic */
|
||||
double edge0_delay, /* sec */
|
||||
double edge1_delay, /* set */
|
||||
unsigned card, /* 0 through ... */
|
||||
unsigned channel, /* 0 through channels on a card */
|
||||
unsigned int_source, /* (FALSE)External/ (TRUE)Internal source */
|
||||
void (*event_rtn)(void *pParam), /* subroutine to run on events */
|
||||
void *event_rtn_param /* parameter to pass to above routine */
|
||||
);
|
||||
|
||||
int mz8310_cmd(
|
||||
unsigned value,
|
||||
unsigned card,
|
||||
unsigned chip
|
||||
);
|
||||
|
||||
int mz8310_rdata(int card, int chip);
|
||||
|
||||
int mz8310_wdata(
|
||||
unsigned value,
|
||||
unsigned card,
|
||||
unsigned chip
|
||||
);
|
||||
|
||||
|
||||
@@ -1,316 +0,0 @@
|
||||
/* 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 <taskLib.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "errlog.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;
|
||||
}
|
||||
|
||||
/*
|
||||
* stcWriteData()
|
||||
*/
|
||||
void stcWriteData(volatile uint16_t *pdata, uint16_t data)
|
||||
{
|
||||
*pdata = data;
|
||||
}
|
||||
|
||||
/*
|
||||
* stcReadData()
|
||||
*/
|
||||
uint16_t stcReadData(volatile uint16_t *pdata)
|
||||
{
|
||||
uint16_t data;
|
||||
data = *pdata;
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* stcWriteCmd()
|
||||
*/
|
||||
void stcWriteCmd(volatile uint8_t *pcmd, uint8_t cmd)
|
||||
{
|
||||
*pcmd = cmd;
|
||||
}
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/* 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 stcWriteCmd(pcmd,0xffU);
|
||||
#define STC_BUS16 stcWriteCmd(pcmd,0xefU);
|
||||
#define STC_BUS16 stcWriteCmd(pcmd,0xefU);
|
||||
#define STC_SET_MASTER_MODE(D) {stcWriteCmd(pcmd,0x17U); \
|
||||
stcWriteData(pdata,(D));}
|
||||
#define STC_MASTER_MODE (stcWriteCmd(pcmd,0x17U), stcReadData(pdata))
|
||||
|
||||
#define STC_CTR_INIT(MODE,LOAD,HOLD)\
|
||||
{stcWriteCmd(pcmd,CHIPCHAN+1); stcWriteData(pdata,(MODE)); \
|
||||
stcWriteData(pdata,(LOAD)); stcWriteData(pdata,(HOLD));}
|
||||
|
||||
#define STC_CTR_READ(MODE,LOAD,HOLD)\
|
||||
{stcWriteCmd(pcmd,CHIPCHAN+1); (MODE) = stcReadData(pdata); \
|
||||
(LOAD) = stcReadData(pdata); (HOLD) = stcReadData(pdata);}
|
||||
|
||||
#define STC_SET_TC(D) stcWriteCmd(pcmd, \
|
||||
0xe0U | ((D)?8:0)|(CHIPCHAN+1U) )
|
||||
|
||||
#define STC_LOAD stcWriteCmd(pcmd, 0x40U | 1<<(CHIPCHAN))
|
||||
#define STC_STEP stcWriteCmd(pcmd, 0xf0U | (CHIPCHAN+1U))
|
||||
#define STC_ARM stcWriteCmd(pcmd, 0x20U | 1<<CHIPCHAN)
|
||||
#define STC_DISARM stcWriteCmd(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
|
||||
);
|
||||
|
||||
void stcWriteData(volatile uint16_t *pdata, uint16_t data);
|
||||
uint16_t stcReadData(volatile uint16_t *pdata);
|
||||
void stcWriteCmd(volatile uint8_t *pcmd, uint8_t cmd);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,48 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
drvTip810.h
|
||||
|
||||
Description:
|
||||
Header file for TEWS TIP810 CAN Bus driver.
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
20 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef INCdrvTip810H
|
||||
#define INCdrvTip810H
|
||||
|
||||
#include <types.h>
|
||||
#include "canBus.h"
|
||||
|
||||
|
||||
/* Error Numbers */
|
||||
|
||||
#ifndef M_t810
|
||||
#define M_t810 (810<<16)
|
||||
#endif
|
||||
|
||||
#define S_t810_duplicateDevice (M_t810| 1) /*duplicate t810 device definition*/
|
||||
#define S_t810_badBusRate (M_t810| 2) /*CANbus bit rate not supported*/
|
||||
#define S_t810_badDevice (M_t810| 3) /*device pointer is not for t810*/
|
||||
#define S_t810_transmitterBusy (M_t810| 4) /*transmit buffer unexpectedly busy*/
|
||||
|
||||
|
||||
extern int t810Report(int page);
|
||||
extern int t810Create(char *busName, ushort_t card, ushort_t slot,
|
||||
uint_t busRate);
|
||||
extern int t810Shutdown(int starttype);
|
||||
extern int t810Initialise(void);
|
||||
|
||||
#endif /* INCdrvTip810H */
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
drvVipc310.c
|
||||
|
||||
Description:
|
||||
IPAC Carrier Driver for the GreenSpring VIPC310 Dual IndustryPack
|
||||
Carrier VME board, provides the interface between IPAC driver and the
|
||||
hardware. This carrier is 3U high, and thus cannot support 32-bit
|
||||
accesses to dual-slot IP modules.
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
5 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <vme.h>
|
||||
#include <sysLib.h>
|
||||
#include "drvIpac.h"
|
||||
|
||||
|
||||
/* Characteristics of the card */
|
||||
|
||||
#define SLOTS 2
|
||||
#define IO_SPACES 2 /* Address spaces in A16 */
|
||||
#define IPAC_IRQS 2 /* Interrupts per module */
|
||||
|
||||
|
||||
/* Offsets from base address in VME A16 */
|
||||
|
||||
#define REGS_A 0x0000
|
||||
#define PROM_A 0x0080
|
||||
#define REGS_B 0x0100
|
||||
#define PROM_B 0x0180
|
||||
|
||||
|
||||
/* VME Interrupt levels */
|
||||
|
||||
#define IRQ_A0 4
|
||||
#define IRQ_A1 5
|
||||
#define IRQ_B0 2
|
||||
#define IRQ_B1 1
|
||||
|
||||
|
||||
/* Carrier Private structure type, one instance per board */
|
||||
|
||||
typedef void* private_t[IPAC_ADDR_SPACES][SLOTS];
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
initialise
|
||||
|
||||
Purpose:
|
||||
Creates new private table for VIPC310 at addresses given by cardParams
|
||||
|
||||
Description:
|
||||
Checks the parameter string for the address of the card I/O space and
|
||||
optional size of the memory space for the modules. If both the I/O and
|
||||
memory base addresses can be reached from the CPU, a private table is
|
||||
created for this board. The private table is a 2-D array of pointers
|
||||
to the base addresses of the various accessible parts of the IP module.
|
||||
|
||||
Parameters:
|
||||
The parameter string should comprise a hex number (the 0x or 0X at the
|
||||
start is optional) optionally followed by a comma and a decimal integer.
|
||||
The first number is the I/O base address of the card in the VME A16
|
||||
address space (the factory default is 0x6000). If present the second
|
||||
number gives the memory space in Kbytes allocated to each IP module.
|
||||
The memory base address of the VIPC310 card is set using the same jumpers
|
||||
as the I/O base address and is always 256 times the I/O base address,
|
||||
but in the VME A24 address space. The factory default fot the memory
|
||||
base address is thus 0x600000. If the memory size parameter is omitted
|
||||
or set to zero then neither IP module provides any memory space. Legal
|
||||
memory size values are 0, 64, 128, 256, 512, 1024 or 2048. The memory
|
||||
size interacts with the memory base address such that it is possible to
|
||||
set the existance of memory in either slot independently with suitable
|
||||
adjustment of the base address.
|
||||
|
||||
Examples:
|
||||
"0x6000"
|
||||
This indicates that the carrier has its I/O base set to 0x6000, and
|
||||
neither slot uses any memory space.
|
||||
"1000,512"
|
||||
Here the I/O base is set to 0x1000, and there is 512 Kbytes of
|
||||
memory on each module, with the IP module A memory at 0x100000
|
||||
and module B at 0x180000.
|
||||
"0xfe00, 128"
|
||||
The I/O base is at 0xfe00, and hence the carrier memory base is
|
||||
0xfe0000. However because the memory size is set to give each module
|
||||
128 Kbytes of memory space, module A cannot be selected (128 K =
|
||||
0x020000, so the module is decoded at 0xfc0000 but can't be accessed
|
||||
because this is below the memory base).
|
||||
|
||||
Returns:
|
||||
0 = OK,
|
||||
S_IPAC_badAddress = Parameter string error, or address not reachable
|
||||
|
||||
*/
|
||||
|
||||
LOCAL int initialise (
|
||||
char *cardParams,
|
||||
void **pprivate
|
||||
) {
|
||||
int params, status1 = OK, status2 = OK, mSize = 0;
|
||||
long ioBase, mOrig, mBase;
|
||||
ushort_t space, slot;
|
||||
private_t *private;
|
||||
static const int offset[IO_SPACES][SLOTS] = {
|
||||
PROM_A, PROM_B,
|
||||
REGS_A, REGS_B
|
||||
};
|
||||
|
||||
if (cardParams == NULL ||
|
||||
strlen(cardParams) == 0) {
|
||||
ioBase = 0x6000;
|
||||
} else {
|
||||
params = sscanf(cardParams, "%p,%i", (void **) &ioBase, &mSize);
|
||||
if (params < 1 || params > 2 ||
|
||||
ioBase > 0xfe00 || ioBase & 0x01ff ||
|
||||
mSize < 0 || mSize > 2048 || mSize & 63) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
}
|
||||
|
||||
mBase = ioBase << 8; /* Fixed by VIPC310 card */
|
||||
|
||||
status1 = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,
|
||||
(char *) ioBase, (char **) &ioBase);
|
||||
if (mSize > 0) {
|
||||
status2 = sysBusToLocalAdrs(VME_AM_STD_SUP_DATA,
|
||||
(char *) mBase, (char **) &mBase);
|
||||
}
|
||||
if (status1 || status2) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
|
||||
mSize = mSize << 10; /* Convert size from K to Bytes */
|
||||
mOrig = mBase & ~(mSize * SLOTS - 1);
|
||||
|
||||
private = malloc(sizeof (private_t));
|
||||
for (space = 0; space < IO_SPACES; space++) {
|
||||
for (slot = 0; slot < SLOTS; slot++) {
|
||||
(*private)[space][slot] = (void *) (ioBase + offset[space][slot]);
|
||||
}
|
||||
}
|
||||
|
||||
(*private)[ipac_addrIO32][0] = NULL;
|
||||
(*private)[ipac_addrIO32][1] = NULL;
|
||||
|
||||
if (mOrig == mBase) {
|
||||
(*private)[ipac_addrMem][0] = (void *) mBase;
|
||||
(*private)[ipac_addrMem][1] = (void *) (mBase + mSize);
|
||||
} else {
|
||||
(*private)[ipac_addrMem][0] = NULL;
|
||||
(*private)[ipac_addrMem][1] = (void *) mBase;
|
||||
}
|
||||
|
||||
*pprivate = private;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
baseAddr
|
||||
|
||||
Purpose:
|
||||
Returns the base address for the requested slot & address space
|
||||
|
||||
Description:
|
||||
Because we did all that hard work in the initialise routine, this
|
||||
routine only has to do a table lookup in the private array.
|
||||
Note that no parameter checking is required - the IPAC driver which
|
||||
calls this routine handles that.
|
||||
|
||||
Returns:
|
||||
The requested address, or NULL if the module has no memory.
|
||||
|
||||
*/
|
||||
|
||||
LOCAL void *baseAddr (
|
||||
void *private,
|
||||
ushort_t slot,
|
||||
ipac_addr_t space
|
||||
) {
|
||||
return (*(private_t *) private)[space][slot];
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
irqCmd
|
||||
|
||||
Purpose:
|
||||
Handles interrupter commands and status requests
|
||||
|
||||
Description:
|
||||
The GreenSpring board is limited to fixed interrupt levels, and has
|
||||
no control over interrupts. The only commands thus supported are
|
||||
a request of the interrupt level associated with a particular slot
|
||||
and interrupt number, or to enable interrupts by making sure the
|
||||
VMEbus interrupter is listening on the necessary level.
|
||||
|
||||
Returns:
|
||||
ipac_irqGetLevel returns the interrupt level (1, 2, 4 or 5),
|
||||
ipac_irqEnable returns 0 = OK,
|
||||
other calls return S_IPAC_notImplemented.
|
||||
|
||||
*/
|
||||
|
||||
LOCAL int irqCmd (
|
||||
void *private,
|
||||
ushort_t slot,
|
||||
ushort_t irqNumber,
|
||||
ipac_irqCmd_t cmd
|
||||
) {
|
||||
static const int irqLevel[SLOTS][IPAC_IRQS] = {
|
||||
IRQ_A0, IRQ_A1,
|
||||
IRQ_B0, IRQ_B1
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case ipac_irqGetLevel:
|
||||
return irqLevel[slot][irqNumber];
|
||||
|
||||
case ipac_irqEnable:
|
||||
sysIntEnable(irqLevel[slot][irqNumber]);
|
||||
return OK;
|
||||
|
||||
default:
|
||||
return S_IPAC_notImplemented;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/* IPAC Carrier Table */
|
||||
|
||||
ipac_carrier_t vipc310 = {
|
||||
"GreenSpring VIPC310",
|
||||
SLOTS,
|
||||
initialise,
|
||||
NULL,
|
||||
baseAddr,
|
||||
irqCmd
|
||||
};
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
drvVipc610.c
|
||||
|
||||
Description:
|
||||
IPAC Carrier Driver for the GreenSpring VIPC610-01 Quad IndustryPack
|
||||
Carrier VME board, provides the interface between IPAC driver and the
|
||||
hardware. This carrier is 6U high, but cannot support 32-bit accesses
|
||||
to dual-slot IP modules. Note the -01 option fixes the IRQ levels to
|
||||
be equivalent to two VIPC310 carriers.
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
19 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <vme.h>
|
||||
#include <sysLib.h>
|
||||
#include "drvIpac.h"
|
||||
|
||||
|
||||
/* Characteristics of the card */
|
||||
|
||||
#define SLOTS 4
|
||||
#define IO_SPACES 2 /* Address spaces in A16 */
|
||||
#define IPAC_IRQS 2 /* Interrupts per module */
|
||||
|
||||
|
||||
/* Offsets from base address in VME A16 */
|
||||
|
||||
#define REGS_A 0x0000
|
||||
#define PROM_A 0x0080
|
||||
#define REGS_B 0x0100
|
||||
#define PROM_B 0x0180
|
||||
#define REGS_C 0x0200
|
||||
#define PROM_C 0x0280
|
||||
#define REGS_D 0x0300
|
||||
#define PROM_D 0x0380
|
||||
|
||||
|
||||
/* VME Interrupt levels for -01 option */
|
||||
|
||||
#define IRQ_A0 4
|
||||
#define IRQ_A1 5
|
||||
#define IRQ_B0 2
|
||||
#define IRQ_B1 1
|
||||
#define IRQ_C0 4
|
||||
#define IRQ_C1 5
|
||||
#define IRQ_D0 2
|
||||
#define IRQ_D1 1
|
||||
|
||||
|
||||
/* Carrier Private structure type, one instance per board */
|
||||
|
||||
typedef void* private_t[IPAC_ADDR_SPACES][SLOTS];
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
initialise
|
||||
|
||||
Purpose:
|
||||
Creates new private table for VIPC610 at addresses given by cardParams
|
||||
|
||||
Description:
|
||||
Checks the parameter string for the address of the card I/O space and
|
||||
optional size of the memory space for the modules. If both the I/O and
|
||||
memory base addresses can be reached from the CPU, a private table is
|
||||
created for this board. The private table is a 2-D array of pointers
|
||||
to the base addresses of the various accessible parts of the IP module.
|
||||
|
||||
Parameters:
|
||||
The parameter string should comprise a hex number (the 0x or 0X at the
|
||||
start is optional) optionally followed by a comma and a decimal integer.
|
||||
The first number is the I/O base address of the card in the VME A16
|
||||
address space (the factory default is 0x6000). If present the second
|
||||
number gives the memory space in Kbytes allocated to each IP module.
|
||||
The memory base address of the VIPC610 card is set using the same jumpers
|
||||
as the I/O base address and is always 256 times the I/O base address,
|
||||
but in the VME A24 address space. The factory default for the memory
|
||||
base address is thus 0x600000. If the memory size parameter is omitted
|
||||
or set to zero then none of the IP modules on the carrier provide any
|
||||
memory space. Legal memory size values are 0, 64?, 128, 256, 512, 1024
|
||||
or 2048. The memory size interacts with the memory base address such
|
||||
that it is possible to exclude memory from the lower slots while still
|
||||
providing access to memory in the later slots by adjusting the base
|
||||
address suitably.
|
||||
|
||||
Examples:
|
||||
"0x6000"
|
||||
This indicates that the carrier board has its I/O base set to
|
||||
0x6000, and none of the slots provide memory space.
|
||||
"1000,128"
|
||||
Here the I/O base is set to 0x1000, and there is 128Kbytes of
|
||||
memory on each module, with the IP module A memory at 0x100000,
|
||||
module B at 0x120000, module C at 0x140000 and D at 0x160000.
|
||||
"7000,1024"
|
||||
The I/O base is at 0x7000, and hence the carrier memory base is
|
||||
0x700000. However because the memory size is set to 1024 Kbytes,
|
||||
modules A, B and C cannot be selected (1024 K = 0x100000, so they
|
||||
are decoded at 0x400000, 0x500000 and 0x600000 but can't be accessed
|
||||
because these are below the base address).
|
||||
|
||||
Returns:
|
||||
0 = OK,
|
||||
S_IPAC_badAddress = Parameter string error, or address not reachable
|
||||
|
||||
*/
|
||||
|
||||
LOCAL int initialise (
|
||||
char *cardParams,
|
||||
void **pprivate
|
||||
) {
|
||||
int params, status1 = OK, status2 = OK, mSize = 0;
|
||||
ulong_t ioBase, mOrig, mBase, addr;
|
||||
ushort_t space, slot;
|
||||
private_t *private;
|
||||
static const int offset[IO_SPACES][SLOTS] = {
|
||||
PROM_A, PROM_B, PROM_C, PROM_D,
|
||||
REGS_A, REGS_B, REGS_C, REGS_D
|
||||
};
|
||||
|
||||
if (cardParams == NULL ||
|
||||
strlen(cardParams) == 0) {
|
||||
ioBase = 0x6000;
|
||||
} else {
|
||||
params = sscanf(cardParams, "%p,%i", (void **) &ioBase, &mSize);
|
||||
if (params < 1 || params > 2 ||
|
||||
ioBase > 0xfc00 || ioBase & 0x01ff ||
|
||||
mSize < 0 || mSize > 2048 || mSize & 63) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
}
|
||||
|
||||
mBase = ioBase << 8; /* Fixed by the VIPC610 card */
|
||||
ioBase = ioBase & 0xfc00; /* Clear A09 */
|
||||
|
||||
status1 = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,
|
||||
(char *) ioBase, (char **) &ioBase);
|
||||
if (mSize > 0) {
|
||||
status2 = sysBusToLocalAdrs(VME_AM_STD_SUP_DATA,
|
||||
(char *) mBase, (char **) &mBase);
|
||||
}
|
||||
if (status1 || status2) {
|
||||
return S_IPAC_badAddress;
|
||||
}
|
||||
|
||||
mSize = mSize << 10; /* Convert size from K to Bytes */
|
||||
mOrig = mBase & ~(mSize * SLOTS - 1);
|
||||
|
||||
private = malloc(sizeof (private_t));
|
||||
for (space = 0; space < IO_SPACES; space++) {
|
||||
for (slot = 0; slot < SLOTS; slot++) {
|
||||
(*private)[space][slot] = (void *) (ioBase + offset[space][slot]);
|
||||
}
|
||||
}
|
||||
|
||||
for (slot = 0; slot < SLOTS; slot++) {
|
||||
(*private)[ipac_addrIO32][slot] = NULL;
|
||||
addr = mOrig + (mSize * slot);
|
||||
if (addr < mBase) {
|
||||
(*private)[ipac_addrMem][slot] = NULL;
|
||||
} else {
|
||||
(*private)[ipac_addrMem][slot] = (void *) addr;
|
||||
}
|
||||
}
|
||||
|
||||
*pprivate = private;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
baseAddr
|
||||
|
||||
Purpose:
|
||||
Returns the base address for the requested slot & address space
|
||||
|
||||
Description:
|
||||
Because we did all that hard work in the initialise routine, this
|
||||
routine only has to do a table lookup in the private array.
|
||||
Note that no parameter checking is required - the IPAC driver which
|
||||
calls this routine handles that.
|
||||
|
||||
Returns:
|
||||
The requested address, or NULL if the module has no memory.
|
||||
|
||||
*/
|
||||
|
||||
LOCAL void *baseAddr (
|
||||
void *private,
|
||||
ushort_t slot,
|
||||
ipac_addr_t space
|
||||
) {
|
||||
return (*(private_t *) private)[space][slot];
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Routine:
|
||||
irqCmd
|
||||
|
||||
Purpose:
|
||||
Handles interrupter commands and status requests
|
||||
|
||||
Description:
|
||||
The GreenSpring board is limited to fixed interrupt levels, and has
|
||||
no control over interrupts. The only commands thus supported are
|
||||
a request of the interrupt level associated with a particular slot
|
||||
and interrupt number, or to enable interrupts by making sure the
|
||||
VMEbus interrupter is listening on the necessary level.
|
||||
|
||||
Returns:
|
||||
ipac_irqGetLevel returns the interrupt level (1, 2, 4 or 5),
|
||||
ipac_irqEnable returns 0 = OK,
|
||||
other calls return S_IPAC_notImplemented.
|
||||
|
||||
*/
|
||||
|
||||
LOCAL int irqCmd (
|
||||
void *private,
|
||||
ushort_t slot,
|
||||
ushort_t irqNumber,
|
||||
ipac_irqCmd_t cmd
|
||||
) {
|
||||
static const int irqLevel[SLOTS][IPAC_IRQS] = {
|
||||
IRQ_A0, IRQ_A1,
|
||||
IRQ_B0, IRQ_B1,
|
||||
IRQ_C0, IRQ_C1,
|
||||
IRQ_D0, IRQ_D1
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case ipac_irqGetLevel:
|
||||
return irqLevel[slot][irqNumber];
|
||||
|
||||
case ipac_irqEnable:
|
||||
sysIntEnable(irqLevel[slot][irqNumber]);
|
||||
return OK;
|
||||
|
||||
default:
|
||||
return S_IPAC_notImplemented;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/* IPAC Carrier Table */
|
||||
|
||||
ipac_carrier_t vipc610 = {
|
||||
"GreenSpring VIPC610-01",
|
||||
SLOTS,
|
||||
initialise,
|
||||
NULL,
|
||||
baseAddr,
|
||||
irqCmd
|
||||
};
|
||||
|
||||
@@ -1,690 +0,0 @@
|
||||
/* drvVmi2534.c */
|
||||
/* share/src/drv @(#)drvVmic2534.c 1.1 003/22/94 */
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) /babar/CVSROOT/epics/base/src/drv/old/drvVmi2534.c,v 1.1 1996/01/09 19:54:35 lewis Exp(LBL)";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* routines used to test and interface with V.M.I.C. VMIVME-2534
|
||||
* digital i/o module
|
||||
*
|
||||
* Author: Bill Brown
|
||||
* Date: 03/22/94
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1994, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (DE-AC03-76SF00) at Lawrence Berkeley Laboratory.
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* Control System Group
|
||||
* Advanced Light Source
|
||||
* Lawrence Berkeley Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* NOTES:
|
||||
* This code is/was cloned from "drvXy240.c" of EPICS R3.11
|
||||
*
|
||||
* Data direction is dynamically assigned at ioInit() time.
|
||||
* The definition of the first bit(s) in a given byte will
|
||||
* determine the data direction of all bits within that byte.
|
||||
*
|
||||
* Modification Log:
|
||||
*
|
||||
*
|
||||
@(#) drvVmi2534.c,v
|
||||
@(#) Revision 1.1 1996/01/09 19:54:35 lewis
|
||||
@(#) Add PAL record. Remove APS eg/er records.
|
||||
@(#) Add 4 STAR drivers, LBL 2534, and preliminaries for LBL/SLAC 9210/9325 drivers.
|
||||
@(#)
|
||||
* Revision 1.1.1.1 1995/07/25 21:49:57 lewis
|
||||
* Baseline import R3.12 w/LBL drivers and mods.
|
||||
*
|
||||
* Revision 1.5 1994/09/28 09:05:51 wbrown
|
||||
* at beginning of init function, ctrl reg is set to match
|
||||
* SYS_RESET* condition.
|
||||
*
|
||||
* Revision 1.4 94/09/27 09:44:31 wbrown
|
||||
* changed order of "writes to '2534 hardware during initialization
|
||||
* to prevent undesired output transistions when calculating
|
||||
* "output correction factor."
|
||||
*
|
||||
* Revision 1.3 94/08/19 15:16:14 wbrown
|
||||
* added debug #ifdef, printf statements
|
||||
* fixed initialization of record definition structure
|
||||
*
|
||||
* Revision 1.2 94/07/20 09:25:26 wbrown
|
||||
* modified to dynamically assign data direction at
|
||||
* record init time.
|
||||
*
|
||||
* Revision 1.1 94/05/27 09:57:51 wbrown
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <taskLib.h>
|
||||
#include <types.h>
|
||||
#include <vme.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "errlog.h"
|
||||
#include "errlog.h"
|
||||
#include "module_types.h"
|
||||
#include "task_params.h"
|
||||
#include "drvSup.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbScan.h"
|
||||
#include "taskwd.h"
|
||||
|
||||
#define VMIC_2534_ADDR0 (bi_addrs[VMIC_2534_BI])
|
||||
#define VMIC_2534_MAX_CARDS (bi_num_cards[VMIC_2534_BI])
|
||||
#define VMIC_2534_MAX_CHANS (bi_num_channels[VMIC_2534_BI])
|
||||
|
||||
/* control-status register
|
||||
bit definiitions */
|
||||
|
||||
#define BYTE_0_OUT_ENA 1<<0
|
||||
#define BYTE_1_OUT_ENA 1<<1
|
||||
#define BYTE_2_OUT_ENA 1<<2
|
||||
#define BYTE_3_OUT_ENA 1<<3
|
||||
|
||||
#define FAIL_LED_OFF 1<<5
|
||||
#define TM1_ENABLE 1<<7
|
||||
#define TM2_ENABLE 1<<6
|
||||
|
||||
/* Refer to VMIVME-2534 manual for hardware options */
|
||||
/* These boards are available in two configurations; */
|
||||
/* "POSITIVE-TRUE Option" - writing a "1" to the output register */
|
||||
/* "TURNS ON the output driver, ie pulls the output LOW */
|
||||
/* "NEGATIVE-TRUE Option" - writing a "1" to the output register */
|
||||
/* "TURNS OFF" the output driver, allowing the load to pull */
|
||||
/* the output HIGH. */
|
||||
|
||||
/* The initialization routine recognizes which type of board is */
|
||||
/* installed and generates a mask which is used by the device- */
|
||||
/* driver to cause BOTH board types to appear to have the */
|
||||
/* POSITIVE-TRUE Option installed. */
|
||||
|
||||
#define FAIL_FLAG 1<<5
|
||||
/* Test Mode */
|
||||
#define TM2 1<<6 /* TM2 - "1" = disable test buffers */
|
||||
#define TM1 1<<7 /* TM1 - "1" = enable output drivers */
|
||||
|
||||
#define masks( K ) ((1<<K))
|
||||
|
||||
|
||||
/* VMIVME-2534 memory structure */
|
||||
|
||||
/* Data direction is dynamically assigned at ioInit() time. */
|
||||
/* The definition of the first bit(s) in a given byte will */
|
||||
/* determine the data direction of all bits within that byte. */
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u_long pioData;
|
||||
u_char brdIdReg;
|
||||
u_char ctlStatReg;
|
||||
u_char endPad[2];
|
||||
} VMIC_2534 ;
|
||||
|
||||
|
||||
/* VMIVME-2534 control structure record */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
VMIC_2534 *vmicDevice; /* pointer to the hardware */
|
||||
short deviceNr; /* device number */
|
||||
u_long savedInputs; /* previous input value */
|
||||
u_long outputCorrector; /* polarity correction factor */
|
||||
u_long inputMask; /* and-mask for input bytes */
|
||||
u_long outputMask; /* and-mask for output bytes */
|
||||
IOSCANPVT ioscanpvt;
|
||||
} VMIC_2534_REC ;
|
||||
|
||||
|
||||
VMIC_2534_REC *vmic2534Rec; /* points to control structures */
|
||||
|
||||
static long report( );
|
||||
static long init( );
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvVmi2534 =
|
||||
{
|
||||
2,
|
||||
report,
|
||||
init
|
||||
} ;
|
||||
|
||||
static
|
||||
long report( int level)
|
||||
{
|
||||
vmic2534_io_report( level );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
void vmic2534BiReport( int card );
|
||||
void vmic2534BoReport( int card );
|
||||
|
||||
static long init( )
|
||||
{
|
||||
vmic2534Init( );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* This hardware does not support interrupts
|
||||
*
|
||||
* NO interrupt service routine is applicable
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* vmic2534IOScan
|
||||
*
|
||||
* task to check of a change of state
|
||||
* (used to simulate "change-of-state" interrupts)
|
||||
*
|
||||
*/
|
||||
|
||||
vmic2534IOScan( )
|
||||
{
|
||||
int i;
|
||||
int firstScan = TRUE;
|
||||
long temp;
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
if ( interruptAccept ) break;
|
||||
taskDelay( vxTicksPerSecond/30 );
|
||||
}
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
for ( i = 0; i < VMIC_2534_MAX_CARDS; i++ )
|
||||
{
|
||||
if ( vmic2534Rec[ i ].vmicDevice )
|
||||
{
|
||||
temp = ( vmic2534Rec[ i ].vmicDevice->pioData )
|
||||
& ( vmic2534Rec[ i ].inputMask );
|
||||
|
||||
if ( (temp ^ vmic2534Rec[ i ].savedInputs) || firstScan )
|
||||
{
|
||||
scanIoRequest( vmic2534Rec[ i ].ioscanpvt );
|
||||
vmic2534Rec[ i ].savedInputs = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( firstScan )
|
||||
firstScan = FALSE;
|
||||
|
||||
taskDelay( vxTicksPerSecond/30 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DIO DRIVER INIT
|
||||
*
|
||||
*/
|
||||
|
||||
vmic2534Init( )
|
||||
{
|
||||
u_long dummy;
|
||||
register short i;
|
||||
VMIC_2534 *theHardware;
|
||||
int tid;
|
||||
int status;
|
||||
int atLeastOnePresent = FALSE;
|
||||
|
||||
/*
|
||||
* allow for runtime reconfiguration of the addr map
|
||||
*/
|
||||
|
||||
vmic2534Rec = (VMIC_2534_REC *)calloc(
|
||||
VMIC_2534_MAX_CARDS, sizeof( VMIC_2534_REC ) );
|
||||
if ( !vmic2534Rec )
|
||||
{
|
||||
logMsg("Attempt to calloc \"VMIC_2534_REC\" failed\n");
|
||||
return( ERROR );
|
||||
}
|
||||
status = sysBusToLocalAdrs( VME_AM_SUP_SHORT_IO, (VMIC_2534_ADDR0),
|
||||
&theHardware );
|
||||
if ( status != OK )
|
||||
{
|
||||
logMsg("%s: Unable to map VMIC_2534 base addr\n", __FILE__);
|
||||
return( ERROR );
|
||||
}
|
||||
|
||||
for ( i = 0; i < VMIC_2534_MAX_CARDS; i++, theHardware++ )
|
||||
{
|
||||
if ( (vxMemProbe( theHardware, READ, 2 ,&dummy )) != OK )
|
||||
{
|
||||
vmic2534Rec[i].vmicDevice = NULL;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
/* initialize hardware */
|
||||
{
|
||||
/* Outputs/Inputs are undetermined at this time */
|
||||
/* Disable output drivers in case of no SYS_RESET* */
|
||||
theHardware->ctlStatReg = 0;
|
||||
|
||||
/* determine "sense" of output and save correction factor */
|
||||
theHardware->pioData = 0;
|
||||
vmic2534Rec[i].outputCorrector = theHardware->pioData;
|
||||
|
||||
/* clear input & output masks, (malloc'ed mem may != 0) */
|
||||
vmic2534Rec[i].inputMask = 0;
|
||||
vmic2534Rec[i].outputMask = 0;
|
||||
|
||||
/* insure that outputs are initially "OFF", i.e. HIGH */
|
||||
theHardware->pioData = vmic2534Rec[i].outputCorrector;
|
||||
theHardware->ctlStatReg = TM1 | TM2 | FAIL_LED_OFF;
|
||||
|
||||
/*
|
||||
* record structure initalization
|
||||
*/
|
||||
|
||||
vmic2534Rec[ i ].vmicDevice = theHardware;
|
||||
atLeastOnePresent = TRUE;
|
||||
scanIoInit( &(vmic2534Rec[ i ].ioscanpvt) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( atLeastOnePresent)
|
||||
{
|
||||
if ( (tid = taskNameToId( VMIC_2534_NAME )) != ERROR )
|
||||
{
|
||||
taskwdRemove( tid );
|
||||
taskDelete( tid );
|
||||
}
|
||||
|
||||
if ( (status = taskSpawn(
|
||||
VMIC_2534_NAME, VMIC_2534_PRI, VMIC_2534_OPT,
|
||||
VMIC_2534_STACK, vmic2534IOScan )) == ERROR )
|
||||
logMsg("Unable to spawn \"vmic2534IOScan( )\" task\n");
|
||||
else
|
||||
taskwdInsert( status, NULL, NULL );
|
||||
}
|
||||
return( OK );
|
||||
}
|
||||
|
||||
/*
|
||||
* Set data direction control for specified data bits
|
||||
* Note:
|
||||
* Data direction is controlled on a "per-byte" basis.
|
||||
* The first bit defined within a byte sets the direction for the entire
|
||||
* byte. Any attempt to define conflicting bits after the direction
|
||||
* for a byte is set will return an error (-1) response.)
|
||||
* Permmissable values for "direction" are:
|
||||
* direction == 0 indicates input
|
||||
* direction != 0 indicates output
|
||||
*
|
||||
*/
|
||||
vmic2534_setIOBitDirection( short card, u_int mask, u_int direction )
|
||||
{
|
||||
int status = 0;
|
||||
u_long work, j;
|
||||
|
||||
static u_long maskTbl[ ] =
|
||||
{ 0x000000ff,
|
||||
0x0000ff00,
|
||||
0x00ff0000,
|
||||
0xff000000
|
||||
};
|
||||
|
||||
if ( (card >= VMIC_2534_MAX_CARDS) || !(vmic2534Rec[ card ].vmicDevice) )
|
||||
status = -1 ;
|
||||
else
|
||||
{
|
||||
if ( direction == 0)
|
||||
{
|
||||
/* INPUT */
|
||||
#ifdef DEBUG_2534
|
||||
printf("Mask = %08x, outPutMask =%08x\n",
|
||||
mask, vmic2534Rec[ card ].outputMask);
|
||||
#endif DEBUG_2534
|
||||
if ( ((u_long)mask & vmic2534Rec[ card ].outputMask) == 0 )
|
||||
{
|
||||
for ( j = 0; j < 4; j++ )
|
||||
{
|
||||
|
||||
if ( ( (u_long)mask & maskTbl[ j ] ) != 0 )
|
||||
{
|
||||
vmic2534Rec[ card ].inputMask |= maskTbl[ j ];
|
||||
#ifdef DEBUG_2534
|
||||
printf("inputMask = %08x\n",
|
||||
vmic2534Rec[ card ].inputMask);
|
||||
#endif DEBUG_2534
|
||||
vmic2534Rec[ card ].vmicDevice->ctlStatReg
|
||||
&= (u_char) ~(1 << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OUTPUT */
|
||||
#ifdef DEBUG_2534
|
||||
printf("Mask = %08x, inputMask =%08x\n",
|
||||
mask, vmic2534Rec[ card ].inputMask);
|
||||
#endif DEBUG_2534
|
||||
if ( ((u_long)mask & vmic2534Rec[ card ].inputMask) == 0 )
|
||||
{
|
||||
for ( j = 0; j < 4; j++ )
|
||||
{
|
||||
if ( ( (u_long)mask & maskTbl[ j ] ) != 0 )
|
||||
{
|
||||
vmic2534Rec[ card ].outputMask |= maskTbl[ j ];
|
||||
#ifdef DEBUG_2534
|
||||
printf("outputMask = %08x\n",
|
||||
vmic2534Rec[ card ].outputMask);
|
||||
#endif DEBUG_2534
|
||||
vmic2534Rec[ card ].vmicDevice->ctlStatReg
|
||||
|= (u_char)(1 << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return( status );
|
||||
}
|
||||
|
||||
vmic2534_getioscanpvt( short card, IOSCANPVT *scanpvt )
|
||||
{
|
||||
if ( (card >= VMIC_2534_MAX_CARDS) || !(vmic2534Rec[ card ].vmicDevice) )
|
||||
return( -1 );
|
||||
*scanpvt = vmic2534Rec[ card ].ioscanpvt;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* VMEVMIC_BI_DRIVER
|
||||
*
|
||||
* interface binary inputs
|
||||
*/
|
||||
|
||||
vmic2534_bi_driver( register short card,
|
||||
u_int mask,
|
||||
register u_int * prval )
|
||||
{
|
||||
if ( (card >= VMIC_2534_MAX_CARDS) || !(vmic2534Rec[ card ].vmicDevice) )
|
||||
return( -1 );
|
||||
|
||||
*prval = (u_int)( (vmic2534Rec[ card ].vmicDevice->pioData)
|
||||
& (vmic2534Rec[ card ].inputMask) )
|
||||
& mask;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* vmic2534_bo_read
|
||||
*
|
||||
* (read) interface to binary outputs
|
||||
*
|
||||
*/
|
||||
|
||||
vmic2534_bo_read( register short card,
|
||||
u_int mask,
|
||||
register u_int * prval )
|
||||
{
|
||||
if ( (card >= VMIC_2534_MAX_CARDS) || !(vmic2534Rec[ card ].vmicDevice) )
|
||||
return( -1 );
|
||||
|
||||
*prval = (u_int)(~( ( (vmic2534Rec[ card ].vmicDevice->pioData)
|
||||
& (vmic2534Rec[ card ].outputMask) )
|
||||
^ vmic2534Rec[card].outputCorrector) ) & mask;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* vmic2534_bo_driver
|
||||
*
|
||||
* (write) interface to binary outputs
|
||||
*/
|
||||
|
||||
vmic2534_bo_driver( register short card,
|
||||
register u_int val,
|
||||
u_int mask )
|
||||
{
|
||||
u_long work;
|
||||
|
||||
if ( (card >= VMIC_2534_MAX_CARDS) || !(vmic2534Rec[ card ].vmicDevice) )
|
||||
return( ERROR );
|
||||
|
||||
#ifndef DEBUGTHIS
|
||||
|
||||
|
||||
vmic2534Rec[ card ].vmicDevice->pioData =
|
||||
( ( ( ~(vmic2534Rec[ card ].vmicDevice->pioData) & (u_long)~mask)
|
||||
| (u_long)(val & mask) ) ^ vmic2534Rec[card].outputCorrector )
|
||||
& vmic2534Rec[ card ].outputMask;
|
||||
#else
|
||||
printf("Data = 0x%x, mask = 0x%x, corrector = 0x%x\n",
|
||||
val, mask, vmic2534Rec[card].outputCorrector);
|
||||
|
||||
work = vmic2534Rec[ card ].vmicDevice->pioData;
|
||||
printf("Current raw i/o data = 0x%x, output mask = 0x%x\n",
|
||||
work, vmic2534Rec[ card ].outputMask);
|
||||
work = ~work;
|
||||
printf("Corrected output data = 0x%x\n", work);
|
||||
work &= ( (u_long)~mask );
|
||||
printf("Masked data = 0x%x\n", work);
|
||||
work |= ( (u_long)(val & mask) );
|
||||
printf("New output data = 0x%x\n", work);
|
||||
work ^= vmic2534Rec[card].outputCorrector;
|
||||
printf("Polarity-corrected output data = 0x%x\n", work);
|
||||
work &= vmic2534Rec[ card ].outputMask;
|
||||
printf("Output data masked to output bits only = 0x%x\n", work);
|
||||
vmic2534Rec[ card ].vmicDevice->pioData = work;
|
||||
printf("*\n");
|
||||
#undef DEBUGTHIS
|
||||
#endif DEBUGTHIS
|
||||
return( OK );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* vmiv2534Out
|
||||
*
|
||||
* test routine for vm1c2534 output
|
||||
*/
|
||||
|
||||
vmiv2534Out( short card,
|
||||
u_long val )
|
||||
{
|
||||
/* check for valid card nr */
|
||||
if ( card >= VMIC_2534_MAX_CARDS )
|
||||
{
|
||||
logMsg("card # out of range/n");
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* check for card actually installed */
|
||||
if ( !(vmic2534Rec[ card ].vmicDevice) )
|
||||
{
|
||||
logMsg("card #%d not found\n", card);
|
||||
return( -2 );
|
||||
}
|
||||
|
||||
/* set the physical output */
|
||||
vmic2534Rec[ card ].vmicDevice->pioData
|
||||
= vmic2534Rec[ card ].outputCorrector ^ val;
|
||||
return( OK );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* vmic2534Write
|
||||
*
|
||||
* command line interface to test bo driver
|
||||
*/
|
||||
|
||||
vmic2534Write( short card,
|
||||
u_int val )
|
||||
{
|
||||
return( vmic2534_bo_driver( card, val, 0xffff ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
long
|
||||
vmic2534_io_report( short level )
|
||||
{
|
||||
int card;
|
||||
|
||||
for ( card = 0; card < VMIC_2534_MAX_CARDS; card++ )
|
||||
{
|
||||
if ( vmic2534Rec[ card ].vmicDevice )
|
||||
{
|
||||
printf("B*: vmic2534:\tcard%d\n", card);
|
||||
if( level >= 1 )
|
||||
{
|
||||
vmic2534_bi_io_report( card );
|
||||
vmic2534_bo_io_report( card );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vmic2534_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 = VMIC_2534_MAX_CHANS;
|
||||
|
||||
if( !vmic2534Rec[card].vmicDevice )
|
||||
return;
|
||||
|
||||
printf("\tVMEVMI-2534 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 )
|
||||
{
|
||||
vmic2534_bi_driver( card, masks( j ), &jval );
|
||||
if ( jval != 0 )
|
||||
jval = 1;
|
||||
printf("\tChan %d = %x\t ", j, jval);
|
||||
}
|
||||
|
||||
if( k < num_chans )
|
||||
{
|
||||
vmic2534_bi_driver( card, masks( k ), &kval );
|
||||
if ( kval != 0)
|
||||
kval = 1;
|
||||
printf("Chan %d = %x\t ", k, kval);
|
||||
}
|
||||
|
||||
if( l < num_chans )
|
||||
{
|
||||
vmic2534_bi_driver( card, masks( l ), &lval );
|
||||
if ( lval != 0 )
|
||||
lval = 1;
|
||||
printf("Chan %d = %x \t", l, lval);
|
||||
}
|
||||
if( m < num_chans)
|
||||
{
|
||||
vmic2534_bi_driver( card, masks( m ), &mval );
|
||||
if ( mval != 0 )
|
||||
mval = 1;
|
||||
printf("Chan %d = %x \n", m, mval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vmic2534_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 = VMIC_2534_MAX_CHANS;
|
||||
|
||||
if( !vmic2534Rec[card].vmicDevice )
|
||||
return;
|
||||
|
||||
printf("\tVMEVMI-2534 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 )
|
||||
{
|
||||
vmic2534_bo_read( card, masks( j ), &jval );
|
||||
if ( jval != 0 )
|
||||
jval = 1;
|
||||
printf("\tChan %d = %x\t ", j, jval);
|
||||
}
|
||||
|
||||
if( k < num_chans )
|
||||
{
|
||||
vmic2534_bo_read( card, masks( k ), &kval );
|
||||
if ( kval != 0)
|
||||
kval = 1;
|
||||
printf("Chan %d = %x\t ", k, kval);
|
||||
}
|
||||
|
||||
if( l < num_chans )
|
||||
{
|
||||
vmic2534_bo_read( card, masks( l ), &lval );
|
||||
if ( lval != 0 )
|
||||
lval = 1;
|
||||
printf("Chan %d = %x \t", l, lval);
|
||||
}
|
||||
if( m < num_chans)
|
||||
{
|
||||
vmic2534_bo_read( card, masks( m ), &mval );
|
||||
if ( mval != 0 )
|
||||
mval = 1;
|
||||
printf("Chan %d = %x \n", m, mval);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,532 +0,0 @@
|
||||
/* $Id$
|
||||
*
|
||||
* VXI standard defines
|
||||
*
|
||||
* 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:
|
||||
* -----------------
|
||||
* .01 joh 021490 changed NVXIADDR to 32 before formal release
|
||||
* .02 joh 120591 reorganized to support nivxi
|
||||
* .03 joh 010892 added message based device registers and
|
||||
* commands
|
||||
* .04 joh 013091 moved some of the slot 0 stuff here
|
||||
* .05 joh 070692 added KSC manufacturer id
|
||||
* .06 joh 070692 added address space defines
|
||||
* .07 joh 081992 added csr typedef
|
||||
* .08 joh 071593 typedef for device registers
|
||||
* .09 joh 051995 fixed incorrect MBC_TOP_LEVEL_CMDR def
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INCepvxih
|
||||
#define INCepvxih
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* offset from the bottom of VME short addr of
|
||||
* VXI logical address space
|
||||
*/
|
||||
#define VXIBASEADDR 0xc000
|
||||
|
||||
typedef volatile uint16_t vxi16_t;
|
||||
typedef volatile uint8_t vxi8_t;
|
||||
|
||||
/*
|
||||
* set NVXIADDR to less than 0x100 since other VME modules
|
||||
* currently live in VXI address space
|
||||
*/
|
||||
#define NVXIADDR (0x100)
|
||||
#define NVXISLOTS 13
|
||||
#define VXIDYNAMICADDR (0xff)
|
||||
#define NVXIADDRBITS 8
|
||||
#define VXIADDRMASK ((1<<NVXIADDRBITS)-1)
|
||||
#define VXI_RESMAN_LA 0
|
||||
#define VXI_NBBY 8
|
||||
#define VXIDEVBITS 6
|
||||
#define VXIDEVSIZE (1<<VXIDEVBITS)
|
||||
|
||||
#define VXI_LA_TO_PA(LA, VXIBASEADDR) \
|
||||
( (VXICSR *) (((char *)VXIBASEADDR)+(((unsigned)LA)<<VXIDEVBITS)) )
|
||||
|
||||
#define VXI_PA_TO_LA(PA) ( (((unsigned)PA)>>VXIDEVBITS)&VXIADDRMASK )
|
||||
|
||||
struct vxi_msg_dev_w{
|
||||
vxi16_t signal;
|
||||
vxi16_t dextended;
|
||||
vxi16_t dhigh;
|
||||
vxi16_t dlow;
|
||||
};
|
||||
|
||||
struct vxi_mxi_dev_w{
|
||||
vxi16_t modid;
|
||||
vxi16_t la_window;
|
||||
vxi8_t a16_window_high;
|
||||
vxi8_t a16_window_low;
|
||||
vxi8_t a24_window_high;
|
||||
vxi8_t a24_window_low;
|
||||
vxi8_t a32_window_high;
|
||||
vxi8_t a32_window_low;
|
||||
vxi16_t INTX_interrupt;
|
||||
vxi16_t INTX_trigger;
|
||||
vxi16_t dd7;
|
||||
vxi16_t INTX_utility;
|
||||
vxi16_t dd9;
|
||||
vxi16_t dd10;
|
||||
vxi16_t subclass;
|
||||
vxi16_t control;
|
||||
vxi16_t lock;
|
||||
vxi16_t irq;
|
||||
vxi16_t trigger_drive;
|
||||
vxi16_t trigger_mode;
|
||||
vxi16_t interrupt;
|
||||
vxi16_t status_id;
|
||||
vxi16_t trigger_config;
|
||||
vxi16_t trigger_sync_ack;
|
||||
vxi16_t trigger_async_ack;
|
||||
vxi16_t irq_ack;
|
||||
};
|
||||
|
||||
struct vxi_reg_dev_w{
|
||||
vxi16_t ddx08;
|
||||
vxi16_t ddxoa;
|
||||
vxi16_t ddx0c;
|
||||
vxi16_t ddx0e;
|
||||
vxi16_t ddx10;
|
||||
vxi16_t ddx12;
|
||||
vxi16_t ddx14;
|
||||
vxi16_t ddx16;
|
||||
vxi16_t ddx18;
|
||||
vxi16_t ddx1a;
|
||||
vxi16_t ddx1c;
|
||||
vxi16_t ddx1e;
|
||||
vxi16_t ddx20;
|
||||
vxi16_t ddx22;
|
||||
vxi16_t ddx24;
|
||||
vxi16_t ddx26;
|
||||
vxi16_t ddx28;
|
||||
vxi16_t ddx2a;
|
||||
vxi16_t ddx2c;
|
||||
vxi16_t ddx2e;
|
||||
};
|
||||
|
||||
struct vxi_reg_slot0_dev_w{
|
||||
vxi16_t modid;
|
||||
vxi16_t ddxoa;
|
||||
vxi16_t ddx0c;
|
||||
vxi16_t ddx0e;
|
||||
vxi16_t ddx10;
|
||||
vxi16_t ddx12;
|
||||
vxi16_t ddx14;
|
||||
vxi16_t ddx16;
|
||||
vxi16_t ddx18;
|
||||
vxi16_t ddx1a;
|
||||
vxi16_t ddx1c;
|
||||
vxi16_t ddx1e;
|
||||
vxi16_t ddx20;
|
||||
vxi16_t ddx22;
|
||||
vxi16_t ddx24;
|
||||
vxi16_t ddx26;
|
||||
vxi16_t ddx28;
|
||||
vxi16_t ddx2a;
|
||||
vxi16_t ddx2c;
|
||||
vxi16_t ddx2e;
|
||||
};
|
||||
|
||||
struct vxi_csr_w{
|
||||
vxi16_t addr;
|
||||
vxi16_t pad0;
|
||||
vxi16_t control;
|
||||
vxi16_t offset;
|
||||
union {
|
||||
struct vxi_msg_dev_w msg;
|
||||
struct vxi_mxi_dev_w mxi;
|
||||
struct vxi_reg_dev_w reg;
|
||||
struct vxi_reg_slot0_dev_w reg_s0;
|
||||
}dd;
|
||||
};
|
||||
|
||||
struct vxi_msg_dev_r{
|
||||
vxi16_t protocol;
|
||||
vxi16_t response;
|
||||
vxi16_t dhigh;
|
||||
vxi16_t dlow;
|
||||
};
|
||||
|
||||
struct vxi_mxi_dev_r{
|
||||
vxi16_t modid;
|
||||
vxi16_t la_window;
|
||||
vxi16_t a16_window;
|
||||
vxi16_t a24_window;
|
||||
vxi16_t a32_window;
|
||||
vxi16_t dd5;
|
||||
vxi16_t dd6;
|
||||
vxi16_t dd7;
|
||||
vxi16_t dd8;
|
||||
vxi16_t dd9;
|
||||
vxi16_t dd10;
|
||||
vxi16_t subclass;
|
||||
vxi16_t status;
|
||||
vxi16_t lock;
|
||||
vxi16_t irq;
|
||||
vxi16_t read_la;
|
||||
vxi16_t trigger_mode;
|
||||
vxi16_t interrupt;
|
||||
vxi16_t status_id;
|
||||
vxi16_t trigger_config;
|
||||
vxi16_t trigger_sync_ack;
|
||||
vxi16_t trigger_async_ack;
|
||||
vxi16_t irq_ack;
|
||||
};
|
||||
|
||||
struct vxi_reg_dev_r{
|
||||
vxi16_t ddx08;
|
||||
vxi16_t ddxoa;
|
||||
vxi16_t ddx0c;
|
||||
vxi16_t ddx0e;
|
||||
vxi16_t ddx10;
|
||||
vxi16_t ddx12;
|
||||
vxi16_t ddx14;
|
||||
vxi16_t ddx16;
|
||||
vxi16_t ddx18;
|
||||
vxi16_t ddx1a;
|
||||
vxi16_t ddx1c;
|
||||
vxi16_t ddx1e;
|
||||
vxi16_t ddx20;
|
||||
vxi16_t ddx22;
|
||||
vxi16_t ddx24;
|
||||
vxi16_t ddx26;
|
||||
vxi16_t ddx28;
|
||||
vxi16_t ddx2a;
|
||||
vxi16_t ddx2c;
|
||||
vxi16_t ddx2e;
|
||||
};
|
||||
|
||||
struct vxi_reg_slot0_dev_r{
|
||||
vxi16_t modid;
|
||||
vxi16_t ddxoa;
|
||||
vxi16_t ddx0c;
|
||||
vxi16_t ddx0e;
|
||||
vxi16_t ddx10;
|
||||
vxi16_t ddx12;
|
||||
vxi16_t ddx14;
|
||||
vxi16_t ddx16;
|
||||
vxi16_t ddx18;
|
||||
vxi16_t ddx1a;
|
||||
vxi16_t ddx1c;
|
||||
vxi16_t ddx1e;
|
||||
vxi16_t ddx20;
|
||||
vxi16_t ddx22;
|
||||
vxi16_t ddx24;
|
||||
vxi16_t ddx26;
|
||||
vxi16_t ddx28;
|
||||
vxi16_t ddx2a;
|
||||
vxi16_t ddx2c;
|
||||
vxi16_t ddx2e;
|
||||
};
|
||||
|
||||
struct vxi_csr_r{
|
||||
vxi16_t make;
|
||||
vxi16_t model;
|
||||
vxi16_t status;
|
||||
vxi16_t offset;
|
||||
union {
|
||||
struct vxi_msg_dev_r msg;
|
||||
struct vxi_mxi_dev_r mxi;
|
||||
struct vxi_reg_dev_r reg;
|
||||
struct vxi_reg_slot0_dev_r reg_s0;
|
||||
}dd;
|
||||
};
|
||||
|
||||
|
||||
struct vxi_csr{
|
||||
union {
|
||||
struct vxi_csr_w w;
|
||||
struct vxi_csr_r r;
|
||||
}dir;
|
||||
};
|
||||
|
||||
typedef struct vxi_csr VXICSR;
|
||||
|
||||
#define CSRRMEM(PSR,MEMBER) ( ((VXICSR *)(PSR))->MEMBER )
|
||||
|
||||
/*
|
||||
* Reserved device types
|
||||
*/
|
||||
#define VXIMODELMASK(WD) ( (WD)&0xfff )
|
||||
#define VXIMODEL(PSR) ( (unsigned) VXIMODELMASK(CSRRMEM(PSR,dir.r.model)) )
|
||||
#define VXIMAKE(PSR) ( (unsigned) 0xfff&CSRRMEM(PSR,dir.r.make) )
|
||||
#define VXISLOT0MODELTEST(WD) ((WD)<0x100)
|
||||
#define VXISLOT0MODEL(PCSR) (VXISLOT0MODELTEST(VXIMODEL(PCSR)))
|
||||
|
||||
/*
|
||||
* vxi device classes
|
||||
*/
|
||||
#define VXI_MEMORY_DEVICE 0
|
||||
#define VXI_EXTENDED_DEVICE 1
|
||||
#define VXI_MESSAGE_DEVICE 2
|
||||
#define VXI_REGISTER_DEVICE 3
|
||||
#define VXICLASS(PSR) ((unsigned)(0xc000&CSRRMEM(PSR,dir.r.make))>>14)
|
||||
#define VXISUBCLASS(PSR) ((unsigned)CSRRMEM(PSR,dir.r.dd.mxi.subclass) )
|
||||
#define VXIMXI(PSR)\
|
||||
(VXICLASS(PSR)==VXI_EXTENDED_DEVICE ? VXISUBCLASS(PSR)==VXI_MXI_DEVICE : 0)
|
||||
#define VXI_MXI_DEVICE 0xfffc
|
||||
#define MXI_BASE_DEVICE 0xf
|
||||
#define MXI_INTX_DEVICE 0xe
|
||||
#define MXI_EXTENDED_TYPE(PSR) ((((unsigned)CSRRMEM(PSR,dir.r.status))>>10)&0xf)
|
||||
#define MXIINTX(PSR) (MXI_EXTENDED_TYPE(PSR) == MXI_INTX_DEVICE)
|
||||
#ifndef SRCepvxiLib
|
||||
extern
|
||||
#endif
|
||||
char *vxi_device_class_names[]
|
||||
#ifdef SRCepvxiLib
|
||||
= {
|
||||
"memory",
|
||||
"extended",
|
||||
"message",
|
||||
"register"}
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* A32/A24 address space
|
||||
*/
|
||||
#define VXIADDRSPACE(PSR) ( (unsigned long) 3&(CSRRMEM(PSR,dir.r.make)>>12) )
|
||||
#define VXIREQMEM(PSR) ( (unsigned long) 0xf&(CSRRMEM(PSR,dir.r.model)>>12) )
|
||||
#define VXIA24MEMSIZE(M) ( (long) 1<<(23-(M)) )
|
||||
#define VXIA32MEMSIZE(M) ( (long) 1<<(31-(M)) )
|
||||
#define VXI_ADDR_EXT_A24 0
|
||||
#define VXI_ADDR_EXT_A32 1
|
||||
#define VXI_ADDR_EXT_NONE 3
|
||||
|
||||
/*
|
||||
*
|
||||
* VXI vendor codes
|
||||
*
|
||||
*/
|
||||
#define VXI_MAKE_HP 0xfff /* Hewlett Packard */
|
||||
#define VXI_MAKE_RD 0xffb /* Racal Dana */
|
||||
#define VXI_MAKE_NI 0xff6 /* National Instruments */
|
||||
#define VXI_MAKE_LANSCE5 0xfa0 /* Los Alamos Natl Lab LANSCE-5 */
|
||||
#define VXI_MAKE_KSC 0xf29 /* Kinetic Systems */
|
||||
struct vxi_vendor_info{
|
||||
uint16_t make;
|
||||
char *pvendor_name;
|
||||
};
|
||||
|
||||
/*
|
||||
* In decreasing order of vendor id
|
||||
*/
|
||||
#ifndef SRCepvxiLib
|
||||
extern
|
||||
#endif
|
||||
struct vxi_vendor_info vxi_vi[]
|
||||
#ifdef SRCepvxiLib
|
||||
= {
|
||||
{VXI_MAKE_HP, "Hewlett-Packard"},
|
||||
{VXI_MAKE_RD, "Racal-Dana"},
|
||||
{VXI_MAKE_NI, "National Instruments"},
|
||||
{VXI_MAKE_LANSCE5, "LANL LANSCE-5"},
|
||||
{VXI_MAKE_KSC, "Kinetic Systems"},
|
||||
}
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
* MXI commands
|
||||
* (for the MXI control register)
|
||||
*/
|
||||
#define MXI_UPPER_LOWER_BOUNDS 0x4000
|
||||
#define MXI_LA_WINDOW_SIZE_MASK 0x3
|
||||
#define MXIA24MASK (0xffff)
|
||||
#define MXIA24MASKSIZE 16
|
||||
#define MXIA32MASK (0xffffff)
|
||||
#define MXIA32MASKSIZE 24
|
||||
#define MXIA24ALIGN(A) (((unsigned long)(A)+MXIA24MASK)&~MXIA24MASK)
|
||||
#define MXIA32ALIGN(A) (((unsigned long)(A)+MXIA32MASK)&~MXIA32MASK)
|
||||
|
||||
/*
|
||||
* applies to all vxi devices
|
||||
*/
|
||||
#define VXIMEMENBLMASK (0x8000)
|
||||
#define VXIMEMENBL(PSR) (VXIMEMENBLMASK&CSRRMEM(PSR,dir.r.status))
|
||||
#define VXINDCDEVICESMASK (0xff)
|
||||
#define VXINDCDEVICES(PSR) (VXINDCDEVICESMASK&CSRRMEM(PSR,dir.r.offset))
|
||||
|
||||
/*
|
||||
* Register based slot zero
|
||||
*/
|
||||
#define VXIMODIDSTATUS(WD) ((WD)&0x4000?FALSE:TRUE)
|
||||
#define VXIPASS 3
|
||||
#define VXIPASSEDSTATUS(WD) (((WD)>>2)&VXIPASS)
|
||||
|
||||
|
||||
/*
|
||||
* RULE C.4.4
|
||||
*
|
||||
* The resource manager shall write all ones to the
|
||||
* device dependent bits when writing to the control register
|
||||
*
|
||||
*/
|
||||
#define VXISAFECONTROL 0x7fff /* sys fail inhibit, reset, no mem enbl */
|
||||
#define VXIMEMENBLCONTROL 0xfffc /* mem enbl, no sys fail inhibit, no reset */
|
||||
|
||||
#define VXI_SET_REG_MODID(PCSR, SLOT) \
|
||||
( ((VXICSR *)(PCSR))->dir.w.dd.reg_s0.modid = \
|
||||
0x2000|1<<(SLOT) )
|
||||
#define VXI_CLR_ALL_REG_MODID(PCSR) \
|
||||
( ((VXICSR *)(PCSR))->dir.w.dd.reg_s0.modid = 0 )
|
||||
|
||||
/*
|
||||
* vxi msg based functions
|
||||
*/
|
||||
#define VXIWRITEREADYMASK (0x0200)
|
||||
#define VXIREADREADYMASK (0x0400)
|
||||
#define VXIDIRMASK (0x1000)
|
||||
#define VXIDORMASK (0x2000)
|
||||
#define VXIFHSMMASK (0x0100)
|
||||
#define VXIERRNOTMASK (0x0800)
|
||||
|
||||
#define VXICMDRMASK (0x8000)
|
||||
#define VXICMDR(PSR) (!(VXICMDRMASK&CSRRMEM(PSR,dir.r.dd.msg.protocol)))
|
||||
#define VXIFHSMASK (0x0800)
|
||||
#define VXIFHS(PSR) (!(VXIFHSMASK&CSRRMEM(PSR,dir.r.dd.msg.protocol)))
|
||||
#define VXISHMMASK (0x0400)
|
||||
#define VXISHM(PSR) (!(VXISHMMASK&CSRRMEM(PSR,dir.r.dd.msg.protocol)))
|
||||
#define VXIMBINTMASK (0x1000)
|
||||
#define VXIMBINT(PSR) (VXIMBINTMASK&CSRRMEM(PSR,dir.r.dd.msg.protocol))
|
||||
#define VXIVMEBMMASK (0x2000)
|
||||
#define VXIVMEBM(PSR) (!(VXIVMEBMMASK&CSRRMEM(PSR,dir.r.dd.msg.protocol)))
|
||||
#define VXISIGREGMASK (0x4000)
|
||||
#define VXISIGREG(PSR) (!(VXISIGREGMASK&CSRRMEM(PSR,dir.r.dd.msg.protocol)))
|
||||
|
||||
/*
|
||||
* serial protocol errors
|
||||
*/
|
||||
#define MBE_NO_ERROR (0xff)
|
||||
#define MBE_MULTIPLE_QUERIES (0xfd)
|
||||
#define MBE_UNSUPPORTED_CMD (0xfc)
|
||||
#define MBE_DIR_VIOLATION (0xfb)
|
||||
#define MBE_DOR_VIOLATION (0xfa)
|
||||
#define MBE_RR_VIOLATION (0xf9)
|
||||
#define MBE_WR_VIOLATION (0xf8)
|
||||
|
||||
/*
|
||||
* vxi message based commands
|
||||
*/
|
||||
#define MBC_BEGIN_NORMAL_OPERATION 0xfcff
|
||||
#define MBC_TOP_LEVEL_CMDR 0x0100
|
||||
#define MBC_READ_SERVANT_AREA 0xceff
|
||||
#define MBC_BA 0xbc00
|
||||
#define MBC_BR 0xdeff
|
||||
#define MBC_END 0x0100
|
||||
#define MBC_READ_PROTOCOL 0xdfff
|
||||
#define MBC_ASSIGN_INTERRUPTER_LINE 0xaa00
|
||||
#define MBC_READ_INTERRUPTERS 0xcaff
|
||||
#define MBC_READ_PROTOCOL_ERROR 0xcdff
|
||||
#define MBC_GRANT_DEVICE 0xbf00
|
||||
#define MBC_IDENTIFY_COMMANDER 0xbe00
|
||||
#define MBC_CLEAR 0xffff
|
||||
|
||||
/*
|
||||
* async mode control commands
|
||||
*/
|
||||
#define MBC_ASYNC_MODE_CONTROL 0xa800
|
||||
|
||||
#define MBC_AMC_RESP_ENABLE 0x0000
|
||||
#define MBC_AMC_RESP_DISABLE 0x0008
|
||||
#define MBC_AMC_EVENT_ENABLE 0x0000
|
||||
#define MBC_AMC_EVENT_DISABLE 0x0004
|
||||
|
||||
#define MBC_AMC_RESP_INT_ENABLE 0x0000
|
||||
#define MBC_AMC_RESP_SIGNAL_ENABLE 0x0002
|
||||
#define MBC_AMC_EVENT_INT_ENABLE 0x0000
|
||||
#define MBC_AMC_EVENT_SIGNAL_ENABLE 0x0001
|
||||
|
||||
/*
|
||||
* control resp command
|
||||
* (enable all)
|
||||
*/
|
||||
#define MBC_CONTROL_RESPONSE 0x8fc0
|
||||
|
||||
/*
|
||||
* msg based responses
|
||||
*/
|
||||
#define MBR_STATUS(RESP) (((RESP)>>12) & 0xf)
|
||||
#define MBR_STATUS_SUCCESS 0xf
|
||||
#define MBR_READ_SERVANT_AREA_MASK 0x00ff
|
||||
#define MBR_CR_CONFIRM_MASK 0x007f
|
||||
|
||||
/*
|
||||
* read interrupters response
|
||||
*/
|
||||
#define MBR_READ_INTERRUPTERS_MASK 0x7
|
||||
|
||||
/*
|
||||
* async mode control resp
|
||||
*/
|
||||
#define MBR_AMC_CONFIRM_MASK 0xf
|
||||
|
||||
/*
|
||||
* begin normal operation message based responses
|
||||
*/
|
||||
#define MBR_BNO_STATE(RESP) (((RESP)>>8) & 0xf)
|
||||
#define MBR_BNO_STATE_NO 0xf
|
||||
|
||||
/*
|
||||
* read protocol message based responses
|
||||
*/
|
||||
#define MBR_RP_LW(RESP) (!((RESP)&0x1))
|
||||
#define MBR_RP_ELW(RESP) (!((RESP)&0x2))
|
||||
#define MBR_RP_I(RESP) (!((RESP)&0x4))
|
||||
#define MBR_RP_I4(RESP) (!((RESP)&0x8))
|
||||
#define MBR_RP_TRG(RESP) (!((RESP)&0x10))
|
||||
#define MBR_RP_PH(RESP) (!((RESP)&0x20))
|
||||
#define MBR_RP_PI(RESP) (!((RESP)&0x40))
|
||||
#define MBR_RP_EG(RESP) (!((RESP)&0x100))
|
||||
#define MBR_RP_RG(RESP) (!((RESP)&0x200))
|
||||
#define MBR_REV_12(RESP) (!((RESP)&0x8000))
|
||||
|
||||
/*
|
||||
* protocol events
|
||||
* vxi spec E.4
|
||||
*/
|
||||
#define MBE_EVENT_TEST(EVENT) ((EVENT)&0x1000)
|
||||
|
||||
/*
|
||||
* vxi trigger constants
|
||||
*/
|
||||
#define VXI_N_TTL_TRIGGERS 8
|
||||
#define VXI_N_ECL_TRIGGERS 6
|
||||
#define MXI_ECL0_ENABLE 0x0800
|
||||
#define MXI_ECL0_FP_TO_BP 0x0400
|
||||
#define MXI_ECL0_BP_TO_FP 0
|
||||
#define MXI_ECL1_ENABLE 0x2000
|
||||
#define MXI_ECL1_FP_TO_BP 0x1000
|
||||
#define MXI_ECL1_BP_TO_FP 0
|
||||
|
||||
#endif /* INCvxih */
|
||||
@@ -1,33 +0,0 @@
|
||||
|
||||
#ifndef INCipModulesH
|
||||
#define INCipModulesH
|
||||
|
||||
|
||||
#define IP_MANUFACTURER_GREENSPRING 0xf0
|
||||
|
||||
#define IP_MODEL_GS_PRECISION_ADC 0x15
|
||||
#define IP_MODEL_GS_PRECISION_ADC_N "ADC"
|
||||
|
||||
#define IP_MODEL_GS_QUAD_SERIAL 0x37
|
||||
#define IP_MODEL_GS_QUAD_SERIAL_N "Quad_Serial"
|
||||
|
||||
#define IP_MODEL_GS_OCTAL_SERIAL 0x22
|
||||
#define IP_MODEL_GS_OCTAL_SERIAL_N "Octal_Serial"
|
||||
|
||||
#define IP_MODEL_GS_SERIAL 0x10
|
||||
#define IP_MODEL_GS_SERIAL_N "Serial"
|
||||
|
||||
#define IP_MODEL_GS_QUADRATURE 0x41
|
||||
#define IP_MODEL_GS_QUADRATURE_N "Quadrature"
|
||||
|
||||
#define IP_MODEL_GS_488 0x14
|
||||
#define IP_MODEL_GS_488_N "ip488"
|
||||
|
||||
|
||||
#define IP_MANUFACTURER_TEWS 0xb3
|
||||
|
||||
#define IP_MODEL_TEWS_TIP810 0x01
|
||||
|
||||
|
||||
#endif /* INCipModulesH */
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
ipic.h
|
||||
|
||||
Description:
|
||||
IndustryPack Interface Controller ASIC header file, giving the register
|
||||
layout and programming model for the IPIC chip used on the MVME162.
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
6 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef INCipicH
|
||||
#define INCipicH
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Chip Registers */
|
||||
|
||||
#define IPIC_CHIP_ID 0x23
|
||||
#define IPIC_CHIP_REVISION 0x00
|
||||
|
||||
|
||||
/* Interrupt Control Register bits */
|
||||
|
||||
#define IPIC_INT_LEVEL 0x07
|
||||
#define IPIC_INT_ICLR 0x08
|
||||
#define IPIC_INT_IEN 0x10
|
||||
#define IPIC_INT_INT 0x20
|
||||
#define IPIC_INT_EDGE 0x40
|
||||
#define IPIC_INT_PLTY 0x80
|
||||
|
||||
|
||||
/* General Control Registers bits */
|
||||
|
||||
#define IPIC_GEN_MEN 0x01
|
||||
#define IPIC_GEN_WIDTH 0x0c
|
||||
#define IPIC_GEN_WIDTH_8 0x04
|
||||
#define IPIC_GEN_WIDTH_16 0x08
|
||||
#define IPIC_GEN_WIDTH_32 0x00
|
||||
#define IPIC_GEN_RT 0x30
|
||||
#define IPIC_GEN_RT_0 0x00
|
||||
#define IPIC_GEN_RT_2 0x10
|
||||
#define IPIC_GEN_RT_4 0x20
|
||||
#define IPIC_GEN_RT_8 0x30
|
||||
#define IPIC_GEN_ERR 0x80
|
||||
|
||||
|
||||
/* IP Reset register bits */
|
||||
|
||||
#define IPIC_IP_RESET 0x01
|
||||
|
||||
|
||||
/* Chip Structure */
|
||||
|
||||
typedef struct {
|
||||
uchar_t chipId;
|
||||
uchar_t chipRevision;
|
||||
uchar_t reserved1[2];
|
||||
ushort_t memBase[4];
|
||||
uchar_t memSize[4];
|
||||
uchar_t intCtrl[4][2];
|
||||
uchar_t genCtrl[4];
|
||||
uchar_t reserved2[3];
|
||||
uchar_t ipReset;
|
||||
} ipic_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INCipicH */
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Project:
|
||||
Gemini/UKIRT CAN Bus Driver for EPICS
|
||||
|
||||
File:
|
||||
pca82c200.h
|
||||
|
||||
Description:
|
||||
Philips Stand-alone CAN-controller chip header file, giving the register
|
||||
layout and programming model for the chip used on the TIP810 IP module.
|
||||
|
||||
Author:
|
||||
Andrew Johnson
|
||||
Created:
|
||||
19 July 1995
|
||||
|
||||
(c) 1995 Royal Greenwich Observatory
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef INCpca82c200H
|
||||
#define INCpca82c200H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/***** Control Segment Bit Patterns *****/
|
||||
|
||||
/* Control Register */
|
||||
|
||||
#define PCA_CR_TM 0x80 /* Test Mode */
|
||||
#define PCA_CR_S 0x40 /* Synch */
|
||||
#define PCA_CR_OIE 0x10 /* Overrun Interrupt Enable */
|
||||
#define PCA_CR_EIE 0x08 /* Error Interrupt Enable */
|
||||
#define PCA_CR_TIE 0x04 /* Transmit Interrupt Enable */
|
||||
#define PCA_CR_RIE 0x02 /* Receive Interrupt Enable */
|
||||
#define PCA_CR_RR 0x01 /* Reset Request */
|
||||
|
||||
|
||||
/* Command Register */
|
||||
|
||||
#define PCA_CMR_GTS 0x10 /* Goto Sleep */
|
||||
#define PCA_CMR_COS 0x08 /* Clear Overrun Status */
|
||||
#define PCA_CMR_RRB 0x04 /* Release Receive Buffer */
|
||||
#define PCA_CMR_AT 0x02 /* Abort Transmission */
|
||||
#define PCA_CMR_TR 0x01 /* Transmission Request */
|
||||
|
||||
|
||||
/* Status Register */
|
||||
|
||||
#define PCA_SR_BS 0x80 /* Bus Status */
|
||||
#define PCA_SR_ES 0x40 /* Error Status */
|
||||
#define PCA_SR_TS 0x20 /* Transmit Status */
|
||||
#define PCA_SR_RS 0x10 /* Receive Status */
|
||||
#define PCA_SR_TCS 0x08 /* Transmission Complete Status */
|
||||
#define PCA_SR_TBS 0x04 /* Transmit Buffer Status */
|
||||
#define PCA_SR_DO 0x02 /* Data Overrun */
|
||||
#define PCA_SR_RBS 0x01 /* Receive Buffer Status */
|
||||
|
||||
|
||||
/* Interrupt Register */
|
||||
|
||||
#define PCA_IR_WUI 0x10 /* Wake-Up Interrupt */
|
||||
#define PCA_IR_OI 0x08 /* Overrun Interrupt */
|
||||
#define PCA_IR_EI 0x04 /* Error Interrupt */
|
||||
#define PCA_IR_TI 0x02 /* Transmit Interrupt */
|
||||
#define PCA_IR_RI 0x01 /* Receive Interrupt */
|
||||
|
||||
|
||||
/* Bus Timing Register 0 */
|
||||
|
||||
#define PCA_BTR0_1M6 0x00 /* 1.6 Mbits/sec, 20 m */
|
||||
#define PCA_BTR0_1M0 0x00 /* 1.0 Mbits/sec, 40 m */
|
||||
#define PCA_BTR0_500K 0x00 /* 500 Kbits/sec, 130 m */
|
||||
#define PCA_BTR0_250K 0x01 /* 250 Kbits/sec, 270 m */
|
||||
#define PCA_BTR0_125K 0x03 /* 125 Kbits/sec, 530 m */
|
||||
#define PCA_BTR0_100K 0x43 /* 100 Kbits/sec, 620 m */
|
||||
#define PCA_BTR0_50K 0x47 /* 50 Kbits/sec, 1.3 km */
|
||||
#define PCA_BTR0_20K 0x53 /* 20 Kbits/sec, 3.3 km */
|
||||
#define PCA_BTR0_10K 0x67 /* 10 Kbits/sec, 6.7 km */
|
||||
#define PCA_BTR0_5K 0x7f /* 5 Kbits/sec, 10 km */
|
||||
|
||||
#define PCA_KVASER_1M0 0x00 /* 1.0 Mbits/sec, 40 m -- Kvaser standard */
|
||||
#define PCA_KVASER_500K 0x01 /* 500 Kbits/sec, 130 m -- Kvaser standard */
|
||||
#define PCA_KVASER_250K 0x03 /* 250 Kbits/sec, 270 m -- Kvaser standard */
|
||||
#define PCA_KVASER_125K 0x07 /* 125 Kbits/sec, 530 m -- Kvaser standard */
|
||||
|
||||
|
||||
/* Bus Timing Register 1 */
|
||||
|
||||
#define PCA_BTR1_1M6 0x11 /* 1.6 Mbits/sec, 20 m */
|
||||
#define PCA_BTR1_1M0 0x14 /* 1.0 Mbits/sec, 40 m */
|
||||
#define PCA_BTR1_500K 0x1c /* 500 Kbits/sec, 130 m */
|
||||
#define PCA_BTR1_250K 0x1c /* 250 Kbits/sec, 270 m */
|
||||
#define PCA_BTR1_125K 0x1c /* 125 Kbits/sec, 530 m */
|
||||
#define PCA_BTR1_100K 0x2f /* 100 Kbits/sec, 620 m */
|
||||
#define PCA_BTR1_50K 0x2f /* 50 Kbits/sec, 1.3 km */
|
||||
#define PCA_BTR1_20K 0x2f /* 20 Kbits/sec, 3.3 km */
|
||||
#define PCA_BTR1_10K 0x2f /* 10 Kbits/sec, 6.7 km */
|
||||
#define PCA_BTR1_5K 0x7f /* 5 Kbits/sec, 10 km */
|
||||
|
||||
#define PCA_BTR1_KVASER 0x23 /* All speeds -- Kvaser standard */
|
||||
|
||||
/* Output Control Register */
|
||||
|
||||
#define PCA_OCR_OCM_NORMAL 0x02
|
||||
#define PCA_OCR_OCM_CLOCK 0x03
|
||||
#define PCA_OCR_OCM_BIPHASE 0x00
|
||||
#define PCA_OCR_OCM_TEST 0x01
|
||||
|
||||
#define PCA_OCR_OCT1_FLOAT 0x00
|
||||
#define PCA_OCR_OCT1_PULLDOWN 0x40
|
||||
#define PCA_OCR_OCT1_PULLUP 0x80
|
||||
#define PCA_OCR_OCT1_PUSHPULL 0xc0
|
||||
|
||||
#define PCA_OCR_OCT0_FLOAT 0x00
|
||||
#define PCA_OCR_OCT0_PULLDOWN 0x08
|
||||
#define PCA_OCR_OCT0_PULLUP 0x10
|
||||
#define PCA_OCR_OCT0_PUSHPULL 0x18
|
||||
|
||||
#define PCA_OCR_OCP1_INVERT 0x20
|
||||
#define PCA_OCR_OCP0_INVERT 0x04
|
||||
|
||||
|
||||
/* Message Buffers */
|
||||
|
||||
#define PCA_MSG_ID0_RSHIFT 3
|
||||
#define PCA_MSG_ID1_LSHIFT 5
|
||||
#define PCA_MSG_ID1_MASK 0xe0
|
||||
#define PCA_MSG_RTR 0x10
|
||||
#define PCA_MSG_DLC_MASK 0x0f
|
||||
|
||||
|
||||
/***** Chip Structure *****/
|
||||
|
||||
/* Message Buffers */
|
||||
|
||||
typedef struct {
|
||||
uchar_t pad0;
|
||||
uchar_t descriptor0;
|
||||
uchar_t pad1;
|
||||
uchar_t descriptor1;
|
||||
ushort_t data[8];
|
||||
} msgBuffer_t;
|
||||
|
||||
|
||||
/* Chip Registers */
|
||||
|
||||
typedef volatile struct {
|
||||
uchar_t pad00;
|
||||
uchar_t control;
|
||||
uchar_t pad01;
|
||||
uchar_t command;
|
||||
uchar_t pad02;
|
||||
uchar_t status;
|
||||
uchar_t pad03;
|
||||
uchar_t interrupt;
|
||||
uchar_t pad04;
|
||||
uchar_t acceptanceCode;
|
||||
uchar_t pad05;
|
||||
uchar_t acceptanceMask;
|
||||
uchar_t pad06;
|
||||
uchar_t busTiming0;
|
||||
uchar_t pad07;
|
||||
uchar_t busTiming1;
|
||||
uchar_t pad08;
|
||||
uchar_t outputControl;
|
||||
uchar_t pad09;
|
||||
uchar_t test;
|
||||
msgBuffer_t txBuffer;
|
||||
msgBuffer_t rxBuffer;
|
||||
uchar_t pad31;
|
||||
uchar_t clockDivider;
|
||||
} pca82c200_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INCpca82c200H */
|
||||
|
||||
Reference in New Issue
Block a user