⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial_tm1if_generic.c

📁 PNX系列设备驱动 PNX系列设备驱动
💻 C
字号:
/*
 *  COPYRIGHT (c) 1995 by Philips Semiconductors
 *
 *   +-----------------------------------------------------------------+
 *   | THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED |
 *   | AND COPIED IN ACCORDANCE WITH THE TERMS AND CONDITIONS OF SUCH  |
 *   | A LICENSE AND WITH THE INCLUSION OF THE THIS COPY RIGHT NOTICE. |
 *   | THIS SOFTWARE OR ANY OTHER COPIES OF THIS SOFTWARE MAY NOT BE   |
 *   | PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. THE   |
 *   | OWNERSHIP AND TITLE OF THIS SOFTWARE IS NOT TRANSFERRED.        |
 *   +-----------------------------------------------------------------+
 *
 *  Module name              : Serial_TM1IF_Generic.c    1.9
 *
 *  Module type              : IMPLEMENTATION
 *
 *  Title                    : Implementation of HostCall interface
 *
 *  Author                   : Juul van der Spek 
 *
 *  Last update              : 12:48:57 - 99/12/22
 *
 *  Reviewed                 : 
 *
 *  Revision history         : 
 *
 *  Description              :  
 *
 *            This module is part of an implementation of the server part  
 *            for a HostCall interface. HostCall is the software component 
 *            which is required by the TCS toolset to adapt the programs 
 *            generated by this toolset to a specific host (see file 
 *            HostCall.h in the TCS include dir).
 *
 *            HostIF is the part of the implementation which runs on the
 *            host, serving all IO requests of the TM-1 application. 
 *            HostIF is one of two modules of this host-resident part, and
 *            defines all host specific issues which are communication
 *            with the target and the ability to start a number of server
 *            tasks. The other part, RPCClient, defines *how* messages 
 *            should be served; RPCClient it still is host independent.
 *
 *            RPCServ is the counterpart of RPCClient on the target, and
 *            TM1IF is the counterpart of HostIF on the target. However,
 *            contrary to the target situation, where RPCClient is built
 *            on top of HostIF, on the host side TM1IF is built on top of
 *            RPCServ. Hence TM1IF forms the external interface of the 
 *            server pair.
 *
 *            SerialTM1IF interfaces to this target by means of a message 
 *            passing interface. This message passing interface is defined
 *            in SerialRPCDriver, and must be implemented by the user.
 *
 */

/*---------------------------- Includes --------------------------------------*/

#define SERIAL_RPC

#include <stdarg.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include <setjmp.h>
#include <errno.h>
#include "fcntl.h"
#include "stdio.h"
#include "stdlib.h"

#ifdef __MWERKS__
#include <MacMemory.h>
#include <Threads.h>
#include <types.h>
#include <stat.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#endif

#include "tmtypes.h"
#include "Lib_Local.h"
#include "HostCall.h"
#include "mmio.h"
#include "TM1IF.h"
#include "RPC_Common.h"
#include "RPCServ.h"
#include "tmInterrupts.h"
#include "OpenDll.h"
#include "SerialRPC.h"
#include "SerialRPCDriver.h"

/*---------------------------- Module State ----------------------------------*/


/*
 * Various global state:
 */
static Bool       serving_stopped;
static Bool       same_endian= True;

static HostCall_command g_command_buffer;

Pointer           TM1IF_in_buffer;
Pointer           TM1IF_in_buffer2;
Pointer           TM1IF_result_buffer;
HostCall_command* TM1IF_command_buffer = &g_command_buffer;
static Int        TM1IF_result_buffer_len;

/*---------------------------- Communication Functions -----------------------*/


static void SerialRPC_write_byte(Byte b)
{
    SerialRPC_write_buffer(&b,1);
}


static Int32 SerialRPC_read_int()
{
    Int32 result;

    SerialRPC_read_buffer(&result,sizeof(Int32));

    if (!same_endian) {
        return TM1IF_endian_swap(result);
    } else {
        return result;
    }
}


static Byte SerialRPC_read_byte()
{
    Byte result;

    SerialRPC_read_buffer(&result, 1);

    return result;
}

/*---------------------------- Communication Functions -----------------------*/



static HostCall_command* get_pending_request()
{
    Byte command= SerialRPC_read_byte();

    if (command == SERIAL_XFer_Input) {
        Int len= SerialRPC_read_int();

        TM1IF_in_buffer= (Pointer)malloc(len);
        assert(TM1IF_in_buffer);  /* ADD: checking */

        SerialRPC_read_buffer( TM1IF_in_buffer, len );

        command= SerialRPC_read_byte();
    }

    if (command == SERIAL_XFer_Input) {
        Int len= SerialRPC_read_int();

        TM1IF_in_buffer2= (Pointer)malloc(len);
        assert(TM1IF_in_buffer2);  /* ADD: checking */

        SerialRPC_read_buffer( TM1IF_in_buffer2, len );

        command= SerialRPC_read_byte();
    }

    if (command == SERIAL_XFer_IOutput) {
        TM1IF_result_buffer_len= SerialRPC_read_int();
        TM1IF_result_buffer    = (Pointer)malloc(TM1IF_result_buffer_len);
        assert(TM1IF_result_buffer);  /* ADD: checking */

        SerialRPC_read_buffer( TM1IF_result_buffer, TM1IF_result_buffer_len );
        command= SerialRPC_read_byte();

    } else 
    if (command == SERIAL_XFer_Output) {
        TM1IF_result_buffer_len= SerialRPC_read_int();
        TM1IF_result_buffer    = (Pointer)malloc(TM1IF_result_buffer_len);
        assert(TM1IF_result_buffer);  /* ADD: checking */

        command= SerialRPC_read_byte();
    } 

    assert( command == SERIAL_XFer_Command );

    SerialRPC_read_buffer( TM1IF_command_buffer, sizeof(HostCall_command) );

    return TM1IF_command_buffer;
}



static void send_back( HostCall_command* raw_command )
{
    assert(raw_command == TM1IF_command_buffer);

    SerialRPC_write_buffer(&raw_command->requester, sizeof(Pointer) );

    if (TM1IF_result_buffer != Null) {
        SerialRPC_write_buffer( TM1IF_result_buffer, TM1IF_result_buffer_len );
        free(TM1IF_result_buffer); 
        TM1IF_result_buffer= Null;
    } 
    if (TM1IF_in_buffer != Null) {
        free(TM1IF_in_buffer); 
        TM1IF_in_buffer= Null;
    } 
    if (TM1IF_in_buffer2 != Null) {
        free(TM1IF_in_buffer2); 
        TM1IF_in_buffer2= Null;
    } 
    SerialRPC_write_buffer( TM1IF_command_buffer, sizeof(HostCall_command) );
}



/*--------------------------- Exported Functions -----------------------------*/



/*
 * Function         : Initialise this module, and make the
 *                    I/O callback functions known to it.
 * Parameters       : open .. exit        (I) IO functions.
 *                    endian              (I) node's endianness
 * Function Result  : True iff initialisation succeeded
 */

Bool TM1IF_init(
	RPCServ_OpenFunc    open,
	RPCServ_OpenDllFunc open_dll,
	RPCServ_CloseFunc   close,
	RPCServ_ReadFunc    read,
	RPCServ_WriteFunc   write,
	RPCServ_SeekFunc    seek,
	RPCServ_IsattyFunc  isatty,
	RPCServ_FstatFunc   fstat,
	RPCServ_FcntlFunc   fcntl,
	RPCServ_StatFunc    stat,
	RPCServ_ExitFunc    exit,
        Endian              endian                
     )
{
        serving_stopped= False;

        if ( !SerialRPC_init()                                   ) { return False; }
        if ( !SerialRPC_read_byte() == SERIAL_XFer_endian_probe  ) { return False; }

	same_endian = (SerialRPC_read_int() == 1);

	return 
	   RPCServ_init(
		open,
		open_dll,
		close,
		read,
		write,
		seek,
		isatty,
		fstat,
		fcntl,
		stat,
		exit,
		endian                
	   );
}



/*
 * Function         : Add information on new node 
 * Parameters       : node_number         (I) Node number assigned to executable
 *                                            via TMDownLoader interface.
 *                    argc, argv          (I) Command line arguments
 *                    Stdin,Stdout,Stderr (I) file descriptors to be used as
 *                                            standard file descriptors.
 *                                            NB: these must be legal parameter
 *                                                values for the IO functions
 *                    address_shift       (I) the difference between the virtual
 *                                            and physical address of the each location
 *                                            in the node's SDRAM, as seen from the host
 *                    sdram_base          (I) physical address of the node's SDRAM start
 *                    sdram_limit         (I) physical address of the node's SDRAM limit
 *                    data                (I) additional, monitor specific data
 * Function Result  : True iff add succeeded.
 */

Bool TM1IF_add_node_info( 
           UInt32    node_number,
           UInt32    argc,
           String   *argv,
           UInt32    Stdin,
           UInt32    Stdout,
           UInt32    Stderr,
           UInt32    address_shift,
           UInt32    sdram_base,
           UInt32    sdram_limit,
           Pointer   data
     )
{
	return 
	     RPCServ_add_node_info( 
		   node_number,
		   argc,
		   argv,
		   Stdin,
		   Stdout,
		   Stderr,
		   address_shift,
                   sdram_base,
                   sdram_limit,
                   Null,
                   Null
	     );
}



/*
 * Function         : Remove information on node, when present. 
 * Parameters       : node_number         (I) Node number assigned to executable
 *                                            via TMDownLoader interface.
 * Function Result  : -
 */

void TM1IF_remove_node_info( UInt32 node_number )
{
    RPCServ_remove_node_info(node_number);
}



/*
 * Function         : Start serving the (independently started)
 *                    TM-1 application. Serving should use the specified
 *                    IO functions, and use the specified file descriptors
 *                    for stdin, stdout and stderr. It should try to 
 *                    start the requested number of serving tasks and return,
 *                    but when there are no capabilities for starting 
 *                    tasks this function itself can act as server before
 *                    it returns.
 * Function Result  : see module header
 * Precondition     : -
 * Postcondition    : -
 * Sideeffects      : -
 */

TM1IF_Served_Status
        TM1IF_start_serving( )
{
        while (!serving_stopped) {
            HostCall_command*  raw_command;

            raw_command= get_pending_request();

            if (serving_stopped) { break; }

            if (RPCServ_serve(raw_command)) {
                send_back(raw_command);
            }
        }

        RPCServ_term();

        return TM1IF_Serving_Completed;
}




/*
 * Function         : Terminate this module
 * Parameters       : -
 */

void TM1IF_term()
{
    serving_stopped= True;

#ifdef DEBUG
    if (tracefile) fclose(tracefile);
    tracefile = NULL;
#endif
}



UInt32 TM1IF_endian_swap( UInt32 value )
{ 
    return (same_endian
           ? value
           : LIENDIAN_SWAP4(value)); 
}

UInt32 TM1IF_endian_swap_short (UInt32 value)
{ 
   return same_endian? value: LIENDIAN_SWAP2 (value);
}

/* ------------------------------------ main program ------------------------------- */

        static Int32 exit_status;

	static int exitf(UInt32 node_id, Int32 status) 
	{
	    exit_status = status;
	
	    TM1IF_term();
		    
	    return 0; 
	}


        static Int32 open_dll( String path ) 
        { 
            return 
               OpenDll_open_dll(
                     path,
                     (RPCServ_OpenFunc)open,
                     LCURRENT_ENDIAN
               ); 
        }


Int32 _serial_main(Int argc, String argv[])
{
	if ( TM1IF_init(
		   (RPCServ_OpenFunc)    open,
		   (RPCServ_OpenDllFunc) open_dll,
		   (RPCServ_CloseFunc)   close,
		   (RPCServ_ReadFunc)    read,
		   (RPCServ_WriteFunc)   write,
		   (RPCServ_SeekFunc)    lseek,
		   (RPCServ_IsattyFunc)  isatty,
		   (RPCServ_FstatFunc)   fstat,
		   (RPCServ_FcntlFunc)   fcntl,
		   (RPCServ_StatFunc)    stat,
		   (RPCServ_ExitFunc)    exitf,
		   0)
           ) {
		TM1IF_add_node_info(0, argc, argv, 0, 1, 2, 0, 0, -1, Null);
	
		TM1IF_start_serving();
	
		return exit_status;

        } else {
                return -1;
        }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -