📄 dos2udip.c
字号:
/****************************************************************************** * Copyright 1991 Advanced Micro Devices, Inc. * * This software is the property of Advanced Micro Devices, Inc (AMD) which * specifically grants the user the right to modify, use and distribute this * software provided this notice is not removed or altered. All other rights * are reserved by AMD. * * AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS * SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL * DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR * USE OF THIS SOFTWARE. * * Comments about this software should be directed to udi@amd.com. If access * to electronic mail isn't available, send mail to: * * Advanced Micro Devices, Inc. * 29K Support Products * Mail Stop 573 * 5900 E. Ben White Blvd. * Austin, TX 78741 * 800-292-9263 ***************************************************************************** * DOS386 changes were merged into: * $Id: dos2udip.c,v 1.2 1993/12/23 04:44:38 cassidy Exp $ * $Id: @(#)dos2udip.c 2.11, AMD */ /* TIPIPCId components */#define TIPIPCIdCompany 0x0001 /* Company ID from AMD, others should change this */#define TIPIPCIdVersion 0x124 /* Version */#ifdef DOS386#define TIPIPCIdProduct 0x3 /* Product ID for DOS386 IPC */#else#define TIPIPCIdProduct 0x2 /* Product ID for non-DOS386 IPC */#endif#include <stdio.h>#include <dos.h>#ifdef HAVE_STDLIB_H# include <stdlib.h>#endif#ifdef HAVE_STRING_H# include <string.h>#else# include <strings.h>#endif#include <udiproc.h>#include <udidos.h>static FILE * fpstdout = stdout; /* where we write the information */#ifndef DOS386#pragma check_stack( off )#pragma check_pointer( off ) /******************************************************** * In non-DOS386 mode, a standard C PTR is just a far real ptr * so FARCPTR_TO_REALPTR and REALPTR_TO_FARCPTR are pass-thru ********************************************************/#define FARCPTR_TO_REALPTR(p) p#define REALPTR_TO_FARCPTR(p) p#define IPCFar far /* qualifier for pointer that can reach the real data used by IPC */#define REALNULL NULLtypedef void far * FARCPTR;#else #include "malloc.h"#include "alloca.h"#include "pharlap.h"#include "realcopy.h"#define IPCFar _far /* qualifier for pointer that can reach the real data used by IPC */#define REALNULL (REALPTR) 0typedef void _far * FARCPTR; /******************************************************** * In DOS386 protected mode, we have two types of pointers, near and far * near is a 32-bit pointer, ie a 32-bit offset from DS. * far is a 48-bit pointer, with an explicit segment register. * We want to be able to convert real mode pointers (16-bit seg, 16-bit ofst) * into these near and far protected mode pointers and vice versa. * * It is always possible to convert a real mode pointer to a far prot ptr. * (Pharlap provides an explicit segment that maps to the low 1 meg of memory). ********************************************************/FARCPTR REALPTR_TO_FARCPTR(REALPTR p); /******************************************************** * The ability to convert from a real mode pointer to a near protected * pointer depends on being able to map converntional memory onto the * end of our data segment. This is NOT possible under DPMI 0.90 * If we're not under DPMI 0.90, * REALPTR_TO_NEARCPTR takes a real ptr, and returns its offset * in the SS_DATA segment (using the fact that the 1 meg of real * memory was mapped to the SS_DATA by dx_map_physical). * ********************************************************/#define REALPTR_TO_NEARCPTR(rp) ((void *)(&conventional_memory[LINEARIZE(rp)])) /********************************************************** * LINEARIZE converts a segment:ofst pointer into a linear * addr between 0 and 1meg *********************************************************/#define LINEARIZE(rp) ((RP_SEG(rp)<<4) + RP_OFF(rp)) /******************************************************** * FARCPTR_TO_REALPTR converts a far protected ptr to a real ptr. * Naturally, only certain protected pointers can be converted * into real pointers (they must map to something in the * first 1 meg of memory). If it can't be converted, it's * a fatal error. This is a routine rather than a macro. * If we need to convert a near prot ptr to a real ptr, * this can be done by simply casting it to a far * ********************************************************/REALPTR FARCPTR_TO_REALPTR(FARPTR p);extern USHORT GetCS();extern USHORT GetDS();#endif /* DOS386 *//****************** External Prototypes *****************************/extern void TIPPrintUsage(char *arg);#ifndef DOS386extern UDIError UDIASMDisconnect UDIParams(( UDISessionId Session, /* In */ UDIBool Terminate, /* In */ DOSTerm far *TermStruct /* In - not seen in UDIP */ ));extern UDIError UDIASMConnect UDIParams(( char *Configuration, /* In */ UDISessionId *Session, /* Out */ DOSTerm far *TermStruct /* In - not seen in UDIP */ ));#endif/****************** Internal Prototypes *****************************/UDIError UDICCapabilities UDIParams(( UDIUInt32 *TIPId, /* Out */ UDIUInt32 *TargetId, /* Out */ UDIUInt32 DFEId, /* In */ UDIUInt32 DFE, /* In */ UDIUInt32 *TIP, /* Out */ UDIUInt32 *DFEIPCId, /* Out */ UDIUInt32 *TIPIPCId, /* Out */ char *TIPString /* Out */ ));static unsigned short GetPSP( void );static void SetPSP( unsigned short PSPSegment );static unsigned int ComputeTSRSize(void *topofstack);static void SetupEnvironment(void);static void TerminateTIP UDIParams((DOSTerm IPCFar *TermStruct));/****************** External and Static Data *****************************/static int ConnectCount;#ifdef DOS386char *conventional_memory; /* pointer to first byte of conventinal memory */ /* if 0, then conventional mem not mapped */USHORT our_tsr_psp; /* TIP's original PSP */USHORT dos_ext_psp; /* Dos extender PSP (TIP's parent) */extern REALPTR call_prot; /* These are in the module dostip.asm */extern USHORT code_selector;extern USHORT data_selector;extern USHORT segregblock[4];extern int end_real; /* marks end of stuff that must be placed in low mem */int * stack_table[3]; /* used when we need to get a new stack frame * to establish C context on each UDI call * but only if conventional memory didn't map */REALPTR real_basep; /* returned by realcopy */FARPTR prot_basep; /* returned by realcopy */USHORT rmem_adrp; /* returned by realcopy */extern char TIPName[]; /* in DOS386, defined in rmdata in dosdfe.asm */extern struct UDIVecRec TIPVecRec; /* in DOS386, defined in rmdata in dosdfe.asm */#else /* non-DOS386 static and external data */char TIPName[ FILENAME_MAX ]; /* in non-386 version, TIPName defined right here */struct UDIVecRec TIPVecRec = { /* in non-386 version, TIPVecRec defined right here */ UDIDOSTIPRecognizer, /* Initialized in main */ NULL, /* Pointer to next TIP */ NULL, /* Pointer to previous TIP */ TIPName, /* Name of the executable we were loaded as */ UDIASMConnect, UDIASMDisconnect, UDISetCurrentConnection, UDICCapabilities, UDIGetErrorMsg, UDIGetTargetConfig, UDICreateProcess, UDISetCurrentProcess, UDIDestroyProcess, UDIInitializeProcess, UDIRead, UDIWrite, UDICopy, UDIExecute, UDIStep, UDIStop, UDIWait, UDISetBreakpoint, UDIQueryBreakpoint, UDIClearBreakpoint, UDIGetStdout, UDIGetStderr, UDIPutStdin, UDIStdinMode, UDIPutTrans, UDIGetTrans, UDITransMode };#endifstruct UDIVecRec IPCFar * pTIPVecRec; /* pointer to TIPVecRec */ /* in DOS386, this points to real memory */static RealUDIVecRecPtr IPCFar * UDIVecP;static int loaded_from_exp_file = 0;void do_exit(int errcode){ /* this routine normally just calls exit but in the special case * of DOS386 mode AND we were loaded from a .exp file, then we want * to exit in a different way by calling exp_return */#ifdef DOS386extern void _exp_return(int err); if (loaded_from_exp_file) _exp_return(errcode); else#endif /* normal non-DOS386 and non-exp_file exit */ exit(errcode);}void do_dos_keep(int errcode, int tsrsize){ /* similar logic to do_exit above, but this time for dos_keep */#ifdef DOS386extern void _exp_return(int err); if (loaded_from_exp_file) _exp_return(errcode); else#endif /* normal non-DOS386 and non-exp_file dos_keep */ _dos_keep( 0, tsrsize );}void get_tip_name(int argc, char *argv[]){ /* This routine normally gets the Tipname from argv[1], but * in the special case of DOS386 and loaded as an exp file, * it gets the name from the stack */#ifdef DOS386 extern char * _top; if ((GetCS() & 0xfffc) != SS_CODE) { /* a CS that is not SS_CODE indicates that we were loaded as a .exp file. In that case, we don't want to exit or do a TSR, instead we want to return back to the DFE using _exp_return. */ loaded_from_exp_file = TRUE; strcpy(TIPName, _top+16); return; }#endif if ((argc!= 2) || (argv[1][0] == '-')) { TIPPrintUsage(argv[1]); do_exit( 1 ); } strcpy( TIPName, argv[1] );}#ifdef DOS386REALPTR FARCPTR_TO_REALPTR(FARCPTR p) /* converts a FAR PROT ptr to a REALPTR */{REALPTR dummyrp;int err; /* returns a real mode pointer given a prot mode pointer p */ err = _dx_toreal(p, 0, &dummyrp); if (err) { printf("Fatal Error _dx_toreal(%04x:%08x)\n", FP_SEG(p), FP_OFF(p)); do_exit(err); } else return(dummyrp); }FARCPTR REALPTR_TO_FARCPTR(REALPTR rp){FARCPTR dummyfp; FP_SET(dummyfp, LINEARIZE(rp), SS_DOSMEM); return(dummyfp);}/***************** * Routine used to create and initialize a stack for C context stack switching * (used only when conventional memory can't be mapped ****************/static void create_stack(int stack_index, int size_in_bytes){int *p;int index_to_last_int; /* malloc appropriate size and point stack_table entry to second last word */ p = (int *)malloc(size_in_bytes); if (p == 0) { printf("\nTIP: unable to malloc stacks\n"); do_exit(1); } index_to_last_int = (size_in_bytes/sizeof(int)) - 1; stack_table[stack_index] = &p[index_to_last_int-1]; /* and set last word to 0 (marked as free) */ /* set second last word to stack size (used for alloca checking) */ p[index_to_last_int-1] = size_in_bytes-8; p[index_to_last_int] = 0;}#endifstatic void TerminateTIP UDIParams(( DOSTerm IPCFar *TermStruct /* In - not seen in UDIP */ )){ /* Delink ourselves from the linked list of TIPs */ if (pTIPVecRec->Next != REALNULL) ((struct UDIVecRec IPCFar *)REALPTR_TO_FARCPTR(pTIPVecRec->Next))->Prev = pTIPVecRec->Prev; if (pTIPVecRec->Prev != REALNULL) ((struct UDIVecRec IPCFar *)REALPTR_TO_FARCPTR(pTIPVecRec->Prev))->Next = pTIPVecRec->Next; else *UDIVecP = pTIPVecRec->Next; /* no previous TIP, set the interrupt vector to point to our Next TIP */#ifdef DOS386{ if (loaded_from_exp_file) /* if we were loaded from an exp file, skip all this PSP stuff */ return; /* Under DOSEXT, our PSP is parented by the DOSEXTENDER's PSP */ /* We want to modify the DOSEXT's PSP to point to the DFE info */REALPTR ptr_dos_ext_psp_parent;REALPTR ptr_dos_ext_psp_termaddr; /* Set the dos_ext_psp's Parent PSP to the current PSP (ie, the DFE PSP)*/ RP_SET(ptr_dos_ext_psp_parent,0x16, dos_ext_psp); *((USHORT _far *)(REALPTR_TO_FARCPTR(ptr_dos_ext_psp_parent))) = GetPSP(); /* Set the dos_ext_psp's Terminate address to reasonable address in current PSP (DFE)'s program space */ RP_SET(ptr_dos_ext_psp_termaddr,0xa, dos_ext_psp); *((ULONG _far *)(REALPTR_TO_FARCPTR(ptr_dos_ext_psp_termaddr))) = (ULONG) TermStruct->TermFunc;}#else /* Set our TSR's PSP's Parent PSP to the current PSP */ fflush(fpstdout); *(unsigned _far *)(((long)_psp << 16) + 0x16) = GetPSP(); /* Set our TSR's PSP's Terminate address to reasonable address in current PSP's program space */ /*(void _far (_far *) (void))(((long)_psp << 16) + 0xa) = ExitAddr;*/ *(void (_far *(_far *))(void))(((long)_psp << 16) + 0xa) = TermStruct->TermFunc;#endif /* Change DOS's notion of what the current PSP is to be our TSR's PSP */#ifdef DOS386 SetPSP(our_tsr_psp); /* Under Dosext, termination will chain back from our_psp to DOSEXT PSP */ /* and then back to the DFE (since we modified the DOSEXT PSP above) */#else SetPSP(_psp );#endif /* Terminate the program by using DOSTerminate 0x21/0x4c. Execution will resume at the Terminate address set above with ALL REGISTERS UNKNOWN especially SS:SP, DS, ES, etc */ bdos( 0x4c, 0, 0 ); }UDIError UDICConnect UDIParams(( char *Configuration, /* In */ UDISessionId *Session, /* Out */ DOSTerm IPCFar *TermStruct /* In - not seen in UDIP */ )){ UDIError err; if ((err = UDIConnect( Configuration, Session )) <= UDINoError) ConnectCount++; if (ConnectCount == 0) { /* Terminate the unused TIP */ /* Save the error status in the TermStruct */ TermStruct->retval = err; TerminateTIP( TermStruct ); /* Never returns */ } return err; }UDIError UDICDisconnect UDIParams(( UDISessionId Session, /* In */ UDIBool Terminate, /* In */ DOSTerm IPCFar *TermStruct /* In - not seen in UDIP */ )){ UDIError err; /* Disconnect via the real TIP */ if ((err = UDIDisconnect( Session, Terminate )) == UDINoError) ConnectCount--; if (Terminate != UDIContinueSession && ConnectCount == 0) { /* Terminate the unused TIP */ /* Save the error status in the TermStruct */ TermStruct->retval = err; TerminateTIP( TermStruct ); /* Never returns */ } return err; }UDIError UDICCapabilities UDIParams(( UDIUInt32 *TIPId, /* Out */ UDIUInt32 *TargetId, /* Out */ UDIUInt32 DFEId, /* In */ UDIUInt32 DFE, /* In */ UDIUInt32 *TIP, /* Out */ UDIUInt32 *DFEIPCId, /* Out */ UDIUInt32 *TIPIPCId, /* Out */ char *TIPString /* Out */ )){ UDIError err; err = UDICapabilities( TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId, TIPString ); *TIPIPCId = (((UDIUInt32)TIPIPCIdCompany) << 16) | (TIPIPCIdProduct << 12) | TIPIPCIdVersion; return err; }static RealUDIVecRecPtr IPCFar * AllocateIntVect(){ RealUDIVecRecPtr IPCFar * VecP; /* Try and find a vector that is unused */ for (VecP = (RealUDIVecRecPtr IPCFar *)(REALPTR_TO_FARCPTR(0x60*4)); VecP <= (RealUDIVecRecPtr IPCFar *)(REALPTR_TO_FARCPTR(0x66*4)); VecP++) { if (*VecP == REALNULL) return VecP; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -