home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l350 / 3.ddi / EXAMPLES / MDRAW / REALCOPY.C < prev   
Encoding:
C/C++ Source or Header  |  1992-12-28  |  4.9 KB  |  143 lines

  1. /************************************************************************/
  2. /*    Copyright (C) 1986-1993 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. BOOL realcopy(ULONG start_offs, ULONG end_offs, REALPTR *real_basep, 
  21.                 FARPTR *prot_basep, USHORT *rmem_adrp)
  22.  
  23. /*
  24. Description:
  25.     This routine allocates conventional memory for the specified block
  26.     of code (which must be within the first 64K of the protected mode
  27.     program segment) and copies the code to it.
  28.  
  29.     The caller should free up the conventional memory block when it
  30.     is done with the conventional memory.
  31.  
  32.     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
  33.  
  34. Calling arguments:
  35.     start_offs    start of real mode code in program segment
  36.     end_offs    1 byte past end of real mode code in program segment
  37.     real_basep    returned;  real mode ptr to use as a base for the
  38.                 real mode code (eg, to get the real mode FAR
  39.                 addr of a function foo(), take
  40.                 real_basep + (ULONG) foo).
  41.                 This pointer is constructed such that
  42.                 offsets within the real mode segment are
  43.                 the same as the link-time offsets in the
  44.                 protected mode program segment
  45.     prot_basep    returned;  prot mode ptr to use as a base for getting
  46.                 to the conventional memory, also constructed
  47.                 so that adding the prot mode offset of a
  48.                 function or variable to the base gets you a 
  49.                 ptr to the function or variable in the 
  50.                 conventional memory block.
  51.     rmem_adrp    returned;  real mode para addr of allocated 
  52.                 conventional memory block, to be used to free
  53.                 up the conventional memory when done.  DO NOT
  54.                 USE THIS TO CONSTRUCT A REAL MODE PTR, USE
  55.                 REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
  56.                 CORRECTLY. 
  57.  
  58. Returned values:
  59.     TRUE        if error
  60.     FALSE        if success
  61. */
  62. {
  63.     ULONG    rm_base;    /* base real mode para addr for accessing */
  64.                     /* allocated conventional memory */
  65.     UCHAR    *sp;        /* source pointer for copy */
  66.     FARPTR    dp;        /* destination pointer for copy */
  67.     ULONG    len;        /* number of bytes to copy */
  68.     ULONG    templ;
  69.     USHORT    temps;
  70.  
  71. /*
  72.  * First check for valid inputs
  73.  */
  74.      if (start_offs >= end_offs || end_offs > 0x10000)
  75.     {
  76.         printf("Real mode code not in 1st 64K of program segment\n");
  77.         return TRUE;
  78.     }
  79.  
  80. /*
  81.  * Round start_offs down to a paragraph (16-byte) boundary so we can set up
  82.  * the real mode pointer easily.
  83.  */
  84.      start_offs &= ~15;
  85.  
  86. /*
  87.  * Allocate the conventional memory for our real mode code.  Remember to
  88.  * round byte count UP to 16-byte paragraph size.  We alloc it
  89.  * above the DOS data buffer so both the DOS data buffer and the appl
  90.  * conventional mem block can still be resized.
  91.  *
  92.  * First just try to alloc it;  if we can't get it, shrink the appl mem
  93.  * block down to the minimum, try to alloc the memory again, then grow the
  94.  * appl mem block back to the maximum.  (Don't try to shrink the DOS data 
  95.  * buffer to free conventional memory;  it wouldn't be good for this routine 
  96.  * to have the possible side effect of making file I/O run slower.)
  97.  */
  98.     len = ((end_offs - start_offs) + 15) >> 4; 
  99.     if (_dx_real_above(len, rmem_adrp, &temps) != _DOSE_NONE)
  100.     {
  101.         if (_dx_cmem_usage(0, FALSE, &templ, &templ) != _DOSE_NONE)
  102.         {
  103.             printf("Error shrinking conv memory block\n");
  104.             return TRUE;
  105.         }
  106.         if (_dx_real_above(len, rmem_adrp, &temps) != _DOSE_NONE)
  107.             *rmem_adrp = 0;
  108.         if (_dx_cmem_usage(0, TRUE, &templ, &templ) != _DOSE_NONE)
  109.         {
  110.             if (*rmem_adrp != 0)
  111.                 _dx_real_free(*rmem_adrp);
  112.             printf("Error growing conv memory block\n");
  113.             return TRUE;
  114.         }
  115.         if (*rmem_adrp == 0)
  116.         {
  117.             printf("Can't allocate conv mem for real mode code\n");
  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.     FP_SET(dp, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));
  139.     len = end_offs - start_offs; 
  140.     WriteFarMem(dp, sp, len);
  141.      return FALSE;
  142. }
  143.