VirtualBox

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

Last change on this file since 7072 was 6654, checked in by vboxsync, 17 years ago

Unbroke the OS/2 additions build.

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