VirtualBox

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

Last change on this file since 10639 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 23.4 KB
Line 
1/* $Id: VBoxGuest-os2.cpp 8155 2008-04-18 15:16:47Z vboxsync $ */
2/** @file
3 * VBoxGuest - OS/2 specifics.
4 */
5
6/*
7 * Copyright (C) 2007 knut st. osmundsen <[email protected]>
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 * 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 <[email protected]>
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
90__BEGIN_DECLS
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;
111__END_DECLS
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 else
163 rc = VBoxGuestInitDevExt(&g_DevExt, g_IOPortBase, NULL, 0,
164 vboxGuestOS2DetectVersion());
165 if (RT_SUCCESS(rc))
166 {
167 /*
168 * Initialize the session hash table.
169 */
170 rc = RTSpinlockCreate(&g_Spinlock);
171 if (RT_SUCCESS(rc))
172 {
173 /*
174 * Configure the interrupt handler.
175 */
176 if (g_bInterruptLine)
177 {
178 rc = VBoxGuestOS2SetIRQ(g_bInterruptLine);
179 if (rc)
180 {
181 Log(("VBoxGuestOS2SetIRQ(%d) -> %d\n", g_bInterruptLine, rc));
182 rc = RTErrConvertFromOS2(rc);
183 }
184 }
185 if (RT_SUCCESS(rc))
186 {
187 /*
188 * Success
189 */
190 if (fVerbose)
191 {
192 strcpy(&g_szInitText[0],
193 "\r\n"
194 "VirtualBox Guest Additions Driver for OS/2 version " VBOX_VERSION_STRING "\r\n"
195 "Copyright (C) 2008 Sun Microsystems, Inc.\r\n");
196 g_cchInitText = strlen(&g_szInitText[0]);
197 }
198 Log(("VBoxGuestOS2Init: Successfully loaded\n%s", g_szInitText));
199 return VINF_SUCCESS;
200 }
201
202 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: SetIrq failed for IRQ %#d, rc=%Vrc\n",
203 g_bInterruptLine, rc);
204 }
205 else
206 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: RTSpinlockCreate failed, rc=%Vrc\n", rc);
207 VBoxGuestDeleteDevExt(&g_DevExt);
208 }
209 else
210 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: VBoxGuestOS2InitDevExt failed, rc=%Vrc\n", rc);
211
212 int rc2 = RTR0MemObjFree(g_MemObjMMIO, true /* fFreeMappings */); AssertRC(rc2);
213 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
214 }
215 else
216 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: VBoxGuestOS2MapMMIO failed, rc=%Vrc\n", rc);
217 RTR0Term();
218 }
219 else
220 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxGuest.sys: RTR0Init failed, rc=%Vrc\n", rc);
221
222 RTLogBackdoorPrintf("VBoxGuestOS2Init: failed rc=%Vrc - %s", rc, &g_szInitText[0]);
223 return rc;
224}
225
226
227/**
228 * Maps the VMMDev memory.
229 *
230 * @returns VBox status code.
231 * @retval VERR_VERSION_MISMATCH The VMMDev memory didn't meet our expectations.
232 *
233 * @param pDevExt The device extension.
234 */
235static int vboxGuestOS2MapMemory(void)
236{
237 const RTCCPHYS PhysMMIOBase = g_PhysMMIOBase;
238
239 /*
240 * Did we find any MMIO region (0 or NIL)?
241 */
242 if ( !PhysMMIOBase
243 || PhysMMIOBase == NIL_RTCCPHYS)
244 {
245 Assert(g_MemMapMMIO != NIL_RTR0MEMOBJ);
246 return VINF_SUCCESS;
247 }
248
249 /*
250 * Create a physical memory object for it.
251 *
252 * Since we don't know the actual size (OS/2 doesn't at least), we make
253 * a qualified guess using the VMMDEV_RAM_SIZE.
254 */
255 size_t cb = RT_ALIGN_Z(VMMDEV_RAM_SIZE, PAGE_SIZE);
256 int rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb);
257 if (RT_FAILURE(rc))
258 {
259 cb = _4K;
260 rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb);
261 }
262 if (RT_FAILURE(rc))
263 {
264 Log(("vboxGuestOS2MapMemory: RTR0MemObjEnterPhys(,%RCp,%zx) -> %Rrc\n",
265 PhysMMIOBase, cb, rc));
266 return rc;
267 }
268
269 /*
270 * Map the object into kernel space.
271 *
272 * We want a normal mapping with normal caching, which good in two ways. First
273 * since the API doesn't have any flags indicating how the mapping should be cached.
274 * And second, because PGM doesn't necessarily respect the cache/writethru bits
275 * anyway for normal RAM.
276 */
277 rc = RTR0MemObjMapKernel(&g_MemMapMMIO, g_MemObjMMIO, (void *)-1, 0,
278 RTMEM_PROT_READ | RTMEM_PROT_WRITE);
279 if (RT_SUCCESS(rc))
280 {
281 /*
282 * Validate the VMM memory.
283 */
284 VMMDevMemory *pVMMDev = (VMMDevMemory *)RTR0MemObjAddress(g_MemMapMMIO);
285 Assert(pVMMDev);
286 if ( pVMMDev->u32Version == VMMDEV_MEMORY_VERSION
287 && pVMMDev->u32Size >= 32 /* just for checking sanity */)
288 {
289 /*
290 * Did we hit the the correct size? If not we'll have to
291 * redo the mapping using the correct size.
292 */
293 if (RT_ALIGN_32(pVMMDev->u32Size, PAGE_SIZE) == cb)
294 return VINF_SUCCESS;
295
296 Log(("vboxGuestOS2MapMemory: Actual size %#RX32 (tried %#zx)\n", pVMMDev->u32Size, cb));
297 cb = RT_ALIGN_32(pVMMDev->u32Size, PAGE_SIZE);
298
299 rc = RTR0MemObjFree(g_MemObjMMIO, true); AssertRC(rc);
300 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
301
302 rc = RTR0MemObjEnterPhys(&g_MemObjMMIO, PhysMMIOBase, cb);
303 if (RT_SUCCESS(rc))
304 {
305 rc = RTR0MemObjMapKernel(&g_MemMapMMIO, g_MemObjMMIO, (void *)-1, 0,
306 RTMEM_PROT_READ | RTMEM_PROT_WRITE);
307 if (RT_SUCCESS(rc))
308 return VINF_SUCCESS;
309
310 Log(("vboxGuestOS2MapMemory: RTR0MemObjMapKernel [%RCp,%zx] -> %Rrc (2nd)\n",
311 PhysMMIOBase, cb, rc));
312 }
313 else
314 Log(("vboxGuestOS2MapMemory: RTR0MemObjEnterPhys(,%RCp,%zx) -> %Rrc (2nd)\n",
315 PhysMMIOBase, cb, rc));
316 }
317 else
318 {
319 rc = VERR_VERSION_MISMATCH;
320 LogRel(("vboxGuestOS2MapMemory: Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32\n",
321 pVMMDev->u32Version, VMMDEV_MEMORY_VERSION, pVMMDev->u32Size));
322 }
323 }
324 else
325 Log(("vboxGuestOS2MapMemory: RTR0MemObjMapKernel [%RCp,%zx] -> %Rrc\n",
326 PhysMMIOBase, cb, rc));
327
328 int rc2 = RTR0MemObjFree(g_MemObjMMIO, true /* fFreeMappings */); AssertRC(rc2);
329 g_MemObjMMIO = g_MemMapMMIO = NIL_RTR0MEMOBJ;
330 return rc;
331}
332
333
334/**
335 * Called fromn VBoxGuestOS2Init to determin which OS/2 version this is.
336 *
337 * @returns VBox OS/2 type.
338 */
339static VBOXOSTYPE vboxGuestOS2DetectVersion(void)
340{
341 VBOXOSTYPE enmOSType = VBOXOSTYPE_OS2;
342
343#if 0 /** @todo dig up the version stuff from GIS later and verify that the numbers are actually decimal. */
344 unsigned uMajor, uMinor;
345 if (uMajor == 2)
346 {
347 if (uMinor >= 30 && uMinor < 40)
348 enmOSType = VBOXOSTYPE_OS2Warp3;
349 else if (uMinor >= 40 && uMinor < 45)
350 enmOSType = VBOXOSTYPE_OS2Warp4;
351 else if (uMinor >= 45 && uMinor < 50)
352 enmOSType = VBOXOSTYPE_OS2Warp45;
353 }
354#endif
355 return enmOSType;
356}
357
358
359DECLASM(int) VBoxGuestOS2Open(uint16_t sfn)
360{
361 int rc;
362 PVBOXGUESTSESSION pSession;
363
364 /*
365 * Create a new session.
366 */
367 rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession);
368 if (RT_SUCCESS(rc))
369 {
370 pSession->sfn = sfn;
371
372 /*
373 * Insert it into the hash table.
374 */
375 unsigned iHash = SESSION_HASH(sfn);
376 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
377 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
378 pSession->pNextHash = g_apSessionHashTab[iHash];
379 g_apSessionHashTab[iHash] = pSession;
380 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
381 }
382
383 Log(("VBoxGuestOS2Open: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
384 return rc;
385}
386
387
388DECLASM(int) VBoxGuestOS2Close(uint16_t sfn)
389{
390 Log(("VBoxGuestOS2Close: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
391
392 /*
393 * Remove from the hash table.
394 */
395 PVBOXGUESTSESSION pSession;
396 const RTPROCESS Process = RTProcSelf();
397 const unsigned iHash = SESSION_HASH(sfn);
398 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
399 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
400
401 pSession = g_apSessionHashTab[iHash];
402 if (pSession)
403 {
404 if ( pSession->sfn == sfn
405 && pSession->Process == Process)
406 {
407 g_apSessionHashTab[iHash] = pSession->pNextHash;
408 pSession->pNextHash = NULL;
409 }
410 else
411 {
412 PVBOXGUESTSESSION pPrev = pSession;
413 pSession = pSession->pNextHash;
414 while (pSession)
415 {
416 if ( pSession->sfn == sfn
417 && pSession->Process == Process)
418 {
419 pPrev->pNextHash = pSession->pNextHash;
420 pSession->pNextHash = NULL;
421 break;
422 }
423
424 /* next */
425 pPrev = pSession;
426 pSession = pSession->pNextHash;
427 }
428 }
429 }
430 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
431 if (!pSession)
432 {
433 Log(("VBoxGuestIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
434 return VERR_INVALID_PARAMETER;
435 }
436
437 /*
438 * Close the session.
439 */
440 VBoxGuestCloseSession(&g_DevExt, pSession);
441 return 0;
442}
443
444
445DECLASM(int) VBoxGuestOS2IOCtlFast(uint16_t sfn, uint8_t iFunction, int32_t *prc)
446{
447 /*
448 * Find the session.
449 */
450 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
451 const RTPROCESS Process = RTProcSelf();
452 const unsigned iHash = SESSION_HASH(sfn);
453 PVBOXGUESTSESSION pSession;
454
455 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
456 pSession = g_apSessionHashTab[iHash];
457 if (pSession && pSession->Process != Process)
458 {
459 do pSession = pSession->pNextHash;
460 while ( pSession
461 && ( pSession->sfn != sfn
462 || pSession->Process != Process));
463 }
464 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
465 if (RT_UNLIKELY(!pSession))
466 {
467 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
468 return VERR_INVALID_PARAMETER;
469 }
470
471 /*
472 * Dispatch the fast IOCtl.
473 */
474 *prc = VBoxGuestCommonIOCtlFast(iFunction, &g_DevExt, pSession);
475 return 0;
476}
477
478
479/**
480 * 32-bit IDC service routine.
481 *
482 * @returns VBox status code.
483 * @param u32Session The session handle (PVBOXGUESTSESSION).
484 * @param iFunction The requested function.
485 * @param pvData The input/output data buffer. The caller ensures that this
486 * cannot be swapped out, or that it's acceptable to take a
487 * page in fault in the current context. If the request doesn't
488 * take input or produces output, apssing NULL is okay.
489 * @param cbData The size of the data buffer.
490 * @param pcbDataReturned Where to store the amount of data that's returned.
491 * This can be NULL if pvData is NULL.
492 *
493 * @remark This is called from the 16-bit thunker as well as directly from the 32-bit clients.
494 */
495DECLASM(int) VBoxGuestOS2IDCService(uint32_t u32Session, unsigned iFunction, void *pvData, size_t cbData, size_t *pcbDataReturned)
496{
497 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)u32Session;
498 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
499 AssertMsgReturn(pSession->sfn == 0xffff, ("%RX16\n", pSession->sfn), VERR_INVALID_HANDLE);
500 AssertMsgReturn(pSession->pDevExt == &g_DevExt, ("%p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
501
502 int rc;
503 switch (iFunction)
504 {
505 default:
506 rc = VBoxGuestCommonIOCtl(iFunction, &g_DevExt, pSession, pvData, cbData, pcbDataReturned);
507 break;
508
509 case VBOXGUEST_IOCTL_OS2_IDC_DISCONNECT:
510 pSession->sfn = 0;
511 VBoxGuestCloseSession(&g_DevExt, pSession);
512 rc = VINF_SUCCESS;
513 break;
514 }
515 return rc;
516}
517
518
519/**
520 * Worker for VBoxGuestOS2IDC, it creates the kernel session.
521 *
522 * @returns Pointer to the session.
523 */
524DECLASM(PVBOXGUESTSESSION) VBoxGuestOS2IDCConnect(void)
525{
526 PVBOXGUESTSESSION pSession;
527 int rc = VBoxGuestCreateKernelSession(&g_DevExt, &pSession);
528 if (RT_SUCCESS(rc))
529 {
530 pSession->sfn = 0xffff;
531 return pSession;
532 }
533 return NULL;
534}
535
536
537DECLASM(int) VBoxGuestOS2IOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData, uint16_t *pcbParm, uint16_t *pcbData)
538{
539 /*
540 * Find the session.
541 */
542 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
543 const RTPROCESS Process = RTProcSelf();
544 const unsigned iHash = SESSION_HASH(sfn);
545 PVBOXGUESTSESSION pSession;
546
547 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
548 pSession = g_apSessionHashTab[iHash];
549 if (pSession && pSession->Process != Process)
550 {
551 do pSession = pSession->pNextHash;
552 while ( pSession
553 && ( pSession->sfn != sfn
554 || pSession->Process != Process));
555 }
556 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
557 if (!pSession)
558 {
559 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
560 return VERR_INVALID_PARAMETER;
561 }
562
563 /*
564 * Verify the category and dispatch the IOCtl.
565 *
566 * The IOCtl call uses the parameter buffer as generic data input/output
567 * buffer similar to the one unix ioctl buffer argument. While the data
568 * buffer is used for passing the VBox status code back to the caller
569 * since the status codes that OS/2 accepts thru the DosDevIOCtl API is
570 * severely restricted.
571 */
572 if (RT_LIKELY(iCat == VBOXGUEST_IOCTL_CATEGORY))
573 {
574 Log(("VBoxGuestOS2IOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
575 Assert(pvParm || !*pcbData);
576 Assert(pvData);
577 Assert(*pcbData == sizeof(int32_t)); /* the return code */
578
579 /*
580 * Lock the buffers.
581 */
582 int32_t rc;
583 KernVMLock_t ParmLock;
584 if (pvParm)
585 {
586 Assert(*pcbData);
587 rc = KernVMLock(VMDHL_WRITE, pvParm, *pcbParm, &ParmLock, (KernPageList_t *)-1, NULL);
588 AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvParm, *pcbParm, &ParmLock, rc), VERR_LOCK_FAILED);
589 }
590
591#if 0 /* don't bother locking it since it's only 4 bytes (the return code). */
592 KernVMLock_t DataLock;
593 if (pvData)
594 {
595 Assert(*pcbData);
596 rc = KernVMLock(VMDHL_WRITE, pvData, *pcbData, &DataLock, (KernPageList_t *)-1, NULL);
597 if (rc)
598 {
599 AssertMsgFailed(("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvData, *pcbData, &DataLock, rc));
600 KernVMUnlock(&ParmLock);
601 return VERR_LOCK_FAILED;
602 }
603 }
604#endif
605
606 /*
607 * Process the IOCtl.
608 */
609 size_t cbDataReturned = 0;
610 rc = VBoxGuestCommonIOCtl(iFunction, &g_DevExt, pSession,
611 pvParm, *pcbParm, &cbDataReturned);
612
613 /*
614 * Unlock the buffers.
615 */
616 if (pvParm)
617 {
618 int rc2 = KernVMUnlock(&ParmLock);
619 AssertMsg(!rc2, ("rc2=%d\n", rc2)); NOREF(rc2);
620 AssertMsg(cbDataReturned < _64K, ("cbDataReturned=%d\n", cbDataReturned));
621 *pcbParm = cbDataReturned;
622 }
623#if 0
624 if (pvData)
625 {
626 int rc2 = KernVMUnlock(&DataLock);
627 AssertMsg(!rc2, ("rc2=%d\n", rc2));
628 }
629#else
630 rc = KernCopyOut(pvData, &rc, sizeof(int32_t));
631 AssertMsgReturn(!rc, ("KernCopyOut(%p, %p, sizeof(int32_t)) -> %d\n", pvData, &rc, rc), VERR_LOCK_FAILED);
632#endif
633
634 Log2(("VBoxGuestOS2IOCtl: returns VINF_SUCCESS / %d\n", rc));
635 return VINF_SUCCESS;
636 }
637 return VERR_NOT_SUPPORTED;
638}
639
640
641/**
642 * 32-bit ISR, called by 16-bit assembly thunker in VBoxGuestA-os2.asm.
643 *
644 * @returns true if it's our interrupt, false it isn't.
645 */
646DECLASM(bool) VBoxGuestOS2ISR(void)
647{
648 Log(("VBoxGuestOS2ISR\n"));
649
650 return VBoxGuestCommonISR(&g_DevExt);
651}
652
653
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 */
664static DECLCALLBACK(size_t) vboxGuestNativeLogOutput(void *pvArg, const char *pachChars, size_t cbChars)
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);
692 int cch = RTLogFormatV(vboxGuestNativeLogOutput, NULL, pszFormat, va);
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.

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