/****************************************************************************/
/* Copyright 2002 MBARI							*/
/****************************************************************************/
/* Summary  : Main Routine for OASIS Mooring Controller                     */
/* Filename : oasis.c                                                       */
/* Author   : Robert Herlien (rah)					    */
/* Project  : OASIS Mooring Replacement (OASIS3)			*/
/* Revision : 0.1							*/
/* Created  : 10/14/2002						*/
/*									    */
/* MBARI provides this documentation and code "as is", with no warranty,    */
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium  */
/* Research Institute to assist in its use, correction, modification, or    */
/* enhancement. This information should not be published or distributed to  */
/* third parties without specific written permission from MBARI.            */
/*									    */
/****************************************************************************/
/* Modification History:						    */
/* 10oct2002 rah - created from OASIS oasis.c				*/
/****************************************************************************/

#include	<mbariTypes.h>		/* MBARI type definitions	    */
#include	<mbariConst.h>		/* MBARI constants		    */
#include	<cfxbios.h>		// Persistor BIOS and I/O Definitions
#include	<cfxpico.h>		// Persistor PicoDOS Definitions
#include	<stdio.h>
#include	<stdlib.h>
#include	<fcntl.h>
#include	<unistd.h>
#include	<dosdrive.h>

typedef short	dsdfunc(short, ulong, void *, short);
typedef dsdfunc	*dsdfp;

static char	*filename = "TEST.DAT";
static dsdfp	picoDSDReadSectors = NULL, picoDSDWriteSectors = NULL;
static Nat32	readCnt = 0L, writeCnt = 0L;
static DPBPB	dosPackedParmBlk;
static DWBPB	dosParmBlk;
static char	buffer[32768];

#define CPU_CLOCK	7360L
#define DRIVE		2
	
short DSDReadSectorsPatch(short logdrv, ulong sector, 
			  void *buffer, short count);
short DSDWriteSectorsPatch(short logdrv, ulong sector, 
			   void *buffer, short count);


/************************************************************************/
/* Function    : DSDReadSectorsPatch					*/
/* Purpose     : Patched routine for PicoDos DSDReadSectors()		*/
/* Inputs      : Drive, sector, buffer, number of sectors		*/
/* Outputs     : Return code						*/
/************************************************************************/
short DSDReadSectorsPatch(short logdrv, ulong sector, 
			  void *buffer, short count) 
{
  char		*rtype;
  short		rtn;
  Nat32		readtime;
  RTCTimer	rt;

  if (sector < (dosParmBlk.ffat + dosParmBlk.spf))
    rtype = "FAT1";
  else if (sector < dosParmBlk.fdir)
    rtype = "FAT2";
  else if (sector < dosParmBlk.fdat)
    rtype = "DIR";
  else
    rtype = "DAT";

  if (picoDSDReadSectors == NULL)
    return(ERROR);
  
  readCnt++;
  RTCElapsedTimerSetup(&rt);
  rtn = (*picoDSDReadSectors)(logdrv, sector, buffer, count);
  readtime = RTCElapsedTime(&rt);
  printf("DSDRead %s sector %ld count %d time %lu\n",
	 rtype, sector, count, readtime);
  return(rtn);

} /* DSDReadSectorsPatch() */


/************************************************************************/
/* Function    : DSDWriteSectorsPatch					*/
/* Purpose     : Patched routine for PicoDos DSDReadSectors()		*/
/* Inputs      : Drive, sector, buffer, number of sectors		*/
/* Outputs     : Return code						*/
/************************************************************************/
short DSDWriteSectorsPatch(short logdrv, ulong sector, 
			   void *buffer, short count) 
{
  char		*rtype;
  short		rtn;
  Nat32		writetime;
  RTCTimer	rt;

  if (sector < (dosParmBlk.ffat + dosParmBlk.spf))
    rtype = "FAT1";
  else if (sector < dosParmBlk.fdir)
    rtype = "FAT2";
  else if (sector < dosParmBlk.fdat)
    rtype = "DIR";
  else
    rtype = "DAT";

  if (picoDSDWriteSectors == NULL)
    return(ERROR);
  
  writeCnt++;
  RTCElapsedTimerSetup(&rt);
  rtn = (*picoDSDWriteSectors)(logdrv, sector, buffer, count);
  writetime = RTCElapsedTime(&rt);
  printf("DSDWrite %s sector %ld count %d time %lu\n",
	 rtype, sector, count, writetime);
  return(rtn);

} /* DSDWriteSectorsPatch() */


/************************************************************************/
/* Function    : main							*/
/* Purpose     : Main entry point					*/
/* Inputs      : None							*/
/* Outputs     : None							*/
/* Comments    : Never returns						*/
/************************************************************************/
int main( int argc, char **argv)
{
#pragma unused (argc, argv)
  Nat32		i;
  Nat16		filesize = 32;
  Nat16		sz;
  Nat32		cursize, remain;
  int		fd;
  FILE		*fp;
  MBool		zoomOn = FALSE;

  //  BIOSInit();
  TMGSetSpeed(CPU_CLOCK);
  // Identify the progam and build
  printf("\nProgram: %s: %s %s \n", __FILE__, __DATE__, __TIME__);
  // Identify the device and its firmware
  printf("Persistor CF%d SN:%ld   BIOS:%d.%d   PicoDOS:%d.%d\n", CFX,
	 BIOSGVT.CFxSerNum, BIOSGVT.BIOSVersion, BIOSGVT.BIOSRelease, 
	 BIOSGVT.PICOVersion, BIOSGVT.PICORelease);
	
  printf("OASIS file test program\n\n");
  //  chdir("\FOO");
  //  getcwd(buffer, sizeof(buffer));
  //  printf("Working directory is %s\n", buffer);
  picoDSDReadSectors = PICOPatchInsert(DSDReadSectors, DSDReadSectorsPatch);
  picoDSDWriteSectors = PICOPatchInsert(DSDWriteSectors, DSDWriteSectorsPatch);
  DBRGetBootParamBlock(DRIVE, &dosPackedParmBlk);
  DBRUnpackParamBlock(&dosParmBlk, &dosPackedParmBlk);

  while(TRUE)
  {
    printf("\n");
    printf("Type 'R' to read file using fread\n");
    printf("Type 'r' to read file using read\n");
    printf("Type 'W' to write file using fwrite\n");
    printf("Type 'w' to write file using write\n");
    printf("Type 'S' to change size of file\n");
    printf("Type 'C' to turn on/off PicoZoom cacheing\n");
    printf("Type 'F' to get disk free space\n");
    printf("Type 'X' to exit\n");

    switch(cgetc())
    {
      case 'X':
      case 'x':
      case 3:
	printf("%ld Reads, %ld Writes\n", readCnt, writeCnt);
	printf("Goodbye\n");
	return(0);

      case 'S':
      case 's':
	printf("Current file size is %d KB.  New file size in KBytes:  ",
	       filesize);
	if ((scanf("%d", &sz) < 1) || (sz < 1) || (sz > 2048))
	{
	  printf("\nBad input value\n");
	  break;
	}
	filesize = sz;
	printf("\nNew file size is %d KB\n", filesize);
	break;

      case 'C':
      case 'c':
	if (zoomOn)
	{
	  PZCacheRelease(DRIVE);
	  printf("PicoZoom cacheing is now OFF\n");
	  zoomOn = FALSE;
	}
	else
	{
	  PZCacheSetup(DRIVE, calloc, free);
	  printf("PicoZoom cacheing is now ON\n");
	  zoomOn = TRUE;
	}
	break;

      case 'R':
	printf("File fopen\n");
	if ((fp = fopen(filename, "rb")) == NULL)
	{
	  perror("Filetest:  Can't open file");
	  break;
	}

	printf("File fread\n");
	for (remain = 1024L * filesize; remain > 0L; )
	{
	  cursize = (remain < sizeof(buffer)) ? remain : sizeof(buffer);
	  fread(buffer, cursize, 1, fp);
	  remain -= cursize;
	}
	
	printf("File fclose\n");
	fclose(fp);
	break;

      case 'W':
	for (i = 0; i < sizeof(buffer); i++)
	  buffer[i] = (char)i;

	printf("File fopen\n");
	if ((fp = fopen(filename, "wb")) == NULL)
	{
	  perror("Filetest:  Can't create file");
	  break;
	}

	printf("File fwrite\n");
	for (remain = 1024L * filesize; remain > 0L; )
	{
	  cursize = (remain < sizeof(buffer)) ? remain : sizeof(buffer);
	  fwrite(buffer, cursize, 1, fp);
	  remain -= cursize;
	}
	
	printf("File fclose\n");
	fclose(fp);
	break;

      case 'r':
	printf("File open\n");
	if ((fd = open(filename, O_RDONLY)) < 0)
	{
	  perror("Filetest:  Can't open file");
	  break;
	}

	printf("File read\n");
	for (remain = 1024L * filesize; remain > 0L; )
	{
	  cursize = (remain < sizeof(buffer)) ? remain : sizeof(buffer);
	  read(fd, buffer, cursize);
	  remain -= cursize;
	}
	
	printf("File close\n");
	close(fd);
	break;

      case 'w':
	for (i = 0; i < sizeof(buffer); i++)
	  buffer[i] = (char)i;

	printf("File unlink\n");
	unlink(filename);

	printf("File open\n");
	if ((fd = open(filename, O_WRONLY | O_CREAT)) < 0)
	{
	  perror("Filetest:  Can't create file");
	  break;
	}

	printf("File write\n");
	for (remain = 1024L * filesize; remain > 0L; )
	{
	  cursize = (remain < sizeof(buffer)) ? remain : sizeof(buffer);
	  write(fd, buffer, cursize);
	  remain -= cursize;
	}
	
	printf("File close\n");
	close(fd);
	break;

      case 'F':
      case 'f':
	cursize = DIRFreeSpace("C:");
	printf("Free space = %ld\n", cursize);
	break;
    }
  }

  return(0);

}	//____ main() ____//

