]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/MEMM/MEMM/RETREAL.ASM
4 ;******************************************************************************
5 title RetReal
- Return
-To
-Real routine
(s
) for the
386
6 ;******************************************************************************
8 ; (C) Copyright MICROSOFT Corp. 1986
10 ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
12 ; Module: RetReal - Return-To-Real routine(s) for the 386
16 ; Date: February 20, 1986
20 ;******************************************************************************
24 ; DATE REVISION DESCRIPTION
25 ; -------- -------- -------------------------------------------------------
27 ; 05/12/86 A Cleanup and segment reorganization
28 ; 06/01/86 Removed Real386a (loadall version) and left only
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
36 ;******************************************************************************
38 ; Functional Description:
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).
43 ; NOTE: this module only works on the B0 and later parts. The A2 part
44 ; will leave the CS non writeable.
46 ;******************************************************************************
47 .lfcond
; list false conditionals
50 ;******************************************************************************
51 ; P U B L I C D E C L A R A T I O N S
52 ;******************************************************************************
58 ;******************************************************************************
59 ; I N C L U D E F I L E S
60 ;******************************************************************************
68 ;******************************************************************************
69 ; E X T E R N A L R E F E R E N C E S
70 ;******************************************************************************
73 extrn Active_Status
:byte
78 extrn SelToSeg
:near ; selector to segment (I286)
79 extrn DisableA20
:near ; disable A20 line (MODESW)
82 ;******************************************************************************
83 ; L O C A L C O N S T A N T S
84 ;******************************************************************************
90 ;******************************************************************************
91 ; S E G M E N T D E F I N I T I O N
92 ;******************************************************************************
95 assume
cs:_TEXT
, ds:DGROUP
97 ;*** RetReal - cause a 386 mode switch to real mode
99 ; ENTRY Ring 0 protected mode
100 ; CLI - interrupts disabled
101 ; NMI should also be disabled here.
103 ; FS = Diag segment selector
107 ; DGROUP:[Active_Status] = 0
109 ; DS = ES = FS = GS = DGROUP
111 ; general registers preserved
113 ; interrupts disabled
116 ; high system memory LOCKED
119 ; USES see exit conditions above
124 real_idt dw 0FFFFh ; limit
127 dw 0000 ; just in case
131 PUSH_EAX
; save two scratch registers
135 smsw ax ;check to see if we are in real mode
137 jnz rl386_a
;jump if in protected mode
141 ret ;otherwise return
146 ; reset TSS busy bit before returning to Real Mode
149 mov es, ax ; ES:0 = ptr to gdt
151 and byte ptr ES:[TSS_GSEL
+ 5], 11111101B
154 ; lock high system ROM before returning to real
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.
164 ; We get the base address from the descriptor table,
165 ; and convert it to a paragraph number.
167 mov bx,ss ; bx = selector for stack
168 call SelToSeg
; AX = segment number for SS
169 mov bx,ax ; BX = setup stack segment
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
177 mov ax,VDMD_GSEL
; selector with real mode attributes
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).
188 MOV_EAX_CR0
; get CR0
191 and ax,0FFFEh ; force real mode and shut down paging
192 dw 07FFFh ; (mov eax,07FFFFFFEh)
194 MOV_CR0_EAX
; set CR0
196 ; flush prefetched instructions with:
197 db 0EAh ; Far Jump opcode
198 dw offset _TEXT
:rl386_b
; destination offset
200 dw _TEXT
; destination segment
202 OP32
; load up full IDT address
203 lidt qword ptr cs:[real_idt
]
207 MOV_EAX_CR3
; get CR3
208 MOV_CR3_EAX
; set CR3 => clear TLB
210 mov ss,bx ; ss = real mode stack segment
217 mov [Active_Status
],0 ; rest VDM status
219 call DisableA20
; disable A20 line