initial commit
[fifth.git] / emulator / system.inc
1 ; part of virtual processor, emulator for FIFTH.\r
2 \r
3 system_init:\r
4         mov     ax,7202h\r
5         push    ax\r
6         popf\r
7         pushf\r
8         pop     bx\r
9         cmp     ax,bx\r
10         je      processor_ok\r
11         mov     dx, badcpu\r
12         mov     ah,9\r
13         int     21h\r
14         mov     ah,4Ch\r
15         int     21h\r
16         badcpu db 'required 80386 or better',24h\r
17 processor_ok:\r
18         smsw    ax\r
19         test    al,1\r
20         jz      mode_ok\r
21         mov     dx, badmode\r
22         mov     ah,9\r
23         int     21h\r
24         mov     ah,4Ch\r
25         int     21h\r
26         badmode db 'error: CPU in protected mode',24h\r
27 mode_ok:\r
28         mov     ax,4300h                ; check for XMS\r
29         int     2Fh\r
30         cmp     al,80h                  ; XMS present?\r
31         je      xms_ok\r
32         mov     dx, badxms\r
33         mov     ah,9\r
34         int     21h\r
35         jmp     system_exit\r
36         badxms db 'error: HIMEM.SYS not loaded',24h\r
37 xms_ok:\r
38         mov     ax,350Dh\r
39         int     21h\r
40         mov     word [irq_5],bx\r
41         mov     word [irq_5+2],es\r
42         push    cs\r
43         pop     es\r
44         mov     ax,250Dh\r
45         mov     dx,int_13\r
46         int     21h\r
47 \r
48         push    es\r
49         mov     ax,4310h                ; get XMS driver address\r
50         int     2Fh\r
51         mov     word [xms_call],bx      ; store XMS driver address\r
52         mov     word [xms_call+2],es\r
53         pop     es\r
54         mov     ah,3                    ; enable A20\r
55         call    far dword [xms_call]\r
56         mov     ah,8                    ; get free extended memory size\r
57         xor     bl,bl\r
58         call    far dword [xms_call]\r
59         or      bl,bl\r
60         mov     dx,ax\r
61         movzx   eax,ax\r
62         shl     eax,10\r
63         mov     ah,9                    ; allocate largest memory block\r
64         call    far dword [xms_call]\r
65         mov     [xms_handle],dx\r
66         mov     ah,0Ch                  ; lock extended memory block\r
67         call    far dword [xms_call]\r
68         shl     edx,16\r
69         mov     dx,bx\r
70         mov     [xms_addr],edx          ; store memory block address\r
71         ret\r
72 \r
73 \r
74 system_exit:\r
75         cmp     [xms_handle],0\r
76         je      sys_exit\r
77         mov     ah, 0dh                 ; unlock extended memory block\r
78         mov     dx, [xms_handle]\r
79         call    far dword [xms_call]\r
80         mov     ah, 0ah                 ; free extended memory block\r
81         call    far dword [xms_call]\r
82 sys_exit:\r
83         mov     ax, 250dh\r
84         mov     dx, word [irq_5]\r
85         mov     ds, word [irq_5+2]\r
86         int     21h\r
87         pop     ax\r
88         mov     ah, 4ch\r
89         int     21h\r
90 \r
91 int_13: push    eax\r
92         mov     al, 00001011b           ; OCW3 - read IRQ in-service register\r
93         out     20h, al\r
94         in      al, 20h\r
95         test    al, 00100000b           ; is IRQ 5 in service?\r
96         jz      exception\r
97         pop     eax\r
98         jmp     dword 0:0\r
99         label   irq_5 dword at $-4\r
100 exception:\r
101         push    ds es fs gs\r
102         cli                             ; disable interrupts\r
103         xor     eax, eax                ; calculate linear address of GDT\r
104         mov     ax, cs\r
105         shl     eax, 4\r
106         add     eax, GDT\r
107         mov     dword [cs:GDTR+2],eax\r
108         lgdt    pword [cs:GDTR]         ; load GDT register\r
109         mov     eax, cr0                ; switch to protected mode\r
110         or      al, 1\r
111         mov     cr0, eax\r
112         jmp     pm_start\r
113     pm_start:\r
114         mov     ax, 1 shl 3             ; load 32-bit data descriptor\r
115         mov     ds, ax                  ; to all data segment registers\r
116         mov     es, ax\r
117         mov     fs, ax\r
118         mov     gs, ax\r
119         mov     eax, cr0                ; switch back to real mode\r
120         and     al, not 1\r
121         mov     cr0, eax\r
122         jmp     pm_end\r
123     pm_end:\r
124         sti                             ; enable interrupts\r
125         pop     gs fs es ds\r
126         pop     eax\r
127         iret\r
128 \r
129 GDTR dw 2*8-1                           ; limit of GDT\r
130      dd ?                               ; linear address of GDT\r
131 \r
132 GDT rw 4                                ; null descriptor\r
133     dw 0FFFFh, 0, 9200h, 8Fh            ; 32-bit data descriptor\r
134 \r
135 xms_call dd 0                           ; XMS driver pointer\r
136 xms_handle dw 0                         ; handle of XMS memory block\r
137 xms_addr dd 0                           ; address to XMS block\r