VirtualBox

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

Last change on this file since 56335 was 54608, checked in by vboxsync, 10 years ago

VBoxGuest: cleanups, mainly fixing and shortening function name prefixes.

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