VirtualBox

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

Last change on this file since 76409 was 75779, checked in by vboxsync, 6 years ago

VBoxGuest-os2.c: Correctly set requestor. bugref:9105

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.2 KB
Line 
1/* $Id: VBoxGuest-os2.cpp 75779 2018-11-27 22:37:39Z 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 <[email protected]>
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 uint32_t fRequestor = VMMDEV_REQUESTOR_USERMODE
367 | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN
368 | VMMDEV_REQUESTOR_USR_ROOT /* everyone is root on OS/2 */
369 | VMMDEV_REQUESTOR_GRP_WHEEL /* and their admins */
370 | VMMDEV_REQUESTOR_NO_USER_DEVICE /** @todo implement /dev/vboxuser? */
371 | VMMDEV_REQUESTOR_CON_DONT_KNOW; /** @todo check screen group/whatever of process to see if console */
372 rc = VGDrvCommonCreateUserSession(&g_DevExt, fRequestor, &pSession);
373 if (RT_SUCCESS(rc))
374 {
375 pSession->sfn = sfn;
376
377 /*
378 * Insert it into the hash table.
379 */
380 unsigned iHash = SESSION_HASH(sfn);
381 RTSpinlockAcquire(g_Spinlock);
382 pSession->pNextHash = g_apSessionHashTab[iHash];
383 g_apSessionHashTab[iHash] = pSession;
384 RTSpinlockRelease(g_Spinlock);
385 }
386
387 Log(("vgdrvOS2Open: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
388 return rc;
389}
390
391
392DECLASM(int) vgdrvOS2Close(uint16_t sfn)
393{
394 Log(("vgdrvOS2Close: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
395
396 /*
397 * Remove from the hash table.
398 */
399 PVBOXGUESTSESSION pSession;
400 const RTPROCESS Process = RTProcSelf();
401 const unsigned iHash = SESSION_HASH(sfn);
402 RTSpinlockAcquire(g_Spinlock);
403
404 pSession = g_apSessionHashTab[iHash];
405 if (pSession)
406 {
407 if ( pSession->sfn == sfn
408 && pSession->Process == Process)
409 {
410 g_apSessionHashTab[iHash] = pSession->pNextHash;
411 pSession->pNextHash = NULL;
412 }
413 else
414 {
415 PVBOXGUESTSESSION pPrev = pSession;
416 pSession = pSession->pNextHash;
417 while (pSession)
418 {
419 if ( pSession->sfn == sfn
420 && pSession->Process == Process)
421 {
422 pPrev->pNextHash = pSession->pNextHash;
423 pSession->pNextHash = NULL;
424 break;
425 }
426
427 /* next */
428 pPrev = pSession;
429 pSession = pSession->pNextHash;
430 }
431 }
432 }
433 RTSpinlockRelease(g_Spinlock);
434 if (!pSession)
435 {
436 Log(("VBoxGuestIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
437 return VERR_INVALID_PARAMETER;
438 }
439
440 /*
441 * Close the session.
442 */
443 VGDrvCommonCloseSession(&g_DevExt, pSession);
444 return 0;
445}
446
447
448DECLASM(int) vgdrvOS2IOCtlFast(uint16_t sfn, uint8_t iFunction, int32_t *prc)
449{
450 /*
451 * Find the session.
452 */
453 const RTPROCESS Process = RTProcSelf();
454 const unsigned iHash = SESSION_HASH(sfn);
455 PVBOXGUESTSESSION pSession;
456
457 RTSpinlockAcquire(g_Spinlock);
458 pSession = g_apSessionHashTab[iHash];
459 if (pSession && pSession->Process != Process)
460 {
461 do pSession = pSession->pNextHash;
462 while ( pSession
463 && ( pSession->sfn != sfn
464 || pSession->Process != Process));
465 }
466 RTSpinlockRelease(g_Spinlock);
467 if (RT_UNLIKELY(!pSession))
468 {
469 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
470 return VERR_INVALID_PARAMETER;
471 }
472
473 /*
474 * Dispatch the fast IOCtl.
475 */
476 *prc = VGDrvCommonIoCtlFast(iFunction, &g_DevExt, pSession);
477 return 0;
478}
479
480
481/**
482 * 32-bit IDC service routine.
483 *
484 * @returns VBox status code.
485 * @param u32Session The session handle (PVBOXGUESTSESSION).
486 * @param iFunction The requested function.
487 * @param pReqHdr The input/output data buffer. The caller
488 * ensures that this cannot be swapped out, or that
489 * it's acceptable to take a page in fault in the
490 * current context. If the request doesn't take
491 * input or produces output, apssing NULL is okay.
492 * @param cbReq The size of the data buffer.
493 *
494 * @remark This is called from the 16-bit thunker as well as directly from the 32-bit clients.
495 */
496DECLASM(int) VGDrvOS2IDCService(uint32_t u32Session, unsigned iFunction, PVBGLREQHDR pReqHdr, size_t cbReq)
497{
498 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)u32Session;
499 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
500 AssertMsgReturn(pSession->sfn == 0xffff, ("%RX16\n", pSession->sfn), VERR_INVALID_HANDLE);
501 AssertMsgReturn(pSession->pDevExt == &g_DevExt, ("%p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
502
503 return VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pReqHdr, cbReq);
504}
505
506
507/**
508 * Worker for VBoxGuestOS2IDC, it creates the kernel session.
509 *
510 * @returns Pointer to the session.
511 */
512DECLASM(PVBOXGUESTSESSION) vgdrvOS2IDCConnect(void)
513{
514 PVBOXGUESTSESSION pSession;
515 int rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession);
516 if (RT_SUCCESS(rc))
517 {
518 pSession->sfn = 0xffff;
519 return pSession;
520 }
521 return NULL;
522}
523
524
525DECLASM(int) vgdrvOS2IOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData,
526 uint16_t *pcbParm, uint16_t *pcbData)
527{
528 /*
529 * Find the session.
530 */
531 const RTPROCESS Process = RTProcSelf();
532 const unsigned iHash = SESSION_HASH(sfn);
533 PVBOXGUESTSESSION pSession;
534
535 RTSpinlockAcquire(g_Spinlock);
536 pSession = g_apSessionHashTab[iHash];
537 if (pSession && pSession->Process != Process)
538 {
539 do pSession = pSession->pNextHash;
540 while ( pSession
541 && ( pSession->sfn != sfn
542 || pSession->Process != Process));
543 }
544 RTSpinlockRelease(g_Spinlock);
545 if (!pSession)
546 {
547 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
548 return VERR_INVALID_PARAMETER;
549 }
550
551 /*
552 * Verify the category and dispatch the IOCtl.
553 *
554 * The IOCtl call uses the parameter buffer as generic data input/output
555 * buffer similar to the one unix ioctl buffer argument. While the data
556 * buffer is not used.
557 */
558 if (RT_LIKELY(iCat == VBGL_IOCTL_CATEGORY))
559 {
560 Log(("vgdrvOS2IOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
561 if ( pvParm
562 && *pcbParm >= sizeof(VBGLREQHDR)
563 && *pcbData == 0)
564 {
565 /*
566 * Lock the buffer.
567 */
568 KernVMLock_t ParmLock;
569 int32_t rc = KernVMLock(VMDHL_WRITE, pvParm, *pcbParm, &ParmLock, (KernPageList_t *)-1, NULL);
570 if (rc == 0)
571 {
572 /*
573 * Process the IOCtl.
574 */
575 PVBGLREQHDR pReqHdr = (PVBGLREQHDR)pvParm;
576 rc = VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pReqHdr, *pcbParm);
577
578 /*
579 * Unlock the buffer.
580 */
581 *pcbParm = RT_SUCCESS(rc) ? pReqHdr->cbOut : sizeof(*pReqHdr);
582 int rc2 = KernVMUnlock(&ParmLock);
583 AssertMsg(rc2 == 0, ("rc2=%d\n", rc2)); NOREF(rc2);
584
585 Log2(("vgdrvOS2IOCtl: returns %d\n", rc));
586 return rc;
587 }
588 AssertMsgFailed(("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvParm, *pcbParm, &ParmLock, rc));
589 return VERR_LOCK_FAILED;
590 }
591 Log2(("vgdrvOS2IOCtl: returns VERR_INVALID_PARAMETER (iFunction=%#x)\n", iFunction));
592 return VERR_INVALID_PARAMETER;
593 }
594 return VERR_NOT_SUPPORTED;
595}
596
597
598/**
599 * 32-bit ISR, called by 16-bit assembly thunker in VBoxGuestA-os2.asm.
600 *
601 * @returns true if it's our interrupt, false it isn't.
602 */
603DECLASM(bool) vgdrvOS2ISR(void)
604{
605 Log(("vgdrvOS2ISR\n"));
606
607 return VGDrvCommonISR(&g_DevExt);
608}
609
610
611void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
612{
613 /* No polling on OS/2 */
614 NOREF(pDevExt);
615}
616
617
618bool VGDrvNativeProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue)
619{
620 RT_NOREF(pDevExt); RT_NOREF(pszName); RT_NOREF(pszValue);
621 return false;
622}
623
624
625#ifdef DEBUG_READ /** @todo figure out this one once and for all... */
626
627/**
628 * Callback for writing to the log buffer.
629 *
630 * @returns number of bytes written.
631 * @param pvArg Unused.
632 * @param pachChars Pointer to an array of utf-8 characters.
633 * @param cbChars Number of bytes in the character array pointed to by pachChars.
634 */
635static DECLCALLBACK(size_t) vgdrvOS2LogOutput(void *pvArg, const char *pachChars, size_t cbChars)
636{
637 size_t cchWritten = 0;
638 while (cbChars-- > 0)
639 {
640 const uint16_t offLogHead = g_offLogHead;
641 const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1);
642 if (offLogHeadNext == g_offLogTail)
643 break; /* no */
644 g_szLog[offLogHead] = *pachChars++;
645 g_offLogHead = offLogHeadNext;
646 cchWritten++;
647 }
648 return cchWritten;
649}
650
651
652int SUPR0Printf(const char *pszFormat, ...)
653{
654 va_list va;
655
656#if 0 //def DEBUG_bird
657 va_start(va, pszFormat);
658 RTLogComPrintfV(pszFormat, va);
659 va_end(va);
660#endif
661
662 va_start(va, pszFormat);
663 int cch = RTLogFormatV(vgdrvOS2LogOutput, NULL, pszFormat, va);
664 va_end(va);
665
666 return cch;
667}
668
669#endif /* DEBUG_READ */
670
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