/* devVme17k53.c */
/* devVme17k53.c - Device Support Routines for  VME 17K53 */
/*
 *      Original Author: Makoto Tobiyama
 *      Current Author:
 *      Date:            05/Nov/98
 *
 *      Experimental Physics and Industrial Control System (EPICS)
 *
 *      Copyright 1997, KEKB.
 *
 *
 * Modification Log:
 * -----------------
 *	05-Nov-98	Makoto Tobiyama (original)
 */


#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>

/* #define	Base_IO		0x20000 */ /* Std. I/O Address */


struct Dvme17k53 {
	unsigned short	Cntl;
	unsigned short	Hatt;
        unsigned short  Vatt;
        unsigned short  dummy;
};


static long init_all();
static long init_li_record();
static long init_lo_record();
static long read_longin();
static long write_longout();
static int  checkLink();

/* Create the dset for devLiK53 */

struct {
	long		number;
	DEVSUPFUN	report;
	DEVSUPFUN	init;
	DEVSUPFUN	init_li_record;
	DEVSUPFUN	get_ioint_info;
	DEVSUPFUN	read_longin;
	DEVSUPFUN	special_linconv;
}devLiK53={
	6,
	NULL,
	NULL,
	init_li_record,
	NULL,
	read_longin,
        NULL};

struct {
	long		number;
	DEVSUPFUN	report;
	DEVSUPFUN	init;
	DEVSUPFUN	init_lo_record;
	DEVSUPFUN	get_ioint_info;
	DEVSUPFUN	write_longout;
	DEVSUPFUN	special_linconv;
}devLoK53={
	6,
	NULL,
	NULL,
	NULL,
	NULL,
	write_longout,
        NULL};


struct ioCard {
        volatile struct Dvme17k53     *card; /* address of this card */
        FAST_LOCK                     lock; /* semaphore */
      };

#define CONST_NUM_LINKS 20
/* #define STATIC  */
#define DEBUG_ON

static int      debug_flag = 1;
static unsigned long Base_IO;
static int      k53_num_links;

static struct   ioCard cards[CONST_NUM_LINKS];
static int      init_flag = 0;


int devK53Config(ncards,a32base)
int ncards;
long a32base;
{
  k53_num_links = ncards;
  Base_IO = a32base;
  logMsg("Vme17K53 NumLink= %d BaseIO= %x\n",k53_num_links,Base_IO);
  init_all(0);
}


static long init_all(after)
int after;
{
  int                          cardNum, chanNum;
  unsigned char                probeVal[2];
  volatile  struct Dvme17k53   *p;

  if (init_flag != 0 ) 
   return(OK);

  init_flag = 1;

  if (sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
	{
		logMsg("Vme17K53: cannot find extended address space\n");
		return(ERROR);
	}
#ifdef DEBUG_ON  
    logMsg("devLiK53 (init) Called. pass = %d\n", after);
#endif
  for (cardNum=0; cardNum< k53_num_links; cardNum++)
   {
     if ((vxMemProbe((char*) &(p->Cntl), READ, 2, &probeVal[0])<OK))
       {
	 if (debug_flag >0 ) 
         logMsg("No 17K53 with cardNum= %d\n probe= %x\n",cardNum,p);
	 cards[cardNum].card = NULL;
       }
     else
       {
	 
	 if (debug_flag >0)
         logMsg("Found 17K53 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_li_record(plongin)
struct longinRecord	*plongin;
{
  return(0);
}

static long read_longin(plongin)
struct longinRecord	*plongin;
{
  short cardN;
  short temp_in;

  if (debug_flag >5)
    logMsg("read_longin called...\n");

  cardN = plongin->inp.value.vmeio.card;
  if (debug_flag >5)
    logMsg("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->Hatt & 0x1f); 
    break;
  case 1:
    plongin->val = (cards[cardN].card->Vatt & 0x1f);
    break;
  case 2:
    plongin->val = (cards[cardN].card->Cntl & 0x03);
    break;
  }
  return(CONVERT);
}

static long init_lo_record(plongout)
struct longoutRecord	*plongout;
{
  return(0);
}

static long write_longout(plongout)
struct longoutRecord	*plongout;
{
  short cardN;
  unsigned short attset;

  if (debug_flag >5)
    logMsg("write_longout called...\n");

  cardN = plongout->out.value.vmeio.card;
  if (debug_flag >5)
    logMsg("write_longout called with card number of %d\n",cardN);

  if (checkLink(cardN) == ERROR)
    return(ERROR);

  FASTLOCK(&(cards[cardN].lock));
  switch(plongout->out.value.vmeio.signal){
  case 0:
    attset = plongout->val;
    if (attset>31)
      attset = 31;
    cards[cardN].card->Hatt = (attset & 0x1f);
    break;
  case 1:
    attset = plongout ->val;
    cards[cardN].card->Vatt = (attset & 0x1f);
    break;
  case 2:
    cards[cardN].card->Cntl = (plongout->val & 0x03);
    break;
  }
  FASTUNLOCK(&(cards[cardN].lock));
  return(CONVERT);
}




/**************************************************************************
 *
 * Make sure card number is valid
 *
 **************************************************************************/
static int checkLink(cardN)
short   cardN;
{
  if (cardN >= k53_num_links)
    return(ERROR);
  if (cards[cardN].card == NULL)
    {
      logMsg("No 17K53 with this number = %d\n",cardN);
      return(ERROR);
    }

  if (debug_flag >10)
    logMsg("Yes you have 17K53 with card No= %d\n",cardN);
  return(OK);
}

mailto: makoto.tobiyama@kek.jp