VirtualBox

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

Last change on this file since 62484 was 58113, checked in by vboxsync, 9 years ago

VBoxGuest: Vbgd -> VGDrv, cleanups - will probably not build cleanly everywhere. :)

  • 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 58113 2015-10-08 10:13:54Z 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 vgdrvOS2MapMemory(void);
112static VBOXOSTYPE vgdrvOS2DetectVersion(void);
113
114/* in VBoxGuestA-os2.asm */
115DECLASM(int) vgdrvOS2DevHlpSetIRQ(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) vgdrvOS2Init(const char *pszArgs)
127{
128 Log(("vgdrvOS2Init: 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 = vgdrvOS2MapMemory();
146 if (RT_SUCCESS(rc))
147 {
148 /*
149 * Initialize the device extension.
150 */
151 if (g_MemMapMMIO != NIL_RTR0MEMOBJ)
152 rc = VGDrvCommonInitDevExt(&g_DevExt, g_IOPortBase,
153 RTR0MemObjAddress(g_MemMapMMIO),
154 RTR0MemObjSize(g_MemMapMMIO),
155 vgdrvOS2DetectVersion(),
156 0);
157 else
158 rc = VGDrvCommonInitDevExt(&g_DevExt, g_IOPortBase, NULL, 0, vgdrvOS2DetectVersion(), 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 = vgdrvOS2DevHlpSetIRQ(g_bInterruptLine);
173 if (rc)
174 {
175 Log(("vgdrvOS2DevHlpSetIRQ(%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(("vgdrvOS2Init: 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 VGDrvCommonDeleteDevExt(&g_DevExt);
202 }
203 else
204 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: vgdrvOS2InitDevExt 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("vgdrvOS2Init: 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 */
227static int vgdrvOS2MapMemory(void)
228{
229 const RTCCPHYS PhysMMIOBase = g_PhysMMIOBase;
230
231 /*
232 * Did we find any MMIO region (0 or NIL)?
233 */
234 if ( !PhysMMIOBase
235 || PhysMMIOBase == NIL_RTCCPHYS)
236 {
237 Assert(g_MemMapMMIO != NIL_RTR0MEMOBJ);
238 return VINF_SUCCESS;
239 }
240
241 /*
242 * Create a physical memory object for it.
243 *
244 * Since we don't know the actual size (OS/2 doesn't at least), we make
245 * a qualified guess using the VMMDEV_RAM_SIZE.
246 */
247 size_t cb = RT_ALIGN_Z(VMMDEV_RAM_SIZE, PAGE_SIZE);
248 int rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
249 if (RT_FAILURE(rc))
250 {
251 cb = _4K;
252 rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
253 }
254 if (RT_FAILURE(rc))
255 {
256 Log(("vgdrvOS2MapMemory: RTR0MemObjEnterPhys(,%RCp,%zx) -> %Rrc\n", PhysMMIOBase, cb, rc));
257 return rc;
258 }
259
260 /*
261 * Map the object into kernel space.
262 *
263 * We want a normal mapping with normal caching, which good in two ways. First
264 * since the API doesn't have any flags indicating how the mapping should be cached.
265 * And second, because PGM doesn't necessarily respect the cache/writethru bits
266 * anyway for normal RAM.
267 */
268 rc = RTR0MemObjMapKernel(&g_MemMapMMIO, g_MemObjMMIO, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
269 if (RT_SUCCESS(rc))
270 {
271 /*
272 * Validate the VMM memory.
273 */
274 VMMDevMemory *pVMMDev = (VMMDevMemory *)RTR0MemObjAddress(g_MemMapMMIO);
275 Assert(pVMMDev);
276 if ( pVMMDev->u32Version == VMMDEV_MEMORY_VERSION
277 && pVMMDev->u32Size >= 32 /* just for checking sanity */)
278 {
279 /*
280 * Did we hit the correct size? If not we'll have to
281 * redo the mapping using the correct size.
282 */
283 if (RT_ALIGN_32(pVMMDev->u32Size, PAGE_SIZE) == cb)
284 return VINF_SUCCESS;
285
286 Log(("vgdrvOS2MapMemory: Actual size %#RX32 (tried %#zx)\n", pVMMDev->u32Size, cb));
287 cb = RT_ALIGN_32(pVMMDev->u32Size, PAGE_SIZE);
288
289 rc = RTR0MemObjFree(g_MemObjMMIO, true); AssertRC(rc);
290 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
291
292 rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb, RTMEM_CACHE_POLICY_DONT_CARE);
293 if (RT_SUCCESS(rc))
294 {
295 rc = RTR0MemObjMapKernel(&g_MemMapMMIO, g_MemObjMMIO, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
296 if (RT_SUCCESS(rc))
297 return VINF_SUCCESS;
298
299 Log(("vgdrvOS2MapMemory: RTR0MemObjMapKernel [%RCp,%zx] -> %Rrc (2nd)\n", PhysMMIOBase, cb, rc));
300 }
301 else
302 Log(("vgdrvOS2MapMemory: RTR0MemObjEnterPhys(,%RCp,%zx) -> %Rrc (2nd)\n", PhysMMIOBase, cb, rc));
303 }
304 else
305 {
306 rc = VERR_VERSION_MISMATCH;
307 LogRel(("vgdrvOS2MapMemory: Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32\n",
308 pVMMDev->u32Version, VMMDEV_MEMORY_VERSION, pVMMDev->u32Size));
309 }
310 }
311 else
312 Log(("vgdrvOS2MapMemory: RTR0MemObjMapKernel [%RCp,%zx] -> %Rrc\n", PhysMMIOBase, cb, rc));
313
314 int rc2 = RTR0MemObjFree(g_MemObjMMIO, true /* fFreeMappings */); AssertRC(rc2);
315 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
316 return rc;
317}
318
319
320/**
321 * Called fromn vgdrvOS2Init to determine which OS/2 version this is.
322 *
323 * @returns VBox OS/2 type.
324 */
325static VBOXOSTYPE vgdrvOS2DetectVersion(void)
326{
327 VBOXOSTYPE enmOSType = VBOXOSTYPE_OS2;
328
329#if 0 /** @todo dig up the version stuff from GIS later and verify that the numbers are actually decimal. */
330 unsigned uMajor, uMinor;
331 if (uMajor == 2)
332 {
333 if (uMinor >= 30 && uMinor < 40)
334 enmOSType = VBOXOSTYPE_OS2Warp3;
335 else if (uMinor >= 40 && uMinor < 45)
336 enmOSType = VBOXOSTYPE_OS2Warp4;
337 else if (uMinor >= 45 && uMinor < 50)
338 enmOSType = VBOXOSTYPE_OS2Warp45;
339 }
340#endif
341 return enmOSType;
342}
343
344
345DECLASM(int) vgdrvOS2Open(uint16_t sfn)
346{
347 int rc;
348 PVBOXGUESTSESSION pSession;
349
350 /*
351 * Create a new session.
352 */
353 rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession);
354 if (RT_SUCCESS(rc))
355 {
356 pSession->sfn = sfn;
357
358 /*
359 * Insert it into the hash table.
360 */
361 unsigned iHash = SESSION_HASH(sfn);
362 RTSpinlockAcquire(g_Spinlock);
363 pSession->pNextHash = g_apSessionHashTab[iHash];
364 g_apSessionHashTab[iHash] = pSession;
365 RTSpinlockRelease(g_Spinlock);
366 }
367
368 Log(("vgdrvOS2Open: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
369 return rc;
370}
371
372
373DECLASM(int) vgdrvOS2Close(uint16_t sfn)
374{
375 Log(("vgdrvOS2Close: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
376
377 /*
378 * Remove from the hash table.
379 */
380 PVBOXGUESTSESSION pSession;
381 const RTPROCESS Process = RTProcSelf();
382 const unsigned iHash = SESSION_HASH(sfn);
383 RTSpinlockAcquire(g_Spinlock);
384
385 pSession = g_apSessionHashTab[iHash];
386 if (pSession)
387 {
388 if ( pSession->sfn == sfn
389 && pSession->Process == Process)
390 {
391 g_apSessionHashTab[iHash] = pSession->pNextHash;
392 pSession->pNextHash = NULL;
393 }
394 else
395 {
396 PVBOXGUESTSESSION pPrev = pSession;
397 pSession = pSession->pNextHash;
398 while (pSession)
399 {
400 if ( pSession->sfn == sfn
401 && pSession->Process == Process)
402 {
403 pPrev->pNextHash = pSession->pNextHash;
404 pSession->pNextHash = NULL;
405 break;
406 }
407
408 /* next */
409 pPrev = pSession;
410 pSession = pSession->pNextHash;
411 }
412 }
413 }
414 RTSpinlockRelease(g_Spinlock);
415 if (!pSession)
416 {
417 Log(("VBoxGuestIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
418 return VERR_INVALID_PARAMETER;
419 }
420
421 /*
422 * Close the session.
423 */
424 VGDrvCommonCloseSession(&g_DevExt, pSession);
425 return 0;
426}
427
428
429DECLASM(int) vgdrvOS2IOCtlFast(uint16_t sfn, uint8_t iFunction, int32_t *prc)
430{
431 /*
432 * Find the session.
433 */
434 const RTPROCESS Process = RTProcSelf();
435 const unsigned iHash = SESSION_HASH(sfn);
436 PVBOXGUESTSESSION pSession;
437
438 RTSpinlockAcquire(g_Spinlock);
439 pSession = g_apSessionHashTab[iHash];
440 if (pSession && pSession->Process != Process)
441 {
442 do pSession = pSession->pNextHash;
443 while ( pSession
444 && ( pSession->sfn != sfn
445 || pSession->Process != Process));
446 }
447 RTSpinlockRelease(g_Spinlock);
448 if (RT_UNLIKELY(!pSession))
449 {
450 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
451 return VERR_INVALID_PARAMETER;
452 }
453
454 /*
455 * Dispatch the fast IOCtl.
456 */
457 *prc = VGDrvCommonIoCtlFast(iFunction, &g_DevExt, pSession);
458 return 0;
459}
460
461
462/**
463 * 32-bit IDC service routine.
464 *
465 * @returns VBox status code.
466 * @param u32Session The session handle (PVBOXGUESTSESSION).
467 * @param iFunction The requested function.
468 * @param pvData The input/output data buffer. The caller ensures that this
469 * cannot be swapped out, or that it's acceptable to take a
470 * page in fault in the current context. If the request doesn't
471 * take input or produces output, apssing NULL is okay.
472 * @param cbData The size of the data buffer.
473 * @param pcbDataReturned Where to store the amount of data that's returned.
474 * This can be NULL if pvData is NULL.
475 *
476 * @remark This is called from the 16-bit thunker as well as directly from the 32-bit clients.
477 */
478DECLASM(int) VGDrvOS2IDCService(uint32_t u32Session, unsigned iFunction, void *pvData, size_t cbData, size_t *pcbDataReturned)
479{
480 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)u32Session;
481 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
482 AssertMsgReturn(pSession->sfn == 0xffff, ("%RX16\n", pSession->sfn), VERR_INVALID_HANDLE);
483 AssertMsgReturn(pSession->pDevExt == &g_DevExt, ("%p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
484
485 int rc;
486 switch (iFunction)
487 {
488 default:
489 rc = VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pvData, cbData, pcbDataReturned);
490 break;
491
492 case VBOXGUEST_IOCTL_OS2_IDC_DISCONNECT:
493 pSession->sfn = 0;
494 VGDrvCommonCloseSession(&g_DevExt, pSession);
495 rc = VINF_SUCCESS;
496 break;
497 }
498 return rc;
499}
500
501
502/**
503 * Worker for VBoxGuestOS2IDC, it creates the kernel session.
504 *
505 * @returns Pointer to the session.
506 */
507DECLASM(PVBOXGUESTSESSION) vgdrvOS2IDCConnect(void)
508{
509 PVBOXGUESTSESSION pSession;
510 int rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession);
511 if (RT_SUCCESS(rc))
512 {
513 pSession->sfn = 0xffff;
514 return pSession;
515 }
516 return NULL;
517}
518
519
520DECLASM(int) vgdrvOS2IOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData,
521 uint16_t *pcbParm, uint16_t *pcbData)
522{
523 /*
524 * Find the session.
525 */
526 const RTPROCESS Process = RTProcSelf();
527 const unsigned iHash = SESSION_HASH(sfn);
528 PVBOXGUESTSESSION pSession;
529
530 RTSpinlockAcquire(g_Spinlock);
531 pSession = g_apSessionHashTab[iHash];
532 if (pSession && pSession->Process != Process)
533 {
534 do pSession = pSession->pNextHash;
535 while ( pSession
536 && ( pSession->sfn != sfn
537 || pSession->Process != Process));
538 }
539 RTSpinlockRelease(g_Spinlock);
540 if (!pSession)
541 {
542 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
543 return VERR_INVALID_PARAMETER;
544 }
545
546 /*
547 * Verify the category and dispatch the IOCtl.
548 *
549 * The IOCtl call uses the parameter buffer as generic data input/output
550 * buffer similar to the one unix ioctl buffer argument. While the data
551 * buffer is used for passing the VBox status code back to the caller
552 * since the status codes that OS/2 accepts thru the DosDevIOCtl API is
553 * severely restricted.
554 */
555 if (RT_LIKELY(iCat == VBOXGUEST_IOCTL_CATEGORY))
556 {
557 Log(("vgdrvOS2IOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
558 Assert(pvParm || !*pcbData);
559 Assert(pvData);
560 Assert(*pcbData == sizeof(int32_t)); /* the return code */
561
562 /*
563 * Lock the buffers.
564 */
565 int32_t rc;
566 KernVMLock_t ParmLock;
567 if (pvParm)
568 {
569 Assert(*pcbData);
570 rc = KernVMLock(VMDHL_WRITE, pvParm, *pcbParm, &ParmLock, (KernPageList_t *)-1, NULL);
571 AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvParm, *pcbParm, &ParmLock, rc), VERR_LOCK_FAILED);
572 }
573
574#if 0 /* don't bother locking it since it's only 4 bytes (the return code). */
575 KernVMLock_t DataLock;
576 if (pvData)
577 {
578 Assert(*pcbData);
579 rc = KernVMLock(VMDHL_WRITE, pvData, *pcbData, &DataLock, (KernPageList_t *)-1, NULL);
580 if (rc)
581 {
582 AssertMsgFailed(("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvData, *pcbData, &DataLock, rc));
583 KernVMUnlock(&ParmLock);
584 return VERR_LOCK_FAILED;
585 }
586 }
587#endif
588
589 /*
590 * Process the IOCtl.
591 */
592 size_t cbDataReturned;
593 rc = VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pvParm, *pcbParm, &cbDataReturned);
594
595 /*
596 * Unlock the buffers.
597 */
598 if (pvParm)
599 {
600 int rc2 = KernVMUnlock(&ParmLock);
601 AssertMsg(!rc2, ("rc2=%d\n", rc2)); NOREF(rc2);
602 AssertMsg(cbDataReturned < _64K, ("cbDataReturned=%d\n", cbDataReturned));
603 *pcbParm = cbDataReturned;
604 }
605#if 0
606 if (pvData)
607 {
608 int rc2 = KernVMUnlock(&DataLock);
609 AssertMsg(!rc2, ("rc2=%d\n", rc2));
610 }
611#else
612 rc = KernCopyOut(pvData, &rc, sizeof(int32_t));
613 AssertMsgReturn(!rc, ("KernCopyOut(%p, %p, sizeof(int32_t)) -> %d\n", pvData, &rc, rc), VERR_LOCK_FAILED);
614#endif
615
616 Log2(("vgdrvOS2IOCtl: returns VINF_SUCCESS / %d\n", rc));
617 return VINF_SUCCESS;
618 }
619 return VERR_NOT_SUPPORTED;
620}
621
622
623/**
624 * 32-bit ISR, called by 16-bit assembly thunker in VBoxGuestA-os2.asm.
625 *
626 * @returns true if it's our interrupt, false it isn't.
627 */
628DECLASM(bool) vgdrvOS2ISR(void)
629{
630 Log(("vgdrvOS2ISR\n"));
631
632 return VGDrvCommonISR(&g_DevExt);
633}
634
635
636void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
637{
638 /* No polling on OS/2 */
639 NOREF(pDevExt);
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