VirtualBox

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

Last change on this file since 97828 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

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