home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / utils / amd-udi / udi / udip2dos.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-23  |  26.6 KB  |  1,086 lines

  1. /******************************************************************************
  2.  * Copyright 1991 Advanced Micro Devices, Inc.
  3.  *
  4.  * This software is the property of Advanced Micro Devices, Inc  (AMD)  which
  5.  * specifically  grants the user the right to modify, use and distribute this
  6.  * software provided this notice is not removed or altered.  All other rights
  7.  * are reserved by AMD.
  8.  *
  9.  * AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS
  10.  * SOFTWARE.  IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL
  11.  * DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR
  12.  * USE OF THIS SOFTWARE.
  13.  *
  14.  * Comments about this software should be directed to udi@amd.com. If access
  15.  * to electronic mail isn't available, send mail to:
  16.  *
  17.  * Advanced Micro Devices, Inc.
  18.  * 29K Support Products
  19.  * Mail Stop 573
  20.  * 5900 E. Ben White Blvd.
  21.  * Austin, TX 78741
  22.  *****************************************************************************
  23.  *       $Id: udip2dos.c,v 1.2 1993/12/23 04:45:04 cassidy Exp $
  24.  *       $Id: @(#)udip2dos.c    2.22, AMD
  25.  */
  26.  
  27. /* Modified M.Typaldos 11/92 - Added '386 specific code (mainly calls to
  28.  *              functions in dos386c.c, UDIPxxx calls).
  29.  */
  30.  
  31. #define _UDIP2DOS_C
  32.  
  33.  
  34. #if 1
  35. #define DFEIPCIdCompany 0x0001    /* Company ID AMD */
  36. #define DFEIPCIdProduct 0x1    /* Product ID 0 */
  37. #endif
  38. #define DFEIPCIdVersion 0x125    /* 1.2.5 */
  39.  
  40. #include <process.h>
  41. #include <stdio.h>
  42. #include <string.h>
  43. #include <stdlib.h>
  44. #include <ctype.h>
  45. #include <udiproc.h>
  46. #include <udidos.h>
  47.  
  48. #ifdef DOS386
  49. #include <pltypes.h>
  50. #include <pharlap.h>
  51. #include <dos386c.h>
  52. #include <realcopy.h>
  53.  
  54.     /* 
  55.      * term_addr will be used to store the protected mode address
  56.      * of TermStruct.  This is a 48 bit pointer into the area
  57.      * allocated by the call to realcopy.  The address is stored
  58.      * in term_addr by UDIConnect.
  59.      *
  60.      */
  61.     ULONG    *term_addr_ptr;    
  62.     FARPTR    term_addr;
  63.  
  64.     /********************************************************
  65.      * In DOS386 mode, a standard C PTR is a protected mode ptr
  66.      * so CPTR_TO_REALPTR invokes PROT_TO_REAL and REALPTR_TO_CPTR
  67.      * just invokes REAL_TO_PROT
  68.      ********************************************************/
  69. #define CPTR_TO_REALPTR(p) PROT_TO_REAL(p)
  70. #define REALPTR_TO_CPTR(p) REAL_TO_PROT(p)
  71.  
  72.  
  73. #else    /* not DOS386 */
  74.  
  75.     /********************************************************
  76.      * In non-DOS386 mode, a standard C PTR is just a far real ptr
  77.      * so CPTR_TO_REALPTR and REALPTR_TO_CPTR are noops
  78.      ********************************************************/
  79. #define CPTR_TO_REALPTR(p) (p)
  80. #define REALPTR_TO_CPTR(p) (p)
  81. #define NEARPTR_TO_FARPTR(p) (p)
  82.  
  83. #define _fstrcmp(a,b) strcmp(a,b)
  84.  
  85. #define FP_OFF(p) (p)
  86. #define REALPTR
  87.  
  88.     
  89.  
  90. #endif  /* DOS386 */
  91.  
  92.  
  93. #ifdef __HIGHC__
  94. /* hc386 doesn't have fstrcmp */
  95. /* this specialized version only works for strings less than 256 */
  96. /* which is good enough for comparing TIP names */
  97. int _fstrcmp(FARPTR s1, char _far * s2)
  98. {
  99. #define MAXFARSTR 256
  100.   char nears1[MAXFARSTR];
  101.   char nears2[MAXFARSTR];
  102.   extern USHORT    GetDS();
  103.  
  104.   _movedata(FP_SEL(s1), FP_OFF(s1), GetDS(), (unsigned int)nears1, MAXFARSTR);
  105.   _movedata(FP_SEL(s2), FP_OFF(s2), GetDS(), (unsigned int)nears2, MAXFARSTR);
  106.   return(strcmp(nears1,nears2));
  107.  
  108. }
  109.  
  110. #endif
  111.  
  112. #ifdef DOS386
  113. #include "io.h"
  114.     /* this routine takes a possibly incomplete executable name */
  115.     /* and uses the PATH environment variable to get the full name */
  116. void get_full_exe_name(char *TIPName, char *FullName)
  117. {
  118. char *path_env = getenv("PATH");
  119. char drive[10];
  120. char dir[128];
  121. char fname[10];
  122. char ext[10];
  123. char pathprefix[128];
  124. char pathdir[128];
  125. char *tmp;
  126.  
  127.     _splitpath(TIPName, drive, dir, fname, ext);
  128.     if (strlen(ext) == 0)
  129.     strcpy(ext, ".exe");    /* if no ext, force .exe */
  130.     if (dir[0] == '\\') {
  131.         /* absolute pathname, just return it */
  132.     _makepath(FullName, drive,dir,fname,ext);
  133.     return;
  134.     }
  135.     else {
  136.     /* not an absolute pathname, need to use PATH env var */
  137.         tmp = path_env;
  138.         while ( *tmp != '\0')
  139.         {
  140.             sscanf(tmp, "%[^;]", pathprefix);
  141.             sprintf (pathdir, "%s\\%s", pathprefix, dir);
  142.         _makepath(FullName, drive,pathdir,fname,ext);
  143.             if (access (FullName, 0) == 0 ) {  /* check for open with read access */
  144.                return;                /* found one, return with FullName set */
  145.             }
  146.             else {
  147.                 tmp += strlen(pathprefix) + 1;
  148.         }
  149.         }   /* while */
  150.     /* if we got this far, we didn't find a match */
  151.         *FullName = 0;
  152.     } /* if */
  153.     
  154. }
  155.  
  156.  
  157. int dpmi_exists(void)
  158. {
  159.     CONFIG_INF config;  /* for DPMI config info */
  160.     UCHAR vmmname[256];
  161.  
  162.     _dx_config_inf(&config, vmmname);    /* arg2 not really used here */
  163.     return(config.c_dpmif);
  164. }
  165.  
  166.  
  167. #endif
  168.  
  169. /*************************************************************
  170.  * The following macros allow us to use a common macro to make a UDICall
  171.  * for either real mode DFEs or DOS386 mode DFEs
  172.  *************************************************************/
  173. #if defined __STDC__ || defined _MSC_VER
  174. #define XCAT(a,b) a##b
  175. #else
  176. #define XCAT(a,b) a/**/b
  177. #endif
  178. #define CAT(a,b) XCAT(a,b)
  179.  
  180. #ifndef DOS386
  181.  
  182.     /************************************************
  183.      * in real mode, just call directly thru the connection pointer to the TIP
  184.      * eg, UDICALL3(p,f,a,b,c) becomes p->UDIf(a,b,c)
  185.      ************************************************/
  186. #define UDICALLPREFIX0(p,f) CAT(p->UDI,f)(
  187. #define UDICALLPREFIX(p,f)  UDICALLPREFIX0(p,f)     /* same for 0 or >0 args */
  188.  
  189. #else    /* not DOS386 */
  190.  
  191.  
  192.     /************************************************
  193.      * in DOS386 mode, call an intermediate function UDIPxxx
  194.      * and pass it a pointer to the TIP function, (along with all parameters)
  195.      * eg, UDICALL3(p,f,a,b,c) becomes UDIPf(p->UDIf,a,b,c)
  196.      ************************************************/
  197. #define UDICALLPREFIX0(p,f) CAT(UDIP,f)(CAT((REALPTR)p->UDI,f)
  198. #define UDICALLPREFIX(p,f)  UDICALLPREFIX0(p,f) ,    /* need a comma here for >0 args */
  199. #endif /* else on DOS386 */
  200.  
  201. #define UDICALL0(p,f)                 UDICALLPREFIX0(p,f) )
  202. #define UDICALL1(p,f,a1)             UDICALLPREFIX(p,f) a1)
  203. #define UDICALL2(p,f,a1,a2)             UDICALLPREFIX(p,f) a1,a2)
  204. #define UDICALL3(p,f,a1,a2,a3)             UDICALLPREFIX(p,f) a1,a2,a3)
  205. #define UDICALL4(p,f,a1,a2,a3,a4)         UDICALLPREFIX(p,f) a1,a2,a3,a4)
  206. #define UDICALL5(p,f,a1,a2,a3,a4,a5)         UDICALLPREFIX(p,f) a1,a2,a3,a4,a5)
  207. #define UDICALL6(p,f,a1,a2,a3,a4,a5,a6)     UDICALLPREFIX(p,f) a1,a2,a3,a4,a5,a6)
  208. #define UDICALL7(p,f,a1,a2,a3,a4,a5,a6,a7)     UDICALLPREFIX(p,f) a1,a2,a3,a4,a5,a6,a7)
  209. #define UDICALL8(p,f,a1,a2,a3,a4,a5,a6,a7,a8)     UDICALLPREFIX(p,f) a1,a2,a3,a4,a5,a6,a7,a8)
  210.  
  211.  
  212.  
  213.  
  214. extern DOSTerm TermStruct;    /* located in dosdfe.asm */
  215. extern void    UDITerminate();
  216.  
  217.  
  218. #define FBUFSIZE 2048
  219.  
  220. struct UDIConnections {
  221.     struct UDIVecRec _far * VecRecP;
  222.     UDISessionId ConnId;
  223. }; /* struct UDIConnections */
  224.  
  225. #define NumSessions 10
  226.  
  227. static struct UDIVecRec _far * CurrentConnection;
  228.  
  229. #ifdef DOS386
  230.  
  231. REALPTR _far * UDIVecP;
  232. #define REALNULL (REALPTR) 0
  233.  
  234. #else
  235.  
  236. static struct UDIVecRec _FAR * _FAR * UDIVecP;
  237. #define REALNULL NULL
  238.  
  239. #endif
  240.  
  241.  
  242. static struct UDIConnections Connections[ NumSessions ];
  243.  
  244. static char *GetConfigFileName( void )
  245. {
  246.     char *cp;
  247.     static char buf[ _MAX_PATH ];
  248.  
  249.     if ((cp = getenv( "UDICONF" )) != NULL)
  250.     return cp;
  251.     
  252.     _searchenv( "udiconfs.txt", "PATH", buf );
  253.  
  254.     return buf;
  255.     }
  256.  
  257. #ifdef DOS386
  258.  
  259. REALPTR _far * FindIntVect() 
  260.  
  261. #else
  262.  
  263. static struct UDIVecRec _FAR * _FAR * FindIntVect()
  264.  
  265. #endif
  266. {
  267.     union rec recognizer;
  268.     int i;
  269.  
  270.     InitRecognizer( &recognizer );
  271.  
  272.  
  273.     /* Try and find a vector that is currently in use for UDI */
  274.     for (i = 0x60; i < 0x66; i++ ) {
  275.  
  276. #ifdef DOS386
  277.  
  278.      UDIVecP = (REALPTR _far *) (REALPTR_TO_CPTR(i*4));
  279.  
  280. #else
  281.  
  282.     UDIVecP =  (static struct UDIVecRec _FAR * _FAR *)(i * 4);
  283.  
  284. #endif
  285.  
  286.     if ((*UDIVecP != REALNULL) &&
  287.         ((struct UDIVecRec _far *) REALPTR_TO_CPTR(*UDIVecP))->recognizer.l == recognizer.l)
  288.             return UDIVecP;
  289.     }
  290.  
  291.     return NULL;
  292. }
  293.  
  294.  
  295.  
  296. UDIError CheckForConnect(char *TIPName, int SessionNum, UDISessionId *Session, char *TIPParms)
  297. /* Check the interrupt table for a matching connection. 
  298.  * Note that the call to the TIPs UDIConnect is via annother function UDIPConnect
  299.  * for the protected mode version.
  300.  *
  301.  * 7/93 MDT -- Took out 'if' that only set up the connection id if there was
  302.  *             no error message returned.  This caused the DFE to be unable
  303.  *             to report TIP specific (negative) error messages from a 
  304.  *             call to UDIConnect.  Placed a new if which checks if the error
  305.  *             is positive and sets the CurrentConnection and VecRecP to null
  306.  *             so that any subsequent call to UDIDisconnect will work properly.
  307.  *
  308.  */
  309. {
  310.     struct UDIVecRec _far * CurConn;
  311.     UDIError    err;
  312.     UDISessionId    tempId=0;
  313.  
  314.  
  315.     if (UDIVecP)  {    /* TIPs running somewhere on machine */
  316.         for (CurConn = (struct UDIVecRec _far *)REALPTR_TO_CPTR(*UDIVecP); 
  317.             FP_OFF(CurConn); 
  318. #ifdef DOS386
  319.             CurConn = (struct UDIVecRec _far *) REALPTR_TO_CPTR((REALPTR)(CurConn->Next))) 
  320. #else
  321.             CurConn = (struct UDIVecRec _far *) REALPTR_TO_CPTR((CurConn->Next))) 
  322. #endif
  323.     
  324.         {
  325. #ifdef DOS386
  326.             if (!_fstrcmp(NEARPTR_TO_FARPTR(TIPName),(char _far *)REALPTR_TO_CPTR((REALPTR)(CurConn->exeName)))) {
  327.                 err = UDICALL3(CurConn, Connect, TIPParms,
  328.                     &tempId,(DOSTerm _far *)term_addr);
  329. #else
  330.             if (!_fstrcmp(NEARPTR_TO_FARPTR(TIPName),(char _far *)REALPTR_TO_CPTR((CurConn->exeName)))) {
  331.                 err = UDICALL3(CurConn, Connect, TIPParms,
  332.                     &tempId, &TermStruct);
  333. #endif
  334.                 Connections[SessionNum].ConnId = tempId;
  335.                 *Session = SessionNum;
  336.                 if (err > 0)
  337.                     CurrentConnection = Connections[SessionNum].VecRecP = 0;
  338.                 else
  339.                     CurrentConnection = Connections[SessionNum].VecRecP = CurConn;
  340.                  return err;
  341.             } /* if */
  342.         } /* for */
  343.     } /* if */
  344.  
  345.     return UDIErrorExecutableNotTIP;
  346.  
  347.  
  348. } /* CheckForConnect */
  349.  
  350.  
  351.  
  352. UDIError UDIConnect UDIParams((
  353.   char        *Configuration,        /* In */
  354.   UDISessionId    *Session        /* Out */
  355.   ))
  356. {
  357.     int    i, n;
  358.     char    buf[ FBUFSIZE ];
  359.     char    TIPName[ FILENAME_MAX ];
  360.     char    *TIPParms;
  361.  
  362.  
  363.     FILE *fp;
  364.  
  365. #ifdef DOS386
  366.     static int        DOS386_Initialized;
  367.     extern USHORT    GetCS();
  368.     extern USHORT    GetDS();
  369.  
  370.  
  371.     int    start_real(), end_real();    /* prototypes to cast locations */
  372.                             /*   in real-mode code and data */
  373.     REALPTR    term_func_addr;
  374.     ULONG    *term_func_addr_ptr;
  375.  
  376.    
  377.     if (!DOS386_Initialized) {        /* Do this init logic only once */
  378.  
  379.  
  380.         /* Need to copy the real mode code into conventional memory. */
  381.     if (realcopy((ULONG)start_real,(ULONG) end_real,(REALPTR *) &real_base,(FARPTR *) &prot_base,(USHORT *) &rmem_adr)) {
  382.         printf("\nUDIConnect: realcopy call failed;\n");
  383.         printf(  "   Probable cause: insufficient free conventional memory.\n");
  384.         exit(0);
  385.     }
  386.  
  387.     /* 
  388.      * The following code sets up the pointer in TermStruct to 
  389.      * contain the correct real mode address of the UDITerminate
  390.      * function.  This process can best be illustrated with the
  391.      * following diagram.
  392.      *
  393.      *                      |    ____________________
  394.      *            |   |                    |____
  395.      *            |   | term_func_addr_ptr |    |
  396.      *                      |   |____________________|    |
  397.      *            |                  |D
  398.      *            |    ____________________     |
  399.      *            |   |                 |/___|
  400.      *            |   | term_func_addr     |\
  401.      *                      |   |                    |_________
  402.      *            |   |____________________|         |
  403.      *                      |                       |
  404.      *                      |    ____________________          |
  405.      *  Protected Memory       |   |                 |____     |
  406.      *                      |   | term_addr             |    |    |
  407.      *                      |   |____________________|    |    |
  408.      *                      |                          |    |
  409.      *                      |                      |B   |
  410.      *                      |---------------------------- |    |C
  411.      *                      |___ ____________________     |    |
  412.      *                      |r  |                 |/___|    |
  413.      *                      |e m|                 |\        |
  414.      *                      |a e| TermStruct         |____     |
  415.      *  Real Mode Memory    |l m|____________________|    |    |
  416.      *                      |  o|                 |    |A   |
  417.      *                      |c r|                 |/___|       |
  418.         *                      |o y| UDITerminate()     |\       |
  419.         *                      |p  |                 |/________|
  420.         *                      |y  |____________________|\
  421.      *                      |---
  422.      *
  423.      * Note that the point of this is to get TermStruct to contain
  424.      * a real mode pointer to the UDITerminate() function.  Therefor,
  425.      * pointer A is a real mode far pointer.  To write the function
  426.      * address into TermStruct, we are going to need a protected
  427.      * mode far pointer, pointer B.  We also need the real mode
  428.      * function address to copy into TermStruct, this is pointer C.
  429.      * Since we'll need to use _fmemmove, which requires two far
  430.      * pointers (remember that since B is a protected mode far pointer,
  431.      * we must use _fmemmove), we need another protected mode far
  432.      * pointer to point at the address to be copied, this is pointer
  433.      * D.
  434.      *
  435.      * Calls to NEARPTR_TO_FARPTR cannot be used to create pointers
  436.      * into the real-copy allocated area.  These need to be constructed
  437.      * using real_base and prot_base, as explained in the "Mixing
  438.      * Real and Protected Mode Code" section of the chapter on 
  439.      * "Programming for DPMI Compatablity" in the Phar Lap 386|DOS-
  440.      * Extender Programmer's Guide to DPMI and Windows.
  441.      *
  442.      */
  443.  
  444.     term_func_addr_ptr = &term_func_addr;
  445.     term_func_addr = (REALPTR)(real_base + (ULONG)(&UDITerminate));
  446.     term_addr = (FARPTR)(prot_base + (ULONG)(&TermStruct));
  447.     
  448.     
  449.     /*
  450.      * Used to create pointers into conventional memory other than the
  451.      * the area created by the call to real_copy (for example to access
  452.      * the interrupt table.
  453.      */
  454.     code_selector = GetCS();
  455.     data_selector = GetDS();
  456.  
  457.     _fmemmove(term_addr,NEARPTR_TO_FARPTR(term_func_addr_ptr),sizeof(*term_func_addr_ptr));
  458.  
  459.     DOS386_Initialized = TRUE;
  460.     }
  461.  
  462. #endif /* DOS386 */
  463.  
  464.     n = strlen( Configuration );
  465.     TIPParms = NULL;
  466.  
  467.     /* Get configuration line that corresponds to requested configuration */
  468.     if ((fp = fopen( GetConfigFileName(), "r" )) == NULL)
  469.     return UDIErrorCantOpenConfigFile;
  470.  
  471.     while (fgets( buf, FBUFSIZE -1, fp ) != NULL) {
  472.         if (isspace( buf[n] ) && (strncmp( buf, Configuration, n ) == 0)) {
  473.             sscanf( buf, "%*s %s%n", TIPName, &n );
  474.                 TIPParms = &buf[n];
  475.                 while (isspace( *TIPParms ))
  476.                 TIPParms++;
  477.                 if (*TIPParms)
  478.                 TIPParms[ strlen( TIPParms ) -1 ] = '\0';
  479.                 break;
  480.             } /* if */
  481.     } /* while */
  482.  
  483.     fclose( fp );
  484.  
  485.     if (!TIPParms)
  486.         return UDIErrorNoSuchConfiguration;
  487.  
  488.     for (i = 0; i < NumSessions; i++)
  489.         if (!Connections[i].VecRecP)
  490.             break;
  491.     
  492.     if (i >= NumSessions)
  493.     return UDIErrorCantConnect;
  494.  
  495.     /* Determine if any TIPs are currently running */
  496.     if (!UDIVecP)    /* None for this DFE */
  497.     UDIVecP = FindIntVect();    /* Try other DFEs */
  498.  
  499.  
  500.     n = CheckForConnect(TIPName, i, Session, TIPParms);
  501.  
  502.     if (n != UDIErrorExecutableNotTIP)
  503.         return n;
  504.  
  505. #ifdef DOS386
  506.   {
  507.     char FullTIPName[256]; /* general name storage */
  508.     UINT errinfo, doserr;
  509.     UINT vmmh;
  510.     LDEXP_BLK parmp;
  511.     typedef UDIStruct {    /* a shortened version of the pharlap.h struct */
  512.                 /* to make sure this ons is packed (in this modeule, */
  513.                 /* all we really need from this structure is ss:esp */
  514.       ULONG     eip;        /* initial EIP */
  515.       USHORT cs;        /* initial CS */
  516.       ULONG     esp;        /* initial ESP */
  517.       USHORT ss;        /* initial SS */
  518.     } PACKED_LDEXP_BLK;
  519.     PACKED_LDEXP_BLK *packed_parmp = (PACKED_LDEXP_BLK *) &parmp;
  520.     int err;
  521.     FARPTR TIPStackPtr;
  522.     extern int _exp_call_to(LDEXP_BLK *p);
  523.     
  524.       /* Under Windows (DPMI 0.9) support we can't load a second DOS extender
  525.     application and switch back and forth to it.  So we get around this
  526.     by loading the .exp file instead (using the current Dos extender)
  527.     if DPMI is present, check if the tip program name also exists with a .exp extension 
  528.     if it does, do a dx_ld_flat of that and run it under our DFE dos extender
  529.      */
  530.  
  531.     if (dpmi_exists()) {
  532.     get_full_exe_name(TIPName, FullTIPName);    /* ld_flat needs full pathname */
  533.  
  534.     /* now try to load the .exe file as if it were an exp file */
  535.     /* (a nice feature of pharlap is that it dx_ld_flat can load */
  536.     /* an .exe file that has an .exp file bound into it */
  537.     err = _dx_ld_flat((UCHAR *) FullTIPName,
  538.           &parmp,
  539.           FALSE,        /* read into mem immediately */
  540.           &vmmh,        /* vmm handle pointer */
  541.           &errinfo,        /* error info */
  542.           &doserr);        /* dos error */
  543.  
  544.     if (err)        /* if any kind of error at all, give up on exp file */
  545.         goto SpawnTipExe;    /* and go back to exe file */
  546.     else {
  547.         /* successful load, now jump to .exp file code, which will
  548.            return back to here. First we will put the original TIPName
  549.            into the top of stack so the TIP can find it (like an argument).
  550.         */
  551.         FP_SET(TIPStackPtr, packed_parmp->esp-256, packed_parmp->ss);
  552.         _fmemmove(TIPStackPtr, NEARPTR_TO_FARPTR(TIPName), strlen(TIPName)+1);
  553.  
  554.         /* now call into loaded exp code (and hopefully return) */
  555.         if (_exp_call_to(&parmp) != 0)
  556.             return UDIErrorCantStartTIP;
  557.         else
  558.             goto TIPLoaded;
  559.         }/*else*/
  560.     } /* if DPMI present */
  561.   } /* block for ifdef DOS386 */
  562. #endif
  563.  
  564.  
  565. SpawnTipExe:
  566.     /* To get around DOS 2.x problems as well as problems with filename
  567.        expansion/searching, we pass the executable name as an addtional
  568.        parameter. Also, we expect the TIP to TSR, so the high byte of
  569.        the return value is probably 0x03. But some TIPs might be more
  570.        clever and really return (activating a device driver or other
  571.        TSR first), so we ignore the high byte of the return from spawnlp.
  572.     */
  573.  
  574.     if ((n = spawnlp( P_WAIT, TIPName, TIPName, TIPName, NULL ) & 0xff) != 0)
  575.     return UDIErrorCantStartTIP;
  576.  
  577. TIPLoaded:
  578.     /* Determine if any TIPs are currently running */
  579.     if (!UDIVecP)    /* None for this DFE */
  580.         UDIVecP = FindIntVect();    /* Try other DFEs (or new TIPs) */
  581.  
  582.  
  583.     return CheckForConnect(TIPName, i, Session, TIPParms);
  584.     
  585. } /* UDIConnect() */
  586.  
  587.  
  588.  
  589. UDIError UDIDisconnect UDIParams((
  590.     UDISessionId    Session,        /* In */
  591.     UDIBool        Terminate        /* In */
  592.     ))
  593. {
  594.     UDIError err;
  595.  
  596.     if (Session >= NumSessions || !Connections[Session].VecRecP)
  597.         return UDIErrorNoSuchConnection;
  598.  
  599. #ifdef DOS386
  600.     if (((err = UDICALL3(CurrentConnection,Disconnect,
  601.         Connections[ Session ].ConnId, Terminate, (DOSTerm _far *)term_addr ))
  602.         == UDINoError) &&
  603.         (CurrentConnection == Connections[ Session ].VecRecP))
  604. #else
  605.     if (((err = UDICALL3(CurrentConnection,Disconnect,
  606.         Connections[ Session ].ConnId, Terminate, &TermStruct))
  607.         == UDINoError) &&
  608.         (CurrentConnection == Connections[ Session ].VecRecP))
  609. #endif
  610.  
  611.     CurrentConnection = NULL;
  612.  
  613.         return err;
  614.  
  615. } /* UDIDisconnect() */
  616.  
  617.  
  618.  
  619. UDIError UDISetCurrentConnection UDIParams((
  620.     UDISessionId    Session            /* In */
  621.     ))
  622. {
  623.     UDIError n;
  624.     struct UDIConnections *ConnP;
  625.  
  626.     if (Session >= NumSessions || !Connections[Session].VecRecP)
  627.         return UDIErrorNoSuchConnection;
  628.  
  629.     ConnP = &Connections[Session];
  630.  
  631.     n = UDICALL1(ConnP->VecRecP,SetCurrentConnection,
  632.                ConnP->ConnId);
  633.     if (n == UDINoError)
  634.         CurrentConnection = ConnP->VecRecP;
  635.  
  636.     return n;
  637.  
  638. }  /* UDIDisconnect () */
  639.  
  640.  
  641.  
  642.  
  643. UDIError UDICapabilities UDIParams((
  644.     UDIUInt32    *TIPId,            /* Out */
  645.     UDIUInt32    *TargetId,        /* Out */
  646.     UDIUInt32    DFEId,            /* In */
  647.     UDIUInt32    DFE,            /* In */
  648.     UDIUInt32    *TIP,            /* Out */
  649.     UDIUInt32    *DFEIPCId,        /* Out */
  650.     UDIUInt32    *TIPIPCId,        /* Out */
  651.     char        *TIPString        /* Out */
  652.     ))
  653. {
  654.     UDIError err;
  655.  
  656.     if (!CurrentConnection)
  657.         return UDIErrorNoConnection;
  658.  
  659.     err = UDICALL8(CurrentConnection,Capabilities,
  660.         TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId,
  661.         TIPIPCId, TIPString);
  662.  
  663.     *DFEIPCId = (((UDIUInt32)DFEIPCIdCompany) << 16) |
  664.         (DFEIPCIdProduct << 12) | DFEIPCIdVersion;
  665.  
  666.     return err;
  667.  
  668. }  /* UDICapabilities() */
  669.  
  670.  
  671.  
  672.  
  673. UDIError UDIEnumerateTIPs UDIParams((
  674.     UDIInt    (*UDIETCallback)    /* In */
  675.     UDIParams(( char *Configuration ))    /* In to callback() */
  676.     ))
  677. {
  678.     FILE *fp;
  679.     char buf[ FBUFSIZE ];
  680.  
  681.     if ((fp = fopen( GetConfigFileName(), "r" )) == NULL)
  682.         return UDIErrorCantOpenConfigFile;
  683.  
  684.     while (fgets( buf, FBUFSIZE, fp ))
  685.         if (UDIETCallback( buf ) == UDITerminateEnumeration)
  686.             break;
  687.  
  688.     fclose( fp );
  689.  
  690.     return UDINoError;
  691.  
  692. } /* UDIEnumerateTIPs() */
  693.  
  694.  
  695.  
  696. UDIError UDIGetErrorMsg UDIParams((
  697.     UDIError    ErrorCode,        /* In */
  698.     UDISizeT    MsgSize,        /* In */
  699.     char        *Msg,            /* Out */
  700.     UDISizeT    *CountDone        /* Out */
  701.     ))
  702. {
  703.     if (!CurrentConnection)
  704.         return UDIErrorNoConnection;
  705.  
  706.     return UDICALL4(CurrentConnection,GetErrorMsg,
  707.         ErrorCode, MsgSize, Msg, CountDone);
  708.  
  709. } /* UDIGetErrorMsg() */
  710.  
  711.  
  712.  
  713. UDIError UDIGetTargetConfig UDIParams((
  714.     UDIMemoryRange KnownMemory[],        /* Out */
  715.     UDIInt    *NumberOfRanges,    /* In/Out */
  716.     UDIUInt32    ChipVersions[],        /* Out */
  717.     UDIInt    *NumberOfChips        /* In/Out */
  718.     ))
  719. {
  720.     if (!CurrentConnection)
  721.         return UDIErrorNoConnection;
  722.  
  723.     return UDICALL4(CurrentConnection,GetTargetConfig,
  724.         KnownMemory, NumberOfRanges, ChipVersions, NumberOfChips);
  725.  
  726. } /* UDIGetTargetConfig() */
  727.  
  728.  
  729.  
  730. UDIError UDICreateProcess UDIParams((
  731.     UDIPId    *PId            /* Out */
  732.     ))
  733. {
  734.     if (!CurrentConnection)
  735.         return UDIErrorNoConnection;
  736.  
  737.     return UDICALL1(CurrentConnection,CreateProcess,
  738.             PId);
  739.  
  740. } /* UDICreateProcess() */
  741.  
  742.  
  743.  
  744. UDIError UDISetCurrentProcess UDIParams((
  745.     UDIPId    PId            /* In */
  746.     ))
  747. {
  748.     if (!CurrentConnection)
  749.         return UDIErrorNoConnection;
  750.  
  751.     return    UDICALL1(CurrentConnection,SetCurrentProcess,
  752.              PId);
  753.  
  754. } /* UDISetCurrentProcess() */
  755.  
  756.  
  757.  
  758. UDIError UDIDestroyProcess UDIParams((
  759.     UDIPId    PId            /* In */
  760.     ))
  761. {
  762.     
  763.     if (!CurrentConnection)
  764.         return UDIErrorNoConnection;
  765.  
  766.     return UDICALL1(CurrentConnection,DestroyProcess,
  767.             PId);
  768.     
  769. } /* UDIDestroyProcess() */
  770.  
  771.  
  772.  
  773. UDIError UDIInitializeProcess UDIParams((
  774.     UDIMemoryRange    ProcessMemory[],    /* In */
  775.     UDIInt        NumberOfRanges,        /* In */
  776.     UDIResource    EntryPoint,        /* In */
  777.     CPUSizeT    StackSizes[],        /* In */
  778.     UDIInt        NumberOfStacks,        /* In */
  779.     char        *ArgString        /* In */
  780.     ))
  781. {
  782.     if (!CurrentConnection)
  783.         return UDIErrorNoConnection;
  784.  
  785.     return UDICALL6(CurrentConnection,InitializeProcess,
  786.         ProcessMemory, NumberOfRanges, EntryPoint, StackSizes,
  787.         NumberOfStacks, ArgString );
  788.  
  789. } /* UDIInitializeProcess() */
  790.  
  791.  
  792.  
  793. UDIError UDIRead UDIParams((
  794.     UDIResource    From,            /* In */
  795.     UDIHostMemPtr    To,            /* Out */
  796.     UDICount    Count,            /* In */
  797.     UDISizeT    Size,            /* In */
  798.     UDICount    *CountDone,        /* Out */
  799.     UDIBool        HostEndian        /* In */
  800.     ))
  801. {
  802.     if (!CurrentConnection)
  803.         return UDIErrorNoConnection;
  804.  
  805.     return UDICALL6(CurrentConnection,Read, 
  806.         From, To, Count, Size, CountDone, HostEndian);
  807.  
  808. } /* UDIRead() */
  809.  
  810.  
  811.  
  812. UDIError UDIWrite UDIParams((
  813.     UDIHostMemPtr    From,            /* In */
  814.     UDIResource    To,            /* In */
  815.     UDICount    Count,            /* In */
  816.     UDISizeT    Size,            /* In */
  817.     UDICount    *CountDone,        /* Out */
  818.     UDIBool        HostEndian        /* In */
  819.   ))
  820. {
  821.     if (!CurrentConnection)
  822.         return UDIErrorNoConnection;
  823.  
  824.  
  825.     return UDICALL6(CurrentConnection,Write,
  826.         From, To, Count, Size, CountDone, HostEndian);
  827.  
  828. } /* UDIWrite() */
  829.  
  830.  
  831.  
  832. UDIError UDICopy UDIParams((
  833.     UDIResource    From,            /* In */
  834.     UDIResource    To,            /* In */
  835.     UDICount    Count,            /* In */
  836.     UDISizeT    Size,            /* In */
  837.     UDICount    *CountDone,        /* Out */
  838.     UDIBool        Direction        /* In */
  839.     ))
  840. {
  841.     if (!CurrentConnection)
  842.         return UDIErrorNoConnection;
  843.  
  844.     return UDICALL6(CurrentConnection,Copy,
  845.         From, To, Count, Size, CountDone, Direction);
  846.  
  847. } /* UDICopy() */
  848.  
  849.  
  850.  
  851. UDIError UDIExecute UDIParams((
  852.     void
  853.     ))
  854. {
  855.     if (!CurrentConnection)
  856.         return UDIErrorNoConnection;
  857.  
  858.     return UDICALL0(CurrentConnection,Execute);
  859.  
  860. } /* UDIExecute() */
  861.  
  862.  
  863.  
  864. UDIError UDIStep UDIParams((
  865.     UDIUInt32    Steps,            /* In */
  866.     UDIStepType   StepType,        /* In */
  867.     UDIRange      Range            /* In */
  868.     ))
  869. {
  870.     if (!CurrentConnection)
  871.         return UDIErrorNoConnection;
  872.  
  873.     return UDICALL3(CurrentConnection,Step,
  874.             Steps,StepType,Range);
  875.  
  876. } /* UDIStep() */
  877.  
  878.  
  879.  
  880.  
  881. UDIVoid UDIStop UDIParams((
  882.     void
  883.     ))
  884. {
  885.     if (!CurrentConnection)
  886.         return;
  887.  
  888.     UDICALL0(CurrentConnection,Stop);
  889.  
  890. } /* UDIStop() */
  891.  
  892.  
  893.  
  894.  
  895. UDIError UDIWait UDIParams((
  896.     UDIInt32    MaxTime,        /* In */
  897.     UDIPId        *PId,            /* Out */
  898.     UDIUInt32    *StopReason        /* Out */
  899.     ))
  900. {
  901.     if (!CurrentConnection)
  902.         return UDIErrorNoConnection;
  903.  
  904.     return UDICALL3(CurrentConnection,Wait,
  905.         MaxTime, PId, StopReason);
  906.  
  907. } /* UDIWait() */
  908.  
  909.  
  910.  
  911. UDIError UDISetBreakpoint UDIParams((
  912.     UDIResource    Addr,            /* In */
  913.     UDIInt32    PassCount,        /* In */
  914.     UDIBreakType    Type,            /* In */
  915.     UDIBreakId    *BreakId        /* Out */
  916.     ))
  917. {
  918.     if (!CurrentConnection)
  919.         return UDIErrorNoConnection;
  920.  
  921.     return UDICALL4(CurrentConnection,SetBreakpoint,
  922.         Addr, PassCount, Type, BreakId);
  923.  
  924. } /* UDISetBreakpoint() */
  925.  
  926.  
  927.  
  928. UDIError UDIQueryBreakpoint UDIParams((
  929.     UDIBreakId    BreakId,        /* In */
  930.     UDIResource    *Addr,            /* Out */
  931.     UDIInt32    *PassCount,        /* Out */
  932.     UDIBreakType    *Type,            /* Out */
  933.     UDIInt32    *CurrentCount        /* Out */
  934.     ))
  935. {
  936.     if (!CurrentConnection)
  937.         return UDIErrorNoConnection;
  938.  
  939.     return UDICALL5(CurrentConnection,QueryBreakpoint,
  940.         BreakId, Addr, PassCount, Type, CurrentCount);
  941.  
  942. } /* UDIQueryBreakpoint() */
  943.  
  944.  
  945.  
  946.  
  947. UDIError UDIClearBreakpoint UDIParams((
  948.     UDIBreakId    BreakId            /* In */
  949.     ))
  950. {
  951.     if (!CurrentConnection)
  952.         return UDIErrorNoConnection;
  953.  
  954.     return UDICALL1(CurrentConnection,ClearBreakpoint,
  955.         BreakId);
  956.  
  957. } /* UDIClearBreakpoint() */
  958.  
  959.  
  960.  
  961. UDIError UDIGetStdout UDIParams((
  962.     UDIHostMemPtr    Buf,            /* Out */
  963.     UDISizeT    BufSize,        /* In */
  964.     UDISizeT    *CountDone        /* Out */
  965.     ))
  966. {
  967.     if (!CurrentConnection)
  968.         return UDIErrorNoConnection;
  969.  
  970.  
  971.     return UDICALL3(CurrentConnection,GetStdout,
  972.         Buf, BufSize, CountDone);
  973.  
  974. } /* UDIGetStout() */
  975.  
  976.  
  977.  
  978. UDIError UDIGetStderr UDIParams((
  979.     UDIHostMemPtr    Buf,            /* Out */
  980.     UDISizeT    BufSize,        /* In */
  981.     UDISizeT    *CountDone        /* Out */
  982.     ))
  983. {
  984.     if (!CurrentConnection)
  985.         return UDIErrorNoConnection;
  986.  
  987.     return UDICALL3(CurrentConnection,GetStderr,
  988.         Buf, BufSize, CountDone);
  989.  
  990. } /* UDIGetStderr() */
  991.  
  992.  
  993.  
  994.  
  995. UDIError UDIPutStdin UDIParams((
  996.     UDIHostMemPtr    Buf,            /* In */
  997.     UDISizeT    Count,            /* In */
  998.     UDISizeT    *CountDone        /* Out */
  999.     ))
  1000. {
  1001.     if (!CurrentConnection)
  1002.         return UDIErrorNoConnection;
  1003.  
  1004.     return UDICALL3(CurrentConnection,PutStdin,
  1005.         Buf, Count, CountDone);
  1006.  
  1007. } /* UDIPutStdin() */
  1008.  
  1009.  
  1010.  
  1011. UDIError UDIStdinMode UDIParams((
  1012.     UDIMode        *Mode            /* Out */
  1013.     ))
  1014. {
  1015.     if (!CurrentConnection)
  1016.         return UDIErrorNoConnection;
  1017.  
  1018.  
  1019.     return UDICALL1(CurrentConnection,StdinMode,
  1020.         Mode);
  1021.  
  1022. } /* UDIStdinMode() */
  1023.  
  1024.  
  1025.  
  1026.  
  1027. UDIError UDIPutTrans UDIParams((
  1028.     UDIHostMemPtr    Buf,            /* In */
  1029.     UDISizeT    Count,            /* In */
  1030.     UDISizeT    *CountDone        /* Out */
  1031.     ))
  1032. {
  1033.     if (!CurrentConnection)
  1034.         return UDIErrorNoConnection;
  1035.  
  1036.  
  1037.     return UDICALL3(CurrentConnection,PutTrans,
  1038.         Buf, Count, CountDone);
  1039.  
  1040.  
  1041. } /* UDIPutTrans() */
  1042.  
  1043.  
  1044.  
  1045.  
  1046. UDIError UDIGetTrans UDIParams((
  1047.     UDIHostMemPtr    Buf,            /* Out */
  1048.     UDISizeT    BufSize,        /* In */
  1049.     UDISizeT    *CountDone        /* Out */
  1050.     ))
  1051. {
  1052.     if (!CurrentConnection)
  1053.         return UDIErrorNoConnection;
  1054.  
  1055.  
  1056.     return UDICALL3(CurrentConnection,GetTrans,
  1057.         Buf, BufSize, CountDone);
  1058.  
  1059. } /* UDIGetTrans() */
  1060.  
  1061.  
  1062.  
  1063.  
  1064. UDIError UDITransMode UDIParams((
  1065.     UDIMode        *Mode            /* Out */
  1066.     ))
  1067. {
  1068.     if (!CurrentConnection)
  1069.         return UDIErrorNoConnection;
  1070.  
  1071.  
  1072.     return UDICALL1(CurrentConnection,TransMode,
  1073.             Mode);
  1074.  
  1075.  
  1076. } /* UDITransMode() */
  1077.  
  1078.  
  1079.  
  1080. UDIUInt32 UDIGetDFEIPCId()
  1081. {
  1082.  
  1083.     return((((UDIUInt32)DFEIPCIdCompany) << 16) |(DFEIPCIdProduct << 12) | DFEIPCIdVersion);
  1084.  
  1085. } /* UDIGetDFEIPCId() */
  1086.