static int vgdrvFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd) #endif { int rc; PVBOXGUESTSESSION pSession; LogFlow(("vgdrvFreeBSDOpen:\n")); /* * Try grab it (we don't grab the giant, remember). */ if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, (void *)0x42, NULL)) return EBUSY; /* * Create a new session. */ rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession); if (RT_SUCCESS(rc)) { if (ASMAtomicCmpXchgPtr(&pDev->si_drv1, pSession, (void *)0x42)) { Log(("vgdrvFreeBSDOpen: success - g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf())); ASMAtomicIncU32(&cUsers); return 0; } VGDrvCommonCloseSession(&g_DevExt, pSession); } LogRel(("vgdrvFreeBSDOpen: failed. rc=%d\n", rc)); return RTErrConvertToErrno(rc); }
static int vgdrvSolarisClose(dev_t Dev, int flag, int fType, cred_t *pCred) { LogFlow(("vgdrvSolarisClose: pid=%d\n", (int)RTProcSelf())); PVBOXGUESTSESSION pSession = NULL; vboxguest_state_t *pState = ddi_get_soft_state(g_pvgdrvSolarisState, getminor(Dev)); if (!pState) { Log(("vgdrvSolarisClose: failed to get pState.\n")); return EFAULT; } if (pState->pvProcRef != NULL) { proc_unref(pState->pvProcRef); pState->pvProcRef = NULL; } pSession = pState->pSession; pState->pSession = NULL; Log(("vgdrvSolarisClose: pSession=%p pState=%p\n", pSession, pState)); ddi_soft_state_free(g_pvgdrvSolarisState, getminor(Dev)); if (!pSession) { Log(("vgdrvSolarisClose: failed to get pSession.\n")); return EFAULT; } /* * Close the session. */ if (pSession) VGDrvCommonCloseSession(&g_DevExt, pSession); return 0; }
/** * Close device. * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. */ static int vgdrvLinuxRelease(struct inode *pInode, struct file *pFilp) { Log(("vgdrvLinuxRelease: pFilp=%p pSession=%p pid=%d/%d %s\n", pFilp, pFilp->private_data, RTProcSelf(), current->pid, current->comm)); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) /* This housekeeping was needed in older kernel versions to ensure that * the file pointer didn't get left on the polling queue. */ vgdrvLinuxFAsync(-1, pFilp, 0); #endif VGDrvCommonCloseSession(&g_DevExt, (PVBOXGUESTSESSION)pFilp->private_data); pFilp->private_data = NULL; return 0; }
/** * Driver free hook. * @param cookie The session. * * @return Haiku status code. */ static status_t vgdrvHaikuFree(void *cookie) { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; Log(("vgdrvHaikuFree: pSession=%p\n", pSession)); /* * Close the session if it's still hanging on to the device... */ if (VALID_PTR(pSession)) { VGDrvCommonCloseSession(&g_DevExt, pSession); ASMAtomicDecU32(&cUsers); } else Log(("vgdrvHaikuFree: si_drv1=%p!\n", pSession)); return B_OK; }
/** * Unload the module. */ static void __exit vgdrvLinuxModExit(void) { /* * Inverse order of init. */ vgdrvLinuxTermDeviceNodes(); #ifdef VBOXGUEST_WITH_INPUT_DRIVER vgdrvLinuxTermInputDevice(); #endif VGDrvCommonCloseSession(&g_DevExt, g_pKernelSession); VGDrvCommonDeleteDevExt(&g_DevExt); vgdrvLinuxTermISR(); pci_unregister_driver(&g_PciDriver); RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); RTLogDestroy(RTLogSetDefaultInstance(NULL)); RTR0Term(); }
/** * File close handler * */ static int vgdrvFreeBSDClose(struct cdev *pDev, int fFile, int DevType, struct thread *pTd) { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1; Log(("vgdrvFreeBSDClose: fFile=%#x pSession=%p\n", fFile, pSession)); /* * Close the session if it's still hanging on to the device... */ if (VALID_PTR(pSession)) { VGDrvCommonCloseSession(&g_DevExt, pSession); if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, NULL, pSession)) Log(("vgdrvFreeBSDClose: si_drv1=%p expected %p!\n", pDev->si_drv1, pSession)); ASMAtomicDecU32(&cUsers); /* Don't use destroy_dev here because it may sleep resulting in a hanging user process. */ destroy_dev_sched(pDev); } else Log(("vgdrvFreeBSDClose: si_drv1=%p!\n", pSession)); return 0; }
/** * @note This code is duplicated on other platforms with variations, so please * keep them all up to date when making changes! */ int VBOXCALL VBoxGuestIDC(void *pvSession, uintptr_t uReq, PVBGLREQHDR pReqHdr, size_t cbReq) { /* * Simple request validation (common code does the rest). */ int rc; if ( RT_VALID_PTR(pReqHdr) && cbReq >= sizeof(*pReqHdr)) { /* * All requests except the connect one requires a valid session. */ PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession; if (pSession) { if ( RT_VALID_PTR(pSession) && pSession->pDevExt == &g_DevExt) rc = VGDrvCommonIoCtl(uReq, &g_DevExt, pSession, pReqHdr, cbReq); else rc = VERR_INVALID_HANDLE; } else if (uReq == VBGL_IOCTL_IDC_CONNECT) { rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession); if (RT_SUCCESS(rc)) { rc = VGDrvCommonIoCtl(uReq, &g_DevExt, pSession, pReqHdr, cbReq); if (RT_FAILURE(rc)) VGDrvCommonCloseSession(&g_DevExt, pSession); } } else rc = VERR_INVALID_HANDLE; } else rc = VERR_INVALID_POINTER; return rc; }
/** * Initialize module. * * @returns appropriate status code. */ static int __init vgdrvLinuxModInit(void) { static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; PRTLOGGER pRelLogger; int rc; /* * Initialize IPRT first. */ rc = RTR0Init(0); if (RT_FAILURE(rc)) { printk(KERN_ERR DEVICE_NAME ": RTR0Init failed, rc=%d.\n", rc); return -EINVAL; } /* * Create the release log. * (We do that here instead of common code because we want to log * early failures using the LogRel macro.) */ rc = RTLogCreate(&pRelLogger, 0 /* fFlags */, "all", "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL); if (RT_SUCCESS(rc)) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) RTLogGroupSettings(pRelLogger, g_szLogGrp); RTLogFlags(pRelLogger, g_szLogFlags); RTLogDestinations(pRelLogger, g_szLogDst); #endif RTLogRelSetDefaultInstance(pRelLogger); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) g_fLoggerCreated = true; #endif /* * Locate and initialize the PCI device. */ rc = pci_register_driver(&g_PciDriver); if (rc >= 0 && g_pPciDev) { /* * Register the interrupt service routine for it. */ rc = vgdrvLinuxInitISR(); if (rc >= 0) { /* * Call the common device extension initializer. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_X86) VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux26; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_AMD64) VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux26_x64; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && defined(RT_ARCH_X86) VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux24; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && defined(RT_ARCH_AMD64) VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux24_x64; #else # warning "huh? which arch + version is this?" VBOXOSTYPE enmOsType = VBOXOSTYPE_Linux; #endif rc = VGDrvCommonInitDevExt(&g_DevExt, g_IOPortBase, g_pvMMIOBase, g_cbMMIO, enmOSType, VMMDEV_EVENT_MOUSE_POSITION_CHANGED); if (RT_SUCCESS(rc)) { /* * Create the kernel session for this driver. */ rc = VGDrvCommonCreateKernelSession(&g_DevExt, &g_pKernelSession); if (RT_SUCCESS(rc)) { /* * Create the kernel input device. */ #ifdef VBOXGUEST_WITH_INPUT_DRIVER rc = vgdrvLinuxCreateInputDevice(); if (rc >= 0) { #endif /* * Finally, create the device nodes. */ rc = vgdrvLinuxInitDeviceNodes(); if (rc >= 0) { /* some useful information for the user but don't show this on the console */ LogRel((DEVICE_NAME ": misc device minor %d, IRQ %d, I/O port %RTiop, MMIO at %RHp (size 0x%x)\n", g_MiscDevice.minor, g_pPciDev->irq, g_IOPortBase, g_MMIOPhysAddr, g_cbMMIO)); printk(KERN_DEBUG DEVICE_NAME ": Successfully loaded version " VBOX_VERSION_STRING " (interface " RT_XSTR(VMMDEV_VERSION) ")\n"); return rc; } /* bail out */ #ifdef VBOXGUEST_WITH_INPUT_DRIVER vgdrvLinuxTermInputDevice(); } else { LogRel((DEVICE_NAME ": vboxguestCreateInputDevice failed with rc=%Rrc\n", rc)); rc = RTErrConvertFromErrno(rc); } #endif VGDrvCommonCloseSession(&g_DevExt, g_pKernelSession); } VGDrvCommonDeleteDevExt(&g_DevExt); } else { LogRel((DEVICE_NAME ": VGDrvCommonInitDevExt failed with rc=%Rrc\n", rc)); rc = RTErrConvertFromErrno(rc); } vgdrvLinuxTermISR(); } } else { LogRel((DEVICE_NAME ": PCI device not found, probably running on physical hardware.\n")); rc = -ENODEV; } pci_unregister_driver(&g_PciDriver); RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); RTLogDestroy(RTLogSetDefaultInstance(NULL)); RTR0Term(); return rc; }