static int vgdrvFreeBSDAttach(device_t pDevice) { int rc; int iResId; struct VBoxGuestDeviceState *pState; cUsers = 0; /* * Initialize IPRT R0 driver, which internally calls OS-specific r0 init. */ rc = RTR0Init(0); if (RT_FAILURE(rc)) { LogFunc(("RTR0Init failed.\n")); return ENXIO; } pState = device_get_softc(pDevice); /* * Allocate I/O port resource. */ iResId = PCIR_BAR(0); pState->pIOPortRes = bus_alloc_resource_any(pDevice, SYS_RES_IOPORT, &iResId, RF_ACTIVE); pState->uIOPortBase = rman_get_start(pState->pIOPortRes); pState->iIOPortResId = iResId; if (pState->uIOPortBase) { /* * Map the MMIO region. */ iResId = PCIR_BAR(1); pState->pVMMDevMemRes = bus_alloc_resource_any(pDevice, SYS_RES_MEMORY, &iResId, RF_ACTIVE); pState->VMMDevMemHandle = rman_get_bushandle(pState->pVMMDevMemRes); pState->VMMDevMemSize = rman_get_size(pState->pVMMDevMemRes); pState->pMMIOBase = rman_get_virtual(pState->pVMMDevMemRes); pState->iVMMDevMemResId = iResId; if (pState->pMMIOBase) { /* * Call the common device extension initializer. */ rc = VGDrvCommonInitDevExt(&g_DevExt, pState->uIOPortBase, pState->pMMIOBase, pState->VMMDevMemSize, #if ARCH_BITS == 64 VBOXOSTYPE_FreeBSD_x64, #else VBOXOSTYPE_FreeBSD, #endif VMMDEV_EVENT_MOUSE_POSITION_CHANGED); if (RT_SUCCESS(rc)) { /* * Add IRQ of VMMDev. */ rc = vgdrvFreeBSDAddIRQ(pDevice, pState); if (RT_SUCCESS(rc)) { /* * Read host configuration. */ VGDrvCommonProcessOptionsFromHost(&g_DevExt); /* * Configure device cloning. */ clone_setup(&g_pvgdrvFreeBSDClones); g_vgdrvFreeBSDEHTag = EVENTHANDLER_REGISTER(dev_clone, vgdrvFreeBSDClone, 0, 1000); if (g_vgdrvFreeBSDEHTag) { printf(DEVICE_NAME ": loaded successfully\n"); return 0; } printf(DEVICE_NAME ": EVENTHANDLER_REGISTER(dev_clone,,,) failed\n"); clone_cleanup(&g_pvgdrvFreeBSDClones); vgdrvFreeBSDRemoveIRQ(pDevice, pState); } else printf((DEVICE_NAME ": VGDrvCommonInitDevExt failed.\n")); VGDrvCommonDeleteDevExt(&g_DevExt); } else printf((DEVICE_NAME ": vgdrvFreeBSDAddIRQ failed.\n")); } else printf((DEVICE_NAME ": MMIO region setup failed.\n")); } else printf((DEVICE_NAME ": IOport setup failed.\n")); RTR0Term(); return ENXIO; }
/** * Attach entry point, to attach a device to the system or resume it. * * @param pDip The module structure instance. * @param enmCmd Attach type (ddi_attach_cmd_t) * * @return corresponding solaris error code. */ static int vgdrvSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd) { LogFlow(("vgdrvSolarisAttach:\n")); switch (enmCmd) { case DDI_ATTACH: { if (g_pDip) { LogRel(("vgdrvSolarisAttach: Only one instance supported.\n")); return DDI_FAILURE; } int instance = ddi_get_instance(pDip); /* * Enable resources for PCI access. */ ddi_acc_handle_t PciHandle; int rc = pci_config_setup(pDip, &PciHandle); if (rc == DDI_SUCCESS) { /* * Map the register address space. */ caddr_t baseAddr; ddi_device_acc_attr_t deviceAttr; deviceAttr.devacc_attr_version = DDI_DEVICE_ATTR_V0; deviceAttr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; deviceAttr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; deviceAttr.devacc_attr_access = DDI_DEFAULT_ACC; rc = ddi_regs_map_setup(pDip, 1, &baseAddr, 0, 0, &deviceAttr, &g_PciIOHandle); if (rc == DDI_SUCCESS) { /* * Read size of the MMIO region. */ g_uIOPortBase = (uintptr_t)baseAddr; rc = ddi_dev_regsize(pDip, 2, &g_cbMMIO); if (rc == DDI_SUCCESS) { rc = ddi_regs_map_setup(pDip, 2, &g_pMMIOBase, 0, g_cbMMIO, &deviceAttr, &g_PciMMIOHandle); if (rc == DDI_SUCCESS) { /* * Add IRQ of VMMDev. */ rc = vgdrvSolarisAddIRQ(pDip); if (rc == DDI_SUCCESS) { /* * Call the common device extension initializer. */ rc = VGDrvCommonInitDevExt(&g_DevExt, g_uIOPortBase, g_pMMIOBase, g_cbMMIO, #if ARCH_BITS == 64 VBOXOSTYPE_Solaris_x64, #else VBOXOSTYPE_Solaris, #endif VMMDEV_EVENT_MOUSE_POSITION_CHANGED); if (RT_SUCCESS(rc)) { /* * Read host configuration. */ VGDrvCommonProcessOptionsFromHost(&g_DevExt); rc = ddi_create_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, 0 /* fFlags */); if (rc == DDI_SUCCESS) { g_pDip = pDip; pci_config_teardown(&PciHandle); return DDI_SUCCESS; } LogRel((DEVICE_NAME "::Attach: ddi_create_minor_node failed.\n")); VGDrvCommonDeleteDevExt(&g_DevExt); } else LogRel((DEVICE_NAME "::Attach: VGDrvCommonInitDevExt failed.\n")); vgdrvSolarisRemoveIRQ(pDip); } else LogRel((DEVICE_NAME "::Attach: vgdrvSolarisAddIRQ failed.\n")); ddi_regs_map_free(&g_PciMMIOHandle); } else LogRel((DEVICE_NAME "::Attach: ddi_regs_map_setup for MMIO region failed.\n")); } else LogRel((DEVICE_NAME "::Attach: ddi_dev_regsize for MMIO region failed.\n")); ddi_regs_map_free(&g_PciIOHandle); } else LogRel((DEVICE_NAME "::Attach: ddi_regs_map_setup for IOport failed.\n")); pci_config_teardown(&PciHandle); } else LogRel((DEVICE_NAME "::Attach: pci_config_setup failed rc=%d.\n", rc)); return DDI_FAILURE; } case DDI_RESUME: { /** @todo implement resume for guest driver. */ return DDI_SUCCESS; } default: return DDI_FAILURE; } }
/** * Start this service. */ bool org_virtualbox_VBoxGuest::start(IOService *pProvider) { /* * Low level initialization / device initialization should be performed only once. */ if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false)) return false; if (!IOService::start(pProvider)) return false; m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider); if (m_pIOPCIDevice) { if (isVmmDev(m_pIOPCIDevice)) { /* Enable memory response from VMM device */ m_pIOPCIDevice->setMemoryEnable(true); m_pIOPCIDevice->setIOEnable(true); IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0); if (pMem) { IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress(); /* Check that returned value is from I/O port range (at least it is 16-bit lenght) */ if((IOPortBasePhys >> 16) == 0) { RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys; void *pvMMIOBase = NULL; uint32_t cbMMIO = 0; m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1); if (m_pMap) { pvMMIOBase = (void *)m_pMap->getVirtualAddress(); cbMMIO = m_pMap->getLength(); } int rc = VGDrvCommonInitDevExt(&g_DevExt, IOPortBase, pvMMIOBase, cbMMIO, #if ARCH_BITS == 64 VBOXOSTYPE_MacOS_x64, #else VBOXOSTYPE_MacOS, #endif 0); if (RT_SUCCESS(rc)) { rc = vgdrvDarwinCharDevInit(); if (rc == KMOD_RETURN_SUCCESS) { if (setupVmmDevInterrupts(pProvider)) { /* register the service. */ registerService(); LogRel(("VBoxGuest: IOService started\n")); return true; } LogRel(("VBoxGuest: Failed to set up interrupts\n")); vgdrvDarwinCharDevRemove(); } else LogRel(("VBoxGuest: Failed to initialize character device (rc=%d).\n", rc)); VGDrvCommonDeleteDevExt(&g_DevExt); } else LogRel(("VBoxGuest: Failed to initialize common code (rc=%d).\n", rc)); if (m_pMap) { m_pMap->release(); m_pMap = NULL; } } } else LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n")); } else
/** * 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; }