diff options
| author | pgoyette <pgoyette@NetBSD.org> | 2015-12-07 03:25:57 +0000 |
|---|---|---|
| committer | pgoyette <pgoyette@NetBSD.org> | 2015-12-07 03:25:57 +0000 |
| commit | edf0b3446a599a7c13dc35601a62ee2e6de22996 (patch) | |
| tree | 9b55af70cdb2215e4c18b77c41795cff585ebbfd /sys/dev/clockctl.c | |
| parent | a30736a20f4afa2515329a601f5bbf2924497c11 (diff) | |
Modularize the clockctl pseudo-device and link to the build.
Diffstat (limited to 'sys/dev/clockctl.c')
| -rw-r--r-- | sys/dev/clockctl.c | 181 |
1 files changed, 177 insertions, 4 deletions
diff --git a/sys/dev/clockctl.c b/sys/dev/clockctl.c index 169bd335f24..09417fcb190 100644 --- a/sys/dev/clockctl.c +++ b/sys/dev/clockctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: clockctl.c,v 1.32 2014/07/25 08:10:35 dholland Exp $ */ +/* $NetBSD: clockctl.c,v 1.33 2015/12/07 03:25:57 pgoyette Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -31,10 +31,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: clockctl.c,v 1.32 2014/07/25 08:10:35 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: clockctl.c,v 1.33 2015/12/07 03:25:57 pgoyette Exp $"); +#ifdef _KERNEL_OPT #include "opt_ntp.h" #include "opt_compat_netbsd.h" +#endif #include <sys/param.h> #include <sys/systm.h> @@ -48,17 +50,28 @@ __KERNEL_RCSID(0, "$NetBSD: clockctl.c,v 1.32 2014/07/25 08:10:35 dholland Exp $ #include <sys/timex.h> #endif /* NTP */ #include <sys/kauth.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/once.h> #include <sys/clockctl.h> #ifdef COMPAT_50 #include <compat/sys/clockctl.h> +#include <compat/sys/time_types.h> #endif +kmutex_t clockctl_mtx; +int clockctl_refcnt; + +ONCE_DECL(clockctl_once); + +#include "ioconf.h" + dev_type_ioctl(clockctlioctl); const struct cdevsw clockctl_cdevsw = { - .d_open = nullopen, - .d_close = nullclose, + .d_open = clockctlopen, + .d_close = clockctlclose, .d_read = noread, .d_write = nowrite, .d_ioctl = clockctlioctl, @@ -102,8 +115,102 @@ void clockctlattach(int num) { +/* + * Don't initialize the listener here - it will get handled as part + * of module initialization. + */ +#if 0 clockctl_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, clockctl_listener_cb, NULL); +#endif +} + +/* + * Maintain a refcount for each open/close, so we know when it is + * safe to call devsw_detach() + */ +int +clockctlopen(dev_t dev, int flag, int mode, struct lwp *l) +{ + + mutex_enter(&clockctl_mtx); + clockctl_refcnt++; + mutex_exit(&clockctl_mtx); + + return 0; +} + +int +clockctlclose(dev_t dev, int flag, int mode, struct lwp *l) +{ + + mutex_enter(&clockctl_mtx); + clockctl_refcnt--; + mutex_exit(&clockctl_mtx); + + return 0; +} + +int +clockctl_init(void) +{ + + mutex_init(&clockctl_mtx, MUTEX_DEFAULT, IPL_NONE); + clockctl_refcnt = 0; + return 0; +} + +MODULE(MODULE_CLASS_DRIVER, clockctl, NULL); + +int +clockctl_modcmd(modcmd_t cmd, void *data) +{ + int error; +#ifdef _MODULE + int bmajor, cmajor; +#endif + + error = 0; + + switch (cmd) { + case MODULE_CMD_INIT: + RUN_ONCE(&clockctl_once, clockctl_init); + + clockctl_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, + clockctl_listener_cb, NULL); + +#ifdef _MODULE + bmajor = cmajor = -1; + error = devsw_attach("clockctl", NULL, &bmajor, + &clockctl_cdevsw, &cmajor); + if (error != 0) + kauth_unlisten_scope(clockctl_listener); +#endif + + break; + + case MODULE_CMD_FINI: + mutex_enter(&clockctl_mtx); + if (clockctl_refcnt != 0) { + mutex_exit(&clockctl_mtx); + return EBUSY; + } +#ifdef _MODULE + error = devsw_detach(NULL, &clockctl_cdevsw); +#endif + mutex_exit(&clockctl_mtx); + + if (error == 0) + kauth_unlisten_scope(clockctl_listener); + + break; + + default: + error = ENOTTY; + break; + } + + return error; } int @@ -177,4 +284,70 @@ clockctlioctl( return (error); } +#ifdef COMPAT_50 +int +compat50_clockctlioctl(dev_t dev, u_long cmd, void *data, int flags, + struct lwp *l) +{ + int error = 0; + const struct cdevsw *cd = cdevsw_lookup(dev); + + if (cd == NULL || cd->d_ioctl == NULL) + return ENXIO; + + switch (cmd) { + case CLOCKCTL_OSETTIMEOFDAY: { + struct timeval50 tv50; + struct timeval tv; + struct clockctl50_settimeofday *args = data; + error = copyin(args->tv, &tv50, sizeof(tv50)); + if (error) + return (error); + timeval50_to_timeval(&tv50, &tv); + error = settimeofday1(&tv, false, args->tzp, l, false); + break; + } + case CLOCKCTL_OADJTIME: { + struct timeval atv, oldatv; + struct timeval50 atv50; + struct clockctl50_adjtime *args = data; + + if (args->delta) { + error = copyin(args->delta, &atv50, sizeof(atv50)); + if (error) + return (error); + timeval50_to_timeval(&atv50, &atv); + } + adjtime1(args->delta ? &atv : NULL, + args->olddelta ? &oldatv : NULL, l->l_proc); + if (args->olddelta) { + timeval_to_timeval50(&oldatv, &atv50); + error = copyout(&atv50, args->olddelta, sizeof(atv50)); + } + break; + } + case CLOCKCTL_OCLOCK_SETTIME: { + struct timespec50 tp50; + struct timespec tp; + struct clockctl50_clock_settime *args = data; + + error = copyin(args->tp, &tp50, sizeof(tp50)); + if (error) + return (error); + timespec50_to_timespec(&tp50, &tp); + error = clock_settime1(l->l_proc, args->clock_id, &tp, true); + break; + } + case CLOCKCTL_ONTP_ADJTIME: + /* The ioctl number changed but the data did not change. */ + error = (cd->d_ioctl)(dev, CLOCKCTL_NTP_ADJTIME, + data, flags, l); + break; + default: + error = EINVAL; + } + + return (error); +} +#endif |
