VirtualBox

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

Last change on this file since 69496 was 69496, checked in by vboxsync, 8 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.3 KB
Line 
1/* $Id: VBoxGuest-os2.cpp 69496 2017-10-28 14:55:58Z vboxsync $ */
2/** @file
3 * VBoxGuest - OS/2 specifics.
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.215389.xyz. 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 specifics.
28 *
29 * Copyright (c) 2007-2012 knut st. osmundsen <bird-src-spam@anduin.net>
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#include <os2ddk/bsekee.h>
58
59#include "VBoxGuestInternal.h"
60#include <VBox/version.h>
61#include <iprt/assert.h>
62#include <iprt/initterm.h>
63#include <iprt/log.h>
64#include <iprt/memobj.h>
65#include <iprt/mem.h>
66#include <iprt/param.h>
67#include <iprt/process.h>
68#include <iprt/spinlock.h>
69#include <iprt/string.h>
70
71
72/*********************************************************************************************************************************
73* Global Variables *
74*********************************************************************************************************************************/
75/**
76 * Device extention & session data association structure.
77 */
78static VBOXGUESTDEVEXT g_DevExt;
79/** The memory object for the MMIO memory. */
80static RTR0MEMOBJ g_MemObjMMIO = NIL_RTR0MEMOBJ;
81/** The memory mapping object the MMIO memory. */
82static RTR0MEMOBJ g_MemMapMMIO = NIL_RTR0MEMOBJ;
83
84/** Spinlock protecting g_apSessionHashTab. */
85static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
86/** Hash table */
87static PVBOXGUESTSESSION g_apSessionHashTab[19];
88/** Calculates the index into g_apSessionHashTab.*/
89#define SESSION_HASH(sfn) ((sfn) % RT_ELEMENTS(g_apSessionHashTab))
90
91RT_C_DECLS_BEGIN
92/* Defined in VBoxGuestA-os2.asm */
93extern uint32_t g_PhysMMIOBase;
94extern uint32_t g_cbMMIO; /* 0 currently not set. */
95extern uint16_t g_IOPortBase;
96extern uint8_t g_bInterruptLine;
97extern uint8_t g_bPciBusNo;
98extern uint8_t g_bPciDevFunNo;
99extern RTFAR16 g_fpfnVBoxGuestOs2IDCService16;
100extern RTFAR16 g_fpfnVBoxGuestOs2IDCService16Asm;
101#ifdef DEBUG_READ
102/* (debugging) */
103extern uint16_t g_offLogHead;
104extern uint16_t volatile g_offLogTail;
105extern uint16_t const g_cchLogMax;
106extern char g_szLog[];
107#endif
108/* (init only:) */
109extern char g_szInitText[];
110extern uint16_t g_cchInitText;
111extern uint16_t g_cchInitTextMax;
112RT_C_DECLS_END
113
114
115/*********************************************************************************************************************************
116* Internal Functions *
117*********************************************************************************************************************************/
118static int vgdrvOS2MapMemory(void);
119static VBOXOSTYPE vgdrvOS2DetectVersion(void);
120
121/* in VBoxGuestA-os2.asm */
122DECLASM(int) vgdrvOS2DevHlpSetIRQ(uint8_t bIRQ);
123
124
125/**
126 * 32-bit Ring-0 initialization.
127 *
128 * This is called from VBoxGuestA-os2.asm upon the first open call to the vboxgst$ device.
129 *
130 * @returns 0 on success, non-zero on failure.
131 * @param pszArgs Pointer to the device arguments.
132 */
133DECLASM(int) vgdrvOS2Init(const char *pszArgs)
134{
135 Log(("vgdrvOS2Init: pszArgs='%s' MMIO=0x%RX32 IOPort=0x%RX16 Int=%#x Bus=%#x Dev=%#x Fun=%d\n",
136 pszArgs, g_PhysMMIOBase, g_IOPortBase, g_bInterruptLine, g_bPciBusNo, g_bPciDevFunNo >> 3, g_bPciDevFunNo & 7));
137
138 /*
139 * Initialize the runtime.
140 */
141 int rc = RTR0Init(0);
142 if (RT_SUCCESS(rc))
143 {
144 /*
145 * Process the commandline. Later.
146 */
147 bool fVerbose = true;
148
149 /*
150 * Map the MMIO memory if found.
151 */
152 rc = vgdrvOS2MapMemory();
153 if (RT_SUCCESS(rc))
154 {
155 /*
156 * Initialize the device extension.
157 */
158 if (g_MemMapMMIO != NIL_RTR0MEMOBJ)
159 rc = VGDrvCommonInitDevExt(&g_DevExt, g_IOPortBase,
160 RTR0MemObjAddress(g_MemMapMMIO),
161 RTR0MemObjSize(g_MemMapMMIO),
162 vgdrvOS2DetectVersion(),
163 0);
164 else
165 rc = VGDrvCommonInitDevExt(&g_DevExt, g_IOPortBase, NULL, 0, vgdrvOS2DetectVersion(), 0);
166 if (RT_SUCCESS(rc))
167 {
168 /*
169 * Initialize the session hash table.
170 */
171 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestOS2");
172 if (RT_SUCCESS(rc))
173 {
174 /*
175 * Configure the interrupt handler.
176 */
177 if (g_bInterruptLine)
178 {
179 rc = vgdrvOS2DevHlpSetIRQ(g_bInterruptLine);
180 if (rc)
181 {
182 Log(("vgdrvOS2DevHlpSetIRQ(%d) -> %d\n", g_bInterruptLine, rc));
183 rc = RTErrConvertFromOS2(rc);
184 }
185 }
186 if (RT_SUCCESS(rc))
187 {
188 /*
189 * Success
190 */
191 if (fVerbose)
192 {
193 strcpy(&g_szInitText[0],
194 "\r\n"
195 "VirtualBox Guest Additions Driver for OS/2 version " VBOX_VERSION_STRING "\r\n"
196 "Copyright (C) 2008-" VBOX_C_YEAR " " VBOX_VENDOR "\r\n");
197 g_cchInitText = strlen(&g_szInitText[0]);
198 }
199 Log(("vgdrvOS2Init: Successfully loaded\n%s", g_szInitText));
200 return VINF_SUCCESS;
201 }
202
203 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: SetIrq failed for IRQ %#d, rc=%Rrc\n",
204 g_bInterruptLine, rc);
205 }
206 else
207 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: RTSpinlockCreate failed, rc=%Rrc\n", rc);
208 VGDrvCommonDeleteDevExt(&g_DevExt);
209 }
210 else
211 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: vgdrvOS2InitDevExt failed, rc=%Rrc\n", rc);
212
213 int rc2 = RTR0MemObjFree(g_MemObjMMIO, true /* fFreeMappings */); AssertRC(rc2);
214 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
215 }
216 else
217 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: VBoxGuestOS2MapMMIO failed, rc=%Rrc\n", rc);
218 RTR0Term();
219 }
220 else
221 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: RTR0Init failed, rc=%Rrc\n", rc);
222
223 RTLogBackdoorPrintf("vgdrvOS2Init: failed rc=%Rrc - %s", rc, &g_szInitText[0]);
224 return rc;
225}
226
227
228/**
229 * Maps the VMMDev memory.
230 *
231 * @returns VBox status code.
232 * @retval VERR_VERSION_MISMATCH The VMMDev memory didn't meet our expectations.
233 */
234static int vgdrvOS2MapMemory(void)
235{
236 const RTCCPHYS PhysMMIOBase = g_PhysMMIOBase;
237
238 /*
239 * Did we find any MMIO region (0 or NIL)?
240 */
241 if ( !PhysMMIOBase
242 || PhysMMIOBase == NIL_RTCCPHYS)
243 {
244 Assert(g_MemMapMMIO != NIL_RTR0MEMOBJ);
245 return VINF_SUCCESS;
246 }
247
248 /*
249 * Create a physical memory object for it.
250 *
251 * Since we don't know the actual size (OS/2 doesn't at least), we make
252 * a qualified guess using the VMMDEV_RAM_SIZE.
253 */
254 size_t cb = RT_ALIGN_Z(VMMDEV_RAM_SIZE, PAGE_SIZE);
255 int rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
256 if (RT_FAILURE(rc))
257 {
258 cb = _4K;
259 rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
260 }
261 if (RT_FAILURE(rc))
262 {
263 Log(("vgdrvOS2MapMemory: RTR0MemObjEnterPhys(,%RCp,%zx) -> %Rrc\n", PhysMMIOBase, cb, rc));
264 return rc;
265 }
266
267 /*
268 * Map the object into kernel space.
269 *
270 * We want a normal mapping with normal caching, which good in two ways. First
271 * since the API doesn't have any flags indicating how the mapping should be cached.
272 * And second, because PGM doesn't necessarily respect the cache/writethru bits
273 * anyway for normal RAM.
274 */
275 rc = RTR0MemObjMapKernel(&g_MemMapMMIO, g_MemObjMMIO, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
276 if (RT_SUCCESS(rc))
277 {
278 /*
279 * Validate the VMM memory.
280 */
281 VMMDevMemory *pVMMDev = (VMMDevMemory *)RTR0MemObjAddress(g_MemMapMMIO);
282 Assert(pVMMDev);
283 if ( pVMMDev->u32Version == VMMDEV_MEMORY_VERSION
284 && pVMMDev->u32Size >= 32 /* just for checking sanity */)
285 {
286 /*
287 * Did we hit the correct size? If not we'll have to
288 * redo the mapping using the correct size.
289 */
290 if (RT_ALIGN_32(pVMMDev->u32Size, PAGE_SIZE) == cb)
291 return VINF_SUCCESS;
292
293 Log(("vgdrvOS2MapMemory: Actual size %#RX32 (tried %#zx)\n", pVMMDev->u32Size, cb));
294 cb = RT_ALIGN_32(pVMMDev->u32Size, PAGE_SIZE);
295
296 rc = RTR0MemObjFree(g_MemObjMMIO, true); AssertRC(rc);
297 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
298
299 rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
300 if (RT_SUCCESS(rc))
301 {
302 rc = RTR0MemObjMapKernel(&g_MemMapMMIO, g_MemObjMMIO, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
303 if (RT_SUCCESS(rc))
304 return VINF_SUCCESS;
305
306 Log(("vgdrvOS2MapMemory: RTR0MemObjMapKernel [%RCp,%zx] -> %Rrc (2nd)\n", PhysMMIOBase, cb, rc));
307 }
308 else
309 Log(("vgdrvOS2MapMemory: RTR0MemObjEnterPhys(,%RCp,%zx) -> %Rrc (2nd)\n", PhysMMIOBase, cb, rc));
310 }
311 else
312 {
313 rc = VERR_VERSION_MISMATCH;
314 LogRel(("vgdrvOS2MapMemory: Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32\n",
315 pVMMDev->u32Version, VMMDEV_MEMORY_VERSION, pVMMDev->u32Size));
316 }
317 }
318 else
319 Log(("vgdrvOS2MapMemory: RTR0MemObjMapKernel [%RCp,%zx] -> %Rrc\n", PhysMMIOBase, cb, rc));
320
321 int rc2 = RTR0MemObjFree(g_MemObjMMIO, true /* fFreeMappings */); AssertRC(rc2);
322 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
323 return rc;
324}
325
326
327/**
328 * Called fromn vgdrvOS2Init to determine which OS/2 version this is.
329 *
330 * @returns VBox OS/2 type.
331 */
332static VBOXOSTYPE vgdrvOS2DetectVersion(void)
333{
334 VBOXOSTYPE enmOSType = VBOXOSTYPE_OS2;
335
336#if 0 /** @todo dig up the version stuff from GIS later and verify that the numbers are actually decimal. */
337 unsigned uMajor, uMinor;
338 if (uMajor == 2)
339 {
340 if (uMinor >= 30 && uMinor < 40)
341 enmOSType = VBOXOSTYPE_OS2Warp3;
342 else if (uMinor >= 40 && uMinor < 45)
343 enmOSType = VBOXOSTYPE_OS2Warp4;
344 else if (uMinor >= 45 && uMinor < 50)
345 enmOSType = VBOXOSTYPE_OS2Warp45;
346 }
347#endif
348 return enmOSType;
349}
350
351
352DECLASM(int) vgdrvOS2Open(uint16_t sfn)
353{
354 int rc;
355 PVBOXGUESTSESSION pSession;
356
357 /*
358 * Create a new session.
359 */
360 rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession);
361 if (RT_SUCCESS(rc))
362 {
363 pSession->sfn = sfn;
364
365 /*
366 * Insert it into the hash table.
367 */
368 unsigned iHash = SESSION_HASH(sfn);
369 RTSpinlockAcquire(g_Spinlock);
370 pSession->pNextHash = g_apSessionHashTab[iHash];
371 g_apSessionHashTab[iHash] = pSession;
372 RTSpinlockRelease(g_Spinlock);
373 }
374
375 Log(("vgdrvOS2Open: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
376 return rc;
377}
378
379
380DECLASM(int) vgdrvOS2Close(uint16_t sfn)
381{
382 Log(("vgdrvOS2Close: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
383
384 /*
385 * Remove from the hash table.
386 */
387 PVBOXGUESTSESSION pSession;
388 const RTPROCESS Process = RTProcSelf();
389 const unsigned iHash = SESSION_HASH(sfn);
390 RTSpinlockAcquire(g_Spinlock);
391
392 pSession = g_apSessionHashTab[iHash];
393 if (pSession)
394 {
395 if ( pSession->sfn == sfn
396 && pSession->Process == Process)
397 {
398 g_apSessionHashTab[iHash] = pSession->pNextHash;
399 pSession->pNextHash = NULL;
400 }
401 else
402 {
403 PVBOXGUESTSESSION pPrev = pSession;
404 pSession = pSession->pNextHash;
405 while (pSession)
406 {
407 if ( pSession->sfn == sfn
408 && pSession->Process == Process)
409 {
410 pPrev->pNextHash = pSession->pNextHash;
411 pSession->pNextHash = NULL;
412 break;
413 }
414
415 /* next */
416 pPrev = pSession;
417 pSession = pSession->pNextHash;
418 }
419 }
420 }
421 RTSpinlockRelease(g_Spinlock);
422 if (!pSession)
423 {
424 Log(("VBoxGuestIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
425 return VERR_INVALID_PARAMETER;
426 }
427
428 /*
429 * Close the session.
430 */
431 VGDrvCommonCloseSession(&g_DevExt, pSession);
432 return 0;
433}
434
435
436DECLASM(int) vgdrvOS2IOCtlFast(uint16_t sfn, uint8_t iFunction, int32_t *prc)
437{
438 /*
439 * Find the session.
440 */
441 const RTPROCESS Process = RTProcSelf();
442 const unsigned iHash = SESSION_HASH(sfn);
443 PVBOXGUESTSESSION pSession;
444
445 RTSpinlockAcquire(g_Spinlock);
446 pSession = g_apSessionHashTab[iHash];
447 if (pSession && pSession->Process != Process)
448 {
449 do pSession = pSession->pNextHash;
450 while ( pSession
451 && ( pSession->sfn != sfn
452 || pSession->Process != Process));
453 }
454 RTSpinlockRelease(g_Spinlock);
455 if (RT_UNLIKELY(!pSession))
456 {
457 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
458 return VERR_INVALID_PARAMETER;
459 }
460
461 /*
462 * Dispatch the fast IOCtl.
463 */
464 *prc = VGDrvCommonIoCtlFast(iFunction, &g_DevExt, pSession);
465 return 0;
466}
467
468
469/**
470 * 32-bit IDC service routine.
471 *
472 * @returns VBox status code.
473 * @param u32Session The session handle (PVBOXGUESTSESSION).
474 * @param iFunction The requested function.
475 * @param pReqHdr The input/output data buffer. The caller
476 * ensures that this cannot be swapped out, or that
477 * it's acceptable to take a page in fault in the
478 * current context. If the request doesn't take
479 * input or produces output, apssing NULL is okay.
480 * @param cbReq The size of the data buffer.
481 *
482 * @remark This is called from the 16-bit thunker as well as directly from the 32-bit clients.
483 */
484DECLASM(int) VGDrvOS2IDCService(uint32_t u32Session, unsigned iFunction, PVBGLREQHDR pReqHdr, size_t cbReq)
485{
486 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)u32Session;
487 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
488 AssertMsgReturn(pSession->sfn == 0xffff, ("%RX16\n", pSession->sfn), VERR_INVALID_HANDLE);
489 AssertMsgReturn(pSession->pDevExt == &g_DevExt, ("%p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
490
491 return VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pReqHdr, cbReq);
492}
493
494
495/**
496 * Worker for VBoxGuestOS2IDC, it creates the kernel session.
497 *
498 * @returns Pointer to the session.
499 */
500DECLASM(PVBOXGUESTSESSION) vgdrvOS2IDCConnect(void)
501{
502 PVBOXGUESTSESSION pSession;
503 int rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession);
504 if (RT_SUCCESS(rc))
505 {
506 pSession->sfn = 0xffff;
507 return pSession;
508 }
509 return NULL;
510}
511
512
513DECLASM(int) vgdrvOS2IOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData,
514 uint16_t *pcbParm, uint16_t *pcbData)
515{
516 /*
517 * Find the session.
518 */
519 const RTPROCESS Process = RTProcSelf();
520 const unsigned iHash = SESSION_HASH(sfn);
521 PVBOXGUESTSESSION pSession;
522
523 RTSpinlockAcquire(g_Spinlock);
524 pSession = g_apSessionHashTab[iHash];
525 if (pSession && pSession->Process != Process)
526 {
527 do pSession = pSession->pNextHash;
528 while ( pSession
529 && ( pSession->sfn != sfn
530 || pSession->Process != Process));
531 }
532 RTSpinlockRelease(g_Spinlock);
533 if (!pSession)
534 {
535 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
536 return VERR_INVALID_PARAMETER;
537 }
538
539 /*
540 * Verify the category and dispatch the IOCtl.
541 *
542 * The IOCtl call uses the parameter buffer as generic data input/output
543 * buffer similar to the one unix ioctl buffer argument. While the data
544 * buffer is not used.
545 */
546 if (RT_LIKELY(iCat == VBGL_IOCTL_CATEGORY))
547 {
548 Log(("vgdrvOS2IOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
549 if ( pvParm
550 && *pcbParm >= sizeof(VBGLREQHDR)
551 && *pcbData == 0)
552 {
553 /*
554 * Lock the buffer.
555 */
556 KernVMLock_t ParmLock;
557 int32_t rc = KernVMLock(VMDHL_WRITE, pvParm, *pcbParm, &ParmLock, (KernPageList_t *)-1, NULL);
558 if (rc == 0)
559 {
560 /*
561 * Process the IOCtl.
562 */
563 PVBGLREQHDR pReqHdr = (PVBGLREQHDR)pvParm;
564 rc = VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pReqHdr, *pcbParm);
565
566 /*
567 * Unlock the buffer.
568 */
569 *pcbParm = RT_SUCCESS(rc) ? pReqHdr->cbOut : sizeof(*pReqHdr);
570 int rc2 = KernVMUnlock(&ParmLock);
571 AssertMsg(rc2 == 0, ("rc2=%d\n", rc2)); NOREF(rc2);
572
573 Log2(("vgdrvOS2IOCtl: returns %d\n", rc));
574 return rc;
575 }
576 AssertMsgFailed(("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvParm, *pcbParm, &ParmLock, rc));
577 return VERR_LOCK_FAILED;
578 }
579 Log2(("vgdrvOS2IOCtl: returns VERR_INVALID_PARAMETER (iFunction=%#x)\n", iFunction));
580 return VERR_INVALID_PARAMETER;
581 }
582 return VERR_NOT_SUPPORTED;
583}
584
585
586/**
587 * 32-bit ISR, called by 16-bit assembly thunker in VBoxGuestA-os2.asm.
588 *
589 * @returns true if it's our interrupt, false it isn't.
590 */
591DECLASM(bool) vgdrvOS2ISR(void)
592{
593 Log(("vgdrvOS2ISR\n"));
594
595 return VGDrvCommonISR(&g_DevExt);
596}
597
598
599void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
600{
601 /* No polling on OS/2 */
602 NOREF(pDevExt);
603}
604
605
606#ifdef DEBUG_READ /** @todo figure out this one once and for all... */
607
608/**
609 * Callback for writing to the log buffer.
610 *
611 * @returns number of bytes written.
612 * @param pvArg Unused.
613 * @param pachChars Pointer to an array of utf-8 characters.
614 * @param cbChars Number of bytes in the character array pointed to by pachChars.
615 */
616static DECLCALLBACK(size_t) vgdrvOS2LogOutput(void *pvArg, const char *pachChars, size_t cbChars)
617{
618 size_t cchWritten = 0;
619 while (cbChars-- > 0)
620 {
621 const uint16_t offLogHead = g_offLogHead;
622 const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1);
623 if (offLogHeadNext == g_offLogTail)
624 break; /* no */
625 g_szLog[offLogHead] = *pachChars++;
626 g_offLogHead = offLogHeadNext;
627 cchWritten++;
628 }
629 return cchWritten;
630}
631
632
633int SUPR0Printf(const char *pszFormat, ...)
634{
635 va_list va;
636
637#if 0 //def DEBUG_bird
638 va_start(va, pszFormat);
639 RTLogComPrintfV(pszFormat, va);
640 va_end(va);
641#endif
642
643 va_start(va, pszFormat);
644 int cch = RTLogFormatV(vgdrvOS2LogOutput, NULL, pszFormat, va);
645 va_end(va);
646
647 return cch;
648}
649
650#endif /* DEBUG_READ */
651
Note: See TracBrowser for help on using the repository browser.

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