/******************************************************************************
 *
 *	mthood_linux_app.c
 *	--------------------
 *	Linux example applicaton for mthood
 *
 ******************************************************************************
 *
 *	COPYRIGHT 2003 BY RADISYS CORPORATION.  ALL RIGHTS RESERVED.
 *
 ******************************************************************************/

#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <enpv2_types.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <signal.h>

/******************************************************************************
 *	BUILD SWITCHES
 ******************************************************************************/
/* loading spi3br.o will do this for us */
#define SLOW_PORT_FIX					FALSE


/******************************************************************************
 *	GLOBAL DECLARATIONS
 ******************************************************************************/
int tcp1_port;
int tcp2_port;

/******************************************************************************
 *	FORWARD DECLARATIONS
 ******************************************************************************/
extern void TestSPI3Interrupts(void);
extern void StartMicroEngines( char *filename );
extern void StopMicroEngines(void);
extern void PrintCount();
extern void ZeroCount();

void PrintHelp();

/******************************************************************************
 *
 *							APPLICATION FUNCTIONS
 *
 ******************************************************************************/
void HWStart( void )
{

#if( SLOW_PORT_FIX == TRUE )
	/* put slowport in corect mode if not already */
	spfix();
#endif

	/* init and start spi3br */
	StartSpi3br();


	/* init and start macs */
	StartMacs();
}

void UcodeStart( char *filename ) {
  /* Zero out the counters */
  ZeroCount();
  
  /* Initialize microengines */
  StartMicroEngines( filename );
}

void HWStop( void )
{
  StopMacs();
  StopSpi3br();
}

void PCWrapper( int sig ) {
  PrintCount();
}

int main()
{

  while( 1 ) {
    char line[80];
    char args[5][32];
    int count;

    printf( "> " );
    memset( line, 0, sizeof(line));
    if( scanf( "%79[^\n]", line ) < 0 ) {
      printf( "EOF\n" );
      break;
    }
    while( getchar() != '\n' );

    count = sscanf( line, " %31s %31s %31s %31s %31s", args[0], args[1],
		    args[2], args[3], args[4] );

    if( count <= 0 ) {
      continue;
    }
    
    if ( strncmp( args[0], "tcp3", 4 ) == 0 && strlen( args[0] ) == 4 ) {
      if( count != 3 ) {
	printf( "TCP ports needed for fixed_tcp3 filter\n" );
	continue;
      }
      tcp1_port = atoi( args[1] );
      tcp2_port = atoi( args[2] );
    } else if( strncmp( args[0],"netstart",8 ) == 0 && strlen(args[0]) == 8 ) {
      HWStart();
    } else if( strncmp( args[0],"netstop",7 ) == 0 && strlen(args[0]) == 7 ) {
      HWStop();
    } else if( strncmp( args[0],"uestart",7 ) == 0 && strlen(args[0]) == 7 ) {
      if( count != 2 ) {
	printf( "Missing microcode filename\n" );
	continue;
      }
      UcodeStart( args[1] );
    } else if( strncmp( args[0],"uestop",6 ) == 0 && strlen(args[0]) == 6 ) {
      StopMicroEngines();
    } else if (strncmp(args[0], "tstart", 6) == 0 && strlen(args[0]) == 6 ) {
      struct itimerval time = {{30L,0L},{1L,0L}};
      if( count > 1 ) {
	time.it_value.tv_sec = atoi( args[1] );
      }
      if( signal( SIGALRM, PCWrapper) == SIG_ERR ) {
	perror( "Register signal handler failed" );
	continue;
      }
      printf( "Timer starting...\n" );
      if( setitimer( ITIMER_REAL, &time, NULL ) == -1 ) {
	perror( "Setitimer() failed" );
	continue;
      }
    } else if( strncmp(args[0],"tstop",5) == 0 && strlen(args[0])==5 ) {
      struct itimerval time = {{0L,0L},{0L,0L}};
      if( setitimer( ITIMER_REAL, &time, NULL ) == -1 ) {
	perror( "Setitimer() failed" );
	continue;
      }
      if( signal( SIGALRM, SIG_DFL ) == SIG_ERR ) {
	perror( "Register signal handler failed" );
	continue;
      }
      printf( "Timer stopped.\n" );
    } else if(strncmp(args[0],"showmacstats",12) == 0 && strlen(args[0])==12) {
      ShowMacStats();
    } else if (strncmp(args[0], "showmacs", 8) == 0 && strlen(args[0]) == 8) {
      printf("\n------ MAC 0 ------\n");
      ShowMac(0);
      printf("\n\n------ MAC 1 ------\n");
      ShowMac(1);
    } else if (strncmp(args[0], "show", 4) == 0 && strlen(args[0]) == 4) {
      PrintCount();
    } else if (strncmp(args[0], "spi3bridge", 10)==0 && strlen(args[0])==10) {
      ShowSpi3br();
    } else if (strncmp(args[0], "testints", 8)==0 && strlen(args[0])==8) {
      TestSPI3Interrupts();
    } else if( strncmp(args[0],"exit",4)==0 && strlen(args[0])==4) {
      break;
    } else if (strncmp(args[0],"help",4)==0 && strlen(args[0])==4) {
      PrintHelp();
    } else {
      printf("Invalid parameter, use 'help' for available commands\n");
    }
  }
}

void PrintHelp( void ) {
  typedef struct {
    char *command;
    char *description;
  } help_e;

  int i;
  help_e he[] = {
    { "tcp3",
      "set watch ports for fixed_tcp3 filter, usage: tcp3 <port1> <port2>" },
    { "netstart",
      "initialize and start SPI-3 bridge and PM-338x MAC controllers" },
    { "netstop",
      " shutdown SPI-3 bridge and PM-338x MAC controllers" },
    { "uestart",
      "load microcode and start microengines, usage: uestart <ucode file>" },
    { "uestop",
      "put all microengines in reset" },
    { "tstart",
      "start count dump every thirty seconds, usage tstart [initial_value]" },
    { "tstop",
      "stop count dump" },
    { "exit",
      "exit application entirely" },
    { "help",
      "print this message" },
    { "showmacstats",
      "dump hardware statistics for MACs" },
    { "showmacs",
      "dump MAC information" },
    { "spi3bridge",
      "dump SPI-3 bridge information" },
    { "testints",
      "test SPI-3 bridge interrupts" },
  };

  for( i = 0; i < sizeof(he)/sizeof(help_e); ++i ) {
    printf( "%s\n\t%s\n", he[i].command, he[i].description );
  }
}
