home *** CD-ROM | disk | FTP | other *** search
- /**************************** EXTENDED **********************************/
- /* EXTENDED -- The base functions needed to deal with extended */
- /* memory. There is very little in the way of error checking at this */
- /* level. If you ask these routines to do something they assume you */
- /* know what you are doing. Note that the block move functions move */
- /* words not bytes. That means that the smallest amount of memory that */
- /* can be moved is two bytes. */
- /* ROUTINES: */
- /* int copy_from_extended( */
- /* void far *destination, Destination address. */
- /* long source, Source address, absolute form. */
- /* int words Number of words to transfer. */
- /* ) */
- /* returns an error code from the bios interrupt. A value */
- /* of 0 indicates success, anything else indicates an */
- /* error of some sort. */
- /* int copy_to_extended( */
- /* long destination, Destination address, absolute */
- /* form. */
- /* void far *source, Source address. */
- /* int words Number of words to transfer. */
- /* ) */
- /* returns an error code from the bios interrupt. A value */
- /* of 0 indicates success, anything else indicates an */
- /* error of some sort. */
- /* */
- /* V 1.00 28/05/90 Robert Adsett Original version. */
- /* */
- /************************************************************************/
-
- #pragma inline /* In line asembler code used in this module. */
- #include <dos.h> /* Contains macros used in breaking up a far */
- /* pointer into its component parts. */
- #include "bgi.h" /* Make sure public definitions agree with */
- /* these ones. */
-
- /********* Macro to convert a far pointer to a linear address. **********/
-
- #define far_to_linear( address) (((long)(FP_SEG( (address)))*16l)\
- +FP_OFF((address)))
-
- #define EM_INT 0x15 /* Extended memory bios interrupt. */
- #define EM_MEMSIZE 0x88 /* Sub function to determine the size */
- /* of extended memory. */
- #define EM_BLKMOVE 0x87 /* Sub function to move a block of */
- /* memory between different areas. */
-
- /* Segment descriptor used by '286/'386 processors. */
- typedef struct {
- int descriptor_limit; /* Length of segment. */
- int descriptor_base_low_word; /* Base address, 24 */
- char descriptor_base_high_byte; /* bits long. */
- char descriptor_access_rights; /* Access rights. */
- int reserved; /* Reserved in '286, */
- /* partially used in '386. */
- } SEGMENT_DESCRIPTOR;
-
- /* Global Descriptor table used by the bios interrupt. Source and */
- /* destination descriptors are intialized to have read & write */
- /* privliges. SOURCE and DESTINATION are defined to be the offsets */
- /* into the GDT of the source and destination descriptors respectively. */
-
- static SEGMENT_DESCRIPTOR global_descriptor_table[6]={
- { 0, 0, 0, 0, 0},
- { 0, 0, 0, 0, 0},
- { 0, 0, 0, 0x93, 0},
- { 0, 0, 0, 0x93, 0},
- { 0, 0, 0, 0, 0},
- { 0, 0, 0, 0, 0}
- };
-
- #define SOURCE 2 /* Offset of source descriptor. */
- #define DESTINATION 3 /* Offset of destination descriptor. */
-
- /************************************************************************/
- /* */
- /* copy_from_extended -- Copy a block of memory from extended */
- /* memory to regular memory. Returns 0 if successful, otherwise */
- /* it returns the error code returned by the bios. */
- /* Three arguments: */
- /* void far *destination -- far address of where the */
- /* memory block is to be copied */
- /* long source -- address of the extended memory block to */
- /* be copied. The address is the offset */
- /* of the block from the beginning of */
- /* memory. */
- /* int words -- the number of words (two bytes) to copy. */
- /* */
- /************************************************************************/
-
- int copy_from_extended( /* Copy from extended to regular memory.*/
- void far *destination, /* Destination address. */
- unsigned long source, /* Source address, absolute form. */
- int words /* Number of words to transfer. */
- )
- {
- long temp_dest;
- int segment, offset;
- void far *gdt;
-
- /* Load the source descriptor with the base address of the source. */
- global_descriptor_table[SOURCE].descriptor_base_low_word =
- (int)(source & 0xffff);
- global_descriptor_table[SOURCE].descriptor_base_high_byte =
- (char)((source >> 16) & 0xff);
-
- /* Convert the destination address to a linear form, and save as base */
- /* of the destination segment. */
- temp_dest = far_to_linear( destination);
-
- global_descriptor_table[DESTINATION].descriptor_base_low_word =
- (int)(temp_dest & 0xffff);
- global_descriptor_table[DESTINATION].descriptor_base_high_byte =
- (char)((temp_dest >> 16) & 0xff);
-
- /* Set the size of the segments. */
- global_descriptor_table[SOURCE].descriptor_limit = words*2;
- global_descriptor_table[DESTINATION].descriptor_limit = words*2;
-
- gdt = global_descriptor_table; /* Make sure we have a far pointer to */
- /* the global descriptor table. */
- segment = FP_SEG( gdt); /* Get the segment and offset of the */
- offset = FP_OFF( gdt); /* GDT. */
-
- asm push bp /* This is a symptom of paranoia about the */
- asm push si /* safety of registers in bios like calls. It */
- asm push di /* may not be pretty or efficient but at least */
- asm push ds /* it should be safe. */
- asm push es
-
- asm mov ax, segment /* Set ES:SI to point to the GDT. */
- asm mov es, ax
- asm mov si, offset
- asm mov cx, words /* How much do we copy? */
- asm mov ah, EM_BLKMOVE /* Set the function. */
- asm int EM_INT /* Perform the blockmove. */
-
- asm pop es /* Restore saved registers. Nothing else */
- asm pop ds /* should modify them. */
- asm pop di
- asm pop si
- asm pop bp
-
- return( _AH); /* Return the error code. */
- }
-
- /************************************************************************/
- /* */
- /* copy_to_extended -- Copy a block of memory to extended memory */
- /* from regular memory. Returns 0 if successful, otherwise it */
- /* returns the error code returned by the bios. */
- /* Three arguments: */
- /* long destination -- address of the extended memory */
- /* block to copy to. The address is the */
- /* offset of the block from the beginning */
- /* of memory. */
- /* void far *source -- far address of block of memory to */
- /* copy to extended memory. */
- /* int words -- the number of words (two bytes) to copy. */
- /* */
- /************************************************************************/
-
- int copy_to_extended( /* Copy from regular to extended memory.*/
- unsigned long destination,/* Destination address, absolute form.*/
- void far *source, /* Source address. */
- int words /* Number of words to transfer. */
- )
- {
- long temp_source;
- int segment, offset;
- void far *gdt;
-
- /* Load the destination descriptor with base address of the destination.*/
- global_descriptor_table[DESTINATION].descriptor_base_low_word =
- (int)(destination & 0xffff);
- global_descriptor_table[DESTINATION].descriptor_base_high_byte =
- (char)((destination >> 16) & 0xff);
-
- /* Convert the source address to a linear form, and save as base */
- /* of the source segment. */
- temp_source = far_to_linear( source);
-
- global_descriptor_table[SOURCE].descriptor_base_low_word =
- (int)(temp_source & 0xffff);
- global_descriptor_table[SOURCE].descriptor_base_high_byte =
- (char)((temp_source >> 16) & 0xffff);
-
- /* Set the size of the segments. */
- global_descriptor_table[SOURCE].descriptor_limit = words*2;
- global_descriptor_table[DESTINATION].descriptor_limit = words*2;
-
- gdt = global_descriptor_table; /* Make sure we have a far pointer to */
- /* the global descriptor table. */
- segment = FP_SEG( gdt); /* Get the segment and offset of the */
- offset = FP_OFF( gdt); /* GDT. */
-
- asm push bp /* This is a symptom of paranoia about the */
- asm push si /* safety of registers in bios like calls. It */
- asm push di /* may not be pretty or efficient but at least */
- asm push ds /* it should be safe. */
- asm push es
-
- asm mov ax, segment /* Set ES:SI to point to the GDT. */
- asm mov es, ax
- asm mov si, offset
- asm mov cx, words /* How much do we copy? */
- asm mov ah, EM_BLKMOVE /* Set the function. */
- asm int EM_INT /* Perform the blockmove. */
-
- asm pop es /* Restore saved registers. Nothing else */
- asm pop ds /* should modify them. */
- asm pop di
- asm pop si
- asm pop bp
-
- return( _AH); /* Return the error code. */
- }
-
-
-