home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / cbgi111 / src / lib / extended.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-28  |  8.6 KB  |  220 lines

  1. /**************************** EXTENDED **********************************/
  2. /*   EXTENDED -- The base functions needed to deal with extended     */
  3. /* memory.  There is very little in the way of error checking at this    */
  4. /* level.  If you ask these routines to do something they assume you    */
  5. /* know what you are doing.  Note that the block move functions move    */
  6. /* words not bytes.  That means that the smallest amount of memory that    */
  7. /* can be moved is two bytes.                        */
  8. /*   ROUTINES:                                */
  9. /*    int copy_from_extended(                     */
  10. /*            void far *destination,      Destination address.        */
  11. /*        long source,          Source address, absolute form.    */
  12. /*        int words         Number of words to transfer.    */
  13. /*        )                            */
  14. /*        returns an error code from the bios interrupt.  A value    */
  15. /*          of 0 indicates success, anything else indicates an    */
  16. /*          error of some sort.                      */
  17. /*    int copy_to_extended(                         */
  18. /*            long destination,      Destination address, absolute    */
  19. /*                       form.            */
  20. /*        void far *source,     Source address.        */
  21. /*        int words         Number of words to transfer.    */
  22. /*        )                            */
  23. /*        returns an error code from the bios interrupt.  A value    */
  24. /*          of 0 indicates success, anything else indicates an    */
  25. /*          error of some sort.                      */
  26. /*                                    */
  27. /*    V 1.00 28/05/90    Robert Adsett  Original version.        */
  28. /*                                    */
  29. /************************************************************************/
  30.  
  31. #pragma inline        /*  In line asembler code used in this module.    */
  32. #include <dos.h>    /*  Contains macros used in breaking up a far    */
  33.             /* pointer into its component parts.        */
  34. #include "bgi.h"    /*  Make sure public definitions agree with    */
  35.             /* these ones.                    */
  36.  
  37. /********* Macro to convert a far pointer to a linear address. **********/
  38.  
  39. #define    far_to_linear( address)     (((long)(FP_SEG( (address)))*16l)\
  40.                                    +FP_OFF((address)))
  41.  
  42. #define    EM_INT        0x15    /*  Extended memory bios interrupt.    */
  43. #define    EM_MEMSIZE    0x88    /*  Sub function to determine the size    */
  44.                 /* of extended memory.            */
  45. #define EM_BLKMOVE    0x87    /*  Sub function to move a block of    */
  46.                 /* memory between different areas.    */
  47.  
  48. /* Segment descriptor used by '286/'386 processors.            */
  49. typedef struct {
  50.     int    descriptor_limit;        /* Length of segment.    */
  51.     int    descriptor_base_low_word;    /* Base address, 24    */
  52.     char    descriptor_base_high_byte;    /*   bits long.        */
  53.     char    descriptor_access_rights;    /* Access rights.    */
  54.     int    reserved;            /* Reserved in '286,    */
  55.                     /* partially used in '386.    */
  56.     }    SEGMENT_DESCRIPTOR;
  57.  
  58. /*  Global Descriptor table used by the bios interrupt.  Source and    */
  59. /* destination descriptors are intialized to have read & write        */
  60. /* privliges.  SOURCE and DESTINATION are defined to be the offsets    */
  61. /* into the GDT of the source and destination descriptors respectively.    */
  62.  
  63. static SEGMENT_DESCRIPTOR global_descriptor_table[6]={
  64.                         { 0, 0, 0, 0, 0},
  65.                         { 0, 0, 0, 0, 0},
  66.                         { 0, 0, 0, 0x93, 0},
  67.                         { 0, 0, 0, 0x93, 0},
  68.                         { 0, 0, 0, 0, 0},
  69.                         { 0, 0, 0, 0, 0}
  70.                         };
  71.  
  72. #define    SOURCE        2    /* Offset of source descriptor.        */
  73. #define    DESTINATION    3    /* Offset of destination descriptor.    */
  74.  
  75. /************************************************************************/
  76. /*                                    */
  77. /*    copy_from_extended -- Copy a block of memory from extended    */
  78. /*   memory to regular memory.  Returns 0 if successful, otherwise    */
  79. /*   it returns the error code returned by the bios.              */
  80. /*    Three arguments:                        */
  81. /*        void far *destination  -- far address of where the    */
  82. /*                    memory block is to be copied    */
  83. /*        long source -- address of the extended memory block to    */
  84. /*                be copied.  The address is the offset    */
  85. /*                of the block from the beginning of    */
  86. /*                memory.                    */
  87. /*        int words -- the number of words (two bytes) to copy.    */
  88. /*                                    */
  89. /************************************************************************/
  90.  
  91. int copy_from_extended(     /* Copy from extended to regular memory.*/
  92.         void far *destination,     /* Destination address.            */
  93.     unsigned long source,    /* Source address, absolute form.    */
  94.     int words        /* Number of words to transfer.        */
  95.     )
  96. {
  97. long    temp_dest;
  98. int    segment, offset;
  99. void far *gdt;
  100.  
  101. /*  Load the source descriptor with the base address of the source.    */
  102. global_descriptor_table[SOURCE].descriptor_base_low_word = 
  103.                           (int)(source & 0xffff);
  104. global_descriptor_table[SOURCE].descriptor_base_high_byte = 
  105.                        (char)((source >> 16) & 0xff);
  106.  
  107. /*  Convert the destination address to a linear form, and save as base    */
  108. /*   of the destination segment.                    */
  109. temp_dest = far_to_linear( destination);
  110.  
  111. global_descriptor_table[DESTINATION].descriptor_base_low_word = 
  112.                         (int)(temp_dest & 0xffff);
  113. global_descriptor_table[DESTINATION].descriptor_base_high_byte = 
  114.                      (char)((temp_dest >> 16) & 0xff);
  115.  
  116. /*   Set the size of the segments.                    */
  117. global_descriptor_table[SOURCE].descriptor_limit = words*2;
  118. global_descriptor_table[DESTINATION].descriptor_limit = words*2;
  119.  
  120. gdt = global_descriptor_table;    /* Make sure we have a far pointer to    */
  121.                 /*   the global descriptor table.    */
  122. segment = FP_SEG( gdt);        /* Get the segment and offset of the    */
  123. offset = FP_OFF( gdt);        /*   GDT.                */
  124.  
  125. asm    push    bp    /*  This is a symptom of paranoia about the    */
  126. asm    push    si    /* safety of registers in bios like calls.  It    */
  127. asm    push    di    /* may not be pretty or efficient but at least    */
  128. asm    push    ds    /* it should be safe.                */
  129. asm    push    es
  130.  
  131. asm    mov    ax, segment    /* Set ES:SI to point to the GDT.    */
  132. asm    mov    es, ax
  133. asm    mov    si, offset
  134. asm    mov    cx, words    /* How much do we copy?            */
  135. asm    mov    ah, EM_BLKMOVE    /* Set the function.            */
  136. asm    int    EM_INT        /* Perform the blockmove.        */
  137.  
  138. asm    pop    es    /*  Restore saved registers.  Nothing else    */
  139. asm    pop    ds    /* should modify them.                */
  140. asm    pop    di
  141. asm    pop    si
  142. asm    pop    bp
  143.  
  144. return( _AH);            /* Return the error code.        */
  145. }
  146.  
  147. /************************************************************************/
  148. /*                                    */
  149. /*    copy_to_extended -- Copy a block of memory to extended    memory  */
  150. /*   from regular memory.  Returns 0 if successful, otherwise it     */
  151. /*   returns the error code returned by the bios.              */
  152. /*    Three arguments:                        */
  153. /*        long destination -- address of the extended memory    */
  154. /*                block to copy to.  The address is the     */
  155. /*                offset of the block from the beginning     */
  156. /*                of memory.                */
  157. /*        void far *source -- far address of block of memory to    */
  158. /*                    copy to extended memory.    */
  159. /*        int words -- the number of words (two bytes) to copy.    */
  160. /*                                    */
  161. /************************************************************************/
  162.  
  163. int copy_to_extended(         /* Copy from regular to extended memory.*/
  164.         unsigned long destination,/* Destination address, absolute form.*/
  165.     void far *source,     /* Source address.            */
  166.     int words        /* Number of words to transfer.        */
  167.     )
  168. {
  169. long    temp_source;
  170. int    segment, offset;
  171. void far *gdt;
  172.  
  173. /* Load the destination descriptor with base address of the destination.*/
  174. global_descriptor_table[DESTINATION].descriptor_base_low_word = 
  175.                                               (int)(destination & 0xffff);
  176. global_descriptor_table[DESTINATION].descriptor_base_high_byte = 
  177.                        (char)((destination >> 16) & 0xff);
  178.  
  179. /*  Convert the source address to a linear form, and save as base    */
  180. /*   of the source segment.                        */
  181. temp_source = far_to_linear( source);
  182.  
  183. global_descriptor_table[SOURCE].descriptor_base_low_word = 
  184.                           (int)(temp_source & 0xffff);
  185. global_descriptor_table[SOURCE].descriptor_base_high_byte = 
  186.                      (char)((temp_source >> 16) & 0xffff);
  187.  
  188. /*   Set the size of the segments.                    */
  189. global_descriptor_table[SOURCE].descriptor_limit = words*2;
  190. global_descriptor_table[DESTINATION].descriptor_limit = words*2;
  191.  
  192. gdt = global_descriptor_table;    /* Make sure we have a far pointer to    */
  193.                 /*   the global descriptor table.    */
  194. segment = FP_SEG( gdt);        /* Get the segment and offset of the    */
  195. offset = FP_OFF( gdt);        /*   GDT.                */
  196.  
  197. asm    push    bp    /*  This is a symptom of paranoia about the    */
  198. asm    push    si    /* safety of registers in bios like calls.  It    */
  199. asm    push    di    /* may not be pretty or efficient but at least    */
  200. asm    push    ds    /* it should be safe.                */
  201. asm    push    es
  202.  
  203. asm    mov    ax, segment    /* Set ES:SI to point to the GDT.    */
  204. asm    mov    es, ax
  205. asm    mov    si, offset
  206. asm    mov    cx, words    /* How much do we copy?            */
  207. asm    mov    ah, EM_BLKMOVE    /* Set the function.            */
  208. asm    int    EM_INT        /* Perform the blockmove.        */
  209.  
  210. asm    pop    es    /*  Restore saved registers.  Nothing else    */
  211. asm    pop    ds    /* should modify them.                */
  212. asm    pop    di
  213. asm    pop    si
  214. asm    pop    bp
  215.  
  216. return( _AH);            /* Return the error code.        */
  217. }
  218.  
  219.  
  220.