VirtualBox

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

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