VirtualBox

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

Last change on this file since 78376 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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