rmonmain.c 7.04 KB
/*
 * ==========================================================================
 * Copyright (c) 1994, Silicon Graphics, Inc.  All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
 * the contents of this file may not be disclosed to third parties, copied
 * or duplicated in any form, in whole or in part, without the prior written
 * permission of Silicon Graphics, Inc.
 *
 * RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to restrictions
 * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
 * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
 * successor clauses in the FAR, DOD or NASA FAR Supplement.  Unpublished
 * rights reserved under the Copyright Laws of the United States.
 * ==========================================================================
 */

/************************************************************************
Program: rmon (reality monitor) in-circuit target monitor
File: main.c
Contents: This file is the main entry point and communication functions
	for HERMON execution environments.
Author: Kenneth F. Greenberg
Revision history:
	94.10.21  Original
************************************************************************/

#include "rmonint.h"
#include "rcp.h"
#include <rdb.h>

#ifndef _FINALROM

#define BDBIT 0x80000000
#define PAUSE 15000

int __rmonActive = 0;		/* flag so others can know if rmon is alive */

static vu32 somethingToDo;
static u32 inbuffer[MAXENCODED/4];

static u8 cmdinptr, cmdoutptr;

static int state;		/* current state of the command parser */
static char * inPointer;	/* current read location in input buffer */


/************************************************************************
Function: __rmonSendHeader
Args:
	KKHeader * block - address of the standard protocol structure for
		packet headers - or maybe more... At least, the address
		of what is to be sent.
	u32 blockSize - how many bytes to send
	u32 type - what type of message this is (reply, exception, ...)
Type: void
Purpose: This function sends a header (or perhaps a whole packet) to
	the host debugger. Normally, it is called by SendReply and
	implements the entire reply transmission. (Note that it does
	not look at what it is sending to see if it is ONLY a header.)
	For very large (unbuffered) packets, we send the header separately
	and then send the data later. Thus, this function may really
	send only the header in some cases. This has been isolated to
	a separate function to avoid duplication of code.
************************************************************************/
void __rmonSendHeader( KKHeader * const block, u32 blockSize, u32 type )
{
    int   sent;
    unsigned char *cPtr = (unsigned char *)block;

    /* set the version number */

    block->rev = VERSION;
    block->type = type;

    sent = 0;
    while(sent < blockSize)
	sent += __osRdbSend(cPtr + sent, blockSize - sent, RDB_TYPE_GtoH_DEBUG);

}

/************************************************************************
Function: __rmonSendReply
Args:
	KKHeader * block - address of the standard protocol structure for
		a header and associated data.
	u32 blockSize - number of bytes to send
Type: void
Purpose: This function sends a buffered reply packet to the host
	debugger. It is passed the beginning of the reply buffer and
	the number of bytes to transmit. It assumes the size of the block
	is the number of bytes to be sent, and so fills it in for the
	caller. It then invokes SendHeader to do the transmission.
	Some functions (e.g., read mem) do not use this mechanism,
	since they do not buffer the packet. Note also that declaring
	a large packet counts as buffering, since the entire reply
	packet exists at consecutive memory locations.
************************************************************************/
void __rmonSendReply( KKHeader * const block, u32 blockSize, u32 replyType )
{
    unsigned char  *cPtr;
    int            sent = 0;

    block->length = blockSize;

    cPtr = (unsigned char*)&blockSize;

    /* send the size of the transfer */
    while(sent < 4)
	sent += __osRdbSend(&cPtr[sent],4-sent,RDB_TYPE_GtoH_DEBUG);

    __rmonSendHeader( block, blockSize, replyType );

    __rmonIOflush(); 
}

/************************************************************************
Function: __rmonSendData
Args:
	const char * block - address of data to be sent
	unsigned int blockSize - number of bytes to send
Type: void
Purpose: This function sends a block of memory from the target to the
	host debugger. In all cases, it is safe to assume that SendHeader
	has already been called to prepare the host to receive this info.
	The primary purpose of this function is to implement the ReadMem
	command, which is unbuffered.
************************************************************************/
void __rmonSendData( const char * block, unsigned int blockSize )
{
    int * blockPointer = (int *) block;
    unsigned int wordCount;
    u32 data;
    union {
	char bufBytes[4];
	u32 bufWord;
    } buffer;


    wordCount = (blockSize + 3) >> 2;
    
    /*
      Look for the easy case first - even number of words starting on
      a word boundary. For the real hardware or the emulator, do a 
      range check on RCP memory, which must be done specially.
    */
    
    if ( ((u32) block & 3) == 0 )
    {
	while ( wordCount-- )
	{
	    if ( (u32) blockPointer >= RCPMEM_START &&
		 (u32) blockPointer <= RCPMEM_END )
	    {
		__osSpRawReadIo( (u32) blockPointer++, &data );
		__rmonIOputw( data );
	    }
	    else
		__rmonIOputw( *blockPointer++ );
	}
    }
    else while ( wordCount-- )
    {
	__rmonMemcpy( (u8 *) &buffer.bufBytes, (u8 *) blockPointer, 4 );
	__rmonIOputw( buffer.bufWord );
	++blockPointer;
    }
    __rmonIOflush();
}

/************************************************************************
Function: rmonMain
Args: none
Type: void
Purpose: This is the main loop of the rmon debugger. It is mostly a protocol
	parser/dispatcher.
************************************************************************/
void rmonMain( void )
{
    register int newChars;

    somethingToDo = 0;
    cmdinptr = cmdoutptr = 0;
	
    __rmonInit();
    __rmonActive = 1;


    /*
     *     Loop forever acquiring commands
     */

    for ( state = 0, newChars = 0, inPointer = (char *) inbuffer; ; )
    {
	OSMesg work;

	osRecvMesg( &__rmonMQ, &work, OS_MESG_BLOCK );
	somethingToDo |= (u32) work;

	if ( somethingToDo & MSG_BREAKPOINT )
	{
	    somethingToDo &= ~MSG_BREAKPOINT;
	    __rmonHitBreak();
	}

	if ( somethingToDo & MSG_SPBREAKPOINT )
	{
	    somethingToDo &= ~MSG_SPBREAKPOINT;
	    __rmonHitSpBreak();
	}
	
	if ( somethingToDo & MSG_CPUFAULT )
	{
	    somethingToDo &= ~MSG_CPUFAULT;
	    __rmonHitCpuFault();
	}
	
	if ( somethingToDo & MSG_THREADCREATE )
	{
	    Debug( "rmon: Thread %d created\n", somethingToDo >> 8 );
	    somethingToDo &= ~(MSG_THREADCREATE | 0xffffff00);
	}

	if ( somethingToDo & MSG_THREADDESTROY )
	{
	    Debug( "rmon: Thread %d destroyed\n", somethingToDo >> 8 );
	    somethingToDo &= ~(MSG_THREADDESTROY | 0xffffff00);
	}
    }
}

#endif /* #ifndef _FINALROM */