VirtualBox

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

Last change on this file since 21170 was 21170, checked in by vboxsync, 16 years ago

Additions: Mouse polling support in Solaris kernel module and minor common code changes.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette