VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-freebsd.c@ 8170

Last change on this file since 8170 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 20.3 KB
Line 
1/* $Id: VBoxGuest-freebsd.c 8155 2008-04-18 15:16:47Z vboxsync $ */
2/** @file
3 * VirtualBox Guest Additions Driver for FreeBSD.
4 */
5
6/*
7 * Copyright (C) 2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/** @todo r=bird: This must merge with SUPDrv-freebsd.c before long. The two
23 * source files should only differ on prefixes and the extra bits wrt to the
24 * pci device. I.e. it should be diffable so that fixes to one can easily be
25 * applied to the other. */
26
27#include <sys/param.h>
28#include <sys/systm.h>
29#include <sys/kernel.h>
30#include <sys/module.h>
31#include <sys/bus.h>
32#include <sys/queue.h>
33#include <sys/lockmgr.h>
34#include <sys/types.h>
35#include <sys/conf.h>
36#include <sys/malloc.h>
37#include <sys/uio.h>
38#include <sys/file.h>
39#include <machine/bus.h>
40#include <sys/rman.h>
41#include <machine/resource.h>
42#include <dev/pci/pcivar.h>
43#include <dev/pci/pcireg.h>
44
45#include "VBoxGuestInternal.h"
46#include <VBox/log.h>
47#include <iprt/assert.h>
48#include <iprt/initterm.h>
49#include <iprt/process.h>
50#include <iprt/mem.h>
51
52/** The module name. */
53#define DEVICE_NAME "vboxguest"
54
55struct VBoxGuestDeviceState
56{
57 /** file node minor code */
58 unsigned minor;
59 /** first IO port */
60 int io_port_resid;
61 struct resource *io_port;
62 bus_space_tag_t io_port_tag;
63 bus_space_handle_t io_port_handle;
64 /** IO Port. */
65 uint16_t uIOPortBase;
66 /** device memory resources */
67 int vmmdevmem_resid;
68 struct resource *vmmdevmem;
69 bus_space_tag_t vmmdevmem_tag;
70 bus_space_handle_t vmmdevmem_handle;
71 bus_size_t vmmdevmem_size;
72 /** physical address of adapter memory */
73 uint32_t vmmdevmem_addr;
74 /** Mapping of the register space */
75 void *pMMIOBase;
76 /** IRQ number */
77 int irq_resid;
78 struct resource *irq;
79 void *irq_handler;
80 /** VMMDev version */
81 uint32_t u32Version;
82};
83
84static MALLOC_DEFINE(M_VBOXDEV, "vboxdev_pci", "VirtualBox Guest driver PCI");
85
86#if FreeBSD >= 700
87static int VBoxGuestFreeBSDOpen(struct cdev *dev, int flags, int fmt, struct thread *td, struct file *pFd);
88#else
89static int VBoxGuestFreeBSDOpen(struct cdev *dev, int flags, int fmt, struct thread *td);
90#endif
91static int VBoxGuestFreeBSDClose(struct cdev *dev, int flags, int fmt, struct thread *td);
92static int VBoxGuestFreeBSDIOCtl(struct cdev *dev, u_long cmd, caddr_t data,
93 int fflag, struct thread *td);
94static ssize_t VBoxGuestFreeBSDWrite (struct cdev *dev, struct uio *uio, int ioflag);
95static ssize_t VBoxGuestFreeBSDRead (struct cdev *dev, struct uio *uio, int ioflag);
96static void VBoxGuestFreeBSDRemoveIRQ(device_t self, void *pvState);
97static int VBoxGuestFreeBSDAddIRQ(device_t self, void *pvState);
98int VBoxGuestFreeBSDISR(void *pvState);
99DECLVBGL(int) VBoxGuestFreeBSDServiceCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned);
100DECLVBGL(void *) VBoxGuestFreeBSDServiceOpen(uint32_t *pu32Version);
101DECLVBGL(int) VBoxGuestFreeBSDServiceClose(void *pvSession);
102
103/*
104 * Device node entry points.
105 */
106static struct cdevsw g_VBoxAddFreeBSDChrDevSW =
107{
108 .d_version = D_VERSION,
109 .d_flags = D_TRACKCLOSE,
110 .d_open = VBoxGuestFreeBSDOpen,
111 .d_close = VBoxGuestFreeBSDClose,
112 .d_ioctl = VBoxGuestFreeBSDIOCtl,
113 .d_read = VBoxGuestFreeBSDRead,
114 .d_write = VBoxGuestFreeBSDWrite,
115 .d_name = DEVICE_NAME
116};
117
118/** The make_dev result. */
119static struct cdev *g_pVBoxAddFreeBSDChrDev;
120/** Device extention & session data association structure. */
121static VBOXGUESTDEVEXT g_DevExt;
122/** Spinlock protecting g_apSessionHashTab. */
123static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
124/** Hash table */
125static PVBOXGUESTSESSION g_apSessionHashTab[19];
126/** Calculates the index into g_apSessionHashTab.*/
127#define SESSION_HASH(sfn) ((sfn) % RT_ELEMENTS(g_apSessionHashTab))
128
129/** @todo r=bird: fork() and session hash table didn't work well for solaris, so I doubt it works for
130 * FreeBSD... A different solution is needed unless the current can be improved. */
131
132/**
133 * VBoxGuest Common ioctl wrapper from VBoxGuestLib.
134 *
135 * @returns VBox error code.
136 * @param pvSession Opaque pointer to the session.
137 * @param iCmd Requested function.
138 * @param pvData IO data buffer.
139 * @param cbData Size of the data buffer.
140 * @param pcbDataReturned Where to store the amount of returned data.
141 */
142DECLVBGL(int) VBoxGuestFreeBSDServiceCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned)
143{
144 LogFlow((DEVICE_NAME ":VBoxGuestSolarisServiceCall %pvSesssion=%p Cmd=%u pvData=%p cbData=%d\n", pvSession, iCmd, pvData, cbData));
145
146 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession;
147 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
148 AssertMsgReturn(pSession->pDevExt == &g_DevExt,
149 ("SC: %p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
150
151 return VBoxGuestCommonIOCtl(iCmd, &g_DevExt, pSession, pvData, cbData, pcbDataReturned);
152}
153
154
155/**
156 * FreeBSD Guest service open.
157 *
158 * @returns Opaque pointer to session object.
159 * @param pu32Version Where to store VMMDev version.
160 */
161DECLVBGL(void *) VBoxGuestFreeBSDServiceOpen(uint32_t *pu32Version)
162{
163 LogFlow((DEVICE_NAME ":VBoxGuestSolarisServiceOpen\n"));
164
165 AssertPtrReturn(pu32Version, NULL);
166 PVBOXGUESTSESSION pSession;
167 int rc = VBoxGuestCreateKernelSession(&g_DevExt, &pSession);
168 if (RT_SUCCESS(rc))
169 {
170 *pu32Version = VMMDEV_VERSION;
171 return pSession;
172 }
173 LogRel((DEVICE_NAME ":VBoxGuestCreateKernelSession failed. rc=%d\n", rc));
174 return NULL;
175}
176
177
178/**
179 * FreeBSD Guest service close.
180 *
181 * @returns VBox error code.
182 * @param pvState Opaque pointer to the session object.
183 */
184DECLVBGL(int) VBoxGuestFreeBSDServiceClose(void *pvSession)
185{
186 LogFlow((DEVICE_NAME ":VBoxGuestSolarisServiceClose\n"));
187
188 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession;
189 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
190 if (pSession)
191 {
192 VBoxGuestCloseSession(&g_DevExt, pSession);
193 return VINF_SUCCESS;
194 }
195 LogRel((DEVICE_NAME ":Invalid pSession.\n"));
196 return VERR_INVALID_HANDLE;
197}
198
199/**
200 * File open handler
201 *
202 */
203#if FreeBSD >= 700
204static int VBoxGuestFreeBSDOpen(struct cdev *dev, int flags, int fmt, struct thread *td, struct file *pFd)
205#else
206static int VBoxGuestFreeBSDOpen(struct cdev *dev, int flags, int fmt, struct thread *td)
207#endif
208{
209 int rc;
210 PVBOXGUESTSESSION pSession;
211
212 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDOpen\n"));
213
214 /*
215 * Create a new session.
216 */
217 rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession);
218 if (RT_SUCCESS(rc))
219 {
220 /*
221 * Insert it into the hash table.
222 */
223 unsigned iHash = SESSION_HASH(pSession->Process);
224 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
225 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
226 pSession->pNextHash = g_apSessionHashTab[iHash];
227 g_apSessionHashTab[iHash] = pSession;
228 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
229
230 Log((DEVICE_NAME ":VBoxGuestFreeBSDOpen success: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
231 return 0;
232 }
233
234 LogRel((DEVICE_NAME ":VBoxGuestFreeBSDOpen: VBoxGuestCreateUserSession failed. rc=%d\n", rc));
235 return EFAULT;
236}
237
238/**
239 * File close handler
240 *
241 */
242static int VBoxGuestFreeBSDClose(struct cdev *dev, int flags, int fmt, struct thread *td)
243{
244 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDClose pid=%d\n", (int)RTProcSelf()));
245
246 /*
247 * Remove from the hash table.
248 */
249 PVBOXGUESTSESSION pSession;
250 const RTPROCESS Process = RTProcSelf();
251 const unsigned iHash = SESSION_HASH(Process);
252 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
253 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
254
255 pSession = g_apSessionHashTab[iHash];
256 if (pSession)
257 {
258 if (pSession->Process == Process)
259 {
260 g_apSessionHashTab[iHash] = pSession->pNextHash;
261 pSession->pNextHash = NULL;
262 }
263 else
264 {
265 PVBOXGUESTSESSION pPrev = pSession;
266 pSession = pSession->pNextHash;
267 while (pSession)
268 {
269 if (pSession->Process == Process)
270 {
271 pPrev->pNextHash = pSession->pNextHash;
272 pSession->pNextHash = NULL;
273 break;
274 }
275
276 /* next */
277 pPrev = pSession;
278 pSession = pSession->pNextHash;
279 }
280 }
281 }
282 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
283 if (!pSession)
284 {
285 Log((DEVICE_NAME ":VBoxGuestFreeBSDClose: WHUT?!? pSession == NULL! This must be a mistake... pid=%d", (int)Process));
286 return EFAULT;
287 }
288 Log((DEVICE_NAME ":VBoxGuestFreeBSDClose: pid=%d\n", (int)Process));
289
290 /*
291 * Close the session.
292 */
293 VBoxGuestCloseSession(&g_DevExt, pSession);
294 return 0;
295}
296
297/**
298 * IOCTL handler
299 *
300 */
301static int VBoxGuestFreeBSDIOCtl(struct cdev *dev, u_long cmd, caddr_t data,
302 int fflag, struct thread *td)
303{
304 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl\n"));
305
306 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
307 const RTPROCESS Process = RTProcSelf();
308 const unsigned iHash = SESSION_HASH(Process);
309 PVBOXGUESTSESSION pSession;
310 int rc = 0;
311
312 /*
313 * Find the session.
314 */
315 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
316 pSession = g_apSessionHashTab[iHash];
317 if (pSession && pSession->Process != Process)
318 {
319 do pSession = pSession->pNextHash;
320 while (pSession && pSession->Process != Process);
321 }
322 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
323 if (!pSession)
324 {
325 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#lx\n", (int)Process, cmd));
326 return EINVAL;
327 }
328
329 /*
330 * Validate the request wrapper.
331 */
332 if (IOCPARM_LEN(cmd) != sizeof(VBGLBIGREQ))
333 {
334 Log((DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad request %lu size=%lu expected=%d\n", cmd, IOCPARM_LEN(cmd), sizeof(VBGLBIGREQ)));
335 return ENOTTY;
336 }
337
338 PVBGLBIGREQ ReqWrap = (PVBGLBIGREQ)data;
339 if (ReqWrap->u32Magic != VBGLBIGREQ_MAGIC)
340 {
341 Log((DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad magic %#x; pArg=%p Cmd=%lu.\n", ReqWrap->u32Magic, data, cmd));
342 return EINVAL;
343 }
344 if (RT_UNLIKELY( ReqWrap->cbData == 0
345 || ReqWrap->cbData > _1M*16))
346 {
347 printf(DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", ReqWrap->cbData, data, cmd);
348 return EINVAL;
349 }
350
351 /*
352 * Read the request.
353 */
354 void *pvBuf = RTMemTmpAlloc(ReqWrap->cbData);
355 if (RT_UNLIKELY(!pvBuf))
356 {
357 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap->cbData));
358 return ENOMEM;
359 }
360
361 rc = copyin((void *)(uintptr_t)ReqWrap->pvDataR3, pvBuf, ReqWrap->cbData);
362 if (RT_UNLIKELY(rc))
363 {
364 RTMemTmpFree(pvBuf);
365 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: copyin failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, data, cmd, rc));
366 return EFAULT;
367 }
368 if (RT_UNLIKELY( ReqWrap->cbData != 0
369 && !VALID_PTR(pvBuf)))
370 {
371 RTMemTmpFree(pvBuf);
372 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: pvBuf invalid pointer %p\n", pvBuf));
373 return EINVAL;
374 }
375 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: pSession=%p pid=%d.\n", pSession, (int)RTProcSelf()));
376
377 /*
378 * Process the IOCtl.
379 */
380 size_t cbDataReturned;
381 rc = VBoxGuestCommonIOCtl(cmd, &g_DevExt, pSession, pvBuf, ReqWrap->cbData, &cbDataReturned);
382 if (RT_SUCCESS(rc))
383 {
384 rc = 0;
385 if (RT_UNLIKELY(cbDataReturned > ReqWrap->cbData))
386 {
387 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap->cbData));
388 cbDataReturned = ReqWrap->cbData;
389 }
390 if (cbDataReturned > 0)
391 {
392 rc = copyout(pvBuf, (void *)(uintptr_t)ReqWrap->pvDataR3, cbDataReturned);
393 if (RT_UNLIKELY(rc))
394 {
395 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: copyout failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, data, cmd, rc));
396 rc = EFAULT;
397 }
398 }
399 }
400 else
401 {
402 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: VBoxGuestCommonIOCtl failed. rc=%d\n", rc));
403 rc = EFAULT;
404 }
405 RTMemTmpFree(pvBuf);
406 return rc;
407}
408
409static ssize_t VBoxGuestFreeBSDWrite (struct cdev *dev, struct uio *uio, int ioflag)
410{
411 return 0;
412}
413
414static ssize_t VBoxGuestFreeBSDRead (struct cdev *dev, struct uio *uio, int ioflag)
415{
416 return 0;
417}
418
419static int VBoxGuestFreeBSDDetach(device_t self)
420{
421 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)device_get_softc(self);
422
423 VBoxGuestFreeBSDRemoveIRQ(self, pState);
424
425 if (pState->vmmdevmem)
426 bus_release_resource(self, SYS_RES_MEMORY, pState->vmmdevmem_resid, pState->vmmdevmem);
427 if (pState->io_port)
428 bus_release_resource(self, SYS_RES_IOPORT, pState->io_port_resid, pState->io_port);
429
430 VBoxGuestDeleteDevExt(&g_DevExt);
431
432 RTSpinlockDestroy(g_Spinlock);
433 g_Spinlock = NIL_RTSPINLOCK;
434
435 free(pState, M_VBOXDEV);
436 RTR0Term();
437
438 return 0;
439}
440
441/**
442 * Interrupt service routine.
443 *
444 * @returns Whether the interrupt was from VMMDev.
445 * @param pvState Opaque pointer to the device state.
446 */
447int VBoxGuestFreeBSDISR(void *pvState)
448{
449 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDISR pvState=%p\n", pvState));
450
451 bool fOurIRQ = VBoxGuestCommonISR(&g_DevExt);
452
453 return fOurIRQ ? 0 : 1;
454}
455
456/**
457 * Sets IRQ for VMMDev.
458 *
459 * @returns FreeBSD error code.
460 * @param self Pointer to the device info structure.
461 * @param pvState Pointer to the state info structure.
462 */
463static int VBoxGuestFreeBSDAddIRQ(device_t self, void *pvState)
464{
465 int res_id = 0;
466 int rc = 0;
467 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
468
469 pState->irq = bus_alloc_resource_any(self, SYS_RES_IRQ, &res_id, RF_SHAREABLE | RF_ACTIVE);
470
471#if __FreeBSD_version >= 700000
472 rc = bus_setup_intr(self, pState->irq, INTR_TYPE_BIO, NULL, (driver_intr_t *)VBoxGuestFreeBSDISR, pState, &pState->irq_handler);
473#else
474 rc = bus_setup_intr(self, pState->irq, INTR_TYPE_BIO, (driver_intr_t *)VBoxGuestFreeBSDISR, pState, &pState->irq_handler);
475#endif
476
477 if (rc)
478 {
479 pState->irq_handler = NULL;
480 return VERR_DEV_IO_ERROR;
481 }
482
483 pState->irq_resid = res_id;
484
485 return VINF_SUCCESS;
486}
487
488/**
489 * Removes IRQ for VMMDev.
490 *
491 * @param self Pointer to the device info structure.
492 * @param pvState Opaque pointer to the state info structure.
493 */
494static void VBoxGuestFreeBSDRemoveIRQ(device_t self, void *pvState)
495{
496 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
497
498 if (pState->irq)
499 {
500 bus_teardown_intr(self, pState->irq, pState->irq_handler);
501 bus_release_resource(self, SYS_RES_IRQ, 0, pState->irq);
502 }
503}
504
505static int VBoxGuestFreeBSDAttach(device_t self)
506{
507 int rc = VINF_SUCCESS;
508 int res_id = 0;
509 struct VBoxGuestDeviceState *pState = NULL;
510
511 /*
512 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
513 */
514 rc = RTR0Init(0);
515 if (RT_FAILURE(rc))
516 {
517 LogFunc(("RTR0Init failed.\n"));
518 return ENXIO;
519 }
520
521 pState = device_get_softc(self);
522 if (!pState)
523 {
524 pState = malloc(sizeof(struct VBoxGuestDeviceState), M_VBOXDEV, M_NOWAIT | M_ZERO);
525 if (!pState)
526 return ENOMEM;
527
528 device_set_softc(self, pState);
529 }
530
531 /*
532 * Initialize the session hash table.
533 */
534 rc = RTSpinlockCreate(&g_Spinlock);
535 if (RT_SUCCESS(rc))
536 {
537 /*
538 * Map the register address space.
539 */
540 res_id = PCIR_BAR(0);
541 pState->io_port = bus_alloc_resource_any(self, SYS_RES_IOPORT, &res_id, RF_ACTIVE);
542 pState->io_port_tag = rman_get_bustag(pState->io_port);
543 pState->io_port_handle = rman_get_bushandle(pState->io_port);
544 pState->uIOPortBase = bus_get_resource_start(self, SYS_RES_IOPORT, res_id);
545 pState->io_port_resid = res_id;
546 if (pState->uIOPortBase)
547 {
548 /*
549 * Map the MMIO region.
550 */
551 res_id = PCIR_BAR(1);
552 pState->vmmdevmem = bus_alloc_resource_any(self, SYS_RES_MEMORY, &res_id, RF_ACTIVE);
553 pState->vmmdevmem_tag = rman_get_bustag(pState->vmmdevmem);
554 pState->vmmdevmem_handle = rman_get_bushandle(pState->vmmdevmem);
555 pState->vmmdevmem_addr = bus_get_resource_start(self, SYS_RES_MEMORY, res_id);
556 pState->vmmdevmem_size = bus_get_resource_count(self, SYS_RES_MEMORY, res_id);
557
558 pState->pMMIOBase = (void *)pState->vmmdevmem_handle;
559 pState->vmmdevmem_resid = res_id;
560 if (pState->pMMIOBase)
561 {
562 /*
563 * Add IRQ of VMMDev.
564 */
565 rc = VBoxGuestFreeBSDAddIRQ(self, pState);
566 if (RT_SUCCESS(rc))
567 {
568 /*
569 * Call the common device extension initializer.
570 */
571 rc = VBoxGuestInitDevExt(&g_DevExt, pState->uIOPortBase, pState->pMMIOBase,
572 pState->vmmdevmem_size, VBOXOSTYPE_FreeBSD);
573 printf("rc=%d\n", rc);
574 if (RT_SUCCESS(rc))
575 {
576 /*
577 * Create device node.
578 */
579 g_pVBoxAddFreeBSDChrDev = make_dev(&g_VBoxAddFreeBSDChrDevSW,
580 0,
581 UID_ROOT,
582 GID_WHEEL,
583 0666,
584 DEVICE_NAME);
585 g_pVBoxAddFreeBSDChrDev->si_drv1 = self;
586 return 0;
587 }
588 else
589 printf((DEVICE_NAME ":VBoxGuestInitDevExt failed.\n"));
590 VBoxGuestFreeBSDRemoveIRQ(self, pState);
591 }
592 else
593 printf((DEVICE_NAME ":VBoxGuestFreeBSDAddIRQ failed.\n"));
594 }
595 else
596 printf((DEVICE_NAME ":MMIO region setup failed.\n"));
597 }
598 else
599 printf((DEVICE_NAME ":IOport setup failed.\n"));
600 RTSpinlockDestroy(g_Spinlock);
601 g_Spinlock = NIL_RTSPINLOCK;
602 }
603 else
604 printf((DEVICE_NAME ":RTSpinlockCreate failed.\n"));
605
606 RTR0Term();
607 return ENXIO;
608}
609
610static int VBoxGuestFreeBSDProbe(device_t self)
611{
612 if ((pci_get_vendor(self) == VMMDEV_VENDORID) && (pci_get_device(self) == VMMDEV_DEVICEID))
613 {
614 Log(("Found VBox device\n"));
615 return 0;
616 }
617
618 return ENXIO;
619}
620
621static device_method_t VBoxGuestFreeBSDMethods[] =
622{
623 /* Device interface. */
624 DEVMETHOD(device_probe, VBoxGuestFreeBSDProbe),
625 DEVMETHOD(device_attach, VBoxGuestFreeBSDAttach),
626 DEVMETHOD(device_detach, VBoxGuestFreeBSDDetach),
627 {0,0}
628};
629
630static driver_t VBoxGuestFreeBSDDriver =
631{
632 DEVICE_NAME,
633 VBoxGuestFreeBSDMethods,
634 sizeof(struct VBoxGuestDeviceState),
635};
636
637static devclass_t VBoxGuestFreeBSDClass;
638
639DRIVER_MODULE(vboxguest, pci, VBoxGuestFreeBSDDriver, VBoxGuestFreeBSDClass, 0, 0);
640MODULE_VERSION(vboxguest, 1);
641
642int __gxx_personality_v0 = 0xdeadbeef;
643
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