📄 tmmprun.c
字号:
/*
* COPYRIGHT (c) 1997 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. |
* +-----------------------------------------------------------------+
*
* Revision history :
* 10/26/96: CJP : Tested and basically working.
* More error checking and reporting added.
*
* 970106: Tilakraj Roy : Added support for the TMCons in tmDSPRunExecutable.
* Commenetd the use of tmDSPRunExecutable
* 970114: Tilakraj Roy : Added command line processing of windows size
* 970128: Tilakraj Roy : Added tmDSPExecutableStop in exit function
* 970327: Tilakraj Roy : Revamped the entire code for proper error handling
* Added the ExitEvent for proper cleanup.
* 970630: Tilakraj Roy : Added multiprocessor support.
* 970631: Tilakraj Roy : Added new cruntime support.
* 970728: Tilakraj Roy : Fixed exit code error bug.
*
*
* Description :
*
* This module is driver for the
* host part of the PC version of the Level 2
* Remote Procedure Call Server. An implementation
* of this is needed for each particular host of
* a TM-1 board which uses TCS's generic ANSI C library.
*
* In its current form this module is intended to run as
* an independent executable that must be
* started from a PC command line. Its first argument
* must be the name of a TM-1 executable which is to be
* downloaded, started, and which is passed all additional
* command line arguments. Between starting the executable
* and receiving its termination message, this module behaves
* as a server for the HostCall interface.
*
*/
/*---------------------------- Includes --------------------------------------*/
#include "windows.h"
#include "stdio.h"
#include "tmman32.h"
#include "tmtypes.h"
#include "tmcrt.h"
#include "tmif.h"
#include "TMDownLoader.h"
#define PGM_MAJOR_VERSION (4)
#define PGM_MINOR_VERSION (0)
DWORD GlobalExitCode = (~0x0);
BOOL Interactive = TRUE;
PCHAR TargetExecutableName = NULL;
DWORD TargetArgumentOffset;
BOOL WINAPI tmrunControlHandler(DWORD dwCtrlType);
#define MAXIMUM_NODES 4
#define MAXIMUM_COMMAND_LINE_ARGS 100
DWORD DSPCount = 0;
HANDLE EventArray[MAXIMUM_NODES];
STATUS tmDSPExecutableLoadEx (
DWORD DSPHandle,
PCHAR pszImagePath,
DWORD NumberOfDSPs,
TMDwnLdr_SharedSectionTab_Handle SharedSections,
PDWORD MMIOPhysicalAddressArray );
/*******************************************************************************/
int
main(int argc, char *argv[])
{
STATUS Status;
TMSTD_VERSION_INFO Version;
TMMAN_DSP_CAPS DSPCaps;
COORD ConsoleSize;
DWORD wIdxArg;
DWORD CRTHandle[MAXIMUM_NODES];
DWORD DSPHandle[MAXIMUM_NODES];
DWORD ArgumentCountArray[MAXIMUM_NODES];
PVOID ArgumentVectorArray[MAXIMUM_NODES];
DWORD IdxNode;
DWORD ArgumentCount;
DWORD MMIOPhysicalAddressArray[MAXIMUM_NODES];
CHAR* ArgumentVector[MAXIMUM_COMMAND_LINE_ARGS];
TMDwnLdr_SharedSectionTab_Handle SharedSections;
if (argc == 1)
{
goto mainUsage;
}
/* check for compatible driver version */
Version.dwMajor = TMMAN_DEFAULT_VERSION_MAJ;
Version.dwMinor = TMMAN_DEFAULT_VERSION_MIN;
if ((Status = tmNegotiateVersion(TMMAN_DEFAULT, &Version)) != TMOK)
{
fprintf(stderr, "tmmprun:tmNegotiateVersion:FAIL[0x%x](%s)\n",
Status,
tmGetErrorString(Status) );
goto mainExit1;
}
//install a control C handler so that we can perform cleanup before exit.
if (SetConsoleCtrlHandler(tmrunControlHandler, TRUE) != TRUE)
{
fprintf(stderr, "tmmprun:SetConsoleCtrlHandler:FAIL:[0x%x]\n", GetLastError());
goto mainExit1;
}
// count the number of DSPs we have download into
for ( wIdxArg = 1 ; wIdxArg < argc; wIdxArg++ )
{
// images indicates start of target executable names
if ( _stricmp ( argv[wIdxArg], "-exec" ) == 0 )
{
DSPCount++;
}
}
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
Status = tmDSPOpen(IdxNode, &DSPHandle[IdxNode]);
if (Status != TMOK)
{
fprintf(stderr, "tmmprun:tmDSPOpen:FAIL[0x%x](%s)\n",
Status,
tmGetErrorString(Status) );
goto mainExit2;
}
/* TBD : put error cheking here */
tmDSPGetCaps ( DSPHandle[IdxNode] , &DSPCaps );
MMIOPhysicalAddressArray[IdxNode] = DSPCaps.MMIO.dwPhysical;
}
//process the generic command line parameters here
for (wIdxArg = 1; wIdxArg < argc; wIdxArg++)
{
// images indicates start of target executable names
if ( _stricmp ( argv[wIdxArg], "-exec" ) == 0 )
{
// the next argument should be the name of the
// executable , point to it.
wIdxArg++;
break;
}
switch (toupper(argv[wIdxArg][1]))
{
case 'B':
Interactive = FALSE;
break;
case 'W':
{
DWORD dwWindowLines;
COORD ConsoleSize;
if (sscanf(&argv[wIdxArg][2], "%x", &dwWindowLines) != 1)
{
goto mainUsage;
}
ConsoleSize.X = 80;
ConsoleSize.Y = dwWindowLines;
SetConsoleScreenBufferSize(
GetStdHandle(STD_OUTPUT_HANDLE), ConsoleSize);
}
break;
//add other command line optons here
case '?':
default:
goto mainUsage;
}
}
//////////////////////////////////////////////////////////////////////////
TMDwnLdr_create_shared_section_table(&SharedSections);
cruntimeInit();
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
CRunTimeParameterBlock CRTParam;
DWORD i;
EventArray[IdxNode] = CreateEvent(
NULL, //not running on workstation 4.0
FALSE, //auto reset event
FALSE, //initial state is not signalled
NULL);
if (EventArray[IdxNode] == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "tmmprun:CreateEvent:FAIL:[0x%x]", GetLastError());
goto mainExit4;
}
CRTParam.OptionBitmap = 0;
CRTParam.StdInHandle = (DWORD) GetStdHandle(STD_INPUT_HANDLE);
CRTParam.StdOutHandle = (DWORD) GetStdHandle(STD_OUTPUT_HANDLE);
CRTParam.StdErrHandle = (DWORD) GetStdHandle(STD_ERROR_HANDLE);
// process target specific command line arguments here
// this parameter should be the executable filename
TargetExecutableName = argv[wIdxArg];
ArgumentCount = 0;
ArgumentVector[ArgumentCount++] = argv[wIdxArg];
for ( wIdxArg++ ; wIdxArg < argc; wIdxArg++)
{
// images indicates start of target executable names
if ( _stricmp ( argv[wIdxArg], "-exec" ) == 0 )
{
wIdxArg++;
break;
}
ArgumentVector[ArgumentCount++] = argv[wIdxArg];
}
ArgumentVector[ArgumentCount] = NULL;
// we have to allocate persistent storage for these values
ArgumentCountArray[IdxNode] = ArgumentCount;
if ( ( ArgumentVectorArray[IdxNode] =
malloc ( sizeof ( PVOID ) * ( ArgumentCount + 1 ) ) ) == NULL )
{
fprintf(stderr, "tmmprun:malloc:argv:FAIL\n" );
goto mainExit5;
}
memcpy ( ArgumentVectorArray[IdxNode] ,
ArgumentVector,
sizeof ( PVOID ) * ( ArgumentCount + 1 ) );
/*
for ( i = 0 ; i < ArgumentCountArray[IdxNode] ; i ++ )
{
printf ("Argument #%d = %s\n", i , ((PVOID *)ArgumentVectorArray[IdxNode])[i] );
}
*/
/////PERFORM RELOCATION HERE /////////////////////////
Status = tmDSPExecutableLoadEx (
DSPHandle[IdxNode],
TargetExecutableName,
DSPCount,
SharedSections,
MMIOPhysicalAddressArray );
///////////////////////////////////////////////////////
if (Status != TMOK)
{
fprintf(stderr, "tmmprun:tmDSPExecutableLoadEx(%s):FAIL[0x%x](%s)\n",
TargetExecutableName,
Status,
tmGetErrorString(Status) );
goto mainExit6;
}
CRTParam.OptionBitmap |= constCRunTimeFlagsUseSynchObject;
CRTParam.SynchronizationObject = (DWORD) EventArray[IdxNode];
CRTParam.VirtualNodeNumber = IdxNode; /* this is requried by juul's code */
if (!Interactive)
{
CRTParam.OptionBitmap |= constCRunTimeFlagsNonInteractive;
}
if (cruntimeCreate(
IdxNode,/* the physical DSP Number */
ArgumentCountArray[IdxNode],
ArgumentVectorArray[IdxNode],
&CRTParam,
&CRTHandle[IdxNode] ) != True)
{
fprintf(stdout,
"\ntmmprun:Cannot Initialize C Run Time Server : CRT I/O calls will not work:ERROR\n");
goto mainExit6;
}
}
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
TMMAN_TMCONS_PARAMS TMConsControl;
TMConsControl.fRedirectedStdin = FALSE;
TMConsControl.fRedirectedStdout = FALSE;
TMConsControl.fRedirectedStderr = FALSE;
TMConsControl.fUseWindowSize = FALSE;
TMConsControl.fIgnoreTMCons = TRUE;
TMConsControl.fUseTMMonWindow = FALSE;
Status = tmDSPExecutableRun(
DSPHandle[IdxNode],
TMMAN_DEFAULT,
&TMConsControl);
if (Status != TMOK)
{
fprintf(stderr,
"tmmprun:tmDSPExecutableRun:FAIL[0x%x](%s)\n",
Status,
tmGetErrorString(Status));
goto mainExit7;
}
}
WaitForMultipleObjects (DSPCount, EventArray, TRUE, INFINITE );
/*
mainExit7:
*/
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
tmDSPExecutableStop(DSPHandle[IdxNode] );
}
mainExit7:
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
GlobalExitCode = cruntimeDestroy(CRTHandle[IdxNode]);
}
mainExit6:
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
if ( ArgumentVectorArray[IdxNode] )
free ( ArgumentVectorArray[IdxNode] );
}
mainExit5:
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
CloseHandle(EventArray[IdxNode]);
}
mainExit4:
cruntimeExit();
TMDwnLdr_unload_shared_section_table(SharedSections);
mainExit3:
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
tmDSPClose ( DSPHandle[IdxNode] );
}
mainExit2:
SetConsoleCtrlHandler(tmrunControlHandler, FALSE);
mainExit1:
if (Interactive)
{
fprintf(stdout, "\ntmmprun:Press a key to close server >>");
getchar();
}
return (GlobalExitCode);
mainUsage:
fprintf(stderr, "usage:tmmprun [-b] [-wWindowSize] -exec ExecutableImageName1 [Arg1] [Arg2] ... -exec ExecutableImageName2 [Arg1] [Arg2] .....\n");
goto mainExit1;
}
BOOL WINAPI
tmrunControlHandler(DWORD dwCtrlType)
{
DWORD IdxNode;
fprintf(stderr, "\ntmmprun:Control C Detected : Performing Cleanup\n");
for ( IdxNode = 0 ; IdxNode < DSPCount ; IdxNode++ )
{
SetEvent(EventArray[IdxNode]);
}
return TRUE;
}
STATUS tmDSPExecutableLoadEx (
DWORD DSPHandle,
PCHAR pszImagePath,
DWORD NumberOfDSPs,
TMDwnLdr_SharedSectionTab_Handle SharedSections,
PDWORD MMIOPhysicalAddressArray )
{
PTMSTD_MEMORY_BLOCK pSDRAM;
TMMAN_DSP_CAPS DSPCaps;
TMMAN_DSP_INFO DSPInfo;
TMDwnLdr_Status LoaderStatus;
STATUS Status = TMOK;
DWORD ImageSize;
DWORD Alignment;
DWORD ClockSpeed = 0x5f5e100;
DWORD CacheOption = TMDwnLdr_LeaveCachingToDownloader;
DWORD AlignedDownloadAddress;
TMDwnLdr_Object_Handle ObjectHandle;
Endian endian;
CHAR szDeviceName[0x10];
/* TBD : put error cheking here */
tmDSPGetCaps ( DSPHandle , &DSPCaps );
/* TBD : put error checking here */
tmDSPGetMiscInfo ( DSPHandle , &DSPInfo );
pSDRAM = &DSPCaps.SDRAM;
if ( ( LoaderStatus = TMDwnLdr_load_object_from_file (
pszImagePath,
SharedSections,
&ObjectHandle ) ) != TMDwnLdr_OK )
{
//Status = TM_STATUS ( TMERRTMMAN32_ERR_OPENIMAGEFILEFAIL );
OutputDebugString ( TMDwnLdr_get_last_error (LoaderStatus) );
Status = TM_STATUS ( TMERR(TM_STATUS_HCOMP_TMLD, LoaderStatus) );
goto tmDSPExecutableLoadExit1;
}
if ( ( LoaderStatus = TMDwnLdr_get_endian (
ObjectHandle,
&endian ) ) != TMDwnLdr_OK )
{
OutputDebugString ( TMDwnLdr_get_last_error (LoaderStatus) );
Status = TM_STATUS ( TMERR(TM_STATUS_HCOMP_TMLD, LoaderStatus) );
goto tmDSPExecutableLoadExit2;
}
if ( endian != LittleEndian )
{
Status = TM_STATUS ( TMMAN32_ERR_IMAGENOTLITTLEENDIAN );
goto tmDSPExecutableLoadExit2;
}
if ( ( LoaderStatus = TMDwnLdr_resolve_symbol(
ObjectHandle,
"_TMMANSharedPatch",
DSPInfo.TMMANSharedPhys ) ) != TMDwnLdr_OK )
{
// for future reference store that this target image for this
// board doesn't have libtmman.a linked with it.
DSPInfo.Flags |= TMIF_DSPMISCINFO_SYMBOLNOTPATCHED;
tmDSPSetMiscInfo ( DSPHandle, &DSPInfo );
OutputDebugString( "tmman32:tmDSPExecutableLoad:WARNING:_TMMANSharedPatch:UNDEFINED\n" );
}
else
{
DSPInfo.Flags &= (~TMIF_DSPMISCINFO_SYMBOLNOTPATCHED);
tmDSPSetMiscInfo ( DSPHandle, &DSPInfo );
}
if ( ( LoaderStatus = TMDwnLdr_get_image_size ( ObjectHandle,
&ImageSize, &Alignment ) ) != TMDwnLdr_OK )
{
Status = TM_STATUS ( TMERR(TM_STATUS_HCOMP_TMLD, LoaderStatus) );
OutputDebugString ( TMDwnLdr_get_last_error (LoaderStatus) );
goto tmDSPExecutableLoadExit2;
}
AlignedDownloadAddress =
( (DSPCaps.SDRAM.dwPhysical + Alignment -1 ) & ( ~( Alignment - 1 ) ) );
// read in clock speed here
sprintf ( szDeviceName, "Device.%x", DSPCaps.DSPNumber );
ClockSpeed = GetPrivateProfileInt (
szDeviceName, "ClockSpeed", ClockSpeed, "tmman.ini" );
// read in Cache Option goes here
// the cache options are the same as the values defined in
// TMDownLoader.h this is kind of fucked up because
// TMDownloader enumerate TMDwnLdr_CacheingSupport changes
// the ini file values and hence documentatino will have to
// be update.
sprintf ( szDeviceName, "Device.%x", DSPCaps.DSPNumber );
CacheOption = GetPrivateProfileInt (
szDeviceName, "CacheOption", CacheOption, "tmman.ini" );
if ( ( LoaderStatus = TMDwnLdr_multiproc_relocate (
ObjectHandle,
tmWin95Host,
(Address*)MMIOPhysicalAddressArray,
DSPCaps.DSPNumber, // NodeNumber
NumberOfDSPs,// NumberOfNodes
ClockSpeed,
(Address)AlignedDownloadAddress,
DSPCaps.SDRAM.dwSize,
CacheOption ) ) != TMDwnLdr_OK )
{
OutputDebugString ( TMDwnLdr_get_last_error (LoaderStatus) );
Status = TM_STATUS ( TMERR(TM_STATUS_HCOMP_TMLD, LoaderStatus) );
goto tmDSPExecutableLoadExit2;
}
if ( ( LoaderStatus = TMDwnLdr_get_memory_image (
ObjectHandle,
(Address)tmPhysToLin ( AlignedDownloadAddress, &DSPCaps.SDRAM ) ) ) != TMDwnLdr_OK )
{
OutputDebugString ( TMDwnLdr_get_last_error (LoaderStatus) );
Status = TM_STATUS ( TMERR(TM_STATUS_HCOMP_TMLD, LoaderStatus ) );
goto tmDSPExecutableLoadExit2;
}
tmDSPExecutableLoadExit2 :
TMDwnLdr_unload_object ( ObjectHandle );
tmDSPExecutableLoadExit1 :
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -