VirtualBox

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

Last change on this file since 83563 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

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