/************************************************/
/*                                              */
/* File        : rockm.c                        */
/* Description : ROCKM hardware base access     */
/*                                              */
/*                                              */
/* Author       : Maurizio De Nino              */
/* Modified by  : Sfiligoi Igor                 */
/*                                              */
/* Created      : 01/10/97                      */
/* Last modified: 20/10/97                      */
/*                                              */
/************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <Error.h>
#include <GeoVme.h>
#include <Vme.h>
#include <Vme_am.h>
#include "RockM.h"

/*  per entrare nella logica di GeoVme devi definire a priori il numero */
/*  del crate in cui sta il rockm, che deve essere fisso                */
/*   Il numero del crate di secondo livello e' stato deciso essere 0    */
/*     qualche mese fa.                                                 */

#define ROCKM_CRATE                 0  

/*  buffer per il dma del rockm                   */

#define ROCKM_DMA_BUFFER_SIZE           (200*1024)


/* Finds the RockM slot */
/* Returns the slot number or -1 if the RockM was not found */

int rockm_find(int chain)
{
  int i;

  for (i=GEOVME_INF_SLOTS; i<(GEOVME_INF_SLOTS+GEOVME_MAX_NUM_SLOTS); i++)
    {
      if ((GeoVme_exist(chain,ROCKM_CRATE,i)==GEOVME_BOARD_EXIST) &&
	  (GeoVme_btype(chain,ROCKM_CRATE,i)==GEOVME_ROCKM_BTYPE))
	return i;
    }

  return -1;
}

/*********************************************************************/
/*                          Query routines                           */
/*********************************************************************/

/* returns 0 if ROCKM not present, 1 else */

int rockm_ispresent(int chain)                   /* IN, VIC chain */
{
  if (rockm_find(chain)<-1)
    return 0;
  else
    return 1;
}

/*********************************************************************/
/*                       Initialization routines                     */
/*********************************************************************/

int rockm_open(int chain,                    /* IN, VIC chain */
	       ROCKM_id *rockm_id)           /* OUT */
{
 int result;
 int slot;
 GeoBoardAddr GeoData;

#ifdef DEBUG
 printf("rockm_open:\nchain %x\n",chain);
#endif

 *rockm_id = (ROCKM_id) malloc(sizeof(ROCKM_id_base));
  if (*rockm_id==NULL)
   {
     ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_open","Malloc returned NULL.");
     return ROCKM_ERROR_UNKNOWN;
   }

 slot = rockm_find(chain);
 result=GeoVmeOpen(chain,ROCKM_CRATE,slot,&GeoData);

 if (result!=GEOVME_ERROR_OK)
   {
     ErrorSetF(ROCKM_ERROR_UNKNOWN,"rockm_open","GeoVmeOpen error: %s",ErrorGetMessage());
     return ROCKM_ERROR_UNKNOWN;
   }

 if (GeoData.btype!=GEOVME_ROCKM_BTYPE)
   {
     GeoVmeClose(chain,ROCKM_CRATE,slot);
     ErrorSetF(ROCKM_ERROR_UNKNOWN,"rockm_open","Chain %i does not have a ROCKM!",chain);
     return ROCKM_ERROR_UNKNOWN;
   }
   
 (*rockm_id)->chain = chain;
 (*rockm_id)->slot = slot;
 (*rockm_id)->cid = GeoData.cid;
 (*rockm_id)->map_ptr = (void *)GeoData.map_ptr;
 (*rockm_id)->vme_addr = GeoData.addr;
 (*rockm_id)->offs = GeoData.offs;
 (*rockm_id)->vme_am = GeoData.am;


 /* alloc a buffer for DMA ************/

 (*rockm_id)->DMAbuffer = (unsigned int *)VmeAllocateMemory((*rockm_id)->cid,
NULL,ROCKM_DMA_BUFFER_SIZE*sizeof(unsigned int),Vme_MEMORY_FASTEST);

 if ((*rockm_id)->DMAbuffer==NULL)
   {
     ErrorSetF(ROCKM_ERROR_UNKNOWN,"rockm_open","VmeAllocateMemory error: %s",ErrorGetMessage());
     return ROCKM_ERROR_UNKNOWN;
   }

#ifdef DEBUG
 printf("map: %p\naddr: %x\noffs: %x\nDMAbuffer: %p\n",
	(*rockm_id)->map_ptr,
	(*rockm_id)->vme_addr,
	(*rockm_id)->offs,
	(*rockm_id)->DMAbuffer);
#endif

 VmeSetProperty((*rockm_id)->cid,Vme_SET_COPY_FIFO,1);

 return ROCKM_ERROR_OK;
}



int rockm_open_raw(unsigned int vme_addr,       /* IN  */
		   int vme_size,                /* IN  */
		   int vme_am,                  /* IN  */
		   int offs,                    /* IN, ROCKM offset  */
		   ROCKM_id *rockm_id)           /* OUT */
{
 *rockm_id = (ROCKM_id) malloc(sizeof(ROCKM_id_base));
  if (*rockm_id==NULL)
   {
     ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_open","Malloc returned NULL.");
     return ROCKM_ERROR_UNKNOWN;
   }


 (*rockm_id)->cid = VmeOpenChannel("Rockm","pio,dma");

 if ((*rockm_id)->cid==Vme_FAILURE)
   {
     ErrorSetF(ROCKM_ERROR_UNKNOWN,"rockm_open","VmeOpenChannel error: %s",ErrorGetMessage());
     return ROCKM_ERROR_UNKNOWN;
   }

 /* alloc a buffer for DMA */
 
 
 (*rockm_id)->DMAbuffer = (unsigned int *) VmeAllocateMemory((*rockm_id)->cid,NULL,ROCKM_DMA_BUFFER_SIZE*sizeof(unsigned int),Vme_MEMORY_FASTEST);

 if ((*rockm_id)->DMAbuffer==NULL)
   {
     ErrorSetF(ROCKM_ERROR_UNKNOWN,"rockm_open","VmeAllocateMemory error: %s",ErrorGetMessage());
     return ROCKM_ERROR_UNKNOWN;
   }

 (*rockm_id)->map_ptr=VmeMapAddress((*rockm_id)->cid,vme_addr,vme_size,vme_am);
 (*rockm_id)->vme_addr = vme_addr;
 (*rockm_id)->vme_am = vme_am;
 (*rockm_id)->offs = offs;
 (*rockm_id)->chain = -1;  /* set to an invalid vaule */
 (*rockm_id)->slot  = -1;  /* set to an invalid vaule */

 if ((*rockm_id)->map_ptr==NULL)
   {
     ErrorSetF(ROCKM_ERROR_UNKNOWN,"rockm_open","VmeMapAddress error: %s",
     ErrorGetMessage());
     return ROCKM_ERROR_UNKNOWN;
   }

#ifdef DEBUG
 printf("map: %x\naddr: %p\noffs: %x\nDMAbuffer: %p\n",
	(*rockm_id)->map_ptr,
	(*rockm_id)->vme_addr,
	(*rockm_id)->offs,
	(*rockm_id)->DMAbuffer);
#endif

 VmeSetProperty((*rockm_id)->cid,Vme_SET_COPY_FIFO,1);

 return ROCKM_ERROR_OK;
}


int rockm_close(ROCKM_id rockm_id)            /* IN  */
{
 int result;

 if ( rockm_id->chain>=0 )
   { /* normal opened */

     result = GeoVmeClose(rockm_id->chain,ROCKM_CRATE,rockm_id->slot);

     free(rockm_id);

     if (result!=GEOVME_ERROR_OK)
       {
	 ErrorSetF(ROCKM_ERROR_UNKNOWN,"rockm_close","GeoVmeClose(%i) error: %s",rockm_id->chain,ErrorGetMessage());
	 return ROCKM_ERROR_UNKNOWN;
       }
     else
       return ROCKM_ERROR_OK;
   }
 else
   { /* raw opened */
     result = VmeCloseChannel(rockm_id->cid);

     free(rockm_id);

     if (result!=Vme_SUCCESS)
       {
	 ErrorSetF(ROCKM_ERROR_UNKNOWN,"rockm_close","VmeCloseChannel error: %s",ErrorGetMessage());
	 return ROCKM_ERROR_UNKNOWN;
       }
     else
       return ROCKM_ERROR_OK;
   }
}