VirtualBox

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

Last change on this file was 100274, checked in by vboxsync, 11 months ago

Additions/VBoxGuest-os2: Changeset r157982 added an additional argument
to VGDrvCommonInitDevExt() but missed updating one of the callers in the
OS/2 Guest Additions. Attempt at a follow-up build fix to r157982.
bugref:10457

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

© 2023 Oracle
ContactPrivacy policyTerms of Use