/*****************************************************************************
*	File:		monitor.c
*	Purpose:	to allow a user to easily edit memory using 1,2 
*                         or 4 byte
*				words.
*	Author:		Scott Johnson
*	Host Sys:	VxWorks
*	Started:	01/20/90
*	Updates:	02/13/90	added my own display routine
*				03/29/90	added history
*				08/22/90	fixed repeat command (return key)
*				11/13/90	bus errors are trapped
*                       Mark Koennecke
*                               04/02/2002      for Tornado 2.0.2
*****************************************************************************/
/* tabstop = 4 */

#include "vxWorks.h"
#include "strLib.h"
#include "stdioLib.h"

int data_type = 2;	/* 1 = byte 2 = word 4 = long */

static void help(void);
static int process_command(char *command);

int monitor (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
	     int a8, int a9, int suspend) 
{

  char command [80];
  char input [80];
  char *from_read;

  printf ("VxWorks history added 03/29/90\n");
  printf ("Bus Error trapping added 11/13/90\n\n");
  do
    {
      switch (data_type)
	{
	case 1 : printf ("byte>"); break;
	case 2 : printf ("word>"); break;
	case 4 : printf ("long>"); break;
	}

      if ((from_read = fgets(input,79,stdin)) != EOF)
	{
	  if ( strlen(input) == 0  && (strlen(command) != 0))
	    {
	      printf ("%s\n", command);
	      process_command (command);
	    }
	  else
	    {
	      printf ("%s\n", input);
	      process_command (input);
	      strcpy (command, input);
	    }
	}

    } while ((input [0] != 'q') && (from_read != EOF));
  fflush (stdin);
  fflush (stdout);
  return 1;
}

static int process_command (command)
     char *command;
{

  unsigned long longInt, longVal;
  unsigned short shortInt;
  unsigned char byte;
  unsigned char *ptr;
  unsigned char *address, *size;
  unsigned int start, end, value;
  int scanned;
  char ch;

  switch (command [0])
    {
    case 'q' : 	/* user wants to quit so do nothing */
    case '#' :	/* comment character */
      break;
    case 'f' :	/* block fill */
      scanned=sscanf(command,"%c %x %x %x",&ch,&address,&size,&longInt); 
      if (scanned != 4)
	printf ("usage : f address size value\n");
      else 
	{
	  for (ptr = address ;(int)ptr < ((int)size + (int)address);
	       ptr+=data_type)
	    {
	      switch (data_type)
		{
		case 1 : 
		  if (vxMemProbe (ptr, READ, data_type, &byte) != OK)
		    {
		      printf ("Bus error: address = %06x, data size = %d\n",
			      (unsigned int) ptr, data_type);
		      return (1);
		    }
		  else
		    *((unsigned char *) ptr) = byte;
		  break;
		case 2 : 
		  if (vxMemProbe (ptr, READ, data_type, &shortInt) != OK)
		    {
		      printf ("Bus error: address = %06x, data size = %d\n",
			      (unsigned int) ptr, data_type);
		      return (1);
		    }
		  else
		    *((unsigned short *) ptr) = shortInt;
		  break;
		case 4 :
		  if (vxMemProbe (ptr, READ, data_type, &longInt) != OK)
		    {
		      printf ("Bus error: address = %06x, data size = %d\n",
			      (unsigned int) ptr, data_type);
		      return (1);
		    }
		  else
		    *((unsigned long *) ptr) = longInt;
		  break;
		}
	    }
	}
      break;
    case 's' :	/* scan range */
      scanned=sscanf(command,"%c %x %x %x",&ch,&start,&end,&value); 
      if (scanned != 4)
	printf ("usage : s start end value\n");
      else 
	{
	  /**
	    scanning does not work: some memory locations lock up!!!!
	  */
          printf("Scanning from %x %x for %x\n", start, end, value);
	  for (ptr = start ;(unsigned int)ptr <  end;
	       ptr+=data_type)
	    {
	      switch (data_type)
		{
		case 1 : 
		  if (vxMemProbe (ptr, READ, data_type, &byte) != OK)
		    {
		      printf ("Bus error: address = %06x, data size = %d\n",
			      (unsigned int) ptr, data_type);
		    }
		  else {
		    if((unsigned char)*ptr == value){
		      printf("Value found at %08x\n",ptr);
                    }
                  }
		  break;
		case 2 : 
		  if (vxMemProbe (ptr, READ, data_type, &shortInt) != OK)
		    {
		      printf ("Bus error: address = %06x, data size = %d\n",
			      (unsigned int) ptr, data_type);
		    }
		  else
		    {
		      if((unsigned short)*ptr == value){
			printf("Value found at %08x\n",ptr); 
                      }
		    }
		  break;
		case 4 :
		  if (vxMemProbe (ptr, READ, data_type, &longInt) != OK)
		    {
		      printf ("Bus error: address = %06x, data size = %d\n",
			      (unsigned int) ptr, data_type);
		    }
		  else
		    {
		      if((unsigned int)*ptr == value){
			printf("Value found at %08x\n",ptr); 
                      }
		    }
		}
	    }
	}
      printf("Finished scanning....\n");
      break;
    case 'l' :
      data_type = 4;
      break;
    case 'b' :
      data_type = 1;
      break;
    case 'w' :
      if (command [1] == 'o') 
	data_type = 2;
      else 
	{
	  scanned=sscanf(command,"%c %x %x",&ch,&ptr,&longInt); 
	  if (scanned != 3)
	    printf ("usage : w address value\n");
	  else 
	    {
	      switch (data_type)
		{
		case 1 : 
		  byte = (unsigned char) longInt;
		  if (vxMemProbe (ptr, WRITE, data_type, &byte) != OK)
		    printf ("Bus error: address = %06x, data size = %d\n",
			    (unsigned int) ptr, data_type);
		  else
		    printf("%06X : %02X\n",(unsigned) ptr, byte); 
		  break;
		case 2 : 
		  shortInt = (unsigned short) longInt;
		  if (vxMemProbe (ptr, WRITE, data_type, &shortInt) != OK)
		    printf ("Bus error: address = %06x, data size = %d\n",
			    (unsigned int) ptr, data_type);
		  else
		    printf ("%06X : %04X\n", (unsigned) ptr, shortInt);
		  break;
		case 4 :
		  if (vxMemProbe (ptr, WRITE, data_type, &longInt) != OK)
		    printf ("Bus error: address = %06x, data size = %d\n",
			    (unsigned int) ptr, data_type);
		  else
		    printf ("%06X : %08X\n", (unsigned) ptr, longInt);
		  break;
		}
	    }
	}
      break;
    case 'r' :
      scanned = sscanf (command,"%c %x", &ch,&ptr);
      if (scanned != 2)
	printf ("usage : r address\n");
      else 
	{
	  switch (data_type)
	    {
	    case 1 : 
	      if (vxMemProbe (ptr, READ, data_type, &byte) != OK)
		printf ("Bus error: address = %06x, data size = %d\n",
			(unsigned int) ptr, data_type);
	      else
		printf ("%06x : %02x\n",(unsigned) ptr, byte);
	      break;
	    case 2 : 
	      if (vxMemProbe (ptr, READ, data_type, &shortInt) != OK)
		printf ("Bus error: address = %06x, data size = %d\n",
			(unsigned int) ptr, data_type);
	      else
		printf ("%06x : %04x\n",(unsigned) ptr, shortInt);
	      break;
	    case 4 :
	      if (vxMemProbe (ptr, READ, data_type, &longInt) != OK)
		printf ("Bus error: address = %06x, data size = %d\n",
			(unsigned int) ptr, data_type);
	      else
		printf ("%06X : %08X\n", (unsigned) ptr, longInt);
	      break;
	    }
	}
      break;
    case 'd' :	/* use VxWorks display routine */
      scanned = sscanf (command,"%c %x", &ch,&ptr);
      if (scanned != 2)
	printf ("usage : d address\n");
      else
	{	
	  int x,y;
	  for (y=0;y<16;y++)
	    {
	      printf ("%06X-", (unsigned int) ptr);
	      for (x=0;x<16/data_type;x++, ptr += data_type)
		{
		  switch (data_type) 
		    {
		    case 1 : 
		      if (vxMemProbe (ptr, READ, data_type, &byte) != OK)
			{
			  printf ("Bus error: address = %06x, data size = %d\n",
				  (unsigned int) ptr, data_type);
			  return (1);
			}
		      else
			printf (" %02x", byte);
		      break;
		    case 2 :
		      if (vxMemProbe (ptr, READ, data_type, &shortInt) != OK)
			{
			  printf ("Bus error: address = %06x, data size = %d\n",
				  (unsigned int) ptr, data_type);
			  return (1);
			}
		      else
			printf (" %04x", shortInt);
		      break;
		    case 4 :
		      if (vxMemProbe (ptr, READ, data_type, &longInt) != OK)
			{
			  printf ("Bus error: address = %06x, data size = %d\n",
				  (unsigned int) ptr, data_type);
			  return (1);
			}
		      else
			printf (" %08x", longInt);
		      break;
		    }
		}
	      printf ("\n");
	    }
	}
      break;
    case 'h' : 
      help ();
      break;
    default :
      printf ("Unrecognized command.  Use h for help.\n");
      break;
    }
  return 1;
}

static void help ()
{

  printf ("===================================================\n");
  printf ("=                   Monitor                       =\n");
  printf ("=                By Scott Johnson                 =\n");
  printf ("===================================================\n");
  printf ("Commands:\n");
  printf ("[r]ead address..................reads given address\n");
  printf ("[w]rite address value...........writes value to address\n");
  printf ("[b]yte..........................read/write 8 bits\n");
  printf ("[wo]rd..........................read/write 16 bits\n");
  printf ("[l]ong..........................read/write 32 bits\n");
  printf ("[d]isplay address...............show memory at address\n");
  printf ("[f]ill address size value.......fill a block with value\n");
  printf 
  ("[s]scan start end value.........scan range between start end for value\n");
  printf ("[q]uit..........................quit\n");
  printf ("\n");
  printf ("Features:\n");
  printf ("1) Hit return to do a command again.\n");
  printf ("2) VxWorks history is supported\n");
  printf ("3) Redirect a script file while in the shell to easily\n");
  printf ("   setup multiple locations.\n");
  printf ("   Ex:   -> monitor < script_file  \n"); 
  printf ("\n");
  printf ("Remember to end script files with a 'q'\n");
  printf ("\n");
}


