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

📄 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              : TM1IF_Generic.c    1.45
 *
 *  Module type              : IMPLEMENTATION
 *
 *  Title                    : PC version of HostCall server, PC part
 *
 *  Author                   : Juul van der Spek 
 *
 *  Last update              : 11:03:47 - 99/03/29
 *
 *  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.
 *
 *            The interface to this module is as follows: First, it should
 *            be initialised. Second, a number of nodes should be defined, 
 *            specifying node specific information. 
 *            After this, the nodes can be started and a communication
 *            session with these nodes can be started by means of function
 *            TM1IF_start_serving; depending on the implementation, a call
 *            to this function either immediately returns, with a number
 *            of serving tasks created for handling target's IO requests,
 *            or it blocks until function TM1IF_term is called (typically
 *            by the exit handler, when the last node has reported termination).
 *
 *            Having a pool of servers reduces the possibility that serving
 *            is halted due to serving requests which take a longer 
 *            time to complete. For instance, when running pSOS on the 
 *            target with one task requesting keyboard input from the host, 
 *            the current implementation of RPCClient will stop serving 
 *            requests when only one server task is selected: while blocked 
 *            on the keyboard, it will not be able to serve requests from 
 *            other pSOS tasks. 
 *            The current host (with the OS used) might or might not be
 *            able to dispatch multiple tasks, so start_serving returns
 *            one of the following results:
 *                - TM1IF_Serving_Failed
 *                           Initialisation (e.g. setup of target
 *                           communication, or server task creation) 
 *                           failed.
 *                - TM1IF_Serving_Started
 *                           The servers have been created, and
 *                           are now busy serving.
 *                           Serving should be stopped using the
 *                           TM1IF_term function.
 *                - TM1IF_Serving_Completed
 *                           TM1IF was not capable of creating independent 
 *                           serving tasks, so the TM-1 application
 *                           has been entirely served during the call
 *                           to start_serving.
 *           
 *            NB: This interface does not provide for loading and
 *                starting the TM1 appication. 
 *
 *           This is a simple TM1IF implementation using one RPCServer 
 *           which uses polling. Communication by polling is inherently  
 *           synchronous, in the sense that the target always waits
 *           for host requests to fully complete. 
 *           For this reason, the TM1IF communication part from host to
 *           target need not be implemented.
 *           Such polling is not very friendly in a multithreaded TM-1 system.
 */

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

#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>
#endif

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

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


/*
 * Various global state:
 */
static FILE      *tracefile;
static volatile   Pointer dummy;
static Bool       serving_stopped;
static Bool       same_endian;

volatile Pointer *_HostCall_commvar;



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



static Pointer get_pending_request()
{
    Pointer result;

    result= _HostCall_commvar[0]; 

    while (result == NULL) {
#ifdef __MWERKS__
        YieldToAnyThread();
#endif		  
        result= _HostCall_commvar[0]; 
    }

   _HostCall_commvar[0]= NULL;

    return result;
}



static void send_back( Pointer raw_command )
{
        RPCServ_NodeInfo *node_info= RPCServ_raw_to_info(raw_command);

       /*
        * Do an SDRAM read, in order to force 
        * all writes of results by the PC to 
        * complete. 
        */
       _HostCall_commvar[1] = raw_command;

        dummy= _HostCall_commvar[1];

        MMIO_M( node_info->node_number, IPENDING)= 1 << intHOSTCOMM;

        while (_HostCall_commvar[1] != NULL) {
#ifdef __MWERKS__
		  YieldToAnyThread(); 
#endif		  
	}
}



/*--------------------------- 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                
     )
{
       _HostCall_commvar[0]= Null;
       _HostCall_commvar[1]= Null;

        serving_stopped= False;
        same_endian    = endian==LCURRENT_ENDIAN;

        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) {
            Pointer  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;
   _HostCall_commvar[0]= (Pointer)1;
}

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);
}

Address TM1IF_tm2host( RPCServ_NodeInfo *ninfo, Address tm_address )
{ 
    return (tm_address == Null)
           ? Null
           : (Address)(TM1IF_endian_swap((Int32)tm_address)+ninfo->address_shift); 
}

Address TM1IF_host2tm( RPCServ_NodeInfo *ninfo, Address host_address )
{
    return (host_address == Null) 
          ? Null
	  : (Address)TM1IF_endian_swap(((Int32)host_address)-ninfo->address_shift);
}




⌨️ 快捷键说明

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