;
;       Switches slave procs from protect mocde to real mode
;
;       Currently, _SwitchToRealMode must be in it's own code class
;       and be the only object in this class.
;

        TITLE   $Switch

        .386P

_TEXT   SEGMENT  DWORD USE32 PUBLIC 'CODE1'
_TEXT   ENDS

_DATA   SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA   ENDS

PUBLIC  _SwitchToRealMode
PUBLIC  GDTDesc
PUBLIC  GDTNew
PUBLIC  $off1
PUBLIC  $sel1
PUBLIC  $dest1
PUBLIC  $off2
PUBLIC  $sel2

        ASSUME   CS: FLAT, DS: FLAT, SS: FLAT, ES: FLAT

_TEXT   SEGMENT

_SwitchToRealMode       PROC NEAR
;
;       ESI = ptr to GDTDesc for lgdt
;       EDI = ptr to GDTNew (new descriptors)
;       EBX = physical=linear address of this function
;       EDX = selector=segment, used after reloading GDT and when in real mode

        cli
        mov     ebx,   10203040h                ; 01020304h will be replaced
                                                ; by the physical address of
                                                ; _SwitchToRealMode.  This
                                                ; is done during PSD init.
        mov     esi,   ebx                      ;
        add     esi,   offset GDTDesc           ; pointer to GDTDesc for lgdt
        mov     edi,   ebx                      ;
        add     edi,   offset GDTNew            ; pointer to GDTNew descriptor

        mov     edx,   ebx                      ; NOTE : we will be < 1 Meg
        and     edx,   0ffff0000h               ; Base 64K lin/phys we are on
        shr     edx,   04h                      ; Selector to use
        mov     eax,   edi                      ; pointer to GDTDesc
        sub     eax,   edx                      ; New GDT base linear address

        mov     word ptr [esi],         0ffffh  ; New GDT limit
        mov     dword ptr [esi+02h],    eax     ; New GDT base linear addr

        mov     eax ,   ebx                     ; fixup the long jump used for
        and     eax,    0000ffffh               ; reloading CS after the new
        add     eax,    offset $dest1           ; GDT is loaded
                                                ;
        mov     ecx,    ebx                     ;
        add     ecx,    offset $off1            ;
        mov     dword ptr [ecx],        eax     ; offset
                                                ;
        mov     word ptr  [ecx+4],      dx      ; selector
                                                ;
        mov     eax,    cs:[467h]               ; fixup the long jump used to
                                                ; jump to the warm boot vector
        mov     ecx,    ebx                     ;
        add     ecx,    offset $off2            ;
        mov     word ptr [ecx],         ax      ; offset
        shr     eax,    16                      ;
        mov     word ptr [ecx+2],       ax      ; segment
                                                ;
        mov     ebx,    edx                     ; Save selector used
        add     ebx,    8                       ; The next selector is data
        shl     edx,    4                       ; Base 64K lin/phys we are on

        mov     ecx,    edx                     ;
        shl     ecx,    10h                     ; Use limit of ffff
        or      ecx,    0ffffh                  ; dword 0 of new descriptor 1

        xor     eax,    eax                     ;
        shr     edx,    10H                     ;
        mov     al,     dh                      ;
        shl     eax,    18h                     ; base address 31:24
        mov     al,     dl                      ; base address 23:16
        or      eax,    00009b00h               ; dword 1 of new descriptor 1
                                                ;
                                                ; Byte Granular
                                                ; 16-bit
                                                ; present
                                                ; system desc
                                                ; type
        mov     dword ptr [edi],        ecx       ; dword 0                   1
        mov     dword ptr [edi+04h],    eax       ; dword 1                   1
        mov     dword ptr [edi+08h],    0000ffffh ; dword 0 of new descrpitor 2
        mov     dword ptr [edi+0ch],    00109300h ; dword 1 of new descriptor 2

        lgdt    fword ptr [esi]                 ;
                                                ; Reload CS
        db      0eah                            ; jmp $sel1:$off1 ($dest1)
$off1:  db       99h
        db       88H
        db       77H
        db       66H
$sel1:  db       55H
        db       44H

$dest1: mov     ss,     ebx                     ; we are now 16 bit segment
        mov     ds,     ebx
        mov     es,     ebx
        mov     fs,     ebx
        mov     gs,     ebx

        mov     ebx,    cr0
        db      66H
        and     ebx, 0fffffffeh
        mov     cr0,    ebx                     ; go to real mode

        db      0eah                            ; jmp to warm boot vector
$off2:  db      55h
        db      66h
$sel2:  db      77h
        db      88h

        nop
GDTDesc df    ?
GDTNew  dd    4 dup(1111)
Test1   dw    ?
Test2   dw    ?
        nop
        nop
        nop
        nop
_SwitchToRealMode       ENDP

_TEXT   ENDS

END


        mov     al,    18h
;       mov     dx,    810h
        db      0bah
        db      10h
        db      08h
        out     dx,    al
;       mov     dx,    814h
        db      0bah
        db      14h
        db      08h
        mov     al,    88h
        out     dx,    al





        mov     al,    18h
;       mov     dx,    810h
        db      0bah
        db      10h
        db      08h
        out     dx,    al
;       mov     dx,    814h
        db      0bah
        db      14h
        db      08h
        mov     al,    99h
        out     dx,    al
