VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestA-os2.asm@ 63206

Last change on this file since 63206 was 62521, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 46.7 KB
Line 
1; $Id: VBoxGuestA-os2.asm 62521 2016-07-22 19:16:33Z vboxsync $
2;; @file
3; VBoxGuest - OS/2 assembly file, the first file in the link.
4;
5
6;
7; Copyright (C) 2007-2016 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17; --------------------------------------------------------------------
18;
19; This code is based on:
20;
21; VBoxDrv - OS/2 assembly file, the first file in the link.
22;
23; Copyright (c) 2007-2010 knut st. osmundsen <bird-src-spam@anduin.net>
24;
25; Permission is hereby granted, free of charge, to any person
26; obtaining a copy of this software and associated documentation
27; files (the "Software"), to deal in the Software without
28; restriction, including without limitation the rights to use,
29; copy, modify, merge, publish, distribute, sublicense, and/or sell
30; copies of the Software, and to permit persons to whom the
31; Software is furnished to do so, subject to the following
32; conditions:
33;
34; The above copyright notice and this permission notice shall be
35; included in all copies or substantial portions of the Software.
36;
37; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
38; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
39; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
40; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
41; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
43; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
44; OTHER DEALINGS IN THE SOFTWARE.
45;
46
47
48;*******************************************************************************
49;* Header Files *
50;*******************************************************************************
51%define RT_INCL_16BIT_SEGMENTS
52%include "iprt/asmdefs.mac"
53%include "iprt/err.mac"
54%include "VBox/VBoxGuest.mac"
55
56
57;*******************************************************************************
58;* Structures and Typedefs *
59;*******************************************************************************
60;;
61; Request packet header.
62struc PKTHDR
63 .cb resb 1
64 .unit resb 1
65 .cmd resb 1
66 .status resw 1
67 .res1 resd 1
68 .link resd 1
69endstruc
70
71
72;;
73; Init request packet - input.
74struc PKTINITIN
75 .cb resb 1
76 .unit resb 1
77 .cmd resb 1
78 .status resw 1
79 .res1 resd 1
80 .link resd 1
81
82 .data_1 resb 1
83 .fpfnDevHlp resd 1
84 .fpszArgs resd 1
85 .data_2 resb 1
86endstruc
87
88;;
89; Init request packet - output.
90struc PKTINITOUT
91 .cb resb 1
92 .unit resb 1
93 .cmd resb 1
94 .status resw 1
95 .res1 resd 1
96 .link resd 1
97
98 .cUnits resb 1 ; block devs only.
99 .cbCode16 resw 1
100 .cbData16 resw 1
101 .fpaBPBs resd 1 ; block devs only.
102 .data_2 resb 1
103endstruc
104
105;;
106; Open request packet.
107struc PKTOPEN
108 .cb resb 1
109 .unit resb 1
110 .cmd resb 1
111 .status resw 1
112 .res1 resd 1
113 .link resd 1
114 .sfn resw 1
115endstruc
116
117;;
118; Close request packet.
119struc PKTCLOSE
120 .cb resb 1
121 .unit resb 1
122 .cmd resb 1
123 .status resw 1
124 .res1 resd 1
125 .link resd 1
126 .sfn resw 1
127endstruc
128
129;;
130; IOCtl request packet.
131struc PKTIOCTL
132 .cb resb 1
133 .unit resb 1
134 .cmd resb 1
135 .status resw 1
136 .res1 resd 1
137 .link resd 1
138
139 .cat resb 1
140 .fun resb 1
141 .pParm resd 1
142 .pData resd 1
143 .sfn resw 1
144 .cbParm resw 1
145 .cbData resw 1
146endstruc
147
148;;
149; Read/Write request packet
150struc PKTRW
151 .cb resb 1
152 .unit resb 1
153 .cmd resb 1
154 .status resw 1
155 .res1 resd 1
156 .link resd 1
157
158 .media resb 1
159 .PhysTrans resd 1
160 .cbTrans resw 1
161 .start resd 1
162 .sfn resw 1
163endstruc
164
165
166;*******************************************************************************
167;* Defined Constants And Macros *
168;*******************************************************************************
169; Some devhdr.inc stuff.
170%define DEVLEV_3 0180h
171%define DEV_30 0800h
172%define DEV_IOCTL 4000h
173%define DEV_CHAR_DEV 8000h
174
175%define DEV_16MB 0002h
176%define DEV_IOCTL2 0001h
177
178; Some dhcalls.h stuff.
179%define DevHlp_VirtToLin 05bh
180%define DevHlp_SAVE_MESSAGE 03dh
181%define DevHlp_EIO 031h
182%define DevHlp_SetIRQ 01bh
183%define DevHlp_PhysToVirt 015h
184
185; Fast IOCtl category, also defined in VBoxGuest.h
186%define VBOXGUEST_IOCTL_CATEGORY_FAST 0c3h
187
188;;
189; Got some nasm/link trouble, so emit the stuff ourselves.
190; @param %1 Must be a GLOBALNAME.
191%macro JMP32TO16 1
192 ;jmp far dword NAME(%1) wrt CODE16
193 db 066h
194 db 0eah
195 dw NAME(%1) wrt CODE16
196 dw CODE16
197%endmacro
198
199;;
200; Got some nasm/link trouble, so emit the stuff ourselves.
201; @param %1 Must be a GLOBALNAME.
202%macro JMP16TO32 1
203 ;jmp far dword NAME(%1) wrt FLAT
204 db 066h
205 db 0eah
206 dd NAME(%1) ;wrt FLAT
207 dw TEXT32 wrt FLAT
208%endmacro
209
210
211;*******************************************************************************
212;* External Symbols *
213;*******************************************************************************
214segment CODE16
215extern DOS16OPEN
216extern DOS16CLOSE
217extern DOS16WRITE
218extern DOS16DEVIOCTL2
219segment TEXT32
220extern KernThunkStackTo32
221extern KernThunkStackTo16
222
223extern NAME(vgdrvOS2Init)
224extern NAME(vgdrvOS2Open)
225extern NAME(vgdrvOS2Close)
226extern NAME(vgdrvOS2IOCtl)
227extern NAME(vgdrvOS2IOCtlFast)
228extern NAME(vgdrvOS2IDCConnect)
229extern NAME(VGDrvOS2IDCService)
230extern NAME(vgdrvOS2ISR)
231
232
233segment DATA16
234
235;;
236; Device headers. The first one is the one we'll be opening and the
237; latter is only used for 32-bit initialization.
238GLOBALNAME g_VBoxGuestHdr1
239 dw NAME(g_VBoxGuestHdr2) wrt DATA16 ; NextHeader.off
240 dw DATA16 ; NextHeader.sel
241 dw DEVLEV_3 | DEV_30 | DEV_CHAR_DEV | DEV_IOCTL; SDevAtt
242 dw NAME(VGDrvOS2Entrypoint) wrt CODE16 ; StrategyEP
243 dw NAME(VGDrvOS2IDC) wrt CODE16 ; IDCEP
244 db 'vboxgst$' ; DevName
245 dw 0 ; SDevProtCS
246 dw 0 ; SDevProtDS
247 dw 0 ; SDevRealCS
248 dw 0 ; SDevRealDS
249 dd DEV_16MB | DEV_IOCTL2 ; SDevCaps
250
251align 4
252GLOBALNAME g_VBoxGuestHdr2
253 dd 0ffffffffh ; NextHeader (NIL)
254 dw DEVLEV_3 | DEV_30 | DEV_CHAR_DEV ; SDevAtt
255 dw NAME(vgdrvOS2InitEntrypoint) wrt CODE16 ; StrategyEP
256 dw 0 ; IDCEP
257 db 'vboxgs1$' ; DevName
258 dw 0 ; SDevProtCS
259 dw 0 ; SDevProtDS
260 dw 0 ; SDevRealCS
261 dw 0 ; SDevRealDS
262 dd DEV_16MB | DEV_IOCTL2 ; SDevCaps
263
264
265;; Tristate 32-bit initialization indicator [0 = need init, -1 = init failed, 1 init succeeded].
266; Check in the open path of the primary driver. The secondary driver will
267; open the primary one during it's init and thereby trigger the 32-bit init.
268GLOBALNAME g_fInitialized
269 db 0
270
271align 4
272;; Pointer to the device helper service routine
273; This is set during the initialization of the 2nd device driver.
274GLOBALNAME g_fpfnDevHlp
275 dd 0
276
277
278;; vgdrvFindAdapter Output
279; @{
280
281;; The MMIO base of the VMMDev.
282GLOBALNAME g_PhysMMIOBase
283 dd 0
284;; The size of the MMIO memory of the VMMDev.
285GLOBALNAME g_cbMMIO
286 dd 0
287;; The I/O port base of the VMMDev.
288GLOBALNAME g_IOPortBase
289 dw 0
290;; The VMMDev Interrupt Line.
291GLOBALNAME g_bInterruptLine
292 db 0
293;; The PCI bus number returned by Find PCI Device.
294GLOBALNAME g_bPciBusNo
295 db 0
296;; The PCI Device No / Function Number returned by Find PCI Device.
297; (The upper 5 bits is the number, and the lower 3 the function.)
298GLOBALNAME g_bPciDevFunNo
299 db 0
300;; Flag that is set by the vboxgst$ init routine if VMMDev was found.
301; Both init routines must refuse loading the driver if the
302; device cannot be located.
303GLOBALNAME g_fFoundAdapter
304 db 0
305;; @}
306
307
308%ifdef DEBUG_READ
309;; Where we write to the log.
310GLOBALNAME g_offLogHead
311 dw 0
312;; Where we read from the log.
313GLOBALNAME g_offLogTail
314 dw 0
315;; The size of the log. (power of two!)
316%define LOG_SIZE 16384
317GLOBALNAME g_cchLogMax
318 dw LOG_SIZE
319;; The log buffer.
320GLOBALNAME g_szLog
321 times LOG_SIZE db 0
322%endif ; DEBUG_READ
323
324
325;
326; The init data.
327;
328segment DATA16_INIT
329GLOBALNAME g_InitDataStart
330
331;; Far pointer to the device argument.
332g_fpszArgs:
333 dd 0
334
335%if 0
336;; Message table for the Save_Message device helper.
337GLOBALNAME g_MsgTab
338 dw 1178 ; MsgId - 'MSG_REPLACEMENT_STRING'.
339 dw 1 ; cMsgStrings
340 dw NAME(g_szInitText) ; MsgStrings[0]
341 dw seg NAME(g_szInitText)
342%else
343;; Far pointer to DOS16WRITE (corrected set before called).
344; Just a temporary hack to work around a wlink issue.
345GLOBALNAME g_fpfnDos16Write
346 dw DOS16WRITE
347 dw seg DOS16WRITE
348%endif
349
350;; Size of the text currently in the g_szInitText buffer.
351GLOBALNAME g_cchInitText
352 dw 0
353;; The max size of text that can fit into the g_szInitText buffer.
354GLOBALNAME g_cchInitTextMax
355 dw 512
356;; The init text buffer.
357GLOBALNAME g_szInitText
358 times 512 db 0
359
360;; Message string that's written on failure.
361g_achLoadFailureMsg1:
362 db 0dh,0ah,'VBoxGuest: load failure no. '
363g_cchLoadFailureMsg1 EQU $ - g_achLoadFailureMsg1
364g_achLoadFailureMsg2:
365 db '!',0dh,0ah
366g_cchLoadFailureMsg2 EQU $ - g_achLoadFailureMsg2
367
368
369;
370; The 16-bit code segment.
371;
372segment CODE16
373
374
375;;
376; The strategy entry point (vboxdrv$).
377;
378; ss:bx -> request packet
379; ds:si -> device header
380;
381; Can clobber any registers it likes except SP.
382;
383BEGINPROC VGDrvOS2Entrypoint
384 push ebp
385 mov ebp, esp
386 push es ; bp - 2
387 push bx ; bp - 4
388 and sp, 0fffch
389
390 ;
391 ; Check for the most frequent first.
392 ;
393 cmp byte [es:bx + PKTHDR.cmd], 10h ; Generic IOCtl
394 jne near vgdrvOS2EP_NotGenIOCtl
395
396
397 ;
398 ; Generic I/O Control Request.
399 ;
400vgdrvOS2EP_GenIOCtl:
401
402 ; Fast IOCtl?
403 cmp byte [es:bx + PKTIOCTL.cat], VBOXGUEST_IOCTL_CATEGORY_FAST
404 jne vgdrvOS2EP_GenIOCtl_Other
405
406 ;
407 ; Fast IOCtl.
408 ; DECLASM(int) vgdrvOS2IOCtlFast(uint16_t sfn, uint8_t iFunction, uint16_t *pcbParm)
409 ;
410vgdrvOS2EP_GenIOCtl_Fast:
411 mov ax, [es:bx + PKTIOCTL.pData + 2] ; LDT selector to flat address.
412 shr ax, 3
413 shl eax, 16
414 mov ax, [es:bx + PKTIOCTL.pData]
415 push eax ; 08h - pointer to the rc buffer.
416
417 ; function.
418 movzx edx, byte [es:bx + PKTIOCTL.fun]
419 push edx ; 04h
420
421 ; system file number.
422 movzx eax, word [es:bx + PKTIOCTL.sfn]
423 push eax ; 00h
424
425 JMP16TO32 vgdrvOS2EP_GenIOCtl_Fast_32
426segment TEXT32
427GLOBALNAME vgdrvOS2EP_GenIOCtl_Fast_32
428
429 ; switch stack to 32-bit.
430 mov ax, DATA32 wrt FLAT
431 mov ds, ax
432 mov es, ax
433 call KernThunkStackTo32
434
435 ; call the C code (don't cleanup the stack).
436 call NAME(vgdrvOS2IOCtlFast)
437
438 ; switch back the stack.
439 push eax
440 call KernThunkStackTo16
441 pop eax
442
443 JMP32TO16 vgdrvOS2EP_GenIOCtl_Fast_32
444segment CODE16
445GLOBALNAME vgdrvOS2EP_GenIOCtl_Fast_16
446
447 les bx, [bp - 4] ; Reload the packet pointer.
448 or eax, eax
449 jnz near vgdrvOS2EP_GeneralFailure
450
451 ; setup output stuff.
452 mov edx, esp
453 mov eax, [ss:edx + 0ch] ; output sizes.
454 mov [es:bx + PKTIOCTL.cbParm], eax ; update cbParm and cbData.
455 mov word [es:bx + PKTHDR.status], 00100h ; done, ok.
456
457 mov sp, bp
458 pop ebp
459 retf
460
461 ;
462 ; Other IOCtl (slow)
463 ;
464vgdrvOS2EP_GenIOCtl_Other:
465 mov eax, [es:bx + PKTIOCTL.cbParm] ; Load cbParm and cbData
466 push eax ; 1eh - in/out data size.
467 ; 1ch - in/out parameter size.
468 push edx ; 18h - pointer to data size (filled in later).
469 push ecx ; 14h - pointer to param size (filled in later).
470
471 ; pData (convert to flat 32-bit)
472 mov ax, word [es:bx + PKTIOCTL.pData + 2] ; selector
473 cmp ax, 3 ; <= 3 -> nil selector...
474 jbe .no_data
475 movzx esi, word [es:bx + PKTIOCTL.pData] ; offset
476 mov dl, DevHlp_VirtToLin
477 call far [NAME(g_fpfnDevHlp)]
478 jc near vgdrvOS2EP_GeneralFailure
479 jmp .finish_data
480.no_data:
481 xor eax, eax
482.finish_data:
483 push eax ; 10h
484
485 ; pParm (convert to flat 32-bit)
486 mov ax, word [es:bx + PKTIOCTL.pParm + 2] ; selector
487 cmp ax, 3 ; <= 3 -> nil selector...
488 jbe .no_parm
489 movzx esi, word [es:bx + PKTIOCTL.pParm] ; offset
490 mov dl, DevHlp_VirtToLin
491 call far [NAME(g_fpfnDevHlp)]
492 jc near vgdrvOS2EP_GeneralFailure
493 jmp .finish_parm
494.no_parm:
495 xor eax, eax
496.finish_parm:
497 push eax ; 0ch
498
499 ; function.
500 movzx edx, byte [es:bx + PKTIOCTL.fun]
501 push edx ; 08h
502
503 ; category.
504 movzx ecx, byte [es:bx + PKTIOCTL.cat]
505 push ecx ; 04h
506
507 ; system file number.
508 movzx eax, word [es:bx + PKTIOCTL.sfn]
509 push eax ; 00h
510
511 JMP16TO32 vgdrvOS2EP_GenIOCtl_Other_32
512segment TEXT32
513GLOBALNAME vgdrvOS2EP_GenIOCtl_Other_32
514
515 ; switch stack to 32-bit.
516 mov ax, DATA32 wrt FLAT
517 mov ds, ax
518 mov es, ax
519 call KernThunkStackTo32
520
521 ; update in/out parameter pointers
522 lea eax, [esp + 1ch]
523 mov [esp + 14h], eax
524 lea edx, [esp + 1eh]
525 mov [esp + 18h], edx
526
527 ; call the C code (don't cleanup the stack).
528 call NAME(vgdrvOS2IOCtl)
529
530 ; switch back the stack.
531 push eax
532 call KernThunkStackTo16
533 pop eax
534
535 JMP32TO16 vgdrvOS2EP_GenIOCtl_Other_16
536segment CODE16
537GLOBALNAME vgdrvOS2EP_GenIOCtl_Other_16
538
539 les bx, [bp - 4] ; Reload the packet pointer.
540 or eax, eax
541 jnz near vgdrvOS2EP_GeneralFailure
542
543 ; setup output stuff.
544 mov edx, esp
545 mov eax, [ss:edx + 1ch] ; output sizes.
546 mov [es:bx + PKTIOCTL.cbParm], eax ; update cbParm and cbData.
547 mov word [es:bx + PKTHDR.status], 00100h ; done, ok.
548
549 mov sp, bp
550 pop ebp
551 retf
552
553
554 ;
555 ; Less Performance Critical Requests.
556 ;
557vgdrvOS2EP_NotGenIOCtl:
558 cmp byte [es:bx + PKTHDR.cmd], 0dh ; Open
559 je vgdrvOS2EP_Open
560 cmp byte [es:bx + PKTHDR.cmd], 0eh ; Close
561 je vgdrvOS2EP_Close
562 cmp byte [es:bx + PKTHDR.cmd], 00h ; Init
563 je vgdrvOS2EP_Init
564%ifdef DEBUG_READ
565 cmp byte [es:bx + PKTHDR.cmd], 04h ; Read
566 je near vgdrvOS2EP_Read
567%endif
568 jmp near vgdrvOS2EP_NotSupported
569
570
571 ;
572 ; Open Request. w/ ring-0 init.
573 ;
574vgdrvOS2EP_Open:
575 cmp byte [NAME(g_fInitialized)], 1
576 jne vgdrvOS2EP_OpenOther
577
578 ; First argument, the system file number.
579 movzx eax, word [es:bx + PKTOPEN.sfn]
580 push eax
581
582 JMP16TO32 vgdrvOS2EP_Open_32
583segment TEXT32
584GLOBALNAME vgdrvOS2EP_Open_32
585
586 ; switch stack to 32-bit.
587 mov ax, DATA32 wrt FLAT
588 mov ds, ax
589 mov es, ax
590 call KernThunkStackTo32
591
592 ; call the C code.
593 call NAME(vgdrvOS2Open)
594
595 ; switch back the stack.
596 push eax
597 call KernThunkStackTo16
598 pop eax
599
600 JMP32TO16 vgdrvOS2EP_Open_16
601segment CODE16
602GLOBALNAME vgdrvOS2EP_Open_16
603
604 les bx, [bp - 4] ; Reload the packet pointer.
605 or eax, eax
606 jnz near vgdrvOS2EP_GeneralFailure
607 mov word [es:bx + PKTHDR.status], 00100h ; done, ok.
608 jmp near vgdrvOS2EP_Done
609
610 ; Initializing or failed init?
611vgdrvOS2EP_OpenOther:
612 cmp byte [NAME(g_fInitialized)], 0
613 jne vgdrvOS2EP_OpenFailed
614
615 mov byte [NAME(g_fInitialized)], -1
616 call NAME(vgdrvRing0Init)
617 cmp byte [NAME(g_fInitialized)], 1
618 je vgdrvOS2EP_Open
619
620vgdrvOS2EP_OpenFailed:
621 mov word [es:bx + PKTHDR.status], 0810fh ; error, done, init failed.
622 jmp near vgdrvOS2EP_Done
623
624
625 ;
626 ; Close Request.
627 ;
628vgdrvOS2EP_Close:
629 ; First argument, the system file number.
630 movzx eax, word [es:bx + PKTOPEN.sfn]
631 push eax
632
633 JMP16TO32 vgdrvOS2EP_Close_32
634segment TEXT32
635GLOBALNAME vgdrvOS2EP_Close_32
636
637 ; switch stack to 32-bit.
638 mov ax, DATA32 wrt FLAT
639 mov ds, ax
640 mov es, ax
641 call KernThunkStackTo32
642
643 ; call the C code.
644 call NAME(vgdrvOS2Close)
645
646 ; switch back the stack.
647 push eax
648 call KernThunkStackTo16
649 pop eax
650
651 JMP32TO16 vgdrvOS2EP_Close_16
652segment CODE16
653GLOBALNAME vgdrvOS2EP_Close_16
654
655 les bx, [bp - 4] ; Reload the packet pointer.
656 or eax, eax
657 jnz near vgdrvOS2EP_GeneralFailure
658 mov word [es:bx + PKTHDR.status], 00100h ; done, ok.
659 jmp near vgdrvOS2EP_Done
660
661
662 ;
663 ; Init Request.
664 ; Find the VMMDev adapter so we can unload the driver (and avoid trouble) if not found.
665 ;
666vgdrvOS2EP_Init:
667 call NAME(vgdrvFindAdapter)
668 test ax, ax
669 jz .ok
670 mov word [es:bx + PKTHDR.status], 0810fh ; error, done, init failed.
671 call NAME(vgdrvOS2InitFlushText)
672 jmp .next
673.ok:
674 mov word [es:bx + PKTHDR.status], 00100h ; done, ok.
675.next:
676 mov byte [es:bx + PKTINITOUT.cUnits], 0
677 mov word [es:bx + PKTINITOUT.cbCode16], NAME(g_InitCodeStart) wrt CODE16
678 mov word [es:bx + PKTINITOUT.cbData16], NAME(g_InitDataStart) wrt DATA16
679 mov dword [es:bx + PKTINITOUT.fpaBPBs], 0
680 jmp near vgdrvOS2EP_Done
681
682
683%ifdef DEBUG_READ
684 ;
685 ; Read Request.
686 ; Return log data.
687 ;
688vgdrvOS2EP_Read:
689 ; Any log data available?
690 xor dx, dx
691 mov ax, [NAME(g_offLogTail)]
692 cmp ax, [NAME(g_offLogHead)]
693 jz near .log_done
694
695 ; create a temporary mapping of the physical buffer. Docs claims it trashes nearly everything...
696 push ebp
697 mov cx, [es:bx + PKTRW.cbTrans]
698 push cx
699 mov ax, [es:bx + PKTRW.PhysTrans + 2]
700 mov bx, [es:bx + PKTRW.PhysTrans]
701 mov dh, 1
702 mov dl, DevHlp_PhysToVirt
703 call far [NAME(g_fpfnDevHlp)]
704 pop bx ; bx = cbTrans
705 pop ebp
706 jc near .log_phystovirt_failed
707 ; es:di -> the output buffer.
708
709 ; setup the copy operation.
710 mov ax, [NAME(g_offLogTail)]
711 xor dx, dx ; dx tracks the number of bytes copied.
712.log_loop:
713 mov cx, [NAME(g_offLogHead)]
714 cmp ax, cx
715 je .log_done
716 jb .log_loop_before
717 mov cx, LOG_SIZE
718.log_loop_before: ; cx = end offset
719 sub cx, ax ; cx = sequential bytes to copy.
720 cmp cx, bx
721 jbe .log_loop_min
722 mov cx, bx ; output buffer is smaller than available data.
723.log_loop_min:
724 mov si, NAME(g_szLog)
725 add si, ax ; ds:si -> the log buffer.
726 add dx, cx ; update output counter
727 add ax, cx ; calc new offLogTail
728 and ax, LOG_SIZE - 1
729 rep movsb ; do the copy
730 mov [NAME(g_offLogTail)], ax ; commit the read.
731 jmp .log_loop
732
733.log_done:
734 les bx, [bp - 4] ; Reload the packet pointer.
735 mov word [es:bx + PKTRW.cbTrans], dx
736 mov word [es:bx + PKTHDR.status], 00100h ; done, ok.
737 jmp near vgdrvOS2EP_Done
738
739.log_phystovirt_failed:
740 les bx, [bp - 4] ; Reload the packet pointer.
741 jmp vgdrvOS2EP_GeneralFailure
742%endif ; DEBUG_READ
743
744
745 ;
746 ; Return 'unknown command' error.
747 ;
748vgdrvOS2EP_NotSupported:
749 mov word [es:bx + PKTHDR.status], 08103h ; error, done, unknown command.
750 jmp vgdrvOS2EP_Done
751
752 ;
753 ; Return 'general failure' error.
754 ;
755vgdrvOS2EP_GeneralFailure:
756 mov word [es:bx + PKTHDR.status], 0810ch ; error, done, general failure.
757 jmp vgdrvOS2EP_Done
758
759 ;
760 ; Non-optimized return path.
761 ;
762vgdrvOS2EP_Done:
763 mov sp, bp
764 pop ebp
765 retf
766ENDPROC VGDrvOS2Entrypoint
767
768
769;;
770; The helper device entry point.
771;
772; This is only used to do the DosOpen on the main driver so we can
773; do ring-3 init and report failures.
774;
775GLOBALNAME vgdrvOS2InitEntrypoint
776 ; The only request we're servicing is the 'init' one.
777 cmp word [es:bx + PKTHDR.cmd], 0
778 je near NAME(vgdrvOS2InitEntrypointServiceInitReq)
779
780 ; Ok, it's not the init request, just fail it.
781 mov word [es:bx + PKTHDR.status], 08103h ; error, done, unknown command.
782 retf
783
784
785;;
786; The OS/2 IDC entry point.
787;
788; This is only used to setup connection, the returned structure
789; will provide the entry points that we'll be using.
790;
791; @cproto void far __cdecl VGDrvOS2IDC(VBOXGUESTOS2IDCCONNECT far *fpConnectInfo);
792;
793; @param fpConnectInfo [bp + 8] Pointer to an VBOXGUESTOS2IDCCONNECT structure.
794;
795GLOBALNAME VGDrvOS2IDC
796 push ebp ; bp - 0h
797 mov ebp, esp
798 ; save everything we might touch.
799 push es ; bp - 2h
800 push ds ; bp - 4h
801 push eax ; bp - 8h
802 push ebx ; bp - 0ch
803 push ecx ; bp - 10h
804 push edx ; bp - 14h
805 and sp, 0fffch
806
807 JMP16TO32 VGDrvOS2IDC_32
808segment TEXT32
809GLOBALNAME VGDrvOS2IDC_32
810
811 ; switch stack to 32-bit.
812 mov ax, DATA32 wrt FLAT
813 mov ds, ax
814 mov es, ax
815 call KernThunkStackTo32
816
817 ; call the C code.
818 call NAME(vgdrvOS2IDCConnect)
819
820 ;
821 ; Load the return buffer address into ds:ebx and setup the buffer.
822 ; (eax == u32Session)
823 ;
824 mov cx, [ebp + 08h + 2]
825 mov ds, cx
826 movzx ebx, word [ebp + 08h]
827
828 mov dword [ebx + VBGOS2IDC.u32Version ], VMMDEV_VERSION
829 mov dword [ebx + VBGOS2IDC.u32Session ], eax
830 mov dword [ebx + VBGOS2IDC.pfnServiceEP ], NAME(VGDrvOS2IDCService)
831 mov word [ebx + VBGOS2IDC.fpfnServiceEP ], NAME(VGDrvOS2IDCService16) wrt CODE16
832 mov word [ebx + VBGOS2IDC.fpfnServiceEP + 2], CODE16
833 mov word [ebx + VBGOS2IDC.fpfnServiceAsmEP ], NAME(VGDrvOS2IDCService16Asm) wrt CODE16
834 mov word [ebx + VBGOS2IDC.fpfnServiceAsmEP+2],CODE16
835
836 mov ax, DATA32 wrt FLAT
837 mov ds, ax
838
839 ; switch back the stack.
840 call KernThunkStackTo16
841
842 JMP32TO16 VGDrvOS2IDC_16
843segment CODE16
844GLOBALNAME VGDrvOS2IDC_16
845
846 ; restore.
847 lea sp, [bp - 14h]
848 pop edx
849 pop ecx
850 pop ebx
851 pop eax
852 pop ds
853 pop es
854 pop ebp
855 retf
856ENDPROC VGDrvOS2IDC
857
858
859;;
860; The 16-bit IDC entry point, cdecl.
861;
862; All this does is thunking the request into something that fits
863; the 32-bit IDC service routine.
864;
865;
866; @returns VBox status code.
867; @param u32Session bp + 8h - The above session handle.
868; @param iFunction bp + 0ch - The requested function.
869; @param pvData bp + 0eh - The input/output data buffer. The caller ensures that this
870; cannot be swapped out, or that it's acceptable to take a
871; page in fault in the current context. If the request doesn't
872; take input or produces output, passing NULL is okay.
873; @param cbData bp + 12h - The size of the data buffer.
874; @param pcbDataReturned bp + 14h - Where to store the amount of data that's returned.
875; This can be NULL if pvData is NULL.
876;
877; @cproto long far __cdecl VGDrvOS2IDCService16(uint32_t u32Session, uint16_t iFunction, void far *fpvData, uint16_t cbData, uint16_t far *pcbDataReturned);
878;
879GLOBALNAME VGDrvOS2IDCService16
880 push ebp ; bp - 0h
881 mov ebp, esp
882 push es ; bp - 2h
883 push ds ; bp - 4h
884 push ecx ; bp - 8h
885 push edx ; bp - 0ch
886 push esi ; bp - 10h
887 and sp, 0fffch ; align the stack.
888
889 ; locals
890 push dword 0 ; esp + 18h (dd): cbDataReturned
891
892 ; load our ds (for g_fpfnDevHlp).
893 mov ax, DATA16
894 mov ds, ax
895
896 ;
897 ; Create the call frame before switching.
898 ;
899 push dword 0 ; esp + 14h: &cbDataReturned (filled in after stack switch)
900 movzx ecx, word [bp + 12h]
901 push ecx ; esp + 10h: cbData
902
903 ; thunk data argument if present.
904 mov ax, [bp + 0eh + 2] ; selector
905 cmp ax, 3 ; <= 3 -> nil selector...
906 jbe .no_data
907 movzx esi, word [bp + 0eh] ; offset
908 mov dl, DevHlp_VirtToLin
909 call far [NAME(g_fpfnDevHlp)]
910 jc near VGDrvOS2IDCService16_InvalidPointer
911 jmp .finish_data
912.no_data:
913 xor eax, eax
914.finish_data:
915 push eax ; esp + 08h: pvData
916 movzx edx, word [bp + 0ch]
917 push edx ; esp + 04h: iFunction
918 mov ecx, [bp + 08h]
919 push ecx ; esp + 00h: u32Session
920
921 JMP16TO32 VGDrvOS2IDCService16_32
922segment TEXT32
923GLOBALNAME VGDrvOS2IDCService16_32
924
925 ; switch stack to 32-bit.
926 mov ax, DATA32 wrt FLAT
927 mov ds, ax
928 mov es, ax
929 call KernThunkStackTo32
930
931 ; update the cbDataReturned pointer
932 lea eax, [esp + 18h]
933 mov [esp + 14h], eax
934
935 ; call the C code (don't cleanup the stack).
936 call NAME(VGDrvOS2IDCService)
937
938 ; switch back the stack.
939 push eax
940 call KernThunkStackTo16
941 pop eax
942
943 JMP32TO16 VGDrvOS2IDCService16_16
944segment CODE16
945GLOBALNAME VGDrvOS2IDCService16_16
946
947 ; Set *pcbDataReturned.
948 cmp word [bp + 14h + 2], 3
949 jbe .no_pcbDataReturned
950 xchg dx, bx
951 mov cx, [esp + 18h]
952 les bx, [bp + 14h]
953 mov word [es:bx], cx
954 xchg dx, bx
955.no_pcbDataReturned:
956
957VGDrvOS2IDCService16_Done:
958 lea sp, [bp - 10h]
959 pop esi
960 pop edx
961 pop ecx
962 pop ds
963 pop es
964 pop ebp
965 retf
966
967VGDrvOS2IDCService16_InvalidPointer:
968 mov ax, VERR_INVALID_POINTER
969 jmp VGDrvOS2IDCService16_Done
970ENDPROC VGDrvOS2IDCService16
971
972
973;;
974; The 16-bit IDC entry point, register based.
975;
976; This is just a wrapper around VGDrvOS2IDCService16 to simplify
977; calls from 16-bit assembly code.
978;
979; @returns ax: VBox status code; cx: The amount of data returned.
980;
981; @param u32Session eax - The above session handle.
982; @param iFunction dl - The requested function.
983; @param pvData es:bx - The input/output data buffer.
984; @param cbData cx - The size of the data buffer.
985;
986GLOBALNAME VGDrvOS2IDCService16Asm
987 push ebp ; bp - 0h
988 mov ebp, esp
989 push edx ; bp - 4h
990 lea sp, [bp - 18h] ; allocate the call frame.
991
992 ; bp - 06h (dw): oops...
993 mov [bp - 08h], word 0 ; bp - 08h (dw): cbDataReturned
994
995 mov [bp - 0eh], cx ; bp - 0eh (dw): cbData (NOTE: out of order to free up CX)
996 lea cx, [bp - 08h] ; bp - 0ch (dd): &cbDataReturned
997 mov [bp - 0ah], cx
998 mov cx, ss
999 mov [bp - 0ch], cx
1000 mov [bp - 10h], bx ; bp - 10h (dd): pvData
1001 mov cx, es
1002 mov [bp - 12h], cx
1003 mov [bp - 14h], dl ; bp - 14h (dw): iFunction
1004 mov [bp - 13h], byte 0
1005 mov [bp - 18h], eax ; bp - 18h (dd): u32Session
1006
1007 call NAME(VGDrvOS2IDCService16)
1008
1009 mov cx, [bp - 08h] ; cbDataReturned.
1010
1011 mov edx, [bp - 4]
1012 mov esp, ebp
1013 pop ebp
1014 retf
1015ENDPROC VGDrvOS2IDCService16Asm
1016
1017
1018
1019;;
1020; The 16-bit interrupt service routine.
1021;
1022; OS/2 saves all registers according to the docs, although it doesn't say whether
1023; this includes the 32-bit parts. Since it doesn't cost much to be careful, save
1024; everything.
1025;
1026; @returns CF=0 if it's our interrupt, CF=1 it it isn't.
1027;
1028;
1029GLOBALNAME vgdrvOS2ISR16
1030 push ebp
1031 mov ebp, esp
1032 pushf ; bp - 02h
1033 cli
1034 push eax ; bp - 06h
1035 push edx ; bp - 0ah
1036 push ebx ; bp - 0eh
1037 push ds ; bp - 10h
1038 push es ; bp - 12h
1039 push ecx ; bp - 16h
1040 push esi ; bp - 1ah
1041 push edi ; bp - 1eh
1042
1043 and sp, 0fff0h ; align the stack (16-bytes make GCC extremely happy).
1044
1045 JMP16TO32 vgdrvOS2ISR16_32
1046segment TEXT32
1047GLOBALNAME vgdrvOS2ISR16_32
1048
1049 mov ax, DATA32 wrt FLAT
1050 mov ds, ax
1051 mov es, ax
1052
1053 call KernThunkStackTo32
1054
1055 call NAME(vgdrvOS2ISR)
1056 mov ebx, eax
1057
1058 call KernThunkStackTo16
1059
1060 JMP32TO16 vgdrvOS2ISR16_16
1061segment CODE16
1062GLOBALNAME vgdrvOS2ISR16_16
1063
1064 lea sp, [bp - 1eh]
1065 pop edi
1066 pop esi
1067 pop ecx
1068 pop es
1069 pop ds
1070 test bl, 0ffh
1071 jnz .our
1072 pop ebx
1073 pop edx
1074 pop eax
1075 popf
1076 pop ebp
1077 stc
1078 retf
1079
1080 ;
1081 ; Do EIO.
1082 ;
1083.our:
1084 mov al, [NAME(g_bInterruptLine)]
1085 mov dl, DevHlp_EIO
1086 call far [NAME(g_fpfnDevHlp)]
1087
1088 pop ebx
1089 pop edx
1090 pop eax
1091 popf
1092 pop ebp
1093 clc
1094 retf
1095ENDPROC vgdrvOS2ISR16
1096
1097
1098
1099
1100
1101
1102;
1103; The 32-bit text segment.
1104;
1105segment TEXT32
1106;;
1107; 32-bit worker for registering the ISR.
1108;
1109; @returns 0 on success, some non-zero OS/2 error code on failure.
1110; @param bIrq [ebp + 8] The IRQ number. (uint8_t)
1111;
1112GLOBALNAME vgdrvOS2DevHlpSetIRQ
1113 push ebp
1114 mov ebp, esp
1115 push ebx
1116 push ds
1117
1118 call KernThunkStackTo16
1119
1120 movzx ebx, byte [ebp + 8] ; load bIrq into BX.
1121
1122 JMP32TO16 vgdrvOS2DevHlpSetIRQ_16
1123segment CODE16
1124GLOBALNAME vgdrvOS2DevHlpSetIRQ_16
1125
1126 mov ax, DATA16 ; for g_fpfnDevHlp.
1127 mov ds, ax
1128 mov ax, NAME(vgdrvOS2ISR16) ; The devhlp assume it's relative to DS.
1129 mov dh, 1 ; 1 = shared
1130 mov dl, DevHlp_SetIRQ
1131 call far [NAME(g_fpfnDevHlp)]
1132 jnc .ok
1133 movzx eax, ax
1134 or eax, eax
1135 jnz .go_back
1136 or eax, 6
1137 jmp .go_back
1138.ok:
1139 xor eax, eax
1140
1141.go_back:
1142 JMP16TO32 vgdrvOS2DevHlpSetIRQ_32
1143segment TEXT32
1144GLOBALNAME vgdrvOS2DevHlpSetIRQ_32
1145
1146 pop ds ; KernThunkStackTo32 ASSUMES flat DS and ES.
1147
1148 mov ebx, eax
1149 call KernThunkStackTo32
1150 mov eax, ebx
1151
1152 pop ebx
1153 pop ebp
1154 ret
1155ENDPROC vgdrvOS2DevHlpSetIRQ
1156
1157
1158
1159
1160;
1161; The 16-bit init code.
1162;
1163segment CODE16_INIT
1164GLOBALNAME g_InitCodeStart
1165
1166;; The device name for DosOpen.
1167g_szDeviceName:
1168 db '\DEV\vboxgst$', 0
1169
1170; icsdebug can't see where stuff starts otherwise. (kDevTest)
1171int3
1172int3
1173int3
1174int3
1175int3
1176int3
1177
1178;;
1179; The Ring-3 init code.
1180;
1181BEGINPROC vgdrvOS2InitEntrypointServiceInitReq
1182 push ebp
1183 mov ebp, esp
1184 push es ; bp - 2
1185 push sp ; bp - 4
1186 push -1 ; bp - 6: hfOpen
1187 push 0 ; bp - 8: usAction
1188 and sp, 0fffch
1189
1190 ; check for the init package.
1191 cmp word [es:bx + PKTHDR.cmd], 0
1192 jne near .not_init
1193
1194 ; check that we found the VMMDev.
1195 test byte [NAME(g_fFoundAdapter)], 1
1196 jz near .done_err
1197
1198 ;
1199 ; Copy the data out of the init packet.
1200 ;
1201 mov eax, [es:bx + PKTINITIN.fpfnDevHlp]
1202 mov [NAME(g_fpfnDevHlp)], eax
1203 mov edx, [es:bx + PKTINITIN.fpszArgs]
1204 mov [g_fpszArgs], edx
1205
1206 ;
1207 ; Open the first driver, close it, and check status.
1208 ;
1209
1210 ; APIRET _Pascal DosOpen(PSZ pszFname, PHFILE phfOpen, PUSHORT pusAction,
1211 ; ULONG ulFSize, USHORT usAttr, USHORT fsOpenFlags,
1212 ; USHORT fsOpenMode, ULONG ulReserved);
1213 push seg g_szDeviceName ; pszFname
1214 push g_szDeviceName
1215 push ss ; phfOpen
1216 lea dx, [bp - 6]
1217 push dx
1218 push ss ; pusAction
1219 lea dx, [bp - 8]
1220 push dx
1221 push dword 0 ; ulFSize
1222 push 0 ; usAttr = FILE_NORMAL
1223 push 1 ; fsOpenFlags = FILE_OPEN
1224 push 00040h ; fsOpenMode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY
1225 push dword 0 ; ulReserved
1226 call far DOS16OPEN
1227
1228 push ax ; Quickly flush any text.
1229 call NAME(vgdrvOS2InitFlushText)
1230 pop ax
1231
1232 or ax, ax
1233 jnz .done_err
1234
1235 ; APIRET APIENTRY DosClose(HFILE hf);
1236 mov cx, [bp - 6]
1237 push cx
1238 call far DOS16CLOSE
1239 or ax, ax
1240 jnz .done_err ; This can't happen (I hope).
1241
1242 ;
1243 ; Ok, we're good.
1244 ;
1245 mov word [es:bx + PKTHDR.status], 00100h ; done, ok.
1246 mov byte [es:bx + PKTINITOUT.cUnits], 0
1247 mov word [es:bx + PKTINITOUT.cbCode16], NAME(g_InitCodeStart) wrt CODE16
1248 mov word [es:bx + PKTINITOUT.cbData16], NAME(g_InitDataStart) wrt DATA16
1249 mov dword [es:bx + PKTINITOUT.fpaBPBs], 0
1250 jmp .done
1251
1252 ;
1253 ; Init failure.
1254 ;
1255.done_err:
1256 mov word [es:bx + PKTHDR.status], 0810fh ; error, done, init failed.
1257 mov byte [es:bx + PKTINITOUT.cUnits], 0
1258 mov word [es:bx + PKTINITOUT.cbCode16], 0
1259 mov word [es:bx + PKTINITOUT.cbData16], 0
1260 mov dword [es:bx + PKTINITOUT.fpaBPBs], 0
1261 jmp .done
1262
1263 ;
1264 ; Not init, return 'unknown command'.
1265 ;
1266.not_init:
1267 mov word [es:bx + PKTHDR.status], 08103h ; error, done, unknown command.
1268 jmp .done
1269
1270 ;
1271 ; Request done.
1272 ;
1273.done:
1274 mov sp, bp
1275 pop ebp
1276 retf
1277ENDPROC vgdrvOS2InitEntrypointServiceInitReq
1278
1279
1280;;
1281; The Ring-0 init code.
1282;
1283BEGINPROC vgdrvRing0Init
1284 push es
1285 push esi
1286 push ebp
1287 mov ebp, esp
1288 and sp, 0fffch
1289
1290 ;
1291 ; Thunk the argument string pointer first.
1292 ;
1293 movzx esi, word [g_fpszArgs] ; offset
1294 mov ax, [g_fpszArgs + 2] ; selector
1295 mov dl, DevHlp_VirtToLin
1296 call far [NAME(g_fpfnDevHlp)]
1297 jc near vgdrvRing0Init_done ; eax is non-zero on failure (can't happen)
1298 push eax ; 00h - pszArgs (for vgdrvOS2Init).
1299
1300 ;
1301 ; Do 16-bit init?
1302 ;
1303
1304
1305 ;
1306 ; Do 32-bit init
1307 ;
1308 JMP16TO32 vgdrvRing0Init_32
1309segment TEXT32
1310GLOBALNAME vgdrvRing0Init_32
1311
1312 ; switch stack to 32-bit.
1313 mov ax, DATA32 wrt FLAT
1314 mov ds, ax
1315 mov es, ax
1316 call KernThunkStackTo32
1317
1318 ; call the C code.
1319 call NAME(vgdrvOS2Init)
1320
1321 ; switch back the stack and reload ds.
1322 push eax
1323 call KernThunkStackTo16
1324 pop eax
1325
1326 mov dx, seg NAME(g_fInitialized)
1327 mov ds, dx
1328
1329 JMP32TO16 vgdrvRing0Init_16
1330segment CODE16_INIT
1331GLOBALNAME vgdrvRing0Init_16
1332
1333 ; check the result and set g_fInitialized on success.
1334 or eax, eax
1335 jnz vgdrvRing0Init_done
1336 mov byte [NAME(g_fInitialized)], 1
1337
1338vgdrvRing0Init_done:
1339 mov sp, bp
1340 pop ebp
1341 pop esi
1342 pop es
1343 ret
1344ENDPROC vgdrvRing0Init
1345
1346
1347;;
1348; Flush any text in the text buffer.
1349;
1350BEGINPROC vgdrvOS2InitFlushText
1351 push bp
1352 mov bp, sp
1353
1354 ; Anything in the buffer?
1355 mov ax, [NAME(g_cchInitText)]
1356 or ax, ax
1357 jz .done
1358
1359%if 1
1360 ; Write it to STDOUT.
1361 ; APIRET _Pascal DosWrite(HFILE hf, PVOID pvBuf, USHORT cbBuf, PUSHORT pcbBytesWritten);
1362 push ax ; bp - 2 : cbBytesWritten
1363 mov cx, sp
1364 push 1 ; STDOUT
1365 push seg NAME(g_szInitText) ; pvBuf
1366 push NAME(g_szInitText)
1367 push ax ; cbBuf
1368 push ss ; pcbBytesWritten
1369 push cx
1370%if 0 ; wlink generates a non-aliased fixup here which results in 16-bit offset with the flat 32-bit selector.
1371 call far DOS16WRITE
1372%else
1373 ; convert flat pointer to a far pointer using the tiled algorithm.
1374 push ds
1375 mov ax, DATA32 wrt FLAT
1376 mov ds, ax
1377 mov eax, g_pfnDos16Write wrt FLAT
1378 movzx eax, word [eax + 2] ; High word of the flat address (in DATA32).
1379 shl ax, 3
1380 or ax, 0007h
1381 pop ds
1382 mov [NAME(g_fpfnDos16Write) + 2], ax ; Update the selector (in DATA16_INIT).
1383 ; do the call
1384 call far [NAME(g_fpfnDos16Write)]
1385%endif
1386
1387%else ; alternative workaround for the wlink issue.
1388 ; Use the save message devhlp.
1389 push esi
1390 push ebx
1391 xor bx, bx
1392 mov si, NAME(g_MsgTab)
1393 mov dx, seg NAME(g_MsgTab)
1394 mov ds, dx
1395 mov dl, DevHlp_SAVE_MESSAGE
1396 call far [NAME(g_fpfnDevHlp)]
1397 pop ebx
1398 pop esi
1399%endif
1400
1401 ; Empty the buffer.
1402 mov word [NAME(g_cchInitText)], 0
1403 mov byte [NAME(g_szInitText)], 0
1404
1405.done:
1406 mov sp, bp
1407 pop bp
1408 ret
1409ENDPROC vgdrvOS2InitFlushText
1410
1411
1412;; The device name for DosOpen.
1413g_szOemHlpDevName:
1414 db '\DEV\OEMHLP$', 0
1415
1416
1417;;
1418; Talks to OEMHLP$ about finding the VMMDev PCI adapter.
1419;
1420; On success g_fFoundAdapter is set to 1, and g_cbMMIO,
1421; g_PhysMMIOBase and g_IOPortBase are initialized with
1422; the PCI data.
1423;
1424; @returns 0 on success, non-zero on failure. (eax)
1425;
1426; @remark ASSUMES DS:DATA16.
1427; @uses nothing.
1428;
1429BEGINPROC vgdrvFindAdapter
1430 push ebx
1431 push ecx
1432 push edx
1433 push esi
1434 push edi
1435 push ebp
1436 mov ebp, esp
1437 push -1 ; bp - 2: hfOpen
1438%define hfOpen bp - 2
1439 push 0 ; bp - 4: usAction
1440%define usAction bp - 4
1441 sub sp, 20h ; bp - 44: 32 byte parameter buffer.
1442%define abParm bp - 24h
1443 sub sp, 40h ; bp - c4: 32 byte data buffer.
1444%define abData bp - 44h
1445
1446;; VBox stuff
1447%define VBOX_PCI_VENDORID 080eeh
1448%define VMMDEV_DEVICEID 0cafeh
1449
1450;; OEMHLP$ stuff.
1451%define IOCTL_OEMHLP 80h
1452%define OEMHLP_PCI 0bh
1453%define PCI_FIND_DEVICE 1
1454%define PCI_READ_CONFIG 3
1455
1456;; PCI stuff
1457%define PCI_INTERRUPT_LINE 03ch ;;< 8-bit RW - Interrupt line.
1458%define PCI_BASE_ADDRESS_0 010h ;;< 32-bit RW */
1459%define PCI_BASE_ADDRESS_1 014h ;;< 32-bit RW */
1460
1461
1462%macro CallIOCtl 2
1463 ; APIRET _Pascal DosDevIOCtl2(PVOID pData, USHORT cbData, PVOID pParm,
1464 ; USHORT cbParm, USHORT usFun, USHORT usCategory,
1465 ; HFILE hDev);
1466 push ss ; pData
1467 lea dx, [abData]
1468 push dx
1469 push %2 ; cbData
1470
1471 push ss ; pParm
1472 lea dx, [abParm]
1473 push dx
1474 push %1 ; cbParm
1475 push OEMHLP_PCI ; usFun
1476 push IOCTL_OEMHLP ; usCategory
1477
1478 mov ax, [hfOpen] ; hDev
1479 push ax
1480 call far DOS16DEVIOCTL2
1481
1482 ; check for error.
1483 test ax, ax
1484 jnz near .done_err_close
1485 cmp [abData + 0], byte 0
1486 jne near .done_err_close
1487%endmacro
1488
1489
1490 ;
1491 ; Open the OEMHLP$ driver.
1492 ;
1493
1494 ; APIRET _Pascal DosOpen(PSZ pszFname, PHFILE phfOpen, PUSHORT pusAction,
1495 ; ULONG ulFSize, USHORT usAttr, USHORT fsOpenFlags,
1496 ; USHORT fsOpenMode, ULONG ulReserved);
1497 mov di, '0'
1498 push seg g_szOemHlpDevName ; pszFname
1499 push g_szOemHlpDevName
1500 push ss ; phfOpen
1501 lea dx, [hfOpen]
1502 push dx
1503 push ss ; pusAction
1504 lea dx, [usAction]
1505 push dx
1506 push dword 0 ; ulFSize
1507 push 0 ; usAttr = FILE_NORMAL
1508 push 1 ; fsOpenFlags = FILE_OPEN
1509 push 00040h ; fsOpenMode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY
1510 push dword 0 ; ulReserved
1511 call far DOS16OPEN
1512 or ax, ax
1513 jnz near .done
1514
1515
1516 ;
1517 ; Send a PCI_FIND_DEVICE request.
1518 ;
1519
1520 ; Initialize the parameter packet.
1521 mov [abParm + 0], byte PCI_FIND_DEVICE ; 0 - db - SubFunction Number
1522 mov [abParm + 1], word VMMDEV_DEVICEID ; 1 - dw - Device ID
1523 mov [abParm + 3], word VBOX_PCI_VENDORID ; 3 - dw - Vendor ID
1524 mov [abParm + 5], byte 0 ; 5 - db - (Device) Index
1525
1526 ; Zero padd the data packet.
1527 mov [abData + 0], dword 0
1528
1529 mov di, '1'
1530 CallIOCtl 6, 3
1531
1532 mov al, [abData + 1] ; 1 - db - Bus Number.
1533 mov [NAME(g_bPciBusNo)], al
1534 mov al, [abData + 2] ; 2 - db - DevFunc Number.
1535 mov [NAME(g_bPciDevFunNo)], al
1536
1537 ;
1538 ; Read the interrupt register (byte).
1539 ;
1540 mov di, '2'
1541 mov ax, PCI_INTERRUPT_LINE | 0100h
1542 call .NestedReadReg
1543 mov [NAME(g_bInterruptLine)], al
1544
1545 ;
1546 ; Read the first base address (dword), this shall must be in I/O space.
1547 ;
1548 mov di, '3'
1549 mov ax, PCI_BASE_ADDRESS_0 | 0400h
1550 call .NestedReadReg
1551 mov di, '4'
1552 test al, 1h ; Test that it's an I/O space address.
1553 jz .done_err_close
1554 mov di, '5'
1555 test eax, 0ffff0002h ; These shall all be 0 according to the specs.
1556 jnz .done_err_close
1557 and ax, 0fffeh
1558 mov [NAME(g_IOPortBase)], ax
1559
1560 ;
1561 ; Read the second base address (dword), this shall be in memory space if present.
1562 ;
1563 mov di, '6'
1564 mov ax, PCI_BASE_ADDRESS_1 | 0400h
1565 call .NestedReadReg
1566 mov di, '7'
1567 test al, 1h ; Test that it's a memory space address.
1568 jnz .done_err_close
1569 and eax, 0fffffff0h
1570 mov [NAME(g_PhysMMIOBase)], eax
1571
1572 ;or eax, eax
1573 ;jz .done_success ; No memory region.
1574 ;; @todo If there is a simple way of determining the size do that, if
1575 ; not we can easily handle it the code that does the actual mapping.
1576
1577
1578 ;
1579 ; Ok, we're good!
1580 ;
1581.done_success:
1582 or [NAME(g_fFoundAdapter)], byte 1
1583 jmp .done_close
1584
1585 ;
1586 ; Close the OEMHLP$ driver.
1587 ;
1588.done_err_close:
1589 or ax, 80h
1590.done_close:
1591 ; APIRET APIENTRY DosClose(HFILE hf);
1592 push ax ; Save result
1593 mov cx, [hfOpen]
1594 push cx
1595 call far DOS16CLOSE
1596 or ax, ax
1597 jnz .bitch ; This can't happen (I hope).
1598 pop ax
1599 or ax, ax
1600 jnz .bitch
1601
1602 ;
1603 ; Return to vgdrvOS2EP_Init.
1604 ;
1605.done:
1606 mov esp, ebp
1607 pop ebp
1608 pop edi
1609 pop esi
1610 pop edx
1611 pop ecx
1612 pop ebx
1613 ret
1614
1615
1616 ;
1617 ; Puts the reason for failure in message buffer.
1618 ; The caller will flush this.
1619 ;
1620.bitch:
1621 push es
1622
1623 mov ax, ds
1624 mov es, ax
1625 mov ax, di ; save the reason.
1626 mov di, NAME(g_szInitText)
1627 add di, [NAME(g_cchInitText)]
1628
1629 mov si, g_achLoadFailureMsg1
1630 mov cx, g_cchLoadFailureMsg1
1631 rep movsb
1632
1633 stosb
1634
1635 mov si, g_achLoadFailureMsg2
1636 mov cx, g_cchLoadFailureMsg2
1637 rep movsb
1638
1639 mov [di], byte 0
1640 sub di, NAME(g_szInitText)
1641 mov [NAME(g_cchInitText)], di
1642
1643 pop es
1644 jmp .done
1645
1646
1647 ;
1648 ; Nested function which reads a PCI config register.
1649 ; (This operates on the vgdrvFindAdapter stack frame.)
1650 ;
1651 ; Input:
1652 ; al - register to read
1653 ; ah - register size.
1654 ;
1655 ; Output:
1656 ; eax - the value.
1657 ;
1658 ; Uses:
1659 ; dx
1660 ;
1661.NestedReadReg:
1662 ; Fill in the request packet.
1663 mov [abParm + 0], byte PCI_READ_CONFIG ; 0 - db - SubFunction Number
1664 mov dl, [NAME(g_bPciBusNo)]
1665 mov [abParm + 1], dl ; 1 - db - Bus Number
1666 mov dl, [NAME(g_bPciDevFunNo)]
1667 mov [abParm + 2], dl ; 2 - db - DevFunc Number
1668 mov [abParm + 3], al ; 3 - db - Configuration Register
1669 mov [abParm + 4], ah ; 4 - db - (Register) Size
1670
1671 ; Pad the data packet.
1672 mov [abData + 0], dword 0
1673 mov [abData + 4], dword 0
1674
1675 CallIOCtl 5, 5
1676
1677 mov eax, [abData + 1] ; 1 - dd - Data
1678
1679 ret
1680
1681ENDPROC vgdrvFindAdapter
1682
1683
1684
1685;;
1686; This must be present
1687segment DATA32
1688g_pfnDos16Write:
1689 dd DOS16WRITE ; flat
1690
1691
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use