/* devVmeTd4v.c */
/* devVmeTd4v.c - Device Support Routines for VME TD-4V */
/*
* Original Author: Akiyama
* Current Author:
* Date: 2th May 1997
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1997, KEKB.
*
*
* Modification Log:
* -----------------
* 5-8-97 ak
* 27-Oct-97 Makoto 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>
/* #define Base_IO 0x20000 */ /* Std. I/O Address */
struct DvmeTd4v {
unsigned short PreSet;
unsigned short Dummy0;
unsigned short Enable;
unsigned short Dummy1;
unsigned short Last_PreSet;
unsigned short Dummy2;
unsigned short Dummy3;
unsigned short Dummy4;
};
#define Status Enable
static long init();
static long init_record();
static long read_longin();
static long write_longout();
static long init_bi_record();
static long init_bo_record();
static long read_bi();
static long write_bo();
static int checkLink();
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_longin;
DEVSUPFUN special_linconv;
}devLiTd4v={
6,
NULL,
init,
init_record,
NULL,
read_longin,
NULL};
/* Create the dset for devLoTd4v */
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout;
DEVSUPFUN special_linconv;
}devLoTd4v={
6,
NULL,
NULL,
NULL,
NULL,
write_longout,
NULL};
/* Create the dset for devBoTd4v */
struct {
long number;
DEVSUPFUN report; /* used by dbior */
DEVSUPFUN init; /* called 1 time before & after all records */
DEVSUPFUN init_record; /* called 1 time for each record */
DEVSUPFUN get_ioint_info; /* used for COS processing (not used for outputs)*/
DEVSUPFUN write_bo; /* output command goes here */
}devBoTd4v={
5,
NULL,
NULL,
init_bo_record,
NULL,
write_bo
};
/* Create the dset for devBiTd4V */
struct {
long number;
DEVSUPFUN report; /* used by dbior */
DEVSUPFUN init; /* called 1 time before & after all records */
DEVSUPFUN init_record; /* called 1 time for each record */
DEVSUPFUN get_ioint_info; /* used for COS processing */
DEVSUPFUN read_bi; /* input command goes here */
}devBiTd4v={
5,
NULL,
NULL,
init_bi_record,
NULL,
read_bi
};
struct ioCard {
volatile struct DvmeTd4v *card; /* address of this card */
FAST_LOCK lock; /* semaphore */
};
#define CONST_NUM_LINKS 10
/* #define STATIC */
#define DEBUG_ON
int debug_flag = 0;
static unsigned long Base_IO;
static int td4v_num_links;
static struct ioCard cards[CONST_NUM_LINKS];
static int init_flag = 0;
int devTd4vConfig(ncards,a24base)
int ncards;
long a24base;
{
td4v_num_links = ncards;
Base_IO = a24base;
printf("VmeTd4 NumLink= %d BaseIO= %x\n",td4v_num_links,Base_IO);
init(0);cd
}
static long init(after)
int after;
{
int cardNum, chanNum;
unsigned char probeVal[2];
volatile struct DvmeTd4v *p;
if (init_flag != 0 )
return(OK);
init_flag = 1;
if (sysBusToLocalAdrs(VME_AM_STD_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
{
printf("VmeTd4v: cannot find standard address space\n");
return(ERROR);
}
#ifdef DEBUG_ON
if ( CDEBUG)printf("devLiTd4v (init) Called. pass = %d\n", after);
#endif
for (cardNum=0; cardNum< td4v_num_links; cardNum++)
{
if (vxMemProbe((char*) &(p->PreSet), READ, 2, &probeVal[0])< OK)
{
if (debug_flag >0 )
printf("No TD4V with cardNum= %d\n probe= %x\n",cardNum,p);
cards[cardNum].card = NULL;
}
else
{
if (debug_flag >0)
printf("Found TD4V 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_record(plongin)
struct longinRecord *plongin;
{
return(0);
}
static long read_longin(plongin)
struct longinRecord *plongin;
{
short cardN;
if (debug_flag >0)
printf("read_longin called...\n");
cardN = plongin->inp.value.vmeio.card;
if (debug_flag >0)
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:
plongin->val = cards[cardN].card->PreSet;
if (debug_flag >0)
printf("read_longin signal 0 Preset %d\n",
plongin->val);
break;
case 1:
plongin->val = cards[cardN].card->Last_PreSet;
if (debug_flag >0)
printf("read_longin signal 1 Last Preset %d\n",
plongin->val);
break;
default:
return(-1);
}
return(CONVERT);
}
static long write_longout(plongout)
struct longoutRecord *plongout;
{
short cardN;
cardN = plongout->out.value.vmeio.card;
if (debug_flag >0)
printf("write_longout called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
FASTLOCK(&(cards[cardN].lock));
if (debug_flag >0)
printf("card locked...\n");
cards[cardN].card->PreSet = plongout->val;
if (debug_flag >0)
printf("write complete \n");
FASTUNLOCK(&(cards[cardN].lock));
if (debug_flag >0)
printf("unlock card ...\n");
return(CONVERT);
}
/**************************************************************************
*
* 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)
{
printf("Error--- No TD4V for card %d\n",cardN);
return(ERROR);
}
FASTLOCK(&(cards[cardN].lock));
cards[cardN].card->Enable = pbo->rval & pbo->mask;
FASTUNLOCK(&(cards[cardN].lock));
return(0);
}
/**************************************************************************
*
* BI Initialization (Called one time for each BI PowerUT card record)
*
**************************************************************************/
static long
init_bi_record(pbi)
struct biRecord *pbi;
{
pbi->mask = 1;
return(0);
}
/**************************************************************************
*
* Perform a read operation from a BI record
*
**************************************************************************/
static long
read_bi(pbi)
struct biRecord *pbi;
{
short cardN;
cardN = pbi->inp.value.vmeio.card;
if (checkLink(cardN) == ERROR)
return(ERROR);
pbi->rval = cards[cardN].card->Enable & pbi->mask;
return(0);
}
/**************************************************************************
*
* Make sure card number is valid
*
**************************************************************************/
static int checkLink(cardN)
short cardN;
{
if (cardN >= td4v_num_links)
return(ERROR);
if (cards[cardN].card == NULL)
{
printf("No TD4V with this number = %d\n",cardN);
return(ERROR);
}
if (debug_flag >0)
printf("Yes you have TD4V with card No= %d\n",cardN);
return(OK);
}