/* devPVME501.c */
/* devPVME501.c - Device Support Routines for VME PVME-501 */
/* general I/O (40 bits I/O) */
/*
* Original Author: M. Tobiyama
* Current Author: M. Tobiyama
* Date:
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1997, KEKB.
*
*
* Modification Log:
* -----------------
* ver0.0 11/Jul/98 M.Tobiyama
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#include <string.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 <longinRecord.h>
#include <longoutRecord.h>
#include <boRecord.h>
#include <biRecord.h>
#include <mbbiDirectRecord.h>
#include <mbboDirectRecord.h>
/* #define Base_IO 0x20000 */ /* Std. I/O Address */
#define UTREG 0x00
#define BM1REG 0x00
#define BM2REG 0x00
#define ETREG 0x00
#define UVEC 0x00
#define BM1VEC 0x00
#define BM2VEC 0x00
#define ETVEC 0x00
#define CKCREG 0x34
#define PMCREG 0x74
#define UTCREG 0xB4
#define C0ENAB 0x00
#define C1ENAB 0x00
#define C2ENAB 0x00
#define IOD1 0x00
#define IOD2 0x1F
#define PMCOMP 0x00
#define PORTCP 0x00
#define PORTDP 0x00
#define PATEQ 0x00
#define PORTEN1 0x1F
#define PORTEN2 0x1F
struct DPvme501 {
char dummy00;
char bim_cntlreg0;
char dummy0;
char bim_cntlreg1;
char dummy1;
char bim_cntlreg2;
char dummy2;
char bim_cntlreg3;
char dummy3;
char bim_vecreg0;
char dummy4;
char bim_vecreg1;
char dummy5;
char bim_vecreg2;
char dummy6;
char bim_vecreg3;
char dummy7;
char timer_counter0;
char dummy8;
char timer_counter1;
char dummy9;
char timer_counter2;
char dummy10;
char timer_cntlreg;
char dummy11;
char timer_gate0;
char dummy12;
char timer_gate1;
char dummy13;
char timer_gate2;
char dummy14;
char io_reg_a;
char dummy15;
char io_reg_b;
char dummy16;
char comp_pat_cond;
char dummy17;
char pattern_c_reg;
char dummy18;
char pattern_d_reg;
char dummy19;
char pattern_match_out;
char dummy20;
char port_a_enable;
char dummy21;
char port_b_enable;
char dum[14];
unsigned short port_j;
unsigned short port_k;
unsigned short port_ab;
unsigned short port_cd;
unsigned short port_ef;
unsigned short port_gh;
unsigned short dums[92];
};
#define Status Enable
static long init();
static long init_li_record();
static long init_lo_record();
static long init_mi_record();
static long init_mo_record();
static long read_longin();
static long write_longout();
static long read_mbbiDirect();
static long write_mbboDirect();
static int checkLink();
/* for devLiPvme501 */
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_li_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_longin;
DEVSUPFUN special_linconv;
}devLiPvme501={
6,
NULL,
init,
init_li_record,
NULL,
read_longin,
NULL};
/* Create the dset for devLoPvme501 */
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_lo_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout;
DEVSUPFUN special_linconv;
}devLoPvme501={
6,
NULL,
NULL,
NULL,
NULL,
write_longout,
NULL};
/* For devMbbiPvme501 */
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mi_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbiDirect;
}devMbbiPvme501={
5,
NULL,
NULL,
init_mi_record,
NULL,
read_mbbiDirect};
/* For devMbboPvme501 */
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mo_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_mbboDirect;
}devMbboPvme501={
5,
NULL,
NULL,
init_mo_record,
NULL,
write_mbboDirect};
struct ioCard {
volatile struct DPvme501 *card; /* address of this card */
FAST_LOCK lock; /* semaphore */
};
#define CONST_NUM_LINKS 10
/* #define STATIC */
#define DEBUG_ON
static int debug_flag = 1;
static unsigned long Base_IO;
static int pvme501_num_links;
static struct ioCard cards[CONST_NUM_LINKS];
static int init_flag = 0;
int devPvme501Config(ncards,a24base)
int ncards;
long a24base;
{
pvme501_num_links = ncards;
Base_IO = a24base;
printf("Pvme501 NumLink= %d BaseIO= %x\n",pvme501_num_links,Base_IO);
init(0);
}
static long init(after)
int after;
{
int cardNum, chanNum;
unsigned char probeVal;
volatile struct DPvme501 *p;
if (init_flag != 0 )
return(OK);
init_flag = 1;
if (sysBusToLocalAdrs(VME_AM_STD_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
{
printf("VmeP501: cannot find A24 address space\n");
return(ERROR);
}
#ifdef DEBUG_ON
if ( CDEBUG)printf("PVME501 (init) Called. pass = %d\n", after);
#endif
for (cardNum=0; cardNum< pvme501_num_links; cardNum++)
{
probeVal = UTREG;
if (vxMemProbe((char*) &(p->bim_cntlreg0), WRITE, 1, &probeVal)< OK)
{
if (debug_flag >0 )
printf("No PVME501 with cardNum= %d\n probe= %x\n",cardNum,p);
cards[cardNum].card = NULL;
}
else
{
probeVal = BM1REG;
if ((vxMemProbe((char*) &(p->bim_cntlreg1), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d bit pattern reg 1 init\n",cardNum);
probeVal = BM2REG;
if ((vxMemProbe((char*) &(p->bim_cntlreg2), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d bit pattern reg 2 init\n",cardNum);
probeVal = ETREG;
if ((vxMemProbe((char*) &(p->bim_cntlreg3), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d ext trig reg init\n",cardNum);
probeVal = UVEC;
if ((vxMemProbe((char*) &(p->bim_vecreg0), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d user timer int vec init\n",cardNum);
probeVal = BM1VEC;
if ((vxMemProbe((char*) &(p->bim_vecreg1), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d bit pattern 1 int vec init\n",cardNum);
probeVal = BM2VEC;
if ((vxMemProbe((char*) &(p->bim_vecreg2), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d bit pattern 2 int vec init\n",cardNum);
probeVal = ETVEC;
if ((vxMemProbe((char*) &(p->bim_vecreg3), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d ext trig int vec init\n",cardNum);
probeVal = CKCREG;
if ((vxMemProbe((char*) &(p->timer_cntlreg), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d clock timer cntl\n",cardNum);
probeVal = 0xFF;
if ((vxMemProbe((char*) &(p->timer_counter0), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer 0 lower init\n",cardNum);
probeVal = 0xFF;
if ((vxMemProbe((char*) &(p->timer_counter0), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer 0 upper init\n",cardNum);
probeVal = PMCREG;
if ((vxMemProbe((char*) &(p->timer_cntlreg), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d pattern match timer cntl\n",cardNum);
probeVal = 0xFF;
if ((vxMemProbe((char*) &(p->timer_counter1), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer 1 lower init\n",cardNum);
probeVal = 0xFF;
if ((vxMemProbe((char*) &(p->timer_counter1), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer 1 upper init\n",cardNum);
probeVal = UTCREG;
if ((vxMemProbe((char*) &(p->timer_cntlreg), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d user timer cntl\n",cardNum);
probeVal = 0xFF;
if ((vxMemProbe((char*) &(p->timer_counter2), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer 2 lower init\n",cardNum);
probeVal = 0xFF;
if ((vxMemProbe((char*) &(p->timer_counter2), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer 2 upper init\n",cardNum);
probeVal = C0ENAB;
if ((vxMemProbe((char*) &(p->timer_gate0), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer gate0 init\n",cardNum);
probeVal = C1ENAB;
if ((vxMemProbe((char*) &(p->timer_gate1), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer gate1 init\n",cardNum);
probeVal = C2ENAB;
if ((vxMemProbe((char*) &(p->timer_gate2), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d timer gate2 init\n",cardNum);
probeVal = IOD1;
if ((vxMemProbe((char*) &(p->io_reg_a), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d I/O direction for ABCDJ init\n",cardNum);
probeVal = IOD2;
if ((vxMemProbe((char*) &(p->io_reg_b), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d I/O direction for EFGHK init\n",cardNum);
probeVal = PMCOMP;
if ((vxMemProbe((char*) &(p->comp_pat_cond), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d comparation cond init\n",cardNum);
probeVal = PORTCP;
if ((vxMemProbe((char*) &(p->pattern_c_reg), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d port C comp pattern init\n",cardNum);
probeVal = PORTDP;
if ((vxMemProbe((char*) &(p->pattern_d_reg), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d port D comp pattern init\n",cardNum);
probeVal = PATEQ;
if ((vxMemProbe((char*) &(p->pattern_match_out), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d pattern match out init\n",cardNum);
probeVal = PORTEN1;
if ((vxMemProbe((char*) &(p->port_a_enable), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d port ABCDJ enable init\n",cardNum);
probeVal = PORTEN2;
if ((vxMemProbe((char*) &(p->port_b_enable), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d port EFGHK enable init\n",cardNum);
if (debug_flag >0)
printf("Found PVME501 with cardNum= %d\n address= %x\n",cardNum,p);
cards[cardNum].card = p; /* Remember address of the board */
FASTLOCKINIT(&(cards[cardNum].lock));
FASTUNLOCK(&(cards[cardNum].lock)); /* Init the board lock */
}
p++;
}
return(OK);
}
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)
printf("write_mbboDirect called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
FASTLOCK(&(cards[cardN].lock));
if (debug_flag >5)
printf("card locked...\n");
switch(pmbbo->out.value.vmeio.signal){
case 0: /* Port EF */
cards[cardN].card->port_ef = pmbbo->rval;
pmbbo->rbv=cards[cardN].card->port_ef;
break;
case 1: /* Port GH */
cards[cardN].card->port_gh = pmbbo->rval;
pmbbo->rbv=cards[cardN].card->port_gh;
break;
case 2: /* Port k */
cards[cardN].card->port_k = ((pmbbo->rval) & (0xff));
pmbbo->rbv=((cards[cardN].card->port_gh) & (0xff));
break;
default:
FASTUNLOCK(&(cards[cardN].lock));
return(-1);
}
if (debug_flag >5)
printf("write complete \n");
FASTUNLOCK(&(cards[cardN].lock));
if (debug_flag >0)
printf("unlock card ...\n");
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)
printf("read_mbbiDirect called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
switch(pmbbi->inp.value.vmeio.signal){
case 0: /* port AB */
pmbbi->rval = cards[cardN].card->port_ab;
break;
case 1: /* port CD */
pmbbi->rval = cards[cardN].card->port_cd;
break;
case 2: /* port J */
pmbbi->rval = ((cards[cardN].card->port_j) & (0xff));
break;
default:
return(-1);
}
if (debug_flag >5)
printf("read complete \n");
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 >5)
printf("read_longin called...\n");
cardN = plongin->inp.value.vmeio.card;
if (debug_flag >5)
printf("read_longin called with card number of %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
switch(plongin->inp.value.vmeio.signal){
case 0: /* port ab */
plongin->val = cards[cardN].card->port_ab;
if (debug_flag >10)
printf("read_longin signal 0 port ab %d\n",
plongin->val);
break;
case 1: /* port cd */
plongin->val = cards[cardN].card->port_cd;
if (debug_flag >10)
printf("read_longin signal 1 port cd %d\n",
plongin->val);
break;
case 2: /* port j */
plongin->val = cards[cardN].card->port_j;
if (debug_flag >10)
printf("read_longin signal 2 port j %d\n",
plongin->val);
break;
default:
return(-1);
}
return(CONVERT);
}
static long init_lo_record(plongin)
struct longinRecord *plongin;
{
return(0);
}
static long write_longout(plongout)
struct longoutRecord *plongout;
{
short cardN;
cardN = plongout->out.value.vmeio.card;
if (debug_flag >4)
printf("write_longout called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
FASTLOCK(&(cards[cardN].lock));
if (debug_flag >4)
printf("card locked...\n");
switch(plongout->out.value.vmeio.signal){
case 0: /* port ef */
cards[cardN].card->port_ef = (short)plongout->val;
if (debug_flag >4)
printf("write_longout signal 0 port ef\n");
break;
case 1: /* port gh */
cards[cardN].card->port_gh = (short)plongout->val;
if (debug_flag >4)
printf("write_longout signal 1 port gh\n");
break;
case 2: /* port k */
cards[cardN].card->port_k = (short)plongout->val;
if (debug_flag >4)
printf("write_longout signal 2 port k\n");
break;
default:
return(-1);
}
FASTUNLOCK(&(cards[cardN].lock));
if (debug_flag >4)
printf("unlock card ...\n");
return(CONVERT);
}
/**************************************************************************
*
* Make sure card number is valid
*
**************************************************************************/
static int checkLink(cardN)
short cardN;
{
if (cardN >= pvme501_num_links)
return(ERROR);
if (cards[cardN].card == NULL)
{
printf("No PVME501 with this number = %d\n",cardN);
return(ERROR);
}
if (debug_flag >5)
printf("Yes you have PVME501 with card No= %d\n",cardN);
return(OK);
}