📄 serial_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 : 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 + -