VirtualBox

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

最後變更 在這個檔案從43363是 43363,由 vboxsync 提交於 13 年 前

Haiku Additions.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.1 KB
 
1/* $Id: VBoxGuest-haiku.c 43363 2012-09-20 09:56:07Z vboxsync $ */
2/** @file
3 * VBoxGuest kernel module, Haiku Guest Additions, implementation.
4 */
5
6/*
7 * Copyright (C) 2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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#define IN_VBOXGUEST
48#define LOG_GROUP LOG_GROUP_SUP_DRV
49//#undef LOG_DISABLED
50//#define LOG_ENABLED
51//#define LOG_ENABLE_FLOW
52//#define DO_LOG
53#include <sys/param.h>
54#include <sys/types.h>
55#include <sys/uio.h>
56#include <OS.h>
57#include <Drivers.h>
58#include <KernelExport.h>
59#include <PCI.h>
60
61#include "VBoxGuest-haiku.h"
62#include "VBoxGuestInternal.h"
63#include <VBox/log.h>
64#include <iprt/assert.h>
65#include <iprt/initterm.h>
66#include <iprt/process.h>
67#include <iprt/mem.h>
68#include <iprt/memobj.h>
69#include <iprt/asm.h>
70#include <iprt/timer.h>
71#include <iprt/heap.h>
72
73#define MODULE_NAME VBOXGUEST_MODULE_NAME
74
75/*
76 * IRQ related functions.
77 */
78static void VBoxGuestHaikuRemoveIRQ(void *pvState);
79static int VBoxGuestHaikuAddIRQ(void *pvState);
80static int32 VBoxGuestHaikuISR(void *pvState);
81
82/*
83 * Available functions for kernel drivers.
84 */
85DECLVBGL(int) VBoxGuestHaikuServiceCall(void *pvSession, unsigned uCmd, void *pvData, size_t cbData, size_t *pcbDataReturned);
86DECLVBGL(void *) VBoxGuestHaikuServiceOpen(uint32_t *pu32Version);
87DECLVBGL(int) VBoxGuestHaikuServiceClose(void *pvSession);
88DECLVBGL(void *) VBoxGuestIDCOpen(uint32_t *pu32Version);
89DECLVBGL(int) VBoxGuestIDCClose(void *pvSession);
90DECLVBGL(int) VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned);
91
92static status_t std_ops(int32 op, ...);
93
94static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
95
96int32 api_version = B_CUR_DRIVER_API_VERSION;
97
98/** List of cloned device. Managed by the kernel. */
99//static struct clonedevs *g_pVBoxGuestHaikuClones;
100/** The dev_clone event handler tag. */
101//static eventhandler_tag g_VBoxGuestHaikuEHTag;
102/** selinfo structure used for polling. */
103//static struct selinfo g_SelInfo;
104/** PCI Bus Manager Module */
105static pci_module_info *gPCI;
106
107static struct vboxguest_module_info g_VBoxGuest = {
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 RTSpinlockReleaseNoInts,
178 RTMemTmpAllocTag,
179 RTMemTmpFree,
180 RTLogDefaultInstance,
181 RTLogRelDefaultInstance,
182 RTErrConvertToErrno,
183 VBoxGuestCommonIOCtl,
184 VBoxGuestCreateUserSession,
185 VBoxGuestCloseSession,
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
266static status_t VBoxGuestHaikuDetach(void)
267{
268 struct VBoxGuestDeviceState *pState = &sState;
269
270 if (cUsers > 0)
271 return EBUSY;
272
273 /*
274 * Reverse what we did in VBoxGuestHaikuAttach.
275 */
276
277 VBoxGuestHaikuRemoveIRQ(pState);
278
279 if (pState->iVMMDevMemAreaId)
280 delete_area(pState->iVMMDevMemAreaId);
281
282 VBoxGuestDeleteDevExt(&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
295 return B_OK;
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 = VBoxGuestCommonISR(&g_DevExt);
309
310 return fOurIRQ ? B_HANDLED_INTERRUPT : B_UNHANDLED_INTERRUPT;
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 //dprintf(MODULE_NAME ": isr mouse: notify\n");
329 notify_select_event(sState.selectSync, sState.selectEvent);
330 sState.selectEvent = (uint8_t)0;
331 sState.selectRef = (uint32_t)0;
332 sState.selectSync = NULL;
333 } else
334 err = B_ERROR;
335
336 RTSpinlockRelease(g_Spinlock);
337}
338
339/**
340 * Sets IRQ for VMMDev.
341 *
342 * @returns Haiku error code.
343 * @param pvState Pointer to the state info structure.
344 */
345static int VBoxGuestHaikuAddIRQ(void *pvState)
346{
347 status_t status;
348 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
349
350 status = install_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState, 0);
351
352 if (status != B_OK)
353 {
354 return VERR_DEV_IO_ERROR;
355 }
356
357 return VINF_SUCCESS;
358}
359
360/**
361 * Removes IRQ for VMMDev.
362 *
363 * @param pvState Opaque pointer to the state info structure.
364 */
365static void VBoxGuestHaikuRemoveIRQ(void *pvState)
366{
367 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
368
369 remove_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState);
370}
371
372static status_t VBoxGuestHaikuAttach(const pci_info *pDevice)
373{
374 status_t status;
375 int rc = VINF_SUCCESS;
376 int iResId = 0;
377 struct VBoxGuestDeviceState *pState = &sState;
378 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
379 PRTLOGGER pRelLogger;
380
381 cUsers = 0;
382
383 /*
384 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
385 */
386 rc = RTR0Init(0);
387 if (RT_FAILURE(rc))
388 {
389 /** @todo r=ramshankar: use dprintf here */
390 LogFunc(("RTR0Init failed.\n"));
391 return ENXIO;
392 }
393
394 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestHaiku");
395 if (RT_FAILURE(rc))
396 {
397 LogRel(("VBoxGuestHaikuAttach: RTSpinlock create failed. rc=%Rrc\n", rc));
398 return ENXIO;
399 }
400
401#ifdef DO_LOG
402 /*
403 * Create the release log.
404 * (We do that here instead of common code because we want to log
405 * early failures using the LogRel macro.)
406 */
407 rc = RTLogCreate(&pRelLogger, 0|RTLOGFLAGS_PREFIX_THREAD /* fFlags */, "all",
408 "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
409 RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL);
410dprintf(MODULE_NAME ": RTLogCreate: %d\n", rc);
411 if (RT_SUCCESS(rc))
412 {
413 //RTLogGroupSettings(pRelLogger, g_szLogGrp);
414 //RTLogFlags(pRelLogger, g_szLogFlags);
415 //RTLogDestinations(pRelLogger, "/var/log/vboxguest.log");
416 RTLogRelSetDefaultInstance(pRelLogger);
417 RTLogSetDefaultInstance(pRelLogger);//XXX
418 }
419#endif
420 Log((MODULE_NAME ": plip!\n"));
421 LogAlways((MODULE_NAME ": plop!\n"));
422
423
424 /*
425 * Allocate I/O port resource.
426 */
427 pState->uIOPortBase = pDevice->u.h0.base_registers[0];
428 //XXX check flags for IO ?
429 if (pState->uIOPortBase)
430 {
431 /*
432 * Map the MMIO region.
433 */
434 uint32 phys = pDevice->u.h0.base_registers[1];
435 //XXX check flags for mem ?
436 pState->VMMDevMemSize = pDevice->u.h0.base_register_sizes[1];
437 pState->iVMMDevMemAreaId = map_physical_memory("VirtualBox Guest MMIO",
438 phys, pState->VMMDevMemSize, B_ANY_KERNEL_BLOCK_ADDRESS,
439 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &pState->pMMIOBase);
440
441 if (pState->iVMMDevMemAreaId > 0 && pState->pMMIOBase)
442 {
443 /*
444 * Call the common device extension initializer.
445 */
446 rc = VBoxGuestInitDevExt(&g_DevExt, pState->uIOPortBase,
447 pState->pMMIOBase, pState->VMMDevMemSize,
448#if ARCH_BITS == 64
449 VBOXOSTYPE_Haiku_x64,
450#else
451 VBOXOSTYPE_Haiku,
452#endif
453 VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
454 if (RT_SUCCESS(rc))
455 {
456 /*
457 * Add IRQ of VMMDev.
458 */
459 pState->iIrqResId = pDevice->u.h0.interrupt_line;
460 rc = VBoxGuestHaikuAddIRQ(pState);
461 if (RT_SUCCESS(rc))
462 {
463 dprintf(MODULE_NAME ": loaded successfully\n");
464 return 0;
465 }
466 else
467 dprintf((MODULE_NAME ":VBoxGuestInitDevExt failed.\n"));
468 VBoxGuestDeleteDevExt(&g_DevExt);
469 }
470 else
471 dprintf((MODULE_NAME ":VBoxGuestHaikuAddIRQ failed.\n"));
472 }
473 else
474 dprintf((MODULE_NAME ":MMIO region setup failed.\n"));
475 }
476 else
477 dprintf((MODULE_NAME ":IOport setup failed.\n"));
478
479 RTR0Term();
480 return ENXIO;
481}
482
483static status_t VBoxGuestHaikuProbe(pci_info *pDevice)
484{
485 if ((pDevice->vendor_id == VMMDEV_VENDORID) && (pDevice->device_id == VMMDEV_DEVICEID))
486 return 0;
487
488 return ENXIO;
489}
490
491status_t init_module(void)
492{
493 status_t status = B_ENTRY_NOT_FOUND;
494 pci_info info;
495 int ix = 0;
496
497 if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI))
498 return ENOSYS;
499
500 while ((*gPCI->get_nth_pci_info)(ix++, &info) == B_OK) {
501 if (VBoxGuestHaikuProbe(&info) == 0) {
502 // we found it
503 status = VBoxGuestHaikuAttach(&info);
504 break;
505 }
506 }
507
508 return status;
509}
510
511void uninit_module(void)
512{
513 VBoxGuestHaikuDetach();
514
515 put_module(B_PCI_MODULE_NAME);
516}
517
518static status_t std_ops(int32 op, ...) {
519 switch(op) {
520 case B_MODULE_INIT:
521 dprintf(MODULE_NAME ": B_MODULE_INIT\n");
522 return init_module();
523 case B_MODULE_UNINIT:
524 dprintf(MODULE_NAME ": B_MODULE_UNINIT\n");
525 uninit_module();
526 return B_OK;
527 default:
528 return B_ERROR;
529 }
530}
531
532_EXPORT module_info *modules[] = {
533 (module_info*) &g_VBoxGuest,
534 NULL
535};
536
537/* Common code that depend on g_DevExt. */
538#include "VBoxGuestIDC-unix.c.h"
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette