VirtualBox

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

Last change on this file since 6118 was 6032, checked in by vboxsync, 17 years ago

Moved the MMIO mapping code myself. (probably doesn't compile now)

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