📄 tm1if_generic.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 + -