/* devVme17k82.c */
/* devVme17k82.c - Device Support Routines for VME adc board */
/*
* Original Author: Makoto Tobiyama
* Current Author:
* Date: 18/Aug/2003
* Modified
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1997, KEKB.
*
*
* Modification Log:
* -----------------
*/
#include <vxWorks.h>
#include <types.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 <devCamac.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>
struct D17k82 {
unsigned long ch1ch3[262144];
unsigned long ch2ch4[262144];
unsigned long status;
unsigned long dum1[262143];
unsigned long trigger;
unsigned long dummy[262143];
};
#define Status Enable
static long init_all();
static long init_mi_record();
static long init_bo_record();
static long write_bo();
static long read_mbbiDirect();
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 devBo17k82 */
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;
}devBo17k82={
5,
NULL,
NULL,
init_bo_record,
NULL,
write_bo
};
/* For devMbbi17k82 */
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mi_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbiDirect;
}devMbbi17k82={
5,
NULL,
NULL,
init_mi_record,
NULL,
read_mbbiDirect
};
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_write;
DEVSUPFUN conv;
}devWf17k82 ={
6,
NULL,
NULL,
init_wf_record,
NULL,
read_wf_record,
NULL
};
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout;
DEVSUPFUN special_linconv;
}devLo17k82={
6,
NULL,
NULL,
NULL,
NULL,
write_longout,
NULL
};
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_longin;
DEVSUPFUN special_linconv;
}devLi17k82={
6,
NULL,
NULL,
init_li_record,
NULL,
read_longin,
NULL};
struct ioCard {
volatile struct D17k82 *card; /* address of this card */
FAST_LOCK lock; /* semaphore */
};
#define CONST_NUM_LINKS 10
/* #define STATIC */
#define DEBUG_ON
static int debug_flag = 5;
static unsigned long Base_IO;
static int D17k82_num_links;
static struct ioCard cards[CONST_NUM_LINKS];
static int init_flag = 0;
static int mem_size[CONST_NUM_LINKS];
static int ad_ready[CONST_NUM_LINKS];
static long cardstatusA[CONST_NUM_LINKS];
int dev17k82Config(ncards,a32base)
int ncards;
long a32base;
{
D17k82_num_links = ncards;
Base_IO = a32base;
logMsg("dev17k82 NumLink= %d BaseIO= %x\n",D17k82_num_links,Base_IO);
init_all(0);
}
static long init_all(after)
int after;
{
int cardNum, chanNum;
unsigned char probeVal[4];
volatile struct D17k82 *p;
unsigned short mem_pat;
if (init_flag != 0 )
return(OK);
init_flag = 1;
if (sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
{
logMsg("17k82: cannot find extended address space\n");
return(ERROR);
}
for (cardNum=0; cardNum< D17k82_num_links; cardNum++)
{
if (vxMemProbe((char*) &(p->status), READ, 4, &probeVal[0])!= OK)
{
if (debug_flag >0 )
logMsg("No 17k82 with cardNum= %d\n probe= %x\n",cardNum,p);
cards[cardNum].card = NULL;
}
else
{
if (debug_flag >0)
logMsg("Found 17k82 with cardNum= %d\n address= %x\n",cardNum,p);
cards[cardNum].card = p; /* Remember address of the board */
}
cardstatusA[cardNum] = 0x0;
p->status = cardstatusA[cardNum];
FASTLOCKINIT(&(cards[cardNum].lock));
FASTUNLOCK(&(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 17k82 for card %d\n",cardN);
return(ERROR);
}
if (debug_flag>5) logMsg("BO\n");
FASTLOCK(&(cards[cardN].lock));
switch(pbo->out.value.vmeio.signal){
case 0 :{ /* trigger on_off */
if (pbo->rval == 0x0) /* trigger off */
cardstatusA[cardN] = (cardstatusA[cardN] & 0xfffffffe);
else /* trigger on */
cardstatusA[cardN] = (cardstatusA[cardN] | 0x1);
cards[cardN].card->status = cardstatusA[cardN];
break;
}
case 1:{ /* sample internal / external */
if (pbo->rval == 0x1) /* sample internal */
cardstatusA[cardN] = (cardstatusA[cardN] | 0x100);
else /* external */
cardstatusA[cardN] = (cardstatusA[cardN] & 0xfffffeff);
cards[cardN].card->status = cardstatusA[cardN];
break;
}
}
FASTUNLOCK(&(cards[cardN].lock));
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);
if (checkLink(cardN) == ERROR)
return(ERROR);
FASTLOCK(&(cards[cardN].lock));
switch(plongout->out.value.vmeio.signal){
case 0 :{ /* trigger point */
switch(plongout->val){
case 0 : { /* 0 -100% */
cardstatusA[cardN] = (cardstatusA[cardN] & 0xfffff1ff);
cards[cardN].card->status = cardstatusA[cardN];
break;
}
case 1 : { /* 12.5% */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xfffff1ff) | 0x200) ;
cards[cardN].card->status = cardstatusA[cardN];
break;
}
case 2 : { /* 25% */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xfffff1ff) | 0x400) ;
cards[cardN].card->status = cardstatusA[cardN];
break;
}
case 3 : { /* 37.5% */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xfffff1ff) | 0x600) ;
cards[cardN].card->status = cardstatusA[cardN];
break;
}
case 4 : { /* 50% */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xfffff1ff) | 0x800) ;
cards[cardN].card->status = cardstatusA[cardN];
break;
}
case 5 : { /* 62.5% */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xfffff1ff) | 0xA00) ;
cards[cardN].card->status = cardstatusA[cardN];
break;
}
case 6 : { /* 75% */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xfffff1ff) | 0xC00) ;
cards[cardN].card->status = cardstatusA[cardN];
break;
}
case 7 : { /* 87.5% */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xfffff1ff) | 0xE00) ;
cards[cardN].card->status = cardstatusA[cardN];
break;
}
default:{ break;}
break;
}
break;}
case 1: { /* memory capacity */
switch(plongout->val){
case 0 : { /* 2048 */
cardstatusA[cardN] = (cardstatusA[cardN] & 0xffff0fff);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 2048;
break;
}
case 1 : { /* 4096 */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xffff0fff) | 0x1000);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 4096;
break;
}
case 2 : { /* 8192 */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xffff0fff) | 0x2000);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 8192;
break;
}
case 3 : { /* 16384 */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xffff0fff) | 0x3000);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 16384;
break;
}
case 4 : { /* 32768 */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xffff0fff) | 0x4000);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 32768;
break;
}
case 5 : { /* 65536 */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xffff0fff) | 0x5000);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 65536;
break;
}
case 6 : { /* 131072 */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xffff0fff) | 0x6000);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 131072;
break;
}
case 7 : { /* 262144 */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xffff0fff) | 0x7000);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 262144;
break;
}
default : { /* 262144 */
cardstatusA[cardN] = ((cardstatusA[cardN] & 0xffff0fff) | 0x7000);
cards[cardN].card->status = cardstatusA[cardN];
mem_size[cardN] = 262144;
break;
}
}
}
}
FASTUNLOCK(&(cards[cardN].lock));
return(CONVERT);
}
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");
cardN = plongin->inp.value.vmeio.card;
if (debug_flag >10)
logMsg("read_longin called with card number of %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
plongin->val = (cards[cardN].card->trigger) & 0x3ffff;
return(CONVERT);
}
static long init_mi_record(pmbbi)
struct MbbiDirectRecord *pmbbi;
{
return(0);
}
static long read_mbbiDirect(pmbbi)
struct mbbiDirectRecord *pmbbi;
{
short cardN;
cardN = pmbbi->inp.value.vmeio.card;
if (debug_flag >5)
logMsg("read_mbbiDirect called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
pmbbi->rval = (cards[cardN].card->status) & 0x7fff;
if (debug_flag >5)
logMsg("mbbi read complete \n");
return(CONVERT);
}
static long init_wf_record(pwf)
struct waveformRecord *pwf;
{
return(0);
}
static long read_wf_record(pwf)
struct waveformRecord *pwf;
{
short cardN;
unsigned long a1;
long ii;
long taddress,sta,t_set,mems,mem_start,start,is;
unsigned short* us_thing = (unsigned 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);
if (checkLink(cardN) == ERROR)
return(ERROR);
if (((((cards[cardN].card->status)>>2) & 0x01) == 0 ) &&
((((cards[cardN].card->status)>>1) & 0x01) ==1)){
logMsg("17k82 card %d Memory not ready\n",cardN);
return(ERROR);
}
cardstatusA[cardN] = (cardstatusA[cardN] & 0xfffffffe);
cards[cardN].card->status = cardstatusA[cardN]; /* disable trigger */
taddress = (cards[cardN].card->trigger) & 0x3ffff;
sta = (cards[cardN].card->status) & 0x7fff;
t_set = ((sta & 0xf00) >>9);
mems = 2048 << ((sta & 0xf000)>>12);
mem_start = mems *t_set/8;
start = taddress - mem_start;
if (start < 0) start = start + mems;
switch(pwf->inp.value.vmeio.signal){
case 0: { /* ch1ch3 */
for (ii=0;ii<mems;ii++)
{
is = (ii-start);
if (is <0) is += mems;
(unsigned long)a1 = (unsigned long)(cards[cardN].card->ch1ch3[ii]);
us_thing[is] = (unsigned short)(a1 & 0xfff);
us_thing[is+262144] = (unsigned short)((a1>>16) & 0xfff);
/* if (is<10) logMsg("ch1ch3 %d %x\n",is,a1); */
}
pwf->nord = 524288;
break;
}
case 1: { /* ch2ch4 */
for (ii=0;ii<mems;ii++)
{
is = (ii-start);
if (is <0) is += mems;
(unsigned long)a1 = (unsigned long)(cards[cardN].card->ch2ch4[ii]);
us_thing[is] = (unsigned short)(a1 & 0xfff);
us_thing[is+262144] = (unsigned short)((a1>>16) & 0xfff);
if ((debug_flag >10 ) && (ii<40)){
logMsg("ii= %d down %d up %d\n",ii,us_thing[ii],us_thing[ii+262144]);
}
}
pwf->nord = 524288;
/* cardstatusA[cardN] = (cardstatusA[cardN] | 0x1); *//* enable trigger */
/* cards[cardN].card->status = cardstatusA[cardN]; */
break;
}
default : logMsg("Invalid Signal\n");
}
/* cards[cardN].card->status = 0x1; */
if (debug_flag >5) logMsg("17k82 card %d end of read\n",cardN);
return(0);
}
/**************************************************************************
*
* Make sure card number is valid
*
**************************************************************************/
static int checkLink(cardN)
short cardN;
{
if (cardN >= D17k82_num_links)
return(ERROR);
if (cards[cardN].card == NULL)
{
logMsg("No 17K82 with this number = %d\n",cardN);
return(ERROR);
}
if (debug_flag >10)
logMsg("Yes you have 17k82 with card No= %d\n",cardN);
return(OK);
}