/* devVme18k14.c */
/* devVme18k14.c - Device Support Routines for VME 64 ch adc board */
/*
 *    
 *      Original Author: Makoto Tobiyama
 *      Current Author:
 *      Date:            10/Sep/2013
 *
 *      Experimental Physics and Industrial Control System (EPICS)
 *
 *      Copyright 1997, KEKB.
 *
 *
 * Modification Log:
 * -----------------
 */


#include<vxWorks.h>
#include <vxLib.h>#include <logLib.h> #include <sysLib.h> /* #include <memLib.h> */ #include <intLib.h>
#include<types.h>
#include <stdio.h>
#include<stdioLib.h>
#include<string.h>
/* #include <sys/time.h> */
#include<vme.h>
#include<dbDefs.h>
#include<dbAccess.h>
#include<recSup.h>
#include<devSup.h>
#include<link.h>
#include <iv.h>
#include<module_types.h>
#include<longinRecord.h>
#include<longoutRecord.h>
#include<boRecord.h>
#include<biRecord.h>
#include<mbbiDirectRecord.h>
#include<mbboDirectRecord.h>
#include<waveformRecord.h>
#include <stringoutRecord.h>
#include<dbScan.h>
#include <epicsMutex.h>#include <epicsExport.h> #include <vxLib.h> #include <time.h> struct D18k14 { unsigned long mean[32]; unsigned long peak[32]; unsigned long mini[32]; unsigned long curr[32]; unsigned long math_enb; unsigned long math_size; unsigned long math_single; unsigned long math_end; unsigned long status; unsigned long adc_sw; unsigned long irq_id; unsigned long irq_no; unsigned long irqenb; unsigned long sync; unsigned long dum2; unsigned long dum3; unsigned long res1; unsigned long ave_mode; unsigned long res2; unsigned long fpga_ver; unsigned long dum4[112]; };
#defineStatusEnable
static long init_all(); static long init_bo_record(); static long write_bo(); static long init_bi_record(); static long read_bi(); static long init_wf_record(); static long read_wf_record(); static long init_lo_record(); static long write_longout(); static long init_li_record(); static long read_longin(); static int checkLink(); /* Create the dset for devBo18k14 */ struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN write_bo; }devBo18k14={ 5, NULL, NULL, init_bo_record, NULL, write_bo }; epicsExportAddress(dset,devBo18k14); /* Create the dset for devBi18k14 */ struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_bi; }devBi18k14={ 5, NULL, NULL, init_bi_record, NULL, read_bi }; epicsExportAddress(dset,devBi18k14); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_write; DEVSUPFUN conv; }devWf18k14 ={ 6, NULL, NULL, init_wf_record, NULL, read_wf_record, NULL }; epicsExportAddress(dset,devWf18k14); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN write_longout; DEVSUPFUN special_linconv; }devLo18k14={ 6, NULL, NULL, init_lo_record, NULL, write_longout, NULL }; epicsExportAddress(dset,devLo18k14); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_longin; DEVSUPFUN special_linconv; }devLi18k14={ 6, NULL, NULL, init_li_record, NULL, read_longin, NULL}; epicsExportAddress(dset,devLi18k14); struct ioCard { volatile struct D18k14 *card; /* address of this card */ epicsMutexId lock; /* semaphore */ }; #define CONST_NUM_LINKS 10 /* #define STATIC */ #define DEBUG_ON static int debug_flag = 5; static unsigned long Base_IO; static int D18k14_num_links; static struct ioCard cards[CONST_NUM_LINKS]; static int init_flag = 0; int dev18k14Config(ncards,a32base) int ncards; long a32base; { D18k14_num_links = ncards; Base_IO = a32base; logMsg("dev18k14 NumLink= %d BaseIO= %x\n",D18k14_num_links,Base_IO,0,0,0,0); init_all(0); return 0; } static long init_all(after) int after; { int cardNum; unsigned char probeVal[4]; volatile struct D18k14 *p; if (init_flag != 0 ) return(OK); init_flag = 1; if (sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
{ logMsg("18k14: cannot find extended address space\n",0,0,0,0,0,0); return(ERROR); }
/* if (debug_flag >0) logMsg("18k14 address %x\n",(int)p,0,0,0,0,0); */ for (cardNum=0; cardNum< D18k14_num_links; cardNum++) { if (vxMemProbe((char*) &(p->status), READ, 4, (char *)&probeVal[0])!= OK) {
if (debug_flag >0 )
logMsg("No 18k14 with cardNum= %d\n probe= %x\n",cardNum,(int)p,0,0,0,0);
cards[cardNum].card = NULL;
} else {
if (debug_flag >0)
logMsg("Found 18k14 with cardNum= %d\n address= %x\n",cardNum,(int)p,0,0,0,0);
cards[cardNum].card = p; /* Remember address of the board */
} cards[cardNum].lock = epicsMutexMustCreate(); epicsMutexUnlock((cards[cardNum].lock)); /* Init the board lock */ p++; } return(OK); } /************************************************************************** * * BO Initialization (Called one time for each BO PowerUT card record) * **************************************************************************/ static long init_bo_record(pbo) struct boRecord *pbo; { pbo->mask = 1;
return(0);
} /************************************************************************** * * Perform a write operation from a BO record * **************************************************************************/ static long write_bo(pbo) struct boRecord *pbo; { short cardN; cardN = pbo->out.value.vmeio.card; if (checkLink(cardN) == ERROR) { logMsg("Error--- No 18k14 for card %d\n",cardN,0,0,0,0,0); return(ERROR); } if (debug_flag>5) logMsg("BO\n",0,0,0,0,0,0); epicsMutexMustLock((cards[cardN].lock)); switch(pbo->out.value.vmeio.signal){ case 0 : /* math enable 1: enable */ cards[cardN].card->math_enb = pbo->val & 0x1; break; case 1 : /* math_single 1: for debug */ cards[cardN].card->math_single = pbo->val & 0x1; break; case 2 : /* irqenb 1 : enable */ cards[cardN].card->irqenb = pbo->val &0x1; break; case 3 : /* ave_mode 1: round, 0 : cut */ cards[cardN].card->ave_mode = pbo->val &0x1; break; case 4 : /* soft sync */ cards[cardN].card->sync = 0x1; break; default : break; } epicsMutexUnlock((cards[cardN].lock)); return(0); } static long init_bi_record(pbi) struct biRecord *pbi; { pbi->mask=0x1; return(0); } static long read_bi(pbi) struct biRecord *pbi; { short cardN; cardN = pbi->inp.value.vmeio.card; if (checkLink(cardN) == ERROR) return(ERROR); switch(pbi->inp.value.vmeio.signal){ case 0: pbi->rval = cards[cardN].card->math_enb & pbi->mask; break; case 1: pbi->rval = cards[cardN].card->math_single & pbi->mask; break; case 2: pbi->rval = cards[cardN].card->math_end & pbi->mask; break; case 3: pbi->rval = cards[cardN].card->irqenb & pbi->mask; break; case 4: pbi->rval = cards[cardN].card->ave_mode & pbi->mask; break; default: break; } return(0); } static long init_lo_record(plongout) struct longoutRecord *plongout; { return(0); } static long write_longout(plongout) struct longoutRecord *plongout; { short cardN; cardN = plongout->out.value.vmeio.card; if (debug_flag >10) logMsg("write_lo called with card %d\n",cardN,0,0,0,0,0); if (checkLink(cardN) == ERROR) return(ERROR); epicsMutexMustLock((cards[cardN].lock)); switch(plongout->out.value.vmeio.signal){ case 0 : /* math size */
cards[cardN].card->math_size = 0x3 & (plongout->val); break;
default: break; } epicsMutexUnlock((cards[cardN].lock)); return(0); } static long init_li_record(plongin) struct longinRecord *plongin; { return(0); } static long read_longin(plongin) struct longinRecord *plongin; { short cardN; if (debug_flag >10) logMsg("read_longin called...\n",0,0,0,0,0,0); cardN = plongin->inp.value.vmeio.card; if (checkLink(cardN) == ERROR) return(ERROR); switch(plongin->inp.value.vmeio.signal){ case 0: /* math size */ plongin->val = (cards[cardN].card->math_size) & 0x3; break; case 1: /* status */ plongin->val = (cards[cardN].card->status) & 0x7; break; case 2: /* adc_switch */ plongin->val = (cards[cardN].card->adc_sw) & 0xff; break; case 3 : /* irq_id */ plongin->val = (cards[cardN].card->irq_id) & 0xff; break; case 4: /* IRQ_NO */ plongin->val = (cards[cardN].card->irq_no) & 0x7; default: break; } return(OK); } static long init_wf_record(pwf)
struct waveformRecord*pwf;
{ /* short cardNum; cardNum = pwf->inp.value.vmeio.card; if (intConnect(INUM_TO_IVEC(INT_VEC_BASE + cardNum),
(VOIDFUNCPTR)vme18k14_isr, (int)pwf) != OK)
logMsg("devVme18k14: Interrupt connect failed for card %d\n",pwf->inp.value.vmeio.card); logMsg("intConnect 0x%x\n",pwf);
sysIntEnable(int_level); logMsg("devVme18k14 int set for int 0x%x\n",int_level); */ return(0); } static long read_wf_record(pwf)
struct waveformRecord*pwf;
{ short cardN; unsigned long a1; long ii; short* s_thing = (short*)pwf->bptr; cardN = pwf->inp.value.vmeio.card; if (debug_flag >5) logMsg("read_wf_record called with card number of %d\n",cardN,0,0,0,0,0); if (checkLink(cardN) == ERROR) return(ERROR); switch(pwf->inp.value.vmeio.signal){ case 0: { /* avarage channel */ for (ii=0;ii<32;ii++) {
a1 = (unsigned long)(cards[cardN].card->mean[ii]); s_thing[ii*2] = (short)((a1>>16) & 0xffff);
s_thing[ii*2+1] = (short)(a1 & 0xffff); } pwf->nord = 64; break; } case 1: { /* peak */ for (ii=0;ii<32;ii++) {
a1 = (unsigned long)(cards[cardN].card->peak[ii]); s_thing[ii*2] = (short)((a1>>16) & 0xffff);
s_thing[ii*2+1] = (short)(a1 & 0xffff); } pwf->nord = 64; break; } case 2: { /* mini */ for (ii=0;ii<32;ii++) {
a1 = (unsigned long)(cards[cardN].card->mini[ii]); s_thing[ii*2] = (short)((a1>>16) & 0xffff);
s_thing[ii*2+1] = (short)(a1 & 0xffff); } pwf->nord = 64; break; } case 3: { /* curr */ for (ii=0;ii<32;ii++) {
a1 = (unsigned long)(cards[cardN].card->curr[ii]); s_thing[ii*2] = (short)((a1>>16) & 0xffff);
s_thing[ii*2+1] = (short)(a1 & 0xffff); } pwf->nord = 64; break; } default : logMsg("Invalid Signal\n",0,0,0,0,0,0); } if (debug_flag >5) logMsg("18k14 card %d end of read\n",cardN,0,0,0,0,0); return(0); } /* static long get_wf_int_info(cmd,pwf,ppvt) int cmd; struct waveformRecord *pwf; IOSCANPVT *ppvt; { short cardN; unsigned char stat; cardN = pwf->inp.value.vmeio.card; *ppvt = cards[cardN].ioscanpvt; if (debug_flag >5) logMsg("wf_INT CALLED\n"); return(0); } */ /************************************************************************** * * Make sure card number is valid * **************************************************************************/ static int checkLink(cardN) short cardN; { if (cardN >= D18k14_num_links) return(ERROR); if (cards[cardN].card == NULL) { logMsg("No 18K14 with this number = %d\n",cardN,0,0,0,0,0); return(ERROR); } if (debug_flag >10) logMsg("Yes you have 18k14 with card No= %d\n",cardN,0,0,0,0,0); return(OK); }