summaryrefslogtreecommitdiff
path: root/v4.0/src/MEMM
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
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')
-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
-rw-r--r--v4.0/src/MEMM/MAKEFILE14
-rw-r--r--v4.0/src/MEMM/MEMM/A20TRAP.ASM528
-rw-r--r--v4.0/src/MEMM/MEMM/ALLOCMEM.ASM567
-rw-r--r--v4.0/src/MEMM/MEMM/ASCII_SM.EQU41
-rw-r--r--v4.0/src/MEMM/MEMM/DESC.INC277
-rw-r--r--v4.0/src/MEMM/MEMM/DISP.INC50
-rw-r--r--v4.0/src/MEMM/MEMM/DMA.INC234
-rw-r--r--v4.0/src/MEMM/MEMM/DRIVER.EQU105
-rw-r--r--v4.0/src/MEMM/MEMM/DRIVER.STR129
-rw-r--r--v4.0/src/MEMM/MEMM/EKBD.ASM139
-rw-r--r--v4.0/src/MEMM/MEMM/ELIM.INC128
-rw-r--r--v4.0/src/MEMM/MEMM/ELIMFUNC.ASM268
-rw-r--r--v4.0/src/MEMM/MEMM/ELIMTRAP.ASM1560
-rw-r--r--v4.0/src/MEMM/MEMM/EM286LL.ASM360
-rw-r--r--v4.0/src/MEMM/MEMM/EM386LL.ASM397
-rw-r--r--v4.0/src/MEMM/MEMM/EMM.ASM522
-rw-r--r--v4.0/src/MEMM/MEMM/EMM386.INC49
-rw-r--r--v4.0/src/MEMM/MEMM/EMM386.LNK41
-rw-r--r--v4.0/src/MEMM/MEMM/EMM386D.LNK41
-rw-r--r--v4.0/src/MEMM/MEMM/EMMCOM.LNK5
-rw-r--r--v4.0/src/MEMM/MEMM/EMMINIT.ASM678
-rw-r--r--v4.0/src/MEMM/MEMM/EMMMES.ASM210
-rw-r--r--v4.0/src/MEMM/MEMM/ERRHNDLR.ASM385
-rw-r--r--v4.0/src/MEMM/MEMM/EXTPOOL.ASM187
-rw-r--r--v4.0/src/MEMM/MEMM/I286.ASM312
-rw-r--r--v4.0/src/MEMM/MEMM/I386.ASM240
-rw-r--r--v4.0/src/MEMM/MEMM/INIT.ASM1123
-rw-r--r--v4.0/src/MEMM/MEMM/INITDEB.ASM180
-rw-r--r--v4.0/src/MEMM/MEMM/INITEPG.ASM377
-rw-r--r--v4.0/src/MEMM/MEMM/INITTAB.ASM632
-rw-r--r--v4.0/src/MEMM/MEMM/INSTR386.INC563
-rw-r--r--v4.0/src/MEMM/MEMM/IOTRAP.ASM165
-rw-r--r--v4.0/src/MEMM/MEMM/KBD.ASM1608
-rw-r--r--v4.0/src/MEMM/MEMM/KBD.INC99
-rw-r--r--v4.0/src/MEMM/MEMM/LOADALL.INC173
-rw-r--r--v4.0/src/MEMM/MEMM/MACH_ID.INC38
-rw-r--r--v4.0/src/MEMM/MEMM/MAKEFILE343
-rw-r--r--v4.0/src/MEMM/MEMM/MAPDMA.ASM633
-rw-r--r--v4.0/src/MEMM/MEMM/MAPDMA.C425
-rw-r--r--v4.0/src/MEMM/MEMM/MAPLIN.ASM172
-rw-r--r--v4.0/src/MEMM/MEMM/MEMM386.ASM561
-rw-r--r--v4.0/src/MEMM/MEMM/MEMMCOM.ASM243
-rw-r--r--v4.0/src/MEMM/MEMM/MEMMINC.ASM80
-rw-r--r--v4.0/src/MEMM/MEMM/MEMMONF.ASM337
-rw-r--r--v4.0/src/MEMM/MEMM/MEMM_MSG.INC43
-rw-r--r--v4.0/src/MEMM/MEMM/MOVEB.ASM533
-rw-r--r--v4.0/src/MEMM/MEMM/M_STATE.ASM114
-rw-r--r--v4.0/src/MEMM/MEMM/OEMDEP.INC111
-rw-r--r--v4.0/src/MEMM/MEMM/OEMPROC.ASM1120
-rw-r--r--v4.0/src/MEMM/MEMM/PAGE.INC52
-rw-r--r--v4.0/src/MEMM/MEMM/PIC_DEF.EQU78
-rw-r--r--v4.0/src/MEMM/MEMM/PPAGE.ASM510
-rw-r--r--v4.0/src/MEMM/MEMM/PRINT.ASM424
-rw-r--r--v4.0/src/MEMM/MEMM/RETREAL.ASM228
-rw-r--r--v4.0/src/MEMM/MEMM/ROMSTRUC.EQU37
-rw-r--r--v4.0/src/MEMM/MEMM/ROMXBIOS.EQU45
-rw-r--r--v4.0/src/MEMM/MEMM/ROM_SRCH.ASM317
-rw-r--r--v4.0/src/MEMM/MEMM/RRTRAP.ASM436
-rw-r--r--v4.0/src/MEMM/MEMM/SHIPHI.ASM325
-rw-r--r--v4.0/src/MEMM/MEMM/TABDEF.ASM357
-rw-r--r--v4.0/src/MEMM/MEMM/TRAPDEF.ASM469
-rw-r--r--v4.0/src/MEMM/MEMM/UTIL.ASM335
-rw-r--r--v4.0/src/MEMM/MEMM/VDMINIT.ASM527
-rw-r--r--v4.0/src/MEMM/MEMM/VDMSEG.INC168
-rw-r--r--v4.0/src/MEMM/MEMM/VDMSEL.INC101
-rw-r--r--v4.0/src/MEMM/MEMM/VM386.INC206
-rw-r--r--v4.0/src/MEMM/MEMM/VMINIT.ASM292
-rw-r--r--v4.0/src/MEMM/MEMM/VMINST.ASM2135
-rw-r--r--v4.0/src/MEMM/MEMM/VMTRAP.ASM791
79 files changed, 31239 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/EMM/EMM.H b/v4.0/src/MEMM/EMM/EMM.H
new file mode 100644
index 0000000..24c0974
--- /dev/null
+++ b/v4.0/src/MEMM/EMM/EMM.H
@@ -0,0 +1,223 @@
1/*******************************************************************************
2 *
3 * (C) Copyright Microsoft Corp. 1986
4 *
5 * TITLE: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver
6 * EMMLIB.LIB - Expanded Memory Manager Library
7 *
8 * MODULE: EMM.H - EMM includes for "C" code
9 *
10 * VERSION: 0.04
11 *
12 * DATE: June 14,1986
13 *
14 *******************************************************************************
15 * CHANGE LOG
16 * Date Version Description
17 * -------- -------- -------------------------------------------------------
18 * 06/14/86 Original
19 * 06/14/86 0.00 Changed stack frame structure to match new emmdisp.asm
20 * and allow byte regs access (SBP).
21 * 06/28/86 0.02 Name change from CEMM386 to CEMM (SBP).
22 * 07/06/86 0.04 Changed save area structure (SBP).
23 *
24 ******************************************************************************/
25
26#define OK 0
27#define EMM_SW_MALFUNCTION 0x80
28#define EMM_HW_MALFUNCTION 0x81
29#define INVALID_HANDLE 0x83
30#define INVALID_FUNCTION 0x84
31#define NO_MORE_HANDLES 0x85
32#define SAVED_PAGE_DEALLOC 0x86
33#define NOT_ENOUGH_EXT_MEM 0x87
34#define NOT_ENOUGH_FREE_MEM 0x88
35#define ZERO_PAGES 0x89
36#define LOG_PAGE_RANGE 0x8A
37#define PHYS_PAGE_RANGE 0x8B
38#define SAVE_AREA_FULL 0x8C
39#define MAP_PREV_SAVED 0x8D
40#define NO_MAP_SAVED 0x8E
41#define INVALID_SUBFUNCTION 0x8F
42#define FEATURE_NOT_SUPPORTED 0x91
43#define NAMED_HANDLE_NOT_FOUND 0xA0
44#define DUPLICATE_HANDLE_NAMES 0xA1
45#define ACCESS_DENIED 0xA4
46
47/*
48 * various usefull defines
49 */
50#define PAGE_SIZE 0x1000
51#define NULL_HANDLE (struct handle_ptr *)0x0FFF
52#define NULL_PAGE 0xFFFF
53#define NULL_SAVE (struct save_map *)0
54
55#define GET 0x00 /* get/set page map sub codes */
56#define SET 0x01
57#define GETSET 0x02
58#define SIZE 0x03
59
60#define EMM_VERSION 0x40
61#define Handle_Name_Len 8
62
63/*
64 * defines for INTERNAL vs EXTERNAL current_map save
65 */
66#define INTERNAL_SAVE (unsigned)1
67#define EXTERNAL_SAVE (unsigned)0
68
69/*
70 * page table structure
71 */
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
diff --git a/v4.0/src/MEMM/MAKEFILE b/v4.0/src/MEMM/MAKEFILE
new file mode 100644
index 0000000..e9c4c70
--- /dev/null
+++ b/v4.0/src/MEMM/MAKEFILE
@@ -0,0 +1,14 @@
1#************************* Root level Makefile *************************
2
3make =nmake
4
5all:
6 cd emm
7 $(make)
8 cd ..\memm
9 $(make)
10 cd ..
11
12
13
14
diff --git a/v4.0/src/MEMM/MEMM/A20TRAP.ASM b/v4.0/src/MEMM/MEMM/A20TRAP.ASM
new file mode 100644
index 0000000..2f7f377
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/A20TRAP.ASM
@@ -0,0 +1,528 @@
1
2
3page 58,132
4;******************************************************************************
5 title A20TRAP.ASM - I/O trap handlers for watching the A20 line.
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: A20TRAP.ASM - I/O trap handlers for watching the A20 line.
13;
14; Version: 0.03
15;
16; Date: June 1, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 07/03/86 0.03 From ChkDisA20 routine in VMINST.
27;
28;******************************************************************************
29;
30; Functional Description:
31; This module contains the I/O trap handlers for the A20 line watching
32; logic.
33;
34;
35; COMMENTS: This module displays weaknesses due to carryover from previous
36; sources. A lot of the code here can be shifted to the LAST
37; segment. There is a duplication of routines for getting the a20
38; state. (ISP)
39;******************************************************************************
40.lfcond ; list false conditionals
41.386p
42 page
43;******************************************************************************
44; P U B L I C D E C L A R A T I O N S
45;******************************************************************************
46;
47 public A20_Handler
48 public A20_Trap_Init
49 public EnableA20
50 public DisableA20
51 public togl_A20
52 public get_a20_state
53 public estb_a20_state
54 public get_init_a20_state
55
56
57;
58;******************************************************************************
59; E X T E R N A L R E F E R E N C E S
60;******************************************************************************
61 include VDMseg.inc
62 include VDMsel.inc
63;
64_DATA segment
65; (none)
66_DATA ends
67
68_TEXT segment
69
70 extrn PortTrap:near
71
72_TEXT ends
73 page
74;******************************************************************************
75; L O C A L C O N S T A N T S
76;******************************************************************************
77;
78FALSE equ 0
79TRUE equ not FALSE
80
81YesLLdone equ 1
82KbdDataEnb equ 2
83
84A20CmdBit equ 02h ; high is enabled
85A20DsbCmd equ 0DDh
86A20EnbCmd equ 0DFh
87
88KbdCmdPort equ 64h ; 8042 cmd port
89KbdWrtData equ 0D1h ; Enable write to data port
90KbdDataPort equ 60h ; 8042 data port
91KbdStatusPort equ 64h ; 8042 cmd port
92KbdBufFull equ 2 ; Buffer bull(data not received) status
93
94; equates for the state_a20 flag
95
96A20_ON equ A20CmdBit ;
97A20_OFF equ 0 ;
98;
99; equate for the bit which will toggle the state of
100;
101WRAP_BIT equ 00100000h ; page table entry bit
102;
103;******************************************************************************
104; S E G M E N T D E F I N I T I O N
105;******************************************************************************
106;
107
108;
109; _DATA segment
110;
111_DATA segment
112
113KbdComd db 0 ; last CMD written to port 64h
114state_a20 db 0 ; A20 line state: A20_ON is on, A20_OFF is off
115
116_DATA ends
117
118;
119 page
120;------------------------------------------------------------------------------
121_TEXT segment
122 assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP
123;
124;******************************************************************************
125; L O C A L D A T A A R E A
126;******************************************************************************
127;
128
129;******************************************************************************
130; A20_Handler - I/O trap handler for Address line 20 modification
131;
132; ENTRY: Protected Mode Ring 0
133; AL = byte to output to port.
134; BX == 2 * port address(either KbdDataPort or KbdCmdPort)
135; DX == 0 => Emulate input
136; <> 0 => Emulate output
137; DS = DGROUP
138; SS:BP = points to stack frame on entry to GP fault handler
139;
140; EXIT:
141; CLC => I/O emulated.
142; STC => I/O NOT emulated.
143;
144; USED: BX,Flags
145; STACK:
146;------------------------------------------------------------------------------
147A20_Handler proc near
148 or dx,dx ;Q: Output ?
149 jnz A20_Write ; Y: check for write to output port
150 stc ; N: don't bother to emulate it
151 ret
152A20_Write:
153 cmp bx,KbdDataPort*2 ;Q: Keyboard data port?
154 jne Kbd_C_Handler ; N: Go handle Kybd Command output
155 ; Y: Go handle Kybd Data output
156
157; keyboard data write
158Kbd_D_Dwrite:
159 cmp [KbdComd],KbdWrtData ;Q: write to output port?
160 mov [KbdComd],0 ; data port write => no CMD
161 je Kbd_D_out ; Y: filter client's data
162 stc ; N: don't bother to emulate it
163 ret
164;
165; here if Output Port write
166;
167Kbd_D_out:
168 push ax ; Set A20 cmd bit
169 call check_a20_togl ; do we need to toggle the
170 ; the a20 state
171 jz skip_togl ; N: Skip routine to toggle
172 call togl_a20
173skip_togl:
174 or al, A20CmdBit ; to leave A20 enabled
175 out KbdDataPort,al ; "emulate" it
176 pop ax ; restore client's byte
177 clc ; emulated
178 ret
179
180;Output to Keyboard command port
181Kbd_C_Handler:
182;
183 mov [KbdComd],al ; Y: save new port 64 byte
184 stc ; don't bother to emulate it
185 ret
186;
187A20_Handler endp
188
189
190;******************************************************************************
191; A20_Trap_Init - turn on I/O bit map trapping for A20 line watching
192;
193; ENTRY: DS -> DGROUP - real,virtual, or protected mode
194; ES -> TSS segment
195; IOTrap_Tab already has address of A20_Handler for KbdDataPort and
196; KbdCmdPort
197;
198; EXIT: IO_BitMap Updated to trap ports used to change A20 line
199;
200; USED: AX,Flags
201; STACK:
202;------------------------------------------------------------------------------
203A20_Trap_Init proc near
204;
205; reset flag
206;
207 mov [KbdComd],0
208;
209; Set IOBM traps to look for client's disabling of the A20 line
210;
211 mov bh, 80h ; set every 1k
212 mov ax, KbdDataPort
213 call PortTrap ; set traps on keyboard ports
214 mov ax, KbdCmdPort ; in case client
215 call PortTrap ; tries to disable A20
216 ret
217;
218A20_Trap_Init endp
219;
220;*****************************************************************************;
221;*** EnableA20 - switch 20th address line ;
222; ;
223; This routine is used to enable the 20th address line in ;
224; the system. ;
225; ;
226; In general when in real mode we want the A20 line disabled, ;
227; when in protected mode enabled. However if there is no high ;
228; memory installed we can optimise out unnecessary switching ;
229; of the A20 line. Unfortunately the PC/AT ROM does not allow ;
230; us to completely decouple mode switching the 286 from gating ;
231; the A20 line. ;
232; ;
233; In real mode we would want A20 enabled if we need to access ;
234; high memory, for example in a device driver. We want it ;
235; disabled while running arbitrary applications because they ;
236; may rely on the 1 meg address wrap feature which having the ;
237; A20 line off provides. ;
238; ;
239; This code is largely duplicated from the PC/AT ROM BIOS. ;
240; See Module "BIOS1" on page 5-155 of the PC/AT tech ref. ;
241; ;
242; ENTRY none ;ds = DGROUP ;
243; EXIT A20 line enabled ;
244; USES ax, flags modified ;
245; ;
246; WARNING: ;
247; ;
248; The performance characteristics of these routines ;
249; are not well understood. There may be worst case ;
250; scenarios where the routine could take a relatively ;
251; long time to complete. ;
252; ;
253; TO BE ADDED: ;
254; ;
255; 8042 error handling ;
256;*****************************************************************************;
257EnableA20 proc near
258 mov ah,0dfh ; code for enable
259 jmp a20common ; jump to common code
260
261EnableA20 endp
262
263;*****************************************************************************;
264;*** DisableA20 - switch 20th address line ;
265; ;
266; This routine is used to disable the 20th address line in ;
267; the system. ;
268; ;
269; ENTRY none ;ds = DATA ;
270; EXIT A20 line disabled ;
271; [state_a20] = 0 ;
272; USES ax, flags modified ;
273;*****************************************************************************;
274
275DisableA20 proc near
276 mov ah,0ddh ; code for disable
277 jmp a20common ; jump to common code
278
279DisableA20 endp
280
281
282a20common proc near
283
284; This is entered via a jmp from one of the two procedural
285; entry points above.
286
287 call empty_8042 ; ensure 8042 input buffer empty
288 jnz com1 ; 8042 error return
289 mov al,0d1h ; 8042 cmd to write output port
290 out KbdCmdPort,al ; send cmd to 8042
291 call empty_8042 ; wait for 8042 to accept cmd
292 jnz com1 ; 8042 error return
293 mov al,ah ; 8042 port data
294 out KbdDataPort,al ; output port data to 8042
295 call empty_8042
296;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
297;
298; AST P/386 needs the delay for their
299; A20 switch settle. If not, it won't work !
300; PC (10/03/88)
301;
302 push cx
303 mov cx, 0100h
304ASTloop:
305 loop ASTloop
306 pop cx
307;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
308
309com1:
310 ret
311a20common endp
312
313;*****************************************************************************;
314;*** empty_8042 - wait for 8042 input buffer to drain ;
315; ;
316; ENTRY none ;
317; EXIT al=0, z=0 => 8042 input buffer empty ;
318; al=2, z=1 => timeout, input buffer full ;
319; USES none ;
320;*****************************************************************************;
321empty_8042 proc near
322 push cx ; save it
323 sub cx,cx ; cx = 0, timeout loop counter
324emp1:
325 in al,KbdStatusPort ; read 8042 status port
326 and al,KbdBufFull ; test buffer full bit
327 loopnz emp1
328 pop cx
329 ret
330empty_8042 endp
331
332;*****************************************************************************;
333;*** check_a20_togl - check if a20 state emulated needs to be toggled ;
334; ;
335; ENTRY [state_a20] = A20 emulated state ;
336; al = byte to output to kbd data port ;
337; EXIT Z set if A20 not to be toggled ;
338; clear if A20 to be toggled ;
339; USES Flags ;
340; ;
341;*****************************************************************************;
342check_a20_togl proc near
343;
344 push ax
345 and al,A20CmdBit ; make all other bits 0
346 xor al,[state_a20] ; does the state of the a20 bit match
347 ; Y: then Z is set
348 ; N: then Z is not set
349 pop ax
350 ret
351;
352check_a20_togl endp
353
354
355;*****************************************************************************;
356;*** get_a20_state - see if virtualised a20 is enabled or not ;
357; ;
358; ENTRY [state_a20] = A20 emulated state ;
359; ;
360; EXIT ZF set if A20 disabled ;
361; ZF not set if A20 enabled ;
362; ;
363; USES Flags ;
364;*****************************************************************************;
365
366get_a20_state proc near
367;
368 test [state_a20], A20_ON
369 ret
370get_a20_state endp
371
372
373;*****************************************************************************;
374;*** togl_A20 - toggle emulated A20 state. ;
375; ;
376; ENTRY [state_a20] = A20 emulated state ;
377; PROTECTED MODE ONLY ;
378; DS:DGROUP ;
379; ;
380; EXIT [state_a20] toggled ;
381; page table entries for the 1M --> 1M + 64k area toggled ;
382; ;
383; USES Flags ;
384; ;
385; ;
386;*****************************************************************************;
387togl_A20 proc near
388;
389 push es
390 push di
391 push cx
392 push eax
393;
394; get addressability to page table
395;
396 push PAGET_GSEL
397 pop es
398;
399; and offset into entries for the 64k block at 1M
400;
401 mov di,100h*4 ; 1024k/4k = 256 entries, each 4 bytes long
402 mov cx,10h ; 64k/4k = 16 entries
403 cld
404;
405; for all the entries flip the bit which will make the entries either wrap
406; around for 1M-1M+64k to either 1M-1M+64k or 0-64k. This bit is the 1M bit
407; in the base address.
408;
409w64_loop:
410 xor dword ptr es:[di], WRAP_BIT
411 add di,4
412 loop w64_loop
413;
414; flush the tlb
415;
416 mov eax,cr3
417 mov cr3,eax
418;
419; toggle a20 state
420;
421 xor [state_a20],A20_ON
422;
423; restore the registers
424;
425 pop eax
426 pop cx
427 pop di
428 pop es
429 ret
430;
431togl_A20 endp
432
433
434
435_TEXT ends ; end of segment
436
437LAST segment
438
439 assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP
440
441
442;******************************************************************************
443;***estb_a20_state ;
444; ;
445; since we are fixing the a20 state to be always enabled we need to implement ;
446; a logical a20 state independent of the physical one. this routine inits ;
447; this state. we do this comparing 3 double words at 0:80 and 1M:80. if these;
448; compare the a20 is disabled thus causing a wraparound. ;
449; ;
450; INPUTS: ;
451; ;
452; OUTPUTS: [state_a20] .. A20_ON if a20 is on currently ;
453; .. A20_OFF if a20 is off currently ;
454; ;
455; USES: flags ;
456; ;
457; AUTHOR: ISP. Shifted in from smartdrv sources. 8/29/88. ;
458; ;
459;*****************************************************************************;
460; A20 address line state determination addresses
461;
462 low_mem label dword
463 dw 20h*4
464 dw 0
465
466 high_mem label dword
467 dw 20h*4 + 10h
468 dw 0ffffh
469
470estb_a20_state proc near
471 push cx
472 push ds
473 push es
474 push si
475 push di
476 ;
477 ; initialise a20 to off
478 ;
479 mov [state_a20],A20_OFF
480 ;
481 ; compare 3 dwords at 0:80h and 1M:80h. if these are equal then
482 ; we can assume that a20 is off
483 ;
484 lds si,cs:low_mem
485 ASSUME DS:NOTHING
486 les di,cs:high_mem
487 ASSUME ES:NOTHING
488 mov cx,3
489 cld
490repe cmpsd
491 pop di
492 pop si
493 pop es
494 pop ds
495 ASSUME DS:DGROUP,ES:DGROUP
496 jcxz not_enabled
497 ;
498 ; a20 is on
499 ;
500 mov [state_a20],A20_ON
501not_enabled:
502 pop cx
503 ret
504estb_a20_state endp
505
506;*****************************************************************************;
507;*** get_init_a20_state - see if virtualised a20 is enabled or not ;
508; ;
509; ENTRY [state_a20] = A20 state at startup ;
510; ;
511; EXIT ZF set if A20 disabled ;
512; ZF not set if A20 enabled ;
513; ;
514; USES Flags ;
515;*****************************************************************************;
516
517 ASSUME DS:DGROUP,ES:NOTHING
518
519get_init_a20_state proc near
520;
521 test [state_a20], A20_ON
522 ret
523get_init_a20_state endp
524
525LAST ends
526
527 end ; end of module
528 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM b/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM
new file mode 100644
index 0000000..430f849
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM
@@ -0,0 +1,567 @@
1
2
3 page 58,132
4;******************************************************************************
5 title ALLOCMEM - allocate memory for EMM Pages Pool
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: AllocMem - allocate memory for EMM Pages Pool
13;
14; Version: 0.05
15;
16; Date: May 24,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 05/24/86 Original
27; 06/28/86 0.02 code read changes to various routines
28; 07/05/86 0.04 Changes due to segment re-org
29; 07/06/86 0.04 Made EXT_RES a define
30; 07/06/86 0.04 Changed to DGROUP assume
31; 07/10/86 0.05 added NOHIMEM flag
32; 06/02/88 pc change from VDISK allocation to INT-15 method
33; 07/26/88 isp completed work in changing over to int15 alloc
34;
35;******************************************************************************
36; Functional Description:
37; This module allocates the pool of memory to be used for the pool of
38; EMM pages. The pool of memory is allocated from "high" extended
39; memory (located in the 15-16 Meg range)and from "regular" extended memory
40; (starting at 1 Meg). This module attempts to allocate high memory first,
41; then extended memory. When allocating memory from either area, the memory
42; is allocated in 16k byte blocks which are aligned on a physical 4k boundary.
43; This module attempts to allocate extended memory using the int15 allocation
44; scheme.
45;
46; NOTE: if this module is compiled with NOHIMEM defined, then
47; this code will not attempt to use the OEM specific
48; "high" memory.
49;
50;******************************************************************************
51.lfcond
52.386p
53;
54;
55;******************************************************************************
56; P U B L I C D E C L A R A T I O N S
57;******************************************************************************
58;
59 public AllocMem
60 public DeallocMem
61 public xbase_addr_l ; data publics
62 public xbase_addr_h
63 public ext_size
64 public sys_size
65
66 page
67;******************************************************************************
68; L O C A L C O N S T A N T S
69;******************************************************************************
70;
71 include vdmseg.inc
72 include vdmsel.inc
73 include emm386.inc
74 include driver.equ
75 include driver.str
76 include romxbios.equ
77 include desc.inc
78 include ascii_sm.equ
79 include oemdep.inc
80 include emmdef.inc
81;
82EXT_RES equ 10h ; must be a power of 2.
83;
84GET_VER equ 30h ; get dos version number
85MSDOS equ 21h ; DOS interrupt
86;
87FALSE equ 0
88TRUE equ not FALSE
89
90;******************************************************************************
91; E X T E R N A L R E F E R E N C E S
92;******************************************************************************
93;
94_DATA segment
95
96 extrn dos_version:byte
97 extrn pool_size:word
98 extrn msg_flag:word
99
100ifndef NOHIMEM
101 extrn hi_size:word ; size of hi memory in kbytes
102 extrn hi_alloc:word ; hi memory allocated
103 extrn hisys_alloc:word ; hi system memory allocated
104 ; in 4k byte blocks
105endif
106
107_DATA ends
108
109
110LAST segment
111 extrn mappable_segs:byte ; mappable segment map
112 extrn set_ext:near ; routine to set amount of ext mem
113 ; reported by int15 handler
114 extrn memreq:near ; memory requirements for move
115 extrn pool_initialise:near ; initialise the pool of extended
116 ; memory
117
118ifndef NOHIMEM
119 extrn hbuf_chk:near
120 extrn HiAlloc:near
121 extrn HiMod:near
122endif
123LAST ends
124;
125 page
126;******************************************************************************
127; S E G M E N T D E F I N I T I O N
128;******************************************************************************
129
130 page
131;******************************************************************************
132; Data segment
133;******************************************************************************
134_DATA segment
135 ASSUME CS:DGROUP,DS:DGROUP
136
137xbase_addr_l dw 0000h ; 24 bit address of beginning of
138xbase_addr_h db 10h ; extended mem pool of EMM pages. (1M initially)
139ext_size dw 0 ; size of extended memory allocated in kb
140sys_size dw 0 ; size of system memory from 4000h in emm pool
141total_mem dw 0 ; size of extended memory available at any moment
142avail_mem dw 0 ; total size (hi+ext) available for MEMM
143;
144
145_DATA ends
146
147
148;******************************************************************************
149;
150; Code Segment
151;
152;******************************************************************************
153;
154LAST segment
155 assume cs:LAST, ds:DGROUP, es:DGROUP
156
157 page
158;******************************************************************************
159;
160; AllocMem Allocate Extended memory for MEMM using the int15
161; method of allocating extended memory.
162;
163; description:
164; This routine attempts to get the requested extended memory
165; from two sources: a) the himem area (just below 16M) first
166; and if not enough b) extended memory. Extended memory is
167; allocated using the int15 scheme. We do not care for
168; compatibility with vdisk. The memory we allocate either in
169; himem area or in extended memory must start at a 4k boundary
170; because we are using them as pages.
171;
172; entry: DS pts to DGROUP
173; DGROUP:[pool_size] = mem size requested (kbytes)
174;
175; exit: If extended memory pool space is not available then
176; set MEM_ERR_MSG bit in DGROUP:[msg_flag] and exit.
177;
178;
179; used: none
180;
181; stack:
182;
183; modified: ISP 07/26/88 Changed to a simple check for availability
184; of hi / ext memory and allocation of
185; of appropriate amounts of each.
186;
187;
188;******************************************************************************
189;
190AllocMem proc near
191;
192 push ax
193 push bx
194 push cx
195 push dx
196 push es
197
198
199;
200; 1. Check available hi/extended memory
201;
202AM_getmem:
203 call xbuf_chk
204 test [msg_flag],MEM_ERR_MSG ;Q: memory error found ?
205 jz AM_nba ; N: continue with allocation
206 jmp AM_exit ; Y: exit
207;
208; 2. Allocate extended memory
209;
210AM_nba:
211 call ExtAlloc ; alloc ext mem
212
213ifndef NOHIMEM ; if HI memory in this model
214;
215; 3. Allocate Hi memory
216;
217AM_halloc:
218 call HiAlloc ; Allocate hi memory
219 jnc AM_exit ; no error
220 or [msg_flag],MEM_ERR_MSG ; memory error
221endif
222
223;
224; 4. Allocate system memory
225;
226 call SysAlloc
227;
228AM_exit:
229 pop es
230 pop dx
231 pop cx
232 pop bx
233 pop ax
234 ret
235AllocMem endp ; End of procedure
236;
237 page
238;******************************************************************************
239;
240; DeallocMem Deallocate Extended memory for MEMM using the int15
241; method of allocating extended memory. Note that since
242; we call this routine when we haven't already installed tc.)
243; the int15 handler we really don't need to do anything
244; as far as the regular extended memory is concerned. We
245; only need to deallocate hi memory if allocated.
246;
247; entry: DS pts to DGROUP
248; DGROUP:[hi_alloc] amount of hi memory to deallocate
249;
250; used: none
251;
252; stack:
253;
254; modif: 7/26/88 ISP Removed VDISK deallocation of extended memory
255;******************************************************************************
256;
257DeallocMem proc near
258 push ax
259 push bx
260 push cx
261 push dx
262 push si
263 push es
264;
265ifndef NOHIMEM ; if high memory in this model
266 mov ax,[hi_alloc] ; get hi memory to deallocate
267 or ax,ax ; q: did we ever get any?
268 jz deall_hisys ; n: check hi system memory
269 neg ax ; # of 16 byte pieces to remove
270 mov [hi_alloc],0 ; make sure we never do it again
271deall_hisys:
272 mov bx,[hisys_alloc] ; get hi system memory to deallocate
273 neg bx ; update by a negative amount
274 add bx,ax ; q: any hi or hisys to deallocate?
275 jz deall_ext ; n: don't waste our time doing it
276 sub bx,ax ; y: straighten our regs out
277 mov [hisys_alloc],0 ; make sure we don't do it again
278 call HImod ; modify memory. ignore any errors
279deall_ext:
280;
281endif ; end of conditional
282 pop es
283 pop si
284 pop dx
285 pop cx
286 pop bx
287 pop ax
288;
289 ret
290DeallocMem endp
291;
292 page
293;******************************************************************************
294;
295; xbuf_chk Extended memory pool check.
296; Check 1) for previously loaded MEMM,VDISKs in extended memory
297; 2) available memory pool space. (hi memory and extended)
298;
299; entry: DS = DGROUP
300; DGROUP:[pool_size] = mem size requested (kbytes)
301;
302;
303; exit: If hi memory pool space is available then
304;
305; DGROUP:[hi_size] = hi memory size allocated (kbytes).
306;
307; If extended memory pool space is necessary and available then
308;
309; DGROUP:[xbase_addr_h] and DGROUP:[xbase_addr_l] contain the
310; starting 24-bit address of MEMM extended memory pool.
311;
312; DGROUP:[pool_size] = mem size ALLOCATED (kbytes)
313; DGROUP:[total_mem] = total extended memory left after allocation
314; DGROUP:[avail_mem] = available memory for MEMM.
315; DGROUP:[ext_size] = extended memory size allocated (kbytes)
316;
317; If hi/extended memory pool space is not available then
318; set MEM_ERR_MSG bit in DGROUP:[msg_flag] and exit.
319;
320; used: none
321;
322; stack:
323;
324; modified: ISP 07/26/88 int15 allocation requires different check
325; on extended memory. substancial rewrite.
326;******************************************************************************
327;
328xbuf_chk proc near
329;
330 push ax
331 push bx
332 push cx
333 push dx
334 push di
335;
336; determine amount of extended memory and store it in total_mem
337;
338 mov ah,EXT_MEM ; function request - ext mem data
339 clc ; clear carry flag
340 int XBIOS ;Q: extended memory supported ?
341;
342 jnc store_ext ; Y: go to store the amount got
343 xor ax,ax ; N: Assume zero extended memory
344store_ext:
345 mov [total_mem],ax
346;
347ifndef NOHIMEM ; if high memory in this model
348;
349; check for hi memory
350;
351 call hbuf_chk ; get available hi memory in AX
352 jc xb_NoHiMem
353 mov [hi_size],ax ; save it
354 mov [avail_mem],ax ; update available memory
355xb_NoHiMem:
356 mov ax,[pool_size]
357 cmp ax,[hi_size] ; q: enough?
358 ja get_ext ; n: try extended memory
359 mov [hi_size],ax ; y: just use enough
360 jmp x_buf_exit ; and exit
361endif
362
363get_ext:
364 mov ax,[total_mem] ; get size of extended memory available
365 ; Y: how much there ?
366;
367; we have to reserve enough memory here to ship the segments up hi.
368;
369 call memreq ; get memory requirements for our o
370 ; our grand operation in cx in K
371 cmp ax,cx ; lets see if we can satisfy
372 jbe x_buf_no_install ; if not we shan't install memm
373
374 push ax
375 sub ax,cx
376 cmp ax,64 + 64 ; we should try to leave enough memory
377 ; for himem and atleast four pages of
378 ; expanded memory.
379 pop ax
380 jbe x_buf_no_install ; if we don't have enough for this we
381 ; shouldn't install memm
382 ;
383 ; we can now get memory to shift things up. and intialise the manager of
384 ; this pool.
385 ;
386 sub ax,cx ; ax = start of this pool as an offset
387 ; in K from 1M
388 ; cx = size in K of this pool
389 call pool_initialise ; intialise the pool
390 or ax,ax ;Q: any extended memory ?
391 jz x_buf_2 ; N: If none go to set buf adj or no
392 ; memory error
393; ; Y: continue to process
394;
395 mov bx,[pool_size] ; get size requested
396;
397ifndef NOHIMEM ; if high memory in this model
398 sub bx,[hi_size] ; adjust by the size already allocated
399endif ; from the high memory
400
401 and ax,0fff0h ; round to 16k boundary
402;
403; it is necessary to support himem. So if we have a 64k block at 1M we
404; should leave it for himem. The himem we are talking about here is the
405; EMS 4.1 standard himem at 1M
406 ;
407 ; initialise reserved memory for himem
408 ;
409 xor cx,cx ; amount reserved for himem
410 ;
411 ; see if we have 64k available for himem
412 ;
413 cmp ax,64 ; Q:do we have 64k?
414 jb no_himem_alloc ; N: we reserve nothing for himem
415 ; Y: we should reserve 64k for himem
416 ;
417 ; reserve 64k for himem
418 ;
419 mov cx,64
420 sub ax,cx
421 ;
422no_himem_alloc:
423 ;
424 cmp ax,bx ; compare amount available to size needed
425 jae enough_mem ; Y: fine
426 mov bx,ax ; N: adjust size reuested to size avail
427enough_mem:
428 ;
429 ; add back the memory reserved for himem as this figures in the size of
430 ; free extended memory
431 ;
432 add ax,cx ; adjust size to include amnt res. himem
433 sub ax,bx ; adjust the size of extended memory
434 ; after allocation
435 mov [total_mem],ax ; store size of extended mem available
436;
437 add [avail_mem],bx ; add memory available to memory pool
438 mov [ext_size],bx ; and indicate size allocated
439;
440; find the start address of extended memory allocated
441;
442 mov cx,1024 ; kb multiplier
443 mul cx ; dx:ax = ax*cx
444 add [xbase_addr_l],ax ; adjsut starting address of allocated mem
445 adc [xbase_addr_h],dl ; higher byte of 24 bit address
446;
447x_buf_2:
448;
449 mov ax,[avail_mem] ; ax == Available memory
450 cmp ax,[pool_size] ; Q: Extended memory available?
451 jnb x_buf_exit ; Y: Go to finish
452;
453not_enough:
454 or ax,ax ; Q: Any extended memory available?
455 jz x_buf_no_install ; N: Set error flag and exit
456 mov [pool_size],ax ; Y: Set pool_size to remaining memory
457 or [msg_flag],SIZE_ADJ_MSG ; Set buffer adjusted message bit
458 jmp short x_buf_exit ; And jump to exit
459;
460x_buf_no_install:
461 or [msg_flag],MEM_ERR_MSG ; memory error found in x_bufchk
462;
463x_buf_exit:
464 pop di
465 pop dx
466 pop cx
467 pop bx
468 pop ax
469 ret ; *** return ***
470;
471xbuf_chk endp
472;
473 page
474;******************************************************************************
475;
476; ExtAlloc - allocate extended memory - update break address for ext. mem.
477;
478; entry: DS pts to DGROUP
479;
480; exit: extended memory size
481;
482; used: none. int15 size reported by int 15 handler in MEMM adjusted.
483;
484; stack:
485;
486; modified: ISP 07/26/88 Substancially simplified. For int15 scheme
487; allocation is by lowering the size of int15
488; reported extended memory size.
489;
490;******************************************************************************
491ExtAlloc proc near
492;
493 mov bx,[total_mem] ;size left after allocation to MEMM
494 call set_ext ; set this size in the int15 handler
495 ret
496;
497ExtAlloc endp
498;
499;******************************************************************************
500;
501; SysAlloc - allocate extended memory - update break address for ext. mem.
502;
503; entry: DS pts to DGROUP
504;
505; exit: system memory size
506;
507; used: none.
508;
509; stack:
510;
511; written: ISP 07/28/88 This allocates the system memory from 0000H
512; to A000h to the EMM pool. This is for the LIM
513; 4.0 implementation.
514;
515;******************************************************************************
516
517SysAlloc proc near
518;
519 push ax
520 push bx
521 push cx
522;
523; find end of memory reported by bios int 12 and round this to upper 16k.
524;
525 int 12h
526 add ax,0000fh ;
527 and ax,0fff0h ; round it 16k figure
528;
529; convert this to the a page #
530;
531 shr ax, 4 ; number of 16k pages
532;
533; start search for pages which can be reclaimed from the system mem. region
534;
535 mov cx,ax ; number of pages from pg0 to be examined
536 mov [sys_size],0 ; initialise the system memory allocate
537 xor bx,bx ; page #
538
539 jcxz find_sys_done
540find_sys_page:
541 cmp cs:mappable_segs[bx], PAGE_MAPPABLE
542 jne find_next_sys
543 add [sys_size],16 ; page found add 16k to system mem size
544find_next_sys:
545 inc bx
546 loop find_sys_page
547find_sys_done:
548
549 mov ax,[sys_size] ; find the total memory found
550 add [pool_size],ax ; add this to the pool size
551
552;
553 pop cx
554 pop bx
555 pop ax
556 ret
557
558SysAlloc endp
559
560
561
562LAST ends ; End of segment
563;
564 end ; End of module
565
566
567 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/ASCII_SM.EQU b/v4.0/src/MEMM/MEMM/ASCII_SM.EQU
new file mode 100644
index 0000000..c4f656b
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ASCII_SM.EQU
@@ -0,0 +1,41 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: ASCII_SM.EQU - ASCII (1968) control characters (small version)
10;
11; Version: 0.02
12;
13; Date: June 25,1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 06/25/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25;
26;******************************************************************************
27ifndef INC_LIST
28.xlist
29endif
30NUL equ 0 ; 00 ^@ Null
31BEL equ 7 ; 07 ^G Bell
32BS equ 8 ; 08 ^H Backspace
33TAB equ 9 ; 09 ^I (Horizontal) Tab
34LF equ 10 ; 0A ^J Line Feed
35FF equ 12 ; 0C ^L Form Feed
36CR equ 13 ; 0D ^M Carriage Return
37ASCII_ESC equ 27 ; 1B ^[ Escape
38SPACE equ 32 ; 20 Space
39DEL equ 127 ; 7F Delete/Rubout
40
41.list ; end of ASCII_SM.EQU
diff --git a/v4.0/src/MEMM/MEMM/DESC.INC b/v4.0/src/MEMM/MEMM/DESC.INC
new file mode 100644
index 0000000..229fccb
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/DESC.INC
@@ -0,0 +1,277 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: DESC.INC - Descriptor Table Definitions for 286/386
10;
11; Version: 0.02
12;
13; Date: January 31, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 01/31/86 Original
24; 04/07/86 A added bit map base to 386 TSS
25; 05/12/86 B Cleanup and segment reorganization
26; 06/25/86 0.02 removed A0 macros
27; 06/28/86 0.02 Name change from MEMM386 to MEMM
28;
29;******************************************************************************
30ifndef INC_LIST
31.xlist
32endif
33
34; ---------------------------------------------------
35;
36; Definitions for the access byte in a descriptor
37;
38; ---------------------------------------------------
39
40
41; Following fields are common to segment and control descriptors
42
43D_PRES equ 080h ; present in memory
44D_NOTPRES equ 0 ; not present in memory
45
46D_DPL0 equ 0 ; Ring 0
47D_DPL1 equ 020h ; Ring 1
48D_DPL2 equ 040h ; Ring 2
49D_DPL3 equ 060h ; Ring 3
50
51D_SEG equ 010h ; Segment descriptor
52D_CTRL equ 0 ; Control descriptor
53
54
55; Following fields are specific to control descriptors
56
57D_TSS equ 01h ; A Free TSS
58D_LDT equ 02h ; LDT
59D_TSS_BUSY equ 03h ; A Busy TSS
60D_CALLGATE equ 04h ; call gate
61D_TASKGATE equ 05h ; task gate
62D_INTGATE equ 06h ; interrupt gate
63D_TRAPGATE equ 07h ; trap gate
64 ; 8 is invalid
65D_386TSS equ 9 ; available 386 TSS
66 ; 0ah - Intel Reserved
67D_BUSY386TSS equ 0bh ; busy 386 TSS
68D_386CALL_GATE equ 0ch ; 386 call gate
69 ; 0dh - Intel Reserved
70D_386INT_GATE equ 0eh ; 386 interrupt gate
71D_386TRAP_GATE equ 0fh ; 386 trap gate
72
73; Following fields are specific to segment descriptors
74
75D_CODE equ 08h ; code
76D_DATA equ 0 ; data
77
78D_CONFORM equ 04h ; if code, conforming
79D_EXPDN equ 04h ; if data, expand down
80
81D_RX equ 02h ; if code, readable
82D_X equ 0 ; if code, exec only
83D_W equ 02h ; if data, writable
84D_R equ 0 ; if data, read only
85
86D_ACCESSED equ 1 ; segment accessed bit
87
88
89; Useful combination access rights bytes
90
91D_DATA0 equ (D_PRES+D_DPL0+D_SEG+D_DATA+D_W) ; Ring 0 rw data
92D_CODE0 equ (D_PRES+D_DPL0+D_SEG+D_CODE+D_RX) ; Ring 0 rx code
93D_TRAP0 equ (D_PRES+D_DPL0+D_CTRL+D_TRAPGATE) ; Ring 0 trap gate
94D_INT0 equ (D_PRES+D_DPL0+D_CTRL+D_INTGATE) ; Ring 0 int gate
95D_TSS0 equ (D_PRES+D_DPL0+D_CTRL+D_TSS) ; Ring 0 TSS
96D_386TSS0 equ (D_PRES+D_DPL0+D_CTRL+D_386TSS) ; Ring 0 TSS
97D_LDT0 equ (D_PRES+D_DPL0+D_CTRL+D_LDT) ; Ring 0 LDT
98D_386INT0 equ (D_PRES+D_DPL0+D_CTRL+D_386INT_GATE) ; Ring 0 int gate
99
100;D_DATA1 equ (D_PRES+D_DPL1+D_SEG+D_DATA+D_W) ; Ring 1 rw data
101;D_CODE1 equ (D_PRES+D_DPL1+D_SEG+D_CODE+D_RX) ; Ring 1 rx code
102
103;D_DATA2 equ (D_PRES+D_DPL2+D_SEG+D_DATA+D_W) ; Ring 2 rw data
104;D_CODE2 equ (D_PRES+D_DPL2+D_SEG+D_CODE+D_RX) ; Ring 2 rx code
105
106D_DATA3 equ (D_PRES+D_DPL3+D_SEG+D_DATA+D_W) ; Ring 3 rw data
107D_CODE3 equ (D_PRES+D_DPL3+D_SEG+D_CODE+D_RX) ; Ring 3 rx code
108D_INT3 equ (D_PRES+D_DPL3+D_CTRL+D_INTGATE) ; Ring 3 int gate
109D_GATE3 equ (D_PRES+D_DPL3+D_CTRL+D_CALLGATE) ; Ring 3 call gate
110D_386INT3 equ (D_PRES+D_DPL3+D_CTRL+D_386INT_GATE) ; Ring 3 int gate
111
112; 386 Extensions
113
114D_B_BIT equ (1 SHL 6) ; 32 bit stack offsets
115
116
117; Masks for selector fields
118
119SELECTOR_MASK equ 0fff8h ; selector index
120SEL_LOW_MASK equ 0f8h ; mask for low byte of sel indx
121TABLE_MASK equ 04h ; table bit
122RPL_MASK equ 03h ; privilige bits
123RPL_CLR equ not 03h ; clear ring bits
124
125
126; Machine Status Word bits
127
128MSW_PROTECT equ 1 ; virtual mode bit
129
130
131; System IOPL
132
133SYS_IOPL equ 3000h ; wide open
134CLEAR_IOPL equ 0cfffh ; mask to remove IOPL bits
135
136
137; Kernel Stack Size (TO BE ADDED)
138
139STK_SIZE equ 4000h ; TO BE ADDED
140
141
142; --------------------------------------------------
143;
144; Macros for creating descriptor table entries
145;
146; --------------------------------------------------
147
148
149
150; structure for 386 descriptor
151
152desc struc
153LIMIT dw 0 ; offset of last byte in segment
154BASE_LOW dw 0 ; Low 16 bits of 24 bit base address
155BASE_HIGH db 0 ; High 8 bits of 24 bit base address
156RIGHTS db 0 ; access rights
157RES386 db 0 ; reserved for 386
158BASE_XHI db 0 ; High 8 bits of 32 bit base address
159desc ends
160
161; MASK for RES386
162
163R_GRAN equ 10000000b ; granularity bit
164R_AVL equ 00010000b ; available
165R_LIMIT_XHI equ 00001111b ; limit bits 16..19
166
167; IDT_ENTRY - for interrupt and task gate definitions in IDT
168
169IDT_ENTRY macro sel, off, acc
170 dw off ; offset
171 dw sel ; selector
172 db 0 ; word count, unused for trap/int gates
173 db acc ; access rights byte
174 dw 0 ; reserved, must be 0 for 386
175endm
176
177
178; GDT_ENTRY - for static initialisation of GDT entries
179
180GDT_ENTRY macro BaseLow, BaseHi, Size, Access
181 dw Size - 1 ; segment limit
182 dw BaseLow ; low word of 24 bit base address
183 db BaseHi ; high byte of base address
184 db Access ; access rights byte
185 dw 0 ; reserved, must be 0 for 386
186endm
187
188
189; LDT_ENTRY - for static initialisation of LDT entries
190
191LDT_ENTRY macro BaseLow, BaseHi, Size, Access
192 dw Size - 1 ; segment limit
193 dw BaseLow ; low word of 24 bit base address
194 db BaseHi ; high byte of base address
195 db Access ; access rights byte
196 dw 0 ; reserved, must be 0 for 386
197endm
198
199
200;*** 286 TSS Format
201;
202
203TSS286STRUC struc
204
205 TSS286_BackLink dw 0 ; back link selector to TSS
206 TSS286_SP0 dw 0 ; ring 0 sp
207 TSS286_SS0 dw 0 ; ring 0 ss
208 TSS286_SP1 dw 0 ; ring 1 sp
209 TSS286_SS1 dw 0 ; ring 1 ss
210 TSS286_SP2 dw 0 ; ring 2 sp
211 TSS286_SS2 dw 0 ; ring 2 ss
212 TSS286_IP dw 0 ; entry point IP
213 TSS286_Flags dw 0 ; flag word
214 TSS286_AX dw 0 ; AX
215 TSS286_CX dw 0 ; CX
216 TSS286_DX dw 0 ; DX
217 TSS286_BX dw 0 ; BX
218 TSS286_SP dw 0 ; SP
219 TSS286_BP dw 0 ; BP
220 TSS286_SI dw 0 ; SI
221 TSS286_DI dw 0 ; DI
222 TSS286_ES dw 0 ; ES
223 TSS286_CS dw 0 ; CS
224 TSS286_SS dw 0 ; SS
225 TSS286_DS dw 0 ; DS
226 TSS286_LDT dw 0 ; LDT
227
228TSS286STRUC ends
229
230;*** 386 TSS Format
231;
232
233TSS386STRUC struc
234
235 TSS386_BackLink dw 0 ; back link selector to TSS
236 TSS386_Unused1 dw 0 ; unused
237 TSS386_ESP0lo dw 0 ; ring 0 ESP low word
238 TSS386_ESP0hi dw 0 ; ring 0 ESP high word
239 TSS386_SS0 dw 0 ; ring 0 SS
240 TSS386_Unused2 dw 0 ; unused
241 TSS386_ESP1 dd 0 ; ring 1 ESP
242 TSS386_SS1 dw 0 ; ring 1 SS
243 TSS386_Unused3 dw 0 ; unused
244 TSS386_ESP2 dd 0 ; ring 2 ESP
245 TSS386_SS2 dw 0 ; ring 2 SS
246 TSS386_Unused4 dw 0 ; unused
247 TSS386_CR3 dd 0 ; CR3
248 TSS386_EIP dd 0 ; EIP
249 TSS386_EFLAGS dd 0 ; EFLAGS
250 TSS386_EAX dd 0 ; EAX
251 TSS386_ECX dd 0 ; ECX
252 TSS386_EDX dd 0 ; EDX
253 TSS386_EBX dd 0 ; EBX
254 TSS386_ESP dd 0 ; ESP
255 TSS386_EBP dd 0 ; EBP
256 TSS386_ESI dd 0 ; ESI
257 TSS386_EDI dd 0 ; EDI
258 TSS386_ES dw 0 ; ES
259 TSS386_Unused5 dw 0 ; Unused
260 TSS386_CS dw 0 ; CS
261 TSS386_Unused6 dw 0 ; Unused
262 TSS386_SS dw 0 ; SS
263 TSS386_Unused7 dw 0 ; Unused
264 TSS386_DS dw 0 ; DS
265 TSS386_Unused8 dw 0 ; Unused
266 TSS386_FS dw 0 ; FS
267 TSS386_Unused9 dw 0 ; Unused
268 TSS386_GS dw 0 ; GS
269 TSS386_Unused10 dw 0 ; Unused
270 TSS386_LDT dw 0 ; LDT
271 TSS386_Unused11 dw 0 ; Unused
272 TaskAttributes dw 0 ; Task Attributes
273 BitMapBase dw 0 ; offset of Base of Bit Map
274TSS386STRUC ends
275
276.list ; end of DESC.INC
277 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/DISP.INC b/v4.0/src/MEMM/MEMM/DISP.INC
new file mode 100644
index 0000000..96eeb7b
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/DISP.INC
@@ -0,0 +1,50 @@
1extrn PrintString:near
2extrn PrintHex:near
3
4display macro string
5 local dbs,disp_exit
6 pushf
7 push ds
8 push es
9
10 push cs
11 pop ds
12 push cs
13 pop es
14
15 push si
16 mov si,offset cs:dbs
17 call PrintString
18 pop si
19 pop es
20 pop ds
21 popf
22 jmp disp_exit
23
24dbs db &string,0
25
26disp_exit:
27 endm
28
29content macro reg
30 pushf
31 push ds
32 push es
33 push ax
34
35 mov ax,reg
36
37 push cs
38 pop ds
39 push cs
40 pop es
41
42 call PrintHex
43
44 pop ax
45 pop es
46 pop ds
47 popf
48 endm
49
50 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/DMA.INC b/v4.0/src/MEMM/MEMM/DMA.INC
new file mode 100644
index 0000000..06bed73
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/DMA.INC
@@ -0,0 +1,234 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: ELIM.INC - include for LIM I/O traps (DMA ports)
10;
11; Version: 0.03
12;
13; Date: April 9, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 04/09/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25; 07/01/86 0.03 DMA trapping related equates added
26;
27; DATE AUTHOR DESCRIPTION
28; ------- -------- -------------------------------------------------------
29; 06/21/88 ISP Removed the Intel Above Board Port Definitions
30; 07/27/88 JHB Added Channel 4 ports, ports for Mode Regs and changed
31; DMARegRec and DMARegBuf structure definitions - lifted
32; from vdmad.inc in Win386/2.03.
33; - Jaywant H Bharadwaj
34;
35;******************************************************************************
36ifndef INC_LIST
37.xlist
38endif
39;
40;
41; DMA related ports
42;
43DMA_P0 equ 0087h ; DMA page register for Channel 0
44DMA_P1 equ 0083h ; DMA page register for Channel 1
45DMA_P2 equ 0081h ; DMA page register for Channel 2
46DMA_P3 equ 0082h ; DMA page register for Channel 3
47DMA_P5 equ 008Bh ; DMA page register for Channel 5
48DMA_P6 equ 0089h ; DMA page register for Channel 6
49DMA_P7 equ 008Ah ; DMA page register for Channel 7
50DMA_P4 equ 0080h ; dummy page reg for channel 4
51
52DMA_B0 equ 0000h ; DMA base register for Channel 0
53DMA_C0 equ 0001h ; DMA count register for Channel 0
54DMA_B1 equ 0002h ; DMA base register for Channel 1
55DMA_C1 equ 0003h ; DMA count register for Channel 1
56DMA_B2 equ 0004h ; DMA base register for Channel 2
57DMA_C2 equ 0005h ; DMA count register for Channel 2
58DMA_B3 equ 0006h ; DMA base register for Channel 3
59DMA_C3 equ 0007h ; DMA count register for Channel 3
60DMA_B4 equ 00C0h ; DMA base register for Channel 4
61DMA_C4 equ 00C2h ; DMA count register for Channel 4
62DMA_B5 equ 00C4h ; DMA base register for Channel 5
63DMA_C5 equ 00C6h ; DMA count register for Channel 5
64DMA_B6 equ 00C8h ; DMA base register for Channel 6
65DMA_C6 equ 00CAh ; DMA count register for Channel 6
66DMA_B7 equ 00CCh ; DMA base register for Channel 7
67DMA_C7 equ 00CEh ; DMA count register for Channel 7
68
69DMA1_CLR_FF equ 000Ch ; clear flip-flop cmd for channels 0-3
70DMA2_CLR_FF equ 00D8h ; clear flip-flop cmd for channels 5-7
71
72
73DMA1_MODE equ 000Bh ; Mode register for channels 0-3
74DMA2_MODE equ 00D6h ; Mode register for channels 4-7
75
76DMA_M_CHANNEL equ 03h ; Mask for channel
77DMA_M_OPERATION equ 0Ch ; Mask for operation
78DMA_M_16BIT equ 040h ; 16bit transfers (PS/2 ext mode)
79
80DMA_M_VERIFY equ 0 ; Verify operation
81DMA_M_WRITE equ 4 ; Write
82
83
84;**************************************************************************
85; New defintions for DMARegRec and DMARegBuf - 7/27/88
86;
87;
88; DMA Register Save Structure
89;
90
91;
92; note: the DMA code in ELIMTRAP.ASM is tuned to this structure's size = 16
93; if you change the size, you had better change the code !
94; LinAdr and PhysAdr have to be dwords
95; count though 16 bits long is left as a dword since the rest of the ported
96; 386 code is dependent on this structure being 16 bytes long.
97;
98
99DMARegRec struc
100DMALinAdr dd 00000000 ; Channel Linear Base Register
101DMAPhyAdr dd 00000000 ; Channel Physical Base Register
102DMACount dd 00000000 ; Channel Count Register
103DMAPagePort db ? ; byte addr of page reg
104DMABasePort db ? ; byte addr of base addr reg
105DMACntPort db ? ; byte addr of cnt addr reg
106DMAMode db ? ; Mode register
107DMARegRec ends
108
109DMARegBuf struc
110Chnl0 db (size DMARegRec - 4) dup (00), DMA_P0, DMA_B0, DMA_C0, 0
111Chnl1 db (size DMARegRec - 4) dup (00), DMA_P1, DMA_B1, DMA_C1, 0
112Chnl2 db (size DMARegRec - 4) dup (00), DMA_P2, DMA_B2, DMA_C2, 0
113Chnl3 db (size DMARegRec - 4) dup (00), DMA_P3, DMA_B3, DMA_C3, 0
114Chnl4 db (size DMARegRec - 4) dup (00), DMA_P4, DMA_B4, DMA_C4, DMA_M_16BIT
115Chnl5 db (size DMARegRec - 4) dup (00), DMA_P5, DMA_B5, DMA_C5, DMA_M_16BIT
116Chnl6 db (size DMARegRec - 4) dup (00), DMA_P6, DMA_B6, DMA_C6, DMA_M_16BIT
117Chnl7 db (size DMARegRec - 4) dup (00), DMA_P7, DMA_B7, DMA_C7, DMA_M_16BIT
118DMAFF1 db 00 ; Controller 1 FlipFlop State
119DMAFF2 db 00 ; Controller 2 FlipFlop State
120DMA_Xfun db 0 ; Extended Operation Function
121DMA_Xchn db 0 ; Extended Operation Channel
122DMARegBuf ends
123
124DMAREG_CTRL2_INDEX equ 4 * 2 ; 2 * 1st channel # on 2nd cntlr
125
126
127;**************************************************************************
128;
129; Macros taken from PS2.INC in Win/386 2.03
130;
131;--------------------------------------------------------------------------
132
133; STANDARD ROM BIOS MACHINE TYPES used in ROM_BIOS_Machine_ID
134
135RBMI_PC equ 0FFh
136RBMI_PCXT equ 0FEh
137RBMI_PCjr equ 0FDh
138RBMI_PCAT equ 0FCh
139RBMI_PCConvertible equ 0F9h
140RBMI_Sys80 equ 0F8h
141RBMI_CompaqPortable equ 000h
142
143;******************************************************************************
144; DMA_WADDR_TO_BADDR - convert internal DMA word address to a byte address
145;
146; ENTRY: 386 PROTECTED MODE
147; DS -> 0
148; ES -> 0
149; EAX - Word Address
150;
151; EXIT: EAX - Byte address
152;
153; USED:
154;------------------------------------------------------------------------------
155DMA_WADDR_TO_BADDR MACRO
156 LOCAL Not_AT
157extrn ROM_BIOS_Machine_ID:byte
158
159 cmp [ROM_BIOS_Machine_ID], RBMI_Sys80
160 jbe short Not_AT ; If running on EBIOS machine
161
162 ror eax,16 ; AX = high word
163 shr al,1 ; adjust for D0 null in page reg
164 rol eax,17 ; EAX = address w/ adjust for
165 ; 'A0' offset
166Not_At:
167 shl ecx, 1 ; Adjust for word units
168 ENDM
169
170
171;******************************************************************************
172; DMA_BADDR_TO_WADDR - convert internal DMA byte address to a word address
173;
174; ENTRY: 386 PROTECTED MODE
175; DS -> 0
176; ES -> 0
177; EAX - Word Address
178;
179; EXIT: EAX - Byte address
180;
181; USED:
182;------------------------------------------------------------------------------
183DMA_BADDR_TO_WADDR MACRO
184 LOCAL Not_AT
185extrn ROM_BIOS_Machine_ID:byte
186
187 cmp [ROM_BIOS_Machine_ID], RBMI_Sys80
188 jbe short Not_AT ; If running on EBIOS machine
189
190 shr eax, 1 ; Adjust for implied 'A0'
191 push ax ; Save A16-A1
192 xor ax, ax
193 shl eax, 1 ; Adjust for unused Pg Reg D0
194 pop ax ; Restore A16-A1
195Not_At:
196 ENDM
197
198
199
200;****************************************************************************
201; Old definitions for memm LIM 3.2 - not used anymore - 7/27/88
202;
203; DMA Register Save Structure
204;
205;Chnl1Idx equ 0 ; Address offset in Address tables
206;Chnl2Idx equ 2 ; Address offset in Address tables
207;Chnl3Idx equ 4 ; Address offset in Address tables
208;Chnl5Idx equ 6 ; Address offset in Address tables
209;Chnl6Idx equ 8 ; Address offset in Address tables
210;Chnl7Idx equ 10 ; Address offset in Address tables
211;
212;DMARegRec struc
213;DMALinAdr dd 00000000 ; Channel Linear Base Register
214;DMAPhyAdr dd 00000000 ; Channel Physical Base Register
215;DMACount dd 00000000 ; Channel Count Register
216;DMAChnlIdx db ? ; Channel identifier index
217;DMARegRec ends
218;
219;DMARegBuf struc
220;Chnl1 db (size DMARegRec - 1) dup (00), Chnl1Idx
221;Chnl2 db (size DMARegRec - 1) dup (00), Chnl2Idx
222;Chnl3 db (size DMARegRec - 1) dup (00), Chnl3Idx
223;Chnl5 db (size DMARegRec - 1) dup (00), Chnl5Idx
224;Chnl6 db (size DMARegRec - 1) dup (00), Chnl6Idx
225;Chnl7 db (size DMARegRec - 1) dup (00), Chnl7Idx
226;DMAFF1 db 00 ; Controller 1 FlipFlop State
227;DMAFF2 db 00 ; Controller 2 FlipFlop State
228;DMARegBuf ends
229;
230;******************************************************************************
231
232
233.list ; end of ELIM.INC
234 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/DRIVER.EQU b/v4.0/src/MEMM/MEMM/DRIVER.EQU
new file mode 100644
index 0000000..8e12e90
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/DRIVER.EQU
@@ -0,0 +1,105 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: DRIVER.EQU - MS-DOS device driver equates
10;
11; Version: 0.02
12;
13; Date: June 25, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 06/25/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25;
26;******************************************************************************
27ifndef INC_LIST
28.xlist
29endif
30;
31; Device driver attribute equates
32;
33CHAR_DEV EQU 8000H
34IOCTL_SUP EQU 4000H
35NON_IBM EQU 2000H
36CLK_DEV EQU 0008H
37NUL_DEV EQU 0004H
38OUT_DEV EQU 0002H
39INP_DEV EQU 0001H
40;
41; Device driver command code equates
42;
43INIT EQU 0
44MEDIA EQU 1
45BUILD_BPB EQU 2
46IOCTL_INP EQU 3
47INPUT_READ EQU 4
48NON_INPUT EQU 5
49INP_STATUS EQU 6
50INP_FLUSH EQU 7
51OUTPUT_WRITE EQU 8
52OUTPUT_VER EQU 9
53OUT_STATUS EQU 10
54OUT_FLUSH EQU 11
55IOCTL_OUT EQU 12
56;
57; Device driver status word equates
58;
59ERROR EQU 8000H
60BUSY EQU 0200H
61DONE EQU 0100H
62ERR EQU 80H
63BUS EQU 02H
64DON EQU 01H
65;
66; Device driver i/o control status word equates
67;
68ISDEV EQU 0080H
69EOF EQU 0040H
70RAW EQU 0020H
71ISCLK EQU 0008H
72ISNUL EQU 0004H
73ISCOT EQU 0002H
74ISCIN EQU 0001H
75;
76; Device driver error code equates
77;
78WRT_PROT_VIO EQU 00H
79UNK_UNIT EQU 01H
80DEV_NOT_RDY EQU 02H
81UNK_COMMAND EQU 03H
82CRC_ERROR EQU 04H
83BAD_DRIVE EQU 05H
84SEEK_ERROR EQU 06H
85UNK_MEDIA EQU 07H
86SEC_NOT_FND EQU 08H
87OUT_OF_PAPER EQU 09H
88WRITE_FAULT EQU 0AH
89READ_FAULT EQU 0BH
90GENERAL_FAIL EQU 0CH
91;
92; Device driver function call equates
93;
94NUMBER_UNITS EQU BYTE PTR 0DH
95ENDING_ADDR EQU DWORD PTR 0EH
96BPB_ARRAY EQU DWORD PTR 12H
97DESC_BYTE EQU BYTE PTR 0DH
98RETURN_INFO EQU BYTE PTR 0EH
99BUFFER_ADDR EQU DWORD PTR 0EH
100BPB_PTR EQU DWORD PTR 12H
101TRANS_COUNT EQU WORD PTR 12H
102TRANS_ADDR EQU WORD PTR 14H
103BYTE_READ EQU BYTE PTR 0DH
104
105.list ; end of DRIVER.EQU
diff --git a/v4.0/src/MEMM/MEMM/DRIVER.STR b/v4.0/src/MEMM/MEMM/DRIVER.STR
new file mode 100644
index 0000000..dfb7e90
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/DRIVER.STR
@@ -0,0 +1,129 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: DRIVER.STR - MS-DOS Device Driver structures
10;
11; Version: 0.02
12;
13; Date: June 25,1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 06/25/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25;
26;******************************************************************************
27ifndef INC_LIST
28.xlist
29endif
30
31;
32; Device driver header structure
33;
34DEVICE_HEADER STRUC
35DEV_PTR DD 0
36DEV_ATTR DW 0
37STRAT_PTR DW 0
38INT_PTR DW 0
39DEV_NAME DB " "
40DEVICE_HEADER ENDS
41DEV_OFF EQU WORD PTR DEV_PTR
42DEV_SEG EQU WORD PTR DEV_PTR+2
43;
44; Device driver request header structure
45;
46REQUEST_HEADER STRUC
47HDR_LEN DB 0
48UNIT_CODE DB 0
49COMMAND_CODE DB 0
50STATUS_WORD DW 0
51RES_AREA DB 0,0,0,0,0,0,0,0
52OP_DATA DB 0
53REQUEST_HEADER ENDS
54;
55; Initialize command request header structure
56;
57INIT_HEADER STRUC
58 DB 13 DUP (?)
59NUM_UNITS DB 0
60BRK_ADDR DD 0
61ARG_PTR DD 0
62DRV_NUM DB 0
63INIT_HEADER ENDS
64BRK_OFF EQU WORD PTR BRK_ADDR
65BRK_SEG EQU WORD PTR BRK_ADDR+2
66ARG_OFF EQU WORD PTR ARG_PTR
67ARG_SEG EQU WORD PTR ARG_PTR+2
68;
69; Media check request header structure
70;
71MEDIA_HEADER STRUC
72 DB 13 DUP (?)
73MEDIA_BYTE DB 0
74RET_BYTE DB 0
75VOL_PTR DD 0
76MEDIA_HEADER ENDS
77VOL_OFF EQU WORD PTR VOL_PTR
78VOL_SEG EQU WORD PTR VOL_PTR+2
79;
80; Build BPB request header structure
81;
82BPB_HEADER STRUC
83 DB 13 DUP (?)
84BPB_DESC DB 0
85BPB_TRANS DD 0
86TABLE_PTR DD 0
87BPB_HEADER ENDS
88BPB_OFF EQU WORD PTR BPB_TRANS
89BPB_SEG EQU WORD PTR BPB_TRANS+2
90TABLE_OFF EQU WORD PTR TABLE_PTR
91TABLE_SEG EQU WORD PTR TABLE_PTR+2
92;
93; Input/output request header structure
94;
95IO_HEADER STRUC
96 DB 13 DUP (?)
97IO_DESC DB 0
98IO_TRANS DD 0
99IO_COUNT DW 0
100IO_START DW 0
101VOL_ID DD 0
102IO_HEADER ENDS
103IO_OFF EQU WORD PTR IO_TRANS
104IO_SEG EQU WORD PTR IO_TRANS+2
105ID_OFF EQU WORD PTR VOL_ID
106ID_SEG EQU WORD PTR VOL_ID+2
107;
108; Device driver BIOS Parameter Block (BPB) structure
109;
110BPB_BLOCK STRUC
111BYTES_PER_SECTOR DW 0
112SECTORS_PER_ALLOC DB 0
113RES_SECTORS DW 0
114NUM_FATS DB 0
115ROOT_DIR_ENTRIES DW 0
116NUMBER_OF_SECTORS DW 0
117MEDIA_DESC DB 0
118SECTORS_PER_FAT DW 0
119BPB_BLOCK ENDS
120;
121; Device driver BIOS Parameter option block structure
122;
123BPB_OPTION STRUC
124SECTORS_PER_TRACK DW 0
125NUMBER_OF_HEADS DW 0
126HIDDEN_SECTORS DW 0
127BPB_OPTION ENDS
128
129.list ; end of DRIVER.STR
diff --git a/v4.0/src/MEMM/MEMM/EKBD.ASM b/v4.0/src/MEMM/MEMM/EKBD.ASM
new file mode 100644
index 0000000..9f8a8f2
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EKBD.ASM
@@ -0,0 +1,139 @@
1
2
3 page 58,132
4;******************************************************************************
5 title EKBD - get keyboard make codes
6;******************************************************************************
7; (C) Copyright MICROSOFT Corp. 1986
8;
9; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
10;
11; Module: EKBD - basic keyboard handler for error handler routine
12;
13; Version: 0.04
14;
15; Date : June 10,1986
16;
17; Author:
18;
19;******************************************************************************
20;
21; CHANGES:
22;
23; DATE REVISION DESCRIPTION
24; -------- -------- ------------------------------------------------------
25; 06/10/86 Original
26; 06/28/86 0.02 Name change from MEMM386 to MEMM
27; 07/06/86 0.04 Changed assumes to DGROUP
28;
29;******************************************************************************
30;
31; Functional description: Return keyboard code while ignoring any break
32; or command codes.
33;
34;******************************************************************************
35 page
36.386P
37;
38 include vdmseg.inc
39 include kbd.inc
40;******************************************************************************
41; Public Declarations
42;******************************************************************************
43;
44 public egetc ; get a character
45 public WaitKBD ; wait for keyboard ready
46;******************************************************************************
47; Externs
48;******************************************************************************
49_TEXT segment
50_TEXT ends
51
52_DATA segment
53_DATA ends
54;
55;******************************************************************************
56; Equates
57;******************************************************************************
58;
59;
60;******************************************************************************
61; LOCAL DATA
62;******************************************************************************
63_DATA segment
64_DATA ends
65;
66;******************************************************************************
67;
68; egetc - read a character from keyboard
69;
70; entry: NONE
71;
72; exit: al = make code
73; ZF = 0
74;
75; or ZF = 1 if no code available
76;
77; used: none
78;
79; stack:
80;
81;******************************************************************************
82_TEXT segment
83 ASSUME CS:_TEXT, DS:DGROUP, ES:DGROUP
84egetc proc near
85;
86 in al,KbStatus ; get status
87 test al,1 ; q: is there anything out there?
88 jz kret ; n: return
89; ; y: disable keyboard
90 call WaitKBD ; wait til 8042 ready for input
91 mov al,0adh ; disable keyboard interface
92 out KbStatus,al
93 in al,KbData ; get character
94 cmp al,7fh ; q: break or control word?
95 jae ign_chr ; y: ignore it
96 cmp al,80h ; clear ZF
97 jmp enaKB ; go enable keyboard
98ign_chr:
99 mov al,0 ; return an invalid character
100 ; but preserve ZF
101enaKB:
102 pushf ; save flags
103 push ax ; save character
104 call WaitKBD
105 mov al,0aeh ; enable keyboard
106 out KbStatus,al
107 pop ax
108 popf
109kret:
110 ret
111egetc endp
112;
113;******************************************************************************
114;
115; WaitKBD - wait for status to indicate ready for new command
116;
117; entry: NONE
118;
119; exit: NONE
120;
121; used: al
122;
123; stack:
124;
125;******************************************************************************
126WaitKBD proc near
127 push cx
128 xor cx,cx ; do 65536 times
129wait:
130 in al,KbStatus
131 test al,BufFull ; q: busy?
132 loopnz wait ; y: try again
133;
134 pop cx ; n: return
135 ret
136WaitKBD endp
137
138_TEXT ENDS
139 END
diff --git a/v4.0/src/MEMM/MEMM/ELIM.INC b/v4.0/src/MEMM/MEMM/ELIM.INC
new file mode 100644
index 0000000..47f0bc0
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ELIM.INC
@@ -0,0 +1,128 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: ELIM.INC - include for LIM I/O traps (DMA ports)
10;
11; Version: 0.03
12;
13; Date: April 9, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 04/09/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25; 07/01/86 0.03 DMA trapping related equates added
26;
27; DATE AUTHOR DESCRIPTION
28; ------- -------- -------------------------------------------------------
29; 06/21/88 ISP Removed the Intel Above Board Port Definitions
30; 07/27/88 JHB Added Channel 4 ports, ports for Mode Regs and changed
31; DMARegRec and DMARegBuf structure definitions - lifted
32; from vdmad.inc in Win386/2.03.
33; - Jaywant H Bharadwaj
34;
35;******************************************************************************
36ifndef INC_LIST
37.xlist
38endif
39;
40;
41; DMA related ports
42;
43DMA_P0 equ 0087h ; DMA page register for Channel 0
44DMA_P1 equ 0083h ; DMA page register for Channel 1
45DMA_P2 equ 0081h ; DMA page register for Channel 2
46DMA_P3 equ 0082h ; DMA page register for Channel 3
47DMA_P5 equ 008Bh ; DMA page register for Channel 5
48DMA_P6 equ 0089h ; DMA page register for Channel 6
49DMA_P7 equ 008Ah ; DMA page register for Channel 7
50DMA_P4 equ 0080h ; dummy page reg for channel 4
51
52DMA_B0 equ 0000h ; DMA base register for Channel 0
53DMA_C0 equ 0001h ; DMA count register for Channel 0
54DMA_B1 equ 0002h ; DMA base register for Channel 1
55DMA_C1 equ 0003h ; DMA count register for Channel 1
56DMA_B2 equ 0004h ; DMA base register for Channel 2
57DMA_C2 equ 0005h ; DMA count register for Channel 2
58DMA_B3 equ 0006h ; DMA base register for Channel 3
59DMA_C3 equ 0007h ; DMA count register for Channel 3
60DMA_B4 equ 00C0h ; DMA base register for Channel 4
61DMA_C4 equ 00C2h ; DMA count register for Channel 4
62DMA_B5 equ 00C4h ; DMA base register for Channel 5
63DMA_C5 equ 00C6h ; DMA count register for Channel 5
64DMA_B6 equ 00C8h ; DMA base register for Channel 6
65DMA_C6 equ 00CAh ; DMA count register for Channel 6
66DMA_B7 equ 00CCh ; DMA base register for Channel 7
67DMA_C7 equ 00CEh ; DMA count register for Channel 7
68
69DMA1_CLR_FF equ 000Ch ; clear flip-flop cmd for channels 0-3
70DMA2_CLR_FF equ 00D8h ; clear flip-flop cmd for channels 5-7
71
72
73DMA1_MODE equ 000Bh ; Mode register for channels 0-3
74DMA2_MODE equ 00D6h ; Mode register for channels 4-7
75
76DMA_M_CHANNEL equ 03h ; Mask for channel
77DMA_M_OPERATION equ 0Ch ; Mask for operation
78DMA_M_16BIT equ 040h ; 16bit transfers (PS/2 ext mode)
79
80DMA_M_VERIFY equ 0 ; Verify operation
81DMA_M_WRITE equ 4 ; Write
82
83
84;**************************************************************************
85; New defintions for DMARegRec and DMARegBuf - 7/27/88
86;
87;
88; DMA Register Save Structure
89;
90
91;
92; note: the DMA code in ELIMTRAP.ASM is tuned to this structure's size = 16
93; if you change the size, you had better change the code !
94; LinAdr and PhysAdr have to be dwords
95; count though 16 bits long is left as a dword since the rest of the ported
96; 386 code is dependent on this structure being 16 bytes long.
97;
98
99DMARegRec struc
100DMALinAdr dd 00000000 ; Channel Linear Base Register
101DMAPhyAdr dd 00000000 ; Channel Physical Base Register
102DMACount dd 00000000 ; Channel Count Register
103DMAPagePort db ? ; byte addr of page reg
104DMABasePort db ? ; byte addr of base addr reg
105DMACntPort db ? ; byte addr of cnt addr reg
106DMAMode db ? ; Mode register
107DMARegRec ends
108
109DMARegBuf struc
110Chnl0 db (size DMARegRec - 4) dup (00), DMA_P0, DMA_B0, DMA_C0, 0
111Chnl1 db (size DMARegRec - 4) dup (00), DMA_P1, DMA_B1, DMA_C1, 0
112Chnl2 db (size DMARegRec - 4) dup (00), DMA_P2, DMA_B2, DMA_C2, 0
113Chnl3 db (size DMARegRec - 4) dup (00), DMA_P3, DMA_B3, DMA_C3, 0
114Chnl4 db (size DMARegRec - 4) dup (00), DMA_P4, DMA_B4, DMA_C4, DMA_M_16BIT
115Chnl5 db (size DMARegRec - 4) dup (00), DMA_P5, DMA_B5, DMA_C5, DMA_M_16BIT
116Chnl6 db (size DMARegRec - 4) dup (00), DMA_P6, DMA_B6, DMA_C6, DMA_M_16BIT
117Chnl7 db (size DMARegRec - 4) dup (00), DMA_P7, DMA_B7, DMA_C7, DMA_M_16BIT
118DMAFF1 db 00 ; Controller 1 FlipFlop State
119DMAFF2 db 00 ; Controller 2 FlipFlop State
120DMA_Xfun db 0 ; Extended Operation Function
121DMA_Xchn db 0 ; Extended Operation Channel
122DMARegBuf ends
123
124DMAREG_CTRL2_INDEX equ 4 * 2 ; 2 * 1st channel # on 2nd cntlr
125
126
127.list ; end of ELIM.INC
128
diff --git a/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM b/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM
new file mode 100644
index 0000000..d431f0b
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM
@@ -0,0 +1,268 @@
1
2
3 page 58,132
4;******************************************************************************
5 title ELIMFUNC - MEMM functions module
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: ELIMFUNC - entry point for VDM functions
13;
14; Version: 0.05
15;
16; Date: May 24,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 04/24/86 Original From EMML LIM driver.
27; 06/28/86 0.02 Name change from MEMM386 to MEMM
28; 07/05/86 0.04 Added segment R_CODE
29; 07/06/86 0.04 Changed assume to DGROUP
30; 07/10/86 0.05 jmp $+2 before "POPF"
31;
32;******************************************************************************
33; Functional Description:
34; This module contains the ON/OFF functionality code for activating/
35; deactivating EMM386 from DOS. Functions in _TEXT to reduce code in
36; R_CODE segment.
37;
38;******************************************************************************
39.lfcond
40.386p
41 page
42;******************************************************************************
43; P U B L I C D E C L A R A T I O N S
44;******************************************************************************
45;
46 public ELIM_Entry
47 public EFunTab
48 public EFUN_CNT
49;
50 page
51;******************************************************************************
52; L O C A L C O N S T A N T S
53;******************************************************************************
54;
55 include vdmseg.inc
56
57FALSE equ 0
58TRUE equ not FALSE
59
60;******************************************************************************
61; E X T E R N A L R E F E R E N C E S
62;******************************************************************************
63;
64_DATA segment
65 extrn Active_Status:byte
66 extrn Auto_Mode:byte
67_DATA ends
68
69_TEXT segment
70 extrn _AutoUpdate:near ; update auto mode status
71 extrn GoVirtual:near
72 extrn RRProc:near ; Return processor to real mode(RRTrap)
73_TEXT ends
74
75 page
76;******************************************************************************
77; S E G M E N T D E F I N I T I O N
78;******************************************************************************
79;
80;******************************************************************************
81;
82; Code Segment R_CODE
83;
84;******************************************************************************
85;
86R_CODE segment
87 assume cs:R_CODE, ds:DGROUP, es:DGROUP
88;
89; ELIM functions table - far calls
90;
91EFunTab label dword
92 dw offset E_GetStatus
93 dw seg _TEXT
94
95 dw offset E_ONOFF
96 dw seg _TEXT
97
98EFUN_CNT equ ($-EFunTab)/4
99
100 page
101;******************************************************************************
102; ELIM_Entry - entry point for general ELIM functions
103;
104; THIS IS A FAR CALL ROUTINE
105;
106; ENTRY: REAL or VIRTUAL mode only
107; AH = 0 => get current status of VDM/EMM386
108; AH = 1 => ON/OFF/AUTO
109;
110; EXIT: EMM386 is activated/deactivated if possible
111; NC => no errors.
112; CY => ERROR occured.
113; AH = error number
114; AH= 01 =>invalid function.
115;
116; USED: none
117;
118;******************************************************************************
119ELIM_Entry proc far
120;
121 push bx
122 push ds
123;
124 mov bx,seg DGROUP
125 mov ds,bx
126;
127 cmp ah,EFUN_CNT ;Q: valid function #
128 jae EE_inv_func ; N: return error
129 xor bx,bx ; Y: exec function
130 mov bl,ah ; bx = function #
131 shl bx,2 ; dword index
132 call CS:EFunTab[bx] ; call the function
133;
134EE_exit:
135 pop ds
136 pop bx
137 ret
138;
139EE_inv_func:
140 mov ah,01
141 stc
142 jmp short EE_exit
143;
144ELIM_Entry endp
145
146R_CODE ends
147
148 page
149;******************************************************************************
150;
151; Code Segment _TEXT
152;
153;******************************************************************************
154_TEXT segment
155 assume cs:_TEXT, ds:DGROUP, es:DGROUP
156
157;******************************************************************************
158; E_GetStatus - get ELIM/VDM status
159;
160; ENTRY: AH = 0
161; DS = DGROUP
162;
163; EXIT: AH = 0 => ELIM ON
164; = 1 => ELIM OFF
165; = 2 => ELIM in AUTO mode (ON)
166; = 3 => ELIM in AUTO mode (OFF)
167;
168; USED: none
169;
170;******************************************************************************
171E_GetStatus proc far
172;
173 xor ah,ah ; init to on
174 cmp [Auto_Mode],0 ; Q: auto mode ?
175 je not_auto ; N: try on/off
176 mov ah,2 ; Y: indicate as such
177not_auto:
178 cmp [Active_Status],0 ;Q: is ELIM active ?
179 jne EGS_exit ; Y: exit with status = 0/2
180 inc ah ; N: exit with status = 1/3
181EGS_exit:
182 ret
183;
184E_GetStatus endp
185
186;******************************************************************************
187; E_ONOFF - general ON/OFF code for ELIM
188;
189; ENTRY: AH = 1
190; AL = 0 => ON
191; AL = 1 => OFF
192; AL = 2 => AUTO
193; DS = DGROUP
194;
195; EXIT: Virtual mode and ELIM ON
196; OR Real mode and ELIM OFF
197;
198; USED: none
199;
200;******************************************************************************
201E_ONOFF proc far
202;
203 cmp al,0 ;Q: turn it on ?
204 jne EOO_OFF ; N: check for OFF/AUTO
205 cmp [Active_Status],0 ; Y: Q: is it already active ?
206 jne EOO_AUTO_OFF ; Y: then just leave
207 mov [Active_Status],1 ; N: then go to virtual mode
208 mov [Auto_Mode],0 ; and clear auto mode
209 call GoVirtual
210 jmp short EOO_OK
211EOO_OFF:
212 cmp al,1 ;Q: turn it off ?
213 jne EOO_AUTO ; N: check for AUTO mode
214
215;
216; we are not providing the ability to turn emm off.
217;
218; cmp [Active_Status],0 ; Y: Q: is it already OFF ?
219; je EOO_AUTO_OFF ; Y: then just leave
220; mov [Active_Status],0 ; N: then go to real mode
221; mov [Auto_Mode],0 ; and clear auto mode
222; call RRProc ; put processor in real mode
223; jmp short EOO_OK
224
225 jmp short EOO_inv
226
227
228EOO_AUTO_OFF:
229; cmp [Auto_Mode],0 ; q: auto mode already off?
230; jz EOO_OK ; y: forget it
231; mov [Auto_Mode],0 ; n: clear it
232; jmp short EOO_OK ; and update status
233
234 jmp short EOO_inv
235
236
237EOO_AUTO:
238 cmp al,2 ;Q: go to auto mode ?
239 jne EOO_inv ; N: invalid function
240; cmp [Auto_Mode],0 ; Y: Q: is it already in auto mode
241; jne EOO_OK ; Y: then just leave
242; mov [Auto_Mode],1 ; N: then go to auto mode
243; call _AutoUpdate ;
244
245 jmp short EOO_inv
246;
247; leave with no errors
248;
249EOO_OK:
250 clc
251
252EOO_exit:
253 ret
254;
255; invalide ON/OFF/AUTO function call
256;
257EOO_inv:
258 mov ah,1
259 stc
260 jmp short EOO_exit
261;
262E_ONOFF endp
263
264;
265_TEXT ends
266
267 end
268
diff --git a/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM b/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM
new file mode 100644
index 0000000..1036c33
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM
@@ -0,0 +1,1560 @@
1
2
3;******************************************************************************
4 title DMATRAP.ASM - Trap handlers for DMA ports
5;******************************************************************************
6;
7; (C) Copyright MICROSOFT Corp. 1986
8;
9; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
10;
11; Module: DMATRAP.ASM - Trap Handlers for DMA ports
12;
13; Version: 0.04
14;
15; Date: April 9, 1986
16;
17; Author:
18;
19;******************************************************************************
20;
21; Change log:
22;
23; DATE REVISION DESCRIPTION
24; -------- -------- -------------------------------------------------------
25; 04/09/86 Original
26; 06/18/86 0.01 Modified LIM_Map to handle all 4 boards and call
27; page mapping routine in EMMLIB.LIB
28; 06/27/86 0.02 Made _page_frame_address indexing dword (was word)
29;
30; 06/28/86 0.02 Name change from MEMM386 to MEMM
31; 07/01/86 0.03 Added DMA support routines
32; 07/02/86 0.03 Fixed CNT size vs. length problem
33; 07/06/86 0.04 Made _pft386 a ptr to _pft386 array
34; 07/06/86 0.04 now sets _window array also
35; 08/11/86 0.05 moved IO_Trap code for LIM DMA trapping here
36; 06/09/88 remove IOT_LIM, LIMMap, and InitELIM since we don't
37; have any EMM hardware to trap and emulate now (Paulch)
38; 07/26/88 reintroduced initelim removing iab port trap (ISP)
39;
40; 07/27/88 Started rewriting the DMA port trap handlers - similar to the
41; code in VDMAD.ASM in Win/386 V2.03
42; - Jaywant H Bharadwaj
43;
44;*****************************************************************************
45
46
47;******************************************************************************
48;
49; Functional Description:
50;
51; Monitors writes/reads to the DMA ports.
52; Reads are simple - return the value saved in DMARegSav structure.
53; On a write to Page/Base/count Reg port -
54; user specifies a linear address. DMAs can handle only physical addresses.
55; Therefore, the actual physical address has to be written into the Page and
56; base Address Reg. Also the DMA transfer area may not be physically contiguous.
57; If it isn't we should remap the linear address so that it is physically
58; contiguous.
59;
60; We never know when a DMA is started. Hence on every access to the Page/Base
61; or count Register we make sure that the linear address specified by the user
62; maps to a physical address which is contiguous over the DMA transfer area.
63; This has to be done even if the count register is altered since the user
64; might be relying on the previous contents of Page/Addr Regs which may not be
65; contiguous anymore.
66;
67; All routines except InitDMA are entered through protected mode only.
68;
69;******************************************************************************
70
71.lfcond ; list false conditionals
72.386p
73
74 page
75;******************************************************************************
76; P U B L I C D E C L A R A T I O N S
77;******************************************************************************
78
79;
80; routines called from C
81;
82 public _GetPte
83 public _SetPte
84 public _GetCRSEntry
85 public _GetDMALinAdr
86 public _Exchange16K
87 public _FatalError
88
89 public InitELIM ; initialization routine for LIMulator
90 public InitDMA ; init DMA register save area
91 public DMARegSav
92 public _DMA_Pages
93 public DMA_Pages
94 public _DMA_PAGE_COUNT
95 public DMA_PAGE_COUNT
96
97
98
99 public DMA_DMAFixup
100 public DMABase0
101 public DMABase1
102 public DMABase2
103 public DMABase3
104 public DMABase5
105 public DMABase6
106 public DMABase7
107
108 public DMACnt0
109 public DMACnt1
110 public DMACnt2
111 public DMACnt3
112 public DMACnt5
113 public DMACnt6
114 public DMACnt7
115 public DMAPg0
116 public DMAPg1
117 public DMAPg2
118 public DMAPg3
119 public DMAPg5
120 public DMAPg6
121 public DMAPg7
122 public DMAClrFF1
123 public DMAClrFF2
124 public DMAMode1
125 public DMAMode2
126
127
128 page
129;******************************************************************************
130; L O C A L C O N S T A N T S
131;******************************************************************************
132;
133 include VDMseg.inc
134 include VDMsel.inc
135 include desc.inc
136 include elim.inc
137 include mach_id.inc
138 include page.inc
139 include oemdep.inc
140 include instr386.inc
141 include vm386.inc
142 include emmdef.inc
143
144;******************************************************************************
145;
146; Get_FRS_window - get pointer to Fast Register Set window
147;
148; ENTRY: Reg - points to an FRS_struc
149;
150; EXIT: Reg - points to FRS_window entry in the structure
151;
152; USES: Reg
153;
154;******************************************************************************
155Get_FRS_window MACRO Reg
156
157 mov Reg, word ptr [CurRegSet] ; just offset (assume dgroup)
158 add Reg, FRS_window ; points to FRS window entries
159 ENDM
160
161;****************************************************************************
162;
163; InitDMARegSav - MACRO for initialising save area for channels
164;
165; ENTRY: chan_num = channel number (1,2,3,5,6,7)
166; ES -> DGROUP
167;
168;-----------------------------------------------------------------------------
169
170InitDMARegSav MACRO chan_num
171
172 lea di,[DMARegSav.Chnl&chan_num] ; pt to channel's save area
173
174 xor eax, eax
175 in al,DMA_P&chan_num ; page register for channel
176 jmp $+2
177 jmp $+2 ; timing
178 shl eax,16 ; high EAX = high word of linear addr
179
180 ; flip-flop already reset by the caller
181
182 in al,DMA_B&chan_num ; get low byte of base
183 jmp $+2
184 jmp $+2 ; timing
185 mov ah,al
186 in al,DMA_B&chan_num ; get high byte of base
187 xchg ah,al
188 ; EAX = LINEAR BASE address
189
190 stosd ; store LINEAR BASE address
191
192 stosd ; store PHYSICAL BASE address
193
194 xor eax, eax ; clear EAX
195 jmp $+2
196 jmp $+2 ; timing
197 in al,DMA_C&chan_num ; get low byte of count
198 jmp $+2
199 jmp $+2 ; timing
200 mov ah,al
201 in al,DMA_C&chan_num ; get high byte of count
202 xchg ah,al
203 ; EAX = count
204
205 stosd ; store count
206
207 add di, 4 ; skip 4 bytes - 3 ports+mode byte
208
209 ENDM
210
211
212;******************************************************************************
213; DMA_WADDR_TO_BADDR - convert internal DMA word address to a byte address
214;
215; ENTRY: 386 PROTECTED MODE
216; DS -> DGROUP
217; ES -> DGROUP
218; EAX - Word Address
219;
220; EXIT: EAX - Byte address
221;
222; USED:
223;------------------------------------------------------------------------------
224DMA_WADDR_TO_BADDR MACRO
225 LOCAL Not_AT
226
227 cmp [ROM_BIOS_Machine_ID], RBMI_Sys80
228 jbe short Not_AT ; If running on EBIOS machine
229
230 ror eax,16 ; AX = high word
231 shr al,1 ; adjust for D0 null in page reg
232 rol eax,17 ; EAX = address w/ adjust for
233 ; 'A0' offset
234Not_At:
235 shl ecx, 1 ; Adjust for word units
236 ENDM
237
238
239;******************************************************************************
240; DMA_BADDR_TO_WADDR - convert internal DMA byte address to a word address
241;
242; ENTRY: 386 PROTECTED MODE
243; DS -> DGROUP
244; ES -> DGROUP
245; EAX - Word Address
246;
247; EXIT: EAX - Byte address
248;
249; USED:
250;------------------------------------------------------------------------------
251DMA_BADDR_TO_WADDR MACRO
252 LOCAL Not_AT
253
254 cmp [ROM_BIOS_Machine_ID], RBMI_Sys80
255 jbe short Not_AT ; If running on EBIOS machine
256
257 shr eax, 1 ; Adjust for implied 'A0'
258 push ax ; Save A16-A1
259 xor ax, ax
260 shl eax, 1 ; Adjust for unused Pg Reg D0
261 pop ax ; Restore A16-A1
262Not_At:
263 ENDM
264
265;******************************************************************************
266; E X T E R N A L R E F E R E N C E S
267;******************************************************************************
268
269_DATA segment
270extrn ROM_BIOS_Machine_ID:byte
271extrn _page_frame_base:word
272extrn CurRegSet:word
273extrn Page_Dir:word
274SaveAL db ?
275_DATA ends
276
277_TEXT segment
278
279extrn PortTrap:near ; set port bit in I/O bit Map
280extrn MapLinear:near
281extrn ErrHndlr:near
282;
283; Swap pages so that DMA Xfer area is physically contiguous.
284; defined in mapdma.c
285;
286extrn _SwapDMAPages:near
287
288_TEXT ends
289
290;******************************************************************************
291; S E G M E N T D E F I N I T I O N
292;******************************************************************************
293
294_DATA segment
295
296DMARegSav DMARegBuf <> ; DMA Register buffer
297
298DMAP_Page label word
299; dw DMA_P0 ; DMA page registers
300 dw DMA_P1
301 dw DMA_P2
302 dw DMA_P3
303 dw DMA_P5
304 dw DMA_P6
305 dw DMA_P7
306; dw DMA_P4
307; dw DMA_P0+10h ; page regs mapped to here also
308 dw DMA_P1+10h
309 dw DMA_P2+10h
310 dw DMA_P3+10h
311 dw DMA_P5+10h
312 dw DMA_P6+10h
313 dw DMA_P7+10h
314; dw DMA_P4+10h
315DMAP_Addr label word
316; dw DMA_B0 ; DMA base registers
317 dw DMA_B1
318 dw DMA_B2
319 dw DMA_B3
320 dw DMA_B5
321 dw DMA_B6
322 dw DMA_B7
323DMAP_Count label word
324; dw DMA_C0 ; DMA count registers
325 dw DMA_C1
326 dw DMA_C2
327 dw DMA_C3
328 dw DMA_C5
329 dw DMA_C6
330 dw DMA_C7
331 dw DMA1_CLR_FF ; reset flip-flop commands
332 dw DMA2_CLR_FF
333DMAP_Mode label word
334 dw DMA1_MODE
335 dw DMA2_MODE
336
337LIMDMAP_CNT = ($ - DMAP_Page) / 2
338;
339; DMA_Pages - EMM Pages for DMA relocation. Each is an index into pft386.
340; To access actual entry in pft386 you need to multiply index by 4.
341; If eight contingous 16k EMM pages are not available - the unavailable
342; entries are left at NULL_PAGE.
343; This array should be initialized at boot time.
344;
345_DMA_Pages LABEL WORD
346DMA_Pages dw 8 dup (NULL_PAGE) ; null for start
347_DMA_PAGE_COUNT LABEL WORD
348DMA_PAGE_COUNT dw 0 ; number of above initialised
349
350
351_DATA ends
352
353 page
354
355;------------------------------------------------------------------------------
356
357_TEXT segment
358 assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP
359
360;******************************************************************************
361;
362; InitDMA - initialize internal values for DMA registers of each channel
363;
364; ENTRY: Real Mode
365; DS = DGROUP
366;
367; EXIT: Real Mode
368; DGROUP:[DMARegSav] = DMA register save area initialized
369;
370;------------------------------------------------------------------------------
371
372InitDMA proc near
373
374 push eax
375 push di
376 push es
377
378 pushf
379 cli
380 cld
381
382 push ds
383 pop es ; ES = DGROUP
384
385 xor al,al
386 out DMA1_CLR_FF, al ; clear FF on first controller
387 mov [DMARegSav.DMAFF1], al ; reset S/W FF
388 jmp $+2
389 jmp $+2 ; timing
390;
391; initialize regs for channels 1,2,3
392;
393 InitDMARegSav 1
394 InitDMARegSav 2
395 InitDMARegSav 3
396
397 xor al,al
398 out DMA2_CLR_FF, al ; clear FF on second controller
399 mov [DMARegSav.DMAFF2], al ; reset S/W FF
400 jmp $+2
401 jmp $+2 ; timing
402;
403; initialize regs for channels 5,6,7
404;
405 InitDMARegSav 5
406 InitDMARegSav 6
407 InitDMARegSav 7
408
409 popf
410 pop es
411 pop di
412 pop eax
413 ret
414
415InitDMA endp
416
417;******************************************************************************
418;
419; DMABase(0-7) - Write/Read DMA Channel N Base Register
420;
421; ENTRY:
422; AL = byte to output to port
423; BX = port * 2
424; DH = 0 => Emulate Input
425; <>0 => Emulate Output
426;
427; EXIT:
428; AL = emulated input/output value from port.
429; CLC => I/O emulated or performed
430;
431;------------------------------------------------------------------------------
432DMABase0to7 proc near
433
434DMABase4: ; I/O port C0h
435DMABase5: ; I/O port C4h
436DMABase6: ; I/O port C8h
437DMABase7: ; I/O port CCh
438 push ax
439 push bx
440 push cx
441 push dx
442 push si
443;
444; Now, BX = port * 2 and DX = IO code
445; Code ported from Win/386 expects DX = port and BH = IO code
446;
447 xchg dx, bx
448 shr dx, 1
449 xchg bh,bl ; move IO code to bh
450
451 mov si, dx
452 sub si, 0B0h ; SI = Channel * 4
453 shl si, 2 ; SI = Channel * 16
454 mov bl, [DMARegSav.DMAFF2] ; get flip-flop
455 xor [DMARegSav.DMAFF2], 1 ; and toggle it
456 jmp short DMABaseN ;
457
458DMABase0: ; I/O port 00h
459DMABase1: ; I/O port 02h
460DMABase2: ; I/O port 04h
461DMABase3: ; I/O port 06h
462 push ax
463 push bx
464 push cx
465 push dx
466 push si
467;
468; Now, BX = port * 2 and DX = IO code
469; Code ported from Win/386 expects DX = port and BH = IO code
470;
471 xchg dx, bx
472 shr dx, 1
473 xchg bh,bl ; move IO code to bh
474
475 mov si, dx ; SI = Channel * 2
476 shl si, 3 ; SI = Channel * 16
477 mov bl, [DMARegSav.DMAFF1] ; get flip-flop
478 xor [DMARegSav.DMAFF1], 1 ; and toggle it
479
480;
481; FALL THROUGH!!!
482;
483
484;******************************************************************************
485;
486; DMABaseN - Write/Read DMA Channel N Base Register
487;
488; ENTRY: As above plus
489; SI = 16 * channel #
490;
491;------------------------------------------------------------------------------
492DMABaseN:
493 and bl, 1 ; Look at bit0 only - safety
494
495 or bh,bh ;Q: Input ?
496 jz short Base_rd_port ; Y: do Read operation
497 ; N: save value "written"
498 mov [SaveAL], al ; save AL in Save area.
499 xor bh, bh ; Make BX = Flip Flop state
500 mov byte ptr DMARegSav.DMALinAdr[bx][si], al
501
502 in al, dx ; Just a Dummy I/O to
503 ; toggle the real flip-flop
504 ; to match DMAFF above
505 jmp $+2
506 jmp $+2
507 xor bl,1 ; and the s/w one
508
509 call DMA_DMAFixup ; Translate Lin to Phys
510 ; & Update DMARegSav
511 call DMA_WrtAdrReg ; emulate the write
512 jmp short DBExit
513
514Base_rd_port:
515 in al, dx ; Toggle the real flop-flip
516;
517; bh is already zero, therefore BX = flip flop state
518;
519 mov al,byte ptr DMARegSav.DMALinAdr[bx][si]
520 mov [SaveAL], al
521DBExit:
522 pop si
523 pop dx
524 pop cx
525 pop bx
526 pop ax
527 mov al, [SaveAL]
528 clc
529 ret
530
531DMABase0to7 endp
532
533 page
534
535;******************************************************************************
536;
537; DMACnt(0-7) - Write/Read DMA Channel N Count Register
538;
539;ENTRY:
540; AL = byte to output to port.
541; BX = port * 2
542; DH = 0 => Emulate Input.
543; <>0 => Emulate Output.
544;
545;EXIT:
546; AL = emulated input/output value from port.
547; CLC => I/O emulated or performed
548;
549;------------------------------------------------------------------------------
550
551DMACnt0to7 proc near
552
553DMACnt4: ; I/O port C2h
554DMACnt5: ; I/O port C6h
555DMACnt6: ; I/O port CAh
556DMACnt7: ; I/O port CEh
557 push ax
558 push bx
559 push cx
560 push dx
561 push si
562;
563; Now, BX = port * 2 and DX = IO code
564; Code ported from Win/386 expects DX = port and BH = IO code
565;
566 xchg dx, bx
567 shr dx, 1
568 xchg bh,bl ; move IO code to bh
569
570 mov si, dx
571 sub si, 0B2h ; SI = 4 * channel #
572 shl si, 2 ; si = 16 * channel #
573 mov bl, [DMARegSav.DMAFF2] ; get flip-flop
574 xor [DMARegSav.DMAFF2], 1 ; toggle our flip-flop
575 jmp short DMACntN
576
577DMACnt0: ; I/O port 01h
578DMACnt1: ; I/O port 03h
579DMACnt2: ; I/O port 05h
580DMACnt3: ; I/O port 07h
581 push ax
582 push bx
583 push cx
584 push dx
585 push si
586;
587; Now, BX = port * 2 and DX = IO code
588; Code ported from Win/386 expects DX = port and BH = IO code
589;
590 xchg dx, bx
591 shr dx, 1
592 xchg bh,bl ; move IO code to bh
593
594 mov si, dx
595 dec si
596 shl si, 3 ; si = 16 * channel #
597 mov bl, [DMARegSav.DMAFF1] ; get flip-flop
598 xor [DMARegSav.DMAFF1], 1 ; toggle our flip-flop
599;
600; FALL THROUGH!!!
601;
602
603;******************************************************************************
604;
605; DMACntN - Write/Read DMA Channel N Count Register
606;
607; ENTRY: As DMACnt1to7 plus
608; si = 16 * channel #
609;
610;------------------------------------------------------------------------------
611DMACntN:
612 and bl, 1 ; Look at bit0 only - Safety
613
614 or bh,bh ;Q: Input ?
615 jz short DMA_CntN_rd ; Y: do Read operation
616 ; N: save value "written"
617 mov [SaveAL], al ; save AL in Save area.
618 xor bh, bh ; make BX = Flip Flop state
619 mov byte ptr DMARegSav.DMACount[bx][si], al ; save cnt
620 out dx, al ; do the I/O
621
622 xor bl,1 ; Toggle flip-flop for Wrt
623 call DMA_DMAFixup ; Translate Lin to Phys
624 ; & Update DMARegSav
625 call DMA_WrtAdrReg ; emulate the write
626 call DMALoadCount
627
628 jmp short DCExit
629DMA_CntN_rd:
630 xor bh,bh ; make BX = Flip Flop state
631 in al, dx ; Toggle the real flip-flop
632 ; to match bx above
633 mov [SaveAL], al
634
635 jmp $+2
636 jmp $+2
637 xor bl,1 ; and the s/w one
638;
639; get current count values from cntlr
640;
641 in al, dx ; get 2nd byte of Count reg
642 jmp $+2 ; timing ...
643 jmp $+2 ; timing ...
644 mov byte ptr DMARegSav.DMACount[bx][si], al ; save it
645 xor bl, 1 ; flip to other byte
646 in al, dx ; get 1st byte of Count reg
647 mov byte ptr DMARegSav.DMACount[bx][si], al ; save it
648DCExit:
649 pop si
650 pop dx
651 pop cx
652 pop bx
653 pop ax
654 mov al, [SaveAL]
655
656 clc ; I/O emulated, return
657 ret
658
659DMACnt0to7 endp
660
661 page
662;******************************************************************************
663;
664; DMAPgN - Write/Read DMA Channel N Page Register
665;
666; ENTRY:
667; AL = byte to output to port
668; BX = port * 2
669; DX = 0 => Emulate Input
670; <>0 => Emulate Output
671; si = 2 * Channel #
672;
673; EXIT:
674; AL = emulated input/output value from port.
675; CLC => I/O emulated or performed
676;
677; USED: EBX,Flags
678; STACK:
679;
680; NOTES: For channels 0-4, DMACount is in Bytes, and
681; DMALinAdr holds the address as:
682;
683; +-----------+-----------+----------------------+
684; | 31-24 | 23-16 | 15-0 |
685; +-----------+-----------+----------------------+
686; | 0000 0000 | A23-A16 | A15-A0 |
687; +-----------+-----------+----------------------+
688;
689; For channels 5-7, DMACount is in Words, and
690; DMALinAdr holds the address as:
691;
692; +-----------+-----------+----------------------+
693; | 31-24 |23-17 | 16 | 15-0 |
694; +-----------+-----------+----------------------+
695; | 0000 0000 |A23-A17 |0 | A16-A1 |
696; +-----------+-----------+----------------------+
697;
698;
699;------------------------------------------------------------------------------
700DMAPg0to7 proc near
701
702DMAPg0:
703 push si
704 mov si,0*16 ; si = 16 * channel #
705 jmp short DMAPgN
706DMAPg1:
707 push si
708 mov si,1*16 ; si = 16 * channel #
709 jmp short DMAPgN
710DMAPg2:
711 push si
712 mov si,2*16 ; si = 16 * channel #
713 jmp short DMAPgN
714DMAPg3:
715 push si
716 mov si,3*16 ; si = 16 * channel #
717 jmp short DMAPgN
718DMAPg5:
719 push si
720 mov si,5*16 ; si = 16 * channel #
721 jmp short DMAPgN
722DMAPg6:
723 push si
724 mov si,6*16 ; si = 16 * channel #
725 jmp short DMAPgN
726DMAPg7:
727 push si
728 mov si,7*16 ; si = 16 * channel #
729; FALL THROUGH
730
731;----------------------------------------------------------------------
732; DMAPgN - Common Page Code
733;
734; ENTRY: As above plus
735; si = 16 * Channel #
736;
737;----------------------------------------------------------------------
738
739DMAPgN:
740 push ax
741 push bx
742 push cx
743 push dx
744;
745; Now, BX = port * 2 and DX = IO code
746; Code ported from Win/386 expects DX = port and BH = IO code
747;
748 xchg dx, bx
749 shr dx, 1
750 xchg bh,bl ; move IO code to bh
751
752 or bh,bh ;Q: Input ?
753 jz short Pg_rd_port ; Y: do Read operation
754
755 mov [SaveAL], al ; save AL in Save area.
756;
757; Get s/w FF for WrtAdrReg
758;
759 mov bl, [DMARegSav.DMAFF1] ; Assume Chan 1 FF
760 cmp si, 4*16 ; Q: Addr for 2nd controller
761 jb short PgN_FF ; A: No, FF is correct
762 mov bl, [DMARegSav.DMAFF2] ; Chan 2 FF
763PgN_FF:
764 xor bh, bh ; make BX = flip-flop state
765
766 mov byte ptr DMARegSav.DMALinAdr.HighWord[si], al ; save value
767 call DMA_DMAFixup ; Translate Lin to Phys
768 ; & Update DMARegSav
769 call DMA_WrtAdrReg ; emulate the write
770 jmp short DPExit
771Pg_rd_port:
772 mov al, byte ptr DMARegSav.DMALinAdr.HighWord[si]
773 mov [SaveAL], al
774DPExit:
775 pop dx
776 pop cx
777 pop bx
778 pop ax
779 pop si
780 mov al, [SaveAL]
781 clc
782 ret
783
784DMAPg0to7 endp
785
786 page
787
788;******************************************************************************
789;
790; DMAClrFF1 - Reset Controller 1's FlipFlop
791; DMAClrFF2 - Reset Controller 2's FlipFlop
792;
793; ENTRY:
794; AL = byte to output to port.
795; BX = port * 2
796; DH = 0 => Emulate Input.
797; <>0 => Emulate Output.
798;
799; EXIT:
800; AL = emulated input/output value from port.
801; CLC => I/O emulated or performed
802;
803;------------------------------------------------------------------------------
804
805DMAClrFF1 proc near
806 push ax
807 push bx
808 push cx
809 push dx
810;
811; Now, BX = port * 2 and DX = IO code
812; Code ported from Win/386 expects DX = port and BH = IO code
813;
814 xchg bx, dx
815 shr dx, 1
816 xchg bh,bl ; move IO code to bh
817
818 or bh,bh ;Q: Input ?
819 jz short DMA_CLF_RdEm ; Y: Let it go
820 out dx, al ; N: do it
821 mov [DMARegSav.DMAFF1], 0
822 jmp short DMACFFexit
823DMA_CLF_RdEm:
824 in al,dx ; do the read
825DMACFFexit:
826 pop dx
827 pop cx
828 pop bx
829 pop ax
830 clc
831 ret
832
833DMAClrFF1 endp
834
835DMAClrFF2 proc near
836
837 push ax
838 push bx
839 push cx
840 push dx
841;
842; Now, BX = port * 2 and DX = IO code
843; Code ported from Win/386 expects DX = port and BH = IO code
844;
845 xchg bx, dx
846 shr dx, 1
847 xchg bh,bl ; move IO code to bh
848
849 or bh,bh ;Q: Input ?
850 jz DMA_CLF_RdEm ; Y: Let it go
851 out dx, al ; N: do it
852 mov [DMARegSav.DMAFF2], 0
853 jmp DMACFFexit
854
855DMAClrFF2 endp
856
857 page
858;******************************************************************************
859;
860; DMAMode1 - Track Controller 1's Mode Register
861; DMAMode2 - Track Controller 2's Mode Register
862;
863; ENTRY:
864; AL = byte to output to port.
865; BX = port * 2
866; DX = 0 => Emulate Input.
867; <>0 => Emulate Output.
868;
869; EXIT:
870; AL = emulated input/output value from port.
871; CLC => I/O emulated or performed
872;
873;------------------------------------------------------------------------------
874
875DMAMode1 proc near
876 push ax
877 push bx
878 push cx
879 push dx
880 push si
881;
882; Now, BX = port * 2 and DX = IO code
883; Code ported from Win/386 expects DX = port and BH = IO code
884;
885 xchg bx, dx
886 shr dx, 1
887 xchg bh,bl ; move IO code to bh
888
889 or bh,bh ;Q: Input ?
890 jz short DMA_Mread ; Y: Let it go
891
892 mov [SaveAL], al ; save AL in Save area.
893 xor ah, ah
894 mov si, ax
895 and si, DMA_M_CHANNEL
896 mov bl, al
897 and bl, NOT DMA_M_16BIT ; 8 bit xfers for controller 1
898DMA_Mboth:
899 shl si, 4 ; Channel * 16
900 mov [DMARegSav.DMAMode][si], bl
901 out dx, al ; N: do it
902 jmp short DMExit
903
904DMA_Mread:
905 in al, dx ; do the read
906 mov [SaveAL], al
907DMExit:
908 pop si
909 pop dx
910 pop cx
911 pop bx
912 pop ax
913 mov al, [SaveAL]
914 clc
915 ret
916DMAMode1 endp
917
918DMAMode2 proc near
919
920 push ax
921 push bx
922 push cx
923 push dx
924 push si
925;
926; Now, BX = port * 2 and DX = IO code
927; Code ported from Win/386 expects DX = port and BH = IO code
928;
929 xchg bx, dx
930 shr dx, 1
931 xchg bh,bl ; move IO code to bh
932
933 or bh,bh ;Q: Input ?
934 jz DMA_Mread ; Y: Let it go
935
936 mov [SaveAL], al ; save AL in Save area.
937 xor ah, ah
938 mov si, ax
939 and si, DMA_M_CHANNEL
940 add si, 4 ; Channel 4 to 7
941 mov bl, al
942 or bl, DMA_M_16BIT ; 16 bit for controller 2
943 jmp DMA_Mboth
944
945DMAMode2 endp
946
947; INCLUDE VDMAD2.ASM
948
949 page
950;******************************************************************************
951;DMA_GetLinAdr - return Linear Address, count and mode from DMARegSave area
952;
953; ENTRY:
954; si = channel # * 16
955; DS assume DGROUP
956;
957; EXIT:
958; EAX = linear Base Address
959; ECX = SIZE of transfer (bytes)
960; DL = Mode register
961;
962; USED: Flags
963; STACK:
964;------------------------------------------------------------------------------
965DMA_GetLinAdr proc near
966
967 mov eax, dword ptr DMARegSav.DMALinAdr[si]
968 mov ecx, dword ptr DMARegSav.DMACount[si]
969 mov dl, byte ptr DMARegSav.DMAMode[si]
970 inc ecx ; ECX = SIZE of transfer
971 test dl, DMA_M_16BIT ; Word transfer?
972 jz short GLexit ; N: no special treatment
973
974 DMA_WADDR_TO_BADDR ; Y: fixup values from regs
975GLexit:
976 ret
977
978DMA_GetLinAdr endp
979
980 page
981;******************************************************************************
982; DMA_SetPhyAdr - Load the Page and Base DMA registers with the input
983; Physical Address and save this addr as current phy addr.
984;
985; ENTRY:
986; EAX = physical address
987; SI = DMA channel # * 16
988; DS -> DGROUP
989;
990; USED: Flags
991;------------------------------------------------------------------------------
992DMA_SetPhyAdr proc near
993;
994 push eax
995 push bx
996 push dx
997
998 xor bh, bh
999 mov bl, [DMARegSav.DMAFF1]
1000 cmp si,4*16 ; 2nd cntlr?
1001 jb short DMA_SPA1
1002 mov bl, [DMARegSav.DMAFF2] ; yes, other flip-flop
1003DMA_SPA1:
1004 test [DMARegSav.DMAMode][si], DMA_M_16BIT ; word transfer?
1005 jz short SaveIt ; no, no translation
1006 DMA_BADDR_TO_WADDR
1007SaveIt:
1008 mov dword ptr DMARegSav.DMAPhyAdr[si], eax
1009
1010 ; set page register
1011 xor dh, dh
1012 mov dl, byte ptr DMARegSav.DMAPagePort[si]
1013 mov al, byte ptr DMARegSav.DMAPhyAdr.HighWord[si]
1014 out dx, al
1015
1016 ; set base address register
1017 mov dl, byte ptr DMARegSav.DMABasePort[si]
1018 mov al, byte ptr DMARegSav.DMAPhyAdr[si][bx]
1019 out dx,al ; send out 1st byte
1020 xor bl,1 ; toggle FF
1021 jmp $+2
1022 jmp $+2
1023 mov al, byte ptr DMARegSav.DMAPhyAdr[si][bx]
1024 out dx,al ; send out other byte
1025 xor bl,1 ; toggle FF to original state
1026
1027 pop dx
1028 pop bx
1029 pop eax
1030 ret
1031;
1032DMA_SetPhyAdr endp
1033
1034 page
1035;******************************************************************************
1036; DMALoadCount - Load the Count DMA register with the input
1037;
1038; ENTRY:
1039; si = DMA channel # * 16
1040;
1041;------------------------------------------------------------------------------
1042DMALoadCount proc near
1043 push bx
1044 push ax
1045 push dx
1046
1047 xor bh, bh
1048 mov bl, byte ptr [DMARegSav.DMAFF1]
1049 cmp si,4*16 ;Q: Adrs from 2nd cntlr
1050 jb short DMA_SC1 ; N: save it as is
1051 mov bl, byte ptr [DMARegSav.DMAFF2]
1052
1053DMA_SC1:
1054 mov dl, byte ptr DMARegSav.DMACntPort[si]
1055 xor dh, dh
1056 mov al, byte ptr DMARegSav.DMACount[bx][si]
1057 out dx, al
1058 jmp $+2
1059 jmp $+2
1060 xor bl, 1
1061 mov al, byte ptr DMARegSav.DMACount[bx][si]
1062 out dx, al
1063
1064 pop dx
1065 pop ax
1066 pop bx
1067 ret
1068
1069DMALoadCount endp
1070
1071 page
1072;******************************************************************************
1073; DMA_DMAFixup - Fixup Linear to Physical mapping for DMA
1074;
1075; ENTRY:
1076; SI = 16 * channel #
1077; DS assume DGROUP
1078;
1079; EXIT:
1080; DMARegSav is updated
1081;
1082; USED: flags, registers (calls a C program, so most registers are trashed)
1083;
1084; Check to see if DMA Page fixup is needed.
1085; We test for the following cases for optimization:
1086; Lin Base Add == Lin Page Reg == 0, assume that transfer addr
1087; is not yet valid
1088;
1089;------------------------------------------------------------------------------
1090DMA_DMAFixup proc near
1091 ;Q: LinAddr = 0?
1092
1093 mov eax, dword ptr DMARegSav.DMALinAdr[si]
1094 or eax,eax
1095 jz short DMA_nofixup ; Y:DMA not programmed yet
1096 ;Do the fixup.....
1097 pushfd ; ENABLE INTERRUPTS!
1098 push bx ; C code trashes these regs
1099 push es
1100;
1101; long SwapDMAPages(LinAdr, Len, XferSize);
1102; long LinAdr, Len;
1103; unsigned XferSize; 0/1 Byte/word Xfer
1104;
1105 movzx eax, [DMARegSav.DMAMode][si]
1106 and al, DMA_M_16BIT ; Non-zero for 16bit transfer
1107 push ax ; push XferSize
1108
1109 call DMA_GetLinAdr
1110 push ecx ; push count
1111 push eax ; push LinAdr
1112;
1113; C code saves di si bp ds ss sp
1114
1115 call _SwapDMAPages ; C program to do the dirty work
1116
1117 xchg ax, dx
1118 shl eax, 16
1119 mov ax, dx ; eax = returned value
1120
1121 add sp, 10 ; clean up stack
1122
1123 pop es
1124 pop bx
1125 popfd ; Restore original FLAGS state
1126
1127 test [DMARegSav.DMAMode][si], DMA_M_16BIT ; word transfer?
1128 jz short SavIt ; no, no translation
1129 DMA_BADDR_TO_WADDR ; Y: Put in special format
1130SavIt:
1131 mov dword ptr DMARegSav.DMAPhyAdr[si], eax
1132 clc ; Done fixup
1133 ret
1134DMA_nofixup:
1135 stc
1136 ret
1137
1138DMA_DMAFixup endp
1139
1140 page
1141;******************************************************************************
1142; DMA_WrtAdrReg - Write registers associated with DMA address
1143;
1144; ENTRY:
1145; BX = Flip Flop State, 0 or 1
1146; SI = channel # * 16
1147; DS assume DGROUP
1148; Uses Values in DMARegSav
1149;
1150; EXIT:
1151;
1152; USED: Flags, EAX
1153; STACK:
1154;------------------------------------------------------------------------------
1155DMA_WrtAdrReg proc near
1156
1157; Must Update Page and Base registers simultaneously when remapping occurs...
1158 push bx
1159 push dx
1160
1161 and bx, 1 ; Lose extra bit just in case...
1162 ; Base Register...
1163 xor dh, dh ; clear high byte
1164
1165 ; NOTE: Internal flip-
1166 ; flop flag not updated,
1167 ; since we write twice....
1168 ; BX = flip flop state
1169
1170 mov dl, byte ptr DMARegSav.DMABasePort[si]
1171 mov al, byte ptr DMARegSav.DMAPhyAdr[bx][si]
1172 out dx, al ; output the byte
1173 jmp $+2 ; timing
1174 jmp $+2 ; timing
1175 xor bx, 1 ; toggle flip-flop
1176
1177 mov al, byte ptr DMARegSav.DMAPhyAdr[bx][si]
1178 out dx, al ; output the byte
1179 jmp $+2 ; timing
1180 jmp $+2 ; timing
1181 xor bx, 1 ; toggle flip-flop
1182
1183 ; Page Register...
1184 mov al, byte ptr DMARegSav.DMAPhyAdr.HighWord[si] ; fetch value
1185 mov dl, byte ptr DMARegSav.DMAPagePort[si]
1186 out dx,al ; output the byte
1187
1188 pop dx
1189 pop bx
1190 ret
1191
1192DMA_WrtAdrReg endp
1193
1194 page
1195;******************************************************************************
1196; InitELIM - initialize LIM h/w trapping data structures and
1197; I/O bit map for this ports.
1198;
1199; NOTE: this is a FAR routine
1200;
1201; ENTRY: Real Mode
1202;
1203; EXIT: Real Mode
1204; TSS:[IOBitMap] - LIM addresses entered in I/O bit map
1205;
1206; USED: Flags
1207; STACK:
1208;------------------------------------------------------------------------------
1209InitELIM proc far
1210
1211 push ax
1212 push bx
1213 push cx
1214 push si
1215 push di
1216 push ds
1217 push es
1218
1219 cld
1220
1221 mov ax,seg DGROUP
1222 mov ds,ax
1223;
1224; now set entries in I/O Bit Map
1225;
1226 mov ax,TSS
1227 mov es,ax ; ES -> TSS
1228;
1229; now set DMA ports in I/O Bit Map
1230;
1231 mov cx,LIMDMAP_CNT
1232 mov si,offset DGROUP:DMAP_Page ; DS:SI -> DMA ports
1233 mov bx,8000h ; trap it every 1k
1234IE_maploop:
1235 lodsw ; AX = port to trap
1236 call PortTrap ; set bit(s) for this port
1237 loop IE_maploop ;if more ...
1238
1239 pop es
1240 pop ds
1241 pop di
1242 pop si
1243 pop cx
1244 pop bx
1245 pop ax
1246 ret
1247
1248InitELIM endp
1249
1250
1251;
1252; C callable routines for manipulating page table entries.
1253; and Current FRS - CurRegSet
1254
1255
1256;
1257; Equates for picking up arguments passed in from C code.
1258; Arg1 - word Arg,
1259; Arg2 - word or dword Arg
1260;
1261
1262Arg1 equ [BP+4]
1263Arg2 equ [BP+6]
1264
1265
1266;*****************************************************************************
1267;
1268; _GetPte - called from C code
1269;
1270; return pte in dx:ax
1271;
1272; long GetPte(PTIndex)
1273; unsigned PTIndex;
1274;
1275; Written: JHB Aug 10,1988
1276; Modif: ISP Aug 12,1988 parameter should be returned in dx:ax not eax
1277; removed some of pushes and pops
1278; added cld before load just to be safe
1279; offset specified in DGROUP
1280;
1281; JHB Aug 21 88 changed input param to PTIndex
1282;
1283;*****************************************************************************
1284
1285_GetPte proc near
1286
1287 push bp
1288 mov bp, sp
1289 push si
1290 push ds
1291
1292 mov ax, PAGET_GSEL
1293 mov ds, ax
1294
1295 mov si, WORD PTR Arg1
1296 shl si, 2 ; dword entries in the PT
1297
1298 cld
1299 lodsw ; get low word
1300 mov dx, ax ; into dx
1301 lodsw ; get hiword
1302 xchg dx, ax ; dx:ax = long return value
1303
1304 pop ds
1305 pop si
1306 pop bp
1307 ret
1308_GetPte endp
1309
1310;*****************************************************************************
1311;
1312; _SetPte - called from C code
1313;
1314; Locate the PT entry for given EmmPhyPage and set it to pte.
1315;
1316; SetPte(PTIndex, pte)
1317; unsigned PTIndex;
1318; long pte;
1319;
1320; WRITTEN: JHB Aug 10,1988
1321; MODIF: ISP Aug 12,1988 pushes and pops removed
1322; cld added for safety
1323; offset specified in DGROUP
1324; pushed poped eax (check on this)
1325;
1326; JHB Aug 21, 1988 changed first input param to PTIndex
1327;
1328;*****************************************************************************
1329
1330
1331_SetPte proc near
1332
1333 push bp
1334 mov bp, sp
1335 push di
1336 push es
1337
1338 mov ax, PAGET_GSEL
1339 mov es, ax
1340 mov di, WORD PTR Arg1
1341 shl di, 2
1342
1343 mov eax, DWORD PTR Arg2
1344 and ax, 0F000H ; clear low 12 bits
1345 or ax, P_AVAIL ; page control bits - user, present, write
1346
1347 cld
1348 stosd
1349;
1350; reload CR3 to flush TLB
1351;
1352 mov eax, CR3
1353 mov CR3, eax
1354
1355; mov eax,dword ptr [Page_Dir] ; mov EAX,dword ptr [Page_Dir]
1356; db 0Fh,22h,18h ; mov CR3,EAX
1357
1358 pop es
1359 pop di
1360 pop bp
1361 ret
1362_SetPte endp
1363
1364;*****************************************************************************
1365;
1366; _GetCRSEntry - called from C code
1367;
1368; return the Emm page mapped to the EmmPhyPage by looking up CurRegSet.
1369;
1370; unsigned GetCRSEntry(EmmPhyPage)
1371; unsigned EmmPhyPage
1372;
1373; WRITTEN: JHB Aug 10,1988
1374; MODIF: ISP Aug 12,1988 pushes and pops removed
1375; Offset specified in DGROUP
1376; cld added for safety
1377;*****************************************************************************
1378
1379_GetCRSEntry proc near
1380
1381 push bp
1382 mov bp, sp
1383 push di
1384
1385 mov bx, WORD PTR Arg1
1386 shl bx, 1 ; each FRS entry is a word
1387 Get_FRS_Window DI ; di = address of Current FRS
1388 add di, bx
1389 mov ax, word ptr [di] ; load FRS entry
1390
1391 pop di
1392 pop bp
1393 ret
1394_GetCRSEntry endp
1395
1396;
1397; Equates for picking up long Arguments from C code
1398; LArg1 - long Arg
1399; Larg2 - long Arg when the first Arg is also long
1400;
1401
1402LArg1 equ [BP+4]
1403LArg2 equ [BP+8]
1404
1405;*****************************************************************************
1406;
1407; _GetDMALinAdr - called from C code
1408;
1409; returns the Lin Adr for the DMA buffer whose physical adr is given
1410;
1411; long GetDMALinAdr(DMAPhyAdr)
1412; long DMAPhyAdr;
1413;
1414; Get the Linear address for DMAPhyAdr. There is a pte which always
1415; maps to this always. MapLinear translates DMAPhyAdr to a linear adr.
1416;
1417;
1418; 8/12/88 JHB removed _Copy16K, changed it to this routine.
1419;
1420;*****************************************************************************
1421
1422_GetDMALinAdr proc near
1423
1424 push bp
1425 mov bp, sp
1426 push si
1427 push di
1428 push ds
1429;
1430; convert the DMAPhyAdr into a linear address.
1431;
1432 mov eax, dword ptr LArg1
1433 call MapLinear
1434;
1435; eax = 32 bit linear adr for the DMA Xfer area.
1436;
1437 ror eax, 16
1438 mov dx, ax
1439 ror eax, 16 ; dx:ax 32 bit linear adr to be returned
1440
1441 pop ds
1442 pop di
1443 pop si
1444 pop bp
1445 ret
1446_GetDMALinAdr endp
1447
1448;******************************************************************************
1449;
1450; set_selector - set up a selector address/attrib
1451;
1452; ENTRY: EAX = address for GDT selector - a linear address
1453; DI = GDT selector
1454; EXIT: selector in DI is writeable data segment,128k long and points
1455; to desired address.
1456;
1457;******************************************************************************
1458
1459set_selector proc near
1460
1461 push eax
1462 push di
1463 push es
1464
1465 and di,NOT 07h ; just in case... GDT entry
1466 push GDTD_GSEL
1467 pop es ; ES:DI -> selector entry
1468
1469 mov es:[di+2],ax ; low word of base address
1470
1471 shr eax,16 ; AX = high word of address
1472 mov es:[di+4],al ; low byte of high word of address
1473 xor al,al ; clear limit/G bit
1474 or al, 1 ; set LSB0 i.e. Limit16 bit for 128K Xfer
1475 mov es:[di+6],ax ; set high byte of high word of addr
1476 ; and high nibble of limit/G bit
1477 ; and Limit Bit 16 for 128K transfer
1478 mov ax,0FFFFh
1479 mov es:[di],ax ; set limit bits 0-15
1480
1481 mov al,D_DATA0 ; writeable DATA seg / ring 0
1482 mov es:[di+5],al
1483
1484 pop es
1485 pop di
1486 pop eax
1487
1488 ret
1489
1490set_selector endp
1491
1492;****************************************************************************
1493; _Exchange16K - called from C
1494;
1495; Exchange contents of the pages at LinAdr1 and LinAdr2
1496;
1497; Exchange16K(LinAdr1, LinAdr2)
1498; long LinAdr1, LinAdr2;
1499;
1500; Written: JHB Aug 11, 1988
1501; ISP Aug 12, 1988 Added cld.
1502; DWORD PTR mentioned explicitly
1503;*****************************************************************************
1504
1505_Exchange16K proc near
1506
1507 push bp
1508 mov bp, sp
1509 push si
1510 push di
1511 push ds
1512
1513 mov di,MBSRC_GSEL ; source selector
1514 mov eax,dword ptr LArg1 ; load linear adr
1515 call set_selector ; set up a selector in GDT
1516 mov es,di
1517
1518 mov di,MBTAR_GSEL ; destination selector
1519 mov eax,dword ptr LArg2
1520 call set_selector ; set up selector
1521 mov ds,di
1522 mov cx,1000h ; 16k bytes (4 at a time)
1523 xor di,di ; initialize index
1524 cld
1525sloop:
1526 mov eax,dword ptr es:[di] ; pick a dword at LArg1
1527 xchg eax,dword ptr ds:[di] ; swap with dword at LArg2
1528 stosd ; store new dword at LArg1
1529 loop sloop
1530
1531 pop ds
1532 pop di
1533 pop si
1534 pop bp
1535 ret
1536
1537_Exchange16K endp
1538
1539;
1540; signals an exception error
1541;
1542_FatalError proc near
1543
1544 push bp
1545 mov bp, sp
1546
1547 mov ax, 1
1548 mov bx, 3
1549 call ErrHndlr
1550
1551 pop bp
1552 ret
1553
1554_FatalError endp
1555
1556_TEXT ends ; end of segment
1557
1558end ; end of module
1559
1560 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/EM286LL.ASM b/v4.0/src/MEMM/MEMM/EM286LL.ASM
new file mode 100644
index 0000000..3b3f72e
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EM286LL.ASM
@@ -0,0 +1,360 @@
1
2
3page 58,132
4;******************************************************************************
5 title EM286LL - 386 routine to emulate 286 LOADALL
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: EMM286LL - 286 loadall emulation routine
13;
14; Version: 0.04
15;
16; Date: April 11,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 04/16/86 Original
27; 05/12/86 A Cleanup and segment reorganization
28; 06/18/86 0.01 Moved EL_Off before buffer
29; 06/28/86 0.02 Name change from MEMM386 to MEMM
30; 06/28/86 0.02 Modified CR0 logic & Edi for LL3 buffer
31; 07/03/86 0.03 Removed logic for enabling A20 watch
32; 07/06/86 0.04 Change assume to DGROUP
33;
34;******************************************************************************
35;
36; Functional Description:
37;
38; 286 LOADALL is emulated by building a buffer for a
39; 386 LOADALL from the 286 LOADALL buffer (@80:0) and executing the 386
40; LOADALL.
41;
42;
43;******************************************************************************
44.lfcond ; list false conditionals
45.386p
46 page
47;******************************************************************************
48; P U B L I C D E C L A R A T I O N S
49;******************************************************************************
50;
51 public EM286ll
52 public ELOff
53;
54 page
55;******************************************************************************
56; L O C A L C O N S T A N T S
57;******************************************************************************
58;
59 include loadall.inc
60 include VDMseg.inc
61 include desc.inc
62 include VDMsel.inc
63 include instr386.inc
64 include vm386.inc
65 include oemdep.inc
66
67FALSE equ 0
68TRUE equ not FALSE
69
70;
71; DescCopy
72; Macro for copying a 286 Loadall descriptor cache entry to a
73; 386 Loadall descriptor cache entry.
74; ENTRY: DS:SI pts to 286 Loadall descriptor entry
75; ES:DI pts to 386 Loadall descriptor entry
76;
77; EXIT: DS:SI unchanged.
78; ES:DI pts to byte after 386 Loadall descriptor entry (next entry).
79; *** The access rights byte in set to DPL 3 for virtual mode ***
80;
81; USED: EAX
82;
83DescCopy MACRO
84 XOR_EAX_EAX ; clear EAX
85 mov ax,word ptr [si.dc2_BASEhi] ; AL = junk, AH = Access rights
86 or ah,D_DPL3 ;* set DPL 3 for virtual mode access
87 OP32
88 stosw ; store: junk->AR1,AR->AR2,0->AR3 & AR4
89 OP32
90 mov ax,[si] ; 24 bits of Base Addr from 286 entry
91 OP32
92 and ax,0FFFFh ; AND EAX,00FFFFFFh
93 dw 000FFh ; clear high byte of base addr
94 call MapLinear ; Map address according to page tables
95 OP32
96 stosw ; store Base Addr for 386 entry
97 XOR_EAX_EAX ; clear EAX
98 mov ax,[si.dc2_LIMIT] ; get low 16 bits of limit
99 OP32
100 stosw ; store 32 bit LIMIT into 386 entry
101 ENDM
102;
103; CurCopy
104; Macro for copying a current descriptor cache entry to a
105; 386 Loadall descriptor cache entry.
106; ENTRY: DS:BX pts to current descriptor
107; ES:DI pts to 386 Loadall descriptor entry
108;
109; EXIT: DS:BX unchanged.
110; ES:DI pts to byte after 386 Loadall descriptor entry (next entry).
111; *** The access rights byte in set to DPL 3 for virtual mode ***
112;
113; USED: EAX
114;
115CurCopy MACRO
116 OP32
117 mov ax,[bx+4] ; get AR info
118 or ah,D_DPL3 ;* set DPL 3 for virtual mode access
119 OP32
120 stosw ; store into cache entry
121 mov ah,[bx+7] ; AX = Base[31..16]
122 OP32
123 shl ax,16 ; high word of EAX = Base[31..16]
124 mov ax,[bx+2] ; EAX = Base[31..0]
125 OP32
126 stosw
127 mov al,[bx+6] ; LIMIT[19..16] in low bits of AL
128 and ax,0Fh
129 OP32
130 shl ax,16 ; high word of EAX = LIMIT[31..16]
131 ; NOTE: VDM does not use page
132 ; granularity for limit field !!
133 mov ax,[bx] ; EAX = LIMIT[31..0]
134 OP32
135 stosw ; store into cache for 386 buffer
136 ENDM
137;******************************************************************************
138; E X T E R N A L R E F E R E N C E S
139;******************************************************************************
140;
141L286BUFF segment at 80h
142;
143; Source 286 LoadAll buffer
144;
145SLBuff LoadAllBuf286 <> ; 286 loadall buffer
146
147L286BUFF ends
148
149_TEXT segment
150
151 extrn MapLinear:near ; map linear address
152 extrn PortTrap:near ; IOBM trap set function (VMINIT)
153
154_TEXT ends
155
156;
157;******************************************************************************
158; L O C A L D A T A A R E A
159;******************************************************************************
160
161_DATA segment
162
163ELOff dw offset ELbuff ; offset of 386 loadall buffer
164ELbuff LoadAllBuf386 <> ; 386 loadall buffer
165 dd 0 ; filler - allow dword align
166
167;(0.03)extrn A20watch:byte ; Loadall/KBD A20 disable flag
168
169_DATA ends
170
171 page
172;******************************************************************************
173; S E G M E N T D E F I N I T I O N
174;******************************************************************************
175;
176_TEXT segment
177 ASSUME CS:_TEXT,DS:DGROUP,ES:DGROUP
178
179;******************************************************************************
180; EM286ll - emulate 286 Loadall
181;
182; ENTRY: Protected Mode
183; physical address 80:0 holds 286 loadall buffer info
184;
185; EXIT: via Loadall to virtual mode
186; The 286 Loadall buffer is emulated with the following
187; exceptions:
188; The VM bit is set in EFLAGS.
189; The TR, IDT descriptor cache, & TSS descriptor cache are
190; pointed to the VDM entries.
191;
192; USED:
193;
194;******************************************************************************
195EM286ll proc near
196 mov bx,GDTD_GSEL ; get GDT data alias
197 mov ds,bx ; DS -> GDT
198 mov bx,800h ; BX = VM CS (segment form)
199 mov ds:[VM1_GSEL+2],bx ; place in descriptor
200 xor bx,bx
201 mov ds:[VM1_GSEL+4],bh ; place in descriptor
202 mov bx,VM1_GSEL
203 mov ds,bx ; DS:0 points to 286 loadall buffer
204 ASSUME DS:L286BUFF
205;
206 mov ax,VDMD_GSEL
207 mov es,ax
208 mov di,ES:[ELOff] ; ES:DI pts to 386 loadall buffer
209;
210 cld
211;
212 MOV_EAX_CR0 ; mov EAX,CR0
213 and ax,0FFF1h ;clear current TS,EM, & MP bits
214 mov cx,[SLBuff.ll2_MSW] ; CX = 286 ll_buff MSW
215 and cx,000Eh ;retain 286 TS,EM, & MP bits
216 or ax,cx ; set client's TS,EM, & MP bits
217 OP32
218 stosw ; store CR0 for 386 buffer
219;
220 OP32
221 mov ax,0000h
222 dw 0002h ; VM bit on
223 mov ax,[SLBuff.ll2_FLAGS] ; get low word of flags
224 or ax,3000h ; set IOPL to 3
225 OP32
226 stosw ; store EFLAGS for 386 buffer
227;
228 XOR_EAX_EAX ; clear EAX
229 mov ax,[SLBuff.ll2_IP] ; get 286 IP - high word of EAX clear
230 OP32
231 stosw ; store EIP for 386 buffer
232;
233; Copy the client's EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX
234; register images from his 386 loadall buffer to our 386 loadall buffer
235;
236 mov si,offset ll2_DI ; DS:SI pts to DI in 286 buffer
237 mov cx,8
238CopyGen: ; Copy General Purpose Registers
239 lodsw ; EAX = reg image from client's buffer
240 OP32
241 stosw ; store it in our 386 buffer
242 loop CopyGen
243
244;
245; 386 debug registers
246;
247 MOV_EAX_DR6
248 OP32
249 stosw ; store DR6 in our 386 buffer
250
251 MOV_EAX_DR7
252 OP32
253 stosw ; store DR7 in our 386 buffer
254;
255 XOR_EAX_EAX ; clear EAX
256;
257 mov ax,TSS_GSEL ; get current TR for VDM's TSS !!!
258 OP32
259 stosw ; store TR for 386 buffer
260;
261 mov si,offset ll2_LDT ; DS:SI pts to LDT in 286 buffer
262 lodsw ; get LDT entry from 286 buffer
263 OP32
264 stosw ; store LDT for 386 buffer
265
266 OP32
267 stosw ; store junk into GS for 386 buffer
268
269 OP32
270 stosw ; store junk into FS for 386 buffer
271
272;
273; Copy the client's DS, SS, CS, ES register images from his 286 loadall
274; buffer to our 386 loadall buffer
275;
276 mov cx,4
277CopySeg: ; Copy Segment Registers
278 lodsw ; get seg image from client's buffer
279 OP32
280 stosw ; store it in our 386 buffer
281 loop CopySeg
282
283 ; ES:DI pts to 386 TSS cache entry
284;
285; Copy the current TSS, IDT, & GDT descriptors from the GDT table to
286; our 386 loadall buffer
287;
288 push ds ; save client's buffer selector
289 mov ax,GDTD_GSEL
290 mov ds,ax
291
292 mov cx, 3
293 mov bx, TSS_GSEL
294 push word ptr GDTD_GSEL
295 push word ptr IDTD_GSEL
296
297CopyCur: ; Copy current descriptors
298 CurCopy ; DS:[BX] points to current descriptor
299 pop bx
300 loop CopyCur
301 mov ds, bx ; restore client's buffer selector
302
303;
304 ; ES:DI pts to 386 LDT cache entry
305 mov si,offset ll2_LDTcache ; DS:SI pts to 286 LDT cache entry
306 DescCopy ; store LDT cache for 386 buffer
307;
308 XOR_EAX_EAX ; clear EAX- use 0 for GS/FS caches
309
310 OP32
311 stosw ; store GS cache for 386 buffer
312 OP32
313 stosw
314 OP32
315 stosw
316;
317 OP32
318 stosw ; store FS cache for 386 buffer
319 OP32
320 stosw
321 OP32
322 stosw
323;
324; Copy the client's DS, SS, CS, ES register cache images from
325; his 286 loadall buffer to our 386 loadall buffer
326;
327 mov si,offset ll2_DScache ; DS:SI pts to 286 DS cache entry
328 mov cx,4
329CopyCac: ; ES:DI pts to our 386 ll cache entry
330 DescCopy ; store his cache in our 386 buffer
331 sub si,06h ; DS:SI pts to client's cache entry
332 loop CopyCac
333;
334; 386 Loadall buffer complete
335;
336
337;(0.03) push es
338;(0.03) mov ax, TSSD_GSEL ; Point ES to TSS for PortTrap
339;(0.03) mov es, ax
340;(0.03) mov bh, 80h ; set every 1k
341;(0.03) mov ax, KbdDataPort
342;(0.03) call PortTrap ; set traps on keyboard ports
343;(0.03) mov ax, KbdCmdPort ; in case client
344;(0.03) call PortTrap ; tries to disable A20
345;(0.03) pop es
346;(0.03) mov es:[A20watch], YesLLdone ; set A20 watch flag
347
348 HwTabLock ; Hardware lock the high ram
349
350 OP32
351 xor di,di ; clear EDI
352 mov di,ES:[ELOff] ; ES:EDI pts to loadall buffer
353 dw LODAL386 ; execute 386 LOADALL
354
355 ASSUME DS:DGROUP
356;
357EM286ll endp
358
359_TEXT ends
360 end
diff --git a/v4.0/src/MEMM/MEMM/EM386LL.ASM b/v4.0/src/MEMM/MEMM/EM386LL.ASM
new file mode 100644
index 0000000..3408eaa
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EM386LL.ASM
@@ -0,0 +1,397 @@
1
2
3page 58,132
4;******************************************************************************
5 title EM386LL - 386 routine to emulate 386 LOADALL
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: EM386LL - 386 routine to emulate 386 LOADALL
13;
14; Version: 0.04
15;
16; Date: April 11,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 04/16/86 Original
27; 05/12/86 A Cleanup and segment reorganization
28; 06/28/86 0.02 Name change from MEMM386 to MEMM
29; 06/29/86 0.02 Fixed error handler call. Error handler called
30; only on attempt to set VM bit in EFLAGS
31; 06/30/86 0.02 Jmp to error routine (instead of calling)
32; 07/03/86 0.03 Removed logic to enable A20 line watch
33; 07/05/86 0.04 JumpReal in R_CODE
34; 07/06/86 0.04 Changed assume to DGROUP
35; 07/08/86 0.04 added DB67 NOPs to avoid B1 errata
36;
37;******************************************************************************
38;
39; Functional Description:
40;
41; 386 LOADALL is emulated by building a buffer for a
42; 386 LOADALL from the client's 386 LOADALL buffer and executing the 386
43; LOADALL.
44;
45; check DR6/DR7 for addresses > 1meg ?
46;
47;******************************************************************************
48.lfcond ; list false conditionals
49.386p
50 page
51;******************************************************************************
52; P U B L I C D E C L A R A T I O N S
53;******************************************************************************
54;
55 public EM386ll
56;
57 page
58;******************************************************************************
59; L O C A L C O N S T A N T S
60;******************************************************************************
61;
62 include loadall.inc
63 include VDMseg.inc
64 include desc.inc
65 include VDMsel.inc
66 include instr386.inc
67 include vm386.inc
68 include oemdep.inc
69
70FALSE equ 0
71TRUE equ not FALSE
72
73;
74; Desc3Copy
75; Macro for copying a 386 Loadall descriptor cache entry to a
76; 386 Loadall descriptor cache entry.
77; ENTRY: DS:ESI pts to client's 386 Loadall descriptor entry
78; ES:DI pts to our 386 Loadall descriptor entry
79;
80; EXIT: DS:ESI pts to byte after client's 386 ll descr entry (next entry).
81; ES:DI pts to byte after 386 Loadall descriptor entry (next entry).
82; *** The access rights byte in set to DPL 3 for virtual mode ***
83;
84; USED: EAX
85;
86Desc3Copy MACRO
87 OP32
88 EA32 ; EAX = dword from DS:[ESI]
89 lodsw ; get access rights
90
91 or ah,D_DPL3 ;* set DPL 3 for virtual mode access
92
93 OP32
94 stosw ; store access rights
95
96 OP32
97 EA32 ; EAX = dword from DS:[ESI]
98 lodsw ; 32 bits of Base Addr from 386 entry
99
100 call MapLinear ; map this linear addr by page tables
101
102 OP32
103 stosw ; store Base Addr for 386 entry
104
105 OP32
106 EA32 ; EAX = dword from DS:[ESI]
107 lodsw ; get 32 bits of limit
108
109 OP32
110 stosw ; store 32 bit LIMIT into 386 entry
111 ENDM
112
113;
114; CurCopy
115; Macro for copying a current descriptor cache entry to a
116; 386 Loadall descriptor cache entry.
117; ENTRY: DS:BX pts to current descriptor
118; ES:DI pts to 386 Loadall descriptor entry
119;
120; EXIT: DS:BX unchanged.
121; ES:DI pts to byte after 386 Loadall descriptor entry (next entry).
122; *** The access rights byte in set to DPL 3 for virtual mode ***
123;
124; USED: EAX
125;
126CurCopy MACRO
127 OP32
128 mov ax,[bx+4] ; get AR info
129 or ah,D_DPL3 ;* set DPL 3 for virtual mode access
130 OP32
131 stosw ; store into cache entry
132 mov ah,[bx+7] ; AX = Base[31..16]
133 OP32
134 shl ax,16 ; high word of EAX = Base[31..16]
135 mov ax,[bx+2] ; EAX = Base[31..0]
136 OP32
137 stosw
138 mov al,[bx+6] ; LIMIT[19..16] in low bits of AL
139 and ax,0Fh
140 OP32
141 shl ax,16 ; high word of EAX = LIMIT[31..16]
142 ; NOTE: VDM does not use page
143 ; granularity for limit field !!
144 mov ax,[bx] ; EAX = LIMIT[31..0]
145 OP32
146 stosw ; store into cache for 386 buffer
147 ENDM
148
149;******************************************************************************
150; L O C A L D A T A A R E A
151;******************************************************************************
152
153_DATA segment
154extrn ELOff:word ; offset of 386 loadall buffer
155_DATA ends
156
157
158R_CODE segment
159extrn JumpReal:far ; continue client in real mode (rrtrap.asm)
160R_CODE ends
161
162_TEXT segment
163extrn MapLinear:near ; maps linear addresses (maplin.asm)
164extrn PortTrap:near ; IOBM trap set function (vminit.asm)
165extrn ErrHndlr:near ; error handler (errhndlr.asm)
166_TEXT ends
167
168
169 page
170;******************************************************************************
171; S E G M E N T D E F I N I T I O N
172;******************************************************************************
173;
174_TEXT segment
175 ASSUME CS:_TEXT,DS:DGROUP,ES:DGROUP
176
177;******************************************************************************
178; EM386ll - emulate 386 Loadall
179; The basic approach here is to filter the client's loadall buffer into
180; a temporary buffer, setting our values for the parameters we don't want
181; him to change and then executing the 386 loadall from our buffer.
182;
183; ENTRY: Protected Mode
184; BP points to bottom of client's GPfault stack frame
185; ES(in GP frame):EDI points to the client's loadall buffer info
186; on stack: ESI,EBX,EBP
187;
188; EXIT: via Loadall to virtual mode
189; The 386 Loadall buffer is emulated with the following
190; exceptions:
191; The VM bit is set in EFLAGS.
192; The TR, IDT descriptor cache, & TSS descriptor cache are
193; pointed to the VDM entries.
194;
195; USED: Not applicable... loadall reloads all registers
196;
197;******************************************************************************
198EM386ll proc near
199;
200 PUSH_EAX
201 PUSH_ECX
202 PUSH_EDI
203
204; Build a descriptor to client's 386 loadall buffer
205
206 mov bx,GDTD_GSEL ; get GDT data alias
207 mov ds,bx ; DS -> GDT
208 mov bx, [bp.VTFOE+VMTF_ES] ; Get VM ES from GP stack frame
209 mov ax,bx
210 shl bx,4 ; BX = low 16 bits of base
211 mov ds:[VM1_GSEL+2],bx ; place in descriptor
212 shr ax, 4 ; AH = high 8 bits of base
213 mov ds:[VM1_GSEL+4],ah ; place in descriptor
214
215; Point DS:ESI to start of client's 386 loadall buffer
216 mov bx,VM1_GSEL
217 mov ds,bx
218 OP32
219 mov si,di
220 ASSUME ds:nothing
221
222; Point ES:EDI to start of our 386 loadall buffer
223
224 mov ax,VDMD_GSEL
225 mov es,ax
226 OP32
227 xor di,di ; clear EDI
228 mov di,ES:[ELOff] ; ES:EDI pts to our 386 loadall buffer
229;
230 cld
231
232; Walk through the two buffers in parallel, copying the client's values
233; when appropriate
234
235;
236; CR0 entry
237;
238 EA32
239 OP32
240 lodsw ; get client's CR0
241
242;(0.02) OP32
243;(0.02) test ax,0001h ; TEST EAX,80000001h
244;(0.02) dw 8000h ; Q: PG or PE bit set ?
245;(0.02) jz CR0_OK ; N: continue
246;(0.02) call Em386_Err ; Y: error
247;
248CR0_OK:
249 MOV_ECX_CR0
250 OP32
251 and cx,0011h ; and ECX,80000011h
252 dw 8000h ; save only PG,ET, & PE bits
253 OP32
254 or ax,cx ; or EAX,ECX
255 OP32
256 stosw ; store CR0 for 386 buffer
257 XOR_ECX_ECX ; clear ECX
258;
259; EFLAGS
260;
261 EA32
262 OP32
263 lodsw ; get EFLAGS
264;
265 OP32
266 test ax,0000h
267 dw 0002h ;Q: client's VM bit set ?
268 jz EF_OK ; N: continue
269 jmp Em386_Err ; Y: error handler - won't return here
270EF_OK:
271 and ax,0FFFh ; clear IOPL & NT bits
272 OP32
273 or ax,3000h
274 dw 0002h ; set VM bit and IOPL = 3
275 OP32
276 stosw ; store EFLAGS for 386 buffer
277;
278; Copy the client's EIP, EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX, DR6 & DR7
279; register images from his 386 loadall buffer to our 386 loadall buffer
280;
281 mov cx,11 ; copy 11 register contents
282 OP32 ; dwords from DS:[ESI] to ES:[EDI]
283 EA32
284 rep movsw ; copy 11 dwords
285
286 EA32
287 nop ; this avoids a B1 errata
288;
289; store TR and LDTR
290;
291 XOR_EAX_EAX ; clear EAX
292 mov ax,TSS_GSEL ; get current TR for VDM's TSS !!!
293 OP32
294 stosw ; store TR for 386 buffer
295;
296 sldt ax ; use current LDT
297 OP32
298 stosw ; store LDTR for 386 buffer
299;
300; Copy the client's GS, FS, DS, SS, CS, ES register images from
301; his 386 loadall buffer to our 386 loadall buffer
302;
303 add si,offset ll3_GS - offset ll3_TSSR
304 mov cx,6
305 OP32 ; dwords from DS:[ESI] to ES:[EDI]
306 EA32
307 rep movsw ; copy 6 dwords
308
309 EA32
310 nop ; this avoids a B1 errata
311;
312; Copy the current TSS, GDT, IDT, LDT descriptors from the GDT table to
313; our 386 loadall buffer
314;
315 push ds ; save client's buffer selector
316 mov ax,GDTD_GSEL
317 mov ds,ax
318
319 mov cx, 4
320 mov bx, TSS_GSEL
321 push word ptr LDTD_GSEL
322 push word ptr GDTD_GSEL
323 push word ptr IDTD_GSEL
324
325CopyCur: ; Copy current descriptors
326 CurCopy ; DS:[BX] points to current descriptor
327 pop bx
328 loop CopyCur
329 mov ds, bx ; restore client's buffer selector
330
331 ; DS:SI pts to 386 GS cache entry
332;
333; Copy the client's GS, FS, DS, SS, CS, ES register cache images from
334; his 386 loadall buffer to our 386 loadall buffer
335;
336 add si,offset ll3_GScache - offset ll3_TSScache
337 mov cx,6
338CopyCac: ; ES:DI pts to our 386 buf cache entry
339 Desc3Copy ; store his cache in our 386 buffer
340 loop CopyCac ; DS:SI pts to client's buf cache entry
341
342;
343; 386 Loadall buffer complete
344;
345
346;(0.03) push es
347;(0.03) mov ax, TSSD_GSEL ; Point ES to TSS for PortTrap
348;(0.03) mov es, ax
349;(0.03) mov bh, 80h ; set every 1k
350;(0.03) mov ax, KbdDataPort
351;(0.03) call PortTrap ; set traps on keyboard ports
352;(0.03) mov ax, KbdCmdPort ; in case client
353;(0.03) call PortTrap ; tries to disable A20
354;(0.03) pop es
355;(0.03) mov es:[A20watch], YesLLdone ; set A20 watch flag
356
357 HwTabLock ; Hardware lock the high ram
358
359 OP32
360 xor di,di ; XOR EDI,EDI - clear EDI
361 mov di,ES:[ELOff] ; ES:EDI pts to loadall buffer
362 dw LODAL386 ; execute 386 LOADALL
363
364 ASSUME DS:DGROUP
365;
366;
367EM386ll endp
368
369 page
370;******************************************************************************
371; Em386_Err - handle 386 ll emulation error
372; This routine is currently called only on attempts to set the
373; VM bit via loadall.
374;******************************************************************************
375Em386_Err proc near
376 push ax
377 push bx
378 mov ax, PrivErr
379 mov bx, Err3LL
380 call ErrHndlr
381 pop bx
382 pop bx
383;
384; continue client in real mode
385;
386 POP_EDI ; restore used regs
387 POP_ECX
388 POP_EAX
389 ; stack back to VmFault exit condition
390
391 jmp JumpReal ; "jump" to real mode and continue interrupted
392 ; code.
393
394Em386_Err endp
395;
396_TEXT ends
397 end
diff --git a/v4.0/src/MEMM/MEMM/EMM.ASM b/v4.0/src/MEMM/MEMM/EMM.ASM
new file mode 100644
index 0000000..557afa4
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EMM.ASM
@@ -0,0 +1,522 @@
1
2
3 page 58,132
4;******************************************************************************
5 title EMM - Expanded Memory Manager interface for MEMM
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: EMM - Expanded Memory Manager interface
13;
14; Version: 0.05
15;
16; Date: June 14, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 06/14/86 original
27; 06/28/86 0.02 Name change from MEMM386 to MEMM
28; 06/29/86 0.02 Protect port 84/85 from ints
29; 07/05/86 0.04 moved EMM_rEntry to R_CODE
30; 07/06/86 0.04 Changed assume to DGROUP
31; 07/08/86 0.04 Changed EMM_pEntry to call EMM functions
32; directly
33; 07/10/86 0.05 jmp $+2 before "POPF"
34; 07/10/86 0.05 added EMM_Flag
35; 06/09/88 remove _map_known since there is no map now (pc)
36; 07/20/88 remove debugger code (pc)
37;
38;******************************************************************************
39; Functional Description:
40; The module contains code for calling the EMM functions and a routine
41; for managing the AUTO mode of MEMM.
42; There are two EMM entry points in this module; one for real/virtual
43; mode entry and one for protected mode (IDT entry points here). When
44; MEMM is ON (system in Virtual mode), INT 67H calls transition to protected
45; mode and the EMM_pEntry entry point. EMM_pEntry sets up the same stack
46; conditions as the generic int67_Entry dispatcher and calls the appropriate
47; EMM function. Some EMM functions cannot be executed in protected mode.
48; These functions are called by reflecting the INT 67H to the real/virtual
49; mode entry point. EMM functions which are executed in PROTECTED mode
50; will take less time (they don't suffer the extra time to reflect the
51; INT 67H).
52;
53;******************************************************************************
54.lfcond
55.386p
56 page
57;******************************************************************************
58; P U B L I C D E C L A R A T I O N S
59;******************************************************************************
60;
61 public EMM_pEntry ; protected mode entry point
62 public EMM_rEntry ; real mode entry point
63 public EMM_rEfix ; label for far jump to int67_entry
64 public _AutoUpdate ; update auto mode of VDM/EMM
65 public EMM_Flag ; flag for EMM calls
66
67 page
68;******************************************************************************
69; L O C A L C O N S T A N T S
70;******************************************************************************
71;
72 include vdmseg.inc
73 include vdmsel.inc
74 include vm386.inc
75; include instr386.inc
76 include oemdep.inc
77 include emmdef.inc
78
79FALSE equ 0
80TRUE equ not FALSE
81
82;
83; these EMM functions are handled in protected mode
84;
85EMM_MAP_PAGE equ 44h ; map handle page
86EMM_RESTORE equ 48h ; restore page map
87EMM_GET_SET equ 4Eh ; get/set page map
88EMM_GET_SET_PARTIAL equ 4Fh ; get/set partial page map
89EMM_MAP_PAGE_ARRAY equ 50h ; map handle page array
90EMM_ALTER_MAP_JUMP equ 55h ; alter mapping and jump
91EMM_ALTER_MAP_CALL equ 56h ; alter mapping and call
92EMM_MOVE_XCHG_MEM equ 57h ; move/xchg memory region
93EMM_ALTER_MAP_REG_SET equ 5Bh ; alternate map register set
94
95EMM_HW_MALFUNCTION equ 81h ;
96
97;******************************************************************************
98; E X T E R N A L R E F E R E N C E S
99;******************************************************************************
100;
101ABS0 segment use16 at 0000h
102
103 org 67h * 4 ; EMM function interrupt
104EMMVec dw ? ; offset of vector
105 dw ? ; segment of vector
106
107ABS0 ends
108
109_DATA segment
110
111extrn _EMMstatus:word
112extrn Active_Status:byte ; current VDM status
113extrn Auto_Mode:byte ; current Auto mode status
114;extrn _map_known:byte ; non-zero => I/O map known to a user
115extrn _handle_count:word ; number of active EMM handles
116extrn _regp:word ; pointer to args on stack
117
118_DATA ends
119
120_TEXT segment
121
122extrn int67_Entry:far ; it's far because we need CS on stack too
123extrn GoVirtual:near
124extrn ErrHndlr:near
125extrn hw_int:near
126extrn RRProc:near
127
128extrn _GetStatus:near
129extrn _GetPageFrameAddress:near
130extrn _GetUnallocatedPageCount:near
131extrn _AllocatePages:near
132extrn _MapHandlePage:near
133extrn _DeallocatePages:near
134extrn _GetEMMVersion:near
135extrn _SavePageMap:near
136extrn _RestorePageMap:near
137extrn _GetPageMappingRegisterIOArray:near
138extrn _GetLogicalToPhysicalPageTrans:near
139extrn _GetEMMHandleCount:near
140extrn _GetEMMHandlePages:near
141extrn _GetAllEMMHandlePages:near
142extrn _GetSetPageMap:near
143
144extrn _GetSetPartial:near
145extrn _MapHandleArray:near
146extrn _AlterMapAndJump:near
147extrn _AlterMapAndCall:near
148extrn _MoveExchangeMemory:near
149extrn _AlternateMapRegisterSet:near
150
151_TEXT ends
152
153 page
154;******************************************************************************
155; S E G M E N T D E F I N I T I O N
156;******************************************************************************
157;
158_DATA segment
159EMM_Flag db 0 ; non-zero => EMM function called by our code
160_DATA ends
161
162 page
163;******************************************************************************
164;
165; _TEXT Code Segment
166;
167;******************************************************************************
168;
169_TEXT segment
170 assume cs:_TEXT, ds:DGROUP, es:DGROUP
171;******************************************************************************
172; protected mode dispatch table
173; allocate(43h)/deallocate(45h) pages and get I/O map (49h)
174; MUST be reflected to Virtual mode
175; MapHandlePage,RestorePageMap,GetSetPageMap,GetSetPartial,
176; MapHandleArray,MoveExchangeMemory,AlterMapAndJump,
177; AlterMapAndCall and AlternateMapRegisterSet are protected mode ONLY.
178;******************************************************************************
179EpE_Dispatch label word
180 dw offset _TEXT:EpE_Null
181 dw offset _TEXT:EpE_Null
182 dw offset _TEXT:EpE_Null
183 dw offset _TEXT:EpE_Null
184 dw offset _TEXT:_MapHandlePage ;44h
185 dw offset _TEXT:EpE_Null
186 dw offset _TEXT:EpE_Null
187 dw offset _TEXT:EpE_Null
188 dw offset _TEXT:_RestorePageMap ;48h
189 dw offset _TEXT:EpE_Null
190 dw offset _TEXT:EpE_Null
191 dw offset _TEXT:EpE_Null
192 dw offset _TEXT:EpE_Null
193 dw offset _TEXT:EpE_Null
194 dw offset _TEXT:_GetSetPageMap ;4eh
195 dw offset _TEXT:_GetSetPartial ;4fh
196 dw offset _TEXT:_MapHandleArray ;50h
197 dw offset _TEXT:EpE_Null
198 dw offset _TEXT:EpE_Null
199 dw offset _TEXT:EpE_Null
200 dw offset _TEXT:EpE_Null
201 dw offset _TEXT:_AlterMapAndJump ;55h
202 dw offset _TEXT:_AlterMapAndCall ;56h
203 dw offset _TEXT:_MoveExchangeMemory ;57h
204 dw offset _TEXT:EpE_Null
205 dw offset _TEXT:EpE_Null
206 dw offset _TEXT:EpE_Null
207 dw offset _TEXT:_AlternateMapRegisterSet ;5bh
208 dw offset _TEXT:EpE_Null
209 dw offset _TEXT:EpE_Null
210
211 page
212;******************************************************************************
213; EMM_pEntry - protected mode entry point for EMM function calls
214;
215; ENTRY: Protected mode
216; DGROUP:[EMM_Flag] = zero => reflect this int
217; SS:[SP] pointing to virtual mode INT stack frame
218;
219; EXIT: Protected mode
220; if this EMM function is to be handled in protected mode,
221; registers as set by EMM functions
222; else
223; reflect int 67 to virtual mode EMM code
224;
225; NOTE: *****
226; Allocate(43h)/deallocate(44h) pages and get I/O map (49h)
227; MUST be reflected to Virtual mode.
228;
229; USED: none
230;
231;******************************************************************************
232;
233; reflect EMM function to real mode
234;
235EpE_reflect:
236 push 67h ; refect
237 jmp hw_int ; it...
238;
239;
240; client not in Virtual mode
241;
242EpE_not_VM:
243 pop ebp ; N: call error handler
244
245 mov ax,ExcpErr ; exception error
246 mov bx,ErrINTProt ; invalid software interrupt
247 call ErrHndlr
248;
249; function entry
250;
251EMM_pEntry proc near
252;
253 push ebp
254 mov bp,sp
255 test [bp.VTFO+VMTF_EFLAGShi],2 ;Q:client in Virtual mode ?
256 jz EpE_not_VM ; N: handle it
257 ; Y: check flag
258 push VDMD_GSEL
259 pop ds ; DS = DGROUP
260 push VDMD_GSEL
261 pop es ; ES = DGROUP
262 cmp [EMM_Flag],0 ;Q: did we do this int67 ?
263 je EpE_Reflect ; N: reflect it
264 mov [EMM_Flag],0 ; Y: clear EMM_Flag for next
265 ; time and handle function
266 ; in protected mode.
267;
268; dispatch EMM function OR reflect to real/vm dispatcher
269;
270EpE_chk_func:
271 HwTabUnlock ; unlock ROM
272
273 push [bp.VTFO+VMTF_FS] ; client FS
274 push [bp.VTFO+VMTF_GS] ; client GS
275 push [bp.VTFO+VMTF_ES] ; client ES
276 push [bp.VTFO+VMTF_DS] ; client DS
277 push [bp.VTFO+VMTF_EFLAGS] ; client Flag
278 push [bp.VTFO+VMTF_CS] ; client CS
279 push word ptr [bp.VTFO+VMTF_EIP] ; client IP (low word of EIP)
280 ; stack has - IP,CS,PFlag,DS,ES,GS,FS
281 pushad ; all regs saved
282 mov bp,sp ; SS:BP -> to stack args (see r67_Frame struc)
283 mov [_regp],sp ; regp points to regs on stack
284 mov [_regp+2],ss ; regp now has a far ptr to regs
285
286 push ax
287 mov ax, PFLAG_VIRTUAL ; Faked VM bit
288 or [bp.PFlag], ax ; Incorpated in PFlag
289 pop ax
290 ;
291 ; validate function code
292 ;
293 sub ah,40h ; check if entry code too small
294 jb EpE_inv_exit ; if so, error exit
295 cmp ah,(5Dh-40h) ; check if entry code too big
296 ja EpE_inv_exit ; if so, error exit
297 ; else, AH = 0 base function #
298 ;
299 ; call through the jump table
300 ;
301EpE_jump:
302 xchg ah,al ; AL = function code
303 mov si,ax
304 xchg ah,al ; AH = function code again
305 and si,00FFh ; SI = function #
306 shl si,1 ; SI = table offset
307 call CS:EpE_Dispatch[si] ; call function
308
309 ;
310 ; check to see if we need to patch CS:IP on the iretd stack frame
311 ;
312EpE_Exit:
313 test word ptr [bp.PFlag], PFLAG_PATCH_CS_IP
314 jz EpE_No_Patch
315
316 mov bp, sp ; use bp to address stack
317 ;
318 ; patch iretd's CS:EIP to new CS:IP on stack
319 ;
320 mov ax, [bp.retaddr] ; get return IP
321 mov [bp.rFS+6], ax ; iretd's IP (6 bytes beyond FS)
322 xor ax, ax
323 mov [bp.rFS+8], ax ; zero high word of EIP
324 mov ax, [bp.rCS] ; get return CS
325 mov [bp.rFS+10], ax ; iretd's CS
326
327EpE_No_Patch:
328 popad ; restore regs
329 add sp, 6 ; throw away return addr cs and ip and flags
330 pop [bp.VTFO+VMTF_DS] ; client DS
331 pop [bp.VTFO+VMTF_ES] ; client ES
332 pop [bp.VTFO+VMTF_GS] ; client GS
333 pop [bp.VTFO+VMTF_FS] ; client FS
334
335
336 pop ebp ; restore bp
337
338 HwTabLock ; lock ROM
339
340 iretd ; return to virtual mode caller
341;
342; Null function - do nothing (should not get to here)
343EpE_Null:
344 ret ; return after doing nothing
345;
346; EMM error handling
347;
348EpE_inv_exit: ; set invalid function code error
349 mov byte ptr [bp.rAX+1],INVALID_FUNCTION
350 jmp EpE_Exit
351
352EMM_pEntry endp
353
354 page
355;******************************************************************************
356; EMM_rLink - real/virtual mode link for EMM function calls from
357; R_CODE segment.
358;
359; ENTRY: real/virtual mode
360; all registers as set by user
361;
362; EXIT: real/virtual mode
363; registers as set by EMM functions
364;
365; USED: none
366;
367;******************************************************************************
368EMM_rLINK proc far
369
370 ;
371 ; check for protected mode ONLY function
372 ;
373 cmp ah,EMM_MAP_PAGE ;Q: map handle page function ?
374 je ErE_GoProt ; Y: do it in protected mode
375 cmp ah,EMM_RESTORE ;Q: restore page map function ?
376 je ErE_GoProt ; Y: do it in protected mode
377 cmp ah,EMM_GET_SET ;Q: get/set page map function ?
378 je ErE_GoProt ; Y: do it in protected mode
379 cmp ah,EMM_GET_SET_PARTIAL ;Q: get/set partial function ?
380 je ErE_GoProt ; Y: do it in protected mode
381 cmp ah,EMM_MAP_PAGE_ARRAY ;Q: map handle page array ?
382 je ErE_GoProt ; Y: do it in protected mode
383 cmp ah,EMM_ALTER_MAP_JUMP ;Q: alter map and jump ?
384 je ErE_GoProt ; Y: do it in protected mode
385 cmp ah,EMM_ALTER_MAP_CALL ;Q: alter map and call ?
386 je ErE_GoProt ; Y: do it in protected mode
387 cmp ah,EMM_MOVE_XCHG_MEM ;Q: move/xchg memory region ?
388 je ErE_GoProt ; Y: do it in protected mode
389 cmp ah,EMM_ALTER_MAP_REG_SET;Q: alternate map register set ?
390 je ErE_GoProt ; Y: do it in protected mode
391 ; N: do it in real/virtual mode
392 ;
393 ; here for real/virtual mode functions
394 ;
395 push fs
396 push gs
397 push es
398 push ds
399 push 00 ; PFlag => real mode call to EMM functions
400 push seg DGROUP
401 pop ds ; set DS = DGROUP
402 call int67_Entry ; call dispatcher
403 add sp,2 ; drop PFlag arg
404 pop ds ; restore seg regs
405 pop es
406 pop gs
407 pop fs
408 ret ; and return
409
410 ;
411 ; Here if protected mode function called via real IDT
412 ; - set EMM flag and go for it...
413 ;
414ErE_GoProt:
415 push ds
416 push seg DGROUP
417 pop ds ; DS = DGROUP
418 cmp [Active_Status],0 ;Q: are we in Virtual Mode ?
419 jne ErE_Pcall ; Y: call protected mode function
420; mov [_map_known],TRUE ; N: set global auto mode flag
421 call _AutoUpdate ; go into virtual mode
422 ; and call function
423ErE_Pcall:
424 mov [EMM_Flag],TRUE ; set flag
425 pop ds ; restore DS
426 int 67h ; go for it ...
427 ret ; then return
428
429EMM_rLINK endp
430
431 page
432;******************************************************************************
433; _AutoUpdate - updates the EMM status when in AutoMode
434;
435; ENTRY: REAL or VIRTUAL mode ONLY
436; DS = DGROUP segment
437; DS:[Auto_Mode] = non-zero => system currently in auto mode
438; DS:[Active_Status] = non-zero => system currently ON
439; DS:[_map_known] = non-zero => I/O map has been given to a user
440;
441; EXIT: exits in real or virtual depending on the state variables
442; DS:[Active_Status] = current ON/OFF status
443;
444; USED: none
445;
446;******************************************************************************
447_AutoUpdate proc near
448;
449 cmp [Auto_Mode],0 ;Q: in Auto mode now ?
450 je AU_exit ; N: exit
451 cmp [Active_Status],0 ; Y:Q: ON now ?
452 je AU_chkoff ; N: check OFF state status
453;
454; here if we are currently ON
455;
456; cmp [_map_known],0 ; Y:Q: map known ?
457; jne AU_exit ; Y: then stay ON...
458 cmp [_handle_count],0 ; N:Q: any active handles ?
459 jne AU_exit ; Y: then stay ON...
460 mov [Active_Status],0 ; N: go to OFF state
461 push ax
462 call RRProc ; Force processor into real mode
463 pop ax
464 jmp AU_exit ; and leave in real mode
465;
466; here if we are currently OFF
467;
468AU_chkoff:
469 cmp [_handle_count],0 ;Q: any active handles ?
470 je AU_exit ; N: stay off
471
472; cmp [_map_known],0 ;; Q: is the map known ?
473; je AU_exit ;; N: then stay OFF...
474
475AU_ON: ; Y: turn ON EMM
476 mov [Active_Status],1 ; go to ON state,
477 call GoVirtual ; and go to virtual mode (ON)
478AU_exit:
479 ret
480;
481_AutoUpdate endp
482
483_TEXT ends
484
485 page
486;******************************************************************************
487;
488; R_CODE Code Segment
489;
490;******************************************************************************
491;
492R_CODE segment
493 assume cs:R_CODE, ds:DGROUP, es:DGROUP
494
495 page
496;******************************************************************************
497; EMM_rEntry - real/virtual mode entry point for EMM function calls
498;
499; ENTRY: real/virtual mode
500; all registers as set by user
501;
502; EXIT: real/virtual mode
503; registers as set by EMM functions
504;
505; USED: none
506;
507;******************************************************************************
508EMM_rEntry proc near
509;
510 cli ; just in case pushf/call far
511
512EMM_rEfix:
513 call EMM_rLink ; call _TEXT segment link
514 iret ; return to caller
515;
516EMM_rEntry endp
517
518
519R_CODE ends
520
521 end
522
diff --git a/v4.0/src/MEMM/MEMM/EMM386.INC b/v4.0/src/MEMM/MEMM/EMM386.INC
new file mode 100644
index 0000000..2b1143c
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EMM386.INC
@@ -0,0 +1,49 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: EMM386.INC - general includes for MEMM
10;
11; Version: 0.02
12;
13; Date: May 25,1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change Log:
20;
21; DATE REVISION Description
22; -------- -------- --------------------------------------------
23; 04/25/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25;
26;******************************************************************************
27ifndef INC_LIST
28.xlist
29endif
30
31;
32; Message Flag Equates
33;
34INC_PRC_MSG equ 00000001b ; Incorrect processor type message
35INC_DOS_MSG equ 00000010b ; Incorrect DOS message
36MEM_ERR_MSG equ 00000100b ; Memory error message
37INS_ERR_MSG equ 00001000b ; Already Installed message
38NO_PF_MSG equ 00010000b ; Nowhere to put PF message
39SIZE_ADJ_MSG equ 00100000b ; EMM Pool size adjusted message
40BASE_ADJ_MSG equ 01000000b ; Page Frame Base adjusted msg
41MAPA_ADJ_MSG equ 10000000b ; Map register address adjusted msg
42INV_PARM_MSG equ 100000000b ; Invalid parameter message
43PF_WARN_MSG equ 1000000000b ; PF located over ROM warning message
44;
45; These messages cause MEMM to not install
46;
47KILLER_MSG = INC_PRC_MSG+INC_DOS_MSG+MEM_ERR_MSG+INS_ERR_MSG+NO_PF_MSG
48;
49.list ; end of EMM386.INC
diff --git a/v4.0/src/MEMM/MEMM/EMM386.LNK b/v4.0/src/MEMM/MEMM/EMM386.LNK
new file mode 100644
index 0000000..f48b430
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EMM386.LNK
@@ -0,0 +1,41 @@
1memm386+
2elimfunc+
3emm+
4emmmes+
5emminit+
6memmonf+
7init+
8m_state+
9rom_srch+
10ppage+
11allocmem+
12inittab+
13shiphi+
14extpool+
15vdminit+
16i286+
17i386+
18tabdef+
19trapdef+
20vmtrap+
21vminst+
22elimtrap+
23iotrap+
24a20trap+
25oemproc+
26initepg+
27vminit+
28em286ll+
29em386ll+
30moveb+
31maplin+
32retreal+
33rrtrap+
34errhndlr+
35ekbd+
36util+
37initdeb+
38mapdma
39emm386.exe
40emm386.map/m
41..\emm\emmlib.lib
diff --git a/v4.0/src/MEMM/MEMM/EMM386D.LNK b/v4.0/src/MEMM/MEMM/EMM386D.LNK
new file mode 100644
index 0000000..fd07081
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EMM386D.LNK
@@ -0,0 +1,41 @@
1memm386+
2elimfunc+
3emmD+
4emmmes+
5emminit+
6memmonf+
7init+
8rom_srch+
9ppage+
10allocmem+
11inittab+
12vdminitD+
13i286+
14i386+
15tabdefD+
16trapdef+
17kbd+
18print+
19vmtrapD+
20vminstD+
21elimtrap+
22iotrap+
23a20trap+
24oemproc+
25initepg+
26vminit+
27em286ll+
28em386ll+
29moveb+
30maplin+
31retreal+
32rrtrap+
33errhndlr+
34ekbd+
35util+
36initdebD+
37mapdma
38emm386d.exe
39emm386d.map/m
40..\deb386\buglib.lib ..\emm\emmlib.lib
41
diff --git a/v4.0/src/MEMM/MEMM/EMMCOM.LNK b/v4.0/src/MEMM/MEMM/EMMCOM.LNK
new file mode 100644
index 0000000..a1b6a4d
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EMMCOM.LNK
@@ -0,0 +1,5 @@
1memmcom+
2memmonf
3emmcom.exe
4emmcom.map/m;
5
diff --git a/v4.0/src/MEMM/MEMM/EMMINIT.ASM b/v4.0/src/MEMM/MEMM/EMMINIT.ASM
new file mode 100644
index 0000000..65527b9
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EMMINIT.ASM
@@ -0,0 +1,678 @@
1
2
3 page 58,132
4;******************************************************************************
5 title EMMINIT - Expanded Memory Manager initialization
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: EMMINIT - Expanded Memory Manager initialization routine
13;
14; Version: 0.05
15;
16; Date: May 24 ,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 04/16/86 Original Adapted from DOS clock driver.
27; 05/24/86 0.00 From EMML test driver.
28; 06/21/86 0.02 added cld to EMM_Init
29; 06/28/86 0.02 Name change from MEMM386 to MEMM
30; 06/29/86 0.02 INC AX (was INC AL) for emm_free init
31; 07/06/86 0.04 Size _emm_page,_emm_free, & _pft386 based
32; on # of pages in system
33; 07/06/86 0.04 Changed assume to DGROUP
34; 07/10/86 0.05 moved int 67h patch to INIT
35; 06/07/88 added FRS_array initialization (Paul Chan)
36;
37;******************************************************************************
38; Functional Description:
39; This module initializes the data structures for the EMM
40; and sets the current emm data break address (_emm_brk).
41;
42;******************************************************************************
43.lfcond
44.386p
45 page
46;******************************************************************************
47; P U B L I C D E C L A R A T I O N S
48;******************************************************************************
49;
50 public EMM_Init
51 page
52;******************************************************************************
53; L O C A L C O N S T A N T S
54;******************************************************************************
55;
56 include vdmseg.inc
57 include emmdef.inc
58
59FALSE equ 0
60TRUE equ not FALSE
61
62EMM_HW_ERROR equ 81h ; EMM h/w error status
63
64;******************************************************************************
65; E X T E R N A L R E F E R E N C E S
66;******************************************************************************
67;
68_DATA segment
69
70extrn pool_size:word ; size of EMM Pages Pool in kbytes
71extrn xbase_addr_h:byte ; bit 16-24 of address of first byte of emm memory
72extrn xbase_addr_l:word ; bit 0-15 of address of first byte of emm memory
73extrn sys_size:word ; number of 16k pages taken away from conv. mem
74extrn PageT_Seg:word ; segment of system page table
75
76extrn _PF_Base:word ; segment addr of page frame base
77extrn _page_frame_pages:word ; number of pages in 3.2 page frame
78
79extrn _EMMstatus:word ; status of EMM
80
81extrn _page_frame_base:word ; pointers into page tables for each window
82extrn _mappable_pages:word ; mappable page array
83extrn _EMM_MPindex:byte ; index into mappable page array
84extrn _physical_page_count:word ; number of physical pages
85extrn _mappable_page_count:word ; number of mappable pages
86
87extrn _cntxt_pages:word ; pages in a context
88extrn _cntxt_bytes:word ; bytes in a context
89
90extrn _emm_page:word ; ptr to array of EMM pages
91extrn _free_count:word ; # of free EMM pages
92extrn _emmpt_start:word ; start of empty part of emm page
93extrn _emm_free:word ; ptr to array of free EMM pages
94extrn _free_top:word ; top of _emm_free
95
96extrn _total_pages:word ; total # of EMM pages available
97extrn _pft386:word ; ptr to array of page table entries
98
99extrn _emm_brk:word ; offset for emm data break address
100
101extrn FRS_array:word ;
102extrn CurRegSetn:byte
103extrn CurRegSet:word
104extrn FRS_free:byte
105
106extrn _handle_table:word
107extrn _handle_count:word
108
109_DATA ends
110
111ifndef NOHIMEM
112else
113VDATA segment
114extrn vdata_begin:byte
115VDATA ends
116endif
117
118LAST segment
119extrn mappable_segs:byte
120LAST ends
121
122_TEXT segment
123extrn InitELIM:far
124_TEXT ends
125
126LAST segment
127extrn InitEPage:near
128LAST ends
129
130
131 page
132;******************************************************************************
133; S E G M E N T D E F I N I T I O N
134;******************************************************************************
135;
136;******************************************************************************
137;
138; Code Segment
139;
140;******************************************************************************
141;******************************************************************************
142; MACROS used in the EMM initialisation code
143;******************************************************************************
144;******************************************************************************
145;
146; Get_FRS_window - get pointer to Fast Register Set window
147;
148; ENTRY: Reg - points to an FRS_struc
149;
150; EXIT: Reg - points to FRS_window entry in the structure
151;
152; USES: Reg
153;
154;******************************************************************************
155Get_FRS_window MACRO Reg
156
157 mov Reg, word ptr [CurRegSet] ; just offset (assume dgroup)
158 add Reg, FRS_window ; points to FRS window entries
159 ENDM
160
161;******************************************************************************
162;**init_PAGE_FRAME_BASE: macro to fill in the page_frame_base array. this
163; array contains the selector:offset into page table. The selector is already
164; initialised. So the offset of each of the physical pages into the page
165; table needs to be filled in.
166;
167; ENTRY: SI = INDEX INTO _page_frame_base, also physical page #
168; BX = Segment of physical page
169;
170;******************************************************************************
171init_page_frame_base MACRO
172;
173 push si
174 push bx
175;
176 shl si,2 ; convert index into offset in dword array
177;
178 shr bx,6 ; convert segment into page table offset
179 ; since there is 1 dword entry for each 4k
180 ;
181 mov _page_frame_base[si],bx ; fill this in
182;
183 pop bx
184 pop si
185;
186 ENDM
187
188;******************************************************************************
189;**init_MAPPABLE_PAGES: macro to fill the _mappable_pages array. this array
190; contains the segment and physical page number of all the mappable physical
191; pages.
192;
193; ENTRY: SI = INDEX INTO _page_frame_base, also physical page #
194; BX = Segment of physical page
195; DI = Index into _mappable_pages
196;
197;******************************************************************************
198init_mappable_pages MACRO
199;
200 push di
201;
202 shl di,2 ; convert index into offset in dword array
203;
204 mov _mappable_pages[di],bx ; fill in segment
205 mov _mappable_pages[di][2],si ; and physical page number
206;
207 pop di
208;
209 ENDM
210
211;******************************************************************************
212;**init_MAPPABLE_INDEX: macro to fill in EMM_MPIndex array. This array
213; contains a cross reference for the memory from 4000h to 10000h into the
214; mappable_pages array. There is an entry for each 16k page. The pages in
215; this range which are not mappable are initialised to -1. The ones which
216; are mappable are initialised to the index into the mappable_pages array
217; for the entry which represents this page
218;
219; ENTRY: DI = Index into _mappable_pages
220; BX = Segment of physical page
221;
222;******************************************************************************
223init_mappable_index MACRO
224;
225 push ax
226 push bx
227;
228 shr bx,10 ; convert segment to 16k page #
229 sub bx,CONV_STRT_PG ; first page in EMM_MPIndex array is 16
230;
231 mov ax,di ; to extract the lower byte
232 mov _EMM_MPIndex[bx],al ; fill in index
233;
234 pop bx
235 pop ax
236;
237 ENDM
238
239;******************************************************************************
240; INVALIDATE_MAPPABLE_PAGE_ENTRY: macro to remove the page from the mappable
241; page temporary list we are using. this is to facilitate the recognition
242; of pages above A000 which are not page frame pages. When we recognise page
243; frame pages we invalidate them so that the subsequent pass for pages doesn't
244; include these.
245;
246; ENTRY: BX = Segment of physical page
247;******************************************************************************
248inv_mpbl MACRO
249;
250 push bx
251;
252 shr bx,10 ; convert segment to 16k page #
253 mov cs:mappable_segs[bx],PAGE_NOT_MAPPABLE
254;
255 pop bx
256;
257
258 ENDM
259
260;
261LAST segment USE16
262 assume cs:LAST, ds:DGROUP, es:DGROUP
263
264;******************************************************************************
265; LOCAL VARIABLES
266;******************************************************************************
267first_sys_ppage dw 0ffffh ; physical page number of first system page
268
269 page
270;******************************************************************************
271;
272; CODE FOR INITIALISATION
273;
274;******************************************************************************
275
276
277 page
278;******************************************************************************
279; EMM_Init - initialization routine for EMM.
280; Patches int 67h vector.
281;
282; ENTRY: none
283;
284; EXIT: EMM vector initialized.
285; EMM data structures initialized
286; NC => no errors
287; C => errors
288;
289; USED: none
290;
291;******************************************************************************
292EMM_Init proc near
293;
294 pusha
295 push ds
296 push es
297;
298; set DS,ES to DGROUP segment
299;
300 mov ax,seg DGROUP
301 mov ds,ax
302 mov es,ax
303;
304 cld ; strings foward
305;
306; init EMM status
307;
308 mov [_EMMstatus],0
309
310;
311; set total # of EMM pages
312;
313 mov cx,[pool_size] ; CX = kbytes of expanded memory
314 shr cx,4 ; CX = # of EMM pages available
315 mov [_total_pages],cx ; pages total
316;
317; init ptrs for _emm_page, _emm_free and _pft386
318;
319 shl cx,1 ; CX = bytes in total_pages words
320
321ifndef NOHIMEM
322else
323 mov ax,seg VDATA
324 sub ax,seg DGROUP
325 shl ax,4 ; convert into offset from dgroup
326 add ax,offset VDATA:vdata_begin
327 mov [_emm_page],ax
328endif
329
330
331 mov ax,[_emm_page] ; AX = ptr to emm_page array
332 add ax,cx ; AX = ptr to word just past emm_page[]
333 mov [_emm_free],ax ; set ptr for emm_free[]
334 add ax,cx ; AX = ptr to word just past emm_free[]
335 mov [_pft386],ax ; set ptr for _pft386[]
336 shl cx,1 ; CX = bytes in total_pages dwords
337 add ax,cx ; AX = ptr to word just past _pft386[]
338 mov [_emm_brk],ax ; set break address for emm data
339 shr cx,2 ; CX = total_pages again
340;
341; init free pages array
342;
343 mov [_free_count],cx ; all pages free initially
344 mov [_free_top],0 ; top ptr pts to first free page
345 mov di,[_emm_free] ; ES:DI pts to _emm_free[0]
346 mov bx,[_free_top] ; BX = current top of free list
347 shl bx,1
348 add di,bx ; ES:DI pts to begin of free page area
349 xor ax,ax ; start with EMM page#0
350EMMP_loop: ; copy free pages into _emm_free
351 stosw ; store EMM page#
352 inc ax ;(0.02) increment page#
353 loop EMMP_loop ;Q: all entries in _emm_free[] ?
354 ; N: do next page.
355;
356; fix _page_frame_pages to be a maximum of 4 (for the LIM 3.2 frame)
357;
358 cmp [_page_frame_pages],4
359 jbe EMIN_1
360 mov [_page_frame_pages],4
361EMIN_1:
362;
363; See validity of page frame
364;
365 test [_PF_base],3ffh ; if any of these bits are set it is
366 ; invalid
367 jne EMIN_2 ;
368 cmp [_PF_base],0E400h ; in the ROM area
369 jae EMIN_2 ; also invalid
370 cmp [_PF_base],0C000h ; or in the video area
371 jnb EMIN_3 ;
372EMIN_2:
373;
374; Page Frame invalid, set it to FFFFh and _page_frame_pages to 0
375;
376 mov [_PF_base],0FFFFh
377 mov [_page_frame_pages],0
378;
379EMIN_3:
380;
381; setting up _page_frame_base
382; _mappable_pages
383; _EMM_MPIndex
384; _physical_page_count
385; _mappable_page_count
386;
387;
388;
389; ----------------- ----------------- -----------------
390; | for pages | | for pages | | |FC00h
391; | below | | below | |---------------|
392; | A000h | | A000h | | |
393; ----------------- ----------------- | |
394; | | | | | . |
395; | for pages | | for pages | | . |
396; | above | | above | | . |
397; | A000h | | A000h | <-- | |
398; | | | | | |---------------|
399; ----------------- ----------------- | | |4800h
400; | for page frame| | for page frame| | |---------------|
401; | pages even if | | pages only if | |------- |4400h
402; | they don't | | they exist | |---------------|
403; | exist | | | | |4000h
404; ----------------- ----------------- -----------------
405;
406; _page_frame_base _mappable_pages EMM_MPIndex
407;
408; Each entry reps Each entry reps Each entry reps
409; a physical page. a mappable ph. page a system page
410;
411; DWORD. DWORD Byte
412;
413; 1st WORD: offset 1st WORD: segment Index into
414; into page table of ph. page _mappable_pages
415; which reps the page
416; 2nd WORD: sel. 2nd WORD: physical
417; of page table page # of ph. page
418;
419;
420; 1. Set up for the page frame pages. Note that they may or may not exist.
421; Even if they do not exist entries must be set up for them in the
422; _page_frame_base.
423;
424 ;
425 ; initialise indexes.
426 ;
427 xor si,si ; index into _page_frame_pages
428 ; thus also physical page number
429 xor di,di ; index into _mappable_pages
430 ;
431 ; set up for page frame pages
432 ;
433 mov cx,[_page_frame_pages] ; get number
434 jcxz EMIN_5 ; if none exist then skip next portion
435 ;
436 mov bx,[_PF_base] ; get page frame base
437 ;
438 ; the setup loop:
439 ;
440EMIN_4:
441 init_page_frame_base
442 init_mappable_pages
443 init_mappable_index
444 inv_mpbl
445 ;
446 ; update counters for next entry
447 ;
448 inc si
449 inc di
450 add bx,0400h
451 ;
452 ; and loop back
453 ;
454 loop EMIN_4
455;
456EMIN_5:
457;
458; 2. If page frame pages were less than 4 then also we should set aside
459; four entries in the physical page array
460;
461 mov si,4
462;
463; 3. Setup for the mappable pages above A000h. Search the mappable_segs
464; array for mappable pages above A000h and for each mappable page make
465; an entry in the arrays
466;
467 ;
468 ; setup the segment and the count of pages we have to look for. also
469 ; the index into the mappable_segs array
470 ;
471 mov bx,0A000h ; segment
472 mov dx,bx ;
473 shr dx,10 ; page # corresponding to segment
474 ;
475 mov cx,64 ; max page #
476 sub cx,dx ;
477 ;
478 ; setup loop
479EMIN_6:
480 ;
481 ; see if page mappable
482 ;
483 xchg dx,bx
484 cmp cs:mappable_segs[bx],PAGE_MAPPABLE ;
485 xchg dx,bx
486 jnz EMIN_7
487 ;
488 ; page mappable. set up entries for it
489 ;
490 init_page_frame_base ; set up the page_frame_base entry
491 init_mappable_pages ; set up the mappable_pages entry
492 init_mappable_index ; set up the EMM_MPIndex
493 ;
494 ; update counters for next entry
495 ;
496 inc si ; these two are only updated
497 inc di ; if an entry is found
498EMIN_7:
499 inc dx ; and these two are updated in
500 add bx,0400h ; any case
501 ;
502 ; and loop back
503 ;
504 loop EMIN_6
505
506;
507; 4. Finally set up for the system pages
508;
509 ;
510 ; store the physical page # of the 1st system page.
511 ;
512 mov cs:[first_sys_ppage],si
513 ;
514 ; setup the segment and the count of pages we have to look for. also
515 ; the index into the mappable_segs array
516 ;
517 mov bx,04000h ; segment
518 mov dx,bx ;
519 shr dx,10 ; page # corresponding to segment
520 ;
521 mov cx,40 ; max page #
522 sub cx,dx ;
523 ; number of pages to be examined
524 ;
525 ; setup loop
526EMIN_8:
527 ;
528 ; see if page mappable.
529 ;
530 xchg dx,bx
531 cmp cs:mappable_segs[bx],PAGE_MAPPABLE ;
532 xchg dx,bx
533 jnz EMIN_9
534 ;
535 ; page mappable. set up entries for it
536 ;
537 init_page_frame_base ; set up the page_frame_base entry
538 init_mappable_pages ; set up the mappable_pages entry
539 init_mappable_index ; set up the EMM_MPIndex
540 ;
541 ; update counters for next entry
542 ;
543 inc si ; these two are only updated
544 inc di ; if an entry is found
545EMIN_9:
546 inc dx ; and these two are updated in
547 add bx,0400h ; any case
548 ;
549 ; and loop back
550 ;
551 loop EMIN_8
552;
553; 5. finally use the indexes to fill up the counts of the number of entries in
554; each array.
555;
556 mov [_physical_page_count],si
557 mov [_mappable_page_count],di
558;
559;
560; 6. and the pages in a context and the number of bytes needed to save a
561; context.
562;
563 inc si ; cntxt_pages = (physical_page_count
564 ; + 1) & NOT 1
565 and si, NOT 0001h ; to round up si to higher even #
566 mov [_cntxt_pages],si ; number of pages in a context
567;
568 shl si,1
569 add si,2 ; cntxt_bytes = cntxt_pages*2 + 2
570 mov [_cntxt_bytes],si ;
571;
572
573;
574; initialize FRS_array
575;
576 lea si,FRS_array ; DS:SI <-- FRS_array
577 mov [si.FRS_alloc], 1 ; mark FRS set 0 as allocated
578 mov [CurRegSetn], 0 ; use FRS set 0
579 mov [FRS_free], FRS_COUNT-1 ; one less FRS set
580 mov word ptr [CurRegSet], SI; save current FRS pointer
581
582;
583; NOW for some Handle 0 initialisation. We have to reclaim the pages we
584; released to the emm page pool from the conventional memory. This is
585; easy. These happen to be the first k pages in the emm page pool. We
586; need to fix the following data structures to reclaim these.
587;
588; k pages need to be transferred to emm_page array from emm_free array
589; and emmpt_start, _free_top, _free_count and _handle_table and _handle_count
590; updated
591 ;
592 ; find out the number of pages to be reclaimed
593 ;
594 mov cx,[sys_size] ; in kb
595 shr cx, 4 ; convert to number of 16k pages
596 ;
597 ; transfer these many pages from the emm_free array to the emm_pages array
598 ;
599 push cx
600 ;
601 mov si,_emm_free ;
602 add si,_free_top ;
603 add si,_free_top ; get offset to free page
604 ;
605 mov di,_emm_page ;
606 add di,_emmpt_start ;
607 add di,_emmpt_start ; get offset to next available loc in
608 ; emm_page
609 ;
610 cld
611 rep movsw ; transfer the pages over
612 ;
613 pop cx
614 ;
615 ; fix entry for handle 0 in handle table
616 ;
617 mov dx, [_emmpt_start]
618 mov _handle_table[0],dx ; offset into emm_page array
619 mov _handle_table[2],cx ; number of pages
620 ;
621 ; handle_count needs to be incremented to indicate that handle 0 is
622 ; allocated
623 ;
624 inc [_handle_count]
625 ;
626 ; fix ptr in emm page tracking arrays
627 ;
628 add [_emmpt_start],cx
629 add [_free_top],cx
630 sub [_free_count],cx
631;
632; Initialise FRS initialisation
633;
634; di = pointer into FRS. bx = physical page number. si = pointer into emm_page
635; cx = number of pages mapped.
636;
637 mov si,_handle_table[0] ; get pointer into emm_page
638 shl si,1 ; emm_page is a word array
639 add si,[_emm_page] ;
640 ;
641 GET_FRS_WINDOW di ; get pointer to FRS area
642
643 mov bx,cs:[first_sys_ppage]
644 shl bx,1
645 add di,bx ;
646 ;
647 cld
648 rep movsw
649 ;
650;
651; the way we have allocated the pages we don't need to update the Page table
652; the pages that have been mapped
653;
654; init ELIM h/w emulation (DMA PORTS)
655;
656 call InitELIM
657
658;
659; init EMM_PTE - ptrs to EMM pages
660;
661 call InitEPage
662;
663; leave - no errors
664;
665 pop es
666 pop ds
667 popa
668;
669 xor ax,ax
670 clc
671 ret
672;
673EMM_Init endp
674
675;
676LAST ends
677
678 end
diff --git a/v4.0/src/MEMM/MEMM/EMMMES.ASM b/v4.0/src/MEMM/MEMM/EMMMES.ASM
new file mode 100644
index 0000000..1036a66
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EMMMES.ASM
@@ -0,0 +1,210 @@
1
2
3 page 58,132
4;******************************************************************************
5 title EMMMES - messages for MEMM
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: EMMMES - messages for MEMM
13;
14; Version: 0.05
15;
16; Date: May 24,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 05/24/86 Original
27; 06/26/86 0.02 changed version #.
28; 06/28/86 0.02 Name changed from MEMM386 to MEMM
29; 07/06/86 0.04 changed version #.
30; 07/06/86 0.04 changed assume to DGROUP
31; 07/06/86 0.04 moved some messages to LAST
32; 07/08/86 0.04 Changed messages for incorrect machine
33; 07/09/86 0.05 changed version displayed version# to 3.20.
34;
35;******************************************************************************
36.lfcond
37.386p
38 page
39;******************************************************************************
40; P U B L I C D E C L A R A T I O N S
41;******************************************************************************
42;
43 public InitMess
44 public InstallMess
45 public ISizeMess
46 public ExtSizeMess
47 public SysSizeMess
48 public PFBAMess
49 public ActiveMess
50 public InactiveMess
51 public AutoMess
52 public POE_Mess
53 public POE_Num
54 public POE_Len
55 public EXCPE_Mess
56 public EXCPE_Num
57 public EXCPE_CS
58 public EXCPE_EIP
59 public EXCPE_ERR
60 public EXCPE_Len
61 public InvParm
62 public InvPFBA
63 public InvMRA
64 public Adj_Size
65 public InsfMem
66 public Incorrect_DOS
67 public Incorrect_PRT
68 public Already_Inst
69 public PFWarning
70 public No_PF_Avail
71 page
72;******************************************************************************
73; L O C A L C O N S T A N T S
74;******************************************************************************
75;
76 include ascii_sm.equ
77 include vdmseg.inc
78
79 page
80;******************************************************************************
81; S E G M E N T D E F I N I T I O N
82;******************************************************************************
83
84;******************************************************************************
85;
86; LAST Segment messages
87;
88;******************************************************************************
89;
90LAST segment
91
92InitMess db CR,LF
93 db "MICROSOFT Expanded Memory Manager 386 Version 4.00",CR,LF
94 db "(C) Copyright MICROSOFT Corporation 1988",CR,LF
95 db "$"
96
97InstallMess db "EMM386 Installed.", CR,LF
98 db " Extended memory allocated: "
99ExtSizeMess db " KB",CR,LF
100 db " System memory allocated: "
101SysSizeMess db " KB",CR,LF
102 db " "
103 db "--------",CR,LF
104 db " Expanded memory available: "
105ISizeMess db " KB",CR,LF
106 db " Page frame base address: "
107PFBAMess db "XX000 H",CR,LF
108 db "$"
109
110ActiveMess db "EMM386 Active.",CR,LF
111 db CR,LF
112 db "$"
113
114InactiveMess db "EMM386 Inactive.",CR,LF
115 db CR,LF
116 db "$"
117
118AutoMess db "EMM386 is in Auto mode.",CR,LF
119 db CR,LF
120 db "$"
121
122;
123; install error messages
124;
125
126InvParm db "Invalid parameter specified.",CR,LF
127 db "$"
128
129InvPFBA db "Page Frame Base Address adjusted.",CR,LF
130 db "$"
131
132InvMRA db "Mapping Register Address adjusted.",CR,LF
133 db "$"
134
135Adj_Size db "Size of expanded memory pool adjusted.",CR,LF
136 db "$"
137
138PFWarning db "WARNING - "
139 db "Option ROM or RAM detected within page frame."
140 db CR,LF
141 db CR,LF
142 db BEL
143 db "$"
144
145InsfMem db "EMM386 not installed - insufficient memory.",CR,LF
146 db BEL
147 db CR,LF
148 db "$"
149
150Incorrect_DOS db "EMM386 not installed - incorrect DOS version.",CR,LF
151 db BEL
152 db CR,LF
153 db "$"
154
155Incorrect_PRT db "EMM386 not installed - incorrect machine type.",CR,LF
156 db BEL
157 db CR,LF
158 db "$"
159
160No_PF_Avail db "EMM386 not installed - "
161 db "unable to set page frame base address.",CR,LF
162 db BEL
163 db CR,LF
164 db "$"
165
166Already_Inst db "EMM386 already installed.",CR,LF
167 db BEL
168 db CR,LF
169 db "$"
170
171LAST ends
172
173 page
174;******************************************************************************
175;
176; _DATA Segment messages
177;
178;******************************************************************************
179;
180_DATA segment
181
182;
183; run time error messages
184;
185POE_Mess db CR,LF
186 db BEL
187 db "EMM386 Privileged operation error #"
188POE_Num db "xx -",CR,LF
189 db "Deactivate EMM386 and Continue (C) or reBoot (B)"
190 db " (C or B) ? "
191POE_Len = $-POE_Mess
192 db "$"
193
194EXCPE_Mess db CR,LF
195 db BEL
196 db "EMM386 Exception error #"
197EXCPE_Num db "xx @"
198EXCPE_CS db "xxxx:"
199EXCPE_EIP db "xxxxxxxx Code "
200EXCPE_ERR db "xxxx"
201 db CR,LF,"Press enter to reboot"
202EXCPE_Len = $-EXCPE_Mess
203 db "$"
204
205;
206_DATA ends
207
208 end
209
210
diff --git a/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM b/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM
new file mode 100644
index 0000000..a675868
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM
@@ -0,0 +1,385 @@
1
2
3 page 58,132
4;******************************************************************************
5 TITLE ErrHndlr - Error Handler
6;******************************************************************************
7; (C) Copyright MICROSOFT Corp. 1986
8;
9; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
10;
11; Module: ErrHndlr - Recover from exception and priveledged operation errors
12;
13; Version: 0.04
14;
15; Date: June 6,1986
16;
17; Authors: Brad Tate
18;
19;******************************************************************************
20;
21; CHANGES:
22;
23; DATE REVISION DESCRIPTION
24; -------- -------- ------------------------------------------------------
25; 06/06/86 Original
26; 06/28/86 0.02 Name changed from MEMM386 to MEMM
27; 06/28/86 0.02 Removed STI at end of ErrHndlr
28; 06/28/86 0.02 Changed error # display to leading zeroes
29; 07/06/86 0.04 Changed assume to DGROUP
30;
31;******************************************************************************
32 page
33;******************************************************************************
34;
35; Functional description:
36;
37; This module contains the code that displays an error message and
38; asks the user to continue or reboot.
39;
40;******************************************************************************
41 page
42.386P
43;
44 include vdmseg.inc
45 include vdmsel.inc
46 include vm386.inc
47 include kbd.inc
48;******************************************************************************
49; Public Declarations
50;******************************************************************************
51;
52 public ErrHndlr ; Display message and continue or reboot
53 public Error_Flag
54;******************************************************************************
55; Externs
56;******************************************************************************
57_TEXT segment
58 extrn RetReal:near ; return to real mode
59 extrn egetc:near ; get keyboard character
60 extrn WaitKBD:near ; wait for keyboard ready
61_TEXT ends
62
63_DATA segment
64 extrn powr10:word ; power of 10's table
65 extrn POE_Mess:byte ; privileged operation error
66 extrn POE_Num:byte ; where to put error code
67 extrn POE_Len:abs ; length of message
68 extrn EXCPE_Mess:byte ; exception error message
69 extrn EXCPE_Num:byte ; where to put error code
70 extrn EXCPE_CS:byte ; where to put CS
71 extrn EXCPE_EIP:byte ; where to put EIP
72 extrn EXCPE_ERR:byte ; where to put ERR
73 extrn EXCPE_Len:abs ; length of message
74_DATA ends
75;
76romdata segment use16 at 40h
77 org 71h
78fBreak db ?
79fReset dw ?
80romdata ends
81;
82;******************************************************************************
83; Equates
84;******************************************************************************
85;
86MASTER = 0A1H ; Master interrupt i/o port
87SLAVE = 021H ; Slave interrupt i/o port
88NMI = 070H ; Non-Maskable interrupt i/o port
89DIS_MSTSLV = 00H ; Value to write to disable master/slave
90DIS_NMI = 080H ; Value to write to disable NMI
91ENA_NMI = 008H ; Value to write to enable NMI
92B = 48 ; make code for B
93C = 46 ; make code for C
94ENTER = 28 ; make code for enter key
95ATTR = 07 ; attribute for write string
96WRSTR = 1301h ; write string function code (format 1)
97CPOSN = 5*256+0 ; cursor position to write
98;
99;
100;******************************************************************************
101; LOCAL DATA
102;******************************************************************************
103_DATA segment
104Error_Flag dw 0 ; flags for Instruction Prefixes
105masterp db 0 ; save master port value
106slavep db 0 ; save slave port value
107mode db 0 ; save mode
108boot db 0 ; value to reboot
109continue db 0 ; value to continue
110
111GPsavERR dw 0 ; GP fault Error Code save
112GPsavEIP dd 0 ; GP fault EIP save
113GPsavCS dw 0 ; GP fault CS save
114
115_DATA ends
116;
117;******************************************************************************
118;
119; ErrHndlr - displays the appropriate error message and prompts the
120; user for a character to continue or reboot. The screen
121; is cleared by this routine. If the user chooses to
122; continue, the system is in real mode.
123;
124; entry: ax = 0 => Privileged operation error
125; ax = 1 => Exception error
126; bx = error number to display
127;
128; exit: either reboot, or exit in "real" mode with CLI
129;
130; used: none
131;
132; stack:
133;
134;******************************************************************************
135_TEXT segment
136 ASSUME CS:_TEXT, DS:DGROUP, ES:DGROUP
137ErrHndlr proc near
138;
139; save fault infos
140;
141 push eax
142 push ds
143 push VDMD_GSEL
144 pop ds
145 mov eax, dword ptr [bp.VTFO] ; error code
146 mov [GPsavERR], ax
147 mov eax, dword ptr [bp.VTFOE+VMTF_EIP] ; EIP
148 mov [GPsavEIP], eax
149 mov ax, word ptr [bp.VTFOE+VMTF_CS] ; CS
150 mov [GPsavCS], ax
151 pop ds
152 pop eax
153
154 call RetReal ; return to real mode
155;
156 push ax
157 push bx
158 push cx
159 push dx
160 push bp
161 push di
162;
163 push ax ; save input to this routine
164 in al,MASTER ; get value of master interrupt port
165 mov [masterp],al ; save it
166 in al,SLAVE ; get value of slave interrupt port
167 mov [slavep],al ; save it
168 mov al,DIS_MSTSLV ; value to disable master/slave int
169 out MASTER,al ; disable master
170 out SLAVE,al ; disable slave
171 mov al,DIS_NMI ; value to disable NMI
172 out NMI,al
173kbdbusy:
174 call egetc ; q: is there stuff in keyboard buffer?
175 jnz kbdbusy ; y: get it and pitch it
176 ; n: continue
177 pop ax ; get entry condition
178 or ax,ax ; q: privileged error?
179 jnz excep ; n: exception error
180 mov bp,offset DGROUP:POE_Mess ; y: privileged error
181 mov cx,POE_Len
182 mov di,offset DGROUP:POE_Num; error number location
183 mov ax,bx ; error number in ax
184 call b2asc10 ; convert to ascii
185 mov [boot],B ; key to boot
186 mov [continue],C ; key to continue
187 jmp skip_exc ; skip exception stuff
188excep:
189 mov bp,offset DGROUP:EXCPE_Mess ; n: load up exception error
190 mov cx,EXCPE_Len ; length of msg
191 mov di,offset DGROUP:EXCPE_Num ; error number location
192 mov ax,bx ; error number in ax
193 call b2asc10 ; convert to ascii
194 mov di,offset DGROUP:EXCPE_CS
195 mov ax,[GPsavCS]
196 call b2asc16
197 mov di,offset DGROUP:EXCPE_EIP
198 mov eax,[GPsavEIP]
199 ror eax,16
200 call b2asc16
201 ror eax,16
202 call b2asc16
203 mov di,offset DGROUP:EXCPE_ERR
204 mov ax,[GPsavERR]
205 call b2asc16
206 mov [boot],ENTER ; key to reboot
207 mov [continue],0ffh ; can't continue
208skip_exc:
209 mov ah,0fh ; read video state
210 int 10h
211 mov [mode],al ; save mode
212; mov ax,3 ; set to mode 3
213; int 10h ; standard 80 x 25 color
214 mov dx,CPOSN ; cursor position
215 mov bl,ATTR ; attribute
216 mov ax,WRSTR ; write string function code
217 int 10h ; do it
218 cli ; make sure int 10 didn't enable
219key_loop:
220 call egetc ; get a character
221 jz key_loop ; nothing there yet
222 cmp al,[continue] ; q: continue?
223 je err_cont ; y
224 cmp al,[boot] ; q: boot?
225 jne key_loop ; n: try again
226;******************************************************************************
227;
228; Reboot system
229;
230;******************************************************************************
231 assume ds:romdata
232 mov ax,romdata
233 mov ds,ax ; ds = romdata segment
234 mov [freset],0 ; cold restart
235 mov al,0fh or 80h ; shutdown byte address/disable NMI
236 out 70h,al ; write CMOS address
237 jmp short $+2 ; delay
238 mov al,0h ; shutdown code 0 = processor reset
239 out 71h,al ; write shutdown code to shutdown byte
240 call WaitKBD ; wait for 8042 to accept command
241 mov al,0feh ; feh = pulse output bit 0 (reset)
242 out KbStatus,al ; reset processor
243 hlt
244 assume ds:DGROUP
245;
246err_cont:
247 xor ah,ah ; ah = 0 to set video mode
248 mov al,[mode] ; restore their mode
249 int 10h
250 cli ; turn them off...
251;
252; restore master, slave, and NMI
253;
254 mov al,[masterp] ; get value of master interrupt port
255 out MASTER,al ; restore it
256 mov al,[slavep] ; get value of slave interrupt port
257 out SLAVE,al ; restore it
258 mov al,ENA_NMI ; value to enable NMI
259 out NMI,al
260;
261 pop di
262 pop bp
263 pop dx
264 pop cx
265 pop bx
266 pop ax
267 ret
268ErrHndlr endp
269
270page
271;******************************************************************************
272;
273; b2asc10 - converts binary to ascii decimal and store at _TEXT:DI
274; stores 2 ascii chars (decimal # is right justified and
275; filled on left with 0s)
276;
277; entry: ax = binary number
278; ds:DGROUP
279; ds:di = place to store ascii chars.
280;
281; exit: ASCII decimal representation of number stored at _TEXT:DI
282;
283; used: none
284;
285; stack:
286;
287;******************************************************************************
288;
289b2asc10 proc near
290;
291 push ax
292 push bx
293 push cx
294 push dx
295 push si
296 push di
297;
298 mov si,2 ; pointer to base 10 table
299 mov bl,1 ; leading zeroes on
300;
301; convert binary number to decimal ascii
302;
303b2_loop:
304 xor dx,dx ; clear word extension
305 mov cx,powr10[si]
306 div cx ; divide by power of 10
307 or bl,bl
308 jnz b2_ascii
309;
310 or ax,ax ; q: zero result?
311 jnz b2_ascii ; n: go convert to ascii
312;
313 mov al,' ' ; y: go blank fill
314 jmp b2_make_strg ;
315;
316b2_ascii:
317 add al,'0' ; put into ascii format
318 mov bl,1 ; leading zeroes on
319;
320b2_make_strg:
321 mov ds:[di],al ; put ascii number into string
322 xchg ax,dx
323 inc di ; increment buffer string pointer
324 dec si ; decrement power of 10 pointer
325 dec si ;
326 jge b2_loop ; Q: Last digit? N: Jump if not
327;
328 pop di
329 pop si
330 pop dx
331 pop cx
332 pop bx
333 pop ax
334 ret ; *** return ***
335;
336b2asc10 endp
337;
338;******************************************************************************
339;
340; b2asc16 - converts binary to hexidecimal and store at _TEXT:DI
341; stores 4 ascii chars (# is right justified and
342; filled on left with 0s)
343;
344; entry: ax = binary number
345; ds:DGROUP
346; ds:di = place to store ascii chars.
347;
348; exit: ASCII hexidecimal representation of number stored at _TEXT:DI
349;
350; used: none
351;
352; stack:
353;
354;******************************************************************************
355;
356b2asc16 proc near
357
358 push ax
359 push bx
360 push cx
361
362 mov cx,4
363b2asc16_loop:
364 mov bl,ah
365 shr bl,4
366 add bl,'0'
367 cmp bl,'9'
368 jbe b2asc16_skip
369 add bl,'A'-'9'-1
370b2asc16_skip:
371 mov ds:[di],bl
372 shl ax,4
373 inc di
374 loop b2asc16_loop
375
376 pop cx
377 pop bx
378 pop ax
379 ret
380
381b2asc16 endp
382
383_TEXT ENDS
384 END
385 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/EXTPOOL.ASM b/v4.0/src/MEMM/MEMM/EXTPOOL.ASM
new file mode 100644
index 0000000..de7b492
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EXTPOOL.ASM
@@ -0,0 +1,187 @@
1
2
3 page 58,132
4;******************************************************************************
5 TITLE EXTPOOL - MODULE to manage a pool of extended memory
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: EXTPOOL - Manage a pool of extended memory.
13;
14; Version: 0.01
15;
16; Date: Sep 1, 1988
17;
18; Author: ISP (ISP)
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26;******************************************************************************
27; Functional Description:
28;
29; "Fixit Orders" Crisis mode file. We need to ship data structures up hi.
30; So at init time we get a pool of extended memory and manage it for the
31; fixit routine. Services provided include initialise, allocate and
32; blkmov to the memory.
33;
34;******************************************************************************
35.lfcond
36.386p
37
38 page
39;******************************************************************************
40; P U B L I C D E C L A R A T I O N S
41;******************************************************************************
42 public pool_initialise
43 public get_buffer
44
45 page
46;******************************************************************************
47; L O C A L C O N S T A N T S
48;******************************************************************************
49;
50
51;******************************************************************************
52; INCLUDE FILES
53;******************************************************************************
54 include vdmseg.inc ; segment definitions
55
56 page
57;******************************************************************************
58; E X T E R N A L R E F E R E N C E S
59;******************************************************************************
60;
61;
62 page
63;******************************************************************************
64; S E G M E N T D E F I N I T I O N
65;******************************************************************************
66
67;*************************************************************************
68;
69; DATA
70;
71;*************************************************************************
72
73LAST SEGMENT
74
75ext_start dw 0000h ; start of the pool of extended memory
76 dw 0010h ; 24 bit address
77
78ext_size dw 0 ; size
79 dw 0 ;
80
81LAST ENDS
82
83;*************************************************************************
84;
85; CODE
86;
87;*************************************************************************
88LAST SEGMENT
89assume cs:LAST, DS:DGROUP, ES:DGROUP
90
91
92;******************************************************************************
93;*** Pool Initialise *** Give this memory manager the memory it is to play ;
94; with. ;
95; ;
96; INPUTS: AX = start offset of the extended memory in K ;
97; CX = size of the memory ;
98; ;
99; OUTPUTS: None ;
100; ;
101; USES: None ;
102; ;
103; AUTHOR: ISP (ISP) Sep 1, 1988 ;
104; ;
105;*****************************************************************************;
106
107Pool_Initialise proc near
108;
109 push dx
110 push cx
111 push ax
112;
113 push cx ; save size of memory
114 xor dx,dx
115 mov cx,1024
116 mul cx ; dx:ax size in bytes offset from 1M
117;
118 add ax,cs:[ext_start] ; add it to 1M
119 adc dx,cs:[ext_start+2] ;
120;
121 mov cs:[ext_start],ax ;
122 mov cs:[ext_start+2],dx ;
123;
124 pop ax ; get size into ax
125 xor dx,dx ;
126 mul cx
127;
128 mov cs:[ext_size],ax
129 mov cs:[ext_size+2],dx
130;
131 pop ax
132 pop cx
133 pop dx
134;
135 ret
136;
137Pool_Initialise endp
138
139
140
141;******************************************************************************
142;***Get buffer*** Give some poor beggar the memory he is asking for ;
143; ;
144; INPUTS: cx = size of buffer required in bytes ;
145; ;
146; OUTPUTS: DX:AX = address of buffer ;
147; cx = size allocated
148; ;
149; USES: None ;
150; ;
151; AUTHOR: ISP (ISP) Sep 1, 1988 ;
152; ;
153;*****************************************************************************;
154
155Get_Buffer proc near
156;
157 ;
158 ; assume that the memory is present, put start address in dx:ax
159 ;
160 mov dx,cs:[ext_start+2]
161 mov ax,cs:[ext_start]
162 ;
163 ; then proceed to determine if it really exists
164 ;
165 push eax
166 xor eax,eax
167 mov ax,cx
168 cmp eax, dword ptr cs:[ext_size]
169 ja no_mem
170 ;
171 ; it does exist, adjust the size and the start address
172 ;
173 sub dword ptr cs:[ext_size],eax
174 add dword ptr cs:[ext_start],eax
175;
176 pop eax
177 clc
178 ret
179
180no_mem:
181 pop eax
182 stc
183 ret
184Get_buffer endp
185
186LAST ENDS
187 end
diff --git a/v4.0/src/MEMM/MEMM/I286.ASM b/v4.0/src/MEMM/MEMM/I286.ASM
new file mode 100644
index 0000000..8eb2102
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/I286.ASM
@@ -0,0 +1,312 @@
1
2
3page 58,132
4;******************************************************************************
5 TITLE i286.asm - Support Routines for protected mode system
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: i286.asm - Support Routines for protected mode system
13;
14; Version: 0.02
15;
16; Date: January 31, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 01/31/86 Original
27; 02/05/86 A added is286, is386
28; 05/12/86 B Cleanup and segment reorganization
29; 06/03/86 C added push/pop es to Init_GDT and changed Ring 0
30; stack to STACK0 and STACK0_SIZE.
31; 06/28/86 0.02 Name changed from MEMM386 to MEMM
32;
33;******************************************************************************
34;
35; Functional Description:
36;
37; Anthony Short
38; 26th Dec 1985
39;
40; DESCRIPTION
41;
42; These routines manage the various 286 memory management
43; tables and manipulate descriptors and selectors.
44;
45; The routines which deal with descriptors use the following
46; register usage conventions:
47;
48; BX - selector of required descriptor. The selector may
49; have RPL bits present, the routines ignore them.
50;
51; CX - SIZE IN BYTES of segment. NOTE: descriptors contain
52; limits, not sizes (limit = size - 1). Since everyone
53; else talks sizes, these routines do too, and do their
54; own conversion.
55;
56; DX - second selector when needed
57;
58; AH - access rights byte
59;
60; AL, DX - 24 bit physical address
61;
62; ES:0 - pointer to the desired descriptor table.
63;
64; All the routines which manipulate descriptors are callable
65; in both real and protected mode.
66;
67; In general all registers are preserved.
68;
69; The following routines are provided:
70;
71; SetDescInfo - set descriptor information
72; SetSegDesc - set segment descriptor information
73;
74; SegTo24 - convert segment number to 24 bit addr
75; SegOffTo24 - convert seg:offset to 24 bit addr
76;
77; InitGdt - set up parts of GDT which cannot easily
78; be initialised statically.
79;
80; WARNING This code is 286 specific, it will NOT run on an 8088.
81;
82;******************************************************************************
83.lfcond ; list false conditionals
84.386p
85
86
87 include VDMseg.inc
88 include VDMsel.inc
89 include desc.inc
90
91;******************************************************************************
92; E X T E R N A L R E F E R E N C E S
93;******************************************************************************
94GDT segment
95 extrn GDTLEN:abs
96GDT ends
97
98IDT segment
99 extrn IDTLEN:abs
100IDT ends
101
102TSS segment
103 extrn TSSLEN:abs
104TSS ends
105
106LAST SEGMENT
107
108 assume cs:LAST
109
110;** SetDescInfo - set descriptor information
111;
112; The limit field of a specified descriptor is set.
113; (limit = size - 1).
114; The base address of the specified descriptor is set.
115; The access field of the specified descriptor is set.
116;
117; ENTRY BX = selector
118; ES:0 = descriptor table to use
119; CX = limit
120; AL, DX = 24 bit base address
121; AH = access rights byte
122; EXIT None
123; USES Flags, other regs preserved
124;
125; WARNING This code only works on a 286. It can be called in
126; either mode.
127
128 public SetDescInfo
129SetDescInfo proc near
130 push bx ; save selector
131 and bl,SEL_LOW_MASK
132
133; fill in the limit field
134
135 mov es:[bx],cx
136
137; fill in base address
138
139 mov es:[bx + 2],dx
140 mov es:[bx + 4],al
141
142; fill in access rights byte
143
144 mov es:[bx + 5],ah
145 pop bx
146 ret
147SetDescInfo endp
148
149
150;** SetSegDesc - set segment descriptor information
151;
152; The limit field of a specified descriptor is set.
153; (limit = size - 1).
154; The base address of the specified descriptor is set.
155; The access field of the specified descriptor is set.
156;
157; ENTRY BX = selector
158; ES:0 = descriptor table to use
159; CX = size
160; AL, DX = 24 bit base address
161; AH = access rights byte
162; EXIT None
163; USES Flags, other regs preserved
164;
165; WARNING This code only works on a 286. It can be called in
166; either mode.
167
168 public SetSegDesc
169SetSegDesc proc near
170 dec cx ; convert size to limit
171 call SetDescInfo ; set descriptor information
172 inc cx ; restore size
173 ret
174SetSegDesc endp
175
176
177;** SegTo24 - convert segment to 24 bit physical address
178;
179; The real mode segment number is convert to a 24 bit addr
180;
181; ENTRY AX = segment
182; EXIT AL, DX = 24 bit physical address
183; USES AH, Flags, other regs preserved
184;
185; WARNING This code only works on a 286, it can be called in
186; either mode.
187 public SegTo24
188SegTo24 proc near
189 mov dl,ah
190 shr dl,4 ; DH = high byte of 24 bit addr
191 xchg ax,dx ; AH = high byte, DX = segment
192 shl dx,4 ; DX = low word of 24 bit addr
193 ret
194SegTo24 endp
195
196
197;** SegOffTo24 - convert seg:off to 24 bit physical address
198;
199; The specified real mode segment:offset is converted to
200; a 24 bit physical address.
201;
202; ENTRY AX = segment
203; DX = offset
204; EXIT AL, DX = 24 bit physical address
205; USES AH, Flags, other regs preserved.
206;
207; WARNING This code only works on a 286. It can be called in
208; either mode.
209
210 public SegOffTo24
211SegOffTo24 proc near
212 push cx
213
214; Convert AX:DX into 24 bit addr in AL, DX
215
216 mov ch,ah
217 shl ax,4
218 shr ch,4 ; CH = high byte
219 add dx,ax ; DX = low word
220 mov al,ch ; AL = high byte
221 adc al,0 ; propagate cy from low word
222
223 pop cx
224 ret
225SegOffTo24 endp
226
227
228 page
229;******************************************************************************
230; IS286 - return type of processor (286 vs. 8088/86). 386 returns 286.
231; This routine relies on the documented behaviour of the PUSH SP
232; instruction as executed on the various processors. This routine
233; may be called from any mode on any processor, provided a proper
234; stack exists.
235;
236; ENTRY: (none)
237; EXIT: ZF = 1 if 8088/86
238; ZF = 0 if 286/386
239; USED: flags
240; STACK: 6 bytes
241;------------------------------------------------------------------------------
242 public Is286
243Is286 proc near
244 push bp
245 push sp
246 mov bp,sp
247 cmp bp,[bp] ; compare SP with saved SP
248 pop bp ; clean SP off stack
249 pop bp ; restore BP
250 ret ; *** RETURN ***
251Is286 endp
252 page
253;******************************************************************************
254; Is386 - return type of processor (386 vs. 8088/86/286).
255; This routine relies on Intel-approved code that takes advantage
256; of the documented behavior of the high nibble of the flag word
257; in the REAL MODE of the various processors. The MSB (bit 15)
258; is always a one on the 8086 and 8088 and a zero on the 286 and
259; 386. Bit 14 (NT flag) and bits 13/12 (IOPL bit field) are
260; always zero on the 286, but can be set on the 386.
261;
262; For future compatibility of this test, it is strongly recommended
263; that this specific instruction sequence be used. The exit codes
264; can of course be changed to fit a particular need.
265;
266; CALLABLE FROM REAL MODE ONLY - FAR ROUTINE
267;
268; ENTRY: (none)
269; EXIT: STC if 8088/86/286
270; CLC if 386
271; USED: none
272; STACK: 6 bytes
273;------------------------------------------------------------------------------
274 public Is386
275Is386 proc FAR
276 push ax
277 pushf ; save entry flags
278;
279 xor ax,ax ; 0000 into AX
280 push ax
281 popf ; try to put that in the flags
282 pushf
283 pop ax ; look at what really went into flags
284 test ax,08000h ;Q: was high bit set ?
285 jnz IsNot386_exit ; Y: 8086/8088
286 mov ax,07000h ; N: try to set the NT/IOPL bits
287 push ax
288 popf ; ... in the flags
289 pushf
290 pop ax ; look at actual flags
291 test ax,07000h ; Q: any high bits set ?
292 jz IsNot386_exit ; N: 80286
293 ; Y: 80386
294Is386_exit:
295 popf ; restore flags
296 clc ; 386
297 jmp short I386_exit ; and leave
298
299IsNot386_exit:
300 popf ; restore flags
301 stc ; not a 386
302
303I386_exit:
304 pop ax
305 ret ; *** RETURN ***
306
307Is386 endp
308
309LAST ends
310
311
312 end
diff --git a/v4.0/src/MEMM/MEMM/I386.ASM b/v4.0/src/MEMM/MEMM/I386.ASM
new file mode 100644
index 0000000..6065dbe
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/I386.ASM
@@ -0,0 +1,240 @@
1
2
3page 58,132
4;******************************************************************************
5 TITLE i386.asm - Support Routines for protected mode system
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: i386.asm - Support Routines for protected mode system
13;
14; Version: 0.04
15;
16; Date: January 31, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 01/31/86 Original
27; 05/12/86 A Cleanup and segment reorganization
28; 06/21/86 0.02 Added clds just in case
29; 06/28/86 0.02 Name changed from MEMM386 to MEMM
30; 07/06/86 0.04 changed assume to DGROUP
31;
32;******************************************************************************
33;
34; DESCRIPTION
35;
36; These routines manage the various 386 memory management
37; tables and manipulate descriptors and selectors.
38;
39; All the routines which manipulate descriptors are callable
40; in both real and protected mode.
41;
42; In general all registers are preserved.
43;
44; The following routines are provided:
45;
46; SetPageEntry - set up an entry in a Page Directory on Page
47; Table.
48;
49; GetPageEntry - retrieve a page dir/page table entry.
50;
51; InitPages - initialize page directory and page table.
52;
53; PageDirOff - convert 32 bit addr to page dir entry offset
54;
55; PageTableOff - convert 32 bit addr to page table entry offset
56;
57; WARNING This code is 386 specific, it will NOT run on an 8088.
58;
59;******************************************************************************
60.lfcond ; list false conditionals
61.386p
62;
63 include VDMseg.inc
64 include VDMsel.inc
65 include desc.inc
66 include page.inc
67
68;******************************************************************************
69; E X T E R N A L S
70;******************************************************************************
71LAST SEGMENT
72extrn SegTo24:near
73LAST ENDS
74
75
76;******************************************************************************
77; S E G M E N T D E F I N I T I O N S
78;******************************************************************************
79LAST SEGMENT
80
81 assume cs:LAST,ds:DGROUP,es:DGROUP
82
83;** SetGateDesc - set up Gate Descriptor entry
84;
85;
86; ENTRY DX,AX = 32 bit offset of target routine
87; CX = target code segment selector
88; ES:[DI] = points to table entry
89; BL = access bits
90; EXIT descriptor set.
91; USES Flags, other regs preserved
92;
93; WARNING This code only works on a 386. It can be called in
94; either mode.
95
96 public SetGateDesc
97SetGateDesc proc near
98;
99 push ax
100 push di
101;
102 cld ; stings foward
103;
104 stosw ; store low word of offset
105 mov ax,cx
106 stosw ; store selector
107 mov al,0
108 mov ah,bl
109 stosw ; store access rights
110 mov ax,dx
111 stosw ; store high word of offset
112;
113 pop di
114 pop ax
115 ret
116SetGateDesc endp
117
118
119;** SetPageEntry - set up entry in Page Directory or Page Table
120;
121;
122; ENTRY DX,AX = 32 bit address of page or page table
123; ES:[DI] = page directory or table entry to set
124; BX = access/status bits ( bits 0 - 11 )
125; EXIT ES:[DI] = next page directory or table entry
126; USES Flags, other regs preserved
127;
128; WARNING This code only works on a 386. It can be called in
129; either mode.
130
131 public SetPageEntry
132SetPageEntry proc near
133;
134 push ax
135;
136 cld ; strings foward
137;
138 and bx,0FFFh ; turn off any bits in address range
139 or ax,bx ; mov status bits into AX
140 stosw ; store status and addr bits 12 - 15
141 mov ax,dx ; AX = addr bits 16-31
142 stosw ; store addr bits 16-31
143;
144 pop ax
145 ret
146SetPageEntry endp
147
148
149;** GetPageEntry - up entry in Page Directory or Page Table
150;
151; ENTRY ES:[DI] = page directory or table entry
152; EXIT DX,AX = 32 bit address of page or page table
153; BX = access/status bits (bits 0 - 11).
154; USES Flags, other regs preserved
155;
156; WARNING This code only works on a 386. It can be called in
157; either mode.
158
159 public GetPageEntry
160GetPageEntry proc near
161;
162 mov ax,ES:[DI] ; AX = low word of entry
163 mov bx,ax ; get access/status rights bits
164 and bx,00FFFh ; turn off address bits
165;
166 and ax,0F000h ; turn off status bits
167 mov dx,ES:[DI+2] ; get high word of addr
168;
169 ret
170GetPageEntry endp
171
172
173;** PageDirOff - convert 32 bit linear address to page directory offset
174;
175;
176; ENTRY EAX = 32 bit linear address
177; EXIT DI = offset in page dir to appropriate entry
178; USES Flags, other regs preserved
179;
180; WARNING This code only works on a 386. It can be called in
181; either mode.
182
183 public PageDirOff
184PageDirOff proc near
185;
186 db 66h
187 push bx ; push EBX
188
189 db 66h
190 mov bx,ax ; EBX = EAX
191
192 db 66h
193 shr bx,22 ; EBX[0:9] = EBX[22:31] = high 10 bits
194 shl bx,2 ; *4 for dword indexing into table
195
196 mov di,bx ; DI = dir offset
197
198 db 66h
199 pop bx ; pop EBX
200;
201 ret
202PageDirOff endp
203
204
205;** PageTableOff - convert 32 bit linear address to page table offset
206;
207;
208; ENTRY EAX = 32 bit linear address
209; EXIT DI = offset in page table to appropriate entry
210; USES Flags, other regs preserved
211;
212; WARNING This code only works on a 386. It can be called in
213; either mode.
214
215 public PageTableOff
216PageTableOff proc near
217;
218 db 66h
219 push bx ; push EBX
220
221 db 66h
222 mov bx,ax ; mov EBX,EAX
223
224 db 66h
225 shr bx,12 ; EBX[0:9] = EBX[12:21] = middle 10 bits
226 and bx,3FFh ; only EBX[0:9]
227 shl bx,2 ; *4 for dword indexing into table
228
229 mov di,bx ; DI has table offset
230
231 db 66h
232 pop bx ; pop EBX
233;
234 ret
235PageTableOff endp
236
237
238LAST ends
239
240 end
diff --git a/v4.0/src/MEMM/MEMM/INIT.ASM b/v4.0/src/MEMM/MEMM/INIT.ASM
new file mode 100644
index 0000000..44ab1c7
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/INIT.ASM
@@ -0,0 +1,1123 @@
1
2
3 page 58,132
4;******************************************************************************
5 TITLE INIT - initialization code for MEMM
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: INIT - initialization code for MEMM
13;
14; Version: 0.05
15;
16; Date: May 24,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 05/24/86 Original
27; 06/18/86 0.01 Added AUTO as a valid config line parameter.
28; 06/25/86 0.02 Added call to debug init.
29; 06/27/86 0.02 Check for Mx length = 2 and only 2
30; 06/28/86 0.02 Change name from MEMM386 to MEMM
31; 06/29/86 0.02 Size > 8192 were used instead of converted
32; to 256
33; 07/03/86 0.04 Added TEXT_Seg
34; 07/06/86 0.04 changed assume to DGROUP
35; 07/06/86 0.04 moved init messages to LAST
36; 07/10/86 0.05 added int15 patch and int67 patch here
37; 07/20/88 removed debugger codes (pc)
38; 07/29/88 removed ON/OFF/AUTO support
39;
40;******************************************************************************
41; Functional Description:
42; This module allocates the pool of extended memory to be used for
43; expanded memory, then call routines to initialize the data structures
44; for EMM and VDM.
45;
46;******************************************************************************
47.lfcond
48.386p
49 page
50;******************************************************************************
51; P U B L I C D E C L A R A T I O N S
52;******************************************************************************
53;
54 public Init_MEMM386
55
56 public pool_size
57 public msg_flag
58 public Active_Status
59 public Auto_Mode
60 public dos_version
61 public TEXT_Seg
62 public STACK_Seg
63 public GDT_Seg
64 public IDT_Seg
65 public TSS_Seg
66 public driver_end
67 public powr10
68
69
70 page
71;******************************************************************************
72; L O C A L C O N S T A N T S
73;******************************************************************************
74;
75 include vdmseg.inc
76 include vdmsel.inc ; for Deb386 Init
77 include desc.inc ; " " "
78 include emm386.inc
79 include driver.equ
80 include driver.str
81 include ascii_sm.equ
82;
83; maximum value for SIZE parameter
84;
85MAX_SIZE equ 32 * 1024 ; 32K => 32Meg
86
87;
88MS_DOS equ 21h
89PRINT_STRING equ 09h
90GET_VERSION equ 30h
91;
92FALSE equ 0
93TRUE equ not FALSE
94DOS3X_ADJ equ 1 ; DOS 3.x base memory adjustment
95
96;
97; macro for printing messages located in LAST segment
98; ENTRY: DX = offset LAST:message
99;
100PRINT_MSG macro
101 push ds
102 push seg LAST
103 pop ds ; ds = LAST
104 mov ah,PRINT_STRING
105 int MS_DOS ; output init message
106 pop ds
107 ENDM
108
109
110;******************************************************************************
111; E X T E R N A L R E F E R E N C E S
112;******************************************************************************
113;
114;
115_DATA segment
116
117 extrn PF_Base:word
118; extrn himem_use:byte ;* this is defined in oemproc.asm since it
119 ; deals with memory so oem dependent
120 extrn ext_size:word ; size of extended memory allocated
121 extrn sys_size:word ; size of system memory allocated
122
123_DATA ends
124
125ABS0 segment use16 at 0
126 org 4*15h ; int 15h vector
127i15_vector dw 0
128 dw 0
129
130 org 4*67h ; int 67h vector
131i67_vector dw 0
132 dw 0
133ABS0 ends
134
135;
136R_CODE segment
137extrn i15_Entry:near ; int15h patch code
138extrn EMM_rEntry:near ; int67h patch code
139extrn i15_Old:word ; old int15 vector
140R_CODE ends
141
142;
143_TEXT segment
144
145 extrn Inst_chk_f:far ; check for MEMM already installed
146 extrn FarGoVirtual:far ; go to virtual mode
147 extrn get_token:near ; get token from command line
148
149_TEXT ends
150;
151LAST segment
152
153 extrn VerifyMachine:near
154 extrn InitMess:byte
155 extrn InstallMess:byte
156 extrn ISizeMess:byte
157 extrn ExtSizeMess:byte
158 extrn SysSizeMess:byte
159 extrn PFBAMess:byte
160 extrn ActiveMess:byte
161 extrn InactiveMess:byte
162 extrn AutoMess:byte
163 extrn InvParm:byte
164 extrn InvPFBA:byte
165 extrn InvMRA:byte
166 extrn Adj_Size:byte
167 extrn InsfMem:byte
168 extrn Incorrect_DOS:byte
169 extrn Incorrect_PRT:byte
170 extrn Already_Inst:byte
171 extrn No_PF_Avail:byte
172 extrn PFWarning:byte
173
174 extrn Is386:far ; check for 386
175 extrn EMM_Init:near ; initialization for EMM data structs
176 extrn AllocMem:near ; allocate extended memory routine
177 extrn InitTab:near ; OEM init code for tables
178 extrn VDM_Init:near ; initialize VDM
179 extrn DeallocMem:near ; deallocate hi/extended memory routine
180
181 extrn find_phys_pages:near ; find the mappable pages in 0-1M range
182 extrn exclude_segments:near ; exclude segments within a range
183 extrn estb_mach_state:near ; establish machine environment
184
185LAST ends
186
187 page
188;******************************************************************************
189; S E G M E N T D E F I N I T I O N
190;******************************************************************************
191
192 page
193;******************************************************************************
194; Data segment
195;******************************************************************************
196_DATA segment
197;
198dos_version db 0h ; MS-DOS version
199pool_size dw 0 ; size of EMM Pages Pool in kbytes
200msg_flag dw 0 ; Message flag byte
201
202driver_end dw 0 ; end of driver -> driver brk address
203 dw seg LAST
204powr10 dw 1,10,100,1000,10000
205max_arg_len equ 11 ; maximum length of argument on cmd line
206arg_str db max_arg_len+1 dup(0)
207;
208; Active_Status is used to signal the termination condition for the
209; driver. After the driver installs, Active_Status holds the
210; current status (ON or OFF).
211; Auto_Mode is set when MEMM is running in AUTO mode.
212;
213Active_Status db 0FFh ; 0 => OFF , non-zero => ON
214Auto_Mode db 0h ; non-zero => auto mode
215
216;
217; The following pointers are segment addresses for various segments
218;
219TEXT_Seg dw seg _TEXT ; current segment for _TEXT
220STACK_Seg dw seg STACK ; current segment for STACK
221GDT_Seg dw seg GDT ; current segment for GDT
222IDT_Seg dw seg IDT ; current segment for IDT
223TSS_Seg dw seg TSS ; current segment for TSS
224
225_DATA ends
226
227
228;******************************************************************************
229;
230; Code Segments
231;
232;******************************************************************************
233;
234_TEXT segment
235 assume cs:_TEXT
236
237
238;*************************************************************************
239;
240; get_token_far call get_token which must be near since it is
241; also part of a .COM file
242;
243;*************************************************************************
244get_token_far proc far
245 call get_token
246 ret
247get_token_far endp
248_TEXT ends
249
250LAST segment
251 assume cs:LAST, ds:DGROUP, es:DGROUP
252
253 page
254;******************************************************************************
255; Init - Initialization routine for MEMM.
256;
257; ENTRY: DS:BX pts to INIT request header.
258;
259; EXIT: AX = INIT status for request header
260; if NO errors :
261; MEMM initialized.
262; if [ON] parameter specified on command line
263; exit in Virtual mode and MEMM active.
264; else ( [OFF] parameter specified )
265; exit in Real mode and MEMM inactive.
266; if errors:
267; Real Mode
268; USED: none
269;
270;******************************************************************************
271Init_MEMM386 proc far
272 push bx ; BP+10
273 push dx ; BP+8
274 push bp ; BP+6
275 push di ; BP+4
276 push ds ; BP+2
277 push es ; BP+0
278 mov bp,sp
279;
280; set up DS = DGROUP and ES:BX to request header
281;
282 push ds
283 pop es ; ES:BX pts to req hdr
284 mov ax,seg DGROUP
285 mov ds,ax ; DS = DGROUP
286
287;
288; initialize break address to not install
289;
290 mov word ptr ES:[bx.BRK_OFF],0000 ; set it
291 mov ax,seg R_CODE ; get brk addr segment
292 inc ax ; reserve dos link pointer
293 mov ES:[bx.BRK_SEG],ax ; break addr = cs - don't install
294 mov byte ptr es:[bx.NUM_UNITS],0 ; 0 - don't install
295;
296; verify that MEMM is not already installed
297;
298 call Inst_chk_f
299 or ax,ax ; q: already installed?
300 jz chk_pt ; n: go check processor type
301 or [msg_flag],INS_ERR_MSG ; y: error
302 jmp IE_exit ; quit
303;
304; verify processor type
305;
306chk_pt:
307 call Is386 ;Q: is this a 386 ?
308 jnz inc_prc ; N: no, set error
309 ; Y: check machine type
310;
311; verify machine type
312;
313chk_mt:
314 stc ; Indicate this is verify from INIT
315 call VerifyMachine ;Q: is this a good machine to run on?
316 jnc chk_dos ; y: ok so far. go check dos version
317inc_prc:
318 or [msg_flag],INC_PRC_MSG ; n: incorrect processor type
319 jmp IE_exit ; quit
320;
321; get DOS version - accept >= 3.1
322;
323chk_dos:
324 push bx
325 mov ah,GET_VERSION
326 int MS_DOS ; get dos version #
327 mov [dos_version],al ; save it.
328 pop bx
329 cmp ax,4 ;Q: DOS 4.00
330 je IE_parse ; Y: OK - continue install
331 cmp al,3 ;Q: DOS 3.xx ?
332 jl IE_dos_err ; N: return error
333 cmp ah,10 ;Q: current DOS >= 3.10 ?
334 jae IE_parse ; Y: OK - continue install
335IE_dos_err:
336 or [msg_flag],INC_DOS_MSG ; N: set error and exit
337 jmp IE_exit
338;
339; parse command line for
340; (1) requested size for expanded memory
341; (2) page frame base address
342; (3) I/O addresses for board emulations
343; (4) Driver exit mode (virtual or real)
344;
345IE_parse:
346 les di,ES:[bx.ARG_PTR] ; ES:DI pts to config.sys command
347 ; line parameters
348 call parser ; parse the parameters
349 test [msg_flag],KILLER_MSG ;Q: any killer messages?
350 jz IE_mach_state ; N: go to establish machine state
351 jmp IE_exit ; Y: exit with error
352
353IE_mach_state:
354;
355 push ds
356 pop es ; ES:DGROUP
357;
358 call estb_mach_state ; since we are an environment, we need
359 ; to find the state we exist in right
360 ; now and maintain it.
361 test [msg_flag],KILLER_MSG ;Q: any killer messages?
362 jz IE_find_phys ; N:go to find physical pages
363 jmp IE_exit ; Y: exit with error
364;
365IE_find_phys:
366 call find_phys_pages ; find mappable physical pages
367 ; and page frame
368 test [msg_flag],KILLER_MSG ;Q: any killer messages
369 jz IE_alloc ; N: Go to find and allocate log. pages
370 jmp IE_exit ; Y: exit with error
371;
372; find and allocate logical emm pages
373;
374IE_alloc:
375 call AllocMem
376 test [msg_flag],KILLER_MSG ;Q: any killer messages?
377 jz IE_InitEMM ; N: init EMM
378 jmp IE_exit ; Y: exit
379;
380; init EMM data
381;
382IE_InitEMM:
383
384 call EMM_Init
385 test [msg_flag],KILLER_MSG ;Q: any killer messages?
386 jz IE_InitVDM ; N: init VDM
387 jmp IE_exit ; Y: exit
388;
389; init VDM - GDT,IDT,TSS,Page Tables
390;
391IE_InitVDM:
392 call VDM_Init
393 test [msg_flag],KILLER_MSG ;Q: any killer messages?
394 jz IE_InitTAB ; N: init TABLES
395 jmp IE_exit ; Y: exit
396;
397; set up segment pointers to Tables & OEM table init
398;
399IE_InitTAB:
400 call InitTab
401 jnc IE_InitT_Good ;Q: any memory allocation error?
402 or [msg_flag],MEM_ERR_MSG ; Y: Some serious memory error
403IE_InitT_Good:
404 test [msg_flag],KILLER_MSG ;Q: any killer messages?
405 jz IE_chkbase ; N: check base memory left
406 jmp IE_exit ; Y: exit
407;
408; Verify that we will have at least 64k of base memory after MEMM
409; is loaded
410;
411IE_chkbase:
412 int 12h ; get base memory size
413 push ax ; save it
414 mov ax,[driver_end] ; get offset of end of MEMM resident
415 add ax,15 ; convert to paragraphs
416 shr ax,4
417 add ax,[driver_end+2] ; add in segment of brk address
418 add ax,63 ; round up to kbytes (64 paras per K)
419 shr ax,6 ; AX = kbytes to end of MEMM resident
420 add ax,DOS3X_ADJ+64 ; add in dos 3.xx adjustment and 64k
421 pop dx ; get base memory back
422 cmp dx,ax ; q: do we have enough?
423 jae IE_setbrk ; y: continue
424 or [msg_flag],MEM_ERR_MSG ; n: set memory error
425 jmp IE_exit ; and exit
426
427;
428; set driver break addr in Init Request Header
429;
430IE_setbrk:
431 mov bx,[bp+2] ; get entry DS from stack
432 mov es,bx
433 mov bx,[bp+10] ; ES:BX pts to req hdr
434 mov ax,[driver_end] ; get brk addr offset
435 mov ES:[bx.BRK_OFF],ax ; set it
436 mov ax,[driver_end+2] ; get brk addr segment
437 mov ES:[bx.BRK_SEG],ax ; set it
438;
439; check exit status of VDM/MEMM (now with lim 4.0) exit must be ON
440;
441; cmp [Auto_Mode],0 ;Q: exit in Auto mode ?
442; je IE_chkOFF ; N: then continue
443; mov [Active_Status],0 ; Y: exit in OFF state
444;IE_chkOFF:
445; cmp [Active_Status],0 ;Q: exit in real mode - OFF
446; je IE_Exit ; Y: continue
447
448; Initialize DEBX_GSEL GDT Selector and Deb386
449;
450 push ds
451 push es
452 push ax
453 push bx
454 push cx
455 push si
456 push di
457
458 push [IDT_Seg]
459 pop es ; ES:DI <-- IDT
460 push [GDT_Seg]
461 pop ds ; DS:SI <-- GDT
462 mov bx, DEBX_GSEL
463 and bl, SEL_LOW_MASK
464 mov word ptr [bx], 1800h ; Limit = 20M
465 mov word ptr [bx + 2], 0
466 mov byte ptr [bx + 4], 0 ; Base = 0
467 mov byte ptr [bx + 5], D_DATA0 ; Ring 0 Data
468 mov byte ptr [bx + 6], 80h ; Page Granularity
469
470 mov ax, 4400h ; Initialize Deb386
471 mov bx, DEBX_GSEL ; BIG selector for all addresses
472 mov cx, DEB1_GSEL ; start of 5 working Selector
473 xor si, si
474 xor di, di
475 int 68h
476
477 pop di
478 pop si
479 pop cx
480 pop bx
481 pop ax
482 pop es
483 pop ds
484
485 call FarGoVirtual ; N: go into virtual mode
486
487;
488; exit - display status messages and set exit status
489;
490IE_exit:
491;
492; display signon message first
493;
494 mov dx,offset LAST:InitMess
495 PRINT_MSG
496;
497; check for messages to display
498;
499IE_Install:
500 mov cx,MAX_MSG ; number of potential msgs
501 mov si,offset msg_tbl ; table of messages
502m_loop:
503 test [msg_flag],01 ; q:is this one set?
504 jz m_inc_ptr ; n: increment table pointer
505 mov dx,cs:[si] ; y: display message
506 PRINT_MSG
507 cmp cx,KILL_MSG ; q: is this one a killer?
508 jbe m_inc_ptr ; n: continue
509 jmp IE_not_installed ; y: don't install
510m_inc_ptr:
511 inc si ; increment msg table ptr
512 inc si
513 shr [msg_flag],1 ; look for next flag
514 loop m_loop
515;
516 mov ax,[pool_size] ; size of EMM page pool in Kbytes
517 mov di,offset LAST:ISizeMess; store decimal size in ASCII here.
518 call b2asc10 ; convert to ASCII...
519;
520 mov ax,[ext_size]
521IFNDEF NOHIMEM
522 add ax,[hi_size]
523endif
524 mov di,offset LAST:ExtSizeMess ; store decimal size of ext/hi alloc
525 ; here
526 call b2asc10
527
528 mov ax,[sys_size]
529 mov di,offset LAST:SysSizeMess ; system memory allocated
530 call b2asc10
531;
532 mov ax,[PF_Base] ; page frame base addr
533 shr ax,8 ; shift right to get significant digits
534 mov di,offset LAST:PFBAMess+1; where to put ascii base address
535base_loop:
536 push ax ; save all digits
537 and ax,0fh ; get one digit
538 cmp ax,9 ; q: digit <=9
539 jbe skip_dig_adj ; y: don't adjust
540 add ax,'A'-':'
541skip_dig_adj:
542 add ax,'0' ; make it ascii
543 mov CS:[di],al ; store in message
544 dec di ; update pointer
545 pop ax ; get all digits back
546 ; shift right for next digit
547 shr ax,4 ; q: done?
548 jnz base_loop ; n: do another
549; y: print it
550 mov dx,offset LAST:InstallMess
551 PRINT_MSG
552;
553; mov dx,offset LAST:AutoMess ; assume AUTO
554; cmp [Auto_Mode],0 ;Q: auto mode ?
555; jne print_mode ; Y: display message
556; mov dx,offset LAST:InactiveMess ; N: assume OFF
557; cmp [Active_Status],0 ; q: OFF specified?
558; jz print_mode ; y
559; mov dx,offset LAST:ActiveMess ; n
560;print_mode:
561; PRINT_MSG
562;
563; Ok, now we can patch int15h - must be careful not to install
564; patch when Active_Status set, but not in virtual mode
565;
566 pushf
567 cli ; clear ints
568 xor ax,ax
569 mov ds,ax ; DS -> 0:0
570 ASSUME DS:ABS0
571 les bx,dword ptr [i15_vector] ; DS:BX -> pts to old one
572 mov ax,offset R_CODE:i15_Entry
573 mov [i15_vector],ax ; set new ip
574 mov ax,seg R_CODE ;
575 mov [i15_vector+2],ax ; set new cs
576 mov ds,ax ; DS -> R_CODE
577 ASSUME DS:R_CODE
578 mov [i15_Old],bx ; save old IP
579 mov [i15_Old+2],es ; save old CS
580 popf ; restore IF
581 mov ax,seg DGROUP
582 mov ds,ax ; DS -> dgroup
583 ASSUME DS:DGROUP
584;
585; now patch int67 for EMM functions
586;
587 pushf
588 cli ; clear ints
589 xor ax,ax
590 mov ds,ax ; DS -> 0:0
591 ASSUME DS:ABS0
592 mov ax,offset R_CODE:EMM_rEntry
593 mov [i67_vector],ax ; set new ip
594 mov ax,seg R_CODE ;
595 mov [i67_vector+2],ax ; set new cs
596 popf ; restore IF
597 mov ax,seg DGROUP
598 mov ds,ax ; DS -> dgroup
599 ASSUME DS:DGROUP
600;
601; all done with no errors
602;
603 xor ax,ax ; NO errors
604;
605IE_leave:
606 pop es
607 pop ds
608 pop di
609 pop bp
610 pop dx
611 pop bx
612 ret
613;
614IE_not_installed:
615 call DeallocMem ; put back any memory we took
616 mov ax,ERROR ; error return
617 jmp IE_leave
618;
619Init_MEMM386 endp
620
621;
622page
623;******************************************************************************
624;
625; parser - parse out MEMM parameters and set appropriate values
626; for expanded memory size ([pool_size]), page frame base
627; address ([PF_Base])
628;
629; entry: es:di == config.sys command line parameters
630; ds = DGROUP
631;
632; exit: [pool_size] = expanded memory size
633; [PF_Base] = page frame base address
634; [Active_Status] =flag for virtual/real mode exit
635; [msg_flag] = appropriate messages to display
636;
637; used: none
638;
639;******************************************************************************
640;
641parser proc near
642 push ax ; BP+16
643 push bx ; BP+14
644 push cx ; BP+12
645 push dx ; BP+10
646 push si ; BP+8
647 push di ; BP+6
648 push bp ; BP+4
649 push ds ; BP+2
650 push es ; BP+0
651 mov bp,sp ;
652 cld ; make sure we go forward
653 xor ax,ax ; clear accumulator
654;
655; Skip past MEMM.EXE in command line
656;
657parm1_loop: ; find 1st parameter
658 mov al,es:[di]
659 cmp al,' ' ; q: find end of MEMM.exe?
660 jbe ploop1 ; y: start parsing
661 inc di ; n: try next one
662 jmp short parm1_loop
663jmp_def:
664 jmp set_def
665;
666jmp_PF:
667 jmp chk_PF
668;
669;jmp_onf:
670; jmp chk_onf
671;
672;jmp_auto:
673; jmp chk_auto
674;
675jmp_Hx:
676 jmp chk_Hx
677;
678jmp_Xs:
679 jmp chk_Xs
680
681ploop1:
682 mov si,offset DGROUP:arg_str; ds:si = storage for argument
683 mov cx,max_arg_len ; maximum length of argument
684 call get_token_far ; get next token
685 or cx,cx ; q: anything there?
686 jz jmp_def ; n: go set default values
687 lodsb ; y: get 1st char
688 cmp al,'m' ; q: PF base address?
689 je jmp_PF ; maybe: go validate it
690 cmp al,'h' ; q: Himem enable /disable?
691 je jmp_Hx ; maybe: go validate it
692 cmp al,'x' ; q: Exclude segment parameter
693 je jmp_Xs ; maybe: go validate it
694; cmp al,'o' ; q: ON/OFF?
695; je jmp_onf ; maybe: go validate it
696; cmp al,'a' ; q: AUTO?
697; je jmp_auto ; maybe: go validate it
698
699 cmp al,'0' ; q: is it a digit (size)
700 jb inv_parm ; n: invalid
701 cmp al,'9' ; q: is it a digit?
702 jbe chk_siz ; y: validate the size
703inv_parm:
704 or [msg_flag],INV_PARM_MSG ; set invalid parameter flag
705 jmp short ploop1 ; continue
706chk_siz:
707 mov bx,cx ; bx = number of digits
708 mov byte ptr [bx+si-1],' ' ; terminate string
709 mov cx,10 ; decimal multiplier
710 xor dx,dx ; clear upper 16 bits
711 xor bx,bx ; clear temporary accumulator
712 cmp [pool_size],0 ; q: have we already done this?
713 jz dig_loop ; n: continue
714 mov dx,1 ; y: skip all of this
715dig_loop:
716 or dx,dx ; q: overflow?
717 jnz new_digit ; y: just skip rest of digits
718 sub al,'0' ; get ones value
719 xchg ax,bx ; swap accumulated value to ax
720 mul cx ; times 10
721 add ax,bx ; add in ones value
722 adc dx,0 ; carry to dx
723 xchg ax,bx ; temporary value to bx
724;
725new_digit:
726 lodsb ; get new char into al
727 cmp al,'0' ; q: between 0 & 9?
728 jb dig_exit ; n: done
729 cmp al,'9'
730 ja dig_exit
731 jmp dig_loop ; y: process it
732;
733dig_exit:
734 cmp al,' ' ; q: any invalid digits?
735 jne ck_inv_parm ; y: invalid parameter
736 or dx,dx ; q: something wrong?
737 jz chk_siz1 ; n: not yet
738 cmp [pool_size],0 ; q: is this the second time for size?
739 jz siz_adj ; n: they just asked for too much
740ck_inv_parm:
741 or [msg_flag],INV_PARM_MSG ; y: only let them do it once
742 jmp ploop1 ; continue
743chk_siz1:
744 cmp bx,16 ;q: did they ask for too little?
745 jb siz_adj ; y: go adjust it
746 cmp bx,MAX_SIZE ;q: too much?
747 ja siz_adj ; y: adjust it
748 mov dx,0fh ; n: make sure it was a multiple of 16k
749 and dx,bx ;q: was it?
750 jz set_siz ; y: no problem
751 sub bx,dx ; n: drop it down
752 jmp siz_msg ; and give them the message
753siz_adj:
754 mov bx,256 ; default value for size
755siz_msg:
756 or [msg_flag],SIZE_ADJ_MSG ; size adjusted
757set_siz:
758 mov [pool_size],bx ; save it
759 jmp ploop1 ; go check more parameters
760
761
762;
763; Check page frame base address
764;
765chk_PF:
766 cmp cx,2 ; q: 2 and only 2 chars in argument?
767 jne inv_prm ; n: error
768 lodsb ; get Mx specifier
769 cmp [PF_Base],0ffffh ; q: have they already specified this?
770 jnz inv_prm ; y: don't let them do it again
771 cmp al,'0' ; q: between 1 & 8?
772 jb inv_prm ; n: invalid
773 cmp al,'8'
774 ja inv_prm ; n: invalid
775 sub al,'0' ; make zero relative
776 xor ah,ah ; zero out hi bits
777 shl ax,1 ; make word offset
778 mov [PF_Base],ax ; store address
779 jmp ploop1 ; get next parameter
780
781;
782; supporting use of Hi Ram. We are providing a command line option for this
783; the parameter is specified as He for himem enable or Hd for Himem disable
784; this parameter may be specified only once in a command line. Also
785;
786chk_Hx:
787; cmp cx,2 ; q: 2 and only 2 chars in argument
788; jne inv_prm ; n: error
789; lodsb ; get Hx specifier
790;;
791; cmp [himem_use],0ffh ; has this already been specified
792; jnz inv_parm
793;;
794; cmp al,'e' ; is user asking us to enable
795; jne Hx$1 ; no, go to check enable
796;;
797; mov [himem_use],01h ; enable himem use
798; jmp ploop1
799;Hx$1:
800; cmp al,'d'
801; jne inv_parm ; if neither d or e it is invalid
802;;
803; mov [himem_use],00h
804 jmp ploop1
805
806;
807inv_prm:
808 or [msg_flag],INV_PARM_MSG ; invalid
809 jmp ploop1 ; get next parameter
810;
811;
812; check for exclusion of segments. this parameter is specfied thusly:
813;
814; X:nnnn-mmmm where nnnn is lo segment and mmmm is hi segment of range to
815; be excluded from being mappable.
816;
817; more than one of these may be specified.
818;
819chk_Xs:
820 call handle_Xswitch
821 jc inv_parm
822 jmp ploop1
823;
824;
825; Check for ON/OFF
826;
827;chk_onf:
828; lodsb ; get next char
829; cmp [Active_Status],1 ; q: have they already specified this?
830; jbe inv_prm ; y: ignore and set error flag
831; cmp [Auto_Mode],1 ; n:q: have they specified auto_mode?
832; je inv_prm ; y: ignore and set error flag
833; cmp al,'n' ; q: on?
834; jne onf_cont ; n: continue
835; cmp cx,2 ; y: is that all there is?
836; jne inv_prm ; n: error
837; mov [Active_Status],1 ; y: set on
838; mov [Auto_Mode],0 ; clear Auto mode
839; jmp ploop1 ; get next parameter
840;onf_cont:
841; cmp al,'f' ; q: OF?
842; jne inv_prm ; n: invalid
843; lodsb ; y: get next char
844; cmp al,'f' ; q: OFF?
845; jne inv_prm ; n: invalid
846; cmp cx,3 ; q: is that all there is?
847; jne inv_prm ; n: error
848; mov [Active_Status],0 ; y: set OFF
849; mov [Auto_Mode],0 ; clear Auto mode
850; jmp ploop1 ; get next parameter
851;
852; Check for AUTO
853;
854;chk_auto:
855; cmp [Active_Status],1 ; q: have they already specified ON/OFF?
856; jbe inv_prm ; y: ignore and set error flag
857; cmp [Auto_Mode],1 ; n:q: have they specified auto_mode?
858; je inv_prm ; y: ignore and set error flag
859; cmp cx,AUTO_LEN ; n: q: parameter correct length ?
860; jne inv_prm ; n: ignore and set error flag
861; push es ; y: check for 'AUTO'
862; push di
863; dec si ; DS:SI pts to begin of arg
864; mov di,offset LAST:AUTO_parm
865; push cs
866; pop es ; ES:DI pts to 'AUTO'
867; cld
868; repe cmpsb ;Q: do CX bytes compare ?
869; pop di ; restore DI
870; pop es ; restore ES
871; jne inv_prm ; N: invalid parameter message
872; mov [Auto_Mode],1 ; Y: set AUTO mode
873; jmp ploop1 ; get next parameter
874;
875; Set default values for those items that were not specified
876;
877set_def:
878
879 ;
880 ; default pool size if not defined is 256k
881 ;
882set_pool_size:
883 cmp [pool_size],0 ; q: did they specify size?
884 jnz set_himem ; y: ok
885 mov [pool_size],256 ; n: set default
886 or [msg_flag],SIZE_ADJ_MSG ; display size adjusted
887
888 ;
889 ; default of use of hi system ram is that it should not be used
890 ;
891set_himem:
892; cmp [himem_use],0ffh ; q:did they specify himem enb/dsb
893; jnz parse_xit ; y: ok
894; mov [himem_use],0 ; n: set default that it is not used
895
896parse_xit: ; restore registers and exit
897 pop es
898 pop ds
899 pop bp
900 pop di
901 pop si
902 pop dx
903 pop cx
904 pop bx
905 pop ax
906 ret
907parser endp
908;
909; parser local data
910;
911;AUTO_parm db "auto"
912;AUTO_LEN equ $-AUTO_parm
913
914
915msg_tbl label word
916 dw offset LAST:Incorrect_PRT ; Incorrect Processor Type
917 dw offset LAST:Incorrect_DOS ; Incorrect Version of DOS
918 dw offset LAST:InsfMem ; Insufficient Memory
919 dw offset LAST:Already_Inst ; Already Installed
920 dw offset LAST:No_PF_Avail ; No Page Frame Space Avail
921kill_end label word ; End of messages that kill driver
922 dw offset LAST:Adj_Size ; Pool Size Adjusted
923 dw offset LAST:InvPFBA ; Page Frame Base Addr Adjusted
924 dw offset LAST:InvMRA ; Map Register Adjusted
925 dw offset LAST:InvParm ; Invalid Parameter msg
926 dw offset LAST:PFWarning ; Page Frame warning message
927MAX_MSG equ (this byte - msg_tbl)/2 ; # of messages to display
928KILL_MSG equ (this byte - kill_end)/2; 1st four will abort driver
929;
930
931page
932;******************************************************************************
933; handle_Xswitch - processes the X switch to make some segments non-mappable ;
934; ;
935; entry: ds:di string with X switch parameters in form "X:nnnn-mmmm" ;
936; cx is length of string
937; ;
938; exit: CY set if invalid parameter ;
939; CY clear if parameter processed ;
940; and non-mappable segments excluded ;
941; ;
942; uses: flags,ax,cx,si ;
943; ;
944; author: ISP 8/24/88 ;
945; ;
946;*****************************************************************************;
947handle_XSwitch proc near
948;
949 cmp cx,5 ; must have atleast 5 symbols
950 jb error_Xs ;
951;
952 lodsb ; get the next letter ":"
953 sub cx,2 ;
954;
955 cmp al,":" ; is it ":"
956 jne error_Xs ; if not it is a bad parameter
957;
958 call htoi ; convert hex to integer
959 jcxz error_Xs ; if we have run out we have a bad parameter
960;
961 mov bx,ax ; save in bx the start segment to be excluded
962;
963 lodsb ; get the next letter
964 dec cx ;
965 jcxz error_Xs
966 cmp al,"-" ; is it the letter "-"
967 jnz error_Xs ;
968;
969 call htoi ; convert hex to mappable
970 call exclude_segments
971
972 clc ; set success and
973 ret ; return
974error_Xs:
975 stc ; set error and
976 ret ; return
977;
978handle_XSwitch endp
979
980;-----------------------------------------------------------------------;
981; htoi ;
982; ;
983; Converts a string to an integer. ;
984; ;
985; Arguments: ;
986; DS:SI = string ;
987; CX = length ;
988; Returns: ;
989; AX = integer ;
990; DS:SI = remaining string ;
991; CX = remaining length ;
992; Alters: ;
993; nothing ;
994; Calls: ;
995; nothing ;
996; History: ;
997; ;
998; ISP (isp) 8/24/88 shifted from ps2emm srces ;
999;-----------------------------------------------------------------------;
1000
1001
1002htoi proc near
1003 push bx
1004 xor ax,ax
1005 mov bx,ax
1006htoi_loop:
1007 jcxz htoi_done
1008
1009; get the next character
1010
1011 mov bl,[si]
1012 inc si
1013 dec cx
1014
1015; see if it's a digit
1016
1017 sub bl,'0'
1018 cmp bl,9
1019 jbe have_hvalue
1020 sub bl,'A'-'0'
1021 cmp bl,'F'-'A'
1022 jbe have_hvalue_but_10
1023 sub bl,'a'-'A'
1024 cmp bl,'F'-'A'
1025 ja htoi_not_digit
1026have_hvalue_but_10:
1027 add bl,10
1028have_hvalue:
1029
1030; shift and add
1031
1032 shl ax,1
1033 shl ax,1
1034 shl ax,1
1035 shl ax,1
1036 add ax,bx
1037 jmp htoi_loop
1038htoi_not_digit:
1039 inc cx ; give back the character
1040 dec si
1041htoi_done:
1042 pop bx
1043 ret
1044htoi endp
1045
1046
1047
1048page
1049;******************************************************************************
1050;
1051; b2asc10 - converts binary to ascii decimal and store at CS:DI
1052; stores 5 ascii chars (decimal # is right justified and
1053; filled on left with blanks)
1054;
1055; entry: ax = binary number
1056; DS = DGROUP
1057; CS:di = place to store ascii chars.
1058;
1059; exit: ASCII decimal representation of number stored at DS:DI
1060;
1061; used: none
1062;
1063; stack:
1064;
1065;******************************************************************************
1066;
1067b2asc10 proc near
1068;
1069 push ax
1070 push bx
1071 push cx
1072 push dx
1073 push si
1074 push di
1075;
1076 mov si,8 ; pointer to base 10 table
1077 xor bl,bl ; leading zeroes flag
1078;
1079; convert binary number to decimal ascii
1080;
1081b2_loop:
1082 xor dx,dx ; clear word extension
1083 mov cx,powr10[si]
1084 div cx ; divide by power of 10
1085 or bl,bl
1086 jnz b2_ascii
1087;
1088 or ax,ax ; q: zero result?
1089 jnz b2_ascii ; n: go convert to ascii
1090;
1091 mov al,' ' ; y: go blank fill
1092 jmp b2_make_strg ;
1093;
1094b2_ascii:
1095 add al,'0' ; put into ascii format
1096 mov bl,1 ; leading zeroes on
1097;
1098b2_make_strg:
1099 mov CS:[di],al ; put ascii number into string
1100 xchg ax,dx
1101 inc di ; increment buffer string pointer
1102 dec si ; decrement power of 10 pointer
1103 dec si ;
1104 jge b2_loop ; Q: Last digit? N: Jump if not
1105;
1106 pop di
1107 pop si
1108 pop dx
1109 pop cx
1110 pop bx
1111 pop ax
1112 ret ; *** return ***
1113;
1114b2asc10 endp
1115;
1116
1117LAST ends ; End of segment
1118;
1119
1120 end ; End of module
1121
1122
1123 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/INITDEB.ASM b/v4.0/src/MEMM/MEMM/INITDEB.ASM
new file mode 100644
index 0000000..76db0dc
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/INITDEB.ASM
@@ -0,0 +1,180 @@
1
2
3page 58,132
4;******************************************************************************
5 title InitDeb - initialize debugger
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: InitDeb - initialize debugger
13;
14; Version: 0.04
15;
16; Date: June 16,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/16/86 Original from VDM MAIN.ASM module
27; 06/28/86 0.02 Name changed from MEMM386 to MEMM
28; 07/06/86 0.04 Changed assume to DGROUP
29;
30;******************************************************************************
31;
32; Functional Description:
33;
34; This routine is linked in when linking with the kernel debugger.
35; InitDeb calls the debugger initialization routine.
36;
37;******************************************************************************
38.lfcond ; list false conditionals
39.386p
40;******************************************************************************
41; P U B L I C S
42;******************************************************************************
43
44 public InitDeb
45
46;******************************************************************************
47; D E F I N E S
48;******************************************************************************
49 include VDMseg.inc
50 include VDMsel.inc
51
52FALSE equ 0
53TRUE equ not FALSE
54CR equ 0dh
55LF equ 0ah
56
57MASTER_IMR equ 21h ; mask port for master 8259
58
59;
60; Definition of the packet used in debug initialization. A pointer to
61; this structure is passed to Debug_Entry.
62;
63DebugInit struc
64 CSseg dw ? ;Real mode code segment
65 DSseg dw ? ;Real mode data segment
66 CSsel dw ? ;Prot mode code selector
67 DSsel dw ? ;Prot mode data selector
68 SpareSel1 dw ? ;Prot mode alias selector 1
69 SpareSel2 dw ? ;Prot mode alias selector 2
70 GDTalias dw ? ;Prot mode GDT r/w alias
71 ProtIDTaddr dq ? ;Prot mode IDT base & limit
72 RealIDTaddr dq ? ;Real mode IDT base & limit
73 BrkFlag db ? ;TRUE if break to debugger
74 ComFlag db ? ;TRUE if com1, FALSE if com2
75DebugInit ends
76
77
78;******************************************************************************
79; E X T E R N A L R E F E R E N C E S
80;******************************************************************************
81ifndef NoBugMode
82dcode segment
83extrn _Debug_Entry:far ; (debinit.asm)
84dcode ends
85endif
86
87_DATA SEGMENT
88
89extrn GDT_Seg:word
90
91_DATA ENDS
92
93;******************************************************************************
94; S E G M E N T D E F I N I T I O N S
95;******************************************************************************
96
97_DATA SEGMENT
98
99InitData DebugInit <>
100
101_DATA ENDS
102
103;
104; code
105;
106LAST SEGMENT
107
108 assume cs:LAST, ds:DGROUP, es:DGROUP
109
110;******************************************************************************
111; InitDeb - initialize kernel debugger
112;
113;
114; ENTRY: Real Mode
115; DS = DGROUP
116; AL = 00h => dont't break on debug init
117; AL = FFh => break on debug init
118;
119; EXIT: Real Mode
120; Kernel debugger initialized
121;
122; USED: none
123;
124;******************************************************************************
125InitDeb proc near
126;
127ifndef NoBugMode
128 pusha
129 push ds
130 push es
131;
132 push ds
133 pop es ; ES = data
134;
135 mov di, offset DGROUP:InitData
136
137 mov bx, dcode
138 mov [di].CSseg, bx
139 mov bx, ddata
140 mov [di].DSseg, bx
141 mov [di].CSsel, DEBC_GSEL
142 mov [di].DSsel, DEBD_GSEL
143 mov [di].SpareSel1, DEBW1_GSEL
144 mov [di].SpareSel2, DEBW2_GSEL
145 mov [di].GDTalias, GDTD_GSEL
146 mov [di].BrkFlag, al ; ? break on entry ?
147 mov [di].ComFlag, FALSE ; com2
148
149 sidt [di].RealIDTaddr
150
151 push ds
152 push di
153 mov ax, [GDT_Seg]
154 mov ds, ax
155
156 lgdt qword ptr ds:[GDTD_GSEL]
157
158 mov si, IDTD_GSEL
159 mov cx, 6
160 lea di, [di].ProtIDTaddr
161 cld
162 rep movsb
163 pop di
164 pop ds
165
166 call _Debug_Entry
167;
168; and return
169;
170 pop es
171 pop ds
172 popa
173endif
174 ret
175InitDeb endp
176
177
178LAST ends
179
180 END
diff --git a/v4.0/src/MEMM/MEMM/INITEPG.ASM b/v4.0/src/MEMM/MEMM/INITEPG.ASM
new file mode 100644
index 0000000..7129b17
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/INITEPG.ASM
@@ -0,0 +1,377 @@
1
2
3page 58,132
4;******************************************************************************
5 title InitEPage - initialize EMM Page pointers
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: InitEPage - initialize EMM Page pointers
13;
14; Version: 0.05
15;
16; Date: June 4,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/04/86 Original
27; 06/28/86 0.02 Name changed from MEMM386 to MEMM
28; 07/06/86 0.04 _pft386 changed to a ptr
29; 07/06/86 0.04 fixed hdma_exit label to edma_exit
30; 07/06/86 0.04 changed assume to DGROUP
31; 07/09/86 0.05 added to FindDMA routine
32;
33;******************************************************************************
34;
35; Functional Description:
36;
37; This module initializes the array of pointers to the EMM Pages used
38; by the expanded memory manager code. Specifically, this module initializes
39; the array EMM_PTE.
40;
41;******************************************************************************
42.lfcond ; list false conditionals
43.386p
44 page
45;******************************************************************************
46; P U B L I C D E C L A R A T I O N S
47;******************************************************************************
48;
49 public InitEPage
50
51 page
52;******************************************************************************
53; L O C A L C O N S T A N T S
54;******************************************************************************
55;
56 include VDMseg.inc
57 include VDMsel.inc
58 include desc.inc
59 include page.inc
60 include instr386.inc
61 include emmdef.inc
62;
63;******************************************************************************
64; E X T E R N A L R E F E R E N C E S
65;******************************************************************************
66;
67
68LAST segment
69
70ifndef NOHIMEM
71extrn Hi_Mem_Size:near
72endif
73
74extrn mappable_segs:byte
75
76LAST ends
77
78
79ABS0 segment at 0000h
80ABS0 ends
81
82
83_DATA segment
84
85extrn DMA_Pages:word ; DMA EMM pages buffer
86extrn DMA_PAGE_COUNT:word ; number of DMA pages
87
88extrn xbase_addr_l:word ; 24 bit address of beginning of extended mem
89extrn xbase_addr_h:byte ; pool of EMM pages.
90extrn ext_size:word ; size of extended memory in kbytes
91extrn sys_size:word ; size of system memory in kbytes
92
93extrn _pft386:word ; ptr to dword array of Page Table entries
94
95_DATA ends
96
97;******************************************************************************
98; S E G M E N T D E F I N I T I O N
99;******************************************************************************
100_DATA segment
101
102ifndef NOHIMEM
103DMA_hi_begin dw 0 ; EMM page # for begin of DMA area in hi mem
104DMA_hi_cnt dw 0 ; # of contiguous EMM pages in hi mem DMA area
105endif
106
107DMA_ext_begin dw 0 ; EMM page # for begin of DMA area in ext mem
108DMA_ext_cnt dw 0 ; # of contiguous EMM pages in ext mem DMA area
109
110;
111; FindDMA variables
112;
113crossed db 0 ; flag => crossed 1st 64k bndry
114b_start dw 0 ; 1st EMM page before 1st 64k bndry
115b_cnt dw 0 ; # of EMM pages before 1st 64k bndry
116a_start dw 0 ; 1st EMM page after 1st 64k bndry
117a_cnt dw 0 ; # of EMM pages after 1st 64k bndry
118
119
120_DATA ends
121;
122;------------------------------------------------------------------------------
123LAST segment
124 assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP
125 page
126;******************************************************************************
127; InitEPage - init EMM_PTE - array of pointers for EMM pages.
128;
129; ENTRY: Real Mode
130; DGROUP:[xbase_addr_l] = 24 bit address of beginning of extended mem
131; DGROUP:[xbase_addr_h] pool of EMM pages.
132; DGROUP:[ext_size] = size of extended memory buffer in kbytes
133;
134; EXIT: Real Mode
135; DGROUP:[DMA_Pages] = initialized to point to up to 8 physically
136; contiguous EMM pages in high memory.
137; DGROUP:[_pft386] = pts to array of ptrs for EMM Pages
138;
139; USED: Flags
140; STACK:
141;------------------------------------------------------------------------------
142InitEPage proc near
143;
144 PUSH_EAX
145 push bx
146 push cx
147 push dx
148 push si
149 push di
150 push ds
151 push es
152;
153 cld
154;
155 mov ax,seg DGROUP
156 mov ds,ax
157 mov es,ax
158 mov di,[_pft386] ; ES:DI points to begin of table
159;
160 mov bx,0 ; BX = current EMM page #
161;
162; set system memory pointers first
163;
164 mov cx,[sys_size] ; get size of system memory in kb
165 shr cx,4 ; convert to number of pages
166 jcxz fin_sys
167 mov eax,0000h*16 ; address of first system page
168 xor si,si ; index into mappable page array
169;
170; store in pft386 array
171;
172SEP_hloop:
173 cmp cs:mappable_segs[si],PAGE_MAPPABLE
174 jne not_this_page
175;
176 stosd
177 inc bx ; next emm page
178 dec cx
179 jcxz fin_sys ; found all pages
180not_this_page:
181 inc si
182 add eax,4000h ; point to next 16k page
183 jmp SEP_hloop ;
184fin_sys:
185;
186ifndef NOHIMEM
187;
188; set high memory pointers next
189;
190 call Hi_Mem_Size ; CX = kbytes of high mem,
191 ; EAX = pointer to high mem
192 ;Q: any hi memory pages ? CX = pg cnt
193 jz IEP_ext ; N: set up ext mem pointers
194 ; Y: set high memory pointers
195;
196; check for contiguous EMM pages
197;
198 push bx ; first hi mem EMM page #
199 push cx ; save # of hi mem EMM pages
200 call FindDMA ; find the DMA pages for hi mem
201 mov [DMA_hi_begin],bx ; save begin EMM page #
202 mov [DMA_hi_cnt],cx ; save cnt
203 pop cx ; restore # of hi mem EMM pages
204 pop bx ; restore EMM page# for 1st of hi mem
205;
206; set entries in _pft386
207;
208IEP_hloop:
209 db 66h
210 stosw ; set this table entry
211 db 66h
212 add ax,4000h ; ADD EAX,4000h
213 dw 0000h ; EAX = addr of next EMM page
214 inc bx ; increment EMM page #
215 loop IEP_hloop ; set all high memory entries
216
217endif ; NOHIMEM
218
219;
220; set extended memory entries
221;
222IEP_ext:
223 mov cx,[ext_size] ; CX = kbytes of ext memory
224 shr cx,4 ;Q: any ext memory pages ? CX = pg cnt
225 jz IEP_Dpages ; N: all done - leave
226 db 66h ; Y: set ext memory pointers
227 mov ax,[xbase_addr_l] ; get pointer to ext memory pool
228 db 66h
229 and ax,0FFFFh ; AND EAX,00FFFFFFh
230 dw 00FFh ; clear highest nibble
231;
232; check for contiguous EMM pages
233;
234 push bx ; first ext mem EMM page #
235 push cx ; save # of ext mem EMM pages
236 call FindDMA ; find the DMA pages for ext mem
237 mov [DMA_ext_begin],bx ; save begin EMM page #
238 mov [DMA_ext_cnt],cx ; save cnt
239 pop cx ; restore # of ext mem EMM pages
240 pop bx ; restore EMM page# for 1st of ext mem
241;
242; set entries in _pft386
243;
244IEP_xloop:
245 db 66h
246 stosw ; set this table entry
247 db 66h
248 add ax,4000h ; ADD EAX,4000h
249 dw 0000h ; EAX = addr of next EMM page
250 inc bx ; increment EMM page #
251 loop IEP_xloop ; set all ext memory entries
252;
253;
254; set up DMA Pages
255;
256IEP_Dpages:
257ifndef NOHIMEM
258 mov ax,[DMA_hi_begin] ; SI = beginning hi mem DMA page
259 mov cx,[DMA_hi_cnt] ; CX = # of hi mem DMA pages
260 cmp cx,[DMA_ext_cnt] ;Q: more hi DMA pages ?
261 jae IEP_Dset ; Y: use hi mem DMA pages
262endif
263 mov cx,[DMA_ext_cnt] ; N: use ext mem pages
264 mov ax,[DMA_ext_begin]
265IEP_Dset:
266
267 mov DMA_Page_Count,cx
268 mov di,offset DGROUP:DMA_Pages ; ES:DI ->dest array
269 cld
270DMA_Pg_St:
271 stosw ; store index for dma page
272 inc ax ;
273 loop DMA_Pg_St ;
274;
275; all done
276;
277 pop es
278 pop ds
279 pop di
280 pop si
281 pop dx
282 pop cx
283 pop bx
284 POP_EAX
285 ret
286;
287InitEPage endp
288;
289
290;******************************************************************************
291; FindDMA - find contiguous DMA pages
292;
293; ENTRY: Real Mode
294; EAX = 24 bits of beginning address of EMM memory pool
295; BX = first EMM page #
296; CX = # of EMM pages in this pool
297;
298; EXIT: Real Mode
299; BX = EMM page# of first DMA page
300; CX = # of DMA pages
301;
302; USED: Flags
303; STACK:
304;------------------------------------------------------------------------------
305FindDMA proc near
306;
307 push eax
308
309;
310; initialise the variables needed for this calculation
311;
312 mov [b_start],bx
313 mov [a_start],bx
314 mov [crossed],0
315 mov [a_cnt],0
316 mov [b_cnt],0
317
318 jcxz fdp_exit ; if no pages to check exit ...
319;
320; convert physical address in eax (which is assumed to be aligned on 4k bdry)
321; to page # (in 4k physical pages) modulo 32. This is to find the page # in
322; the current 128k block
323;
324 shr eax,12 ; physical_address >> 4*1024
325 and ax,01fh ; modulo 32, also sets Z flag if on 128k
326 ; bdry. So Q: On 128K bdry?
327 jnz fdp_loop ; N: continue as normal
328 mov [crossed],1 ; Y: set flag
329
330fdp_loop:
331 add ax,04h ;Q: add 16k bytes, did it cross 128k ?
332 test ax,NOT 01fh ; if into next 128k it will go into next
333 ; bit
334 je fdp_no_cross ; N: continue
335 cmp [crossed],0 ; Y:Q: have we crossed it before ?
336 je fdp_cross1 ; N: update counts
337 and ax,01fh ; Y:Q: equal to 128k bndry ?
338 jnz fdp_exit ; N: then leave
339 inc [a_cnt] ; Y: update last cnt
340 jmp fdp_exit ; and leave
341
342fdp_cross1: ; first crossing of 128k bndry
343 mov [crossed],1 ; set crossed flag.
344 mov [a_start],bx ; start with ...
345 inc [a_start] ; next page.
346 and ax,01fh ;Q: equal to 128k bndry ?
347 jnz fdp_next ; N: next page
348 inc [b_cnt] ; Y: include page in before pages
349 jmp fdp_next ; and go to next page
350
351fdp_no_cross:
352 cmp [crossed],0 ;Q: have we crossed first 64k bndry ?
353 jne fdp_n_c ; Y: update it's count
354 inc [b_cnt] ; N: update before count
355 jmp fdp_next
356fdp_n_c:
357 inc [a_cnt] ; update after count
358fdp_next:
359 inc bx ; next page #
360 loop fdp_loop ; and continue
361;
362fdp_exit:
363 mov bx,[b_start] ; BX = first page before
364 mov cx,[b_cnt] ; CX = cnt of pages before
365 cmp cx,[a_cnt] ;Q: more before than after ?
366 jae fdp_ret ; Y: return pages before
367 mov bx,[a_start] ; N: return pages after
368 mov cx,[a_cnt] ;
369fdp_ret:
370 pop eax ; restore EAX
371 ret
372;
373FindDMA endp
374
375LAST ends ; end of segment
376;
377 end ; end of module
diff --git a/v4.0/src/MEMM/MEMM/INITTAB.ASM b/v4.0/src/MEMM/MEMM/INITTAB.ASM
new file mode 100644
index 0000000..c37b78e
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/INITTAB.ASM
@@ -0,0 +1,632 @@
1
2
3page 58,132
4;******************************************************************************
5 title InitTab - OEM init routines to init tables
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: InitTab
13;
14; Version: 0.05
15;
16; Date: June 4,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/04/86 Original
27; 06/21/86 0.02 Added cld
28; 06/28/86 0.02 Name changed from MEMM386 to MEMM
29; 07/05/86 0.04 Added NOHIMEM ifdef and added code to
30; move _TEXT segment to high mem
31; 07/06/86 0.04 changed assume to DGROUP
32; 07/06/86 0.04 added ring0 stack move
33; 07/10/86 0.05 removed CODE_GSEL reset
34; 07/10/86 0.05 PageT_Seg and PageD_Seg
35;
36;******************************************************************************
37;
38; Functional Description:
39;
40; This module is called after the system has been set up in a viable
41; state to start executing MEMM. This routine provides a "hook" where
42; the tables (GDT,IDT,TSS, & PageTables, etc) can be modified. This routine
43; must set the variables which hold the 32 bit address for each of the
44; VDM tables. This routine also sets up the EXTRA1_GSEL to point to the
45; Diagnostics byte segment.
46;
47;******************************************************************************
48.lfcond ; list false conditionals
49.386p
50 page
51;******************************************************************************
52; P U B L I C D E C L A R A T I O N S
53;******************************************************************************
54;
55 public InitTab
56
57 page
58;******************************************************************************
59; L O C A L C O N S T A N T S
60;******************************************************************************
61;
62OEM_MEM_HI equ 80c0h ; Upper 16 bits of high mem physical adr
63
64 include VDMseg.inc
65 include VDMsel.inc
66 include desc.inc
67 include page.inc
68 include instr386.inc
69 include oemdep.inc
70;
71;******************************************************************************
72; E X T E R N A L R E F E R E N C E S
73;******************************************************************************
74;
75
76GDT segment
77 extrn GDTLEN:abs
78GDT ends
79
80IDT segment
81 extrn IDTLEN:abs
82IDT ends
83
84TSS segment
85 extrn TSSLEN:abs
86TSS ends
87
88PAGESEG segment
89 extrn P_TABLE_CNT:abs
90PAGESEG ends
91
92
93_DATA segment
94 extrn TEXT_Seg:word ; segment for TEXT
95 extrn STACK_Seg:word ; segment for STACK
96 extrn GDT_Seg:word ; segment for GDT
97 extrn IDT_Seg:word ; segment for IDT
98 extrn TSS_Seg:word ; segment for TSS
99 extrn PageD_Seg:word ; segment for page dir
100 extrn PageT_Seg:word ; segment for page table
101 extrn Page_Dir:word ; 32 bit address for Page directory
102 extrn driver_end:dword ; ending address for MEMM.EXE
103 extrn _emm_brk:word ; break address for EMM data
104
105_DATA ends
106
107LAST segment
108ifndef NOHIMEM
109 extrn HiSysAlloc:near ; allocate high system memory
110 extrn UnLockROM:near
111 extrn LockROM:near
112endif
113 extrn SegTo24:near
114 extrn SetSegDesc:near
115 extrn SetPageEntry:near
116 extrn moveb:near
117 extrn get_buffer:near
118
119LAST ends
120
121_TEXT segment
122 extrn Real_Seg:word ; fixup for _TEXT in RetReal (retreal.asm)
123_TEXT ends
124
125R_CODE segment
126 extrn EFunTab:word ; table of ELIM functions
127 extrn EFUN_CNT:abs ; # of entries in table
128 extrn EMM_rEfix:near ; far call to EMM function dispatcher in _TEXT
129R_CODE ends
130
131
132;******************************************************************************
133; S E G M E N T D E F I N I T I O N
134;******************************************************************************
135;
136;------------------------------------------------------------------------------
137LAST segment
138 assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP
139 page
140;******************************************************************************
141; InitTab - init tables & 32 bit address
142;
143; ENTRY: Real Mode
144; GDT = current segment for GDT
145; IDT = current segment for IDT
146; TSS = current segment for TSS
147; _TEXT = current segment for _TEXT
148; STACK = current segment for STACK
149; DGROUP:[PageD_Seg] = current segment portion of page directory
150; DGROUP:[PageT_Seg] = current segment portion of page tables
151; DGROUP:[Page_Dir] = current 32 bit address for page directory
152; IDTLEN:abs = length of IDT
153; TSSLEN:abs = length of TSS
154; P_TABLE_CNT:abs = # of page TABLES
155; _TEXT:[Real_Seg] = fixup location for _TEXT in RetReal
156; R_CODE:[EFunTab] = table of ELIM functions
157; R_CODE:EFUN_CNT = # of entries in table
158; R_CODE:[EMM_rEfix] = far call to EMM function dispatcher in _TEXT
159;
160; EXIT: Real Mode
161; DGROUP:[TEXT_Seg] = current segment for TEXT
162; DGROUP:[STACK_Seg] = current segment for STACK
163; DGROUP:[GDT_Seg] = current segment for GDT
164; DGROUP:[IDT_Seg] = current segment for IDT
165; DGROUP:[TSS_Seg] = current segment for TSS
166; DGROUP:[PageD_Seg] = current segment portion of page directory
167; DGROUP:[PageT_Seg] = current segment portion of page tables
168; DGROUP:[Page_Dir] = current 32 bit address for page directory
169; DGROUP:[driver_end] = end of MEMM.EXE device driver
170; GDT:[IDTD_GSEL] = current descriptor for IDT
171; GDT:[TSS_GSEL] = current descriptor for TSS
172; GDT:[TSSD_GSEL] = current descriptor for TSS
173; GDT:[PAGET_GSEL] = current descriptor for Page TABLES
174;
175;
176; USED: Flags
177; STACK:
178;------------------------------------------------------------------------------
179InitTab proc near
180;
181ifndef NOHIMEM
182
183 PUSH_EAX
184 push di
185 push ds
186 push es
187 pushf
188 cli ; turn off ints
189 cld ; strings foward
190;
191 mov ax,seg DGROUP
192 mov ds,ax
193;
194; set up GDT entry for the diagnostics segment
195;
196 mov ax, seg GDT ; GDT not moved yet !
197 mov es,ax
198
199 xor dx,dx
200 mov al,00h ; only low 24 bits of address here !
201 mov cx,0 ; 64k long
202 mov ah,D_DATA0 ; data segment
203 mov bx,OEM0_GSEL
204 call SetSegDesc ; Set up GDT alias descriptor
205 mov ES:[bx.BASE_XHI],01h ; set high 8 bits of address
206
207;
208;------------------------------------------------------------------------------
209; Move Tables to HIGH SYSTEM memory
210; The high system memory is mapped to FE0000h - FEFFFFh
211; AND 0E0000h-0EFFFFh. The following code copies data to the E0000h
212; range
213;------------------------------------------------------------------------------
214;
215
216;
217;------------------------------------------------------------------------------
218; move PAGE DIR/TABLES up to high memory
219;------------------------------------------------------------------------------
220;
221 mov ax,P_TABLE_CNT ; AX = # of page tables
222 inc ax ; include page directory
223 mov cx,ax ; CX=AX = # of pages for page table seg
224 call HiSysAlloc ;Q: enough room in high sys mem ?
225 jnc IT_move_pt ; Y: move page dir/tables to hi sys mem
226 inc ax ; N: Q: is error not enough room?
227 jnz To_IT_Exit ; Y: just go ahead and exit
228 popf
229 stc ; N: return CF = 1(mem alloc error)
230 jmp IT_Quit
231To_IT_Exit:
232 jmp IT_Exit ; N: then nothing is moved up
233IT_move_pt: ;
234 call UnLockROM ;turn off write protect
235 shl ax,8 ;
236 add ax,0E000h ; AX = segment for sys mem block
237 mov es,ax ; ES -> sys mem block
238 xor di,di ; ES:DI -> sys mem block
239 mov ax,[PageD_Seg] ;
240 mov ds,ax ; DS -> page dir/tables
241 xor si,si ; DS:SI -> page dir/tables
242 shl cx,10 ; CX = # of dwords in page tables
243 cld
244 OP32
245 rep movsw ; mov cx dwords into hi sys mem
246;
247 mov ax,seg DGROUP
248 mov ds,ax ; DS = DATA
249;
250; reset break address for driver
251;
252 mov word ptr [driver_end],0
253 mov ax,[PageD_Seg]
254 mov word ptr [driver_end+2],ax
255
256;
257; reset page dir/table pointers
258 XOR_EAX_EAX ; clear eax
259 mov ax,es ;
260 mov [PageD_Seg],ax ; reset segment for page dir
261 add ax,P_SIZE/10h ; ax = segment page table
262 mov [PageT_Seg],ax ; rest it
263
264 mov ax,es ; get page dir seg again
265 OP32
266 shl ax,4 ; shl EAX,4 => EAX = 32 bit address
267 OP32
268 mov [Page_Dir],ax ; store 32 bit addr of page dir
269;
270; reset page directory entries
271;
272 mov ax,word ptr [Page_Dir] ; DX,AX = 32 bit addr of Page Directory
273 mov dx,word ptr [Page_Dir+2] ; save it
274;
275; get addr of Page Table for Page Directory entry
276;
277 add ax,1000h ; add page
278 adc dx,0h ; carry it => DX,AX = addr of page table
279;
280; DX,AX = addr of first page table
281;
282 xor di,di ; ES:[DI] -> 1st entry in page dir
283 mov bh,0
284 mov bl,P_AVAIL ; make table available to all
285 mov cx,P_TABLE_CNT ; set entries in page table directory
286 ; for existing page tables.
287IT_pdir:
288 call SetPageEntry ; set entry for first page table
289;
290; ES:[DI] pts to next entry in page directory
291 add ax,1000h
292 adc dx,0 ; DX,AX = addr of next page table
293 loop IT_pdir ; set next entry in dir
294;
295; reset PAGET_GSEL descriptor
296;
297 mov ax,seg GDT ; GDT has not yet moved!!!
298 mov es,ax ; ES pts to GDT
299
300 mov ax,[PageT_Seg] ; segment for page tables
301 call SegTo24
302 mov cx,0 ; enough room for tables
303 mov ah,D_DATA0
304 mov bx,PAGET_GSEL
305 call SetSegDesc ; set up page table descriptor
306;
307; now set CR3 in the TSS - to reflect new Page DIR position
308;
309 mov ax,seg TSS ; TSS not moved yet !!!
310 mov es,ax ; ES -> TSS
311 xor di,di ; ES:DI -> TSS
312
313 db 66h
314 mov ax,[Page_Dir] ; EAX = page dir 32 bit addr
315 db 66h
316 mov word ptr ES:[di.TSS386_CR3],ax ; mov EAX into CR3 spot in TSS
317;
318;------------------------------------------------------------------------------
319; move _TEXT, GDT,IDT, & TSS up to high system memory
320; **** this code depends on the order of the _TEXT, GDT, IDT, & TSS
321; segments when linked. They should be in the order
322; _TEXT, GDT, IDT, then TSS.
323;------------------------------------------------------------------------------
324;
325 mov ax,seg TSS ; compute # of paras from begin of _TEXT
326 sub ax,seg _TEXT ; to begin of TSS
327 shl ax,4 ; convert it to bytes
328 add ax,TSSLEN ; and add in length of TSS
329 ; AX=length of _TEXT,GDT,IDT, & TSS segs
330 add ax,P_SIZE-1 ; round up to nearest page boundary
331 shr ax,12 ; AX = # of 4k pages for these tables
332 mov cx,ax ; CX=AX = # of pages for these tables
333 call HiSysAlloc ;Q: enough room in high sys mem ?
334 jnc IT_move_tables ; Y: move page dir/tables to hi sys mem
335 call LockROM ; N: move nothing. write protect ROM
336 jmp IT_Exit ;
337IT_move_tables:
338 call UnLockROM ; turn off write protect
339 shl ax,8 ; AX = # of paras already allocated
340 ; in high memory
341 add ax,0E000h ; AX = segment for sys mem block
342 mov es,ax ; ES -> sys mem block
343 xor di,di ; ES:DI -> sys mem block
344
345 mov ax,seg _TEXT ; start with _TEXT
346 mov ds,ax ; DS -> _TEXT
347 xor si,si ; DS:SI -> _TEXT
348 shl cx,10 ; CX=# of dwords for _TEXT,GDT,IDT,&TSS
349 cld
350 OP32
351 rep movsw ; mov _TEXT,GDT,IDT,&TSS into hi sys mem
352
353;
354; now reset pointers to _TEXT, GDT, IDT, & TSS
355 mov ax,seg DGROUP
356 mov ds,ax ; DS = DATA
357
358 mov ax,es ; AX = segment for new _TEXT location
359 mov [TEXT_Seg],ax ; set new _TEXT segment
360
361 mov bx,seg GDT
362 sub bx,seg _TEXT ; bx = offset from _TEXT to GDT
363 add ax,bx ; (don't worry, won't cross Linear 64k)
364 mov [GDT_Seg],ax ; set new GDT segment
365
366 mov bx,seg IDT
367 sub bx,seg GDT ; bx = offset from GDT to IDT
368 add ax,bx ; (don't worry, won't cross Linear 64k)
369 mov [IDT_Seg],ax ; set new IDT segment
370
371 mov bx,seg TSS
372 sub bx,seg IDT ; bx = offset from IDT to TSS
373 add ax,bx ; (don't worry, won't cross Linear 64k)
374 mov [TSS_Seg],ax ; set new TSS segment
375;
376; reset descriptors for _TEXT, GDT, IDT, & TSS
377;
378 mov ax,[GDT_Seg] ; GDT has MOVED !!!
379 mov es,ax ; ES pts to GDT
380
381 mov ax,[TEXT_Seg] ; _TEXT segment
382 call SegTo24
383 mov cx,0
384 mov ah,D_CODE0
385 mov bx,VDMC_GSEL
386 call SetSegDesc ; Set up VDM code descriptor - VDMC
387
388 mov ax,[TEXT_Seg] ; _TEXT segment
389 call SegTo24
390 mov cx,0
391 mov ah,D_DATA0
392 mov bx,VDMCA_GSEL
393 call SetSegDesc ; Set up VDM code alias descriptor
394
395 mov ax,[GDT_Seg] ; GDT segment
396 call SegTo24
397 mov cx,GDTLEN
398 mov ah,D_DATA0
399 mov bx,GDTD_GSEL
400 call SetSegDesc ; Set up GDT alias descriptor
401
402 mov ax,[IDT_Seg] ; IDT segment
403 call SegTo24
404 mov cx,IDTLEN
405 mov ah,D_DATA0
406 mov bx,IDTD_GSEL
407 call SetSegDesc ; Set up IDT alias descriptor
408
409 mov ax,[TSS_Seg] ; segment of TSS
410 call SegTo24
411 mov cx,TSSLEN
412 mov ah,D_386TSS0
413 mov bx,TSS_GSEL
414 call SetSegDesc ; Set up TSS descriptor
415
416 mov ah,D_DATA0
417 mov bx,TSSD_GSEL
418 call SetSegDesc ; Set up TSS alias descriptor
419
420;
421; fixup new RING 0 stack location
422;
423 mov ax,[_emm_brk] ; get EMM break address
424 add ax,15 ; round up to next paragraph
425 shr ax,4
426 add ax,seg _DATA ; AX = new seg address for STACK
427 mov [STACK_seg],ax ; save it
428
429 call SegTo24
430 mov cx,offset STACK0_SIZE ; length of stack
431 mov ah,D_DATA0
432 mov bx,VDMS_GSEL
433 call SetSegDesc ; Set up STACK segment GDT entry
434
435;
436; fixup far call / far jump references to _TEXT
437;
438
439; far call pointers in ELIM function table
440 mov ax,seg R_CODE
441 mov es,ax ; ES -> R_CODE
442 mov di,offset R_CODE:EFunTab+2 ; ES:DI -> 1st seg in func tab
443 mov cx,EFUN_CNT ; CX = # of dword entries
444 mov ax,[TEXT_Seg]
445IT_Tloop:
446 stosw ; store new TEXT seg
447 inc di
448 inc di ; point to next seg in table
449 loop IT_Tloop
450
451; ELIM_rEntry far call
452 mov di,offset R_CODE:EMM_rEfix ; point to far call
453 mov ES:[di+3],ax ; set seg portion of call
454
455; Far jump in return to real code
456 mov es,ax ; ES -> new TEXT seg
457 mov di,offset _TEXT:Real_Seg ; ES:DI -> seg of far jmp
458 mov ES:[di],ax ; fix it
459
460;
461; reset break address for driver - throw away _TEXT seg and all after it
462;
463 mov word ptr [driver_end],10h ; just in case
464 mov ax,[STACK_Seg] ; begin of new stack location
465 add ax,STACK0_SIZE/10h ; add in size of stack
466 mov word ptr [driver_end+2],ax ; set break seg to end of stack
467
468;
469; OK, now lock high system RAM
470;
471 call LockROM
472;
473IT_exit:
474 popf
475 clc ; No error in memory allocation attempt
476IT_quit:
477 pop es
478 pop ds
479 pop di
480 POP_EAX
481else
482
483 push es
484 push di
485 push eax
486 push dx
487 push cx
488 push bx
489;
490; try to move the pageseg up
491;
492 ;
493 ; segment to be moved up
494 ;
495 mov ax, [PageD_Seg]
496 mov es,ax
497 ;
498 ; its length
499 ;
500 mov ax,seg LAST
501 sub ax,seg PAGESEG
502 shl ax,4
503 mov cx,ax
504 ;
505 ; we need to allocate enough to have a page aligned page directory. so
506 ; increase this by 4k
507 push cx
508 add cx,4*1024
509 ;
510 ; allocate a block of memory for this
511
512 call get_buffer
513 pop cx
514 jc no_mem
515 ;
516 ; dx:ax is new address of page directory, adjust this to be page aligned
517 ;
518 add ax,4*1024
519 adc dx,0
520 and ax,0F000h
521 ;
522 push ax
523 push dx
524 push cx
525 ;
526 add ax,1000h
527 adc dx,0h
528 ;
529 ; set the entries in the page directory for these
530 ;
531 xor di,di ; es:di points to first page_dir entry
532 mov bh,0
533 mov bl, P_AVAIL
534 mov cx,P_TABLE_CNT
535set_entries:
536 call SetPageEntry
537 ;
538 ; es:di points to next entry in page directory
539 ;
540 add ax,1000h
541 adc dx,0 ; next page table
542 loop set_entries
543 ;
544 ; now we can move the page directory and tables up into extended
545 ;
546 pop cx
547 pop dx
548 pop ax
549 ;
550 xor di,di ; es:di is now the beginning, cx count of
551 ; number of bytes in segment and dx:ax area
552 ; where it is to be moved
553 call moveb ; move the data
554 jnz move_error ; there was an error in moving. the page
555 ; table entries need to be restored to the
556 ; lo memory stuff
557 ;
558 ; move succeded, fix page directory address and driver_end
559 ;
560 mov word ptr [Page_Dir],ax ; DX,AX = 32 bit addr of Page Directory
561 mov word ptr [Page_Dir+2],dx ; save it
562;
563; reset PAGET_GSEL descriptor
564;
565 mov cx,seg GDT ; GDT has not yet moved!!!
566 mov es,cx ; ES pts to GDT
567
568 add ax,1000h
569 adc dx,0
570 xchg ax,dx ; for setsegdesc in opposite
571 ; al:dx
572
573 mov cx,0 ; enough room for tables
574 mov ah,D_DATA0
575 mov bx,PAGET_GSEL
576 call SetSegDesc ; set up page table descriptor
577 ;
578 ; if we succeed in shifting the page tables up the ground is clear for us
579 ; to shrink the driver even more to the point where the variable emm data
580 ; structures end.
581 ;
582 mov ax,[_emm_brk] ; get EMM break address
583 add ax,15 ; round up to next paragraph
584 shr ax,4
585 add ax,seg DGROUP ; AX = end address for driver
586 mov word ptr [driver_end],10h ; just in case, para offset
587 mov word ptr [driver_end+2],ax ; segment
588
589
590no_mem:
591 pop bx
592 pop cx
593 pop dx
594 pop eax
595 pop di
596 pop es
597 clc
598 jmp end_inittab
599
600move_error:
601 ; the address of page table in lo mem
602 ;
603 mov ax,[PageT_Seg]
604 mov cx,4
605 xor dx,dx
606 mul cx
607 ;
608 ; set the entries in the page directory for these
609 ;
610 xor di,di ; es:di points to first page_dir entry
611 mov bh,0
612 mov bl, P_AVAIL
613 mov cx,P_TABLE_CNT
614restore_entries:
615 call SetPageEntry
616 ;
617 ; es:di points to next entry in page directory
618 ;
619 add ax,1000h
620 adc dx,0 ; next page table
621 loop restore_entries
622 ;
623 jmp no_mem
624endif
625end_inittab:
626 ret
627;
628InitTab endp
629;
630LAST ends ; end of segment
631;
632 end ; end of module
diff --git a/v4.0/src/MEMM/MEMM/INSTR386.INC b/v4.0/src/MEMM/MEMM/INSTR386.INC
new file mode 100644
index 0000000..490435a
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/INSTR386.INC
@@ -0,0 +1,563 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: INSTR386 - 386 Instruction Macro Declaration file
10;
11; Version: 0.03
12;
13; Date: May 11, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 05/11/86 Original
24; 06/01/86 Added operand/address size overide defines
25; 06/28/86 0.02 Name change from MEMM386 to MEMM
26; 07/01/86 0.03 Added 32 arithmetic defines
27;
28;******************************************************************************
29ifndef INC_LIST
30.xlist
31endif
32
33;*** OP32_IRET - 32 bit mode iret
34OP32_IRET macro
35 db 66h
36 iret
37 endm
38
39;*** OP32 - instruction prefix to invert sense of operand size attribute
40
41OP32 macro
42 db 66h
43 endm
44
45
46;*** EA32 - instruction prefix to invert sense of effective addr attribute
47
48EA32 macro
49 db 67h
50 endm
51
52
53;*** FS and GS overides
54FSOVER macro
55 db 64h
56 endm
57GSOVER macro
58 db 65h
59 endm
60
61; *** General Register 32 bit moves ***
62
63MOV_EBX_EAX macro
64 db 66h
65 mov bx, ax
66 endm
67
68MOV_EAX_EBX macro
69 db 66h
70 mov ax, bx
71 endm
72
73MOV_ECX_EAX macro
74 db 66h
75 mov cx, ax
76 endm
77
78MOV_EAX_ECX macro
79 db 66h
80 mov ax, cx
81 endm
82
83MOV_EDX_EAX macro
84 db 66h
85 mov dx, ax
86 endm
87
88MOV_EAX_EDX macro
89 db 66h
90 mov ax, dx
91 endm
92
93MOV_EDI_EAX macro
94 db 66h
95 mov di, ax
96 endm
97
98MOV_EAX_EDI macro
99 db 66h
100 mov ax, di
101 endm
102
103MOV_ESI_EAX macro
104 db 66h
105 mov si, ax
106 endm
107
108MOV_EAX_ESI macro
109 db 66h
110 mov ax, si
111 endm
112
113MOV_EBP_EAX macro
114 db 66h
115 mov bp, ax
116 endm
117
118MOV_EAX_EBP macro
119 db 66h
120 mov ax, bp
121 endm
122
123MOV_ESP_EAX macro
124 db 66h
125 mov sp, ax
126 endm
127
128MOV_EAX_ESP macro
129 db 66h
130 mov ax, sp
131 endm
132
133; *** Special Register/EAX 32 bit moves ***
134
135MOV_CR0_EAX macro
136 db 0Fh,22h,0C0h
137 endm
138
139MOV_CR0_EBX macro
140 db 0Fh,22h,0C3h
141 endm
142
143MOV_CR0_ECX macro
144 db 0Fh,22h,0C1h
145 endm
146
147MOV_CR0_EDX macro
148 db 0Fh,22h,0C2h
149 endm
150
151MOV_CR0_ESP macro
152 db 0Fh,22h,0C4h
153 endm
154
155MOV_CR0_EBP macro
156 db 0Fh,22h,0C5h
157 endm
158
159MOV_CR0_ESI macro
160 db 0Fh,22h,0C6h
161 endm
162
163MOV_CR0_EDI macro
164 db 0Fh,22h,0C7h
165 endm
166
167MOV_EAX_CR0 macro
168 db 0Fh,20h,0C0h
169 endm
170
171MOV_EBX_CR0 macro
172 db 0Fh,20h,0C3h
173 endm
174
175MOV_ECX_CR0 macro
176 db 0Fh,20h,0C1h
177 endm
178
179MOV_EDX_CR0 macro
180 db 0Fh,20h,0C2h
181 endm
182
183MOV_ESP_CR0 macro
184 db 0Fh,20h,0C4h
185 endm
186
187MOV_EBP_CR0 macro
188 db 0Fh,20h,0C5h
189 endm
190
191MOV_ESI_CR0 macro
192 db 0Fh,20h,0C6h
193 endm
194
195MOV_EDI_CR0 macro
196 db 0Fh,20h,0C7h
197 endm
198
199MOV_CR2_EAX macro
200 db 0Fh,22h,0D0h
201 endm
202
203MOV_EAX_CR2 macro
204 db 0Fh,20h,0D0h
205 endm
206
207MOV_CR3_EAX macro
208 db 0Fh,22h,0D8h
209 endm
210
211MOV_EAX_CR3 macro
212 db 0Fh,20h,0D8h
213 endm
214
215MOV_DR0_EAX macro
216 db 0Fh,23h,0C0h
217 endm
218
219MOV_DR0_EBX macro
220 db 0Fh,23h,0C3h
221 endm
222
223MOV_DR1_EAX macro
224 db 0Fh,23h,0C8h
225 endm
226
227MOV_DR2_EAX macro
228 db 0Fh,23h,0D0h
229 endm
230
231MOV_DR3_EAX macro
232 db 0Fh,23h,0D8h
233 endm
234
235MOV_DR6_EAX macro
236 db 0Fh,23h,0F0h
237 endm
238
239MOV_DR7_EAX macro
240 db 0Fh,23h,0F8h
241 endm
242
243MOV_EAX_DR0 macro
244 db 0Fh,21h,0C0h
245 endm
246
247MOV_ECX_DR0 macro
248 db 0Fh,21h,0C1h
249 endm
250
251MOV_EDX_DR0 macro
252 db 0Fh,21h,0C2h
253 endm
254
255MOV_EAX_DR1 macro
256 db 0Fh,21h,0C8h
257 endm
258
259MOV_EAX_DR2 macro
260 db 0Fh,21h,0D0h
261 endm
262
263MOV_EAX_DR3 macro
264 db 0Fh,21h,0D8h
265 endm
266
267MOV_EAX_DR6 macro
268 db 0Fh,21h,0F0h
269 endm
270
271MOV_EAX_DR7 macro
272 db 0Fh,21h,0F8h
273 endm
274
275MOV_TR6_EAX macro
276 db 0Fh,26h,0F0h
277 endm
278
279MOV_EAX_TR6 macro
280 db 0Fh,24h,0F0h
281 endm
282
283MOV_TR7_EAX macro
284 db 0Fh,26h,0F8h
285 endm
286
287MOV_EAX_TR7 macro
288 db 0Fh,24h,0F8h
289 endm
290
291; *** 32 bit Register/Immediate moves ***
292
293MOV_EAX_ macro imm
294 db 66h, 0B8h
295 dd imm
296 endm
297
298MOV_EBX_ macro imm
299 db 66h, 0BBh
300 dd imm
301 endm
302
303MOV_ECX_ macro imm
304 db 66h, 0B9h
305 dd imm
306 endm
307
308MOV_EDX_ macro imm
309 db 66h, 0BAh
310 dd imm
311 endm
312
313MOV_EDI_ macro imm
314 db 66h, 0BFh
315 dd imm
316 endm
317
318MOV_ESI_ macro imm
319 db 66h, 0BEh
320 dd imm
321 endm
322
323MOV_EBP_ macro imm
324 db 66h, 0BDh
325 dd imm
326 endm
327
328MOV_ESP_ macro imm
329 db 66h, 0BCh
330 dd imm
331 endm
332
333; *** 32-bit immediate arithmetic instructions
334
335ADD_EAX_ macro imm
336 db 66h,05h
337 dd imm
338 endm
339
340ADD_EBX_ macro imm
341 db 66h,81h,0C3h
342 dd imm
343 endm
344
345ADD_ECX_ macro imm
346 db 66h,81h,0C1h
347 dd imm
348 endm
349
350ADD_EDX_ macro imm
351 db 66h,81h,0C2h
352 dd imm
353 endm
354
355SUB_EAX_ macro imm
356 db 66h,2Dh
357 dd imm
358 endm
359
360SUB_EBX_ macro imm
361 db 66h,81h,0EBh
362 dd imm
363 endm
364
365SUB_ECX_ macro imm
366 db 66h,81h,0E9h
367 dd imm
368 endm
369
370SUB_EDX_ macro imm
371 db 66h,81h,0EAh
372 dd imm
373 endm
374
375CMP_EAX_ macro imm
376 db 66h,3Dh
377 dd imm
378 endm
379
380CMP_EBX_ macro imm
381 db 66h,81h,0FBh
382 dd imm
383 endm
384
385CMP_ECX_ macro imm
386 db 66h,81h,0F9h
387 dd imm
388 endm
389
390CMP_EDX_ macro imm
391 db 66h,81h,0FAh
392 dd imm
393 endm
394
395; *** New Segment Register/AX moves ***
396
397MOV_FS_AX macro
398 db 8Eh,0E0h
399 endm
400
401MOV_AX_FS macro
402 db 8Ch,0E0h
403 endm
404
405MOV_GS_AX macro
406 db 8Eh,0E8h
407 endm
408
409MOV_AX_GS macro
410 db 8Ch,0E8h
411 endm
412
413; *** New Segment Register pushes & pops ***
414
415PUSH_FS macro
416 db 0Fh,0A0h
417 endm
418
419PUSH_GS macro
420 db 0Fh,0A8h
421 endm
422
423POP_FS macro
424 db 0Fh,0A1h
425 endm
426
427POP_GS macro
428 db 0Fh,0A9h
429 endm
430
431; *** New Segment Register offset 16 memory moves ***
432
433MOV_off16_FS macro off16
434 db 8Ch,26h
435 dw off16
436 endm
437
438MOV_FS_off16 macro off16
439 db 8Eh,26h
440 dw off16
441 endm
442
443MOV_off16_GS macro off16
444 db 8Ch,2Eh
445 dw off16
446 endm
447
448MOV_GS_off16 macro off16
449 db 8Eh,2Eh
450 dw off16
451 endm
452
453; *** General Register 32 bit pushes & pops ***
454
455PUSH_EAX macro
456 db 66h
457 push ax
458 endm
459
460POP_EAX macro
461 db 66h
462 pop ax
463 endm
464
465PUSH_EBX macro
466 db 66h
467 push bx
468 endm
469
470POP_EBX macro
471 db 66h
472 pop bx
473 endm
474
475PUSH_ECX macro
476 db 66h
477 push cx
478 endm
479
480POP_ECX macro
481 db 66h
482 pop cx
483 endm
484
485PUSH_EDX macro
486 db 66h
487 push dx
488 endm
489
490POP_EDX macro
491 db 66h
492 pop dx
493 endm
494
495PUSH_EDI macro
496 db 66h
497 push di
498 endm
499
500POP_EDI macro
501 db 66h
502 pop di
503 endm
504
505PUSH_ESI macro
506 db 66h
507 push si
508 endm
509
510POP_ESI macro
511 db 66h
512 pop si
513 endm
514
515PUSH_EBP macro
516 db 66h
517 push bp
518 endm
519
520POP_EBP macro
521 db 66h
522 pop bp
523 endm
524
525PUSH_ESP macro
526 db 66h
527 push sp
528 endm
529
530POP_ESP macro
531 db 66h
532 pop sp
533 endm
534
535
536; *** General Register 32 bit xors ***
537
538XOR_EAX_EAX macro
539 db 66h
540 xor ax, ax
541 endm
542
543XOR_EBX_EBX macro
544 db 66h
545 xor bx, bx
546 endm
547
548XOR_ECX_ECX macro
549 db 66h
550 xor cx, cx
551 endm
552
553XOR_EDX_EDX macro
554 db 66h
555 xor dx, dx
556 endm
557
558XOR_EBP_EBP macro
559 db 66h
560 xor bp, bp
561 endm
562
563.list ; end of INSTR386.INC
diff --git a/v4.0/src/MEMM/MEMM/IOTRAP.ASM b/v4.0/src/MEMM/MEMM/IOTRAP.ASM
new file mode 100644
index 0000000..eb7d79c
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/IOTRAP.ASM
@@ -0,0 +1,165 @@
1
2
3 page 58,132
4;******************************************************************************
5 title IOTRAP.ASM - Dispatches I/O trap handlers
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: IOTRAP.ASM - Dispatches I/O trap handlers
13;
14; Version: 0.04
15;
16; Date: July 1, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 07/01/86 0.03 From ELIMTRAP.ASM
27; 07/03/86 0.03 Added handlers for 84,85,60, & 64
28; 07/06/86 0.04 Changed assume to DGROUP
29;
30;******************************************************************************
31;
32; Functional Description:
33;
34; This routine is called by all I/O space trap handlers to allow
35; emulation/monitoring of I/O address reads and writes. When a GP fault
36; occurs due to I/O to an address trapped in the I/O Bit Map, the I/O
37; instruction emulation routine in VMINST calls this routine. This
38; routine calls the appropriate I/O trap handler for the I/O address.
39;
40;******************************************************************************
41.lfcond ; list false conditionals
42.386p
43 page
44 page
45;******************************************************************************
46; P U B L I C D E C L A R A T I O N S
47;******************************************************************************
48;
49 public IO_Trap ; dispatches I/O trap handlers
50
51;******************************************************************************
52; L O C A L C O N S T A N T S
53;******************************************************************************
54;
55FALSE equ 0
56TRUE equ not FALSE
57
58 include VDMseg.inc
59 include VDMsel.inc
60
61;******************************************************************************
62; E X T E R N A L R E F E R E N C E S
63;******************************************************************************
64
65_TEXT segment
66
67extrn IOTrap_Tab:word ; System board IO trap routine address table
68extrn IOT_BadT:near ; Routine to execute for unknown port
69;extrn IOT_LIM:near ; Routine to handle LIM emulated ports
70extrn IOT_OEM:near ; Routine to handle OEM specific emulate ports
71
72_TEXT ends
73
74;******************************************************************************
75; S E G M E N T D E F I N I T I O N
76;******************************************************************************
77
78_TEXT segment
79 assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP
80
81;******************************************************************************
82; IO_Trap - Dispatches trap handler for an I/O address
83;
84; ENTRY: Protected Mode Ring 0
85; AL = byte to output to port.
86; DX = port address for I/O.
87; SS:BP = points to stack frame on entry to GP fault handler
88; BX = 0 => Emulate Input.
89; <>0 => Emulate Output.
90;
91; EXIT: Protected Mode Ring 0
92; AL = emulated input value from port.
93; CLC => I/O emulated by LIM_Trap.
94; STC => I/O NOT emulated by LIM_Trap.
95;
96; WARNING:***********
97; This routine is closely allied with IOTBadT which is in TrapDef.
98; IOTBadT assumes that the stack is in a certain state!
99; ***********
100;
101;
102; USED: Flags
103; STACK:
104;------------------------------------------------------------------------------
105IO_Trap proc near
106;
107 push ds
108 push dx
109
110 push VDMD_GSEL
111 pop ds ; set DS = DGROUP
112
113 cmp dx,0100h ;Q: I/O Addr < 0100h (system brd port)?
114 jae IOT_NotSys ; N: check mapping regs
115IOT_Sys: ; Y: dispatch I/O trap handler
116 xchg bx, dx ; BL = port address
117 shl bx,1 ; BX = BX*2 (word table)
118 call cs:IOTrap_Tab[bx] ; call handler
119 ; ENTRY: entry DX,DS on stack
120 ; DS = DGROUP selector
121 ; BX = 2 * port address in 0100h range
122 ; DX = input/output flag
123
124 xchg bx,dx ; reset bx
125 pop dx ;
126 pop ds ; reset dx
127 ret ; CF = 1 if I/O not emulated
128
129;
130; Address >= 0100h
131
132IOT_NotSys:
133;
134; check for OEM specific I/O emulation
135;
136 call IOT_OEM ;If emulated by OEM specific routine
137 ; does not return(returns from IO_Trap)
138; NOTE : we don't have LIM h/w port anymore
139;
140; check for LIM mapping register address
141;
142; call IOT_LIM ;If emulated by LIM emulation routine
143 ; does not return(returns from IO_Trap)
144
145;
146; Here if I/O Address >= 0100h and not a mapping register
147; map it into 1k and try system board ports again
148;
149 and dx,3FFh ; map address into 1k range
150 cmp dx,0100h ;Q: I/O Addr < 0100h (system brd port)?
151 jb IOT_Sys ; Y: check system ports
152 ; N: unknown port
153 xchg bx,dx ; put Input/Output flag in DX for IOT_BadT
154 shl bx,1
155 call IOT_BadT
156 jmp $ ;IOT_BadT pops return address off restores regs
157 ; and returns
158
159IO_Trap endp
160
161
162_TEXT ends
163
164 end
165 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/KBD.ASM b/v4.0/src/MEMM/MEMM/KBD.ASM
new file mode 100644
index 0000000..3616c1e
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/KBD.ASM
@@ -0,0 +1,1608 @@
1
2
3page 58,132
4;******************************************************************************
5 title KBD.ASM - - protected mode AT keyboard driver
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMMD.EXE - MICROSOFT Expanded Memory Manager 386 DEBUG Driver
11;
12; Module: KBD.ASM - - protected mode AT keyboard driver for debugger
13;
14; Version: 0.04
15;
16; Date: January 31, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 01/31/86 Original
27; A- Removed STIs and changed CLI/STIs to keep interrupt
28; status stable (OFF) during debugger execution. The
29; specific problem was in reporting unexpected traps
30; fielded from Virtual Mode during DOS execution,
31; e.g. timer ticks.
32; B- Fixed Ctrl-NumLock, Ctrl-Alt-Del, Ctrl-Break, and
33; Shift-PrtSc
34; 05/12/86 C Cleanup and segment reorganization
35; 06/28/86 0.02 Name changed from MEMM386 to MEMM
36; 07/05/86 0.04 Moved to DCODE segment
37;
38;******************************************************************************
39;
40; Functional Description:
41;
42; THIS CODE IS USED BY THE DEBUGGER ONLY !
43;
44; This is a PC/AT keyboard driver capable of running
45; in protected mode. It does not require any ROM support.
46;
47; The major modifications are:
48;
49; - Remove foreign tables, use US only
50; - Hard code machine type rather than looking in ROM
51; - hard code BeepFreq, BeepDur
52; - removed KeyVector, put read-only data in CS
53; - removed Accent stuff, which had code writes
54; - removed code writes in foreign kbd
55; - removed INT 15h sysreq and post
56; - removed T&SR stuff, added buffer read routine "getc"
57; - made it polled, removed all interrupt stuff
58; - changed "data" segment to "romdata"
59;
60;
61; SCCSID = @(#)keybxx.asm 4.1 85/10/09
62;------------------------------------------------------
63;
64; KEYBXX - foreign keyboard driver.
65;
66; April 1985 by Michael Hanson
67; Copyright 1985 by Microsoft Corporation
68;
69; KeybXX is a keyboard handling program using tables
70; supplied in a separate file to do foreign language
71; keyboard support. It is the basis for the KEYB??.EXE
72; programs which use this program and the corresponding
73; table defined in KEYB??.ASM.
74;
75; KeybXX.OBJ must be linked with one of the Keyb??.OBJ
76; programs to work, the KEYB?? file must be first.
77; See the accompanying makefile for examples.
78;
79; Note: KEYB?? refers to any of KEYBFR ( French ),
80; KEYBGR (German), KEYBUK (United Kingdom),
81; KEYBIT (Italian), KEYBSP (Spanish) and
82; KEYBDV (Dvorak). These are the currently
83; defined data tables for KEYBXX.
84;
85; Compatability notes:
86; 1. The IBM foreign keyboard drivers don't return
87; anything for a CTRL-ALT space. This is not
88; what I expect from the manuals, but for
89; compatibility, KEYBXX doesn't return anything
90; in this case either.
91;
92; 2. For the AT the keyboard driver should do a post
93; call (int 15). The ROM keyboard driver does, but
94; IBM's foreign keyboard drivers appear not to.
95; Currently KEYBXX does a post code, though only
96; one is issued at any one time (that is, only 1 post
97; call for the 2 characters returned by an illegal
98; accent combination).
99;
100; This program is a modified version of the keyboard handler from -
101;
102; Microsoft Mach 10 Enhancement Software
103;
104; Copyright 1984 by Microsoft Corporation
105; Written June 1984 by Chris Peters
106;
107;******************************************************************************
108.lfcond ; list false conditionals
109.386p
110
111include VDMseg.inc
112include desc.inc
113include kbd.inc
114
115
116MASTER_IMR equ 21h ; mask port for master 8259
117
118;*** ROM BIOS data area, set up addresses
119romdata segment use16 at 40h
120 org 17h
121KeyState db ?
122BreakState db ?
123AltKey db ?
124KbHead dw ?
125KbTail dw ?
126KbBuffer dw 16 dup (?)
127KbBufferEnd label word
128
129 org 49h
130VidMode db ?
131 org 65h
132VidReg db ?
133
134 org 71h
135fBreak db ?
136fReset dw ?
137
138 org 80h
139KbStart dw ?
140KbEnd dw ?
141
142 org 97h
143ATKbFlags db ?
144romdata ends
145
146
147
148;*** Routines used by data table modules (Keyb??)
149public SpecKey
150public AlphaKey
151public NormalKey
152public Keys$2$13
153public CapKey
154public Cap$2$13
155public FuncKey
156public PadKey
157public NumKey
158public SpaceKey
159public ShiftKey
160public ScrollKey
161public StateKey
162;public AccKey
163public AltShiftKey
164public BufferFull
165public ReBoot
166public XBoot
167public PrintScreen
168public SysReq
169
170
171
172
173DCODE segment
174 assume cs:DCODE,ds:romdata,es:nothing
175
176
177;*** Tables for foreign language key layout
178; See Keyb?? files for more details
179
180
181;* Actual foreign language key layout
182; extrn ForeignTable :word
183
184
185;* Tables to map CNTRL ALT char
186; extrn AltChrs :byte
187AltChrs label byte
188; extrn AltChrsEnd :byte
189AltChrsEnd label byte
190
191; extrn AltMap :byte
192AltMap label byte
193
194
195;* Tables to map accented characters
196; extrn AccentChTbl :word
197AccentChTbl label word
198
199; extrn AccentMpTbl :word
200AccentMpTbl label word
201
202
203;* Table of accent characters, shifted, ALTed and CTRLed.
204; defined using the AccChStruc struct
205; extrn AccChTbl :word
206AccChTbl label word
207
208
209
210;*** Internal variables used by KEYBXX interrupt handler
211; KeyVector dd ? ; origin of keyboard decode table
212;PCType db ? ; type of PC running on
213PCType db 0fch ; type of PC running on
214
215PC_AT = 0FCh ;if anything else, assume PC/XT
216
217;Accent db 0 ; set for accent key, =0 for none.
218;AccentKey dw ? ; last accent key pressed
219
220; BeepFreq dw PCBeepFreq ;Count for beep half-cycle
221BeepFreq dw ATBeepFreq ;Count for beep half-cycle
222; BeepDur dw PCBeepDur ;Count of half-cycles to beep
223BeepDur dw ATBeepDur ;Count of half-cycles to beep
224
225
226;*** Normal keyboard table, used in CTRL-ALT F1 mode
227;
228; See Keyb?? files for structure information.
229;
230ForeignTable label word
231KeyMapTable label word
232 public KeyMapTable
233
234 db 0,0 ;0
235 dw BufferFull
236 db esc,esc ;1
237 dw SpecKey
238 db "1","!" ;2
239 dw Keys$2$13
240 db "2","@" ;3
241 dw Keys$2$13
242 db "3","#" ;4
243 dw Keys$2$13
244 db "4","$" ;5
245 dw Keys$2$13
246 db "5","%" ;6
247 dw Keys$2$13
248 db "6","^" ;7
249 dw Keys$2$13
250 db "7","&" ;8
251 dw Keys$2$13
252 db "8","*" ;9
253 dw Keys$2$13
254 db "9","(" ;10
255 dw Keys$2$13
256 db "0",")" ;11
257 dw Keys$2$13
258 db "-","_" ;12
259 dw Keys$2$13
260 db "=","+" ;13
261 dw Keys$2$13
262 db 8,127 ;14
263 dw SpecKey
264 db 9,0 ;15
265 dw NormalKey
266 db "q","Q" ;16
267 dw AlphaKey
268 db "w","W" ;17
269 dw AlphaKey
270 db "e","E" ;18
271 dw AlphaKey
272 db "r","R" ;19
273 dw AlphaKey
274 db "t","T" ;20
275 dw AlphaKey
276 db "y","Y" ;21
277 dw AlphaKey
278 db "u","U" ;22
279 dw AlphaKey
280 db "i","I" ;23
281 dw AlphaKey
282 db "o","O" ;24
283 dw AlphaKey
284 db "p","P" ;25
285 dw AlphaKey
286 db "[","{" ;26
287 dw NormalKey
288 db "]","}" ;27
289 dw NormalKey
290 db 13,10 ;28
291 dw SpecKey
292 db CtrlShift,(255-CtrlShift)
293 dw ShiftKey
294 db "a","A" ;30
295 dw AlphaKey
296 db "s","S" ;31
297 dw AlphaKey
298 db "d","D" ;32
299 dw AlphaKey
300 db "f","F" ;33
301 dw AlphaKey
302 db "g","G" ;34
303 dw AlphaKey
304 db "h","H" ;35
305 dw AlphaKey
306 db "j","J" ;36
307 dw AlphaKey
308 db "k","K" ;37
309 dw AlphaKey
310 db "l","L" ;38
311 dw AlphaKey
312 db ";",":" ;39
313 dw NormalKey
314 db "'",'"' ;40
315 dw NormalKey
316 db "`","~" ;41
317 dw NormalKey
318 db LeftShift,(255-LeftShift)
319 dw ShiftKey
320 db "\","|" ;43
321 dw NormalKey
322 db "z","Z" ;44
323 dw AlphaKey
324 db "x","X" ;45
325 dw AlphaKey
326 db "c","C" ;46
327 dw AlphaKey
328 db "v","V" ;47
329 dw AlphaKey
330 db "b","B" ;48
331 dw AlphaKey
332 db "n","N" ;49
333 dw AlphaKey
334 db "m","M" ;50
335 dw AlphaKey
336 db ",","<" ;51
337 dw NormalKey
338 db ".",">" ;52
339 dw NormalKey
340 db "/","?" ;53
341 dw NormalKey
342 db RightShift,(255-RightShift)
343 dw ShiftKey
344 db "*",114 ;55
345 dw PrintScreen
346 db AltShift,(255-AltShift) ;56
347 dw AltShiftKey
348 db " "," " ;57
349 dw SpaceKey
350 db CapsState,(255-CapsState)
351 dw StateKey
352 db 1,1 ;59
353 dw FuncKey
354 db 2,2 ;60
355 dw FuncKey
356 db 3,3 ;61
357 dw FuncKey
358 db 4,4 ;62
359 dw FuncKey
360 db 5,5 ;63
361 dw FuncKey
362 db 6,6 ;64
363 dw FuncKey
364 db 7,7 ;65
365 dw FuncKey
366 db 8,8 ;66
367 dw FuncKey
368 db 9,9 ;67
369 dw FuncKey
370 db 0,0 ;68
371 dw FuncKey
372 db NumState,(255-NumState) ;69
373 dw NumKey
374 db ScrollState,(255-ScrollState)
375 dw ScrollKey
376 db 0,"7" ;71
377 dw PadKey
378 db 1,"8" ;72
379 dw PadKey
380 db 2,"9" ;73
381 dw PadKey
382 db 3,"-" ;74
383 dw PadKey
384 db 4,"4" ;75
385 dw PadKey
386 db 5,"5" ;76
387 dw PadKey
388 db 6,"6" ;77
389 dw PadKey
390 db 7,"+" ;78
391 dw PadKey
392 db 8,"1" ;79
393 dw PadKey
394 db 9,"2" ;80
395 dw PadKey
396 db 10,"3" ;81
397 dw PadKey
398 db 11,"0" ;82
399 dw PadKey
400 db 12,"." ;83
401 dw ReBoot
402 db 0, 0 ;84 (On AT only)
403 dw SysReq
404
405
406
407;*** Tables for keypad with ALT and control
408; Same for foreign as normal
409AltKeyPad label byte
410 db 7,8,9,-1
411 db 4,5,6,-1
412 db 1,2,3
413 db 0,-1
414
415CtrlKeyPad label byte
416 db 119,-1,132,-1
417 db 115,-1,116,-1
418 db 117,-1,118
419 db -1,-1
420
421
422
423;*** Table for ALT alphabetical character
424;
425; Since uses alpha char as index, this is the same
426; for normal and foreign keyboards.
427;
428AltTable label byte
429; a, b, c, d, e, f, g, h, i, j, k, l, m
430 db 30,48,46,32,18,33,34,35,23,36,37,38,50
431; n, o, p, q, r, s, t, u, v, w, x, y, z
432 db 49,24,25,16,19,31,20,22,47,17,45,21,44
433
434
435
436 SUBTTL Keyboard Interrupt Handler
437
438
439;*** Keyboard interrupt handler
440;
441handler proc near
442
443KbInt:
444;* sti
445 cld
446 push ax
447 push bx
448 push cx
449 push dx
450 push si
451 push di
452 push ds
453 push es
454
455; First see if there is any data in the kbd buffer.
456; Return to caller if not.
457
458 in al, KbStatus
459 test al, 1
460 jnz intr1
461 jmp RestoreRegs
462intr1:
463
464 mov ax,romdata
465 mov ds,ax
466 call GetSCode ;Get scan code from keyboard in al
467 mov ah,al ;(ah) = scan code
468 cmp al,-1
469 jnz KbI1
470 jmp BufferFull ;go handle overrun code
471KbI1:
472 mov bx,ax
473 and bx,7fh ;(bl) = scan code without break bit
474 cmp bl,84
475 jle KBI2
476 jmp KeyRet ;ignore code if not in range
477KBI2:
478 shl bx,1 ;index into lookup table
479 shl bx,1
480;* Check for CTRL-ALT chars
481 test ah, 80h ;no CTRL-ALT remap on break code
482 jnz KbI23
483; cmp word ptr [KeyVector],offset KeyMapTable
484; je KbI23 ;Not foreign keyboard
485 jmp KbI23
486 test [KeyState], CtrlShift
487 jz KbI23
488 test [KeyState], AltShift
489 jz KbI23
490 push ax ; save scan code
491
492;* map CTRL-ALT char
493; look up chars in table, if found then put out corresponding
494; entry from map table.
495 mov si, offset AltChrs - 1 ;Set up index to lookup
496KbI21:
497 inc si ; Advance to next entry
498 cmp si, offset AltChrsEnd
499 jae KbI22 ;at end of table, so no remap
500 cmp ah, cs:[si]
501 jne KbI21 ;this isn't it so loop
502; Found character, so do the mapping
503 sub si, offset AltChrs
504 add si, offset AltMap ;get index into remaped table
505 pop ax ;get scan code
506 mov al, cs:[si] ;get new character to use
507 jmp PutKRet
508KbI22:
509 pop ax
510KbI23:
511
512; les si,[KeyVector]
513 mov si, offset KeyMapTable
514 mov cx,cs:[si+bx] ;(cx) = lc, uc bytes
515 mov al,cl ;(al) = lc code for key
516 mov dl,[KeyState] ;(dl) = keyboard flags
517 jmp word ptr cs:[si+bx+2] ;Call appropriate key handler
518;***
519; for all key handler routines,
520;
521; (CX) = uc, lc code bytes from table
522; (DL) = keyboard flags byte (see equates above for bits)
523; (AL) = lc code from cl
524; (AH) = scan code from keyboard
525
526handler endp
527
528
529 SUBTTL Key Routines
530
531;*** Key handling routines, called as specified by the key table
532
533;------------------------------------------------------
534;
535; Alphabetical key, caps lock works as do CTRL and ALT
536;
537AlphaKey:
538 call NoBreak
539 test dl,AltShift
540 jz ak1
541 cbw
542 add bx,ax
543 mov ah,[AltTable+bx-"a"]
544 jmp MakeAlt
545
546ak1: test dl,CtrlShift
547 jz ak2
548 sub al,"a"-1
549 jmp PutKRet
550
551ak2: xor bh,bh
552 test dl,RightShift+LeftShift
553 jz ak3
554 or bh,CapsState
555ak3: mov cl,dl
556 and cl,CapsState
557 xor bh,cl
558 jz ak4
559 mov al,ch
560ak4: jmp PutKRet
561
562
563;------------------------------------------------------
564;
565; Keys that do something different when CTRL is down
566;
567SpecKey:
568 call NoAlt
569 test dl,CtrlShift
570 jz bsp1
571 mov al,ch
572bsp1: jmp PutKRet
573
574
575;-----------------------------------------------------
576;
577; Normal, Non Alphabetic key
578;
579NormalKey: ;These return nothing on ALT
580 call NoAlt
581 test dl,CtrlShift
582 jz nk0
583 jmp short Ca20 ;ky21
584
585Keys$2$13: ;Keys #2 - 13 have ALT codes 120,...
586 call NoBreak
587 test dl,AltShift
588 jz Ky2
589 add ah,120-2
590 jmp MakeAlt
591
592ky2: test dl,CtrlShift
593 jnz Ca20 ;handle CTRL key same as for CapKey
594nk0:
595 test dl,RightShift+LeftShift
596 jz nk1
597 mov al,ch
598nk1: jmp PutKRet
599
600
601;-----------------------------------------------------
602;
603; Non Alphabetic key for which cap lock works
604;
605CapKey: ; CAPLOCK works, ALT doesn't
606 call NoAlt
607 test dl,CtrlShift
608 jz ca5
609 jmp short ca20 ;ca3
610
611Cap$2$13: ; KEYS 2-13 with CAPLOCK working
612 call NoBreak
613 test dl,AltShift
614 jz ca2
615 add ah,120-2
616 jmp MakeAlt
617
618ca2: test dl,CtrlShift
619 jz ca5
620ca20: cmp ah, 3 ;Keep CTRL keys at same scan code locations
621 jnz ca21
622 jmp MakeAlt
623ca21: cmp ah, 7
624 jnz ca22
625 mov al, 30
626 jmp short ca7
627ca22: cmp ah, 26
628 jnz ca23
629 mov al, 27
630 jmp short ca7
631ca23: cmp ah, 27
632 jnz ca24
633 mov al, 29
634 jmp short ca7
635ca24:
636 cmp ah, 43
637 jnz ca25
638 mov al, 28
639 jmp short ca7
640ca25: cmp al, '-' ;Except for - key, which moves around.
641 jnz ca26
642 mov al, 31
643 jmp short ca7
644ca26: jmp KeyRet
645
646
647ca5: xor bh,bh
648 test dl,RightShift+LeftShift
649 jz ca6
650 or bh,CapsState
651ca6: mov cl,dl
652 and cl,CapsState
653 xor bh,cl
654 jz ca7
655 mov al,ch
656ca7: jmp PutKRet
657
658
659;---------------------------------------------------
660;
661; Scroll Lock, Caps Lock, Num Lock
662;
663ScrollKey:
664 test ah,80h
665 jnz stk0
666 test dl,CtrlShift
667 jz stk1
668 mov ax,[KbStart]
669 mov [KbHead],ax
670 mov [KbTail],ax
671 mov [fBreak],80h
672 call EnableKB
673;*a int 1bh
674;*a xor ax,ax
675 mov ax,0003 ;*a simulate ^C
676 jmp PutKRet
677
678NumKey: ; NUM LOCK key
679 test ah,80h
680 jnz stk0
681 test dl,CtrlShift
682 jz stk1
683 or [BreakState],HoldState ; CTRL NUMLOCK
684 call VideoOn
685nlk1:
686 call handler ;*a (look for key since no interrupts)
687 test [BreakState],HoldState ; Wait for a key press
688 jnz nlk1
689 jmp RestoreRegs
690
691StateKey: ; Toggle key
692 test ah,80h
693 jz stk1
694stk0: and [BreakState],ch ; Indicate key no longer held down
695 jmp short shf4
696
697stk1: mov ah,al
698 and al,[BreakState]
699 jnz shf4 ; Ignore if key already down
700 or [BreakState],ah ; Indicate key held down
701 xor dl,ah ; Toggle bit for this key
702 jmp short shf3 ; And go store it.
703
704
705;---------------------------------------------------
706;
707; Alt Shift
708;
709AltShiftKey:
710 test ah,80h
711 jz shf2 ; Indicate that ALT key down
712 xor al,al
713 xchg al,[AltKey] ; Find numeric code entered
714 or al,al
715 jz shf1 ; Just reset indicator if none
716 and [KeyState],ch
717 xor ah,ah ; Make it a key with 0 scan code
718 jmp PutKRet
719
720;----------------------------------------------------
721;
722; Shift, Ctrl
723;
724ShiftKey:
725 test ah,80h
726 jz shf2
727shf1: and dl,ch ; Unset indicator bit for break code
728 jmp short shf3
729shf2: or dl,al ; Set indicator bit for make code
730shf3: mov [KeyState],dl
731shf4: jmp KeyRet
732
733
734;----------------------------------------------------
735;
736; Reboot System?
737;
738ReBoot: call NoBreak ; Del key pressed, check CTRL ALT DEL
739 test dl,AltShift
740 jz pdk2
741 test dl,CtrlShift
742 jz pdkx
743XBoot: ; Reboot system.
744 mov ax,romdata ; ds = romdata segment
745 mov ds,ax
746 mov [fReset],1234h
747;*a
748;*a 02/12/86 - use shutdown code 10 and [40:67] to return to real mode
749;*a and enter the ROM at the CTRL-ALT-DEL entry point
750;*a
751 cli ; make sure
752 mov al,0Fh or 80h ; shutdown byte address/disable NMI
753 out 70h,al ; write CMOS address
754 jmp short $+2 ; (delay)
755 mov al,0Ah ; Shutdown code 10 = jump [dword @40:67]
756 out 71h,al ; write shutdown code to shutdown byte
757;
758; Set up entry point after the reset
759;
760 mov ds:[67h],0EA81h ; offset of CTRL-ALT-DEL entry point
761 mov ds:[67h+2],0F000h ; segment of CTRL-ALT-DEL entry point
762;
763; Reset the CPU
764;
765 mov al,0FEh ; FEh = pulse output bit 0 (286 reset)
766 out 64h,al ; command to 8042
767 hlt ; don't want to coast
768;*a
769;*a end inserted code
770;*a
771;*a mov ax,-1
772;*a push ax
773;*a xor ax,ax
774;*a push ax
775;*a xxx proc far
776;*a ret ; To reboot system, do a far return to FFFFh:0
777;*a xxx endp
778
779
780;----------------------------------------------------
781;
782; Key Pad Key
783;
784PadKey:
785 mov bl,[AltKey]
786 call NoBreak2
787 test dl,AltShift
788 jz pdk2 ; Not entering a character number
789 xor bx,bx
790 mov bl,cl
791 mov cl,cs:AltKeyPad[bx] ; Get numeric value for this key
792 cmp cl,-1
793 jz pdk0 ; Start over if non-digit key
794 mov al,10
795 mul [AltKey]
796 add al,cl
797 jmp short pdk1
798pdk0: xor ax,ax
799pdk1: mov [AltKey],al
800pdkx: jmp KeyRet
801
802pdk2: mov al,0
803 test dl,CtrlShift
804 jz pdk3
805 xor bx,bx ; Lookup CTRL keypad key code
806 mov bl,cl
807 mov ah,cs:CtrlKeyPad[bx]
808 jmp short pdk6
809pdk3: cmp ah,74 ; - key independent of shift state
810 jz pdk41
811 cmp ah,78 ; + key independent of shift state
812 jz pdk41
813 xor bx,bx
814 test dl,RightShift+LeftShift
815 jz pdk4
816 or bh,NumState
817pdk4: mov cl,dl
818 and cl,NumState
819 xor bh,cl
820 jz pdk5
821pdk41: mov al,ch ; use char2 if shifted or in numlock
822pdk5: or al,al
823 jnz pdk7
824pdk6: cmp ah,-1
825 jz pdk8 ; Ignore CTRL with keypad 2, etc.
826 cmp ah,76
827 jz pdk8
828pdk7: jmp PutKRet
829pdk8: jmp KeyRet
830
831
832;----------------------------------------------------
833;
834; Function Key
835;
836FuncKey:
837 call NoBreak
838 test dl,AltShift+CtrlShift+LeftShift+RightShift
839 jz fk1 ; Normal function key
840 add ah,84-59
841 test dl,AltShift+CtrlShift
842 jz fk1 ; Shifted function key
843 add ah,10
844 test dl,AltShift
845 jz fk1 ; Just CTRL function key
846 add ah,10
847 test dl,CtrlShift
848 jz fk1 ; Just ALT function key
849 mov bx,offset KeyMapTable
850 cmp ah,104 ; CTRL ALT f1 to use normal keyboard
851 jz fk01
852 cmp ah,105 ; CTRL ALT f2 for foreign keyboard
853 jnz fk1 ; if not F1 or F2 then treat as ALT
854 mov bx,offset ForeignTable
855fk01:
856 cli ; Change translation table used
857; mov word ptr [KeyVector],bx
858; mov word ptr [KeyVector+2],cs
859 jmp KeyRet
860
861fk1: jmp MakeAlt
862
863
864;--------------------------------------------------------------------
865;
866; Print Screen Key
867;
868PrintScreen:
869 call NoAlt
870 test dl,CtrlShift
871 jz ps1
872 mov ah,ch
873 jmp fk1
874ps1: test dl,LeftShift+RightShift
875 jz pdk7
876 call VideoOn ;CTRL PrtSc - enable video and do Print Screen
877;*a int 5
878 jmp RestoreRegs
879
880
881;--------------------------------------------------------------------
882;
883; Space Key
884;
885SpaceKey:
886 call NoBreak
887 test dl, CtrlShift
888 jz sp1
889 test dl, AltShift
890 jz sp1
891 jmp KeyRet ; Don't return anything on CTRL-ALT space
892sp1:
893 jmp PutKRet
894
895
896;--------------------------------------------------------------------
897;
898; An accent key
899;
900; Each accent key is assumed to be accent both non-shifted
901; and shifted, and the accent number for the shifted should
902; be the next one up from the unshifted accent number.
903;
904;AccKey:
905; call NoBreak
906; cbw ;convert accent number to an index
907; mov bx, ax
908; dec bx
909; shl bx,1
910; shl bx,1 ;index to table of AccChStruc's
911; test dl, altshift
912; jz acc2 ;ALT not down
913; mov ax, [AccChTbl+bx].alt
914; jmp short acc5
915;acc2:
916; test dl, ctrlshift
917; jz acc3 ;just a normal or shifted keypress
918; mov ax, [AccChTbl+bx].ctrl
919; jmp short acc5
920;acc3:
921; test dl, leftshift+rightshift
922; jz acc4 ; not shifted (caps lock not used)
923; mov Accent,ch ; Get shifted accent number
924; mov ax, [AccChTbl+bx].shift
925; mov AccentKey, ax ; Save key and scn code next key int
926; jmp KeyRet
927;acc4:
928; mov Accent, al
929; mov ax, [AccChTbl+bx].normal
930; mov AccentKey, ax
931; jmp KeyRet
932;acc5:
933; jmp PutKRet
934;
935
936
937;--------------------------------------------------------------------
938;
939; System Request Key
940;
941SysReq:
942 test ah, 80h
943 jnz sys2 ;this is break code
944 test BreakState, SysShift
945 jz sys1
946 jmp KeyRet ;Ignore if SysReq already down
947
948sys1:
949 or BreakState, SysShift ;set held down flag
950 mov ax, 08500h
951 jmp short sys3
952sys2:
953 and BreakState, Not SysShift ;turn off held down flag
954 mov ax, 08501h
955sys3:
956 push ax ; Save SysReq action number
957 mov al,20h ; EOI to control port
958; out 20h,al
959 call EnableKB
960 pop ax
961; int 15h ; Indicate SysReq to BIOS
962 jmp RestoreRegs
963
964
965
966
967;*** Finish up processing of interrupt
968;
969
970;* Make this an ALT seq by removing chr code (ret scan code, 0)
971MakeAlt:mov al,0
972
973;* Put Key in buffer and return
974PutKRet:
975; cmp Accent, 0 ; check for accented char
976; je puk3 ;no accent pressed, just put out key
977; mov bl, Accent
978; dec bl ;make accent no an index
979; xor bh,bh
980; mov Accent, bh ;Accent only this character
981; shl bx,1 ;index into word table
982; mov si, AccentChTbl[bx] ;Get pointer to string for this accent
983; dec si ;Negate effect of initial inc in loop
984;puk1:
985; inc si
986; cmp al,cs:[si]
987; jz puk2 ;This is an accentable char - so remap
988; cmp byte ptr cs:[si], 0
989; jnz puk1 ;not done yet
990;
991;;* The character is not in this list, so do a beep and put
992;; out booth accent char and this char
993; call ErrBeep
994; mov bx,ax
995; mov ax,AccentKey ;Put out accent
996; call PutKey
997; mov ax,bx
998; cmp al, ' '
999; je puk4 ;Char is space, just beep and put out accent.
1000; jmp short puk3 ;Put out the character
1001;
1002;puk2:
1003; xor ah, ah ;Zero scan code for accented chrs
1004; cmp al, 0 ;for accented ALT chr put out 0, don't beep
1005; je puk3
1006; sub si, AccentChTbl[bx] ; Make index to map table
1007; add si, AccentMpTbl[bx]
1008; mov al, cs:[si] ; Get remapped char
1009puk3:
1010 call PutKey
1011puk4:
1012 cmp [PCType],PC_AT
1013 jnz KeyRet ; just return for non-AT
1014 cli
1015 mov al,20h ; EOI to control port
1016; out 20h,al
1017 call EnableKB
1018; mov ax, 09102h ; Send a post code
1019; int 15h
1020 jmp RestoreRegs
1021
1022
1023
1024;* Common validity check routines (Check for ALT, ignore break codes)
1025;
1026
1027NoAlt: test dl,AltShift ; Don't allow ALT with this key
1028 jnz IgB1
1029NoBreak: ; Ignore break code for this key
1030 mov bl,0
1031NoBreak2:
1032 test ah,80h
1033 jnz IgB1
1034 test [BreakState],HoldState ; in hold state?
1035 jz IgB0 ; no...
1036 and [BreakState],(255-HoldState)
1037 jmp short IgB1
1038IgB0: mov [AltKey],bl
1039 ret
1040IgB1: pop ax ; pop off return address
1041 jmp short KeyRet
1042
1043
1044;* buffer is full, beep the speaker and return from interrupt
1045BufferFull:
1046 cli
1047 mov al,20h
1048; out 20h,al
1049 call ErrBeep
1050 jmp short KeyRet1
1051
1052
1053;* Normal return from interrupt, handle EOI and enable KB
1054KeyRet:
1055 cli
1056 mov al,20h
1057; out 20h,al
1058KeyRet1:
1059 call EnableKB
1060RestoreRegs:
1061 cli
1062 pop es
1063 pop ds
1064 pop di
1065 pop si
1066 pop dx
1067 pop cx
1068 pop bx
1069 pop ax
1070ppp proc near
1071 ret
1072ppp endp
1073; iret
1074
1075
1076 SUBTTL Subroutines
1077
1078
1079
1080
1081;*** VideoOn - enable keyboard and video
1082;
1083; ENTRY: Nothing
1084;
1085; EXIT: (dx), (al) destroyed.
1086;
1087VideoOn proc near
1088 mov al,20h ; EOI to control port
1089; out 20h,al
1090 call EnableKB ; Enable AT keyboard
1091 cmp [VidMode],7
1092 jz vdo1 ; Do nothing for monochrome monitor
1093 mov al,[VidReg]
1094 mov dx,3d8h
1095 out dx,al ; Enable video controller
1096vdo1: ret
1097VideoOn endp
1098
1099
1100
1101
1102;*** EnableKB - Enable the keyboard interface on an AT, no effect on PC/XT.
1103;
1104; ENTRY: Nothing
1105;
1106; EXIT: (al) destroyed
1107;
1108; EFFECTS: Enables the Keyboard interface.
1109;
1110EnableKB proc near
1111 cmp [PCType], PC_AT
1112 jne ena1 ;for non-AT simply ignore
1113 pushf ;* save interrupt status
1114 cli
1115 call WaitStatus
1116 mov al,0AEh ;output enable keyboard command
1117 out KbStatus,al
1118 popf ;* restore original interrupt status
1119;* sti
1120ena1:
1121 ret
1122EnableKB endp
1123
1124
1125
1126
1127;*** DisableKB - Disable the keyboard interface on an AT, no effect on PC/XT
1128;
1129; ENTRY: Nothing
1130;
1131; EXIT: (al) destroyed
1132;
1133; EFFECTS: Disables the Keyboard interface.
1134;
1135DisableKB proc near
1136 cmp [PCType], PC_AT
1137 jne dis1 ; Ignore if not an AT
1138 pushf ;* save interrupt status
1139 cli
1140 call WaitStatus
1141 mov al,0ADh ;output disable command
1142 out KBStatus, al
1143 popf ;* restore original interrupt status
1144;* sti
1145dis1:
1146 ret
1147DisableKB endp
1148
1149
1150
1151
1152;*** ErrBeep - beep the speaker
1153;
1154; ENTRY: Nothing
1155;
1156; EXIT: Nothing
1157;
1158; USES: (ax) - to access I/O port
1159; (bx) - length of beep in cycles
1160; (cx) - counter for cycle length
1161;
1162; EFFECTS: Speaker is beeped
1163;
1164; WARNING: Uses in/out to keyboard port to beep speaker directly.
1165;
1166ErrBeep proc near
1167 push ax
1168 push bx
1169 push cx
1170 mov bx,BeepDur ; count of speaker cycles
1171 in al,KbCtl
1172 push ax
1173 and al,0fch ; turn off bits 0 and 1 (speaker off)
1174bee1: xor al,2 ; toggle speaker bit
1175 out KbCtl,al
1176 mov cx,BeepFreq
1177bee2: loop bee2 ; wait for half cycle
1178 dec bx
1179 jnz bee1 ; keep cycling speaker
1180 pop ax ; restore speaker/keyboard port value
1181 out KbCtl,al
1182 pop cx
1183 pop bx
1184 pop ax
1185 ret
1186ErrBeep endp
1187
1188
1189
1190
1191;*** PutKey - put key in the buffer
1192;
1193; ENTRY: (ax) = key code and scn code to go in buffer
1194;
1195; EXIT: (si), (di) destroyed.
1196; ints disabled.
1197;
1198; EFFECTS: KbTail updated
1199; (ax) put in buffer at end.
1200; On AT - do post call.
1201;
1202; If it isn't possible to put key in buffer (full) then beep
1203; and ignore.
1204; If (ax) = -1 then the key is not put in buffer.
1205;
1206PutKey proc near
1207 cmp ax, -1 ; Code to ignore a key
1208 jz put2
1209 cli ; Make sure only ones using buffer now
1210 mov si,[KbTail]
1211 mov di,si ; Get old buffer end and save it
1212 inc si ; Advance pointer
1213 inc si
1214 cmp si,[KbEnd]
1215 jb put01
1216 mov si,[KbStart] ; Wrap to beginning if at end
1217put01:
1218 cmp si,[KbHead]
1219 jnz put1 ; Buffer not Full
1220 pop ax ; Drop return address
1221 jmp BufferFull ; Go beep and return from interrupt
1222
1223put1:
1224 mov [di],ax ; Put key in buffer at end
1225 mov [KbTail],si
1226put2:
1227 ret
1228PutKey endp
1229
1230
1231
1232
1233;*** GetSCode - read the scan code from the keyboard
1234;
1235; ENTRY: nothing
1236;
1237; EXIT: (al) = key scan code from keyboard
1238; (ah) destroyed
1239;
1240; USES: PCType - to use PC/AT sequence, for AT - handles LEDs
1241;
1242GetSCode proc near
1243 cmp [PCType], PC_AT
1244 je gsc1 ;handle AT differently
1245 in al,KbData ;get key code
1246 xchg bx,ax ;save scan code
1247 in al,KbCtl ;acknowledge to keyboard
1248 mov ah,al
1249 or al,80h
1250 out KbCtl,al
1251 xchg ah,al
1252 out KbCtl,al
1253 xchg ax,bx ;(al) = scan code
1254 ret
1255
1256gsc1: ;have to do handshake
1257 call DisableKB
1258 pushf ;* save interrupt status
1259 cli
1260 call WaitStatus
1261 in al,KbData ;read in character
1262 popf ;* restore original interrupt status
1263;* sti
1264
1265; check for and flag control bytes from keyboard
1266 cmp al,ATResend
1267 jne gsc2 ;it isn't a resend
1268 cli
1269 or [ATKbFlags], KbResend
1270 pop bx ;throw away return address
1271 jmp KeyRet ;and don't do anything more with key
1272
1273gsc2:
1274 cmp al,ATAck
1275 jne gsc3 ;it isn't an ack
1276 cli
1277 or [ATKbFlags], KBAck
1278 pop bx ;throw away return address
1279 jmp KeyRet ;and don't do anything more with key
1280
1281gsc3:
1282 call UpdateLeds ;update AT's leds
1283 ret
1284GetSCode endp
1285
1286
1287
1288;*** Don't need to keep code after here when not running on an AT
1289xt_endcode:
1290
1291
1292
1293;*** UpdateLeds - update the leds on the AT keyboard
1294;
1295; ENTRY: Nothing
1296;
1297; EXIT: All regs preserved
1298;
1299; EFFECTS: Sets the keyboard LEDs according to the status byte.
1300;
1301; WARNING: Assumes it is operating on an AT, must not be called for a PC.
1302;
1303UpdateLeds proc near
1304 pushf ;* save interrupt status
1305 push ax
1306 cli
1307 mov ah, KeyState ; get the toggle key states
1308 and ah, CapsState + NumState + ScrollState
1309 rol ah, 1
1310 rol ah, 1
1311 rol ah, 1
1312 rol ah, 1 ; in format for ATKbFlags
1313 mov al, ATKbFlags
1314 and al, 07h
1315 cmp ah, al
1316 jz Updn1 ; No change in leds, so don't update
1317 test ATKbFlags, KBSndLed
1318 jnz Updn1 ; Already updating, so don't update
1319 or ATKbFlags, KBSndLed
1320 mov al, 20h
1321; out 20h, al ; send EOI
1322 mov al, 0EDh ; Set indicators command
1323 call SendByte
1324 test ATKbFlags, KBErr
1325 jnz Updn2
1326 mov al, ah ; Send indicator values
1327 call SendByte
1328 test ATKbFlags, KBErr
1329 jnz Updn2
1330 and ATKbFlags, 0F8h
1331 or ATKbFlags, ah ; Record indicators
1332Updn2:
1333 and ATKbFlags, Not (KBSndLed + KBErr)
1334Updn1:
1335 pop ax
1336 popf ;* restore original interrupt status
1337;* sti
1338 ret
1339UpdateLeds endp
1340
1341
1342
1343
1344;*** SendByte - send a byte to the keyboard
1345;
1346; ENTRY: (al) - command/data to send
1347;
1348; EXIT: BreakState flags set according to success of operation.
1349; Ints disabled on completion.
1350;
1351; USES: (al) - byte to send.
1352; (ah) - count of retries.
1353; (cx) - time out counter on wait for response.
1354;
1355; Send the byte in al to the AT keyboard controller, and
1356; do handshaking to make sure they get there OK.
1357; Must not be called for the PC.
1358;
1359SendByte proc near
1360 push ax
1361 push cx
1362 mov ah, 03 ; Set up count of retries
1363Sen1:
1364 pushf ;* save interrupt status
1365 cli
1366 and ATKbFlags, Not (KBResend + KBAck + KBErr)
1367 push ax ; save byte to send
1368 call WaitStatus ; Wait for keyboard ready
1369 pop ax
1370 out KbData, al ; Send byte to keyboard
1371 popf ;* restore original interrupt status
1372;* sti
1373 mov cx,2000h ; Time out length, Approximate value for AT ROM
1374Sen2: ; Wait for ACK
1375 call handler ;*a (look for key since no interrupts)
1376 test ATKbFlags, KBResend + KBAck
1377 jnz Sen4
1378 loop Sen2
1379Sen3: ; Timed out - try to resend
1380 dec ah
1381 jnz Sen1
1382 or ATKbFlags, KBErr
1383 jmp Sen5
1384Sen4:
1385 call handler ;*a (look for key since no interrupts)
1386 test ATKbFlags, KBResend
1387 jnz Sen3
1388Sen5:
1389 cli
1390 pop cx
1391 pop ax
1392 ret
1393SendByte endp
1394
1395
1396
1397
1398;*** WaitStatus - wait for status to indicate ready for new command
1399;
1400; ENTRY: Nothing
1401;
1402; EXIT: (AL) Destroyed.
1403;
1404WaitStatus proc near
1405 push cx
1406 xor cx,cx
1407wai1: ;wait for empty buffer
1408 in al,KbStatus
1409 test al,BufFull
1410 loopnz wai1
1411 pop cx
1412 ret
1413WaitStatus endp
1414
1415 SUBTTL Initialization
1416
1417
1418
1419;* Initialization, called when run by DOS, doesn't stay resident.
1420;
1421init_bios:
1422
1423 mov al,0ffh ; all OFF
1424 out MASTER_IMR,al
1425
1426 push ds
1427 push cs
1428 pop ds ; establish segment, since offsets are from cs
1429 mov dx,offset Kbint
1430 mov ax,2509h
1431 int 21h ;Set interrupt 9 (keyboard) vector
1432
1433 mov ax, romdata
1434 mov ds, ax
1435init1: cmp [KbStart],0
1436 jnz init2 ;New PC/AT - KbStart already initialized
1437 pushf ;* save interrupt status
1438 cli ;For old PC - initialize pointers to KbBuffer
1439 mov ax,offset KbBuffer
1440 mov [KbStart],ax
1441 mov [KbHead],ax
1442 mov [KbTail],ax
1443 mov [KbEnd],offset KbBufferEnd
1444 popf ;* restore original interrupt status
1445;* sti
1446init2: ; Start up in Foreign keyboard mode
1447; mov word ptr [KeyVector],offset ForeignTable
1448; mov word ptr [KeyVector+2],cs
1449
1450; mov [accent],0 ; No previous accent key pressed
1451
1452; Get PC type information and save in PCType flag
1453; assume ds:rom
1454
1455; mov ax, rom
1456; mov ds, ax
1457; mov al, [systid]
1458; mov [PCType], al
1459
1460 assume ds:romdata
1461 pop ds
1462
1463; mov dx,offset xt_endcode + 100h
1464; cmp [PCType], PC_AT
1465; jnz init6 ; Drop AT specific code
1466
1467;* Initialization specific to AT
1468; Set up speaker counts, exchange keys 41, 43
1469; And keep AT specific code when terminate
1470; mov [BeepFreq], ATBeepFreq
1471; mov [BeepDur], ATBeepDur
1472
1473; Reverse keys 41 and 43 for foreign keyboards
1474; mov ax, [ForeignTable + (41 * 4)] ; exchange char codes
1475; xchg ax, [ForeignTable + (43 * 4)]
1476; mov [ForeignTable + (41 * 4)], ax
1477; mov ax, [ForeignTable + (41 * 4) + 2] ;exchange function codes also
1478; xchg ax, [ForeignTable + (43 * 4) + 2]
1479; mov [ForeignTable + (41 * 4) + 2], ax
1480; Also handle for Ctrl Alt table
1481; mov si, offset AltChrs - 1
1482;init3: ;search AltChrs table
1483; inc si
1484; cmp si, offset AltChrsEnd
1485; jae init5 ;Done scaning - go terminate
1486; cmp byte ptr cs:[si], 43
1487; jnz init4
1488; mov byte ptr cs:[si], 41 ; found key 43 - replace with 41
1489; jmp init3
1490;init4:
1491; cmp byte ptr cs:[si], 41
1492; jnz init3
1493; mov byte ptr cs:[si], 43 ; found key 41 - replace with 43
1494; jmp init3
1495;
1496;init5:
1497; mov dx,offset init_bios + 100h ; Keep AT specific code
1498init6:
1499; Terminate and stay resident, don't keep init code
1500; push ds ; adjust cs to psp
1501; mov bx, offset init7 + 100h ; by doing a far return to init7
1502; push bx
1503;xxxx proc far
1504; ret
1505;xxxx endp
1506;init7:
1507; int 27h
1508
1509 mov ah, 14
1510 mov al, 'i'
1511 int 10h
1512ini1:
1513
1514 ;mov ah, 14
1515 ;mov al, 'h'
1516 ;int 10h
1517
1518 call handler
1519; call getc
1520 jz ini1
1521 mov ah, 14
1522 int 10h
1523 jmp ini1
1524
1525DCODE ends
1526
1527;*** getc - read character out of keyboard buffer
1528;
1529; This routine gets characters from the buffer
1530; in the ROM data area.
1531;
1532; ENTRY
1533;
1534; EXIT AL - character
1535; AH - scan code
1536; 'Z' = 0
1537;
1538; or 'Z' = 1 if no code available
1539;
1540; USES flags
1541;
1542
1543DCODE segment
1544
1545 assume cs:DCODE, ds:nothing, es:nothing, ss:nothing
1546
1547 public kgetc
1548kgetc proc far
1549
1550 push bx
1551 push cx
1552 push dx
1553 push si
1554 push di
1555
1556 mov bx, 202h
1557 mov cx, 303h
1558 mov dx, 404h
1559 mov si, 505h
1560 mov di, 606h
1561
1562 call handler ; pull data into kbd buffer
1563
1564 mov bx, 2020h
1565 mov cx, 3030h
1566 mov dx, 4040h
1567 mov si, 5050h
1568 mov di, 6060h
1569
1570 push ds ; save caller's regs
1571 push bx
1572
1573 mov bx, romdata
1574 mov ds, bx ; DS -> ROM data area
1575
1576 cli
1577 mov bx, ds:[KbHead] ; bx = start of buffer
1578 cmp bx, ds:[KbTail] ; is buffer empty
1579;* sti
1580 jz ge1
1581
1582 cli
1583 mov ax, [bx] ; AX = character and scan code
1584 add bx, 2 ; step buffer pointer
1585 cmp bx, ds:[KbEnd] ; is it at end of buffer
1586 jne ge2
1587 mov bx, ds:[KbStart] ; move it back to start
1588ge2:
1589 mov ds:[KbHead], bx ; store new start pointer
1590;* sti
1591 and bx, 0ffffh ; just to clear zero flag
1592ge1:
1593 pop bx
1594 pop ds
1595
1596 pop di
1597 pop si
1598 pop dx
1599 pop cx
1600 pop bx
1601
1602 ret
1603
1604kgetc endp
1605
1606DCODE ends
1607 end
1608 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/KBD.INC b/v4.0/src/MEMM/MEMM/KBD.INC
new file mode 100644
index 0000000..ce3ca1a
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/KBD.INC
@@ -0,0 +1,99 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: KBD.INC - KBD.ASM Structures and Equates
10;
11; Version: 0.02
12;
13; Date: January 31, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 01/31/86 Original
24; 05/12/86 A Cleanup and segment reorganization
25; 06/28/86 0.02 Name change from MEMM386 to MEMM
26;
27;******************************************************************************
28;
29; Functional Description:
30;
31;******************************************************************************
32ifndef INC_LIST
33.xlist
34endif
35
36; SCCSID = @(#)keybxx.inc 1.1 85/10/09
37;------------------------------------------------------
38;
39; Keybxx.inc - Define struct and equates for KeybXX and Keyb??.ASM .
40;
41; Keyb?? - denotes any of the files keybfr, keybgr, keybit, keybuk,
42; keybsp or keybdv (Dvorak keyboard).
43;
44
45
46esc equ 1bh
47
48
49KbData equ 60h ; I/O Ports for keyboard
50KbCtl equ 61h
51KbStatus equ 64h
52
53PCBeepFreq equ 48h ; Count for Beep frequency
54PCBeepDur equ 105h ; Number of Beep half cycles
55ATBeepFreq equ 0CEh ; Use larger values since AT faster
56ATBeepDur equ 82h
57
58InsState equ 80h ; Bit values for BreakState and KeyState
59CapsState equ 40h
60NumState equ 20h
61ScrollState equ 10h
62HoldState equ 08h
63
64
65AltShift equ 08h ; Bit values for KeyState
66CtrlShift equ 04h
67LeftShift equ 02h
68RightShift equ 01h
69
70
71BufFull equ 02h ; Bit value for KbStatus port
72
73
74ATResend equ 0FEh ; AT keyboard commands
75ATAck equ 0FAh
76
77
78KBErr equ 080h ; Bit values for ATKbFlags
79KBSndLed equ 040h
80KBResend equ 020h
81KBAck equ 010h
82SysShift equ 004h ;SysReq key held down
83
84
85;*** AccChStruc - Structure for information about accent keys
86;
87; Contains scan and char codes returned for all shift combinations
88; with an accent key.
89;
90; Note: an accent key is an accent in both normal and shifted mode.
91;
92AccChStruc struc
93normal dw 0 ;chr & scan code for unshifted accent key
94shift dw 0 ; " " " for shifted " "
95ctrl dw -1
96alt dw -1
97AccChStruc ends
98
99.list ; end of KBD.INC
diff --git a/v4.0/src/MEMM/MEMM/LOADALL.INC b/v4.0/src/MEMM/MEMM/LOADALL.INC
new file mode 100644
index 0000000..bd31ec4
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/LOADALL.INC
@@ -0,0 +1,173 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6; **** INTEL PROPRIETARY ****
7;
8; Title: MEMM - MICROSOFT Expanded Memory Manager 386
9;
10; Module: LOADALL - contains structures for 286 and 386 loadall
11;
12; Version: 0.02
13;
14; Date: April 11,1986
15;
16; Author:
17;
18;******************************************************************************
19;
20; Change log:
21;
22; DATE REVISION DESCRIPTION
23; -------- -------- -------------------------------------------------------
24; 04/11/86 Original
25; 06/28/86 0.02 Name change from MEMM386 to MEMM
26;
27;******************************************************************************
28;
29ifndef INC_LIST
30.xlist
31endif
32
33LODAL286 equ 050Fh ; instruction as a WORD
34LODAL386 equ 070Fh ; instruction as a WORD
35
36;******************************************************************************
37;
38; Note that entries are statically initialized to 0000, so limits and
39; access rights must be set up at run time.
40;
41; Structure of a 286 system table/segment descriptor cache:
42;
43DescCache286 struc
44dc2_BASElo dw 0000 ; low word of base (0..15)
45dc2_BASEhi db 00 ; high byte of base (16..24)
46dc2_AR db 00 ; access rights byte
47dc2_LIMIT dw 0000 ; segment limit
48DescCache286 ends
49;
50; Structure of the 286 LOADALL buffer
51;
52LoadAllBuf286 struc
53
54ll2_None1 db 6 dup (0) ; temp
55ll2_MSW dw 0000 ; MSW
56ll2_None2 db 14 dup (0) ; temp
57ll2_TR dw 0000 ; TR
58ll2_FLAGS dw 0000 ; FLAGS
59ll2_IP dw 0000 ; IP
60ll2_LDT dw 0000 ; LDT
61ll2_DS dw 0000 ; DS
62ll2_SS dw 0000 ; SS
63ll2_CS dw 0000 ; CS
64ll2_ES dw 0000 ; ES
65ll2_DI dw 0000 ; DI
66ll2_SI dw 0000 ; SI
67ll2_BP dw 0000 ; BP
68ll2_SP dw 0000 ; SP
69ll2_BX dw 0000 ; BX
70ll2_DX dw 0000 ; DX
71ll2_CX dw 0000 ; CX
72ll2_AX dw 0000 ; AX
73
74;
75; System table and segment descriptor caches
76;
77ll2_EScache db size DescCache286 dup (00)
78ll2_CScache db size DescCache286 dup (00)
79ll2_SScache db size DescCache286 dup (00)
80ll2_DScache db size DescCache286 dup (00)
81ll2_GDTcache db size DescCache286 dup (00)
82ll2_LDTcache db size DescCache286 dup (00)
83ll2_IDTcache db size DescCache286 dup (00)
84ll2_TSScache db size DescCache286 dup (00)
85
86LoadAllBuf286 ends
87;
88
89;
90;******************************************************************************
91; Define the 386 LOADALL buffer structure - 'nested' structures must be
92; used because the complete definition is too complex for the linker.
93; Note that entries are statically initialized to 0000, so limits and
94; access rights must be set up at run time.
95;
96; Structure of a 386 system table/segment descriptor cache:
97;
98DescCache386 struc
99dc3_AR1 db 00 ; base 16..23 (ignored)
100dc3_AR2 db 00 ; access rights byte
101dc3_AR3 db 00 ; limit 16..19 (ignored), B/D, G
102dc3_AR4 db 00 ; base 24..31 (ignored)
103dc3_BASElo dw 0000 ; low word of base
104dc3_BASEhi dw 0000 ; high word of base
105dc3_LIMITlo dw 0000 ; low word of limit
106dc3_LIMIThi dw 0000 ; high word of limit
107DescCache386 ends
108;
109; Structure of the 386 LOADALL buffer
110;
111LoadAllBuf386 struc
112
113ll3_CR0 dw 0000 ; low word of CR0
114ll3_CR0hi dw 0000 ; high word of CR0
115ll3_EFLAGS dw 0000 ; low word of EFLAGS
116ll3_EFLAGShi dw 0000 ; high word of EFLAGS
117ll3_EIP dw 0000 ; low word of EIP
118ll3_EIPhi dw 0000 ; high word of EIP
119ll3_EDI dw 0000 ; low word of EDI
120ll3_EDIhi dw 0000 ; high word of EDI
121ll3_ESI dw 0000 ; low word of ESI
122ll3_ESIhi dw 0000 ; high word of ESI
123ll3_EBP dw 0000 ; low word of EBP
124ll3_EBPhi dw 0000 ; high word of EBP
125ll3_ESP dw 0000 ; low word of ESP
126ll3_ESPhi dw 0000 ; high word of ESP
127ll3_EBX dw 0000 ; low word of EBX
128ll3_EBXhi dw 0000 ; high word of EBX
129ll3_EDX dw 0000 ; low word of EDX
130ll3_EDXhi dw 0000 ; high word of EDX
131ll3_ECX dw 0000 ; low word of ECX
132ll3_ECXhi dw 0000 ; high word of ECX
133ll3_EAX dw 0000 ; low word of EAX
134ll3_EAXhi dw 0000 ; high word of EAX
135ll3_DR6 dw 0000 ; low word of DR6
136ll3_DR6hi dw 0000 ; high word of DR6
137ll3_DR7 dw 0000 ; low word of DR7
138ll3_DR7hi dw 0000 ; high word of DR7
139ll3_TSSR dw 0000 ; TSSR (TSS selector)
140 dw 0000 ; (padding)
141ll3_LDTR dw 0000 ; LDTR (LDT selector)
142 dw 0000 ; (padding)
143ll3_GS dw 0000 ; GS
144 dw 0000 ; (padding)
145ll3_FS dw 0000 ; FS
146 dw 0000 ; (padding)
147ll3_DS dw 0000 ; DS
148 dw 0000 ; (padding)
149ll3_SS dw 0000 ; SS
150 dw 0000 ; (padding)
151ll3_CS dw 0000 ; CS
152 dw 0000 ; (padding)
153ll3_ES dw 0000 ; ES
154 dw 0000 ; (padding)
155;
156; System table and segment descriptor caches
157;
158ll3_TSScache db size DescCache386 dup (00)
159ll3_IDTcache db size DescCache386 dup (00)
160ll3_GDTcache db size DescCache386 dup (00)
161ll3_LDTcache db size DescCache386 dup (00)
162ll3_GScache db size DescCache386 dup (00)
163ll3_FScache db size DescCache386 dup (00)
164ll3_DScache db size DescCache386 dup (00)
165ll3_SScache db size DescCache386 dup (00)
166ll3_CScache db size DescCache386 dup (00)
167ll3_EScache db size DescCache386 dup (00)
168
169ll3_temps db 134h dup (00) ; padding for internal temps
170
171LoadAllBuf386 ends
172
173.list ; end of LOADALL.INC
diff --git a/v4.0/src/MEMM/MEMM/MACH_ID.INC b/v4.0/src/MEMM/MEMM/MACH_ID.INC
new file mode 100644
index 0000000..ba217cb
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MACH_ID.INC
@@ -0,0 +1,38 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: MACH_ID.INC - include for Machine ID types
10;
11; Version: 0.03
12;
13; Date: April 9, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 04/09/86 Original
24;
25;******************************************************************************
26ifndef INC_LIST
27.xlist
28endif
29
30; STANDARD ROM BIOS MACHINE TYPES used in ROM_BIOS_Machine_ID
31
32RBMI_PC equ 0FFh
33RBMI_PCXT equ 0FEh
34RBMI_PCjr equ 0FDh
35RBMI_PCAT equ 0FCh
36RBMI_PCConvertible equ 0F9h
37RBMI_Sys80 equ 0F8h
38RBMI_CompaqPortable equ 000h
diff --git a/v4.0/src/MEMM/MEMM/MAKEFILE b/v4.0/src/MEMM/MEMM/MAKEFILE
new file mode 100644
index 0000000..9f1a77b
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MAKEFILE
@@ -0,0 +1,343 @@
1#******************************************************************************
2# title MAKEFILE - MEMM build file
3#******************************************************************************
4#
5# (C) Copyright MICROSOFT Corp. 1986
6#
7# Title: MEMM - MICROSOFT Expanded Memory Manager 386
8#
9# Module: MAKEFILE
10#
11# Version: 0.06
12#
13# Date: May 12, 1986
14#
15# Author:
16#
17#******************************************************************************
18#
19# Change log:
20#
21# DATE REVISION DESCRIPTION
22# -------- -------- -------------------------------------------------------
23# Original
24# 05/12/86 B- Cleanup and segment reorganization
25# 06/03/86 C- Added module for driver i/f
26# 06/08/86 C- Merge in lastest code from MS
27# 06/17/86 D- Added debug version.
28# 06/28/86 0.02 Name change from MEMM386 to MEMM
29# 07/01/86 0.03 Added MapDMA module.
30# 07/11/86 0.05 Moved HIFLAG into global includes.
31#
32#******************************************************************************
33#
34# Functional Description:
35#
36# This file assembles and links
37# (1) EMM386.EXE - Production version of EMM386 driver
38# (2) EMM386.COM - Production version of EMM386 utility
39# (3) EMM386D.EXE - Debug (Internal) version of EMM386 driver
40#
41#******************************************************************************
42
43#******************************************************************************
44# R U L E S and M A C R O S
45#******************************************************************************
46.SUFFIXES:
47.SUFFIXES: .c .asm .obj .lst .def .lnk .lrf .exe .com
48
49
50# Definition for turning OFF high memory allocation
51# HIFLAG = -DNOHIMEM => turns it off
52# HIFLAG = => turns on high memory allocation
53HIFLAG = -DNOHIMEM
54#HIFLAG =
55
56# Definitions for assembler
57#ASM = c:\bin\masm400
58#ASM = masm400
59ASM = masm
60AFLAGS = -Mx -t -DI386 -DNoBugMode $(HIFLAG)
61ADFLAGS = -Mx -t -DI386 $(HIFLAG)
62AINC = -i..\emm
63
64# Defines for C Compiler
65C = cl
66CFLAGS =/AS /G2 /Oat /Gs /Ze /Zl /Fc /c
67
68# Definitions for linker for old style .exe files
69#LINK = c:\bin\link
70#LINK = link
71LINK = link
72LFLAGS = /NOI
73
74# Definitions for .COM generation
75CONVERT = c:\dos\exe2bin
76#CONVERT = exe2bin
77
78# Rules for generating object and linker response and definition files
79.asm.obj:
80 $(ASM) $(AFLAGS) $(AINC) -p $*.asm;
81
82.asm.lst:
83 $(ASM) -l -n $(AFLAGS) $(AINC) -p $*.asm;
84
85#******************************************************************************
86# List of include files required
87#******************************************************************************
88MEMMINC = ascii_sm.equ driver.equ pic_def.equ romstruc.equ romxbios.equ \
89 desc.inc elim.inc emm386.inc instr386.inc kbd.inc loadall.inc \
90 oemdep.inc page.inc vdmseg.inc vdmsel.inc vm386.inc mach_id.inc
91
92
93#******************************************************************************
94# List of object files required
95#******************************************************************************
96
97MEMMOBJ = memm386.obj elimfunc.obj init.obj allocmem.obj ppage.obj emmmes.obj \
98 inittab.obj memmonf.obj rom_srch.obj i286.obj trapdef.obj \
99 i386.obj tabdef.obj vmtrap.obj vminst.obj elimtrap.obj \
100 vminit.obj moveb.obj em286ll.obj em386ll.obj retreal.obj \
101 rrtrap.obj vdminit.obj initepg.obj errhndlr.obj maplin.obj \
102 ekbd.obj util.obj initdeb.obj emm.obj emminit.obj mapdma.obj \
103 iotrap.obj a20trap.obj oemproc.obj m_state.obj \
104 shiphi.obj extpool.obj
105
106COMOBJ = memmcom.obj memmonf.obj
107
108BUGOBJ = memm386.obj elimfunc.obj init.obj allocmem.obj ppage.obj emmmes.obj \
109 inittab.obj memmonf.obj rom_srch.obj i286.obj trapdef.obj \
110 i386.obj tabdefD.obj vmtrapD.obj vminstD.obj elimtrap.obj \
111 vminit.obj moveb.obj em286ll.obj em386ll.obj retreal.obj \
112 rrtrap.obj vdminitD.obj initepg.obj errhndlr.obj maplin.obj \
113 ekbd.obj util.obj initdebD.obj emmD.obj emminit.obj mapdma.obj \
114 iotrap.obj a20trap.obj oemproc.obj kbd.obj print.obj m_state.obj
115
116#******************************************************************************
117# List of libraries required
118#******************************************************************************
119
120MEMMLIBS = ..\emm\emmlib.lib
121
122BUGLIBS = ..\deb386\buglib.lib ..\emm\emmlib.lib
123
124#******************************************************************************
125# Listing files
126#******************************************************************************
127MEMMLST = memm386.lst elimfunc.lst init.lst ppage.lst allocmem.lst emmmes.lst \
128 inittab.lst memmonf.lst rom_srch.lst i286.lst trapdef.obj \
129 i386.lst tabdef.lst vmtrap.lst vminst.lst elimtrap.lst \
130 vminit.lst moveb.lst em286ll.lst em386ll.lst retreal.lst \
131 rrtrap.lst vdminit.lst initepg.lst errhndlr.lst maplin.lst \
132 ekbd.lst util.lst initdeb.lst emm.lst emminit.lst mapdma.lst \
133 iotrap.lst a20trap.lst memminc.lst oemproc.lst shiphi.lst \
134 extpool.lst
135
136COMLST = memmcom.lst memmonf.lst
137
138BUGLST = memm386.lst elimfunc.lst init.lst allocmem.lst ppage.lst emmmes.lst \
139 inittab.lst memmonf.lst rom_srch.lst i286.lst trapdef.lst \
140 i386.lst tabdefD.lst vmtrapD.lst vminstD.lst elimtrap.lst \
141 vminit.lst moveb.lst em286ll.lst em386ll.lst retreal.lst \
142 rrtrap.lst vdminitD.lst initepg.lst errhndlr.lst maplin.lst \
143 ekbd.lst util.lst initdebD.lst emmD.lst emminit.lst mapdma.lst \
144 iotrap.lst a20trap.lst kbd.lst emmincD.lst oemproc.lst
145
146
147#******************************************************************************
148# MEMM targets
149#******************************************************************************
150#emm386: emm386.exe emm386.com emm386d.exe
151emm386: emm386.exe
152
153# production version of EMM386 device driver
154#
155emm386.exe: $(MEMMOBJ) $(MEMMLIBS) emm386.lnk
156 $(LINK) $(LFLAGS) @emm386.lnk
157 del emm386.sys
158 ren emm386.exe emm386.sys
159
160# EMM386.COM utility
161#
162#emm386.com: $(COMOBJ) emmcom.lnk
163# $(LINK) $(LFLAGS) @emmcom.lnk
164# $(CONVERT) emmcom.exe emm386.com
165
166# debug version of EMM386 driver
167#
168#emm386d.exe: $(BUGOBJ) $(BUGLIBS) emm386d.lnk
169# $(LINK) $(LFLAGS) @emm386d.lnk
170
171#******************************************************************************
172# EMM386 driver i/f modules
173#******************************************************************************
174
175memm386.obj: memm386.asm $(MEMMINC)
176 $(ASM) $(AFLAGS) $(AINC) $*.asm;
177memm386.lst: memm386.asm $(MEMMINC)
178 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
179
180elimfunc.obj: elimfunc.asm $(MEMMINC)
181 $(ASM) $(AFLAGS) $(AINC) $*.asm;
182elimfunc.lst: elimfunc.asm $(MEMMINC)
183 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
184
185init.obj: init.asm $(MEMMINC)
186 $(ASM) $(AFLAGS) $(AINC) $*.asm;
187init.lst: init.asm $(MEMMINC)
188 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
189
190allocmem.obj: allocmem.asm $(MEMMINC)
191 $(ASM) $(AFLAGS) $(AINC) $*.asm;
192allocmem.lst: allocmem.asm $(MEMMINC)
193 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
194
195rom_srch.obj: rom_srch.asm $(MEMMINC)
196 $(ASM) $(AFLAGS) $(AINC) $*.asm;
197rom_srch.lst: rom_srch.asm $(MEMMINC)
198 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
199
200inittab.obj inittab.lst: inittab.asm $(MEMMINC)
201
202emmmes.obj emmmes.lst: emmmes.asm $(MEMMINC)
203
204extpool.obj extpool.lst: extpool.asm $(MEMMINC)
205
206shiphi.obj shiphi.lst: shiphi.asm $(MEMMINC)
207
208m_state.obj m_state.lst: m_state.asm $(MEMMINC)
209
210ppage.obj ppage.lst: ppage.asm $(MEMMINC) ..\emm\emmdef.inc
211
212#******************************************************************************
213# VDM modules
214#******************************************************************************
215
216vdminit.obj vdminit.lst: vdminit.asm $(MEMMINC)
217
218i286.obj i286.lst: i286.asm $(MEMMINC)
219
220i386.obj i386.lst: i386.asm $(MEMMINC)
221
222trapdef.obj trapdef.lst: trapdef.asm $(MEMMINC)
223
224tabdef.obj tabdef.lst: tabdef.asm $(MEMMINC)
225
226vmtrap.obj vmtrap.lst: vmtrap.asm $(MEMMINC)
227
228vminst.obj vminst.lst: vminst.asm $(MEMMINC)
229
230elimtrap.obj: elimtrap.asm $(MEMMINC) ..\emm\emmdef.inc
231 $(ASM) $(AFLAGS) $(AINC) $*.asm;
232elimtrap.lst: elimtrap.asm $(MEMMINC) ..\emm\emmdef.inc
233 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
234
235iotrap.obj iotrap.lst: iotrap.asm $(MEMMINC)
236
237initepg.obj: initepg.asm $(MEMMINC)
238 $(ASM) $(AFLAGS) $(AINC) $*.asm;
239initepg.lst: initepg.asm $(MEMMINC)
240 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
241
242vminit.obj vminit.lst: vminit.asm $(MEMMINC)
243
244em286ll.obj em286ll.lst: em286ll.asm $(MEMMINC)
245
246em386ll.obj em386ll.lst: em386ll.asm $(MEMMINC)
247
248moveb.obj: moveb.asm $(MEMMINC)
249 $(ASM) $(AFLAGS) $(AINC) $*.asm;
250moveb.lst: moveb.asm $(MEMMINC)
251 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
252
253util.obj: util.asm $(MEMMINC)
254 $(ASM) $(AFLAGS) $(AINC) $*.asm;
255util.lst: util.asm $(MEMMINC)
256 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
257
258maplin.obj maplin.lst: maplin.asm $(MEMMINC)
259
260a20trap.obj a20trap.lst: a20trap.asm $(MEMMINC)
261
262oemproc.obj oemproc.lst: oemproc.asm $(MEMMINC)
263
264rrtrap.obj rrtrap.lst: rrtrap.asm $(MEMMINC)
265
266retreal.obj retreal.lst: retreal.asm $(MEMMINC)
267
268errhndlr.obj errhndlr.lst: errhndlr.asm $(MEMMINC)
269
270ekbd.obj ekbd.lst: ekbd.asm $(MEMMINC)
271
272initdeb.obj initdeb.lst: initdeb.asm $(MEMMINC)
273
274emminit.obj emminit.lst: emminit.asm $(MEMMINC)
275
276emm.obj emm.lst: emm.asm $(MEMMINC)
277
278mapdma.obj mapdma.lst: mapdma.c
279 $(C) /ASw /G2 /Oat /Gs /Ze /Zl /Fc /c mapdma.c
280
281memminc.lst: memminc.asm $(MEMMINC)
282 $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
283
284#******************************************************************************
285# debug modules
286#******************************************************************************
287
288#tabdefD.obj: tabdef.asm $(MEMMINC)
289# $(ASM) $(ADFLAGS) $(AINC) tabdef.asm,tabdefD.obj;
290#tabdefD.lst: tabdef.asm $(MEMMINC)
291# $(ASM) -l -n $(ADFLAGS) $(AINC) tabdef.asm,tabdefD.obj,tabdefD.lst;
292#
293#vminstD.obj: vminst.asm $(MEMMINC)
294# $(ASM) $(ADFLAGS) $(AINC) vminst.asm,vminstD.obj;
295#vminstD.lst: vminst.asm $(MEMMINC)
296# $(ASM) -l -n $(ADFLAGS) $(AINC) vminst.asm,vminstD.obj,vminstD.lst;
297
298#vmtrapD.obj: vmtrap.asm $(MEMMINC)
299# $(ASM) $(ADFLAGS) $(AINC) vmtrap.asm,vmtrapD.obj;
300#vmtrapD.lst: vmtrap.asm $(MEMMINC)
301# $(ASM) -l -n $(ADFLAGS) $(AINC) vmtrap.asm,vmtrapD.obj,vmtrapD.lst;
302#
303#vdminitD.obj: vdminit.asm $(MEMMINC)
304# $(ASM) $(ADFLAGS) $(AINC) vdminit.asm,vdminitD.obj;
305#vdminitD.lst: vdminit.asm $(MEMMINC)
306# $(ASM) -l -n $(ADFLAGS) $(AINC) vdminit.asm,vdminitD.obj,vdminitD.lst;
307
308#initdebD.obj: initdeb.asm $(MEMMINC)
309# $(ASM) $(ADFLAGS) $(AINC) initdeb.asm,initdebD.obj;
310#initdebD.lst: initdeb.asm $(MEMMINC)
311# $(ASM) -l -n $(ADFLAGS) $(AINC) initdeb.asm,initdebD.obj,initdebD.lst;
312
313#emmD.obj: emm.asm $(MEMMINC)
314# $(ASM) $(ADFLAGS) $(AINC) emm.asm,emmD.obj;
315#emmD.lst: emm.asm $(MEMMINC)
316# $(ASM) -l -n $(ADFLAGS) $(AINC) emm.asm,emmD.obj,emmD.lst;
317
318#kbd.obj kbd.lst: kbd.asm $(MEMMINC)
319# $(ASM) $(ADFLAGS) $(AINC) -p $*.asm;
320
321#print.obj print.lst: print.asm $(MEMMINC)
322# $(ASM) $(ADFLAGS) $(AINC) -p $*.asm;
323
324#memmincD.lst: memminc.asm $(MEMMINC)
325# $(ASM) -l -n $(ADFLAGS) $(AINC) memminc.asm,memmincD.obj,memmincD.lst;
326
327#******************************************************************************
328# EMM386.COM modules
329#******************************************************************************
330
331#memmcom.obj: memmcom.asm
332# $(ASM) $(AFLAGS) $(AINC) $*.asm;
333#memmcom.lst: memmcom.asm
334# $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
335
336#memmonf.obj: memmonf.asm memm_msg.inc
337# $(ASM) $(AFLAGS) $(AINC) $*.asm;
338#memmonf.lst: memmonf.asm memm_msg.inc
339# $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm;
340
341
342
343 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/MAPDMA.ASM b/v4.0/src/MEMM/MEMM/MAPDMA.ASM
new file mode 100644
index 0000000..c1e1f4f
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MAPDMA.ASM
@@ -0,0 +1,633 @@
1
2
3page 58,132
4;******************************************************************************
5 title MapDMA - Ensure all DMA transfers are physically contiguous
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: MapDMA
13;
14; Version: 0.04
15;
16; Date: June 18,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/18/86 Original
27; 07/02/86 0.03 Added check for ECX = 0
28; 07/02/86 0.03 MapLinear added to set_selector
29; 07/06/86 0.04 Changed _pft386 to ptr to _pft386 array
30; 07/06/86 0.04 Changed assume to DGROUP
31;
32;******************************************************************************
33;
34; Functional Description:
35;
36; This module ensures that EMM pages accessed by a DMA transfer (within
37; the EMM Page Frame) are physically contiguous in memory. This is accomplished
38; by physically relocating entire EMM pages so that all of the pages participating
39; in the DMA transfer are adjacent. As a first pass, pages that need to be
40; relocated will always be moved to the base address of extended memory (or
41; possibly hi memory if that option is selected). A four word array (DMA_Pages)
42; initialized by InitEPG will contain the actual 32 bit physical address of
43; the first four physical EMM page locations. Although this will decrease
44; the time necessary to search for potential relocation candidates, it could
45; also result in the relocation of all pages when a fewer number might suffice
46; (given a more elegant mapping scheme).
47;
48; Some transfers that will NOT require remapping are:
49; 1. The DMA transfer is entirely outside the EMM Page Frame
50; 2. The DMA transfer is entirely within one Page Frame Window
51; 3. The DMA transfer spans more than one Page Frame Window, but
52; the EMM pages currently residing there are already contiguous
53; 4. See number 4 below
54;
55; Some transfers that will result in an exception are:
56; 1. The DMA transfer spans more than one Page Frame Window, where
57; at least one (but not all) of the windows is currently unmapped.
58; 2. The DMA transfer spans more than one Page Frame Window, with
59; the same EMM page residing in more than one of the windows
60; 3. The DMA transfer spans more than one Page Frame Window, but there
61; is physically not enough contiguous memory in which to locate the
62; requested EMM Pages. (This could occur in the model where both
63; extended memory and hi memory combine to form the EMM pool)
64; 4. The DMA transfer includes memory outside the Page Frame, AND
65; INSIDE the Page Frame (unless the Page Frame Windows are currently
66; unmapped, in which case no relocation is necessary)
67;
68;******************************************************************************
69.lfcond ; list false conditionals
70.386p
71 page
72;******************************************************************************
73; P U B L I C D E C L A R A T I O N S
74;******************************************************************************
75;
76 public MapDMA
77 public DMA_Pages
78 public DMA_PAGE_COUNT
79
80 page
81;******************************************************************************
82; L O C A L C O N S T A N T S
83;******************************************************************************
84;
85 include VDMseg.inc
86 include VDMsel.inc
87 include desc.inc
88 include page.inc
89 include instr386.inc
90 include vm386.inc
91 include emmdef.inc
92;
93;******************************************************************************
94; E X T E R N A L R E F E R E N C E S
95;******************************************************************************
96;
97ABS0 segment use16 at 0000h
98ABS0 ends
99
100_DATA segment
101
102extrn _page_frame_base:dword ; Page Table Entry pointers for windows 0-3
103extrn _pft386:word ; ptr to array of Page Table entries
104;extrn _current_map:byte ; current mapping register values
105extrn PF_Base:word ; Base addr of page frame
106extrn _total_pages:word ; total number of EMM pages
107extrn Page_Dir:word
108
109xfer_map dw 0 ; map of windows participating in DMA xfer
110_DATA ends
111
112_TEXT segment
113
114 extrn ErrHndlr:near
115 extrn MapLinear:near
116
117_TEXT ends
118
119;******************************************************************************
120; S E G M E N T D E F I N I T I O N
121;******************************************************************************
122;
123_DATA segment
124
125;
126; DMA_Pages - EMM Pages for DMA relocation. Each is an index into pft386.
127; To access actual entry in pft386 you need to multiply index by 4.
128; If eight contingous 16k EMM pages are not available - the unavailable
129; entries are left at NULL_PAGE.
130; This array should be initialized at boot time.
131;
132DMA_Pages dw 8 dup (NULL_PAGE) ; null for start
133DMA_PAGE_COUNT dw 0 ; number of above initialised
134
135_DATA ends
136
137;------------------------------------------------------------------------------
138_TEXT segment
139
140 assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP
141 page
142;******************************************************************************
143; MapDMA - Relocate (if necessary) EMM pages to ensure that a DMA transfer
144; is contiguous
145;
146; ENTRY: Protected Mode Ring 0
147; EAX = linear base address of DMA transfer
148; ECX = byte count of transfer
149; DGROUP:[_pft386] = ptr to dword array of ptrs for EMM Pages
150; DGROUP:[DMA_Pages] = array of EMM page addresses in 1st 64k (used for
151; relocating pages to contiguous physical memory)
152;
153; EXIT: Protected mode Ring 0
154; EAX = physical base address for DMA transfer
155; DGROUP:_pft386[] = modified to reflect relocation of EMM pages
156; Page Table Entries modified to reflect relocation.
157; CY = CLEAR if exit address = entry address
158; CY = SET if exit address <> entry address (mapping was necessary)
159;
160; USED: EAX
161; Flags
162; STACK:
163;******************************************************************************
164MapDMA proc near
165;
166 PUSH_EBX
167 PUSH_EAX ; save original address
168 PUSH_ECX
169 PUSH_EDX
170 PUSH_EDI
171 PUSH_ESI
172 push es
173;
174 cld
175;
176; check for ECX = 0
177;
178 jecxz nomap1 ; nomap out of jmp range
179 jmp short mDMA_domap
180nomap1:
181 jmp nomap
182;
183; As a quick first check, let's see if this transfer is any where near the PF
184;
185mDMA_domap:
186 mov ebx,eax ; get address
187 shr ebx,16 ; get rid of 64k
188 mov dx,[PF_Base] ; base address of Page Frame div 4
189 mov di,dx ; save it
190 shr dx,12 ; divide by 64k
191 cmp bx,dx ; q: is it in PF?
192 jb nomap ; n: no mapping necessary
193 add di,0fffh ; plus 64k div 4 for end of PF
194 shr di,12 ; divide by 64k
195 cmp bx,di ; q: before end of PF?
196 ja nomap ; n: no mapping necessary
197;
198 push ax ; save lower 16 bits of addr
199 mov ebx,4000h ; window size
200;
201; build a map of windows used in this transfer
202;
203 mov [xfer_map],0 ; zero to start with
204 dec ecx ; stop at last byte
205lloop:
206 call chk_loc ; mark this guy's location in the map
207 or ecx,ecx ; q: done?
208 jz chk_done ; y
209 cmp ecx,ebx ; n: q: is there a whole window left?
210 jae full_wind ; y: skip the adjustment
211 mov bx,cx ; n: just check what's left
212full_wind:
213 sub ecx,ebx ; adjust count by window size
214 add ax,bx ; and base addr (let it wrap)
215 jmp lloop ; do the next one
216chk_done:
217 pop ax ; restore base addr of transfer
218 shl [xfer_map],1 ; q: is the transfer outside the PF?
219 jnc in_PF ; n: entirely within Page Frame
220;
221; At least part of the transfer involves an area outside the Page Frame.
222; This is ok as long as all parts inside the Page Frame are currently unmapped.
223;
224 mov cx,[xfer_map] ; get the map values
225 xor si,si ; set up to check all windows
226 xor edx,edx ; clean out high bits
227 mov dx,[PF_Base] ; dx = address of window 0
228 shl edx,4 ; make it 32 bits
229mloop1:
230 shl cx,1 ; q: is this window involved?
231 jnc not_inv ; n: not involved but still more to check
232 call IsMapped ; q: is this page mapped?
233 jne excp ; y: exception (can't handle it)
234not_inv:
235 add edx, 4000h ; n: update address of window
236 add si,4 ; and _page_frame_base index
237 or cx,cx ; q: any more to check?
238 jnz mloop1 ; y: check the next window
239;
240nomap: jmp DMA_nomap ; don't need to relocate
241;
242excp: jmp DMA_excp ; exception (can't deal with this)
243;
244; The DMA transfer is entirely within the Page Frame area. If the
245; physical location of the EMM pages (mapped into the windows participating
246; in the DMA transfer) are already contiguous, then don't do anything.
247; Otherwise, relocate them to the base area.
248;
249; eax >= [PF_Base] = linear base address of xfer
250;
251in_PF:
252 mov bx,[xfer_map] ; get a copy of the map
253 shr bx,4 ; duplicate on the end
254 or [xfer_map],bx ; ... for wraparound
255 op32
256 mov cx,ax ; ecx = base addr of xfer
257 op32
258 shr cx,4 ; paragraph form
259 sub cx,[PF_Base]
260 shr cx,10 ; cx = starting window of transfer
261 shl [xfer_map],cl ; position on 1st window of transfer
262 and [xfer_map],0f7ffh ; only 1st 4 windows are valid
263 shl [xfer_map],1 ; we know there's at least one
264 or [xfer_map],cx ; save starting window number
265 mov bx,cx ; bx = starting window
266 shl bx,2 ; bx = double word index
267 mov cx,[xfer_map] ; get map back
268 les di,_page_frame_base[bx] ; es:di = page table pointer for window bx
269 and ax,3fffh ; get lower 14 bits
270 push ax ; save lower 14 bits of starting addr
271 op32
272 mov ax,es:[di] ; get page table entry
273 and ax,0f000h ; get rid of lower 12 bits
274 push_eax ; save physical address
275;
276; bx = window number to check for contiguity
277; eax = physical address of EMM page mapped into previous window
278; cx = bit map of windows participating in the transfer
279;
280c_chk:
281 shl cx,1 ; q: is the next window involved?
282 jnc DMA_addr ; n: no need to check any more
283 add bx,4 ; next window
284 and bx,0fh ; mod 16
285 add ax,4000h ; next physically contiguous window
286 les di,_page_frame_base[bx] ; es:di = page table pointer for window bx
287 op32
288 mov dx,es:[di] ; get page table entry
289 and dx,0f000h ; get rid of lower 12 bits
290 op32
291 cmp ax,dx ; q: contiguous?
292 je c_chk ; y: check next window
293;
294 jmp DMA_reloc ; They were not contiguous, must relocate
295DMA_addr:
296 pop_eax ; top part of actual address
297 pop dx ; get second half of actual address
298 or ax,dx ; form real address
299 jmp DMA_nomap ; don't need to map
300;
301; Relocate EMM pages mapped into the windows starting with the
302; low order bits of [xfer_map], for as many high bits of [xfer_map].
303; The lower 14 bits of original address are still on the stack
304;
305DMA_reloc:
306 pop_eax ; top part of actual address
307 mov bx,[xfer_map] ; get map
308 mov cx,bx ; copy it
309 and bx,3 ; bx = starting window number
310 xor di,di ; di = index into DMA_Pages
311reloc_loop:
312 mov si,12 ; board index for _current_map
313 push cx ; save window map
314 mov cx,4 ; 4 boards
315bloop:
316; WE NEED TO WORK ON THE DMA MORE
317; BUT int the mean time, ignore _current_map (Paul Chan)
318; mov dl,_current_map[bx+si] ; get mapping register value
319 shl dl,1 ; q: is it mapped?
320 jnc next_board ; n: try next board
321 mov dh,cl ; y: dh = board number
322 dec dh ; board is zero relative
323 shr dx,1 ; dx = EMM page number
324 cmp dx,[_total_pages] ; q: is this page in range?
325 jb found_page ; y: go relocate it
326next_board: ; n: try next board
327 sub si,4 ; update index to _current_map
328 loop bloop ; do another
329;
330; If we ever get here, we've got a problem in the data structures, or
331; in the previous couple of hundred lines since we couldn't seem to locate
332; any pages occupying window bx (which should have generated an exception
333; long ago). In either case, we might just as well call it an exception.
334excp2: jmp DMA_excp ; don't know what else to do
335;
336; At this point we have found the EMM page (= dx) occupying window bx.
337; di is the index into DMA_Pages that tells us the physical address of this
338; particular relocation area. Now we need to run through _pft386 and find
339; this address so we can swap him with page dx. If DMA_Pages contains -1,
340; then we just don't have the physically contiguous memory to get the job done.
341;
342found_page:
343 push di ; save di
344 op32
345 mov ax,DMA_Pages[di] ; get addr of relocation area
346 op32
347 or ax,ax ; q: -1?
348 js excp2 ; y: not enough contig memory
349 mov cx,[_total_pages] ; number of entries in _pft386
350 mov si,-4 ; index into _pft386
351 add si,[_pft386] ; si = ptr for _pft386 array
352floop:
353 add si,4 ; point to next entry
354 op32
355 mov di,[si] ; get pft entry
356 and di,0f000h ; get rid of low 12 bits
357 op32
358 cmp di,ax ; q: did we find who's there?
359 loopne floop ; n: keep looking
360 jne excp2 ; whoops, nobody was using it
361;
362; si = ptr to EMM page currently using our relocation area.
363; Swap it with EMM page # dx
364;
365 mov di,dx ; page number in window
366 shl di,2 ; offset for _pft386
367 add di,[_pft386] ; di -> EMM page#dx entry
368 cmp di,si ; q: was it us all along?
369 je no_swap ; y: don't need to move it
370 op32
371 mov dx,[di] ; PTE for this page
372 and dx,0f000h ; get rid of low 12 bits
373;
374; DS:SI -> relocation page entry in _pft386
375; DS:DI -> EMM page # dx entry in _pft386
376; check to see if we have already relocated this guy once. If so, that
377; implies that the same EMM page is mapped into more than one window.
378; Since there is no way (without scratch buffers) to make that contiguous,
379; we will just abort.
380;
381 op32
382 cmp dx,[DMA_Pages] ; q: have we already relocated it?
383 jb no_dup ; n: ok
384 op32
385 cmp dx,ax ; q: is it in the relocation area?
386 jb excp2 ; y: sorry
387no_dup:
388 op32
389 and [si],0fffh ; preserve his 12 bits
390 dw 0
391 op32
392 or [si],dx ; move in his new address
393 op32
394 and [di],0fffh ; now do the same thing
395 dw 0 ; for the page in the window
396 op32
397 or [di],ax ; fix up his address
398;
399; swap pages residing at addresses eax and edx
400;
401 push_eax ; save address in window
402 push ds
403 mov di,MBSRC_GSEL ; source selector
404 call set_selector ; set to address eax
405 mov es,di
406 mov di,MBTAR_GSEL ; destination selector
407 op32
408 mov ax,dx ; destination
409 call set_selector ; set up selector
410 mov ds,di
411 mov cx,1000h ; 16k bytes (4 at a time)
412 xor di,di ; initialize index
413sloop:
414 op32
415 mov ax,es:[di] ; get a word from dest.
416 op32
417 xchg ax,ds:[di] ; swap with source
418 op32
419 stosw ; store in dest.
420 loop sloop ; do the next one
421;
422 pop ds
423 pop_eax ; restore physical address
424
425no_swap:
426
427
428 pop di ; index into DMA_Pages
429 add di,4 ; update index
430 pop cx ; window map
431 inc bx ; next window number
432 and bx,3 ; mod 4
433 shl cx,1 ; q: any left?
434 jnc fix_pte ; n: done relocating
435 jmp reloc_loop ; y: relocate the next page
436fix_pte:
437;
438; Now set all 4 entries in page table. Rather than try to figure out exactly
439; which entries in here have changed, we will reset all entries shown as
440; being "mapped" by _current_map. Unmapped entries shouldn't have changed.
441;
442 mov cx,15 ; start at last entry
443ploop:
444 mov si,cx ; copy index
445; mov bl,_current_map[si] ; get current_map entry
446 shl bl,1 ; q: is it mapped?
447 jnc pte_not_mapped ; n: try next
448 mov bh,cl ; copy index number
449 shr bh,2 ; get board number
450 shr bx,1 ; bx = emm page number
451 cmp bx,[_total_pages] ; q: in range?
452 jae pte_not_mapped ; n: try next
453 shl bx,2 ; y: index into _pft386
454 add bx,[_pft386] ; ptr into _pft386
455 op32
456 mov ax,[bx] ; y: get pte value
457 and ax,0f000h ; get rid of lower 12 bits
458 mov si,cx ; get index number
459 and si,3 ; get window number
460 shl si,2 ; 32 bit index
461 les di,_page_frame_base[si] ; pointer to page table entry
462 or ax,P_AVAIL ; set access bits
463 op32
464 stosw ; set 1st Page Table Entry
465
466 add_eax_ 1000h ; 2nd 386 page
467 op32
468 stosw ; set 2nd Page Table Entry
469
470 add_eax_ 1000h ; 3rd 386 page
471 op32
472 stosw ; set 3rd Page Table Entry
473
474 add_eax_ 1000h ; 4th 386 page
475 op32
476 stosw ; set 4th Page Table Entry
477pte_not_mapped:
478 dec cx ; q: done with _current_map?
479 jns ploop ; n: keep going
480
481;
482; reload CR3 to flush TLB
483;
484 db 66h
485 mov ax,[Page_Dir] ; mov EAX,dword ptr [Page_Dir]
486 db 0Fh,22h,18h ; mov CR3,EAX
487 op32
488 mov ax,[DMA_Pages] ; get physical address to return
489 pop dx ; don't forget about the lower 14 bits
490 or ax,dx
491;
492; eax = physical address for DMA transfer
493;
494DMA_nomap:
495 pop es
496 POP_ESI
497 POP_EDI
498 POP_EDX
499 POP_ECX
500 POP_EBX ; get original eax
501 clc ; assume they're the same
502 OP32
503 cmp ax,bx ; q: did we have to map?
504 je cy_noset ; n: don't set carry
505 stc ; y: set carry
506cy_noset:
507 POP_EBX
508;
509 ret
510DMA_excp:
511 mov ax,ExcpErr
512 mov bx,ErrDMA
513 jmp ErrHndlr ; don't come back
514
515MapDMA endp
516
517
518 page
519;******************************************************************************
520; IsMapped - Check whether or not a window is unmapped
521;
522; ENTRY: Protected Mode Ring 0
523; si = window number * 4
524; edx = physical address of Page Frame Window
525; DGROUP:[_page_frame_base] = array of ptrs to page table entries
526;
527; EXIT: Protected mode Ring 0
528; ZF = unmapped
529; NZF= mapped
530;
531; USED: di,ebx,es
532; Flags
533; STACK:
534;******************************************************************************
535isMapped proc near
536 les di,_page_frame_base[si] ; es:di = addr of page table entry
537 op32
538 mov bx,es:[di] ; ebx = page table entry for window
539 and bx,0f000h ; mask off low order 12 bits
540 op32
541 cmp bx,dx ; q: is it mapped to itself (unmapped)?
542 ret
543isMapped endp
544
545
546 page
547;******************************************************************************
548; chk_loc - Check the location of a given address and update map accordingly
549;
550; ENTRY: Protected Mode Ring 0
551; eax = physical address to check
552; DGROUP:[xfer_map] = map of addresses used in this transfer
553; bit 16 indicates an address outside the PF
554; bits 15-12 correspond to windows 0-3 resp.
555;
556; EXIT: Protected mode Ring 0
557; DGROUP:[xfer_map] = updated as necessary
558;
559; USED: none
560; Flags
561; STACK:
562;******************************************************************************
563chk_loc proc near
564 push_eax ; save address
565 push cx
566;
567 mov ch,80h ; set high bit (outside indicator)
568 op32
569 shr ax,4 ; put in paragraph form
570 sub ax,[PF_Base] ; make it relative to base of Page Frame
571 jb outside ; outside of page frame
572 op32
573 shr ax,10 ; ax = window number
574 cmp_eax_ 3 ; q: inside Page Frame?
575 ja outside ; n: outside
576 mov cl,al ;
577 inc cl ; skip over outside bit
578 shr ch,cl
579outside:
580 xor cl,cl ; clear lower byte
581 or [xfer_map],cx
582;
583 pop cx
584 pop_eax
585 ret
586chk_loc endp
587 page
588;******************************************************************************
589; set_selector - set up a selector address/attrib
590;
591; ENTRY: EAX = address for GDT selector
592; DI = GDT selector
593; EXIT: selector at ES:DI is writeable data segment,64k long and points
594; to desired address.
595;
596;******************************************************************************
597set_selector proc near
598;
599 PUSH_EAX
600 push di
601 push es
602;
603 call MapLinear
604;
605 and di,NOT 07h ; just in case... GDT entry
606 push GDTD_GSEL
607 pop es ; ES:DI -> selector entry
608;
609 mov es:[di+2],ax ; low word of base address
610 OP32
611 shr ax,16 ; AX = high word of address
612 mov es:[di+4],al ; low byte of high word of address
613 xor al,al ; clear limit/G bit
614 mov es:[di+6],ax ; set high byte of high word of addr
615 ; and high nibble of limit/G bit
616;
617 mov ax,0FFFFh
618 mov es:[di],ax ; set limit to 64k
619;
620 mov al,D_DATA0 ; writeable DATA seg / ring 0
621 mov es:[di+5],al
622;
623 pop es
624 pop di
625 POP_EAX
626 ret
627;
628set_selector endp
629
630_TEXT ends ; end of segment
631;
632 end ; end of module
633
diff --git a/v4.0/src/MEMM/MEMM/MAPDMA.C b/v4.0/src/MEMM/MEMM/MAPDMA.C
new file mode 100644
index 0000000..7aae10d
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MAPDMA.C
@@ -0,0 +1,425 @@
1
2
3/* MAPDMA.C - Ensures DMA Xfer area is physically contiguous. Swaps pages
4 * if necessary.
5 *
6 * Date Author Comments
7 8/12/88 JHB updated comments, checking for sufficient pages
8 available in DMA_Pages[] before remappping
9
10 8/18/88 JHB if incoming parameters appear to be wrong or
11 if any unmapped page found in the transfer area assume
12 the Address and Count registers do not have valid values
13 and hence return without swapping pages.
14 Removed IFDEF DEBUG code
15 */
16
17#define HEX4K 0x1000
18#define HEX16K 0x4000L
19#define HEX64K 0x10000
20#define HEX128K 0x20000
21#define HEX256K 0x40000L
22#define HEX640K 0xA0000L
23#define HEX1MB 0x100000L
24
25#define ALIGN128K ~0x1FFFFL
26#define ALIGN64K ~0x0FFFFL
27#define ALIGN16K ~0x03FFFL
28
29#define MAX_PHYS_PAGES 40
30
31/* macros
32 * PT(a) - pte from index a
33 * INDEX(a) - index from Linear Adr
34 * OFFSET(a) - offset from Linear Adr
35 * LIN2PHY(l) - Physical Adr from Linear Adr
36 * DosPhyPage - consider 16K pages from 0 to 1MB. Let Page at 256K be page 0.
37 * DOSPHYPAGE(a) - DosPhyPage for Adr in 1 MB range
38 * PFT(a) - pick up ith entry in pft386[]
39 */
40
41#define PT(a) (GetPteFromIndex((a)))
42#define INDEX(a) ((((long)a)>>12) & 0x3FF)
43#define OFFSET(a) (((long)a) & 0xFFF)
44#define LIN2PHY(l) ((PT(INDEX(l)) & ~0xFFFL)+(long)OFFSET(l))
45#define DOSPHYPAGE(a) (((a)>>14)-16)
46#define PFT(a) (*(long *)(pft386+a))
47struct mappable_page {
48 unsigned short page_seg; /* segment of physical page */
49 unsigned short physical_page; /* physical page number */
50};
51
52/* Xlates DosPhyPage into an index in mappable_pages[]. */
53extern char EMM_MPindex[]; /* index from 4000H to 10000H in steps of 16K */
54extern struct mappable_page mappable_pages[];
55extern long *pft386;
56extern unsigned DMA_Pages[];
57extern DMA_PAGE_COUNT; /* size of DMA_Pages[] */
58extern unsigned physical_page_count;
59
60/* routines imported from elimtrap.asm */
61extern long GetPte(); /* get a PT entry given index */
62extern SetPte(); /* set a PT entry */
63extern unsigned GetCRSEntry(); /* get CurRegSet entry for given EmmPhyPage */
64extern long GetDMALinAdr(); /* Get Linear Adr for the DMA buffer */
65extern Exchange16K(); /* exchange page contents */
66extern FatalError();
67
68/* forward declarations */
69long GetPteFromIndex();
70
71/*
72 * SwapDMAPages()
73 * FromAdr - DMA Xfer addr
74 * Len - Xfer length
75 * bXfer - 0 for byte transfer, 1 for word transfer
76 *
77 * Check whether the DMA Xfer area starting at FromAdr is contiguous in
78 * physical memory. If it isn't, make it contiguous by exchanging pages
79 * with the DMA buffer.
80 */
81
82long SwapDMAPages(FromAdr, Len, bXfer)
83long FromAdr, Len;
84unsigned bXfer;
85{
86unsigned Index, Offset, /* components of a PTE */
87 n4KPages, /* # of 4K Pages involved in the DMA transfer */
88 PhyPages[8], /* Emm Phy page numbers involved in the DMA transfer
89 atmost 8.*/
90 DMAPageK, /* kth DMA Page - start exchanging pages from here */
91 Page, MPIndex;
92
93long FromAdr16K, /* FromAdr rounded down to 16K boundary */
94 FromAdr64_128K, /* FromAdr rounded down to 64/128K boundary */
95 ToAdr, /* Last Byte for the DMA trasfer */
96 ToAdr16K, /* ToAdr rounded down to 16K boundary */
97 ExpectedAdr,
98 PgFrame, /* PgFrame Address */
99 First64_128K_Adr, Last64_128K_Adr,/* First and Last 4K page aligned on a 64/128 boundary */
100 Adr, PhyAdr, LinAdr;
101
102int i, j, k, bSwap,
103 n16KPages; /* # of 16K Pages involved in the DMA transfer */
104
105
106 if (FromAdr < HEX256K || FromAdr >= HEX1MB)
107 return LIN2PHY(FromAdr); /* not in the EMM area */
108
109/* Since the Address and count register are programmed a byte at a time
110 * they might have invalid values in them (because of left overs).
111 * If invalid parameters, i.e. Xfer area crosses 64K or 128K boundary,or count
112 * is invalid or the DMA Xfer area has unmapped pages - just return.
113 */
114 if ((!bXfer && (FromAdr + Len) > ((FromAdr & ALIGN64K) + HEX64K)) ||
115 (bXfer && (FromAdr + Len) > ((FromAdr & ALIGN128K) + HEX128K)) ||
116 (!bXfer && Len > HEX64K) || (bXfer && Len > HEX128K))
117 return FromAdr; /* assume DMA registers not programmed yet */
118
119/* initialise PhyPages[] - unequal negative values */
120 for (i = 0; i < 8; i++)
121 PhyPages[i] = -(i+1);
122
123
124/* The DMA buffer is part of the Emm pool.
125 * Hence we can only swap pages which are 16K in size. Hence calculate
126 * n16KPages - # of 16K pages involved in the transfer.
127
128 * ToAdr - Linear Address of the last byte where the DMA transfer
129 * is to take place
130 */
131 ToAdr = FromAdr + Len - 1L;
132 FromAdr16K = FromAdr & ALIGN16K;
133 ToAdr16K = ToAdr & ALIGN16K;
134 n16KPages = ((ToAdr16K - FromAdr16K)>>14) + 1; /* (ToAdr16K-FromAdr16K)/HEX16K + 1 */
135
136/* If any unmapped page in the transfer area - assume DMA registers not
137 * fully programmed yet
138 */
139 for (i = 0, Adr = FromAdr16K; Adr <= ToAdr16K; Adr += HEX16K, i++) {
140 MPIndex = EMM_MPindex[DOSPHYPAGE(Adr)];
141 if (MPIndex == -1) /* Adr not mappable */
142 return FromAdr;
143 else {
144 PhyPages[i] = GetCRSEntry(mappable_pages[MPIndex].physical_page);
145 if (PhyPages[i] == -1) /* Adr not mapped currently */
146 return FromAdr;
147 }
148 }
149
150 for (j = 0; j < i; j++) {
151 Page = PhyPages[j];
152 for (k = j+1; k < i; k++) {
153 if (PhyPages[k] == Page)
154 FatalError("SwapDMAPages : Two Emm pages mapped to same logical page in the xfer area");
155 }
156 }
157
158/* No unmapped page in the transfer area. Assume the Address and count registers
159 * have meaningful values in them.
160 */
161 Index = INDEX(FromAdr);
162 PgFrame = PT(Index) >> 12;
163 Offset = OFFSET(FromAdr);
164 PhyAdr = (((long)PgFrame) << 12) + Offset;
165
166 if (Offset + Len <= HEX4K) /* within a page */
167 return PhyAdr;
168
169/* calculate # of 4K pages involved in the DMA transfer */
170
171 n4KPages = ((Offset + Len)>>12) + 1; /* (Offset+Len)/4096K + 1 */
172 if (((Offset + Len) % HEX4K) == 0)
173 n4KPages--;
174
175/* see if these n4KPages are physically contiguous */
176 bSwap = 0;
177 for (i = 1; i < n4KPages; i++) {
178 if ((PT(Index + i)>>12) != (PgFrame + i)) {
179 bSwap = 1;
180 break;
181 }
182 }
183
184/* Suppose the Xfer area is physically contiguous. We may still need to swap
185 * pages with the DMA buffer if the physical pages straddle a 64K/128K boundary
186 * (the DMA will wrap around in this case). DOS would have tried to fix this
187 * but it would have split the Linear Address - this is of very little use.
188 *
189 * if (!bSwap && straddling 64/128K boundary) set bSwap;
190 */
191 if (!bSwap) { /* the DMA Pages are contiguous, any straddling ? */
192 if (!bXfer) { /* byte transfer */
193 First64_128K_Adr = PT(Index) & ALIGN64K;
194 Last64_128K_Adr = PT(Index+n4KPages-1) & ALIGN64K;
195 }
196 else { /* word transfer */
197 First64_128K_Adr = PT(Index) & ALIGN128K;
198 Last64_128K_Adr = PT(Index+n4KPages-1) & ALIGN128K;
199 }
200
201 if (First64_128K_Adr != Last64_128K_Adr)
202 bSwap = 1;
203 }
204
205 if (!bSwap)
206 return PhyAdr;
207
208/* The DMA transfer area is not contiguous. The DMA buffer is part of the Emm
209 * pool. Hence we can only swap pages which are 16K in size. n16KPages is the
210 * # of 16K pages involved in the transfer.
211 */
212
213/* Round down FromAdr to 64/128K boundary */
214 if (bXfer) /* word transfer ? */
215 FromAdr64_128K = FromAdr & ALIGN128K; /* Align on 128K boundary */
216 else
217 FromAdr64_128K = FromAdr & ALIGN64K; /* Align on 64K boundary */
218
219/* Swap pages so that the DMA Xfer area is physically contiguous.
220
221 | | | |
222 FromAdr ->| | | |
223 | | | |
224 | | | |
225 FromAdr16K ->| | - - - DMAPage[k] -->| |
226 | | | |
227 | | | |
228FromAdr64_128k-| | DMAPage[0] -->| |
229 ---------- ----------
230
231 DMA transfer area starts at FromAdr.
232 Map kth DMA page to FromAdr16K and so on until all the transfer area is mapped
233
234 */
235
236/* Linear Adr of user page which has to be relocated */
237 LinAdr = FromAdr16K;
238
239/* corresponding DMA Page - k value in the above figure */
240 DMAPageK = (FromAdr16K - FromAdr64_128K) >> 14;
241
242 ExpectedAdr = PFT(DMA_Pages[DMAPageK]);
243
244 if (DMAPageK + n16KPages > DMA_PAGE_COUNT)
245 FatalError("Insufficient DMA pages in the DMA Buffer");
246
247 for (k = DMAPageK; k < DMAPageK + n16KPages; k++, LinAdr += HEX16K,
248 ExpectedAdr += HEX16K) {
249 /* Already mapped correctly ? */
250 if (LIN2PHY(LinAdr) == ExpectedAdr)
251 continue;
252 /* Swap the 16K page(4 4K pages) at LinAdr with the kth DMA Page */
253 SwapAPage(LinAdr, k);
254 }
255
256 return LIN2PHY(FromAdr);
257}
258
259/* Swap the 16K page(4 4K pages) at LinAdr with the kth DMA Page.
260 * Update the Emm Data Structures to reflect this remapping.
261 * Update the Page Table too.
262 */
263SwapAPage(LinAdr, k)
264long LinAdr;
265unsigned k;
266{
267unsigned DosPhyPage, /* each page 16K in size, page at 256K is Page 0 */
268 EmmPhyPage, /* Phy page numbering according to Emm */
269 UserPFTIndex; /* index into pft386 for Emm phy page at LinAdr */
270
271long DMAPhyAdr, DMALinAdr;
272int i, j;
273
274/* Updating Emm data structures */
275
276/* Find the pft386 entry for LinAdr */
277 DosPhyPage = DOSPHYPAGE(LinAdr); /* Page at 256K is page zero */
278 EmmPhyPage = mappable_pages[EMM_MPindex[DosPhyPage]].physical_page;
279
280/* get the CurRegSet entry for this physical page. */
281 UserPFTIndex = GetCRSEntry(EmmPhyPage);
282
283 if (UserPFTIndex == -1)
284 FatalError("Cannot find PFT386 entry for EMM page corresponding to LinAdr");
285
286/* exchange pft386 entries at UserPFTIndex and DMA_Pages[k] */
287
288 DMAPhyAdr = PFT(DMA_Pages[k]);
289 PFT(DMA_Pages[k]) = PFT(UserPFTIndex);
290 PFT(UserPFTIndex) = DMAPhyAdr;
291
292/* Fix Page table entries .
293 * The contents of the user page and DMA buffer page are exchanged always.
294 * - because a mapping for this page may exist in a saved context,
295 * - can do a one way copy if the non-existence of such a mapping is detected
296 * by scanning emm_pages[]. Will optimize this later. 8/12/88 - JHB
297 *
298 * The PT entry for the user page has to be updated.
299 * There may or may not exist a PT entry for the DMA page. There exists
300 * an entry only if there exists a mapping in the CurRegSet. If there exists
301 * an entry it should be updated too.
302 */
303
304/* Does PT Entry exist for the DMA buffer below 1 MB? */
305
306 for (i = 0; i < physical_page_count; i++) {
307 if (GetCRSEntry(i) == DMA_Pages[k])
308 break;
309 }
310
311 if (i == physical_page_count) {
312 /* No Phy page mapped to the DMA page - so no pte to be updated for DMA Page */
313 Exchange16K(LinAdr, GetDMALinAdr(DMAPhyAdr));
314 UpdateUserPTE(LinAdr, UserPFTIndex);
315 }
316 else {
317 /* ith EmmPhyPage mapped to DMA buffer
318 * Scan mappable_pages[] array and find the Linear address that maps to it.
319 */
320 for (j = 0; j < MAX_PHYS_PAGES; j++) {
321 if (mappable_pages[j].physical_page == i)
322 break;
323 }
324 if (j == MAX_PHYS_PAGES)
325 FatalError(); /* invalid Phy page # - doesn't exist in mappable_pages[] */
326 else
327 DMALinAdr = ((long )mappable_pages[j].page_seg) << 4;
328
329 Exchange16K(LinAdr, DMALinAdr);
330 ExchangePTEs(LinAdr, DMALinAdr);
331 }
332
333/* UserPFTIndex is present in DMA_Pages[] we should exchange the entries in
334 * DMA_Pages[] */
335 for (i = 0; i < DMA_PAGE_COUNT; i++) {
336 if (DMA_Pages[i] == UserPFTIndex) {
337 DMA_Pages[i] = DMA_Pages[k];
338 break;
339 }
340 }
341
342/* Now, DMA_Pages[k] has a different index into the pft386[] array */
343 DMA_Pages[k] = UserPFTIndex;
344}
345
346/* Update PT entry for LinAdr to map to pft386[UserPFTIndex] */
347UpdateUserPTE(LinAdr, UserPFTIndex)
348long LinAdr;
349unsigned UserPFTIndex;
350{
351unsigned index;
352long pte;
353
354 index = INDEX(LinAdr);
355
356 pte = PFT(UserPFTIndex) & ~0xfff; /* Pg Frame Adr in 20 MSBs */
357
358 SetPteFromIndex(index, pte);
359 SetPteFromIndex(index+1, pte+HEX4K);
360 SetPteFromIndex(index+2, pte+HEX4K*2);
361 SetPteFromIndex(index+3, pte+HEX4K*3);
362}
363
364/* exchange 4 ptes at LinAdr1 and LinAdr2 */
365ExchangePTEs(LinAdr1, LinAdr2)
366long LinAdr1, LinAdr2;
367{
368unsigned index1, index2;
369long tPte;
370int i;
371
372 index1 = INDEX(LinAdr1);
373 index2 = INDEX(LinAdr2);
374
375 for (i = 0; i < 4; i++) {
376 tPte = PT(index1+i);
377 SetPteFromIndex(index1+i, PT(index2+i));
378 SetPteFromIndex(index2+i, tPte);
379 }
380}
381
382/* sanity check on the index, and then call GetPte */
383long GetPteFromIndex(index)
384unsigned index;
385{
386unsigned i;
387long PhyAdr;
388
389 PhyAdr = ((long) index) << 12;
390
391 if (PhyAdr < HEX256K || PhyAdr >= HEX1MB)
392 return (PhyAdr);
393
394 i = EMM_MPindex[DOSPHYPAGE(PhyAdr)];
395
396 if (i != -1)
397 return GetPte(index);
398 else
399 return PhyAdr;
400}
401
402/* sanity check on the index and then call SetPte */
403SetPteFromIndex(index, pte)
404unsigned index;
405long pte;
406{
407unsigned i;
408long PhyAdr;
409
410 PhyAdr = ((long) index) << 12;
411
412 if (PhyAdr < HEX256K || PhyAdr >= HEX1MB)
413 return;
414
415 i = EMM_MPindex[DOSPHYPAGE(PhyAdr)];
416
417 if (i != -1)
418 return SetPte(index, pte);
419 else
420 return;
421}
422
423
424
425 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/MAPLIN.ASM b/v4.0/src/MEMM/MEMM/MAPLIN.ASM
new file mode 100644
index 0000000..d37d9ac
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MAPLIN.ASM
@@ -0,0 +1,172 @@
1
2
3page 58,132
4;******************************************************************************
5 title MapLinear - map linear address according to page tables
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: MapLinear
13;
14; Version: 0.04
15;
16; Date: June 2, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/08/86 Original
27; 06/28/86 0.02 Name changed from MEMM386 to MEMM
28; 07/05/86 0.04 DiagByte moved to _DATA
29; 07/06/86 0.04 changed assume to DGROUP
30;
31;******************************************************************************
32;
33; Functional Description:
34; This routine in this module takes a "virtual" addresses specified by
35; a virtual mode processs and "maps" it to the corresponding linear address
36; according to the linear to physical mapping in the page tables.
37; This file also contains a routine to do the inverse mapping.
38;
39;
40;******************************************************************************
41.lfcond ; list false conditionals
42.386p
43 page
44;******************************************************************************
45; P U B L I C D E C L A R A T I O N S
46;******************************************************************************
47;
48 public MapLinear
49 public UnMapLinear
50;
51
52 page
53;******************************************************************************
54; I N C L U D E F I L E S
55;******************************************************************************
56
57 include vdmseg.inc
58 include vdmsel.inc
59 include instr386.inc
60 include oemdep.inc
61
62;******************************************************************************
63; E X T E R N A L R E F E R E N C E S
64;******************************************************************************
65;
66;******************************************************************************
67; C O D E S E G M E N T
68;******************************************************************************
69_TEXT segment
70 assume cs:_TEXT, ds:DGROUP, es:DGROUP
71 page
72;******************************************************************************
73; MapLinear - maps a linear address to it's "true" linear address.
74;
75; ENTRY: PROTECTED MODE ONLY
76; EAX = 32 bit linear address
77;
78; EXIT: EAX = 32 bit "mapped" linear address
79;
80; USED: none.
81;
82; The page dir and table set up by this routine maps the linear
83; addresses for Virtual mode programs into physical addresses using
84; the following scheme. Note that "high" memory is mapped to the
85; range starting at 16 Meg so that the page tables can be shorter.
86;
87; Linear Addr Physical Addr
88; 00000000h - 000FFFFFh 00000000h - 000FFFFFh
89; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound)
90; 00110000h - 010FFFFFh 00100000h - 00FFFFFFh (top 15Meg of phys)
91ifndef NOHIMEM
92; 01010000h - 0101FFFFh xxxx0000h - xxxxFFFFh ("high" memory)
93; xxxx is mapped by Map_Lin_OEM in OEMPROC module
94endif
95;
96; True Linear is same as linear in our new mapping scheme. So except
97; for the "high" memory we have the true linear returned being the same
98; as linear. The new mapping is:
99;
100; Linear Addr Physical Addr
101; 00000000h - 000FFFFFh 00000000h - 000FFFFFh
102; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound)
103; 00110000h - 00ffffffh 00110000h - 00ffffffh (top 15Meg of phys)
104; 01000000h - 0100FFFFh xxxx0000h - xxxxFFFFh ("high" memory)
105; xxxx is mapped by Map_Lin_OEM in OEMPROC module
106;
107;******************************************************************************
108MapLinear proc near
109;
110 call Map_Lin_OEM ;Q: Special mapping done by OEM routines?
111 jc ML_Exit ; Y: AX = mapped address
112 ; N: Do standard mapping
113
114;
115; the routine here is to be executed to get the true linear address. Since
116; it is a 1 - 1 mapping we have no code here
117;
118ML_exit:
119 ret
120;
121MapLinear endp
122
123
124;******************************************************************************
125; UnMapLinear - maps a "true" linear address to it's linear address.
126;
127; ENTRY: EAX = 32 bit "mapped" linear address
128;
129; EXIT: EAX = 32 bit linear address
130;
131; USED: none.
132;
133; The page dir and table set up maps the linear
134; addresses for Virtual mode programs into physical addresses using
135; the following scheme.
136; Linear Addr Physical Addr
137; 00000000h - 000FFFFFh 00000000h - 000FFFFFh
138; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound)
139; 00110000h - 010FFFFFh 00100000h - 00FFFFFFh (top 15Meg of phys)
140ifndef NOHIMEM
141; 01010000h - 0101FFFFh xxxx0000h - xxxxFFFFh (high memory)
142; xxxx is mapped by UMap_Lin_OEM in OEMPROC module
143endif
144;
145; Our new mapping scheme is:
146;
147; Linear Addr Physical Addr
148; 00000000h - 000FFFFFh 00000000h - 000FFFFFh
149; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound)
150; 00110000h - 00ffffffh 00110000h - 00ffffffh (top 15Meg of phys)
151; 01000000h - 0100FFFFh xxxx0000h - xxxxFFFFh ("high" memory)
152; xxxx is mapped by Map_Lin_OEM in OEMPROC module
153;
154;******************************************************************************
155UnMapLinear proc near
156;
157 cmp eax,01000000 ;
158 jb UML_mask ; N: chk for < 1 meg
159 call UMap_Lin_OEM ; Y: set EAX to physical address for diags
160 jmp short UML_exit
161
162UML_mask:
163UML_exit:
164 ret
165;
166UnMapLinear endp
167
168
169_TEXT ends
170
171 end
172
diff --git a/v4.0/src/MEMM/MEMM/MEMM386.ASM b/v4.0/src/MEMM/MEMM/MEMM386.ASM
new file mode 100644
index 0000000..d2b6d26
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MEMM386.ASM
@@ -0,0 +1,561 @@
1
2
3 page 58,132
4;******************************************************************************
5 title MEMM386 - main module for MEMM
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: MEMM386 - main module
13;
14; Version: 0.04
15;
16; Date: May 24,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 04/24/86 Original From EMML LIM driver.
27; 06/26/86 0.02 Put CLD in Inst_Chk
28; 06/28/86 0.02 Name change from MEMM386 to MEMM.
29; 07/05/86 0.04 Changed segment to R_CODE
30; 06/07/88 exclude VDISK header info's since we are
31; using INT-15 method now (Paul Chan)
32; 06/21/88 Removed VDISK stuff.
33;
34;******************************************************************************
35; Functional Description:
36; MEMM is an Expanded Memory Manager which implements expanded memory
37; on the MICROSOFT 386 machine. MEMM uses Virtual mode and paging on
38; the 386 to make Extended memory useable as expanded memory. The are two
39; basic functional parts of MEMM; the Virtual DOS Monitor (VDM) and the
40; Expanded Memory Manager (EMM). VDM simulates the 386 Real mode under the
41; 386 Virtual mode. EMM provides the software functionality for a EMM as
42; described in the Lotus-Intel-Microsoft (LIM) specification for expanded
43; memory.
44; This module contains the Device Driver header, stategy, and interrupt
45; routines required by a LIM standard EMM.
46; This device driver is a .EXE file and may be invoked as a DOS utility
47; program as well as loaded as a device driver. When it is loaded as a
48; DOS utility, MEMM has three command line options: ON,OFF and AUTO.
49; The OFF options disables MEMM and exits to MS-DOS in real mode.
50; The ON option enables MEMM and exits to MS-DOS in virtual mode (only
51; if the MEMM.EXE driver has been loaded). The AUTO option puts
52; MEMM in "auto mode". In this mode, MEMM will enable and disable
53; itself automatically, depending on accesses to the EMM functions.
54; The general device driver CONFIG.SYS options are described below.
55;
56; Syntax:
57;
58; device=[d]:[<path>]MEMM.EXE [SIZE] [Mx] [ON | OFF | AUTO]
59;
60;
61; NOTE: SUNILP - See if we need the /X option for excluding segments from
62; being mappable. This turned out to be quite useful in ps2emm and since
63; here we are dealing with different hardware this option may turn out
64; essential here**** WISH001
65;
66; The following sections describe the optional arguments which the
67; user may specify for MEMM.EXE at load time (in the CONFIG.SYS
68; file). These arguments are placed after the device driver name
69; in the CONFIG.SYS file.
70;
71; MEMM arguments in the CONFIG.SYS file must be separated by spaces
72; or tabs. Arguments may appear in any order; however, any redundant
73; or excessive instances are ignored and only the first valid instance
74; of an argument is used. Invalid or extraneous arguments produce an
75; error message.
76;
77; [SIZE]
78;
79; The argument SIZE is the amount of expanded memory desired in
80; K bytes. The default amount of expanded memory, 256K, is available
81; without using any extended memory. To use more than 256K of
82; expanded memory, the 386 system must have extended memory. When
83; If there is not enough memory available
84; to provide SIZE kbytes of expanded memory, MEMM will adjust SIZE to
85; provide as much expanded memory as possible.
86;
87; - The valid range for SIZE is 16K - 8192K. Value outside this range
88; are converted to the default of 256K.
89;
90; - If SIZE is not a multiple of 16K (size of an EMM page), then SIZE
91; is rounded down to the nearest multiple of 16K.
92;
93; [Mx]
94;
95; The argument [Mx] specifies the address of the 64k EMM page frame.
96; This argument is optional since MEMM can choose an appropriate
97; location for the page frame when it is loaded. To choose a location
98; the 386 EMM driver scans memory addresses above video memory for
99; an appropriate 64K address range for the EMM page frame. For a
100; default page frame base address MEMM looks for option ROMs and
101; RAM in the EMM addressing range and chooses a 64K slot of memory
102; for the page frame which apparently does not confict with existing
103; memory. The user may override the 386 EMM driver's choice by
104; specifying the beginning address with the Mx argument. If the
105; user specifies a page frame base address which conflicts with an
106; option ROM or RAM, MEMM displays a warning message and uses the
107; specified page frame base address.
108;
109; The following options are possible:
110; Page Frame Base Address
111; M1 => 0C0000 Hex
112; M2 => 0C4000 Hex
113; M3 => 0C8000 Hex
114; M4 => 0CC000 Hex
115; M5 => 0D0000 Hex
116;
117; [ ON | OFF | AUTO ]
118;
119; The argument [ON | OFF | AUTO] specifies the state of the 386 when
120; MEMM returns to DOS after the driver INIT routine finishes. If this
121; argument is ON, then MEMM returns to DOS in virtual mode and
122; expanded memory is available. If this argument is OFF, then MEMM
123; returns to DOS in real mode and expanded memory is not available
124; until MEMM is turned ON. The default for this argument is AUTO
125; mode. In AUTO mode, the MEMM.EXE device driver will exit to
126; DOS in the OFF state; afterwards, MEMM will enable and disable
127; itself automatically. In the AUTO mode, MEMM will be enabled
128; only while the expanded memory manager is in use.
129;
130;
131;******************************************************************************
132.lfcond
133.386p
134 page
135;******************************************************************************
136; P U B L I C D E C L A R A T I O N S
137;******************************************************************************
138
139;
140; R_CODE publics
141;
142 public strategy
143 public interrupt
144 public MEMM_Entry
145
146;
147; _TEXT publics
148;
149 public ELIM_EXE ; .EXE execution entry point
150 public ELIM_link
151 public Inst_chk ; Check to see if MEMM already installed
152 public Inst_chk_f ; Far call version of above
153
154 page
155;******************************************************************************
156; L O C A L C O N S T A N T S
157;******************************************************************************
158;
159 include driver.equ
160 include driver.str
161 include vdmseg.inc
162
163FALSE equ 0
164TRUE equ not FALSE
165
166MS_DOS equ 21h ; DOS interrupt
167GET_PSP equ 62h ; get program segment prefix
168
169NULL EQU 0FFFFH ;Null address pointer
170
171dospsp_str struc
172 db 80h dup (?)
173cmd_len db ? ; length of command line
174cmd_line db ? ; commande line
175dospsp_str ends
176
177;******************************************************************************
178; E X T E R N A L R E F E R E N C E S
179;******************************************************************************
180;
181abs0 segment use16 at 0000h
182
183 org 67h*4 ; EMM function interrupt
184int67 dw ? ; offset of vector
185 dw ? ; segment of vector
186abs0 ends
187
188LAST segment
189extrn Init_MEMM386:far ; initializes VDM,EMM, and driver
190LAST ends
191
192R_CODE segment
193extrn ELIM_Entry:far ; general entry point for MEMM functions
194R_CODE ends
195
196_TEXT segment
197extrn onf_func:near ; perform on, off, or auto checking for elim.exe
198_TEXT ends
199
200 page
201;******************************************************************************
202; S E G M E N T D E F I N I T I O N
203;******************************************************************************
204;
205;******************************************************************************
206;
207; R_CODE Code Segment
208;
209;******************************************************************************
210;
211R_CODE segment
212 assume cs:R_CODE, ds:R_CODE, es:R_CODE, ss:R_CODE
213
214Start:
215;******************************************************************************
216; Device driver header
217;******************************************************************************
218;
219 DW NULL ;Null segment address
220 DW NULL ;Null offset address
221 DW CHAR_DEV+IOCTL_SUP ;Attribute - Char
222 DW OFFSET STRATEGY ;Strategy routine entry
223 DW OFFSET INTERRUPT ;Interrupt routine entry
224 DB 'EMMXXXX0' ;Character device name
225;
226;******************************************************************************
227; GENERAL FUNCTIONS ENTRY POINT
228; R_CODE:ELIM_Entry is a entry point for executing general MEMM
229; functions. (e.g. ON, OFF function).
230;******************************************************************************
231;
232MEMM_Entry dw offset ELIM_Entry ; general entry point
233
234;******************************************************************************
235; MEMM signature
236;******************************************************************************
237memmsig db 'MICROSOFT EXPANDED MEMORY MANAGER 386'
238SIG_LENGTH equ (this byte - memmsig)
239
240 page
241;******************************************************************************
242; L O C A L D A T A A R E A
243;******************************************************************************
244
245;
246; Define the command dispatch table for the driver functions
247;
248Cmd_Table LABEL NEAR
249 DW Init_Call ;0 - Initialization
250 DW Null_Exit ;1 - Media Check
251 DW Null_Exit ;2 - Get BPB
252 DW Null_Exit ;3 - IOCTL input
253 DW Null_Exit ;4 - Input (Destructive)
254 DW Null_Exit ;5 - No wait input
255 DW Null_Exit ;6 - Input status
256 DW Null_Exit ;7 - Input buffer flush
257 DW Null_Exit ;8 - Output (Write)
258 DW Null_Exit ;9 - Output with verify
259 DW Null_Exit ;A - Output status
260 DW Null_Exit ;B - Output buffer flush
261 DW Null_Exit ;C - IOCTL output
262TBL_LENGTH EQU (THIS BYTE-CMD_TABLE)/2 ;Dispatch table length
263
264 public ReqPtr
265ReqPtr label dword ; dword ptr to Request Header
266ReqOff dw 0 ; saved offset of Request Header
267ReqSeg dw 0 ; saved segment of Request Header
268
269 page
270;******************************************************************************
271; Strategy - strategy routine for MEMM
272;
273; ENTRY: ES:BX = pointer to Request Header
274;
275; EXIT: CS:ReqOff, CS:ReqSeg - saved pointer to Request Header
276;
277; USED: none
278;
279;******************************************************************************
280Strategy proc far
281 mov CS:[ReqOff],bx ;Save header offset
282 mov CS:[ReqSeg],es ;Save header segment
283 ret
284Strategy endp
285
286;******************************************************************************
287; Interrupt - device driver interrupt routine for MEMM
288;
289; ENTRY: CS:ReqPtr = pointer to request header.
290;
291; EXIT: Request completed.
292;
293; USED: none
294;
295;******************************************************************************
296Interrupt proc far
297 push ax
298 push bx
299 push cx
300 push dx
301 push si
302 push di
303 push ds
304 push es
305 cld ;All strings forward
306 lds bx,CS:[ReqPtr] ;DS:BX pts to Request Header
307 mov al,[bx.COMMAND_CODE] ;Get the command code
308 cmp al,TBL_LENGTH ;Check for validity
309 jae Invalid ;Jump if command invalid
310 cbw ;Command to a full word
311 shl ax,1 ;Compute dispatch index
312 mov si,OFFSET Cmd_Table ;Point to dispatch table
313 add si,ax ;Index based on command
314 call CS:[si] ;Call correct routine
315
316;
317; ENTRY: AX = Status field for Request Header
318;
319Finish:
320 lds bx,CS:[ReqPtr] ;Get request header ptr.
321 or ah,DON ;Set done bit in status
322 mov DS:[bx.STATUS_WORD],ax ;Save status in header
323 pop es ;Restore the ES register
324 pop ds
325 pop di
326 pop si
327 pop dx
328 pop cx
329 pop bx
330 pop ax
331 ret
332Invalid:
333 mov al,UNK_COMMAND ; unknown command
334 mov ah,ERR ; error
335 stc
336 jmp SHORT Finish ;Go return to caller
337Interrupt endp
338
339;******************************************************************************
340; Null_Exit: do nothing
341;
342; ENTRY: DS:BX pts to request header
343;
344; EXIT: No error returned.
345; CLC
346;
347;******************************************************************************
348Null_Exit proc near
349;
350 xor ax,ax
351 clc
352 ret
353;
354Null_Exit endp
355
356;******************************************************************************
357; Init_Call - call initialization routine
358;
359; ENTRY: DS:BX pts to request header
360;
361; EXIT: AX = status field for request header
362;
363;******************************************************************************
364Init_Call proc near
365;
366 call Init_MEMM386
367 ret
368;
369Init_Call endp
370
371;******************************************************************************
372 db 'SBP'
373 db 'BMT'
374;******************************************************************************
375;
376
377R_CODE ends
378
379 page
380;******************************************************************************
381;
382; _TEXT Code Segment
383;
384;******************************************************************************
385_TEXT segment
386 assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT
387
388FarLink dd 0 ; far pointer to installed memm386 entry point
389 ; OK as writeable because it is only used
390 ; during .EXE execution.
391
392;
393rh db 23,0,0,0,0,8 dup (0)
394 db 10 dup (0)
395;
396MEMM:
397;******************************************************************************
398;
399; ELIM_EXE - .EXE entry point - when MEMM.EXE is invoked as a DOS
400; utility.
401;
402;******************************************************************************
403
404;------------------------------------------------------------------------------
405; NOTE** SUNILP .. Paulch changed this to load it as an terminate and stay
406; resident. This entry should only be to turn an existing MEMM ON
407; OFF or AUTO. Once the driver is debugged change this back to the
408; original code given here in comments. Also remove the above rh
409; storage block. WISH002
410;ELIM_EXE proc near
411;;
412; push cs
413; pop ds ; ds = cs
414; mov ah,GET_PSP ; get segment of PSP
415; int MS_DOS
416; mov es,bx ; DOS call returned seg in bx
417; mov di,offset cmd_line ; es:di = command line
418; call onf_func ; look for on, off, or auto
419; mov ax,4c00h ; exit to DOS
420; int MS_DOS
421;;
422;ELIM_EXE endp
423;;
424;------------------------------------------------------------------------------
425
426ELIM_EXE proc near
427;
428 extrn exe_stack:byte
429
430 push seg STACK
431 pop ss
432 mov sp, offset STACK:exe_stack
433 push cs
434 pop ds
435 mov ah,GET_PSP
436 int MS_DOS
437 mov es,bx
438 mov di,offset cmd_line
439
440 mov bx,seg rh
441 mov ds,bx
442 mov bx,offset rh
443 mov [bx+20],es
444 mov [bx+18],di
445
446 push ds
447 pop es
448 call Strategy
449 call Interrupt
450
451 mov bx,seg rh
452 mov es,bx
453 mov bx,offset rh
454 mov dx,es:[bx+16]
455 sub dx,es:[bx+20]
456 mov ah,31h
457 int 21h
458;
459
460; push cs
461; pop ds ; ds = cs
462; mov ah,GET_PSP ; get segment of PSP
463; int MS_DOS
464; mov es,bx ; DOS call returned seg in bx
465; mov di,offset cmd_line ; es:di = command line
466; call onf_func ; look for on, off, or auto
467 mov ax,4c00h ; exit to DOS
468 int MS_DOS
469;
470ELIM_EXE endp
471;
472;******************************************************************************
473; Inst_chk_f - call Inst_chk
474;
475; ENTRY: see Inst_chk
476;
477; EXIT: see Inst_chk
478;
479; USED: none
480;
481;******************************************************************************
482Inst_chk_f proc far
483 call Inst_chk
484 ret
485Inst_chk_f endp
486
487;******************************************************************************
488; Inst_chk - Check to see if MEMM is already installed
489;
490; ENTRY: int 67 vector
491;
492; EXIT: ax = 0 if not already installed
493; ax = 1 if MEMM is already installed
494; _TEXT:[FarLink] = far address for installed MEMM entry point
495;
496; USED: none
497;
498;******************************************************************************
499Inst_chk proc near
500 push di ; save di
501 push si ; and si
502 push ds ; and ds
503 push es ; and es
504 push cx ; and cx
505;
506 xor ax,ax ; put segment 0000h in ds
507 mov ds,ax
508 ASSUME DS:abs0 ; assume ds is abs0
509 mov ax,[int67+2] ; get segment pointed to by int 67
510 mov es,ax
511 ASSUME ES:R_CODE
512
513 push seg R_CODE
514 pop ds ; set DS = R_CODE
515 assume DS:R_CODE ; update assume
516
517 mov di,offset memmsig ; memm386 signature
518 mov si,di ; save for source string
519 xor ax,ax ; initialize to not found
520 mov cx,SIG_LENGTH ; length to compare
521 cld ; strings foward
522 repe cmpsb ; q: is the memm386 signature out there?
523 jne not_inst ; n: return zero
524 inc ax ; y: return one
525 mov word ptr CS:[FarLink+2],es ; set segment of far call
526 mov cx,ES:[MEMM_Entry] ; get offset for far call
527 mov word ptr CS:[FarLink],cx ; set offset of far call
528not_inst:
529
530 ASSUME DS:_TEXT, ES:_TEXT
531
532 pop cx
533 pop es
534 pop ds
535 pop si
536 pop di
537 ret
538Inst_chk endp
539
540;******************************************************************************
541; ELIM_link - Link to Installed MEMM's ELIM_Entry
542;
543; ENTRY: see ELIM_Entry
544; and
545; _TEXT:[FarLink] = far address of installed MEMM ELIM_Entry
546;
547; EXIT: see ELIM_Entry
548;
549; USED: none
550;
551;******************************************************************************
552ELIM_link proc near
553 call CS:[FarLink]
554 ret
555ELIM_link endp
556
557
558_TEXT ends
559
560 end MEMM
561 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/MEMMCOM.ASM b/v4.0/src/MEMM/MEMM/MEMMCOM.ASM
new file mode 100644
index 0000000..b92cfdb
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MEMMCOM.ASM
@@ -0,0 +1,243 @@
1
2
3 page 58,132
4;******************************************************************************
5 title MEMMCOM - main module for MEMM.COM
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.COM - MICROSOFT Expanded Memory Manager 386 Utility
11;
12; Module: MEMMCOM - main module for MEMM.COM
13;
14; Version: 0.02
15;
16; Date: June 4, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/04/86 Original
27; 06/21/86 0.02 Added CLD to Inst_Chk
28; 06/28/86 0.02 Name change from MEMM386.COM to MEMM.COM
29;
30;******************************************************************************
31;
32; Functional Description:
33; MEMM.COM which allows the user to poll or set the operating mode
34; of the MEMM device driver.
35; Syntax:
36; MEMM [ ON | OFF | AUTO ]
37;
38; If the user specifies no arguments, MEMM.COM will return the
39; current mode of the MEMM device driver.
40;
41; ON
42; If the user specifies ON, MEMM.COM enables the MEMM driver;
43; expanded memory is available and the processor is in virtual mode.
44;
45; OFF
46; If the user specifies OFF, MEMM.COM disables the MEMM driver;
47; expanded memory is not available and the processor is in real mode.
48;
49; AUTO
50; If the user specifies AUTO, MEMM.COM enables the MEMM driver's auto
51; mode. In auto mode, the driver will enable and disable itself
52; "automatically" (depending on accesses to the EMM functions).
53;
54;******************************************************************************
55.lfcond ; list false conditionals
56.386p
57 page
58;******************************************************************************
59; P U B L I C D E C L A R A T I O N S
60;******************************************************************************
61;
62 public EMM386
63 public Inst_chk
64 public ELIM_link
65;
66;******************************************************************************
67; E X T E R N A L R E F E R E N C E S
68;******************************************************************************
69_TEXT segment byte use16 public 'CODE'
70 extrn onf_func:near
71_TEXT ends
72abs0 segment use16 at 0000h
73
74 org 67h*4 ; EMM function interrupt
75int67 dw ? ; offset of vector
76 dw ? ; segment of vector
77abs0 ends
78
79
80 page
81;******************************************************************************
82; L O C A L C O N S T A N T S
83;******************************************************************************
84;
85
86MSDOS equ 21h ; MS-DOS function call
87
88;
89; Device driver header for MEMM
90;
91emm_hdr STRUC
92;
93 DW ? ;Null segment address
94 DW ? ;Null offset address
95 DW ? ;Attribute - Char
96 DW ? ;Strategy routine entry
97 DW ? ;Interrupt routine entry
98 DB 'EMMXXXX0' ;Character device name
99;
100; GENERAL FUNCTIONS ENTRY POINT
101; ELIM_Entry is a entry point for executing general MEMM
102; functions. (e.g. ON, OFF function).
103;
104ELIM_Entry_off dw ? ; general entry point
105
106;
107; MEMM signature
108;
109memmsig db ? ; MEMM signature
110
111emm_hdr ends
112
113;******************************************************************************
114; S E G M E N T D E F I N I T I O N
115;******************************************************************************
116;
117_TEXT segment byte use16 public 'CODE'
118 assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT
119 org 81h
120cmd_line dw ? ; pointer to command line
121;
122;******************************************************************************
123; M O D U L E E N T R Y P O I N T
124;******************************************************************************
125;
126; Standard .COM entry conditions are assumed
127;
128 org 100h
129EMM386 proc near
130 jmp start
131;******************************************************************************
132; L O C A L D A T A A R E A
133;******************************************************************************
134;
135
136oursig db 'MICROSOFT EXPANDED MEMORY MANAGER 386'
137SIG_LENGTH equ (this byte - oursig)
138;
139; define double word to store segment/offset of status routine for far call
140;
141status_loc label dword
142entry_off dw 0 ; store offset for far call
143entry_seg dw 0 ; store segment for far call
144;
145
146start:
147 push cs
148 pop ds
149 push cs
150 pop es
151
152;
153 cli
154 mov sp,offset Stack_Top
155 sti
156;
157 cld
158;
159 mov di,offset cmd_line ; es:di = command line pointer
160 call onf_func ; do the on/off function
161
162 mov ax,4C00h
163 int MSDOS ; exit to DOS
164
165EMM386 endp
166
167page
168;******************************************************************************
169; ELIM_link - Call ELIM_Entry status routine via the status_loc
170;
171; ENTRY: [status_loc] contains the far address
172;
173; EXIT: ?
174;
175; USED: none
176;
177;******************************************************************************
178ELIM_link proc near
179 call status_loc
180 ret
181ELIM_link endp
182page
183;******************************************************************************
184; Inst_chk - Check to see if MEMM is already installed
185;
186; ENTRY: int 67 vector
187;
188; EXIT: ax = 0 if not already installed
189; ax = 1 if MEMM is already installed
190; If MEMM is installed, then
191; [entry_seg] = segment of driver header
192; [entry_off] = offset of status routine in MEMM
193;
194; USED: none
195;
196;******************************************************************************
197Inst_chk proc near
198 push di ; save di
199 push si ; and si
200 push ds ; and ds
201 push es ; and es
202 push cx ; and cx
203;
204 xor ax,ax ; put segment 0000h in ds
205 mov ds,ax
206 assume ds:abs0 ; assume ds is abs0
207 mov ax,[int67+2] ; get segment pointed to by int 67
208 mov es,ax
209
210 assume ds:_TEXT ; update assume
211 push cs
212 pop ds ; set DS = _TEXT
213
214 mov di,offset memmsig ; MEMM signature
215 mov si,offset oursig ; point to our signature
216 xor ax,ax ; initialize to not found
217 mov cx,SIG_LENGTH ; length to compare
218 cld ; strings foward
219 repe cmpsb ; q: is the MEMM signature out there?
220 jne not_inst ; n: return zero
221 inc ax ; y: return one
222 mov [entry_seg],es ; save segment for far call
223 xor di,di
224 mov cx,es:[ELIM_Entry_off] ; save offset for far call
225 mov [entry_off],cx
226not_inst:
227 pop cx
228 pop es
229 pop ds
230 pop si
231 pop di
232 ret
233Inst_chk endp
234
235
236 db 100h dup (0)
237Stack_Top:
238 db 0
239
240_TEXT ends
241
242 end EMM386
243 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/MEMMINC.ASM b/v4.0/src/MEMM/MEMM/MEMMINC.ASM
new file mode 100644
index 0000000..1eb897f
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MEMMINC.ASM
@@ -0,0 +1,80 @@
1
2
3 page 58,132
4;******************************************************************************
5 title MEMMINC.ASM - lists all MEMM include files
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM - MICROSOFT Expanded Memory Manager
11;
12; Module: MEMMINC.ASM - lists all MEMM include files
13;
14; Version: 0.02
15;
16; Date: June 14, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 06/25/86 original
27; 06/28/86 0.02 Name change from MEMM386 to MEMM
28;
29;******************************************************************************
30; Functional Description:
31; This module includes all MEMM include files and will
32; provide a listing of all when assembled to produce a listing file.
33;
34;******************************************************************************
35.lfcond
36.386p
37
38;******************************************************************************
39; I N C L U D E S
40;******************************************************************************
41INC_LIST EQU 1 ; list include files
42
43 page
44 include ASCII_SM.EQU
45 page
46 include DRIVER.EQU
47 page
48 include PIC_DEF.EQU
49 page
50 include ROMSTRUC.EQU
51 page
52 include ROMXBIOS.EQU
53
54 page
55 include DESC.INC
56 page
57 include ELIM.INC
58 page
59 include EMM386.INC
60 page
61 include INSTR386.INC
62 page
63 include KBD.INC
64 page
65 include LOADALL.INC
66 page
67 include OEMDEP.INC
68 page
69 include PAGE.INC
70 page
71 include VDMSEG.INC
72 page
73 include VDMSEL.INC
74 page
75 include VM386.INC
76
77 page
78 include DRIVER.STR
79
80 end
diff --git a/v4.0/src/MEMM/MEMM/MEMMONF.ASM b/v4.0/src/MEMM/MEMM/MEMMONF.ASM
new file mode 100644
index 0000000..5eee389
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MEMMONF.ASM
@@ -0,0 +1,337 @@
1
2
3 page 58,132
4;******************************************************************************
5 title MEMMONF - (C) Copyright MICROSOFT Corp. 1986
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM - MICROSOFT Expanded Memory Manager 386
11;
12; Module: MEMMONF - parse for on/off/auto and perform the function
13;
14; Version: 0.02
15;
16; Date: June 4, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/04/86 Original
27; 06/28/86 0.02 Name change from MEMM386 to MEMM
28;
29;******************************************************************************
30;
31; Functional Description:
32; MEMMONF is used by MEMM.EXE UTILITY code and MEMM.COM to parse
33; the command line for ON, OFF, or AUTO and perform the function
34; via a call to ELIM_Entry. It also displays the appropriate message
35; depending on the results of the parsing and call to ELIM_Entry.
36;
37;******************************************************************************
38.lfcond ; list false conditionals
39.386p
40 page
41;******************************************************************************
42; P U B L I C D E C L A R A T I O N S
43;******************************************************************************
44;
45 public onf_func
46 public get_token
47;
48;******************************************************************************
49; E X T E R N A L R E F E R E N C E S
50;******************************************************************************
51
52
53
54_TEXT segment byte use16 public 'CODE'
55 extrn Inst_chk:near
56 extrn ELIM_link:near
57_TEXT ends
58;
59 page
60;******************************************************************************
61; L O C A L C O N S T A N T S
62;******************************************************************************
63;
64MSDOS equ 21h ; MS-DOS function call
65
66 include ascii_sm.equ
67
68;******************************************************************************
69; S E G M E N T D E F I N I T I O N
70;******************************************************************************
71;
72_TEXT segment byte use16 public 'CODE'
73 assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT
74;
75;******************************************************************************
76; L O C A L D A T A A R E A
77;******************************************************************************
78;
79 include memm_msg.inc
80;
81msg_tbl label word ; table of final messages to display
82 dw offset vmode ; on
83 dw offset rmode ; off
84 dw offset amode ; auto
85 dw 0 ; no parameter will use above msgs
86 dw offset parmerr ; invalid parameter
87 dw offset verr_msg ; error entering vmode
88 dw offset rerr ; error entering rmode
89 dw offset aerr ; error entering amode
90;
91; the valid arguments
92;
93on_arg db "on"
94on_len equ (this byte - on_arg)
95
96off_arg db "off"
97off_len equ (this byte - off_arg)
98
99auto_arg db "auto"
100auto_len equ (this byte - auto_arg)
101
102null_arg db " "
103null_len equ 1
104max_arg_len equ 11
105arg_str db max_arg_len dup(0) ; storage for get_token
106;
107arg_tbl label word ; table of valid arguments
108 dw offset on_arg
109 dw offset off_arg
110 dw offset auto_arg
111;
112no_arg equ (this byte - arg_tbl)
113 dw offset null_arg ; should be last entry
114max_args equ (this byte - arg_tbl)
115;
116arg_len label word ; table of argument lengths
117 dw on_len
118 dw off_len
119 dw auto_len
120;
121 dw null_len
122
123page
124;******************************************************************************
125; onf_func - Check command line for ON OFF or AUTO and perform function
126;
127; ENTRY: es:di points to command line terminated by CR or LF
128;
129; EXIT: The appropriate message is displayed
130;
131; USED: none
132;
133;******************************************************************************
134onf_func proc near
135
136 push ax
137 push dx
138 push di
139
140 cld
141;
142; check for driver installed
143;
144 call Inst_chk ; ax = 0/1 => isn't/is installed
145 or ax,ax ; q: is it installed?
146 jnz drvr_installed
147 mov dx,offset not_there ; Not installed message
148 jmp term ; display message and quit
149;
150drvr_installed:
151;
152 call parse_onf ; look for ON/OFF
153 jc msg_disp ; invalid parameter
154 cmp ax,no_arg/2 ; q: no argument?
155 je get_status ; y: get status
156 push ax ; save on/off indicator
157 mov ah,1 ; ah=1 for set status routine
158 call ELIM_link ; go turn it on or off
159 pop ax ; restore on/off indicator
160 jnc get_status ; no error in status routine
161 add ax,max_args/2+1 ; indicate error
162 jmp msg_disp
163;
164get_status:
165 xor ah,ah ; get status
166 call ELIM_link ; status in ah
167 mov al,ah
168 xor ah,ah ; status in ax
169 cmp ax,2 ; q: auto mode?
170 jb msg_disp ; n: display mode
171 push ax ; save it
172 mov dx,offset amode
173 mov ah,9
174 int MSDOS ; print auto mode
175 pop ax ; restore mode
176 sub ax,2 ; get on or off indicator
177;
178msg_disp:
179 shl ax,1 ; make it a word index
180 mov di,ax ; offset into message table
181 mov dx,msg_tbl[di] ; get appropriate message
182term:
183 mov ah,9
184 int MSDOS ; display error message
185;
186 pop di
187 pop dx
188 pop ax
189
190 ret
191onf_func endp
192
193 page
194;******************************************************************************
195; get_token - Retrieve a non-white-space string from a source string
196;
197; ENTRY: es:di points to command line terminated by CR or LF
198; ds:si points to storage for token
199; cx = maximum length to store
200;
201; EXIT: cx = length of token (0 => end of source string)
202; es:di points to first char after new token in source string
203; string of length cx stored in ds:si (and converted to lower case)
204;
205; USED: see above
206;
207;******************************************************************************
208get_token proc near
209 push si ; save storage area
210 push bx
211 push ax
212;
213 mov bx,cx ; number to store
214 xor cx,cx ; no chars found so far
215;
216; go to first non-blank character
217;
218gloop1:
219 mov al,es:[di] ; get a character
220 inc di ; point to next
221 cmp al,' ' ; Q: space ?
222 je gloop1 ; y: skip it
223 cmp al,TAB ; Q: TAB ?
224 je gloop1 ; y: skip it
225 dec di ; N: start parsing and reset di
226gloop2:
227 mov al,es:[di] ; get next char
228 cmp al,CR ; q: carriage return?
229 je token_xit ; y: quit
230 cmp al,LF ; q: line feed?
231 je token_xit ; y: quit
232 cmp al,' ' ; Q: space ?
233 je token_xit ; y: quit
234 cmp al,TAB ; Q: TAB ?
235 je token_xit ; y: quit
236 inc di ; n: point to next
237 inc cx ; increment number of chars found
238 cmp cx,bx ; q: have we stored our limit yet?
239 ja gloop2 ; y: don't store any more
240 or al,20h ; make it lower case
241 mov ds:[si],al ; store it
242 inc si ; and point to next
243 jmp short gloop2 ; continue
244token_xit:
245;
246 pop ax
247 pop bx
248 pop si
249 ret
250get_token endp
251
252 page
253;******************************************************************************
254; parse_onf - Parse command line for ON or OFF
255;
256; ENTRY: es:di points to command line terminated by CR or LF
257;
258; EXIT: ax = 0 => ON
259; ax = 1 => OFF
260; ax = 2 => AUTO
261; ax = 3 => no argument encountered
262; ax = 4 => Error in command line
263; CARRY = cleared if no errors
264; set if error (ax will also = 4)
265; es:di points to end of parsed string
266;
267; USED: see above
268;
269;******************************************************************************
270parse_onf proc near
271;
272 push si
273 push ds
274 push bx
275 push es
276;
277 mov bx,no_arg ; initialize to no parameters encountered
278 cld ; go foward
279;
280; es:di = 1st char
281;
282 mov si,offset arg_str ; ds:si = storage for argument
283 push cs
284 pop ds ; arg storage in _CODE
285 mov cx,max_arg_len ; maximum argument length
286 call get_token ; get an argument
287 or cx,cx ; q: any parms?
288 jz parse_xit ; n: quit
289 push di ; y: save di for later
290 push ds ; es:di = parameter table
291 pop es
292
293 xor bx,bx ; index into parameter table
294ploop2:
295 cmp cx,arg_len[bx] ; q: lengths equal?
296 jne not_found ; n: keep looking
297 mov di,arg_tbl[bx] ; get destination address
298 push si ; save source string addr
299 repe cmpsb ; q: is this a valid argument?
300 pop si ; restore source string address (command line)
301 je found ; y: matched one
302not_found:
303 inc bx
304 inc bx ; update table pointer
305 cmp bx,max_args ; q: have we done them all yet?
306 jne ploop2 ; n: keep looking
307parse_inv:
308 mov bx,max_args ; y: invalid
309 pop di ; restore di
310 jmp short parse_xit ; leave
311found:
312 pop di ; restore original string addr
313 pop es
314 mov cx,1 ; just need to check for one non blank
315 call get_token ; get another token
316 or cx,cx ; q: was there another one?
317 jz parse_xit2 ; n: good
318 mov bx,max_args ; y: invalid
319 jmp short parse_xit2
320parse_xit:
321 pop es
322parse_xit2:
323 shr bx,1 ; get result of parse
324 mov ax,bx ; put in ax
325 mov bx,max_args/2-1
326 cmp bx,ax ; set/clear carry on invalid/valid return
327;
328 pop bx
329 pop ds
330 pop si
331;
332 ret
333parse_onf endp
334
335_TEXT ends
336
337 end
diff --git a/v4.0/src/MEMM/MEMM/MEMM_MSG.INC b/v4.0/src/MEMM/MEMM/MEMM_MSG.INC
new file mode 100644
index 0000000..da17c94
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MEMM_MSG.INC
@@ -0,0 +1,43 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - 386 EMM device driver
8;
9; Module: CEM_MSG.INC - messages for ON/OFF/AUTO utility
10;
11; Version: 0.02
12;
13; Date: June 7,1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change Log:
20;
21; DATE REVISION Description
22; -------- -------- --------------------------------------------
23; 06/07/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25;
26;******************************************************************************
27;
28not_there db "EMM386 driver not installed.",CR,LF,BEL,"$"
29
30vmode db "EMM386 Active.",CR,LF,"$"
31
32rmode db "EMM386 Inactive.",CR,LF,"$"
33
34amode db "EMM386 in Auto mode.",CR,LF,"$"
35
36verr_msg db "Unable to activate EMM386.",CR,LF,BEL,"$"
37
38rerr db "Unable to inactivate EMM386.",CR,LF,BEL,"$"
39
40aerr db "Unable to place EMM386 in Auto mode.",CR,LF,BEL,"$"
41
42parmerr db "Usage: EMM386 [ ON | OFF | AUTO]"
43 db CR,LF,BEL,"$"
diff --git a/v4.0/src/MEMM/MEMM/MOVEB.ASM b/v4.0/src/MEMM/MEMM/MOVEB.ASM
new file mode 100644
index 0000000..00b9a07
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/MOVEB.ASM
@@ -0,0 +1,533 @@
1
2
3page 58,132
4;******************************************************************************
5 title MOVEB - move block emulator
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: MOVEB - move block code for MEMM
13;
14; Version: 0.05
15;
16; Date: 05/22/86
17;
18; Author:
19;
20;*************************************************************************
21; CHANGE LOG:
22; DATE VERSION Description
23;--------- -------- --------------------------------------------------
24; 05/15/86 Check source/target selector using verr,verw
25; and add parity handler
26; 06/09/86 Added MapLinear call
27; 06/17/86 Added code to detect and "handle" writes to
28; diag byte location.
29; 06/28/86 0.02 Name changed from MEMM386 to MEMM
30; 07/06/86 0.04 DiagByte moved to _DATA
31; 07/06/86 0.04 changed assume to DGROUP
32; 07/10/86 0.05 Added Real Mode patch code
33;*************************************************************************
34.386p
35
36
37;****************************************
38; P U B L I C S
39;****************************************
40 public Move_Block
41 public MB_Exit
42 public MB_Stat
43 public i15_Entry
44 public MB_Flag
45 public i15_Old
46
47 page
48;****************************************
49; D E F I N E S
50;****************************************
51 include vdmseg.inc
52 include vdmsel.inc
53 include desc.inc
54 include instr386.inc
55 include oemdep.inc
56 include vm386.inc
57
58TRUE equ 0FFh
59FALSE equ 00h
60
61D_G_BIT equ 80h ; granularity bit in high status bits
62
63FLAGS_CY equ 0001h
64FLAGS_ZF equ 0040h
65FLAGS_IF equ 0200h
66
67 ; 386 data descriptor format
68DATA_DESC_386 struc
69DD386_Limit_lo dw ? ; low word of seg limit
70DD386_Base_lo dw ? ; low 24 bits of seg base addr
71 db ? ;
72DD386_Access db ? ; access byte
73DD386_L_Stat db ? ; high 4 bits of seg limit
74 ; and futher status
75DD386_Base_hi db ? ; high 8 bits of seg base addr
76DATA_DESC_386 ends
77
78 ; format of move block descriptor table passed on entry
79MB_GDT struc
80MG_dummy dd 2 dup (?) ; dummy descriptor entry
81MG_GDT dd 2 dup (?) ; GDT entry
82MG_Source dd 2 dup (?) ; source segment entry
83MG_Target dd 2 dup (?) ; target segment entry
84MB_GDT ends
85
86;************************************************************
87; DescrMap - map address in descriptor
88; ENTRY: ES:DI = descriptor
89; EXIT: descriptor's address is mapped by MapLinear
90; USED: EAX
91;************************************************************
92DescrMap MACRO
93 mov ah,ES:[di.DD386_Base_hi] ; ah = high 8 bits of address
94 mov al,byte ptr ES:[di.DD386_Base_lo+2] ; al = bits 16-23 of addr
95 OP32
96 shl ax,16 ; high addr word into high EAX
97 mov ax,ES:[di.DD386_Base_lo] ; EAX = 32 bit address
98 call MapLinear ; map linear address
99 mov ES:[di.DD386_Base_lo],ax ; store low word of address
100 OP32
101 shr ax,16 ; ax = high word of address
102 mov byte ptr ES:[di.DD386_Base_lo+2],al ; store
103 mov ES:[di.DD386_Base_hi],ah ; high word of address
104 ENDM
105
106;*******************************************************************************
107; E X T E R N A L R E F E R E N C E S
108;*******************************************************************************
109_TEXT segment
110
111 extrn MapLinear:near
112 extrn Set_Par_Vect:near
113 extrn Rest_Par_Vect:near
114 extrn togl_A20:near
115 extrn get_a20_state:near
116
117_TEXT ends
118
119_DATA segment
120
121 extrn Active_Status:byte ; non-zero if in VM
122
123_DATA ends
124
125
126 page
127;*******************************************************************************
128; D A T A S E G M E N T
129;*******************************************************************************
130_DATA segment
131
132MB_Stat db 0 ; move block status
133Toggle_st db 0
134
135_DATA ends
136
137 page
138;****************************************
139; C O D E S E G M E N T _TEXT
140;****************************************
141_TEXT segment
142 assume cs:_TEXT, ds:DGROUP, es:DGROUP
143
144 page
145;*************************************************************************
146;*** Move_Block - Mimics the 286 ROM function Move Block ( int15h AH=87h ).
147; Move a block of data (copy it) to/from anywhere in
148; 24bits of linear address space. Normally used to move
149; data to/from extended memory (past 1M) since real mode
150; can only address the first meg of memory.
151;
152;
153; ENTRY PROTECTED MODE
154; AH = 87h
155; CX = # of words to move ( max 8000h ).
156; ES:SI = ptr to a descriptor table containing segment descriptors
157; for the source and target memory of the transfer.
158;
159; EXIT PROTECTED MODE
160; AH = 00 if OK
161; 01 if parity error *** currently not checked ***
162; 02 if exception error
163; 03 if gate address bit A20 fails.
164; if no error:
165; ZF and NC in client's flags
166; if error:
167; NZ and CY in client's flags
168;
169;
170; USES AX, FLAGS -> CLD.
171;
172; Descriptor Table Format
173; ES:SI ---> +-------------------------------+
174; | Dummy descriptor |
175; +-------------------------------+
176; | GDT descriptor |
177; +-------------------------------+
178; | Source segment descriptor |
179; +-------------------------------+
180; | Target segment descriptor |
181; +-------------------------------+
182;
183;*************************************************************************
184Move_Block proc near
185;
186 push ds
187 push es
188 PUSH_EAX
189 push cx
190 push si
191 push di
192;
193 cld
194;
195 mov ax,VDMD_GSEL ; get data selector
196 mov ds,ax ; DS = DGROUP
197 mov [MB_Stat],0 ; init status of move block to OK.
198;
199; check word count field
200;
201 cmp cx,8000h ;Q: word count too high
202 jbe MB_chk_length ; N: check length of segments
203 jmp MB_Excp_Error ; Y: report exception error
204
205;
206; check source and target descriptor's lengths against transfer count
207; only need check low word since caller set up a 286 descriptor
208;
209MB_chk_length:
210 mov ax,cx
211 shl ax,1 ; AX = # of bytes to transfer(0=>8000h)
212 dec ax ; convert to seg limit type value
213 ; ( 0FFFFh => 64K )
214 cmp ax,ES:[si.MG_Source.DD386_Limit_lo] ;Q: source seg limit low ?
215 jbe MB_chk_tarl ; N: chk target length
216 jmp MB_Excp_Error ; Y: return excp error.
217
218MB_chk_tarl:
219 cmp ax,ES:[si.MG_Target.DD386_Limit_lo] ;Q: tar seg too small ?
220 jbe MB_setup ; N: seg limits OK.
221 jmp MB_Excp_Error ; Y: return excp error
222;
223; source and target descriptors OK, set up scratch selector descriptors
224;
225
226MB_setup:
227 push cx ; save copy count
228
229 push es
230 pop ds ; set DS:SI to input descriptor table
231 mov ax,GDTD_GSEL
232 mov es,ax ; ES:0 pts to GDT
233 mov di,MBSRC_GSEL ; ES:DI pts to source work descriptor in GDT
234 push si ; save input descr table ptr
235 lea si,[si.MG_Source]; DS:SI pts to input source descr
236 mov cx,4
237 rep movsw ; set move block source work descr
238 pop si ; restore input descr table ptr
239 mov di,MBSRC_GSEL ; ES:DI pts to source work descriptor in GDT
240 call MB_Map_Src
241 DescrMap ; fixup this descriptor's linear address
242
243 mov di,MBTAR_GSEL ; ES:DI pts to target work descr in GDT
244 push si ; save input descr table ptr
245 lea si,[si.MG_Target] ; DS:SI pts to input target descr
246 mov cx,4
247 rep movsw ; set move blk target work descr
248 pop si ; restore input descr table ptr
249 mov di,MBTAR_GSEL ; ES:DI pts to target work descr in GDT
250 call MB_Map_Dest
251 DescrMap ; fixup this descriptor's linear address
252
253;
254; install NMI/parity exception handler
255;
256 call Set_Par_Vect ; restore the parity interrupt handler
257
258;
259; copy the data
260;
261
262;
263; check if a20 line is to be enabled or not
264;
265 call get_a20_state
266 jnz a20_is_enb
267;
268; a20 line is currently disabled. we need to enable the a20
269;
270 call togl_a20
271 mov [toggle_st],0ffh
272a20_is_enb:
273;
274 pop cx ; restore copy count
275
276 xor di,di
277 xor si,si
278 mov ax,MBSRC_GSEL
279 verr ax ;Q: source selector valid ?
280 jnz MB_Excp_Error ; N: return exception error
281 mov ds,ax ; Y: DS:SI pts to source segment
282 mov ax,MBTAR_GSEL
283 verw ax ;Q: target selector valid ?
284 jnz MB_Excp_Error ; N: return exception error
285 mov es,ax ; Y: ES:DI pts to target segment
286 jmp MB_move_block ; and go ahead
287;
288; Error reporting
289;
290MB_Excp_Error:
291 mov ax,VDMD_GSEL ; get data selector
292 mov ds,ax ; DS = DGROUP
293 mov [MB_Stat],2
294 jmp MB_Exit
295;
296; move the block
297;
298MB_move_block:
299
300 call MB_Start
301
302;
303; MOVE the BLOCK - dwords
304;
305 test cx,01h ;Q: move an odd # of words?
306 jz MB_moved ; N: move dwords
307 movsw ; Y: move the first one => dwords now
308MB_moved:
309 shr cx,1 ; move CX dwords...
310 OP32
311 rep movsw ; REP MOVSD
312
313 mov ax,VDMD_GSEL ; get data selector
314 mov ds,ax ; DS = DGROUP
315
316; restore a20 state to what it was before this routine
317;
318 test [toggle_st],0ffh ; do we need to toggle the a20 back?
319 jz a20_restored ; N: skip toggling
320 call togl_a20 ; Y: else toggle the A20 line
321a20_restored:
322 mov [toggle_st],0 ; clear this flag
323
324 jmp MB_Exit
325Move_Block endp
326
327;*************************************************************************
328; This is special JUMP entry point for parity handler
329;
330MB_Exit proc near
331;
332; reset NMI handler
333;
334
335 call Rest_Par_Vect ; restore the parity interrupt handler
336
337;
338;
339MB_leave:
340 pop di
341 pop si
342 pop cx
343 POP_EAX
344 mov ah,[MB_Stat]
345;
346; set client's flags to no error
347;
348 or [bp.VTFOE+VMTF_EFLAGS],FLAGS_ZF ; ZF
349 and [bp.VTFOE+VMTF_EFLAGS],NOT FLAGS_CY ; NC
350
351 or ah,ah ;Q: error occured ?
352 jz MB_ret ; N: continue
353 ; Y: set error in client's flags
354 and [bp.VTFOE+VMTF_EFLAGS],NOT FLAGS_ZF ; NZ
355 or [bp.VTFOE+VMTF_EFLAGS],FLAGS_CY ; CY
356;
357MB_ret:
358 pop es
359 pop ds
360 ret
361;
362MB_Exit endp
363
364_TEXT ends
365
366 page
367;****************************************
368; C O D E S E G M E N T R_CODE
369;****************************************
370R_CODE segment
371 assume cs:R_CODE, ds:DGROUP, es:DGROUP
372
373;*************************************************************************
374; local data
375;*************************************************************************
376I15_Old dd 0 ; old Int 15h handler
377MB_Flag db 0 ; non-zero => do move block in ring 0
378Exit_Flags dw 0 ; flags for int15 exit
379;
380ext_mem_size dw 0 ; we are using new int 15 allocation
381 ; scheme now whereby we have to lower
382 ; the size reported by int 15 function
383 ; 88h to grab some memory for ourself
384 ; The extended memory allocate routine
385 ; in allocmem.asm fills in the approp.
386 ; size here.
387
388 page
389;*************************************************************************
390; i15_Entry - real/virtual mode patch code for int 15h
391;
392; This function patches the real mode IDT for MEMM. If it is
393; entered for a move block, this code sets a flag to tell MEMM to
394; pick up the move block, then i15_Entry lets MEMM do it. Otherwise
395; MEMM jumps to the previous code. For function 88h it reports the
396; the new size of extended memory.
397;
398; ENTRY Real/Virtual mode
399; see int15h entry parameters in ROM spec
400;
401; EXIT
402;
403; 87h: Real/Virtual mode
404; AH = 00 if OK
405; 01 if parity error *** currently not checked ***
406; 02 if exception error
407; 03 if gate address bit A20 fails.
408; if no error:
409; ZF and NC in client's flags
410; if error:
411; NZ and CY in client's flags
412;
413; 88h: Real/Virtual mode
414; AX = Size of extended memory in KB
415;
416;
417; USES AX, FLAGS -> CLD.
418;
419; NOTE:**ISP This routine was modified to implement the new INT15 allocation
420; scheme whereby MEMM by lowering the size of extended memory could
421; grab the difference between the old size and the new size reported
422; for itself.
423;*************************************************************************
424i15_flags equ 6
425i15_cs equ 4
426i15_ip equ 2
427i15_bp equ 0
428
429i15_Entry proc near
430;
431 cli ; in case of pushf/call far
432 pushf ; save entry flags
433;
434; Check to see if it is the extended memory size request
435;
436 cmp ah,88h ;Q: extended memory size request?
437 jne chk_blk_move ; N: go to check for move block call
438;
439; Implement int15 allocation scheme by reporting a lowered value of extended
440; memory.
441 popf
442 mov ax,cs:[ext_mem_size] ; report new extended memory size
443 iret ;
444;
445; Checking for move block call
446;
447chk_blk_move:
448 cmp ah,87h ;Q: move block call ?
449 jne i15_jmpf ; N: jmp to old code
450 push ds
451 push seg DGROUP ;
452 pop ds ; DS -> DOSGROUP
453 cmp [Active_Status],0 ; Y: Q: in Virtual mode ?
454 pop ds ; reset DS
455 je i15_jmpf ; N: jmp to old code
456 ; Y: VM move block
457 mov CS:[MB_Flag],TRUE ; let MEMM have it ...
458 popf ; retrieve entry flags (IF cleared!!!)
459 int 15h ; give it to MEMM
460 ; MEMM will reset MB_Flag
461 cli ; just in case
462 push bp ; save bp
463 mov bp,sp
464 push ax ; save ax
465 pushf
466 pop ax ; AX = exit flags
467 xchg ax,[bp+i15_Flags] ; AX = entry flag, exit flags on stack
468 and ax,FLAGS_IF ; save only IF bit of entry
469 or [bp+i15_Flags],ax ; set IF state in flags on stack
470 pop ax
471 pop bp
472 iret ; and leave
473;
474; far jump to old code
475;
476i15_jmpf:
477 popf ; retrieve entry flags
478 jmp CS:[i15_Old]
479;
480i15_Entry endp
481
482R_CODE ends
483
484
485LAST SEGMENT
486;
487 ASSUME CS:LAST
488;
489public set_ext
490;
491;*************************************************************************
492; set_ext - to fill up size of extended memory reported by int 15
493;
494; This function fills up the size of extended memory reported by the
495; int 15 real/virtual mode patch.
496;
497; ENTRY Real Mode
498; bx=size of extended memory in Kb
499;
500; EXIT None. R_CODE:ext_mem_size filled.
501;
502; USES None.
503;
504; WRITTEN 7/25/88 ISP
505;
506;*************************************************************************
507
508set_ext proc near
509;
510 ASSUME DS:NOTHING,ES:NOTHING
511
512 push ax
513 push ds
514;
515 mov ax,seg R_CODE
516 mov ds,ax
517;
518 ASSUME DS:R_CODE
519;
520 mov [ext_mem_size],bx
521;
522 pop ds
523 pop ax
524;
525 ASSUME DS:NOTHING
526;
527 ret
528;
529set_ext endp
530;
531
532LAST ENDS
533 end
diff --git a/v4.0/src/MEMM/MEMM/M_STATE.ASM b/v4.0/src/MEMM/MEMM/M_STATE.ASM
new file mode 100644
index 0000000..9961558
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/M_STATE.ASM
@@ -0,0 +1,114 @@
1
2
3 page 58,132
4;******************************************************************************
5 TITLE M_STATE:MODULE to establish machine state at emm boot time
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: M_STATE
13;
14; Version: 0.01
15;
16; Date: Aug 29,1988
17;
18; Author: ISP (ISP)
19;******************************************************************************
20;
21; Change Log:
22;
23; DATE REVISION Description
24; -------- -------- --------------------------------------------
25;******************************************************************************
26; Functional Description:
27;
28;******************************************************************************
29.lfcond
30.386p
31
32 page
33;******************************************************************************
34; P U B L I C D E C L A R A T I O N S
35;******************************************************************************
36
37 public estb_mach_state
38
39 page
40;******************************************************************************
41; L O C A L C O N S T A N T S
42;******************************************************************************
43;
44
45;******************************************************************************
46; INCLUDE FILES
47;******************************************************************************
48 include vdmseg.inc ; segment definitions
49
50 page
51;******************************************************************************
52; E X T E R N A L R E F E R E N C E S
53;******************************************************************************
54;
55;
56_DATA segment
57_DATA ends
58
59;
60LAST segment
61;
62 extrn estb_a20_state:near
63;
64LAST ends
65
66 page
67;******************************************************************************
68; S E G M E N T D E F I N I T I O N
69;******************************************************************************
70
71
72;******************************************************************************
73;
74; Code Segments
75;
76;******************************************************************************
77;
78_TEXT segment
79_TEXT ends
80
81LAST segment
82 assume cs:LAST, ds:DGROUP, es:DGROUP
83
84 page
85;-----------------------------------------------------------------------;
86; estb_mach_state ;
87; ;
88; establishes the state of the machine at memm boot. the only thing we ;
89; are concerned about right now is the a20 state which needs to be ;
90; preserved via emulation ;
91; ;
92; Arguments: ;
93; nothing ;
94; Returns: ;
95; nothing ;
96; Alters: ;
97; flags ;
98; Calls: ;
99; estb_a20_state ;
100; History: ;
101; ISP (isp). ;
102;-----------------------------------------------------------------------;
103estb_mach_state proc near
104;
105 call estb_a20_state
106 ret
107;
108estb_mach_state endp
109
110LAST ends ; End of segment
111;
112
113 end ; End of module
114
diff --git a/v4.0/src/MEMM/MEMM/OEMDEP.INC b/v4.0/src/MEMM/MEMM/OEMDEP.INC
new file mode 100644
index 0000000..0a2607d
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/OEMDEP.INC
@@ -0,0 +1,111 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: OEMDEP.INC
10;
11; Version: 0.04
12;
13; Date: June 13, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 06/13/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25; 07/05/86 0.04 Moved Diagbyte to _DATA
26; 07/06/86 0.04 Change from _DATA assume to DGROUP
27; 08/06/86 0.05 Broke out OEMPROC.ASM from OEMDEP.INC
28;
29;******************************************************************************
30ifndef INC_LIST
31.xlist
32endif
33
34
35_TEXT segment
36
37extrn MaskIntAll:near ; Mask interrupts routine
38extrn RestIntMask:near ; restore interrupt mask routine
39
40extrn Map_Lin_OEM:near ; MapLinear hook
41extrn UMap_Lin_OEM:near ; UnMapLinear hook
42extrn MB_Map_Src:near ; Move block map source hook
43extrn MB_Map_Dest:near ; Move block map destination hook
44extrn MB_Start:near ; Move block start move hook
45
46_TEXT ends
47
48
49LAST segment
50
51extrn VerifyMachine:near ; Verify machine valid for software
52
53LAST ends
54
55ifndef NOHIMEM ; only for high memory
56
57;Define routines in OEMPROC module
58
59_TEXT segment
60
61extrn HwMemLock:near
62extrn HwMemUnlock:near
63
64_TEXT ends
65
66LAST segment
67
68extrn hbuf_chk:near
69extrn HiAlloc:near
70extrn HiSysAlloc:near
71extrn HImod:near
72extrn LockROM:near
73extrn UnLockROM:near
74
75LAST ends
76
77endif
78
79;******************************************************************************
80;
81; HwTabUnlock - unlocks high system RAM - makes tables writeable
82;
83; EXIT: FS points to DIAG segment
84; high system RAM writeable
85;
86HwTabUnlock MACRO
87ifndef NOHIMEM ; only for high memory
88 call HwMemUnlock
89endif
90 ENDM
91
92;******************************************************************************
93;
94; HwTabLock - update client's hi system RAM write locks state
95;
96; ENTRY: CS = _TEXT
97; CS:[DiagByte] = last byte written to diag byte by user.
98;
99; EXIT: high system RAM write protect ON or OFF depenending on
100; write protect bit in CS:[DiagByte].
101; Bit 1 = 0 => write protect ON
102; Bit 1 = 1 => write protect OFF
103;
104HwTabLock MACRO
105ifndef NOHIMEM ; only for high memory
106 call HwMemLock
107endif
108
109 ENDM
110
111.list ; end of OEMDEP.INC
diff --git a/v4.0/src/MEMM/MEMM/OEMPROC.ASM b/v4.0/src/MEMM/MEMM/OEMPROC.ASM
new file mode 100644
index 0000000..b5e4931
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/OEMPROC.ASM
@@ -0,0 +1,1120 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: OEMPROC.ASM
10;
11; Version: 0.05
12;
13; Date: June 13, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 06/13/86 Original Separated out OEMPROC from OEMDEP.INC
24;
25;******************************************************************************
26;
27.386p
28.lfcond ; list false conditionals
29
30public VerifyMachine
31public MaskIntAll
32public RestIntMask
33public OEM_Trap_Init
34public Map_Lin_OEM
35public UMap_Lin_OEM
36public MB_Map_Src
37public MB_Map_Dest
38public MB_Start
39public Rest_Par_Vect
40public Set_Par_Vect
41
42public DisableNMI
43public ROM_BIOS_Machine_ID
44public OEM_Init_Diag_Page
45
46
47ifndef NOHIMEM
48
49public hi_size
50public hi_alloc
51public hisys_alloc
52
53public HwMemLock
54public HwMemUnlock
55
56public Hi_Mem_Size
57public hbuf_chk
58public HiAlloc
59public HiSysAlloc
60public HImod
61
62public InitLock
63public LockROM
64public UnLockROM
65
66
67endif
68
69 include page.inc
70 include vdmseg.inc
71 include VDMsel.inc
72 include desc.inc
73 include Instr386.inc
74 include romxbios.equ
75
76
77;******************************************************************************
78; E X T E R N A L R E F E R E N C E S
79;******************************************************************************
80;
81_DATA segment
82 extrn gdt_mb:word
83 extrn MB_Stat:word
84_DATA ends
85
86
87LAST segment
88 extrn set_src_selector:near
89 extrn set_dest_selector:near
90 extrn SetPageEntry:near
91LAST ends
92
93_TEXT segment
94 extrn MB_Exit:near
95_TEXT ends
96
97 page
98;******************************************************************************
99; L O C A L C O N S T A N T S
100;******************************************************************************
101;
102
103MASTER_IMR equ 21h ; mask port for master 8259
104
105;
106; PPI port bit definitions
107;
108PPI equ 61h
109PPO equ 61h
110PPO_MASK_IOCHECK equ 04h ; disable system board parity check
111PPO_MASK_PCHECK equ 08h ; disable IO parity check
112
113RTC_CMD equ 70h ; Real Time Clock cmd port
114DISABLE_NMI equ 80h ; mask bit for NMI
115ENABLE_NMI equ 00h ; this command to RTC_CMD enables NMI
116
117;****** REMOVE BEFORE DISTRIBUTION begin
118; Compaq specific 386 related addresses
119;
120X_HI_MEM_SEG equ 0f000h ;segment for the following words
121X_MT_386 equ 0fffeh ; Machine type
122X_RT_386 equ 0ffe8h ; Rom type
123X_HI_PTR equ 0ffe0h ; pointer to four words (offsets below)
124X_MEM_BOARD equ 0 ; 32-bit memory board status word
125X_HISYS equ 0 ; low byte = # of free 4k system pages
126X_AVAIL_MEM equ 4 ; available hi memory in 16 byte chunks
127X_LAST_HI equ 6 ; last used byte in hi memory (grows down)
128;
129; Addresses and values used to write the "ROM"
130;
131OEM_MEM_HI equ 80c0h ; Upper 16 bits of high mem physical adr
132LOCK_ADR_LO equ 0000h ; 0:15 of 32-bit location
133LOCK_ADR_HI equ OEM_MEM_HI ; 16-31 of 32-bit location
134LOCK_ROM equ 0fcfch ; value to write to lock rom
135UNLOCK_ROM equ 0fefeh ; value to write to unlock rom
136
137
138
139DIAGSEG segment use16 at 0
140DiagLoc dw ? ; 32 bit memory board diagnostic byte
141DIAGSEG ends
142
143
144;
145; data definitions
146;
147_DATA segment
148
149NMI_Old db 8 dup (0) ; save area for old NMI handler
150
151NMI_New label byte ; descriptor for new NMI handler
152IDT_ENTRY VDMC_GSEL,<offset _TEXT:Parity_Handler>,D_386INT0
153
154;
155ifndef NOHIMEM ; if high memory in this model
156;Next two entries MUST stay together!
157hbase_addr_l dw 0000h ; 24 bit address of beginning of hi memory
158hbase_addr_h db 00h ; pool of EMM pages.
159;
160hi_size dw 0 ; size of hi memory in kbytes
161hi_alloc dw 0 ; actual hi memory allocated (due to potential waste)
162hisys_alloc dw 0 ; amount of hi system memory allocated in 4k bytes
163;
164DiagAddr db 0 ; set this when writting to diag byte location
165DiagByte db LOW LOCK_ROM ; most recent diag byte written by user
166buffer dw 0 ; buffer for 1 word move blocks
167endif
168
169
170int_mask db ? ; save for restoring masked interrupts
171
172;
173ROM_BIOS_Machine_ID db 0fch ; hard coded right now to AT model byte.
174 ; should be changed to be initialised at
175 ; init time ...isp
176
177
178_DATA ends
179;****** REMOVE BEFORE DISTRIBUTION end
180
181
182_TEXT segment
183 ASSUME CS:_TEXT, DS:DGROUP
184
185;******************************************************************************
186;
187; MaskIntAll Save current interrupt mask state and mask all interrupts
188;
189; entry: DS pts to DGROUP
190;
191; exit: All interrupts disabled
192;
193; used: AX
194;
195; stack:
196;
197;******************************************************************************
198MaskIntAll proc near
199 in al,MASTER_IMR
200 mov [int_mask], al
201 mov al,0ffh ;;; all OFF
202 out MASTER_IMR,al
203 ret
204MaskIntAll endp
205
206;******************************************************************************
207;
208; RestIntMask Restore interrupt mask saved in MaskIntAll
209;
210; entry: DS pts to DGROUP
211;
212; exit: Interrupts restored to state previous to MaskIntAll
213;
214; used: AX
215;
216; stack:
217;
218;******************************************************************************
219RestIntMask proc near
220 mov al,[int_mask] ; restore interrupt mask
221 out MASTER_IMR,al
222 ret
223RestIntMask endp
224
225;******************************************************************************
226; OEM_Trap_Init - turn on I/O bit map trapping for I/O port watching
227;
228; ENTRY: DS -> DGROUP - real,virtual, or protected mode
229; ES -> TSS segment
230; Trap_Tab already has address of OEM_Handler for ??? ports
231;
232; Description: This routine is used to initialize any data structures,
233; including the IOBitMap(via PortTrap call) used for trapping I/O ports
234; when going into virtual mode. The routine(s) used to handle the
235; trap(s) should already be installed in the IOTrap_tab table.
236; See RRTrap.asm for an example.
237;
238; EXIT: IO_BitMap Updated to trap ports used for ???
239;
240; USED: AX,Flags
241; STACK:
242;------------------------------------------------------------------------------
243 assume cs:_TEXT, ds:DGROUP, es:TSS
244OEM_Trap_Init proc near
245;
246; Initialize data structures
247;
248;
249; Set IOBM traps to look for client's disabling of the A20 line
250;
251; push bx
252; mov bh, 80h ; set every 1k
253; mov ax, ??? ; AX = port num to trap
254; call PortTrap ; set traps on ??? port
255;
256; mov ax,0FFFFh
257; mov [???],ax ; Initialize trap data structure
258; pop bx
259
260 ret
261;
262OEM_Trap_Init endp
263;
264
265ifndef NOHIMEM ; only for high memory
266
267;******************************************************************************
268;
269; HwMemUnlock - unlocks high system RAM - makes tables writeable
270;
271; ENTRY: None
272;
273; EXIT: If NOHIMEM, does nothing, else:
274; FS points to DIAG segment
275; high system RAM writeable
276;
277 assume cs:_TEXT, ds:NOTHING, es:NOTHING
278HwMemUnlock proc near
279 push OEM0_GSEL
280 POP_FS ; set FS to diag segment
281 ASSUME DS:DIAGSEG
282 FSOVER
283 mov word ptr [DiagLoc],UNLOCK_ROM
284 ret
285HwMemUnlock endp
286
287
288
289;******************************************************************************
290;
291; HwMemLock - update client's hi system RAM write locks state
292;
293; ENTRY: CS = _TEXT(Protected mode)
294; DGROUP:[DiagByte] = last byte written to diag byte by user.
295;
296; EXIT: high system RAM write protect ON or OFF depenending on
297; write protect bit in CS:[DiagByte].
298; Bit 1 = 0 => write protect ON
299; Bit 1 = 1 => write protect OFF
300;
301 assume cs:_TEXT, ds:NOTHING, es:NOTHING
302HwMemLock proc near
303
304 push VDMD_GSEL
305 POP_FS ; FS = DGROUP
306 assume ds:DGROUP
307 FSOVER
308 test [DiagByte],02h ;Q: client's ROM write protected?
309
310 push OEM0_GSEL
311 POP_FS ; set FS to diag segment
312 ASSUME DS:DIAGSEG
313
314 jz HTL_wp ; Y: then write protect ON
315 FSOVER ; N: then write protect OFF
316 mov word ptr [DiagLoc],UNLOCK_ROM
317 jmp short HTL_exit
318HTL_wp:
319 FSOVER
320 mov word ptr [DiagLoc],LOCK_ROM
321HTL_exit:
322 ret
323HwMemLock endp
324
325endif ;end of "high" memory routines(ifndef NOHIMEM)
326
327;******************************************************************************
328;
329; Map_Lin_OEM Map OEM high memory from physical to linear address
330;
331; description: This maps an attempt to access the "high" memory to the
332; area starting at 16Meg, which the page tables map to the
333; proper physical address.
334;
335; entry: EAX = physical address to map to linear address
336;
337; exit: If address has been mapped in AX, CF = 1, else CF = 0.
338;
339; used: AX
340;
341; stack:
342;
343;******************************************************************************
344;
345 assume cs:_TEXT, ds:NOTHING, es:NOTHING
346Map_Lin_OEM proc near
347 OP32
348 cmp ax,0000h
349 dw OEM_MEM_HI ;Q: Addr in diags byte region ?
350 clc
351 jne Mp_Lin_Exit ; N: return, CF = 0(no mapping done)
352 OP32 ; Y: set EAX to proper seg address for diags
353 sub ax,0000h
354 dw (OEM_MEM_HI - 0100h); move to 0100h segment
355ifndef NOHIMEM
356; set write to diag byte flag
357 push ds ; save DS
358 push VDMD_GSEL
359 pop ds ; DS = DGROUP
360 ASSUME DS:DGROUP
361 mov [DiagAddr],1 ; set flag for diag addr
362 pop ds ; reset DS
363endif
364 stc
365Mp_Lin_Exit:
366 ret
367Map_Lin_OEM endp
368
369
370
371;******************************************************************************
372;
373; UMap_Lin_OEM Map OEM high memory from linear to physical address
374;
375; description: This maps an attempt to access the "high" memory in the
376; linear address area starting at 16Meg, to the proper physical
377; address.
378;
379; entry: EAX = linear address to map to physical address
380;
381; exit: EAX = physical address
382;
383; used: EAX
384;
385; stack:
386;
387;******************************************************************************
388;
389 assume cs:_TEXT, ds:NOTHING, es:NOTHING
390UMap_Lin_OEM proc near
391 OP32 ; Y: set EAX to physical address for diags
392 add ax,0000h
393 dw (OEM_MEM_HI - 0100h) ; move to OEM_MEM_HI segment
394 ret
395UMap_Lin_OEM endp
396
397;******************************************************************************
398;
399; MB_Map_Src Do special move block processing before source mapping
400;
401; description:
402; This routine is called just before MoveBlock does mapping of
403; the source. In conjunction with the Map_Lin_OEM routine, and
404; the MB_Start routine, it can perform special processing on the
405; data moved.
406;
407; entry: ES:DI pts to source work descr in GDT
408;
409; exit: any flag setting or perturbation of descriptor is done
410;
411; used: none
412;
413; stack:
414;
415;******************************************************************************
416 assume cs:_TEXT, ds:NOTHING, es:NOTHING
417MB_Map_Src proc near
418 ret
419MB_Map_Src endp
420
421;******************************************************************************
422;
423; MB_Map_Dest Do special move block processing before destination mapping
424;
425; description:
426; This routine is called just before MoveBlock does mapping of
427; the destination. In conjunction with the Map_Lin_OEM routine,
428; and the MB_Start routine, it can perform special processing on
429; the data moved.
430;
431; entry: ES:DI pts to destination work descr in GDT
432;
433; exit: any flag setting or perturbation of descriptor is done
434;
435; used: AX
436;
437; stack:
438;
439;******************************************************************************
440 assume cs:_TEXT, ds:NOTHING, es:NOTHING
441MB_Map_Dest proc near
442ifndef NOHIMEM
443 push ds
444 push VDMD_GSEL
445 pop ds ; DS = DGROUP alias selector
446 ASSUME DS:DGROUP
447 mov [DiagAddr],0 ; reset diag addr flag before write
448 pop ds ; reset DS
449endif
450 ret
451MB_Map_Dest endp
452
453;******************************************************************************
454;
455; MB_Start Do any special move block processing
456;
457; description:
458; This routine is called just before MoveBlock does the move.
459; It allows for any special processing of data moved
460;
461; entry: DS is source selector
462; ES is destination selector
463; SI is source offset
464; DI is destination offset
465;
466; exit: nothing
467;
468; used: AX
469;
470; stack:
471;
472;******************************************************************************
473 assume cs:_TEXT, ds:NOTHING, es:NOTHING
474MB_Start proc near
475ifndef NOHIMEM
476;
477; check for write to diag byte location
478;
479 push es
480 push VDMD_GSEL
481 pop es ; ES = DGROUP alias
482 ASSUME ES:DGROUP
483 cmp es:[DiagAddr],0 ;Q: does target -> diag byte ?
484 je MB_nodiag ; N: then don't worry
485 mov al,[si] ; Y: get current diag byte
486 mov es:[DiagByte],al ; and save it where we can access it
487MB_nodiag:
488 pop es ; restore es
489endif
490 ret
491MB_Start endp
492
493;*************************************************************************
494; Set_Par_Vect - Set parity handling routine to routine below
495;
496; Description:
497; This routine sets up a parity handling routine in case of
498; a parity error during a MOVEBLOCK.
499;
500; ENTRY: protected mode
501;
502; EXIT: vector restored
503;
504; USES: AX, CX, ES, DS, DI, SI
505;
506; note: entry is from protected mode -> DS,ES are same as during
507; move block.
508;*************************************************************************
509 assume cs:_TEXT, ds:NOTHING, es:NOTHING
510Set_Par_Vect proc near
511 mov ax,VDMD_GSEL
512 mov es,ax ; ES pts to DGROUP
513 mov ax,IDTD_GSEL ;
514 mov ds,ax ; DS points to IDT
515
516 mov si,0010h ; DS:[SI] points to NMI descr address in IDT
517 mov di,offset DGROUP:NMI_Old ; ES:[DI] pts to store area
518 mov cx,2
519 db 66h
520 rep movsw ; store 2 dwords - save current NMI descriptor
521 push ds
522 push es
523 pop ds ; DS = DGROUP
524 pop es ; ES = IDT
525 mov di,0010h ; ES:[DI] points to NMI descr address in IDT
526 mov si,offset DGROUP:NMI_New ; DS:[SI] pts to new NMI descr
527 mov cx,2
528 db 66h
529 rep movsw ; set up new NMI descriptor in IDT
530 ret
531Set_Par_Vect endp
532
533;*************************************************************************
534; Rest_Par_Vect - restore parity handling routine to original
535;
536; Description:
537; This routine restores the parity handling vector to the
538; contents before Set_Par_Vect was called. It is called after
539; a MOVEBLOCK has been completed.
540;
541; ENTRY: DS = DGROUP
542;
543; EXIT: vector restored
544;
545; USES: AX, CX, ES, DI, SI
546;
547; note: entry is from protected mode -> DS,ES are same as during
548; move block.
549;*************************************************************************
550 assume cs:_TEXT, ds:DGROUP, es:NOTHING
551Rest_Par_Vect proc near
552ifndef NOHIMEM
553 call HwMemUnlock ; in case IDT is in high mem
554endif
555 mov ax,IDTD_GSEL ; selector for IDT
556 mov es,ax ; ES points to IDT
557
558 mov di,0010h ; ES:[DI] points to NMI descr address in IDT
559 mov si,offset DGROUP:NMI_Old ; DS:[SI] pts to store area
560 mov cx,2
561 db 66h
562 rep movsw ; restore previous NMI descriptor
563ifndef NOHIMEM
564 call HwMemLock
565endif
566 ret
567Rest_Par_Vect endp
568
569
570;*************************************************************************
571; Parity_Handler - routine to handle parity errors which occur during
572; move_block.
573; Description:
574; This routine writes to the parity error location to
575; clear the parity error on the memory board, then it clears
576; the parity error on the system board.
577;
578; note: entry is from protected mode -> DS,ES are same as during
579; move block.
580;*************************************************************************
581 assume cs:_TEXT, ds:NOTHING, es:NOTHING
582Parity_Handler proc far
583;
584 dec si
585 dec si ;;; DS:SI pts to address causing parity error
586 mov ax,[si] ;;; retrieve value and write it back
587 mov [si],ax ;;; to reset parity on memory board.
588 in al,PPI ;;; Get parity error flags, reset then set
589 jmp $+2 ;;; parity checking to reset parity on
590 jmp $+2 ;;; system board
591 or al,PPO_MASK_IOCHECK ;;; disable IOCHECK
592 or al,PPO_MASK_PCHECK ;;; disable PCHECK
593 out PPO,al ;;; disable them
594 jmp $+2
595 jmp $+2
596 jmp $+2
597
598ifndef NOHIMEM
599 call HwMemlock ;;; LOCK high sys mem
600endif
601
602 and al, NOT PPO_MASK_IOCHECK ;;; enable IOCHECK
603 and al, NOT PPO_MASK_PCHECK ;;; enable PCHECK
604 out PPO,al ;;; enable them
605 ;;; system board parity now reset
606
607;
608 mov ax,VDMD_GSEL ;;;
609 mov ds,ax ;;; set DS to data seg
610 assume ds:DGROUP
611 mov [MB_Stat],1 ;;; set parity error
612 add sp,12 ;;; remove NMI stuff from stack
613 jmp MB_Exit ;;; and exit move block
614
615Parity_Handler endp
616
617;*************************************************************************
618; DisableNMI - This is called by the NMI handler to disable the
619; NMI interrupt(stop gracefully) as part of the
620; graceful handling of the NMI interrupt.
621;
622; Description:
623;
624; note: entry is from 386 protected mode
625;*************************************************************************
626 assume cs:_TEXT, ds:NOTHING, es:NOTHING
627DisableNMI proc near
628 push ax
629 mov al,DISABLE_NMI
630 out RTC_CMD,al
631 pop ax
632 ret
633DisableNMI endp
634
635_TEXT ends
636
637LAST segment
638
639;******************************************************************************
640;
641; VerifyMachine Check ID, etc. to make sure machine is 386 valid for
642; running the LIM/386 product.
643;
644; description:
645; This routine should check ROM signature bytes and any other
646; hardware features that guarantee the appropriateness of running this
647; software on the machine.
648;
649; entry: DS pts to DGROUP
650; CF = 1 if from INIT procedure, CF = 0 if from AllocMem procedure
651; REAL or VIRTUAL MODE
652;
653; exit: If not correct machine, CF = 1, else CF = 0.
654;
655; used: AX
656;
657; stack:
658;
659;******************************************************************************
660;
661 assume cs:LAST, ds:NOTHING, es:NOTHING
662VerifyMachine proc near
663 pushf
664 push es ; save es
665 push bx ; save bx
666 mov bx,X_HI_MEM_SEG ; segment of hi memory control words
667 mov es,bx ; into es
668 mov ax,es:X_MT_386 ; get machine type
669 cmp al,0FCh ; q: is this an AT class machine?
670 mov ax,es:X_RT_386 ; get ROM type
671 pop bx ; restore bx
672 pop es ; restore es
673 jne inc_prcf ; n: invalid
674 popf
675 jc Cor_Prc ; that's all the checking for INIT
676 cmp ax,'30' ; q: is this a 386? (really '03')
677 jne inc_prc
678Cor_Prc:
679 clc
680 ret
681inc_prcf:
682 popf
683inc_prc:
684 stc
685 ret
686VerifyMachine endp ; End of procedure
687
688
689ifndef NOHIMEM ; if high memory in this model
690;******************************************************************************
691;
692; Hi_Mem_Size - returns pointer and size of high mem allocated to EMM
693;
694; entry:
695;
696; exit: if ZF = 1, no high memory allocated to EMM, else
697; EAX = 24 bit pointer to EMM allocated high memory
698; CX = kbytes of high memory allocated
699;
700; used: EAX, CX(returned values)
701;
702; stack:
703;
704;******************************************************************************
705;
706 assume cs:LAST, ds:DGROUP, es:NOTHING
707Hi_Mem_Size proc near
708 mov cx,[hi_size] ; CX = kbytes of high mem
709 shr cx,4 ;Q: any hi memory pages ? CX = pg cnt
710 jz Hi_Mem_SXit ; N: Exit with ZF = 1
711 db 66h ; Y: get high memory pointers
712 mov ax,[hbase_addr_l] ; get pointer to high memory pool
713 db 66h
714 and ax,0FFFFh ; AND EAX,00FFFFFFh
715 dw 00FFh ; clear highest nibble
716Hi_Mem_SXit:
717 ret
718Hi_Mem_Size endp
719
720 page
721;******************************************************************************
722;
723; hbuf_chk Hi memory pool check.
724; Check available hi memory pool space
725;
726; entry:
727;
728; exit: If hi memory pool space is available then
729; AX = size of memory available and CF = 0
730; else AX = 0 and CF = 1
731;
732; used: AX(returned value)
733;
734; stack:
735;
736;******************************************************************************
737;
738 assume cs:LAST, ds:DGROUP, es:NOTHING
739hbuf_chk proc near
740 push es ; save es
741 push bx
742 mov bx,X_HI_MEM_SEG ; segment of hi memory control words
743 mov es,bx
744 mov bx,es:X_HI_PTR ; pointer to hi memory control words
745 mov ax,es:[bx+X_MEM_BOARD] ; 32-bit memory board status
746 inc ax ; q: memory board status word == -1?
747 stc
748 jz hbuf_xit ; y: not installed
749 mov ax,es:[bx+X_AVAIL_MEM] ; get available memory in 16 byte pieces
750 mov bx,es:[bx+X_LAST_HI] ; get last used address
751 and bx,0ffh ; align to 4k byte boundary (2**8)*16
752 sub ax,bx ; ax = available 16 byte pieces
753 shr ax,10 ; ax = available 16k byte pieces
754 shl ax,4 ; ax = available 1k byte pieces
755 clc
756hbuf_xit:
757 pop bx ; ax = availble memory unless CF = 1
758 pop es
759 ret
760hbuf_chk endp
761;
762 page
763;******************************************************************************
764;
765; HiAlloc - allocate hi memory - update hi memory control words
766;
767; entry: REAL or VIRTUAL MODE
768; DS pts to DGROUP
769; DGROUP:[hi_size] size in kbytes to allocate
770;
771; exit: update available hi memory and last used address.
772; Set [hbase_addr_l] and [hbase_addr_h] to starting address.
773; If error occurs in writing control words, CF = 1, else CF = 0.
774;
775; used: none
776;
777; stack:
778;
779;******************************************************************************
780 assume cs:LAST, ds:DGROUP, es:NOTHING
781HiAlloc proc near
782;
783 push ax
784 push bx
785 push cx
786 push dx
787 push si
788 push es
789;
790 mov ax,[hi_size] ; get amount of hi memory to allocate
791 or ax,ax ; q: allocate any?
792 jz Hi_xit ; n: quit(CF = 0)
793
794 mov cl,6
795 shl ax,cl ; back to 16 byte pieces
796;
797 mov bx,X_HI_MEM_SEG ; high memory segment
798 mov es,bx
799 mov bx,es:X_HI_PTR ; pointer to high memory control words
800 mov cx,0ffh ; determine waste by aligning to 4k
801 and cx,es:[bx+X_LAST_HI] ; cx = extra needed to align
802 add ax,cx ; ax = total to allocate
803 mov [hi_alloc],ax ; save it in case we need to put it back
804 xor bx,bx ; bx = no hi system memory to alloc
805 call HImod ; go allocate it
806 ; ax = start of this hi memory
807 jc Hi_xit ; error occurred during move block(CF=1)
808 mov cx,16
809 mul cx ; make it 24 bits
810 add dl,0f0h ; last 1M segment
811 mov [hbase_addr_h],dl ; save starting address of hi mem
812 mov [hbase_addr_l],ax
813 clc
814;
815Hi_xit: ; CF = 1 if error, else CF = 0
816 pop es
817 pop si
818 pop dx
819 pop cx
820 pop bx
821 pop ax
822 ret
823HiAlloc endp
824;
825 page
826;******************************************************************************
827;
828; HiSysAlloc - allocate hi system memory - update hi memory control words
829;
830; entry: REAL or VIRTUAL MODE
831; DS pts to DGROUP
832; ax = # of 4k byte pieces to allocate
833;
834; exit: If enough hi system memory available
835; update available hi system memory.
836; ax = # of 4k byte pieces used before this allocation.
837; CY cleared
838; else
839; ax = amount of hi system memory available
840; CY set
841; If error occurs in writing control words,
842; CY set
843; ax = -1
844;
845; used: see above
846;
847; stack:
848;
849;******************************************************************************
850 assume cs:LAST, ds:DGROUP, es:NOTHING
851HiSysAlloc proc near
852 push bx
853 push es
854;
855 push ax ; save amount asked for
856 mov bx,X_HI_MEM_SEG ; high memory segment
857 mov es,bx
858 mov bx,es:X_HI_PTR ; pointer to high memory control words
859 mov ax,es:[bx+X_HISYS] ; ax = amount of hi system mem available
860 and ax,00ffh ; after we get rid of high byte
861 pop bx ; bx = amount requested
862 ; ax = amount currently available
863 cmp ax,bx ; Q: available >= requested?
864 jb Hisys_xit ; N: quit - carry set => not enough mem
865 add [hisys_alloc],bx ; Y: save it in case we must deallocate
866 push ax ; save amount available before
867 xor ax,ax ; ax = no hi user mem to alloc
868 call HImod ; go allocate high sys mem
869 pop bx ; bx = amount available before
870 jc Hisys_err ; MOD ERROR -> set error flag
871 mov ax,10h ; 16 pages in high sys mem pool
872 sub ax,bx ; ax = amount used before this request
873 jmp Hisys_xit ; no error in move block
874;
875Hisys_err:
876 mov ax,-1
877 stc ; to be sure
878Hisys_xit:
879 pop es
880 pop bx
881 ret
882HiSysAlloc endp
883;
884 page
885;******************************************************************************
886;
887; Himod - allocate/deallocate hi memory - update hi memory control words
888;
889; entry: REAL or VIRTUAL MODE
890; DS pts to DGROUP
891; ax = size in 16 bytes of hi USER mem to alloc (a negative #
892; will deallocate)
893; bx = size in 4k bytes of hi SYSTEM mem to alloc (ditto above)
894;
895; exit: update available hi memory and last used address.
896; ax = New last used address for high user memory
897; CY = set if block move error occurred
898;
899; used: none
900;
901; stack:
902;
903;******************************************************************************
904 assume cs:LAST, ds:DGROUP, es:NOTHING
905HImod proc near
906 push bx
907 push cx
908 push dx
909 push si
910 push es
911;
912 call UnLockROM ;Q: ROM space writeable?
913 jz unlock_ok ; Y: continue
914 jmp Himod_err ; N: exit
915unlock_ok:
916 push bx ; save hi system memory allocation
917 mov bx,X_HI_MEM_SEG ; high memory segment
918 mov es,bx
919 mov bx,es:X_HI_PTR ; pointer to high memory control words
920 sub es:[bx+X_AVAIL_MEM],ax ; update hi memory available
921 sub es:[bx+X_LAST_HI],ax ; and last used address
922 pop ax ; get hi system memory amount
923 sub es:[bx+X_HISYS],ax ; update hi system memory available
924 mov ax,es:[bx+X_LAST_HI] ; start of this hi memory
925;
926 call LockROM ;Q: ROM write protected now ?
927 clc ; clear error flag
928 jz Himod_xit ; Y: exit with no error
929; ; N: report error
930Himod_err:
931 stc ; indicate error
932HImod_xit:
933 pop es
934 pop si
935 pop dx
936 pop cx
937 pop bx
938;
939 ret
940
941
942HImod endp
943 page
944;******************************************************************************
945;
946; LockROM - write protects high system RAM
947;
948; entry: REAL or VIRTUAL MODE
949; DS pts to DGROUP
950;
951; exit: Z = no error - high system RAM write protected
952; NZ = ERROR.
953;
954; used: none
955;
956; stack:
957;
958;******************************************************************************
959 assume cs:LAST, ds:DGROUP, es:NOTHING
960LockROM proc near
961 push ax ; save ax
962 push cx
963 push dx
964 push es
965;
966 mov word ptr [buffer],LOCK_ROM ; word to write to unlock
967 jmp UL_write ; go write it...
968;
969LockROM endp
970
971 page
972;******************************************************************************
973;
974; UnLockROM - turns off write protect on high system RAM
975;
976; entry: REAL or VIRTUAL MODE
977; DS pts to DGROUP
978;
979; exit: Z = no error - high system RAM writeable
980; NZ = ERROR.
981;
982; used: none
983;
984; stack:
985;
986;******************************************************************************
987 assume cs:LAST, ds:DGROUP, es:DGROUP
988UnLockROM proc near
989 push ax ; save ax
990 push cx
991 push dx
992 push es
993;
994 mov word ptr [buffer],UNLOCK_ROM ; word to write to unlock
995;
996UL_write:
997 mov ax,seg DGROUP ; set source addr to buffer
998 mov es,ax ; set ES to DGROUP
999 mov cx,16
1000 mul cx ; make 24 bits
1001 add ax,offset DGROUP:buffer
1002 adc dl,0
1003 mov cx,1 ; 1 word to transfer
1004 call set_src_selector ; set source segment selector to buffer
1005 mov ax,LOCK_ADR_LO ; DX:AX = 32-bit addr of ROM LOCK
1006 mov dx,LOCK_ADR_HI
1007 mov cx,1 ; 1 word long
1008 call set_dest_selector ; destination is unlock address
1009
1010 mov ax,seg LAST
1011 mov es,ax ; es to last segmetn
1012 mov si,offset DGROUP:gdt_mb ; ES:SI -> global descriptor table
1013 mov ah,MOVE_BLK ; int 15 block move function code
1014 int XBIOS ; unlock rom
1015 or ah,ah ; Q: error?
1016 ; Y: return NZ
1017 ; N: return Z
1018 pop es
1019 pop dx
1020 pop cx
1021 pop ax
1022 ret
1023UnLockROM endp ; end of procedure
1024
1025endif ; end of code for not NOHIMEM
1026
1027
1028;******************************************************************************
1029;
1030; OEM_Init_Diag_Page: Initialise the 5th page table to point to the
1031; diagnostic segment.
1032;
1033; description:
1034;
1035; place 32 bit memory board diagnostic byte address into page table
1036; xxxx0000h - xxxxFFFFh physical
1037; -> 01000000h - 0100FFFFh linear => 64k => 16 entries in page tables
1038; => 1st 64k in 5th page table
1039;
1040; entry: DS pts to DGROUP
1041; ES:0 Page table seg.
1042;
1043; exit: nothing
1044;
1045; used: ax,di,dx,bx,cx,flags
1046;
1047; stack:
1048;
1049;******************************************************************************
1050;
1051OEM_Init_Diag_Page proc near
1052 assume cs:LAST, ds:dgroup, es:NOTHING
1053;
1054;
1055 mov di,4*P_SIZE ; ES:DI -> 1st 64k of 5th page table
1056 mov dx,OEM_MEM_HI
1057 xor ax,ax ; start with physical addr = xxxx0000h
1058 mov bh,0
1059 mov bl,P_AVAIL ; make pages available to all
1060 mov cx,10h ; set 64k worth of entries
1061IT_set_entry:
1062 call SetPageEntry
1063 ; ES:[DI] pts to next page table entry
1064 add ax,1000h ; next physical page
1065 adc dx,0h ; address in DX,AX
1066 loop IT_set_entry ;Q: done with page table entries ?
1067 ; N: loop again
1068 ; Y: all done
1069 ret
1070;
1071OEM_Init_Diag_Page endp
1072
1073LAST ends ; End of segment
1074
1075ifndef NOHIMEM ; if high memory in this model
1076
1077R_CODE SEGMENT
1078 assume cs:R_CODE, ds:DGROUP, es:DGROUP
1079
1080;******************************************************************************
1081; InitLock - Init state of Table lock
1082;
1083; NOTE: this is a FAR routine.
1084;
1085; ENTRY: REAL MODE
1086; DS = DGROUP
1087;
1088; EXIT: REAL MODE
1089; DGROUP:[DiagByte] = updated to current LOCK state
1090;
1091; USED: AX,BX
1092;
1093;******************************************************************************
1094InitLOCK proc far
1095
1096 mov [DiagByte],LOW LOCK_ROM ; default is locked
1097 push es
1098 mov ax,X_HI_MEM_SEG
1099 mov es,ax ; ES -> ROM
1100 mov bx,X_MT_386 ; ES:BX -> machine type byte
1101 mov ax,ES:[bx] ; AX = ROM contents
1102 xor ES:[bx],0FFFFh ; flip all bits in ROM
1103 xor ax,0FFFFh ; AX = "flipped" value
1104 cmp ax,ES:[bx] ;Q: flipped value in ROM ?
1105 jne gv_locked ; N: "ROM" is locked
1106 mov [DiagByte],LOW UNLOCK_ROM ;Y: ROM is UNLOCKED
1107gv_locked:
1108 xor ES:[bx],0FFFFh ; restore ROM contents (if changed)
1109;
1110 pop es
1111 ret
1112
1113InitLOCK endp
1114
1115R_CODE ENDS
1116
1117endif ; end of code for not NOHIMEM
1118
1119 end ; of module
1120
diff --git a/v4.0/src/MEMM/MEMM/PAGE.INC b/v4.0/src/MEMM/MEMM/PAGE.INC
new file mode 100644
index 0000000..aa76e69
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/PAGE.INC
@@ -0,0 +1,52 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: PAGE.INC - Definitions for paging on 386
10;
11; Version: 0.02
12;
13; Date: January 31, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 01/31/86 Original
24; 05/12/86 A Cleanup and segment reorganization
25; 06/28/86 0.02 Name change from MEMM386 to MEMM
26;
27;******************************************************************************
28;
29; Functional Description:
30;
31;******************************************************************************
32ifndef INC_LIST
33.xlist
34endif
35
36P_SIZE equ 1000h ; page size
37
38P_PRES equ 01h ; page present bit
39P_WRITE equ 02h ; write access bit
40P_USER equ 04h ; access bit for User mode
41P_ACC equ 10h ; page accessed bit
42P_DIRTY equ 20h ; page dirty bit
43
44
45P_AVAIL equ (P_PRES+P_WRITE+P_USER) ; avail to everyone & present
46
47PAGE_ENTRY macro addr,stat
48 dd addr ; access & status in low 12
49 ; address in high 20
50endm
51
52.list ; end of PAGE.INC
diff --git a/v4.0/src/MEMM/MEMM/PIC_DEF.EQU b/v4.0/src/MEMM/MEMM/PIC_DEF.EQU
new file mode 100644
index 0000000..93706b5
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/PIC_DEF.EQU
@@ -0,0 +1,78 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: PIC_DEF.EQU - 8259 programmable interrupt controllers
10;
11; Version: 0.02
12;
13; Date: January 31, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 01/31/86 Original
24; 05/12/86 B Cleanup and segment reorganization
25; 06/28/86 0.02 Name change from MEMM386 to MEMM
26;
27;******************************************************************************
28ifndef INC_LIST
29.xlist
30endif
31;
32; Master interrupt controller parameters
33;
34PIC1_CMD = 20H ; 8259A command register.
35PIC1_INIT = 21H ; 8259A initialization register.
36PIC1_STAT = 20H ; 8259A status (who interrupted)
37PIC1_MASK = 21H ; 8259A operation control word #1.
38;
39PIC1_ICW1_VAL = 11H ; Edge trig, 8 interval, cascade, ICW4.
40PIC1_ICW2_VAL = 08H ; Interrupt vector address.
41PIC1_ICW3_VAL = 04H ; Slave id.
42PIC1_ICW4_VAL = 01H ; 8088 mode, norm EOI, non-buf, no nest.
43;
44; Slave interrupt controller parameters
45;
46PIC2_CMD = 0A0H ; 8259A command register.
47PIC2_INIT = 0A1H ; 8259A initialization register.
48PIC2_STAT = 0A0H ; 8259A status (who interrupted)
49PIC2_MASK = 0A1H ; 8259A operation control word #1.
50;
51PIC2_ICW1_VAL = 11H ; Edge trig, 8 interval, cascade, ICW4.
52PIC2_ICW2_VAL = 70H ; Interrupt vector address.
53PIC2_ICW3_VAL = 02H ; Master id.
54PIC2_ICW4_VAL = 01H ; 8088 mode, norm EOI, non-buf, no nest.
55;
56MASK_DISABLE = 0FFH ; Mask register, no levels allowed.
57READ_ISR = 0BH ; Command to read PIC In-Service-Reg.
58EOI = 20H ; End-Of-Interrupt (non-specific).
59;
60IRQ0_ENABLE = 11111110B ; Mask to enable IRQ0.
61IRQ1_ENABLE = 11111101B ; Mask to enable IRQ1.
62IRQ2_ENABLE = 11111011B ; Mask to enable IRQ2.
63IRQ3_ENABLE = 11110111B ; Mask to enable IRQ3.
64IRQ4_ENABLE = 11101111B ; Mask to enable IRQ4.
65IRQ5_ENABLE = 11011111B ; Mask to enable IRQ5.
66IRQ6_ENABLE = 10111111B ; Mask to enable IRQ6.
67IRQ7_ENABLE = 01111110B ; Mask to enable IRQ7.
68;
69IRQ8_ENABLE = 11111110B ; Mask to enable IRQ8.
70IRQ9_ENABLE = 11111101B ; Mask to enable IRQ9.
71IRQ10_ENABLE = 11111011B ; Mask to enable IRQ10.
72IRQ11_ENABLE = 11110111B ; Mask to enable IRQ11.
73IRQ12_ENABLE = 11101111B ; Mask to enable IRQ12.
74IRQ13_ENABLE = 11011111B ; Mask to enable IRQ13.
75IRQ14_ENABLE = 10111111B ; Mask to enable IRQ14.
76IRQ15_ENABLE = 01111111B ; Mask to enable IRQ15.
77;
78.list ; end of PIC_DEF.EQU
diff --git a/v4.0/src/MEMM/MEMM/PPAGE.ASM b/v4.0/src/MEMM/MEMM/PPAGE.ASM
new file mode 100644
index 0000000..677c583
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/PPAGE.ASM
@@ -0,0 +1,510 @@
1
2
3 page 58,132
4;******************************************************************************
5 TITLE PPAGE - MODULE to find mappable Physical pages
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: PPAGE - Find Mappable Physical Pages
13;
14; Version: 0.01
15;
16; Date: Aug 1, 1988
17;
18; Author: ISP
19; COMMENTS** This routine needs extensive work to do a better
20; job of identification of unmappable segments. That
21; is why we seem to have a whole lot of procedures
22; which don't do much now.
23;******************************************************************************
24;
25; Change Log:
26;
27; DATE REVISION Description
28; -------- -------- --------------------------------------------
29;******************************************************************************
30; Functional Description:
31; This module initialises the mappable physical pages in memory.
32; It also finds a valid page frame for use.
33;
34;******************************************************************************
35.lfcond
36.386p
37
38 page
39;******************************************************************************
40; P U B L I C D E C L A R A T I O N S
41;******************************************************************************
42
43 public mappable_segs
44 public Map_tbl
45 public max_PF
46 public find_phys_pages
47 public exclude_segments
48 public is_page_mappable
49
50 page
51;******************************************************************************
52; L O C A L C O N S T A N T S
53;******************************************************************************
54;
55FIRST_SYSTEM_ROM_SEG_HI = 0F000h
56FIRST_SYSTEM_ROM_SEG_LO = 0E000h
57LAST_SYSTEM_ROM_SEG = 0FFFFh
58;
59FIRST_VIDEO_MEM_SEG = 0A000h
60LAST_VIDEO_MEM_SEG = 0BFFFh
61;
62FIRST_CONV_UMAP_SEG = 00000h
63LAST_CONV_UMAP_SEG = 03FFFh
64
65
66;******************************************************************************
67; INCLUDE FILES
68;******************************************************************************
69 include vdmseg.inc ; segment definitions
70 include emm386.inc ;contains the error messages
71 include emmdef.inc ;contains some emm defines
72
73 page
74;******************************************************************************
75; E X T E R N A L R E F E R E N C E S
76;******************************************************************************
77;
78;
79_DATA segment
80
81 extrn PF_Base:word
82 extrn msg_flag:word
83
84_DATA ends
85
86;
87LAST segment
88;
89 extrn rom_srch:near
90;
91LAST ends
92
93 page
94;******************************************************************************
95; S E G M E N T D E F I N I T I O N
96;******************************************************************************
97
98
99;******************************************************************************
100;
101; Code Segments
102;
103;******************************************************************************
104;
105_TEXT segment
106_TEXT ends
107
108LAST segment
109 assume cs:LAST, ds:DGROUP, es:DGROUP
110
111 page
112;*************************************************************************
113;
114; initialisation data
115;
116;*************************************************************************
117; table for identifying mappable pages
118;
119mappable_segs label byte
120 db TOT_PHYS_PAGES dup(PAGE_MAPPABLE) ;
121;
122; table for PF base addresses
123;
124Map_tbl label word
125 dw 0c000h
126 dw 0c400h
127 dw 0c800h
128 dw 0cc00h
129 dw 0d000h
130 dw 0d400h
131 dw 0d800h
132 dw 0dc00h
133max_PF equ (this byte - Map_tbl)
134 dw 0e000h
135
136 page
137;******************************************************************************
138; find_phys_pages: routine to find mappable phsyical pages and a page fr
139;
140; ENTRY: PF_base set to -1 (user didn't specify apge frame)
141; or offset into Map_tbl
142; EXIT: mappable_segs array initalised to indicate mappable pages
143; first_system_page initialised
144; num_system_pages initialised
145; PF_Base initalised to page frame
146; [msg_flag] set if error to error message number
147; USED: none
148;
149;******************************************************************************
150find_phys_pages proc near
151;
152; start out with all the pages initialised to be mappable except those excluded
153; by explicit instruction of the command line.
154;
155
156;
157; exclude segments in the lo end of system memory
158;
159 call exclude_conv_RAM
160
161; exclude segments in the system ROM area
162;
163 call exclude_system_ROM
164
165;
166; exclude segments in the video area
167;
168 call exclude_video_mem
169
170;
171; then search for option rom's in the area C000 to E000 and exclude the
172; segments in which option rom exists.
173;
174 call rom_srch ; this searches for option rom's and
175 ; removes the segments of these from
176 ; being mappable
177;
178; then find the page frame from the information of mappable segs from C000-E000
179; and the user specified page frame (if any).
180;
181 call find_pf_base
182;
183; and then exit
184;
185 ret
186;
187find_phys_pages endp
188
189 page
190;******************************************************************************
191; find_pf_base: routine to find a valid page frame
192;
193; ENTRY: PF_base set to -1 (user didn't specify apge frame)
194; or index into Map_tbl
195; ax = index into Map_tbl from rom_srch on a possible pageframe.
196;
197; EXIT: PF_base set to page frame segment (C000..E000) on no error
198; If error msg_flag set to appropriate error message
199;
200; USES: NONE
201;
202;******************************************************************************
203find_pf_base proc near
204;
205 push ax
206 push bx
207 push cx
208 push si
209;
210; we have to examine all the possible page frames by looking at the entries
211; for the page frame in the mappable_segs array and find all possible page
212; frames. the first such valid page frame found is remembered
213;
214
215 ;
216 ; initialise
217 ;
218 mov ax,0ffffh ; first possible page frame
219 xor bx,bx ; index into map_tbl
220 ;
221 ; outer loop entry. check for loop termination
222 ;
223examine_map_tbl_loop:
224 ;
225 cmp bx,MAX_PF ; are we done
226 ja choose_PF ; yes, go to choose page frame
227 ;
228 ; get the page frame segment. convert to phys. page #
229 ;
230 mov si,cs:Map_Tbl[bx] ;
231 shr si,10
232 ;
233 ; examine the entries for the 4 pages comprising this segment
234 ;
235 mov cx,4
236check_pages_loop:
237 cmp cs:mappable_segs[si],PAGE_MAPPABLE
238 jne invalidate_PF
239 inc si
240 loop check_pages_loop
241
242 ;***SUCCESS
243
244 ;
245 ; exit point. pf is valid. see if we already have a pf. if not we store
246 ; this.
247 ;
248 cmp ax,0ffffh ; do we have a pf already?
249 jne skip_get_PF ; skip if we do
250 mov ax,bx ; else store
251skip_get_PF:
252 ;
253 ; go to examine next PF
254 ;
255 jmp next_PF
256
257 ;***FAILURE
258
259 ;
260 ; exit point. pf is invalid. remove it from map_tbl
261 ;
262invalidate_PF:
263 mov cs:Map_Tbl[bx],0ffffh ;
264 ;
265 ;***SETUP TO LOOP AGAIN
266next_PF:
267 ;
268 add bx,2
269 jmp examine_map_tbl_loop
270;
271choose_PF:
272;
273; Choosing a page frame. If the user has specified a page frame then
274; validate it else give him the page frame we found first.
275;
276 ;
277 ; has the user specified a pf. if so go to validate it
278 ;
279 cmp [PF_Base],0ffffh ;
280 jne def_cont2
281 ;
282 ; user didn't specify a pf. did we find a pf. if so give it else indicate
283 ; error
284 ;
285 cmp ax,0ffffh ; did we find one
286 je no_PF_warn ; if not go to warn the user
287 mov bx,ax
288 mov ax, cs:Map_Tbl[bx] ; get the PF
289 mov [PF_Base],ax ;
290 or [msg_flag],BASE_ADJ_MSG ;
291 jmp pf_xit
292
293 ;
294 ; we don't have a pf. warn the user
295 ;
296no_PF_warn:
297 or [msg_flag],NO_PF_MSG
298 jmp pf_xit
299;
300; they specified a base address. Let's make sure it's good
301;
302def_cont2:
303 mov bx,[PF_Base] ; get the offset they specified
304 mov ax,bx ; ax = bx
305 shr ax,1 ; back to 0..8
306 mov cx,0400h ; length of PF segments
307 mul cx ; addr = 0c000h + (Mx-1)*400h
308 add ax,0c000h
309 mov [PF_Base],ax ; save it
310
311 cmp cs:Map_tbl[bx],0ffffh ; Is this any good?
312 jne pf_xit ; probably
313 or [msg_flag],PF_WARN_MSG ; probably not
314;
315; we need to ensure that the pages corresponding to the page frame are forced
316; into being mappable. this is necessary because we accept the user's discretio
317; in forcing a page frame in a certain area.
318;
319 mov si,ax ; segment
320 shr si,10 ; phys page#
321 mov cx,4
322force_PF_pages:
323 mov cs:mappable_segs[si],PAGE_MAPPABLE
324 inc si
325 loop force_PF_pages
326
327pf_xit:
328 pop si
329 pop cx
330 pop bx
331 pop ax
332 ret
333
334find_pf_base endp
335
336
337;***********************************************************************;
338; exclude_video_mem ;
339; ;
340; Excludes the segments between A000 and C000. ;
341; ;
342; input: none ;
343; ;
344; returns: none ;
345; ;
346; uses: ;
347; ;
348; calls:exclude_segments ;
349; ;
350; History: ;
351; ISP (isp). Wrote it. ;
352;***********************************************************************;
353exclude_video_mem proc near
354;
355 push bx
356 push ax
357;
358 mov bx,FIRST_VIDEO_MEM_SEG
359 mov ax,LAST_VIDEO_MEM_SEG
360 call exclude_segments
361;
362 pop ax
363 pop bx
364 ret
365;
366exclude_video_mem endp
367
368;***********************************************************************;
369; exclude_system_ROM ;
370; ;
371; Excludes the segments between A000 and C000. ;
372; ;
373; input: none ;
374; ;
375; returns: none ;
376; ;
377; uses: ;
378; ;
379; calls:exclude_segments ;
380; ;
381; History: ;
382; ISP (isp). Wrote it. ;
383;***********************************************************************;
384exclude_system_ROM proc near
385;
386 push bx
387 push ax
388;
389ifndef NOHIMEM
390 mov bx,FIRST_SYSTEM_ROM_SEG_LO
391else
392 mov bx,FIRST_SYSTEM_ROM_SEG_HI
393endif
394
395 mov ax,LAST_SYSTEM_ROM_SEG
396 call exclude_segments
397;
398 pop ax
399 pop bx
400 ret
401;
402exclude_system_ROM endp
403
404;***********************************************************************;
405; exclude_conv_RAM ;
406; ;
407; Excludes segments between 0000 and 4000h ;
408; ;
409; inputs:none ;
410; ;
411; returns: none ;
412; ;
413; History: ;
414; ISP (isp). Wrote it
415;***********************************************************************;
416exclude_conv_RAM proc near
417;
418 push bx
419 push ax
420;
421 mov bx,FIRST_CONV_UMAP_SEG
422 mov ax,LAST_CONV_UMAP_SEG
423 call exclude_segments
424;
425 pop ax
426 pop bx
427 ret
428;
429exclude_conv_RAM endp
430
431;-----------------------------------------------------------------------;
432; exclude_segments ;
433; ;
434; Excludes the given segments from the memory map. ;
435; ;
436; Arguments: ;
437; AX = high segment ;
438; BX = low segment ;
439; Returns: ;
440; nothing ;
441; Alters: ;
442; AX,BX ;
443; Calls: ;
444; nothing ;
445; History: ;
446; ISP (isp). modified from ps2emm sources. ;
447;-----------------------------------------------------------------------;
448exclude_segments proc near
449;
450 push cx
451 push es
452 push di
453;
454; fix the segments to form physical page numbers
455;
456 mov cl,10 ; to convert segment to physical page #
457 shr ax,cl
458 shr bx,cl
459 sub ax,bx
460 jb exclude_segments_done
461 inc ax
462 mov cx,ax
463;
464; get addressing into mappable_segs array
465;
466 push cs
467 pop es
468 assume es:nothing
469 lea di, mappable_segs[bx]
470 mov al,PAGE_NOT_MAPPABLE
471 cld
472 rep stosb
473exclude_segments_done:
474;
475 pop di
476 pop es
477 pop cx
478 ret
479;
480exclude_segments endp
481
482;-----------------------------------------------------------------------;
483; is_page_mappable ;
484; ;
485; specifies whether a given physical page is mappable or not. ;
486; ;
487; Arguments: ;
488; si = physical page ;
489; Returns: ;
490; ZF set if mappable ;
491; ZF clear if not mappable ;
492; Alters: ;
493; flags ;
494; Calls: ;
495; nothing ;
496; History: ;
497; ISP (isp). 8/29/88 ;
498;-----------------------------------------------------------------------;
499is_page_mappable proc near
500;
501 cmp cs:mappable_segs[si],PAGE_MAPPABLE
502 ret
503;
504is_page_mappable endp
505
506LAST ends ; End of segment
507;
508
509 end ; End of module
510
diff --git a/v4.0/src/MEMM/MEMM/PRINT.ASM b/v4.0/src/MEMM/MEMM/PRINT.ASM
new file mode 100644
index 0000000..91d8571
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/PRINT.ASM
@@ -0,0 +1,424 @@
1
2
3page 58,132
4;******************************************************************************
5 title PRINT.ASM - Protected Mode Print Routines
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMMD.EXE - MICROSOFT Expanded Memory Manager 386 DEBUG Driver
11;
12; Module: PRINT.ASM - Protected Mode Print Routines
13;
14; Version: 0.04
15;
16; Date: January 31, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 01/31/86 Original
27; 05/12/86 A Cleanup and segment reorganization
28; 06/28/86 0.02 Name changed from MEMM386 to MEMM
29; 07/05/86 0.04 Moved to DCODE segment
30; 07/06/86 0.04 moved data to DDATA segment
31;
32;******************************************************************************
33;
34; Functional Description:
35;
36;******************************************************************************
37.lfcond ; list false conditionals
38.386p
39
40 public PrintString
41 public PrintHex
42 public kputc
43 public RowCol
44 public IsReal
45
46NAME print
47
48;** print - cga simple print routines
49;
50 include VDMseg.inc
51 include VDMsel.inc
52 include desc.inc
53
54;*** IsReal - determine mode of cpu
55;
56; This routine is useful when writing dual mode code.
57; It returns with 'Z' = 1 if the cpu is in real mode,
58; otherwise 'Z' = 0.
59;
60; ENTRY DUAL MODE
61;
62; EXIT 'Z' = 1 (protected mode), 0 (real mode)
63;
64; USES flags
65;
66_TEXT segment
67
68 assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing
69
70IsReal proc near
71
72 push ax
73 smsw ax
74 xor al, 0ffh
75 and al, 1
76 pop ax
77 ret ; returns with flags set
78
79IsReal endp
80
81_TEXT ends
82
83;*** kputc - write character/attribute to screen
84;
85; This is a simple character output routine. It does not
86; interleave writes to video memory with the 6845. It
87; does not update the cursor position. It does not understand
88; anything except a CGA in 80x25 text mode.
89;
90; ENTRY PROTECTED MODE
91; AX - character-attribute to write
92; DS - kernel data selector
93;
94; EXIT none - character written
95;
96; USES AX, flags
97;
98
99_DATA segment
100RowCol dw 0
101_DATA ends
102
103CR equ 0dh ; carriage return
104LF equ 0ah ; line feed
105TAB equ 9 ; tab
106BS equ 8 ; backspace
107
108COLOUR_PARA equ 0b800h
109
110_TEXT segment
111
112 assume cs:_TEXT, ds:_DATA, es:nothing, ss:nothing
113
114kputc proc far
115
116 push bx ; save callers regs
117 push cx
118 push dx
119 push si
120 push di
121 push es
122 push ds
123
124 call IsReal ; need dual mode access
125 jnz kp10
126 mov dx, VDMD_GSEL ; selector for protected mode
127 jmp kp11
128kp10:
129 mov dx, seg _DATA ; para for real mode
130kp11:
131 push dx ; save this segment for later
132
133 mov ds, dx ; DS -> data segment
134 mov dx, ds:[RowCol] ; DX = current row/col
135
136 cmp al, CR ; is character a CR?
137 jne kp1
138
139 mov dl, 0 ; yes, go to column 0
140 jmp kp3 ; jump to common code
141kp1:
142
143 cmp al, LF ; is character a LF?
144 jne kp2
145
146 inc dh ; yes, go to next row
147 jmp kp3 ; jump to common code
148kp2:
149
150 cmp al, TAB ; is it a tab
151 jne kp12
152 and dl, 0f8h ; mask off low 3 bits (8 ch)
153 add dl, 8 ; move to next tab position
154 jmp kp3 ; jmp to common code
155kp12:
156
157 cmp al, BS ; is it backspace
158 jne kp13
159 dec dl ; back up one column
160 jmp kp3 ; goto common code
161kp13:
162; Must be ordinary character. Write it to screen, update position
163
164 push ax ; save char/attr
165
166 mov al, dh ; AL = row
167 mov ah, 80 ; multiplier, 80 char per row
168 mul ah ; AX = cell at start of row
169 mov bh, 0
170 mov bl, dl ; BX = column
171 add bx, ax ; BX = cell
172 shl bx, 1 ; BX = byte offset of cell
173
174 call IsReal ; bi-modal access to screen
175 jnz kp6
176 mov ax, COLOUR_GSEL ; screen selector for protected mode
177 jmp kp7
178kp6:
179 mov ax, COLOUR_PARA ; screen para for real mode
180kp7:
181 mov es, ax ; ES -> screen
182
183 pop es:[bx] ; write character
184 inc dl ; update column
185kp3:
186; Common code, first check for line wrap:
187
188 cmp dl, 80 ; beyond rhs of screen?
189 jl kp4
190 mov dl, 0 ; go to col 0
191 inc dh ; and move to next line
192kp4:
193; Now check for scroll needed:
194
195 cmp dh, 25 ; are we off end of screen?
196 jl kp5
197
198; Now scroll screen
199
200 call IsReal ; bi-modal access to screen
201 jnz kp8
202 mov ax, COLOUR_GSEL ; screen selector for protected mode
203 jmp kp9
204kp8:
205 mov ax, COLOUR_PARA ; screen para for real mode
206kp9:
207 mov ds, ax ; DS -> screen
208 mov es, ax ; ES -> screen
209
210 mov di, 0 ; ES:DI = copy destination
211 mov si, 160 ; DS:SI = copy source
212 mov cx, 2000-80 ; copy word count
213 cld
214 rep movsw ; scroll
215
216; Blank bottom line
217
218 mov al, ' '
219 mov ah, 7 ; AX = blank character
220
221 mov cx, 80 ; number of cells to blank
222 mov di, 4000-160 ; ES:DI = start point
223 rep stosw
224
225; Update position
226
227 mov dh, 24 ; new row
228kp5:
229 pop ds ; set DS to data again
230 mov ds:[RowCol], dx ; update row/col
231
232; call SetCursor
233
234 pop ds ; restore regs
235 pop es
236 pop di
237 pop si
238 pop dx
239 pop cx
240 pop bx
241
242 ret
243
244kputc endp
245_TEXT ends
246
247
248;*** SetCursor - updates cursor position
249;
250; This routine reprograms the 6845 cursor position, and
251; stores the new cursor position in the ROM bios data area.
252;
253; ENTRY DUAL MODE
254; DH, DL = row, col
255;
256; EXIT cursor updated
257;
258; USES ax, bx, cx, flags
259;
260
261CRT_COLS equ 04ah
262CURSOR_POSN equ 050h
263CRT_START equ 04eh
264ADDR_6845 equ 063h
265
266_TEXT segment
267
268 assume cs:_TEXT, ds:_DATA, es:nothing, ss:nothing
269
270SetCursor proc near
271
272 push ds
273 mov bx, 40h
274 mov ds, bx
275
276; Save new position in BIOS data area
277
278 mov ds:[CURSOR_POSN], dx
279
280; Calculate offset on screen
281
282 mov al, dh ; row
283 mul byte ptr ds:[CRT_COLS] ; row * cols
284 mov bl, dl ; bl = column
285 mov bh, 0 ; bx = column
286 add ax, bx ; ax = offset in screen
287 sal ax, 1 ; double for attribute bytes
288 mov cx, ds:[CRT_START] ; cx = start point of screen
289 add cx, ax ; cx = offset of cursor
290 sar cx, 1 ; convert to char count only
291
292; Now program 6845
293
294 mov al, 14 ; 6845 register
295 mov dx, ds:[ADDR_6845] ; base port #
296 out dx, al
297 inc dx
298 jmp short $+2
299
300 mov al, ch
301 out dx, al
302 dec dx
303 jmp short $+2
304
305 mov al, 15
306 out dx, al
307 inc dx
308 jmp short $+2
309
310 mov al, cl
311 out dx, al
312
313 pop ds
314
315 ret
316
317SetCursor endp
318_TEXT ends
319
320
321;*** PrintString - prints a message on console
322;
323; This routine calls the "kernel" to print a string
324; one character at a time.
325;
326; ENTRY 286 PROTECTED MODE
327; DS - DATA3_SEL
328; ES - DATA3_SEL
329; SI - offset in DS of null terminated string to print
330;
331; EXIT String printed
332;
333; USES Flags
334;
335
336_TEXT segment
337
338 assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing
339
340PrintString proc near
341
342 cld ; set up for string ops
343 push si ; save callers regs
344 push ax
345
346pr1: ; loop printing until null
347 lodsb ; al = char to print
348 and al, al ; terminator ?
349 je pr2
350 mov ah, 7 ; attribute
351
352 db 9ah ; far call
353 dw offset _TEXT:kputc ; offset
354 dw VDMC_GSEL ; selector
355
356 jmp pr1 ; back for more
357pr2:
358 pop ax ; restore callers regs
359 pop si
360
361 ret
362
363PrintString endp
364
365_TEXT ends
366
367;*** Hex2String
368;
369; Convert content of AX into 4 Hex digits string at ES:DI
370;
371; ENTRY AX value to convert
372; ES:DI storage string location
373;
374
375_TEXT segment
376
377 assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing
378
379PutHexChar proc near
380
381 cmp al,9
382 ja PHC_AF
383 add al,30h
384 jmp PHC_exit
385PHC_AF:
386 add al,(41h - 0ah)
387PHC_exit:
388 push ax
389 mov ah,7
390 db 9ah ; far call
391 dw offset _TEXT:kputc ; offset
392 dw VDMC_GSEL ; selector
393 pop ax
394 ret
395
396PutHexChar endp
397
398PrintHex proc near
399
400 cld
401
402 xchg al,ah
403 push ax
404 shr al,4
405 call PutHexChar
406 pop ax
407 and al,0fh
408 call PutHexChar
409 xchg al,ah
410 push ax
411 shr al,4
412 call PutHexChar
413 pop ax
414 and al,0fh
415 call PutHexChar
416
417 ret
418
419PrintHex endp
420
421_TEXT ends
422
423 end
424 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/RETREAL.ASM b/v4.0/src/MEMM/MEMM/RETREAL.ASM
new file mode 100644
index 0000000..8ffc602
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/RETREAL.ASM
@@ -0,0 +1,228 @@
1
2
3page 58,132
4;******************************************************************************
5 title RetReal - Return-To-Real routine(s) for the 386
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: RetReal - Return-To-Real routine(s) for the 386
13;
14; Version: 0.04
15;
16; Date: February 20, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 02/20/86 Original
27; 05/12/86 A Cleanup and segment reorganization
28; 06/01/86 Removed Real386a (loadall version) and left only
29; RetReal via PE bit
30; 06/21/86 0.02 Saved Eax
31; 06/28/86 0.02 Name changed from MEMM386 to MEMM
32; 07/02/86 0.03 Reset TSS busy bit
33; 07/05/86 0.04 Added Real_Seg label for _TEXT fixup
34; 07/06/86 0.04 changed assume to DGROUP
35;
36;******************************************************************************
37;
38; Functional Description:
39;
40; This module contains the routine RetReal which goes from Ring 0 protected
41; mode to Real Mode by resetting the PE bit (and the PG bit).
42;
43; NOTE: this module only works on the B0 and later parts. The A2 part
44; will leave the CS non writeable.
45;
46;******************************************************************************
47.lfcond ; list false conditionals
48.386p
49 page
50;******************************************************************************
51; P U B L I C D E C L A R A T I O N S
52;******************************************************************************
53;
54 public RetReal
55 public Real_Seg
56
57 page
58;******************************************************************************
59; I N C L U D E F I L E S
60;******************************************************************************
61
62include VDMSEG.INC
63include VDMSEL.INC
64include INSTR386.INC
65include OEMDEP.INC
66
67;
68;******************************************************************************
69; E X T E R N A L R E F E R E N C E S
70;******************************************************************************
71;
72_DATA segment
73 extrn Active_Status:byte
74_DATA ends
75
76_TEXT segment
77
78 extrn SelToSeg:near ; selector to segment (I286)
79 extrn DisableA20:near ; disable A20 line (MODESW)
80
81_TEXT ends
82;******************************************************************************
83; L O C A L C O N S T A N T S
84;******************************************************************************
85;
86FALSE equ 0
87TRUE equ not FALSE
88
89 page
90;******************************************************************************
91; S E G M E N T D E F I N I T I O N
92;******************************************************************************
93
94_TEXT segment
95 assume cs:_TEXT, ds:DGROUP
96
97;*** RetReal - cause a 386 mode switch to real mode
98;
99; ENTRY Ring 0 protected mode
100; CLI - interrupts disabled
101; NMI should also be disabled here.
102ifndef NOHIMEM
103; FS = Diag segment selector
104endif
105;
106; EXIT Real Mode
107; DGROUP:[Active_Status] = 0
108; CS = _TEXT
109; DS = ES = FS = GS = DGROUP
110; SS = stack segment
111; general registers preserved
112; flags modified
113; interrupts disabled
114; A20 disabled
115ifndef NOHIMEM
116; high system memory LOCKED
117endif
118;
119; USES see exit conditions above
120;
121; DESCRIPTION
122;
123real_gdt label qword
124real_idt dw 0FFFFh ; limit
125 dw 0000 ; base
126 dw 0000
127 dw 0000 ; just in case
128
129 public RetReal
130RetReal proc near
131 PUSH_EAX ; save two scratch registers
132 push bx
133 cli ; disable ints
134
135 smsw ax ;check to see if we are in real mode
136 test ax,1
137 jnz rl386_a ;jump if in protected mode
138 sti
139 pop bx
140 POP_EAX
141 ret ;otherwise return
142
143rl386_a:
144
145;
146; reset TSS busy bit before returning to Real Mode
147;
148 mov ax, GDTD_GSEL
149 mov es, ax ; ES:0 = ptr to gdt
150
151 and byte ptr ES:[TSS_GSEL + 5], 11111101B
152
153;
154; lock high system ROM before returning to real
155;
156 HwTabLock
157
158;
159; First save return ss:sp. We have to translate
160; the current ss (a selector) into a segment number.
161; Calculate a real mode segment corresponding to the
162; current protected mode stack selector base address.
163;
164; We get the base address from the descriptor table,
165; and convert it to a paragraph number.
166;
167 mov bx,ss ; bx = selector for stack
168 call SelToSeg ; AX = segment number for SS
169 mov bx,ax ; BX = setup stack segment
170;
171;
172; Intel shows DS,ES,FS,GS,and SS set up to make sure 'Real Mode' type
173; access rights, and limit are installed. In this program, that happens
174; to already be the case, but for general purposeness, VDMD_GSEL fits
175; the bill.
176;
177 mov ax,VDMD_GSEL ; selector with real mode attributes
178 mov ds,ax
179 mov es,ax
180 mov ss,ax
181 MOV_FS_AX
182 MOV_GS_AX
183;
184; Intel recommends the following code for resetting the PE bit. Mine
185; works OK, but maybe it's not general purpose enough (I was counting
186; on knowing that paging wasn't enabled).
187;
188 MOV_EAX_CR0 ; get CR0
189
190 OP32
191 and ax,0FFFEh ; force real mode and shut down paging
192 dw 07FFFh ; (mov eax,07FFFFFFEh)
193
194 MOV_CR0_EAX ; set CR0
195
196 ; flush prefetched instructions with:
197 db 0EAh ; Far Jump opcode
198 dw offset _TEXT:rl386_b ; destination offset
199Real_Seg label word
200 dw _TEXT ; destination segment
201rl386_b:
202 OP32 ; load up full IDT address
203 lidt qword ptr cs:[real_idt]
204
205 sti
206
207 MOV_EAX_CR3 ; get CR3
208 MOV_CR3_EAX ; set CR3 => clear TLB
209
210 mov ss,bx ; ss = real mode stack segment
211 mov ax,DGROUP
212 mov ds,ax
213 mov es,ax
214 MOV_FS_AX
215 MOV_GS_AX
216
217 mov [Active_Status],0 ; rest VDM status
218
219 call DisableA20 ; disable A20 line
220
221 pop bx
222 POP_EAX
223 ret ; *** RETURN ***
224RetReal endp
225
226_TEXT ends
227 end
228 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU b/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU
new file mode 100644
index 0000000..774afb1
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU
@@ -0,0 +1,37 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: ROMSTRUC.EQU - structure of the option ROM headers.
10;
11; Version: 0.02
12;
13; Date: June 25,1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 06/25/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25;
26;******************************************************************************
27ifndef INC_LIST
28.xlist
29endif
30
31OPTION_ROM STRUC
32ROM_RECOGNITION DW ? ; HOLDS 0AA55 WORD IF REAL OPTION ROM
33ROM_LEN DB ? ; BYTE HOLDING ROM SIZE / 512
34ROM_ENTRY DB ? ; WHERE CODE STARTS IN OPTION ROM
35OPTION_ROM ENDS
36
37.list ; end of ROMSTRUC.EQU
diff --git a/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU b/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU
new file mode 100644
index 0000000..2ee4418
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU
@@ -0,0 +1,45 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: ROMXBIOS.EQU - ROM Extra BIOS function calls
10;
11; Version: 0.02
12;
13; Date: June 25,1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 06/25/86 Original
24; 06/28/86 0.02 Name change from MEMM386 to MEMM
25;
26;******************************************************************************
27ifndef INC_LIST
28.xlist
29endif
30
31XBIOS equ 15h ; Extra BIOS functions
32 DEV_OPEN equ 80h ; - device open dummy call
33 DEV_CLOSE equ 81h ; - device close dummy call
34 PROG_TERM equ 82h ; - program terminate
35 EVENT_WAIT equ 83h ; - Event Wait
36 JOYSTICK equ 84h ; - joystick
37 SYS_REQ equ 85h ; - sys request key routine
38 UNCOND_WAIT equ 86h ; - unconditional Wait
39 MOVE_BLK equ 87h ; - move block
40 EXT_MEM equ 88h ; - extended memory size
41 ENTER_PROT equ 89h ; - enter protected mode
42 DEV_WAIT equ 90h ; - Device Wait
43 DEV_POST equ 91h ; - Device Post
44
45.list ; end of ROMXBIOS.EQU
diff --git a/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM b/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM
new file mode 100644
index 0000000..77da48a
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM
@@ -0,0 +1,317 @@
1
2
3;
4 page 58,132
5;******************************************************************************
6 title ROM_SRCH - search for option ROMs
7;******************************************************************************
8;
9; (C) Copyright MICROSOFT Corp. 1986
10;
11; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
12;
13; Module: ROM_SRCH - search for option ROMS and RAM
14;
15; Version: 0.04
16;
17; Date : June 5,1986
18;
19; Authors: SP, BT
20;
21;******************************************************************************
22;
23; CHANGES:
24;
25; DATE REVISION DESCRIPTION
26; -------- -------- ------------------------------------------------------
27; 06/05/86 Original Adapted from ROM code
28; 06/25/86 0.02 Fixed upd_map.
29; 06/26/86 0.02 Fixed upd_map (again) and ram_srch
30; 06/28/86 0.02 Name changed from MEMM386 to MEMM
31; 07/06/86 0.04 changed assume to DGROUP
32; 08/01/88 Updated to identify mappable segs between C000 and E000
33;
34;******************************************************************************
35 page
36;******************************************************************************
37;
38; Functional description:
39;
40; This module contains the code that scans the ROM at the segment
41; supplied in register AX looking for ROMs on hardware interface
42; boards. The layout of each valid ROM is as follows:
43;
44; OFFSET +-----------------------+
45; 0 | 55h |
46; +-----------------------+
47; 1 | AAh |
48; +-----------------------+
49; 2 | ROM size / 512 |
50; +-----------------------+
51; 3 | Start of init code |
52; :
53; n-1 | |
54; +-----------------------+
55; (Sum of all bytes MOD 100h is 00h.)
56;
57; This module also contains the code to search and vector to VDU
58; roms (C000:0 to C000:7800 in 2K increments).
59;
60;******************************************************************************
61 page
62.386P
63;
64;******************************************************************************
65; Public Declarations
66;******************************************************************************
67;
68 public rom_srch ; Search and Vector to option ROMs.
69;******************************************************************************
70; Externs
71;******************************************************************************
72LAST segment
73 extrn Map_tbl:word
74 extrn max_PF:abs
75 extrn mappable_segs:byte
76 extrn exclude_segments:near
77
78LAST ends
79;
80;******************************************************************************
81; Equates
82;******************************************************************************
83;
84FIRST_ROM = 0C800H ; Segment address of first option ROM.
85LAST_ROM = 0EF80H ; Segment address of last option ROM.
86FIRST_VDU_ROM = 0C000H ; Seg address of first VDU option ROM.
87LAST_VDU_ROM = 0C780H ; Seg address of last VDU option ROM.
88FIRST_RAM = 0C000H ; Seg address of 1st possible RAM addr
89LAST_RAM = 0EF80H ; Seg addr of last possible RAM addr
90NOT_FOUND_INCR = 0800H ; Amount to skip if no ROM found.
91;
92 include emmdef.inc
93 include vdmseg.inc
94 include romstruc.equ ; Option ROM structure.
95PF_LENGTH equ 0400h ; length of a page frame (*16)
96;
97;******************************************************************************
98; S E G M E N T S
99;******************************************************************************
100LAST segment
101 ASSUME CS:LAST, DS:DGROUP
102;
103 page
104;******************************************************************************
105;
106; ROM_SRCH - Search for option ROMs.
107;
108; This section of code searches the auxiliary rom area (from C8000 up
109; to E0000) in 2K increments. A ROM checksum is calculated to insure
110; that the ROMs are valid. Valid ROMs must have the 1st byte = 55H
111; and the next byte = 0AAH. The next byte indicates the size of the
112; ROM in 512-byte blocks. The sum of all bytes in the ROM, modulo 256,
113; must be zero.
114;
115; If a ROM is not found at a location, the next location 2K-bytes down
116; is examined. However, if it is found, the next location after this
117; ROM is tried. The next ROM location is determine according to the
118; size of the previous ROM.
119;
120;
121;******************************************************************************
122rom_srch proc near ; Entry point.
123 push bx
124;
125; search for option ROMs
126;
127 mov ax,FIRST_ROM ; Segment address of first option ROM.
128 cld ; Set direction flag.
129nxt_opt:
130 call opt_rom ; Look for option ROM.
131 jnc not_fnd1 ; No ROM here
132 call upd_seg
133not_fnd1:
134 cmp ax,LAST_ROM ;Q: All ROMs looked at ?
135 jbe nxt_opt ; No, keep looking
136 ; Y: check for VDU roms
137;
138; search for VDM ROMs
139;
140 mov ax,FIRST_VDU_ROM ; segment addr for first vdu ROM
141 cld
142nxt_vdu:
143 call opt_rom ; Q:is it there
144 jnc not_fnd2 ; No ROM here
145 call upd_seg
146not_fnd2:
147 cmp ax,LAST_VDU_ROM ;Q: last VDU ROM ?
148 jbe nxt_vdu ; N: continue
149 ; Y: check for RAM
150;
151; search for RAM
152;
153 mov ax,FIRST_RAM ; first seg addr for RAM search
154 cld
155nxt_ram:
156 call ram_srch ;Q: RAM here ?
157 jnc not_fndr ; N: check again ?
158 call upd_seg
159not_fndr:
160 cmp ax,LAST_RAM ;Q: last RAM location
161 jbe nxt_ram ; N: continue searching
162 ; Y: all done
163;
164 pop bx
165 ret
166rom_srch endp
167 page
168;
169;******************************************************************************
170; OPT_ROM - This routine looks at the ROM located at the segment address
171; specified in AX to see if 0TH and 1ST Bytes = 0AA55H.
172; If so, it calculates the checksum over the length of
173; ROM. If the checksum is valid it updates AX to point
174; to the location of the next ROM.
175;
176; Inputs: AX = Segment address of ROM.
177;
178; Outputs: CY = Found a VDU ROM at this location.
179; NC = Did not find a valid ROM at this location.
180; AX = Segment address of next ROM location.
181; DX = Length of this ROM
182;
183;******************************************************************************
184;
185opt_rom proc near
186 push bx
187 push cx
188 push si
189 push ds
190;
191 mov ds,ax ; DS=ROM segment address.
192 xor bx,bx ; Index uses less code than absolute.
193 cmp [bx.ROM_RECOGNITION],0AA55H ;Q: Looks like a ROM?
194 jne rs_3 ; No, Skip down
195;
196; Compute checksum over ROM.
197;
198 xor si,si ; DS:SI=ROM Pointer; Start at beg.
199 xor cx,cx ; Prepare to accept byte into word.
200 mov ch,[bx.ROM_LEN] ; CH=byte count/512 (CX=byte count/2)
201 shl cx,1 ; CX=adjusted byte count.
202 mov dx,cx ; Extract size.
203rs_2:
204 lodsb ; MOV AL,DS:[SI+]; Pickup next byte.
205 add bl,al ; Checksum += byte(SEG:offset)
206 loop rs_2 ; Loop doesn't affect flags.
207 jnz rs_3 ; Jump down if bad checksum.
208;
209 mov cl,4 ; Shift of 4...
210 shr dx,cl ; Converts bytes to paragraphs (D.03)
211 mov ax,ds ; Replace segment in AX.
212 add ax,dx ; increment segment by this amount
213 stc ; rom found
214 jmp short rs_exit ; Continue.
215;
216rs_3:
217 mov dx,(NOT_FOUND_INCR shr 4) ; Prepare for next ROM.
218 mov ax,ds ; Replace segment in AX.
219 add ax,dx ; Increment segment.
220 clc ; no rom found
221;
222rs_exit:
223 pop ds
224 pop si
225 pop cx
226 pop bx
227 ret ; *** RETURN ***
228;
229opt_rom endp
230 page
231;
232;******************************************************************************
233; RAM_SRCH - This routine looks at the address range potentially used
234; by the Page Frame to determine if any RAM is in the way.
235; It updates the map accordingly.
236;
237; Inputs: AX = Segment address for RAM search.
238;
239; Outputs: CY = Found RAM at this location.
240; NC = Did not find RAM at this location.
241; AX = Segment address of next RAM location.
242; DX = Length of this RAM
243;
244;******************************************************************************
245;
246ram_srch proc near
247
248 push bx
249 push ds
250;
251; search for RAM
252;
253 xor dx,dx ; length = 0
254ram_loop:
255 mov ds,ax
256 add ax,(NOT_FOUND_INCR shr 4); prepare for next chunk
257 mov bx,ds:0 ; get a word
258 xor ds:0,0FFFFh ; flip all bits
259 xor bx,0FFFFh ; BX = "flipped" value
260 cmp bx,ds:0 ;Q: "flipped" value written out ?
261 jne no_more_ram ; N: not RAM - leave
262 xor ds:0,0FFFFh ; Y: is ram, flip bits back
263 add dx,(NOT_FOUND_INCR shr 4); increment length count
264 cmp ax,LAST_RAM ;Q: last RAM location ?
265 jbe ram_loop ; N: continue searching
266 mov ds,ax ; Y: no more searching
267no_more_ram:
268;
269 mov ax,ds ; get current segment
270 or dx,dx ;Q: any RAM found ?
271 jnz ram_found ; Y: set RAM found & chk DS seg again
272 clc ; N: set no RAM
273 add ax,(NOT_FOUND_INCR shr 4) ; AX -> next one to check
274 jmp short ram_exit ; and leave
275;
276ram_found:
277 stc
278ram_exit:
279 pop ds
280 pop bx
281;
282 ret
283ram_srch endp
284 page
285;
286
287;******************************************************************************
288; UPD_SEG - This routine looks at the address range used by the ROM/RAM
289; that was found to determine how many potential physical
290; pages are invalidated from being mappable. It updates
291; the mappable_segs array appropriately.
292;
293; Inputs: AX = Segment address of next ROM/RAM position.
294; DX = Length of ROM/RAM
295;
296; Outputs: [mappable_segs] updated.
297;
298; Written: 8/1/88 ISP
299; Modif: 8/25/88 ISP to make use of exclude_segments
300;******************************************************************************
301upd_seg proc near
302;
303 push bx
304 push ax
305;
306 mov bx,ax
307 sub bx,dx ; bx now has the first segment of the area
308 dec ax ; and ax has the last segment of the area
309;
310 call exclude_segments
311;
312 pop ax
313 pop bx
314 ret
315upd_seg endp
316LAST ENDS
317 END
diff --git a/v4.0/src/MEMM/MEMM/RRTRAP.ASM b/v4.0/src/MEMM/MEMM/RRTRAP.ASM
new file mode 100644
index 0000000..c1bb1a7
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/RRTRAP.ASM
@@ -0,0 +1,436 @@
1
2
3page 58,132
4;******************************************************************************
5 title RRTRAP.ASM - Return To Real Trap
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: RRTRAP.ASM - Return to Real Trap
13;
14; Version: 0.04
15;
16; Date: June 1, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/01/86 Original
27; 06/28/86 0.02 Name changed from MEMM386 to MEMM
28; 07/03/86 0.03 Changed to P84/85 Handlers
29; 07/06/86 0.04 Moved JumpReal to R_CODE and far label
30; 07/06/86 0.04 Changed assume to DGROUP
31;
32;******************************************************************************
33;
34; Functional Description:
35; This module traps ports 85h and 84h and watches for an application
36; to output the Return-to-Real code to these ports. If a 84h=0Fh is output,
37; then 85h=0h is output, the code in this module returns the system
38; to real mode.
39;
40;
41;******************************************************************************
42.lfcond ; list false conditionals
43.386p
44 page
45
46;******************************************************************************
47; I N C L U D E F I L E S
48;
49 include VDMseg.inc
50 include VDMsel.inc
51 include desc.inc
52 include INSTR386.INC
53 include VM386.INC
54;
55;******************************************************************************
56; P U B L I C D E C L A R A T I O N S
57;
58 public RRP_Handler
59 public RR_Trap_Init
60 public RRProc
61 public JumpReal
62;
63;******************************************************************************
64; E X T E R N A L R E F E R E N C E S
65;
66_TEXT segment
67extrn RetReal:near
68extrn PortTrap:near
69_TEXT ends
70
71 page
72;******************************************************************************
73; L O C A L C O N S T A N T S
74;
75FALSE equ 0
76TRUE equ not FALSE
77
78RR85_Value equ 00h
79RR84_Value equ 0Fh
80
81FLAGS_IF equ 0200h
82FLAGS_TF equ 0100h
83
84RR_MASK equ NOT (FLAGS_IF+FLAGS_TF) ; mask off IF and TF bits
85
86RTC_CMD equ 70h ; real time clock command port
87DISABLE_NMI equ 80h ; cmd to disable NMI
88ENABLE_NMI equ 00h ; cmd to enable NMI
89
90;
91;******************************************************************************
92; D A T A S E G M E N T D E F I N I T I O N S
93;
94ABS0 segment at 0000h
95ABS0 ends
96;
97_DATA segment
98RR_Last db 0 ; last RR port trapped
99RR85save db 0FFh
100RR84save db 0FFh
101_DATA ends
102
103;
104;------------------------------------------------------------------------------
105; _TEXT code
106;------------------------------------------------------------------------------
107_TEXT segment
108 assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP
109
110 page
111;******************************************************************************
112; RRP_Handler - I/O Trap handler for return to real ports 84h and 85h
113;
114; ENTRY: Protected Mode Ring 0
115; AL = byte to output to port.
116; BX = 2 * port addr
117; DX == 0 => input
118; <> 0 => output
119; DS = DGROUP
120; SS:SP pts to: IP, saved DS, saved DX, IP ,
121; saved DX,saved BX,saved ESI,saved EBX,saved EBP,
122; then GP fault stack frame with error code.
123; SS:BP = points to stack frame on entry to GP fault handler
124;
125; EXIT: Protected Mode Ring 0
126; CLC => I/O emulated.
127; STC => I/O NOT emulated.
128;
129; USED: Flags
130; STACK:
131;------------------------------------------------------------------------------
132RRP_Handler proc near
133 or dx,dx ;Q: Output ?
134 jz RRP_Bye ; N: then leave
135 cmp bx,84h*2
136 je P84_Handler ; Process port 84h
137 cmp bx,85h*2
138 je P85_Handler ; Process port 85h
139RRP_Bye:
140 stc ; don't bother to emulate it
141 ret
142RRP_Handler endp
143
144;******************************************************************************
145; P84_Handler - I/O Trap handler for port 84h
146;
147; ENTRY: Protected Mode Ring 0
148; AL = byte to output to port.
149; BX = 2 * port addr
150; DX == 0 => input
151; <> 0 => output
152; DS = DGROUP
153; SS:SP pts to: IP, saved DS, saved DX, IP ,
154; saved DX,saved BX,saved ESI,saved EBX,saved EBP,
155; then GP fault stack frame with error code.
156; SS:BP = points to stack frame on entry to GP fault handler
157;
158; EXIT: Protected Mode Ring 0
159; CLC => I/O emulated.
160; STC => I/O NOT emulated.
161;
162; USED: Flags
163; STACK:
164;------------------------------------------------------------------------------
165P84_Handler proc near
166;
167 mov [RR84save],al ; Y: save value written to 84
168 mov [RR_Last],84h ; save this RR port #
169 stc ; don't bother to emulate it
170 ret
171;
172P84_Handler endp
173
174 page
175;******************************************************************************
176; P85_Handler - I/O Trap handler for port 85h
177;
178; ENTRY: Protected Mode Ring 0
179; AL = byte to output to port.
180; BX = 2 * port addr
181; DX == 0 => input
182; <> 0 => output
183; DS = DGROUP
184; SS:SP pts to: IP, saved DS, saved DX, IP ,
185; saved DX,saved BX,saved ESI,saved EBX,saved EBP,
186; then GP fault stack frame with error code.
187; SS:BP = points to stack frame on entry to GP fault handler
188;
189; EXIT: If output to 85h => return to Real
190; RRTrap emulates the output to 85h
191; RRTrap returns to real, fixes the segments and stack, and
192; returns to the instruction past the output in real mode.
193; If output does not imply return to Real
194; Protected Mode Ring 0
195; CLC => I/O emulated.
196; STC => I/O NOT emulated.
197;
198; USED: Flags
199; STACK:
200;------------------------------------------------------------------------------
201P85_Handler proc near
202;
203 mov [RR85save],al ; Y: save value for 85h
204 cmp al,RR85_Value ; Q: return to real value output to 85 ?
205 jne P85_Exit ; N: save port # and leave
206 cmp [RR_Last],84h ; Y: Q: was last 84h last RR port output ?
207 jne P85_Exit ; N: save port # and leave
208 cmp [RR84Save],RR84_Value ; Y: Q: was 84h value RR value ?
209 jne P85_Exit ; N: save port # and leave
210 out 85h,al ; Y: emulate output and
211 jmp RR_GoReal ; return to real(we're in real)
212P85_Exit:
213 mov [RR_Last],85h ; save this RR port addr
214 stc ; don't bother to emulate it
215 ret
216;
217P85_Handler endp
218
219 page
220;******************************************************************************
221; RR_GoReal - return client to real after 84/85 trap
222;
223; This is the return to real code. First we return to real mode.
224; Then we set up the stack, restore the registers and return to
225; the instruction following the out to 85h.
226;**************
227;NOTE: the following depends on the entry stack for P85_Handler
228; the same.
229; ENTRY:
230; SS:SP pts to: IP, saved DS, saved DX, IP ,
231; saved DX,saved BX,saved ESI,saved EBX,saved EBP,
232; then GP fault stack frame with error code.
233;**************
234;******************************************************************************
235;
236RR_GoReal:
237 push ax
238 mov al,DISABLE_NMI
239 out RTC_CMD,al ; disable NMIs
240 pop ax
241
242 call RetReal ; return to real mode, DS,ES = DGROUP
243;
244; now start resetting registers from the stack
245;
246;
247 add sp,8 ; skip IP,DS,DX, and IP
248 pop dx
249 pop bx ; last pushed by OUT emulator
250;
251; now back to stack presented by VmFault's jmp to instr handler
252;
253; on to JumpReal code and continue in Real mode
254;
255 jmp FAR PTR JumpReal
256
257;******************************************************************************
258;
259; RRProc Force processor into real mode
260;
261; entry:
262;
263; exit: Processor is in real mode
264;
265; used: AX
266;
267; stack:
268;
269;******************************************************************************
270RRProc proc near
271 pushf
272 cli ; protect this sequence
273 mov al,RR84_Value ;
274 out 84h,al ; port 84/85 return to real
275 mov al,RR85_Value ; sequence ...
276 out 85h,al ;
277 jmp $+2 ; clear prefetch/avoid race cond
278 popf
279 ret
280RRProc endp
281
282;******************************************************************************
283;
284; RR_Trap_Init Initialize data structure for return to real trapping
285;
286; description: This routine is called when the processor is put in
287; virtual mode. It should initialize anything that is
288; used by the RRTrap code. It assumes that the handler
289; addresses for ports 84h and 85h in IOTrap_Tab are set
290; up to point to RRP_Handler.
291;
292; entry: DS pts to DGROUP
293;
294; exit: Return to real trapping data structure initialized
295;
296; used: AX, BX
297;
298; stack:
299;
300;******************************************************************************
301RR_Trap_Init proc near
302 mov [RR_Last],0 ; reset Return to real trap vars
303 mov [RR85save],0FFh
304 mov [RR84save],0FFh
305 mov bh, 00h ; only set for 0084h and 0085h
306 mov ax, 84h
307 call PortTrap ; set traps on both return to real
308 mov ax, 85h ; ports in case client tries to
309 call PortTrap ; return to real
310 ret
311RR_Trap_Init endp
312
313_TEXT ends ; end of segment
314
315;------------------------------------------------------------------------------
316; R_CODE code
317;------------------------------------------------------------------------------
318R_CODE segment
319 assume cs:R_CODE, ds:DGROUP, es:DGROUP, ss:DGROUP
320;
321;******************************************************************************
322; L O C A L D A T A A R E A
323;******************************************************************************
324;
325RR_Jump label dword ; ret addr for instr after out 84
326RR_JOff dw 0
327RR_JSeg dw 0
328
329RR_DS dw 0 ; DS for return
330RR_SS dw 0 ; SS for return
331RR_SP dw 0 ; SP for return
332
333RR_Flags dw 0 ; low word of flags for return
334
335;******************************************************************************
336;
337; NAME: JumpReal - jump into faulting code and continuing executing in Real
338; mode. When a virtual mode process causes a GP fault, then wishes
339; to continue executing in Real mode afterwards, VDM returns to real
340; mode then calls this routine to "unwind" the stack and continue
341; the process in real mode.
342;
343; THIS IS A FAR JUMP ***
344;
345; ENTRY: REAL MODE
346; SS:[BP] -> points to GP fault stack frame
347; SS:[SP] = saved client's ESI
348; SS:[SP+4] = saved client's EBX
349; SS:[SP+8] = saved client's EBP
350;
351; EXIT: REAL MODE
352; continues execution of process specified in GP fault stack
353; frame.
354;
355;******************************************************************************
356JumpReal label far
357 push cs
358 pop ds ; set DS= CS = R_CODE
359 ASSUME DS:R_CODE
360 ; set up return address
361 mov bx,[bp.VTFOE+VMTF_EIP] ; get return IP
362 mov [RR_JOff],bx ; save it
363 mov bx,[bp.VTFOE+VMTF_CS] ; get return CS
364 mov [RR_JSeg],bx ; save it
365;
366 mov bx,[bp.VTFOE+VMTF_EFLAGS] ; get flags
367 mov [RR_Flags],bx ; and save
368 and [bp.VTFOE+VMTF_EFLAGS],RR_MASK ; mask off certain bits
369;
370 mov bx,[bp.VTFOE+VMTF_DS] ; get DS
371 mov [RR_DS],bx ; save it
372
373 mov bx,[bp.VTFOE+VMTF_SS] ; get SS
374 mov [RR_SS],bx ; save it
375 mov bx,[bp.VTFOE+VMTF_ESP] ; get SP
376 mov [RR_SP],bx ; save it
377;
378; restore regs pushed by VM_Fault entry
379;
380 POP_ESI
381 POP_EBX
382 POP_EBP ; ALL regs except SEGMENT and SP are
383 ; restored.
384 add sp,4+VMTF_ES ; skip error code and GP fault stack
385 ; up to ES
386
387 pop es ; reset ES for return
388 add sp,6 ; skip high word of ES segment
389 ; and DS dword
390
391 POP_FS ; reset FS for return
392 add sp,2 ; skip high word of segment
393
394 POP_GS ; reset GS for return
395;
396; now set flags, DS, stack, and jump to return.
397;
398 test [RR_Flags],FLAGS_IF ;Q: IF bit set in return flags ?
399 jz RR_CLIexit ; N: then just return
400 push [RR_Flags] ; Y: enable interrupts on return
401 popf ; set flags
402 push [RR_DS]
403 pop ds ; set DS for exit
404 push ax
405 mov al,ENABLE_NMI
406 out RTC_CMD,al ; enable NMIs
407 pop ax
408 ;*** there is a small window here
409 ; --- NMI could occur with invalid
410 ; STACK
411
412 mov ss,CS:[RR_SS] ; restore SS
413 mov sp,CS:[RR_SP] ; restore SP
414 sti ; enable ints
415 jmp CS:[RR_Jump] ; and return
416
417RR_CLIexit:
418 push [RR_Flags] ; leave interrupts disabled on return
419 popf ; set flags
420 push [RR_DS]
421 pop ds ; set DS for exit
422 push ax
423 mov al,ENABLE_NMI
424 out RTC_CMD,al ; enable NMIs
425 pop ax
426 ;*** there is a small window here
427 ; --- NMI could occur with invalid
428 ; STACK
429
430 mov ss,CS:[RR_SS] ; restore SS
431 mov sp,CS:[RR_SP] ; restore SP
432 jmp CS:[RR_Jump] ; far jump for return
433;
434R_CODE ends ; end of segment
435;
436 end ; end of module
diff --git a/v4.0/src/MEMM/MEMM/SHIPHI.ASM b/v4.0/src/MEMM/MEMM/SHIPHI.ASM
new file mode 100644
index 0000000..be09a96
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/SHIPHI.ASM
@@ -0,0 +1,325 @@
1
2
3 page 58,132
4;******************************************************************************
5 TITLE SHIPHI - MODULE to ship a segment up hi
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: SHIPHI - Ship a segment up hi into extended memory
13;
14; Version: 0.01
15;
16; Date: Sep 1, 1988
17;
18; Author: ISP
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26;******************************************************************************
27; Functional Description:
28;
29; We need to ship data structures up hi.
30; This file has routines to specify size requirements for this operation
31; and to shift a segment up hi. Remember that in shipping a segment up hi
32; the GDT segment should be the last to be sent up since it is modified while
33; shipping a segment up hi
34;
35;******************************************************************************
36.lfcond
37.386p
38
39 page
40;******************************************************************************
41; P U B L I C D E C L A R A T I O N S
42;******************************************************************************
43 public set_src_selector ; Routines and data(GDT) for move block
44 public set_dest_selector
45 public moveb
46 public memreq
47
48 public gdt_mb
49
50
51 page
52;******************************************************************************
53; L O C A L C O N S T A N T S
54;******************************************************************************
55;
56
57;******************************************************************************
58; INCLUDE FILES
59;******************************************************************************
60 include vdmseg.inc ; segment definitions
61 include desc.inc ;
62 include page.inc
63
64 page
65;******************************************************************************
66; E X T E R N A L R E F E R E N C E S
67;******************************************************************************
68;
69;
70LAST SEGMENT
71 extrn get_buffer:near
72LAST ENDS
73
74 page
75;******************************************************************************
76; S E G M E N T D E F I N I T I O N
77;******************************************************************************
78
79;*************************************************************************
80;
81; DATA
82;
83;*************************************************************************
84
85_DATA SEGMENT
86 ASSUME CS:DGROUP,DS:DGROUP
87;
88_DATA ENDS
89
90
91
92
93LAST SEGMENT
94ASSUME CS:LAST,DS:DGROUP,ES:DGROUP
95
96; GDT for ROM Move Block calls
97;
98gdt_mb label word
99;
100gdt0_mb: GDT_ENTRY 0,0,1,0 ; Dummy seg descriptor
101gdt1_mb: GDT_ENTRY 0,0,1,0 ; GDT seg descriptor
102gdt2_mb: GDT_ENTRY 0,0,0,D_DATA3 ; Src seg descriptor
103gdt3_mb: GDT_ENTRY 0,0,0,D_DATA3 ; Dest seg descriptor
104gdt4_mb: GDT_ENTRY 0,0,1,0 ; Bios cs seg descriptor
105gdt5_mb: GDT_ENTRY 0,0,1,0 ; Bios ss seg descriptor
106;
107
108LAST ENDS
109
110;*************************************************************************
111;
112; CODE
113;
114;*************************************************************************
115LAST SEGMENT
116ASSUME CS:LAST,DS:DGROUP,ES:DGROUP
117
118;******************************************************************************
119; SHIPHI - routine to ship a segment up hi ;
120; ;
121; INPUTS: es = segment to be moved up ;
122; cx = number of bytes in the segment ;
123; ;
124; OUTPUTS: dx:ax = new address of the segment ;
125; Z set if succeeded, NZ if error ;
126; ;
127; USES: ax,dx,flags ;
128; ;
129; CALLS: ;
130; ;
131; AUTHOR: ISP (ISP) Sep 2, 1988 ;
132; ;
133;*****************************************************************************;
134SHIPHI proc near
135 ;
136 push di
137 ;
138 ; first get some memory to play with
139 ;
140 call get_buffer
141 ;
142 ; then move the segment up to this new segment
143 ;
144 xor dh,dh ; dx:ax 32 bit addr of dest
145 xor di,di ; es:di is source segment
146 call moveb
147 ;
148 pop di
149 ;
150 ret
151SHIPHI endp
152
153
154
155;*****************************************************************************;
156;*** MOVEB *** ;
157; ;
158; Move data between from conventional memory to extended memory ;
159; ;
160; ;
161; INPUTS: dl:ax = 24 bit address of extended memory address ;
162; es:di = source address in lo memory
163; cx = number of bytes to transfer
164; ;
165; OUTPUTS: Z set if succeeded ;
166; NZ if error ;
167; ;
168; USES: ;
169; ;
170; AUTHOR: ISP, Sep 2,1988. ;
171; ;
172;*****************************************************************************;
173
174
175MOVEB proc near
176 push es
177 push dx
178 push ax
179 push di
180 push cx
181
182
183 ;
184 ; no setup needed for dest selector, already set up.
185 ;
186 call set_dest_selector ; destination is unlock address
187 ;
188 ; for source selector we need to convert segment:offset to dl:ax
189 ; cx is already # of words
190 ;
191 xor dx,dx
192 mov ax,es
193 mov bx,16
194 mul bx
195 add ax,di
196 adc dx,0
197
198 call set_src_selector ; set source segment selector to buffer
199 ;
200 ; do the block move
201 ;
202 mov si,seg LAST
203 mov es,si
204 mov si,offset LAST:gdt_mb ; ES:SI -> global descriptor table
205 ;
206 ; convert count to number of words
207 ;
208 inc cx
209 shr cx,1
210;
211 ;
212 mov ah,87h ; int 15 block move function code
213 int 15h ; unlock rom
214 or ah,ah ; Q: error?
215 ; Y: return NZ
216 pop cx
217 pop di
218 pop ax
219 pop dx
220 pop es
221 ; N: return Z
222 ret
223MOVEB endp
224
225 page
226;******************************************************************************
227;
228; set_src_selector
229; Set base address, limit of source segment selector
230; in gdt_mb for int 15h block move
231;
232;
233; entry: dl:ax == source address (24 bits)
234; cx == size, in words
235;
236; exit: gdt_mb(2) contains source base address, limit
237;
238; used: none
239;
240;******************************************************************************
241;
242set_src_selector proc near
243;
244 push di
245 mov di,offset LAST:gdt2_mb ; cs:di -> source seg descriptor
246set_entry:
247 mov cs:[di.BASE_LOW],ax ; Store base address bits 15:00
248 mov cs:[di.BASE_HIGH],dl ; Store base address bits 23:16
249 mov cs:[di.LIMIT],cx ; Store size
250 sub cs:[di.LIMIT],1 ; subtract 1 => convert to limit
251;
252 pop di
253 ret ; *** Return ***
254;
255set_src_selector endp ; End of procedure
256;
257 page
258;******************************************************************************
259;
260; set_dest_selector
261; Set base address, limit of destination segment selector
262; in gdt_mb for int 15h block move
263;
264; entry: dx:ax == address (32 bits)
265; cx == size of segment, in words
266; ds = DGROUP
267;
268; exit: gdt_mb(3) contains destination base address,
269; limit
270;
271; used: none
272;
273;******************************************************************************
274;
275set_dest_selector proc near
276;
277 push di
278 mov di,offset LAST:gdt3_mb ; cs:di -> source seg descriptor
279 mov cs:[di.BASE_XHI],dh ; bits 24-31
280 jmp set_entry ; set this entry in gdt_mb
281;
282 ret ; *** Return ***
283;
284set_dest_selector endp ; End of procedure
285
286
287
288
289
290
291
292;******************************************************************************
293; MEMREQ - routine to determine memory requirements for shifting the driver ;
294; up into extended memory ;
295; ;
296; INPUTS: none ;
297; ;
298; OUTPUTS: CX = size requirements in K ;
299; ;
300; USES: CX, flags ;
301; ;
302; AUTHOR: ISP (ISP) Sep 2, 1988 ;
303; ;
304;*****************************************************************************;
305MEMREQ proc near
306;
307 push ax
308;
309 mov ax,seg LAST ; this is the last segment and
310 ; one which is discarded.
311 sub ax,seg PAGESEG ; this is the first segment of the
312 ; region which is to be moved.
313
314 add ax, (P_SIZE/16 -1) ; to round it up to next page bdry
315 shr ax, 6 ; find the size in K
316 add ax,16 ; throw in 4 more pages for safety
317 mov cx,ax ; and return the size needed
318;
319 pop ax
320 ret
321MEMREQ endp
322
323LAST ENDS
324
325 end
diff --git a/v4.0/src/MEMM/MEMM/TABDEF.ASM b/v4.0/src/MEMM/MEMM/TABDEF.ASM
new file mode 100644
index 0000000..c70406e
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/TABDEF.ASM
@@ -0,0 +1,357 @@
1
2
3page 58,132
4;******************************************************************************
5 title TABDEF.ASM - 386 Protected Mode CPU Tables
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: TABDEF.ASM - 386 Protected Mode CPU Tables
13;
14; Version: 0.04
15;
16; Date: January 31, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 01/31/86 Tables for Standalone protected mode system
27; A- Modified for Virtual DOS
28; 05/12/86 B- Cleanup and segment reorganization
29; 06/28/86 0.02 Name changed from MEMM386 to MEMM
30; 07/05/86 0.04 Moved KBD and PRINT to DCODE segment
31; 07/20/88 Remove debugger codes (pc)
32;
33;******************************************************************************
34;
35; Functional Description:
36;
37;******************************************************************************
38.lfcond ; list false conditionals
39.386p
40
41NAME tabdef
42;
43
44.xlist
45 include VDMseg.inc
46 include VDMsel.inc
47 include desc.inc
48 include page.inc
49.list
50
51
52_TEXT SEGMENT
53 extrn vm_trap00:far
54 extrn vm_trap01:far
55 extrn vm_trap02:far
56 extrn vm_trap03:far
57 extrn vm_trap04:far
58 extrn vm_trap05:far
59 extrn vm_trap06:far
60 extrn vm_trap07:far
61 extrn vm_trap08:far
62 extrn vm_trap09:far
63 extrn vm_trap0a:far
64 extrn vm_trap0b:far
65 extrn vm_trap0c:far
66 extrn vm_trap0d:far
67 extrn vm_trap0e:far
68 extrn vm_trap0f:far
69 extrn vm_trap50:far
70 extrn vm_trap51:far
71 extrn vm_trap52:far
72 extrn vm_trap53:far
73 extrn vm_trap54:far
74 extrn vm_trap55:far
75 extrn vm_trap56:far
76 extrn vm_trap57:far
77 extrn vm_trap70:far
78 extrn vm_trap71:far
79 extrn vm_trap72:far
80 extrn vm_trap73:far
81 extrn vm_trap74:far
82 extrn vm_trap75:far
83 extrn vm_trap76:far
84 extrn vm_trap77:far
85
86 extrn EMM_pEntry:far
87
88_TEXT ENDS
89
90
91;*** GDT - Global Descriptor Table
92;
93; This is the system GDT. Some parts are statically initialised,
94; others must be set up at run time, either because masm can't
95; calculate the data or it changes while the system is running.
96;
97; WARNING
98;
99; Don't change this without consulting "sel.inc", and the
100; routines which initialise the gdt.
101;
102
103GDT SEGMENT
104
105gdtstart label byte ; label for everyone to refer to the GDT
106
107GDT_ENTRY 0, 0, 1, 0 ; null selector
108GDT_ENTRY 0, 0, 0, D_DATA0 ; GDT alias
109GDT_ENTRY 0, 0, 0, D_DATA0 ; IDT alias
110GDT_ENTRY 0, 0, 0, D_LDT0 ; LDT
111GDT_ENTRY 0, 0, 0, D_DATA0 ; LDT alias
112GDT_ENTRY 0, 0, 0, D_386TSS0 ; TSS
113GDT_ENTRY 0, 0, 0, D_DATA0 ; TSS alias
114GDT_ENTRY 0, 0, <400h>, D_DATA3 ; Real Mode IDT
115GDT_ENTRY 400h, 0, <300h>, D_DATA0 ; ROM Data
116GDT_ENTRY 0, 0, 0, D_CODE0 ; VDM Code
117GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Data
118GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Stack
119GDT_ENTRY 0, 0bh, 1000h, D_DATA0 ; Mono Display
120GDT_ENTRY 8000h, 0bh, 4000h, D_DATA0 ; Colour Disp
121GDT_ENTRY 0, 0ah, 0, D_DATA0 ; EGA Low
122GDT_ENTRY 0, 0ch, 0, D_DATA0 ; EGA High
123GDT_ENTRY 800h, 0, 66h, D_DATA0 ; LOADALL
124GDT_ENTRY 0, 0, 0, 0 ; debugger work 1
125GDT_ENTRY 0, 0, 0, 0 ; debugger work 2
126GDT_ENTRY 0, 0, 0, 0 ; debugger work 3
127GDT_ENTRY 0, 0, 0, 0 ; debugger work 4
128GDT_ENTRY 0, 0, 0, 0 ; debugger work 5
129GDT_ENTRY 0, 0, 0, 0 ; debugger work (Addresses all memory)
130GDT_ENTRY 0, 0, 0, 0 ; general work
131GDT_ENTRY 0, 0, 0, 0 ; general work
132GDT_ENTRY 0, 0, 0, D_CODE0 ; maps CODE segment
133GDT_ENTRY 0, 0, 0, D_DATA0 ; VM1_GSEL - vm trap scratch
134GDT_ENTRY 0, 0, 0, D_DATA0 ; VM2_GSEL - vm trap scratch
135GDT_ENTRY 0, 0, 0, D_DATA0 ; MBSRC_GSEL - move blk scratch
136GDT_ENTRY 0, 0, 0, D_DATA0 ; MBTAR_GSEL - move blk scratch
137GDT_ENTRY 0, 0, 0, D_DATA0 ; PAGET_GSEL - page table area
138GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Code - Data Alias
139GDT_ENTRY 0, 0, 0, D_DATA0 ; EMM1 - EMM scratch selector
140GDT_ENTRY 0, 0, 0, D_DATA0 ; EMM2 - EMM scratch selector
141GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM0 entry
142GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM1 entry
143GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM2 entry
144GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM3 entry
145GDT_ENTRY 0, 0, 0, D_DATA0 ; USER1 entry
146
147 public GDTLEN
148GDTLEN equ $ - gdtstart
149
150GDT ENDS
151
152
153;*** TSS for protected Mode
154;
155; This is the VDM TSS. We only use one, for loading
156; SS:SP on privilige transitions. We don't use all
157; the 286 task switching stuff.
158;
159;
160
161TSS segment
162;
163 TssArea TSS386STRUC <>
164;
165; I/O Bit Map for Virtual Mode I/O trapping
166;
167 public IOBitMap
168IOBitMap label byte
169 db 2000h dup (0) ; initialize all ports to NO trapping
170 db 0FFh ; last byte is all 1's
171
172 public TSSLEN
173TSSLEN equ $ - tss
174
175TSS ends
176
177;*** IDT for protected mode
178;
179; This is the protected mode interrupt descriptor table.
180;
181; The first 78h entries are defined. Only processor exceptions and
182; hardware interrupts are fielded through the PM IDT. Since the
183; gate DPLs are < 3, all software INTs are funneled through INT 13
184; (GP exception) and emulated. Note that Null IDT entries and limit
185; exceptions produce the same results (GP error code) as DPL faults,
186; so we can use a truncated IDT. This assumes no one is reprogramming
187; the 8259s base vector for some reason - don't know of any DOS apps
188; that do this.
189;
190IDT SEGMENT
191
192idtstart label byte
193
194IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap00>,D_386INT0 ; 00 Divide Error
195IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap01>,D_386INT0 ; 01 Debug
196IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap02>,D_386INT0 ; 02 NMI/287 Error
197IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap03>,D_386INT0 ; 03 Breakpoint
198IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap04>,D_386INT0 ; 04 INTO
199IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap05>,D_386INT0 ; 05 BOUND/Print Screen
200IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap06>,D_386INT0 ; 06 Invalid Opcode
201IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap07>,D_386INT0 ; 07 287 Not Available
202
203IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap08>,D_386INT0 ; 08 Double Exception/Timer
204IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap09>,D_386INT0 ; 09 (not on 386)/Keyboard
205IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0a>,D_386INT0 ; 0A Invalid TSS/Cascade
206IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0b>,D_386INT0 ; 0B Segment Not Present/COM2
207IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0c>,D_386INT0 ; 0C Stack Fault/COM1
208IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0d>,D_386INT0 ; 0D General Protection/LPT2
209IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0e>,D_386INT0 ; 0E Page Fault/Diskette
210IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0F>,D_386INT0 ; 0F Intel Reserved/LPT1
211
212IDT_ENTRY 0, 0, 0 ; 10 [287 Error]/Video INT (This exception
213 ; cannot occur on AT architecture)
214IDT_ENTRY 0, 0, 0 ; 11 Equipment Check
215IDT_ENTRY 0, 0, 0 ; 12 Memory Size
216IDT_ENTRY 0, 0, 0 ; 13 Disk INT
217IDT_ENTRY 0, 0, 0 ; 14 RS232
218IDT_ENTRY 0, 0, 0 ; 15 Post&Wait, mov_blk via GP fault
219IDT_ENTRY 0, 0, 0 ; 16 Keyboard
220IDT_ENTRY 0, 0, 0 ; 17 Printer
221
222IDT_ENTRY 0, 0, 0 ; 18 Resident BASIC
223IDT_ENTRY 0, 0, 0 ; 19 Bootstrap
224IDT_ENTRY 0, 0, 0 ; 1A Time of Day
225IDT_ENTRY 0, 0, 0 ; 1B Break
226IDT_ENTRY 0, 0, 0 ; 1C Timer Tick
227IDT_ENTRY 0, 0, 0 ; 1D Ptr to Video Param
228IDT_ENTRY 0, 0, 0 ; 1E Ptr to Disk Params
229IDT_ENTRY 0, 0, 0 ; 1F Ptr to Graphics
230
231IDT_ENTRY 0, 0, 0 ; 20 DOS
232IDT_ENTRY 0, 0, 0 ; 21 DOS
233IDT_ENTRY 0, 0, 0 ; 22 DOS
234IDT_ENTRY 0, 0, 0 ; 23 DOS
235IDT_ENTRY 0, 0, 0 ; 24 DOS
236IDT_ENTRY 0, 0, 0 ; 25 DOS
237IDT_ENTRY 0, 0, 0 ; 26 DOS
238IDT_ENTRY 0, 0, 0 ; 27 DOS
239
240IDT_ENTRY 0, 0, 0 ; 28 DOS
241IDT_ENTRY 0, 0, 0 ; 29 DOS
242IDT_ENTRY 0, 0, 0 ; 2A DOS
243IDT_ENTRY 0, 0, 0 ; 2B DOS
244IDT_ENTRY 0, 0, 0 ; 2C DOS
245IDT_ENTRY 0, 0, 0 ; 2D DOS
246IDT_ENTRY 0, 0, 0 ; 2E DOS
247IDT_ENTRY 0, 0, 0 ; 2F DOS
248
249IDT_ENTRY 0, 0, 0 ; 30 DOS
250IDT_ENTRY 0, 0, 0 ; 31 DOS
251IDT_ENTRY 0, 0, 0 ; 32 DOS
252IDT_ENTRY 0, 0, 0 ; 33 DOS
253IDT_ENTRY 0, 0, 0 ; 34 DOS
254IDT_ENTRY 0, 0, 0 ; 35 DOS
255IDT_ENTRY 0, 0, 0 ; 36 DOS
256IDT_ENTRY 0, 0, 0 ; 37 DOS
257
258IDT_ENTRY 0, 0, 0 ; 38 DOS
259IDT_ENTRY 0, 0, 0 ; 39 DOS
260IDT_ENTRY 0, 0, 0 ; 3A DOS
261IDT_ENTRY 0, 0, 0 ; 3B DOS
262IDT_ENTRY 0, 0, 0 ; 3C DOS
263IDT_ENTRY 0, 0, 0 ; 3D DOS
264IDT_ENTRY 0, 0, 0 ; 3E DOS
265IDT_ENTRY 0, 0, 0 ; 3F DOS
266
267IDT_ENTRY 0, 0, 0 ; 40 Reserved
268IDT_ENTRY 0, 0, 0 ; 41 Reserved
269IDT_ENTRY 0, 0, 0 ; 42 Reserved
270IDT_ENTRY 0, 0, 0 ; 43 Reserved
271IDT_ENTRY 0, 0, 0 ; 44 Reserved
272IDT_ENTRY 0, 0, 0 ; 45 Reserved
273IDT_ENTRY 0, 0, 0 ; 46 Reserved
274IDT_ENTRY 0, 0, 0 ; 47 Reserved
275
276IDT_ENTRY 0, 0, 0 ; 48 Reserved
277IDT_ENTRY 0, 0, 0 ; 49 Reserved
278IDT_ENTRY 0, 0, 0 ; 4A Reserved
279IDT_ENTRY 0, 0, 0 ; 4B Reserved
280IDT_ENTRY 0, 0, 0 ; 4C Reserved
281IDT_ENTRY 0, 0, 0 ; 4D Reserved
282IDT_ENTRY 0, 0, 0 ; 4E Reserved
283IDT_ENTRY 0, 0, 0 ; 4F Reserved
284
285;
286; The following table entries assume the master 8259 base vector has been
287; set up to 50h.
288;
289IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap50>,D_386INT0 ; 50 Timer Interrupt
290IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap51>,D_386INT0 ; 51 Keyboard Interrupt
291IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap52>,D_386INT0 ; 52 Misc peripheral Interrupt
292IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap53>,D_386INT0 ; 53 COM2
293IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap54>,D_386INT0 ; 54 COM1
294IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap55>,D_386INT0 ; 55 2nd Parallel
295IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap56>,D_386INT0 ; 56 Diskette Interrupt
296IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap57>,D_386INT0 ; 57 1st Parallel
297
298IDT_ENTRY 0, 0, 0 ; 58 Reserved
299IDT_ENTRY 0, 0, 0 ; 59 Reserved
300IDT_ENTRY 0, 0, 0 ; 5A Reserved
301IDT_ENTRY 0, 0, 0 ; 5B Reserved
302IDT_ENTRY 0, 0, 0 ; 5C Reserved
303IDT_ENTRY 0, 0, 0 ; 5D Reserved
304IDT_ENTRY 0, 0, 0 ; 5E Reserved
305IDT_ENTRY 0, 0, 0 ; 5F Reserved
306
307IDT_ENTRY 0, 0, 0 ; 60 User Programs
308IDT_ENTRY 0, 0, 0 ; 61 User Programs
309IDT_ENTRY 0, 0, 0 ; 62 User Programs
310IDT_ENTRY 0, 0, 0 ; 63 User Programs
311IDT_ENTRY 0, 0, 0 ; 64 User Programs
312IDT_ENTRY 0, 0, 0 ; 65 User Programs
313IDT_ENTRY 0, 0, 0 ; 66 User Programs
314;;;IDT_ENTRY 0, 0, 0 ; 67 User Programs
315IDT_ENTRY VDMC_GSEL,<offset _TEXT:EMM_pEntry>,D_386INT3 ; 67 ELIM
316
317IDT_ENTRY 0, 0, 0 ; 68 Not Used
318IDT_ENTRY 0, 0, 0 ; 69 Not Used
319IDT_ENTRY 0, 0, 0 ; 6A Not Used
320IDT_ENTRY 0, 0, 0 ; 6B Not Used
321IDT_ENTRY 0, 0, 0 ; 6C Not Used
322IDT_ENTRY 0, 0, 0 ; 6D Not Used
323IDT_ENTRY 0, 0, 0 ; 6E Not Used
324IDT_ENTRY 0, 0, 0 ; 6F Not Used
325
326IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap70>,D_386INT0 ; 70 IRQ8 - Real Time Clock
327IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap71>,D_386INT0 ; 71 IRQ9
328IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap72>,D_386INT0 ; 72 IRQ10
329IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap73>,D_386INT0 ; 73 IRQ11
330IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap74>,D_386INT0 ; 74 IRQ12
331IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap75>,D_386INT0 ; 75 IRQ13 - 287 error
332IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap76>,D_386INT0 ; 76 IRQ14 - Fixed disk
333IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap77>,D_386INT0 ; 77 IRQ15
334
335 public IDTLEN
336idtlen equ this byte - idtstart
337
338IDT ends
339
340PAGESEG SEGMENT
341;*** Page Tables Area
342;
343; This area is used for the page directory and page tables
344;
345
346 public P_TABLE_CNT
347P_TABLE_CNT equ 5 ; # of page tables
348
349 public Page_Area
350Page_Area label byte
351 db (2+P_TABLE_CNT) * P_SIZE dup (0) ; enough for page dir &
352 ; tables after page
353 ; alignment.
354PAGESEG ENDS
355
356 END
357 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/TRAPDEF.ASM b/v4.0/src/MEMM/MEMM/TRAPDEF.ASM
new file mode 100644
index 0000000..b82f661
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/TRAPDEF.ASM
@@ -0,0 +1,469 @@
1
2
3 page 58,132
4;******************************************************************************
5 title TRAPDEF.ASM - I/O trap Dispatch table
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: TRAPDEF.ASM - I/O trap Dispatch table
13;
14; Version: 0.04
15;
16; Date: July 1, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 08/11/86 Split from IOTrap.asm
27;
28; 7/26/88 Added Trap handler entries for DMA ports on Channel 4
29; - Jaywant H Bharadwaj
30;
31;******************************************************************************
32;
33.lfcond ; list false conditionals
34.386p
35 page
36;******************************************************************************
37; P U B L I C D E C L A R A T I O N S
38;******************************************************************************
39;
40 public IOTrap_Tab ; dispatches I/O trap handlers
41 public IOT_BadT ; Unknown port trap routine
42 public IOT_OEM ; OEM specific port emulation
43
44 page
45;******************************************************************************
46; L O C A L C O N S T A N T S
47;******************************************************************************
48;
49; % - how many of these are actually needed?
50; % - Need any includes from Win/386 DMA code - trapdef.asm ?
51
52 include VDMseg.inc
53 include VDMsel.inc
54 include desc.inc
55 include elim.inc
56 include page.inc
57 include oemdep.inc
58 include instr386.inc
59 include vm386.inc
60;
61;******************************************************************************
62; E X T E R N A L R E F E R E N C E S
63;******************************************************************************
64;
65
66_DATA segment
67;extrn _map_size:byte ; # of mapping registers used
68;extrn LIMP_Addr:word
69_DATA ends
70
71_TEXT segment
72;
73extrn RRP_Handler:near
74extrn A20_Handler:near ; Kybd Data port - A20 watch
75extrn DMABase0:near ; DMA base register for Channel 0
76extrn DMABase1:near ; DMA base register for Channel 1
77extrn DMABase2:near ; DMA base register for Channel 2
78extrn DMABase3:near ; DMA base register for Channel 3
79extrn DMABase5:near ; DMA base register for Channel 5
80extrn DMABase6:near ; DMA base register for Channel 6
81extrn DMABase7:near ; DMA base register for Channel 7
82extrn DMACnt0:near ; DMA count register for Channel 0
83extrn DMACnt1:near ; DMA count register for Channel 1
84extrn DMACnt2:near ; DMA count register for Channel 2
85extrn DMACnt3:near ; DMA count register for Channel 3
86extrn DMACnt5:near ; DMA count register for Channel 5
87extrn DMACnt6:near ; DMA count register for Channel 6
88extrn DMACnt7:near ; DMA count register for Channel 7
89extrn DMAPg0:near ; DMA page register for Channel 0
90extrn DMAPg1:near ; DMA page register for Channel 1
91extrn DMAPg2:near ; DMA page register for Channel 2
92extrn DMAPg3:near ; DMA page register for Channel 3
93extrn DMAPg5:near ; DMA page register for Channel 5
94extrn DMAPg6:near ; DMA page register for Channel 6
95extrn DMAPg7:near ; DMA page register for Channel 7
96extrn DMAClrFF1:near ; clear flip-flop cmd for channels 0-3
97extrn DMAClrFF2:near ; clear flip-flop cmd for channels 5-7
98extrn DMAMode1:near ; Mode register for channels 0-3
99extrn DMAMode2:near ; Mode register for channels 4-7
100
101_TEXT ends
102
103;******************************************************************************
104; S E G M E N T D E F I N I T I O N
105;******************************************************************************
106
107;
108;------------------------------------------------------------------------------
109_TEXT segment
110 assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP
111;
112; IOTrapTab
113; One entry per port in the I/O space from 00h to FFh.
114; Note that ports not specifically mapped otherwise(by IOT_OEM or
115; LIM emulation and whose least significant 10 bits are less than
116; 100h are also dispatched through this table(upper 6 bits assumed to
117; be intended as zero since some earlier systems only had 10 bits of
118; I/O addressing).
119;
120IOTrap_Tab label word
121 dw offset _TEXT:DMAbase0 ; 0 DMA base register for Channel 0
122 dw offset _TEXT:DMACnt0 ; 1 DMA count register for Channel 0
123 dw offset _TEXT:DMABase1 ; 2 DMA base register for Channel 1
124 dw offset _TEXT:DMACnt1 ; 3 DMA count register for Channel 1
125 dw offset _TEXT:DMABase2 ; 4 DMA base register for Channel 2
126 dw offset _TEXT:DMACnt2 ; 5 DMA count register for Channel 2
127 dw offset _TEXT:DMABase3 ; 6 DMA base register for Channel 3
128 dw offset _TEXT:DMACnt3 ; 7 DMA count register for Channel 3
129 dw offset _TEXT:IOT_BadT ; 8
130 dw offset _TEXT:IOT_BadT ; 9
131 dw offset _TEXT:IOT_BadT ; a
132 dw offset _TEXT:DMAMode1 ; b DMA Mode Register for for Ch 0-3
133 dw offset _TEXT:DMAClrFF1 ; c clear flip-flop cmd for channels 0-3
134 dw offset _TEXT:IOT_BadT ; d
135 dw offset _TEXT:IOT_BadT ; e
136 dw offset _TEXT:IOT_BadT ; f
137 dw offset _TEXT:IOT_BadT ; 10
138 dw offset _TEXT:IOT_BadT ; 11
139 dw offset _TEXT:IOT_BadT ; 12
140 dw offset _TEXT:IOT_BadT ; 13
141 dw offset _TEXT:IOT_BadT ; 14
142 dw offset _TEXT:IOT_BadT ; 15
143 dw offset _TEXT:IOT_BadT ; 16
144 dw offset _TEXT:IOT_BadT ; 17
145 dw offset _TEXT:IOT_BadT ; 18
146 dw offset _TEXT:IOT_BadT ; 19
147 dw offset _TEXT:IOT_BadT ; 1a
148 dw offset _TEXT:IOT_BadT ; 1b
149 dw offset _TEXT:IOT_BadT ; 1c
150 dw offset _TEXT:IOT_BadT ; 1d
151 dw offset _TEXT:IOT_BadT ; 1e
152 dw offset _TEXT:IOT_BadT ; 1f
153 dw offset _TEXT:IOT_BadT ; 20
154 dw offset _TEXT:IOT_BadT ; 21
155 dw offset _TEXT:IOT_BadT ; 22
156 dw offset _TEXT:IOT_BadT ; 23
157 dw offset _TEXT:IOT_BadT ; 24
158 dw offset _TEXT:IOT_BadT ; 25
159 dw offset _TEXT:IOT_BadT ; 26
160 dw offset _TEXT:IOT_BadT ; 27
161 dw offset _TEXT:IOT_BadT ; 28
162 dw offset _TEXT:IOT_BadT ; 29
163 dw offset _TEXT:IOT_BadT ; 2a
164 dw offset _TEXT:IOT_BadT ; 2b
165 dw offset _TEXT:IOT_BadT ; 2c
166 dw offset _TEXT:IOT_BadT ; 2d
167 dw offset _TEXT:IOT_BadT ; 2e
168 dw offset _TEXT:IOT_BadT ; 2f
169 dw offset _TEXT:IOT_BadT ; 30
170 dw offset _TEXT:IOT_BadT ; 31
171 dw offset _TEXT:IOT_BadT ; 32
172 dw offset _TEXT:IOT_BadT ; 33
173 dw offset _TEXT:IOT_BadT ; 34
174 dw offset _TEXT:IOT_BadT ; 35
175 dw offset _TEXT:IOT_BadT ; 36
176 dw offset _TEXT:IOT_BadT ; 37
177 dw offset _TEXT:IOT_BadT ; 38
178 dw offset _TEXT:IOT_BadT ; 39
179 dw offset _TEXT:IOT_BadT ; 3a
180 dw offset _TEXT:IOT_BadT ; 3b
181 dw offset _TEXT:IOT_BadT ; 3c
182 dw offset _TEXT:IOT_BadT ; 3d
183 dw offset _TEXT:IOT_BadT ; 3e
184 dw offset _TEXT:IOT_BadT ; 3f
185 dw offset _TEXT:IOT_BadT ; 40
186 dw offset _TEXT:IOT_BadT ; 41
187 dw offset _TEXT:IOT_BadT ; 42
188 dw offset _TEXT:IOT_BadT ; 43
189 dw offset _TEXT:IOT_BadT ; 44
190 dw offset _TEXT:IOT_BadT ; 45
191 dw offset _TEXT:IOT_BadT ; 46
192 dw offset _TEXT:IOT_BadT ; 47
193 dw offset _TEXT:IOT_BadT ; 48
194 dw offset _TEXT:IOT_BadT ; 49
195 dw offset _TEXT:IOT_BadT ; 4a
196 dw offset _TEXT:IOT_BadT ; 4b
197 dw offset _TEXT:IOT_BadT ; 4c
198 dw offset _TEXT:IOT_BadT ; 4d
199 dw offset _TEXT:IOT_BadT ; 4e
200 dw offset _TEXT:IOT_BadT ; 4f
201 dw offset _TEXT:IOT_BadT ; 50
202 dw offset _TEXT:IOT_BadT ; 51
203 dw offset _TEXT:IOT_BadT ; 52
204 dw offset _TEXT:IOT_BadT ; 53
205 dw offset _TEXT:IOT_BadT ; 54
206 dw offset _TEXT:IOT_BadT ; 55
207 dw offset _TEXT:IOT_BadT ; 56
208 dw offset _TEXT:IOT_BadT ; 57
209 dw offset _TEXT:IOT_BadT ; 58
210 dw offset _TEXT:IOT_BadT ; 59
211 dw offset _TEXT:IOT_BadT ; 5a
212 dw offset _TEXT:IOT_BadT ; 5b
213 dw offset _TEXT:IOT_BadT ; 5c
214 dw offset _TEXT:IOT_BadT ; 5d
215 dw offset _TEXT:IOT_BadT ; 5e
216 dw offset _TEXT:IOT_BadT ; 5f
217 dw offset _TEXT:A20_Handler ; A20 watch on kybd data port
218 dw offset _TEXT:IOT_BadT ; 61
219 dw offset _TEXT:IOT_BadT ; 62
220 dw offset _TEXT:IOT_BadT ; 63
221 dw offset _TEXT:A20_Handler ; A20 watch on kybd cmd port
222 dw offset _TEXT:IOT_BadT ; 65
223 dw offset _TEXT:IOT_BadT ; 66
224 dw offset _TEXT:IOT_BadT ; 67
225 dw offset _TEXT:IOT_BadT ; 68
226 dw offset _TEXT:IOT_BadT ; 69
227 dw offset _TEXT:IOT_BadT ; 6a
228 dw offset _TEXT:IOT_BadT ; 6b
229 dw offset _TEXT:IOT_BadT ; 6c
230 dw offset _TEXT:IOT_BadT ; 6d
231 dw offset _TEXT:IOT_BadT ; 6e
232 dw offset _TEXT:IOT_BadT ; 6f
233 dw offset _TEXT:IOT_BadT ; 70
234 dw offset _TEXT:IOT_BadT ; 71
235 dw offset _TEXT:IOT_BadT ; 72
236 dw offset _TEXT:IOT_BadT ; 73
237 dw offset _TEXT:IOT_BadT ; 74
238 dw offset _TEXT:IOT_BadT ; 75
239 dw offset _TEXT:IOT_BadT ; 76
240 dw offset _TEXT:IOT_BadT ; 77
241 dw offset _TEXT:IOT_BadT ; 78
242 dw offset _TEXT:IOT_BadT ; 79
243 dw offset _TEXT:IOT_BadT ; 7a
244 dw offset _TEXT:IOT_BadT ; 7b
245 dw offset _TEXT:IOT_BadT ; 7c
246 dw offset _TEXT:IOT_BadT ; 7d
247 dw offset _TEXT:IOT_BadT ; 7e
248 dw offset _TEXT:IOT_BadT ; 7f
249 dw offset _TEXT:IOT_BadT ; 80
250 dw offset _TEXT:DMAPg2 ; 81 DMA page register for Channel 2
251 dw offset _TEXT:DMAPg3 ; 82 DMA page register for Channel 3
252 dw offset _TEXT:DMAPg1 ; 83 DMA page register for Channel 1
253 dw offset _TEXT:RRP_Handler ; return to real port
254 dw offset _TEXT:RRP_Handler ; return to real port
255 dw offset _TEXT:IOT_BadT ; 86
256 dw offset _TEXT:DMAPg0 ; 87 DMA page register for Channel 0
257 dw offset _TEXT:IOT_BadT ; 88
258 dw offset _TEXT:DMAPg6 ; 89 DMA page register for Channel 6
259 dw offset _TEXT:DMAPg7 ; 8a DMA page register for Channel 7
260 dw offset _TEXT:DMAPg5 ; 8b DMA page register for Channel 5
261 dw offset _TEXT:IOT_BadT ; 8c
262 dw offset _TEXT:IOT_BadT ; 8d
263 dw offset _TEXT:IOT_BadT ; 8e
264 dw offset _TEXT:IOT_BadT ; 8f
265 dw offset _TEXT:IOT_BadT ; 90
266 dw offset _TEXT:DMAPg2 ; 91 DMA page register for Channel 2
267 dw offset _TEXT:DMAPg3 ; 92 DMA page register for Channel 3
268 dw offset _TEXT:DMAPg1 ; 93 DMA page register for Channel 1
269 dw offset _TEXT:IOT_BadT ; 94
270 dw offset _TEXT:IOT_BadT ; 95
271 dw offset _TEXT:IOT_BadT ; 96
272 dw offset _TEXT:IOT_BadT ; 97 DMA page register for Channel 0
273 dw offset _TEXT:IOT_BadT ; 98
274 dw offset _TEXT:DMAPg6 ; 99 DMA page register for Channel 6
275 dw offset _TEXT:DMAPg7 ; 9a DMA page register for Channel 7
276 dw offset _TEXT:DMAPg5 ; 9b DMA page register for Channel 5
277 dw offset _TEXT:IOT_BadT ; 9c
278 dw offset _TEXT:IOT_BadT ; 9d
279 dw offset _TEXT:IOT_BadT ; 9e
280 dw offset _TEXT:IOT_BadT ; 9f
281 dw offset _TEXT:IOT_BadT ; a0
282 dw offset _TEXT:IOT_BadT ; a1
283 dw offset _TEXT:IOT_BadT ; a2
284 dw offset _TEXT:IOT_BadT ; a3
285 dw offset _TEXT:IOT_BadT ; a4
286 dw offset _TEXT:IOT_BadT ; a5
287 dw offset _TEXT:IOT_BadT ; a6
288 dw offset _TEXT:IOT_BadT ; a7
289 dw offset _TEXT:IOT_BadT ; a8
290 dw offset _TEXT:IOT_BadT ; a9
291 dw offset _TEXT:IOT_BadT ; aa
292 dw offset _TEXT:IOT_BadT ; ab
293 dw offset _TEXT:IOT_BadT ; ac
294 dw offset _TEXT:IOT_BadT ; ad
295 dw offset _TEXT:IOT_BadT ; ae
296 dw offset _TEXT:IOT_BadT ; af
297 dw offset _TEXT:IOT_BadT ; b0
298 dw offset _TEXT:IOT_BadT ; b1
299 dw offset _TEXT:IOT_BadT ; b2
300 dw offset _TEXT:IOT_BadT ; b3
301 dw offset _TEXT:IOT_BadT ; b4
302 dw offset _TEXT:IOT_BadT ; b5
303 dw offset _TEXT:IOT_BadT ; b6
304 dw offset _TEXT:IOT_BadT ; b7
305 dw offset _TEXT:IOT_BadT ; b8
306 dw offset _TEXT:IOT_BadT ; b9
307 dw offset _TEXT:IOT_BadT ; ba
308 dw offset _TEXT:IOT_BadT ; bb
309 dw offset _TEXT:IOT_BadT ; bc
310 dw offset _TEXT:IOT_BadT ; bd
311 dw offset _TEXT:IOT_BadT ; be
312 dw offset _TEXT:IOT_BadT ; bf
313 dw offset _TEXT:IOT_BadT ; c0 DMA base register for Channel 4
314 dw offset _TEXT:IOT_BadT ; c1
315 dw offset _TEXT:IOT_BadT ; c2 DMA count register for Channel 4
316 dw offset _TEXT:IOT_BadT ; c3
317 dw offset _TEXT:DMABase5 ; c4 DMA base register for Channel 5
318 dw offset _TEXT:IOT_BadT ; c5
319 dw offset _TEXT:DMACnt5 ; c6 DMA count register for Channel 5
320 dw offset _TEXT:IOT_BadT ; c7
321 dw offset _TEXT:DMABase6 ; c8 DMA base register for Channel 6
322 dw offset _TEXT:IOT_BadT ; c9
323 dw offset _TEXT:DMACnt6 ; ca DMA count register for Channel 6
324 dw offset _TEXT:IOT_BadT ; cb
325 dw offset _TEXT:DMABase7 ; cc DMA base register for Channel 7
326 dw offset _TEXT:IOT_BadT ; cd
327 dw offset _TEXT:DMACnt7 ; ce DMA count register for Channel 7
328 dw offset _TEXT:IOT_BadT ; cf
329 dw offset _TEXT:IOT_BadT ; d0
330 dw offset _TEXT:IOT_BadT ; d1
331 dw offset _TEXT:IOT_BadT ; d2
332 dw offset _TEXT:IOT_BadT ; d3
333 dw offset _TEXT:IOT_BadT ; d4
334 dw offset _TEXT:IOT_BadT ; d5
335 dw offset _TEXT:DMAMode2 ; d6 DMA Mode Register for channels 4-7
336 dw offset _TEXT:IOT_BadT ; d7
337 dw offset _TEXT:DMAClrFF2 ; d8 clear flip-flop cmd for channels 5-7
338 dw offset _TEXT:IOT_BadT ; d9
339 dw offset _TEXT:IOT_BadT ; da
340 dw offset _TEXT:IOT_BadT ; db
341 dw offset _TEXT:IOT_BadT ; dc
342 dw offset _TEXT:IOT_BadT ; dd
343 dw offset _TEXT:IOT_BadT ; de
344 dw offset _TEXT:IOT_BadT ; df
345 dw offset _TEXT:IOT_BadT ; e0
346 dw offset _TEXT:IOT_BadT ; e1
347 dw offset _TEXT:IOT_BadT ; e2
348 dw offset _TEXT:IOT_BadT ; e3
349 dw offset _TEXT:IOT_BadT ; e4
350 dw offset _TEXT:IOT_BadT ; e5
351 dw offset _TEXT:IOT_BadT ; e6
352 dw offset _TEXT:IOT_BadT ; e7
353 dw offset _TEXT:IOT_BadT ; e8
354 dw offset _TEXT:IOT_BadT ; e9
355 dw offset _TEXT:IOT_BadT ; ea
356 dw offset _TEXT:IOT_BadT ; eb
357 dw offset _TEXT:IOT_BadT ; ec
358 dw offset _TEXT:IOT_BadT ; ed
359 dw offset _TEXT:IOT_BadT ; ee
360 dw offset _TEXT:IOT_BadT ; ef
361 dw offset _TEXT:IOT_BadT ; f0
362 dw offset _TEXT:IOT_BadT ; f1
363 dw offset _TEXT:IOT_BadT ; f2
364 dw offset _TEXT:IOT_BadT ; f3
365 dw offset _TEXT:IOT_BadT ; f4
366 dw offset _TEXT:IOT_BadT ; f5
367 dw offset _TEXT:IOT_BadT ; f6
368 dw offset _TEXT:IOT_BadT ; f7
369 dw offset _TEXT:IOT_BadT ; f8
370 dw offset _TEXT:IOT_BadT ; f9
371 dw offset _TEXT:IOT_BadT ; fa
372 dw offset _TEXT:IOT_BadT ; fb
373 dw offset _TEXT:IOT_BadT ; fc
374 dw offset _TEXT:IOT_BadT ; fd
375 dw offset _TEXT:IOT_BadT ; fe
376 dw offset _TEXT:IOT_BadT ; ff
377
378;******************************************************************************
379; IOT_BadT - GP fault on Unknown I/O address
380;
381; DESCRIPTION: This routine is entered by being in the IOTrap_Tab above
382; and also for I/O ports which are not LIM(DMA) ports and are not
383; emulated by IOT_OEM routine below and the first 10 bits of the
384; address is greater than 100h. Note that only the first 10 bits
385; of the port (times 2) is passed in BX. If the entire port
386; address is desired, it is available on the stack as the value
387; which is popped into DX.
388;
389; ENTRY: Protected Mode Ring 0
390; return address, DX, DS, return address on stack
391; AL = byte to output to port.
392; BX == 2 * port address(either 0-1FE or 200-7FE)
393; DX == 0 => Emulate input
394; <> 0 => Emulate output
395; DS = DGROUP
396; SS:BP = points to stack frame on entry to GP fault handler
397;
398;
399; EXIT: Protected Mode Ring 0
400; First return address, pop'd from stack.
401; DX and DS restored from stack.
402; BX = DX on entry
403; STC => I/O NOT emulated.
404;
405; WARNING:***********
406; This routine is closely allied with IOTrap which is in IOTrap.
407; It is assumed that IOTrap puts the stack in a certain state!
408; ***********
409
410; USED: Flags
411; STACK:
412;------------------------------------------------------------------------------
413;
414IOT_BadT proc near
415 pop bx ; dump return address
416 mov bx,dx ; restore BX
417 pop dx ; restore DX(port address)
418 pop ds ; restore DS
419 stc ; port not emulated !
420 ret ; and return
421IOT_BadT endp
422
423;******************************************************************************
424; IOT_OEM - Handles OEM specific I/O traps
425;
426; ENTRY: Protected Mode Ring 0
427; AL = byte to output to port.
428; DX = port address for I/O.
429; SS:BP = points to stack frame on entry to GP fault handler
430; BX = 0 => Emulate Input.
431; <>0 => Emulate Output.
432; DS = DGROUP
433; stack: near return to IOTrap, DX, DS, near return from IOTrap
434;
435; EXIT: Protected Mode Ring 0
436; Either emulate I/O and pop return, DX, DS from stack and RET
437; with CF = 1(CF = 0 if I/O is to be ignored!?!?).
438; Or just return(no emulation done)
439;
440;
441; WARNING:***********
442; This routine is closely allied with IOTrap.
443; It assumes that the stack is in a certain state!
444; ***********
445;
446;
447; USED: Flags
448; STACK:
449;------------------------------------------------------------------------------
450IOT_OEM proc near
451; cmp dx,????
452; jnz NoEmulation
453; or bx,bx
454; jnz NoEmulation
455; mov al,???? ;emulate input
456; pop dx ;remove return
457; pop dx ;restore DX
458; pop ds ;restore DS
459; ret ;return from IOTRAP
460;
461;NoEmulation:
462 ret ; no emulation
463IOT_OEM endp
464
465
466_TEXT ends
467
468 end
469 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/UTIL.ASM b/v4.0/src/MEMM/MEMM/UTIL.ASM
new file mode 100644
index 0000000..221efdf
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/UTIL.ASM
@@ -0,0 +1,335 @@
1
2
3page 58,132
4;******************************************************************************
5 title UTIL - general MEMM utilities
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: UTIL - utilities
13;
14; Version: 0.04
15;
16; Date: June 11, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/11/86 Original from i286.asm
27; 06/18/86 0.01 in GoVirtual - added code to init VDM state variables
28; 06/25/86 0.02 in GoVirtual - more DiagByte state variable.
29; 06/28/86 0.02 Name change from MEMM386 to MEMM
30; 06/29/86 0.02 Changed check code for ROM write protect state
31; 07/01/86 0.03 Added call to InitDMA in GoVirtual
32; 07/05/86 0.04 Moved code to InitLOCK
33; 07/05/86 0.04 Added FarGoVirtual and moved IsReal to PRINT.ASM
34; 07/06/86 0.04 Changed assume to DGROUP and moved stack out of DGROUP
35;
36;******************************************************************************
37;
38; Functional Description:
39;
40;
41;******************************************************************************
42.lfcond ; list false conditionals
43.386p
44
45 public GoVirtual
46 public FarGoVirtual
47 public SelToSeg
48
49;******************************************************************************
50; D E F I N E S
51;******************************************************************************
52 include VDMseg.inc
53 include VDMsel.inc
54 include desc.inc
55 include instr386.inc
56 include oemdep.inc
57
58FALSE equ 0
59TRUE equ not FALSE
60
61;******************************************************************************
62; E X T E R N A L R E F E R E N C E S
63;******************************************************************************
64_DATA SEGMENT
65
66extrn TEXT_Seg:word ; segment for _TEXT
67extrn GDT_Seg:word ; segment for GDT
68extrn TSS_Seg:word ; segment address of TSS
69extrn Page_Dir:word ; 32-bit address of Page Directory Table
70
71extrn Active_Status:byte
72
73_DATA ENDS
74
75_TEXT SEGMENT
76
77extrn InitDMA:near ; (elimtrap.asm)
78extrn EnableA20:near ; (modesw.asm)
79extrn A20_Trap_Init:near ; (a20trap.asm)
80extrn RR_Trap_Init:near ; (RRTrap.asm)
81extrn OEM_Trap_Init:near ; (OEMTrap.asm)
82
83_TEXT ENDS
84
85STACK segment
86 extrn kstack_top:byte
87STACK ends
88
89ifndef NOHIMEM
90
91R_CODE segment
92extrn InitLock:far
93R_CODE ends
94
95endif
96
97 page
98;******************************************************************************
99; S E G M E N T D E F I N I T I O N S
100;******************************************************************************
101
102;******************************************************************************
103; _TEXT segment
104;******************************************************************************
105
106_TEXT SEGMENT
107 assume cs:_TEXT, ds:DGROUP, es:DGROUP
108
109;******************************************************************************
110; FarGoVirtual - far link for GoVirtual
111;
112; NOTE: this is a FAR routine.
113;
114; ENTRY: Real Mode
115; DS = DGROUP
116;
117; EXIT: Virtual Mode
118; VDM state variables initialized
119;
120; USED: none
121;
122;******************************************************************************
123FarGoVirtual proc far
124 call GoVirtual
125 ret
126FarGoVirtual endp
127
128;******************************************************************************
129; GoVirtual - go to virtual mode
130;
131; ENTRY: Real Mode
132; DS = DGROUP
133;
134; EXIT: Virtual Mode
135; VDM state variables initialized
136;
137; USED: none
138;
139;******************************************************************************
140GoVirtual proc near
141;
142 PUSH_EAX
143 push bx
144 push bp
145 push ds
146 push es
147 PUSH_FS
148 PUSH_GS
149;
150 cli ; interrupts OFF
151;
152; init VDM state variables
153;
154 push es
155 mov ax,[TSS_Seg]
156 mov es,ax ; ES -> TSS
157 call A20_Trap_Init ; init a20 line watch
158 call RR_Trap_Init ; init return to real watch
159 call OEM_Trap_Init ; init any other I/O port watches
160 pop es
161
162 mov [Active_Status],1
163
164 call InitDMA ; init DMA watcher
165
166ifndef NOHIMEM
167 call FAR PTR InitLOCK ; init status of TABLE lock
168endif
169
170;
171; mask off master 8259 to prevent all interrupts during setup
172;
173 call MaskIntAll ; Mask all interrupts
174;
175; Set the CPU into 386 protected mode.
176;
177; The following CPU registers are changed to have values
178; appropriate to protected mode operation:
179;
180; CS, DS, ES, SS, TR, LDT, Flags, MSW, GDT, IDT
181 call EnableA20 ; enable A20 address line
182
183;
184; load CR3 register for paging
185;
186 OP32
187 mov ax,[Page_Dir] ; EAX = 32-bit address of Page Dir
188
189 MOV_CR3_EAX
190
191;
192; load gdt and ldt base registers
193;
194 mov ax,[GDT_Seg]
195 mov ds, ax ; DS:0 = ptr to gdt
196 lgdt qword ptr ds:[GDTD_GSEL]
197 lidt qword ptr ds:[IDTD_GSEL]
198;
199; go protected and enable paging - turn on bits in CR0
200;
201 MOV_EAX_CR0
202
203 OP32
204 or ax,MSW_PROTECT ; or EAX,imm32 - enable PE bit - PROT MODE
205 dw 8000h ; - enable PG bit - PAGING
206
207 MOV_CR0_EAX
208
209; far jump to flush prefetch, and reload CS
210
211 db 0eah ; far jmp opcode
212 dw offset _TEXT:pm1 ; offset
213 dw VDMC_GSEL ; selector
214pm1:
215;
216; We are now protected, set the Task Register and LDT Register
217;
218 mov ax,TSS_GSEL
219 ltr ax
220
221 xor ax, ax ; LDT is null, not needed
222 lldt ax
223;
224; save current stack pointer for after return to VM
225;
226 mov bx,ss ; BX = saved SS
227 mov bp,sp ; BP = saved SP
228;
229; set the stack selector to RING 0 stack
230;
231 mov ax, VDMS_GSEL
232 mov ss, ax
233 mov sp, offset STACK:kstack_top
234;
235; now reload DS and ES to be data selectors for protected mode
236;
237 mov ax, VDMD_GSEL
238 mov ds, ax
239 assume ds:DGROUP
240 mov es, ax
241 assume es:DGROUP
242
243;
244; reset NT bit so IRET won't attempt a task switch
245;
246 pushf
247 pop ax
248 and ax,0FFFh
249 push ax
250 popf
251;
252; build stack frame for IRET into virtual mode
253;
254 push 0
255 push 0 ; GS
256 push 0
257 push 0 ; FS
258 push 0
259 push seg DGROUP ; DS (DGROUP for variable access)
260 push 0
261 push 0 ; ES
262
263 push 0
264 push bx ;* virtual mode SS
265
266 push 0
267 push bp ;* virtual mode ESP
268
269 push 2 ; EFlags high, VM bit set
270 push 3000h ;* EFlags low, NT = 0, IOPL=3, CLI
271
272 push 0
273 mov ax, [TEXT_Seg]
274 push ax ; CS
275 push 0
276 mov ax, offset _TEXT:VM_return
277 push ax ; IP
278
279 OP32 ; 32 bit operand size override
280 iret
281
282;
283; Enter Virtual Mode here
284;
285VM_return:
286;
287; re-enable interrupts
288;
289 call RestIntMask ; Restore interrupt mask
290 POP_GS
291 POP_FS
292 pop es
293 pop ds
294 pop bp
295 pop bx
296 POP_EAX
297 ret
298GoVirtual endp
299
300
301;** SelToSeg - convert selector to a segment number
302;
303; The protected mode selector value is converted to a
304; real mode segment number.
305;
306; ENTRY BX = selector
307; EXIT AX = segment number
308; USES BX, Flags, other regs preserved
309;
310; WARNING This code only works on a 286. It can be
311; called only in protected mode.
312
313SelToSeg proc near
314 push ds
315 mov ax,LDTD_GSEL
316 test bx,TAB_LDT ; is the selector in the LDT?
317 jnz sts_addr ; yes,
318 mov ax,GDTD_GSEL ; selector is in the GDT
319sts_addr:
320 mov ds,ax
321 and bl,0F8h
322
323 mov ax,word ptr ds:[bx + 2] ; low 16 bits of base address
324 mov bh,ds:[bx + 4] ; high 8 bits of base address
325 shr ax,4
326 shl bh,4
327 mov bl,0
328 add ax,bx ; AX = segment number for selector
329 pop ds
330 ret
331SelToSeg endp
332
333_TEXT ends
334
335 end
diff --git a/v4.0/src/MEMM/MEMM/VDMINIT.ASM b/v4.0/src/MEMM/MEMM/VDMINIT.ASM
new file mode 100644
index 0000000..a6e7072
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/VDMINIT.ASM
@@ -0,0 +1,527 @@
1
2
3page 58,132
4;******************************************************************************
5 title VDM_Init - VDM initialization module
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: VDM_Init - VDM initialization routine
13;
14; Version: 0.05
15;
16; Date: June 3,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 06/03/86 Original from VDM MAIN.ASM module
27; 06/16/86 0.01 Added code to dword align LL buffer
28; 06/21/86 0.02 moved cld in init_pages
29; 06/28/86 0.02 Name change from MEMM386 to MEMM
30; 07/06/86 0.04 changed assume to DGROUP and moved stack out of
31; DGROUP
32; 07/10/86 0.05 Init of RCODEA_GSEL
33; 07/10/86 0.05 Added PageT_Seg
34; 07/20/88 Removed debugger codes (pc)
35;
36;******************************************************************************
37;
38; Functional Description:
39;
40; This module is the general initialization module for the Virtual DOS
41; Monitor part of MEMM. This module initializes the protected mode
42; GDT, IDT, TSS (and I/O BitMap), and the Page Tables. This module also
43; initializes all variables used by the VDM code. This module returns
44; to the calling routine in Virtual Mode.
45;
46;******************************************************************************
47.lfcond ; list false conditionals
48.386p
49;******************************************************************************
50; P U B L I C S
51;******************************************************************************
52
53 public VDM_Init
54 public PageD_Seg
55 public PageT_Seg
56 public Page_Dir
57
58;******************************************************************************
59; D E F I N E S
60;******************************************************************************
61 include VDMseg.inc
62 include VDMsel.inc
63 include desc.inc
64 include instr386.inc
65 include page.inc
66
67FALSE equ 0
68TRUE equ not FALSE
69CR equ 0dh
70LF equ 0ah
71
72;******************************************************************************
73; E X T E R N A L R E F E R E N C E S
74;******************************************************************************
75_DATA SEGMENT
76extrn P_TABLE_CNT:abs
77extrn ELOff:word ; offset of LL buffer
78_DATA ENDS
79
80_TEXT SEGMENT
81
82extrn InitBitMap:far ; (vminit.asm)
83
84_TEXT ENDS
85
86GDT SEGMENT
87extrn GDTLEN:abs
88GDT ENDS
89
90IDT SEGMENT
91extrn IDTLEN:abs
92IDT ENDS
93
94TSS SEGMENT
95extrn TSSLEN:abs
96TSS ENDS
97
98PAGESEG SEGMENT
99extrn Page_Area:byte
100PAGESEG ENDS
101
102
103LAST SEGMENT
104extrn SetSegDesc:near
105extrn SegTo24:near
106extrn SetPageEntry:near
107extrn get_init_a20_state:near
108extrn OEM_Init_Diag_Page:near
109LAST ENDS
110
111;******************************************************************************
112; S E G M E N T D E F I N I T I O N S
113;******************************************************************************
114
115;
116; Ring 0 stack for VDM exception/int handling
117;
118STACK SEGMENT
119stkstrt label byte
120
121 db STACK0_SIZE dup(0)
122
123 public kstack_top
124kstack_top label byte
125
126 db 400h dup (0)
127 public exe_stack
128exe_stack label byte
129
130STACK ENDS
131
132_DATA SEGMENT
133
134PageD_Seg dw 0 ; segment for Page Directory
135PageT_Seg dw 0 ; segment for Page Tables
136Page_Dir dd 0 ; 32 bit address of Page Directory
137
138_DATA ENDS
139
140;
141; code
142;
143LAST SEGMENT
144
145 assume cs:LAST, ds:DGROUP, es:DGROUP
146
147;******************************************************************************
148; VDM_Init - VDM initialization routine
149;
150;
151; ENTRY: Real Mode
152; DS = DGROUP
153; GDT = GDT segment
154; TSS = TSS segment
155;
156; EXIT: Real Mode
157; VDM Tables initialized
158; TSS initialized
159;
160; USED: none
161;
162;******************************************************************************
163VDM_Init proc near
164;
165 pushf
166 pusha
167 PUSH_EAX
168 push ds
169 push es
170;
171 push ds
172 pop es ; ES = data
173;
174 cli
175;
176 call InitGdt ;;; initialize GDT descriptors
177;
178; initialize Page Table, I/O Bit Map and LIM h/w emulator
179;
180 call InitPages ;;; initialize paging tables
181 call InitBitMap ;;; initialize I/O Bit Map
182;
183; initialize TSS,GDTR,IDTR
184;
185; set ring 0 SS:SP in the TSS so we can take outer ring traps
186
187 mov ax, seg TSS
188 mov es,ax ; ES -> TSS
189 xor di,di ; ES:DI -> TSS
190
191 mov ES:[di.TSS386_SS0], VDMS_GSEL
192 mov word ptr ES:[di.TSS386_ESP0lo], offset STACK:kstack_top
193 mov word ptr ES:[di.TSS386_ESP0hi], 0
194
195; now set CR3 in the TSS
196
197 db 66h
198 mov ax,word ptr [Page_Dir] ; EAX = page dir 32 bit addr
199 db 66h
200 mov word ptr ES:[di.TSS386_CR3],ax ; mov EAX into CR3 spot in TSS
201
202; clear the TSS busy flag
203
204 mov ax,seg GDT
205 mov es, ax ; DS:0 = ptr to gdt
206
207 and byte ptr ES:[TSS_GSEL + 5], 11111101B
208
209;
210; dword align the LL buffer (move foward)
211;
212 mov ax,[ELOff]
213 and ax,0003h ; MOD 4
214 mov bx,4
215 sub bx,ax ; BX = amount to add to dword align
216 add [ELOff],bx ; dword align it...
217
218;
219; and return
220;
221 pop es
222 pop ds
223 POP_EAX
224 popa
225 popf
226 ret
227VDM_Init endp
228
229;** InitGdt - initialise GDT
230;
231; Some of the GDT is statically initialised. This routine
232; initialises the rest, except the LDT pointer which
233; changes dynamically, and the VDM stack which changes too.
234;
235; ENTRY GDT:0 = GDT to use.
236; EXIT None
237; USES All except BP
238;
239; WARNING This code only works on a 286.
240; Designed to be called from real mode ONLY.
241
242 public InitGdt
243InitGdt proc near
244 push es
245
246 mov ax,GDT
247 mov es,ax ; ES:0 -> gdt
248
249 mov ax,GDT
250 call SegTo24
251 mov cx,GDTLEN
252 mov ah,D_DATA0
253 mov bx,GDTD_GSEL
254 call SetSegDesc ; Set up GDT alias descriptor
255
256 mov ax,IDT
257 call SegTo24
258 mov cx,IDTLEN
259 mov ah,D_DATA0
260 mov bx,IDTD_GSEL
261 call SetSegDesc ; Set up IDT alias descriptor
262
263 mov ax,TSS
264 call SegTo24
265 mov cx,TSSLEN
266 mov ah,D_386TSS0
267 mov bx,TSS_GSEL
268 call SetSegDesc ; Set up TSS descriptor
269
270 mov ah,D_DATA0
271 mov bx,TSSD_GSEL
272 call SetSegDesc ; Set up TSS alias descriptor
273
274 mov ax,seg _TEXT
275 call SegTo24
276 mov cx,0 ; 0 = 64K size
277 mov ah,D_CODE0
278 mov bx,VDMC_GSEL
279 call SetSegDesc ; Set up VDM Code descriptor
280
281 mov ax,_TEXT
282 call SegTo24
283 mov cx,0 ; 0 = 64K size
284 mov ah,D_DATA0
285 mov bx,VDMCA_GSEL
286 call SetSegDesc ; Set up VDM Code segment alias descr
287
288 mov ax,R_CODE
289 call SegTo24
290 mov cx,0 ; 0 = 64K size
291 mov ah,D_DATA0
292 mov bx,RCODEA_GSEL
293 call SetSegDesc ; Set up R_CODE segment alias descriptor
294
295 mov ax,seg DGROUP
296 call SegTo24
297 mov cx,0 ; 0 = 64K size
298 mov ah,D_DATA0
299 mov bx,VDMD_GSEL
300 call SetSegDesc ; Set up VDM Data descriptor
301
302 mov ax, seg STACK ; set up Ring 0 stack
303 call SegTo24
304 mov cx, offset STACK:kstack_top
305 mov ah, D_DATA0
306 mov bx, VDMS_GSEL
307 call SetSegDesc
308
309 pop es
310 ret
311InitGdt endp
312
313;** InitPages - initialize Page Directory and Table
314;
315; This routine initializes a page directory and a page table.
316; Both of these are aligned on a physical page boundary by
317; starting them at the nearest bndry. Thus, the page table area
318; must be large enough to allow this alignment.
319;
320; The page dir and table set up by this routine maps the linear
321; addresses for Virtual mode programs into physical addresses using
322; the following scheme.
323; Linear Addr Physical Addr
324; 00000000h - 000FFFFFh 00000000h - 000FFFFFh
325; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound)
326; 00110000h - 0100FFFFh 00100000h - 00FFFFFFh (top 15Meg of phys)
327;
328; ISP,PC: The above was totally unnecessary. When the A20 is turned
329; off the 64k at 1M is anyway unaccessible. A better mapping
330; has been implemented here:
331;
332; Linear Addr Physical Addr
333; 00000000h - 000FFFFFh 00000000h - 000FFFFFh
334; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound)
335; 00110000h - 01000000h 00110000h - 01000000h (top 15Meg of phys)
336; 01000000h - 0100ffffh xxxx0000h - xxxxffffh (Done in OEMPROC)
337;
338;
339; ENTRY PAGESEG:Page_Area = pointer to page table area.
340; DS = DGROUP
341; EXIT DS:PageD_Seg = seg ptr for page directory.
342; DS:PageT_Seg = seg ptr for page tables
343; DS:Page_Dir = 32 bit addr for page directory.
344; USES none
345;
346; WARNING This code only works on a 286/386.
347; Designed to be called from real mode ONLY.
348
349 public InitPages
350InitPages proc near
351 push ax
352 push bx
353 push cx
354 push dx
355 push di
356 push es
357 cld ; strings foward
358;
359; get physical pointer to nearest page
360;
361 mov ax,offset PAGESEG:Page_Area
362 add ax,15
363 shr ax,4 ; AX = seg offset for page area
364 mov bx,PAGESEG ; PAGESEG is on a 256 boundary
365 add ax,bx ; AX = seg offset for page area
366 add ax,0FFh ; 0FFh = # of paras in page - 1
367 xor al,al ; AX = seg addr for page align
368 mov [PageD_Seg],ax ; save it
369;
370 xor di,di
371 mov es,ax ; ES:DI = ptr to Page Directory
372;
373 mov dl,ah
374 shr dl,4 ; DL = bits 16 - 19
375 xor dh,dh ; DX = bits 16 - 31
376 shl ah,4 ; AX = bits 0 - 15
377 mov word ptr [Page_Dir],AX ; DX,AX = 32 bit addr of Page Directory
378 mov word ptr [Page_Dir+2],DX ; save it
379;
380; get addr of Page Table for Page Directory entry
381;
382 add ax,1000h ; add page
383 adc dx,0h ; carry it => DX,AX = addr of page table
384;
385; set entries in page directory
386;
387; ES:[DI] pts to first entry in page directory
388; DX,AX = addr of first page table
389;
390 mov bh,0
391 mov bl,P_AVAIL ; make table available to all
392 mov cx,P_TABLE_CNT ; set entries in page table directory
393 ; for existing page tables.
394init_dir:
395 call SetPageEntry ; set entry for first page table
396;
397; ES:[DI] pts to next entry in page directory
398 add ax,1000h
399 adc dx,0 ; DX,AX = addr of next page table
400 loop init_dir ; set next entry in dir
401;
402; set rest of entries in page directory to not present
403 mov bh,0
404 mov bl,NOT P_PRES ; mark page table as not present
405 mov cx,400h
406 sub cx,P_TABLE_CNT ; set rest of entries in directory
407set_dir:
408 call SetPageEntry
409 loop set_dir
410;
411; set entries in page tables
412;
413; first 1 Meg
414; Linear Addr Physical Addr
415; 00000000h - 000FFFFFh 00000000h - 000FFFFFh
416;
417 mov ax,[PageD_Seg] ; get segment for page directory
418 add ax,0100h ; add 1 page to get to first page table
419 mov [PageT_Seg],ax ; save it
420
421 mov es,ax
422 xor di,di ; ES:[DI] pts to first page table
423
424 xor dx,dx
425 xor ax,ax ; start with physical addr = 00000000h
426 mov bh,0
427 mov bl,P_AVAIL ; make pages available to all
428 mov cx,100h ; set 1 Meg worth of entries in table
429set1_tentry:
430 call SetPageEntry
431 ; ES:[DI] pts to next page table entry
432 add ax,1000h ; next physical page
433 adc dx,0h ; address in DX,AX
434 loop set1_tentry ;Q: done with this page table
435 ; N: the loop again
436 ; Y: set next entries in next tables
437; 64k wraparound at 1.0 Meg
438; Linear Addr Physical Addr
439; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound)
440;
441 call get_init_a20_state ; the physical a20 state has already
442 ; been established
443 jnz skip_wrap
444 xor dx,dx
445 xor ax,ax ; start with physical addr = 00000000h
446skip_wrap:
447 mov bh,0
448 mov bl,P_AVAIL ; make pages available to all
449 mov cx,10h ; set 64k worth of entries
450set2_tentry:
451 call SetPageEntry
452 ; ES:[DI] pts to next page table entry
453 add ax,1000h ; next physical page
454 adc dx,0h ; address in DX,AX
455 loop set2_tentry ;Q: done with the wraparound entries
456 ; N: loop again
457 ; Y: all done
458;
459; last (15M - 64K) of linear addresses ( for Move Block/Loadall )
460; Linear Addr Physical Addr
461; 00110000h - 01000000h 00110000h - 01000000h
462;
463 mov dx,0011h
464 xor ax,ax ; start with 00110000h physical
465 mov bh,0
466 mov bl,P_AVAIL ; make pages available to all
467 mov cx,(4*400h)-100h-10h ; (15M-64K) worth of Page Table Entries
468set3_tentry:
469 call SetPageEntry
470 ; ES:[DI] pts to next page table entry
471 add ax,1000h ; next physical page
472 adc dx,0h ; address in DX,AX
473 loop set3_tentry ;Q: done with last entries
474 ; N: loop again
475 ; Y: all done
476
477;
478; fill out entries in last table as not present
479;
480 xor ax,ax
481 xor dx,dx ; addr = 0
482 mov bh,0
483 mov bl,0 ; page not present
484;
485; we can actually forget about this last page table because we
486; are not going to use them
487;
488 mov cx,400h ; last table
489setL_tentry:
490 call SetPageEntry ; set this entry
491 loop setL_tentry
492;
493; our honorable OEM Compaq has to be supported, so we have this hook into
494; OEMPROC to modify the last page table to point at the diagnostics segment
495;
496 call OEM_Init_Diag_Page
497;
498; all done with page dir and table setup
499; set up page directory and page table selectors
500;
501 mov ax,seg GDT
502 mov es,ax ; ES pts to GDT
503
504 mov ax,[PageT_Seg] ; seg for page tables
505 call SegTo24
506 mov cx,0 ; enough room for tables
507 mov ah,D_DATA0
508 mov bx,PAGET_GSEL
509 call SetSegDesc ; set up page tables entry
510
511;
512; EXIT
513;
514 pop es
515 pop di
516 pop dx
517 pop cx
518 pop bx
519 pop ax
520 ret
521InitPages endp
522
523LAST ends
524
525 END
526
527
diff --git a/v4.0/src/MEMM/MEMM/VDMSEG.INC b/v4.0/src/MEMM/MEMM/VDMSEG.INC
new file mode 100644
index 0000000..5a73bb3
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/VDMSEG.INC
@@ -0,0 +1,168 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: VDMSEG.INC - Segment Ordering and attributes for VDM
10;
11; Version: 0.04
12;
13; Date: May 12, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; Original
24; 05/12/86 A Cleanup and segment reorganization
25; 06/03/86 C changed order and added STACK and STACK0,STACK0_SIZE
26; 06/06/86 C changed CODE to _TEXT and DATA to _DATA
27; 06/28/86 0.02 Name change from MEMM386 to MEMM
28; 07/05/86 0.04 Re-organized to allow code seg move
29; 06/03/88 add use16 to all segments
30;
31;******************************************************************************
32ifndef INC_LIST
33.xlist
34endif
35
36ifndef NOHIMEM
37;
38; SEGMENT definitions and order
39;
40
41;* CODE area containing EMM/VDISK headers and writeable Real mode code
42R_CODE SEGMENT PARA USE16 PUBLIC 'R_CODE'
43R_CODE ENDS
44
45;* Contains initialized variables and variables used at startup.
46_DATA SEGMENT WORD USE16 PUBLIC 'DATA'
47_DATA ENDS
48
49;* read only constants for C
50CONST SEGMENT WORD USE16 PUBLIC 'CONST'
51CONST ENDS
52
53;* uninitialized static data for C
54_BSS SEGMENT WORD USE16 PUBLIC 'BSS'
55_BSS ENDS
56
57;* Ring 0 stack in VDM
58STACK SEGMENT PARA USE16 STACK 'STACK'
59STACK ENDS
60
61;
62; data group
63;
64DGROUP GROUP _DATA,CONST,_BSS
65
66;* The code comprising the system. Must be READ-ONLY in real mode.
67_TEXT SEGMENT BYTE USE16 PUBLIC 'CODE'
68_TEXT ENDS
69
70;* Global Descriptor Table
71GDT SEGMENT PARA USE16 COMMON
72GDT ENDS
73
74;* Local Descriptor Table
75LDT SEGMENT PARA USE16 COMMON
76LDT ENDS
77
78;* Interrupt Descriptor Table
79IDT SEGMENT PARA USE16 COMMON
80IDT ENDS
81
82;* Task State Segment
83TSS SEGMENT PARA USE16 COMMON
84TSS ENDS
85
86;* Contains initialized variables and variables used at startup.
87PAGESEG SEGMENT PARA USE16 PUBLIC 'PAGES'
88PAGESEG ENDS
89
90;* Initialization code and variables. Used for data later.
91; Must be last segment.
92LAST SEGMENT PARA USE16 PUBLIC 'LAST'
93LAST ENDS
94
95
96
97else
98;
99; SEGMENT definitions and order
100;
101
102;* CODE area containing EMM/VDISK headers and writeable Real mode code
103R_CODE SEGMENT PARA USE16 PUBLIC 'R_CODE'
104R_CODE ENDS
105
106;* Global Descriptor Table
107GDT SEGMENT PARA USE16 COMMON
108GDT ENDS
109
110;* Local Descriptor Table
111LDT SEGMENT PARA USE16 COMMON
112LDT ENDS
113
114;* Interrupt Descriptor Table
115IDT SEGMENT PARA USE16 COMMON
116IDT ENDS
117
118;* Task State Segment
119TSS SEGMENT PARA USE16 COMMON
120TSS ENDS
121
122;* Contains initialized variables and variables used at startup.
123_DATA SEGMENT WORD USE16 PUBLIC 'DATA'
124_DATA ENDS
125
126;* read only constants for C
127CONST SEGMENT WORD USE16 PUBLIC 'CONST'
128CONST ENDS
129
130;* uninitialized static data for C
131_BSS SEGMENT WORD USE16 PUBLIC 'BSS'
132_BSS ENDS
133
134;* Ring 0 stack in VDM
135STACK SEGMENT PARA USE16 STACK 'STACK'
136STACK ENDS
137
138;
139; data group
140;
141DGROUP GROUP _DATA,CONST,_BSS
142
143;* The code comprising the system. Must be READ-ONLY in real mode.
144_TEXT SEGMENT BYTE USE16 PUBLIC 'CODE'
145_TEXT ENDS
146
147;* Contains dynamically sized emm data structures.
148VDATA SEGMENT WORD USE16 PUBLIC 'VDATA'
149VDATA ENDS
150
151;* Contains initialized variables and variables used at startup.
152PAGESEG SEGMENT PARA USE16 PUBLIC 'PAGES'
153PAGESEG ENDS
154
155;* Initialization code and variables. Used for data later.
156; Must be last segment.
157LAST SEGMENT PARA USE16 PUBLIC 'LAST'
158LAST ENDS
159endif
160;
161; segment related equates
162;
163
164; ring 0 stack size
165STACK0_SIZE equ 512
166
167.list ; end of VDMSEG.INC
168
diff --git a/v4.0/src/MEMM/MEMM/VDMSEL.INC b/v4.0/src/MEMM/MEMM/VDMSEL.INC
new file mode 100644
index 0000000..f408c40
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/VDMSEL.INC
@@ -0,0 +1,101 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: VDMSEL.INC - Selector Definitions for MEMM
10;
11; Version: 0.05
12;
13; Date: May 12, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; Original
24; 05/12/86 A Cleanup and segment reorganization
25; 06/07/86 C merged with module from Rick
26; 06/28/86 0.02 Name change from MEMM386 to MEMM
27; 07/10/86 0.05 Changed CODE_GSEL to RCODEA_GSEL
28; 07/20/88 Remove debugger selectors
29;
30;******************************************************************************
31ifndef INC_LIST
32.xlist
33endif
34
35
36;
37; DESCRIPTION
38;
39; These are the fixed selector numbers for the GDT and LDT
40;
41; All are declared with RPL = 0 so they can easily be used
42; as table indices.
43;
44; Do not change anything without consulting files which include
45; this one. Add new selectors to the end and update the
46; gdt declaration and initialisation code elsewhere.
47;
48
49; Define LDT and GDT table bits
50
51TAB_LDT equ 4h
52TAB_GDT equ 0h
53
54
55; Define GDT selectors
56
57GDTD_GSEL equ 008h OR TAB_GDT ; gdt data alias
58IDTD_GSEL equ 010h OR TAB_GDT ; idt data alias
59LDT_GSEL equ 018h OR TAB_GDT ; ldt
60LDTD_GSEL equ 020h OR TAB_GDT ; ldt data alias
61TSS_GSEL equ 028h OR TAB_GDT ; tss
62TSSD_GSEL equ 030h OR TAB_GDT ; tss data alias
63RM_IDT_GSEL equ 038h OR TAB_GDT ; real mode idt (locn 0)
64ROMDATA_GSEL equ 040h OR TAB_GDT ; maps 40:0 - DON'T CHANGE!!
65VDMC_GSEL equ 048h OR TAB_GDT ; VDM Code selector
66VDMD_GSEL equ 050h OR TAB_GDT ; VDM Data Selector
67VDMS_GSEL equ 058h OR TAB_GDT ; VDM stack selector
68MONO_GSEL equ 060h OR TAB_GDT ; monochrome display memory
69COLOUR_GSEL equ 068h OR TAB_GDT ; colour display memory
70EGA1_GSEL equ 070h OR TAB_GDT ; first EGA sel
71EGA2_GSEL equ 078h OR TAB_GDT ; second EGA sel
72LOADALL_GSEL equ 080h OR TAB_GDT ; loadall buffer - DON'T CHANGE
73;DEBC_GSEL equ 088h or TAB_GDT ; debugger work descr
74;DEBD_GSEL equ 090h or TAB_GDT ; debugger work descr
75;DEBW1_GSEL equ 098h or TAB_GDT ; debugger work descr
76;DEBW2_GSEL equ 0A0h or TAB_GDT ; debugger work descr
77DEB1_GSEL equ 088h or TAB_GDT ; deb386 word descr
78DEB2_GSEL equ 090h or TAB_GDT ; deb386 word descr
79DEB3_GSEL equ 098h or TAB_GDT ; deb386 word descr
80DEB4_GSEL equ 0A0h or TAB_GDT ; deb386 word descr
81DEB5_GSEL equ 0A8h or TAB_GDT ; deb386 word descr
82DEBX_GSEL equ 0B0h or TAB_GDT ; deb386 descr for all of addressing space
83K_PUTC286 equ 0B8h OR TAB_GDT ; 286 call gate to kputc
84K_GETC286 equ 0C0h OR TAB_GDT ; 286 call gate to kgetc
85RCODEA_GSEL equ 0C8h OR TAB_GDT ; data alias for R_CODE segment
86VM1_GSEL equ 0D0h OR TAB_GDT ; scratch for vm handler
87VM2_GSEL equ 0D8h OR TAB_GDT ; scratch for vm handler
88MBSRC_GSEL equ 0E0h OR TAB_GDT ; source sel for move blk
89MBTAR_GSEL equ 0E8h OR TAB_GDT ; target sel for move blk
90PAGET_GSEL equ 0F0h OR TAB_GDT ; page table area sel
91VDMCA_GSEL equ 0F8h OR TAB_GDT ; VDM code segment alias
92EMM1_GSEL equ 100h OR TAB_GDT ; EMM scratch selector
93EMM2_GSEL equ 108h OR TAB_GDT ; EMM scratch selector
94OEM0_GSEL equ 110h OR TAB_GDT ; OEM specific selector
95OEM1_GSEL equ 118h OR TAB_GDT ; OEM specific selector
96OEM2_GSEL equ 120h OR TAB_GDT ; OEM specific selector
97OEM3_GSEL equ 128h OR TAB_GDT ; OEM specific selector
98USER1_GSEL equ 130h OR TAB_GDT ; USER data structure
99
100.list ; end of VDMSEL.INC
101 \ No newline at end of file
diff --git a/v4.0/src/MEMM/MEMM/VM386.INC b/v4.0/src/MEMM/MEMM/VM386.INC
new file mode 100644
index 0000000..19ce94e
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/VM386.INC
@@ -0,0 +1,206 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: VM386.INC
10;
11; Version: 0.03
12;
13; Date: May 12, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; Original
24; 05/12/86 A Cleanup and segment reorganization
25; 06/08/86 B Added Disable A20 equates
26; 06/14/86 C Added MOV_CDTR_FRAME, PROT_INS_FRAME, and changed
27; VTFO from 2 to 4 to reflect push of EBP from BP
28; 06/15/86 D Added GPFAULT_FRAME
29; 06/28/86 0.02 Name change from MEMM386 to MEMM
30; 07/01/86 0.03 Added structures for accessing memory
31;
32;******************************************************************************
33ifndef INC_LIST
34.xlist
35endif
36
37;
38; Structures for accessing memory
39;
40WordS struc
41 LowByte db ?
42 HighByte db ?
43WordS ends
44
45DwordS struc
46 LowWord dw ?
47 HighWord dw ?
48DwordS ends
49
50;
51; Structure for accessing stack frame pushed during trap exit from VM
52;
53
54VM_TRAP_FRAME struc
55VMTF_EIP dw ? ; EIP (low)
56 dw ? ; EIP (high)
57VMTF_CS dw ? ; CS
58 dw ? ; (padding)
59VMTF_EFLAGS dw ? ; EFLAGS (low)
60VMTF_EFLAGShi dw ? ; EFLAGS (high)
61VMTF_ESP dw ? ; ESP (low)
62 dw ? ; ESP (high)
63VMTF_SS dw ? ; SS
64 dw ? ; (padding)
65VMTF_ES dw ? ; ES
66 dw ? ; (padding)
67VMTF_DS dw ? ; DS
68 dw ? ; (padding)
69VMTF_FS dw ? ; FS
70 dw ? ; (padding)
71VMTF_GS dw ? ; GS
72 dw ? ; (padding)
73VM_TRAP_FRAME ends
74;
75 ; Used in EmMovCDTR (vminst.asm)
76MOV_CDTR_FRAME struc
77MCF_WBP dw ? ; Work BP
78MCF_WES dw ? ; Work ES
79MCF_EAX dw ? ; EAXlo
80 dw ? ; EAXhi
81MCF_ESI dw ? ; ESIlo
82 dw ? ; ESIhi
83MCF_EBX dw ? ; EBXlo
84 dw ? ; EBXhi
85MCF_EBP dw ? ; EBPlo
86 dw ? ; EBPhi
87MCF_VMERR dw ? ; VM Error Code (low)
88 dw ? ; VM Error Code (high)
89MCF_VMEIP dw ? ; VM EIP (low)
90 dw ? ; VM EIP (high)
91MCF_VMCS dw ? ; VM CS
92 dw ? ; (padding)
93MCF_VMEFLAGS dw ? ; VM EFLAGS (low)
94MCF_VMEFLAGShi dw ? ; VM EFLAGS (high)
95MCF_VMESP dw ? ; VM ESP (low)
96 dw ? ; VM ESP (high)
97MCF_VMSS dw ? ; VM SS
98 dw ? ; (padding)
99MCF_VMES dw ? ; VM ES
100 dw ? ; (padding)
101MCF_VMDS dw ? ; VM DS
102 dw ? ; (padding)
103MCF_VMFS dw ? ; VM FS
104 dw ? ; (padding)
105MCF_VMGS dw ? ; VM GS
106 dw ? ; (padding)
107MOV_CDTR_FRAME ends
108;
109 ; Used in EmProtIns (vminst.asm)
110PROT_INS_FRAME struc
111PIF_WBP dw ? ; Work BP
112PIF_WES dw ? ; Work ES
113PIF_AX dw ? ; EAXlo
114PIF_DX dw ? ; EDXlo
115PIF_ESI dw ? ; ESIlo
116 dw ? ; ESIhi
117PIF_EBX dw ? ; EBXlo
118 dw ? ; EBXhi
119PIF_EBP dw ? ; EBPlo
120 dw ? ; EBPhi
121PIF_VMERR dw ? ; VM Error Code (low)
122 dw ? ; VM Error Code (high)
123PIF_VMEIP dw ? ; VM EIP (low)
124 dw ? ; VM EIP (high)
125PIF_VMCS dw ? ; VM CS
126 dw ? ; (padding)
127PIF_VMEFLAGS dw ? ; VM EFLAGS (low)
128PIF_VMEFLAGShi dw ? ; VM EFLAGS (high)
129PIF_VMESP dw ? ; VM ESP (low)
130 dw ? ; VM ESP (high)
131PIF_VMSS dw ? ; VM SS
132 dw ? ; (padding)
133PIF_VMES dw ? ; VM ES
134 dw ? ; (padding)
135PIF_VMDS dw ? ; VM DS
136 dw ? ; (padding)
137PIF_VMFS dw ? ; VM FS
138 dw ? ; (padding)
139PIF_VMGS dw ? ; VM GS
140 dw ? ; (padding)
141PROT_INS_FRAME ends
142;
143GPFAULT_FRAME struc
144GPF_ESI dw ? ; ESIlo
145 dw ? ; ESIhi
146GPF_EBX dw ? ; EBXlo
147 dw ? ; EBXhi
148GPF_EBP dw ? ; EBPlo
149 dw ? ; EBPhi
150GPFAULT_FRAME ends
151;
152; The following constants define the offset of the Virtual Mode trap stack
153; frame (from current SP assuming BP has been pushed) for the two cases:
154; 1) exceptions that don't push error codes and 2) those that do.
155;
156VTFO equ 4 ; offset of VM trap stack frame
157VTFOE equ VTFO + 4 ; as above, but including error code
158;
159; These constants are used to sanity-check the value of SP when one of
160; the exception handlers has been entered:
161;
162STACK segment
163 extrn kstack_top:byte
164STACK ends
165
166 ; Trap/no error
167VMT_STACK equ offset STACK:kstack_top - size VM_TRAP_FRAME - VTFO
168 ; Trap w/error
169VMTERR_STACK equ offset STACK:kstack_top - size VM_TRAP_FRAME - VTFOE
170
171;******************************************************************************
172; E R R O R C O D E S
173;******************************************************************************
174;
175PrivErr equ 0000h ; Privileged Operation Error class
176ErrLGDT equ 0000h ; Client tried to execute a LGDT
177ErrLIDT equ 0001h ; Client tried to execute a LIDT
178ErrLMSW equ 0002h ; Client tried to execute a LMSW
179Err2LL equ 0003h ; Client tried to execute a 286 Loadall
180Err3LL equ 0004h ; Client tried to execute a 386 Loadall
181ErrMovCR equ 0005h ; Client tried to execute a CRn mov
182ErrMovDR equ 0006h ; Client tried to execute a DRn mov
183ErrMovTR equ 0007h ; Client tried to execute a TRn mov
184
185ExcpErr equ 0001h ; Exception Error class
186ErrDIV equ 0000h ; Divide Error
187ErrINT1 equ 0001h ; Debug Exception
188ErrNMI equ 0002h ; NMI
189ErrINT3 equ 0003h ; Int 3
190ErrINTO equ 0004h ; Int O error
191ErrBounds equ 0005h ; Array Bounds Check
192ErrOpCode equ 0006h ; Invalid Opcode
193ErrCoPNA equ 0007h ; Coprocessor Device not available
194ErrDouble equ 0008h ; Double Fault
195ErrCoPseg equ 0009h ; Coprocessor Segment Overrun
196ErrTSS equ 000Ah ; Invalid TSS
197ErrSegNP equ 000Bh ; Segment not Present
198ErrStack equ 000Ch ; Stack Fault
199ErrGP equ 000Dh ; General Protection Fault
200ErrPage equ 000Eh ; Page Fault
201ErrCoPerr equ 0010h ; Coprocessor Error
202ErrWrite equ 0020h ; Attempt to write to protected area
203ErrDMA equ 0021h ; Attempt to DMA into page frame (not for user)
204ErrINTProt equ 0022h ; General Protected interrupt error
205
206.list ; end of VM386.INC
diff --git a/v4.0/src/MEMM/MEMM/VMINIT.ASM b/v4.0/src/MEMM/MEMM/VMINIT.ASM
new file mode 100644
index 0000000..5b69b1a
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/VMINIT.ASM
@@ -0,0 +1,292 @@
1
2
3page 58,132
4;******************************************************************************
5 title VMINIT.ASM - Initialization routines for VM-DOS
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: VMINIT - Initialization routines for MEMM/ VDM
13;
14; Version: 0.04
15;
16; Date: January 30, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 01/30/86 Original
27; 04/07/86 A Added InitBitMap
28; 05/12/86 B Cleanup and segment reorganization
29; 06/18/86 0.01 Re-arranged comments, etc.
30; 06/28/86 0.02 Name change from MEMM386 to MEMM
31; 07/03/86 0.03 Added call to Kybd_Watch
32; 07/06/86 0.04 changed assume to DGROUP
33; 07/30/86 0.06 removed PortClear reference
34;
35;******************************************************************************
36;
37; Functional Description:
38;
39; This module contains various initialization routines for Virtual DOS
40;
41;******************************************************************************
42.386p
43.lfcond ; list false conditionals
44 page
45;******************************************************************************
46; P U B L I C D E C L A R A T I O N S
47;******************************************************************************
48;
49 public vminit ; module label
50 public InitBitMap ; init I/O Bit Map
51 public PortTrap ; set bit(s) in I/O Bit Map
52ifdef oldstuff
53 public PortClear ; clear bit(s) in I/O Bit Map
54endif
55 public BitOFF ; bit offset calculation
56 page
57;******************************************************************************
58; L O C A L C O N S T A N T S
59;******************************************************************************
60;
61 include VDMseg.inc
62 include VDMsel.inc
63 include desc.inc
64 include elim.inc
65FALSE equ 0
66TRUE equ not FALSE
67
68 page
69;******************************************************************************
70; E X T E R N A L R E F E R E N C E S
71;******************************************************************************
72;
73ABS0 segment at 0000h
74ABS0 ends
75
76TSS segment
77
78 extrn IOBitMap:byte ; Bit Map in Tss
79
80TSS ends
81
82
83_TEXT segment
84
85 extrn A20_Trap_Init:near ; (a20trap.asm)
86 extrn RR_Trap_Init:near ; (RRtrap.asm)
87 extrn OEM_Trap_Init:near ; (OEMProc.asm)
88
89_TEXT ends
90;
91;
92;******************************************************************************
93; L O C A L D A T A A R E A
94;******************************************************************************
95;
96_DATA segment
97;
98_DATA ends
99
100;
101;******************************************************************************
102; S E G M E N T D E F I N I T I O N
103;******************************************************************************
104;
105;------------------------------------------------------------------------------
106_TEXT segment
107 assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP
108vminit label byte
109 page
110;******************************************************************************
111; InitBitMap - Initialize 386 Tss I/O bit map for Virtual mode I/O trapping.
112;
113; ENTRY: Real Mode
114; DS = DGROUP
115; I/O bit map all zeroes (no trapping) except last byte.
116; EXIT: Real Mode
117; I/O bit map in Tss initialized.
118; USED: Flags
119; STACK:
120;------------------------------------------------------------------------------
121InitBitMap proc far
122;
123 push ax
124 push bx
125 push si
126 push es
127;
128 mov ax,seg TSS
129 mov es,ax ; set ES to I/O Bit Map seg
130 ASSUME ES:TSS
131 xor bx,bx ; ES:[BX] = pts to TSS
132;
133; initialize BitMapBase in Tss
134;
135 mov ax,offset TSS:IOBitMap
136 mov ES:[bx.BitMapBase],ax ; set Bit Map base in Tss
137;
138; set ports for return to real trap
139;
140 call RR_Trap_Init
141;
142; Turn on Keyboard watching for A20 disable
143;
144 call A20_Trap_Init
145;
146; Turn on any other OEM specific trapping
147;
148 call OEM_Trap_Init
149
150IB_exit:
151 pop es
152 ASSUME ES:DGROUP
153 pop si
154 pop bx
155 pop ax
156 ret ; *** RETURN ***
157InitBitMap endp
158
159;******************************************************************************
160; PortTrap - sets bit(s) in I/O bit map to enable trapping at an I/O address
161;
162; This function sets the appropriate bits in the I/O bit map to enable
163; trapping of the desired I/O address. Since some I/O ports on the AT system
164; board are selected via only 10 bits of address lines, these ports appear
165; at every 1K in the I/O address space. When trapping these "system board"
166; ports, the trap bits in the I/O bit map must be set for every 1k instance
167; of the port.
168;
169; ENTRY: AX = byte I/O address to set in Bit Map
170; BH = high bit set => set traps bits for this address @ every 1K
171; ES = TSS
172;
173; EXIT: none.
174;
175; USED: Flags
176; STACK:
177;------------------------------------------------------------------------------
178PortTrap proc near
179;
180 ASSUME ES:TSS
181 push ax
182 push bx
183 push cx
184;
185 mov cx,1 ; once by default
186 test bh,80h ;Q: map it every 1K ?
187 jz PT_loop ; N: do it once
188 mov cx,64 ; Y: do it 64 times (once per 1k)
189PT_loop:
190 push ax ; map it. save this address
191 call BitOFF ; get offset and bit
192 or ES:IOBitMap[bx],al ; trap this address
193 pop ax ; restore this address
194 add ax,400h ; add 1k for next address
195 loop PT_loop ; and continue ...
196;
197 pop cx
198 pop bx
199 pop ax
200 ret
201 ASSUME ES:DGROUP
202;
203PortTrap endp
204
205
206ifdef oldstuff
207;******************************************************************************
208; PortClear - clears bit(s) in I/O bit map to disable trapping at an I/O
209; address
210;
211; This function clears the appropriate bits in the I/O bit map to disable
212; trapping of the desired I/O address. Since some I/O ports on the AT system
213; board are selected via only 10 bits of address lines, these ports appear
214; at every 1K in the I/O address space. When clearing these "system board"
215; ports, the trap bits in the I/O bit map must be cleared at every 1k instance
216; of the port.
217;
218; ENTRY: AX = byte I/O address to clear in Bit Map
219; BH = high bit set => clear traps bits for this address @ every 1K
220; ES = data segment for I/O bit map
221;
222; EXIT: none.
223;
224; USED: Flags
225; STACK:
226; NOTE: This implementation does not account for a port being multiply set
227; for many purposes. (ie. If a port is set 3 times, it still only takes one
228; PortClear call to clear it.) If this is a problem, a counter for each
229; enabled port will have to be added.
230;
231;------------------------------------------------------------------------------
232PortClear proc near
233;
234 ASSUME ES:TSS
235 push ax
236 push bx
237 push cx
238;
239 mov cx,1 ; once by default
240 test bh,80h ;Q: map it every 1K ?
241 jz PC_loop ; N: do it once
242 mov cx,64 ; Y: do it 64 times (once per 1k)
243PC_loop:
244 push ax ; map it. save this address
245 call BitOFF ; get offset and bit
246 not al
247 and ES:IOBitMap[bx],al ; clear this address
248 pop ax ; restore this address
249 add ax,400h ; add 1k for next address
250 loop PC_loop ; and continue ...
251;
252 pop cx
253 pop bx
254 pop ax
255 ret
256 ASSUME ES:DGROUP
257;
258PortClear endp
259endif ; oldstuff
260
261
262;******************************************************************************
263; BitOFF - sets up byte and bit for I/O address in I/O Bit Map
264;
265; ENTRY: AX = byte I/O address to set in Bit Map
266;
267; EXIT: BX = byte offset
268; AL = bit to OR in to set proper bit
269;
270; USED: Flags
271; STACK:
272;------------------------------------------------------------------------------
273BitOFF proc near
274;
275 push cx
276
277 mov cx,ax
278 and cx,07h ; CL = bit pos for this port
279 shr ax,3 ; AX = byte offset for this bit
280 mov bx,ax ; BX = byte offset for port
281 mov ax,1
282 shl ax,cl ; AL = bit mask for this port
283
284 pop cx
285 ret
286;
287BitOFF endp
288
289;
290_TEXT ends ; end of segment
291;
292 end ; end of module
diff --git a/v4.0/src/MEMM/MEMM/VMINST.ASM b/v4.0/src/MEMM/MEMM/VMINST.ASM
new file mode 100644
index 0000000..9b1a5c7
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/VMINST.ASM
@@ -0,0 +1,2135 @@
1
2
3page 58,132
4;******************************************************************************
5 title VMINST.ASM - Virtual Mode GP fault instruction emulation
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: VMINST.ASM - Virtual Mode GP fault instruction emulation
13;
14; Version: 0.07
15;
16; Date: February 11, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 02/12/86 Original
27; 04/07/86 A- Added call to LIM emulation routines for all I/O.
28; Bit Map set up to trap only LIM related ports. SBP.
29; 05/12/86 B Cleanup and segment reorganization
30; 05/18/86 C Added VM privileged instruction emulation
31; 06/08/86 D Added calls to RRTrap.
32; 06/14/86 E Changed stack saves from BP, BX, SI to EBP, EBX, ESI
33; 06/15/86 F Changed inc [bp.VTFOE+VMTF_EIP] to inc SI in Prefix
34; Handlers
35; 06/15/86 G Added MOVSB and MOVSW for Rash Rule emulation
36; 06/16/86 H Added Error Handler interfaces, BugMode conditional
37; assembly constructs, and Error Handler return logic
38; 06/19/86 0.01 Changed call JumpReal to jmp JumpReal
39; 06/19/86 0.01 Clear TF bit on all INT reflects, but not on emulations.
40; 06/19/86 0.01 CLTS now does a clts for the VM client.
41; 06/27/86 0.02 INT3 emulation now ALLWAYS reflects
42; 06/28/86 0.02 Name change from MEMM386 to MEMM
43; 07/01/86 0.03 Call to IO_Trap instead of LIM_Trap
44; 07/03/86 0.03 Let IO_Trap handle A20 and Return to real logic
45; 07/05/86 0.04 JumpReal in R_CODE
46; 07/06/86 0.04 changed assume to DGROUP
47; 07/10/86 0.05 added MB_Flag check for move block emulator
48; 07/30/86 0.06 removed PortClear reference
49; 08/05/86 0.07 Changed EmHalt to really HLT if user IF=0
50; 07/20/88 Removed debugger codes (pc)
51;
52;******************************************************************************
53;
54; Functional Description:
55;
56; This module contains the routines that handle GP faults fielded from
57; Virtual Mode. The offending instruction is either emulated or we exit
58; to the debugger.
59;
60; NOTE: The current implementation is sufficient for breadboard - see
61; 'to do' notes in various header for holes. Specifically, the only
62; override that is handled is REP, and only for INS/OUTS. Segment
63; overrides are not yet supported.
64;
65;******************************************************************************
66.lfcond ; list false conditionals
67.386p
68 page
69;******************************************************************************
70; P U B L I C D E C L A R A T I O N S
71;******************************************************************************
72;
73 public VmInst ; module label
74 public VmFault
75 public EmProtIns ; just for debug map
76 public EmMovCDTR ; just for debug map
77 public EmMOVSW ; just for debug map
78;
79;******************************************************************************
80; E X T E R N A L R E F E R E N C E S
81;******************************************************************************
82;
83R_CODE segment
84 extrn JumpReal:far ; cont client in RM (rrtrap.asm)
85 extrn MB_Flag:byte ; non-zero => do move block
86R_CODE ends
87
88_TEXT segment
89 extrn IO_Trap:near ; I/O Trap Dispatcher
90 extrn EM286ll:near ; 286 loadall emulator (EM286LL)
91 extrn EM386ll:near ; 386 loadall emulator (EM386LL)
92 extrn Move_Block:near ; Int 15h move block function (MOVEB)
93 extrn hw_int:near ; HW-ROM reflection code (VMTRAP)
94 extrn ErrHndlr:near ; Handle user's error response
95 extrn MapLinear:near ; map linear address
96 extrn UnMapLinear:near ; unmap linear address
97_TEXT ends
98
99 page
100;******************************************************************************
101; I N C L U D E F I L E S
102;******************************************************************************
103
104include VDMseg.inc
105include desc.inc
106include VDMsel.inc
107include vm386.inc
108include loadall.inc
109include instr386.inc
110include oemdep.inc
111;******************************************************************************
112; L O C A L C O N S T A N T S
113;******************************************************************************
114;
115FALSE equ 0
116TRUE equ not FALSE
117
118LOCK_PREFIX equ 0F0h
119
120IF_FLAG equ 0200h ; IF bit in flags
121DF_FLAG equ 0400h ; DF bit in flags
122
123;
124; bit flags for instruction prefixes
125;
126REP_FLAG equ 0001h
127REPNE_FLAG equ 0002h
128REPS_FLAG equ (REP_FLAG or REPNE_FLAG)
129CS_FLAG equ 0004h
130DS_FLAG equ 0008h
131ES_FLAG equ 0010h
132SS_FLAG equ 0020h
133FS_FLAG equ 0040h
134GS_FLAG equ 0080h
135LOCK_FLAG equ 0100h
136OPER_SZ_FLAG equ 0200h
137ADDR_SZ_FLAG equ 0400h
138P0F_FLAG equ 0800h
139
140page
141;******************************************************************************
142; L O C A L D A T A A R E A
143;******************************************************************************
144_DATA segment
145
146PrefixFlag dw 0 ; flags for Fault Instr Prefixes
147RefNum dw 0 ; Reflect number for RefToRom
148
149_DATA ends
150
151page
152;******************************************************************************
153; C O D E A R E A
154;******************************************************************************
155_TEXT segment
156 assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP
157
158VmInst label byte
159;
160; Index table for opcode emulation dispatch - This is too general-purpose
161; if all we want to handle is INT instructions, but it'll get fleshed out
162; later, when we start emulating IOPL-sensitive stuff
163;
164; the directive below is giving problems because this segment is byte aligned
165; will fix it..sunilp
166; EVEN ; word aligning should make execution
167 ; faster
168OpTable label word
169 dw offset _TEXT:BadVmTrap ; 0 - LLDT, LTR, SLDT, STR, VERR, VERW
170 dw offset _TEXT:EmProtIns ; 1 - LGDT, LIDT, LMSW
171 dw offset _TEXT:BadVmTrap ; 2 - LAR
172 dw offset _TEXT:BadVmTrap ; 3 - LSL
173 dw offset _TEXT:BadVmTrap ; 4
174 dw offset _TEXT:EmLoadal2 ; 5 - 286Loadall
175 dw offset _TEXT:EmCLTS ; 6 - CLTS
176 dw offset _TEXT:EmLoadal3 ; 7 - 386Loadall
177 dw offset _TEXT:BadVmTrap ; 8
178 dw offset _TEXT:BadVmTrap ; 9
179 dw offset _TEXT:BadVmTrap ; a
180 dw offset _TEXT:BadVmTrap ; b
181 dw offset _TEXT:BadVmTrap ; c
182 dw offset _TEXT:BadVmTrap ; d
183 dw offset _TEXT:BadVmTrap ; e
184 dw offset _TEXT:Prefix_0F ; f
185 dw offset _TEXT:BadVmTrap ; 10
186 dw offset _TEXT:BadVmTrap ; 11
187 dw offset _TEXT:BadVmTrap ; 12
188 dw offset _TEXT:BadVmTrap ; 13
189 dw offset _TEXT:BadVmTrap ; 14
190 dw offset _TEXT:BadVmTrap ; 15
191 dw offset _TEXT:BadVmTrap ; 16
192 dw offset _TEXT:BadVmTrap ; 17
193 dw offset _TEXT:BadVmTrap ; 18
194 dw offset _TEXT:BadVmTrap ; 19
195 dw offset _TEXT:BadVmTrap ; 1a
196 dw offset _TEXT:BadVmTrap ; 1b
197 dw offset _TEXT:BadVmTrap ; 1c
198 dw offset _TEXT:BadVmTrap ; 1d
199 dw offset _TEXT:BadVmTrap ; 1e
200 dw offset _TEXT:BadVmTrap ; 1f
201 dw offset _TEXT:EmMovCDTR ; 20 - Mov Rn, CRn
202 dw offset _TEXT:EmMovCDTR ; 21 - Mov Rn, DRn
203 dw offset _TEXT:EmMovCDTR ; 22 - Mov CRn, Rn
204 dw offset _TEXT:EmMovCDTR ; 23 - Mov DRn, Rn
205 dw offset _TEXT:EmMovCDTR ; 24 - Mov Rn, TRn
206 dw offset _TEXT:BadVmTrap ; 25
207 dw offset _TEXT:ESOverride ; 26 - ES Override & Mov TRn, Rn
208 dw offset _TEXT:BadVmTrap ; 27
209 dw offset _TEXT:BadVmTrap ; 28
210 dw offset _TEXT:BadVmTrap ; 29
211 dw offset _TEXT:BadVmTrap ; 2a
212 dw offset _TEXT:BadVmTrap ; 2b
213 dw offset _TEXT:BadVmTrap ; 2c
214 dw offset _TEXT:BadVmTrap ; 2d
215 dw offset _TEXT:CSOverride ; 2e - CS Override
216 dw offset _TEXT:BadVmTrap ; 2f
217 dw offset _TEXT:BadVmTrap ; 30
218 dw offset _TEXT:BadVmTrap ; 31
219 dw offset _TEXT:BadVmTrap ; 32
220 dw offset _TEXT:BadVmTrap ; 33
221 dw offset _TEXT:BadVmTrap ; 34
222 dw offset _TEXT:BadVmTrap ; 35
223 dw offset _TEXT:SSOverride ; 36 - SS Override
224 dw offset _TEXT:BadVmTrap ; 37
225 dw offset _TEXT:BadVmTrap ; 38
226 dw offset _TEXT:BadVmTrap ; 39
227 dw offset _TEXT:BadVmTrap ; 3a
228 dw offset _TEXT:BadVmTrap ; 3b
229 dw offset _TEXT:BadVmTrap ; 3c
230 dw offset _TEXT:BadVmTrap ; 3d
231 dw offset _TEXT:DSOverride ; 3e - DS Override
232 dw offset _TEXT:BadVmTrap ; 3f
233 dw offset _TEXT:BadVmTrap ; 40
234 dw offset _TEXT:BadVmTrap ; 41
235 dw offset _TEXT:BadVmTrap ; 42
236 dw offset _TEXT:BadVmTrap ; 43
237 dw offset _TEXT:BadVmTrap ; 44
238 dw offset _TEXT:BadVmTrap ; 45
239 dw offset _TEXT:BadVmTrap ; 46
240 dw offset _TEXT:BadVmTrap ; 47
241 dw offset _TEXT:BadVmTrap ; 48
242 dw offset _TEXT:BadVmTrap ; 49
243 dw offset _TEXT:BadVmTrap ; 4a
244 dw offset _TEXT:BadVmTrap ; 4b
245 dw offset _TEXT:BadVmTrap ; 4c
246 dw offset _TEXT:BadVmTrap ; 4d
247 dw offset _TEXT:BadVmTrap ; 4e
248 dw offset _TEXT:BadVmTrap ; 4f
249 dw offset _TEXT:BadVmTrap ; 50
250 dw offset _TEXT:BadVmTrap ; 51
251 dw offset _TEXT:BadVmTrap ; 52
252 dw offset _TEXT:BadVmTrap ; 53
253 dw offset _TEXT:BadVmTrap ; 54
254 dw offset _TEXT:BadVmTrap ; 55
255 dw offset _TEXT:BadVmTrap ; 56
256 dw offset _TEXT:BadVmTrap ; 57
257 dw offset _TEXT:BadVmTrap ; 58
258 dw offset _TEXT:BadVmTrap ; 59
259 dw offset _TEXT:BadVmTrap ; 5a
260 dw offset _TEXT:BadVmTrap ; 5b
261 dw offset _TEXT:BadVmTrap ; 5c
262 dw offset _TEXT:BadVmTrap ; 5d
263 dw offset _TEXT:BadVmTrap ; 5e
264 dw offset _TEXT:BadVmTrap ; 5f
265 dw offset _TEXT:BadVmTrap ; 60
266 dw offset _TEXT:BadVmTrap ; 61
267 dw offset _TEXT:BadVmTrap ; 62
268;
269; ARPL is used to return from virtual mode to protected mode for use in MEMM
270;
271 dw offset _TEXT:ReturnEMM ; 63 - ARPL (return to Protected mode gateway)
272 dw offset _TEXT:FSOverride ; 64 - FS override
273 dw offset _TEXT:GSOverride ; 65 - GS override
274 dw offset _TEXT:BadVmTrap ; 66 - Operand size override
275 dw offset _TEXT:BadVmTrap ; 67 - Address size override
276 dw offset _TEXT:BadVmTrap ; 68
277 dw offset _TEXT:BadVmTrap ; 69
278 dw offset _TEXT:BadVmTrap ; 6a
279 dw offset _TEXT:BadVmTrap ; 6b
280 dw offset _TEXT:EmINSB ; 6c - INSB
281 dw offset _TEXT:EmINSW ; 6d - INSW
282 dw offset _TEXT:EmOUTSB ; 6e - OUTSB
283 dw offset _TEXT:EmOUTSW ; 6f - OUTSW
284 dw offset _TEXT:BadVmTrap ; 70
285 dw offset _TEXT:BadVmTrap ; 71
286 dw offset _TEXT:BadVmTrap ; 72
287 dw offset _TEXT:BadVmTrap ; 73
288 dw offset _TEXT:BadVmTrap ; 74
289 dw offset _TEXT:BadVmTrap ; 75
290 dw offset _TEXT:BadVmTrap ; 76
291 dw offset _TEXT:BadVmTrap ; 77
292 dw offset _TEXT:BadVmTrap ; 78
293 dw offset _TEXT:BadVmTrap ; 79
294 dw offset _TEXT:BadVmTrap ; 7a
295 dw offset _TEXT:BadVmTrap ; 7b
296 dw offset _TEXT:BadVmTrap ; 7c
297 dw offset _TEXT:BadVmTrap ; 7d
298 dw offset _TEXT:BadVmTrap ; 7e
299 dw offset _TEXT:BadVmTrap ; 7f
300 dw offset _TEXT:BadVmTrap ; 80
301 dw offset _TEXT:BadVmTrap ; 81
302 dw offset _TEXT:BadVmTrap ; 82
303 dw offset _TEXT:BadVmTrap ; 83
304 dw offset _TEXT:BadVmTrap ; 84
305 dw offset _TEXT:BadVmTrap ; 85
306 dw offset _TEXT:BadVmTrap ; 86
307 dw offset _TEXT:BadVmTrap ; 87
308 dw offset _TEXT:BadVmTrap ; 88
309 dw offset _TEXT:BadVmTrap ; 89
310 dw offset _TEXT:BadVmTrap ; 8a
311 dw offset _TEXT:BadVmTrap ; 8b
312 dw offset _TEXT:BadVmTrap ; 8c
313 dw offset _TEXT:BadVmTrap ; 8d
314 dw offset _TEXT:BadVmTrap ; 8e
315 dw offset _TEXT:BadVmTrap ; 8f
316 dw offset _TEXT:BadVmTrap ; 90
317 dw offset _TEXT:BadVmTrap ; 91
318 dw offset _TEXT:BadVmTrap ; 92
319 dw offset _TEXT:BadVmTrap ; 93
320 dw offset _TEXT:BadVmTrap ; 94
321 dw offset _TEXT:BadVmTrap ; 95
322 dw offset _TEXT:BadVmTrap ; 96
323 dw offset _TEXT:BadVmTrap ; 97
324 dw offset _TEXT:BadVmTrap ; 98
325 dw offset _TEXT:BadVmTrap ; 99
326 dw offset _TEXT:BadVmTrap ; 9a
327 dw offset _TEXT:BadVmTrap ; 9b
328 dw offset _TEXT:BadVmTrap ; 9c - PUSHF (not for IOPL=3)
329 dw offset _TEXT:BadVmTrap ; 9d - POPF (not for IOPL=3)
330 dw offset _TEXT:BadVmTrap ; 9e
331 dw offset _TEXT:BadVmTrap ; 9f
332 dw offset _TEXT:BadVmTrap ; a0
333 dw offset _TEXT:BadVmTrap ; a1
334 dw offset _TEXT:BadVmTrap ; a2
335 dw offset _TEXT:BadVmTrap ; a3
336 dw offset _TEXT:BadVmTrap ; a4 - MOVSB
337 dw offset _TEXT:EmMOVSW ; a5 - MOVSW
338 dw offset _TEXT:BadVmTrap ; a6
339 dw offset _TEXT:BadVmTrap ; a7
340 dw offset _TEXT:BadVmTrap ; a8
341 dw offset _TEXT:BadVmTrap ; a9
342 dw offset _TEXT:BadVmTrap ; aa
343 dw offset _TEXT:BadVmTrap ; ab
344 dw offset _TEXT:BadVmTrap ; ac
345 dw offset _TEXT:BadVmTrap ; ad
346 dw offset _TEXT:BadVmTrap ; ae
347 dw offset _TEXT:BadVmTrap ; af
348 dw offset _TEXT:BadVmTrap ; b0
349 dw offset _TEXT:BadVmTrap ; b1
350 dw offset _TEXT:BadVmTrap ; b2
351 dw offset _TEXT:BadVmTrap ; b3
352 dw offset _TEXT:BadVmTrap ; b4
353 dw offset _TEXT:BadVmTrap ; b5
354 dw offset _TEXT:BadVmTrap ; b6
355 dw offset _TEXT:BadVmTrap ; b7
356 dw offset _TEXT:BadVmTrap ; b8
357 dw offset _TEXT:BadVmTrap ; b9
358 dw offset _TEXT:BadVmTrap ; ba
359 dw offset _TEXT:BadVmTrap ; bb
360 dw offset _TEXT:BadVmTrap ; bc
361 dw offset _TEXT:BadVmTrap ; bd
362 dw offset _TEXT:BadVmTrap ; be
363 dw offset _TEXT:BadVmTrap ; bf
364 dw offset _TEXT:BadVmTrap ; c0
365 dw offset _TEXT:BadVmTrap ; c1
366 dw offset _TEXT:BadVmTrap ; c2
367 dw offset _TEXT:BadVmTrap ; c3
368 dw offset _TEXT:BadVmTrap ; c4
369 dw offset _TEXT:BadVmTrap ; c5
370 dw offset _TEXT:BadVmTrap ; c6
371 dw offset _TEXT:BadVmTrap ; c7
372 dw offset _TEXT:BadVmTrap ; c8
373 dw offset _TEXT:BadVmTrap ; c9
374 dw offset _TEXT:BadVmTrap ; ca
375 dw offset _TEXT:BadVmTrap ; cb
376 dw offset _TEXT:EmINT3 ; cc - INT 3
377 dw offset _TEXT:EmINTnn ; cd - INT nn
378 dw offset _TEXT:EmINTO ; ce - INTO
379 dw offset _TEXT:BadVmTrap ; cf - IRET/EmIRET (not for IOPL=3)
380 dw offset _TEXT:BadVmTrap ; d0
381 dw offset _TEXT:BadVmTrap ; d1
382 dw offset _TEXT:BadVmTrap ; d2
383 dw offset _TEXT:BadVmTrap ; d3
384 dw offset _TEXT:BadVmTrap ; d4
385 dw offset _TEXT:BadVmTrap ; d5
386 dw offset _TEXT:BadVmTrap ; d6
387 dw offset _TEXT:BadVmTrap ; d7
388 dw offset _TEXT:BadVmTrap ; d8
389 dw offset _TEXT:BadVmTrap ; d9
390 dw offset _TEXT:BadVmTrap ; da
391 dw offset _TEXT:BadVmTrap ; db
392 dw offset _TEXT:BadVmTrap ; dc
393 dw offset _TEXT:BadVmTrap ; dd
394 dw offset _TEXT:BadVmTrap ; de
395 dw offset _TEXT:BadVmTrap ; df
396 dw offset _TEXT:BadVmTrap ; e0
397 dw offset _TEXT:BadVmTrap ; e1
398 dw offset _TEXT:BadVmTrap ; e2
399 dw offset _TEXT:BadVmTrap ; e3
400 dw offset _TEXT:EmINBimm ; e4 - INB imm
401 dw offset _TEXT:EmINWimm ; e5 - INW imm
402 dw offset _TEXT:EmOUTBimm ; e6 - OUTB imm
403 dw offset _TEXT:EmOUTWimm ; e7 - OUTW imm
404 dw offset _TEXT:BadVmTrap ; e8
405 dw offset _TEXT:BadVmTrap ; e9
406 dw offset _TEXT:BadVmTrap ; ea
407 dw offset _TEXT:BadVmTrap ; eb
408 dw offset _TEXT:EmINB ; ec - INB
409 dw offset _TEXT:EmINW ; ed - INW
410 dw offset _TEXT:EmOUTB ; ee - OUTB
411 dw offset _TEXT:EmOUTW ; ef - OUTW
412 dw offset _TEXT:EmLOCK ; f0 - LOCK
413 dw offset _TEXT:BadVmTrap ; f1
414 dw offset _TEXT:EmREPNE ; f2 - REPNE
415 dw offset _TEXT:EmREP ; f3 - REP/REPE
416 dw offset _TEXT:EmHALT ; f4 - HLT
417 dw offset _TEXT:BadVmTrap ; f5
418 dw offset _TEXT:BadVmTrap ; f6
419 dw offset _TEXT:BadVmTrap ; f7
420 dw offset _TEXT:BadVmTrap ; f8
421 dw offset _TEXT:BadVmTrap ; f9
422 dw offset _TEXT:BadVmTrap ; fa - CLI EmCLI (not for IOPL=3)
423 dw offset _TEXT:BadVmTrap ; fb - STI EmSTI (not for IOPL=3)
424 dw offset _TEXT:BadVmTrap ; fc
425 dw offset _TEXT:BadVmTrap ; fd
426 dw offset _TEXT:BadVmTrap ; fe
427 dw offset _TEXT:BadVmTrap ; ff - Change P0F_Invalid, if used
428
429 page
430;******************************************************************************
431; VmFault - entry point for Virtual Mode GP faults (from routine vm_trap0d
432; in module VMTRAP.ASM). The appropriate instructions are emulated and
433; control is returned to the Virtual Mode client. Currently, we assume
434; the client is running WITH IOPL, INT gate DPL = 0, and a truncated
435; IDT, so INT instruction fault to here and are emulated. All other
436; GP faults enter the debugger.
437;
438; The following instructions are invalid in Real or Virtual Mode:
439;
440; ARPL, LAR, LSL, VERR, VERW, STR, LTR, SLDT, LLDT
441;
442; The following instructions are privileged and are thus invalid in
443; Virtual Mode since VM progs run at CPL 3:
444;
445; LIDT, LDGT, LMSW, CLTS, HLT, Debug Register ops, Control
446; Register ops, and Test Register ops
447;
448; If client does not have IOPL, the following instructions must be handled
449; (in addition to the INT instructions). This scenario changes for B0:
450;
451; IN, INS, OUT, OUTS, STI, CLI, LOCK, PUSHF, POPF, and IRET
452;
453; For B0, the following instructions must be handled when they trap
454; according to the bit map in the TSS.
455;
456; IN, INS, OUT, and OUTS
457;
458; For Invalid Opcode (vm_trap06) emulation:
459; The following instructions are invalid in Real or Virtual Mode:
460;
461; LTR, LLDT, LAR, LSL, ARPL, STR, SLDT, VERR, VERW
462;
463; In fielding the exception from Virtual Mode, the 386 interrupt gate
464; switched to the Ring 0 stack and pushed 32-bit values as follows:
465;
466; hiword loword offset (in addition to error code and BP push)
467; +------+------+ <-------- Top of 'kernel' stack
468; | 0000 | GS | +32 (decimal)
469; |------+------|
470; | 0000 | FS | +28
471; |------|------|
472; | 0000 | DS | +24
473; |------|------|
474; | 0000 | ES | +20
475; |------|------|
476; | 0000 | SS | +16
477; |------|------|
478; | ESP | +12
479; |------|------|
480; | EFLAGS | +08
481; |------|------|
482; | 0000 | CS | +04
483; |------|------|
484; | EIP | +00
485; +------|------+
486; | error code |
487; |------|------| <-------- Ring 0 SS:SP
488; | (ebp) |
489; +------+------+ <-------- Ring 0 SS:EBP
490;
491;
492; ENTRY: 386 Protected Mode - ring 0
493; EBP is on the stack
494; SS:BP -> VM trap frame on stack w/error code (faulting selector)
495; GP exceptions are faults: pushed CS:EIP points to faulting opcode
496; EXIT: via IRET to VM client, instruction emulated as necessary
497; USED: (none) (note that DS & ES are free to use - saved during trap)
498; STACK: n/a
499;------------------------------------------------------------------------------
500VmFault proc near
501 PUSH_EBX ; local registers
502 PUSH_ESI
503 HwTabUnlock ; unlock high ram for gdt changes
504 mov bx,GDTD_GSEL ; get GDT data alias
505 mov ds,bx ; DS -> GDT
506;
507; Build a selector (VM1_GSEL) to client's stack. VM1_GSEL is already set
508; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base.
509;
510 mov bx,[bp.VTFOE+VMTF_SS] ; BX = VM SS (segment form)
511 shl bx,4 ; BX = low 16 bits of base
512 mov ds:[VM1_GSEL+2],bx ; place in descriptor
513 mov bx,[bp.VTFOE+VMTF_SS] ; BX = VM SS (again)
514 shr bx,4 ; BH = high 8 bits of base
515 mov ds:[VM1_GSEL+4],bh ; place in descriptor
516;
517; Build a selector (VM2_GSEL) to client's code segment, as above.
518;
519 mov bx,[bp.VTFOE+VMTF_CS] ; BX = VM CS (in segment form)
520 shl bx,4 ; BX = low 16 bits of base
521 mov ds:[VM2_GSEL+2],bx ; place in descriptor
522 mov bx,[bp.VTFOE+VMTF_CS] ; BX = VM CS (again)
523 shr bx,4 ; BH = high 8 bits of base
524 mov ds:[VM2_GSEL+4],bh ; place in descriptor
525;
526; Reset prefix flags
527;
528 mov bx,VDMD_GSEL
529 mov es,bx
530 mov ES:[PrefixFlag],0 ; start with no prefixes
531;
532; Jump to appropriate instruction handler
533;
534 mov bx,VM2_GSEL
535 mov ds,bx ; DS = selector for VM code segment
536 mov si,[bp.VTFOE+VMTF_EIP] ; DS:SI = VM CS:IP
537VmInsHandle:
538 mov bl,ds:[si] ; BL = opcode
539 mov bh,0 ; BX = opcode
540 shl bx,1 ; BX = BX*2 (word table)
541 ; DS:SI = VM CS:IP
542 ; ES pts to local data segment
543 ; VM1_GSEL pts to VM SS
544 ; VM2_GSEL pts to VM CS
545 jmp cs:OpTable[bx] ; enter instruction emulation routine
546
547VmFault endp
548
549page
550;******************************************************************************
551; BadVmTrap - unsupported Virtual Mode GP exception - enter the debugger
552;
553; ENTRY: EBP,EBX,ESI are on the stack
554; EXIT: to the debugger
555; USED:
556; STACK: n/a
557;------------------------------------------------------------------------------
558BadVmTrap proc near
559 jmp Reflect6 ; Reflect to VM illegal opcode handler
560BadVmTrap endp
561
562page
563;******************************************************************************
564; ReturnEMM - user is trying to go back into the protected mode via ARPL
565;
566; ENTRY: EBP,EBX,ESI are on the stack
567; EXIT: to the debugger
568; USED:
569; STACK: n/a
570;------------------------------------------------------------------------------
571ReturnEMM proc near
572 add si, 2 ; "IP" now points to instruction
573 push si ; after "ARPL reg,reg"
574 ret ; back in protected mode!
575ReturnEMM endp
576
577page
578;******************************************************************************
579; EmINTnn - emulate software interrupt
580;
581; The emulation of the software INT instructions requires us to massage
582; the trap stack frame (see VmFault header) and build a 'real mode'
583; stack frame for the virtual mode client so that we can transfer
584; control to virtual mode at the address specified in the appropriate
585; real mode IDT vector. The client's IRET out of the interrupt routine
586; will proceed normally (assuming we're letting him run with IOPL = 3).
587; Since we're fielding the trap from Virtual Mode, we assume the high
588; word of ESP and EIP is 0000.
589;
590; +-------+ <-------- Client's current SS:SP
591; | Flags | +4
592; |-------|
593; | CS | +2
594; |-------|
595; | IP | +0
596; +-------+ <-------- Client's SS:SP when we let him have control
597;
598; ENTRY: 386 Protected Mode
599; EBP,EBX,ESI pushed on stack
600; VM1_GSEL = VM client's stack segment
601; VM2_GSEL = VM client's code segment
602; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL)
603; EXIT: via IRET to VM client
604; appropriate real mode IRET set up @ client's SS:SP
605; USED: (none)
606; STACK:
607;
608; to do: Streamline this code - it's on the critical path
609; Decide about how to handle Trace Bit in general
610;------------------------------------------------------------------------------
611EmINTnn proc near
612
613 inc si ; DS:SI -> nn (int #)
614
615; Check for Int15 (Move Block call)
616 cmp byte ptr [si], 15h
617 jne NotInt15
618 cmp ah,87h ;Q: is this a move block call ?
619 jne NotInt15 ; N: process as normal interrupt
620 mov bx,RCODEA_GSEL ; Y: check local flag
621 mov ds,bx ; DS -> R_CODE seg
622 ASSUME DS:R_CODE
623 cmp [MB_Flag],0 ; Q: do we see this move block ?
624 je NotInt15 ; N: process as normal int
625 ; Y: emulate move block
626 ; set up VM1_GSEL to point to ES:0 from
627 ; Virtual Mode
628 ;NOTE: DS -> R_CODE
629 inc si
630 mov [bp.VTFOE+VMTF_EIP], si ; point beyond int6 instr
631 mov bx,GDTD_GSEL
632 mov es,bx ; ES pts to GDT
633 mov bx,[bp.VTFOE+VMTF_ES] ; BX = ES seg addr
634 shl bx,4 ; BX = low 16 bits of ES addr
635 mov es:[VM1_GSEL+2],bx ; set low 16 bits of ES base addr
636 mov bx,[bp.VTFOE+VMTF_ES] ; BX = ES seg addr again
637 shr bx,4 ; BH = high 8 bits of ES addr
638 mov es:[VM1_GSEL+4],bh ; place in descriptor
639
640 mov bx,VM1_GSEL
641 mov es,bx ; ES pts to VM ES area
642
643 mov bx,sp ; SS:BX -> GP Fault stack frame
644 mov si,SS:[bx.GPF_ESI] ; ES:SI pts to caller's gdt
645 call move_block ; move block function
646 mov ds:[MB_Flag],0 ; turn off flag !!
647
648 ASSUME DS:DGROUP ; done with R_CODE
649
650 jmp short EmSkipLockExit ; exit, but skip table lock.
651 ; move block MAY unlock tables.
652;
653; Adjust client's SP to make room for building his IRET frame
654;
655NotInt15:
656 sub word ptr [bp.VTFOE+VMTF_ESP],6 ; adjust client's SP
657 mov bx,VM1_GSEL
658 mov ds,bx ; DS = VM stack segment
659 mov si,[bp.VTFOE+VMTF_ESP] ; DS:SI -> client's IRET stack frame
660;
661; Move low 16 bits of Flags, CS, and EIP from IRET frame to client stack frame
662;
663 mov bx,[bp.VTFOE+VMTF_EFLAGS] ; low word of EFLAGS
664;
665; *** Clear IF bit on flags for reflect, but leave it unchanged for the
666; flags on the IRET stack we build on the client's stack
667; *** Also clear the Trace Flag -> because all software INTs clear the trace
668; flag.
669;
670 and [bp.VTFOE+VMTF_EFLAGS],not 300h
671
672 mov ds:[si.4],bx ; to client's flags
673 mov bx,[bp.VTFOE+VMTF_CS] ;
674 mov ds:[si.2],bx ; to client's CS
675 mov bx,[bp.VTFOE+VMTF_EIP] ; low word of EIP
676 add bx,2 ; set IP past the instruction we emulate
677 mov ds:[si.0],bx ; to client's IP
678;
679; Replace low 16 bits of IRET frame CS:EIP with vector from real mode IDT
680;
681 mov si,VM2_GSEL
682 mov ds,si ; DS -> Client's code segment
683 mov bl,ds:[bx-1] ; get INTerrupt number
684 xor bh,bh ; BX has INT number
685 shl bx,2 ; BX = BX * 4 (vector table index)
686 mov si,RM_IDT_GSEL ; get real mode IDT alias
687 mov ds,si ; DS -> Real Mode IDT
688 mov si,ds:[bx] ;
689 mov [bp.VTFOE+VMTF_EIP],si ; move the IP
690 mov si,ds:[bx+2] ;
691 mov [bp.VTFOE+VMTF_CS],si ; move the CS
692;
693; 32-bit IRET back to client
694;
695EmExit:
696 HwTabLock ; enable the high ram hw protection
697EmSkipLockExit: ; as the label implies...
698 POP_ESI ; restore local regs
699 POP_EBX
700 POP_EBP
701 add sp,4 ; throw away error code
702 OP32_IRET ; *** RETURN *** to client
703EmINTnn endp
704
705page
706;******************************************************************************
707; EmINT3 - emulate the 'breakpoint' interrupt instruction
708;
709; ENTRY: 386 Protected Mode
710; EBP,EBX,ESI pushed on stack
711; VM1_GSEL = VM client's stack segment
712; VM2_GSEL = VM client's code segment
713; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL)
714; EXIT: via IRET to VM client
715; appropriate real mode IRET set up @ client's SS:SP
716; USED: (none)
717; STACK:
718;
719; to do: implement the handler
720;------------------------------------------------------------------------------
721EmINT3 proc near
722 mov ES:[RefNum], 03h ; Vector to VM int 3 handler
723RefIntN:
724 inc si ; fault, not a trap
725 mov [bp.VTFOE+VMTF_EIP], si ; point beyond int3
726 jmp RefToRom ; and let the VM OS handle it
727EmINT3 endp
728
729;******************************************************************************
730; EmINTO - emulate overflow interrupt
731;
732; ENTRY: 386 Protected Mode
733; EBP,EBX,ESI pushed on stack
734; VM1_GSEL = VM client's stack segment
735; VM2_GSEL = VM client's code segment
736; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL)
737; EXIT: via IRET to VM client
738; appropriate real mode IRET set up @ client's SS:SP
739; USED: (none)
740; STACK:
741;------------------------------------------------------------------------------
742EmINTO proc near
743 mov ES:[RefNum], 04h ; Vector to VM int 3 handler
744 jmp short RefIntN
745EmINTO endp
746
747page
748;******************************************************************************
749; EmINB - emulate the IN byte instruction
750;
751; ENTRY: 386 Protected Mode
752; EBP,EBX,ESI pushed on stack
753; VM1_GSEL = VM client's stack segment
754; VM2_GSEL = VM client's code segment
755; DS:SI -> faulting opcode = nn (DS = VM2_GSEL)
756; EXIT: via IRET to VM client
757; USED:
758; STACK: n/a
759;------------------------------------------------------------------------------
760EmINB proc near
761 inc si
762 mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate
763 push bx
764 xor bx,bx ; IN instruction
765 call IO_Trap ; Q: Emulated ?
766 jnc EINB_Exit ; Y: exit
767 in al,dx ; N:do the INput
768EINB_Exit:
769 pop bx
770 jmp EmExit ; *** RETURN *** to VM client
771EmINB endp
772
773page
774;******************************************************************************
775; EmINW - emulate IN word
776;
777; This routine emulates the IN word instruction
778;
779; ENTRY 386 PROTECTED MODE
780; see common description at top
781;
782; EXIT IRET back to VM program
783;------------------------------------------------------------------------------
784EmINW proc near
785 inc si
786 mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate
787 push bx
788 xor bx,bx ; IN instruction
789 call IO_Trap ; Q: Emulated ?
790 cbw ; AX= returned value
791 jnc EINW_Exit ; Y: exit
792 in ax,dx ; N:do the word INput
793EINW_Exit: ;
794 pop bx ;
795 jmp EmExit ; *** RETURN *** to VM client
796EmINW endp
797
798page
799;******************************************************************************
800; EmINBimm - emulate IN word immediate
801;
802; This routine emulates the IN word immediate instruction
803;
804; ENTRY 386 PROTECTED MODE
805; see common description at top
806;
807; EXIT IRET back to VM program
808;------------------------------------------------------------------------------
809EmINBimm proc near
810 push bx
811 push dx
812 mov dl,ds:[si+1] ; get port number
813 xor dh,dh ; DX has INT number
814 add si, 2
815 mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate
816 xor bx,bx ; IN instruction
817 call IO_Trap ; Q: Emulated ?
818 jnc EINBi_Exit ; Y: exit
819 in al,dx ; N:do the INput
820EINBi_exit:
821 pop dx
822 pop bx
823 jmp EmExit ; *** RETURN *** to VM client
824EmINBimm endp
825
826page
827;******************************************************************************
828;*** EmINWimm - emulate IN word immediate
829;
830; This routine emulates the IN word immediate instruction
831;
832; ENTRY 386 PROTECTED MODE
833; see common description at top
834;
835; EXIT IRET back to VM program
836;------------------------------------------------------------------------------
837EmINWimm proc near
838 push bx
839 push dx
840 mov dl,ds:[si+1] ; get port number
841 xor dh,dh ; DX has INT number
842 add si, 2
843 mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate
844 xor bx,bx ; IN instruction
845 call IO_Trap ; Q: Emulated ?
846 cbw ; AX = returned value
847 jnc EINWi_Exit ; Y: exit
848 in ax,dx ; N:do the word INput
849EINWi_Exit:
850 pop dx
851 pop bx
852 jmp EmExit ; *** RETURN *** to VM client
853EmINWimm endp
854
855page
856;******************************************************************************
857;*** EmOUTB - emulate OUT byte
858;
859; This routine emulates the OUT byte instruction
860;
861; ENTRY 386 PROTECTED MODE
862; see common description at top
863;
864; EXIT IRET back to VM program
865;
866EmOUTB proc near
867 inc si
868 mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate
869 push bx
870 push dx
871 mov bx,1 ; OUT instruction
872 call IO_Trap ; Q: Emulated ?
873 jnc EOUTB_Exit ; Y:exit
874EOUTB_em:
875 out dx,al ; N:do the byte OUTput
876EOUTB_Exit:
877 pop dx
878 pop bx
879 jmp EmExit ; *** RETURN *** to VM client
880EmOUTB endp
881
882page
883;******************************************************************************
884;*** EmOUTW - emulate OUT word
885;
886; This routine emulates the OUT word instruction
887;
888; ENTRY 386 PROTECTED MODE
889; see common description at top
890;
891; EXIT IRET back to VM program
892;
893EmOUTW proc near
894 inc si
895 mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate
896 push bx
897 mov bx,1 ; OUT instruction
898 call IO_Trap ; Q: Emulated ?
899 jnc EOUTW_Exit ; Y: exit
900 ; N:
901 out dx,ax ; do the word OUTput
902EOUTW_Exit:
903 pop bx
904 jmp EmExit ; *** RETURN *** to VM client
905EmOUTW endp
906
907page
908;******************************************************************************
909;*** EmOUTBimm - emulate OUT byte immediate
910;
911; This routine emulates the OUT byte immediate
912;
913; ENTRY 386 PROTECTED MODE
914; see common description at top
915;
916; EXIT IRET back to VM program
917;
918EmOUTBimm proc near
919 push bx
920 push dx
921 mov dl,ds:[si+1] ; get port number
922 xor dh,dh ; DX has INT number
923 add si, 2
924 mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate
925 mov bx,1 ; OUT instruction
926 call IO_Trap ; Q: Emulated ?
927 jnc EOUTBi_Exit ; Y:exit
928EOUTBi_em:
929 out dx,al ; N:do the byte OUTput
930EOUTBi_Exit:
931 pop dx
932 pop bx
933 jmp EmExit ; *** RETURN *** to VM client
934EmOUTBimm endp
935
936page
937;******************************************************************************
938;*** EmOUTWimm - emulate OUT word immediate
939;
940; This routine emulates the OUT word immediate instruction
941;
942; ENTRY 386 PROTECTED MODE
943; see common description at top
944;
945; EXIT IRET back to VM program
946;
947EmOUTWimm proc near
948 push bx
949 push dx
950 mov dl,ds:[si+1] ; get port number
951 xor dh,dh ; DX has INT number
952 add si, 2
953 mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate
954 mov bx,1 ; OUT instruction
955 call IO_Trap ; Q: Emulated ?
956 jnc EOUTWi_Exit ; Y: exit
957 out dx,ax ; N:do the word OUTput
958EOUTWi_Exit:
959 pop dx
960 pop bx
961 jmp EmExit ; *** RETURN *** to VM client
962EmOUTWimm endp
963page
964;******************************************************************************
965;*** EmHALT - Emulate HALT command
966;
967; This routine is entered if a faulting instruction
968; is a HALT command
969;
970; ENTRY 386 PROTECTED MODE
971; see common description at top
972;
973; EXIT return to VM client unless client IF=0 then
974; HLT is executed with IF=0
975;
976EmHALT proc near
977 ; Q: client's IF bit is 0?
978 test word ptr [bp.VTFOE+VMTF_EFLAGS], IF_FLAG
979 jz EmDoHlt ; Y: execute HLT if IF=0
980 inc si ; inc VM CS:IP past command
981 mov [bp.VTFOE+VMTF_EIP], si ; we emulate
982; A halt on an INTEL architecture machine is just waiting for an interrupt
983; We'll pretend an interrupt occurs after a short wait
984 push cx
985 mov cx,4000h
986 loop $ ; Wait awhile
987 pop cx
988 jmp EmExit ; then leave
989emDoHlt:
990 cli
991 hlt ; Halt till NMI
992 jmp EmExit
993
994EmHALT endp
995
996page
997;******************************************************************************
998;*** EmLoadal2 - Emulate 286 Loadall command
999;
1000; This routine is entered if a faulting instruction
1001; is a Loadall 286 command
1002;
1003; ENTRY 386 PROTECTED MODE
1004; see common description at top
1005;
1006; EXIT return to VM client
1007;
1008EmLoadal2 proc near
1009
1010 test ES:[PrefixFlag],P0F_FLAG ; Q:Do we have the right prefix?
1011 jz Not_Loadall
1012 jmp EM286ll ; Y: emulate 286 loadall
1013
1014Not_Loadall:
1015 jmp BadVmTrap ; N: Vector to VM illegal opcode
1016
1017EmLoadal2 endp
1018
1019;******************************************************************************
1020;*** EmLoadal3 - Emulate 386 Loadall command
1021;
1022; This routine is entered if a faulting instruction
1023; is a Loadall 386 command
1024;
1025; ENTRY 386 PROTECTED MODE
1026; see common description at top
1027;
1028; EXIT return to VM client
1029;
1030EmLoadal3 proc near
1031
1032 test ES:[PrefixFlag],P0F_FLAG
1033 jz Not_Loadall
1034 jmp EM386ll ; Y: emulate 386 loadall
1035
1036EmLoadal3 endp
1037
1038;******************************************************************************
1039; EmCLTS - emulate the CLTS instruction
1040;
1041; ENTRY: 386 Protected Mode
1042; EBP,EBX,ESI pushed on stack
1043; VM1_GSEL = VM client's stack segment
1044; VM2_GSEL = VM client's code segment
1045; DS:SI -> faulting opcode = nn (DS = VM2_GSEL)
1046; EXIT: via IRET to VM client
1047; USED:
1048; STACK: n/a
1049;------------------------------------------------------------------------------
1050EmCLTS proc near
1051
1052 test ES:[PrefixFlag],P0F_FLAG
1053 jz Not_CLTS
1054 clts ; go ahead and CLTS
1055 inc si ; inc VM CS:IP past command
1056 mov [bp.VTFOE+VMTF_EIP], si ; we emulate
1057 jmp EmExit ; and leave
1058
1059Not_CLTS:
1060 jmp BadVmTrap
1061
1062EmCLTS endp
1063
1064;******************************************************************************
1065; EmProtIns - emulate the protection control instructions
1066; Currently this throws LIDT and LGDT to the error handler and only emulates
1067; LMSW
1068; NOTE: The Stack configuration is critical!!! If it is changed, the
1069; offsets to the register images must be updated accordingly.
1070;
1071;
1072; ENTRY: 386 Protected Mode
1073; EBP,EBX,ESI pushed on stack
1074; VM1_GSEL = VM client's stack segment
1075; VM2_GSEL = VM client's code segment
1076; DS:SI -> faulting opcode = nn (DS = VM2_GSEL)
1077; EXIT: via IRET to VM client
1078; bp.VTFOE+VMTF_EIP points beyond offender to next client instruction
1079; VM2_GSEL, DS, and SI may be modified at exit, this should not be a
1080; problem for the IRET
1081; USED:
1082; STACK: n/a
1083;------------------------------------------------------------------------------
1084EmProtIns proc near
1085
1086 test ES:[PrefixFlag],P0F_FLAG
1087 jnz EmPI1
1088 jmp Not_ProtIns1
1089EmPI1:
1090 push dx
1091 push ax
1092 push es
1093 mov dx, ES:[PrefixFlag]
1094 mov bx,VDMCA_GSEL ; Load CODE (writeable) alias
1095 mov es, bx
1096 assume es:_TEXT
1097 inc si ; set si past the opcode
1098 mov bl,[si] ; BL = modR/M
1099 mov bh, bl ; BH = modR/M
1100 and bl, 38h
1101 cmp bl, 30h
1102 je EmLMSW ; Emulate LMSW
1103 cmp bl, 18h
1104 jne LGDTerr ; VM guy not allowed to LGDT
1105 mov bx, ErrLIDT
1106 jmp ExitPIer ; VM guy not allowed to LIDT
1107LGDTerr:
1108 mov bx, ErrLGDT
1109 jmp ExitPIer
1110EmLMSW:
1111 inc si ; set SI past the modR/M
1112 mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI
1113 mov bl, bh ; BL = modR/M
1114 cmp bl, 0C0h ; is MSW being loaded from a register?
1115 jb MoveData ; N: do a move from the VM's memory
1116 jmp MoveReg ; Y: go do a register move
1117
1118MoveData:
1119; Because of all the possible addressing modes this is pretty nasty. Like
1120; MoveReg, it is complicated by the requirement to not clear the PE bit.
1121; The general approach is to find the client's data value, put it in AX,
1122; set the PE bit in AX, then load the MSW from AX. To keep from having
1123; to know about all the modR/M combinations, we yank the client's possible
1124; offset from his code, and put his slightly modified modR/M byte in our
1125; home-made MOV AX, MemData instruction.
1126
1127; If there is a data offset, yank it from the VM instruction and put it
1128; in our instruction.
1129
1130 and bl, 0C7h ; Force AX to be the MOV destination
1131 mov byte ptr es:[LMSWmod],bl
1132 mov ax, 09090h
1133 mov word ptr es:[LMSWoff],ax ; initialize offset to NOPS
1134 cmp bl, 06h ; special case for DS:d16
1135 je load16off
1136 and bl, 0C0h
1137 cmp bl, 040h
1138 je load8off
1139 cmp bl, 080h
1140 jne BldDesc ; No data offset, so go build desc
1141Load16off:
1142 mov ax,[si] ; AX = 16 bit offset
1143 mov word ptr es:[LMSWoff],ax
1144 add si, 2
1145 mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI
1146 jmp short BldDesc
1147Load8off:
1148 mov al,[si] ; AL = 8 bit offset
1149 mov byte ptr es:[LMSWoff],al
1150 inc si
1151 mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI
1152
1153BldDesc:
1154; Build a descriptor to the client's data segment
1155
1156 mov bl, bh
1157 mov ax, [bp.VTFOE+VMTF_DS] ; Assume DS is the data segment
1158
1159; Check for segment override
1160 and dx, 00FCh ; strip all but segment overrides
1161 cmp dx, CS_FLAG
1162 jl GetmodBase ; no override, check base
1163 je CS_data
1164 cmp dx, ES_FLAG
1165 je ES_data
1166 jl GetSel ; ds is override
1167 cmp dx, FS_FLAG
1168 jl SS_data
1169 je FS_data
1170GS_data:
1171 mov ax, [bp.VTFOE+VMTF_GS] ; GS is the data segment
1172 jmp short GetSel
1173FS_data:
1174 mov ax, [bp.VTFOE+VMTF_FS] ; FS is the data segment
1175 jmp short GetSel
1176SS_data:
1177 mov ax, VM1_GSEL
1178 mov ds, ax
1179 jmp short RestoreRegs
1180CS_data:
1181 mov ax, VM2_GSEL
1182 mov ds, ax
1183 jmp short RestoreRegs
1184ES_data:
1185 mov ax, [bp.VTFOE+VMTF_ES] ; ES is the data segment
1186 jmp short GetSel
1187
1188GetmodBase:
1189; We have no Segment override, so we need to look at the modR/M byte to
1190; see whether or not the data index/offset is based on DS (assumed) or SS
1191 and bl, 0C7h ; clear instruction bits
1192 cmp bl, 46h
1193 je SS_Data ; EA = SS:[BP+d8]
1194 and bl, 7
1195 cmp bl, 2
1196 je SS_Data ; EA = SS:[BP+SI+?]
1197 cmp bl, 3
1198 je SS_Data ; EA = SS:[BP+DI+?]
1199
1200GetSel:
1201; Build a selector (VM2_GSEL) to client's data. VM2_GSEL is already set
1202; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base.
1203; The Descriptor base VM segment value is in AX
1204 push es
1205 push bx
1206 mov bx,GDTD_GSEL ; get GDT data alias
1207 mov es,bx ; DS -> GDT
1208 mov bx, ax ; copy the VM data segment value
1209 shl ax,4 ; BX = low 16 bits of base
1210 mov es:[VM2_GSEL+2],ax ; place in descriptor
1211 shr bx,4 ; BH = high 8 bits of base
1212 mov es:[VM2_GSEL+4],bh ; place in descriptor
1213 mov ax, VM2_GSEL
1214 mov ds, ax
1215 pop bx
1216 pop es
1217
1218RestoreRegs:
1219; Since BX, SI, DI, and BP can all be used to form an effective address we
1220; blindly restore BX, SI, and BP from the stack so that we don't
1221; have to know what the instruction is using for its effective address.
1222; DI does not need to be restored, because it should still be the client's
1223
1224 push bp
1225 mov bp, sp
1226
1227; Now the Stack had better look like PROT_INS_FRAME. (vm386.inc)
1228 mov si, [bp.PIF_ESI]
1229 mov bx, [bp.PIF_EBX]
1230 mov bp, [bp.PIF_EBP]
1231
1232; Move the VM data operand to AX
1233 db 3Eh ; ds overide (for bp & di)
1234 db 8Bh ; MOV opcode
1235LMSWmod db 00h ; modR/M
1236LMSWoff db 90h, 90h ; possible offset (NOPS otherwise)
1237
1238 jmp ExLMSW ; Finally... go do the LMSW
1239
1240MoveReg:
1241; Here we have a LMSW from one of the general registers. This is pretty
1242; ugly because many of the possible registers the client might have used
1243; are currently saved on the stack. It is also complicated by the
1244; requirement to not clear the PE bit. The general approach is to find
1245; the client's register value/image, put it in AX, set the PE bit in AX,
1246; then load the MSW from AX. To keep from having to know all the modR/M
1247; combinations, we again use a slightly modified client's modR/M byte in
1248; our home-made MOV AX, RegData instruction.
1249
1250 push bp
1251 mov bp, sp
1252
1253; Now the Stack had better look like PROT_INS_FRAME. (vm386.inc)
1254
1255 and bh, 07h ; If Src is AX, it hasn't been changed
1256 jz ExLMSW ; so just go do the the LMSW
1257CkSrcBX: ; otherwise, find it and move it to AX
1258 cmp bh, 3
1259 jne CkSrcBP
1260 mov ax, [bp.PIF_EBX] ; src was BX, get from stack
1261 jmp short ExLMSW
1262CkSrcBP:
1263 cmp bh, 5
1264 jne CkSrcSI
1265 mov ax, [bp.PIF_EBP] ; src was BP, get from stack
1266 jmp short ExLMSW
1267CkSrcSI:
1268 cmp bh, 6
1269 jne CkSrcDX
1270 mov ax, [bp.PIF_ESI] ; src was SI, get from stack
1271 jmp short ExLMSW
1272CkSrcDX:
1273 cmp bh, 2
1274 jne CkSrcSP
1275 mov ax, [bp.PIF_DX] ; src was DX, get from stack
1276 jmp short ExLMSW
1277CkSrcSP:
1278 cmp bh, 4
1279 jne GetReg
1280 mov ax, [bp.PIF_VMESP] ; src was SP, get from stack
1281 jmp short ExLMSW
1282GetReg:
1283 or bh, 0C0h ; set register to register move bits
1284 mov es:[Lmod], bh ; setup move from client's src register
1285 jmp short GetRn ; clear prefetch so that bh gets there
1286GetRn:
1287; Execute MOV AX, Rn
1288 db 08Bh
1289Lmod db 0C0h
1290
1291; Finally Execute the LMSW
1292ExLMSW:
1293
1294; At this point we could check for the PE bit and notify the user that
1295; he must switch to real mode... but because an old app might do a SMSW,
1296; which copies the PE bit (?!!), then set a bit in that image and do a LMSW,
1297; (not caring about the PE bit), we just let it go... under the assumption
1298; that if he really were trying to enter Protected mode, he would have
1299; failed trying to LIDT and LGDT.
1300
1301; test ax, 0001h ; Is client trying to set PE bit
1302; jnz ExitPIer ; Y: jump to error
1303 or ax, 0001h ; N: we want to stay in Prot mode
1304 LMSW ax ; So we must set it (use BTS above)
1305
1306 pop bp
1307 pop es
1308 assume es:DGROUP
1309 pop ax
1310 pop dx
1311 jmp EmExit ; *** RETURN *** to VM client
1312
1313ExitPIer:
1314 pop es
1315 assume es:DGROUP
1316 mov ax, PrivErr ; privileged error
1317 call ErrHndlr ; If the user want's to continue
1318 pop ax
1319 pop dx
1320 jmp JumpReal ; we return and go unwind the stack
1321Not_ProtIns1:
1322 jmp BadVmTrap
1323
1324EmProtIns endp
1325
1326;******************************************************************************
1327; EmMovCDTR - emulate the - MOV Rn, C/D/TRn & MOV C/D/TRn, Rn - instructions
1328; This is done by copying the MOV instruction from the VM to our
1329; code and then executing it. If CR0 is being stored, the PE
1330; bit is masked clear before completing the instruction. Execution speed
1331; should not be critical for these instructions, so I have lumped them
1332; all together to save memory that can be better used for more time
1333; critical emulations.
1334; NOTE: The Stack configuration is critical!!! If it is changed, the
1335; offsets to the register images must be updated accordingly.
1336;
1337; Also NOTE: The TR register opcodes have been removed from the legal 0F
1338; prefix list, (P0F_OpTab(x)), and the EmMovCDTR address removed from their
1339; opcode table ,(OpTable), vectors, so that they don't come here anymore.
1340;
1341; ENTRY: 386 Protected Mode
1342; EBP,EBX,ESI pushed on stack
1343; VM1_GSEL = VM client's stack segment
1344; VM2_GSEL = VM client's code segment
1345; DS:SI -> faulting opcode = nn (DS = VM2_GSEL)
1346; EXIT: via IRET to VM client
1347; bp.VTFOE+VMTF_EIP points beyond offender to next client instruction
1348; USED:
1349; STACK: n/a
1350;------------------------------------------------------------------------------
1351EmMovCDTR proc near
1352
1353 test ES:[PrefixFlag],P0F_FLAG
1354 jnz MovCDTR1
1355 jmp Not_MovCDTR ; Didn't come from a 0F prefix
1356MovCDTR1:
1357 PUSH_EAX
1358 push es
1359 mov bx,VDMCA_GSEL ; Load CODE (writeable) alias
1360 mov es, bx
1361 assume es:_TEXT
1362 mov bl,[si] ; BL = opcode
1363 mov es:[CDTRopc], bl
1364 inc si ; set SI past the opcode
1365 mov bl,[si] ; BL = modR/M
1366 mov bh, bl ; Copy modR/M
1367 and bl, 0F8h ; For control, we reroute move thru AX
1368 mov es:[CDTRmod], bl
1369 inc si ; set SI past the modR/M
1370 mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI
1371
1372 push bp
1373 mov bp, sp
1374
1375; Now the Stack had better look like MOV_CDTR_FRAME. (vm386.inc)
1376
1377 mov bl, es:[CDTRopc] ; load opcode
1378 cmp bl, 024h ; Check TRn load/store
1379 jb NotTRErr ; N: continue
1380 mov bx, ErrMovTR ; Y: go flag error
1381 jmp CTRErr
1382
1383NotTRErr:
1384 and bh, 7 ; strip all but src reg bits
1385 cmp bh, 0
1386 je ExCDTR ; reg is AX, so just do move
1387
1388 cmp bl, 020h ; Check CRn store
1389 je ExCDTR1 ; Y: go do it
1390 cmp bl, 021h ; Check DRn store
1391 je ExCDTR1 ; Y: go do it
1392
1393ChkSrcBX:
1394 cmp bh, 3
1395 jne ChkSrcBP
1396 OP32
1397 mov ax, [bp.MCF_EBX] ; mov EBX from stack
1398 jmp short ExCDTR
1399ChkSrcBP:
1400 cmp bh, 5
1401 jne ChkSrcSI
1402 OP32
1403 mov ax, [bp.MCF_EBP] ; mov EBP from stack
1404 jmp short ExCDTR
1405ChkSrcSI:
1406 cmp bh, 6
1407 jne ChkSrcSP
1408 OP32
1409 mov ax, [bp.MCF_ESI] ; mov ESI from stack
1410 jmp short ExCDTR
1411ChkSrcSP:
1412 cmp bh, 4
1413 jne GetFmReg
1414 OP32
1415 mov ax, [bp.MCF_VMESP] ; mov ESP from stack
1416 jmp short ExCDTR
1417GetFmReg:
1418 or bh, 0C0h ; set register to register move bits
1419 mov es:[CDTRreg], bh ; setup move from client's src register
1420 jmp short GetERn ; clear prefetch so that bh gets there
1421GetERn:
1422; Execute MOV EAX, ERn
1423 OP32
1424 db 08Bh
1425CDTRreg db 0C0h
1426
1427ExCDTR:
1428 cmp bl, 022h ; Check CRn load
1429 jne FltrDRL3 ; N: destination not CRn
1430 cmp byte ptr es:[CDTRmod], 0C0h ; Check for CR0 load
1431 je CR0FltrL ; Y: filter it
1432 mov bx, ErrMovCR
1433 jmp CTRErr ; N: go tell user he did a NoNo
1434FltrDRL3:
1435 cmp byte ptr es:[CDTRmod], 0C3h ; Check for DR0-3 load
1436 ja FltrGDbit ; N: continue
1437 call MapLinear ; Y: convert address to our paging
1438 jmp short ExCDTR1 ; linear map, then continue
1439FltrGDbit:
1440 cmp byte ptr es:[CDTRmod], 0C7h ; Check for DR7 load
1441 jne ExCDTR1 ; N: continue
1442 and ax, 0DFFFh ; Y: don't let client set the GD bit
1443 jmp short ExCDTR1 ; continue
1444
1445; For the reason below, we don't bug the user about setting the PE bit
1446; through LMSW. To be consistent, and because the client would die
1447; in his attmept to LGDT or Mov CR3,Reg before this, we let him go here
1448; also.
1449; LMSW Reason:
1450; At this point we could check for the PE bit and notify the user that
1451; he must switch to real mode... but because an old app might do a SMSW,
1452; which copies the PE bit (?!!), then set a bit in that image and do a LMSW,
1453; (not caring about the PE bit), we just let it go... under the assumption
1454; that if he really were trying to enter Protected mode, he would have
1455; failed trying to LIDT and LGDT.
1456
1457CR0FltrL:
1458; OP32
1459; test AX, 0FFFEh ; Is Client trying to set the
1460; dw 7FFFh ; PE bit or the PG bit?
1461; jnz ExitxCRer ; Y: go tell him he can't
1462 OP32
1463 or AX, 0001h ; set PE bit
1464 dw 8000h ; and PG bit if they weren't
1465ExCDTR1:
1466; Execute MOV CDTRn, EAX (Finally!)
1467 db 0Fh
1468CDTRopc db 020h
1469CDTRmod db 0C0h
1470
1471; The special register move has now been executed, but we altered it to
1472; use AX. If the move was a load, we are done. If it was a store to one of
1473; the registers on the stack, we need to stuff the register's stack image,
1474; otherwise we need to move AX to the proper register.
1475
1476 cmp bl, 022h ; Check CRn load
1477 je Exit_MovCDTR ; Y: we're done
1478 cmp bl, 023h ; Check DRn load
1479 je Exit_MovCDTR ; Y: we're done
1480 cmp bl, 021h ; Check DRn store
1481 je FltrDRS3 ; Y: go filter it
1482 jmp short NotDRS3
1483FltrDRS3:
1484 cmp byte ptr es:[CDTRmod], 0C3h ; Check for DR0-3 load
1485 ja NotDRS3 ; N: continue
1486 call UnMapLinear ; Y: convert address from our paging
1487 ; linear map, then continue
1488NotDRS3:
1489 cmp bl, 020h ; Check CRn store
1490 jne ChkDstBX ; N: source not CRn
1491 cmp byte ptr es:[CDTRmod], 0C0h ; Check for CR0 store
1492 je CR0FltrS ; Y: filter it
1493 mov bx, ErrMovCR
1494 jmp short CTRErr ; N: go tell user he did a NoNo
1495
1496; Because SMSW shows the PE bit, we let it go through here also
1497CR0FltrS:
1498 OP32
1499 and AX, 0FFFFh ; Y: clear
1500 dw 7FFFh ; PG bit if it was set
1501ChkDstBX:
1502 cmp bh, 3
1503 jne ChkDstBP
1504 OP32
1505 mov [bp.MCF_EBX], ax ; mov EBX to stack
1506 jmp short Exit_MovCDTR
1507ChkDstBP:
1508 cmp bh, 5
1509 jne ChkDstSI
1510 OP32
1511 mov [bp.MCF_EBP], ax ; mov EBP to stack
1512 jmp short Exit_MovCDTR
1513ChkDstSI:
1514 cmp bh, 6
1515 jne ChkDstAX
1516 OP32
1517 mov [bp.MCF_ESI], ax ; mov ESI to stack
1518 jmp short Exit_MovCDTR
1519ChkDstAX:
1520 cmp bh, 0
1521 jne ChkDstSP
1522 OP32
1523 mov [bp.MCF_EAX], ax ; mov EAX to stack
1524 jmp short Exit_MovCDTR ; at exit
1525ChkDstSP:
1526 cmp bh, 4
1527 jne PutInReg
1528 OP32
1529 mov [bp.MCF_VMESP], ax ; mov ESP to stack
1530 jmp short Exit_MovCDTR ; at exit
1531PutInReg:
1532; Execute MOV ERn, EAX
1533 or bh, 0C0h ; set register to register move bits
1534 mov es:[regCDTR], bh ; setup load to client's dest register
1535 jmp short PutERn ; clear prefetch so that bh gets there
1536PutERn:
1537 db 66h
1538 db 089h
1539regCDTR db 0C0h
1540
1541
1542Exit_MovCDTR:
1543 pop bp
1544 pop es
1545 assume es:DGROUP
1546 POP_EAX
1547 jmp EmExit ; *** RETURN *** to VM client
1548CTRErr:
1549 mov ax, PrivErr
1550 pop bp
1551 sub [bp.VTFOE+VMTF_EIP],3 ; VM CS:IP = faulting instruction
1552 pop es
1553 assume es:DGROUP
1554 call ErrHndlr ; If we return here, the user wants to
1555 POP_EAX ; continue in real mode... so go unwind
1556 jmp JumpReal ; the stack and let him continue
1557Not_MovCDTR:
1558 jmp BadVmTrap
1559
1560EmMovCDTR endp
1561
1562;******************************************************************************
1563;*** EmLOCK - Emulate LOCK prefix
1564;
1565; This routine is entered if a faulting instruction
1566; is a LOCK prefix.
1567;
1568; ENTRY 386 PROTECTED MODE
1569; see common description at top
1570;
1571; EXIT xfer on to handler for next opcode
1572;
1573EmLOCK proc near
1574
1575; 6/15 - Probably should jump to VmInsHandle rather than EmExit to handle a
1576; a lock prefix on some other offending instruction. In that case you would
1577; have:
1578;; or ES:[PrefixFlag],LOCK_FLAG ; set appropriate flag
1579;; inc si ; inc VM CS:IP past prefix
1580;; jmp VmInsHandle ; and go process offender
1581; rather than:
1582 inc si ; set IP past the
1583 mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate
1584 jmp EmExit ; and leave
1585
1586EmLOCK endp
1587
1588;******************************************************************************
1589;*** EmREPNE - handle REPNE prefix
1590;
1591; We come here if the trapping instruction has
1592; a REPNE prefix. We just pass it on to the handler
1593; for the next opcode.
1594;
1595; ENTRY 386 PROTECTED MODE
1596; see common description at top
1597;
1598; EXIT IRET back to VM program
1599;
1600EmREPNE proc near
1601
1602 or ES:[PrefixFlag],REPNE_FLAG ; set appropriate flag
1603 inc si ; inc VM CS:IP past prefix
1604 jmp VmInsHandle ; handle next part of instr
1605
1606EmREPNE endp
1607
1608;*** EmREP - handle REP prefix
1609;
1610; We come here if the trapping instruction has
1611; a REP or REPE prefix. We just pass it on to the handler
1612; for the next opcode.
1613;
1614; ENTRY 386 PROTECTED MODE
1615; see common description at top
1616;
1617; EXIT IRET back to VM program
1618;
1619EmREP proc near
1620
1621 or ES:[PrefixFlag],REP_FLAG ; set appropriate flag
1622 inc si ; inc VM CS:IP past prefix
1623 jmp VmInsHandle ; handle next part of instr
1624
1625EmREP endp
1626
1627;******************************************************************************
1628;*** Prefix_0F - handle 0F overrides
1629;
1630; This routine is entered if an instruction begins with a 0F prefix.
1631; It checks the current opcode against a table of valid 0F-opcodes,
1632; and if the opcode is valid, it indexes back into OpTable to jump
1633; to the proper opcode handler.
1634; (NOTE: This scheme works fine as long as the valid 0F-opcodes
1635; continue to have low values allowing this P0F_OpTabx to stay
1636; relatively small. If this changes, we probably should go back
1637; to using the P0F_OpTab scheme.)
1638;
1639; ENTRY: 386 Protected Mode
1640; EBP,EBX,ESI pushed on stack
1641; VM1_GSEL = VM client's stack segment
1642; VM2_GSEL = VM client's code segment
1643; DS:SI -> faulting prefix = nn (DS = VM2_GSEL)
1644; EXIT xfer directly to handler for next opcode
1645;
1646;***
1647P0F_Invalid equ 0FFh ; OpTable vector offset to BadVmTrap
1648
1649P0F_OpTabx label byte
1650 db 00h ; 00h - LLDT, LTR, SLDT, STR, VERR, VERW
1651 db 02h ; 01h - LIDT, LGDT, LMSW
1652 db 04h ; 02h - LAR
1653 db 06h ; 03h - LSL
1654 db P0F_Invalid ; 04h - BadVmTrap
1655 db 0Ah ; 05h - 286 Loadall
1656 db 0Ch ; 06h - CLTS
1657 db 0Eh ; 07h - 386 Loadall
1658 db P0F_Invalid ; 08h - BadVmTrap
1659 db P0F_Invalid ; 09h - BadVmTrap
1660 db P0F_Invalid ; 0Ah - BadVmTrap
1661 db P0F_Invalid ; 0Bh - BadVmTrap
1662 db P0F_Invalid ; 0Ch - BadVmTrap
1663 db P0F_Invalid ; 0Dh - BadVmTrap
1664 db P0F_Invalid ; 0Eh - BadVmTrap
1665 db P0F_Invalid ; 0Fh - BadVmTrap
1666 db P0F_Invalid ; 10h - BadVmTrap
1667 db P0F_Invalid ; 11h - BadVmTrap
1668 db P0F_Invalid ; 12h - BadVmTrap
1669 db P0F_Invalid ; 13h - BadVmTrap
1670 db P0F_Invalid ; 14h - BadVmTrap
1671 db P0F_Invalid ; 15h - BadVmTrap
1672 db P0F_Invalid ; 16h - BadVmTrap
1673 db P0F_Invalid ; 17h - BadVmTrap
1674 db P0F_Invalid ; 18h - BadVmTrap
1675 db P0F_Invalid ; 19h - BadVmTrap
1676 db P0F_Invalid ; 1Ah - BadVmTrap
1677 db P0F_Invalid ; 1Bh - BadVmTrap
1678 db P0F_Invalid ; 1Ch - BadVmTrap
1679 db P0F_Invalid ; 1Dh - BadVmTrap
1680 db P0F_Invalid ; 1Eh - BadVmTrap
1681 db P0F_Invalid ; 1Fh - BadVmTrap
1682 db 40h ; 20h - CR moves
1683 db 42h ; 21h - DR moves
1684 db 44h ; 22h - CR moves
1685 db 46h ; 23h - DR moves
1686 db 48h ; 24h - TR moves
1687 db P0F_Invalid ; 25h - BadVmTrap
1688 db 4Ch ; 26h - TR moves
1689P0F_OpTabx_Size equ $-P0F_OpTabx
1690
1691;***
1692Prefix_0F proc near
1693 inc si ; inc DS:SI past prefix
1694 mov bl,[si] ; BL = opcode
1695 cmp bl, P0F_OpTabx_Size
1696 jae Bad_0F
1697 mov bh,0 ; BX = opcode
1698 mov bl, cs:P0F_OpTabx[bx]
1699 cmp bl, P0F_Invalid
1700 je Bad_0F
1701 or es:[PrefixFlag],P0F_FLAG ; set appropriate flag
1702 jmp cs:OpTable[bx] ; enter instr emulation routine
1703
1704Bad_0F:
1705 jmp BadVmTrap
1706
1707Prefix_0F endp
1708
1709;******************************************************************************
1710;*** CSOverride - handle CS overrides
1711;
1712; This routine is entered if a faulting instruction
1713; has a CS override.
1714;
1715; ENTRY 386 PROTECTED MODE
1716; see common description at top
1717;
1718; EXIT xfer on to handler for next opcode
1719;
1720CSOverride proc near
1721
1722 or ES:[PrefixFlag],CS_FLAG ; set appropriate flag
1723 inc si ; inc VM CS:IP past prefix
1724 jmp VmInsHandle ; handle next part of instr
1725
1726CSOverride endp
1727
1728;******************************************************************************
1729;*** DSOverride - handle DS overrides
1730;
1731; This routine is entered if a faulting instruction
1732; has a DS override.
1733;
1734; ENTRY 386 PROTECTED MODE
1735; see common description at top
1736;
1737; EXIT xfer on to handler for next opcode
1738;
1739DSOverride proc near
1740
1741 or ES:[PrefixFlag],DS_FLAG ; set appropriate flag
1742 inc si ; inc VM CS:IP past prefix
1743 jmp VmInsHandle ; handle next part of instr
1744
1745DSOverride endp
1746
1747;******************************************************************************
1748;*** ESOverride - handle ES overrides
1749;
1750; This routine is entered if a faulting instruction
1751; has a ES override or a MOV TRn, Rn opcode
1752;
1753; ENTRY 386 PROTECTED MODE
1754; see common description at top
1755;
1756; EXIT xfer on to handler for next opcode
1757;
1758
1759ESOverride proc near
1760
1761 test ES:[PrefixFlag],P0F_FLAG ; only for TR emulation
1762 jz ESO1 ; only for TR emulation
1763 jmp EmMovCDTR ; only for TR emulation
1764ESO1:
1765 or ES:[PrefixFlag],ES_FLAG ; set appropriate flag
1766 inc si ; inc VM CS:IP past prefix
1767 jmp VmInsHandle ; handle next part of instr
1768
1769ESOverride endp
1770
1771;******************************************************************************
1772;*** SSOverride - handle SS overrides
1773;
1774; This routine is entered if a faulting instruction
1775; has a SS override.
1776;
1777; ENTRY 386 PROTECTED MODE
1778; see common description at top
1779;
1780; EXIT xfer on to handler for next opcode
1781;
1782
1783SSOverride proc near
1784
1785 or ES:[PrefixFlag],SS_FLAG ; set appropriate flag
1786;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix
1787 inc si ; inc VM CS:IP past prefix
1788 jmp VmInsHandle ; handle next part of instr
1789
1790SSOverride endp
1791
1792;******************************************************************************
1793;*** FSOverride - handle FS overrides
1794;
1795; This routine is entered if a faulting instruction
1796; has a FS override.
1797;
1798; ENTRY 386 PROTECTED MODE
1799; see common description at top
1800;
1801; EXIT xfer on to handler for next opcode
1802;
1803
1804FSOverride proc near
1805
1806 or ES:[PrefixFlag],FS_FLAG ; set appropriate flag
1807;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix
1808 inc si ; inc VM CS:IP past prefix
1809 jmp VmInsHandle ; handle next part of instr
1810
1811FSOverride endp
1812
1813;******************************************************************************
1814;*** GSOverride - handle GS overrides
1815;
1816; This routine is entered if a faulting instruction
1817; has a GS override.
1818;
1819; ENTRY 386 PROTECTED MODE
1820; see common description at top
1821;
1822; EXIT xfer on to handler for next opcode
1823;
1824
1825GSOverride proc near
1826
1827 or ES:[PrefixFlag],GS_FLAG ; set appropriate flag
1828;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix
1829 inc si ; inc VM CS:IP past prefix
1830 jmp VmInsHandle ; handle next part of instr
1831
1832GSOverride endp
1833
1834;******************************************************************************
1835;*** EmINSB - emulate IN byte string
1836;
1837; This routine emulates the IN byte string instruction
1838; *** this routine emulates REP instructions entirely ***
1839; *** within protected mode. This effectively masks out ***
1840; *** interupts between bytes in the operation, even ***
1841; *** if the VM code had interrupts on. ***
1842;
1843; ENTRY 386 PROTECTED MODE
1844; see common description at top
1845;
1846; EXIT IRET back to VM program
1847;
1848; USES ES,BX,DI
1849;
1850
1851EmINSB proc near
1852;
1853;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate
1854 inc si ; set IP past the
1855 mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate
1856;
1857;
1858; Build a selector (VM1_GSEL) to client's ES segment. VM1_GSEL is already set
1859; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base.
1860;
1861 mov bx,GDTD_GSEL
1862 mov ds,bx ; DS = GDT selector
1863 mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (segment form)
1864 shl bx,4 ; BX = low 16 bits of base
1865 mov ds:[VM1_GSEL+2],bx ; place in descriptor
1866 mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (again)
1867 shr bx,4 ; BH = high 8 bits of base
1868 mov ds:[VM1_GSEL+4],bh ; place in descriptor
1869 mov bx,VM1_GSEL
1870 test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ?
1871 mov es,bx ; ES = VM ES
1872 jnz EINSB_loop ; Y: go do rep instruction
1873 insb ; N: do single instruction
1874 jmp EINSB_exit ; and leave
1875EINSB_loop:
1876 cld ; assume cld
1877 mov bx,DF_FLAG
1878 test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD?
1879 jz EINSB_rep ; Y: go ahead
1880 std ; N: set it
1881EINSB_rep:
1882 rep insb ; rep version
1883
1884EINSB_Exit: ;
1885 jmp EmExit ; *** RETURN *** to VM client
1886;
1887EmINSB endp
1888
1889
1890;******************************************************************************
1891;*** EmINSW - emulate IN word string
1892;
1893; This routine emulates the IN word string instruction
1894; *** this routine emulates REP instructions entirely ***
1895; *** within protected mode. This effectively masks out ***
1896; *** interupts between bytes in the operation, even ***
1897; *** if the VM code had interrupts on. ***
1898;
1899; ENTRY 386 PROTECTED MODE
1900; see common description at top
1901;
1902; EXIT IRET back to VM program
1903;
1904; USES ES,BX,DI
1905;
1906
1907EmINSW proc near
1908;
1909;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate
1910 inc si ; set IP past the
1911 mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate
1912;
1913;
1914;
1915; Build a selector (VM1_GSEL) to client's ES segment. VM1_GSEL is already set
1916; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base.
1917;
1918 mov bx,GDTD_GSEL
1919 mov ds,bx ; DS = GDT selector
1920 mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (segment form)
1921 shl bx,4 ; BX = low 16 bits of base
1922 mov ds:[VM1_GSEL+2],bx ; place in descriptor
1923 mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (again)
1924 shr bx,4 ; BH = high 8 bits of base
1925 mov ds:[VM1_GSEL+4],bh ; place in descriptor
1926 mov bx,VM1_GSEL
1927 test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ?
1928 mov es,bx ; ES = VM ES
1929 jnz EINSW_loop ; Y: go do rep instruction
1930 insw ; N: do single instruction
1931 jmp EINSW_exit ; and leave
1932EINSW_loop:
1933 cld ; assume cld
1934 mov bx,DF_FLAG
1935 test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD?
1936 jz EINSW_rep ; Y: go ahead
1937 std ; N: set it
1938EINSW_rep:
1939 rep insw ; rep version
1940
1941EINSW_Exit: ;
1942 jmp EmExit ; *** RETURN *** to VM client
1943;
1944EmINSW endp
1945
1946
1947;******************************************************************************
1948;*** EmOUTSB - emulate OUT byte string
1949;
1950; This routine emulates the OUT byte string instruction
1951; *** this routine emulates REP instructions entirely ***
1952; *** within protected mode. This effectively masks out ***
1953; *** interupts between bytes in the operation, even ***
1954; *** if the VM code had interrupts on. ***
1955;
1956; ENTRY 386 PROTECTED MODE
1957; see common description at top
1958;
1959; EXIT IRET back to VM program
1960;
1961; USES DS,BX,SI
1962;
1963
1964EmOUTSB proc near
1965;
1966;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate
1967 inc si ; set IP past the
1968 mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate
1969;
1970; restore SI
1971;
1972 pop si
1973 push si
1974;
1975; Build a selector (VM1_GSEL) to client's DS segment. VM1_GSEL is already set
1976; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base.
1977;
1978 mov bx,GDTD_GSEL
1979 mov ds,bx ; DS = GDT selector
1980 mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (segment form)
1981 shl bx,4 ; BX = low 16 bits of base
1982 mov ds:[VM1_GSEL+2],bx ; place in descriptor
1983 mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (again)
1984 shr bx,4 ; BH = high 8 bits of base
1985 mov ds:[VM1_GSEL+4],bh ; place in descriptor
1986 mov bx,VM1_GSEL
1987 mov ds,bx ; DS = VM DS
1988
1989 test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ?
1990 jnz EOUTSB_loop ; Y: go do rep instruction
1991 outsb ; N: do single instruction
1992 jmp EOUTSB_exit ; and leave
1993EOUTSB_loop:
1994 cld ; assume cld
1995 mov bx,DF_FLAG
1996 test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD?
1997 jz EOUTSB_rep ; Y: go ahead
1998 std ; N: set it
1999EOUTSB_rep:
2000 rep outsb ; rep version
2001
2002EOUTSB_Exit: ;
2003 jmp EmExit ; *** RETURN *** to VM client
2004;
2005EmOUTSB endp
2006
2007
2008;******************************************************************************
2009;*** EmOUTSW - emulate OUT word string
2010;
2011; This routine emulates the OUT word string instruction
2012; *** this routine emulates REP instructions entirely ***
2013; *** within protected mode. This effectively masks out ***
2014; *** interupts between bytes in the operation, even ***
2015; *** if the VM code had interrupts on. ***
2016;
2017; ENTRY 386 PROTECTED MODE
2018; see common description at top
2019;
2020; EXIT IRET back to VM program
2021;
2022; USES DS,BX,SI
2023;
2024
2025EmOUTSW proc near
2026;
2027;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate
2028 inc si ; set IP past the
2029 mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate
2030;
2031; restore SI
2032;
2033 pop si
2034 push si
2035;
2036;
2037; Build a selector (VM1_GSEL) to client's DS segment. VM1_GSEL is already set
2038; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base.
2039;
2040 mov bx,GDTD_GSEL
2041 mov ds,bx ; DS = GDT selector
2042 mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (segment form)
2043 shl bx,4 ; BX = low 16 bits of base
2044 mov ds:[VM1_GSEL+2],bx ; place in descriptor
2045 mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (again)
2046 shr bx,4 ; BH = high 8 bits of base
2047 mov ds:[VM1_GSEL+4],bh ; place in descriptor
2048 mov bx,VM1_GSEL
2049 mov ds,bx ; DS = VM DS
2050
2051 test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ?
2052 jnz EOUTSW_loop ; Y: go do rep instruction
2053 outsw ; N: do single instruction
2054 jmp EOUTSW_exit ; and leave
2055EOUTSW_loop:
2056 cld ; assume cld
2057 mov bx,DF_FLAG
2058 test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD?
2059 jz EOUTSW_rep ; Y: go ahead
2060 std ; N: set it
2061EOUTSW_rep:
2062 rep outsw ; rep version
2063
2064EOUTSW_Exit: ;
2065 jmp EmExit ; *** RETURN *** to VM client
2066;
2067EmOUTSW endp
2068
2069;******************************************************************************
2070;*** EmMOVSW - emulate MOV word string
2071;
2072; This routine emulates the MOV word string instruction
2073; specifically to handle the RASH Rules (Jokes) emulation.
2074; For now, the only reason for doing this is to allow a bug
2075; in PC Week's benchmark tests to FAIL "properly" so that the test
2076; works. (Unbelievable!)
2077;
2078; NOTE: After testing, if the ROM properly emulates the RASH
2079; requirements, this routine should be reduced to the Reflect6
2080; function.
2081;
2082; ENTRY 386 PROTECTED MODE
2083; see common description at top
2084;
2085; EXIT IRET back to VM program
2086;
2087; USES DS,BX,SI
2088;
2089EmMOVSW proc near
2090 mov bx, sp
2091 cmp di, 0FFFFh ; Q:Does either Di
2092 je EmWRASH
2093 cmp ss:[bx.GPF_ESI], 0FFFFh ; or SI = FFFF?
2094 je EmWRASH ; Y:Assume RASH GPfault
2095Reflect6:
2096 mov es:[RefNum], 06h
2097RefToROM:
2098 POP_ESI ; N: clean up the stack,
2099 POP_EBX
2100 POP_EBP
2101 add sp,4 ; throw away error code,
2102 PUSH_EBP
2103 mov bp,sp ; reset BP to stack frame
2104 push es:[RefNum] ; push the trap number
2105 jmp hw_int ; and, Reflect to ROM
2106EmWRASH:
2107 test es:[PrefixFlag], REPS_FLAG ; Q:Is this a REP of REPNE?
2108 jz EMWCXok ; N: don't change CX
2109 inc cx
2110EMWCXok:
2111 mov ax, 2 ; assume up counter
2112 test [bp.VTFOE+VMTF_EFLAGS], DF_FLAG
2113 jz EMWUpdtSI
2114 not ax
2115EMWUpdtSI:
2116 mov si, ss:[bx.GPF_ESI]
2117 add ss:[bx.GPF_ESI], ax ; verify neg???
2118 cmp si, 0FFFFh ; Q:Did SI cause the GP fault
2119 jne EMWUpdtDI ; N:Go fixup DI and CX
2120 jmp short EMW_Exit ; Y:We're done
2121EMWUpdtDI:
2122 test es:[PrefixFlag], REPS_FLAG ; Q:Is this a REP of REPNE?
2123 jz EMWCXok2 ; N: don't change CX
2124 inc cx
2125EMWCXok2:
2126 add di, ax ; verify neg???
2127EMW_Exit:
2128 jmp EmExit ; *** RETURN *** to VM client
2129;
2130EmMOVSW endp
2131
2132_TEXT ends
2133
2134 end
2135
diff --git a/v4.0/src/MEMM/MEMM/VMTRAP.ASM b/v4.0/src/MEMM/MEMM/VMTRAP.ASM
new file mode 100644
index 0000000..095ebef
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/VMTRAP.ASM
@@ -0,0 +1,791 @@
1
2
3page 58,132
4;******************************************************************************
5 title VMTRAP - 386 Virtual Mode interrupt handler routines
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: VMTRAP - 386 Virtual Mode interrupt handler routines
13;
14; Version: 0.02
15;
16; Date: January 26, 1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- ------------------------------------------------------
26; 01/26/86 Original
27; 02/05/86 A- Added int 15h trap to move block function.
28; 05/12/86 A Cleanup and segment reorganization
29; 06/19/86 0.01 Added emul_reflect entry point for preserving
30; IF and TF flags bits on reflections done by
31; instruction emulators.
32; 06/28/86 0.02 Name change from MEMM386 to MEMM
33; 07/20/88 Removed debugger codes (pc)
34;
35;******************************************************************************
36;
37; Functional Description:
38;
39; This module contains the interrupt and trap handlers for Virtual DOS.
40;
41; Note that a conscious decision has been made to attempt to field the
42; Master 8259 interrupts at the normal PC location (vectors 8 - F). The
43; main problem is that these overlap CPU exception vectors. While the
44; 8259 base vector address could be changed (there's lots of room in the
45; IDT, since we're fielding S/W INTs through GP 13), the primary reason
46; for not doing so is to avoid any potential trouble with an application
47; reprogramming the 8259. We don't know of any that do, and you could
48; trap them if they tried anyway.
49;
50; "to do:" marks potential holes/things to consider
51;
52;******************************************************************************
53.lfcond ; list false conditionals
54.386p
55 page
56;******************************************************************************
57; P U B L I C D E C L A R A T I O N S
58;******************************************************************************
59;
60 public VmTrap ; module label
61
62 public hw_int
63 public emul_reflect
64
65 public vm_trap00
66 public vm_trap01
67 public vm_trap02
68 public vm_trap03
69 public vm_trap04
70 public vm_trap05
71 public vm_trap06
72 public vm_trap07
73 public vm_trap08
74 public vm_trap09
75 public vm_trap0a
76 public vm_trap0b
77 public vm_trap0c
78 public vm_trap0d
79 public vm_trap0e
80 public vm_trap0f
81 public vm_trap10
82 public vm_trap50
83 public vm_trap51
84 public vm_trap52
85 public vm_trap53
86 public vm_trap54
87 public vm_trap55
88 public vm_trap56
89 public vm_trap57
90 public vm_trap70
91 public vm_trap71
92 public vm_trap72
93 public vm_trap73
94 public vm_trap74
95 public vm_trap75
96 public vm_trap76
97 public vm_trap77
98
99 page
100;******************************************************************************
101; E X T E R N A L R E F E R E N C E S
102;******************************************************************************
103;
104_TEXT segment
105 extrn VmFault:near ; V Mode GP fault handler (VMINST)
106 extrn ErrHndlr:near ; Error Handler (ERRHNDLR)
107 extrn DisableNMI:near ; Disable NMI for NMI trap handler
108_TEXT ends
109 page
110;******************************************************************************
111; I N C L U D E F I L E S
112;******************************************************************************
113;
114include VDMseg.inc
115include VDMsel.inc
116include vm386.inc
117include pic_def.equ
118include instr386.inc
119include oemdep.inc
120
121 page
122;******************************************************************************
123; L O C A L C O N S T A N T S
124;******************************************************************************
125;
126FALSE equ 0
127TRUE equ not FALSE
128
129ProcessExcep macro ExcepNum
130 mov bx, ExcepNum
131 mov ax, ExcpErr
132 jmp ErrHndlr
133endm
134;
135;******************************************************************************
136; S E G M E N T D E F I N I T I O N
137;******************************************************************************
138;
139ABS0 segment at 0000h
140ABS0 ends
141;
142;------------------------------------------------------------------------------
143_TEXT segment
144 assume cs:_TEXT, ds:NOTHING, es:NOTHING, ss:NOTHING
145VmTrap label byte
146;
147 db 'WCC'
148;
149 page
150;******************************************************************************
151; CPU: Divide error fault
152;
153; ENTRY: 386 Protected Mode via 386 Interrupt gate
154; No error code on stack
155; EXIT: to handler or debugger as appropriate
156; USED:
157; STACK:
158;------------------------------------------------------------------------------
159vm_trap00 proc near
160 PUSH_EBP
161 mov bp,sp
162 test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ?
163 jz vmt0_dexit ; N: exit to debugger
164 push 0000 ; Y: interrupt 00
165 jmp hw_int ; reflect it to virtual mode
166vmt0_dexit:
167 ProcessExcep ErrDIV
168vm_trap00 endp
169
170;******************************************************************************
171; CPU: Debug trap
172;
173; Traps from Virtual mode are reflected to virtual mode. Unfortunately
174; this breaks the debugger's ability to GO and TRACE the VM program.
175;
176; ENTRY: 386 Protected Mode via 386 Interrupt gate
177; No error code on stack
178; EXIT: to handler or debugger as appropriate
179; USED:
180; STACK:
181;------------------------------------------------------------------------------
182vm_trap01 proc near
183 PUSH_EBP
184 mov bp,sp
185 test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ?
186 jz vmt1_dexit ; N: exit to debugger
187 push 0001 ; Y: interrupt 01
188 jmp hw_int ; reflect it to virtual mode
189vmt1_dexit:
190 ProcessExcep ErrINT1
191vm_trap01 endp
192
193;******************************************************************************
194; H/W: NMI
195;
196; For now, this always traps to the debugger. It's a general purpose hook
197; to let the debugger get control via an NMI button.
198;
199; ENTRY: 386 Protected Mode via 386 Interrupt gate
200; No error code on stack
201; EXIT: to handler or debugger as appropriate
202; USED:
203; STACK:
204;------------------------------------------------------------------------------
205vm_trap02 proc near
206 PUSH_EBP
207 mov bp,sp
208
209 call DisableNMI
210
211 test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ?
212 jz vmt2_parity ; N: error/debug trap
213 ; Y: reflect it/debugger
214 push 02 ; reflect it
215 jmp hw_int
216vmt2_parity:
217 ProcessExcep ErrNMI
218
219vm_trap02 endp
220
221;******************************************************************************
222; CPU: Breakpoint trap (INT 3 instruction)
223;
224; Traps from Virtual mode are reflected to virtual mode. Unfortunately
225; this breaks the debugger's ability to GO and TRACE the VM program.
226;
227; ENTRY: 386 Protected Mode via 386 Interrupt gate
228; No error code on stack
229; EXIT: to handler or debugger as appropriate
230; USED:
231; STACK:
232;------------------------------------------------------------------------------
233vm_trap03 proc near
234 ProcessExcep ErrINT3
235vm_trap03 endp
236
237;******************************************************************************
238; CPU: Overflow trap (INTO instruction)
239;
240; ENTRY: 386 Protected Mode via 386 Interrupt gate
241; No error code on stack
242; EXIT: to handler or debugger as appropriate
243; USED:
244; STACK:
245;------------------------------------------------------------------------------
246vm_trap04 proc near
247 ProcessExcep ErrINTO
248vm_trap04 endp
249
250
251;******************************************************************************
252; CPU: Array bounds fault
253;
254; ENTRY: 386 Protected Mode via 386 Interrupt gate
255; No error code on stack
256; EXIT: to handler or debugger as appropriate
257; USED:
258; STACK:
259;------------------------------------------------------------------------------
260vm_trap05 proc near
261 PUSH_EBP
262 mov bp,sp
263 test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ?
264 jz vmt5_dexit ; N: exit to debugger
265 push 0005 ; Y: interrupt 01
266 jmp hw_int ; reflect it to virtual mode
267vmt5_dexit:
268 ProcessExcep ErrBounds
269vm_trap05 endp
270
271;******************************************************************************
272; CPU: Invalid Opcode fault
273;
274; ENTRY: 386 Protected Mode via 386 Interrupt gate
275; No error code on stack
276; EXIT: to handler or debugger as appropriate
277; USED:
278; STACK:
279;
280; add Invalid instruction emulator ??? (specifically LOCK prefix)
281;
282;------------------------------------------------------------------------------
283vm_trap06 proc near
284 push 0 ; align stack with error offset
285 push 0 ; for VmFault
286 PUSH_EBP
287 mov bp,sp
288 test [bp.VTFOE+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ?
289 jz vmt6_dexit ; N: exit to debugger
290 jmp VmFault ; Y: enter VM 06 Invalid handler
291
292vmt6_dexit:
293 ProcessExcep ErrOpCode
294vm_trap06 endp
295
296;******************************************************************************
297; CPU: Coprocessor not present fault
298;
299; ENTRY: 386 Protected Mode via 386 Interrupt gate
300; No error code on stack
301; EXIT: to handler or debugger as appropriate
302; USED:
303; STACK:
304;------------------------------------------------------------------------------
305vm_trap07 proc near
306 PUSH_EBP
307 mov bp,sp
308 test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ?
309 jz vmt7_dexit ; N: exit to debugger
310 push 0007 ; Y: interrupt 07
311 jmp hw_int ; reflect it to virtual mode
312vmt7_dexit:
313 ProcessExcep ErrCoPNA
314vm_trap07 endp
315
316
317;******************************************************************************
318; CPU: Double Fault
319; H/W: IRQ0 - System timer
320;
321; ENTRY: 386 Protected Mode via 386 Interrupt gate
322; Error Code on stack = 0000
323; EXIT: to handler or debugger as appropriate
324; USED:
325; STACK:
326;------------------------------------------------------------------------------
327vm_trap08 proc near
328 PUSH_EBP
329 mov bp,sp
330 cmp sp,VMT_STACK ; Q: H/W interrupt from VM ?
331 jne vmt8_dexit ; N: exit to debugger
332 push 0008 ; Y: interrupt 8
333 jmp hw_int ; reflect it to virtual mode
334vmt8_dexit:
335 ProcessExcep ErrDouble
336vm_trap08 endp
337
338
339;******************************************************************************
340; CPU: (none for 386)
341; H/W: IRQ1 - Keyboard
342;
343; ENTRY: 386 Protected Mode via 386 Interrupt gate
344; No error code on stack
345; EXIT: to handler or debugger as appropriate
346; USED:
347; STACK:
348;------------------------------------------------------------------------------
349vm_trap09 proc near
350 PUSH_EBP
351 mov bp,sp
352 push 0009 ; Y: interrupt 9
353 jmp hw_int ; reflect it to virtual mode
354vm_trap09 endp
355
356;******************************************************************************
357; CPU: Invalid TSS fault
358; H/W: IRQ2 - Cascade from slave 8259 (see INT 70-77)
359; (shouldn't get H/W interrupts here)
360;
361; ENTRY: 386 Protected Mode via 386 Interrupt gate
362; Error Code on stack = Selector
363; EXIT: to handler or debugger as appropriate
364; USED:
365; STACK:
366
367; to do: someone could reprogram master 8259 - need to handle ?
368;------------------------------------------------------------------------------
369vm_trap0A proc near
370 ProcessExcep ErrTSS
371vm_trap0A endp
372
373
374;******************************************************************************
375; CPU: Segment Not Present fault
376; H/W: IRQ3 - COM2
377;
378; ENTRY: 386 Protected Mode via 386 Interrupt gate
379; Error Code on stack = Selector
380; EXIT: to handler or debugger as appropriate
381; USED:
382; STACK:
383;------------------------------------------------------------------------------
384vm_trap0B proc near
385 PUSH_EBP
386 mov bp,sp
387 test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ?
388 jz vmtB_dexit ; N: exit to debugger
389 push 000Bh ; Y: interrupt 0B
390 jmp hw_int ; reflect it to virtual mode
391vmtB_dexit:
392 ProcessExcep ErrSegNP
393vm_trap0B endp
394
395;******************************************************************************
396; CPU: Stack fault
397; H/W: IRQ4 - COM1
398;
399; ENTRY: 386 Protected Mode via 386 Interrupt gate
400; Error Code on stack = Selector or 0000
401; EXIT: to handler or debugger as appropriate
402; USED:
403; STACK:
404;------------------------------------------------------------------------------
405vm_trap0C proc near
406 PUSH_EBP
407 mov bp,sp
408 test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ?
409 jz vmtC_dexit ; N: exit to debugger
410 push 000Ch ; Y: interrupt 0C
411 jmp hw_int ; reflect it to virtual mode
412vmtC_dexit:
413 ProcessExcep ErrStack
414vm_trap0C endp
415
416;******************************************************************************
417; CPU: General Protection fault
418; H/W: IRQ5 - Second parallel printer
419;
420; ENTRY: 386 Protected Mode via 386 Interrupt gate
421; Error Code on stack = Selector or 0000
422; EXIT: to handler or debugger as appropriate
423; USED:
424; STACK:
425;------------------------------------------------------------------------------
426vm_trap0D proc near
427 PUSH_EBP
428 mov bp,sp
429 cmp sp,VMT_STACK ; Q: H/W interrupt from VM ?
430 jne vmtD_1 ; N: continue
431 push 000Dh ; Y: interrupt vector 0Dh
432 jmp hw_int ; reflect it to virtual mode
433;
434; Here we have a GP fault that was not a H/W interrupt 13 from VM.
435;
436vmtD_1:
437 cmp sp,VMTERR_STACK ; Q: 'normal' exception w/error code ?
438 jne vmtD_dexit ; N: what the hell was it ???? - exit
439 jmp VmFault ; Y: enter VM GP fault handler
440 ; (fall thru to debugger)
441vmtD_dexit:
442 ProcessExcep ErrGP
443vm_trap0D endp
444
445;******************************************************************************
446; CPU: Page fault
447; H/W: IRQ6 - diskette interrupt
448;
449; ENTRY: 386 Protected Mode via 386 Interrupt gate
450; Error Code on stack = type of fault
451; EXIT: to handler or debugger as appropriate
452; USED:
453; STACK:
454;------------------------------------------------------------------------------
455vm_trap0E proc near
456 PUSH_EBP
457 mov bp,sp
458 cmp sp,VMT_STACK ; Q: H/W interrupt from VM ?
459 jne vmtE_dexit ; N: exit to debugger
460 push 000Eh ; Y: interrupt vector 0Eh
461 jmp hw_int ; reflect it to virtual mode
462vmtE_dexit:
463 ProcessExcep ErrPage
464vm_trap0E endp
465
466;******************************************************************************
467; CPU: (none)
468; H/W: IRQ7 - parallel printer
469;
470; ENTRY: 386 Protected Mode via 386 Interrupt gate
471; No error code on stack
472; EXIT: to handler or debugger as appropriate
473; USED:
474; STACK:
475;------------------------------------------------------------------------------
476vm_trap0F proc near
477 PUSH_EBP
478 mov bp,sp
479 push 000Fh ; push interrupt number
480 jmp hw_int ; enter common H/W interrupt handler
481vm_trap0F endp
482
483;******************************************************************************
484; CPU: Coprocessor Error - GOES TO NOT PRESENT FAULT IN DEBUGGER FOR NOW
485;
486; ENTRY: 386 Protected Mode via 386 Interrupt gate
487; No error code on stack
488; EXIT: to handler or debugger as appropriate
489; USED:
490; STACK:
491;------------------------------------------------------------------------------
492vm_trap10 proc near
493 ProcessExcep ErrCoPerr
494vm_trap10 endp
495
496;******************************************************************************
497; VmTrap5x - Handlers for hardware interrupts. Sometimes the master 8259
498; is set to here.
499;
500; ENTRY: 386 Protected Mode via 386 Interrupt gate
501; EXIT: EBP pushed on stack
502; BP = normal stack frame pointer
503; Interrupt number pushed on stack
504; USED:
505; STACK: (4 bytes)
506;------------------------------------------------------------------------------
507vm_trap50 proc near
508 PUSH_EBP
509 mov bp,sp ; set up BP frame pointer
510 push 0050h
511 jmp short hw_int ; enter common code
512vm_trap50 endp
513
514;------------------------------------------------------------------------------
515vm_trap51 proc near
516 PUSH_EBP
517 mov bp,sp ; set up BP frame pointer
518 push 0051h
519 jmp short hw_int ; enter common code
520vm_trap51 endp
521
522;------------------------------------------------------------------------------
523vm_trap52 proc near
524 PUSH_EBP
525 mov bp,sp ; set up BP frame pointer
526 push 0052h
527 jmp short hw_int ; enter common code
528vm_trap52 endp
529
530;------------------------------------------------------------------------------
531vm_trap53 proc near
532 PUSH_EBP
533 mov bp,sp ; set up BP frame pointer
534 push 0053h
535 jmp short hw_int ; enter common code
536vm_trap53 endp
537
538;------------------------------------------------------------------------------
539vm_trap54 proc near
540 PUSH_EBP
541 mov bp,sp ; set up BP frame pointer
542 push 0054h
543 jmp short hw_int ; enter common code
544vm_trap54 endp
545
546;------------------------------------------------------------------------------
547vm_trap55 proc near
548 PUSH_EBP
549 mov bp,sp ; set up BP frame pointer
550 push 0055h
551 jmp short hw_int ; enter common code
552vm_trap55 endp
553
554;------------------------------------------------------------------------------
555vm_trap56 proc near
556 PUSH_EBP
557 mov bp,sp ; set up BP frame pointer
558 push 0056h
559 jmp short hw_int ; enter common code
560vm_trap56 endp
561
562;------------------------------------------------------------------------------
563vm_trap57 proc near
564 PUSH_EBP
565 mov bp,sp ; set up BP frame pointer
566 push 0057h
567 jmp short hw_int ; enter common code
568vm_trap57 endp
569
570;******************************************************************************
571; VmTrap7x - handlers for hardware interrupts from the slave 8259
572;
573; ENTRY: 386 Protected Mode via 386 Interrupt gate
574; EXIT: EBP pushed on stack
575; BP = normal stack frame pointer
576; Interrupt number pushed on stack
577; USED:
578; STACK: (4 bytes)
579;------------------------------------------------------------------------------
580vm_trap70 proc near
581 PUSH_EBP
582 mov bp,sp ; set up BP frame pointer
583 push 0070h
584 jmp short hw_int ; enter common code
585vm_trap70 endp
586
587;------------------------------------------------------------------------------
588vm_trap71 proc near
589 PUSH_EBP
590 mov bp,sp ; set up BP frame pointer
591 push 0071h
592 jmp short hw_int ; enter common code
593vm_trap71 endp
594
595;------------------------------------------------------------------------------
596vm_trap72 proc near
597 PUSH_EBP
598 mov bp,sp ; set up BP frame pointer
599 push 0072h
600 jmp short hw_int ; enter common code
601vm_trap72 endp
602
603;------------------------------------------------------------------------------
604vm_trap73 proc near
605 PUSH_EBP
606 mov bp,sp ; set up BP frame pointer
607 push 0073h
608 jmp short hw_int ; enter common code
609vm_trap73 endp
610
611;------------------------------------------------------------------------------
612vm_trap74 proc near
613 PUSH_EBP
614 mov bp,sp ; set up BP frame pointer
615 push 0074h
616 jmp short hw_int ; enter common code
617vm_trap74 endp
618
619;------------------------------------------------------------------------------
620vm_trap75 proc near
621 PUSH_EBP
622 mov bp,sp ; set up BP frame pointer
623 push 0075h
624 jmp short hw_int ; enter common code
625vm_trap75 endp
626
627;------------------------------------------------------------------------------
628vm_trap76 proc near
629 PUSH_EBP
630 mov bp,sp ; set up BP frame pointer
631 push 0076h
632 jmp short hw_int ; enter common code
633vm_trap76 endp
634
635;------------------------------------------------------------------------------
636vm_trap77 proc near
637 PUSH_EBP
638 mov bp,sp ; set up BP frame pointer
639 push 0077h
640 jmp short hw_int ; enter common code
641vm_trap77 endp
642
643 page
644;******************************************************************************
645; HW_INT - common handler for hardware interrupts. The interrupt is
646; reflected directly to the appropriate Real Mode (Virtual) handler.
647; This entry point clear the trace flag (TF) and int flag (IF), since
648; a h/w interrupt would (NOTE: INT n and INTO instructions also clear
649; TF and IF - so this entry is suitable for reflecting these also).
650;
651; EMUL_REFLECT - entry point for reflecting emulations.
652; This entry point does not clear the trace flag (TF) and int flag (IF).
653;
654; 386 interrupt gate switched us to the Ring 0 stack on the way in
655; from Virtual Mode and pushed 32-bit values as follows:
656;
657; hiword loword offset (in addition to EBP push)
658; +------+------+ <-------- Top of 'kernel' stack
659; | 0000 | GS | +32 (decimal)
660; |------|------|
661; | 0000 | FS | +28
662; |------|------|
663; | 0000 | DS | +24
664; |------|------|
665; | 0000 | ES | +20
666; |------|------|
667; | 0000 | SS | +16
668; |------|------|
669; | ESP | +12
670; |------|------|
671; | EFLAGS | +08
672; |------|------|
673; | 0000 | CS | +04
674; |------|------|
675; | EIP | +00
676; +------+------+ <-------- Ring 0 SS:SP
677; | (ebp) |
678; +-------------+ <-------- Ring 0 SS:BP
679;
680; The object of this routine is to massage the trap stack frame (above)
681; and build a 'real mode' stack frame for the virtual mode client so that
682; we can transfer control to virtual mode at the address specified in
683; the appropriate real mode IDT vector. The client's IRET out of the
684; interrupt routine will proceed normally (assuming we're letting him
685; run with IOPL = 3). Since we're fielding the trap from Virtual Mode,
686; we assume the high word of ESP and EIP is 0000.
687;
688; +-------+ <-------- Client's current SS:SP
689; | Flags | +4
690; |-------|
691; | CS | +2
692; |-------|
693; | IP | +0
694; +-------+ <-------- Client's SS:SP when we let him have control
695;
696; Assume entry from Virtual Mode, for now. We shouldn't be getting entered
697; here except via Hardware interrupt, so no sanity checks are performed.
698;
699; ENTRY: 386 Protected Mode
700; BP -> standard frame
701; EBP and Interrupt number have been pushed onto stack
702; EXIT: via IRET to VM86 program
703; appropriate real mode IRET set up @ client's SS:SP
704; USED: (none) (note that DS & ES are free to use - saved during trap)
705; STACK:
706;
707; to do: Need to check for entry mode ?
708;------------------------------------------------------------------------------
709hw_int proc near
710 push bx
711 push si ;
712 mov si,[bp.VTFO+VMTF_EFLAGS] ; SI = saved low word of EFLAGS
713;
714; *** clear IF bit and Trace Flag on flags for reflect, but leave them
715; unchanged for the flags on the IRET stack we build on the
716; client's stack.
717;
718 and [bp.VTFO+VMTF_EFLAGS],not 300h ; clear IF and TF
719reflect_common:
720;
721; Build a selector (VM1_GSEL) to client's stack. VM1_GSEL is already set
722; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base.
723;
724 HwTabUnlock ; disable HW protection on high ram
725 mov bx,GDTD_GSEL ; get GDT data alias
726 mov ds,bx ; DS -> GDT
727 mov bx,[bp.VTFO+VMTF_SS] ; BX = VM SS (segment form)
728 shl bx,4 ; BX = low 16 bits of base
729 mov ds:[VM1_GSEL+2],bx ; place in descriptor
730 mov bx,[bp.VTFO+VMTF_SS] ; BX = VM SS (again)
731 shr bx,4 ; BH = high 8 bits of base
732 mov ds:[VM1_GSEL+4],bh ; place in descriptor
733;
734; Adjust client's SP to make room for building his IRET frame
735;
736 sub word ptr [bp.VTFO+VMTF_ESP],6 ; adjust client's SP
737 mov bx, VM1_GSEL
738 mov ds, bx ; DS = VM stack segment
739;
740 mov bx,si ; BX = low word of client's EFLAGS
741;
742 mov si,[bp.VTFO+VMTF_ESP] ; DS:SI = pointer to client's frame
743;
744; Move low 16 bits of Flags, CS, and EIP from IRET frame to client stack frame
745;
746 mov ds:[si.4],bx ; to client's flags
747 mov bx,[bp.VTFO+VMTF_CS] ;
748 mov ds:[si.2],bx ; to client's CS
749 mov bx,[bp.VTFO+VMTF_EIP] ; low word of EIP
750 mov ds:[si.0],bx ; to client's IP
751;
752; Replace low 16 bits of IRET frame CS:EIP with vector from real mode IDT
753;
754 mov bx,[bp-2] ; get the interrupt vector
755 shl bx,2 ; BX = BX * 4 (vector table index)
756 mov si,RM_IDT_GSEL ; get real mode IDT alias
757 mov ds,si ; DS -> Real Mode IDT
758 mov si,ds:[bx] ;
759 mov [bp.VTFO+VMTF_EIP],si ; move the IP
760 mov si,ds:[bx+2] ;
761 mov [bp.VTFO+VMTF_CS],si ; move the CS
762;
763; 32-bit IRET back to client
764;
765 HwTabLock ; enable HW protection on high ram
766 pop si ; restore local regs
767 pop bx
768 pop bp ; throw away fake interrupt number
769 POP_EBP
770 db 66h
771 iret ; *** RETURN *** to client
772hw_int endp
773
774;******************************************************************************
775; EMUL_REFLECT
776;******************************************************************************
777;
778; emulation relfection entry point - don't mess with client's flags
779;
780emul_reflect label near
781 push bx ; local registers
782 push si ;
783 mov si,[bp.VTFO+VMTF_EFLAGS] ; SI = saved low word of EFLAGS
784 jmp reflect_common
785
786
787;
788_TEXT ends ; end of segment
789;
790 end ; end of module
791 \ No newline at end of file