/* devPVME321.c */
/* devPVME321.c - Device Support Routines for VME PVME-321 */
/* 12 bit low cost D/A board (8ch) */
/*
* Original Author: M. Tobiyama
* Current Author: M. Tobiyama
* Date:
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1997, KEKB.
*
*
* Modification Log:
* -----------------
* ver0.0 27/Aug/98 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 <waveformRecord.h>
#include <dbScan.h>
/* #define Base_IO 0x20000 */ /* Std. I/O Address */
#define CNT 0xff
#define FC1 0x34
#define ALLENABLE 0xff
#define ALLDISABLE 0x00
#define TIMER 0x00
struct DPvme321 {
unsigned char func_reg_0;
unsigned char dummy0;
unsigned char dummy1;
unsigned char dummy2;
unsigned char dummy3;
unsigned char dummy4;
unsigned char func_reg_1;
unsigned char dummy5;
unsigned short dummy6;
unsigned short dummy7;
unsigned short dummy8;
unsigned short dummy9;
unsigned short dummy10;
unsigned short dummy11;
unsigned short dummy12;
unsigned short dummy13;
unsigned char dummy14;
unsigned char cntl_reg_0;
unsigned short dummy15;
unsigned short dummy16;
unsigned short dummy17;
unsigned short dummy18;
unsigned short cntl_reg_1;
unsigned char dummy19;
unsigned char cntl_reg_2;
unsigned short dummy20;
unsigned short dummy21;
unsigned short dummy22;
unsigned short dummy23;
unsigned short dummy24;
unsigned short dac_0;
unsigned short dac_1;
unsigned short dac_2;
unsigned short dac_3;
unsigned short dac_4;
unsigned short dac_5;
unsigned short dac_6;
unsigned short dac_7;
};
/* #define Status Enable */
static long init_all();
static long init_mi_record();
static long init_mo_record();
static long write_longout_record ();
static long read_mbbiDirect_record();
static long write_mbboDirect_record();
static int checkLink();
/* Create the dset for devLoPvme321 */
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_lo_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout;
DEVSUPFUN special_linconv;
}devLoPvme321={
6,
NULL,
NULL,
NULL,
NULL,
write_longout_record,
NULL};
/* For devMbbiPvme321 */
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mi_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbiDirect;
}devMbbiPvme321={
5,
NULL,
NULL,
init_mi_record,
NULL,
read_mbbiDirect_record};
/* For devMbboPvme321 */
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mo_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_mbboDirect;
}devMbboPvme321={
5,
NULL,
NULL,
init_mo_record,
NULL,
write_mbboDirect_record};
struct ioCard {
volatile struct DPvme321 *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 pvme321_num_links;
static struct ioCard cards[CONST_NUM_LINKS];
static int init_flag = 0;
int devPvme321Config(ncards,a24base)
int ncards;
long a24base;
{
pvme321_num_links = ncards;
Base_IO = a24base;
logMsg("Pvme321 NumLink= %d BaseIO= %x\n",pvme321_num_links,Base_IO);
init_all(0);
}
static long init_all(after)
int after;
{
int cardNum, chanNum;
unsigned char probeVal;
volatile struct DPvme321 *p;
if (init_flag != 0 )
return(OK);
init_flag = 1;
if (sysBusToLocalAdrs(VME_AM_STD_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
{
logMsg("VmeP321: cannot find A24 address space\n");
return(ERROR);
}
#ifdef DEBUG_ON
if ( CDEBUG)logMsg("PVME321 (init) Called. pass = %d\n", after);
#endif
for (cardNum=0; cardNum< pvme321_num_links; cardNum++)
{
probeVal = CNT;
if (vxMemProbe((char*) &(p->func_reg_0), WRITE, 1, &probeVal)< OK)
{
if (debug_flag >0 )
logMsg("No PVME321 with cardNum= %d\n probe= %x\n",cardNum,p);
cards[cardNum].card = NULL;
}
else
{
p->func_reg_0 = CNT;
probeVal=FC1;
if ((vxMemProbe((char*) &(p->func_reg_1), WRITE,1,&probeVal)==OK) && (debug_flag>10))
logMsg("PVME321 card %d user timer cond set\n");
probeVal= ALLENABLE;
if ((vxMemProbe((char*) &(p->cntl_reg_0), WRITE,1,&probeVal)==OK) && (debug_flag>10))
logMsg("PVME321 card %d All D/A Enable\n");
probeVal=TIMER;
if ((vxMemProbe((char*) &(p->cntl_reg_2), WRITE,1,&probeVal)==OK) && (debug_flag>10))
logMsg("PVME321 card %d TIMER Disable\n");
if (debug_flag >0)
logMsg("Found PVME321 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_record(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");
cards[cardN].card->cntl_reg_0 = (char)(pmbbo->rval);
pmbbo->rbv=(cards[cardN].card->cntl_reg_0) & 0xff;
if (debug_flag >5)
logMsg("write complete \n");
FASTUNLOCK(&(cards[cardN].lock));
if (debug_flag >0)
logMsg("unlock card ...\n");
return(CONVERT);
}
static long init_mi_record(pmbbi)
struct MbbiDirectRecord *pmbbi;
{
return(0);
}
static long read_mbbiDirect_record(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->cntl_reg_0) & 0xff;
if (debug_flag >5)
logMsg("read complete \n");
return(CONVERT);
}
static long init_lo_record(plongin)
struct longinRecord *plongin;
{
return(0);
}
static long write_longout_record(plongout)
struct longoutRecord *plongout;
{
short cardN;
cardN = plongout->out.value.vmeio.card;
if (debug_flag >4)
logMsg("write_longout called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
FASTLOCK(&(cards[cardN].lock));
if (debug_flag >4)
logMsg("card locked...\n");
switch(plongout->out.value.vmeio.signal){
case 0: /* DAC 0 */
cards[cardN].card->dac_0 = (short)plongout->val+2047;
if (debug_flag >4)
logMsg("write_longout signal 0 DAC0\n");
break;
case 1: /* DAC 1 */
cards[cardN].card->dac_1 = (short)plongout->val+2047;
if (debug_flag >4)
logMsg("write_longout signal 1 DAC1\n");
break;
case 2: /* DAC 2 */
cards[cardN].card->dac_2 = (short)plongout->val+2047;
if (debug_flag >4)
logMsg("write_longout signal 2 DAC0\n");
break;
case 3: /* DAC 3 */
cards[cardN].card->dac_3 = (short)plongout->val+2047;
if (debug_flag >4)
logMsg("write_longout signal 3 DAC3\n");
break;
case 4: /* DAC 4 */
cards[cardN].card->dac_4 = (short)plongout->val+2047;
if (debug_flag >4)
logMsg("write_longout signal 4 DAC4\n");
break;
case 5: /* DAC 5 */
cards[cardN].card->dac_5 = (short)plongout->val+2047;
if (debug_flag >4)
logMsg("write_longout signal 5 DAC5\n");
break;
case 6: /* DAC 6 */
cards[cardN].card->dac_6 = (short)plongout->val+2047;
if (debug_flag >4)
logMsg("write_longout signal 6 DAC6\n");
break;
case 7: /* DAC 7 */
cards[cardN].card->dac_7 = (short)plongout->val+2047;
if (debug_flag >4)
logMsg("write_longout signal 7 DAC7\n");
break;
default:
return(-1);
}
FASTUNLOCK(&(cards[cardN].lock));
if (debug_flag >4)
logMsg("unlock card ...\n");
return(CONVERT);
}
/**************************************************************************
*
* Make sure card number is valid
*
**************************************************************************/
static int checkLink(cardN)
short cardN;
{
if (cardN >= pvme321_num_links)
return(ERROR);
if (cards[cardN].card == NULL)
{
logMsg("No PVME321 with this number = %d\n",cardN);
return(ERROR);
}
if (debug_flag >5)
logMsg("Yes you have PVME321 with card No= %d\n",cardN);
return(OK);
}