diff options
| author | 2024-04-25 21:24:10 +0100 | |
|---|---|---|
| committer | 2024-04-25 22:32:27 +0000 | |
| commit | 2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch) | |
| tree | 80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/MEMM/EMM | |
| parent | Merge pull request #430 from jpbaltazar/typoptbr (diff) | |
| download | ms-dos-main.tar.gz ms-dos-main.tar.xz ms-dos-main.zip | |
Diffstat (limited to 'v4.0/src/MEMM/EMM')
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMM.H | 223 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMM40.C | 571 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMMDATA.ASM | 467 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMMDEF.INC | 331 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMMDISP.ASM | 234 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMMFUNCT.C | 660 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMMINC.ASM | 55 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMMP.ASM | 2978 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMMSUP.ASM | 652 | ||||
| -rw-r--r-- | v4.0/src/MEMM/EMM/MAKEFILE | 95 |
10 files changed, 6266 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/EMM/EMM.H b/v4.0/src/MEMM/EMM/EMM.H new file mode 100644 index 0000000..24c0974 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMM.H | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * | ||
| 3 | * (C) Copyright Microsoft Corp. 1986 | ||
| 4 | * | ||
| 5 | * TITLE: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 6 | * EMMLIB.LIB - Expanded Memory Manager Library | ||
| 7 | * | ||
| 8 | * MODULE: EMM.H - EMM includes for "C" code | ||
| 9 | * | ||
| 10 | * VERSION: 0.04 | ||
| 11 | * | ||
| 12 | * DATE: June 14,1986 | ||
| 13 | * | ||
| 14 | ******************************************************************************* | ||
| 15 | * CHANGE LOG | ||
| 16 | * Date Version Description | ||
| 17 | * -------- -------- ------------------------------------------------------- | ||
| 18 | * 06/14/86 Original | ||
| 19 | * 06/14/86 0.00 Changed stack frame structure to match new emmdisp.asm | ||
| 20 | * and allow byte regs access (SBP). | ||
| 21 | * 06/28/86 0.02 Name change from CEMM386 to CEMM (SBP). | ||
| 22 | * 07/06/86 0.04 Changed save area structure (SBP). | ||
| 23 | * | ||
| 24 | ******************************************************************************/ | ||
| 25 | |||
| 26 | #define OK 0 | ||
| 27 | #define EMM_SW_MALFUNCTION 0x80 | ||
| 28 | #define EMM_HW_MALFUNCTION 0x81 | ||
| 29 | #define INVALID_HANDLE 0x83 | ||
| 30 | #define INVALID_FUNCTION 0x84 | ||
| 31 | #define NO_MORE_HANDLES 0x85 | ||
| 32 | #define SAVED_PAGE_DEALLOC 0x86 | ||
| 33 | #define NOT_ENOUGH_EXT_MEM 0x87 | ||
| 34 | #define NOT_ENOUGH_FREE_MEM 0x88 | ||
| 35 | #define ZERO_PAGES 0x89 | ||
| 36 | #define LOG_PAGE_RANGE 0x8A | ||
| 37 | #define PHYS_PAGE_RANGE 0x8B | ||
| 38 | #define SAVE_AREA_FULL 0x8C | ||
| 39 | #define MAP_PREV_SAVED 0x8D | ||
| 40 | #define NO_MAP_SAVED 0x8E | ||
| 41 | #define INVALID_SUBFUNCTION 0x8F | ||
| 42 | #define FEATURE_NOT_SUPPORTED 0x91 | ||
| 43 | #define NAMED_HANDLE_NOT_FOUND 0xA0 | ||
| 44 | #define DUPLICATE_HANDLE_NAMES 0xA1 | ||
| 45 | #define ACCESS_DENIED 0xA4 | ||
| 46 | |||
| 47 | /* | ||
| 48 | * various usefull defines | ||
| 49 | */ | ||
| 50 | #define PAGE_SIZE 0x1000 | ||
| 51 | #define NULL_HANDLE (struct handle_ptr *)0x0FFF | ||
| 52 | #define NULL_PAGE 0xFFFF | ||
| 53 | #define NULL_SAVE (struct save_map *)0 | ||
| 54 | |||
| 55 | #define GET 0x00 /* get/set page map sub codes */ | ||
| 56 | #define SET 0x01 | ||
| 57 | #define GETSET 0x02 | ||
| 58 | #define SIZE 0x03 | ||
| 59 | |||
| 60 | #define EMM_VERSION 0x40 | ||
| 61 | #define Handle_Name_Len 8 | ||
| 62 | |||
| 63 | /* | ||
| 64 | * defines for INTERNAL vs EXTERNAL current_map save | ||
| 65 | */ | ||
| 66 | #define INTERNAL_SAVE (unsigned)1 | ||
| 67 | #define EXTERNAL_SAVE (unsigned)0 | ||
| 68 | |||
| 69 | /* | ||
| 70 | * page table structure | ||
| 71 | */ | ||
| 72 | struct pt { /* page table structure, HW defined */ | ||
| 73 | long pt_entry[1024]; | ||
| 74 | }; | ||
| 75 | |||
| 76 | /* | ||
| 77 | * Page frame table. | ||
| 78 | * Size is dynamic, based on number of pages | ||
| 79 | * available. Allocated at intialization time. Each entry | ||
| 80 | * references 4 80386 pages. | ||
| 81 | * Note that the lower 12 bits of the page address are used | ||
| 82 | * as a link field | ||
| 83 | */ | ||
| 84 | union pft386{ | ||
| 85 | unsigned long address; | ||
| 86 | struct{ | ||
| 87 | unsigned short p_handle; | ||
| 88 | unsigned short high; | ||
| 89 | } words; | ||
| 90 | }; | ||
| 91 | |||
| 92 | /* | ||
| 93 | * save_map | ||
| 94 | * This is an array of structures that save the | ||
| 95 | * current mapping state. Size is dynamically determined. | ||
| 96 | */ | ||
| 97 | struct save_map{ | ||
| 98 | unsigned short s_handle; | ||
| 99 | unsigned short window[4]; | ||
| 100 | }; | ||
| 101 | /* | ||
| 102 | * handle_table | ||
| 103 | * This is an array of handle pointers. It | ||
| 104 | * is dynamically sized based on the amount of memory being | ||
| 105 | * managed. | ||
| 106 | * pft_index of NULL_PAGE means free | ||
| 107 | */ | ||
| 108 | struct handle_ptr{ | ||
| 109 | unsigned short page_index; /* index of list header in emm_page */ | ||
| 110 | unsigned short page_count; /* size of list in EMM pages */ | ||
| 111 | }; | ||
| 112 | |||
| 113 | /* | ||
| 114 | * Handle_Name | ||
| 115 | * This is an 8 character handle name. | ||
| 116 | */ | ||
| 117 | typedef char Handle_Name[Handle_Name_Len]; | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Handle_Dir_Entry | ||
| 121 | * | ||
| 122 | */ | ||
| 123 | struct Handle_Dir_Entry { | ||
| 124 | unsigned short Handle_Value; | ||
| 125 | Handle_Name Dir_Handle_Name; | ||
| 126 | }; | ||
| 127 | |||
| 128 | |||
| 129 | /* | ||
| 130 | * register frame on stack | ||
| 131 | * | ||
| 132 | * This is the stack frame on entry to the in67 dispatcher | ||
| 133 | */ | ||
| 134 | struct reg_frame { | ||
| 135 | unsigned short rdi; /* int 67 entry registers */ | ||
| 136 | unsigned short pad0; | ||
| 137 | unsigned short rsi; | ||
| 138 | unsigned short pad1; | ||
| 139 | unsigned short rbp; | ||
| 140 | unsigned short pad2; | ||
| 141 | unsigned short rsp; | ||
| 142 | unsigned short pad3; | ||
| 143 | union { | ||
| 144 | struct { | ||
| 145 | unsigned short rbx; | ||
| 146 | unsigned short pad4; | ||
| 147 | unsigned short rdx; | ||
| 148 | unsigned short pad5; | ||
| 149 | unsigned short rcx; | ||
| 150 | unsigned short pad6; | ||
| 151 | unsigned short rax; | ||
| 152 | unsigned short pad7; | ||
| 153 | } x; | ||
| 154 | struct { | ||
| 155 | unsigned char rbl; | ||
| 156 | unsigned char rbh; | ||
| 157 | unsigned short pad8; | ||
| 158 | unsigned char rdl; | ||
| 159 | unsigned char rdh; | ||
| 160 | unsigned short pad9; | ||
| 161 | unsigned char rcl; | ||
| 162 | unsigned char rch; | ||
| 163 | unsigned short padA; | ||
| 164 | unsigned char ral; | ||
| 165 | unsigned char rah; | ||
| 166 | unsigned short padB; | ||
| 167 | } h; | ||
| 168 | } hregs; | ||
| 169 | unsigned short ret_addr; /* return addr */ | ||
| 170 | unsigned short rcs; /* CS segment */ | ||
| 171 | unsigned short PFlag; /* protected mode flag */ | ||
| 172 | unsigned short rds; /* int 67 entry DS segment */ | ||
| 173 | unsigned short res; /* int 67 entry ES segment */ | ||
| 174 | unsigned short rgs; /* int 67 entry GS segment */ | ||
| 175 | unsigned short rfs; /* int 67 entry FS segment */ | ||
| 176 | }; | ||
| 177 | |||
| 178 | extern struct reg_frame far *regp; | ||
| 179 | /* | ||
| 180 | * macros to set the value of a given register | ||
| 181 | * on the stack | ||
| 182 | */ | ||
| 183 | #define setAH(xx) regp->hregs.h.rah = xx | ||
| 184 | #define setAX(xx) regp->hregs.x.rax = xx | ||
| 185 | #define setBX(xx) regp->hregs.x.rbx = xx | ||
| 186 | #define setCX(xx) regp->hregs.x.rcx = xx | ||
| 187 | #define setDX(xx) regp->hregs.x.rdx = xx | ||
| 188 | |||
| 189 | |||
| 190 | |||
| 191 | /* | ||
| 192 | * 4.0 EXTRAS | ||
| 193 | */ | ||
| 194 | |||
| 195 | /* | ||
| 196 | * Number of Physical Pages: | ||
| 197 | * | ||
| 198 | * LIM 3.2: Page Frame ==> 4 x 16k pages | ||
| 199 | * LIM 4.0: 256k to 640k ==> 24 x 16k pages plus 3.2 page frame | ||
| 200 | */ | ||
| 201 | #define EMM32_PHYS_PAGES 4 | ||
| 202 | #define EMM40_PHYS_PAGES (24 + EMM32_PHYS_PAGES) | ||
| 203 | |||
| 204 | /* | ||
| 205 | * structure of mappable physical page | ||
| 206 | */ | ||
| 207 | struct mappable_page { | ||
| 208 | unsigned short page_seg; /* segment of physical page */ | ||
| 209 | unsigned short physical_page; /* physical page number */ | ||
| 210 | }; | ||
| 211 | |||
| 212 | /* OS/E Enable/Disable defines */ | ||
| 213 | #define OS_IDLE 0 | ||
| 214 | #define OS_ENABLED 1 | ||
| 215 | #define OS_DISABLED 2 | ||
| 216 | |||
| 217 | /* | ||
| 218 | * structure of page map `register' bank | ||
| 219 | */ | ||
| 220 | struct PageBankMap { | ||
| 221 | unsigned short pbm_window; | ||
| 222 | unsigned char pbm_map[64]; | ||
| 223 | }; | ||
diff --git a/v4.0/src/MEMM/EMM/EMM40.C b/v4.0/src/MEMM/EMM/EMM40.C new file mode 100644 index 0000000..cce3a64 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMM40.C | |||
| @@ -0,0 +1,571 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * | ||
| 3 | * (C) Copyright Microsoft Corp. 1986 | ||
| 4 | * | ||
| 5 | * TITLE: VDMM | ||
| 6 | * | ||
| 7 | * MODULE: EMM40.C - EMM 4.0 functions code. | ||
| 8 | * | ||
| 9 | * VERSION: 0.00 | ||
| 10 | * | ||
| 11 | * DATE: Feb 25, 1987 | ||
| 12 | * | ||
| 13 | ******************************************************************************* | ||
| 14 | * CHANGE LOG | ||
| 15 | * Date Version Description | ||
| 16 | * -------- -------- ------------------------------------------------------- | ||
| 17 | * 02/25/87 0.00 Orignal | ||
| 18 | * | ||
| 19 | ******************************************************************************* | ||
| 20 | * FUNCTIONAL DESCRIPTION | ||
| 21 | * | ||
| 22 | * Paged EMM Driver for the iAPX 386. | ||
| 23 | * Extra functions defined in the 4.0 spec required by Windows. | ||
| 24 | * | ||
| 25 | ******************************************************************************/ | ||
| 26 | |||
| 27 | /****************************************************************************** | ||
| 28 | INCLUDE FILES | ||
| 29 | ******************************************************************************/ | ||
| 30 | #include "emm.h" | ||
| 31 | /*#include "mem_mgr.h"*/ | ||
| 32 | |||
| 33 | |||
| 34 | /****************************************************************************** | ||
| 35 | EXTERNAL DATA STRUCTURES | ||
| 36 | ******************************************************************************/ | ||
| 37 | /* | ||
| 38 | * handle_table | ||
| 39 | * This is an array of handle pointers. | ||
| 40 | * page_index of zero means free | ||
| 41 | */ | ||
| 42 | extern struct handle_ptr handle_table[]; | ||
| 43 | extern Handle_Name Handle_Name_Table[]; /* Handle names */ | ||
| 44 | extern unsigned short handle_table_size; /* number of entries */ | ||
| 45 | extern unsigned short handle_count; /* active handle count */ | ||
| 46 | |||
| 47 | /* | ||
| 48 | * EMM Page table | ||
| 49 | * this array contains lists of indexes into the 386 | ||
| 50 | * Page Table. Each list is pointed to by a handle | ||
| 51 | * table entry and is sequential/contiguous. This is | ||
| 52 | * so that maphandlepage doesn't have to scan a list | ||
| 53 | * for the specified entry. | ||
| 54 | */ | ||
| 55 | extern unsigned short *emm_page; /* _emm_page array */ | ||
| 56 | extern int free_count; /* current free count */ | ||
| 57 | extern int total_pages; /* number being managed */ | ||
| 58 | extern unsigned emmpt_start; /* next free entry in table */ | ||
| 59 | |||
| 60 | /* | ||
| 61 | * EMM free table | ||
| 62 | * this array is a stack of available page table entries. | ||
| 63 | * each entry is an index into the pseudo page table | ||
| 64 | */ | ||
| 65 | /*extern unsigned free_stack_count; /* number of entries */ | ||
| 66 | |||
| 67 | /* | ||
| 68 | * Current status of `HW'. The way this is handled is that | ||
| 69 | * when returning status to caller, normal status is reported | ||
| 70 | * via EMMstatus being moved into AX. Persistant errors | ||
| 71 | * (such as internal datastructure inconsistancies, etc) are | ||
| 72 | * placed in `EMMstatus' as HW failures. All other errors are | ||
| 73 | * transient in nature (out of memory, handles, ...) and are | ||
| 74 | * thus reported by directly setting AX. The EMMstatus variable | ||
| 75 | * is provided for expansion and is not currently being | ||
| 76 | * set to any other value. | ||
| 77 | */ | ||
| 78 | extern unsigned short EMMstatus; | ||
| 79 | |||
| 80 | /* | ||
| 81 | * 4.0 EXTRAS | ||
| 82 | */ | ||
| 83 | |||
| 84 | extern unsigned short emm40_info[5]; /* hardware information */ | ||
| 85 | extern struct mappable_page mappable_pages[]; /* mappable segments | ||
| 86 | and corresponding pages */ | ||
| 87 | extern short mappable_page_count; /* number of entries in above */ | ||
| 88 | extern short page_frame_pages; /* pages in the page frame */ | ||
| 89 | extern short physical_page_count; /* number of physical pages */ | ||
| 90 | /*extern char VM1_cntxt_pages; /* pages in a VM1 context */ | ||
| 91 | /*extern char VMn_cntxt_pages; /* pages in a VM context */ | ||
| 92 | /*extern char VM1_cntxt_bytes; /* bytes in a VM1 context */ | ||
| 93 | /*extern char VMn_cntxt_bytes; /* bytes in a VM context */ | ||
| 94 | extern char cntxt_pages; /* pages in context */ | ||
| 95 | extern char cntxt_bytes; /* bytes in context */ | ||
| 96 | extern unsigned short PF_Base; | ||
| 97 | extern unsigned short VM1_EMM_Pages; | ||
| 98 | /*extern unsigned short VM1_EMM_Offset;*/ | ||
| 99 | extern long page_frame_base[]; | ||
| 100 | extern char EMM_MPindex[]; | ||
| 101 | extern long OSEnabled; /* OS/E function flag */ | ||
| 102 | extern long OSKey; /* Key for OS/E function */ | ||
| 103 | |||
| 104 | /****************************************************************************** | ||
| 105 | EXTERNAL FUNCTIONS | ||
| 106 | ******************************************************************************/ | ||
| 107 | extern struct handle_ptr *valid_handle(); /* validate handle */ | ||
| 108 | extern unsigned far *source_addr(); /* get DS:SI far ptr */ | ||
| 109 | extern unsigned far *dest_addr(); /* get ES:DI far ptr */ | ||
| 110 | extern unsigned wcopyb(); | ||
| 111 | extern unsigned copyout(); | ||
| 112 | extern unsigned short Avail_Pages(); | ||
| 113 | |||
| 114 | |||
| 115 | /****************************************************************************** | ||
| 116 | ROUTINES | ||
| 117 | ******************************************************************************/ | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Reallocate Pages | ||
| 121 | * parameters: | ||
| 122 | * bx -- new number of pages | ||
| 123 | * dx -- handle | ||
| 124 | * returns: | ||
| 125 | * bx -- new number of pages | ||
| 126 | * | ||
| 127 | * Change the number of pages allocated to a handle. | ||
| 128 | * | ||
| 129 | * ISP 5/23/88 Updated for MEMM | ||
| 130 | */ | ||
| 131 | ReallocatePages() | ||
| 132 | { | ||
| 133 | #define handle ((unsigned short)regp->hregs.x.rdx) | ||
| 134 | |||
| 135 | register struct handle_ptr *hp; | ||
| 136 | struct handle_ptr *hp_save; | ||
| 137 | unsigned new_size; | ||
| 138 | register unsigned n_pages; | ||
| 139 | register unsigned next; | ||
| 140 | |||
| 141 | if ( (hp = valid_handle(handle)) == NULL_HANDLE ) | ||
| 142 | return; /* (error code already set) */ | ||
| 143 | |||
| 144 | setAH((unsigned char)EMMstatus); /* Assume success */ | ||
| 145 | new_size = regp->hregs.x.rbx; | ||
| 146 | if ( new_size == hp->page_count ) | ||
| 147 | return; /* do nothing... */ | ||
| 148 | |||
| 149 | if ( new_size > hp->page_count ) { | ||
| 150 | if ( new_size > total_pages ) { | ||
| 151 | setAH(NOT_ENOUGH_EXT_MEM); | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | n_pages = new_size - hp->page_count; | ||
| 155 | if ( n_pages > Avail_Pages() ) { | ||
| 156 | setAH(NOT_ENOUGH_FREE_MEM); | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | if ( hp->page_count == 0 ) | ||
| 160 | next = hp->page_index = emmpt_start; | ||
| 161 | else | ||
| 162 | next = hp->page_index + hp->page_count; | ||
| 163 | hp->page_count = new_size; | ||
| 164 | if ( next != emmpt_start ) { | ||
| 165 | /* | ||
| 166 | * Must shuffle emm_page array to make room | ||
| 167 | * for the extra pages. wcopyb correctly | ||
| 168 | * handles this case where the destination | ||
| 169 | * overlaps the source. | ||
| 170 | */ | ||
| 171 | wcopyb(emm_page+next, emm_page+next+n_pages, | ||
| 172 | emmpt_start - next); | ||
| 173 | /* Now tell other handles where their pages went */ | ||
| 174 | hp_save = hp; | ||
| 175 | for ( hp = handle_table; | ||
| 176 | hp < &handle_table[handle_table_size]; hp++ ) | ||
| 177 | if ( hp->page_index != NULL_PAGE && | ||
| 178 | hp->page_index >= next ) | ||
| 179 | hp->page_index += n_pages; | ||
| 180 | hp = hp_save; | ||
| 181 | } | ||
| 182 | emmpt_start += n_pages; | ||
| 183 | if ( get_pages(n_pages, next) == NULL_PAGE) { /* strange failure */ | ||
| 184 | setAH(NOT_ENOUGH_FREE_MEM); | ||
| 185 | new_size = hp->page_count - n_pages; /* as it was! */ | ||
| 186 | setBX(new_size); | ||
| 187 | goto shrink; /* and undo damage */ | ||
| 188 | } | ||
| 189 | } else { | ||
| 190 | /* Shrinking - make handle point to unwanted pages */ | ||
| 191 | shrink: | ||
| 192 | hp->page_count -= new_size; | ||
| 193 | hp->page_index += new_size; | ||
| 194 | free_pages(hp); /* free space in emm_page array */ | ||
| 195 | /* Undo damage to handle, the index was not changed */ | ||
| 196 | hp->page_count = new_size; | ||
| 197 | hp->page_index -= new_size; | ||
| 198 | } | ||
| 199 | |||
| 200 | #undef handle | ||
| 201 | } | ||
| 202 | |||
| 203 | /* | ||
| 204 | * UndefinedFunction | ||
| 205 | * | ||
| 206 | * An undefined or unsupported function. | ||
| 207 | * | ||
| 208 | * 05/10/88 ISP No update needed | ||
| 209 | */ | ||
| 210 | UndefinedFunction() | ||
| 211 | { | ||
| 212 | setAH(INVALID_FUNCTION); | ||
| 213 | } | ||
| 214 | |||
| 215 | /* | ||
| 216 | * Get Mappable Physical Address Array | ||
| 217 | * parameters: | ||
| 218 | * al == 0 | ||
| 219 | * es:di -- destination | ||
| 220 | * returns: | ||
| 221 | * cx -- number of mappable pages | ||
| 222 | * | ||
| 223 | * parameters: | ||
| 224 | * al == 1 | ||
| 225 | * returns: | ||
| 226 | * cx -- number of mappable pages | ||
| 227 | * | ||
| 228 | * Get the number of mappable pages and the segment address for each | ||
| 229 | * physical page. | ||
| 230 | * | ||
| 231 | * ISP 5/23/88 Updated for MEMM. u_ptr made into a far pointer. | ||
| 232 | */ | ||
| 233 | GetMappablePAddrArray() | ||
| 234 | { | ||
| 235 | unsigned far *u_ptr; | ||
| 236 | int n_pages; | ||
| 237 | int i; | ||
| 238 | struct mappable_page *mp = mappable_pages; | ||
| 239 | |||
| 240 | n_pages = mappable_page_count; | ||
| 241 | |||
| 242 | if ( regp->hregs.h.ral == 0 ) { | ||
| 243 | if ( n_pages > 0 ) { | ||
| 244 | u_ptr = dest_addr(); /* ES:DI */ | ||
| 245 | for (i=0 ; i < 48 ; i++) | ||
| 246 | if (EMM_MPindex[i] != -1) | ||
| 247 | copyout(((struct mappable_page far *)u_ptr)++, | ||
| 248 | mp + EMM_MPindex[i], | ||
| 249 | sizeof(struct mappable_page) ); | ||
| 250 | } | ||
| 251 | } else if ( regp->hregs.h.ral != 1 ) { | ||
| 252 | setAH(INVALID_SUBFUNCTION); | ||
| 253 | return; | ||
| 254 | } | ||
| 255 | setCX(n_pages); | ||
| 256 | setAH((unsigned char)EMMstatus); | ||
| 257 | } | ||
| 258 | |||
| 259 | /* | ||
| 260 | * Get Expanded Memory Hardware Information | ||
| 261 | * parameters: | ||
| 262 | * al == 0 | ||
| 263 | * es:di -- user array | ||
| 264 | * returns: | ||
| 265 | * es:di[0] = raw page size in paragraphs | ||
| 266 | * es:di[2] = number of EXTRA fast register sets | ||
| 267 | * es:di[4] = number of bytes needed to save a context | ||
| 268 | * es:di[6] = number of settable DMA channels | ||
| 269 | * | ||
| 270 | * parameters: | ||
| 271 | * al == 1 | ||
| 272 | * returns: | ||
| 273 | * bx = number of free raw pages | ||
| 274 | * dx = total number of raw pages | ||
| 275 | * | ||
| 276 | * ISP 5/23/88 Updated for MEMM. Made u_ptr into far ptr. | ||
| 277 | */ | ||
| 278 | GetInformation() | ||
| 279 | { | ||
| 280 | unsigned far *u_ptr; | ||
| 281 | unsigned pages; | ||
| 282 | |||
| 283 | if ( OSEnabled >= OS_DISABLED ) { | ||
| 284 | setAH(ACCESS_DENIED); /* Denied by operating system */ | ||
| 285 | return; | ||
| 286 | } | ||
| 287 | |||
| 288 | if ( regp->hregs.h.ral == 0 ) { | ||
| 289 | u_ptr = dest_addr(); /* ES:DI */ | ||
| 290 | emm40_info[2] = (short)cntxt_bytes; /* update size */ | ||
| 291 | copyout(u_ptr, emm40_info, sizeof(emm40_info)); | ||
| 292 | setAH((unsigned char)EMMstatus); | ||
| 293 | } else if ( regp->hregs.h.ral == 1 ) { | ||
| 294 | GetUnallocatedPageCount(); /* Use existing code */ | ||
| 295 | } else | ||
| 296 | setAH(INVALID_SUBFUNCTION); | ||
| 297 | } | ||
| 298 | |||
| 299 | /* | ||
| 300 | * GetSetHandleAttribute | ||
| 301 | * | ||
| 302 | * parameters: | ||
| 303 | * al == 0 | ||
| 304 | * returns: | ||
| 305 | * al == 0 -- volatile handles | ||
| 306 | * | ||
| 307 | * parameters: | ||
| 308 | * al == 1 | ||
| 309 | * returns: | ||
| 310 | * ah = 91h -- Feature not supported | ||
| 311 | * | ||
| 312 | * parameters: | ||
| 313 | * al == 2 | ||
| 314 | * returns: | ||
| 315 | * al == 0 -- Supports ONLY volatile handles | ||
| 316 | * | ||
| 317 | * 05/09/88 ISP No update needed | ||
| 318 | */ | ||
| 319 | GetSetHandleAttribute() | ||
| 320 | { | ||
| 321 | #define handle ((unsigned short)regp->hregs.x.rdx) | ||
| 322 | |||
| 323 | if ( regp->hregs.h.ral == 0 ) { | ||
| 324 | if (valid_handle(handle) == NULL_HANDLE) | ||
| 325 | return; /* (error code already set) */ | ||
| 326 | setAX(EMMstatus << 8); /* AL = 0 [volatile attribute] */ | ||
| 327 | } else if ( regp->hregs.h.ral == 1 ) { | ||
| 328 | setAH(FEATURE_NOT_SUPPORTED); | ||
| 329 | } else if ( regp->hregs.h.ral == 2 ) { | ||
| 330 | setAX(EMMstatus << 8); /* AL = 0 [volatile attribute] */ | ||
| 331 | } else | ||
| 332 | setAH(INVALID_SUBFUNCTION); | ||
| 333 | |||
| 334 | #undef handle | ||
| 335 | } | ||
| 336 | |||
| 337 | |||
| 338 | |||
| 339 | |||
| 340 | /* | ||
| 341 | * GetSetHandleName | ||
| 342 | * | ||
| 343 | * Subfunction 0 Gets the name of a given handle | ||
| 344 | * Subfunction 1 Sets a new name for handle | ||
| 345 | * | ||
| 346 | * parameters: | ||
| 347 | * al == 0 | ||
| 348 | * es:di == Data area to copy handle name to | ||
| 349 | * dx -- handle | ||
| 350 | * returns: | ||
| 351 | * [es:di] == Name of DX handle | ||
| 352 | * | ||
| 353 | * parameters: | ||
| 354 | * al == 1 | ||
| 355 | * ds:si == new handle name | ||
| 356 | * dx -- handle | ||
| 357 | * returns: | ||
| 358 | * ah = Status | ||
| 359 | * | ||
| 360 | * ISP 5/23/88 Updated for MEMM. Name made into far *. Copyin routine used | ||
| 361 | * to copy name in into handle name table. | ||
| 362 | */ | ||
| 363 | GetSetHandleName() | ||
| 364 | { | ||
| 365 | register unsigned short handle = ((unsigned short)regp->hregs.x.rdx); | ||
| 366 | register char far *Name; | ||
| 367 | |||
| 368 | /* Validate subfunction */ | ||
| 369 | if ( (regp->hregs.h.ral != 0) && (regp->hregs.h.ral != 1) ) { | ||
| 370 | setAH(INVALID_SUBFUNCTION); | ||
| 371 | return; | ||
| 372 | } | ||
| 373 | |||
| 374 | /* Validate handle */ | ||
| 375 | |||
| 376 | if ( valid_handle(handle) == NULL_HANDLE ) | ||
| 377 | return; /* (error code already set) */ | ||
| 378 | |||
| 379 | /* Implement subfunctions 0 and 1 */ | ||
| 380 | if ( regp->hregs.h.ral == 0 ) { | ||
| 381 | Name = (char far *)dest_addr(); /* ES:DI */ | ||
| 382 | copyout(Name, Handle_Name_Table[handle & 0xFF], Handle_Name_Len); | ||
| 383 | setAH((unsigned char)EMMstatus); | ||
| 384 | } else if ( regp->hregs.h.ral == 1 ) { | ||
| 385 | GetHandleDirectory(); /* See if already there */ | ||
| 386 | switch ( regp->hregs.h.rah ) { | ||
| 387 | case NAMED_HANDLE_NOT_FOUND: | ||
| 388 | break; | ||
| 389 | case DUPLICATE_HANDLE_NAMES: | ||
| 390 | return; | ||
| 391 | default: | ||
| 392 | if ( handle == regp->hregs.x.rdx ) | ||
| 393 | break; /* same handle, OK */ | ||
| 394 | regp->hregs.x.rdx = handle; | ||
| 395 | setAH(DUPLICATE_HANDLE_NAMES); | ||
| 396 | return; | ||
| 397 | } | ||
| 398 | Name = (char far *)source_addr(); | ||
| 399 | copyin(Handle_Name_Table[handle & 0xFF], Name, Handle_Name_Len); | ||
| 400 | setAH((unsigned char)EMMstatus); | ||
| 401 | } else | ||
| 402 | setAH(INVALID_SUBFUNCTION); | ||
| 403 | |||
| 404 | } | ||
| 405 | |||
| 406 | |||
| 407 | |||
| 408 | |||
| 409 | /* | ||
| 410 | * GetHandleDirectory | ||
| 411 | * | ||
| 412 | * Subfunction 0 Returns a directory of handles and handle names | ||
| 413 | * Subfunction 1 Returns the handle specified by the name at [ds:si] | ||
| 414 | * | ||
| 415 | * parameters: | ||
| 416 | * al == 0 | ||
| 417 | * es:di == Data area to copy handle name to | ||
| 418 | * returns: | ||
| 419 | * al == Number of entries in the handle_dir array | ||
| 420 | * [es:di] == Handle_Dir array | ||
| 421 | * | ||
| 422 | * parameters: | ||
| 423 | * al == 1 | ||
| 424 | * [ds:si] == Handle name to locate | ||
| 425 | * returns: | ||
| 426 | * ah == Status | ||
| 427 | * | ||
| 428 | * parameters: | ||
| 429 | * al == 2 | ||
| 430 | * returns: | ||
| 431 | * bx == Total handles in system | ||
| 432 | * | ||
| 433 | * ISP 5/23/88 Updated for MEMM. nameaddress and dir_entry made into far * | ||
| 434 | * copyin routine used to copy name into local area for search. | ||
| 435 | */ | ||
| 436 | GetHandleDirectory() | ||
| 437 | { | ||
| 438 | char far *NameAddress; | ||
| 439 | register struct handle_ptr *hp; | ||
| 440 | struct Handle_Dir_Entry far *Dir_Entry; | ||
| 441 | unsigned short Handle_Num, Found; | ||
| 442 | /* | ||
| 443 | * since all local variables are allocated on stack (SS seg) | ||
| 444 | * and DS and SS has grown apart (ie DS != SS), | ||
| 445 | * we need variables in DS seg (ie static variables) to pass | ||
| 446 | * to copyout(),copyin() and Names_Match() which expects those | ||
| 447 | * parameters that are near pointers to be in DS | ||
| 448 | * | ||
| 449 | * PC 08/03/88 | ||
| 450 | */ | ||
| 451 | static Handle_Name Name; | ||
| 452 | static unsigned short Real_Handle; | ||
| 453 | |||
| 454 | if ( regp->hregs.h.ral == 0 ) { | ||
| 455 | Dir_Entry = (struct Handle_Dir_Entry far *)dest_addr(); | ||
| 456 | hp = handle_table; | ||
| 457 | for (Handle_Num = 0; Handle_Num < handle_table_size; Handle_Num++) { | ||
| 458 | if ( hp->page_index != NULL_PAGE) { | ||
| 459 | Real_Handle = Handle_Num; | ||
| 460 | copyout(Dir_Entry, &Real_Handle, sizeof(short)); | ||
| 461 | copyout(Dir_Entry->Dir_Handle_Name, Handle_Name_Table[Handle_Num], Handle_Name_Len); | ||
| 462 | Dir_Entry++; | ||
| 463 | } hp++; | ||
| 464 | } setAX((EMMstatus << 8) + handle_count); | ||
| 465 | } else if ( regp->hregs.h.ral == 1 ) { | ||
| 466 | NameAddress = (char far *)source_addr(); | ||
| 467 | copyin(Name, NameAddress, Handle_Name_Len); | ||
| 468 | hp = handle_table; | ||
| 469 | Found = 0; | ||
| 470 | Handle_Num = 0; | ||
| 471 | while ((Handle_Num < handle_table_size) && (Found < 2)) { | ||
| 472 | if ( hp->page_index != NULL_PAGE ) { | ||
| 473 | if (Names_Match(Name, Handle_Name_Table[Handle_Num])) { | ||
| 474 | Found++; | ||
| 475 | Real_Handle = Handle_Num; | ||
| 476 | } | ||
| 477 | } hp++; | ||
| 478 | Handle_Num++; | ||
| 479 | } | ||
| 480 | switch (Found) { | ||
| 481 | case 0: | ||
| 482 | setAH((unsigned char)NAMED_HANDLE_NOT_FOUND); | ||
| 483 | break; | ||
| 484 | case 1: | ||
| 485 | setDX(Real_Handle); | ||
| 486 | setAH((unsigned char)EMMstatus); | ||
| 487 | break; | ||
| 488 | default: | ||
| 489 | setAH((unsigned char)DUPLICATE_HANDLE_NAMES); | ||
| 490 | } | ||
| 491 | |||
| 492 | } else if ( regp->hregs.h.ral == 2 ) { | ||
| 493 | setBX(handle_table_size); | ||
| 494 | setAH((unsigned char)EMMstatus); | ||
| 495 | } else | ||
| 496 | setAH(INVALID_SUBFUNCTION); | ||
| 497 | |||
| 498 | #undef handle | ||
| 499 | } | ||
| 500 | |||
| 501 | /* | ||
| 502 | * Prepare For Warm Boot | ||
| 503 | * | ||
| 504 | * Always ready to reboot the system so just return status = OK | ||
| 505 | * | ||
| 506 | * parameters: | ||
| 507 | * None | ||
| 508 | * returns: | ||
| 509 | * AH = EMMstatus | ||
| 510 | * | ||
| 511 | * 05/09/88 ISP No update needed. | ||
| 512 | * | ||
| 513 | */ | ||
| 514 | PrepareForWarmBoot() | ||
| 515 | { | ||
| 516 | setAH((unsigned char)EMMstatus); | ||
| 517 | } | ||
| 518 | |||
| 519 | /* | ||
| 520 | * Enable/Disable OS/E Function Set Functions | ||
| 521 | * | ||
| 522 | * Enable/Disable access to functions 26, 28 and 30 | ||
| 523 | * | ||
| 524 | * parameters: | ||
| 525 | * AL = 0 Enable Functions | ||
| 526 | * AL = 1 Disable Functions | ||
| 527 | * AL = 2 Return Access Key | ||
| 528 | * BX, CX Access Key | ||
| 529 | * returns: | ||
| 530 | * AH = EMMstatus | ||
| 531 | * BX, CX Access Key if successful | ||
| 532 | * | ||
| 533 | * 05/09/88 ISP Updated for MEMM. Removed check for pCurVMID | ||
| 534 | * | ||
| 535 | */ | ||
| 536 | OSDisable() | ||
| 537 | { | ||
| 538 | unsigned char function = regp->hregs.h.ral; | ||
| 539 | |||
| 540 | if ( function > 2 ) { | ||
| 541 | setAH(INVALID_SUBFUNCTION); | ||
| 542 | return; | ||
| 543 | } | ||
| 544 | |||
| 545 | if ( OSEnabled == OS_IDLE ) { /* First invocation */ | ||
| 546 | if ( function == 2 ) { | ||
| 547 | setAH(ACCESS_DENIED); | ||
| 548 | return; | ||
| 549 | } | ||
| 550 | OSKey = Get_Key_Val(); /* Suitably random number */ | ||
| 551 | regp->hregs.x.rbx = (short)OSKey; | ||
| 552 | regp->hregs.x.rcx = (short)(OSKey >> 16); | ||
| 553 | } else { /* Check Key */ | ||
| 554 | if ( (short)OSKey != regp->hregs.x.rbx | ||
| 555 | || (short)(OSKey >> 16) != regp->hregs.x.rcx ) { | ||
| 556 | setAH(ACCESS_DENIED); | ||
| 557 | return; | ||
| 558 | } | ||
| 559 | } | ||
| 560 | if ( function == 0 ) /* enable */ | ||
| 561 | OSEnabled = 1; | ||
| 562 | else if ( function == 1 ) /* disable */ | ||
| 563 | OSEnabled = 2; | ||
| 564 | else if ( function == 2 ) /* return key */ | ||
| 565 | OSEnabled = 0; | ||
| 566 | |||
| 567 | setAH((unsigned char)EMMstatus); | ||
| 568 | } | ||
| 569 | |||
| 570 | |||
| 571 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/EMM/EMMDATA.ASM b/v4.0/src/MEMM/EMM/EMMDATA.ASM new file mode 100644 index 0000000..dce5928 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMDATA.ASM | |||
| @@ -0,0 +1,467 @@ | |||
| 1 | page 58,132 | ||
| 2 | ;****************************************************************************** | ||
| 3 | title EMMDATA - EMM data structures definitions | ||
| 4 | ;****************************************************************************** | ||
| 5 | ; | ||
| 6 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 7 | ; | ||
| 8 | ; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 9 | ; EMMLIB.LIB - Expanded Memory Manager Functions Library | ||
| 10 | ; | ||
| 11 | ; Module: EMMDAT | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date: June 14,1986 | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/14/86 Added MapSize (SBP) | ||
| 24 | ; 06/27/86 0.02 Reordered tables to place size dependent ones at end. | ||
| 25 | ; 06/28/86 0.02 Name change from CEMM386 to CEMM (SBP). | ||
| 26 | ; 07/06/86 0.04 Made _emm_page,_emm_free, and _pft386 pointers instead | ||
| 27 | ; of labels to allow sizing of these arrays based on the | ||
| 28 | ; number of pages in the system. Also added _emm_brk. | ||
| 29 | ; ? 0.05 Modified for WIN386 | ||
| 30 | ; 05/06/88 0.06 Modified back for MEMM. | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; Functional Description: | ||
| 35 | ; data definitions for emm/lim | ||
| 36 | ; | ||
| 37 | ; | ||
| 38 | ;****************************************************************************** | ||
| 39 | .lfcond ; list false conditionals | ||
| 40 | .386p | ||
| 41 | ; include protseg.inc | ||
| 42 | include vdmseg.inc | ||
| 43 | include vdmsel.inc | ||
| 44 | include page.inc | ||
| 45 | include emmdef.inc | ||
| 46 | |||
| 47 | _DATA SEGMENT | ||
| 48 | |||
| 49 | public EMM_PAGE_CNT | ||
| 50 | public HANDLE_CNT | ||
| 51 | |||
| 52 | PUBLIC _total_pages | ||
| 53 | PUBLIC _EMMstatus | ||
| 54 | PUBLIC _emm40_info | ||
| 55 | PUBLIC _page_frame_base | ||
| 56 | PUBLIC _mappable_pages | ||
| 57 | PUBLIC _mappable_page_count | ||
| 58 | PUBLIC _physical_page_count | ||
| 59 | PUBLIC _page_frame_pages | ||
| 60 | PUBLIC EMM_MPindex | ||
| 61 | PUBLIC _EMM_MPindex | ||
| 62 | PUBLIC _save_map | ||
| 63 | PUBLIC _handle_table | ||
| 64 | PUBLIC _Handle_Name_Table | ||
| 65 | PUBLIC _handle_table_size | ||
| 66 | PUBLIC _handle_count | ||
| 67 | PUBLIC _emmpt_start | ||
| 68 | PUBLIC _free_top | ||
| 69 | PUBLIC _free_count | ||
| 70 | PUBLIC _emm_page | ||
| 71 | PUBLIC _emm_free | ||
| 72 | PUBLIC _pft386 | ||
| 73 | PUBLIC _emm_brk | ||
| 74 | PUBLIC EMM_dynamic_data_area | ||
| 75 | PUBLIC EMM_data_end | ||
| 76 | PUBLIC _regp | ||
| 77 | PUBLIC EMM_savES | ||
| 78 | PUBLIC EMM_savDI | ||
| 79 | PUBLIC CurRegSet | ||
| 80 | PUBLIC _CurRegSet | ||
| 81 | PUBLIC CurRegSetn | ||
| 82 | PUBLIC FRS_array | ||
| 83 | PUBLIC FRS_free | ||
| 84 | PUBLIC PF_Base | ||
| 85 | PUBLIC _PF_Base | ||
| 86 | PUBLIC _OSEnabled | ||
| 87 | PUBLIC _OSKey | ||
| 88 | PUBLIC _VM1_EMM_Pages | ||
| 89 | PUBLIC _cntxt_pages | ||
| 90 | PUBLIC _cntxt_bytes | ||
| 91 | |||
| 92 | |||
| 93 | |||
| 94 | ;****************************************************************************** | ||
| 95 | ; DATA STRUCTURES FOR MEMM | ||
| 96 | ; | ||
| 97 | ; The data structures are documented below. Only a description of how | ||
| 98 | ; emm interfaces with the page table memory mananger is appropriate here | ||
| 99 | ; | ||
| 100 | ; During initialisation the pages in the physical address space to be devoted | ||
| 101 | ; to emm are indicated in the _pft386 array. This array translates the emm | ||
| 102 | ; page number to a pte in the system page table. | ||
| 103 | ; | ||
| 104 | ; The emm pages currently free are copied to the emm_free stack and the | ||
| 105 | ; free_stack pointer points to the top of this stack. | ||
| 106 | ; | ||
| 107 | ; When pages are allocated to a handle the pages are allocated from the stack | ||
| 108 | ; and copied to the emm_page array. The place where a handles pages are | ||
| 109 | ; copied to in this array is recorded in the handle table. The emm_page array | ||
| 110 | ; should be kept compacted all the time. Thus if a handle is deallocated, the | ||
| 111 | ; pages allocated to the handle are copied to the emm_free stack and the hole | ||
| 112 | ; left behind in the emm_page array is compacted by shifting all the entries | ||
| 113 | ; below upwards updating the indexes stored in the handle table if needed. | ||
| 114 | ; | ||
| 115 | ; given map_handle_page(phys_page, log_page, handle) | ||
| 116 | ; | ||
| 117 | ; a. determine pte offset in system page table corresponding to phys_page | ||
| 118 | ; from the _page_frame_base table. | ||
| 119 | ; | ||
| 120 | ; b. access handle table for the handle and determine the start of the | ||
| 121 | ; emm pages allocated to the handle in the emm_page array. | ||
| 122 | ; | ||
| 123 | ; c. add log_page to this start offset in the emm_page array and access | ||
| 124 | ; the entry in this array. This entry is an offset into the _pft386 | ||
| 125 | ; array for the emm page under consideration. | ||
| 126 | ; | ||
| 127 | ; d. use this index into _pft386 to access the pte for the log page under | ||
| 128 | ; consideration. | ||
| 129 | ; | ||
| 130 | ; e. store this pte in the pte offset corresponding to the phys_page as | ||
| 131 | ; determined in a. | ||
| 132 | ;****************************************************************************** | ||
| 133 | |||
| 134 | |||
| 135 | |||
| 136 | |||
| 137 | |||
| 138 | |||
| 139 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 140 | ;00. EMM Status | ||
| 141 | ; Current status of `HW'. The way this is handled is that | ||
| 142 | ; when returning status to caller, normal status is reported | ||
| 143 | ; via EMMstatus being moved into AX. Persistant errors | ||
| 144 | ; (such as internal datastructure inconsistancies, etc) are | ||
| 145 | ; placed in `EMMstatus' as HW failures. All other errors are | ||
| 146 | ; transient in nature (out of memory, handles, ...) and are | ||
| 147 | ; thus reported by directly setting AX. The EMMstatus variable | ||
| 148 | ; is provided for expansion and is not currently being | ||
| 149 | ; set to any other value. | ||
| 150 | ; | ||
| 151 | ; set to OK for now. when integrated, the value should be | ||
| 152 | ; set to EMM_HW_MALFUNCTION (81H) initially, then set to | ||
| 153 | ; OK (00H) when the `EMM ON' function is invoke | ||
| 154 | ; | ||
| 155 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 156 | _EMMstatus LABEL WORD | ||
| 157 | DW 00H | ||
| 158 | |||
| 159 | |||
| 160 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 161 | ;01. Register Block Pointer | ||
| 162 | ; points to the the vm86 regs on the | ||
| 163 | ; stack | ||
| 164 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 165 | _regp LABEL WORD | ||
| 166 | DW 0 | ||
| 167 | DW 0 | ||
| 168 | |||
| 169 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 170 | ;02. TOTAL_PAGES | ||
| 171 | ; total # of EMM pages in system | ||
| 172 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 173 | _total_pages LABEL WORD | ||
| 174 | DW 0 | ||
| 175 | |||
| 176 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 177 | ;03. LIM 3.2 PAGE FRAME | ||
| 178 | ; A suitable lim 3.2 page frame found | ||
| 179 | ; by scanning for free area | ||
| 180 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 181 | PF_Base label word | ||
| 182 | _PF_Base label word | ||
| 183 | dw 0FFFFh ; Undefined initially | ||
| 184 | |||
| 185 | |||
| 186 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 187 | ;04. PAGE FRAME BASE | ||
| 188 | ; this is the map of linear addr. | ||
| 189 | ; of the n 16kb physical pages used to | ||
| 190 | ; access the EMM pages. The contents | ||
| 191 | ; far pointers into the system page | ||
| 192 | ; table. If a lim 3.2 page frame is | ||
| 193 | ; available it gets the entries at the | ||
| 194 | ; beginning | ||
| 195 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 196 | _page_frame_base LABEL DWORD | ||
| 197 | DW MAX_PHYS_PAGES dup (0, PAGET_GSEL) ; PTE offsets of physical pages | ||
| 198 | |||
| 199 | ; | ||
| 200 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 201 | ;05. MAPPABLE PAGE ARRAY | ||
| 202 | ; this is the segment, physical page | ||
| 203 | ; correspondence array | ||
| 204 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 205 | ; | ||
| 206 | _mappable_pages LABEL WORD | ||
| 207 | REPT MAX_PHYS_PAGES | ||
| 208 | Mappable_Page <0, 0> | ||
| 209 | ENDM | ||
| 210 | |||
| 211 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 212 | ;06. MAPPABLE PAGE INDEX ARRAY | ||
| 213 | ; the pages in system memory are numbered | ||
| 214 | ; 4000h onwards whereas the physical page | ||
| 215 | ; numbers are arbitrarily numbered. this | ||
| 216 | ; array indexes into the mappable page | ||
| 217 | ; array. | ||
| 218 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 219 | EMM_MPindex LABEL byte ; table of indexes into above | ||
| 220 | _EMM_MPindex LABEL byte | ||
| 221 | db 48 dup (-1) ; 4000h to 10000h | ||
| 222 | |||
| 223 | _mappable_page_count dw MAX_PHYS_PAGES ; number of entries in above | ||
| 224 | _physical_page_count dw 0 ; number of physical pages | ||
| 225 | |||
| 226 | |||
| 227 | _page_frame_pages dw 4 ; pages in the page frame | ||
| 228 | ifdef CGA | ||
| 229 | _VM1_EMM_Pages dw 30 ; 4000h to B800h for now | ||
| 230 | else | ||
| 231 | _VM1_EMM_Pages dw 24 ; 4000h to A000h for now | ||
| 232 | endif | ||
| 233 | |||
| 234 | ; don't need it (used only in _set_40windows) | ||
| 235 | ; | ||
| 236 | ;_VM1_EMM_Offset dw 0 ; Offset of these in context | ||
| 237 | ; | ||
| 238 | ; combined into _cntxt_pages and _cntxt_bytes | ||
| 239 | ; | ||
| 240 | ;_VM1_cntxt_pages db 0 ; Pages in context | ||
| 241 | ;_VM1_cntxt_bytes db 0 ; Bytes in context | ||
| 242 | ;_VMn_cntxt_pages db 0 | ||
| 243 | ;_VMn_cntxt_bytes db 0 | ||
| 244 | |||
| 245 | _cntxt_pages db 0 ; Pages in context | ||
| 246 | _cntxt_bytes db 0 ; Bytes in context | ||
| 247 | |||
| 248 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 249 | ;07. HARDWARE INFORMATION | ||
| 250 | ; Hardware information returned by Get | ||
| 251 | ; Information call | ||
| 252 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 253 | _emm40_info LABEL WORD | ||
| 254 | dw 0400h ; raw page size in paragraphs (16k) | ||
| 255 | dw FRS_COUNT-1 ; number of fast register sets | ||
| 256 | dw size FRS_window+2 ; max. number of bytes to save a context | ||
| 257 | ; ( FRS_window size + 2 ) | ||
| 258 | dw 0 ; settable DMA channels | ||
| 259 | dw 0 ; DMA_channel_operation | ||
| 260 | |||
| 261 | ; | ||
| 262 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 263 | ;08. FRS MAPPING STATE ARRAY | ||
| 264 | ; Used to emulate FRS. FRS 0..FRS_COUNT-1. FRS 0 | ||
| 265 | ; is the normal mapping set. | ||
| 266 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 267 | FRS_array LABEL WORD ; Array of Fast Register Set structures | ||
| 268 | REPT FRS_COUNT | ||
| 269 | FRS_struc <> | ||
| 270 | ENDM | ||
| 271 | |||
| 272 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 273 | ;09. Variables to support FRS Implementation | ||
| 274 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 275 | FRS_free db 0 ; How many of the above are free | ||
| 276 | CurRegSetn db 0 ; Number of Current Register Set | ||
| 277 | _CurRegSet LABEL WORD | ||
| 278 | CurRegSet dw 0 ; Pointer to Current Register Set Area | ||
| 279 | ; in FRS_array | ||
| 280 | |||
| 281 | ; initialized to 0:0 for initial buffer inquiry | ||
| 282 | ; | ||
| 283 | EMM_savES dw 0 ; store for buffer address provided | ||
| 284 | EMM_savDI dw 0 ; by user on frs function | ||
| 285 | |||
| 286 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 287 | ;10. Variable to support OS access functions | ||
| 288 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 289 | _OSEnabled dd 0 ; Security feature | ||
| 290 | _OSKey dd ? ; Key for security functions | ||
| 291 | |||
| 292 | |||
| 293 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 294 | ;11. Mysterious variable right now | ||
| 295 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 296 | VEMMD_SSbase dd 0 ; Linear base of Stack Segment | ||
| 297 | |||
| 298 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 299 | ;12. save_map | ||
| 300 | ; This is an array of structures that save | ||
| 301 | ; the current mapping state. | ||
| 302 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 303 | _save_map LABEL BYTE | ||
| 304 | REPT HANDLE_CNT ; one save area per handle | ||
| 305 | SaveMap_struc <> ; save area | ||
| 306 | ENDM | ||
| 307 | |||
| 308 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 309 | ;13. handle_table | ||
| 310 | ; This is an array of handle pointers. | ||
| 311 | ; In addition to the handle number a ptr | ||
| 312 | ; to the start of the ems pages allocated | ||
| 313 | ; to the handle in emm_page array is given | ||
| 314 | ; emm_page index of NULL_PAGE means free | ||
| 315 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 316 | _handle_table LABEL WORD | ||
| 317 | REPT HANDLE_CNT ; one table per handle | ||
| 318 | HandleTable_struc <> ; initialized handle table | ||
| 319 | ENDM | ||
| 320 | |||
| 321 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 322 | ;14. handle name table | ||
| 323 | ; Under LIM 4.0 each allocated handle can | ||
| 324 | ; be given a 8 byte name. this array keeps | ||
| 325 | ; track of the handle names | ||
| 326 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 327 | _Handle_Name_Table LABEL QWORD | ||
| 328 | DQ HANDLE_CNT dup (0) ; 8 0 bytes for every handle name | ||
| 329 | |||
| 330 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 331 | ;15. book-keeping variables for handle table | ||
| 332 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 333 | _handle_table_size LABEL WORD | ||
| 334 | DW HANDLE_CNT | ||
| 335 | |||
| 336 | _handle_count LABEL WORD | ||
| 337 | DW 0 | ||
| 338 | |||
| 339 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 340 | ;16. EMMPT_START | ||
| 341 | ; emmpt_start is the index of the next | ||
| 342 | ; free entry in emm_page | ||
| 343 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 344 | _emmpt_start LABEL WORD | ||
| 345 | DW 0 | ||
| 346 | |||
| 347 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 348 | ;17. FREE pointers | ||
| 349 | ; free_top is the index for the top free | ||
| 350 | ; page in the emm_free stack. | ||
| 351 | ; free_count is the number of free | ||
| 352 | ; pages in the emm_free stack | ||
| 353 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 354 | _free_top LABEL WORD | ||
| 355 | DW EMM_PAGE_CNT ; none free initially | ||
| 356 | |||
| 357 | _free_count LABEL WORD | ||
| 358 | DW 0 ; none free initially | ||
| 359 | |||
| 360 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 361 | ;18. POINTERS to the variable sized data structures | ||
| 362 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 363 | _emm_page dw offset dgroup:EMM_dynamic_data_area | ||
| 364 | _emm_free dw 0 | ||
| 365 | _pft386 dw 0 | ||
| 366 | _emm_brk dw offset dgroup:EMM_data_end | ||
| 367 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 368 | ; Espensive data structures are going to be | ||
| 369 | ; to be assigned storage dynamically so that we | ||
| 370 | ; don't end up wasting space. These data areas | ||
| 371 | ; are referred to by pointers above. | ||
| 372 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 373 | EMM_dynamic_data_area LABEL BYTE | ||
| 374 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 375 | |||
| 376 | ifndef NOHIMEM | ||
| 377 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 378 | ;19. EMM Page table | ||
| 379 | ; this array contains lists of indexes into the pseudo | ||
| 380 | ; Page Table. Each list is pointed to | ||
| 381 | ; by a handle table entry and is sequential/contiguous. | ||
| 382 | ; This is so that maphandlepage doesn't have to scan | ||
| 383 | ; a list for the specified entry. | ||
| 384 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 385 | _def_emm_page LABEL WORD | ||
| 386 | DW EMM_PAGE_CNT DUP(0) | ||
| 387 | |||
| 388 | |||
| 389 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 390 | ;20. EMM free table | ||
| 391 | ; this array is a stack of available page table entries. | ||
| 392 | ; each entry is an index into pft386[]. | ||
| 393 | ; it is initialized to FFFF entries. this is | ||
| 394 | ; a null page entry/ | ||
| 395 | ; it is initialized to FFFF entries. this is | ||
| 396 | ; a null page entry. | ||
| 397 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 398 | _def_emm_free LABEL WORD | ||
| 399 | DW EMM_PAGE_CNT DUP(NULL_PAGE) | ||
| 400 | |||
| 401 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 402 | ;21. PAGE FRAME TABLE | ||
| 403 | ; This array contains addresses of physical | ||
| 404 | ; page frames for 386 pages. A page is | ||
| 405 | ; referred to by an index into this array. | ||
| 406 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 407 | _def_pft386 LABEL DWORD | ||
| 408 | DD EMM_PAGE_CNT DUP(NULL_HANDLE AND 0fffh) | ||
| 409 | |||
| 410 | endif | ||
| 411 | |||
| 412 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 413 | EMM_data_end label byte | ||
| 414 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 415 | |||
| 416 | _DATA ENDS | ||
| 417 | |||
| 418 | ifndef NOHIMEM | ||
| 419 | |||
| 420 | else | ||
| 421 | |||
| 422 | VDATA SEGMENT | ||
| 423 | public vdata_begin | ||
| 424 | vdata_begin label byte | ||
| 425 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 426 | ;19. EMM Page table | ||
| 427 | ; this array contains lists of indexes into the pseudo | ||
| 428 | ; Page Table. Each list is pointed to | ||
| 429 | ; by a handle table entry and is sequential/contiguous. | ||
| 430 | ; This is so that maphandlepage doesn't have to scan | ||
| 431 | ; a list for the specified entry. | ||
| 432 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 433 | _def_emm_pagev LABEL WORD | ||
| 434 | DW EMM_PAGE_CNT DUP(0) | ||
| 435 | |||
| 436 | |||
| 437 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 438 | ;20. EMM free table | ||
| 439 | ; this array is a stack of available page table entries. | ||
| 440 | ; each entry is an index into pft386[]. | ||
| 441 | ; it is initialized to FFFF entries. this is | ||
| 442 | ; a null page entry/ | ||
| 443 | ; it is initialized to FFFF entries. this is | ||
| 444 | ; a null page entry. | ||
| 445 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 446 | _def_emm_freev LABEL WORD | ||
| 447 | DW EMM_PAGE_CNT DUP(NULL_PAGE) | ||
| 448 | |||
| 449 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 450 | ;21. PAGE FRAME TABLE | ||
| 451 | ; This array contains addresses of physical | ||
| 452 | ; page frames for 386 pages. A page is | ||
| 453 | ; referred to by an index into this array. | ||
| 454 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 455 | _def_pft386v LABEL DWORD | ||
| 456 | DD EMM_PAGE_CNT DUP(NULL_HANDLE AND 0fffh) | ||
| 457 | |||
| 458 | VDATA ENDS | ||
| 459 | |||
| 460 | |||
| 461 | |||
| 462 | endif | ||
| 463 | |||
| 464 | |||
| 465 | END | ||
| 466 | |||
| 467 | |||
diff --git a/v4.0/src/MEMM/EMM/EMMDEF.INC b/v4.0/src/MEMM/EMM/EMMDEF.INC new file mode 100644 index 0000000..ffe0630 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMDEF.INC | |||
| @@ -0,0 +1,331 @@ | |||
| 1 | ;****************************************************************************** | ||
| 2 | ; | ||
| 3 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 4 | ; | ||
| 5 | ; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 6 | ; EMMLIB.LIB - Expanded Memory Manager Library | ||
| 7 | ; | ||
| 8 | ; Module: EMMDEF.INC - defines for EMM code. | ||
| 9 | ; | ||
| 10 | ; Version: 0.04 | ||
| 11 | ; | ||
| 12 | ; Date: June 21, 1986 | ||
| 13 | ; | ||
| 14 | ;****************************************************************************** | ||
| 15 | ; | ||
| 16 | ; Change log: | ||
| 17 | ; | ||
| 18 | ; DATE REVISION DESCRIPTION | ||
| 19 | ; -------- -------- ------------------------------------------------------- | ||
| 20 | ; 06/21/86 Original | ||
| 21 | ; 06/25/86 0.02 Changed HANDLE_CNT to 255 to match LIM spec (SBP). | ||
| 22 | ; 06/28/86 0.02 Name change from CEMM386 to CEMM (SBP). | ||
| 23 | ; 07/06/86 0.04 Changed save area struct (SBP). | ||
| 24 | ; 05/25/88 Changed to meet LIM 4.0 Spec (PC) | ||
| 25 | ;****************************************************************************** | ||
| 26 | ifndef INC_LIST | ||
| 27 | .xlist | ||
| 28 | endif | ||
| 29 | |||
| 30 | ;****************************************************************************** | ||
| 31 | ; G E N E R A L D E F I N E S | ||
| 32 | ;****************************************************************************** | ||
| 33 | EMM_PAGE_CNT = 2048 ; maximum of 2048 EMM pages (32MB) | ||
| 34 | HANDLE_CNT = 255 ; maximum of 255 EMM handles | ||
| 35 | FRS_COUNT = 16 ; number of 'Fast Register Sets' | ||
| 36 | |||
| 37 | EMM32_PHYS_PAGES = 4 ; page frame contains 4 pages | ||
| 38 | ; | ||
| 39 | ; The 0 to 1M contains 64 physical pages. Of these we are not mapping anything | ||
| 40 | ; between E000 and FFFF, 0000 and 4000. So the Maximum physcial pages we can | ||
| 41 | ; get for mapping is 40. | ||
| 42 | |||
| 43 | TOT_PHYS_PAGES equ 64 | ||
| 44 | MAX_PHYS_PAGES equ 40 ; Life, the Universe | ||
| 45 | ; and Everything | ||
| 46 | PAGE_SIZE = 1000h | ||
| 47 | ; | ||
| 48 | ; Of the above mappable pages the regions C000h to Dfffh have to be searched | ||
| 49 | ; for the mappable pages. | ||
| 50 | ; | ||
| 51 | ABOVE_CONV_STRT_SEG equ 0C000h | ||
| 52 | ABOVE_CONV_STRT_PG equ ABOVE_CONV_STRT_SEG SHR 10 | ||
| 53 | ; | ||
| 54 | ABOVE_CONV_END_SEG equ 0DC00h | ||
| 55 | ABOVE_CONV_END_PG equ ABOVE_CONV_END_SEG SHR 10 | ||
| 56 | ; | ||
| 57 | MAX_ABOVE_CONV_PAGES EQU 8 | ||
| 58 | ; | ||
| 59 | ; Also the system memory mappable region starts at 4000h | ||
| 60 | ; | ||
| 61 | CONV_STRT_SEG equ 4000h | ||
| 62 | CONV_STRT_PG equ CONV_STRT_SEG SHR 10 | ||
| 63 | ; | ||
| 64 | NUM_CONV_PGS equ (0A000h -4000h) SHR 10 | ||
| 65 | ; | ||
| 66 | ; During init we keep track of mappable pages with an array of mappable_segs | ||
| 67 | ; | ||
| 68 | |||
| 69 | PAGE_MAPPABLE equ 0FFh ; | ||
| 70 | PAGE_NOT_MAPPABLE equ 0h ; | ||
| 71 | |||
| 72 | |||
| 73 | NULL_PAGE = 0FFFFh | ||
| 74 | NULL_HANDLE = 00FFFh | ||
| 75 | |||
| 76 | |||
| 77 | ; | ||
| 78 | ; Flags for memory move/xchg | ||
| 79 | ; | ||
| 80 | Source_GT_Dest_Flag = 80h ; Source > Destination for copy / xchg | ||
| 81 | Overlap_Flag = 40h ; Copy overlapping memory | ||
| 82 | Backward_Copy_Flag = 20h ; copy is going to be backward | ||
| 83 | ; | ||
| 84 | ; Flags for PFlag use in Alter Map and Jump | ||
| 85 | ; | ||
| 86 | PFLAG_VM = 0002h ; VM bit in High word of EFLAG | ||
| 87 | PFLAG_VIRTUAL = 0020h ; wheather it's call from virtual or proected mode | ||
| 88 | PFLAG_PATCH_CS_IP = 0008h ; Tell Protected mode dispatch to | ||
| 89 | ; patch new CS:IP onto it's return address | ||
| 90 | ;****************************************************************************** | ||
| 91 | ; S T A T U S D E F I N E S | ||
| 92 | ;****************************************************************************** | ||
| 93 | OK = 0 | ||
| 94 | EMM_SW_MALFUNCTION = 80h | ||
| 95 | EMM_HW_MALFUNCTION = 81h | ||
| 96 | INVALID_HANDLE = 83h | ||
| 97 | INVALID_FUNCTION = 84h | ||
| 98 | NO_MORE_HANDLES = 85h | ||
| 99 | SAVED_PAGE_DEALLOC = 86h | ||
| 100 | NOT_ENOUGH_EXT_MEM = 87h | ||
| 101 | NOT_ENOUGH_FREE_MEM = 88h | ||
| 102 | ZERO_PAGES = 89h | ||
| 103 | LOG_PAGE_RANGE = 8Ah | ||
| 104 | PHYS_PAGE_RANGE = 8Bh | ||
| 105 | SAVE_AREA_FULL = 8Ch | ||
| 106 | MAP_PREV_SAVED = 8Dh | ||
| 107 | NO_MAP_SAVED = 8Eh | ||
| 108 | INVALID_SUBFUNCTION = 8Fh | ||
| 109 | |||
| 110 | ; LIM 4.0 extras | ||
| 111 | |||
| 112 | VALID_OVERLAP = 92h | ||
| 113 | INSUFFICIENT_EMM_PAGES = 93h | ||
| 114 | CONVENTIONAL_EMM_OVERLAP= 94h | ||
| 115 | INVALID_OFFSET = 95h | ||
| 116 | INVALID_REGION_LENGTH = 96h | ||
| 117 | OVERLAPPING_EXCHANGE = 97h | ||
| 118 | INVALID_MEMORY_TYPE = 98h | ||
| 119 | FRSETS_UNSUPPORTED = 99h | ||
| 120 | INVALID_FRSET = 9Ah | ||
| 121 | NO_MORE_FRSETS = 9Bh | ||
| 122 | FRSET_NON_ZERO = 9Ch | ||
| 123 | FRSET_UNDEFINED = 9Dh | ||
| 124 | FRSET_NO_DMA = 9Eh | ||
| 125 | FRSET_INVALID_DMA = 9Fh | ||
| 126 | HANDLE_NAME_NOT_FOUND = 0A0h | ||
| 127 | DUPLICATE_HANDLE_NAME = 0A1h | ||
| 128 | INVALID_WRAPAROUND = 0A2h | ||
| 129 | SOURCE_CORRUPTED = 0A3h | ||
| 130 | ACCESS_DENIED = 0A4h | ||
| 131 | |||
| 132 | |||
| 133 | ;****************************************************************************** | ||
| 134 | ; GET/SET PAGE MAP SUBFUNCTION CODES | ||
| 135 | ;****************************************************************************** | ||
| 136 | GSPM_GET equ 0 | ||
| 137 | GSPM_SET equ 1 | ||
| 138 | GSPM_GETSET equ 2 | ||
| 139 | GSPM_SIZE equ 3 | ||
| 140 | |||
| 141 | ; | ||
| 142 | ; OSEnabled Values | ||
| 143 | ; | ||
| 144 | OS_IDLE equ 0 | ||
| 145 | OS_ENABLED equ 1 | ||
| 146 | OS_DISABLED equ 2 | ||
| 147 | |||
| 148 | ;****************************************************************************** | ||
| 149 | ; S T R U C T U R E S | ||
| 150 | ;****************************************************************************** | ||
| 151 | |||
| 152 | ; | ||
| 153 | ; stack frame after pushad on real/virtual mode entry | ||
| 154 | ; | ||
| 155 | r67_Frame struc | ||
| 156 | rDI dd ? | ||
| 157 | rSI dd ? | ||
| 158 | rBP dd ? | ||
| 159 | rSP dd ? | ||
| 160 | rBX dd ? | ||
| 161 | rDX dd ? | ||
| 162 | rCX dd ? | ||
| 163 | rAX dd ? | ||
| 164 | retaddr dw ? | ||
| 165 | rCS dw ? | ||
| 166 | PFlag dw ? | ||
| 167 | rDS dw ? | ||
| 168 | rES dw ? | ||
| 169 | rGS dw ? | ||
| 170 | rFS dw ? | ||
| 171 | r67_Frame ends | ||
| 172 | |||
| 173 | |||
| 174 | ; | ||
| 175 | ; for _handle_table | ||
| 176 | ; | ||
| 177 | HandleTable_struc struc | ||
| 178 | ht_index dw NULL_PAGE ; index into emm_page for handle's pgs | ||
| 179 | ht_count dw 0 ; number of emm_pages for this handle | ||
| 180 | HandleTable_struc ends | ||
| 181 | |||
| 182 | ; | ||
| 183 | ; for _save_area | ||
| 184 | ; | ||
| 185 | SaveMap_struc struc | ||
| 186 | s_handle dw NULL_HANDLE ; owning handle | ||
| 187 | s_map dw EMM32_PHYS_PAGES dup (NULL_PAGE) ; EMM page #s | ||
| 188 | SaveMap_struc ends | ||
| 189 | |||
| 190 | ; | ||
| 191 | ; structure linking segment with physical page number | ||
| 192 | ; | ||
| 193 | Mappable_Page struc | ||
| 194 | mappable_seg dw ? | ||
| 195 | mappable_pg dw ? | ||
| 196 | Mappable_Page ends | ||
| 197 | |||
| 198 | ; | ||
| 199 | ; Get Partial Page Map | ||
| 200 | ; | ||
| 201 | gppm_struc struc | ||
| 202 | gppm_count dw ? | ||
| 203 | gppm_segs dw ? | ||
| 204 | gppm_struc ends | ||
| 205 | |||
| 206 | ; | ||
| 207 | ; Structures used as arguments to Map Handle Array function | ||
| 208 | ; | ||
| 209 | |||
| 210 | ; For subfunction 0: | ||
| 211 | mha_array0 struc | ||
| 212 | mha0_log_pg dw ? | ||
| 213 | mha0_phys_pg dw ? | ||
| 214 | mha_array0 ends | ||
| 215 | |||
| 216 | ; For subfunction 1: | ||
| 217 | mha_array1 struc | ||
| 218 | mha1_log_pg dw ? | ||
| 219 | mha1_seg dw ? | ||
| 220 | mha_array1 ends | ||
| 221 | |||
| 222 | ; Used by Map and Jump and Map and Call -- Identical to mha_array0 and 1 | ||
| 223 | log_phys_map_struct struc | ||
| 224 | log_page_number dw ? | ||
| 225 | phys_page_number_seg dw ? | ||
| 226 | log_phys_map_struct ends | ||
| 227 | |||
| 228 | ; Map and Jump structure | ||
| 229 | maj_struct struc | ||
| 230 | maj_target_address dd ? | ||
| 231 | maj_log_phys_map_len db ? | ||
| 232 | maj_map_address dd ? | ||
| 233 | maj_struct ends | ||
| 234 | |||
| 235 | ; Map and Call structure | ||
| 236 | mac_struct struc | ||
| 237 | mac_target_address dd ? | ||
| 238 | mac_new_page_map_len db ? | ||
| 239 | mac_new_map_address dd ? | ||
| 240 | mac_old_page_map_len db ? | ||
| 241 | mac_old_map_address dd ? | ||
| 242 | mac_reserved dw 4 dup (?) | ||
| 243 | mac_struct ends | ||
| 244 | |||
| 245 | ; Move / Exchange memory structure | ||
| 246 | mem_memory_descriptor_struct struc | ||
| 247 | mem_memory_type db ? | ||
| 248 | mem_handle dw ? | ||
| 249 | mem_initial_offset dw ? | ||
| 250 | mem_initial_seg_page dw ? | ||
| 251 | mem_memory_descriptor_struct ends | ||
| 252 | |||
| 253 | |||
| 254 | mem_struct struc | ||
| 255 | mem_region_length dd ? | ||
| 256 | mem_source db (SIZE mem_memory_descriptor_struct) dup (?) | ||
| 257 | mem_dest db (SIZE mem_memory_descriptor_struct) dup (?) | ||
| 258 | mem_struct ends | ||
| 259 | |||
| 260 | ; | ||
| 261 | ; Fast Register Set Description | ||
| 262 | ; | ||
| 263 | FRS_struc struc | ||
| 264 | FRS_Window dw MAX_PHYS_PAGES dup (NULL_PAGE) ; emm page numbers | ||
| 265 | FRS_alloc dw 0 ; Is this set allocated | ||
| 266 | FRS_struc ends | ||
| 267 | |||
| 268 | page | ||
| 269 | ;**************************************************************************** | ||
| 270 | ; | ||
| 271 | ; Dword_Align -- Aligns code to dword boundry by inserting nops | ||
| 272 | ; | ||
| 273 | ;**************************************************************************** | ||
| 274 | |||
| 275 | Dword_Align MACRO Seg_Name | ||
| 276 | IF (($ - OFFSET Seg_Name:0) MOD 4) | ||
| 277 | db 90h ;; Nop in code / else byte of 90h in data | ||
| 278 | Dword_Align Seg_Name | ||
| 279 | ENDIF | ||
| 280 | ENDM | ||
| 281 | |||
| 282 | page | ||
| 283 | ;*********************************************** | ||
| 284 | ; | ||
| 285 | ; Validate_Handle - check the handle in DX | ||
| 286 | ; | ||
| 287 | ; ENTRY: Handle as per LIM4.0 spec. in DX | ||
| 288 | ; | ||
| 289 | ; EXIT: If the handle is invalid jump To Death_Label, otherwise, | ||
| 290 | ; EDX points to the _handle_table entry for the handle | ||
| 291 | ; | ||
| 292 | ; USES: EDX | ||
| 293 | ; | ||
| 294 | ;*********************************************** | ||
| 295 | Validate_Handle MACRO Death_Label | ||
| 296 | |||
| 297 | cmp dx, [_handle_table_size] ;Q: handle in range ? | ||
| 298 | jae Death_Label ; N: go to error label | ||
| 299 | shl dx, 2 ; Y: convert handle to | ||
| 300 | add dx, offset _handle_table ; pointer | ||
| 301 | xchg bx, dx | ||
| 302 | cmp [bx.ht_index], NULL_PAGE ;Q: is this handle active ? | ||
| 303 | xchg bx, dx | ||
| 304 | je Death_Label ; N: return error | ||
| 305 | |||
| 306 | ENDM | ||
| 307 | |||
| 308 | ;*********************************************** | ||
| 309 | ; | ||
| 310 | ; Handle2HandlePtr - convert the handle in DX to | ||
| 311 | ; points into handle_table | ||
| 312 | ; | ||
| 313 | ; ENTRY: Handle as per LIM4.0 spec. in DX | ||
| 314 | ; | ||
| 315 | ; EXIT: EDX points to the _handle_table entry for the handle | ||
| 316 | ; | ||
| 317 | ; USES: EDX | ||
| 318 | ; | ||
| 319 | ;*********************************************** | ||
| 320 | Handle2HandlePtr MACRO | ||
| 321 | |||
| 322 | shl dx, 2 ; Y: convert handle to | ||
| 323 | add dx, offset _handle_table ; pointer | ||
| 324 | |||
| 325 | ENDM | ||
| 326 | |||
| 327 | .list ; end of EMMDEF.INC | ||
| 328 | |||
| 329 | |||
| 330 | |||
| 331 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/EMM/EMMDISP.ASM b/v4.0/src/MEMM/EMM/EMMDISP.ASM new file mode 100644 index 0000000..f7ec55c --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMDISP.ASM | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | page 58,132 | ||
| 2 | ;****************************************************************************** | ||
| 3 | title EMMDISP - EMM dispatcher | ||
| 4 | ;****************************************************************************** | ||
| 5 | ; | ||
| 6 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 7 | ; | ||
| 8 | ; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 9 | ; EMMLIB.LIB - Expanded Memory Manager Functions Library | ||
| 10 | ; | ||
| 11 | ; Module: EMM Dispatcher | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date: May 17, 1986 | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 5/17/86 0 initial code | ||
| 24 | ; 6/14/86 modified registers on stack for exit and removed call | ||
| 25 | ; to _emm_init (SBP). | ||
| 26 | ; 6/28/86 0.02 Name change from CEMM386 to CEMM (SBP). | ||
| 27 | ; 7/06/86 0.04 Changed data assumes to DGROUP (SBP). | ||
| 28 | ; 5/25/88 Changed function range check to cover LIM 4.0 (PC) | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; | ||
| 31 | ; Functional Description: | ||
| 32 | ; This module serves to trap Int 67h, place | ||
| 33 | ; arguments on the stack and call the associated | ||
| 34 | ; function | ||
| 35 | ; | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | .lfcond ; list false conditionals | ||
| 39 | .386p | ||
| 40 | |||
| 41 | ;****************************************************************************** | ||
| 42 | ; P U B L I C S | ||
| 43 | ;****************************************************************************** | ||
| 44 | public int67_Entry | ||
| 45 | public dispatch_vector | ||
| 46 | |||
| 47 | ;****************************************************************************** | ||
| 48 | ; I N C L U D E S | ||
| 49 | ;****************************************************************************** | ||
| 50 | include vdmseg.inc | ||
| 51 | include vdmsel.inc | ||
| 52 | include emmdef.inc | ||
| 53 | ; | ||
| 54 | ;****************************************************************************** | ||
| 55 | ; D E F I N E S | ||
| 56 | ;****************************************************************************** | ||
| 57 | ; | ||
| 58 | FALSE equ 0 | ||
| 59 | TRUE equ not FALSE | ||
| 60 | CR equ 0dh | ||
| 61 | LF equ 0ah | ||
| 62 | |||
| 63 | mkvect MACRO name | ||
| 64 | extrn _&name:near | ||
| 65 | dw offset _TEXT:_&name | ||
| 66 | endm | ||
| 67 | |||
| 68 | ;****************************************************************************** | ||
| 69 | ; E X T E R N A L S | ||
| 70 | ;****************************************************************************** | ||
| 71 | |||
| 72 | _DATA SEGMENT | ||
| 73 | extrn _EMMstatus:word | ||
| 74 | extrn Active_Status:byte | ||
| 75 | extrn Auto_Mode:byte | ||
| 76 | extrn _regp:word | ||
| 77 | _DATA ENDS | ||
| 78 | |||
| 79 | |||
| 80 | ;****************************************************************************** | ||
| 81 | ; local data | ||
| 82 | ;****************************************************************************** | ||
| 83 | ; | ||
| 84 | ; remove duplicated variables (defined in emmdata.asm) | ||
| 85 | ; | ||
| 86 | ;_DATA SEGMENT | ||
| 87 | ; | ||
| 88 | ;_regp label word | ||
| 89 | ; dw 0 | ||
| 90 | ; dw 0 | ||
| 91 | ; | ||
| 92 | ;_DATA ENDS | ||
| 93 | |||
| 94 | _TEXT SEGMENT | ||
| 95 | assume cs:_text,ds:DGROUP,ss:DGROUP,es:DGROUP | ||
| 96 | ; | ||
| 97 | db 'PxB' | ||
| 98 | ; | ||
| 99 | |||
| 100 | dispatch_vector label word | ||
| 101 | mkvect GetStatus | ||
| 102 | mkvect GetPageFrameAddress | ||
| 103 | mkvect GetUnallocatedPageCount | ||
| 104 | mkvect AllocatePages | ||
| 105 | mkvect MapHandlePage | ||
| 106 | mkvect DeallocatePages | ||
| 107 | mkvect GetEMMVersion | ||
| 108 | mkvect SavePageMap | ||
| 109 | mkvect RestorePageMap | ||
| 110 | mkvect GetPageMappingRegisterIOArray | ||
| 111 | mkvect GetLogicalToPhysicalPageTrans | ||
| 112 | mkvect GetEMMHandleCount | ||
| 113 | mkvect GetEMMHandlePages | ||
| 114 | mkvect GetAllEMMHandlePages | ||
| 115 | mkvect GetSetPageMap | ||
| 116 | mkvect GetSetPartial ; AH = 4Fh | ||
| 117 | ; 4.0 Functions... | ||
| 118 | mkvect MapHandleArray ; AH = 50h | ||
| 119 | mkvect ReallocatePages | ||
| 120 | mkvect GetSetHandleAttribute | ||
| 121 | mkvect GetSetHandleName | ||
| 122 | mkvect GetHandleDirectory | ||
| 123 | mkvect AlterMapAndJump | ||
| 124 | mkvect AlterMapAndCall | ||
| 125 | mkvect MoveExchangeMemory | ||
| 126 | mkvect GetMappablePAddrArray | ||
| 127 | mkvect GetInformation | ||
| 128 | mkvect AllocateRawPages | ||
| 129 | mkvect AlternateMapRegisterSet | ||
| 130 | mkvect PrepareForWarmBoot | ||
| 131 | mkvect OSDisable | ||
| 132 | |||
| 133 | ;************************************* | ||
| 134 | ; int67_Entry(PFlag,DS,ES) - entry point for int 67 (EMM functions) | ||
| 135 | ; | ||
| 136 | ; unsigned PFlag; /* non-zero = protected mode, else */ | ||
| 137 | ; /* virtual or real mode */ | ||
| 138 | ; unsigned DS; /* DS segment value on entry to int67 */ | ||
| 139 | ; unsigned ES; /* ES segment value on entry to int67 */ | ||
| 140 | ; | ||
| 141 | ; ENTRY: | ||
| 142 | ; REAL or VIRTUAL mode | ||
| 143 | ; DS = DGROUP segment | ||
| 144 | ; PROTECTED mode | ||
| 145 | ; DS = VDMD_GSEL | ||
| 146 | ; | ||
| 147 | ; At the point of the indirect call, | ||
| 148 | ; The stack looks as follows: | ||
| 149 | ; | ||
| 150 | ; | ||
| 151 | ; +-------+ | ||
| 152 | ; | FS | +2CH <--- entry FS segment | ||
| 153 | ; +-------+ | ||
| 154 | ; | GS | +2AH <--- entry GS segment | ||
| 155 | ; +-------+ | ||
| 156 | ; | ES | +28H <--- entry ES segment | ||
| 157 | ; +-------+ | ||
| 158 | ; | DS | +26h <--- entry DS segment | ||
| 159 | ; +-------+ | ||
| 160 | ; | PFlag | +24h <--- protected mode flag | ||
| 161 | ; +-------+ | ||
| 162 | ; | CS | +22h <--- from FAR call to int67_handler | ||
| 163 | ; +-------+ | ||
| 164 | ; | ret | +20h <--- CS:ret | ||
| 165 | ; +-------+ | ||
| 166 | ; | EAX | +1C <-+- from PUSH ALL | ||
| 167 | ; +-------+ | | ||
| 168 | ; | ECX | +18 V | ||
| 169 | ; +-------+ | ||
| 170 | ; | EDX | +14 | ||
| 171 | ; +-------+ | ||
| 172 | ; | EBX | +10 | ||
| 173 | ; +-------+ | ||
| 174 | ; | ESP | +C | ||
| 175 | ; +-------+ | ||
| 176 | ; | EBP | +8 | ||
| 177 | ; +-------+ | ||
| 178 | ; | ESI | +4 | ||
| 179 | ; +-------+ | ||
| 180 | ; | EDI | <--- regp | ||
| 181 | ; +-------+ | ||
| 182 | ; | ||
| 183 | ;************************************* | ||
| 184 | int67_Entry proc far | ||
| 185 | pushad ; save all regs | ||
| 186 | mov bp,sp ; SS:[BP] points to stack frame | ||
| 187 | ; | ||
| 188 | mov [_regp],sp ; regp points to regs on stack | ||
| 189 | mov [_regp+2],ss ; regp now has a far ptr to regs | ||
| 190 | |||
| 191 | ; | ||
| 192 | ; validate function code | ||
| 193 | ; | ||
| 194 | sub ah,40h ; check if entry code too small | ||
| 195 | jb i67_inv_exit ; if so, error exit | ||
| 196 | cmp ah,(5Dh-40h) ; check if entry code too big | ||
| 197 | ja i67_inv_exit ; if so, error exit | ||
| 198 | |||
| 199 | ; | ||
| 200 | ; check for VDM off | ||
| 201 | ; | ||
| 202 | cmp [Auto_Mode],0 ;Q: Auto mode on ? | ||
| 203 | jne i67_jump ; Y: go ahead | ||
| 204 | cmp [Active_Status],0 ; N:Q: are we ON ? | ||
| 205 | je i67_off_err ; N: exit with error code | ||
| 206 | |||
| 207 | ; | ||
| 208 | ; call through the jump table | ||
| 209 | ; | ||
| 210 | i67_jump: | ||
| 211 | xchg ah,al ; AL = function code | ||
| 212 | mov si,ax | ||
| 213 | xchg ah,al ; AH = function code again | ||
| 214 | and si,00FFh ; SI = function # | ||
| 215 | shl si,1 ; SI = table offset | ||
| 216 | call CS:dispatch_vector[si] ; call function | ||
| 217 | |||
| 218 | ok_exit: | ||
| 219 | popad ; restore all regs | ||
| 220 | ret ; bye! | ||
| 221 | |||
| 222 | i67_off_err: ; set h/w error | ||
| 223 | mov byte ptr [bp.rAX+1],EMM_HW_MALFUNCTION | ||
| 224 | jmp ok_exit | ||
| 225 | |||
| 226 | i67_inv_exit: ; set invalid function code error | ||
| 227 | mov byte ptr [bp.rAX+1],INVALID_FUNCTION | ||
| 228 | jmp ok_exit | ||
| 229 | |||
| 230 | int67_entry endp | ||
| 231 | |||
| 232 | _TEXT ENDS | ||
| 233 | END | ||
| 234 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/EMM/EMMFUNCT.C b/v4.0/src/MEMM/EMM/EMMFUNCT.C new file mode 100644 index 0000000..7547536 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMFUNCT.C | |||
| @@ -0,0 +1,660 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * | ||
| 3 | * (C) Copyright Microsoft Corp. 1986 | ||
| 4 | * | ||
| 5 | * TITLE: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 6 | * EMMLIB.LIB - Expanded Memory Manager Library | ||
| 7 | * | ||
| 8 | * MODULE: EMMFUNCT.C - EMM functions code. | ||
| 9 | * | ||
| 10 | * VERSION: 0.10 | ||
| 11 | * | ||
| 12 | * DATE: June 14,1986 | ||
| 13 | * | ||
| 14 | ******************************************************************************* | ||
| 15 | * CHANGE LOG | ||
| 16 | * Date Version Description | ||
| 17 | * -------- -------- ------------------------------------------------------- | ||
| 18 | * 06/14/86 Changed status return to return only AH. And added | ||
| 19 | * PFlag to decide on selector versus segment on long | ||
| 20 | * address generation (SBP). | ||
| 21 | * 06/14/86 Moved save_current_map and restore_map to ASM (SBP). | ||
| 22 | * 06/15/86 Changed NULL_HANDLE to 0x0FFF (see emm.h) (SBP). | ||
| 23 | * 06/21/86 Moved MapHandlePage to ASM (SBP). | ||
| 24 | * Handle # passed to client has high byte = NOT (low byte) | ||
| 25 | * as in the Above Board (SBP). | ||
| 26 | * Valid_Handle -> ASM (SBP). | ||
| 27 | * 06/23/86 Make_Addr removed. source_addr and dest_addr added(SBP). | ||
| 28 | * 06/25/86 0.02 Dealloc checks for save area in use (SBP). | ||
| 29 | * 06/28/86 0.02 Name change from CEMM386 to CEMM (SBP). | ||
| 30 | * 06/29/86 0.02 Return after NOT_ENOUGH_FREE_MEM error in Allocate(SBP). | ||
| 31 | * 07/06/86 0.04 Changed _emm_page,_emm_free, & _pft386 to ptrs (SBP). | ||
| 32 | * 07/06/86 0.04 moved SavePageMap and RestorePageMap to .ASM (SBP). | ||
| 33 | * 07/08/86 0.04 moved GetSetPageMap to .ASM (SBP). | ||
| 34 | * 07/09/86 0.04 removed code which places handle # in _pft386 | ||
| 35 | * entry (SBP). | ||
| 36 | * 07/09/86 0.05 fixed bug in deallocate (SBP). | ||
| 37 | * 05/09/88 0.10 modified for MEMM, modifications are indicated in | ||
| 38 | * individual routines (ISP). | ||
| 39 | * | ||
| 40 | ******************************************************************************* | ||
| 41 | * FUNCTIONAL DESCRIPTION | ||
| 42 | * | ||
| 43 | * Paged EMM Driver for the iAPX 386. | ||
| 44 | * | ||
| 45 | * The basic concept is to use the 386's page tables to emulate | ||
| 46 | * the functions of an EMM board. There are several constraints | ||
| 47 | * that are a result of poor planning on the LIM specifiers part. | ||
| 48 | * - maximum of 64K instantaneously mapped. this will | ||
| 49 | * be faithfully emulated in this design | ||
| 50 | * - maximum of 8Mb of extended memory can be used. | ||
| 51 | * The actual reason for this is because each board | ||
| 52 | * can only support 128 16Kb pages and the limit of | ||
| 53 | * 4 Aboveboards implies 512 pages maximum. This will | ||
| 54 | * not be adhered to since the limit in unnecessary. | ||
| 55 | * | ||
| 56 | * The memory managed by this scheme can be discontiguous but | ||
| 57 | * a 16Kb EMM page can not be composed of discontiguous pieces. | ||
| 58 | * This is not necessary but does simplify the job of managing | ||
| 59 | * the memory. | ||
| 60 | * | ||
| 61 | * The LIM specification implies the existence of a partitioning | ||
| 62 | * of extended memory into `boards'. While this concept is not | ||
| 63 | * meaningfull in the 386 environment, a page to logical board | ||
| 64 | * mapping is provided to support some of the LIM specified | ||
| 65 | * functions: | ||
| 66 | * pages 0 to 127 map to board 0 | ||
| 67 | * pages 128 to 255 map to board 1 | ||
| 68 | * ... | ||
| 69 | * The pages in this case are logical pages and pages on the | ||
| 70 | * same logical board may actually reside on different physical | ||
| 71 | * boards. (In fact, if contiguous memory, a page could actually | ||
| 72 | * be split across 2 different boards.) | ||
| 73 | * | ||
| 74 | * A brief note on parameters: | ||
| 75 | * all parameters to EMM functions are passed in registers. | ||
| 76 | * on entry to the EMM dispatch code, the registers are pushed | ||
| 77 | * onto the stack. In order to access them, they are pointed | ||
| 78 | * to by a global variable (regp). Defines are used to name | ||
| 79 | * these parameters and make the code more readable. | ||
| 80 | * | ||
| 81 | * Definitions: | ||
| 82 | * Handle: | ||
| 83 | * 16 bit value that references a block of | ||
| 84 | * allocated memory. Internally, it is an index into a handle | ||
| 85 | * table. Externally, the high byte is the NOT of the low byte | ||
| 86 | * for compatibility with the Above Board EMM driver. | ||
| 87 | * | ||
| 88 | * EMM page: | ||
| 89 | * a 16Kb contiguous portion of memory, aligned on a | ||
| 90 | * 16Kb boundary in 8086 address space. In physical | ||
| 91 | * address space it can be aligned on a 4Kb boundary. | ||
| 92 | * | ||
| 93 | * page | ||
| 94 | * 386 page. 4Kb in size and 4Kb aligned in physical | ||
| 95 | * address space. | ||
| 96 | * | ||
| 97 | * far86 * | ||
| 98 | * An iAPX 86 style 32 bit pointer. It consists of | ||
| 99 | * a 16 bit offset in the low word and a base | ||
| 100 | * address in the high word. | ||
| 101 | * | ||
| 102 | * Logical page | ||
| 103 | * an EMM page allocated to a handle via allocatepages | ||
| 104 | * function. each such page has a logical page number. | ||
| 105 | * | ||
| 106 | * physical page frame | ||
| 107 | * the location in physical 8086 space that an EMM page | ||
| 108 | * gets mapped to. there are 4 such locations. they are | ||
| 109 | * contiguous starting at page_frame_base | ||
| 110 | * | ||
| 111 | * 386 page frame | ||
| 112 | * this is the physical page in 80386 physical | ||
| 113 | * address space. the address of a 386 page frame | ||
| 114 | * is the value placed in a 80386 page table entry's | ||
| 115 | * high 20 bits. | ||
| 116 | ******************************************************************************/ | ||
| 117 | |||
| 118 | /****************************************************************************** | ||
| 119 | INCLUDE FILES | ||
| 120 | ******************************************************************************/ | ||
| 121 | #include "emm.h" | ||
| 122 | |||
| 123 | |||
| 124 | /****************************************************************************** | ||
| 125 | EXTERNAL DATA STRUCTURES | ||
| 126 | ******************************************************************************/ | ||
| 127 | /* | ||
| 128 | * I/O Map | ||
| 129 | * map_size | ||
| 130 | * this is an array of port addresses, 4 ports per | ||
| 131 | * emulated board. Each emulated board has up to | ||
| 132 | * 128 16Kb EMM pages assigned. The size of the table, | ||
| 133 | * the number of ports used, is map_size | ||
| 134 | * map_size = (<number of 386 pages>/(128*4))*4 | ||
| 135 | */ | ||
| 136 | /*extern unsigned short iomap[]; */ | ||
| 137 | /*extern char map_size;*/ | ||
| 138 | |||
| 139 | /* | ||
| 140 | * map_known | ||
| 141 | * This flags is set whenever the user is given the I/O map | ||
| 142 | */ | ||
| 143 | /*extern char map_known; */ | ||
| 144 | |||
| 145 | /* | ||
| 146 | * page frame base | ||
| 147 | * this is a map of the linear addresses of the | ||
| 148 | * 4 16Kb EMM `physical' windows that the user | ||
| 149 | * accesses the EMM pages through. The entries | ||
| 150 | * of this array are far pointers into the page table. | ||
| 151 | * Thus, the address defined by page_frame_base[0] | ||
| 152 | * is the address of the long word that is the page | ||
| 153 | * table entry for the first EMM window. The reason for | ||
| 154 | * this obscurity is in speed of mapping -- it is used | ||
| 155 | * to directly obtain access to the entry to be programmed | ||
| 156 | */ | ||
| 157 | extern unsigned long page_frame_base[]; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * save_map | ||
| 161 | * This is an array of structures that save the | ||
| 162 | * current mapping state. Size is dynamically determined. | ||
| 163 | */ | ||
| 164 | extern struct save_map save_map[]; | ||
| 165 | |||
| 166 | /* | ||
| 167 | * handle_table | ||
| 168 | * This is an array of handle pointers. | ||
| 169 | * page_index of zero means free | ||
| 170 | */ | ||
| 171 | extern struct handle_ptr handle_table[]; | ||
| 172 | extern Handle_Name Handle_Name_Table[]; | ||
| 173 | extern unsigned short handle_table_size; /* number of entries */ | ||
| 174 | extern unsigned short handle_count; /* active handle count */ | ||
| 175 | |||
| 176 | /* | ||
| 177 | * EMM Page table | ||
| 178 | * this array contains lists of indexes into the 386 | ||
| 179 | * Page Frame Addresses (pft386). Each list is pointed to | ||
| 180 | * by a handle table entry and is sequential/contiguous. | ||
| 181 | * This is so that maphandlepage doesn't have to scan | ||
| 182 | * a list for the specified entry. | ||
| 183 | */ | ||
| 184 | extern unsigned short *emm_page; /* ptr to _emm_page array */ | ||
| 185 | extern unsigned short free_count; /* current free count */ | ||
| 186 | extern unsigned short total_pages; /* number being managed */ | ||
| 187 | extern unsigned short emmpt_start; /* next free entry in table */ | ||
| 188 | |||
| 189 | /* | ||
| 190 | * EMM free table | ||
| 191 | * this array is a stack of available page table entries. | ||
| 192 | * each entry is an index into pft386[]. | ||
| 193 | */ | ||
| 194 | extern unsigned short *emm_free; /* ptr to _emm_free array */ | ||
| 195 | extern unsigned short free_top; | ||
| 196 | |||
| 197 | /* | ||
| 198 | * Page frame table | ||
| 199 | * This array contains addresses of physical page frames | ||
| 200 | * for 386 pages. A page is refered to by an index into | ||
| 201 | * this array | ||
| 202 | */ | ||
| 203 | extern union pft386 *pft386; /* ptr to page frame table array */ | ||
| 204 | |||
| 205 | |||
| 206 | /* | ||
| 207 | * Current status of `HW'. The way this is handled is that | ||
| 208 | * when returning status to caller, normal status is reported | ||
| 209 | * via EMMstatus being moved into AX. Persistant errors | ||
| 210 | * (such as internal datastructure inconsistancies, etc) are | ||
| 211 | * placed in `EMMstatus' as HW failures. All other errors are | ||
| 212 | * transient in nature (out of memory, handles, ...) and are | ||
| 213 | * thus reported by directly setting AX. The EMMstatus variable | ||
| 214 | * is provided for expansion and is not currently being | ||
| 215 | * set to any other value. | ||
| 216 | */ | ||
| 217 | extern unsigned short EMMstatus; | ||
| 218 | |||
| 219 | /* | ||
| 220 | * debug & such | ||
| 221 | */ | ||
| 222 | /*unsigned null_count = 0; /* number of attempts to map null pages */ | ||
| 223 | |||
| 224 | |||
| 225 | /****************************************************************************** | ||
| 226 | EXTERNAL FUNCTIONS | ||
| 227 | ******************************************************************************/ | ||
| 228 | extern struct handle_ptr *valid_handle(); /* validate handle */ | ||
| 229 | extern unsigned far *source_addr(); /* get DS:SI far ptr */ | ||
| 230 | extern unsigned far *dest_addr(); /* get ES:DI far ptr */ | ||
| 231 | /*extern unsigned AutoUpdate(); /* update auto mode */ | ||
| 232 | extern unsigned wcopy(); | ||
| 233 | extern unsigned copyout(); | ||
| 234 | extern void reallocate(); | ||
| 235 | |||
| 236 | |||
| 237 | /****************************************************************************** | ||
| 238 | ROUTINES | ||
| 239 | ******************************************************************************/ | ||
| 240 | |||
| 241 | /* | ||
| 242 | * Avail_Pages() | ||
| 243 | * returns: number of available emm pages | ||
| 244 | * | ||
| 245 | * 06/09/88 PC added the function | ||
| 246 | */ | ||
| 247 | unsigned short | ||
| 248 | Avail_Pages() | ||
| 249 | { | ||
| 250 | return(free_count) ; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * get_pages(num,pto) | ||
| 255 | * num --- number of pages desired | ||
| 256 | * pto --- offset into emm_page array where the pages got are to be copied | ||
| 257 | * return value: | ||
| 258 | * emm_page[] index (pointer to list of allocated pages) | ||
| 259 | * NULL_PAGE means failure. | ||
| 260 | * | ||
| 261 | * 05/06/88 ISP Updated for MEMM removed handle as a parameter | ||
| 262 | */ | ||
| 263 | unsigned | ||
| 264 | get_pages(num,pto) | ||
| 265 | register unsigned num; | ||
| 266 | register unsigned pto; | ||
| 267 | { | ||
| 268 | register unsigned pg; | ||
| 269 | unsigned f_page; | ||
| 270 | |||
| 271 | if(free_count < num) | ||
| 272 | return(NULL_PAGE); /* not enough memory */ | ||
| 273 | free_count -= num; /* adjust free count */ | ||
| 274 | f_page = pg = pto; | ||
| 275 | /* emmpt_start += num; */ /* new offset of avail area */ | ||
| 276 | |||
| 277 | /* | ||
| 278 | * copy num elements from the emm_free array | ||
| 279 | * to the emm_page table array and update the | ||
| 280 | * corresponding page frame table entry (with a | ||
| 281 | * handle back pointer) | ||
| 282 | */ | ||
| 283 | wcopy(emm_free+free_top, emm_page+pg, num); | ||
| 284 | free_top += num; | ||
| 285 | return(f_page); | ||
| 286 | } | ||
| 287 | |||
| 288 | |||
| 289 | /* | ||
| 290 | * free_pages(hp) | ||
| 291 | * hp --- handle whose pages should be deallocated | ||
| 292 | * | ||
| 293 | * Free the pages associated with the handle, but don't free the handle | ||
| 294 | * | ||
| 295 | * 05/09/88 ISP Pulled out from the deallocate page routine | ||
| 296 | */ | ||
| 297 | void | ||
| 298 | free_pages(hp) | ||
| 299 | register struct handle_ptr *hp; | ||
| 300 | { | ||
| 301 | register unsigned next; | ||
| 302 | unsigned new_start; | ||
| 303 | unsigned h_size; | ||
| 304 | |||
| 305 | if (hp->page_count == 0) return ; | ||
| 306 | /* | ||
| 307 | * copy freed pages to top of free stack | ||
| 308 | */ | ||
| 309 | free_top -= hp->page_count; /* free_top points to new top */ | ||
| 310 | free_count += hp->page_count; /* bookkeeping */ | ||
| 311 | wcopy(emm_page+hp->page_index, /* addr of first of list */ | ||
| 312 | emm_free+free_top, /* addr of free space */ | ||
| 313 | hp->page_count); /* # of pages to be freed */ | ||
| 314 | |||
| 315 | /* | ||
| 316 | * now, the hard part. squeeze the newly created hole | ||
| 317 | * out of the emm_page array. this also requires updating the | ||
| 318 | * handle_table entry via the backlink in the pft386 array. | ||
| 319 | * | ||
| 320 | * do this in two phases: | ||
| 321 | * - copy the lower portion up to squeeze the hole out | ||
| 322 | * - readjust the handle table to point to the new | ||
| 323 | * location of the head element | ||
| 324 | */ | ||
| 325 | |||
| 326 | next = hp->page_index + hp->page_count; | ||
| 327 | if(next == emmpt_start ) /* any lists below? */ | ||
| 328 | { | ||
| 329 | /* no, all done */ | ||
| 330 | emmpt_start -= hp->page_count; | ||
| 331 | return; | ||
| 332 | } | ||
| 333 | |||
| 334 | new_start = emmpt_start - hp->page_count; | ||
| 335 | wcopy(emm_page+next, /* 1st of rest of list */ | ||
| 336 | emm_page+hp->page_index,/* addr of freed area */ | ||
| 337 | emmpt_start-next); /* size of block of pages */ | ||
| 338 | |||
| 339 | /* | ||
| 340 | * loop through the handle table entries, fixing up | ||
| 341 | * their page index fields | ||
| 342 | */ | ||
| 343 | h_size = hp->page_count; | ||
| 344 | hp->page_count = 0; /* not really necessary */ | ||
| 345 | for(hp=handle_table;hp < &handle_table[handle_table_size];hp++) | ||
| 346 | if((hp->page_index != NULL_PAGE) && | ||
| 347 | (hp->page_index >= next) ) | ||
| 348 | hp->page_index -= h_size; | ||
| 349 | emmpt_start = new_start; /* fix emmpt_start */ | ||
| 350 | } | ||
| 351 | |||
| 352 | /* | ||
| 353 | * get status | ||
| 354 | * no parameters | ||
| 355 | * | ||
| 356 | * return current status of EMM subsystem | ||
| 357 | * (which, due to superior design is always just fine) | ||
| 358 | * | ||
| 359 | * 05/06/88 ISP No Update needed for MEMM | ||
| 360 | */ | ||
| 361 | GetStatus() | ||
| 362 | { | ||
| 363 | setAH((unsigned char)EMMstatus); /* if we got here, we're OK */ | ||
| 364 | } | ||
| 365 | |||
| 366 | |||
| 367 | /* | ||
| 368 | * get page frame address | ||
| 369 | * no parameters | ||
| 370 | * | ||
| 371 | * return the address of where the pages get mapped | ||
| 372 | * in user space | ||
| 373 | * | ||
| 374 | * 05/06/88 ISP Updated this routine from WIN386 sources. | ||
| 375 | */ | ||
| 376 | GetPageFrameAddress() | ||
| 377 | { | ||
| 378 | extern unsigned short PF_Base; | ||
| 379 | extern unsigned short page_frame_pages; | ||
| 380 | |||
| 381 | /* | ||
| 382 | * return the 8086 style base address of | ||
| 383 | * the page frame base. | ||
| 384 | */ | ||
| 385 | if ( page_frame_pages < 4 ) { | ||
| 386 | setAH(EMM_HW_MALFUNCTION); /* GET LOST!!! */ | ||
| 387 | if ( PF_Base == 0xFFFF ) | ||
| 388 | setBX(0xB000); /* In case error is ignored */ | ||
| 389 | else | ||
| 390 | setBX(PF_Base); /* stunted page frame */ | ||
| 391 | return; | ||
| 392 | } | ||
| 393 | setBX(PF_Base); | ||
| 394 | setAH((unsigned char)EMMstatus); /* OK return */ | ||
| 395 | } | ||
| 396 | |||
| 397 | |||
| 398 | /* | ||
| 399 | * get unallocated page count | ||
| 400 | * no parameters | ||
| 401 | * | ||
| 402 | * returns: | ||
| 403 | * bx -- count of free pages | ||
| 404 | * dx -- total number of pages (free and allocated) | ||
| 405 | * | ||
| 406 | * 05/06/88 ISP No update needed for MEMM | ||
| 407 | */ | ||
| 408 | GetUnallocatedPageCount() | ||
| 409 | { | ||
| 410 | setBX(free_count); | ||
| 411 | setDX(total_pages); | ||
| 412 | setAH((unsigned char)EMMstatus); | ||
| 413 | } | ||
| 414 | |||
| 415 | /* | ||
| 416 | * allocate pages | ||
| 417 | * parameters: | ||
| 418 | * n_pages (bx) -- allocation size request | ||
| 419 | * | ||
| 420 | * allocates the requested number of pages, creates | ||
| 421 | * a handle table entry and returns a handle to the | ||
| 422 | * allocated pages. | ||
| 423 | * calls AllocateRawPages | ||
| 424 | * | ||
| 425 | * 05/09/88 ISP updated for MEMM. Only handle value returned, not handle | ||
| 426 | * value with high byte as not of handle value. call to get | ||
| 427 | * pages also updated to remove handle parameter. | ||
| 428 | */ | ||
| 429 | AllocatePages() | ||
| 430 | { | ||
| 431 | #define n_pages ((unsigned)regp->hregs.x.rbx) | ||
| 432 | if(handle_count == handle_table_size){ /* no more handles? */ | ||
| 433 | setAH(NO_MORE_HANDLES); /* nope */ | ||
| 434 | return; | ||
| 435 | } | ||
| 436 | |||
| 437 | if(n_pages == 0) { | ||
| 438 | setAH(ZERO_PAGES); | ||
| 439 | return; | ||
| 440 | } | ||
| 441 | |||
| 442 | AllocateRawPages() ; | ||
| 443 | } | ||
| 444 | #undef n_pages | ||
| 445 | |||
| 446 | /* | ||
| 447 | * allocate raw pages | ||
| 448 | * parameters: | ||
| 449 | * n_pages (bx) -- allocation size request | ||
| 450 | * | ||
| 451 | * allocates the requested number of raw pages, | ||
| 452 | * allocating 0 page is Okay | ||
| 453 | * calls allocated pages if non-zero. | ||
| 454 | * | ||
| 455 | * CREATED : 08/08/88 PLC | ||
| 456 | */ | ||
| 457 | AllocateRawPages() | ||
| 458 | { | ||
| 459 | #define n_pages ((unsigned)regp->hregs.x.rbx) | ||
| 460 | register unsigned handle; /* handle table index */ | ||
| 461 | register struct handle_ptr *hp; | ||
| 462 | |||
| 463 | if(handle_count == handle_table_size){ /* no more handles? */ | ||
| 464 | setAH(NO_MORE_HANDLES); /* nope */ | ||
| 465 | return; | ||
| 466 | } | ||
| 467 | |||
| 468 | if(n_pages > total_pages) { | ||
| 469 | setAH(NOT_ENOUGH_EXT_MEM); | ||
| 470 | return; | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | ||
| 474 | * loop through table to | ||
| 475 | * find available handle (page_index = NULL_PAGE) | ||
| 476 | */ | ||
| 477 | hp = (struct handle_ptr *)handle_table; | ||
| 478 | for(handle=0;handle<handle_table_size;handle++,hp++) | ||
| 479 | if(hp->page_index == NULL_PAGE) | ||
| 480 | break; /* found a free one */ | ||
| 481 | /* | ||
| 482 | * try and allocate pages | ||
| 483 | */ | ||
| 484 | if((hp->page_index=get_pages(n_pages,emmpt_start)) != NULL_PAGE) { | ||
| 485 | emmpt_start += n_pages; | ||
| 486 | setAH((unsigned char)EMMstatus); /* got them! */ | ||
| 487 | } | ||
| 488 | else { | ||
| 489 | setAH(NOT_ENOUGH_FREE_MEM); /* out of pages */ | ||
| 490 | return; | ||
| 491 | } | ||
| 492 | |||
| 493 | hp->page_count=n_pages; /* set count */ | ||
| 494 | handle_count++; | ||
| 495 | setDX(handle); | ||
| 496 | |||
| 497 | /* AutoUpdate(); /* update status of Auto mode */ | ||
| 498 | |||
| 499 | } | ||
| 500 | #undef n_pages | ||
| 501 | |||
| 502 | /* | ||
| 503 | * deallocate pages | ||
| 504 | * parameters: | ||
| 505 | * dx -- handle | ||
| 506 | * | ||
| 507 | * free up the pages and handle table entry associated | ||
| 508 | * with this handle | ||
| 509 | * | ||
| 510 | * 05/09/88 ISP Updated for MEMM. Pulled out free_page routine and | ||
| 511 | * added support for handle name blanking. | ||
| 512 | */ | ||
| 513 | DeallocatePages() | ||
| 514 | { | ||
| 515 | #define handle ((unsigned)regp->hregs.x.rdx) | ||
| 516 | register struct handle_ptr *hp; | ||
| 517 | struct save_map *smp; /* save map table ptr */ | ||
| 518 | long *Name ; /* points to handle name entry to clear */ | ||
| 519 | |||
| 520 | if ( handle == 0 ) { /* Special handle, don't release */ | ||
| 521 | int savbx = regp->hregs.x.rbx; | ||
| 522 | regp->hregs.x.rbx = 0; | ||
| 523 | ReallocatePages(); | ||
| 524 | regp->hregs.x.rbx = savbx; | ||
| 525 | return; | ||
| 526 | } | ||
| 527 | |||
| 528 | if((hp=valid_handle(handle)) == NULL_HANDLE) | ||
| 529 | return; /* invalid handle, error code set */ | ||
| 530 | /* | ||
| 531 | * check for save area in use for this handle | ||
| 532 | */ | ||
| 533 | if( save_map[ (handle & 0x00FF) ].s_handle != (unsigned)NULL_HANDLE ) | ||
| 534 | { | ||
| 535 | setAH(SAVED_PAGE_DEALLOC); | ||
| 536 | return; | ||
| 537 | } | ||
| 538 | |||
| 539 | free_pages(hp); /*free the pages associated with handle*/ | ||
| 540 | hp->page_index = NULL_PAGE; /*and then free the handle*/ | ||
| 541 | hp->page_count = 0; /*bookkeeping*/ | ||
| 542 | Name = (long *)Handle_Name_Table[handle & 0xFF]; | ||
| 543 | *(Name+1) = *(Name) = 0L; /* zero the eight byte name */ | ||
| 544 | handle_count--; /* one less active handle */ | ||
| 545 | |||
| 546 | /* AutoUpdate(); /* update status of Auto mode */ | ||
| 547 | setAH((unsigned char)EMMstatus); /* done */ | ||
| 548 | } | ||
| 549 | #undef handle | ||
| 550 | |||
| 551 | |||
| 552 | /* | ||
| 553 | * get emm version | ||
| 554 | * no parameters | ||
| 555 | * | ||
| 556 | * returns the version number of the emm driver | ||
| 557 | * | ||
| 558 | * 05/06/88 ISP No update needed for MEMM | ||
| 559 | */ | ||
| 560 | GetEMMVersion() | ||
| 561 | { | ||
| 562 | setAX( (EMMstatus<<8) | EMM_VERSION ); | ||
| 563 | } | ||
| 564 | |||
| 565 | /* | ||
| 566 | * Get EMM handle count | ||
| 567 | * no parameters | ||
| 568 | * | ||
| 569 | * return the number of active EMM handles | ||
| 570 | * | ||
| 571 | * 05/06/88 ISP No update needed for MEMM | ||
| 572 | */ | ||
| 573 | GetEMMHandleCount() | ||
| 574 | { | ||
| 575 | setBX(handle_count); | ||
| 576 | setAH((unsigned char)EMMstatus); | ||
| 577 | } | ||
| 578 | |||
| 579 | /* | ||
| 580 | * Get EMM handle pages | ||
| 581 | * parameters: | ||
| 582 | * dx -- handle | ||
| 583 | * | ||
| 584 | * return the number of pages allocated to specified handle in BX | ||
| 585 | * | ||
| 586 | * 05/09/88 ISP No update needed for MEMM | ||
| 587 | */ | ||
| 588 | GetEMMHandlePages() | ||
| 589 | { | ||
| 590 | #define handle ((unsigned)regp->hregs.x.rdx) | ||
| 591 | register struct handle_ptr *hp; | ||
| 592 | |||
| 593 | if((hp=valid_handle(handle))==NULL_HANDLE) /*valid handle? */ | ||
| 594 | return; /* no */ | ||
| 595 | setBX(hp->page_count); | ||
| 596 | setAH((unsigned char)EMMstatus); | ||
| 597 | } | ||
| 598 | |||
| 599 | /* | ||
| 600 | * Get All EMM Handle Pages | ||
| 601 | * parameters: | ||
| 602 | * es:di -- userptr | ||
| 603 | * | ||
| 604 | * fill out array of handle/size pairs | ||
| 605 | * | ||
| 606 | * 05/09/88 ISP Updated for MEMM (just removed upper byte of handle) | ||
| 607 | */ | ||
| 608 | GetAllEMMHandlePages() | ||
| 609 | { | ||
| 610 | unsigned far *u_ptr; | ||
| 611 | register struct handle_ptr *hp; | ||
| 612 | register unsigned h_index; | ||
| 613 | |||
| 614 | /* | ||
| 615 | * scan handle table and for each valid entry, | ||
| 616 | * copy handle and size to user array | ||
| 617 | */ | ||
| 618 | u_ptr = dest_addr(); | ||
| 619 | |||
| 620 | hp=handle_table; | ||
| 621 | for(h_index=0;h_index<handle_table_size;h_index++) | ||
| 622 | { | ||
| 623 | /* scan table for entries */ | ||
| 624 | if(hp->page_index != NULL_PAGE) /* valid entry? */ | ||
| 625 | { | ||
| 626 | *u_ptr++ = h_index; /* handle */ | ||
| 627 | *u_ptr++ = hp->page_count; /*# of pgs for handle*/ | ||
| 628 | } | ||
| 629 | hp++; /* next entry */ | ||
| 630 | } | ||
| 631 | setBX(handle_count); /* bx <-- handle count */ | ||
| 632 | setAH((unsigned char)EMMstatus); | ||
| 633 | } | ||
| 634 | |||
| 635 | /* | ||
| 636 | * Get Page Mapping Register I/O Port Array | ||
| 637 | * parameters: | ||
| 638 | es:di -- user array | ||
| 639 | * | ||
| 640 | * 05/09/88 ISP Function not supported | ||
| 641 | */ | ||
| 642 | GetPageMappingRegisterIOArray() | ||
| 643 | { | ||
| 644 | |||
| 645 | setAH(INVALID_FUNCTION); | ||
| 646 | } | ||
| 647 | |||
| 648 | /* | ||
| 649 | * Get Logical to Physical Page Translation Array | ||
| 650 | * parameters: | ||
| 651 | * es:di -- pointer to user array | ||
| 652 | * dx ----- EMM handle | ||
| 653 | * | ||
| 654 | * 05/09/88 ISP Function not supported | ||
| 655 | */ | ||
| 656 | GetLogicalToPhysicalPageTrans() | ||
| 657 | { | ||
| 658 | setAH(INVALID_FUNCTION); | ||
| 659 | } | ||
| 660 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/EMM/EMMINC.ASM b/v4.0/src/MEMM/EMM/EMMINC.ASM new file mode 100644 index 0000000..0074f54 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMINC.ASM | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | page 58,132 | ||
| 2 | ;****************************************************************************** | ||
| 3 | title EMMINC.ASM - lists all EMMLIB.LIB include files | ||
| 4 | ;****************************************************************************** | ||
| 5 | ; | ||
| 6 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 7 | ; | ||
| 8 | ; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 9 | ; EMMLIB.LIB - Expanded Memory Manager Functions Library | ||
| 10 | ; | ||
| 11 | ; Module: EMMINC.ASM - lists all EMMLIB.LIB include files | ||
| 12 | ; | ||
| 13 | ; Version: 0.02 | ||
| 14 | ; | ||
| 15 | ; Date: June 14, 1986 | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change Log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION Description | ||
| 22 | ; -------- -------- -------------------------------------------- | ||
| 23 | ; 06/25/86 original | ||
| 24 | ; 06/28/86 0.02 Name change from CEMM386 to CEMM (SBP). | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ; Functional Description: | ||
| 28 | ; This module includes all CEMM include files used by EMMLIB | ||
| 29 | ; and will provide a listing of all when assembled to produce a listing file. | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | .lfcond | ||
| 33 | .386p | ||
| 34 | |||
| 35 | ;****************************************************************************** | ||
| 36 | ; I N C L U D E S | ||
| 37 | ;****************************************************************************** | ||
| 38 | INC_LIST EQU 1 ; list include files | ||
| 39 | |||
| 40 | page | ||
| 41 | include DESC.INC | ||
| 42 | page | ||
| 43 | include EMMDEF.INC | ||
| 44 | page | ||
| 45 | ; include INSTR386.INC | ||
| 46 | ; page | ||
| 47 | include OEMDEP.INC | ||
| 48 | page | ||
| 49 | include PAGE.INC | ||
| 50 | page | ||
| 51 | include VDMSEG.INC | ||
| 52 | page | ||
| 53 | include VDMSEL.INC | ||
| 54 | |||
| 55 | end | ||
diff --git a/v4.0/src/MEMM/EMM/EMMP.ASM b/v4.0/src/MEMM/EMM/EMMP.ASM new file mode 100644 index 0000000..a60b46e --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMP.ASM | |||
| @@ -0,0 +1,2978 @@ | |||
| 1 | page 58,132 | ||
| 2 | ;****************************************************************************** | ||
| 3 | title EMMP - EMM protected mode functions | ||
| 4 | ;****************************************************************************** | ||
| 5 | ; | ||
| 6 | ; (C) Copyright MICROSOFT Corp. 1986, 1987 | ||
| 7 | ; | ||
| 8 | ; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 9 | ; EMMLIB.LIB - Expanded Memory Manager Functions Library | ||
| 10 | ; | ||
| 11 | ; Module: EMMP - WIN386 EMM functions | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date: July 7,1986 | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 07/07/86 0.04 Moved here from version 0.04 EMMSUP.ASM | ||
| 24 | ; 07/08/86 0.04 Added Get/Set Page Map (SBP). | ||
| 25 | ; 05/13/88 Change to LIM 4.0 functionality (PC) | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ; | ||
| 29 | ; Functional Description: | ||
| 30 | ; This file contains the EMM functions which require greatest efficiency. | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | .lfcond ; list false conditionals | ||
| 34 | .386p | ||
| 35 | |||
| 36 | ; include protseg.inc | ||
| 37 | include vdmseg.inc | ||
| 38 | include page.inc | ||
| 39 | ; include vdmm.inc | ||
| 40 | include vm386.inc | ||
| 41 | include vdmsel.inc | ||
| 42 | include emmdef.inc | ||
| 43 | include desc.inc | ||
| 44 | ; include vmdm.inc | ||
| 45 | ; include vpicd.inc | ||
| 46 | ; include vdmmmac.inc | ||
| 47 | |||
| 48 | ;****************************************************************************** | ||
| 49 | ; P U B L I C S | ||
| 50 | ;****************************************************************************** | ||
| 51 | _TEXT segment | ||
| 52 | public _MapHandlePage | ||
| 53 | public _SavePageMap | ||
| 54 | public _RestorePageMap | ||
| 55 | public _GetSetPageMap | ||
| 56 | public _GetSetPartial | ||
| 57 | public _MapHandleArray | ||
| 58 | public _AlterMapAndJump | ||
| 59 | public _AlterMapAndCall | ||
| 60 | ; public TS_VEMMD_MC_Ret | ||
| 61 | public _MoveExchangeMemory | ||
| 62 | public _AlternateMapRegisterSet | ||
| 63 | ; public VEMMD_Set_Map_Region | ||
| 64 | ; public VEMMD_Unset_Map_Region | ||
| 65 | ; public _VMpte_to_EMMpte | ||
| 66 | ; public _Remap_EMM | ||
| 67 | public _Get_Key_Val | ||
| 68 | _TEXT ends | ||
| 69 | |||
| 70 | page | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; E X T E R N A L R E F E R E N C E S | ||
| 73 | ;****************************************************************************** | ||
| 74 | |||
| 75 | _TEXT segment | ||
| 76 | |||
| 77 | extrn _source_addr:near | ||
| 78 | extrn _dest_addr:near | ||
| 79 | |||
| 80 | extrn SetDescInfoResident:near | ||
| 81 | extrn SegOffTo24Resident:near | ||
| 82 | |||
| 83 | extrn ErrHndlr:near | ||
| 84 | |||
| 85 | _TEXT ends | ||
| 86 | |||
| 87 | _DATA SEGMENT | ||
| 88 | |||
| 89 | ;extrn _regp:dword ; pointer to entry stack frame | ||
| 90 | ;extrn VEMMD_pt:dword | ||
| 91 | ;extrn Cur_VM_Handle:dword | ||
| 92 | ;extrn Cur_VMID:dword | ||
| 93 | ;extrn _VM_List:dword | ||
| 94 | ;extrn _MaxEMMSize:dword | ||
| 95 | ;extrn _VEMMD_PgFrame:word | ||
| 96 | ;extrn _VEMMD_Last_Offset:word | ||
| 97 | extrn PF_Base:word | ||
| 98 | extrn _OSEnabled:dword | ||
| 99 | ;extrn NullAvailPTE:dword | ||
| 100 | ;extrn NullUnavailPTE:dword | ||
| 101 | |||
| 102 | extrn _total_pages:word ; total # of EMM pages in system | ||
| 103 | |||
| 104 | ; | ||
| 105 | ; table of offsets into in to the first page table | ||
| 106 | ; for user logical emm page map | ||
| 107 | ; | ||
| 108 | extrn _page_frame_base:dword | ||
| 109 | |||
| 110 | extrn _pft386:word | ||
| 111 | |||
| 112 | extrn _mappable_pages:word ; table of mappable pages | ||
| 113 | extrn _mappable_page_count:word ; how many in the table | ||
| 114 | extrn _page_frame_pages:word ; how many in the page frame | ||
| 115 | extrn _physical_page_count:word ; number of physical pages | ||
| 116 | extrn _VM1_EMM_Pages:word ; pages not in the page frame | ||
| 117 | ;extrn _VM1_EMM_Offset:word ; offset of these in a context | ||
| 118 | extrn _cntxt_pages:byte ; number of pages in a context | ||
| 119 | extrn _cntxt_bytes:byte ; number of bytes in a context | ||
| 120 | |||
| 121 | |||
| 122 | ; | ||
| 123 | ; table of indexes into the above - maps segment to physical page | ||
| 124 | ; | ||
| 125 | extrn EMM_MPindex:byte | ||
| 126 | |||
| 127 | ; | ||
| 128 | ; ptr to table of emm page # for each handle's logical pages. | ||
| 129 | ; | ||
| 130 | extrn _emm_page:word | ||
| 131 | |||
| 132 | ; | ||
| 133 | ; handle data structure | ||
| 134 | ; | ||
| 135 | extrn _handle_table:word | ||
| 136 | extrn _handle_table_size:word | ||
| 137 | |||
| 138 | ; | ||
| 139 | ; save area for handles | ||
| 140 | ; | ||
| 141 | extrn _save_map:byte | ||
| 142 | |||
| 143 | ; | ||
| 144 | ; Save area and misc variables for 4.0 function 27 | ||
| 145 | ; | ||
| 146 | extrn EMM_savES:word | ||
| 147 | extrn EMM_savDI:word | ||
| 148 | |||
| 149 | extrn CurRegSetn:byte | ||
| 150 | extrn FRS_free:byte | ||
| 151 | extrn CurRegSet:dword | ||
| 152 | extrn FRS_array:word | ||
| 153 | |||
| 154 | extrn _regp:word | ||
| 155 | _DATA ENDS | ||
| 156 | |||
| 157 | page | ||
| 158 | ;****************************************************************************** | ||
| 159 | ; C O D E | ||
| 160 | ;****************************************************************************** | ||
| 161 | _TEXT SEGMENT | ||
| 162 | assume cs:_TEXT, ds:DGROUP, ss:DGROUP | ||
| 163 | |||
| 164 | page | ||
| 165 | ;*********************************************** | ||
| 166 | ; | ||
| 167 | ; normalize | ||
| 168 | ; | ||
| 169 | ; ENTRY: Sel,Off - Selector:offset to be normalize | ||
| 170 | ; protected mode only | ||
| 171 | ; | ||
| 172 | ; EXIT: Sel:Off normalized | ||
| 173 | ; | ||
| 174 | ; USES: Sel,Off | ||
| 175 | ; NOTE: Sel and Off should not be BX,DX,AX | ||
| 176 | ; | ||
| 177 | ;*********************************************** | ||
| 178 | normalize MACRO Sel,Off | ||
| 179 | |||
| 180 | push dx | ||
| 181 | push ax | ||
| 182 | push bx | ||
| 183 | push es | ||
| 184 | |||
| 185 | push Sel ; save for later reload | ||
| 186 | mov bx, Sel ; get Selector into BX | ||
| 187 | |||
| 188 | push GDTD_GSEL ; ES -> GDT | ||
| 189 | pop es | ||
| 190 | |||
| 191 | and bl,SEL_LOW_MASK ; mask off mode bits | ||
| 192 | mov dx,es:[bx+2] ; AL:DX <-- base address | ||
| 193 | mov al,es:[bx+4] | ||
| 194 | add dx,Off ; adjust base address | ||
| 195 | adc al,0 | ||
| 196 | mov es:[bx+2],dx ; store it back | ||
| 197 | mov es:[bx+4],al | ||
| 198 | xor Off, Off ; new Offset | ||
| 199 | |||
| 200 | pop Sel ; reload Selector (flush cache) | ||
| 201 | |||
| 202 | pop es | ||
| 203 | pop bx | ||
| 204 | pop ax | ||
| 205 | pop dx | ||
| 206 | |||
| 207 | ENDM | ||
| 208 | |||
| 209 | ;*********************************************** | ||
| 210 | ; | ||
| 211 | ; get_space_from_stack | ||
| 212 | ; | ||
| 213 | ; ENTRY: Len - amount of space requested | ||
| 214 | ; | ||
| 215 | ; EXIT: Len space allocated on ES:DI (client's stack) | ||
| 216 | ; ES:DI - points to First element on top of stack | ||
| 217 | ; | ||
| 218 | ; USES: DI | ||
| 219 | ; | ||
| 220 | ;*********************************************** | ||
| 221 | Get_space_from_stack MACRO Len | ||
| 222 | |||
| 223 | sub di, Len | ||
| 224 | ENDM | ||
| 225 | |||
| 226 | ;*********************************************** | ||
| 227 | ; | ||
| 228 | ; release_space_to_stack | ||
| 229 | ; | ||
| 230 | ; ENTRY: Len - amount of space to be release | ||
| 231 | ; | ||
| 232 | ; EXIT: Len space released from client's stack (DS:SI) | ||
| 233 | ; | ||
| 234 | ; USES: SI | ||
| 235 | ; | ||
| 236 | ;*********************************************** | ||
| 237 | release_space_to_stack MACRO Len | ||
| 238 | |||
| 239 | add si, Len | ||
| 240 | ENDM | ||
| 241 | |||
| 242 | ;*********************************************** | ||
| 243 | ; | ||
| 244 | ; Set_EMM_GDT - set GDT entry of selector with some fix infos | ||
| 245 | ; like access and limit | ||
| 246 | ; | ||
| 247 | ; ENTRY: Handle - selector of GDT to modify | ||
| 248 | ; | ||
| 249 | ; EXIT: GDT entry set | ||
| 250 | ; bx - selector | ||
| 251 | ; | ||
| 252 | ; USES: ax,bx,cx,dx,es | ||
| 253 | ; | ||
| 254 | ;*********************************************** | ||
| 255 | Set_EMM_GDT MACRO handle | ||
| 256 | |||
| 257 | mov bx, handle ; GDT selector | ||
| 258 | call SegOffTo24Resident ; AL:DX <-- 24 bit base address | ||
| 259 | mov cx, 0ffffh ; Limit | ||
| 260 | mov ah, D_DATA0 ; Acess right | ||
| 261 | push GDTD_GSEL | ||
| 262 | pop es ; ES:0 <-- GDT | ||
| 263 | call SetDescInfoResident ; set GDT entry | ||
| 264 | ENDM | ||
| 265 | |||
| 266 | ;*********************************************** | ||
| 267 | ; | ||
| 268 | ; Set_Byte_Gran - set granularity of GDT entry to byte | ||
| 269 | ; | ||
| 270 | ; ENTRY: Handle - selector of GDT to modify | ||
| 271 | ; | ||
| 272 | ; EXIT: Granularity bit clear in GDT | ||
| 273 | ; bx - Selector | ||
| 274 | ; | ||
| 275 | ; USES: bx,es | ||
| 276 | ; | ||
| 277 | ;*********************************************** | ||
| 278 | Set_Byte_Gran MACRO handle | ||
| 279 | |||
| 280 | mov bx, handle ; GDT selector | ||
| 281 | push GDTD_GSEL | ||
| 282 | pop es ; ES:0 <-- GDT | ||
| 283 | and byte ptr es:[bx+6],NOT R_GRAN ; clear gran bit | ||
| 284 | ENDM | ||
| 285 | |||
| 286 | ;*********************************************** | ||
| 287 | ; | ||
| 288 | ; Set_Page_Gran - set granularity of GDT entry to page | ||
| 289 | ; | ||
| 290 | ; ENTRY: Handle - selector of GDT to modify | ||
| 291 | ; | ||
| 292 | ; EXIT: Granularity bit set in GDT | ||
| 293 | ; bx - Selector | ||
| 294 | ; | ||
| 295 | ; USES: bx,es | ||
| 296 | ; | ||
| 297 | ;*********************************************** | ||
| 298 | Set_Page_Gran MACRO handle | ||
| 299 | |||
| 300 | mov bx, handle ; GDT selector | ||
| 301 | push GDTD_GSEL | ||
| 302 | pop es ; ES:0 <-- GDT | ||
| 303 | or byte ptr es:[bx+6], R_GRAN ; set gran bit | ||
| 304 | ENDM | ||
| 305 | |||
| 306 | ;*********************************************** | ||
| 307 | ; | ||
| 308 | ; Get_FRS_window - get pointer to Fast Register Set window | ||
| 309 | ; | ||
| 310 | ; ENTRY: Reg - points to an FRS_struc | ||
| 311 | ; | ||
| 312 | ; EXIT: Reg - points to FRS_window entry in the structure | ||
| 313 | ; | ||
| 314 | ; USES: Reg | ||
| 315 | ; | ||
| 316 | ;*********************************************** | ||
| 317 | Get_FRS_window MACRO Reg | ||
| 318 | |||
| 319 | mov Reg, word ptr [CurRegSet] ; just offset (assume dgroup) | ||
| 320 | add Reg, FRS_window ; points to FRS window entries | ||
| 321 | ENDM | ||
| 322 | |||
| 323 | page | ||
| 324 | ;********************************************************************** | ||
| 325 | ; | ||
| 326 | ; map_EMM_page - set page table entries for a page frame | ||
| 327 | ; | ||
| 328 | ; ENTRY: AX - physical page number to be mapped | ||
| 329 | ; BX - EMM page number to map | ||
| 330 | ; EXIT: page table set up for EMM page # in this page frame | ||
| 331 | ; DESTROY:EAX,BX | ||
| 332 | ; | ||
| 333 | ;*********************************************** | ||
| 334 | map_EMM_page proc near | ||
| 335 | cmp ax,[_physical_page_count] ;Q: valid physical page# ? | ||
| 336 | jae short mEp_inv_page ; N: invalid page number | ||
| 337 | ; Y: continue with it | ||
| 338 | cmp bx,[_total_pages] ;Q: valid EMM page# ? | ||
| 339 | jae short mEp_inv_page ; N: invalid page number | ||
| 340 | ; Y: continue with it | ||
| 341 | push es ; preserve es | ||
| 342 | push cx ; preserve cx | ||
| 343 | push di ; preserve di | ||
| 344 | push ax ; save ax (phys page#) | ||
| 345 | |||
| 346 | ; | ||
| 347 | ; construct pointer to physical address of the first | ||
| 348 | ; 386 page and move it into eax | ||
| 349 | ; | ||
| 350 | mov cx,bx ; emm page# in cx to save in FRS later | ||
| 351 | shl bx,2 ; bx <-- pft index * 4 | ||
| 352 | |||
| 353 | ; | ||
| 354 | ; continue calulation of pte | ||
| 355 | ; | ||
| 356 | add bx,[_pft386] ; BX = points into _pft386 | ||
| 357 | mov eax,[bx] ; EAX = physical address of EMM page # | ||
| 358 | and ax,0F000H ; clear the low 12 bits | ||
| 359 | or ax,P_AVAIL ; page ctl bits <-- user,present,write | ||
| 360 | |||
| 361 | pop bx ; bx <-- physical page index | ||
| 362 | |||
| 363 | ; | ||
| 364 | ; save mapping (offset into _pft386 struct) into | ||
| 365 | ; current FRS's physical page entry | ||
| 366 | ; | ||
| 367 | |||
| 368 | Get_FRS_Window DI ; di <-- address of current FRS | ||
| 369 | add di,bx ; di <-- address of physical page | ||
| 370 | add di,bx ; entry in FRS | ||
| 371 | mov [di],cx ; save mapping (emm page#) into FRS | ||
| 372 | ; | ||
| 373 | ; construct pointer to physical address of | ||
| 374 | ; page frame | ||
| 375 | ; | ||
| 376 | |||
| 377 | shl bx,2 ; bx <-- index * 4 | ||
| 378 | add bx,offset DGROUP:_page_frame_base ; bx = offset for entry in _page_frame_base | ||
| 379 | les di,[bx] ; es:di <-- page frame address | ||
| 380 | |||
| 381 | ; | ||
| 382 | ; now, | ||
| 383 | ; es:di points to the 1st entry in the page table | ||
| 384 | ; for this page frame | ||
| 385 | ; eax contains the new value of the PTE | ||
| 386 | ; set up 4 entries | ||
| 387 | ; | ||
| 388 | |||
| 389 | pushf ; preserve direction flag | ||
| 390 | cld ; forward | ||
| 391 | |||
| 392 | stosd ; store 1st page table entry | ||
| 393 | add eax,P_SIZE ; eax <-- next address | ||
| 394 | |||
| 395 | stosd ; store 2nd page table entry | ||
| 396 | add eax,P_SIZE ; eax <-- next address | ||
| 397 | |||
| 398 | stosd ; store 3rd page table entry | ||
| 399 | add eax,P_SIZE ; eax <-- next address | ||
| 400 | |||
| 401 | stosd ; store 4th page table entry | ||
| 402 | |||
| 403 | popf ; restore direction flag | ||
| 404 | pop di ; get DI back | ||
| 405 | pop cx ; get CX back | ||
| 406 | pop es ; get ES back | ||
| 407 | clc | ||
| 408 | ret | ||
| 409 | |||
| 410 | mEp_inv_page: | ||
| 411 | stc | ||
| 412 | ret | ||
| 413 | |||
| 414 | map_EMM_page endp | ||
| 415 | |||
| 416 | page | ||
| 417 | ;********************************************************************** | ||
| 418 | ; | ||
| 419 | ; unmap_page - unmap a physical page | ||
| 420 | ; | ||
| 421 | ; ENTRY: AX - physical page number to be unmapped | ||
| 422 | ; DESTROY:EAX | ||
| 423 | ; | ||
| 424 | ;********************************************************************** | ||
| 425 | unmap_page proc near | ||
| 426 | ; | ||
| 427 | ; find FRS entry for the physical page and | ||
| 428 | ; update it as unmapped | ||
| 429 | ; | ||
| 430 | push es | ||
| 431 | push di | ||
| 432 | push bx | ||
| 433 | push cx | ||
| 434 | Get_FRS_Window DI ; di <-- address of current FRS | ||
| 435 | add di, ax ; di <-- address of physical page | ||
| 436 | add di, ax ; entry in FRS | ||
| 437 | mov [di], NULL_PAGE ; unmap the entry | ||
| 438 | |||
| 439 | ; | ||
| 440 | ; find out the segment of the physical page | ||
| 441 | ; | ||
| 442 | mov cx, [_physical_page_count] | ||
| 443 | mov di, offset DGROUP:_mappable_pages | ||
| 444 | unmap_page_loop: | ||
| 445 | cmp ax, [di].mappable_pg | ||
| 446 | je unmap_page_found | ||
| 447 | add di, size Mappable_Page | ||
| 448 | loop unmap_page_loop | ||
| 449 | |||
| 450 | jmp short unmap_page_exit ; non-found : just return | ||
| 451 | |||
| 452 | unmap_page_found: | ||
| 453 | mov bx, [di].mappable_seg ; get segment into bx first | ||
| 454 | |||
| 455 | ; | ||
| 456 | ; construct pointer to physical address of | ||
| 457 | ; page frame | ||
| 458 | ; | ||
| 459 | xchg ax,bx | ||
| 460 | shl bx,2 ; bx <-- index * 4 | ||
| 461 | add bx,offset DGROUP:_page_frame_base ; bx <-- points to PTE address of phys page# | ||
| 462 | les di,[bx] ; es:di <-- points to PTE of page frame | ||
| 463 | xchg ax,bx | ||
| 464 | |||
| 465 | ; | ||
| 466 | ; construct PTE | ||
| 467 | ; | ||
| 468 | movzx eax, bx ; EAX <-- segment of physical page | ||
| 469 | shl eax, 4 | ||
| 470 | and ax,0F000H ; clear the low 12 bits | ||
| 471 | or ax,P_AVAIL ; page ctl bits <-- user,present,write | ||
| 472 | |||
| 473 | cmp eax, 0A0000h ; Q:above 640K ? | ||
| 474 | jge unmap_page_ok ; Y: go ahead, unmap it | ||
| 475 | mov eax, 0 ; N: shouldn't unmap below 640K - make page NotPresent | ||
| 476 | |||
| 477 | unmap_page_ok: | ||
| 478 | pushf | ||
| 479 | cld | ||
| 480 | stosd ; unmap pte of page frame | ||
| 481 | add eax,P_SIZE | ||
| 482 | stosd | ||
| 483 | add eax,P_SIZE | ||
| 484 | stosd | ||
| 485 | add eax,P_SIZE | ||
| 486 | stosd | ||
| 487 | popf | ||
| 488 | |||
| 489 | unmap_page_exit: | ||
| 490 | pop cx | ||
| 491 | pop bx | ||
| 492 | pop di | ||
| 493 | pop es | ||
| 494 | ret | ||
| 495 | unmap_page endp | ||
| 496 | |||
| 497 | page | ||
| 498 | ;********************************************************************** | ||
| 499 | ; | ||
| 500 | ; map_page - map a logical page to a phyical page | ||
| 501 | ; | ||
| 502 | ; ENTRY: AX - physical page number to be mapped | ||
| 503 | ; BX - logical page number to map | ||
| 504 | ; DX - handle pointer (do not destroy) | ||
| 505 | ; DESTROY:EAX,BX | ||
| 506 | ; | ||
| 507 | ;********************************************************************** | ||
| 508 | map_page proc near | ||
| 509 | cmp ax,[_physical_page_count] ;Q: valid physical page# ? | ||
| 510 | jae short mp_inv_phy ; N: invalid page number | ||
| 511 | ; Y: continue with it | ||
| 512 | cmp bx,0FFFFh ;Q: unmap ? | ||
| 513 | je short mp_unmap_page ; Y: go ahead | ||
| 514 | |||
| 515 | xchg bx, dx | ||
| 516 | cmp dx,[bx.ht_count] ;Q: valid logical page# ? | ||
| 517 | xchg bx, dx | ||
| 518 | jae short mp_inv_log ; N: invalid page number | ||
| 519 | ; Y: continue with it | ||
| 520 | |||
| 521 | xchg bx, dx | ||
| 522 | add dx,[bx.ht_index] ; dx <-- index into _emm_page | ||
| 523 | xchg bx, dx | ||
| 524 | shl bx,1 ; bx <-- index * 2 | ||
| 525 | add bx,[_emm_page] | ||
| 526 | mov bx,[bx] ; bx <-- emm page# | ||
| 527 | call map_EMM_page | ||
| 528 | jc short mp_inv_emm_page ; emm page range error | ||
| 529 | ret | ||
| 530 | |||
| 531 | mp_unmap_page: | ||
| 532 | call unmap_page | ||
| 533 | clc | ||
| 534 | ret | ||
| 535 | |||
| 536 | mp_inv_emm_page: | ||
| 537 | mov byte ptr [bp.rAX+1],SOURCE_CORRUPTED | ||
| 538 | stc | ||
| 539 | ret | ||
| 540 | |||
| 541 | mp_inv_phy: | ||
| 542 | mov byte ptr [bp.rAX+1],PHYS_PAGE_RANGE | ||
| 543 | stc | ||
| 544 | ret | ||
| 545 | |||
| 546 | mp_inv_log: | ||
| 547 | mov byte ptr [bp.rAX+1],LOG_PAGE_RANGE | ||
| 548 | stc | ||
| 549 | ret | ||
| 550 | map_page endp | ||
| 551 | |||
| 552 | |||
| 553 | page | ||
| 554 | ;*********************************************** | ||
| 555 | ; | ||
| 556 | ; _MapHandlePage - map a handle's page | ||
| 557 | ; | ||
| 558 | ; This routine maps 4 386 pages into the address | ||
| 559 | ; space. | ||
| 560 | ; | ||
| 561 | ; ENTRY: PROTECTED MODE ONLY | ||
| 562 | ; AH = 44h = map handle page function # | ||
| 563 | ; AL = window # (physical page #) | ||
| 564 | ; BX = logical page # | ||
| 565 | ; DX = EMM handle | ||
| 566 | ; REGS on STACK: SI = not used by this function | ||
| 567 | ; SS:[EBP] -> regp stack frame | ||
| 568 | ; DS = DGROUP | ||
| 569 | ; | ||
| 570 | ; EXIT: page table entries set up | ||
| 571 | ; AH = status of this function | ||
| 572 | ; = EMM_HW_MALFUNCTION if entry in real/virtual mode. | ||
| 573 | ; | ||
| 574 | ; USED: EAX, EBX, EDX, EDI | ||
| 575 | ; | ||
| 576 | ;*********************************************** | ||
| 577 | |||
| 578 | Dword_Align _TEXT | ||
| 579 | _MapHandlePage proc near | ||
| 580 | |||
| 581 | Validate_Handle <short mhp_inv_handle> | ||
| 582 | |||
| 583 | mov byte ptr [bp.rAX+1],OK ; Assume success! | ||
| 584 | movzx eax, al ; Physical page | ||
| 585 | movzx ebx, bx ; Logical page | ||
| 586 | |||
| 587 | push eax | ||
| 588 | mov eax, cr3 | ||
| 589 | mov cr3, eax ; Flush old mapping now | ||
| 590 | pop eax | ||
| 591 | |||
| 592 | jmp map_page ; Common page mapping code | ||
| 593 | |||
| 594 | mhp_inv_handle: | ||
| 595 | mov byte ptr [bp.rAX+1], INVALID_HANDLE | ||
| 596 | ret | ||
| 597 | |||
| 598 | _MapHandlePage endp | ||
| 599 | |||
| 600 | page | ||
| 601 | ;*********************************************** | ||
| 602 | ; | ||
| 603 | ; _SavePageMap - save current page mapping | ||
| 604 | ; | ||
| 605 | ; This routine save the current page mapping context for a handle. | ||
| 606 | ; | ||
| 607 | ; ENTRY: PROTECTED MODE | ||
| 608 | ; AH = 07h = save page map function # | ||
| 609 | ; DX = EMM handle | ||
| 610 | ; REGS on STACK: SI = not used by this function | ||
| 611 | ; SS:[BP] -> regp stack frame | ||
| 612 | ; DS = DGROUP | ||
| 613 | ; | ||
| 614 | ; EXIT: current state saved | ||
| 615 | ; AH = status of this function | ||
| 616 | ; | ||
| 617 | ; USED: AX,BX,CX,DX,SI,DI | ||
| 618 | ; | ||
| 619 | ;*********************************************** | ||
| 620 | |||
| 621 | Dword_Align _TEXT | ||
| 622 | _SavePageMap proc near | ||
| 623 | cmp [_page_frame_pages], 4 | ||
| 624 | jb short srpm_nopf ; no page frame | ||
| 625 | |||
| 626 | mov ax, dx ; Save for later | ||
| 627 | Validate_Handle <short srpm_inv_handle> | ||
| 628 | ; check state of handle's page area | ||
| 629 | imul bx,ax,SIZE SaveMap_struc ; BX = offset within Save Area for | ||
| 630 | ; this handle's save area | ||
| 631 | lea di,_save_map[bx] ; DS:DI points to handle's save area | ||
| 632 | cmp [di].s_handle,NULL_HANDLE | ||
| 633 | ;Q: save area in use ? | ||
| 634 | jne short spm_prev_saved ; Y: return error | ||
| 635 | ; N: use it now | ||
| 636 | cld | ||
| 637 | push ds | ||
| 638 | pop es | ||
| 639 | stosw ; store handle # in s_handle | ||
| 640 | Get_FRS_window SI ; Current FRS page mappings | ||
| 641 | movsd ; move to save area | ||
| 642 | movsd ; Lim 3.2 has only 4 page frames | ||
| 643 | |||
| 644 | mov byte ptr [bp.rAX+1],OK ; ok return | ||
| 645 | ret | ||
| 646 | |||
| 647 | spm_prev_saved: | ||
| 648 | mov byte ptr [bp.rAX+1],MAP_PREV_SAVED | ||
| 649 | ret | ||
| 650 | |||
| 651 | srpm_inv_handle: ; Shared error returns | ||
| 652 | mov byte ptr [bp.rAX+1],INVALID_HANDLE | ||
| 653 | ret | ||
| 654 | |||
| 655 | srpm_nopf: | ||
| 656 | mov byte ptr [bp.rAX+1], EMM_HW_MALFUNCTION ; No page frame!!! | ||
| 657 | ret | ||
| 658 | |||
| 659 | _SavePageMap endp | ||
| 660 | |||
| 661 | page | ||
| 662 | ;*********************************************** | ||
| 663 | ; | ||
| 664 | ; _RestorePageMap - restore handle's saved page mapping | ||
| 665 | ; | ||
| 666 | ; This routine restores the current page mapping context | ||
| 667 | ; from a handle's save area. | ||
| 668 | ; | ||
| 669 | ; ENTRY: PROTECTED MODE ONLY | ||
| 670 | ; AH = 08h = restore page map function # | ||
| 671 | ; DX = EMM handle | ||
| 672 | ; REGS on STACK: SI = not used by this function | ||
| 673 | ; SS:[BP] -> regp stack frame | ||
| 674 | ; DS = DGROUP | ||
| 675 | ; | ||
| 676 | ; EXIT: current state restored | ||
| 677 | ; AH = status of this function | ||
| 678 | ; | ||
| 679 | ; USED: AX,BX,CX,DX,SI,DI | ||
| 680 | ; | ||
| 681 | ;*********************************************** | ||
| 682 | |||
| 683 | Dword_Align _TEXT | ||
| 684 | _RestorePageMap proc near | ||
| 685 | cmp [_page_frame_pages], 4 | ||
| 686 | jb short srpm_nopf ; no page frame | ||
| 687 | |||
| 688 | mov ax, dx ; Save for later | ||
| 689 | Validate_Handle srpm_inv_handle | ||
| 690 | ; check state of handle's page area | ||
| 691 | imul bx,ax,SIZE SaveMap_struc ; BX = offset within Save Area for | ||
| 692 | ; this handle's save area | ||
| 693 | lea si,_save_map[bx] ; DS:SI points to handle's save area | ||
| 694 | cmp [si].s_handle,NULL_HANDLE | ||
| 695 | ;Q: save area in use ? | ||
| 696 | je short rpm_no_map_saved ; N: return error | ||
| 697 | ; Y: restore it | ||
| 698 | |||
| 699 | mov byte ptr [bp.rAX+1],OK ; Assume success | ||
| 700 | mov [si].s_handle,NULL_HANDLE ; null handle's save area | ||
| 701 | |||
| 702 | lea si,[si].s_map ; SI -> handle's save area | ||
| 703 | Get_FRS_window DI ; Get pointer to current window | ||
| 704 | push ds | ||
| 705 | pop es ; ES <-- DGROUP | ||
| 706 | cld | ||
| 707 | movsd ; restore 4 words | ||
| 708 | movsd ; Lim 3.2 has only 4 page frames | ||
| 709 | jmp _set_windows ; Restore mapping | ||
| 710 | |||
| 711 | rpm_no_map_saved: | ||
| 712 | mov byte ptr [bp.rAX+1],NO_MAP_SAVED | ||
| 713 | ret | ||
| 714 | |||
| 715 | _RestorePageMap endp | ||
| 716 | |||
| 717 | page | ||
| 718 | ;*********************************************** | ||
| 719 | ; | ||
| 720 | ; _GetSetPageMap - get/set page map to/from external save area | ||
| 721 | ; | ||
| 722 | ; This routine stores the current page mapping context (Intel | ||
| 723 | ; compatible form for now) to an external save area and/or restores | ||
| 724 | ; the current page mapping context from an external save area. | ||
| 725 | ; | ||
| 726 | ; ENTRY: PROTECTED MODE ONLY | ||
| 727 | ; AH = 4Eh = Get/Set page map function number | ||
| 728 | ; or AH = 5Ch = Get/Set large page map function number | ||
| 729 | ; AL = SUBFUNCTION CODE | ||
| 730 | ; AL = 0 => Get page map | ||
| 731 | ; AL = 1 => Set page map | ||
| 732 | ; AL = 2 => Get and Set page map | ||
| 733 | ; AL = 3 => return size of page map | ||
| 734 | ; REGS on STACK: SI = not used by this function | ||
| 735 | ; SS:[BP] -> regp stack frame | ||
| 736 | ; DS = DGROUP | ||
| 737 | ; | ||
| 738 | ; EXIT: current state saved / restored | ||
| 739 | ; AH = status of this function | ||
| 740 | ; | ||
| 741 | ; USED: BX,CX,DX,SI,DI | ||
| 742 | ; | ||
| 743 | ;*********************************************** | ||
| 744 | Dword_Align _TEXT | ||
| 745 | _GetSetPageMap proc near | ||
| 746 | |||
| 747 | cmp al,GSPM_GET ;Q: get page map subfunction ? | ||
| 748 | je short _get_map ; Y: get it | ||
| 749 | |||
| 750 | cmp al,GSPM_SET ;Q: set page map subfunction ? | ||
| 751 | je _set_map ; Y: set it | ||
| 752 | |||
| 753 | cmp al,GSPM_GETSET ;Q: get & set page map subfunction ? | ||
| 754 | jne short gspm_chk_size ; N: check for size function | ||
| 755 | call _get_map ; Y: get current map first | ||
| 756 | jmp short _set_map ; set new one | ||
| 757 | |||
| 758 | gspm_chk_size: | ||
| 759 | cmp al, GSPM_SIZE ;Q: return map size subfunction ? | ||
| 760 | jne short gspm_inv_subfun ; N: return invalid subfunction | ||
| 761 | |||
| 762 | mov al, [_cntxt_bytes] ; size of map | ||
| 763 | mov ah, OK ; ok return | ||
| 764 | mov word ptr [bp.rAX], ax | ||
| 765 | ret | ||
| 766 | |||
| 767 | gspm_inv_subfun: | ||
| 768 | mov byte ptr [bp.rAX+1],INVALID_SUBFUNCTION | ||
| 769 | ret | ||
| 770 | |||
| 771 | gspm_inv_fun: | ||
| 772 | mov byte ptr [bp.rAX+1],INVALID_FUNCTION | ||
| 773 | ret | ||
| 774 | |||
| 775 | _GetSetPageMap endp | ||
| 776 | |||
| 777 | page | ||
| 778 | ;*********************************************** | ||
| 779 | ; | ||
| 780 | ; _get_map - save current mapping register state to external area | ||
| 781 | ; | ||
| 782 | ; ENTRY: on stack | ||
| 783 | ; clients ES:DI -> client's buffer for state | ||
| 784 | ; SS:[BP] -> regp stack frame | ||
| 785 | ; DS = DGROUP | ||
| 786 | ; | ||
| 787 | ; EXIT: state stored in client's buffer | ||
| 788 | ; return code set on stack | ||
| 789 | ; | ||
| 790 | ; USED: AX,BX,CX,DX,SI,DI,ES | ||
| 791 | ; | ||
| 792 | ; DESCRIPTION: This function saves the current mapping | ||
| 793 | ; into the save area specified. | ||
| 794 | ; | ||
| 795 | ;*********************************************** | ||
| 796 | Dword_Align _TEXT | ||
| 797 | _get_map proc | ||
| 798 | |||
| 799 | cld | ||
| 800 | call _dest_addr ; DX:AX ptr for client's buff | ||
| 801 | mov es,dx | ||
| 802 | mov di,ax ; ES:DI pts to clients buffer | ||
| 803 | |||
| 804 | Get_FRS_window SI ; Get pointer to current window | ||
| 805 | movzx ecx, [_cntxt_pages] | ||
| 806 | mov ax, cx | ||
| 807 | stosw ; save # pages | ||
| 808 | shr cx, 1 ; now dwords | ||
| 809 | rep movsd ; mov bytes to current map area | ||
| 810 | mov byte ptr [bp.rAX+1],OK ; ok return | ||
| 811 | ret | ||
| 812 | |||
| 813 | _get_map endp | ||
| 814 | |||
| 815 | page | ||
| 816 | ;*********************************************** | ||
| 817 | ; | ||
| 818 | ; _set_map - restore mapping register state | ||
| 819 | ; | ||
| 820 | ; ENTRY: on stack | ||
| 821 | ; clients DS:SI -> client's buffer containing state to restore | ||
| 822 | ; SS:[BP] -> regp stack frame | ||
| 823 | ; DS = DGROUP | ||
| 824 | ; | ||
| 825 | ; EXIT: state restored from client's buffer | ||
| 826 | ; return code set on stack | ||
| 827 | ; CLC => no errors | ||
| 828 | ; STC => error occurred | ||
| 829 | ; | ||
| 830 | ; USED: EAX,BX,CX,DX,SI,DI,ES | ||
| 831 | ; | ||
| 832 | ; | ||
| 833 | ; DESCRIPTION: This function restores the mapping from the state info input. | ||
| 834 | ; The mapping is assumed to be the same as in the | ||
| 835 | ; save_current_map function. The count in the saved | ||
| 836 | ; state is verified. | ||
| 837 | ; | ||
| 838 | ;*********************************************** | ||
| 839 | Dword_Align _TEXT | ||
| 840 | _set_map proc near | ||
| 841 | |||
| 842 | mov byte ptr [bp.rAX+1],OK ; Assume success | ||
| 843 | Get_FRS_window DI ; Get pointer to current window | ||
| 844 | ; before DS gets trashed | ||
| 845 | push ds | ||
| 846 | pop es ; use ES to address data | ||
| 847 | push dx | ||
| 848 | mov si, ax | ||
| 849 | call _source_addr ; DX:AX ptr for client's buff | ||
| 850 | mov ds,dx | ||
| 851 | xchg si,ax ; DS:SI pts to clients buffer | ||
| 852 | pop dx | ||
| 853 | |||
| 854 | cld | ||
| 855 | movzx ecx, es:[_cntxt_pages] ; number of words in mapping | ||
| 856 | lodsw ; saved size | ||
| 857 | cmp ax, cx ; should be this | ||
| 858 | jne short sm_inv_source ; Wrong, saved data corrupted | ||
| 859 | shr cx, 1 ; now a word count | ||
| 860 | rep movsd | ||
| 861 | push es | ||
| 862 | pop ds ; DS <-- DGROUP | ||
| 863 | jmp _set_windows ; make it effective | ||
| 864 | |||
| 865 | sm_inv_source: | ||
| 866 | mov byte ptr [bp.rAX+1], SOURCE_CORRUPTED | ||
| 867 | ret | ||
| 868 | |||
| 869 | sm_exit: | ||
| 870 | ret | ||
| 871 | |||
| 872 | _set_map endp | ||
| 873 | |||
| 874 | page | ||
| 875 | ;*********************************************** | ||
| 876 | ; | ||
| 877 | ; _set_windows - re-map all mapped physical pages | ||
| 878 | ; | ||
| 879 | ; This routine maps all mapped 386 pages of the EMM page frame into the | ||
| 880 | ; linear address space for the page frame. | ||
| 881 | ; | ||
| 882 | ; ENTRY: PROTECTED MODE ONLY | ||
| 883 | ; DS = DGROUP | ||
| 884 | ; SS:[BP] -> regp stack frame | ||
| 885 | ; | ||
| 886 | ; EXIT: page tables changed to map these pages. | ||
| 887 | ; _current_map contents initialized. | ||
| 888 | ; | ||
| 889 | ; uses: | ||
| 890 | ; FLAGS, EAX, EBX, ECX, ESI, EDI | ||
| 891 | ; | ||
| 892 | ;*********************************************** | ||
| 893 | ; | ||
| 894 | _set_windows proc near | ||
| 895 | ; | ||
| 896 | xor ax, ax ; start from PHYS page 0 | ||
| 897 | Get_FRS_Window SI ; SI <-- current FRS map | ||
| 898 | sw_loop: | ||
| 899 | mov bx, word ptr [si] ; BX <-- emm page # | ||
| 900 | add si, 2 ; prepare for next PHYS page | ||
| 901 | cmp bx, 0FFFFh ; not mapped ? | ||
| 902 | je sw_unmap_page ; Y: unmap it | ||
| 903 | cmp bx, [_total_pages] ; emm page out of range ? | ||
| 904 | ja sw_corrupt ; Y: error | ||
| 905 | mov di, bx | ||
| 906 | shl di, 2 ; SI <-- _pft386 offset of emm page | ||
| 907 | add di, [_pft386] | ||
| 908 | cmp dword ptr [di], 0 ; pte not mapped ? | ||
| 909 | je sw_corrupt ; Y: error | ||
| 910 | push eax | ||
| 911 | call map_EMM_page ; map a page | ||
| 912 | pop eax | ||
| 913 | sw_done_page: | ||
| 914 | inc ax | ||
| 915 | cmp ax, [_physical_page_count] | ||
| 916 | jb sw_loop ; next page | ||
| 917 | |||
| 918 | mov eax, cr3 | ||
| 919 | mov cr3, eax ; flush TLB | ||
| 920 | ret | ||
| 921 | |||
| 922 | sw_unmap_page: | ||
| 923 | push eax | ||
| 924 | call unmap_Page | ||
| 925 | pop eax | ||
| 926 | jmp short sw_done_page | ||
| 927 | |||
| 928 | sw_corrupt: | ||
| 929 | mov byte ptr [bp.rAX+1], SOURCE_CORRUPTED | ||
| 930 | pop dx | ||
| 931 | ret | ||
| 932 | |||
| 933 | _set_windows endp | ||
| 934 | |||
| 935 | page | ||
| 936 | ;******************************************************************************* | ||
| 937 | ; | ||
| 938 | ; LIM 4.0 EXTRAS for Windows | ||
| 939 | ; | ||
| 940 | ;******************************************************************************* | ||
| 941 | |||
| 942 | ;*********************************************** | ||
| 943 | ; | ||
| 944 | ; _GetSetPartial - get/set partial page map to/from external save area | ||
| 945 | ; | ||
| 946 | ; This routine stores the current page mapping context | ||
| 947 | ; to an external save area and/or restores the current page | ||
| 948 | ; mapping context from an external save area. | ||
| 949 | ; | ||
| 950 | ; ENTRY: PROTECTED MODE ONLY | ||
| 951 | ; AH = 4Fh = Get/Set page map function number | ||
| 952 | ; AL = SUBFUNCTION CODE | ||
| 953 | ; AL = 0 => Get page map | ||
| 954 | ; AL = 1 => Set page map | ||
| 955 | ; AL = 2 => return size of page map | ||
| 956 | ; REGS on STACK: SI = not used by this function | ||
| 957 | ; SS:[BP] -> regp stack frame | ||
| 958 | ; DS = DGROUP | ||
| 959 | ; | ||
| 960 | ; EXIT: current state saved / restored | ||
| 961 | ; AH = status of this function | ||
| 962 | ; | ||
| 963 | ; USED: BX,CX,DX,SI,DI | ||
| 964 | ; | ||
| 965 | ;*********************************************** | ||
| 966 | _GetSetPartial proc near | ||
| 967 | cmp al, 0 ; Get...? | ||
| 968 | jne gsppm_not0 | ||
| 969 | |||
| 970 | call _source_addr ; uses AX, DX | ||
| 971 | mov fs, dx | ||
| 972 | mov si, ax | ||
| 973 | call _dest_addr ; uses AX, DX | ||
| 974 | mov es, dx | ||
| 975 | mov di, ax | ||
| 976 | cld | ||
| 977 | lods word ptr fs:[si] | ||
| 978 | stosw ; Save count in save area | ||
| 979 | or ax, ax | ||
| 980 | jz gsppm_ok ; nothing to do | ||
| 981 | movzx ecx, ax | ||
| 982 | |||
| 983 | mov dx, [_mappable_page_count] | ||
| 984 | cmp cx, dx | ||
| 985 | ja gsppm_inv_phys | ||
| 986 | gsppm_get_loop: | ||
| 987 | lods word ptr fs:[si] ; Get segment | ||
| 988 | shr ax, 10 ; 16k page number | ||
| 989 | sub ax, CONV_STRT_PG ; first page in emm_mpindex arr | ||
| 990 | jb gsppm_inv_seg ; only pages above 256k | ||
| 991 | mov bx, ax | ||
| 992 | mov al, EMM_MPindex[bx] ; convert to physical page | ||
| 993 | cmp al, -1 ; does it exist | ||
| 994 | je gsppm_inv_seg | ||
| 995 | mov bx, ax | ||
| 996 | shl bx, 2 | ||
| 997 | lea ax, _mappable_pages[bx] | ||
| 998 | mov bx, ax | ||
| 999 | mov bx, [bx.mappable_seg] ; segment for this page | ||
| 1000 | cmp bx, fs:[si-2] | ||
| 1001 | jne gsppm_inv_seg ; must match exactly | ||
| 1002 | mov bx, ax | ||
| 1003 | movzx ebx, [bx.mappable_pg] ; the physical page | ||
| 1004 | cmp bx, dx | ||
| 1005 | ja gsppm_inv_seg | ||
| 1006 | mov ax, bx | ||
| 1007 | stosw ; Save physical page | ||
| 1008 | Get_FRS_window BX ; Get pointer to current window | ||
| 1009 | add bx, ax ; get ptr to emm page# in FRS | ||
| 1010 | add bx, ax | ||
| 1011 | mov ax, [bx] | ||
| 1012 | stosw ; and current mapping | ||
| 1013 | loop gsppm_get_loop | ||
| 1014 | |||
| 1015 | gsppm_ok: | ||
| 1016 | mov byte ptr [bp.rAX+1], OK | ||
| 1017 | ret | ||
| 1018 | |||
| 1019 | gsppm_not0: | ||
| 1020 | cmp al, 1 ; Set...? | ||
| 1021 | jne gsppm_not1 | ||
| 1022 | ; Set Partial Page Map | ||
| 1023 | call _source_addr ; uses AX, DX | ||
| 1024 | mov fs, dx | ||
| 1025 | mov si, ax | ||
| 1026 | movzx ecx, word ptr fs:[si] ; Get count from save area | ||
| 1027 | add si, 2 | ||
| 1028 | jecxz gsppm_ok ; Zero count, do nothing | ||
| 1029 | |||
| 1030 | Get_FRS_window DX ; Get pointer to current window | ||
| 1031 | cmp cx, [_mappable_page_count] | ||
| 1032 | ja short gsppm_corrupt ; can't be more than phys pages | ||
| 1033 | gsppm_set_loop: | ||
| 1034 | push esi | ||
| 1035 | movzx eax, word ptr fs:[si] ; Get Physical page | ||
| 1036 | cmp ax, [_mappable_page_count] | ||
| 1037 | jae gsppm_sl_bad | ||
| 1038 | |||
| 1039 | movzx esi, word ptr fs:[si+2] ; Get mapping (emm page#) | ||
| 1040 | mov di,dx | ||
| 1041 | add di,ax | ||
| 1042 | add di,ax ; di <-- current FRS phy page | ||
| 1043 | mov [di], si ; Save new mapping | ||
| 1044 | |||
| 1045 | cmp si, 0FFFFh ; Unmapped? | ||
| 1046 | je short gsppm_unmap ; yes, go unmap it | ||
| 1047 | cmp si, [_total_pages] ; valid page? | ||
| 1048 | jae short gsppm_sl_bad ; no, fail | ||
| 1049 | |||
| 1050 | mov bx, si ; bx <-- emm page# | ||
| 1051 | ; ax <-- phys page# | ||
| 1052 | call map_EMM_page | ||
| 1053 | |||
| 1054 | gsppm_set_done: | ||
| 1055 | pop esi | ||
| 1056 | add esi, 4 ; Next page to map | ||
| 1057 | loop gsppm_set_loop | ||
| 1058 | mov eax, cr3 ; Flush TLB | ||
| 1059 | mov cr3, eax | ||
| 1060 | jmp gsppm_ok | ||
| 1061 | |||
| 1062 | gsppm_unmap: | ||
| 1063 | call unmap_page ; with ax <-- phys page# | ||
| 1064 | jmp gsppm_set_done ; On to next page | ||
| 1065 | |||
| 1066 | gsppm_sl_bad: | ||
| 1067 | pop esi | ||
| 1068 | gsppm_corrupt: | ||
| 1069 | mov byte ptr [bp.rAX+1], SOURCE_CORRUPTED | ||
| 1070 | ret | ||
| 1071 | |||
| 1072 | gsppm_not1: | ||
| 1073 | cmp al, 2 ; Size? | ||
| 1074 | jne gspm_inv_subfun | ||
| 1075 | cmp bx, [_mappable_page_count] ; # of page frames | ||
| 1076 | ja short gsppm_inv_phys | ||
| 1077 | shl bx, 2 ; Size = pages * 4 + 2 | ||
| 1078 | add bx, 2 | ||
| 1079 | mov byte ptr [bp.rAX], bl | ||
| 1080 | jmp gsppm_ok | ||
| 1081 | |||
| 1082 | gsppm_inv_subfun: | ||
| 1083 | mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION | ||
| 1084 | ret | ||
| 1085 | |||
| 1086 | gsppm_inv_phys: | ||
| 1087 | gsppm_inv_seg: | ||
| 1088 | mov byte ptr [bp.rAX+1], PHYS_PAGE_RANGE | ||
| 1089 | ret | ||
| 1090 | |||
| 1091 | _GetSetPartial endp | ||
| 1092 | |||
| 1093 | page | ||
| 1094 | ;*********************************************** | ||
| 1095 | ; | ||
| 1096 | ; _MapHandleArray - map an array of a handle's pages | ||
| 1097 | ; | ||
| 1098 | ; This routine maps the physical pages according to | ||
| 1099 | ; an array of mappings. | ||
| 1100 | ; | ||
| 1101 | ; ENTRY: PROTECTED MODE ONLY | ||
| 1102 | ; AH = 50h = map handle page function # | ||
| 1103 | ; AL = Subfunction: 0) Physical pages described by their number | ||
| 1104 | ; 1) Physical pages described by segment | ||
| 1105 | ; CX = number of pages to be mapped | ||
| 1106 | ; DX = EMM handle | ||
| 1107 | ; REGS on STACK DS:SI = array of mappings | ||
| 1108 | ; SS:[BP] -> regp stack frame | ||
| 1109 | ; DS = DGROUP | ||
| 1110 | ; NOTE: | ||
| 1111 | ; There is a second entry point for this procedure at the label | ||
| 1112 | ; MapHandleArray_Entry_2. The entry conditions for this are identical | ||
| 1113 | ; to those specified above except that ESI points to the mapping array-- | ||
| 1114 | ; the DS:SI on the stack are ignored. Also, the value in AH is undefined. | ||
| 1115 | ; This entry point is used by the AlterMapAndJump and AlterMapAndCall | ||
| 1116 | ; functions. | ||
| 1117 | ; | ||
| 1118 | ; EXIT: context block ve_window set up | ||
| 1119 | ; page table entries set up | ||
| 1120 | ; AH = status of this function | ||
| 1121 | ; = EMM_HW_MALFUNCTION if entry in real/virtual mode. | ||
| 1122 | ; | ||
| 1123 | ; USED: AX,BX,DX,SI,DI,FS | ||
| 1124 | ; | ||
| 1125 | ;*********************************************** | ||
| 1126 | Dword_Align _TEXT | ||
| 1127 | _MapHandleArray proc near | ||
| 1128 | mov si, ax | ||
| 1129 | push dx | ||
| 1130 | call _source_addr ; DX:AX <-- mapping array | ||
| 1131 | xchg si, ax | ||
| 1132 | mov fs, dx | ||
| 1133 | pop dx ; FS:SI <-- mapping array | ||
| 1134 | |||
| 1135 | MapHandleArray_Entry_2: | ||
| 1136 | cmp al, 1 ; Q: Is subfunction 0 or 1? | ||
| 1137 | ja mha_inv_sub ; N: Invalid subfunction | ||
| 1138 | |||
| 1139 | Validate_Handle <mha_inv_handle> | ||
| 1140 | |||
| 1141 | mov byte ptr [bp.rAX+1], OK ; Assume success | ||
| 1142 | movzx ecx, cx | ||
| 1143 | jecxz short mha_exit ; none to do, just return | ||
| 1144 | |||
| 1145 | or al, al ; which subfunction? | ||
| 1146 | jnz short mha_sub1 ; subfunction 1? | ||
| 1147 | |||
| 1148 | ; | ||
| 1149 | ; Subfunction 0: array contains logical and physical | ||
| 1150 | ; page numbers. | ||
| 1151 | ; | ||
| 1152 | mha_sub0: | ||
| 1153 | movzx eax, fs:[si.mha0_phys_pg] ; physical page number | ||
| 1154 | movzx ebx, fs:[si.mha0_log_pg] ; logical page number | ||
| 1155 | call map_page ; map it if possible | ||
| 1156 | jc short mha_exit ; Error code already set | ||
| 1157 | add si, size mha_array0 | ||
| 1158 | loop mha_sub0 | ||
| 1159 | jmp short mha_exit | ||
| 1160 | |||
| 1161 | ; | ||
| 1162 | ; Subfunction 1: array contains logical page number and | ||
| 1163 | ; segment numbers corresponding to the | ||
| 1164 | ; desired physical pages. | ||
| 1165 | ; | ||
| 1166 | mha_sub1: | ||
| 1167 | mov di, fs:[si.mha1_seg] ; segment to map | ||
| 1168 | mov ax, di ; save for later | ||
| 1169 | shr di, 10 ; 16k page number | ||
| 1170 | sub di, CONV_STRT_PG ; first page in emm_mpindex arr | ||
| 1171 | jb short mha_inv_seg ; only pages above 256k | ||
| 1172 | movsx edi, EMM_MPindex[di] ; convert to physical page | ||
| 1173 | cmp edi, -1 ; does it exist | ||
| 1174 | je short mha_inv_seg | ||
| 1175 | shl di, 2 ; index * 4 | ||
| 1176 | lea di, _mappable_pages[di] | ||
| 1177 | cmp ax, [di.mappable_seg] ; segment for this page | ||
| 1178 | jne short mha_inv_seg ; must match exactly | ||
| 1179 | movzx eax, [di.mappable_pg] ; the physical page | ||
| 1180 | movzx ebx, fs:[si.mha1_log_pg] ; the logical page | ||
| 1181 | call map_page ; try to map it | ||
| 1182 | jc short mha_exit ; error code already set | ||
| 1183 | add si, size mha_array1 | ||
| 1184 | loop mha_sub1 ; back for next segment to map | ||
| 1185 | |||
| 1186 | mha_exit: | ||
| 1187 | mov eax, cr3 ; Always clear TLB, we may have | ||
| 1188 | mov cr3, eax ; mapped pages before an error | ||
| 1189 | ret | ||
| 1190 | ; ERRORS... | ||
| 1191 | mha_inv_handle: | ||
| 1192 | mov byte ptr [bp.rAX+1], INVALID_HANDLE | ||
| 1193 | ret | ||
| 1194 | mha_inv_sub: | ||
| 1195 | mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION | ||
| 1196 | ret | ||
| 1197 | mha_inv_seg: | ||
| 1198 | mov byte ptr [bp.rAX+1], PHYS_PAGE_RANGE | ||
| 1199 | jmp mha_exit | ||
| 1200 | |||
| 1201 | _MapHandleArray endp | ||
| 1202 | |||
| 1203 | |||
| 1204 | |||
| 1205 | page | ||
| 1206 | ;*********************************************** | ||
| 1207 | ; | ||
| 1208 | ; _AlterMapAndJump - map an array of a handle's pages and Jump to a | ||
| 1209 | ; a specified address | ||
| 1210 | ; | ||
| 1211 | ; This routine maps pages using the MapHandleArray procedure and jumps | ||
| 1212 | ; to the specified address | ||
| 1213 | ; | ||
| 1214 | ; ENTRY: PROTECTED MODE ONLY | ||
| 1215 | ; AL = Mapping method -- 0 = Physical pages, 1 = Segments | ||
| 1216 | ; DX = EMM handle | ||
| 1217 | ; REGS on STACK | ||
| 1218 | ; REGS on STACK -- DS:SI -> Map and Jump structure | ||
| 1219 | ; SS:[BP] -> regp stack frame | ||
| 1220 | ; DS = DGROUP | ||
| 1221 | ; | ||
| 1222 | ; EXIT: context block ve_window set up | ||
| 1223 | ; page table entries set up | ||
| 1224 | ; AH = status of this function | ||
| 1225 | ; = EMM_HW_MALFUNCTION if entry in real/virtual mode. | ||
| 1226 | ; Address specified in Map and Jump structure will be new return address | ||
| 1227 | ; | ||
| 1228 | ; USED: AX,BX,CX,SI,DI,FS,GS | ||
| 1229 | ; | ||
| 1230 | ;********************************************** | ||
| 1231 | |||
| 1232 | _AlterMapAndJump PROC NEAR | ||
| 1233 | |||
| 1234 | push dx | ||
| 1235 | mov si, ax | ||
| 1236 | call _source_addr ; DX:AX <-- map & jump struct | ||
| 1237 | mov gs, dx | ||
| 1238 | xchg si, ax ; GS:SI <-- map & jump struct | ||
| 1239 | pop dx | ||
| 1240 | push si | ||
| 1241 | push ax | ||
| 1242 | push dx ; save EMM handle | ||
| 1243 | mov dx, WORD PTR gs:[si.maj_map_address] ; AX:DX <-- map array | ||
| 1244 | mov ax, WORD PTR gs:[si.maj_map_address+2] | ||
| 1245 | Set_EMM_GDT EMM2_GSEL | ||
| 1246 | mov fs, bx ; FS:0 <-- map array | ||
| 1247 | pop dx ; restore handle | ||
| 1248 | pop ax ; restore subfunction | ||
| 1249 | movzx ecx, byte ptr gs:[si.maj_log_phys_map_len] ; Length of map | ||
| 1250 | xor si, si ; FS:SI <-- map array | ||
| 1251 | call MapHandleArray_Entry_2 ; Map the array | ||
| 1252 | pop si | ||
| 1253 | |||
| 1254 | mov ah, byte ptr [bp.rAX+1] | ||
| 1255 | or ah, ah | ||
| 1256 | jnz SHORT AMJ_Error | ||
| 1257 | mov eax, dword ptr gs:[si.maj_target_address] | ||
| 1258 | mov word ptr [bp.retaddr], ax ; Put jump address in place of | ||
| 1259 | shr eax, 16 ; old IRET return address | ||
| 1260 | mov word ptr [bp.rCS], ax | ||
| 1261 | ; | ||
| 1262 | ; now, pop 5 words from client's stack because we are not | ||
| 1263 | ; going to go back. (See AlterMapAndCall for client's | ||
| 1264 | ; Stack frame structure) | ||
| 1265 | ; | ||
| 1266 | mov edi, dword ptr [bp.rFS+2+VTFO.VMTF_ESP] ; clients's ESP | ||
| 1267 | add edi, 5 * 2 ; "pop" 5 words | ||
| 1268 | mov dword ptr [bp.rFS+2+VTFO.VMTF_ESP], edi ; save it | ||
| 1269 | ; | ||
| 1270 | ; tell EMMpEntry to patch CS:IP onto its' iretd stack frame | ||
| 1271 | ; | ||
| 1272 | or word ptr [bp.PFlag], PFLAG_PATCH_CS_IP | ||
| 1273 | AMJ_Error: ; Do the jump | ||
| 1274 | ret | ||
| 1275 | |||
| 1276 | _AlterMapAndJump ENDP | ||
| 1277 | |||
| 1278 | |||
| 1279 | page | ||
| 1280 | ;*********************************************** | ||
| 1281 | ; | ||
| 1282 | ; _AlterMapAndCall - map an array of a handle's pages and call a procedure | ||
| 1283 | ; at a specified address (similar to a FAR call) | ||
| 1284 | ; This function pushes the return address on the | ||
| 1285 | ; client's stack and Jumps to the specified procedure. | ||
| 1286 | ; The "Called" procedure will return to AMC_return_address | ||
| 1287 | ; | ||
| 1288 | ; ENTRY: PROTECTED MODE ONLY | ||
| 1289 | ; AL = Subfunction -- 0 = Map phys pages, 1 = Map segs, 2 = Frame size | ||
| 1290 | ; DX = EMM handle | ||
| 1291 | ; REGS on STACK DS:SI = Map and Call structure | ||
| 1292 | ; SS:[BP] -> regp stack frame | ||
| 1293 | ; DS = DGROUP | ||
| 1294 | ; | ||
| 1295 | ; EXIT: context block ve_window set up | ||
| 1296 | ; page table entries set up | ||
| 1297 | ; Transfer Space pushed on client's stack | ||
| 1298 | ; Return address CS and IP will point to called procedure | ||
| 1299 | ; AH = status of this function | ||
| 1300 | ; = EMM_HW_MALFUNCTION if entry in real/virtual mode. | ||
| 1301 | ; | ||
| 1302 | ; USED: AX,BX,CX,DX,SI,DI | ||
| 1303 | ; | ||
| 1304 | ;*********************************************** | ||
| 1305 | |||
| 1306 | _AlterMapAndCall PROC NEAR | ||
| 1307 | |||
| 1308 | cmp al, 2 ; Q: Which subfuction ? | ||
| 1309 | ja AMC_inv_sub ; >2: invalid subfunction | ||
| 1310 | je AMC_Stack_Fram_Size ; =2: Stack frame size subfuncion | ||
| 1311 | ; <2: map and call | ||
| 1312 | push dx | ||
| 1313 | mov si, ax | ||
| 1314 | call _source_addr ; DX:AX <-- map & call structure | ||
| 1315 | mov gs, dx | ||
| 1316 | xchg si, ax ; GS:SI <-- map & call structure | ||
| 1317 | pop dx | ||
| 1318 | ; | ||
| 1319 | ; check new and old map's length | ||
| 1320 | ; | ||
| 1321 | xor ch, ch | ||
| 1322 | mov cl, byte ptr gs:[si.mac_old_page_map_len] ; CX = Length of old map | ||
| 1323 | cmp cx, [_physical_page_count] | ||
| 1324 | jae AMC_inv_phys_pages | ||
| 1325 | mov cl, byte ptr gs:[si.mac_new_page_map_len] ; CX = Length of new map | ||
| 1326 | cmp cx, [_physical_page_count] | ||
| 1327 | jae AMC_inv_phys_pages | ||
| 1328 | ; | ||
| 1329 | ; get client's SS:ESP so we can push stuffs on it | ||
| 1330 | ; | ||
| 1331 | push ax | ||
| 1332 | push dx | ||
| 1333 | |||
| 1334 | mov edi, dword ptr [bp.rFS+2+VTFO.VMTF_ESP] ; clients's ESP | ||
| 1335 | mov ax, word ptr [bp.rFS+2+VTFO.VMTF_SS] ; client's SS | ||
| 1336 | xor dx, dx ; AX:DX <-- Seg:Off of Client's Stack | ||
| 1337 | |||
| 1338 | push ax ; client's Stack Segment | ||
| 1339 | Set_EMM_GDT EMM2_GSEL | ||
| 1340 | push bx ; client's Stack Selector | ||
| 1341 | ; | ||
| 1342 | ; get CS's Base to "push" on stack for later retf from client | ||
| 1343 | ; | ||
| 1344 | push GDTD_GSEL | ||
| 1345 | pop es ; ES:0 <-- GDT | ||
| 1346 | mov bx, cs ; selector | ||
| 1347 | and bl, SEL_LOW_MASK | ||
| 1348 | mov dx, word ptr es:[bx + 2] ; get lower 16 bit of Base | ||
| 1349 | mov al, byte ptr es:[bx + 4] ; get upper 8 bit of Base | ||
| 1350 | shr dx, 4 | ||
| 1351 | shl al, 4 | ||
| 1352 | or dh, al ; get the segment value | ||
| 1353 | mov bx, dx ; into BX | ||
| 1354 | |||
| 1355 | pop es ; ES:DI <-- client's SS | ||
| 1356 | pop cx ; CX <-- Client's stack Segment | ||
| 1357 | |||
| 1358 | pop dx | ||
| 1359 | pop ax | ||
| 1360 | ; | ||
| 1361 | ; save client's stack segment and target address on stack | ||
| 1362 | ; cause they (CX and EMM1_GSEL) get destroy | ||
| 1363 | ; | ||
| 1364 | push cx | ||
| 1365 | push word ptr gs:[si].mac_target_address+2 | ||
| 1366 | push word ptr gs:[si].mac_target_address | ||
| 1367 | ; | ||
| 1368 | ; On the Client's stack : | ||
| 1369 | ; | ||
| 1370 | ; +-----------------+ | ||
| 1371 | ; | client's Flag | | ||
| 1372 | ; +-----------------+ | ||
| 1373 | ; | client's CS | | ||
| 1374 | ; +-----------------+ | ||
| 1375 | ; | client's IP | | ||
| 1376 | ; +-----------------+ | ||
| 1377 | ; | EMM_rEntry's CS | | ||
| 1378 | ; +-----------------+ | ||
| 1379 | ; | EMM_rEntry's IP | <-- "SS:ESP" (ES:EDI) | ||
| 1380 | ; +-----------------+ | ||
| 1381 | ; | ||
| 1382 | ; "pop" EMM_rEntry's CS:IP off the stack, save it on Ring0 stack | ||
| 1383 | ; in case thereis an error and need to restore state of stack. | ||
| 1384 | ; keep the rest (client's FLAG, CS and IP) | ||
| 1385 | ; | ||
| 1386 | push es:[di+2] ; EMM_rEntry's CS | ||
| 1387 | push es:[di] ; EMM_rEntry's IP | ||
| 1388 | add di, 2 * 2 ; "pop" | ||
| 1389 | ; | ||
| 1390 | ; save old map on stack | ||
| 1391 | ; | ||
| 1392 | movzx ecx, byte ptr gs:[si.mac_old_page_map_len] ; CX = Length of old map | ||
| 1393 | shl cx, 2 ; CX * 4 (4 bytes each entry) | ||
| 1394 | inc cx ; one more for length | ||
| 1395 | get_space_from_stack CX ; ES:DI <-- space on stack | ||
| 1396 | dec cx | ||
| 1397 | shr cx, 2 ; CX back to length in bytes | ||
| 1398 | |||
| 1399 | push ds | ||
| 1400 | push di ; save postion of stack | ||
| 1401 | push si | ||
| 1402 | push ax | ||
| 1403 | push bx | ||
| 1404 | push dx | ||
| 1405 | push cx ; save #pages | ||
| 1406 | |||
| 1407 | cld | ||
| 1408 | mov dx, word ptr gs:[si.mac_old_map_address] ; AX:DX <-- map array | ||
| 1409 | mov ax, word ptr gs:[si.mac_old_map_address+2] | ||
| 1410 | push es | ||
| 1411 | Set_EMM_GDT USER1_GSEL | ||
| 1412 | pop es | ||
| 1413 | mov ds, bx ; DS:0 <-- map array | ||
| 1414 | xor si, si | ||
| 1415 | pop cx | ||
| 1416 | mov ax, cx | ||
| 1417 | stosb ; store length of map | ||
| 1418 | |||
| 1419 | shl cx, 1 ; move word | ||
| 1420 | rep movsw | ||
| 1421 | |||
| 1422 | pop dx ; restore handle | ||
| 1423 | pop bx ; restore Segment of client Stack | ||
| 1424 | pop ax ; restore subfunction | ||
| 1425 | pop si | ||
| 1426 | pop di | ||
| 1427 | pop ds | ||
| 1428 | ; | ||
| 1429 | ; save FRS context on stack | ||
| 1430 | ; | ||
| 1431 | movzx ecx, [_cntxt_bytes] | ||
| 1432 | get_space_from_stack CX ; ES:DI <-- space on stack | ||
| 1433 | |||
| 1434 | push si | ||
| 1435 | push di | ||
| 1436 | get_FRS_Window SI ; DS:SI <-- mapping context | ||
| 1437 | shr ecx, 1 ; move words | ||
| 1438 | rep movsw | ||
| 1439 | |||
| 1440 | pop di | ||
| 1441 | pop si | ||
| 1442 | ; | ||
| 1443 | ; map new mapping | ||
| 1444 | ; | ||
| 1445 | push bx | ||
| 1446 | push ax | ||
| 1447 | push dx | ||
| 1448 | |||
| 1449 | push di ; save "stack pointer" | ||
| 1450 | push si | ||
| 1451 | push ax | ||
| 1452 | push dx ; save EMM handle | ||
| 1453 | mov dx, WORD PTR gs:[si.mac_new_map_address]; AX:DX <-- map array | ||
| 1454 | mov ax, WORD PTR gs:[si.mac_new_map_address+2] | ||
| 1455 | push es | ||
| 1456 | Set_EMM_GDT USER1_GSEL | ||
| 1457 | pop es | ||
| 1458 | mov fs, bx ; FS:0 <-- map array | ||
| 1459 | xor si, si | ||
| 1460 | pop dx ; restore handle | ||
| 1461 | pop ax ; restore subfunction | ||
| 1462 | movzx ecx, byte ptr gs:[si.mac_new_page_map_len] | ||
| 1463 | call MapHandleArray_Entry_2 ; Map the array | ||
| 1464 | pop si ; Restore structure pointer | ||
| 1465 | pop di ; restore "stack" pointer | ||
| 1466 | pop dx | ||
| 1467 | pop ax | ||
| 1468 | mov bh, byte ptr [bp.rAX+1] | ||
| 1469 | or bh, bh | ||
| 1470 | pop bx | ||
| 1471 | jnz AMC_map_Error | ||
| 1472 | ; | ||
| 1473 | ; save needed registers, return address and call address | ||
| 1474 | ; on client's stack | ||
| 1475 | ; | ||
| 1476 | dec di | ||
| 1477 | dec di ; "pre-decrement" stack | ||
| 1478 | std ; store backward | ||
| 1479 | stosw ; subfunction code | ||
| 1480 | mov ax, dx ; EMM handle | ||
| 1481 | stosw | ||
| 1482 | mov ax, ds ; DGROUP | ||
| 1483 | stosw | ||
| 1484 | mov ax, bx ; CS for return from called code | ||
| 1485 | stosw | ||
| 1486 | mov ax, offset AMC_return_address ; IP for return from called code | ||
| 1487 | mov es:[di], ax ; "push" without decrement "SP" | ||
| 1488 | cld | ||
| 1489 | ; | ||
| 1490 | ; NOW build a iretd stack frame to go back to virtual mode | ||
| 1491 | ; | ||
| 1492 | pop ax ; no error : we can throw | ||
| 1493 | pop ax ; away EMM-rEntry's CS:IP now | ||
| 1494 | |||
| 1495 | pop ax ; target address | ||
| 1496 | pop dx ; target address+2 | ||
| 1497 | pop cx ; Stack Segment | ||
| 1498 | |||
| 1499 | push 0 | ||
| 1500 | push word ptr [bp].rGS | ||
| 1501 | push 0 | ||
| 1502 | push word ptr [bp].rFS | ||
| 1503 | push 0 | ||
| 1504 | push word ptr [bp].rDS | ||
| 1505 | push 0 | ||
| 1506 | push word ptr [bp].rES | ||
| 1507 | push 0 | ||
| 1508 | push cx ; client's SS | ||
| 1509 | push edi ; client's ESP | ||
| 1510 | push PFLAG_VM ; VM bit | ||
| 1511 | mov bx, word ptr [bp].PFlag | ||
| 1512 | and bx, not PFLAG_VIRTUAL ; clear fake bit | ||
| 1513 | push bx | ||
| 1514 | push 0 | ||
| 1515 | push dx ; target address+2 | ||
| 1516 | push 0 | ||
| 1517 | push ax ; target address | ||
| 1518 | ; | ||
| 1519 | ; restore registers context from stack frame | ||
| 1520 | ; | ||
| 1521 | mov eax, dword ptr [bp].rAX | ||
| 1522 | mov ebx, dword ptr [bp].rBX | ||
| 1523 | mov ecx, dword ptr [bp].rCX | ||
| 1524 | mov edx, dword ptr [bp].rDX | ||
| 1525 | mov esi, dword ptr [bp].rSI | ||
| 1526 | mov edi, dword ptr [bp].rDI | ||
| 1527 | mov ebp, dword ptr [bp].rFS+2 ; clients's EBP | ||
| 1528 | ; | ||
| 1529 | ; return to virtual mode via iretd with calling address on stack | ||
| 1530 | ; | ||
| 1531 | iretd | ||
| 1532 | |||
| 1533 | AMC_map_Error: | ||
| 1534 | ; | ||
| 1535 | ; mapping error occur : restore state and exit | ||
| 1536 | ; | ||
| 1537 | movzx ecx, [_cntxt_bytes] | ||
| 1538 | push es | ||
| 1539 | pop ds ; DS:SI <-- stack | ||
| 1540 | xchg si, di | ||
| 1541 | release_space_to_stack CX ; DS:SI <-- space on stack | ||
| 1542 | ; | ||
| 1543 | movzx ecx, byte ptr gs:[di.mac_old_page_map_len] ; CX = Length of old map | ||
| 1544 | shl cx, 2 ; CX * 4 (4 bytes each entry) | ||
| 1545 | inc cx ; one more for length | ||
| 1546 | release_space_to_stack CX ; DS:SI <-- space on stack | ||
| 1547 | ; | ||
| 1548 | mov di, si | ||
| 1549 | mov cx, 4 | ||
| 1550 | get_space_from_stack CX ; ES:DI <-- space on stack | ||
| 1551 | pop es:[di] ; restore EMM_rEntry's CS:IP | ||
| 1552 | pop es:[di+2] | ||
| 1553 | |||
| 1554 | pop ax ; discard target addr etc | ||
| 1555 | pop ax | ||
| 1556 | pop ax | ||
| 1557 | |||
| 1558 | ret | ||
| 1559 | |||
| 1560 | AMC_Stack_Fram_Size: | ||
| 1561 | mov byte ptr [bp.rAX+1], OK ; No error | ||
| 1562 | mov ax, [_mappable_page_count] ; assume ALL mappable pages | ||
| 1563 | shl ax, 2 ; 4 bytes per page | ||
| 1564 | add ax, 1 + (3+5)*2 ; map length | ||
| 1565 | ; + 3 words already pushed by EMM_rEntry | ||
| 1566 | ; + 5 registers pushed | ||
| 1567 | add al, [_cntxt_bytes] ; FRS context | ||
| 1568 | adc ah, 0 | ||
| 1569 | mov word ptr [bp.rBX], ax | ||
| 1570 | ret | ||
| 1571 | |||
| 1572 | AMC_inv_phys_pages: | ||
| 1573 | mov byte ptr [bp.rAX+1], PHYS_PAGE_RANGE | ||
| 1574 | ret | ||
| 1575 | |||
| 1576 | AMC_inv_sub: | ||
| 1577 | mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION | ||
| 1578 | ret | ||
| 1579 | |||
| 1580 | _AlterMapAndCall ENDP | ||
| 1581 | |||
| 1582 | |||
| 1583 | ;****************************************************************************** | ||
| 1584 | ; | ||
| 1585 | ; AMC_return_address -- Return from procedure called through a Map & Call | ||
| 1586 | ; | ||
| 1587 | ; NOTE: MapHandleArray will only access AH on the stack and so the | ||
| 1588 | ; TSTF stack frame will work properly for this procedure. | ||
| 1589 | ; | ||
| 1590 | ; ENTRY: VTFOE frame,EBP,EBX,ESI are on the stack | ||
| 1591 | ; | ||
| 1592 | ;****************************************************************************** | ||
| 1593 | |||
| 1594 | AMC_return_address proc far | ||
| 1595 | |||
| 1596 | ; | ||
| 1597 | ; This will causes an illegal instruction trap and goes into protected | ||
| 1598 | ; mode. The handler will return back to the point right after the | ||
| 1599 | ; 2 bytes ARPL instruction with ring0 stack having and IRETD stack frame | ||
| 1600 | ; | ||
| 1601 | arpl ax, ax | ||
| 1602 | ; | ||
| 1603 | ; In Protected Mode Now | ||
| 1604 | ; | ||
| 1605 | pushad ; saves all regs | ||
| 1606 | mov ax, sp ; saves stack frame address | ||
| 1607 | mov [_regp], ax ; to _regp | ||
| 1608 | |||
| 1609 | mov esi, dword ptr [bp.VTFOE.VMTF_ESP] ; clients's ESP | ||
| 1610 | mov ax, word ptr [bp.VTFOE.VMTF_SS] ; client's SS | ||
| 1611 | xor dx, dx ; AX:DX <-- Seg:Off of Client's Stack | ||
| 1612 | |||
| 1613 | Set_EMM_GDT EMM2_GSEL | ||
| 1614 | mov fs, bx ; FS:SI <-- client's Stack | ||
| 1615 | |||
| 1616 | cld ; forward | ||
| 1617 | ; | ||
| 1618 | ; "pop" back registers on "stack" FS:SI | ||
| 1619 | ; | ||
| 1620 | push fs | ||
| 1621 | pop ds | ||
| 1622 | lodsw | ||
| 1623 | mov es, ax ; DGROUP | ||
| 1624 | lodsw | ||
| 1625 | mov dx, ax ; EMM handle | ||
| 1626 | lodsw ; subfunction code | ||
| 1627 | ; | ||
| 1628 | ; restore mapping context | ||
| 1629 | ; | ||
| 1630 | push ax | ||
| 1631 | |||
| 1632 | push es | ||
| 1633 | pop ds ; DGROUP | ||
| 1634 | get_FRS_Window DI ; ES:DI <-- FRS mapping context regs | ||
| 1635 | push fs | ||
| 1636 | pop ds ; DS:SI <-- client's stack | ||
| 1637 | xor ch, ch | ||
| 1638 | mov cl, ES:[_cntxt_bytes] | ||
| 1639 | shr cx, 1 ; move word | ||
| 1640 | cld | ||
| 1641 | rep movsw | ||
| 1642 | ; | ||
| 1643 | ; map old mapping | ||
| 1644 | ; | ||
| 1645 | lodsb | ||
| 1646 | mov ah, 0 | ||
| 1647 | mov cx, ax ; length | ||
| 1648 | pop ax ; subfunction code | ||
| 1649 | push si | ||
| 1650 | push cx | ||
| 1651 | push bp | ||
| 1652 | mov bp, [_regp] ; setup pushad frame first | ||
| 1653 | push es | ||
| 1654 | pop ds ; DS <-- DGROUP | ||
| 1655 | call MapHandleArray_Entry_2 ; map it | ||
| 1656 | pop bp | ||
| 1657 | pop cx | ||
| 1658 | pop si | ||
| 1659 | shl cx, 2 ; 4 bytes per mapping | ||
| 1660 | release_space_to_stack CX | ||
| 1661 | ; | ||
| 1662 | ; saves CS:IP (BX:CX) on iretd stack frame | ||
| 1663 | ; | ||
| 1664 | push fs | ||
| 1665 | pop ds ; DS <-- Client's Stack | ||
| 1666 | push ax | ||
| 1667 | lodsw | ||
| 1668 | mov word ptr [bp.VTFOE+VMTF_EIP], ax | ||
| 1669 | lodsw | ||
| 1670 | mov word ptr [bp.VTFOE+VMTF_CS], ax | ||
| 1671 | lodsw | ||
| 1672 | mov word ptr [bp.VTFOE+VMTF_EFLAGS], ax | ||
| 1673 | mov word ptr [bp.VTFOE+VMTF_EFLAGShi], PFLAG_VM | ||
| 1674 | pop ax | ||
| 1675 | ; | ||
| 1676 | ; save client's new stack pointer | ||
| 1677 | ; | ||
| 1678 | mov dword ptr [bp.VTFOE.VMTF_ESP], esi | ||
| 1679 | popad | ||
| 1680 | pop esi | ||
| 1681 | pop ebx | ||
| 1682 | pop ebp | ||
| 1683 | add esp, 4 ; discard "error" code | ||
| 1684 | ; | ||
| 1685 | ; set return status | ||
| 1686 | ; | ||
| 1687 | mov ah, OK | ||
| 1688 | |||
| 1689 | iretd | ||
| 1690 | |||
| 1691 | AMC_return_address endp | ||
| 1692 | |||
| 1693 | page | ||
| 1694 | ;****************************************************************************** | ||
| 1695 | ; | ||
| 1696 | ; _MoveExchangeMemory | ||
| 1697 | ; | ||
| 1698 | ; This function (23) will copy or exchange memory between EMM and | ||
| 1699 | ; conventional memory or EMM to EMM. | ||
| 1700 | ; Subfunction 0 is memory copy. Subfunction 1 is exchange. | ||
| 1701 | ; The current mapping context is preserved since the EMM pages are | ||
| 1702 | ; mapped into high memory using VM1s page table. | ||
| 1703 | ; | ||
| 1704 | ; ENTRY: PROTECTED MODE ONLY | ||
| 1705 | ; AL = Subfunction -- 0 = Copy, 1 = Exchange | ||
| 1706 | ; DX = EMM handle | ||
| 1707 | ; REGS on STACK DS:SI = Move/Exchange structure | ||
| 1708 | ; SS:[BP] -> regp stack frame | ||
| 1709 | ; DS = DGROUP | ||
| 1710 | ; | ||
| 1711 | ; EXIT: AL = Status | ||
| 1712 | ; | ||
| 1713 | ; USES: AX, BX, CX, DX, SI, DI | ||
| 1714 | ; | ||
| 1715 | ;============================================================================== | ||
| 1716 | ; | ||
| 1717 | ; ALGORITHM: | ||
| 1718 | ; | ||
| 1719 | ; BEGIN | ||
| 1720 | ; check/validate source/dest and overlay,etc | ||
| 1721 | ; | ||
| 1722 | ; save mapping context of first physical page frame as source page frame | ||
| 1723 | ; save mapping context of second physical page frame as dest page frame | ||
| 1724 | ; | ||
| 1725 | ; /* | ||
| 1726 | ; * setup source and dest memory pointers | ||
| 1727 | ; */ | ||
| 1728 | ; if (source.type == conv.mem) | ||
| 1729 | ; DS:SI = source.initial.segment:source.initial.offset | ||
| 1730 | ; else | ||
| 1731 | ; if (backward.copy) | ||
| 1732 | ; calculate last source emm page and new offset | ||
| 1733 | ; map source.initial.page into source.page.frame | ||
| 1734 | ; DS:SI = segment.of.source.page.frame:source.initial.offset | ||
| 1735 | ; | ||
| 1736 | ; if (dest.type == conv.mem) | ||
| 1737 | ; ES:DI = dest.initial.segment:dest.initial.offset | ||
| 1738 | ; else | ||
| 1739 | ; if (backward.copy) | ||
| 1740 | ; calculate last dest emm page and new offset | ||
| 1741 | ; map dest.initial.page into dest.page.frame | ||
| 1742 | ; ES:DI = segment.of.dest.page.frame:dest.initial.offset | ||
| 1743 | ; | ||
| 1744 | ; /******** | ||
| 1745 | ; * | ||
| 1746 | ; * DS:SI - addresses source data area | ||
| 1747 | ; * ES:DI - addresses dest buffer area | ||
| 1748 | ; * | ||
| 1749 | ; */ | ||
| 1750 | ; | ||
| 1751 | ; for (total.byte.to.process != 0) { | ||
| 1752 | ; /* | ||
| 1753 | ; * find out how many bytes to process (least bytes to process) | ||
| 1754 | ; */ | ||
| 1755 | ; if (source.type == conv.mem) | ||
| 1756 | ; bytes.to.process = 0x4000 - dest.offset | ||
| 1757 | ; else | ||
| 1758 | ; if (dest.type == conv.mem) | ||
| 1759 | ; bytes.to.process = 0x4000 - source.offset | ||
| 1760 | ; else /* emm to emm */ | ||
| 1761 | ; if (backward.copy) | ||
| 1762 | ; bytes.to.process = min(source.offset, dest.offset) + 1 | ||
| 1763 | ; else | ||
| 1764 | ; bytes.to.process = 0x4000 - max(source.offset, dest.offset) | ||
| 1765 | ; | ||
| 1766 | ; /* | ||
| 1767 | ; * adjust the total | ||
| 1768 | ; */ | ||
| 1769 | ; if (bytes.to.process > totol.bytes.to.process) | ||
| 1770 | ; bytes.to.process = totol.bytes.to.process | ||
| 1771 | ; | ||
| 1772 | ; total.bytes.to.process -= bytes.to.process | ||
| 1773 | ; | ||
| 1774 | ; /* | ||
| 1775 | ; * do the processing | ||
| 1776 | ; */ | ||
| 1777 | ; move/exchange bytes.to.process bytes | ||
| 1778 | ; | ||
| 1779 | ; /* | ||
| 1780 | ; * adjust memory pointers and map in new pages if necessary | ||
| 1781 | ; * for the next iternation | ||
| 1782 | ; */ | ||
| 1783 | ; if (total.bytes.to.process != 0) | ||
| 1784 | ; if (source.type == emm) | ||
| 1785 | ; if (SI == 0x4000) | ||
| 1786 | ; /* | ||
| 1787 | ; * forward.copy's index expire | ||
| 1788 | ; */ | ||
| 1789 | ; map next emm source page into source.page.frame | ||
| 1790 | ; SI = 0 | ||
| 1791 | ; if (SI == 0xffff) | ||
| 1792 | ; /* | ||
| 1793 | ; * backward.copy's index expire | ||
| 1794 | ; */ | ||
| 1795 | ; map prev emm source page into source.page.frame | ||
| 1796 | ; SI = 0x3fff | ||
| 1797 | ; else | ||
| 1798 | ; normalize DS:SI | ||
| 1799 | ; | ||
| 1800 | ; if (dest.type == emm) | ||
| 1801 | ; if (DI == 0x4000) | ||
| 1802 | ; /* | ||
| 1803 | ; * forward.copy's index expire | ||
| 1804 | ; */ | ||
| 1805 | ; map next emm dest page into dest.page.frame | ||
| 1806 | ; DI = 0 | ||
| 1807 | ; if (DI == 0xffff) | ||
| 1808 | ; /* | ||
| 1809 | ; * backward.copy's index expire | ||
| 1810 | ; */ | ||
| 1811 | ; map prev emm dest page into dest.page.frame | ||
| 1812 | ; DI = 0x3fff | ||
| 1813 | ; else | ||
| 1814 | ; normalize ES:DI | ||
| 1815 | ; } | ||
| 1816 | ; | ||
| 1817 | ; restore first page frame's mapping context | ||
| 1818 | ; restore second page frame's mapping context | ||
| 1819 | ; END | ||
| 1820 | ; | ||
| 1821 | ;============================================================================== | ||
| 1822 | |||
| 1823 | |||
| 1824 | _MoveExchangeMemory proc near | ||
| 1825 | mov byte ptr [bp.rAX+1], OK ; Assume everything work OK | ||
| 1826 | cld ; Assume forward direction | ||
| 1827 | |||
| 1828 | cmp al, 1 ; Q: Valid subfunction? | ||
| 1829 | ja mem_inv_sub ; N: Error | ||
| 1830 | |||
| 1831 | push ds | ||
| 1832 | pop fs ; fs <-- addresses MEMM's data group | ||
| 1833 | |||
| 1834 | push dx | ||
| 1835 | push cx | ||
| 1836 | push bx | ||
| 1837 | push ax | ||
| 1838 | |||
| 1839 | push bp | ||
| 1840 | mov bp,[_regp] | ||
| 1841 | mov ax, word ptr [bp.rDS] ; DX:AX <-- move/xchg struct | ||
| 1842 | mov dx, word ptr [bp.rSI] | ||
| 1843 | Set_EMM_GDT USER1_GSEL ; use USER1_GSEL since both EMM1_GSEL | ||
| 1844 | ; and EMM2_GSEL will be used | ||
| 1845 | mov ds, bx | ||
| 1846 | xor si, si ; DS:SI <-- Move/Exchange structure | ||
| 1847 | pop bp | ||
| 1848 | pop ax | ||
| 1849 | pop bx | ||
| 1850 | pop cx | ||
| 1851 | pop dx | ||
| 1852 | |||
| 1853 | mov ecx, [si.mem_region_length]; ECX = Length of memory region | ||
| 1854 | or ecx, ecx ; Q: Move 0 bytes? | ||
| 1855 | jz mem_no_error ; Y: Silly! -- Just return | ||
| 1856 | cmp ecx, 0100000h ; Q: Move greater than 1 Meg? | ||
| 1857 | ja mem_inv_region_len ; Y: Error | ||
| 1858 | |||
| 1859 | mov bl, [si.mem_source.mem_memory_type]; Q: Is move Conventional | ||
| 1860 | or bl, [si.mem_dest.mem_memory_type] ; to Conven? | ||
| 1861 | jz mem_conv_to_conv ; Y: Go do it | ||
| 1862 | |||
| 1863 | mov bl, [si.mem_source.mem_memory_type]; Q: Is move EMM | ||
| 1864 | and bl, [si.mem_dest.mem_memory_type] ; to EMM | ||
| 1865 | jz SHORT mem_no_overlap ; N: No overlap | ||
| 1866 | mov bx, [si.mem_source.mem_handle] | ||
| 1867 | cmp bx, [si.mem_dest.mem_handle] ; Q: Same handle? | ||
| 1868 | jnz SHORT mem_no_overlap ; N: No overlap | ||
| 1869 | movzx ebx, [si.mem_source.mem_initial_seg_page] | ||
| 1870 | movzx edx, [si.mem_source.mem_initial_offset] | ||
| 1871 | shl ebx, 14 ; * 4000h | ||
| 1872 | add ebx, edx ; EBX = Source offset within EMM | ||
| 1873 | push ebx ; Save it temporarily | ||
| 1874 | movzx edx, [si.mem_dest.mem_initial_seg_page] | ||
| 1875 | movzx ebx, [si.mem_dest.mem_initial_offset] | ||
| 1876 | shl edx, 14 ; * 4000h | ||
| 1877 | add edx, ebx ; EDX = Dest offset within EMM | ||
| 1878 | pop ebx ; Source offset | ||
| 1879 | sub edx, ebx ; EDX = Source - Destination | ||
| 1880 | jg SHORT mem_dest_gt_source ; Don't negate if Dest > Source | ||
| 1881 | or al, Source_GT_Dest_Flag ; Set flag to note Source > Dest | ||
| 1882 | neg edx ; Absolute value of EDX | ||
| 1883 | mem_dest_gt_source: | ||
| 1884 | cmp edx, ecx ; Q: Is there an overlap? | ||
| 1885 | jae SHORT mem_no_overlap ; N: Continue | ||
| 1886 | test al, 1 ; Q: Is this an exchange? | ||
| 1887 | jnz mem_inv_overlap ; Y: Error -- Cant overlap xchg | ||
| 1888 | mov byte ptr [bp.rAX+1], VALID_OVERLAP ; Assume everything OK but overlap | ||
| 1889 | or al, Overlap_Flag ; N: Note this for later | ||
| 1890 | test al, Source_GT_Dest_Flag ; Q: Is it gonna be backward copy | ||
| 1891 | jnz mem_no_overlap ; N: Continue | ||
| 1892 | or al, Backward_Copy_Flag ; Y: Note for later | ||
| 1893 | std ; Set backword direction | ||
| 1894 | |||
| 1895 | mem_no_overlap: | ||
| 1896 | ; | ||
| 1897 | ; check validility of source | ||
| 1898 | ; | ||
| 1899 | lea di, [si.mem_source] | ||
| 1900 | call validate_for_Move_or_Exchange | ||
| 1901 | or ah, ah | ||
| 1902 | jnz mem_error_exit | ||
| 1903 | ; | ||
| 1904 | ; check validility of dest | ||
| 1905 | ; | ||
| 1906 | lea di, [si.mem_dest] | ||
| 1907 | call validate_for_Move_or_Exchange | ||
| 1908 | or ah, ah | ||
| 1909 | jnz mem_error_exit | ||
| 1910 | |||
| 1911 | or edx, edx ; delayed test for exact move/xchg | ||
| 1912 | je mem_valid_overlap ; WEIRD!!! -- Move to same place! | ||
| 1913 | ; | ||
| 1914 | ; initialize loop | ||
| 1915 | ; | ||
| 1916 | push ds | ||
| 1917 | pop gs | ||
| 1918 | mov bx, si ; GS:BX <-- move/exchange structure | ||
| 1919 | ; | ||
| 1920 | ; save first 2 physical page frames' mapping and use those pages | ||
| 1921 | ; as source and dest physical pages | ||
| 1922 | ; | ||
| 1923 | push fs | ||
| 1924 | pop ds ; DS <-- DGROUP | ||
| 1925 | get_FRS_Window SI | ||
| 1926 | push word ptr [SI] ; save 1st pgae's mapping on stack | ||
| 1927 | push word ptr [SI+2] ; save 2st page's mapping on stack | ||
| 1928 | |||
| 1929 | ; | ||
| 1930 | ; setup dest | ||
| 1931 | ; | ||
| 1932 | mem_set_dest: | ||
| 1933 | cmp gs:[bx.mem_dest.mem_memory_type], 0 ; Q: conv mem ? | ||
| 1934 | jnz mem_map_dest ; N: map in emm page | ||
| 1935 | ; | ||
| 1936 | ; conv memory : setup starting address of dest (always forward) | ||
| 1937 | ; | ||
| 1938 | mov cx, gs:[bx.mem_dest.mem_initial_seg_page] | ||
| 1939 | mov dx, gs:[bx.mem_dest.mem_initial_offset] ; CX:DX <-- dest address | ||
| 1940 | |||
| 1941 | push ax | ||
| 1942 | push bx | ||
| 1943 | mov ax, cx ; AX:DX <-- first byte | ||
| 1944 | Set_EMM_GDT EMM2_GSEL | ||
| 1945 | mov es, bx | ||
| 1946 | xor di, di ; ES:DI <-- dest SelOff | ||
| 1947 | pop bx | ||
| 1948 | pop ax | ||
| 1949 | push 0ffffh ; fake a logical page# | ||
| 1950 | jmp mem_set_source | ||
| 1951 | |||
| 1952 | mem_map_dest: | ||
| 1953 | ; | ||
| 1954 | ; emm memory : find out starting address of dest | ||
| 1955 | ; | ||
| 1956 | mov dx, gs:[bx.mem_dest.mem_initial_seg_page] ; initial logical page# | ||
| 1957 | mov di, gs:[bx.mem_dest.mem_initial_offset] ; initial offset | ||
| 1958 | |||
| 1959 | test al, Backward_Copy_Flag ; Q: Backward copy ? | ||
| 1960 | jz SHORT mem_map_dest_forward ; N: forward | ||
| 1961 | |||
| 1962 | ; | ||
| 1963 | ; backward move : calculate last logical page# and offset | ||
| 1964 | ; | ||
| 1965 | mov ecx, gs:[bx.mem_region_length] | ||
| 1966 | movzx edi, gs:[bx.mem_dest.mem_initial_offset] | ||
| 1967 | dec edi | ||
| 1968 | add ecx, edi | ||
| 1969 | push ecx | ||
| 1970 | and ecx, 00003fffh | ||
| 1971 | mov edi, ecx ; new offset | ||
| 1972 | pop ecx | ||
| 1973 | shr ecx, 14 ; / 16K = # of pages | ||
| 1974 | add dx, cx ; last emm page# | ||
| 1975 | |||
| 1976 | mem_map_dest_forward: | ||
| 1977 | push dx ; put current dest logical page# on stack | ||
| 1978 | ; | ||
| 1979 | ; prepare to map | ||
| 1980 | ; | ||
| 1981 | push ax | ||
| 1982 | push bx | ||
| 1983 | |||
| 1984 | push dx | ||
| 1985 | mov dx, gs:[bx.mem_dest.mem_handle] | ||
| 1986 | Handle2HandlePtr | ||
| 1987 | pop bx | ||
| 1988 | mov ax, 1 ; 2nd page frame | ||
| 1989 | call map_page | ||
| 1990 | jc mem_mapping_error_3_pop ; pop out dest seg_page | ||
| 1991 | |||
| 1992 | ; contruct GDT entry for EMM2_GSEL for ES:0 | ||
| 1993 | ; | ||
| 1994 | mov ax, [PF_Base] | ||
| 1995 | add ax, 0400h ; 2nd page frame segment | ||
| 1996 | xor dx, dx ; offset 0 | ||
| 1997 | Set_EMM_GDT EMM2_GSEL | ||
| 1998 | mov es, bx ; ES:DI <-- dest address | ||
| 1999 | |||
| 2000 | pop bx | ||
| 2001 | pop ax | ||
| 2002 | |||
| 2003 | ; | ||
| 2004 | ; setup source | ||
| 2005 | ; | ||
| 2006 | mem_set_source: | ||
| 2007 | cmp gs:[bx.mem_source.mem_memory_type], 0 ; Q: conv mem ? | ||
| 2008 | jnz mem_map_source ; N: map in emm page | ||
| 2009 | ; | ||
| 2010 | ; conv memory : setup starting address of source (always forward) | ||
| 2011 | ; | ||
| 2012 | mov cx, gs:[bx.mem_source.mem_initial_seg_page] | ||
| 2013 | mov dx, gs:[bx.mem_source.mem_initial_offset] ; CX:DX <-- source address | ||
| 2014 | |||
| 2015 | push ax | ||
| 2016 | push bx | ||
| 2017 | push es | ||
| 2018 | mov ax, cx ; AX:DX <-- first byte | ||
| 2019 | Set_EMM_GDT EMM1_GSEL | ||
| 2020 | mov ds, bx | ||
| 2021 | xor si, si | ||
| 2022 | pop es | ||
| 2023 | pop bx | ||
| 2024 | pop ax | ||
| 2025 | push 0ffffh ; fake a logical page# | ||
| 2026 | jmp short mem_set_done | ||
| 2027 | |||
| 2028 | mem_map_source: | ||
| 2029 | ; | ||
| 2030 | ; emm memory : find out starting address of dest | ||
| 2031 | ; | ||
| 2032 | mov dx, gs:[bx.mem_source.mem_initial_seg_page] ; initial logical page# | ||
| 2033 | mov si, gs:[bx.mem_source.mem_initial_offset] ; inital offset | ||
| 2034 | |||
| 2035 | test al, Backward_Copy_Flag ; Q: Backward copy ? | ||
| 2036 | jz SHORT mem_map_source_forward ; N: forward | ||
| 2037 | |||
| 2038 | ; | ||
| 2039 | ; backward move : calculate last logical page# and offset | ||
| 2040 | ; | ||
| 2041 | mov ecx, gs:[bx.mem_region_length] | ||
| 2042 | movzx esi, gs:[bx.mem_source.mem_initial_offset] | ||
| 2043 | dec esi | ||
| 2044 | add ecx, esi | ||
| 2045 | push ecx | ||
| 2046 | and ecx, 00003fffh | ||
| 2047 | mov esi, ecx ; new offset | ||
| 2048 | pop ecx | ||
| 2049 | shr ecx, 14 ; / 16K = # of pages | ||
| 2050 | add dx, cx ; last emm page# | ||
| 2051 | |||
| 2052 | mem_map_source_forward: | ||
| 2053 | push dx ; put current source logical page# on stack | ||
| 2054 | ; | ||
| 2055 | ; prepare to map | ||
| 2056 | ; | ||
| 2057 | push ax | ||
| 2058 | push bx | ||
| 2059 | |||
| 2060 | push dx | ||
| 2061 | mov dx, gs:[bx.mem_source.mem_handle] | ||
| 2062 | Handle2HandlePtr | ||
| 2063 | pop bx | ||
| 2064 | mov ax, 0 ; 1st page frame | ||
| 2065 | call map_page | ||
| 2066 | jc mem_mapping_error_4_pop ; pop out dest and source seg_page | ||
| 2067 | |||
| 2068 | ; contruct GDT entry for EMM1_GSEL for DS:0 | ||
| 2069 | ; | ||
| 2070 | mov ax, [PF_Base] ; 1st page frame segment | ||
| 2071 | xor dx, dx ; offset 0 | ||
| 2072 | push es | ||
| 2073 | Set_EMM_GDT EMM1_GSEL | ||
| 2074 | pop es ; ES:0 <-- GDT | ||
| 2075 | mov ds, bx ; ES:DI <-- dest address | ||
| 2076 | |||
| 2077 | pop bx | ||
| 2078 | pop ax | ||
| 2079 | |||
| 2080 | ; DS:SI <-- source address | ||
| 2081 | ; ES:DI <-- dest address | ||
| 2082 | |||
| 2083 | mem_set_done: | ||
| 2084 | mov edx, gs:[bx.mem_region_length] ; total length to move/xchg | ||
| 2085 | |||
| 2086 | ; | ||
| 2087 | ; main move/exchange loop | ||
| 2088 | ; | ||
| 2089 | mem_loop: | ||
| 2090 | mov ecx, cr3 | ||
| 2091 | mov cr3, ecx ; flush TLB after each map loop | ||
| 2092 | |||
| 2093 | mov ecx, 4000h ; maximum length to move/xchg | ||
| 2094 | ; in one mapping (<16K) | ||
| 2095 | cmp gs:[bx.mem_source.mem_memory_type], 0 ; Q: conv mem ? | ||
| 2096 | jnz mem_source_is_emm ; N: check dest | ||
| 2097 | sub cx, di ; CX <-- length to move/xchg | ||
| 2098 | jmp short mem_calculate_length | ||
| 2099 | mem_source_is_emm: | ||
| 2100 | cmp gs:[bx.mem_dest.mem_memory_type], 0 ; Q: conv mem ? | ||
| 2101 | jnz mem_both_are_emm ; N: find out which | ||
| 2102 | ; emm has less | ||
| 2103 | ; to move/exchange | ||
| 2104 | sub cx, si ; CX <-- length to move/xchg | ||
| 2105 | jmp short mem_calculate_length | ||
| 2106 | mem_both_are_emm: | ||
| 2107 | test al, Backward_Copy_Flag ; Q:backward copy ? | ||
| 2108 | jz SHORT mem_2_emm_forward ; N:forward | ||
| 2109 | mov cx, si | ||
| 2110 | inc cx | ||
| 2111 | cmp si, di ; Q:si<di ? (min(si,di)) | ||
| 2112 | jb short mem_calculate_length ; Y: use si | ||
| 2113 | mov cx, di ; N: use di | ||
| 2114 | inc cx | ||
| 2115 | jmp short mem_calculate_length | ||
| 2116 | |||
| 2117 | mem_2_emm_forward: | ||
| 2118 | cmp si, di ; Q:si>di ? (max(si,di)) | ||
| 2119 | ja mem_si_gt_di ; Y: use si | ||
| 2120 | sub cx, di ; N: use di | ||
| 2121 | jmp short mem_calculate_length | ||
| 2122 | mem_si_gt_di: | ||
| 2123 | sub cx, si ; si>di | ||
| 2124 | |||
| 2125 | mem_calculate_length: | ||
| 2126 | cmp ecx, edx ; Q: bytes in this batch > total | ||
| 2127 | jbe mem_do_move_xchg ; N: go ahead to move/xchg | ||
| 2128 | mov ecx, edx ; Y: use total instead | ||
| 2129 | |||
| 2130 | ; | ||
| 2131 | ; move/xchg loop | ||
| 2132 | ; | ||
| 2133 | mem_do_move_xchg: | ||
| 2134 | sub edx, ecx ; Adjust total first | ||
| 2135 | |||
| 2136 | test al, 1 ; Q: Is this an exchange? | ||
| 2137 | jnz SHORT mem_exchange ; Y: Do it | ||
| 2138 | test al, Backward_Copy_Flag ; N: Q:Is this backward copy ? | ||
| 2139 | jz SHORT mem_move_forward ; N: forward | ||
| 2140 | ; | ||
| 2141 | ; memory move backward | ||
| 2142 | ; | ||
| 2143 | rep movsb | ||
| 2144 | jmp mem_next_round | ||
| 2145 | ; | ||
| 2146 | ; memory move forward | ||
| 2147 | ; | ||
| 2148 | mem_move_forward: | ||
| 2149 | push eax | ||
| 2150 | mov eax, ecx | ||
| 2151 | shr ecx, 2 ; ECX = # DWORDS to copy | ||
| 2152 | rep movsd ; Move the DWORDS | ||
| 2153 | mov ecx, eax | ||
| 2154 | and ecx, 00000003h ; ECX = # BYTES left to copy | ||
| 2155 | rep movsb ; Move the BYTES | ||
| 2156 | pop eax | ||
| 2157 | jmp short mem_next_round | ||
| 2158 | ; | ||
| 2159 | ; momory exchange | ||
| 2160 | ; | ||
| 2161 | mem_exchange: | ||
| 2162 | push dx | ||
| 2163 | push ax | ||
| 2164 | push bx | ||
| 2165 | push ecx ; Save total # bytes on stack | ||
| 2166 | shr ecx, 2 ; ECX = # DWORDS to exchange | ||
| 2167 | jecxz mem_xchg_bytes ; Exit if no DWORDS left | ||
| 2168 | mov dx, 4 ; Size of DWORD | ||
| 2169 | mem_xchg_dword_loop: | ||
| 2170 | mov eax, [si] | ||
| 2171 | mov ebx, es:[di] | ||
| 2172 | mov es:[di], eax | ||
| 2173 | mov [si], ebx | ||
| 2174 | add si, dx | ||
| 2175 | add di, dx | ||
| 2176 | loop mem_xchg_dword_loop ; Loop until all DWORDS exchanged | ||
| 2177 | mem_xchg_bytes: | ||
| 2178 | pop ecx | ||
| 2179 | and ecx, 00000003h ; ECX = # BYTES left to exchange | ||
| 2180 | jecxz mem_xchg_done ; Exit if no DWORDS left | ||
| 2181 | mem_xchg_byte_loop: | ||
| 2182 | mov al, [si] | ||
| 2183 | mov bl, es:[di] | ||
| 2184 | mov es:[di], al | ||
| 2185 | mov [si], bl | ||
| 2186 | inc si | ||
| 2187 | inc di | ||
| 2188 | loop mem_xchg_byte_loop ; Loop until all BYTES exchanged | ||
| 2189 | mem_xchg_done: | ||
| 2190 | pop bx | ||
| 2191 | pop ax | ||
| 2192 | pop dx ; DONE!!!! | ||
| 2193 | |||
| 2194 | ; | ||
| 2195 | ; prepare for next iteration | ||
| 2196 | ; | ||
| 2197 | mem_next_round: | ||
| 2198 | ; | ||
| 2199 | ; get source and dest's current mapped logical page | ||
| 2200 | ; from stack | ||
| 2201 | ; | ||
| 2202 | pop cx ; source logical page# | ||
| 2203 | shl ecx, 16 ; put in high word | ||
| 2204 | pop cx ; dest logical page# | ||
| 2205 | |||
| 2206 | or edx, edx ; Q: all done ? | ||
| 2207 | jz mem_exit ; Y: restore context first | ||
| 2208 | |||
| 2209 | ; fix dest addresses | ||
| 2210 | ; | ||
| 2211 | cmp gs:[bx.mem_dest.mem_memory_type], 0 ; Q: conv mem ? | ||
| 2212 | jnz mem_map_next_dest ; N: map next page | ||
| 2213 | normalize ES,DI | ||
| 2214 | jmp mem_check_source | ||
| 2215 | |||
| 2216 | mem_map_next_dest: | ||
| 2217 | cmp di, 4000h ; Q: di expires (forward)? | ||
| 2218 | je short mem_map_next_dest_forward ; Y: | ||
| 2219 | cmp di, 0ffffh ; Q: di expires (backward) ? | ||
| 2220 | jne short mem_check_source ; N: go check source | ||
| 2221 | |||
| 2222 | mov di, 3fffh ; set di for next round | ||
| 2223 | dec cx ; next logical page | ||
| 2224 | jmp SHORT mem_map_next_dest_do_map | ||
| 2225 | |||
| 2226 | mem_map_next_dest_forward: | ||
| 2227 | xor di, di ; clear di for next round | ||
| 2228 | inc cx ; next logical page | ||
| 2229 | |||
| 2230 | ; | ||
| 2231 | ; map in the next dest page | ||
| 2232 | ; | ||
| 2233 | mem_map_next_dest_do_map: | ||
| 2234 | push dx | ||
| 2235 | push ax | ||
| 2236 | push bx | ||
| 2237 | push ecx | ||
| 2238 | push ds | ||
| 2239 | push fs | ||
| 2240 | pop ds | ||
| 2241 | mov dx, gs:[bx.mem_dest.mem_handle] | ||
| 2242 | Handle2HandlePtr | ||
| 2243 | mov ax, 1 ; 2nd page frame | ||
| 2244 | mov bx, cx | ||
| 2245 | call map_page | ||
| 2246 | pop ds | ||
| 2247 | pop ecx | ||
| 2248 | pop bx | ||
| 2249 | pop ax | ||
| 2250 | pop dx | ||
| 2251 | jc mem_mapping_error | ||
| 2252 | |||
| 2253 | ; | ||
| 2254 | ; fix source addresses | ||
| 2255 | ; | ||
| 2256 | mem_check_source: | ||
| 2257 | ror ecx, 16 ; get source log page in low word | ||
| 2258 | cmp gs:[bx.mem_source.mem_memory_type], 0 ; Q: conv mem ? | ||
| 2259 | jnz mem_map_next_source ; N: map next page | ||
| 2260 | normalize DS,SI | ||
| 2261 | jmp mem_check_done | ||
| 2262 | |||
| 2263 | mem_map_next_source: | ||
| 2264 | cmp si, 4000h ; Q: si expires (forward)? | ||
| 2265 | je short mem_map_next_source_forward ; Y: | ||
| 2266 | cmp si, 0ffffh ; Q: si expires (backward) ? | ||
| 2267 | jne short mem_check_done ; N: all done | ||
| 2268 | |||
| 2269 | mov si, 3fffh ; set si for next round | ||
| 2270 | dec cx ; next logical page | ||
| 2271 | jmp SHORT mem_map_next_source_do_map | ||
| 2272 | |||
| 2273 | mem_map_next_source_forward: | ||
| 2274 | xor si, si ; clear si for next round | ||
| 2275 | inc cx ; next logical page | ||
| 2276 | |||
| 2277 | ; | ||
| 2278 | ; map in the next source page | ||
| 2279 | ; | ||
| 2280 | mem_map_next_source_do_map: | ||
| 2281 | push dx | ||
| 2282 | push ax | ||
| 2283 | push bx | ||
| 2284 | push ecx | ||
| 2285 | push ds | ||
| 2286 | push fs | ||
| 2287 | pop ds | ||
| 2288 | mov dx, gs:[bx.mem_source.mem_handle] | ||
| 2289 | Handle2HandlePtr | ||
| 2290 | mov ax, 0 ; 1st page frame | ||
| 2291 | mov bx, cx | ||
| 2292 | call map_page | ||
| 2293 | pop ds | ||
| 2294 | pop ecx | ||
| 2295 | pop bx | ||
| 2296 | pop ax | ||
| 2297 | pop dx | ||
| 2298 | jc mem_mapping_error | ||
| 2299 | ; | ||
| 2300 | ; push back the logical pages on stack for | ||
| 2301 | ; next iternation : dest first, then source | ||
| 2302 | ; | ||
| 2303 | mem_check_done: | ||
| 2304 | ror ecx, 16 | ||
| 2305 | push cx | ||
| 2306 | ror ecx, 16 | ||
| 2307 | push cx | ||
| 2308 | jmp mem_loop | ||
| 2309 | |||
| 2310 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 2311 | ; | ||
| 2312 | ; conv to conv | ||
| 2313 | ; | ||
| 2314 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 2315 | mem_conv_to_conv: | ||
| 2316 | ; | ||
| 2317 | ; check validility of source | ||
| 2318 | ; | ||
| 2319 | lea di, [si.mem_source] | ||
| 2320 | call validate_for_Move_or_Exchange | ||
| 2321 | or ah, ah | ||
| 2322 | jnz mem_error_exit | ||
| 2323 | ; | ||
| 2324 | ; check validility of dest | ||
| 2325 | ; | ||
| 2326 | lea di, [si.mem_dest] | ||
| 2327 | call validate_for_Move_or_Exchange | ||
| 2328 | or ah, ah | ||
| 2329 | jnz mem_error_exit | ||
| 2330 | |||
| 2331 | push ax ; save subfunction | ||
| 2332 | push [si.mem_region_length] ; save length | ||
| 2333 | |||
| 2334 | movzx eax, [si.mem_dest.mem_initial_seg_page] | ||
| 2335 | movzx edx, [si.mem_dest.mem_initial_offset] | ||
| 2336 | mov edi, eax | ||
| 2337 | shl edi, 4 | ||
| 2338 | add edi, edx ; EDI <-- dest linear addr | ||
| 2339 | Set_EMM_GDT EMM2_GSEL | ||
| 2340 | Set_Page_Gran EMM2_GSEL | ||
| 2341 | push bx ; save dest GDT selector | ||
| 2342 | |||
| 2343 | movzx eax, [si.mem_source.mem_initial_seg_page] | ||
| 2344 | movzx edx, [si.mem_source.mem_initial_offset] | ||
| 2345 | mov esi, eax | ||
| 2346 | shl esi, 4 | ||
| 2347 | add esi, edx ; ESI <-- source linear addr | ||
| 2348 | Set_EMM_GDT EMM1_GSEL | ||
| 2349 | Set_Page_Gran EMM1_GSEL | ||
| 2350 | mov ds, bx | ||
| 2351 | |||
| 2352 | pop es ; recover dest GDT sel | ||
| 2353 | pop ecx ; recover length | ||
| 2354 | pop ax ; recover subfunction | ||
| 2355 | ; | ||
| 2356 | ; test for overlapping transfer | ||
| 2357 | ; | ||
| 2358 | mov byte ptr [bp.rAX+1], VALID_OVERLAP ; assume valid overlap | ||
| 2359 | sub edi, esi ; EDI = Source - Destination | ||
| 2360 | jg SHORT mem_dest_gt_source_2 ; Don't negate if Dest > Source | ||
| 2361 | or al, Source_GT_Dest_Flag ; Set flag to note Source > Dest | ||
| 2362 | neg edi ; Absolute value of EDI | ||
| 2363 | mem_dest_gt_source_2: | ||
| 2364 | mov ebx, edi ; Use EBX instead | ||
| 2365 | cmp ebx, ecx ; Q: Is there an overlap? | ||
| 2366 | jae SHORT mem_no_overlap_2 ; N: Continue | ||
| 2367 | test al, 1 ; Q: Is this an exchange? | ||
| 2368 | jnz mem_inv_overlap ; Y: Error -- Cant overlap xchg | ||
| 2369 | or al, Overlap_Flag ; N: Note this for later | ||
| 2370 | test al, Source_GT_Dest_Flag ; Q: Is it gonna be backward copy | ||
| 2371 | jnz mem_no_overlap_2 ; N: Continue | ||
| 2372 | or al, Backward_Copy_Flag ; Y: Note for later | ||
| 2373 | |||
| 2374 | mov edx, (not 1)+1 ; increment value of -1 (2's compliment of 4) | ||
| 2375 | mov esi, ecx ; Fix ESI and EDI for reverse copy | ||
| 2376 | dec esi | ||
| 2377 | mov edi, esi | ||
| 2378 | jmp short mem_conv_copy | ||
| 2379 | |||
| 2380 | mem_no_overlap_2: | ||
| 2381 | mov byte ptr [ebp.rAX+1], OK ; Everything worked OK | ||
| 2382 | mov edx, 1 ; increment value of 1 | ||
| 2383 | xor esi, esi ; DS:ESI <-- source addr | ||
| 2384 | xor edi, edi ; ES:EDI <-- dest addr | ||
| 2385 | |||
| 2386 | test al, 1 ; Q:copy ? | ||
| 2387 | jnz mem_conv_xchg ; N:go do exchange | ||
| 2388 | |||
| 2389 | mem_conv_copy: | ||
| 2390 | or ebx, ebx | ||
| 2391 | je mem_valid_overlap ; WEIRD!!! -- Move to same place! | ||
| 2392 | |||
| 2393 | jecxz mem_conv_done | ||
| 2394 | mem_conv_copy_loop: | ||
| 2395 | mov bl, [esi] | ||
| 2396 | mov es:[edi], bl | ||
| 2397 | add esi, edx | ||
| 2398 | add edi, edx | ||
| 2399 | dec ecx | ||
| 2400 | jnz mem_conv_copy_loop | ||
| 2401 | jmp mem_conv_done ; DONE!!!! | ||
| 2402 | |||
| 2403 | mem_conv_xchg: | ||
| 2404 | jecxz mem_conv_done | ||
| 2405 | mem_conv_xchg_loop: | ||
| 2406 | mov al, [esi] | ||
| 2407 | mov bl, es:[edi] | ||
| 2408 | mov es:[edi], al | ||
| 2409 | mov [esi], bl | ||
| 2410 | inc esi | ||
| 2411 | inc edi | ||
| 2412 | dec ecx | ||
| 2413 | jnz mem_conv_xchg_loop ; Loop until all BYTES exchanged | ||
| 2414 | mem_conv_done: | ||
| 2415 | Set_Byte_Gran EMM1_GSEL ; make sure EMM1_GSEL and | ||
| 2416 | Set_Byte_Gran EMM2_GSEL ; EMM2_GSEL are Byte Granulated | ||
| 2417 | ret | ||
| 2418 | |||
| 2419 | mem_error_exit: | ||
| 2420 | cld | ||
| 2421 | mov byte ptr [bp.rAX+1], ah ; error code already set in ah | ||
| 2422 | ret | ||
| 2423 | mem_valid_overlap: | ||
| 2424 | mov byte ptr [bp.rAX+1], VALID_OVERLAP | ||
| 2425 | ret | ||
| 2426 | mem_no_error: | ||
| 2427 | mov byte ptr [bp.rAX+1], OK | ||
| 2428 | ret | ||
| 2429 | |||
| 2430 | mem_inv_sub: | ||
| 2431 | mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION | ||
| 2432 | ret | ||
| 2433 | mem_inv_region_len: | ||
| 2434 | mov byte ptr [bp.rAX+1], INVALID_REGION_LENGTH | ||
| 2435 | ret | ||
| 2436 | mem_bad_memory_types: | ||
| 2437 | mov byte ptr [bp.rAX+1], INVALID_MEMORY_TYPE | ||
| 2438 | ret | ||
| 2439 | mem_inv_overlap: | ||
| 2440 | mov byte ptr [bp.rAX+1], OVERLAPPING_EXCHANGE | ||
| 2441 | ret | ||
| 2442 | ; | ||
| 2443 | ; discard old ax,bx,source seg_page#,dest seg_page# | ||
| 2444 | ; | ||
| 2445 | mem_mapping_error_4_pop: | ||
| 2446 | pop bx | ||
| 2447 | mem_mapping_error_3_pop: | ||
| 2448 | pop bx | ||
| 2449 | pop bx | ||
| 2450 | pop bx | ||
| 2451 | mem_mapping_error: | ||
| 2452 | mov eax, cr3 ; Always clear TLB, we may have | ||
| 2453 | mov cr3, eax ; mapped pages before an error | ||
| 2454 | ; | ||
| 2455 | ; all done, need to restore context of physical page frames | ||
| 2456 | ; | ||
| 2457 | mem_exit: | ||
| 2458 | push fs ; get DGROUP back into DS | ||
| 2459 | pop ds | ||
| 2460 | get_FRS_Window BX | ||
| 2461 | pop word ptr [bx+2] | ||
| 2462 | pop word ptr [bx] | ||
| 2463 | cld ; string forward again | ||
| 2464 | jmp _set_windows ; remap all pages | ||
| 2465 | |||
| 2466 | _MoveExchangeMemory endp | ||
| 2467 | |||
| 2468 | |||
| 2469 | ;****************************************************************************** | ||
| 2470 | ; | ||
| 2471 | ; validate_for_Move_Or_Exchange | ||
| 2472 | ; | ||
| 2473 | ; This procedure is called by _MoveExchangeMemory to validate | ||
| 2474 | ; varies parameter on the memeory descriptor structure. | ||
| 2475 | ; It is called once for the source and once for the | ||
| 2476 | ; destination memory descriptor structures. | ||
| 2477 | ; | ||
| 2478 | ; ENTRY: | ||
| 2479 | ; CX = move length | ||
| 2480 | ; DS:DI = Move/Exchange memory descriptor data structure (source or dest) | ||
| 2481 | ; FS = MEMM's data segment | ||
| 2482 | ; EXIT: | ||
| 2483 | ; AH = Status (0 = No error) -- AL is preserved | ||
| 2484 | ; | ||
| 2485 | ; USES: | ||
| 2486 | ; DI, Flags | ||
| 2487 | ; AL and all other registers are preserved | ||
| 2488 | ; | ||
| 2489 | ;============================================================================== | ||
| 2490 | |||
| 2491 | validate_for_Move_Or_Exchange PROC NEAR | ||
| 2492 | |||
| 2493 | push edx ; Used as temporary variable | ||
| 2494 | push eax | ||
| 2495 | |||
| 2496 | mov dl, [di.mem_memory_type] | ||
| 2497 | or dl, dl ; Q: Conventional memory? | ||
| 2498 | jz ME_Map_Conventional ; Y: Nothing to map | ||
| 2499 | cmp dl, 1 ; Q: Expanded memory? | ||
| 2500 | jne ME_Map_Inv_Mem ; N: Invalid memory type | ||
| 2501 | ; Y: EMM memory -- Must map it | ||
| 2502 | mov dx, [di.mem_handle] ; Get the handle | ||
| 2503 | |||
| 2504 | push ds ; validate_handle expect DS | ||
| 2505 | push fs ; points to dgroup | ||
| 2506 | pop ds | ||
| 2507 | Validate_Handle ME_Map_Inv_Handle ; check it | ||
| 2508 | pop ds | ||
| 2509 | |||
| 2510 | xchg bx, dx | ||
| 2511 | mov ax, fs:[bx.ht_count] ; EAX = # pages in handle | ||
| 2512 | xchg bx, dx | ||
| 2513 | cmp ax,[di.mem_initial_seg_page];Q: Is initial page in range | ||
| 2514 | jbe ME_Map_Invalid_log_page ; N: Error | ||
| 2515 | cmp [di.mem_initial_offset], 04000h; Q: Is offset unreasonable? | ||
| 2516 | jae ME_Map_Invalid_Offset ; Y: Error | ||
| 2517 | |||
| 2518 | movzx edx, [di.mem_initial_offset] | ||
| 2519 | add edx, ecx | ||
| 2520 | add edx, 16 * 1024 - 1 ; round up to nearest emm page boundary | ||
| 2521 | shr edx, 14 ; / 16K = # of emm pages | ||
| 2522 | add dx, [di.mem_initial_seg_page] ; last emm page of move/exchange | ||
| 2523 | cmp dx, ax | ||
| 2524 | ja ME_Map_Not_Enough_EMM ;Q: Is last page in range | ||
| 2525 | jmp short ME_Map_OK ; N: error | ||
| 2526 | |||
| 2527 | ME_Map_Conventional: | ||
| 2528 | movzx edx, word ptr [di.mem_initial_seg_page] | ||
| 2529 | shl edx, 4 | ||
| 2530 | movzx edi, word ptr [di.mem_initial_offset] | ||
| 2531 | add edx, edi ; EDX --> Conven mem to move/exch | ||
| 2532 | mov edi, edx ; Use EDI for test | ||
| 2533 | add edi, ecx ; EDI = Base + Move length | ||
| 2534 | cmp edi, 100000h ; Q: Is there wraparound? | ||
| 2535 | jae SHORT ME_Map_Inv_Wraparound ; Y: Error | ||
| 2536 | cmp fs:[_page_frame_pages], 0 ; Is there a page frame? | ||
| 2537 | je short No_EMM_Overlap ; no, no problem | ||
| 2538 | cmp edi, 0E0000h ; Q: Is move ABOVE EMM area? | ||
| 2539 | jae SHORT No_EMM_Overlap ; Y: That's not a problem | ||
| 2540 | movzx eax, fs:[PF_Base] ; Where page frame starts | ||
| 2541 | shl eax, 4 | ||
| 2542 | cmp edi, eax ; Q: Does move run into EMM area? | ||
| 2543 | ja SHORT ME_Map_Inv_Overlap ; Y: Error | ||
| 2544 | No_EMM_Overlap: | ||
| 2545 | ; N: Everything is okie dokie | ||
| 2546 | ME_Map_OK: | ||
| 2547 | pop eax | ||
| 2548 | pop edx | ||
| 2549 | mov ah, OK | ||
| 2550 | ret | ||
| 2551 | |||
| 2552 | ME_Map_Inv_Mem: | ||
| 2553 | pop eax | ||
| 2554 | pop edx | ||
| 2555 | mov ah, INVALID_MEMORY_TYPE | ||
| 2556 | ret | ||
| 2557 | |||
| 2558 | ME_Map_Inv_Handle: | ||
| 2559 | pop ds | ||
| 2560 | pop eax | ||
| 2561 | pop edx | ||
| 2562 | mov ah, INVALID_HANDLE | ||
| 2563 | ret | ||
| 2564 | |||
| 2565 | ME_Map_Invalid_log_page: | ||
| 2566 | pop eax | ||
| 2567 | pop edx | ||
| 2568 | mov ah, LOG_PAGE_RANGE | ||
| 2569 | ret | ||
| 2570 | |||
| 2571 | ME_Map_Invalid_Offset: | ||
| 2572 | pop eax | ||
| 2573 | pop edx | ||
| 2574 | mov ah, INVALID_OFFSET | ||
| 2575 | ret | ||
| 2576 | |||
| 2577 | ME_Map_Not_Enough_EMM: | ||
| 2578 | pop eax | ||
| 2579 | pop edx | ||
| 2580 | mov ah, INSUFFICIENT_EMM_PAGES | ||
| 2581 | ret | ||
| 2582 | |||
| 2583 | ME_Map_Inv_Overlap: | ||
| 2584 | pop eax | ||
| 2585 | pop edx | ||
| 2586 | mov ah, CONVENTIONAL_EMM_OVERLAP | ||
| 2587 | ret | ||
| 2588 | |||
| 2589 | ME_Map_Inv_Wraparound: | ||
| 2590 | pop eax | ||
| 2591 | pop edx | ||
| 2592 | mov ah, INVALID_WRAPAROUND | ||
| 2593 | ret | ||
| 2594 | |||
| 2595 | validate_for_Move_Or_Exchange ENDP | ||
| 2596 | |||
| 2597 | |||
| 2598 | page | ||
| 2599 | ;*********************************************** | ||
| 2600 | ; | ||
| 2601 | ; _AlternateMapRegisterSet - handle alternative register sets | ||
| 2602 | ; | ||
| 2603 | ; This routine switches the current register set or stores | ||
| 2604 | ; the current page mapping context to an external save area and/or | ||
| 2605 | ; restores the current page mapping context from an external save area. | ||
| 2606 | ; | ||
| 2607 | ; ENTRY: PROTECTED MODE ONLY | ||
| 2608 | ; AH = 5Bh = Alternate Map Register Set function | ||
| 2609 | ; AL = SUBFUNCTION CODE | ||
| 2610 | ; AL = 0 => Get Alternate Map Register Set | ||
| 2611 | ; AL = 1 => Set Alternate Map Register Set | ||
| 2612 | ; AL = 2 => Get and Set Alternate Map Register Set | ||
| 2613 | ; AL = 3 => Get Alternate Map Save Array size | ||
| 2614 | ; AL = 4 => Allocate Alternate Map Register Set | ||
| 2615 | ; AL = 5 => Deallocate Alternate Map Register Set | ||
| 2616 | ; AL = 6 => Enable DMA on Alternate Map Register Set | ||
| 2617 | ; AL = 7 => Disable DMA on Alternate Map Register Set | ||
| 2618 | ; See sub-functions for individual ENTRY registers | ||
| 2619 | ; SS:[EBP] -> regp stack frame | ||
| 2620 | ; DS = DGROUP | ||
| 2621 | ; | ||
| 2622 | ; EXIT: from individual sub-function or error with | ||
| 2623 | ; AH = INVALID_SUBFUNCTION | ||
| 2624 | ; | ||
| 2625 | ; USED: EAX,ESI | ||
| 2626 | ; | ||
| 2627 | ;*********************************************** | ||
| 2628 | Dword_Align _TEXT | ||
| 2629 | _AlternateMapRegisterSet proc near | ||
| 2630 | cmp [_OSEnabled], OS_DISABLED | ||
| 2631 | jae short AMRS_NotAllowed ; Disabled by OS | ||
| 2632 | cmp al, 08h ; Valid sub-function? | ||
| 2633 | ja short AMRS_invalid | ||
| 2634 | cld ; Done for all sub-functions | ||
| 2635 | mov byte ptr [bp.rAX+1], OK ; Assume success! | ||
| 2636 | movzx esi, al ; get offset to function dispatch | ||
| 2637 | shl si, 1 | ||
| 2638 | jmp CS:AMRS_map[si] ; go to relevant sub-function | ||
| 2639 | ; Return directly or to AMRS_exit... | ||
| 2640 | AMRS_exit: ; Exit with AH already set | ||
| 2641 | ret | ||
| 2642 | |||
| 2643 | AMRS_NotAllowed: | ||
| 2644 | mov byte ptr [bp.rAX+1], ACCESS_DENIED | ||
| 2645 | ret | ||
| 2646 | |||
| 2647 | AMRS_invalid: | ||
| 2648 | mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION | ||
| 2649 | ret ; Error return! | ||
| 2650 | |||
| 2651 | AMRS_bad_src: | ||
| 2652 | mov byte ptr [bp.rAX+1], SOURCE_CORRUPTED | ||
| 2653 | ret ; Error return! | ||
| 2654 | |||
| 2655 | AMRS_noDMA: | ||
| 2656 | mov byte ptr [bp.rAX+1], FRSET_NO_DMA | ||
| 2657 | ret ; Error return! | ||
| 2658 | |||
| 2659 | Dword_Align _TEXT | ||
| 2660 | AMRS_map dw _TEXT:AMRS_get | ||
| 2661 | dw _TEXT:AMRS_set | ||
| 2662 | dw _TEXT:AMRS_size | ||
| 2663 | dw _TEXT:AMRS_allocate | ||
| 2664 | dw _TEXT:AMRS_deallocate | ||
| 2665 | ; For now... | ||
| 2666 | dw _TEXT:AMRS_noDMA ; AMRS_DMAallocate | ||
| 2667 | dw _TEXT:AMRS_noDMA ; AMRS_DMAassign | ||
| 2668 | dw _TEXT:AMRS_noDMA ; AMRS_DMAdeassign | ||
| 2669 | dw _TEXT:AMRS_noDMA ; AMRS_DMAfree | ||
| 2670 | |||
| 2671 | page | ||
| 2672 | ;*********************************************** | ||
| 2673 | ; | ||
| 2674 | ; AMRS_get - get the current 'fast' register set | ||
| 2675 | ; | ||
| 2676 | ; ENTRY: on stack | ||
| 2677 | ; SS:[EBP] -> regp stack frame | ||
| 2678 | ; DS = DGROUP | ||
| 2679 | ; | ||
| 2680 | ; EXIT: on stack | ||
| 2681 | ; BL = register set number, | ||
| 2682 | ; state stored in client's buffer if BL == 0 | ||
| 2683 | ; ES:SI set to point to client's buffer | ||
| 2684 | ; return code set on stack | ||
| 2685 | ; | ||
| 2686 | ; USED: EAX, EBX | ||
| 2687 | ; | ||
| 2688 | ; DESCRIPTION: This function returns the current register set number. | ||
| 2689 | ; If it is zero, it returns the save area previously specified | ||
| 2690 | ; | ||
| 2691 | ;----------------------------------------------- | ||
| 2692 | Dword_Align _TEXT | ||
| 2693 | AMRS_get: | ||
| 2694 | mov al, [CurRegSetn] ; Get current set number | ||
| 2695 | mov byte ptr [bp.rBX], al ; to be picked up later | ||
| 2696 | or al, al | ||
| 2697 | jz short AMRS_get0 | ||
| 2698 | ret ; non-zero - all done | ||
| 2699 | AMRS_get0: ; Echo save area address | ||
| 2700 | movzx eax, [EMM_savES] ; saved ES for reg set 0 | ||
| 2701 | mov word ptr [bp.rES], ax | ||
| 2702 | movzx edi, [EMM_savDI] ; saved DI for reg set 0 | ||
| 2703 | mov word ptr [bp.rDI], di | ||
| 2704 | or ax, ax | ||
| 2705 | jnz short AMRS_get2 ; got dest addr | ||
| 2706 | or di, di | ||
| 2707 | jz short AMRS_get1 ; not specified yet | ||
| 2708 | AMRS_get2: | ||
| 2709 | xor dx, dx | ||
| 2710 | Set_EMM_GDT EMM1_GSEL | ||
| 2711 | mov es, bx ; ES:DI <-- temp store | ||
| 2712 | Get_FRS_window SI ; Get pointer to current window | ||
| 2713 | movzx eax, [_cntxt_pages] ; how many pages | ||
| 2714 | stosw ; save size | ||
| 2715 | mov ecx, eax | ||
| 2716 | shr ecx, 1 ; convert to dwords | ||
| 2717 | rep movsd ; save the map | ||
| 2718 | AMRS_get1: | ||
| 2719 | ret | ||
| 2720 | |||
| 2721 | page | ||
| 2722 | ;*********************************************** | ||
| 2723 | ; | ||
| 2724 | ; AMRS_set - set the current 'fast' register set | ||
| 2725 | ; | ||
| 2726 | ; ENTRY: BL = register set number | ||
| 2727 | ; on stack | ||
| 2728 | ; if BL == 0 | ||
| 2729 | ; ES:DI -> buffer containing mappings for register set 0 | ||
| 2730 | ; SS:[EBP] -> regp stack frame | ||
| 2731 | ; DS = DGROUP | ||
| 2732 | ; | ||
| 2733 | ; EXIT: return code set on stack | ||
| 2734 | ; | ||
| 2735 | ; USED: EAX, EBX, ECX, EDX, ESI, EDI | ||
| 2736 | ; | ||
| 2737 | ; DESCRIPTION: This function sets the current register set number. | ||
| 2738 | ; If it is zero, it uses the save area specified in ES:DI. | ||
| 2739 | ; | ||
| 2740 | ;----------------------------------------------- | ||
| 2741 | Dword_Align _TEXT | ||
| 2742 | AMRS_set: | ||
| 2743 | cmp bl, FRS_COUNT ; Validate new Reg Set | ||
| 2744 | jae AMRS_inv_FRS | ||
| 2745 | movzx eax, bl | ||
| 2746 | imul eax, size FRS_struc | ||
| 2747 | xchg ax, bx | ||
| 2748 | lea bx, FRS_array[bx] ; Get pointer to the new Reg Set | ||
| 2749 | cmp [bx.FRS_alloc], 0 ; Make sure it is allocated | ||
| 2750 | xchg ax, bx | ||
| 2751 | je AMRS_undef_FRS ; unallocated, go complain | ||
| 2752 | |||
| 2753 | cmp bl, 0 ; New reg set 0? | ||
| 2754 | je short AMRS_set0 ; yes, always set context | ||
| 2755 | cmp bl, [CurRegSetn] ; Setting the same reg set? | ||
| 2756 | je AMRS_exit ; yes, just return | ||
| 2757 | AMRS_set0: ; Now set up new reg set | ||
| 2758 | mov word ptr [CurRegSet], ax ; Set Current reg. set Offset | ||
| 2759 | mov [CurRegSetn], bl | ||
| 2760 | |||
| 2761 | or bl, bl ; Real register set? | ||
| 2762 | jne _set_windows ; yes, go deal with it | ||
| 2763 | ; no, deal with reg set 0 | ||
| 2764 | mov ax, word ptr [bp.rES] ; Pick up user's pointer | ||
| 2765 | mov [EMM_savES], ax ; and save for AMRS_get | ||
| 2766 | mov dx, word ptr [bp.rDI] | ||
| 2767 | mov [EMM_savDI], dx ; AX:DX <-- regs cntxt restore area | ||
| 2768 | push ax | ||
| 2769 | or ax, dx | ||
| 2770 | pop ax | ||
| 2771 | jz _set_windows ; AX:DX == 0:0 implies no save area | ||
| 2772 | |||
| 2773 | ; construct GDT entry using EMM1_GSEL to access user's FRS buffer | ||
| 2774 | ; | ||
| 2775 | push es | ||
| 2776 | Set_EMM_GDT EMM1_GSEL | ||
| 2777 | pop es | ||
| 2778 | |||
| 2779 | mov fs, bx ; FS:SI <-- FRS buffer | ||
| 2780 | xor si, si | ||
| 2781 | lods word ptr fs:[si] ; get saved count | ||
| 2782 | movzx ecx, [_cntxt_pages] ; what it should be | ||
| 2783 | cmp ax, cx ; Sensible count? | ||
| 2784 | jne _set_windows ; no, restore last context | ||
| 2785 | Get_FRS_window DI | ||
| 2786 | shr ecx, 1 ; size in dwords | ||
| 2787 | push ds ; xchg ds,fs | ||
| 2788 | push fs | ||
| 2789 | pop ds | ||
| 2790 | pop fs ; use DS as default seg. reg. | ||
| 2791 | rep movsd | ||
| 2792 | push ds | ||
| 2793 | push fs | ||
| 2794 | pop ds | ||
| 2795 | pop fs | ||
| 2796 | jmp _set_windows ; set up mappings | ||
| 2797 | |||
| 2798 | page | ||
| 2799 | ;*********************************************** | ||
| 2800 | ; | ||
| 2801 | ; AMRS_size - get the size of the register set 0 save area | ||
| 2802 | ; | ||
| 2803 | ; ENTRY: | ||
| 2804 | ; SS:[EBP] -> regp stack frame | ||
| 2805 | ; DS = DGROUP | ||
| 2806 | ; | ||
| 2807 | ; EXIT: return code set on stack | ||
| 2808 | ; DX = size of the save area | ||
| 2809 | ; | ||
| 2810 | ; USED: none | ||
| 2811 | ; | ||
| 2812 | ; DESCRIPTION: This function returns the size of the save area used | ||
| 2813 | ; for register set 0. | ||
| 2814 | ; | ||
| 2815 | ;----------------------------------------------- | ||
| 2816 | AMRS_size: | ||
| 2817 | movzx eax, [_cntxt_bytes] ; Previously calculated value | ||
| 2818 | mov word ptr [bp.rDX], ax | ||
| 2819 | ret | ||
| 2820 | |||
| 2821 | page | ||
| 2822 | ;*********************************************** | ||
| 2823 | ; | ||
| 2824 | ; AMRS_allocate - allocate a fast register set | ||
| 2825 | ; | ||
| 2826 | ; ENTRY: | ||
| 2827 | ; SS:[EBP] -> regp stack frame | ||
| 2828 | ; DS = DGROUP | ||
| 2829 | ; | ||
| 2830 | ; EXIT: return code set on stack | ||
| 2831 | ; BL = register set number | ||
| 2832 | ; | ||
| 2833 | ; USED: EBX, ESI | ||
| 2834 | ; | ||
| 2835 | ; DESCRIPTION: This function allocates a free register set. | ||
| 2836 | ; | ||
| 2837 | ;----------------------------------------------- | ||
| 2838 | AMRS_allocate: | ||
| 2839 | cmp [FRS_free], 0 ; See if any are free | ||
| 2840 | je short AMRS_noRS ; no, none available | ||
| 2841 | ; Search for first free set | ||
| 2842 | dec [FRS_free] ; We are going to take one | ||
| 2843 | lea di, [FRS_array] ; Start of FRS structures | ||
| 2844 | xor bl, bl ; FRS number | ||
| 2845 | AMRS_search: | ||
| 2846 | cmp [di.FRS_alloc], 0 ; This one free? | ||
| 2847 | je short AMRS_foundRS ; yes, bl has the number | ||
| 2848 | add di, size FRS_struc ; on to the next one | ||
| 2849 | inc bl | ||
| 2850 | cmp bl, FRS_COUNT ; Safety... should never fail | ||
| 2851 | jb short AMRS_search | ||
| 2852 | |||
| 2853 | mov byte ptr [bp.rAX+1], EMM_SW_MALFUNCTION ; Honesty... | ||
| 2854 | ret | ||
| 2855 | |||
| 2856 | AMRS_foundRS: | ||
| 2857 | mov [di.FRS_alloc], 1 ; Allocate it | ||
| 2858 | Get_FRS_Window SI | ||
| 2859 | lea di, [di.FRS_Window] | ||
| 2860 | movzx ecx, [_cntxt_pages] | ||
| 2861 | shr ecx, 1 | ||
| 2862 | rep movsd ; Initialise to current mapping | ||
| 2863 | mov byte ptr [bp.rBX], bl ; Return the number | ||
| 2864 | ret | ||
| 2865 | |||
| 2866 | AMRS_noRS: ; None free; return error | ||
| 2867 | mov byte ptr [bp.rAX+1], NO_MORE_FRSETS | ||
| 2868 | ret | ||
| 2869 | |||
| 2870 | page | ||
| 2871 | ;*********************************************** | ||
| 2872 | ; | ||
| 2873 | ; AMRS_deallocate - deallocate a fast register set | ||
| 2874 | ; | ||
| 2875 | ; ENTRY: BL = register set to deallocate | ||
| 2876 | ; SS:[EBP] -> regp stack frame | ||
| 2877 | ; DS = DGROUP | ||
| 2878 | ; | ||
| 2879 | ; EXIT: return code set on stack | ||
| 2880 | ; | ||
| 2881 | ; USED: EAX | ||
| 2882 | ; | ||
| 2883 | ; DESCRIPTION: This function deallocates a register set. | ||
| 2884 | ; | ||
| 2885 | ;----------------------------------------------- | ||
| 2886 | AMRS_deallocate: | ||
| 2887 | or bl, bl | ||
| 2888 | jz AMRS_exit ; Deallocating 0 is ignored | ||
| 2889 | cmp bl, [CurRegSetn] ; Can't deallocate current set | ||
| 2890 | je short AMRS_undef_FRS | ||
| 2891 | cmp bl, FRS_COUNT | ||
| 2892 | jae short AMRS_undef_FRS ; Invalid Register set | ||
| 2893 | movzx eax, bl | ||
| 2894 | imul eax, size FRS_struc ; Offset into array | ||
| 2895 | xchg ax, bx | ||
| 2896 | cmp FRS_array[bx.FRS_alloc], 0 ; Paranoid... | ||
| 2897 | xchg ax, bx | ||
| 2898 | je short AMRS_undef_FRS ; Not allocated, complain | ||
| 2899 | xchg ax, bx | ||
| 2900 | mov FRS_array[bx.FRS_alloc], 0 ; Mark it free | ||
| 2901 | xchg ax, bx | ||
| 2902 | inc [FRS_free] ; one more set free | ||
| 2903 | ret | ||
| 2904 | |||
| 2905 | AMRS_Inv_FRS: | ||
| 2906 | AMRS_undef_FRS: | ||
| 2907 | mov byte ptr [bp.rAX+1], FRSET_UNDEFINED | ||
| 2908 | ret | ||
| 2909 | |||
| 2910 | _AlternateMapRegisterSet endp | ||
| 2911 | |||
| 2912 | |||
| 2913 | page | ||
| 2914 | ;****************************************************************************** | ||
| 2915 | ; _Get_Key_Val - use the timer to get a random number for OSDisable Key | ||
| 2916 | ; | ||
| 2917 | ; ENTRY DS, ES = DGROUP selectors | ||
| 2918 | ; | ||
| 2919 | ; STACK | ||
| 2920 | ; | ||
| 2921 | ; EXIT EAX has randomish number | ||
| 2922 | ; | ||
| 2923 | ; USES Flags, EAX, EDX | ||
| 2924 | ; | ||
| 2925 | ;------------------------------------------------------------------------------ | ||
| 2926 | _Get_Key_Val proc near | ||
| 2927 | call Get_Counter_Value ; (Who cares about the junk in | ||
| 2928 | mov dx, ax ; the high words...?) | ||
| 2929 | call Get_Counter_Value ; Likely to be very close | ||
| 2930 | mul edx ; Mess it all up! | ||
| 2931 | ret | ||
| 2932 | |||
| 2933 | _Get_Key_Val endp | ||
| 2934 | |||
| 2935 | ;****************************************************************************** | ||
| 2936 | ; | ||
| 2937 | ; NAME: | ||
| 2938 | ; Get_Counter_Value | ||
| 2939 | ; | ||
| 2940 | ; DESCRIPTION: | ||
| 2941 | ; Returns the current system timer counter value | ||
| 2942 | ; | ||
| 2943 | ; ENTRY: | ||
| 2944 | ; Assumes nothing | ||
| 2945 | ; | ||
| 2946 | ; EXIT: | ||
| 2947 | ; AX = Current counter value (High word of EAX NOT CHANGED) | ||
| 2948 | ; | ||
| 2949 | ; USES: | ||
| 2950 | ; Flags | ||
| 2951 | ; | ||
| 2952 | ;------------------------------------------------------------------------------ | ||
| 2953 | |||
| 2954 | Get_Counter_Value PROC NEAR | ||
| 2955 | |||
| 2956 | System_Clock_Port EQU 40h | ||
| 2957 | Sys_Clock_Ctrl_Port EQU 43h | ||
| 2958 | |||
| 2959 | Latch_Counter EQU 0 | ||
| 2960 | |||
| 2961 | mov al, Latch_Counter | ||
| 2962 | out Sys_Clock_Ctrl_Port, al ; Latch the timer counter | ||
| 2963 | jmp $+2 | ||
| 2964 | in al, System_Clock_Port ; Read the LSB | ||
| 2965 | mov ah, al | ||
| 2966 | jmp $+2 | ||
| 2967 | in al, System_Clock_Port ; Read the MSB | ||
| 2968 | xchg ah, al ; AX = Counter value | ||
| 2969 | ret | ||
| 2970 | |||
| 2971 | Get_Counter_Value ENDP | ||
| 2972 | |||
| 2973 | |||
| 2974 | _TEXT ENDS | ||
| 2975 | END | ||
| 2976 | |||
| 2977 | |||
| 2978 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/EMM/EMMSUP.ASM b/v4.0/src/MEMM/EMM/EMMSUP.ASM new file mode 100644 index 0000000..4034e18 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMSUP.ASM | |||
| @@ -0,0 +1,652 @@ | |||
| 1 | page 58,132 | ||
| 2 | ;****************************************************************************** | ||
| 3 | title EMMSUP - EMM support routines | ||
| 4 | ;****************************************************************************** | ||
| 5 | ; | ||
| 6 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 7 | ; | ||
| 8 | ; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 9 | ; EMMLIB.LIB - Expanded Memory Manager Functions Library | ||
| 10 | ; | ||
| 11 | ; Module: EMMSUP - EMM support routines | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date: May 13, 1986 | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 5/13/86 Original Initial _TEXT | ||
| 24 | ; 6/14/86 Added _sotofar routine and removed stack define. | ||
| 25 | ; And added protected mode check to Map_Page (SBP). | ||
| 26 | ; 6/14/86 map_page now sets _current_map(SBP). | ||
| 27 | ; 6/14/86 moved save_current_map and restore_map from C code (SBP) | ||
| 28 | ; 6/14/86 brought SegOffTo24 and SetDescInfo in from LAST code | ||
| 29 | ; segment as local routines(SBP). | ||
| 30 | ; 6/21/86 0.02 cld in copyout (SBP). | ||
| 31 | ; 6/21/86 0.02 MapHandlePage added. | ||
| 32 | ; 6/23/86 0.02 make_addr, sotofar removed. source_addr and dest_addr | ||
| 33 | ; added. | ||
| 34 | ; 6/27/86 0.02 Fix for restore_map. | ||
| 35 | ; 6/28/86 0.02 Name change from CEMM386 to CEMM (SBP). | ||
| 36 | ; 7/06/86 0.04 Changed _emm_page,_emm_free, & _pft386 to ptrs (SBP). | ||
| 37 | ; 7/06/86 0.04 Changed assumes from _DATA to DGROUP (SBP). | ||
| 38 | ; 7/06/86 0.04 Changed internal save area structure (SBP). | ||
| 39 | ; 7/06/86 0.04 moved SavePageMap and RestorePageMap to .ASM (SBP). | ||
| 40 | ; 7/07/86 0.04 moved MapHandlePage,SavePageMap, and RestorePageMap to | ||
| 41 | ; emmp.asm (SBP). | ||
| 42 | ; 5/09/88 1.01 moved routines names_match and flush_tlb from win386 | ||
| 43 | ; 9/01/88 rename SegOffTo24/SetDescInfo to | ||
| 44 | ; SegOffTo24Resident/SetDescInfoResdient and made public | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; | ||
| 47 | ; Functional Description: | ||
| 48 | ; Support routines for emm/386 | ||
| 49 | ; C callable | ||
| 50 | ; | ||
| 51 | ; | ||
| 52 | ;****************************************************************************** | ||
| 53 | .lfcond ; list false conditionals | ||
| 54 | .386p | ||
| 55 | |||
| 56 | ;****************************************************************************** | ||
| 57 | ; P U B L I C S | ||
| 58 | ;****************************************************************************** | ||
| 59 | public _source_addr | ||
| 60 | public _dest_addr | ||
| 61 | public _copyout | ||
| 62 | public _copyin | ||
| 63 | public _wcopy | ||
| 64 | public _wcopyb | ||
| 65 | public _valid_handle | ||
| 66 | public SetDescInfoResident | ||
| 67 | public SegOffTo24Resident | ||
| 68 | ; | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; D E F I N E S | ||
| 71 | ;****************************************************************************** | ||
| 72 | |||
| 73 | include vdmseg.inc | ||
| 74 | include vdmsel.inc | ||
| 75 | include desc.inc | ||
| 76 | include page.inc | ||
| 77 | ; include instr386.inc | ||
| 78 | include emmdef.inc | ||
| 79 | |||
| 80 | FALSE equ 0 | ||
| 81 | TRUE equ not FALSE | ||
| 82 | CR equ 0dh | ||
| 83 | LF equ 0ah | ||
| 84 | |||
| 85 | page | ||
| 86 | ;****************************************************************************** | ||
| 87 | ; E X T E R N A L R E F E R E N C E S | ||
| 88 | ;****************************************************************************** | ||
| 89 | |||
| 90 | _DATA SEGMENT | ||
| 91 | ; | ||
| 92 | ; pointer to entry stack frame | ||
| 93 | ; stored as offset, SS | ||
| 94 | extrn _regp:word | ||
| 95 | |||
| 96 | ; | ||
| 97 | ; current state of mapping registers and # of mapping registers emulated | ||
| 98 | ; | ||
| 99 | ;extrn _current_map:byte | ||
| 100 | ;extrn _map_size:byte | ||
| 101 | |||
| 102 | ; | ||
| 103 | ; total # of EMM pages in system | ||
| 104 | ; | ||
| 105 | extrn _total_pages:word | ||
| 106 | |||
| 107 | ; | ||
| 108 | ; table of offsets into in to the first page table | ||
| 109 | ; for user logical emm page map | ||
| 110 | ; | ||
| 111 | extrn _page_frame_base:dword | ||
| 112 | |||
| 113 | ; | ||
| 114 | ; ptr to table of emm page # for each handle's logical pages. | ||
| 115 | ; | ||
| 116 | extrn _emm_page:word | ||
| 117 | |||
| 118 | ; | ||
| 119 | ; ptr to table of page table entries for the EMM pages | ||
| 120 | ; | ||
| 121 | extrn _pft386:word ; note: actually a dword array | ||
| 122 | |||
| 123 | ; | ||
| 124 | ; handle data structure | ||
| 125 | ; | ||
| 126 | extrn _handle_table:word | ||
| 127 | extrn _handle_table_size:word | ||
| 128 | |||
| 129 | ; | ||
| 130 | ; save area for handles | ||
| 131 | ; | ||
| 132 | extrn _save_map:byte | ||
| 133 | |||
| 134 | _DATA ENDS | ||
| 135 | |||
| 136 | |||
| 137 | page | ||
| 138 | ;****************************************************************************** | ||
| 139 | ; L O C A L D A T A | ||
| 140 | ;****************************************************************************** | ||
| 141 | _DATA SEGMENT | ||
| 142 | ; | ||
| 143 | ; kludge to prevent unresolved from C compiler | ||
| 144 | ; | ||
| 145 | public __acrtused | ||
| 146 | __acrtused label dword | ||
| 147 | dd (0) | ||
| 148 | _DATA ENDS | ||
| 149 | |||
| 150 | page | ||
| 151 | ;****************************************************************************** | ||
| 152 | ; C O D E | ||
| 153 | ;****************************************************************************** | ||
| 154 | _TEXT SEGMENT | ||
| 155 | assume cs:_TEXT, ds:DGROUP, ss:DGROUP | ||
| 156 | |||
| 157 | ;*********************************************** | ||
| 158 | ; | ||
| 159 | ; _source_addr - return far pointer for source address (= int 67 entry DS:SI). | ||
| 160 | ; | ||
| 161 | ; SYNOPSIS: src = source_addr() | ||
| 162 | ; char far *src; /* ptr to area at DS:SI */ | ||
| 163 | ; | ||
| 164 | ; DESCRIPTION: This function generates a far pointer equivalent to the client's | ||
| 165 | ; DS:SI pointer. If this code was called in protected mode, the | ||
| 166 | ; address is a (selector,offset) pair; otherwise, it is a segment | ||
| 167 | ; offset pair. EMM1_GSEL is used if a selector is needed. | ||
| 168 | ; | ||
| 169 | ; 05/09/88 ISP No update needed for MEMM | ||
| 170 | ;*********************************************** | ||
| 171 | _source_addr proc near | ||
| 172 | ; | ||
| 173 | push bp | ||
| 174 | ; | ||
| 175 | mov bp,[_regp] ; get entry stack frame pointer | ||
| 176 | test [bp.PFlag],PFLAG_VIRTUAL ;Q: real/virtual mode ? | ||
| 177 | jnz sa_pm ; N: go get selector/offset | ||
| 178 | mov ax,word ptr [bp.rSI] ; Y: get offset | ||
| 179 | mov dx,word ptr [bp.rDS] ; get segment | ||
| 180 | jmp sa_exit ; return DX:AX = seg:offset | ||
| 181 | ; | ||
| 182 | ; protected mode - set up selector to client's DS | ||
| 183 | sa_pm: | ||
| 184 | push bx | ||
| 185 | push cx | ||
| 186 | push es ; save ES | ||
| 187 | ; | ||
| 188 | ; load ES with GDT alias | ||
| 189 | ; | ||
| 190 | push GDTD_GSEL | ||
| 191 | pop es ; ES -> GDT | ||
| 192 | ; | ||
| 193 | ; compute physical address | ||
| 194 | ; | ||
| 195 | mov ax,word ptr [bp.rDS] ; ax <-- base addr | ||
| 196 | mov dx,word ptr [bp.rSI] ; dx <-- offset | ||
| 197 | call SegOffTo24Resident ; converts to physical addr | ||
| 198 | |||
| 199 | ; | ||
| 200 | ; set up the appropriate table entry | ||
| 201 | ; | ||
| 202 | mov bx,EMM1_GSEL ; bx <-- selector | ||
| 203 | mov cx,0FFFFh ; cx <-- gets limit (64k) | ||
| 204 | mov ah,D_DATA0 ; ah <-- gets access rights | ||
| 205 | ; | ||
| 206 | ; at this point: | ||
| 207 | ; ah -- access rights | ||
| 208 | ; al -- bits 16-23 of linear address | ||
| 209 | ; dx -- low 16 bits of linear address | ||
| 210 | ; cx -- limit = 64k | ||
| 211 | ; bx -- selector | ||
| 212 | ; es -- selector to GDT Alias | ||
| 213 | call SetDescInfoResident ; set up descriptor | ||
| 214 | |||
| 215 | ; | ||
| 216 | ; set up return pointer | ||
| 217 | ; | ||
| 218 | xor ax,ax ; ax <-- offset (0) | ||
| 219 | mov dx,bx ; dx <-- selector | ||
| 220 | ; | ||
| 221 | pop es ; restore ES | ||
| 222 | pop cx | ||
| 223 | pop bx | ||
| 224 | ; | ||
| 225 | sa_exit: | ||
| 226 | pop bp | ||
| 227 | ret | ||
| 228 | ; | ||
| 229 | _source_addr endp | ||
| 230 | |||
| 231 | ;*********************************************** | ||
| 232 | ; | ||
| 233 | ; _dest_addr - return far pointer for destination address (= int 67 entry ES:DI). | ||
| 234 | ; | ||
| 235 | ; SYNOPSIS: dest = dest_addr() | ||
| 236 | ; char far *dest; /* ptr to area at ES:DI */ | ||
| 237 | ; | ||
| 238 | ; DESCRIPTION: This function generates a far pointer equivalent to the client's | ||
| 239 | ; ES:DI pointer. If this code was called in protected mode, the | ||
| 240 | ; address is a (selector,offset) pair; otherwise, it is a segment | ||
| 241 | ; offset pair. EMM2_GSEL is used if a selector is needed. | ||
| 242 | ; | ||
| 243 | ; 05/09/88 ISP No update needed for MEMM | ||
| 244 | ;*********************************************** | ||
| 245 | _dest_addr proc near | ||
| 246 | ; | ||
| 247 | push bp | ||
| 248 | ; | ||
| 249 | mov bp,[_regp] ; get entry stack frame pointer | ||
| 250 | test [bp.PFlag],PFLAG_VIRTUAL ;Q: real/virtual mode ? | ||
| 251 | jnz da_pm ; N: go get selector/offset | ||
| 252 | mov ax,word ptr [bp.rDI] ; Y: get offset | ||
| 253 | mov dx,word ptr [bp.rES] ; get segment | ||
| 254 | jmp da_exit ; return DX:AX = seg:offset | ||
| 255 | ; | ||
| 256 | ; protected mode - set up selector to client's DS | ||
| 257 | da_pm: | ||
| 258 | push bx | ||
| 259 | push cx | ||
| 260 | push es ; save ES | ||
| 261 | ; | ||
| 262 | ; load ES with GDT alias | ||
| 263 | ; | ||
| 264 | push GDTD_GSEL | ||
| 265 | pop es ; ES -> GDT | ||
| 266 | ; | ||
| 267 | ; compute physical address | ||
| 268 | ; | ||
| 269 | mov ax,word ptr [bp.rES] ; ax <-- base addr | ||
| 270 | mov dx,word ptr [bp.rDI] ; dx <-- offset | ||
| 271 | call SegOffTo24Resident ; converts to physical addr | ||
| 272 | |||
| 273 | ; | ||
| 274 | ; set up the appropriate table entry | ||
| 275 | ; | ||
| 276 | mov bx,EMM2_GSEL ; bx <-- selector | ||
| 277 | mov cx,0FFFFh ; cx <-- gets limit (64k) | ||
| 278 | mov ah,D_DATA0 ; ah <-- gets access rights | ||
| 279 | ; | ||
| 280 | ; at this point: | ||
| 281 | ; ah -- access rights | ||
| 282 | ; al -- bits 16-23 of linear address | ||
| 283 | ; dx -- low 16 bits of linear address | ||
| 284 | ; cx -- limit = 64k | ||
| 285 | ; bx -- selector | ||
| 286 | ; es -- selector to GDT Alias | ||
| 287 | call SetDescInfoResident ; set up descriptor | ||
| 288 | |||
| 289 | ; | ||
| 290 | ; set up return pointer | ||
| 291 | ; | ||
| 292 | xor ax,ax ; ax <-- offset (0) | ||
| 293 | mov dx,bx ; dx <-- selector | ||
| 294 | ; | ||
| 295 | pop es ; restore ES | ||
| 296 | pop cx | ||
| 297 | pop bx | ||
| 298 | ; | ||
| 299 | da_exit: | ||
| 300 | pop bp | ||
| 301 | ret | ||
| 302 | ; | ||
| 303 | _dest_addr endp | ||
| 304 | |||
| 305 | page | ||
| 306 | ;*********************************************** | ||
| 307 | ; | ||
| 308 | ; _copyout | ||
| 309 | ; | ||
| 310 | ; This routine takes a far pointer, a near pointer | ||
| 311 | ; and a byte count and copies from the near address | ||
| 312 | ; to the far address. | ||
| 313 | ; | ||
| 314 | ; Parameters: | ||
| 315 | ; destptr -- sel:off 286 pointer to target area | ||
| 316 | ; srcptr --- offset of source data in current D Seg | ||
| 317 | ; count ---- byte count for copy | ||
| 318 | ; | ||
| 319 | ; uses: | ||
| 320 | ; cx, ax, es | ||
| 321 | ; | ||
| 322 | ; 05/09/88 ISP No update needed for MEMM | ||
| 323 | ;*********************************************** | ||
| 324 | destptr = 4 | ||
| 325 | srcptr = 8 | ||
| 326 | count = 10 | ||
| 327 | _copyout proc near | ||
| 328 | push bp ; entry prolog | ||
| 329 | mov bp,sp | ||
| 330 | push di ; reg var | ||
| 331 | push si ; reg var | ||
| 332 | |||
| 333 | les di,[bp+destptr] ; es:di <-- destination address | ||
| 334 | mov si,[bp+srcptr] ; ds:si <-- source address | ||
| 335 | mov cx,[bp+count] ; cx <-- byte count | ||
| 336 | cld ; strings foward | ||
| 337 | rep movsb ; do it | ||
| 338 | |||
| 339 | pop si ; restore reg var | ||
| 340 | pop di ; restore reg var | ||
| 341 | pop bp | ||
| 342 | ret | ||
| 343 | _copyout endp | ||
| 344 | page | ||
| 345 | |||
| 346 | ;*********************************************** | ||
| 347 | ; | ||
| 348 | ; _copyin | ||
| 349 | ; | ||
| 350 | ; This routine takes a near pointer, a far pointer | ||
| 351 | ; and a byte count and copies from the far address | ||
| 352 | ; to the near address. | ||
| 353 | ; | ||
| 354 | ; Parameters: | ||
| 355 | ; destptr -- offset of dest in current D Seg | ||
| 356 | ; srcptr --- sel:off 286 pointer to source data area | ||
| 357 | ; count ---- byte count for copy | ||
| 358 | ; | ||
| 359 | ; uses: | ||
| 360 | ; cx, ax, es | ||
| 361 | ; | ||
| 362 | ; 05/09/88 ISP Written for MEMM. | ||
| 363 | ;*********************************************** | ||
| 364 | destptr = 4 | ||
| 365 | srcptr = 6 | ||
| 366 | count = 10 | ||
| 367 | _copyin proc near | ||
| 368 | push bp ; entry prolog | ||
| 369 | mov bp,sp | ||
| 370 | push di ; reg var | ||
| 371 | push si ; reg var | ||
| 372 | push ds | ||
| 373 | |||
| 374 | push ds | ||
| 375 | pop es ; es to dgroup | ||
| 376 | |||
| 377 | mov di,[bp+destptr] ; es:di <-- destination address | ||
| 378 | lds si,[bp+srcptr] ; ds:si <-- source address | ||
| 379 | mov cx,[bp+count] ; cx <-- byte count | ||
| 380 | cld ; strings foward | ||
| 381 | rep movsb ; do it | ||
| 382 | |||
| 383 | pop ds | ||
| 384 | pop si ; restore reg var | ||
| 385 | pop di ; restore reg var | ||
| 386 | pop bp | ||
| 387 | ret | ||
| 388 | _copyin endp | ||
| 389 | page | ||
| 390 | ;*********************************************** | ||
| 391 | ; | ||
| 392 | ; _wcopy | ||
| 393 | ; | ||
| 394 | ; This routine takes a two near pointers | ||
| 395 | ; and a word count and copies from the | ||
| 396 | ; first address to the second address. | ||
| 397 | ; | ||
| 398 | ; Parameters: | ||
| 399 | ; srcptr --- offset of source data in current D Seg | ||
| 400 | ; destptr -- offset of destination address in DS | ||
| 401 | ; count ---- word count for copy | ||
| 402 | ; | ||
| 403 | ; uses: | ||
| 404 | ; si, di, cx, ax | ||
| 405 | ; (si, di are restored) | ||
| 406 | ; | ||
| 407 | ; 05/09/88 ISP No update needed for MEMM | ||
| 408 | ;*********************************************** | ||
| 409 | srcptr = 4 | ||
| 410 | destptr = 6 | ||
| 411 | count = 8 | ||
| 412 | _wcopy proc near | ||
| 413 | push bp ; entry prolog | ||
| 414 | mov bp,sp | ||
| 415 | push di ; reg var | ||
| 416 | push si ; reg var | ||
| 417 | |||
| 418 | cld ; clear dir flag (forward move) | ||
| 419 | mov ax,ds ; | ||
| 420 | mov es,ax ; mov es,ds | ||
| 421 | mov di,[bp+destptr] ; es:di <-- destination address | ||
| 422 | mov si,[bp+srcptr] ; ds:si <-- source address | ||
| 423 | mov cx,[bp+count] ; cx <-- word count | ||
| 424 | rep movsw ; do it | ||
| 425 | |||
| 426 | pop si ; restore reg var | ||
| 427 | pop di ; restore reg var | ||
| 428 | pop bp | ||
| 429 | ret | ||
| 430 | _wcopy endp | ||
| 431 | page | ||
| 432 | ;*********************************************** | ||
| 433 | ; | ||
| 434 | ; _wcopyb | ||
| 435 | ; | ||
| 436 | ; This routine takes a two near pointers | ||
| 437 | ; and a word count and copies from the | ||
| 438 | ; first address to the second address. | ||
| 439 | ; The copy is done backwards to allow certain overlap of source and destination. | ||
| 440 | ; | ||
| 441 | ; Parameters: | ||
| 442 | ; srcptr --- offset of source data in current D Seg | ||
| 443 | ; destptr -- offset of destination address in DS | ||
| 444 | ; count ---- word count for copy | ||
| 445 | ; | ||
| 446 | ; uses: | ||
| 447 | ; si, di, cx, ax, es | ||
| 448 | ; (si, di are restored) | ||
| 449 | ; | ||
| 450 | ; 05/20/88 ISP Shifted in from win386 and updated for 16 bit ptrs | ||
| 451 | ;*********************************************** | ||
| 452 | srcptr = 4 | ||
| 453 | destptr = 6 | ||
| 454 | count = 8 | ||
| 455 | _wcopyb proc near | ||
| 456 | push bp ; entry prolog | ||
| 457 | mov bp,sp | ||
| 458 | push di ; reg var | ||
| 459 | push si ; reg var | ||
| 460 | |||
| 461 | mov ax,ds ; | ||
| 462 | mov es,ax ; mov es,ds | ||
| 463 | mov di, word ptr [bp+destptr] ; destination address | ||
| 464 | mov si, word ptr [bp+srcptr] ; source address | ||
| 465 | mov cx, word ptr [bp+count] ; word count | ||
| 466 | dec cx | ||
| 467 | shl cx, 1 ; offset of 'last' word to move | ||
| 468 | add si, cx | ||
| 469 | add di, cx | ||
| 470 | mov cx, word ptr [bp+count] ; recover word count | ||
| 471 | |||
| 472 | std ; set dir flag (backward move) | ||
| 473 | rep movsw ; do it | ||
| 474 | cld ; 'C' tends to expect this. | ||
| 475 | |||
| 476 | pop si ; restore reg var | ||
| 477 | pop di ; restore reg var | ||
| 478 | pop bp | ||
| 479 | ret | ||
| 480 | _wcopyb endp | ||
| 481 | page | ||
| 482 | ;*********************************************** | ||
| 483 | ; | ||
| 484 | ; _valid_handle - validate current handle | ||
| 485 | ; | ||
| 486 | ; SYNOPSIS: hp = _valid_handle() | ||
| 487 | ; struct handle_ptr *hp; /* ptr to handle's structure */ | ||
| 488 | ; /* OR NULL_HANDLE if invalid handle */ | ||
| 489 | ; /* also sets AH = INVALID_HANDLE if it fails */ | ||
| 490 | ; | ||
| 491 | ; DESCRIPTION: This routine validates the current handle in regp->rDX and | ||
| 492 | ; returns either an error or a ptr to the handle's index and | ||
| 493 | ; page count structure. | ||
| 494 | ; | ||
| 495 | ; 05/09/88 ISP No update needed for MEMM | ||
| 496 | ;*********************************************** | ||
| 497 | _valid_handle proc near | ||
| 498 | ; | ||
| 499 | push bp | ||
| 500 | mov bp,[_regp] ; get entry args pointer | ||
| 501 | push bx | ||
| 502 | ; | ||
| 503 | mov bx,word ptr [bp.rDX] ; BX = entry handle | ||
| 504 | cmp bx,[_handle_table_size] ;Q: handle in range ? | ||
| 505 | jae vh_fail ; N: return invalid handle error | ||
| 506 | shl bx,2 ; Y: BX = handle's table offset | ||
| 507 | add bx,offset DGROUP:_handle_table ; BX = offset to handle's data | ||
| 508 | cmp [bx.ht_index],NULL_PAGE ;Q: is this an active handle ? | ||
| 509 | je vh_fail ; N: return invalid handle error | ||
| 510 | mov ax,bx ; Y: return ptr to handle's data | ||
| 511 | ; | ||
| 512 | vh_exit: | ||
| 513 | pop bx | ||
| 514 | pop bp | ||
| 515 | ret | ||
| 516 | vh_fail: | ||
| 517 | mov byte ptr [bp.rAX+1],INVALID_HANDLE ; set AH on stack | ||
| 518 | mov ax,NULL_HANDLE ; return NULL_HANDLE to caller | ||
| 519 | jmp short vh_exit | ||
| 520 | |||
| 521 | ; | ||
| 522 | _valid_handle endp | ||
| 523 | |||
| 524 | ;*********************************************** | ||
| 525 | ; | ||
| 526 | ; flush_tlb: | ||
| 527 | ; | ||
| 528 | ; no params, no return value, uses eax | ||
| 529 | ; | ||
| 530 | ; flush the Translation Look-Aside Buffer | ||
| 531 | ; | ||
| 532 | ; 05/09/88 ISP Shifted in from WIN386 | ||
| 533 | ;*********************************************** | ||
| 534 | _flush_tlb proc near | ||
| 535 | public _flush_tlb | ||
| 536 | mov eax, cr3 | ||
| 537 | mov cr3, eax | ||
| 538 | ret | ||
| 539 | _flush_tlb endp | ||
| 540 | |||
| 541 | ;*********************************************** | ||
| 542 | ; | ||
| 543 | ; _Names_Match | ||
| 544 | ; | ||
| 545 | ; Returns a boolean value (0 = false, FFFF = True) if 2 handle names match | ||
| 546 | ; | ||
| 547 | ; uses: | ||
| 548 | ; cx, ax | ||
| 549 | ; | ||
| 550 | ; 05/09/88 ISP Shifted in from WIN386 and modified for 16 bit ptrs | ||
| 551 | ;*********************************************** | ||
| 552 | name1 = 4 | ||
| 553 | name2 = 6 | ||
| 554 | public _Names_Match | ||
| 555 | _Names_Match proc near | ||
| 556 | push bp ; entry prolog | ||
| 557 | mov bp,sp | ||
| 558 | push di ; reg var | ||
| 559 | push si ; reg var | ||
| 560 | |||
| 561 | mov ax,ds ; initialise es segment to | ||
| 562 | mov es,ax ; DGROUP | ||
| 563 | |||
| 564 | xor ax, ax ; Assume it did NOT work | ||
| 565 | |||
| 566 | mov di, word ptr [bp+name1] ; First name | ||
| 567 | mov si, word ptr [bp+name2] ; Second name | ||
| 568 | cld | ||
| 569 | mov cx, 2 ; Compare 2 dwords | ||
| 570 | rep cmpsd ; do it | ||
| 571 | jne SHORT Names_Dont_Match | ||
| 572 | not ax ; They match! | ||
| 573 | |||
| 574 | Names_Dont_Match: | ||
| 575 | pop si ; restore reg var | ||
| 576 | pop di ; restore reg var | ||
| 577 | pop bp | ||
| 578 | ret | ||
| 579 | _Names_Match endp | ||
| 580 | |||
| 581 | page | ||
| 582 | ;** SetDescInfoResident - set descriptor information | ||
| 583 | ; | ||
| 584 | ; The limit field of a specified descriptor is set. | ||
| 585 | ; (limit = size - 1). | ||
| 586 | ; The base address of the specified descriptor is set. | ||
| 587 | ; The access field of the specified descriptor is set. | ||
| 588 | ; | ||
| 589 | ; ENTRY BX = selector | ||
| 590 | ; ES:0 = descriptor table to use | ||
| 591 | ; CX = limit | ||
| 592 | ; AL, DX = 24 bit base address | ||
| 593 | ; AH = access rights byte | ||
| 594 | ; EXIT None | ||
| 595 | ; USES Flags, other regs preserved | ||
| 596 | ; | ||
| 597 | ; WARNING This code only works on a 286. It can be called in | ||
| 598 | ; either mode. | ||
| 599 | |||
| 600 | SetDescInfoResident proc near | ||
| 601 | push bx ; save selector | ||
| 602 | and bl,SEL_LOW_MASK | ||
| 603 | |||
| 604 | ; fill in the limit field | ||
| 605 | |||
| 606 | mov es:[bx],cx | ||
| 607 | |||
| 608 | ; fill in base address | ||
| 609 | |||
| 610 | mov es:[bx + 2],dx | ||
| 611 | mov es:[bx + 4],al | ||
| 612 | |||
| 613 | ; fill in access rights byte | ||
| 614 | |||
| 615 | mov es:[bx + 5],ah | ||
| 616 | pop bx | ||
| 617 | ret | ||
| 618 | SetDescInfoResident endp | ||
| 619 | |||
| 620 | page | ||
| 621 | ;** SegOffTo24Resident - convert seg:off to 24 bit physical address | ||
| 622 | ; | ||
| 623 | ; The specified real mode segment:offset is converted to | ||
| 624 | ; a 24 bit physical address. | ||
| 625 | ; | ||
| 626 | ; ENTRY AX = segment | ||
| 627 | ; DX = offset | ||
| 628 | ; EXIT AL, DX = 24 bit physical address | ||
| 629 | ; USES AH, Flags, other regs preserved. | ||
| 630 | ; | ||
| 631 | ; WARNING This code only works on a 286. It can be called in | ||
| 632 | ; either mode. | ||
| 633 | |||
| 634 | SegOffTo24Resident proc near | ||
| 635 | push cx | ||
| 636 | |||
| 637 | ; Convert AX:DX into 24 bit addr in AL, DX | ||
| 638 | |||
| 639 | mov ch,ah | ||
| 640 | shl ax,4 | ||
| 641 | shr ch,4 ; CH = high byte | ||
| 642 | add dx,ax ; DX = low word | ||
| 643 | mov al,ch ; AL = high byte | ||
| 644 | adc al,0 ; propagate cy from low word | ||
| 645 | |||
| 646 | pop cx | ||
| 647 | ret | ||
| 648 | SegOffTo24Resident endp | ||
| 649 | |||
| 650 | _TEXT ENDS | ||
| 651 | END | ||
| 652 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/EMM/MAKEFILE b/v4.0/src/MEMM/EMM/MAKEFILE new file mode 100644 index 0000000..95f440a --- /dev/null +++ b/v4.0/src/MEMM/EMM/MAKEFILE | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | #****************************************************************************** | ||
| 2 | # title MAKEFILE - EMMLIB.LIB build file | ||
| 3 | #****************************************************************************** | ||
| 4 | # | ||
| 5 | # (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | # | ||
| 7 | # Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | # EMMLIB.LIB - EMM functions library | ||
| 9 | # | ||
| 10 | # Module: MAKEFILE for EMMLIB - EMM library | ||
| 11 | # | ||
| 12 | # Version: 0.02 | ||
| 13 | # | ||
| 14 | # Date: May 12, 1986 | ||
| 15 | # | ||
| 16 | #****************************************************************************** | ||
| 17 | # | ||
| 18 | # Change log: | ||
| 19 | # | ||
| 20 | # DATE REVISION DESCRIPTION | ||
| 21 | # -------- -------- ------------------------------------------------------- | ||
| 22 | # 06/12/86 Original | ||
| 23 | # 06/25/86 0.02 Added EMMDEF.INC (SBP). | ||
| 24 | # | ||
| 25 | #****************************************************************************** | ||
| 26 | # | ||
| 27 | # Functional Description: | ||
| 28 | # | ||
| 29 | # This file assembles and links EMMLIB.LIB | ||
| 30 | # | ||
| 31 | #****************************************************************************** | ||
| 32 | .SUFFIXES: | ||
| 33 | .SUFFIXES: .c .asm .obj .lst .def .lnk .lrf .exe .com | ||
| 34 | |||
| 35 | # Definition for turning OFF high memory allocation | ||
| 36 | # HIFLAG = -DNOHIMEM => turns it off | ||
| 37 | # HIFLAG = => turns on high memory allocation | ||
| 38 | HIFLAG = /DNOHIMEM | ||
| 39 | #HIFLAG = | ||
| 40 | |||
| 41 | # Definitions for assembler | ||
| 42 | # (using masm 4.00) | ||
| 43 | MASM = masm | ||
| 44 | #MASM = \bin\masm400 | ||
| 45 | #MASM = masm400 | ||
| 46 | AFLAGS = /Mx /t /DI386 /i..\memm $(HIFLAG) | ||
| 47 | AINC = ..\memm\vdmseg.inc ..\memm\vdmsel.inc emmdef.inc | ||
| 48 | |||
| 49 | # Definitions for linker for old style .exe files | ||
| 50 | #LINK = \bin\link | ||
| 51 | LINK = link | ||
| 52 | LFLAGS = /NOI /M | ||
| 53 | LIBS = | ||
| 54 | |||
| 55 | # Definitions for librarian | ||
| 56 | #LIB = \bin\lib | ||
| 57 | LIB = lib | ||
| 58 | |||
| 59 | # Defines for C Compiler | ||
| 60 | C = cl | ||
| 61 | #C = \bin\msc | ||
| 62 | #C = msc | ||
| 63 | CFLAGS =/ASw /G2 /Oat /Gs /Ze /Zl /Fc /c | ||
| 64 | |||
| 65 | # | ||
| 66 | # definition of objects | ||
| 67 | # | ||
| 68 | OBJS=emmfunct.obj emm40.obj emmp.obj emmsup.obj emmdisp.obj emmdata.obj emminc.obj | ||
| 69 | LOBJS=emmfunct.obj+emm40.obj+emmp.obj+emmsup.obj+emmdisp.obj+emmdata.obj | ||
| 70 | |||
| 71 | emmlib.lib: $(OBJS) | ||
| 72 | del emmlib.lib | ||
| 73 | $(LIB) emmlib+$(LOBJS),; | ||
| 74 | |||
| 75 | emmfunct.obj: emmfunct.c emm.h | ||
| 76 | $(C) $(CFLAGS) emmfunct.c | ||
| 77 | |||
| 78 | emm40.obj: emm40.c emm.h | ||
| 79 | $(C) $(CFLAGS) emm40.c | ||
| 80 | |||
| 81 | emmp.obj: emmp.asm $(AINC) | ||
| 82 | $(MASM) $(AFLAGS) emmp.asm,emmp.obj,emmp.lst; | ||
| 83 | |||
| 84 | emmsup.obj: emmsup.asm $(AINC) | ||
| 85 | $(MASM) $(AFLAGS) emmsup.asm,emmsup.obj,emmsup.lst; | ||
| 86 | |||
| 87 | emmdisp.obj: emmdisp.asm $(AINC) | ||
| 88 | $(MASM) $(AFLAGS) emmdisp.asm,emmdisp.obj,emmdisp.lst; | ||
| 89 | |||
| 90 | emmdata.obj: emmdata.asm $(AINC) | ||
| 91 | $(MASM) $(AFLAGS) emmdata.asm,emmdata.obj,emmdata.lst; | ||
| 92 | |||
| 93 | emminc.obj: emminc.asm $(AINC) | ||
| 94 | $(MASM) $(AFLAGS) emminc.asm,emminc.obj,emminc.lst; | ||
| 95 | |||