Subversion Repositories Kolibri OS

Rev

Rev 2167 | Rev 2384 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 2288 $
9
 
10
; Virtual-8086 mode manager
11
; diamond, 2007, 2008
12
 
13
DEBUG_SHOW_IO = 0
14
 
15
struc V86_machine
16
{
17
; page directory
18
        .pagedir dd     ?
19
; translation table: V86 address -> flat linear address
20
        .pages  dd      ?
21
; mutex to protect all data from writing by multiple threads at one time
22
        .mutex  dd      ?
23
; i/o permission map
24
        .iopm   dd      ?
25
.size = $
26
}
27
virtual at 0
28
V86_machine V86_machine
29
end virtual
30
 
31
; Create V86 machine
32
; in: nothing
33
; out: eax = handle (pointer to struc V86_machine)
34
;      eax = NULL => failure
35
; destroys: ebx, ecx, edx (due to malloc)
36
v86_create:
37
; allocate V86_machine structure
38
        mov     eax, V86_machine.size
39
        call    malloc
40
        test    eax, eax
41
        jz      .fail
42
; initialize mutex
43
        and     dword [eax+V86_machine.mutex], 0
44
; allocate tables
45
        mov     ebx, eax
46
; We allocate 4 pages.
47
; First is main page directory for V86 mode.
48
; Second page:
49
; first half (0x800 bytes) is page table for addresses 0 - 0x100000,
50
; second half is for V86-to-linear translation.
51
; Third and fourth are for I/O permission map.
52
        push    8000h           ; blocks less than 8 pages are discontinuous
53
        call    kernel_alloc
54
        test    eax, eax
55
        jz      .fail2
56
        mov     [ebx+V86_machine.pagedir], eax
57
        push    edi eax
58
        mov     edi, eax
59
        add     eax, 1800h
60
        mov     [ebx+V86_machine.pages], eax
61
; initialize tables
62
        mov     ecx, 2000h/4
63
        xor     eax, eax
64
        rep stosd
65
        mov     [ebx+V86_machine.iopm], edi
66
        dec     eax
67
        mov     ecx, 2000h/4
68
        rep stosd
69
        pop     eax
70
; page directory: first entry is page table...
71
        mov     edi, eax
72
        add     eax, 1000h
73
        push    eax
74
        call    get_pg_addr
75
        or      al, PG_UW
76
        stosd
77
; ...and also copy system page tables
78
; thx to Serge, system is located at high addresses
79
        add     edi, (OS_BASE shr 20) - 4
80
        push    esi
81
        mov     esi, (OS_BASE shr 20) + sys_pgdir
82
        mov     ecx, 0x80000000 shr 22
83
        rep movsd
84
 
85
        mov     eax, [ebx+V86_machine.pagedir]   ;root dir also is
86
        call    get_pg_addr                      ;used as page table
87
        or      al, PG_SW
88
        mov     [edi-4096+(page_tabs shr 20)], eax
89
 
90
        pop     esi
91
; now V86 specific: initialize known addresses in first Mb
92
        pop     eax
93
; first page - BIOS data (shared between all machines!)
94
; physical address = 0
95
; linear address = OS_BASE
96
        mov     dword [eax], 111b
97
        mov     dword [eax+800h], OS_BASE
98
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
99
; physical address = 0x9C000
100
; linear address = 0x8009C000
101
; (I have seen one computer with EBDA segment = 0x9D80,
102
; all other computers use less memory)
103
        mov     ecx, 4
104
        mov     edx, 0x9C000
105
        push    eax
106
        lea     edi, [eax+0x9C*4]
107
@@:
108
        lea     eax, [edx + OS_BASE]
109
        mov     [edi+800h], eax
110
        lea     eax, [edx + 111b]
111
        stosd
112
        add     edx, 0x1000
113
        loop    @b
114
        pop     eax
115
        pop     edi
116
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
117
; physical address = 0xC0000
118
; linear address = 0x800C0000
119
        mov     ecx, 0xC0
120
@@:
121
        mov     edx, ecx
122
        shl     edx, 12
123
        push    edx
124
        or      edx, 111b
125
        mov     [eax+ecx*4], edx
126
        pop     edx
127
        add     edx, OS_BASE
128
        mov     [eax+ecx*4+0x800], edx
129
        inc     cl
130
        jnz     @b
131
        mov     eax, ebx
132
        ret
133
.fail2:
134
        mov     eax, ebx
135
        call    free
136
.fail:
137
        xor     eax, eax
138
        ret
139
 
140
; Destroy V86 machine
141
; in: eax = handle
142
; out: nothing
143
; destroys: eax, ebx, ecx, edx (due to free)
144
v86_destroy:
145
        push    eax
146
        stdcall kernel_free, [eax+V86_machine.pagedir]
147
        pop     eax
148
        jmp     free
149
 
150
; Translate V86-address to linear address
151
; in: eax=V86 address
152
;     esi=handle
153
; out: eax=linear address
154
; destroys: nothing
155
v86_get_lin_addr:
156
        push    ecx edx
157
        mov     ecx, eax
158
        mov     edx, [esi+V86_machine.pages]
159
        shr     ecx, 12
160
        and     eax, 0xFFF
161
        add     eax, [edx+ecx*4]        ; atomic operation, no mutex needed
162
        pop     edx ecx
163
        ret
164
 
165
; Sets linear address for V86-page
166
; in: eax=linear address (must be page-aligned)
167
;     ecx=V86 page (NOT address!)
168
;     esi=handle
169
; out: nothing
170
; destroys: nothing
171
v86_set_page:
172
        push    eax ebx
173
        mov     ebx, [esi+V86_machine.pagedir]
174
        mov     [ebx+ecx*4+0x1800], eax
175
        call    get_pg_addr
176
        or      al, 111b
177
        mov     [ebx+ecx*4+0x1000], eax
178
        pop     ebx eax
179
        ret
180
 
181
; Allocate memory in V86 machine
182
; in: eax=size (in bytes)
183
;     esi=handle
184
; out: eax=V86 address, para-aligned (0x10 multiple)
185
; destroys: nothing
186
; недописана!!!
187
;v86_alloc:
188
;        push    ebx ecx edx edi
189
;        lea     ebx, [esi+V86_machine.mutex]
190
;        call    wait_mutex
191
;        add     eax, 0x1F
192
;        shr     eax, 4
193
;        mov     ebx, 0x1000  ; start with address 0x1000 (second page)
194
;        mov     edi, [esi+V86_machine.tables]
195
;.l:
196
;        mov     ecx, ebx
197
;        shr     ecx, 12
198
;        mov     edx, [edi+0x1000+ecx*4] ; get linear address
199
;        test    edx, edx                ; page allocated?
200
;        jz      .unalloc
201
;        mov     ecx, ebx
202
;        and     ecx, 0xFFF
203
;        add     edx, ecx
204
;        cmp     dword [edx], 0          ; free block?
205
;        jnz     .n
206
;        cmp     dword [edx+4],
207
;        and     [esi+V86_machine.mutex], 0
208
;        pop     edi edx ecx ebx
209
;        ret
210
 
211
uglobal
212
sys_v86_machine dd      ?
213
endg
214
 
215
; Called from kernel.asm at first stages of loading
216
; Initialize system V86 machine (used to simulate BIOS int 13h)
217
init_sys_v86:
218
        call    v86_create
219
        mov     [sys_v86_machine], eax
220
        test    eax, eax
221
        jz      .ret
222
        mov     byte [OS_BASE + 0x500], 0xCD
223
        mov     byte [OS_BASE + 0x501], 0x13
224
        mov     byte [OS_BASE + 0x502], 0xF4
225
        mov     byte [OS_BASE + 0x503], 0xCD
226
        mov     byte [OS_BASE + 0x504], 0x10
227
        mov     byte [OS_BASE + 0x505], 0xF4
228
        mov     esi, eax
229
        mov     ebx, [eax+V86_machine.pagedir]
230
; one page for stack, two pages for results (0x2000 bytes = 16 sectors)
231
        mov     dword [ebx+0x99*4+0x1000], 0x99000 or 111b
232
        mov     dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000
233
        mov     dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b
234
        mov     dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000
235
        mov     dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b
236
        mov     dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000
237
if ~DEBUG_SHOW_IO
238
; allow access to all ports
239
        mov     ecx, [esi+V86_machine.iopm]
240
        xor     eax, eax
241
        mov     edi, ecx
242
        mov     ecx, 10000h/8/4
243
        rep stosd
244
end if
245
.ret:
246
        ret
247
 
248
struc v86_regs
249
{
250
; don't change the order, it is important
251
        .edi    dd      ?
252
        .esi    dd      ?
253
        .ebp    dd      ?
254
                dd      ?       ; ignored
255
        .ebx    dd      ?
256
        .edx    dd      ?
257
        .ecx    dd      ?
258
        .eax    dd      ?
259
        .eip    dd      ?
260
        .cs     dd      ?
261
        .eflags dd      ?       ; VM flag must be set!
262
        .esp    dd      ?
263
        .ss     dd      ?
264
        .es     dd      ?
265
        .ds     dd      ?
266
        .fs     dd      ?
267
        .gs     dd      ?
268
.size = $
269