summaryrefslogtreecommitdiff
path: root/v4.0/src/MEMM/EMM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/MEMM/EMM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/MEMM/EMM')
-rw-r--r--v4.0/src/MEMM/EMM/EMM.H223
-rw-r--r--v4.0/src/MEMM/EMM/EMM40.C571
-rw-r--r--v4.0/src/MEMM/EMM/EMMDATA.ASM467
-rw-r--r--v4.0/src/MEMM/EMM/EMMDEF.INC331
-rw-r--r--v4.0/src/MEMM/EMM/EMMDISP.ASM234
-rw-r--r--v4.0/src/MEMM/EMM/EMMFUNCT.C660
-rw-r--r--v4.0/src/MEMM/EMM/EMMINC.ASM55
-rw-r--r--v4.0/src/MEMM/EMM/EMMP.ASM2978
-rw-r--r--v4.0/src/MEMM/EMM/EMMSUP.ASM652
-rw-r--r--v4.0/src/MEMM/EMM/MAKEFILE95
10 files changed, 6266 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/EMM/EMM.H b/v4.0/src/MEMM/EMM/EMM.H
new file mode 100644
index 0000000..24c0974
--- /dev/null
+++ b/v4.0/src/MEMM/EMM/EMM.H
@@ -0,0 +1,223 @@
1/*******************************************************************************
2 *
3 * (C) Copyright Microsoft Corp. 1986
4 *
5 * TITLE: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver
6 * EMMLIB.LIB - Expanded Memory Manager Library
7 *
8 * MODULE: EMM.H - EMM includes for "C" code
9 *
10 * VERSION: 0.04
11 *
12 * DATE: June 14,1986
13 *
14 *******************************************************************************
15 * CHANGE LOG
16 * Date Version Description
17 * -------- -------- -------------------------------------------------------
18 * 06/14/86 Original
19 * 06/14/86 0.00 Changed stack frame structure to match new emmdisp.asm
20 * and allow byte regs access (SBP).
21 * 06/28/86 0.02 Name change from CEMM386 to CEMM (SBP).
22 * 07/06/86 0.04 Changed save area structure (SBP).
23 *
24 ******************************************************************************/
25
26#define OK 0
27#define EMM_SW_MALFUNCTION 0x80
28#define EMM_HW_MALFUNCTION 0x81
29#define INVALID_HANDLE 0x83
30#define INVALID_FUNCTION 0x84
31#define NO_MORE_HANDLES 0x85
32#define SAVED_PAGE_DEALLOC 0x86
33#define NOT_ENOUGH_EXT_MEM 0x87
34#define NOT_ENOUGH_FREE_MEM 0x88
35#define ZERO_PAGES 0x89
36#define LOG_PAGE_RANGE 0x8A
37#define PHYS_PAGE_RANGE 0x8B
38#define SAVE_AREA_FULL 0x8C
39#define MAP_PREV_SAVED 0x8D
40#define NO_MAP_SAVED 0x8E
41#define INVALID_SUBFUNCTION 0x8F
42#define FEATURE_NOT_SUPPORTED 0x91
43#define NAMED_HANDLE_NOT_FOUND 0xA0
44#define DUPLICATE_HANDLE_NAMES 0xA1
45#define ACCESS_DENIED 0xA4
46
47/*
48 * various usefull defines
49 */
50#define PAGE_SIZE 0x1000
51#define NULL_HANDLE (struct handle_ptr *)0x0FFF
52#define NULL_PAGE 0xFFFF
53#define NULL_SAVE (struct save_map *)0
54
55#define GET 0x00 /* get/set page map sub codes */
56#define SET 0x01
57#define GETSET 0x02
58#define SIZE 0x03
59
60#define EMM_VERSION 0x40
61#define Handle_Name_Len 8
62
63/*
64 * defines for INTERNAL vs EXTERNAL current_map save
65 */
66#define INTERNAL_SAVE (unsigned)1
67#define EXTERNAL_SAVE (unsigned)0
68
69/*
70 * page table structure
71 */
72struct 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 */
84union 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 */
97struct 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 */
108struct 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 */
117typedef char Handle_Name[Handle_Name_Len];
118
119/*
120 * Handle_Dir_Entry
121 *
122 */
123struct 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 */
134struct 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
178extern 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 */
207struct 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 */
220struct 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 */
42extern struct handle_ptr handle_table[];
43extern Handle_Name Handle_Name_Table[]; /* Handle names */
44extern unsigned short handle_table_size; /* number of entries */
45extern 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 */
55extern unsigned short *emm_page; /* _emm_page array */
56extern int free_count; /* current free count */
57extern int total_pages; /* number being managed */
58extern 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 */
78extern unsigned short EMMstatus;
79
80/*
81 * 4.0 EXTRAS
82 */
83
84extern unsigned short emm40_info[5]; /* hardware information */
85extern struct mappable_page mappable_pages[]; /* mappable segments
86 and corresponding pages */
87extern short mappable_page_count; /* number of entries in above */
88extern short page_frame_pages; /* pages in the page frame */
89extern 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 */
94extern char cntxt_pages; /* pages in context */
95extern char cntxt_bytes; /* bytes in context */
96extern unsigned short PF_Base;
97extern unsigned short VM1_EMM_Pages;
98/*extern unsigned short VM1_EMM_Offset;*/
99extern long page_frame_base[];
100extern char EMM_MPindex[];
101extern long OSEnabled; /* OS/E function flag */
102extern long OSKey; /* Key for OS/E function */
103
104/******************************************************************************
105 EXTERNAL FUNCTIONS
106 ******************************************************************************/
107extern struct handle_ptr *valid_handle(); /* validate handle */
108extern unsigned far *source_addr(); /* get DS:SI far ptr */
109extern unsigned far *dest_addr(); /* get ES:DI far ptr */
110extern unsigned wcopyb();
111extern unsigned copyout();
112extern 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 */
131ReallocatePages()
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 */
210UndefinedFunction()
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 */
233GetMappablePAddrArray()
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 */
278GetInformation()
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 */
319GetSetHandleAttribute()
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 */
363GetSetHandleName()
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 */
436GetHandleDirectory()
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 */
514PrepareForWarmBoot()
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 */
536OSDisable()
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 @@
1page 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
181PF_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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
219EMM_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
228ifdef CGA
229_VM1_EMM_Pages dw 30 ; 4000h to B800h for now
230else
231_VM1_EMM_Pages dw 24 ; 4000h to A000h for now
232endif
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
267FRS_array LABEL WORD ; Array of Fast Register Set structures
268 REPT FRS_COUNT
269FRS_struc <>
270 ENDM
271
272;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
273;09. Variables to support FRS Implementation
274;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
275FRS_free db 0 ; How many of the above are free
276CurRegSetn db 0 ; Number of Current Register Set
277_CurRegSet LABEL WORD
278CurRegSet dw 0 ; Pointer to Current Register Set Area
279 ; in FRS_array
280
281; initialized to 0:0 for initial buffer inquiry
282;
283EMM_savES dw 0 ; store for buffer address provided
284EMM_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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
296VEMMD_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
305SaveMap_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
318HandleTable_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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
373EMM_dynamic_data_area LABEL BYTE
374;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
375
376ifndef 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
410endif
411
412;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
413EMM_data_end label byte
414;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
415
416_DATA ENDS
417
418ifndef NOHIMEM
419
420else
421
422VDATA SEGMENT
423 public vdata_begin
424vdata_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
458VDATA ENDS
459
460
461
462endif
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;******************************************************************************
26ifndef INC_LIST
27.xlist
28endif
29
30;******************************************************************************
31; G E N E R A L D E F I N E S
32;******************************************************************************
33EMM_PAGE_CNT = 2048 ; maximum of 2048 EMM pages (32MB)
34HANDLE_CNT = 255 ; maximum of 255 EMM handles
35FRS_COUNT = 16 ; number of 'Fast Register Sets'
36
37EMM32_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
43TOT_PHYS_PAGES equ 64
44MAX_PHYS_PAGES equ 40 ; Life, the Universe
45 ; and Everything
46PAGE_SIZE = 1000h
47;
48; Of the above mappable pages the regions C000h to Dfffh have to be searched
49; for the mappable pages.
50;
51ABOVE_CONV_STRT_SEG equ 0C000h
52ABOVE_CONV_STRT_PG equ ABOVE_CONV_STRT_SEG SHR 10
53;
54ABOVE_CONV_END_SEG equ 0DC00h
55ABOVE_CONV_END_PG equ ABOVE_CONV_END_SEG SHR 10
56;
57MAX_ABOVE_CONV_PAGES EQU 8
58;
59; Also the system memory mappable region starts at 4000h
60;
61CONV_STRT_SEG equ 4000h
62CONV_STRT_PG equ CONV_STRT_SEG SHR 10
63;
64NUM_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
69PAGE_MAPPABLE equ 0FFh ;
70PAGE_NOT_MAPPABLE equ 0h ;
71
72
73NULL_PAGE = 0FFFFh
74NULL_HANDLE = 00FFFh
75
76
77;
78; Flags for memory move/xchg
79;
80Source_GT_Dest_Flag = 80h ; Source > Destination for copy / xchg
81Overlap_Flag = 40h ; Copy overlapping memory
82Backward_Copy_Flag = 20h ; copy is going to be backward
83;
84; Flags for PFlag use in Alter Map and Jump
85;
86PFLAG_VM = 0002h ; VM bit in High word of EFLAG
87PFLAG_VIRTUAL = 0020h ; wheather it's call from virtual or proected mode
88PFLAG_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;******************************************************************************
93OK = 0
94EMM_SW_MALFUNCTION = 80h
95EMM_HW_MALFUNCTION = 81h
96INVALID_HANDLE = 83h
97INVALID_FUNCTION = 84h
98NO_MORE_HANDLES = 85h
99SAVED_PAGE_DEALLOC = 86h
100NOT_ENOUGH_EXT_MEM = 87h
101NOT_ENOUGH_FREE_MEM = 88h
102ZERO_PAGES = 89h
103LOG_PAGE_RANGE = 8Ah
104PHYS_PAGE_RANGE = 8Bh
105SAVE_AREA_FULL = 8Ch
106MAP_PREV_SAVED = 8Dh
107NO_MAP_SAVED = 8Eh
108INVALID_SUBFUNCTION = 8Fh
109
110; LIM 4.0 extras
111
112VALID_OVERLAP = 92h
113INSUFFICIENT_EMM_PAGES = 93h
114CONVENTIONAL_EMM_OVERLAP= 94h
115INVALID_OFFSET = 95h
116INVALID_REGION_LENGTH = 96h
117OVERLAPPING_EXCHANGE = 97h
118INVALID_MEMORY_TYPE = 98h
119FRSETS_UNSUPPORTED = 99h
120INVALID_FRSET = 9Ah
121NO_MORE_FRSETS = 9Bh
122FRSET_NON_ZERO = 9Ch
123FRSET_UNDEFINED = 9Dh
124FRSET_NO_DMA = 9Eh
125FRSET_INVALID_DMA = 9Fh
126HANDLE_NAME_NOT_FOUND = 0A0h
127DUPLICATE_HANDLE_NAME = 0A1h
128INVALID_WRAPAROUND = 0A2h
129SOURCE_CORRUPTED = 0A3h
130ACCESS_DENIED = 0A4h
131
132
133;******************************************************************************
134; GET/SET PAGE MAP SUBFUNCTION CODES
135;******************************************************************************
136GSPM_GET equ 0
137GSPM_SET equ 1
138GSPM_GETSET equ 2
139GSPM_SIZE equ 3
140
141;
142; OSEnabled Values
143;
144OS_IDLE equ 0
145OS_ENABLED equ 1
146OS_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;
155r67_Frame struc
156rDI dd ?
157rSI dd ?
158rBP dd ?
159rSP dd ?
160rBX dd ?
161rDX dd ?
162rCX dd ?
163rAX dd ?
164retaddr dw ?
165rCS dw ?
166PFlag dw ?
167rDS dw ?
168rES dw ?
169rGS dw ?
170rFS dw ?
171r67_Frame ends
172
173
174;
175; for _handle_table
176;
177HandleTable_struc struc
178ht_index dw NULL_PAGE ; index into emm_page for handle's pgs
179ht_count dw 0 ; number of emm_pages for this handle
180HandleTable_struc ends
181
182;
183; for _save_area
184;
185SaveMap_struc struc
186s_handle dw NULL_HANDLE ; owning handle
187s_map dw EMM32_PHYS_PAGES dup (NULL_PAGE) ; EMM page #s
188SaveMap_struc ends
189
190;
191; structure linking segment with physical page number
192;
193Mappable_Page struc
194mappable_seg dw ?
195mappable_pg dw ?
196Mappable_Page ends
197
198;
199; Get Partial Page Map
200;
201gppm_struc struc
202gppm_count dw ?
203gppm_segs dw ?
204gppm_struc ends
205
206;
207; Structures used as arguments to Map Handle Array function
208;
209
210; For subfunction 0:
211mha_array0 struc
212mha0_log_pg dw ?
213mha0_phys_pg dw ?
214mha_array0 ends
215
216; For subfunction 1:
217mha_array1 struc
218mha1_log_pg dw ?
219mha1_seg dw ?
220mha_array1 ends
221
222; Used by Map and Jump and Map and Call -- Identical to mha_array0 and 1
223log_phys_map_struct struc
224log_page_number dw ?
225phys_page_number_seg dw ?
226log_phys_map_struct ends
227
228; Map and Jump structure
229maj_struct struc
230maj_target_address dd ?
231maj_log_phys_map_len db ?
232maj_map_address dd ?
233maj_struct ends
234
235; Map and Call structure
236mac_struct struc
237mac_target_address dd ?
238mac_new_page_map_len db ?
239mac_new_map_address dd ?
240mac_old_page_map_len db ?
241mac_old_map_address dd ?
242mac_reserved dw 4 dup (?)
243mac_struct ends
244
245; Move / Exchange memory structure
246mem_memory_descriptor_struct struc
247mem_memory_type db ?
248mem_handle dw ?
249mem_initial_offset dw ?
250mem_initial_seg_page dw ?
251mem_memory_descriptor_struct ends
252
253
254mem_struct struc
255mem_region_length dd ?
256mem_source db (SIZE mem_memory_descriptor_struct) dup (?)
257mem_dest db (SIZE mem_memory_descriptor_struct) dup (?)
258mem_struct ends
259
260;
261; Fast Register Set Description
262;
263FRS_struc struc
264FRS_Window dw MAX_PHYS_PAGES dup (NULL_PAGE) ; emm page numbers
265FRS_alloc dw 0 ; Is this set allocated
266FRS_struc ends
267
268 page
269;****************************************************************************
270;
271; Dword_Align -- Aligns code to dword boundry by inserting nops
272;
273;****************************************************************************
274
275Dword_Align MACRO Seg_Name
276IF (($ - OFFSET Seg_Name:0) MOD 4)
277 db 90h ;; Nop in code / else byte of 90h in data
278 Dword_Align Seg_Name
279ENDIF
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;***********************************************
295Validate_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;***********************************************
320Handle2HandlePtr 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 @@
1page 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;
58FALSE equ 0
59TRUE equ not FALSE
60CR equ 0dh
61LF equ 0ah
62
63mkvect MACRO name
64 extrn _&name:near
65 dw offset _TEXT:_&name
66endm
67
68;******************************************************************************
69; E X T E R N A L S
70;******************************************************************************
71
72_DATA SEGMENT
73extrn _EMMstatus:word
74extrn Active_Status:byte
75extrn Auto_Mode:byte
76extrn _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
95assume cs:_text,ds:DGROUP,ss:DGROUP,es:DGROUP
96;
97 db 'PxB'
98;
99
100dispatch_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;*************************************
184int67_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 ;
210i67_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
218ok_exit:
219 popad ; restore all regs
220 ret ; bye!
221
222i67_off_err: ; set h/w error
223 mov byte ptr [bp.rAX+1],EMM_HW_MALFUNCTION
224 jmp ok_exit
225
226i67_inv_exit: ; set invalid function code error
227 mov byte ptr [bp.rAX+1],INVALID_FUNCTION
228 jmp ok_exit
229
230int67_entry endp
231
232_TEXT ENDS
233END
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 */
157extern 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 */
164extern 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 */
171extern struct handle_ptr handle_table[];
172extern Handle_Name Handle_Name_Table[];
173extern unsigned short handle_table_size; /* number of entries */
174extern 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 */
184extern unsigned short *emm_page; /* ptr to _emm_page array */
185extern unsigned short free_count; /* current free count */
186extern unsigned short total_pages; /* number being managed */
187extern 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 */
194extern unsigned short *emm_free; /* ptr to _emm_free array */
195extern 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 */
203extern 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 */
217extern 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 ******************************************************************************/
228extern struct handle_ptr *valid_handle(); /* validate handle */
229extern unsigned far *source_addr(); /* get DS:SI far ptr */
230extern unsigned far *dest_addr(); /* get ES:DI far ptr */
231/*extern unsigned AutoUpdate(); /* update auto mode */
232extern unsigned wcopy();
233extern unsigned copyout();
234extern 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 */
247unsigned short
248Avail_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 */
263unsigned
264get_pages(num,pto)
265register unsigned num;
266register 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 */
297void
298free_pages(hp)
299register 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 */
361GetStatus()
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 */
376GetPageFrameAddress()
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 */
408GetUnallocatedPageCount()
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 */
429AllocatePages()
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 */
457AllocateRawPages()
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 */
513DeallocatePages()
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 */
560GetEMMVersion()
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 */
573GetEMMHandleCount()
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 */
588GetEMMHandlePages()
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 */
608GetAllEMMHandlePages()
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 */
642GetPageMappingRegisterIOArray()
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 */
656GetLogicalToPhysicalPageTrans()
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;******************************************************************************
38INC_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 @@
1page 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
77extrn _source_addr:near
78extrn _dest_addr:near
79
80extrn SetDescInfoResident:near
81extrn SegOffTo24Resident:near
82
83extrn 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
97extrn PF_Base:word
98extrn _OSEnabled:dword
99;extrn NullAvailPTE:dword
100;extrn NullUnavailPTE:dword
101
102extrn _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;
108extrn _page_frame_base:dword
109
110extrn _pft386:word
111
112extrn _mappable_pages:word ; table of mappable pages
113extrn _mappable_page_count:word ; how many in the table
114extrn _page_frame_pages:word ; how many in the page frame
115extrn _physical_page_count:word ; number of physical pages
116extrn _VM1_EMM_Pages:word ; pages not in the page frame
117;extrn _VM1_EMM_Offset:word ; offset of these in a context
118extrn _cntxt_pages:byte ; number of pages in a context
119extrn _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;
125extrn EMM_MPindex:byte
126
127;
128; ptr to table of emm page # for each handle's logical pages.
129;
130extrn _emm_page:word
131
132;
133; handle data structure
134;
135extrn _handle_table:word
136extrn _handle_table_size:word
137
138;
139; save area for handles
140;
141extrn _save_map:byte
142
143;
144; Save area and misc variables for 4.0 function 27
145;
146extrn EMM_savES:word
147extrn EMM_savDI:word
148
149extrn CurRegSetn:byte
150extrn FRS_free:byte
151extrn CurRegSet:dword
152extrn FRS_array:word
153
154extrn _regp:word
155_DATA ENDS
156
157 page
158;******************************************************************************
159; C O D E
160;******************************************************************************
161_TEXT SEGMENT
162assume 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;***********************************************
178normalize 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;***********************************************
221Get_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;***********************************************
237release_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;***********************************************
255Set_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;***********************************************
278Set_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;***********************************************
298Set_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;***********************************************
317Get_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;***********************************************
334map_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
410mEp_inv_page:
411 stc
412 ret
413
414map_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;**********************************************************************
425unmap_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
444unmap_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
452unmap_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
477unmap_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
489unmap_page_exit:
490 pop cx
491 pop bx
492 pop di
493 pop es
494 ret
495unmap_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;**********************************************************************
508map_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
531mp_unmap_page:
532 call unmap_page
533 clc
534 ret
535
536mp_inv_emm_page:
537 mov byte ptr [bp.rAX+1],SOURCE_CORRUPTED
538 stc
539 ret
540
541mp_inv_phy:
542 mov byte ptr [bp.rAX+1],PHYS_PAGE_RANGE
543 stc
544 ret
545
546mp_inv_log:
547 mov byte ptr [bp.rAX+1],LOG_PAGE_RANGE
548 stc
549 ret
550map_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
578Dword_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
594mhp_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
621Dword_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
647spm_prev_saved:
648 mov byte ptr [bp.rAX+1],MAP_PREV_SAVED
649 ret
650
651srpm_inv_handle: ; Shared error returns
652 mov byte ptr [bp.rAX+1],INVALID_HANDLE
653 ret
654
655srpm_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
683Dword_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
711rpm_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;***********************************************
744Dword_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
758gspm_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
767gspm_inv_subfun:
768 mov byte ptr [bp.rAX+1],INVALID_SUBFUNCTION
769 ret
770
771gspm_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;***********************************************
796Dword_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;***********************************************
839Dword_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
865sm_inv_source:
866 mov byte ptr [bp.rAX+1], SOURCE_CORRUPTED
867 ret
868
869sm_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
898sw_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
913sw_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
922sw_unmap_page:
923 push eax
924 call unmap_Page
925 pop eax
926 jmp short sw_done_page
927
928sw_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
986gsppm_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
1015gsppm_ok:
1016 mov byte ptr [bp.rAX+1], OK
1017 ret
1018
1019gsppm_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
1033gsppm_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
1054gsppm_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
1062gsppm_unmap:
1063 call unmap_page ; with ax <-- phys page#
1064 jmp gsppm_set_done ; On to next page
1065
1066gsppm_sl_bad:
1067 pop esi
1068gsppm_corrupt:
1069 mov byte ptr [bp.rAX+1], SOURCE_CORRUPTED
1070 ret
1071
1072gsppm_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
1082gsppm_inv_subfun:
1083 mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION
1084 ret
1085
1086gsppm_inv_phys:
1087gsppm_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;***********************************************
1126Dword_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
1135MapHandleArray_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 ;
1152mha_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 ;
1166mha_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
1186mha_exit:
1187 mov eax, cr3 ; Always clear TLB, we may have
1188 mov cr3, eax ; mapped pages before an error
1189 ret
1190 ; ERRORS...
1191mha_inv_handle:
1192 mov byte ptr [bp.rAX+1], INVALID_HANDLE
1193 ret
1194mha_inv_sub:
1195 mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION
1196 ret
1197mha_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
1273AMJ_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
1533AMC_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
1560AMC_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
1572AMC_inv_phys_pages:
1573 mov byte ptr [bp.rAX+1], PHYS_PAGE_RANGE
1574 ret
1575
1576AMC_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
1594AMC_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
1691AMC_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
1883mem_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
1895mem_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 ;
1932mem_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
1952mem_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
1976mem_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 ;
2006mem_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
2028mem_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
2052mem_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
2083mem_set_done:
2084 mov edx, gs:[bx.mem_region_length] ; total length to move/xchg
2085
2086;
2087; main move/exchange loop
2088;
2089mem_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
2099mem_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
2106mem_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
2117mem_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
2122mem_si_gt_di:
2123 sub cx, si ; si>di
2124
2125mem_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;
2133mem_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;
2148mem_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;
2161mem_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
2169mem_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
2177mem_xchg_bytes:
2178 pop ecx
2179 and ecx, 00000003h ; ECX = # BYTES left to exchange
2180 jecxz mem_xchg_done ; Exit if no DWORDS left
2181mem_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
2189mem_xchg_done:
2190 pop bx
2191 pop ax
2192 pop dx ; DONE!!!!
2193
2194;
2195; prepare for next iteration
2196;
2197mem_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
2216mem_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
2226mem_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 ;
2233mem_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 ;
2256mem_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
2263mem_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
2273mem_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 ;
2280mem_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 ;
2303mem_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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2315mem_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
2363mem_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
2380mem_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
2389mem_conv_copy:
2390 or ebx, ebx
2391 je mem_valid_overlap ; WEIRD!!! -- Move to same place!
2392
2393 jecxz mem_conv_done
2394mem_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
2403mem_conv_xchg:
2404 jecxz mem_conv_done
2405mem_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
2414mem_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
2419mem_error_exit:
2420 cld
2421 mov byte ptr [bp.rAX+1], ah ; error code already set in ah
2422 ret
2423mem_valid_overlap:
2424 mov byte ptr [bp.rAX+1], VALID_OVERLAP
2425 ret
2426mem_no_error:
2427 mov byte ptr [bp.rAX+1], OK
2428 ret
2429
2430mem_inv_sub:
2431 mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION
2432 ret
2433mem_inv_region_len:
2434 mov byte ptr [bp.rAX+1], INVALID_REGION_LENGTH
2435 ret
2436mem_bad_memory_types:
2437 mov byte ptr [bp.rAX+1], INVALID_MEMORY_TYPE
2438 ret
2439mem_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;
2445mem_mapping_error_4_pop:
2446 pop bx
2447mem_mapping_error_3_pop:
2448 pop bx
2449 pop bx
2450 pop bx
2451mem_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;
2457mem_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
2491validate_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
2527ME_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
2544No_EMM_Overlap:
2545 ; N: Everything is okie dokie
2546ME_Map_OK:
2547 pop eax
2548 pop edx
2549 mov ah, OK
2550 ret
2551
2552ME_Map_Inv_Mem:
2553 pop eax
2554 pop edx
2555 mov ah, INVALID_MEMORY_TYPE
2556 ret
2557
2558ME_Map_Inv_Handle:
2559 pop ds
2560 pop eax
2561 pop edx
2562 mov ah, INVALID_HANDLE
2563 ret
2564
2565ME_Map_Invalid_log_page:
2566 pop eax
2567 pop edx
2568 mov ah, LOG_PAGE_RANGE
2569 ret
2570
2571ME_Map_Invalid_Offset:
2572 pop eax
2573 pop edx
2574 mov ah, INVALID_OFFSET
2575 ret
2576
2577ME_Map_Not_Enough_EMM:
2578 pop eax
2579 pop edx
2580 mov ah, INSUFFICIENT_EMM_PAGES
2581 ret
2582
2583ME_Map_Inv_Overlap:
2584 pop eax
2585 pop edx
2586 mov ah, CONVENTIONAL_EMM_OVERLAP
2587 ret
2588
2589ME_Map_Inv_Wraparound:
2590 pop eax
2591 pop edx
2592 mov ah, INVALID_WRAPAROUND
2593 ret
2594
2595validate_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;***********************************************
2628Dword_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...
2640AMRS_exit: ; Exit with AH already set
2641 ret
2642
2643AMRS_NotAllowed:
2644 mov byte ptr [bp.rAX+1], ACCESS_DENIED
2645 ret
2646
2647AMRS_invalid:
2648 mov byte ptr [bp.rAX+1], INVALID_SUBFUNCTION
2649 ret ; Error return!
2650
2651AMRS_bad_src:
2652 mov byte ptr [bp.rAX+1], SOURCE_CORRUPTED
2653 ret ; Error return!
2654
2655AMRS_noDMA:
2656 mov byte ptr [bp.rAX+1], FRSET_NO_DMA
2657 ret ; Error return!
2658
2659Dword_Align _TEXT
2660AMRS_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;-----------------------------------------------
2692Dword_Align _TEXT
2693AMRS_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
2699AMRS_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
2708AMRS_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
2718AMRS_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;-----------------------------------------------
2741Dword_Align _TEXT
2742AMRS_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
2757AMRS_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;-----------------------------------------------
2816AMRS_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;-----------------------------------------------
2838AMRS_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
2845AMRS_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
2856AMRS_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
2866AMRS_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;-----------------------------------------------
2886AMRS_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
2905AMRS_Inv_FRS:
2906AMRS_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
2954Get_Counter_Value PROC NEAR
2955
2956System_Clock_Port EQU 40h
2957Sys_Clock_Ctrl_Port EQU 43h
2958
2959Latch_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
2971Get_Counter_Value ENDP
2972
2973
2974_TEXT ENDS
2975END
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 @@
1page 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
80FALSE equ 0
81TRUE equ not FALSE
82CR equ 0dh
83LF 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
94extrn _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;
105extrn _total_pages:word
106
107;
108; table of offsets into in to the first page table
109; for user logical emm page map
110;
111extrn _page_frame_base:dword
112
113;
114; ptr to table of emm page # for each handle's logical pages.
115;
116extrn _emm_page:word
117
118;
119; ptr to table of page table entries for the EMM pages
120;
121extrn _pft386:word ; note: actually a dword array
122
123;
124; handle data structure
125;
126extrn _handle_table:word
127extrn _handle_table_size:word
128
129;
130; save area for handles
131;
132extrn _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;
145public __acrtused
146__acrtused label dword
147 dd (0)
148_DATA ENDS
149
150 page
151;******************************************************************************
152; C O D E
153;******************************************************************************
154_TEXT SEGMENT
155assume 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
183sa_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;
225sa_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
257da_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;
299da_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;***********************************************
324destptr = 4
325srcptr = 8
326count = 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;***********************************************
364destptr = 4
365srcptr = 6
366count = 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;***********************************************
409srcptr = 4
410destptr = 6
411count = 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;***********************************************
452srcptr = 4
453destptr = 6
454count = 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;
512vh_exit:
513 pop bx
514 pop bp
515 ret
516vh_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
535public _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;***********************************************
552name1 = 4
553name2 = 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
574Names_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
600SetDescInfoResident 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
618SetDescInfoResident 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
634SegOffTo24Resident 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
648SegOffTo24Resident endp
649
650_TEXT ENDS
651END
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
38HIFLAG = /DNOHIMEM
39#HIFLAG =
40
41# Definitions for assembler
42# (using masm 4.00)
43MASM = masm
44#MASM = \bin\masm400
45#MASM = masm400
46AFLAGS = /Mx /t /DI386 /i..\memm $(HIFLAG)
47AINC = ..\memm\vdmseg.inc ..\memm\vdmsel.inc emmdef.inc
48
49# Definitions for linker for old style .exe files
50#LINK = \bin\link
51LINK = link
52LFLAGS = /NOI /M
53LIBS =
54
55# Definitions for librarian
56#LIB = \bin\lib
57LIB = lib
58
59# Defines for C Compiler
60C = cl
61#C = \bin\msc
62#C = msc
63CFLAGS =/ASw /G2 /Oat /Gs /Ze /Zl /Fc /c
64
65#
66# definition of objects
67#
68OBJS=emmfunct.obj emm40.obj emmp.obj emmsup.obj emmdisp.obj emmdata.obj emminc.obj
69LOBJS=emmfunct.obj+emm40.obj+emmp.obj+emmsup.obj+emmdisp.obj+emmdata.obj
70
71emmlib.lib: $(OBJS)
72 del emmlib.lib
73 $(LIB) emmlib+$(LOBJS),;
74
75emmfunct.obj: emmfunct.c emm.h
76 $(C) $(CFLAGS) emmfunct.c
77
78emm40.obj: emm40.c emm.h
79 $(C) $(CFLAGS) emm40.c
80
81emmp.obj: emmp.asm $(AINC)
82 $(MASM) $(AFLAGS) emmp.asm,emmp.obj,emmp.lst;
83
84emmsup.obj: emmsup.asm $(AINC)
85 $(MASM) $(AFLAGS) emmsup.asm,emmsup.obj,emmsup.lst;
86
87emmdisp.obj: emmdisp.asm $(AINC)
88 $(MASM) $(AFLAGS) emmdisp.asm,emmdisp.obj,emmdisp.lst;
89
90emmdata.obj: emmdata.asm $(AINC)
91 $(MASM) $(AFLAGS) emmdata.asm,emmdata.obj,emmdata.lst;
92
93emminc.obj: emminc.asm $(AINC)
94 $(MASM) $(AFLAGS) emminc.asm,emminc.obj,emminc.lst;
95