VirtualBox

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

Last change on this file since 53402 was 52618, checked in by vboxsync, 10 years ago

HostDrivers, Runtime, Devices, Additions: TSC delta measurement and other changes resulting from bumping supdrv major version. TSC delta measurement currently disabled.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.2 KB
Line 
1/* $Id: VBoxGuest-haiku.c 52618 2014-09-05 12:07:29Z vboxsync $ */
2/** @file
3 * VBoxGuest kernel module, Haiku Guest Additions, implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2014 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* 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 RTLogRelDefaultInstance,
180 RTErrConvertToErrno,
181 VBoxGuestCommonIOCtl,
182 VBoxGuestCreateUserSession,
183 VBoxGuestCloseSession,
184 VBoxGuestIDCOpen,
185 VBoxGuestIDCClose,
186 VBoxGuestIDCCall,
187 RTAssertMsg1Weak,
188 RTAssertMsg2Weak,
189 RTAssertMsg2WeakV,
190 RTAssertShouldPanic,
191 RTSemFastMutexCreate,
192 RTSemFastMutexDestroy,
193 RTSemFastMutexRelease,
194 RTSemFastMutexRequest,
195 RTSemMutexCreate,
196 RTSemMutexDestroy,
197 RTSemMutexRelease,
198 RTSemMutexRequest,
199 RTHeapSimpleRelocate,
200 RTHeapOffsetInit,
201 RTHeapSimpleInit,
202 RTHeapOffsetAlloc,
203 RTHeapSimpleAlloc,
204 RTHeapOffsetFree,
205 RTHeapSimpleFree
206};
207
208#if 0
209/**
210 * DEVFS event handler.
211 */
212static void VBoxGuestHaikuClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev)
213{
214 int iUnit;
215 int rc;
216
217 Log(("VBoxGuestHaikuClone: pszName=%s ppDev=%p\n", pszName, ppDev));
218
219 /*
220 * One device node per user, si_drv1 points to the session.
221 * /dev/vboxguest<N> where N = {0...255}.
222 */
223 if (!ppDev)
224 return;
225 if (strcmp(pszName, "vboxguest") == 0)
226 iUnit = -1;
227 else if (dev_stdclone(pszName, NULL, "vboxguest", &iUnit) != 1)
228 return;
229 if (iUnit >= 256)
230 {
231 Log(("VBoxGuestHaikuClone: iUnit=%d >= 256 - rejected\n", iUnit));
232 return;
233 }
234
235 Log(("VBoxGuestHaikuClone: pszName=%s iUnit=%d\n", pszName, iUnit));
236
237 rc = clone_create(&g_pVBoxGuestHaikuClones, &g_VBoxGuestHaikuDeviceHooks, &iUnit, ppDev, 0);
238 Log(("VBoxGuestHaikuClone: clone_create -> %d; iUnit=%d\n", rc, iUnit));
239 if (rc)
240 {
241 *ppDev = make_dev(&g_VBoxGuestHaikuDeviceHooks,
242 iUnit,
243 UID_ROOT,
244 GID_WHEEL,
245 0644,
246 "vboxguest%d", iUnit);
247 if (*ppDev)
248 {
249 dev_ref(*ppDev);
250 (*ppDev)->si_flags |= SI_CHEAPCLONE;
251 Log(("VBoxGuestHaikuClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
252 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
253 (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL;
254 }
255 else
256 Log(("VBoxGuestHaikuClone: make_dev iUnit=%d failed\n", iUnit));
257 }
258 else
259 Log(("VBoxGuestHaikuClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
260 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
261}
262#endif
263
264
265static status_t VBoxGuestHaikuDetach(void)
266{
267 struct VBoxGuestDeviceState *pState = &sState;
268
269 if (cUsers > 0)
270 return EBUSY;
271
272 /*
273 * Reverse what we did in VBoxGuestHaikuAttach.
274 */
275 VBoxGuestHaikuRemoveIRQ(pState);
276
277 if (pState->iVMMDevMemAreaId)
278 delete_area(pState->iVMMDevMemAreaId);
279
280 VBoxGuestDeleteDevExt(&g_DevExt);
281
282#ifdef DO_LOG
283 RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
284 RTLogSetDefaultInstance(NULL);
285// RTLogDestroy(RTLogSetDefaultInstance(NULL));
286#endif
287
288 RTSpinlockDestroy(g_Spinlock);
289 g_Spinlock = NIL_RTSPINLOCK;
290
291 RTR0Term();
292 return B_OK;
293}
294
295
296/**
297 * Interrupt service routine.
298 *
299 * @returns Whether the interrupt was from VMMDev.
300 * @param pvState Opaque pointer to the device state.
301 */
302static int32 VBoxGuestHaikuISR(void *pvState)
303{
304 LogFlow((MODULE_NAME ":VBoxGuestHaikuISR pvState=%p\n", pvState));
305
306 bool fOurIRQ = VBoxGuestCommonISR(&g_DevExt);
307 if (fOurIRQ)
308 return B_HANDLED_INTERRUPT;
309 return B_UNHANDLED_INTERRUPT;
310}
311
312
313void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
314{
315 LogFlow((MODULE_NAME "::NativeISRMousePollEvent:\n"));
316
317 status_t err = B_OK;
318 //dprintf(MODULE_NAME ": isr mouse\n");
319
320 /*
321 * Wake up poll waiters.
322 */
323 //selwakeup(&g_SelInfo);
324 //XXX:notify_select_event();
325 RTSpinlockAcquire(g_Spinlock);
326
327 if (sState.selectSync)
328 {
329 //dprintf(MODULE_NAME ": isr mouse: notify\n");
330 notify_select_event(sState.selectSync, sState.selectEvent);
331 sState.selectEvent = (uint8_t)0;
332 sState.selectRef = (uint32_t)0;
333 sState.selectSync = NULL;
334 }
335 else
336 err = B_ERROR;
337
338 RTSpinlockRelease(g_Spinlock);
339}
340
341
342/**
343 * Sets IRQ for VMMDev.
344 *
345 * @returns Haiku error code.
346 * @param pvState Pointer to the state info structure.
347 */
348static int VBoxGuestHaikuAddIRQ(void *pvState)
349{
350 status_t err;
351 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
352
353 AssertReturn(pState, VERR_INVALID_PARAMETER);
354
355 err = install_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState, 0);
356 if (err == B_OK)
357 return VINF_SUCCESS;
358 return VERR_DEV_IO_ERROR;
359}
360
361
362/**
363 * Removes IRQ for VMMDev.
364 *
365 * @param pvState Opaque pointer to the state info structure.
366 */
367static void VBoxGuestHaikuRemoveIRQ(void *pvState)
368{
369 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
370 AssertPtr(pState);
371
372 remove_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState);
373}
374
375
376static status_t VBoxGuestHaikuAttach(const pci_info *pDevice)
377{
378 status_t status;
379 int rc = VINF_SUCCESS;
380 int iResId = 0;
381 struct VBoxGuestDeviceState *pState = &sState;
382 static const char *const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
383 PRTLOGGER pRelLogger;
384
385 AssertReturn(pDevice, B_BAD_VALUE);
386
387 cUsers = 0;
388
389 /*
390 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
391 */
392 rc = RTR0Init(0);
393 if (RT_FAILURE(rc))
394 {
395 /** @todo r=ramshankar: use dprintf here. */
396 LogFunc(("RTR0Init failed.\n"));
397 return ENXIO;
398 }
399
400 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestHaiku");
401 if (RT_FAILURE(rc))
402 {
403 LogRel(("VBoxGuestHaikuAttach: RTSpinlock create failed. rc=%Rrc\n", rc));
404 return ENXIO;
405 }
406
407#ifdef DO_LOG
408 /*
409 * Create the release log.
410 * (We do that here instead of common code because we want to log
411 * early failures using the LogRel macro.)
412 */
413 rc = RTLogCreate(&pRelLogger, 0 | RTLOGFLAGS_PREFIX_THREAD /* fFlags */, "all",
414 "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
415 RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL);
416 dprintf(MODULE_NAME ": RTLogCreate: %d\n", rc);
417 if (RT_SUCCESS(rc))
418 {
419 //RTLogGroupSettings(pRelLogger, g_szLogGrp);
420 //RTLogFlags(pRelLogger, g_szLogFlags);
421 //RTLogDestinations(pRelLogger, "/var/log/vboxguest.log");
422 RTLogRelSetDefaultInstance(pRelLogger);
423 RTLogSetDefaultInstance(pRelLogger); //XXX
424 }
425#endif
426
427 /*
428 * Allocate I/O port resource.
429 */
430 pState->uIOPortBase = pDevice->u.h0.base_registers[0];
431 /* @todo check flags for IO? */
432 if (pState->uIOPortBase)
433 {
434 /*
435 * Map the MMIO region.
436 */
437 uint32 phys = pDevice->u.h0.base_registers[1];
438 /* @todo Check flags for mem? */
439 pState->VMMDevMemSize = pDevice->u.h0.base_register_sizes[1];
440 pState->iVMMDevMemAreaId = map_physical_memory("VirtualBox Guest MMIO", phys, pState->VMMDevMemSize,
441 B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
442 &pState->pMMIOBase);
443 if (pState->iVMMDevMemAreaId > 0 && pState->pMMIOBase)
444 {
445 /*
446 * Call the common device extension initializer.
447 */
448 rc = VBoxGuestInitDevExt(&g_DevExt, pState->uIOPortBase, pState->pMMIOBase, pState->VMMDevMemSize,
449#if ARCH_BITS == 64
450 VBOXOSTYPE_Haiku_x64,
451#else
452 VBOXOSTYPE_Haiku,
453#endif
454 VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
455 if (RT_SUCCESS(rc))
456 {
457 /*
458 * Add IRQ of VMMDev.
459 */
460 pState->iIrqResId = pDevice->u.h0.interrupt_line;
461 rc = VBoxGuestHaikuAddIRQ(pState);
462 if (RT_SUCCESS(rc))
463 {
464 LogRel((MODULE_NAME ": loaded successfully\n"));
465 return B_OK;
466 }
467
468 LogRel((MODULE_NAME ":VBoxGuestInitDevExt failed.\n"));
469 VBoxGuestDeleteDevExt(&g_DevExt);
470 }
471 else
472 LogRel((MODULE_NAME ":VBoxGuestHaikuAddIRQ failed.\n"));
473 }
474 else
475 LogRel((MODULE_NAME ":MMIO region setup failed.\n"));
476 }
477 else
478 LogRel((MODULE_NAME ":IOport setup failed.\n"));
479
480 RTR0Term();
481 return ENXIO;
482}
483
484
485static status_t VBoxGuestHaikuProbe(pci_info *pDevice)
486{
487 if ((pDevice->vendor_id == VMMDEV_VENDORID) && (pDevice->device_id == VMMDEV_DEVICEID))
488 return B_OK;
489
490 return ENXIO;
491}
492
493
494status_t init_module(void)
495{
496 status_t err = B_ENTRY_NOT_FOUND;
497 pci_info info;
498 int ix = 0;
499
500 err = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
501 if (err != B_OK)
502 return err;
503
504 while ((*gPCI->get_nth_pci_info)(ix++, &info) == B_OK)
505 {
506 if (VBoxGuestHaikuProbe(&info) == 0)
507 {
508 /* We found it */
509 err = VBoxGuestHaikuAttach(&info);
510 return err;
511 }
512 }
513
514 return B_ENTRY_NOT_FOUND;
515}
516
517
518void uninit_module(void)
519{
520 VBoxGuestHaikuDetach();
521 put_module(B_PCI_MODULE_NAME);
522}
523
524
525static status_t std_ops(int32 op, ...)
526{
527 switch (op)
528 {
529 case B_MODULE_INIT:
530 return init_module();
531
532 case B_MODULE_UNINIT:
533 {
534 uninit_module();
535 return B_OK;
536 }
537
538 default:
539 return B_ERROR;
540 }
541}
542
543
544_EXPORT module_info *modules[] =
545{
546 (module_info *)&g_VBoxGuest,
547 NULL
548};
549
550/* Common code that depend on g_DevExt. */
551#include "VBoxGuestIDC-unix.c.h"
552
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