VirtualBox

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

Last change on this file since 57500 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.4 KB
Line 
1/* $Id: VBoxGuest-haiku.c 57358 2015-08-14 15:16:38Z 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 <[email protected]>
23 * François Revol <[email protected]>
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#define MODULE_NAME VBOXGUEST_MODULE_NAME
73
74/*
75 * IRQ related functions.
76 */
77static void VBoxGuestHaikuRemoveIRQ(void *pvState);
78static int VBoxGuestHaikuAddIRQ(void *pvState);
79static int32 VBoxGuestHaikuISR(void *pvState);
80
81/*
82 * Available functions for kernel drivers.
83 */
84DECLVBGL(int) VBoxGuestHaikuServiceCall(void *pvSession, unsigned uCmd, void *pvData, size_t cbData, size_t *pcbDataReturned);
85DECLVBGL(void *) VBoxGuestHaikuServiceOpen(uint32_t *pu32Version);
86DECLVBGL(int) VBoxGuestHaikuServiceClose(void *pvSession);
87DECLVBGL(void *) VBoxGuestIDCOpen(uint32_t *pu32Version);
88DECLVBGL(int) VBoxGuestIDCClose(void *pvSession);
89DECLVBGL(int) VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned);
90
91static status_t std_ops(int32 op, ...);
92
93static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
94
95int32 api_version = B_CUR_DRIVER_API_VERSION;
96
97/** List of cloned device. Managed by the kernel. */
98//static struct clonedevs *g_pVBoxGuestHaikuClones;
99/** The dev_clone event handler tag. */
100//static eventhandler_tag g_VBoxGuestHaikuEHTag;
101/** selinfo structure used for polling. */
102//static struct selinfo g_SelInfo;
103/** PCI Bus Manager Module */
104static pci_module_info *gPCI;
105
106static struct vboxguest_module_info g_VBoxGuest =
107{
108 {
109 MODULE_NAME,
110 0,
111 std_ops
112 },
113 { 0 },
114 { 0 },
115 0,
116 RTLogBackdoorPrintf,
117 RTLogBackdoorPrintfV,
118 RTLogSetDefaultInstanceThread,
119 RTMemAllocExTag,
120 RTMemContAlloc,
121 RTMemContFree,
122 RTMemFreeEx,
123 RTMpIsCpuPossible,
124 RTMpNotificationDeregister,
125 RTMpNotificationRegister,
126 RTMpOnAll,
127 RTMpOnOthers,
128 RTMpOnSpecific,
129 RTPowerNotificationDeregister,
130 RTPowerNotificationRegister,
131 RTPowerSignalEvent,
132 RTR0AssertPanicSystem,
133 RTR0Init,
134 RTR0MemObjAddress,
135 RTR0MemObjAddressR3,
136 RTR0MemObjAllocContTag,
137 RTR0MemObjAllocLowTag,
138 RTR0MemObjAllocPageTag,
139 RTR0MemObjAllocPhysExTag,
140 RTR0MemObjAllocPhysNCTag,
141 RTR0MemObjAllocPhysTag,
142 RTR0MemObjEnterPhysTag,
143 RTR0MemObjFree,
144 RTR0MemObjGetPagePhysAddr,
145 RTR0MemObjIsMapping,
146 RTR0MemObjLockKernelTag,
147 RTR0MemObjLockUserTag,
148 RTR0MemObjMapKernelExTag,
149 RTR0MemObjMapKernelTag,
150 RTR0MemObjMapUserTag,
151 RTR0MemObjProtect,
152 RTR0MemObjReserveKernelTag,
153 RTR0MemObjReserveUserTag,
154 RTR0MemObjSize,
155 RTR0ProcHandleSelf,
156 RTR0Term,
157 RTR0TermForced,
158 RTProcSelf,
159 RTSemEventGetResolution,
160 RTSemEventMultiGetResolution,
161 RTSemEventMultiWaitEx,
162 RTSemEventMultiWaitExDebug,
163 RTSemEventWaitEx,
164 RTSemEventWaitExDebug,
165 RTThreadIsInInterrupt,
166 RTThreadPreemptDisable,
167 RTThreadPreemptIsEnabled,
168 RTThreadPreemptIsPending,
169 RTThreadPreemptIsPendingTrusty,
170 RTThreadPreemptIsPossible,
171 RTThreadPreemptRestore,
172 RTTimerGetSystemGranularity,
173 RTTimerReleaseSystemGranularity,
174 RTTimerRequestSystemGranularity,
175 RTSpinlockAcquire,
176 RTSpinlockRelease,
177 RTMemTmpAllocTag,
178 RTMemTmpFree,
179 RTLogDefaultInstance,
180 RTLogDefaultInstanceEx,
181 RTLogRelGetDefaultInstance,
182 RTLogRelGetDefaultInstanceEx,
183 RTErrConvertToErrno,
184 VbgdCommonIoCtl,
185 VbgdCommonCreateUserSession,
186 VbgdCommonCloseSession,
187 VBoxGuestIDCOpen,
188 VBoxGuestIDCClose,
189 VBoxGuestIDCCall,
190 RTAssertMsg1Weak,
191 RTAssertMsg2Weak,
192 RTAssertMsg2WeakV,
193 RTAssertShouldPanic,
194 RTSemFastMutexCreate,
195 RTSemFastMutexDestroy,
196 RTSemFastMutexRelease,
197 RTSemFastMutexRequest,
198 RTSemMutexCreate,
199 RTSemMutexDestroy,
200 RTSemMutexRelease,
201 RTSemMutexRequest,
202 RTHeapSimpleRelocate,
203 RTHeapOffsetInit,
204 RTHeapSimpleInit,
205 RTHeapOffsetAlloc,
206 RTHeapSimpleAlloc,
207 RTHeapOffsetFree,
208 RTHeapSimpleFree
209};
210
211#if 0
212/**
213 * DEVFS event handler.
214 */
215static void VBoxGuestHaikuClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev)
216{
217 int iUnit;
218 int rc;
219
220 Log(("VBoxGuestHaikuClone: pszName=%s ppDev=%p\n", pszName, ppDev));
221
222 /*
223 * One device node per user, si_drv1 points to the session.
224 * /dev/vboxguest<N> where N = {0...255}.
225 */
226 if (!ppDev)
227 return;
228 if (strcmp(pszName, "vboxguest") == 0)
229 iUnit = -1;
230 else if (dev_stdclone(pszName, NULL, "vboxguest", &iUnit) != 1)
231 return;
232 if (iUnit >= 256)
233 {
234 Log(("VBoxGuestHaikuClone: iUnit=%d >= 256 - rejected\n", iUnit));
235 return;
236 }
237
238 Log(("VBoxGuestHaikuClone: pszName=%s iUnit=%d\n", pszName, iUnit));
239
240 rc = clone_create(&g_pVBoxGuestHaikuClones, &g_VBoxGuestHaikuDeviceHooks, &iUnit, ppDev, 0);
241 Log(("VBoxGuestHaikuClone: clone_create -> %d; iUnit=%d\n", rc, iUnit));
242 if (rc)
243 {
244 *ppDev = make_dev(&g_VBoxGuestHaikuDeviceHooks,
245 iUnit,
246 UID_ROOT,
247 GID_WHEEL,
248 0644,
249 "vboxguest%d", iUnit);
250 if (*ppDev)
251 {
252 dev_ref(*ppDev);
253 (*ppDev)->si_flags |= SI_CHEAPCLONE;
254 Log(("VBoxGuestHaikuClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
255 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
256 (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL;
257 }
258 else
259 Log(("VBoxGuestHaikuClone: make_dev iUnit=%d failed\n", iUnit));
260 }
261 else
262 Log(("VBoxGuestHaikuClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
263 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
264}
265#endif
266
267
268static status_t VBoxGuestHaikuDetach(void)
269{
270 struct VBoxGuestDeviceState *pState = &sState;
271
272 if (cUsers > 0)
273 return EBUSY;
274
275 /*
276 * Reverse what we did in VBoxGuestHaikuAttach.
277 */
278 VBoxGuestHaikuRemoveIRQ(pState);
279
280 if (pState->iVMMDevMemAreaId)
281 delete_area(pState->iVMMDevMemAreaId);
282
283 VbgdCommonDeleteDevExt(&g_DevExt);
284
285#ifdef DO_LOG
286 RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
287 RTLogSetDefaultInstance(NULL);
288// RTLogDestroy(RTLogSetDefaultInstance(NULL));
289#endif
290
291 RTSpinlockDestroy(g_Spinlock);
292 g_Spinlock = NIL_RTSPINLOCK;
293
294 RTR0Term();
295 return B_OK;
296}
297
298
299/**
300 * Interrupt service routine.
301 *
302 * @returns Whether the interrupt was from VMMDev.
303 * @param pvState Opaque pointer to the device state.
304 */
305static int32 VBoxGuestHaikuISR(void *pvState)
306{
307 LogFlow((MODULE_NAME ":VBoxGuestHaikuISR pvState=%p\n", pvState));
308
309 bool fOurIRQ = VbgdCommonISR(&g_DevExt);
310 if (fOurIRQ)
311 return B_HANDLED_INTERRUPT;
312 return B_UNHANDLED_INTERRUPT;
313}
314
315
316void VbgdNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
317{
318 LogFlow((MODULE_NAME "::NativeISRMousePollEvent:\n"));
319
320 status_t err = B_OK;
321 //dprintf(MODULE_NAME ": isr mouse\n");
322
323 /*
324 * Wake up poll waiters.
325 */
326 //selwakeup(&g_SelInfo);
327 //XXX:notify_select_event();
328 RTSpinlockAcquire(g_Spinlock);
329
330 if (sState.selectSync)
331 {
332 //dprintf(MODULE_NAME ": isr mouse: notify\n");
333 notify_select_event(sState.selectSync, sState.selectEvent);
334 sState.selectEvent = (uint8_t)0;
335 sState.selectRef = (uint32_t)0;
336 sState.selectSync = NULL;
337 }
338 else
339 err = B_ERROR;
340
341 RTSpinlockRelease(g_Spinlock);
342}
343
344
345/**
346 * Sets IRQ for VMMDev.
347 *
348 * @returns Haiku error code.
349 * @param pvState Pointer to the state info structure.
350 */
351static int VBoxGuestHaikuAddIRQ(void *pvState)
352{
353 status_t err;
354 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
355
356 AssertReturn(pState, VERR_INVALID_PARAMETER);
357
358 err = install_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState, 0);
359 if (err == B_OK)
360 return VINF_SUCCESS;
361 return VERR_DEV_IO_ERROR;
362}
363
364
365/**
366 * Removes IRQ for VMMDev.
367 *
368 * @param pvState Opaque pointer to the state info structure.
369 */
370static void VBoxGuestHaikuRemoveIRQ(void *pvState)
371{
372 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
373 AssertPtr(pState);
374
375 remove_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState);
376}
377
378
379static status_t VBoxGuestHaikuAttach(const pci_info *pDevice)
380{
381 status_t status;
382 int rc = VINF_SUCCESS;
383 int iResId = 0;
384 struct VBoxGuestDeviceState *pState = &sState;
385 static const char *const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
386 PRTLOGGER pRelLogger;
387
388 AssertReturn(pDevice, B_BAD_VALUE);
389
390 cUsers = 0;
391
392 /*
393 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
394 */
395 rc = RTR0Init(0);
396 if (RT_FAILURE(rc))
397 {
398 /** @todo r=ramshankar: use dprintf here. */
399 LogFunc(("RTR0Init failed.\n"));
400 return ENXIO;
401 }
402
403 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestHaiku");
404 if (RT_FAILURE(rc))
405 {
406 LogRel(("VBoxGuestHaikuAttach: RTSpinlock create failed. rc=%Rrc\n", rc));
407 return ENXIO;
408 }
409
410#ifdef DO_LOG
411 /*
412 * Create the release log.
413 * (We do that here instead of common code because we want to log
414 * early failures using the LogRel macro.)
415 */
416 rc = RTLogCreate(&pRelLogger, 0 | RTLOGFLAGS_PREFIX_THREAD /* fFlags */, "all",
417 "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
418 RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL);
419 dprintf(MODULE_NAME ": RTLogCreate: %d\n", rc);
420 if (RT_SUCCESS(rc))
421 {
422 //RTLogGroupSettings(pRelLogger, g_szLogGrp);
423 //RTLogFlags(pRelLogger, g_szLogFlags);
424 //RTLogDestinations(pRelLogger, "/var/log/vboxguest.log");
425 RTLogRelSetDefaultInstance(pRelLogger);
426 RTLogSetDefaultInstance(pRelLogger); //XXX
427 }
428#endif
429
430 /*
431 * Allocate I/O port resource.
432 */
433 pState->uIOPortBase = pDevice->u.h0.base_registers[0];
434 /* @todo check flags for IO? */
435 if (pState->uIOPortBase)
436 {
437 /*
438 * Map the MMIO region.
439 */
440 uint32 phys = pDevice->u.h0.base_registers[1];
441 /* @todo Check flags for mem? */
442 pState->VMMDevMemSize = pDevice->u.h0.base_register_sizes[1];
443 pState->iVMMDevMemAreaId = map_physical_memory("VirtualBox Guest MMIO", phys, pState->VMMDevMemSize,
444 B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
445 &pState->pMMIOBase);
446 if (pState->iVMMDevMemAreaId > 0 && pState->pMMIOBase)
447 {
448 /*
449 * Call the common device extension initializer.
450 */
451 rc = VbgdCommonInitDevExt(&g_DevExt, pState->uIOPortBase, pState->pMMIOBase, pState->VMMDevMemSize,
452#if ARCH_BITS == 64
453 VBOXOSTYPE_Haiku_x64,
454#else
455 VBOXOSTYPE_Haiku,
456#endif
457 VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
458 if (RT_SUCCESS(rc))
459 {
460 /*
461 * Add IRQ of VMMDev.
462 */
463 pState->iIrqResId = pDevice->u.h0.interrupt_line;
464 rc = VBoxGuestHaikuAddIRQ(pState);
465 if (RT_SUCCESS(rc))
466 {
467 LogRel((MODULE_NAME ": loaded successfully\n"));
468 return B_OK;
469 }
470
471 LogRel((MODULE_NAME ":VbgdCommonInitDevExt failed.\n"));
472 VbgdCommonDeleteDevExt(&g_DevExt);
473 }
474 else
475 LogRel((MODULE_NAME ":VBoxGuestHaikuAddIRQ failed.\n"));
476 }
477 else
478 LogRel((MODULE_NAME ":MMIO region setup failed.\n"));
479 }
480 else
481 LogRel((MODULE_NAME ":IOport setup failed.\n"));
482
483 RTR0Term();
484 return ENXIO;
485}
486
487
488static status_t VBoxGuestHaikuProbe(pci_info *pDevice)
489{
490 if ((pDevice->vendor_id == VMMDEV_VENDORID) && (pDevice->device_id == VMMDEV_DEVICEID))
491 return B_OK;
492
493 return ENXIO;
494}
495
496
497status_t init_module(void)
498{
499 status_t err = B_ENTRY_NOT_FOUND;
500 pci_info info;
501 int ix = 0;
502
503 err = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
504 if (err != B_OK)
505 return err;
506
507 while ((*gPCI->get_nth_pci_info)(ix++, &info) == B_OK)
508 {
509 if (VBoxGuestHaikuProbe(&info) == 0)
510 {
511 /* We found it */
512 err = VBoxGuestHaikuAttach(&info);
513 return err;
514 }
515 }
516
517 return B_ENTRY_NOT_FOUND;
518}
519
520
521void uninit_module(void)
522{
523 VBoxGuestHaikuDetach();
524 put_module(B_PCI_MODULE_NAME);
525}
526
527
528static status_t std_ops(int32 op, ...)
529{
530 switch (op)
531 {
532 case B_MODULE_INIT:
533 return init_module();
534
535 case B_MODULE_UNINIT:
536 {
537 uninit_module();
538 return B_OK;
539 }
540
541 default:
542 return B_ERROR;
543 }
544}
545
546
547_EXPORT module_info *modules[] =
548{
549 (module_info *)&g_VBoxGuest,
550 NULL
551};
552
553/* Common code that depend on g_DevExt. */
554#include "VBoxGuestIDC-unix.c.h"
555
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