/* devRPV130.c */
/* devRPV130.c - Device Support Routines for VME RPV-130 */
/* 8 bit interrupt & I/O register */
/*
* Original Author: M. Tobiyama
* Current Author: M. Tobiyama
* Date:
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1997, KEKB.
*
*
* Modification Log:
* -----------------
* ver0.0 08/Mar/2001 M.Tobiyama
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#include <string.h>
#include <iv.h>
#include <vme.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <recSup.h>
#include <devSup.h>
#include <devCamac.h>
#include <link.h>
#include <module_types.h>
#include <fast_lock.h>
#include <longinRecord.h>
#include <longoutRecord.h>
#include <boRecord.h>
#include <biRecord.h>
#include <mbbiDirectRecord.h>
#include <mbboDirectRecord.h>
#include <dbScan.h>
/* #define INT_LEVEL 0x05 */
struct DRPV130 {
unsigned short latch1;
unsigned short latch2;
unsigned short ff;
unsigned short through;
unsigned short pulse;
unsigned short level;
unsigned short csr1;
unsigned short csr2;
};
#define Status Enable
int devRPV130Config();
static long init_all();
static long init_mi_record();
static long init_mo_record();
static long read_mbbiDirect();
static long write_mbboDirect();
static long init_bo_record();
static long write_bo();
static void rpv130_isr();
static long get_mi_int_info();
static int checkLink();
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mi_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbiDirect;
}devMbbiRPV130={
5,
NULL,
NULL,
init_mi_record,
get_mi_int_info,
read_mbbiDirect};
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mo_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_mbboDirect;
}devMbboRPV130={
5,
NULL,
NULL,
init_mo_record,
NULL,
write_mbboDirect};
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;
}devBoRPV130={
5,
NULL,
NULL,
init_bo_record,
NULL,
write_bo
};
struct ioCard {
volatile struct DRPV130 *card; /* address of this card */
FAST_LOCK lock; /* semaphore */
IOSCANPVT ioscanpvt;/* list or records processed upon interrupt */
};
#define CONST_NUM_LINKS 10
/* #define STATIC */
#define DEBUG_ON
static unsigned short INT_LEVEL = 0x07;
static int debug_flag = 0;
static unsigned long Base_IO;
static int rpv130_num_links;
static unsigned short INT_VEC_BASE;
static struct ioCard cards[CONST_NUM_LINKS];
static int init_flag = 0;
static int int_level;
int devRPV130Config(ncards,a16base,int_level,intvecbase)
int ncards;
long a16base;
int int_level;
int intvecbase;
{
rpv130_num_links = ncards;
Base_IO = a16base;
INT_LEVEL = int_level;
INT_VEC_BASE = intvecbase;
logMsg("RPV130 NumLink= %d BaseIO= %x INT_LEVEL= %x INTVECBASE= %x\n",rpv130_num_links,Base_IO,INT_LEVEL,INT_VEC_BASE);
init_all(0);
}
static long init_all(after)
int after;
{
int cardNum, chanNum;
int i,j;
unsigned char probeVal[2];
unsigned short p1;
volatile struct DRPV130 *p;
if (init_flag != 0 )
return(OK);
init_flag = 1;
if (sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,(char *)Base_IO,(char **)&p) == ERROR)
{
logMsg("VME RPV130: cannot find A16 address space\n");
return(ERROR);
}
for (cardNum=0; cardNum< rpv130_num_links; cardNum++)
{
if (vxMemProbe((char*) &(p->csr1), READ, 2, &probeVal)!=OK)
{
logMsg("No RPV130 with cardNum= %d\n probe= %x\n",cardNum,p);
cards[cardNum].card = NULL;
}
else
{
p->csr1 = 0x01; /* clear all and dissable interrupt */
int_level = INT_LEVEL;
if (debug_flag >0)
logMsg("Found RPV130 with cardNum= %d address= %x\n",cardNum,p);
cards[cardNum].card = p; /* Remember address of the board */
scanIoInit(&cards[cardNum].ioscanpvt);
logMsg("rpv130 ioInit. 0x%X\n",cards[cardNum].ioscanpvt);
FASTLOCKINIT(&(cards[cardNum].lock));
FASTUNLOCK(&(cards[cardNum].lock)); /* Init the board lock */
}
p++;
}
return(OK);
}
static long init_bo_record(pbo)
struct boRecord *pbo;
{
pbo->mask = 1;
return(0);
}
static long write_bo(pbo)
struct boRecord *pbo;
{
short cardN;
unsigned char tgreg;
cardN = pbo->out.value.vmeio.card;
if (checkLink(cardN) == ERROR)
{
logMsg("Error--- No RPV130 for card %d\n",cardN);
return(ERROR);
}
FASTLOCK(&(cards[cardN].lock));
switch(pbo->out.value.vmeio.signal){
case 0: /* clr all, enalble 3 unmask all */
cards[cardN].card->csr1 = 0x01;
cards[cardN].card->csr1 = 0x18;
break;
case 1: /* clr 1 , enable 1 mask 1 */
cards[cardN].card->csr1 = 0x02;
cards[cardN].card->csr1 = 0x18;
break;
case 2: /* clr 2 , enable 2 mask 2 */
cards[cardN].card->csr2 = 0x02;
cards[cardN].card->csr2 = 0x1A;
break;
case 3: /* clr all , enable all mask 1 & 2 */
cards[cardN].card->csr1 = 0x03;
cards[cardN].card->csr2 = 0x03;
cards[cardN].card->csr1 = 0x18;
cards[cardN].card->csr2 = 0x18;
break;
case4 : /* disable latch2 */
cards[cardN].card->csr2 = 0x02;
cards[cardN].card->csr2 = 0x00;
break;
default:
FASTUNLOCK(&(cards[cardN].lock));
return(-1);
}
FASTUNLOCK(&(cards[cardN].lock));
return(0);
}
/******************************************************************
*
* Interrupt service routine
*
*******************************************************************/
static void rpv130_isr(pmbbi)
struct mbbiDirectRecord *pmbbi;
{
unsigned char mode;
short cardN;
cardN = pmbbi->inp.value.vmeio.card;
/* logMsg("rpv130_isr int called \n");*/
scanIoRequest(cards[cardN].ioscanpvt);
/* logMsg("rpv130 int called \n");*/
return;
}
static long init_mi_record(pmbbi)
struct mbbiDirectRecord *pmbbi;
{
short cardNum;
cardNum = pmbbi->inp.value.vmeio.card;
if (intConnect(INUM_TO_IVEC(INT_VEC_BASE + cardNum),
(VOIDFUNCPTR)rpv130_isr,
(int)pmbbi) != OK)
logMsg("devRPV130: Interrupt connect failed for card %d\n",pmbbi->inp.value.vmeio.card);
logMsg("intConnect 0x%X\n",pmbbi);
sysIntEnable(int_level);
logMsg("rpv130 int set for int 0x%x\n",int_level);
/* cards[cardNum].card->csr1 = 0x58; *//* enable 3 mask 1*/
/* cards[cardNum].card->csr2 = 0x58; *//* enable 3 mask 2*/
return(0);
}
static long read_mbbiDirect(pmbbi)
struct mbbiDirectRecord *pmbbi;
{
short cardN;
unsigned short reg1,reg2;
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);
reg1 = (cards[cardN].card-> csr1);
reg2 = (cards[cardN].card-> csr2);
if (debug_flag > 5)
logMsg("reg1 0x%x\n",reg1);
switch(pmbbi->inp.value.vmeio.signal){
case 0: /* set_reset_ff */
pmbbi->rval = (cards[cardN].card->ff) & 0xff;
cards[cardN].card->csr1 = 0x01; /* clr 3 */
cards[cardN].card->csr1 = 0x18; /* enable 1 mask 1 */
break;
case 1: /* through */
pmbbi->rval = (cards[cardN].card->through) & 0xff;
break;
case 2: /* latch1 */
if ((reg1 & 0x20) == 0x20){
pmbbi->rval = (cards[cardN].card->latch1) & 0xff;
cards[cardN].card->csr1 = 0x02; /* clr 1 */
}
cards[cardN].card->csr1 = 0x18; /* enable 1 mask 1 */
break;
case 3: /* latch2 */
if ((reg2 & 0x20) == 0x20){
pmbbi->rval = (cards[cardN].card->latch2) & 0xff;
cards[cardN].card->csr2 = 0x02; /* clr 2 */
}
cards[cardN].card->csr2 = 0x18; /* enable 2 mask 2 */
break;
case 4: /* csr1 */
pmbbi->rval = reg1 & 0xff;
break;
case 5: /* csr2 */
pmbbi->rval = reg2 & 0xff;
break;
default:
return(-1);
}
if (debug_flag >5)
logMsg("read complete \n");
return(CONVERT);
}
#define ADDING 0
#define DELETING 1
static long get_mi_int_info(cmd,pmbbi,ppvt)
int cmd;
struct mbbiDirectRecord *pmbbi;
IOSCANPVT *ppvt;
{
short cardN;
cardN = pmbbi->inp.value.vmeio.card;
*ppvt = cards[cardN].ioscanpvt;
logMsg("rpv130 intInfo. 0x%X\n",*ppvt);
cards[cardN].card->csr1 = 0x0; /* disable all interrupt */
cards[cardN].card->csr2 = 0x0;
if (debug_flag >0) logMsg("MI_INT CALLED\n");
return(0);
}
static long init_mo_record(pmbbo)
struct mbboDirectRecord *pmbbo;
{
return(0);
}
static long write_mbboDirect(pmbbo)
struct mbboDirectRecord *pmbbo;
{
short cardN;
cardN = pmbbo->out.value.vmeio.card;
if (debug_flag >5)
logMsg("write_mbboDirect called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
FASTLOCK(&(cards[cardN].lock));
if (debug_flag >5)
logMsg("card locked...\n");
switch(pmbbo->out.value.vmeio.signal){
case 0: /* pulse */
cards[cardN].card->pulse = pmbbo->rval;
pmbbo->rbv=pmbbo->rval;
break;
case 1: /* level */
cards[cardN].card->level = pmbbo->rval;
pmbbo->rbv=pmbbo->rval;
break;
case 2: /* csr1 */
cards[cardN].card->csr1 = (pmbbo->rval);
pmbbo->rbv=pmbbo->rval;
break;
case 3 : /* csr2 */
cards[cardN].card->csr2 = pmbbo->rval;
pmbbo->rbv = pmbbo->rval;
break;
default:
FASTUNLOCK(&(cards[cardN].lock));
return(-1);
}
if (debug_flag >5)
logMsg("write complete \n");
FASTUNLOCK(&(cards[cardN].lock));
if (debug_flag >5)
logMsg("unlock card ...\n");
return(CONVERT);
}
/**************************************************************************
*
* Make sure card number is valid
*
**************************************************************************/
static int checkLink(cardN)
short cardN;
{
if (cardN >= rpv130_num_links)
return(ERROR);
if (cards[cardN].card == NULL)
{
logMsg("No RPV130 with this number = %d\n",cardN);
return(ERROR);
}
if (debug_flag >10)
logMsg("Yes you have RPV130 with card No= %d\n",cardN);
return(OK);
}