VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use