示例#1
0
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;
}
示例#2
0
/**
 * 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;
    }
}
示例#3
0
/**
 * 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;
}