diff --git a/src/drv/drvKscV215.c b/src/drv/drvKscV215.c new file mode 100644 index 000000000..5158bac9b --- /dev/null +++ b/src/drv/drvKscV215.c @@ -0,0 +1,404 @@ +/* + * 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: + * ----------------- + * + */ + + +#include +#ifdef V5_vxWorks +# include <68k/iv.h> +#else +# include +#endif +#include +#include +#include +#include +#include + +#define LOCAL + +#define VXI_MODEL_KSCV215 (0x215) + +#define MAXTRIES 100 + +#define KSCV215_PCONFIG(LA) \ +epvxiPConfig((LA), KscV215DriverId, struct KscV215_config *) + +#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 */ +}; + +#define KSCV215_INT_LEVEL 1 +#define KscV215Handshake (0x0040) +#define KscV215csrInit (0x9000) + +LOCAL +int KscV215DriverId; + +void KscV215_int_service(); +void KscV215_init_card(); +void KscV215_stat(); +int KscV215WriteSync(); + + +struct KscV215_A24{ + unsigned short diag; + unsigned short isr; + unsigned short pad1[7]; + unsigned short channels[64]; /* odd access causes a bus error ? */ + unsigned short controlMemoryAddr; + unsigned short pad2; + unsigned short controlMemoryDataWrite; + unsigned short pad3; + unsigned short controlMemoryDataRead; + unsigned short pad4; + unsigned short lastChannel; + unsigned short pad5; + unsigned short singleScan; + unsigned short pad6; + unsigned short stopScan; + unsigned short pad7; + unsigned short clearControlMemoryAddr; + unsigned short pad8; + unsigned short enableContinuousScanning; + unsigned short pad9; + unsigned short disableContinuousScanning; + unsigned short pad10; + unsigned short enableDoneInt; + unsigned short pad11; + unsigned short disbaleDoneInt; + unsigned short pad12; + unsigned short clearDoneInt; + unsigned short pad13; + unsigned short testDoneInt; + unsigned short pad14; +}; + + +/* + * KscV215_init + * + * initialize all KscV215 cards + * + */ +KscV215Init() +{ + int r0; + + /* + * do nothing on crates without VXI + */ + if(!epvxiResourceMangerOK){ + return ERROR; + } + + KscV215DriverId = vxiUniqueDriverID(); + + { + 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<0){ + return ERROR; + } + } + + return OK; +} + + + +/* + * KSCV215_INIT_CARD + * + * initialize single at5vxi card + * + */ +LOCAL void +KscV215_init_card(la) +unsigned la; +{ + int status; + int i; + struct KscV215_config *pc; + struct KscV215_A24 *pA24; + struct vxi_csr *pcsr; + + status = epvxiOpen( + la, + KscV215DriverId, + (unsigned long) sizeof(*pc), + KscV215_stat); + if(status<0){ + logMsg("KscV215: device open failed %d\n", la); + return; + } + + pc = KSCV215_PCONFIG(la); + if(pc == NULL){ + epvxiClose(la, KscV215DriverId); + return; + } + + pA24 = epvxiA24Base(la); + pcsr = VXIBASE(la); + + pcsr->dir.w.control = KscV215csrInit; + + status = KscV215WriteSync(pA24, &pA24->controlMemoryAddr, 0); + if(status<0){ + epvxiClose(la, KscV215DriverId); + logMsg("KscV215 init failed\n"); + return; + } + for(i=0; i<(NELEMENTS(pA24->channels)/2); i++){ + status = KscV215WriteSync( + pA24, + &pA24->controlMemoryDataWrite, + 0); + if(status<0){ + epvxiClose(la, KscV215DriverId); + logMsg("KscV215 init failed\n"); + return; + } + } + + /* + * turn on continuous scan mode + */ + status = KscV215WriteSync( + pA24, + &pA24->enableContinuousScanning, + 0); + if(status<0){ + epvxiClose(la, KscV215DriverId); + logMsg("KscV215 init failed- device left open\n"); + return; + } + + FASTLOCKINIT(&pc->lock); + +#ifdef INTERRUPTS + r0 = intConnect( + (unsigned char) INUM_TO_IVEC(la), + KscV215_int_service, + (void *) la); + if(r0 == ERROR) + return; + sysIntEnable(KSCV215_INT_LEVEL); +#endif + + +} + + +/* + * + * KscV215WriteSync + * + * + */ +LOCAL int +KscV215WriteSync(pA24, preg, val) +struct KscV215_A24 *pA24; +unsigned short *preg; +unsigned short val; +{ + int i; + + for(i=0; idiag & KscV215Handshake){ + return OK; + } + taskDelay(1); + } + + logMsg("KscV215 timed out\n"); + + return ERROR; +} + + +/* + * + * KscV215_int_service() + * + * + * This device interrupts once the + * switches have settled + * + */ +#ifdef INTERRUPTS +LOCAL void +KscV215_int_service(la) +unsigned la; +{ + struct KscV215_config *pc; + + pc = KSCV215_PCONFIG(la); + if(pc == NULL){ + return; + } + + /* + * operation completed so we can update + * the shadow value + */ + + /* + * tell them that the switches have settled + */ + io_scanner_wakeup(IO_AI, KSCV215_BI, la); +} +#endif + + +/* + * KSCV215_STAT + * + * initialize single at5vxi card + * + */ +LOCAL void +KscV215_stat(la,level) +unsigned la; +int level; +{ + struct KscV215_config *pc; + struct vxi_csr *pcsr; + struct KscV215_A24 *pA24; + int i; + + pc = KSCV215_PCONFIG(la); + if(pc == 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 + */ +int +KscV215_ai_driver(la,chan,prval) +register unsigned short la; +unsigned short chan; +register unsigned short *prval; +{ + struct KscV215_config *pc; + struct vxi_csr *pcsr; + struct KscV215_A24 *pA24; + long tmp; + int i; + + pc = KSCV215_PCONFIG(la); + if(pc == NULL){ + return ERROR; + } + pcsr = VXIBASE(la); + + pA24 = epvxiA24Base(la); + + if(chan >= NELEMENTS(pA24->channels)/2) + return ERROR; + + for(i=0; ichannels[chan<<1]; + if(pA24->diag & KscV215Handshake){ + tmp = tmp + 0xffff; + tmp = tmp >> 4; + tmp &= 0xfff; + *prval = tmp; + return OK; + } + taskDelay(1); + } + + return ERROR; +}