VirtualBox

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

Last change on this file since 69922 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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