]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/MEMM/MEMM/EMM.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / MEMM / MEMM / EMM.ASM
1
2
3 page 58,132
4 ;******************************************************************************
5 title EMM - Expanded Memory Manager interface for MEMM
6 ;******************************************************************************
7 ;
8 ; (C) Copyright MICROSOFT Corp. 1986
9 ;
10 ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11 ;
12 ; Module: EMM - Expanded Memory Manager interface
13 ;
14 ; Version: 0.05
15 ;
16 ; Date: June 14, 1986
17 ;
18 ; Author:
19 ;
20 ;******************************************************************************
21 ;
22 ; Change Log:
23 ;
24 ; DATE REVISION Description
25 ; -------- -------- --------------------------------------------
26 ; 06/14/86 original
27 ; 06/28/86 0.02 Name change from MEMM386 to MEMM
28 ; 06/29/86 0.02 Protect port 84/85 from ints
29 ; 07/05/86 0.04 moved EMM_rEntry to R_CODE
30 ; 07/06/86 0.04 Changed assume to DGROUP
31 ; 07/08/86 0.04 Changed EMM_pEntry to call EMM functions
32 ; directly
33 ; 07/10/86 0.05 jmp $+2 before "POPF"
34 ; 07/10/86 0.05 added EMM_Flag
35 ; 06/09/88 remove _map_known since there is no map now (pc)
36 ; 07/20/88 remove debugger code (pc)
37 ;
38 ;******************************************************************************
39 ; Functional Description:
40 ; The module contains code for calling the EMM functions and a routine
41 ; for managing the AUTO mode of MEMM.
42 ; There are two EMM entry points in this module; one for real/virtual
43 ; mode entry and one for protected mode (IDT entry points here). When
44 ; MEMM is ON (system in Virtual mode), INT 67H calls transition to protected
45 ; mode and the EMM_pEntry entry point. EMM_pEntry sets up the same stack
46 ; conditions as the generic int67_Entry dispatcher and calls the appropriate
47 ; EMM function. Some EMM functions cannot be executed in protected mode.
48 ; These functions are called by reflecting the INT 67H to the real/virtual
49 ; mode entry point. EMM functions which are executed in PROTECTED mode
50 ; will take less time (they don't suffer the extra time to reflect the
51 ; INT 67H).
52 ;
53 ;******************************************************************************
54 .lfcond
55 .386p
56 page
57 ;******************************************************************************
58 ; P U B L I C D E C L A R A T I O N S
59 ;******************************************************************************
60 ;
61 public EMM_pEntry ; protected mode entry point
62 public EMM_rEntry ; real mode entry point
63 public EMM_rEfix ; label for far jump to int67_entry
64 public _AutoUpdate ; update auto mode of VDM/EMM
65 public EMM_Flag ; flag for EMM calls
66
67 page
68 ;******************************************************************************
69 ; L O C A L C O N S T A N T S
70 ;******************************************************************************
71 ;
72 include vdmseg.inc
73 include vdmsel.inc
74 include vm386.inc
75 ; include instr386.inc
76 include oemdep.inc
77 include emmdef.inc
78
79 FALSE equ 0
80 TRUE equ not FALSE
81
82 ;
83 ; these EMM functions are handled in protected mode
84 ;
85 EMM_MAP_PAGE equ 44h ; map handle page
86 EMM_RESTORE equ 48h ; restore page map
87 EMM_GET_SET equ 4Eh ; get/set page map
88 EMM_GET_SET_PARTIAL equ 4Fh ; get/set partial page map
89 EMM_MAP_PAGE_ARRAY equ 50h ; map handle page array
90 EMM_ALTER_MAP_JUMP equ 55h ; alter mapping and jump
91 EMM_ALTER_MAP_CALL equ 56h ; alter mapping and call
92 EMM_MOVE_XCHG_MEM equ 57h ; move/xchg memory region
93 EMM_ALTER_MAP_REG_SET equ 5Bh ; alternate map register set
94
95 EMM_HW_MALFUNCTION equ 81h ;
96
97 ;******************************************************************************
98 ; E X T E R N A L R E F E R E N C E S
99 ;******************************************************************************
100 ;
101 ABS0 segment use16 at 0000h
102
103 org 67h * 4 ; EMM function interrupt
104 EMMVec dw ? ; offset of vector
105 dw ? ; segment of vector
106
107 ABS0 ends
108
109 _DATA segment
110
111 extrn _EMMstatus:word
112 extrn Active_Status:byte ; current VDM status
113 extrn Auto_Mode:byte ; current Auto mode status
114 ;extrn _map_known:byte ; non-zero => I/O map known to a user
115 extrn _handle_count:word ; number of active EMM handles
116 extrn _regp:word ; pointer to args on stack
117
118 _DATA ends
119
120 _TEXT segment
121
122 extrn int67_Entry:far ; it's far because we need CS on stack too
123 extrn GoVirtual:near
124 extrn ErrHndlr:near
125 extrn hw_int:near
126 extrn RRProc:near
127
128 extrn _GetStatus:near
129 extrn _GetPageFrameAddress:near
130 extrn _GetUnallocatedPageCount:near
131 extrn _AllocatePages:near
132 extrn _MapHandlePage:near
133 extrn _DeallocatePages:near
134 extrn _GetEMMVersion:near
135 extrn _SavePageMap:near
136 extrn _RestorePageMap:near
137 extrn _GetPageMappingRegisterIOArray:near
138 extrn _GetLogicalToPhysicalPageTrans:near
139 extrn _GetEMMHandleCount:near
140 extrn _GetEMMHandlePages:near
141 extrn _GetAllEMMHandlePages:near
142 extrn _GetSetPageMap:near
143
144 extrn _GetSetPartial:near
145 extrn _MapHandleArray:near
146 extrn _AlterMapAndJump:near
147 extrn _AlterMapAndCall:near
148 extrn _MoveExchangeMemory:near
149 extrn _AlternateMapRegisterSet:near
150
151 _TEXT ends
152
153 page
154 ;******************************************************************************
155 ; S E G M E N T D E F I N I T I O N
156 ;******************************************************************************
157 ;
158 _DATA segment
159 EMM_Flag db 0 ; non-zero => EMM function called by our code
160 _DATA ends
161
162 page
163 ;******************************************************************************
164 ;
165 ; _TEXT Code Segment
166 ;
167 ;******************************************************************************
168 ;
169 _TEXT segment
170 assume cs:_TEXT, ds:DGROUP, es:DGROUP
171 ;******************************************************************************
172 ; protected mode dispatch table
173 ; allocate(43h)/deallocate(45h) pages and get I/O map (49h)
174 ; MUST be reflected to Virtual mode
175 ; MapHandlePage,RestorePageMap,GetSetPageMap,GetSetPartial,
176 ; MapHandleArray,MoveExchangeMemory,AlterMapAndJump,
177 ; AlterMapAndCall and AlternateMapRegisterSet are protected mode ONLY.
178 ;******************************************************************************
179 EpE_Dispatch label word
180 dw offset _TEXT:EpE_Null
181 dw offset _TEXT:EpE_Null
182 dw offset _TEXT:EpE_Null
183 dw offset _TEXT:EpE_Null
184 dw offset _TEXT:_MapHandlePage ;44h
185 dw offset _TEXT:EpE_Null
186 dw offset _TEXT:EpE_Null
187 dw offset _TEXT:EpE_Null
188 dw offset _TEXT:_RestorePageMap ;48h
189 dw offset _TEXT:EpE_Null
190 dw offset _TEXT:EpE_Null
191 dw offset _TEXT:EpE_Null
192 dw offset _TEXT:EpE_Null
193 dw offset _TEXT:EpE_Null
194 dw offset _TEXT:_GetSetPageMap ;4eh
195 dw offset _TEXT:_GetSetPartial ;4fh
196 dw offset _TEXT:_MapHandleArray ;50h
197 dw offset _TEXT:EpE_Null
198 dw offset _TEXT:EpE_Null
199 dw offset _TEXT:EpE_Null
200 dw offset _TEXT:EpE_Null
201 dw offset _TEXT:_AlterMapAndJump ;55h
202 dw offset _TEXT:_AlterMapAndCall ;56h
203 dw offset _TEXT:_MoveExchangeMemory ;57h
204 dw offset _TEXT:EpE_Null
205 dw offset _TEXT:EpE_Null
206 dw offset _TEXT:EpE_Null
207 dw offset _TEXT:_AlternateMapRegisterSet ;5bh
208 dw offset _TEXT:EpE_Null
209 dw offset _TEXT:EpE_Null
210
211 page
212 ;******************************************************************************
213 ; EMM_pEntry - protected mode entry point for EMM function calls
214 ;
215 ; ENTRY: Protected mode
216 ; DGROUP:[EMM_Flag] = zero => reflect this int
217 ; SS:[SP] pointing to virtual mode INT stack frame
218 ;
219 ; EXIT: Protected mode
220 ; if this EMM function is to be handled in protected mode,
221 ; registers as set by EMM functions
222 ; else
223 ; reflect int 67 to virtual mode EMM code
224 ;
225 ; NOTE: *****
226 ; Allocate(43h)/deallocate(44h) pages and get I/O map (49h)
227 ; MUST be reflected to Virtual mode.
228 ;
229 ; USED: none
230 ;
231 ;******************************************************************************
232 ;
233 ; reflect EMM function to real mode
234 ;
235 EpE_reflect:
236 push 67h ; refect
237 jmp hw_int ; it...
238 ;
239 ;
240 ; client not in Virtual mode
241 ;
242 EpE_not_VM:
243 pop ebp ; N: call error handler
244
245 mov ax,ExcpErr ; exception error
246 mov bx,ErrINTProt ; invalid software interrupt
247 call ErrHndlr
248 ;
249 ; function entry
250 ;
251 EMM_pEntry proc near
252 ;
253 push ebp
254 mov bp,sp
255 test [bp.VTFO+VMTF_EFLAGShi],2 ;Q:client in Virtual mode ?
256 jz EpE_not_VM ; N: handle it
257 ; Y: check flag
258 push VDMD_GSEL
259 pop ds ; DS = DGROUP
260 push VDMD_GSEL
261 pop es ; ES = DGROUP
262 cmp [EMM_Flag],0 ;Q: did we do this int67 ?
263 je EpE_Reflect ; N: reflect it
264 mov [EMM_Flag],0 ; Y: clear EMM_Flag for next
265 ; time and handle function
266 ; in protected mode.
267 ;
268 ; dispatch EMM function OR reflect to real/vm dispatcher
269 ;
270 EpE_chk_func:
271 HwTabUnlock ; unlock ROM
272
273 push [bp.VTFO+VMTF_FS] ; client FS
274 push [bp.VTFO+VMTF_GS] ; client GS
275 push [bp.VTFO+VMTF_ES] ; client ES
276 push [bp.VTFO+VMTF_DS] ; client DS
277 push [bp.VTFO+VMTF_EFLAGS] ; client Flag
278 push [bp.VTFO+VMTF_CS] ; client CS
279 push word ptr [bp.VTFO+VMTF_EIP] ; client IP (low word of EIP)
280 ; stack has - IP,CS,PFlag,DS,ES,GS,FS
281 pushad ; all regs saved
282 mov bp,sp ; SS:BP -> to stack args (see r67_Frame struc)
283 mov [_regp],sp ; regp points to regs on stack
284 mov [_regp+2],ss ; regp now has a far ptr to regs
285
286 push ax
287 mov ax, PFLAG_VIRTUAL ; Faked VM bit
288 or [bp.PFlag], ax ; Incorpated in PFlag
289 pop ax
290 ;
291 ; validate function code
292 ;
293 sub ah,40h ; check if entry code too small
294 jb EpE_inv_exit ; if so, error exit
295 cmp ah,(5Dh-40h) ; check if entry code too big
296 ja EpE_inv_exit ; if so, error exit
297 ; else, AH = 0 base function #
298 ;
299 ; call through the jump table
300 ;
301 EpE_jump:
302 xchg ah,al ; AL = function code
303 mov si,ax
304 xchg ah,al ; AH = function code again
305 and si,00FFh ; SI = function #
306 shl si,1 ; SI = table offset
307 call CS:EpE_Dispatch[si] ; call function
308
309 ;
310 ; check to see if we need to patch CS:IP on the iretd stack frame
311 ;
312 EpE_Exit:
313 test word ptr [bp.PFlag], PFLAG_PATCH_CS_IP
314 jz EpE_No_Patch
315
316 mov bp, sp ; use bp to address stack
317 ;
318 ; patch iretd's CS:EIP to new CS:IP on stack
319 ;
320 mov ax, [bp.retaddr] ; get return IP
321 mov [bp.rFS+6], ax ; iretd's IP (6 bytes beyond FS)
322 xor ax, ax
323 mov [bp.rFS+8], ax ; zero high word of EIP
324 mov ax, [bp.rCS] ; get return CS
325 mov [bp.rFS+10], ax ; iretd's CS
326
327 EpE_No_Patch:
328 popad ; restore regs
329 add sp, 6 ; throw away return addr cs and ip and flags
330 pop [bp.VTFO+VMTF_DS] ; client DS
331 pop [bp.VTFO+VMTF_ES] ; client ES
332 pop [bp.VTFO+VMTF_GS] ; client GS
333 pop [bp.VTFO+VMTF_FS] ; client FS
334
335
336 pop ebp ; restore bp
337
338 HwTabLock ; lock ROM
339
340 iretd ; return to virtual mode caller
341 ;
342 ; Null function - do nothing (should not get to here)
343 EpE_Null:
344 ret ; return after doing nothing
345 ;
346 ; EMM error handling
347 ;
348 EpE_inv_exit: ; set invalid function code error
349 mov byte ptr [bp.rAX+1],INVALID_FUNCTION
350 jmp EpE_Exit
351
352 EMM_pEntry endp
353
354 page
355 ;******************************************************************************
356 ; EMM_rLink - real/virtual mode link for EMM function calls from
357 ; R_CODE segment.
358 ;
359 ; ENTRY: real/virtual mode
360 ; all registers as set by user
361 ;
362 ; EXIT: real/virtual mode
363 ; registers as set by EMM functions
364 ;
365 ; USED: none
366 ;
367 ;******************************************************************************
368 EMM_rLINK proc far
369
370 ;
371 ; check for protected mode ONLY function
372 ;
373 cmp ah,EMM_MAP_PAGE ;Q: map handle page function ?
374 je ErE_GoProt ; Y: do it in protected mode
375 cmp ah,EMM_RESTORE ;Q: restore page map function ?
376 je ErE_GoProt ; Y: do it in protected mode
377 cmp ah,EMM_GET_SET ;Q: get/set page map function ?
378 je ErE_GoProt ; Y: do it in protected mode
379 cmp ah,EMM_GET_SET_PARTIAL ;Q: get/set partial function ?
380 je ErE_GoProt ; Y: do it in protected mode
381 cmp ah,EMM_MAP_PAGE_ARRAY ;Q: map handle page array ?
382 je ErE_GoProt ; Y: do it in protected mode
383 cmp ah,EMM_ALTER_MAP_JUMP ;Q: alter map and jump ?
384 je ErE_GoProt ; Y: do it in protected mode
385 cmp ah,EMM_ALTER_MAP_CALL ;Q: alter map and call ?
386 je ErE_GoProt ; Y: do it in protected mode
387 cmp ah,EMM_MOVE_XCHG_MEM ;Q: move/xchg memory region ?
388 je ErE_GoProt ; Y: do it in protected mode
389 cmp ah,EMM_ALTER_MAP_REG_SET;Q: alternate map register set ?
390 je ErE_GoProt ; Y: do it in protected mode
391 ; N: do it in real/virtual mode
392 ;
393 ; here for real/virtual mode functions
394 ;
395 push fs
396 push gs
397 push es
398 push ds
399 push 00 ; PFlag => real mode call to EMM functions
400 push seg DGROUP
401 pop ds ; set DS = DGROUP
402 call int67_Entry ; call dispatcher
403 add sp,2 ; drop PFlag arg
404 pop ds ; restore seg regs
405 pop es
406 pop gs
407 pop fs
408 ret ; and return
409
410 ;
411 ; Here if protected mode function called via real IDT
412 ; - set EMM flag and go for it...
413 ;
414 ErE_GoProt:
415 push ds
416 push seg DGROUP
417 pop ds ; DS = DGROUP
418 cmp [Active_Status],0 ;Q: are we in Virtual Mode ?
419 jne ErE_Pcall ; Y: call protected mode function
420 ; mov [_map_known],TRUE ; N: set global auto mode flag
421 call _AutoUpdate ; go into virtual mode
422 ; and call function
423 ErE_Pcall:
424 mov [EMM_Flag],TRUE ; set flag
425 pop ds ; restore DS
426 int 67h ; go for it ...
427 ret ; then return
428
429 EMM_rLINK endp
430
431 page
432 ;******************************************************************************
433 ; _AutoUpdate - updates the EMM status when in AutoMode
434 ;
435 ; ENTRY: REAL or VIRTUAL mode ONLY
436 ; DS = DGROUP segment
437 ; DS:[Auto_Mode] = non-zero => system currently in auto mode
438 ; DS:[Active_Status] = non-zero => system currently ON
439 ; DS:[_map_known] = non-zero => I/O map has been given to a user
440 ;
441 ; EXIT: exits in real or virtual depending on the state variables
442 ; DS:[Active_Status] = current ON/OFF status
443 ;
444 ; USED: none
445 ;
446 ;******************************************************************************
447 _AutoUpdate proc near
448 ;
449 cmp [Auto_Mode],0 ;Q: in Auto mode now ?
450 je AU_exit ; N: exit
451 cmp [Active_Status],0 ; Y:Q: ON now ?
452 je AU_chkoff ; N: check OFF state status
453 ;
454 ; here if we are currently ON
455 ;
456 ; cmp [_map_known],0 ; Y:Q: map known ?
457 ; jne AU_exit ; Y: then stay ON...
458 cmp [_handle_count],0 ; N:Q: any active handles ?
459 jne AU_exit ; Y: then stay ON...
460 mov [Active_Status],0 ; N: go to OFF state
461 push ax
462 call RRProc ; Force processor into real mode
463 pop ax
464 jmp AU_exit ; and leave in real mode
465 ;
466 ; here if we are currently OFF
467 ;
468 AU_chkoff:
469 cmp [_handle_count],0 ;Q: any active handles ?
470 je AU_exit ; N: stay off
471
472 ; cmp [_map_known],0 ;; Q: is the map known ?
473 ; je AU_exit ;; N: then stay OFF...
474
475 AU_ON: ; Y: turn ON EMM
476 mov [Active_Status],1 ; go to ON state,
477 call GoVirtual ; and go to virtual mode (ON)
478 AU_exit:
479 ret
480 ;
481 _AutoUpdate endp
482
483 _TEXT ends
484
485 page
486 ;******************************************************************************
487 ;
488 ; R_CODE Code Segment
489 ;
490 ;******************************************************************************
491 ;
492 R_CODE segment
493 assume cs:R_CODE, ds:DGROUP, es:DGROUP
494
495 page
496 ;******************************************************************************
497 ; EMM_rEntry - real/virtual mode entry point for EMM function calls
498 ;
499 ; ENTRY: real/virtual mode
500 ; all registers as set by user
501 ;
502 ; EXIT: real/virtual mode
503 ; registers as set by EMM functions
504 ;
505 ; USED: none
506 ;
507 ;******************************************************************************
508 EMM_rEntry proc near
509 ;
510 cli ; just in case pushf/call far
511
512 EMM_rEfix:
513 call EMM_rLink ; call _TEXT segment link
514 iret ; return to caller
515 ;
516 EMM_rEntry endp
517
518
519 R_CODE ends
520
521 end
522 \1a