📄 dos386c.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 ***************************************************************************** * $Id: dos386c.c,v 1.2 1993/12/23 04:44:41 cassidy Exp $ * $Id: @(#)dos386c.c 1.9, AMD *//* DOS386 specific constructs and functions. These assume the use of * the 386|DOS-Extender from Pharlap. * * This file contains functions which serve as an intermediate between * protected mode UDI function calls made by the DFE and the possibly * real-mode function called in the TIP. These functions assume that * the interface between the TIP and the DFE is real-mode and that the * DFE is protected mode, flat model (32 bit linear addresses). * * Note: * This code allocates a section of real-mode memory using * a call to _dx_real_alloc. Protected mode far pointers (48-bit) * must be used to access this memory area. * * For every UDI function named UDIx..x, there is a function in this * module named UDIPx..x, where the "P" indicates that this is a protected * mode interface function. A protected mode DFE needs to call the * UDIPx..x equivalent of the call to the TIP UDI function. The call * parameters are the same as the UDI call except that the address of the * TIP UDI function is always the first parameter to the UDIPx..x * function. * * Each function follows the format outlined below: * * UDIError UDIPx..x(REALPTR function_address [, UDI function parameters]) * { * Allocate pointers into the conventional memory area used for * parameter passing (PPM) for all parameters which are * passed-by-reference. Each of these pointers is given * the same name as a parameter with "Ptr" appended to it. * * Create a packed structure for parameter passing if there is more * than one parameter to the function. Each member of this * structure (always named params) has the same name as the * corresponding parameter to the UDIP... call. * * Set the parameter pointers to the appropriate offsets in the PPM. * The protected mode pointer to the first parameter is always * rm_address (the real mode equivalent to this pointer is * rm_buffer_addr). * * Copy the data from protected mode (possibly extended) memory to * the location indicated by the correct pointer * * Copy the passed-by-value parameters directly into the params * structure. Convert the protected mode version of the * pointers into the PPM area to real-mode pointers and * assign them to their corresponding params data member. * * Call the real-mode function, pushing the params structure onto * the stack. Generally this involves the use of the macro * REALCALL, however functions with no parameters call * _dx_call_real explicitly. The size of the params structure * is determined by the macro WORDSIZE. * * Check for an error returned from _dx_call_real. If there is one * report it and die (how uncouth!). * * Copy all "out" parameters into their local (non-conventional * memory eqivalents. In functions with "count" parameters, * make sure that the count value makes sense and only * copy as much as is allowed by the buffer size. * * The return value of the UDI TIP function is in the ax register of * the regs structure, return this as the value of the UDIP * function. * } * * * UDIPRead, UDIPWrite, UDIPPutStdOut, UDIPGetStdOut, * UDIPGetStderr, UDIPPutTrans and UDIPGetTrans differ from the other * UDIP functions in that they allow looping within the UDIP layer * call to the TIP. This looping is done so that the size of the * real mode buffer area does not limit the size of the data transfer * since all data passed by reference *must* be copied into the real * mode buffer area and the TIP can only return as much information * as can fit in this real mode buffer (unlike the situation for a * real mode DFE where the DFE and the TIP write to the same memory). * * The calls all use the same logic, outlined below: * * * Set the CurrentCount equal to the total number of items to * be transfered (CurrentCount = *Count). * * Set the total number of items transfered so far to zero (TotalDone = 0) * * Set up moving pointers into the From and To transfer areas to keep * track of where the current transfer should be read and/or written. * (CurrentTo = To; CurrentFrom = From) * * do * Set a pointer to the end of the memory that would be required * to do the complete transfer. * * If the pointer is outside of the buffer area (determined by * call the BufferSizeCheck), then we need to adjust the * size of the requested transfer. * * Set the pointer to the last item to the last valid location * in the real mode buffer area. * * Set the value of CurrentCount to the maximum number of data * items that can be transfered, based on the Size parameter. * * Call the TIP function with CurrentCount instead of *Count, * CurrentTo instead of To and CurrentFrom instead of From. * * Set the CurrentDone equal to the CountDone returned by the * function call. * * Update the pointers into the From and To transfer areas to the * end of the just completed transfer (CurrentFrom += CurrentDone * * Size, CurrentTo += CurrentDone * Size) * * Increment the TotalDone by the number of items transfered in * the last call (TotalDone += CurrentDone) * * while transfer is not complete (TotalDone < *Count) * */#define _DOS386C_C#include <dos.h>#include <process.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include <udiproc.h>#include <pharlap.h>#include <udidos.h>#include <stdarg.h>#include <dos386c.h>#define REAL_BUFFER_SIZE 0x1000#define PRINT_ON 1#define PRINT_OFF 0#define WORDSIZE(param) ((sizeof(param)/2) + (sizeof(param) %2))#define REALCALL(x,y) _dx_call_real(x, &real_regs, WORDSIZE(y), y)#define FUNC_VAL ((UDIError) real_regs.eax)#define SIZE_ERROR(Done, Size, function_name) printf("Return size (%d) > Buffer size (%d) in function %s\n",Done,Size,function_name)/* * 4/93 MDT * The following defines are used to allow UDI 1.2 functions to identify * themselves to the compiler and the user when UDI 1.3 is defined. These * are needed to differentiate the 1.2 versions of some functions (UDIPConnect) * from their 1.3 versions. */#if defined __STDC__ || defined _MSC_VER#define XCAT(a,b) a##b#else#define XCAT(a,b) a/**/b#endif#ifdef UDI13 #define UDI12FUNCVER _12#define UDI12FUNCVERSTR " (1.2)"#define CAT(a,b) XCAT(a,b)#else /* not UDI 1.3 */#define UDI12FUNCVER dummy /* Have to pass two arguments to CAT */ #define UDI12FUNCVERSTR ""#define CAT(a,b) a /* Don't actually want to concatenate anything */#endif /* UDI 1.3 *//* Needed by call to _dx_real_call, but no values need to be set * since TIP is compiled assuming it doesn't know anything about the * values in the registers. */RMC_BLK real_regs; /* Pointers to use for handling conventional memory buffer area. This * area is used to pass parameters to and from real-mode procedures. */REALPTR rm_buffer_addr; /* real-mode pointer to parameter buffer area. */ULONG rm_buffer_size; /* size of paramter buffer area. */USHORT _far *rm_address; /* pointer to paramter buffer area. */USHORT _far *rm_end_address; /* the last valid address of the parameter buffer */int buffer_allocated=0; /* used to denote that the status of the buffer */REALPTR PROT_TO_REAL(FARPTR p) /* converts a PROT ptr to a REALPTR */{REALPTR dummyrp;FARPTR dummyfp;int err; /* returns a real mode pointer given a prot mode pointer p */// FP_SET(dummyfp,p,data_selector); dummyfp = p; err = _dx_toreal(dummyfp, 0, &dummyrp); if (err) { printf("Fatal Error _dx_toreal (0x%lX)\n", (ULONG) p); exit(err); } return(dummyrp); } /* PROT_TO_REAL */FARPTR REAL_TO_PROT(REALPTR rp) /* converts a REALPTR to a FARPTR */{FARPTR dummyfp; FP_SET(dummyfp,LINEARIZE(rp),SS_DOSMEM); return (dummyfp); } /* REAL_TO_PROT */FARPTR NEARPTR_TO_FARPTR(void *ptr)/* Convert a near (32 bit linear) pointer to a far (48 bit) pointer. */{ FARPTR dummyfptr; FP_SET(dummyfptr, ptr, data_selector); return(dummyfptr);} /* NEARPTR_TO_FARPTR() */long BufferSizeCheck(FARPTR ptr, char *function_name, int print_message)/* Check passed ptr to make sure that it points to a valid location in * the real-mode parameter passing buffer. If not, just report an * error for now. */{ if ((long)ptr < (long)rm_address) { printf("Invalid address for real mode parameters in function: %s\n",function_name); exit(1); } if ((long)ptr > (long)rm_end_address) { if (print_message) { printf("Parameters too large for passing to real mode in function: %s\n",function_name); printf("Value of ptr - rm_end_address:%ld\n",(long)(ptr - (FARPTR)rm_end_address)); } return (long)((long)ptr - (long)rm_end_address); } return 0; /* passed the size check */} /* BufferSizeCheck() */void CheckRealError(int Err, char *func_name) { if (Err) { printf("DOS386 real mode call error: %s\n",func_name); exit(1); } /* if */} /* CheckRealError() */UDIError CAT(UDIPConnect,UDI12FUNCVER)( REALPTR UDIConnectAddr, char *Configuration, /* In */ UDISessionId *Session, /* Out */ DOSTerm _far *TermStruct) /* In */{ int err; UDISessionId _far *SessionPtr; UDIError ConnectErr; USHORT rm_seg,rm_size; _Packed struct { REALPTR Configuration; REALPTR Session; REALPTR TermStruct; } params; if (!buffer_allocated) { /* Need to get address of conventional memory area for passing parameters. * This will set it for future use everywhere, not just in this function. * rm_address is the protected (32 bit) pointer to the real mode parameter. * passing area. rm_buffer_addr is the real mode pointer to the same buffer. */ err = _dx_real_alloc(REAL_BUFFER_SIZE,&rm_seg,&rm_size); if (err) { printf("Unable to allocate real-mode parameter transfer area (_dx_real_alloc)\n"); exit(0); } /* rm_seg is the real mode paragraph (segment). * Build rm_buffer_addr to be the full real mode pointer (seg:ofst) */ RP_SET(rm_buffer_addr, 0, rm_seg); /* * rm_address will be the protected pointer to that same buffer */ rm_address = (USHORT _far *)REAL_TO_PROT(rm_buffer_addr); rm_end_address = (USHORT _far *) (((char _far *)rm_address) + REAL_BUFFER_SIZE*16); buffer_allocated = 1; } /* Get pointers to locations where passed by reference parameters * will be stored in the parameter passing buffer area. The first * parameter is always at rm_buffer (= rm_buffer_addr in real mode). */ /* NOTE: see comments under UDIPDisconnect for explanation of why * we don't copy TermStruct even though it's an in parameter. */ SessionPtr = (UDISessionId _far *)((char _far *)rm_address + strlen(Configuration)+1); if (BufferSizeCheck((FARPTR)(SessionPtr + sizeof(UDISessionId)),"UDIPConnect" UDI12FUNCVERSTR,PRINT_ON)) { return UDIErrorIPCInternal; } /* if */ /* Move input parameters which are passed by reference into paramter buffer area. */ _fmemmove(rm_address,NEARPTR_TO_FARPTR(Configuration),strlen(Configuration)+1); _fmemmove(SessionPtr,NEARPTR_TO_FARPTR(Session),sizeof(UDISessionId)); /* Put actual parameters into packed structure for passing to real * mode function. */ params.Configuration = rm_buffer_addr; params.Session = PROT_TO_REAL((FARPTR) SessionPtr); params.TermStruct = PROT_TO_REAL((FARPTR)TermStruct); /* Call the real-mode function with the address of the function, * the number of bytes in the packed structure and the address of * the structure. */ ConnectErr = REALCALL(UDIConnectAddr,params); CheckRealError(ConnectErr,"UDIConnect" UDI12FUNCVERSTR); /* Copy output parameters from parameter passing area back to protected space */ _fmemmove(NEARPTR_TO_FARPTR(Session),SessionPtr,sizeof(UDISessionId)); return FUNC_VAL;} /* UDIPConnect (UDI 1.2) */#ifdef UDI13/* 4/93 MDT - This function is needed only for UDI 1.3 and greater * implementations. This code should be checked when the * final specification for UDI 1.3 becomes available. */UDIError UDIPConnect_13( REALPTR UDIConnectAddr, char *Configuration, /* In */ UDISessionId *Session, /* Out */ DOSTerm *TermStruct, /* In */ UDIUInt32 DFEIPCId, /* In 1.3 */ UDIUInt32 *TIPIPCId, /* Out 1.3 */ struct UDIDFEVecRec *DFEVecRec /* In 1.3 */ ){ int err; UDISessionId _far *SessionPtr; UDIUInt32 _far *TIPIPCIdPtr; UDIError ConnectErr; USHORT rm_seg,rm_size; _Packed struct { REALPTR Configuration; REALPTR Session; REALPTR TermStruct; UDIUInt32 DFEIPCId; REALPTR TIPIPCId; REALPTR DFEVecRec; } params; if (!buffer_allocated) { /* Need to get address of conventional memory area for passing parameters. * This will set it for future use everywhere, not just in this function. * rm_address is the protected (32 bit) pointer to the real mode parameter. * passing area. rm_buffer_addr is the real mode pointer to the same buffer. */ err = _dx_real_alloc(REAL_BUFFER_SIZE,&rm_seg,&rm_size); if (err) { printf("Unable to allocate real-mode parameter transfer area (_dx_real_alloc)\n"); exit(0); } /* rm_seg is the real mode paragraph (segment). * Build rm_buffer_addr to be the full real mode pointer (seg:ofst) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -