diff options
Diffstat (limited to 'v4.0/src/MEMM')
79 files changed, 31239 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 | |||
diff --git a/v4.0/src/MEMM/MAKEFILE b/v4.0/src/MEMM/MAKEFILE new file mode 100644 index 0000000..e9c4c70 --- /dev/null +++ b/v4.0/src/MEMM/MAKEFILE | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #************************* Root level Makefile ************************* | ||
| 2 | |||
| 3 | make =nmake | ||
| 4 | |||
| 5 | all: | ||
| 6 | cd emm | ||
| 7 | $(make) | ||
| 8 | cd ..\memm | ||
| 9 | $(make) | ||
| 10 | cd .. | ||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
diff --git a/v4.0/src/MEMM/MEMM/A20TRAP.ASM b/v4.0/src/MEMM/MEMM/A20TRAP.ASM new file mode 100644 index 0000000..2f7f377 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/A20TRAP.ASM | |||
| @@ -0,0 +1,528 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title A20TRAP.ASM - I/O trap handlers for watching the A20 line. | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: A20TRAP.ASM - I/O trap handlers for watching the A20 line. | ||
| 13 | ; | ||
| 14 | ; Version: 0.03 | ||
| 15 | ; | ||
| 16 | ; Date: June 1, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 07/03/86 0.03 From ChkDisA20 routine in VMINST. | ||
| 27 | ; | ||
| 28 | ;****************************************************************************** | ||
| 29 | ; | ||
| 30 | ; Functional Description: | ||
| 31 | ; This module contains the I/O trap handlers for the A20 line watching | ||
| 32 | ; logic. | ||
| 33 | ; | ||
| 34 | ; | ||
| 35 | ; COMMENTS: This module displays weaknesses due to carryover from previous | ||
| 36 | ; sources. A lot of the code here can be shifted to the LAST | ||
| 37 | ; segment. There is a duplication of routines for getting the a20 | ||
| 38 | ; state. (ISP) | ||
| 39 | ;****************************************************************************** | ||
| 40 | .lfcond ; list false conditionals | ||
| 41 | .386p | ||
| 42 | page | ||
| 43 | ;****************************************************************************** | ||
| 44 | ; P U B L I C D E C L A R A T I O N S | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; | ||
| 47 | public A20_Handler | ||
| 48 | public A20_Trap_Init | ||
| 49 | public EnableA20 | ||
| 50 | public DisableA20 | ||
| 51 | public togl_A20 | ||
| 52 | public get_a20_state | ||
| 53 | public estb_a20_state | ||
| 54 | public get_init_a20_state | ||
| 55 | |||
| 56 | |||
| 57 | ; | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; E X T E R N A L R E F E R E N C E S | ||
| 60 | ;****************************************************************************** | ||
| 61 | include VDMseg.inc | ||
| 62 | include VDMsel.inc | ||
| 63 | ; | ||
| 64 | _DATA segment | ||
| 65 | ; (none) | ||
| 66 | _DATA ends | ||
| 67 | |||
| 68 | _TEXT segment | ||
| 69 | |||
| 70 | extrn PortTrap:near | ||
| 71 | |||
| 72 | _TEXT ends | ||
| 73 | page | ||
| 74 | ;****************************************************************************** | ||
| 75 | ; L O C A L C O N S T A N T S | ||
| 76 | ;****************************************************************************** | ||
| 77 | ; | ||
| 78 | FALSE equ 0 | ||
| 79 | TRUE equ not FALSE | ||
| 80 | |||
| 81 | YesLLdone equ 1 | ||
| 82 | KbdDataEnb equ 2 | ||
| 83 | |||
| 84 | A20CmdBit equ 02h ; high is enabled | ||
| 85 | A20DsbCmd equ 0DDh | ||
| 86 | A20EnbCmd equ 0DFh | ||
| 87 | |||
| 88 | KbdCmdPort equ 64h ; 8042 cmd port | ||
| 89 | KbdWrtData equ 0D1h ; Enable write to data port | ||
| 90 | KbdDataPort equ 60h ; 8042 data port | ||
| 91 | KbdStatusPort equ 64h ; 8042 cmd port | ||
| 92 | KbdBufFull equ 2 ; Buffer bull(data not received) status | ||
| 93 | |||
| 94 | ; equates for the state_a20 flag | ||
| 95 | |||
| 96 | A20_ON equ A20CmdBit ; | ||
| 97 | A20_OFF equ 0 ; | ||
| 98 | ; | ||
| 99 | ; equate for the bit which will toggle the state of | ||
| 100 | ; | ||
| 101 | WRAP_BIT equ 00100000h ; page table entry bit | ||
| 102 | ; | ||
| 103 | ;****************************************************************************** | ||
| 104 | ; S E G M E N T D E F I N I T I O N | ||
| 105 | ;****************************************************************************** | ||
| 106 | ; | ||
| 107 | |||
| 108 | ; | ||
| 109 | ; _DATA segment | ||
| 110 | ; | ||
| 111 | _DATA segment | ||
| 112 | |||
| 113 | KbdComd db 0 ; last CMD written to port 64h | ||
| 114 | state_a20 db 0 ; A20 line state: A20_ON is on, A20_OFF is off | ||
| 115 | |||
| 116 | _DATA ends | ||
| 117 | |||
| 118 | ; | ||
| 119 | page | ||
| 120 | ;------------------------------------------------------------------------------ | ||
| 121 | _TEXT segment | ||
| 122 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 123 | ; | ||
| 124 | ;****************************************************************************** | ||
| 125 | ; L O C A L D A T A A R E A | ||
| 126 | ;****************************************************************************** | ||
| 127 | ; | ||
| 128 | |||
| 129 | ;****************************************************************************** | ||
| 130 | ; A20_Handler - I/O trap handler for Address line 20 modification | ||
| 131 | ; | ||
| 132 | ; ENTRY: Protected Mode Ring 0 | ||
| 133 | ; AL = byte to output to port. | ||
| 134 | ; BX == 2 * port address(either KbdDataPort or KbdCmdPort) | ||
| 135 | ; DX == 0 => Emulate input | ||
| 136 | ; <> 0 => Emulate output | ||
| 137 | ; DS = DGROUP | ||
| 138 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 139 | ; | ||
| 140 | ; EXIT: | ||
| 141 | ; CLC => I/O emulated. | ||
| 142 | ; STC => I/O NOT emulated. | ||
| 143 | ; | ||
| 144 | ; USED: BX,Flags | ||
| 145 | ; STACK: | ||
| 146 | ;------------------------------------------------------------------------------ | ||
| 147 | A20_Handler proc near | ||
| 148 | or dx,dx ;Q: Output ? | ||
| 149 | jnz A20_Write ; Y: check for write to output port | ||
| 150 | stc ; N: don't bother to emulate it | ||
| 151 | ret | ||
| 152 | A20_Write: | ||
| 153 | cmp bx,KbdDataPort*2 ;Q: Keyboard data port? | ||
| 154 | jne Kbd_C_Handler ; N: Go handle Kybd Command output | ||
| 155 | ; Y: Go handle Kybd Data output | ||
| 156 | |||
| 157 | ; keyboard data write | ||
| 158 | Kbd_D_Dwrite: | ||
| 159 | cmp [KbdComd],KbdWrtData ;Q: write to output port? | ||
| 160 | mov [KbdComd],0 ; data port write => no CMD | ||
| 161 | je Kbd_D_out ; Y: filter client's data | ||
| 162 | stc ; N: don't bother to emulate it | ||
| 163 | ret | ||
| 164 | ; | ||
| 165 | ; here if Output Port write | ||
| 166 | ; | ||
| 167 | Kbd_D_out: | ||
| 168 | push ax ; Set A20 cmd bit | ||
| 169 | call check_a20_togl ; do we need to toggle the | ||
| 170 | ; the a20 state | ||
| 171 | jz skip_togl ; N: Skip routine to toggle | ||
| 172 | call togl_a20 | ||
| 173 | skip_togl: | ||
| 174 | or al, A20CmdBit ; to leave A20 enabled | ||
| 175 | out KbdDataPort,al ; "emulate" it | ||
| 176 | pop ax ; restore client's byte | ||
| 177 | clc ; emulated | ||
| 178 | ret | ||
| 179 | |||
| 180 | ;Output to Keyboard command port | ||
| 181 | Kbd_C_Handler: | ||
| 182 | ; | ||
| 183 | mov [KbdComd],al ; Y: save new port 64 byte | ||
| 184 | stc ; don't bother to emulate it | ||
| 185 | ret | ||
| 186 | ; | ||
| 187 | A20_Handler endp | ||
| 188 | |||
| 189 | |||
| 190 | ;****************************************************************************** | ||
| 191 | ; A20_Trap_Init - turn on I/O bit map trapping for A20 line watching | ||
| 192 | ; | ||
| 193 | ; ENTRY: DS -> DGROUP - real,virtual, or protected mode | ||
| 194 | ; ES -> TSS segment | ||
| 195 | ; IOTrap_Tab already has address of A20_Handler for KbdDataPort and | ||
| 196 | ; KbdCmdPort | ||
| 197 | ; | ||
| 198 | ; EXIT: IO_BitMap Updated to trap ports used to change A20 line | ||
| 199 | ; | ||
| 200 | ; USED: AX,Flags | ||
| 201 | ; STACK: | ||
| 202 | ;------------------------------------------------------------------------------ | ||
| 203 | A20_Trap_Init proc near | ||
| 204 | ; | ||
| 205 | ; reset flag | ||
| 206 | ; | ||
| 207 | mov [KbdComd],0 | ||
| 208 | ; | ||
| 209 | ; Set IOBM traps to look for client's disabling of the A20 line | ||
| 210 | ; | ||
| 211 | mov bh, 80h ; set every 1k | ||
| 212 | mov ax, KbdDataPort | ||
| 213 | call PortTrap ; set traps on keyboard ports | ||
| 214 | mov ax, KbdCmdPort ; in case client | ||
| 215 | call PortTrap ; tries to disable A20 | ||
| 216 | ret | ||
| 217 | ; | ||
| 218 | A20_Trap_Init endp | ||
| 219 | ; | ||
| 220 | ;*****************************************************************************; | ||
| 221 | ;*** EnableA20 - switch 20th address line ; | ||
| 222 | ; ; | ||
| 223 | ; This routine is used to enable the 20th address line in ; | ||
| 224 | ; the system. ; | ||
| 225 | ; ; | ||
| 226 | ; In general when in real mode we want the A20 line disabled, ; | ||
| 227 | ; when in protected mode enabled. However if there is no high ; | ||
| 228 | ; memory installed we can optimise out unnecessary switching ; | ||
| 229 | ; of the A20 line. Unfortunately the PC/AT ROM does not allow ; | ||
| 230 | ; us to completely decouple mode switching the 286 from gating ; | ||
| 231 | ; the A20 line. ; | ||
| 232 | ; ; | ||
| 233 | ; In real mode we would want A20 enabled if we need to access ; | ||
| 234 | ; high memory, for example in a device driver. We want it ; | ||
| 235 | ; disabled while running arbitrary applications because they ; | ||
| 236 | ; may rely on the 1 meg address wrap feature which having the ; | ||
| 237 | ; A20 line off provides. ; | ||
| 238 | ; ; | ||
| 239 | ; This code is largely duplicated from the PC/AT ROM BIOS. ; | ||
| 240 | ; See Module "BIOS1" on page 5-155 of the PC/AT tech ref. ; | ||
| 241 | ; ; | ||
| 242 | ; ENTRY none ;ds = DGROUP ; | ||
| 243 | ; EXIT A20 line enabled ; | ||
| 244 | ; USES ax, flags modified ; | ||
| 245 | ; ; | ||
| 246 | ; WARNING: ; | ||
| 247 | ; ; | ||
| 248 | ; The performance characteristics of these routines ; | ||
| 249 | ; are not well understood. There may be worst case ; | ||
| 250 | ; scenarios where the routine could take a relatively ; | ||
| 251 | ; long time to complete. ; | ||
| 252 | ; ; | ||
| 253 | ; TO BE ADDED: ; | ||
| 254 | ; ; | ||
| 255 | ; 8042 error handling ; | ||
| 256 | ;*****************************************************************************; | ||
| 257 | EnableA20 proc near | ||
| 258 | mov ah,0dfh ; code for enable | ||
| 259 | jmp a20common ; jump to common code | ||
| 260 | |||
| 261 | EnableA20 endp | ||
| 262 | |||
| 263 | ;*****************************************************************************; | ||
| 264 | ;*** DisableA20 - switch 20th address line ; | ||
| 265 | ; ; | ||
| 266 | ; This routine is used to disable the 20th address line in ; | ||
| 267 | ; the system. ; | ||
| 268 | ; ; | ||
| 269 | ; ENTRY none ;ds = DATA ; | ||
| 270 | ; EXIT A20 line disabled ; | ||
| 271 | ; [state_a20] = 0 ; | ||
| 272 | ; USES ax, flags modified ; | ||
| 273 | ;*****************************************************************************; | ||
| 274 | |||
| 275 | DisableA20 proc near | ||
| 276 | mov ah,0ddh ; code for disable | ||
| 277 | jmp a20common ; jump to common code | ||
| 278 | |||
| 279 | DisableA20 endp | ||
| 280 | |||
| 281 | |||
| 282 | a20common proc near | ||
| 283 | |||
| 284 | ; This is entered via a jmp from one of the two procedural | ||
| 285 | ; entry points above. | ||
| 286 | |||
| 287 | call empty_8042 ; ensure 8042 input buffer empty | ||
| 288 | jnz com1 ; 8042 error return | ||
| 289 | mov al,0d1h ; 8042 cmd to write output port | ||
| 290 | out KbdCmdPort,al ; send cmd to 8042 | ||
| 291 | call empty_8042 ; wait for 8042 to accept cmd | ||
| 292 | jnz com1 ; 8042 error return | ||
| 293 | mov al,ah ; 8042 port data | ||
| 294 | out KbdDataPort,al ; output port data to 8042 | ||
| 295 | call empty_8042 | ||
| 296 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 297 | ; | ||
| 298 | ; AST P/386 needs the delay for their | ||
| 299 | ; A20 switch settle. If not, it won't work ! | ||
| 300 | ; PC (10/03/88) | ||
| 301 | ; | ||
| 302 | push cx | ||
| 303 | mov cx, 0100h | ||
| 304 | ASTloop: | ||
| 305 | loop ASTloop | ||
| 306 | pop cx | ||
| 307 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 308 | |||
| 309 | com1: | ||
| 310 | ret | ||
| 311 | a20common endp | ||
| 312 | |||
| 313 | ;*****************************************************************************; | ||
| 314 | ;*** empty_8042 - wait for 8042 input buffer to drain ; | ||
| 315 | ; ; | ||
| 316 | ; ENTRY none ; | ||
| 317 | ; EXIT al=0, z=0 => 8042 input buffer empty ; | ||
| 318 | ; al=2, z=1 => timeout, input buffer full ; | ||
| 319 | ; USES none ; | ||
| 320 | ;*****************************************************************************; | ||
| 321 | empty_8042 proc near | ||
| 322 | push cx ; save it | ||
| 323 | sub cx,cx ; cx = 0, timeout loop counter | ||
| 324 | emp1: | ||
| 325 | in al,KbdStatusPort ; read 8042 status port | ||
| 326 | and al,KbdBufFull ; test buffer full bit | ||
| 327 | loopnz emp1 | ||
| 328 | pop cx | ||
| 329 | ret | ||
| 330 | empty_8042 endp | ||
| 331 | |||
| 332 | ;*****************************************************************************; | ||
| 333 | ;*** check_a20_togl - check if a20 state emulated needs to be toggled ; | ||
| 334 | ; ; | ||
| 335 | ; ENTRY [state_a20] = A20 emulated state ; | ||
| 336 | ; al = byte to output to kbd data port ; | ||
| 337 | ; EXIT Z set if A20 not to be toggled ; | ||
| 338 | ; clear if A20 to be toggled ; | ||
| 339 | ; USES Flags ; | ||
| 340 | ; ; | ||
| 341 | ;*****************************************************************************; | ||
| 342 | check_a20_togl proc near | ||
| 343 | ; | ||
| 344 | push ax | ||
| 345 | and al,A20CmdBit ; make all other bits 0 | ||
| 346 | xor al,[state_a20] ; does the state of the a20 bit match | ||
| 347 | ; Y: then Z is set | ||
| 348 | ; N: then Z is not set | ||
| 349 | pop ax | ||
| 350 | ret | ||
| 351 | ; | ||
| 352 | check_a20_togl endp | ||
| 353 | |||
| 354 | |||
| 355 | ;*****************************************************************************; | ||
| 356 | ;*** get_a20_state - see if virtualised a20 is enabled or not ; | ||
| 357 | ; ; | ||
| 358 | ; ENTRY [state_a20] = A20 emulated state ; | ||
| 359 | ; ; | ||
| 360 | ; EXIT ZF set if A20 disabled ; | ||
| 361 | ; ZF not set if A20 enabled ; | ||
| 362 | ; ; | ||
| 363 | ; USES Flags ; | ||
| 364 | ;*****************************************************************************; | ||
| 365 | |||
| 366 | get_a20_state proc near | ||
| 367 | ; | ||
| 368 | test [state_a20], A20_ON | ||
| 369 | ret | ||
| 370 | get_a20_state endp | ||
| 371 | |||
| 372 | |||
| 373 | ;*****************************************************************************; | ||
| 374 | ;*** togl_A20 - toggle emulated A20 state. ; | ||
| 375 | ; ; | ||
| 376 | ; ENTRY [state_a20] = A20 emulated state ; | ||
| 377 | ; PROTECTED MODE ONLY ; | ||
| 378 | ; DS:DGROUP ; | ||
| 379 | ; ; | ||
| 380 | ; EXIT [state_a20] toggled ; | ||
| 381 | ; page table entries for the 1M --> 1M + 64k area toggled ; | ||
| 382 | ; ; | ||
| 383 | ; USES Flags ; | ||
| 384 | ; ; | ||
| 385 | ; ; | ||
| 386 | ;*****************************************************************************; | ||
| 387 | togl_A20 proc near | ||
| 388 | ; | ||
| 389 | push es | ||
| 390 | push di | ||
| 391 | push cx | ||
| 392 | push eax | ||
| 393 | ; | ||
| 394 | ; get addressability to page table | ||
| 395 | ; | ||
| 396 | push PAGET_GSEL | ||
| 397 | pop es | ||
| 398 | ; | ||
| 399 | ; and offset into entries for the 64k block at 1M | ||
| 400 | ; | ||
| 401 | mov di,100h*4 ; 1024k/4k = 256 entries, each 4 bytes long | ||
| 402 | mov cx,10h ; 64k/4k = 16 entries | ||
| 403 | cld | ||
| 404 | ; | ||
| 405 | ; for all the entries flip the bit which will make the entries either wrap | ||
| 406 | ; around for 1M-1M+64k to either 1M-1M+64k or 0-64k. This bit is the 1M bit | ||
| 407 | ; in the base address. | ||
| 408 | ; | ||
| 409 | w64_loop: | ||
| 410 | xor dword ptr es:[di], WRAP_BIT | ||
| 411 | add di,4 | ||
| 412 | loop w64_loop | ||
| 413 | ; | ||
| 414 | ; flush the tlb | ||
| 415 | ; | ||
| 416 | mov eax,cr3 | ||
| 417 | mov cr3,eax | ||
| 418 | ; | ||
| 419 | ; toggle a20 state | ||
| 420 | ; | ||
| 421 | xor [state_a20],A20_ON | ||
| 422 | ; | ||
| 423 | ; restore the registers | ||
| 424 | ; | ||
| 425 | pop eax | ||
| 426 | pop cx | ||
| 427 | pop di | ||
| 428 | pop es | ||
| 429 | ret | ||
| 430 | ; | ||
| 431 | togl_A20 endp | ||
| 432 | |||
| 433 | |||
| 434 | |||
| 435 | _TEXT ends ; end of segment | ||
| 436 | |||
| 437 | LAST segment | ||
| 438 | |||
| 439 | assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 440 | |||
| 441 | |||
| 442 | ;****************************************************************************** | ||
| 443 | ;***estb_a20_state ; | ||
| 444 | ; ; | ||
| 445 | ; since we are fixing the a20 state to be always enabled we need to implement ; | ||
| 446 | ; a logical a20 state independent of the physical one. this routine inits ; | ||
| 447 | ; this state. we do this comparing 3 double words at 0:80 and 1M:80. if these; | ||
| 448 | ; compare the a20 is disabled thus causing a wraparound. ; | ||
| 449 | ; ; | ||
| 450 | ; INPUTS: ; | ||
| 451 | ; ; | ||
| 452 | ; OUTPUTS: [state_a20] .. A20_ON if a20 is on currently ; | ||
| 453 | ; .. A20_OFF if a20 is off currently ; | ||
| 454 | ; ; | ||
| 455 | ; USES: flags ; | ||
| 456 | ; ; | ||
| 457 | ; AUTHOR: ISP. Shifted in from smartdrv sources. 8/29/88. ; | ||
| 458 | ; ; | ||
| 459 | ;*****************************************************************************; | ||
| 460 | ; A20 address line state determination addresses | ||
| 461 | ; | ||
| 462 | low_mem label dword | ||
| 463 | dw 20h*4 | ||
| 464 | dw 0 | ||
| 465 | |||
| 466 | high_mem label dword | ||
| 467 | dw 20h*4 + 10h | ||
| 468 | dw 0ffffh | ||
| 469 | |||
| 470 | estb_a20_state proc near | ||
| 471 | push cx | ||
| 472 | push ds | ||
| 473 | push es | ||
| 474 | push si | ||
| 475 | push di | ||
| 476 | ; | ||
| 477 | ; initialise a20 to off | ||
| 478 | ; | ||
| 479 | mov [state_a20],A20_OFF | ||
| 480 | ; | ||
| 481 | ; compare 3 dwords at 0:80h and 1M:80h. if these are equal then | ||
| 482 | ; we can assume that a20 is off | ||
| 483 | ; | ||
| 484 | lds si,cs:low_mem | ||
| 485 | ASSUME DS:NOTHING | ||
| 486 | les di,cs:high_mem | ||
| 487 | ASSUME ES:NOTHING | ||
| 488 | mov cx,3 | ||
| 489 | cld | ||
| 490 | repe cmpsd | ||
| 491 | pop di | ||
| 492 | pop si | ||
| 493 | pop es | ||
| 494 | pop ds | ||
| 495 | ASSUME DS:DGROUP,ES:DGROUP | ||
| 496 | jcxz not_enabled | ||
| 497 | ; | ||
| 498 | ; a20 is on | ||
| 499 | ; | ||
| 500 | mov [state_a20],A20_ON | ||
| 501 | not_enabled: | ||
| 502 | pop cx | ||
| 503 | ret | ||
| 504 | estb_a20_state endp | ||
| 505 | |||
| 506 | ;*****************************************************************************; | ||
| 507 | ;*** get_init_a20_state - see if virtualised a20 is enabled or not ; | ||
| 508 | ; ; | ||
| 509 | ; ENTRY [state_a20] = A20 state at startup ; | ||
| 510 | ; ; | ||
| 511 | ; EXIT ZF set if A20 disabled ; | ||
| 512 | ; ZF not set if A20 enabled ; | ||
| 513 | ; ; | ||
| 514 | ; USES Flags ; | ||
| 515 | ;*****************************************************************************; | ||
| 516 | |||
| 517 | ASSUME DS:DGROUP,ES:NOTHING | ||
| 518 | |||
| 519 | get_init_a20_state proc near | ||
| 520 | ; | ||
| 521 | test [state_a20], A20_ON | ||
| 522 | ret | ||
| 523 | get_init_a20_state endp | ||
| 524 | |||
| 525 | LAST ends | ||
| 526 | |||
| 527 | end ; end of module | ||
| 528 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM b/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM new file mode 100644 index 0000000..430f849 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM | |||
| @@ -0,0 +1,567 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title ALLOCMEM - allocate memory for EMM Pages Pool | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: AllocMem - allocate memory for EMM Pages Pool | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: May 24,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 05/24/86 Original | ||
| 27 | ; 06/28/86 0.02 code read changes to various routines | ||
| 28 | ; 07/05/86 0.04 Changes due to segment re-org | ||
| 29 | ; 07/06/86 0.04 Made EXT_RES a define | ||
| 30 | ; 07/06/86 0.04 Changed to DGROUP assume | ||
| 31 | ; 07/10/86 0.05 added NOHIMEM flag | ||
| 32 | ; 06/02/88 pc change from VDISK allocation to INT-15 method | ||
| 33 | ; 07/26/88 isp completed work in changing over to int15 alloc | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ; Functional Description: | ||
| 37 | ; This module allocates the pool of memory to be used for the pool of | ||
| 38 | ; EMM pages. The pool of memory is allocated from "high" extended | ||
| 39 | ; memory (located in the 15-16 Meg range)and from "regular" extended memory | ||
| 40 | ; (starting at 1 Meg). This module attempts to allocate high memory first, | ||
| 41 | ; then extended memory. When allocating memory from either area, the memory | ||
| 42 | ; is allocated in 16k byte blocks which are aligned on a physical 4k boundary. | ||
| 43 | ; This module attempts to allocate extended memory using the int15 allocation | ||
| 44 | ; scheme. | ||
| 45 | ; | ||
| 46 | ; NOTE: if this module is compiled with NOHIMEM defined, then | ||
| 47 | ; this code will not attempt to use the OEM specific | ||
| 48 | ; "high" memory. | ||
| 49 | ; | ||
| 50 | ;****************************************************************************** | ||
| 51 | .lfcond | ||
| 52 | .386p | ||
| 53 | ; | ||
| 54 | ; | ||
| 55 | ;****************************************************************************** | ||
| 56 | ; P U B L I C D E C L A R A T I O N S | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; | ||
| 59 | public AllocMem | ||
| 60 | public DeallocMem | ||
| 61 | public xbase_addr_l ; data publics | ||
| 62 | public xbase_addr_h | ||
| 63 | public ext_size | ||
| 64 | public sys_size | ||
| 65 | |||
| 66 | page | ||
| 67 | ;****************************************************************************** | ||
| 68 | ; L O C A L C O N S T A N T S | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; | ||
| 71 | include vdmseg.inc | ||
| 72 | include vdmsel.inc | ||
| 73 | include emm386.inc | ||
| 74 | include driver.equ | ||
| 75 | include driver.str | ||
| 76 | include romxbios.equ | ||
| 77 | include desc.inc | ||
| 78 | include ascii_sm.equ | ||
| 79 | include oemdep.inc | ||
| 80 | include emmdef.inc | ||
| 81 | ; | ||
| 82 | EXT_RES equ 10h ; must be a power of 2. | ||
| 83 | ; | ||
| 84 | GET_VER equ 30h ; get dos version number | ||
| 85 | MSDOS equ 21h ; DOS interrupt | ||
| 86 | ; | ||
| 87 | FALSE equ 0 | ||
| 88 | TRUE equ not FALSE | ||
| 89 | |||
| 90 | ;****************************************************************************** | ||
| 91 | ; E X T E R N A L R E F E R E N C E S | ||
| 92 | ;****************************************************************************** | ||
| 93 | ; | ||
| 94 | _DATA segment | ||
| 95 | |||
| 96 | extrn dos_version:byte | ||
| 97 | extrn pool_size:word | ||
| 98 | extrn msg_flag:word | ||
| 99 | |||
| 100 | ifndef NOHIMEM | ||
| 101 | extrn hi_size:word ; size of hi memory in kbytes | ||
| 102 | extrn hi_alloc:word ; hi memory allocated | ||
| 103 | extrn hisys_alloc:word ; hi system memory allocated | ||
| 104 | ; in 4k byte blocks | ||
| 105 | endif | ||
| 106 | |||
| 107 | _DATA ends | ||
| 108 | |||
| 109 | |||
| 110 | LAST segment | ||
| 111 | extrn mappable_segs:byte ; mappable segment map | ||
| 112 | extrn set_ext:near ; routine to set amount of ext mem | ||
| 113 | ; reported by int15 handler | ||
| 114 | extrn memreq:near ; memory requirements for move | ||
| 115 | extrn pool_initialise:near ; initialise the pool of extended | ||
| 116 | ; memory | ||
| 117 | |||
| 118 | ifndef NOHIMEM | ||
| 119 | extrn hbuf_chk:near | ||
| 120 | extrn HiAlloc:near | ||
| 121 | extrn HiMod:near | ||
| 122 | endif | ||
| 123 | LAST ends | ||
| 124 | ; | ||
| 125 | page | ||
| 126 | ;****************************************************************************** | ||
| 127 | ; S E G M E N T D E F I N I T I O N | ||
| 128 | ;****************************************************************************** | ||
| 129 | |||
| 130 | page | ||
| 131 | ;****************************************************************************** | ||
| 132 | ; Data segment | ||
| 133 | ;****************************************************************************** | ||
| 134 | _DATA segment | ||
| 135 | ASSUME CS:DGROUP,DS:DGROUP | ||
| 136 | |||
| 137 | xbase_addr_l dw 0000h ; 24 bit address of beginning of | ||
| 138 | xbase_addr_h db 10h ; extended mem pool of EMM pages. (1M initially) | ||
| 139 | ext_size dw 0 ; size of extended memory allocated in kb | ||
| 140 | sys_size dw 0 ; size of system memory from 4000h in emm pool | ||
| 141 | total_mem dw 0 ; size of extended memory available at any moment | ||
| 142 | avail_mem dw 0 ; total size (hi+ext) available for MEMM | ||
| 143 | ; | ||
| 144 | |||
| 145 | _DATA ends | ||
| 146 | |||
| 147 | |||
| 148 | ;****************************************************************************** | ||
| 149 | ; | ||
| 150 | ; Code Segment | ||
| 151 | ; | ||
| 152 | ;****************************************************************************** | ||
| 153 | ; | ||
| 154 | LAST segment | ||
| 155 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 156 | |||
| 157 | page | ||
| 158 | ;****************************************************************************** | ||
| 159 | ; | ||
| 160 | ; AllocMem Allocate Extended memory for MEMM using the int15 | ||
| 161 | ; method of allocating extended memory. | ||
| 162 | ; | ||
| 163 | ; description: | ||
| 164 | ; This routine attempts to get the requested extended memory | ||
| 165 | ; from two sources: a) the himem area (just below 16M) first | ||
| 166 | ; and if not enough b) extended memory. Extended memory is | ||
| 167 | ; allocated using the int15 scheme. We do not care for | ||
| 168 | ; compatibility with vdisk. The memory we allocate either in | ||
| 169 | ; himem area or in extended memory must start at a 4k boundary | ||
| 170 | ; because we are using them as pages. | ||
| 171 | ; | ||
| 172 | ; entry: DS pts to DGROUP | ||
| 173 | ; DGROUP:[pool_size] = mem size requested (kbytes) | ||
| 174 | ; | ||
| 175 | ; exit: If extended memory pool space is not available then | ||
| 176 | ; set MEM_ERR_MSG bit in DGROUP:[msg_flag] and exit. | ||
| 177 | ; | ||
| 178 | ; | ||
| 179 | ; used: none | ||
| 180 | ; | ||
| 181 | ; stack: | ||
| 182 | ; | ||
| 183 | ; modified: ISP 07/26/88 Changed to a simple check for availability | ||
| 184 | ; of hi / ext memory and allocation of | ||
| 185 | ; of appropriate amounts of each. | ||
| 186 | ; | ||
| 187 | ; | ||
| 188 | ;****************************************************************************** | ||
| 189 | ; | ||
| 190 | AllocMem proc near | ||
| 191 | ; | ||
| 192 | push ax | ||
| 193 | push bx | ||
| 194 | push cx | ||
| 195 | push dx | ||
| 196 | push es | ||
| 197 | |||
| 198 | |||
| 199 | ; | ||
| 200 | ; 1. Check available hi/extended memory | ||
| 201 | ; | ||
| 202 | AM_getmem: | ||
| 203 | call xbuf_chk | ||
| 204 | test [msg_flag],MEM_ERR_MSG ;Q: memory error found ? | ||
| 205 | jz AM_nba ; N: continue with allocation | ||
| 206 | jmp AM_exit ; Y: exit | ||
| 207 | ; | ||
| 208 | ; 2. Allocate extended memory | ||
| 209 | ; | ||
| 210 | AM_nba: | ||
| 211 | call ExtAlloc ; alloc ext mem | ||
| 212 | |||
| 213 | ifndef NOHIMEM ; if HI memory in this model | ||
| 214 | ; | ||
| 215 | ; 3. Allocate Hi memory | ||
| 216 | ; | ||
| 217 | AM_halloc: | ||
| 218 | call HiAlloc ; Allocate hi memory | ||
| 219 | jnc AM_exit ; no error | ||
| 220 | or [msg_flag],MEM_ERR_MSG ; memory error | ||
| 221 | endif | ||
| 222 | |||
| 223 | ; | ||
| 224 | ; 4. Allocate system memory | ||
| 225 | ; | ||
| 226 | call SysAlloc | ||
| 227 | ; | ||
| 228 | AM_exit: | ||
| 229 | pop es | ||
| 230 | pop dx | ||
| 231 | pop cx | ||
| 232 | pop bx | ||
| 233 | pop ax | ||
| 234 | ret | ||
| 235 | AllocMem endp ; End of procedure | ||
| 236 | ; | ||
| 237 | page | ||
| 238 | ;****************************************************************************** | ||
| 239 | ; | ||
| 240 | ; DeallocMem Deallocate Extended memory for MEMM using the int15 | ||
| 241 | ; method of allocating extended memory. Note that since | ||
| 242 | ; we call this routine when we haven't already installed tc.) | ||
| 243 | ; the int15 handler we really don't need to do anything | ||
| 244 | ; as far as the regular extended memory is concerned. We | ||
| 245 | ; only need to deallocate hi memory if allocated. | ||
| 246 | ; | ||
| 247 | ; entry: DS pts to DGROUP | ||
| 248 | ; DGROUP:[hi_alloc] amount of hi memory to deallocate | ||
| 249 | ; | ||
| 250 | ; used: none | ||
| 251 | ; | ||
| 252 | ; stack: | ||
| 253 | ; | ||
| 254 | ; modif: 7/26/88 ISP Removed VDISK deallocation of extended memory | ||
| 255 | ;****************************************************************************** | ||
| 256 | ; | ||
| 257 | DeallocMem proc near | ||
| 258 | push ax | ||
| 259 | push bx | ||
| 260 | push cx | ||
| 261 | push dx | ||
| 262 | push si | ||
| 263 | push es | ||
| 264 | ; | ||
| 265 | ifndef NOHIMEM ; if high memory in this model | ||
| 266 | mov ax,[hi_alloc] ; get hi memory to deallocate | ||
| 267 | or ax,ax ; q: did we ever get any? | ||
| 268 | jz deall_hisys ; n: check hi system memory | ||
| 269 | neg ax ; # of 16 byte pieces to remove | ||
| 270 | mov [hi_alloc],0 ; make sure we never do it again | ||
| 271 | deall_hisys: | ||
| 272 | mov bx,[hisys_alloc] ; get hi system memory to deallocate | ||
| 273 | neg bx ; update by a negative amount | ||
| 274 | add bx,ax ; q: any hi or hisys to deallocate? | ||
| 275 | jz deall_ext ; n: don't waste our time doing it | ||
| 276 | sub bx,ax ; y: straighten our regs out | ||
| 277 | mov [hisys_alloc],0 ; make sure we don't do it again | ||
| 278 | call HImod ; modify memory. ignore any errors | ||
| 279 | deall_ext: | ||
| 280 | ; | ||
| 281 | endif ; end of conditional | ||
| 282 | pop es | ||
| 283 | pop si | ||
| 284 | pop dx | ||
| 285 | pop cx | ||
| 286 | pop bx | ||
| 287 | pop ax | ||
| 288 | ; | ||
| 289 | ret | ||
| 290 | DeallocMem endp | ||
| 291 | ; | ||
| 292 | page | ||
| 293 | ;****************************************************************************** | ||
| 294 | ; | ||
| 295 | ; xbuf_chk Extended memory pool check. | ||
| 296 | ; Check 1) for previously loaded MEMM,VDISKs in extended memory | ||
| 297 | ; 2) available memory pool space. (hi memory and extended) | ||
| 298 | ; | ||
| 299 | ; entry: DS = DGROUP | ||
| 300 | ; DGROUP:[pool_size] = mem size requested (kbytes) | ||
| 301 | ; | ||
| 302 | ; | ||
| 303 | ; exit: If hi memory pool space is available then | ||
| 304 | ; | ||
| 305 | ; DGROUP:[hi_size] = hi memory size allocated (kbytes). | ||
| 306 | ; | ||
| 307 | ; If extended memory pool space is necessary and available then | ||
| 308 | ; | ||
| 309 | ; DGROUP:[xbase_addr_h] and DGROUP:[xbase_addr_l] contain the | ||
| 310 | ; starting 24-bit address of MEMM extended memory pool. | ||
| 311 | ; | ||
| 312 | ; DGROUP:[pool_size] = mem size ALLOCATED (kbytes) | ||
| 313 | ; DGROUP:[total_mem] = total extended memory left after allocation | ||
| 314 | ; DGROUP:[avail_mem] = available memory for MEMM. | ||
| 315 | ; DGROUP:[ext_size] = extended memory size allocated (kbytes) | ||
| 316 | ; | ||
| 317 | ; If hi/extended memory pool space is not available then | ||
| 318 | ; set MEM_ERR_MSG bit in DGROUP:[msg_flag] and exit. | ||
| 319 | ; | ||
| 320 | ; used: none | ||
| 321 | ; | ||
| 322 | ; stack: | ||
| 323 | ; | ||
| 324 | ; modified: ISP 07/26/88 int15 allocation requires different check | ||
| 325 | ; on extended memory. substancial rewrite. | ||
| 326 | ;****************************************************************************** | ||
| 327 | ; | ||
| 328 | xbuf_chk proc near | ||
| 329 | ; | ||
| 330 | push ax | ||
| 331 | push bx | ||
| 332 | push cx | ||
| 333 | push dx | ||
| 334 | push di | ||
| 335 | ; | ||
| 336 | ; determine amount of extended memory and store it in total_mem | ||
| 337 | ; | ||
| 338 | mov ah,EXT_MEM ; function request - ext mem data | ||
| 339 | clc ; clear carry flag | ||
| 340 | int XBIOS ;Q: extended memory supported ? | ||
| 341 | ; | ||
| 342 | jnc store_ext ; Y: go to store the amount got | ||
| 343 | xor ax,ax ; N: Assume zero extended memory | ||
| 344 | store_ext: | ||
| 345 | mov [total_mem],ax | ||
| 346 | ; | ||
| 347 | ifndef NOHIMEM ; if high memory in this model | ||
| 348 | ; | ||
| 349 | ; check for hi memory | ||
| 350 | ; | ||
| 351 | call hbuf_chk ; get available hi memory in AX | ||
| 352 | jc xb_NoHiMem | ||
| 353 | mov [hi_size],ax ; save it | ||
| 354 | mov [avail_mem],ax ; update available memory | ||
| 355 | xb_NoHiMem: | ||
| 356 | mov ax,[pool_size] | ||
| 357 | cmp ax,[hi_size] ; q: enough? | ||
| 358 | ja get_ext ; n: try extended memory | ||
| 359 | mov [hi_size],ax ; y: just use enough | ||
| 360 | jmp x_buf_exit ; and exit | ||
| 361 | endif | ||
| 362 | |||
| 363 | get_ext: | ||
| 364 | mov ax,[total_mem] ; get size of extended memory available | ||
| 365 | ; Y: how much there ? | ||
| 366 | ; | ||
| 367 | ; we have to reserve enough memory here to ship the segments up hi. | ||
| 368 | ; | ||
| 369 | call memreq ; get memory requirements for our o | ||
| 370 | ; our grand operation in cx in K | ||
| 371 | cmp ax,cx ; lets see if we can satisfy | ||
| 372 | jbe x_buf_no_install ; if not we shan't install memm | ||
| 373 | |||
| 374 | push ax | ||
| 375 | sub ax,cx | ||
| 376 | cmp ax,64 + 64 ; we should try to leave enough memory | ||
| 377 | ; for himem and atleast four pages of | ||
| 378 | ; expanded memory. | ||
| 379 | pop ax | ||
| 380 | jbe x_buf_no_install ; if we don't have enough for this we | ||
| 381 | ; shouldn't install memm | ||
| 382 | ; | ||
| 383 | ; we can now get memory to shift things up. and intialise the manager of | ||
| 384 | ; this pool. | ||
| 385 | ; | ||
| 386 | sub ax,cx ; ax = start of this pool as an offset | ||
| 387 | ; in K from 1M | ||
| 388 | ; cx = size in K of this pool | ||
| 389 | call pool_initialise ; intialise the pool | ||
| 390 | or ax,ax ;Q: any extended memory ? | ||
| 391 | jz x_buf_2 ; N: If none go to set buf adj or no | ||
| 392 | ; memory error | ||
| 393 | ; ; Y: continue to process | ||
| 394 | ; | ||
| 395 | mov bx,[pool_size] ; get size requested | ||
| 396 | ; | ||
| 397 | ifndef NOHIMEM ; if high memory in this model | ||
| 398 | sub bx,[hi_size] ; adjust by the size already allocated | ||
| 399 | endif ; from the high memory | ||
| 400 | |||
| 401 | and ax,0fff0h ; round to 16k boundary | ||
| 402 | ; | ||
| 403 | ; it is necessary to support himem. So if we have a 64k block at 1M we | ||
| 404 | ; should leave it for himem. The himem we are talking about here is the | ||
| 405 | ; EMS 4.1 standard himem at 1M | ||
| 406 | ; | ||
| 407 | ; initialise reserved memory for himem | ||
| 408 | ; | ||
| 409 | xor cx,cx ; amount reserved for himem | ||
| 410 | ; | ||
| 411 | ; see if we have 64k available for himem | ||
| 412 | ; | ||
| 413 | cmp ax,64 ; Q:do we have 64k? | ||
| 414 | jb no_himem_alloc ; N: we reserve nothing for himem | ||
| 415 | ; Y: we should reserve 64k for himem | ||
| 416 | ; | ||
| 417 | ; reserve 64k for himem | ||
| 418 | ; | ||
| 419 | mov cx,64 | ||
| 420 | sub ax,cx | ||
| 421 | ; | ||
| 422 | no_himem_alloc: | ||
| 423 | ; | ||
| 424 | cmp ax,bx ; compare amount available to size needed | ||
| 425 | jae enough_mem ; Y: fine | ||
| 426 | mov bx,ax ; N: adjust size reuested to size avail | ||
| 427 | enough_mem: | ||
| 428 | ; | ||
| 429 | ; add back the memory reserved for himem as this figures in the size of | ||
| 430 | ; free extended memory | ||
| 431 | ; | ||
| 432 | add ax,cx ; adjust size to include amnt res. himem | ||
| 433 | sub ax,bx ; adjust the size of extended memory | ||
| 434 | ; after allocation | ||
| 435 | mov [total_mem],ax ; store size of extended mem available | ||
| 436 | ; | ||
| 437 | add [avail_mem],bx ; add memory available to memory pool | ||
| 438 | mov [ext_size],bx ; and indicate size allocated | ||
| 439 | ; | ||
| 440 | ; find the start address of extended memory allocated | ||
| 441 | ; | ||
| 442 | mov cx,1024 ; kb multiplier | ||
| 443 | mul cx ; dx:ax = ax*cx | ||
| 444 | add [xbase_addr_l],ax ; adjsut starting address of allocated mem | ||
| 445 | adc [xbase_addr_h],dl ; higher byte of 24 bit address | ||
| 446 | ; | ||
| 447 | x_buf_2: | ||
| 448 | ; | ||
| 449 | mov ax,[avail_mem] ; ax == Available memory | ||
| 450 | cmp ax,[pool_size] ; Q: Extended memory available? | ||
| 451 | jnb x_buf_exit ; Y: Go to finish | ||
| 452 | ; | ||
| 453 | not_enough: | ||
| 454 | or ax,ax ; Q: Any extended memory available? | ||
| 455 | jz x_buf_no_install ; N: Set error flag and exit | ||
| 456 | mov [pool_size],ax ; Y: Set pool_size to remaining memory | ||
| 457 | or [msg_flag],SIZE_ADJ_MSG ; Set buffer adjusted message bit | ||
| 458 | jmp short x_buf_exit ; And jump to exit | ||
| 459 | ; | ||
| 460 | x_buf_no_install: | ||
| 461 | or [msg_flag],MEM_ERR_MSG ; memory error found in x_bufchk | ||
| 462 | ; | ||
| 463 | x_buf_exit: | ||
| 464 | pop di | ||
| 465 | pop dx | ||
| 466 | pop cx | ||
| 467 | pop bx | ||
| 468 | pop ax | ||
| 469 | ret ; *** return *** | ||
| 470 | ; | ||
| 471 | xbuf_chk endp | ||
| 472 | ; | ||
| 473 | page | ||
| 474 | ;****************************************************************************** | ||
| 475 | ; | ||
| 476 | ; ExtAlloc - allocate extended memory - update break address for ext. mem. | ||
| 477 | ; | ||
| 478 | ; entry: DS pts to DGROUP | ||
| 479 | ; | ||
| 480 | ; exit: extended memory size | ||
| 481 | ; | ||
| 482 | ; used: none. int15 size reported by int 15 handler in MEMM adjusted. | ||
| 483 | ; | ||
| 484 | ; stack: | ||
| 485 | ; | ||
| 486 | ; modified: ISP 07/26/88 Substancially simplified. For int15 scheme | ||
| 487 | ; allocation is by lowering the size of int15 | ||
| 488 | ; reported extended memory size. | ||
| 489 | ; | ||
| 490 | ;****************************************************************************** | ||
| 491 | ExtAlloc proc near | ||
| 492 | ; | ||
| 493 | mov bx,[total_mem] ;size left after allocation to MEMM | ||
| 494 | call set_ext ; set this size in the int15 handler | ||
| 495 | ret | ||
| 496 | ; | ||
| 497 | ExtAlloc endp | ||
| 498 | ; | ||
| 499 | ;****************************************************************************** | ||
| 500 | ; | ||
| 501 | ; SysAlloc - allocate extended memory - update break address for ext. mem. | ||
| 502 | ; | ||
| 503 | ; entry: DS pts to DGROUP | ||
| 504 | ; | ||
| 505 | ; exit: system memory size | ||
| 506 | ; | ||
| 507 | ; used: none. | ||
| 508 | ; | ||
| 509 | ; stack: | ||
| 510 | ; | ||
| 511 | ; written: ISP 07/28/88 This allocates the system memory from 0000H | ||
| 512 | ; to A000h to the EMM pool. This is for the LIM | ||
| 513 | ; 4.0 implementation. | ||
| 514 | ; | ||
| 515 | ;****************************************************************************** | ||
| 516 | |||
| 517 | SysAlloc proc near | ||
| 518 | ; | ||
| 519 | push ax | ||
| 520 | push bx | ||
| 521 | push cx | ||
| 522 | ; | ||
| 523 | ; find end of memory reported by bios int 12 and round this to upper 16k. | ||
| 524 | ; | ||
| 525 | int 12h | ||
| 526 | add ax,0000fh ; | ||
| 527 | and ax,0fff0h ; round it 16k figure | ||
| 528 | ; | ||
| 529 | ; convert this to the a page # | ||
| 530 | ; | ||
| 531 | shr ax, 4 ; number of 16k pages | ||
| 532 | ; | ||
| 533 | ; start search for pages which can be reclaimed from the system mem. region | ||
| 534 | ; | ||
| 535 | mov cx,ax ; number of pages from pg0 to be examined | ||
| 536 | mov [sys_size],0 ; initialise the system memory allocate | ||
| 537 | xor bx,bx ; page # | ||
| 538 | |||
| 539 | jcxz find_sys_done | ||
| 540 | find_sys_page: | ||
| 541 | cmp cs:mappable_segs[bx], PAGE_MAPPABLE | ||
| 542 | jne find_next_sys | ||
| 543 | add [sys_size],16 ; page found add 16k to system mem size | ||
| 544 | find_next_sys: | ||
| 545 | inc bx | ||
| 546 | loop find_sys_page | ||
| 547 | find_sys_done: | ||
| 548 | |||
| 549 | mov ax,[sys_size] ; find the total memory found | ||
| 550 | add [pool_size],ax ; add this to the pool size | ||
| 551 | |||
| 552 | ; | ||
| 553 | pop cx | ||
| 554 | pop bx | ||
| 555 | pop ax | ||
| 556 | ret | ||
| 557 | |||
| 558 | SysAlloc endp | ||
| 559 | |||
| 560 | |||
| 561 | |||
| 562 | LAST ends ; End of segment | ||
| 563 | ; | ||
| 564 | end ; End of module | ||
| 565 | |||
| 566 | |||
| 567 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/ASCII_SM.EQU b/v4.0/src/MEMM/MEMM/ASCII_SM.EQU new file mode 100644 index 0000000..c4f656b --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ASCII_SM.EQU | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ASCII_SM.EQU - ASCII (1968) control characters (small version) | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 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 MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | NUL equ 0 ; 00 ^@ Null | ||
| 31 | BEL equ 7 ; 07 ^G Bell | ||
| 32 | BS equ 8 ; 08 ^H Backspace | ||
| 33 | TAB equ 9 ; 09 ^I (Horizontal) Tab | ||
| 34 | LF equ 10 ; 0A ^J Line Feed | ||
| 35 | FF equ 12 ; 0C ^L Form Feed | ||
| 36 | CR equ 13 ; 0D ^M Carriage Return | ||
| 37 | ASCII_ESC equ 27 ; 1B ^[ Escape | ||
| 38 | SPACE equ 32 ; 20 Space | ||
| 39 | DEL equ 127 ; 7F Delete/Rubout | ||
| 40 | |||
| 41 | .list ; end of ASCII_SM.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/DESC.INC b/v4.0/src/MEMM/MEMM/DESC.INC new file mode 100644 index 0000000..229fccb --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DESC.INC | |||
| @@ -0,0 +1,277 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: DESC.INC - Descriptor Table Definitions for 286/386 | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: January 31, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 01/31/86 Original | ||
| 24 | ; 04/07/86 A added bit map base to 386 TSS | ||
| 25 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 26 | ; 06/25/86 0.02 removed A0 macros | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ifndef INC_LIST | ||
| 31 | .xlist | ||
| 32 | endif | ||
| 33 | |||
| 34 | ; --------------------------------------------------- | ||
| 35 | ; | ||
| 36 | ; Definitions for the access byte in a descriptor | ||
| 37 | ; | ||
| 38 | ; --------------------------------------------------- | ||
| 39 | |||
| 40 | |||
| 41 | ; Following fields are common to segment and control descriptors | ||
| 42 | |||
| 43 | D_PRES equ 080h ; present in memory | ||
| 44 | D_NOTPRES equ 0 ; not present in memory | ||
| 45 | |||
| 46 | D_DPL0 equ 0 ; Ring 0 | ||
| 47 | D_DPL1 equ 020h ; Ring 1 | ||
| 48 | D_DPL2 equ 040h ; Ring 2 | ||
| 49 | D_DPL3 equ 060h ; Ring 3 | ||
| 50 | |||
| 51 | D_SEG equ 010h ; Segment descriptor | ||
| 52 | D_CTRL equ 0 ; Control descriptor | ||
| 53 | |||
| 54 | |||
| 55 | ; Following fields are specific to control descriptors | ||
| 56 | |||
| 57 | D_TSS equ 01h ; A Free TSS | ||
| 58 | D_LDT equ 02h ; LDT | ||
| 59 | D_TSS_BUSY equ 03h ; A Busy TSS | ||
| 60 | D_CALLGATE equ 04h ; call gate | ||
| 61 | D_TASKGATE equ 05h ; task gate | ||
| 62 | D_INTGATE equ 06h ; interrupt gate | ||
| 63 | D_TRAPGATE equ 07h ; trap gate | ||
| 64 | ; 8 is invalid | ||
| 65 | D_386TSS equ 9 ; available 386 TSS | ||
| 66 | ; 0ah - Intel Reserved | ||
| 67 | D_BUSY386TSS equ 0bh ; busy 386 TSS | ||
| 68 | D_386CALL_GATE equ 0ch ; 386 call gate | ||
| 69 | ; 0dh - Intel Reserved | ||
| 70 | D_386INT_GATE equ 0eh ; 386 interrupt gate | ||
| 71 | D_386TRAP_GATE equ 0fh ; 386 trap gate | ||
| 72 | |||
| 73 | ; Following fields are specific to segment descriptors | ||
| 74 | |||
| 75 | D_CODE equ 08h ; code | ||
| 76 | D_DATA equ 0 ; data | ||
| 77 | |||
| 78 | D_CONFORM equ 04h ; if code, conforming | ||
| 79 | D_EXPDN equ 04h ; if data, expand down | ||
| 80 | |||
| 81 | D_RX equ 02h ; if code, readable | ||
| 82 | D_X equ 0 ; if code, exec only | ||
| 83 | D_W equ 02h ; if data, writable | ||
| 84 | D_R equ 0 ; if data, read only | ||
| 85 | |||
| 86 | D_ACCESSED equ 1 ; segment accessed bit | ||
| 87 | |||
| 88 | |||
| 89 | ; Useful combination access rights bytes | ||
| 90 | |||
| 91 | D_DATA0 equ (D_PRES+D_DPL0+D_SEG+D_DATA+D_W) ; Ring 0 rw data | ||
| 92 | D_CODE0 equ (D_PRES+D_DPL0+D_SEG+D_CODE+D_RX) ; Ring 0 rx code | ||
| 93 | D_TRAP0 equ (D_PRES+D_DPL0+D_CTRL+D_TRAPGATE) ; Ring 0 trap gate | ||
| 94 | D_INT0 equ (D_PRES+D_DPL0+D_CTRL+D_INTGATE) ; Ring 0 int gate | ||
| 95 | D_TSS0 equ (D_PRES+D_DPL0+D_CTRL+D_TSS) ; Ring 0 TSS | ||
| 96 | D_386TSS0 equ (D_PRES+D_DPL0+D_CTRL+D_386TSS) ; Ring 0 TSS | ||
| 97 | D_LDT0 equ (D_PRES+D_DPL0+D_CTRL+D_LDT) ; Ring 0 LDT | ||
| 98 | D_386INT0 equ (D_PRES+D_DPL0+D_CTRL+D_386INT_GATE) ; Ring 0 int gate | ||
| 99 | |||
| 100 | ;D_DATA1 equ (D_PRES+D_DPL1+D_SEG+D_DATA+D_W) ; Ring 1 rw data | ||
| 101 | ;D_CODE1 equ (D_PRES+D_DPL1+D_SEG+D_CODE+D_RX) ; Ring 1 rx code | ||
| 102 | |||
| 103 | ;D_DATA2 equ (D_PRES+D_DPL2+D_SEG+D_DATA+D_W) ; Ring 2 rw data | ||
| 104 | ;D_CODE2 equ (D_PRES+D_DPL2+D_SEG+D_CODE+D_RX) ; Ring 2 rx code | ||
| 105 | |||
| 106 | D_DATA3 equ (D_PRES+D_DPL3+D_SEG+D_DATA+D_W) ; Ring 3 rw data | ||
| 107 | D_CODE3 equ (D_PRES+D_DPL3+D_SEG+D_CODE+D_RX) ; Ring 3 rx code | ||
| 108 | D_INT3 equ (D_PRES+D_DPL3+D_CTRL+D_INTGATE) ; Ring 3 int gate | ||
| 109 | D_GATE3 equ (D_PRES+D_DPL3+D_CTRL+D_CALLGATE) ; Ring 3 call gate | ||
| 110 | D_386INT3 equ (D_PRES+D_DPL3+D_CTRL+D_386INT_GATE) ; Ring 3 int gate | ||
| 111 | |||
| 112 | ; 386 Extensions | ||
| 113 | |||
| 114 | D_B_BIT equ (1 SHL 6) ; 32 bit stack offsets | ||
| 115 | |||
| 116 | |||
| 117 | ; Masks for selector fields | ||
| 118 | |||
| 119 | SELECTOR_MASK equ 0fff8h ; selector index | ||
| 120 | SEL_LOW_MASK equ 0f8h ; mask for low byte of sel indx | ||
| 121 | TABLE_MASK equ 04h ; table bit | ||
| 122 | RPL_MASK equ 03h ; privilige bits | ||
| 123 | RPL_CLR equ not 03h ; clear ring bits | ||
| 124 | |||
| 125 | |||
| 126 | ; Machine Status Word bits | ||
| 127 | |||
| 128 | MSW_PROTECT equ 1 ; virtual mode bit | ||
| 129 | |||
| 130 | |||
| 131 | ; System IOPL | ||
| 132 | |||
| 133 | SYS_IOPL equ 3000h ; wide open | ||
| 134 | CLEAR_IOPL equ 0cfffh ; mask to remove IOPL bits | ||
| 135 | |||
| 136 | |||
| 137 | ; Kernel Stack Size (TO BE ADDED) | ||
| 138 | |||
| 139 | STK_SIZE equ 4000h ; TO BE ADDED | ||
| 140 | |||
| 141 | |||
| 142 | ; -------------------------------------------------- | ||
| 143 | ; | ||
| 144 | ; Macros for creating descriptor table entries | ||
| 145 | ; | ||
| 146 | ; -------------------------------------------------- | ||
| 147 | |||
| 148 | |||
| 149 | |||
| 150 | ; structure for 386 descriptor | ||
| 151 | |||
| 152 | desc struc | ||
| 153 | LIMIT dw 0 ; offset of last byte in segment | ||
| 154 | BASE_LOW dw 0 ; Low 16 bits of 24 bit base address | ||
| 155 | BASE_HIGH db 0 ; High 8 bits of 24 bit base address | ||
| 156 | RIGHTS db 0 ; access rights | ||
| 157 | RES386 db 0 ; reserved for 386 | ||
| 158 | BASE_XHI db 0 ; High 8 bits of 32 bit base address | ||
| 159 | desc ends | ||
| 160 | |||
| 161 | ; MASK for RES386 | ||
| 162 | |||
| 163 | R_GRAN equ 10000000b ; granularity bit | ||
| 164 | R_AVL equ 00010000b ; available | ||
| 165 | R_LIMIT_XHI equ 00001111b ; limit bits 16..19 | ||
| 166 | |||
| 167 | ; IDT_ENTRY - for interrupt and task gate definitions in IDT | ||
| 168 | |||
| 169 | IDT_ENTRY macro sel, off, acc | ||
| 170 | dw off ; offset | ||
| 171 | dw sel ; selector | ||
| 172 | db 0 ; word count, unused for trap/int gates | ||
| 173 | db acc ; access rights byte | ||
| 174 | dw 0 ; reserved, must be 0 for 386 | ||
| 175 | endm | ||
| 176 | |||
| 177 | |||
| 178 | ; GDT_ENTRY - for static initialisation of GDT entries | ||
| 179 | |||
| 180 | GDT_ENTRY macro BaseLow, BaseHi, Size, Access | ||
| 181 | dw Size - 1 ; segment limit | ||
| 182 | dw BaseLow ; low word of 24 bit base address | ||
| 183 | db BaseHi ; high byte of base address | ||
| 184 | db Access ; access rights byte | ||
| 185 | dw 0 ; reserved, must be 0 for 386 | ||
| 186 | endm | ||
| 187 | |||
| 188 | |||
| 189 | ; LDT_ENTRY - for static initialisation of LDT entries | ||
| 190 | |||
| 191 | LDT_ENTRY macro BaseLow, BaseHi, Size, Access | ||
| 192 | dw Size - 1 ; segment limit | ||
| 193 | dw BaseLow ; low word of 24 bit base address | ||
| 194 | db BaseHi ; high byte of base address | ||
| 195 | db Access ; access rights byte | ||
| 196 | dw 0 ; reserved, must be 0 for 386 | ||
| 197 | endm | ||
| 198 | |||
| 199 | |||
| 200 | ;*** 286 TSS Format | ||
| 201 | ; | ||
| 202 | |||
| 203 | TSS286STRUC struc | ||
| 204 | |||
| 205 | TSS286_BackLink dw 0 ; back link selector to TSS | ||
| 206 | TSS286_SP0 dw 0 ; ring 0 sp | ||
| 207 | TSS286_SS0 dw 0 ; ring 0 ss | ||
| 208 | TSS286_SP1 dw 0 ; ring 1 sp | ||
| 209 | TSS286_SS1 dw 0 ; ring 1 ss | ||
| 210 | TSS286_SP2 dw 0 ; ring 2 sp | ||
| 211 | TSS286_SS2 dw 0 ; ring 2 ss | ||
| 212 | TSS286_IP dw 0 ; entry point IP | ||
| 213 | TSS286_Flags dw 0 ; flag word | ||
| 214 | TSS286_AX dw 0 ; AX | ||
| 215 | TSS286_CX dw 0 ; CX | ||
| 216 | TSS286_DX dw 0 ; DX | ||
| 217 | TSS286_BX dw 0 ; BX | ||
| 218 | TSS286_SP dw 0 ; SP | ||
| 219 | TSS286_BP dw 0 ; BP | ||
| 220 | TSS286_SI dw 0 ; SI | ||
| 221 | TSS286_DI dw 0 ; DI | ||
| 222 | TSS286_ES dw 0 ; ES | ||
| 223 | TSS286_CS dw 0 ; CS | ||
| 224 | TSS286_SS dw 0 ; SS | ||
| 225 | TSS286_DS dw 0 ; DS | ||
| 226 | TSS286_LDT dw 0 ; LDT | ||
| 227 | |||
| 228 | TSS286STRUC ends | ||
| 229 | |||
| 230 | ;*** 386 TSS Format | ||
| 231 | ; | ||
| 232 | |||
| 233 | TSS386STRUC struc | ||
| 234 | |||
| 235 | TSS386_BackLink dw 0 ; back link selector to TSS | ||
| 236 | TSS386_Unused1 dw 0 ; unused | ||
| 237 | TSS386_ESP0lo dw 0 ; ring 0 ESP low word | ||
| 238 | TSS386_ESP0hi dw 0 ; ring 0 ESP high word | ||
| 239 | TSS386_SS0 dw 0 ; ring 0 SS | ||
| 240 | TSS386_Unused2 dw 0 ; unused | ||
| 241 | TSS386_ESP1 dd 0 ; ring 1 ESP | ||
| 242 | TSS386_SS1 dw 0 ; ring 1 SS | ||
| 243 | TSS386_Unused3 dw 0 ; unused | ||
| 244 | TSS386_ESP2 dd 0 ; ring 2 ESP | ||
| 245 | TSS386_SS2 dw 0 ; ring 2 SS | ||
| 246 | TSS386_Unused4 dw 0 ; unused | ||
| 247 | TSS386_CR3 dd 0 ; CR3 | ||
| 248 | TSS386_EIP dd 0 ; EIP | ||
| 249 | TSS386_EFLAGS dd 0 ; EFLAGS | ||
| 250 | TSS386_EAX dd 0 ; EAX | ||
| 251 | TSS386_ECX dd 0 ; ECX | ||
| 252 | TSS386_EDX dd 0 ; EDX | ||
| 253 | TSS386_EBX dd 0 ; EBX | ||
| 254 | TSS386_ESP dd 0 ; ESP | ||
| 255 | TSS386_EBP dd 0 ; EBP | ||
| 256 | TSS386_ESI dd 0 ; ESI | ||
| 257 | TSS386_EDI dd 0 ; EDI | ||
| 258 | TSS386_ES dw 0 ; ES | ||
| 259 | TSS386_Unused5 dw 0 ; Unused | ||
| 260 | TSS386_CS dw 0 ; CS | ||
| 261 | TSS386_Unused6 dw 0 ; Unused | ||
| 262 | TSS386_SS dw 0 ; SS | ||
| 263 | TSS386_Unused7 dw 0 ; Unused | ||
| 264 | TSS386_DS dw 0 ; DS | ||
| 265 | TSS386_Unused8 dw 0 ; Unused | ||
| 266 | TSS386_FS dw 0 ; FS | ||
| 267 | TSS386_Unused9 dw 0 ; Unused | ||
| 268 | TSS386_GS dw 0 ; GS | ||
| 269 | TSS386_Unused10 dw 0 ; Unused | ||
| 270 | TSS386_LDT dw 0 ; LDT | ||
| 271 | TSS386_Unused11 dw 0 ; Unused | ||
| 272 | TaskAttributes dw 0 ; Task Attributes | ||
| 273 | BitMapBase dw 0 ; offset of Base of Bit Map | ||
| 274 | TSS386STRUC ends | ||
| 275 | |||
| 276 | .list ; end of DESC.INC | ||
| 277 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/DISP.INC b/v4.0/src/MEMM/MEMM/DISP.INC new file mode 100644 index 0000000..96eeb7b --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DISP.INC | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | extrn PrintString:near | ||
| 2 | extrn PrintHex:near | ||
| 3 | |||
| 4 | display macro string | ||
| 5 | local dbs,disp_exit | ||
| 6 | pushf | ||
| 7 | push ds | ||
| 8 | push es | ||
| 9 | |||
| 10 | push cs | ||
| 11 | pop ds | ||
| 12 | push cs | ||
| 13 | pop es | ||
| 14 | |||
| 15 | push si | ||
| 16 | mov si,offset cs:dbs | ||
| 17 | call PrintString | ||
| 18 | pop si | ||
| 19 | pop es | ||
| 20 | pop ds | ||
| 21 | popf | ||
| 22 | jmp disp_exit | ||
| 23 | |||
| 24 | dbs db &string,0 | ||
| 25 | |||
| 26 | disp_exit: | ||
| 27 | endm | ||
| 28 | |||
| 29 | content macro reg | ||
| 30 | pushf | ||
| 31 | push ds | ||
| 32 | push es | ||
| 33 | push ax | ||
| 34 | |||
| 35 | mov ax,reg | ||
| 36 | |||
| 37 | push cs | ||
| 38 | pop ds | ||
| 39 | push cs | ||
| 40 | pop es | ||
| 41 | |||
| 42 | call PrintHex | ||
| 43 | |||
| 44 | pop ax | ||
| 45 | pop es | ||
| 46 | pop ds | ||
| 47 | popf | ||
| 48 | endm | ||
| 49 | |||
| 50 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/DMA.INC b/v4.0/src/MEMM/MEMM/DMA.INC new file mode 100644 index 0000000..06bed73 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DMA.INC | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ELIM.INC - include for LIM I/O traps (DMA ports) | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: April 9, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 04/09/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; 07/01/86 0.03 DMA trapping related equates added | ||
| 26 | ; | ||
| 27 | ; DATE AUTHOR DESCRIPTION | ||
| 28 | ; ------- -------- ------------------------------------------------------- | ||
| 29 | ; 06/21/88 ISP Removed the Intel Above Board Port Definitions | ||
| 30 | ; 07/27/88 JHB Added Channel 4 ports, ports for Mode Regs and changed | ||
| 31 | ; DMARegRec and DMARegBuf structure definitions - lifted | ||
| 32 | ; from vdmad.inc in Win386/2.03. | ||
| 33 | ; - Jaywant H Bharadwaj | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ifndef INC_LIST | ||
| 37 | .xlist | ||
| 38 | endif | ||
| 39 | ; | ||
| 40 | ; | ||
| 41 | ; DMA related ports | ||
| 42 | ; | ||
| 43 | DMA_P0 equ 0087h ; DMA page register for Channel 0 | ||
| 44 | DMA_P1 equ 0083h ; DMA page register for Channel 1 | ||
| 45 | DMA_P2 equ 0081h ; DMA page register for Channel 2 | ||
| 46 | DMA_P3 equ 0082h ; DMA page register for Channel 3 | ||
| 47 | DMA_P5 equ 008Bh ; DMA page register for Channel 5 | ||
| 48 | DMA_P6 equ 0089h ; DMA page register for Channel 6 | ||
| 49 | DMA_P7 equ 008Ah ; DMA page register for Channel 7 | ||
| 50 | DMA_P4 equ 0080h ; dummy page reg for channel 4 | ||
| 51 | |||
| 52 | DMA_B0 equ 0000h ; DMA base register for Channel 0 | ||
| 53 | DMA_C0 equ 0001h ; DMA count register for Channel 0 | ||
| 54 | DMA_B1 equ 0002h ; DMA base register for Channel 1 | ||
| 55 | DMA_C1 equ 0003h ; DMA count register for Channel 1 | ||
| 56 | DMA_B2 equ 0004h ; DMA base register for Channel 2 | ||
| 57 | DMA_C2 equ 0005h ; DMA count register for Channel 2 | ||
| 58 | DMA_B3 equ 0006h ; DMA base register for Channel 3 | ||
| 59 | DMA_C3 equ 0007h ; DMA count register for Channel 3 | ||
| 60 | DMA_B4 equ 00C0h ; DMA base register for Channel 4 | ||
| 61 | DMA_C4 equ 00C2h ; DMA count register for Channel 4 | ||
| 62 | DMA_B5 equ 00C4h ; DMA base register for Channel 5 | ||
| 63 | DMA_C5 equ 00C6h ; DMA count register for Channel 5 | ||
| 64 | DMA_B6 equ 00C8h ; DMA base register for Channel 6 | ||
| 65 | DMA_C6 equ 00CAh ; DMA count register for Channel 6 | ||
| 66 | DMA_B7 equ 00CCh ; DMA base register for Channel 7 | ||
| 67 | DMA_C7 equ 00CEh ; DMA count register for Channel 7 | ||
| 68 | |||
| 69 | DMA1_CLR_FF equ 000Ch ; clear flip-flop cmd for channels 0-3 | ||
| 70 | DMA2_CLR_FF equ 00D8h ; clear flip-flop cmd for channels 5-7 | ||
| 71 | |||
| 72 | |||
| 73 | DMA1_MODE equ 000Bh ; Mode register for channels 0-3 | ||
| 74 | DMA2_MODE equ 00D6h ; Mode register for channels 4-7 | ||
| 75 | |||
| 76 | DMA_M_CHANNEL equ 03h ; Mask for channel | ||
| 77 | DMA_M_OPERATION equ 0Ch ; Mask for operation | ||
| 78 | DMA_M_16BIT equ 040h ; 16bit transfers (PS/2 ext mode) | ||
| 79 | |||
| 80 | DMA_M_VERIFY equ 0 ; Verify operation | ||
| 81 | DMA_M_WRITE equ 4 ; Write | ||
| 82 | |||
| 83 | |||
| 84 | ;************************************************************************** | ||
| 85 | ; New defintions for DMARegRec and DMARegBuf - 7/27/88 | ||
| 86 | ; | ||
| 87 | ; | ||
| 88 | ; DMA Register Save Structure | ||
| 89 | ; | ||
| 90 | |||
| 91 | ; | ||
| 92 | ; note: the DMA code in ELIMTRAP.ASM is tuned to this structure's size = 16 | ||
| 93 | ; if you change the size, you had better change the code ! | ||
| 94 | ; LinAdr and PhysAdr have to be dwords | ||
| 95 | ; count though 16 bits long is left as a dword since the rest of the ported | ||
| 96 | ; 386 code is dependent on this structure being 16 bytes long. | ||
| 97 | ; | ||
| 98 | |||
| 99 | DMARegRec struc | ||
| 100 | DMALinAdr dd 00000000 ; Channel Linear Base Register | ||
| 101 | DMAPhyAdr dd 00000000 ; Channel Physical Base Register | ||
| 102 | DMACount dd 00000000 ; Channel Count Register | ||
| 103 | DMAPagePort db ? ; byte addr of page reg | ||
| 104 | DMABasePort db ? ; byte addr of base addr reg | ||
| 105 | DMACntPort db ? ; byte addr of cnt addr reg | ||
| 106 | DMAMode db ? ; Mode register | ||
| 107 | DMARegRec ends | ||
| 108 | |||
| 109 | DMARegBuf struc | ||
| 110 | Chnl0 db (size DMARegRec - 4) dup (00), DMA_P0, DMA_B0, DMA_C0, 0 | ||
| 111 | Chnl1 db (size DMARegRec - 4) dup (00), DMA_P1, DMA_B1, DMA_C1, 0 | ||
| 112 | Chnl2 db (size DMARegRec - 4) dup (00), DMA_P2, DMA_B2, DMA_C2, 0 | ||
| 113 | Chnl3 db (size DMARegRec - 4) dup (00), DMA_P3, DMA_B3, DMA_C3, 0 | ||
| 114 | Chnl4 db (size DMARegRec - 4) dup (00), DMA_P4, DMA_B4, DMA_C4, DMA_M_16BIT | ||
| 115 | Chnl5 db (size DMARegRec - 4) dup (00), DMA_P5, DMA_B5, DMA_C5, DMA_M_16BIT | ||
| 116 | Chnl6 db (size DMARegRec - 4) dup (00), DMA_P6, DMA_B6, DMA_C6, DMA_M_16BIT | ||
| 117 | Chnl7 db (size DMARegRec - 4) dup (00), DMA_P7, DMA_B7, DMA_C7, DMA_M_16BIT | ||
| 118 | DMAFF1 db 00 ; Controller 1 FlipFlop State | ||
| 119 | DMAFF2 db 00 ; Controller 2 FlipFlop State | ||
| 120 | DMA_Xfun db 0 ; Extended Operation Function | ||
| 121 | DMA_Xchn db 0 ; Extended Operation Channel | ||
| 122 | DMARegBuf ends | ||
| 123 | |||
| 124 | DMAREG_CTRL2_INDEX equ 4 * 2 ; 2 * 1st channel # on 2nd cntlr | ||
| 125 | |||
| 126 | |||
| 127 | ;************************************************************************** | ||
| 128 | ; | ||
| 129 | ; Macros taken from PS2.INC in Win/386 2.03 | ||
| 130 | ; | ||
| 131 | ;-------------------------------------------------------------------------- | ||
| 132 | |||
| 133 | ; STANDARD ROM BIOS MACHINE TYPES used in ROM_BIOS_Machine_ID | ||
| 134 | |||
| 135 | RBMI_PC equ 0FFh | ||
| 136 | RBMI_PCXT equ 0FEh | ||
| 137 | RBMI_PCjr equ 0FDh | ||
| 138 | RBMI_PCAT equ 0FCh | ||
| 139 | RBMI_PCConvertible equ 0F9h | ||
| 140 | RBMI_Sys80 equ 0F8h | ||
| 141 | RBMI_CompaqPortable equ 000h | ||
| 142 | |||
| 143 | ;****************************************************************************** | ||
| 144 | ; DMA_WADDR_TO_BADDR - convert internal DMA word address to a byte address | ||
| 145 | ; | ||
| 146 | ; ENTRY: 386 PROTECTED MODE | ||
| 147 | ; DS -> 0 | ||
| 148 | ; ES -> 0 | ||
| 149 | ; EAX - Word Address | ||
| 150 | ; | ||
| 151 | ; EXIT: EAX - Byte address | ||
| 152 | ; | ||
| 153 | ; USED: | ||
| 154 | ;------------------------------------------------------------------------------ | ||
| 155 | DMA_WADDR_TO_BADDR MACRO | ||
| 156 | LOCAL Not_AT | ||
| 157 | extrn ROM_BIOS_Machine_ID:byte | ||
| 158 | |||
| 159 | cmp [ROM_BIOS_Machine_ID], RBMI_Sys80 | ||
| 160 | jbe short Not_AT ; If running on EBIOS machine | ||
| 161 | |||
| 162 | ror eax,16 ; AX = high word | ||
| 163 | shr al,1 ; adjust for D0 null in page reg | ||
| 164 | rol eax,17 ; EAX = address w/ adjust for | ||
| 165 | ; 'A0' offset | ||
| 166 | Not_At: | ||
| 167 | shl ecx, 1 ; Adjust for word units | ||
| 168 | ENDM | ||
| 169 | |||
| 170 | |||
| 171 | ;****************************************************************************** | ||
| 172 | ; DMA_BADDR_TO_WADDR - convert internal DMA byte address to a word address | ||
| 173 | ; | ||
| 174 | ; ENTRY: 386 PROTECTED MODE | ||
| 175 | ; DS -> 0 | ||
| 176 | ; ES -> 0 | ||
| 177 | ; EAX - Word Address | ||
| 178 | ; | ||
| 179 | ; EXIT: EAX - Byte address | ||
| 180 | ; | ||
| 181 | ; USED: | ||
| 182 | ;------------------------------------------------------------------------------ | ||
| 183 | DMA_BADDR_TO_WADDR MACRO | ||
| 184 | LOCAL Not_AT | ||
| 185 | extrn ROM_BIOS_Machine_ID:byte | ||
| 186 | |||
| 187 | cmp [ROM_BIOS_Machine_ID], RBMI_Sys80 | ||
| 188 | jbe short Not_AT ; If running on EBIOS machine | ||
| 189 | |||
| 190 | shr eax, 1 ; Adjust for implied 'A0' | ||
| 191 | push ax ; Save A16-A1 | ||
| 192 | xor ax, ax | ||
| 193 | shl eax, 1 ; Adjust for unused Pg Reg D0 | ||
| 194 | pop ax ; Restore A16-A1 | ||
| 195 | Not_At: | ||
| 196 | ENDM | ||
| 197 | |||
| 198 | |||
| 199 | |||
| 200 | ;**************************************************************************** | ||
| 201 | ; Old definitions for memm LIM 3.2 - not used anymore - 7/27/88 | ||
| 202 | ; | ||
| 203 | ; DMA Register Save Structure | ||
| 204 | ; | ||
| 205 | ;Chnl1Idx equ 0 ; Address offset in Address tables | ||
| 206 | ;Chnl2Idx equ 2 ; Address offset in Address tables | ||
| 207 | ;Chnl3Idx equ 4 ; Address offset in Address tables | ||
| 208 | ;Chnl5Idx equ 6 ; Address offset in Address tables | ||
| 209 | ;Chnl6Idx equ 8 ; Address offset in Address tables | ||
| 210 | ;Chnl7Idx equ 10 ; Address offset in Address tables | ||
| 211 | ; | ||
| 212 | ;DMARegRec struc | ||
| 213 | ;DMALinAdr dd 00000000 ; Channel Linear Base Register | ||
| 214 | ;DMAPhyAdr dd 00000000 ; Channel Physical Base Register | ||
| 215 | ;DMACount dd 00000000 ; Channel Count Register | ||
| 216 | ;DMAChnlIdx db ? ; Channel identifier index | ||
| 217 | ;DMARegRec ends | ||
| 218 | ; | ||
| 219 | ;DMARegBuf struc | ||
| 220 | ;Chnl1 db (size DMARegRec - 1) dup (00), Chnl1Idx | ||
| 221 | ;Chnl2 db (size DMARegRec - 1) dup (00), Chnl2Idx | ||
| 222 | ;Chnl3 db (size DMARegRec - 1) dup (00), Chnl3Idx | ||
| 223 | ;Chnl5 db (size DMARegRec - 1) dup (00), Chnl5Idx | ||
| 224 | ;Chnl6 db (size DMARegRec - 1) dup (00), Chnl6Idx | ||
| 225 | ;Chnl7 db (size DMARegRec - 1) dup (00), Chnl7Idx | ||
| 226 | ;DMAFF1 db 00 ; Controller 1 FlipFlop State | ||
| 227 | ;DMAFF2 db 00 ; Controller 2 FlipFlop State | ||
| 228 | ;DMARegBuf ends | ||
| 229 | ; | ||
| 230 | ;****************************************************************************** | ||
| 231 | |||
| 232 | |||
| 233 | .list ; end of ELIM.INC | ||
| 234 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/DRIVER.EQU b/v4.0/src/MEMM/MEMM/DRIVER.EQU new file mode 100644 index 0000000..8e12e90 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DRIVER.EQU | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: DRIVER.EQU - MS-DOS device driver equates | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 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 MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | ; | ||
| 31 | ; Device driver attribute equates | ||
| 32 | ; | ||
| 33 | CHAR_DEV EQU 8000H | ||
| 34 | IOCTL_SUP EQU 4000H | ||
| 35 | NON_IBM EQU 2000H | ||
| 36 | CLK_DEV EQU 0008H | ||
| 37 | NUL_DEV EQU 0004H | ||
| 38 | OUT_DEV EQU 0002H | ||
| 39 | INP_DEV EQU 0001H | ||
| 40 | ; | ||
| 41 | ; Device driver command code equates | ||
| 42 | ; | ||
| 43 | INIT EQU 0 | ||
| 44 | MEDIA EQU 1 | ||
| 45 | BUILD_BPB EQU 2 | ||
| 46 | IOCTL_INP EQU 3 | ||
| 47 | INPUT_READ EQU 4 | ||
| 48 | NON_INPUT EQU 5 | ||
| 49 | INP_STATUS EQU 6 | ||
| 50 | INP_FLUSH EQU 7 | ||
| 51 | OUTPUT_WRITE EQU 8 | ||
| 52 | OUTPUT_VER EQU 9 | ||
| 53 | OUT_STATUS EQU 10 | ||
| 54 | OUT_FLUSH EQU 11 | ||
| 55 | IOCTL_OUT EQU 12 | ||
| 56 | ; | ||
| 57 | ; Device driver status word equates | ||
| 58 | ; | ||
| 59 | ERROR EQU 8000H | ||
| 60 | BUSY EQU 0200H | ||
| 61 | DONE EQU 0100H | ||
| 62 | ERR EQU 80H | ||
| 63 | BUS EQU 02H | ||
| 64 | DON EQU 01H | ||
| 65 | ; | ||
| 66 | ; Device driver i/o control status word equates | ||
| 67 | ; | ||
| 68 | ISDEV EQU 0080H | ||
| 69 | EOF EQU 0040H | ||
| 70 | RAW EQU 0020H | ||
| 71 | ISCLK EQU 0008H | ||
| 72 | ISNUL EQU 0004H | ||
| 73 | ISCOT EQU 0002H | ||
| 74 | ISCIN EQU 0001H | ||
| 75 | ; | ||
| 76 | ; Device driver error code equates | ||
| 77 | ; | ||
| 78 | WRT_PROT_VIO EQU 00H | ||
| 79 | UNK_UNIT EQU 01H | ||
| 80 | DEV_NOT_RDY EQU 02H | ||
| 81 | UNK_COMMAND EQU 03H | ||
| 82 | CRC_ERROR EQU 04H | ||
| 83 | BAD_DRIVE EQU 05H | ||
| 84 | SEEK_ERROR EQU 06H | ||
| 85 | UNK_MEDIA EQU 07H | ||
| 86 | SEC_NOT_FND EQU 08H | ||
| 87 | OUT_OF_PAPER EQU 09H | ||
| 88 | WRITE_FAULT EQU 0AH | ||
| 89 | READ_FAULT EQU 0BH | ||
| 90 | GENERAL_FAIL EQU 0CH | ||
| 91 | ; | ||
| 92 | ; Device driver function call equates | ||
| 93 | ; | ||
| 94 | NUMBER_UNITS EQU BYTE PTR 0DH | ||
| 95 | ENDING_ADDR EQU DWORD PTR 0EH | ||
| 96 | BPB_ARRAY EQU DWORD PTR 12H | ||
| 97 | DESC_BYTE EQU BYTE PTR 0DH | ||
| 98 | RETURN_INFO EQU BYTE PTR 0EH | ||
| 99 | BUFFER_ADDR EQU DWORD PTR 0EH | ||
| 100 | BPB_PTR EQU DWORD PTR 12H | ||
| 101 | TRANS_COUNT EQU WORD PTR 12H | ||
| 102 | TRANS_ADDR EQU WORD PTR 14H | ||
| 103 | BYTE_READ EQU BYTE PTR 0DH | ||
| 104 | |||
| 105 | .list ; end of DRIVER.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/DRIVER.STR b/v4.0/src/MEMM/MEMM/DRIVER.STR new file mode 100644 index 0000000..dfb7e90 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DRIVER.STR | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: DRIVER.STR - MS-DOS Device Driver structures | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 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 MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | |||
| 31 | ; | ||
| 32 | ; Device driver header structure | ||
| 33 | ; | ||
| 34 | DEVICE_HEADER STRUC | ||
| 35 | DEV_PTR DD 0 | ||
| 36 | DEV_ATTR DW 0 | ||
| 37 | STRAT_PTR DW 0 | ||
| 38 | INT_PTR DW 0 | ||
| 39 | DEV_NAME DB " " | ||
| 40 | DEVICE_HEADER ENDS | ||
| 41 | DEV_OFF EQU WORD PTR DEV_PTR | ||
| 42 | DEV_SEG EQU WORD PTR DEV_PTR+2 | ||
| 43 | ; | ||
| 44 | ; Device driver request header structure | ||
| 45 | ; | ||
| 46 | REQUEST_HEADER STRUC | ||
| 47 | HDR_LEN DB 0 | ||
| 48 | UNIT_CODE DB 0 | ||
| 49 | COMMAND_CODE DB 0 | ||
| 50 | STATUS_WORD DW 0 | ||
| 51 | RES_AREA DB 0,0,0,0,0,0,0,0 | ||
| 52 | OP_DATA DB 0 | ||
| 53 | REQUEST_HEADER ENDS | ||
| 54 | ; | ||
| 55 | ; Initialize command request header structure | ||
| 56 | ; | ||
| 57 | INIT_HEADER STRUC | ||
| 58 | DB 13 DUP (?) | ||
| 59 | NUM_UNITS DB 0 | ||
| 60 | BRK_ADDR DD 0 | ||
| 61 | ARG_PTR DD 0 | ||
| 62 | DRV_NUM DB 0 | ||
| 63 | INIT_HEADER ENDS | ||
| 64 | BRK_OFF EQU WORD PTR BRK_ADDR | ||
| 65 | BRK_SEG EQU WORD PTR BRK_ADDR+2 | ||
| 66 | ARG_OFF EQU WORD PTR ARG_PTR | ||
| 67 | ARG_SEG EQU WORD PTR ARG_PTR+2 | ||
| 68 | ; | ||
| 69 | ; Media check request header structure | ||
| 70 | ; | ||
| 71 | MEDIA_HEADER STRUC | ||
| 72 | DB 13 DUP (?) | ||
| 73 | MEDIA_BYTE DB 0 | ||
| 74 | RET_BYTE DB 0 | ||
| 75 | VOL_PTR DD 0 | ||
| 76 | MEDIA_HEADER ENDS | ||
| 77 | VOL_OFF EQU WORD PTR VOL_PTR | ||
| 78 | VOL_SEG EQU WORD PTR VOL_PTR+2 | ||
| 79 | ; | ||
| 80 | ; Build BPB request header structure | ||
| 81 | ; | ||
| 82 | BPB_HEADER STRUC | ||
| 83 | DB 13 DUP (?) | ||
| 84 | BPB_DESC DB 0 | ||
| 85 | BPB_TRANS DD 0 | ||
| 86 | TABLE_PTR DD 0 | ||
| 87 | BPB_HEADER ENDS | ||
| 88 | BPB_OFF EQU WORD PTR BPB_TRANS | ||
| 89 | BPB_SEG EQU WORD PTR BPB_TRANS+2 | ||
| 90 | TABLE_OFF EQU WORD PTR TABLE_PTR | ||
| 91 | TABLE_SEG EQU WORD PTR TABLE_PTR+2 | ||
| 92 | ; | ||
| 93 | ; Input/output request header structure | ||
| 94 | ; | ||
| 95 | IO_HEADER STRUC | ||
| 96 | DB 13 DUP (?) | ||
| 97 | IO_DESC DB 0 | ||
| 98 | IO_TRANS DD 0 | ||
| 99 | IO_COUNT DW 0 | ||
| 100 | IO_START DW 0 | ||
| 101 | VOL_ID DD 0 | ||
| 102 | IO_HEADER ENDS | ||
| 103 | IO_OFF EQU WORD PTR IO_TRANS | ||
| 104 | IO_SEG EQU WORD PTR IO_TRANS+2 | ||
| 105 | ID_OFF EQU WORD PTR VOL_ID | ||
| 106 | ID_SEG EQU WORD PTR VOL_ID+2 | ||
| 107 | ; | ||
| 108 | ; Device driver BIOS Parameter Block (BPB) structure | ||
| 109 | ; | ||
| 110 | BPB_BLOCK STRUC | ||
| 111 | BYTES_PER_SECTOR DW 0 | ||
| 112 | SECTORS_PER_ALLOC DB 0 | ||
| 113 | RES_SECTORS DW 0 | ||
| 114 | NUM_FATS DB 0 | ||
| 115 | ROOT_DIR_ENTRIES DW 0 | ||
| 116 | NUMBER_OF_SECTORS DW 0 | ||
| 117 | MEDIA_DESC DB 0 | ||
| 118 | SECTORS_PER_FAT DW 0 | ||
| 119 | BPB_BLOCK ENDS | ||
| 120 | ; | ||
| 121 | ; Device driver BIOS Parameter option block structure | ||
| 122 | ; | ||
| 123 | BPB_OPTION STRUC | ||
| 124 | SECTORS_PER_TRACK DW 0 | ||
| 125 | NUMBER_OF_HEADS DW 0 | ||
| 126 | HIDDEN_SECTORS DW 0 | ||
| 127 | BPB_OPTION ENDS | ||
| 128 | |||
| 129 | .list ; end of DRIVER.STR | ||
diff --git a/v4.0/src/MEMM/MEMM/EKBD.ASM b/v4.0/src/MEMM/MEMM/EKBD.ASM new file mode 100644 index 0000000..9f8a8f2 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EKBD.ASM | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EKBD - get keyboard make codes | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 8 | ; | ||
| 9 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 10 | ; | ||
| 11 | ; Module: EKBD - basic keyboard handler for error handler routine | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date : June 10,1986 | ||
| 16 | ; | ||
| 17 | ; Author: | ||
| 18 | ; | ||
| 19 | ;****************************************************************************** | ||
| 20 | ; | ||
| 21 | ; CHANGES: | ||
| 22 | ; | ||
| 23 | ; DATE REVISION DESCRIPTION | ||
| 24 | ; -------- -------- ------------------------------------------------------ | ||
| 25 | ; 06/10/86 Original | ||
| 26 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 27 | ; 07/06/86 0.04 Changed assumes to DGROUP | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; | ||
| 31 | ; Functional description: Return keyboard code while ignoring any break | ||
| 32 | ; or command codes. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | page | ||
| 36 | .386P | ||
| 37 | ; | ||
| 38 | include vdmseg.inc | ||
| 39 | include kbd.inc | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; Public Declarations | ||
| 42 | ;****************************************************************************** | ||
| 43 | ; | ||
| 44 | public egetc ; get a character | ||
| 45 | public WaitKBD ; wait for keyboard ready | ||
| 46 | ;****************************************************************************** | ||
| 47 | ; Externs | ||
| 48 | ;****************************************************************************** | ||
| 49 | _TEXT segment | ||
| 50 | _TEXT ends | ||
| 51 | |||
| 52 | _DATA segment | ||
| 53 | _DATA ends | ||
| 54 | ; | ||
| 55 | ;****************************************************************************** | ||
| 56 | ; Equates | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; | ||
| 59 | ; | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; LOCAL DATA | ||
| 62 | ;****************************************************************************** | ||
| 63 | _DATA segment | ||
| 64 | _DATA ends | ||
| 65 | ; | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; | ||
| 68 | ; egetc - read a character from keyboard | ||
| 69 | ; | ||
| 70 | ; entry: NONE | ||
| 71 | ; | ||
| 72 | ; exit: al = make code | ||
| 73 | ; ZF = 0 | ||
| 74 | ; | ||
| 75 | ; or ZF = 1 if no code available | ||
| 76 | ; | ||
| 77 | ; used: none | ||
| 78 | ; | ||
| 79 | ; stack: | ||
| 80 | ; | ||
| 81 | ;****************************************************************************** | ||
| 82 | _TEXT segment | ||
| 83 | ASSUME CS:_TEXT, DS:DGROUP, ES:DGROUP | ||
| 84 | egetc proc near | ||
| 85 | ; | ||
| 86 | in al,KbStatus ; get status | ||
| 87 | test al,1 ; q: is there anything out there? | ||
| 88 | jz kret ; n: return | ||
| 89 | ; ; y: disable keyboard | ||
| 90 | call WaitKBD ; wait til 8042 ready for input | ||
| 91 | mov al,0adh ; disable keyboard interface | ||
| 92 | out KbStatus,al | ||
| 93 | in al,KbData ; get character | ||
| 94 | cmp al,7fh ; q: break or control word? | ||
| 95 | jae ign_chr ; y: ignore it | ||
| 96 | cmp al,80h ; clear ZF | ||
| 97 | jmp enaKB ; go enable keyboard | ||
| 98 | ign_chr: | ||
| 99 | mov al,0 ; return an invalid character | ||
| 100 | ; but preserve ZF | ||
| 101 | enaKB: | ||
| 102 | pushf ; save flags | ||
| 103 | push ax ; save character | ||
| 104 | call WaitKBD | ||
| 105 | mov al,0aeh ; enable keyboard | ||
| 106 | out KbStatus,al | ||
| 107 | pop ax | ||
| 108 | popf | ||
| 109 | kret: | ||
| 110 | ret | ||
| 111 | egetc endp | ||
| 112 | ; | ||
| 113 | ;****************************************************************************** | ||
| 114 | ; | ||
| 115 | ; WaitKBD - wait for status to indicate ready for new command | ||
| 116 | ; | ||
| 117 | ; entry: NONE | ||
| 118 | ; | ||
| 119 | ; exit: NONE | ||
| 120 | ; | ||
| 121 | ; used: al | ||
| 122 | ; | ||
| 123 | ; stack: | ||
| 124 | ; | ||
| 125 | ;****************************************************************************** | ||
| 126 | WaitKBD proc near | ||
| 127 | push cx | ||
| 128 | xor cx,cx ; do 65536 times | ||
| 129 | wait: | ||
| 130 | in al,KbStatus | ||
| 131 | test al,BufFull ; q: busy? | ||
| 132 | loopnz wait ; y: try again | ||
| 133 | ; | ||
| 134 | pop cx ; n: return | ||
| 135 | ret | ||
| 136 | WaitKBD endp | ||
| 137 | |||
| 138 | _TEXT ENDS | ||
| 139 | END | ||
diff --git a/v4.0/src/MEMM/MEMM/ELIM.INC b/v4.0/src/MEMM/MEMM/ELIM.INC new file mode 100644 index 0000000..47f0bc0 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ELIM.INC | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ELIM.INC - include for LIM I/O traps (DMA ports) | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: April 9, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 04/09/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; 07/01/86 0.03 DMA trapping related equates added | ||
| 26 | ; | ||
| 27 | ; DATE AUTHOR DESCRIPTION | ||
| 28 | ; ------- -------- ------------------------------------------------------- | ||
| 29 | ; 06/21/88 ISP Removed the Intel Above Board Port Definitions | ||
| 30 | ; 07/27/88 JHB Added Channel 4 ports, ports for Mode Regs and changed | ||
| 31 | ; DMARegRec and DMARegBuf structure definitions - lifted | ||
| 32 | ; from vdmad.inc in Win386/2.03. | ||
| 33 | ; - Jaywant H Bharadwaj | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ifndef INC_LIST | ||
| 37 | .xlist | ||
| 38 | endif | ||
| 39 | ; | ||
| 40 | ; | ||
| 41 | ; DMA related ports | ||
| 42 | ; | ||
| 43 | DMA_P0 equ 0087h ; DMA page register for Channel 0 | ||
| 44 | DMA_P1 equ 0083h ; DMA page register for Channel 1 | ||
| 45 | DMA_P2 equ 0081h ; DMA page register for Channel 2 | ||
| 46 | DMA_P3 equ 0082h ; DMA page register for Channel 3 | ||
| 47 | DMA_P5 equ 008Bh ; DMA page register for Channel 5 | ||
| 48 | DMA_P6 equ 0089h ; DMA page register for Channel 6 | ||
| 49 | DMA_P7 equ 008Ah ; DMA page register for Channel 7 | ||
| 50 | DMA_P4 equ 0080h ; dummy page reg for channel 4 | ||
| 51 | |||
| 52 | DMA_B0 equ 0000h ; DMA base register for Channel 0 | ||
| 53 | DMA_C0 equ 0001h ; DMA count register for Channel 0 | ||
| 54 | DMA_B1 equ 0002h ; DMA base register for Channel 1 | ||
| 55 | DMA_C1 equ 0003h ; DMA count register for Channel 1 | ||
| 56 | DMA_B2 equ 0004h ; DMA base register for Channel 2 | ||
| 57 | DMA_C2 equ 0005h ; DMA count register for Channel 2 | ||
| 58 | DMA_B3 equ 0006h ; DMA base register for Channel 3 | ||
| 59 | DMA_C3 equ 0007h ; DMA count register for Channel 3 | ||
| 60 | DMA_B4 equ 00C0h ; DMA base register for Channel 4 | ||
| 61 | DMA_C4 equ 00C2h ; DMA count register for Channel 4 | ||
| 62 | DMA_B5 equ 00C4h ; DMA base register for Channel 5 | ||
| 63 | DMA_C5 equ 00C6h ; DMA count register for Channel 5 | ||
| 64 | DMA_B6 equ 00C8h ; DMA base register for Channel 6 | ||
| 65 | DMA_C6 equ 00CAh ; DMA count register for Channel 6 | ||
| 66 | DMA_B7 equ 00CCh ; DMA base register for Channel 7 | ||
| 67 | DMA_C7 equ 00CEh ; DMA count register for Channel 7 | ||
| 68 | |||
| 69 | DMA1_CLR_FF equ 000Ch ; clear flip-flop cmd for channels 0-3 | ||
| 70 | DMA2_CLR_FF equ 00D8h ; clear flip-flop cmd for channels 5-7 | ||
| 71 | |||
| 72 | |||
| 73 | DMA1_MODE equ 000Bh ; Mode register for channels 0-3 | ||
| 74 | DMA2_MODE equ 00D6h ; Mode register for channels 4-7 | ||
| 75 | |||
| 76 | DMA_M_CHANNEL equ 03h ; Mask for channel | ||
| 77 | DMA_M_OPERATION equ 0Ch ; Mask for operation | ||
| 78 | DMA_M_16BIT equ 040h ; 16bit transfers (PS/2 ext mode) | ||
| 79 | |||
| 80 | DMA_M_VERIFY equ 0 ; Verify operation | ||
| 81 | DMA_M_WRITE equ 4 ; Write | ||
| 82 | |||
| 83 | |||
| 84 | ;************************************************************************** | ||
| 85 | ; New defintions for DMARegRec and DMARegBuf - 7/27/88 | ||
| 86 | ; | ||
| 87 | ; | ||
| 88 | ; DMA Register Save Structure | ||
| 89 | ; | ||
| 90 | |||
| 91 | ; | ||
| 92 | ; note: the DMA code in ELIMTRAP.ASM is tuned to this structure's size = 16 | ||
| 93 | ; if you change the size, you had better change the code ! | ||
| 94 | ; LinAdr and PhysAdr have to be dwords | ||
| 95 | ; count though 16 bits long is left as a dword since the rest of the ported | ||
| 96 | ; 386 code is dependent on this structure being 16 bytes long. | ||
| 97 | ; | ||
| 98 | |||
| 99 | DMARegRec struc | ||
| 100 | DMALinAdr dd 00000000 ; Channel Linear Base Register | ||
| 101 | DMAPhyAdr dd 00000000 ; Channel Physical Base Register | ||
| 102 | DMACount dd 00000000 ; Channel Count Register | ||
| 103 | DMAPagePort db ? ; byte addr of page reg | ||
| 104 | DMABasePort db ? ; byte addr of base addr reg | ||
| 105 | DMACntPort db ? ; byte addr of cnt addr reg | ||
| 106 | DMAMode db ? ; Mode register | ||
| 107 | DMARegRec ends | ||
| 108 | |||
| 109 | DMARegBuf struc | ||
| 110 | Chnl0 db (size DMARegRec - 4) dup (00), DMA_P0, DMA_B0, DMA_C0, 0 | ||
| 111 | Chnl1 db (size DMARegRec - 4) dup (00), DMA_P1, DMA_B1, DMA_C1, 0 | ||
| 112 | Chnl2 db (size DMARegRec - 4) dup (00), DMA_P2, DMA_B2, DMA_C2, 0 | ||
| 113 | Chnl3 db (size DMARegRec - 4) dup (00), DMA_P3, DMA_B3, DMA_C3, 0 | ||
| 114 | Chnl4 db (size DMARegRec - 4) dup (00), DMA_P4, DMA_B4, DMA_C4, DMA_M_16BIT | ||
| 115 | Chnl5 db (size DMARegRec - 4) dup (00), DMA_P5, DMA_B5, DMA_C5, DMA_M_16BIT | ||
| 116 | Chnl6 db (size DMARegRec - 4) dup (00), DMA_P6, DMA_B6, DMA_C6, DMA_M_16BIT | ||
| 117 | Chnl7 db (size DMARegRec - 4) dup (00), DMA_P7, DMA_B7, DMA_C7, DMA_M_16BIT | ||
| 118 | DMAFF1 db 00 ; Controller 1 FlipFlop State | ||
| 119 | DMAFF2 db 00 ; Controller 2 FlipFlop State | ||
| 120 | DMA_Xfun db 0 ; Extended Operation Function | ||
| 121 | DMA_Xchn db 0 ; Extended Operation Channel | ||
| 122 | DMARegBuf ends | ||
| 123 | |||
| 124 | DMAREG_CTRL2_INDEX equ 4 * 2 ; 2 * 1st channel # on 2nd cntlr | ||
| 125 | |||
| 126 | |||
| 127 | .list ; end of ELIM.INC | ||
| 128 | |||
diff --git a/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM b/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM new file mode 100644 index 0000000..d431f0b --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM | |||
| @@ -0,0 +1,268 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title ELIMFUNC - MEMM functions module | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: ELIMFUNC - entry point for VDM functions | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: May 24,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 04/24/86 Original From EMML LIM driver. | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; 07/05/86 0.04 Added segment R_CODE | ||
| 29 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 30 | ; 07/10/86 0.05 jmp $+2 before "POPF" | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; Functional Description: | ||
| 34 | ; This module contains the ON/OFF functionality code for activating/ | ||
| 35 | ; deactivating EMM386 from DOS. Functions in _TEXT to reduce code in | ||
| 36 | ; R_CODE segment. | ||
| 37 | ; | ||
| 38 | ;****************************************************************************** | ||
| 39 | .lfcond | ||
| 40 | .386p | ||
| 41 | page | ||
| 42 | ;****************************************************************************** | ||
| 43 | ; P U B L I C D E C L A R A T I O N S | ||
| 44 | ;****************************************************************************** | ||
| 45 | ; | ||
| 46 | public ELIM_Entry | ||
| 47 | public EFunTab | ||
| 48 | public EFUN_CNT | ||
| 49 | ; | ||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; L O C A L C O N S T A N T S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | include vdmseg.inc | ||
| 56 | |||
| 57 | FALSE equ 0 | ||
| 58 | TRUE equ not FALSE | ||
| 59 | |||
| 60 | ;****************************************************************************** | ||
| 61 | ; E X T E R N A L R E F E R E N C E S | ||
| 62 | ;****************************************************************************** | ||
| 63 | ; | ||
| 64 | _DATA segment | ||
| 65 | extrn Active_Status:byte | ||
| 66 | extrn Auto_Mode:byte | ||
| 67 | _DATA ends | ||
| 68 | |||
| 69 | _TEXT segment | ||
| 70 | extrn _AutoUpdate:near ; update auto mode status | ||
| 71 | extrn GoVirtual:near | ||
| 72 | extrn RRProc:near ; Return processor to real mode(RRTrap) | ||
| 73 | _TEXT ends | ||
| 74 | |||
| 75 | page | ||
| 76 | ;****************************************************************************** | ||
| 77 | ; S E G M E N T D E F I N I T I O N | ||
| 78 | ;****************************************************************************** | ||
| 79 | ; | ||
| 80 | ;****************************************************************************** | ||
| 81 | ; | ||
| 82 | ; Code Segment R_CODE | ||
| 83 | ; | ||
| 84 | ;****************************************************************************** | ||
| 85 | ; | ||
| 86 | R_CODE segment | ||
| 87 | assume cs:R_CODE, ds:DGROUP, es:DGROUP | ||
| 88 | ; | ||
| 89 | ; ELIM functions table - far calls | ||
| 90 | ; | ||
| 91 | EFunTab label dword | ||
| 92 | dw offset E_GetStatus | ||
| 93 | dw seg _TEXT | ||
| 94 | |||
| 95 | dw offset E_ONOFF | ||
| 96 | dw seg _TEXT | ||
| 97 | |||
| 98 | EFUN_CNT equ ($-EFunTab)/4 | ||
| 99 | |||
| 100 | page | ||
| 101 | ;****************************************************************************** | ||
| 102 | ; ELIM_Entry - entry point for general ELIM functions | ||
| 103 | ; | ||
| 104 | ; THIS IS A FAR CALL ROUTINE | ||
| 105 | ; | ||
| 106 | ; ENTRY: REAL or VIRTUAL mode only | ||
| 107 | ; AH = 0 => get current status of VDM/EMM386 | ||
| 108 | ; AH = 1 => ON/OFF/AUTO | ||
| 109 | ; | ||
| 110 | ; EXIT: EMM386 is activated/deactivated if possible | ||
| 111 | ; NC => no errors. | ||
| 112 | ; CY => ERROR occured. | ||
| 113 | ; AH = error number | ||
| 114 | ; AH= 01 =>invalid function. | ||
| 115 | ; | ||
| 116 | ; USED: none | ||
| 117 | ; | ||
| 118 | ;****************************************************************************** | ||
| 119 | ELIM_Entry proc far | ||
| 120 | ; | ||
| 121 | push bx | ||
| 122 | push ds | ||
| 123 | ; | ||
| 124 | mov bx,seg DGROUP | ||
| 125 | mov ds,bx | ||
| 126 | ; | ||
| 127 | cmp ah,EFUN_CNT ;Q: valid function # | ||
| 128 | jae EE_inv_func ; N: return error | ||
| 129 | xor bx,bx ; Y: exec function | ||
| 130 | mov bl,ah ; bx = function # | ||
| 131 | shl bx,2 ; dword index | ||
| 132 | call CS:EFunTab[bx] ; call the function | ||
| 133 | ; | ||
| 134 | EE_exit: | ||
| 135 | pop ds | ||
| 136 | pop bx | ||
| 137 | ret | ||
| 138 | ; | ||
| 139 | EE_inv_func: | ||
| 140 | mov ah,01 | ||
| 141 | stc | ||
| 142 | jmp short EE_exit | ||
| 143 | ; | ||
| 144 | ELIM_Entry endp | ||
| 145 | |||
| 146 | R_CODE ends | ||
| 147 | |||
| 148 | page | ||
| 149 | ;****************************************************************************** | ||
| 150 | ; | ||
| 151 | ; Code Segment _TEXT | ||
| 152 | ; | ||
| 153 | ;****************************************************************************** | ||
| 154 | _TEXT segment | ||
| 155 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 156 | |||
| 157 | ;****************************************************************************** | ||
| 158 | ; E_GetStatus - get ELIM/VDM status | ||
| 159 | ; | ||
| 160 | ; ENTRY: AH = 0 | ||
| 161 | ; DS = DGROUP | ||
| 162 | ; | ||
| 163 | ; EXIT: AH = 0 => ELIM ON | ||
| 164 | ; = 1 => ELIM OFF | ||
| 165 | ; = 2 => ELIM in AUTO mode (ON) | ||
| 166 | ; = 3 => ELIM in AUTO mode (OFF) | ||
| 167 | ; | ||
| 168 | ; USED: none | ||
| 169 | ; | ||
| 170 | ;****************************************************************************** | ||
| 171 | E_GetStatus proc far | ||
| 172 | ; | ||
| 173 | xor ah,ah ; init to on | ||
| 174 | cmp [Auto_Mode],0 ; Q: auto mode ? | ||
| 175 | je not_auto ; N: try on/off | ||
| 176 | mov ah,2 ; Y: indicate as such | ||
| 177 | not_auto: | ||
| 178 | cmp [Active_Status],0 ;Q: is ELIM active ? | ||
| 179 | jne EGS_exit ; Y: exit with status = 0/2 | ||
| 180 | inc ah ; N: exit with status = 1/3 | ||
| 181 | EGS_exit: | ||
| 182 | ret | ||
| 183 | ; | ||
| 184 | E_GetStatus endp | ||
| 185 | |||
| 186 | ;****************************************************************************** | ||
| 187 | ; E_ONOFF - general ON/OFF code for ELIM | ||
| 188 | ; | ||
| 189 | ; ENTRY: AH = 1 | ||
| 190 | ; AL = 0 => ON | ||
| 191 | ; AL = 1 => OFF | ||
| 192 | ; AL = 2 => AUTO | ||
| 193 | ; DS = DGROUP | ||
| 194 | ; | ||
| 195 | ; EXIT: Virtual mode and ELIM ON | ||
| 196 | ; OR Real mode and ELIM OFF | ||
| 197 | ; | ||
| 198 | ; USED: none | ||
| 199 | ; | ||
| 200 | ;****************************************************************************** | ||
| 201 | E_ONOFF proc far | ||
| 202 | ; | ||
| 203 | cmp al,0 ;Q: turn it on ? | ||
| 204 | jne EOO_OFF ; N: check for OFF/AUTO | ||
| 205 | cmp [Active_Status],0 ; Y: Q: is it already active ? | ||
| 206 | jne EOO_AUTO_OFF ; Y: then just leave | ||
| 207 | mov [Active_Status],1 ; N: then go to virtual mode | ||
| 208 | mov [Auto_Mode],0 ; and clear auto mode | ||
| 209 | call GoVirtual | ||
| 210 | jmp short EOO_OK | ||
| 211 | EOO_OFF: | ||
| 212 | cmp al,1 ;Q: turn it off ? | ||
| 213 | jne EOO_AUTO ; N: check for AUTO mode | ||
| 214 | |||
| 215 | ; | ||
| 216 | ; we are not providing the ability to turn emm off. | ||
| 217 | ; | ||
| 218 | ; cmp [Active_Status],0 ; Y: Q: is it already OFF ? | ||
| 219 | ; je EOO_AUTO_OFF ; Y: then just leave | ||
| 220 | ; mov [Active_Status],0 ; N: then go to real mode | ||
| 221 | ; mov [Auto_Mode],0 ; and clear auto mode | ||
| 222 | ; call RRProc ; put processor in real mode | ||
| 223 | ; jmp short EOO_OK | ||
| 224 | |||
| 225 | jmp short EOO_inv | ||
| 226 | |||
| 227 | |||
| 228 | EOO_AUTO_OFF: | ||
| 229 | ; cmp [Auto_Mode],0 ; q: auto mode already off? | ||
| 230 | ; jz EOO_OK ; y: forget it | ||
| 231 | ; mov [Auto_Mode],0 ; n: clear it | ||
| 232 | ; jmp short EOO_OK ; and update status | ||
| 233 | |||
| 234 | jmp short EOO_inv | ||
| 235 | |||
| 236 | |||
| 237 | EOO_AUTO: | ||
| 238 | cmp al,2 ;Q: go to auto mode ? | ||
| 239 | jne EOO_inv ; N: invalid function | ||
| 240 | ; cmp [Auto_Mode],0 ; Y: Q: is it already in auto mode | ||
| 241 | ; jne EOO_OK ; Y: then just leave | ||
| 242 | ; mov [Auto_Mode],1 ; N: then go to auto mode | ||
| 243 | ; call _AutoUpdate ; | ||
| 244 | |||
| 245 | jmp short EOO_inv | ||
| 246 | ; | ||
| 247 | ; leave with no errors | ||
| 248 | ; | ||
| 249 | EOO_OK: | ||
| 250 | clc | ||
| 251 | |||
| 252 | EOO_exit: | ||
| 253 | ret | ||
| 254 | ; | ||
| 255 | ; invalide ON/OFF/AUTO function call | ||
| 256 | ; | ||
| 257 | EOO_inv: | ||
| 258 | mov ah,1 | ||
| 259 | stc | ||
| 260 | jmp short EOO_exit | ||
| 261 | ; | ||
| 262 | E_ONOFF endp | ||
| 263 | |||
| 264 | ; | ||
| 265 | _TEXT ends | ||
| 266 | |||
| 267 | end | ||
| 268 | |||
diff --git a/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM b/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM new file mode 100644 index 0000000..1036c33 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM | |||
| @@ -0,0 +1,1560 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | title DMATRAP.ASM - Trap handlers for DMA ports | ||
| 5 | ;****************************************************************************** | ||
| 6 | ; | ||
| 7 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 8 | ; | ||
| 9 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 10 | ; | ||
| 11 | ; Module: DMATRAP.ASM - Trap Handlers for DMA ports | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date: April 9, 1986 | ||
| 16 | ; | ||
| 17 | ; Author: | ||
| 18 | ; | ||
| 19 | ;****************************************************************************** | ||
| 20 | ; | ||
| 21 | ; Change log: | ||
| 22 | ; | ||
| 23 | ; DATE REVISION DESCRIPTION | ||
| 24 | ; -------- -------- ------------------------------------------------------- | ||
| 25 | ; 04/09/86 Original | ||
| 26 | ; 06/18/86 0.01 Modified LIM_Map to handle all 4 boards and call | ||
| 27 | ; page mapping routine in EMMLIB.LIB | ||
| 28 | ; 06/27/86 0.02 Made _page_frame_address indexing dword (was word) | ||
| 29 | ; | ||
| 30 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 31 | ; 07/01/86 0.03 Added DMA support routines | ||
| 32 | ; 07/02/86 0.03 Fixed CNT size vs. length problem | ||
| 33 | ; 07/06/86 0.04 Made _pft386 a ptr to _pft386 array | ||
| 34 | ; 07/06/86 0.04 now sets _window array also | ||
| 35 | ; 08/11/86 0.05 moved IO_Trap code for LIM DMA trapping here | ||
| 36 | ; 06/09/88 remove IOT_LIM, LIMMap, and InitELIM since we don't | ||
| 37 | ; have any EMM hardware to trap and emulate now (Paulch) | ||
| 38 | ; 07/26/88 reintroduced initelim removing iab port trap (ISP) | ||
| 39 | ; | ||
| 40 | ; 07/27/88 Started rewriting the DMA port trap handlers - similar to the | ||
| 41 | ; code in VDMAD.ASM in Win/386 V2.03 | ||
| 42 | ; - Jaywant H Bharadwaj | ||
| 43 | ; | ||
| 44 | ;***************************************************************************** | ||
| 45 | |||
| 46 | |||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | ; Functional Description: | ||
| 50 | ; | ||
| 51 | ; Monitors writes/reads to the DMA ports. | ||
| 52 | ; Reads are simple - return the value saved in DMARegSav structure. | ||
| 53 | ; On a write to Page/Base/count Reg port - | ||
| 54 | ; user specifies a linear address. DMAs can handle only physical addresses. | ||
| 55 | ; Therefore, the actual physical address has to be written into the Page and | ||
| 56 | ; base Address Reg. Also the DMA transfer area may not be physically contiguous. | ||
| 57 | ; If it isn't we should remap the linear address so that it is physically | ||
| 58 | ; contiguous. | ||
| 59 | ; | ||
| 60 | ; We never know when a DMA is started. Hence on every access to the Page/Base | ||
| 61 | ; or count Register we make sure that the linear address specified by the user | ||
| 62 | ; maps to a physical address which is contiguous over the DMA transfer area. | ||
| 63 | ; This has to be done even if the count register is altered since the user | ||
| 64 | ; might be relying on the previous contents of Page/Addr Regs which may not be | ||
| 65 | ; contiguous anymore. | ||
| 66 | ; | ||
| 67 | ; All routines except InitDMA are entered through protected mode only. | ||
| 68 | ; | ||
| 69 | ;****************************************************************************** | ||
| 70 | |||
| 71 | .lfcond ; list false conditionals | ||
| 72 | .386p | ||
| 73 | |||
| 74 | page | ||
| 75 | ;****************************************************************************** | ||
| 76 | ; P U B L I C D E C L A R A T I O N S | ||
| 77 | ;****************************************************************************** | ||
| 78 | |||
| 79 | ; | ||
| 80 | ; routines called from C | ||
| 81 | ; | ||
| 82 | public _GetPte | ||
| 83 | public _SetPte | ||
| 84 | public _GetCRSEntry | ||
| 85 | public _GetDMALinAdr | ||
| 86 | public _Exchange16K | ||
| 87 | public _FatalError | ||
| 88 | |||
| 89 | public InitELIM ; initialization routine for LIMulator | ||
| 90 | public InitDMA ; init DMA register save area | ||
| 91 | public DMARegSav | ||
| 92 | public _DMA_Pages | ||
| 93 | public DMA_Pages | ||
| 94 | public _DMA_PAGE_COUNT | ||
| 95 | public DMA_PAGE_COUNT | ||
| 96 | |||
| 97 | |||
| 98 | |||
| 99 | public DMA_DMAFixup | ||
| 100 | public DMABase0 | ||
| 101 | public DMABase1 | ||
| 102 | public DMABase2 | ||
| 103 | public DMABase3 | ||
| 104 | public DMABase5 | ||
| 105 | public DMABase6 | ||
| 106 | public DMABase7 | ||
| 107 | |||
| 108 | public DMACnt0 | ||
| 109 | public DMACnt1 | ||
| 110 | public DMACnt2 | ||
| 111 | public DMACnt3 | ||
| 112 | public DMACnt5 | ||
| 113 | public DMACnt6 | ||
| 114 | public DMACnt7 | ||
| 115 | public DMAPg0 | ||
| 116 | public DMAPg1 | ||
| 117 | public DMAPg2 | ||
| 118 | public DMAPg3 | ||
| 119 | public DMAPg5 | ||
| 120 | public DMAPg6 | ||
| 121 | public DMAPg7 | ||
| 122 | public DMAClrFF1 | ||
| 123 | public DMAClrFF2 | ||
| 124 | public DMAMode1 | ||
| 125 | public DMAMode2 | ||
| 126 | |||
| 127 | |||
| 128 | page | ||
| 129 | ;****************************************************************************** | ||
| 130 | ; L O C A L C O N S T A N T S | ||
| 131 | ;****************************************************************************** | ||
| 132 | ; | ||
| 133 | include VDMseg.inc | ||
| 134 | include VDMsel.inc | ||
| 135 | include desc.inc | ||
| 136 | include elim.inc | ||
| 137 | include mach_id.inc | ||
| 138 | include page.inc | ||
| 139 | include oemdep.inc | ||
| 140 | include instr386.inc | ||
| 141 | include vm386.inc | ||
| 142 | include emmdef.inc | ||
| 143 | |||
| 144 | ;****************************************************************************** | ||
| 145 | ; | ||
| 146 | ; Get_FRS_window - get pointer to Fast Register Set window | ||
| 147 | ; | ||
| 148 | ; ENTRY: Reg - points to an FRS_struc | ||
| 149 | ; | ||
| 150 | ; EXIT: Reg - points to FRS_window entry in the structure | ||
| 151 | ; | ||
| 152 | ; USES: Reg | ||
| 153 | ; | ||
| 154 | ;****************************************************************************** | ||
| 155 | Get_FRS_window MACRO Reg | ||
| 156 | |||
| 157 | mov Reg, word ptr [CurRegSet] ; just offset (assume dgroup) | ||
| 158 | add Reg, FRS_window ; points to FRS window entries | ||
| 159 | ENDM | ||
| 160 | |||
| 161 | ;**************************************************************************** | ||
| 162 | ; | ||
| 163 | ; InitDMARegSav - MACRO for initialising save area for channels | ||
| 164 | ; | ||
| 165 | ; ENTRY: chan_num = channel number (1,2,3,5,6,7) | ||
| 166 | ; ES -> DGROUP | ||
| 167 | ; | ||
| 168 | ;----------------------------------------------------------------------------- | ||
| 169 | |||
| 170 | InitDMARegSav MACRO chan_num | ||
| 171 | |||
| 172 | lea di,[DMARegSav.Chnl&chan_num] ; pt to channel's save area | ||
| 173 | |||
| 174 | xor eax, eax | ||
| 175 | in al,DMA_P&chan_num ; page register for channel | ||
| 176 | jmp $+2 | ||
| 177 | jmp $+2 ; timing | ||
| 178 | shl eax,16 ; high EAX = high word of linear addr | ||
| 179 | |||
| 180 | ; flip-flop already reset by the caller | ||
| 181 | |||
| 182 | in al,DMA_B&chan_num ; get low byte of base | ||
| 183 | jmp $+2 | ||
| 184 | jmp $+2 ; timing | ||
| 185 | mov ah,al | ||
| 186 | in al,DMA_B&chan_num ; get high byte of base | ||
| 187 | xchg ah,al | ||
| 188 | ; EAX = LINEAR BASE address | ||
| 189 | |||
| 190 | stosd ; store LINEAR BASE address | ||
| 191 | |||
| 192 | stosd ; store PHYSICAL BASE address | ||
| 193 | |||
| 194 | xor eax, eax ; clear EAX | ||
| 195 | jmp $+2 | ||
| 196 | jmp $+2 ; timing | ||
| 197 | in al,DMA_C&chan_num ; get low byte of count | ||
| 198 | jmp $+2 | ||
| 199 | jmp $+2 ; timing | ||
| 200 | mov ah,al | ||
| 201 | in al,DMA_C&chan_num ; get high byte of count | ||
| 202 | xchg ah,al | ||
| 203 | ; EAX = count | ||
| 204 | |||
| 205 | stosd ; store count | ||
| 206 | |||
| 207 | add di, 4 ; skip 4 bytes - 3 ports+mode byte | ||
| 208 | |||
| 209 | ENDM | ||
| 210 | |||
| 211 | |||
| 212 | ;****************************************************************************** | ||
| 213 | ; DMA_WADDR_TO_BADDR - convert internal DMA word address to a byte address | ||
| 214 | ; | ||
| 215 | ; ENTRY: 386 PROTECTED MODE | ||
| 216 | ; DS -> DGROUP | ||
| 217 | ; ES -> DGROUP | ||
| 218 | ; EAX - Word Address | ||
| 219 | ; | ||
| 220 | ; EXIT: EAX - Byte address | ||
| 221 | ; | ||
| 222 | ; USED: | ||
| 223 | ;------------------------------------------------------------------------------ | ||
| 224 | DMA_WADDR_TO_BADDR MACRO | ||
| 225 | LOCAL Not_AT | ||
| 226 | |||
| 227 | cmp [ROM_BIOS_Machine_ID], RBMI_Sys80 | ||
| 228 | jbe short Not_AT ; If running on EBIOS machine | ||
| 229 | |||
| 230 | ror eax,16 ; AX = high word | ||
| 231 | shr al,1 ; adjust for D0 null in page reg | ||
| 232 | rol eax,17 ; EAX = address w/ adjust for | ||
| 233 | ; 'A0' offset | ||
| 234 | Not_At: | ||
| 235 | shl ecx, 1 ; Adjust for word units | ||
| 236 | ENDM | ||
| 237 | |||
| 238 | |||
| 239 | ;****************************************************************************** | ||
| 240 | ; DMA_BADDR_TO_WADDR - convert internal DMA byte address to a word address | ||
| 241 | ; | ||
| 242 | ; ENTRY: 386 PROTECTED MODE | ||
| 243 | ; DS -> DGROUP | ||
| 244 | ; ES -> DGROUP | ||
| 245 | ; EAX - Word Address | ||
| 246 | ; | ||
| 247 | ; EXIT: EAX - Byte address | ||
| 248 | ; | ||
| 249 | ; USED: | ||
| 250 | ;------------------------------------------------------------------------------ | ||
| 251 | DMA_BADDR_TO_WADDR MACRO | ||
| 252 | LOCAL Not_AT | ||
| 253 | |||
| 254 | cmp [ROM_BIOS_Machine_ID], RBMI_Sys80 | ||
| 255 | jbe short Not_AT ; If running on EBIOS machine | ||
| 256 | |||
| 257 | shr eax, 1 ; Adjust for implied 'A0' | ||
| 258 | push ax ; Save A16-A1 | ||
| 259 | xor ax, ax | ||
| 260 | shl eax, 1 ; Adjust for unused Pg Reg D0 | ||
| 261 | pop ax ; Restore A16-A1 | ||
| 262 | Not_At: | ||
| 263 | ENDM | ||
| 264 | |||
| 265 | ;****************************************************************************** | ||
| 266 | ; E X T E R N A L R E F E R E N C E S | ||
| 267 | ;****************************************************************************** | ||
| 268 | |||
| 269 | _DATA segment | ||
| 270 | extrn ROM_BIOS_Machine_ID:byte | ||
| 271 | extrn _page_frame_base:word | ||
| 272 | extrn CurRegSet:word | ||
| 273 | extrn Page_Dir:word | ||
| 274 | SaveAL db ? | ||
| 275 | _DATA ends | ||
| 276 | |||
| 277 | _TEXT segment | ||
| 278 | |||
| 279 | extrn PortTrap:near ; set port bit in I/O bit Map | ||
| 280 | extrn MapLinear:near | ||
| 281 | extrn ErrHndlr:near | ||
| 282 | ; | ||
| 283 | ; Swap pages so that DMA Xfer area is physically contiguous. | ||
| 284 | ; defined in mapdma.c | ||
| 285 | ; | ||
| 286 | extrn _SwapDMAPages:near | ||
| 287 | |||
| 288 | _TEXT ends | ||
| 289 | |||
| 290 | ;****************************************************************************** | ||
| 291 | ; S E G M E N T D E F I N I T I O N | ||
| 292 | ;****************************************************************************** | ||
| 293 | |||
| 294 | _DATA segment | ||
| 295 | |||
| 296 | DMARegSav DMARegBuf <> ; DMA Register buffer | ||
| 297 | |||
| 298 | DMAP_Page label word | ||
| 299 | ; dw DMA_P0 ; DMA page registers | ||
| 300 | dw DMA_P1 | ||
| 301 | dw DMA_P2 | ||
| 302 | dw DMA_P3 | ||
| 303 | dw DMA_P5 | ||
| 304 | dw DMA_P6 | ||
| 305 | dw DMA_P7 | ||
| 306 | ; dw DMA_P4 | ||
| 307 | ; dw DMA_P0+10h ; page regs mapped to here also | ||
| 308 | dw DMA_P1+10h | ||
| 309 | dw DMA_P2+10h | ||
| 310 | dw DMA_P3+10h | ||
| 311 | dw DMA_P5+10h | ||
| 312 | dw DMA_P6+10h | ||
| 313 | dw DMA_P7+10h | ||
| 314 | ; dw DMA_P4+10h | ||
| 315 | DMAP_Addr label word | ||
| 316 | ; dw DMA_B0 ; DMA base registers | ||
| 317 | dw DMA_B1 | ||
| 318 | dw DMA_B2 | ||
| 319 | dw DMA_B3 | ||
| 320 | dw DMA_B5 | ||
| 321 | dw DMA_B6 | ||
| 322 | dw DMA_B7 | ||
| 323 | DMAP_Count label word | ||
| 324 | ; dw DMA_C0 ; DMA count registers | ||
| 325 | dw DMA_C1 | ||
| 326 | dw DMA_C2 | ||
| 327 | dw DMA_C3 | ||
| 328 | dw DMA_C5 | ||
| 329 | dw DMA_C6 | ||
| 330 | dw DMA_C7 | ||
| 331 | dw DMA1_CLR_FF ; reset flip-flop commands | ||
| 332 | dw DMA2_CLR_FF | ||
| 333 | DMAP_Mode label word | ||
| 334 | dw DMA1_MODE | ||
| 335 | dw DMA2_MODE | ||
| 336 | |||
| 337 | LIMDMAP_CNT = ($ - DMAP_Page) / 2 | ||
| 338 | ; | ||
| 339 | ; DMA_Pages - EMM Pages for DMA relocation. Each is an index into pft386. | ||
| 340 | ; To access actual entry in pft386 you need to multiply index by 4. | ||
| 341 | ; If eight contingous 16k EMM pages are not available - the unavailable | ||
| 342 | ; entries are left at NULL_PAGE. | ||
| 343 | ; This array should be initialized at boot time. | ||
| 344 | ; | ||
| 345 | _DMA_Pages LABEL WORD | ||
| 346 | DMA_Pages dw 8 dup (NULL_PAGE) ; null for start | ||
| 347 | _DMA_PAGE_COUNT LABEL WORD | ||
| 348 | DMA_PAGE_COUNT dw 0 ; number of above initialised | ||
| 349 | |||
| 350 | |||
| 351 | _DATA ends | ||
| 352 | |||
| 353 | page | ||
| 354 | |||
| 355 | ;------------------------------------------------------------------------------ | ||
| 356 | |||
| 357 | _TEXT segment | ||
| 358 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 359 | |||
| 360 | ;****************************************************************************** | ||
| 361 | ; | ||
| 362 | ; InitDMA - initialize internal values for DMA registers of each channel | ||
| 363 | ; | ||
| 364 | ; ENTRY: Real Mode | ||
| 365 | ; DS = DGROUP | ||
| 366 | ; | ||
| 367 | ; EXIT: Real Mode | ||
| 368 | ; DGROUP:[DMARegSav] = DMA register save area initialized | ||
| 369 | ; | ||
| 370 | ;------------------------------------------------------------------------------ | ||
| 371 | |||
| 372 | InitDMA proc near | ||
| 373 | |||
| 374 | push eax | ||
| 375 | push di | ||
| 376 | push es | ||
| 377 | |||
| 378 | pushf | ||
| 379 | cli | ||
| 380 | cld | ||
| 381 | |||
| 382 | push ds | ||
| 383 | pop es ; ES = DGROUP | ||
| 384 | |||
| 385 | xor al,al | ||
| 386 | out DMA1_CLR_FF, al ; clear FF on first controller | ||
| 387 | mov [DMARegSav.DMAFF1], al ; reset S/W FF | ||
| 388 | jmp $+2 | ||
| 389 | jmp $+2 ; timing | ||
| 390 | ; | ||
| 391 | ; initialize regs for channels 1,2,3 | ||
| 392 | ; | ||
| 393 | InitDMARegSav 1 | ||
| 394 | InitDMARegSav 2 | ||
| 395 | InitDMARegSav 3 | ||
| 396 | |||
| 397 | xor al,al | ||
| 398 | out DMA2_CLR_FF, al ; clear FF on second controller | ||
| 399 | mov [DMARegSav.DMAFF2], al ; reset S/W FF | ||
| 400 | jmp $+2 | ||
| 401 | jmp $+2 ; timing | ||
| 402 | ; | ||
| 403 | ; initialize regs for channels 5,6,7 | ||
| 404 | ; | ||
| 405 | InitDMARegSav 5 | ||
| 406 | InitDMARegSav 6 | ||
| 407 | InitDMARegSav 7 | ||
| 408 | |||
| 409 | popf | ||
| 410 | pop es | ||
| 411 | pop di | ||
| 412 | pop eax | ||
| 413 | ret | ||
| 414 | |||
| 415 | InitDMA endp | ||
| 416 | |||
| 417 | ;****************************************************************************** | ||
| 418 | ; | ||
| 419 | ; DMABase(0-7) - Write/Read DMA Channel N Base Register | ||
| 420 | ; | ||
| 421 | ; ENTRY: | ||
| 422 | ; AL = byte to output to port | ||
| 423 | ; BX = port * 2 | ||
| 424 | ; DH = 0 => Emulate Input | ||
| 425 | ; <>0 => Emulate Output | ||
| 426 | ; | ||
| 427 | ; EXIT: | ||
| 428 | ; AL = emulated input/output value from port. | ||
| 429 | ; CLC => I/O emulated or performed | ||
| 430 | ; | ||
| 431 | ;------------------------------------------------------------------------------ | ||
| 432 | DMABase0to7 proc near | ||
| 433 | |||
| 434 | DMABase4: ; I/O port C0h | ||
| 435 | DMABase5: ; I/O port C4h | ||
| 436 | DMABase6: ; I/O port C8h | ||
| 437 | DMABase7: ; I/O port CCh | ||
| 438 | push ax | ||
| 439 | push bx | ||
| 440 | push cx | ||
| 441 | push dx | ||
| 442 | push si | ||
| 443 | ; | ||
| 444 | ; Now, BX = port * 2 and DX = IO code | ||
| 445 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 446 | ; | ||
| 447 | xchg dx, bx | ||
| 448 | shr dx, 1 | ||
| 449 | xchg bh,bl ; move IO code to bh | ||
| 450 | |||
| 451 | mov si, dx | ||
| 452 | sub si, 0B0h ; SI = Channel * 4 | ||
| 453 | shl si, 2 ; SI = Channel * 16 | ||
| 454 | mov bl, [DMARegSav.DMAFF2] ; get flip-flop | ||
| 455 | xor [DMARegSav.DMAFF2], 1 ; and toggle it | ||
| 456 | jmp short DMABaseN ; | ||
| 457 | |||
| 458 | DMABase0: ; I/O port 00h | ||
| 459 | DMABase1: ; I/O port 02h | ||
| 460 | DMABase2: ; I/O port 04h | ||
| 461 | DMABase3: ; I/O port 06h | ||
| 462 | push ax | ||
| 463 | push bx | ||
| 464 | push cx | ||
| 465 | push dx | ||
| 466 | push si | ||
| 467 | ; | ||
| 468 | ; Now, BX = port * 2 and DX = IO code | ||
| 469 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 470 | ; | ||
| 471 | xchg dx, bx | ||
| 472 | shr dx, 1 | ||
| 473 | xchg bh,bl ; move IO code to bh | ||
| 474 | |||
| 475 | mov si, dx ; SI = Channel * 2 | ||
| 476 | shl si, 3 ; SI = Channel * 16 | ||
| 477 | mov bl, [DMARegSav.DMAFF1] ; get flip-flop | ||
| 478 | xor [DMARegSav.DMAFF1], 1 ; and toggle it | ||
| 479 | |||
| 480 | ; | ||
| 481 | ; FALL THROUGH!!! | ||
| 482 | ; | ||
| 483 | |||
| 484 | ;****************************************************************************** | ||
| 485 | ; | ||
| 486 | ; DMABaseN - Write/Read DMA Channel N Base Register | ||
| 487 | ; | ||
| 488 | ; ENTRY: As above plus | ||
| 489 | ; SI = 16 * channel # | ||
| 490 | ; | ||
| 491 | ;------------------------------------------------------------------------------ | ||
| 492 | DMABaseN: | ||
| 493 | and bl, 1 ; Look at bit0 only - safety | ||
| 494 | |||
| 495 | or bh,bh ;Q: Input ? | ||
| 496 | jz short Base_rd_port ; Y: do Read operation | ||
| 497 | ; N: save value "written" | ||
| 498 | mov [SaveAL], al ; save AL in Save area. | ||
| 499 | xor bh, bh ; Make BX = Flip Flop state | ||
| 500 | mov byte ptr DMARegSav.DMALinAdr[bx][si], al | ||
| 501 | |||
| 502 | in al, dx ; Just a Dummy I/O to | ||
| 503 | ; toggle the real flip-flop | ||
| 504 | ; to match DMAFF above | ||
| 505 | jmp $+2 | ||
| 506 | jmp $+2 | ||
| 507 | xor bl,1 ; and the s/w one | ||
| 508 | |||
| 509 | call DMA_DMAFixup ; Translate Lin to Phys | ||
| 510 | ; & Update DMARegSav | ||
| 511 | call DMA_WrtAdrReg ; emulate the write | ||
| 512 | jmp short DBExit | ||
| 513 | |||
| 514 | Base_rd_port: | ||
| 515 | in al, dx ; Toggle the real flop-flip | ||
| 516 | ; | ||
| 517 | ; bh is already zero, therefore BX = flip flop state | ||
| 518 | ; | ||
| 519 | mov al,byte ptr DMARegSav.DMALinAdr[bx][si] | ||
| 520 | mov [SaveAL], al | ||
| 521 | DBExit: | ||
| 522 | pop si | ||
| 523 | pop dx | ||
| 524 | pop cx | ||
| 525 | pop bx | ||
| 526 | pop ax | ||
| 527 | mov al, [SaveAL] | ||
| 528 | clc | ||
| 529 | ret | ||
| 530 | |||
| 531 | DMABase0to7 endp | ||
| 532 | |||
| 533 | page | ||
| 534 | |||
| 535 | ;****************************************************************************** | ||
| 536 | ; | ||
| 537 | ; DMACnt(0-7) - Write/Read DMA Channel N Count Register | ||
| 538 | ; | ||
| 539 | ;ENTRY: | ||
| 540 | ; AL = byte to output to port. | ||
| 541 | ; BX = port * 2 | ||
| 542 | ; DH = 0 => Emulate Input. | ||
| 543 | ; <>0 => Emulate Output. | ||
| 544 | ; | ||
| 545 | ;EXIT: | ||
| 546 | ; AL = emulated input/output value from port. | ||
| 547 | ; CLC => I/O emulated or performed | ||
| 548 | ; | ||
| 549 | ;------------------------------------------------------------------------------ | ||
| 550 | |||
| 551 | DMACnt0to7 proc near | ||
| 552 | |||
| 553 | DMACnt4: ; I/O port C2h | ||
| 554 | DMACnt5: ; I/O port C6h | ||
| 555 | DMACnt6: ; I/O port CAh | ||
| 556 | DMACnt7: ; I/O port CEh | ||
| 557 | push ax | ||
| 558 | push bx | ||
| 559 | push cx | ||
| 560 | push dx | ||
| 561 | push si | ||
| 562 | ; | ||
| 563 | ; Now, BX = port * 2 and DX = IO code | ||
| 564 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 565 | ; | ||
| 566 | xchg dx, bx | ||
| 567 | shr dx, 1 | ||
| 568 | xchg bh,bl ; move IO code to bh | ||
| 569 | |||
| 570 | mov si, dx | ||
| 571 | sub si, 0B2h ; SI = 4 * channel # | ||
| 572 | shl si, 2 ; si = 16 * channel # | ||
| 573 | mov bl, [DMARegSav.DMAFF2] ; get flip-flop | ||
| 574 | xor [DMARegSav.DMAFF2], 1 ; toggle our flip-flop | ||
| 575 | jmp short DMACntN | ||
| 576 | |||
| 577 | DMACnt0: ; I/O port 01h | ||
| 578 | DMACnt1: ; I/O port 03h | ||
| 579 | DMACnt2: ; I/O port 05h | ||
| 580 | DMACnt3: ; I/O port 07h | ||
| 581 | push ax | ||
| 582 | push bx | ||
| 583 | push cx | ||
| 584 | push dx | ||
| 585 | push si | ||
| 586 | ; | ||
| 587 | ; Now, BX = port * 2 and DX = IO code | ||
| 588 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 589 | ; | ||
| 590 | xchg dx, bx | ||
| 591 | shr dx, 1 | ||
| 592 | xchg bh,bl ; move IO code to bh | ||
| 593 | |||
| 594 | mov si, dx | ||
| 595 | dec si | ||
| 596 | shl si, 3 ; si = 16 * channel # | ||
| 597 | mov bl, [DMARegSav.DMAFF1] ; get flip-flop | ||
| 598 | xor [DMARegSav.DMAFF1], 1 ; toggle our flip-flop | ||
| 599 | ; | ||
| 600 | ; FALL THROUGH!!! | ||
| 601 | ; | ||
| 602 | |||
| 603 | ;****************************************************************************** | ||
| 604 | ; | ||
| 605 | ; DMACntN - Write/Read DMA Channel N Count Register | ||
| 606 | ; | ||
| 607 | ; ENTRY: As DMACnt1to7 plus | ||
| 608 | ; si = 16 * channel # | ||
| 609 | ; | ||
| 610 | ;------------------------------------------------------------------------------ | ||
| 611 | DMACntN: | ||
| 612 | and bl, 1 ; Look at bit0 only - Safety | ||
| 613 | |||
| 614 | or bh,bh ;Q: Input ? | ||
| 615 | jz short DMA_CntN_rd ; Y: do Read operation | ||
| 616 | ; N: save value "written" | ||
| 617 | mov [SaveAL], al ; save AL in Save area. | ||
| 618 | xor bh, bh ; make BX = Flip Flop state | ||
| 619 | mov byte ptr DMARegSav.DMACount[bx][si], al ; save cnt | ||
| 620 | out dx, al ; do the I/O | ||
| 621 | |||
| 622 | xor bl,1 ; Toggle flip-flop for Wrt | ||
| 623 | call DMA_DMAFixup ; Translate Lin to Phys | ||
| 624 | ; & Update DMARegSav | ||
| 625 | call DMA_WrtAdrReg ; emulate the write | ||
| 626 | call DMALoadCount | ||
| 627 | |||
| 628 | jmp short DCExit | ||
| 629 | DMA_CntN_rd: | ||
| 630 | xor bh,bh ; make BX = Flip Flop state | ||
| 631 | in al, dx ; Toggle the real flip-flop | ||
| 632 | ; to match bx above | ||
| 633 | mov [SaveAL], al | ||
| 634 | |||
| 635 | jmp $+2 | ||
| 636 | jmp $+2 | ||
| 637 | xor bl,1 ; and the s/w one | ||
| 638 | ; | ||
| 639 | ; get current count values from cntlr | ||
| 640 | ; | ||
| 641 | in al, dx ; get 2nd byte of Count reg | ||
| 642 | jmp $+2 ; timing ... | ||
| 643 | jmp $+2 ; timing ... | ||
| 644 | mov byte ptr DMARegSav.DMACount[bx][si], al ; save it | ||
| 645 | xor bl, 1 ; flip to other byte | ||
| 646 | in al, dx ; get 1st byte of Count reg | ||
| 647 | mov byte ptr DMARegSav.DMACount[bx][si], al ; save it | ||
| 648 | DCExit: | ||
| 649 | pop si | ||
| 650 | pop dx | ||
| 651 | pop cx | ||
| 652 | pop bx | ||
| 653 | pop ax | ||
| 654 | mov al, [SaveAL] | ||
| 655 | |||
| 656 | clc ; I/O emulated, return | ||
| 657 | ret | ||
| 658 | |||
| 659 | DMACnt0to7 endp | ||
| 660 | |||
| 661 | page | ||
| 662 | ;****************************************************************************** | ||
| 663 | ; | ||
| 664 | ; DMAPgN - Write/Read DMA Channel N Page Register | ||
| 665 | ; | ||
| 666 | ; ENTRY: | ||
| 667 | ; AL = byte to output to port | ||
| 668 | ; BX = port * 2 | ||
| 669 | ; DX = 0 => Emulate Input | ||
| 670 | ; <>0 => Emulate Output | ||
| 671 | ; si = 2 * Channel # | ||
| 672 | ; | ||
| 673 | ; EXIT: | ||
| 674 | ; AL = emulated input/output value from port. | ||
| 675 | ; CLC => I/O emulated or performed | ||
| 676 | ; | ||
| 677 | ; USED: EBX,Flags | ||
| 678 | ; STACK: | ||
| 679 | ; | ||
| 680 | ; NOTES: For channels 0-4, DMACount is in Bytes, and | ||
| 681 | ; DMALinAdr holds the address as: | ||
| 682 | ; | ||
| 683 | ; +-----------+-----------+----------------------+ | ||
| 684 | ; | 31-24 | 23-16 | 15-0 | | ||
| 685 | ; +-----------+-----------+----------------------+ | ||
| 686 | ; | 0000 0000 | A23-A16 | A15-A0 | | ||
| 687 | ; +-----------+-----------+----------------------+ | ||
| 688 | ; | ||
| 689 | ; For channels 5-7, DMACount is in Words, and | ||
| 690 | ; DMALinAdr holds the address as: | ||
| 691 | ; | ||
| 692 | ; +-----------+-----------+----------------------+ | ||
| 693 | ; | 31-24 |23-17 | 16 | 15-0 | | ||
| 694 | ; +-----------+-----------+----------------------+ | ||
| 695 | ; | 0000 0000 |A23-A17 |0 | A16-A1 | | ||
| 696 | ; +-----------+-----------+----------------------+ | ||
| 697 | ; | ||
| 698 | ; | ||
| 699 | ;------------------------------------------------------------------------------ | ||
| 700 | DMAPg0to7 proc near | ||
| 701 | |||
| 702 | DMAPg0: | ||
| 703 | push si | ||
| 704 | mov si,0*16 ; si = 16 * channel # | ||
| 705 | jmp short DMAPgN | ||
| 706 | DMAPg1: | ||
| 707 | push si | ||
| 708 | mov si,1*16 ; si = 16 * channel # | ||
| 709 | jmp short DMAPgN | ||
| 710 | DMAPg2: | ||
| 711 | push si | ||
| 712 | mov si,2*16 ; si = 16 * channel # | ||
| 713 | jmp short DMAPgN | ||
| 714 | DMAPg3: | ||
| 715 | push si | ||
| 716 | mov si,3*16 ; si = 16 * channel # | ||
| 717 | jmp short DMAPgN | ||
| 718 | DMAPg5: | ||
| 719 | push si | ||
| 720 | mov si,5*16 ; si = 16 * channel # | ||
| 721 | jmp short DMAPgN | ||
| 722 | DMAPg6: | ||
| 723 | push si | ||
| 724 | mov si,6*16 ; si = 16 * channel # | ||
| 725 | jmp short DMAPgN | ||
| 726 | DMAPg7: | ||
| 727 | push si | ||
| 728 | mov si,7*16 ; si = 16 * channel # | ||
| 729 | ; FALL THROUGH | ||
| 730 | |||
| 731 | ;---------------------------------------------------------------------- | ||
| 732 | ; DMAPgN - Common Page Code | ||
| 733 | ; | ||
| 734 | ; ENTRY: As above plus | ||
| 735 | ; si = 16 * Channel # | ||
| 736 | ; | ||
| 737 | ;---------------------------------------------------------------------- | ||
| 738 | |||
| 739 | DMAPgN: | ||
| 740 | push ax | ||
| 741 | push bx | ||
| 742 | push cx | ||
| 743 | push dx | ||
| 744 | ; | ||
| 745 | ; Now, BX = port * 2 and DX = IO code | ||
| 746 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 747 | ; | ||
| 748 | xchg dx, bx | ||
| 749 | shr dx, 1 | ||
| 750 | xchg bh,bl ; move IO code to bh | ||
| 751 | |||
| 752 | or bh,bh ;Q: Input ? | ||
| 753 | jz short Pg_rd_port ; Y: do Read operation | ||
| 754 | |||
| 755 | mov [SaveAL], al ; save AL in Save area. | ||
| 756 | ; | ||
| 757 | ; Get s/w FF for WrtAdrReg | ||
| 758 | ; | ||
| 759 | mov bl, [DMARegSav.DMAFF1] ; Assume Chan 1 FF | ||
| 760 | cmp si, 4*16 ; Q: Addr for 2nd controller | ||
| 761 | jb short PgN_FF ; A: No, FF is correct | ||
| 762 | mov bl, [DMARegSav.DMAFF2] ; Chan 2 FF | ||
| 763 | PgN_FF: | ||
| 764 | xor bh, bh ; make BX = flip-flop state | ||
| 765 | |||
| 766 | mov byte ptr DMARegSav.DMALinAdr.HighWord[si], al ; save value | ||
| 767 | call DMA_DMAFixup ; Translate Lin to Phys | ||
| 768 | ; & Update DMARegSav | ||
| 769 | call DMA_WrtAdrReg ; emulate the write | ||
| 770 | jmp short DPExit | ||
| 771 | Pg_rd_port: | ||
| 772 | mov al, byte ptr DMARegSav.DMALinAdr.HighWord[si] | ||
| 773 | mov [SaveAL], al | ||
| 774 | DPExit: | ||
| 775 | pop dx | ||
| 776 | pop cx | ||
| 777 | pop bx | ||
| 778 | pop ax | ||
| 779 | pop si | ||
| 780 | mov al, [SaveAL] | ||
| 781 | clc | ||
| 782 | ret | ||
| 783 | |||
| 784 | DMAPg0to7 endp | ||
| 785 | |||
| 786 | page | ||
| 787 | |||
| 788 | ;****************************************************************************** | ||
| 789 | ; | ||
| 790 | ; DMAClrFF1 - Reset Controller 1's FlipFlop | ||
| 791 | ; DMAClrFF2 - Reset Controller 2's FlipFlop | ||
| 792 | ; | ||
| 793 | ; ENTRY: | ||
| 794 | ; AL = byte to output to port. | ||
| 795 | ; BX = port * 2 | ||
| 796 | ; DH = 0 => Emulate Input. | ||
| 797 | ; <>0 => Emulate Output. | ||
| 798 | ; | ||
| 799 | ; EXIT: | ||
| 800 | ; AL = emulated input/output value from port. | ||
| 801 | ; CLC => I/O emulated or performed | ||
| 802 | ; | ||
| 803 | ;------------------------------------------------------------------------------ | ||
| 804 | |||
| 805 | DMAClrFF1 proc near | ||
| 806 | push ax | ||
| 807 | push bx | ||
| 808 | push cx | ||
| 809 | push dx | ||
| 810 | ; | ||
| 811 | ; Now, BX = port * 2 and DX = IO code | ||
| 812 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 813 | ; | ||
| 814 | xchg bx, dx | ||
| 815 | shr dx, 1 | ||
| 816 | xchg bh,bl ; move IO code to bh | ||
| 817 | |||
| 818 | or bh,bh ;Q: Input ? | ||
| 819 | jz short DMA_CLF_RdEm ; Y: Let it go | ||
| 820 | out dx, al ; N: do it | ||
| 821 | mov [DMARegSav.DMAFF1], 0 | ||
| 822 | jmp short DMACFFexit | ||
| 823 | DMA_CLF_RdEm: | ||
| 824 | in al,dx ; do the read | ||
| 825 | DMACFFexit: | ||
| 826 | pop dx | ||
| 827 | pop cx | ||
| 828 | pop bx | ||
| 829 | pop ax | ||
| 830 | clc | ||
| 831 | ret | ||
| 832 | |||
| 833 | DMAClrFF1 endp | ||
| 834 | |||
| 835 | DMAClrFF2 proc near | ||
| 836 | |||
| 837 | push ax | ||
| 838 | push bx | ||
| 839 | push cx | ||
| 840 | push dx | ||
| 841 | ; | ||
| 842 | ; Now, BX = port * 2 and DX = IO code | ||
| 843 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 844 | ; | ||
| 845 | xchg bx, dx | ||
| 846 | shr dx, 1 | ||
| 847 | xchg bh,bl ; move IO code to bh | ||
| 848 | |||
| 849 | or bh,bh ;Q: Input ? | ||
| 850 | jz DMA_CLF_RdEm ; Y: Let it go | ||
| 851 | out dx, al ; N: do it | ||
| 852 | mov [DMARegSav.DMAFF2], 0 | ||
| 853 | jmp DMACFFexit | ||
| 854 | |||
| 855 | DMAClrFF2 endp | ||
| 856 | |||
| 857 | page | ||
| 858 | ;****************************************************************************** | ||
| 859 | ; | ||
| 860 | ; DMAMode1 - Track Controller 1's Mode Register | ||
| 861 | ; DMAMode2 - Track Controller 2's Mode Register | ||
| 862 | ; | ||
| 863 | ; ENTRY: | ||
| 864 | ; AL = byte to output to port. | ||
| 865 | ; BX = port * 2 | ||
| 866 | ; DX = 0 => Emulate Input. | ||
| 867 | ; <>0 => Emulate Output. | ||
| 868 | ; | ||
| 869 | ; EXIT: | ||
| 870 | ; AL = emulated input/output value from port. | ||
| 871 | ; CLC => I/O emulated or performed | ||
| 872 | ; | ||
| 873 | ;------------------------------------------------------------------------------ | ||
| 874 | |||
| 875 | DMAMode1 proc near | ||
| 876 | push ax | ||
| 877 | push bx | ||
| 878 | push cx | ||
| 879 | push dx | ||
| 880 | push si | ||
| 881 | ; | ||
| 882 | ; Now, BX = port * 2 and DX = IO code | ||
| 883 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 884 | ; | ||
| 885 | xchg bx, dx | ||
| 886 | shr dx, 1 | ||
| 887 | xchg bh,bl ; move IO code to bh | ||
| 888 | |||
| 889 | or bh,bh ;Q: Input ? | ||
| 890 | jz short DMA_Mread ; Y: Let it go | ||
| 891 | |||
| 892 | mov [SaveAL], al ; save AL in Save area. | ||
| 893 | xor ah, ah | ||
| 894 | mov si, ax | ||
| 895 | and si, DMA_M_CHANNEL | ||
| 896 | mov bl, al | ||
| 897 | and bl, NOT DMA_M_16BIT ; 8 bit xfers for controller 1 | ||
| 898 | DMA_Mboth: | ||
| 899 | shl si, 4 ; Channel * 16 | ||
| 900 | mov [DMARegSav.DMAMode][si], bl | ||
| 901 | out dx, al ; N: do it | ||
| 902 | jmp short DMExit | ||
| 903 | |||
| 904 | DMA_Mread: | ||
| 905 | in al, dx ; do the read | ||
| 906 | mov [SaveAL], al | ||
| 907 | DMExit: | ||
| 908 | pop si | ||
| 909 | pop dx | ||
| 910 | pop cx | ||
| 911 | pop bx | ||
| 912 | pop ax | ||
| 913 | mov al, [SaveAL] | ||
| 914 | clc | ||
| 915 | ret | ||
| 916 | DMAMode1 endp | ||
| 917 | |||
| 918 | DMAMode2 proc near | ||
| 919 | |||
| 920 | push ax | ||
| 921 | push bx | ||
| 922 | push cx | ||
| 923 | push dx | ||
| 924 | push si | ||
| 925 | ; | ||
| 926 | ; Now, BX = port * 2 and DX = IO code | ||
| 927 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 928 | ; | ||
| 929 | xchg bx, dx | ||
| 930 | shr dx, 1 | ||
| 931 | xchg bh,bl ; move IO code to bh | ||
| 932 | |||
| 933 | or bh,bh ;Q: Input ? | ||
| 934 | jz DMA_Mread ; Y: Let it go | ||
| 935 | |||
| 936 | mov [SaveAL], al ; save AL in Save area. | ||
| 937 | xor ah, ah | ||
| 938 | mov si, ax | ||
| 939 | and si, DMA_M_CHANNEL | ||
| 940 | add si, 4 ; Channel 4 to 7 | ||
| 941 | mov bl, al | ||
| 942 | or bl, DMA_M_16BIT ; 16 bit for controller 2 | ||
| 943 | jmp DMA_Mboth | ||
| 944 | |||
| 945 | DMAMode2 endp | ||
| 946 | |||
| 947 | ; INCLUDE VDMAD2.ASM | ||
| 948 | |||
| 949 | page | ||
| 950 | ;****************************************************************************** | ||
| 951 | ;DMA_GetLinAdr - return Linear Address, count and mode from DMARegSave area | ||
| 952 | ; | ||
| 953 | ; ENTRY: | ||
| 954 | ; si = channel # * 16 | ||
| 955 | ; DS assume DGROUP | ||
| 956 | ; | ||
| 957 | ; EXIT: | ||
| 958 | ; EAX = linear Base Address | ||
| 959 | ; ECX = SIZE of transfer (bytes) | ||
| 960 | ; DL = Mode register | ||
| 961 | ; | ||
| 962 | ; USED: Flags | ||
| 963 | ; STACK: | ||
| 964 | ;------------------------------------------------------------------------------ | ||
| 965 | DMA_GetLinAdr proc near | ||
| 966 | |||
| 967 | mov eax, dword ptr DMARegSav.DMALinAdr[si] | ||
| 968 | mov ecx, dword ptr DMARegSav.DMACount[si] | ||
| 969 | mov dl, byte ptr DMARegSav.DMAMode[si] | ||
| 970 | inc ecx ; ECX = SIZE of transfer | ||
| 971 | test dl, DMA_M_16BIT ; Word transfer? | ||
| 972 | jz short GLexit ; N: no special treatment | ||
| 973 | |||
| 974 | DMA_WADDR_TO_BADDR ; Y: fixup values from regs | ||
| 975 | GLexit: | ||
| 976 | ret | ||
| 977 | |||
| 978 | DMA_GetLinAdr endp | ||
| 979 | |||
| 980 | page | ||
| 981 | ;****************************************************************************** | ||
| 982 | ; DMA_SetPhyAdr - Load the Page and Base DMA registers with the input | ||
| 983 | ; Physical Address and save this addr as current phy addr. | ||
| 984 | ; | ||
| 985 | ; ENTRY: | ||
| 986 | ; EAX = physical address | ||
| 987 | ; SI = DMA channel # * 16 | ||
| 988 | ; DS -> DGROUP | ||
| 989 | ; | ||
| 990 | ; USED: Flags | ||
| 991 | ;------------------------------------------------------------------------------ | ||
| 992 | DMA_SetPhyAdr proc near | ||
| 993 | ; | ||
| 994 | push eax | ||
| 995 | push bx | ||
| 996 | push dx | ||
| 997 | |||
| 998 | xor bh, bh | ||
| 999 | mov bl, [DMARegSav.DMAFF1] | ||
| 1000 | cmp si,4*16 ; 2nd cntlr? | ||
| 1001 | jb short DMA_SPA1 | ||
| 1002 | mov bl, [DMARegSav.DMAFF2] ; yes, other flip-flop | ||
| 1003 | DMA_SPA1: | ||
| 1004 | test [DMARegSav.DMAMode][si], DMA_M_16BIT ; word transfer? | ||
| 1005 | jz short SaveIt ; no, no translation | ||
| 1006 | DMA_BADDR_TO_WADDR | ||
| 1007 | SaveIt: | ||
| 1008 | mov dword ptr DMARegSav.DMAPhyAdr[si], eax | ||
| 1009 | |||
| 1010 | ; set page register | ||
| 1011 | xor dh, dh | ||
| 1012 | mov dl, byte ptr DMARegSav.DMAPagePort[si] | ||
| 1013 | mov al, byte ptr DMARegSav.DMAPhyAdr.HighWord[si] | ||
| 1014 | out dx, al | ||
| 1015 | |||
| 1016 | ; set base address register | ||
| 1017 | mov dl, byte ptr DMARegSav.DMABasePort[si] | ||
| 1018 | mov al, byte ptr DMARegSav.DMAPhyAdr[si][bx] | ||
| 1019 | out dx,al ; send out 1st byte | ||
| 1020 | xor bl,1 ; toggle FF | ||
| 1021 | jmp $+2 | ||
| 1022 | jmp $+2 | ||
| 1023 | mov al, byte ptr DMARegSav.DMAPhyAdr[si][bx] | ||
| 1024 | out dx,al ; send out other byte | ||
| 1025 | xor bl,1 ; toggle FF to original state | ||
| 1026 | |||
| 1027 | pop dx | ||
| 1028 | pop bx | ||
| 1029 | pop eax | ||
| 1030 | ret | ||
| 1031 | ; | ||
| 1032 | DMA_SetPhyAdr endp | ||
| 1033 | |||
| 1034 | page | ||
| 1035 | ;****************************************************************************** | ||
| 1036 | ; DMALoadCount - Load the Count DMA register with the input | ||
| 1037 | ; | ||
| 1038 | ; ENTRY: | ||
| 1039 | ; si = DMA channel # * 16 | ||
| 1040 | ; | ||
| 1041 | ;------------------------------------------------------------------------------ | ||
| 1042 | DMALoadCount proc near | ||
| 1043 | push bx | ||
| 1044 | push ax | ||
| 1045 | push dx | ||
| 1046 | |||
| 1047 | xor bh, bh | ||
| 1048 | mov bl, byte ptr [DMARegSav.DMAFF1] | ||
| 1049 | cmp si,4*16 ;Q: Adrs from 2nd cntlr | ||
| 1050 | jb short DMA_SC1 ; N: save it as is | ||
| 1051 | mov bl, byte ptr [DMARegSav.DMAFF2] | ||
| 1052 | |||
| 1053 | DMA_SC1: | ||
| 1054 | mov dl, byte ptr DMARegSav.DMACntPort[si] | ||
| 1055 | xor dh, dh | ||
| 1056 | mov al, byte ptr DMARegSav.DMACount[bx][si] | ||
| 1057 | out dx, al | ||
| 1058 | jmp $+2 | ||
| 1059 | jmp $+2 | ||
| 1060 | xor bl, 1 | ||
| 1061 | mov al, byte ptr DMARegSav.DMACount[bx][si] | ||
| 1062 | out dx, al | ||
| 1063 | |||
| 1064 | pop dx | ||
| 1065 | pop ax | ||
| 1066 | pop bx | ||
| 1067 | ret | ||
| 1068 | |||
| 1069 | DMALoadCount endp | ||
| 1070 | |||
| 1071 | page | ||
| 1072 | ;****************************************************************************** | ||
| 1073 | ; DMA_DMAFixup - Fixup Linear to Physical mapping for DMA | ||
| 1074 | ; | ||
| 1075 | ; ENTRY: | ||
| 1076 | ; SI = 16 * channel # | ||
| 1077 | ; DS assume DGROUP | ||
| 1078 | ; | ||
| 1079 | ; EXIT: | ||
| 1080 | ; DMARegSav is updated | ||
| 1081 | ; | ||
| 1082 | ; USED: flags, registers (calls a C program, so most registers are trashed) | ||
| 1083 | ; | ||
| 1084 | ; Check to see if DMA Page fixup is needed. | ||
| 1085 | ; We test for the following cases for optimization: | ||
| 1086 | ; Lin Base Add == Lin Page Reg == 0, assume that transfer addr | ||
| 1087 | ; is not yet valid | ||
| 1088 | ; | ||
| 1089 | ;------------------------------------------------------------------------------ | ||
| 1090 | DMA_DMAFixup proc near | ||
| 1091 | ;Q: LinAddr = 0? | ||
| 1092 | |||
| 1093 | mov eax, dword ptr DMARegSav.DMALinAdr[si] | ||
| 1094 | or eax,eax | ||
| 1095 | jz short DMA_nofixup ; Y:DMA not programmed yet | ||
| 1096 | ;Do the fixup..... | ||
| 1097 | pushfd ; ENABLE INTERRUPTS! | ||
| 1098 | push bx ; C code trashes these regs | ||
| 1099 | push es | ||
| 1100 | ; | ||
| 1101 | ; long SwapDMAPages(LinAdr, Len, XferSize); | ||
| 1102 | ; long LinAdr, Len; | ||
| 1103 | ; unsigned XferSize; 0/1 Byte/word Xfer | ||
| 1104 | ; | ||
| 1105 | movzx eax, [DMARegSav.DMAMode][si] | ||
| 1106 | and al, DMA_M_16BIT ; Non-zero for 16bit transfer | ||
| 1107 | push ax ; push XferSize | ||
| 1108 | |||
| 1109 | call DMA_GetLinAdr | ||
| 1110 | push ecx ; push count | ||
| 1111 | push eax ; push LinAdr | ||
| 1112 | ; | ||
| 1113 | ; C code saves di si bp ds ss sp | ||
| 1114 | |||
| 1115 | call _SwapDMAPages ; C program to do the dirty work | ||
| 1116 | |||
| 1117 | xchg ax, dx | ||
| 1118 | shl eax, 16 | ||
| 1119 | mov ax, dx ; eax = returned value | ||
| 1120 | |||
| 1121 | add sp, 10 ; clean up stack | ||
| 1122 | |||
| 1123 | pop es | ||
| 1124 | pop bx | ||
| 1125 | popfd ; Restore original FLAGS state | ||
| 1126 | |||
| 1127 | test [DMARegSav.DMAMode][si], DMA_M_16BIT ; word transfer? | ||
| 1128 | jz short SavIt ; no, no translation | ||
| 1129 | DMA_BADDR_TO_WADDR ; Y: Put in special format | ||
| 1130 | SavIt: | ||
| 1131 | mov dword ptr DMARegSav.DMAPhyAdr[si], eax | ||
| 1132 | clc ; Done fixup | ||
| 1133 | ret | ||
| 1134 | DMA_nofixup: | ||
| 1135 | stc | ||
| 1136 | ret | ||
| 1137 | |||
| 1138 | DMA_DMAFixup endp | ||
| 1139 | |||
| 1140 | page | ||
| 1141 | ;****************************************************************************** | ||
| 1142 | ; DMA_WrtAdrReg - Write registers associated with DMA address | ||
| 1143 | ; | ||
| 1144 | ; ENTRY: | ||
| 1145 | ; BX = Flip Flop State, 0 or 1 | ||
| 1146 | ; SI = channel # * 16 | ||
| 1147 | ; DS assume DGROUP | ||
| 1148 | ; Uses Values in DMARegSav | ||
| 1149 | ; | ||
| 1150 | ; EXIT: | ||
| 1151 | ; | ||
| 1152 | ; USED: Flags, EAX | ||
| 1153 | ; STACK: | ||
| 1154 | ;------------------------------------------------------------------------------ | ||
| 1155 | DMA_WrtAdrReg proc near | ||
| 1156 | |||
| 1157 | ; Must Update Page and Base registers simultaneously when remapping occurs... | ||
| 1158 | push bx | ||
| 1159 | push dx | ||
| 1160 | |||
| 1161 | and bx, 1 ; Lose extra bit just in case... | ||
| 1162 | ; Base Register... | ||
| 1163 | xor dh, dh ; clear high byte | ||
| 1164 | |||
| 1165 | ; NOTE: Internal flip- | ||
| 1166 | ; flop flag not updated, | ||
| 1167 | ; since we write twice.... | ||
| 1168 | ; BX = flip flop state | ||
| 1169 | |||
| 1170 | mov dl, byte ptr DMARegSav.DMABasePort[si] | ||
| 1171 | mov al, byte ptr DMARegSav.DMAPhyAdr[bx][si] | ||
| 1172 | out dx, al ; output the byte | ||
| 1173 | jmp $+2 ; timing | ||
| 1174 | jmp $+2 ; timing | ||
| 1175 | xor bx, 1 ; toggle flip-flop | ||
| 1176 | |||
| 1177 | mov al, byte ptr DMARegSav.DMAPhyAdr[bx][si] | ||
| 1178 | out dx, al ; output the byte | ||
| 1179 | jmp $+2 ; timing | ||
| 1180 | jmp $+2 ; timing | ||
| 1181 | xor bx, 1 ; toggle flip-flop | ||
| 1182 | |||
| 1183 | ; Page Register... | ||
| 1184 | mov al, byte ptr DMARegSav.DMAPhyAdr.HighWord[si] ; fetch value | ||
| 1185 | mov dl, byte ptr DMARegSav.DMAPagePort[si] | ||
| 1186 | out dx,al ; output the byte | ||
| 1187 | |||
| 1188 | pop dx | ||
| 1189 | pop bx | ||
| 1190 | ret | ||
| 1191 | |||
| 1192 | DMA_WrtAdrReg endp | ||
| 1193 | |||
| 1194 | page | ||
| 1195 | ;****************************************************************************** | ||
| 1196 | ; InitELIM - initialize LIM h/w trapping data structures and | ||
| 1197 | ; I/O bit map for this ports. | ||
| 1198 | ; | ||
| 1199 | ; NOTE: this is a FAR routine | ||
| 1200 | ; | ||
| 1201 | ; ENTRY: Real Mode | ||
| 1202 | ; | ||
| 1203 | ; EXIT: Real Mode | ||
| 1204 | ; TSS:[IOBitMap] - LIM addresses entered in I/O bit map | ||
| 1205 | ; | ||
| 1206 | ; USED: Flags | ||
| 1207 | ; STACK: | ||
| 1208 | ;------------------------------------------------------------------------------ | ||
| 1209 | InitELIM proc far | ||
| 1210 | |||
| 1211 | push ax | ||
| 1212 | push bx | ||
| 1213 | push cx | ||
| 1214 | push si | ||
| 1215 | push di | ||
| 1216 | push ds | ||
| 1217 | push es | ||
| 1218 | |||
| 1219 | cld | ||
| 1220 | |||
| 1221 | mov ax,seg DGROUP | ||
| 1222 | mov ds,ax | ||
| 1223 | ; | ||
| 1224 | ; now set entries in I/O Bit Map | ||
| 1225 | ; | ||
| 1226 | mov ax,TSS | ||
| 1227 | mov es,ax ; ES -> TSS | ||
| 1228 | ; | ||
| 1229 | ; now set DMA ports in I/O Bit Map | ||
| 1230 | ; | ||
| 1231 | mov cx,LIMDMAP_CNT | ||
| 1232 | mov si,offset DGROUP:DMAP_Page ; DS:SI -> DMA ports | ||
| 1233 | mov bx,8000h ; trap it every 1k | ||
| 1234 | IE_maploop: | ||
| 1235 | lodsw ; AX = port to trap | ||
| 1236 | call PortTrap ; set bit(s) for this port | ||
| 1237 | loop IE_maploop ;if more ... | ||
| 1238 | |||
| 1239 | pop es | ||
| 1240 | pop ds | ||
| 1241 | pop di | ||
| 1242 | pop si | ||
| 1243 | pop cx | ||
| 1244 | pop bx | ||
| 1245 | pop ax | ||
| 1246 | ret | ||
| 1247 | |||
| 1248 | InitELIM endp | ||
| 1249 | |||
| 1250 | |||
| 1251 | ; | ||
| 1252 | ; C callable routines for manipulating page table entries. | ||
| 1253 | ; and Current FRS - CurRegSet | ||
| 1254 | |||
| 1255 | |||
| 1256 | ; | ||
| 1257 | ; Equates for picking up arguments passed in from C code. | ||
| 1258 | ; Arg1 - word Arg, | ||
| 1259 | ; Arg2 - word or dword Arg | ||
| 1260 | ; | ||
| 1261 | |||
| 1262 | Arg1 equ [BP+4] | ||
| 1263 | Arg2 equ [BP+6] | ||
| 1264 | |||
| 1265 | |||
| 1266 | ;***************************************************************************** | ||
| 1267 | ; | ||
| 1268 | ; _GetPte - called from C code | ||
| 1269 | ; | ||
| 1270 | ; return pte in dx:ax | ||
| 1271 | ; | ||
| 1272 | ; long GetPte(PTIndex) | ||
| 1273 | ; unsigned PTIndex; | ||
| 1274 | ; | ||
| 1275 | ; Written: JHB Aug 10,1988 | ||
| 1276 | ; Modif: ISP Aug 12,1988 parameter should be returned in dx:ax not eax | ||
| 1277 | ; removed some of pushes and pops | ||
| 1278 | ; added cld before load just to be safe | ||
| 1279 | ; offset specified in DGROUP | ||
| 1280 | ; | ||
| 1281 | ; JHB Aug 21 88 changed input param to PTIndex | ||
| 1282 | ; | ||
| 1283 | ;***************************************************************************** | ||
| 1284 | |||
| 1285 | _GetPte proc near | ||
| 1286 | |||
| 1287 | push bp | ||
| 1288 | mov bp, sp | ||
| 1289 | push si | ||
| 1290 | push ds | ||
| 1291 | |||
| 1292 | mov ax, PAGET_GSEL | ||
| 1293 | mov ds, ax | ||
| 1294 | |||
| 1295 | mov si, WORD PTR Arg1 | ||
| 1296 | shl si, 2 ; dword entries in the PT | ||
| 1297 | |||
| 1298 | cld | ||
| 1299 | lodsw ; get low word | ||
| 1300 | mov dx, ax ; into dx | ||
| 1301 | lodsw ; get hiword | ||
| 1302 | xchg dx, ax ; dx:ax = long return value | ||
| 1303 | |||
| 1304 | pop ds | ||
| 1305 | pop si | ||
| 1306 | pop bp | ||
| 1307 | ret | ||
| 1308 | _GetPte endp | ||
| 1309 | |||
| 1310 | ;***************************************************************************** | ||
| 1311 | ; | ||
| 1312 | ; _SetPte - called from C code | ||
| 1313 | ; | ||
| 1314 | ; Locate the PT entry for given EmmPhyPage and set it to pte. | ||
| 1315 | ; | ||
| 1316 | ; SetPte(PTIndex, pte) | ||
| 1317 | ; unsigned PTIndex; | ||
| 1318 | ; long pte; | ||
| 1319 | ; | ||
| 1320 | ; WRITTEN: JHB Aug 10,1988 | ||
| 1321 | ; MODIF: ISP Aug 12,1988 pushes and pops removed | ||
| 1322 | ; cld added for safety | ||
| 1323 | ; offset specified in DGROUP | ||
| 1324 | ; pushed poped eax (check on this) | ||
| 1325 | ; | ||
| 1326 | ; JHB Aug 21, 1988 changed first input param to PTIndex | ||
| 1327 | ; | ||
| 1328 | ;***************************************************************************** | ||
| 1329 | |||
| 1330 | |||
| 1331 | _SetPte proc near | ||
| 1332 | |||
| 1333 | push bp | ||
| 1334 | mov bp, sp | ||
| 1335 | push di | ||
| 1336 | push es | ||
| 1337 | |||
| 1338 | mov ax, PAGET_GSEL | ||
| 1339 | mov es, ax | ||
| 1340 | mov di, WORD PTR Arg1 | ||
| 1341 | shl di, 2 | ||
| 1342 | |||
| 1343 | mov eax, DWORD PTR Arg2 | ||
| 1344 | and ax, 0F000H ; clear low 12 bits | ||
| 1345 | or ax, P_AVAIL ; page control bits - user, present, write | ||
| 1346 | |||
| 1347 | cld | ||
| 1348 | stosd | ||
| 1349 | ; | ||
| 1350 | ; reload CR3 to flush TLB | ||
| 1351 | ; | ||
| 1352 | mov eax, CR3 | ||
| 1353 | mov CR3, eax | ||
| 1354 | |||
| 1355 | ; mov eax,dword ptr [Page_Dir] ; mov EAX,dword ptr [Page_Dir] | ||
| 1356 | ; db 0Fh,22h,18h ; mov CR3,EAX | ||
| 1357 | |||
| 1358 | pop es | ||
| 1359 | pop di | ||
| 1360 | pop bp | ||
| 1361 | ret | ||
| 1362 | _SetPte endp | ||
| 1363 | |||
| 1364 | ;***************************************************************************** | ||
| 1365 | ; | ||
| 1366 | ; _GetCRSEntry - called from C code | ||
| 1367 | ; | ||
| 1368 | ; return the Emm page mapped to the EmmPhyPage by looking up CurRegSet. | ||
| 1369 | ; | ||
| 1370 | ; unsigned GetCRSEntry(EmmPhyPage) | ||
| 1371 | ; unsigned EmmPhyPage | ||
| 1372 | ; | ||
| 1373 | ; WRITTEN: JHB Aug 10,1988 | ||
| 1374 | ; MODIF: ISP Aug 12,1988 pushes and pops removed | ||
| 1375 | ; Offset specified in DGROUP | ||
| 1376 | ; cld added for safety | ||
| 1377 | ;***************************************************************************** | ||
| 1378 | |||
| 1379 | _GetCRSEntry proc near | ||
| 1380 | |||
| 1381 | push bp | ||
| 1382 | mov bp, sp | ||
| 1383 | push di | ||
| 1384 | |||
| 1385 | mov bx, WORD PTR Arg1 | ||
| 1386 | shl bx, 1 ; each FRS entry is a word | ||
| 1387 | Get_FRS_Window DI ; di = address of Current FRS | ||
| 1388 | add di, bx | ||
| 1389 | mov ax, word ptr [di] ; load FRS entry | ||
| 1390 | |||
| 1391 | pop di | ||
| 1392 | pop bp | ||
| 1393 | ret | ||
| 1394 | _GetCRSEntry endp | ||
| 1395 | |||
| 1396 | ; | ||
| 1397 | ; Equates for picking up long Arguments from C code | ||
| 1398 | ; LArg1 - long Arg | ||
| 1399 | ; Larg2 - long Arg when the first Arg is also long | ||
| 1400 | ; | ||
| 1401 | |||
| 1402 | LArg1 equ [BP+4] | ||
| 1403 | LArg2 equ [BP+8] | ||
| 1404 | |||
| 1405 | ;***************************************************************************** | ||
| 1406 | ; | ||
| 1407 | ; _GetDMALinAdr - called from C code | ||
| 1408 | ; | ||
| 1409 | ; returns the Lin Adr for the DMA buffer whose physical adr is given | ||
| 1410 | ; | ||
| 1411 | ; long GetDMALinAdr(DMAPhyAdr) | ||
| 1412 | ; long DMAPhyAdr; | ||
| 1413 | ; | ||
| 1414 | ; Get the Linear address for DMAPhyAdr. There is a pte which always | ||
| 1415 | ; maps to this always. MapLinear translates DMAPhyAdr to a linear adr. | ||
| 1416 | ; | ||
| 1417 | ; | ||
| 1418 | ; 8/12/88 JHB removed _Copy16K, changed it to this routine. | ||
| 1419 | ; | ||
| 1420 | ;***************************************************************************** | ||
| 1421 | |||
| 1422 | _GetDMALinAdr proc near | ||
| 1423 | |||
| 1424 | push bp | ||
| 1425 | mov bp, sp | ||
| 1426 | push si | ||
| 1427 | push di | ||
| 1428 | push ds | ||
| 1429 | ; | ||
| 1430 | ; convert the DMAPhyAdr into a linear address. | ||
| 1431 | ; | ||
| 1432 | mov eax, dword ptr LArg1 | ||
| 1433 | call MapLinear | ||
| 1434 | ; | ||
| 1435 | ; eax = 32 bit linear adr for the DMA Xfer area. | ||
| 1436 | ; | ||
| 1437 | ror eax, 16 | ||
| 1438 | mov dx, ax | ||
| 1439 | ror eax, 16 ; dx:ax 32 bit linear adr to be returned | ||
| 1440 | |||
| 1441 | pop ds | ||
| 1442 | pop di | ||
| 1443 | pop si | ||
| 1444 | pop bp | ||
| 1445 | ret | ||
| 1446 | _GetDMALinAdr endp | ||
| 1447 | |||
| 1448 | ;****************************************************************************** | ||
| 1449 | ; | ||
| 1450 | ; set_selector - set up a selector address/attrib | ||
| 1451 | ; | ||
| 1452 | ; ENTRY: EAX = address for GDT selector - a linear address | ||
| 1453 | ; DI = GDT selector | ||
| 1454 | ; EXIT: selector in DI is writeable data segment,128k long and points | ||
| 1455 | ; to desired address. | ||
| 1456 | ; | ||
| 1457 | ;****************************************************************************** | ||
| 1458 | |||
| 1459 | set_selector proc near | ||
| 1460 | |||
| 1461 | push eax | ||
| 1462 | push di | ||
| 1463 | push es | ||
| 1464 | |||
| 1465 | and di,NOT 07h ; just in case... GDT entry | ||
| 1466 | push GDTD_GSEL | ||
| 1467 | pop es ; ES:DI -> selector entry | ||
| 1468 | |||
| 1469 | mov es:[di+2],ax ; low word of base address | ||
| 1470 | |||
| 1471 | shr eax,16 ; AX = high word of address | ||
| 1472 | mov es:[di+4],al ; low byte of high word of address | ||
| 1473 | xor al,al ; clear limit/G bit | ||
| 1474 | or al, 1 ; set LSB0 i.e. Limit16 bit for 128K Xfer | ||
| 1475 | mov es:[di+6],ax ; set high byte of high word of addr | ||
| 1476 | ; and high nibble of limit/G bit | ||
| 1477 | ; and Limit Bit 16 for 128K transfer | ||
| 1478 | mov ax,0FFFFh | ||
| 1479 | mov es:[di],ax ; set limit bits 0-15 | ||
| 1480 | |||
| 1481 | mov al,D_DATA0 ; writeable DATA seg / ring 0 | ||
| 1482 | mov es:[di+5],al | ||
| 1483 | |||
| 1484 | pop es | ||
| 1485 | pop di | ||
| 1486 | pop eax | ||
| 1487 | |||
| 1488 | ret | ||
| 1489 | |||
| 1490 | set_selector endp | ||
| 1491 | |||
| 1492 | ;**************************************************************************** | ||
| 1493 | ; _Exchange16K - called from C | ||
| 1494 | ; | ||
| 1495 | ; Exchange contents of the pages at LinAdr1 and LinAdr2 | ||
| 1496 | ; | ||
| 1497 | ; Exchange16K(LinAdr1, LinAdr2) | ||
| 1498 | ; long LinAdr1, LinAdr2; | ||
| 1499 | ; | ||
| 1500 | ; Written: JHB Aug 11, 1988 | ||
| 1501 | ; ISP Aug 12, 1988 Added cld. | ||
| 1502 | ; DWORD PTR mentioned explicitly | ||
| 1503 | ;***************************************************************************** | ||
| 1504 | |||
| 1505 | _Exchange16K proc near | ||
| 1506 | |||
| 1507 | push bp | ||
| 1508 | mov bp, sp | ||
| 1509 | push si | ||
| 1510 | push di | ||
| 1511 | push ds | ||
| 1512 | |||
| 1513 | mov di,MBSRC_GSEL ; source selector | ||
| 1514 | mov eax,dword ptr LArg1 ; load linear adr | ||
| 1515 | call set_selector ; set up a selector in GDT | ||
| 1516 | mov es,di | ||
| 1517 | |||
| 1518 | mov di,MBTAR_GSEL ; destination selector | ||
| 1519 | mov eax,dword ptr LArg2 | ||
| 1520 | call set_selector ; set up selector | ||
| 1521 | mov ds,di | ||
| 1522 | mov cx,1000h ; 16k bytes (4 at a time) | ||
| 1523 | xor di,di ; initialize index | ||
| 1524 | cld | ||
| 1525 | sloop: | ||
| 1526 | mov eax,dword ptr es:[di] ; pick a dword at LArg1 | ||
| 1527 | xchg eax,dword ptr ds:[di] ; swap with dword at LArg2 | ||
| 1528 | stosd ; store new dword at LArg1 | ||
| 1529 | loop sloop | ||
| 1530 | |||
| 1531 | pop ds | ||
| 1532 | pop di | ||
| 1533 | pop si | ||
| 1534 | pop bp | ||
| 1535 | ret | ||
| 1536 | |||
| 1537 | _Exchange16K endp | ||
| 1538 | |||
| 1539 | ; | ||
| 1540 | ; signals an exception error | ||
| 1541 | ; | ||
| 1542 | _FatalError proc near | ||
| 1543 | |||
| 1544 | push bp | ||
| 1545 | mov bp, sp | ||
| 1546 | |||
| 1547 | mov ax, 1 | ||
| 1548 | mov bx, 3 | ||
| 1549 | call ErrHndlr | ||
| 1550 | |||
| 1551 | pop bp | ||
| 1552 | ret | ||
| 1553 | |||
| 1554 | _FatalError endp | ||
| 1555 | |||
| 1556 | _TEXT ends ; end of segment | ||
| 1557 | |||
| 1558 | end ; end of module | ||
| 1559 | |||
| 1560 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/EM286LL.ASM b/v4.0/src/MEMM/MEMM/EM286LL.ASM new file mode 100644 index 0000000..3b3f72e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EM286LL.ASM | |||
| @@ -0,0 +1,360 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EM286LL - 386 routine to emulate 286 LOADALL | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EMM286LL - 286 loadall emulation routine | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: April 11,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 04/16/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/18/86 0.01 Moved EL_Off before buffer | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 06/28/86 0.02 Modified CR0 logic & Edi for LL3 buffer | ||
| 31 | ; 07/03/86 0.03 Removed logic for enabling A20 watch | ||
| 32 | ; 07/06/86 0.04 Change assume to DGROUP | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | ; | ||
| 36 | ; Functional Description: | ||
| 37 | ; | ||
| 38 | ; 286 LOADALL is emulated by building a buffer for a | ||
| 39 | ; 386 LOADALL from the 286 LOADALL buffer (@80:0) and executing the 386 | ||
| 40 | ; LOADALL. | ||
| 41 | ; | ||
| 42 | ; | ||
| 43 | ;****************************************************************************** | ||
| 44 | .lfcond ; list false conditionals | ||
| 45 | .386p | ||
| 46 | page | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; P U B L I C D E C L A R A T I O N S | ||
| 49 | ;****************************************************************************** | ||
| 50 | ; | ||
| 51 | public EM286ll | ||
| 52 | public ELOff | ||
| 53 | ; | ||
| 54 | page | ||
| 55 | ;****************************************************************************** | ||
| 56 | ; L O C A L C O N S T A N T S | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; | ||
| 59 | include loadall.inc | ||
| 60 | include VDMseg.inc | ||
| 61 | include desc.inc | ||
| 62 | include VDMsel.inc | ||
| 63 | include instr386.inc | ||
| 64 | include vm386.inc | ||
| 65 | include oemdep.inc | ||
| 66 | |||
| 67 | FALSE equ 0 | ||
| 68 | TRUE equ not FALSE | ||
| 69 | |||
| 70 | ; | ||
| 71 | ; DescCopy | ||
| 72 | ; Macro for copying a 286 Loadall descriptor cache entry to a | ||
| 73 | ; 386 Loadall descriptor cache entry. | ||
| 74 | ; ENTRY: DS:SI pts to 286 Loadall descriptor entry | ||
| 75 | ; ES:DI pts to 386 Loadall descriptor entry | ||
| 76 | ; | ||
| 77 | ; EXIT: DS:SI unchanged. | ||
| 78 | ; ES:DI pts to byte after 386 Loadall descriptor entry (next entry). | ||
| 79 | ; *** The access rights byte in set to DPL 3 for virtual mode *** | ||
| 80 | ; | ||
| 81 | ; USED: EAX | ||
| 82 | ; | ||
| 83 | DescCopy MACRO | ||
| 84 | XOR_EAX_EAX ; clear EAX | ||
| 85 | mov ax,word ptr [si.dc2_BASEhi] ; AL = junk, AH = Access rights | ||
| 86 | or ah,D_DPL3 ;* set DPL 3 for virtual mode access | ||
| 87 | OP32 | ||
| 88 | stosw ; store: junk->AR1,AR->AR2,0->AR3 & AR4 | ||
| 89 | OP32 | ||
| 90 | mov ax,[si] ; 24 bits of Base Addr from 286 entry | ||
| 91 | OP32 | ||
| 92 | and ax,0FFFFh ; AND EAX,00FFFFFFh | ||
| 93 | dw 000FFh ; clear high byte of base addr | ||
| 94 | call MapLinear ; Map address according to page tables | ||
| 95 | OP32 | ||
| 96 | stosw ; store Base Addr for 386 entry | ||
| 97 | XOR_EAX_EAX ; clear EAX | ||
| 98 | mov ax,[si.dc2_LIMIT] ; get low 16 bits of limit | ||
| 99 | OP32 | ||
| 100 | stosw ; store 32 bit LIMIT into 386 entry | ||
| 101 | ENDM | ||
| 102 | ; | ||
| 103 | ; CurCopy | ||
| 104 | ; Macro for copying a current descriptor cache entry to a | ||
| 105 | ; 386 Loadall descriptor cache entry. | ||
| 106 | ; ENTRY: DS:BX pts to current descriptor | ||
| 107 | ; ES:DI pts to 386 Loadall descriptor entry | ||
| 108 | ; | ||
| 109 | ; EXIT: DS:BX unchanged. | ||
| 110 | ; ES:DI pts to byte after 386 Loadall descriptor entry (next entry). | ||
| 111 | ; *** The access rights byte in set to DPL 3 for virtual mode *** | ||
| 112 | ; | ||
| 113 | ; USED: EAX | ||
| 114 | ; | ||
| 115 | CurCopy MACRO | ||
| 116 | OP32 | ||
| 117 | mov ax,[bx+4] ; get AR info | ||
| 118 | or ah,D_DPL3 ;* set DPL 3 for virtual mode access | ||
| 119 | OP32 | ||
| 120 | stosw ; store into cache entry | ||
| 121 | mov ah,[bx+7] ; AX = Base[31..16] | ||
| 122 | OP32 | ||
| 123 | shl ax,16 ; high word of EAX = Base[31..16] | ||
| 124 | mov ax,[bx+2] ; EAX = Base[31..0] | ||
| 125 | OP32 | ||
| 126 | stosw | ||
| 127 | mov al,[bx+6] ; LIMIT[19..16] in low bits of AL | ||
| 128 | and ax,0Fh | ||
| 129 | OP32 | ||
| 130 | shl ax,16 ; high word of EAX = LIMIT[31..16] | ||
| 131 | ; NOTE: VDM does not use page | ||
| 132 | ; granularity for limit field !! | ||
| 133 | mov ax,[bx] ; EAX = LIMIT[31..0] | ||
| 134 | OP32 | ||
| 135 | stosw ; store into cache for 386 buffer | ||
| 136 | ENDM | ||
| 137 | ;****************************************************************************** | ||
| 138 | ; E X T E R N A L R E F E R E N C E S | ||
| 139 | ;****************************************************************************** | ||
| 140 | ; | ||
| 141 | L286BUFF segment at 80h | ||
| 142 | ; | ||
| 143 | ; Source 286 LoadAll buffer | ||
| 144 | ; | ||
| 145 | SLBuff LoadAllBuf286 <> ; 286 loadall buffer | ||
| 146 | |||
| 147 | L286BUFF ends | ||
| 148 | |||
| 149 | _TEXT segment | ||
| 150 | |||
| 151 | extrn MapLinear:near ; map linear address | ||
| 152 | extrn PortTrap:near ; IOBM trap set function (VMINIT) | ||
| 153 | |||
| 154 | _TEXT ends | ||
| 155 | |||
| 156 | ; | ||
| 157 | ;****************************************************************************** | ||
| 158 | ; L O C A L D A T A A R E A | ||
| 159 | ;****************************************************************************** | ||
| 160 | |||
| 161 | _DATA segment | ||
| 162 | |||
| 163 | ELOff dw offset ELbuff ; offset of 386 loadall buffer | ||
| 164 | ELbuff LoadAllBuf386 <> ; 386 loadall buffer | ||
| 165 | dd 0 ; filler - allow dword align | ||
| 166 | |||
| 167 | ;(0.03)extrn A20watch:byte ; Loadall/KBD A20 disable flag | ||
| 168 | |||
| 169 | _DATA ends | ||
| 170 | |||
| 171 | page | ||
| 172 | ;****************************************************************************** | ||
| 173 | ; S E G M E N T D E F I N I T I O N | ||
| 174 | ;****************************************************************************** | ||
| 175 | ; | ||
| 176 | _TEXT segment | ||
| 177 | ASSUME CS:_TEXT,DS:DGROUP,ES:DGROUP | ||
| 178 | |||
| 179 | ;****************************************************************************** | ||
| 180 | ; EM286ll - emulate 286 Loadall | ||
| 181 | ; | ||
| 182 | ; ENTRY: Protected Mode | ||
| 183 | ; physical address 80:0 holds 286 loadall buffer info | ||
| 184 | ; | ||
| 185 | ; EXIT: via Loadall to virtual mode | ||
| 186 | ; The 286 Loadall buffer is emulated with the following | ||
| 187 | ; exceptions: | ||
| 188 | ; The VM bit is set in EFLAGS. | ||
| 189 | ; The TR, IDT descriptor cache, & TSS descriptor cache are | ||
| 190 | ; pointed to the VDM entries. | ||
| 191 | ; | ||
| 192 | ; USED: | ||
| 193 | ; | ||
| 194 | ;****************************************************************************** | ||
| 195 | EM286ll proc near | ||
| 196 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 197 | mov ds,bx ; DS -> GDT | ||
| 198 | mov bx,800h ; BX = VM CS (segment form) | ||
| 199 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 200 | xor bx,bx | ||
| 201 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 202 | mov bx,VM1_GSEL | ||
| 203 | mov ds,bx ; DS:0 points to 286 loadall buffer | ||
| 204 | ASSUME DS:L286BUFF | ||
| 205 | ; | ||
| 206 | mov ax,VDMD_GSEL | ||
| 207 | mov es,ax | ||
| 208 | mov di,ES:[ELOff] ; ES:DI pts to 386 loadall buffer | ||
| 209 | ; | ||
| 210 | cld | ||
| 211 | ; | ||
| 212 | MOV_EAX_CR0 ; mov EAX,CR0 | ||
| 213 | and ax,0FFF1h ;clear current TS,EM, & MP bits | ||
| 214 | mov cx,[SLBuff.ll2_MSW] ; CX = 286 ll_buff MSW | ||
| 215 | and cx,000Eh ;retain 286 TS,EM, & MP bits | ||
| 216 | or ax,cx ; set client's TS,EM, & MP bits | ||
| 217 | OP32 | ||
| 218 | stosw ; store CR0 for 386 buffer | ||
| 219 | ; | ||
| 220 | OP32 | ||
| 221 | mov ax,0000h | ||
| 222 | dw 0002h ; VM bit on | ||
| 223 | mov ax,[SLBuff.ll2_FLAGS] ; get low word of flags | ||
| 224 | or ax,3000h ; set IOPL to 3 | ||
| 225 | OP32 | ||
| 226 | stosw ; store EFLAGS for 386 buffer | ||
| 227 | ; | ||
| 228 | XOR_EAX_EAX ; clear EAX | ||
| 229 | mov ax,[SLBuff.ll2_IP] ; get 286 IP - high word of EAX clear | ||
| 230 | OP32 | ||
| 231 | stosw ; store EIP for 386 buffer | ||
| 232 | ; | ||
| 233 | ; Copy the client's EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX | ||
| 234 | ; register images from his 386 loadall buffer to our 386 loadall buffer | ||
| 235 | ; | ||
| 236 | mov si,offset ll2_DI ; DS:SI pts to DI in 286 buffer | ||
| 237 | mov cx,8 | ||
| 238 | CopyGen: ; Copy General Purpose Registers | ||
| 239 | lodsw ; EAX = reg image from client's buffer | ||
| 240 | OP32 | ||
| 241 | stosw ; store it in our 386 buffer | ||
| 242 | loop CopyGen | ||
| 243 | |||
| 244 | ; | ||
| 245 | ; 386 debug registers | ||
| 246 | ; | ||
| 247 | MOV_EAX_DR6 | ||
| 248 | OP32 | ||
| 249 | stosw ; store DR6 in our 386 buffer | ||
| 250 | |||
| 251 | MOV_EAX_DR7 | ||
| 252 | OP32 | ||
| 253 | stosw ; store DR7 in our 386 buffer | ||
| 254 | ; | ||
| 255 | XOR_EAX_EAX ; clear EAX | ||
| 256 | ; | ||
| 257 | mov ax,TSS_GSEL ; get current TR for VDM's TSS !!! | ||
| 258 | OP32 | ||
| 259 | stosw ; store TR for 386 buffer | ||
| 260 | ; | ||
| 261 | mov si,offset ll2_LDT ; DS:SI pts to LDT in 286 buffer | ||
| 262 | lodsw ; get LDT entry from 286 buffer | ||
| 263 | OP32 | ||
| 264 | stosw ; store LDT for 386 buffer | ||
| 265 | |||
| 266 | OP32 | ||
| 267 | stosw ; store junk into GS for 386 buffer | ||
| 268 | |||
| 269 | OP32 | ||
| 270 | stosw ; store junk into FS for 386 buffer | ||
| 271 | |||
| 272 | ; | ||
| 273 | ; Copy the client's DS, SS, CS, ES register images from his 286 loadall | ||
| 274 | ; buffer to our 386 loadall buffer | ||
| 275 | ; | ||
| 276 | mov cx,4 | ||
| 277 | CopySeg: ; Copy Segment Registers | ||
| 278 | lodsw ; get seg image from client's buffer | ||
| 279 | OP32 | ||
| 280 | stosw ; store it in our 386 buffer | ||
| 281 | loop CopySeg | ||
| 282 | |||
| 283 | ; ES:DI pts to 386 TSS cache entry | ||
| 284 | ; | ||
| 285 | ; Copy the current TSS, IDT, & GDT descriptors from the GDT table to | ||
| 286 | ; our 386 loadall buffer | ||
| 287 | ; | ||
| 288 | push ds ; save client's buffer selector | ||
| 289 | mov ax,GDTD_GSEL | ||
| 290 | mov ds,ax | ||
| 291 | |||
| 292 | mov cx, 3 | ||
| 293 | mov bx, TSS_GSEL | ||
| 294 | push word ptr GDTD_GSEL | ||
| 295 | push word ptr IDTD_GSEL | ||
| 296 | |||
| 297 | CopyCur: ; Copy current descriptors | ||
| 298 | CurCopy ; DS:[BX] points to current descriptor | ||
| 299 | pop bx | ||
| 300 | loop CopyCur | ||
| 301 | mov ds, bx ; restore client's buffer selector | ||
| 302 | |||
| 303 | ; | ||
| 304 | ; ES:DI pts to 386 LDT cache entry | ||
| 305 | mov si,offset ll2_LDTcache ; DS:SI pts to 286 LDT cache entry | ||
| 306 | DescCopy ; store LDT cache for 386 buffer | ||
| 307 | ; | ||
| 308 | XOR_EAX_EAX ; clear EAX- use 0 for GS/FS caches | ||
| 309 | |||
| 310 | OP32 | ||
| 311 | stosw ; store GS cache for 386 buffer | ||
| 312 | OP32 | ||
| 313 | stosw | ||
| 314 | OP32 | ||
| 315 | stosw | ||
| 316 | ; | ||
| 317 | OP32 | ||
| 318 | stosw ; store FS cache for 386 buffer | ||
| 319 | OP32 | ||
| 320 | stosw | ||
| 321 | OP32 | ||
| 322 | stosw | ||
| 323 | ; | ||
| 324 | ; Copy the client's DS, SS, CS, ES register cache images from | ||
| 325 | ; his 286 loadall buffer to our 386 loadall buffer | ||
| 326 | ; | ||
| 327 | mov si,offset ll2_DScache ; DS:SI pts to 286 DS cache entry | ||
| 328 | mov cx,4 | ||
| 329 | CopyCac: ; ES:DI pts to our 386 ll cache entry | ||
| 330 | DescCopy ; store his cache in our 386 buffer | ||
| 331 | sub si,06h ; DS:SI pts to client's cache entry | ||
| 332 | loop CopyCac | ||
| 333 | ; | ||
| 334 | ; 386 Loadall buffer complete | ||
| 335 | ; | ||
| 336 | |||
| 337 | ;(0.03) push es | ||
| 338 | ;(0.03) mov ax, TSSD_GSEL ; Point ES to TSS for PortTrap | ||
| 339 | ;(0.03) mov es, ax | ||
| 340 | ;(0.03) mov bh, 80h ; set every 1k | ||
| 341 | ;(0.03) mov ax, KbdDataPort | ||
| 342 | ;(0.03) call PortTrap ; set traps on keyboard ports | ||
| 343 | ;(0.03) mov ax, KbdCmdPort ; in case client | ||
| 344 | ;(0.03) call PortTrap ; tries to disable A20 | ||
| 345 | ;(0.03) pop es | ||
| 346 | ;(0.03) mov es:[A20watch], YesLLdone ; set A20 watch flag | ||
| 347 | |||
| 348 | HwTabLock ; Hardware lock the high ram | ||
| 349 | |||
| 350 | OP32 | ||
| 351 | xor di,di ; clear EDI | ||
| 352 | mov di,ES:[ELOff] ; ES:EDI pts to loadall buffer | ||
| 353 | dw LODAL386 ; execute 386 LOADALL | ||
| 354 | |||
| 355 | ASSUME DS:DGROUP | ||
| 356 | ; | ||
| 357 | EM286ll endp | ||
| 358 | |||
| 359 | _TEXT ends | ||
| 360 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/EM386LL.ASM b/v4.0/src/MEMM/MEMM/EM386LL.ASM new file mode 100644 index 0000000..3408eaa --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EM386LL.ASM | |||
| @@ -0,0 +1,397 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EM386LL - 386 routine to emulate 386 LOADALL | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EM386LL - 386 routine to emulate 386 LOADALL | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: April 11,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 04/16/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 29 | ; 06/29/86 0.02 Fixed error handler call. Error handler called | ||
| 30 | ; only on attempt to set VM bit in EFLAGS | ||
| 31 | ; 06/30/86 0.02 Jmp to error routine (instead of calling) | ||
| 32 | ; 07/03/86 0.03 Removed logic to enable A20 line watch | ||
| 33 | ; 07/05/86 0.04 JumpReal in R_CODE | ||
| 34 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 35 | ; 07/08/86 0.04 added DB67 NOPs to avoid B1 errata | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | ; | ||
| 39 | ; Functional Description: | ||
| 40 | ; | ||
| 41 | ; 386 LOADALL is emulated by building a buffer for a | ||
| 42 | ; 386 LOADALL from the client's 386 LOADALL buffer and executing the 386 | ||
| 43 | ; LOADALL. | ||
| 44 | ; | ||
| 45 | ; check DR6/DR7 for addresses > 1meg ? | ||
| 46 | ; | ||
| 47 | ;****************************************************************************** | ||
| 48 | .lfcond ; list false conditionals | ||
| 49 | .386p | ||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; P U B L I C D E C L A R A T I O N S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | public EM386ll | ||
| 56 | ; | ||
| 57 | page | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; L O C A L C O N S T A N T S | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; | ||
| 62 | include loadall.inc | ||
| 63 | include VDMseg.inc | ||
| 64 | include desc.inc | ||
| 65 | include VDMsel.inc | ||
| 66 | include instr386.inc | ||
| 67 | include vm386.inc | ||
| 68 | include oemdep.inc | ||
| 69 | |||
| 70 | FALSE equ 0 | ||
| 71 | TRUE equ not FALSE | ||
| 72 | |||
| 73 | ; | ||
| 74 | ; Desc3Copy | ||
| 75 | ; Macro for copying a 386 Loadall descriptor cache entry to a | ||
| 76 | ; 386 Loadall descriptor cache entry. | ||
| 77 | ; ENTRY: DS:ESI pts to client's 386 Loadall descriptor entry | ||
| 78 | ; ES:DI pts to our 386 Loadall descriptor entry | ||
| 79 | ; | ||
| 80 | ; EXIT: DS:ESI pts to byte after client's 386 ll descr entry (next entry). | ||
| 81 | ; ES:DI pts to byte after 386 Loadall descriptor entry (next entry). | ||
| 82 | ; *** The access rights byte in set to DPL 3 for virtual mode *** | ||
| 83 | ; | ||
| 84 | ; USED: EAX | ||
| 85 | ; | ||
| 86 | Desc3Copy MACRO | ||
| 87 | OP32 | ||
| 88 | EA32 ; EAX = dword from DS:[ESI] | ||
| 89 | lodsw ; get access rights | ||
| 90 | |||
| 91 | or ah,D_DPL3 ;* set DPL 3 for virtual mode access | ||
| 92 | |||
| 93 | OP32 | ||
| 94 | stosw ; store access rights | ||
| 95 | |||
| 96 | OP32 | ||
| 97 | EA32 ; EAX = dword from DS:[ESI] | ||
| 98 | lodsw ; 32 bits of Base Addr from 386 entry | ||
| 99 | |||
| 100 | call MapLinear ; map this linear addr by page tables | ||
| 101 | |||
| 102 | OP32 | ||
| 103 | stosw ; store Base Addr for 386 entry | ||
| 104 | |||
| 105 | OP32 | ||
| 106 | EA32 ; EAX = dword from DS:[ESI] | ||
| 107 | lodsw ; get 32 bits of limit | ||
| 108 | |||
| 109 | OP32 | ||
| 110 | stosw ; store 32 bit LIMIT into 386 entry | ||
| 111 | ENDM | ||
| 112 | |||
| 113 | ; | ||
| 114 | ; CurCopy | ||
| 115 | ; Macro for copying a current descriptor cache entry to a | ||
| 116 | ; 386 Loadall descriptor cache entry. | ||
| 117 | ; ENTRY: DS:BX pts to current descriptor | ||
| 118 | ; ES:DI pts to 386 Loadall descriptor entry | ||
| 119 | ; | ||
| 120 | ; EXIT: DS:BX unchanged. | ||
| 121 | ; ES:DI pts to byte after 386 Loadall descriptor entry (next entry). | ||
| 122 | ; *** The access rights byte in set to DPL 3 for virtual mode *** | ||
| 123 | ; | ||
| 124 | ; USED: EAX | ||
| 125 | ; | ||
| 126 | CurCopy MACRO | ||
| 127 | OP32 | ||
| 128 | mov ax,[bx+4] ; get AR info | ||
| 129 | or ah,D_DPL3 ;* set DPL 3 for virtual mode access | ||
| 130 | OP32 | ||
| 131 | stosw ; store into cache entry | ||
| 132 | mov ah,[bx+7] ; AX = Base[31..16] | ||
| 133 | OP32 | ||
| 134 | shl ax,16 ; high word of EAX = Base[31..16] | ||
| 135 | mov ax,[bx+2] ; EAX = Base[31..0] | ||
| 136 | OP32 | ||
| 137 | stosw | ||
| 138 | mov al,[bx+6] ; LIMIT[19..16] in low bits of AL | ||
| 139 | and ax,0Fh | ||
| 140 | OP32 | ||
| 141 | shl ax,16 ; high word of EAX = LIMIT[31..16] | ||
| 142 | ; NOTE: VDM does not use page | ||
| 143 | ; granularity for limit field !! | ||
| 144 | mov ax,[bx] ; EAX = LIMIT[31..0] | ||
| 145 | OP32 | ||
| 146 | stosw ; store into cache for 386 buffer | ||
| 147 | ENDM | ||
| 148 | |||
| 149 | ;****************************************************************************** | ||
| 150 | ; L O C A L D A T A A R E A | ||
| 151 | ;****************************************************************************** | ||
| 152 | |||
| 153 | _DATA segment | ||
| 154 | extrn ELOff:word ; offset of 386 loadall buffer | ||
| 155 | _DATA ends | ||
| 156 | |||
| 157 | |||
| 158 | R_CODE segment | ||
| 159 | extrn JumpReal:far ; continue client in real mode (rrtrap.asm) | ||
| 160 | R_CODE ends | ||
| 161 | |||
| 162 | _TEXT segment | ||
| 163 | extrn MapLinear:near ; maps linear addresses (maplin.asm) | ||
| 164 | extrn PortTrap:near ; IOBM trap set function (vminit.asm) | ||
| 165 | extrn ErrHndlr:near ; error handler (errhndlr.asm) | ||
| 166 | _TEXT ends | ||
| 167 | |||
| 168 | |||
| 169 | page | ||
| 170 | ;****************************************************************************** | ||
| 171 | ; S E G M E N T D E F I N I T I O N | ||
| 172 | ;****************************************************************************** | ||
| 173 | ; | ||
| 174 | _TEXT segment | ||
| 175 | ASSUME CS:_TEXT,DS:DGROUP,ES:DGROUP | ||
| 176 | |||
| 177 | ;****************************************************************************** | ||
| 178 | ; EM386ll - emulate 386 Loadall | ||
| 179 | ; The basic approach here is to filter the client's loadall buffer into | ||
| 180 | ; a temporary buffer, setting our values for the parameters we don't want | ||
| 181 | ; him to change and then executing the 386 loadall from our buffer. | ||
| 182 | ; | ||
| 183 | ; ENTRY: Protected Mode | ||
| 184 | ; BP points to bottom of client's GPfault stack frame | ||
| 185 | ; ES(in GP frame):EDI points to the client's loadall buffer info | ||
| 186 | ; on stack: ESI,EBX,EBP | ||
| 187 | ; | ||
| 188 | ; EXIT: via Loadall to virtual mode | ||
| 189 | ; The 386 Loadall buffer is emulated with the following | ||
| 190 | ; exceptions: | ||
| 191 | ; The VM bit is set in EFLAGS. | ||
| 192 | ; The TR, IDT descriptor cache, & TSS descriptor cache are | ||
| 193 | ; pointed to the VDM entries. | ||
| 194 | ; | ||
| 195 | ; USED: Not applicable... loadall reloads all registers | ||
| 196 | ; | ||
| 197 | ;****************************************************************************** | ||
| 198 | EM386ll proc near | ||
| 199 | ; | ||
| 200 | PUSH_EAX | ||
| 201 | PUSH_ECX | ||
| 202 | PUSH_EDI | ||
| 203 | |||
| 204 | ; Build a descriptor to client's 386 loadall buffer | ||
| 205 | |||
| 206 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 207 | mov ds,bx ; DS -> GDT | ||
| 208 | mov bx, [bp.VTFOE+VMTF_ES] ; Get VM ES from GP stack frame | ||
| 209 | mov ax,bx | ||
| 210 | shl bx,4 ; BX = low 16 bits of base | ||
| 211 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 212 | shr ax, 4 ; AH = high 8 bits of base | ||
| 213 | mov ds:[VM1_GSEL+4],ah ; place in descriptor | ||
| 214 | |||
| 215 | ; Point DS:ESI to start of client's 386 loadall buffer | ||
| 216 | mov bx,VM1_GSEL | ||
| 217 | mov ds,bx | ||
| 218 | OP32 | ||
| 219 | mov si,di | ||
| 220 | ASSUME ds:nothing | ||
| 221 | |||
| 222 | ; Point ES:EDI to start of our 386 loadall buffer | ||
| 223 | |||
| 224 | mov ax,VDMD_GSEL | ||
| 225 | mov es,ax | ||
| 226 | OP32 | ||
| 227 | xor di,di ; clear EDI | ||
| 228 | mov di,ES:[ELOff] ; ES:EDI pts to our 386 loadall buffer | ||
| 229 | ; | ||
| 230 | cld | ||
| 231 | |||
| 232 | ; Walk through the two buffers in parallel, copying the client's values | ||
| 233 | ; when appropriate | ||
| 234 | |||
| 235 | ; | ||
| 236 | ; CR0 entry | ||
| 237 | ; | ||
| 238 | EA32 | ||
| 239 | OP32 | ||
| 240 | lodsw ; get client's CR0 | ||
| 241 | |||
| 242 | ;(0.02) OP32 | ||
| 243 | ;(0.02) test ax,0001h ; TEST EAX,80000001h | ||
| 244 | ;(0.02) dw 8000h ; Q: PG or PE bit set ? | ||
| 245 | ;(0.02) jz CR0_OK ; N: continue | ||
| 246 | ;(0.02) call Em386_Err ; Y: error | ||
| 247 | ; | ||
| 248 | CR0_OK: | ||
| 249 | MOV_ECX_CR0 | ||
| 250 | OP32 | ||
| 251 | and cx,0011h ; and ECX,80000011h | ||
| 252 | dw 8000h ; save only PG,ET, & PE bits | ||
| 253 | OP32 | ||
| 254 | or ax,cx ; or EAX,ECX | ||
| 255 | OP32 | ||
| 256 | stosw ; store CR0 for 386 buffer | ||
| 257 | XOR_ECX_ECX ; clear ECX | ||
| 258 | ; | ||
| 259 | ; EFLAGS | ||
| 260 | ; | ||
| 261 | EA32 | ||
| 262 | OP32 | ||
| 263 | lodsw ; get EFLAGS | ||
| 264 | ; | ||
| 265 | OP32 | ||
| 266 | test ax,0000h | ||
| 267 | dw 0002h ;Q: client's VM bit set ? | ||
| 268 | jz EF_OK ; N: continue | ||
| 269 | jmp Em386_Err ; Y: error handler - won't return here | ||
| 270 | EF_OK: | ||
| 271 | and ax,0FFFh ; clear IOPL & NT bits | ||
| 272 | OP32 | ||
| 273 | or ax,3000h | ||
| 274 | dw 0002h ; set VM bit and IOPL = 3 | ||
| 275 | OP32 | ||
| 276 | stosw ; store EFLAGS for 386 buffer | ||
| 277 | ; | ||
| 278 | ; Copy the client's EIP, EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX, DR6 & DR7 | ||
| 279 | ; register images from his 386 loadall buffer to our 386 loadall buffer | ||
| 280 | ; | ||
| 281 | mov cx,11 ; copy 11 register contents | ||
| 282 | OP32 ; dwords from DS:[ESI] to ES:[EDI] | ||
| 283 | EA32 | ||
| 284 | rep movsw ; copy 11 dwords | ||
| 285 | |||
| 286 | EA32 | ||
| 287 | nop ; this avoids a B1 errata | ||
| 288 | ; | ||
| 289 | ; store TR and LDTR | ||
| 290 | ; | ||
| 291 | XOR_EAX_EAX ; clear EAX | ||
| 292 | mov ax,TSS_GSEL ; get current TR for VDM's TSS !!! | ||
| 293 | OP32 | ||
| 294 | stosw ; store TR for 386 buffer | ||
| 295 | ; | ||
| 296 | sldt ax ; use current LDT | ||
| 297 | OP32 | ||
| 298 | stosw ; store LDTR for 386 buffer | ||
| 299 | ; | ||
| 300 | ; Copy the client's GS, FS, DS, SS, CS, ES register images from | ||
| 301 | ; his 386 loadall buffer to our 386 loadall buffer | ||
| 302 | ; | ||
| 303 | add si,offset ll3_GS - offset ll3_TSSR | ||
| 304 | mov cx,6 | ||
| 305 | OP32 ; dwords from DS:[ESI] to ES:[EDI] | ||
| 306 | EA32 | ||
| 307 | rep movsw ; copy 6 dwords | ||
| 308 | |||
| 309 | EA32 | ||
| 310 | nop ; this avoids a B1 errata | ||
| 311 | ; | ||
| 312 | ; Copy the current TSS, GDT, IDT, LDT descriptors from the GDT table to | ||
| 313 | ; our 386 loadall buffer | ||
| 314 | ; | ||
| 315 | push ds ; save client's buffer selector | ||
| 316 | mov ax,GDTD_GSEL | ||
| 317 | mov ds,ax | ||
| 318 | |||
| 319 | mov cx, 4 | ||
| 320 | mov bx, TSS_GSEL | ||
| 321 | push word ptr LDTD_GSEL | ||
| 322 | push word ptr GDTD_GSEL | ||
| 323 | push word ptr IDTD_GSEL | ||
| 324 | |||
| 325 | CopyCur: ; Copy current descriptors | ||
| 326 | CurCopy ; DS:[BX] points to current descriptor | ||
| 327 | pop bx | ||
| 328 | loop CopyCur | ||
| 329 | mov ds, bx ; restore client's buffer selector | ||
| 330 | |||
| 331 | ; DS:SI pts to 386 GS cache entry | ||
| 332 | ; | ||
| 333 | ; Copy the client's GS, FS, DS, SS, CS, ES register cache images from | ||
| 334 | ; his 386 loadall buffer to our 386 loadall buffer | ||
| 335 | ; | ||
| 336 | add si,offset ll3_GScache - offset ll3_TSScache | ||
| 337 | mov cx,6 | ||
| 338 | CopyCac: ; ES:DI pts to our 386 buf cache entry | ||
| 339 | Desc3Copy ; store his cache in our 386 buffer | ||
| 340 | loop CopyCac ; DS:SI pts to client's buf cache entry | ||
| 341 | |||
| 342 | ; | ||
| 343 | ; 386 Loadall buffer complete | ||
| 344 | ; | ||
| 345 | |||
| 346 | ;(0.03) push es | ||
| 347 | ;(0.03) mov ax, TSSD_GSEL ; Point ES to TSS for PortTrap | ||
| 348 | ;(0.03) mov es, ax | ||
| 349 | ;(0.03) mov bh, 80h ; set every 1k | ||
| 350 | ;(0.03) mov ax, KbdDataPort | ||
| 351 | ;(0.03) call PortTrap ; set traps on keyboard ports | ||
| 352 | ;(0.03) mov ax, KbdCmdPort ; in case client | ||
| 353 | ;(0.03) call PortTrap ; tries to disable A20 | ||
| 354 | ;(0.03) pop es | ||
| 355 | ;(0.03) mov es:[A20watch], YesLLdone ; set A20 watch flag | ||
| 356 | |||
| 357 | HwTabLock ; Hardware lock the high ram | ||
| 358 | |||
| 359 | OP32 | ||
| 360 | xor di,di ; XOR EDI,EDI - clear EDI | ||
| 361 | mov di,ES:[ELOff] ; ES:EDI pts to loadall buffer | ||
| 362 | dw LODAL386 ; execute 386 LOADALL | ||
| 363 | |||
| 364 | ASSUME DS:DGROUP | ||
| 365 | ; | ||
| 366 | ; | ||
| 367 | EM386ll endp | ||
| 368 | |||
| 369 | page | ||
| 370 | ;****************************************************************************** | ||
| 371 | ; Em386_Err - handle 386 ll emulation error | ||
| 372 | ; This routine is currently called only on attempts to set the | ||
| 373 | ; VM bit via loadall. | ||
| 374 | ;****************************************************************************** | ||
| 375 | Em386_Err proc near | ||
| 376 | push ax | ||
| 377 | push bx | ||
| 378 | mov ax, PrivErr | ||
| 379 | mov bx, Err3LL | ||
| 380 | call ErrHndlr | ||
| 381 | pop bx | ||
| 382 | pop bx | ||
| 383 | ; | ||
| 384 | ; continue client in real mode | ||
| 385 | ; | ||
| 386 | POP_EDI ; restore used regs | ||
| 387 | POP_ECX | ||
| 388 | POP_EAX | ||
| 389 | ; stack back to VmFault exit condition | ||
| 390 | |||
| 391 | jmp JumpReal ; "jump" to real mode and continue interrupted | ||
| 392 | ; code. | ||
| 393 | |||
| 394 | Em386_Err endp | ||
| 395 | ; | ||
| 396 | _TEXT ends | ||
| 397 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/EMM.ASM b/v4.0/src/MEMM/MEMM/EMM.ASM new file mode 100644 index 0000000..557afa4 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMM.ASM | |||
| @@ -0,0 +1,522 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EMM - Expanded Memory Manager interface for MEMM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EMM - Expanded Memory Manager interface | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: June 14, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 06/14/86 original | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; 06/29/86 0.02 Protect port 84/85 from ints | ||
| 29 | ; 07/05/86 0.04 moved EMM_rEntry to R_CODE | ||
| 30 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 31 | ; 07/08/86 0.04 Changed EMM_pEntry to call EMM functions | ||
| 32 | ; directly | ||
| 33 | ; 07/10/86 0.05 jmp $+2 before "POPF" | ||
| 34 | ; 07/10/86 0.05 added EMM_Flag | ||
| 35 | ; 06/09/88 remove _map_known since there is no map now (pc) | ||
| 36 | ; 07/20/88 remove debugger code (pc) | ||
| 37 | ; | ||
| 38 | ;****************************************************************************** | ||
| 39 | ; Functional Description: | ||
| 40 | ; The module contains code for calling the EMM functions and a routine | ||
| 41 | ; for managing the AUTO mode of MEMM. | ||
| 42 | ; There are two EMM entry points in this module; one for real/virtual | ||
| 43 | ; mode entry and one for protected mode (IDT entry points here). When | ||
| 44 | ; MEMM is ON (system in Virtual mode), INT 67H calls transition to protected | ||
| 45 | ; mode and the EMM_pEntry entry point. EMM_pEntry sets up the same stack | ||
| 46 | ; conditions as the generic int67_Entry dispatcher and calls the appropriate | ||
| 47 | ; EMM function. Some EMM functions cannot be executed in protected mode. | ||
| 48 | ; These functions are called by reflecting the INT 67H to the real/virtual | ||
| 49 | ; mode entry point. EMM functions which are executed in PROTECTED mode | ||
| 50 | ; will take less time (they don't suffer the extra time to reflect the | ||
| 51 | ; INT 67H). | ||
| 52 | ; | ||
| 53 | ;****************************************************************************** | ||
| 54 | .lfcond | ||
| 55 | .386p | ||
| 56 | page | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; P U B L I C D E C L A R A T I O N S | ||
| 59 | ;****************************************************************************** | ||
| 60 | ; | ||
| 61 | public EMM_pEntry ; protected mode entry point | ||
| 62 | public EMM_rEntry ; real mode entry point | ||
| 63 | public EMM_rEfix ; label for far jump to int67_entry | ||
| 64 | public _AutoUpdate ; update auto mode of VDM/EMM | ||
| 65 | public EMM_Flag ; flag for EMM calls | ||
| 66 | |||
| 67 | page | ||
| 68 | ;****************************************************************************** | ||
| 69 | ; L O C A L C O N S T A N T S | ||
| 70 | ;****************************************************************************** | ||
| 71 | ; | ||
| 72 | include vdmseg.inc | ||
| 73 | include vdmsel.inc | ||
| 74 | include vm386.inc | ||
| 75 | ; include instr386.inc | ||
| 76 | include oemdep.inc | ||
| 77 | include emmdef.inc | ||
| 78 | |||
| 79 | FALSE equ 0 | ||
| 80 | TRUE equ not FALSE | ||
| 81 | |||
| 82 | ; | ||
| 83 | ; these EMM functions are handled in protected mode | ||
| 84 | ; | ||
| 85 | EMM_MAP_PAGE equ 44h ; map handle page | ||
| 86 | EMM_RESTORE equ 48h ; restore page map | ||
| 87 | EMM_GET_SET equ 4Eh ; get/set page map | ||
| 88 | EMM_GET_SET_PARTIAL equ 4Fh ; get/set partial page map | ||
| 89 | EMM_MAP_PAGE_ARRAY equ 50h ; map handle page array | ||
| 90 | EMM_ALTER_MAP_JUMP equ 55h ; alter mapping and jump | ||
| 91 | EMM_ALTER_MAP_CALL equ 56h ; alter mapping and call | ||
| 92 | EMM_MOVE_XCHG_MEM equ 57h ; move/xchg memory region | ||
| 93 | EMM_ALTER_MAP_REG_SET equ 5Bh ; alternate map register set | ||
| 94 | |||
| 95 | EMM_HW_MALFUNCTION equ 81h ; | ||
| 96 | |||
| 97 | ;****************************************************************************** | ||
| 98 | ; E X T E R N A L R E F E R E N C E S | ||
| 99 | ;****************************************************************************** | ||
| 100 | ; | ||
| 101 | ABS0 segment use16 at 0000h | ||
| 102 | |||
| 103 | org 67h * 4 ; EMM function interrupt | ||
| 104 | EMMVec dw ? ; offset of vector | ||
| 105 | dw ? ; segment of vector | ||
| 106 | |||
| 107 | ABS0 ends | ||
| 108 | |||
| 109 | _DATA segment | ||
| 110 | |||
| 111 | extrn _EMMstatus:word | ||
| 112 | extrn Active_Status:byte ; current VDM status | ||
| 113 | extrn Auto_Mode:byte ; current Auto mode status | ||
| 114 | ;extrn _map_known:byte ; non-zero => I/O map known to a user | ||
| 115 | extrn _handle_count:word ; number of active EMM handles | ||
| 116 | extrn _regp:word ; pointer to args on stack | ||
| 117 | |||
| 118 | _DATA ends | ||
| 119 | |||
| 120 | _TEXT segment | ||
| 121 | |||
| 122 | extrn int67_Entry:far ; it's far because we need CS on stack too | ||
| 123 | extrn GoVirtual:near | ||
| 124 | extrn ErrHndlr:near | ||
| 125 | extrn hw_int:near | ||
| 126 | extrn RRProc:near | ||
| 127 | |||
| 128 | extrn _GetStatus:near | ||
| 129 | extrn _GetPageFrameAddress:near | ||
| 130 | extrn _GetUnallocatedPageCount:near | ||
| 131 | extrn _AllocatePages:near | ||
| 132 | extrn _MapHandlePage:near | ||
| 133 | extrn _DeallocatePages:near | ||
| 134 | extrn _GetEMMVersion:near | ||
| 135 | extrn _SavePageMap:near | ||
| 136 | extrn _RestorePageMap:near | ||
| 137 | extrn _GetPageMappingRegisterIOArray:near | ||
| 138 | extrn _GetLogicalToPhysicalPageTrans:near | ||
| 139 | extrn _GetEMMHandleCount:near | ||
| 140 | extrn _GetEMMHandlePages:near | ||
| 141 | extrn _GetAllEMMHandlePages:near | ||
| 142 | extrn _GetSetPageMap:near | ||
| 143 | |||
| 144 | extrn _GetSetPartial:near | ||
| 145 | extrn _MapHandleArray:near | ||
| 146 | extrn _AlterMapAndJump:near | ||
| 147 | extrn _AlterMapAndCall:near | ||
| 148 | extrn _MoveExchangeMemory:near | ||
| 149 | extrn _AlternateMapRegisterSet:near | ||
| 150 | |||
| 151 | _TEXT ends | ||
| 152 | |||
| 153 | page | ||
| 154 | ;****************************************************************************** | ||
| 155 | ; S E G M E N T D E F I N I T I O N | ||
| 156 | ;****************************************************************************** | ||
| 157 | ; | ||
| 158 | _DATA segment | ||
| 159 | EMM_Flag db 0 ; non-zero => EMM function called by our code | ||
| 160 | _DATA ends | ||
| 161 | |||
| 162 | page | ||
| 163 | ;****************************************************************************** | ||
| 164 | ; | ||
| 165 | ; _TEXT Code Segment | ||
| 166 | ; | ||
| 167 | ;****************************************************************************** | ||
| 168 | ; | ||
| 169 | _TEXT segment | ||
| 170 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 171 | ;****************************************************************************** | ||
| 172 | ; protected mode dispatch table | ||
| 173 | ; allocate(43h)/deallocate(45h) pages and get I/O map (49h) | ||
| 174 | ; MUST be reflected to Virtual mode | ||
| 175 | ; MapHandlePage,RestorePageMap,GetSetPageMap,GetSetPartial, | ||
| 176 | ; MapHandleArray,MoveExchangeMemory,AlterMapAndJump, | ||
| 177 | ; AlterMapAndCall and AlternateMapRegisterSet are protected mode ONLY. | ||
| 178 | ;****************************************************************************** | ||
| 179 | EpE_Dispatch label word | ||
| 180 | dw offset _TEXT:EpE_Null | ||
| 181 | dw offset _TEXT:EpE_Null | ||
| 182 | dw offset _TEXT:EpE_Null | ||
| 183 | dw offset _TEXT:EpE_Null | ||
| 184 | dw offset _TEXT:_MapHandlePage ;44h | ||
| 185 | dw offset _TEXT:EpE_Null | ||
| 186 | dw offset _TEXT:EpE_Null | ||
| 187 | dw offset _TEXT:EpE_Null | ||
| 188 | dw offset _TEXT:_RestorePageMap ;48h | ||
| 189 | dw offset _TEXT:EpE_Null | ||
| 190 | dw offset _TEXT:EpE_Null | ||
| 191 | dw offset _TEXT:EpE_Null | ||
| 192 | dw offset _TEXT:EpE_Null | ||
| 193 | dw offset _TEXT:EpE_Null | ||
| 194 | dw offset _TEXT:_GetSetPageMap ;4eh | ||
| 195 | dw offset _TEXT:_GetSetPartial ;4fh | ||
| 196 | dw offset _TEXT:_MapHandleArray ;50h | ||
| 197 | dw offset _TEXT:EpE_Null | ||
| 198 | dw offset _TEXT:EpE_Null | ||
| 199 | dw offset _TEXT:EpE_Null | ||
| 200 | dw offset _TEXT:EpE_Null | ||
| 201 | dw offset _TEXT:_AlterMapAndJump ;55h | ||
| 202 | dw offset _TEXT:_AlterMapAndCall ;56h | ||
| 203 | dw offset _TEXT:_MoveExchangeMemory ;57h | ||
| 204 | dw offset _TEXT:EpE_Null | ||
| 205 | dw offset _TEXT:EpE_Null | ||
| 206 | dw offset _TEXT:EpE_Null | ||
| 207 | dw offset _TEXT:_AlternateMapRegisterSet ;5bh | ||
| 208 | dw offset _TEXT:EpE_Null | ||
| 209 | dw offset _TEXT:EpE_Null | ||
| 210 | |||
| 211 | page | ||
| 212 | ;****************************************************************************** | ||
| 213 | ; EMM_pEntry - protected mode entry point for EMM function calls | ||
| 214 | ; | ||
| 215 | ; ENTRY: Protected mode | ||
| 216 | ; DGROUP:[EMM_Flag] = zero => reflect this int | ||
| 217 | ; SS:[SP] pointing to virtual mode INT stack frame | ||
| 218 | ; | ||
| 219 | ; EXIT: Protected mode | ||
| 220 | ; if this EMM function is to be handled in protected mode, | ||
| 221 | ; registers as set by EMM functions | ||
| 222 | ; else | ||
| 223 | ; reflect int 67 to virtual mode EMM code | ||
| 224 | ; | ||
| 225 | ; NOTE: ***** | ||
| 226 | ; Allocate(43h)/deallocate(44h) pages and get I/O map (49h) | ||
| 227 | ; MUST be reflected to Virtual mode. | ||
| 228 | ; | ||
| 229 | ; USED: none | ||
| 230 | ; | ||
| 231 | ;****************************************************************************** | ||
| 232 | ; | ||
| 233 | ; reflect EMM function to real mode | ||
| 234 | ; | ||
| 235 | EpE_reflect: | ||
| 236 | push 67h ; refect | ||
| 237 | jmp hw_int ; it... | ||
| 238 | ; | ||
| 239 | ; | ||
| 240 | ; client not in Virtual mode | ||
| 241 | ; | ||
| 242 | EpE_not_VM: | ||
| 243 | pop ebp ; N: call error handler | ||
| 244 | |||
| 245 | mov ax,ExcpErr ; exception error | ||
| 246 | mov bx,ErrINTProt ; invalid software interrupt | ||
| 247 | call ErrHndlr | ||
| 248 | ; | ||
| 249 | ; function entry | ||
| 250 | ; | ||
| 251 | EMM_pEntry proc near | ||
| 252 | ; | ||
| 253 | push ebp | ||
| 254 | mov bp,sp | ||
| 255 | test [bp.VTFO+VMTF_EFLAGShi],2 ;Q:client in Virtual mode ? | ||
| 256 | jz EpE_not_VM ; N: handle it | ||
| 257 | ; Y: check flag | ||
| 258 | push VDMD_GSEL | ||
| 259 | pop ds ; DS = DGROUP | ||
| 260 | push VDMD_GSEL | ||
| 261 | pop es ; ES = DGROUP | ||
| 262 | cmp [EMM_Flag],0 ;Q: did we do this int67 ? | ||
| 263 | je EpE_Reflect ; N: reflect it | ||
| 264 | mov [EMM_Flag],0 ; Y: clear EMM_Flag for next | ||
| 265 | ; time and handle function | ||
| 266 | ; in protected mode. | ||
| 267 | ; | ||
| 268 | ; dispatch EMM function OR reflect to real/vm dispatcher | ||
| 269 | ; | ||
| 270 | EpE_chk_func: | ||
| 271 | HwTabUnlock ; unlock ROM | ||
| 272 | |||
| 273 | push [bp.VTFO+VMTF_FS] ; client FS | ||
| 274 | push [bp.VTFO+VMTF_GS] ; client GS | ||
| 275 | push [bp.VTFO+VMTF_ES] ; client ES | ||
| 276 | push [bp.VTFO+VMTF_DS] ; client DS | ||
| 277 | push [bp.VTFO+VMTF_EFLAGS] ; client Flag | ||
| 278 | push [bp.VTFO+VMTF_CS] ; client CS | ||
| 279 | push word ptr [bp.VTFO+VMTF_EIP] ; client IP (low word of EIP) | ||
| 280 | ; stack has - IP,CS,PFlag,DS,ES,GS,FS | ||
| 281 | pushad ; all regs saved | ||
| 282 | mov bp,sp ; SS:BP -> to stack args (see r67_Frame struc) | ||
| 283 | mov [_regp],sp ; regp points to regs on stack | ||
| 284 | mov [_regp+2],ss ; regp now has a far ptr to regs | ||
| 285 | |||
| 286 | push ax | ||
| 287 | mov ax, PFLAG_VIRTUAL ; Faked VM bit | ||
| 288 | or [bp.PFlag], ax ; Incorpated in PFlag | ||
| 289 | pop ax | ||
| 290 | ; | ||
| 291 | ; validate function code | ||
| 292 | ; | ||
| 293 | sub ah,40h ; check if entry code too small | ||
| 294 | jb EpE_inv_exit ; if so, error exit | ||
| 295 | cmp ah,(5Dh-40h) ; check if entry code too big | ||
| 296 | ja EpE_inv_exit ; if so, error exit | ||
| 297 | ; else, AH = 0 base function # | ||
| 298 | ; | ||
| 299 | ; call through the jump table | ||
| 300 | ; | ||
| 301 | EpE_jump: | ||
| 302 | xchg ah,al ; AL = function code | ||
| 303 | mov si,ax | ||
| 304 | xchg ah,al ; AH = function code again | ||
| 305 | and si,00FFh ; SI = function # | ||
| 306 | shl si,1 ; SI = table offset | ||
| 307 | call CS:EpE_Dispatch[si] ; call function | ||
| 308 | |||
| 309 | ; | ||
| 310 | ; check to see if we need to patch CS:IP on the iretd stack frame | ||
| 311 | ; | ||
| 312 | EpE_Exit: | ||
| 313 | test word ptr [bp.PFlag], PFLAG_PATCH_CS_IP | ||
| 314 | jz EpE_No_Patch | ||
| 315 | |||
| 316 | mov bp, sp ; use bp to address stack | ||
| 317 | ; | ||
| 318 | ; patch iretd's CS:EIP to new CS:IP on stack | ||
| 319 | ; | ||
| 320 | mov ax, [bp.retaddr] ; get return IP | ||
| 321 | mov [bp.rFS+6], ax ; iretd's IP (6 bytes beyond FS) | ||
| 322 | xor ax, ax | ||
| 323 | mov [bp.rFS+8], ax ; zero high word of EIP | ||
| 324 | mov ax, [bp.rCS] ; get return CS | ||
| 325 | mov [bp.rFS+10], ax ; iretd's CS | ||
| 326 | |||
| 327 | EpE_No_Patch: | ||
| 328 | popad ; restore regs | ||
| 329 | add sp, 6 ; throw away return addr cs and ip and flags | ||
| 330 | pop [bp.VTFO+VMTF_DS] ; client DS | ||
| 331 | pop [bp.VTFO+VMTF_ES] ; client ES | ||
| 332 | pop [bp.VTFO+VMTF_GS] ; client GS | ||
| 333 | pop [bp.VTFO+VMTF_FS] ; client FS | ||
| 334 | |||
| 335 | |||
| 336 | pop ebp ; restore bp | ||
| 337 | |||
| 338 | HwTabLock ; lock ROM | ||
| 339 | |||
| 340 | iretd ; return to virtual mode caller | ||
| 341 | ; | ||
| 342 | ; Null function - do nothing (should not get to here) | ||
| 343 | EpE_Null: | ||
| 344 | ret ; return after doing nothing | ||
| 345 | ; | ||
| 346 | ; EMM error handling | ||
| 347 | ; | ||
| 348 | EpE_inv_exit: ; set invalid function code error | ||
| 349 | mov byte ptr [bp.rAX+1],INVALID_FUNCTION | ||
| 350 | jmp EpE_Exit | ||
| 351 | |||
| 352 | EMM_pEntry endp | ||
| 353 | |||
| 354 | page | ||
| 355 | ;****************************************************************************** | ||
| 356 | ; EMM_rLink - real/virtual mode link for EMM function calls from | ||
| 357 | ; R_CODE segment. | ||
| 358 | ; | ||
| 359 | ; ENTRY: real/virtual mode | ||
| 360 | ; all registers as set by user | ||
| 361 | ; | ||
| 362 | ; EXIT: real/virtual mode | ||
| 363 | ; registers as set by EMM functions | ||
| 364 | ; | ||
| 365 | ; USED: none | ||
| 366 | ; | ||
| 367 | ;****************************************************************************** | ||
| 368 | EMM_rLINK proc far | ||
| 369 | |||
| 370 | ; | ||
| 371 | ; check for protected mode ONLY function | ||
| 372 | ; | ||
| 373 | cmp ah,EMM_MAP_PAGE ;Q: map handle page function ? | ||
| 374 | je ErE_GoProt ; Y: do it in protected mode | ||
| 375 | cmp ah,EMM_RESTORE ;Q: restore page map function ? | ||
| 376 | je ErE_GoProt ; Y: do it in protected mode | ||
| 377 | cmp ah,EMM_GET_SET ;Q: get/set page map function ? | ||
| 378 | je ErE_GoProt ; Y: do it in protected mode | ||
| 379 | cmp ah,EMM_GET_SET_PARTIAL ;Q: get/set partial function ? | ||
| 380 | je ErE_GoProt ; Y: do it in protected mode | ||
| 381 | cmp ah,EMM_MAP_PAGE_ARRAY ;Q: map handle page array ? | ||
| 382 | je ErE_GoProt ; Y: do it in protected mode | ||
| 383 | cmp ah,EMM_ALTER_MAP_JUMP ;Q: alter map and jump ? | ||
| 384 | je ErE_GoProt ; Y: do it in protected mode | ||
| 385 | cmp ah,EMM_ALTER_MAP_CALL ;Q: alter map and call ? | ||
| 386 | je ErE_GoProt ; Y: do it in protected mode | ||
| 387 | cmp ah,EMM_MOVE_XCHG_MEM ;Q: move/xchg memory region ? | ||
| 388 | je ErE_GoProt ; Y: do it in protected mode | ||
| 389 | cmp ah,EMM_ALTER_MAP_REG_SET;Q: alternate map register set ? | ||
| 390 | je ErE_GoProt ; Y: do it in protected mode | ||
| 391 | ; N: do it in real/virtual mode | ||
| 392 | ; | ||
| 393 | ; here for real/virtual mode functions | ||
| 394 | ; | ||
| 395 | push fs | ||
| 396 | push gs | ||
| 397 | push es | ||
| 398 | push ds | ||
| 399 | push 00 ; PFlag => real mode call to EMM functions | ||
| 400 | push seg DGROUP | ||
| 401 | pop ds ; set DS = DGROUP | ||
| 402 | call int67_Entry ; call dispatcher | ||
| 403 | add sp,2 ; drop PFlag arg | ||
| 404 | pop ds ; restore seg regs | ||
| 405 | pop es | ||
| 406 | pop gs | ||
| 407 | pop fs | ||
| 408 | ret ; and return | ||
| 409 | |||
| 410 | ; | ||
| 411 | ; Here if protected mode function called via real IDT | ||
| 412 | ; - set EMM flag and go for it... | ||
| 413 | ; | ||
| 414 | ErE_GoProt: | ||
| 415 | push ds | ||
| 416 | push seg DGROUP | ||
| 417 | pop ds ; DS = DGROUP | ||
| 418 | cmp [Active_Status],0 ;Q: are we in Virtual Mode ? | ||
| 419 | jne ErE_Pcall ; Y: call protected mode function | ||
| 420 | ; mov [_map_known],TRUE ; N: set global auto mode flag | ||
| 421 | call _AutoUpdate ; go into virtual mode | ||
| 422 | ; and call function | ||
| 423 | ErE_Pcall: | ||
| 424 | mov [EMM_Flag],TRUE ; set flag | ||
| 425 | pop ds ; restore DS | ||
| 426 | int 67h ; go for it ... | ||
| 427 | ret ; then return | ||
| 428 | |||
| 429 | EMM_rLINK endp | ||
| 430 | |||
| 431 | page | ||
| 432 | ;****************************************************************************** | ||
| 433 | ; _AutoUpdate - updates the EMM status when in AutoMode | ||
| 434 | ; | ||
| 435 | ; ENTRY: REAL or VIRTUAL mode ONLY | ||
| 436 | ; DS = DGROUP segment | ||
| 437 | ; DS:[Auto_Mode] = non-zero => system currently in auto mode | ||
| 438 | ; DS:[Active_Status] = non-zero => system currently ON | ||
| 439 | ; DS:[_map_known] = non-zero => I/O map has been given to a user | ||
| 440 | ; | ||
| 441 | ; EXIT: exits in real or virtual depending on the state variables | ||
| 442 | ; DS:[Active_Status] = current ON/OFF status | ||
| 443 | ; | ||
| 444 | ; USED: none | ||
| 445 | ; | ||
| 446 | ;****************************************************************************** | ||
| 447 | _AutoUpdate proc near | ||
| 448 | ; | ||
| 449 | cmp [Auto_Mode],0 ;Q: in Auto mode now ? | ||
| 450 | je AU_exit ; N: exit | ||
| 451 | cmp [Active_Status],0 ; Y:Q: ON now ? | ||
| 452 | je AU_chkoff ; N: check OFF state status | ||
| 453 | ; | ||
| 454 | ; here if we are currently ON | ||
| 455 | ; | ||
| 456 | ; cmp [_map_known],0 ; Y:Q: map known ? | ||
| 457 | ; jne AU_exit ; Y: then stay ON... | ||
| 458 | cmp [_handle_count],0 ; N:Q: any active handles ? | ||
| 459 | jne AU_exit ; Y: then stay ON... | ||
| 460 | mov [Active_Status],0 ; N: go to OFF state | ||
| 461 | push ax | ||
| 462 | call RRProc ; Force processor into real mode | ||
| 463 | pop ax | ||
| 464 | jmp AU_exit ; and leave in real mode | ||
| 465 | ; | ||
| 466 | ; here if we are currently OFF | ||
| 467 | ; | ||
| 468 | AU_chkoff: | ||
| 469 | cmp [_handle_count],0 ;Q: any active handles ? | ||
| 470 | je AU_exit ; N: stay off | ||
| 471 | |||
| 472 | ; cmp [_map_known],0 ;; Q: is the map known ? | ||
| 473 | ; je AU_exit ;; N: then stay OFF... | ||
| 474 | |||
| 475 | AU_ON: ; Y: turn ON EMM | ||
| 476 | mov [Active_Status],1 ; go to ON state, | ||
| 477 | call GoVirtual ; and go to virtual mode (ON) | ||
| 478 | AU_exit: | ||
| 479 | ret | ||
| 480 | ; | ||
| 481 | _AutoUpdate endp | ||
| 482 | |||
| 483 | _TEXT ends | ||
| 484 | |||
| 485 | page | ||
| 486 | ;****************************************************************************** | ||
| 487 | ; | ||
| 488 | ; R_CODE Code Segment | ||
| 489 | ; | ||
| 490 | ;****************************************************************************** | ||
| 491 | ; | ||
| 492 | R_CODE segment | ||
| 493 | assume cs:R_CODE, ds:DGROUP, es:DGROUP | ||
| 494 | |||
| 495 | page | ||
| 496 | ;****************************************************************************** | ||
| 497 | ; EMM_rEntry - real/virtual mode entry point for EMM function calls | ||
| 498 | ; | ||
| 499 | ; ENTRY: real/virtual mode | ||
| 500 | ; all registers as set by user | ||
| 501 | ; | ||
| 502 | ; EXIT: real/virtual mode | ||
| 503 | ; registers as set by EMM functions | ||
| 504 | ; | ||
| 505 | ; USED: none | ||
| 506 | ; | ||
| 507 | ;****************************************************************************** | ||
| 508 | EMM_rEntry proc near | ||
| 509 | ; | ||
| 510 | cli ; just in case pushf/call far | ||
| 511 | |||
| 512 | EMM_rEfix: | ||
| 513 | call EMM_rLink ; call _TEXT segment link | ||
| 514 | iret ; return to caller | ||
| 515 | ; | ||
| 516 | EMM_rEntry endp | ||
| 517 | |||
| 518 | |||
| 519 | R_CODE ends | ||
| 520 | |||
| 521 | end | ||
| 522 | |||
diff --git a/v4.0/src/MEMM/MEMM/EMM386.INC b/v4.0/src/MEMM/MEMM/EMM386.INC new file mode 100644 index 0000000..2b1143c --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMM386.INC | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: EMM386.INC - general includes for MEMM | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: May 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change Log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION Description | ||
| 22 | ; -------- -------- -------------------------------------------- | ||
| 23 | ; 04/25/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | |||
| 31 | ; | ||
| 32 | ; Message Flag Equates | ||
| 33 | ; | ||
| 34 | INC_PRC_MSG equ 00000001b ; Incorrect processor type message | ||
| 35 | INC_DOS_MSG equ 00000010b ; Incorrect DOS message | ||
| 36 | MEM_ERR_MSG equ 00000100b ; Memory error message | ||
| 37 | INS_ERR_MSG equ 00001000b ; Already Installed message | ||
| 38 | NO_PF_MSG equ 00010000b ; Nowhere to put PF message | ||
| 39 | SIZE_ADJ_MSG equ 00100000b ; EMM Pool size adjusted message | ||
| 40 | BASE_ADJ_MSG equ 01000000b ; Page Frame Base adjusted msg | ||
| 41 | MAPA_ADJ_MSG equ 10000000b ; Map register address adjusted msg | ||
| 42 | INV_PARM_MSG equ 100000000b ; Invalid parameter message | ||
| 43 | PF_WARN_MSG equ 1000000000b ; PF located over ROM warning message | ||
| 44 | ; | ||
| 45 | ; These messages cause MEMM to not install | ||
| 46 | ; | ||
| 47 | KILLER_MSG = INC_PRC_MSG+INC_DOS_MSG+MEM_ERR_MSG+INS_ERR_MSG+NO_PF_MSG | ||
| 48 | ; | ||
| 49 | .list ; end of EMM386.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/EMM386.LNK b/v4.0/src/MEMM/MEMM/EMM386.LNK new file mode 100644 index 0000000..f48b430 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMM386.LNK | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | memm386+ | ||
| 2 | elimfunc+ | ||
| 3 | emm+ | ||
| 4 | emmmes+ | ||
| 5 | emminit+ | ||
| 6 | memmonf+ | ||
| 7 | init+ | ||
| 8 | m_state+ | ||
| 9 | rom_srch+ | ||
| 10 | ppage+ | ||
| 11 | allocmem+ | ||
| 12 | inittab+ | ||
| 13 | shiphi+ | ||
| 14 | extpool+ | ||
| 15 | vdminit+ | ||
| 16 | i286+ | ||
| 17 | i386+ | ||
| 18 | tabdef+ | ||
| 19 | trapdef+ | ||
| 20 | vmtrap+ | ||
| 21 | vminst+ | ||
| 22 | elimtrap+ | ||
| 23 | iotrap+ | ||
| 24 | a20trap+ | ||
| 25 | oemproc+ | ||
| 26 | initepg+ | ||
| 27 | vminit+ | ||
| 28 | em286ll+ | ||
| 29 | em386ll+ | ||
| 30 | moveb+ | ||
| 31 | maplin+ | ||
| 32 | retreal+ | ||
| 33 | rrtrap+ | ||
| 34 | errhndlr+ | ||
| 35 | ekbd+ | ||
| 36 | util+ | ||
| 37 | initdeb+ | ||
| 38 | mapdma | ||
| 39 | emm386.exe | ||
| 40 | emm386.map/m | ||
| 41 | ..\emm\emmlib.lib | ||
diff --git a/v4.0/src/MEMM/MEMM/EMM386D.LNK b/v4.0/src/MEMM/MEMM/EMM386D.LNK new file mode 100644 index 0000000..fd07081 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMM386D.LNK | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | memm386+ | ||
| 2 | elimfunc+ | ||
| 3 | emmD+ | ||
| 4 | emmmes+ | ||
| 5 | emminit+ | ||
| 6 | memmonf+ | ||
| 7 | init+ | ||
| 8 | rom_srch+ | ||
| 9 | ppage+ | ||
| 10 | allocmem+ | ||
| 11 | inittab+ | ||
| 12 | vdminitD+ | ||
| 13 | i286+ | ||
| 14 | i386+ | ||
| 15 | tabdefD+ | ||
| 16 | trapdef+ | ||
| 17 | kbd+ | ||
| 18 | print+ | ||
| 19 | vmtrapD+ | ||
| 20 | vminstD+ | ||
| 21 | elimtrap+ | ||
| 22 | iotrap+ | ||
| 23 | a20trap+ | ||
| 24 | oemproc+ | ||
| 25 | initepg+ | ||
| 26 | vminit+ | ||
| 27 | em286ll+ | ||
| 28 | em386ll+ | ||
| 29 | moveb+ | ||
| 30 | maplin+ | ||
| 31 | retreal+ | ||
| 32 | rrtrap+ | ||
| 33 | errhndlr+ | ||
| 34 | ekbd+ | ||
| 35 | util+ | ||
| 36 | initdebD+ | ||
| 37 | mapdma | ||
| 38 | emm386d.exe | ||
| 39 | emm386d.map/m | ||
| 40 | ..\deb386\buglib.lib ..\emm\emmlib.lib | ||
| 41 | |||
diff --git a/v4.0/src/MEMM/MEMM/EMMCOM.LNK b/v4.0/src/MEMM/MEMM/EMMCOM.LNK new file mode 100644 index 0000000..a1b6a4d --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMMCOM.LNK | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | memmcom+ | ||
| 2 | memmonf | ||
| 3 | emmcom.exe | ||
| 4 | emmcom.map/m; | ||
| 5 | |||
diff --git a/v4.0/src/MEMM/MEMM/EMMINIT.ASM b/v4.0/src/MEMM/MEMM/EMMINIT.ASM new file mode 100644 index 0000000..65527b9 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMMINIT.ASM | |||
| @@ -0,0 +1,678 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EMMINIT - Expanded Memory Manager initialization | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EMMINIT - Expanded Memory Manager initialization routine | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: May 24 ,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 04/16/86 Original Adapted from DOS clock driver. | ||
| 27 | ; 05/24/86 0.00 From EMML test driver. | ||
| 28 | ; 06/21/86 0.02 added cld to EMM_Init | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 06/29/86 0.02 INC AX (was INC AL) for emm_free init | ||
| 31 | ; 07/06/86 0.04 Size _emm_page,_emm_free, & _pft386 based | ||
| 32 | ; on # of pages in system | ||
| 33 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 34 | ; 07/10/86 0.05 moved int 67h patch to INIT | ||
| 35 | ; 06/07/88 added FRS_array initialization (Paul Chan) | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | ; Functional Description: | ||
| 39 | ; This module initializes the data structures for the EMM | ||
| 40 | ; and sets the current emm data break address (_emm_brk). | ||
| 41 | ; | ||
| 42 | ;****************************************************************************** | ||
| 43 | .lfcond | ||
| 44 | .386p | ||
| 45 | page | ||
| 46 | ;****************************************************************************** | ||
| 47 | ; P U B L I C D E C L A R A T I O N S | ||
| 48 | ;****************************************************************************** | ||
| 49 | ; | ||
| 50 | public EMM_Init | ||
| 51 | page | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; L O C A L C O N S T A N T S | ||
| 54 | ;****************************************************************************** | ||
| 55 | ; | ||
| 56 | include vdmseg.inc | ||
| 57 | include emmdef.inc | ||
| 58 | |||
| 59 | FALSE equ 0 | ||
| 60 | TRUE equ not FALSE | ||
| 61 | |||
| 62 | EMM_HW_ERROR equ 81h ; EMM h/w error status | ||
| 63 | |||
| 64 | ;****************************************************************************** | ||
| 65 | ; E X T E R N A L R E F E R E N C E S | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; | ||
| 68 | _DATA segment | ||
| 69 | |||
| 70 | extrn pool_size:word ; size of EMM Pages Pool in kbytes | ||
| 71 | extrn xbase_addr_h:byte ; bit 16-24 of address of first byte of emm memory | ||
| 72 | extrn xbase_addr_l:word ; bit 0-15 of address of first byte of emm memory | ||
| 73 | extrn sys_size:word ; number of 16k pages taken away from conv. mem | ||
| 74 | extrn PageT_Seg:word ; segment of system page table | ||
| 75 | |||
| 76 | extrn _PF_Base:word ; segment addr of page frame base | ||
| 77 | extrn _page_frame_pages:word ; number of pages in 3.2 page frame | ||
| 78 | |||
| 79 | extrn _EMMstatus:word ; status of EMM | ||
| 80 | |||
| 81 | extrn _page_frame_base:word ; pointers into page tables for each window | ||
| 82 | extrn _mappable_pages:word ; mappable page array | ||
| 83 | extrn _EMM_MPindex:byte ; index into mappable page array | ||
| 84 | extrn _physical_page_count:word ; number of physical pages | ||
| 85 | extrn _mappable_page_count:word ; number of mappable pages | ||
| 86 | |||
| 87 | extrn _cntxt_pages:word ; pages in a context | ||
| 88 | extrn _cntxt_bytes:word ; bytes in a context | ||
| 89 | |||
| 90 | extrn _emm_page:word ; ptr to array of EMM pages | ||
| 91 | extrn _free_count:word ; # of free EMM pages | ||
| 92 | extrn _emmpt_start:word ; start of empty part of emm page | ||
| 93 | extrn _emm_free:word ; ptr to array of free EMM pages | ||
| 94 | extrn _free_top:word ; top of _emm_free | ||
| 95 | |||
| 96 | extrn _total_pages:word ; total # of EMM pages available | ||
| 97 | extrn _pft386:word ; ptr to array of page table entries | ||
| 98 | |||
| 99 | extrn _emm_brk:word ; offset for emm data break address | ||
| 100 | |||
| 101 | extrn FRS_array:word ; | ||
| 102 | extrn CurRegSetn:byte | ||
| 103 | extrn CurRegSet:word | ||
| 104 | extrn FRS_free:byte | ||
| 105 | |||
| 106 | extrn _handle_table:word | ||
| 107 | extrn _handle_count:word | ||
| 108 | |||
| 109 | _DATA ends | ||
| 110 | |||
| 111 | ifndef NOHIMEM | ||
| 112 | else | ||
| 113 | VDATA segment | ||
| 114 | extrn vdata_begin:byte | ||
| 115 | VDATA ends | ||
| 116 | endif | ||
| 117 | |||
| 118 | LAST segment | ||
| 119 | extrn mappable_segs:byte | ||
| 120 | LAST ends | ||
| 121 | |||
| 122 | _TEXT segment | ||
| 123 | extrn InitELIM:far | ||
| 124 | _TEXT ends | ||
| 125 | |||
| 126 | LAST segment | ||
| 127 | extrn InitEPage:near | ||
| 128 | LAST ends | ||
| 129 | |||
| 130 | |||
| 131 | page | ||
| 132 | ;****************************************************************************** | ||
| 133 | ; S E G M E N T D E F I N I T I O N | ||
| 134 | ;****************************************************************************** | ||
| 135 | ; | ||
| 136 | ;****************************************************************************** | ||
| 137 | ; | ||
| 138 | ; Code Segment | ||
| 139 | ; | ||
| 140 | ;****************************************************************************** | ||
| 141 | ;****************************************************************************** | ||
| 142 | ; MACROS used in the EMM initialisation code | ||
| 143 | ;****************************************************************************** | ||
| 144 | ;****************************************************************************** | ||
| 145 | ; | ||
| 146 | ; Get_FRS_window - get pointer to Fast Register Set window | ||
| 147 | ; | ||
| 148 | ; ENTRY: Reg - points to an FRS_struc | ||
| 149 | ; | ||
| 150 | ; EXIT: Reg - points to FRS_window entry in the structure | ||
| 151 | ; | ||
| 152 | ; USES: Reg | ||
| 153 | ; | ||
| 154 | ;****************************************************************************** | ||
| 155 | Get_FRS_window MACRO Reg | ||
| 156 | |||
| 157 | mov Reg, word ptr [CurRegSet] ; just offset (assume dgroup) | ||
| 158 | add Reg, FRS_window ; points to FRS window entries | ||
| 159 | ENDM | ||
| 160 | |||
| 161 | ;****************************************************************************** | ||
| 162 | ;**init_PAGE_FRAME_BASE: macro to fill in the page_frame_base array. this | ||
| 163 | ; array contains the selector:offset into page table. The selector is already | ||
| 164 | ; initialised. So the offset of each of the physical pages into the page | ||
| 165 | ; table needs to be filled in. | ||
| 166 | ; | ||
| 167 | ; ENTRY: SI = INDEX INTO _page_frame_base, also physical page # | ||
| 168 | ; BX = Segment of physical page | ||
| 169 | ; | ||
| 170 | ;****************************************************************************** | ||
| 171 | init_page_frame_base MACRO | ||
| 172 | ; | ||
| 173 | push si | ||
| 174 | push bx | ||
| 175 | ; | ||
| 176 | shl si,2 ; convert index into offset in dword array | ||
| 177 | ; | ||
| 178 | shr bx,6 ; convert segment into page table offset | ||
| 179 | ; since there is 1 dword entry for each 4k | ||
| 180 | ; | ||
| 181 | mov _page_frame_base[si],bx ; fill this in | ||
| 182 | ; | ||
| 183 | pop bx | ||
| 184 | pop si | ||
| 185 | ; | ||
| 186 | ENDM | ||
| 187 | |||
| 188 | ;****************************************************************************** | ||
| 189 | ;**init_MAPPABLE_PAGES: macro to fill the _mappable_pages array. this array | ||
| 190 | ; contains the segment and physical page number of all the mappable physical | ||
| 191 | ; pages. | ||
| 192 | ; | ||
| 193 | ; ENTRY: SI = INDEX INTO _page_frame_base, also physical page # | ||
| 194 | ; BX = Segment of physical page | ||
| 195 | ; DI = Index into _mappable_pages | ||
| 196 | ; | ||
| 197 | ;****************************************************************************** | ||
| 198 | init_mappable_pages MACRO | ||
| 199 | ; | ||
| 200 | push di | ||
| 201 | ; | ||
| 202 | shl di,2 ; convert index into offset in dword array | ||
| 203 | ; | ||
| 204 | mov _mappable_pages[di],bx ; fill in segment | ||
| 205 | mov _mappable_pages[di][2],si ; and physical page number | ||
| 206 | ; | ||
| 207 | pop di | ||
| 208 | ; | ||
| 209 | ENDM | ||
| 210 | |||
| 211 | ;****************************************************************************** | ||
| 212 | ;**init_MAPPABLE_INDEX: macro to fill in EMM_MPIndex array. This array | ||
| 213 | ; contains a cross reference for the memory from 4000h to 10000h into the | ||
| 214 | ; mappable_pages array. There is an entry for each 16k page. The pages in | ||
| 215 | ; this range which are not mappable are initialised to -1. The ones which | ||
| 216 | ; are mappable are initialised to the index into the mappable_pages array | ||
| 217 | ; for the entry which represents this page | ||
| 218 | ; | ||
| 219 | ; ENTRY: DI = Index into _mappable_pages | ||
| 220 | ; BX = Segment of physical page | ||
| 221 | ; | ||
| 222 | ;****************************************************************************** | ||
| 223 | init_mappable_index MACRO | ||
| 224 | ; | ||
| 225 | push ax | ||
| 226 | push bx | ||
| 227 | ; | ||
| 228 | shr bx,10 ; convert segment to 16k page # | ||
| 229 | sub bx,CONV_STRT_PG ; first page in EMM_MPIndex array is 16 | ||
| 230 | ; | ||
| 231 | mov ax,di ; to extract the lower byte | ||
| 232 | mov _EMM_MPIndex[bx],al ; fill in index | ||
| 233 | ; | ||
| 234 | pop bx | ||
| 235 | pop ax | ||
| 236 | ; | ||
| 237 | ENDM | ||
| 238 | |||
| 239 | ;****************************************************************************** | ||
| 240 | ; INVALIDATE_MAPPABLE_PAGE_ENTRY: macro to remove the page from the mappable | ||
| 241 | ; page temporary list we are using. this is to facilitate the recognition | ||
| 242 | ; of pages above A000 which are not page frame pages. When we recognise page | ||
| 243 | ; frame pages we invalidate them so that the subsequent pass for pages doesn't | ||
| 244 | ; include these. | ||
| 245 | ; | ||
| 246 | ; ENTRY: BX = Segment of physical page | ||
| 247 | ;****************************************************************************** | ||
| 248 | inv_mpbl MACRO | ||
| 249 | ; | ||
| 250 | push bx | ||
| 251 | ; | ||
| 252 | shr bx,10 ; convert segment to 16k page # | ||
| 253 | mov cs:mappable_segs[bx],PAGE_NOT_MAPPABLE | ||
| 254 | ; | ||
| 255 | pop bx | ||
| 256 | ; | ||
| 257 | |||
| 258 | ENDM | ||
| 259 | |||
| 260 | ; | ||
| 261 | LAST segment USE16 | ||
| 262 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 263 | |||
| 264 | ;****************************************************************************** | ||
| 265 | ; LOCAL VARIABLES | ||
| 266 | ;****************************************************************************** | ||
| 267 | first_sys_ppage dw 0ffffh ; physical page number of first system page | ||
| 268 | |||
| 269 | page | ||
| 270 | ;****************************************************************************** | ||
| 271 | ; | ||
| 272 | ; CODE FOR INITIALISATION | ||
| 273 | ; | ||
| 274 | ;****************************************************************************** | ||
| 275 | |||
| 276 | |||
| 277 | page | ||
| 278 | ;****************************************************************************** | ||
| 279 | ; EMM_Init - initialization routine for EMM. | ||
| 280 | ; Patches int 67h vector. | ||
| 281 | ; | ||
| 282 | ; ENTRY: none | ||
| 283 | ; | ||
| 284 | ; EXIT: EMM vector initialized. | ||
| 285 | ; EMM data structures initialized | ||
| 286 | ; NC => no errors | ||
| 287 | ; C => errors | ||
| 288 | ; | ||
| 289 | ; USED: none | ||
| 290 | ; | ||
| 291 | ;****************************************************************************** | ||
| 292 | EMM_Init proc near | ||
| 293 | ; | ||
| 294 | pusha | ||
| 295 | push ds | ||
| 296 | push es | ||
| 297 | ; | ||
| 298 | ; set DS,ES to DGROUP segment | ||
| 299 | ; | ||
| 300 | mov ax,seg DGROUP | ||
| 301 | mov ds,ax | ||
| 302 | mov es,ax | ||
| 303 | ; | ||
| 304 | cld ; strings foward | ||
| 305 | ; | ||
| 306 | ; init EMM status | ||
| 307 | ; | ||
| 308 | mov [_EMMstatus],0 | ||
| 309 | |||
| 310 | ; | ||
| 311 | ; set total # of EMM pages | ||
| 312 | ; | ||
| 313 | mov cx,[pool_size] ; CX = kbytes of expanded memory | ||
| 314 | shr cx,4 ; CX = # of EMM pages available | ||
| 315 | mov [_total_pages],cx ; pages total | ||
| 316 | ; | ||
| 317 | ; init ptrs for _emm_page, _emm_free and _pft386 | ||
| 318 | ; | ||
| 319 | shl cx,1 ; CX = bytes in total_pages words | ||
| 320 | |||
| 321 | ifndef NOHIMEM | ||
| 322 | else | ||
| 323 | mov ax,seg VDATA | ||
| 324 | sub ax,seg DGROUP | ||
| 325 | shl ax,4 ; convert into offset from dgroup | ||
| 326 | add ax,offset VDATA:vdata_begin | ||
| 327 | mov [_emm_page],ax | ||
| 328 | endif | ||
| 329 | |||
| 330 | |||
| 331 | mov ax,[_emm_page] ; AX = ptr to emm_page array | ||
| 332 | add ax,cx ; AX = ptr to word just past emm_page[] | ||
| 333 | mov [_emm_free],ax ; set ptr for emm_free[] | ||
| 334 | add ax,cx ; AX = ptr to word just past emm_free[] | ||
| 335 | mov [_pft386],ax ; set ptr for _pft386[] | ||
| 336 | shl cx,1 ; CX = bytes in total_pages dwords | ||
| 337 | add ax,cx ; AX = ptr to word just past _pft386[] | ||
| 338 | mov [_emm_brk],ax ; set break address for emm data | ||
| 339 | shr cx,2 ; CX = total_pages again | ||
| 340 | ; | ||
| 341 | ; init free pages array | ||
| 342 | ; | ||
| 343 | mov [_free_count],cx ; all pages free initially | ||
| 344 | mov [_free_top],0 ; top ptr pts to first free page | ||
| 345 | mov di,[_emm_free] ; ES:DI pts to _emm_free[0] | ||
| 346 | mov bx,[_free_top] ; BX = current top of free list | ||
| 347 | shl bx,1 | ||
| 348 | add di,bx ; ES:DI pts to begin of free page area | ||
| 349 | xor ax,ax ; start with EMM page#0 | ||
| 350 | EMMP_loop: ; copy free pages into _emm_free | ||
| 351 | stosw ; store EMM page# | ||
| 352 | inc ax ;(0.02) increment page# | ||
| 353 | loop EMMP_loop ;Q: all entries in _emm_free[] ? | ||
| 354 | ; N: do next page. | ||
| 355 | ; | ||
| 356 | ; fix _page_frame_pages to be a maximum of 4 (for the LIM 3.2 frame) | ||
| 357 | ; | ||
| 358 | cmp [_page_frame_pages],4 | ||
| 359 | jbe EMIN_1 | ||
| 360 | mov [_page_frame_pages],4 | ||
| 361 | EMIN_1: | ||
| 362 | ; | ||
| 363 | ; See validity of page frame | ||
| 364 | ; | ||
| 365 | test [_PF_base],3ffh ; if any of these bits are set it is | ||
| 366 | ; invalid | ||
| 367 | jne EMIN_2 ; | ||
| 368 | cmp [_PF_base],0E400h ; in the ROM area | ||
| 369 | jae EMIN_2 ; also invalid | ||
| 370 | cmp [_PF_base],0C000h ; or in the video area | ||
| 371 | jnb EMIN_3 ; | ||
| 372 | EMIN_2: | ||
| 373 | ; | ||
| 374 | ; Page Frame invalid, set it to FFFFh and _page_frame_pages to 0 | ||
| 375 | ; | ||
| 376 | mov [_PF_base],0FFFFh | ||
| 377 | mov [_page_frame_pages],0 | ||
| 378 | ; | ||
| 379 | EMIN_3: | ||
| 380 | ; | ||
| 381 | ; setting up _page_frame_base | ||
| 382 | ; _mappable_pages | ||
| 383 | ; _EMM_MPIndex | ||
| 384 | ; _physical_page_count | ||
| 385 | ; _mappable_page_count | ||
| 386 | ; | ||
| 387 | ; | ||
| 388 | ; | ||
| 389 | ; ----------------- ----------------- ----------------- | ||
| 390 | ; | for pages | | for pages | | |FC00h | ||
| 391 | ; | below | | below | |---------------| | ||
| 392 | ; | A000h | | A000h | | | | ||
| 393 | ; ----------------- ----------------- | | | ||
| 394 | ; | | | | | . | | ||
| 395 | ; | for pages | | for pages | | . | | ||
| 396 | ; | above | | above | | . | | ||
| 397 | ; | A000h | | A000h | <-- | | | ||
| 398 | ; | | | | | |---------------| | ||
| 399 | ; ----------------- ----------------- | | |4800h | ||
| 400 | ; | for page frame| | for page frame| | |---------------| | ||
| 401 | ; | pages even if | | pages only if | |------- |4400h | ||
| 402 | ; | they don't | | they exist | |---------------| | ||
| 403 | ; | exist | | | | |4000h | ||
| 404 | ; ----------------- ----------------- ----------------- | ||
| 405 | ; | ||
| 406 | ; _page_frame_base _mappable_pages EMM_MPIndex | ||
| 407 | ; | ||
| 408 | ; Each entry reps Each entry reps Each entry reps | ||
| 409 | ; a physical page. a mappable ph. page a system page | ||
| 410 | ; | ||
| 411 | ; DWORD. DWORD Byte | ||
| 412 | ; | ||
| 413 | ; 1st WORD: offset 1st WORD: segment Index into | ||
| 414 | ; into page table of ph. page _mappable_pages | ||
| 415 | ; which reps the page | ||
| 416 | ; 2nd WORD: sel. 2nd WORD: physical | ||
| 417 | ; of page table page # of ph. page | ||
| 418 | ; | ||
| 419 | ; | ||
| 420 | ; 1. Set up for the page frame pages. Note that they may or may not exist. | ||
| 421 | ; Even if they do not exist entries must be set up for them in the | ||
| 422 | ; _page_frame_base. | ||
| 423 | ; | ||
| 424 | ; | ||
| 425 | ; initialise indexes. | ||
| 426 | ; | ||
| 427 | xor si,si ; index into _page_frame_pages | ||
| 428 | ; thus also physical page number | ||
| 429 | xor di,di ; index into _mappable_pages | ||
| 430 | ; | ||
| 431 | ; set up for page frame pages | ||
| 432 | ; | ||
| 433 | mov cx,[_page_frame_pages] ; get number | ||
| 434 | jcxz EMIN_5 ; if none exist then skip next portion | ||
| 435 | ; | ||
| 436 | mov bx,[_PF_base] ; get page frame base | ||
| 437 | ; | ||
| 438 | ; the setup loop: | ||
| 439 | ; | ||
| 440 | EMIN_4: | ||
| 441 | init_page_frame_base | ||
| 442 | init_mappable_pages | ||
| 443 | init_mappable_index | ||
| 444 | inv_mpbl | ||
| 445 | ; | ||
| 446 | ; update counters for next entry | ||
| 447 | ; | ||
| 448 | inc si | ||
| 449 | inc di | ||
| 450 | add bx,0400h | ||
| 451 | ; | ||
| 452 | ; and loop back | ||
| 453 | ; | ||
| 454 | loop EMIN_4 | ||
| 455 | ; | ||
| 456 | EMIN_5: | ||
| 457 | ; | ||
| 458 | ; 2. If page frame pages were less than 4 then also we should set aside | ||
| 459 | ; four entries in the physical page array | ||
| 460 | ; | ||
| 461 | mov si,4 | ||
| 462 | ; | ||
| 463 | ; 3. Setup for the mappable pages above A000h. Search the mappable_segs | ||
| 464 | ; array for mappable pages above A000h and for each mappable page make | ||
| 465 | ; an entry in the arrays | ||
| 466 | ; | ||
| 467 | ; | ||
| 468 | ; setup the segment and the count of pages we have to look for. also | ||
| 469 | ; the index into the mappable_segs array | ||
| 470 | ; | ||
| 471 | mov bx,0A000h ; segment | ||
| 472 | mov dx,bx ; | ||
| 473 | shr dx,10 ; page # corresponding to segment | ||
| 474 | ; | ||
| 475 | mov cx,64 ; max page # | ||
| 476 | sub cx,dx ; | ||
| 477 | ; | ||
| 478 | ; setup loop | ||
| 479 | EMIN_6: | ||
| 480 | ; | ||
| 481 | ; see if page mappable | ||
| 482 | ; | ||
| 483 | xchg dx,bx | ||
| 484 | cmp cs:mappable_segs[bx],PAGE_MAPPABLE ; | ||
| 485 | xchg dx,bx | ||
| 486 | jnz EMIN_7 | ||
| 487 | ; | ||
| 488 | ; page mappable. set up entries for it | ||
| 489 | ; | ||
| 490 | init_page_frame_base ; set up the page_frame_base entry | ||
| 491 | init_mappable_pages ; set up the mappable_pages entry | ||
| 492 | init_mappable_index ; set up the EMM_MPIndex | ||
| 493 | ; | ||
| 494 | ; update counters for next entry | ||
| 495 | ; | ||
| 496 | inc si ; these two are only updated | ||
| 497 | inc di ; if an entry is found | ||
| 498 | EMIN_7: | ||
| 499 | inc dx ; and these two are updated in | ||
| 500 | add bx,0400h ; any case | ||
| 501 | ; | ||
| 502 | ; and loop back | ||
| 503 | ; | ||
| 504 | loop EMIN_6 | ||
| 505 | |||
| 506 | ; | ||
| 507 | ; 4. Finally set up for the system pages | ||
| 508 | ; | ||
| 509 | ; | ||
| 510 | ; store the physical page # of the 1st system page. | ||
| 511 | ; | ||
| 512 | mov cs:[first_sys_ppage],si | ||
| 513 | ; | ||
| 514 | ; setup the segment and the count of pages we have to look for. also | ||
| 515 | ; the index into the mappable_segs array | ||
| 516 | ; | ||
| 517 | mov bx,04000h ; segment | ||
| 518 | mov dx,bx ; | ||
| 519 | shr dx,10 ; page # corresponding to segment | ||
| 520 | ; | ||
| 521 | mov cx,40 ; max page # | ||
| 522 | sub cx,dx ; | ||
| 523 | ; number of pages to be examined | ||
| 524 | ; | ||
| 525 | ; setup loop | ||
| 526 | EMIN_8: | ||
| 527 | ; | ||
| 528 | ; see if page mappable. | ||
| 529 | ; | ||
| 530 | xchg dx,bx | ||
| 531 | cmp cs:mappable_segs[bx],PAGE_MAPPABLE ; | ||
| 532 | xchg dx,bx | ||
| 533 | jnz EMIN_9 | ||
| 534 | ; | ||
| 535 | ; page mappable. set up entries for it | ||
| 536 | ; | ||
| 537 | init_page_frame_base ; set up the page_frame_base entry | ||
| 538 | init_mappable_pages ; set up the mappable_pages entry | ||
| 539 | init_mappable_index ; set up the EMM_MPIndex | ||
| 540 | ; | ||
| 541 | ; update counters for next entry | ||
| 542 | ; | ||
| 543 | inc si ; these two are only updated | ||
| 544 | inc di ; if an entry is found | ||
| 545 | EMIN_9: | ||
| 546 | inc dx ; and these two are updated in | ||
| 547 | add bx,0400h ; any case | ||
| 548 | ; | ||
| 549 | ; and loop back | ||
| 550 | ; | ||
| 551 | loop EMIN_8 | ||
| 552 | ; | ||
| 553 | ; 5. finally use the indexes to fill up the counts of the number of entries in | ||
| 554 | ; each array. | ||
| 555 | ; | ||
| 556 | mov [_physical_page_count],si | ||
| 557 | mov [_mappable_page_count],di | ||
| 558 | ; | ||
| 559 | ; | ||
| 560 | ; 6. and the pages in a context and the number of bytes needed to save a | ||
| 561 | ; context. | ||
| 562 | ; | ||
| 563 | inc si ; cntxt_pages = (physical_page_count | ||
| 564 | ; + 1) & NOT 1 | ||
| 565 | and si, NOT 0001h ; to round up si to higher even # | ||
| 566 | mov [_cntxt_pages],si ; number of pages in a context | ||
| 567 | ; | ||
| 568 | shl si,1 | ||
| 569 | add si,2 ; cntxt_bytes = cntxt_pages*2 + 2 | ||
| 570 | mov [_cntxt_bytes],si ; | ||
| 571 | ; | ||
| 572 | |||
| 573 | ; | ||
| 574 | ; initialize FRS_array | ||
| 575 | ; | ||
| 576 | lea si,FRS_array ; DS:SI <-- FRS_array | ||
| 577 | mov [si.FRS_alloc], 1 ; mark FRS set 0 as allocated | ||
| 578 | mov [CurRegSetn], 0 ; use FRS set 0 | ||
| 579 | mov [FRS_free], FRS_COUNT-1 ; one less FRS set | ||
| 580 | mov word ptr [CurRegSet], SI; save current FRS pointer | ||
| 581 | |||
| 582 | ; | ||
| 583 | ; NOW for some Handle 0 initialisation. We have to reclaim the pages we | ||
| 584 | ; released to the emm page pool from the conventional memory. This is | ||
| 585 | ; easy. These happen to be the first k pages in the emm page pool. We | ||
| 586 | ; need to fix the following data structures to reclaim these. | ||
| 587 | ; | ||
| 588 | ; k pages need to be transferred to emm_page array from emm_free array | ||
| 589 | ; and emmpt_start, _free_top, _free_count and _handle_table and _handle_count | ||
| 590 | ; updated | ||
| 591 | ; | ||
| 592 | ; find out the number of pages to be reclaimed | ||
| 593 | ; | ||
| 594 | mov cx,[sys_size] ; in kb | ||
| 595 | shr cx, 4 ; convert to number of 16k pages | ||
| 596 | ; | ||
| 597 | ; transfer these many pages from the emm_free array to the emm_pages array | ||
| 598 | ; | ||
| 599 | push cx | ||
| 600 | ; | ||
| 601 | mov si,_emm_free ; | ||
| 602 | add si,_free_top ; | ||
| 603 | add si,_free_top ; get offset to free page | ||
| 604 | ; | ||
| 605 | mov di,_emm_page ; | ||
| 606 | add di,_emmpt_start ; | ||
| 607 | add di,_emmpt_start ; get offset to next available loc in | ||
| 608 | ; emm_page | ||
| 609 | ; | ||
| 610 | cld | ||
| 611 | rep movsw ; transfer the pages over | ||
| 612 | ; | ||
| 613 | pop cx | ||
| 614 | ; | ||
| 615 | ; fix entry for handle 0 in handle table | ||
| 616 | ; | ||
| 617 | mov dx, [_emmpt_start] | ||
| 618 | mov _handle_table[0],dx ; offset into emm_page array | ||
| 619 | mov _handle_table[2],cx ; number of pages | ||
| 620 | ; | ||
| 621 | ; handle_count needs to be incremented to indicate that handle 0 is | ||
| 622 | ; allocated | ||
| 623 | ; | ||
| 624 | inc [_handle_count] | ||
| 625 | ; | ||
| 626 | ; fix ptr in emm page tracking arrays | ||
| 627 | ; | ||
| 628 | add [_emmpt_start],cx | ||
| 629 | add [_free_top],cx | ||
| 630 | sub [_free_count],cx | ||
| 631 | ; | ||
| 632 | ; Initialise FRS initialisation | ||
| 633 | ; | ||
| 634 | ; di = pointer into FRS. bx = physical page number. si = pointer into emm_page | ||
| 635 | ; cx = number of pages mapped. | ||
| 636 | ; | ||
| 637 | mov si,_handle_table[0] ; get pointer into emm_page | ||
| 638 | shl si,1 ; emm_page is a word array | ||
| 639 | add si,[_emm_page] ; | ||
| 640 | ; | ||
| 641 | GET_FRS_WINDOW di ; get pointer to FRS area | ||
| 642 | |||
| 643 | mov bx,cs:[first_sys_ppage] | ||
| 644 | shl bx,1 | ||
| 645 | add di,bx ; | ||
| 646 | ; | ||
| 647 | cld | ||
| 648 | rep movsw | ||
| 649 | ; | ||
| 650 | ; | ||
| 651 | ; the way we have allocated the pages we don't need to update the Page table | ||
| 652 | ; the pages that have been mapped | ||
| 653 | ; | ||
| 654 | ; init ELIM h/w emulation (DMA PORTS) | ||
| 655 | ; | ||
| 656 | call InitELIM | ||
| 657 | |||
| 658 | ; | ||
| 659 | ; init EMM_PTE - ptrs to EMM pages | ||
| 660 | ; | ||
| 661 | call InitEPage | ||
| 662 | ; | ||
| 663 | ; leave - no errors | ||
| 664 | ; | ||
| 665 | pop es | ||
| 666 | pop ds | ||
| 667 | popa | ||
| 668 | ; | ||
| 669 | xor ax,ax | ||
| 670 | clc | ||
| 671 | ret | ||
| 672 | ; | ||
| 673 | EMM_Init endp | ||
| 674 | |||
| 675 | ; | ||
| 676 | LAST ends | ||
| 677 | |||
| 678 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/EMMMES.ASM b/v4.0/src/MEMM/MEMM/EMMMES.ASM new file mode 100644 index 0000000..1036a66 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMMMES.ASM | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EMMMES - messages for MEMM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EMMMES - messages for MEMM | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: May 24,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 05/24/86 Original | ||
| 27 | ; 06/26/86 0.02 changed version #. | ||
| 28 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 29 | ; 07/06/86 0.04 changed version #. | ||
| 30 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 31 | ; 07/06/86 0.04 moved some messages to LAST | ||
| 32 | ; 07/08/86 0.04 Changed messages for incorrect machine | ||
| 33 | ; 07/09/86 0.05 changed version displayed version# to 3.20. | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | .lfcond | ||
| 37 | .386p | ||
| 38 | page | ||
| 39 | ;****************************************************************************** | ||
| 40 | ; P U B L I C D E C L A R A T I O N S | ||
| 41 | ;****************************************************************************** | ||
| 42 | ; | ||
| 43 | public InitMess | ||
| 44 | public InstallMess | ||
| 45 | public ISizeMess | ||
| 46 | public ExtSizeMess | ||
| 47 | public SysSizeMess | ||
| 48 | public PFBAMess | ||
| 49 | public ActiveMess | ||
| 50 | public InactiveMess | ||
| 51 | public AutoMess | ||
| 52 | public POE_Mess | ||
| 53 | public POE_Num | ||
| 54 | public POE_Len | ||
| 55 | public EXCPE_Mess | ||
| 56 | public EXCPE_Num | ||
| 57 | public EXCPE_CS | ||
| 58 | public EXCPE_EIP | ||
| 59 | public EXCPE_ERR | ||
| 60 | public EXCPE_Len | ||
| 61 | public InvParm | ||
| 62 | public InvPFBA | ||
| 63 | public InvMRA | ||
| 64 | public Adj_Size | ||
| 65 | public InsfMem | ||
| 66 | public Incorrect_DOS | ||
| 67 | public Incorrect_PRT | ||
| 68 | public Already_Inst | ||
| 69 | public PFWarning | ||
| 70 | public No_PF_Avail | ||
| 71 | page | ||
| 72 | ;****************************************************************************** | ||
| 73 | ; L O C A L C O N S T A N T S | ||
| 74 | ;****************************************************************************** | ||
| 75 | ; | ||
| 76 | include ascii_sm.equ | ||
| 77 | include vdmseg.inc | ||
| 78 | |||
| 79 | page | ||
| 80 | ;****************************************************************************** | ||
| 81 | ; S E G M E N T D E F I N I T I O N | ||
| 82 | ;****************************************************************************** | ||
| 83 | |||
| 84 | ;****************************************************************************** | ||
| 85 | ; | ||
| 86 | ; LAST Segment messages | ||
| 87 | ; | ||
| 88 | ;****************************************************************************** | ||
| 89 | ; | ||
| 90 | LAST segment | ||
| 91 | |||
| 92 | InitMess db CR,LF | ||
| 93 | db "MICROSOFT Expanded Memory Manager 386 Version 4.00",CR,LF | ||
| 94 | db "(C) Copyright MICROSOFT Corporation 1988",CR,LF | ||
| 95 | db "$" | ||
| 96 | |||
| 97 | InstallMess db "EMM386 Installed.", CR,LF | ||
| 98 | db " Extended memory allocated: " | ||
| 99 | ExtSizeMess db " KB",CR,LF | ||
| 100 | db " System memory allocated: " | ||
| 101 | SysSizeMess db " KB",CR,LF | ||
| 102 | db " " | ||
| 103 | db "--------",CR,LF | ||
| 104 | db " Expanded memory available: " | ||
| 105 | ISizeMess db " KB",CR,LF | ||
| 106 | db " Page frame base address: " | ||
| 107 | PFBAMess db "XX000 H",CR,LF | ||
| 108 | db "$" | ||
| 109 | |||
| 110 | ActiveMess db "EMM386 Active.",CR,LF | ||
| 111 | db CR,LF | ||
| 112 | db "$" | ||
| 113 | |||
| 114 | InactiveMess db "EMM386 Inactive.",CR,LF | ||
| 115 | db CR,LF | ||
| 116 | db "$" | ||
| 117 | |||
| 118 | AutoMess db "EMM386 is in Auto mode.",CR,LF | ||
| 119 | db CR,LF | ||
| 120 | db "$" | ||
| 121 | |||
| 122 | ; | ||
| 123 | ; install error messages | ||
| 124 | ; | ||
| 125 | |||
| 126 | InvParm db "Invalid parameter specified.",CR,LF | ||
| 127 | db "$" | ||
| 128 | |||
| 129 | InvPFBA db "Page Frame Base Address adjusted.",CR,LF | ||
| 130 | db "$" | ||
| 131 | |||
| 132 | InvMRA db "Mapping Register Address adjusted.",CR,LF | ||
| 133 | db "$" | ||
| 134 | |||
| 135 | Adj_Size db "Size of expanded memory pool adjusted.",CR,LF | ||
| 136 | db "$" | ||
| 137 | |||
| 138 | PFWarning db "WARNING - " | ||
| 139 | db "Option ROM or RAM detected within page frame." | ||
| 140 | db CR,LF | ||
| 141 | db CR,LF | ||
| 142 | db BEL | ||
| 143 | db "$" | ||
| 144 | |||
| 145 | InsfMem db "EMM386 not installed - insufficient memory.",CR,LF | ||
| 146 | db BEL | ||
| 147 | db CR,LF | ||
| 148 | db "$" | ||
| 149 | |||
| 150 | Incorrect_DOS db "EMM386 not installed - incorrect DOS version.",CR,LF | ||
| 151 | db BEL | ||
| 152 | db CR,LF | ||
| 153 | db "$" | ||
| 154 | |||
| 155 | Incorrect_PRT db "EMM386 not installed - incorrect machine type.",CR,LF | ||
| 156 | db BEL | ||
| 157 | db CR,LF | ||
| 158 | db "$" | ||
| 159 | |||
| 160 | No_PF_Avail db "EMM386 not installed - " | ||
| 161 | db "unable to set page frame base address.",CR,LF | ||
| 162 | db BEL | ||
| 163 | db CR,LF | ||
| 164 | db "$" | ||
| 165 | |||
| 166 | Already_Inst db "EMM386 already installed.",CR,LF | ||
| 167 | db BEL | ||
| 168 | db CR,LF | ||
| 169 | db "$" | ||
| 170 | |||
| 171 | LAST ends | ||
| 172 | |||
| 173 | page | ||
| 174 | ;****************************************************************************** | ||
| 175 | ; | ||
| 176 | ; _DATA Segment messages | ||
| 177 | ; | ||
| 178 | ;****************************************************************************** | ||
| 179 | ; | ||
| 180 | _DATA segment | ||
| 181 | |||
| 182 | ; | ||
| 183 | ; run time error messages | ||
| 184 | ; | ||
| 185 | POE_Mess db CR,LF | ||
| 186 | db BEL | ||
| 187 | db "EMM386 Privileged operation error #" | ||
| 188 | POE_Num db "xx -",CR,LF | ||
| 189 | db "Deactivate EMM386 and Continue (C) or reBoot (B)" | ||
| 190 | db " (C or B) ? " | ||
| 191 | POE_Len = $-POE_Mess | ||
| 192 | db "$" | ||
| 193 | |||
| 194 | EXCPE_Mess db CR,LF | ||
| 195 | db BEL | ||
| 196 | db "EMM386 Exception error #" | ||
| 197 | EXCPE_Num db "xx @" | ||
| 198 | EXCPE_CS db "xxxx:" | ||
| 199 | EXCPE_EIP db "xxxxxxxx Code " | ||
| 200 | EXCPE_ERR db "xxxx" | ||
| 201 | db CR,LF,"Press enter to reboot" | ||
| 202 | EXCPE_Len = $-EXCPE_Mess | ||
| 203 | db "$" | ||
| 204 | |||
| 205 | ; | ||
| 206 | _DATA ends | ||
| 207 | |||
| 208 | end | ||
| 209 | |||
| 210 | |||
diff --git a/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM b/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM new file mode 100644 index 0000000..a675868 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM | |||
| @@ -0,0 +1,385 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE ErrHndlr - Error Handler | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 8 | ; | ||
| 9 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 10 | ; | ||
| 11 | ; Module: ErrHndlr - Recover from exception and priveledged operation errors | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date: June 6,1986 | ||
| 16 | ; | ||
| 17 | ; Authors: Brad Tate | ||
| 18 | ; | ||
| 19 | ;****************************************************************************** | ||
| 20 | ; | ||
| 21 | ; CHANGES: | ||
| 22 | ; | ||
| 23 | ; DATE REVISION DESCRIPTION | ||
| 24 | ; -------- -------- ------------------------------------------------------ | ||
| 25 | ; 06/06/86 Original | ||
| 26 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 27 | ; 06/28/86 0.02 Removed STI at end of ErrHndlr | ||
| 28 | ; 06/28/86 0.02 Changed error # display to leading zeroes | ||
| 29 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | page | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; | ||
| 35 | ; Functional description: | ||
| 36 | ; | ||
| 37 | ; This module contains the code that displays an error message and | ||
| 38 | ; asks the user to continue or reboot. | ||
| 39 | ; | ||
| 40 | ;****************************************************************************** | ||
| 41 | page | ||
| 42 | .386P | ||
| 43 | ; | ||
| 44 | include vdmseg.inc | ||
| 45 | include vdmsel.inc | ||
| 46 | include vm386.inc | ||
| 47 | include kbd.inc | ||
| 48 | ;****************************************************************************** | ||
| 49 | ; Public Declarations | ||
| 50 | ;****************************************************************************** | ||
| 51 | ; | ||
| 52 | public ErrHndlr ; Display message and continue or reboot | ||
| 53 | public Error_Flag | ||
| 54 | ;****************************************************************************** | ||
| 55 | ; Externs | ||
| 56 | ;****************************************************************************** | ||
| 57 | _TEXT segment | ||
| 58 | extrn RetReal:near ; return to real mode | ||
| 59 | extrn egetc:near ; get keyboard character | ||
| 60 | extrn WaitKBD:near ; wait for keyboard ready | ||
| 61 | _TEXT ends | ||
| 62 | |||
| 63 | _DATA segment | ||
| 64 | extrn powr10:word ; power of 10's table | ||
| 65 | extrn POE_Mess:byte ; privileged operation error | ||
| 66 | extrn POE_Num:byte ; where to put error code | ||
| 67 | extrn POE_Len:abs ; length of message | ||
| 68 | extrn EXCPE_Mess:byte ; exception error message | ||
| 69 | extrn EXCPE_Num:byte ; where to put error code | ||
| 70 | extrn EXCPE_CS:byte ; where to put CS | ||
| 71 | extrn EXCPE_EIP:byte ; where to put EIP | ||
| 72 | extrn EXCPE_ERR:byte ; where to put ERR | ||
| 73 | extrn EXCPE_Len:abs ; length of message | ||
| 74 | _DATA ends | ||
| 75 | ; | ||
| 76 | romdata segment use16 at 40h | ||
| 77 | org 71h | ||
| 78 | fBreak db ? | ||
| 79 | fReset dw ? | ||
| 80 | romdata ends | ||
| 81 | ; | ||
| 82 | ;****************************************************************************** | ||
| 83 | ; Equates | ||
| 84 | ;****************************************************************************** | ||
| 85 | ; | ||
| 86 | MASTER = 0A1H ; Master interrupt i/o port | ||
| 87 | SLAVE = 021H ; Slave interrupt i/o port | ||
| 88 | NMI = 070H ; Non-Maskable interrupt i/o port | ||
| 89 | DIS_MSTSLV = 00H ; Value to write to disable master/slave | ||
| 90 | DIS_NMI = 080H ; Value to write to disable NMI | ||
| 91 | ENA_NMI = 008H ; Value to write to enable NMI | ||
| 92 | B = 48 ; make code for B | ||
| 93 | C = 46 ; make code for C | ||
| 94 | ENTER = 28 ; make code for enter key | ||
| 95 | ATTR = 07 ; attribute for write string | ||
| 96 | WRSTR = 1301h ; write string function code (format 1) | ||
| 97 | CPOSN = 5*256+0 ; cursor position to write | ||
| 98 | ; | ||
| 99 | ; | ||
| 100 | ;****************************************************************************** | ||
| 101 | ; LOCAL DATA | ||
| 102 | ;****************************************************************************** | ||
| 103 | _DATA segment | ||
| 104 | Error_Flag dw 0 ; flags for Instruction Prefixes | ||
| 105 | masterp db 0 ; save master port value | ||
| 106 | slavep db 0 ; save slave port value | ||
| 107 | mode db 0 ; save mode | ||
| 108 | boot db 0 ; value to reboot | ||
| 109 | continue db 0 ; value to continue | ||
| 110 | |||
| 111 | GPsavERR dw 0 ; GP fault Error Code save | ||
| 112 | GPsavEIP dd 0 ; GP fault EIP save | ||
| 113 | GPsavCS dw 0 ; GP fault CS save | ||
| 114 | |||
| 115 | _DATA ends | ||
| 116 | ; | ||
| 117 | ;****************************************************************************** | ||
| 118 | ; | ||
| 119 | ; ErrHndlr - displays the appropriate error message and prompts the | ||
| 120 | ; user for a character to continue or reboot. The screen | ||
| 121 | ; is cleared by this routine. If the user chooses to | ||
| 122 | ; continue, the system is in real mode. | ||
| 123 | ; | ||
| 124 | ; entry: ax = 0 => Privileged operation error | ||
| 125 | ; ax = 1 => Exception error | ||
| 126 | ; bx = error number to display | ||
| 127 | ; | ||
| 128 | ; exit: either reboot, or exit in "real" mode with CLI | ||
| 129 | ; | ||
| 130 | ; used: none | ||
| 131 | ; | ||
| 132 | ; stack: | ||
| 133 | ; | ||
| 134 | ;****************************************************************************** | ||
| 135 | _TEXT segment | ||
| 136 | ASSUME CS:_TEXT, DS:DGROUP, ES:DGROUP | ||
| 137 | ErrHndlr proc near | ||
| 138 | ; | ||
| 139 | ; save fault infos | ||
| 140 | ; | ||
| 141 | push eax | ||
| 142 | push ds | ||
| 143 | push VDMD_GSEL | ||
| 144 | pop ds | ||
| 145 | mov eax, dword ptr [bp.VTFO] ; error code | ||
| 146 | mov [GPsavERR], ax | ||
| 147 | mov eax, dword ptr [bp.VTFOE+VMTF_EIP] ; EIP | ||
| 148 | mov [GPsavEIP], eax | ||
| 149 | mov ax, word ptr [bp.VTFOE+VMTF_CS] ; CS | ||
| 150 | mov [GPsavCS], ax | ||
| 151 | pop ds | ||
| 152 | pop eax | ||
| 153 | |||
| 154 | call RetReal ; return to real mode | ||
| 155 | ; | ||
| 156 | push ax | ||
| 157 | push bx | ||
| 158 | push cx | ||
| 159 | push dx | ||
| 160 | push bp | ||
| 161 | push di | ||
| 162 | ; | ||
| 163 | push ax ; save input to this routine | ||
| 164 | in al,MASTER ; get value of master interrupt port | ||
| 165 | mov [masterp],al ; save it | ||
| 166 | in al,SLAVE ; get value of slave interrupt port | ||
| 167 | mov [slavep],al ; save it | ||
| 168 | mov al,DIS_MSTSLV ; value to disable master/slave int | ||
| 169 | out MASTER,al ; disable master | ||
| 170 | out SLAVE,al ; disable slave | ||
| 171 | mov al,DIS_NMI ; value to disable NMI | ||
| 172 | out NMI,al | ||
| 173 | kbdbusy: | ||
| 174 | call egetc ; q: is there stuff in keyboard buffer? | ||
| 175 | jnz kbdbusy ; y: get it and pitch it | ||
| 176 | ; n: continue | ||
| 177 | pop ax ; get entry condition | ||
| 178 | or ax,ax ; q: privileged error? | ||
| 179 | jnz excep ; n: exception error | ||
| 180 | mov bp,offset DGROUP:POE_Mess ; y: privileged error | ||
| 181 | mov cx,POE_Len | ||
| 182 | mov di,offset DGROUP:POE_Num; error number location | ||
| 183 | mov ax,bx ; error number in ax | ||
| 184 | call b2asc10 ; convert to ascii | ||
| 185 | mov [boot],B ; key to boot | ||
| 186 | mov [continue],C ; key to continue | ||
| 187 | jmp skip_exc ; skip exception stuff | ||
| 188 | excep: | ||
| 189 | mov bp,offset DGROUP:EXCPE_Mess ; n: load up exception error | ||
| 190 | mov cx,EXCPE_Len ; length of msg | ||
| 191 | mov di,offset DGROUP:EXCPE_Num ; error number location | ||
| 192 | mov ax,bx ; error number in ax | ||
| 193 | call b2asc10 ; convert to ascii | ||
| 194 | mov di,offset DGROUP:EXCPE_CS | ||
| 195 | mov ax,[GPsavCS] | ||
| 196 | call b2asc16 | ||
| 197 | mov di,offset DGROUP:EXCPE_EIP | ||
| 198 | mov eax,[GPsavEIP] | ||
| 199 | ror eax,16 | ||
| 200 | call b2asc16 | ||
| 201 | ror eax,16 | ||
| 202 | call b2asc16 | ||
| 203 | mov di,offset DGROUP:EXCPE_ERR | ||
| 204 | mov ax,[GPsavERR] | ||
| 205 | call b2asc16 | ||
| 206 | mov [boot],ENTER ; key to reboot | ||
| 207 | mov [continue],0ffh ; can't continue | ||
| 208 | skip_exc: | ||
| 209 | mov ah,0fh ; read video state | ||
| 210 | int 10h | ||
| 211 | mov [mode],al ; save mode | ||
| 212 | ; mov ax,3 ; set to mode 3 | ||
| 213 | ; int 10h ; standard 80 x 25 color | ||
| 214 | mov dx,CPOSN ; cursor position | ||
| 215 | mov bl,ATTR ; attribute | ||
| 216 | mov ax,WRSTR ; write string function code | ||
| 217 | int 10h ; do it | ||
| 218 | cli ; make sure int 10 didn't enable | ||
| 219 | key_loop: | ||
| 220 | call egetc ; get a character | ||
| 221 | jz key_loop ; nothing there yet | ||
| 222 | cmp al,[continue] ; q: continue? | ||
| 223 | je err_cont ; y | ||
| 224 | cmp al,[boot] ; q: boot? | ||
| 225 | jne key_loop ; n: try again | ||
| 226 | ;****************************************************************************** | ||
| 227 | ; | ||
| 228 | ; Reboot system | ||
| 229 | ; | ||
| 230 | ;****************************************************************************** | ||
| 231 | assume ds:romdata | ||
| 232 | mov ax,romdata | ||
| 233 | mov ds,ax ; ds = romdata segment | ||
| 234 | mov [freset],0 ; cold restart | ||
| 235 | mov al,0fh or 80h ; shutdown byte address/disable NMI | ||
| 236 | out 70h,al ; write CMOS address | ||
| 237 | jmp short $+2 ; delay | ||
| 238 | mov al,0h ; shutdown code 0 = processor reset | ||
| 239 | out 71h,al ; write shutdown code to shutdown byte | ||
| 240 | call WaitKBD ; wait for 8042 to accept command | ||
| 241 | mov al,0feh ; feh = pulse output bit 0 (reset) | ||
| 242 | out KbStatus,al ; reset processor | ||
| 243 | hlt | ||
| 244 | assume ds:DGROUP | ||
| 245 | ; | ||
| 246 | err_cont: | ||
| 247 | xor ah,ah ; ah = 0 to set video mode | ||
| 248 | mov al,[mode] ; restore their mode | ||
| 249 | int 10h | ||
| 250 | cli ; turn them off... | ||
| 251 | ; | ||
| 252 | ; restore master, slave, and NMI | ||
| 253 | ; | ||
| 254 | mov al,[masterp] ; get value of master interrupt port | ||
| 255 | out MASTER,al ; restore it | ||
| 256 | mov al,[slavep] ; get value of slave interrupt port | ||
| 257 | out SLAVE,al ; restore it | ||
| 258 | mov al,ENA_NMI ; value to enable NMI | ||
| 259 | out NMI,al | ||
| 260 | ; | ||
| 261 | pop di | ||
| 262 | pop bp | ||
| 263 | pop dx | ||
| 264 | pop cx | ||
| 265 | pop bx | ||
| 266 | pop ax | ||
| 267 | ret | ||
| 268 | ErrHndlr endp | ||
| 269 | |||
| 270 | page | ||
| 271 | ;****************************************************************************** | ||
| 272 | ; | ||
| 273 | ; b2asc10 - converts binary to ascii decimal and store at _TEXT:DI | ||
| 274 | ; stores 2 ascii chars (decimal # is right justified and | ||
| 275 | ; filled on left with 0s) | ||
| 276 | ; | ||
| 277 | ; entry: ax = binary number | ||
| 278 | ; ds:DGROUP | ||
| 279 | ; ds:di = place to store ascii chars. | ||
| 280 | ; | ||
| 281 | ; exit: ASCII decimal representation of number stored at _TEXT:DI | ||
| 282 | ; | ||
| 283 | ; used: none | ||
| 284 | ; | ||
| 285 | ; stack: | ||
| 286 | ; | ||
| 287 | ;****************************************************************************** | ||
| 288 | ; | ||
| 289 | b2asc10 proc near | ||
| 290 | ; | ||
| 291 | push ax | ||
| 292 | push bx | ||
| 293 | push cx | ||
| 294 | push dx | ||
| 295 | push si | ||
| 296 | push di | ||
| 297 | ; | ||
| 298 | mov si,2 ; pointer to base 10 table | ||
| 299 | mov bl,1 ; leading zeroes on | ||
| 300 | ; | ||
| 301 | ; convert binary number to decimal ascii | ||
| 302 | ; | ||
| 303 | b2_loop: | ||
| 304 | xor dx,dx ; clear word extension | ||
| 305 | mov cx,powr10[si] | ||
| 306 | div cx ; divide by power of 10 | ||
| 307 | or bl,bl | ||
| 308 | jnz b2_ascii | ||
| 309 | ; | ||
| 310 | or ax,ax ; q: zero result? | ||
| 311 | jnz b2_ascii ; n: go convert to ascii | ||
| 312 | ; | ||
| 313 | mov al,' ' ; y: go blank fill | ||
| 314 | jmp b2_make_strg ; | ||
| 315 | ; | ||
| 316 | b2_ascii: | ||
| 317 | add al,'0' ; put into ascii format | ||
| 318 | mov bl,1 ; leading zeroes on | ||
| 319 | ; | ||
| 320 | b2_make_strg: | ||
| 321 | mov ds:[di],al ; put ascii number into string | ||
| 322 | xchg ax,dx | ||
| 323 | inc di ; increment buffer string pointer | ||
| 324 | dec si ; decrement power of 10 pointer | ||
| 325 | dec si ; | ||
| 326 | jge b2_loop ; Q: Last digit? N: Jump if not | ||
| 327 | ; | ||
| 328 | pop di | ||
| 329 | pop si | ||
| 330 | pop dx | ||
| 331 | pop cx | ||
| 332 | pop bx | ||
| 333 | pop ax | ||
| 334 | ret ; *** return *** | ||
| 335 | ; | ||
| 336 | b2asc10 endp | ||
| 337 | ; | ||
| 338 | ;****************************************************************************** | ||
| 339 | ; | ||
| 340 | ; b2asc16 - converts binary to hexidecimal and store at _TEXT:DI | ||
| 341 | ; stores 4 ascii chars (# is right justified and | ||
| 342 | ; filled on left with 0s) | ||
| 343 | ; | ||
| 344 | ; entry: ax = binary number | ||
| 345 | ; ds:DGROUP | ||
| 346 | ; ds:di = place to store ascii chars. | ||
| 347 | ; | ||
| 348 | ; exit: ASCII hexidecimal representation of number stored at _TEXT:DI | ||
| 349 | ; | ||
| 350 | ; used: none | ||
| 351 | ; | ||
| 352 | ; stack: | ||
| 353 | ; | ||
| 354 | ;****************************************************************************** | ||
| 355 | ; | ||
| 356 | b2asc16 proc near | ||
| 357 | |||
| 358 | push ax | ||
| 359 | push bx | ||
| 360 | push cx | ||
| 361 | |||
| 362 | mov cx,4 | ||
| 363 | b2asc16_loop: | ||
| 364 | mov bl,ah | ||
| 365 | shr bl,4 | ||
| 366 | add bl,'0' | ||
| 367 | cmp bl,'9' | ||
| 368 | jbe b2asc16_skip | ||
| 369 | add bl,'A'-'9'-1 | ||
| 370 | b2asc16_skip: | ||
| 371 | mov ds:[di],bl | ||
| 372 | shl ax,4 | ||
| 373 | inc di | ||
| 374 | loop b2asc16_loop | ||
| 375 | |||
| 376 | pop cx | ||
| 377 | pop bx | ||
| 378 | pop ax | ||
| 379 | ret | ||
| 380 | |||
| 381 | b2asc16 endp | ||
| 382 | |||
| 383 | _TEXT ENDS | ||
| 384 | END | ||
| 385 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/EXTPOOL.ASM b/v4.0/src/MEMM/MEMM/EXTPOOL.ASM new file mode 100644 index 0000000..de7b492 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EXTPOOL.ASM | |||
| @@ -0,0 +1,187 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE EXTPOOL - MODULE to manage a pool of extended memory | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EXTPOOL - Manage a pool of extended memory. | ||
| 13 | ; | ||
| 14 | ; Version: 0.01 | ||
| 15 | ; | ||
| 16 | ; Date: Sep 1, 1988 | ||
| 17 | ; | ||
| 18 | ; Author: ISP (ISP) | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ;****************************************************************************** | ||
| 27 | ; Functional Description: | ||
| 28 | ; | ||
| 29 | ; "Fixit Orders" Crisis mode file. We need to ship data structures up hi. | ||
| 30 | ; So at init time we get a pool of extended memory and manage it for the | ||
| 31 | ; fixit routine. Services provided include initialise, allocate and | ||
| 32 | ; blkmov to the memory. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | .lfcond | ||
| 36 | .386p | ||
| 37 | |||
| 38 | page | ||
| 39 | ;****************************************************************************** | ||
| 40 | ; P U B L I C D E C L A R A T I O N S | ||
| 41 | ;****************************************************************************** | ||
| 42 | public pool_initialise | ||
| 43 | public get_buffer | ||
| 44 | |||
| 45 | page | ||
| 46 | ;****************************************************************************** | ||
| 47 | ; L O C A L C O N S T A N T S | ||
| 48 | ;****************************************************************************** | ||
| 49 | ; | ||
| 50 | |||
| 51 | ;****************************************************************************** | ||
| 52 | ; INCLUDE FILES | ||
| 53 | ;****************************************************************************** | ||
| 54 | include vdmseg.inc ; segment definitions | ||
| 55 | |||
| 56 | page | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; E X T E R N A L R E F E R E N C E S | ||
| 59 | ;****************************************************************************** | ||
| 60 | ; | ||
| 61 | ; | ||
| 62 | page | ||
| 63 | ;****************************************************************************** | ||
| 64 | ; S E G M E N T D E F I N I T I O N | ||
| 65 | ;****************************************************************************** | ||
| 66 | |||
| 67 | ;************************************************************************* | ||
| 68 | ; | ||
| 69 | ; DATA | ||
| 70 | ; | ||
| 71 | ;************************************************************************* | ||
| 72 | |||
| 73 | LAST SEGMENT | ||
| 74 | |||
| 75 | ext_start dw 0000h ; start of the pool of extended memory | ||
| 76 | dw 0010h ; 24 bit address | ||
| 77 | |||
| 78 | ext_size dw 0 ; size | ||
| 79 | dw 0 ; | ||
| 80 | |||
| 81 | LAST ENDS | ||
| 82 | |||
| 83 | ;************************************************************************* | ||
| 84 | ; | ||
| 85 | ; CODE | ||
| 86 | ; | ||
| 87 | ;************************************************************************* | ||
| 88 | LAST SEGMENT | ||
| 89 | assume cs:LAST, DS:DGROUP, ES:DGROUP | ||
| 90 | |||
| 91 | |||
| 92 | ;****************************************************************************** | ||
| 93 | ;*** Pool Initialise *** Give this memory manager the memory it is to play ; | ||
| 94 | ; with. ; | ||
| 95 | ; ; | ||
| 96 | ; INPUTS: AX = start offset of the extended memory in K ; | ||
| 97 | ; CX = size of the memory ; | ||
| 98 | ; ; | ||
| 99 | ; OUTPUTS: None ; | ||
| 100 | ; ; | ||
| 101 | ; USES: None ; | ||
| 102 | ; ; | ||
| 103 | ; AUTHOR: ISP (ISP) Sep 1, 1988 ; | ||
| 104 | ; ; | ||
| 105 | ;*****************************************************************************; | ||
| 106 | |||
| 107 | Pool_Initialise proc near | ||
| 108 | ; | ||
| 109 | push dx | ||
| 110 | push cx | ||
| 111 | push ax | ||
| 112 | ; | ||
| 113 | push cx ; save size of memory | ||
| 114 | xor dx,dx | ||
| 115 | mov cx,1024 | ||
| 116 | mul cx ; dx:ax size in bytes offset from 1M | ||
| 117 | ; | ||
| 118 | add ax,cs:[ext_start] ; add it to 1M | ||
| 119 | adc dx,cs:[ext_start+2] ; | ||
| 120 | ; | ||
| 121 | mov cs:[ext_start],ax ; | ||
| 122 | mov cs:[ext_start+2],dx ; | ||
| 123 | ; | ||
| 124 | pop ax ; get size into ax | ||
| 125 | xor dx,dx ; | ||
| 126 | mul cx | ||
| 127 | ; | ||
| 128 | mov cs:[ext_size],ax | ||
| 129 | mov cs:[ext_size+2],dx | ||
| 130 | ; | ||
| 131 | pop ax | ||
| 132 | pop cx | ||
| 133 | pop dx | ||
| 134 | ; | ||
| 135 | ret | ||
| 136 | ; | ||
| 137 | Pool_Initialise endp | ||
| 138 | |||
| 139 | |||
| 140 | |||
| 141 | ;****************************************************************************** | ||
| 142 | ;***Get buffer*** Give some poor beggar the memory he is asking for ; | ||
| 143 | ; ; | ||
| 144 | ; INPUTS: cx = size of buffer required in bytes ; | ||
| 145 | ; ; | ||
| 146 | ; OUTPUTS: DX:AX = address of buffer ; | ||
| 147 | ; cx = size allocated | ||
| 148 | ; ; | ||
| 149 | ; USES: None ; | ||
| 150 | ; ; | ||
| 151 | ; AUTHOR: ISP (ISP) Sep 1, 1988 ; | ||
| 152 | ; ; | ||
| 153 | ;*****************************************************************************; | ||
| 154 | |||
| 155 | Get_Buffer proc near | ||
| 156 | ; | ||
| 157 | ; | ||
| 158 | ; assume that the memory is present, put start address in dx:ax | ||
| 159 | ; | ||
| 160 | mov dx,cs:[ext_start+2] | ||
| 161 | mov ax,cs:[ext_start] | ||
| 162 | ; | ||
| 163 | ; then proceed to determine if it really exists | ||
| 164 | ; | ||
| 165 | push eax | ||
| 166 | xor eax,eax | ||
| 167 | mov ax,cx | ||
| 168 | cmp eax, dword ptr cs:[ext_size] | ||
| 169 | ja no_mem | ||
| 170 | ; | ||
| 171 | ; it does exist, adjust the size and the start address | ||
| 172 | ; | ||
| 173 | sub dword ptr cs:[ext_size],eax | ||
| 174 | add dword ptr cs:[ext_start],eax | ||
| 175 | ; | ||
| 176 | pop eax | ||
| 177 | clc | ||
| 178 | ret | ||
| 179 | |||
| 180 | no_mem: | ||
| 181 | pop eax | ||
| 182 | stc | ||
| 183 | ret | ||
| 184 | Get_buffer endp | ||
| 185 | |||
| 186 | LAST ENDS | ||
| 187 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/I286.ASM b/v4.0/src/MEMM/MEMM/I286.ASM new file mode 100644 index 0000000..8eb2102 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/I286.ASM | |||
| @@ -0,0 +1,312 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE i286.asm - Support Routines for protected mode system | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: i286.asm - Support Routines for protected mode system | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Original | ||
| 27 | ; 02/05/86 A added is286, is386 | ||
| 28 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 29 | ; 06/03/86 C added push/pop es to Init_GDT and changed Ring 0 | ||
| 30 | ; stack to STACK0 and STACK0_SIZE. | ||
| 31 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 32 | ; | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; | ||
| 35 | ; Functional Description: | ||
| 36 | ; | ||
| 37 | ; Anthony Short | ||
| 38 | ; 26th Dec 1985 | ||
| 39 | ; | ||
| 40 | ; DESCRIPTION | ||
| 41 | ; | ||
| 42 | ; These routines manage the various 286 memory management | ||
| 43 | ; tables and manipulate descriptors and selectors. | ||
| 44 | ; | ||
| 45 | ; The routines which deal with descriptors use the following | ||
| 46 | ; register usage conventions: | ||
| 47 | ; | ||
| 48 | ; BX - selector of required descriptor. The selector may | ||
| 49 | ; have RPL bits present, the routines ignore them. | ||
| 50 | ; | ||
| 51 | ; CX - SIZE IN BYTES of segment. NOTE: descriptors contain | ||
| 52 | ; limits, not sizes (limit = size - 1). Since everyone | ||
| 53 | ; else talks sizes, these routines do too, and do their | ||
| 54 | ; own conversion. | ||
| 55 | ; | ||
| 56 | ; DX - second selector when needed | ||
| 57 | ; | ||
| 58 | ; AH - access rights byte | ||
| 59 | ; | ||
| 60 | ; AL, DX - 24 bit physical address | ||
| 61 | ; | ||
| 62 | ; ES:0 - pointer to the desired descriptor table. | ||
| 63 | ; | ||
| 64 | ; All the routines which manipulate descriptors are callable | ||
| 65 | ; in both real and protected mode. | ||
| 66 | ; | ||
| 67 | ; In general all registers are preserved. | ||
| 68 | ; | ||
| 69 | ; The following routines are provided: | ||
| 70 | ; | ||
| 71 | ; SetDescInfo - set descriptor information | ||
| 72 | ; SetSegDesc - set segment descriptor information | ||
| 73 | ; | ||
| 74 | ; SegTo24 - convert segment number to 24 bit addr | ||
| 75 | ; SegOffTo24 - convert seg:offset to 24 bit addr | ||
| 76 | ; | ||
| 77 | ; InitGdt - set up parts of GDT which cannot easily | ||
| 78 | ; be initialised statically. | ||
| 79 | ; | ||
| 80 | ; WARNING This code is 286 specific, it will NOT run on an 8088. | ||
| 81 | ; | ||
| 82 | ;****************************************************************************** | ||
| 83 | .lfcond ; list false conditionals | ||
| 84 | .386p | ||
| 85 | |||
| 86 | |||
| 87 | include VDMseg.inc | ||
| 88 | include VDMsel.inc | ||
| 89 | include desc.inc | ||
| 90 | |||
| 91 | ;****************************************************************************** | ||
| 92 | ; E X T E R N A L R E F E R E N C E S | ||
| 93 | ;****************************************************************************** | ||
| 94 | GDT segment | ||
| 95 | extrn GDTLEN:abs | ||
| 96 | GDT ends | ||
| 97 | |||
| 98 | IDT segment | ||
| 99 | extrn IDTLEN:abs | ||
| 100 | IDT ends | ||
| 101 | |||
| 102 | TSS segment | ||
| 103 | extrn TSSLEN:abs | ||
| 104 | TSS ends | ||
| 105 | |||
| 106 | LAST SEGMENT | ||
| 107 | |||
| 108 | assume cs:LAST | ||
| 109 | |||
| 110 | ;** SetDescInfo - set descriptor information | ||
| 111 | ; | ||
| 112 | ; The limit field of a specified descriptor is set. | ||
| 113 | ; (limit = size - 1). | ||
| 114 | ; The base address of the specified descriptor is set. | ||
| 115 | ; The access field of the specified descriptor is set. | ||
| 116 | ; | ||
| 117 | ; ENTRY BX = selector | ||
| 118 | ; ES:0 = descriptor table to use | ||
| 119 | ; CX = limit | ||
| 120 | ; AL, DX = 24 bit base address | ||
| 121 | ; AH = access rights byte | ||
| 122 | ; EXIT None | ||
| 123 | ; USES Flags, other regs preserved | ||
| 124 | ; | ||
| 125 | ; WARNING This code only works on a 286. It can be called in | ||
| 126 | ; either mode. | ||
| 127 | |||
| 128 | public SetDescInfo | ||
| 129 | SetDescInfo proc near | ||
| 130 | push bx ; save selector | ||
| 131 | and bl,SEL_LOW_MASK | ||
| 132 | |||
| 133 | ; fill in the limit field | ||
| 134 | |||
| 135 | mov es:[bx],cx | ||
| 136 | |||
| 137 | ; fill in base address | ||
| 138 | |||
| 139 | mov es:[bx + 2],dx | ||
| 140 | mov es:[bx + 4],al | ||
| 141 | |||
| 142 | ; fill in access rights byte | ||
| 143 | |||
| 144 | mov es:[bx + 5],ah | ||
| 145 | pop bx | ||
| 146 | ret | ||
| 147 | SetDescInfo endp | ||
| 148 | |||
| 149 | |||
| 150 | ;** SetSegDesc - set segment descriptor information | ||
| 151 | ; | ||
| 152 | ; The limit field of a specified descriptor is set. | ||
| 153 | ; (limit = size - 1). | ||
| 154 | ; The base address of the specified descriptor is set. | ||
| 155 | ; The access field of the specified descriptor is set. | ||
| 156 | ; | ||
| 157 | ; ENTRY BX = selector | ||
| 158 | ; ES:0 = descriptor table to use | ||
| 159 | ; CX = size | ||
| 160 | ; AL, DX = 24 bit base address | ||
| 161 | ; AH = access rights byte | ||
| 162 | ; EXIT None | ||
| 163 | ; USES Flags, other regs preserved | ||
| 164 | ; | ||
| 165 | ; WARNING This code only works on a 286. It can be called in | ||
| 166 | ; either mode. | ||
| 167 | |||
| 168 | public SetSegDesc | ||
| 169 | SetSegDesc proc near | ||
| 170 | dec cx ; convert size to limit | ||
| 171 | call SetDescInfo ; set descriptor information | ||
| 172 | inc cx ; restore size | ||
| 173 | ret | ||
| 174 | SetSegDesc endp | ||
| 175 | |||
| 176 | |||
| 177 | ;** SegTo24 - convert segment to 24 bit physical address | ||
| 178 | ; | ||
| 179 | ; The real mode segment number is convert to a 24 bit addr | ||
| 180 | ; | ||
| 181 | ; ENTRY AX = segment | ||
| 182 | ; EXIT AL, DX = 24 bit physical address | ||
| 183 | ; USES AH, Flags, other regs preserved | ||
| 184 | ; | ||
| 185 | ; WARNING This code only works on a 286, it can be called in | ||
| 186 | ; either mode. | ||
| 187 | public SegTo24 | ||
| 188 | SegTo24 proc near | ||
| 189 | mov dl,ah | ||
| 190 | shr dl,4 ; DH = high byte of 24 bit addr | ||
| 191 | xchg ax,dx ; AH = high byte, DX = segment | ||
| 192 | shl dx,4 ; DX = low word of 24 bit addr | ||
| 193 | ret | ||
| 194 | SegTo24 endp | ||
| 195 | |||
| 196 | |||
| 197 | ;** SegOffTo24 - convert seg:off to 24 bit physical address | ||
| 198 | ; | ||
| 199 | ; The specified real mode segment:offset is converted to | ||
| 200 | ; a 24 bit physical address. | ||
| 201 | ; | ||
| 202 | ; ENTRY AX = segment | ||
| 203 | ; DX = offset | ||
| 204 | ; EXIT AL, DX = 24 bit physical address | ||
| 205 | ; USES AH, Flags, other regs preserved. | ||
| 206 | ; | ||
| 207 | ; WARNING This code only works on a 286. It can be called in | ||
| 208 | ; either mode. | ||
| 209 | |||
| 210 | public SegOffTo24 | ||
| 211 | SegOffTo24 proc near | ||
| 212 | push cx | ||
| 213 | |||
| 214 | ; Convert AX:DX into 24 bit addr in AL, DX | ||
| 215 | |||
| 216 | mov ch,ah | ||
| 217 | shl ax,4 | ||
| 218 | shr ch,4 ; CH = high byte | ||
| 219 | add dx,ax ; DX = low word | ||
| 220 | mov al,ch ; AL = high byte | ||
| 221 | adc al,0 ; propagate cy from low word | ||
| 222 | |||
| 223 | pop cx | ||
| 224 | ret | ||
| 225 | SegOffTo24 endp | ||
| 226 | |||
| 227 | |||
| 228 | page | ||
| 229 | ;****************************************************************************** | ||
| 230 | ; IS286 - return type of processor (286 vs. 8088/86). 386 returns 286. | ||
| 231 | ; This routine relies on the documented behaviour of the PUSH SP | ||
| 232 | ; instruction as executed on the various processors. This routine | ||
| 233 | ; may be called from any mode on any processor, provided a proper | ||
| 234 | ; stack exists. | ||
| 235 | ; | ||
| 236 | ; ENTRY: (none) | ||
| 237 | ; EXIT: ZF = 1 if 8088/86 | ||
| 238 | ; ZF = 0 if 286/386 | ||
| 239 | ; USED: flags | ||
| 240 | ; STACK: 6 bytes | ||
| 241 | ;------------------------------------------------------------------------------ | ||
| 242 | public Is286 | ||
| 243 | Is286 proc near | ||
| 244 | push bp | ||
| 245 | push sp | ||
| 246 | mov bp,sp | ||
| 247 | cmp bp,[bp] ; compare SP with saved SP | ||
| 248 | pop bp ; clean SP off stack | ||
| 249 | pop bp ; restore BP | ||
| 250 | ret ; *** RETURN *** | ||
| 251 | Is286 endp | ||
| 252 | page | ||
| 253 | ;****************************************************************************** | ||
| 254 | ; Is386 - return type of processor (386 vs. 8088/86/286). | ||
| 255 | ; This routine relies on Intel-approved code that takes advantage | ||
| 256 | ; of the documented behavior of the high nibble of the flag word | ||
| 257 | ; in the REAL MODE of the various processors. The MSB (bit 15) | ||
| 258 | ; is always a one on the 8086 and 8088 and a zero on the 286 and | ||
| 259 | ; 386. Bit 14 (NT flag) and bits 13/12 (IOPL bit field) are | ||
| 260 | ; always zero on the 286, but can be set on the 386. | ||
| 261 | ; | ||
| 262 | ; For future compatibility of this test, it is strongly recommended | ||
| 263 | ; that this specific instruction sequence be used. The exit codes | ||
| 264 | ; can of course be changed to fit a particular need. | ||
| 265 | ; | ||
| 266 | ; CALLABLE FROM REAL MODE ONLY - FAR ROUTINE | ||
| 267 | ; | ||
| 268 | ; ENTRY: (none) | ||
| 269 | ; EXIT: STC if 8088/86/286 | ||
| 270 | ; CLC if 386 | ||
| 271 | ; USED: none | ||
| 272 | ; STACK: 6 bytes | ||
| 273 | ;------------------------------------------------------------------------------ | ||
| 274 | public Is386 | ||
| 275 | Is386 proc FAR | ||
| 276 | push ax | ||
| 277 | pushf ; save entry flags | ||
| 278 | ; | ||
| 279 | xor ax,ax ; 0000 into AX | ||
| 280 | push ax | ||
| 281 | popf ; try to put that in the flags | ||
| 282 | pushf | ||
| 283 | pop ax ; look at what really went into flags | ||
| 284 | test ax,08000h ;Q: was high bit set ? | ||
| 285 | jnz IsNot386_exit ; Y: 8086/8088 | ||
| 286 | mov ax,07000h ; N: try to set the NT/IOPL bits | ||
| 287 | push ax | ||
| 288 | popf ; ... in the flags | ||
| 289 | pushf | ||
| 290 | pop ax ; look at actual flags | ||
| 291 | test ax,07000h ; Q: any high bits set ? | ||
| 292 | jz IsNot386_exit ; N: 80286 | ||
| 293 | ; Y: 80386 | ||
| 294 | Is386_exit: | ||
| 295 | popf ; restore flags | ||
| 296 | clc ; 386 | ||
| 297 | jmp short I386_exit ; and leave | ||
| 298 | |||
| 299 | IsNot386_exit: | ||
| 300 | popf ; restore flags | ||
| 301 | stc ; not a 386 | ||
| 302 | |||
| 303 | I386_exit: | ||
| 304 | pop ax | ||
| 305 | ret ; *** RETURN *** | ||
| 306 | |||
| 307 | Is386 endp | ||
| 308 | |||
| 309 | LAST ends | ||
| 310 | |||
| 311 | |||
| 312 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/I386.ASM b/v4.0/src/MEMM/MEMM/I386.ASM new file mode 100644 index 0000000..6065dbe --- /dev/null +++ b/v4.0/src/MEMM/MEMM/I386.ASM | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE i386.asm - Support Routines for protected mode system | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: i386.asm - Support Routines for protected mode system | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/21/86 0.02 Added clds just in case | ||
| 29 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 30 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; DESCRIPTION | ||
| 35 | ; | ||
| 36 | ; These routines manage the various 386 memory management | ||
| 37 | ; tables and manipulate descriptors and selectors. | ||
| 38 | ; | ||
| 39 | ; All the routines which manipulate descriptors are callable | ||
| 40 | ; in both real and protected mode. | ||
| 41 | ; | ||
| 42 | ; In general all registers are preserved. | ||
| 43 | ; | ||
| 44 | ; The following routines are provided: | ||
| 45 | ; | ||
| 46 | ; SetPageEntry - set up an entry in a Page Directory on Page | ||
| 47 | ; Table. | ||
| 48 | ; | ||
| 49 | ; GetPageEntry - retrieve a page dir/page table entry. | ||
| 50 | ; | ||
| 51 | ; InitPages - initialize page directory and page table. | ||
| 52 | ; | ||
| 53 | ; PageDirOff - convert 32 bit addr to page dir entry offset | ||
| 54 | ; | ||
| 55 | ; PageTableOff - convert 32 bit addr to page table entry offset | ||
| 56 | ; | ||
| 57 | ; WARNING This code is 386 specific, it will NOT run on an 8088. | ||
| 58 | ; | ||
| 59 | ;****************************************************************************** | ||
| 60 | .lfcond ; list false conditionals | ||
| 61 | .386p | ||
| 62 | ; | ||
| 63 | include VDMseg.inc | ||
| 64 | include VDMsel.inc | ||
| 65 | include desc.inc | ||
| 66 | include page.inc | ||
| 67 | |||
| 68 | ;****************************************************************************** | ||
| 69 | ; E X T E R N A L S | ||
| 70 | ;****************************************************************************** | ||
| 71 | LAST SEGMENT | ||
| 72 | extrn SegTo24:near | ||
| 73 | LAST ENDS | ||
| 74 | |||
| 75 | |||
| 76 | ;****************************************************************************** | ||
| 77 | ; S E G M E N T D E F I N I T I O N S | ||
| 78 | ;****************************************************************************** | ||
| 79 | LAST SEGMENT | ||
| 80 | |||
| 81 | assume cs:LAST,ds:DGROUP,es:DGROUP | ||
| 82 | |||
| 83 | ;** SetGateDesc - set up Gate Descriptor entry | ||
| 84 | ; | ||
| 85 | ; | ||
| 86 | ; ENTRY DX,AX = 32 bit offset of target routine | ||
| 87 | ; CX = target code segment selector | ||
| 88 | ; ES:[DI] = points to table entry | ||
| 89 | ; BL = access bits | ||
| 90 | ; EXIT descriptor set. | ||
| 91 | ; USES Flags, other regs preserved | ||
| 92 | ; | ||
| 93 | ; WARNING This code only works on a 386. It can be called in | ||
| 94 | ; either mode. | ||
| 95 | |||
| 96 | public SetGateDesc | ||
| 97 | SetGateDesc proc near | ||
| 98 | ; | ||
| 99 | push ax | ||
| 100 | push di | ||
| 101 | ; | ||
| 102 | cld ; stings foward | ||
| 103 | ; | ||
| 104 | stosw ; store low word of offset | ||
| 105 | mov ax,cx | ||
| 106 | stosw ; store selector | ||
| 107 | mov al,0 | ||
| 108 | mov ah,bl | ||
| 109 | stosw ; store access rights | ||
| 110 | mov ax,dx | ||
| 111 | stosw ; store high word of offset | ||
| 112 | ; | ||
| 113 | pop di | ||
| 114 | pop ax | ||
| 115 | ret | ||
| 116 | SetGateDesc endp | ||
| 117 | |||
| 118 | |||
| 119 | ;** SetPageEntry - set up entry in Page Directory or Page Table | ||
| 120 | ; | ||
| 121 | ; | ||
| 122 | ; ENTRY DX,AX = 32 bit address of page or page table | ||
| 123 | ; ES:[DI] = page directory or table entry to set | ||
| 124 | ; BX = access/status bits ( bits 0 - 11 ) | ||
| 125 | ; EXIT ES:[DI] = next page directory or table entry | ||
| 126 | ; USES Flags, other regs preserved | ||
| 127 | ; | ||
| 128 | ; WARNING This code only works on a 386. It can be called in | ||
| 129 | ; either mode. | ||
| 130 | |||
| 131 | public SetPageEntry | ||
| 132 | SetPageEntry proc near | ||
| 133 | ; | ||
| 134 | push ax | ||
| 135 | ; | ||
| 136 | cld ; strings foward | ||
| 137 | ; | ||
| 138 | and bx,0FFFh ; turn off any bits in address range | ||
| 139 | or ax,bx ; mov status bits into AX | ||
| 140 | stosw ; store status and addr bits 12 - 15 | ||
| 141 | mov ax,dx ; AX = addr bits 16-31 | ||
| 142 | stosw ; store addr bits 16-31 | ||
| 143 | ; | ||
| 144 | pop ax | ||
| 145 | ret | ||
| 146 | SetPageEntry endp | ||
| 147 | |||
| 148 | |||
| 149 | ;** GetPageEntry - up entry in Page Directory or Page Table | ||
| 150 | ; | ||
| 151 | ; ENTRY ES:[DI] = page directory or table entry | ||
| 152 | ; EXIT DX,AX = 32 bit address of page or page table | ||
| 153 | ; BX = access/status bits (bits 0 - 11). | ||
| 154 | ; USES Flags, other regs preserved | ||
| 155 | ; | ||
| 156 | ; WARNING This code only works on a 386. It can be called in | ||
| 157 | ; either mode. | ||
| 158 | |||
| 159 | public GetPageEntry | ||
| 160 | GetPageEntry proc near | ||
| 161 | ; | ||
| 162 | mov ax,ES:[DI] ; AX = low word of entry | ||
| 163 | mov bx,ax ; get access/status rights bits | ||
| 164 | and bx,00FFFh ; turn off address bits | ||
| 165 | ; | ||
| 166 | and ax,0F000h ; turn off status bits | ||
| 167 | mov dx,ES:[DI+2] ; get high word of addr | ||
| 168 | ; | ||
| 169 | ret | ||
| 170 | GetPageEntry endp | ||
| 171 | |||
| 172 | |||
| 173 | ;** PageDirOff - convert 32 bit linear address to page directory offset | ||
| 174 | ; | ||
| 175 | ; | ||
| 176 | ; ENTRY EAX = 32 bit linear address | ||
| 177 | ; EXIT DI = offset in page dir to appropriate entry | ||
| 178 | ; USES Flags, other regs preserved | ||
| 179 | ; | ||
| 180 | ; WARNING This code only works on a 386. It can be called in | ||
| 181 | ; either mode. | ||
| 182 | |||
| 183 | public PageDirOff | ||
| 184 | PageDirOff proc near | ||
| 185 | ; | ||
| 186 | db 66h | ||
| 187 | push bx ; push EBX | ||
| 188 | |||
| 189 | db 66h | ||
| 190 | mov bx,ax ; EBX = EAX | ||
| 191 | |||
| 192 | db 66h | ||
| 193 | shr bx,22 ; EBX[0:9] = EBX[22:31] = high 10 bits | ||
| 194 | shl bx,2 ; *4 for dword indexing into table | ||
| 195 | |||
| 196 | mov di,bx ; DI = dir offset | ||
| 197 | |||
| 198 | db 66h | ||
| 199 | pop bx ; pop EBX | ||
| 200 | ; | ||
| 201 | ret | ||
| 202 | PageDirOff endp | ||
| 203 | |||
| 204 | |||
| 205 | ;** PageTableOff - convert 32 bit linear address to page table offset | ||
| 206 | ; | ||
| 207 | ; | ||
| 208 | ; ENTRY EAX = 32 bit linear address | ||
| 209 | ; EXIT DI = offset in page table to appropriate entry | ||
| 210 | ; USES Flags, other regs preserved | ||
| 211 | ; | ||
| 212 | ; WARNING This code only works on a 386. It can be called in | ||
| 213 | ; either mode. | ||
| 214 | |||
| 215 | public PageTableOff | ||
| 216 | PageTableOff proc near | ||
| 217 | ; | ||
| 218 | db 66h | ||
| 219 | push bx ; push EBX | ||
| 220 | |||
| 221 | db 66h | ||
| 222 | mov bx,ax ; mov EBX,EAX | ||
| 223 | |||
| 224 | db 66h | ||
| 225 | shr bx,12 ; EBX[0:9] = EBX[12:21] = middle 10 bits | ||
| 226 | and bx,3FFh ; only EBX[0:9] | ||
| 227 | shl bx,2 ; *4 for dword indexing into table | ||
| 228 | |||
| 229 | mov di,bx ; DI has table offset | ||
| 230 | |||
| 231 | db 66h | ||
| 232 | pop bx ; pop EBX | ||
| 233 | ; | ||
| 234 | ret | ||
| 235 | PageTableOff endp | ||
| 236 | |||
| 237 | |||
| 238 | LAST ends | ||
| 239 | |||
| 240 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/INIT.ASM b/v4.0/src/MEMM/MEMM/INIT.ASM new file mode 100644 index 0000000..44ab1c7 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INIT.ASM | |||
| @@ -0,0 +1,1123 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE INIT - initialization code for MEMM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: INIT - initialization code for MEMM | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: May 24,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 05/24/86 Original | ||
| 27 | ; 06/18/86 0.01 Added AUTO as a valid config line parameter. | ||
| 28 | ; 06/25/86 0.02 Added call to debug init. | ||
| 29 | ; 06/27/86 0.02 Check for Mx length = 2 and only 2 | ||
| 30 | ; 06/28/86 0.02 Change name from MEMM386 to MEMM | ||
| 31 | ; 06/29/86 0.02 Size > 8192 were used instead of converted | ||
| 32 | ; to 256 | ||
| 33 | ; 07/03/86 0.04 Added TEXT_Seg | ||
| 34 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 35 | ; 07/06/86 0.04 moved init messages to LAST | ||
| 36 | ; 07/10/86 0.05 added int15 patch and int67 patch here | ||
| 37 | ; 07/20/88 removed debugger codes (pc) | ||
| 38 | ; 07/29/88 removed ON/OFF/AUTO support | ||
| 39 | ; | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; Functional Description: | ||
| 42 | ; This module allocates the pool of extended memory to be used for | ||
| 43 | ; expanded memory, then call routines to initialize the data structures | ||
| 44 | ; for EMM and VDM. | ||
| 45 | ; | ||
| 46 | ;****************************************************************************** | ||
| 47 | .lfcond | ||
| 48 | .386p | ||
| 49 | page | ||
| 50 | ;****************************************************************************** | ||
| 51 | ; P U B L I C D E C L A R A T I O N S | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; | ||
| 54 | public Init_MEMM386 | ||
| 55 | |||
| 56 | public pool_size | ||
| 57 | public msg_flag | ||
| 58 | public Active_Status | ||
| 59 | public Auto_Mode | ||
| 60 | public dos_version | ||
| 61 | public TEXT_Seg | ||
| 62 | public STACK_Seg | ||
| 63 | public GDT_Seg | ||
| 64 | public IDT_Seg | ||
| 65 | public TSS_Seg | ||
| 66 | public driver_end | ||
| 67 | public powr10 | ||
| 68 | |||
| 69 | |||
| 70 | page | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; L O C A L C O N S T A N T S | ||
| 73 | ;****************************************************************************** | ||
| 74 | ; | ||
| 75 | include vdmseg.inc | ||
| 76 | include vdmsel.inc ; for Deb386 Init | ||
| 77 | include desc.inc ; " " " | ||
| 78 | include emm386.inc | ||
| 79 | include driver.equ | ||
| 80 | include driver.str | ||
| 81 | include ascii_sm.equ | ||
| 82 | ; | ||
| 83 | ; maximum value for SIZE parameter | ||
| 84 | ; | ||
| 85 | MAX_SIZE equ 32 * 1024 ; 32K => 32Meg | ||
| 86 | |||
| 87 | ; | ||
| 88 | MS_DOS equ 21h | ||
| 89 | PRINT_STRING equ 09h | ||
| 90 | GET_VERSION equ 30h | ||
| 91 | ; | ||
| 92 | FALSE equ 0 | ||
| 93 | TRUE equ not FALSE | ||
| 94 | DOS3X_ADJ equ 1 ; DOS 3.x base memory adjustment | ||
| 95 | |||
| 96 | ; | ||
| 97 | ; macro for printing messages located in LAST segment | ||
| 98 | ; ENTRY: DX = offset LAST:message | ||
| 99 | ; | ||
| 100 | PRINT_MSG macro | ||
| 101 | push ds | ||
| 102 | push seg LAST | ||
| 103 | pop ds ; ds = LAST | ||
| 104 | mov ah,PRINT_STRING | ||
| 105 | int MS_DOS ; output init message | ||
| 106 | pop ds | ||
| 107 | ENDM | ||
| 108 | |||
| 109 | |||
| 110 | ;****************************************************************************** | ||
| 111 | ; E X T E R N A L R E F E R E N C E S | ||
| 112 | ;****************************************************************************** | ||
| 113 | ; | ||
| 114 | ; | ||
| 115 | _DATA segment | ||
| 116 | |||
| 117 | extrn PF_Base:word | ||
| 118 | ; extrn himem_use:byte ;* this is defined in oemproc.asm since it | ||
| 119 | ; deals with memory so oem dependent | ||
| 120 | extrn ext_size:word ; size of extended memory allocated | ||
| 121 | extrn sys_size:word ; size of system memory allocated | ||
| 122 | |||
| 123 | _DATA ends | ||
| 124 | |||
| 125 | ABS0 segment use16 at 0 | ||
| 126 | org 4*15h ; int 15h vector | ||
| 127 | i15_vector dw 0 | ||
| 128 | dw 0 | ||
| 129 | |||
| 130 | org 4*67h ; int 67h vector | ||
| 131 | i67_vector dw 0 | ||
| 132 | dw 0 | ||
| 133 | ABS0 ends | ||
| 134 | |||
| 135 | ; | ||
| 136 | R_CODE segment | ||
| 137 | extrn i15_Entry:near ; int15h patch code | ||
| 138 | extrn EMM_rEntry:near ; int67h patch code | ||
| 139 | extrn i15_Old:word ; old int15 vector | ||
| 140 | R_CODE ends | ||
| 141 | |||
| 142 | ; | ||
| 143 | _TEXT segment | ||
| 144 | |||
| 145 | extrn Inst_chk_f:far ; check for MEMM already installed | ||
| 146 | extrn FarGoVirtual:far ; go to virtual mode | ||
| 147 | extrn get_token:near ; get token from command line | ||
| 148 | |||
| 149 | _TEXT ends | ||
| 150 | ; | ||
| 151 | LAST segment | ||
| 152 | |||
| 153 | extrn VerifyMachine:near | ||
| 154 | extrn InitMess:byte | ||
| 155 | extrn InstallMess:byte | ||
| 156 | extrn ISizeMess:byte | ||
| 157 | extrn ExtSizeMess:byte | ||
| 158 | extrn SysSizeMess:byte | ||
| 159 | extrn PFBAMess:byte | ||
| 160 | extrn ActiveMess:byte | ||
| 161 | extrn InactiveMess:byte | ||
| 162 | extrn AutoMess:byte | ||
| 163 | extrn InvParm:byte | ||
| 164 | extrn InvPFBA:byte | ||
| 165 | extrn InvMRA:byte | ||
| 166 | extrn Adj_Size:byte | ||
| 167 | extrn InsfMem:byte | ||
| 168 | extrn Incorrect_DOS:byte | ||
| 169 | extrn Incorrect_PRT:byte | ||
| 170 | extrn Already_Inst:byte | ||
| 171 | extrn No_PF_Avail:byte | ||
| 172 | extrn PFWarning:byte | ||
| 173 | |||
| 174 | extrn Is386:far ; check for 386 | ||
| 175 | extrn EMM_Init:near ; initialization for EMM data structs | ||
| 176 | extrn AllocMem:near ; allocate extended memory routine | ||
| 177 | extrn InitTab:near ; OEM init code for tables | ||
| 178 | extrn VDM_Init:near ; initialize VDM | ||
| 179 | extrn DeallocMem:near ; deallocate hi/extended memory routine | ||
| 180 | |||
| 181 | extrn find_phys_pages:near ; find the mappable pages in 0-1M range | ||
| 182 | extrn exclude_segments:near ; exclude segments within a range | ||
| 183 | extrn estb_mach_state:near ; establish machine environment | ||
| 184 | |||
| 185 | LAST ends | ||
| 186 | |||
| 187 | page | ||
| 188 | ;****************************************************************************** | ||
| 189 | ; S E G M E N T D E F I N I T I O N | ||
| 190 | ;****************************************************************************** | ||
| 191 | |||
| 192 | page | ||
| 193 | ;****************************************************************************** | ||
| 194 | ; Data segment | ||
| 195 | ;****************************************************************************** | ||
| 196 | _DATA segment | ||
| 197 | ; | ||
| 198 | dos_version db 0h ; MS-DOS version | ||
| 199 | pool_size dw 0 ; size of EMM Pages Pool in kbytes | ||
| 200 | msg_flag dw 0 ; Message flag byte | ||
| 201 | |||
| 202 | driver_end dw 0 ; end of driver -> driver brk address | ||
| 203 | dw seg LAST | ||
| 204 | powr10 dw 1,10,100,1000,10000 | ||
| 205 | max_arg_len equ 11 ; maximum length of argument on cmd line | ||
| 206 | arg_str db max_arg_len+1 dup(0) | ||
| 207 | ; | ||
| 208 | ; Active_Status is used to signal the termination condition for the | ||
| 209 | ; driver. After the driver installs, Active_Status holds the | ||
| 210 | ; current status (ON or OFF). | ||
| 211 | ; Auto_Mode is set when MEMM is running in AUTO mode. | ||
| 212 | ; | ||
| 213 | Active_Status db 0FFh ; 0 => OFF , non-zero => ON | ||
| 214 | Auto_Mode db 0h ; non-zero => auto mode | ||
| 215 | |||
| 216 | ; | ||
| 217 | ; The following pointers are segment addresses for various segments | ||
| 218 | ; | ||
| 219 | TEXT_Seg dw seg _TEXT ; current segment for _TEXT | ||
| 220 | STACK_Seg dw seg STACK ; current segment for STACK | ||
| 221 | GDT_Seg dw seg GDT ; current segment for GDT | ||
| 222 | IDT_Seg dw seg IDT ; current segment for IDT | ||
| 223 | TSS_Seg dw seg TSS ; current segment for TSS | ||
| 224 | |||
| 225 | _DATA ends | ||
| 226 | |||
| 227 | |||
| 228 | ;****************************************************************************** | ||
| 229 | ; | ||
| 230 | ; Code Segments | ||
| 231 | ; | ||
| 232 | ;****************************************************************************** | ||
| 233 | ; | ||
| 234 | _TEXT segment | ||
| 235 | assume cs:_TEXT | ||
| 236 | |||
| 237 | |||
| 238 | ;************************************************************************* | ||
| 239 | ; | ||
| 240 | ; get_token_far call get_token which must be near since it is | ||
| 241 | ; also part of a .COM file | ||
| 242 | ; | ||
| 243 | ;************************************************************************* | ||
| 244 | get_token_far proc far | ||
| 245 | call get_token | ||
| 246 | ret | ||
| 247 | get_token_far endp | ||
| 248 | _TEXT ends | ||
| 249 | |||
| 250 | LAST segment | ||
| 251 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 252 | |||
| 253 | page | ||
| 254 | ;****************************************************************************** | ||
| 255 | ; Init - Initialization routine for MEMM. | ||
| 256 | ; | ||
| 257 | ; ENTRY: DS:BX pts to INIT request header. | ||
| 258 | ; | ||
| 259 | ; EXIT: AX = INIT status for request header | ||
| 260 | ; if NO errors : | ||
| 261 | ; MEMM initialized. | ||
| 262 | ; if [ON] parameter specified on command line | ||
| 263 | ; exit in Virtual mode and MEMM active. | ||
| 264 | ; else ( [OFF] parameter specified ) | ||
| 265 | ; exit in Real mode and MEMM inactive. | ||
| 266 | ; if errors: | ||
| 267 | ; Real Mode | ||
| 268 | ; USED: none | ||
| 269 | ; | ||
| 270 | ;****************************************************************************** | ||
| 271 | Init_MEMM386 proc far | ||
| 272 | push bx ; BP+10 | ||
| 273 | push dx ; BP+8 | ||
| 274 | push bp ; BP+6 | ||
| 275 | push di ; BP+4 | ||
| 276 | push ds ; BP+2 | ||
| 277 | push es ; BP+0 | ||
| 278 | mov bp,sp | ||
| 279 | ; | ||
| 280 | ; set up DS = DGROUP and ES:BX to request header | ||
| 281 | ; | ||
| 282 | push ds | ||
| 283 | pop es ; ES:BX pts to req hdr | ||
| 284 | mov ax,seg DGROUP | ||
| 285 | mov ds,ax ; DS = DGROUP | ||
| 286 | |||
| 287 | ; | ||
| 288 | ; initialize break address to not install | ||
| 289 | ; | ||
| 290 | mov word ptr ES:[bx.BRK_OFF],0000 ; set it | ||
| 291 | mov ax,seg R_CODE ; get brk addr segment | ||
| 292 | inc ax ; reserve dos link pointer | ||
| 293 | mov ES:[bx.BRK_SEG],ax ; break addr = cs - don't install | ||
| 294 | mov byte ptr es:[bx.NUM_UNITS],0 ; 0 - don't install | ||
| 295 | ; | ||
| 296 | ; verify that MEMM is not already installed | ||
| 297 | ; | ||
| 298 | call Inst_chk_f | ||
| 299 | or ax,ax ; q: already installed? | ||
| 300 | jz chk_pt ; n: go check processor type | ||
| 301 | or [msg_flag],INS_ERR_MSG ; y: error | ||
| 302 | jmp IE_exit ; quit | ||
| 303 | ; | ||
| 304 | ; verify processor type | ||
| 305 | ; | ||
| 306 | chk_pt: | ||
| 307 | call Is386 ;Q: is this a 386 ? | ||
| 308 | jnz inc_prc ; N: no, set error | ||
| 309 | ; Y: check machine type | ||
| 310 | ; | ||
| 311 | ; verify machine type | ||
| 312 | ; | ||
| 313 | chk_mt: | ||
| 314 | stc ; Indicate this is verify from INIT | ||
| 315 | call VerifyMachine ;Q: is this a good machine to run on? | ||
| 316 | jnc chk_dos ; y: ok so far. go check dos version | ||
| 317 | inc_prc: | ||
| 318 | or [msg_flag],INC_PRC_MSG ; n: incorrect processor type | ||
| 319 | jmp IE_exit ; quit | ||
| 320 | ; | ||
| 321 | ; get DOS version - accept >= 3.1 | ||
| 322 | ; | ||
| 323 | chk_dos: | ||
| 324 | push bx | ||
| 325 | mov ah,GET_VERSION | ||
| 326 | int MS_DOS ; get dos version # | ||
| 327 | mov [dos_version],al ; save it. | ||
| 328 | pop bx | ||
| 329 | cmp ax,4 ;Q: DOS 4.00 | ||
| 330 | je IE_parse ; Y: OK - continue install | ||
| 331 | cmp al,3 ;Q: DOS 3.xx ? | ||
| 332 | jl IE_dos_err ; N: return error | ||
| 333 | cmp ah,10 ;Q: current DOS >= 3.10 ? | ||
| 334 | jae IE_parse ; Y: OK - continue install | ||
| 335 | IE_dos_err: | ||
| 336 | or [msg_flag],INC_DOS_MSG ; N: set error and exit | ||
| 337 | jmp IE_exit | ||
| 338 | ; | ||
| 339 | ; parse command line for | ||
| 340 | ; (1) requested size for expanded memory | ||
| 341 | ; (2) page frame base address | ||
| 342 | ; (3) I/O addresses for board emulations | ||
| 343 | ; (4) Driver exit mode (virtual or real) | ||
| 344 | ; | ||
| 345 | IE_parse: | ||
| 346 | les di,ES:[bx.ARG_PTR] ; ES:DI pts to config.sys command | ||
| 347 | ; line parameters | ||
| 348 | call parser ; parse the parameters | ||
| 349 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 350 | jz IE_mach_state ; N: go to establish machine state | ||
| 351 | jmp IE_exit ; Y: exit with error | ||
| 352 | |||
| 353 | IE_mach_state: | ||
| 354 | ; | ||
| 355 | push ds | ||
| 356 | pop es ; ES:DGROUP | ||
| 357 | ; | ||
| 358 | call estb_mach_state ; since we are an environment, we need | ||
| 359 | ; to find the state we exist in right | ||
| 360 | ; now and maintain it. | ||
| 361 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 362 | jz IE_find_phys ; N:go to find physical pages | ||
| 363 | jmp IE_exit ; Y: exit with error | ||
| 364 | ; | ||
| 365 | IE_find_phys: | ||
| 366 | call find_phys_pages ; find mappable physical pages | ||
| 367 | ; and page frame | ||
| 368 | test [msg_flag],KILLER_MSG ;Q: any killer messages | ||
| 369 | jz IE_alloc ; N: Go to find and allocate log. pages | ||
| 370 | jmp IE_exit ; Y: exit with error | ||
| 371 | ; | ||
| 372 | ; find and allocate logical emm pages | ||
| 373 | ; | ||
| 374 | IE_alloc: | ||
| 375 | call AllocMem | ||
| 376 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 377 | jz IE_InitEMM ; N: init EMM | ||
| 378 | jmp IE_exit ; Y: exit | ||
| 379 | ; | ||
| 380 | ; init EMM data | ||
| 381 | ; | ||
| 382 | IE_InitEMM: | ||
| 383 | |||
| 384 | call EMM_Init | ||
| 385 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 386 | jz IE_InitVDM ; N: init VDM | ||
| 387 | jmp IE_exit ; Y: exit | ||
| 388 | ; | ||
| 389 | ; init VDM - GDT,IDT,TSS,Page Tables | ||
| 390 | ; | ||
| 391 | IE_InitVDM: | ||
| 392 | call VDM_Init | ||
| 393 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 394 | jz IE_InitTAB ; N: init TABLES | ||
| 395 | jmp IE_exit ; Y: exit | ||
| 396 | ; | ||
| 397 | ; set up segment pointers to Tables & OEM table init | ||
| 398 | ; | ||
| 399 | IE_InitTAB: | ||
| 400 | call InitTab | ||
| 401 | jnc IE_InitT_Good ;Q: any memory allocation error? | ||
| 402 | or [msg_flag],MEM_ERR_MSG ; Y: Some serious memory error | ||
| 403 | IE_InitT_Good: | ||
| 404 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 405 | jz IE_chkbase ; N: check base memory left | ||
| 406 | jmp IE_exit ; Y: exit | ||
| 407 | ; | ||
| 408 | ; Verify that we will have at least 64k of base memory after MEMM | ||
| 409 | ; is loaded | ||
| 410 | ; | ||
| 411 | IE_chkbase: | ||
| 412 | int 12h ; get base memory size | ||
| 413 | push ax ; save it | ||
| 414 | mov ax,[driver_end] ; get offset of end of MEMM resident | ||
| 415 | add ax,15 ; convert to paragraphs | ||
| 416 | shr ax,4 | ||
| 417 | add ax,[driver_end+2] ; add in segment of brk address | ||
| 418 | add ax,63 ; round up to kbytes (64 paras per K) | ||
| 419 | shr ax,6 ; AX = kbytes to end of MEMM resident | ||
| 420 | add ax,DOS3X_ADJ+64 ; add in dos 3.xx adjustment and 64k | ||
| 421 | pop dx ; get base memory back | ||
| 422 | cmp dx,ax ; q: do we have enough? | ||
| 423 | jae IE_setbrk ; y: continue | ||
| 424 | or [msg_flag],MEM_ERR_MSG ; n: set memory error | ||
| 425 | jmp IE_exit ; and exit | ||
| 426 | |||
| 427 | ; | ||
| 428 | ; set driver break addr in Init Request Header | ||
| 429 | ; | ||
| 430 | IE_setbrk: | ||
| 431 | mov bx,[bp+2] ; get entry DS from stack | ||
| 432 | mov es,bx | ||
| 433 | mov bx,[bp+10] ; ES:BX pts to req hdr | ||
| 434 | mov ax,[driver_end] ; get brk addr offset | ||
| 435 | mov ES:[bx.BRK_OFF],ax ; set it | ||
| 436 | mov ax,[driver_end+2] ; get brk addr segment | ||
| 437 | mov ES:[bx.BRK_SEG],ax ; set it | ||
| 438 | ; | ||
| 439 | ; check exit status of VDM/MEMM (now with lim 4.0) exit must be ON | ||
| 440 | ; | ||
| 441 | ; cmp [Auto_Mode],0 ;Q: exit in Auto mode ? | ||
| 442 | ; je IE_chkOFF ; N: then continue | ||
| 443 | ; mov [Active_Status],0 ; Y: exit in OFF state | ||
| 444 | ;IE_chkOFF: | ||
| 445 | ; cmp [Active_Status],0 ;Q: exit in real mode - OFF | ||
| 446 | ; je IE_Exit ; Y: continue | ||
| 447 | |||
| 448 | ; Initialize DEBX_GSEL GDT Selector and Deb386 | ||
| 449 | ; | ||
| 450 | push ds | ||
| 451 | push es | ||
| 452 | push ax | ||
| 453 | push bx | ||
| 454 | push cx | ||
| 455 | push si | ||
| 456 | push di | ||
| 457 | |||
| 458 | push [IDT_Seg] | ||
| 459 | pop es ; ES:DI <-- IDT | ||
| 460 | push [GDT_Seg] | ||
| 461 | pop ds ; DS:SI <-- GDT | ||
| 462 | mov bx, DEBX_GSEL | ||
| 463 | and bl, SEL_LOW_MASK | ||
| 464 | mov word ptr [bx], 1800h ; Limit = 20M | ||
| 465 | mov word ptr [bx + 2], 0 | ||
| 466 | mov byte ptr [bx + 4], 0 ; Base = 0 | ||
| 467 | mov byte ptr [bx + 5], D_DATA0 ; Ring 0 Data | ||
| 468 | mov byte ptr [bx + 6], 80h ; Page Granularity | ||
| 469 | |||
| 470 | mov ax, 4400h ; Initialize Deb386 | ||
| 471 | mov bx, DEBX_GSEL ; BIG selector for all addresses | ||
| 472 | mov cx, DEB1_GSEL ; start of 5 working Selector | ||
| 473 | xor si, si | ||
| 474 | xor di, di | ||
| 475 | int 68h | ||
| 476 | |||
| 477 | pop di | ||
| 478 | pop si | ||
| 479 | pop cx | ||
| 480 | pop bx | ||
| 481 | pop ax | ||
| 482 | pop es | ||
| 483 | pop ds | ||
| 484 | |||
| 485 | call FarGoVirtual ; N: go into virtual mode | ||
| 486 | |||
| 487 | ; | ||
| 488 | ; exit - display status messages and set exit status | ||
| 489 | ; | ||
| 490 | IE_exit: | ||
| 491 | ; | ||
| 492 | ; display signon message first | ||
| 493 | ; | ||
| 494 | mov dx,offset LAST:InitMess | ||
| 495 | PRINT_MSG | ||
| 496 | ; | ||
| 497 | ; check for messages to display | ||
| 498 | ; | ||
| 499 | IE_Install: | ||
| 500 | mov cx,MAX_MSG ; number of potential msgs | ||
| 501 | mov si,offset msg_tbl ; table of messages | ||
| 502 | m_loop: | ||
| 503 | test [msg_flag],01 ; q:is this one set? | ||
| 504 | jz m_inc_ptr ; n: increment table pointer | ||
| 505 | mov dx,cs:[si] ; y: display message | ||
| 506 | PRINT_MSG | ||
| 507 | cmp cx,KILL_MSG ; q: is this one a killer? | ||
| 508 | jbe m_inc_ptr ; n: continue | ||
| 509 | jmp IE_not_installed ; y: don't install | ||
| 510 | m_inc_ptr: | ||
| 511 | inc si ; increment msg table ptr | ||
| 512 | inc si | ||
| 513 | shr [msg_flag],1 ; look for next flag | ||
| 514 | loop m_loop | ||
| 515 | ; | ||
| 516 | mov ax,[pool_size] ; size of EMM page pool in Kbytes | ||
| 517 | mov di,offset LAST:ISizeMess; store decimal size in ASCII here. | ||
| 518 | call b2asc10 ; convert to ASCII... | ||
| 519 | ; | ||
| 520 | mov ax,[ext_size] | ||
| 521 | IFNDEF NOHIMEM | ||
| 522 | add ax,[hi_size] | ||
| 523 | endif | ||
| 524 | mov di,offset LAST:ExtSizeMess ; store decimal size of ext/hi alloc | ||
| 525 | ; here | ||
| 526 | call b2asc10 | ||
| 527 | |||
| 528 | mov ax,[sys_size] | ||
| 529 | mov di,offset LAST:SysSizeMess ; system memory allocated | ||
| 530 | call b2asc10 | ||
| 531 | ; | ||
| 532 | mov ax,[PF_Base] ; page frame base addr | ||
| 533 | shr ax,8 ; shift right to get significant digits | ||
| 534 | mov di,offset LAST:PFBAMess+1; where to put ascii base address | ||
| 535 | base_loop: | ||
| 536 | push ax ; save all digits | ||
| 537 | and ax,0fh ; get one digit | ||
| 538 | cmp ax,9 ; q: digit <=9 | ||
| 539 | jbe skip_dig_adj ; y: don't adjust | ||
| 540 | add ax,'A'-':' | ||
| 541 | skip_dig_adj: | ||
| 542 | add ax,'0' ; make it ascii | ||
| 543 | mov CS:[di],al ; store in message | ||
| 544 | dec di ; update pointer | ||
| 545 | pop ax ; get all digits back | ||
| 546 | ; shift right for next digit | ||
| 547 | shr ax,4 ; q: done? | ||
| 548 | jnz base_loop ; n: do another | ||
| 549 | ; y: print it | ||
| 550 | mov dx,offset LAST:InstallMess | ||
| 551 | PRINT_MSG | ||
| 552 | ; | ||
| 553 | ; mov dx,offset LAST:AutoMess ; assume AUTO | ||
| 554 | ; cmp [Auto_Mode],0 ;Q: auto mode ? | ||
| 555 | ; jne print_mode ; Y: display message | ||
| 556 | ; mov dx,offset LAST:InactiveMess ; N: assume OFF | ||
| 557 | ; cmp [Active_Status],0 ; q: OFF specified? | ||
| 558 | ; jz print_mode ; y | ||
| 559 | ; mov dx,offset LAST:ActiveMess ; n | ||
| 560 | ;print_mode: | ||
| 561 | ; PRINT_MSG | ||
| 562 | ; | ||
| 563 | ; Ok, now we can patch int15h - must be careful not to install | ||
| 564 | ; patch when Active_Status set, but not in virtual mode | ||
| 565 | ; | ||
| 566 | pushf | ||
| 567 | cli ; clear ints | ||
| 568 | xor ax,ax | ||
| 569 | mov ds,ax ; DS -> 0:0 | ||
| 570 | ASSUME DS:ABS0 | ||
| 571 | les bx,dword ptr [i15_vector] ; DS:BX -> pts to old one | ||
| 572 | mov ax,offset R_CODE:i15_Entry | ||
| 573 | mov [i15_vector],ax ; set new ip | ||
| 574 | mov ax,seg R_CODE ; | ||
| 575 | mov [i15_vector+2],ax ; set new cs | ||
| 576 | mov ds,ax ; DS -> R_CODE | ||
| 577 | ASSUME DS:R_CODE | ||
| 578 | mov [i15_Old],bx ; save old IP | ||
| 579 | mov [i15_Old+2],es ; save old CS | ||
| 580 | popf ; restore IF | ||
| 581 | mov ax,seg DGROUP | ||
| 582 | mov ds,ax ; DS -> dgroup | ||
| 583 | ASSUME DS:DGROUP | ||
| 584 | ; | ||
| 585 | ; now patch int67 for EMM functions | ||
| 586 | ; | ||
| 587 | pushf | ||
| 588 | cli ; clear ints | ||
| 589 | xor ax,ax | ||
| 590 | mov ds,ax ; DS -> 0:0 | ||
| 591 | ASSUME DS:ABS0 | ||
| 592 | mov ax,offset R_CODE:EMM_rEntry | ||
| 593 | mov [i67_vector],ax ; set new ip | ||
| 594 | mov ax,seg R_CODE ; | ||
| 595 | mov [i67_vector+2],ax ; set new cs | ||
| 596 | popf ; restore IF | ||
| 597 | mov ax,seg DGROUP | ||
| 598 | mov ds,ax ; DS -> dgroup | ||
| 599 | ASSUME DS:DGROUP | ||
| 600 | ; | ||
| 601 | ; all done with no errors | ||
| 602 | ; | ||
| 603 | xor ax,ax ; NO errors | ||
| 604 | ; | ||
| 605 | IE_leave: | ||
| 606 | pop es | ||
| 607 | pop ds | ||
| 608 | pop di | ||
| 609 | pop bp | ||
| 610 | pop dx | ||
| 611 | pop bx | ||
| 612 | ret | ||
| 613 | ; | ||
| 614 | IE_not_installed: | ||
| 615 | call DeallocMem ; put back any memory we took | ||
| 616 | mov ax,ERROR ; error return | ||
| 617 | jmp IE_leave | ||
| 618 | ; | ||
| 619 | Init_MEMM386 endp | ||
| 620 | |||
| 621 | ; | ||
| 622 | page | ||
| 623 | ;****************************************************************************** | ||
| 624 | ; | ||
| 625 | ; parser - parse out MEMM parameters and set appropriate values | ||
| 626 | ; for expanded memory size ([pool_size]), page frame base | ||
| 627 | ; address ([PF_Base]) | ||
| 628 | ; | ||
| 629 | ; entry: es:di == config.sys command line parameters | ||
| 630 | ; ds = DGROUP | ||
| 631 | ; | ||
| 632 | ; exit: [pool_size] = expanded memory size | ||
| 633 | ; [PF_Base] = page frame base address | ||
| 634 | ; [Active_Status] =flag for virtual/real mode exit | ||
| 635 | ; [msg_flag] = appropriate messages to display | ||
| 636 | ; | ||
| 637 | ; used: none | ||
| 638 | ; | ||
| 639 | ;****************************************************************************** | ||
| 640 | ; | ||
| 641 | parser proc near | ||
| 642 | push ax ; BP+16 | ||
| 643 | push bx ; BP+14 | ||
| 644 | push cx ; BP+12 | ||
| 645 | push dx ; BP+10 | ||
| 646 | push si ; BP+8 | ||
| 647 | push di ; BP+6 | ||
| 648 | push bp ; BP+4 | ||
| 649 | push ds ; BP+2 | ||
| 650 | push es ; BP+0 | ||
| 651 | mov bp,sp ; | ||
| 652 | cld ; make sure we go forward | ||
| 653 | xor ax,ax ; clear accumulator | ||
| 654 | ; | ||
| 655 | ; Skip past MEMM.EXE in command line | ||
| 656 | ; | ||
| 657 | parm1_loop: ; find 1st parameter | ||
| 658 | mov al,es:[di] | ||
| 659 | cmp al,' ' ; q: find end of MEMM.exe? | ||
| 660 | jbe ploop1 ; y: start parsing | ||
| 661 | inc di ; n: try next one | ||
| 662 | jmp short parm1_loop | ||
| 663 | jmp_def: | ||
| 664 | jmp set_def | ||
| 665 | ; | ||
| 666 | jmp_PF: | ||
| 667 | jmp chk_PF | ||
| 668 | ; | ||
| 669 | ;jmp_onf: | ||
| 670 | ; jmp chk_onf | ||
| 671 | ; | ||
| 672 | ;jmp_auto: | ||
| 673 | ; jmp chk_auto | ||
| 674 | ; | ||
| 675 | jmp_Hx: | ||
| 676 | jmp chk_Hx | ||
| 677 | ; | ||
| 678 | jmp_Xs: | ||
| 679 | jmp chk_Xs | ||
| 680 | |||
| 681 | ploop1: | ||
| 682 | mov si,offset DGROUP:arg_str; ds:si = storage for argument | ||
| 683 | mov cx,max_arg_len ; maximum length of argument | ||
| 684 | call get_token_far ; get next token | ||
| 685 | or cx,cx ; q: anything there? | ||
| 686 | jz jmp_def ; n: go set default values | ||
| 687 | lodsb ; y: get 1st char | ||
| 688 | cmp al,'m' ; q: PF base address? | ||
| 689 | je jmp_PF ; maybe: go validate it | ||
| 690 | cmp al,'h' ; q: Himem enable /disable? | ||
| 691 | je jmp_Hx ; maybe: go validate it | ||
| 692 | cmp al,'x' ; q: Exclude segment parameter | ||
| 693 | je jmp_Xs ; maybe: go validate it | ||
| 694 | ; cmp al,'o' ; q: ON/OFF? | ||
| 695 | ; je jmp_onf ; maybe: go validate it | ||
| 696 | ; cmp al,'a' ; q: AUTO? | ||
| 697 | ; je jmp_auto ; maybe: go validate it | ||
| 698 | |||
| 699 | cmp al,'0' ; q: is it a digit (size) | ||
| 700 | jb inv_parm ; n: invalid | ||
| 701 | cmp al,'9' ; q: is it a digit? | ||
| 702 | jbe chk_siz ; y: validate the size | ||
| 703 | inv_parm: | ||
| 704 | or [msg_flag],INV_PARM_MSG ; set invalid parameter flag | ||
| 705 | jmp short ploop1 ; continue | ||
| 706 | chk_siz: | ||
| 707 | mov bx,cx ; bx = number of digits | ||
| 708 | mov byte ptr [bx+si-1],' ' ; terminate string | ||
| 709 | mov cx,10 ; decimal multiplier | ||
| 710 | xor dx,dx ; clear upper 16 bits | ||
| 711 | xor bx,bx ; clear temporary accumulator | ||
| 712 | cmp [pool_size],0 ; q: have we already done this? | ||
| 713 | jz dig_loop ; n: continue | ||
| 714 | mov dx,1 ; y: skip all of this | ||
| 715 | dig_loop: | ||
| 716 | or dx,dx ; q: overflow? | ||
| 717 | jnz new_digit ; y: just skip rest of digits | ||
| 718 | sub al,'0' ; get ones value | ||
| 719 | xchg ax,bx ; swap accumulated value to ax | ||
| 720 | mul cx ; times 10 | ||
| 721 | add ax,bx ; add in ones value | ||
| 722 | adc dx,0 ; carry to dx | ||
| 723 | xchg ax,bx ; temporary value to bx | ||
| 724 | ; | ||
| 725 | new_digit: | ||
| 726 | lodsb ; get new char into al | ||
| 727 | cmp al,'0' ; q: between 0 & 9? | ||
| 728 | jb dig_exit ; n: done | ||
| 729 | cmp al,'9' | ||
| 730 | ja dig_exit | ||
| 731 | jmp dig_loop ; y: process it | ||
| 732 | ; | ||
| 733 | dig_exit: | ||
| 734 | cmp al,' ' ; q: any invalid digits? | ||
| 735 | jne ck_inv_parm ; y: invalid parameter | ||
| 736 | or dx,dx ; q: something wrong? | ||
| 737 | jz chk_siz1 ; n: not yet | ||
| 738 | cmp [pool_size],0 ; q: is this the second time for size? | ||
| 739 | jz siz_adj ; n: they just asked for too much | ||
| 740 | ck_inv_parm: | ||
| 741 | or [msg_flag],INV_PARM_MSG ; y: only let them do it once | ||
| 742 | jmp ploop1 ; continue | ||
| 743 | chk_siz1: | ||
| 744 | cmp bx,16 ;q: did they ask for too little? | ||
| 745 | jb siz_adj ; y: go adjust it | ||
| 746 | cmp bx,MAX_SIZE ;q: too much? | ||
| 747 | ja siz_adj ; y: adjust it | ||
| 748 | mov dx,0fh ; n: make sure it was a multiple of 16k | ||
| 749 | and dx,bx ;q: was it? | ||
| 750 | jz set_siz ; y: no problem | ||
| 751 | sub bx,dx ; n: drop it down | ||
| 752 | jmp siz_msg ; and give them the message | ||
| 753 | siz_adj: | ||
| 754 | mov bx,256 ; default value for size | ||
| 755 | siz_msg: | ||
| 756 | or [msg_flag],SIZE_ADJ_MSG ; size adjusted | ||
| 757 | set_siz: | ||
| 758 | mov [pool_size],bx ; save it | ||
| 759 | jmp ploop1 ; go check more parameters | ||
| 760 | |||
| 761 | |||
| 762 | ; | ||
| 763 | ; Check page frame base address | ||
| 764 | ; | ||
| 765 | chk_PF: | ||
| 766 | cmp cx,2 ; q: 2 and only 2 chars in argument? | ||
| 767 | jne inv_prm ; n: error | ||
| 768 | lodsb ; get Mx specifier | ||
| 769 | cmp [PF_Base],0ffffh ; q: have they already specified this? | ||
| 770 | jnz inv_prm ; y: don't let them do it again | ||
| 771 | cmp al,'0' ; q: between 1 & 8? | ||
| 772 | jb inv_prm ; n: invalid | ||
| 773 | cmp al,'8' | ||
| 774 | ja inv_prm ; n: invalid | ||
| 775 | sub al,'0' ; make zero relative | ||
| 776 | xor ah,ah ; zero out hi bits | ||
| 777 | shl ax,1 ; make word offset | ||
| 778 | mov [PF_Base],ax ; store address | ||
| 779 | jmp ploop1 ; get next parameter | ||
| 780 | |||
| 781 | ; | ||
| 782 | ; supporting use of Hi Ram. We are providing a command line option for this | ||
| 783 | ; the parameter is specified as He for himem enable or Hd for Himem disable | ||
| 784 | ; this parameter may be specified only once in a command line. Also | ||
| 785 | ; | ||
| 786 | chk_Hx: | ||
| 787 | ; cmp cx,2 ; q: 2 and only 2 chars in argument | ||
| 788 | ; jne inv_prm ; n: error | ||
| 789 | ; lodsb ; get Hx specifier | ||
| 790 | ;; | ||
| 791 | ; cmp [himem_use],0ffh ; has this already been specified | ||
| 792 | ; jnz inv_parm | ||
| 793 | ;; | ||
| 794 | ; cmp al,'e' ; is user asking us to enable | ||
| 795 | ; jne Hx$1 ; no, go to check enable | ||
| 796 | ;; | ||
| 797 | ; mov [himem_use],01h ; enable himem use | ||
| 798 | ; jmp ploop1 | ||
| 799 | ;Hx$1: | ||
| 800 | ; cmp al,'d' | ||
| 801 | ; jne inv_parm ; if neither d or e it is invalid | ||
| 802 | ;; | ||
| 803 | ; mov [himem_use],00h | ||
| 804 | jmp ploop1 | ||
| 805 | |||
| 806 | ; | ||
| 807 | inv_prm: | ||
| 808 | or [msg_flag],INV_PARM_MSG ; invalid | ||
| 809 | jmp ploop1 ; get next parameter | ||
| 810 | ; | ||
| 811 | ; | ||
| 812 | ; check for exclusion of segments. this parameter is specfied thusly: | ||
| 813 | ; | ||
| 814 | ; X:nnnn-mmmm where nnnn is lo segment and mmmm is hi segment of range to | ||
| 815 | ; be excluded from being mappable. | ||
| 816 | ; | ||
| 817 | ; more than one of these may be specified. | ||
| 818 | ; | ||
| 819 | chk_Xs: | ||
| 820 | call handle_Xswitch | ||
| 821 | jc inv_parm | ||
| 822 | jmp ploop1 | ||
| 823 | ; | ||
| 824 | ; | ||
| 825 | ; Check for ON/OFF | ||
| 826 | ; | ||
| 827 | ;chk_onf: | ||
| 828 | ; lodsb ; get next char | ||
| 829 | ; cmp [Active_Status],1 ; q: have they already specified this? | ||
| 830 | ; jbe inv_prm ; y: ignore and set error flag | ||
| 831 | ; cmp [Auto_Mode],1 ; n:q: have they specified auto_mode? | ||
| 832 | ; je inv_prm ; y: ignore and set error flag | ||
| 833 | ; cmp al,'n' ; q: on? | ||
| 834 | ; jne onf_cont ; n: continue | ||
| 835 | ; cmp cx,2 ; y: is that all there is? | ||
| 836 | ; jne inv_prm ; n: error | ||
| 837 | ; mov [Active_Status],1 ; y: set on | ||
| 838 | ; mov [Auto_Mode],0 ; clear Auto mode | ||
| 839 | ; jmp ploop1 ; get next parameter | ||
| 840 | ;onf_cont: | ||
| 841 | ; cmp al,'f' ; q: OF? | ||
| 842 | ; jne inv_prm ; n: invalid | ||
| 843 | ; lodsb ; y: get next char | ||
| 844 | ; cmp al,'f' ; q: OFF? | ||
| 845 | ; jne inv_prm ; n: invalid | ||
| 846 | ; cmp cx,3 ; q: is that all there is? | ||
| 847 | ; jne inv_prm ; n: error | ||
| 848 | ; mov [Active_Status],0 ; y: set OFF | ||
| 849 | ; mov [Auto_Mode],0 ; clear Auto mode | ||
| 850 | ; jmp ploop1 ; get next parameter | ||
| 851 | ; | ||
| 852 | ; Check for AUTO | ||
| 853 | ; | ||
| 854 | ;chk_auto: | ||
| 855 | ; cmp [Active_Status],1 ; q: have they already specified ON/OFF? | ||
| 856 | ; jbe inv_prm ; y: ignore and set error flag | ||
| 857 | ; cmp [Auto_Mode],1 ; n:q: have they specified auto_mode? | ||
| 858 | ; je inv_prm ; y: ignore and set error flag | ||
| 859 | ; cmp cx,AUTO_LEN ; n: q: parameter correct length ? | ||
| 860 | ; jne inv_prm ; n: ignore and set error flag | ||
| 861 | ; push es ; y: check for 'AUTO' | ||
| 862 | ; push di | ||
| 863 | ; dec si ; DS:SI pts to begin of arg | ||
| 864 | ; mov di,offset LAST:AUTO_parm | ||
| 865 | ; push cs | ||
| 866 | ; pop es ; ES:DI pts to 'AUTO' | ||
| 867 | ; cld | ||
| 868 | ; repe cmpsb ;Q: do CX bytes compare ? | ||
| 869 | ; pop di ; restore DI | ||
| 870 | ; pop es ; restore ES | ||
| 871 | ; jne inv_prm ; N: invalid parameter message | ||
| 872 | ; mov [Auto_Mode],1 ; Y: set AUTO mode | ||
| 873 | ; jmp ploop1 ; get next parameter | ||
| 874 | ; | ||
| 875 | ; Set default values for those items that were not specified | ||
| 876 | ; | ||
| 877 | set_def: | ||
| 878 | |||
| 879 | ; | ||
| 880 | ; default pool size if not defined is 256k | ||
| 881 | ; | ||
| 882 | set_pool_size: | ||
| 883 | cmp [pool_size],0 ; q: did they specify size? | ||
| 884 | jnz set_himem ; y: ok | ||
| 885 | mov [pool_size],256 ; n: set default | ||
| 886 | or [msg_flag],SIZE_ADJ_MSG ; display size adjusted | ||
| 887 | |||
| 888 | ; | ||
| 889 | ; default of use of hi system ram is that it should not be used | ||
| 890 | ; | ||
| 891 | set_himem: | ||
| 892 | ; cmp [himem_use],0ffh ; q:did they specify himem enb/dsb | ||
| 893 | ; jnz parse_xit ; y: ok | ||
| 894 | ; mov [himem_use],0 ; n: set default that it is not used | ||
| 895 | |||
| 896 | parse_xit: ; restore registers and exit | ||
| 897 | pop es | ||
| 898 | pop ds | ||
| 899 | pop bp | ||
| 900 | pop di | ||
| 901 | pop si | ||
| 902 | pop dx | ||
| 903 | pop cx | ||
| 904 | pop bx | ||
| 905 | pop ax | ||
| 906 | ret | ||
| 907 | parser endp | ||
| 908 | ; | ||
| 909 | ; parser local data | ||
| 910 | ; | ||
| 911 | ;AUTO_parm db "auto" | ||
| 912 | ;AUTO_LEN equ $-AUTO_parm | ||
| 913 | |||
| 914 | |||
| 915 | msg_tbl label word | ||
| 916 | dw offset LAST:Incorrect_PRT ; Incorrect Processor Type | ||
| 917 | dw offset LAST:Incorrect_DOS ; Incorrect Version of DOS | ||
| 918 | dw offset LAST:InsfMem ; Insufficient Memory | ||
| 919 | dw offset LAST:Already_Inst ; Already Installed | ||
| 920 | dw offset LAST:No_PF_Avail ; No Page Frame Space Avail | ||
| 921 | kill_end label word ; End of messages that kill driver | ||
| 922 | dw offset LAST:Adj_Size ; Pool Size Adjusted | ||
| 923 | dw offset LAST:InvPFBA ; Page Frame Base Addr Adjusted | ||
| 924 | dw offset LAST:InvMRA ; Map Register Adjusted | ||
| 925 | dw offset LAST:InvParm ; Invalid Parameter msg | ||
| 926 | dw offset LAST:PFWarning ; Page Frame warning message | ||
| 927 | MAX_MSG equ (this byte - msg_tbl)/2 ; # of messages to display | ||
| 928 | KILL_MSG equ (this byte - kill_end)/2; 1st four will abort driver | ||
| 929 | ; | ||
| 930 | |||
| 931 | page | ||
| 932 | ;****************************************************************************** | ||
| 933 | ; handle_Xswitch - processes the X switch to make some segments non-mappable ; | ||
| 934 | ; ; | ||
| 935 | ; entry: ds:di string with X switch parameters in form "X:nnnn-mmmm" ; | ||
| 936 | ; cx is length of string | ||
| 937 | ; ; | ||
| 938 | ; exit: CY set if invalid parameter ; | ||
| 939 | ; CY clear if parameter processed ; | ||
| 940 | ; and non-mappable segments excluded ; | ||
| 941 | ; ; | ||
| 942 | ; uses: flags,ax,cx,si ; | ||
| 943 | ; ; | ||
| 944 | ; author: ISP 8/24/88 ; | ||
| 945 | ; ; | ||
| 946 | ;*****************************************************************************; | ||
| 947 | handle_XSwitch proc near | ||
| 948 | ; | ||
| 949 | cmp cx,5 ; must have atleast 5 symbols | ||
| 950 | jb error_Xs ; | ||
| 951 | ; | ||
| 952 | lodsb ; get the next letter ":" | ||
| 953 | sub cx,2 ; | ||
| 954 | ; | ||
| 955 | cmp al,":" ; is it ":" | ||
| 956 | jne error_Xs ; if not it is a bad parameter | ||
| 957 | ; | ||
| 958 | call htoi ; convert hex to integer | ||
| 959 | jcxz error_Xs ; if we have run out we have a bad parameter | ||
| 960 | ; | ||
| 961 | mov bx,ax ; save in bx the start segment to be excluded | ||
| 962 | ; | ||
| 963 | lodsb ; get the next letter | ||
| 964 | dec cx ; | ||
| 965 | jcxz error_Xs | ||
| 966 | cmp al,"-" ; is it the letter "-" | ||
| 967 | jnz error_Xs ; | ||
| 968 | ; | ||
| 969 | call htoi ; convert hex to mappable | ||
| 970 | call exclude_segments | ||
| 971 | |||
| 972 | clc ; set success and | ||
| 973 | ret ; return | ||
| 974 | error_Xs: | ||
| 975 | stc ; set error and | ||
| 976 | ret ; return | ||
| 977 | ; | ||
| 978 | handle_XSwitch endp | ||
| 979 | |||
| 980 | ;-----------------------------------------------------------------------; | ||
| 981 | ; htoi ; | ||
| 982 | ; ; | ||
| 983 | ; Converts a string to an integer. ; | ||
| 984 | ; ; | ||
| 985 | ; Arguments: ; | ||
| 986 | ; DS:SI = string ; | ||
| 987 | ; CX = length ; | ||
| 988 | ; Returns: ; | ||
| 989 | ; AX = integer ; | ||
| 990 | ; DS:SI = remaining string ; | ||
| 991 | ; CX = remaining length ; | ||
| 992 | ; Alters: ; | ||
| 993 | ; nothing ; | ||
| 994 | ; Calls: ; | ||
| 995 | ; nothing ; | ||
| 996 | ; History: ; | ||
| 997 | ; ; | ||
| 998 | ; ISP (isp) 8/24/88 shifted from ps2emm srces ; | ||
| 999 | ;-----------------------------------------------------------------------; | ||
| 1000 | |||
| 1001 | |||
| 1002 | htoi proc near | ||
| 1003 | push bx | ||
| 1004 | xor ax,ax | ||
| 1005 | mov bx,ax | ||
| 1006 | htoi_loop: | ||
| 1007 | jcxz htoi_done | ||
| 1008 | |||
| 1009 | ; get the next character | ||
| 1010 | |||
| 1011 | mov bl,[si] | ||
| 1012 | inc si | ||
| 1013 | dec cx | ||
| 1014 | |||
| 1015 | ; see if it's a digit | ||
| 1016 | |||
| 1017 | sub bl,'0' | ||
| 1018 | cmp bl,9 | ||
| 1019 | jbe have_hvalue | ||
| 1020 | sub bl,'A'-'0' | ||
| 1021 | cmp bl,'F'-'A' | ||
| 1022 | jbe have_hvalue_but_10 | ||
| 1023 | sub bl,'a'-'A' | ||
| 1024 | cmp bl,'F'-'A' | ||
| 1025 | ja htoi_not_digit | ||
| 1026 | have_hvalue_but_10: | ||
| 1027 | add bl,10 | ||
| 1028 | have_hvalue: | ||
| 1029 | |||
| 1030 | ; shift and add | ||
| 1031 | |||
| 1032 | shl ax,1 | ||
| 1033 | shl ax,1 | ||
| 1034 | shl ax,1 | ||
| 1035 | shl ax,1 | ||
| 1036 | add ax,bx | ||
| 1037 | jmp htoi_loop | ||
| 1038 | htoi_not_digit: | ||
| 1039 | inc cx ; give back the character | ||
| 1040 | dec si | ||
| 1041 | htoi_done: | ||
| 1042 | pop bx | ||
| 1043 | ret | ||
| 1044 | htoi endp | ||
| 1045 | |||
| 1046 | |||
| 1047 | |||
| 1048 | page | ||
| 1049 | ;****************************************************************************** | ||
| 1050 | ; | ||
| 1051 | ; b2asc10 - converts binary to ascii decimal and store at CS:DI | ||
| 1052 | ; stores 5 ascii chars (decimal # is right justified and | ||
| 1053 | ; filled on left with blanks) | ||
| 1054 | ; | ||
| 1055 | ; entry: ax = binary number | ||
| 1056 | ; DS = DGROUP | ||
| 1057 | ; CS:di = place to store ascii chars. | ||
| 1058 | ; | ||
| 1059 | ; exit: ASCII decimal representation of number stored at DS:DI | ||
| 1060 | ; | ||
| 1061 | ; used: none | ||
| 1062 | ; | ||
| 1063 | ; stack: | ||
| 1064 | ; | ||
| 1065 | ;****************************************************************************** | ||
| 1066 | ; | ||
| 1067 | b2asc10 proc near | ||
| 1068 | ; | ||
| 1069 | push ax | ||
| 1070 | push bx | ||
| 1071 | push cx | ||
| 1072 | push dx | ||
| 1073 | push si | ||
| 1074 | push di | ||
| 1075 | ; | ||
| 1076 | mov si,8 ; pointer to base 10 table | ||
| 1077 | xor bl,bl ; leading zeroes flag | ||
| 1078 | ; | ||
| 1079 | ; convert binary number to decimal ascii | ||
| 1080 | ; | ||
| 1081 | b2_loop: | ||
| 1082 | xor dx,dx ; clear word extension | ||
| 1083 | mov cx,powr10[si] | ||
| 1084 | div cx ; divide by power of 10 | ||
| 1085 | or bl,bl | ||
| 1086 | jnz b2_ascii | ||
| 1087 | ; | ||
| 1088 | or ax,ax ; q: zero result? | ||
| 1089 | jnz b2_ascii ; n: go convert to ascii | ||
| 1090 | ; | ||
| 1091 | mov al,' ' ; y: go blank fill | ||
| 1092 | jmp b2_make_strg ; | ||
| 1093 | ; | ||
| 1094 | b2_ascii: | ||
| 1095 | add al,'0' ; put into ascii format | ||
| 1096 | mov bl,1 ; leading zeroes on | ||
| 1097 | ; | ||
| 1098 | b2_make_strg: | ||
| 1099 | mov CS:[di],al ; put ascii number into string | ||
| 1100 | xchg ax,dx | ||
| 1101 | inc di ; increment buffer string pointer | ||
| 1102 | dec si ; decrement power of 10 pointer | ||
| 1103 | dec si ; | ||
| 1104 | jge b2_loop ; Q: Last digit? N: Jump if not | ||
| 1105 | ; | ||
| 1106 | pop di | ||
| 1107 | pop si | ||
| 1108 | pop dx | ||
| 1109 | pop cx | ||
| 1110 | pop bx | ||
| 1111 | pop ax | ||
| 1112 | ret ; *** return *** | ||
| 1113 | ; | ||
| 1114 | b2asc10 endp | ||
| 1115 | ; | ||
| 1116 | |||
| 1117 | LAST ends ; End of segment | ||
| 1118 | ; | ||
| 1119 | |||
| 1120 | end ; End of module | ||
| 1121 | |||
| 1122 | |||
| 1123 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/INITDEB.ASM b/v4.0/src/MEMM/MEMM/INITDEB.ASM new file mode 100644 index 0000000..76db0dc --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INITDEB.ASM | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title InitDeb - initialize debugger | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: InitDeb - initialize debugger | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 16,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/16/86 Original from VDM MAIN.ASM module | ||
| 27 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 28 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 29 | ; | ||
| 30 | ;****************************************************************************** | ||
| 31 | ; | ||
| 32 | ; Functional Description: | ||
| 33 | ; | ||
| 34 | ; This routine is linked in when linking with the kernel debugger. | ||
| 35 | ; InitDeb calls the debugger initialization routine. | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | .lfcond ; list false conditionals | ||
| 39 | .386p | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; P U B L I C S | ||
| 42 | ;****************************************************************************** | ||
| 43 | |||
| 44 | public InitDeb | ||
| 45 | |||
| 46 | ;****************************************************************************** | ||
| 47 | ; D E F I N E S | ||
| 48 | ;****************************************************************************** | ||
| 49 | include VDMseg.inc | ||
| 50 | include VDMsel.inc | ||
| 51 | |||
| 52 | FALSE equ 0 | ||
| 53 | TRUE equ not FALSE | ||
| 54 | CR equ 0dh | ||
| 55 | LF equ 0ah | ||
| 56 | |||
| 57 | MASTER_IMR equ 21h ; mask port for master 8259 | ||
| 58 | |||
| 59 | ; | ||
| 60 | ; Definition of the packet used in debug initialization. A pointer to | ||
| 61 | ; this structure is passed to Debug_Entry. | ||
| 62 | ; | ||
| 63 | DebugInit struc | ||
| 64 | CSseg dw ? ;Real mode code segment | ||
| 65 | DSseg dw ? ;Real mode data segment | ||
| 66 | CSsel dw ? ;Prot mode code selector | ||
| 67 | DSsel dw ? ;Prot mode data selector | ||
| 68 | SpareSel1 dw ? ;Prot mode alias selector 1 | ||
| 69 | SpareSel2 dw ? ;Prot mode alias selector 2 | ||
| 70 | GDTalias dw ? ;Prot mode GDT r/w alias | ||
| 71 | ProtIDTaddr dq ? ;Prot mode IDT base & limit | ||
| 72 | RealIDTaddr dq ? ;Real mode IDT base & limit | ||
| 73 | BrkFlag db ? ;TRUE if break to debugger | ||
| 74 | ComFlag db ? ;TRUE if com1, FALSE if com2 | ||
| 75 | DebugInit ends | ||
| 76 | |||
| 77 | |||
| 78 | ;****************************************************************************** | ||
| 79 | ; E X T E R N A L R E F E R E N C E S | ||
| 80 | ;****************************************************************************** | ||
| 81 | ifndef NoBugMode | ||
| 82 | dcode segment | ||
| 83 | extrn _Debug_Entry:far ; (debinit.asm) | ||
| 84 | dcode ends | ||
| 85 | endif | ||
| 86 | |||
| 87 | _DATA SEGMENT | ||
| 88 | |||
| 89 | extrn GDT_Seg:word | ||
| 90 | |||
| 91 | _DATA ENDS | ||
| 92 | |||
| 93 | ;****************************************************************************** | ||
| 94 | ; S E G M E N T D E F I N I T I O N S | ||
| 95 | ;****************************************************************************** | ||
| 96 | |||
| 97 | _DATA SEGMENT | ||
| 98 | |||
| 99 | InitData DebugInit <> | ||
| 100 | |||
| 101 | _DATA ENDS | ||
| 102 | |||
| 103 | ; | ||
| 104 | ; code | ||
| 105 | ; | ||
| 106 | LAST SEGMENT | ||
| 107 | |||
| 108 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 109 | |||
| 110 | ;****************************************************************************** | ||
| 111 | ; InitDeb - initialize kernel debugger | ||
| 112 | ; | ||
| 113 | ; | ||
| 114 | ; ENTRY: Real Mode | ||
| 115 | ; DS = DGROUP | ||
| 116 | ; AL = 00h => dont't break on debug init | ||
| 117 | ; AL = FFh => break on debug init | ||
| 118 | ; | ||
| 119 | ; EXIT: Real Mode | ||
| 120 | ; Kernel debugger initialized | ||
| 121 | ; | ||
| 122 | ; USED: none | ||
| 123 | ; | ||
| 124 | ;****************************************************************************** | ||
| 125 | InitDeb proc near | ||
| 126 | ; | ||
| 127 | ifndef NoBugMode | ||
| 128 | pusha | ||
| 129 | push ds | ||
| 130 | push es | ||
| 131 | ; | ||
| 132 | push ds | ||
| 133 | pop es ; ES = data | ||
| 134 | ; | ||
| 135 | mov di, offset DGROUP:InitData | ||
| 136 | |||
| 137 | mov bx, dcode | ||
| 138 | mov [di].CSseg, bx | ||
| 139 | mov bx, ddata | ||
| 140 | mov [di].DSseg, bx | ||
| 141 | mov [di].CSsel, DEBC_GSEL | ||
| 142 | mov [di].DSsel, DEBD_GSEL | ||
| 143 | mov [di].SpareSel1, DEBW1_GSEL | ||
| 144 | mov [di].SpareSel2, DEBW2_GSEL | ||
| 145 | mov [di].GDTalias, GDTD_GSEL | ||
| 146 | mov [di].BrkFlag, al ; ? break on entry ? | ||
| 147 | mov [di].ComFlag, FALSE ; com2 | ||
| 148 | |||
| 149 | sidt [di].RealIDTaddr | ||
| 150 | |||
| 151 | push ds | ||
| 152 | push di | ||
| 153 | mov ax, [GDT_Seg] | ||
| 154 | mov ds, ax | ||
| 155 | |||
| 156 | lgdt qword ptr ds:[GDTD_GSEL] | ||
| 157 | |||
| 158 | mov si, IDTD_GSEL | ||
| 159 | mov cx, 6 | ||
| 160 | lea di, [di].ProtIDTaddr | ||
| 161 | cld | ||
| 162 | rep movsb | ||
| 163 | pop di | ||
| 164 | pop ds | ||
| 165 | |||
| 166 | call _Debug_Entry | ||
| 167 | ; | ||
| 168 | ; and return | ||
| 169 | ; | ||
| 170 | pop es | ||
| 171 | pop ds | ||
| 172 | popa | ||
| 173 | endif | ||
| 174 | ret | ||
| 175 | InitDeb endp | ||
| 176 | |||
| 177 | |||
| 178 | LAST ends | ||
| 179 | |||
| 180 | END | ||
diff --git a/v4.0/src/MEMM/MEMM/INITEPG.ASM b/v4.0/src/MEMM/MEMM/INITEPG.ASM new file mode 100644 index 0000000..7129b17 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INITEPG.ASM | |||
| @@ -0,0 +1,377 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title InitEPage - initialize EMM Page pointers | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: InitEPage - initialize EMM Page pointers | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: June 4,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/04/86 Original | ||
| 27 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 28 | ; 07/06/86 0.04 _pft386 changed to a ptr | ||
| 29 | ; 07/06/86 0.04 fixed hdma_exit label to edma_exit | ||
| 30 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 31 | ; 07/09/86 0.05 added to FindDMA routine | ||
| 32 | ; | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; | ||
| 35 | ; Functional Description: | ||
| 36 | ; | ||
| 37 | ; This module initializes the array of pointers to the EMM Pages used | ||
| 38 | ; by the expanded memory manager code. Specifically, this module initializes | ||
| 39 | ; the array EMM_PTE. | ||
| 40 | ; | ||
| 41 | ;****************************************************************************** | ||
| 42 | .lfcond ; list false conditionals | ||
| 43 | .386p | ||
| 44 | page | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; P U B L I C D E C L A R A T I O N S | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | public InitEPage | ||
| 50 | |||
| 51 | page | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; L O C A L C O N S T A N T S | ||
| 54 | ;****************************************************************************** | ||
| 55 | ; | ||
| 56 | include VDMseg.inc | ||
| 57 | include VDMsel.inc | ||
| 58 | include desc.inc | ||
| 59 | include page.inc | ||
| 60 | include instr386.inc | ||
| 61 | include emmdef.inc | ||
| 62 | ; | ||
| 63 | ;****************************************************************************** | ||
| 64 | ; E X T E R N A L R E F E R E N C E S | ||
| 65 | ;****************************************************************************** | ||
| 66 | ; | ||
| 67 | |||
| 68 | LAST segment | ||
| 69 | |||
| 70 | ifndef NOHIMEM | ||
| 71 | extrn Hi_Mem_Size:near | ||
| 72 | endif | ||
| 73 | |||
| 74 | extrn mappable_segs:byte | ||
| 75 | |||
| 76 | LAST ends | ||
| 77 | |||
| 78 | |||
| 79 | ABS0 segment at 0000h | ||
| 80 | ABS0 ends | ||
| 81 | |||
| 82 | |||
| 83 | _DATA segment | ||
| 84 | |||
| 85 | extrn DMA_Pages:word ; DMA EMM pages buffer | ||
| 86 | extrn DMA_PAGE_COUNT:word ; number of DMA pages | ||
| 87 | |||
| 88 | extrn xbase_addr_l:word ; 24 bit address of beginning of extended mem | ||
| 89 | extrn xbase_addr_h:byte ; pool of EMM pages. | ||
| 90 | extrn ext_size:word ; size of extended memory in kbytes | ||
| 91 | extrn sys_size:word ; size of system memory in kbytes | ||
| 92 | |||
| 93 | extrn _pft386:word ; ptr to dword array of Page Table entries | ||
| 94 | |||
| 95 | _DATA ends | ||
| 96 | |||
| 97 | ;****************************************************************************** | ||
| 98 | ; S E G M E N T D E F I N I T I O N | ||
| 99 | ;****************************************************************************** | ||
| 100 | _DATA segment | ||
| 101 | |||
| 102 | ifndef NOHIMEM | ||
| 103 | DMA_hi_begin dw 0 ; EMM page # for begin of DMA area in hi mem | ||
| 104 | DMA_hi_cnt dw 0 ; # of contiguous EMM pages in hi mem DMA area | ||
| 105 | endif | ||
| 106 | |||
| 107 | DMA_ext_begin dw 0 ; EMM page # for begin of DMA area in ext mem | ||
| 108 | DMA_ext_cnt dw 0 ; # of contiguous EMM pages in ext mem DMA area | ||
| 109 | |||
| 110 | ; | ||
| 111 | ; FindDMA variables | ||
| 112 | ; | ||
| 113 | crossed db 0 ; flag => crossed 1st 64k bndry | ||
| 114 | b_start dw 0 ; 1st EMM page before 1st 64k bndry | ||
| 115 | b_cnt dw 0 ; # of EMM pages before 1st 64k bndry | ||
| 116 | a_start dw 0 ; 1st EMM page after 1st 64k bndry | ||
| 117 | a_cnt dw 0 ; # of EMM pages after 1st 64k bndry | ||
| 118 | |||
| 119 | |||
| 120 | _DATA ends | ||
| 121 | ; | ||
| 122 | ;------------------------------------------------------------------------------ | ||
| 123 | LAST segment | ||
| 124 | assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 125 | page | ||
| 126 | ;****************************************************************************** | ||
| 127 | ; InitEPage - init EMM_PTE - array of pointers for EMM pages. | ||
| 128 | ; | ||
| 129 | ; ENTRY: Real Mode | ||
| 130 | ; DGROUP:[xbase_addr_l] = 24 bit address of beginning of extended mem | ||
| 131 | ; DGROUP:[xbase_addr_h] pool of EMM pages. | ||
| 132 | ; DGROUP:[ext_size] = size of extended memory buffer in kbytes | ||
| 133 | ; | ||
| 134 | ; EXIT: Real Mode | ||
| 135 | ; DGROUP:[DMA_Pages] = initialized to point to up to 8 physically | ||
| 136 | ; contiguous EMM pages in high memory. | ||
| 137 | ; DGROUP:[_pft386] = pts to array of ptrs for EMM Pages | ||
| 138 | ; | ||
| 139 | ; USED: Flags | ||
| 140 | ; STACK: | ||
| 141 | ;------------------------------------------------------------------------------ | ||
| 142 | InitEPage proc near | ||
| 143 | ; | ||
| 144 | PUSH_EAX | ||
| 145 | push bx | ||
| 146 | push cx | ||
| 147 | push dx | ||
| 148 | push si | ||
| 149 | push di | ||
| 150 | push ds | ||
| 151 | push es | ||
| 152 | ; | ||
| 153 | cld | ||
| 154 | ; | ||
| 155 | mov ax,seg DGROUP | ||
| 156 | mov ds,ax | ||
| 157 | mov es,ax | ||
| 158 | mov di,[_pft386] ; ES:DI points to begin of table | ||
| 159 | ; | ||
| 160 | mov bx,0 ; BX = current EMM page # | ||
| 161 | ; | ||
| 162 | ; set system memory pointers first | ||
| 163 | ; | ||
| 164 | mov cx,[sys_size] ; get size of system memory in kb | ||
| 165 | shr cx,4 ; convert to number of pages | ||
| 166 | jcxz fin_sys | ||
| 167 | mov eax,0000h*16 ; address of first system page | ||
| 168 | xor si,si ; index into mappable page array | ||
| 169 | ; | ||
| 170 | ; store in pft386 array | ||
| 171 | ; | ||
| 172 | SEP_hloop: | ||
| 173 | cmp cs:mappable_segs[si],PAGE_MAPPABLE | ||
| 174 | jne not_this_page | ||
| 175 | ; | ||
| 176 | stosd | ||
| 177 | inc bx ; next emm page | ||
| 178 | dec cx | ||
| 179 | jcxz fin_sys ; found all pages | ||
| 180 | not_this_page: | ||
| 181 | inc si | ||
| 182 | add eax,4000h ; point to next 16k page | ||
| 183 | jmp SEP_hloop ; | ||
| 184 | fin_sys: | ||
| 185 | ; | ||
| 186 | ifndef NOHIMEM | ||
| 187 | ; | ||
| 188 | ; set high memory pointers next | ||
| 189 | ; | ||
| 190 | call Hi_Mem_Size ; CX = kbytes of high mem, | ||
| 191 | ; EAX = pointer to high mem | ||
| 192 | ;Q: any hi memory pages ? CX = pg cnt | ||
| 193 | jz IEP_ext ; N: set up ext mem pointers | ||
| 194 | ; Y: set high memory pointers | ||
| 195 | ; | ||
| 196 | ; check for contiguous EMM pages | ||
| 197 | ; | ||
| 198 | push bx ; first hi mem EMM page # | ||
| 199 | push cx ; save # of hi mem EMM pages | ||
| 200 | call FindDMA ; find the DMA pages for hi mem | ||
| 201 | mov [DMA_hi_begin],bx ; save begin EMM page # | ||
| 202 | mov [DMA_hi_cnt],cx ; save cnt | ||
| 203 | pop cx ; restore # of hi mem EMM pages | ||
| 204 | pop bx ; restore EMM page# for 1st of hi mem | ||
| 205 | ; | ||
| 206 | ; set entries in _pft386 | ||
| 207 | ; | ||
| 208 | IEP_hloop: | ||
| 209 | db 66h | ||
| 210 | stosw ; set this table entry | ||
| 211 | db 66h | ||
| 212 | add ax,4000h ; ADD EAX,4000h | ||
| 213 | dw 0000h ; EAX = addr of next EMM page | ||
| 214 | inc bx ; increment EMM page # | ||
| 215 | loop IEP_hloop ; set all high memory entries | ||
| 216 | |||
| 217 | endif ; NOHIMEM | ||
| 218 | |||
| 219 | ; | ||
| 220 | ; set extended memory entries | ||
| 221 | ; | ||
| 222 | IEP_ext: | ||
| 223 | mov cx,[ext_size] ; CX = kbytes of ext memory | ||
| 224 | shr cx,4 ;Q: any ext memory pages ? CX = pg cnt | ||
| 225 | jz IEP_Dpages ; N: all done - leave | ||
| 226 | db 66h ; Y: set ext memory pointers | ||
| 227 | mov ax,[xbase_addr_l] ; get pointer to ext memory pool | ||
| 228 | db 66h | ||
| 229 | and ax,0FFFFh ; AND EAX,00FFFFFFh | ||
| 230 | dw 00FFh ; clear highest nibble | ||
| 231 | ; | ||
| 232 | ; check for contiguous EMM pages | ||
| 233 | ; | ||
| 234 | push bx ; first ext mem EMM page # | ||
| 235 | push cx ; save # of ext mem EMM pages | ||
| 236 | call FindDMA ; find the DMA pages for ext mem | ||
| 237 | mov [DMA_ext_begin],bx ; save begin EMM page # | ||
| 238 | mov [DMA_ext_cnt],cx ; save cnt | ||
| 239 | pop cx ; restore # of ext mem EMM pages | ||
| 240 | pop bx ; restore EMM page# for 1st of ext mem | ||
| 241 | ; | ||
| 242 | ; set entries in _pft386 | ||
| 243 | ; | ||
| 244 | IEP_xloop: | ||
| 245 | db 66h | ||
| 246 | stosw ; set this table entry | ||
| 247 | db 66h | ||
| 248 | add ax,4000h ; ADD EAX,4000h | ||
| 249 | dw 0000h ; EAX = addr of next EMM page | ||
| 250 | inc bx ; increment EMM page # | ||
| 251 | loop IEP_xloop ; set all ext memory entries | ||
| 252 | ; | ||
| 253 | ; | ||
| 254 | ; set up DMA Pages | ||
| 255 | ; | ||
| 256 | IEP_Dpages: | ||
| 257 | ifndef NOHIMEM | ||
| 258 | mov ax,[DMA_hi_begin] ; SI = beginning hi mem DMA page | ||
| 259 | mov cx,[DMA_hi_cnt] ; CX = # of hi mem DMA pages | ||
| 260 | cmp cx,[DMA_ext_cnt] ;Q: more hi DMA pages ? | ||
| 261 | jae IEP_Dset ; Y: use hi mem DMA pages | ||
| 262 | endif | ||
| 263 | mov cx,[DMA_ext_cnt] ; N: use ext mem pages | ||
| 264 | mov ax,[DMA_ext_begin] | ||
| 265 | IEP_Dset: | ||
| 266 | |||
| 267 | mov DMA_Page_Count,cx | ||
| 268 | mov di,offset DGROUP:DMA_Pages ; ES:DI ->dest array | ||
| 269 | cld | ||
| 270 | DMA_Pg_St: | ||
| 271 | stosw ; store index for dma page | ||
| 272 | inc ax ; | ||
| 273 | loop DMA_Pg_St ; | ||
| 274 | ; | ||
| 275 | ; all done | ||
| 276 | ; | ||
| 277 | pop es | ||
| 278 | pop ds | ||
| 279 | pop di | ||
| 280 | pop si | ||
| 281 | pop dx | ||
| 282 | pop cx | ||
| 283 | pop bx | ||
| 284 | POP_EAX | ||
| 285 | ret | ||
| 286 | ; | ||
| 287 | InitEPage endp | ||
| 288 | ; | ||
| 289 | |||
| 290 | ;****************************************************************************** | ||
| 291 | ; FindDMA - find contiguous DMA pages | ||
| 292 | ; | ||
| 293 | ; ENTRY: Real Mode | ||
| 294 | ; EAX = 24 bits of beginning address of EMM memory pool | ||
| 295 | ; BX = first EMM page # | ||
| 296 | ; CX = # of EMM pages in this pool | ||
| 297 | ; | ||
| 298 | ; EXIT: Real Mode | ||
| 299 | ; BX = EMM page# of first DMA page | ||
| 300 | ; CX = # of DMA pages | ||
| 301 | ; | ||
| 302 | ; USED: Flags | ||
| 303 | ; STACK: | ||
| 304 | ;------------------------------------------------------------------------------ | ||
| 305 | FindDMA proc near | ||
| 306 | ; | ||
| 307 | push eax | ||
| 308 | |||
| 309 | ; | ||
| 310 | ; initialise the variables needed for this calculation | ||
| 311 | ; | ||
| 312 | mov [b_start],bx | ||
| 313 | mov [a_start],bx | ||
| 314 | mov [crossed],0 | ||
| 315 | mov [a_cnt],0 | ||
| 316 | mov [b_cnt],0 | ||
| 317 | |||
| 318 | jcxz fdp_exit ; if no pages to check exit ... | ||
| 319 | ; | ||
| 320 | ; convert physical address in eax (which is assumed to be aligned on 4k bdry) | ||
| 321 | ; to page # (in 4k physical pages) modulo 32. This is to find the page # in | ||
| 322 | ; the current 128k block | ||
| 323 | ; | ||
| 324 | shr eax,12 ; physical_address >> 4*1024 | ||
| 325 | and ax,01fh ; modulo 32, also sets Z flag if on 128k | ||
| 326 | ; bdry. So Q: On 128K bdry? | ||
| 327 | jnz fdp_loop ; N: continue as normal | ||
| 328 | mov [crossed],1 ; Y: set flag | ||
| 329 | |||
| 330 | fdp_loop: | ||
| 331 | add ax,04h ;Q: add 16k bytes, did it cross 128k ? | ||
| 332 | test ax,NOT 01fh ; if into next 128k it will go into next | ||
| 333 | ; bit | ||
| 334 | je fdp_no_cross ; N: continue | ||
| 335 | cmp [crossed],0 ; Y:Q: have we crossed it before ? | ||
| 336 | je fdp_cross1 ; N: update counts | ||
| 337 | and ax,01fh ; Y:Q: equal to 128k bndry ? | ||
| 338 | jnz fdp_exit ; N: then leave | ||
| 339 | inc [a_cnt] ; Y: update last cnt | ||
| 340 | jmp fdp_exit ; and leave | ||
| 341 | |||
| 342 | fdp_cross1: ; first crossing of 128k bndry | ||
| 343 | mov [crossed],1 ; set crossed flag. | ||
| 344 | mov [a_start],bx ; start with ... | ||
| 345 | inc [a_start] ; next page. | ||
| 346 | and ax,01fh ;Q: equal to 128k bndry ? | ||
| 347 | jnz fdp_next ; N: next page | ||
| 348 | inc [b_cnt] ; Y: include page in before pages | ||
| 349 | jmp fdp_next ; and go to next page | ||
| 350 | |||
| 351 | fdp_no_cross: | ||
| 352 | cmp [crossed],0 ;Q: have we crossed first 64k bndry ? | ||
| 353 | jne fdp_n_c ; Y: update it's count | ||
| 354 | inc [b_cnt] ; N: update before count | ||
| 355 | jmp fdp_next | ||
| 356 | fdp_n_c: | ||
| 357 | inc [a_cnt] ; update after count | ||
| 358 | fdp_next: | ||
| 359 | inc bx ; next page # | ||
| 360 | loop fdp_loop ; and continue | ||
| 361 | ; | ||
| 362 | fdp_exit: | ||
| 363 | mov bx,[b_start] ; BX = first page before | ||
| 364 | mov cx,[b_cnt] ; CX = cnt of pages before | ||
| 365 | cmp cx,[a_cnt] ;Q: more before than after ? | ||
| 366 | jae fdp_ret ; Y: return pages before | ||
| 367 | mov bx,[a_start] ; N: return pages after | ||
| 368 | mov cx,[a_cnt] ; | ||
| 369 | fdp_ret: | ||
| 370 | pop eax ; restore EAX | ||
| 371 | ret | ||
| 372 | ; | ||
| 373 | FindDMA endp | ||
| 374 | |||
| 375 | LAST ends ; end of segment | ||
| 376 | ; | ||
| 377 | end ; end of module | ||
diff --git a/v4.0/src/MEMM/MEMM/INITTAB.ASM b/v4.0/src/MEMM/MEMM/INITTAB.ASM new file mode 100644 index 0000000..c37b78e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INITTAB.ASM | |||
| @@ -0,0 +1,632 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title InitTab - OEM init routines to init tables | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: InitTab | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: June 4,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/04/86 Original | ||
| 27 | ; 06/21/86 0.02 Added cld | ||
| 28 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 29 | ; 07/05/86 0.04 Added NOHIMEM ifdef and added code to | ||
| 30 | ; move _TEXT segment to high mem | ||
| 31 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 32 | ; 07/06/86 0.04 added ring0 stack move | ||
| 33 | ; 07/10/86 0.05 removed CODE_GSEL reset | ||
| 34 | ; 07/10/86 0.05 PageT_Seg and PageD_Seg | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional Description: | ||
| 39 | ; | ||
| 40 | ; This module is called after the system has been set up in a viable | ||
| 41 | ; state to start executing MEMM. This routine provides a "hook" where | ||
| 42 | ; the tables (GDT,IDT,TSS, & PageTables, etc) can be modified. This routine | ||
| 43 | ; must set the variables which hold the 32 bit address for each of the | ||
| 44 | ; VDM tables. This routine also sets up the EXTRA1_GSEL to point to the | ||
| 45 | ; Diagnostics byte segment. | ||
| 46 | ; | ||
| 47 | ;****************************************************************************** | ||
| 48 | .lfcond ; list false conditionals | ||
| 49 | .386p | ||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; P U B L I C D E C L A R A T I O N S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | public InitTab | ||
| 56 | |||
| 57 | page | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; L O C A L C O N S T A N T S | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; | ||
| 62 | OEM_MEM_HI equ 80c0h ; Upper 16 bits of high mem physical adr | ||
| 63 | |||
| 64 | include VDMseg.inc | ||
| 65 | include VDMsel.inc | ||
| 66 | include desc.inc | ||
| 67 | include page.inc | ||
| 68 | include instr386.inc | ||
| 69 | include oemdep.inc | ||
| 70 | ; | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; E X T E R N A L R E F E R E N C E S | ||
| 73 | ;****************************************************************************** | ||
| 74 | ; | ||
| 75 | |||
| 76 | GDT segment | ||
| 77 | extrn GDTLEN:abs | ||
| 78 | GDT ends | ||
| 79 | |||
| 80 | IDT segment | ||
| 81 | extrn IDTLEN:abs | ||
| 82 | IDT ends | ||
| 83 | |||
| 84 | TSS segment | ||
| 85 | extrn TSSLEN:abs | ||
| 86 | TSS ends | ||
| 87 | |||
| 88 | PAGESEG segment | ||
| 89 | extrn P_TABLE_CNT:abs | ||
| 90 | PAGESEG ends | ||
| 91 | |||
| 92 | |||
| 93 | _DATA segment | ||
| 94 | extrn TEXT_Seg:word ; segment for TEXT | ||
| 95 | extrn STACK_Seg:word ; segment for STACK | ||
| 96 | extrn GDT_Seg:word ; segment for GDT | ||
| 97 | extrn IDT_Seg:word ; segment for IDT | ||
| 98 | extrn TSS_Seg:word ; segment for TSS | ||
| 99 | extrn PageD_Seg:word ; segment for page dir | ||
| 100 | extrn PageT_Seg:word ; segment for page table | ||
| 101 | extrn Page_Dir:word ; 32 bit address for Page directory | ||
| 102 | extrn driver_end:dword ; ending address for MEMM.EXE | ||
| 103 | extrn _emm_brk:word ; break address for EMM data | ||
| 104 | |||
| 105 | _DATA ends | ||
| 106 | |||
| 107 | LAST segment | ||
| 108 | ifndef NOHIMEM | ||
| 109 | extrn HiSysAlloc:near ; allocate high system memory | ||
| 110 | extrn UnLockROM:near | ||
| 111 | extrn LockROM:near | ||
| 112 | endif | ||
| 113 | extrn SegTo24:near | ||
| 114 | extrn SetSegDesc:near | ||
| 115 | extrn SetPageEntry:near | ||
| 116 | extrn moveb:near | ||
| 117 | extrn get_buffer:near | ||
| 118 | |||
| 119 | LAST ends | ||
| 120 | |||
| 121 | _TEXT segment | ||
| 122 | extrn Real_Seg:word ; fixup for _TEXT in RetReal (retreal.asm) | ||
| 123 | _TEXT ends | ||
| 124 | |||
| 125 | R_CODE segment | ||
| 126 | extrn EFunTab:word ; table of ELIM functions | ||
| 127 | extrn EFUN_CNT:abs ; # of entries in table | ||
| 128 | extrn EMM_rEfix:near ; far call to EMM function dispatcher in _TEXT | ||
| 129 | R_CODE ends | ||
| 130 | |||
| 131 | |||
| 132 | ;****************************************************************************** | ||
| 133 | ; S E G M E N T D E F I N I T I O N | ||
| 134 | ;****************************************************************************** | ||
| 135 | ; | ||
| 136 | ;------------------------------------------------------------------------------ | ||
| 137 | LAST segment | ||
| 138 | assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 139 | page | ||
| 140 | ;****************************************************************************** | ||
| 141 | ; InitTab - init tables & 32 bit address | ||
| 142 | ; | ||
| 143 | ; ENTRY: Real Mode | ||
| 144 | ; GDT = current segment for GDT | ||
| 145 | ; IDT = current segment for IDT | ||
| 146 | ; TSS = current segment for TSS | ||
| 147 | ; _TEXT = current segment for _TEXT | ||
| 148 | ; STACK = current segment for STACK | ||
| 149 | ; DGROUP:[PageD_Seg] = current segment portion of page directory | ||
| 150 | ; DGROUP:[PageT_Seg] = current segment portion of page tables | ||
| 151 | ; DGROUP:[Page_Dir] = current 32 bit address for page directory | ||
| 152 | ; IDTLEN:abs = length of IDT | ||
| 153 | ; TSSLEN:abs = length of TSS | ||
| 154 | ; P_TABLE_CNT:abs = # of page TABLES | ||
| 155 | ; _TEXT:[Real_Seg] = fixup location for _TEXT in RetReal | ||
| 156 | ; R_CODE:[EFunTab] = table of ELIM functions | ||
| 157 | ; R_CODE:EFUN_CNT = # of entries in table | ||
| 158 | ; R_CODE:[EMM_rEfix] = far call to EMM function dispatcher in _TEXT | ||
| 159 | ; | ||
| 160 | ; EXIT: Real Mode | ||
| 161 | ; DGROUP:[TEXT_Seg] = current segment for TEXT | ||
| 162 | ; DGROUP:[STACK_Seg] = current segment for STACK | ||
| 163 | ; DGROUP:[GDT_Seg] = current segment for GDT | ||
| 164 | ; DGROUP:[IDT_Seg] = current segment for IDT | ||
| 165 | ; DGROUP:[TSS_Seg] = current segment for TSS | ||
| 166 | ; DGROUP:[PageD_Seg] = current segment portion of page directory | ||
| 167 | ; DGROUP:[PageT_Seg] = current segment portion of page tables | ||
| 168 | ; DGROUP:[Page_Dir] = current 32 bit address for page directory | ||
| 169 | ; DGROUP:[driver_end] = end of MEMM.EXE device driver | ||
| 170 | ; GDT:[IDTD_GSEL] = current descriptor for IDT | ||
| 171 | ; GDT:[TSS_GSEL] = current descriptor for TSS | ||
| 172 | ; GDT:[TSSD_GSEL] = current descriptor for TSS | ||
| 173 | ; GDT:[PAGET_GSEL] = current descriptor for Page TABLES | ||
| 174 | ; | ||
| 175 | ; | ||
| 176 | ; USED: Flags | ||
| 177 | ; STACK: | ||
| 178 | ;------------------------------------------------------------------------------ | ||
| 179 | InitTab proc near | ||
| 180 | ; | ||
| 181 | ifndef NOHIMEM | ||
| 182 | |||
| 183 | PUSH_EAX | ||
| 184 | push di | ||
| 185 | push ds | ||
| 186 | push es | ||
| 187 | pushf | ||
| 188 | cli ; turn off ints | ||
| 189 | cld ; strings foward | ||
| 190 | ; | ||
| 191 | mov ax,seg DGROUP | ||
| 192 | mov ds,ax | ||
| 193 | ; | ||
| 194 | ; set up GDT entry for the diagnostics segment | ||
| 195 | ; | ||
| 196 | mov ax, seg GDT ; GDT not moved yet ! | ||
| 197 | mov es,ax | ||
| 198 | |||
| 199 | xor dx,dx | ||
| 200 | mov al,00h ; only low 24 bits of address here ! | ||
| 201 | mov cx,0 ; 64k long | ||
| 202 | mov ah,D_DATA0 ; data segment | ||
| 203 | mov bx,OEM0_GSEL | ||
| 204 | call SetSegDesc ; Set up GDT alias descriptor | ||
| 205 | mov ES:[bx.BASE_XHI],01h ; set high 8 bits of address | ||
| 206 | |||
| 207 | ; | ||
| 208 | ;------------------------------------------------------------------------------ | ||
| 209 | ; Move Tables to HIGH SYSTEM memory | ||
| 210 | ; The high system memory is mapped to FE0000h - FEFFFFh | ||
| 211 | ; AND 0E0000h-0EFFFFh. The following code copies data to the E0000h | ||
| 212 | ; range | ||
| 213 | ;------------------------------------------------------------------------------ | ||
| 214 | ; | ||
| 215 | |||
| 216 | ; | ||
| 217 | ;------------------------------------------------------------------------------ | ||
| 218 | ; move PAGE DIR/TABLES up to high memory | ||
| 219 | ;------------------------------------------------------------------------------ | ||
| 220 | ; | ||
| 221 | mov ax,P_TABLE_CNT ; AX = # of page tables | ||
| 222 | inc ax ; include page directory | ||
| 223 | mov cx,ax ; CX=AX = # of pages for page table seg | ||
| 224 | call HiSysAlloc ;Q: enough room in high sys mem ? | ||
| 225 | jnc IT_move_pt ; Y: move page dir/tables to hi sys mem | ||
| 226 | inc ax ; N: Q: is error not enough room? | ||
| 227 | jnz To_IT_Exit ; Y: just go ahead and exit | ||
| 228 | popf | ||
| 229 | stc ; N: return CF = 1(mem alloc error) | ||
| 230 | jmp IT_Quit | ||
| 231 | To_IT_Exit: | ||
| 232 | jmp IT_Exit ; N: then nothing is moved up | ||
| 233 | IT_move_pt: ; | ||
| 234 | call UnLockROM ;turn off write protect | ||
| 235 | shl ax,8 ; | ||
| 236 | add ax,0E000h ; AX = segment for sys mem block | ||
| 237 | mov es,ax ; ES -> sys mem block | ||
| 238 | xor di,di ; ES:DI -> sys mem block | ||
| 239 | mov ax,[PageD_Seg] ; | ||
| 240 | mov ds,ax ; DS -> page dir/tables | ||
| 241 | xor si,si ; DS:SI -> page dir/tables | ||
| 242 | shl cx,10 ; CX = # of dwords in page tables | ||
| 243 | cld | ||
| 244 | OP32 | ||
| 245 | rep movsw ; mov cx dwords into hi sys mem | ||
| 246 | ; | ||
| 247 | mov ax,seg DGROUP | ||
| 248 | mov ds,ax ; DS = DATA | ||
| 249 | ; | ||
| 250 | ; reset break address for driver | ||
| 251 | ; | ||
| 252 | mov word ptr [driver_end],0 | ||
| 253 | mov ax,[PageD_Seg] | ||
| 254 | mov word ptr [driver_end+2],ax | ||
| 255 | |||
| 256 | ; | ||
| 257 | ; reset page dir/table pointers | ||
| 258 | XOR_EAX_EAX ; clear eax | ||
| 259 | mov ax,es ; | ||
| 260 | mov [PageD_Seg],ax ; reset segment for page dir | ||
| 261 | add ax,P_SIZE/10h ; ax = segment page table | ||
| 262 | mov [PageT_Seg],ax ; rest it | ||
| 263 | |||
| 264 | mov ax,es ; get page dir seg again | ||
| 265 | OP32 | ||
| 266 | shl ax,4 ; shl EAX,4 => EAX = 32 bit address | ||
| 267 | OP32 | ||
| 268 | mov [Page_Dir],ax ; store 32 bit addr of page dir | ||
| 269 | ; | ||
| 270 | ; reset page directory entries | ||
| 271 | ; | ||
| 272 | mov ax,word ptr [Page_Dir] ; DX,AX = 32 bit addr of Page Directory | ||
| 273 | mov dx,word ptr [Page_Dir+2] ; save it | ||
| 274 | ; | ||
| 275 | ; get addr of Page Table for Page Directory entry | ||
| 276 | ; | ||
| 277 | add ax,1000h ; add page | ||
| 278 | adc dx,0h ; carry it => DX,AX = addr of page table | ||
| 279 | ; | ||
| 280 | ; DX,AX = addr of first page table | ||
| 281 | ; | ||
| 282 | xor di,di ; ES:[DI] -> 1st entry in page dir | ||
| 283 | mov bh,0 | ||
| 284 | mov bl,P_AVAIL ; make table available to all | ||
| 285 | mov cx,P_TABLE_CNT ; set entries in page table directory | ||
| 286 | ; for existing page tables. | ||
| 287 | IT_pdir: | ||
| 288 | call SetPageEntry ; set entry for first page table | ||
| 289 | ; | ||
| 290 | ; ES:[DI] pts to next entry in page directory | ||
| 291 | add ax,1000h | ||
| 292 | adc dx,0 ; DX,AX = addr of next page table | ||
| 293 | loop IT_pdir ; set next entry in dir | ||
| 294 | ; | ||
| 295 | ; reset PAGET_GSEL descriptor | ||
| 296 | ; | ||
| 297 | mov ax,seg GDT ; GDT has not yet moved!!! | ||
| 298 | mov es,ax ; ES pts to GDT | ||
| 299 | |||
| 300 | mov ax,[PageT_Seg] ; segment for page tables | ||
| 301 | call SegTo24 | ||
| 302 | mov cx,0 ; enough room for tables | ||
| 303 | mov ah,D_DATA0 | ||
| 304 | mov bx,PAGET_GSEL | ||
| 305 | call SetSegDesc ; set up page table descriptor | ||
| 306 | ; | ||
| 307 | ; now set CR3 in the TSS - to reflect new Page DIR position | ||
| 308 | ; | ||
| 309 | mov ax,seg TSS ; TSS not moved yet !!! | ||
| 310 | mov es,ax ; ES -> TSS | ||
| 311 | xor di,di ; ES:DI -> TSS | ||
| 312 | |||
| 313 | db 66h | ||
| 314 | mov ax,[Page_Dir] ; EAX = page dir 32 bit addr | ||
| 315 | db 66h | ||
| 316 | mov word ptr ES:[di.TSS386_CR3],ax ; mov EAX into CR3 spot in TSS | ||
| 317 | ; | ||
| 318 | ;------------------------------------------------------------------------------ | ||
| 319 | ; move _TEXT, GDT,IDT, & TSS up to high system memory | ||
| 320 | ; **** this code depends on the order of the _TEXT, GDT, IDT, & TSS | ||
| 321 | ; segments when linked. They should be in the order | ||
| 322 | ; _TEXT, GDT, IDT, then TSS. | ||
| 323 | ;------------------------------------------------------------------------------ | ||
| 324 | ; | ||
| 325 | mov ax,seg TSS ; compute # of paras from begin of _TEXT | ||
| 326 | sub ax,seg _TEXT ; to begin of TSS | ||
| 327 | shl ax,4 ; convert it to bytes | ||
| 328 | add ax,TSSLEN ; and add in length of TSS | ||
| 329 | ; AX=length of _TEXT,GDT,IDT, & TSS segs | ||
| 330 | add ax,P_SIZE-1 ; round up to nearest page boundary | ||
| 331 | shr ax,12 ; AX = # of 4k pages for these tables | ||
| 332 | mov cx,ax ; CX=AX = # of pages for these tables | ||
| 333 | call HiSysAlloc ;Q: enough room in high sys mem ? | ||
| 334 | jnc IT_move_tables ; Y: move page dir/tables to hi sys mem | ||
| 335 | call LockROM ; N: move nothing. write protect ROM | ||
| 336 | jmp IT_Exit ; | ||
| 337 | IT_move_tables: | ||
| 338 | call UnLockROM ; turn off write protect | ||
| 339 | shl ax,8 ; AX = # of paras already allocated | ||
| 340 | ; in high memory | ||
| 341 | add ax,0E000h ; AX = segment for sys mem block | ||
| 342 | mov es,ax ; ES -> sys mem block | ||
| 343 | xor di,di ; ES:DI -> sys mem block | ||
| 344 | |||
| 345 | mov ax,seg _TEXT ; start with _TEXT | ||
| 346 | mov ds,ax ; DS -> _TEXT | ||
| 347 | xor si,si ; DS:SI -> _TEXT | ||
| 348 | shl cx,10 ; CX=# of dwords for _TEXT,GDT,IDT,&TSS | ||
| 349 | cld | ||
| 350 | OP32 | ||
| 351 | rep movsw ; mov _TEXT,GDT,IDT,&TSS into hi sys mem | ||
| 352 | |||
| 353 | ; | ||
| 354 | ; now reset pointers to _TEXT, GDT, IDT, & TSS | ||
| 355 | mov ax,seg DGROUP | ||
| 356 | mov ds,ax ; DS = DATA | ||
| 357 | |||
| 358 | mov ax,es ; AX = segment for new _TEXT location | ||
| 359 | mov [TEXT_Seg],ax ; set new _TEXT segment | ||
| 360 | |||
| 361 | mov bx,seg GDT | ||
| 362 | sub bx,seg _TEXT ; bx = offset from _TEXT to GDT | ||
| 363 | add ax,bx ; (don't worry, won't cross Linear 64k) | ||
| 364 | mov [GDT_Seg],ax ; set new GDT segment | ||
| 365 | |||
| 366 | mov bx,seg IDT | ||
| 367 | sub bx,seg GDT ; bx = offset from GDT to IDT | ||
| 368 | add ax,bx ; (don't worry, won't cross Linear 64k) | ||
| 369 | mov [IDT_Seg],ax ; set new IDT segment | ||
| 370 | |||
| 371 | mov bx,seg TSS | ||
| 372 | sub bx,seg IDT ; bx = offset from IDT to TSS | ||
| 373 | add ax,bx ; (don't worry, won't cross Linear 64k) | ||
| 374 | mov [TSS_Seg],ax ; set new TSS segment | ||
| 375 | ; | ||
| 376 | ; reset descriptors for _TEXT, GDT, IDT, & TSS | ||
| 377 | ; | ||
| 378 | mov ax,[GDT_Seg] ; GDT has MOVED !!! | ||
| 379 | mov es,ax ; ES pts to GDT | ||
| 380 | |||
| 381 | mov ax,[TEXT_Seg] ; _TEXT segment | ||
| 382 | call SegTo24 | ||
| 383 | mov cx,0 | ||
| 384 | mov ah,D_CODE0 | ||
| 385 | mov bx,VDMC_GSEL | ||
| 386 | call SetSegDesc ; Set up VDM code descriptor - VDMC | ||
| 387 | |||
| 388 | mov ax,[TEXT_Seg] ; _TEXT segment | ||
| 389 | call SegTo24 | ||
| 390 | mov cx,0 | ||
| 391 | mov ah,D_DATA0 | ||
| 392 | mov bx,VDMCA_GSEL | ||
| 393 | call SetSegDesc ; Set up VDM code alias descriptor | ||
| 394 | |||
| 395 | mov ax,[GDT_Seg] ; GDT segment | ||
| 396 | call SegTo24 | ||
| 397 | mov cx,GDTLEN | ||
| 398 | mov ah,D_DATA0 | ||
| 399 | mov bx,GDTD_GSEL | ||
| 400 | call SetSegDesc ; Set up GDT alias descriptor | ||
| 401 | |||
| 402 | mov ax,[IDT_Seg] ; IDT segment | ||
| 403 | call SegTo24 | ||
| 404 | mov cx,IDTLEN | ||
| 405 | mov ah,D_DATA0 | ||
| 406 | mov bx,IDTD_GSEL | ||
| 407 | call SetSegDesc ; Set up IDT alias descriptor | ||
| 408 | |||
| 409 | mov ax,[TSS_Seg] ; segment of TSS | ||
| 410 | call SegTo24 | ||
| 411 | mov cx,TSSLEN | ||
| 412 | mov ah,D_386TSS0 | ||
| 413 | mov bx,TSS_GSEL | ||
| 414 | call SetSegDesc ; Set up TSS descriptor | ||
| 415 | |||
| 416 | mov ah,D_DATA0 | ||
| 417 | mov bx,TSSD_GSEL | ||
| 418 | call SetSegDesc ; Set up TSS alias descriptor | ||
| 419 | |||
| 420 | ; | ||
| 421 | ; fixup new RING 0 stack location | ||
| 422 | ; | ||
| 423 | mov ax,[_emm_brk] ; get EMM break address | ||
| 424 | add ax,15 ; round up to next paragraph | ||
| 425 | shr ax,4 | ||
| 426 | add ax,seg _DATA ; AX = new seg address for STACK | ||
| 427 | mov [STACK_seg],ax ; save it | ||
| 428 | |||
| 429 | call SegTo24 | ||
| 430 | mov cx,offset STACK0_SIZE ; length of stack | ||
| 431 | mov ah,D_DATA0 | ||
| 432 | mov bx,VDMS_GSEL | ||
| 433 | call SetSegDesc ; Set up STACK segment GDT entry | ||
| 434 | |||
| 435 | ; | ||
| 436 | ; fixup far call / far jump references to _TEXT | ||
| 437 | ; | ||
| 438 | |||
| 439 | ; far call pointers in ELIM function table | ||
| 440 | mov ax,seg R_CODE | ||
| 441 | mov es,ax ; ES -> R_CODE | ||
| 442 | mov di,offset R_CODE:EFunTab+2 ; ES:DI -> 1st seg in func tab | ||
| 443 | mov cx,EFUN_CNT ; CX = # of dword entries | ||
| 444 | mov ax,[TEXT_Seg] | ||
| 445 | IT_Tloop: | ||
| 446 | stosw ; store new TEXT seg | ||
| 447 | inc di | ||
| 448 | inc di ; point to next seg in table | ||
| 449 | loop IT_Tloop | ||
| 450 | |||
| 451 | ; ELIM_rEntry far call | ||
| 452 | mov di,offset R_CODE:EMM_rEfix ; point to far call | ||
| 453 | mov ES:[di+3],ax ; set seg portion of call | ||
| 454 | |||
| 455 | ; Far jump in return to real code | ||
| 456 | mov es,ax ; ES -> new TEXT seg | ||
| 457 | mov di,offset _TEXT:Real_Seg ; ES:DI -> seg of far jmp | ||
| 458 | mov ES:[di],ax ; fix it | ||
| 459 | |||
| 460 | ; | ||
| 461 | ; reset break address for driver - throw away _TEXT seg and all after it | ||
| 462 | ; | ||
| 463 | mov word ptr [driver_end],10h ; just in case | ||
| 464 | mov ax,[STACK_Seg] ; begin of new stack location | ||
| 465 | add ax,STACK0_SIZE/10h ; add in size of stack | ||
| 466 | mov word ptr [driver_end+2],ax ; set break seg to end of stack | ||
| 467 | |||
| 468 | ; | ||
| 469 | ; OK, now lock high system RAM | ||
| 470 | ; | ||
| 471 | call LockROM | ||
| 472 | ; | ||
| 473 | IT_exit: | ||
| 474 | popf | ||
| 475 | clc ; No error in memory allocation attempt | ||
| 476 | IT_quit: | ||
| 477 | pop es | ||
| 478 | pop ds | ||
| 479 | pop di | ||
| 480 | POP_EAX | ||
| 481 | else | ||
| 482 | |||
| 483 | push es | ||
| 484 | push di | ||
| 485 | push eax | ||
| 486 | push dx | ||
| 487 | push cx | ||
| 488 | push bx | ||
| 489 | ; | ||
| 490 | ; try to move the pageseg up | ||
| 491 | ; | ||
| 492 | ; | ||
| 493 | ; segment to be moved up | ||
| 494 | ; | ||
| 495 | mov ax, [PageD_Seg] | ||
| 496 | mov es,ax | ||
| 497 | ; | ||
| 498 | ; its length | ||
| 499 | ; | ||
| 500 | mov ax,seg LAST | ||
| 501 | sub ax,seg PAGESEG | ||
| 502 | shl ax,4 | ||
| 503 | mov cx,ax | ||
| 504 | ; | ||
| 505 | ; we need to allocate enough to have a page aligned page directory. so | ||
| 506 | ; increase this by 4k | ||
| 507 | push cx | ||
| 508 | add cx,4*1024 | ||
| 509 | ; | ||
| 510 | ; allocate a block of memory for this | ||
| 511 | |||
| 512 | call get_buffer | ||
| 513 | pop cx | ||
| 514 | jc no_mem | ||
| 515 | ; | ||
| 516 | ; dx:ax is new address of page directory, adjust this to be page aligned | ||
| 517 | ; | ||
| 518 | add ax,4*1024 | ||
| 519 | adc dx,0 | ||
| 520 | and ax,0F000h | ||
| 521 | ; | ||
| 522 | push ax | ||
| 523 | push dx | ||
| 524 | push cx | ||
| 525 | ; | ||
| 526 | add ax,1000h | ||
| 527 | adc dx,0h | ||
| 528 | ; | ||
| 529 | ; set the entries in the page directory for these | ||
| 530 | ; | ||
| 531 | xor di,di ; es:di points to first page_dir entry | ||
| 532 | mov bh,0 | ||
| 533 | mov bl, P_AVAIL | ||
| 534 | mov cx,P_TABLE_CNT | ||
| 535 | set_entries: | ||
| 536 | call SetPageEntry | ||
| 537 | ; | ||
| 538 | ; es:di points to next entry in page directory | ||
| 539 | ; | ||
| 540 | add ax,1000h | ||
| 541 | adc dx,0 ; next page table | ||
| 542 | loop set_entries | ||
| 543 | ; | ||
| 544 | ; now we can move the page directory and tables up into extended | ||
| 545 | ; | ||
| 546 | pop cx | ||
| 547 | pop dx | ||
| 548 | pop ax | ||
| 549 | ; | ||
| 550 | xor di,di ; es:di is now the beginning, cx count of | ||
| 551 | ; number of bytes in segment and dx:ax area | ||
| 552 | ; where it is to be moved | ||
| 553 | call moveb ; move the data | ||
| 554 | jnz move_error ; there was an error in moving. the page | ||
| 555 | ; table entries need to be restored to the | ||
| 556 | ; lo memory stuff | ||
| 557 | ; | ||
| 558 | ; move succeded, fix page directory address and driver_end | ||
| 559 | ; | ||
| 560 | mov word ptr [Page_Dir],ax ; DX,AX = 32 bit addr of Page Directory | ||
| 561 | mov word ptr [Page_Dir+2],dx ; save it | ||
| 562 | ; | ||
| 563 | ; reset PAGET_GSEL descriptor | ||
| 564 | ; | ||
| 565 | mov cx,seg GDT ; GDT has not yet moved!!! | ||
| 566 | mov es,cx ; ES pts to GDT | ||
| 567 | |||
| 568 | add ax,1000h | ||
| 569 | adc dx,0 | ||
| 570 | xchg ax,dx ; for setsegdesc in opposite | ||
| 571 | ; al:dx | ||
| 572 | |||
| 573 | mov cx,0 ; enough room for tables | ||
| 574 | mov ah,D_DATA0 | ||
| 575 | mov bx,PAGET_GSEL | ||
| 576 | call SetSegDesc ; set up page table descriptor | ||
| 577 | ; | ||
| 578 | ; if we succeed in shifting the page tables up the ground is clear for us | ||
| 579 | ; to shrink the driver even more to the point where the variable emm data | ||
| 580 | ; structures end. | ||
| 581 | ; | ||
| 582 | mov ax,[_emm_brk] ; get EMM break address | ||
| 583 | add ax,15 ; round up to next paragraph | ||
| 584 | shr ax,4 | ||
| 585 | add ax,seg DGROUP ; AX = end address for driver | ||
| 586 | mov word ptr [driver_end],10h ; just in case, para offset | ||
| 587 | mov word ptr [driver_end+2],ax ; segment | ||
| 588 | |||
| 589 | |||
| 590 | no_mem: | ||
| 591 | pop bx | ||
| 592 | pop cx | ||
| 593 | pop dx | ||
| 594 | pop eax | ||
| 595 | pop di | ||
| 596 | pop es | ||
| 597 | clc | ||
| 598 | jmp end_inittab | ||
| 599 | |||
| 600 | move_error: | ||
| 601 | ; the address of page table in lo mem | ||
| 602 | ; | ||
| 603 | mov ax,[PageT_Seg] | ||
| 604 | mov cx,4 | ||
| 605 | xor dx,dx | ||
| 606 | mul cx | ||
| 607 | ; | ||
| 608 | ; set the entries in the page directory for these | ||
| 609 | ; | ||
| 610 | xor di,di ; es:di points to first page_dir entry | ||
| 611 | mov bh,0 | ||
| 612 | mov bl, P_AVAIL | ||
| 613 | mov cx,P_TABLE_CNT | ||
| 614 | restore_entries: | ||
| 615 | call SetPageEntry | ||
| 616 | ; | ||
| 617 | ; es:di points to next entry in page directory | ||
| 618 | ; | ||
| 619 | add ax,1000h | ||
| 620 | adc dx,0 ; next page table | ||
| 621 | loop restore_entries | ||
| 622 | ; | ||
| 623 | jmp no_mem | ||
| 624 | endif | ||
| 625 | end_inittab: | ||
| 626 | ret | ||
| 627 | ; | ||
| 628 | InitTab endp | ||
| 629 | ; | ||
| 630 | LAST ends ; end of segment | ||
| 631 | ; | ||
| 632 | end ; end of module | ||
diff --git a/v4.0/src/MEMM/MEMM/INSTR386.INC b/v4.0/src/MEMM/MEMM/INSTR386.INC new file mode 100644 index 0000000..490435a --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INSTR386.INC | |||
| @@ -0,0 +1,563 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: INSTR386 - 386 Instruction Macro Declaration file | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: May 11, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 05/11/86 Original | ||
| 24 | ; 06/01/86 Added operand/address size overide defines | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; 07/01/86 0.03 Added 32 arithmetic defines | ||
| 27 | ; | ||
| 28 | ;****************************************************************************** | ||
| 29 | ifndef INC_LIST | ||
| 30 | .xlist | ||
| 31 | endif | ||
| 32 | |||
| 33 | ;*** OP32_IRET - 32 bit mode iret | ||
| 34 | OP32_IRET macro | ||
| 35 | db 66h | ||
| 36 | iret | ||
| 37 | endm | ||
| 38 | |||
| 39 | ;*** OP32 - instruction prefix to invert sense of operand size attribute | ||
| 40 | |||
| 41 | OP32 macro | ||
| 42 | db 66h | ||
| 43 | endm | ||
| 44 | |||
| 45 | |||
| 46 | ;*** EA32 - instruction prefix to invert sense of effective addr attribute | ||
| 47 | |||
| 48 | EA32 macro | ||
| 49 | db 67h | ||
| 50 | endm | ||
| 51 | |||
| 52 | |||
| 53 | ;*** FS and GS overides | ||
| 54 | FSOVER macro | ||
| 55 | db 64h | ||
| 56 | endm | ||
| 57 | GSOVER macro | ||
| 58 | db 65h | ||
| 59 | endm | ||
| 60 | |||
| 61 | ; *** General Register 32 bit moves *** | ||
| 62 | |||
| 63 | MOV_EBX_EAX macro | ||
| 64 | db 66h | ||
| 65 | mov bx, ax | ||
| 66 | endm | ||
| 67 | |||
| 68 | MOV_EAX_EBX macro | ||
| 69 | db 66h | ||
| 70 | mov ax, bx | ||
| 71 | endm | ||
| 72 | |||
| 73 | MOV_ECX_EAX macro | ||
| 74 | db 66h | ||
| 75 | mov cx, ax | ||
| 76 | endm | ||
| 77 | |||
| 78 | MOV_EAX_ECX macro | ||
| 79 | db 66h | ||
| 80 | mov ax, cx | ||
| 81 | endm | ||
| 82 | |||
| 83 | MOV_EDX_EAX macro | ||
| 84 | db 66h | ||
| 85 | mov dx, ax | ||
| 86 | endm | ||
| 87 | |||
| 88 | MOV_EAX_EDX macro | ||
| 89 | db 66h | ||
| 90 | mov ax, dx | ||
| 91 | endm | ||
| 92 | |||
| 93 | MOV_EDI_EAX macro | ||
| 94 | db 66h | ||
| 95 | mov di, ax | ||
| 96 | endm | ||
| 97 | |||
| 98 | MOV_EAX_EDI macro | ||
| 99 | db 66h | ||
| 100 | mov ax, di | ||
| 101 | endm | ||
| 102 | |||
| 103 | MOV_ESI_EAX macro | ||
| 104 | db 66h | ||
| 105 | mov si, ax | ||
| 106 | endm | ||
| 107 | |||
| 108 | MOV_EAX_ESI macro | ||
| 109 | db 66h | ||
| 110 | mov ax, si | ||
| 111 | endm | ||
| 112 | |||
| 113 | MOV_EBP_EAX macro | ||
| 114 | db 66h | ||
| 115 | mov bp, ax | ||
| 116 | endm | ||
| 117 | |||
| 118 | MOV_EAX_EBP macro | ||
| 119 | db 66h | ||
| 120 | mov ax, bp | ||
| 121 | endm | ||
| 122 | |||
| 123 | MOV_ESP_EAX macro | ||
| 124 | db 66h | ||
| 125 | mov sp, ax | ||
| 126 | endm | ||
| 127 | |||
| 128 | MOV_EAX_ESP macro | ||
| 129 | db 66h | ||
| 130 | mov ax, sp | ||
| 131 | endm | ||
| 132 | |||
| 133 | ; *** Special Register/EAX 32 bit moves *** | ||
| 134 | |||
| 135 | MOV_CR0_EAX macro | ||
| 136 | db 0Fh,22h,0C0h | ||
| 137 | endm | ||
| 138 | |||
| 139 | MOV_CR0_EBX macro | ||
| 140 | db 0Fh,22h,0C3h | ||
| 141 | endm | ||
| 142 | |||
| 143 | MOV_CR0_ECX macro | ||
| 144 | db 0Fh,22h,0C1h | ||
| 145 | endm | ||
| 146 | |||
| 147 | MOV_CR0_EDX macro | ||
| 148 | db 0Fh,22h,0C2h | ||
| 149 | endm | ||
| 150 | |||
| 151 | MOV_CR0_ESP macro | ||
| 152 | db 0Fh,22h,0C4h | ||
| 153 | endm | ||
| 154 | |||
| 155 | MOV_CR0_EBP macro | ||
| 156 | db 0Fh,22h,0C5h | ||
| 157 | endm | ||
| 158 | |||
| 159 | MOV_CR0_ESI macro | ||
| 160 | db 0Fh,22h,0C6h | ||
| 161 | endm | ||
| 162 | |||
| 163 | MOV_CR0_EDI macro | ||
| 164 | db 0Fh,22h,0C7h | ||
| 165 | endm | ||
| 166 | |||
| 167 | MOV_EAX_CR0 macro | ||
| 168 | db 0Fh,20h,0C0h | ||
| 169 | endm | ||
| 170 | |||
| 171 | MOV_EBX_CR0 macro | ||
| 172 | db 0Fh,20h,0C3h | ||
| 173 | endm | ||
| 174 | |||
| 175 | MOV_ECX_CR0 macro | ||
| 176 | db 0Fh,20h,0C1h | ||
| 177 | endm | ||
| 178 | |||
| 179 | MOV_EDX_CR0 macro | ||
| 180 | db 0Fh,20h,0C2h | ||
| 181 | endm | ||
| 182 | |||
| 183 | MOV_ESP_CR0 macro | ||
| 184 | db 0Fh,20h,0C4h | ||
| 185 | endm | ||
| 186 | |||
| 187 | MOV_EBP_CR0 macro | ||
| 188 | db 0Fh,20h,0C5h | ||
| 189 | endm | ||
| 190 | |||
| 191 | MOV_ESI_CR0 macro | ||
| 192 | db 0Fh,20h,0C6h | ||
| 193 | endm | ||
| 194 | |||
| 195 | MOV_EDI_CR0 macro | ||
| 196 | db 0Fh,20h,0C7h | ||
| 197 | endm | ||
| 198 | |||
| 199 | MOV_CR2_EAX macro | ||
| 200 | db 0Fh,22h,0D0h | ||
| 201 | endm | ||
| 202 | |||
| 203 | MOV_EAX_CR2 macro | ||
| 204 | db 0Fh,20h,0D0h | ||
| 205 | endm | ||
| 206 | |||
| 207 | MOV_CR3_EAX macro | ||
| 208 | db 0Fh,22h,0D8h | ||
| 209 | endm | ||
| 210 | |||
| 211 | MOV_EAX_CR3 macro | ||
| 212 | db 0Fh,20h,0D8h | ||
| 213 | endm | ||
| 214 | |||
| 215 | MOV_DR0_EAX macro | ||
| 216 | db 0Fh,23h,0C0h | ||
| 217 | endm | ||
| 218 | |||
| 219 | MOV_DR0_EBX macro | ||
| 220 | db 0Fh,23h,0C3h | ||
| 221 | endm | ||
| 222 | |||
| 223 | MOV_DR1_EAX macro | ||
| 224 | db 0Fh,23h,0C8h | ||
| 225 | endm | ||
| 226 | |||
| 227 | MOV_DR2_EAX macro | ||
| 228 | db 0Fh,23h,0D0h | ||
| 229 | endm | ||
| 230 | |||
| 231 | MOV_DR3_EAX macro | ||
| 232 | db 0Fh,23h,0D8h | ||
| 233 | endm | ||
| 234 | |||
| 235 | MOV_DR6_EAX macro | ||
| 236 | db 0Fh,23h,0F0h | ||
| 237 | endm | ||
| 238 | |||
| 239 | MOV_DR7_EAX macro | ||
| 240 | db 0Fh,23h,0F8h | ||
| 241 | endm | ||
| 242 | |||
| 243 | MOV_EAX_DR0 macro | ||
| 244 | db 0Fh,21h,0C0h | ||
| 245 | endm | ||
| 246 | |||
| 247 | MOV_ECX_DR0 macro | ||
| 248 | db 0Fh,21h,0C1h | ||
| 249 | endm | ||
| 250 | |||
| 251 | MOV_EDX_DR0 macro | ||
| 252 | db 0Fh,21h,0C2h | ||
| 253 | endm | ||
| 254 | |||
| 255 | MOV_EAX_DR1 macro | ||
| 256 | db 0Fh,21h,0C8h | ||
| 257 | endm | ||
| 258 | |||
| 259 | MOV_EAX_DR2 macro | ||
| 260 | db 0Fh,21h,0D0h | ||
| 261 | endm | ||
| 262 | |||
| 263 | MOV_EAX_DR3 macro | ||
| 264 | db 0Fh,21h,0D8h | ||
| 265 | endm | ||
| 266 | |||
| 267 | MOV_EAX_DR6 macro | ||
| 268 | db 0Fh,21h,0F0h | ||
| 269 | endm | ||
| 270 | |||
| 271 | MOV_EAX_DR7 macro | ||
| 272 | db 0Fh,21h,0F8h | ||
| 273 | endm | ||
| 274 | |||
| 275 | MOV_TR6_EAX macro | ||
| 276 | db 0Fh,26h,0F0h | ||
| 277 | endm | ||
| 278 | |||
| 279 | MOV_EAX_TR6 macro | ||
| 280 | db 0Fh,24h,0F0h | ||
| 281 | endm | ||
| 282 | |||
| 283 | MOV_TR7_EAX macro | ||
| 284 | db 0Fh,26h,0F8h | ||
| 285 | endm | ||
| 286 | |||
| 287 | MOV_EAX_TR7 macro | ||
| 288 | db 0Fh,24h,0F8h | ||
| 289 | endm | ||
| 290 | |||
| 291 | ; *** 32 bit Register/Immediate moves *** | ||
| 292 | |||
| 293 | MOV_EAX_ macro imm | ||
| 294 | db 66h, 0B8h | ||
| 295 | dd imm | ||
| 296 | endm | ||
| 297 | |||
| 298 | MOV_EBX_ macro imm | ||
| 299 | db 66h, 0BBh | ||
| 300 | dd imm | ||
| 301 | endm | ||
| 302 | |||
| 303 | MOV_ECX_ macro imm | ||
| 304 | db 66h, 0B9h | ||
| 305 | dd imm | ||
| 306 | endm | ||
| 307 | |||
| 308 | MOV_EDX_ macro imm | ||
| 309 | db 66h, 0BAh | ||
| 310 | dd imm | ||
| 311 | endm | ||
| 312 | |||
| 313 | MOV_EDI_ macro imm | ||
| 314 | db 66h, 0BFh | ||
| 315 | dd imm | ||
| 316 | endm | ||
| 317 | |||
| 318 | MOV_ESI_ macro imm | ||
| 319 | db 66h, 0BEh | ||
| 320 | dd imm | ||
| 321 | endm | ||
| 322 | |||
| 323 | MOV_EBP_ macro imm | ||
| 324 | db 66h, 0BDh | ||
| 325 | dd imm | ||
| 326 | endm | ||
| 327 | |||
| 328 | MOV_ESP_ macro imm | ||
| 329 | db 66h, 0BCh | ||
| 330 | dd imm | ||
| 331 | endm | ||
| 332 | |||
| 333 | ; *** 32-bit immediate arithmetic instructions | ||
| 334 | |||
| 335 | ADD_EAX_ macro imm | ||
| 336 | db 66h,05h | ||
| 337 | dd imm | ||
| 338 | endm | ||
| 339 | |||
| 340 | ADD_EBX_ macro imm | ||
| 341 | db 66h,81h,0C3h | ||
| 342 | dd imm | ||
| 343 | endm | ||
| 344 | |||
| 345 | ADD_ECX_ macro imm | ||
| 346 | db 66h,81h,0C1h | ||
| 347 | dd imm | ||
| 348 | endm | ||
| 349 | |||
| 350 | ADD_EDX_ macro imm | ||
| 351 | db 66h,81h,0C2h | ||
| 352 | dd imm | ||
| 353 | endm | ||
| 354 | |||
| 355 | SUB_EAX_ macro imm | ||
| 356 | db 66h,2Dh | ||
| 357 | dd imm | ||
| 358 | endm | ||
| 359 | |||
| 360 | SUB_EBX_ macro imm | ||
| 361 | db 66h,81h,0EBh | ||
| 362 | dd imm | ||
| 363 | endm | ||
| 364 | |||
| 365 | SUB_ECX_ macro imm | ||
| 366 | db 66h,81h,0E9h | ||
| 367 | dd imm | ||
| 368 | endm | ||
| 369 | |||
| 370 | SUB_EDX_ macro imm | ||
| 371 | db 66h,81h,0EAh | ||
| 372 | dd imm | ||
| 373 | endm | ||
| 374 | |||
| 375 | CMP_EAX_ macro imm | ||
| 376 | db 66h,3Dh | ||
| 377 | dd imm | ||
| 378 | endm | ||
| 379 | |||
| 380 | CMP_EBX_ macro imm | ||
| 381 | db 66h,81h,0FBh | ||
| 382 | dd imm | ||
| 383 | endm | ||
| 384 | |||
| 385 | CMP_ECX_ macro imm | ||
| 386 | db 66h,81h,0F9h | ||
| 387 | dd imm | ||
| 388 | endm | ||
| 389 | |||
| 390 | CMP_EDX_ macro imm | ||
| 391 | db 66h,81h,0FAh | ||
| 392 | dd imm | ||
| 393 | endm | ||
| 394 | |||
| 395 | ; *** New Segment Register/AX moves *** | ||
| 396 | |||
| 397 | MOV_FS_AX macro | ||
| 398 | db 8Eh,0E0h | ||
| 399 | endm | ||
| 400 | |||
| 401 | MOV_AX_FS macro | ||
| 402 | db 8Ch,0E0h | ||
| 403 | endm | ||
| 404 | |||
| 405 | MOV_GS_AX macro | ||
| 406 | db 8Eh,0E8h | ||
| 407 | endm | ||
| 408 | |||
| 409 | MOV_AX_GS macro | ||
| 410 | db 8Ch,0E8h | ||
| 411 | endm | ||
| 412 | |||
| 413 | ; *** New Segment Register pushes & pops *** | ||
| 414 | |||
| 415 | PUSH_FS macro | ||
| 416 | db 0Fh,0A0h | ||
| 417 | endm | ||
| 418 | |||
| 419 | PUSH_GS macro | ||
| 420 | db 0Fh,0A8h | ||
| 421 | endm | ||
| 422 | |||
| 423 | POP_FS macro | ||
| 424 | db 0Fh,0A1h | ||
| 425 | endm | ||
| 426 | |||
| 427 | POP_GS macro | ||
| 428 | db 0Fh,0A9h | ||
| 429 | endm | ||
| 430 | |||
| 431 | ; *** New Segment Register offset 16 memory moves *** | ||
| 432 | |||
| 433 | MOV_off16_FS macro off16 | ||
| 434 | db 8Ch,26h | ||
| 435 | dw off16 | ||
| 436 | endm | ||
| 437 | |||
| 438 | MOV_FS_off16 macro off16 | ||
| 439 | db 8Eh,26h | ||
| 440 | dw off16 | ||
| 441 | endm | ||
| 442 | |||
| 443 | MOV_off16_GS macro off16 | ||
| 444 | db 8Ch,2Eh | ||
| 445 | dw off16 | ||
| 446 | endm | ||
| 447 | |||
| 448 | MOV_GS_off16 macro off16 | ||
| 449 | db 8Eh,2Eh | ||
| 450 | dw off16 | ||
| 451 | endm | ||
| 452 | |||
| 453 | ; *** General Register 32 bit pushes & pops *** | ||
| 454 | |||
| 455 | PUSH_EAX macro | ||
| 456 | db 66h | ||
| 457 | push ax | ||
| 458 | endm | ||
| 459 | |||
| 460 | POP_EAX macro | ||
| 461 | db 66h | ||
| 462 | pop ax | ||
| 463 | endm | ||
| 464 | |||
| 465 | PUSH_EBX macro | ||
| 466 | db 66h | ||
| 467 | push bx | ||
| 468 | endm | ||
| 469 | |||
| 470 | POP_EBX macro | ||
| 471 | db 66h | ||
| 472 | pop bx | ||
| 473 | endm | ||
| 474 | |||
| 475 | PUSH_ECX macro | ||
| 476 | db 66h | ||
| 477 | push cx | ||
| 478 | endm | ||
| 479 | |||
| 480 | POP_ECX macro | ||
| 481 | db 66h | ||
| 482 | pop cx | ||
| 483 | endm | ||
| 484 | |||
| 485 | PUSH_EDX macro | ||
| 486 | db 66h | ||
| 487 | push dx | ||
| 488 | endm | ||
| 489 | |||
| 490 | POP_EDX macro | ||
| 491 | db 66h | ||
| 492 | pop dx | ||
| 493 | endm | ||
| 494 | |||
| 495 | PUSH_EDI macro | ||
| 496 | db 66h | ||
| 497 | push di | ||
| 498 | endm | ||
| 499 | |||
| 500 | POP_EDI macro | ||
| 501 | db 66h | ||
| 502 | pop di | ||
| 503 | endm | ||
| 504 | |||
| 505 | PUSH_ESI macro | ||
| 506 | db 66h | ||
| 507 | push si | ||
| 508 | endm | ||
| 509 | |||
| 510 | POP_ESI macro | ||
| 511 | db 66h | ||
| 512 | pop si | ||
| 513 | endm | ||
| 514 | |||
| 515 | PUSH_EBP macro | ||
| 516 | db 66h | ||
| 517 | push bp | ||
| 518 | endm | ||
| 519 | |||
| 520 | POP_EBP macro | ||
| 521 | db 66h | ||
| 522 | pop bp | ||
| 523 | endm | ||
| 524 | |||
| 525 | PUSH_ESP macro | ||
| 526 | db 66h | ||
| 527 | push sp | ||
| 528 | endm | ||
| 529 | |||
| 530 | POP_ESP macro | ||
| 531 | db 66h | ||
| 532 | pop sp | ||
| 533 | endm | ||
| 534 | |||
| 535 | |||
| 536 | ; *** General Register 32 bit xors *** | ||
| 537 | |||
| 538 | XOR_EAX_EAX macro | ||
| 539 | db 66h | ||
| 540 | xor ax, ax | ||
| 541 | endm | ||
| 542 | |||
| 543 | XOR_EBX_EBX macro | ||
| 544 | db 66h | ||
| 545 | xor bx, bx | ||
| 546 | endm | ||
| 547 | |||
| 548 | XOR_ECX_ECX macro | ||
| 549 | db 66h | ||
| 550 | xor cx, cx | ||
| 551 | endm | ||
| 552 | |||
| 553 | XOR_EDX_EDX macro | ||
| 554 | db 66h | ||
| 555 | xor dx, dx | ||
| 556 | endm | ||
| 557 | |||
| 558 | XOR_EBP_EBP macro | ||
| 559 | db 66h | ||
| 560 | xor bp, bp | ||
| 561 | endm | ||
| 562 | |||
| 563 | .list ; end of INSTR386.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/IOTRAP.ASM b/v4.0/src/MEMM/MEMM/IOTRAP.ASM new file mode 100644 index 0000000..eb7d79c --- /dev/null +++ b/v4.0/src/MEMM/MEMM/IOTRAP.ASM | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title IOTRAP.ASM - Dispatches I/O trap handlers | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: IOTRAP.ASM - Dispatches I/O trap handlers | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: July 1, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 07/01/86 0.03 From ELIMTRAP.ASM | ||
| 27 | ; 07/03/86 0.03 Added handlers for 84,85,60, & 64 | ||
| 28 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 29 | ; | ||
| 30 | ;****************************************************************************** | ||
| 31 | ; | ||
| 32 | ; Functional Description: | ||
| 33 | ; | ||
| 34 | ; This routine is called by all I/O space trap handlers to allow | ||
| 35 | ; emulation/monitoring of I/O address reads and writes. When a GP fault | ||
| 36 | ; occurs due to I/O to an address trapped in the I/O Bit Map, the I/O | ||
| 37 | ; instruction emulation routine in VMINST calls this routine. This | ||
| 38 | ; routine calls the appropriate I/O trap handler for the I/O address. | ||
| 39 | ; | ||
| 40 | ;****************************************************************************** | ||
| 41 | .lfcond ; list false conditionals | ||
| 42 | .386p | ||
| 43 | page | ||
| 44 | page | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; P U B L I C D E C L A R A T I O N S | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | public IO_Trap ; dispatches I/O trap handlers | ||
| 50 | |||
| 51 | ;****************************************************************************** | ||
| 52 | ; L O C A L C O N S T A N T S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | FALSE equ 0 | ||
| 56 | TRUE equ not FALSE | ||
| 57 | |||
| 58 | include VDMseg.inc | ||
| 59 | include VDMsel.inc | ||
| 60 | |||
| 61 | ;****************************************************************************** | ||
| 62 | ; E X T E R N A L R E F E R E N C E S | ||
| 63 | ;****************************************************************************** | ||
| 64 | |||
| 65 | _TEXT segment | ||
| 66 | |||
| 67 | extrn IOTrap_Tab:word ; System board IO trap routine address table | ||
| 68 | extrn IOT_BadT:near ; Routine to execute for unknown port | ||
| 69 | ;extrn IOT_LIM:near ; Routine to handle LIM emulated ports | ||
| 70 | extrn IOT_OEM:near ; Routine to handle OEM specific emulate ports | ||
| 71 | |||
| 72 | _TEXT ends | ||
| 73 | |||
| 74 | ;****************************************************************************** | ||
| 75 | ; S E G M E N T D E F I N I T I O N | ||
| 76 | ;****************************************************************************** | ||
| 77 | |||
| 78 | _TEXT segment | ||
| 79 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 80 | |||
| 81 | ;****************************************************************************** | ||
| 82 | ; IO_Trap - Dispatches trap handler for an I/O address | ||
| 83 | ; | ||
| 84 | ; ENTRY: Protected Mode Ring 0 | ||
| 85 | ; AL = byte to output to port. | ||
| 86 | ; DX = port address for I/O. | ||
| 87 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 88 | ; BX = 0 => Emulate Input. | ||
| 89 | ; <>0 => Emulate Output. | ||
| 90 | ; | ||
| 91 | ; EXIT: Protected Mode Ring 0 | ||
| 92 | ; AL = emulated input value from port. | ||
| 93 | ; CLC => I/O emulated by LIM_Trap. | ||
| 94 | ; STC => I/O NOT emulated by LIM_Trap. | ||
| 95 | ; | ||
| 96 | ; WARNING:*********** | ||
| 97 | ; This routine is closely allied with IOTBadT which is in TrapDef. | ||
| 98 | ; IOTBadT assumes that the stack is in a certain state! | ||
| 99 | ; *********** | ||
| 100 | ; | ||
| 101 | ; | ||
| 102 | ; USED: Flags | ||
| 103 | ; STACK: | ||
| 104 | ;------------------------------------------------------------------------------ | ||
| 105 | IO_Trap proc near | ||
| 106 | ; | ||
| 107 | push ds | ||
| 108 | push dx | ||
| 109 | |||
| 110 | push VDMD_GSEL | ||
| 111 | pop ds ; set DS = DGROUP | ||
| 112 | |||
| 113 | cmp dx,0100h ;Q: I/O Addr < 0100h (system brd port)? | ||
| 114 | jae IOT_NotSys ; N: check mapping regs | ||
| 115 | IOT_Sys: ; Y: dispatch I/O trap handler | ||
| 116 | xchg bx, dx ; BL = port address | ||
| 117 | shl bx,1 ; BX = BX*2 (word table) | ||
| 118 | call cs:IOTrap_Tab[bx] ; call handler | ||
| 119 | ; ENTRY: entry DX,DS on stack | ||
| 120 | ; DS = DGROUP selector | ||
| 121 | ; BX = 2 * port address in 0100h range | ||
| 122 | ; DX = input/output flag | ||
| 123 | |||
| 124 | xchg bx,dx ; reset bx | ||
| 125 | pop dx ; | ||
| 126 | pop ds ; reset dx | ||
| 127 | ret ; CF = 1 if I/O not emulated | ||
| 128 | |||
| 129 | ; | ||
| 130 | ; Address >= 0100h | ||
| 131 | |||
| 132 | IOT_NotSys: | ||
| 133 | ; | ||
| 134 | ; check for OEM specific I/O emulation | ||
| 135 | ; | ||
| 136 | call IOT_OEM ;If emulated by OEM specific routine | ||
| 137 | ; does not return(returns from IO_Trap) | ||
| 138 | ; NOTE : we don't have LIM h/w port anymore | ||
| 139 | ; | ||
| 140 | ; check for LIM mapping register address | ||
| 141 | ; | ||
| 142 | ; call IOT_LIM ;If emulated by LIM emulation routine | ||
| 143 | ; does not return(returns from IO_Trap) | ||
| 144 | |||
| 145 | ; | ||
| 146 | ; Here if I/O Address >= 0100h and not a mapping register | ||
| 147 | ; map it into 1k and try system board ports again | ||
| 148 | ; | ||
| 149 | and dx,3FFh ; map address into 1k range | ||
| 150 | cmp dx,0100h ;Q: I/O Addr < 0100h (system brd port)? | ||
| 151 | jb IOT_Sys ; Y: check system ports | ||
| 152 | ; N: unknown port | ||
| 153 | xchg bx,dx ; put Input/Output flag in DX for IOT_BadT | ||
| 154 | shl bx,1 | ||
| 155 | call IOT_BadT | ||
| 156 | jmp $ ;IOT_BadT pops return address off restores regs | ||
| 157 | ; and returns | ||
| 158 | |||
| 159 | IO_Trap endp | ||
| 160 | |||
| 161 | |||
| 162 | _TEXT ends | ||
| 163 | |||
| 164 | end | ||
| 165 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/KBD.ASM b/v4.0/src/MEMM/MEMM/KBD.ASM new file mode 100644 index 0000000..3616c1e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/KBD.ASM | |||
| @@ -0,0 +1,1608 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title KBD.ASM - - protected mode AT keyboard driver | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMMD.EXE - MICROSOFT Expanded Memory Manager 386 DEBUG Driver | ||
| 11 | ; | ||
| 12 | ; Module: KBD.ASM - - protected mode AT keyboard driver for debugger | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Original | ||
| 27 | ; A- Removed STIs and changed CLI/STIs to keep interrupt | ||
| 28 | ; status stable (OFF) during debugger execution. The | ||
| 29 | ; specific problem was in reporting unexpected traps | ||
| 30 | ; fielded from Virtual Mode during DOS execution, | ||
| 31 | ; e.g. timer ticks. | ||
| 32 | ; B- Fixed Ctrl-NumLock, Ctrl-Alt-Del, Ctrl-Break, and | ||
| 33 | ; Shift-PrtSc | ||
| 34 | ; 05/12/86 C Cleanup and segment reorganization | ||
| 35 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 36 | ; 07/05/86 0.04 Moved to DCODE segment | ||
| 37 | ; | ||
| 38 | ;****************************************************************************** | ||
| 39 | ; | ||
| 40 | ; Functional Description: | ||
| 41 | ; | ||
| 42 | ; THIS CODE IS USED BY THE DEBUGGER ONLY ! | ||
| 43 | ; | ||
| 44 | ; This is a PC/AT keyboard driver capable of running | ||
| 45 | ; in protected mode. It does not require any ROM support. | ||
| 46 | ; | ||
| 47 | ; The major modifications are: | ||
| 48 | ; | ||
| 49 | ; - Remove foreign tables, use US only | ||
| 50 | ; - Hard code machine type rather than looking in ROM | ||
| 51 | ; - hard code BeepFreq, BeepDur | ||
| 52 | ; - removed KeyVector, put read-only data in CS | ||
| 53 | ; - removed Accent stuff, which had code writes | ||
| 54 | ; - removed code writes in foreign kbd | ||
| 55 | ; - removed INT 15h sysreq and post | ||
| 56 | ; - removed T&SR stuff, added buffer read routine "getc" | ||
| 57 | ; - made it polled, removed all interrupt stuff | ||
| 58 | ; - changed "data" segment to "romdata" | ||
| 59 | ; | ||
| 60 | ; | ||
| 61 | ; SCCSID = @(#)keybxx.asm 4.1 85/10/09 | ||
| 62 | ;------------------------------------------------------ | ||
| 63 | ; | ||
| 64 | ; KEYBXX - foreign keyboard driver. | ||
| 65 | ; | ||
| 66 | ; April 1985 by Michael Hanson | ||
| 67 | ; Copyright 1985 by Microsoft Corporation | ||
| 68 | ; | ||
| 69 | ; KeybXX is a keyboard handling program using tables | ||
| 70 | ; supplied in a separate file to do foreign language | ||
| 71 | ; keyboard support. It is the basis for the KEYB??.EXE | ||
| 72 | ; programs which use this program and the corresponding | ||
| 73 | ; table defined in KEYB??.ASM. | ||
| 74 | ; | ||
| 75 | ; KeybXX.OBJ must be linked with one of the Keyb??.OBJ | ||
| 76 | ; programs to work, the KEYB?? file must be first. | ||
| 77 | ; See the accompanying makefile for examples. | ||
| 78 | ; | ||
| 79 | ; Note: KEYB?? refers to any of KEYBFR ( French ), | ||
| 80 | ; KEYBGR (German), KEYBUK (United Kingdom), | ||
| 81 | ; KEYBIT (Italian), KEYBSP (Spanish) and | ||
| 82 | ; KEYBDV (Dvorak). These are the currently | ||
| 83 | ; defined data tables for KEYBXX. | ||
| 84 | ; | ||
| 85 | ; Compatability notes: | ||
| 86 | ; 1. The IBM foreign keyboard drivers don't return | ||
| 87 | ; anything for a CTRL-ALT space. This is not | ||
| 88 | ; what I expect from the manuals, but for | ||
| 89 | ; compatibility, KEYBXX doesn't return anything | ||
| 90 | ; in this case either. | ||
| 91 | ; | ||
| 92 | ; 2. For the AT the keyboard driver should do a post | ||
| 93 | ; call (int 15). The ROM keyboard driver does, but | ||
| 94 | ; IBM's foreign keyboard drivers appear not to. | ||
| 95 | ; Currently KEYBXX does a post code, though only | ||
| 96 | ; one is issued at any one time (that is, only 1 post | ||
| 97 | ; call for the 2 characters returned by an illegal | ||
| 98 | ; accent combination). | ||
| 99 | ; | ||
| 100 | ; This program is a modified version of the keyboard handler from - | ||
| 101 | ; | ||
| 102 | ; Microsoft Mach 10 Enhancement Software | ||
| 103 | ; | ||
| 104 | ; Copyright 1984 by Microsoft Corporation | ||
| 105 | ; Written June 1984 by Chris Peters | ||
| 106 | ; | ||
| 107 | ;****************************************************************************** | ||
| 108 | .lfcond ; list false conditionals | ||
| 109 | .386p | ||
| 110 | |||
| 111 | include VDMseg.inc | ||
| 112 | include desc.inc | ||
| 113 | include kbd.inc | ||
| 114 | |||
| 115 | |||
| 116 | MASTER_IMR equ 21h ; mask port for master 8259 | ||
| 117 | |||
| 118 | ;*** ROM BIOS data area, set up addresses | ||
| 119 | romdata segment use16 at 40h | ||
| 120 | org 17h | ||
| 121 | KeyState db ? | ||
| 122 | BreakState db ? | ||
| 123 | AltKey db ? | ||
| 124 | KbHead dw ? | ||
| 125 | KbTail dw ? | ||
| 126 | KbBuffer dw 16 dup (?) | ||
| 127 | KbBufferEnd label word | ||
| 128 | |||
| 129 | org 49h | ||
| 130 | VidMode db ? | ||
| 131 | org 65h | ||
| 132 | VidReg db ? | ||
| 133 | |||
| 134 | org 71h | ||
| 135 | fBreak db ? | ||
| 136 | fReset dw ? | ||
| 137 | |||
| 138 | org 80h | ||
| 139 | KbStart dw ? | ||
| 140 | KbEnd dw ? | ||
| 141 | |||
| 142 | org 97h | ||
| 143 | ATKbFlags db ? | ||
| 144 | romdata ends | ||
| 145 | |||
| 146 | |||
| 147 | |||
| 148 | ;*** Routines used by data table modules (Keyb??) | ||
| 149 | public SpecKey | ||
| 150 | public AlphaKey | ||
| 151 | public NormalKey | ||
| 152 | public Keys$2$13 | ||
| 153 | public CapKey | ||
| 154 | public Cap$2$13 | ||
| 155 | public FuncKey | ||
| 156 | public PadKey | ||
| 157 | public NumKey | ||
| 158 | public SpaceKey | ||
| 159 | public ShiftKey | ||
| 160 | public ScrollKey | ||
| 161 | public StateKey | ||
| 162 | ;public AccKey | ||
| 163 | public AltShiftKey | ||
| 164 | public BufferFull | ||
| 165 | public ReBoot | ||
| 166 | public XBoot | ||
| 167 | public PrintScreen | ||
| 168 | public SysReq | ||
| 169 | |||
| 170 | |||
| 171 | |||
| 172 | |||
| 173 | DCODE segment | ||
| 174 | assume cs:DCODE,ds:romdata,es:nothing | ||
| 175 | |||
| 176 | |||
| 177 | ;*** Tables for foreign language key layout | ||
| 178 | ; See Keyb?? files for more details | ||
| 179 | |||
| 180 | |||
| 181 | ;* Actual foreign language key layout | ||
| 182 | ; extrn ForeignTable :word | ||
| 183 | |||
| 184 | |||
| 185 | ;* Tables to map CNTRL ALT char | ||
| 186 | ; extrn AltChrs :byte | ||
| 187 | AltChrs label byte | ||
| 188 | ; extrn AltChrsEnd :byte | ||
| 189 | AltChrsEnd label byte | ||
| 190 | |||
| 191 | ; extrn AltMap :byte | ||
| 192 | AltMap label byte | ||
| 193 | |||
| 194 | |||
| 195 | ;* Tables to map accented characters | ||
| 196 | ; extrn AccentChTbl :word | ||
| 197 | AccentChTbl label word | ||
| 198 | |||
| 199 | ; extrn AccentMpTbl :word | ||
| 200 | AccentMpTbl label word | ||
| 201 | |||
| 202 | |||
| 203 | ;* Table of accent characters, shifted, ALTed and CTRLed. | ||
| 204 | ; defined using the AccChStruc struct | ||
| 205 | ; extrn AccChTbl :word | ||
| 206 | AccChTbl label word | ||
| 207 | |||
| 208 | |||
| 209 | |||
| 210 | ;*** Internal variables used by KEYBXX interrupt handler | ||
| 211 | ; KeyVector dd ? ; origin of keyboard decode table | ||
| 212 | ;PCType db ? ; type of PC running on | ||
| 213 | PCType db 0fch ; type of PC running on | ||
| 214 | |||
| 215 | PC_AT = 0FCh ;if anything else, assume PC/XT | ||
| 216 | |||
| 217 | ;Accent db 0 ; set for accent key, =0 for none. | ||
| 218 | ;AccentKey dw ? ; last accent key pressed | ||
| 219 | |||
| 220 | ; BeepFreq dw PCBeepFreq ;Count for beep half-cycle | ||
| 221 | BeepFreq dw ATBeepFreq ;Count for beep half-cycle | ||
| 222 | ; BeepDur dw PCBeepDur ;Count of half-cycles to beep | ||
| 223 | BeepDur dw ATBeepDur ;Count of half-cycles to beep | ||
| 224 | |||
| 225 | |||
| 226 | ;*** Normal keyboard table, used in CTRL-ALT F1 mode | ||
| 227 | ; | ||
| 228 | ; See Keyb?? files for structure information. | ||
| 229 | ; | ||
| 230 | ForeignTable label word | ||
| 231 | KeyMapTable label word | ||
| 232 | public KeyMapTable | ||
| 233 | |||
| 234 | db 0,0 ;0 | ||
| 235 | dw BufferFull | ||
| 236 | db esc,esc ;1 | ||
| 237 | dw SpecKey | ||
| 238 | db "1","!" ;2 | ||
| 239 | dw Keys$2$13 | ||
| 240 | db "2","@" ;3 | ||
| 241 | dw Keys$2$13 | ||
| 242 | db "3","#" ;4 | ||
| 243 | dw Keys$2$13 | ||
| 244 | db "4","$" ;5 | ||
| 245 | dw Keys$2$13 | ||
| 246 | db "5","%" ;6 | ||
| 247 | dw Keys$2$13 | ||
| 248 | db "6","^" ;7 | ||
| 249 | dw Keys$2$13 | ||
| 250 | db "7","&" ;8 | ||
| 251 | dw Keys$2$13 | ||
| 252 | db "8","*" ;9 | ||
| 253 | dw Keys$2$13 | ||
| 254 | db "9","(" ;10 | ||
| 255 | dw Keys$2$13 | ||
| 256 | db "0",")" ;11 | ||
| 257 | dw Keys$2$13 | ||
| 258 | db "-","_" ;12 | ||
| 259 | dw Keys$2$13 | ||
| 260 | db "=","+" ;13 | ||
| 261 | dw Keys$2$13 | ||
| 262 | db 8,127 ;14 | ||
| 263 | dw SpecKey | ||
| 264 | db 9,0 ;15 | ||
| 265 | dw NormalKey | ||
| 266 | db "q","Q" ;16 | ||
| 267 | dw AlphaKey | ||
| 268 | db "w","W" ;17 | ||
| 269 | dw AlphaKey | ||
| 270 | db "e","E" ;18 | ||
| 271 | dw AlphaKey | ||
| 272 | db "r","R" ;19 | ||
| 273 | dw AlphaKey | ||
| 274 | db "t","T" ;20 | ||
| 275 | dw AlphaKey | ||
| 276 | db "y","Y" ;21 | ||
| 277 | dw AlphaKey | ||
| 278 | db "u","U" ;22 | ||
| 279 | dw AlphaKey | ||
| 280 | db "i","I" ;23 | ||
| 281 | dw AlphaKey | ||
| 282 | db "o","O" ;24 | ||
| 283 | dw AlphaKey | ||
| 284 | db "p","P" ;25 | ||
| 285 | dw AlphaKey | ||
| 286 | db "[","{" ;26 | ||
| 287 | dw NormalKey | ||
| 288 | db "]","}" ;27 | ||
| 289 | dw NormalKey | ||
| 290 | db 13,10 ;28 | ||
| 291 | dw SpecKey | ||
| 292 | db CtrlShift,(255-CtrlShift) | ||
| 293 | dw ShiftKey | ||
| 294 | db "a","A" ;30 | ||
| 295 | dw AlphaKey | ||
| 296 | db "s","S" ;31 | ||
| 297 | dw AlphaKey | ||
| 298 | db "d","D" ;32 | ||
| 299 | dw AlphaKey | ||
| 300 | db "f","F" ;33 | ||
| 301 | dw AlphaKey | ||
| 302 | db "g","G" ;34 | ||
| 303 | dw AlphaKey | ||
| 304 | db "h","H" ;35 | ||
| 305 | dw AlphaKey | ||
| 306 | db "j","J" ;36 | ||
| 307 | dw AlphaKey | ||
| 308 | db "k","K" ;37 | ||
| 309 | dw AlphaKey | ||
| 310 | db "l","L" ;38 | ||
| 311 | dw AlphaKey | ||
| 312 | db ";",":" ;39 | ||
| 313 | dw NormalKey | ||
| 314 | db "'",'"' ;40 | ||
| 315 | dw NormalKey | ||
| 316 | db "`","~" ;41 | ||
| 317 | dw NormalKey | ||
| 318 | db LeftShift,(255-LeftShift) | ||
| 319 | dw ShiftKey | ||
| 320 | db "\","|" ;43 | ||
| 321 | dw NormalKey | ||
| 322 | db "z","Z" ;44 | ||
| 323 | dw AlphaKey | ||
| 324 | db "x","X" ;45 | ||
| 325 | dw AlphaKey | ||
| 326 | db "c","C" ;46 | ||
| 327 | dw AlphaKey | ||
| 328 | db "v","V" ;47 | ||
| 329 | dw AlphaKey | ||
| 330 | db "b","B" ;48 | ||
| 331 | dw AlphaKey | ||
| 332 | db "n","N" ;49 | ||
| 333 | dw AlphaKey | ||
| 334 | db "m","M" ;50 | ||
| 335 | dw AlphaKey | ||
| 336 | db ",","<" ;51 | ||
| 337 | dw NormalKey | ||
| 338 | db ".",">" ;52 | ||
| 339 | dw NormalKey | ||
| 340 | db "/","?" ;53 | ||
| 341 | dw NormalKey | ||
| 342 | db RightShift,(255-RightShift) | ||
| 343 | dw ShiftKey | ||
| 344 | db "*",114 ;55 | ||
| 345 | dw PrintScreen | ||
| 346 | db AltShift,(255-AltShift) ;56 | ||
| 347 | dw AltShiftKey | ||
| 348 | db " "," " ;57 | ||
| 349 | dw SpaceKey | ||
| 350 | db CapsState,(255-CapsState) | ||
| 351 | dw StateKey | ||
| 352 | db 1,1 ;59 | ||
| 353 | dw FuncKey | ||
| 354 | db 2,2 ;60 | ||
| 355 | dw FuncKey | ||
| 356 | db 3,3 ;61 | ||
| 357 | dw FuncKey | ||
| 358 | db 4,4 ;62 | ||
| 359 | dw FuncKey | ||
| 360 | db 5,5 ;63 | ||
| 361 | dw FuncKey | ||
| 362 | db 6,6 ;64 | ||
| 363 | dw FuncKey | ||
| 364 | db 7,7 ;65 | ||
| 365 | dw FuncKey | ||
| 366 | db 8,8 ;66 | ||
| 367 | dw FuncKey | ||
| 368 | db 9,9 ;67 | ||
| 369 | dw FuncKey | ||
| 370 | db 0,0 ;68 | ||
| 371 | dw FuncKey | ||
| 372 | db NumState,(255-NumState) ;69 | ||
| 373 | dw NumKey | ||
| 374 | db ScrollState,(255-ScrollState) | ||
| 375 | dw ScrollKey | ||
| 376 | db 0,"7" ;71 | ||
| 377 | dw PadKey | ||
| 378 | db 1,"8" ;72 | ||
| 379 | dw PadKey | ||
| 380 | db 2,"9" ;73 | ||
| 381 | dw PadKey | ||
| 382 | db 3,"-" ;74 | ||
| 383 | dw PadKey | ||
| 384 | db 4,"4" ;75 | ||
| 385 | dw PadKey | ||
| 386 | db 5,"5" ;76 | ||
| 387 | dw PadKey | ||
| 388 | db 6,"6" ;77 | ||
| 389 | dw PadKey | ||
| 390 | db 7,"+" ;78 | ||
| 391 | dw PadKey | ||
| 392 | db 8,"1" ;79 | ||
| 393 | dw PadKey | ||
| 394 | db 9,"2" ;80 | ||
| 395 | dw PadKey | ||
| 396 | db 10,"3" ;81 | ||
| 397 | dw PadKey | ||
| 398 | db 11,"0" ;82 | ||
| 399 | dw PadKey | ||
| 400 | db 12,"." ;83 | ||
| 401 | dw ReBoot | ||
| 402 | db 0, 0 ;84 (On AT only) | ||
| 403 | dw SysReq | ||
| 404 | |||
| 405 | |||
| 406 | |||
| 407 | ;*** Tables for keypad with ALT and control | ||
| 408 | ; Same for foreign as normal | ||
| 409 | AltKeyPad label byte | ||
| 410 | db 7,8,9,-1 | ||
| 411 | db 4,5,6,-1 | ||
| 412 | db 1,2,3 | ||
| 413 | db 0,-1 | ||
| 414 | |||
| 415 | CtrlKeyPad label byte | ||
| 416 | db 119,-1,132,-1 | ||
| 417 | db 115,-1,116,-1 | ||
| 418 | db 117,-1,118 | ||
| 419 | db -1,-1 | ||
| 420 | |||
| 421 | |||
| 422 | |||
| 423 | ;*** Table for ALT alphabetical character | ||
| 424 | ; | ||
| 425 | ; Since uses alpha char as index, this is the same | ||
| 426 | ; for normal and foreign keyboards. | ||
| 427 | ; | ||
| 428 | AltTable label byte | ||
| 429 | ; a, b, c, d, e, f, g, h, i, j, k, l, m | ||
| 430 | db 30,48,46,32,18,33,34,35,23,36,37,38,50 | ||
| 431 | ; n, o, p, q, r, s, t, u, v, w, x, y, z | ||
| 432 | db 49,24,25,16,19,31,20,22,47,17,45,21,44 | ||
| 433 | |||
| 434 | |||
| 435 | |||
| 436 | SUBTTL Keyboard Interrupt Handler | ||
| 437 | |||
| 438 | |||
| 439 | ;*** Keyboard interrupt handler | ||
| 440 | ; | ||
| 441 | handler proc near | ||
| 442 | |||
| 443 | KbInt: | ||
| 444 | ;* sti | ||
| 445 | cld | ||
| 446 | push ax | ||
| 447 | push bx | ||
| 448 | push cx | ||
| 449 | push dx | ||
| 450 | push si | ||
| 451 | push di | ||
| 452 | push ds | ||
| 453 | push es | ||
| 454 | |||
| 455 | ; First see if there is any data in the kbd buffer. | ||
| 456 | ; Return to caller if not. | ||
| 457 | |||
| 458 | in al, KbStatus | ||
| 459 | test al, 1 | ||
| 460 | jnz intr1 | ||
| 461 | jmp RestoreRegs | ||
| 462 | intr1: | ||
| 463 | |||
| 464 | mov ax,romdata | ||
| 465 | mov ds,ax | ||
| 466 | call GetSCode ;Get scan code from keyboard in al | ||
| 467 | mov ah,al ;(ah) = scan code | ||
| 468 | cmp al,-1 | ||
| 469 | jnz KbI1 | ||
| 470 | jmp BufferFull ;go handle overrun code | ||
| 471 | KbI1: | ||
| 472 | mov bx,ax | ||
| 473 | and bx,7fh ;(bl) = scan code without break bit | ||
| 474 | cmp bl,84 | ||
| 475 | jle KBI2 | ||
| 476 | jmp KeyRet ;ignore code if not in range | ||
| 477 | KBI2: | ||
| 478 | shl bx,1 ;index into lookup table | ||
| 479 | shl bx,1 | ||
| 480 | ;* Check for CTRL-ALT chars | ||
| 481 | test ah, 80h ;no CTRL-ALT remap on break code | ||
| 482 | jnz KbI23 | ||
| 483 | ; cmp word ptr [KeyVector],offset KeyMapTable | ||
| 484 | ; je KbI23 ;Not foreign keyboard | ||
| 485 | jmp KbI23 | ||
| 486 | test [KeyState], CtrlShift | ||
| 487 | jz KbI23 | ||
| 488 | test [KeyState], AltShift | ||
| 489 | jz KbI23 | ||
| 490 | push ax ; save scan code | ||
| 491 | |||
| 492 | ;* map CTRL-ALT char | ||
| 493 | ; look up chars in table, if found then put out corresponding | ||
| 494 | ; entry from map table. | ||
| 495 | mov si, offset AltChrs - 1 ;Set up index to lookup | ||
| 496 | KbI21: | ||
| 497 | inc si ; Advance to next entry | ||
| 498 | cmp si, offset AltChrsEnd | ||
| 499 | jae KbI22 ;at end of table, so no remap | ||
| 500 | cmp ah, cs:[si] | ||
| 501 | jne KbI21 ;this isn't it so loop | ||
| 502 | ; Found character, so do the mapping | ||
| 503 | sub si, offset AltChrs | ||
| 504 | add si, offset AltMap ;get index into remaped table | ||
| 505 | pop ax ;get scan code | ||
| 506 | mov al, cs:[si] ;get new character to use | ||
| 507 | jmp PutKRet | ||
| 508 | KbI22: | ||
| 509 | pop ax | ||
| 510 | KbI23: | ||
| 511 | |||
| 512 | ; les si,[KeyVector] | ||
| 513 | mov si, offset KeyMapTable | ||
| 514 | mov cx,cs:[si+bx] ;(cx) = lc, uc bytes | ||
| 515 | mov al,cl ;(al) = lc code for key | ||
| 516 | mov dl,[KeyState] ;(dl) = keyboard flags | ||
| 517 | jmp word ptr cs:[si+bx+2] ;Call appropriate key handler | ||
| 518 | ;*** | ||
| 519 | ; for all key handler routines, | ||
| 520 | ; | ||
| 521 | ; (CX) = uc, lc code bytes from table | ||
| 522 | ; (DL) = keyboard flags byte (see equates above for bits) | ||
| 523 | ; (AL) = lc code from cl | ||
| 524 | ; (AH) = scan code from keyboard | ||
| 525 | |||
| 526 | handler endp | ||
| 527 | |||
| 528 | |||
| 529 | SUBTTL Key Routines | ||
| 530 | |||
| 531 | ;*** Key handling routines, called as specified by the key table | ||
| 532 | |||
| 533 | ;------------------------------------------------------ | ||
| 534 | ; | ||
| 535 | ; Alphabetical key, caps lock works as do CTRL and ALT | ||
| 536 | ; | ||
| 537 | AlphaKey: | ||
| 538 | call NoBreak | ||
| 539 | test dl,AltShift | ||
| 540 | jz ak1 | ||
| 541 | cbw | ||
| 542 | add bx,ax | ||
| 543 | mov ah,[AltTable+bx-"a"] | ||
| 544 | jmp MakeAlt | ||
| 545 | |||
| 546 | ak1: test dl,CtrlShift | ||
| 547 | jz ak2 | ||
| 548 | sub al,"a"-1 | ||
| 549 | jmp PutKRet | ||
| 550 | |||
| 551 | ak2: xor bh,bh | ||
| 552 | test dl,RightShift+LeftShift | ||
| 553 | jz ak3 | ||
| 554 | or bh,CapsState | ||
| 555 | ak3: mov cl,dl | ||
| 556 | and cl,CapsState | ||
| 557 | xor bh,cl | ||
| 558 | jz ak4 | ||
| 559 | mov al,ch | ||
| 560 | ak4: jmp PutKRet | ||
| 561 | |||
| 562 | |||
| 563 | ;------------------------------------------------------ | ||
| 564 | ; | ||
| 565 | ; Keys that do something different when CTRL is down | ||
| 566 | ; | ||
| 567 | SpecKey: | ||
| 568 | call NoAlt | ||
| 569 | test dl,CtrlShift | ||
| 570 | jz bsp1 | ||
| 571 | mov al,ch | ||
| 572 | bsp1: jmp PutKRet | ||
| 573 | |||
| 574 | |||
| 575 | ;----------------------------------------------------- | ||
| 576 | ; | ||
| 577 | ; Normal, Non Alphabetic key | ||
| 578 | ; | ||
| 579 | NormalKey: ;These return nothing on ALT | ||
| 580 | call NoAlt | ||
| 581 | test dl,CtrlShift | ||
| 582 | jz nk0 | ||
| 583 | jmp short Ca20 ;ky21 | ||
| 584 | |||
| 585 | Keys$2$13: ;Keys #2 - 13 have ALT codes 120,... | ||
| 586 | call NoBreak | ||
| 587 | test dl,AltShift | ||
| 588 | jz Ky2 | ||
| 589 | add ah,120-2 | ||
| 590 | jmp MakeAlt | ||
| 591 | |||
| 592 | ky2: test dl,CtrlShift | ||
| 593 | jnz Ca20 ;handle CTRL key same as for CapKey | ||
| 594 | nk0: | ||
| 595 | test dl,RightShift+LeftShift | ||
| 596 | jz nk1 | ||
| 597 | mov al,ch | ||
| 598 | nk1: jmp PutKRet | ||
| 599 | |||
| 600 | |||
| 601 | ;----------------------------------------------------- | ||
| 602 | ; | ||
| 603 | ; Non Alphabetic key for which cap lock works | ||
| 604 | ; | ||
| 605 | CapKey: ; CAPLOCK works, ALT doesn't | ||
| 606 | call NoAlt | ||
| 607 | test dl,CtrlShift | ||
| 608 | jz ca5 | ||
| 609 | jmp short ca20 ;ca3 | ||
| 610 | |||
| 611 | Cap$2$13: ; KEYS 2-13 with CAPLOCK working | ||
| 612 | call NoBreak | ||
| 613 | test dl,AltShift | ||
| 614 | jz ca2 | ||
| 615 | add ah,120-2 | ||
| 616 | jmp MakeAlt | ||
| 617 | |||
| 618 | ca2: test dl,CtrlShift | ||
| 619 | jz ca5 | ||
| 620 | ca20: cmp ah, 3 ;Keep CTRL keys at same scan code locations | ||
| 621 | jnz ca21 | ||
| 622 | jmp MakeAlt | ||
| 623 | ca21: cmp ah, 7 | ||
| 624 | jnz ca22 | ||
| 625 | mov al, 30 | ||
| 626 | jmp short ca7 | ||
| 627 | ca22: cmp ah, 26 | ||
| 628 | jnz ca23 | ||
| 629 | mov al, 27 | ||
| 630 | jmp short ca7 | ||
| 631 | ca23: cmp ah, 27 | ||
| 632 | jnz ca24 | ||
| 633 | mov al, 29 | ||
| 634 | jmp short ca7 | ||
| 635 | ca24: | ||
| 636 | cmp ah, 43 | ||
| 637 | jnz ca25 | ||
| 638 | mov al, 28 | ||
| 639 | jmp short ca7 | ||
| 640 | ca25: cmp al, '-' ;Except for - key, which moves around. | ||
| 641 | jnz ca26 | ||
| 642 | mov al, 31 | ||
| 643 | jmp short ca7 | ||
| 644 | ca26: jmp KeyRet | ||
| 645 | |||
| 646 | |||
| 647 | ca5: xor bh,bh | ||
| 648 | test dl,RightShift+LeftShift | ||
| 649 | jz ca6 | ||
| 650 | or bh,CapsState | ||
| 651 | ca6: mov cl,dl | ||
| 652 | and cl,CapsState | ||
| 653 | xor bh,cl | ||
| 654 | jz ca7 | ||
| 655 | mov al,ch | ||
| 656 | ca7: jmp PutKRet | ||
| 657 | |||
| 658 | |||
| 659 | ;--------------------------------------------------- | ||
| 660 | ; | ||
| 661 | ; Scroll Lock, Caps Lock, Num Lock | ||
| 662 | ; | ||
| 663 | ScrollKey: | ||
| 664 | test ah,80h | ||
| 665 | jnz stk0 | ||
| 666 | test dl,CtrlShift | ||
| 667 | jz stk1 | ||
| 668 | mov ax,[KbStart] | ||
| 669 | mov [KbHead],ax | ||
| 670 | mov [KbTail],ax | ||
| 671 | mov [fBreak],80h | ||
| 672 | call EnableKB | ||
| 673 | ;*a int 1bh | ||
| 674 | ;*a xor ax,ax | ||
| 675 | mov ax,0003 ;*a simulate ^C | ||
| 676 | jmp PutKRet | ||
| 677 | |||
| 678 | NumKey: ; NUM LOCK key | ||
| 679 | test ah,80h | ||
| 680 | jnz stk0 | ||
| 681 | test dl,CtrlShift | ||
| 682 | jz stk1 | ||
| 683 | or [BreakState],HoldState ; CTRL NUMLOCK | ||
| 684 | call VideoOn | ||
| 685 | nlk1: | ||
| 686 | call handler ;*a (look for key since no interrupts) | ||
| 687 | test [BreakState],HoldState ; Wait for a key press | ||
| 688 | jnz nlk1 | ||
| 689 | jmp RestoreRegs | ||
| 690 | |||
| 691 | StateKey: ; Toggle key | ||
| 692 | test ah,80h | ||
| 693 | jz stk1 | ||
| 694 | stk0: and [BreakState],ch ; Indicate key no longer held down | ||
| 695 | jmp short shf4 | ||
| 696 | |||
| 697 | stk1: mov ah,al | ||
| 698 | and al,[BreakState] | ||
| 699 | jnz shf4 ; Ignore if key already down | ||
| 700 | or [BreakState],ah ; Indicate key held down | ||
| 701 | xor dl,ah ; Toggle bit for this key | ||
| 702 | jmp short shf3 ; And go store it. | ||
| 703 | |||
| 704 | |||
| 705 | ;--------------------------------------------------- | ||
| 706 | ; | ||
| 707 | ; Alt Shift | ||
| 708 | ; | ||
| 709 | AltShiftKey: | ||
| 710 | test ah,80h | ||
| 711 | jz shf2 ; Indicate that ALT key down | ||
| 712 | xor al,al | ||
| 713 | xchg al,[AltKey] ; Find numeric code entered | ||
| 714 | or al,al | ||
| 715 | jz shf1 ; Just reset indicator if none | ||
| 716 | and [KeyState],ch | ||
| 717 | xor ah,ah ; Make it a key with 0 scan code | ||
| 718 | jmp PutKRet | ||
| 719 | |||
| 720 | ;---------------------------------------------------- | ||
| 721 | ; | ||
| 722 | ; Shift, Ctrl | ||
| 723 | ; | ||
| 724 | ShiftKey: | ||
| 725 | test ah,80h | ||
| 726 | jz shf2 | ||
| 727 | shf1: and dl,ch ; Unset indicator bit for break code | ||
| 728 | jmp short shf3 | ||
| 729 | shf2: or dl,al ; Set indicator bit for make code | ||
| 730 | shf3: mov [KeyState],dl | ||
| 731 | shf4: jmp KeyRet | ||
| 732 | |||
| 733 | |||
| 734 | ;---------------------------------------------------- | ||
| 735 | ; | ||
| 736 | ; Reboot System? | ||
| 737 | ; | ||
| 738 | ReBoot: call NoBreak ; Del key pressed, check CTRL ALT DEL | ||
| 739 | test dl,AltShift | ||
| 740 | jz pdk2 | ||
| 741 | test dl,CtrlShift | ||
| 742 | jz pdkx | ||
| 743 | XBoot: ; Reboot system. | ||
| 744 | mov ax,romdata ; ds = romdata segment | ||
| 745 | mov ds,ax | ||
| 746 | mov [fReset],1234h | ||
| 747 | ;*a | ||
| 748 | ;*a 02/12/86 - use shutdown code 10 and [40:67] to return to real mode | ||
| 749 | ;*a and enter the ROM at the CTRL-ALT-DEL entry point | ||
| 750 | ;*a | ||
| 751 | cli ; make sure | ||
| 752 | mov al,0Fh or 80h ; shutdown byte address/disable NMI | ||
| 753 | out 70h,al ; write CMOS address | ||
| 754 | jmp short $+2 ; (delay) | ||
| 755 | mov al,0Ah ; Shutdown code 10 = jump [dword @40:67] | ||
| 756 | out 71h,al ; write shutdown code to shutdown byte | ||
| 757 | ; | ||
| 758 | ; Set up entry point after the reset | ||
| 759 | ; | ||
| 760 | mov ds:[67h],0EA81h ; offset of CTRL-ALT-DEL entry point | ||
| 761 | mov ds:[67h+2],0F000h ; segment of CTRL-ALT-DEL entry point | ||
| 762 | ; | ||
| 763 | ; Reset the CPU | ||
| 764 | ; | ||
| 765 | mov al,0FEh ; FEh = pulse output bit 0 (286 reset) | ||
| 766 | out 64h,al ; command to 8042 | ||
| 767 | hlt ; don't want to coast | ||
| 768 | ;*a | ||
| 769 | ;*a end inserted code | ||
| 770 | ;*a | ||
| 771 | ;*a mov ax,-1 | ||
| 772 | ;*a push ax | ||
| 773 | ;*a xor ax,ax | ||
| 774 | ;*a push ax | ||
| 775 | ;*a xxx proc far | ||
| 776 | ;*a ret ; To reboot system, do a far return to FFFFh:0 | ||
| 777 | ;*a xxx endp | ||
| 778 | |||
| 779 | |||
| 780 | ;---------------------------------------------------- | ||
| 781 | ; | ||
| 782 | ; Key Pad Key | ||
| 783 | ; | ||
| 784 | PadKey: | ||
| 785 | mov bl,[AltKey] | ||
| 786 | call NoBreak2 | ||
| 787 | test dl,AltShift | ||
| 788 | jz pdk2 ; Not entering a character number | ||
| 789 | xor bx,bx | ||
| 790 | mov bl,cl | ||
| 791 | mov cl,cs:AltKeyPad[bx] ; Get numeric value for this key | ||
| 792 | cmp cl,-1 | ||
| 793 | jz pdk0 ; Start over if non-digit key | ||
| 794 | mov al,10 | ||
| 795 | mul [AltKey] | ||
| 796 | add al,cl | ||
| 797 | jmp short pdk1 | ||
| 798 | pdk0: xor ax,ax | ||
| 799 | pdk1: mov [AltKey],al | ||
| 800 | pdkx: jmp KeyRet | ||
| 801 | |||
| 802 | pdk2: mov al,0 | ||
| 803 | test dl,CtrlShift | ||
| 804 | jz pdk3 | ||
| 805 | xor bx,bx ; Lookup CTRL keypad key code | ||
| 806 | mov bl,cl | ||
| 807 | mov ah,cs:CtrlKeyPad[bx] | ||
| 808 | jmp short pdk6 | ||
| 809 | pdk3: cmp ah,74 ; - key independent of shift state | ||
| 810 | jz pdk41 | ||
| 811 | cmp ah,78 ; + key independent of shift state | ||
| 812 | jz pdk41 | ||
| 813 | xor bx,bx | ||
| 814 | test dl,RightShift+LeftShift | ||
| 815 | jz pdk4 | ||
| 816 | or bh,NumState | ||
| 817 | pdk4: mov cl,dl | ||
| 818 | and cl,NumState | ||
| 819 | xor bh,cl | ||
| 820 | jz pdk5 | ||
| 821 | pdk41: mov al,ch ; use char2 if shifted or in numlock | ||
| 822 | pdk5: or al,al | ||
| 823 | jnz pdk7 | ||
| 824 | pdk6: cmp ah,-1 | ||
| 825 | jz pdk8 ; Ignore CTRL with keypad 2, etc. | ||
| 826 | cmp ah,76 | ||
| 827 | jz pdk8 | ||
| 828 | pdk7: jmp PutKRet | ||
| 829 | pdk8: jmp KeyRet | ||
| 830 | |||
| 831 | |||
| 832 | ;---------------------------------------------------- | ||
| 833 | ; | ||
| 834 | ; Function Key | ||
| 835 | ; | ||
| 836 | FuncKey: | ||
| 837 | call NoBreak | ||
| 838 | test dl,AltShift+CtrlShift+LeftShift+RightShift | ||
| 839 | jz fk1 ; Normal function key | ||
| 840 | add ah,84-59 | ||
| 841 | test dl,AltShift+CtrlShift | ||
| 842 | jz fk1 ; Shifted function key | ||
| 843 | add ah,10 | ||
| 844 | test dl,AltShift | ||
| 845 | jz fk1 ; Just CTRL function key | ||
| 846 | add ah,10 | ||
| 847 | test dl,CtrlShift | ||
| 848 | jz fk1 ; Just ALT function key | ||
| 849 | mov bx,offset KeyMapTable | ||
| 850 | cmp ah,104 ; CTRL ALT f1 to use normal keyboard | ||
| 851 | jz fk01 | ||
| 852 | cmp ah,105 ; CTRL ALT f2 for foreign keyboard | ||
| 853 | jnz fk1 ; if not F1 or F2 then treat as ALT | ||
| 854 | mov bx,offset ForeignTable | ||
| 855 | fk01: | ||
| 856 | cli ; Change translation table used | ||
| 857 | ; mov word ptr [KeyVector],bx | ||
| 858 | ; mov word ptr [KeyVector+2],cs | ||
| 859 | jmp KeyRet | ||
| 860 | |||
| 861 | fk1: jmp MakeAlt | ||
| 862 | |||
| 863 | |||
| 864 | ;-------------------------------------------------------------------- | ||
| 865 | ; | ||
| 866 | ; Print Screen Key | ||
| 867 | ; | ||
| 868 | PrintScreen: | ||
| 869 | call NoAlt | ||
| 870 | test dl,CtrlShift | ||
| 871 | jz ps1 | ||
| 872 | mov ah,ch | ||
| 873 | jmp fk1 | ||
| 874 | ps1: test dl,LeftShift+RightShift | ||
| 875 | jz pdk7 | ||
| 876 | call VideoOn ;CTRL PrtSc - enable video and do Print Screen | ||
| 877 | ;*a int 5 | ||
| 878 | jmp RestoreRegs | ||
| 879 | |||
| 880 | |||
| 881 | ;-------------------------------------------------------------------- | ||
| 882 | ; | ||
| 883 | ; Space Key | ||
| 884 | ; | ||
| 885 | SpaceKey: | ||
| 886 | call NoBreak | ||
| 887 | test dl, CtrlShift | ||
| 888 | jz sp1 | ||
| 889 | test dl, AltShift | ||
| 890 | jz sp1 | ||
| 891 | jmp KeyRet ; Don't return anything on CTRL-ALT space | ||
| 892 | sp1: | ||
| 893 | jmp PutKRet | ||
| 894 | |||
| 895 | |||
| 896 | ;-------------------------------------------------------------------- | ||
| 897 | ; | ||
| 898 | ; An accent key | ||
| 899 | ; | ||
| 900 | ; Each accent key is assumed to be accent both non-shifted | ||
| 901 | ; and shifted, and the accent number for the shifted should | ||
| 902 | ; be the next one up from the unshifted accent number. | ||
| 903 | ; | ||
| 904 | ;AccKey: | ||
| 905 | ; call NoBreak | ||
| 906 | ; cbw ;convert accent number to an index | ||
| 907 | ; mov bx, ax | ||
| 908 | ; dec bx | ||
| 909 | ; shl bx,1 | ||
| 910 | ; shl bx,1 ;index to table of AccChStruc's | ||
| 911 | ; test dl, altshift | ||
| 912 | ; jz acc2 ;ALT not down | ||
| 913 | ; mov ax, [AccChTbl+bx].alt | ||
| 914 | ; jmp short acc5 | ||
| 915 | ;acc2: | ||
| 916 | ; test dl, ctrlshift | ||
| 917 | ; jz acc3 ;just a normal or shifted keypress | ||
| 918 | ; mov ax, [AccChTbl+bx].ctrl | ||
| 919 | ; jmp short acc5 | ||
| 920 | ;acc3: | ||
| 921 | ; test dl, leftshift+rightshift | ||
| 922 | ; jz acc4 ; not shifted (caps lock not used) | ||
| 923 | ; mov Accent,ch ; Get shifted accent number | ||
| 924 | ; mov ax, [AccChTbl+bx].shift | ||
| 925 | ; mov AccentKey, ax ; Save key and scn code next key int | ||
| 926 | ; jmp KeyRet | ||
| 927 | ;acc4: | ||
| 928 | ; mov Accent, al | ||
| 929 | ; mov ax, [AccChTbl+bx].normal | ||
| 930 | ; mov AccentKey, ax | ||
| 931 | ; jmp KeyRet | ||
| 932 | ;acc5: | ||
| 933 | ; jmp PutKRet | ||
| 934 | ; | ||
| 935 | |||
| 936 | |||
| 937 | ;-------------------------------------------------------------------- | ||
| 938 | ; | ||
| 939 | ; System Request Key | ||
| 940 | ; | ||
| 941 | SysReq: | ||
| 942 | test ah, 80h | ||
| 943 | jnz sys2 ;this is break code | ||
| 944 | test BreakState, SysShift | ||
| 945 | jz sys1 | ||
| 946 | jmp KeyRet ;Ignore if SysReq already down | ||
| 947 | |||
| 948 | sys1: | ||
| 949 | or BreakState, SysShift ;set held down flag | ||
| 950 | mov ax, 08500h | ||
| 951 | jmp short sys3 | ||
| 952 | sys2: | ||
| 953 | and BreakState, Not SysShift ;turn off held down flag | ||
| 954 | mov ax, 08501h | ||
| 955 | sys3: | ||
| 956 | push ax ; Save SysReq action number | ||
| 957 | mov al,20h ; EOI to control port | ||
| 958 | ; out 20h,al | ||
| 959 | call EnableKB | ||
| 960 | pop ax | ||
| 961 | ; int 15h ; Indicate SysReq to BIOS | ||
| 962 | jmp RestoreRegs | ||
| 963 | |||
| 964 | |||
| 965 | |||
| 966 | |||
| 967 | ;*** Finish up processing of interrupt | ||
| 968 | ; | ||
| 969 | |||
| 970 | ;* Make this an ALT seq by removing chr code (ret scan code, 0) | ||
| 971 | MakeAlt:mov al,0 | ||
| 972 | |||
| 973 | ;* Put Key in buffer and return | ||
| 974 | PutKRet: | ||
| 975 | ; cmp Accent, 0 ; check for accented char | ||
| 976 | ; je puk3 ;no accent pressed, just put out key | ||
| 977 | ; mov bl, Accent | ||
| 978 | ; dec bl ;make accent no an index | ||
| 979 | ; xor bh,bh | ||
| 980 | ; mov Accent, bh ;Accent only this character | ||
| 981 | ; shl bx,1 ;index into word table | ||
| 982 | ; mov si, AccentChTbl[bx] ;Get pointer to string for this accent | ||
| 983 | ; dec si ;Negate effect of initial inc in loop | ||
| 984 | ;puk1: | ||
| 985 | ; inc si | ||
| 986 | ; cmp al,cs:[si] | ||
| 987 | ; jz puk2 ;This is an accentable char - so remap | ||
| 988 | ; cmp byte ptr cs:[si], 0 | ||
| 989 | ; jnz puk1 ;not done yet | ||
| 990 | ; | ||
| 991 | ;;* The character is not in this list, so do a beep and put | ||
| 992 | ;; out booth accent char and this char | ||
| 993 | ; call ErrBeep | ||
| 994 | ; mov bx,ax | ||
| 995 | ; mov ax,AccentKey ;Put out accent | ||
| 996 | ; call PutKey | ||
| 997 | ; mov ax,bx | ||
| 998 | ; cmp al, ' ' | ||
| 999 | ; je puk4 ;Char is space, just beep and put out accent. | ||
| 1000 | ; jmp short puk3 ;Put out the character | ||
| 1001 | ; | ||
| 1002 | ;puk2: | ||
| 1003 | ; xor ah, ah ;Zero scan code for accented chrs | ||
| 1004 | ; cmp al, 0 ;for accented ALT chr put out 0, don't beep | ||
| 1005 | ; je puk3 | ||
| 1006 | ; sub si, AccentChTbl[bx] ; Make index to map table | ||
| 1007 | ; add si, AccentMpTbl[bx] | ||
| 1008 | ; mov al, cs:[si] ; Get remapped char | ||
| 1009 | puk3: | ||
| 1010 | call PutKey | ||
| 1011 | puk4: | ||
| 1012 | cmp [PCType],PC_AT | ||
| 1013 | jnz KeyRet ; just return for non-AT | ||
| 1014 | cli | ||
| 1015 | mov al,20h ; EOI to control port | ||
| 1016 | ; out 20h,al | ||
| 1017 | call EnableKB | ||
| 1018 | ; mov ax, 09102h ; Send a post code | ||
| 1019 | ; int 15h | ||
| 1020 | jmp RestoreRegs | ||
| 1021 | |||
| 1022 | |||
| 1023 | |||
| 1024 | ;* Common validity check routines (Check for ALT, ignore break codes) | ||
| 1025 | ; | ||
| 1026 | |||
| 1027 | NoAlt: test dl,AltShift ; Don't allow ALT with this key | ||
| 1028 | jnz IgB1 | ||
| 1029 | NoBreak: ; Ignore break code for this key | ||
| 1030 | mov bl,0 | ||
| 1031 | NoBreak2: | ||
| 1032 | test ah,80h | ||
| 1033 | jnz IgB1 | ||
| 1034 | test [BreakState],HoldState ; in hold state? | ||
| 1035 | jz IgB0 ; no... | ||
| 1036 | and [BreakState],(255-HoldState) | ||
| 1037 | jmp short IgB1 | ||
| 1038 | IgB0: mov [AltKey],bl | ||
| 1039 | ret | ||
| 1040 | IgB1: pop ax ; pop off return address | ||
| 1041 | jmp short KeyRet | ||
| 1042 | |||
| 1043 | |||
| 1044 | ;* buffer is full, beep the speaker and return from interrupt | ||
| 1045 | BufferFull: | ||
| 1046 | cli | ||
| 1047 | mov al,20h | ||
| 1048 | ; out 20h,al | ||
| 1049 | call ErrBeep | ||
| 1050 | jmp short KeyRet1 | ||
| 1051 | |||
| 1052 | |||
| 1053 | ;* Normal return from interrupt, handle EOI and enable KB | ||
| 1054 | KeyRet: | ||
| 1055 | cli | ||
| 1056 | mov al,20h | ||
| 1057 | ; out 20h,al | ||
| 1058 | KeyRet1: | ||
| 1059 | call EnableKB | ||
| 1060 | RestoreRegs: | ||
| 1061 | cli | ||
| 1062 | pop es | ||
| 1063 | pop ds | ||
| 1064 | pop di | ||
| 1065 | pop si | ||
| 1066 | pop dx | ||
| 1067 | pop cx | ||
| 1068 | pop bx | ||
| 1069 | pop ax | ||
| 1070 | ppp proc near | ||
| 1071 | ret | ||
| 1072 | ppp endp | ||
| 1073 | ; iret | ||
| 1074 | |||
| 1075 | |||
| 1076 | SUBTTL Subroutines | ||
| 1077 | |||
| 1078 | |||
| 1079 | |||
| 1080 | |||
| 1081 | ;*** VideoOn - enable keyboard and video | ||
| 1082 | ; | ||
| 1083 | ; ENTRY: Nothing | ||
| 1084 | ; | ||
| 1085 | ; EXIT: (dx), (al) destroyed. | ||
| 1086 | ; | ||
| 1087 | VideoOn proc near | ||
| 1088 | mov al,20h ; EOI to control port | ||
| 1089 | ; out 20h,al | ||
| 1090 | call EnableKB ; Enable AT keyboard | ||
| 1091 | cmp [VidMode],7 | ||
| 1092 | jz vdo1 ; Do nothing for monochrome monitor | ||
| 1093 | mov al,[VidReg] | ||
| 1094 | mov dx,3d8h | ||
| 1095 | out dx,al ; Enable video controller | ||
| 1096 | vdo1: ret | ||
| 1097 | VideoOn endp | ||
| 1098 | |||
| 1099 | |||
| 1100 | |||
| 1101 | |||
| 1102 | ;*** EnableKB - Enable the keyboard interface on an AT, no effect on PC/XT. | ||
| 1103 | ; | ||
| 1104 | ; ENTRY: Nothing | ||
| 1105 | ; | ||
| 1106 | ; EXIT: (al) destroyed | ||
| 1107 | ; | ||
| 1108 | ; EFFECTS: Enables the Keyboard interface. | ||
| 1109 | ; | ||
| 1110 | EnableKB proc near | ||
| 1111 | cmp [PCType], PC_AT | ||
| 1112 | jne ena1 ;for non-AT simply ignore | ||
| 1113 | pushf ;* save interrupt status | ||
| 1114 | cli | ||
| 1115 | call WaitStatus | ||
| 1116 | mov al,0AEh ;output enable keyboard command | ||
| 1117 | out KbStatus,al | ||
| 1118 | popf ;* restore original interrupt status | ||
| 1119 | ;* sti | ||
| 1120 | ena1: | ||
| 1121 | ret | ||
| 1122 | EnableKB endp | ||
| 1123 | |||
| 1124 | |||
| 1125 | |||
| 1126 | |||
| 1127 | ;*** DisableKB - Disable the keyboard interface on an AT, no effect on PC/XT | ||
| 1128 | ; | ||
| 1129 | ; ENTRY: Nothing | ||
| 1130 | ; | ||
| 1131 | ; EXIT: (al) destroyed | ||
| 1132 | ; | ||
| 1133 | ; EFFECTS: Disables the Keyboard interface. | ||
| 1134 | ; | ||
| 1135 | DisableKB proc near | ||
| 1136 | cmp [PCType], PC_AT | ||
| 1137 | jne dis1 ; Ignore if not an AT | ||
| 1138 | pushf ;* save interrupt status | ||
| 1139 | cli | ||
| 1140 | call WaitStatus | ||
| 1141 | mov al,0ADh ;output disable command | ||
| 1142 | out KBStatus, al | ||
| 1143 | popf ;* restore original interrupt status | ||
| 1144 | ;* sti | ||
| 1145 | dis1: | ||
| 1146 | ret | ||
| 1147 | DisableKB endp | ||
| 1148 | |||
| 1149 | |||
| 1150 | |||
| 1151 | |||
| 1152 | ;*** ErrBeep - beep the speaker | ||
| 1153 | ; | ||
| 1154 | ; ENTRY: Nothing | ||
| 1155 | ; | ||
| 1156 | ; EXIT: Nothing | ||
| 1157 | ; | ||
| 1158 | ; USES: (ax) - to access I/O port | ||
| 1159 | ; (bx) - length of beep in cycles | ||
| 1160 | ; (cx) - counter for cycle length | ||
| 1161 | ; | ||
| 1162 | ; EFFECTS: Speaker is beeped | ||
| 1163 | ; | ||
| 1164 | ; WARNING: Uses in/out to keyboard port to beep speaker directly. | ||
| 1165 | ; | ||
| 1166 | ErrBeep proc near | ||
| 1167 | push ax | ||
| 1168 | push bx | ||
| 1169 | push cx | ||
| 1170 | mov bx,BeepDur ; count of speaker cycles | ||
| 1171 | in al,KbCtl | ||
| 1172 | push ax | ||
| 1173 | and al,0fch ; turn off bits 0 and 1 (speaker off) | ||
| 1174 | bee1: xor al,2 ; toggle speaker bit | ||
| 1175 | out KbCtl,al | ||
| 1176 | mov cx,BeepFreq | ||
| 1177 | bee2: loop bee2 ; wait for half cycle | ||
| 1178 | dec bx | ||
| 1179 | jnz bee1 ; keep cycling speaker | ||
| 1180 | pop ax ; restore speaker/keyboard port value | ||
| 1181 | out KbCtl,al | ||
| 1182 | pop cx | ||
| 1183 | pop bx | ||
| 1184 | pop ax | ||
| 1185 | ret | ||
| 1186 | ErrBeep endp | ||
| 1187 | |||
| 1188 | |||
| 1189 | |||
| 1190 | |||
| 1191 | ;*** PutKey - put key in the buffer | ||
| 1192 | ; | ||
| 1193 | ; ENTRY: (ax) = key code and scn code to go in buffer | ||
| 1194 | ; | ||
| 1195 | ; EXIT: (si), (di) destroyed. | ||
| 1196 | ; ints disabled. | ||
| 1197 | ; | ||
| 1198 | ; EFFECTS: KbTail updated | ||
| 1199 | ; (ax) put in buffer at end. | ||
| 1200 | ; On AT - do post call. | ||
| 1201 | ; | ||
| 1202 | ; If it isn't possible to put key in buffer (full) then beep | ||
| 1203 | ; and ignore. | ||
| 1204 | ; If (ax) = -1 then the key is not put in buffer. | ||
| 1205 | ; | ||
| 1206 | PutKey proc near | ||
| 1207 | cmp ax, -1 ; Code to ignore a key | ||
| 1208 | jz put2 | ||
| 1209 | cli ; Make sure only ones using buffer now | ||
| 1210 | mov si,[KbTail] | ||
| 1211 | mov di,si ; Get old buffer end and save it | ||
| 1212 | inc si ; Advance pointer | ||
| 1213 | inc si | ||
| 1214 | cmp si,[KbEnd] | ||
| 1215 | jb put01 | ||
| 1216 | mov si,[KbStart] ; Wrap to beginning if at end | ||
| 1217 | put01: | ||
| 1218 | cmp si,[KbHead] | ||
| 1219 | jnz put1 ; Buffer not Full | ||
| 1220 | pop ax ; Drop return address | ||
| 1221 | jmp BufferFull ; Go beep and return from interrupt | ||
| 1222 | |||
| 1223 | put1: | ||
| 1224 | mov [di],ax ; Put key in buffer at end | ||
| 1225 | mov [KbTail],si | ||
| 1226 | put2: | ||
| 1227 | ret | ||
| 1228 | PutKey endp | ||
| 1229 | |||
| 1230 | |||
| 1231 | |||
| 1232 | |||
| 1233 | ;*** GetSCode - read the scan code from the keyboard | ||
| 1234 | ; | ||
| 1235 | ; ENTRY: nothing | ||
| 1236 | ; | ||
| 1237 | ; EXIT: (al) = key scan code from keyboard | ||
| 1238 | ; (ah) destroyed | ||
| 1239 | ; | ||
| 1240 | ; USES: PCType - to use PC/AT sequence, for AT - handles LEDs | ||
| 1241 | ; | ||
| 1242 | GetSCode proc near | ||
| 1243 | cmp [PCType], PC_AT | ||
| 1244 | je gsc1 ;handle AT differently | ||
| 1245 | in al,KbData ;get key code | ||
| 1246 | xchg bx,ax ;save scan code | ||
| 1247 | in al,KbCtl ;acknowledge to keyboard | ||
| 1248 | mov ah,al | ||
| 1249 | or al,80h | ||
| 1250 | out KbCtl,al | ||
| 1251 | xchg ah,al | ||
| 1252 | out KbCtl,al | ||
| 1253 | xchg ax,bx ;(al) = scan code | ||
| 1254 | ret | ||
| 1255 | |||
| 1256 | gsc1: ;have to do handshake | ||
| 1257 | call DisableKB | ||
| 1258 | pushf ;* save interrupt status | ||
| 1259 | cli | ||
| 1260 | call WaitStatus | ||
| 1261 | in al,KbData ;read in character | ||
| 1262 | popf ;* restore original interrupt status | ||
| 1263 | ;* sti | ||
| 1264 | |||
| 1265 | ; check for and flag control bytes from keyboard | ||
| 1266 | cmp al,ATResend | ||
| 1267 | jne gsc2 ;it isn't a resend | ||
| 1268 | cli | ||
| 1269 | or [ATKbFlags], KbResend | ||
| 1270 | pop bx ;throw away return address | ||
| 1271 | jmp KeyRet ;and don't do anything more with key | ||
| 1272 | |||
| 1273 | gsc2: | ||
| 1274 | cmp al,ATAck | ||
| 1275 | jne gsc3 ;it isn't an ack | ||
| 1276 | cli | ||
| 1277 | or [ATKbFlags], KBAck | ||
| 1278 | pop bx ;throw away return address | ||
| 1279 | jmp KeyRet ;and don't do anything more with key | ||
| 1280 | |||
| 1281 | gsc3: | ||
| 1282 | call UpdateLeds ;update AT's leds | ||
| 1283 | ret | ||
| 1284 | GetSCode endp | ||
| 1285 | |||
| 1286 | |||
| 1287 | |||
| 1288 | ;*** Don't need to keep code after here when not running on an AT | ||
| 1289 | xt_endcode: | ||
| 1290 | |||
| 1291 | |||
| 1292 | |||
| 1293 | ;*** UpdateLeds - update the leds on the AT keyboard | ||
| 1294 | ; | ||
| 1295 | ; ENTRY: Nothing | ||
| 1296 | ; | ||
| 1297 | ; EXIT: All regs preserved | ||
| 1298 | ; | ||
| 1299 | ; EFFECTS: Sets the keyboard LEDs according to the status byte. | ||
| 1300 | ; | ||
| 1301 | ; WARNING: Assumes it is operating on an AT, must not be called for a PC. | ||
| 1302 | ; | ||
| 1303 | UpdateLeds proc near | ||
| 1304 | pushf ;* save interrupt status | ||
| 1305 | push ax | ||
| 1306 | cli | ||
| 1307 | mov ah, KeyState ; get the toggle key states | ||
| 1308 | and ah, CapsState + NumState + ScrollState | ||
| 1309 | rol ah, 1 | ||
| 1310 | rol ah, 1 | ||
| 1311 | rol ah, 1 | ||
| 1312 | rol ah, 1 ; in format for ATKbFlags | ||
| 1313 | mov al, ATKbFlags | ||
| 1314 | and al, 07h | ||
| 1315 | cmp ah, al | ||
| 1316 | jz Updn1 ; No change in leds, so don't update | ||
| 1317 | test ATKbFlags, KBSndLed | ||
| 1318 | jnz Updn1 ; Already updating, so don't update | ||
| 1319 | or ATKbFlags, KBSndLed | ||
| 1320 | mov al, 20h | ||
| 1321 | ; out 20h, al ; send EOI | ||
| 1322 | mov al, 0EDh ; Set indicators command | ||
| 1323 | call SendByte | ||
| 1324 | test ATKbFlags, KBErr | ||
| 1325 | jnz Updn2 | ||
| 1326 | mov al, ah ; Send indicator values | ||
| 1327 | call SendByte | ||
| 1328 | test ATKbFlags, KBErr | ||
| 1329 | jnz Updn2 | ||
| 1330 | and ATKbFlags, 0F8h | ||
| 1331 | or ATKbFlags, ah ; Record indicators | ||
| 1332 | Updn2: | ||
| 1333 | and ATKbFlags, Not (KBSndLed + KBErr) | ||
| 1334 | Updn1: | ||
| 1335 | pop ax | ||
| 1336 | popf ;* restore original interrupt status | ||
| 1337 | ;* sti | ||
| 1338 | ret | ||
| 1339 | UpdateLeds endp | ||
| 1340 | |||
| 1341 | |||
| 1342 | |||
| 1343 | |||
| 1344 | ;*** SendByte - send a byte to the keyboard | ||
| 1345 | ; | ||
| 1346 | ; ENTRY: (al) - command/data to send | ||
| 1347 | ; | ||
| 1348 | ; EXIT: BreakState flags set according to success of operation. | ||
| 1349 | ; Ints disabled on completion. | ||
| 1350 | ; | ||
| 1351 | ; USES: (al) - byte to send. | ||
| 1352 | ; (ah) - count of retries. | ||
| 1353 | ; (cx) - time out counter on wait for response. | ||
| 1354 | ; | ||
| 1355 | ; Send the byte in al to the AT keyboard controller, and | ||
| 1356 | ; do handshaking to make sure they get there OK. | ||
| 1357 | ; Must not be called for the PC. | ||
| 1358 | ; | ||
| 1359 | SendByte proc near | ||
| 1360 | push ax | ||
| 1361 | push cx | ||
| 1362 | mov ah, 03 ; Set up count of retries | ||
| 1363 | Sen1: | ||
| 1364 | pushf ;* save interrupt status | ||
| 1365 | cli | ||
| 1366 | and ATKbFlags, Not (KBResend + KBAck + KBErr) | ||
| 1367 | push ax ; save byte to send | ||
| 1368 | call WaitStatus ; Wait for keyboard ready | ||
| 1369 | pop ax | ||
| 1370 | out KbData, al ; Send byte to keyboard | ||
| 1371 | popf ;* restore original interrupt status | ||
| 1372 | ;* sti | ||
| 1373 | mov cx,2000h ; Time out length, Approximate value for AT ROM | ||
| 1374 | Sen2: ; Wait for ACK | ||
| 1375 | call handler ;*a (look for key since no interrupts) | ||
| 1376 | test ATKbFlags, KBResend + KBAck | ||
| 1377 | jnz Sen4 | ||
| 1378 | loop Sen2 | ||
| 1379 | Sen3: ; Timed out - try to resend | ||
| 1380 | dec ah | ||
| 1381 | jnz Sen1 | ||
| 1382 | or ATKbFlags, KBErr | ||
| 1383 | jmp Sen5 | ||
| 1384 | Sen4: | ||
| 1385 | call handler ;*a (look for key since no interrupts) | ||
| 1386 | test ATKbFlags, KBResend | ||
| 1387 | jnz Sen3 | ||
| 1388 | Sen5: | ||
| 1389 | cli | ||
| 1390 | pop cx | ||
| 1391 | pop ax | ||
| 1392 | ret | ||
| 1393 | SendByte endp | ||
| 1394 | |||
| 1395 | |||
| 1396 | |||
| 1397 | |||
| 1398 | ;*** WaitStatus - wait for status to indicate ready for new command | ||
| 1399 | ; | ||
| 1400 | ; ENTRY: Nothing | ||
| 1401 | ; | ||
| 1402 | ; EXIT: (AL) Destroyed. | ||
| 1403 | ; | ||
| 1404 | WaitStatus proc near | ||
| 1405 | push cx | ||
| 1406 | xor cx,cx | ||
| 1407 | wai1: ;wait for empty buffer | ||
| 1408 | in al,KbStatus | ||
| 1409 | test al,BufFull | ||
| 1410 | loopnz wai1 | ||
| 1411 | pop cx | ||
| 1412 | ret | ||
| 1413 | WaitStatus endp | ||
| 1414 | |||
| 1415 | SUBTTL Initialization | ||
| 1416 | |||
| 1417 | |||
| 1418 | |||
| 1419 | ;* Initialization, called when run by DOS, doesn't stay resident. | ||
| 1420 | ; | ||
| 1421 | init_bios: | ||
| 1422 | |||
| 1423 | mov al,0ffh ; all OFF | ||
| 1424 | out MASTER_IMR,al | ||
| 1425 | |||
| 1426 | push ds | ||
| 1427 | push cs | ||
| 1428 | pop ds ; establish segment, since offsets are from cs | ||
| 1429 | mov dx,offset Kbint | ||
| 1430 | mov ax,2509h | ||
| 1431 | int 21h ;Set interrupt 9 (keyboard) vector | ||
| 1432 | |||
| 1433 | mov ax, romdata | ||
| 1434 | mov ds, ax | ||
| 1435 | init1: cmp [KbStart],0 | ||
| 1436 | jnz init2 ;New PC/AT - KbStart already initialized | ||
| 1437 | pushf ;* save interrupt status | ||
| 1438 | cli ;For old PC - initialize pointers to KbBuffer | ||
| 1439 | mov ax,offset KbBuffer | ||
| 1440 | mov [KbStart],ax | ||
| 1441 | mov [KbHead],ax | ||
| 1442 | mov [KbTail],ax | ||
| 1443 | mov [KbEnd],offset KbBufferEnd | ||
| 1444 | popf ;* restore original interrupt status | ||
| 1445 | ;* sti | ||
| 1446 | init2: ; Start up in Foreign keyboard mode | ||
| 1447 | ; mov word ptr [KeyVector],offset ForeignTable | ||
| 1448 | ; mov word ptr [KeyVector+2],cs | ||
| 1449 | |||
| 1450 | ; mov [accent],0 ; No previous accent key pressed | ||
| 1451 | |||
| 1452 | ; Get PC type information and save in PCType flag | ||
| 1453 | ; assume ds:rom | ||
| 1454 | |||
| 1455 | ; mov ax, rom | ||
| 1456 | ; mov ds, ax | ||
| 1457 | ; mov al, [systid] | ||
| 1458 | ; mov [PCType], al | ||
| 1459 | |||
| 1460 | assume ds:romdata | ||
| 1461 | pop ds | ||
| 1462 | |||
| 1463 | ; mov dx,offset xt_endcode + 100h | ||
| 1464 | ; cmp [PCType], PC_AT | ||
| 1465 | ; jnz init6 ; Drop AT specific code | ||
| 1466 | |||
| 1467 | ;* Initialization specific to AT | ||
| 1468 | ; Set up speaker counts, exchange keys 41, 43 | ||
| 1469 | ; And keep AT specific code when terminate | ||
| 1470 | ; mov [BeepFreq], ATBeepFreq | ||
| 1471 | ; mov [BeepDur], ATBeepDur | ||
| 1472 | |||
| 1473 | ; Reverse keys 41 and 43 for foreign keyboards | ||
| 1474 | ; mov ax, [ForeignTable + (41 * 4)] ; exchange char codes | ||
| 1475 | ; xchg ax, [ForeignTable + (43 * 4)] | ||
| 1476 | ; mov [ForeignTable + (41 * 4)], ax | ||
| 1477 | ; mov ax, [ForeignTable + (41 * 4) + 2] ;exchange function codes also | ||
| 1478 | ; xchg ax, [ForeignTable + (43 * 4) + 2] | ||
| 1479 | ; mov [ForeignTable + (41 * 4) + 2], ax | ||
| 1480 | ; Also handle for Ctrl Alt table | ||
| 1481 | ; mov si, offset AltChrs - 1 | ||
| 1482 | ;init3: ;search AltChrs table | ||
| 1483 | ; inc si | ||
| 1484 | ; cmp si, offset AltChrsEnd | ||
| 1485 | ; jae init5 ;Done scaning - go terminate | ||
| 1486 | ; cmp byte ptr cs:[si], 43 | ||
| 1487 | ; jnz init4 | ||
| 1488 | ; mov byte ptr cs:[si], 41 ; found key 43 - replace with 41 | ||
| 1489 | ; jmp init3 | ||
| 1490 | ;init4: | ||
| 1491 | ; cmp byte ptr cs:[si], 41 | ||
| 1492 | ; jnz init3 | ||
| 1493 | ; mov byte ptr cs:[si], 43 ; found key 41 - replace with 43 | ||
| 1494 | ; jmp init3 | ||
| 1495 | ; | ||
| 1496 | ;init5: | ||
| 1497 | ; mov dx,offset init_bios + 100h ; Keep AT specific code | ||
| 1498 | init6: | ||
| 1499 | ; Terminate and stay resident, don't keep init code | ||
| 1500 | ; push ds ; adjust cs to psp | ||
| 1501 | ; mov bx, offset init7 + 100h ; by doing a far return to init7 | ||
| 1502 | ; push bx | ||
| 1503 | ;xxxx proc far | ||
| 1504 | ; ret | ||
| 1505 | ;xxxx endp | ||
| 1506 | ;init7: | ||
| 1507 | ; int 27h | ||
| 1508 | |||
| 1509 | mov ah, 14 | ||
| 1510 | mov al, 'i' | ||
| 1511 | int 10h | ||
| 1512 | ini1: | ||
| 1513 | |||
| 1514 | ;mov ah, 14 | ||
| 1515 | ;mov al, 'h' | ||
| 1516 | ;int 10h | ||
| 1517 | |||
| 1518 | call handler | ||
| 1519 | ; call getc | ||
| 1520 | jz ini1 | ||
| 1521 | mov ah, 14 | ||
| 1522 | int 10h | ||
| 1523 | jmp ini1 | ||
| 1524 | |||
| 1525 | DCODE ends | ||
| 1526 | |||
| 1527 | ;*** getc - read character out of keyboard buffer | ||
| 1528 | ; | ||
| 1529 | ; This routine gets characters from the buffer | ||
| 1530 | ; in the ROM data area. | ||
| 1531 | ; | ||
| 1532 | ; ENTRY | ||
| 1533 | ; | ||
| 1534 | ; EXIT AL - character | ||
| 1535 | ; AH - scan code | ||
| 1536 | ; 'Z' = 0 | ||
| 1537 | ; | ||
| 1538 | ; or 'Z' = 1 if no code available | ||
| 1539 | ; | ||
| 1540 | ; USES flags | ||
| 1541 | ; | ||
| 1542 | |||
| 1543 | DCODE segment | ||
| 1544 | |||
| 1545 | assume cs:DCODE, ds:nothing, es:nothing, ss:nothing | ||
| 1546 | |||
| 1547 | public kgetc | ||
| 1548 | kgetc proc far | ||
| 1549 | |||
| 1550 | push bx | ||
| 1551 | push cx | ||
| 1552 | push dx | ||
| 1553 | push si | ||
| 1554 | push di | ||
| 1555 | |||
| 1556 | mov bx, 202h | ||
| 1557 | mov cx, 303h | ||
| 1558 | mov dx, 404h | ||
| 1559 | mov si, 505h | ||
| 1560 | mov di, 606h | ||
| 1561 | |||
| 1562 | call handler ; pull data into kbd buffer | ||
| 1563 | |||
| 1564 | mov bx, 2020h | ||
| 1565 | mov cx, 3030h | ||
| 1566 | mov dx, 4040h | ||
| 1567 | mov si, 5050h | ||
| 1568 | mov di, 6060h | ||
| 1569 | |||
| 1570 | push ds ; save caller's regs | ||
| 1571 | push bx | ||
| 1572 | |||
| 1573 | mov bx, romdata | ||
| 1574 | mov ds, bx ; DS -> ROM data area | ||
| 1575 | |||
| 1576 | cli | ||
| 1577 | mov bx, ds:[KbHead] ; bx = start of buffer | ||
| 1578 | cmp bx, ds:[KbTail] ; is buffer empty | ||
| 1579 | ;* sti | ||
| 1580 | jz ge1 | ||
| 1581 | |||
| 1582 | cli | ||
| 1583 | mov ax, [bx] ; AX = character and scan code | ||
| 1584 | add bx, 2 ; step buffer pointer | ||
| 1585 | cmp bx, ds:[KbEnd] ; is it at end of buffer | ||
| 1586 | jne ge2 | ||
| 1587 | mov bx, ds:[KbStart] ; move it back to start | ||
| 1588 | ge2: | ||
| 1589 | mov ds:[KbHead], bx ; store new start pointer | ||
| 1590 | ;* sti | ||
| 1591 | and bx, 0ffffh ; just to clear zero flag | ||
| 1592 | ge1: | ||
| 1593 | pop bx | ||
| 1594 | pop ds | ||
| 1595 | |||
| 1596 | pop di | ||
| 1597 | pop si | ||
| 1598 | pop dx | ||
| 1599 | pop cx | ||
| 1600 | pop bx | ||
| 1601 | |||
| 1602 | ret | ||
| 1603 | |||
| 1604 | kgetc endp | ||
| 1605 | |||
| 1606 | DCODE ends | ||
| 1607 | end | ||
| 1608 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/KBD.INC b/v4.0/src/MEMM/MEMM/KBD.INC new file mode 100644 index 0000000..ce3ca1a --- /dev/null +++ b/v4.0/src/MEMM/MEMM/KBD.INC | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: KBD.INC - KBD.ASM Structures and Equates | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: January 31, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 01/31/86 Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ; | ||
| 29 | ; Functional Description: | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ifndef INC_LIST | ||
| 33 | .xlist | ||
| 34 | endif | ||
| 35 | |||
| 36 | ; SCCSID = @(#)keybxx.inc 1.1 85/10/09 | ||
| 37 | ;------------------------------------------------------ | ||
| 38 | ; | ||
| 39 | ; Keybxx.inc - Define struct and equates for KeybXX and Keyb??.ASM . | ||
| 40 | ; | ||
| 41 | ; Keyb?? - denotes any of the files keybfr, keybgr, keybit, keybuk, | ||
| 42 | ; keybsp or keybdv (Dvorak keyboard). | ||
| 43 | ; | ||
| 44 | |||
| 45 | |||
| 46 | esc equ 1bh | ||
| 47 | |||
| 48 | |||
| 49 | KbData equ 60h ; I/O Ports for keyboard | ||
| 50 | KbCtl equ 61h | ||
| 51 | KbStatus equ 64h | ||
| 52 | |||
| 53 | PCBeepFreq equ 48h ; Count for Beep frequency | ||
| 54 | PCBeepDur equ 105h ; Number of Beep half cycles | ||
| 55 | ATBeepFreq equ 0CEh ; Use larger values since AT faster | ||
| 56 | ATBeepDur equ 82h | ||
| 57 | |||
| 58 | InsState equ 80h ; Bit values for BreakState and KeyState | ||
| 59 | CapsState equ 40h | ||
| 60 | NumState equ 20h | ||
| 61 | ScrollState equ 10h | ||
| 62 | HoldState equ 08h | ||
| 63 | |||
| 64 | |||
| 65 | AltShift equ 08h ; Bit values for KeyState | ||
| 66 | CtrlShift equ 04h | ||
| 67 | LeftShift equ 02h | ||
| 68 | RightShift equ 01h | ||
| 69 | |||
| 70 | |||
| 71 | BufFull equ 02h ; Bit value for KbStatus port | ||
| 72 | |||
| 73 | |||
| 74 | ATResend equ 0FEh ; AT keyboard commands | ||
| 75 | ATAck equ 0FAh | ||
| 76 | |||
| 77 | |||
| 78 | KBErr equ 080h ; Bit values for ATKbFlags | ||
| 79 | KBSndLed equ 040h | ||
| 80 | KBResend equ 020h | ||
| 81 | KBAck equ 010h | ||
| 82 | SysShift equ 004h ;SysReq key held down | ||
| 83 | |||
| 84 | |||
| 85 | ;*** AccChStruc - Structure for information about accent keys | ||
| 86 | ; | ||
| 87 | ; Contains scan and char codes returned for all shift combinations | ||
| 88 | ; with an accent key. | ||
| 89 | ; | ||
| 90 | ; Note: an accent key is an accent in both normal and shifted mode. | ||
| 91 | ; | ||
| 92 | AccChStruc struc | ||
| 93 | normal dw 0 ;chr & scan code for unshifted accent key | ||
| 94 | shift dw 0 ; " " " for shifted " " | ||
| 95 | ctrl dw -1 | ||
| 96 | alt dw -1 | ||
| 97 | AccChStruc ends | ||
| 98 | |||
| 99 | .list ; end of KBD.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/LOADALL.INC b/v4.0/src/MEMM/MEMM/LOADALL.INC new file mode 100644 index 0000000..bd31ec4 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/LOADALL.INC | |||
| @@ -0,0 +1,173 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; **** INTEL PROPRIETARY **** | ||
| 7 | ; | ||
| 8 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 9 | ; | ||
| 10 | ; Module: LOADALL - contains structures for 286 and 386 loadall | ||
| 11 | ; | ||
| 12 | ; Version: 0.02 | ||
| 13 | ; | ||
| 14 | ; Date: April 11,1986 | ||
| 15 | ; | ||
| 16 | ; Author: | ||
| 17 | ; | ||
| 18 | ;****************************************************************************** | ||
| 19 | ; | ||
| 20 | ; Change log: | ||
| 21 | ; | ||
| 22 | ; DATE REVISION DESCRIPTION | ||
| 23 | ; -------- -------- ------------------------------------------------------- | ||
| 24 | ; 04/11/86 Original | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ; | ||
| 29 | ifndef INC_LIST | ||
| 30 | .xlist | ||
| 31 | endif | ||
| 32 | |||
| 33 | LODAL286 equ 050Fh ; instruction as a WORD | ||
| 34 | LODAL386 equ 070Fh ; instruction as a WORD | ||
| 35 | |||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Note that entries are statically initialized to 0000, so limits and | ||
| 39 | ; access rights must be set up at run time. | ||
| 40 | ; | ||
| 41 | ; Structure of a 286 system table/segment descriptor cache: | ||
| 42 | ; | ||
| 43 | DescCache286 struc | ||
| 44 | dc2_BASElo dw 0000 ; low word of base (0..15) | ||
| 45 | dc2_BASEhi db 00 ; high byte of base (16..24) | ||
| 46 | dc2_AR db 00 ; access rights byte | ||
| 47 | dc2_LIMIT dw 0000 ; segment limit | ||
| 48 | DescCache286 ends | ||
| 49 | ; | ||
| 50 | ; Structure of the 286 LOADALL buffer | ||
| 51 | ; | ||
| 52 | LoadAllBuf286 struc | ||
| 53 | |||
| 54 | ll2_None1 db 6 dup (0) ; temp | ||
| 55 | ll2_MSW dw 0000 ; MSW | ||
| 56 | ll2_None2 db 14 dup (0) ; temp | ||
| 57 | ll2_TR dw 0000 ; TR | ||
| 58 | ll2_FLAGS dw 0000 ; FLAGS | ||
| 59 | ll2_IP dw 0000 ; IP | ||
| 60 | ll2_LDT dw 0000 ; LDT | ||
| 61 | ll2_DS dw 0000 ; DS | ||
| 62 | ll2_SS dw 0000 ; SS | ||
| 63 | ll2_CS dw 0000 ; CS | ||
| 64 | ll2_ES dw 0000 ; ES | ||
| 65 | ll2_DI dw 0000 ; DI | ||
| 66 | ll2_SI dw 0000 ; SI | ||
| 67 | ll2_BP dw 0000 ; BP | ||
| 68 | ll2_SP dw 0000 ; SP | ||
| 69 | ll2_BX dw 0000 ; BX | ||
| 70 | ll2_DX dw 0000 ; DX | ||
| 71 | ll2_CX dw 0000 ; CX | ||
| 72 | ll2_AX dw 0000 ; AX | ||
| 73 | |||
| 74 | ; | ||
| 75 | ; System table and segment descriptor caches | ||
| 76 | ; | ||
| 77 | ll2_EScache db size DescCache286 dup (00) | ||
| 78 | ll2_CScache db size DescCache286 dup (00) | ||
| 79 | ll2_SScache db size DescCache286 dup (00) | ||
| 80 | ll2_DScache db size DescCache286 dup (00) | ||
| 81 | ll2_GDTcache db size DescCache286 dup (00) | ||
| 82 | ll2_LDTcache db size DescCache286 dup (00) | ||
| 83 | ll2_IDTcache db size DescCache286 dup (00) | ||
| 84 | ll2_TSScache db size DescCache286 dup (00) | ||
| 85 | |||
| 86 | LoadAllBuf286 ends | ||
| 87 | ; | ||
| 88 | |||
| 89 | ; | ||
| 90 | ;****************************************************************************** | ||
| 91 | ; Define the 386 LOADALL buffer structure - 'nested' structures must be | ||
| 92 | ; used because the complete definition is too complex for the linker. | ||
| 93 | ; Note that entries are statically initialized to 0000, so limits and | ||
| 94 | ; access rights must be set up at run time. | ||
| 95 | ; | ||
| 96 | ; Structure of a 386 system table/segment descriptor cache: | ||
| 97 | ; | ||
| 98 | DescCache386 struc | ||
| 99 | dc3_AR1 db 00 ; base 16..23 (ignored) | ||
| 100 | dc3_AR2 db 00 ; access rights byte | ||
| 101 | dc3_AR3 db 00 ; limit 16..19 (ignored), B/D, G | ||
| 102 | dc3_AR4 db 00 ; base 24..31 (ignored) | ||
| 103 | dc3_BASElo dw 0000 ; low word of base | ||
| 104 | dc3_BASEhi dw 0000 ; high word of base | ||
| 105 | dc3_LIMITlo dw 0000 ; low word of limit | ||
| 106 | dc3_LIMIThi dw 0000 ; high word of limit | ||
| 107 | DescCache386 ends | ||
| 108 | ; | ||
| 109 | ; Structure of the 386 LOADALL buffer | ||
| 110 | ; | ||
| 111 | LoadAllBuf386 struc | ||
| 112 | |||
| 113 | ll3_CR0 dw 0000 ; low word of CR0 | ||
| 114 | ll3_CR0hi dw 0000 ; high word of CR0 | ||
| 115 | ll3_EFLAGS dw 0000 ; low word of EFLAGS | ||
| 116 | ll3_EFLAGShi dw 0000 ; high word of EFLAGS | ||
| 117 | ll3_EIP dw 0000 ; low word of EIP | ||
| 118 | ll3_EIPhi dw 0000 ; high word of EIP | ||
| 119 | ll3_EDI dw 0000 ; low word of EDI | ||
| 120 | ll3_EDIhi dw 0000 ; high word of EDI | ||
| 121 | ll3_ESI dw 0000 ; low word of ESI | ||
| 122 | ll3_ESIhi dw 0000 ; high word of ESI | ||
| 123 | ll3_EBP dw 0000 ; low word of EBP | ||
| 124 | ll3_EBPhi dw 0000 ; high word of EBP | ||
| 125 | ll3_ESP dw 0000 ; low word of ESP | ||
| 126 | ll3_ESPhi dw 0000 ; high word of ESP | ||
| 127 | ll3_EBX dw 0000 ; low word of EBX | ||
| 128 | ll3_EBXhi dw 0000 ; high word of EBX | ||
| 129 | ll3_EDX dw 0000 ; low word of EDX | ||
| 130 | ll3_EDXhi dw 0000 ; high word of EDX | ||
| 131 | ll3_ECX dw 0000 ; low word of ECX | ||
| 132 | ll3_ECXhi dw 0000 ; high word of ECX | ||
| 133 | ll3_EAX dw 0000 ; low word of EAX | ||
| 134 | ll3_EAXhi dw 0000 ; high word of EAX | ||
| 135 | ll3_DR6 dw 0000 ; low word of DR6 | ||
| 136 | ll3_DR6hi dw 0000 ; high word of DR6 | ||
| 137 | ll3_DR7 dw 0000 ; low word of DR7 | ||
| 138 | ll3_DR7hi dw 0000 ; high word of DR7 | ||
| 139 | ll3_TSSR dw 0000 ; TSSR (TSS selector) | ||
| 140 | dw 0000 ; (padding) | ||
| 141 | ll3_LDTR dw 0000 ; LDTR (LDT selector) | ||
| 142 | dw 0000 ; (padding) | ||
| 143 | ll3_GS dw 0000 ; GS | ||
| 144 | dw 0000 ; (padding) | ||
| 145 | ll3_FS dw 0000 ; FS | ||
| 146 | dw 0000 ; (padding) | ||
| 147 | ll3_DS dw 0000 ; DS | ||
| 148 | dw 0000 ; (padding) | ||
| 149 | ll3_SS dw 0000 ; SS | ||
| 150 | dw 0000 ; (padding) | ||
| 151 | ll3_CS dw 0000 ; CS | ||
| 152 | dw 0000 ; (padding) | ||
| 153 | ll3_ES dw 0000 ; ES | ||
| 154 | dw 0000 ; (padding) | ||
| 155 | ; | ||
| 156 | ; System table and segment descriptor caches | ||
| 157 | ; | ||
| 158 | ll3_TSScache db size DescCache386 dup (00) | ||
| 159 | ll3_IDTcache db size DescCache386 dup (00) | ||
| 160 | ll3_GDTcache db size DescCache386 dup (00) | ||
| 161 | ll3_LDTcache db size DescCache386 dup (00) | ||
| 162 | ll3_GScache db size DescCache386 dup (00) | ||
| 163 | ll3_FScache db size DescCache386 dup (00) | ||
| 164 | ll3_DScache db size DescCache386 dup (00) | ||
| 165 | ll3_SScache db size DescCache386 dup (00) | ||
| 166 | ll3_CScache db size DescCache386 dup (00) | ||
| 167 | ll3_EScache db size DescCache386 dup (00) | ||
| 168 | |||
| 169 | ll3_temps db 134h dup (00) ; padding for internal temps | ||
| 170 | |||
| 171 | LoadAllBuf386 ends | ||
| 172 | |||
| 173 | .list ; end of LOADALL.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/MACH_ID.INC b/v4.0/src/MEMM/MEMM/MACH_ID.INC new file mode 100644 index 0000000..ba217cb --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MACH_ID.INC | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: MACH_ID.INC - include for Machine ID types | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: April 9, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 04/09/86 Original | ||
| 24 | ; | ||
| 25 | ;****************************************************************************** | ||
| 26 | ifndef INC_LIST | ||
| 27 | .xlist | ||
| 28 | endif | ||
| 29 | |||
| 30 | ; STANDARD ROM BIOS MACHINE TYPES used in ROM_BIOS_Machine_ID | ||
| 31 | |||
| 32 | RBMI_PC equ 0FFh | ||
| 33 | RBMI_PCXT equ 0FEh | ||
| 34 | RBMI_PCjr equ 0FDh | ||
| 35 | RBMI_PCAT equ 0FCh | ||
| 36 | RBMI_PCConvertible equ 0F9h | ||
| 37 | RBMI_Sys80 equ 0F8h | ||
| 38 | RBMI_CompaqPortable equ 000h | ||
diff --git a/v4.0/src/MEMM/MEMM/MAKEFILE b/v4.0/src/MEMM/MEMM/MAKEFILE new file mode 100644 index 0000000..9f1a77b --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MAKEFILE | |||
| @@ -0,0 +1,343 @@ | |||
| 1 | #****************************************************************************** | ||
| 2 | # title MAKEFILE - MEMM build file | ||
| 3 | #****************************************************************************** | ||
| 4 | # | ||
| 5 | # (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | # | ||
| 7 | # Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | # | ||
| 9 | # Module: MAKEFILE | ||
| 10 | # | ||
| 11 | # Version: 0.06 | ||
| 12 | # | ||
| 13 | # Date: May 12, 1986 | ||
| 14 | # | ||
| 15 | # Author: | ||
| 16 | # | ||
| 17 | #****************************************************************************** | ||
| 18 | # | ||
| 19 | # Change log: | ||
| 20 | # | ||
| 21 | # DATE REVISION DESCRIPTION | ||
| 22 | # -------- -------- ------------------------------------------------------- | ||
| 23 | # Original | ||
| 24 | # 05/12/86 B- Cleanup and segment reorganization | ||
| 25 | # 06/03/86 C- Added module for driver i/f | ||
| 26 | # 06/08/86 C- Merge in lastest code from MS | ||
| 27 | # 06/17/86 D- Added debug version. | ||
| 28 | # 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 29 | # 07/01/86 0.03 Added MapDMA module. | ||
| 30 | # 07/11/86 0.05 Moved HIFLAG into global includes. | ||
| 31 | # | ||
| 32 | #****************************************************************************** | ||
| 33 | # | ||
| 34 | # Functional Description: | ||
| 35 | # | ||
| 36 | # This file assembles and links | ||
| 37 | # (1) EMM386.EXE - Production version of EMM386 driver | ||
| 38 | # (2) EMM386.COM - Production version of EMM386 utility | ||
| 39 | # (3) EMM386D.EXE - Debug (Internal) version of EMM386 driver | ||
| 40 | # | ||
| 41 | #****************************************************************************** | ||
| 42 | |||
| 43 | #****************************************************************************** | ||
| 44 | # R U L E S and M A C R O S | ||
| 45 | #****************************************************************************** | ||
| 46 | .SUFFIXES: | ||
| 47 | .SUFFIXES: .c .asm .obj .lst .def .lnk .lrf .exe .com | ||
| 48 | |||
| 49 | |||
| 50 | # Definition for turning OFF high memory allocation | ||
| 51 | # HIFLAG = -DNOHIMEM => turns it off | ||
| 52 | # HIFLAG = => turns on high memory allocation | ||
| 53 | HIFLAG = -DNOHIMEM | ||
| 54 | #HIFLAG = | ||
| 55 | |||
| 56 | # Definitions for assembler | ||
| 57 | #ASM = c:\bin\masm400 | ||
| 58 | #ASM = masm400 | ||
| 59 | ASM = masm | ||
| 60 | AFLAGS = -Mx -t -DI386 -DNoBugMode $(HIFLAG) | ||
| 61 | ADFLAGS = -Mx -t -DI386 $(HIFLAG) | ||
| 62 | AINC = -i..\emm | ||
| 63 | |||
| 64 | # Defines for C Compiler | ||
| 65 | C = cl | ||
| 66 | CFLAGS =/AS /G2 /Oat /Gs /Ze /Zl /Fc /c | ||
| 67 | |||
| 68 | # Definitions for linker for old style .exe files | ||
| 69 | #LINK = c:\bin\link | ||
| 70 | #LINK = link | ||
| 71 | LINK = link | ||
| 72 | LFLAGS = /NOI | ||
| 73 | |||
| 74 | # Definitions for .COM generation | ||
| 75 | CONVERT = c:\dos\exe2bin | ||
| 76 | #CONVERT = exe2bin | ||
| 77 | |||
| 78 | # Rules for generating object and linker response and definition files | ||
| 79 | .asm.obj: | ||
| 80 | $(ASM) $(AFLAGS) $(AINC) -p $*.asm; | ||
| 81 | |||
| 82 | .asm.lst: | ||
| 83 | $(ASM) -l -n $(AFLAGS) $(AINC) -p $*.asm; | ||
| 84 | |||
| 85 | #****************************************************************************** | ||
| 86 | # List of include files required | ||
| 87 | #****************************************************************************** | ||
| 88 | MEMMINC = ascii_sm.equ driver.equ pic_def.equ romstruc.equ romxbios.equ \ | ||
| 89 | desc.inc elim.inc emm386.inc instr386.inc kbd.inc loadall.inc \ | ||
| 90 | oemdep.inc page.inc vdmseg.inc vdmsel.inc vm386.inc mach_id.inc | ||
| 91 | |||
| 92 | |||
| 93 | #****************************************************************************** | ||
| 94 | # List of object files required | ||
| 95 | #****************************************************************************** | ||
| 96 | |||
| 97 | MEMMOBJ = memm386.obj elimfunc.obj init.obj allocmem.obj ppage.obj emmmes.obj \ | ||
| 98 | inittab.obj memmonf.obj rom_srch.obj i286.obj trapdef.obj \ | ||
| 99 | i386.obj tabdef.obj vmtrap.obj vminst.obj elimtrap.obj \ | ||
| 100 | vminit.obj moveb.obj em286ll.obj em386ll.obj retreal.obj \ | ||
| 101 | rrtrap.obj vdminit.obj initepg.obj errhndlr.obj maplin.obj \ | ||
| 102 | ekbd.obj util.obj initdeb.obj emm.obj emminit.obj mapdma.obj \ | ||
| 103 | iotrap.obj a20trap.obj oemproc.obj m_state.obj \ | ||
| 104 | shiphi.obj extpool.obj | ||
| 105 | |||
| 106 | COMOBJ = memmcom.obj memmonf.obj | ||
| 107 | |||
| 108 | BUGOBJ = memm386.obj elimfunc.obj init.obj allocmem.obj ppage.obj emmmes.obj \ | ||
| 109 | inittab.obj memmonf.obj rom_srch.obj i286.obj trapdef.obj \ | ||
| 110 | i386.obj tabdefD.obj vmtrapD.obj vminstD.obj elimtrap.obj \ | ||
| 111 | vminit.obj moveb.obj em286ll.obj em386ll.obj retreal.obj \ | ||
| 112 | rrtrap.obj vdminitD.obj initepg.obj errhndlr.obj maplin.obj \ | ||
| 113 | ekbd.obj util.obj initdebD.obj emmD.obj emminit.obj mapdma.obj \ | ||
| 114 | iotrap.obj a20trap.obj oemproc.obj kbd.obj print.obj m_state.obj | ||
| 115 | |||
| 116 | #****************************************************************************** | ||
| 117 | # List of libraries required | ||
| 118 | #****************************************************************************** | ||
| 119 | |||
| 120 | MEMMLIBS = ..\emm\emmlib.lib | ||
| 121 | |||
| 122 | BUGLIBS = ..\deb386\buglib.lib ..\emm\emmlib.lib | ||
| 123 | |||
| 124 | #****************************************************************************** | ||
| 125 | # Listing files | ||
| 126 | #****************************************************************************** | ||
| 127 | MEMMLST = memm386.lst elimfunc.lst init.lst ppage.lst allocmem.lst emmmes.lst \ | ||
| 128 | inittab.lst memmonf.lst rom_srch.lst i286.lst trapdef.obj \ | ||
| 129 | i386.lst tabdef.lst vmtrap.lst vminst.lst elimtrap.lst \ | ||
| 130 | vminit.lst moveb.lst em286ll.lst em386ll.lst retreal.lst \ | ||
| 131 | rrtrap.lst vdminit.lst initepg.lst errhndlr.lst maplin.lst \ | ||
| 132 | ekbd.lst util.lst initdeb.lst emm.lst emminit.lst mapdma.lst \ | ||
| 133 | iotrap.lst a20trap.lst memminc.lst oemproc.lst shiphi.lst \ | ||
| 134 | extpool.lst | ||
| 135 | |||
| 136 | COMLST = memmcom.lst memmonf.lst | ||
| 137 | |||
| 138 | BUGLST = memm386.lst elimfunc.lst init.lst allocmem.lst ppage.lst emmmes.lst \ | ||
| 139 | inittab.lst memmonf.lst rom_srch.lst i286.lst trapdef.lst \ | ||
| 140 | i386.lst tabdefD.lst vmtrapD.lst vminstD.lst elimtrap.lst \ | ||
| 141 | vminit.lst moveb.lst em286ll.lst em386ll.lst retreal.lst \ | ||
| 142 | rrtrap.lst vdminitD.lst initepg.lst errhndlr.lst maplin.lst \ | ||
| 143 | ekbd.lst util.lst initdebD.lst emmD.lst emminit.lst mapdma.lst \ | ||
| 144 | iotrap.lst a20trap.lst kbd.lst emmincD.lst oemproc.lst | ||
| 145 | |||
| 146 | |||
| 147 | #****************************************************************************** | ||
| 148 | # MEMM targets | ||
| 149 | #****************************************************************************** | ||
| 150 | #emm386: emm386.exe emm386.com emm386d.exe | ||
| 151 | emm386: emm386.exe | ||
| 152 | |||
| 153 | # production version of EMM386 device driver | ||
| 154 | # | ||
| 155 | emm386.exe: $(MEMMOBJ) $(MEMMLIBS) emm386.lnk | ||
| 156 | $(LINK) $(LFLAGS) @emm386.lnk | ||
| 157 | del emm386.sys | ||
| 158 | ren emm386.exe emm386.sys | ||
| 159 | |||
| 160 | # EMM386.COM utility | ||
| 161 | # | ||
| 162 | #emm386.com: $(COMOBJ) emmcom.lnk | ||
| 163 | # $(LINK) $(LFLAGS) @emmcom.lnk | ||
| 164 | # $(CONVERT) emmcom.exe emm386.com | ||
| 165 | |||
| 166 | # debug version of EMM386 driver | ||
| 167 | # | ||
| 168 | #emm386d.exe: $(BUGOBJ) $(BUGLIBS) emm386d.lnk | ||
| 169 | # $(LINK) $(LFLAGS) @emm386d.lnk | ||
| 170 | |||
| 171 | #****************************************************************************** | ||
| 172 | # EMM386 driver i/f modules | ||
| 173 | #****************************************************************************** | ||
| 174 | |||
| 175 | memm386.obj: memm386.asm $(MEMMINC) | ||
| 176 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 177 | memm386.lst: memm386.asm $(MEMMINC) | ||
| 178 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 179 | |||
| 180 | elimfunc.obj: elimfunc.asm $(MEMMINC) | ||
| 181 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 182 | elimfunc.lst: elimfunc.asm $(MEMMINC) | ||
| 183 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 184 | |||
| 185 | init.obj: init.asm $(MEMMINC) | ||
| 186 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 187 | init.lst: init.asm $(MEMMINC) | ||
| 188 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 189 | |||
| 190 | allocmem.obj: allocmem.asm $(MEMMINC) | ||
| 191 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 192 | allocmem.lst: allocmem.asm $(MEMMINC) | ||
| 193 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 194 | |||
| 195 | rom_srch.obj: rom_srch.asm $(MEMMINC) | ||
| 196 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 197 | rom_srch.lst: rom_srch.asm $(MEMMINC) | ||
| 198 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 199 | |||
| 200 | inittab.obj inittab.lst: inittab.asm $(MEMMINC) | ||
| 201 | |||
| 202 | emmmes.obj emmmes.lst: emmmes.asm $(MEMMINC) | ||
| 203 | |||
| 204 | extpool.obj extpool.lst: extpool.asm $(MEMMINC) | ||
| 205 | |||
| 206 | shiphi.obj shiphi.lst: shiphi.asm $(MEMMINC) | ||
| 207 | |||
| 208 | m_state.obj m_state.lst: m_state.asm $(MEMMINC) | ||
| 209 | |||
| 210 | ppage.obj ppage.lst: ppage.asm $(MEMMINC) ..\emm\emmdef.inc | ||
| 211 | |||
| 212 | #****************************************************************************** | ||
| 213 | # VDM modules | ||
| 214 | #****************************************************************************** | ||
| 215 | |||
| 216 | vdminit.obj vdminit.lst: vdminit.asm $(MEMMINC) | ||
| 217 | |||
| 218 | i286.obj i286.lst: i286.asm $(MEMMINC) | ||
| 219 | |||
| 220 | i386.obj i386.lst: i386.asm $(MEMMINC) | ||
| 221 | |||
| 222 | trapdef.obj trapdef.lst: trapdef.asm $(MEMMINC) | ||
| 223 | |||
| 224 | tabdef.obj tabdef.lst: tabdef.asm $(MEMMINC) | ||
| 225 | |||
| 226 | vmtrap.obj vmtrap.lst: vmtrap.asm $(MEMMINC) | ||
| 227 | |||
| 228 | vminst.obj vminst.lst: vminst.asm $(MEMMINC) | ||
| 229 | |||
| 230 | elimtrap.obj: elimtrap.asm $(MEMMINC) ..\emm\emmdef.inc | ||
| 231 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 232 | elimtrap.lst: elimtrap.asm $(MEMMINC) ..\emm\emmdef.inc | ||
| 233 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 234 | |||
| 235 | iotrap.obj iotrap.lst: iotrap.asm $(MEMMINC) | ||
| 236 | |||
| 237 | initepg.obj: initepg.asm $(MEMMINC) | ||
| 238 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 239 | initepg.lst: initepg.asm $(MEMMINC) | ||
| 240 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 241 | |||
| 242 | vminit.obj vminit.lst: vminit.asm $(MEMMINC) | ||
| 243 | |||
| 244 | em286ll.obj em286ll.lst: em286ll.asm $(MEMMINC) | ||
| 245 | |||
| 246 | em386ll.obj em386ll.lst: em386ll.asm $(MEMMINC) | ||
| 247 | |||
| 248 | moveb.obj: moveb.asm $(MEMMINC) | ||
| 249 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 250 | moveb.lst: moveb.asm $(MEMMINC) | ||
| 251 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 252 | |||
| 253 | util.obj: util.asm $(MEMMINC) | ||
| 254 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 255 | util.lst: util.asm $(MEMMINC) | ||
| 256 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 257 | |||
| 258 | maplin.obj maplin.lst: maplin.asm $(MEMMINC) | ||
| 259 | |||
| 260 | a20trap.obj a20trap.lst: a20trap.asm $(MEMMINC) | ||
| 261 | |||
| 262 | oemproc.obj oemproc.lst: oemproc.asm $(MEMMINC) | ||
| 263 | |||
| 264 | rrtrap.obj rrtrap.lst: rrtrap.asm $(MEMMINC) | ||
| 265 | |||
| 266 | retreal.obj retreal.lst: retreal.asm $(MEMMINC) | ||
| 267 | |||
| 268 | errhndlr.obj errhndlr.lst: errhndlr.asm $(MEMMINC) | ||
| 269 | |||
| 270 | ekbd.obj ekbd.lst: ekbd.asm $(MEMMINC) | ||
| 271 | |||
| 272 | initdeb.obj initdeb.lst: initdeb.asm $(MEMMINC) | ||
| 273 | |||
| 274 | emminit.obj emminit.lst: emminit.asm $(MEMMINC) | ||
| 275 | |||
| 276 | emm.obj emm.lst: emm.asm $(MEMMINC) | ||
| 277 | |||
| 278 | mapdma.obj mapdma.lst: mapdma.c | ||
| 279 | $(C) /ASw /G2 /Oat /Gs /Ze /Zl /Fc /c mapdma.c | ||
| 280 | |||
| 281 | memminc.lst: memminc.asm $(MEMMINC) | ||
| 282 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 283 | |||
| 284 | #****************************************************************************** | ||
| 285 | # debug modules | ||
| 286 | #****************************************************************************** | ||
| 287 | |||
| 288 | #tabdefD.obj: tabdef.asm $(MEMMINC) | ||
| 289 | # $(ASM) $(ADFLAGS) $(AINC) tabdef.asm,tabdefD.obj; | ||
| 290 | #tabdefD.lst: tabdef.asm $(MEMMINC) | ||
| 291 | # $(ASM) -l -n $(ADFLAGS) $(AINC) tabdef.asm,tabdefD.obj,tabdefD.lst; | ||
| 292 | # | ||
| 293 | #vminstD.obj: vminst.asm $(MEMMINC) | ||
| 294 | # $(ASM) $(ADFLAGS) $(AINC) vminst.asm,vminstD.obj; | ||
| 295 | #vminstD.lst: vminst.asm $(MEMMINC) | ||
| 296 | # $(ASM) -l -n $(ADFLAGS) $(AINC) vminst.asm,vminstD.obj,vminstD.lst; | ||
| 297 | |||
| 298 | #vmtrapD.obj: vmtrap.asm $(MEMMINC) | ||
| 299 | # $(ASM) $(ADFLAGS) $(AINC) vmtrap.asm,vmtrapD.obj; | ||
| 300 | #vmtrapD.lst: vmtrap.asm $(MEMMINC) | ||
| 301 | # $(ASM) -l -n $(ADFLAGS) $(AINC) vmtrap.asm,vmtrapD.obj,vmtrapD.lst; | ||
| 302 | # | ||
| 303 | #vdminitD.obj: vdminit.asm $(MEMMINC) | ||
| 304 | # $(ASM) $(ADFLAGS) $(AINC) vdminit.asm,vdminitD.obj; | ||
| 305 | #vdminitD.lst: vdminit.asm $(MEMMINC) | ||
| 306 | # $(ASM) -l -n $(ADFLAGS) $(AINC) vdminit.asm,vdminitD.obj,vdminitD.lst; | ||
| 307 | |||
| 308 | #initdebD.obj: initdeb.asm $(MEMMINC) | ||
| 309 | # $(ASM) $(ADFLAGS) $(AINC) initdeb.asm,initdebD.obj; | ||
| 310 | #initdebD.lst: initdeb.asm $(MEMMINC) | ||
| 311 | # $(ASM) -l -n $(ADFLAGS) $(AINC) initdeb.asm,initdebD.obj,initdebD.lst; | ||
| 312 | |||
| 313 | #emmD.obj: emm.asm $(MEMMINC) | ||
| 314 | # $(ASM) $(ADFLAGS) $(AINC) emm.asm,emmD.obj; | ||
| 315 | #emmD.lst: emm.asm $(MEMMINC) | ||
| 316 | # $(ASM) -l -n $(ADFLAGS) $(AINC) emm.asm,emmD.obj,emmD.lst; | ||
| 317 | |||
| 318 | #kbd.obj kbd.lst: kbd.asm $(MEMMINC) | ||
| 319 | # $(ASM) $(ADFLAGS) $(AINC) -p $*.asm; | ||
| 320 | |||
| 321 | #print.obj print.lst: print.asm $(MEMMINC) | ||
| 322 | # $(ASM) $(ADFLAGS) $(AINC) -p $*.asm; | ||
| 323 | |||
| 324 | #memmincD.lst: memminc.asm $(MEMMINC) | ||
| 325 | # $(ASM) -l -n $(ADFLAGS) $(AINC) memminc.asm,memmincD.obj,memmincD.lst; | ||
| 326 | |||
| 327 | #****************************************************************************** | ||
| 328 | # EMM386.COM modules | ||
| 329 | #****************************************************************************** | ||
| 330 | |||
| 331 | #memmcom.obj: memmcom.asm | ||
| 332 | # $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 333 | #memmcom.lst: memmcom.asm | ||
| 334 | # $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 335 | |||
| 336 | #memmonf.obj: memmonf.asm memm_msg.inc | ||
| 337 | # $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 338 | #memmonf.lst: memmonf.asm memm_msg.inc | ||
| 339 | # $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 340 | |||
| 341 | |||
| 342 | |||
| 343 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/MAPDMA.ASM b/v4.0/src/MEMM/MEMM/MAPDMA.ASM new file mode 100644 index 0000000..c1e1f4f --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MAPDMA.ASM | |||
| @@ -0,0 +1,633 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MapDMA - Ensure all DMA transfers are physically contiguous | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: MapDMA | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 18,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/18/86 Original | ||
| 27 | ; 07/02/86 0.03 Added check for ECX = 0 | ||
| 28 | ; 07/02/86 0.03 MapLinear added to set_selector | ||
| 29 | ; 07/06/86 0.04 Changed _pft386 to ptr to _pft386 array | ||
| 30 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; Functional Description: | ||
| 35 | ; | ||
| 36 | ; This module ensures that EMM pages accessed by a DMA transfer (within | ||
| 37 | ; the EMM Page Frame) are physically contiguous in memory. This is accomplished | ||
| 38 | ; by physically relocating entire EMM pages so that all of the pages participating | ||
| 39 | ; in the DMA transfer are adjacent. As a first pass, pages that need to be | ||
| 40 | ; relocated will always be moved to the base address of extended memory (or | ||
| 41 | ; possibly hi memory if that option is selected). A four word array (DMA_Pages) | ||
| 42 | ; initialized by InitEPG will contain the actual 32 bit physical address of | ||
| 43 | ; the first four physical EMM page locations. Although this will decrease | ||
| 44 | ; the time necessary to search for potential relocation candidates, it could | ||
| 45 | ; also result in the relocation of all pages when a fewer number might suffice | ||
| 46 | ; (given a more elegant mapping scheme). | ||
| 47 | ; | ||
| 48 | ; Some transfers that will NOT require remapping are: | ||
| 49 | ; 1. The DMA transfer is entirely outside the EMM Page Frame | ||
| 50 | ; 2. The DMA transfer is entirely within one Page Frame Window | ||
| 51 | ; 3. The DMA transfer spans more than one Page Frame Window, but | ||
| 52 | ; the EMM pages currently residing there are already contiguous | ||
| 53 | ; 4. See number 4 below | ||
| 54 | ; | ||
| 55 | ; Some transfers that will result in an exception are: | ||
| 56 | ; 1. The DMA transfer spans more than one Page Frame Window, where | ||
| 57 | ; at least one (but not all) of the windows is currently unmapped. | ||
| 58 | ; 2. The DMA transfer spans more than one Page Frame Window, with | ||
| 59 | ; the same EMM page residing in more than one of the windows | ||
| 60 | ; 3. The DMA transfer spans more than one Page Frame Window, but there | ||
| 61 | ; is physically not enough contiguous memory in which to locate the | ||
| 62 | ; requested EMM Pages. (This could occur in the model where both | ||
| 63 | ; extended memory and hi memory combine to form the EMM pool) | ||
| 64 | ; 4. The DMA transfer includes memory outside the Page Frame, AND | ||
| 65 | ; INSIDE the Page Frame (unless the Page Frame Windows are currently | ||
| 66 | ; unmapped, in which case no relocation is necessary) | ||
| 67 | ; | ||
| 68 | ;****************************************************************************** | ||
| 69 | .lfcond ; list false conditionals | ||
| 70 | .386p | ||
| 71 | page | ||
| 72 | ;****************************************************************************** | ||
| 73 | ; P U B L I C D E C L A R A T I O N S | ||
| 74 | ;****************************************************************************** | ||
| 75 | ; | ||
| 76 | public MapDMA | ||
| 77 | public DMA_Pages | ||
| 78 | public DMA_PAGE_COUNT | ||
| 79 | |||
| 80 | page | ||
| 81 | ;****************************************************************************** | ||
| 82 | ; L O C A L C O N S T A N T S | ||
| 83 | ;****************************************************************************** | ||
| 84 | ; | ||
| 85 | include VDMseg.inc | ||
| 86 | include VDMsel.inc | ||
| 87 | include desc.inc | ||
| 88 | include page.inc | ||
| 89 | include instr386.inc | ||
| 90 | include vm386.inc | ||
| 91 | include emmdef.inc | ||
| 92 | ; | ||
| 93 | ;****************************************************************************** | ||
| 94 | ; E X T E R N A L R E F E R E N C E S | ||
| 95 | ;****************************************************************************** | ||
| 96 | ; | ||
| 97 | ABS0 segment use16 at 0000h | ||
| 98 | ABS0 ends | ||
| 99 | |||
| 100 | _DATA segment | ||
| 101 | |||
| 102 | extrn _page_frame_base:dword ; Page Table Entry pointers for windows 0-3 | ||
| 103 | extrn _pft386:word ; ptr to array of Page Table entries | ||
| 104 | ;extrn _current_map:byte ; current mapping register values | ||
| 105 | extrn PF_Base:word ; Base addr of page frame | ||
| 106 | extrn _total_pages:word ; total number of EMM pages | ||
| 107 | extrn Page_Dir:word | ||
| 108 | |||
| 109 | xfer_map dw 0 ; map of windows participating in DMA xfer | ||
| 110 | _DATA ends | ||
| 111 | |||
| 112 | _TEXT segment | ||
| 113 | |||
| 114 | extrn ErrHndlr:near | ||
| 115 | extrn MapLinear:near | ||
| 116 | |||
| 117 | _TEXT ends | ||
| 118 | |||
| 119 | ;****************************************************************************** | ||
| 120 | ; S E G M E N T D E F I N I T I O N | ||
| 121 | ;****************************************************************************** | ||
| 122 | ; | ||
| 123 | _DATA segment | ||
| 124 | |||
| 125 | ; | ||
| 126 | ; DMA_Pages - EMM Pages for DMA relocation. Each is an index into pft386. | ||
| 127 | ; To access actual entry in pft386 you need to multiply index by 4. | ||
| 128 | ; If eight contingous 16k EMM pages are not available - the unavailable | ||
| 129 | ; entries are left at NULL_PAGE. | ||
| 130 | ; This array should be initialized at boot time. | ||
| 131 | ; | ||
| 132 | DMA_Pages dw 8 dup (NULL_PAGE) ; null for start | ||
| 133 | DMA_PAGE_COUNT dw 0 ; number of above initialised | ||
| 134 | |||
| 135 | _DATA ends | ||
| 136 | |||
| 137 | ;------------------------------------------------------------------------------ | ||
| 138 | _TEXT segment | ||
| 139 | |||
| 140 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 141 | page | ||
| 142 | ;****************************************************************************** | ||
| 143 | ; MapDMA - Relocate (if necessary) EMM pages to ensure that a DMA transfer | ||
| 144 | ; is contiguous | ||
| 145 | ; | ||
| 146 | ; ENTRY: Protected Mode Ring 0 | ||
| 147 | ; EAX = linear base address of DMA transfer | ||
| 148 | ; ECX = byte count of transfer | ||
| 149 | ; DGROUP:[_pft386] = ptr to dword array of ptrs for EMM Pages | ||
| 150 | ; DGROUP:[DMA_Pages] = array of EMM page addresses in 1st 64k (used for | ||
| 151 | ; relocating pages to contiguous physical memory) | ||
| 152 | ; | ||
| 153 | ; EXIT: Protected mode Ring 0 | ||
| 154 | ; EAX = physical base address for DMA transfer | ||
| 155 | ; DGROUP:_pft386[] = modified to reflect relocation of EMM pages | ||
| 156 | ; Page Table Entries modified to reflect relocation. | ||
| 157 | ; CY = CLEAR if exit address = entry address | ||
| 158 | ; CY = SET if exit address <> entry address (mapping was necessary) | ||
| 159 | ; | ||
| 160 | ; USED: EAX | ||
| 161 | ; Flags | ||
| 162 | ; STACK: | ||
| 163 | ;****************************************************************************** | ||
| 164 | MapDMA proc near | ||
| 165 | ; | ||
| 166 | PUSH_EBX | ||
| 167 | PUSH_EAX ; save original address | ||
| 168 | PUSH_ECX | ||
| 169 | PUSH_EDX | ||
| 170 | PUSH_EDI | ||
| 171 | PUSH_ESI | ||
| 172 | push es | ||
| 173 | ; | ||
| 174 | cld | ||
| 175 | ; | ||
| 176 | ; check for ECX = 0 | ||
| 177 | ; | ||
| 178 | jecxz nomap1 ; nomap out of jmp range | ||
| 179 | jmp short mDMA_domap | ||
| 180 | nomap1: | ||
| 181 | jmp nomap | ||
| 182 | ; | ||
| 183 | ; As a quick first check, let's see if this transfer is any where near the PF | ||
| 184 | ; | ||
| 185 | mDMA_domap: | ||
| 186 | mov ebx,eax ; get address | ||
| 187 | shr ebx,16 ; get rid of 64k | ||
| 188 | mov dx,[PF_Base] ; base address of Page Frame div 4 | ||
| 189 | mov di,dx ; save it | ||
| 190 | shr dx,12 ; divide by 64k | ||
| 191 | cmp bx,dx ; q: is it in PF? | ||
| 192 | jb nomap ; n: no mapping necessary | ||
| 193 | add di,0fffh ; plus 64k div 4 for end of PF | ||
| 194 | shr di,12 ; divide by 64k | ||
| 195 | cmp bx,di ; q: before end of PF? | ||
| 196 | ja nomap ; n: no mapping necessary | ||
| 197 | ; | ||
| 198 | push ax ; save lower 16 bits of addr | ||
| 199 | mov ebx,4000h ; window size | ||
| 200 | ; | ||
| 201 | ; build a map of windows used in this transfer | ||
| 202 | ; | ||
| 203 | mov [xfer_map],0 ; zero to start with | ||
| 204 | dec ecx ; stop at last byte | ||
| 205 | lloop: | ||
| 206 | call chk_loc ; mark this guy's location in the map | ||
| 207 | or ecx,ecx ; q: done? | ||
| 208 | jz chk_done ; y | ||
| 209 | cmp ecx,ebx ; n: q: is there a whole window left? | ||
| 210 | jae full_wind ; y: skip the adjustment | ||
| 211 | mov bx,cx ; n: just check what's left | ||
| 212 | full_wind: | ||
| 213 | sub ecx,ebx ; adjust count by window size | ||
| 214 | add ax,bx ; and base addr (let it wrap) | ||
| 215 | jmp lloop ; do the next one | ||
| 216 | chk_done: | ||
| 217 | pop ax ; restore base addr of transfer | ||
| 218 | shl [xfer_map],1 ; q: is the transfer outside the PF? | ||
| 219 | jnc in_PF ; n: entirely within Page Frame | ||
| 220 | ; | ||
| 221 | ; At least part of the transfer involves an area outside the Page Frame. | ||
| 222 | ; This is ok as long as all parts inside the Page Frame are currently unmapped. | ||
| 223 | ; | ||
| 224 | mov cx,[xfer_map] ; get the map values | ||
| 225 | xor si,si ; set up to check all windows | ||
| 226 | xor edx,edx ; clean out high bits | ||
| 227 | mov dx,[PF_Base] ; dx = address of window 0 | ||
| 228 | shl edx,4 ; make it 32 bits | ||
| 229 | mloop1: | ||
| 230 | shl cx,1 ; q: is this window involved? | ||
| 231 | jnc not_inv ; n: not involved but still more to check | ||
| 232 | call IsMapped ; q: is this page mapped? | ||
| 233 | jne excp ; y: exception (can't handle it) | ||
| 234 | not_inv: | ||
| 235 | add edx, 4000h ; n: update address of window | ||
| 236 | add si,4 ; and _page_frame_base index | ||
| 237 | or cx,cx ; q: any more to check? | ||
| 238 | jnz mloop1 ; y: check the next window | ||
| 239 | ; | ||
| 240 | nomap: jmp DMA_nomap ; don't need to relocate | ||
| 241 | ; | ||
| 242 | excp: jmp DMA_excp ; exception (can't deal with this) | ||
| 243 | ; | ||
| 244 | ; The DMA transfer is entirely within the Page Frame area. If the | ||
| 245 | ; physical location of the EMM pages (mapped into the windows participating | ||
| 246 | ; in the DMA transfer) are already contiguous, then don't do anything. | ||
| 247 | ; Otherwise, relocate them to the base area. | ||
| 248 | ; | ||
| 249 | ; eax >= [PF_Base] = linear base address of xfer | ||
| 250 | ; | ||
| 251 | in_PF: | ||
| 252 | mov bx,[xfer_map] ; get a copy of the map | ||
| 253 | shr bx,4 ; duplicate on the end | ||
| 254 | or [xfer_map],bx ; ... for wraparound | ||
| 255 | op32 | ||
| 256 | mov cx,ax ; ecx = base addr of xfer | ||
| 257 | op32 | ||
| 258 | shr cx,4 ; paragraph form | ||
| 259 | sub cx,[PF_Base] | ||
| 260 | shr cx,10 ; cx = starting window of transfer | ||
| 261 | shl [xfer_map],cl ; position on 1st window of transfer | ||
| 262 | and [xfer_map],0f7ffh ; only 1st 4 windows are valid | ||
| 263 | shl [xfer_map],1 ; we know there's at least one | ||
| 264 | or [xfer_map],cx ; save starting window number | ||
| 265 | mov bx,cx ; bx = starting window | ||
| 266 | shl bx,2 ; bx = double word index | ||
| 267 | mov cx,[xfer_map] ; get map back | ||
| 268 | les di,_page_frame_base[bx] ; es:di = page table pointer for window bx | ||
| 269 | and ax,3fffh ; get lower 14 bits | ||
| 270 | push ax ; save lower 14 bits of starting addr | ||
| 271 | op32 | ||
| 272 | mov ax,es:[di] ; get page table entry | ||
| 273 | and ax,0f000h ; get rid of lower 12 bits | ||
| 274 | push_eax ; save physical address | ||
| 275 | ; | ||
| 276 | ; bx = window number to check for contiguity | ||
| 277 | ; eax = physical address of EMM page mapped into previous window | ||
| 278 | ; cx = bit map of windows participating in the transfer | ||
| 279 | ; | ||
| 280 | c_chk: | ||
| 281 | shl cx,1 ; q: is the next window involved? | ||
| 282 | jnc DMA_addr ; n: no need to check any more | ||
| 283 | add bx,4 ; next window | ||
| 284 | and bx,0fh ; mod 16 | ||
| 285 | add ax,4000h ; next physically contiguous window | ||
| 286 | les di,_page_frame_base[bx] ; es:di = page table pointer for window bx | ||
| 287 | op32 | ||
| 288 | mov dx,es:[di] ; get page table entry | ||
| 289 | and dx,0f000h ; get rid of lower 12 bits | ||
| 290 | op32 | ||
| 291 | cmp ax,dx ; q: contiguous? | ||
| 292 | je c_chk ; y: check next window | ||
| 293 | ; | ||
| 294 | jmp DMA_reloc ; They were not contiguous, must relocate | ||
| 295 | DMA_addr: | ||
| 296 | pop_eax ; top part of actual address | ||
| 297 | pop dx ; get second half of actual address | ||
| 298 | or ax,dx ; form real address | ||
| 299 | jmp DMA_nomap ; don't need to map | ||
| 300 | ; | ||
| 301 | ; Relocate EMM pages mapped into the windows starting with the | ||
| 302 | ; low order bits of [xfer_map], for as many high bits of [xfer_map]. | ||
| 303 | ; The lower 14 bits of original address are still on the stack | ||
| 304 | ; | ||
| 305 | DMA_reloc: | ||
| 306 | pop_eax ; top part of actual address | ||
| 307 | mov bx,[xfer_map] ; get map | ||
| 308 | mov cx,bx ; copy it | ||
| 309 | and bx,3 ; bx = starting window number | ||
| 310 | xor di,di ; di = index into DMA_Pages | ||
| 311 | reloc_loop: | ||
| 312 | mov si,12 ; board index for _current_map | ||
| 313 | push cx ; save window map | ||
| 314 | mov cx,4 ; 4 boards | ||
| 315 | bloop: | ||
| 316 | ; WE NEED TO WORK ON THE DMA MORE | ||
| 317 | ; BUT int the mean time, ignore _current_map (Paul Chan) | ||
| 318 | ; mov dl,_current_map[bx+si] ; get mapping register value | ||
| 319 | shl dl,1 ; q: is it mapped? | ||
| 320 | jnc next_board ; n: try next board | ||
| 321 | mov dh,cl ; y: dh = board number | ||
| 322 | dec dh ; board is zero relative | ||
| 323 | shr dx,1 ; dx = EMM page number | ||
| 324 | cmp dx,[_total_pages] ; q: is this page in range? | ||
| 325 | jb found_page ; y: go relocate it | ||
| 326 | next_board: ; n: try next board | ||
| 327 | sub si,4 ; update index to _current_map | ||
| 328 | loop bloop ; do another | ||
| 329 | ; | ||
| 330 | ; If we ever get here, we've got a problem in the data structures, or | ||
| 331 | ; in the previous couple of hundred lines since we couldn't seem to locate | ||
| 332 | ; any pages occupying window bx (which should have generated an exception | ||
| 333 | ; long ago). In either case, we might just as well call it an exception. | ||
| 334 | excp2: jmp DMA_excp ; don't know what else to do | ||
| 335 | ; | ||
| 336 | ; At this point we have found the EMM page (= dx) occupying window bx. | ||
| 337 | ; di is the index into DMA_Pages that tells us the physical address of this | ||
| 338 | ; particular relocation area. Now we need to run through _pft386 and find | ||
| 339 | ; this address so we can swap him with page dx. If DMA_Pages contains -1, | ||
| 340 | ; then we just don't have the physically contiguous memory to get the job done. | ||
| 341 | ; | ||
| 342 | found_page: | ||
| 343 | push di ; save di | ||
| 344 | op32 | ||
| 345 | mov ax,DMA_Pages[di] ; get addr of relocation area | ||
| 346 | op32 | ||
| 347 | or ax,ax ; q: -1? | ||
| 348 | js excp2 ; y: not enough contig memory | ||
| 349 | mov cx,[_total_pages] ; number of entries in _pft386 | ||
| 350 | mov si,-4 ; index into _pft386 | ||
| 351 | add si,[_pft386] ; si = ptr for _pft386 array | ||
| 352 | floop: | ||
| 353 | add si,4 ; point to next entry | ||
| 354 | op32 | ||
| 355 | mov di,[si] ; get pft entry | ||
| 356 | and di,0f000h ; get rid of low 12 bits | ||
| 357 | op32 | ||
| 358 | cmp di,ax ; q: did we find who's there? | ||
| 359 | loopne floop ; n: keep looking | ||
| 360 | jne excp2 ; whoops, nobody was using it | ||
| 361 | ; | ||
| 362 | ; si = ptr to EMM page currently using our relocation area. | ||
| 363 | ; Swap it with EMM page # dx | ||
| 364 | ; | ||
| 365 | mov di,dx ; page number in window | ||
| 366 | shl di,2 ; offset for _pft386 | ||
| 367 | add di,[_pft386] ; di -> EMM page#dx entry | ||
| 368 | cmp di,si ; q: was it us all along? | ||
| 369 | je no_swap ; y: don't need to move it | ||
| 370 | op32 | ||
| 371 | mov dx,[di] ; PTE for this page | ||
| 372 | and dx,0f000h ; get rid of low 12 bits | ||
| 373 | ; | ||
| 374 | ; DS:SI -> relocation page entry in _pft386 | ||
| 375 | ; DS:DI -> EMM page # dx entry in _pft386 | ||
| 376 | ; check to see if we have already relocated this guy once. If so, that | ||
| 377 | ; implies that the same EMM page is mapped into more than one window. | ||
| 378 | ; Since there is no way (without scratch buffers) to make that contiguous, | ||
| 379 | ; we will just abort. | ||
| 380 | ; | ||
| 381 | op32 | ||
| 382 | cmp dx,[DMA_Pages] ; q: have we already relocated it? | ||
| 383 | jb no_dup ; n: ok | ||
| 384 | op32 | ||
| 385 | cmp dx,ax ; q: is it in the relocation area? | ||
| 386 | jb excp2 ; y: sorry | ||
| 387 | no_dup: | ||
| 388 | op32 | ||
| 389 | and [si],0fffh ; preserve his 12 bits | ||
| 390 | dw 0 | ||
| 391 | op32 | ||
| 392 | or [si],dx ; move in his new address | ||
| 393 | op32 | ||
| 394 | and [di],0fffh ; now do the same thing | ||
| 395 | dw 0 ; for the page in the window | ||
| 396 | op32 | ||
| 397 | or [di],ax ; fix up his address | ||
| 398 | ; | ||
| 399 | ; swap pages residing at addresses eax and edx | ||
| 400 | ; | ||
| 401 | push_eax ; save address in window | ||
| 402 | push ds | ||
| 403 | mov di,MBSRC_GSEL ; source selector | ||
| 404 | call set_selector ; set to address eax | ||
| 405 | mov es,di | ||
| 406 | mov di,MBTAR_GSEL ; destination selector | ||
| 407 | op32 | ||
| 408 | mov ax,dx ; destination | ||
| 409 | call set_selector ; set up selector | ||
| 410 | mov ds,di | ||
| 411 | mov cx,1000h ; 16k bytes (4 at a time) | ||
| 412 | xor di,di ; initialize index | ||
| 413 | sloop: | ||
| 414 | op32 | ||
| 415 | mov ax,es:[di] ; get a word from dest. | ||
| 416 | op32 | ||
| 417 | xchg ax,ds:[di] ; swap with source | ||
| 418 | op32 | ||
| 419 | stosw ; store in dest. | ||
| 420 | loop sloop ; do the next one | ||
| 421 | ; | ||
| 422 | pop ds | ||
| 423 | pop_eax ; restore physical address | ||
| 424 | |||
| 425 | no_swap: | ||
| 426 | |||
| 427 | |||
| 428 | pop di ; index into DMA_Pages | ||
| 429 | add di,4 ; update index | ||
| 430 | pop cx ; window map | ||
| 431 | inc bx ; next window number | ||
| 432 | and bx,3 ; mod 4 | ||
| 433 | shl cx,1 ; q: any left? | ||
| 434 | jnc fix_pte ; n: done relocating | ||
| 435 | jmp reloc_loop ; y: relocate the next page | ||
| 436 | fix_pte: | ||
| 437 | ; | ||
| 438 | ; Now set all 4 entries in page table. Rather than try to figure out exactly | ||
| 439 | ; which entries in here have changed, we will reset all entries shown as | ||
| 440 | ; being "mapped" by _current_map. Unmapped entries shouldn't have changed. | ||
| 441 | ; | ||
| 442 | mov cx,15 ; start at last entry | ||
| 443 | ploop: | ||
| 444 | mov si,cx ; copy index | ||
| 445 | ; mov bl,_current_map[si] ; get current_map entry | ||
| 446 | shl bl,1 ; q: is it mapped? | ||
| 447 | jnc pte_not_mapped ; n: try next | ||
| 448 | mov bh,cl ; copy index number | ||
| 449 | shr bh,2 ; get board number | ||
| 450 | shr bx,1 ; bx = emm page number | ||
| 451 | cmp bx,[_total_pages] ; q: in range? | ||
| 452 | jae pte_not_mapped ; n: try next | ||
| 453 | shl bx,2 ; y: index into _pft386 | ||
| 454 | add bx,[_pft386] ; ptr into _pft386 | ||
| 455 | op32 | ||
| 456 | mov ax,[bx] ; y: get pte value | ||
| 457 | and ax,0f000h ; get rid of lower 12 bits | ||
| 458 | mov si,cx ; get index number | ||
| 459 | and si,3 ; get window number | ||
| 460 | shl si,2 ; 32 bit index | ||
| 461 | les di,_page_frame_base[si] ; pointer to page table entry | ||
| 462 | or ax,P_AVAIL ; set access bits | ||
| 463 | op32 | ||
| 464 | stosw ; set 1st Page Table Entry | ||
| 465 | |||
| 466 | add_eax_ 1000h ; 2nd 386 page | ||
| 467 | op32 | ||
| 468 | stosw ; set 2nd Page Table Entry | ||
| 469 | |||
| 470 | add_eax_ 1000h ; 3rd 386 page | ||
| 471 | op32 | ||
| 472 | stosw ; set 3rd Page Table Entry | ||
| 473 | |||
| 474 | add_eax_ 1000h ; 4th 386 page | ||
| 475 | op32 | ||
| 476 | stosw ; set 4th Page Table Entry | ||
| 477 | pte_not_mapped: | ||
| 478 | dec cx ; q: done with _current_map? | ||
| 479 | jns ploop ; n: keep going | ||
| 480 | |||
| 481 | ; | ||
| 482 | ; reload CR3 to flush TLB | ||
| 483 | ; | ||
| 484 | db 66h | ||
| 485 | mov ax,[Page_Dir] ; mov EAX,dword ptr [Page_Dir] | ||
| 486 | db 0Fh,22h,18h ; mov CR3,EAX | ||
| 487 | op32 | ||
| 488 | mov ax,[DMA_Pages] ; get physical address to return | ||
| 489 | pop dx ; don't forget about the lower 14 bits | ||
| 490 | or ax,dx | ||
| 491 | ; | ||
| 492 | ; eax = physical address for DMA transfer | ||
| 493 | ; | ||
| 494 | DMA_nomap: | ||
| 495 | pop es | ||
| 496 | POP_ESI | ||
| 497 | POP_EDI | ||
| 498 | POP_EDX | ||
| 499 | POP_ECX | ||
| 500 | POP_EBX ; get original eax | ||
| 501 | clc ; assume they're the same | ||
| 502 | OP32 | ||
| 503 | cmp ax,bx ; q: did we have to map? | ||
| 504 | je cy_noset ; n: don't set carry | ||
| 505 | stc ; y: set carry | ||
| 506 | cy_noset: | ||
| 507 | POP_EBX | ||
| 508 | ; | ||
| 509 | ret | ||
| 510 | DMA_excp: | ||
| 511 | mov ax,ExcpErr | ||
| 512 | mov bx,ErrDMA | ||
| 513 | jmp ErrHndlr ; don't come back | ||
| 514 | |||
| 515 | MapDMA endp | ||
| 516 | |||
| 517 | |||
| 518 | page | ||
| 519 | ;****************************************************************************** | ||
| 520 | ; IsMapped - Check whether or not a window is unmapped | ||
| 521 | ; | ||
| 522 | ; ENTRY: Protected Mode Ring 0 | ||
| 523 | ; si = window number * 4 | ||
| 524 | ; edx = physical address of Page Frame Window | ||
| 525 | ; DGROUP:[_page_frame_base] = array of ptrs to page table entries | ||
| 526 | ; | ||
| 527 | ; EXIT: Protected mode Ring 0 | ||
| 528 | ; ZF = unmapped | ||
| 529 | ; NZF= mapped | ||
| 530 | ; | ||
| 531 | ; USED: di,ebx,es | ||
| 532 | ; Flags | ||
| 533 | ; STACK: | ||
| 534 | ;****************************************************************************** | ||
| 535 | isMapped proc near | ||
| 536 | les di,_page_frame_base[si] ; es:di = addr of page table entry | ||
| 537 | op32 | ||
| 538 | mov bx,es:[di] ; ebx = page table entry for window | ||
| 539 | and bx,0f000h ; mask off low order 12 bits | ||
| 540 | op32 | ||
| 541 | cmp bx,dx ; q: is it mapped to itself (unmapped)? | ||
| 542 | ret | ||
| 543 | isMapped endp | ||
| 544 | |||
| 545 | |||
| 546 | page | ||
| 547 | ;****************************************************************************** | ||
| 548 | ; chk_loc - Check the location of a given address and update map accordingly | ||
| 549 | ; | ||
| 550 | ; ENTRY: Protected Mode Ring 0 | ||
| 551 | ; eax = physical address to check | ||
| 552 | ; DGROUP:[xfer_map] = map of addresses used in this transfer | ||
| 553 | ; bit 16 indicates an address outside the PF | ||
| 554 | ; bits 15-12 correspond to windows 0-3 resp. | ||
| 555 | ; | ||
| 556 | ; EXIT: Protected mode Ring 0 | ||
| 557 | ; DGROUP:[xfer_map] = updated as necessary | ||
| 558 | ; | ||
| 559 | ; USED: none | ||
| 560 | ; Flags | ||
| 561 | ; STACK: | ||
| 562 | ;****************************************************************************** | ||
| 563 | chk_loc proc near | ||
| 564 | push_eax ; save address | ||
| 565 | push cx | ||
| 566 | ; | ||
| 567 | mov ch,80h ; set high bit (outside indicator) | ||
| 568 | op32 | ||
| 569 | shr ax,4 ; put in paragraph form | ||
| 570 | sub ax,[PF_Base] ; make it relative to base of Page Frame | ||
| 571 | jb outside ; outside of page frame | ||
| 572 | op32 | ||
| 573 | shr ax,10 ; ax = window number | ||
| 574 | cmp_eax_ 3 ; q: inside Page Frame? | ||
| 575 | ja outside ; n: outside | ||
| 576 | mov cl,al ; | ||
| 577 | inc cl ; skip over outside bit | ||
| 578 | shr ch,cl | ||
| 579 | outside: | ||
| 580 | xor cl,cl ; clear lower byte | ||
| 581 | or [xfer_map],cx | ||
| 582 | ; | ||
| 583 | pop cx | ||
| 584 | pop_eax | ||
| 585 | ret | ||
| 586 | chk_loc endp | ||
| 587 | page | ||
| 588 | ;****************************************************************************** | ||
| 589 | ; set_selector - set up a selector address/attrib | ||
| 590 | ; | ||
| 591 | ; ENTRY: EAX = address for GDT selector | ||
| 592 | ; DI = GDT selector | ||
| 593 | ; EXIT: selector at ES:DI is writeable data segment,64k long and points | ||
| 594 | ; to desired address. | ||
| 595 | ; | ||
| 596 | ;****************************************************************************** | ||
| 597 | set_selector proc near | ||
| 598 | ; | ||
| 599 | PUSH_EAX | ||
| 600 | push di | ||
| 601 | push es | ||
| 602 | ; | ||
| 603 | call MapLinear | ||
| 604 | ; | ||
| 605 | and di,NOT 07h ; just in case... GDT entry | ||
| 606 | push GDTD_GSEL | ||
| 607 | pop es ; ES:DI -> selector entry | ||
| 608 | ; | ||
| 609 | mov es:[di+2],ax ; low word of base address | ||
| 610 | OP32 | ||
| 611 | shr ax,16 ; AX = high word of address | ||
| 612 | mov es:[di+4],al ; low byte of high word of address | ||
| 613 | xor al,al ; clear limit/G bit | ||
| 614 | mov es:[di+6],ax ; set high byte of high word of addr | ||
| 615 | ; and high nibble of limit/G bit | ||
| 616 | ; | ||
| 617 | mov ax,0FFFFh | ||
| 618 | mov es:[di],ax ; set limit to 64k | ||
| 619 | ; | ||
| 620 | mov al,D_DATA0 ; writeable DATA seg / ring 0 | ||
| 621 | mov es:[di+5],al | ||
| 622 | ; | ||
| 623 | pop es | ||
| 624 | pop di | ||
| 625 | POP_EAX | ||
| 626 | ret | ||
| 627 | ; | ||
| 628 | set_selector endp | ||
| 629 | |||
| 630 | _TEXT ends ; end of segment | ||
| 631 | ; | ||
| 632 | end ; end of module | ||
| 633 | |||
diff --git a/v4.0/src/MEMM/MEMM/MAPDMA.C b/v4.0/src/MEMM/MEMM/MAPDMA.C new file mode 100644 index 0000000..7aae10d --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MAPDMA.C | |||
| @@ -0,0 +1,425 @@ | |||
| 1 | |||
| 2 | |||
| 3 | /* MAPDMA.C - Ensures DMA Xfer area is physically contiguous. Swaps pages | ||
| 4 | * if necessary. | ||
| 5 | * | ||
| 6 | * Date Author Comments | ||
| 7 | 8/12/88 JHB updated comments, checking for sufficient pages | ||
| 8 | available in DMA_Pages[] before remappping | ||
| 9 | |||
| 10 | 8/18/88 JHB if incoming parameters appear to be wrong or | ||
| 11 | if any unmapped page found in the transfer area assume | ||
| 12 | the Address and Count registers do not have valid values | ||
| 13 | and hence return without swapping pages. | ||
| 14 | Removed IFDEF DEBUG code | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define HEX4K 0x1000 | ||
| 18 | #define HEX16K 0x4000L | ||
| 19 | #define HEX64K 0x10000 | ||
| 20 | #define HEX128K 0x20000 | ||
| 21 | #define HEX256K 0x40000L | ||
| 22 | #define HEX640K 0xA0000L | ||
| 23 | #define HEX1MB 0x100000L | ||
| 24 | |||
| 25 | #define ALIGN128K ~0x1FFFFL | ||
| 26 | #define ALIGN64K ~0x0FFFFL | ||
| 27 | #define ALIGN16K ~0x03FFFL | ||
| 28 | |||
| 29 | #define MAX_PHYS_PAGES 40 | ||
| 30 | |||
| 31 | /* macros | ||
| 32 | * PT(a) - pte from index a | ||
| 33 | * INDEX(a) - index from Linear Adr | ||
| 34 | * OFFSET(a) - offset from Linear Adr | ||
| 35 | * LIN2PHY(l) - Physical Adr from Linear Adr | ||
| 36 | * DosPhyPage - consider 16K pages from 0 to 1MB. Let Page at 256K be page 0. | ||
| 37 | * DOSPHYPAGE(a) - DosPhyPage for Adr in 1 MB range | ||
| 38 | * PFT(a) - pick up ith entry in pft386[] | ||
| 39 | */ | ||
| 40 | |||
| 41 | #define PT(a) (GetPteFromIndex((a))) | ||
| 42 | #define INDEX(a) ((((long)a)>>12) & 0x3FF) | ||
| 43 | #define OFFSET(a) (((long)a) & 0xFFF) | ||
| 44 | #define LIN2PHY(l) ((PT(INDEX(l)) & ~0xFFFL)+(long)OFFSET(l)) | ||
| 45 | #define DOSPHYPAGE(a) (((a)>>14)-16) | ||
| 46 | #define PFT(a) (*(long *)(pft386+a)) | ||
| 47 | struct mappable_page { | ||
| 48 | unsigned short page_seg; /* segment of physical page */ | ||
| 49 | unsigned short physical_page; /* physical page number */ | ||
| 50 | }; | ||
| 51 | |||
| 52 | /* Xlates DosPhyPage into an index in mappable_pages[]. */ | ||
| 53 | extern char EMM_MPindex[]; /* index from 4000H to 10000H in steps of 16K */ | ||
| 54 | extern struct mappable_page mappable_pages[]; | ||
| 55 | extern long *pft386; | ||
| 56 | extern unsigned DMA_Pages[]; | ||
| 57 | extern DMA_PAGE_COUNT; /* size of DMA_Pages[] */ | ||
| 58 | extern unsigned physical_page_count; | ||
| 59 | |||
| 60 | /* routines imported from elimtrap.asm */ | ||
| 61 | extern long GetPte(); /* get a PT entry given index */ | ||
| 62 | extern SetPte(); /* set a PT entry */ | ||
| 63 | extern unsigned GetCRSEntry(); /* get CurRegSet entry for given EmmPhyPage */ | ||
| 64 | extern long GetDMALinAdr(); /* Get Linear Adr for the DMA buffer */ | ||
| 65 | extern Exchange16K(); /* exchange page contents */ | ||
| 66 | extern FatalError(); | ||
| 67 | |||
| 68 | /* forward declarations */ | ||
| 69 | long GetPteFromIndex(); | ||
| 70 | |||
| 71 | /* | ||
| 72 | * SwapDMAPages() | ||
| 73 | * FromAdr - DMA Xfer addr | ||
| 74 | * Len - Xfer length | ||
| 75 | * bXfer - 0 for byte transfer, 1 for word transfer | ||
| 76 | * | ||
| 77 | * Check whether the DMA Xfer area starting at FromAdr is contiguous in | ||
| 78 | * physical memory. If it isn't, make it contiguous by exchanging pages | ||
| 79 | * with the DMA buffer. | ||
| 80 | */ | ||
| 81 | |||
| 82 | long SwapDMAPages(FromAdr, Len, bXfer) | ||
| 83 | long FromAdr, Len; | ||
| 84 | unsigned bXfer; | ||
| 85 | { | ||
| 86 | unsigned Index, Offset, /* components of a PTE */ | ||
| 87 | n4KPages, /* # of 4K Pages involved in the DMA transfer */ | ||
| 88 | PhyPages[8], /* Emm Phy page numbers involved in the DMA transfer | ||
| 89 | atmost 8.*/ | ||
| 90 | DMAPageK, /* kth DMA Page - start exchanging pages from here */ | ||
| 91 | Page, MPIndex; | ||
| 92 | |||
| 93 | long FromAdr16K, /* FromAdr rounded down to 16K boundary */ | ||
| 94 | FromAdr64_128K, /* FromAdr rounded down to 64/128K boundary */ | ||
| 95 | ToAdr, /* Last Byte for the DMA trasfer */ | ||
| 96 | ToAdr16K, /* ToAdr rounded down to 16K boundary */ | ||
| 97 | ExpectedAdr, | ||
| 98 | PgFrame, /* PgFrame Address */ | ||
| 99 | First64_128K_Adr, Last64_128K_Adr,/* First and Last 4K page aligned on a 64/128 boundary */ | ||
| 100 | Adr, PhyAdr, LinAdr; | ||
| 101 | |||
| 102 | int i, j, k, bSwap, | ||
| 103 | n16KPages; /* # of 16K Pages involved in the DMA transfer */ | ||
| 104 | |||
| 105 | |||
| 106 | if (FromAdr < HEX256K || FromAdr >= HEX1MB) | ||
| 107 | return LIN2PHY(FromAdr); /* not in the EMM area */ | ||
| 108 | |||
| 109 | /* Since the Address and count register are programmed a byte at a time | ||
| 110 | * they might have invalid values in them (because of left overs). | ||
| 111 | * If invalid parameters, i.e. Xfer area crosses 64K or 128K boundary,or count | ||
| 112 | * is invalid or the DMA Xfer area has unmapped pages - just return. | ||
| 113 | */ | ||
| 114 | if ((!bXfer && (FromAdr + Len) > ((FromAdr & ALIGN64K) + HEX64K)) || | ||
| 115 | (bXfer && (FromAdr + Len) > ((FromAdr & ALIGN128K) + HEX128K)) || | ||
| 116 | (!bXfer && Len > HEX64K) || (bXfer && Len > HEX128K)) | ||
| 117 | return FromAdr; /* assume DMA registers not programmed yet */ | ||
| 118 | |||
| 119 | /* initialise PhyPages[] - unequal negative values */ | ||
| 120 | for (i = 0; i < 8; i++) | ||
| 121 | PhyPages[i] = -(i+1); | ||
| 122 | |||
| 123 | |||
| 124 | /* The DMA buffer is part of the Emm pool. | ||
| 125 | * Hence we can only swap pages which are 16K in size. Hence calculate | ||
| 126 | * n16KPages - # of 16K pages involved in the transfer. | ||
| 127 | |||
| 128 | * ToAdr - Linear Address of the last byte where the DMA transfer | ||
| 129 | * is to take place | ||
| 130 | */ | ||
| 131 | ToAdr = FromAdr + Len - 1L; | ||
| 132 | FromAdr16K = FromAdr & ALIGN16K; | ||
| 133 | ToAdr16K = ToAdr & ALIGN16K; | ||
| 134 | n16KPages = ((ToAdr16K - FromAdr16K)>>14) + 1; /* (ToAdr16K-FromAdr16K)/HEX16K + 1 */ | ||
| 135 | |||
| 136 | /* If any unmapped page in the transfer area - assume DMA registers not | ||
| 137 | * fully programmed yet | ||
| 138 | */ | ||
| 139 | for (i = 0, Adr = FromAdr16K; Adr <= ToAdr16K; Adr += HEX16K, i++) { | ||
| 140 | MPIndex = EMM_MPindex[DOSPHYPAGE(Adr)]; | ||
| 141 | if (MPIndex == -1) /* Adr not mappable */ | ||
| 142 | return FromAdr; | ||
| 143 | else { | ||
| 144 | PhyPages[i] = GetCRSEntry(mappable_pages[MPIndex].physical_page); | ||
| 145 | if (PhyPages[i] == -1) /* Adr not mapped currently */ | ||
| 146 | return FromAdr; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | for (j = 0; j < i; j++) { | ||
| 151 | Page = PhyPages[j]; | ||
| 152 | for (k = j+1; k < i; k++) { | ||
| 153 | if (PhyPages[k] == Page) | ||
| 154 | FatalError("SwapDMAPages : Two Emm pages mapped to same logical page in the xfer area"); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | /* No unmapped page in the transfer area. Assume the Address and count registers | ||
| 159 | * have meaningful values in them. | ||
| 160 | */ | ||
| 161 | Index = INDEX(FromAdr); | ||
| 162 | PgFrame = PT(Index) >> 12; | ||
| 163 | Offset = OFFSET(FromAdr); | ||
| 164 | PhyAdr = (((long)PgFrame) << 12) + Offset; | ||
| 165 | |||
| 166 | if (Offset + Len <= HEX4K) /* within a page */ | ||
| 167 | return PhyAdr; | ||
| 168 | |||
| 169 | /* calculate # of 4K pages involved in the DMA transfer */ | ||
| 170 | |||
| 171 | n4KPages = ((Offset + Len)>>12) + 1; /* (Offset+Len)/4096K + 1 */ | ||
| 172 | if (((Offset + Len) % HEX4K) == 0) | ||
| 173 | n4KPages--; | ||
| 174 | |||
| 175 | /* see if these n4KPages are physically contiguous */ | ||
| 176 | bSwap = 0; | ||
| 177 | for (i = 1; i < n4KPages; i++) { | ||
| 178 | if ((PT(Index + i)>>12) != (PgFrame + i)) { | ||
| 179 | bSwap = 1; | ||
| 180 | break; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | /* Suppose the Xfer area is physically contiguous. We may still need to swap | ||
| 185 | * pages with the DMA buffer if the physical pages straddle a 64K/128K boundary | ||
| 186 | * (the DMA will wrap around in this case). DOS would have tried to fix this | ||
| 187 | * but it would have split the Linear Address - this is of very little use. | ||
| 188 | * | ||
| 189 | * if (!bSwap && straddling 64/128K boundary) set bSwap; | ||
| 190 | */ | ||
| 191 | if (!bSwap) { /* the DMA Pages are contiguous, any straddling ? */ | ||
| 192 | if (!bXfer) { /* byte transfer */ | ||
| 193 | First64_128K_Adr = PT(Index) & ALIGN64K; | ||
| 194 | Last64_128K_Adr = PT(Index+n4KPages-1) & ALIGN64K; | ||
| 195 | } | ||
| 196 | else { /* word transfer */ | ||
| 197 | First64_128K_Adr = PT(Index) & ALIGN128K; | ||
| 198 | Last64_128K_Adr = PT(Index+n4KPages-1) & ALIGN128K; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (First64_128K_Adr != Last64_128K_Adr) | ||
| 202 | bSwap = 1; | ||
| 203 | } | ||
| 204 | |||
| 205 | if (!bSwap) | ||
| 206 | return PhyAdr; | ||
| 207 | |||
| 208 | /* The DMA transfer area is not contiguous. The DMA buffer is part of the Emm | ||
| 209 | * pool. Hence we can only swap pages which are 16K in size. n16KPages is the | ||
| 210 | * # of 16K pages involved in the transfer. | ||
| 211 | */ | ||
| 212 | |||
| 213 | /* Round down FromAdr to 64/128K boundary */ | ||
| 214 | if (bXfer) /* word transfer ? */ | ||
| 215 | FromAdr64_128K = FromAdr & ALIGN128K; /* Align on 128K boundary */ | ||
| 216 | else | ||
| 217 | FromAdr64_128K = FromAdr & ALIGN64K; /* Align on 64K boundary */ | ||
| 218 | |||
| 219 | /* Swap pages so that the DMA Xfer area is physically contiguous. | ||
| 220 | |||
| 221 | | | | | | ||
| 222 | FromAdr ->| | | | | ||
| 223 | | | | | | ||
| 224 | | | | | | ||
| 225 | FromAdr16K ->| | - - - DMAPage[k] -->| | | ||
| 226 | | | | | | ||
| 227 | | | | | | ||
| 228 | FromAdr64_128k-| | DMAPage[0] -->| | | ||
| 229 | ---------- ---------- | ||
| 230 | |||
| 231 | DMA transfer area starts at FromAdr. | ||
| 232 | Map kth DMA page to FromAdr16K and so on until all the transfer area is mapped | ||
| 233 | |||
| 234 | */ | ||
| 235 | |||
| 236 | /* Linear Adr of user page which has to be relocated */ | ||
| 237 | LinAdr = FromAdr16K; | ||
| 238 | |||
| 239 | /* corresponding DMA Page - k value in the above figure */ | ||
| 240 | DMAPageK = (FromAdr16K - FromAdr64_128K) >> 14; | ||
| 241 | |||
| 242 | ExpectedAdr = PFT(DMA_Pages[DMAPageK]); | ||
| 243 | |||
| 244 | if (DMAPageK + n16KPages > DMA_PAGE_COUNT) | ||
| 245 | FatalError("Insufficient DMA pages in the DMA Buffer"); | ||
| 246 | |||
| 247 | for (k = DMAPageK; k < DMAPageK + n16KPages; k++, LinAdr += HEX16K, | ||
| 248 | ExpectedAdr += HEX16K) { | ||
| 249 | /* Already mapped correctly ? */ | ||
| 250 | if (LIN2PHY(LinAdr) == ExpectedAdr) | ||
| 251 | continue; | ||
| 252 | /* Swap the 16K page(4 4K pages) at LinAdr with the kth DMA Page */ | ||
| 253 | SwapAPage(LinAdr, k); | ||
| 254 | } | ||
| 255 | |||
| 256 | return LIN2PHY(FromAdr); | ||
| 257 | } | ||
| 258 | |||
| 259 | /* Swap the 16K page(4 4K pages) at LinAdr with the kth DMA Page. | ||
| 260 | * Update the Emm Data Structures to reflect this remapping. | ||
| 261 | * Update the Page Table too. | ||
| 262 | */ | ||
| 263 | SwapAPage(LinAdr, k) | ||
| 264 | long LinAdr; | ||
| 265 | unsigned k; | ||
| 266 | { | ||
| 267 | unsigned DosPhyPage, /* each page 16K in size, page at 256K is Page 0 */ | ||
| 268 | EmmPhyPage, /* Phy page numbering according to Emm */ | ||
| 269 | UserPFTIndex; /* index into pft386 for Emm phy page at LinAdr */ | ||
| 270 | |||
| 271 | long DMAPhyAdr, DMALinAdr; | ||
| 272 | int i, j; | ||
| 273 | |||
| 274 | /* Updating Emm data structures */ | ||
| 275 | |||
| 276 | /* Find the pft386 entry for LinAdr */ | ||
| 277 | DosPhyPage = DOSPHYPAGE(LinAdr); /* Page at 256K is page zero */ | ||
| 278 | EmmPhyPage = mappable_pages[EMM_MPindex[DosPhyPage]].physical_page; | ||
| 279 | |||
| 280 | /* get the CurRegSet entry for this physical page. */ | ||
| 281 | UserPFTIndex = GetCRSEntry(EmmPhyPage); | ||
| 282 | |||
| 283 | if (UserPFTIndex == -1) | ||
| 284 | FatalError("Cannot find PFT386 entry for EMM page corresponding to LinAdr"); | ||
| 285 | |||
| 286 | /* exchange pft386 entries at UserPFTIndex and DMA_Pages[k] */ | ||
| 287 | |||
| 288 | DMAPhyAdr = PFT(DMA_Pages[k]); | ||
| 289 | PFT(DMA_Pages[k]) = PFT(UserPFTIndex); | ||
| 290 | PFT(UserPFTIndex) = DMAPhyAdr; | ||
| 291 | |||
| 292 | /* Fix Page table entries . | ||
| 293 | * The contents of the user page and DMA buffer page are exchanged always. | ||
| 294 | * - because a mapping for this page may exist in a saved context, | ||
| 295 | * - can do a one way copy if the non-existence of such a mapping is detected | ||
| 296 | * by scanning emm_pages[]. Will optimize this later. 8/12/88 - JHB | ||
| 297 | * | ||
| 298 | * The PT entry for the user page has to be updated. | ||
| 299 | * There may or may not exist a PT entry for the DMA page. There exists | ||
| 300 | * an entry only if there exists a mapping in the CurRegSet. If there exists | ||
| 301 | * an entry it should be updated too. | ||
| 302 | */ | ||
| 303 | |||
| 304 | /* Does PT Entry exist for the DMA buffer below 1 MB? */ | ||
| 305 | |||
| 306 | for (i = 0; i < physical_page_count; i++) { | ||
| 307 | if (GetCRSEntry(i) == DMA_Pages[k]) | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | |||
| 311 | if (i == physical_page_count) { | ||
| 312 | /* No Phy page mapped to the DMA page - so no pte to be updated for DMA Page */ | ||
| 313 | Exchange16K(LinAdr, GetDMALinAdr(DMAPhyAdr)); | ||
| 314 | UpdateUserPTE(LinAdr, UserPFTIndex); | ||
| 315 | } | ||
| 316 | else { | ||
| 317 | /* ith EmmPhyPage mapped to DMA buffer | ||
| 318 | * Scan mappable_pages[] array and find the Linear address that maps to it. | ||
| 319 | */ | ||
| 320 | for (j = 0; j < MAX_PHYS_PAGES; j++) { | ||
| 321 | if (mappable_pages[j].physical_page == i) | ||
| 322 | break; | ||
| 323 | } | ||
| 324 | if (j == MAX_PHYS_PAGES) | ||
| 325 | FatalError(); /* invalid Phy page # - doesn't exist in mappable_pages[] */ | ||
| 326 | else | ||
| 327 | DMALinAdr = ((long )mappable_pages[j].page_seg) << 4; | ||
| 328 | |||
| 329 | Exchange16K(LinAdr, DMALinAdr); | ||
| 330 | ExchangePTEs(LinAdr, DMALinAdr); | ||
| 331 | } | ||
| 332 | |||
| 333 | /* UserPFTIndex is present in DMA_Pages[] we should exchange the entries in | ||
| 334 | * DMA_Pages[] */ | ||
| 335 | for (i = 0; i < DMA_PAGE_COUNT; i++) { | ||
| 336 | if (DMA_Pages[i] == UserPFTIndex) { | ||
| 337 | DMA_Pages[i] = DMA_Pages[k]; | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | /* Now, DMA_Pages[k] has a different index into the pft386[] array */ | ||
| 343 | DMA_Pages[k] = UserPFTIndex; | ||
| 344 | } | ||
| 345 | |||
| 346 | /* Update PT entry for LinAdr to map to pft386[UserPFTIndex] */ | ||
| 347 | UpdateUserPTE(LinAdr, UserPFTIndex) | ||
| 348 | long LinAdr; | ||
| 349 | unsigned UserPFTIndex; | ||
| 350 | { | ||
| 351 | unsigned index; | ||
| 352 | long pte; | ||
| 353 | |||
| 354 | index = INDEX(LinAdr); | ||
| 355 | |||
| 356 | pte = PFT(UserPFTIndex) & ~0xfff; /* Pg Frame Adr in 20 MSBs */ | ||
| 357 | |||
| 358 | SetPteFromIndex(index, pte); | ||
| 359 | SetPteFromIndex(index+1, pte+HEX4K); | ||
| 360 | SetPteFromIndex(index+2, pte+HEX4K*2); | ||
| 361 | SetPteFromIndex(index+3, pte+HEX4K*3); | ||
| 362 | } | ||
| 363 | |||
| 364 | /* exchange 4 ptes at LinAdr1 and LinAdr2 */ | ||
| 365 | ExchangePTEs(LinAdr1, LinAdr2) | ||
| 366 | long LinAdr1, LinAdr2; | ||
| 367 | { | ||
| 368 | unsigned index1, index2; | ||
| 369 | long tPte; | ||
| 370 | int i; | ||
| 371 | |||
| 372 | index1 = INDEX(LinAdr1); | ||
| 373 | index2 = INDEX(LinAdr2); | ||
| 374 | |||
| 375 | for (i = 0; i < 4; i++) { | ||
| 376 | tPte = PT(index1+i); | ||
| 377 | SetPteFromIndex(index1+i, PT(index2+i)); | ||
| 378 | SetPteFromIndex(index2+i, tPte); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | /* sanity check on the index, and then call GetPte */ | ||
| 383 | long GetPteFromIndex(index) | ||
| 384 | unsigned index; | ||
| 385 | { | ||
| 386 | unsigned i; | ||
| 387 | long PhyAdr; | ||
| 388 | |||
| 389 | PhyAdr = ((long) index) << 12; | ||
| 390 | |||
| 391 | if (PhyAdr < HEX256K || PhyAdr >= HEX1MB) | ||
| 392 | return (PhyAdr); | ||
| 393 | |||
| 394 | i = EMM_MPindex[DOSPHYPAGE(PhyAdr)]; | ||
| 395 | |||
| 396 | if (i != -1) | ||
| 397 | return GetPte(index); | ||
| 398 | else | ||
| 399 | return PhyAdr; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* sanity check on the index and then call SetPte */ | ||
| 403 | SetPteFromIndex(index, pte) | ||
| 404 | unsigned index; | ||
| 405 | long pte; | ||
| 406 | { | ||
| 407 | unsigned i; | ||
| 408 | long PhyAdr; | ||
| 409 | |||
| 410 | PhyAdr = ((long) index) << 12; | ||
| 411 | |||
| 412 | if (PhyAdr < HEX256K || PhyAdr >= HEX1MB) | ||
| 413 | return; | ||
| 414 | |||
| 415 | i = EMM_MPindex[DOSPHYPAGE(PhyAdr)]; | ||
| 416 | |||
| 417 | if (i != -1) | ||
| 418 | return SetPte(index, pte); | ||
| 419 | else | ||
| 420 | return; | ||
| 421 | } | ||
| 422 | |||
| 423 | |||
| 424 | |||
| 425 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/MAPLIN.ASM b/v4.0/src/MEMM/MEMM/MAPLIN.ASM new file mode 100644 index 0000000..d37d9ac --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MAPLIN.ASM | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MapLinear - map linear address according to page tables | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: MapLinear | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 2, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/08/86 Original | ||
| 27 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 28 | ; 07/05/86 0.04 DiagByte moved to _DATA | ||
| 29 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ; | ||
| 33 | ; Functional Description: | ||
| 34 | ; This routine in this module takes a "virtual" addresses specified by | ||
| 35 | ; a virtual mode processs and "maps" it to the corresponding linear address | ||
| 36 | ; according to the linear to physical mapping in the page tables. | ||
| 37 | ; This file also contains a routine to do the inverse mapping. | ||
| 38 | ; | ||
| 39 | ; | ||
| 40 | ;****************************************************************************** | ||
| 41 | .lfcond ; list false conditionals | ||
| 42 | .386p | ||
| 43 | page | ||
| 44 | ;****************************************************************************** | ||
| 45 | ; P U B L I C D E C L A R A T I O N S | ||
| 46 | ;****************************************************************************** | ||
| 47 | ; | ||
| 48 | public MapLinear | ||
| 49 | public UnMapLinear | ||
| 50 | ; | ||
| 51 | |||
| 52 | page | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; I N C L U D E F I L E S | ||
| 55 | ;****************************************************************************** | ||
| 56 | |||
| 57 | include vdmseg.inc | ||
| 58 | include vdmsel.inc | ||
| 59 | include instr386.inc | ||
| 60 | include oemdep.inc | ||
| 61 | |||
| 62 | ;****************************************************************************** | ||
| 63 | ; E X T E R N A L R E F E R E N C E S | ||
| 64 | ;****************************************************************************** | ||
| 65 | ; | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; C O D E S E G M E N T | ||
| 68 | ;****************************************************************************** | ||
| 69 | _TEXT segment | ||
| 70 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 71 | page | ||
| 72 | ;****************************************************************************** | ||
| 73 | ; MapLinear - maps a linear address to it's "true" linear address. | ||
| 74 | ; | ||
| 75 | ; ENTRY: PROTECTED MODE ONLY | ||
| 76 | ; EAX = 32 bit linear address | ||
| 77 | ; | ||
| 78 | ; EXIT: EAX = 32 bit "mapped" linear address | ||
| 79 | ; | ||
| 80 | ; USED: none. | ||
| 81 | ; | ||
| 82 | ; The page dir and table set up by this routine maps the linear | ||
| 83 | ; addresses for Virtual mode programs into physical addresses using | ||
| 84 | ; the following scheme. Note that "high" memory is mapped to the | ||
| 85 | ; range starting at 16 Meg so that the page tables can be shorter. | ||
| 86 | ; | ||
| 87 | ; Linear Addr Physical Addr | ||
| 88 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 89 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 90 | ; 00110000h - 010FFFFFh 00100000h - 00FFFFFFh (top 15Meg of phys) | ||
| 91 | ifndef NOHIMEM | ||
| 92 | ; 01010000h - 0101FFFFh xxxx0000h - xxxxFFFFh ("high" memory) | ||
| 93 | ; xxxx is mapped by Map_Lin_OEM in OEMPROC module | ||
| 94 | endif | ||
| 95 | ; | ||
| 96 | ; True Linear is same as linear in our new mapping scheme. So except | ||
| 97 | ; for the "high" memory we have the true linear returned being the same | ||
| 98 | ; as linear. The new mapping is: | ||
| 99 | ; | ||
| 100 | ; Linear Addr Physical Addr | ||
| 101 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 102 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 103 | ; 00110000h - 00ffffffh 00110000h - 00ffffffh (top 15Meg of phys) | ||
| 104 | ; 01000000h - 0100FFFFh xxxx0000h - xxxxFFFFh ("high" memory) | ||
| 105 | ; xxxx is mapped by Map_Lin_OEM in OEMPROC module | ||
| 106 | ; | ||
| 107 | ;****************************************************************************** | ||
| 108 | MapLinear proc near | ||
| 109 | ; | ||
| 110 | call Map_Lin_OEM ;Q: Special mapping done by OEM routines? | ||
| 111 | jc ML_Exit ; Y: AX = mapped address | ||
| 112 | ; N: Do standard mapping | ||
| 113 | |||
| 114 | ; | ||
| 115 | ; the routine here is to be executed to get the true linear address. Since | ||
| 116 | ; it is a 1 - 1 mapping we have no code here | ||
| 117 | ; | ||
| 118 | ML_exit: | ||
| 119 | ret | ||
| 120 | ; | ||
| 121 | MapLinear endp | ||
| 122 | |||
| 123 | |||
| 124 | ;****************************************************************************** | ||
| 125 | ; UnMapLinear - maps a "true" linear address to it's linear address. | ||
| 126 | ; | ||
| 127 | ; ENTRY: EAX = 32 bit "mapped" linear address | ||
| 128 | ; | ||
| 129 | ; EXIT: EAX = 32 bit linear address | ||
| 130 | ; | ||
| 131 | ; USED: none. | ||
| 132 | ; | ||
| 133 | ; The page dir and table set up maps the linear | ||
| 134 | ; addresses for Virtual mode programs into physical addresses using | ||
| 135 | ; the following scheme. | ||
| 136 | ; Linear Addr Physical Addr | ||
| 137 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 138 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 139 | ; 00110000h - 010FFFFFh 00100000h - 00FFFFFFh (top 15Meg of phys) | ||
| 140 | ifndef NOHIMEM | ||
| 141 | ; 01010000h - 0101FFFFh xxxx0000h - xxxxFFFFh (high memory) | ||
| 142 | ; xxxx is mapped by UMap_Lin_OEM in OEMPROC module | ||
| 143 | endif | ||
| 144 | ; | ||
| 145 | ; Our new mapping scheme is: | ||
| 146 | ; | ||
| 147 | ; Linear Addr Physical Addr | ||
| 148 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 149 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 150 | ; 00110000h - 00ffffffh 00110000h - 00ffffffh (top 15Meg of phys) | ||
| 151 | ; 01000000h - 0100FFFFh xxxx0000h - xxxxFFFFh ("high" memory) | ||
| 152 | ; xxxx is mapped by Map_Lin_OEM in OEMPROC module | ||
| 153 | ; | ||
| 154 | ;****************************************************************************** | ||
| 155 | UnMapLinear proc near | ||
| 156 | ; | ||
| 157 | cmp eax,01000000 ; | ||
| 158 | jb UML_mask ; N: chk for < 1 meg | ||
| 159 | call UMap_Lin_OEM ; Y: set EAX to physical address for diags | ||
| 160 | jmp short UML_exit | ||
| 161 | |||
| 162 | UML_mask: | ||
| 163 | UML_exit: | ||
| 164 | ret | ||
| 165 | ; | ||
| 166 | UnMapLinear endp | ||
| 167 | |||
| 168 | |||
| 169 | _TEXT ends | ||
| 170 | |||
| 171 | end | ||
| 172 | |||
diff --git a/v4.0/src/MEMM/MEMM/MEMM386.ASM b/v4.0/src/MEMM/MEMM/MEMM386.ASM new file mode 100644 index 0000000..d2b6d26 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMM386.ASM | |||
| @@ -0,0 +1,561 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MEMM386 - main module for MEMM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: MEMM386 - main module | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: May 24,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 04/24/86 Original From EMML LIM driver. | ||
| 27 | ; 06/26/86 0.02 Put CLD in Inst_Chk | ||
| 28 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM. | ||
| 29 | ; 07/05/86 0.04 Changed segment to R_CODE | ||
| 30 | ; 06/07/88 exclude VDISK header info's since we are | ||
| 31 | ; using INT-15 method now (Paul Chan) | ||
| 32 | ; 06/21/88 Removed VDISK stuff. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | ; Functional Description: | ||
| 36 | ; MEMM is an Expanded Memory Manager which implements expanded memory | ||
| 37 | ; on the MICROSOFT 386 machine. MEMM uses Virtual mode and paging on | ||
| 38 | ; the 386 to make Extended memory useable as expanded memory. The are two | ||
| 39 | ; basic functional parts of MEMM; the Virtual DOS Monitor (VDM) and the | ||
| 40 | ; Expanded Memory Manager (EMM). VDM simulates the 386 Real mode under the | ||
| 41 | ; 386 Virtual mode. EMM provides the software functionality for a EMM as | ||
| 42 | ; described in the Lotus-Intel-Microsoft (LIM) specification for expanded | ||
| 43 | ; memory. | ||
| 44 | ; This module contains the Device Driver header, stategy, and interrupt | ||
| 45 | ; routines required by a LIM standard EMM. | ||
| 46 | ; This device driver is a .EXE file and may be invoked as a DOS utility | ||
| 47 | ; program as well as loaded as a device driver. When it is loaded as a | ||
| 48 | ; DOS utility, MEMM has three command line options: ON,OFF and AUTO. | ||
| 49 | ; The OFF options disables MEMM and exits to MS-DOS in real mode. | ||
| 50 | ; The ON option enables MEMM and exits to MS-DOS in virtual mode (only | ||
| 51 | ; if the MEMM.EXE driver has been loaded). The AUTO option puts | ||
| 52 | ; MEMM in "auto mode". In this mode, MEMM will enable and disable | ||
| 53 | ; itself automatically, depending on accesses to the EMM functions. | ||
| 54 | ; The general device driver CONFIG.SYS options are described below. | ||
| 55 | ; | ||
| 56 | ; Syntax: | ||
| 57 | ; | ||
| 58 | ; device=[d]:[<path>]MEMM.EXE [SIZE] [Mx] [ON | OFF | AUTO] | ||
| 59 | ; | ||
| 60 | ; | ||
| 61 | ; NOTE: SUNILP - See if we need the /X option for excluding segments from | ||
| 62 | ; being mappable. This turned out to be quite useful in ps2emm and since | ||
| 63 | ; here we are dealing with different hardware this option may turn out | ||
| 64 | ; essential here**** WISH001 | ||
| 65 | ; | ||
| 66 | ; The following sections describe the optional arguments which the | ||
| 67 | ; user may specify for MEMM.EXE at load time (in the CONFIG.SYS | ||
| 68 | ; file). These arguments are placed after the device driver name | ||
| 69 | ; in the CONFIG.SYS file. | ||
| 70 | ; | ||
| 71 | ; MEMM arguments in the CONFIG.SYS file must be separated by spaces | ||
| 72 | ; or tabs. Arguments may appear in any order; however, any redundant | ||
| 73 | ; or excessive instances are ignored and only the first valid instance | ||
| 74 | ; of an argument is used. Invalid or extraneous arguments produce an | ||
| 75 | ; error message. | ||
| 76 | ; | ||
| 77 | ; [SIZE] | ||
| 78 | ; | ||
| 79 | ; The argument SIZE is the amount of expanded memory desired in | ||
| 80 | ; K bytes. The default amount of expanded memory, 256K, is available | ||
| 81 | ; without using any extended memory. To use more than 256K of | ||
| 82 | ; expanded memory, the 386 system must have extended memory. When | ||
| 83 | ; If there is not enough memory available | ||
| 84 | ; to provide SIZE kbytes of expanded memory, MEMM will adjust SIZE to | ||
| 85 | ; provide as much expanded memory as possible. | ||
| 86 | ; | ||
| 87 | ; - The valid range for SIZE is 16K - 8192K. Value outside this range | ||
| 88 | ; are converted to the default of 256K. | ||
| 89 | ; | ||
| 90 | ; - If SIZE is not a multiple of 16K (size of an EMM page), then SIZE | ||
| 91 | ; is rounded down to the nearest multiple of 16K. | ||
| 92 | ; | ||
| 93 | ; [Mx] | ||
| 94 | ; | ||
| 95 | ; The argument [Mx] specifies the address of the 64k EMM page frame. | ||
| 96 | ; This argument is optional since MEMM can choose an appropriate | ||
| 97 | ; location for the page frame when it is loaded. To choose a location | ||
| 98 | ; the 386 EMM driver scans memory addresses above video memory for | ||
| 99 | ; an appropriate 64K address range for the EMM page frame. For a | ||
| 100 | ; default page frame base address MEMM looks for option ROMs and | ||
| 101 | ; RAM in the EMM addressing range and chooses a 64K slot of memory | ||
| 102 | ; for the page frame which apparently does not confict with existing | ||
| 103 | ; memory. The user may override the 386 EMM driver's choice by | ||
| 104 | ; specifying the beginning address with the Mx argument. If the | ||
| 105 | ; user specifies a page frame base address which conflicts with an | ||
| 106 | ; option ROM or RAM, MEMM displays a warning message and uses the | ||
| 107 | ; specified page frame base address. | ||
| 108 | ; | ||
| 109 | ; The following options are possible: | ||
| 110 | ; Page Frame Base Address | ||
| 111 | ; M1 => 0C0000 Hex | ||
| 112 | ; M2 => 0C4000 Hex | ||
| 113 | ; M3 => 0C8000 Hex | ||
| 114 | ; M4 => 0CC000 Hex | ||
| 115 | ; M5 => 0D0000 Hex | ||
| 116 | ; | ||
| 117 | ; [ ON | OFF | AUTO ] | ||
| 118 | ; | ||
| 119 | ; The argument [ON | OFF | AUTO] specifies the state of the 386 when | ||
| 120 | ; MEMM returns to DOS after the driver INIT routine finishes. If this | ||
| 121 | ; argument is ON, then MEMM returns to DOS in virtual mode and | ||
| 122 | ; expanded memory is available. If this argument is OFF, then MEMM | ||
| 123 | ; returns to DOS in real mode and expanded memory is not available | ||
| 124 | ; until MEMM is turned ON. The default for this argument is AUTO | ||
| 125 | ; mode. In AUTO mode, the MEMM.EXE device driver will exit to | ||
| 126 | ; DOS in the OFF state; afterwards, MEMM will enable and disable | ||
| 127 | ; itself automatically. In the AUTO mode, MEMM will be enabled | ||
| 128 | ; only while the expanded memory manager is in use. | ||
| 129 | ; | ||
| 130 | ; | ||
| 131 | ;****************************************************************************** | ||
| 132 | .lfcond | ||
| 133 | .386p | ||
| 134 | page | ||
| 135 | ;****************************************************************************** | ||
| 136 | ; P U B L I C D E C L A R A T I O N S | ||
| 137 | ;****************************************************************************** | ||
| 138 | |||
| 139 | ; | ||
| 140 | ; R_CODE publics | ||
| 141 | ; | ||
| 142 | public strategy | ||
| 143 | public interrupt | ||
| 144 | public MEMM_Entry | ||
| 145 | |||
| 146 | ; | ||
| 147 | ; _TEXT publics | ||
| 148 | ; | ||
| 149 | public ELIM_EXE ; .EXE execution entry point | ||
| 150 | public ELIM_link | ||
| 151 | public Inst_chk ; Check to see if MEMM already installed | ||
| 152 | public Inst_chk_f ; Far call version of above | ||
| 153 | |||
| 154 | page | ||
| 155 | ;****************************************************************************** | ||
| 156 | ; L O C A L C O N S T A N T S | ||
| 157 | ;****************************************************************************** | ||
| 158 | ; | ||
| 159 | include driver.equ | ||
| 160 | include driver.str | ||
| 161 | include vdmseg.inc | ||
| 162 | |||
| 163 | FALSE equ 0 | ||
| 164 | TRUE equ not FALSE | ||
| 165 | |||
| 166 | MS_DOS equ 21h ; DOS interrupt | ||
| 167 | GET_PSP equ 62h ; get program segment prefix | ||
| 168 | |||
| 169 | NULL EQU 0FFFFH ;Null address pointer | ||
| 170 | |||
| 171 | dospsp_str struc | ||
| 172 | db 80h dup (?) | ||
| 173 | cmd_len db ? ; length of command line | ||
| 174 | cmd_line db ? ; commande line | ||
| 175 | dospsp_str ends | ||
| 176 | |||
| 177 | ;****************************************************************************** | ||
| 178 | ; E X T E R N A L R E F E R E N C E S | ||
| 179 | ;****************************************************************************** | ||
| 180 | ; | ||
| 181 | abs0 segment use16 at 0000h | ||
| 182 | |||
| 183 | org 67h*4 ; EMM function interrupt | ||
| 184 | int67 dw ? ; offset of vector | ||
| 185 | dw ? ; segment of vector | ||
| 186 | abs0 ends | ||
| 187 | |||
| 188 | LAST segment | ||
| 189 | extrn Init_MEMM386:far ; initializes VDM,EMM, and driver | ||
| 190 | LAST ends | ||
| 191 | |||
| 192 | R_CODE segment | ||
| 193 | extrn ELIM_Entry:far ; general entry point for MEMM functions | ||
| 194 | R_CODE ends | ||
| 195 | |||
| 196 | _TEXT segment | ||
| 197 | extrn onf_func:near ; perform on, off, or auto checking for elim.exe | ||
| 198 | _TEXT ends | ||
| 199 | |||
| 200 | page | ||
| 201 | ;****************************************************************************** | ||
| 202 | ; S E G M E N T D E F I N I T I O N | ||
| 203 | ;****************************************************************************** | ||
| 204 | ; | ||
| 205 | ;****************************************************************************** | ||
| 206 | ; | ||
| 207 | ; R_CODE Code Segment | ||
| 208 | ; | ||
| 209 | ;****************************************************************************** | ||
| 210 | ; | ||
| 211 | R_CODE segment | ||
| 212 | assume cs:R_CODE, ds:R_CODE, es:R_CODE, ss:R_CODE | ||
| 213 | |||
| 214 | Start: | ||
| 215 | ;****************************************************************************** | ||
| 216 | ; Device driver header | ||
| 217 | ;****************************************************************************** | ||
| 218 | ; | ||
| 219 | DW NULL ;Null segment address | ||
| 220 | DW NULL ;Null offset address | ||
| 221 | DW CHAR_DEV+IOCTL_SUP ;Attribute - Char | ||
| 222 | DW OFFSET STRATEGY ;Strategy routine entry | ||
| 223 | DW OFFSET INTERRUPT ;Interrupt routine entry | ||
| 224 | DB 'EMMXXXX0' ;Character device name | ||
| 225 | ; | ||
| 226 | ;****************************************************************************** | ||
| 227 | ; GENERAL FUNCTIONS ENTRY POINT | ||
| 228 | ; R_CODE:ELIM_Entry is a entry point for executing general MEMM | ||
| 229 | ; functions. (e.g. ON, OFF function). | ||
| 230 | ;****************************************************************************** | ||
| 231 | ; | ||
| 232 | MEMM_Entry dw offset ELIM_Entry ; general entry point | ||
| 233 | |||
| 234 | ;****************************************************************************** | ||
| 235 | ; MEMM signature | ||
| 236 | ;****************************************************************************** | ||
| 237 | memmsig db 'MICROSOFT EXPANDED MEMORY MANAGER 386' | ||
| 238 | SIG_LENGTH equ (this byte - memmsig) | ||
| 239 | |||
| 240 | page | ||
| 241 | ;****************************************************************************** | ||
| 242 | ; L O C A L D A T A A R E A | ||
| 243 | ;****************************************************************************** | ||
| 244 | |||
| 245 | ; | ||
| 246 | ; Define the command dispatch table for the driver functions | ||
| 247 | ; | ||
| 248 | Cmd_Table LABEL NEAR | ||
| 249 | DW Init_Call ;0 - Initialization | ||
| 250 | DW Null_Exit ;1 - Media Check | ||
| 251 | DW Null_Exit ;2 - Get BPB | ||
| 252 | DW Null_Exit ;3 - IOCTL input | ||
| 253 | DW Null_Exit ;4 - Input (Destructive) | ||
| 254 | DW Null_Exit ;5 - No wait input | ||
| 255 | DW Null_Exit ;6 - Input status | ||
| 256 | DW Null_Exit ;7 - Input buffer flush | ||
| 257 | DW Null_Exit ;8 - Output (Write) | ||
| 258 | DW Null_Exit ;9 - Output with verify | ||
| 259 | DW Null_Exit ;A - Output status | ||
| 260 | DW Null_Exit ;B - Output buffer flush | ||
| 261 | DW Null_Exit ;C - IOCTL output | ||
| 262 | TBL_LENGTH EQU (THIS BYTE-CMD_TABLE)/2 ;Dispatch table length | ||
| 263 | |||
| 264 | public ReqPtr | ||
| 265 | ReqPtr label dword ; dword ptr to Request Header | ||
| 266 | ReqOff dw 0 ; saved offset of Request Header | ||
| 267 | ReqSeg dw 0 ; saved segment of Request Header | ||
| 268 | |||
| 269 | page | ||
| 270 | ;****************************************************************************** | ||
| 271 | ; Strategy - strategy routine for MEMM | ||
| 272 | ; | ||
| 273 | ; ENTRY: ES:BX = pointer to Request Header | ||
| 274 | ; | ||
| 275 | ; EXIT: CS:ReqOff, CS:ReqSeg - saved pointer to Request Header | ||
| 276 | ; | ||
| 277 | ; USED: none | ||
| 278 | ; | ||
| 279 | ;****************************************************************************** | ||
| 280 | Strategy proc far | ||
| 281 | mov CS:[ReqOff],bx ;Save header offset | ||
| 282 | mov CS:[ReqSeg],es ;Save header segment | ||
| 283 | ret | ||
| 284 | Strategy endp | ||
| 285 | |||
| 286 | ;****************************************************************************** | ||
| 287 | ; Interrupt - device driver interrupt routine for MEMM | ||
| 288 | ; | ||
| 289 | ; ENTRY: CS:ReqPtr = pointer to request header. | ||
| 290 | ; | ||
| 291 | ; EXIT: Request completed. | ||
| 292 | ; | ||
| 293 | ; USED: none | ||
| 294 | ; | ||
| 295 | ;****************************************************************************** | ||
| 296 | Interrupt proc far | ||
| 297 | push ax | ||
| 298 | push bx | ||
| 299 | push cx | ||
| 300 | push dx | ||
| 301 | push si | ||
| 302 | push di | ||
| 303 | push ds | ||
| 304 | push es | ||
| 305 | cld ;All strings forward | ||
| 306 | lds bx,CS:[ReqPtr] ;DS:BX pts to Request Header | ||
| 307 | mov al,[bx.COMMAND_CODE] ;Get the command code | ||
| 308 | cmp al,TBL_LENGTH ;Check for validity | ||
| 309 | jae Invalid ;Jump if command invalid | ||
| 310 | cbw ;Command to a full word | ||
| 311 | shl ax,1 ;Compute dispatch index | ||
| 312 | mov si,OFFSET Cmd_Table ;Point to dispatch table | ||
| 313 | add si,ax ;Index based on command | ||
| 314 | call CS:[si] ;Call correct routine | ||
| 315 | |||
| 316 | ; | ||
| 317 | ; ENTRY: AX = Status field for Request Header | ||
| 318 | ; | ||
| 319 | Finish: | ||
| 320 | lds bx,CS:[ReqPtr] ;Get request header ptr. | ||
| 321 | or ah,DON ;Set done bit in status | ||
| 322 | mov DS:[bx.STATUS_WORD],ax ;Save status in header | ||
| 323 | pop es ;Restore the ES register | ||
| 324 | pop ds | ||
| 325 | pop di | ||
| 326 | pop si | ||
| 327 | pop dx | ||
| 328 | pop cx | ||
| 329 | pop bx | ||
| 330 | pop ax | ||
| 331 | ret | ||
| 332 | Invalid: | ||
| 333 | mov al,UNK_COMMAND ; unknown command | ||
| 334 | mov ah,ERR ; error | ||
| 335 | stc | ||
| 336 | jmp SHORT Finish ;Go return to caller | ||
| 337 | Interrupt endp | ||
| 338 | |||
| 339 | ;****************************************************************************** | ||
| 340 | ; Null_Exit: do nothing | ||
| 341 | ; | ||
| 342 | ; ENTRY: DS:BX pts to request header | ||
| 343 | ; | ||
| 344 | ; EXIT: No error returned. | ||
| 345 | ; CLC | ||
| 346 | ; | ||
| 347 | ;****************************************************************************** | ||
| 348 | Null_Exit proc near | ||
| 349 | ; | ||
| 350 | xor ax,ax | ||
| 351 | clc | ||
| 352 | ret | ||
| 353 | ; | ||
| 354 | Null_Exit endp | ||
| 355 | |||
| 356 | ;****************************************************************************** | ||
| 357 | ; Init_Call - call initialization routine | ||
| 358 | ; | ||
| 359 | ; ENTRY: DS:BX pts to request header | ||
| 360 | ; | ||
| 361 | ; EXIT: AX = status field for request header | ||
| 362 | ; | ||
| 363 | ;****************************************************************************** | ||
| 364 | Init_Call proc near | ||
| 365 | ; | ||
| 366 | call Init_MEMM386 | ||
| 367 | ret | ||
| 368 | ; | ||
| 369 | Init_Call endp | ||
| 370 | |||
| 371 | ;****************************************************************************** | ||
| 372 | db 'SBP' | ||
| 373 | db 'BMT' | ||
| 374 | ;****************************************************************************** | ||
| 375 | ; | ||
| 376 | |||
| 377 | R_CODE ends | ||
| 378 | |||
| 379 | page | ||
| 380 | ;****************************************************************************** | ||
| 381 | ; | ||
| 382 | ; _TEXT Code Segment | ||
| 383 | ; | ||
| 384 | ;****************************************************************************** | ||
| 385 | _TEXT segment | ||
| 386 | assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT | ||
| 387 | |||
| 388 | FarLink dd 0 ; far pointer to installed memm386 entry point | ||
| 389 | ; OK as writeable because it is only used | ||
| 390 | ; during .EXE execution. | ||
| 391 | |||
| 392 | ; | ||
| 393 | rh db 23,0,0,0,0,8 dup (0) | ||
| 394 | db 10 dup (0) | ||
| 395 | ; | ||
| 396 | MEMM: | ||
| 397 | ;****************************************************************************** | ||
| 398 | ; | ||
| 399 | ; ELIM_EXE - .EXE entry point - when MEMM.EXE is invoked as a DOS | ||
| 400 | ; utility. | ||
| 401 | ; | ||
| 402 | ;****************************************************************************** | ||
| 403 | |||
| 404 | ;------------------------------------------------------------------------------ | ||
| 405 | ; NOTE** SUNILP .. Paulch changed this to load it as an terminate and stay | ||
| 406 | ; resident. This entry should only be to turn an existing MEMM ON | ||
| 407 | ; OFF or AUTO. Once the driver is debugged change this back to the | ||
| 408 | ; original code given here in comments. Also remove the above rh | ||
| 409 | ; storage block. WISH002 | ||
| 410 | ;ELIM_EXE proc near | ||
| 411 | ;; | ||
| 412 | ; push cs | ||
| 413 | ; pop ds ; ds = cs | ||
| 414 | ; mov ah,GET_PSP ; get segment of PSP | ||
| 415 | ; int MS_DOS | ||
| 416 | ; mov es,bx ; DOS call returned seg in bx | ||
| 417 | ; mov di,offset cmd_line ; es:di = command line | ||
| 418 | ; call onf_func ; look for on, off, or auto | ||
| 419 | ; mov ax,4c00h ; exit to DOS | ||
| 420 | ; int MS_DOS | ||
| 421 | ;; | ||
| 422 | ;ELIM_EXE endp | ||
| 423 | ;; | ||
| 424 | ;------------------------------------------------------------------------------ | ||
| 425 | |||
| 426 | ELIM_EXE proc near | ||
| 427 | ; | ||
| 428 | extrn exe_stack:byte | ||
| 429 | |||
| 430 | push seg STACK | ||
| 431 | pop ss | ||
| 432 | mov sp, offset STACK:exe_stack | ||
| 433 | push cs | ||
| 434 | pop ds | ||
| 435 | mov ah,GET_PSP | ||
| 436 | int MS_DOS | ||
| 437 | mov es,bx | ||
| 438 | mov di,offset cmd_line | ||
| 439 | |||
| 440 | mov bx,seg rh | ||
| 441 | mov ds,bx | ||
| 442 | mov bx,offset rh | ||
| 443 | mov [bx+20],es | ||
| 444 | mov [bx+18],di | ||
| 445 | |||
| 446 | push ds | ||
| 447 | pop es | ||
| 448 | call Strategy | ||
| 449 | call Interrupt | ||
| 450 | |||
| 451 | mov bx,seg rh | ||
| 452 | mov es,bx | ||
| 453 | mov bx,offset rh | ||
| 454 | mov dx,es:[bx+16] | ||
| 455 | sub dx,es:[bx+20] | ||
| 456 | mov ah,31h | ||
| 457 | int 21h | ||
| 458 | ; | ||
| 459 | |||
| 460 | ; push cs | ||
| 461 | ; pop ds ; ds = cs | ||
| 462 | ; mov ah,GET_PSP ; get segment of PSP | ||
| 463 | ; int MS_DOS | ||
| 464 | ; mov es,bx ; DOS call returned seg in bx | ||
| 465 | ; mov di,offset cmd_line ; es:di = command line | ||
| 466 | ; call onf_func ; look for on, off, or auto | ||
| 467 | mov ax,4c00h ; exit to DOS | ||
| 468 | int MS_DOS | ||
| 469 | ; | ||
| 470 | ELIM_EXE endp | ||
| 471 | ; | ||
| 472 | ;****************************************************************************** | ||
| 473 | ; Inst_chk_f - call Inst_chk | ||
| 474 | ; | ||
| 475 | ; ENTRY: see Inst_chk | ||
| 476 | ; | ||
| 477 | ; EXIT: see Inst_chk | ||
| 478 | ; | ||
| 479 | ; USED: none | ||
| 480 | ; | ||
| 481 | ;****************************************************************************** | ||
| 482 | Inst_chk_f proc far | ||
| 483 | call Inst_chk | ||
| 484 | ret | ||
| 485 | Inst_chk_f endp | ||
| 486 | |||
| 487 | ;****************************************************************************** | ||
| 488 | ; Inst_chk - Check to see if MEMM is already installed | ||
| 489 | ; | ||
| 490 | ; ENTRY: int 67 vector | ||
| 491 | ; | ||
| 492 | ; EXIT: ax = 0 if not already installed | ||
| 493 | ; ax = 1 if MEMM is already installed | ||
| 494 | ; _TEXT:[FarLink] = far address for installed MEMM entry point | ||
| 495 | ; | ||
| 496 | ; USED: none | ||
| 497 | ; | ||
| 498 | ;****************************************************************************** | ||
| 499 | Inst_chk proc near | ||
| 500 | push di ; save di | ||
| 501 | push si ; and si | ||
| 502 | push ds ; and ds | ||
| 503 | push es ; and es | ||
| 504 | push cx ; and cx | ||
| 505 | ; | ||
| 506 | xor ax,ax ; put segment 0000h in ds | ||
| 507 | mov ds,ax | ||
| 508 | ASSUME DS:abs0 ; assume ds is abs0 | ||
| 509 | mov ax,[int67+2] ; get segment pointed to by int 67 | ||
| 510 | mov es,ax | ||
| 511 | ASSUME ES:R_CODE | ||
| 512 | |||
| 513 | push seg R_CODE | ||
| 514 | pop ds ; set DS = R_CODE | ||
| 515 | assume DS:R_CODE ; update assume | ||
| 516 | |||
| 517 | mov di,offset memmsig ; memm386 signature | ||
| 518 | mov si,di ; save for source string | ||
| 519 | xor ax,ax ; initialize to not found | ||
| 520 | mov cx,SIG_LENGTH ; length to compare | ||
| 521 | cld ; strings foward | ||
| 522 | repe cmpsb ; q: is the memm386 signature out there? | ||
| 523 | jne not_inst ; n: return zero | ||
| 524 | inc ax ; y: return one | ||
| 525 | mov word ptr CS:[FarLink+2],es ; set segment of far call | ||
| 526 | mov cx,ES:[MEMM_Entry] ; get offset for far call | ||
| 527 | mov word ptr CS:[FarLink],cx ; set offset of far call | ||
| 528 | not_inst: | ||
| 529 | |||
| 530 | ASSUME DS:_TEXT, ES:_TEXT | ||
| 531 | |||
| 532 | pop cx | ||
| 533 | pop es | ||
| 534 | pop ds | ||
| 535 | pop si | ||
| 536 | pop di | ||
| 537 | ret | ||
| 538 | Inst_chk endp | ||
| 539 | |||
| 540 | ;****************************************************************************** | ||
| 541 | ; ELIM_link - Link to Installed MEMM's ELIM_Entry | ||
| 542 | ; | ||
| 543 | ; ENTRY: see ELIM_Entry | ||
| 544 | ; and | ||
| 545 | ; _TEXT:[FarLink] = far address of installed MEMM ELIM_Entry | ||
| 546 | ; | ||
| 547 | ; EXIT: see ELIM_Entry | ||
| 548 | ; | ||
| 549 | ; USED: none | ||
| 550 | ; | ||
| 551 | ;****************************************************************************** | ||
| 552 | ELIM_link proc near | ||
| 553 | call CS:[FarLink] | ||
| 554 | ret | ||
| 555 | ELIM_link endp | ||
| 556 | |||
| 557 | |||
| 558 | _TEXT ends | ||
| 559 | |||
| 560 | end MEMM | ||
| 561 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/MEMMCOM.ASM b/v4.0/src/MEMM/MEMM/MEMMCOM.ASM new file mode 100644 index 0000000..b92cfdb --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMMCOM.ASM | |||
| @@ -0,0 +1,243 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MEMMCOM - main module for MEMM.COM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.COM - MICROSOFT Expanded Memory Manager 386 Utility | ||
| 11 | ; | ||
| 12 | ; Module: MEMMCOM - main module for MEMM.COM | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: June 4, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/04/86 Original | ||
| 27 | ; 06/21/86 0.02 Added CLD to Inst_Chk | ||
| 28 | ; 06/28/86 0.02 Name change from MEMM386.COM to MEMM.COM | ||
| 29 | ; | ||
| 30 | ;****************************************************************************** | ||
| 31 | ; | ||
| 32 | ; Functional Description: | ||
| 33 | ; MEMM.COM which allows the user to poll or set the operating mode | ||
| 34 | ; of the MEMM device driver. | ||
| 35 | ; Syntax: | ||
| 36 | ; MEMM [ ON | OFF | AUTO ] | ||
| 37 | ; | ||
| 38 | ; If the user specifies no arguments, MEMM.COM will return the | ||
| 39 | ; current mode of the MEMM device driver. | ||
| 40 | ; | ||
| 41 | ; ON | ||
| 42 | ; If the user specifies ON, MEMM.COM enables the MEMM driver; | ||
| 43 | ; expanded memory is available and the processor is in virtual mode. | ||
| 44 | ; | ||
| 45 | ; OFF | ||
| 46 | ; If the user specifies OFF, MEMM.COM disables the MEMM driver; | ||
| 47 | ; expanded memory is not available and the processor is in real mode. | ||
| 48 | ; | ||
| 49 | ; AUTO | ||
| 50 | ; If the user specifies AUTO, MEMM.COM enables the MEMM driver's auto | ||
| 51 | ; mode. In auto mode, the driver will enable and disable itself | ||
| 52 | ; "automatically" (depending on accesses to the EMM functions). | ||
| 53 | ; | ||
| 54 | ;****************************************************************************** | ||
| 55 | .lfcond ; list false conditionals | ||
| 56 | .386p | ||
| 57 | page | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; P U B L I C D E C L A R A T I O N S | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; | ||
| 62 | public EMM386 | ||
| 63 | public Inst_chk | ||
| 64 | public ELIM_link | ||
| 65 | ; | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; E X T E R N A L R E F E R E N C E S | ||
| 68 | ;****************************************************************************** | ||
| 69 | _TEXT segment byte use16 public 'CODE' | ||
| 70 | extrn onf_func:near | ||
| 71 | _TEXT ends | ||
| 72 | abs0 segment use16 at 0000h | ||
| 73 | |||
| 74 | org 67h*4 ; EMM function interrupt | ||
| 75 | int67 dw ? ; offset of vector | ||
| 76 | dw ? ; segment of vector | ||
| 77 | abs0 ends | ||
| 78 | |||
| 79 | |||
| 80 | page | ||
| 81 | ;****************************************************************************** | ||
| 82 | ; L O C A L C O N S T A N T S | ||
| 83 | ;****************************************************************************** | ||
| 84 | ; | ||
| 85 | |||
| 86 | MSDOS equ 21h ; MS-DOS function call | ||
| 87 | |||
| 88 | ; | ||
| 89 | ; Device driver header for MEMM | ||
| 90 | ; | ||
| 91 | emm_hdr STRUC | ||
| 92 | ; | ||
| 93 | DW ? ;Null segment address | ||
| 94 | DW ? ;Null offset address | ||
| 95 | DW ? ;Attribute - Char | ||
| 96 | DW ? ;Strategy routine entry | ||
| 97 | DW ? ;Interrupt routine entry | ||
| 98 | DB 'EMMXXXX0' ;Character device name | ||
| 99 | ; | ||
| 100 | ; GENERAL FUNCTIONS ENTRY POINT | ||
| 101 | ; ELIM_Entry is a entry point for executing general MEMM | ||
| 102 | ; functions. (e.g. ON, OFF function). | ||
| 103 | ; | ||
| 104 | ELIM_Entry_off dw ? ; general entry point | ||
| 105 | |||
| 106 | ; | ||
| 107 | ; MEMM signature | ||
| 108 | ; | ||
| 109 | memmsig db ? ; MEMM signature | ||
| 110 | |||
| 111 | emm_hdr ends | ||
| 112 | |||
| 113 | ;****************************************************************************** | ||
| 114 | ; S E G M E N T D E F I N I T I O N | ||
| 115 | ;****************************************************************************** | ||
| 116 | ; | ||
| 117 | _TEXT segment byte use16 public 'CODE' | ||
| 118 | assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT | ||
| 119 | org 81h | ||
| 120 | cmd_line dw ? ; pointer to command line | ||
| 121 | ; | ||
| 122 | ;****************************************************************************** | ||
| 123 | ; M O D U L E E N T R Y P O I N T | ||
| 124 | ;****************************************************************************** | ||
| 125 | ; | ||
| 126 | ; Standard .COM entry conditions are assumed | ||
| 127 | ; | ||
| 128 | org 100h | ||
| 129 | EMM386 proc near | ||
| 130 | jmp start | ||
| 131 | ;****************************************************************************** | ||
| 132 | ; L O C A L D A T A A R E A | ||
| 133 | ;****************************************************************************** | ||
| 134 | ; | ||
| 135 | |||
| 136 | oursig db 'MICROSOFT EXPANDED MEMORY MANAGER 386' | ||
| 137 | SIG_LENGTH equ (this byte - oursig) | ||
| 138 | ; | ||
| 139 | ; define double word to store segment/offset of status routine for far call | ||
| 140 | ; | ||
| 141 | status_loc label dword | ||
| 142 | entry_off dw 0 ; store offset for far call | ||
| 143 | entry_seg dw 0 ; store segment for far call | ||
| 144 | ; | ||
| 145 | |||
| 146 | start: | ||
| 147 | push cs | ||
| 148 | pop ds | ||
| 149 | push cs | ||
| 150 | pop es | ||
| 151 | |||
| 152 | ; | ||
| 153 | cli | ||
| 154 | mov sp,offset Stack_Top | ||
| 155 | sti | ||
| 156 | ; | ||
| 157 | cld | ||
| 158 | ; | ||
| 159 | mov di,offset cmd_line ; es:di = command line pointer | ||
| 160 | call onf_func ; do the on/off function | ||
| 161 | |||
| 162 | mov ax,4C00h | ||
| 163 | int MSDOS ; exit to DOS | ||
| 164 | |||
| 165 | EMM386 endp | ||
| 166 | |||
| 167 | page | ||
| 168 | ;****************************************************************************** | ||
| 169 | ; ELIM_link - Call ELIM_Entry status routine via the status_loc | ||
| 170 | ; | ||
| 171 | ; ENTRY: [status_loc] contains the far address | ||
| 172 | ; | ||
| 173 | ; EXIT: ? | ||
| 174 | ; | ||
| 175 | ; USED: none | ||
| 176 | ; | ||
| 177 | ;****************************************************************************** | ||
| 178 | ELIM_link proc near | ||
| 179 | call status_loc | ||
| 180 | ret | ||
| 181 | ELIM_link endp | ||
| 182 | page | ||
| 183 | ;****************************************************************************** | ||
| 184 | ; Inst_chk - Check to see if MEMM is already installed | ||
| 185 | ; | ||
| 186 | ; ENTRY: int 67 vector | ||
| 187 | ; | ||
| 188 | ; EXIT: ax = 0 if not already installed | ||
| 189 | ; ax = 1 if MEMM is already installed | ||
| 190 | ; If MEMM is installed, then | ||
| 191 | ; [entry_seg] = segment of driver header | ||
| 192 | ; [entry_off] = offset of status routine in MEMM | ||
| 193 | ; | ||
| 194 | ; USED: none | ||
| 195 | ; | ||
| 196 | ;****************************************************************************** | ||
| 197 | Inst_chk proc near | ||
| 198 | push di ; save di | ||
| 199 | push si ; and si | ||
| 200 | push ds ; and ds | ||
| 201 | push es ; and es | ||
| 202 | push cx ; and cx | ||
| 203 | ; | ||
| 204 | xor ax,ax ; put segment 0000h in ds | ||
| 205 | mov ds,ax | ||
| 206 | assume ds:abs0 ; assume ds is abs0 | ||
| 207 | mov ax,[int67+2] ; get segment pointed to by int 67 | ||
| 208 | mov es,ax | ||
| 209 | |||
| 210 | assume ds:_TEXT ; update assume | ||
| 211 | push cs | ||
| 212 | pop ds ; set DS = _TEXT | ||
| 213 | |||
| 214 | mov di,offset memmsig ; MEMM signature | ||
| 215 | mov si,offset oursig ; point to our signature | ||
| 216 | xor ax,ax ; initialize to not found | ||
| 217 | mov cx,SIG_LENGTH ; length to compare | ||
| 218 | cld ; strings foward | ||
| 219 | repe cmpsb ; q: is the MEMM signature out there? | ||
| 220 | jne not_inst ; n: return zero | ||
| 221 | inc ax ; y: return one | ||
| 222 | mov [entry_seg],es ; save segment for far call | ||
| 223 | xor di,di | ||
| 224 | mov cx,es:[ELIM_Entry_off] ; save offset for far call | ||
| 225 | mov [entry_off],cx | ||
| 226 | not_inst: | ||
| 227 | pop cx | ||
| 228 | pop es | ||
| 229 | pop ds | ||
| 230 | pop si | ||
| 231 | pop di | ||
| 232 | ret | ||
| 233 | Inst_chk endp | ||
| 234 | |||
| 235 | |||
| 236 | db 100h dup (0) | ||
| 237 | Stack_Top: | ||
| 238 | db 0 | ||
| 239 | |||
| 240 | _TEXT ends | ||
| 241 | |||
| 242 | end EMM386 | ||
| 243 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/MEMMINC.ASM b/v4.0/src/MEMM/MEMM/MEMMINC.ASM new file mode 100644 index 0000000..1eb897f --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMMINC.ASM | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MEMMINC.ASM - lists all MEMM include files | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM - MICROSOFT Expanded Memory Manager | ||
| 11 | ; | ||
| 12 | ; Module: MEMMINC.ASM - lists all MEMM include files | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: June 14, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 06/25/86 original | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; Functional Description: | ||
| 31 | ; This module includes all MEMM include files and will | ||
| 32 | ; provide a listing of all when assembled to produce a listing file. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | .lfcond | ||
| 36 | .386p | ||
| 37 | |||
| 38 | ;****************************************************************************** | ||
| 39 | ; I N C L U D E S | ||
| 40 | ;****************************************************************************** | ||
| 41 | INC_LIST EQU 1 ; list include files | ||
| 42 | |||
| 43 | page | ||
| 44 | include ASCII_SM.EQU | ||
| 45 | page | ||
| 46 | include DRIVER.EQU | ||
| 47 | page | ||
| 48 | include PIC_DEF.EQU | ||
| 49 | page | ||
| 50 | include ROMSTRUC.EQU | ||
| 51 | page | ||
| 52 | include ROMXBIOS.EQU | ||
| 53 | |||
| 54 | page | ||
| 55 | include DESC.INC | ||
| 56 | page | ||
| 57 | include ELIM.INC | ||
| 58 | page | ||
| 59 | include EMM386.INC | ||
| 60 | page | ||
| 61 | include INSTR386.INC | ||
| 62 | page | ||
| 63 | include KBD.INC | ||
| 64 | page | ||
| 65 | include LOADALL.INC | ||
| 66 | page | ||
| 67 | include OEMDEP.INC | ||
| 68 | page | ||
| 69 | include PAGE.INC | ||
| 70 | page | ||
| 71 | include VDMSEG.INC | ||
| 72 | page | ||
| 73 | include VDMSEL.INC | ||
| 74 | page | ||
| 75 | include VM386.INC | ||
| 76 | |||
| 77 | page | ||
| 78 | include DRIVER.STR | ||
| 79 | |||
| 80 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/MEMMONF.ASM b/v4.0/src/MEMM/MEMM/MEMMONF.ASM new file mode 100644 index 0000000..5eee389 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMMONF.ASM | |||
| @@ -0,0 +1,337 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MEMMONF - (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 11 | ; | ||
| 12 | ; Module: MEMMONF - parse for on/off/auto and perform the function | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: June 4, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/04/86 Original | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; | ||
| 31 | ; Functional Description: | ||
| 32 | ; MEMMONF is used by MEMM.EXE UTILITY code and MEMM.COM to parse | ||
| 33 | ; the command line for ON, OFF, or AUTO and perform the function | ||
| 34 | ; via a call to ELIM_Entry. It also displays the appropriate message | ||
| 35 | ; depending on the results of the parsing and call to ELIM_Entry. | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | .lfcond ; list false conditionals | ||
| 39 | .386p | ||
| 40 | page | ||
| 41 | ;****************************************************************************** | ||
| 42 | ; P U B L I C D E C L A R A T I O N S | ||
| 43 | ;****************************************************************************** | ||
| 44 | ; | ||
| 45 | public onf_func | ||
| 46 | public get_token | ||
| 47 | ; | ||
| 48 | ;****************************************************************************** | ||
| 49 | ; E X T E R N A L R E F E R E N C E S | ||
| 50 | ;****************************************************************************** | ||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | _TEXT segment byte use16 public 'CODE' | ||
| 55 | extrn Inst_chk:near | ||
| 56 | extrn ELIM_link:near | ||
| 57 | _TEXT ends | ||
| 58 | ; | ||
| 59 | page | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; L O C A L C O N S T A N T S | ||
| 62 | ;****************************************************************************** | ||
| 63 | ; | ||
| 64 | MSDOS equ 21h ; MS-DOS function call | ||
| 65 | |||
| 66 | include ascii_sm.equ | ||
| 67 | |||
| 68 | ;****************************************************************************** | ||
| 69 | ; S E G M E N T D E F I N I T I O N | ||
| 70 | ;****************************************************************************** | ||
| 71 | ; | ||
| 72 | _TEXT segment byte use16 public 'CODE' | ||
| 73 | assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT | ||
| 74 | ; | ||
| 75 | ;****************************************************************************** | ||
| 76 | ; L O C A L D A T A A R E A | ||
| 77 | ;****************************************************************************** | ||
| 78 | ; | ||
| 79 | include memm_msg.inc | ||
| 80 | ; | ||
| 81 | msg_tbl label word ; table of final messages to display | ||
| 82 | dw offset vmode ; on | ||
| 83 | dw offset rmode ; off | ||
| 84 | dw offset amode ; auto | ||
| 85 | dw 0 ; no parameter will use above msgs | ||
| 86 | dw offset parmerr ; invalid parameter | ||
| 87 | dw offset verr_msg ; error entering vmode | ||
| 88 | dw offset rerr ; error entering rmode | ||
| 89 | dw offset aerr ; error entering amode | ||
| 90 | ; | ||
| 91 | ; the valid arguments | ||
| 92 | ; | ||
| 93 | on_arg db "on" | ||
| 94 | on_len equ (this byte - on_arg) | ||
| 95 | |||
| 96 | off_arg db "off" | ||
| 97 | off_len equ (this byte - off_arg) | ||
| 98 | |||
| 99 | auto_arg db "auto" | ||
| 100 | auto_len equ (this byte - auto_arg) | ||
| 101 | |||
| 102 | null_arg db " " | ||
| 103 | null_len equ 1 | ||
| 104 | max_arg_len equ 11 | ||
| 105 | arg_str db max_arg_len dup(0) ; storage for get_token | ||
| 106 | ; | ||
| 107 | arg_tbl label word ; table of valid arguments | ||
| 108 | dw offset on_arg | ||
| 109 | dw offset off_arg | ||
| 110 | dw offset auto_arg | ||
| 111 | ; | ||
| 112 | no_arg equ (this byte - arg_tbl) | ||
| 113 | dw offset null_arg ; should be last entry | ||
| 114 | max_args equ (this byte - arg_tbl) | ||
| 115 | ; | ||
| 116 | arg_len label word ; table of argument lengths | ||
| 117 | dw on_len | ||
| 118 | dw off_len | ||
| 119 | dw auto_len | ||
| 120 | ; | ||
| 121 | dw null_len | ||
| 122 | |||
| 123 | page | ||
| 124 | ;****************************************************************************** | ||
| 125 | ; onf_func - Check command line for ON OFF or AUTO and perform function | ||
| 126 | ; | ||
| 127 | ; ENTRY: es:di points to command line terminated by CR or LF | ||
| 128 | ; | ||
| 129 | ; EXIT: The appropriate message is displayed | ||
| 130 | ; | ||
| 131 | ; USED: none | ||
| 132 | ; | ||
| 133 | ;****************************************************************************** | ||
| 134 | onf_func proc near | ||
| 135 | |||
| 136 | push ax | ||
| 137 | push dx | ||
| 138 | push di | ||
| 139 | |||
| 140 | cld | ||
| 141 | ; | ||
| 142 | ; check for driver installed | ||
| 143 | ; | ||
| 144 | call Inst_chk ; ax = 0/1 => isn't/is installed | ||
| 145 | or ax,ax ; q: is it installed? | ||
| 146 | jnz drvr_installed | ||
| 147 | mov dx,offset not_there ; Not installed message | ||
| 148 | jmp term ; display message and quit | ||
| 149 | ; | ||
| 150 | drvr_installed: | ||
| 151 | ; | ||
| 152 | call parse_onf ; look for ON/OFF | ||
| 153 | jc msg_disp ; invalid parameter | ||
| 154 | cmp ax,no_arg/2 ; q: no argument? | ||
| 155 | je get_status ; y: get status | ||
| 156 | push ax ; save on/off indicator | ||
| 157 | mov ah,1 ; ah=1 for set status routine | ||
| 158 | call ELIM_link ; go turn it on or off | ||
| 159 | pop ax ; restore on/off indicator | ||
| 160 | jnc get_status ; no error in status routine | ||
| 161 | add ax,max_args/2+1 ; indicate error | ||
| 162 | jmp msg_disp | ||
| 163 | ; | ||
| 164 | get_status: | ||
| 165 | xor ah,ah ; get status | ||
| 166 | call ELIM_link ; status in ah | ||
| 167 | mov al,ah | ||
| 168 | xor ah,ah ; status in ax | ||
| 169 | cmp ax,2 ; q: auto mode? | ||
| 170 | jb msg_disp ; n: display mode | ||
| 171 | push ax ; save it | ||
| 172 | mov dx,offset amode | ||
| 173 | mov ah,9 | ||
| 174 | int MSDOS ; print auto mode | ||
| 175 | pop ax ; restore mode | ||
| 176 | sub ax,2 ; get on or off indicator | ||
| 177 | ; | ||
| 178 | msg_disp: | ||
| 179 | shl ax,1 ; make it a word index | ||
| 180 | mov di,ax ; offset into message table | ||
| 181 | mov dx,msg_tbl[di] ; get appropriate message | ||
| 182 | term: | ||
| 183 | mov ah,9 | ||
| 184 | int MSDOS ; display error message | ||
| 185 | ; | ||
| 186 | pop di | ||
| 187 | pop dx | ||
| 188 | pop ax | ||
| 189 | |||
| 190 | ret | ||
| 191 | onf_func endp | ||
| 192 | |||
| 193 | page | ||
| 194 | ;****************************************************************************** | ||
| 195 | ; get_token - Retrieve a non-white-space string from a source string | ||
| 196 | ; | ||
| 197 | ; ENTRY: es:di points to command line terminated by CR or LF | ||
| 198 | ; ds:si points to storage for token | ||
| 199 | ; cx = maximum length to store | ||
| 200 | ; | ||
| 201 | ; EXIT: cx = length of token (0 => end of source string) | ||
| 202 | ; es:di points to first char after new token in source string | ||
| 203 | ; string of length cx stored in ds:si (and converted to lower case) | ||
| 204 | ; | ||
| 205 | ; USED: see above | ||
| 206 | ; | ||
| 207 | ;****************************************************************************** | ||
| 208 | get_token proc near | ||
| 209 | push si ; save storage area | ||
| 210 | push bx | ||
| 211 | push ax | ||
| 212 | ; | ||
| 213 | mov bx,cx ; number to store | ||
| 214 | xor cx,cx ; no chars found so far | ||
| 215 | ; | ||
| 216 | ; go to first non-blank character | ||
| 217 | ; | ||
| 218 | gloop1: | ||
| 219 | mov al,es:[di] ; get a character | ||
| 220 | inc di ; point to next | ||
| 221 | cmp al,' ' ; Q: space ? | ||
| 222 | je gloop1 ; y: skip it | ||
| 223 | cmp al,TAB ; Q: TAB ? | ||
| 224 | je gloop1 ; y: skip it | ||
| 225 | dec di ; N: start parsing and reset di | ||
| 226 | gloop2: | ||
| 227 | mov al,es:[di] ; get next char | ||
| 228 | cmp al,CR ; q: carriage return? | ||
| 229 | je token_xit ; y: quit | ||
| 230 | cmp al,LF ; q: line feed? | ||
| 231 | je token_xit ; y: quit | ||
| 232 | cmp al,' ' ; Q: space ? | ||
| 233 | je token_xit ; y: quit | ||
| 234 | cmp al,TAB ; Q: TAB ? | ||
| 235 | je token_xit ; y: quit | ||
| 236 | inc di ; n: point to next | ||
| 237 | inc cx ; increment number of chars found | ||
| 238 | cmp cx,bx ; q: have we stored our limit yet? | ||
| 239 | ja gloop2 ; y: don't store any more | ||
| 240 | or al,20h ; make it lower case | ||
| 241 | mov ds:[si],al ; store it | ||
| 242 | inc si ; and point to next | ||
| 243 | jmp short gloop2 ; continue | ||
| 244 | token_xit: | ||
| 245 | ; | ||
| 246 | pop ax | ||
| 247 | pop bx | ||
| 248 | pop si | ||
| 249 | ret | ||
| 250 | get_token endp | ||
| 251 | |||
| 252 | page | ||
| 253 | ;****************************************************************************** | ||
| 254 | ; parse_onf - Parse command line for ON or OFF | ||
| 255 | ; | ||
| 256 | ; ENTRY: es:di points to command line terminated by CR or LF | ||
| 257 | ; | ||
| 258 | ; EXIT: ax = 0 => ON | ||
| 259 | ; ax = 1 => OFF | ||
| 260 | ; ax = 2 => AUTO | ||
| 261 | ; ax = 3 => no argument encountered | ||
| 262 | ; ax = 4 => Error in command line | ||
| 263 | ; CARRY = cleared if no errors | ||
| 264 | ; set if error (ax will also = 4) | ||
| 265 | ; es:di points to end of parsed string | ||
| 266 | ; | ||
| 267 | ; USED: see above | ||
| 268 | ; | ||
| 269 | ;****************************************************************************** | ||
| 270 | parse_onf proc near | ||
| 271 | ; | ||
| 272 | push si | ||
| 273 | push ds | ||
| 274 | push bx | ||
| 275 | push es | ||
| 276 | ; | ||
| 277 | mov bx,no_arg ; initialize to no parameters encountered | ||
| 278 | cld ; go foward | ||
| 279 | ; | ||
| 280 | ; es:di = 1st char | ||
| 281 | ; | ||
| 282 | mov si,offset arg_str ; ds:si = storage for argument | ||
| 283 | push cs | ||
| 284 | pop ds ; arg storage in _CODE | ||
| 285 | mov cx,max_arg_len ; maximum argument length | ||
| 286 | call get_token ; get an argument | ||
| 287 | or cx,cx ; q: any parms? | ||
| 288 | jz parse_xit ; n: quit | ||
| 289 | push di ; y: save di for later | ||
| 290 | push ds ; es:di = parameter table | ||
| 291 | pop es | ||
| 292 | |||
| 293 | xor bx,bx ; index into parameter table | ||
| 294 | ploop2: | ||
| 295 | cmp cx,arg_len[bx] ; q: lengths equal? | ||
| 296 | jne not_found ; n: keep looking | ||
| 297 | mov di,arg_tbl[bx] ; get destination address | ||
| 298 | push si ; save source string addr | ||
| 299 | repe cmpsb ; q: is this a valid argument? | ||
| 300 | pop si ; restore source string address (command line) | ||
| 301 | je found ; y: matched one | ||
| 302 | not_found: | ||
| 303 | inc bx | ||
| 304 | inc bx ; update table pointer | ||
| 305 | cmp bx,max_args ; q: have we done them all yet? | ||
| 306 | jne ploop2 ; n: keep looking | ||
| 307 | parse_inv: | ||
| 308 | mov bx,max_args ; y: invalid | ||
| 309 | pop di ; restore di | ||
| 310 | jmp short parse_xit ; leave | ||
| 311 | found: | ||
| 312 | pop di ; restore original string addr | ||
| 313 | pop es | ||
| 314 | mov cx,1 ; just need to check for one non blank | ||
| 315 | call get_token ; get another token | ||
| 316 | or cx,cx ; q: was there another one? | ||
| 317 | jz parse_xit2 ; n: good | ||
| 318 | mov bx,max_args ; y: invalid | ||
| 319 | jmp short parse_xit2 | ||
| 320 | parse_xit: | ||
| 321 | pop es | ||
| 322 | parse_xit2: | ||
| 323 | shr bx,1 ; get result of parse | ||
| 324 | mov ax,bx ; put in ax | ||
| 325 | mov bx,max_args/2-1 | ||
| 326 | cmp bx,ax ; set/clear carry on invalid/valid return | ||
| 327 | ; | ||
| 328 | pop bx | ||
| 329 | pop ds | ||
| 330 | pop si | ||
| 331 | ; | ||
| 332 | ret | ||
| 333 | parse_onf endp | ||
| 334 | |||
| 335 | _TEXT ends | ||
| 336 | |||
| 337 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/MEMM_MSG.INC b/v4.0/src/MEMM/MEMM/MEMM_MSG.INC new file mode 100644 index 0000000..da17c94 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMM_MSG.INC | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - 386 EMM device driver | ||
| 8 | ; | ||
| 9 | ; Module: CEM_MSG.INC - messages for ON/OFF/AUTO utility | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 7,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change Log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION Description | ||
| 22 | ; -------- -------- -------------------------------------------- | ||
| 23 | ; 06/07/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ; | ||
| 28 | not_there db "EMM386 driver not installed.",CR,LF,BEL,"$" | ||
| 29 | |||
| 30 | vmode db "EMM386 Active.",CR,LF,"$" | ||
| 31 | |||
| 32 | rmode db "EMM386 Inactive.",CR,LF,"$" | ||
| 33 | |||
| 34 | amode db "EMM386 in Auto mode.",CR,LF,"$" | ||
| 35 | |||
| 36 | verr_msg db "Unable to activate EMM386.",CR,LF,BEL,"$" | ||
| 37 | |||
| 38 | rerr db "Unable to inactivate EMM386.",CR,LF,BEL,"$" | ||
| 39 | |||
| 40 | aerr db "Unable to place EMM386 in Auto mode.",CR,LF,BEL,"$" | ||
| 41 | |||
| 42 | parmerr db "Usage: EMM386 [ ON | OFF | AUTO]" | ||
| 43 | db CR,LF,BEL,"$" | ||
diff --git a/v4.0/src/MEMM/MEMM/MOVEB.ASM b/v4.0/src/MEMM/MEMM/MOVEB.ASM new file mode 100644 index 0000000..00b9a07 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MOVEB.ASM | |||
| @@ -0,0 +1,533 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MOVEB - move block emulator | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: MOVEB - move block code for MEMM | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: 05/22/86 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;************************************************************************* | ||
| 21 | ; CHANGE LOG: | ||
| 22 | ; DATE VERSION Description | ||
| 23 | ;--------- -------- -------------------------------------------------- | ||
| 24 | ; 05/15/86 Check source/target selector using verr,verw | ||
| 25 | ; and add parity handler | ||
| 26 | ; 06/09/86 Added MapLinear call | ||
| 27 | ; 06/17/86 Added code to detect and "handle" writes to | ||
| 28 | ; diag byte location. | ||
| 29 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 30 | ; 07/06/86 0.04 DiagByte moved to _DATA | ||
| 31 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 32 | ; 07/10/86 0.05 Added Real Mode patch code | ||
| 33 | ;************************************************************************* | ||
| 34 | .386p | ||
| 35 | |||
| 36 | |||
| 37 | ;**************************************** | ||
| 38 | ; P U B L I C S | ||
| 39 | ;**************************************** | ||
| 40 | public Move_Block | ||
| 41 | public MB_Exit | ||
| 42 | public MB_Stat | ||
| 43 | public i15_Entry | ||
| 44 | public MB_Flag | ||
| 45 | public i15_Old | ||
| 46 | |||
| 47 | page | ||
| 48 | ;**************************************** | ||
| 49 | ; D E F I N E S | ||
| 50 | ;**************************************** | ||
| 51 | include vdmseg.inc | ||
| 52 | include vdmsel.inc | ||
| 53 | include desc.inc | ||
| 54 | include instr386.inc | ||
| 55 | include oemdep.inc | ||
| 56 | include vm386.inc | ||
| 57 | |||
| 58 | TRUE equ 0FFh | ||
| 59 | FALSE equ 00h | ||
| 60 | |||
| 61 | D_G_BIT equ 80h ; granularity bit in high status bits | ||
| 62 | |||
| 63 | FLAGS_CY equ 0001h | ||
| 64 | FLAGS_ZF equ 0040h | ||
| 65 | FLAGS_IF equ 0200h | ||
| 66 | |||
| 67 | ; 386 data descriptor format | ||
| 68 | DATA_DESC_386 struc | ||
| 69 | DD386_Limit_lo dw ? ; low word of seg limit | ||
| 70 | DD386_Base_lo dw ? ; low 24 bits of seg base addr | ||
| 71 | db ? ; | ||
| 72 | DD386_Access db ? ; access byte | ||
| 73 | DD386_L_Stat db ? ; high 4 bits of seg limit | ||
| 74 | ; and futher status | ||
| 75 | DD386_Base_hi db ? ; high 8 bits of seg base addr | ||
| 76 | DATA_DESC_386 ends | ||
| 77 | |||
| 78 | ; format of move block descriptor table passed on entry | ||
| 79 | MB_GDT struc | ||
| 80 | MG_dummy dd 2 dup (?) ; dummy descriptor entry | ||
| 81 | MG_GDT dd 2 dup (?) ; GDT entry | ||
| 82 | MG_Source dd 2 dup (?) ; source segment entry | ||
| 83 | MG_Target dd 2 dup (?) ; target segment entry | ||
| 84 | MB_GDT ends | ||
| 85 | |||
| 86 | ;************************************************************ | ||
| 87 | ; DescrMap - map address in descriptor | ||
| 88 | ; ENTRY: ES:DI = descriptor | ||
| 89 | ; EXIT: descriptor's address is mapped by MapLinear | ||
| 90 | ; USED: EAX | ||
| 91 | ;************************************************************ | ||
| 92 | DescrMap MACRO | ||
| 93 | mov ah,ES:[di.DD386_Base_hi] ; ah = high 8 bits of address | ||
| 94 | mov al,byte ptr ES:[di.DD386_Base_lo+2] ; al = bits 16-23 of addr | ||
| 95 | OP32 | ||
| 96 | shl ax,16 ; high addr word into high EAX | ||
| 97 | mov ax,ES:[di.DD386_Base_lo] ; EAX = 32 bit address | ||
| 98 | call MapLinear ; map linear address | ||
| 99 | mov ES:[di.DD386_Base_lo],ax ; store low word of address | ||
| 100 | OP32 | ||
| 101 | shr ax,16 ; ax = high word of address | ||
| 102 | mov byte ptr ES:[di.DD386_Base_lo+2],al ; store | ||
| 103 | mov ES:[di.DD386_Base_hi],ah ; high word of address | ||
| 104 | ENDM | ||
| 105 | |||
| 106 | ;******************************************************************************* | ||
| 107 | ; E X T E R N A L R E F E R E N C E S | ||
| 108 | ;******************************************************************************* | ||
| 109 | _TEXT segment | ||
| 110 | |||
| 111 | extrn MapLinear:near | ||
| 112 | extrn Set_Par_Vect:near | ||
| 113 | extrn Rest_Par_Vect:near | ||
| 114 | extrn togl_A20:near | ||
| 115 | extrn get_a20_state:near | ||
| 116 | |||
| 117 | _TEXT ends | ||
| 118 | |||
| 119 | _DATA segment | ||
| 120 | |||
| 121 | extrn Active_Status:byte ; non-zero if in VM | ||
| 122 | |||
| 123 | _DATA ends | ||
| 124 | |||
| 125 | |||
| 126 | page | ||
| 127 | ;******************************************************************************* | ||
| 128 | ; D A T A S E G M E N T | ||
| 129 | ;******************************************************************************* | ||
| 130 | _DATA segment | ||
| 131 | |||
| 132 | MB_Stat db 0 ; move block status | ||
| 133 | Toggle_st db 0 | ||
| 134 | |||
| 135 | _DATA ends | ||
| 136 | |||
| 137 | page | ||
| 138 | ;**************************************** | ||
| 139 | ; C O D E S E G M E N T _TEXT | ||
| 140 | ;**************************************** | ||
| 141 | _TEXT segment | ||
| 142 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 143 | |||
| 144 | page | ||
| 145 | ;************************************************************************* | ||
| 146 | ;*** Move_Block - Mimics the 286 ROM function Move Block ( int15h AH=87h ). | ||
| 147 | ; Move a block of data (copy it) to/from anywhere in | ||
| 148 | ; 24bits of linear address space. Normally used to move | ||
| 149 | ; data to/from extended memory (past 1M) since real mode | ||
| 150 | ; can only address the first meg of memory. | ||
| 151 | ; | ||
| 152 | ; | ||
| 153 | ; ENTRY PROTECTED MODE | ||
| 154 | ; AH = 87h | ||
| 155 | ; CX = # of words to move ( max 8000h ). | ||
| 156 | ; ES:SI = ptr to a descriptor table containing segment descriptors | ||
| 157 | ; for the source and target memory of the transfer. | ||
| 158 | ; | ||
| 159 | ; EXIT PROTECTED MODE | ||
| 160 | ; AH = 00 if OK | ||
| 161 | ; 01 if parity error *** currently not checked *** | ||
| 162 | ; 02 if exception error | ||
| 163 | ; 03 if gate address bit A20 fails. | ||
| 164 | ; if no error: | ||
| 165 | ; ZF and NC in client's flags | ||
| 166 | ; if error: | ||
| 167 | ; NZ and CY in client's flags | ||
| 168 | ; | ||
| 169 | ; | ||
| 170 | ; USES AX, FLAGS -> CLD. | ||
| 171 | ; | ||
| 172 | ; Descriptor Table Format | ||
| 173 | ; ES:SI ---> +-------------------------------+ | ||
| 174 | ; | Dummy descriptor | | ||
| 175 | ; +-------------------------------+ | ||
| 176 | ; | GDT descriptor | | ||
| 177 | ; +-------------------------------+ | ||
| 178 | ; | Source segment descriptor | | ||
| 179 | ; +-------------------------------+ | ||
| 180 | ; | Target segment descriptor | | ||
| 181 | ; +-------------------------------+ | ||
| 182 | ; | ||
| 183 | ;************************************************************************* | ||
| 184 | Move_Block proc near | ||
| 185 | ; | ||
| 186 | push ds | ||
| 187 | push es | ||
| 188 | PUSH_EAX | ||
| 189 | push cx | ||
| 190 | push si | ||
| 191 | push di | ||
| 192 | ; | ||
| 193 | cld | ||
| 194 | ; | ||
| 195 | mov ax,VDMD_GSEL ; get data selector | ||
| 196 | mov ds,ax ; DS = DGROUP | ||
| 197 | mov [MB_Stat],0 ; init status of move block to OK. | ||
| 198 | ; | ||
| 199 | ; check word count field | ||
| 200 | ; | ||
| 201 | cmp cx,8000h ;Q: word count too high | ||
| 202 | jbe MB_chk_length ; N: check length of segments | ||
| 203 | jmp MB_Excp_Error ; Y: report exception error | ||
| 204 | |||
| 205 | ; | ||
| 206 | ; check source and target descriptor's lengths against transfer count | ||
| 207 | ; only need check low word since caller set up a 286 descriptor | ||
| 208 | ; | ||
| 209 | MB_chk_length: | ||
| 210 | mov ax,cx | ||
| 211 | shl ax,1 ; AX = # of bytes to transfer(0=>8000h) | ||
| 212 | dec ax ; convert to seg limit type value | ||
| 213 | ; ( 0FFFFh => 64K ) | ||
| 214 | cmp ax,ES:[si.MG_Source.DD386_Limit_lo] ;Q: source seg limit low ? | ||
| 215 | jbe MB_chk_tarl ; N: chk target length | ||
| 216 | jmp MB_Excp_Error ; Y: return excp error. | ||
| 217 | |||
| 218 | MB_chk_tarl: | ||
| 219 | cmp ax,ES:[si.MG_Target.DD386_Limit_lo] ;Q: tar seg too small ? | ||
| 220 | jbe MB_setup ; N: seg limits OK. | ||
| 221 | jmp MB_Excp_Error ; Y: return excp error | ||
| 222 | ; | ||
| 223 | ; source and target descriptors OK, set up scratch selector descriptors | ||
| 224 | ; | ||
| 225 | |||
| 226 | MB_setup: | ||
| 227 | push cx ; save copy count | ||
| 228 | |||
| 229 | push es | ||
| 230 | pop ds ; set DS:SI to input descriptor table | ||
| 231 | mov ax,GDTD_GSEL | ||
| 232 | mov es,ax ; ES:0 pts to GDT | ||
| 233 | mov di,MBSRC_GSEL ; ES:DI pts to source work descriptor in GDT | ||
| 234 | push si ; save input descr table ptr | ||
| 235 | lea si,[si.MG_Source]; DS:SI pts to input source descr | ||
| 236 | mov cx,4 | ||
| 237 | rep movsw ; set move block source work descr | ||
| 238 | pop si ; restore input descr table ptr | ||
| 239 | mov di,MBSRC_GSEL ; ES:DI pts to source work descriptor in GDT | ||
| 240 | call MB_Map_Src | ||
| 241 | DescrMap ; fixup this descriptor's linear address | ||
| 242 | |||
| 243 | mov di,MBTAR_GSEL ; ES:DI pts to target work descr in GDT | ||
| 244 | push si ; save input descr table ptr | ||
| 245 | lea si,[si.MG_Target] ; DS:SI pts to input target descr | ||
| 246 | mov cx,4 | ||
| 247 | rep movsw ; set move blk target work descr | ||
| 248 | pop si ; restore input descr table ptr | ||
| 249 | mov di,MBTAR_GSEL ; ES:DI pts to target work descr in GDT | ||
| 250 | call MB_Map_Dest | ||
| 251 | DescrMap ; fixup this descriptor's linear address | ||
| 252 | |||
| 253 | ; | ||
| 254 | ; install NMI/parity exception handler | ||
| 255 | ; | ||
| 256 | call Set_Par_Vect ; restore the parity interrupt handler | ||
| 257 | |||
| 258 | ; | ||
| 259 | ; copy the data | ||
| 260 | ; | ||
| 261 | |||
| 262 | ; | ||
| 263 | ; check if a20 line is to be enabled or not | ||
| 264 | ; | ||
| 265 | call get_a20_state | ||
| 266 | jnz a20_is_enb | ||
| 267 | ; | ||
| 268 | ; a20 line is currently disabled. we need to enable the a20 | ||
| 269 | ; | ||
| 270 | call togl_a20 | ||
| 271 | mov [toggle_st],0ffh | ||
| 272 | a20_is_enb: | ||
| 273 | ; | ||
| 274 | pop cx ; restore copy count | ||
| 275 | |||
| 276 | xor di,di | ||
| 277 | xor si,si | ||
| 278 | mov ax,MBSRC_GSEL | ||
| 279 | verr ax ;Q: source selector valid ? | ||
| 280 | jnz MB_Excp_Error ; N: return exception error | ||
| 281 | mov ds,ax ; Y: DS:SI pts to source segment | ||
| 282 | mov ax,MBTAR_GSEL | ||
| 283 | verw ax ;Q: target selector valid ? | ||
| 284 | jnz MB_Excp_Error ; N: return exception error | ||
| 285 | mov es,ax ; Y: ES:DI pts to target segment | ||
| 286 | jmp MB_move_block ; and go ahead | ||
| 287 | ; | ||
| 288 | ; Error reporting | ||
| 289 | ; | ||
| 290 | MB_Excp_Error: | ||
| 291 | mov ax,VDMD_GSEL ; get data selector | ||
| 292 | mov ds,ax ; DS = DGROUP | ||
| 293 | mov [MB_Stat],2 | ||
| 294 | jmp MB_Exit | ||
| 295 | ; | ||
| 296 | ; move the block | ||
| 297 | ; | ||
| 298 | MB_move_block: | ||
| 299 | |||
| 300 | call MB_Start | ||
| 301 | |||
| 302 | ; | ||
| 303 | ; MOVE the BLOCK - dwords | ||
| 304 | ; | ||
| 305 | test cx,01h ;Q: move an odd # of words? | ||
| 306 | jz MB_moved ; N: move dwords | ||
| 307 | movsw ; Y: move the first one => dwords now | ||
| 308 | MB_moved: | ||
| 309 | shr cx,1 ; move CX dwords... | ||
| 310 | OP32 | ||
| 311 | rep movsw ; REP MOVSD | ||
| 312 | |||
| 313 | mov ax,VDMD_GSEL ; get data selector | ||
| 314 | mov ds,ax ; DS = DGROUP | ||
| 315 | |||
| 316 | ; restore a20 state to what it was before this routine | ||
| 317 | ; | ||
| 318 | test [toggle_st],0ffh ; do we need to toggle the a20 back? | ||
| 319 | jz a20_restored ; N: skip toggling | ||
| 320 | call togl_a20 ; Y: else toggle the A20 line | ||
| 321 | a20_restored: | ||
| 322 | mov [toggle_st],0 ; clear this flag | ||
| 323 | |||
| 324 | jmp MB_Exit | ||
| 325 | Move_Block endp | ||
| 326 | |||
| 327 | ;************************************************************************* | ||
| 328 | ; This is special JUMP entry point for parity handler | ||
| 329 | ; | ||
| 330 | MB_Exit proc near | ||
| 331 | ; | ||
| 332 | ; reset NMI handler | ||
| 333 | ; | ||
| 334 | |||
| 335 | call Rest_Par_Vect ; restore the parity interrupt handler | ||
| 336 | |||
| 337 | ; | ||
| 338 | ; | ||
| 339 | MB_leave: | ||
| 340 | pop di | ||
| 341 | pop si | ||
| 342 | pop cx | ||
| 343 | POP_EAX | ||
| 344 | mov ah,[MB_Stat] | ||
| 345 | ; | ||
| 346 | ; set client's flags to no error | ||
| 347 | ; | ||
| 348 | or [bp.VTFOE+VMTF_EFLAGS],FLAGS_ZF ; ZF | ||
| 349 | and [bp.VTFOE+VMTF_EFLAGS],NOT FLAGS_CY ; NC | ||
| 350 | |||
| 351 | or ah,ah ;Q: error occured ? | ||
| 352 | jz MB_ret ; N: continue | ||
| 353 | ; Y: set error in client's flags | ||
| 354 | and [bp.VTFOE+VMTF_EFLAGS],NOT FLAGS_ZF ; NZ | ||
| 355 | or [bp.VTFOE+VMTF_EFLAGS],FLAGS_CY ; CY | ||
| 356 | ; | ||
| 357 | MB_ret: | ||
| 358 | pop es | ||
| 359 | pop ds | ||
| 360 | ret | ||
| 361 | ; | ||
| 362 | MB_Exit endp | ||
| 363 | |||
| 364 | _TEXT ends | ||
| 365 | |||
| 366 | page | ||
| 367 | ;**************************************** | ||
| 368 | ; C O D E S E G M E N T R_CODE | ||
| 369 | ;**************************************** | ||
| 370 | R_CODE segment | ||
| 371 | assume cs:R_CODE, ds:DGROUP, es:DGROUP | ||
| 372 | |||
| 373 | ;************************************************************************* | ||
| 374 | ; local data | ||
| 375 | ;************************************************************************* | ||
| 376 | I15_Old dd 0 ; old Int 15h handler | ||
| 377 | MB_Flag db 0 ; non-zero => do move block in ring 0 | ||
| 378 | Exit_Flags dw 0 ; flags for int15 exit | ||
| 379 | ; | ||
| 380 | ext_mem_size dw 0 ; we are using new int 15 allocation | ||
| 381 | ; scheme now whereby we have to lower | ||
| 382 | ; the size reported by int 15 function | ||
| 383 | ; 88h to grab some memory for ourself | ||
| 384 | ; The extended memory allocate routine | ||
| 385 | ; in allocmem.asm fills in the approp. | ||
| 386 | ; size here. | ||
| 387 | |||
| 388 | page | ||
| 389 | ;************************************************************************* | ||
| 390 | ; i15_Entry - real/virtual mode patch code for int 15h | ||
| 391 | ; | ||
| 392 | ; This function patches the real mode IDT for MEMM. If it is | ||
| 393 | ; entered for a move block, this code sets a flag to tell MEMM to | ||
| 394 | ; pick up the move block, then i15_Entry lets MEMM do it. Otherwise | ||
| 395 | ; MEMM jumps to the previous code. For function 88h it reports the | ||
| 396 | ; the new size of extended memory. | ||
| 397 | ; | ||
| 398 | ; ENTRY Real/Virtual mode | ||
| 399 | ; see int15h entry parameters in ROM spec | ||
| 400 | ; | ||
| 401 | ; EXIT | ||
| 402 | ; | ||
| 403 | ; 87h: Real/Virtual mode | ||
| 404 | ; AH = 00 if OK | ||
| 405 | ; 01 if parity error *** currently not checked *** | ||
| 406 | ; 02 if exception error | ||
| 407 | ; 03 if gate address bit A20 fails. | ||
| 408 | ; if no error: | ||
| 409 | ; ZF and NC in client's flags | ||
| 410 | ; if error: | ||
| 411 | ; NZ and CY in client's flags | ||
| 412 | ; | ||
| 413 | ; 88h: Real/Virtual mode | ||
| 414 | ; AX = Size of extended memory in KB | ||
| 415 | ; | ||
| 416 | ; | ||
| 417 | ; USES AX, FLAGS -> CLD. | ||
| 418 | ; | ||
| 419 | ; NOTE:**ISP This routine was modified to implement the new INT15 allocation | ||
| 420 | ; scheme whereby MEMM by lowering the size of extended memory could | ||
| 421 | ; grab the difference between the old size and the new size reported | ||
| 422 | ; for itself. | ||
| 423 | ;************************************************************************* | ||
| 424 | i15_flags equ 6 | ||
| 425 | i15_cs equ 4 | ||
| 426 | i15_ip equ 2 | ||
| 427 | i15_bp equ 0 | ||
| 428 | |||
| 429 | i15_Entry proc near | ||
| 430 | ; | ||
| 431 | cli ; in case of pushf/call far | ||
| 432 | pushf ; save entry flags | ||
| 433 | ; | ||
| 434 | ; Check to see if it is the extended memory size request | ||
| 435 | ; | ||
| 436 | cmp ah,88h ;Q: extended memory size request? | ||
| 437 | jne chk_blk_move ; N: go to check for move block call | ||
| 438 | ; | ||
| 439 | ; Implement int15 allocation scheme by reporting a lowered value of extended | ||
| 440 | ; memory. | ||
| 441 | popf | ||
| 442 | mov ax,cs:[ext_mem_size] ; report new extended memory size | ||
| 443 | iret ; | ||
| 444 | ; | ||
| 445 | ; Checking for move block call | ||
| 446 | ; | ||
| 447 | chk_blk_move: | ||
| 448 | cmp ah,87h ;Q: move block call ? | ||
| 449 | jne i15_jmpf ; N: jmp to old code | ||
| 450 | push ds | ||
| 451 | push seg DGROUP ; | ||
| 452 | pop ds ; DS -> DOSGROUP | ||
| 453 | cmp [Active_Status],0 ; Y: Q: in Virtual mode ? | ||
| 454 | pop ds ; reset DS | ||
| 455 | je i15_jmpf ; N: jmp to old code | ||
| 456 | ; Y: VM move block | ||
| 457 | mov CS:[MB_Flag],TRUE ; let MEMM have it ... | ||
| 458 | popf ; retrieve entry flags (IF cleared!!!) | ||
| 459 | int 15h ; give it to MEMM | ||
| 460 | ; MEMM will reset MB_Flag | ||
| 461 | cli ; just in case | ||
| 462 | push bp ; save bp | ||
| 463 | mov bp,sp | ||
| 464 | push ax ; save ax | ||
| 465 | pushf | ||
| 466 | pop ax ; AX = exit flags | ||
| 467 | xchg ax,[bp+i15_Flags] ; AX = entry flag, exit flags on stack | ||
| 468 | and ax,FLAGS_IF ; save only IF bit of entry | ||
| 469 | or [bp+i15_Flags],ax ; set IF state in flags on stack | ||
| 470 | pop ax | ||
| 471 | pop bp | ||
| 472 | iret ; and leave | ||
| 473 | ; | ||
| 474 | ; far jump to old code | ||
| 475 | ; | ||
| 476 | i15_jmpf: | ||
| 477 | popf ; retrieve entry flags | ||
| 478 | jmp CS:[i15_Old] | ||
| 479 | ; | ||
| 480 | i15_Entry endp | ||
| 481 | |||
| 482 | R_CODE ends | ||
| 483 | |||
| 484 | |||
| 485 | LAST SEGMENT | ||
| 486 | ; | ||
| 487 | ASSUME CS:LAST | ||
| 488 | ; | ||
| 489 | public set_ext | ||
| 490 | ; | ||
| 491 | ;************************************************************************* | ||
| 492 | ; set_ext - to fill up size of extended memory reported by int 15 | ||
| 493 | ; | ||
| 494 | ; This function fills up the size of extended memory reported by the | ||
| 495 | ; int 15 real/virtual mode patch. | ||
| 496 | ; | ||
| 497 | ; ENTRY Real Mode | ||
| 498 | ; bx=size of extended memory in Kb | ||
| 499 | ; | ||
| 500 | ; EXIT None. R_CODE:ext_mem_size filled. | ||
| 501 | ; | ||
| 502 | ; USES None. | ||
| 503 | ; | ||
| 504 | ; WRITTEN 7/25/88 ISP | ||
| 505 | ; | ||
| 506 | ;************************************************************************* | ||
| 507 | |||
| 508 | set_ext proc near | ||
| 509 | ; | ||
| 510 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 511 | |||
| 512 | push ax | ||
| 513 | push ds | ||
| 514 | ; | ||
| 515 | mov ax,seg R_CODE | ||
| 516 | mov ds,ax | ||
| 517 | ; | ||
| 518 | ASSUME DS:R_CODE | ||
| 519 | ; | ||
| 520 | mov [ext_mem_size],bx | ||
| 521 | ; | ||
| 522 | pop ds | ||
| 523 | pop ax | ||
| 524 | ; | ||
| 525 | ASSUME DS:NOTHING | ||
| 526 | ; | ||
| 527 | ret | ||
| 528 | ; | ||
| 529 | set_ext endp | ||
| 530 | ; | ||
| 531 | |||
| 532 | LAST ENDS | ||
| 533 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/M_STATE.ASM b/v4.0/src/MEMM/MEMM/M_STATE.ASM new file mode 100644 index 0000000..9961558 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/M_STATE.ASM | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE M_STATE:MODULE to establish machine state at emm boot time | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: M_STATE | ||
| 13 | ; | ||
| 14 | ; Version: 0.01 | ||
| 15 | ; | ||
| 16 | ; Date: Aug 29,1988 | ||
| 17 | ; | ||
| 18 | ; Author: ISP (ISP) | ||
| 19 | ;****************************************************************************** | ||
| 20 | ; | ||
| 21 | ; Change Log: | ||
| 22 | ; | ||
| 23 | ; DATE REVISION Description | ||
| 24 | ; -------- -------- -------------------------------------------- | ||
| 25 | ;****************************************************************************** | ||
| 26 | ; Functional Description: | ||
| 27 | ; | ||
| 28 | ;****************************************************************************** | ||
| 29 | .lfcond | ||
| 30 | .386p | ||
| 31 | |||
| 32 | page | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; P U B L I C D E C L A R A T I O N S | ||
| 35 | ;****************************************************************************** | ||
| 36 | |||
| 37 | public estb_mach_state | ||
| 38 | |||
| 39 | page | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; L O C A L C O N S T A N T S | ||
| 42 | ;****************************************************************************** | ||
| 43 | ; | ||
| 44 | |||
| 45 | ;****************************************************************************** | ||
| 46 | ; INCLUDE FILES | ||
| 47 | ;****************************************************************************** | ||
| 48 | include vdmseg.inc ; segment definitions | ||
| 49 | |||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; E X T E R N A L R E F E R E N C E S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | ; | ||
| 56 | _DATA segment | ||
| 57 | _DATA ends | ||
| 58 | |||
| 59 | ; | ||
| 60 | LAST segment | ||
| 61 | ; | ||
| 62 | extrn estb_a20_state:near | ||
| 63 | ; | ||
| 64 | LAST ends | ||
| 65 | |||
| 66 | page | ||
| 67 | ;****************************************************************************** | ||
| 68 | ; S E G M E N T D E F I N I T I O N | ||
| 69 | ;****************************************************************************** | ||
| 70 | |||
| 71 | |||
| 72 | ;****************************************************************************** | ||
| 73 | ; | ||
| 74 | ; Code Segments | ||
| 75 | ; | ||
| 76 | ;****************************************************************************** | ||
| 77 | ; | ||
| 78 | _TEXT segment | ||
| 79 | _TEXT ends | ||
| 80 | |||
| 81 | LAST segment | ||
| 82 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 83 | |||
| 84 | page | ||
| 85 | ;-----------------------------------------------------------------------; | ||
| 86 | ; estb_mach_state ; | ||
| 87 | ; ; | ||
| 88 | ; establishes the state of the machine at memm boot. the only thing we ; | ||
| 89 | ; are concerned about right now is the a20 state which needs to be ; | ||
| 90 | ; preserved via emulation ; | ||
| 91 | ; ; | ||
| 92 | ; Arguments: ; | ||
| 93 | ; nothing ; | ||
| 94 | ; Returns: ; | ||
| 95 | ; nothing ; | ||
| 96 | ; Alters: ; | ||
| 97 | ; flags ; | ||
| 98 | ; Calls: ; | ||
| 99 | ; estb_a20_state ; | ||
| 100 | ; History: ; | ||
| 101 | ; ISP (isp). ; | ||
| 102 | ;-----------------------------------------------------------------------; | ||
| 103 | estb_mach_state proc near | ||
| 104 | ; | ||
| 105 | call estb_a20_state | ||
| 106 | ret | ||
| 107 | ; | ||
| 108 | estb_mach_state endp | ||
| 109 | |||
| 110 | LAST ends ; End of segment | ||
| 111 | ; | ||
| 112 | |||
| 113 | end ; End of module | ||
| 114 | |||
diff --git a/v4.0/src/MEMM/MEMM/OEMDEP.INC b/v4.0/src/MEMM/MEMM/OEMDEP.INC new file mode 100644 index 0000000..0a2607d --- /dev/null +++ b/v4.0/src/MEMM/MEMM/OEMDEP.INC | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: OEMDEP.INC | ||
| 10 | ; | ||
| 11 | ; Version: 0.04 | ||
| 12 | ; | ||
| 13 | ; Date: June 13, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/13/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; 07/05/86 0.04 Moved Diagbyte to _DATA | ||
| 26 | ; 07/06/86 0.04 Change from _DATA assume to DGROUP | ||
| 27 | ; 08/06/86 0.05 Broke out OEMPROC.ASM from OEMDEP.INC | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ifndef INC_LIST | ||
| 31 | .xlist | ||
| 32 | endif | ||
| 33 | |||
| 34 | |||
| 35 | _TEXT segment | ||
| 36 | |||
| 37 | extrn MaskIntAll:near ; Mask interrupts routine | ||
| 38 | extrn RestIntMask:near ; restore interrupt mask routine | ||
| 39 | |||
| 40 | extrn Map_Lin_OEM:near ; MapLinear hook | ||
| 41 | extrn UMap_Lin_OEM:near ; UnMapLinear hook | ||
| 42 | extrn MB_Map_Src:near ; Move block map source hook | ||
| 43 | extrn MB_Map_Dest:near ; Move block map destination hook | ||
| 44 | extrn MB_Start:near ; Move block start move hook | ||
| 45 | |||
| 46 | _TEXT ends | ||
| 47 | |||
| 48 | |||
| 49 | LAST segment | ||
| 50 | |||
| 51 | extrn VerifyMachine:near ; Verify machine valid for software | ||
| 52 | |||
| 53 | LAST ends | ||
| 54 | |||
| 55 | ifndef NOHIMEM ; only for high memory | ||
| 56 | |||
| 57 | ;Define routines in OEMPROC module | ||
| 58 | |||
| 59 | _TEXT segment | ||
| 60 | |||
| 61 | extrn HwMemLock:near | ||
| 62 | extrn HwMemUnlock:near | ||
| 63 | |||
| 64 | _TEXT ends | ||
| 65 | |||
| 66 | LAST segment | ||
| 67 | |||
| 68 | extrn hbuf_chk:near | ||
| 69 | extrn HiAlloc:near | ||
| 70 | extrn HiSysAlloc:near | ||
| 71 | extrn HImod:near | ||
| 72 | extrn LockROM:near | ||
| 73 | extrn UnLockROM:near | ||
| 74 | |||
| 75 | LAST ends | ||
| 76 | |||
| 77 | endif | ||
| 78 | |||
| 79 | ;****************************************************************************** | ||
| 80 | ; | ||
| 81 | ; HwTabUnlock - unlocks high system RAM - makes tables writeable | ||
| 82 | ; | ||
| 83 | ; EXIT: FS points to DIAG segment | ||
| 84 | ; high system RAM writeable | ||
| 85 | ; | ||
| 86 | HwTabUnlock MACRO | ||
| 87 | ifndef NOHIMEM ; only for high memory | ||
| 88 | call HwMemUnlock | ||
| 89 | endif | ||
| 90 | ENDM | ||
| 91 | |||
| 92 | ;****************************************************************************** | ||
| 93 | ; | ||
| 94 | ; HwTabLock - update client's hi system RAM write locks state | ||
| 95 | ; | ||
| 96 | ; ENTRY: CS = _TEXT | ||
| 97 | ; CS:[DiagByte] = last byte written to diag byte by user. | ||
| 98 | ; | ||
| 99 | ; EXIT: high system RAM write protect ON or OFF depenending on | ||
| 100 | ; write protect bit in CS:[DiagByte]. | ||
| 101 | ; Bit 1 = 0 => write protect ON | ||
| 102 | ; Bit 1 = 1 => write protect OFF | ||
| 103 | ; | ||
| 104 | HwTabLock MACRO | ||
| 105 | ifndef NOHIMEM ; only for high memory | ||
| 106 | call HwMemLock | ||
| 107 | endif | ||
| 108 | |||
| 109 | ENDM | ||
| 110 | |||
| 111 | .list ; end of OEMDEP.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/OEMPROC.ASM b/v4.0/src/MEMM/MEMM/OEMPROC.ASM new file mode 100644 index 0000000..b5e4931 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/OEMPROC.ASM | |||
| @@ -0,0 +1,1120 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: OEMPROC.ASM | ||
| 10 | ; | ||
| 11 | ; Version: 0.05 | ||
| 12 | ; | ||
| 13 | ; Date: June 13, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/13/86 Original Separated out OEMPROC from OEMDEP.INC | ||
| 24 | ; | ||
| 25 | ;****************************************************************************** | ||
| 26 | ; | ||
| 27 | .386p | ||
| 28 | .lfcond ; list false conditionals | ||
| 29 | |||
| 30 | public VerifyMachine | ||
| 31 | public MaskIntAll | ||
| 32 | public RestIntMask | ||
| 33 | public OEM_Trap_Init | ||
| 34 | public Map_Lin_OEM | ||
| 35 | public UMap_Lin_OEM | ||
| 36 | public MB_Map_Src | ||
| 37 | public MB_Map_Dest | ||
| 38 | public MB_Start | ||
| 39 | public Rest_Par_Vect | ||
| 40 | public Set_Par_Vect | ||
| 41 | |||
| 42 | public DisableNMI | ||
| 43 | public ROM_BIOS_Machine_ID | ||
| 44 | public OEM_Init_Diag_Page | ||
| 45 | |||
| 46 | |||
| 47 | ifndef NOHIMEM | ||
| 48 | |||
| 49 | public hi_size | ||
| 50 | public hi_alloc | ||
| 51 | public hisys_alloc | ||
| 52 | |||
| 53 | public HwMemLock | ||
| 54 | public HwMemUnlock | ||
| 55 | |||
| 56 | public Hi_Mem_Size | ||
| 57 | public hbuf_chk | ||
| 58 | public HiAlloc | ||
| 59 | public HiSysAlloc | ||
| 60 | public HImod | ||
| 61 | |||
| 62 | public InitLock | ||
| 63 | public LockROM | ||
| 64 | public UnLockROM | ||
| 65 | |||
| 66 | |||
| 67 | endif | ||
| 68 | |||
| 69 | include page.inc | ||
| 70 | include vdmseg.inc | ||
| 71 | include VDMsel.inc | ||
| 72 | include desc.inc | ||
| 73 | include Instr386.inc | ||
| 74 | include romxbios.equ | ||
| 75 | |||
| 76 | |||
| 77 | ;****************************************************************************** | ||
| 78 | ; E X T E R N A L R E F E R E N C E S | ||
| 79 | ;****************************************************************************** | ||
| 80 | ; | ||
| 81 | _DATA segment | ||
| 82 | extrn gdt_mb:word | ||
| 83 | extrn MB_Stat:word | ||
| 84 | _DATA ends | ||
| 85 | |||
| 86 | |||
| 87 | LAST segment | ||
| 88 | extrn set_src_selector:near | ||
| 89 | extrn set_dest_selector:near | ||
| 90 | extrn SetPageEntry:near | ||
| 91 | LAST ends | ||
| 92 | |||
| 93 | _TEXT segment | ||
| 94 | extrn MB_Exit:near | ||
| 95 | _TEXT ends | ||
| 96 | |||
| 97 | page | ||
| 98 | ;****************************************************************************** | ||
| 99 | ; L O C A L C O N S T A N T S | ||
| 100 | ;****************************************************************************** | ||
| 101 | ; | ||
| 102 | |||
| 103 | MASTER_IMR equ 21h ; mask port for master 8259 | ||
| 104 | |||
| 105 | ; | ||
| 106 | ; PPI port bit definitions | ||
| 107 | ; | ||
| 108 | PPI equ 61h | ||
| 109 | PPO equ 61h | ||
| 110 | PPO_MASK_IOCHECK equ 04h ; disable system board parity check | ||
| 111 | PPO_MASK_PCHECK equ 08h ; disable IO parity check | ||
| 112 | |||
| 113 | RTC_CMD equ 70h ; Real Time Clock cmd port | ||
| 114 | DISABLE_NMI equ 80h ; mask bit for NMI | ||
| 115 | ENABLE_NMI equ 00h ; this command to RTC_CMD enables NMI | ||
| 116 | |||
| 117 | ;****** REMOVE BEFORE DISTRIBUTION begin | ||
| 118 | ; Compaq specific 386 related addresses | ||
| 119 | ; | ||
| 120 | X_HI_MEM_SEG equ 0f000h ;segment for the following words | ||
| 121 | X_MT_386 equ 0fffeh ; Machine type | ||
| 122 | X_RT_386 equ 0ffe8h ; Rom type | ||
| 123 | X_HI_PTR equ 0ffe0h ; pointer to four words (offsets below) | ||
| 124 | X_MEM_BOARD equ 0 ; 32-bit memory board status word | ||
| 125 | X_HISYS equ 0 ; low byte = # of free 4k system pages | ||
| 126 | X_AVAIL_MEM equ 4 ; available hi memory in 16 byte chunks | ||
| 127 | X_LAST_HI equ 6 ; last used byte in hi memory (grows down) | ||
| 128 | ; | ||
| 129 | ; Addresses and values used to write the "ROM" | ||
| 130 | ; | ||
| 131 | OEM_MEM_HI equ 80c0h ; Upper 16 bits of high mem physical adr | ||
| 132 | LOCK_ADR_LO equ 0000h ; 0:15 of 32-bit location | ||
| 133 | LOCK_ADR_HI equ OEM_MEM_HI ; 16-31 of 32-bit location | ||
| 134 | LOCK_ROM equ 0fcfch ; value to write to lock rom | ||
| 135 | UNLOCK_ROM equ 0fefeh ; value to write to unlock rom | ||
| 136 | |||
| 137 | |||
| 138 | |||
| 139 | DIAGSEG segment use16 at 0 | ||
| 140 | DiagLoc dw ? ; 32 bit memory board diagnostic byte | ||
| 141 | DIAGSEG ends | ||
| 142 | |||
| 143 | |||
| 144 | ; | ||
| 145 | ; data definitions | ||
| 146 | ; | ||
| 147 | _DATA segment | ||
| 148 | |||
| 149 | NMI_Old db 8 dup (0) ; save area for old NMI handler | ||
| 150 | |||
| 151 | NMI_New label byte ; descriptor for new NMI handler | ||
| 152 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:Parity_Handler>,D_386INT0 | ||
| 153 | |||
| 154 | ; | ||
| 155 | ifndef NOHIMEM ; if high memory in this model | ||
| 156 | ;Next two entries MUST stay together! | ||
| 157 | hbase_addr_l dw 0000h ; 24 bit address of beginning of hi memory | ||
| 158 | hbase_addr_h db 00h ; pool of EMM pages. | ||
| 159 | ; | ||
| 160 | hi_size dw 0 ; size of hi memory in kbytes | ||
| 161 | hi_alloc dw 0 ; actual hi memory allocated (due to potential waste) | ||
| 162 | hisys_alloc dw 0 ; amount of hi system memory allocated in 4k bytes | ||
| 163 | ; | ||
| 164 | DiagAddr db 0 ; set this when writting to diag byte location | ||
| 165 | DiagByte db LOW LOCK_ROM ; most recent diag byte written by user | ||
| 166 | buffer dw 0 ; buffer for 1 word move blocks | ||
| 167 | endif | ||
| 168 | |||
| 169 | |||
| 170 | int_mask db ? ; save for restoring masked interrupts | ||
| 171 | |||
| 172 | ; | ||
| 173 | ROM_BIOS_Machine_ID db 0fch ; hard coded right now to AT model byte. | ||
| 174 | ; should be changed to be initialised at | ||
| 175 | ; init time ...isp | ||
| 176 | |||
| 177 | |||
| 178 | _DATA ends | ||
| 179 | ;****** REMOVE BEFORE DISTRIBUTION end | ||
| 180 | |||
| 181 | |||
| 182 | _TEXT segment | ||
| 183 | ASSUME CS:_TEXT, DS:DGROUP | ||
| 184 | |||
| 185 | ;****************************************************************************** | ||
| 186 | ; | ||
| 187 | ; MaskIntAll Save current interrupt mask state and mask all interrupts | ||
| 188 | ; | ||
| 189 | ; entry: DS pts to DGROUP | ||
| 190 | ; | ||
| 191 | ; exit: All interrupts disabled | ||
| 192 | ; | ||
| 193 | ; used: AX | ||
| 194 | ; | ||
| 195 | ; stack: | ||
| 196 | ; | ||
| 197 | ;****************************************************************************** | ||
| 198 | MaskIntAll proc near | ||
| 199 | in al,MASTER_IMR | ||
| 200 | mov [int_mask], al | ||
| 201 | mov al,0ffh ;;; all OFF | ||
| 202 | out MASTER_IMR,al | ||
| 203 | ret | ||
| 204 | MaskIntAll endp | ||
| 205 | |||
| 206 | ;****************************************************************************** | ||
| 207 | ; | ||
| 208 | ; RestIntMask Restore interrupt mask saved in MaskIntAll | ||
| 209 | ; | ||
| 210 | ; entry: DS pts to DGROUP | ||
| 211 | ; | ||
| 212 | ; exit: Interrupts restored to state previous to MaskIntAll | ||
| 213 | ; | ||
| 214 | ; used: AX | ||
| 215 | ; | ||
| 216 | ; stack: | ||
| 217 | ; | ||
| 218 | ;****************************************************************************** | ||
| 219 | RestIntMask proc near | ||
| 220 | mov al,[int_mask] ; restore interrupt mask | ||
| 221 | out MASTER_IMR,al | ||
| 222 | ret | ||
| 223 | RestIntMask endp | ||
| 224 | |||
| 225 | ;****************************************************************************** | ||
| 226 | ; OEM_Trap_Init - turn on I/O bit map trapping for I/O port watching | ||
| 227 | ; | ||
| 228 | ; ENTRY: DS -> DGROUP - real,virtual, or protected mode | ||
| 229 | ; ES -> TSS segment | ||
| 230 | ; Trap_Tab already has address of OEM_Handler for ??? ports | ||
| 231 | ; | ||
| 232 | ; Description: This routine is used to initialize any data structures, | ||
| 233 | ; including the IOBitMap(via PortTrap call) used for trapping I/O ports | ||
| 234 | ; when going into virtual mode. The routine(s) used to handle the | ||
| 235 | ; trap(s) should already be installed in the IOTrap_tab table. | ||
| 236 | ; See RRTrap.asm for an example. | ||
| 237 | ; | ||
| 238 | ; EXIT: IO_BitMap Updated to trap ports used for ??? | ||
| 239 | ; | ||
| 240 | ; USED: AX,Flags | ||
| 241 | ; STACK: | ||
| 242 | ;------------------------------------------------------------------------------ | ||
| 243 | assume cs:_TEXT, ds:DGROUP, es:TSS | ||
| 244 | OEM_Trap_Init proc near | ||
| 245 | ; | ||
| 246 | ; Initialize data structures | ||
| 247 | ; | ||
| 248 | ; | ||
| 249 | ; Set IOBM traps to look for client's disabling of the A20 line | ||
| 250 | ; | ||
| 251 | ; push bx | ||
| 252 | ; mov bh, 80h ; set every 1k | ||
| 253 | ; mov ax, ??? ; AX = port num to trap | ||
| 254 | ; call PortTrap ; set traps on ??? port | ||
| 255 | ; | ||
| 256 | ; mov ax,0FFFFh | ||
| 257 | ; mov [???],ax ; Initialize trap data structure | ||
| 258 | ; pop bx | ||
| 259 | |||
| 260 | ret | ||
| 261 | ; | ||
| 262 | OEM_Trap_Init endp | ||
| 263 | ; | ||
| 264 | |||
| 265 | ifndef NOHIMEM ; only for high memory | ||
| 266 | |||
| 267 | ;****************************************************************************** | ||
| 268 | ; | ||
| 269 | ; HwMemUnlock - unlocks high system RAM - makes tables writeable | ||
| 270 | ; | ||
| 271 | ; ENTRY: None | ||
| 272 | ; | ||
| 273 | ; EXIT: If NOHIMEM, does nothing, else: | ||
| 274 | ; FS points to DIAG segment | ||
| 275 | ; high system RAM writeable | ||
| 276 | ; | ||
| 277 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 278 | HwMemUnlock proc near | ||
| 279 | push OEM0_GSEL | ||
| 280 | POP_FS ; set FS to diag segment | ||
| 281 | ASSUME DS:DIAGSEG | ||
| 282 | FSOVER | ||
| 283 | mov word ptr [DiagLoc],UNLOCK_ROM | ||
| 284 | ret | ||
| 285 | HwMemUnlock endp | ||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | ;****************************************************************************** | ||
| 290 | ; | ||
| 291 | ; HwMemLock - update client's hi system RAM write locks state | ||
| 292 | ; | ||
| 293 | ; ENTRY: CS = _TEXT(Protected mode) | ||
| 294 | ; DGROUP:[DiagByte] = last byte written to diag byte by user. | ||
| 295 | ; | ||
| 296 | ; EXIT: high system RAM write protect ON or OFF depenending on | ||
| 297 | ; write protect bit in CS:[DiagByte]. | ||
| 298 | ; Bit 1 = 0 => write protect ON | ||
| 299 | ; Bit 1 = 1 => write protect OFF | ||
| 300 | ; | ||
| 301 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 302 | HwMemLock proc near | ||
| 303 | |||
| 304 | push VDMD_GSEL | ||
| 305 | POP_FS ; FS = DGROUP | ||
| 306 | assume ds:DGROUP | ||
| 307 | FSOVER | ||
| 308 | test [DiagByte],02h ;Q: client's ROM write protected? | ||
| 309 | |||
| 310 | push OEM0_GSEL | ||
| 311 | POP_FS ; set FS to diag segment | ||
| 312 | ASSUME DS:DIAGSEG | ||
| 313 | |||
| 314 | jz HTL_wp ; Y: then write protect ON | ||
| 315 | FSOVER ; N: then write protect OFF | ||
| 316 | mov word ptr [DiagLoc],UNLOCK_ROM | ||
| 317 | jmp short HTL_exit | ||
| 318 | HTL_wp: | ||
| 319 | FSOVER | ||
| 320 | mov word ptr [DiagLoc],LOCK_ROM | ||
| 321 | HTL_exit: | ||
| 322 | ret | ||
| 323 | HwMemLock endp | ||
| 324 | |||
| 325 | endif ;end of "high" memory routines(ifndef NOHIMEM) | ||
| 326 | |||
| 327 | ;****************************************************************************** | ||
| 328 | ; | ||
| 329 | ; Map_Lin_OEM Map OEM high memory from physical to linear address | ||
| 330 | ; | ||
| 331 | ; description: This maps an attempt to access the "high" memory to the | ||
| 332 | ; area starting at 16Meg, which the page tables map to the | ||
| 333 | ; proper physical address. | ||
| 334 | ; | ||
| 335 | ; entry: EAX = physical address to map to linear address | ||
| 336 | ; | ||
| 337 | ; exit: If address has been mapped in AX, CF = 1, else CF = 0. | ||
| 338 | ; | ||
| 339 | ; used: AX | ||
| 340 | ; | ||
| 341 | ; stack: | ||
| 342 | ; | ||
| 343 | ;****************************************************************************** | ||
| 344 | ; | ||
| 345 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 346 | Map_Lin_OEM proc near | ||
| 347 | OP32 | ||
| 348 | cmp ax,0000h | ||
| 349 | dw OEM_MEM_HI ;Q: Addr in diags byte region ? | ||
| 350 | clc | ||
| 351 | jne Mp_Lin_Exit ; N: return, CF = 0(no mapping done) | ||
| 352 | OP32 ; Y: set EAX to proper seg address for diags | ||
| 353 | sub ax,0000h | ||
| 354 | dw (OEM_MEM_HI - 0100h); move to 0100h segment | ||
| 355 | ifndef NOHIMEM | ||
| 356 | ; set write to diag byte flag | ||
| 357 | push ds ; save DS | ||
| 358 | push VDMD_GSEL | ||
| 359 | pop ds ; DS = DGROUP | ||
| 360 | ASSUME DS:DGROUP | ||
| 361 | mov [DiagAddr],1 ; set flag for diag addr | ||
| 362 | pop ds ; reset DS | ||
| 363 | endif | ||
| 364 | stc | ||
| 365 | Mp_Lin_Exit: | ||
| 366 | ret | ||
| 367 | Map_Lin_OEM endp | ||
| 368 | |||
| 369 | |||
| 370 | |||
| 371 | ;****************************************************************************** | ||
| 372 | ; | ||
| 373 | ; UMap_Lin_OEM Map OEM high memory from linear to physical address | ||
| 374 | ; | ||
| 375 | ; description: This maps an attempt to access the "high" memory in the | ||
| 376 | ; linear address area starting at 16Meg, to the proper physical | ||
| 377 | ; address. | ||
| 378 | ; | ||
| 379 | ; entry: EAX = linear address to map to physical address | ||
| 380 | ; | ||
| 381 | ; exit: EAX = physical address | ||
| 382 | ; | ||
| 383 | ; used: EAX | ||
| 384 | ; | ||
| 385 | ; stack: | ||
| 386 | ; | ||
| 387 | ;****************************************************************************** | ||
| 388 | ; | ||
| 389 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 390 | UMap_Lin_OEM proc near | ||
| 391 | OP32 ; Y: set EAX to physical address for diags | ||
| 392 | add ax,0000h | ||
| 393 | dw (OEM_MEM_HI - 0100h) ; move to OEM_MEM_HI segment | ||
| 394 | ret | ||
| 395 | UMap_Lin_OEM endp | ||
| 396 | |||
| 397 | ;****************************************************************************** | ||
| 398 | ; | ||
| 399 | ; MB_Map_Src Do special move block processing before source mapping | ||
| 400 | ; | ||
| 401 | ; description: | ||
| 402 | ; This routine is called just before MoveBlock does mapping of | ||
| 403 | ; the source. In conjunction with the Map_Lin_OEM routine, and | ||
| 404 | ; the MB_Start routine, it can perform special processing on the | ||
| 405 | ; data moved. | ||
| 406 | ; | ||
| 407 | ; entry: ES:DI pts to source work descr in GDT | ||
| 408 | ; | ||
| 409 | ; exit: any flag setting or perturbation of descriptor is done | ||
| 410 | ; | ||
| 411 | ; used: none | ||
| 412 | ; | ||
| 413 | ; stack: | ||
| 414 | ; | ||
| 415 | ;****************************************************************************** | ||
| 416 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 417 | MB_Map_Src proc near | ||
| 418 | ret | ||
| 419 | MB_Map_Src endp | ||
| 420 | |||
| 421 | ;****************************************************************************** | ||
| 422 | ; | ||
| 423 | ; MB_Map_Dest Do special move block processing before destination mapping | ||
| 424 | ; | ||
| 425 | ; description: | ||
| 426 | ; This routine is called just before MoveBlock does mapping of | ||
| 427 | ; the destination. In conjunction with the Map_Lin_OEM routine, | ||
| 428 | ; and the MB_Start routine, it can perform special processing on | ||
| 429 | ; the data moved. | ||
| 430 | ; | ||
| 431 | ; entry: ES:DI pts to destination work descr in GDT | ||
| 432 | ; | ||
| 433 | ; exit: any flag setting or perturbation of descriptor is done | ||
| 434 | ; | ||
| 435 | ; used: AX | ||
| 436 | ; | ||
| 437 | ; stack: | ||
| 438 | ; | ||
| 439 | ;****************************************************************************** | ||
| 440 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 441 | MB_Map_Dest proc near | ||
| 442 | ifndef NOHIMEM | ||
| 443 | push ds | ||
| 444 | push VDMD_GSEL | ||
| 445 | pop ds ; DS = DGROUP alias selector | ||
| 446 | ASSUME DS:DGROUP | ||
| 447 | mov [DiagAddr],0 ; reset diag addr flag before write | ||
| 448 | pop ds ; reset DS | ||
| 449 | endif | ||
| 450 | ret | ||
| 451 | MB_Map_Dest endp | ||
| 452 | |||
| 453 | ;****************************************************************************** | ||
| 454 | ; | ||
| 455 | ; MB_Start Do any special move block processing | ||
| 456 | ; | ||
| 457 | ; description: | ||
| 458 | ; This routine is called just before MoveBlock does the move. | ||
| 459 | ; It allows for any special processing of data moved | ||
| 460 | ; | ||
| 461 | ; entry: DS is source selector | ||
| 462 | ; ES is destination selector | ||
| 463 | ; SI is source offset | ||
| 464 | ; DI is destination offset | ||
| 465 | ; | ||
| 466 | ; exit: nothing | ||
| 467 | ; | ||
| 468 | ; used: AX | ||
| 469 | ; | ||
| 470 | ; stack: | ||
| 471 | ; | ||
| 472 | ;****************************************************************************** | ||
| 473 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 474 | MB_Start proc near | ||
| 475 | ifndef NOHIMEM | ||
| 476 | ; | ||
| 477 | ; check for write to diag byte location | ||
| 478 | ; | ||
| 479 | push es | ||
| 480 | push VDMD_GSEL | ||
| 481 | pop es ; ES = DGROUP alias | ||
| 482 | ASSUME ES:DGROUP | ||
| 483 | cmp es:[DiagAddr],0 ;Q: does target -> diag byte ? | ||
| 484 | je MB_nodiag ; N: then don't worry | ||
| 485 | mov al,[si] ; Y: get current diag byte | ||
| 486 | mov es:[DiagByte],al ; and save it where we can access it | ||
| 487 | MB_nodiag: | ||
| 488 | pop es ; restore es | ||
| 489 | endif | ||
| 490 | ret | ||
| 491 | MB_Start endp | ||
| 492 | |||
| 493 | ;************************************************************************* | ||
| 494 | ; Set_Par_Vect - Set parity handling routine to routine below | ||
| 495 | ; | ||
| 496 | ; Description: | ||
| 497 | ; This routine sets up a parity handling routine in case of | ||
| 498 | ; a parity error during a MOVEBLOCK. | ||
| 499 | ; | ||
| 500 | ; ENTRY: protected mode | ||
| 501 | ; | ||
| 502 | ; EXIT: vector restored | ||
| 503 | ; | ||
| 504 | ; USES: AX, CX, ES, DS, DI, SI | ||
| 505 | ; | ||
| 506 | ; note: entry is from protected mode -> DS,ES are same as during | ||
| 507 | ; move block. | ||
| 508 | ;************************************************************************* | ||
| 509 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 510 | Set_Par_Vect proc near | ||
| 511 | mov ax,VDMD_GSEL | ||
| 512 | mov es,ax ; ES pts to DGROUP | ||
| 513 | mov ax,IDTD_GSEL ; | ||
| 514 | mov ds,ax ; DS points to IDT | ||
| 515 | |||
| 516 | mov si,0010h ; DS:[SI] points to NMI descr address in IDT | ||
| 517 | mov di,offset DGROUP:NMI_Old ; ES:[DI] pts to store area | ||
| 518 | mov cx,2 | ||
| 519 | db 66h | ||
| 520 | rep movsw ; store 2 dwords - save current NMI descriptor | ||
| 521 | push ds | ||
| 522 | push es | ||
| 523 | pop ds ; DS = DGROUP | ||
| 524 | pop es ; ES = IDT | ||
| 525 | mov di,0010h ; ES:[DI] points to NMI descr address in IDT | ||
| 526 | mov si,offset DGROUP:NMI_New ; DS:[SI] pts to new NMI descr | ||
| 527 | mov cx,2 | ||
| 528 | db 66h | ||
| 529 | rep movsw ; set up new NMI descriptor in IDT | ||
| 530 | ret | ||
| 531 | Set_Par_Vect endp | ||
| 532 | |||
| 533 | ;************************************************************************* | ||
| 534 | ; Rest_Par_Vect - restore parity handling routine to original | ||
| 535 | ; | ||
| 536 | ; Description: | ||
| 537 | ; This routine restores the parity handling vector to the | ||
| 538 | ; contents before Set_Par_Vect was called. It is called after | ||
| 539 | ; a MOVEBLOCK has been completed. | ||
| 540 | ; | ||
| 541 | ; ENTRY: DS = DGROUP | ||
| 542 | ; | ||
| 543 | ; EXIT: vector restored | ||
| 544 | ; | ||
| 545 | ; USES: AX, CX, ES, DI, SI | ||
| 546 | ; | ||
| 547 | ; note: entry is from protected mode -> DS,ES are same as during | ||
| 548 | ; move block. | ||
| 549 | ;************************************************************************* | ||
| 550 | assume cs:_TEXT, ds:DGROUP, es:NOTHING | ||
| 551 | Rest_Par_Vect proc near | ||
| 552 | ifndef NOHIMEM | ||
| 553 | call HwMemUnlock ; in case IDT is in high mem | ||
| 554 | endif | ||
| 555 | mov ax,IDTD_GSEL ; selector for IDT | ||
| 556 | mov es,ax ; ES points to IDT | ||
| 557 | |||
| 558 | mov di,0010h ; ES:[DI] points to NMI descr address in IDT | ||
| 559 | mov si,offset DGROUP:NMI_Old ; DS:[SI] pts to store area | ||
| 560 | mov cx,2 | ||
| 561 | db 66h | ||
| 562 | rep movsw ; restore previous NMI descriptor | ||
| 563 | ifndef NOHIMEM | ||
| 564 | call HwMemLock | ||
| 565 | endif | ||
| 566 | ret | ||
| 567 | Rest_Par_Vect endp | ||
| 568 | |||
| 569 | |||
| 570 | ;************************************************************************* | ||
| 571 | ; Parity_Handler - routine to handle parity errors which occur during | ||
| 572 | ; move_block. | ||
| 573 | ; Description: | ||
| 574 | ; This routine writes to the parity error location to | ||
| 575 | ; clear the parity error on the memory board, then it clears | ||
| 576 | ; the parity error on the system board. | ||
| 577 | ; | ||
| 578 | ; note: entry is from protected mode -> DS,ES are same as during | ||
| 579 | ; move block. | ||
| 580 | ;************************************************************************* | ||
| 581 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 582 | Parity_Handler proc far | ||
| 583 | ; | ||
| 584 | dec si | ||
| 585 | dec si ;;; DS:SI pts to address causing parity error | ||
| 586 | mov ax,[si] ;;; retrieve value and write it back | ||
| 587 | mov [si],ax ;;; to reset parity on memory board. | ||
| 588 | in al,PPI ;;; Get parity error flags, reset then set | ||
| 589 | jmp $+2 ;;; parity checking to reset parity on | ||
| 590 | jmp $+2 ;;; system board | ||
| 591 | or al,PPO_MASK_IOCHECK ;;; disable IOCHECK | ||
| 592 | or al,PPO_MASK_PCHECK ;;; disable PCHECK | ||
| 593 | out PPO,al ;;; disable them | ||
| 594 | jmp $+2 | ||
| 595 | jmp $+2 | ||
| 596 | jmp $+2 | ||
| 597 | |||
| 598 | ifndef NOHIMEM | ||
| 599 | call HwMemlock ;;; LOCK high sys mem | ||
| 600 | endif | ||
| 601 | |||
| 602 | and al, NOT PPO_MASK_IOCHECK ;;; enable IOCHECK | ||
| 603 | and al, NOT PPO_MASK_PCHECK ;;; enable PCHECK | ||
| 604 | out PPO,al ;;; enable them | ||
| 605 | ;;; system board parity now reset | ||
| 606 | |||
| 607 | ; | ||
| 608 | mov ax,VDMD_GSEL ;;; | ||
| 609 | mov ds,ax ;;; set DS to data seg | ||
| 610 | assume ds:DGROUP | ||
| 611 | mov [MB_Stat],1 ;;; set parity error | ||
| 612 | add sp,12 ;;; remove NMI stuff from stack | ||
| 613 | jmp MB_Exit ;;; and exit move block | ||
| 614 | |||
| 615 | Parity_Handler endp | ||
| 616 | |||
| 617 | ;************************************************************************* | ||
| 618 | ; DisableNMI - This is called by the NMI handler to disable the | ||
| 619 | ; NMI interrupt(stop gracefully) as part of the | ||
| 620 | ; graceful handling of the NMI interrupt. | ||
| 621 | ; | ||
| 622 | ; Description: | ||
| 623 | ; | ||
| 624 | ; note: entry is from 386 protected mode | ||
| 625 | ;************************************************************************* | ||
| 626 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 627 | DisableNMI proc near | ||
| 628 | push ax | ||
| 629 | mov al,DISABLE_NMI | ||
| 630 | out RTC_CMD,al | ||
| 631 | pop ax | ||
| 632 | ret | ||
| 633 | DisableNMI endp | ||
| 634 | |||
| 635 | _TEXT ends | ||
| 636 | |||
| 637 | LAST segment | ||
| 638 | |||
| 639 | ;****************************************************************************** | ||
| 640 | ; | ||
| 641 | ; VerifyMachine Check ID, etc. to make sure machine is 386 valid for | ||
| 642 | ; running the LIM/386 product. | ||
| 643 | ; | ||
| 644 | ; description: | ||
| 645 | ; This routine should check ROM signature bytes and any other | ||
| 646 | ; hardware features that guarantee the appropriateness of running this | ||
| 647 | ; software on the machine. | ||
| 648 | ; | ||
| 649 | ; entry: DS pts to DGROUP | ||
| 650 | ; CF = 1 if from INIT procedure, CF = 0 if from AllocMem procedure | ||
| 651 | ; REAL or VIRTUAL MODE | ||
| 652 | ; | ||
| 653 | ; exit: If not correct machine, CF = 1, else CF = 0. | ||
| 654 | ; | ||
| 655 | ; used: AX | ||
| 656 | ; | ||
| 657 | ; stack: | ||
| 658 | ; | ||
| 659 | ;****************************************************************************** | ||
| 660 | ; | ||
| 661 | assume cs:LAST, ds:NOTHING, es:NOTHING | ||
| 662 | VerifyMachine proc near | ||
| 663 | pushf | ||
| 664 | push es ; save es | ||
| 665 | push bx ; save bx | ||
| 666 | mov bx,X_HI_MEM_SEG ; segment of hi memory control words | ||
| 667 | mov es,bx ; into es | ||
| 668 | mov ax,es:X_MT_386 ; get machine type | ||
| 669 | cmp al,0FCh ; q: is this an AT class machine? | ||
| 670 | mov ax,es:X_RT_386 ; get ROM type | ||
| 671 | pop bx ; restore bx | ||
| 672 | pop es ; restore es | ||
| 673 | jne inc_prcf ; n: invalid | ||
| 674 | popf | ||
| 675 | jc Cor_Prc ; that's all the checking for INIT | ||
| 676 | cmp ax,'30' ; q: is this a 386? (really '03') | ||
| 677 | jne inc_prc | ||
| 678 | Cor_Prc: | ||
| 679 | clc | ||
| 680 | ret | ||
| 681 | inc_prcf: | ||
| 682 | popf | ||
| 683 | inc_prc: | ||
| 684 | stc | ||
| 685 | ret | ||
| 686 | VerifyMachine endp ; End of procedure | ||
| 687 | |||
| 688 | |||
| 689 | ifndef NOHIMEM ; if high memory in this model | ||
| 690 | ;****************************************************************************** | ||
| 691 | ; | ||
| 692 | ; Hi_Mem_Size - returns pointer and size of high mem allocated to EMM | ||
| 693 | ; | ||
| 694 | ; entry: | ||
| 695 | ; | ||
| 696 | ; exit: if ZF = 1, no high memory allocated to EMM, else | ||
| 697 | ; EAX = 24 bit pointer to EMM allocated high memory | ||
| 698 | ; CX = kbytes of high memory allocated | ||
| 699 | ; | ||
| 700 | ; used: EAX, CX(returned values) | ||
| 701 | ; | ||
| 702 | ; stack: | ||
| 703 | ; | ||
| 704 | ;****************************************************************************** | ||
| 705 | ; | ||
| 706 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 707 | Hi_Mem_Size proc near | ||
| 708 | mov cx,[hi_size] ; CX = kbytes of high mem | ||
| 709 | shr cx,4 ;Q: any hi memory pages ? CX = pg cnt | ||
| 710 | jz Hi_Mem_SXit ; N: Exit with ZF = 1 | ||
| 711 | db 66h ; Y: get high memory pointers | ||
| 712 | mov ax,[hbase_addr_l] ; get pointer to high memory pool | ||
| 713 | db 66h | ||
| 714 | and ax,0FFFFh ; AND EAX,00FFFFFFh | ||
| 715 | dw 00FFh ; clear highest nibble | ||
| 716 | Hi_Mem_SXit: | ||
| 717 | ret | ||
| 718 | Hi_Mem_Size endp | ||
| 719 | |||
| 720 | page | ||
| 721 | ;****************************************************************************** | ||
| 722 | ; | ||
| 723 | ; hbuf_chk Hi memory pool check. | ||
| 724 | ; Check available hi memory pool space | ||
| 725 | ; | ||
| 726 | ; entry: | ||
| 727 | ; | ||
| 728 | ; exit: If hi memory pool space is available then | ||
| 729 | ; AX = size of memory available and CF = 0 | ||
| 730 | ; else AX = 0 and CF = 1 | ||
| 731 | ; | ||
| 732 | ; used: AX(returned value) | ||
| 733 | ; | ||
| 734 | ; stack: | ||
| 735 | ; | ||
| 736 | ;****************************************************************************** | ||
| 737 | ; | ||
| 738 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 739 | hbuf_chk proc near | ||
| 740 | push es ; save es | ||
| 741 | push bx | ||
| 742 | mov bx,X_HI_MEM_SEG ; segment of hi memory control words | ||
| 743 | mov es,bx | ||
| 744 | mov bx,es:X_HI_PTR ; pointer to hi memory control words | ||
| 745 | mov ax,es:[bx+X_MEM_BOARD] ; 32-bit memory board status | ||
| 746 | inc ax ; q: memory board status word == -1? | ||
| 747 | stc | ||
| 748 | jz hbuf_xit ; y: not installed | ||
| 749 | mov ax,es:[bx+X_AVAIL_MEM] ; get available memory in 16 byte pieces | ||
| 750 | mov bx,es:[bx+X_LAST_HI] ; get last used address | ||
| 751 | and bx,0ffh ; align to 4k byte boundary (2**8)*16 | ||
| 752 | sub ax,bx ; ax = available 16 byte pieces | ||
| 753 | shr ax,10 ; ax = available 16k byte pieces | ||
| 754 | shl ax,4 ; ax = available 1k byte pieces | ||
| 755 | clc | ||
| 756 | hbuf_xit: | ||
| 757 | pop bx ; ax = availble memory unless CF = 1 | ||
| 758 | pop es | ||
| 759 | ret | ||
| 760 | hbuf_chk endp | ||
| 761 | ; | ||
| 762 | page | ||
| 763 | ;****************************************************************************** | ||
| 764 | ; | ||
| 765 | ; HiAlloc - allocate hi memory - update hi memory control words | ||
| 766 | ; | ||
| 767 | ; entry: REAL or VIRTUAL MODE | ||
| 768 | ; DS pts to DGROUP | ||
| 769 | ; DGROUP:[hi_size] size in kbytes to allocate | ||
| 770 | ; | ||
| 771 | ; exit: update available hi memory and last used address. | ||
| 772 | ; Set [hbase_addr_l] and [hbase_addr_h] to starting address. | ||
| 773 | ; If error occurs in writing control words, CF = 1, else CF = 0. | ||
| 774 | ; | ||
| 775 | ; used: none | ||
| 776 | ; | ||
| 777 | ; stack: | ||
| 778 | ; | ||
| 779 | ;****************************************************************************** | ||
| 780 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 781 | HiAlloc proc near | ||
| 782 | ; | ||
| 783 | push ax | ||
| 784 | push bx | ||
| 785 | push cx | ||
| 786 | push dx | ||
| 787 | push si | ||
| 788 | push es | ||
| 789 | ; | ||
| 790 | mov ax,[hi_size] ; get amount of hi memory to allocate | ||
| 791 | or ax,ax ; q: allocate any? | ||
| 792 | jz Hi_xit ; n: quit(CF = 0) | ||
| 793 | |||
| 794 | mov cl,6 | ||
| 795 | shl ax,cl ; back to 16 byte pieces | ||
| 796 | ; | ||
| 797 | mov bx,X_HI_MEM_SEG ; high memory segment | ||
| 798 | mov es,bx | ||
| 799 | mov bx,es:X_HI_PTR ; pointer to high memory control words | ||
| 800 | mov cx,0ffh ; determine waste by aligning to 4k | ||
| 801 | and cx,es:[bx+X_LAST_HI] ; cx = extra needed to align | ||
| 802 | add ax,cx ; ax = total to allocate | ||
| 803 | mov [hi_alloc],ax ; save it in case we need to put it back | ||
| 804 | xor bx,bx ; bx = no hi system memory to alloc | ||
| 805 | call HImod ; go allocate it | ||
| 806 | ; ax = start of this hi memory | ||
| 807 | jc Hi_xit ; error occurred during move block(CF=1) | ||
| 808 | mov cx,16 | ||
| 809 | mul cx ; make it 24 bits | ||
| 810 | add dl,0f0h ; last 1M segment | ||
| 811 | mov [hbase_addr_h],dl ; save starting address of hi mem | ||
| 812 | mov [hbase_addr_l],ax | ||
| 813 | clc | ||
| 814 | ; | ||
| 815 | Hi_xit: ; CF = 1 if error, else CF = 0 | ||
| 816 | pop es | ||
| 817 | pop si | ||
| 818 | pop dx | ||
| 819 | pop cx | ||
| 820 | pop bx | ||
| 821 | pop ax | ||
| 822 | ret | ||
| 823 | HiAlloc endp | ||
| 824 | ; | ||
| 825 | page | ||
| 826 | ;****************************************************************************** | ||
| 827 | ; | ||
| 828 | ; HiSysAlloc - allocate hi system memory - update hi memory control words | ||
| 829 | ; | ||
| 830 | ; entry: REAL or VIRTUAL MODE | ||
| 831 | ; DS pts to DGROUP | ||
| 832 | ; ax = # of 4k byte pieces to allocate | ||
| 833 | ; | ||
| 834 | ; exit: If enough hi system memory available | ||
| 835 | ; update available hi system memory. | ||
| 836 | ; ax = # of 4k byte pieces used before this allocation. | ||
| 837 | ; CY cleared | ||
| 838 | ; else | ||
| 839 | ; ax = amount of hi system memory available | ||
| 840 | ; CY set | ||
| 841 | ; If error occurs in writing control words, | ||
| 842 | ; CY set | ||
| 843 | ; ax = -1 | ||
| 844 | ; | ||
| 845 | ; used: see above | ||
| 846 | ; | ||
| 847 | ; stack: | ||
| 848 | ; | ||
| 849 | ;****************************************************************************** | ||
| 850 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 851 | HiSysAlloc proc near | ||
| 852 | push bx | ||
| 853 | push es | ||
| 854 | ; | ||
| 855 | push ax ; save amount asked for | ||
| 856 | mov bx,X_HI_MEM_SEG ; high memory segment | ||
| 857 | mov es,bx | ||
| 858 | mov bx,es:X_HI_PTR ; pointer to high memory control words | ||
| 859 | mov ax,es:[bx+X_HISYS] ; ax = amount of hi system mem available | ||
| 860 | and ax,00ffh ; after we get rid of high byte | ||
| 861 | pop bx ; bx = amount requested | ||
| 862 | ; ax = amount currently available | ||
| 863 | cmp ax,bx ; Q: available >= requested? | ||
| 864 | jb Hisys_xit ; N: quit - carry set => not enough mem | ||
| 865 | add [hisys_alloc],bx ; Y: save it in case we must deallocate | ||
| 866 | push ax ; save amount available before | ||
| 867 | xor ax,ax ; ax = no hi user mem to alloc | ||
| 868 | call HImod ; go allocate high sys mem | ||
| 869 | pop bx ; bx = amount available before | ||
| 870 | jc Hisys_err ; MOD ERROR -> set error flag | ||
| 871 | mov ax,10h ; 16 pages in high sys mem pool | ||
| 872 | sub ax,bx ; ax = amount used before this request | ||
| 873 | jmp Hisys_xit ; no error in move block | ||
| 874 | ; | ||
| 875 | Hisys_err: | ||
| 876 | mov ax,-1 | ||
| 877 | stc ; to be sure | ||
| 878 | Hisys_xit: | ||
| 879 | pop es | ||
| 880 | pop bx | ||
| 881 | ret | ||
| 882 | HiSysAlloc endp | ||
| 883 | ; | ||
| 884 | page | ||
| 885 | ;****************************************************************************** | ||
| 886 | ; | ||
| 887 | ; Himod - allocate/deallocate hi memory - update hi memory control words | ||
| 888 | ; | ||
| 889 | ; entry: REAL or VIRTUAL MODE | ||
| 890 | ; DS pts to DGROUP | ||
| 891 | ; ax = size in 16 bytes of hi USER mem to alloc (a negative # | ||
| 892 | ; will deallocate) | ||
| 893 | ; bx = size in 4k bytes of hi SYSTEM mem to alloc (ditto above) | ||
| 894 | ; | ||
| 895 | ; exit: update available hi memory and last used address. | ||
| 896 | ; ax = New last used address for high user memory | ||
| 897 | ; CY = set if block move error occurred | ||
| 898 | ; | ||
| 899 | ; used: none | ||
| 900 | ; | ||
| 901 | ; stack: | ||
| 902 | ; | ||
| 903 | ;****************************************************************************** | ||
| 904 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 905 | HImod proc near | ||
| 906 | push bx | ||
| 907 | push cx | ||
| 908 | push dx | ||
| 909 | push si | ||
| 910 | push es | ||
| 911 | ; | ||
| 912 | call UnLockROM ;Q: ROM space writeable? | ||
| 913 | jz unlock_ok ; Y: continue | ||
| 914 | jmp Himod_err ; N: exit | ||
| 915 | unlock_ok: | ||
| 916 | push bx ; save hi system memory allocation | ||
| 917 | mov bx,X_HI_MEM_SEG ; high memory segment | ||
| 918 | mov es,bx | ||
| 919 | mov bx,es:X_HI_PTR ; pointer to high memory control words | ||
| 920 | sub es:[bx+X_AVAIL_MEM],ax ; update hi memory available | ||
| 921 | sub es:[bx+X_LAST_HI],ax ; and last used address | ||
| 922 | pop ax ; get hi system memory amount | ||
| 923 | sub es:[bx+X_HISYS],ax ; update hi system memory available | ||
| 924 | mov ax,es:[bx+X_LAST_HI] ; start of this hi memory | ||
| 925 | ; | ||
| 926 | call LockROM ;Q: ROM write protected now ? | ||
| 927 | clc ; clear error flag | ||
| 928 | jz Himod_xit ; Y: exit with no error | ||
| 929 | ; ; N: report error | ||
| 930 | Himod_err: | ||
| 931 | stc ; indicate error | ||
| 932 | HImod_xit: | ||
| 933 | pop es | ||
| 934 | pop si | ||
| 935 | pop dx | ||
| 936 | pop cx | ||
| 937 | pop bx | ||
| 938 | ; | ||
| 939 | ret | ||
| 940 | |||
| 941 | |||
| 942 | HImod endp | ||
| 943 | page | ||
| 944 | ;****************************************************************************** | ||
| 945 | ; | ||
| 946 | ; LockROM - write protects high system RAM | ||
| 947 | ; | ||
| 948 | ; entry: REAL or VIRTUAL MODE | ||
| 949 | ; DS pts to DGROUP | ||
| 950 | ; | ||
| 951 | ; exit: Z = no error - high system RAM write protected | ||
| 952 | ; NZ = ERROR. | ||
| 953 | ; | ||
| 954 | ; used: none | ||
| 955 | ; | ||
| 956 | ; stack: | ||
| 957 | ; | ||
| 958 | ;****************************************************************************** | ||
| 959 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 960 | LockROM proc near | ||
| 961 | push ax ; save ax | ||
| 962 | push cx | ||
| 963 | push dx | ||
| 964 | push es | ||
| 965 | ; | ||
| 966 | mov word ptr [buffer],LOCK_ROM ; word to write to unlock | ||
| 967 | jmp UL_write ; go write it... | ||
| 968 | ; | ||
| 969 | LockROM endp | ||
| 970 | |||
| 971 | page | ||
| 972 | ;****************************************************************************** | ||
| 973 | ; | ||
| 974 | ; UnLockROM - turns off write protect on high system RAM | ||
| 975 | ; | ||
| 976 | ; entry: REAL or VIRTUAL MODE | ||
| 977 | ; DS pts to DGROUP | ||
| 978 | ; | ||
| 979 | ; exit: Z = no error - high system RAM writeable | ||
| 980 | ; NZ = ERROR. | ||
| 981 | ; | ||
| 982 | ; used: none | ||
| 983 | ; | ||
| 984 | ; stack: | ||
| 985 | ; | ||
| 986 | ;****************************************************************************** | ||
| 987 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 988 | UnLockROM proc near | ||
| 989 | push ax ; save ax | ||
| 990 | push cx | ||
| 991 | push dx | ||
| 992 | push es | ||
| 993 | ; | ||
| 994 | mov word ptr [buffer],UNLOCK_ROM ; word to write to unlock | ||
| 995 | ; | ||
| 996 | UL_write: | ||
| 997 | mov ax,seg DGROUP ; set source addr to buffer | ||
| 998 | mov es,ax ; set ES to DGROUP | ||
| 999 | mov cx,16 | ||
| 1000 | mul cx ; make 24 bits | ||
| 1001 | add ax,offset DGROUP:buffer | ||
| 1002 | adc dl,0 | ||
| 1003 | mov cx,1 ; 1 word to transfer | ||
| 1004 | call set_src_selector ; set source segment selector to buffer | ||
| 1005 | mov ax,LOCK_ADR_LO ; DX:AX = 32-bit addr of ROM LOCK | ||
| 1006 | mov dx,LOCK_ADR_HI | ||
| 1007 | mov cx,1 ; 1 word long | ||
| 1008 | call set_dest_selector ; destination is unlock address | ||
| 1009 | |||
| 1010 | mov ax,seg LAST | ||
| 1011 | mov es,ax ; es to last segmetn | ||
| 1012 | mov si,offset DGROUP:gdt_mb ; ES:SI -> global descriptor table | ||
| 1013 | mov ah,MOVE_BLK ; int 15 block move function code | ||
| 1014 | int XBIOS ; unlock rom | ||
| 1015 | or ah,ah ; Q: error? | ||
| 1016 | ; Y: return NZ | ||
| 1017 | ; N: return Z | ||
| 1018 | pop es | ||
| 1019 | pop dx | ||
| 1020 | pop cx | ||
| 1021 | pop ax | ||
| 1022 | ret | ||
| 1023 | UnLockROM endp ; end of procedure | ||
| 1024 | |||
| 1025 | endif ; end of code for not NOHIMEM | ||
| 1026 | |||
| 1027 | |||
| 1028 | ;****************************************************************************** | ||
| 1029 | ; | ||
| 1030 | ; OEM_Init_Diag_Page: Initialise the 5th page table to point to the | ||
| 1031 | ; diagnostic segment. | ||
| 1032 | ; | ||
| 1033 | ; description: | ||
| 1034 | ; | ||
| 1035 | ; place 32 bit memory board diagnostic byte address into page table | ||
| 1036 | ; xxxx0000h - xxxxFFFFh physical | ||
| 1037 | ; -> 01000000h - 0100FFFFh linear => 64k => 16 entries in page tables | ||
| 1038 | ; => 1st 64k in 5th page table | ||
| 1039 | ; | ||
| 1040 | ; entry: DS pts to DGROUP | ||
| 1041 | ; ES:0 Page table seg. | ||
| 1042 | ; | ||
| 1043 | ; exit: nothing | ||
| 1044 | ; | ||
| 1045 | ; used: ax,di,dx,bx,cx,flags | ||
| 1046 | ; | ||
| 1047 | ; stack: | ||
| 1048 | ; | ||
| 1049 | ;****************************************************************************** | ||
| 1050 | ; | ||
| 1051 | OEM_Init_Diag_Page proc near | ||
| 1052 | assume cs:LAST, ds:dgroup, es:NOTHING | ||
| 1053 | ; | ||
| 1054 | ; | ||
| 1055 | mov di,4*P_SIZE ; ES:DI -> 1st 64k of 5th page table | ||
| 1056 | mov dx,OEM_MEM_HI | ||
| 1057 | xor ax,ax ; start with physical addr = xxxx0000h | ||
| 1058 | mov bh,0 | ||
| 1059 | mov bl,P_AVAIL ; make pages available to all | ||
| 1060 | mov cx,10h ; set 64k worth of entries | ||
| 1061 | IT_set_entry: | ||
| 1062 | call SetPageEntry | ||
| 1063 | ; ES:[DI] pts to next page table entry | ||
| 1064 | add ax,1000h ; next physical page | ||
| 1065 | adc dx,0h ; address in DX,AX | ||
| 1066 | loop IT_set_entry ;Q: done with page table entries ? | ||
| 1067 | ; N: loop again | ||
| 1068 | ; Y: all done | ||
| 1069 | ret | ||
| 1070 | ; | ||
| 1071 | OEM_Init_Diag_Page endp | ||
| 1072 | |||
| 1073 | LAST ends ; End of segment | ||
| 1074 | |||
| 1075 | ifndef NOHIMEM ; if high memory in this model | ||
| 1076 | |||
| 1077 | R_CODE SEGMENT | ||
| 1078 | assume cs:R_CODE, ds:DGROUP, es:DGROUP | ||
| 1079 | |||
| 1080 | ;****************************************************************************** | ||
| 1081 | ; InitLock - Init state of Table lock | ||
| 1082 | ; | ||
| 1083 | ; NOTE: this is a FAR routine. | ||
| 1084 | ; | ||
| 1085 | ; ENTRY: REAL MODE | ||
| 1086 | ; DS = DGROUP | ||
| 1087 | ; | ||
| 1088 | ; EXIT: REAL MODE | ||
| 1089 | ; DGROUP:[DiagByte] = updated to current LOCK state | ||
| 1090 | ; | ||
| 1091 | ; USED: AX,BX | ||
| 1092 | ; | ||
| 1093 | ;****************************************************************************** | ||
| 1094 | InitLOCK proc far | ||
| 1095 | |||
| 1096 | mov [DiagByte],LOW LOCK_ROM ; default is locked | ||
| 1097 | push es | ||
| 1098 | mov ax,X_HI_MEM_SEG | ||
| 1099 | mov es,ax ; ES -> ROM | ||
| 1100 | mov bx,X_MT_386 ; ES:BX -> machine type byte | ||
| 1101 | mov ax,ES:[bx] ; AX = ROM contents | ||
| 1102 | xor ES:[bx],0FFFFh ; flip all bits in ROM | ||
| 1103 | xor ax,0FFFFh ; AX = "flipped" value | ||
| 1104 | cmp ax,ES:[bx] ;Q: flipped value in ROM ? | ||
| 1105 | jne gv_locked ; N: "ROM" is locked | ||
| 1106 | mov [DiagByte],LOW UNLOCK_ROM ;Y: ROM is UNLOCKED | ||
| 1107 | gv_locked: | ||
| 1108 | xor ES:[bx],0FFFFh ; restore ROM contents (if changed) | ||
| 1109 | ; | ||
| 1110 | pop es | ||
| 1111 | ret | ||
| 1112 | |||
| 1113 | InitLOCK endp | ||
| 1114 | |||
| 1115 | R_CODE ENDS | ||
| 1116 | |||
| 1117 | endif ; end of code for not NOHIMEM | ||
| 1118 | |||
| 1119 | end ; of module | ||
| 1120 | |||
diff --git a/v4.0/src/MEMM/MEMM/PAGE.INC b/v4.0/src/MEMM/MEMM/PAGE.INC new file mode 100644 index 0000000..aa76e69 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/PAGE.INC | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: PAGE.INC - Definitions for paging on 386 | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: January 31, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 01/31/86 Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ; | ||
| 29 | ; Functional Description: | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ifndef INC_LIST | ||
| 33 | .xlist | ||
| 34 | endif | ||
| 35 | |||
| 36 | P_SIZE equ 1000h ; page size | ||
| 37 | |||
| 38 | P_PRES equ 01h ; page present bit | ||
| 39 | P_WRITE equ 02h ; write access bit | ||
| 40 | P_USER equ 04h ; access bit for User mode | ||
| 41 | P_ACC equ 10h ; page accessed bit | ||
| 42 | P_DIRTY equ 20h ; page dirty bit | ||
| 43 | |||
| 44 | |||
| 45 | P_AVAIL equ (P_PRES+P_WRITE+P_USER) ; avail to everyone & present | ||
| 46 | |||
| 47 | PAGE_ENTRY macro addr,stat | ||
| 48 | dd addr ; access & status in low 12 | ||
| 49 | ; address in high 20 | ||
| 50 | endm | ||
| 51 | |||
| 52 | .list ; end of PAGE.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/PIC_DEF.EQU b/v4.0/src/MEMM/MEMM/PIC_DEF.EQU new file mode 100644 index 0000000..93706b5 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/PIC_DEF.EQU | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: PIC_DEF.EQU - 8259 programmable interrupt controllers | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: January 31, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 01/31/86 Original | ||
| 24 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ifndef INC_LIST | ||
| 29 | .xlist | ||
| 30 | endif | ||
| 31 | ; | ||
| 32 | ; Master interrupt controller parameters | ||
| 33 | ; | ||
| 34 | PIC1_CMD = 20H ; 8259A command register. | ||
| 35 | PIC1_INIT = 21H ; 8259A initialization register. | ||
| 36 | PIC1_STAT = 20H ; 8259A status (who interrupted) | ||
| 37 | PIC1_MASK = 21H ; 8259A operation control word #1. | ||
| 38 | ; | ||
| 39 | PIC1_ICW1_VAL = 11H ; Edge trig, 8 interval, cascade, ICW4. | ||
| 40 | PIC1_ICW2_VAL = 08H ; Interrupt vector address. | ||
| 41 | PIC1_ICW3_VAL = 04H ; Slave id. | ||
| 42 | PIC1_ICW4_VAL = 01H ; 8088 mode, norm EOI, non-buf, no nest. | ||
| 43 | ; | ||
| 44 | ; Slave interrupt controller parameters | ||
| 45 | ; | ||
| 46 | PIC2_CMD = 0A0H ; 8259A command register. | ||
| 47 | PIC2_INIT = 0A1H ; 8259A initialization register. | ||
| 48 | PIC2_STAT = 0A0H ; 8259A status (who interrupted) | ||
| 49 | PIC2_MASK = 0A1H ; 8259A operation control word #1. | ||
| 50 | ; | ||
| 51 | PIC2_ICW1_VAL = 11H ; Edge trig, 8 interval, cascade, ICW4. | ||
| 52 | PIC2_ICW2_VAL = 70H ; Interrupt vector address. | ||
| 53 | PIC2_ICW3_VAL = 02H ; Master id. | ||
| 54 | PIC2_ICW4_VAL = 01H ; 8088 mode, norm EOI, non-buf, no nest. | ||
| 55 | ; | ||
| 56 | MASK_DISABLE = 0FFH ; Mask register, no levels allowed. | ||
| 57 | READ_ISR = 0BH ; Command to read PIC In-Service-Reg. | ||
| 58 | EOI = 20H ; End-Of-Interrupt (non-specific). | ||
| 59 | ; | ||
| 60 | IRQ0_ENABLE = 11111110B ; Mask to enable IRQ0. | ||
| 61 | IRQ1_ENABLE = 11111101B ; Mask to enable IRQ1. | ||
| 62 | IRQ2_ENABLE = 11111011B ; Mask to enable IRQ2. | ||
| 63 | IRQ3_ENABLE = 11110111B ; Mask to enable IRQ3. | ||
| 64 | IRQ4_ENABLE = 11101111B ; Mask to enable IRQ4. | ||
| 65 | IRQ5_ENABLE = 11011111B ; Mask to enable IRQ5. | ||
| 66 | IRQ6_ENABLE = 10111111B ; Mask to enable IRQ6. | ||
| 67 | IRQ7_ENABLE = 01111110B ; Mask to enable IRQ7. | ||
| 68 | ; | ||
| 69 | IRQ8_ENABLE = 11111110B ; Mask to enable IRQ8. | ||
| 70 | IRQ9_ENABLE = 11111101B ; Mask to enable IRQ9. | ||
| 71 | IRQ10_ENABLE = 11111011B ; Mask to enable IRQ10. | ||
| 72 | IRQ11_ENABLE = 11110111B ; Mask to enable IRQ11. | ||
| 73 | IRQ12_ENABLE = 11101111B ; Mask to enable IRQ12. | ||
| 74 | IRQ13_ENABLE = 11011111B ; Mask to enable IRQ13. | ||
| 75 | IRQ14_ENABLE = 10111111B ; Mask to enable IRQ14. | ||
| 76 | IRQ15_ENABLE = 01111111B ; Mask to enable IRQ15. | ||
| 77 | ; | ||
| 78 | .list ; end of PIC_DEF.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/PPAGE.ASM b/v4.0/src/MEMM/MEMM/PPAGE.ASM new file mode 100644 index 0000000..677c583 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/PPAGE.ASM | |||
| @@ -0,0 +1,510 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE PPAGE - MODULE to find mappable Physical pages | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: PPAGE - Find Mappable Physical Pages | ||
| 13 | ; | ||
| 14 | ; Version: 0.01 | ||
| 15 | ; | ||
| 16 | ; Date: Aug 1, 1988 | ||
| 17 | ; | ||
| 18 | ; Author: ISP | ||
| 19 | ; COMMENTS** This routine needs extensive work to do a better | ||
| 20 | ; job of identification of unmappable segments. That | ||
| 21 | ; is why we seem to have a whole lot of procedures | ||
| 22 | ; which don't do much now. | ||
| 23 | ;****************************************************************************** | ||
| 24 | ; | ||
| 25 | ; Change Log: | ||
| 26 | ; | ||
| 27 | ; DATE REVISION Description | ||
| 28 | ; -------- -------- -------------------------------------------- | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; Functional Description: | ||
| 31 | ; This module initialises the mappable physical pages in memory. | ||
| 32 | ; It also finds a valid page frame for use. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | .lfcond | ||
| 36 | .386p | ||
| 37 | |||
| 38 | page | ||
| 39 | ;****************************************************************************** | ||
| 40 | ; P U B L I C D E C L A R A T I O N S | ||
| 41 | ;****************************************************************************** | ||
| 42 | |||
| 43 | public mappable_segs | ||
| 44 | public Map_tbl | ||
| 45 | public max_PF | ||
| 46 | public find_phys_pages | ||
| 47 | public exclude_segments | ||
| 48 | public is_page_mappable | ||
| 49 | |||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; L O C A L C O N S T A N T S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | FIRST_SYSTEM_ROM_SEG_HI = 0F000h | ||
| 56 | FIRST_SYSTEM_ROM_SEG_LO = 0E000h | ||
| 57 | LAST_SYSTEM_ROM_SEG = 0FFFFh | ||
| 58 | ; | ||
| 59 | FIRST_VIDEO_MEM_SEG = 0A000h | ||
| 60 | LAST_VIDEO_MEM_SEG = 0BFFFh | ||
| 61 | ; | ||
| 62 | FIRST_CONV_UMAP_SEG = 00000h | ||
| 63 | LAST_CONV_UMAP_SEG = 03FFFh | ||
| 64 | |||
| 65 | |||
| 66 | ;****************************************************************************** | ||
| 67 | ; INCLUDE FILES | ||
| 68 | ;****************************************************************************** | ||
| 69 | include vdmseg.inc ; segment definitions | ||
| 70 | include emm386.inc ;contains the error messages | ||
| 71 | include emmdef.inc ;contains some emm defines | ||
| 72 | |||
| 73 | page | ||
| 74 | ;****************************************************************************** | ||
| 75 | ; E X T E R N A L R E F E R E N C E S | ||
| 76 | ;****************************************************************************** | ||
| 77 | ; | ||
| 78 | ; | ||
| 79 | _DATA segment | ||
| 80 | |||
| 81 | extrn PF_Base:word | ||
| 82 | extrn msg_flag:word | ||
| 83 | |||
| 84 | _DATA ends | ||
| 85 | |||
| 86 | ; | ||
| 87 | LAST segment | ||
| 88 | ; | ||
| 89 | extrn rom_srch:near | ||
| 90 | ; | ||
| 91 | LAST ends | ||
| 92 | |||
| 93 | page | ||
| 94 | ;****************************************************************************** | ||
| 95 | ; S E G M E N T D E F I N I T I O N | ||
| 96 | ;****************************************************************************** | ||
| 97 | |||
| 98 | |||
| 99 | ;****************************************************************************** | ||
| 100 | ; | ||
| 101 | ; Code Segments | ||
| 102 | ; | ||
| 103 | ;****************************************************************************** | ||
| 104 | ; | ||
| 105 | _TEXT segment | ||
| 106 | _TEXT ends | ||
| 107 | |||
| 108 | LAST segment | ||
| 109 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 110 | |||
| 111 | page | ||
| 112 | ;************************************************************************* | ||
| 113 | ; | ||
| 114 | ; initialisation data | ||
| 115 | ; | ||
| 116 | ;************************************************************************* | ||
| 117 | ; table for identifying mappable pages | ||
| 118 | ; | ||
| 119 | mappable_segs label byte | ||
| 120 | db TOT_PHYS_PAGES dup(PAGE_MAPPABLE) ; | ||
| 121 | ; | ||
| 122 | ; table for PF base addresses | ||
| 123 | ; | ||
| 124 | Map_tbl label word | ||
| 125 | dw 0c000h | ||
| 126 | dw 0c400h | ||
| 127 | dw 0c800h | ||
| 128 | dw 0cc00h | ||
| 129 | dw 0d000h | ||
| 130 | dw 0d400h | ||
| 131 | dw 0d800h | ||
| 132 | dw 0dc00h | ||
| 133 | max_PF equ (this byte - Map_tbl) | ||
| 134 | dw 0e000h | ||
| 135 | |||
| 136 | page | ||
| 137 | ;****************************************************************************** | ||
| 138 | ; find_phys_pages: routine to find mappable phsyical pages and a page fr | ||
| 139 | ; | ||
| 140 | ; ENTRY: PF_base set to -1 (user didn't specify apge frame) | ||
| 141 | ; or offset into Map_tbl | ||
| 142 | ; EXIT: mappable_segs array initalised to indicate mappable pages | ||
| 143 | ; first_system_page initialised | ||
| 144 | ; num_system_pages initialised | ||
| 145 | ; PF_Base initalised to page frame | ||
| 146 | ; [msg_flag] set if error to error message number | ||
| 147 | ; USED: none | ||
| 148 | ; | ||
| 149 | ;****************************************************************************** | ||
| 150 | find_phys_pages proc near | ||
| 151 | ; | ||
| 152 | ; start out with all the pages initialised to be mappable except those excluded | ||
| 153 | ; by explicit instruction of the command line. | ||
| 154 | ; | ||
| 155 | |||
| 156 | ; | ||
| 157 | ; exclude segments in the lo end of system memory | ||
| 158 | ; | ||
| 159 | call exclude_conv_RAM | ||
| 160 | |||
| 161 | ; exclude segments in the system ROM area | ||
| 162 | ; | ||
| 163 | call exclude_system_ROM | ||
| 164 | |||
| 165 | ; | ||
| 166 | ; exclude segments in the video area | ||
| 167 | ; | ||
| 168 | call exclude_video_mem | ||
| 169 | |||
| 170 | ; | ||
| 171 | ; then search for option rom's in the area C000 to E000 and exclude the | ||
| 172 | ; segments in which option rom exists. | ||
| 173 | ; | ||
| 174 | call rom_srch ; this searches for option rom's and | ||
| 175 | ; removes the segments of these from | ||
| 176 | ; being mappable | ||
| 177 | ; | ||
| 178 | ; then find the page frame from the information of mappable segs from C000-E000 | ||
| 179 | ; and the user specified page frame (if any). | ||
| 180 | ; | ||
| 181 | call find_pf_base | ||
| 182 | ; | ||
| 183 | ; and then exit | ||
| 184 | ; | ||
| 185 | ret | ||
| 186 | ; | ||
| 187 | find_phys_pages endp | ||
| 188 | |||
| 189 | page | ||
| 190 | ;****************************************************************************** | ||
| 191 | ; find_pf_base: routine to find a valid page frame | ||
| 192 | ; | ||
| 193 | ; ENTRY: PF_base set to -1 (user didn't specify apge frame) | ||
| 194 | ; or index into Map_tbl | ||
| 195 | ; ax = index into Map_tbl from rom_srch on a possible pageframe. | ||
| 196 | ; | ||
| 197 | ; EXIT: PF_base set to page frame segment (C000..E000) on no error | ||
| 198 | ; If error msg_flag set to appropriate error message | ||
| 199 | ; | ||
| 200 | ; USES: NONE | ||
| 201 | ; | ||
| 202 | ;****************************************************************************** | ||
| 203 | find_pf_base proc near | ||
| 204 | ; | ||
| 205 | push ax | ||
| 206 | push bx | ||
| 207 | push cx | ||
| 208 | push si | ||
| 209 | ; | ||
| 210 | ; we have to examine all the possible page frames by looking at the entries | ||
| 211 | ; for the page frame in the mappable_segs array and find all possible page | ||
| 212 | ; frames. the first such valid page frame found is remembered | ||
| 213 | ; | ||
| 214 | |||
| 215 | ; | ||
| 216 | ; initialise | ||
| 217 | ; | ||
| 218 | mov ax,0ffffh ; first possible page frame | ||
| 219 | xor bx,bx ; index into map_tbl | ||
| 220 | ; | ||
| 221 | ; outer loop entry. check for loop termination | ||
| 222 | ; | ||
| 223 | examine_map_tbl_loop: | ||
| 224 | ; | ||
| 225 | cmp bx,MAX_PF ; are we done | ||
| 226 | ja choose_PF ; yes, go to choose page frame | ||
| 227 | ; | ||
| 228 | ; get the page frame segment. convert to phys. page # | ||
| 229 | ; | ||
| 230 | mov si,cs:Map_Tbl[bx] ; | ||
| 231 | shr si,10 | ||
| 232 | ; | ||
| 233 | ; examine the entries for the 4 pages comprising this segment | ||
| 234 | ; | ||
| 235 | mov cx,4 | ||
| 236 | check_pages_loop: | ||
| 237 | cmp cs:mappable_segs[si],PAGE_MAPPABLE | ||
| 238 | jne invalidate_PF | ||
| 239 | inc si | ||
| 240 | loop check_pages_loop | ||
| 241 | |||
| 242 | ;***SUCCESS | ||
| 243 | |||
| 244 | ; | ||
| 245 | ; exit point. pf is valid. see if we already have a pf. if not we store | ||
| 246 | ; this. | ||
| 247 | ; | ||
| 248 | cmp ax,0ffffh ; do we have a pf already? | ||
| 249 | jne skip_get_PF ; skip if we do | ||
| 250 | mov ax,bx ; else store | ||
| 251 | skip_get_PF: | ||
| 252 | ; | ||
| 253 | ; go to examine next PF | ||
| 254 | ; | ||
| 255 | jmp next_PF | ||
| 256 | |||
| 257 | ;***FAILURE | ||
| 258 | |||
| 259 | ; | ||
| 260 | ; exit point. pf is invalid. remove it from map_tbl | ||
| 261 | ; | ||
| 262 | invalidate_PF: | ||
| 263 | mov cs:Map_Tbl[bx],0ffffh ; | ||
| 264 | ; | ||
| 265 | ;***SETUP TO LOOP AGAIN | ||
| 266 | next_PF: | ||
| 267 | ; | ||
| 268 | add bx,2 | ||
| 269 | jmp examine_map_tbl_loop | ||
| 270 | ; | ||
| 271 | choose_PF: | ||
| 272 | ; | ||
| 273 | ; Choosing a page frame. If the user has specified a page frame then | ||
| 274 | ; validate it else give him the page frame we found first. | ||
| 275 | ; | ||
| 276 | ; | ||
| 277 | ; has the user specified a pf. if so go to validate it | ||
| 278 | ; | ||
| 279 | cmp [PF_Base],0ffffh ; | ||
| 280 | jne def_cont2 | ||
| 281 | ; | ||
| 282 | ; user didn't specify a pf. did we find a pf. if so give it else indicate | ||
| 283 | ; error | ||
| 284 | ; | ||
| 285 | cmp ax,0ffffh ; did we find one | ||
| 286 | je no_PF_warn ; if not go to warn the user | ||
| 287 | mov bx,ax | ||
| 288 | mov ax, cs:Map_Tbl[bx] ; get the PF | ||
| 289 | mov [PF_Base],ax ; | ||
| 290 | or [msg_flag],BASE_ADJ_MSG ; | ||
| 291 | jmp pf_xit | ||
| 292 | |||
| 293 | ; | ||
| 294 | ; we don't have a pf. warn the user | ||
| 295 | ; | ||
| 296 | no_PF_warn: | ||
| 297 | or [msg_flag],NO_PF_MSG | ||
| 298 | jmp pf_xit | ||
| 299 | ; | ||
| 300 | ; they specified a base address. Let's make sure it's good | ||
| 301 | ; | ||
| 302 | def_cont2: | ||
| 303 | mov bx,[PF_Base] ; get the offset they specified | ||
| 304 | mov ax,bx ; ax = bx | ||
| 305 | shr ax,1 ; back to 0..8 | ||
| 306 | mov cx,0400h ; length of PF segments | ||
| 307 | mul cx ; addr = 0c000h + (Mx-1)*400h | ||
| 308 | add ax,0c000h | ||
| 309 | mov [PF_Base],ax ; save it | ||
| 310 | |||
| 311 | cmp cs:Map_tbl[bx],0ffffh ; Is this any good? | ||
| 312 | jne pf_xit ; probably | ||
| 313 | or [msg_flag],PF_WARN_MSG ; probably not | ||
| 314 | ; | ||
| 315 | ; we need to ensure that the pages corresponding to the page frame are forced | ||
| 316 | ; into being mappable. this is necessary because we accept the user's discretio | ||
| 317 | ; in forcing a page frame in a certain area. | ||
| 318 | ; | ||
| 319 | mov si,ax ; segment | ||
| 320 | shr si,10 ; phys page# | ||
| 321 | mov cx,4 | ||
| 322 | force_PF_pages: | ||
| 323 | mov cs:mappable_segs[si],PAGE_MAPPABLE | ||
| 324 | inc si | ||
| 325 | loop force_PF_pages | ||
| 326 | |||
| 327 | pf_xit: | ||
| 328 | pop si | ||
| 329 | pop cx | ||
| 330 | pop bx | ||
| 331 | pop ax | ||
| 332 | ret | ||
| 333 | |||
| 334 | find_pf_base endp | ||
| 335 | |||
| 336 | |||
| 337 | ;***********************************************************************; | ||
| 338 | ; exclude_video_mem ; | ||
| 339 | ; ; | ||
| 340 | ; Excludes the segments between A000 and C000. ; | ||
| 341 | ; ; | ||
| 342 | ; input: none ; | ||
| 343 | ; ; | ||
| 344 | ; returns: none ; | ||
| 345 | ; ; | ||
| 346 | ; uses: ; | ||
| 347 | ; ; | ||
| 348 | ; calls:exclude_segments ; | ||
| 349 | ; ; | ||
| 350 | ; History: ; | ||
| 351 | ; ISP (isp). Wrote it. ; | ||
| 352 | ;***********************************************************************; | ||
| 353 | exclude_video_mem proc near | ||
| 354 | ; | ||
| 355 | push bx | ||
| 356 | push ax | ||
| 357 | ; | ||
| 358 | mov bx,FIRST_VIDEO_MEM_SEG | ||
| 359 | mov ax,LAST_VIDEO_MEM_SEG | ||
| 360 | call exclude_segments | ||
| 361 | ; | ||
| 362 | pop ax | ||
| 363 | pop bx | ||
| 364 | ret | ||
| 365 | ; | ||
| 366 | exclude_video_mem endp | ||
| 367 | |||
| 368 | ;***********************************************************************; | ||
| 369 | ; exclude_system_ROM ; | ||
| 370 | ; ; | ||
| 371 | ; Excludes the segments between A000 and C000. ; | ||
| 372 | ; ; | ||
| 373 | ; input: none ; | ||
| 374 | ; ; | ||
| 375 | ; returns: none ; | ||
| 376 | ; ; | ||
| 377 | ; uses: ; | ||
| 378 | ; ; | ||
| 379 | ; calls:exclude_segments ; | ||
| 380 | ; ; | ||
| 381 | ; History: ; | ||
| 382 | ; ISP (isp). Wrote it. ; | ||
| 383 | ;***********************************************************************; | ||
| 384 | exclude_system_ROM proc near | ||
| 385 | ; | ||
| 386 | push bx | ||
| 387 | push ax | ||
| 388 | ; | ||
| 389 | ifndef NOHIMEM | ||
| 390 | mov bx,FIRST_SYSTEM_ROM_SEG_LO | ||
| 391 | else | ||
| 392 | mov bx,FIRST_SYSTEM_ROM_SEG_HI | ||
| 393 | endif | ||
| 394 | |||
| 395 | mov ax,LAST_SYSTEM_ROM_SEG | ||
| 396 | call exclude_segments | ||
| 397 | ; | ||
| 398 | pop ax | ||
| 399 | pop bx | ||
| 400 | ret | ||
| 401 | ; | ||
| 402 | exclude_system_ROM endp | ||
| 403 | |||
| 404 | ;***********************************************************************; | ||
| 405 | ; exclude_conv_RAM ; | ||
| 406 | ; ; | ||
| 407 | ; Excludes segments between 0000 and 4000h ; | ||
| 408 | ; ; | ||
| 409 | ; inputs:none ; | ||
| 410 | ; ; | ||
| 411 | ; returns: none ; | ||
| 412 | ; ; | ||
| 413 | ; History: ; | ||
| 414 | ; ISP (isp). Wrote it | ||
| 415 | ;***********************************************************************; | ||
| 416 | exclude_conv_RAM proc near | ||
| 417 | ; | ||
| 418 | push bx | ||
| 419 | push ax | ||
| 420 | ; | ||
| 421 | mov bx,FIRST_CONV_UMAP_SEG | ||
| 422 | mov ax,LAST_CONV_UMAP_SEG | ||
| 423 | call exclude_segments | ||
| 424 | ; | ||
| 425 | pop ax | ||
| 426 | pop bx | ||
| 427 | ret | ||
| 428 | ; | ||
| 429 | exclude_conv_RAM endp | ||
| 430 | |||
| 431 | ;-----------------------------------------------------------------------; | ||
| 432 | ; exclude_segments ; | ||
| 433 | ; ; | ||
| 434 | ; Excludes the given segments from the memory map. ; | ||
| 435 | ; ; | ||
| 436 | ; Arguments: ; | ||
| 437 | ; AX = high segment ; | ||
| 438 | ; BX = low segment ; | ||
| 439 | ; Returns: ; | ||
| 440 | ; nothing ; | ||
| 441 | ; Alters: ; | ||
| 442 | ; AX,BX ; | ||
| 443 | ; Calls: ; | ||
| 444 | ; nothing ; | ||
| 445 | ; History: ; | ||
| 446 | ; ISP (isp). modified from ps2emm sources. ; | ||
| 447 | ;-----------------------------------------------------------------------; | ||
| 448 | exclude_segments proc near | ||
| 449 | ; | ||
| 450 | push cx | ||
| 451 | push es | ||
| 452 | push di | ||
| 453 | ; | ||
| 454 | ; fix the segments to form physical page numbers | ||
| 455 | ; | ||
| 456 | mov cl,10 ; to convert segment to physical page # | ||
| 457 | shr ax,cl | ||
| 458 | shr bx,cl | ||
| 459 | sub ax,bx | ||
| 460 | jb exclude_segments_done | ||
| 461 | inc ax | ||
| 462 | mov cx,ax | ||
| 463 | ; | ||
| 464 | ; get addressing into mappable_segs array | ||
| 465 | ; | ||
| 466 | push cs | ||
| 467 | pop es | ||
| 468 | assume es:nothing | ||
| 469 | lea di, mappable_segs[bx] | ||
| 470 | mov al,PAGE_NOT_MAPPABLE | ||
| 471 | cld | ||
| 472 | rep stosb | ||
| 473 | exclude_segments_done: | ||
| 474 | ; | ||
| 475 | pop di | ||
| 476 | pop es | ||
| 477 | pop cx | ||
| 478 | ret | ||
| 479 | ; | ||
| 480 | exclude_segments endp | ||
| 481 | |||
| 482 | ;-----------------------------------------------------------------------; | ||
| 483 | ; is_page_mappable ; | ||
| 484 | ; ; | ||
| 485 | ; specifies whether a given physical page is mappable or not. ; | ||
| 486 | ; ; | ||
| 487 | ; Arguments: ; | ||
| 488 | ; si = physical page ; | ||
| 489 | ; Returns: ; | ||
| 490 | ; ZF set if mappable ; | ||
| 491 | ; ZF clear if not mappable ; | ||
| 492 | ; Alters: ; | ||
| 493 | ; flags ; | ||
| 494 | ; Calls: ; | ||
| 495 | ; nothing ; | ||
| 496 | ; History: ; | ||
| 497 | ; ISP (isp). 8/29/88 ; | ||
| 498 | ;-----------------------------------------------------------------------; | ||
| 499 | is_page_mappable proc near | ||
| 500 | ; | ||
| 501 | cmp cs:mappable_segs[si],PAGE_MAPPABLE | ||
| 502 | ret | ||
| 503 | ; | ||
| 504 | is_page_mappable endp | ||
| 505 | |||
| 506 | LAST ends ; End of segment | ||
| 507 | ; | ||
| 508 | |||
| 509 | end ; End of module | ||
| 510 | |||
diff --git a/v4.0/src/MEMM/MEMM/PRINT.ASM b/v4.0/src/MEMM/MEMM/PRINT.ASM new file mode 100644 index 0000000..91d8571 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/PRINT.ASM | |||
| @@ -0,0 +1,424 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title PRINT.ASM - Protected Mode Print Routines | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMMD.EXE - MICROSOFT Expanded Memory Manager 386 DEBUG Driver | ||
| 11 | ; | ||
| 12 | ; Module: PRINT.ASM - Protected Mode Print Routines | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 29 | ; 07/05/86 0.04 Moved to DCODE segment | ||
| 30 | ; 07/06/86 0.04 moved data to DDATA segment | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; Functional Description: | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | .lfcond ; list false conditionals | ||
| 38 | .386p | ||
| 39 | |||
| 40 | public PrintString | ||
| 41 | public PrintHex | ||
| 42 | public kputc | ||
| 43 | public RowCol | ||
| 44 | public IsReal | ||
| 45 | |||
| 46 | NAME print | ||
| 47 | |||
| 48 | ;** print - cga simple print routines | ||
| 49 | ; | ||
| 50 | include VDMseg.inc | ||
| 51 | include VDMsel.inc | ||
| 52 | include desc.inc | ||
| 53 | |||
| 54 | ;*** IsReal - determine mode of cpu | ||
| 55 | ; | ||
| 56 | ; This routine is useful when writing dual mode code. | ||
| 57 | ; It returns with 'Z' = 1 if the cpu is in real mode, | ||
| 58 | ; otherwise 'Z' = 0. | ||
| 59 | ; | ||
| 60 | ; ENTRY DUAL MODE | ||
| 61 | ; | ||
| 62 | ; EXIT 'Z' = 1 (protected mode), 0 (real mode) | ||
| 63 | ; | ||
| 64 | ; USES flags | ||
| 65 | ; | ||
| 66 | _TEXT segment | ||
| 67 | |||
| 68 | assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing | ||
| 69 | |||
| 70 | IsReal proc near | ||
| 71 | |||
| 72 | push ax | ||
| 73 | smsw ax | ||
| 74 | xor al, 0ffh | ||
| 75 | and al, 1 | ||
| 76 | pop ax | ||
| 77 | ret ; returns with flags set | ||
| 78 | |||
| 79 | IsReal endp | ||
| 80 | |||
| 81 | _TEXT ends | ||
| 82 | |||
| 83 | ;*** kputc - write character/attribute to screen | ||
| 84 | ; | ||
| 85 | ; This is a simple character output routine. It does not | ||
| 86 | ; interleave writes to video memory with the 6845. It | ||
| 87 | ; does not update the cursor position. It does not understand | ||
| 88 | ; anything except a CGA in 80x25 text mode. | ||
| 89 | ; | ||
| 90 | ; ENTRY PROTECTED MODE | ||
| 91 | ; AX - character-attribute to write | ||
| 92 | ; DS - kernel data selector | ||
| 93 | ; | ||
| 94 | ; EXIT none - character written | ||
| 95 | ; | ||
| 96 | ; USES AX, flags | ||
| 97 | ; | ||
| 98 | |||
| 99 | _DATA segment | ||
| 100 | RowCol dw 0 | ||
| 101 | _DATA ends | ||
| 102 | |||
| 103 | CR equ 0dh ; carriage return | ||
| 104 | LF equ 0ah ; line feed | ||
| 105 | TAB equ 9 ; tab | ||
| 106 | BS equ 8 ; backspace | ||
| 107 | |||
| 108 | COLOUR_PARA equ 0b800h | ||
| 109 | |||
| 110 | _TEXT segment | ||
| 111 | |||
| 112 | assume cs:_TEXT, ds:_DATA, es:nothing, ss:nothing | ||
| 113 | |||
| 114 | kputc proc far | ||
| 115 | |||
| 116 | push bx ; save callers regs | ||
| 117 | push cx | ||
| 118 | push dx | ||
| 119 | push si | ||
| 120 | push di | ||
| 121 | push es | ||
| 122 | push ds | ||
| 123 | |||
| 124 | call IsReal ; need dual mode access | ||
| 125 | jnz kp10 | ||
| 126 | mov dx, VDMD_GSEL ; selector for protected mode | ||
| 127 | jmp kp11 | ||
| 128 | kp10: | ||
| 129 | mov dx, seg _DATA ; para for real mode | ||
| 130 | kp11: | ||
| 131 | push dx ; save this segment for later | ||
| 132 | |||
| 133 | mov ds, dx ; DS -> data segment | ||
| 134 | mov dx, ds:[RowCol] ; DX = current row/col | ||
| 135 | |||
| 136 | cmp al, CR ; is character a CR? | ||
| 137 | jne kp1 | ||
| 138 | |||
| 139 | mov dl, 0 ; yes, go to column 0 | ||
| 140 | jmp kp3 ; jump to common code | ||
| 141 | kp1: | ||
| 142 | |||
| 143 | cmp al, LF ; is character a LF? | ||
| 144 | jne kp2 | ||
| 145 | |||
| 146 | inc dh ; yes, go to next row | ||
| 147 | jmp kp3 ; jump to common code | ||
| 148 | kp2: | ||
| 149 | |||
| 150 | cmp al, TAB ; is it a tab | ||
| 151 | jne kp12 | ||
| 152 | and dl, 0f8h ; mask off low 3 bits (8 ch) | ||
| 153 | add dl, 8 ; move to next tab position | ||
| 154 | jmp kp3 ; jmp to common code | ||
| 155 | kp12: | ||
| 156 | |||
| 157 | cmp al, BS ; is it backspace | ||
| 158 | jne kp13 | ||
| 159 | dec dl ; back up one column | ||
| 160 | jmp kp3 ; goto common code | ||
| 161 | kp13: | ||
| 162 | ; Must be ordinary character. Write it to screen, update position | ||
| 163 | |||
| 164 | push ax ; save char/attr | ||
| 165 | |||
| 166 | mov al, dh ; AL = row | ||
| 167 | mov ah, 80 ; multiplier, 80 char per row | ||
| 168 | mul ah ; AX = cell at start of row | ||
| 169 | mov bh, 0 | ||
| 170 | mov bl, dl ; BX = column | ||
| 171 | add bx, ax ; BX = cell | ||
| 172 | shl bx, 1 ; BX = byte offset of cell | ||
| 173 | |||
| 174 | call IsReal ; bi-modal access to screen | ||
| 175 | jnz kp6 | ||
| 176 | mov ax, COLOUR_GSEL ; screen selector for protected mode | ||
| 177 | jmp kp7 | ||
| 178 | kp6: | ||
| 179 | mov ax, COLOUR_PARA ; screen para for real mode | ||
| 180 | kp7: | ||
| 181 | mov es, ax ; ES -> screen | ||
| 182 | |||
| 183 | pop es:[bx] ; write character | ||
| 184 | inc dl ; update column | ||
| 185 | kp3: | ||
| 186 | ; Common code, first check for line wrap: | ||
| 187 | |||
| 188 | cmp dl, 80 ; beyond rhs of screen? | ||
| 189 | jl kp4 | ||
| 190 | mov dl, 0 ; go to col 0 | ||
| 191 | inc dh ; and move to next line | ||
| 192 | kp4: | ||
| 193 | ; Now check for scroll needed: | ||
| 194 | |||
| 195 | cmp dh, 25 ; are we off end of screen? | ||
| 196 | jl kp5 | ||
| 197 | |||
| 198 | ; Now scroll screen | ||
| 199 | |||
| 200 | call IsReal ; bi-modal access to screen | ||
| 201 | jnz kp8 | ||
| 202 | mov ax, COLOUR_GSEL ; screen selector for protected mode | ||
| 203 | jmp kp9 | ||
| 204 | kp8: | ||
| 205 | mov ax, COLOUR_PARA ; screen para for real mode | ||
| 206 | kp9: | ||
| 207 | mov ds, ax ; DS -> screen | ||
| 208 | mov es, ax ; ES -> screen | ||
| 209 | |||
| 210 | mov di, 0 ; ES:DI = copy destination | ||
| 211 | mov si, 160 ; DS:SI = copy source | ||
| 212 | mov cx, 2000-80 ; copy word count | ||
| 213 | cld | ||
| 214 | rep movsw ; scroll | ||
| 215 | |||
| 216 | ; Blank bottom line | ||
| 217 | |||
| 218 | mov al, ' ' | ||
| 219 | mov ah, 7 ; AX = blank character | ||
| 220 | |||
| 221 | mov cx, 80 ; number of cells to blank | ||
| 222 | mov di, 4000-160 ; ES:DI = start point | ||
| 223 | rep stosw | ||
| 224 | |||
| 225 | ; Update position | ||
| 226 | |||
| 227 | mov dh, 24 ; new row | ||
| 228 | kp5: | ||
| 229 | pop ds ; set DS to data again | ||
| 230 | mov ds:[RowCol], dx ; update row/col | ||
| 231 | |||
| 232 | ; call SetCursor | ||
| 233 | |||
| 234 | pop ds ; restore regs | ||
| 235 | pop es | ||
| 236 | pop di | ||
| 237 | pop si | ||
| 238 | pop dx | ||
| 239 | pop cx | ||
| 240 | pop bx | ||
| 241 | |||
| 242 | ret | ||
| 243 | |||
| 244 | kputc endp | ||
| 245 | _TEXT ends | ||
| 246 | |||
| 247 | |||
| 248 | ;*** SetCursor - updates cursor position | ||
| 249 | ; | ||
| 250 | ; This routine reprograms the 6845 cursor position, and | ||
| 251 | ; stores the new cursor position in the ROM bios data area. | ||
| 252 | ; | ||
| 253 | ; ENTRY DUAL MODE | ||
| 254 | ; DH, DL = row, col | ||
| 255 | ; | ||
| 256 | ; EXIT cursor updated | ||
| 257 | ; | ||
| 258 | ; USES ax, bx, cx, flags | ||
| 259 | ; | ||
| 260 | |||
| 261 | CRT_COLS equ 04ah | ||
| 262 | CURSOR_POSN equ 050h | ||
| 263 | CRT_START equ 04eh | ||
| 264 | ADDR_6845 equ 063h | ||
| 265 | |||
| 266 | _TEXT segment | ||
| 267 | |||
| 268 | assume cs:_TEXT, ds:_DATA, es:nothing, ss:nothing | ||
| 269 | |||
| 270 | SetCursor proc near | ||
| 271 | |||
| 272 | push ds | ||
| 273 | mov bx, 40h | ||
| 274 | mov ds, bx | ||
| 275 | |||
| 276 | ; Save new position in BIOS data area | ||
| 277 | |||
| 278 | mov ds:[CURSOR_POSN], dx | ||
| 279 | |||
| 280 | ; Calculate offset on screen | ||
| 281 | |||
| 282 | mov al, dh ; row | ||
| 283 | mul byte ptr ds:[CRT_COLS] ; row * cols | ||
| 284 | mov bl, dl ; bl = column | ||
| 285 | mov bh, 0 ; bx = column | ||
| 286 | add ax, bx ; ax = offset in screen | ||
| 287 | sal ax, 1 ; double for attribute bytes | ||
| 288 | mov cx, ds:[CRT_START] ; cx = start point of screen | ||
| 289 | add cx, ax ; cx = offset of cursor | ||
| 290 | sar cx, 1 ; convert to char count only | ||
| 291 | |||
| 292 | ; Now program 6845 | ||
| 293 | |||
| 294 | mov al, 14 ; 6845 register | ||
| 295 | mov dx, ds:[ADDR_6845] ; base port # | ||
| 296 | out dx, al | ||
| 297 | inc dx | ||
| 298 | jmp short $+2 | ||
| 299 | |||
| 300 | mov al, ch | ||
| 301 | out dx, al | ||
| 302 | dec dx | ||
| 303 | jmp short $+2 | ||
| 304 | |||
| 305 | mov al, 15 | ||
| 306 | out dx, al | ||
| 307 | inc dx | ||
| 308 | jmp short $+2 | ||
| 309 | |||
| 310 | mov al, cl | ||
| 311 | out dx, al | ||
| 312 | |||
| 313 | pop ds | ||
| 314 | |||
| 315 | ret | ||
| 316 | |||
| 317 | SetCursor endp | ||
| 318 | _TEXT ends | ||
| 319 | |||
| 320 | |||
| 321 | ;*** PrintString - prints a message on console | ||
| 322 | ; | ||
| 323 | ; This routine calls the "kernel" to print a string | ||
| 324 | ; one character at a time. | ||
| 325 | ; | ||
| 326 | ; ENTRY 286 PROTECTED MODE | ||
| 327 | ; DS - DATA3_SEL | ||
| 328 | ; ES - DATA3_SEL | ||
| 329 | ; SI - offset in DS of null terminated string to print | ||
| 330 | ; | ||
| 331 | ; EXIT String printed | ||
| 332 | ; | ||
| 333 | ; USES Flags | ||
| 334 | ; | ||
| 335 | |||
| 336 | _TEXT segment | ||
| 337 | |||
| 338 | assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing | ||
| 339 | |||
| 340 | PrintString proc near | ||
| 341 | |||
| 342 | cld ; set up for string ops | ||
| 343 | push si ; save callers regs | ||
| 344 | push ax | ||
| 345 | |||
| 346 | pr1: ; loop printing until null | ||
| 347 | lodsb ; al = char to print | ||
| 348 | and al, al ; terminator ? | ||
| 349 | je pr2 | ||
| 350 | mov ah, 7 ; attribute | ||
| 351 | |||
| 352 | db 9ah ; far call | ||
| 353 | dw offset _TEXT:kputc ; offset | ||
| 354 | dw VDMC_GSEL ; selector | ||
| 355 | |||
| 356 | jmp pr1 ; back for more | ||
| 357 | pr2: | ||
| 358 | pop ax ; restore callers regs | ||
| 359 | pop si | ||
| 360 | |||
| 361 | ret | ||
| 362 | |||
| 363 | PrintString endp | ||
| 364 | |||
| 365 | _TEXT ends | ||
| 366 | |||
| 367 | ;*** Hex2String | ||
| 368 | ; | ||
| 369 | ; Convert content of AX into 4 Hex digits string at ES:DI | ||
| 370 | ; | ||
| 371 | ; ENTRY AX value to convert | ||
| 372 | ; ES:DI storage string location | ||
| 373 | ; | ||
| 374 | |||
| 375 | _TEXT segment | ||
| 376 | |||
| 377 | assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing | ||
| 378 | |||
| 379 | PutHexChar proc near | ||
| 380 | |||
| 381 | cmp al,9 | ||
| 382 | ja PHC_AF | ||
| 383 | add al,30h | ||
| 384 | jmp PHC_exit | ||
| 385 | PHC_AF: | ||
| 386 | add al,(41h - 0ah) | ||
| 387 | PHC_exit: | ||
| 388 | push ax | ||
| 389 | mov ah,7 | ||
| 390 | db 9ah ; far call | ||
| 391 | dw offset _TEXT:kputc ; offset | ||
| 392 | dw VDMC_GSEL ; selector | ||
| 393 | pop ax | ||
| 394 | ret | ||
| 395 | |||
| 396 | PutHexChar endp | ||
| 397 | |||
| 398 | PrintHex proc near | ||
| 399 | |||
| 400 | cld | ||
| 401 | |||
| 402 | xchg al,ah | ||
| 403 | push ax | ||
| 404 | shr al,4 | ||
| 405 | call PutHexChar | ||
| 406 | pop ax | ||
| 407 | and al,0fh | ||
| 408 | call PutHexChar | ||
| 409 | xchg al,ah | ||
| 410 | push ax | ||
| 411 | shr al,4 | ||
| 412 | call PutHexChar | ||
| 413 | pop ax | ||
| 414 | and al,0fh | ||
| 415 | call PutHexChar | ||
| 416 | |||
| 417 | ret | ||
| 418 | |||
| 419 | PrintHex endp | ||
| 420 | |||
| 421 | _TEXT ends | ||
| 422 | |||
| 423 | end | ||
| 424 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/RETREAL.ASM b/v4.0/src/MEMM/MEMM/RETREAL.ASM new file mode 100644 index 0000000..8ffc602 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/RETREAL.ASM | |||
| @@ -0,0 +1,228 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title RetReal - Return-To-Real routine(s) for the 386 | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: RetReal - Return-To-Real routine(s) for the 386 | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: February 20, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 02/20/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/01/86 Removed Real386a (loadall version) and left only | ||
| 29 | ; RetReal via PE bit | ||
| 30 | ; 06/21/86 0.02 Saved Eax | ||
| 31 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 32 | ; 07/02/86 0.03 Reset TSS busy bit | ||
| 33 | ; 07/05/86 0.04 Added Real_Seg label for _TEXT fixup | ||
| 34 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional Description: | ||
| 39 | ; | ||
| 40 | ; This module contains the routine RetReal which goes from Ring 0 protected | ||
| 41 | ; mode to Real Mode by resetting the PE bit (and the PG bit). | ||
| 42 | ; | ||
| 43 | ; NOTE: this module only works on the B0 and later parts. The A2 part | ||
| 44 | ; will leave the CS non writeable. | ||
| 45 | ; | ||
| 46 | ;****************************************************************************** | ||
| 47 | .lfcond ; list false conditionals | ||
| 48 | .386p | ||
| 49 | page | ||
| 50 | ;****************************************************************************** | ||
| 51 | ; P U B L I C D E C L A R A T I O N S | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; | ||
| 54 | public RetReal | ||
| 55 | public Real_Seg | ||
| 56 | |||
| 57 | page | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; I N C L U D E F I L E S | ||
| 60 | ;****************************************************************************** | ||
| 61 | |||
| 62 | include VDMSEG.INC | ||
| 63 | include VDMSEL.INC | ||
| 64 | include INSTR386.INC | ||
| 65 | include OEMDEP.INC | ||
| 66 | |||
| 67 | ; | ||
| 68 | ;****************************************************************************** | ||
| 69 | ; E X T E R N A L R E F E R E N C E S | ||
| 70 | ;****************************************************************************** | ||
| 71 | ; | ||
| 72 | _DATA segment | ||
| 73 | extrn Active_Status:byte | ||
| 74 | _DATA ends | ||
| 75 | |||
| 76 | _TEXT segment | ||
| 77 | |||
| 78 | extrn SelToSeg:near ; selector to segment (I286) | ||
| 79 | extrn DisableA20:near ; disable A20 line (MODESW) | ||
| 80 | |||
| 81 | _TEXT ends | ||
| 82 | ;****************************************************************************** | ||
| 83 | ; L O C A L C O N S T A N T S | ||
| 84 | ;****************************************************************************** | ||
| 85 | ; | ||
| 86 | FALSE equ 0 | ||
| 87 | TRUE equ not FALSE | ||
| 88 | |||
| 89 | page | ||
| 90 | ;****************************************************************************** | ||
| 91 | ; S E G M E N T D E F I N I T I O N | ||
| 92 | ;****************************************************************************** | ||
| 93 | |||
| 94 | _TEXT segment | ||
| 95 | assume cs:_TEXT, ds:DGROUP | ||
| 96 | |||
| 97 | ;*** RetReal - cause a 386 mode switch to real mode | ||
| 98 | ; | ||
| 99 | ; ENTRY Ring 0 protected mode | ||
| 100 | ; CLI - interrupts disabled | ||
| 101 | ; NMI should also be disabled here. | ||
| 102 | ifndef NOHIMEM | ||
| 103 | ; FS = Diag segment selector | ||
| 104 | endif | ||
| 105 | ; | ||
| 106 | ; EXIT Real Mode | ||
| 107 | ; DGROUP:[Active_Status] = 0 | ||
| 108 | ; CS = _TEXT | ||
| 109 | ; DS = ES = FS = GS = DGROUP | ||
| 110 | ; SS = stack segment | ||
| 111 | ; general registers preserved | ||
| 112 | ; flags modified | ||
| 113 | ; interrupts disabled | ||
| 114 | ; A20 disabled | ||
| 115 | ifndef NOHIMEM | ||
| 116 | ; high system memory LOCKED | ||
| 117 | endif | ||
| 118 | ; | ||
| 119 | ; USES see exit conditions above | ||
| 120 | ; | ||
| 121 | ; DESCRIPTION | ||
| 122 | ; | ||
| 123 | real_gdt label qword | ||
| 124 | real_idt dw 0FFFFh ; limit | ||
| 125 | dw 0000 ; base | ||
| 126 | dw 0000 | ||
| 127 | dw 0000 ; just in case | ||
| 128 | |||
| 129 | public RetReal | ||
| 130 | RetReal proc near | ||
| 131 | PUSH_EAX ; save two scratch registers | ||
| 132 | push bx | ||
| 133 | cli ; disable ints | ||
| 134 | |||
| 135 | smsw ax ;check to see if we are in real mode | ||
| 136 | test ax,1 | ||
| 137 | jnz rl386_a ;jump if in protected mode | ||
| 138 | sti | ||
| 139 | pop bx | ||
| 140 | POP_EAX | ||
| 141 | ret ;otherwise return | ||
| 142 | |||
| 143 | rl386_a: | ||
| 144 | |||
| 145 | ; | ||
| 146 | ; reset TSS busy bit before returning to Real Mode | ||
| 147 | ; | ||
| 148 | mov ax, GDTD_GSEL | ||
| 149 | mov es, ax ; ES:0 = ptr to gdt | ||
| 150 | |||
| 151 | and byte ptr ES:[TSS_GSEL + 5], 11111101B | ||
| 152 | |||
| 153 | ; | ||
| 154 | ; lock high system ROM before returning to real | ||
| 155 | ; | ||
| 156 | HwTabLock | ||
| 157 | |||
| 158 | ; | ||
| 159 | ; First save return ss:sp. We have to translate | ||
| 160 | ; the current ss (a selector) into a segment number. | ||
| 161 | ; Calculate a real mode segment corresponding to the | ||
| 162 | ; current protected mode stack selector base address. | ||
| 163 | ; | ||
| 164 | ; We get the base address from the descriptor table, | ||
| 165 | ; and convert it to a paragraph number. | ||
| 166 | ; | ||
| 167 | mov bx,ss ; bx = selector for stack | ||
| 168 | call SelToSeg ; AX = segment number for SS | ||
| 169 | mov bx,ax ; BX = setup stack segment | ||
| 170 | ; | ||
| 171 | ; | ||
| 172 | ; Intel shows DS,ES,FS,GS,and SS set up to make sure 'Real Mode' type | ||
| 173 | ; access rights, and limit are installed. In this program, that happens | ||
| 174 | ; to already be the case, but for general purposeness, VDMD_GSEL fits | ||
| 175 | ; the bill. | ||
| 176 | ; | ||
| 177 | mov ax,VDMD_GSEL ; selector with real mode attributes | ||
| 178 | mov ds,ax | ||
| 179 | mov es,ax | ||
| 180 | mov ss,ax | ||
| 181 | MOV_FS_AX | ||
| 182 | MOV_GS_AX | ||
| 183 | ; | ||
| 184 | ; Intel recommends the following code for resetting the PE bit. Mine | ||
| 185 | ; works OK, but maybe it's not general purpose enough (I was counting | ||
| 186 | ; on knowing that paging wasn't enabled). | ||
| 187 | ; | ||
| 188 | MOV_EAX_CR0 ; get CR0 | ||
| 189 | |||
| 190 | OP32 | ||
| 191 | and ax,0FFFEh ; force real mode and shut down paging | ||
| 192 | dw 07FFFh ; (mov eax,07FFFFFFEh) | ||
| 193 | |||
| 194 | MOV_CR0_EAX ; set CR0 | ||
| 195 | |||
| 196 | ; flush prefetched instructions with: | ||
| 197 | db 0EAh ; Far Jump opcode | ||
| 198 | dw offset _TEXT:rl386_b ; destination offset | ||
| 199 | Real_Seg label word | ||
| 200 | dw _TEXT ; destination segment | ||
| 201 | rl386_b: | ||
| 202 | OP32 ; load up full IDT address | ||
| 203 | lidt qword ptr cs:[real_idt] | ||
| 204 | |||
| 205 | sti | ||
| 206 | |||
| 207 | MOV_EAX_CR3 ; get CR3 | ||
| 208 | MOV_CR3_EAX ; set CR3 => clear TLB | ||
| 209 | |||
| 210 | mov ss,bx ; ss = real mode stack segment | ||
| 211 | mov ax,DGROUP | ||
| 212 | mov ds,ax | ||
| 213 | mov es,ax | ||
| 214 | MOV_FS_AX | ||
| 215 | MOV_GS_AX | ||
| 216 | |||
| 217 | mov [Active_Status],0 ; rest VDM status | ||
| 218 | |||
| 219 | call DisableA20 ; disable A20 line | ||
| 220 | |||
| 221 | pop bx | ||
| 222 | POP_EAX | ||
| 223 | ret ; *** RETURN *** | ||
| 224 | RetReal endp | ||
| 225 | |||
| 226 | _TEXT ends | ||
| 227 | end | ||
| 228 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU b/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU new file mode 100644 index 0000000..774afb1 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ROMSTRUC.EQU - structure of the option ROM headers. | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 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 MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | |||
| 31 | OPTION_ROM STRUC | ||
| 32 | ROM_RECOGNITION DW ? ; HOLDS 0AA55 WORD IF REAL OPTION ROM | ||
| 33 | ROM_LEN DB ? ; BYTE HOLDING ROM SIZE / 512 | ||
| 34 | ROM_ENTRY DB ? ; WHERE CODE STARTS IN OPTION ROM | ||
| 35 | OPTION_ROM ENDS | ||
| 36 | |||
| 37 | .list ; end of ROMSTRUC.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU b/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU new file mode 100644 index 0000000..2ee4418 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ROMXBIOS.EQU - ROM Extra BIOS function calls | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 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 MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | |||
| 31 | XBIOS equ 15h ; Extra BIOS functions | ||
| 32 | DEV_OPEN equ 80h ; - device open dummy call | ||
| 33 | DEV_CLOSE equ 81h ; - device close dummy call | ||
| 34 | PROG_TERM equ 82h ; - program terminate | ||
| 35 | EVENT_WAIT equ 83h ; - Event Wait | ||
| 36 | JOYSTICK equ 84h ; - joystick | ||
| 37 | SYS_REQ equ 85h ; - sys request key routine | ||
| 38 | UNCOND_WAIT equ 86h ; - unconditional Wait | ||
| 39 | MOVE_BLK equ 87h ; - move block | ||
| 40 | EXT_MEM equ 88h ; - extended memory size | ||
| 41 | ENTER_PROT equ 89h ; - enter protected mode | ||
| 42 | DEV_WAIT equ 90h ; - Device Wait | ||
| 43 | DEV_POST equ 91h ; - Device Post | ||
| 44 | |||
| 45 | .list ; end of ROMXBIOS.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM b/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM new file mode 100644 index 0000000..77da48a --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM | |||
| @@ -0,0 +1,317 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ; | ||
| 4 | page 58,132 | ||
| 5 | ;****************************************************************************** | ||
| 6 | title ROM_SRCH - search for option ROMs | ||
| 7 | ;****************************************************************************** | ||
| 8 | ; | ||
| 9 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 10 | ; | ||
| 11 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 12 | ; | ||
| 13 | ; Module: ROM_SRCH - search for option ROMS and RAM | ||
| 14 | ; | ||
| 15 | ; Version: 0.04 | ||
| 16 | ; | ||
| 17 | ; Date : June 5,1986 | ||
| 18 | ; | ||
| 19 | ; Authors: SP, BT | ||
| 20 | ; | ||
| 21 | ;****************************************************************************** | ||
| 22 | ; | ||
| 23 | ; CHANGES: | ||
| 24 | ; | ||
| 25 | ; DATE REVISION DESCRIPTION | ||
| 26 | ; -------- -------- ------------------------------------------------------ | ||
| 27 | ; 06/05/86 Original Adapted from ROM code | ||
| 28 | ; 06/25/86 0.02 Fixed upd_map. | ||
| 29 | ; 06/26/86 0.02 Fixed upd_map (again) and ram_srch | ||
| 30 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 31 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 32 | ; 08/01/88 Updated to identify mappable segs between C000 and E000 | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | page | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional description: | ||
| 39 | ; | ||
| 40 | ; This module contains the code that scans the ROM at the segment | ||
| 41 | ; supplied in register AX looking for ROMs on hardware interface | ||
| 42 | ; boards. The layout of each valid ROM is as follows: | ||
| 43 | ; | ||
| 44 | ; OFFSET +-----------------------+ | ||
| 45 | ; 0 | 55h | | ||
| 46 | ; +-----------------------+ | ||
| 47 | ; 1 | AAh | | ||
| 48 | ; +-----------------------+ | ||
| 49 | ; 2 | ROM size / 512 | | ||
| 50 | ; +-----------------------+ | ||
| 51 | ; 3 | Start of init code | | ||
| 52 | ; : | ||
| 53 | ; n-1 | | | ||
| 54 | ; +-----------------------+ | ||
| 55 | ; (Sum of all bytes MOD 100h is 00h.) | ||
| 56 | ; | ||
| 57 | ; This module also contains the code to search and vector to VDU | ||
| 58 | ; roms (C000:0 to C000:7800 in 2K increments). | ||
| 59 | ; | ||
| 60 | ;****************************************************************************** | ||
| 61 | page | ||
| 62 | .386P | ||
| 63 | ; | ||
| 64 | ;****************************************************************************** | ||
| 65 | ; Public Declarations | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; | ||
| 68 | public rom_srch ; Search and Vector to option ROMs. | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; Externs | ||
| 71 | ;****************************************************************************** | ||
| 72 | LAST segment | ||
| 73 | extrn Map_tbl:word | ||
| 74 | extrn max_PF:abs | ||
| 75 | extrn mappable_segs:byte | ||
| 76 | extrn exclude_segments:near | ||
| 77 | |||
| 78 | LAST ends | ||
| 79 | ; | ||
| 80 | ;****************************************************************************** | ||
| 81 | ; Equates | ||
| 82 | ;****************************************************************************** | ||
| 83 | ; | ||
| 84 | FIRST_ROM = 0C800H ; Segment address of first option ROM. | ||
| 85 | LAST_ROM = 0EF80H ; Segment address of last option ROM. | ||
| 86 | FIRST_VDU_ROM = 0C000H ; Seg address of first VDU option ROM. | ||
| 87 | LAST_VDU_ROM = 0C780H ; Seg address of last VDU option ROM. | ||
| 88 | FIRST_RAM = 0C000H ; Seg address of 1st possible RAM addr | ||
| 89 | LAST_RAM = 0EF80H ; Seg addr of last possible RAM addr | ||
| 90 | NOT_FOUND_INCR = 0800H ; Amount to skip if no ROM found. | ||
| 91 | ; | ||
| 92 | include emmdef.inc | ||
| 93 | include vdmseg.inc | ||
| 94 | include romstruc.equ ; Option ROM structure. | ||
| 95 | PF_LENGTH equ 0400h ; length of a page frame (*16) | ||
| 96 | ; | ||
| 97 | ;****************************************************************************** | ||
| 98 | ; S E G M E N T S | ||
| 99 | ;****************************************************************************** | ||
| 100 | LAST segment | ||
| 101 | ASSUME CS:LAST, DS:DGROUP | ||
| 102 | ; | ||
| 103 | page | ||
| 104 | ;****************************************************************************** | ||
| 105 | ; | ||
| 106 | ; ROM_SRCH - Search for option ROMs. | ||
| 107 | ; | ||
| 108 | ; This section of code searches the auxiliary rom area (from C8000 up | ||
| 109 | ; to E0000) in 2K increments. A ROM checksum is calculated to insure | ||
| 110 | ; that the ROMs are valid. Valid ROMs must have the 1st byte = 55H | ||
| 111 | ; and the next byte = 0AAH. The next byte indicates the size of the | ||
| 112 | ; ROM in 512-byte blocks. The sum of all bytes in the ROM, modulo 256, | ||
| 113 | ; must be zero. | ||
| 114 | ; | ||
| 115 | ; If a ROM is not found at a location, the next location 2K-bytes down | ||
| 116 | ; is examined. However, if it is found, the next location after this | ||
| 117 | ; ROM is tried. The next ROM location is determine according to the | ||
| 118 | ; size of the previous ROM. | ||
| 119 | ; | ||
| 120 | ; | ||
| 121 | ;****************************************************************************** | ||
| 122 | rom_srch proc near ; Entry point. | ||
| 123 | push bx | ||
| 124 | ; | ||
| 125 | ; search for option ROMs | ||
| 126 | ; | ||
| 127 | mov ax,FIRST_ROM ; Segment address of first option ROM. | ||
| 128 | cld ; Set direction flag. | ||
| 129 | nxt_opt: | ||
| 130 | call opt_rom ; Look for option ROM. | ||
| 131 | jnc not_fnd1 ; No ROM here | ||
| 132 | call upd_seg | ||
| 133 | not_fnd1: | ||
| 134 | cmp ax,LAST_ROM ;Q: All ROMs looked at ? | ||
| 135 | jbe nxt_opt ; No, keep looking | ||
| 136 | ; Y: check for VDU roms | ||
| 137 | ; | ||
| 138 | ; search for VDM ROMs | ||
| 139 | ; | ||
| 140 | mov ax,FIRST_VDU_ROM ; segment addr for first vdu ROM | ||
| 141 | cld | ||
| 142 | nxt_vdu: | ||
| 143 | call opt_rom ; Q:is it there | ||
| 144 | jnc not_fnd2 ; No ROM here | ||
| 145 | call upd_seg | ||
| 146 | not_fnd2: | ||
| 147 | cmp ax,LAST_VDU_ROM ;Q: last VDU ROM ? | ||
| 148 | jbe nxt_vdu ; N: continue | ||
| 149 | ; Y: check for RAM | ||
| 150 | ; | ||
| 151 | ; search for RAM | ||
| 152 | ; | ||
| 153 | mov ax,FIRST_RAM ; first seg addr for RAM search | ||
| 154 | cld | ||
| 155 | nxt_ram: | ||
| 156 | call ram_srch ;Q: RAM here ? | ||
| 157 | jnc not_fndr ; N: check again ? | ||
| 158 | call upd_seg | ||
| 159 | not_fndr: | ||
| 160 | cmp ax,LAST_RAM ;Q: last RAM location | ||
| 161 | jbe nxt_ram ; N: continue searching | ||
| 162 | ; Y: all done | ||
| 163 | ; | ||
| 164 | pop bx | ||
| 165 | ret | ||
| 166 | rom_srch endp | ||
| 167 | page | ||
| 168 | ; | ||
| 169 | ;****************************************************************************** | ||
| 170 | ; OPT_ROM - This routine looks at the ROM located at the segment address | ||
| 171 | ; specified in AX to see if 0TH and 1ST Bytes = 0AA55H. | ||
| 172 | ; If so, it calculates the checksum over the length of | ||
| 173 | ; ROM. If the checksum is valid it updates AX to point | ||
| 174 | ; to the location of the next ROM. | ||
| 175 | ; | ||
| 176 | ; Inputs: AX = Segment address of ROM. | ||
| 177 | ; | ||
| 178 | ; Outputs: CY = Found a VDU ROM at this location. | ||
| 179 | ; NC = Did not find a valid ROM at this location. | ||
| 180 | ; AX = Segment address of next ROM location. | ||
| 181 | ; DX = Length of this ROM | ||
| 182 | ; | ||
| 183 | ;****************************************************************************** | ||
| 184 | ; | ||
| 185 | opt_rom proc near | ||
| 186 | push bx | ||
| 187 | push cx | ||
| 188 | push si | ||
| 189 | push ds | ||
| 190 | ; | ||
| 191 | mov ds,ax ; DS=ROM segment address. | ||
| 192 | xor bx,bx ; Index uses less code than absolute. | ||
| 193 | cmp [bx.ROM_RECOGNITION],0AA55H ;Q: Looks like a ROM? | ||
| 194 | jne rs_3 ; No, Skip down | ||
| 195 | ; | ||
| 196 | ; Compute checksum over ROM. | ||
| 197 | ; | ||
| 198 | xor si,si ; DS:SI=ROM Pointer; Start at beg. | ||
| 199 | xor cx,cx ; Prepare to accept byte into word. | ||
| 200 | mov ch,[bx.ROM_LEN] ; CH=byte count/512 (CX=byte count/2) | ||
| 201 | shl cx,1 ; CX=adjusted byte count. | ||
| 202 | mov dx,cx ; Extract size. | ||
| 203 | rs_2: | ||
| 204 | lodsb ; MOV AL,DS:[SI+]; Pickup next byte. | ||
| 205 | add bl,al ; Checksum += byte(SEG:offset) | ||
| 206 | loop rs_2 ; Loop doesn't affect flags. | ||
| 207 | jnz rs_3 ; Jump down if bad checksum. | ||
| 208 | ; | ||
| 209 | mov cl,4 ; Shift of 4... | ||
| 210 | shr dx,cl ; Converts bytes to paragraphs (D.03) | ||
| 211 | mov ax,ds ; Replace segment in AX. | ||
| 212 | add ax,dx ; increment segment by this amount | ||
| 213 | stc ; rom found | ||
| 214 | jmp short rs_exit ; Continue. | ||
| 215 | ; | ||
| 216 | rs_3: | ||
| 217 | mov dx,(NOT_FOUND_INCR shr 4) ; Prepare for next ROM. | ||
| 218 | mov ax,ds ; Replace segment in AX. | ||
| 219 | add ax,dx ; Increment segment. | ||
| 220 | clc ; no rom found | ||
| 221 | ; | ||
| 222 | rs_exit: | ||
| 223 | pop ds | ||
| 224 | pop si | ||
| 225 | pop cx | ||
| 226 | pop bx | ||
| 227 | ret ; *** RETURN *** | ||
| 228 | ; | ||
| 229 | opt_rom endp | ||
| 230 | page | ||
| 231 | ; | ||
| 232 | ;****************************************************************************** | ||
| 233 | ; RAM_SRCH - This routine looks at the address range potentially used | ||
| 234 | ; by the Page Frame to determine if any RAM is in the way. | ||
| 235 | ; It updates the map accordingly. | ||
| 236 | ; | ||
| 237 | ; Inputs: AX = Segment address for RAM search. | ||
| 238 | ; | ||
| 239 | ; Outputs: CY = Found RAM at this location. | ||
| 240 | ; NC = Did not find RAM at this location. | ||
| 241 | ; AX = Segment address of next RAM location. | ||
| 242 | ; DX = Length of this RAM | ||
| 243 | ; | ||
| 244 | ;****************************************************************************** | ||
| 245 | ; | ||
| 246 | ram_srch proc near | ||
| 247 | |||
| 248 | push bx | ||
| 249 | push ds | ||
| 250 | ; | ||
| 251 | ; search for RAM | ||
| 252 | ; | ||
| 253 | xor dx,dx ; length = 0 | ||
| 254 | ram_loop: | ||
| 255 | mov ds,ax | ||
| 256 | add ax,(NOT_FOUND_INCR shr 4); prepare for next chunk | ||
| 257 | mov bx,ds:0 ; get a word | ||
| 258 | xor ds:0,0FFFFh ; flip all bits | ||
| 259 | xor bx,0FFFFh ; BX = "flipped" value | ||
| 260 | cmp bx,ds:0 ;Q: "flipped" value written out ? | ||
| 261 | jne no_more_ram ; N: not RAM - leave | ||
| 262 | xor ds:0,0FFFFh ; Y: is ram, flip bits back | ||
| 263 | add dx,(NOT_FOUND_INCR shr 4); increment length count | ||
| 264 | cmp ax,LAST_RAM ;Q: last RAM location ? | ||
| 265 | jbe ram_loop ; N: continue searching | ||
| 266 | mov ds,ax ; Y: no more searching | ||
| 267 | no_more_ram: | ||
| 268 | ; | ||
| 269 | mov ax,ds ; get current segment | ||
| 270 | or dx,dx ;Q: any RAM found ? | ||
| 271 | jnz ram_found ; Y: set RAM found & chk DS seg again | ||
| 272 | clc ; N: set no RAM | ||
| 273 | add ax,(NOT_FOUND_INCR shr 4) ; AX -> next one to check | ||
| 274 | jmp short ram_exit ; and leave | ||
| 275 | ; | ||
| 276 | ram_found: | ||
| 277 | stc | ||
| 278 | ram_exit: | ||
| 279 | pop ds | ||
| 280 | pop bx | ||
| 281 | ; | ||
| 282 | ret | ||
| 283 | ram_srch endp | ||
| 284 | page | ||
| 285 | ; | ||
| 286 | |||
| 287 | ;****************************************************************************** | ||
| 288 | ; UPD_SEG - This routine looks at the address range used by the ROM/RAM | ||
| 289 | ; that was found to determine how many potential physical | ||
| 290 | ; pages are invalidated from being mappable. It updates | ||
| 291 | ; the mappable_segs array appropriately. | ||
| 292 | ; | ||
| 293 | ; Inputs: AX = Segment address of next ROM/RAM position. | ||
| 294 | ; DX = Length of ROM/RAM | ||
| 295 | ; | ||
| 296 | ; Outputs: [mappable_segs] updated. | ||
| 297 | ; | ||
| 298 | ; Written: 8/1/88 ISP | ||
| 299 | ; Modif: 8/25/88 ISP to make use of exclude_segments | ||
| 300 | ;****************************************************************************** | ||
| 301 | upd_seg proc near | ||
| 302 | ; | ||
| 303 | push bx | ||
| 304 | push ax | ||
| 305 | ; | ||
| 306 | mov bx,ax | ||
| 307 | sub bx,dx ; bx now has the first segment of the area | ||
| 308 | dec ax ; and ax has the last segment of the area | ||
| 309 | ; | ||
| 310 | call exclude_segments | ||
| 311 | ; | ||
| 312 | pop ax | ||
| 313 | pop bx | ||
| 314 | ret | ||
| 315 | upd_seg endp | ||
| 316 | LAST ENDS | ||
| 317 | END | ||
diff --git a/v4.0/src/MEMM/MEMM/RRTRAP.ASM b/v4.0/src/MEMM/MEMM/RRTRAP.ASM new file mode 100644 index 0000000..c1bb1a7 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/RRTRAP.ASM | |||
| @@ -0,0 +1,436 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title RRTRAP.ASM - Return To Real Trap | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: RRTRAP.ASM - Return to Real Trap | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 1, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/01/86 Original | ||
| 27 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 28 | ; 07/03/86 0.03 Changed to P84/85 Handlers | ||
| 29 | ; 07/06/86 0.04 Moved JumpReal to R_CODE and far label | ||
| 30 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; Functional Description: | ||
| 35 | ; This module traps ports 85h and 84h and watches for an application | ||
| 36 | ; to output the Return-to-Real code to these ports. If a 84h=0Fh is output, | ||
| 37 | ; then 85h=0h is output, the code in this module returns the system | ||
| 38 | ; to real mode. | ||
| 39 | ; | ||
| 40 | ; | ||
| 41 | ;****************************************************************************** | ||
| 42 | .lfcond ; list false conditionals | ||
| 43 | .386p | ||
| 44 | page | ||
| 45 | |||
| 46 | ;****************************************************************************** | ||
| 47 | ; I N C L U D E F I L E S | ||
| 48 | ; | ||
| 49 | include VDMseg.inc | ||
| 50 | include VDMsel.inc | ||
| 51 | include desc.inc | ||
| 52 | include INSTR386.INC | ||
| 53 | include VM386.INC | ||
| 54 | ; | ||
| 55 | ;****************************************************************************** | ||
| 56 | ; P U B L I C D E C L A R A T I O N S | ||
| 57 | ; | ||
| 58 | public RRP_Handler | ||
| 59 | public RR_Trap_Init | ||
| 60 | public RRProc | ||
| 61 | public JumpReal | ||
| 62 | ; | ||
| 63 | ;****************************************************************************** | ||
| 64 | ; E X T E R N A L R E F E R E N C E S | ||
| 65 | ; | ||
| 66 | _TEXT segment | ||
| 67 | extrn RetReal:near | ||
| 68 | extrn PortTrap:near | ||
| 69 | _TEXT ends | ||
| 70 | |||
| 71 | page | ||
| 72 | ;****************************************************************************** | ||
| 73 | ; L O C A L C O N S T A N T S | ||
| 74 | ; | ||
| 75 | FALSE equ 0 | ||
| 76 | TRUE equ not FALSE | ||
| 77 | |||
| 78 | RR85_Value equ 00h | ||
| 79 | RR84_Value equ 0Fh | ||
| 80 | |||
| 81 | FLAGS_IF equ 0200h | ||
| 82 | FLAGS_TF equ 0100h | ||
| 83 | |||
| 84 | RR_MASK equ NOT (FLAGS_IF+FLAGS_TF) ; mask off IF and TF bits | ||
| 85 | |||
| 86 | RTC_CMD equ 70h ; real time clock command port | ||
| 87 | DISABLE_NMI equ 80h ; cmd to disable NMI | ||
| 88 | ENABLE_NMI equ 00h ; cmd to enable NMI | ||
| 89 | |||
| 90 | ; | ||
| 91 | ;****************************************************************************** | ||
| 92 | ; D A T A S E G M E N T D E F I N I T I O N S | ||
| 93 | ; | ||
| 94 | ABS0 segment at 0000h | ||
| 95 | ABS0 ends | ||
| 96 | ; | ||
| 97 | _DATA segment | ||
| 98 | RR_Last db 0 ; last RR port trapped | ||
| 99 | RR85save db 0FFh | ||
| 100 | RR84save db 0FFh | ||
| 101 | _DATA ends | ||
| 102 | |||
| 103 | ; | ||
| 104 | ;------------------------------------------------------------------------------ | ||
| 105 | ; _TEXT code | ||
| 106 | ;------------------------------------------------------------------------------ | ||
| 107 | _TEXT segment | ||
| 108 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 109 | |||
| 110 | page | ||
| 111 | ;****************************************************************************** | ||
| 112 | ; RRP_Handler - I/O Trap handler for return to real ports 84h and 85h | ||
| 113 | ; | ||
| 114 | ; ENTRY: Protected Mode Ring 0 | ||
| 115 | ; AL = byte to output to port. | ||
| 116 | ; BX = 2 * port addr | ||
| 117 | ; DX == 0 => input | ||
| 118 | ; <> 0 => output | ||
| 119 | ; DS = DGROUP | ||
| 120 | ; SS:SP pts to: IP, saved DS, saved DX, IP , | ||
| 121 | ; saved DX,saved BX,saved ESI,saved EBX,saved EBP, | ||
| 122 | ; then GP fault stack frame with error code. | ||
| 123 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 124 | ; | ||
| 125 | ; EXIT: Protected Mode Ring 0 | ||
| 126 | ; CLC => I/O emulated. | ||
| 127 | ; STC => I/O NOT emulated. | ||
| 128 | ; | ||
| 129 | ; USED: Flags | ||
| 130 | ; STACK: | ||
| 131 | ;------------------------------------------------------------------------------ | ||
| 132 | RRP_Handler proc near | ||
| 133 | or dx,dx ;Q: Output ? | ||
| 134 | jz RRP_Bye ; N: then leave | ||
| 135 | cmp bx,84h*2 | ||
| 136 | je P84_Handler ; Process port 84h | ||
| 137 | cmp bx,85h*2 | ||
| 138 | je P85_Handler ; Process port 85h | ||
| 139 | RRP_Bye: | ||
| 140 | stc ; don't bother to emulate it | ||
| 141 | ret | ||
| 142 | RRP_Handler endp | ||
| 143 | |||
| 144 | ;****************************************************************************** | ||
| 145 | ; P84_Handler - I/O Trap handler for port 84h | ||
| 146 | ; | ||
| 147 | ; ENTRY: Protected Mode Ring 0 | ||
| 148 | ; AL = byte to output to port. | ||
| 149 | ; BX = 2 * port addr | ||
| 150 | ; DX == 0 => input | ||
| 151 | ; <> 0 => output | ||
| 152 | ; DS = DGROUP | ||
| 153 | ; SS:SP pts to: IP, saved DS, saved DX, IP , | ||
| 154 | ; saved DX,saved BX,saved ESI,saved EBX,saved EBP, | ||
| 155 | ; then GP fault stack frame with error code. | ||
| 156 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 157 | ; | ||
| 158 | ; EXIT: Protected Mode Ring 0 | ||
| 159 | ; CLC => I/O emulated. | ||
| 160 | ; STC => I/O NOT emulated. | ||
| 161 | ; | ||
| 162 | ; USED: Flags | ||
| 163 | ; STACK: | ||
| 164 | ;------------------------------------------------------------------------------ | ||
| 165 | P84_Handler proc near | ||
| 166 | ; | ||
| 167 | mov [RR84save],al ; Y: save value written to 84 | ||
| 168 | mov [RR_Last],84h ; save this RR port # | ||
| 169 | stc ; don't bother to emulate it | ||
| 170 | ret | ||
| 171 | ; | ||
| 172 | P84_Handler endp | ||
| 173 | |||
| 174 | page | ||
| 175 | ;****************************************************************************** | ||
| 176 | ; P85_Handler - I/O Trap handler for port 85h | ||
| 177 | ; | ||
| 178 | ; ENTRY: Protected Mode Ring 0 | ||
| 179 | ; AL = byte to output to port. | ||
| 180 | ; BX = 2 * port addr | ||
| 181 | ; DX == 0 => input | ||
| 182 | ; <> 0 => output | ||
| 183 | ; DS = DGROUP | ||
| 184 | ; SS:SP pts to: IP, saved DS, saved DX, IP , | ||
| 185 | ; saved DX,saved BX,saved ESI,saved EBX,saved EBP, | ||
| 186 | ; then GP fault stack frame with error code. | ||
| 187 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 188 | ; | ||
| 189 | ; EXIT: If output to 85h => return to Real | ||
| 190 | ; RRTrap emulates the output to 85h | ||
| 191 | ; RRTrap returns to real, fixes the segments and stack, and | ||
| 192 | ; returns to the instruction past the output in real mode. | ||
| 193 | ; If output does not imply return to Real | ||
| 194 | ; Protected Mode Ring 0 | ||
| 195 | ; CLC => I/O emulated. | ||
| 196 | ; STC => I/O NOT emulated. | ||
| 197 | ; | ||
| 198 | ; USED: Flags | ||
| 199 | ; STACK: | ||
| 200 | ;------------------------------------------------------------------------------ | ||
| 201 | P85_Handler proc near | ||
| 202 | ; | ||
| 203 | mov [RR85save],al ; Y: save value for 85h | ||
| 204 | cmp al,RR85_Value ; Q: return to real value output to 85 ? | ||
| 205 | jne P85_Exit ; N: save port # and leave | ||
| 206 | cmp [RR_Last],84h ; Y: Q: was last 84h last RR port output ? | ||
| 207 | jne P85_Exit ; N: save port # and leave | ||
| 208 | cmp [RR84Save],RR84_Value ; Y: Q: was 84h value RR value ? | ||
| 209 | jne P85_Exit ; N: save port # and leave | ||
| 210 | out 85h,al ; Y: emulate output and | ||
| 211 | jmp RR_GoReal ; return to real(we're in real) | ||
| 212 | P85_Exit: | ||
| 213 | mov [RR_Last],85h ; save this RR port addr | ||
| 214 | stc ; don't bother to emulate it | ||
| 215 | ret | ||
| 216 | ; | ||
| 217 | P85_Handler endp | ||
| 218 | |||
| 219 | page | ||
| 220 | ;****************************************************************************** | ||
| 221 | ; RR_GoReal - return client to real after 84/85 trap | ||
| 222 | ; | ||
| 223 | ; This is the return to real code. First we return to real mode. | ||
| 224 | ; Then we set up the stack, restore the registers and return to | ||
| 225 | ; the instruction following the out to 85h. | ||
| 226 | ;************** | ||
| 227 | ;NOTE: the following depends on the entry stack for P85_Handler | ||
| 228 | ; the same. | ||
| 229 | ; ENTRY: | ||
| 230 | ; SS:SP pts to: IP, saved DS, saved DX, IP , | ||
| 231 | ; saved DX,saved BX,saved ESI,saved EBX,saved EBP, | ||
| 232 | ; then GP fault stack frame with error code. | ||
| 233 | ;************** | ||
| 234 | ;****************************************************************************** | ||
| 235 | ; | ||
| 236 | RR_GoReal: | ||
| 237 | push ax | ||
| 238 | mov al,DISABLE_NMI | ||
| 239 | out RTC_CMD,al ; disable NMIs | ||
| 240 | pop ax | ||
| 241 | |||
| 242 | call RetReal ; return to real mode, DS,ES = DGROUP | ||
| 243 | ; | ||
| 244 | ; now start resetting registers from the stack | ||
| 245 | ; | ||
| 246 | ; | ||
| 247 | add sp,8 ; skip IP,DS,DX, and IP | ||
| 248 | pop dx | ||
| 249 | pop bx ; last pushed by OUT emulator | ||
| 250 | ; | ||
| 251 | ; now back to stack presented by VmFault's jmp to instr handler | ||
| 252 | ; | ||
| 253 | ; on to JumpReal code and continue in Real mode | ||
| 254 | ; | ||
| 255 | jmp FAR PTR JumpReal | ||
| 256 | |||
| 257 | ;****************************************************************************** | ||
| 258 | ; | ||
| 259 | ; RRProc Force processor into real mode | ||
| 260 | ; | ||
| 261 | ; entry: | ||
| 262 | ; | ||
| 263 | ; exit: Processor is in real mode | ||
| 264 | ; | ||
| 265 | ; used: AX | ||
| 266 | ; | ||
| 267 | ; stack: | ||
| 268 | ; | ||
| 269 | ;****************************************************************************** | ||
| 270 | RRProc proc near | ||
| 271 | pushf | ||
| 272 | cli ; protect this sequence | ||
| 273 | mov al,RR84_Value ; | ||
| 274 | out 84h,al ; port 84/85 return to real | ||
| 275 | mov al,RR85_Value ; sequence ... | ||
| 276 | out 85h,al ; | ||
| 277 | jmp $+2 ; clear prefetch/avoid race cond | ||
| 278 | popf | ||
| 279 | ret | ||
| 280 | RRProc endp | ||
| 281 | |||
| 282 | ;****************************************************************************** | ||
| 283 | ; | ||
| 284 | ; RR_Trap_Init Initialize data structure for return to real trapping | ||
| 285 | ; | ||
| 286 | ; description: This routine is called when the processor is put in | ||
| 287 | ; virtual mode. It should initialize anything that is | ||
| 288 | ; used by the RRTrap code. It assumes that the handler | ||
| 289 | ; addresses for ports 84h and 85h in IOTrap_Tab are set | ||
| 290 | ; up to point to RRP_Handler. | ||
| 291 | ; | ||
| 292 | ; entry: DS pts to DGROUP | ||
| 293 | ; | ||
| 294 | ; exit: Return to real trapping data structure initialized | ||
| 295 | ; | ||
| 296 | ; used: AX, BX | ||
| 297 | ; | ||
| 298 | ; stack: | ||
| 299 | ; | ||
| 300 | ;****************************************************************************** | ||
| 301 | RR_Trap_Init proc near | ||
| 302 | mov [RR_Last],0 ; reset Return to real trap vars | ||
| 303 | mov [RR85save],0FFh | ||
| 304 | mov [RR84save],0FFh | ||
| 305 | mov bh, 00h ; only set for 0084h and 0085h | ||
| 306 | mov ax, 84h | ||
| 307 | call PortTrap ; set traps on both return to real | ||
| 308 | mov ax, 85h ; ports in case client tries to | ||
| 309 | call PortTrap ; return to real | ||
| 310 | ret | ||
| 311 | RR_Trap_Init endp | ||
| 312 | |||
| 313 | _TEXT ends ; end of segment | ||
| 314 | |||
| 315 | ;------------------------------------------------------------------------------ | ||
| 316 | ; R_CODE code | ||
| 317 | ;------------------------------------------------------------------------------ | ||
| 318 | R_CODE segment | ||
| 319 | assume cs:R_CODE, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 320 | ; | ||
| 321 | ;****************************************************************************** | ||
| 322 | ; L O C A L D A T A A R E A | ||
| 323 | ;****************************************************************************** | ||
| 324 | ; | ||
| 325 | RR_Jump label dword ; ret addr for instr after out 84 | ||
| 326 | RR_JOff dw 0 | ||
| 327 | RR_JSeg dw 0 | ||
| 328 | |||
| 329 | RR_DS dw 0 ; DS for return | ||
| 330 | RR_SS dw 0 ; SS for return | ||
| 331 | RR_SP dw 0 ; SP for return | ||
| 332 | |||
| 333 | RR_Flags dw 0 ; low word of flags for return | ||
| 334 | |||
| 335 | ;****************************************************************************** | ||
| 336 | ; | ||
| 337 | ; NAME: JumpReal - jump into faulting code and continuing executing in Real | ||
| 338 | ; mode. When a virtual mode process causes a GP fault, then wishes | ||
| 339 | ; to continue executing in Real mode afterwards, VDM returns to real | ||
| 340 | ; mode then calls this routine to "unwind" the stack and continue | ||
| 341 | ; the process in real mode. | ||
| 342 | ; | ||
| 343 | ; THIS IS A FAR JUMP *** | ||
| 344 | ; | ||
| 345 | ; ENTRY: REAL MODE | ||
| 346 | ; SS:[BP] -> points to GP fault stack frame | ||
| 347 | ; SS:[SP] = saved client's ESI | ||
| 348 | ; SS:[SP+4] = saved client's EBX | ||
| 349 | ; SS:[SP+8] = saved client's EBP | ||
| 350 | ; | ||
| 351 | ; EXIT: REAL MODE | ||
| 352 | ; continues execution of process specified in GP fault stack | ||
| 353 | ; frame. | ||
| 354 | ; | ||
| 355 | ;****************************************************************************** | ||
| 356 | JumpReal label far | ||
| 357 | push cs | ||
| 358 | pop ds ; set DS= CS = R_CODE | ||
| 359 | ASSUME DS:R_CODE | ||
| 360 | ; set up return address | ||
| 361 | mov bx,[bp.VTFOE+VMTF_EIP] ; get return IP | ||
| 362 | mov [RR_JOff],bx ; save it | ||
| 363 | mov bx,[bp.VTFOE+VMTF_CS] ; get return CS | ||
| 364 | mov [RR_JSeg],bx ; save it | ||
| 365 | ; | ||
| 366 | mov bx,[bp.VTFOE+VMTF_EFLAGS] ; get flags | ||
| 367 | mov [RR_Flags],bx ; and save | ||
| 368 | and [bp.VTFOE+VMTF_EFLAGS],RR_MASK ; mask off certain bits | ||
| 369 | ; | ||
| 370 | mov bx,[bp.VTFOE+VMTF_DS] ; get DS | ||
| 371 | mov [RR_DS],bx ; save it | ||
| 372 | |||
| 373 | mov bx,[bp.VTFOE+VMTF_SS] ; get SS | ||
| 374 | mov [RR_SS],bx ; save it | ||
| 375 | mov bx,[bp.VTFOE+VMTF_ESP] ; get SP | ||
| 376 | mov [RR_SP],bx ; save it | ||
| 377 | ; | ||
| 378 | ; restore regs pushed by VM_Fault entry | ||
| 379 | ; | ||
| 380 | POP_ESI | ||
| 381 | POP_EBX | ||
| 382 | POP_EBP ; ALL regs except SEGMENT and SP are | ||
| 383 | ; restored. | ||
| 384 | add sp,4+VMTF_ES ; skip error code and GP fault stack | ||
| 385 | ; up to ES | ||
| 386 | |||
| 387 | pop es ; reset ES for return | ||
| 388 | add sp,6 ; skip high word of ES segment | ||
| 389 | ; and DS dword | ||
| 390 | |||
| 391 | POP_FS ; reset FS for return | ||
| 392 | add sp,2 ; skip high word of segment | ||
| 393 | |||
| 394 | POP_GS ; reset GS for return | ||
| 395 | ; | ||
| 396 | ; now set flags, DS, stack, and jump to return. | ||
| 397 | ; | ||
| 398 | test [RR_Flags],FLAGS_IF ;Q: IF bit set in return flags ? | ||
| 399 | jz RR_CLIexit ; N: then just return | ||
| 400 | push [RR_Flags] ; Y: enable interrupts on return | ||
| 401 | popf ; set flags | ||
| 402 | push [RR_DS] | ||
| 403 | pop ds ; set DS for exit | ||
| 404 | push ax | ||
| 405 | mov al,ENABLE_NMI | ||
| 406 | out RTC_CMD,al ; enable NMIs | ||
| 407 | pop ax | ||
| 408 | ;*** there is a small window here | ||
| 409 | ; --- NMI could occur with invalid | ||
| 410 | ; STACK | ||
| 411 | |||
| 412 | mov ss,CS:[RR_SS] ; restore SS | ||
| 413 | mov sp,CS:[RR_SP] ; restore SP | ||
| 414 | sti ; enable ints | ||
| 415 | jmp CS:[RR_Jump] ; and return | ||
| 416 | |||
| 417 | RR_CLIexit: | ||
| 418 | push [RR_Flags] ; leave interrupts disabled on return | ||
| 419 | popf ; set flags | ||
| 420 | push [RR_DS] | ||
| 421 | pop ds ; set DS for exit | ||
| 422 | push ax | ||
| 423 | mov al,ENABLE_NMI | ||
| 424 | out RTC_CMD,al ; enable NMIs | ||
| 425 | pop ax | ||
| 426 | ;*** there is a small window here | ||
| 427 | ; --- NMI could occur with invalid | ||
| 428 | ; STACK | ||
| 429 | |||
| 430 | mov ss,CS:[RR_SS] ; restore SS | ||
| 431 | mov sp,CS:[RR_SP] ; restore SP | ||
| 432 | jmp CS:[RR_Jump] ; far jump for return | ||
| 433 | ; | ||
| 434 | R_CODE ends ; end of segment | ||
| 435 | ; | ||
| 436 | end ; end of module | ||
diff --git a/v4.0/src/MEMM/MEMM/SHIPHI.ASM b/v4.0/src/MEMM/MEMM/SHIPHI.ASM new file mode 100644 index 0000000..be09a96 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/SHIPHI.ASM | |||
| @@ -0,0 +1,325 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE SHIPHI - MODULE to ship a segment up hi | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: SHIPHI - Ship a segment up hi into extended memory | ||
| 13 | ; | ||
| 14 | ; Version: 0.01 | ||
| 15 | ; | ||
| 16 | ; Date: Sep 1, 1988 | ||
| 17 | ; | ||
| 18 | ; Author: ISP | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ;****************************************************************************** | ||
| 27 | ; Functional Description: | ||
| 28 | ; | ||
| 29 | ; We need to ship data structures up hi. | ||
| 30 | ; This file has routines to specify size requirements for this operation | ||
| 31 | ; and to shift a segment up hi. Remember that in shipping a segment up hi | ||
| 32 | ; the GDT segment should be the last to be sent up since it is modified while | ||
| 33 | ; shipping a segment up hi | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | .lfcond | ||
| 37 | .386p | ||
| 38 | |||
| 39 | page | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; P U B L I C D E C L A R A T I O N S | ||
| 42 | ;****************************************************************************** | ||
| 43 | public set_src_selector ; Routines and data(GDT) for move block | ||
| 44 | public set_dest_selector | ||
| 45 | public moveb | ||
| 46 | public memreq | ||
| 47 | |||
| 48 | public gdt_mb | ||
| 49 | |||
| 50 | |||
| 51 | page | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; L O C A L C O N S T A N T S | ||
| 54 | ;****************************************************************************** | ||
| 55 | ; | ||
| 56 | |||
| 57 | ;****************************************************************************** | ||
| 58 | ; INCLUDE FILES | ||
| 59 | ;****************************************************************************** | ||
| 60 | include vdmseg.inc ; segment definitions | ||
| 61 | include desc.inc ; | ||
| 62 | include page.inc | ||
| 63 | |||
| 64 | page | ||
| 65 | ;****************************************************************************** | ||
| 66 | ; E X T E R N A L R E F E R E N C E S | ||
| 67 | ;****************************************************************************** | ||
| 68 | ; | ||
| 69 | ; | ||
| 70 | LAST SEGMENT | ||
| 71 | extrn get_buffer:near | ||
| 72 | LAST ENDS | ||
| 73 | |||
| 74 | page | ||
| 75 | ;****************************************************************************** | ||
| 76 | ; S E G M E N T D E F I N I T I O N | ||
| 77 | ;****************************************************************************** | ||
| 78 | |||
| 79 | ;************************************************************************* | ||
| 80 | ; | ||
| 81 | ; DATA | ||
| 82 | ; | ||
| 83 | ;************************************************************************* | ||
| 84 | |||
| 85 | _DATA SEGMENT | ||
| 86 | ASSUME CS:DGROUP,DS:DGROUP | ||
| 87 | ; | ||
| 88 | _DATA ENDS | ||
| 89 | |||
| 90 | |||
| 91 | |||
| 92 | |||
| 93 | LAST SEGMENT | ||
| 94 | ASSUME CS:LAST,DS:DGROUP,ES:DGROUP | ||
| 95 | |||
| 96 | ; GDT for ROM Move Block calls | ||
| 97 | ; | ||
| 98 | gdt_mb label word | ||
| 99 | ; | ||
| 100 | gdt0_mb: GDT_ENTRY 0,0,1,0 ; Dummy seg descriptor | ||
| 101 | gdt1_mb: GDT_ENTRY 0,0,1,0 ; GDT seg descriptor | ||
| 102 | gdt2_mb: GDT_ENTRY 0,0,0,D_DATA3 ; Src seg descriptor | ||
| 103 | gdt3_mb: GDT_ENTRY 0,0,0,D_DATA3 ; Dest seg descriptor | ||
| 104 | gdt4_mb: GDT_ENTRY 0,0,1,0 ; Bios cs seg descriptor | ||
| 105 | gdt5_mb: GDT_ENTRY 0,0,1,0 ; Bios ss seg descriptor | ||
| 106 | ; | ||
| 107 | |||
| 108 | LAST ENDS | ||
| 109 | |||
| 110 | ;************************************************************************* | ||
| 111 | ; | ||
| 112 | ; CODE | ||
| 113 | ; | ||
| 114 | ;************************************************************************* | ||
| 115 | LAST SEGMENT | ||
| 116 | ASSUME CS:LAST,DS:DGROUP,ES:DGROUP | ||
| 117 | |||
| 118 | ;****************************************************************************** | ||
| 119 | ; SHIPHI - routine to ship a segment up hi ; | ||
| 120 | ; ; | ||
| 121 | ; INPUTS: es = segment to be moved up ; | ||
| 122 | ; cx = number of bytes in the segment ; | ||
| 123 | ; ; | ||
| 124 | ; OUTPUTS: dx:ax = new address of the segment ; | ||
| 125 | ; Z set if succeeded, NZ if error ; | ||
| 126 | ; ; | ||
| 127 | ; USES: ax,dx,flags ; | ||
| 128 | ; ; | ||
| 129 | ; CALLS: ; | ||
| 130 | ; ; | ||
| 131 | ; AUTHOR: ISP (ISP) Sep 2, 1988 ; | ||
| 132 | ; ; | ||
| 133 | ;*****************************************************************************; | ||
| 134 | SHIPHI proc near | ||
| 135 | ; | ||
| 136 | push di | ||
| 137 | ; | ||
| 138 | ; first get some memory to play with | ||
| 139 | ; | ||
| 140 | call get_buffer | ||
| 141 | ; | ||
| 142 | ; then move the segment up to this new segment | ||
| 143 | ; | ||
| 144 | xor dh,dh ; dx:ax 32 bit addr of dest | ||
| 145 | xor di,di ; es:di is source segment | ||
| 146 | call moveb | ||
| 147 | ; | ||
| 148 | pop di | ||
| 149 | ; | ||
| 150 | ret | ||
| 151 | SHIPHI endp | ||
| 152 | |||
| 153 | |||
| 154 | |||
| 155 | ;*****************************************************************************; | ||
| 156 | ;*** MOVEB *** ; | ||
| 157 | ; ; | ||
| 158 | ; Move data between from conventional memory to extended memory ; | ||
| 159 | ; ; | ||
| 160 | ; ; | ||
| 161 | ; INPUTS: dl:ax = 24 bit address of extended memory address ; | ||
| 162 | ; es:di = source address in lo memory | ||
| 163 | ; cx = number of bytes to transfer | ||
| 164 | ; ; | ||
| 165 | ; OUTPUTS: Z set if succeeded ; | ||
| 166 | ; NZ if error ; | ||
| 167 | ; ; | ||
| 168 | ; USES: ; | ||
| 169 | ; ; | ||
| 170 | ; AUTHOR: ISP, Sep 2,1988. ; | ||
| 171 | ; ; | ||
| 172 | ;*****************************************************************************; | ||
| 173 | |||
| 174 | |||
| 175 | MOVEB proc near | ||
| 176 | push es | ||
| 177 | push dx | ||
| 178 | push ax | ||
| 179 | push di | ||
| 180 | push cx | ||
| 181 | |||
| 182 | |||
| 183 | ; | ||
| 184 | ; no setup needed for dest selector, already set up. | ||
| 185 | ; | ||
| 186 | call set_dest_selector ; destination is unlock address | ||
| 187 | ; | ||
| 188 | ; for source selector we need to convert segment:offset to dl:ax | ||
| 189 | ; cx is already # of words | ||
| 190 | ; | ||
| 191 | xor dx,dx | ||
| 192 | mov ax,es | ||
| 193 | mov bx,16 | ||
| 194 | mul bx | ||
| 195 | add ax,di | ||
| 196 | adc dx,0 | ||
| 197 | |||
| 198 | call set_src_selector ; set source segment selector to buffer | ||
| 199 | ; | ||
| 200 | ; do the block move | ||
| 201 | ; | ||
| 202 | mov si,seg LAST | ||
| 203 | mov es,si | ||
| 204 | mov si,offset LAST:gdt_mb ; ES:SI -> global descriptor table | ||
| 205 | ; | ||
| 206 | ; convert count to number of words | ||
| 207 | ; | ||
| 208 | inc cx | ||
| 209 | shr cx,1 | ||
| 210 | ; | ||
| 211 | ; | ||
| 212 | mov ah,87h ; int 15 block move function code | ||
| 213 | int 15h ; unlock rom | ||
| 214 | or ah,ah ; Q: error? | ||
| 215 | ; Y: return NZ | ||
| 216 | pop cx | ||
| 217 | pop di | ||
| 218 | pop ax | ||
| 219 | pop dx | ||
| 220 | pop es | ||
| 221 | ; N: return Z | ||
| 222 | ret | ||
| 223 | MOVEB endp | ||
| 224 | |||
| 225 | page | ||
| 226 | ;****************************************************************************** | ||
| 227 | ; | ||
| 228 | ; set_src_selector | ||
| 229 | ; Set base address, limit of source segment selector | ||
| 230 | ; in gdt_mb for int 15h block move | ||
| 231 | ; | ||
| 232 | ; | ||
| 233 | ; entry: dl:ax == source address (24 bits) | ||
| 234 | ; cx == size, in words | ||
| 235 | ; | ||
| 236 | ; exit: gdt_mb(2) contains source base address, limit | ||
| 237 | ; | ||
| 238 | ; used: none | ||
| 239 | ; | ||
| 240 | ;****************************************************************************** | ||
| 241 | ; | ||
| 242 | set_src_selector proc near | ||
| 243 | ; | ||
| 244 | push di | ||
| 245 | mov di,offset LAST:gdt2_mb ; cs:di -> source seg descriptor | ||
| 246 | set_entry: | ||
| 247 | mov cs:[di.BASE_LOW],ax ; Store base address bits 15:00 | ||
| 248 | mov cs:[di.BASE_HIGH],dl ; Store base address bits 23:16 | ||
| 249 | mov cs:[di.LIMIT],cx ; Store size | ||
| 250 | sub cs:[di.LIMIT],1 ; subtract 1 => convert to limit | ||
| 251 | ; | ||
| 252 | pop di | ||
| 253 | ret ; *** Return *** | ||
| 254 | ; | ||
| 255 | set_src_selector endp ; End of procedure | ||
| 256 | ; | ||
| 257 | page | ||
| 258 | ;****************************************************************************** | ||
| 259 | ; | ||
| 260 | ; set_dest_selector | ||
| 261 | ; Set base address, limit of destination segment selector | ||
| 262 | ; in gdt_mb for int 15h block move | ||
| 263 | ; | ||
| 264 | ; entry: dx:ax == address (32 bits) | ||
| 265 | ; cx == size of segment, in words | ||
| 266 | ; ds = DGROUP | ||
| 267 | ; | ||
| 268 | ; exit: gdt_mb(3) contains destination base address, | ||
| 269 | ; limit | ||
| 270 | ; | ||
| 271 | ; used: none | ||
| 272 | ; | ||
| 273 | ;****************************************************************************** | ||
| 274 | ; | ||
| 275 | set_dest_selector proc near | ||
| 276 | ; | ||
| 277 | push di | ||
| 278 | mov di,offset LAST:gdt3_mb ; cs:di -> source seg descriptor | ||
| 279 | mov cs:[di.BASE_XHI],dh ; bits 24-31 | ||
| 280 | jmp set_entry ; set this entry in gdt_mb | ||
| 281 | ; | ||
| 282 | ret ; *** Return *** | ||
| 283 | ; | ||
| 284 | set_dest_selector endp ; End of procedure | ||
| 285 | |||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | |||
| 291 | |||
| 292 | ;****************************************************************************** | ||
| 293 | ; MEMREQ - routine to determine memory requirements for shifting the driver ; | ||
| 294 | ; up into extended memory ; | ||
| 295 | ; ; | ||
| 296 | ; INPUTS: none ; | ||
| 297 | ; ; | ||
| 298 | ; OUTPUTS: CX = size requirements in K ; | ||
| 299 | ; ; | ||
| 300 | ; USES: CX, flags ; | ||
| 301 | ; ; | ||
| 302 | ; AUTHOR: ISP (ISP) Sep 2, 1988 ; | ||
| 303 | ; ; | ||
| 304 | ;*****************************************************************************; | ||
| 305 | MEMREQ proc near | ||
| 306 | ; | ||
| 307 | push ax | ||
| 308 | ; | ||
| 309 | mov ax,seg LAST ; this is the last segment and | ||
| 310 | ; one which is discarded. | ||
| 311 | sub ax,seg PAGESEG ; this is the first segment of the | ||
| 312 | ; region which is to be moved. | ||
| 313 | |||
| 314 | add ax, (P_SIZE/16 -1) ; to round it up to next page bdry | ||
| 315 | shr ax, 6 ; find the size in K | ||
| 316 | add ax,16 ; throw in 4 more pages for safety | ||
| 317 | mov cx,ax ; and return the size needed | ||
| 318 | ; | ||
| 319 | pop ax | ||
| 320 | ret | ||
| 321 | MEMREQ endp | ||
| 322 | |||
| 323 | LAST ENDS | ||
| 324 | |||
| 325 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/TABDEF.ASM b/v4.0/src/MEMM/MEMM/TABDEF.ASM new file mode 100644 index 0000000..c70406e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/TABDEF.ASM | |||
| @@ -0,0 +1,357 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title TABDEF.ASM - 386 Protected Mode CPU Tables | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: TABDEF.ASM - 386 Protected Mode CPU Tables | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Tables for Standalone protected mode system | ||
| 27 | ; A- Modified for Virtual DOS | ||
| 28 | ; 05/12/86 B- Cleanup and segment reorganization | ||
| 29 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 30 | ; 07/05/86 0.04 Moved KBD and PRINT to DCODE segment | ||
| 31 | ; 07/20/88 Remove debugger codes (pc) | ||
| 32 | ; | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; | ||
| 35 | ; Functional Description: | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | .lfcond ; list false conditionals | ||
| 39 | .386p | ||
| 40 | |||
| 41 | NAME tabdef | ||
| 42 | ; | ||
| 43 | |||
| 44 | .xlist | ||
| 45 | include VDMseg.inc | ||
| 46 | include VDMsel.inc | ||
| 47 | include desc.inc | ||
| 48 | include page.inc | ||
| 49 | .list | ||
| 50 | |||
| 51 | |||
| 52 | _TEXT SEGMENT | ||
| 53 | extrn vm_trap00:far | ||
| 54 | extrn vm_trap01:far | ||
| 55 | extrn vm_trap02:far | ||
| 56 | extrn vm_trap03:far | ||
| 57 | extrn vm_trap04:far | ||
| 58 | extrn vm_trap05:far | ||
| 59 | extrn vm_trap06:far | ||
| 60 | extrn vm_trap07:far | ||
| 61 | extrn vm_trap08:far | ||
| 62 | extrn vm_trap09:far | ||
| 63 | extrn vm_trap0a:far | ||
| 64 | extrn vm_trap0b:far | ||
| 65 | extrn vm_trap0c:far | ||
| 66 | extrn vm_trap0d:far | ||
| 67 | extrn vm_trap0e:far | ||
| 68 | extrn vm_trap0f:far | ||
| 69 | extrn vm_trap50:far | ||
| 70 | extrn vm_trap51:far | ||
| 71 | extrn vm_trap52:far | ||
| 72 | extrn vm_trap53:far | ||
| 73 | extrn vm_trap54:far | ||
| 74 | extrn vm_trap55:far | ||
| 75 | extrn vm_trap56:far | ||
| 76 | extrn vm_trap57:far | ||
| 77 | extrn vm_trap70:far | ||
| 78 | extrn vm_trap71:far | ||
| 79 | extrn vm_trap72:far | ||
| 80 | extrn vm_trap73:far | ||
| 81 | extrn vm_trap74:far | ||
| 82 | extrn vm_trap75:far | ||
| 83 | extrn vm_trap76:far | ||
| 84 | extrn vm_trap77:far | ||
| 85 | |||
| 86 | extrn EMM_pEntry:far | ||
| 87 | |||
| 88 | _TEXT ENDS | ||
| 89 | |||
| 90 | |||
| 91 | ;*** GDT - Global Descriptor Table | ||
| 92 | ; | ||
| 93 | ; This is the system GDT. Some parts are statically initialised, | ||
| 94 | ; others must be set up at run time, either because masm can't | ||
| 95 | ; calculate the data or it changes while the system is running. | ||
| 96 | ; | ||
| 97 | ; WARNING | ||
| 98 | ; | ||
| 99 | ; Don't change this without consulting "sel.inc", and the | ||
| 100 | ; routines which initialise the gdt. | ||
| 101 | ; | ||
| 102 | |||
| 103 | GDT SEGMENT | ||
| 104 | |||
| 105 | gdtstart label byte ; label for everyone to refer to the GDT | ||
| 106 | |||
| 107 | GDT_ENTRY 0, 0, 1, 0 ; null selector | ||
| 108 | GDT_ENTRY 0, 0, 0, D_DATA0 ; GDT alias | ||
| 109 | GDT_ENTRY 0, 0, 0, D_DATA0 ; IDT alias | ||
| 110 | GDT_ENTRY 0, 0, 0, D_LDT0 ; LDT | ||
| 111 | GDT_ENTRY 0, 0, 0, D_DATA0 ; LDT alias | ||
| 112 | GDT_ENTRY 0, 0, 0, D_386TSS0 ; TSS | ||
| 113 | GDT_ENTRY 0, 0, 0, D_DATA0 ; TSS alias | ||
| 114 | GDT_ENTRY 0, 0, <400h>, D_DATA3 ; Real Mode IDT | ||
| 115 | GDT_ENTRY 400h, 0, <300h>, D_DATA0 ; ROM Data | ||
| 116 | GDT_ENTRY 0, 0, 0, D_CODE0 ; VDM Code | ||
| 117 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Data | ||
| 118 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Stack | ||
| 119 | GDT_ENTRY 0, 0bh, 1000h, D_DATA0 ; Mono Display | ||
| 120 | GDT_ENTRY 8000h, 0bh, 4000h, D_DATA0 ; Colour Disp | ||
| 121 | GDT_ENTRY 0, 0ah, 0, D_DATA0 ; EGA Low | ||
| 122 | GDT_ENTRY 0, 0ch, 0, D_DATA0 ; EGA High | ||
| 123 | GDT_ENTRY 800h, 0, 66h, D_DATA0 ; LOADALL | ||
| 124 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 1 | ||
| 125 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 2 | ||
| 126 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 3 | ||
| 127 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 4 | ||
| 128 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 5 | ||
| 129 | GDT_ENTRY 0, 0, 0, 0 ; debugger work (Addresses all memory) | ||
| 130 | GDT_ENTRY 0, 0, 0, 0 ; general work | ||
| 131 | GDT_ENTRY 0, 0, 0, 0 ; general work | ||
| 132 | GDT_ENTRY 0, 0, 0, D_CODE0 ; maps CODE segment | ||
| 133 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VM1_GSEL - vm trap scratch | ||
| 134 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VM2_GSEL - vm trap scratch | ||
| 135 | GDT_ENTRY 0, 0, 0, D_DATA0 ; MBSRC_GSEL - move blk scratch | ||
| 136 | GDT_ENTRY 0, 0, 0, D_DATA0 ; MBTAR_GSEL - move blk scratch | ||
| 137 | GDT_ENTRY 0, 0, 0, D_DATA0 ; PAGET_GSEL - page table area | ||
| 138 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Code - Data Alias | ||
| 139 | GDT_ENTRY 0, 0, 0, D_DATA0 ; EMM1 - EMM scratch selector | ||
| 140 | GDT_ENTRY 0, 0, 0, D_DATA0 ; EMM2 - EMM scratch selector | ||
| 141 | GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM0 entry | ||
| 142 | GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM1 entry | ||
| 143 | GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM2 entry | ||
| 144 | GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM3 entry | ||
| 145 | GDT_ENTRY 0, 0, 0, D_DATA0 ; USER1 entry | ||
| 146 | |||
| 147 | public GDTLEN | ||
| 148 | GDTLEN equ $ - gdtstart | ||
| 149 | |||
| 150 | GDT ENDS | ||
| 151 | |||
| 152 | |||
| 153 | ;*** TSS for protected Mode | ||
| 154 | ; | ||
| 155 | ; This is the VDM TSS. We only use one, for loading | ||
| 156 | ; SS:SP on privilige transitions. We don't use all | ||
| 157 | ; the 286 task switching stuff. | ||
| 158 | ; | ||
| 159 | ; | ||
| 160 | |||
| 161 | TSS segment | ||
| 162 | ; | ||
| 163 | TssArea TSS386STRUC <> | ||
| 164 | ; | ||
| 165 | ; I/O Bit Map for Virtual Mode I/O trapping | ||
| 166 | ; | ||
| 167 | public IOBitMap | ||
| 168 | IOBitMap label byte | ||
| 169 | db 2000h dup (0) ; initialize all ports to NO trapping | ||
| 170 | db 0FFh ; last byte is all 1's | ||
| 171 | |||
| 172 | public TSSLEN | ||
| 173 | TSSLEN equ $ - tss | ||
| 174 | |||
| 175 | TSS ends | ||
| 176 | |||
| 177 | ;*** IDT for protected mode | ||
| 178 | ; | ||
| 179 | ; This is the protected mode interrupt descriptor table. | ||
| 180 | ; | ||
| 181 | ; The first 78h entries are defined. Only processor exceptions and | ||
| 182 | ; hardware interrupts are fielded through the PM IDT. Since the | ||
| 183 | ; gate DPLs are < 3, all software INTs are funneled through INT 13 | ||
| 184 | ; (GP exception) and emulated. Note that Null IDT entries and limit | ||
| 185 | ; exceptions produce the same results (GP error code) as DPL faults, | ||
| 186 | ; so we can use a truncated IDT. This assumes no one is reprogramming | ||
| 187 | ; the 8259s base vector for some reason - don't know of any DOS apps | ||
| 188 | ; that do this. | ||
| 189 | ; | ||
| 190 | IDT SEGMENT | ||
| 191 | |||
| 192 | idtstart label byte | ||
| 193 | |||
| 194 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap00>,D_386INT0 ; 00 Divide Error | ||
| 195 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap01>,D_386INT0 ; 01 Debug | ||
| 196 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap02>,D_386INT0 ; 02 NMI/287 Error | ||
| 197 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap03>,D_386INT0 ; 03 Breakpoint | ||
| 198 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap04>,D_386INT0 ; 04 INTO | ||
| 199 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap05>,D_386INT0 ; 05 BOUND/Print Screen | ||
| 200 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap06>,D_386INT0 ; 06 Invalid Opcode | ||
| 201 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap07>,D_386INT0 ; 07 287 Not Available | ||
| 202 | |||
| 203 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap08>,D_386INT0 ; 08 Double Exception/Timer | ||
| 204 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap09>,D_386INT0 ; 09 (not on 386)/Keyboard | ||
| 205 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0a>,D_386INT0 ; 0A Invalid TSS/Cascade | ||
| 206 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0b>,D_386INT0 ; 0B Segment Not Present/COM2 | ||
| 207 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0c>,D_386INT0 ; 0C Stack Fault/COM1 | ||
| 208 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0d>,D_386INT0 ; 0D General Protection/LPT2 | ||
| 209 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0e>,D_386INT0 ; 0E Page Fault/Diskette | ||
| 210 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0F>,D_386INT0 ; 0F Intel Reserved/LPT1 | ||
| 211 | |||
| 212 | IDT_ENTRY 0, 0, 0 ; 10 [287 Error]/Video INT (This exception | ||
| 213 | ; cannot occur on AT architecture) | ||
| 214 | IDT_ENTRY 0, 0, 0 ; 11 Equipment Check | ||
| 215 | IDT_ENTRY 0, 0, 0 ; 12 Memory Size | ||
| 216 | IDT_ENTRY 0, 0, 0 ; 13 Disk INT | ||
| 217 | IDT_ENTRY 0, 0, 0 ; 14 RS232 | ||
| 218 | IDT_ENTRY 0, 0, 0 ; 15 Post&Wait, mov_blk via GP fault | ||
| 219 | IDT_ENTRY 0, 0, 0 ; 16 Keyboard | ||
| 220 | IDT_ENTRY 0, 0, 0 ; 17 Printer | ||
| 221 | |||
| 222 | IDT_ENTRY 0, 0, 0 ; 18 Resident BASIC | ||
| 223 | IDT_ENTRY 0, 0, 0 ; 19 Bootstrap | ||
| 224 | IDT_ENTRY 0, 0, 0 ; 1A Time of Day | ||
| 225 | IDT_ENTRY 0, 0, 0 ; 1B Break | ||
| 226 | IDT_ENTRY 0, 0, 0 ; 1C Timer Tick | ||
| 227 | IDT_ENTRY 0, 0, 0 ; 1D Ptr to Video Param | ||
| 228 | IDT_ENTRY 0, 0, 0 ; 1E Ptr to Disk Params | ||
| 229 | IDT_ENTRY 0, 0, 0 ; 1F Ptr to Graphics | ||
| 230 | |||
| 231 | IDT_ENTRY 0, 0, 0 ; 20 DOS | ||
| 232 | IDT_ENTRY 0, 0, 0 ; 21 DOS | ||
| 233 | IDT_ENTRY 0, 0, 0 ; 22 DOS | ||
| 234 | IDT_ENTRY 0, 0, 0 ; 23 DOS | ||
| 235 | IDT_ENTRY 0, 0, 0 ; 24 DOS | ||
| 236 | IDT_ENTRY 0, 0, 0 ; 25 DOS | ||
| 237 | IDT_ENTRY 0, 0, 0 ; 26 DOS | ||
| 238 | IDT_ENTRY 0, 0, 0 ; 27 DOS | ||
| 239 | |||
| 240 | IDT_ENTRY 0, 0, 0 ; 28 DOS | ||
| 241 | IDT_ENTRY 0, 0, 0 ; 29 DOS | ||
| 242 | IDT_ENTRY 0, 0, 0 ; 2A DOS | ||
| 243 | IDT_ENTRY 0, 0, 0 ; 2B DOS | ||
| 244 | IDT_ENTRY 0, 0, 0 ; 2C DOS | ||
| 245 | IDT_ENTRY 0, 0, 0 ; 2D DOS | ||
| 246 | IDT_ENTRY 0, 0, 0 ; 2E DOS | ||
| 247 | IDT_ENTRY 0, 0, 0 ; 2F DOS | ||
| 248 | |||
| 249 | IDT_ENTRY 0, 0, 0 ; 30 DOS | ||
| 250 | IDT_ENTRY 0, 0, 0 ; 31 DOS | ||
| 251 | IDT_ENTRY 0, 0, 0 ; 32 DOS | ||
| 252 | IDT_ENTRY 0, 0, 0 ; 33 DOS | ||
| 253 | IDT_ENTRY 0, 0, 0 ; 34 DOS | ||
| 254 | IDT_ENTRY 0, 0, 0 ; 35 DOS | ||
| 255 | IDT_ENTRY 0, 0, 0 ; 36 DOS | ||
| 256 | IDT_ENTRY 0, 0, 0 ; 37 DOS | ||
| 257 | |||
| 258 | IDT_ENTRY 0, 0, 0 ; 38 DOS | ||
| 259 | IDT_ENTRY 0, 0, 0 ; 39 DOS | ||
| 260 | IDT_ENTRY 0, 0, 0 ; 3A DOS | ||
| 261 | IDT_ENTRY 0, 0, 0 ; 3B DOS | ||
| 262 | IDT_ENTRY 0, 0, 0 ; 3C DOS | ||
| 263 | IDT_ENTRY 0, 0, 0 ; 3D DOS | ||
| 264 | IDT_ENTRY 0, 0, 0 ; 3E DOS | ||
| 265 | IDT_ENTRY 0, 0, 0 ; 3F DOS | ||
| 266 | |||
| 267 | IDT_ENTRY 0, 0, 0 ; 40 Reserved | ||
| 268 | IDT_ENTRY 0, 0, 0 ; 41 Reserved | ||
| 269 | IDT_ENTRY 0, 0, 0 ; 42 Reserved | ||
| 270 | IDT_ENTRY 0, 0, 0 ; 43 Reserved | ||
| 271 | IDT_ENTRY 0, 0, 0 ; 44 Reserved | ||
| 272 | IDT_ENTRY 0, 0, 0 ; 45 Reserved | ||
| 273 | IDT_ENTRY 0, 0, 0 ; 46 Reserved | ||
| 274 | IDT_ENTRY 0, 0, 0 ; 47 Reserved | ||
| 275 | |||
| 276 | IDT_ENTRY 0, 0, 0 ; 48 Reserved | ||
| 277 | IDT_ENTRY 0, 0, 0 ; 49 Reserved | ||
| 278 | IDT_ENTRY 0, 0, 0 ; 4A Reserved | ||
| 279 | IDT_ENTRY 0, 0, 0 ; 4B Reserved | ||
| 280 | IDT_ENTRY 0, 0, 0 ; 4C Reserved | ||
| 281 | IDT_ENTRY 0, 0, 0 ; 4D Reserved | ||
| 282 | IDT_ENTRY 0, 0, 0 ; 4E Reserved | ||
| 283 | IDT_ENTRY 0, 0, 0 ; 4F Reserved | ||
| 284 | |||
| 285 | ; | ||
| 286 | ; The following table entries assume the master 8259 base vector has been | ||
| 287 | ; set up to 50h. | ||
| 288 | ; | ||
| 289 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap50>,D_386INT0 ; 50 Timer Interrupt | ||
| 290 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap51>,D_386INT0 ; 51 Keyboard Interrupt | ||
| 291 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap52>,D_386INT0 ; 52 Misc peripheral Interrupt | ||
| 292 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap53>,D_386INT0 ; 53 COM2 | ||
| 293 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap54>,D_386INT0 ; 54 COM1 | ||
| 294 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap55>,D_386INT0 ; 55 2nd Parallel | ||
| 295 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap56>,D_386INT0 ; 56 Diskette Interrupt | ||
| 296 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap57>,D_386INT0 ; 57 1st Parallel | ||
| 297 | |||
| 298 | IDT_ENTRY 0, 0, 0 ; 58 Reserved | ||
| 299 | IDT_ENTRY 0, 0, 0 ; 59 Reserved | ||
| 300 | IDT_ENTRY 0, 0, 0 ; 5A Reserved | ||
| 301 | IDT_ENTRY 0, 0, 0 ; 5B Reserved | ||
| 302 | IDT_ENTRY 0, 0, 0 ; 5C Reserved | ||
| 303 | IDT_ENTRY 0, 0, 0 ; 5D Reserved | ||
| 304 | IDT_ENTRY 0, 0, 0 ; 5E Reserved | ||
| 305 | IDT_ENTRY 0, 0, 0 ; 5F Reserved | ||
| 306 | |||
| 307 | IDT_ENTRY 0, 0, 0 ; 60 User Programs | ||
| 308 | IDT_ENTRY 0, 0, 0 ; 61 User Programs | ||
| 309 | IDT_ENTRY 0, 0, 0 ; 62 User Programs | ||
| 310 | IDT_ENTRY 0, 0, 0 ; 63 User Programs | ||
| 311 | IDT_ENTRY 0, 0, 0 ; 64 User Programs | ||
| 312 | IDT_ENTRY 0, 0, 0 ; 65 User Programs | ||
| 313 | IDT_ENTRY 0, 0, 0 ; 66 User Programs | ||
| 314 | ;;;IDT_ENTRY 0, 0, 0 ; 67 User Programs | ||
| 315 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:EMM_pEntry>,D_386INT3 ; 67 ELIM | ||
| 316 | |||
| 317 | IDT_ENTRY 0, 0, 0 ; 68 Not Used | ||
| 318 | IDT_ENTRY 0, 0, 0 ; 69 Not Used | ||
| 319 | IDT_ENTRY 0, 0, 0 ; 6A Not Used | ||
| 320 | IDT_ENTRY 0, 0, 0 ; 6B Not Used | ||
| 321 | IDT_ENTRY 0, 0, 0 ; 6C Not Used | ||
| 322 | IDT_ENTRY 0, 0, 0 ; 6D Not Used | ||
| 323 | IDT_ENTRY 0, 0, 0 ; 6E Not Used | ||
| 324 | IDT_ENTRY 0, 0, 0 ; 6F Not Used | ||
| 325 | |||
| 326 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap70>,D_386INT0 ; 70 IRQ8 - Real Time Clock | ||
| 327 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap71>,D_386INT0 ; 71 IRQ9 | ||
| 328 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap72>,D_386INT0 ; 72 IRQ10 | ||
| 329 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap73>,D_386INT0 ; 73 IRQ11 | ||
| 330 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap74>,D_386INT0 ; 74 IRQ12 | ||
| 331 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap75>,D_386INT0 ; 75 IRQ13 - 287 error | ||
| 332 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap76>,D_386INT0 ; 76 IRQ14 - Fixed disk | ||
| 333 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap77>,D_386INT0 ; 77 IRQ15 | ||
| 334 | |||
| 335 | public IDTLEN | ||
| 336 | idtlen equ this byte - idtstart | ||
| 337 | |||
| 338 | IDT ends | ||
| 339 | |||
| 340 | PAGESEG SEGMENT | ||
| 341 | ;*** Page Tables Area | ||
| 342 | ; | ||
| 343 | ; This area is used for the page directory and page tables | ||
| 344 | ; | ||
| 345 | |||
| 346 | public P_TABLE_CNT | ||
| 347 | P_TABLE_CNT equ 5 ; # of page tables | ||
| 348 | |||
| 349 | public Page_Area | ||
| 350 | Page_Area label byte | ||
| 351 | db (2+P_TABLE_CNT) * P_SIZE dup (0) ; enough for page dir & | ||
| 352 | ; tables after page | ||
| 353 | ; alignment. | ||
| 354 | PAGESEG ENDS | ||
| 355 | |||
| 356 | END | ||
| 357 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/TRAPDEF.ASM b/v4.0/src/MEMM/MEMM/TRAPDEF.ASM new file mode 100644 index 0000000..b82f661 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/TRAPDEF.ASM | |||
| @@ -0,0 +1,469 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title TRAPDEF.ASM - I/O trap Dispatch table | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: TRAPDEF.ASM - I/O trap Dispatch table | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: July 1, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 08/11/86 Split from IOTrap.asm | ||
| 27 | ; | ||
| 28 | ; 7/26/88 Added Trap handler entries for DMA ports on Channel 4 | ||
| 29 | ; - Jaywant H Bharadwaj | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ; | ||
| 33 | .lfcond ; list false conditionals | ||
| 34 | .386p | ||
| 35 | page | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; P U B L I C D E C L A R A T I O N S | ||
| 38 | ;****************************************************************************** | ||
| 39 | ; | ||
| 40 | public IOTrap_Tab ; dispatches I/O trap handlers | ||
| 41 | public IOT_BadT ; Unknown port trap routine | ||
| 42 | public IOT_OEM ; OEM specific port emulation | ||
| 43 | |||
| 44 | page | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; L O C A L C O N S T A N T S | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | ; % - how many of these are actually needed? | ||
| 50 | ; % - Need any includes from Win/386 DMA code - trapdef.asm ? | ||
| 51 | |||
| 52 | include VDMseg.inc | ||
| 53 | include VDMsel.inc | ||
| 54 | include desc.inc | ||
| 55 | include elim.inc | ||
| 56 | include page.inc | ||
| 57 | include oemdep.inc | ||
| 58 | include instr386.inc | ||
| 59 | include vm386.inc | ||
| 60 | ; | ||
| 61 | ;****************************************************************************** | ||
| 62 | ; E X T E R N A L R E F E R E N C E S | ||
| 63 | ;****************************************************************************** | ||
| 64 | ; | ||
| 65 | |||
| 66 | _DATA segment | ||
| 67 | ;extrn _map_size:byte ; # of mapping registers used | ||
| 68 | ;extrn LIMP_Addr:word | ||
| 69 | _DATA ends | ||
| 70 | |||
| 71 | _TEXT segment | ||
| 72 | ; | ||
| 73 | extrn RRP_Handler:near | ||
| 74 | extrn A20_Handler:near ; Kybd Data port - A20 watch | ||
| 75 | extrn DMABase0:near ; DMA base register for Channel 0 | ||
| 76 | extrn DMABase1:near ; DMA base register for Channel 1 | ||
| 77 | extrn DMABase2:near ; DMA base register for Channel 2 | ||
| 78 | extrn DMABase3:near ; DMA base register for Channel 3 | ||
| 79 | extrn DMABase5:near ; DMA base register for Channel 5 | ||
| 80 | extrn DMABase6:near ; DMA base register for Channel 6 | ||
| 81 | extrn DMABase7:near ; DMA base register for Channel 7 | ||
| 82 | extrn DMACnt0:near ; DMA count register for Channel 0 | ||
| 83 | extrn DMACnt1:near ; DMA count register for Channel 1 | ||
| 84 | extrn DMACnt2:near ; DMA count register for Channel 2 | ||
| 85 | extrn DMACnt3:near ; DMA count register for Channel 3 | ||
| 86 | extrn DMACnt5:near ; DMA count register for Channel 5 | ||
| 87 | extrn DMACnt6:near ; DMA count register for Channel 6 | ||
| 88 | extrn DMACnt7:near ; DMA count register for Channel 7 | ||
| 89 | extrn DMAPg0:near ; DMA page register for Channel 0 | ||
| 90 | extrn DMAPg1:near ; DMA page register for Channel 1 | ||
| 91 | extrn DMAPg2:near ; DMA page register for Channel 2 | ||
| 92 | extrn DMAPg3:near ; DMA page register for Channel 3 | ||
| 93 | extrn DMAPg5:near ; DMA page register for Channel 5 | ||
| 94 | extrn DMAPg6:near ; DMA page register for Channel 6 | ||
| 95 | extrn DMAPg7:near ; DMA page register for Channel 7 | ||
| 96 | extrn DMAClrFF1:near ; clear flip-flop cmd for channels 0-3 | ||
| 97 | extrn DMAClrFF2:near ; clear flip-flop cmd for channels 5-7 | ||
| 98 | extrn DMAMode1:near ; Mode register for channels 0-3 | ||
| 99 | extrn DMAMode2:near ; Mode register for channels 4-7 | ||
| 100 | |||
| 101 | _TEXT ends | ||
| 102 | |||
| 103 | ;****************************************************************************** | ||
| 104 | ; S E G M E N T D E F I N I T I O N | ||
| 105 | ;****************************************************************************** | ||
| 106 | |||
| 107 | ; | ||
| 108 | ;------------------------------------------------------------------------------ | ||
| 109 | _TEXT segment | ||
| 110 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 111 | ; | ||
| 112 | ; IOTrapTab | ||
| 113 | ; One entry per port in the I/O space from 00h to FFh. | ||
| 114 | ; Note that ports not specifically mapped otherwise(by IOT_OEM or | ||
| 115 | ; LIM emulation and whose least significant 10 bits are less than | ||
| 116 | ; 100h are also dispatched through this table(upper 6 bits assumed to | ||
| 117 | ; be intended as zero since some earlier systems only had 10 bits of | ||
| 118 | ; I/O addressing). | ||
| 119 | ; | ||
| 120 | IOTrap_Tab label word | ||
| 121 | dw offset _TEXT:DMAbase0 ; 0 DMA base register for Channel 0 | ||
| 122 | dw offset _TEXT:DMACnt0 ; 1 DMA count register for Channel 0 | ||
| 123 | dw offset _TEXT:DMABase1 ; 2 DMA base register for Channel 1 | ||
| 124 | dw offset _TEXT:DMACnt1 ; 3 DMA count register for Channel 1 | ||
| 125 | dw offset _TEXT:DMABase2 ; 4 DMA base register for Channel 2 | ||
| 126 | dw offset _TEXT:DMACnt2 ; 5 DMA count register for Channel 2 | ||
| 127 | dw offset _TEXT:DMABase3 ; 6 DMA base register for Channel 3 | ||
| 128 | dw offset _TEXT:DMACnt3 ; 7 DMA count register for Channel 3 | ||
| 129 | dw offset _TEXT:IOT_BadT ; 8 | ||
| 130 | dw offset _TEXT:IOT_BadT ; 9 | ||
| 131 | dw offset _TEXT:IOT_BadT ; a | ||
| 132 | dw offset _TEXT:DMAMode1 ; b DMA Mode Register for for Ch 0-3 | ||
| 133 | dw offset _TEXT:DMAClrFF1 ; c clear flip-flop cmd for channels 0-3 | ||
| 134 | dw offset _TEXT:IOT_BadT ; d | ||
| 135 | dw offset _TEXT:IOT_BadT ; e | ||
| 136 | dw offset _TEXT:IOT_BadT ; f | ||
| 137 | dw offset _TEXT:IOT_BadT ; 10 | ||
| 138 | dw offset _TEXT:IOT_BadT ; 11 | ||
| 139 | dw offset _TEXT:IOT_BadT ; 12 | ||
| 140 | dw offset _TEXT:IOT_BadT ; 13 | ||
| 141 | dw offset _TEXT:IOT_BadT ; 14 | ||
| 142 | dw offset _TEXT:IOT_BadT ; 15 | ||
| 143 | dw offset _TEXT:IOT_BadT ; 16 | ||
| 144 | dw offset _TEXT:IOT_BadT ; 17 | ||
| 145 | dw offset _TEXT:IOT_BadT ; 18 | ||
| 146 | dw offset _TEXT:IOT_BadT ; 19 | ||
| 147 | dw offset _TEXT:IOT_BadT ; 1a | ||
| 148 | dw offset _TEXT:IOT_BadT ; 1b | ||
| 149 | dw offset _TEXT:IOT_BadT ; 1c | ||
| 150 | dw offset _TEXT:IOT_BadT ; 1d | ||
| 151 | dw offset _TEXT:IOT_BadT ; 1e | ||
| 152 | dw offset _TEXT:IOT_BadT ; 1f | ||
| 153 | dw offset _TEXT:IOT_BadT ; 20 | ||
| 154 | dw offset _TEXT:IOT_BadT ; 21 | ||
| 155 | dw offset _TEXT:IOT_BadT ; 22 | ||
| 156 | dw offset _TEXT:IOT_BadT ; 23 | ||
| 157 | dw offset _TEXT:IOT_BadT ; 24 | ||
| 158 | dw offset _TEXT:IOT_BadT ; 25 | ||
| 159 | dw offset _TEXT:IOT_BadT ; 26 | ||
| 160 | dw offset _TEXT:IOT_BadT ; 27 | ||
| 161 | dw offset _TEXT:IOT_BadT ; 28 | ||
| 162 | dw offset _TEXT:IOT_BadT ; 29 | ||
| 163 | dw offset _TEXT:IOT_BadT ; 2a | ||
| 164 | dw offset _TEXT:IOT_BadT ; 2b | ||
| 165 | dw offset _TEXT:IOT_BadT ; 2c | ||
| 166 | dw offset _TEXT:IOT_BadT ; 2d | ||
| 167 | dw offset _TEXT:IOT_BadT ; 2e | ||
| 168 | dw offset _TEXT:IOT_BadT ; 2f | ||
| 169 | dw offset _TEXT:IOT_BadT ; 30 | ||
| 170 | dw offset _TEXT:IOT_BadT ; 31 | ||
| 171 | dw offset _TEXT:IOT_BadT ; 32 | ||
| 172 | dw offset _TEXT:IOT_BadT ; 33 | ||
| 173 | dw offset _TEXT:IOT_BadT ; 34 | ||
| 174 | dw offset _TEXT:IOT_BadT ; 35 | ||
| 175 | dw offset _TEXT:IOT_BadT ; 36 | ||
| 176 | dw offset _TEXT:IOT_BadT ; 37 | ||
| 177 | dw offset _TEXT:IOT_BadT ; 38 | ||
| 178 | dw offset _TEXT:IOT_BadT ; 39 | ||
| 179 | dw offset _TEXT:IOT_BadT ; 3a | ||
| 180 | dw offset _TEXT:IOT_BadT ; 3b | ||
| 181 | dw offset _TEXT:IOT_BadT ; 3c | ||
| 182 | dw offset _TEXT:IOT_BadT ; 3d | ||
| 183 | dw offset _TEXT:IOT_BadT ; 3e | ||
| 184 | dw offset _TEXT:IOT_BadT ; 3f | ||
| 185 | dw offset _TEXT:IOT_BadT ; 40 | ||
| 186 | dw offset _TEXT:IOT_BadT ; 41 | ||
| 187 | dw offset _TEXT:IOT_BadT ; 42 | ||
| 188 | dw offset _TEXT:IOT_BadT ; 43 | ||
| 189 | dw offset _TEXT:IOT_BadT ; 44 | ||
| 190 | dw offset _TEXT:IOT_BadT ; 45 | ||
| 191 | dw offset _TEXT:IOT_BadT ; 46 | ||
| 192 | dw offset _TEXT:IOT_BadT ; 47 | ||
| 193 | dw offset _TEXT:IOT_BadT ; 48 | ||
| 194 | dw offset _TEXT:IOT_BadT ; 49 | ||
| 195 | dw offset _TEXT:IOT_BadT ; 4a | ||
| 196 | dw offset _TEXT:IOT_BadT ; 4b | ||
| 197 | dw offset _TEXT:IOT_BadT ; 4c | ||
| 198 | dw offset _TEXT:IOT_BadT ; 4d | ||
| 199 | dw offset _TEXT:IOT_BadT ; 4e | ||
| 200 | dw offset _TEXT:IOT_BadT ; 4f | ||
| 201 | dw offset _TEXT:IOT_BadT ; 50 | ||
| 202 | dw offset _TEXT:IOT_BadT ; 51 | ||
| 203 | dw offset _TEXT:IOT_BadT ; 52 | ||
| 204 | dw offset _TEXT:IOT_BadT ; 53 | ||
| 205 | dw offset _TEXT:IOT_BadT ; 54 | ||
| 206 | dw offset _TEXT:IOT_BadT ; 55 | ||
| 207 | dw offset _TEXT:IOT_BadT ; 56 | ||
| 208 | dw offset _TEXT:IOT_BadT ; 57 | ||
| 209 | dw offset _TEXT:IOT_BadT ; 58 | ||
| 210 | dw offset _TEXT:IOT_BadT ; 59 | ||
| 211 | dw offset _TEXT:IOT_BadT ; 5a | ||
| 212 | dw offset _TEXT:IOT_BadT ; 5b | ||
| 213 | dw offset _TEXT:IOT_BadT ; 5c | ||
| 214 | dw offset _TEXT:IOT_BadT ; 5d | ||
| 215 | dw offset _TEXT:IOT_BadT ; 5e | ||
| 216 | dw offset _TEXT:IOT_BadT ; 5f | ||
| 217 | dw offset _TEXT:A20_Handler ; A20 watch on kybd data port | ||
| 218 | dw offset _TEXT:IOT_BadT ; 61 | ||
| 219 | dw offset _TEXT:IOT_BadT ; 62 | ||
| 220 | dw offset _TEXT:IOT_BadT ; 63 | ||
| 221 | dw offset _TEXT:A20_Handler ; A20 watch on kybd cmd port | ||
| 222 | dw offset _TEXT:IOT_BadT ; 65 | ||
| 223 | dw offset _TEXT:IOT_BadT ; 66 | ||
| 224 | dw offset _TEXT:IOT_BadT ; 67 | ||
| 225 | dw offset _TEXT:IOT_BadT ; 68 | ||
| 226 | dw offset _TEXT:IOT_BadT ; 69 | ||
| 227 | dw offset _TEXT:IOT_BadT ; 6a | ||
| 228 | dw offset _TEXT:IOT_BadT ; 6b | ||
| 229 | dw offset _TEXT:IOT_BadT ; 6c | ||
| 230 | dw offset _TEXT:IOT_BadT ; 6d | ||
| 231 | dw offset _TEXT:IOT_BadT ; 6e | ||
| 232 | dw offset _TEXT:IOT_BadT ; 6f | ||
| 233 | dw offset _TEXT:IOT_BadT ; 70 | ||
| 234 | dw offset _TEXT:IOT_BadT ; 71 | ||
| 235 | dw offset _TEXT:IOT_BadT ; 72 | ||
| 236 | dw offset _TEXT:IOT_BadT ; 73 | ||
| 237 | dw offset _TEXT:IOT_BadT ; 74 | ||
| 238 | dw offset _TEXT:IOT_BadT ; 75 | ||
| 239 | dw offset _TEXT:IOT_BadT ; 76 | ||
| 240 | dw offset _TEXT:IOT_BadT ; 77 | ||
| 241 | dw offset _TEXT:IOT_BadT ; 78 | ||
| 242 | dw offset _TEXT:IOT_BadT ; 79 | ||
| 243 | dw offset _TEXT:IOT_BadT ; 7a | ||
| 244 | dw offset _TEXT:IOT_BadT ; 7b | ||
| 245 | dw offset _TEXT:IOT_BadT ; 7c | ||
| 246 | dw offset _TEXT:IOT_BadT ; 7d | ||
| 247 | dw offset _TEXT:IOT_BadT ; 7e | ||
| 248 | dw offset _TEXT:IOT_BadT ; 7f | ||
| 249 | dw offset _TEXT:IOT_BadT ; 80 | ||
| 250 | dw offset _TEXT:DMAPg2 ; 81 DMA page register for Channel 2 | ||
| 251 | dw offset _TEXT:DMAPg3 ; 82 DMA page register for Channel 3 | ||
| 252 | dw offset _TEXT:DMAPg1 ; 83 DMA page register for Channel 1 | ||
| 253 | dw offset _TEXT:RRP_Handler ; return to real port | ||
| 254 | dw offset _TEXT:RRP_Handler ; return to real port | ||
| 255 | dw offset _TEXT:IOT_BadT ; 86 | ||
| 256 | dw offset _TEXT:DMAPg0 ; 87 DMA page register for Channel 0 | ||
| 257 | dw offset _TEXT:IOT_BadT ; 88 | ||
| 258 | dw offset _TEXT:DMAPg6 ; 89 DMA page register for Channel 6 | ||
| 259 | dw offset _TEXT:DMAPg7 ; 8a DMA page register for Channel 7 | ||
| 260 | dw offset _TEXT:DMAPg5 ; 8b DMA page register for Channel 5 | ||
| 261 | dw offset _TEXT:IOT_BadT ; 8c | ||
| 262 | dw offset _TEXT:IOT_BadT ; 8d | ||
| 263 | dw offset _TEXT:IOT_BadT ; 8e | ||
| 264 | dw offset _TEXT:IOT_BadT ; 8f | ||
| 265 | dw offset _TEXT:IOT_BadT ; 90 | ||
| 266 | dw offset _TEXT:DMAPg2 ; 91 DMA page register for Channel 2 | ||
| 267 | dw offset _TEXT:DMAPg3 ; 92 DMA page register for Channel 3 | ||
| 268 | dw offset _TEXT:DMAPg1 ; 93 DMA page register for Channel 1 | ||
| 269 | dw offset _TEXT:IOT_BadT ; 94 | ||
| 270 | dw offset _TEXT:IOT_BadT ; 95 | ||
| 271 | dw offset _TEXT:IOT_BadT ; 96 | ||
| 272 | dw offset _TEXT:IOT_BadT ; 97 DMA page register for Channel 0 | ||
| 273 | dw offset _TEXT:IOT_BadT ; 98 | ||
| 274 | dw offset _TEXT:DMAPg6 ; 99 DMA page register for Channel 6 | ||
| 275 | dw offset _TEXT:DMAPg7 ; 9a DMA page register for Channel 7 | ||
| 276 | dw offset _TEXT:DMAPg5 ; 9b DMA page register for Channel 5 | ||
| 277 | dw offset _TEXT:IOT_BadT ; 9c | ||
| 278 | dw offset _TEXT:IOT_BadT ; 9d | ||
| 279 | dw offset _TEXT:IOT_BadT ; 9e | ||
| 280 | dw offset _TEXT:IOT_BadT ; 9f | ||
| 281 | dw offset _TEXT:IOT_BadT ; a0 | ||
| 282 | dw offset _TEXT:IOT_BadT ; a1 | ||
| 283 | dw offset _TEXT:IOT_BadT ; a2 | ||
| 284 | dw offset _TEXT:IOT_BadT ; a3 | ||
| 285 | dw offset _TEXT:IOT_BadT ; a4 | ||
| 286 | dw offset _TEXT:IOT_BadT ; a5 | ||
| 287 | dw offset _TEXT:IOT_BadT ; a6 | ||
| 288 | dw offset _TEXT:IOT_BadT ; a7 | ||
| 289 | dw offset _TEXT:IOT_BadT ; a8 | ||
| 290 | dw offset _TEXT:IOT_BadT ; a9 | ||
| 291 | dw offset _TEXT:IOT_BadT ; aa | ||
| 292 | dw offset _TEXT:IOT_BadT ; ab | ||
| 293 | dw offset _TEXT:IOT_BadT ; ac | ||
| 294 | dw offset _TEXT:IOT_BadT ; ad | ||
| 295 | dw offset _TEXT:IOT_BadT ; ae | ||
| 296 | dw offset _TEXT:IOT_BadT ; af | ||
| 297 | dw offset _TEXT:IOT_BadT ; b0 | ||
| 298 | dw offset _TEXT:IOT_BadT ; b1 | ||
| 299 | dw offset _TEXT:IOT_BadT ; b2 | ||
| 300 | dw offset _TEXT:IOT_BadT ; b3 | ||
| 301 | dw offset _TEXT:IOT_BadT ; b4 | ||
| 302 | dw offset _TEXT:IOT_BadT ; b5 | ||
| 303 | dw offset _TEXT:IOT_BadT ; b6 | ||
| 304 | dw offset _TEXT:IOT_BadT ; b7 | ||
| 305 | dw offset _TEXT:IOT_BadT ; b8 | ||
| 306 | dw offset _TEXT:IOT_BadT ; b9 | ||
| 307 | dw offset _TEXT:IOT_BadT ; ba | ||
| 308 | dw offset _TEXT:IOT_BadT ; bb | ||
| 309 | dw offset _TEXT:IOT_BadT ; bc | ||
| 310 | dw offset _TEXT:IOT_BadT ; bd | ||
| 311 | dw offset _TEXT:IOT_BadT ; be | ||
| 312 | dw offset _TEXT:IOT_BadT ; bf | ||
| 313 | dw offset _TEXT:IOT_BadT ; c0 DMA base register for Channel 4 | ||
| 314 | dw offset _TEXT:IOT_BadT ; c1 | ||
| 315 | dw offset _TEXT:IOT_BadT ; c2 DMA count register for Channel 4 | ||
| 316 | dw offset _TEXT:IOT_BadT ; c3 | ||
| 317 | dw offset _TEXT:DMABase5 ; c4 DMA base register for Channel 5 | ||
| 318 | dw offset _TEXT:IOT_BadT ; c5 | ||
| 319 | dw offset _TEXT:DMACnt5 ; c6 DMA count register for Channel 5 | ||
| 320 | dw offset _TEXT:IOT_BadT ; c7 | ||
| 321 | dw offset _TEXT:DMABase6 ; c8 DMA base register for Channel 6 | ||
| 322 | dw offset _TEXT:IOT_BadT ; c9 | ||
| 323 | dw offset _TEXT:DMACnt6 ; ca DMA count register for Channel 6 | ||
| 324 | dw offset _TEXT:IOT_BadT ; cb | ||
| 325 | dw offset _TEXT:DMABase7 ; cc DMA base register for Channel 7 | ||
| 326 | dw offset _TEXT:IOT_BadT ; cd | ||
| 327 | dw offset _TEXT:DMACnt7 ; ce DMA count register for Channel 7 | ||
| 328 | dw offset _TEXT:IOT_BadT ; cf | ||
| 329 | dw offset _TEXT:IOT_BadT ; d0 | ||
| 330 | dw offset _TEXT:IOT_BadT ; d1 | ||
| 331 | dw offset _TEXT:IOT_BadT ; d2 | ||
| 332 | dw offset _TEXT:IOT_BadT ; d3 | ||
| 333 | dw offset _TEXT:IOT_BadT ; d4 | ||
| 334 | dw offset _TEXT:IOT_BadT ; d5 | ||
| 335 | dw offset _TEXT:DMAMode2 ; d6 DMA Mode Register for channels 4-7 | ||
| 336 | dw offset _TEXT:IOT_BadT ; d7 | ||
| 337 | dw offset _TEXT:DMAClrFF2 ; d8 clear flip-flop cmd for channels 5-7 | ||
| 338 | dw offset _TEXT:IOT_BadT ; d9 | ||
| 339 | dw offset _TEXT:IOT_BadT ; da | ||
| 340 | dw offset _TEXT:IOT_BadT ; db | ||
| 341 | dw offset _TEXT:IOT_BadT ; dc | ||
| 342 | dw offset _TEXT:IOT_BadT ; dd | ||
| 343 | dw offset _TEXT:IOT_BadT ; de | ||
| 344 | dw offset _TEXT:IOT_BadT ; df | ||
| 345 | dw offset _TEXT:IOT_BadT ; e0 | ||
| 346 | dw offset _TEXT:IOT_BadT ; e1 | ||
| 347 | dw offset _TEXT:IOT_BadT ; e2 | ||
| 348 | dw offset _TEXT:IOT_BadT ; e3 | ||
| 349 | dw offset _TEXT:IOT_BadT ; e4 | ||
| 350 | dw offset _TEXT:IOT_BadT ; e5 | ||
| 351 | dw offset _TEXT:IOT_BadT ; e6 | ||
| 352 | dw offset _TEXT:IOT_BadT ; e7 | ||
| 353 | dw offset _TEXT:IOT_BadT ; e8 | ||
| 354 | dw offset _TEXT:IOT_BadT ; e9 | ||
| 355 | dw offset _TEXT:IOT_BadT ; ea | ||
| 356 | dw offset _TEXT:IOT_BadT ; eb | ||
| 357 | dw offset _TEXT:IOT_BadT ; ec | ||
| 358 | dw offset _TEXT:IOT_BadT ; ed | ||
| 359 | dw offset _TEXT:IOT_BadT ; ee | ||
| 360 | dw offset _TEXT:IOT_BadT ; ef | ||
| 361 | dw offset _TEXT:IOT_BadT ; f0 | ||
| 362 | dw offset _TEXT:IOT_BadT ; f1 | ||
| 363 | dw offset _TEXT:IOT_BadT ; f2 | ||
| 364 | dw offset _TEXT:IOT_BadT ; f3 | ||
| 365 | dw offset _TEXT:IOT_BadT ; f4 | ||
| 366 | dw offset _TEXT:IOT_BadT ; f5 | ||
| 367 | dw offset _TEXT:IOT_BadT ; f6 | ||
| 368 | dw offset _TEXT:IOT_BadT ; f7 | ||
| 369 | dw offset _TEXT:IOT_BadT ; f8 | ||
| 370 | dw offset _TEXT:IOT_BadT ; f9 | ||
| 371 | dw offset _TEXT:IOT_BadT ; fa | ||
| 372 | dw offset _TEXT:IOT_BadT ; fb | ||
| 373 | dw offset _TEXT:IOT_BadT ; fc | ||
| 374 | dw offset _TEXT:IOT_BadT ; fd | ||
| 375 | dw offset _TEXT:IOT_BadT ; fe | ||
| 376 | dw offset _TEXT:IOT_BadT ; ff | ||
| 377 | |||
| 378 | ;****************************************************************************** | ||
| 379 | ; IOT_BadT - GP fault on Unknown I/O address | ||
| 380 | ; | ||
| 381 | ; DESCRIPTION: This routine is entered by being in the IOTrap_Tab above | ||
| 382 | ; and also for I/O ports which are not LIM(DMA) ports and are not | ||
| 383 | ; emulated by IOT_OEM routine below and the first 10 bits of the | ||
| 384 | ; address is greater than 100h. Note that only the first 10 bits | ||
| 385 | ; of the port (times 2) is passed in BX. If the entire port | ||
| 386 | ; address is desired, it is available on the stack as the value | ||
| 387 | ; which is popped into DX. | ||
| 388 | ; | ||
| 389 | ; ENTRY: Protected Mode Ring 0 | ||
| 390 | ; return address, DX, DS, return address on stack | ||
| 391 | ; AL = byte to output to port. | ||
| 392 | ; BX == 2 * port address(either 0-1FE or 200-7FE) | ||
| 393 | ; DX == 0 => Emulate input | ||
| 394 | ; <> 0 => Emulate output | ||
| 395 | ; DS = DGROUP | ||
| 396 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 397 | ; | ||
| 398 | ; | ||
| 399 | ; EXIT: Protected Mode Ring 0 | ||
| 400 | ; First return address, pop'd from stack. | ||
| 401 | ; DX and DS restored from stack. | ||
| 402 | ; BX = DX on entry | ||
| 403 | ; STC => I/O NOT emulated. | ||
| 404 | ; | ||
| 405 | ; WARNING:*********** | ||
| 406 | ; This routine is closely allied with IOTrap which is in IOTrap. | ||
| 407 | ; It is assumed that IOTrap puts the stack in a certain state! | ||
| 408 | ; *********** | ||
| 409 | |||
| 410 | ; USED: Flags | ||
| 411 | ; STACK: | ||
| 412 | ;------------------------------------------------------------------------------ | ||
| 413 | ; | ||
| 414 | IOT_BadT proc near | ||
| 415 | pop bx ; dump return address | ||
| 416 | mov bx,dx ; restore BX | ||
| 417 | pop dx ; restore DX(port address) | ||
| 418 | pop ds ; restore DS | ||
| 419 | stc ; port not emulated ! | ||
| 420 | ret ; and return | ||
| 421 | IOT_BadT endp | ||
| 422 | |||
| 423 | ;****************************************************************************** | ||
| 424 | ; IOT_OEM - Handles OEM specific I/O traps | ||
| 425 | ; | ||
| 426 | ; ENTRY: Protected Mode Ring 0 | ||
| 427 | ; AL = byte to output to port. | ||
| 428 | ; DX = port address for I/O. | ||
| 429 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 430 | ; BX = 0 => Emulate Input. | ||
| 431 | ; <>0 => Emulate Output. | ||
| 432 | ; DS = DGROUP | ||
| 433 | ; stack: near return to IOTrap, DX, DS, near return from IOTrap | ||
| 434 | ; | ||
| 435 | ; EXIT: Protected Mode Ring 0 | ||
| 436 | ; Either emulate I/O and pop return, DX, DS from stack and RET | ||
| 437 | ; with CF = 1(CF = 0 if I/O is to be ignored!?!?). | ||
| 438 | ; Or just return(no emulation done) | ||
| 439 | ; | ||
| 440 | ; | ||
| 441 | ; WARNING:*********** | ||
| 442 | ; This routine is closely allied with IOTrap. | ||
| 443 | ; It assumes that the stack is in a certain state! | ||
| 444 | ; *********** | ||
| 445 | ; | ||
| 446 | ; | ||
| 447 | ; USED: Flags | ||
| 448 | ; STACK: | ||
| 449 | ;------------------------------------------------------------------------------ | ||
| 450 | IOT_OEM proc near | ||
| 451 | ; cmp dx,???? | ||
| 452 | ; jnz NoEmulation | ||
| 453 | ; or bx,bx | ||
| 454 | ; jnz NoEmulation | ||
| 455 | ; mov al,???? ;emulate input | ||
| 456 | ; pop dx ;remove return | ||
| 457 | ; pop dx ;restore DX | ||
| 458 | ; pop ds ;restore DS | ||
| 459 | ; ret ;return from IOTRAP | ||
| 460 | ; | ||
| 461 | ;NoEmulation: | ||
| 462 | ret ; no emulation | ||
| 463 | IOT_OEM endp | ||
| 464 | |||
| 465 | |||
| 466 | _TEXT ends | ||
| 467 | |||
| 468 | end | ||
| 469 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/UTIL.ASM b/v4.0/src/MEMM/MEMM/UTIL.ASM new file mode 100644 index 0000000..221efdf --- /dev/null +++ b/v4.0/src/MEMM/MEMM/UTIL.ASM | |||
| @@ -0,0 +1,335 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title UTIL - general MEMM utilities | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: UTIL - utilities | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 11, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/11/86 Original from i286.asm | ||
| 27 | ; 06/18/86 0.01 in GoVirtual - added code to init VDM state variables | ||
| 28 | ; 06/25/86 0.02 in GoVirtual - more DiagByte state variable. | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 06/29/86 0.02 Changed check code for ROM write protect state | ||
| 31 | ; 07/01/86 0.03 Added call to InitDMA in GoVirtual | ||
| 32 | ; 07/05/86 0.04 Moved code to InitLOCK | ||
| 33 | ; 07/05/86 0.04 Added FarGoVirtual and moved IsReal to PRINT.ASM | ||
| 34 | ; 07/06/86 0.04 Changed assume to DGROUP and moved stack out of DGROUP | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional Description: | ||
| 39 | ; | ||
| 40 | ; | ||
| 41 | ;****************************************************************************** | ||
| 42 | .lfcond ; list false conditionals | ||
| 43 | .386p | ||
| 44 | |||
| 45 | public GoVirtual | ||
| 46 | public FarGoVirtual | ||
| 47 | public SelToSeg | ||
| 48 | |||
| 49 | ;****************************************************************************** | ||
| 50 | ; D E F I N E S | ||
| 51 | ;****************************************************************************** | ||
| 52 | include VDMseg.inc | ||
| 53 | include VDMsel.inc | ||
| 54 | include desc.inc | ||
| 55 | include instr386.inc | ||
| 56 | include oemdep.inc | ||
| 57 | |||
| 58 | FALSE equ 0 | ||
| 59 | TRUE equ not FALSE | ||
| 60 | |||
| 61 | ;****************************************************************************** | ||
| 62 | ; E X T E R N A L R E F E R E N C E S | ||
| 63 | ;****************************************************************************** | ||
| 64 | _DATA SEGMENT | ||
| 65 | |||
| 66 | extrn TEXT_Seg:word ; segment for _TEXT | ||
| 67 | extrn GDT_Seg:word ; segment for GDT | ||
| 68 | extrn TSS_Seg:word ; segment address of TSS | ||
| 69 | extrn Page_Dir:word ; 32-bit address of Page Directory Table | ||
| 70 | |||
| 71 | extrn Active_Status:byte | ||
| 72 | |||
| 73 | _DATA ENDS | ||
| 74 | |||
| 75 | _TEXT SEGMENT | ||
| 76 | |||
| 77 | extrn InitDMA:near ; (elimtrap.asm) | ||
| 78 | extrn EnableA20:near ; (modesw.asm) | ||
| 79 | extrn A20_Trap_Init:near ; (a20trap.asm) | ||
| 80 | extrn RR_Trap_Init:near ; (RRTrap.asm) | ||
| 81 | extrn OEM_Trap_Init:near ; (OEMTrap.asm) | ||
| 82 | |||
| 83 | _TEXT ENDS | ||
| 84 | |||
| 85 | STACK segment | ||
| 86 | extrn kstack_top:byte | ||
| 87 | STACK ends | ||
| 88 | |||
| 89 | ifndef NOHIMEM | ||
| 90 | |||
| 91 | R_CODE segment | ||
| 92 | extrn InitLock:far | ||
| 93 | R_CODE ends | ||
| 94 | |||
| 95 | endif | ||
| 96 | |||
| 97 | page | ||
| 98 | ;****************************************************************************** | ||
| 99 | ; S E G M E N T D E F I N I T I O N S | ||
| 100 | ;****************************************************************************** | ||
| 101 | |||
| 102 | ;****************************************************************************** | ||
| 103 | ; _TEXT segment | ||
| 104 | ;****************************************************************************** | ||
| 105 | |||
| 106 | _TEXT SEGMENT | ||
| 107 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 108 | |||
| 109 | ;****************************************************************************** | ||
| 110 | ; FarGoVirtual - far link for GoVirtual | ||
| 111 | ; | ||
| 112 | ; NOTE: this is a FAR routine. | ||
| 113 | ; | ||
| 114 | ; ENTRY: Real Mode | ||
| 115 | ; DS = DGROUP | ||
| 116 | ; | ||
| 117 | ; EXIT: Virtual Mode | ||
| 118 | ; VDM state variables initialized | ||
| 119 | ; | ||
| 120 | ; USED: none | ||
| 121 | ; | ||
| 122 | ;****************************************************************************** | ||
| 123 | FarGoVirtual proc far | ||
| 124 | call GoVirtual | ||
| 125 | ret | ||
| 126 | FarGoVirtual endp | ||
| 127 | |||
| 128 | ;****************************************************************************** | ||
| 129 | ; GoVirtual - go to virtual mode | ||
| 130 | ; | ||
| 131 | ; ENTRY: Real Mode | ||
| 132 | ; DS = DGROUP | ||
| 133 | ; | ||
| 134 | ; EXIT: Virtual Mode | ||
| 135 | ; VDM state variables initialized | ||
| 136 | ; | ||
| 137 | ; USED: none | ||
| 138 | ; | ||
| 139 | ;****************************************************************************** | ||
| 140 | GoVirtual proc near | ||
| 141 | ; | ||
| 142 | PUSH_EAX | ||
| 143 | push bx | ||
| 144 | push bp | ||
| 145 | push ds | ||
| 146 | push es | ||
| 147 | PUSH_FS | ||
| 148 | PUSH_GS | ||
| 149 | ; | ||
| 150 | cli ; interrupts OFF | ||
| 151 | ; | ||
| 152 | ; init VDM state variables | ||
| 153 | ; | ||
| 154 | push es | ||
| 155 | mov ax,[TSS_Seg] | ||
| 156 | mov es,ax ; ES -> TSS | ||
| 157 | call A20_Trap_Init ; init a20 line watch | ||
| 158 | call RR_Trap_Init ; init return to real watch | ||
| 159 | call OEM_Trap_Init ; init any other I/O port watches | ||
| 160 | pop es | ||
| 161 | |||
| 162 | mov [Active_Status],1 | ||
| 163 | |||
| 164 | call InitDMA ; init DMA watcher | ||
| 165 | |||
| 166 | ifndef NOHIMEM | ||
| 167 | call FAR PTR InitLOCK ; init status of TABLE lock | ||
| 168 | endif | ||
| 169 | |||
| 170 | ; | ||
| 171 | ; mask off master 8259 to prevent all interrupts during setup | ||
| 172 | ; | ||
| 173 | call MaskIntAll ; Mask all interrupts | ||
| 174 | ; | ||
| 175 | ; Set the CPU into 386 protected mode. | ||
| 176 | ; | ||
| 177 | ; The following CPU registers are changed to have values | ||
| 178 | ; appropriate to protected mode operation: | ||
| 179 | ; | ||
| 180 | ; CS, DS, ES, SS, TR, LDT, Flags, MSW, GDT, IDT | ||
| 181 | call EnableA20 ; enable A20 address line | ||
| 182 | |||
| 183 | ; | ||
| 184 | ; load CR3 register for paging | ||
| 185 | ; | ||
| 186 | OP32 | ||
| 187 | mov ax,[Page_Dir] ; EAX = 32-bit address of Page Dir | ||
| 188 | |||
| 189 | MOV_CR3_EAX | ||
| 190 | |||
| 191 | ; | ||
| 192 | ; load gdt and ldt base registers | ||
| 193 | ; | ||
| 194 | mov ax,[GDT_Seg] | ||
| 195 | mov ds, ax ; DS:0 = ptr to gdt | ||
| 196 | lgdt qword ptr ds:[GDTD_GSEL] | ||
| 197 | lidt qword ptr ds:[IDTD_GSEL] | ||
| 198 | ; | ||
| 199 | ; go protected and enable paging - turn on bits in CR0 | ||
| 200 | ; | ||
| 201 | MOV_EAX_CR0 | ||
| 202 | |||
| 203 | OP32 | ||
| 204 | or ax,MSW_PROTECT ; or EAX,imm32 - enable PE bit - PROT MODE | ||
| 205 | dw 8000h ; - enable PG bit - PAGING | ||
| 206 | |||
| 207 | MOV_CR0_EAX | ||
| 208 | |||
| 209 | ; far jump to flush prefetch, and reload CS | ||
| 210 | |||
| 211 | db 0eah ; far jmp opcode | ||
| 212 | dw offset _TEXT:pm1 ; offset | ||
| 213 | dw VDMC_GSEL ; selector | ||
| 214 | pm1: | ||
| 215 | ; | ||
| 216 | ; We are now protected, set the Task Register and LDT Register | ||
| 217 | ; | ||
| 218 | mov ax,TSS_GSEL | ||
| 219 | ltr ax | ||
| 220 | |||
| 221 | xor ax, ax ; LDT is null, not needed | ||
| 222 | lldt ax | ||
| 223 | ; | ||
| 224 | ; save current stack pointer for after return to VM | ||
| 225 | ; | ||
| 226 | mov bx,ss ; BX = saved SS | ||
| 227 | mov bp,sp ; BP = saved SP | ||
| 228 | ; | ||
| 229 | ; set the stack selector to RING 0 stack | ||
| 230 | ; | ||
| 231 | mov ax, VDMS_GSEL | ||
| 232 | mov ss, ax | ||
| 233 | mov sp, offset STACK:kstack_top | ||
| 234 | ; | ||
| 235 | ; now reload DS and ES to be data selectors for protected mode | ||
| 236 | ; | ||
| 237 | mov ax, VDMD_GSEL | ||
| 238 | mov ds, ax | ||
| 239 | assume ds:DGROUP | ||
| 240 | mov es, ax | ||
| 241 | assume es:DGROUP | ||
| 242 | |||
| 243 | ; | ||
| 244 | ; reset NT bit so IRET won't attempt a task switch | ||
| 245 | ; | ||
| 246 | pushf | ||
| 247 | pop ax | ||
| 248 | and ax,0FFFh | ||
| 249 | push ax | ||
| 250 | popf | ||
| 251 | ; | ||
| 252 | ; build stack frame for IRET into virtual mode | ||
| 253 | ; | ||
| 254 | push 0 | ||
| 255 | push 0 ; GS | ||
| 256 | push 0 | ||
| 257 | push 0 ; FS | ||
| 258 | push 0 | ||
| 259 | push seg DGROUP ; DS (DGROUP for variable access) | ||
| 260 | push 0 | ||
| 261 | push 0 ; ES | ||
| 262 | |||
| 263 | push 0 | ||
| 264 | push bx ;* virtual mode SS | ||
| 265 | |||
| 266 | push 0 | ||
| 267 | push bp ;* virtual mode ESP | ||
| 268 | |||
| 269 | push 2 ; EFlags high, VM bit set | ||
| 270 | push 3000h ;* EFlags low, NT = 0, IOPL=3, CLI | ||
| 271 | |||
| 272 | push 0 | ||
| 273 | mov ax, [TEXT_Seg] | ||
| 274 | push ax ; CS | ||
| 275 | push 0 | ||
| 276 | mov ax, offset _TEXT:VM_return | ||
| 277 | push ax ; IP | ||
| 278 | |||
| 279 | OP32 ; 32 bit operand size override | ||
| 280 | iret | ||
| 281 | |||
| 282 | ; | ||
| 283 | ; Enter Virtual Mode here | ||
| 284 | ; | ||
| 285 | VM_return: | ||
| 286 | ; | ||
| 287 | ; re-enable interrupts | ||
| 288 | ; | ||
| 289 | call RestIntMask ; Restore interrupt mask | ||
| 290 | POP_GS | ||
| 291 | POP_FS | ||
| 292 | pop es | ||
| 293 | pop ds | ||
| 294 | pop bp | ||
| 295 | pop bx | ||
| 296 | POP_EAX | ||
| 297 | ret | ||
| 298 | GoVirtual endp | ||
| 299 | |||
| 300 | |||
| 301 | ;** SelToSeg - convert selector to a segment number | ||
| 302 | ; | ||
| 303 | ; The protected mode selector value is converted to a | ||
| 304 | ; real mode segment number. | ||
| 305 | ; | ||
| 306 | ; ENTRY BX = selector | ||
| 307 | ; EXIT AX = segment number | ||
| 308 | ; USES BX, Flags, other regs preserved | ||
| 309 | ; | ||
| 310 | ; WARNING This code only works on a 286. It can be | ||
| 311 | ; called only in protected mode. | ||
| 312 | |||
| 313 | SelToSeg proc near | ||
| 314 | push ds | ||
| 315 | mov ax,LDTD_GSEL | ||
| 316 | test bx,TAB_LDT ; is the selector in the LDT? | ||
| 317 | jnz sts_addr ; yes, | ||
| 318 | mov ax,GDTD_GSEL ; selector is in the GDT | ||
| 319 | sts_addr: | ||
| 320 | mov ds,ax | ||
| 321 | and bl,0F8h | ||
| 322 | |||
| 323 | mov ax,word ptr ds:[bx + 2] ; low 16 bits of base address | ||
| 324 | mov bh,ds:[bx + 4] ; high 8 bits of base address | ||
| 325 | shr ax,4 | ||
| 326 | shl bh,4 | ||
| 327 | mov bl,0 | ||
| 328 | add ax,bx ; AX = segment number for selector | ||
| 329 | pop ds | ||
| 330 | ret | ||
| 331 | SelToSeg endp | ||
| 332 | |||
| 333 | _TEXT ends | ||
| 334 | |||
| 335 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/VDMINIT.ASM b/v4.0/src/MEMM/MEMM/VDMINIT.ASM new file mode 100644 index 0000000..a6e7072 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VDMINIT.ASM | |||
| @@ -0,0 +1,527 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title VDM_Init - VDM initialization module | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: VDM_Init - VDM initialization routine | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: June 3,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/03/86 Original from VDM MAIN.ASM module | ||
| 27 | ; 06/16/86 0.01 Added code to dword align LL buffer | ||
| 28 | ; 06/21/86 0.02 moved cld in init_pages | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 07/06/86 0.04 changed assume to DGROUP and moved stack out of | ||
| 31 | ; DGROUP | ||
| 32 | ; 07/10/86 0.05 Init of RCODEA_GSEL | ||
| 33 | ; 07/10/86 0.05 Added PageT_Seg | ||
| 34 | ; 07/20/88 Removed debugger codes (pc) | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional Description: | ||
| 39 | ; | ||
| 40 | ; This module is the general initialization module for the Virtual DOS | ||
| 41 | ; Monitor part of MEMM. This module initializes the protected mode | ||
| 42 | ; GDT, IDT, TSS (and I/O BitMap), and the Page Tables. This module also | ||
| 43 | ; initializes all variables used by the VDM code. This module returns | ||
| 44 | ; to the calling routine in Virtual Mode. | ||
| 45 | ; | ||
| 46 | ;****************************************************************************** | ||
| 47 | .lfcond ; list false conditionals | ||
| 48 | .386p | ||
| 49 | ;****************************************************************************** | ||
| 50 | ; P U B L I C S | ||
| 51 | ;****************************************************************************** | ||
| 52 | |||
| 53 | public VDM_Init | ||
| 54 | public PageD_Seg | ||
| 55 | public PageT_Seg | ||
| 56 | public Page_Dir | ||
| 57 | |||
| 58 | ;****************************************************************************** | ||
| 59 | ; D E F I N E S | ||
| 60 | ;****************************************************************************** | ||
| 61 | include VDMseg.inc | ||
| 62 | include VDMsel.inc | ||
| 63 | include desc.inc | ||
| 64 | include instr386.inc | ||
| 65 | include page.inc | ||
| 66 | |||
| 67 | FALSE equ 0 | ||
| 68 | TRUE equ not FALSE | ||
| 69 | CR equ 0dh | ||
| 70 | LF equ 0ah | ||
| 71 | |||
| 72 | ;****************************************************************************** | ||
| 73 | ; E X T E R N A L R E F E R E N C E S | ||
| 74 | ;****************************************************************************** | ||
| 75 | _DATA SEGMENT | ||
| 76 | extrn P_TABLE_CNT:abs | ||
| 77 | extrn ELOff:word ; offset of LL buffer | ||
| 78 | _DATA ENDS | ||
| 79 | |||
| 80 | _TEXT SEGMENT | ||
| 81 | |||
| 82 | extrn InitBitMap:far ; (vminit.asm) | ||
| 83 | |||
| 84 | _TEXT ENDS | ||
| 85 | |||
| 86 | GDT SEGMENT | ||
| 87 | extrn GDTLEN:abs | ||
| 88 | GDT ENDS | ||
| 89 | |||
| 90 | IDT SEGMENT | ||
| 91 | extrn IDTLEN:abs | ||
| 92 | IDT ENDS | ||
| 93 | |||
| 94 | TSS SEGMENT | ||
| 95 | extrn TSSLEN:abs | ||
| 96 | TSS ENDS | ||
| 97 | |||
| 98 | PAGESEG SEGMENT | ||
| 99 | extrn Page_Area:byte | ||
| 100 | PAGESEG ENDS | ||
| 101 | |||
| 102 | |||
| 103 | LAST SEGMENT | ||
| 104 | extrn SetSegDesc:near | ||
| 105 | extrn SegTo24:near | ||
| 106 | extrn SetPageEntry:near | ||
| 107 | extrn get_init_a20_state:near | ||
| 108 | extrn OEM_Init_Diag_Page:near | ||
| 109 | LAST ENDS | ||
| 110 | |||
| 111 | ;****************************************************************************** | ||
| 112 | ; S E G M E N T D E F I N I T I O N S | ||
| 113 | ;****************************************************************************** | ||
| 114 | |||
| 115 | ; | ||
| 116 | ; Ring 0 stack for VDM exception/int handling | ||
| 117 | ; | ||
| 118 | STACK SEGMENT | ||
| 119 | stkstrt label byte | ||
| 120 | |||
| 121 | db STACK0_SIZE dup(0) | ||
| 122 | |||
| 123 | public kstack_top | ||
| 124 | kstack_top label byte | ||
| 125 | |||
| 126 | db 400h dup (0) | ||
| 127 | public exe_stack | ||
| 128 | exe_stack label byte | ||
| 129 | |||
| 130 | STACK ENDS | ||
| 131 | |||
| 132 | _DATA SEGMENT | ||
| 133 | |||
| 134 | PageD_Seg dw 0 ; segment for Page Directory | ||
| 135 | PageT_Seg dw 0 ; segment for Page Tables | ||
| 136 | Page_Dir dd 0 ; 32 bit address of Page Directory | ||
| 137 | |||
| 138 | _DATA ENDS | ||
| 139 | |||
| 140 | ; | ||
| 141 | ; code | ||
| 142 | ; | ||
| 143 | LAST SEGMENT | ||
| 144 | |||
| 145 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 146 | |||
| 147 | ;****************************************************************************** | ||
| 148 | ; VDM_Init - VDM initialization routine | ||
| 149 | ; | ||
| 150 | ; | ||
| 151 | ; ENTRY: Real Mode | ||
| 152 | ; DS = DGROUP | ||
| 153 | ; GDT = GDT segment | ||
| 154 | ; TSS = TSS segment | ||
| 155 | ; | ||
| 156 | ; EXIT: Real Mode | ||
| 157 | ; VDM Tables initialized | ||
| 158 | ; TSS initialized | ||
| 159 | ; | ||
| 160 | ; USED: none | ||
| 161 | ; | ||
| 162 | ;****************************************************************************** | ||
| 163 | VDM_Init proc near | ||
| 164 | ; | ||
| 165 | pushf | ||
| 166 | pusha | ||
| 167 | PUSH_EAX | ||
| 168 | push ds | ||
| 169 | push es | ||
| 170 | ; | ||
| 171 | push ds | ||
| 172 | pop es ; ES = data | ||
| 173 | ; | ||
| 174 | cli | ||
| 175 | ; | ||
| 176 | call InitGdt ;;; initialize GDT descriptors | ||
| 177 | ; | ||
| 178 | ; initialize Page Table, I/O Bit Map and LIM h/w emulator | ||
| 179 | ; | ||
| 180 | call InitPages ;;; initialize paging tables | ||
| 181 | call InitBitMap ;;; initialize I/O Bit Map | ||
| 182 | ; | ||
| 183 | ; initialize TSS,GDTR,IDTR | ||
| 184 | ; | ||
| 185 | ; set ring 0 SS:SP in the TSS so we can take outer ring traps | ||
| 186 | |||
| 187 | mov ax, seg TSS | ||
| 188 | mov es,ax ; ES -> TSS | ||
| 189 | xor di,di ; ES:DI -> TSS | ||
| 190 | |||
| 191 | mov ES:[di.TSS386_SS0], VDMS_GSEL | ||
| 192 | mov word ptr ES:[di.TSS386_ESP0lo], offset STACK:kstack_top | ||
| 193 | mov word ptr ES:[di.TSS386_ESP0hi], 0 | ||
| 194 | |||
| 195 | ; now set CR3 in the TSS | ||
| 196 | |||
| 197 | db 66h | ||
| 198 | mov ax,word ptr [Page_Dir] ; EAX = page dir 32 bit addr | ||
| 199 | db 66h | ||
| 200 | mov word ptr ES:[di.TSS386_CR3],ax ; mov EAX into CR3 spot in TSS | ||
| 201 | |||
| 202 | ; clear the TSS busy flag | ||
| 203 | |||
| 204 | mov ax,seg GDT | ||
| 205 | mov es, ax ; DS:0 = ptr to gdt | ||
| 206 | |||
| 207 | and byte ptr ES:[TSS_GSEL + 5], 11111101B | ||
| 208 | |||
| 209 | ; | ||
| 210 | ; dword align the LL buffer (move foward) | ||
| 211 | ; | ||
| 212 | mov ax,[ELOff] | ||
| 213 | and ax,0003h ; MOD 4 | ||
| 214 | mov bx,4 | ||
| 215 | sub bx,ax ; BX = amount to add to dword align | ||
| 216 | add [ELOff],bx ; dword align it... | ||
| 217 | |||
| 218 | ; | ||
| 219 | ; and return | ||
| 220 | ; | ||
| 221 | pop es | ||
| 222 | pop ds | ||
| 223 | POP_EAX | ||
| 224 | popa | ||
| 225 | popf | ||
| 226 | ret | ||
| 227 | VDM_Init endp | ||
| 228 | |||
| 229 | ;** InitGdt - initialise GDT | ||
| 230 | ; | ||
| 231 | ; Some of the GDT is statically initialised. This routine | ||
| 232 | ; initialises the rest, except the LDT pointer which | ||
| 233 | ; changes dynamically, and the VDM stack which changes too. | ||
| 234 | ; | ||
| 235 | ; ENTRY GDT:0 = GDT to use. | ||
| 236 | ; EXIT None | ||
| 237 | ; USES All except BP | ||
| 238 | ; | ||
| 239 | ; WARNING This code only works on a 286. | ||
| 240 | ; Designed to be called from real mode ONLY. | ||
| 241 | |||
| 242 | public InitGdt | ||
| 243 | InitGdt proc near | ||
| 244 | push es | ||
| 245 | |||
| 246 | mov ax,GDT | ||
| 247 | mov es,ax ; ES:0 -> gdt | ||
| 248 | |||
| 249 | mov ax,GDT | ||
| 250 | call SegTo24 | ||
| 251 | mov cx,GDTLEN | ||
| 252 | mov ah,D_DATA0 | ||
| 253 | mov bx,GDTD_GSEL | ||
| 254 | call SetSegDesc ; Set up GDT alias descriptor | ||
| 255 | |||
| 256 | mov ax,IDT | ||
| 257 | call SegTo24 | ||
| 258 | mov cx,IDTLEN | ||
| 259 | mov ah,D_DATA0 | ||
| 260 | mov bx,IDTD_GSEL | ||
| 261 | call SetSegDesc ; Set up IDT alias descriptor | ||
| 262 | |||
| 263 | mov ax,TSS | ||
| 264 | call SegTo24 | ||
| 265 | mov cx,TSSLEN | ||
| 266 | mov ah,D_386TSS0 | ||
| 267 | mov bx,TSS_GSEL | ||
| 268 | call SetSegDesc ; Set up TSS descriptor | ||
| 269 | |||
| 270 | mov ah,D_DATA0 | ||
| 271 | mov bx,TSSD_GSEL | ||
| 272 | call SetSegDesc ; Set up TSS alias descriptor | ||
| 273 | |||
| 274 | mov ax,seg _TEXT | ||
| 275 | call SegTo24 | ||
| 276 | mov cx,0 ; 0 = 64K size | ||
| 277 | mov ah,D_CODE0 | ||
| 278 | mov bx,VDMC_GSEL | ||
| 279 | call SetSegDesc ; Set up VDM Code descriptor | ||
| 280 | |||
| 281 | mov ax,_TEXT | ||
| 282 | call SegTo24 | ||
| 283 | mov cx,0 ; 0 = 64K size | ||
| 284 | mov ah,D_DATA0 | ||
| 285 | mov bx,VDMCA_GSEL | ||
| 286 | call SetSegDesc ; Set up VDM Code segment alias descr | ||
| 287 | |||
| 288 | mov ax,R_CODE | ||
| 289 | call SegTo24 | ||
| 290 | mov cx,0 ; 0 = 64K size | ||
| 291 | mov ah,D_DATA0 | ||
| 292 | mov bx,RCODEA_GSEL | ||
| 293 | call SetSegDesc ; Set up R_CODE segment alias descriptor | ||
| 294 | |||
| 295 | mov ax,seg DGROUP | ||
| 296 | call SegTo24 | ||
| 297 | mov cx,0 ; 0 = 64K size | ||
| 298 | mov ah,D_DATA0 | ||
| 299 | mov bx,VDMD_GSEL | ||
| 300 | call SetSegDesc ; Set up VDM Data descriptor | ||
| 301 | |||
| 302 | mov ax, seg STACK ; set up Ring 0 stack | ||
| 303 | call SegTo24 | ||
| 304 | mov cx, offset STACK:kstack_top | ||
| 305 | mov ah, D_DATA0 | ||
| 306 | mov bx, VDMS_GSEL | ||
| 307 | call SetSegDesc | ||
| 308 | |||
| 309 | pop es | ||
| 310 | ret | ||
| 311 | InitGdt endp | ||
| 312 | |||
| 313 | ;** InitPages - initialize Page Directory and Table | ||
| 314 | ; | ||
| 315 | ; This routine initializes a page directory and a page table. | ||
| 316 | ; Both of these are aligned on a physical page boundary by | ||
| 317 | ; starting them at the nearest bndry. Thus, the page table area | ||
| 318 | ; must be large enough to allow this alignment. | ||
| 319 | ; | ||
| 320 | ; The page dir and table set up by this routine maps the linear | ||
| 321 | ; addresses for Virtual mode programs into physical addresses using | ||
| 322 | ; the following scheme. | ||
| 323 | ; Linear Addr Physical Addr | ||
| 324 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 325 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 326 | ; 00110000h - 0100FFFFh 00100000h - 00FFFFFFh (top 15Meg of phys) | ||
| 327 | ; | ||
| 328 | ; ISP,PC: The above was totally unnecessary. When the A20 is turned | ||
| 329 | ; off the 64k at 1M is anyway unaccessible. A better mapping | ||
| 330 | ; has been implemented here: | ||
| 331 | ; | ||
| 332 | ; Linear Addr Physical Addr | ||
| 333 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 334 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 335 | ; 00110000h - 01000000h 00110000h - 01000000h (top 15Meg of phys) | ||
| 336 | ; 01000000h - 0100ffffh xxxx0000h - xxxxffffh (Done in OEMPROC) | ||
| 337 | ; | ||
| 338 | ; | ||
| 339 | ; ENTRY PAGESEG:Page_Area = pointer to page table area. | ||
| 340 | ; DS = DGROUP | ||
| 341 | ; EXIT DS:PageD_Seg = seg ptr for page directory. | ||
| 342 | ; DS:PageT_Seg = seg ptr for page tables | ||
| 343 | ; DS:Page_Dir = 32 bit addr for page directory. | ||
| 344 | ; USES none | ||
| 345 | ; | ||
| 346 | ; WARNING This code only works on a 286/386. | ||
| 347 | ; Designed to be called from real mode ONLY. | ||
| 348 | |||
| 349 | public InitPages | ||
| 350 | InitPages proc near | ||
| 351 | push ax | ||
| 352 | push bx | ||
| 353 | push cx | ||
| 354 | push dx | ||
| 355 | push di | ||
| 356 | push es | ||
| 357 | cld ; strings foward | ||
| 358 | ; | ||
| 359 | ; get physical pointer to nearest page | ||
| 360 | ; | ||
| 361 | mov ax,offset PAGESEG:Page_Area | ||
| 362 | add ax,15 | ||
| 363 | shr ax,4 ; AX = seg offset for page area | ||
| 364 | mov bx,PAGESEG ; PAGESEG is on a 256 boundary | ||
| 365 | add ax,bx ; AX = seg offset for page area | ||
| 366 | add ax,0FFh ; 0FFh = # of paras in page - 1 | ||
| 367 | xor al,al ; AX = seg addr for page align | ||
| 368 | mov [PageD_Seg],ax ; save it | ||
| 369 | ; | ||
| 370 | xor di,di | ||
| 371 | mov es,ax ; ES:DI = ptr to Page Directory | ||
| 372 | ; | ||
| 373 | mov dl,ah | ||
| 374 | shr dl,4 ; DL = bits 16 - 19 | ||
| 375 | xor dh,dh ; DX = bits 16 - 31 | ||
| 376 | shl ah,4 ; AX = bits 0 - 15 | ||
| 377 | mov word ptr [Page_Dir],AX ; DX,AX = 32 bit addr of Page Directory | ||
| 378 | mov word ptr [Page_Dir+2],DX ; save it | ||
| 379 | ; | ||
| 380 | ; get addr of Page Table for Page Directory entry | ||
| 381 | ; | ||
| 382 | add ax,1000h ; add page | ||
| 383 | adc dx,0h ; carry it => DX,AX = addr of page table | ||
| 384 | ; | ||
| 385 | ; set entries in page directory | ||
| 386 | ; | ||
| 387 | ; ES:[DI] pts to first entry in page directory | ||
| 388 | ; DX,AX = addr of first page table | ||
| 389 | ; | ||
| 390 | mov bh,0 | ||
| 391 | mov bl,P_AVAIL ; make table available to all | ||
| 392 | mov cx,P_TABLE_CNT ; set entries in page table directory | ||
| 393 | ; for existing page tables. | ||
| 394 | init_dir: | ||
| 395 | call SetPageEntry ; set entry for first page table | ||
| 396 | ; | ||
| 397 | ; ES:[DI] pts to next entry in page directory | ||
| 398 | add ax,1000h | ||
| 399 | adc dx,0 ; DX,AX = addr of next page table | ||
| 400 | loop init_dir ; set next entry in dir | ||
| 401 | ; | ||
| 402 | ; set rest of entries in page directory to not present | ||
| 403 | mov bh,0 | ||
| 404 | mov bl,NOT P_PRES ; mark page table as not present | ||
| 405 | mov cx,400h | ||
| 406 | sub cx,P_TABLE_CNT ; set rest of entries in directory | ||
| 407 | set_dir: | ||
| 408 | call SetPageEntry | ||
| 409 | loop set_dir | ||
| 410 | ; | ||
| 411 | ; set entries in page tables | ||
| 412 | ; | ||
| 413 | ; first 1 Meg | ||
| 414 | ; Linear Addr Physical Addr | ||
| 415 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 416 | ; | ||
| 417 | mov ax,[PageD_Seg] ; get segment for page directory | ||
| 418 | add ax,0100h ; add 1 page to get to first page table | ||
| 419 | mov [PageT_Seg],ax ; save it | ||
| 420 | |||
| 421 | mov es,ax | ||
| 422 | xor di,di ; ES:[DI] pts to first page table | ||
| 423 | |||
| 424 | xor dx,dx | ||
| 425 | xor ax,ax ; start with physical addr = 00000000h | ||
| 426 | mov bh,0 | ||
| 427 | mov bl,P_AVAIL ; make pages available to all | ||
| 428 | mov cx,100h ; set 1 Meg worth of entries in table | ||
| 429 | set1_tentry: | ||
| 430 | call SetPageEntry | ||
| 431 | ; ES:[DI] pts to next page table entry | ||
| 432 | add ax,1000h ; next physical page | ||
| 433 | adc dx,0h ; address in DX,AX | ||
| 434 | loop set1_tentry ;Q: done with this page table | ||
| 435 | ; N: the loop again | ||
| 436 | ; Y: set next entries in next tables | ||
| 437 | ; 64k wraparound at 1.0 Meg | ||
| 438 | ; Linear Addr Physical Addr | ||
| 439 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 440 | ; | ||
| 441 | call get_init_a20_state ; the physical a20 state has already | ||
| 442 | ; been established | ||
| 443 | jnz skip_wrap | ||
| 444 | xor dx,dx | ||
| 445 | xor ax,ax ; start with physical addr = 00000000h | ||
| 446 | skip_wrap: | ||
| 447 | mov bh,0 | ||
| 448 | mov bl,P_AVAIL ; make pages available to all | ||
| 449 | mov cx,10h ; set 64k worth of entries | ||
| 450 | set2_tentry: | ||
| 451 | call SetPageEntry | ||
| 452 | ; ES:[DI] pts to next page table entry | ||
| 453 | add ax,1000h ; next physical page | ||
| 454 | adc dx,0h ; address in DX,AX | ||
| 455 | loop set2_tentry ;Q: done with the wraparound entries | ||
| 456 | ; N: loop again | ||
| 457 | ; Y: all done | ||
| 458 | ; | ||
| 459 | ; last (15M - 64K) of linear addresses ( for Move Block/Loadall ) | ||
| 460 | ; Linear Addr Physical Addr | ||
| 461 | ; 00110000h - 01000000h 00110000h - 01000000h | ||
| 462 | ; | ||
| 463 | mov dx,0011h | ||
| 464 | xor ax,ax ; start with 00110000h physical | ||
| 465 | mov bh,0 | ||
| 466 | mov bl,P_AVAIL ; make pages available to all | ||
| 467 | mov cx,(4*400h)-100h-10h ; (15M-64K) worth of Page Table Entries | ||
| 468 | set3_tentry: | ||
| 469 | call SetPageEntry | ||
| 470 | ; ES:[DI] pts to next page table entry | ||
| 471 | add ax,1000h ; next physical page | ||
| 472 | adc dx,0h ; address in DX,AX | ||
| 473 | loop set3_tentry ;Q: done with last entries | ||
| 474 | ; N: loop again | ||
| 475 | ; Y: all done | ||
| 476 | |||
| 477 | ; | ||
| 478 | ; fill out entries in last table as not present | ||
| 479 | ; | ||
| 480 | xor ax,ax | ||
| 481 | xor dx,dx ; addr = 0 | ||
| 482 | mov bh,0 | ||
| 483 | mov bl,0 ; page not present | ||
| 484 | ; | ||
| 485 | ; we can actually forget about this last page table because we | ||
| 486 | ; are not going to use them | ||
| 487 | ; | ||
| 488 | mov cx,400h ; last table | ||
| 489 | setL_tentry: | ||
| 490 | call SetPageEntry ; set this entry | ||
| 491 | loop setL_tentry | ||
| 492 | ; | ||
| 493 | ; our honorable OEM Compaq has to be supported, so we have this hook into | ||
| 494 | ; OEMPROC to modify the last page table to point at the diagnostics segment | ||
| 495 | ; | ||
| 496 | call OEM_Init_Diag_Page | ||
| 497 | ; | ||
| 498 | ; all done with page dir and table setup | ||
| 499 | ; set up page directory and page table selectors | ||
| 500 | ; | ||
| 501 | mov ax,seg GDT | ||
| 502 | mov es,ax ; ES pts to GDT | ||
| 503 | |||
| 504 | mov ax,[PageT_Seg] ; seg for page tables | ||
| 505 | call SegTo24 | ||
| 506 | mov cx,0 ; enough room for tables | ||
| 507 | mov ah,D_DATA0 | ||
| 508 | mov bx,PAGET_GSEL | ||
| 509 | call SetSegDesc ; set up page tables entry | ||
| 510 | |||
| 511 | ; | ||
| 512 | ; EXIT | ||
| 513 | ; | ||
| 514 | pop es | ||
| 515 | pop di | ||
| 516 | pop dx | ||
| 517 | pop cx | ||
| 518 | pop bx | ||
| 519 | pop ax | ||
| 520 | ret | ||
| 521 | InitPages endp | ||
| 522 | |||
| 523 | LAST ends | ||
| 524 | |||
| 525 | END | ||
| 526 | |||
| 527 | |||
diff --git a/v4.0/src/MEMM/MEMM/VDMSEG.INC b/v4.0/src/MEMM/MEMM/VDMSEG.INC new file mode 100644 index 0000000..5a73bb3 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VDMSEG.INC | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: VDMSEG.INC - Segment Ordering and attributes for VDM | ||
| 10 | ; | ||
| 11 | ; Version: 0.04 | ||
| 12 | ; | ||
| 13 | ; Date: May 12, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/03/86 C changed order and added STACK and STACK0,STACK0_SIZE | ||
| 26 | ; 06/06/86 C changed CODE to _TEXT and DATA to _DATA | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; 07/05/86 0.04 Re-organized to allow code seg move | ||
| 29 | ; 06/03/88 add use16 to all segments | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ifndef INC_LIST | ||
| 33 | .xlist | ||
| 34 | endif | ||
| 35 | |||
| 36 | ifndef NOHIMEM | ||
| 37 | ; | ||
| 38 | ; SEGMENT definitions and order | ||
| 39 | ; | ||
| 40 | |||
| 41 | ;* CODE area containing EMM/VDISK headers and writeable Real mode code | ||
| 42 | R_CODE SEGMENT PARA USE16 PUBLIC 'R_CODE' | ||
| 43 | R_CODE ENDS | ||
| 44 | |||
| 45 | ;* Contains initialized variables and variables used at startup. | ||
| 46 | _DATA SEGMENT WORD USE16 PUBLIC 'DATA' | ||
| 47 | _DATA ENDS | ||
| 48 | |||
| 49 | ;* read only constants for C | ||
| 50 | CONST SEGMENT WORD USE16 PUBLIC 'CONST' | ||
| 51 | CONST ENDS | ||
| 52 | |||
| 53 | ;* uninitialized static data for C | ||
| 54 | _BSS SEGMENT WORD USE16 PUBLIC 'BSS' | ||
| 55 | _BSS ENDS | ||
| 56 | |||
| 57 | ;* Ring 0 stack in VDM | ||
| 58 | STACK SEGMENT PARA USE16 STACK 'STACK' | ||
| 59 | STACK ENDS | ||
| 60 | |||
| 61 | ; | ||
| 62 | ; data group | ||
| 63 | ; | ||
| 64 | DGROUP GROUP _DATA,CONST,_BSS | ||
| 65 | |||
| 66 | ;* The code comprising the system. Must be READ-ONLY in real mode. | ||
| 67 | _TEXT SEGMENT BYTE USE16 PUBLIC 'CODE' | ||
| 68 | _TEXT ENDS | ||
| 69 | |||
| 70 | ;* Global Descriptor Table | ||
| 71 | GDT SEGMENT PARA USE16 COMMON | ||
| 72 | GDT ENDS | ||
| 73 | |||
| 74 | ;* Local Descriptor Table | ||
| 75 | LDT SEGMENT PARA USE16 COMMON | ||
| 76 | LDT ENDS | ||
| 77 | |||
| 78 | ;* Interrupt Descriptor Table | ||
| 79 | IDT SEGMENT PARA USE16 COMMON | ||
| 80 | IDT ENDS | ||
| 81 | |||
| 82 | ;* Task State Segment | ||
| 83 | TSS SEGMENT PARA USE16 COMMON | ||
| 84 | TSS ENDS | ||
| 85 | |||
| 86 | ;* Contains initialized variables and variables used at startup. | ||
| 87 | PAGESEG SEGMENT PARA USE16 PUBLIC 'PAGES' | ||
| 88 | PAGESEG ENDS | ||
| 89 | |||
| 90 | ;* Initialization code and variables. Used for data later. | ||
| 91 | ; Must be last segment. | ||
| 92 | LAST SEGMENT PARA USE16 PUBLIC 'LAST' | ||
| 93 | LAST ENDS | ||
| 94 | |||
| 95 | |||
| 96 | |||
| 97 | else | ||
| 98 | ; | ||
| 99 | ; SEGMENT definitions and order | ||
| 100 | ; | ||
| 101 | |||
| 102 | ;* CODE area containing EMM/VDISK headers and writeable Real mode code | ||
| 103 | R_CODE SEGMENT PARA USE16 PUBLIC 'R_CODE' | ||
| 104 | R_CODE ENDS | ||
| 105 | |||
| 106 | ;* Global Descriptor Table | ||
| 107 | GDT SEGMENT PARA USE16 COMMON | ||
| 108 | GDT ENDS | ||
| 109 | |||
| 110 | ;* Local Descriptor Table | ||
| 111 | LDT SEGMENT PARA USE16 COMMON | ||
| 112 | LDT ENDS | ||
| 113 | |||
| 114 | ;* Interrupt Descriptor Table | ||
| 115 | IDT SEGMENT PARA USE16 COMMON | ||
| 116 | IDT ENDS | ||
| 117 | |||
| 118 | ;* Task State Segment | ||
| 119 | TSS SEGMENT PARA USE16 COMMON | ||
| 120 | TSS ENDS | ||
| 121 | |||
| 122 | ;* Contains initialized variables and variables used at startup. | ||
| 123 | _DATA SEGMENT WORD USE16 PUBLIC 'DATA' | ||
| 124 | _DATA ENDS | ||
| 125 | |||
| 126 | ;* read only constants for C | ||
| 127 | CONST SEGMENT WORD USE16 PUBLIC 'CONST' | ||
| 128 | CONST ENDS | ||
| 129 | |||
| 130 | ;* uninitialized static data for C | ||
| 131 | _BSS SEGMENT WORD USE16 PUBLIC 'BSS' | ||
| 132 | _BSS ENDS | ||
| 133 | |||
| 134 | ;* Ring 0 stack in VDM | ||
| 135 | STACK SEGMENT PARA USE16 STACK 'STACK' | ||
| 136 | STACK ENDS | ||
| 137 | |||
| 138 | ; | ||
| 139 | ; data group | ||
| 140 | ; | ||
| 141 | DGROUP GROUP _DATA,CONST,_BSS | ||
| 142 | |||
| 143 | ;* The code comprising the system. Must be READ-ONLY in real mode. | ||
| 144 | _TEXT SEGMENT BYTE USE16 PUBLIC 'CODE' | ||
| 145 | _TEXT ENDS | ||
| 146 | |||
| 147 | ;* Contains dynamically sized emm data structures. | ||
| 148 | VDATA SEGMENT WORD USE16 PUBLIC 'VDATA' | ||
| 149 | VDATA ENDS | ||
| 150 | |||
| 151 | ;* Contains initialized variables and variables used at startup. | ||
| 152 | PAGESEG SEGMENT PARA USE16 PUBLIC 'PAGES' | ||
| 153 | PAGESEG ENDS | ||
| 154 | |||
| 155 | ;* Initialization code and variables. Used for data later. | ||
| 156 | ; Must be last segment. | ||
| 157 | LAST SEGMENT PARA USE16 PUBLIC 'LAST' | ||
| 158 | LAST ENDS | ||
| 159 | endif | ||
| 160 | ; | ||
| 161 | ; segment related equates | ||
| 162 | ; | ||
| 163 | |||
| 164 | ; ring 0 stack size | ||
| 165 | STACK0_SIZE equ 512 | ||
| 166 | |||
| 167 | .list ; end of VDMSEG.INC | ||
| 168 | |||
diff --git a/v4.0/src/MEMM/MEMM/VDMSEL.INC b/v4.0/src/MEMM/MEMM/VDMSEL.INC new file mode 100644 index 0000000..f408c40 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VDMSEL.INC | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: VDMSEL.INC - Selector Definitions for MEMM | ||
| 10 | ; | ||
| 11 | ; Version: 0.05 | ||
| 12 | ; | ||
| 13 | ; Date: May 12, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/07/86 C merged with module from Rick | ||
| 26 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 27 | ; 07/10/86 0.05 Changed CODE_GSEL to RCODEA_GSEL | ||
| 28 | ; 07/20/88 Remove debugger selectors | ||
| 29 | ; | ||
| 30 | ;****************************************************************************** | ||
| 31 | ifndef INC_LIST | ||
| 32 | .xlist | ||
| 33 | endif | ||
| 34 | |||
| 35 | |||
| 36 | ; | ||
| 37 | ; DESCRIPTION | ||
| 38 | ; | ||
| 39 | ; These are the fixed selector numbers for the GDT and LDT | ||
| 40 | ; | ||
| 41 | ; All are declared with RPL = 0 so they can easily be used | ||
| 42 | ; as table indices. | ||
| 43 | ; | ||
| 44 | ; Do not change anything without consulting files which include | ||
| 45 | ; this one. Add new selectors to the end and update the | ||
| 46 | ; gdt declaration and initialisation code elsewhere. | ||
| 47 | ; | ||
| 48 | |||
| 49 | ; Define LDT and GDT table bits | ||
| 50 | |||
| 51 | TAB_LDT equ 4h | ||
| 52 | TAB_GDT equ 0h | ||
| 53 | |||
| 54 | |||
| 55 | ; Define GDT selectors | ||
| 56 | |||
| 57 | GDTD_GSEL equ 008h OR TAB_GDT ; gdt data alias | ||
| 58 | IDTD_GSEL equ 010h OR TAB_GDT ; idt data alias | ||
| 59 | LDT_GSEL equ 018h OR TAB_GDT ; ldt | ||
| 60 | LDTD_GSEL equ 020h OR TAB_GDT ; ldt data alias | ||
| 61 | TSS_GSEL equ 028h OR TAB_GDT ; tss | ||
| 62 | TSSD_GSEL equ 030h OR TAB_GDT ; tss data alias | ||
| 63 | RM_IDT_GSEL equ 038h OR TAB_GDT ; real mode idt (locn 0) | ||
| 64 | ROMDATA_GSEL equ 040h OR TAB_GDT ; maps 40:0 - DON'T CHANGE!! | ||
| 65 | VDMC_GSEL equ 048h OR TAB_GDT ; VDM Code selector | ||
| 66 | VDMD_GSEL equ 050h OR TAB_GDT ; VDM Data Selector | ||
| 67 | VDMS_GSEL equ 058h OR TAB_GDT ; VDM stack selector | ||
| 68 | MONO_GSEL equ 060h OR TAB_GDT ; monochrome display memory | ||
| 69 | COLOUR_GSEL equ 068h OR TAB_GDT ; colour display memory | ||
| 70 | EGA1_GSEL equ 070h OR TAB_GDT ; first EGA sel | ||
| 71 | EGA2_GSEL equ 078h OR TAB_GDT ; second EGA sel | ||
| 72 | LOADALL_GSEL equ 080h OR TAB_GDT ; loadall buffer - DON'T CHANGE | ||
| 73 | ;DEBC_GSEL equ 088h or TAB_GDT ; debugger work descr | ||
| 74 | ;DEBD_GSEL equ 090h or TAB_GDT ; debugger work descr | ||
| 75 | ;DEBW1_GSEL equ 098h or TAB_GDT ; debugger work descr | ||
| 76 | ;DEBW2_GSEL equ 0A0h or TAB_GDT ; debugger work descr | ||
| 77 | DEB1_GSEL equ 088h or TAB_GDT ; deb386 word descr | ||
| 78 | DEB2_GSEL equ 090h or TAB_GDT ; deb386 word descr | ||
| 79 | DEB3_GSEL equ 098h or TAB_GDT ; deb386 word descr | ||
| 80 | DEB4_GSEL equ 0A0h or TAB_GDT ; deb386 word descr | ||
| 81 | DEB5_GSEL equ 0A8h or TAB_GDT ; deb386 word descr | ||
| 82 | DEBX_GSEL equ 0B0h or TAB_GDT ; deb386 descr for all of addressing space | ||
| 83 | K_PUTC286 equ 0B8h OR TAB_GDT ; 286 call gate to kputc | ||
| 84 | K_GETC286 equ 0C0h OR TAB_GDT ; 286 call gate to kgetc | ||
| 85 | RCODEA_GSEL equ 0C8h OR TAB_GDT ; data alias for R_CODE segment | ||
| 86 | VM1_GSEL equ 0D0h OR TAB_GDT ; scratch for vm handler | ||
| 87 | VM2_GSEL equ 0D8h OR TAB_GDT ; scratch for vm handler | ||
| 88 | MBSRC_GSEL equ 0E0h OR TAB_GDT ; source sel for move blk | ||
| 89 | MBTAR_GSEL equ 0E8h OR TAB_GDT ; target sel for move blk | ||
| 90 | PAGET_GSEL equ 0F0h OR TAB_GDT ; page table area sel | ||
| 91 | VDMCA_GSEL equ 0F8h OR TAB_GDT ; VDM code segment alias | ||
| 92 | EMM1_GSEL equ 100h OR TAB_GDT ; EMM scratch selector | ||
| 93 | EMM2_GSEL equ 108h OR TAB_GDT ; EMM scratch selector | ||
| 94 | OEM0_GSEL equ 110h OR TAB_GDT ; OEM specific selector | ||
| 95 | OEM1_GSEL equ 118h OR TAB_GDT ; OEM specific selector | ||
| 96 | OEM2_GSEL equ 120h OR TAB_GDT ; OEM specific selector | ||
| 97 | OEM3_GSEL equ 128h OR TAB_GDT ; OEM specific selector | ||
| 98 | USER1_GSEL equ 130h OR TAB_GDT ; USER data structure | ||
| 99 | |||
| 100 | .list ; end of VDMSEL.INC | ||
| 101 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/VM386.INC b/v4.0/src/MEMM/MEMM/VM386.INC new file mode 100644 index 0000000..19ce94e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VM386.INC | |||
| @@ -0,0 +1,206 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: VM386.INC | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: May 12, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/08/86 B Added Disable A20 equates | ||
| 26 | ; 06/14/86 C Added MOV_CDTR_FRAME, PROT_INS_FRAME, and changed | ||
| 27 | ; VTFO from 2 to 4 to reflect push of EBP from BP | ||
| 28 | ; 06/15/86 D Added GPFAULT_FRAME | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 07/01/86 0.03 Added structures for accessing memory | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ifndef INC_LIST | ||
| 34 | .xlist | ||
| 35 | endif | ||
| 36 | |||
| 37 | ; | ||
| 38 | ; Structures for accessing memory | ||
| 39 | ; | ||
| 40 | WordS struc | ||
| 41 | LowByte db ? | ||
| 42 | HighByte db ? | ||
| 43 | WordS ends | ||
| 44 | |||
| 45 | DwordS struc | ||
| 46 | LowWord dw ? | ||
| 47 | HighWord dw ? | ||
| 48 | DwordS ends | ||
| 49 | |||
| 50 | ; | ||
| 51 | ; Structure for accessing stack frame pushed during trap exit from VM | ||
| 52 | ; | ||
| 53 | |||
| 54 | VM_TRAP_FRAME struc | ||
| 55 | VMTF_EIP dw ? ; EIP (low) | ||
| 56 | dw ? ; EIP (high) | ||
| 57 | VMTF_CS dw ? ; CS | ||
| 58 | dw ? ; (padding) | ||
| 59 | VMTF_EFLAGS dw ? ; EFLAGS (low) | ||
| 60 | VMTF_EFLAGShi dw ? ; EFLAGS (high) | ||
| 61 | VMTF_ESP dw ? ; ESP (low) | ||
| 62 | dw ? ; ESP (high) | ||
| 63 | VMTF_SS dw ? ; SS | ||
| 64 | dw ? ; (padding) | ||
| 65 | VMTF_ES dw ? ; ES | ||
| 66 | dw ? ; (padding) | ||
| 67 | VMTF_DS dw ? ; DS | ||
| 68 | dw ? ; (padding) | ||
| 69 | VMTF_FS dw ? ; FS | ||
| 70 | dw ? ; (padding) | ||
| 71 | VMTF_GS dw ? ; GS | ||
| 72 | dw ? ; (padding) | ||
| 73 | VM_TRAP_FRAME ends | ||
| 74 | ; | ||
| 75 | ; Used in EmMovCDTR (vminst.asm) | ||
| 76 | MOV_CDTR_FRAME struc | ||
| 77 | MCF_WBP dw ? ; Work BP | ||
| 78 | MCF_WES dw ? ; Work ES | ||
| 79 | MCF_EAX dw ? ; EAXlo | ||
| 80 | dw ? ; EAXhi | ||
| 81 | MCF_ESI dw ? ; ESIlo | ||
| 82 | dw ? ; ESIhi | ||
| 83 | MCF_EBX dw ? ; EBXlo | ||
| 84 | dw ? ; EBXhi | ||
| 85 | MCF_EBP dw ? ; EBPlo | ||
| 86 | dw ? ; EBPhi | ||
| 87 | MCF_VMERR dw ? ; VM Error Code (low) | ||
| 88 | dw ? ; VM Error Code (high) | ||
| 89 | MCF_VMEIP dw ? ; VM EIP (low) | ||
| 90 | dw ? ; VM EIP (high) | ||
| 91 | MCF_VMCS dw ? ; VM CS | ||
| 92 | dw ? ; (padding) | ||
| 93 | MCF_VMEFLAGS dw ? ; VM EFLAGS (low) | ||
| 94 | MCF_VMEFLAGShi dw ? ; VM EFLAGS (high) | ||
| 95 | MCF_VMESP dw ? ; VM ESP (low) | ||
| 96 | dw ? ; VM ESP (high) | ||
| 97 | MCF_VMSS dw ? ; VM SS | ||
| 98 | dw ? ; (padding) | ||
| 99 | MCF_VMES dw ? ; VM ES | ||
| 100 | dw ? ; (padding) | ||
| 101 | MCF_VMDS dw ? ; VM DS | ||
| 102 | dw ? ; (padding) | ||
| 103 | MCF_VMFS dw ? ; VM FS | ||
| 104 | dw ? ; (padding) | ||
| 105 | MCF_VMGS dw ? ; VM GS | ||
| 106 | dw ? ; (padding) | ||
| 107 | MOV_CDTR_FRAME ends | ||
| 108 | ; | ||
| 109 | ; Used in EmProtIns (vminst.asm) | ||
| 110 | PROT_INS_FRAME struc | ||
| 111 | PIF_WBP dw ? ; Work BP | ||
| 112 | PIF_WES dw ? ; Work ES | ||
| 113 | PIF_AX dw ? ; EAXlo | ||
| 114 | PIF_DX dw ? ; EDXlo | ||
| 115 | PIF_ESI dw ? ; ESIlo | ||
| 116 | dw ? ; ESIhi | ||
| 117 | PIF_EBX dw ? ; EBXlo | ||
| 118 | dw ? ; EBXhi | ||
| 119 | PIF_EBP dw ? ; EBPlo | ||
| 120 | dw ? ; EBPhi | ||
| 121 | PIF_VMERR dw ? ; VM Error Code (low) | ||
| 122 | dw ? ; VM Error Code (high) | ||
| 123 | PIF_VMEIP dw ? ; VM EIP (low) | ||
| 124 | dw ? ; VM EIP (high) | ||
| 125 | PIF_VMCS dw ? ; VM CS | ||
| 126 | dw ? ; (padding) | ||
| 127 | PIF_VMEFLAGS dw ? ; VM EFLAGS (low) | ||
| 128 | PIF_VMEFLAGShi dw ? ; VM EFLAGS (high) | ||
| 129 | PIF_VMESP dw ? ; VM ESP (low) | ||
| 130 | dw ? ; VM ESP (high) | ||
| 131 | PIF_VMSS dw ? ; VM SS | ||
| 132 | dw ? ; (padding) | ||
| 133 | PIF_VMES dw ? ; VM ES | ||
| 134 | dw ? ; (padding) | ||
| 135 | PIF_VMDS dw ? ; VM DS | ||
| 136 | dw ? ; (padding) | ||
| 137 | PIF_VMFS dw ? ; VM FS | ||
| 138 | dw ? ; (padding) | ||
| 139 | PIF_VMGS dw ? ; VM GS | ||
| 140 | dw ? ; (padding) | ||
| 141 | PROT_INS_FRAME ends | ||
| 142 | ; | ||
| 143 | GPFAULT_FRAME struc | ||
| 144 | GPF_ESI dw ? ; ESIlo | ||
| 145 | dw ? ; ESIhi | ||
| 146 | GPF_EBX dw ? ; EBXlo | ||
| 147 | dw ? ; EBXhi | ||
| 148 | GPF_EBP dw ? ; EBPlo | ||
| 149 | dw ? ; EBPhi | ||
| 150 | GPFAULT_FRAME ends | ||
| 151 | ; | ||
| 152 | ; The following constants define the offset of the Virtual Mode trap stack | ||
| 153 | ; frame (from current SP assuming BP has been pushed) for the two cases: | ||
| 154 | ; 1) exceptions that don't push error codes and 2) those that do. | ||
| 155 | ; | ||
| 156 | VTFO equ 4 ; offset of VM trap stack frame | ||
| 157 | VTFOE equ VTFO + 4 ; as above, but including error code | ||
| 158 | ; | ||
| 159 | ; These constants are used to sanity-check the value of SP when one of | ||
| 160 | ; the exception handlers has been entered: | ||
| 161 | ; | ||
| 162 | STACK segment | ||
| 163 | extrn kstack_top:byte | ||
| 164 | STACK ends | ||
| 165 | |||
| 166 | ; Trap/no error | ||
| 167 | VMT_STACK equ offset STACK:kstack_top - size VM_TRAP_FRAME - VTFO | ||
| 168 | ; Trap w/error | ||
| 169 | VMTERR_STACK equ offset STACK:kstack_top - size VM_TRAP_FRAME - VTFOE | ||
| 170 | |||
| 171 | ;****************************************************************************** | ||
| 172 | ; E R R O R C O D E S | ||
| 173 | ;****************************************************************************** | ||
| 174 | ; | ||
| 175 | PrivErr equ 0000h ; Privileged Operation Error class | ||
| 176 | ErrLGDT equ 0000h ; Client tried to execute a LGDT | ||
| 177 | ErrLIDT equ 0001h ; Client tried to execute a LIDT | ||
| 178 | ErrLMSW equ 0002h ; Client tried to execute a LMSW | ||
| 179 | Err2LL equ 0003h ; Client tried to execute a 286 Loadall | ||
| 180 | Err3LL equ 0004h ; Client tried to execute a 386 Loadall | ||
| 181 | ErrMovCR equ 0005h ; Client tried to execute a CRn mov | ||
| 182 | ErrMovDR equ 0006h ; Client tried to execute a DRn mov | ||
| 183 | ErrMovTR equ 0007h ; Client tried to execute a TRn mov | ||
| 184 | |||
| 185 | ExcpErr equ 0001h ; Exception Error class | ||
| 186 | ErrDIV equ 0000h ; Divide Error | ||
| 187 | ErrINT1 equ 0001h ; Debug Exception | ||
| 188 | ErrNMI equ 0002h ; NMI | ||
| 189 | ErrINT3 equ 0003h ; Int 3 | ||
| 190 | ErrINTO equ 0004h ; Int O error | ||
| 191 | ErrBounds equ 0005h ; Array Bounds Check | ||
| 192 | ErrOpCode equ 0006h ; Invalid Opcode | ||
| 193 | ErrCoPNA equ 0007h ; Coprocessor Device not available | ||
| 194 | ErrDouble equ 0008h ; Double Fault | ||
| 195 | ErrCoPseg equ 0009h ; Coprocessor Segment Overrun | ||
| 196 | ErrTSS equ 000Ah ; Invalid TSS | ||
| 197 | ErrSegNP equ 000Bh ; Segment not Present | ||
| 198 | ErrStack equ 000Ch ; Stack Fault | ||
| 199 | ErrGP equ 000Dh ; General Protection Fault | ||
| 200 | ErrPage equ 000Eh ; Page Fault | ||
| 201 | ErrCoPerr equ 0010h ; Coprocessor Error | ||
| 202 | ErrWrite equ 0020h ; Attempt to write to protected area | ||
| 203 | ErrDMA equ 0021h ; Attempt to DMA into page frame (not for user) | ||
| 204 | ErrINTProt equ 0022h ; General Protected interrupt error | ||
| 205 | |||
| 206 | .list ; end of VM386.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/VMINIT.ASM b/v4.0/src/MEMM/MEMM/VMINIT.ASM new file mode 100644 index 0000000..5b69b1a --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VMINIT.ASM | |||
| @@ -0,0 +1,292 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title VMINIT.ASM - Initialization routines for VM-DOS | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: VMINIT - Initialization routines for MEMM/ VDM | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 30, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/30/86 Original | ||
| 27 | ; 04/07/86 A Added InitBitMap | ||
| 28 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 29 | ; 06/18/86 0.01 Re-arranged comments, etc. | ||
| 30 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 31 | ; 07/03/86 0.03 Added call to Kybd_Watch | ||
| 32 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 33 | ; 07/30/86 0.06 removed PortClear reference | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ; | ||
| 37 | ; Functional Description: | ||
| 38 | ; | ||
| 39 | ; This module contains various initialization routines for Virtual DOS | ||
| 40 | ; | ||
| 41 | ;****************************************************************************** | ||
| 42 | .386p | ||
| 43 | .lfcond ; list false conditionals | ||
| 44 | page | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; P U B L I C D E C L A R A T I O N S | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | public vminit ; module label | ||
| 50 | public InitBitMap ; init I/O Bit Map | ||
| 51 | public PortTrap ; set bit(s) in I/O Bit Map | ||
| 52 | ifdef oldstuff | ||
| 53 | public PortClear ; clear bit(s) in I/O Bit Map | ||
| 54 | endif | ||
| 55 | public BitOFF ; bit offset calculation | ||
| 56 | page | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; L O C A L C O N S T A N T S | ||
| 59 | ;****************************************************************************** | ||
| 60 | ; | ||
| 61 | include VDMseg.inc | ||
| 62 | include VDMsel.inc | ||
| 63 | include desc.inc | ||
| 64 | include elim.inc | ||
| 65 | FALSE equ 0 | ||
| 66 | TRUE equ not FALSE | ||
| 67 | |||
| 68 | page | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; E X T E R N A L R E F E R E N C E S | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; | ||
| 73 | ABS0 segment at 0000h | ||
| 74 | ABS0 ends | ||
| 75 | |||
| 76 | TSS segment | ||
| 77 | |||
| 78 | extrn IOBitMap:byte ; Bit Map in Tss | ||
| 79 | |||
| 80 | TSS ends | ||
| 81 | |||
| 82 | |||
| 83 | _TEXT segment | ||
| 84 | |||
| 85 | extrn A20_Trap_Init:near ; (a20trap.asm) | ||
| 86 | extrn RR_Trap_Init:near ; (RRtrap.asm) | ||
| 87 | extrn OEM_Trap_Init:near ; (OEMProc.asm) | ||
| 88 | |||
| 89 | _TEXT ends | ||
| 90 | ; | ||
| 91 | ; | ||
| 92 | ;****************************************************************************** | ||
| 93 | ; L O C A L D A T A A R E A | ||
| 94 | ;****************************************************************************** | ||
| 95 | ; | ||
| 96 | _DATA segment | ||
| 97 | ; | ||
| 98 | _DATA ends | ||
| 99 | |||
| 100 | ; | ||
| 101 | ;****************************************************************************** | ||
| 102 | ; S E G M E N T D E F I N I T I O N | ||
| 103 | ;****************************************************************************** | ||
| 104 | ; | ||
| 105 | ;------------------------------------------------------------------------------ | ||
| 106 | _TEXT segment | ||
| 107 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 108 | vminit label byte | ||
| 109 | page | ||
| 110 | ;****************************************************************************** | ||
| 111 | ; InitBitMap - Initialize 386 Tss I/O bit map for Virtual mode I/O trapping. | ||
| 112 | ; | ||
| 113 | ; ENTRY: Real Mode | ||
| 114 | ; DS = DGROUP | ||
| 115 | ; I/O bit map all zeroes (no trapping) except last byte. | ||
| 116 | ; EXIT: Real Mode | ||
| 117 | ; I/O bit map in Tss initialized. | ||
| 118 | ; USED: Flags | ||
| 119 | ; STACK: | ||
| 120 | ;------------------------------------------------------------------------------ | ||
| 121 | InitBitMap proc far | ||
| 122 | ; | ||
| 123 | push ax | ||
| 124 | push bx | ||
| 125 | push si | ||
| 126 | push es | ||
| 127 | ; | ||
| 128 | mov ax,seg TSS | ||
| 129 | mov es,ax ; set ES to I/O Bit Map seg | ||
| 130 | ASSUME ES:TSS | ||
| 131 | xor bx,bx ; ES:[BX] = pts to TSS | ||
| 132 | ; | ||
| 133 | ; initialize BitMapBase in Tss | ||
| 134 | ; | ||
| 135 | mov ax,offset TSS:IOBitMap | ||
| 136 | mov ES:[bx.BitMapBase],ax ; set Bit Map base in Tss | ||
| 137 | ; | ||
| 138 | ; set ports for return to real trap | ||
| 139 | ; | ||
| 140 | call RR_Trap_Init | ||
| 141 | ; | ||
| 142 | ; Turn on Keyboard watching for A20 disable | ||
| 143 | ; | ||
| 144 | call A20_Trap_Init | ||
| 145 | ; | ||
| 146 | ; Turn on any other OEM specific trapping | ||
| 147 | ; | ||
| 148 | call OEM_Trap_Init | ||
| 149 | |||
| 150 | IB_exit: | ||
| 151 | pop es | ||
| 152 | ASSUME ES:DGROUP | ||
| 153 | pop si | ||
| 154 | pop bx | ||
| 155 | pop ax | ||
| 156 | ret ; *** RETURN *** | ||
| 157 | InitBitMap endp | ||
| 158 | |||
| 159 | ;****************************************************************************** | ||
| 160 | ; PortTrap - sets bit(s) in I/O bit map to enable trapping at an I/O address | ||
| 161 | ; | ||
| 162 | ; This function sets the appropriate bits in the I/O bit map to enable | ||
| 163 | ; trapping of the desired I/O address. Since some I/O ports on the AT system | ||
| 164 | ; board are selected via only 10 bits of address lines, these ports appear | ||
| 165 | ; at every 1K in the I/O address space. When trapping these "system board" | ||
| 166 | ; ports, the trap bits in the I/O bit map must be set for every 1k instance | ||
| 167 | ; of the port. | ||
| 168 | ; | ||
| 169 | ; ENTRY: AX = byte I/O address to set in Bit Map | ||
| 170 | ; BH = high bit set => set traps bits for this address @ every 1K | ||
| 171 | ; ES = TSS | ||
| 172 | ; | ||
| 173 | ; EXIT: none. | ||
| 174 | ; | ||
| 175 | ; USED: Flags | ||
| 176 | ; STACK: | ||
| 177 | ;------------------------------------------------------------------------------ | ||
| 178 | PortTrap proc near | ||
| 179 | ; | ||
| 180 | ASSUME ES:TSS | ||
| 181 | push ax | ||
| 182 | push bx | ||
| 183 | push cx | ||
| 184 | ; | ||
| 185 | mov cx,1 ; once by default | ||
| 186 | test bh,80h ;Q: map it every 1K ? | ||
| 187 | jz PT_loop ; N: do it once | ||
| 188 | mov cx,64 ; Y: do it 64 times (once per 1k) | ||
| 189 | PT_loop: | ||
| 190 | push ax ; map it. save this address | ||
| 191 | call BitOFF ; get offset and bit | ||
| 192 | or ES:IOBitMap[bx],al ; trap this address | ||
| 193 | pop ax ; restore this address | ||
| 194 | add ax,400h ; add 1k for next address | ||
| 195 | loop PT_loop ; and continue ... | ||
| 196 | ; | ||
| 197 | pop cx | ||
| 198 | pop bx | ||
| 199 | pop ax | ||
| 200 | ret | ||
| 201 | ASSUME ES:DGROUP | ||
| 202 | ; | ||
| 203 | PortTrap endp | ||
| 204 | |||
| 205 | |||
| 206 | ifdef oldstuff | ||
| 207 | ;****************************************************************************** | ||
| 208 | ; PortClear - clears bit(s) in I/O bit map to disable trapping at an I/O | ||
| 209 | ; address | ||
| 210 | ; | ||
| 211 | ; This function clears the appropriate bits in the I/O bit map to disable | ||
| 212 | ; trapping of the desired I/O address. Since some I/O ports on the AT system | ||
| 213 | ; board are selected via only 10 bits of address lines, these ports appear | ||
| 214 | ; at every 1K in the I/O address space. When clearing these "system board" | ||
| 215 | ; ports, the trap bits in the I/O bit map must be cleared at every 1k instance | ||
| 216 | ; of the port. | ||
| 217 | ; | ||
| 218 | ; ENTRY: AX = byte I/O address to clear in Bit Map | ||
| 219 | ; BH = high bit set => clear traps bits for this address @ every 1K | ||
| 220 | ; ES = data segment for I/O bit map | ||
| 221 | ; | ||
| 222 | ; EXIT: none. | ||
| 223 | ; | ||
| 224 | ; USED: Flags | ||
| 225 | ; STACK: | ||
| 226 | ; NOTE: This implementation does not account for a port being multiply set | ||
| 227 | ; for many purposes. (ie. If a port is set 3 times, it still only takes one | ||
| 228 | ; PortClear call to clear it.) If this is a problem, a counter for each | ||
| 229 | ; enabled port will have to be added. | ||
| 230 | ; | ||
| 231 | ;------------------------------------------------------------------------------ | ||
| 232 | PortClear proc near | ||
| 233 | ; | ||
| 234 | ASSUME ES:TSS | ||
| 235 | push ax | ||
| 236 | push bx | ||
| 237 | push cx | ||
| 238 | ; | ||
| 239 | mov cx,1 ; once by default | ||
| 240 | test bh,80h ;Q: map it every 1K ? | ||
| 241 | jz PC_loop ; N: do it once | ||
| 242 | mov cx,64 ; Y: do it 64 times (once per 1k) | ||
| 243 | PC_loop: | ||
| 244 | push ax ; map it. save this address | ||
| 245 | call BitOFF ; get offset and bit | ||
| 246 | not al | ||
| 247 | and ES:IOBitMap[bx],al ; clear this address | ||
| 248 | pop ax ; restore this address | ||
| 249 | add ax,400h ; add 1k for next address | ||
| 250 | loop PC_loop ; and continue ... | ||
| 251 | ; | ||
| 252 | pop cx | ||
| 253 | pop bx | ||
| 254 | pop ax | ||
| 255 | ret | ||
| 256 | ASSUME ES:DGROUP | ||
| 257 | ; | ||
| 258 | PortClear endp | ||
| 259 | endif ; oldstuff | ||
| 260 | |||
| 261 | |||
| 262 | ;****************************************************************************** | ||
| 263 | ; BitOFF - sets up byte and bit for I/O address in I/O Bit Map | ||
| 264 | ; | ||
| 265 | ; ENTRY: AX = byte I/O address to set in Bit Map | ||
| 266 | ; | ||
| 267 | ; EXIT: BX = byte offset | ||
| 268 | ; AL = bit to OR in to set proper bit | ||
| 269 | ; | ||
| 270 | ; USED: Flags | ||
| 271 | ; STACK: | ||
| 272 | ;------------------------------------------------------------------------------ | ||
| 273 | BitOFF proc near | ||
| 274 | ; | ||
| 275 | push cx | ||
| 276 | |||
| 277 | mov cx,ax | ||
| 278 | and cx,07h ; CL = bit pos for this port | ||
| 279 | shr ax,3 ; AX = byte offset for this bit | ||
| 280 | mov bx,ax ; BX = byte offset for port | ||
| 281 | mov ax,1 | ||
| 282 | shl ax,cl ; AL = bit mask for this port | ||
| 283 | |||
| 284 | pop cx | ||
| 285 | ret | ||
| 286 | ; | ||
| 287 | BitOFF endp | ||
| 288 | |||
| 289 | ; | ||
| 290 | _TEXT ends ; end of segment | ||
| 291 | ; | ||
| 292 | end ; end of module | ||
diff --git a/v4.0/src/MEMM/MEMM/VMINST.ASM b/v4.0/src/MEMM/MEMM/VMINST.ASM new file mode 100644 index 0000000..9b1a5c7 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VMINST.ASM | |||
| @@ -0,0 +1,2135 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title VMINST.ASM - Virtual Mode GP fault instruction emulation | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: VMINST.ASM - Virtual Mode GP fault instruction emulation | ||
| 13 | ; | ||
| 14 | ; Version: 0.07 | ||
| 15 | ; | ||
| 16 | ; Date: February 11, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 02/12/86 Original | ||
| 27 | ; 04/07/86 A- Added call to LIM emulation routines for all I/O. | ||
| 28 | ; Bit Map set up to trap only LIM related ports. SBP. | ||
| 29 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 30 | ; 05/18/86 C Added VM privileged instruction emulation | ||
| 31 | ; 06/08/86 D Added calls to RRTrap. | ||
| 32 | ; 06/14/86 E Changed stack saves from BP, BX, SI to EBP, EBX, ESI | ||
| 33 | ; 06/15/86 F Changed inc [bp.VTFOE+VMTF_EIP] to inc SI in Prefix | ||
| 34 | ; Handlers | ||
| 35 | ; 06/15/86 G Added MOVSB and MOVSW for Rash Rule emulation | ||
| 36 | ; 06/16/86 H Added Error Handler interfaces, BugMode conditional | ||
| 37 | ; assembly constructs, and Error Handler return logic | ||
| 38 | ; 06/19/86 0.01 Changed call JumpReal to jmp JumpReal | ||
| 39 | ; 06/19/86 0.01 Clear TF bit on all INT reflects, but not on emulations. | ||
| 40 | ; 06/19/86 0.01 CLTS now does a clts for the VM client. | ||
| 41 | ; 06/27/86 0.02 INT3 emulation now ALLWAYS reflects | ||
| 42 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 43 | ; 07/01/86 0.03 Call to IO_Trap instead of LIM_Trap | ||
| 44 | ; 07/03/86 0.03 Let IO_Trap handle A20 and Return to real logic | ||
| 45 | ; 07/05/86 0.04 JumpReal in R_CODE | ||
| 46 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 47 | ; 07/10/86 0.05 added MB_Flag check for move block emulator | ||
| 48 | ; 07/30/86 0.06 removed PortClear reference | ||
| 49 | ; 08/05/86 0.07 Changed EmHalt to really HLT if user IF=0 | ||
| 50 | ; 07/20/88 Removed debugger codes (pc) | ||
| 51 | ; | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; | ||
| 54 | ; Functional Description: | ||
| 55 | ; | ||
| 56 | ; This module contains the routines that handle GP faults fielded from | ||
| 57 | ; Virtual Mode. The offending instruction is either emulated or we exit | ||
| 58 | ; to the debugger. | ||
| 59 | ; | ||
| 60 | ; NOTE: The current implementation is sufficient for breadboard - see | ||
| 61 | ; 'to do' notes in various header for holes. Specifically, the only | ||
| 62 | ; override that is handled is REP, and only for INS/OUTS. Segment | ||
| 63 | ; overrides are not yet supported. | ||
| 64 | ; | ||
| 65 | ;****************************************************************************** | ||
| 66 | .lfcond ; list false conditionals | ||
| 67 | .386p | ||
| 68 | page | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; P U B L I C D E C L A R A T I O N S | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; | ||
| 73 | public VmInst ; module label | ||
| 74 | public VmFault | ||
| 75 | public EmProtIns ; just for debug map | ||
| 76 | public EmMovCDTR ; just for debug map | ||
| 77 | public EmMOVSW ; just for debug map | ||
| 78 | ; | ||
| 79 | ;****************************************************************************** | ||
| 80 | ; E X T E R N A L R E F E R E N C E S | ||
| 81 | ;****************************************************************************** | ||
| 82 | ; | ||
| 83 | R_CODE segment | ||
| 84 | extrn JumpReal:far ; cont client in RM (rrtrap.asm) | ||
| 85 | extrn MB_Flag:byte ; non-zero => do move block | ||
| 86 | R_CODE ends | ||
| 87 | |||
| 88 | _TEXT segment | ||
| 89 | extrn IO_Trap:near ; I/O Trap Dispatcher | ||
| 90 | extrn EM286ll:near ; 286 loadall emulator (EM286LL) | ||
| 91 | extrn EM386ll:near ; 386 loadall emulator (EM386LL) | ||
| 92 | extrn Move_Block:near ; Int 15h move block function (MOVEB) | ||
| 93 | extrn hw_int:near ; HW-ROM reflection code (VMTRAP) | ||
| 94 | extrn ErrHndlr:near ; Handle user's error response | ||
| 95 | extrn MapLinear:near ; map linear address | ||
| 96 | extrn UnMapLinear:near ; unmap linear address | ||
| 97 | _TEXT ends | ||
| 98 | |||
| 99 | page | ||
| 100 | ;****************************************************************************** | ||
| 101 | ; I N C L U D E F I L E S | ||
| 102 | ;****************************************************************************** | ||
| 103 | |||
| 104 | include VDMseg.inc | ||
| 105 | include desc.inc | ||
| 106 | include VDMsel.inc | ||
| 107 | include vm386.inc | ||
| 108 | include loadall.inc | ||
| 109 | include instr386.inc | ||
| 110 | include oemdep.inc | ||
| 111 | ;****************************************************************************** | ||
| 112 | ; L O C A L C O N S T A N T S | ||
| 113 | ;****************************************************************************** | ||
| 114 | ; | ||
| 115 | FALSE equ 0 | ||
| 116 | TRUE equ not FALSE | ||
| 117 | |||
| 118 | LOCK_PREFIX equ 0F0h | ||
| 119 | |||
| 120 | IF_FLAG equ 0200h ; IF bit in flags | ||
| 121 | DF_FLAG equ 0400h ; DF bit in flags | ||
| 122 | |||
| 123 | ; | ||
| 124 | ; bit flags for instruction prefixes | ||
| 125 | ; | ||
| 126 | REP_FLAG equ 0001h | ||
| 127 | REPNE_FLAG equ 0002h | ||
| 128 | REPS_FLAG equ (REP_FLAG or REPNE_FLAG) | ||
| 129 | CS_FLAG equ 0004h | ||
| 130 | DS_FLAG equ 0008h | ||
| 131 | ES_FLAG equ 0010h | ||
| 132 | SS_FLAG equ 0020h | ||
| 133 | FS_FLAG equ 0040h | ||
| 134 | GS_FLAG equ 0080h | ||
| 135 | LOCK_FLAG equ 0100h | ||
| 136 | OPER_SZ_FLAG equ 0200h | ||
| 137 | ADDR_SZ_FLAG equ 0400h | ||
| 138 | P0F_FLAG equ 0800h | ||
| 139 | |||
| 140 | page | ||
| 141 | ;****************************************************************************** | ||
| 142 | ; L O C A L D A T A A R E A | ||
| 143 | ;****************************************************************************** | ||
| 144 | _DATA segment | ||
| 145 | |||
| 146 | PrefixFlag dw 0 ; flags for Fault Instr Prefixes | ||
| 147 | RefNum dw 0 ; Reflect number for RefToRom | ||
| 148 | |||
| 149 | _DATA ends | ||
| 150 | |||
| 151 | page | ||
| 152 | ;****************************************************************************** | ||
| 153 | ; C O D E A R E A | ||
| 154 | ;****************************************************************************** | ||
| 155 | _TEXT segment | ||
| 156 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 157 | |||
| 158 | VmInst label byte | ||
| 159 | ; | ||
| 160 | ; Index table for opcode emulation dispatch - This is too general-purpose | ||
| 161 | ; if all we want to handle is INT instructions, but it'll get fleshed out | ||
| 162 | ; later, when we start emulating IOPL-sensitive stuff | ||
| 163 | ; | ||
| 164 | ; the directive below is giving problems because this segment is byte aligned | ||
| 165 | ; will fix it..sunilp | ||
| 166 | ; EVEN ; word aligning should make execution | ||
| 167 | ; faster | ||
| 168 | OpTable label word | ||
| 169 | dw offset _TEXT:BadVmTrap ; 0 - LLDT, LTR, SLDT, STR, VERR, VERW | ||
| 170 | dw offset _TEXT:EmProtIns ; 1 - LGDT, LIDT, LMSW | ||
| 171 | dw offset _TEXT:BadVmTrap ; 2 - LAR | ||
| 172 | dw offset _TEXT:BadVmTrap ; 3 - LSL | ||
| 173 | dw offset _TEXT:BadVmTrap ; 4 | ||
| 174 | dw offset _TEXT:EmLoadal2 ; 5 - 286Loadall | ||
| 175 | dw offset _TEXT:EmCLTS ; 6 - CLTS | ||
| 176 | dw offset _TEXT:EmLoadal3 ; 7 - 386Loadall | ||
| 177 | dw offset _TEXT:BadVmTrap ; 8 | ||
| 178 | dw offset _TEXT:BadVmTrap ; 9 | ||
| 179 | dw offset _TEXT:BadVmTrap ; a | ||
| 180 | dw offset _TEXT:BadVmTrap ; b | ||
| 181 | dw offset _TEXT:BadVmTrap ; c | ||
| 182 | dw offset _TEXT:BadVmTrap ; d | ||
| 183 | dw offset _TEXT:BadVmTrap ; e | ||
| 184 | dw offset _TEXT:Prefix_0F ; f | ||
| 185 | dw offset _TEXT:BadVmTrap ; 10 | ||
| 186 | dw offset _TEXT:BadVmTrap ; 11 | ||
| 187 | dw offset _TEXT:BadVmTrap ; 12 | ||
| 188 | dw offset _TEXT:BadVmTrap ; 13 | ||
| 189 | dw offset _TEXT:BadVmTrap ; 14 | ||
| 190 | dw offset _TEXT:BadVmTrap ; 15 | ||
| 191 | dw offset _TEXT:BadVmTrap ; 16 | ||
| 192 | dw offset _TEXT:BadVmTrap ; 17 | ||
| 193 | dw offset _TEXT:BadVmTrap ; 18 | ||
| 194 | dw offset _TEXT:BadVmTrap ; 19 | ||
| 195 | dw offset _TEXT:BadVmTrap ; 1a | ||
| 196 | dw offset _TEXT:BadVmTrap ; 1b | ||
| 197 | dw offset _TEXT:BadVmTrap ; 1c | ||
| 198 | dw offset _TEXT:BadVmTrap ; 1d | ||
| 199 | dw offset _TEXT:BadVmTrap ; 1e | ||
| 200 | dw offset _TEXT:BadVmTrap ; 1f | ||
| 201 | dw offset _TEXT:EmMovCDTR ; 20 - Mov Rn, CRn | ||
| 202 | dw offset _TEXT:EmMovCDTR ; 21 - Mov Rn, DRn | ||
| 203 | dw offset _TEXT:EmMovCDTR ; 22 - Mov CRn, Rn | ||
| 204 | dw offset _TEXT:EmMovCDTR ; 23 - Mov DRn, Rn | ||
| 205 | dw offset _TEXT:EmMovCDTR ; 24 - Mov Rn, TRn | ||
| 206 | dw offset _TEXT:BadVmTrap ; 25 | ||
| 207 | dw offset _TEXT:ESOverride ; 26 - ES Override & Mov TRn, Rn | ||
| 208 | dw offset _TEXT:BadVmTrap ; 27 | ||
| 209 | dw offset _TEXT:BadVmTrap ; 28 | ||
| 210 | dw offset _TEXT:BadVmTrap ; 29 | ||
| 211 | dw offset _TEXT:BadVmTrap ; 2a | ||
| 212 | dw offset _TEXT:BadVmTrap ; 2b | ||
| 213 | dw offset _TEXT:BadVmTrap ; 2c | ||
| 214 | dw offset _TEXT:BadVmTrap ; 2d | ||
| 215 | dw offset _TEXT:CSOverride ; 2e - CS Override | ||
| 216 | dw offset _TEXT:BadVmTrap ; 2f | ||
| 217 | dw offset _TEXT:BadVmTrap ; 30 | ||
| 218 | dw offset _TEXT:BadVmTrap ; 31 | ||
| 219 | dw offset _TEXT:BadVmTrap ; 32 | ||
| 220 | dw offset _TEXT:BadVmTrap ; 33 | ||
| 221 | dw offset _TEXT:BadVmTrap ; 34 | ||
| 222 | dw offset _TEXT:BadVmTrap ; 35 | ||
| 223 | dw offset _TEXT:SSOverride ; 36 - SS Override | ||
| 224 | dw offset _TEXT:BadVmTrap ; 37 | ||
| 225 | dw offset _TEXT:BadVmTrap ; 38 | ||
| 226 | dw offset _TEXT:BadVmTrap ; 39 | ||
| 227 | dw offset _TEXT:BadVmTrap ; 3a | ||
| 228 | dw offset _TEXT:BadVmTrap ; 3b | ||
| 229 | dw offset _TEXT:BadVmTrap ; 3c | ||
| 230 | dw offset _TEXT:BadVmTrap ; 3d | ||
| 231 | dw offset _TEXT:DSOverride ; 3e - DS Override | ||
| 232 | dw offset _TEXT:BadVmTrap ; 3f | ||
| 233 | dw offset _TEXT:BadVmTrap ; 40 | ||
| 234 | dw offset _TEXT:BadVmTrap ; 41 | ||
| 235 | dw offset _TEXT:BadVmTrap ; 42 | ||
| 236 | dw offset _TEXT:BadVmTrap ; 43 | ||
| 237 | dw offset _TEXT:BadVmTrap ; 44 | ||
| 238 | dw offset _TEXT:BadVmTrap ; 45 | ||
| 239 | dw offset _TEXT:BadVmTrap ; 46 | ||
| 240 | dw offset _TEXT:BadVmTrap ; 47 | ||
| 241 | dw offset _TEXT:BadVmTrap ; 48 | ||
| 242 | dw offset _TEXT:BadVmTrap ; 49 | ||
| 243 | dw offset _TEXT:BadVmTrap ; 4a | ||
| 244 | dw offset _TEXT:BadVmTrap ; 4b | ||
| 245 | dw offset _TEXT:BadVmTrap ; 4c | ||
| 246 | dw offset _TEXT:BadVmTrap ; 4d | ||
| 247 | dw offset _TEXT:BadVmTrap ; 4e | ||
| 248 | dw offset _TEXT:BadVmTrap ; 4f | ||
| 249 | dw offset _TEXT:BadVmTrap ; 50 | ||
| 250 | dw offset _TEXT:BadVmTrap ; 51 | ||
| 251 | dw offset _TEXT:BadVmTrap ; 52 | ||
| 252 | dw offset _TEXT:BadVmTrap ; 53 | ||
| 253 | dw offset _TEXT:BadVmTrap ; 54 | ||
| 254 | dw offset _TEXT:BadVmTrap ; 55 | ||
| 255 | dw offset _TEXT:BadVmTrap ; 56 | ||
| 256 | dw offset _TEXT:BadVmTrap ; 57 | ||
| 257 | dw offset _TEXT:BadVmTrap ; 58 | ||
| 258 | dw offset _TEXT:BadVmTrap ; 59 | ||
| 259 | dw offset _TEXT:BadVmTrap ; 5a | ||
| 260 | dw offset _TEXT:BadVmTrap ; 5b | ||
| 261 | dw offset _TEXT:BadVmTrap ; 5c | ||
| 262 | dw offset _TEXT:BadVmTrap ; 5d | ||
| 263 | dw offset _TEXT:BadVmTrap ; 5e | ||
| 264 | dw offset _TEXT:BadVmTrap ; 5f | ||
| 265 | dw offset _TEXT:BadVmTrap ; 60 | ||
| 266 | dw offset _TEXT:BadVmTrap ; 61 | ||
| 267 | dw offset _TEXT:BadVmTrap ; 62 | ||
| 268 | ; | ||
| 269 | ; ARPL is used to return from virtual mode to protected mode for use in MEMM | ||
| 270 | ; | ||
| 271 | dw offset _TEXT:ReturnEMM ; 63 - ARPL (return to Protected mode gateway) | ||
| 272 | dw offset _TEXT:FSOverride ; 64 - FS override | ||
| 273 | dw offset _TEXT:GSOverride ; 65 - GS override | ||
| 274 | dw offset _TEXT:BadVmTrap ; 66 - Operand size override | ||
| 275 | dw offset _TEXT:BadVmTrap ; 67 - Address size override | ||
| 276 | dw offset _TEXT:BadVmTrap ; 68 | ||
| 277 | dw offset _TEXT:BadVmTrap ; 69 | ||
| 278 | dw offset _TEXT:BadVmTrap ; 6a | ||
| 279 | dw offset _TEXT:BadVmTrap ; 6b | ||
| 280 | dw offset _TEXT:EmINSB ; 6c - INSB | ||
| 281 | dw offset _TEXT:EmINSW ; 6d - INSW | ||
| 282 | dw offset _TEXT:EmOUTSB ; 6e - OUTSB | ||
| 283 | dw offset _TEXT:EmOUTSW ; 6f - OUTSW | ||
| 284 | dw offset _TEXT:BadVmTrap ; 70 | ||
| 285 | dw offset _TEXT:BadVmTrap ; 71 | ||
| 286 | dw offset _TEXT:BadVmTrap ; 72 | ||
| 287 | dw offset _TEXT:BadVmTrap ; 73 | ||
| 288 | dw offset _TEXT:BadVmTrap ; 74 | ||
| 289 | dw offset _TEXT:BadVmTrap ; 75 | ||
| 290 | dw offset _TEXT:BadVmTrap ; 76 | ||
| 291 | dw offset _TEXT:BadVmTrap ; 77 | ||
| 292 | dw offset _TEXT:BadVmTrap ; 78 | ||
| 293 | dw offset _TEXT:BadVmTrap ; 79 | ||
| 294 | dw offset _TEXT:BadVmTrap ; 7a | ||
| 295 | dw offset _TEXT:BadVmTrap ; 7b | ||
| 296 | dw offset _TEXT:BadVmTrap ; 7c | ||
| 297 | dw offset _TEXT:BadVmTrap ; 7d | ||
| 298 | dw offset _TEXT:BadVmTrap ; 7e | ||
| 299 | dw offset _TEXT:BadVmTrap ; 7f | ||
| 300 | dw offset _TEXT:BadVmTrap ; 80 | ||
| 301 | dw offset _TEXT:BadVmTrap ; 81 | ||
| 302 | dw offset _TEXT:BadVmTrap ; 82 | ||
| 303 | dw offset _TEXT:BadVmTrap ; 83 | ||
| 304 | dw offset _TEXT:BadVmTrap ; 84 | ||
| 305 | dw offset _TEXT:BadVmTrap ; 85 | ||
| 306 | dw offset _TEXT:BadVmTrap ; 86 | ||
| 307 | dw offset _TEXT:BadVmTrap ; 87 | ||
| 308 | dw offset _TEXT:BadVmTrap ; 88 | ||
| 309 | dw offset _TEXT:BadVmTrap ; 89 | ||
| 310 | dw offset _TEXT:BadVmTrap ; 8a | ||
| 311 | dw offset _TEXT:BadVmTrap ; 8b | ||
| 312 | dw offset _TEXT:BadVmTrap ; 8c | ||
| 313 | dw offset _TEXT:BadVmTrap ; 8d | ||
| 314 | dw offset _TEXT:BadVmTrap ; 8e | ||
| 315 | dw offset _TEXT:BadVmTrap ; 8f | ||
| 316 | dw offset _TEXT:BadVmTrap ; 90 | ||
| 317 | dw offset _TEXT:BadVmTrap ; 91 | ||
| 318 | dw offset _TEXT:BadVmTrap ; 92 | ||
| 319 | dw offset _TEXT:BadVmTrap ; 93 | ||
| 320 | dw offset _TEXT:BadVmTrap ; 94 | ||
| 321 | dw offset _TEXT:BadVmTrap ; 95 | ||
| 322 | dw offset _TEXT:BadVmTrap ; 96 | ||
| 323 | dw offset _TEXT:BadVmTrap ; 97 | ||
| 324 | dw offset _TEXT:BadVmTrap ; 98 | ||
| 325 | dw offset _TEXT:BadVmTrap ; 99 | ||
| 326 | dw offset _TEXT:BadVmTrap ; 9a | ||
| 327 | dw offset _TEXT:BadVmTrap ; 9b | ||
| 328 | dw offset _TEXT:BadVmTrap ; 9c - PUSHF (not for IOPL=3) | ||
| 329 | dw offset _TEXT:BadVmTrap ; 9d - POPF (not for IOPL=3) | ||
| 330 | dw offset _TEXT:BadVmTrap ; 9e | ||
| 331 | dw offset _TEXT:BadVmTrap ; 9f | ||
| 332 | dw offset _TEXT:BadVmTrap ; a0 | ||
| 333 | dw offset _TEXT:BadVmTrap ; a1 | ||
| 334 | dw offset _TEXT:BadVmTrap ; a2 | ||
| 335 | dw offset _TEXT:BadVmTrap ; a3 | ||
| 336 | dw offset _TEXT:BadVmTrap ; a4 - MOVSB | ||
| 337 | dw offset _TEXT:EmMOVSW ; a5 - MOVSW | ||
| 338 | dw offset _TEXT:BadVmTrap ; a6 | ||
| 339 | dw offset _TEXT:BadVmTrap ; a7 | ||
| 340 | dw offset _TEXT:BadVmTrap ; a8 | ||
| 341 | dw offset _TEXT:BadVmTrap ; a9 | ||
| 342 | dw offset _TEXT:BadVmTrap ; aa | ||
| 343 | dw offset _TEXT:BadVmTrap ; ab | ||
| 344 | dw offset _TEXT:BadVmTrap ; ac | ||
| 345 | dw offset _TEXT:BadVmTrap ; ad | ||
| 346 | dw offset _TEXT:BadVmTrap ; ae | ||
| 347 | dw offset _TEXT:BadVmTrap ; af | ||
| 348 | dw offset _TEXT:BadVmTrap ; b0 | ||
| 349 | dw offset _TEXT:BadVmTrap ; b1 | ||
| 350 | dw offset _TEXT:BadVmTrap ; b2 | ||
| 351 | dw offset _TEXT:BadVmTrap ; b3 | ||
| 352 | dw offset _TEXT:BadVmTrap ; b4 | ||
| 353 | dw offset _TEXT:BadVmTrap ; b5 | ||
| 354 | dw offset _TEXT:BadVmTrap ; b6 | ||
| 355 | dw offset _TEXT:BadVmTrap ; b7 | ||
| 356 | dw offset _TEXT:BadVmTrap ; b8 | ||
| 357 | dw offset _TEXT:BadVmTrap ; b9 | ||
| 358 | dw offset _TEXT:BadVmTrap ; ba | ||
| 359 | dw offset _TEXT:BadVmTrap ; bb | ||
| 360 | dw offset _TEXT:BadVmTrap ; bc | ||
| 361 | dw offset _TEXT:BadVmTrap ; bd | ||
| 362 | dw offset _TEXT:BadVmTrap ; be | ||
| 363 | dw offset _TEXT:BadVmTrap ; bf | ||
| 364 | dw offset _TEXT:BadVmTrap ; c0 | ||
| 365 | dw offset _TEXT:BadVmTrap ; c1 | ||
| 366 | dw offset _TEXT:BadVmTrap ; c2 | ||
| 367 | dw offset _TEXT:BadVmTrap ; c3 | ||
| 368 | dw offset _TEXT:BadVmTrap ; c4 | ||
| 369 | dw offset _TEXT:BadVmTrap ; c5 | ||
| 370 | dw offset _TEXT:BadVmTrap ; c6 | ||
| 371 | dw offset _TEXT:BadVmTrap ; c7 | ||
| 372 | dw offset _TEXT:BadVmTrap ; c8 | ||
| 373 | dw offset _TEXT:BadVmTrap ; c9 | ||
| 374 | dw offset _TEXT:BadVmTrap ; ca | ||
| 375 | dw offset _TEXT:BadVmTrap ; cb | ||
| 376 | dw offset _TEXT:EmINT3 ; cc - INT 3 | ||
| 377 | dw offset _TEXT:EmINTnn ; cd - INT nn | ||
| 378 | dw offset _TEXT:EmINTO ; ce - INTO | ||
| 379 | dw offset _TEXT:BadVmTrap ; cf - IRET/EmIRET (not for IOPL=3) | ||
| 380 | dw offset _TEXT:BadVmTrap ; d0 | ||
| 381 | dw offset _TEXT:BadVmTrap ; d1 | ||
| 382 | dw offset _TEXT:BadVmTrap ; d2 | ||
| 383 | dw offset _TEXT:BadVmTrap ; d3 | ||
| 384 | dw offset _TEXT:BadVmTrap ; d4 | ||
| 385 | dw offset _TEXT:BadVmTrap ; d5 | ||
| 386 | dw offset _TEXT:BadVmTrap ; d6 | ||
| 387 | dw offset _TEXT:BadVmTrap ; d7 | ||
| 388 | dw offset _TEXT:BadVmTrap ; d8 | ||
| 389 | dw offset _TEXT:BadVmTrap ; d9 | ||
| 390 | dw offset _TEXT:BadVmTrap ; da | ||
| 391 | dw offset _TEXT:BadVmTrap ; db | ||
| 392 | dw offset _TEXT:BadVmTrap ; dc | ||
| 393 | dw offset _TEXT:BadVmTrap ; dd | ||
| 394 | dw offset _TEXT:BadVmTrap ; de | ||
| 395 | dw offset _TEXT:BadVmTrap ; df | ||
| 396 | dw offset _TEXT:BadVmTrap ; e0 | ||
| 397 | dw offset _TEXT:BadVmTrap ; e1 | ||
| 398 | dw offset _TEXT:BadVmTrap ; e2 | ||
| 399 | dw offset _TEXT:BadVmTrap ; e3 | ||
| 400 | dw offset _TEXT:EmINBimm ; e4 - INB imm | ||
| 401 | dw offset _TEXT:EmINWimm ; e5 - INW imm | ||
| 402 | dw offset _TEXT:EmOUTBimm ; e6 - OUTB imm | ||
| 403 | dw offset _TEXT:EmOUTWimm ; e7 - OUTW imm | ||
| 404 | dw offset _TEXT:BadVmTrap ; e8 | ||
| 405 | dw offset _TEXT:BadVmTrap ; e9 | ||
| 406 | dw offset _TEXT:BadVmTrap ; ea | ||
| 407 | dw offset _TEXT:BadVmTrap ; eb | ||
| 408 | dw offset _TEXT:EmINB ; ec - INB | ||
| 409 | dw offset _TEXT:EmINW ; ed - INW | ||
| 410 | dw offset _TEXT:EmOUTB ; ee - OUTB | ||
| 411 | dw offset _TEXT:EmOUTW ; ef - OUTW | ||
| 412 | dw offset _TEXT:EmLOCK ; f0 - LOCK | ||
| 413 | dw offset _TEXT:BadVmTrap ; f1 | ||
| 414 | dw offset _TEXT:EmREPNE ; f2 - REPNE | ||
| 415 | dw offset _TEXT:EmREP ; f3 - REP/REPE | ||
| 416 | dw offset _TEXT:EmHALT ; f4 - HLT | ||
| 417 | dw offset _TEXT:BadVmTrap ; f5 | ||
| 418 | dw offset _TEXT:BadVmTrap ; f6 | ||
| 419 | dw offset _TEXT:BadVmTrap ; f7 | ||
| 420 | dw offset _TEXT:BadVmTrap ; f8 | ||
| 421 | dw offset _TEXT:BadVmTrap ; f9 | ||
| 422 | dw offset _TEXT:BadVmTrap ; fa - CLI EmCLI (not for IOPL=3) | ||
| 423 | dw offset _TEXT:BadVmTrap ; fb - STI EmSTI (not for IOPL=3) | ||
| 424 | dw offset _TEXT:BadVmTrap ; fc | ||
| 425 | dw offset _TEXT:BadVmTrap ; fd | ||
| 426 | dw offset _TEXT:BadVmTrap ; fe | ||
| 427 | dw offset _TEXT:BadVmTrap ; ff - Change P0F_Invalid, if used | ||
| 428 | |||
| 429 | page | ||
| 430 | ;****************************************************************************** | ||
| 431 | ; VmFault - entry point for Virtual Mode GP faults (from routine vm_trap0d | ||
| 432 | ; in module VMTRAP.ASM). The appropriate instructions are emulated and | ||
| 433 | ; control is returned to the Virtual Mode client. Currently, we assume | ||
| 434 | ; the client is running WITH IOPL, INT gate DPL = 0, and a truncated | ||
| 435 | ; IDT, so INT instruction fault to here and are emulated. All other | ||
| 436 | ; GP faults enter the debugger. | ||
| 437 | ; | ||
| 438 | ; The following instructions are invalid in Real or Virtual Mode: | ||
| 439 | ; | ||
| 440 | ; ARPL, LAR, LSL, VERR, VERW, STR, LTR, SLDT, LLDT | ||
| 441 | ; | ||
| 442 | ; The following instructions are privileged and are thus invalid in | ||
| 443 | ; Virtual Mode since VM progs run at CPL 3: | ||
| 444 | ; | ||
| 445 | ; LIDT, LDGT, LMSW, CLTS, HLT, Debug Register ops, Control | ||
| 446 | ; Register ops, and Test Register ops | ||
| 447 | ; | ||
| 448 | ; If client does not have IOPL, the following instructions must be handled | ||
| 449 | ; (in addition to the INT instructions). This scenario changes for B0: | ||
| 450 | ; | ||
| 451 | ; IN, INS, OUT, OUTS, STI, CLI, LOCK, PUSHF, POPF, and IRET | ||
| 452 | ; | ||
| 453 | ; For B0, the following instructions must be handled when they trap | ||
| 454 | ; according to the bit map in the TSS. | ||
| 455 | ; | ||
| 456 | ; IN, INS, OUT, and OUTS | ||
| 457 | ; | ||
| 458 | ; For Invalid Opcode (vm_trap06) emulation: | ||
| 459 | ; The following instructions are invalid in Real or Virtual Mode: | ||
| 460 | ; | ||
| 461 | ; LTR, LLDT, LAR, LSL, ARPL, STR, SLDT, VERR, VERW | ||
| 462 | ; | ||
| 463 | ; In fielding the exception from Virtual Mode, the 386 interrupt gate | ||
| 464 | ; switched to the Ring 0 stack and pushed 32-bit values as follows: | ||
| 465 | ; | ||
| 466 | ; hiword loword offset (in addition to error code and BP push) | ||
| 467 | ; +------+------+ <-------- Top of 'kernel' stack | ||
| 468 | ; | 0000 | GS | +32 (decimal) | ||
| 469 | ; |------+------| | ||
| 470 | ; | 0000 | FS | +28 | ||
| 471 | ; |------|------| | ||
| 472 | ; | 0000 | DS | +24 | ||
| 473 | ; |------|------| | ||
| 474 | ; | 0000 | ES | +20 | ||
| 475 | ; |------|------| | ||
| 476 | ; | 0000 | SS | +16 | ||
| 477 | ; |------|------| | ||
| 478 | ; | ESP | +12 | ||
| 479 | ; |------|------| | ||
| 480 | ; | EFLAGS | +08 | ||
| 481 | ; |------|------| | ||
| 482 | ; | 0000 | CS | +04 | ||
| 483 | ; |------|------| | ||
| 484 | ; | EIP | +00 | ||
| 485 | ; +------|------+ | ||
| 486 | ; | error code | | ||
| 487 | ; |------|------| <-------- Ring 0 SS:SP | ||
| 488 | ; | (ebp) | | ||
| 489 | ; +------+------+ <-------- Ring 0 SS:EBP | ||
| 490 | ; | ||
| 491 | ; | ||
| 492 | ; ENTRY: 386 Protected Mode - ring 0 | ||
| 493 | ; EBP is on the stack | ||
| 494 | ; SS:BP -> VM trap frame on stack w/error code (faulting selector) | ||
| 495 | ; GP exceptions are faults: pushed CS:EIP points to faulting opcode | ||
| 496 | ; EXIT: via IRET to VM client, instruction emulated as necessary | ||
| 497 | ; USED: (none) (note that DS & ES are free to use - saved during trap) | ||
| 498 | ; STACK: n/a | ||
| 499 | ;------------------------------------------------------------------------------ | ||
| 500 | VmFault proc near | ||
| 501 | PUSH_EBX ; local registers | ||
| 502 | PUSH_ESI | ||
| 503 | HwTabUnlock ; unlock high ram for gdt changes | ||
| 504 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 505 | mov ds,bx ; DS -> GDT | ||
| 506 | ; | ||
| 507 | ; Build a selector (VM1_GSEL) to client's stack. VM1_GSEL is already set | ||
| 508 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 509 | ; | ||
| 510 | mov bx,[bp.VTFOE+VMTF_SS] ; BX = VM SS (segment form) | ||
| 511 | shl bx,4 ; BX = low 16 bits of base | ||
| 512 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 513 | mov bx,[bp.VTFOE+VMTF_SS] ; BX = VM SS (again) | ||
| 514 | shr bx,4 ; BH = high 8 bits of base | ||
| 515 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 516 | ; | ||
| 517 | ; Build a selector (VM2_GSEL) to client's code segment, as above. | ||
| 518 | ; | ||
| 519 | mov bx,[bp.VTFOE+VMTF_CS] ; BX = VM CS (in segment form) | ||
| 520 | shl bx,4 ; BX = low 16 bits of base | ||
| 521 | mov ds:[VM2_GSEL+2],bx ; place in descriptor | ||
| 522 | mov bx,[bp.VTFOE+VMTF_CS] ; BX = VM CS (again) | ||
| 523 | shr bx,4 ; BH = high 8 bits of base | ||
| 524 | mov ds:[VM2_GSEL+4],bh ; place in descriptor | ||
| 525 | ; | ||
| 526 | ; Reset prefix flags | ||
| 527 | ; | ||
| 528 | mov bx,VDMD_GSEL | ||
| 529 | mov es,bx | ||
| 530 | mov ES:[PrefixFlag],0 ; start with no prefixes | ||
| 531 | ; | ||
| 532 | ; Jump to appropriate instruction handler | ||
| 533 | ; | ||
| 534 | mov bx,VM2_GSEL | ||
| 535 | mov ds,bx ; DS = selector for VM code segment | ||
| 536 | mov si,[bp.VTFOE+VMTF_EIP] ; DS:SI = VM CS:IP | ||
| 537 | VmInsHandle: | ||
| 538 | mov bl,ds:[si] ; BL = opcode | ||
| 539 | mov bh,0 ; BX = opcode | ||
| 540 | shl bx,1 ; BX = BX*2 (word table) | ||
| 541 | ; DS:SI = VM CS:IP | ||
| 542 | ; ES pts to local data segment | ||
| 543 | ; VM1_GSEL pts to VM SS | ||
| 544 | ; VM2_GSEL pts to VM CS | ||
| 545 | jmp cs:OpTable[bx] ; enter instruction emulation routine | ||
| 546 | |||
| 547 | VmFault endp | ||
| 548 | |||
| 549 | page | ||
| 550 | ;****************************************************************************** | ||
| 551 | ; BadVmTrap - unsupported Virtual Mode GP exception - enter the debugger | ||
| 552 | ; | ||
| 553 | ; ENTRY: EBP,EBX,ESI are on the stack | ||
| 554 | ; EXIT: to the debugger | ||
| 555 | ; USED: | ||
| 556 | ; STACK: n/a | ||
| 557 | ;------------------------------------------------------------------------------ | ||
| 558 | BadVmTrap proc near | ||
| 559 | jmp Reflect6 ; Reflect to VM illegal opcode handler | ||
| 560 | BadVmTrap endp | ||
| 561 | |||
| 562 | page | ||
| 563 | ;****************************************************************************** | ||
| 564 | ; ReturnEMM - user is trying to go back into the protected mode via ARPL | ||
| 565 | ; | ||
| 566 | ; ENTRY: EBP,EBX,ESI are on the stack | ||
| 567 | ; EXIT: to the debugger | ||
| 568 | ; USED: | ||
| 569 | ; STACK: n/a | ||
| 570 | ;------------------------------------------------------------------------------ | ||
| 571 | ReturnEMM proc near | ||
| 572 | add si, 2 ; "IP" now points to instruction | ||
| 573 | push si ; after "ARPL reg,reg" | ||
| 574 | ret ; back in protected mode! | ||
| 575 | ReturnEMM endp | ||
| 576 | |||
| 577 | page | ||
| 578 | ;****************************************************************************** | ||
| 579 | ; EmINTnn - emulate software interrupt | ||
| 580 | ; | ||
| 581 | ; The emulation of the software INT instructions requires us to massage | ||
| 582 | ; the trap stack frame (see VmFault header) and build a 'real mode' | ||
| 583 | ; stack frame for the virtual mode client so that we can transfer | ||
| 584 | ; control to virtual mode at the address specified in the appropriate | ||
| 585 | ; real mode IDT vector. The client's IRET out of the interrupt routine | ||
| 586 | ; will proceed normally (assuming we're letting him run with IOPL = 3). | ||
| 587 | ; Since we're fielding the trap from Virtual Mode, we assume the high | ||
| 588 | ; word of ESP and EIP is 0000. | ||
| 589 | ; | ||
| 590 | ; +-------+ <-------- Client's current SS:SP | ||
| 591 | ; | Flags | +4 | ||
| 592 | ; |-------| | ||
| 593 | ; | CS | +2 | ||
| 594 | ; |-------| | ||
| 595 | ; | IP | +0 | ||
| 596 | ; +-------+ <-------- Client's SS:SP when we let him have control | ||
| 597 | ; | ||
| 598 | ; ENTRY: 386 Protected Mode | ||
| 599 | ; EBP,EBX,ESI pushed on stack | ||
| 600 | ; VM1_GSEL = VM client's stack segment | ||
| 601 | ; VM2_GSEL = VM client's code segment | ||
| 602 | ; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL) | ||
| 603 | ; EXIT: via IRET to VM client | ||
| 604 | ; appropriate real mode IRET set up @ client's SS:SP | ||
| 605 | ; USED: (none) | ||
| 606 | ; STACK: | ||
| 607 | ; | ||
| 608 | ; to do: Streamline this code - it's on the critical path | ||
| 609 | ; Decide about how to handle Trace Bit in general | ||
| 610 | ;------------------------------------------------------------------------------ | ||
| 611 | EmINTnn proc near | ||
| 612 | |||
| 613 | inc si ; DS:SI -> nn (int #) | ||
| 614 | |||
| 615 | ; Check for Int15 (Move Block call) | ||
| 616 | cmp byte ptr [si], 15h | ||
| 617 | jne NotInt15 | ||
| 618 | cmp ah,87h ;Q: is this a move block call ? | ||
| 619 | jne NotInt15 ; N: process as normal interrupt | ||
| 620 | mov bx,RCODEA_GSEL ; Y: check local flag | ||
| 621 | mov ds,bx ; DS -> R_CODE seg | ||
| 622 | ASSUME DS:R_CODE | ||
| 623 | cmp [MB_Flag],0 ; Q: do we see this move block ? | ||
| 624 | je NotInt15 ; N: process as normal int | ||
| 625 | ; Y: emulate move block | ||
| 626 | ; set up VM1_GSEL to point to ES:0 from | ||
| 627 | ; Virtual Mode | ||
| 628 | ;NOTE: DS -> R_CODE | ||
| 629 | inc si | ||
| 630 | mov [bp.VTFOE+VMTF_EIP], si ; point beyond int6 instr | ||
| 631 | mov bx,GDTD_GSEL | ||
| 632 | mov es,bx ; ES pts to GDT | ||
| 633 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = ES seg addr | ||
| 634 | shl bx,4 ; BX = low 16 bits of ES addr | ||
| 635 | mov es:[VM1_GSEL+2],bx ; set low 16 bits of ES base addr | ||
| 636 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = ES seg addr again | ||
| 637 | shr bx,4 ; BH = high 8 bits of ES addr | ||
| 638 | mov es:[VM1_GSEL+4],bh ; place in descriptor | ||
| 639 | |||
| 640 | mov bx,VM1_GSEL | ||
| 641 | mov es,bx ; ES pts to VM ES area | ||
| 642 | |||
| 643 | mov bx,sp ; SS:BX -> GP Fault stack frame | ||
| 644 | mov si,SS:[bx.GPF_ESI] ; ES:SI pts to caller's gdt | ||
| 645 | call move_block ; move block function | ||
| 646 | mov ds:[MB_Flag],0 ; turn off flag !! | ||
| 647 | |||
| 648 | ASSUME DS:DGROUP ; done with R_CODE | ||
| 649 | |||
| 650 | jmp short EmSkipLockExit ; exit, but skip table lock. | ||
| 651 | ; move block MAY unlock tables. | ||
| 652 | ; | ||
| 653 | ; Adjust client's SP to make room for building his IRET frame | ||
| 654 | ; | ||
| 655 | NotInt15: | ||
| 656 | sub word ptr [bp.VTFOE+VMTF_ESP],6 ; adjust client's SP | ||
| 657 | mov bx,VM1_GSEL | ||
| 658 | mov ds,bx ; DS = VM stack segment | ||
| 659 | mov si,[bp.VTFOE+VMTF_ESP] ; DS:SI -> client's IRET stack frame | ||
| 660 | ; | ||
| 661 | ; Move low 16 bits of Flags, CS, and EIP from IRET frame to client stack frame | ||
| 662 | ; | ||
| 663 | mov bx,[bp.VTFOE+VMTF_EFLAGS] ; low word of EFLAGS | ||
| 664 | ; | ||
| 665 | ; *** Clear IF bit on flags for reflect, but leave it unchanged for the | ||
| 666 | ; flags on the IRET stack we build on the client's stack | ||
| 667 | ; *** Also clear the Trace Flag -> because all software INTs clear the trace | ||
| 668 | ; flag. | ||
| 669 | ; | ||
| 670 | and [bp.VTFOE+VMTF_EFLAGS],not 300h | ||
| 671 | |||
| 672 | mov ds:[si.4],bx ; to client's flags | ||
| 673 | mov bx,[bp.VTFOE+VMTF_CS] ; | ||
| 674 | mov ds:[si.2],bx ; to client's CS | ||
| 675 | mov bx,[bp.VTFOE+VMTF_EIP] ; low word of EIP | ||
| 676 | add bx,2 ; set IP past the instruction we emulate | ||
| 677 | mov ds:[si.0],bx ; to client's IP | ||
| 678 | ; | ||
| 679 | ; Replace low 16 bits of IRET frame CS:EIP with vector from real mode IDT | ||
| 680 | ; | ||
| 681 | mov si,VM2_GSEL | ||
| 682 | mov ds,si ; DS -> Client's code segment | ||
| 683 | mov bl,ds:[bx-1] ; get INTerrupt number | ||
| 684 | xor bh,bh ; BX has INT number | ||
| 685 | shl bx,2 ; BX = BX * 4 (vector table index) | ||
| 686 | mov si,RM_IDT_GSEL ; get real mode IDT alias | ||
| 687 | mov ds,si ; DS -> Real Mode IDT | ||
| 688 | mov si,ds:[bx] ; | ||
| 689 | mov [bp.VTFOE+VMTF_EIP],si ; move the IP | ||
| 690 | mov si,ds:[bx+2] ; | ||
| 691 | mov [bp.VTFOE+VMTF_CS],si ; move the CS | ||
| 692 | ; | ||
| 693 | ; 32-bit IRET back to client | ||
| 694 | ; | ||
| 695 | EmExit: | ||
| 696 | HwTabLock ; enable the high ram hw protection | ||
| 697 | EmSkipLockExit: ; as the label implies... | ||
| 698 | POP_ESI ; restore local regs | ||
| 699 | POP_EBX | ||
| 700 | POP_EBP | ||
| 701 | add sp,4 ; throw away error code | ||
| 702 | OP32_IRET ; *** RETURN *** to client | ||
| 703 | EmINTnn endp | ||
| 704 | |||
| 705 | page | ||
| 706 | ;****************************************************************************** | ||
| 707 | ; EmINT3 - emulate the 'breakpoint' interrupt instruction | ||
| 708 | ; | ||
| 709 | ; ENTRY: 386 Protected Mode | ||
| 710 | ; EBP,EBX,ESI pushed on stack | ||
| 711 | ; VM1_GSEL = VM client's stack segment | ||
| 712 | ; VM2_GSEL = VM client's code segment | ||
| 713 | ; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL) | ||
| 714 | ; EXIT: via IRET to VM client | ||
| 715 | ; appropriate real mode IRET set up @ client's SS:SP | ||
| 716 | ; USED: (none) | ||
| 717 | ; STACK: | ||
| 718 | ; | ||
| 719 | ; to do: implement the handler | ||
| 720 | ;------------------------------------------------------------------------------ | ||
| 721 | EmINT3 proc near | ||
| 722 | mov ES:[RefNum], 03h ; Vector to VM int 3 handler | ||
| 723 | RefIntN: | ||
| 724 | inc si ; fault, not a trap | ||
| 725 | mov [bp.VTFOE+VMTF_EIP], si ; point beyond int3 | ||
| 726 | jmp RefToRom ; and let the VM OS handle it | ||
| 727 | EmINT3 endp | ||
| 728 | |||
| 729 | ;****************************************************************************** | ||
| 730 | ; EmINTO - emulate overflow interrupt | ||
| 731 | ; | ||
| 732 | ; ENTRY: 386 Protected Mode | ||
| 733 | ; EBP,EBX,ESI pushed on stack | ||
| 734 | ; VM1_GSEL = VM client's stack segment | ||
| 735 | ; VM2_GSEL = VM client's code segment | ||
| 736 | ; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL) | ||
| 737 | ; EXIT: via IRET to VM client | ||
| 738 | ; appropriate real mode IRET set up @ client's SS:SP | ||
| 739 | ; USED: (none) | ||
| 740 | ; STACK: | ||
| 741 | ;------------------------------------------------------------------------------ | ||
| 742 | EmINTO proc near | ||
| 743 | mov ES:[RefNum], 04h ; Vector to VM int 3 handler | ||
| 744 | jmp short RefIntN | ||
| 745 | EmINTO endp | ||
| 746 | |||
| 747 | page | ||
| 748 | ;****************************************************************************** | ||
| 749 | ; EmINB - emulate the IN byte instruction | ||
| 750 | ; | ||
| 751 | ; ENTRY: 386 Protected Mode | ||
| 752 | ; EBP,EBX,ESI pushed on stack | ||
| 753 | ; VM1_GSEL = VM client's stack segment | ||
| 754 | ; VM2_GSEL = VM client's code segment | ||
| 755 | ; DS:SI -> faulting opcode = nn (DS = VM2_GSEL) | ||
| 756 | ; EXIT: via IRET to VM client | ||
| 757 | ; USED: | ||
| 758 | ; STACK: n/a | ||
| 759 | ;------------------------------------------------------------------------------ | ||
| 760 | EmINB proc near | ||
| 761 | inc si | ||
| 762 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 763 | push bx | ||
| 764 | xor bx,bx ; IN instruction | ||
| 765 | call IO_Trap ; Q: Emulated ? | ||
| 766 | jnc EINB_Exit ; Y: exit | ||
| 767 | in al,dx ; N:do the INput | ||
| 768 | EINB_Exit: | ||
| 769 | pop bx | ||
| 770 | jmp EmExit ; *** RETURN *** to VM client | ||
| 771 | EmINB endp | ||
| 772 | |||
| 773 | page | ||
| 774 | ;****************************************************************************** | ||
| 775 | ; EmINW - emulate IN word | ||
| 776 | ; | ||
| 777 | ; This routine emulates the IN word instruction | ||
| 778 | ; | ||
| 779 | ; ENTRY 386 PROTECTED MODE | ||
| 780 | ; see common description at top | ||
| 781 | ; | ||
| 782 | ; EXIT IRET back to VM program | ||
| 783 | ;------------------------------------------------------------------------------ | ||
| 784 | EmINW proc near | ||
| 785 | inc si | ||
| 786 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 787 | push bx | ||
| 788 | xor bx,bx ; IN instruction | ||
| 789 | call IO_Trap ; Q: Emulated ? | ||
| 790 | cbw ; AX= returned value | ||
| 791 | jnc EINW_Exit ; Y: exit | ||
| 792 | in ax,dx ; N:do the word INput | ||
| 793 | EINW_Exit: ; | ||
| 794 | pop bx ; | ||
| 795 | jmp EmExit ; *** RETURN *** to VM client | ||
| 796 | EmINW endp | ||
| 797 | |||
| 798 | page | ||
| 799 | ;****************************************************************************** | ||
| 800 | ; EmINBimm - emulate IN word immediate | ||
| 801 | ; | ||
| 802 | ; This routine emulates the IN word immediate instruction | ||
| 803 | ; | ||
| 804 | ; ENTRY 386 PROTECTED MODE | ||
| 805 | ; see common description at top | ||
| 806 | ; | ||
| 807 | ; EXIT IRET back to VM program | ||
| 808 | ;------------------------------------------------------------------------------ | ||
| 809 | EmINBimm proc near | ||
| 810 | push bx | ||
| 811 | push dx | ||
| 812 | mov dl,ds:[si+1] ; get port number | ||
| 813 | xor dh,dh ; DX has INT number | ||
| 814 | add si, 2 | ||
| 815 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 816 | xor bx,bx ; IN instruction | ||
| 817 | call IO_Trap ; Q: Emulated ? | ||
| 818 | jnc EINBi_Exit ; Y: exit | ||
| 819 | in al,dx ; N:do the INput | ||
| 820 | EINBi_exit: | ||
| 821 | pop dx | ||
| 822 | pop bx | ||
| 823 | jmp EmExit ; *** RETURN *** to VM client | ||
| 824 | EmINBimm endp | ||
| 825 | |||
| 826 | page | ||
| 827 | ;****************************************************************************** | ||
| 828 | ;*** EmINWimm - emulate IN word immediate | ||
| 829 | ; | ||
| 830 | ; This routine emulates the IN word immediate instruction | ||
| 831 | ; | ||
| 832 | ; ENTRY 386 PROTECTED MODE | ||
| 833 | ; see common description at top | ||
| 834 | ; | ||
| 835 | ; EXIT IRET back to VM program | ||
| 836 | ;------------------------------------------------------------------------------ | ||
| 837 | EmINWimm proc near | ||
| 838 | push bx | ||
| 839 | push dx | ||
| 840 | mov dl,ds:[si+1] ; get port number | ||
| 841 | xor dh,dh ; DX has INT number | ||
| 842 | add si, 2 | ||
| 843 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 844 | xor bx,bx ; IN instruction | ||
| 845 | call IO_Trap ; Q: Emulated ? | ||
| 846 | cbw ; AX = returned value | ||
| 847 | jnc EINWi_Exit ; Y: exit | ||
| 848 | in ax,dx ; N:do the word INput | ||
| 849 | EINWi_Exit: | ||
| 850 | pop dx | ||
| 851 | pop bx | ||
| 852 | jmp EmExit ; *** RETURN *** to VM client | ||
| 853 | EmINWimm endp | ||
| 854 | |||
| 855 | page | ||
| 856 | ;****************************************************************************** | ||
| 857 | ;*** EmOUTB - emulate OUT byte | ||
| 858 | ; | ||
| 859 | ; This routine emulates the OUT byte instruction | ||
| 860 | ; | ||
| 861 | ; ENTRY 386 PROTECTED MODE | ||
| 862 | ; see common description at top | ||
| 863 | ; | ||
| 864 | ; EXIT IRET back to VM program | ||
| 865 | ; | ||
| 866 | EmOUTB proc near | ||
| 867 | inc si | ||
| 868 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 869 | push bx | ||
| 870 | push dx | ||
| 871 | mov bx,1 ; OUT instruction | ||
| 872 | call IO_Trap ; Q: Emulated ? | ||
| 873 | jnc EOUTB_Exit ; Y:exit | ||
| 874 | EOUTB_em: | ||
| 875 | out dx,al ; N:do the byte OUTput | ||
| 876 | EOUTB_Exit: | ||
| 877 | pop dx | ||
| 878 | pop bx | ||
| 879 | jmp EmExit ; *** RETURN *** to VM client | ||
| 880 | EmOUTB endp | ||
| 881 | |||
| 882 | page | ||
| 883 | ;****************************************************************************** | ||
| 884 | ;*** EmOUTW - emulate OUT word | ||
| 885 | ; | ||
| 886 | ; This routine emulates the OUT word instruction | ||
| 887 | ; | ||
| 888 | ; ENTRY 386 PROTECTED MODE | ||
| 889 | ; see common description at top | ||
| 890 | ; | ||
| 891 | ; EXIT IRET back to VM program | ||
| 892 | ; | ||
| 893 | EmOUTW proc near | ||
| 894 | inc si | ||
| 895 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 896 | push bx | ||
| 897 | mov bx,1 ; OUT instruction | ||
| 898 | call IO_Trap ; Q: Emulated ? | ||
| 899 | jnc EOUTW_Exit ; Y: exit | ||
| 900 | ; N: | ||
| 901 | out dx,ax ; do the word OUTput | ||
| 902 | EOUTW_Exit: | ||
| 903 | pop bx | ||
| 904 | jmp EmExit ; *** RETURN *** to VM client | ||
| 905 | EmOUTW endp | ||
| 906 | |||
| 907 | page | ||
| 908 | ;****************************************************************************** | ||
| 909 | ;*** EmOUTBimm - emulate OUT byte immediate | ||
| 910 | ; | ||
| 911 | ; This routine emulates the OUT byte immediate | ||
| 912 | ; | ||
| 913 | ; ENTRY 386 PROTECTED MODE | ||
| 914 | ; see common description at top | ||
| 915 | ; | ||
| 916 | ; EXIT IRET back to VM program | ||
| 917 | ; | ||
| 918 | EmOUTBimm proc near | ||
| 919 | push bx | ||
| 920 | push dx | ||
| 921 | mov dl,ds:[si+1] ; get port number | ||
| 922 | xor dh,dh ; DX has INT number | ||
| 923 | add si, 2 | ||
| 924 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 925 | mov bx,1 ; OUT instruction | ||
| 926 | call IO_Trap ; Q: Emulated ? | ||
| 927 | jnc EOUTBi_Exit ; Y:exit | ||
| 928 | EOUTBi_em: | ||
| 929 | out dx,al ; N:do the byte OUTput | ||
| 930 | EOUTBi_Exit: | ||
| 931 | pop dx | ||
| 932 | pop bx | ||
| 933 | jmp EmExit ; *** RETURN *** to VM client | ||
| 934 | EmOUTBimm endp | ||
| 935 | |||
| 936 | page | ||
| 937 | ;****************************************************************************** | ||
| 938 | ;*** EmOUTWimm - emulate OUT word immediate | ||
| 939 | ; | ||
| 940 | ; This routine emulates the OUT word immediate instruction | ||
| 941 | ; | ||
| 942 | ; ENTRY 386 PROTECTED MODE | ||
| 943 | ; see common description at top | ||
| 944 | ; | ||
| 945 | ; EXIT IRET back to VM program | ||
| 946 | ; | ||
| 947 | EmOUTWimm proc near | ||
| 948 | push bx | ||
| 949 | push dx | ||
| 950 | mov dl,ds:[si+1] ; get port number | ||
| 951 | xor dh,dh ; DX has INT number | ||
| 952 | add si, 2 | ||
| 953 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 954 | mov bx,1 ; OUT instruction | ||
| 955 | call IO_Trap ; Q: Emulated ? | ||
| 956 | jnc EOUTWi_Exit ; Y: exit | ||
| 957 | out dx,ax ; N:do the word OUTput | ||
| 958 | EOUTWi_Exit: | ||
| 959 | pop dx | ||
| 960 | pop bx | ||
| 961 | jmp EmExit ; *** RETURN *** to VM client | ||
| 962 | EmOUTWimm endp | ||
| 963 | page | ||
| 964 | ;****************************************************************************** | ||
| 965 | ;*** EmHALT - Emulate HALT command | ||
| 966 | ; | ||
| 967 | ; This routine is entered if a faulting instruction | ||
| 968 | ; is a HALT command | ||
| 969 | ; | ||
| 970 | ; ENTRY 386 PROTECTED MODE | ||
| 971 | ; see common description at top | ||
| 972 | ; | ||
| 973 | ; EXIT return to VM client unless client IF=0 then | ||
| 974 | ; HLT is executed with IF=0 | ||
| 975 | ; | ||
| 976 | EmHALT proc near | ||
| 977 | ; Q: client's IF bit is 0? | ||
| 978 | test word ptr [bp.VTFOE+VMTF_EFLAGS], IF_FLAG | ||
| 979 | jz EmDoHlt ; Y: execute HLT if IF=0 | ||
| 980 | inc si ; inc VM CS:IP past command | ||
| 981 | mov [bp.VTFOE+VMTF_EIP], si ; we emulate | ||
| 982 | ; A halt on an INTEL architecture machine is just waiting for an interrupt | ||
| 983 | ; We'll pretend an interrupt occurs after a short wait | ||
| 984 | push cx | ||
| 985 | mov cx,4000h | ||
| 986 | loop $ ; Wait awhile | ||
| 987 | pop cx | ||
| 988 | jmp EmExit ; then leave | ||
| 989 | emDoHlt: | ||
| 990 | cli | ||
| 991 | hlt ; Halt till NMI | ||
| 992 | jmp EmExit | ||
| 993 | |||
| 994 | EmHALT endp | ||
| 995 | |||
| 996 | page | ||
| 997 | ;****************************************************************************** | ||
| 998 | ;*** EmLoadal2 - Emulate 286 Loadall command | ||
| 999 | ; | ||
| 1000 | ; This routine is entered if a faulting instruction | ||
| 1001 | ; is a Loadall 286 command | ||
| 1002 | ; | ||
| 1003 | ; ENTRY 386 PROTECTED MODE | ||
| 1004 | ; see common description at top | ||
| 1005 | ; | ||
| 1006 | ; EXIT return to VM client | ||
| 1007 | ; | ||
| 1008 | EmLoadal2 proc near | ||
| 1009 | |||
| 1010 | test ES:[PrefixFlag],P0F_FLAG ; Q:Do we have the right prefix? | ||
| 1011 | jz Not_Loadall | ||
| 1012 | jmp EM286ll ; Y: emulate 286 loadall | ||
| 1013 | |||
| 1014 | Not_Loadall: | ||
| 1015 | jmp BadVmTrap ; N: Vector to VM illegal opcode | ||
| 1016 | |||
| 1017 | EmLoadal2 endp | ||
| 1018 | |||
| 1019 | ;****************************************************************************** | ||
| 1020 | ;*** EmLoadal3 - Emulate 386 Loadall command | ||
| 1021 | ; | ||
| 1022 | ; This routine is entered if a faulting instruction | ||
| 1023 | ; is a Loadall 386 command | ||
| 1024 | ; | ||
| 1025 | ; ENTRY 386 PROTECTED MODE | ||
| 1026 | ; see common description at top | ||
| 1027 | ; | ||
| 1028 | ; EXIT return to VM client | ||
| 1029 | ; | ||
| 1030 | EmLoadal3 proc near | ||
| 1031 | |||
| 1032 | test ES:[PrefixFlag],P0F_FLAG | ||
| 1033 | jz Not_Loadall | ||
| 1034 | jmp EM386ll ; Y: emulate 386 loadall | ||
| 1035 | |||
| 1036 | EmLoadal3 endp | ||
| 1037 | |||
| 1038 | ;****************************************************************************** | ||
| 1039 | ; EmCLTS - emulate the CLTS instruction | ||
| 1040 | ; | ||
| 1041 | ; ENTRY: 386 Protected Mode | ||
| 1042 | ; EBP,EBX,ESI pushed on stack | ||
| 1043 | ; VM1_GSEL = VM client's stack segment | ||
| 1044 | ; VM2_GSEL = VM client's code segment | ||
| 1045 | ; DS:SI -> faulting opcode = nn (DS = VM2_GSEL) | ||
| 1046 | ; EXIT: via IRET to VM client | ||
| 1047 | ; USED: | ||
| 1048 | ; STACK: n/a | ||
| 1049 | ;------------------------------------------------------------------------------ | ||
| 1050 | EmCLTS proc near | ||
| 1051 | |||
| 1052 | test ES:[PrefixFlag],P0F_FLAG | ||
| 1053 | jz Not_CLTS | ||
| 1054 | clts ; go ahead and CLTS | ||
| 1055 | inc si ; inc VM CS:IP past command | ||
| 1056 | mov [bp.VTFOE+VMTF_EIP], si ; we emulate | ||
| 1057 | jmp EmExit ; and leave | ||
| 1058 | |||
| 1059 | Not_CLTS: | ||
| 1060 | jmp BadVmTrap | ||
| 1061 | |||
| 1062 | EmCLTS endp | ||
| 1063 | |||
| 1064 | ;****************************************************************************** | ||
| 1065 | ; EmProtIns - emulate the protection control instructions | ||
| 1066 | ; Currently this throws LIDT and LGDT to the error handler and only emulates | ||
| 1067 | ; LMSW | ||
| 1068 | ; NOTE: The Stack configuration is critical!!! If it is changed, the | ||
| 1069 | ; offsets to the register images must be updated accordingly. | ||
| 1070 | ; | ||
| 1071 | ; | ||
| 1072 | ; ENTRY: 386 Protected Mode | ||
| 1073 | ; EBP,EBX,ESI pushed on stack | ||
| 1074 | ; VM1_GSEL = VM client's stack segment | ||
| 1075 | ; VM2_GSEL = VM client's code segment | ||
| 1076 | ; DS:SI -> faulting opcode = nn (DS = VM2_GSEL) | ||
| 1077 | ; EXIT: via IRET to VM client | ||
| 1078 | ; bp.VTFOE+VMTF_EIP points beyond offender to next client instruction | ||
| 1079 | ; VM2_GSEL, DS, and SI may be modified at exit, this should not be a | ||
| 1080 | ; problem for the IRET | ||
| 1081 | ; USED: | ||
| 1082 | ; STACK: n/a | ||
| 1083 | ;------------------------------------------------------------------------------ | ||
| 1084 | EmProtIns proc near | ||
| 1085 | |||
| 1086 | test ES:[PrefixFlag],P0F_FLAG | ||
| 1087 | jnz EmPI1 | ||
| 1088 | jmp Not_ProtIns1 | ||
| 1089 | EmPI1: | ||
| 1090 | push dx | ||
| 1091 | push ax | ||
| 1092 | push es | ||
| 1093 | mov dx, ES:[PrefixFlag] | ||
| 1094 | mov bx,VDMCA_GSEL ; Load CODE (writeable) alias | ||
| 1095 | mov es, bx | ||
| 1096 | assume es:_TEXT | ||
| 1097 | inc si ; set si past the opcode | ||
| 1098 | mov bl,[si] ; BL = modR/M | ||
| 1099 | mov bh, bl ; BH = modR/M | ||
| 1100 | and bl, 38h | ||
| 1101 | cmp bl, 30h | ||
| 1102 | je EmLMSW ; Emulate LMSW | ||
| 1103 | cmp bl, 18h | ||
| 1104 | jne LGDTerr ; VM guy not allowed to LGDT | ||
| 1105 | mov bx, ErrLIDT | ||
| 1106 | jmp ExitPIer ; VM guy not allowed to LIDT | ||
| 1107 | LGDTerr: | ||
| 1108 | mov bx, ErrLGDT | ||
| 1109 | jmp ExitPIer | ||
| 1110 | EmLMSW: | ||
| 1111 | inc si ; set SI past the modR/M | ||
| 1112 | mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI | ||
| 1113 | mov bl, bh ; BL = modR/M | ||
| 1114 | cmp bl, 0C0h ; is MSW being loaded from a register? | ||
| 1115 | jb MoveData ; N: do a move from the VM's memory | ||
| 1116 | jmp MoveReg ; Y: go do a register move | ||
| 1117 | |||
| 1118 | MoveData: | ||
| 1119 | ; Because of all the possible addressing modes this is pretty nasty. Like | ||
| 1120 | ; MoveReg, it is complicated by the requirement to not clear the PE bit. | ||
| 1121 | ; The general approach is to find the client's data value, put it in AX, | ||
| 1122 | ; set the PE bit in AX, then load the MSW from AX. To keep from having | ||
| 1123 | ; to know about all the modR/M combinations, we yank the client's possible | ||
| 1124 | ; offset from his code, and put his slightly modified modR/M byte in our | ||
| 1125 | ; home-made MOV AX, MemData instruction. | ||
| 1126 | |||
| 1127 | ; If there is a data offset, yank it from the VM instruction and put it | ||
| 1128 | ; in our instruction. | ||
| 1129 | |||
| 1130 | and bl, 0C7h ; Force AX to be the MOV destination | ||
| 1131 | mov byte ptr es:[LMSWmod],bl | ||
| 1132 | mov ax, 09090h | ||
| 1133 | mov word ptr es:[LMSWoff],ax ; initialize offset to NOPS | ||
| 1134 | cmp bl, 06h ; special case for DS:d16 | ||
| 1135 | je load16off | ||
| 1136 | and bl, 0C0h | ||
| 1137 | cmp bl, 040h | ||
| 1138 | je load8off | ||
| 1139 | cmp bl, 080h | ||
| 1140 | jne BldDesc ; No data offset, so go build desc | ||
| 1141 | Load16off: | ||
| 1142 | mov ax,[si] ; AX = 16 bit offset | ||
| 1143 | mov word ptr es:[LMSWoff],ax | ||
| 1144 | add si, 2 | ||
| 1145 | mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI | ||
| 1146 | jmp short BldDesc | ||
| 1147 | Load8off: | ||
| 1148 | mov al,[si] ; AL = 8 bit offset | ||
| 1149 | mov byte ptr es:[LMSWoff],al | ||
| 1150 | inc si | ||
| 1151 | mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI | ||
| 1152 | |||
| 1153 | BldDesc: | ||
| 1154 | ; Build a descriptor to the client's data segment | ||
| 1155 | |||
| 1156 | mov bl, bh | ||
| 1157 | mov ax, [bp.VTFOE+VMTF_DS] ; Assume DS is the data segment | ||
| 1158 | |||
| 1159 | ; Check for segment override | ||
| 1160 | and dx, 00FCh ; strip all but segment overrides | ||
| 1161 | cmp dx, CS_FLAG | ||
| 1162 | jl GetmodBase ; no override, check base | ||
| 1163 | je CS_data | ||
| 1164 | cmp dx, ES_FLAG | ||
| 1165 | je ES_data | ||
| 1166 | jl GetSel ; ds is override | ||
| 1167 | cmp dx, FS_FLAG | ||
| 1168 | jl SS_data | ||
| 1169 | je FS_data | ||
| 1170 | GS_data: | ||
| 1171 | mov ax, [bp.VTFOE+VMTF_GS] ; GS is the data segment | ||
| 1172 | jmp short GetSel | ||
| 1173 | FS_data: | ||
| 1174 | mov ax, [bp.VTFOE+VMTF_FS] ; FS is the data segment | ||
| 1175 | jmp short GetSel | ||
| 1176 | SS_data: | ||
| 1177 | mov ax, VM1_GSEL | ||
| 1178 | mov ds, ax | ||
| 1179 | jmp short RestoreRegs | ||
| 1180 | CS_data: | ||
| 1181 | mov ax, VM2_GSEL | ||
| 1182 | mov ds, ax | ||
| 1183 | jmp short RestoreRegs | ||
| 1184 | ES_data: | ||
| 1185 | mov ax, [bp.VTFOE+VMTF_ES] ; ES is the data segment | ||
| 1186 | jmp short GetSel | ||
| 1187 | |||
| 1188 | GetmodBase: | ||
| 1189 | ; We have no Segment override, so we need to look at the modR/M byte to | ||
| 1190 | ; see whether or not the data index/offset is based on DS (assumed) or SS | ||
| 1191 | and bl, 0C7h ; clear instruction bits | ||
| 1192 | cmp bl, 46h | ||
| 1193 | je SS_Data ; EA = SS:[BP+d8] | ||
| 1194 | and bl, 7 | ||
| 1195 | cmp bl, 2 | ||
| 1196 | je SS_Data ; EA = SS:[BP+SI+?] | ||
| 1197 | cmp bl, 3 | ||
| 1198 | je SS_Data ; EA = SS:[BP+DI+?] | ||
| 1199 | |||
| 1200 | GetSel: | ||
| 1201 | ; Build a selector (VM2_GSEL) to client's data. VM2_GSEL is already set | ||
| 1202 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 1203 | ; The Descriptor base VM segment value is in AX | ||
| 1204 | push es | ||
| 1205 | push bx | ||
| 1206 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 1207 | mov es,bx ; DS -> GDT | ||
| 1208 | mov bx, ax ; copy the VM data segment value | ||
| 1209 | shl ax,4 ; BX = low 16 bits of base | ||
| 1210 | mov es:[VM2_GSEL+2],ax ; place in descriptor | ||
| 1211 | shr bx,4 ; BH = high 8 bits of base | ||
| 1212 | mov es:[VM2_GSEL+4],bh ; place in descriptor | ||
| 1213 | mov ax, VM2_GSEL | ||
| 1214 | mov ds, ax | ||
| 1215 | pop bx | ||
| 1216 | pop es | ||
| 1217 | |||
| 1218 | RestoreRegs: | ||
| 1219 | ; Since BX, SI, DI, and BP can all be used to form an effective address we | ||
| 1220 | ; blindly restore BX, SI, and BP from the stack so that we don't | ||
| 1221 | ; have to know what the instruction is using for its effective address. | ||
| 1222 | ; DI does not need to be restored, because it should still be the client's | ||
| 1223 | |||
| 1224 | push bp | ||
| 1225 | mov bp, sp | ||
| 1226 | |||
| 1227 | ; Now the Stack had better look like PROT_INS_FRAME. (vm386.inc) | ||
| 1228 | mov si, [bp.PIF_ESI] | ||
| 1229 | mov bx, [bp.PIF_EBX] | ||
| 1230 | mov bp, [bp.PIF_EBP] | ||
| 1231 | |||
| 1232 | ; Move the VM data operand to AX | ||
| 1233 | db 3Eh ; ds overide (for bp & di) | ||
| 1234 | db 8Bh ; MOV opcode | ||
| 1235 | LMSWmod db 00h ; modR/M | ||
| 1236 | LMSWoff db 90h, 90h ; possible offset (NOPS otherwise) | ||
| 1237 | |||
| 1238 | jmp ExLMSW ; Finally... go do the LMSW | ||
| 1239 | |||
| 1240 | MoveReg: | ||
| 1241 | ; Here we have a LMSW from one of the general registers. This is pretty | ||
| 1242 | ; ugly because many of the possible registers the client might have used | ||
| 1243 | ; are currently saved on the stack. It is also complicated by the | ||
| 1244 | ; requirement to not clear the PE bit. The general approach is to find | ||
| 1245 | ; the client's register value/image, put it in AX, set the PE bit in AX, | ||
| 1246 | ; then load the MSW from AX. To keep from having to know all the modR/M | ||
| 1247 | ; combinations, we again use a slightly modified client's modR/M byte in | ||
| 1248 | ; our home-made MOV AX, RegData instruction. | ||
| 1249 | |||
| 1250 | push bp | ||
| 1251 | mov bp, sp | ||
| 1252 | |||
| 1253 | ; Now the Stack had better look like PROT_INS_FRAME. (vm386.inc) | ||
| 1254 | |||
| 1255 | and bh, 07h ; If Src is AX, it hasn't been changed | ||
| 1256 | jz ExLMSW ; so just go do the the LMSW | ||
| 1257 | CkSrcBX: ; otherwise, find it and move it to AX | ||
| 1258 | cmp bh, 3 | ||
| 1259 | jne CkSrcBP | ||
| 1260 | mov ax, [bp.PIF_EBX] ; src was BX, get from stack | ||
| 1261 | jmp short ExLMSW | ||
| 1262 | CkSrcBP: | ||
| 1263 | cmp bh, 5 | ||
| 1264 | jne CkSrcSI | ||
| 1265 | mov ax, [bp.PIF_EBP] ; src was BP, get from stack | ||
| 1266 | jmp short ExLMSW | ||
| 1267 | CkSrcSI: | ||
| 1268 | cmp bh, 6 | ||
| 1269 | jne CkSrcDX | ||
| 1270 | mov ax, [bp.PIF_ESI] ; src was SI, get from stack | ||
| 1271 | jmp short ExLMSW | ||
| 1272 | CkSrcDX: | ||
| 1273 | cmp bh, 2 | ||
| 1274 | jne CkSrcSP | ||
| 1275 | mov ax, [bp.PIF_DX] ; src was DX, get from stack | ||
| 1276 | jmp short ExLMSW | ||
| 1277 | CkSrcSP: | ||
| 1278 | cmp bh, 4 | ||
| 1279 | jne GetReg | ||
| 1280 | mov ax, [bp.PIF_VMESP] ; src was SP, get from stack | ||
| 1281 | jmp short ExLMSW | ||
| 1282 | GetReg: | ||
| 1283 | or bh, 0C0h ; set register to register move bits | ||
| 1284 | mov es:[Lmod], bh ; setup move from client's src register | ||
| 1285 | jmp short GetRn ; clear prefetch so that bh gets there | ||
| 1286 | GetRn: | ||
| 1287 | ; Execute MOV AX, Rn | ||
| 1288 | db 08Bh | ||
| 1289 | Lmod db 0C0h | ||
| 1290 | |||
| 1291 | ; Finally Execute the LMSW | ||
| 1292 | ExLMSW: | ||
| 1293 | |||
| 1294 | ; At this point we could check for the PE bit and notify the user that | ||
| 1295 | ; he must switch to real mode... but because an old app might do a SMSW, | ||
| 1296 | ; which copies the PE bit (?!!), then set a bit in that image and do a LMSW, | ||
| 1297 | ; (not caring about the PE bit), we just let it go... under the assumption | ||
| 1298 | ; that if he really were trying to enter Protected mode, he would have | ||
| 1299 | ; failed trying to LIDT and LGDT. | ||
| 1300 | |||
| 1301 | ; test ax, 0001h ; Is client trying to set PE bit | ||
| 1302 | ; jnz ExitPIer ; Y: jump to error | ||
| 1303 | or ax, 0001h ; N: we want to stay in Prot mode | ||
| 1304 | LMSW ax ; So we must set it (use BTS above) | ||
| 1305 | |||
| 1306 | pop bp | ||
| 1307 | pop es | ||
| 1308 | assume es:DGROUP | ||
| 1309 | pop ax | ||
| 1310 | pop dx | ||
| 1311 | jmp EmExit ; *** RETURN *** to VM client | ||
| 1312 | |||
| 1313 | ExitPIer: | ||
| 1314 | pop es | ||
| 1315 | assume es:DGROUP | ||
| 1316 | mov ax, PrivErr ; privileged error | ||
| 1317 | call ErrHndlr ; If the user want's to continue | ||
| 1318 | pop ax | ||
| 1319 | pop dx | ||
| 1320 | jmp JumpReal ; we return and go unwind the stack | ||
| 1321 | Not_ProtIns1: | ||
| 1322 | jmp BadVmTrap | ||
| 1323 | |||
| 1324 | EmProtIns endp | ||
| 1325 | |||
| 1326 | ;****************************************************************************** | ||
| 1327 | ; EmMovCDTR - emulate the - MOV Rn, C/D/TRn & MOV C/D/TRn, Rn - instructions | ||
| 1328 | ; This is done by copying the MOV instruction from the VM to our | ||
| 1329 | ; code and then executing it. If CR0 is being stored, the PE | ||
| 1330 | ; bit is masked clear before completing the instruction. Execution speed | ||
| 1331 | ; should not be critical for these instructions, so I have lumped them | ||
| 1332 | ; all together to save memory that can be better used for more time | ||
| 1333 | ; critical emulations. | ||
| 1334 | ; NOTE: The Stack configuration is critical!!! If it is changed, the | ||
| 1335 | ; offsets to the register images must be updated accordingly. | ||
| 1336 | ; | ||
| 1337 | ; Also NOTE: The TR register opcodes have been removed from the legal 0F | ||
| 1338 | ; prefix list, (P0F_OpTab(x)), and the EmMovCDTR address removed from their | ||
| 1339 | ; opcode table ,(OpTable), vectors, so that they don't come here anymore. | ||
| 1340 | ; | ||
| 1341 | ; ENTRY: 386 Protected Mode | ||
| 1342 | ; EBP,EBX,ESI pushed on stack | ||
| 1343 | ; VM1_GSEL = VM client's stack segment | ||
| 1344 | ; VM2_GSEL = VM client's code segment | ||
| 1345 | ; DS:SI -> faulting opcode = nn (DS = VM2_GSEL) | ||
| 1346 | ; EXIT: via IRET to VM client | ||
| 1347 | ; bp.VTFOE+VMTF_EIP points beyond offender to next client instruction | ||
| 1348 | ; USED: | ||
| 1349 | ; STACK: n/a | ||
| 1350 | ;------------------------------------------------------------------------------ | ||
| 1351 | EmMovCDTR proc near | ||
| 1352 | |||
| 1353 | test ES:[PrefixFlag],P0F_FLAG | ||
| 1354 | jnz MovCDTR1 | ||
| 1355 | jmp Not_MovCDTR ; Didn't come from a 0F prefix | ||
| 1356 | MovCDTR1: | ||
| 1357 | PUSH_EAX | ||
| 1358 | push es | ||
| 1359 | mov bx,VDMCA_GSEL ; Load CODE (writeable) alias | ||
| 1360 | mov es, bx | ||
| 1361 | assume es:_TEXT | ||
| 1362 | mov bl,[si] ; BL = opcode | ||
| 1363 | mov es:[CDTRopc], bl | ||
| 1364 | inc si ; set SI past the opcode | ||
| 1365 | mov bl,[si] ; BL = modR/M | ||
| 1366 | mov bh, bl ; Copy modR/M | ||
| 1367 | and bl, 0F8h ; For control, we reroute move thru AX | ||
| 1368 | mov es:[CDTRmod], bl | ||
| 1369 | inc si ; set SI past the modR/M | ||
| 1370 | mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI | ||
| 1371 | |||
| 1372 | push bp | ||
| 1373 | mov bp, sp | ||
| 1374 | |||
| 1375 | ; Now the Stack had better look like MOV_CDTR_FRAME. (vm386.inc) | ||
| 1376 | |||
| 1377 | mov bl, es:[CDTRopc] ; load opcode | ||
| 1378 | cmp bl, 024h ; Check TRn load/store | ||
| 1379 | jb NotTRErr ; N: continue | ||
| 1380 | mov bx, ErrMovTR ; Y: go flag error | ||
| 1381 | jmp CTRErr | ||
| 1382 | |||
| 1383 | NotTRErr: | ||
| 1384 | and bh, 7 ; strip all but src reg bits | ||
| 1385 | cmp bh, 0 | ||
| 1386 | je ExCDTR ; reg is AX, so just do move | ||
| 1387 | |||
| 1388 | cmp bl, 020h ; Check CRn store | ||
| 1389 | je ExCDTR1 ; Y: go do it | ||
| 1390 | cmp bl, 021h ; Check DRn store | ||
| 1391 | je ExCDTR1 ; Y: go do it | ||
| 1392 | |||
| 1393 | ChkSrcBX: | ||
| 1394 | cmp bh, 3 | ||
| 1395 | jne ChkSrcBP | ||
| 1396 | OP32 | ||
| 1397 | mov ax, [bp.MCF_EBX] ; mov EBX from stack | ||
| 1398 | jmp short ExCDTR | ||
| 1399 | ChkSrcBP: | ||
| 1400 | cmp bh, 5 | ||
| 1401 | jne ChkSrcSI | ||
| 1402 | OP32 | ||
| 1403 | mov ax, [bp.MCF_EBP] ; mov EBP from stack | ||
| 1404 | jmp short ExCDTR | ||
| 1405 | ChkSrcSI: | ||
| 1406 | cmp bh, 6 | ||
| 1407 | jne ChkSrcSP | ||
| 1408 | OP32 | ||
| 1409 | mov ax, [bp.MCF_ESI] ; mov ESI from stack | ||
| 1410 | jmp short ExCDTR | ||
| 1411 | ChkSrcSP: | ||
| 1412 | cmp bh, 4 | ||
| 1413 | jne GetFmReg | ||
| 1414 | OP32 | ||
| 1415 | mov ax, [bp.MCF_VMESP] ; mov ESP from stack | ||
| 1416 | jmp short ExCDTR | ||
| 1417 | GetFmReg: | ||
| 1418 | or bh, 0C0h ; set register to register move bits | ||
| 1419 | mov es:[CDTRreg], bh ; setup move from client's src register | ||
| 1420 | jmp short GetERn ; clear prefetch so that bh gets there | ||
| 1421 | GetERn: | ||
| 1422 | ; Execute MOV EAX, ERn | ||
| 1423 | OP32 | ||
| 1424 | db 08Bh | ||
| 1425 | CDTRreg db 0C0h | ||
| 1426 | |||
| 1427 | ExCDTR: | ||
| 1428 | cmp bl, 022h ; Check CRn load | ||
| 1429 | jne FltrDRL3 ; N: destination not CRn | ||
| 1430 | cmp byte ptr es:[CDTRmod], 0C0h ; Check for CR0 load | ||
| 1431 | je CR0FltrL ; Y: filter it | ||
| 1432 | mov bx, ErrMovCR | ||
| 1433 | jmp CTRErr ; N: go tell user he did a NoNo | ||
| 1434 | FltrDRL3: | ||
| 1435 | cmp byte ptr es:[CDTRmod], 0C3h ; Check for DR0-3 load | ||
| 1436 | ja FltrGDbit ; N: continue | ||
| 1437 | call MapLinear ; Y: convert address to our paging | ||
| 1438 | jmp short ExCDTR1 ; linear map, then continue | ||
| 1439 | FltrGDbit: | ||
| 1440 | cmp byte ptr es:[CDTRmod], 0C7h ; Check for DR7 load | ||
| 1441 | jne ExCDTR1 ; N: continue | ||
| 1442 | and ax, 0DFFFh ; Y: don't let client set the GD bit | ||
| 1443 | jmp short ExCDTR1 ; continue | ||
| 1444 | |||
| 1445 | ; For the reason below, we don't bug the user about setting the PE bit | ||
| 1446 | ; through LMSW. To be consistent, and because the client would die | ||
| 1447 | ; in his attmept to LGDT or Mov CR3,Reg before this, we let him go here | ||
| 1448 | ; also. | ||
| 1449 | ; LMSW Reason: | ||
| 1450 | ; At this point we could check for the PE bit and notify the user that | ||
| 1451 | ; he must switch to real mode... but because an old app might do a SMSW, | ||
| 1452 | ; which copies the PE bit (?!!), then set a bit in that image and do a LMSW, | ||
| 1453 | ; (not caring about the PE bit), we just let it go... under the assumption | ||
| 1454 | ; that if he really were trying to enter Protected mode, he would have | ||
| 1455 | ; failed trying to LIDT and LGDT. | ||
| 1456 | |||
| 1457 | CR0FltrL: | ||
| 1458 | ; OP32 | ||
| 1459 | ; test AX, 0FFFEh ; Is Client trying to set the | ||
| 1460 | ; dw 7FFFh ; PE bit or the PG bit? | ||
| 1461 | ; jnz ExitxCRer ; Y: go tell him he can't | ||
| 1462 | OP32 | ||
| 1463 | or AX, 0001h ; set PE bit | ||
| 1464 | dw 8000h ; and PG bit if they weren't | ||
| 1465 | ExCDTR1: | ||
| 1466 | ; Execute MOV CDTRn, EAX (Finally!) | ||
| 1467 | db 0Fh | ||
| 1468 | CDTRopc db 020h | ||
| 1469 | CDTRmod db 0C0h | ||
| 1470 | |||
| 1471 | ; The special register move has now been executed, but we altered it to | ||
| 1472 | ; use AX. If the move was a load, we are done. If it was a store to one of | ||
| 1473 | ; the registers on the stack, we need to stuff the register's stack image, | ||
| 1474 | ; otherwise we need to move AX to the proper register. | ||
| 1475 | |||
| 1476 | cmp bl, 022h ; Check CRn load | ||
| 1477 | je Exit_MovCDTR ; Y: we're done | ||
| 1478 | cmp bl, 023h ; Check DRn load | ||
| 1479 | je Exit_MovCDTR ; Y: we're done | ||
| 1480 | cmp bl, 021h ; Check DRn store | ||
| 1481 | je FltrDRS3 ; Y: go filter it | ||
| 1482 | jmp short NotDRS3 | ||
| 1483 | FltrDRS3: | ||
| 1484 | cmp byte ptr es:[CDTRmod], 0C3h ; Check for DR0-3 load | ||
| 1485 | ja NotDRS3 ; N: continue | ||
| 1486 | call UnMapLinear ; Y: convert address from our paging | ||
| 1487 | ; linear map, then continue | ||
| 1488 | NotDRS3: | ||
| 1489 | cmp bl, 020h ; Check CRn store | ||
| 1490 | jne ChkDstBX ; N: source not CRn | ||
| 1491 | cmp byte ptr es:[CDTRmod], 0C0h ; Check for CR0 store | ||
| 1492 | je CR0FltrS ; Y: filter it | ||
| 1493 | mov bx, ErrMovCR | ||
| 1494 | jmp short CTRErr ; N: go tell user he did a NoNo | ||
| 1495 | |||
| 1496 | ; Because SMSW shows the PE bit, we let it go through here also | ||
| 1497 | CR0FltrS: | ||
| 1498 | OP32 | ||
| 1499 | and AX, 0FFFFh ; Y: clear | ||
| 1500 | dw 7FFFh ; PG bit if it was set | ||
| 1501 | ChkDstBX: | ||
| 1502 | cmp bh, 3 | ||
| 1503 | jne ChkDstBP | ||
| 1504 | OP32 | ||
| 1505 | mov [bp.MCF_EBX], ax ; mov EBX to stack | ||
| 1506 | jmp short Exit_MovCDTR | ||
| 1507 | ChkDstBP: | ||
| 1508 | cmp bh, 5 | ||
| 1509 | jne ChkDstSI | ||
| 1510 | OP32 | ||
| 1511 | mov [bp.MCF_EBP], ax ; mov EBP to stack | ||
| 1512 | jmp short Exit_MovCDTR | ||
| 1513 | ChkDstSI: | ||
| 1514 | cmp bh, 6 | ||
| 1515 | jne ChkDstAX | ||
| 1516 | OP32 | ||
| 1517 | mov [bp.MCF_ESI], ax ; mov ESI to stack | ||
| 1518 | jmp short Exit_MovCDTR | ||
| 1519 | ChkDstAX: | ||
| 1520 | cmp bh, 0 | ||
| 1521 | jne ChkDstSP | ||
| 1522 | OP32 | ||
| 1523 | mov [bp.MCF_EAX], ax ; mov EAX to stack | ||
| 1524 | jmp short Exit_MovCDTR ; at exit | ||
| 1525 | ChkDstSP: | ||
| 1526 | cmp bh, 4 | ||
| 1527 | jne PutInReg | ||
| 1528 | OP32 | ||
| 1529 | mov [bp.MCF_VMESP], ax ; mov ESP to stack | ||
| 1530 | jmp short Exit_MovCDTR ; at exit | ||
| 1531 | PutInReg: | ||
| 1532 | ; Execute MOV ERn, EAX | ||
| 1533 | or bh, 0C0h ; set register to register move bits | ||
| 1534 | mov es:[regCDTR], bh ; setup load to client's dest register | ||
| 1535 | jmp short PutERn ; clear prefetch so that bh gets there | ||
| 1536 | PutERn: | ||
| 1537 | db 66h | ||
| 1538 | db 089h | ||
| 1539 | regCDTR db 0C0h | ||
| 1540 | |||
| 1541 | |||
| 1542 | Exit_MovCDTR: | ||
| 1543 | pop bp | ||
| 1544 | pop es | ||
| 1545 | assume es:DGROUP | ||
| 1546 | POP_EAX | ||
| 1547 | jmp EmExit ; *** RETURN *** to VM client | ||
| 1548 | CTRErr: | ||
| 1549 | mov ax, PrivErr | ||
| 1550 | pop bp | ||
| 1551 | sub [bp.VTFOE+VMTF_EIP],3 ; VM CS:IP = faulting instruction | ||
| 1552 | pop es | ||
| 1553 | assume es:DGROUP | ||
| 1554 | call ErrHndlr ; If we return here, the user wants to | ||
| 1555 | POP_EAX ; continue in real mode... so go unwind | ||
| 1556 | jmp JumpReal ; the stack and let him continue | ||
| 1557 | Not_MovCDTR: | ||
| 1558 | jmp BadVmTrap | ||
| 1559 | |||
| 1560 | EmMovCDTR endp | ||
| 1561 | |||
| 1562 | ;****************************************************************************** | ||
| 1563 | ;*** EmLOCK - Emulate LOCK prefix | ||
| 1564 | ; | ||
| 1565 | ; This routine is entered if a faulting instruction | ||
| 1566 | ; is a LOCK prefix. | ||
| 1567 | ; | ||
| 1568 | ; ENTRY 386 PROTECTED MODE | ||
| 1569 | ; see common description at top | ||
| 1570 | ; | ||
| 1571 | ; EXIT xfer on to handler for next opcode | ||
| 1572 | ; | ||
| 1573 | EmLOCK proc near | ||
| 1574 | |||
| 1575 | ; 6/15 - Probably should jump to VmInsHandle rather than EmExit to handle a | ||
| 1576 | ; a lock prefix on some other offending instruction. In that case you would | ||
| 1577 | ; have: | ||
| 1578 | ;; or ES:[PrefixFlag],LOCK_FLAG ; set appropriate flag | ||
| 1579 | ;; inc si ; inc VM CS:IP past prefix | ||
| 1580 | ;; jmp VmInsHandle ; and go process offender | ||
| 1581 | ; rather than: | ||
| 1582 | inc si ; set IP past the | ||
| 1583 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 1584 | jmp EmExit ; and leave | ||
| 1585 | |||
| 1586 | EmLOCK endp | ||
| 1587 | |||
| 1588 | ;****************************************************************************** | ||
| 1589 | ;*** EmREPNE - handle REPNE prefix | ||
| 1590 | ; | ||
| 1591 | ; We come here if the trapping instruction has | ||
| 1592 | ; a REPNE prefix. We just pass it on to the handler | ||
| 1593 | ; for the next opcode. | ||
| 1594 | ; | ||
| 1595 | ; ENTRY 386 PROTECTED MODE | ||
| 1596 | ; see common description at top | ||
| 1597 | ; | ||
| 1598 | ; EXIT IRET back to VM program | ||
| 1599 | ; | ||
| 1600 | EmREPNE proc near | ||
| 1601 | |||
| 1602 | or ES:[PrefixFlag],REPNE_FLAG ; set appropriate flag | ||
| 1603 | inc si ; inc VM CS:IP past prefix | ||
| 1604 | jmp VmInsHandle ; handle next part of instr | ||
| 1605 | |||
| 1606 | EmREPNE endp | ||
| 1607 | |||
| 1608 | ;*** EmREP - handle REP prefix | ||
| 1609 | ; | ||
| 1610 | ; We come here if the trapping instruction has | ||
| 1611 | ; a REP or REPE prefix. We just pass it on to the handler | ||
| 1612 | ; for the next opcode. | ||
| 1613 | ; | ||
| 1614 | ; ENTRY 386 PROTECTED MODE | ||
| 1615 | ; see common description at top | ||
| 1616 | ; | ||
| 1617 | ; EXIT IRET back to VM program | ||
| 1618 | ; | ||
| 1619 | EmREP proc near | ||
| 1620 | |||
| 1621 | or ES:[PrefixFlag],REP_FLAG ; set appropriate flag | ||
| 1622 | inc si ; inc VM CS:IP past prefix | ||
| 1623 | jmp VmInsHandle ; handle next part of instr | ||
| 1624 | |||
| 1625 | EmREP endp | ||
| 1626 | |||
| 1627 | ;****************************************************************************** | ||
| 1628 | ;*** Prefix_0F - handle 0F overrides | ||
| 1629 | ; | ||
| 1630 | ; This routine is entered if an instruction begins with a 0F prefix. | ||
| 1631 | ; It checks the current opcode against a table of valid 0F-opcodes, | ||
| 1632 | ; and if the opcode is valid, it indexes back into OpTable to jump | ||
| 1633 | ; to the proper opcode handler. | ||
| 1634 | ; (NOTE: This scheme works fine as long as the valid 0F-opcodes | ||
| 1635 | ; continue to have low values allowing this P0F_OpTabx to stay | ||
| 1636 | ; relatively small. If this changes, we probably should go back | ||
| 1637 | ; to using the P0F_OpTab scheme.) | ||
| 1638 | ; | ||
| 1639 | ; ENTRY: 386 Protected Mode | ||
| 1640 | ; EBP,EBX,ESI pushed on stack | ||
| 1641 | ; VM1_GSEL = VM client's stack segment | ||
| 1642 | ; VM2_GSEL = VM client's code segment | ||
| 1643 | ; DS:SI -> faulting prefix = nn (DS = VM2_GSEL) | ||
| 1644 | ; EXIT xfer directly to handler for next opcode | ||
| 1645 | ; | ||
| 1646 | ;*** | ||
| 1647 | P0F_Invalid equ 0FFh ; OpTable vector offset to BadVmTrap | ||
| 1648 | |||
| 1649 | P0F_OpTabx label byte | ||
| 1650 | db 00h ; 00h - LLDT, LTR, SLDT, STR, VERR, VERW | ||
| 1651 | db 02h ; 01h - LIDT, LGDT, LMSW | ||
| 1652 | db 04h ; 02h - LAR | ||
| 1653 | db 06h ; 03h - LSL | ||
| 1654 | db P0F_Invalid ; 04h - BadVmTrap | ||
| 1655 | db 0Ah ; 05h - 286 Loadall | ||
| 1656 | db 0Ch ; 06h - CLTS | ||
| 1657 | db 0Eh ; 07h - 386 Loadall | ||
| 1658 | db P0F_Invalid ; 08h - BadVmTrap | ||
| 1659 | db P0F_Invalid ; 09h - BadVmTrap | ||
| 1660 | db P0F_Invalid ; 0Ah - BadVmTrap | ||
| 1661 | db P0F_Invalid ; 0Bh - BadVmTrap | ||
| 1662 | db P0F_Invalid ; 0Ch - BadVmTrap | ||
| 1663 | db P0F_Invalid ; 0Dh - BadVmTrap | ||
| 1664 | db P0F_Invalid ; 0Eh - BadVmTrap | ||
| 1665 | db P0F_Invalid ; 0Fh - BadVmTrap | ||
| 1666 | db P0F_Invalid ; 10h - BadVmTrap | ||
| 1667 | db P0F_Invalid ; 11h - BadVmTrap | ||
| 1668 | db P0F_Invalid ; 12h - BadVmTrap | ||
| 1669 | db P0F_Invalid ; 13h - BadVmTrap | ||
| 1670 | db P0F_Invalid ; 14h - BadVmTrap | ||
| 1671 | db P0F_Invalid ; 15h - BadVmTrap | ||
| 1672 | db P0F_Invalid ; 16h - BadVmTrap | ||
| 1673 | db P0F_Invalid ; 17h - BadVmTrap | ||
| 1674 | db P0F_Invalid ; 18h - BadVmTrap | ||
| 1675 | db P0F_Invalid ; 19h - BadVmTrap | ||
| 1676 | db P0F_Invalid ; 1Ah - BadVmTrap | ||
| 1677 | db P0F_Invalid ; 1Bh - BadVmTrap | ||
| 1678 | db P0F_Invalid ; 1Ch - BadVmTrap | ||
| 1679 | db P0F_Invalid ; 1Dh - BadVmTrap | ||
| 1680 | db P0F_Invalid ; 1Eh - BadVmTrap | ||
| 1681 | db P0F_Invalid ; 1Fh - BadVmTrap | ||
| 1682 | db 40h ; 20h - CR moves | ||
| 1683 | db 42h ; 21h - DR moves | ||
| 1684 | db 44h ; 22h - CR moves | ||
| 1685 | db 46h ; 23h - DR moves | ||
| 1686 | db 48h ; 24h - TR moves | ||
| 1687 | db P0F_Invalid ; 25h - BadVmTrap | ||
| 1688 | db 4Ch ; 26h - TR moves | ||
| 1689 | P0F_OpTabx_Size equ $-P0F_OpTabx | ||
| 1690 | |||
| 1691 | ;*** | ||
| 1692 | Prefix_0F proc near | ||
| 1693 | inc si ; inc DS:SI past prefix | ||
| 1694 | mov bl,[si] ; BL = opcode | ||
| 1695 | cmp bl, P0F_OpTabx_Size | ||
| 1696 | jae Bad_0F | ||
| 1697 | mov bh,0 ; BX = opcode | ||
| 1698 | mov bl, cs:P0F_OpTabx[bx] | ||
| 1699 | cmp bl, P0F_Invalid | ||
| 1700 | je Bad_0F | ||
| 1701 | or es:[PrefixFlag],P0F_FLAG ; set appropriate flag | ||
| 1702 | jmp cs:OpTable[bx] ; enter instr emulation routine | ||
| 1703 | |||
| 1704 | Bad_0F: | ||
| 1705 | jmp BadVmTrap | ||
| 1706 | |||
| 1707 | Prefix_0F endp | ||
| 1708 | |||
| 1709 | ;****************************************************************************** | ||
| 1710 | ;*** CSOverride - handle CS overrides | ||
| 1711 | ; | ||
| 1712 | ; This routine is entered if a faulting instruction | ||
| 1713 | ; has a CS override. | ||
| 1714 | ; | ||
| 1715 | ; ENTRY 386 PROTECTED MODE | ||
| 1716 | ; see common description at top | ||
| 1717 | ; | ||
| 1718 | ; EXIT xfer on to handler for next opcode | ||
| 1719 | ; | ||
| 1720 | CSOverride proc near | ||
| 1721 | |||
| 1722 | or ES:[PrefixFlag],CS_FLAG ; set appropriate flag | ||
| 1723 | inc si ; inc VM CS:IP past prefix | ||
| 1724 | jmp VmInsHandle ; handle next part of instr | ||
| 1725 | |||
| 1726 | CSOverride endp | ||
| 1727 | |||
| 1728 | ;****************************************************************************** | ||
| 1729 | ;*** DSOverride - handle DS overrides | ||
| 1730 | ; | ||
| 1731 | ; This routine is entered if a faulting instruction | ||
| 1732 | ; has a DS override. | ||
| 1733 | ; | ||
| 1734 | ; ENTRY 386 PROTECTED MODE | ||
| 1735 | ; see common description at top | ||
| 1736 | ; | ||
| 1737 | ; EXIT xfer on to handler for next opcode | ||
| 1738 | ; | ||
| 1739 | DSOverride proc near | ||
| 1740 | |||
| 1741 | or ES:[PrefixFlag],DS_FLAG ; set appropriate flag | ||
| 1742 | inc si ; inc VM CS:IP past prefix | ||
| 1743 | jmp VmInsHandle ; handle next part of instr | ||
| 1744 | |||
| 1745 | DSOverride endp | ||
| 1746 | |||
| 1747 | ;****************************************************************************** | ||
| 1748 | ;*** ESOverride - handle ES overrides | ||
| 1749 | ; | ||
| 1750 | ; This routine is entered if a faulting instruction | ||
| 1751 | ; has a ES override or a MOV TRn, Rn opcode | ||
| 1752 | ; | ||
| 1753 | ; ENTRY 386 PROTECTED MODE | ||
| 1754 | ; see common description at top | ||
| 1755 | ; | ||
| 1756 | ; EXIT xfer on to handler for next opcode | ||
| 1757 | ; | ||
| 1758 | |||
| 1759 | ESOverride proc near | ||
| 1760 | |||
| 1761 | test ES:[PrefixFlag],P0F_FLAG ; only for TR emulation | ||
| 1762 | jz ESO1 ; only for TR emulation | ||
| 1763 | jmp EmMovCDTR ; only for TR emulation | ||
| 1764 | ESO1: | ||
| 1765 | or ES:[PrefixFlag],ES_FLAG ; set appropriate flag | ||
| 1766 | inc si ; inc VM CS:IP past prefix | ||
| 1767 | jmp VmInsHandle ; handle next part of instr | ||
| 1768 | |||
| 1769 | ESOverride endp | ||
| 1770 | |||
| 1771 | ;****************************************************************************** | ||
| 1772 | ;*** SSOverride - handle SS overrides | ||
| 1773 | ; | ||
| 1774 | ; This routine is entered if a faulting instruction | ||
| 1775 | ; has a SS override. | ||
| 1776 | ; | ||
| 1777 | ; ENTRY 386 PROTECTED MODE | ||
| 1778 | ; see common description at top | ||
| 1779 | ; | ||
| 1780 | ; EXIT xfer on to handler for next opcode | ||
| 1781 | ; | ||
| 1782 | |||
| 1783 | SSOverride proc near | ||
| 1784 | |||
| 1785 | or ES:[PrefixFlag],SS_FLAG ; set appropriate flag | ||
| 1786 | ;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix | ||
| 1787 | inc si ; inc VM CS:IP past prefix | ||
| 1788 | jmp VmInsHandle ; handle next part of instr | ||
| 1789 | |||
| 1790 | SSOverride endp | ||
| 1791 | |||
| 1792 | ;****************************************************************************** | ||
| 1793 | ;*** FSOverride - handle FS overrides | ||
| 1794 | ; | ||
| 1795 | ; This routine is entered if a faulting instruction | ||
| 1796 | ; has a FS override. | ||
| 1797 | ; | ||
| 1798 | ; ENTRY 386 PROTECTED MODE | ||
| 1799 | ; see common description at top | ||
| 1800 | ; | ||
| 1801 | ; EXIT xfer on to handler for next opcode | ||
| 1802 | ; | ||
| 1803 | |||
| 1804 | FSOverride proc near | ||
| 1805 | |||
| 1806 | or ES:[PrefixFlag],FS_FLAG ; set appropriate flag | ||
| 1807 | ;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix | ||
| 1808 | inc si ; inc VM CS:IP past prefix | ||
| 1809 | jmp VmInsHandle ; handle next part of instr | ||
| 1810 | |||
| 1811 | FSOverride endp | ||
| 1812 | |||
| 1813 | ;****************************************************************************** | ||
| 1814 | ;*** GSOverride - handle GS overrides | ||
| 1815 | ; | ||
| 1816 | ; This routine is entered if a faulting instruction | ||
| 1817 | ; has a GS override. | ||
| 1818 | ; | ||
| 1819 | ; ENTRY 386 PROTECTED MODE | ||
| 1820 | ; see common description at top | ||
| 1821 | ; | ||
| 1822 | ; EXIT xfer on to handler for next opcode | ||
| 1823 | ; | ||
| 1824 | |||
| 1825 | GSOverride proc near | ||
| 1826 | |||
| 1827 | or ES:[PrefixFlag],GS_FLAG ; set appropriate flag | ||
| 1828 | ;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix | ||
| 1829 | inc si ; inc VM CS:IP past prefix | ||
| 1830 | jmp VmInsHandle ; handle next part of instr | ||
| 1831 | |||
| 1832 | GSOverride endp | ||
| 1833 | |||
| 1834 | ;****************************************************************************** | ||
| 1835 | ;*** EmINSB - emulate IN byte string | ||
| 1836 | ; | ||
| 1837 | ; This routine emulates the IN byte string instruction | ||
| 1838 | ; *** this routine emulates REP instructions entirely *** | ||
| 1839 | ; *** within protected mode. This effectively masks out *** | ||
| 1840 | ; *** interupts between bytes in the operation, even *** | ||
| 1841 | ; *** if the VM code had interrupts on. *** | ||
| 1842 | ; | ||
| 1843 | ; ENTRY 386 PROTECTED MODE | ||
| 1844 | ; see common description at top | ||
| 1845 | ; | ||
| 1846 | ; EXIT IRET back to VM program | ||
| 1847 | ; | ||
| 1848 | ; USES ES,BX,DI | ||
| 1849 | ; | ||
| 1850 | |||
| 1851 | EmINSB proc near | ||
| 1852 | ; | ||
| 1853 | ;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate | ||
| 1854 | inc si ; set IP past the | ||
| 1855 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 1856 | ; | ||
| 1857 | ; | ||
| 1858 | ; Build a selector (VM1_GSEL) to client's ES segment. VM1_GSEL is already set | ||
| 1859 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 1860 | ; | ||
| 1861 | mov bx,GDTD_GSEL | ||
| 1862 | mov ds,bx ; DS = GDT selector | ||
| 1863 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (segment form) | ||
| 1864 | shl bx,4 ; BX = low 16 bits of base | ||
| 1865 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 1866 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (again) | ||
| 1867 | shr bx,4 ; BH = high 8 bits of base | ||
| 1868 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 1869 | mov bx,VM1_GSEL | ||
| 1870 | test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ? | ||
| 1871 | mov es,bx ; ES = VM ES | ||
| 1872 | jnz EINSB_loop ; Y: go do rep instruction | ||
| 1873 | insb ; N: do single instruction | ||
| 1874 | jmp EINSB_exit ; and leave | ||
| 1875 | EINSB_loop: | ||
| 1876 | cld ; assume cld | ||
| 1877 | mov bx,DF_FLAG | ||
| 1878 | test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD? | ||
| 1879 | jz EINSB_rep ; Y: go ahead | ||
| 1880 | std ; N: set it | ||
| 1881 | EINSB_rep: | ||
| 1882 | rep insb ; rep version | ||
| 1883 | |||
| 1884 | EINSB_Exit: ; | ||
| 1885 | jmp EmExit ; *** RETURN *** to VM client | ||
| 1886 | ; | ||
| 1887 | EmINSB endp | ||
| 1888 | |||
| 1889 | |||
| 1890 | ;****************************************************************************** | ||
| 1891 | ;*** EmINSW - emulate IN word string | ||
| 1892 | ; | ||
| 1893 | ; This routine emulates the IN word string instruction | ||
| 1894 | ; *** this routine emulates REP instructions entirely *** | ||
| 1895 | ; *** within protected mode. This effectively masks out *** | ||
| 1896 | ; *** interupts between bytes in the operation, even *** | ||
| 1897 | ; *** if the VM code had interrupts on. *** | ||
| 1898 | ; | ||
| 1899 | ; ENTRY 386 PROTECTED MODE | ||
| 1900 | ; see common description at top | ||
| 1901 | ; | ||
| 1902 | ; EXIT IRET back to VM program | ||
| 1903 | ; | ||
| 1904 | ; USES ES,BX,DI | ||
| 1905 | ; | ||
| 1906 | |||
| 1907 | EmINSW proc near | ||
| 1908 | ; | ||
| 1909 | ;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate | ||
| 1910 | inc si ; set IP past the | ||
| 1911 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 1912 | ; | ||
| 1913 | ; | ||
| 1914 | ; | ||
| 1915 | ; Build a selector (VM1_GSEL) to client's ES segment. VM1_GSEL is already set | ||
| 1916 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 1917 | ; | ||
| 1918 | mov bx,GDTD_GSEL | ||
| 1919 | mov ds,bx ; DS = GDT selector | ||
| 1920 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (segment form) | ||
| 1921 | shl bx,4 ; BX = low 16 bits of base | ||
| 1922 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 1923 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (again) | ||
| 1924 | shr bx,4 ; BH = high 8 bits of base | ||
| 1925 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 1926 | mov bx,VM1_GSEL | ||
| 1927 | test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ? | ||
| 1928 | mov es,bx ; ES = VM ES | ||
| 1929 | jnz EINSW_loop ; Y: go do rep instruction | ||
| 1930 | insw ; N: do single instruction | ||
| 1931 | jmp EINSW_exit ; and leave | ||
| 1932 | EINSW_loop: | ||
| 1933 | cld ; assume cld | ||
| 1934 | mov bx,DF_FLAG | ||
| 1935 | test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD? | ||
| 1936 | jz EINSW_rep ; Y: go ahead | ||
| 1937 | std ; N: set it | ||
| 1938 | EINSW_rep: | ||
| 1939 | rep insw ; rep version | ||
| 1940 | |||
| 1941 | EINSW_Exit: ; | ||
| 1942 | jmp EmExit ; *** RETURN *** to VM client | ||
| 1943 | ; | ||
| 1944 | EmINSW endp | ||
| 1945 | |||
| 1946 | |||
| 1947 | ;****************************************************************************** | ||
| 1948 | ;*** EmOUTSB - emulate OUT byte string | ||
| 1949 | ; | ||
| 1950 | ; This routine emulates the OUT byte string instruction | ||
| 1951 | ; *** this routine emulates REP instructions entirely *** | ||
| 1952 | ; *** within protected mode. This effectively masks out *** | ||
| 1953 | ; *** interupts between bytes in the operation, even *** | ||
| 1954 | ; *** if the VM code had interrupts on. *** | ||
| 1955 | ; | ||
| 1956 | ; ENTRY 386 PROTECTED MODE | ||
| 1957 | ; see common description at top | ||
| 1958 | ; | ||
| 1959 | ; EXIT IRET back to VM program | ||
| 1960 | ; | ||
| 1961 | ; USES DS,BX,SI | ||
| 1962 | ; | ||
| 1963 | |||
| 1964 | EmOUTSB proc near | ||
| 1965 | ; | ||
| 1966 | ;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate | ||
| 1967 | inc si ; set IP past the | ||
| 1968 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 1969 | ; | ||
| 1970 | ; restore SI | ||
| 1971 | ; | ||
| 1972 | pop si | ||
| 1973 | push si | ||
| 1974 | ; | ||
| 1975 | ; Build a selector (VM1_GSEL) to client's DS segment. VM1_GSEL is already set | ||
| 1976 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 1977 | ; | ||
| 1978 | mov bx,GDTD_GSEL | ||
| 1979 | mov ds,bx ; DS = GDT selector | ||
| 1980 | mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (segment form) | ||
| 1981 | shl bx,4 ; BX = low 16 bits of base | ||
| 1982 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 1983 | mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (again) | ||
| 1984 | shr bx,4 ; BH = high 8 bits of base | ||
| 1985 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 1986 | mov bx,VM1_GSEL | ||
| 1987 | mov ds,bx ; DS = VM DS | ||
| 1988 | |||
| 1989 | test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ? | ||
| 1990 | jnz EOUTSB_loop ; Y: go do rep instruction | ||
| 1991 | outsb ; N: do single instruction | ||
| 1992 | jmp EOUTSB_exit ; and leave | ||
| 1993 | EOUTSB_loop: | ||
| 1994 | cld ; assume cld | ||
| 1995 | mov bx,DF_FLAG | ||
| 1996 | test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD? | ||
| 1997 | jz EOUTSB_rep ; Y: go ahead | ||
| 1998 | std ; N: set it | ||
| 1999 | EOUTSB_rep: | ||
| 2000 | rep outsb ; rep version | ||
| 2001 | |||
| 2002 | EOUTSB_Exit: ; | ||
| 2003 | jmp EmExit ; *** RETURN *** to VM client | ||
| 2004 | ; | ||
| 2005 | EmOUTSB endp | ||
| 2006 | |||
| 2007 | |||
| 2008 | ;****************************************************************************** | ||
| 2009 | ;*** EmOUTSW - emulate OUT word string | ||
| 2010 | ; | ||
| 2011 | ; This routine emulates the OUT word string instruction | ||
| 2012 | ; *** this routine emulates REP instructions entirely *** | ||
| 2013 | ; *** within protected mode. This effectively masks out *** | ||
| 2014 | ; *** interupts between bytes in the operation, even *** | ||
| 2015 | ; *** if the VM code had interrupts on. *** | ||
| 2016 | ; | ||
| 2017 | ; ENTRY 386 PROTECTED MODE | ||
| 2018 | ; see common description at top | ||
| 2019 | ; | ||
| 2020 | ; EXIT IRET back to VM program | ||
| 2021 | ; | ||
| 2022 | ; USES DS,BX,SI | ||
| 2023 | ; | ||
| 2024 | |||
| 2025 | EmOUTSW proc near | ||
| 2026 | ; | ||
| 2027 | ;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate | ||
| 2028 | inc si ; set IP past the | ||
| 2029 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 2030 | ; | ||
| 2031 | ; restore SI | ||
| 2032 | ; | ||
| 2033 | pop si | ||
| 2034 | push si | ||
| 2035 | ; | ||
| 2036 | ; | ||
| 2037 | ; Build a selector (VM1_GSEL) to client's DS segment. VM1_GSEL is already set | ||
| 2038 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 2039 | ; | ||
| 2040 | mov bx,GDTD_GSEL | ||
| 2041 | mov ds,bx ; DS = GDT selector | ||
| 2042 | mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (segment form) | ||
| 2043 | shl bx,4 ; BX = low 16 bits of base | ||
| 2044 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 2045 | mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (again) | ||
| 2046 | shr bx,4 ; BH = high 8 bits of base | ||
| 2047 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 2048 | mov bx,VM1_GSEL | ||
| 2049 | mov ds,bx ; DS = VM DS | ||
| 2050 | |||
| 2051 | test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ? | ||
| 2052 | jnz EOUTSW_loop ; Y: go do rep instruction | ||
| 2053 | outsw ; N: do single instruction | ||
| 2054 | jmp EOUTSW_exit ; and leave | ||
| 2055 | EOUTSW_loop: | ||
| 2056 | cld ; assume cld | ||
| 2057 | mov bx,DF_FLAG | ||
| 2058 | test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD? | ||
| 2059 | jz EOUTSW_rep ; Y: go ahead | ||
| 2060 | std ; N: set it | ||
| 2061 | EOUTSW_rep: | ||
| 2062 | rep outsw ; rep version | ||
| 2063 | |||
| 2064 | EOUTSW_Exit: ; | ||
| 2065 | jmp EmExit ; *** RETURN *** to VM client | ||
| 2066 | ; | ||
| 2067 | EmOUTSW endp | ||
| 2068 | |||
| 2069 | ;****************************************************************************** | ||
| 2070 | ;*** EmMOVSW - emulate MOV word string | ||
| 2071 | ; | ||
| 2072 | ; This routine emulates the MOV word string instruction | ||
| 2073 | ; specifically to handle the RASH Rules (Jokes) emulation. | ||
| 2074 | ; For now, the only reason for doing this is to allow a bug | ||
| 2075 | ; in PC Week's benchmark tests to FAIL "properly" so that the test | ||
| 2076 | ; works. (Unbelievable!) | ||
| 2077 | ; | ||
| 2078 | ; NOTE: After testing, if the ROM properly emulates the RASH | ||
| 2079 | ; requirements, this routine should be reduced to the Reflect6 | ||
| 2080 | ; function. | ||
| 2081 | ; | ||
| 2082 | ; ENTRY 386 PROTECTED MODE | ||
| 2083 | ; see common description at top | ||
| 2084 | ; | ||
| 2085 | ; EXIT IRET back to VM program | ||
| 2086 | ; | ||
| 2087 | ; USES DS,BX,SI | ||
| 2088 | ; | ||
| 2089 | EmMOVSW proc near | ||
| 2090 | mov bx, sp | ||
| 2091 | cmp di, 0FFFFh ; Q:Does either Di | ||
| 2092 | je EmWRASH | ||
| 2093 | cmp ss:[bx.GPF_ESI], 0FFFFh ; or SI = FFFF? | ||
| 2094 | je EmWRASH ; Y:Assume RASH GPfault | ||
| 2095 | Reflect6: | ||
| 2096 | mov es:[RefNum], 06h | ||
| 2097 | RefToROM: | ||
| 2098 | POP_ESI ; N: clean up the stack, | ||
| 2099 | POP_EBX | ||
| 2100 | POP_EBP | ||
| 2101 | add sp,4 ; throw away error code, | ||
| 2102 | PUSH_EBP | ||
| 2103 | mov bp,sp ; reset BP to stack frame | ||
| 2104 | push es:[RefNum] ; push the trap number | ||
| 2105 | jmp hw_int ; and, Reflect to ROM | ||
| 2106 | EmWRASH: | ||
| 2107 | test es:[PrefixFlag], REPS_FLAG ; Q:Is this a REP of REPNE? | ||
| 2108 | jz EMWCXok ; N: don't change CX | ||
| 2109 | inc cx | ||
| 2110 | EMWCXok: | ||
| 2111 | mov ax, 2 ; assume up counter | ||
| 2112 | test [bp.VTFOE+VMTF_EFLAGS], DF_FLAG | ||
| 2113 | jz EMWUpdtSI | ||
| 2114 | not ax | ||
| 2115 | EMWUpdtSI: | ||
| 2116 | mov si, ss:[bx.GPF_ESI] | ||
| 2117 | add ss:[bx.GPF_ESI], ax ; verify neg??? | ||
| 2118 | cmp si, 0FFFFh ; Q:Did SI cause the GP fault | ||
| 2119 | jne EMWUpdtDI ; N:Go fixup DI and CX | ||
| 2120 | jmp short EMW_Exit ; Y:We're done | ||
| 2121 | EMWUpdtDI: | ||
| 2122 | test es:[PrefixFlag], REPS_FLAG ; Q:Is this a REP of REPNE? | ||
| 2123 | jz EMWCXok2 ; N: don't change CX | ||
| 2124 | inc cx | ||
| 2125 | EMWCXok2: | ||
| 2126 | add di, ax ; verify neg??? | ||
| 2127 | EMW_Exit: | ||
| 2128 | jmp EmExit ; *** RETURN *** to VM client | ||
| 2129 | ; | ||
| 2130 | EmMOVSW endp | ||
| 2131 | |||
| 2132 | _TEXT ends | ||
| 2133 | |||
| 2134 | end | ||
| 2135 | |||
diff --git a/v4.0/src/MEMM/MEMM/VMTRAP.ASM b/v4.0/src/MEMM/MEMM/VMTRAP.ASM new file mode 100644 index 0000000..095ebef --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VMTRAP.ASM | |||
| @@ -0,0 +1,791 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title VMTRAP - 386 Virtual Mode interrupt handler routines | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: VMTRAP - 386 Virtual Mode interrupt handler routines | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: January 26, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------ | ||
| 26 | ; 01/26/86 Original | ||
| 27 | ; 02/05/86 A- Added int 15h trap to move block function. | ||
| 28 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 29 | ; 06/19/86 0.01 Added emul_reflect entry point for preserving | ||
| 30 | ; IF and TF flags bits on reflections done by | ||
| 31 | ; instruction emulators. | ||
| 32 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 33 | ; 07/20/88 Removed debugger codes (pc) | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ; | ||
| 37 | ; Functional Description: | ||
| 38 | ; | ||
| 39 | ; This module contains the interrupt and trap handlers for Virtual DOS. | ||
| 40 | ; | ||
| 41 | ; Note that a conscious decision has been made to attempt to field the | ||
| 42 | ; Master 8259 interrupts at the normal PC location (vectors 8 - F). The | ||
| 43 | ; main problem is that these overlap CPU exception vectors. While the | ||
| 44 | ; 8259 base vector address could be changed (there's lots of room in the | ||
| 45 | ; IDT, since we're fielding S/W INTs through GP 13), the primary reason | ||
| 46 | ; for not doing so is to avoid any potential trouble with an application | ||
| 47 | ; reprogramming the 8259. We don't know of any that do, and you could | ||
| 48 | ; trap them if they tried anyway. | ||
| 49 | ; | ||
| 50 | ; "to do:" marks potential holes/things to consider | ||
| 51 | ; | ||
| 52 | ;****************************************************************************** | ||
| 53 | .lfcond ; list false conditionals | ||
| 54 | .386p | ||
| 55 | page | ||
| 56 | ;****************************************************************************** | ||
| 57 | ; P U B L I C D E C L A R A T I O N S | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; | ||
| 60 | public VmTrap ; module label | ||
| 61 | |||
| 62 | public hw_int | ||
| 63 | public emul_reflect | ||
| 64 | |||
| 65 | public vm_trap00 | ||
| 66 | public vm_trap01 | ||
| 67 | public vm_trap02 | ||
| 68 | public vm_trap03 | ||
| 69 | public vm_trap04 | ||
| 70 | public vm_trap05 | ||
| 71 | public vm_trap06 | ||
| 72 | public vm_trap07 | ||
| 73 | public vm_trap08 | ||
| 74 | public vm_trap09 | ||
| 75 | public vm_trap0a | ||
| 76 | public vm_trap0b | ||
| 77 | public vm_trap0c | ||
| 78 | public vm_trap0d | ||
| 79 | public vm_trap0e | ||
| 80 | public vm_trap0f | ||
| 81 | public vm_trap10 | ||
| 82 | public vm_trap50 | ||
| 83 | public vm_trap51 | ||
| 84 | public vm_trap52 | ||
| 85 | public vm_trap53 | ||
| 86 | public vm_trap54 | ||
| 87 | public vm_trap55 | ||
| 88 | public vm_trap56 | ||
| 89 | public vm_trap57 | ||
| 90 | public vm_trap70 | ||
| 91 | public vm_trap71 | ||
| 92 | public vm_trap72 | ||
| 93 | public vm_trap73 | ||
| 94 | public vm_trap74 | ||
| 95 | public vm_trap75 | ||
| 96 | public vm_trap76 | ||
| 97 | public vm_trap77 | ||
| 98 | |||
| 99 | page | ||
| 100 | ;****************************************************************************** | ||
| 101 | ; E X T E R N A L R E F E R E N C E S | ||
| 102 | ;****************************************************************************** | ||
| 103 | ; | ||
| 104 | _TEXT segment | ||
| 105 | extrn VmFault:near ; V Mode GP fault handler (VMINST) | ||
| 106 | extrn ErrHndlr:near ; Error Handler (ERRHNDLR) | ||
| 107 | extrn DisableNMI:near ; Disable NMI for NMI trap handler | ||
| 108 | _TEXT ends | ||
| 109 | page | ||
| 110 | ;****************************************************************************** | ||
| 111 | ; I N C L U D E F I L E S | ||
| 112 | ;****************************************************************************** | ||
| 113 | ; | ||
| 114 | include VDMseg.inc | ||
| 115 | include VDMsel.inc | ||
| 116 | include vm386.inc | ||
| 117 | include pic_def.equ | ||
| 118 | include instr386.inc | ||
| 119 | include oemdep.inc | ||
| 120 | |||
| 121 | page | ||
| 122 | ;****************************************************************************** | ||
| 123 | ; L O C A L C O N S T A N T S | ||
| 124 | ;****************************************************************************** | ||
| 125 | ; | ||
| 126 | FALSE equ 0 | ||
| 127 | TRUE equ not FALSE | ||
| 128 | |||
| 129 | ProcessExcep macro ExcepNum | ||
| 130 | mov bx, ExcepNum | ||
| 131 | mov ax, ExcpErr | ||
| 132 | jmp ErrHndlr | ||
| 133 | endm | ||
| 134 | ; | ||
| 135 | ;****************************************************************************** | ||
| 136 | ; S E G M E N T D E F I N I T I O N | ||
| 137 | ;****************************************************************************** | ||
| 138 | ; | ||
| 139 | ABS0 segment at 0000h | ||
| 140 | ABS0 ends | ||
| 141 | ; | ||
| 142 | ;------------------------------------------------------------------------------ | ||
| 143 | _TEXT segment | ||
| 144 | assume cs:_TEXT, ds:NOTHING, es:NOTHING, ss:NOTHING | ||
| 145 | VmTrap label byte | ||
| 146 | ; | ||
| 147 | db 'WCC' | ||
| 148 | ; | ||
| 149 | page | ||
| 150 | ;****************************************************************************** | ||
| 151 | ; CPU: Divide error fault | ||
| 152 | ; | ||
| 153 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 154 | ; No error code on stack | ||
| 155 | ; EXIT: to handler or debugger as appropriate | ||
| 156 | ; USED: | ||
| 157 | ; STACK: | ||
| 158 | ;------------------------------------------------------------------------------ | ||
| 159 | vm_trap00 proc near | ||
| 160 | PUSH_EBP | ||
| 161 | mov bp,sp | ||
| 162 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 163 | jz vmt0_dexit ; N: exit to debugger | ||
| 164 | push 0000 ; Y: interrupt 00 | ||
| 165 | jmp hw_int ; reflect it to virtual mode | ||
| 166 | vmt0_dexit: | ||
| 167 | ProcessExcep ErrDIV | ||
| 168 | vm_trap00 endp | ||
| 169 | |||
| 170 | ;****************************************************************************** | ||
| 171 | ; CPU: Debug trap | ||
| 172 | ; | ||
| 173 | ; Traps from Virtual mode are reflected to virtual mode. Unfortunately | ||
| 174 | ; this breaks the debugger's ability to GO and TRACE the VM program. | ||
| 175 | ; | ||
| 176 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 177 | ; No error code on stack | ||
| 178 | ; EXIT: to handler or debugger as appropriate | ||
| 179 | ; USED: | ||
| 180 | ; STACK: | ||
| 181 | ;------------------------------------------------------------------------------ | ||
| 182 | vm_trap01 proc near | ||
| 183 | PUSH_EBP | ||
| 184 | mov bp,sp | ||
| 185 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 186 | jz vmt1_dexit ; N: exit to debugger | ||
| 187 | push 0001 ; Y: interrupt 01 | ||
| 188 | jmp hw_int ; reflect it to virtual mode | ||
| 189 | vmt1_dexit: | ||
| 190 | ProcessExcep ErrINT1 | ||
| 191 | vm_trap01 endp | ||
| 192 | |||
| 193 | ;****************************************************************************** | ||
| 194 | ; H/W: NMI | ||
| 195 | ; | ||
| 196 | ; For now, this always traps to the debugger. It's a general purpose hook | ||
| 197 | ; to let the debugger get control via an NMI button. | ||
| 198 | ; | ||
| 199 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 200 | ; No error code on stack | ||
| 201 | ; EXIT: to handler or debugger as appropriate | ||
| 202 | ; USED: | ||
| 203 | ; STACK: | ||
| 204 | ;------------------------------------------------------------------------------ | ||
| 205 | vm_trap02 proc near | ||
| 206 | PUSH_EBP | ||
| 207 | mov bp,sp | ||
| 208 | |||
| 209 | call DisableNMI | ||
| 210 | |||
| 211 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 212 | jz vmt2_parity ; N: error/debug trap | ||
| 213 | ; Y: reflect it/debugger | ||
| 214 | push 02 ; reflect it | ||
| 215 | jmp hw_int | ||
| 216 | vmt2_parity: | ||
| 217 | ProcessExcep ErrNMI | ||
| 218 | |||
| 219 | vm_trap02 endp | ||
| 220 | |||
| 221 | ;****************************************************************************** | ||
| 222 | ; CPU: Breakpoint trap (INT 3 instruction) | ||
| 223 | ; | ||
| 224 | ; Traps from Virtual mode are reflected to virtual mode. Unfortunately | ||
| 225 | ; this breaks the debugger's ability to GO and TRACE the VM program. | ||
| 226 | ; | ||
| 227 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 228 | ; No error code on stack | ||
| 229 | ; EXIT: to handler or debugger as appropriate | ||
| 230 | ; USED: | ||
| 231 | ; STACK: | ||
| 232 | ;------------------------------------------------------------------------------ | ||
| 233 | vm_trap03 proc near | ||
| 234 | ProcessExcep ErrINT3 | ||
| 235 | vm_trap03 endp | ||
| 236 | |||
| 237 | ;****************************************************************************** | ||
| 238 | ; CPU: Overflow trap (INTO instruction) | ||
| 239 | ; | ||
| 240 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 241 | ; No error code on stack | ||
| 242 | ; EXIT: to handler or debugger as appropriate | ||
| 243 | ; USED: | ||
| 244 | ; STACK: | ||
| 245 | ;------------------------------------------------------------------------------ | ||
| 246 | vm_trap04 proc near | ||
| 247 | ProcessExcep ErrINTO | ||
| 248 | vm_trap04 endp | ||
| 249 | |||
| 250 | |||
| 251 | ;****************************************************************************** | ||
| 252 | ; CPU: Array bounds fault | ||
| 253 | ; | ||
| 254 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 255 | ; No error code on stack | ||
| 256 | ; EXIT: to handler or debugger as appropriate | ||
| 257 | ; USED: | ||
| 258 | ; STACK: | ||
| 259 | ;------------------------------------------------------------------------------ | ||
| 260 | vm_trap05 proc near | ||
| 261 | PUSH_EBP | ||
| 262 | mov bp,sp | ||
| 263 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 264 | jz vmt5_dexit ; N: exit to debugger | ||
| 265 | push 0005 ; Y: interrupt 01 | ||
| 266 | jmp hw_int ; reflect it to virtual mode | ||
| 267 | vmt5_dexit: | ||
| 268 | ProcessExcep ErrBounds | ||
| 269 | vm_trap05 endp | ||
| 270 | |||
| 271 | ;****************************************************************************** | ||
| 272 | ; CPU: Invalid Opcode fault | ||
| 273 | ; | ||
| 274 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 275 | ; No error code on stack | ||
| 276 | ; EXIT: to handler or debugger as appropriate | ||
| 277 | ; USED: | ||
| 278 | ; STACK: | ||
| 279 | ; | ||
| 280 | ; add Invalid instruction emulator ??? (specifically LOCK prefix) | ||
| 281 | ; | ||
| 282 | ;------------------------------------------------------------------------------ | ||
| 283 | vm_trap06 proc near | ||
| 284 | push 0 ; align stack with error offset | ||
| 285 | push 0 ; for VmFault | ||
| 286 | PUSH_EBP | ||
| 287 | mov bp,sp | ||
| 288 | test [bp.VTFOE+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 289 | jz vmt6_dexit ; N: exit to debugger | ||
| 290 | jmp VmFault ; Y: enter VM 06 Invalid handler | ||
| 291 | |||
| 292 | vmt6_dexit: | ||
| 293 | ProcessExcep ErrOpCode | ||
| 294 | vm_trap06 endp | ||
| 295 | |||
| 296 | ;****************************************************************************** | ||
| 297 | ; CPU: Coprocessor not present fault | ||
| 298 | ; | ||
| 299 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 300 | ; No error code on stack | ||
| 301 | ; EXIT: to handler or debugger as appropriate | ||
| 302 | ; USED: | ||
| 303 | ; STACK: | ||
| 304 | ;------------------------------------------------------------------------------ | ||
| 305 | vm_trap07 proc near | ||
| 306 | PUSH_EBP | ||
| 307 | mov bp,sp | ||
| 308 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 309 | jz vmt7_dexit ; N: exit to debugger | ||
| 310 | push 0007 ; Y: interrupt 07 | ||
| 311 | jmp hw_int ; reflect it to virtual mode | ||
| 312 | vmt7_dexit: | ||
| 313 | ProcessExcep ErrCoPNA | ||
| 314 | vm_trap07 endp | ||
| 315 | |||
| 316 | |||
| 317 | ;****************************************************************************** | ||
| 318 | ; CPU: Double Fault | ||
| 319 | ; H/W: IRQ0 - System timer | ||
| 320 | ; | ||
| 321 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 322 | ; Error Code on stack = 0000 | ||
| 323 | ; EXIT: to handler or debugger as appropriate | ||
| 324 | ; USED: | ||
| 325 | ; STACK: | ||
| 326 | ;------------------------------------------------------------------------------ | ||
| 327 | vm_trap08 proc near | ||
| 328 | PUSH_EBP | ||
| 329 | mov bp,sp | ||
| 330 | cmp sp,VMT_STACK ; Q: H/W interrupt from VM ? | ||
| 331 | jne vmt8_dexit ; N: exit to debugger | ||
| 332 | push 0008 ; Y: interrupt 8 | ||
| 333 | jmp hw_int ; reflect it to virtual mode | ||
| 334 | vmt8_dexit: | ||
| 335 | ProcessExcep ErrDouble | ||
| 336 | vm_trap08 endp | ||
| 337 | |||
| 338 | |||
| 339 | ;****************************************************************************** | ||
| 340 | ; CPU: (none for 386) | ||
| 341 | ; H/W: IRQ1 - Keyboard | ||
| 342 | ; | ||
| 343 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 344 | ; No error code on stack | ||
| 345 | ; EXIT: to handler or debugger as appropriate | ||
| 346 | ; USED: | ||
| 347 | ; STACK: | ||
| 348 | ;------------------------------------------------------------------------------ | ||
| 349 | vm_trap09 proc near | ||
| 350 | PUSH_EBP | ||
| 351 | mov bp,sp | ||
| 352 | push 0009 ; Y: interrupt 9 | ||
| 353 | jmp hw_int ; reflect it to virtual mode | ||
| 354 | vm_trap09 endp | ||
| 355 | |||
| 356 | ;****************************************************************************** | ||
| 357 | ; CPU: Invalid TSS fault | ||
| 358 | ; H/W: IRQ2 - Cascade from slave 8259 (see INT 70-77) | ||
| 359 | ; (shouldn't get H/W interrupts here) | ||
| 360 | ; | ||
| 361 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 362 | ; Error Code on stack = Selector | ||
| 363 | ; EXIT: to handler or debugger as appropriate | ||
| 364 | ; USED: | ||
| 365 | ; STACK: | ||
| 366 | |||
| 367 | ; to do: someone could reprogram master 8259 - need to handle ? | ||
| 368 | ;------------------------------------------------------------------------------ | ||
| 369 | vm_trap0A proc near | ||
| 370 | ProcessExcep ErrTSS | ||
| 371 | vm_trap0A endp | ||
| 372 | |||
| 373 | |||
| 374 | ;****************************************************************************** | ||
| 375 | ; CPU: Segment Not Present fault | ||
| 376 | ; H/W: IRQ3 - COM2 | ||
| 377 | ; | ||
| 378 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 379 | ; Error Code on stack = Selector | ||
| 380 | ; EXIT: to handler or debugger as appropriate | ||
| 381 | ; USED: | ||
| 382 | ; STACK: | ||
| 383 | ;------------------------------------------------------------------------------ | ||
| 384 | vm_trap0B proc near | ||
| 385 | PUSH_EBP | ||
| 386 | mov bp,sp | ||
| 387 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 388 | jz vmtB_dexit ; N: exit to debugger | ||
| 389 | push 000Bh ; Y: interrupt 0B | ||
| 390 | jmp hw_int ; reflect it to virtual mode | ||
| 391 | vmtB_dexit: | ||
| 392 | ProcessExcep ErrSegNP | ||
| 393 | vm_trap0B endp | ||
| 394 | |||
| 395 | ;****************************************************************************** | ||
| 396 | ; CPU: Stack fault | ||
| 397 | ; H/W: IRQ4 - COM1 | ||
| 398 | ; | ||
| 399 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 400 | ; Error Code on stack = Selector or 0000 | ||
| 401 | ; EXIT: to handler or debugger as appropriate | ||
| 402 | ; USED: | ||
| 403 | ; STACK: | ||
| 404 | ;------------------------------------------------------------------------------ | ||
| 405 | vm_trap0C proc near | ||
| 406 | PUSH_EBP | ||
| 407 | mov bp,sp | ||
| 408 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 409 | jz vmtC_dexit ; N: exit to debugger | ||
| 410 | push 000Ch ; Y: interrupt 0C | ||
| 411 | jmp hw_int ; reflect it to virtual mode | ||
| 412 | vmtC_dexit: | ||
| 413 | ProcessExcep ErrStack | ||
| 414 | vm_trap0C endp | ||
| 415 | |||
| 416 | ;****************************************************************************** | ||
| 417 | ; CPU: General Protection fault | ||
| 418 | ; H/W: IRQ5 - Second parallel printer | ||
| 419 | ; | ||
| 420 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 421 | ; Error Code on stack = Selector or 0000 | ||
| 422 | ; EXIT: to handler or debugger as appropriate | ||
| 423 | ; USED: | ||
| 424 | ; STACK: | ||
| 425 | ;------------------------------------------------------------------------------ | ||
| 426 | vm_trap0D proc near | ||
| 427 | PUSH_EBP | ||
| 428 | mov bp,sp | ||
| 429 | cmp sp,VMT_STACK ; Q: H/W interrupt from VM ? | ||
| 430 | jne vmtD_1 ; N: continue | ||
| 431 | push 000Dh ; Y: interrupt vector 0Dh | ||
| 432 | jmp hw_int ; reflect it to virtual mode | ||
| 433 | ; | ||
| 434 | ; Here we have a GP fault that was not a H/W interrupt 13 from VM. | ||
| 435 | ; | ||
| 436 | vmtD_1: | ||
| 437 | cmp sp,VMTERR_STACK ; Q: 'normal' exception w/error code ? | ||
| 438 | jne vmtD_dexit ; N: what the hell was it ???? - exit | ||
| 439 | jmp VmFault ; Y: enter VM GP fault handler | ||
| 440 | ; (fall thru to debugger) | ||
| 441 | vmtD_dexit: | ||
| 442 | ProcessExcep ErrGP | ||
| 443 | vm_trap0D endp | ||
| 444 | |||
| 445 | ;****************************************************************************** | ||
| 446 | ; CPU: Page fault | ||
| 447 | ; H/W: IRQ6 - diskette interrupt | ||
| 448 | ; | ||
| 449 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 450 | ; Error Code on stack = type of fault | ||
| 451 | ; EXIT: to handler or debugger as appropriate | ||
| 452 | ; USED: | ||
| 453 | ; STACK: | ||
| 454 | ;------------------------------------------------------------------------------ | ||
| 455 | vm_trap0E proc near | ||
| 456 | PUSH_EBP | ||
| 457 | mov bp,sp | ||
| 458 | cmp sp,VMT_STACK ; Q: H/W interrupt from VM ? | ||
| 459 | jne vmtE_dexit ; N: exit to debugger | ||
| 460 | push 000Eh ; Y: interrupt vector 0Eh | ||
| 461 | jmp hw_int ; reflect it to virtual mode | ||
| 462 | vmtE_dexit: | ||
| 463 | ProcessExcep ErrPage | ||
| 464 | vm_trap0E endp | ||
| 465 | |||
| 466 | ;****************************************************************************** | ||
| 467 | ; CPU: (none) | ||
| 468 | ; H/W: IRQ7 - parallel printer | ||
| 469 | ; | ||
| 470 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 471 | ; No error code on stack | ||
| 472 | ; EXIT: to handler or debugger as appropriate | ||
| 473 | ; USED: | ||
| 474 | ; STACK: | ||
| 475 | ;------------------------------------------------------------------------------ | ||
| 476 | vm_trap0F proc near | ||
| 477 | PUSH_EBP | ||
| 478 | mov bp,sp | ||
| 479 | push 000Fh ; push interrupt number | ||
| 480 | jmp hw_int ; enter common H/W interrupt handler | ||
| 481 | vm_trap0F endp | ||
| 482 | |||
| 483 | ;****************************************************************************** | ||
| 484 | ; CPU: Coprocessor Error - GOES TO NOT PRESENT FAULT IN DEBUGGER FOR NOW | ||
| 485 | ; | ||
| 486 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 487 | ; No error code on stack | ||
| 488 | ; EXIT: to handler or debugger as appropriate | ||
| 489 | ; USED: | ||
| 490 | ; STACK: | ||
| 491 | ;------------------------------------------------------------------------------ | ||
| 492 | vm_trap10 proc near | ||
| 493 | ProcessExcep ErrCoPerr | ||
| 494 | vm_trap10 endp | ||
| 495 | |||
| 496 | ;****************************************************************************** | ||
| 497 | ; VmTrap5x - Handlers for hardware interrupts. Sometimes the master 8259 | ||
| 498 | ; is set to here. | ||
| 499 | ; | ||
| 500 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 501 | ; EXIT: EBP pushed on stack | ||
| 502 | ; BP = normal stack frame pointer | ||
| 503 | ; Interrupt number pushed on stack | ||
| 504 | ; USED: | ||
| 505 | ; STACK: (4 bytes) | ||
| 506 | ;------------------------------------------------------------------------------ | ||
| 507 | vm_trap50 proc near | ||
| 508 | PUSH_EBP | ||
| 509 | mov bp,sp ; set up BP frame pointer | ||
| 510 | push 0050h | ||
| 511 | jmp short hw_int ; enter common code | ||
| 512 | vm_trap50 endp | ||
| 513 | |||
| 514 | ;------------------------------------------------------------------------------ | ||
| 515 | vm_trap51 proc near | ||
| 516 | PUSH_EBP | ||
| 517 | mov bp,sp ; set up BP frame pointer | ||
| 518 | push 0051h | ||
| 519 | jmp short hw_int ; enter common code | ||
| 520 | vm_trap51 endp | ||
| 521 | |||
| 522 | ;------------------------------------------------------------------------------ | ||
| 523 | vm_trap52 proc near | ||
| 524 | PUSH_EBP | ||
| 525 | mov bp,sp ; set up BP frame pointer | ||
| 526 | push 0052h | ||
| 527 | jmp short hw_int ; enter common code | ||
| 528 | vm_trap52 endp | ||
| 529 | |||
| 530 | ;------------------------------------------------------------------------------ | ||
| 531 | vm_trap53 proc near | ||
| 532 | PUSH_EBP | ||
| 533 | mov bp,sp ; set up BP frame pointer | ||
| 534 | push 0053h | ||
| 535 | jmp short hw_int ; enter common code | ||
| 536 | vm_trap53 endp | ||
| 537 | |||
| 538 | ;------------------------------------------------------------------------------ | ||
| 539 | vm_trap54 proc near | ||
| 540 | PUSH_EBP | ||
| 541 | mov bp,sp ; set up BP frame pointer | ||
| 542 | push 0054h | ||
| 543 | jmp short hw_int ; enter common code | ||
| 544 | vm_trap54 endp | ||
| 545 | |||
| 546 | ;------------------------------------------------------------------------------ | ||
| 547 | vm_trap55 proc near | ||
| 548 | PUSH_EBP | ||
| 549 | mov bp,sp ; set up BP frame pointer | ||
| 550 | push 0055h | ||
| 551 | jmp short hw_int ; enter common code | ||
| 552 | vm_trap55 endp | ||
| 553 | |||
| 554 | ;------------------------------------------------------------------------------ | ||
| 555 | vm_trap56 proc near | ||
| 556 | PUSH_EBP | ||
| 557 | mov bp,sp ; set up BP frame pointer | ||
| 558 | push 0056h | ||
| 559 | jmp short hw_int ; enter common code | ||
| 560 | vm_trap56 endp | ||
| 561 | |||
| 562 | ;------------------------------------------------------------------------------ | ||
| 563 | vm_trap57 proc near | ||
| 564 | PUSH_EBP | ||
| 565 | mov bp,sp ; set up BP frame pointer | ||
| 566 | push 0057h | ||
| 567 | jmp short hw_int ; enter common code | ||
| 568 | vm_trap57 endp | ||
| 569 | |||
| 570 | ;****************************************************************************** | ||
| 571 | ; VmTrap7x - handlers for hardware interrupts from the slave 8259 | ||
| 572 | ; | ||
| 573 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 574 | ; EXIT: EBP pushed on stack | ||
| 575 | ; BP = normal stack frame pointer | ||
| 576 | ; Interrupt number pushed on stack | ||
| 577 | ; USED: | ||
| 578 | ; STACK: (4 bytes) | ||
| 579 | ;------------------------------------------------------------------------------ | ||
| 580 | vm_trap70 proc near | ||
| 581 | PUSH_EBP | ||
| 582 | mov bp,sp ; set up BP frame pointer | ||
| 583 | push 0070h | ||
| 584 | jmp short hw_int ; enter common code | ||
| 585 | vm_trap70 endp | ||
| 586 | |||
| 587 | ;------------------------------------------------------------------------------ | ||
| 588 | vm_trap71 proc near | ||
| 589 | PUSH_EBP | ||
| 590 | mov bp,sp ; set up BP frame pointer | ||
| 591 | push 0071h | ||
| 592 | jmp short hw_int ; enter common code | ||
| 593 | vm_trap71 endp | ||
| 594 | |||
| 595 | ;------------------------------------------------------------------------------ | ||
| 596 | vm_trap72 proc near | ||
| 597 | PUSH_EBP | ||
| 598 | mov bp,sp ; set up BP frame pointer | ||
| 599 | push 0072h | ||
| 600 | jmp short hw_int ; enter common code | ||
| 601 | vm_trap72 endp | ||
| 602 | |||
| 603 | ;------------------------------------------------------------------------------ | ||
| 604 | vm_trap73 proc near | ||
| 605 | PUSH_EBP | ||
| 606 | mov bp,sp ; set up BP frame pointer | ||
| 607 | push 0073h | ||
| 608 | jmp short hw_int ; enter common code | ||
| 609 | vm_trap73 endp | ||
| 610 | |||
| 611 | ;------------------------------------------------------------------------------ | ||
| 612 | vm_trap74 proc near | ||
| 613 | PUSH_EBP | ||
| 614 | mov bp,sp ; set up BP frame pointer | ||
| 615 | push 0074h | ||
| 616 | jmp short hw_int ; enter common code | ||
| 617 | vm_trap74 endp | ||
| 618 | |||
| 619 | ;------------------------------------------------------------------------------ | ||
| 620 | vm_trap75 proc near | ||
| 621 | PUSH_EBP | ||
| 622 | mov bp,sp ; set up BP frame pointer | ||
| 623 | push 0075h | ||
| 624 | jmp short hw_int ; enter common code | ||
| 625 | vm_trap75 endp | ||
| 626 | |||
| 627 | ;------------------------------------------------------------------------------ | ||
| 628 | vm_trap76 proc near | ||
| 629 | PUSH_EBP | ||
| 630 | mov bp,sp ; set up BP frame pointer | ||
| 631 | push 0076h | ||
| 632 | jmp short hw_int ; enter common code | ||
| 633 | vm_trap76 endp | ||
| 634 | |||
| 635 | ;------------------------------------------------------------------------------ | ||
| 636 | vm_trap77 proc near | ||
| 637 | PUSH_EBP | ||
| 638 | mov bp,sp ; set up BP frame pointer | ||
| 639 | push 0077h | ||
| 640 | jmp short hw_int ; enter common code | ||
| 641 | vm_trap77 endp | ||
| 642 | |||
| 643 | page | ||
| 644 | ;****************************************************************************** | ||
| 645 | ; HW_INT - common handler for hardware interrupts. The interrupt is | ||
| 646 | ; reflected directly to the appropriate Real Mode (Virtual) handler. | ||
| 647 | ; This entry point clear the trace flag (TF) and int flag (IF), since | ||
| 648 | ; a h/w interrupt would (NOTE: INT n and INTO instructions also clear | ||
| 649 | ; TF and IF - so this entry is suitable for reflecting these also). | ||
| 650 | ; | ||
| 651 | ; EMUL_REFLECT - entry point for reflecting emulations. | ||
| 652 | ; This entry point does not clear the trace flag (TF) and int flag (IF). | ||
| 653 | ; | ||
| 654 | ; 386 interrupt gate switched us to the Ring 0 stack on the way in | ||
| 655 | ; from Virtual Mode and pushed 32-bit values as follows: | ||
| 656 | ; | ||
| 657 | ; hiword loword offset (in addition to EBP push) | ||
| 658 | ; +------+------+ <-------- Top of 'kernel' stack | ||
| 659 | ; | 0000 | GS | +32 (decimal) | ||
| 660 | ; |------|------| | ||
| 661 | ; | 0000 | FS | +28 | ||
| 662 | ; |------|------| | ||
| 663 | ; | 0000 | DS | +24 | ||
| 664 | ; |------|------| | ||
| 665 | ; | 0000 | ES | +20 | ||
| 666 | ; |------|------| | ||
| 667 | ; | 0000 | SS | +16 | ||
| 668 | ; |------|------| | ||
| 669 | ; | ESP | +12 | ||
| 670 | ; |------|------| | ||
| 671 | ; | EFLAGS | +08 | ||
| 672 | ; |------|------| | ||
| 673 | ; | 0000 | CS | +04 | ||
| 674 | ; |------|------| | ||
| 675 | ; | EIP | +00 | ||
| 676 | ; +------+------+ <-------- Ring 0 SS:SP | ||
| 677 | ; | (ebp) | | ||
| 678 | ; +-------------+ <-------- Ring 0 SS:BP | ||
| 679 | ; | ||
| 680 | ; The object of this routine is to massage the trap stack frame (above) | ||
| 681 | ; and build a 'real mode' stack frame for the virtual mode client so that | ||
| 682 | ; we can transfer control to virtual mode at the address specified in | ||
| 683 | ; the appropriate real mode IDT vector. The client's IRET out of the | ||
| 684 | ; interrupt routine will proceed normally (assuming we're letting him | ||
| 685 | ; run with IOPL = 3). Since we're fielding the trap from Virtual Mode, | ||
| 686 | ; we assume the high word of ESP and EIP is 0000. | ||
| 687 | ; | ||
| 688 | ; +-------+ <-------- Client's current SS:SP | ||
| 689 | ; | Flags | +4 | ||
| 690 | ; |-------| | ||
| 691 | ; | CS | +2 | ||
| 692 | ; |-------| | ||
| 693 | ; | IP | +0 | ||
| 694 | ; +-------+ <-------- Client's SS:SP when we let him have control | ||
| 695 | ; | ||
| 696 | ; Assume entry from Virtual Mode, for now. We shouldn't be getting entered | ||
| 697 | ; here except via Hardware interrupt, so no sanity checks are performed. | ||
| 698 | ; | ||
| 699 | ; ENTRY: 386 Protected Mode | ||
| 700 | ; BP -> standard frame | ||
| 701 | ; EBP and Interrupt number have been pushed onto stack | ||
| 702 | ; EXIT: via IRET to VM86 program | ||
| 703 | ; appropriate real mode IRET set up @ client's SS:SP | ||
| 704 | ; USED: (none) (note that DS & ES are free to use - saved during trap) | ||
| 705 | ; STACK: | ||
| 706 | ; | ||
| 707 | ; to do: Need to check for entry mode ? | ||
| 708 | ;------------------------------------------------------------------------------ | ||
| 709 | hw_int proc near | ||
| 710 | push bx | ||
| 711 | push si ; | ||
| 712 | mov si,[bp.VTFO+VMTF_EFLAGS] ; SI = saved low word of EFLAGS | ||
| 713 | ; | ||
| 714 | ; *** clear IF bit and Trace Flag on flags for reflect, but leave them | ||
| 715 | ; unchanged for the flags on the IRET stack we build on the | ||
| 716 | ; client's stack. | ||
| 717 | ; | ||
| 718 | and [bp.VTFO+VMTF_EFLAGS],not 300h ; clear IF and TF | ||
| 719 | reflect_common: | ||
| 720 | ; | ||
| 721 | ; Build a selector (VM1_GSEL) to client's stack. VM1_GSEL is already set | ||
| 722 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 723 | ; | ||
| 724 | HwTabUnlock ; disable HW protection on high ram | ||
| 725 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 726 | mov ds,bx ; DS -> GDT | ||
| 727 | mov bx,[bp.VTFO+VMTF_SS] ; BX = VM SS (segment form) | ||
| 728 | shl bx,4 ; BX = low 16 bits of base | ||
| 729 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 730 | mov bx,[bp.VTFO+VMTF_SS] ; BX = VM SS (again) | ||
| 731 | shr bx,4 ; BH = high 8 bits of base | ||
| 732 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 733 | ; | ||
| 734 | ; Adjust client's SP to make room for building his IRET frame | ||
| 735 | ; | ||
| 736 | sub word ptr [bp.VTFO+VMTF_ESP],6 ; adjust client's SP | ||
| 737 | mov bx, VM1_GSEL | ||
| 738 | mov ds, bx ; DS = VM stack segment | ||
| 739 | ; | ||
| 740 | mov bx,si ; BX = low word of client's EFLAGS | ||
| 741 | ; | ||
| 742 | mov si,[bp.VTFO+VMTF_ESP] ; DS:SI = pointer to client's frame | ||
| 743 | ; | ||
| 744 | ; Move low 16 bits of Flags, CS, and EIP from IRET frame to client stack frame | ||
| 745 | ; | ||
| 746 | mov ds:[si.4],bx ; to client's flags | ||
| 747 | mov bx,[bp.VTFO+VMTF_CS] ; | ||
| 748 | mov ds:[si.2],bx ; to client's CS | ||
| 749 | mov bx,[bp.VTFO+VMTF_EIP] ; low word of EIP | ||
| 750 | mov ds:[si.0],bx ; to client's IP | ||
| 751 | ; | ||
| 752 | ; Replace low 16 bits of IRET frame CS:EIP with vector from real mode IDT | ||
| 753 | ; | ||
| 754 | mov bx,[bp-2] ; get the interrupt vector | ||
| 755 | shl bx,2 ; BX = BX * 4 (vector table index) | ||
| 756 | mov si,RM_IDT_GSEL ; get real mode IDT alias | ||
| 757 | mov ds,si ; DS -> Real Mode IDT | ||
| 758 | mov si,ds:[bx] ; | ||
| 759 | mov [bp.VTFO+VMTF_EIP],si ; move the IP | ||
| 760 | mov si,ds:[bx+2] ; | ||
| 761 | mov [bp.VTFO+VMTF_CS],si ; move the CS | ||
| 762 | ; | ||
| 763 | ; 32-bit IRET back to client | ||
| 764 | ; | ||
| 765 | HwTabLock ; enable HW protection on high ram | ||
| 766 | pop si ; restore local regs | ||
| 767 | pop bx | ||
| 768 | pop bp ; throw away fake interrupt number | ||
| 769 | POP_EBP | ||
| 770 | db 66h | ||
| 771 | iret ; *** RETURN *** to client | ||
| 772 | hw_int endp | ||
| 773 | |||
| 774 | ;****************************************************************************** | ||
| 775 | ; EMUL_REFLECT | ||
| 776 | ;****************************************************************************** | ||
| 777 | ; | ||
| 778 | ; emulation relfection entry point - don't mess with client's flags | ||
| 779 | ; | ||
| 780 | emul_reflect label near | ||
| 781 | push bx ; local registers | ||
| 782 | push si ; | ||
| 783 | mov si,[bp.VTFO+VMTF_EFLAGS] ; SI = saved low word of EFLAGS | ||
| 784 | jmp reflect_common | ||
| 785 | |||
| 786 | |||
| 787 | ; | ||
| 788 | _TEXT ends ; end of segment | ||
| 789 | ; | ||
| 790 | end ; end of module | ||
| 791 | \ No newline at end of file | ||