VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku.c@ 95798

Last change on this file since 95798 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.7 KB
Line 
1/* $Id: VBoxGuest-haiku.c 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VBoxGuest kernel module, Haiku Guest Additions, implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2022 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*
28 * This code is based on:
29 *
30 * VirtualBox Guest Additions for Haiku.
31 * Copyright (c) 2011 Mike Smith <[email protected]>
32 * François Revol <[email protected]>
33 *
34 * Permission is hereby granted, free of charge, to any person
35 * obtaining a copy of this software and associated documentation
36 * files (the "Software"), to deal in the Software without
37 * restriction, including without limitation the rights to use,
38 * copy, modify, merge, publish, distribute, sublicense, and/or sell
39 * copies of the Software, and to permit persons to whom the
40 * Software is furnished to do so, subject to the following
41 * conditions:
42 *
43 * The above copyright notice and this permission notice shall be
44 * included in all copies or substantial portions of the Software.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
48 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
50 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
51 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
52 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
53 * OTHER DEALINGS IN THE SOFTWARE.
54 */
55
56
57/*********************************************************************************************************************************
58* Header Files *
59*********************************************************************************************************************************/
60#define IN_VBOXGUEST
61#include <sys/param.h>
62#include <sys/types.h>
63#include <sys/uio.h>
64#include <OS.h>
65#include <Drivers.h>
66#include <KernelExport.h>
67#include <PCI.h>
68
69#include "VBoxGuest-haiku.h"
70#include "VBoxGuestInternal.h"
71#include <VBox/log.h>
72#include <iprt/assert.h>
73#include <iprt/initterm.h>
74#include <iprt/process.h>
75#include <iprt/mem.h>
76#include <iprt/memobj.h>
77#include <iprt/asm.h>
78#include <iprt/timer.h>
79#include <iprt/heap.h>
80
81
82/*********************************************************************************************************************************
83* Defined Constants And Macros *
84*********************************************************************************************************************************/
85#define MODULE_NAME VBOXGUEST_MODULE_NAME
86
87
88/*********************************************************************************************************************************
89* Internal Functions *
90*********************************************************************************************************************************/
91/*
92 * IRQ related functions.
93 */
94static void vgdrvHaikuRemoveIRQ(void *pvState);
95static int vgdrvHaikuAddIRQ(void *pvState);
96static int32 vgdrvHaikuISR(void *pvState);
97
98
99/*********************************************************************************************************************************
100* Global Variables *
101*********************************************************************************************************************************/
102static status_t std_ops(int32 op, ...);
103
104static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
105
106int32 api_version = B_CUR_DRIVER_API_VERSION;
107
108/** List of cloned device. Managed by the kernel. */
109//static struct clonedevs *g_pvgdrvHaikuClones;
110/** The dev_clone event handler tag. */
111//static eventhandler_tag g_vgdrvHaikuEHTag;
112/** selinfo structure used for polling. */
113//static struct selinfo g_SelInfo;
114/** PCI Bus Manager Module */
115static pci_module_info *gPCI;
116
117static struct vboxguest_module_info g_VBoxGuest =
118{
119 {
120 MODULE_NAME,
121 0,
122 std_ops
123 },
124 { 0 },
125 { 0 },
126 0,
127 RTLogBackdoorPrintf,
128 RTLogBackdoorPrintfV,
129 RTLogSetDefaultInstanceThread,
130 RTMemAllocExTag,
131 RTMemContAlloc,
132 RTMemContFree,
133 RTMemFreeEx,
134 RTMpIsCpuPossible,
135 RTMpNotificationDeregister,
136 RTMpNotificationRegister,
137 RTMpOnAll,
138 RTMpOnOthers,
139 RTMpOnSpecific,
140 RTPowerNotificationDeregister,
141 RTPowerNotificationRegister,
142 RTPowerSignalEvent,
143 RTR0AssertPanicSystem,
144 RTR0Init,
145 RTR0MemObjAddress,
146 RTR0MemObjAddressR3,
147 RTR0MemObjAllocContTag,
148 RTR0MemObjAllocLowTag,
149 RTR0MemObjAllocPageTag,
150 RTR0MemObjAllocPhysExTag,
151 RTR0MemObjAllocPhysNCTag,
152 RTR0MemObjAllocPhysTag,
153 RTR0MemObjEnterPhysTag,
154 RTR0MemObjFree,
155 RTR0MemObjGetPagePhysAddr,
156 RTR0MemObjIsMapping,
157 RTR0MemObjLockKernelTag,
158 RTR0MemObjLockUserTag,
159 RTR0MemObjMapKernelExTag,
160 RTR0MemObjMapKernelTag,
161 RTR0MemObjMapUserTag,
162 RTR0MemObjProtect,
163 RTR0MemObjReserveKernelTag,
164 RTR0MemObjReserveUserTag,
165 RTR0MemObjSize,
166 RTR0ProcHandleSelf,
167 RTR0Term,
168 RTR0TermForced,
169 RTProcSelf,
170 RTSemEventGetResolution,
171 RTSemEventMultiGetResolution,
172 RTSemEventMultiWaitEx,
173 RTSemEventMultiWaitExDebug,
174 RTSemEventWaitEx,
175 RTSemEventWaitExDebug,
176 RTThreadIsInInterrupt,
177 RTThreadPreemptDisable,
178 RTThreadPreemptIsEnabled,
179 RTThreadPreemptIsPending,
180 RTThreadPreemptIsPendingTrusty,
181 RTThreadPreemptIsPossible,
182 RTThreadPreemptRestore,
183 RTTimerGetSystemGranularity,
184 RTTimerReleaseSystemGranularity,
185 RTTimerRequestSystemGranularity,
186 RTSpinlockAcquire,
187 RTSpinlockRelease,
188 RTMemTmpAllocTag,
189 RTMemTmpFree,
190 RTLogDefaultInstance,
191 RTLogDefaultInstanceEx,
192 RTLogRelGetDefaultInstance,
193 RTLogRelGetDefaultInstanceEx,
194 RTErrConvertToErrno,
195 VGDrvCommonIoCtl,
196 VGDrvCommonCreateUserSession,
197 VGDrvCommonCloseSession,
198 VBoxGuestIDCOpen,
199 VBoxGuestIDCClose,
200 VBoxGuestIDCCall,
201 RTAssertMsg1Weak,
202 RTAssertMsg2Weak,
203 RTAssertMsg2WeakV,
204 RTAssertShouldPanic,
205 RTSemFastMutexCreate,
206 RTSemFastMutexDestroy,
207 RTSemFastMutexRelease,
208 RTSemFastMutexRequest,
209 RTSemMutexCreate,
210 RTSemMutexDestroy,
211 RTSemMutexRelease,
212 RTSemMutexRequest,
213 RTHeapSimpleRelocate,
214 RTHeapOffsetInit,
215 RTHeapSimpleInit,
216 RTHeapOffsetAlloc,
217 RTHeapSimpleAlloc,
218 RTHeapOffsetFree,
219 RTHeapSimpleFree
220};
221
222#if 0
223/**
224 * DEVFS event handler.
225 */
226static void vgdrvHaikuClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev)
227{
228 int iUnit;
229 int rc;
230
231 Log(("vgdrvHaikuClone: pszName=%s ppDev=%p\n", pszName, ppDev));
232
233 /*
234 * One device node per user, si_drv1 points to the session.
235 * /dev/vboxguest<N> where N = {0...255}.
236 */
237 if (!ppDev)
238 return;
239 if (strcmp(pszName, "vboxguest") == 0)
240 iUnit = -1;
241 else if (dev_stdclone(pszName, NULL, "vboxguest", &iUnit) != 1)
242 return;
243 if (iUnit >= 256)
244 {
245 Log(("vgdrvHaikuClone: iUnit=%d >= 256 - rejected\n", iUnit));
246 return;
247 }
248
249 Log(("vgdrvHaikuClone: pszName=%s iUnit=%d\n", pszName, iUnit));
250
251 rc = clone_create(&g_pvgdrvHaikuClones, &g_vgdrvHaikuDeviceHooks, &iUnit, ppDev, 0);
252 Log(("vgdrvHaikuClone: clone_create -> %d; iUnit=%d\n", rc, iUnit));
253 if (rc)
254 {
255 *ppDev = make_dev(&g_vgdrvHaikuDeviceHooks,
256 iUnit,
257 UID_ROOT,
258 GID_WHEEL,
259 0644,
260 "vboxguest%d", iUnit);
261 if (*ppDev)
262 {
263 dev_ref(*ppDev);
264 (*ppDev)->si_flags |= SI_CHEAPCLONE;
265 Log(("vgdrvHaikuClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
266 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
267 (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL;
268 }
269 else
270 Log(("vgdrvHaikuClone: make_dev iUnit=%d failed\n", iUnit));
271 }
272 else
273 Log(("vgdrvHaikuClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
274 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
275}
276#endif
277
278
279static status_t vgdrvHaikuDetach(void)
280{
281 struct VBoxGuestDeviceState *pState = &sState;
282
283 if (cUsers > 0)
284 return EBUSY;
285
286 /*
287 * Reverse what we did in vgdrvHaikuAttach.
288 */
289 vgdrvHaikuRemoveIRQ(pState);
290
291 if (pState->iVMMDevMemAreaId)
292 delete_area(pState->iVMMDevMemAreaId);
293
294 VGDrvCommonDeleteDevExt(&g_DevExt);
295
296#ifdef DO_LOG
297 RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
298 RTLogSetDefaultInstance(NULL);
299// RTLogDestroy(RTLogSetDefaultInstance(NULL));
300#endif
301
302 RTSpinlockDestroy(g_Spinlock);
303 g_Spinlock = NIL_RTSPINLOCK;
304
305 RTR0Term();
306 return B_OK;
307}
308
309
310/**
311 * Interrupt service routine.
312 *
313 * @returns Whether the interrupt was from VMMDev.
314 * @param pvState Opaque pointer to the device state.
315 */
316static int32 vgdrvHaikuISR(void *pvState)
317{
318 LogFlow((MODULE_NAME ":vgdrvHaikuISR pvState=%p\n", pvState));
319
320 bool fOurIRQ = VGDrvCommonISR(&g_DevExt);
321 if (fOurIRQ)
322 return B_HANDLED_INTERRUPT;
323 return B_UNHANDLED_INTERRUPT;
324}
325
326
327void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
328{
329 LogFlow(("VGDrvNativeISRMousePollEvent:\n"));
330
331 status_t err = B_OK;
332 //dprintf(MODULE_NAME ": isr mouse\n");
333
334 /*
335 * Wake up poll waiters.
336 */
337 //selwakeup(&g_SelInfo);
338 //XXX:notify_select_event();
339 RTSpinlockAcquire(g_Spinlock);
340
341 if (sState.selectSync)
342 {
343 //dprintf(MODULE_NAME ": isr mouse: notify\n");
344 notify_select_event(sState.selectSync, sState.selectEvent);
345 sState.selectEvent = (uint8_t)0;
346 sState.selectRef = (uint32_t)0;
347 sState.selectSync = NULL;
348 }
349 else
350 err = B_ERROR;
351
352 RTSpinlockRelease(g_Spinlock);
353}
354
355
356bool VGDrvNativeProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue)
357{
358 RT_NOREF(pDevExt); RT_NOREF(pszName); RT_NOREF(pszValue);
359 return false;
360}
361
362
363/**
364 * Sets IRQ for VMMDev.
365 *
366 * @returns Haiku error code.
367 * @param pvState Pointer to the state info structure.
368 */
369static int vgdrvHaikuAddIRQ(void *pvState)
370{
371 status_t err;
372 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
373
374 AssertReturn(pState, VERR_INVALID_PARAMETER);
375
376 err = install_io_interrupt_handler(pState->iIrqResId, vgdrvHaikuISR, pState, 0);
377 if (err == B_OK)
378 return VINF_SUCCESS;
379 return VERR_DEV_IO_ERROR;
380}
381
382
383/**
384 * Removes IRQ for VMMDev.
385 *
386 * @param pvState Opaque pointer to the state info structure.
387 */
388static void vgdrvHaikuRemoveIRQ(void *pvState)
389{
390 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
391 AssertPtr(pState);
392
393 remove_io_interrupt_handler(pState->iIrqResId, vgdrvHaikuISR, pState);
394}
395
396
397static status_t vgdrvHaikuAttach(const pci_info *pDevice)
398{
399 status_t status;
400 int rc;
401 int iResId;
402 struct VBoxGuestDeviceState *pState = &sState;
403 static const char *const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
404 PRTLOGGER pRelLogger;
405
406 AssertReturn(pDevice, B_BAD_VALUE);
407
408 cUsers = 0;
409
410 /*
411 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
412 */
413 rc = RTR0Init(0);
414 if (RT_FAILURE(rc))
415 {
416 dprintf(MODULE_NAME ": RTR0Init failed: %d\n", rc);
417 return ENXIO;
418 }
419
420 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "vgdrvHaiku");
421 if (RT_FAILURE(rc))
422 {
423 LogRel(("vgdrvHaikuAttach: RTSpinlock create failed. rc=%Rrc\n", rc));
424 return ENXIO;
425 }
426
427#ifdef DO_LOG
428 /*
429 * Create the release log.
430 * (We do that here instead of common code because we want to log
431 * early failures using the LogRel macro.)
432 */
433 rc = RTLogCreate(&pRelLogger, 0 | RTLOGFLAGS_PREFIX_THREAD /* fFlags */, "all",
434 "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
435 RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL);
436 dprintf(MODULE_NAME ": RTLogCreate: %d\n", rc);
437 if (RT_SUCCESS(rc))
438 {
439 //RTLogGroupSettings(pRelLogger, g_szLogGrp);
440 //RTLogFlags(pRelLogger, g_szLogFlags);
441 //RTLogDestinations(pRelLogger, "/var/log/vboxguest.log");
442 RTLogRelSetDefaultInstance(pRelLogger);
443 RTLogSetDefaultInstance(pRelLogger); //XXX
444 }
445#endif
446
447 /*
448 * Allocate I/O port resource.
449 */
450 pState->uIOPortBase = pDevice->u.h0.base_registers[0];
451 /** @todo check flags for IO? */
452 if (pState->uIOPortBase)
453 {
454 /*
455 * Map the MMIO region.
456 */
457 uint32 phys = pDevice->u.h0.base_registers[1];
458 /** @todo Check flags for mem? */
459 pState->VMMDevMemSize = pDevice->u.h0.base_register_sizes[1];
460 pState->iVMMDevMemAreaId = map_physical_memory("VirtualBox Guest MMIO", phys, pState->VMMDevMemSize,
461 B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
462 &pState->pMMIOBase);
463 if (pState->iVMMDevMemAreaId > 0 && pState->pMMIOBase)
464 {
465 /*
466 * Call the common device extension initializer.
467 */
468 rc = VGDrvCommonInitDevExt(&g_DevExt, pState->uIOPortBase, pState->pMMIOBase, pState->VMMDevMemSize,
469#if ARCH_BITS == 64
470 VBOXOSTYPE_Haiku_x64,
471#else
472 VBOXOSTYPE_Haiku,
473#endif
474 VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
475 if (RT_SUCCESS(rc))
476 {
477 /*
478 * Add IRQ of VMMDev.
479 */
480 pState->iIrqResId = pDevice->u.h0.interrupt_line;
481 rc = vgdrvHaikuAddIRQ(pState);
482 if (RT_SUCCESS(rc))
483 {
484 /*
485 * Read host configuration.
486 */
487 VGDrvCommonProcessOptionsFromHost(&g_DevExt);
488
489 LogRel((MODULE_NAME ": loaded successfully\n"));
490 return B_OK;
491 }
492
493 LogRel((MODULE_NAME ": VGDrvCommonInitDevExt failed.\n"));
494 VGDrvCommonDeleteDevExt(&g_DevExt);
495 }
496 else
497 LogRel((MODULE_NAME ": vgdrvHaikuAddIRQ failed.\n"));
498 }
499 else
500 LogRel((MODULE_NAME ": MMIO region setup failed.\n"));
501 }
502 else
503 LogRel((MODULE_NAME ": IOport setup failed.\n"));
504
505 RTR0Term();
506 return ENXIO;
507}
508
509
510static status_t vgdrvHaikuProbe(pci_info *pDevice)
511{
512 if ( pDevice->vendor_id == VMMDEV_VENDORID
513 && pDevice->device_id == VMMDEV_DEVICEID)
514 return B_OK;
515
516 return ENXIO;
517}
518
519
520status_t init_module(void)
521{
522 status_t err = B_ENTRY_NOT_FOUND;
523 pci_info info;
524 int ix = 0;
525
526 err = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
527 if (err != B_OK)
528 return err;
529
530 while ((*gPCI->get_nth_pci_info)(ix++, &info) == B_OK)
531 {
532 if (vgdrvHaikuProbe(&info) == 0)
533 {
534 /* We found it */
535 err = vgdrvHaikuAttach(&info);
536 return err;
537 }
538 }
539
540 return B_ENTRY_NOT_FOUND;
541}
542
543
544void uninit_module(void)
545{
546 vgdrvHaikuDetach();
547 put_module(B_PCI_MODULE_NAME);
548}
549
550
551static status_t std_ops(int32 op, ...)
552{
553 switch (op)
554 {
555 case B_MODULE_INIT:
556 return init_module();
557
558 case B_MODULE_UNINIT:
559 {
560 uninit_module();
561 return B_OK;
562 }
563
564 default:
565 return B_ERROR;
566 }
567}
568
569
570_EXPORT module_info *modules[] =
571{
572 (module_info *)&g_VBoxGuest,
573 NULL
574};
575
576/* Common code that depend on g_DevExt. */
577#include "VBoxGuestIDC-unix.c.h"
578
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