Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4429 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2007-2012. All rights reserved. ;;
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
 
15
struct  V86_machine
16
; page directory
4993 Serge 17
        process         dd ?
4429 Serge 18
; mutex to protect all data from writing by multiple threads at one time
19
        mutex           dd ?
20
; i/o permission map
21
        iopm            dd ?
22
ends
23
 
24
; Create V86 machine
25
; in: nothing
26
; out: eax = handle (pointer to struc V86_machine)
27
;      eax = NULL => failure
28
; destroys: ebx, ecx, edx (due to malloc)
29
v86_create:
30
; allocate V86_machine structure
31
        mov     eax, sizeof.V86_machine
32
        call    malloc
33
        test    eax, eax
34
        jz      .fail
35
; initialize mutex
36
        and     dword [eax+V86_machine.mutex], 0
37
; allocate tables
38
        mov     ebx, eax
4993 Serge 39
 
40
        stdcall create_process, 4096, OS_BASE, 4096
41
        test    eax, eax
42
        jz      .fail2
43
 
44
        mov     [eax+PROC.mem_used], 4096
45
        mov     [ebx+V86_machine.process], eax
46
 
47
        push    2000h
4429 Serge 48
        call    kernel_alloc
49
        test    eax, eax
50
        jz      .fail2
4993 Serge 51
 
52
        mov     [ebx+V86_machine.iopm], eax
53
 
54
 
55
; initialize tables
56
        push    edi
4429 Serge 57
        mov     edi, eax
4993 Serge 58
        mov     eax, -1
4429 Serge 59
        mov     ecx, 2000h/4
60
        rep stosd
61
 
4993 Serge 62
        mov     eax, [ebx+V86_machine.process]
63
        mov     eax, [eax+PROC.pdt_0_phys]
4429 Serge 64
 
4993 Serge 65
        pushfd
66
        cli
67
        mov     cr3, eax
68
 
69
 
4429 Serge 70
; now V86 specific: initialize known addresses in first Mb
4993 Serge 71
 
4429 Serge 72
; first page - BIOS data (shared between all machines!)
73
; physical address = 0
74
; linear address = OS_BASE
75
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
76
; physical address = 0x9C000
77
; linear address = 0x8009C000
78
; (I have seen one computer with EBDA segment = 0x9D80,
79
; all other computers use less memory)
4993 Serge 80
 
81
        mov     eax, PG_UW
82
        mov     [page_tabs], eax
83
        invlpg  [eax]
84
 
85
        mov     byte [0x500], 0xCD
86
        mov     byte [0x501], 0x13
87
        mov     byte [0x502], 0xF4
88
        mov     byte [0x503], 0xCD
89
        mov     byte [0x504], 0x10
90
        mov     byte [0x505], 0xF4
91
 
92
        mov     eax, 0x99000+PG_UW
93
        mov     edi, page_tabs+0x99*4
94
        mov     edx, 0x1000
95
        mov     ecx, 7
4429 Serge 96
@@:
97
        stosd
4993 Serge 98
        add     eax, edx
99
        loop @b
100
 
4429 Serge 101
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
102
; physical address = 0xC0000
4993 Serge 103
 
104
        mov     eax, 0xC0000+PG_UW
105
        mov     edi, page_tabs+0xC0*4
106
        mov     edx, 0x1000
107
        mov     ecx, 64
4429 Serge 108
@@:
4993 Serge 109
        stosd
110
        add     eax, edx
111
        loop @b
112
 
113
        mov     eax, sys_proc-OS_BASE+PROC.pdt_0
114
 
115
        mov     cr3, eax
116
        popfd
117
 
118
        pop     edi
119
 
4429 Serge 120
        mov     eax, ebx
121
        ret
122
.fail2:
123
        mov     eax, ebx
124
        call    free
125
.fail:
126
        xor     eax, eax
127
        ret
128
 
4993 Serge 129
;not used
4429 Serge 130
; Destroy V86 machine
131
; in: eax = handle
132
; out: nothing
133
; destroys: eax, ebx, ecx, edx (due to free)
4993 Serge 134
;v86_destroy:
135
;        push    eax
136
;        stdcall kernel_free, [eax+V86_machine.pagedir]
137
;        pop     eax
138
;        jmp     free
4429 Serge 139
 
140
; Translate V86-address to linear address
141
; in: eax=V86 address
142
;     esi=handle
143
; out: eax=linear address
144
; destroys: nothing
145
v86_get_lin_addr:
146
        push    ecx edx
147
        mov     ecx, eax
4993 Serge 148
        mov     edx, page_tabs
4429 Serge 149
        shr     ecx, 12
150
        and     eax, 0xFFF
151
        add     eax, [edx+ecx*4]        ; atomic operation, no mutex needed
152
        pop     edx ecx
153
        ret
154
 
4993 Serge 155
;not used
4429 Serge 156
; Sets linear address for V86-page
157
; in: eax=linear address (must be page-aligned)
158
;     ecx=V86 page (NOT address!)
159
;     esi=handle
160
; out: nothing
161
; destroys: nothing
4993 Serge 162
;v86_set_page:
163
;        push    eax ebx
164
;        mov     ebx, [esi+V86_machine.pagedir]
165
;        mov     [ebx+ecx*4+0x1800], eax
166
;        call    get_pg_addr
167
;        or      al, 111b
168
;        mov     [ebx+ecx*4+0x1000], eax
169
;        pop     ebx eax
170
;        ret
4429 Serge 171
 
172
; Allocate memory in V86 machine
173
; in: eax=size (in bytes)
174
;     esi=handle
175
; out: eax=V86 address, para-aligned (0x10 multiple)
176
; destroys: nothing
177
; недописана!!!
178
;v86_alloc:
179
;        push    ebx ecx edx edi
180
;        lea     ebx, [esi+V86_machine.mutex]
181
;        call    wait_mutex
182
;        add     eax, 0x1F
183
;        shr     eax, 4
184
;        mov     ebx, 0x1000  ; start with address 0x1000 (second page)
185
;        mov     edi, [esi+V86_machine.tables]
186
;.l:
187
;        mov     ecx, ebx
188
;        shr     ecx, 12
189
;        mov     edx, [edi+0x1000+ecx*4] ; get linear address
190
;        test    edx, edx                ; page allocated?
191
;        jz      .unalloc
192
;        mov     ecx, ebx
193
;        and     ecx, 0xFFF
194
;        add     edx, ecx
195
;        cmp     dword [edx], 0          ; free block?
196
;        jnz     .n
197
;        cmp     dword [edx+4],
198
;        and     [esi+V86_machine.mutex], 0
199
;        pop     edi edx ecx ebx
200
;        ret
201
 
202
uglobal
203
sys_v86_machine dd      ?
204
endg
205
 
206
; Called from kernel.asm at first stages of loading
207
; Initialize system V86 machine (used to simulate BIOS int 13h)
208
init_sys_v86:
209
        call    v86_create
210
        mov     [sys_v86_machine], eax
211
        test    eax, eax
212
        jz      .ret
213
        mov     esi, eax
214
if ~DEBUG_SHOW_IO
215
; allow access to all ports
216
        mov     ecx, [esi+V86_machine.iopm]
217
        xor     eax, eax
218
        mov     edi, ecx
219
        mov     ecx, 10000h/8/4
220
        rep stosd
221
end if
222
.ret:
223
        ret
224
 
225
struct  v86_regs
226
; don't change the order, it is important
227
        edi             dd ?
228
        esi             dd ?
229
        ebp             dd ?
230
                        dd ?    ; ignored
231
        ebx             dd ?
232
        edx             dd ?
233
        ecx             dd ?
234
        eax             dd ?
235
        eip             dd ?
236
        cs              dd ?
237
        eflags          dd ?    ; VM flag must be set!
238
        esp             dd ?
239
        ss              dd ?
240
        es              dd ?
241
        ds              dd ?
242
        fs              dd ?
243
        gs              dd ?
244
ends
245
 
246
; Run V86 machine
247
; in: ebx -> registers for V86 (two structures: in and out)
248
;     esi = handle
249
;     ecx = expected end address (CS:IP)
250
;     edx = IRQ to hook or -1 if not required
251
; out: structure pointed to by ebx is filled with new values
252
;     eax = 1 - exception has occured, cl contains code
253
;     eax = 2 - access to disabled i/o port, ecx contains port address
254
;     eax = 3 - IRQ is already hooked by another VM
255
; destroys: nothing
256
v86_start:
4993 Serge 257
 
258
        xchg bx, bx
259
 
4429 Serge 260
        pushad
261
 
262
        cli
263
 
264
        mov     ecx, [CURRENT_TASK]
265
        shl     ecx, 8
266
        add     ecx, SLOT_BASE
267
 
268
        mov     eax, [esi+V86_machine.iopm]
269
        call    get_pg_addr
270
        inc     eax
271
        push    dword [ecx+APPDATA.io_map]
272
        push    dword [ecx+APPDATA.io_map+4]
273
        mov     dword [ecx+APPDATA.io_map], eax
274
        mov     dword [page_tabs + (tss._io_map_0 shr 10)], eax
275
        add     eax, 0x1000
276
        mov     dword [ecx+APPDATA.io_map+4], eax
277
        mov     dword [page_tabs + (tss._io_map_1 shr 10)], eax
278
 
279
        push    [ecx+APPDATA.process]
280
        push    [ecx+APPDATA.saved_esp0]
281
        mov     [ecx+APPDATA.saved_esp0], esp
282
        mov     [tss._esp0], esp
283
 
4993 Serge 284
        mov     eax, [esi+V86_machine.process]
4429 Serge 285
        mov     [ecx+APPDATA.process], eax
4993 Serge 286
        mov     eax, [eax+PROC.pdt_0_phys]
287
        mov     cr3, eax
4429 Serge 288
 
289
; We do not enable interrupts, because V86 IRQ redirector assumes that
290
; machine is running
291
; They will be enabled by IRET.
292
;        sti
293
 
294
        mov     eax, esi
295
        sub     esp, sizeof.v86_regs
296
        mov     esi, ebx
297
        mov     edi, esp
298
        mov     ecx, sizeof.v86_regs/4
299
        rep movsd
300
 
301
        cmp     edx, -1
302
        jz      .noirqhook
303
uglobal
304
v86_irqhooks    rd      IRQ_RESERVED * 2
305
endg
306
        cmp     [v86_irqhooks+edx*8], 0
307
        jz      @f
308
        cmp     [v86_irqhooks+edx*8], eax
309
        jz      @f
310
        mov     esi, v86_irqerr
311
        call    sys_msg_board_str
312
        inc     [v86_irqhooks+edx*8+4]
313
        mov     eax, 3
314
        jmp     v86_exc_c.exit
315
@@:
316
        mov     [v86_irqhooks+edx*8], eax
317
        inc     [v86_irqhooks+edx*8+4]
318
.noirqhook:
319
 
320
        popad
321
        iretd
322
 
323
; It is only possible to leave virtual-8086 mode by faulting to
324
; a protected-mode interrupt handler (typically the general-protection
325
; exception handler, which in turn calls the virtual 8086-mode monitor).
326
 
327
iglobal
328
  v86_exc_str1  db      'V86 : unexpected exception ',0
329
  v86_exc_str2  db      ' at ',0
330
  v86_exc_str3  db      ':',0
331
  v86_exc_str4  db      13,10,'V86 : faulted code:',0
332
  v86_exc_str5  db      ' (unavailable)',0
333
  v86_newline   db      13,10,0
334
  v86_io_str1   db      'V86 : access to disabled i/o port ',0
335
  v86_io_byte   db      ' (byte)',13,10,0
336
  v86_io_word   db      ' (word)',13,10,0
337
  v86_io_dword  db      ' (dword)',13,10,0
338
  v86_irqerr    db      'V86 : IRQ already hooked',13,10,0
339
endg
340
 
341
v86_exc_c:
342
; Did we all that we have wanted to do?
343
        cmp     bl, 1
344
        jne     @f
345
        xor     eax, eax
346
        mov     dr6, eax
347
  @@:
348
        mov     eax, [esp+sizeof.v86_regs+10h+18h]
349
        cmp     word [esp+v86_regs.eip], ax
350
        jnz     @f
351
        shr     eax, 16
352
        cmp     word [esp+v86_regs.cs], ax
353
        jz      .done
354
@@:
355
; Various system events, which must be handled, result in #GP
356
        cmp     bl, 13
357
        jnz     .nogp
358
; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error
359
        cmp     word [esp+v86_regs.eip+2], 0
360
        jnz     .nogp
361
; Otherwise we can safely access byte at CS:IP
362
; (because it is #GP, not #PF handler)
363
; Если бы мы могли схлопотать исключение только из-за чтения байтов кода,
364
; мы бы его уже схлопотали и это было бы не #GP
365
        movzx   esi, word [esp+v86_regs.cs]
366
        shl     esi, 4
367
        add     esi, [esp+v86_regs.eip]
368
        lodsb
369
        cmp     al, 0xCD        ; int xx command = CD xx
370
        jz      .handle_int
371
        cmp     al, 0xCF
372
        jz      .handle_iret
373
        cmp     al, 0xF3
374
        jz      .handle_rep
375
        cmp     al, 0xEC
376
        jz      .handle_in
377
        cmp     al, 0xED
378
        jz      .handle_in_word
379
        cmp     al, 0xEE
380
        jz      .handle_out
381
        cmp     al, 0xEF
382
        jz      .handle_out_word
383
        cmp     al, 0xE4
384
        jz      .handle_in_imm
385
        cmp     al, 0xE6
386
        jz      .handle_out_imm
387
        cmp     al, 0x9C
388
        jz      .handle_pushf
389
        cmp     al, 0x9D
390
        jz      .handle_popf
391
        cmp     al, 0xFA
392
        jz      .handle_cli
393
        cmp     al, 0xFB
394
        jz      .handle_sti
395
        cmp     al, 0x66
396
        jz      .handle_66
397
        jmp     .nogp
398
.handle_int:
399
        cmp     word [esp+v86_regs.eip], 0xFFFF
400
        jae     .nogp
401
        xor     eax, eax
402
        lodsb
403
;        call    sys_msg_board_byte
404
; simulate INT command
405
; N.B. It is possible that some checks need to be corrected,
406
;      but at least in case of normal execution the code works.
407
.simulate_int:
408
        cmp     word [esp+v86_regs.esp], 6
409
        jae     @f
410
        mov     bl, 12          ; #SS exception
411
        jmp     .nogp
412
@@:
413
        movzx   edx, word [esp+v86_regs.ss]
414
        shl     edx, 4
415
        push    eax
416
        movzx   eax, word [esp+4+v86_regs.esp]
417
        sub     eax, 6
418
        add     edx, eax
419
        mov     eax, edx
420
        mov     esi, [esp+4+sizeof.v86_regs+10h+4]
421
        call    v86_get_lin_addr
422
        cmp     eax, 0x1000
423
        jae     @f
424
        mov     bl, 14          ; #PF exception
425
        jmp     .nogp
426
@@:
427
        lea     eax, [edx+5]
428
        call    v86_get_lin_addr
429
        cmp     eax, 0x1000
430
        jae     @f
431
        mov     bl, 14          ; #PF exception
432
        jmp     .nogp
433
@@:
434
        sub     word [esp+4+v86_regs.esp], 6
435
        mov     eax, [esp+4+v86_regs.eip]
436
        cmp     byte [esp+1], 0
437
        jnz     @f
438
        inc     eax
439
        inc     eax
440
@@:
441
        mov     word [edx], ax
442
        mov     eax, [esp+4+v86_regs.cs]
443
        mov     word [edx+2], ax
444
        mov     eax, [esp+4+v86_regs.eflags]
445
        mov     word [edx+4], ax
446
        pop     eax
447
        mov     ah, 0
448
        mov     cx, [eax*4]
449
        mov     word [esp+v86_regs.eip], cx
450
        mov     cx, [eax*4+2]
451
        mov     word [esp+v86_regs.cs], cx
452
; note that interrupts will be disabled globally at IRET
453
        and     byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags
454
; continue V86 execution
455
        popad
456
        iretd
457
.handle_iret:
458
        cmp     word [esp+v86_regs.esp], 0x10000 - 6
459
        jbe     @f
460
        mov     bl, 12
461
        jmp     .nogp
462
@@:
463
        movzx   edx, word [esp+v86_regs.ss]
464
        shl     edx, 4
465
        movzx   eax, word [esp+v86_regs.esp]
466
        add     edx, eax
467
        mov     eax, edx
468
        mov     esi, [esp+sizeof.v86_regs+10h+4]
469
        call    v86_get_lin_addr
470
        cmp     eax, 0x1000
471
        jae     @f
472
        mov     bl, 14
473
        jmp     .nogp
474
@@:
475
        lea     eax, [edx+5]
476
        call    v86_get_lin_addr
477
        cmp     eax, 0x1000
478
        jae     @f
479
        mov     bl, 14
480
        jmp     .nogp
481
@@:
482
        mov     ax, [edx]
483
        mov     word [esp+v86_regs.eip], ax
484
        mov     ax, [edx+2]
485
        mov     word [esp+v86_regs.cs], ax
486
        mov     ax, [edx+4]
487
        mov     word [esp+v86_regs.eflags], ax
488
        add     word [esp+v86_regs.esp], 6
489
        popad
490
        iretd
491
.handle_pushf:
492
        cmp     word [esp+v86_regs.esp], 1
493
        jnz     @f
494
        mov     bl, 12
495
        jmp     .nogp
496
@@:
497
        movzx   edx, word [esp+v86_regs.ss]
498
        shl     edx, 4
499
        mov     eax, [esp+v86_regs.esp]
500
        sub     eax, 2
501
        movzx   eax, ax
502
        add     edx, eax
503
        mov     eax, edx
504
        mov     esi, [esp+sizeof.v86_regs+10h+4]
505
        call    v86_get_lin_addr
506
        cmp     eax, 0x1000
507
        jae     @f
508
        mov     bl, 14          ; #PF exception
509
        jmp     .nogp
510
@@:
511
        lea     eax, [edx+1]
512
        call    v86_get_lin_addr
513
        cmp     eax, 0x1000
514
        jae     @f
515
        mov     bl, 14
516
        jmp     .nogp
517
@@:
518
        sub     word [esp+v86_regs.esp], 2
519
        mov     eax, [esp+v86_regs.eflags]
520
        mov     [edx], ax
521
        inc     word [esp+v86_regs.eip]
522
        popad
523
        iretd
524
.handle_pushfd:
525
        cmp     word [esp+v86_regs.esp], 4
526
        jae     @f
527
        mov     bl, 12          ; #SS exception
528
        jmp     .nogp
529
@@:
530
        movzx   edx, word [esp+v86_regs.ss]
531
        shl     edx, 4
532
        movzx   eax, word [esp+v86_regs.esp]
533
        sub     eax, 4
534
        add     edx, eax
535
        mov     eax, edx
536
        mov     esi, [esp+sizeof.v86_regs+10h+4]
537
        call    v86_get_lin_addr
538
        cmp     eax, 0x1000
539
        jae     @f
540
        mov     bl, 14          ; #PF exception
541
        jmp     .nogp
542
@@:
543
        lea     eax, [edx+3]
544
        call    v86_get_lin_addr
545
        cmp     eax, 0x1000
546
        jae     @f
547
        mov     bl, 14          ; #PF exception
548
        jmp     .nogp
549
@@:
550
        sub     word [esp+v86_regs.esp], 4
551
        movzx   eax, word [esp+v86_regs.eflags]
552
        mov     [edx], eax
553
        add     word [esp+v86_regs.eip], 2
554
        popad
555
        iretd
556
.handle_popf:
557
        cmp     word [esp+v86_regs.esp], 0xFFFF
558
        jnz     @f
559
        mov     bl, 12
560
        jmp     .nogp
561
@@:
562
        movzx   edx, word [esp+v86_regs.ss]
563
        shl     edx, 4
564
        movzx   eax, word [esp+v86_regs.esp]
565
        add     edx, eax
566
        mov     eax, edx
567
        mov     esi, [esp+sizeof.v86_regs+10h+4]
568
        call    v86_get_lin_addr
569
        cmp     eax, 0x1000
570
        jae     @f
571
        mov     bl, 14          ; #PF exception
572
        jmp     .nogp
573
@@:
574
        lea     eax, [edx+1]
575
        call    v86_get_lin_addr
576
        cmp     eax, 0x1000
577
        jae     @f
578
        mov     bl, 14
579
        jmp     .nogp
580
@@:
581
        mov     ax, [edx]
582
        mov     word [esp+v86_regs.eflags], ax
583
        add     word [esp+v86_regs.esp], 2
584
        inc     word [esp+v86_regs.eip]
585
        popad
586
        iretd
587
.handle_popfd:
588
        cmp     word [esp+v86_regs.esp], 0x10000 - 4
589
        jbe     @f
590
        mov     bl, 12
591
        jmp     .nogp
592
@@:
593
        movzx   edx, word [esp+v86_regs.ss]
594
        shl     edx, 4
595
        movzx   eax, word [esp+v86_regs.esp]
596
        add     edx, eax
597
        mov     eax, edx
598
        mov     esi, [esp+sizeof.v86_regs+10h+4]
599
        call    v86_get_lin_addr
600
        cmp     eax, 0x1000
601
        jae     @f
602
        mov     bl, 14
603
        jmp     .nogp
604
@@:
605
        lea     eax, [edx+3]
606
        call    v86_get_lin_addr
607
        cmp     eax, 0x1000
608
        jae     @f
609
        mov     bl, 14
610
        jmp     .nogp
611
@@:
612
        mov     eax, [edx]
613
        mov     word [esp+v86_regs.eflags], ax
614
        add     word [esp+v86_regs.esp], 4
615
        add     word [esp+v86_regs.eip], 2
616
        popad
617
        iretd
618
.handle_cli:
619
        and     byte [esp+v86_regs.eflags+1], not 2
620
        inc     word [esp+v86_regs.eip]
621
        popad
622
        iretd
623
.handle_sti:
624
        or      byte [esp+v86_regs.eflags+1], 2
625
        inc     word [esp+v86_regs.eip]
626
        popad
627
        iretd
628
.handle_rep:
629
        cmp     word [esp+v86_regs.eip], 0xFFFF
630
        jae     .nogp
631
        lodsb
632
        cmp     al, 6Eh
633
        jz      .handle_rep_outsb
634
        jmp     .nogp
635
.handle_rep_outsb:
636
.handle_in:
637
.handle_out:
638
.invalid_io_byte:
639
        movzx   ebx, word [esp+v86_regs.edx]
640
        mov     ecx, 1
641
        jmp     .invalid_io
642
.handle_in_imm:
643
.handle_out_imm:
644
        cmp     word [esp+v86_regs.eip], 0xFFFF
645
        jae     .nogp
646
        lodsb
647
        movzx   ebx, al
648
        mov     ecx, 1
649
        jmp     .invalid_io
650
.handle_66:
651
        cmp     word [esp+v86_regs.eip], 0xFFFF
652
        jae     .nogp
653
        lodsb
654
        cmp     al, 0x9C
655
        jz      .handle_pushfd
656
        cmp     al, 0x9D
657
        jz      .handle_popfd
658
        cmp     al, 0xEF
659
        jz      .handle_out_dword
660
        cmp     al, 0xED
661
        jz      .handle_in_dword
662
        jmp     .nogp
663
.handle_in_word:
664
.handle_out_word:
665
        movzx   ebx, word [esp+v86_regs.edx]
666
        mov     ecx, 2
667
        jmp     .invalid_io
668
.handle_in_dword:
669
.handle_out_dword:
670
.invalid_io_dword:
671
        movzx   ebx, word [esp+v86_regs.edx]
672
        mov     ecx, 4
673
.invalid_io:
674
        mov     esi, v86_io_str1
675
        call    sys_msg_board_str
676
        mov     eax, ebx
677
        call    sys_msg_board_dword
678
        mov     esi, v86_io_byte
679
        cmp     ecx, 1
680
        jz      @f
681
        mov     esi, v86_io_word
682
        cmp     ecx, 2
683
        jz      @f
684
        mov     esi, v86_io_dword
685
@@:
686
        call    sys_msg_board_str
687
if DEBUG_SHOW_IO
688
        mov     edx, ebx
689
        mov     ebx, 200
690
        call    delay_hs
691
        mov     esi, [esp+v86_regs.size+10h+4]
692
        mov     eax, [esi+V86_machine.iopm]
693
@@:
694
        btr     [eax], edx
695
        inc     edx
696
        loop    @b
697
        popad
698
        iretd
699
else
700
        mov     eax, 2
701
        jmp     .exit
702
end if
703
.nogp:
704
 
705
        mov     esi, v86_exc_str1
706
        call    sys_msg_board_str
707
        mov     al, bl
708
        call    sys_msg_board_byte
709
        mov     esi, v86_exc_str2
710
        call    sys_msg_board_str
711
        mov     ax, [esp+32+4]
712
        call    sys_msg_board_word
713
        mov     esi, v86_exc_str3
714
        call    sys_msg_board_str
715
        mov     ax, [esp+32]
716
        call    sys_msg_board_word
717
        mov     esi, v86_exc_str4
718
        call    sys_msg_board_str
719
        mov     ecx, 8
720
        movzx   edx, word [esp+32+4]
721
        shl     edx, 4
722
        add     edx, [esp+32]
723
@@:
724
        mov     esi, [esp+sizeof.v86_regs+10h+4]
725
        mov     eax, edx
726
        call    v86_get_lin_addr
727
        cmp     eax, 0x1000
728
        jb      .nopage
729
        mov     esi, v86_exc_str3-2
730
        call    sys_msg_board_str
731
        mov     al, [edx]
732
        call    sys_msg_board_byte
733
        inc     edx
734
        loop    @b
735
        jmp     @f
736
.nopage:
737
        mov     esi, v86_exc_str5
738
        call    sys_msg_board_str
739
@@:
740
        mov     esi, v86_newline
741
        call    sys_msg_board_str
742
        mov     eax, 1
743
        jmp     .exit
744
 
745
.done:
746
        xor     eax, eax
747
 
748
.exit:
749
        mov     [esp+sizeof.v86_regs+10h+1Ch], eax
750
        mov     [esp+sizeof.v86_regs+10h+18h], ebx
751
 
752
        mov     edx, [esp+sizeof.v86_regs+10h+14h]
753
        cmp     edx, -1
754
        jz      @f
755
        dec     [v86_irqhooks+edx*8+4]
756
        jnz     @f
757
        and     [v86_irqhooks+edx*8], 0
758
@@:
759
 
760
        mov     esi, esp
761
        mov     edi, [esi+sizeof.v86_regs+10h+10h]
762
        add     edi, sizeof.v86_regs
763
        mov     ecx, sizeof.v86_regs/4
764
        rep movsd
765
        mov     esp, esi
766
 
767
        cli
768
        mov     ecx, [CURRENT_TASK]
769
        shl     ecx, 8
770
        pop     eax
771
        mov     [SLOT_BASE+ecx+APPDATA.saved_esp0], eax
772
        mov     [tss._esp0], eax
773
        pop     eax
774
        mov     [SLOT_BASE+ecx+APPDATA.process], eax
775
        pop     ebx
776
        mov     dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx
777
        mov     dword [page_tabs + (tss._io_map_1 shr 10)], ebx
778
        pop     ebx
779
        mov     dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
780
        mov     dword [page_tabs + (tss._io_map_0 shr 10)], ebx
4993 Serge 781
        mov     eax, [eax+PROC.pdt_0_phys]
4429 Serge 782
        mov     cr3, eax
783
        sti
784
 
785
        popad
786
        ret
787
 
788
;my05:
789
;        mov     dx, 30C2h
790
;        mov     cx, 4
791
;.0:
792
;        in      al, dx
793
;        cmp     al, 0FFh
794
;        jz      @f
795
;        test    al, 4
796
;        jnz     .1
797
;@@:
798
;        add     dx, 8
799
;        in      al, dx
800
;        cmp     al, 0FFh
801
;        jz      @f
802
;        test    al, 4
803
;        jnz     .1
804
;@@:
805
;        loop    .0
806
;        ret
807
;.1:
808
;        or      al, 84h
809
;        out     dx, al
810
;.2:
811
;        mov     dx, 30F7h
812
;        in      al, dx
813
;        mov     byte [BOOT_VAR + 48Eh], 0FFh
814
;        ret
815
 
816
align 4
817
v86_irq:
818
; push irq/pushad/jmp v86_irq
819
; ebp = irq
820
        lea     esi, [esp+1Ch]
821
        lea     edi, [esi+4]
822
        mov     ecx, 8
823
        std
824
        rep movsd
825
        cld
826
        mov     edi, ebp
827
        pop     eax
828
v86_irq2:
829
        mov     esi, [v86_irqhooks+edi*8]       ; get VM handle
4993 Serge 830
        mov     eax, [esi+V86_machine.process]
4429 Serge 831
        mov     ecx, [CURRENT_TASK]
832
        shl     ecx, 8
833
        cmp     [SLOT_BASE+ecx+APPDATA.process], eax
834
        jnz     .notcurrent
835
        lea     eax, [edi+8]
836
        cmp     al, 10h
837
        mov     ah, 1
838
        jb      @f
839
        add     al, 60h
840
@@:
841
        jmp     v86_exc_c.simulate_int
842
.notcurrent:
843
        mov     ebx, SLOT_BASE + 0x100
844
        mov     ecx, [TASK_COUNT]
845
.scan:
846
        cmp     [ebx+APPDATA.process], eax
847
        jnz     .cont
848
        push    ecx
849
        mov     ecx, [ebx+APPDATA.saved_esp0]
850
        cmp     word [ecx-sizeof.v86_regs+v86_regs.esp], 6
851
        jb      .cont2
852
        movzx   edx, word [ecx-sizeof.v86_regs+v86_regs.ss]
853
        shl     edx, 4
854
        push    eax
855
        movzx   eax, word [ecx-sizeof.v86_regs+v86_regs.esp]
856
        sub     eax, 6
857
        add     edx, eax
858
        mov     eax, edx
859
        call    v86_get_lin_addr
860
        cmp     eax, 0x1000
861
        jb      .cont3
862
        lea     eax, [edx+5]
863
        call    v86_get_lin_addr
864
        cmp     eax, 0x1000
865
        jb      .cont3
866
        pop     eax
867
        pop     ecx
868
        jmp     .found
869
.cont3:
870
        pop     eax
871
.cont2:
872
        pop     ecx
873
.cont:
874
        add     ebx, 0x100
875
        loop    .scan
876
        mov     ecx, edi
877
        call    irq_eoi
878
        popad
879
        iretd
880
.found:
4993 Serge 881
        mov     eax, [eax+PROC.pdt_0_phys]
4429 Serge 882
        mov     cr3, eax
883
        mov     esi, [ebx+APPDATA.saved_esp0]
884
        sub     word [esi-sizeof.v86_regs+v86_regs.esp], 6
885
        mov     ecx, [esi-sizeof.v86_regs+v86_regs.eip]
886
        mov     word [edx], cx
887
        mov     ecx, [esi-sizeof.v86_regs+v86_regs.cs]
888
        mov     word [edx+2], cx
889
        mov     ecx, [esi-sizeof.v86_regs+v86_regs.eflags]
890
        mov     word [edx+4], cx
891
        lea     eax, [edi+8]
892
        cmp     al, 10h
893
        jb      @f
894
        add     al, 60h
895
@@:
896
        mov     cx, [eax*4]
897
        mov     word [esi-sizeof.v86_regs+v86_regs.eip], cx
898
        mov     cx, [eax*4+2]
899
        mov     word [esi-sizeof.v86_regs+v86_regs.cs], cx
900
        and     byte [esi-sizeof.v86_regs+v86_regs.eflags+1], not 3
901
        call    update_counters
902
        lea     edi, [ebx + 0x100000000 - SLOT_BASE]
903
        shr     edi, 3
904
        add     edi, CURRENT_TASK
905
        call    find_next_task.found
906
        call    do_change_task
907
        popad
908
        iretd
4923 Serge 909
 
910
align 4
911
 
912
v86_entry:
913
        xchg bx, bx
914
        mov     ebx, 100000
915
        call    delay_hs
916
        jmp     v86_entry
917
 
918
align 4
919
proc v86_init
920
       locals
921
         v86_slot      dd ?
922
         v86_cmdline   dd ? ;0x00
923
         v86_path      dd ? ;0x04
924
         v86_eip       dd ? ;0x08
925
         v86_esp       dd ? ;0x0C
926
         v86_mem       dd ? ;0x10
927
       endl
928
 
929
 
930
        xor     eax, eax
931
        mov     [v86_eip], v86_entry
932
        mov     [v86_cmdline], eax
933
        mov     [v86_esp], eax
934
        mov     [v86_path], eax
935
 
936
        call    lock_application_table
937
 
938
        call    alloc_thread_slot
939
        test    eax, eax
940
        jz      .failed
941
 
942
        mov     [v86_slot], eax
943
 
944
        mov     edi, eax
945
        shl     edi, 8
946
        add     edi, SLOT_BASE
947
        mov     esi, edi      ;edx=edi - pointer to extended infomation about new thread
948
        mov     ecx, 256/4
949
        xor     eax, eax
950
        cld
951
        rep stosd             ;clean extended information about new thread
952
        mov     [esi], dword 'V86 '
953
 
954
        stdcall create_process, 4096, OS_BASE, 4096
955
        test    eax, eax
956
        jz      .failed
957
 
958
        mov     [eax+PROC.mem_used], 4096
959
        mov     [esi+APPDATA.process], eax
960
 
961
        lea     ebx, [esi+APPDATA.list]
962
        lea     ecx, [eax+PROC.thr_list]
963
        list_add_tail ebx, ecx               ;add thread to process child's list
964
 
965
 
966
        lea     eax, [v86_cmdline]
967
        stdcall set_app_params , [v86_slot], eax, 0, 0, 2
968
 
969
        mov     eax, [process_number]           ;set result
970
        call    unlock_application_table
971
        ret
972
.failed:
973
        xor     eax, eax
974
.failed1:
975
        call    unlock_application_table
976
        dec     eax     ;-1
977
        ret
978
endp
979