VirtualBox

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

Last change on this file since 72293 was 70873, checked in by vboxsync, 7 years ago

VMMDev,VBoxGuest: Classify who is calling the host (part 1). bugref:9105

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.7 KB
Line 
1/* $Id: VBoxGuest-os2.cpp 70873 2018-02-05 18:13:55Z 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 * Read host configuration.
191 */
192 VGDrvCommonProcessOptionsFromHost(&g_DevExt);
193
194 /*
195 * Success
196 */
197 if (fVerbose)
198 {
199 strcpy(&g_szInitText[0],
200 "\r\n"
201 "VirtualBox Guest Additions Driver for OS/2 version " VBOX_VERSION_STRING "\r\n"
202 "Copyright (C) 2008-" VBOX_C_YEAR " " VBOX_VENDOR "\r\n");
203 g_cchInitText = strlen(&g_szInitText[0]);
204 }
205 Log(("vgdrvOS2Init: Successfully loaded\n%s", g_szInitText));
206 return VINF_SUCCESS;
207 }
208
209 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: SetIrq failed for IRQ %#d, rc=%Rrc\n",
210 g_bInterruptLine, rc);
211 }
212 else
213 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: RTSpinlockCreate failed, rc=%Rrc\n", rc);
214 VGDrvCommonDeleteDevExt(&g_DevExt);
215 }
216 else
217 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: vgdrvOS2InitDevExt failed, rc=%Rrc\n", rc);
218
219 int rc2 = RTR0MemObjFree(g_MemObjMMIO, true /* fFreeMappings */); AssertRC(rc2);
220 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
221 }
222 else
223 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: VBoxGuestOS2MapMMIO failed, rc=%Rrc\n", rc);
224 RTR0Term();
225 }
226 else
227 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: RTR0Init failed, rc=%Rrc\n", rc);
228
229 RTLogBackdoorPrintf("vgdrvOS2Init: failed rc=%Rrc - %s", rc, &g_szInitText[0]);
230 return rc;
231}
232
233
234/**
235 * Maps the VMMDev memory.
236 *
237 * @returns VBox status code.
238 * @retval VERR_VERSION_MISMATCH The VMMDev memory didn't meet our expectations.
239 */
240static int vgdrvOS2MapMemory(void)
241{
242 const RTCCPHYS PhysMMIOBase = g_PhysMMIOBase;
243
244 /*
245 * Did we find any MMIO region (0 or NIL)?
246 */
247 if ( !PhysMMIOBase
248 || PhysMMIOBase == NIL_RTCCPHYS)
249 {
250 Assert(g_MemMapMMIO != NIL_RTR0MEMOBJ);
251 return VINF_SUCCESS;
252 }
253
254 /*
255 * Create a physical memory object for it.
256 *
257 * Since we don't know the actual size (OS/2 doesn't at least), we make
258 * a qualified guess using the VMMDEV_RAM_SIZE.
259 */
260 size_t cb = RT_ALIGN_Z(VMMDEV_RAM_SIZE, PAGE_SIZE);
261 int rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
262 if (RT_FAILURE(rc))
263 {
264 cb = _4K;
265 rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
266 }
267 if (RT_FAILURE(rc))
268 {
269 Log(("vgdrvOS2MapMemory: RTR0MemObjEnterPhys(,%RCp,%zx) -> %Rrc\n", PhysMMIOBase, cb, rc));
270 return rc;
271 }
272
273 /*
274 * Map the object into kernel space.
275 *
276 * We want a normal mapping with normal caching, which good in two ways. First
277 * since the API doesn't have any flags indicating how the mapping should be cached.
278 * And second, because PGM doesn't necessarily respect the cache/writethru bits
279 * anyway for normal RAM.
280 */
281 rc = RTR0MemObjMapKernel(&g_MemMapMMIO, g_MemObjMMIO, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
282 if (RT_SUCCESS(rc))
283 {
284 /*
285 * Validate the VMM memory.
286 */
287 VMMDevMemory *pVMMDev = (VMMDevMemory *)RTR0MemObjAddress(g_MemMapMMIO);
288 Assert(pVMMDev);
289 if ( pVMMDev->u32Version == VMMDEV_MEMORY_VERSION
290 && pVMMDev->u32Size >= 32 /* just for checking sanity */)
291 {
292 /*
293 * Did we hit the correct size? If not we'll have to
294 * redo the mapping using the correct size.
295 */
296 if (RT_ALIGN_32(pVMMDev->u32Size, PAGE_SIZE) == cb)
297 return VINF_SUCCESS;
298
299 Log(("vgdrvOS2MapMemory: Actual size %#RX32 (tried %#zx)\n", pVMMDev->u32Size, cb));
300 cb = RT_ALIGN_32(pVMMDev->u32Size, PAGE_SIZE);
301
302 rc = RTR0MemObjFree(g_MemObjMMIO, true); AssertRC(rc);
303 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
304
305 rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
306 if (RT_SUCCESS(rc))
307 {
308 rc = RTR0MemObjMapKernel(&g_MemMapMMIO, g_MemObjMMIO, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
309 if (RT_SUCCESS(rc))
310 return VINF_SUCCESS;
311
312 Log(("vgdrvOS2MapMemory: RTR0MemObjMapKernel [%RCp,%zx] -> %Rrc (2nd)\n", PhysMMIOBase, cb, rc));
313 }
314 else
315 Log(("vgdrvOS2MapMemory: RTR0MemObjEnterPhys(,%RCp,%zx) -> %Rrc (2nd)\n", PhysMMIOBase, cb, rc));
316 }
317 else
318 {
319 rc = VERR_VERSION_MISMATCH;
320 LogRel(("vgdrvOS2MapMemory: Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32\n",
321 pVMMDev->u32Version, VMMDEV_MEMORY_VERSION, pVMMDev->u32Size));
322 }
323 }
324 else
325 Log(("vgdrvOS2MapMemory: RTR0MemObjMapKernel [%RCp,%zx] -> %Rrc\n", PhysMMIOBase, cb, rc));
326
327 int rc2 = RTR0MemObjFree(g_MemObjMMIO, true /* fFreeMappings */); AssertRC(rc2);
328 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
329 return rc;
330}
331
332
333/**
334 * Called fromn vgdrvOS2Init to determine which OS/2 version this is.
335 *
336 * @returns VBox OS/2 type.
337 */
338static VBOXOSTYPE vgdrvOS2DetectVersion(void)
339{
340 VBOXOSTYPE enmOSType = VBOXOSTYPE_OS2;
341
342#if 0 /** @todo dig up the version stuff from GIS later and verify that the numbers are actually decimal. */
343 unsigned uMajor, uMinor;
344 if (uMajor == 2)
345 {
346 if (uMinor >= 30 && uMinor < 40)
347 enmOSType = VBOXOSTYPE_OS2Warp3;
348 else if (uMinor >= 40 && uMinor < 45)
349 enmOSType = VBOXOSTYPE_OS2Warp4;
350 else if (uMinor >= 45 && uMinor < 50)
351 enmOSType = VBOXOSTYPE_OS2Warp45;
352 }
353#endif
354 return enmOSType;
355}
356
357
358DECLASM(int) vgdrvOS2Open(uint16_t sfn)
359{
360 int rc;
361 PVBOXGUESTSESSION pSession;
362
363 /*
364 * Create a new session.
365 */
366 rc = VGDrvCommonCreateUserSession(&g_DevExt, VMMDEV_REQUESTOR_USERMODE, &pSession);
367 if (RT_SUCCESS(rc))
368 {
369 pSession->sfn = sfn;
370
371 /*
372 * Insert it into the hash table.
373 */
374 unsigned iHash = SESSION_HASH(sfn);
375 RTSpinlockAcquire(g_Spinlock);
376 pSession->pNextHash = g_apSessionHashTab[iHash];
377 g_apSessionHashTab[iHash] = pSession;
378 RTSpinlockRelease(g_Spinlock);
379 }
380
381 Log(("vgdrvOS2Open: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
382 return rc;
383}
384
385
386DECLASM(int) vgdrvOS2Close(uint16_t sfn)
387{
388 Log(("vgdrvOS2Close: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
389
390 /*
391 * Remove from the hash table.
392 */
393 PVBOXGUESTSESSION pSession;
394 const RTPROCESS Process = RTProcSelf();
395 const unsigned iHash = SESSION_HASH(sfn);
396 RTSpinlockAcquire(g_Spinlock);
397
398 pSession = g_apSessionHashTab[iHash];
399 if (pSession)
400 {
401 if ( pSession->sfn == sfn
402 && pSession->Process == Process)
403 {
404 g_apSessionHashTab[iHash] = pSession->pNextHash;
405 pSession->pNextHash = NULL;
406 }
407 else
408 {
409 PVBOXGUESTSESSION pPrev = pSession;
410 pSession = pSession->pNextHash;
411 while (pSession)
412 {
413 if ( pSession->sfn == sfn
414 && pSession->Process == Process)
415 {
416 pPrev->pNextHash = pSession->pNextHash;
417 pSession->pNextHash = NULL;
418 break;
419 }
420
421 /* next */
422 pPrev = pSession;
423 pSession = pSession->pNextHash;
424 }
425 }
426 }
427 RTSpinlockRelease(g_Spinlock);
428 if (!pSession)
429 {
430 Log(("VBoxGuestIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
431 return VERR_INVALID_PARAMETER;
432 }
433
434 /*
435 * Close the session.
436 */
437 VGDrvCommonCloseSession(&g_DevExt, pSession);
438 return 0;
439}
440
441
442DECLASM(int) vgdrvOS2IOCtlFast(uint16_t sfn, uint8_t iFunction, int32_t *prc)
443{
444 /*
445 * Find the session.
446 */
447 const RTPROCESS Process = RTProcSelf();
448 const unsigned iHash = SESSION_HASH(sfn);
449 PVBOXGUESTSESSION pSession;
450
451 RTSpinlockAcquire(g_Spinlock);
452 pSession = g_apSessionHashTab[iHash];
453 if (pSession && pSession->Process != Process)
454 {
455 do pSession = pSession->pNextHash;
456 while ( pSession
457 && ( pSession->sfn != sfn
458 || pSession->Process != Process));
459 }
460 RTSpinlockRelease(g_Spinlock);
461 if (RT_UNLIKELY(!pSession))
462 {
463 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
464 return VERR_INVALID_PARAMETER;
465 }
466
467 /*
468 * Dispatch the fast IOCtl.
469 */
470 *prc = VGDrvCommonIoCtlFast(iFunction, &g_DevExt, pSession);
471 return 0;
472}
473
474
475/**
476 * 32-bit IDC service routine.
477 *
478 * @returns VBox status code.
479 * @param u32Session The session handle (PVBOXGUESTSESSION).
480 * @param iFunction The requested function.
481 * @param pReqHdr The input/output data buffer. The caller
482 * ensures that this cannot be swapped out, or that
483 * it's acceptable to take a page in fault in the
484 * current context. If the request doesn't take
485 * input or produces output, apssing NULL is okay.
486 * @param cbReq The size of the data buffer.
487 *
488 * @remark This is called from the 16-bit thunker as well as directly from the 32-bit clients.
489 */
490DECLASM(int) VGDrvOS2IDCService(uint32_t u32Session, unsigned iFunction, PVBGLREQHDR pReqHdr, size_t cbReq)
491{
492 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)u32Session;
493 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
494 AssertMsgReturn(pSession->sfn == 0xffff, ("%RX16\n", pSession->sfn), VERR_INVALID_HANDLE);
495 AssertMsgReturn(pSession->pDevExt == &g_DevExt, ("%p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
496
497 return VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pReqHdr, cbReq);
498}
499
500
501/**
502 * Worker for VBoxGuestOS2IDC, it creates the kernel session.
503 *
504 * @returns Pointer to the session.
505 */
506DECLASM(PVBOXGUESTSESSION) vgdrvOS2IDCConnect(void)
507{
508 PVBOXGUESTSESSION pSession;
509 int rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession);
510 if (RT_SUCCESS(rc))
511 {
512 pSession->sfn = 0xffff;
513 return pSession;
514 }
515 return NULL;
516}
517
518
519DECLASM(int) vgdrvOS2IOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData,
520 uint16_t *pcbParm, uint16_t *pcbData)
521{
522 /*
523 * Find the session.
524 */
525 const RTPROCESS Process = RTProcSelf();
526 const unsigned iHash = SESSION_HASH(sfn);
527 PVBOXGUESTSESSION pSession;
528
529 RTSpinlockAcquire(g_Spinlock);
530 pSession = g_apSessionHashTab[iHash];
531 if (pSession && pSession->Process != Process)
532 {
533 do pSession = pSession->pNextHash;
534 while ( pSession
535 && ( pSession->sfn != sfn
536 || pSession->Process != Process));
537 }
538 RTSpinlockRelease(g_Spinlock);
539 if (!pSession)
540 {
541 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
542 return VERR_INVALID_PARAMETER;
543 }
544
545 /*
546 * Verify the category and dispatch the IOCtl.
547 *
548 * The IOCtl call uses the parameter buffer as generic data input/output
549 * buffer similar to the one unix ioctl buffer argument. While the data
550 * buffer is not used.
551 */
552 if (RT_LIKELY(iCat == VBGL_IOCTL_CATEGORY))
553 {
554 Log(("vgdrvOS2IOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
555 if ( pvParm
556 && *pcbParm >= sizeof(VBGLREQHDR)
557 && *pcbData == 0)
558 {
559 /*
560 * Lock the buffer.
561 */
562 KernVMLock_t ParmLock;
563 int32_t rc = KernVMLock(VMDHL_WRITE, pvParm, *pcbParm, &ParmLock, (KernPageList_t *)-1, NULL);
564 if (rc == 0)
565 {
566 /*
567 * Process the IOCtl.
568 */
569 PVBGLREQHDR pReqHdr = (PVBGLREQHDR)pvParm;
570 rc = VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pReqHdr, *pcbParm);
571
572 /*
573 * Unlock the buffer.
574 */
575 *pcbParm = RT_SUCCESS(rc) ? pReqHdr->cbOut : sizeof(*pReqHdr);
576 int rc2 = KernVMUnlock(&ParmLock);
577 AssertMsg(rc2 == 0, ("rc2=%d\n", rc2)); NOREF(rc2);
578
579 Log2(("vgdrvOS2IOCtl: returns %d\n", rc));
580 return rc;
581 }
582 AssertMsgFailed(("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvParm, *pcbParm, &ParmLock, rc));
583 return VERR_LOCK_FAILED;
584 }
585 Log2(("vgdrvOS2IOCtl: returns VERR_INVALID_PARAMETER (iFunction=%#x)\n", iFunction));
586 return VERR_INVALID_PARAMETER;
587 }
588 return VERR_NOT_SUPPORTED;
589}
590
591
592/**
593 * 32-bit ISR, called by 16-bit assembly thunker in VBoxGuestA-os2.asm.
594 *
595 * @returns true if it's our interrupt, false it isn't.
596 */
597DECLASM(bool) vgdrvOS2ISR(void)
598{
599 Log(("vgdrvOS2ISR\n"));
600
601 return VGDrvCommonISR(&g_DevExt);
602}
603
604
605void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
606{
607 /* No polling on OS/2 */
608 NOREF(pDevExt);
609}
610
611
612bool VGDrvNativeProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue)
613{
614 RT_NOREF(pDevExt); RT_NOREF(pszName); RT_NOREF(pszValue);
615 return false;
616}
617
618
619#ifdef DEBUG_READ /** @todo figure out this one once and for all... */
620
621/**
622 * Callback for writing to the log buffer.
623 *
624 * @returns number of bytes written.
625 * @param pvArg Unused.
626 * @param pachChars Pointer to an array of utf-8 characters.
627 * @param cbChars Number of bytes in the character array pointed to by pachChars.
628 */
629static DECLCALLBACK(size_t) vgdrvOS2LogOutput(void *pvArg, const char *pachChars, size_t cbChars)
630{
631 size_t cchWritten = 0;
632 while (cbChars-- > 0)
633 {
634 const uint16_t offLogHead = g_offLogHead;
635 const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1);
636 if (offLogHeadNext == g_offLogTail)
637 break; /* no */
638 g_szLog[offLogHead] = *pachChars++;
639 g_offLogHead = offLogHeadNext;
640 cchWritten++;
641 }
642 return cchWritten;
643}
644
645
646int SUPR0Printf(const char *pszFormat, ...)
647{
648 va_list va;
649
650#if 0 //def DEBUG_bird
651 va_start(va, pszFormat);
652 RTLogComPrintfV(pszFormat, va);
653 va_end(va);
654#endif
655
656 va_start(va, pszFormat);
657 int cch = RTLogFormatV(vgdrvOS2LogOutput, NULL, pszFormat, va);
658 va_end(va);
659
660 return cch;
661}
662
663#endif /* DEBUG_READ */
664
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