VirtualBox

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

Last change on this file since 56294 was 55980, checked in by vboxsync, 9 years ago

iprt/log.h,++: Added extended logger instance getters that also checks whether the given logger and group-flags are enabled, making the LogRel* checks more efficient in avoid uncessary RTLogLoggerEx parameter building and calls. Ditto for debug logging. The LOG_INSTANCE and LOG_REL_INSTANCE tricks are gone for now.

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