VirtualBox

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

Last change on this file since 62484 was 58113, checked in by vboxsync, 9 years ago

VBoxGuest: Vbgd -> VGDrv, cleanups - will probably not build cleanly everywhere. :)

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