VirtualBox

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

Last change on this file since 68662 was 68570, checked in by vboxsync, 8 years ago

merging vbglioc r117736: OS/2 adjustments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
Line 
1/* $Id: VBoxGuest-os2.cpp 68570 2017-08-31 12:10:39Z vboxsync $ */
2/** @file
3 * VBoxGuest - OS/2 specifics.
4 */
5
6/*
7 * Copyright (C) 2007-2016 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 <[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/version.h>
54#include <iprt/assert.h>
55#include <iprt/initterm.h>
56#include <iprt/log.h>
57#include <iprt/memobj.h>
58#include <iprt/mem.h>
59#include <iprt/param.h>
60#include <iprt/process.h>
61#include <iprt/spinlock.h>
62#include <iprt/string.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 pReqHdr The input/output data buffer. The caller
469 * ensures that this cannot be swapped out, or that
470 * it's acceptable to take a page in fault in the
471 * current context. If the request doesn't take
472 * input or produces output, apssing NULL is okay.
473 * @param cbReq The size of the data buffer.
474 *
475 * @remark This is called from the 16-bit thunker as well as directly from the 32-bit clients.
476 */
477DECLASM(int) VGDrvOS2IDCService(uint32_t u32Session, unsigned iFunction, PVBGLREQHDR pReqHdr, size_t cbReq)
478{
479 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)u32Session;
480 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
481 AssertMsgReturn(pSession->sfn == 0xffff, ("%RX16\n", pSession->sfn), VERR_INVALID_HANDLE);
482 AssertMsgReturn(pSession->pDevExt == &g_DevExt, ("%p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
483
484 return VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pReqHdr, cbReq);
485}
486
487
488/**
489 * Worker for VBoxGuestOS2IDC, it creates the kernel session.
490 *
491 * @returns Pointer to the session.
492 */
493DECLASM(PVBOXGUESTSESSION) vgdrvOS2IDCConnect(void)
494{
495 PVBOXGUESTSESSION pSession;
496 int rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession);
497 if (RT_SUCCESS(rc))
498 {
499 pSession->sfn = 0xffff;
500 return pSession;
501 }
502 return NULL;
503}
504
505
506DECLASM(int) vgdrvOS2IOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData,
507 uint16_t *pcbParm, uint16_t *pcbData)
508{
509 /*
510 * Find the session.
511 */
512 const RTPROCESS Process = RTProcSelf();
513 const unsigned iHash = SESSION_HASH(sfn);
514 PVBOXGUESTSESSION pSession;
515
516 RTSpinlockAcquire(g_Spinlock);
517 pSession = g_apSessionHashTab[iHash];
518 if (pSession && pSession->Process != Process)
519 {
520 do pSession = pSession->pNextHash;
521 while ( pSession
522 && ( pSession->sfn != sfn
523 || pSession->Process != Process));
524 }
525 RTSpinlockRelease(g_Spinlock);
526 if (!pSession)
527 {
528 Log(("VBoxGuestIoctl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
529 return VERR_INVALID_PARAMETER;
530 }
531
532 /*
533 * Verify the category and dispatch the IOCtl.
534 *
535 * The IOCtl call uses the parameter buffer as generic data input/output
536 * buffer similar to the one unix ioctl buffer argument. While the data
537 * buffer is not used.
538 */
539 if (RT_LIKELY(iCat == VBGL_IOCTL_CATEGORY))
540 {
541 Log(("vgdrvOS2IOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
542 if ( pvParm
543 && *pcbParm >= sizeof(VBGLREQHDR)
544 && *pcbData == 0)
545 {
546 /*
547 * Lock the buffer.
548 */
549 KernVMLock_t ParmLock;
550 int32_t rc = KernVMLock(VMDHL_WRITE, pvParm, *pcbParm, &ParmLock, (KernPageList_t *)-1, NULL);
551 if (rc == 0)
552 {
553 /*
554 * Process the IOCtl.
555 */
556 PVBGLREQHDR pReqHdr = (PVBGLREQHDR)pvParm;
557 rc = VGDrvCommonIoCtl(iFunction, &g_DevExt, pSession, pReqHdr, *pcbParm);
558
559 /*
560 * Unlock the buffer.
561 */
562 *pcbParm = RT_SUCCESS(rc) ? pReqHdr->cbOut : sizeof(*pReqHdr);
563 int rc2 = KernVMUnlock(&ParmLock);
564 AssertMsg(rc2 == 0, ("rc2=%d\n", rc2)); NOREF(rc2);
565
566 Log2(("vgdrvOS2IOCtl: returns %d\n", rc));
567 return rc;
568 }
569 AssertMsgFailed(("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvParm, *pcbParm, &ParmLock, rc));
570 return VERR_LOCK_FAILED;
571 }
572 Log2(("vgdrvOS2IOCtl: returns VERR_INVALID_PARAMETER (iFunction=%#x)\n", iFunction));
573 return VERR_INVALID_PARAMETER;
574 }
575 return VERR_NOT_SUPPORTED;
576}
577
578
579/**
580 * 32-bit ISR, called by 16-bit assembly thunker in VBoxGuestA-os2.asm.
581 *
582 * @returns true if it's our interrupt, false it isn't.
583 */
584DECLASM(bool) vgdrvOS2ISR(void)
585{
586 Log(("vgdrvOS2ISR\n"));
587
588 return VGDrvCommonISR(&g_DevExt);
589}
590
591
592void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
593{
594 /* No polling on OS/2 */
595 NOREF(pDevExt);
596}
597
598
599#ifdef DEBUG_READ /** @todo figure out this one once and for all... */
600
601/**
602 * Callback for writing to the log buffer.
603 *
604 * @returns number of bytes written.
605 * @param pvArg Unused.
606 * @param pachChars Pointer to an array of utf-8 characters.
607 * @param cbChars Number of bytes in the character array pointed to by pachChars.
608 */
609static DECLCALLBACK(size_t) vgdrvOS2LogOutput(void *pvArg, const char *pachChars, size_t cbChars)
610{
611 size_t cchWritten = 0;
612 while (cbChars-- > 0)
613 {
614 const uint16_t offLogHead = g_offLogHead;
615 const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1);
616 if (offLogHeadNext == g_offLogTail)
617 break; /* no */
618 g_szLog[offLogHead] = *pachChars++;
619 g_offLogHead = offLogHeadNext;
620 cchWritten++;
621 }
622 return cchWritten;
623}
624
625
626int SUPR0Printf(const char *pszFormat, ...)
627{
628 va_list va;
629
630#if 0 //def DEBUG_bird
631 va_start(va, pszFormat);
632 RTLogComPrintfV(pszFormat, va);
633 va_end(va);
634#endif
635
636 va_start(va, pszFormat);
637 int cch = RTLogFormatV(vgdrvOS2LogOutput, NULL, pszFormat, va);
638 va_end(va);
639
640 return cch;
641}
642
643#endif /* DEBUG_READ */
644
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