コード例 #1
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*
 * Remove a scheduling class module.
 *
 * we only null out the init func and the class functions because
 * once a class has been loaded it has that slot in the class
 * array until the next reboot. We don't decrement loaded_classes
 * because this keeps count of the number of classes that have
 * been loaded for this session. It will have to be this way until
 * we implement the class array as a linked list and do true
 * dynamic allocation.
 */
static int
mod_removesched(struct modlsched *modl, struct modlinkage *modlp)
{
	int status;
	sclass_t *clp;
	struct modctl *mcp;
	char *modname;
	id_t cid;

	status = getcidbyname(modl->sched_class->cl_name, &cid);
	if (status != 0) {
		mcp = mod_getctl(modlp);
		ASSERT(mcp != NULL);
		modname = mcp->mod_modname;
		cmn_err(CE_WARN, uninstall_err, modname);
		return (EINVAL);
	}
	clp = &sclass[cid];
	if (moddebug & MODDEBUG_NOAUL_SCHED ||
	    !rw_tryenter(clp->cl_lock, RW_WRITER))
		return (EBUSY);

	clp->cl_init = NULL;
	clp->cl_funcs = NULL;
	rw_exit(clp->cl_lock);
	return (0);
}
コード例 #2
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*
 * Find a free sysent entry or check if the specified one is free.
 */
static struct sysent *
mod_getsysent(struct modlinkage *modlp, struct sysent *se)
{
	int sysnum;
	struct modctl *mcp;
	char *mod_name;

	if ((mcp = mod_getctl(modlp)) == NULL) {
		/*
		 * This happens when we're looking up the module
		 * pointer as part of a stub installation.  So
		 * there's no need to whine at this point.
		 */
		return (NULL);
	}

	mod_name = mcp->mod_modname;

	if ((sysnum = mod_getsysnum(mod_name)) == -1) {
		cmn_err(CE_WARN, "system call missing from bind file");
		return (NULL);
	}

	if (sysnum > 0 && sysnum < NSYSCALL &&
	    (se[sysnum].sy_flags & (SE_LOADABLE | SE_NOUNLOAD)))
		return (se + sysnum);

	cmn_err(CE_WARN, "system call entry %d is already in use", sysnum);
	return (NULL);
}
コード例 #3
0
/**
 * Kernel entry points
 */
int _init(void)
{
    LogFunc((DEVICE_NAME ":_init\n"));

    /*
     * Prevent module autounloading.
     */
    modctl_t *pModCtl = mod_getctl(&g_VBoxNetAdpSolarisModLinkage);
    if (pModCtl)
        pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
    else
        LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));

    /*
     * Initialize IPRT.
     */
    int rc = RTR0Init(0);
    if (RT_SUCCESS(rc))
    {
        rc = mod_install(&g_VBoxNetAdpSolarisModLinkage);
        if (!rc)
            return rc;

        LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc));
        RTR0Term();
    }
    else
        LogRel((DEVICE_NAME ":failed to initialize IPRT (rc=%d)\n", rc));

    return RTErrConvertToErrno(rc);
}
コード例 #4
0
ファイル: modconf.c プロジェクト: andreiw/polaris
static int
mod_installipp(struct modlipp *modl, struct modlinkage *modlp)
{
	struct modctl *mcp = mod_getctl(modlp);

	ASSERT(mcp != NULL);
	return (ipp_mod_register(mcp->mod_modname, modl->ipp_ops));
}
コード例 #5
0
ファイル: modconf.c プロジェクト: andreiw/polaris
static int
mod_installdacf(struct modldacf *modl, struct modlinkage *modlp)
{
	struct modctl	*mcp;

	if ((mcp = mod_getctl(modlp)) == NULL)
		return (EINVAL);
	return (dacf_module_register(mcp->mod_modname, modl->dacf_dacfsw));
}
コード例 #6
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*ARGSUSED*/
static int
mod_removedacf(struct modldacf *modl, struct modlinkage *modlp)
{
	struct modctl	*mcp;

	if ((mcp = mod_getctl(modlp)) == NULL)
		return (EINVAL);
	return (dacf_module_unregister(mcp->mod_modname));
}
コード例 #7
0
ファイル: modconf.c プロジェクト: andreiw/polaris
static int
mod_installdev(struct modldev *modl, struct modlinkage *modlp)
{
	struct modctl	*mcp;

	if ((mcp = mod_getctl(modlp)) == NULL)
		return (EINVAL);
	return (sdev_module_register(mcp->mod_modname, modl->dev_ops));
}
コード例 #8
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*
 * Get module name.
 */
char *
mod_modname(struct modlinkage *modlp)
{
	struct modctl	*mcp;

	if ((mcp = mod_getctl(modlp)) == NULL)
		return (NULL);

	return (mcp->mod_modname);
}
コード例 #9
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*ARGSUSED*/
static int
mod_infodev(struct modldev *modl, struct modlinkage *modlp, int *p0)
{
	if (mod_getctl(modlp) == NULL) {
		*p0 = -1;
		return (0);	/* module is not yet installed */
	}

	*p0 = 0;
	return (0);
}
コード例 #10
0
/**
 * Kernel entry points
 */
int _init(void)
{
    int rc;

    LogFunc((DEVICE_NAME ":_init\n"));

    g_pDip = NULL;

    /*
     * Prevent module autounloading.
     */
    modctl_t *pModCtl = mod_getctl(&g_VBoxUSBMonSolarisModLinkage);
    if (pModCtl)
        pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
    else
        LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));

    /*
     * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
     */
    rc = RTR0Init(0);
    if (RT_SUCCESS(rc))
    {
        /*
         * Initialize global mutex.
         */
        mutex_init(&g_VBoxUSBMonSolarisMtx, NULL, MUTEX_DRIVER, NULL);
        rc = VBoxUSBFilterInit();
        if (RT_SUCCESS(rc))
        {
            rc = ddi_soft_state_init(&g_pVBoxUSBMonSolarisState, sizeof(vboxusbmon_state_t), 1);
            if (!rc)
            {
                rc = mod_install(&g_VBoxUSBMonSolarisModLinkage);
                if (!rc)
                    return rc;

                LogRel((DEVICE_NAME ":mod_install failed! rc=%d\n", rc));
                ddi_soft_state_fini(&g_pVBoxUSBMonSolarisState);
            }
            else
                LogRel((DEVICE_NAME ":ddi_soft_state_init failed! rc=%d\n", rc));
        }
        else
            LogRel((DEVICE_NAME ":VBoxUSBFilterInit failed! rc=%d\n", rc));

        mutex_destroy(&g_VBoxUSBMonSolarisMtx);
        RTR0Term();
    }
    else
        LogRel((DEVICE_NAME ":RTR0Init failed! rc=%d\n", rc));

    return -1;
}
コード例 #11
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*ARGSUSED*/
static int
mod_infoipp(struct modlipp *modl, struct modlinkage *modlp, int *p0)
{
	struct modctl *mcp = mod_getctl(modlp);
	ipp_mod_id_t mid;

	if (mcp == NULL) {
		*p0 = -1;
		return (0);	/* module is not yet installed */
	}

	mid = ipp_mod_lookup(mcp->mod_modname);

	*p0 = mid;
	return (0);
}
コード例 #12
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*ARGSUSED*/
static int
mod_infodrv(struct modldrv *modl, struct modlinkage *modlp, int *p0)
{
	struct modctl *mcp;
	char *mod_name;

	if ((mcp = mod_getctl(modlp)) == NULL) {
		*p0 = -1;
		return (0);	/* driver is not yet installed */
	}

	mod_name = mcp->mod_modname;

	*p0 = ddi_name_to_major(mod_name);
	return (0);
}
コード例 #13
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*ARGSUSED*/
static int
mod_removeipp(struct modlipp *modl, struct modlinkage *modlp)
{
	struct modctl *mcp = mod_getctl(modlp);
	extern kthread_id_t mod_aul_thread;
	ipp_mod_id_t mid;

	ASSERT(mcp != NULL);

	if ((moddebug & MODDEBUG_NOAUL_IPP) && (mod_aul_thread == curthread))
		return (EBUSY);

	mid = ipp_mod_lookup(mcp->mod_modname);
	ASSERT(mid != IPP_MOD_INVAL);

	return (ipp_mod_unregister(mid));
}
コード例 #14
0
/**
 * Kernel entry points
 */
int _init(void)
{
    /*
     * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
     */
    int rc = RTR0Init(0);
    if (RT_SUCCESS(rc))
    {
        PRTLOGGER pRelLogger;
        static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
        rc = RTLogCreate(&pRelLogger, 0 /* fFlags */, "all",
                         "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
                         RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER, NULL);
        if (RT_SUCCESS(rc))
            RTLogRelSetDefaultInstance(pRelLogger);
        else
            cmn_err(CE_NOTE, "failed to initialize driver logging rc=%d!\n", rc);

        mutex_init(&g_LdiMtx, NULL, MUTEX_DRIVER, NULL);

        /*
         * Prevent module autounloading.
         */
        modctl_t *pModCtl = mod_getctl(&g_VBoxGuestSolarisModLinkage);
        if (pModCtl)
            pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
        else
            LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));

        rc = ddi_soft_state_init(&g_pVBoxGuestSolarisState, sizeof(vboxguest_state_t), 1);
        if (!rc)
        {
            rc = mod_install(&g_VBoxGuestSolarisModLinkage);
            if (rc)
                ddi_soft_state_fini(&g_pVBoxGuestSolarisState);
        }
    }
    else
    {
        cmn_err(CE_NOTE, "_init: RTR0Init failed. rc=%d\n", rc);
        return EINVAL;
    }

    return rc;
}
コード例 #15
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*
 * Remove a filesystem
 */
static int
mod_removefs(struct modlfs *modl, struct modlinkage *modlp)
{
	struct vfssw *vswp;
	struct modctl *mcp;
	char *modname;

	if (moddebug & MODDEBUG_NOAUL_FS)
		return (EBUSY);

	WLOCK_VFSSW();
	if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) {
		mcp = mod_getctl(modlp);
		ASSERT(mcp != NULL);
		modname = mcp->mod_modname;
		WUNLOCK_VFSSW();
		cmn_err(CE_WARN, uninstall_err, modname);
		return (EINVAL);
	}
	if (vswp->vsw_count != 1) {
		vfs_unrefvfssw(vswp);
		WUNLOCK_VFSSW();
		return (EBUSY);
	}

	/* XXX - Shouldn't the refcount be sufficient? */

	if (vfs_opsinuse(&vswp->vsw_vfsops)) {
		vfs_unrefvfssw(vswp);
		WUNLOCK_VFSSW();
		return (EBUSY);
	}

	vfs_freeopttbl(&vswp->vsw_optproto);
	vswp->vsw_optproto.mo_count = 0;

	vswp->vsw_flag = 0;
	vswp->vsw_init = NULL;
	vfs_unrefvfssw(vswp);
	WUNLOCK_VFSSW();
	return (0);
}
コード例 #16
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*
 * Remove a loadable system call entry from a sysent table.
 */
static int
mod_removesys_sysent(
	struct modlsys		*modl,
	struct modlinkage	*modlp,
	struct sysent		table[])
{
	struct sysent	*sysp;

	if ((sysp = mod_getsysent(modlp, table)) == NULL ||
	    (sysp->sy_flags & (SE_LOADABLE | SE_NOUNLOAD)) == 0 ||
	    sysp->sy_call != modl->sys_sysent->sy_call) {

		struct modctl *mcp = mod_getctl(modlp);
		char *modname = mcp->mod_modname;

		cmn_err(CE_WARN, uninstall_err, modname);
		return (EINVAL);
	}

	/* If we can't get the write lock, we can't unlink from the system */

	if (!(moddebug & MODDEBUG_NOAUL_SYS) &&
	    rw_tryenter(sysp->sy_lock, RW_WRITER)) {
		/*
		 * Check the flags to be sure the syscall is still
		 * (un)loadable.
		 * If SE_NOUNLOAD is set, SE_LOADABLE will not be.
		 */
		if ((sysp->sy_flags & (SE_LOADED | SE_LOADABLE)) ==
		    (SE_LOADED | SE_LOADABLE)) {
			sysp->sy_flags &= ~SE_LOADED;
			sysp->sy_callc = loadable_syscall;
			sysp->sy_call = (int (*)())nosys;
			rw_exit(sysp->sy_lock);
			return (0);
		}
		rw_exit(sysp->sy_lock);
	}
	return (EBUSY);
}
コード例 #17
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*
 * Install an exec module.
 */
static int
mod_installexec(struct modlexec *modl, struct modlinkage *modlp)
{
	struct execsw *eswp;
	struct modctl *mcp;
	char *modname;
	char *magic;
	size_t magic_size;

	/*
	 * See if execsw entry is already allocated.  Can't use findexectype()
	 * because we may get a recursive call to here.
	 */

	if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL) {
		mcp = mod_getctl(modlp);
		ASSERT(mcp != NULL);
		modname = mcp->mod_modname;
		magic = modl->exec_execsw->exec_magic;
		magic_size = modl->exec_execsw->exec_maglen;
		if ((eswp = allocate_execsw(modname, magic, magic_size)) ==
		    NULL) {
			printf("no unused entries in 'execsw'\n");
			return (ENOSPC);
		}
	}
	if (eswp->exec_func != NULL) {
		printf("exec type %x is already installed\n",
			*eswp->exec_magic);
			return (EBUSY);		 /* it's already there! */
	}

	rw_enter(eswp->exec_lock, RW_WRITER);
	eswp->exec_func = modl->exec_execsw->exec_func;
	eswp->exec_core = modl->exec_execsw->exec_core;
	rw_exit(eswp->exec_lock);

	return (0);
}
コード例 #18
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*
 * Remove an exec module.
 */
static int
mod_removeexec(struct modlexec *modl, struct modlinkage *modlp)
{
	struct execsw *eswp;
	struct modctl *mcp;
	char *modname;

	eswp = findexecsw(modl->exec_execsw->exec_magic);
	if (eswp == NULL) {
		mcp = mod_getctl(modlp);
		ASSERT(mcp != NULL);
		modname = mcp->mod_modname;
		cmn_err(CE_WARN, uninstall_err, modname);
		return (EINVAL);
	}
	if (moddebug & MODDEBUG_NOAUL_EXEC ||
	    !rw_tryenter(eswp->exec_lock, RW_WRITER))
		return (EBUSY);
	eswp->exec_func = NULL;
	eswp->exec_core = NULL;
	rw_exit(eswp->exec_lock);
	return (0);
}
コード例 #19
0
ファイル: VirtioNet-solaris.c プロジェクト: OSLL/vboxhsm
/**
 * Kernel entry points
 */
int _init(void)
{
    LogFlowFunc((VIRTIOLOGNAME ":_init\n"));

    /*
     * Prevent module autounloading.
     */
    modctl_t *pModCtl = mod_getctl(&g_VirtioNetModLinkage);
    if (pModCtl)
        pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
    else
        LogRel((VIRTIOLOGNAME ":failed to disable autounloading!\n"));

    /*
     * Initialize IPRT.
     */
    int rc = RTR0Init(0);
    if (RT_SUCCESS(rc))
    {
        /*
         * Initialize Solaris specific globals here.
         */
        mac_init_ops(&g_VirtioNetDevOps, DEVICE_NAME);
        rc = mod_install(&g_VirtioNetModLinkage);
        if (!rc)
            return rc;

        LogRel((VIRTIOLOGNAME ":mod_install failed. rc=%d\n", rc));
        mac_fini_ops(&g_VirtioNetDevOps);
        RTR0Term();
        return rc;
    }
    else
        LogRel((VIRTIOLOGNAME ":failed to initialize IPRT (rc=%d)\n", rc));

    return RTErrConvertToErrno(rc);
}
コード例 #20
0
/**
 * Kernel entry points
 */
int _init(void)
{
#if 0    /* No IPRT logging before RTR0Init() is done! */
    LogFlowFunc(("vboxdrv:_init\n"));
#endif

    /*
     * Prevent module autounloading.
     */
    modctl_t *pModCtl = mod_getctl(&g_VBoxDrvSolarisModLinkage);
    if (pModCtl)
        pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
    else
        cmn_err(CE_NOTE, "vboxdrv: failed to disable autounloading!\n");

    /*
     * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
     */
    int rc = RTR0Init(0);
    if (RT_SUCCESS(rc))
    {
        /*
         * Initialize the device extension
         */
        rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION));
        if (RT_SUCCESS(rc))
        {
            cmn_err(CE_CONT, "!tsc::mode %s @ tentative %lu Hz\n", SUPGetGIPModeName(g_DevExt.pGip), g_DevExt.pGip->u64CpuHz);

            /*
             * Initialize the session hash table.
             */
            memset(g_apSessionHashTab, 0, sizeof(g_apSessionHashTab));
            rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvSol");
            if (RT_SUCCESS(rc))
            {
                rc = ddi_soft_state_init(&g_pVBoxDrvSolarisState, sizeof(vbox_devstate_t), 8);
                if (!rc)
                {
                    rc = mod_install(&g_VBoxDrvSolarisModLinkage);
                    if (!rc)
                        return rc; /* success */

                    ddi_soft_state_fini(&g_pVBoxDrvSolarisState);
                    LogRel(("vboxdrv: mod_install failed! rc=%d\n", rc));
                }
                else
                    LogRel(("vboxdrv: failed to initialize soft state.\n"));

                RTSpinlockDestroy(g_Spinlock);
                g_Spinlock = NIL_RTSPINLOCK;
            }
            else
            {
                LogRel(("VBoxDrvSolarisAttach: RTSpinlockCreate failed\n"));
                rc = RTErrConvertToErrno(rc);
            }
            supdrvDeleteDevExt(&g_DevExt);
        }
        else
        {
            LogRel(("VBoxDrvSolarisAttach: supdrvInitDevExt failed\n"));
            rc = EINVAL;
        }
        RTR0TermForced();
    }
    else
    {
        LogRel(("VBoxDrvSolarisAttach: failed to init R0Drv\n"));
        rc = RTErrConvertToErrno(rc);
    }
    memset(&g_DevExt, 0, sizeof(g_DevExt));

    return rc;
}
コード例 #21
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*ARGSUSED1*/
static int
mod_installfs(struct modlfs *modl, struct modlinkage *modlp)
{
	struct vfssw *vswp;
	struct modctl *mcp;
	char *fsname;
	char ksname[KSTAT_STRLEN + 1];
	int fstype;	/* index into vfssw[] and vsanchor_fstype[] */
	int allocated;
	int err;
	int vsw_stats_enabled;
	/* Not for public consumption so these aren't in a header file */
	extern int	vopstats_enabled;
	extern vopstats_t **vopstats_fstype;
	extern kstat_t *new_vskstat(char *, vopstats_t *);
	extern void initialize_vopstats(vopstats_t *);

	if (modl->fs_vfsdef->def_version == VFSDEF_VERSION) {
		/* Version matched */
		fsname = modl->fs_vfsdef->name;
	} else {
		if ((modl->fs_vfsdef->def_version > 0) &&
		    (modl->fs_vfsdef->def_version < VFSDEF_VERSION)) {
			/* Older VFSDEF_VERSION */
			fsname = modl->fs_vfsdef->name;
		} else if ((mcp = mod_getctl(modlp)) != NULL) {
			/* Pre-VFSDEF_VERSION */
			fsname = mcp->mod_modname;
		} else {
			/* If all else fails... */
			fsname = "<unknown file system type>";
		}

		cmn_err(CE_WARN, "file system '%s' version mismatch", fsname);
		return (ENXIO);
	}

	allocated = 0;

	WLOCK_VFSSW();
	if ((vswp = vfs_getvfsswbyname(fsname)) == NULL) {
		if ((vswp = allocate_vfssw(fsname)) == NULL) {
			WUNLOCK_VFSSW();
			/*
			 * See 1095689.  If this message appears, then
			 * we either need to make the vfssw table bigger
			 * statically, or make it grow dynamically.
			 */
			cmn_err(CE_WARN, "no room for '%s' in vfssw!", fsname);
			return (ENXIO);
		}
		allocated = 1;
	}
	ASSERT(vswp != NULL);

	fstype = vswp - vfssw;	/* Pointer arithmetic to get the fstype */

	/* Turn on everything by default *except* VSW_STATS */
	vswp->vsw_flag = modl->fs_vfsdef->flags & ~(VSW_STATS);

	if (modl->fs_vfsdef->flags & VSW_HASPROTO) {
		vfs_mergeopttbl(&vfs_mntopts, modl->fs_vfsdef->optproto,
		    &vswp->vsw_optproto);
	} else {
		vfs_copyopttbl(&vfs_mntopts, &vswp->vsw_optproto);
	}

	if (modl->fs_vfsdef->flags & VSW_CANRWRO) {
		/*
		 * This obviously implies VSW_CANREMOUNT.
		 */
		vswp->vsw_flag |= VSW_CANREMOUNT;
	}

	/*
	 * If stats are enabled system wide and for this fstype, then
	 * set the VSW_STATS flag in the proper vfssw[] table entry.
	 */
	if (vopstats_enabled && modl->fs_vfsdef->flags & VSW_STATS) {
		vswp->vsw_flag |= VSW_STATS;
	}

	if (modl->fs_vfsdef->init == NULL)
		err = EFAULT;
	else
		err = (*(modl->fs_vfsdef->init))(fstype, fsname);

	if (err != 0) {
		if (allocated) {
			kmem_free(vswp->vsw_name, strlen(vswp->vsw_name)+1);
			vswp->vsw_name = "";
		}
		vswp->vsw_flag = 0;
		vswp->vsw_init = NULL;
	}

	/* We don't want to hold the vfssw[] write lock over a kmem_alloc() */
	vsw_stats_enabled = vswp->vsw_flag & VSW_STATS;

	vfs_unrefvfssw(vswp);
	WUNLOCK_VFSSW();

	/* If everything is on, set up the per-fstype vopstats */
	if (vsw_stats_enabled && vopstats_enabled &&
	    vopstats_fstype && vopstats_fstype[fstype] == NULL) {
		(void) strlcpy(ksname, VOPSTATS_STR, sizeof (ksname));
		(void) strlcat(ksname, vfssw[fstype].vsw_name, sizeof (ksname));
		vopstats_fstype[fstype] =
		    kmem_alloc(sizeof (vopstats_t), KM_SLEEP);
		initialize_vopstats(vopstats_fstype[fstype]);
		(void) new_vskstat(ksname, vopstats_fstype[fstype]);
	}
	return (err);
}
コード例 #22
0
ファイル: modconf.c プロジェクト: andreiw/polaris
static int
mod_removedrv(struct modldrv *modl, struct modlinkage *modlp)
{
	struct modctl *mcp;
	struct dev_ops *ops;
	struct devnames *dnp;
	struct dev_ops *dp;
	major_t major;
	char *modname;
	extern kthread_id_t mod_aul_thread;
	struct streamtab *str;
	cdevsw_impl_t *cdp;
	int err = 0;

	/* Don't auto unload modules on if moddebug flag is set */
	if ((moddebug & MODDEBUG_NOAUL_DRV) && (mod_aul_thread == curthread)) {
		err = EBUSY;
		goto done;
	}

	/* Verify modname has a driver major */
	mcp = mod_getctl(modlp);
	ASSERT(mcp != NULL);
	modname = mcp->mod_modname;

	if ((major = ddi_name_to_major(modname)) == -1) {
		cmn_err(CE_WARN, uninstall_err, modname);
		err = EINVAL;
		goto done;
	}

	ops = modl->drv_dev_ops;
	dnp = &(devnamesp[major]);
	LOCK_DEV_OPS(&(dnp->dn_lock));

	dp = devopsp[major];

	if (dp != ops)  {
		cmn_err(CE_NOTE, "mod_removedrv: mismatched driver for %s",
		    modname);
		err = EBUSY;
		goto unlock;
	}

	/*
	 * A driver is not unloadable if its dev_ops are held
	 */
	if (!DRV_UNLOADABLE(dp)) {
		mod_dprintf(DRV_DBG, "Cannot unload device driver <%s>,"
		    " refcnt %d\n", modname, dp->devo_refcnt);
		err = EBUSY;
		goto unlock;
	}

	/*
	 * OK to unload.
	 */
	if ((str = STREAMSTAB(major)) != NULL) {	/* streams driver */
		cdp = &devimpl[major];
		ASSERT(cdp->d_str == str);
		cdp->d_str = NULL;

		/* check for reference to per-dev syncq */
		if (cdp->d_dmp != NULL) {
			rele_dm(cdp->d_dmp);
			cdp->d_dmp = NULL;
		}
	}

	devopsp[major] = &mod_nodev_ops;
	dnp->dn_flags &= ~(DN_DRIVER_HELD|DN_NO_AUTODETACH);

unlock:
	UNLOCK_DEV_OPS(&(dnp->dn_lock));
done:
	return (err);
}
コード例 #23
0
ファイル: modconf.c プロジェクト: andreiw/polaris
/*
 * Install a new driver
 */
static int
mod_installdrv(struct modldrv *modl, struct modlinkage *modlp)
{
	struct modctl *mcp;
	struct dev_ops *ops;
	char *modname;
	major_t major;
	struct dev_ops *dp;
	struct devnames *dnp;
	struct streamtab *str;
	cdevsw_impl_t *cdp;
	uint_t sqtype;
	uint_t qflag;
	uint_t flag;
	int err = 0;

	/* sanity check module */
	if ((mcp = mod_getctl(modlp)) == NULL) {
		cmn_err(CE_WARN, "mod_install: bad module linkage data");
		err = ENXIO;
		goto done;
	}
	modname = mcp->mod_modname;

	/* Sanity check modname */
	if ((major = ddi_name_to_major(modname)) == (major_t)-1) {
#ifdef DEBUG
		cmn_err(CE_WARN,
		    "mod_installdrv: no major number for %s", modname);
#endif
		err = ENXIO;
		goto done;
	}

	/* Verify MP safety flag */
	ops = modl->drv_dev_ops;
	if (ops->devo_bus_ops == NULL && ops->devo_cb_ops != NULL &&
	    !(ops->devo_cb_ops->cb_flag & D_MP)) {
		cmn_err(CE_WARN,
		    "mod_installdrv: MT-unsafe driver '%s' rejected", modname);
		err = ENXIO;
		goto done;
	}


	/* Is bus_map_fault signature correct (version 8 and higher)? */
	if (ops->devo_bus_ops != NULL &&
	    ops->devo_bus_ops->bus_map_fault != NULL &&
	    ops->devo_bus_ops->bus_map_fault != i_ddi_map_fault &&
	    ops->devo_bus_ops->busops_rev < BUSO_REV_8) {

		cmn_err(CE_WARN,
		    "mod_installdrv: busops' revision of '%s' is too low"
		    " (must be at least 8)", modname);
		err = ENXIO;
		goto done;
	}


	/* Make sure the driver is uninstalled */
	dnp = &devnamesp[major];
	LOCK_DEV_OPS(&dnp->dn_lock);
	dp = devopsp[major];

	if (dnp->dn_flags & DN_DRIVER_REMOVED) {
#ifdef DEBUG
		cmn_err(CE_NOTE,
		    "mod_installdrv: driver has been removed %s", modname);
#endif
		err = ENXIO;
		goto unlock;
	}

	if (dp != &nodev_ops && dp != &mod_nodev_ops) {
		cmn_err(CE_WARN,
		    "mod_installdrv: driver already installed %s", modname);
		err = EALREADY;
		goto unlock;
	}

	devopsp[major] = ops; /* setup devopsp */

	if ((str = STREAMSTAB(major)) != NULL) {	/* streams driver */
		flag = CBFLAG(major);
		if ((err = devflg_to_qflag(str, flag, &qflag, &sqtype)) != 0)
			goto unlock;
		cdp = &devimpl[major];
		ASSERT(cdp->d_str == NULL);
		cdp->d_str = str;
		cdp->d_qflag = qflag | QISDRV;
		cdp->d_sqtype = sqtype;
	}

	if (ops->devo_bus_ops == NULL)
		dnp->dn_flags |= DN_LEAF_DRIVER;

unlock:
	UNLOCK_DEV_OPS(&dnp->dn_lock);
done:
	return (err);
}
コード例 #24
0
/**
 * Kernel entry points
 */
int _init(void)
{
    LogFlowFunc((DEVICE_NAME ":_init\n"));

    /*
     * Prevent module autounloading.
     */
    modctl_t *pModCtl = mod_getctl(&g_VBoxDrvSolarisModLinkage);
    if (pModCtl)
        pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
    else
        LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));

    /*
     * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
     */
    int rc = RTR0Init(0);
    if (RT_SUCCESS(rc))
    {
        /*
         * Initialize the device extension
         */
        rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION));
        if (RT_SUCCESS(rc))
        {
            /*
             * Initialize the session hash table.
             */
            memset(g_apSessionHashTab, 0, sizeof(g_apSessionHashTab));
            rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvSol");
            if (RT_SUCCESS(rc))
            {
                rc = ddi_soft_state_init(&g_pVBoxDrvSolarisState, sizeof(vbox_devstate_t), 8);
                if (!rc)
                {
                    rc = mod_install(&g_VBoxDrvSolarisModLinkage);
                    if (!rc)
                        return rc; /* success */

                    ddi_soft_state_fini(&g_pVBoxDrvSolarisState);
                    LogRel((DEVICE_NAME ":mod_install failed! rc=%d\n", rc));
                }
                else
                    LogRel((DEVICE_NAME ":failed to initialize soft state.\n"));

                RTSpinlockDestroy(g_Spinlock);
                g_Spinlock = NIL_RTSPINLOCK;
            }
            else
            {
                LogRel((DEVICE_NAME ":VBoxDrvSolarisAttach: RTSpinlockCreate failed\n"));
                rc = RTErrConvertToErrno(rc);
            }
            supdrvDeleteDevExt(&g_DevExt);
        }
        else
        {
            LogRel((DEVICE_NAME ":VBoxDrvSolarisAttach: supdrvInitDevExt failed\n"));
            rc = RTErrConvertToErrno(rc);
        }
        RTR0TermForced();
    }
    else
    {
        LogRel((DEVICE_NAME ":VBoxDrvSolarisAttach: failed to init R0Drv\n"));
        rc = RTErrConvertToErrno(rc);
    }
    memset(&g_DevExt, 0, sizeof(g_DevExt));

    return rc;
}