Subversion Repositories Kolibri OS

Rev

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

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