/***************************************************/
/*                                                 */
/* File        : userrockfifo.c                    */
/* Description : tl compiler definitions           */
/*                                                 */
/* Command     : rockfifo                          */
/* Comment     : ROCK FIFO library tcl interface   */
/*                                                 */
/* Created       : 18.02.1997                      */
/* Last modified : 24.02.1997                      */
/*                                                 */
/***************************************************/

#include <stdlib.h>
#include <string.h>
#include <Error.h>

#include <rockfifo.h>
#include "userrockfifo.h"

/* rockfifo decode data function*/
/* return TL_OK iff no error */
int rockfifot_tl_decode(rockfifot_t_decode *data)
{
  int err;
  ROCK_FIFO_FRAMEs readels;

  if (!data->nrels_present)
    {
      data->nrels = 1;
    }

  err = rock_fifo_frame_blockread((ROCK_FIFO_id) data->fid, data->nrels, &readels);

  switch (err)
    {
    case ROCK_ERROR_OK:
    case ROCK_ERROR_FIFO_EMPTY:
    case ROCK_ERROR_FIFO_FRAME_PARITY:
      break; /* no message */
    case ROCK_ERROR_FIFO_FRAME_HEADER:
      {
	data->result.status = (char *) malloc(16);
	strcpy(data->result.status,"header error");
      }
      break;
    case ROCK_ERROR_FIFO_FRAME_SLAVE:
      {
	data->result.status = (char *) malloc(16);
	strcpy(data->result.status,"slave error");
      }
      break;
    case ROCK_ERROR_FIFO_FRAME_FOOTER:
      {
	data->result.status = (char *) malloc(16);
	strcpy(data->result.status,"footer error");
      }
      break;
    case ROCK_ERROR_FIFO_FRAME_OVERFLOW:
      {
	data->result.status = (char *) malloc(16);
	strcpy(data->result.status,"overflow error");
      }
      break;
    default:
      { /* serious error */
	char *tmp;
	
	tmp = ErrorGetMessage();
	data->errorstr = (char *) malloc(strlen(tmp)+1);
	strcpy(data->errorstr,tmp);
	
	return TL_OK+err;
      }
      break;
    }

  ErrorClean();
  
  /* return read data */

  {
    int i;

    for (i=readels.nrframes-1; i>=0; i--)
      {
	_STR_ROCKFIFOT_OTframe *listel;
	int j;

	listel = (_STR_ROCKFIFOT_OTframe *) malloc(sizeof(_STR_ROCKFIFOT_OTframe));
	listel->next = data->result.elements;
	data->result.elements = listel;

	listel->element.header.sy = readels.frames[i].header.sy;
	listel->element.header.last = readels.frames[i].header.last;
	listel->element.header.cradd = readels.frames[i].header.cradd;
	listel->element.header.trigger = readels.frames[i].header.trigger;


	listel->element.slaves = NULL;

	for (j=0;j<16;j++)
	  {
	    int k;

	    for (k=readels.frames[i].slv[j].nrels-1;k>=0;k--)
	      {
		_STR_ROCKFIFOT_OTslave *slvel;

		slvel = (_STR_ROCKFIFOT_OTslave *) malloc(sizeof(_STR_ROCKFIFOT_OTslave));
		slvel->next = listel->element.slaves;
		listel->element.slaves = slvel;

		listel->element.slaves->element.slvadd = j;
		listel->element.slaves->element.channel = readels.frames[i].slv[j].els[k].channel;
		listel->element.slaves->element.reserved = readels.frames[i].slv[j].els[k].reserved;
		listel->element.slaves->element.slvdata = readels.frames[i].slv[j].els[k].data;
	      }

	    free(readels.frames[i].slv[j].els);
	  }
	listel->element.footer.last = readels.frames[i].footer.last;
	listel->element.footer.softparity = readels.frames[i].footer.softparity;
	listel->element.footer.hardparity = readels.frames[i].footer.hardparity;
      }
  }

  free(readels.frames);
  return TL_OK;
}

/* rockfifo read data function*/
/* return TL_OK iff no error */
int rockfifot_tl_read(rockfifot_t_read *data)
{
  int err;
  ROCK_FIFO_RAW readels;

  if (!data->nrels_present)
    {
      data->nrels = 1;
    }

  err = rock_fifo_raw_blockread((ROCK_FIFO_id) data->fid, data->nrels, &readels);

  if ((err!=ROCK_ERROR_OK)&&(err!=ROCK_ERROR_FIFO_EMPTY))
    {
      char *tmp;

      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);

      return TL_OK+err;
    }

  /* return read data */

  {
    int i;

    for (i=readels.nrels-1; i>=0; i--)
      {
	_STR_natural *listel;

	listel = (_STR_natural *) malloc(sizeof(_STR_natural));
	listel->next = data->result;
	listel->element = readels.els[i];
	data->result = listel;
      }
  }

  free(readels.els);

  return TL_OK;
}

/* rockfifo close data function*/
/* return TL_OK iff no error */
int rockfifot_tl_close(rockfifot_t_close *data)
{
  ROCK_FIFO_RAW cache;
  int err;
  
  err = rock_fifo_close((ROCK_FIFO_id) data->fid,&cache);

  if (err!=ROCK_ERROR_OK)
    {
      char *tmp;

      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);

      return TL_OK+err;
    }

  /* return cache data */

  {
    int i;

    for (i=cache.nrels-1; i>=0; i--)
      {
	_STR_natural *listel;

	listel = (_STR_natural *) malloc(sizeof(_STR_natural));
	listel->next = data->result;
	listel->element = cache.els[i];
	data->result = listel;
      }
  }

  free(cache.els);
  return TL_OK;
}

/* rockfifo open data function*/
/* return TL_OK iff no error */

int rockfifot_tl_open(rockfifot_t_open *data)
{
  int realcancache;
  int err;

  if (!data->cancache_present)
    {
      data->cancache.nr = ROCKFIFOT_Ccancache_minimal;
    }

  switch(data->cancache.nr)
    {
    case ROCKFIFOT_Ccancache_off:
      realcancache = ROCK_FIFO_CACHE_OFF;
      break;
    case ROCKFIFOT_Ccancache_minimal:
      realcancache = ROCK_FIFO_CACHE_MINIMAL;
      break;
    case ROCKFIFOT_Ccancache_advanced:
      realcancache = ROCK_FIFO_CACHE_ADVANCED;
      break;
    case ROCKFIFOT_Ccancache_block:
      realcancache = ROCK_FIFO_CACHE_BLOCK;
      break;
    case ROCKFIFOT_Ccancache_block_advanced:
      realcancache = ROCK_FIFO_CACHE_BLOCK_ADVANCED;
      break;
    }

  if (data->what.nr==ROCKFIFOT_Cwhat_efifo)
      err = rock_fifo_open_efifo((ROCK_id) data->rid, realcancache, (ROCK_FIFO_id *) &(data->result));
  else
    err = rock_fifo_open_dfifo((ROCK_id) data->rid, realcancache, (ROCK_FIFO_id *) &(data->result));

  if (err==ROCK_ERROR_OK)
    return TL_OK;
  else
    {
      char *tmp;

      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);

      return TL_OK+err;
    }
}

/* rockfifo synch data function*/
/* return TL_OK iff no error */
int rockfifot_tl_synch(rockfifot_t_synch *data)
{
  int err;
  ROCK_FIFO_RAW readels;

  err = rock_fifo_frame_synch((ROCK_FIFO_id) data->fid, &readels);

  if ((err!=ROCK_ERROR_OK)&&(err!=ROCK_ERROR_FIFO_EMPTY))
    {
      char *tmp;

      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);

      return TL_OK+err;
    }
  
  /* return read data */

  {
    int i;

    for (i=readels.nrels-1; i>=0; i--)
      {
	_STR_natural *listel;

	listel = (_STR_natural *) malloc(sizeof(_STR_natural));
	listel->next = data->result;
	listel->element = readels.els[i];
	data->result = listel;
      }
  }

  free(readels.els);
  return TL_OK;
}

/* rockfifo isempty data function*/
/* return TL_OK iff no error */
int rockfifot_tl_isempty(rockfifot_t_isempty *data)
{
 int err;

 err = rock_fifo_isnotempty((ROCK_FIFO_id) data->fid);

 if (err==ROCK_ERROR_OK)
   {
     data->result = 0;   /* false */
     return TL_OK;
   }
 else if (err==ROCK_ERROR_FIFO_EMPTY)
   {
     data->result = 1;  /* true */
     return TL_OK;
   }
 else
    { /* error */
      char *tmp;

      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);

      return TL_OK+err;
    }
}