VirtualBox

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

Last change on this file since 68570 was 68570, checked in by vboxsync, 7 years ago

merging vbglioc r117736: OS/2 adjustments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.5 KB
Line 
1; $Id: VBoxGuestA-os2.asm 68570 2017-08-31 12:10:39Z 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 <[email protected]>
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 VBGL_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], VBGL_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 ], VBGL_IOC_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 fpReqHdr 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 cbReq bp + 12h - The size of the data buffer.
874;
875; @cproto long far __cdecl VGDrvOS2IDCService16(uint32_t u32Session, uint16_t iFunction, void far *fpReqHdr, uint16_t cbReq);
876;
877GLOBALNAME VGDrvOS2IDCService16
878 push ebp ; bp - 0h
879 mov ebp, esp
880 push es ; bp - 2h
881 push ds ; bp - 4h
882 push ecx ; bp - 8h
883 push edx ; bp - 0ch
884 push esi ; bp - 10h
885 and sp, 0fffch ; align the stack.
886
887 ; locals
888 push dword 0 ; esp + 18h (dd): cbDataReturned
889
890 ; load our ds (for g_fpfnDevHlp).
891 mov ax, DATA16
892 mov ds, ax
893
894 ;
895 ; Create the call frame before switching.
896 ;
897 movzx ecx, word [bp + 12h]
898 push ecx ; esp + 10h: cbData
899
900 ; thunk data argument if present.
901 mov ax, [bp + 0eh + 2] ; selector
902 cmp ax, 3 ; <= 3 -> nil selector...
903 jbe .no_data
904 movzx esi, word [bp + 0eh] ; offset
905 mov dl, DevHlp_VirtToLin
906 call far [NAME(g_fpfnDevHlp)]
907 jc near VGDrvOS2IDCService16_InvalidPointer
908 jmp .finish_data
909.no_data:
910 xor eax, eax
911.finish_data:
912 push eax ; esp + 08h: pvData
913 movzx edx, word [bp + 0ch]
914 push edx ; esp + 04h: iFunction
915 mov ecx, [bp + 08h]
916 push ecx ; esp + 00h: u32Session
917
918 JMP16TO32 VGDrvOS2IDCService16_32
919segment TEXT32
920GLOBALNAME VGDrvOS2IDCService16_32
921
922 ; switch stack to 32-bit.
923 mov ax, DATA32 wrt FLAT
924 mov ds, ax
925 mov es, ax
926 call KernThunkStackTo32
927
928 ; call the C code (don't cleanup the stack).
929 call NAME(VGDrvOS2IDCService)
930
931 ; switch back the stack.
932 push eax
933 call KernThunkStackTo16
934 pop eax
935
936 JMP32TO16 VGDrvOS2IDCService16_16
937segment CODE16
938GLOBALNAME VGDrvOS2IDCService16_16
939
940VGDrvOS2IDCService16_Done:
941 lea sp, [bp - 10h]
942 pop esi
943 pop edx
944 pop ecx
945 pop ds
946 pop es
947 pop ebp
948 retf
949
950VGDrvOS2IDCService16_InvalidPointer:
951 mov ax, VERR_INVALID_POINTER
952 jmp VGDrvOS2IDCService16_Done
953ENDPROC VGDrvOS2IDCService16
954
955
956;;
957; The 16-bit IDC entry point, register based.
958;
959; This is just a wrapper around VGDrvOS2IDCService16 to simplify
960; calls from 16-bit assembly code.
961;
962; @returns ax: VBox status code; cx: The amount of data returned.
963;
964; @param u32Session eax - The above session handle.
965; @param iFunction dl - The requested function.
966; @param pvData es:bx - The input/output data buffer.
967; @param cbData cx - The size of the data buffer.
968;
969GLOBALNAME VGDrvOS2IDCService16Asm
970 push ebp ; bp - 0h
971 mov ebp, esp
972 push edx ; bp - 4h
973
974 push cx ; cbData
975 push es
976 xor dh, dh
977 push dx
978 push eax
979 call NAME(VGDrvOS2IDCService16)
980
981 mov cx, [es:bx + VBGLREQHDR.cbOut]
982
983 mov edx, [bp - 4]
984 mov esp, ebp
985 pop ebp
986 retf
987ENDPROC VGDrvOS2IDCService16Asm
988
989
990
991;;
992; The 16-bit interrupt service routine.
993;
994; OS/2 saves all registers according to the docs, although it doesn't say whether
995; this includes the 32-bit parts. Since it doesn't cost much to be careful, save
996; everything.
997;
998; @returns CF=0 if it's our interrupt, CF=1 it it isn't.
999;
1000;
1001GLOBALNAME vgdrvOS2ISR16
1002 push ebp
1003 mov ebp, esp
1004 pushf ; bp - 02h
1005 cli
1006 push eax ; bp - 06h
1007 push edx ; bp - 0ah
1008 push ebx ; bp - 0eh
1009 push ds ; bp - 10h
1010 push es ; bp - 12h
1011 push ecx ; bp - 16h
1012 push esi ; bp - 1ah
1013 push edi ; bp - 1eh
1014
1015 and sp, 0fff0h ; align the stack (16-bytes make GCC extremely happy).
1016
1017 JMP16TO32 vgdrvOS2ISR16_32
1018segment TEXT32
1019GLOBALNAME vgdrvOS2ISR16_32
1020
1021 mov ax, DATA32 wrt FLAT
1022 mov ds, ax
1023 mov es, ax
1024
1025 call KernThunkStackTo32
1026
1027 call NAME(vgdrvOS2ISR)
1028 mov ebx, eax
1029
1030 call KernThunkStackTo16
1031
1032 JMP32TO16 vgdrvOS2ISR16_16
1033segment CODE16
1034GLOBALNAME vgdrvOS2ISR16_16
1035
1036 lea sp, [bp - 1eh]
1037 pop edi
1038 pop esi
1039 pop ecx
1040 pop es
1041 pop ds
1042 test bl, 0ffh
1043 jnz .our
1044 pop ebx
1045 pop edx
1046 pop eax
1047 popf
1048 pop ebp
1049 stc
1050 retf
1051
1052 ;
1053 ; Do EIO.
1054 ;
1055.our:
1056 mov al, [NAME(g_bInterruptLine)]
1057 mov dl, DevHlp_EIO
1058 call far [NAME(g_fpfnDevHlp)]
1059
1060 pop ebx
1061 pop edx
1062 pop eax
1063 popf
1064 pop ebp
1065 clc
1066 retf
1067ENDPROC vgdrvOS2ISR16
1068
1069
1070
1071
1072
1073
1074;
1075; The 32-bit text segment.
1076;
1077segment TEXT32
1078;;
1079; 32-bit worker for registering the ISR.
1080;
1081; @returns 0 on success, some non-zero OS/2 error code on failure.
1082; @param bIrq [ebp + 8] The IRQ number. (uint8_t)
1083;
1084GLOBALNAME vgdrvOS2DevHlpSetIRQ
1085 push ebp
1086 mov ebp, esp
1087 push ebx
1088 push ds
1089
1090 call KernThunkStackTo16
1091
1092 movzx ebx, byte [ebp + 8] ; load bIrq into BX.
1093
1094 JMP32TO16 vgdrvOS2DevHlpSetIRQ_16
1095segment CODE16
1096GLOBALNAME vgdrvOS2DevHlpSetIRQ_16
1097
1098 mov ax, DATA16 ; for g_fpfnDevHlp.
1099 mov ds, ax
1100 mov ax, NAME(vgdrvOS2ISR16) ; The devhlp assume it's relative to DS.
1101 mov dh, 1 ; 1 = shared
1102 mov dl, DevHlp_SetIRQ
1103 call far [NAME(g_fpfnDevHlp)]
1104 jnc .ok
1105 movzx eax, ax
1106 or eax, eax
1107 jnz .go_back
1108 or eax, 6
1109 jmp .go_back
1110.ok:
1111 xor eax, eax
1112
1113.go_back:
1114 JMP16TO32 vgdrvOS2DevHlpSetIRQ_32
1115segment TEXT32
1116GLOBALNAME vgdrvOS2DevHlpSetIRQ_32
1117
1118 pop ds ; KernThunkStackTo32 ASSUMES flat DS and ES.
1119
1120 mov ebx, eax
1121 call KernThunkStackTo32
1122 mov eax, ebx
1123
1124 pop ebx
1125 pop ebp
1126 ret
1127ENDPROC vgdrvOS2DevHlpSetIRQ
1128
1129
1130
1131
1132;
1133; The 16-bit init code.
1134;
1135segment CODE16_INIT
1136GLOBALNAME g_InitCodeStart
1137
1138;; The device name for DosOpen.
1139g_szDeviceName:
1140 db '\DEV\vboxgst$', 0
1141
1142; icsdebug can't see where stuff starts otherwise. (kDevTest)
1143int3
1144int3
1145int3
1146int3
1147int3
1148int3
1149
1150;;
1151; The Ring-3 init code.
1152;
1153BEGINPROC vgdrvOS2InitEntrypointServiceInitReq
1154 push ebp
1155 mov ebp, esp
1156 push es ; bp - 2
1157 push sp ; bp - 4
1158 push -1 ; bp - 6: hfOpen
1159 push 0 ; bp - 8: usAction
1160 and sp, 0fffch
1161
1162 ; check for the init package.
1163 cmp word [es:bx + PKTHDR.cmd], 0
1164 jne near .not_init
1165
1166 ; check that we found the VMMDev.
1167 test byte [NAME(g_fFoundAdapter)], 1
1168 jz near .done_err
1169
1170 ;
1171 ; Copy the data out of the init packet.
1172 ;
1173 mov eax, [es:bx + PKTINITIN.fpfnDevHlp]
1174 mov [NAME(g_fpfnDevHlp)], eax
1175 mov edx, [es:bx + PKTINITIN.fpszArgs]
1176 mov [g_fpszArgs], edx
1177
1178 ;
1179 ; Open the first driver, close it, and check status.
1180 ;
1181
1182 ; APIRET _Pascal DosOpen(PSZ pszFname, PHFILE phfOpen, PUSHORT pusAction,
1183 ; ULONG ulFSize, USHORT usAttr, USHORT fsOpenFlags,
1184 ; USHORT fsOpenMode, ULONG ulReserved);
1185 push seg g_szDeviceName ; pszFname
1186 push g_szDeviceName
1187 push ss ; phfOpen
1188 lea dx, [bp - 6]
1189 push dx
1190 push ss ; pusAction
1191 lea dx, [bp - 8]
1192 push dx
1193 push dword 0 ; ulFSize
1194 push 0 ; usAttr = FILE_NORMAL
1195 push 1 ; fsOpenFlags = FILE_OPEN
1196 push 00040h ; fsOpenMode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY
1197 push dword 0 ; ulReserved
1198 call far DOS16OPEN
1199
1200 push ax ; Quickly flush any text.
1201 call NAME(vgdrvOS2InitFlushText)
1202 pop ax
1203
1204 or ax, ax
1205 jnz .done_err
1206
1207 ; APIRET APIENTRY DosClose(HFILE hf);
1208 mov cx, [bp - 6]
1209 push cx
1210 call far DOS16CLOSE
1211 or ax, ax
1212 jnz .done_err ; This can't happen (I hope).
1213
1214 ;
1215 ; Ok, we're good.
1216 ;
1217 mov word [es:bx + PKTHDR.status], 00100h ; done, ok.
1218 mov byte [es:bx + PKTINITOUT.cUnits], 0
1219 mov word [es:bx + PKTINITOUT.cbCode16], NAME(g_InitCodeStart) wrt CODE16
1220 mov word [es:bx + PKTINITOUT.cbData16], NAME(g_InitDataStart) wrt DATA16
1221 mov dword [es:bx + PKTINITOUT.fpaBPBs], 0
1222 jmp .done
1223
1224 ;
1225 ; Init failure.
1226 ;
1227.done_err:
1228 mov word [es:bx + PKTHDR.status], 0810fh ; error, done, init failed.
1229 mov byte [es:bx + PKTINITOUT.cUnits], 0
1230 mov word [es:bx + PKTINITOUT.cbCode16], 0
1231 mov word [es:bx + PKTINITOUT.cbData16], 0
1232 mov dword [es:bx + PKTINITOUT.fpaBPBs], 0
1233 jmp .done
1234
1235 ;
1236 ; Not init, return 'unknown command'.
1237 ;
1238.not_init:
1239 mov word [es:bx + PKTHDR.status], 08103h ; error, done, unknown command.
1240 jmp .done
1241
1242 ;
1243 ; Request done.
1244 ;
1245.done:
1246 mov sp, bp
1247 pop ebp
1248 retf
1249ENDPROC vgdrvOS2InitEntrypointServiceInitReq
1250
1251
1252;;
1253; The Ring-0 init code.
1254;
1255BEGINPROC vgdrvRing0Init
1256 push es
1257 push esi
1258 push ebp
1259 mov ebp, esp
1260 and sp, 0fffch
1261
1262 ;
1263 ; Thunk the argument string pointer first.
1264 ;
1265 movzx esi, word [g_fpszArgs] ; offset
1266 mov ax, [g_fpszArgs + 2] ; selector
1267 mov dl, DevHlp_VirtToLin
1268 call far [NAME(g_fpfnDevHlp)]
1269 jc near vgdrvRing0Init_done ; eax is non-zero on failure (can't happen)
1270 push eax ; 00h - pszArgs (for vgdrvOS2Init).
1271
1272 ;
1273 ; Do 16-bit init?
1274 ;
1275
1276
1277 ;
1278 ; Do 32-bit init
1279 ;
1280 JMP16TO32 vgdrvRing0Init_32
1281segment TEXT32
1282GLOBALNAME vgdrvRing0Init_32
1283
1284 ; switch stack to 32-bit.
1285 mov ax, DATA32 wrt FLAT
1286 mov ds, ax
1287 mov es, ax
1288 call KernThunkStackTo32
1289
1290 ; call the C code.
1291 call NAME(vgdrvOS2Init)
1292
1293 ; switch back the stack and reload ds.
1294 push eax
1295 call KernThunkStackTo16
1296 pop eax
1297
1298 mov dx, seg NAME(g_fInitialized)
1299 mov ds, dx
1300
1301 JMP32TO16 vgdrvRing0Init_16
1302segment CODE16_INIT
1303GLOBALNAME vgdrvRing0Init_16
1304
1305 ; check the result and set g_fInitialized on success.
1306 or eax, eax
1307 jnz vgdrvRing0Init_done
1308 mov byte [NAME(g_fInitialized)], 1
1309
1310vgdrvRing0Init_done:
1311 mov sp, bp
1312 pop ebp
1313 pop esi
1314 pop es
1315 ret
1316ENDPROC vgdrvRing0Init
1317
1318
1319;;
1320; Flush any text in the text buffer.
1321;
1322BEGINPROC vgdrvOS2InitFlushText
1323 push bp
1324 mov bp, sp
1325
1326 ; Anything in the buffer?
1327 mov ax, [NAME(g_cchInitText)]
1328 or ax, ax
1329 jz .done
1330
1331%if 1
1332 ; Write it to STDOUT.
1333 ; APIRET _Pascal DosWrite(HFILE hf, PVOID pvBuf, USHORT cbBuf, PUSHORT pcbBytesWritten);
1334 push ax ; bp - 2 : cbBytesWritten
1335 mov cx, sp
1336 push 1 ; STDOUT
1337 push seg NAME(g_szInitText) ; pvBuf
1338 push NAME(g_szInitText)
1339 push ax ; cbBuf
1340 push ss ; pcbBytesWritten
1341 push cx
1342%if 0 ; wlink generates a non-aliased fixup here which results in 16-bit offset with the flat 32-bit selector.
1343 call far DOS16WRITE
1344%else
1345 ; convert flat pointer to a far pointer using the tiled algorithm.
1346 push ds
1347 mov ax, DATA32 wrt FLAT
1348 mov ds, ax
1349 mov eax, g_pfnDos16Write wrt FLAT
1350 movzx eax, word [eax + 2] ; High word of the flat address (in DATA32).
1351 shl ax, 3
1352 or ax, 0007h
1353 pop ds
1354 mov [NAME(g_fpfnDos16Write) + 2], ax ; Update the selector (in DATA16_INIT).
1355 ; do the call
1356 call far [NAME(g_fpfnDos16Write)]
1357%endif
1358
1359%else ; alternative workaround for the wlink issue.
1360 ; Use the save message devhlp.
1361 push esi
1362 push ebx
1363 xor bx, bx
1364 mov si, NAME(g_MsgTab)
1365 mov dx, seg NAME(g_MsgTab)
1366 mov ds, dx
1367 mov dl, DevHlp_SAVE_MESSAGE
1368 call far [NAME(g_fpfnDevHlp)]
1369 pop ebx
1370 pop esi
1371%endif
1372
1373 ; Empty the buffer.
1374 mov word [NAME(g_cchInitText)], 0
1375 mov byte [NAME(g_szInitText)], 0
1376
1377.done:
1378 mov sp, bp
1379 pop bp
1380 ret
1381ENDPROC vgdrvOS2InitFlushText
1382
1383
1384;; The device name for DosOpen.
1385g_szOemHlpDevName:
1386 db '\DEV\OEMHLP$', 0
1387
1388
1389;;
1390; Talks to OEMHLP$ about finding the VMMDev PCI adapter.
1391;
1392; On success g_fFoundAdapter is set to 1, and g_cbMMIO,
1393; g_PhysMMIOBase and g_IOPortBase are initialized with
1394; the PCI data.
1395;
1396; @returns 0 on success, non-zero on failure. (eax)
1397;
1398; @remark ASSUMES DS:DATA16.
1399; @uses nothing.
1400;
1401BEGINPROC vgdrvFindAdapter
1402 push ebx
1403 push ecx
1404 push edx
1405 push esi
1406 push edi
1407 push ebp
1408 mov ebp, esp
1409 push -1 ; bp - 2: hfOpen
1410%define hfOpen bp - 2
1411 push 0 ; bp - 4: usAction
1412%define usAction bp - 4
1413 sub sp, 20h ; bp - 44: 32 byte parameter buffer.
1414%define abParm bp - 24h
1415 sub sp, 40h ; bp - c4: 32 byte data buffer.
1416%define abData bp - 44h
1417
1418;; VBox stuff
1419%define VBOX_PCI_VENDORID 080eeh
1420%define VMMDEV_DEVICEID 0cafeh
1421
1422;; OEMHLP$ stuff.
1423%define IOCTL_OEMHLP 80h
1424%define OEMHLP_PCI 0bh
1425%define PCI_FIND_DEVICE 1
1426%define PCI_READ_CONFIG 3
1427
1428;; PCI stuff
1429%define PCI_INTERRUPT_LINE 03ch ;;< 8-bit RW - Interrupt line.
1430%define PCI_BASE_ADDRESS_0 010h ;;< 32-bit RW */
1431%define PCI_BASE_ADDRESS_1 014h ;;< 32-bit RW */
1432
1433
1434%macro CallIOCtl 2
1435 ; APIRET _Pascal DosDevIOCtl2(PVOID pData, USHORT cbData, PVOID pParm,
1436 ; USHORT cbParm, USHORT usFun, USHORT usCategory,
1437 ; HFILE hDev);
1438 push ss ; pData
1439 lea dx, [abData]
1440 push dx
1441 push %2 ; cbData
1442
1443 push ss ; pParm
1444 lea dx, [abParm]
1445 push dx
1446 push %1 ; cbParm
1447 push OEMHLP_PCI ; usFun
1448 push IOCTL_OEMHLP ; usCategory
1449
1450 mov ax, [hfOpen] ; hDev
1451 push ax
1452 call far DOS16DEVIOCTL2
1453
1454 ; check for error.
1455 test ax, ax
1456 jnz near .done_err_close
1457 cmp [abData + 0], byte 0
1458 jne near .done_err_close
1459%endmacro
1460
1461
1462 ;
1463 ; Open the OEMHLP$ driver.
1464 ;
1465
1466 ; APIRET _Pascal DosOpen(PSZ pszFname, PHFILE phfOpen, PUSHORT pusAction,
1467 ; ULONG ulFSize, USHORT usAttr, USHORT fsOpenFlags,
1468 ; USHORT fsOpenMode, ULONG ulReserved);
1469 mov di, '0'
1470 push seg g_szOemHlpDevName ; pszFname
1471 push g_szOemHlpDevName
1472 push ss ; phfOpen
1473 lea dx, [hfOpen]
1474 push dx
1475 push ss ; pusAction
1476 lea dx, [usAction]
1477 push dx
1478 push dword 0 ; ulFSize
1479 push 0 ; usAttr = FILE_NORMAL
1480 push 1 ; fsOpenFlags = FILE_OPEN
1481 push 00040h ; fsOpenMode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY
1482 push dword 0 ; ulReserved
1483 call far DOS16OPEN
1484 or ax, ax
1485 jnz near .done
1486
1487
1488 ;
1489 ; Send a PCI_FIND_DEVICE request.
1490 ;
1491
1492 ; Initialize the parameter packet.
1493 mov [abParm + 0], byte PCI_FIND_DEVICE ; 0 - db - SubFunction Number
1494 mov [abParm + 1], word VMMDEV_DEVICEID ; 1 - dw - Device ID
1495 mov [abParm + 3], word VBOX_PCI_VENDORID ; 3 - dw - Vendor ID
1496 mov [abParm + 5], byte 0 ; 5 - db - (Device) Index
1497
1498 ; Zero padd the data packet.
1499 mov [abData + 0], dword 0
1500
1501 mov di, '1'
1502 CallIOCtl 6, 3
1503
1504 mov al, [abData + 1] ; 1 - db - Bus Number.
1505 mov [NAME(g_bPciBusNo)], al
1506 mov al, [abData + 2] ; 2 - db - DevFunc Number.
1507 mov [NAME(g_bPciDevFunNo)], al
1508
1509 ;
1510 ; Read the interrupt register (byte).
1511 ;
1512 mov di, '2'
1513 mov ax, PCI_INTERRUPT_LINE | 0100h
1514 call .NestedReadReg
1515 mov [NAME(g_bInterruptLine)], al
1516
1517 ;
1518 ; Read the first base address (dword), this shall must be in I/O space.
1519 ;
1520 mov di, '3'
1521 mov ax, PCI_BASE_ADDRESS_0 | 0400h
1522 call .NestedReadReg
1523 mov di, '4'
1524 test al, 1h ; Test that it's an I/O space address.
1525 jz .done_err_close
1526 mov di, '5'
1527 test eax, 0ffff0002h ; These shall all be 0 according to the specs.
1528 jnz .done_err_close
1529 and ax, 0fffeh
1530 mov [NAME(g_IOPortBase)], ax
1531
1532 ;
1533 ; Read the second base address (dword), this shall be in memory space if present.
1534 ;
1535 mov di, '6'
1536 mov ax, PCI_BASE_ADDRESS_1 | 0400h
1537 call .NestedReadReg
1538 mov di, '7'
1539 test al, 1h ; Test that it's a memory space address.
1540 jnz .done_err_close
1541 and eax, 0fffffff0h
1542 mov [NAME(g_PhysMMIOBase)], eax
1543
1544 ;or eax, eax
1545 ;jz .done_success ; No memory region.
1546 ;; @todo If there is a simple way of determining the size do that, if
1547 ; not we can easily handle it the code that does the actual mapping.
1548
1549
1550 ;
1551 ; Ok, we're good!
1552 ;
1553.done_success:
1554 or [NAME(g_fFoundAdapter)], byte 1
1555 jmp .done_close
1556
1557 ;
1558 ; Close the OEMHLP$ driver.
1559 ;
1560.done_err_close:
1561 or ax, 80h
1562.done_close:
1563 ; APIRET APIENTRY DosClose(HFILE hf);
1564 push ax ; Save result
1565 mov cx, [hfOpen]
1566 push cx
1567 call far DOS16CLOSE
1568 or ax, ax
1569 jnz .bitch ; This can't happen (I hope).
1570 pop ax
1571 or ax, ax
1572 jnz .bitch
1573
1574 ;
1575 ; Return to vgdrvOS2EP_Init.
1576 ;
1577.done:
1578 mov esp, ebp
1579 pop ebp
1580 pop edi
1581 pop esi
1582 pop edx
1583 pop ecx
1584 pop ebx
1585 ret
1586
1587
1588 ;
1589 ; Puts the reason for failure in message buffer.
1590 ; The caller will flush this.
1591 ;
1592.bitch:
1593 push es
1594
1595 mov ax, ds
1596 mov es, ax
1597 mov ax, di ; save the reason.
1598 mov di, NAME(g_szInitText)
1599 add di, [NAME(g_cchInitText)]
1600
1601 mov si, g_achLoadFailureMsg1
1602 mov cx, g_cchLoadFailureMsg1
1603 rep movsb
1604
1605 stosb
1606
1607 mov si, g_achLoadFailureMsg2
1608 mov cx, g_cchLoadFailureMsg2
1609 rep movsb
1610
1611 mov [di], byte 0
1612 sub di, NAME(g_szInitText)
1613 mov [NAME(g_cchInitText)], di
1614
1615 pop es
1616 jmp .done
1617
1618
1619 ;
1620 ; Nested function which reads a PCI config register.
1621 ; (This operates on the vgdrvFindAdapter stack frame.)
1622 ;
1623 ; Input:
1624 ; al - register to read
1625 ; ah - register size.
1626 ;
1627 ; Output:
1628 ; eax - the value.
1629 ;
1630 ; Uses:
1631 ; dx
1632 ;
1633.NestedReadReg:
1634 ; Fill in the request packet.
1635 mov [abParm + 0], byte PCI_READ_CONFIG ; 0 - db - SubFunction Number
1636 mov dl, [NAME(g_bPciBusNo)]
1637 mov [abParm + 1], dl ; 1 - db - Bus Number
1638 mov dl, [NAME(g_bPciDevFunNo)]
1639 mov [abParm + 2], dl ; 2 - db - DevFunc Number
1640 mov [abParm + 3], al ; 3 - db - Configuration Register
1641 mov [abParm + 4], ah ; 4 - db - (Register) Size
1642
1643 ; Pad the data packet.
1644 mov [abData + 0], dword 0
1645 mov [abData + 4], dword 0
1646
1647 CallIOCtl 5, 5
1648
1649 mov eax, [abData + 1] ; 1 - dd - Data
1650
1651 ret
1652
1653ENDPROC vgdrvFindAdapter
1654
1655
1656
1657;;
1658; This must be present
1659segment DATA32
1660g_pfnDos16Write:
1661 dd DOS16WRITE ; flat
1662
1663
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette