VirtualBox

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

Last change on this file since 16684 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

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