VirtualBox

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

Last change on this file since 14833 was 8250, checked in by vboxsync, 17 years ago

Additions/FreeBSD: Setup IRQ only if initializing of the device state was successful, eliminate a tab

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 19.4 KB
Line 
1/* $Id: VBoxGuest-freebsd.c 8250 2008-04-21 18:42:58Z 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#include <iprt/asm.h>
52
53/** The module name. */
54#define DEVICE_NAME "vboxguest"
55
56struct VBoxGuestDeviceState
57{
58 /** file node minor code */
59 unsigned uMinor;
60 /** Resource ID of the I/O port */
61 int iIOPortResId;
62 /** Pointer to the I/O port resource. */
63 struct resource *pIOPortRes;
64 /** Start address of the IO Port. */
65 uint16_t uIOPortBase;
66 /** Resource ID of the MMIO area */
67 int iVMMDevMemResId;
68 /** Pointer to the MMIO resource. */
69 struct resource *pVMMDevMemRes;
70 /** Handle of the MMIO resource. */
71 bus_space_handle_t VMMDevMemHandle;
72 /** Size of the memory area. */
73 bus_size_t VMMDevMemSize;
74 /** Mapping of the register space */
75 void *pMMIOBase;
76 /** IRQ number */
77 int iIrqResId;
78 /** IRQ resource handle. */
79 struct resource *pIrqRes;
80 /** Pointer to the IRQ handler. */
81 void *pfnIrqHandler;
82 /** VMMDev version */
83 uint32_t u32Version;
84};
85
86static MALLOC_DEFINE(M_VBOXDEV, "vboxdev_pci", "VirtualBox Guest driver PCI");
87
88/*
89 * Character device file handlers.
90 */
91static d_fdopen_t VBoxGuestFreeBSDOpen;
92static d_close_t VBoxGuestFreeBSDClose;
93static d_ioctl_t VBoxGuestFreeBSDIOCtl;
94static d_write_t VBoxGuestFreeBSDWrite;
95static d_read_t VBoxGuestFreeBSDRead;
96
97/*
98 * IRQ related functions.
99 */
100static void VBoxGuestFreeBSDRemoveIRQ(device_t pDevice, void *pvState);
101static int VBoxGuestFreeBSDAddIRQ(device_t pDevice, void *pvState);
102static int VBoxGuestFreeBSDISR(void *pvState);
103
104/*
105 * Available functions for kernel drivers.
106 */
107DECLVBGL(int) VBoxGuestFreeBSDServiceCall(void *pvSession, unsigned uCmd, void *pvData, size_t cbData, size_t *pcbDataReturned);
108DECLVBGL(void *) VBoxGuestFreeBSDServiceOpen(uint32_t *pu32Version);
109DECLVBGL(int) VBoxGuestFreeBSDServiceClose(void *pvSession);
110
111/*
112 * Device node entry points.
113 */
114static struct cdevsw g_VBoxGuestFreeBSDChrDevSW =
115{
116 .d_version = D_VERSION,
117 .d_flags = D_TRACKCLOSE,
118 .d_fdopen = VBoxGuestFreeBSDOpen,
119 .d_close = VBoxGuestFreeBSDClose,
120 .d_ioctl = VBoxGuestFreeBSDIOCtl,
121 .d_read = VBoxGuestFreeBSDRead,
122 .d_write = VBoxGuestFreeBSDWrite,
123 .d_name = DEVICE_NAME
124};
125
126/** Device extention & session data association structure. */
127static VBOXGUESTDEVEXT g_DevExt;
128/** List of cloned device. Managed by the kernel. */
129static struct clonedevs *g_pVBoxGuestFreeBSDClones;
130/** The dev_clone event handler tag. */
131static eventhandler_tag g_VBoxGuestFreeBSDEHTag;
132
133/**
134 * VBoxGuest Common ioctl wrapper from VBoxGuestLib.
135 *
136 * @returns VBox error code.
137 * @param pvSession Opaque pointer to the session.
138 * @param uCmd Requested function.
139 * @param pvData IO data buffer.
140 * @param cbData Size of the data buffer.
141 * @param pcbDataReturned Where to store the amount of returned data.
142 */
143DECLVBGL(int) VBoxGuestFreeBSDServiceCall(void *pvSession, unsigned uCmd, void *pvData, size_t cbData, size_t *pcbDataReturned)
144{
145 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDServiceCall %pvSesssion=%p uCmd=%u pvData=%p cbData=%d\n", pvSession, uCmd, pvData, cbData));
146
147 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession;
148 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
149 AssertMsgReturn(pSession->pDevExt == &g_DevExt,
150 ("SC: %p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
151
152 return VBoxGuestCommonIOCtl(uCmd, &g_DevExt, pSession, pvData, cbData, pcbDataReturned);
153}
154
155
156/**
157 * FreeBSD Guest service open.
158 *
159 * @returns Opaque pointer to session object.
160 * @param pu32Version Where to store VMMDev version.
161 */
162DECLVBGL(void *) VBoxGuestFreeBSDServiceOpen(uint32_t *pu32Version)
163{
164 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDServiceOpen\n"));
165
166 AssertPtrReturn(pu32Version, NULL);
167 PVBOXGUESTSESSION pSession;
168 int rc = VBoxGuestCreateKernelSession(&g_DevExt, &pSession);
169 if (RT_SUCCESS(rc))
170 {
171 *pu32Version = VMMDEV_VERSION;
172 return pSession;
173 }
174 LogRel((DEVICE_NAME ":VBoxGuestCreateKernelSession failed. rc=%d\n", rc));
175 return NULL;
176}
177
178
179/**
180 * FreeBSD Guest service close.
181 *
182 * @returns VBox error code.
183 * @param pvState Opaque pointer to the session object.
184 */
185DECLVBGL(int) VBoxGuestFreeBSDServiceClose(void *pvSession)
186{
187 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDServiceClose\n"));
188
189 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession;
190 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
191 if (pSession)
192 {
193 VBoxGuestCloseSession(&g_DevExt, pSession);
194 return VINF_SUCCESS;
195 }
196 LogRel((DEVICE_NAME ":Invalid pSession.\n"));
197 return VERR_INVALID_HANDLE;
198}
199
200/**
201 * DEVFS event handler.
202 */
203static void VBoxGuestFreeBSDClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev)
204{
205 int iUnit;
206 int rc;
207
208 Log(("VBoxGuestFreeBSDClone: pszName=%s ppDev=%p\n", pszName, ppDev));
209
210 /*
211 * One device node per user, si_drv1 points to the session.
212 * /dev/vboxguest<N> where N = {0...255}.
213 */
214 if (!ppDev)
215 return;
216 if (dev_stdclone(pszName, NULL, "vboxguest", &iUnit) != 1)
217 return;
218 if (iUnit >= 256 || iUnit < 0)
219 {
220 Log(("VBoxGuestFreeBSDClone: iUnit=%d >= 256 - rejected\n", iUnit));
221 return;
222 }
223
224 Log(("VBoxGuestFreeBSDClone: pszName=%s iUnit=%d\n", pszName, iUnit));
225
226 rc = clone_create(&g_pVBoxGuestFreeBSDClones, &g_VBoxGuestFreeBSDChrDevSW, &iUnit, ppDev, 0);
227 Log(("VBoxGuestFreeBSDClone: clone_create -> %d; iUnit=%d\n", rc, iUnit));
228 if (rc)
229 {
230 *ppDev = make_dev(&g_VBoxGuestFreeBSDChrDevSW,
231 unit2minor(iUnit),
232 UID_ROOT,
233 GID_WHEEL,
234 0644,
235 "vboxguest%d", iUnit);
236 if (*ppDev)
237 {
238 dev_ref(*ppDev);
239 (*ppDev)->si_flags |= SI_CHEAPCLONE;
240 Log(("VBoxGuestFreeBSDClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
241 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
242 (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL;
243 }
244 else
245 Log(("VBoxGuestFreeBSDClone: make_dev iUnit=%d failed\n", iUnit));
246 }
247 else
248 Log(("VBoxGuestFreeBSDClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
249 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
250}
251
252/**
253 * File open handler
254 *
255 */
256#if __FreeBSD_version >= 700000
257static int VBoxGuestFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd, struct file *pFd)
258#else
259static int VBoxGuestFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd)
260#endif
261{
262 int rc;
263 PVBOXGUESTSESSION pSession;
264
265 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDOpen\n"));
266
267 /*
268 * Try grab it (we don't grab the giant, remember).
269 */
270 if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, (void *)0x42, NULL))
271 return EBUSY;
272
273 /*
274 * Create a new session.
275 */
276 rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession);
277 if (RT_SUCCESS(rc))
278 {
279 if (ASMAtomicCmpXchgPtr(&pDev->si_drv1, pSession, (void *)0x42))
280 {
281 Log((DEVICE_NAME ":VBoxGuestFreeBSDOpen success: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
282 return 0;
283 }
284
285 VBoxGuestCloseSession(&g_DevExt, pSession);
286 }
287
288 LogRel((DEVICE_NAME ":VBoxGuestFreeBSDOpen: failed. rc=%d\n", rc));
289 return RTErrConvertToErrno(rc);
290}
291
292/**
293 * File close handler
294 *
295 */
296static int VBoxGuestFreeBSDClose(struct cdev *pDev, int fFile, int DevType, struct thread *pTd)
297{
298 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1;
299 Log(("VBoxGuestFreeBSDClose: fFile=%#x iUnit=%d pSession=%p\n", fFile, minor2unit(minor(pDev)), pSession));
300
301 /*
302 * Close the session if it's still hanging on to the device...
303 */
304 if (VALID_PTR(pSession))
305 {
306 VBoxGuestCloseSession(&g_DevExt, pSession);
307 if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, NULL, pSession))
308 Log(("VBoxGuestFreeBSDClose: si_drv1=%p expected %p!\n", pDev->si_drv1, pSession));
309 }
310 else
311 Log(("VBoxGuestFreeBSDClose: si_drv1=%p!\n", pSession));
312 return 0;
313}
314
315/**
316 * IOCTL handler
317 *
318 */
319static int VBoxGuestFreeBSDIOCtl(struct cdev *pDev, u_long ulCmd, caddr_t pvData, int fFile, struct thread *pTd)
320{
321 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl\n"));
322
323 int rc = 0;
324
325 /*
326 * Validate the input.
327 */
328 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1;
329 if (RT_UNLIKELY(!VALID_PTR(pSession)))
330 return EINVAL;
331
332 /*
333 * Validate the request wrapper.
334 */
335 if (IOCPARM_LEN(ulCmd) != sizeof(VBGLBIGREQ))
336 {
337 Log((DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad request %lu size=%lu expected=%d\n", ulCmd, IOCPARM_LEN(ulCmd), sizeof(VBGLBIGREQ)));
338 return ENOTTY;
339 }
340
341 PVBGLBIGREQ ReqWrap = (PVBGLBIGREQ)pvData;
342 if (ReqWrap->u32Magic != VBGLBIGREQ_MAGIC)
343 {
344 Log((DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad magic %#x; pArg=%p Cmd=%lu.\n", ReqWrap->u32Magic, pvData, ulCmd));
345 return EINVAL;
346 }
347 if (RT_UNLIKELY( ReqWrap->cbData == 0
348 || ReqWrap->cbData > _1M*16))
349 {
350 printf(DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", ReqWrap->cbData, pvData, ulCmd);
351 return EINVAL;
352 }
353
354 /*
355 * Read the request.
356 */
357 void *pvBuf = RTMemTmpAlloc(ReqWrap->cbData);
358 if (RT_UNLIKELY(!pvBuf))
359 {
360 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap->cbData));
361 return ENOMEM;
362 }
363
364 rc = copyin((void *)(uintptr_t)ReqWrap->pvDataR3, pvBuf, ReqWrap->cbData);
365 if (RT_UNLIKELY(rc))
366 {
367 RTMemTmpFree(pvBuf);
368 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: copyin failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, pvData, ulCmd, rc));
369 return EFAULT;
370 }
371 if (RT_UNLIKELY( ReqWrap->cbData != 0
372 && !VALID_PTR(pvBuf)))
373 {
374 RTMemTmpFree(pvBuf);
375 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: pvBuf invalid pointer %p\n", pvBuf));
376 return EINVAL;
377 }
378 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: pSession=%p pid=%d.\n", pSession, (int)RTProcSelf()));
379
380 /*
381 * Process the IOCtl.
382 */
383 size_t cbDataReturned;
384 rc = VBoxGuestCommonIOCtl(ulCmd, &g_DevExt, pSession, pvBuf, ReqWrap->cbData, &cbDataReturned);
385 if (RT_SUCCESS(rc))
386 {
387 rc = 0;
388 if (RT_UNLIKELY(cbDataReturned > ReqWrap->cbData))
389 {
390 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap->cbData));
391 cbDataReturned = ReqWrap->cbData;
392 }
393 if (cbDataReturned > 0)
394 {
395 rc = copyout(pvBuf, (void *)(uintptr_t)ReqWrap->pvDataR3, cbDataReturned);
396 if (RT_UNLIKELY(rc))
397 {
398 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: copyout failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, pvData, ulCmd, rc));
399 rc = EFAULT;
400 }
401 }
402 }
403 else
404 {
405 Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: VBoxGuestCommonIOCtl failed. rc=%d\n", rc));
406 rc = EFAULT;
407 }
408 RTMemTmpFree(pvBuf);
409 return rc;
410}
411
412static ssize_t VBoxGuestFreeBSDWrite (struct cdev *pDev, struct uio *pUio, int fIo)
413{
414 return 0;
415}
416
417static ssize_t VBoxGuestFreeBSDRead (struct cdev *pDev, struct uio *pUio, int fIo)
418{
419 return 0;
420}
421
422static int VBoxGuestFreeBSDDetach(device_t pDevice)
423{
424 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)device_get_softc(pDevice);
425
426 /*
427 * Reserve what we did in VBoxGuestFreeBSDAttach.
428 */
429 clone_cleanup(&g_pVBoxGuestFreeBSDClones);
430
431 VBoxGuestFreeBSDRemoveIRQ(pDevice, pState);
432
433 if (pState->pVMMDevMemRes)
434 bus_release_resource(pDevice, SYS_RES_MEMORY, pState->iVMMDevMemResId, pState->pVMMDevMemRes);
435 if (pState->pIOPortRes)
436 bus_release_resource(pDevice, SYS_RES_IOPORT, pState->iIOPortResId, pState->pIOPortRes);
437
438 VBoxGuestDeleteDevExt(&g_DevExt);
439
440 free(pState, M_VBOXDEV);
441 RTR0Term();
442
443 return 0;
444}
445
446/**
447 * Interrupt service routine.
448 *
449 * @returns Whether the interrupt was from VMMDev.
450 * @param pvState Opaque pointer to the device state.
451 */
452static int VBoxGuestFreeBSDISR(void *pvState)
453{
454 LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDISR pvState=%p\n", pvState));
455
456 bool fOurIRQ = VBoxGuestCommonISR(&g_DevExt);
457
458 return fOurIRQ ? 0 : 1;
459}
460
461/**
462 * Sets IRQ for VMMDev.
463 *
464 * @returns FreeBSD error code.
465 * @param pDevice Pointer to the device info structure.
466 * @param pvState Pointer to the state info structure.
467 */
468static int VBoxGuestFreeBSDAddIRQ(device_t pDevice, void *pvState)
469{
470 int iResId = 0;
471 int rc = 0;
472 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
473
474 pState->pIrqRes = bus_alloc_resource_any(pDevice, SYS_RES_IRQ, &iResId, RF_SHAREABLE | RF_ACTIVE);
475
476#if __FreeBSD_version >= 700000
477 rc = bus_setup_intr(pDevice, pState->pIrqRes, INTR_TYPE_BIO, NULL, (driver_intr_t *)VBoxGuestFreeBSDISR, pState, &pState->pfnIrqHandler);
478#else
479 rc = bus_setup_intr(pDevice, pState->pIrqRes, INTR_TYPE_BIO, (driver_intr_t *)VBoxGuestFreeBSDISR, pState, &pState->pfnIrqHandler);
480#endif
481
482 if (rc)
483 {
484 pState->pfnIrqHandler = NULL;
485 return VERR_DEV_IO_ERROR;
486 }
487
488 pState->iIrqResId = iResId;
489
490 return VINF_SUCCESS;
491}
492
493/**
494 * Removes IRQ for VMMDev.
495 *
496 * @param pDevice Pointer to the device info structure.
497 * @param pvState Opaque pointer to the state info structure.
498 */
499static void VBoxGuestFreeBSDRemoveIRQ(device_t pDevice, void *pvState)
500{
501 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
502
503 if (pState->pIrqRes)
504 {
505 bus_teardown_intr(pDevice, pState->pIrqRes, pState->pfnIrqHandler);
506 bus_release_resource(pDevice, SYS_RES_IRQ, 0, pState->pIrqRes);
507 }
508}
509
510static int VBoxGuestFreeBSDAttach(device_t pDevice)
511{
512 int rc = VINF_SUCCESS;
513 int iResId = 0;
514 struct VBoxGuestDeviceState *pState = NULL;
515
516 /*
517 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
518 */
519 rc = RTR0Init(0);
520 if (RT_FAILURE(rc))
521 {
522 LogFunc(("RTR0Init failed.\n"));
523 return ENXIO;
524 }
525
526 pState = device_get_softc(pDevice);
527 if (!pState)
528 {
529 pState = malloc(sizeof(struct VBoxGuestDeviceState), M_VBOXDEV, M_NOWAIT | M_ZERO);
530 if (!pState)
531 return ENOMEM;
532
533 device_set_softc(pDevice, pState);
534 }
535
536 /*
537 * Allocate I/O port resource.
538 */
539 iResId = PCIR_BAR(0);
540 pState->pIOPortRes = bus_alloc_resource_any(pDevice, SYS_RES_IOPORT, &iResId, RF_ACTIVE);
541 pState->uIOPortBase = bus_get_resource_start(pDevice, SYS_RES_IOPORT, iResId);
542 pState->iIOPortResId = iResId;
543 if (pState->uIOPortBase)
544 {
545 /*
546 * Map the MMIO region.
547 */
548 iResId = PCIR_BAR(1);
549 pState->pVMMDevMemRes = bus_alloc_resource_any(pDevice, SYS_RES_MEMORY, &iResId, RF_ACTIVE);
550 pState->VMMDevMemHandle = rman_get_bushandle(pState->pVMMDevMemRes);
551 pState->VMMDevMemSize = bus_get_resource_count(pDevice, SYS_RES_MEMORY, iResId);
552
553 pState->pMMIOBase = (void *)pState->VMMDevMemHandle;
554 pState->iVMMDevMemResId = iResId;
555 if (pState->pMMIOBase)
556 {
557 /*
558 * Call the common device extension initializer.
559 */
560 rc = VBoxGuestInitDevExt(&g_DevExt, pState->uIOPortBase, pState->pMMIOBase,
561 pState->VMMDevMemSize, VBOXOSTYPE_FreeBSD);
562 if (RT_SUCCESS(rc))
563 {
564 /*
565 * Add IRQ of VMMDev.
566 */
567 rc = VBoxGuestFreeBSDAddIRQ(pDevice, pState);
568 if (RT_SUCCESS(rc))
569 {
570 /*
571 * Configure device cloning.
572 */
573 clone_setup(&g_pVBoxGuestFreeBSDClones);
574 g_VBoxGuestFreeBSDEHTag = EVENTHANDLER_REGISTER(dev_clone, VBoxGuestFreeBSDClone, 0, 1000);
575 if (g_VBoxGuestFreeBSDEHTag)
576 {
577 printf(DEVICE_NAME ": loaded successfully\n");
578 return 0;
579 }
580
581 printf(DEVICE_NAME ": EVENTHANDLER_REGISTER(dev_clone,,,) failed\n");
582 clone_cleanup(&g_pVBoxGuestFreeBSDClones);
583 VBoxGuestFreeBSDRemoveIRQ(pDevice, pState);
584 }
585 else
586 printf((DEVICE_NAME ":VBoxGuestInitDevExt failed.\n"));
587 VBoxGuestDeleteDevExt(&g_DevExt);
588 }
589 else
590 printf((DEVICE_NAME ":VBoxGuestFreeBSDAddIRQ failed.\n"));
591 }
592 else
593 printf((DEVICE_NAME ":MMIO region setup failed.\n"));
594 }
595 else
596 printf((DEVICE_NAME ":IOport setup failed.\n"));
597
598 RTR0Term();
599 return ENXIO;
600}
601
602static int VBoxGuestFreeBSDProbe(device_t pDevice)
603{
604 if ((pci_get_vendor(pDevice) == VMMDEV_VENDORID) && (pci_get_device(pDevice) == VMMDEV_DEVICEID))
605 return 0;
606
607 return ENXIO;
608}
609
610static device_method_t VBoxGuestFreeBSDMethods[] =
611{
612 /* Device interface. */
613 DEVMETHOD(device_probe, VBoxGuestFreeBSDProbe),
614 DEVMETHOD(device_attach, VBoxGuestFreeBSDAttach),
615 DEVMETHOD(device_detach, VBoxGuestFreeBSDDetach),
616 {0,0}
617};
618
619static driver_t VBoxGuestFreeBSDDriver =
620{
621 DEVICE_NAME,
622 VBoxGuestFreeBSDMethods,
623 sizeof(struct VBoxGuestDeviceState),
624};
625
626static devclass_t VBoxGuestFreeBSDClass;
627
628DRIVER_MODULE(vboxguest, pci, VBoxGuestFreeBSDDriver, VBoxGuestFreeBSDClass, 0, 0);
629MODULE_VERSION(vboxguest, 1);
630
631int __gxx_personality_v0 = 0xdeadbeef;
632
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