1 |
106 |
markom |
/************************************************************************/
|
2 |
|
|
/* Copyright (C) 1986-1991 Phar Lap Software, Inc. */
|
3 |
|
|
/* Unpublished - rights reserved under the Copyright Laws of the */
|
4 |
|
|
/* United States. Use, duplication, or disclosure by the */
|
5 |
|
|
/* Government is subject to restrictions as set forth in */
|
6 |
|
|
/* subparagraph (c)(1)(ii) of the Rights in Technical Data and */
|
7 |
|
|
/* Computer Software clause at 252.227-7013. */
|
8 |
|
|
/* Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138 */
|
9 |
|
|
/************************************************************************/
|
10 |
|
|
/* REALCOPY.C: copy real mode code to conventional memory */
|
11 |
|
|
|
12 |
|
|
/*
|
13 |
|
|
* The routine in this file allocates conventional memory and copies
|
14 |
|
|
* real mode code to it.
|
15 |
|
|
*/
|
16 |
|
|
#include <stdio.h>
|
17 |
|
|
#include <pltypes.h>
|
18 |
|
|
#include <pharlap.h>
|
19 |
|
|
|
20 |
|
|
realcopy(start_offs, end_offs, real_basep, prot_basep, rmem_adrp)
|
21 |
|
|
ULONG start_offs;
|
22 |
|
|
ULONG end_offs;
|
23 |
|
|
REALPTR *real_basep;
|
24 |
|
|
FARPTR *prot_basep;
|
25 |
|
|
USHORT *rmem_adrp;
|
26 |
|
|
|
27 |
|
|
/*
|
28 |
|
|
Description:
|
29 |
|
|
This routine allocates conventional memory for the specified block
|
30 |
|
|
of code (which must be within the first 64K of the protected mode
|
31 |
|
|
program segment) and copies the code to it.
|
32 |
|
|
|
33 |
|
|
The caller should free up the conventional memory block when it
|
34 |
|
|
is done with the conventional memory.
|
35 |
|
|
|
36 |
|
|
NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
|
37 |
|
|
|
38 |
|
|
Calling arguments:
|
39 |
|
|
start_offs start of real mode code in program segment
|
40 |
|
|
end_offs 1 byte past end of real mode code in program segment
|
41 |
|
|
real_basep returned; real mode ptr to use as a base for the
|
42 |
|
|
real mode code (eg, to get the real mode FAR
|
43 |
|
|
addr of a function foo(), take
|
44 |
|
|
real_basep + (ULONG) foo).
|
45 |
|
|
This pointer is constructed such that
|
46 |
|
|
offsets within the real mode segment are
|
47 |
|
|
the same as the link-time offsets in the
|
48 |
|
|
protected mode program segment
|
49 |
|
|
prot_basep returned; prot mode ptr to use as a base for getting
|
50 |
|
|
to the conventional memory, also constructed
|
51 |
|
|
so that adding the prot mode offset of a
|
52 |
|
|
function or variable to the base gets you a
|
53 |
|
|
ptr to the function or variable in the
|
54 |
|
|
conventional memory block.
|
55 |
|
|
rmem_adrp returned; real mode para addr of allocated
|
56 |
|
|
conventional memory block, to be used to free
|
57 |
|
|
up the conventional memory when done. DO NOT
|
58 |
|
|
USE THIS TO CONSTRUCT A REAL MODE PTR, USE
|
59 |
|
|
REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
|
60 |
|
|
CORRECTLY.
|
61 |
|
|
|
62 |
|
|
Returned values:
|
63 |
|
|
TRUE if error
|
64 |
|
|
FALSE if success
|
65 |
|
|
*/
|
66 |
|
|
{
|
67 |
|
|
ULONG rm_base; /* base real mode para addr for accessing */
|
68 |
|
|
/* allocated conventional memory */
|
69 |
|
|
UCHAR *sp; /* source pointer for copy */
|
70 |
|
|
FARPTR dp; /* destination pointer for copy */
|
71 |
|
|
ULONG len; /* number of bytes to copy */
|
72 |
|
|
ULONG temp;
|
73 |
|
|
USHORT stemp;
|
74 |
|
|
|
75 |
|
|
/*
|
76 |
|
|
* First check for valid inputs
|
77 |
|
|
*/
|
78 |
|
|
if (start_offs >= end_offs || end_offs > 0x10000)
|
79 |
|
|
{
|
80 |
|
|
return TRUE;
|
81 |
|
|
}
|
82 |
|
|
|
83 |
|
|
/*
|
84 |
|
|
* Round start_offs down to a paragraph (16-byte) boundary so we can set up
|
85 |
|
|
* the real mode pointer easily.
|
86 |
|
|
*/
|
87 |
|
|
start_offs &= ~15;
|
88 |
|
|
|
89 |
|
|
/*
|
90 |
|
|
* Allocate the conventional memory for our real mode code. Remember to
|
91 |
|
|
* round byte count UP to 16-byte paragraph size. We alloc it
|
92 |
|
|
* above the DOS data buffer so both the DOS data buffer and the appl
|
93 |
|
|
* conventional mem block can still be resized.
|
94 |
|
|
*
|
95 |
|
|
* First just try to alloc it; if we can't get it, shrink the appl mem
|
96 |
|
|
* block down to the minimum, try to alloc the memory again, then grow the
|
97 |
|
|
* appl mem block back to the maximum. (Don't try to shrink the DOS data
|
98 |
|
|
* buffer to free conventional memory; it wouldn't be good for this routine
|
99 |
|
|
* to have the possible side effect of making file I/O run slower.)
|
100 |
|
|
*/
|
101 |
|
|
len = ((end_offs - start_offs) + 15) >> 4;
|
102 |
|
|
if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
|
103 |
|
|
{
|
104 |
|
|
if (_dx_cmem_usage(0, FALSE, &temp, &temp) != _DOSE_NONE)
|
105 |
|
|
{
|
106 |
|
|
return TRUE;
|
107 |
|
|
}
|
108 |
|
|
if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
|
109 |
|
|
*rmem_adrp = 0;
|
110 |
|
|
if (_dx_cmem_usage(0, TRUE, &temp, &temp) != _DOSE_NONE)
|
111 |
|
|
{
|
112 |
|
|
if (*rmem_adrp != 0)
|
113 |
|
|
_dx_real_free(*rmem_adrp);
|
114 |
|
|
return TRUE;
|
115 |
|
|
}
|
116 |
|
|
if (*rmem_adrp == 0)
|
117 |
|
|
{
|
118 |
|
|
return TRUE;
|
119 |
|
|
}
|
120 |
|
|
}
|
121 |
|
|
|
122 |
|
|
/*
|
123 |
|
|
* Construct real mode & protected mode pointers to access the allocated
|
124 |
|
|
* memory. Note we know start_offs is aligned on a paragraph (16-byte)
|
125 |
|
|
* boundary, because we rounded it down.
|
126 |
|
|
*
|
127 |
|
|
* We make the offsets come out rights by backing off the real mode selector
|
128 |
|
|
* by start_offs.
|
129 |
|
|
*/
|
130 |
|
|
rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);
|
131 |
|
|
RP_SET(*real_basep, 0, rm_base);
|
132 |
|
|
FP_SET(*prot_basep, rm_base << 4, SS_DOSMEM);
|
133 |
|
|
|
134 |
|
|
/*
|
135 |
|
|
* Copy the real mode code to the allocated memory
|
136 |
|
|
*/
|
137 |
|
|
sp = (UCHAR *) start_offs;
|
138 |
|
|
dp = *prot_basep + start_offs;
|
139 |
|
|
len = end_offs - start_offs;
|
140 |
|
|
while (len-- > 0)
|
141 |
|
|
*dp++ = *sp++;
|
142 |
|
|
return FALSE;
|
143 |
|
|
}
|