home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2MISC / CSDPMI3S.ZIP / SRC / CWSDPMI / MSWITCH.ASM < prev    next >
Encoding:
Assembly Source File  |  1996-06-30  |  10.4 KB  |  511 lines

  1. ; Copyright (C) 1995,1996 CW Sandmann (sandmann@clio.rice.edu) 1206 Braelinn, Sugarland, TX 77479
  2. ; Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  3. ;
  4. ; This file is distributed under the terms listed in the document
  5. ; "copying.cws", available from CW Sandmann at the address above.
  6. ; A copy of "copying.cws" should accompany this file; if not, a copy
  7. ; should be available from where this file was obtained.  This file
  8. ; may not be distributed without a verbatim copy of "copying.cws".
  9. ;
  10. ; This file is distributed WITHOUT ANY WARRANTY; without even the implied
  11. ; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12.  
  13. ; Modified for VCPI Implement by Y.Shibata Aug 5th 1991
  14.  
  15.     title    switch between real and protected mode
  16.     include segdefs.inc
  17.     include tss.inc
  18.     include gdt.inc
  19.     include vcpi.inc
  20.  
  21. ;------------------------------------------------------------------------
  22.  
  23.     start_data16
  24.  
  25.     extrn    _gdt:gdt_s
  26.     extrn    _gdt_phys:gdt_s
  27.     extrn    _idt_phys:gdt_s
  28.     extrn    _tss_ptr:word
  29.     extrn    _use_xms:byte
  30.     extrn    _hard_master_lo:byte
  31.     extrn    _hard_master_hi:byte
  32.     extrn    _hard_slave_lo:byte
  33.     extrn    _hard_slave_hi:byte
  34.     extrn    _mtype:byte
  35.  
  36.     extrn    _vcpi_installed:byte    ;VCPI Installed set this not Zero
  37.     extrn    _vcpi_entry:fword
  38.     extrn    _abs_client:dword
  39.     extrn    _DPMIsp:word
  40.     extrn    _saved_interrupt_vector:dword
  41.  
  42.     end_data16
  43.     start_bss
  44.  
  45.     public    _dr
  46. _dr    label    dword
  47. _dr0    dd    ?
  48. _dr1    dd    ?
  49. _dr2    dd    ?
  50. _dr3    dd    ?
  51.     dd    ?
  52.     dd    ?
  53. _dr6    dd    ?
  54. _dr7    dd    ?
  55.  
  56.     public    _c_tss, _a_tss, _o_tss, _f_tss
  57. _c_tss    label    tss_s    ; for "real mode" state
  58.     db    type tss_s dup (?)
  59. _a_tss    label    tss_s    ; for running program
  60.     db    type tss_s dup (?)
  61. _o_tss    label    tss_s    ; for convenience functions
  62.     db    type tss_s dup (?)
  63. _f_tss    label    tss_s    ; for page handling
  64.     db    type tss_s dup (?)
  65.  
  66.     public    _was_exception
  67. _was_exception    db    ?        ; exceptions set this to 1
  68.  
  69.     end_bss
  70.  
  71. ;------------------------------------------------------------------------
  72.  
  73.     start_code16
  74.  
  75.     extrn    _xms_local_enable_a20:near
  76.     extrn    _xms_local_disable_a20:near
  77.  
  78. real_stack    dd    ?
  79. real_idt    dw    03ffh, 0000h, 0000h
  80.  
  81.     public    _go32
  82. _go32    proc    near
  83.     push    si
  84.     push    di
  85.     push    bx
  86. _go32_1:
  87. ;    push    0b000h                ;dbg
  88. ;    pop    fs                ;dbg
  89. ;    mov    word ptr fs:[0f01h],07h        ;dbg - normal
  90.     mov    ax,DGROUP            ; Compute physical offset
  91.     xor    dx,dx                ; of tss_ptr
  92.     shld    dx,ax,4                ; Seg * 16
  93.     shl    ax,4
  94.     add    ax,_tss_ptr            ; plus tss_ptr
  95.     adc    dx,0
  96.     mov    _gdt[g_atss].base0,ax            ; Trick here - make atss
  97.     mov    _gdt[g_atss].base1,dl            ; selector point to
  98.     mov    _gdt[g_atss].base2,dh            ; tss_ptr (jmpt g_atss)
  99.  
  100.  
  101.     mov    al,0fdh                    ; clear busy flag
  102.     and    byte ptr _gdt[g_atss].stype,al
  103.     and    byte ptr _gdt[g_ctss].stype,al        ; non-VCPI LDTR below
  104.  
  105.     mov    _was_exception,0
  106.  
  107. ; set real_stack for return from _go32
  108.     mov    word ptr cs:real_stack,sp
  109.     mov    word ptr cs:real_stack+2,ss
  110.     movzx    esp,sp                ; make sure it's OK
  111.  
  112.     cli
  113.  
  114. ;    call    set_a20
  115.     cmp    _vcpi_installed,0
  116.     je    short real_to_protect        ;Not VCPI Mode
  117.     mov    esi,_abs_client
  118.     mov    ax,VCPI_MODE_CHANGE
  119.     int    VCPI_REQ            ;Change Protect Mode
  120. ;end_loop0:
  121. ;    jmp    short end_loop0            ;Never Come here!! Safety Loop
  122.  
  123. real_to_protect:
  124.     or    _gdt[g_rdata].lim1,40h        ;Set the big bit (non-vcpi only)
  125.     lgdt    fword ptr _gdt_phys
  126.     lidt    fword ptr _idt_phys
  127.  
  128.     mov    eax,cr0
  129.     or    al,1
  130.     mov    cr0,eax                ; we're in protected mode!
  131.     db    0eah                ; far jmp
  132.     dw    offset go_protect_far_jump
  133.     dw    g_rcode
  134. ;
  135. ;    Entry Protect Mode
  136. ;
  137.     public    _protect_entry
  138. _protect_entry    label    near
  139.  
  140. go_protect_far_jump:
  141.     cli
  142.     mov    ax,g_rdata
  143.     mov    ds,ax
  144.     mov    es,ax
  145.     mov    fs,ax
  146.     mov    gs,ax
  147.     mov    ss,ax
  148.     mov    sp,word ptr cs:real_stack    ;Need VCPI Inialize
  149.     xor    eax,eax
  150.     mov    cr2,eax         ;zero so we can tell INT 0E from page fault
  151.  
  152.     mov    eax,_dr0
  153.     mov    dr0,eax
  154.     mov    eax,_dr1
  155.     mov    dr1,eax
  156.     mov    eax,_dr2
  157.     mov    dr2,eax
  158.     mov    eax,_dr3
  159.     mov    dr3,eax
  160.     mov    eax,_dr6
  161.     mov    dr6,eax
  162.     mov    eax,_dr7
  163.     mov    dr7,eax
  164.  
  165.     cmp    _vcpi_installed,0
  166.     jne    short no_tss_load        ;Now Paging Mode in VCPI
  167.     mov    bx,_tss_ptr
  168.     mov    eax,[bx].tss_cr3
  169.     or    eax,eax                ;Test for zero
  170.     je    short set_paging_far_jump
  171.     mov    cr3,eax
  172.     mov    eax,cr0
  173.     or    eax,80000000h
  174.     mov    cr0,eax                ; paging enabled!
  175.     db    0eah                ; far jmp
  176.     dw    offset set_paging_far_jump
  177.     dw    g_rcode
  178. set_paging_far_jump:
  179.     mov    ax,g_ctss
  180.     ltr    ax
  181. no_tss_load:
  182.     jmpt    g_atss                ; load state from VCPU
  183.  
  184. _go32    endp
  185.  
  186. ; _go_real_mode must follow the task jump, so a task jump to return
  187. ; is valid
  188.  
  189.     public    _go_real_mode
  190. _go_real_mode    proc    near
  191.  
  192.     mov    eax,dr6
  193.     mov    _dr6,eax
  194.  
  195.     cmp    _vcpi_installed,0
  196.     je    short protect_to_real
  197.  
  198. ;Make VCPI call to return to real
  199.     clts                ;TS Clear
  200.     mov    eax,DGROUP
  201.     push    eax            ;GS
  202.     push    eax            ;FS
  203.     push    eax            ;DS
  204.     push    eax            ;ES
  205.     push    eax            ;SS
  206.     movzx    eax,word ptr cs:real_stack
  207.     push    eax            ;ESP
  208.     pushfd                ;EFLAGS
  209.     mov    ax,_TEXT        ;high word still zero
  210.     push    eax            ;CS
  211.     mov    ax,offset back_to_v86    ;high word still zero
  212.     push    eax            ;EIP
  213.     movzx    esp,sp
  214.  
  215.     mov    ax,g_core
  216.     mov    ds,ax
  217.     mov    ax,VCPI_MODE_CHANGE
  218.     assume    es:DGROUP
  219.     call    fword ptr es:_vcpi_entry
  220. ;end_loop1:
  221. ;    jmp    short end_loop1        ;Never Come here!! Safety Loop
  222.  
  223. protect_to_real:
  224.     and    _gdt[g_rdata].lim1,0bfh        ;Clear the big bit (non-vcpi only)
  225.     push    ss
  226.     pop    ss                ;Reload
  227.     mov    eax,cr0
  228.     and    eax,07ffffff6h ; clear PE, TS, PG
  229.     mov    cr0,eax
  230.  
  231.     db    0eah                ; far jmp
  232.     dw    offset back_to_real_far_jump
  233.     dw    _TEXT
  234. ;
  235. ;    Entry Real Mode
  236. ;
  237. back_to_real_far_jump:
  238.  
  239.     lidt    fword ptr cs:real_idt
  240.     lss    sp,cs:real_stack
  241. back_to_v86:
  242.  
  243.     mov    ax,ss
  244.     mov    ds,ax
  245.     mov    es,ax
  246.     mov    fs,ax
  247.     mov    gs,ax
  248.  
  249. ;    call    _reset_a20
  250.  
  251.     cmp    _was_exception,0
  252.     je    short not_hard
  253.  
  254.     mov    bx,_tss_ptr
  255.     mov    al,[bx].tss_irqn
  256.  
  257. ;    push    0b000h                ;dbg
  258. ;    pop    fs                ;dbg
  259. ;    mov    ah, 70h                ;dbg - reverse
  260. ;    mov    word ptr fs:[0f00h],ax        ;dbg
  261.  
  262.     mov    bx,16                ;pseudo IRQ
  263.     cmp    al,1ch
  264.     je    short is_hard_1
  265.     xor    bx,bx                ;IRQ base
  266.     cmp    al,_hard_master_lo
  267.     jb    short try_slavepic
  268.     cmp    al,_hard_master_hi
  269.     jbe    short is_hard
  270. try_slavepic:
  271.     mov    bl,8                ;IRQ base
  272.     cmp    al,_hard_slave_lo
  273.     jb    short not_hard
  274.     cmp    al,_hard_slave_hi
  275.     ja    short not_hard
  276.  
  277. is_hard:
  278. ;    mov    cl,_hard_slave_lo
  279. ;    add    cl,5
  280. ;    cmp    al,cl
  281. ;    je    short not_hard        ; for NPX errors
  282.  
  283. ;    mov    cl,_hard_master_lo
  284. ;    inc    cl
  285. ;    cmp    al,cl
  286. ;    je    short not_hard        ; to check for ^C
  287.  
  288.     mov    ah,al
  289.     and    ah,7            ; IRQ offset
  290.     add    bl,ah            ; IRQ #
  291. is_hard_1:
  292.     shl    bx,2
  293.     add    bx,offset _saved_interrupt_vector    ;ES is already DS
  294.     cmp    word ptr [bx+2],0
  295.     jne    short redirect
  296.  
  297.     push    0            ; Not redirected, use interrupt table
  298.     pop    es
  299.     movzx    bx,al
  300.     shl    bx,2            ; 4 bytes per interrupt entry
  301. redirect:
  302.     push    _DPMIsp            ; Needed for RMCB's to be recursive
  303.     mov    _DPMIsp,sp
  304.     sub    _DPMIsp,spare_stack
  305.     push    3002h
  306.     call    dword ptr es:[bx]        ; Really an interrupt
  307.     pop    _DPMIsp
  308.     jmp    _go32_1
  309.  
  310. not_hard:
  311.     pop    bx
  312.     pop    di
  313.     pop    si
  314.     ret
  315.  
  316. _go_real_mode    endp
  317.  
  318. ;------------------------------------------------------------------------
  319.     public    _reset_a20
  320. _reset_a20    proc    near
  321.     cmp    _vcpi_installed,0
  322.     jne    short reset_a20_nop
  323.     cmp    _use_xms,0
  324.     je    short reset_a20_local
  325.     call    _xms_local_disable_a20
  326. reset_a20_nop:
  327.     ret
  328.  
  329. reset_a20_local:
  330.     cmp    _mtype,0    ; PC98 raw mode (640K only)
  331.     jne    short reset_a20_nop
  332.     in    al,092h        ; 092h PS/2 & clone system control port "A"
  333.     and    al,not 2    ; this resets the A20 bit in register al
  334.     jmp    short $+2    ; forget the instruction fetch
  335.     out    092h,al        ; set the A20 bit off
  336.     ret
  337. _reset_a20    endp
  338.  
  339.     public    _set_a20
  340. _set_a20 proc    near
  341.     cmp    _vcpi_installed,0
  342.     jne    short set_a20_nop
  343.     cmp    _use_xms,0
  344.     je    short set_a20_local
  345.     call    _xms_local_enable_a20
  346. set_a20_nop:
  347.     ret
  348.  
  349. set_a20_local:
  350.     cmp    _mtype,0
  351.     jne    short set_a20_nop
  352.     pushf
  353.     cli
  354.  
  355.     in    al,092h        ; 092h PS/2 & clone system control port "A"
  356.     or    al,2        ; this sets the A20 bit in register al
  357.     jmp    short $+2    ; forget the instruction fetch
  358.     out    092h,al        ; set the A20 bit on
  359.  
  360.     call    check_a20
  361.     jz    short a20_done
  362.  
  363. need_to_set_a20:
  364.     call    waitkb
  365.     mov    al,0d1h
  366.     out    64h,al
  367.     call    waitkb
  368.     mov    al,0dfh        ; Patrick
  369.     out    60h,al
  370.     call    waitkb
  371.     mov    al,0ffh        ; Patrick
  372.     out    64h,al        ; Patrick
  373.     call    waitkb        ; Patrick
  374.  
  375. wait_for_valid_a20:
  376.     call    check_a20
  377.     jnz    short wait_for_valid_a20
  378. a20_done:
  379.     popf
  380.     ret
  381.  
  382. ; interrupts disabled, ax, dx, fs, gs destroyed, returns z bit if a20 enabled
  383. check_a20:
  384.     push    bx
  385.     xor    ax,ax        ; zero it
  386.     mov    fs,ax
  387.     dec    ax        ; ax = 0ffffh
  388.     mov    gs,ax
  389.     xor    bx,bx
  390.  
  391.     mov    ax,fs:[bx]    ; word from 0:0 (int 0 interrupt)
  392.     mov    dx,ax        ; save it
  393.     not    ax        ; make a different value
  394.     xchg    ax,gs:[bx+10h]    ; modify ffff:10h to known different value
  395.     xchg    cx,fs:[bx]    ; get fs:[0] with a write
  396.     cmp    dx,cx        ; compare 0:0 with saved; z bit if same = a20
  397.     mov    gs:[bx+10h],ax    ; restore
  398.     mov    fs:[bx],dx
  399.  
  400.     pop    bx
  401.     ret
  402.  
  403. waitkb:
  404.     xor    cx,cx        ; zero it
  405. waitkb1:
  406.         jmp    short $+2
  407.         jcxz    short $+2
  408.     in    al,64h
  409.     test    al,2
  410.     loopnz    waitkb1
  411.     ret
  412. _set_a20 endp
  413.  
  414. ;------------------------------------------------------------------------
  415.  
  416.     public    _cpumode    ; 0=real mode, 1=V86
  417. _cpumode:
  418.     smsw    ax
  419.     and    ax,1
  420.     ret
  421.  
  422. ;------------------------------------------------------------------------
  423. ; Determination of Cpu type.  EAX, EBX, ECX, EDX destroyed.
  424. ;    0  for 8086/80186
  425. ;    2  for 80286
  426. ;    3  for 386
  427. ;    4  for 486
  428. ;    5  for 586 (Pentium) or better (thanks, Morten!)
  429.  
  430. cpuid    macro
  431.     db    0fh,0a2h
  432.     endm
  433.  
  434.     public    _cputype    ; from Intel 80486 reference manual
  435. _cputype:
  436.     xor    cx,cx        ; default type is 8086
  437.     pushf
  438.     pop    bx
  439.     and    bh,0fh
  440.     push    bx
  441.     popf
  442.     pushf
  443.     pop    ax
  444.     and    ax,0f000h
  445.     cmp    ax,0f000h
  446.     jz    short cpu8086
  447.     or    bh,0f0h
  448.     push    bx
  449.     popf
  450.     pushf
  451.     pop    ax
  452.     and    ax,0f000h
  453.     jz    short cpu286
  454.  
  455.     mov    dx,sp        ; Save old SP
  456.     and    sp,not 3    ; Align it! (we will set AC flag)
  457.     mov    al,18        ; AC flag number
  458.     call    cpuflipflag
  459.     mov    sp,dx
  460.     jnc    short cpu386
  461.     mov    al,21        ; ID flag number
  462.     call    cpuflipflag
  463.     jnc    short cpu486
  464.  
  465. ;The cpu supports the CPUID instruction.  Maybe Pentium or late 486?
  466.     xor    eax,eax
  467.     cpuid            ; ebx:edx:ecx = vendor id; eax = max support
  468.     or    eax,eax
  469.     mov    al,5
  470.     jz    short cpu_pentium
  471.     xor    eax,eax
  472.     inc    ax        ; call with eax = 1
  473.     cpuid            ; edx=features; ah&0f = family; al=model/step
  474.     mov    al,ah
  475. cpu_pentium:
  476.     and    ax,0fh
  477.     ret    
  478. cpu486:
  479.     inc    cx
  480. cpu386:
  481.     inc    cx
  482. cpu286:
  483.     inc    cx
  484.     inc    cx
  485. cpu8086:                ; or 186
  486.     mov    ax,cx
  487.     ret
  488.  
  489. cpuflipflag:        ; Try to flip flag #Al in Eflags, Return C=1 if possible
  490.     push    si    ; This plus the pushed ret address still stack aligned
  491.     movzx    esi,al
  492.     pushfd
  493.     pop    eax
  494.     mov    ebx,eax
  495.     btc    eax,esi
  496.     push    eax
  497.     popfd
  498.     pushfd
  499.     pop    eax
  500.     xor    eax,ebx
  501.     push    ebx
  502.     popfd
  503.     bt    eax,esi
  504.     pop    si
  505.     ret
  506. ;------------------------------------------------------------------------
  507.  
  508.     end_code16
  509.  
  510.     end
  511.