summaryrefslogtreecommitdiff
path: root/emulators/rtc/files/rtc.c
diff options
context:
space:
mode:
authorAkinori MUSHA <knu@FreeBSD.org>2000-04-03 15:28:30 +0000
committerAkinori MUSHA <knu@FreeBSD.org>2000-04-03 15:28:30 +0000
commit3cf900afec2aff896e54b02214e9c9d023d0cd20 (patch)
tree25af9c88375549ba5c87e1b652d23c1871e35a73 /emulators/rtc/files/rtc.c
parentUpgrade to 4.16. (diff)
This is rtc, a kernel module for /dev/rtc device support.
Some apps such as VMware for Linux would be happy with it. The code was originally written by Vladimir N. Silyaev. Note: It _includes_ Linux ioctl support, but basically it's FreeBSD native stuff. I'm importing this into emulators category for convevience' sake. Check it out.
Notes
Notes: svn path=/head/; revision=27306
Diffstat (limited to 'emulators/rtc/files/rtc.c')
-rw-r--r--emulators/rtc/files/rtc.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/emulators/rtc/files/rtc.c b/emulators/rtc/files/rtc.c
new file mode 100644
index 000000000000..9623b2f2ac27
--- /dev/null
+++ b/emulators/rtc/files/rtc.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright by Vladimir N. Silyaev 2000
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $vmFreeBSD: vmware/vmnet-only/freebsd/vmnet.c,v 1.14 2000/01/23 22:29:50 vsilyaev Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <sys/filio.h>
+#include <sys/poll.h>
+#include <sys/uio.h>
+#include <sys/vnode.h>
+
+#include <machine/clock.h>
+
+#include "rtc.h"
+
+#define CDEV_MAJOR 202
+#if defined(CDEV_MAJOR_) && CDEV_MAJOR != CDEV_MAJOR_
+#error "CDEV_MAJOR != CDEV_MAJOR_"
+#endif
+
+#define DEVICE_NAME "rtc"
+
+enum rtc_log_level {Lenter=0, Lexit=1, Linfo, Lwarning, Lfail};
+#define DEBUG 0
+#if DEBUG
+#define DEB(x) x
+#define DLog(level, fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args)
+#else /* !DEBUG */
+#define DEB(x)
+#define DLog(level, fmt, args...)
+#endif /* DEBUG */
+
+struct rtc_softc {
+ dev_t dev; /* Back reference to device */
+ struct {
+ int freq;
+ struct {
+ int opened:1;
+ int enabled:1;
+ } flags;
+ } var;
+};
+
+static struct rtc_softc *rtc_sc=NULL;
+
+static d_open_t rtc_open;
+static d_close_t rtc_close;
+static d_ioctl_t rtc_ioctl;
+static d_poll_t rtc_poll;
+
+static int rtc_modeevent(module_t mod, int cmd, void *arg);
+
+static struct cdevsw rtc_cdevsw = {
+ /* open */ rtc_open,
+ /* close */ rtc_close,
+ /* read */ noread,
+ /* write */ nowrite,
+ /* ioctl */ rtc_ioctl,
+ /* poll */ rtc_poll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* name */ DEVICE_NAME,
+ /* maj */ CDEV_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+ /* bmaj */ -1
+};
+
+/*
+ * Now declare the module to the system.
+ * IMPORTANT: Must be before netgraph node declaration.
+ */
+DEV_MODULE(rtc, rtc_modeevent, 0);
+
+
+/* -=-=-=-=-=-=-=-=-= attach/detach device stuff -=-=-=-=-=-=-=-=-= */
+
+static struct rtc_softc *
+rtc_attach(dev_t dev)
+{
+ struct rtc_softc *sc;
+ int unit;
+
+ unit = lminor(dev);
+ DLog(Lenter, "%d %p", unit, dev);
+ if (dev->si_drv1) {
+ DLog(Lexit, "old %p, %p", dev, dev->si_drv1);
+ return dev->si_drv1;
+ }
+
+ if (rtc_sc!=NULL)
+ return NULL;
+
+ dev = make_dev(&rtc_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, 0600, DEVICE_NAME);
+ if (dev==NULL)
+ return (NULL);
+
+ MALLOC(sc, struct rtc_softc*, sizeof(*sc), M_DEVBUF, M_WAITOK);
+ if (sc==NULL)
+ return NULL;
+
+ bzero(sc, sizeof(*sc));
+ rtc_sc = sc;
+ dev->si_drv1 = sc; /* Link together */
+ sc->dev = dev;
+
+ DLog(Lexit, "new %p,%p", dev, sc);
+ return sc;
+}
+
+static int
+rtc_detach(struct rtc_softc *sc)
+{
+ int error=0;
+
+ if (sc == NULL) {
+ return error;
+ }
+ if (sc->var.flags.opened) {
+ return EBUSY;
+ }
+ destroy_dev(sc->dev);
+ FREE(sc, M_DEVBUF);
+ return error;
+}
+
+/* -=-=-=-=-=-=-=-=-= character device stuff -=-=-=-=-=-=-=-=-= */
+
+int
+rtc_open(dev_t dev, int oflag, int otyp, struct proc *p)
+{
+ struct rtc_softc *sc;
+
+ sc = rtc_attach(dev);
+
+ if (sc==NULL)
+ return (EAGAIN);
+
+ if (sc->var.flags.opened)
+ return (EBUSY);
+
+ bzero(&sc->var, sizeof(sc->var));
+
+ sc->var.flags.opened = 1;
+
+ return 0;
+}
+
+int
+rtc_close(dev_t dev, int fflag, int otyp, struct proc *p)
+{
+ struct rtc_softc *sc = (struct rtc_softc *) dev->si_drv1;
+
+ sc->var.flags.opened = 0;
+ return 0;
+}
+
+int
+rtc_ioctl(dev_t dev, u_long cmd, caddr_t arg, int mode, struct proc *p)
+{
+ struct rtc_softc *sc = (struct rtc_softc *) dev->si_drv1;
+ int error=0;
+
+ DLog(Lenter, "cmd 0x%04lx", cmd);
+ switch (cmd) {
+ case RTCIO_IRQP_SET:
+ sc->var.freq = *(int *)arg;
+ DLog(Linfo, "Set RTC freq %d", sc->var.freq);
+ break;
+ case RTCIO_PIE_ON:
+ sc->var.flags.enabled = 1;
+ DLog(Linfo, "Enable interrupts");
+ break;
+ default:
+ DLog(Lfail, "Unknown IOCTL 0x%04lx", cmd);
+ error = EINVAL;
+ break;
+ }
+ DLog(Lenter, "result %d", error);
+ return (error);
+}
+
+int
+rtc_poll(dev_t dev, int events, struct proc *p)
+{
+ struct rtc_softc *sc = (struct rtc_softc *) dev->si_drv1;
+ int revents = 0;
+ int delay;
+
+ if (!sc->var.flags.enabled)
+ return 0;
+
+ delay = 1000000/sc->var.freq;
+
+ if (events) {
+ DLog(Linfo, "Delay for %d usec", delay);
+ DELAY(delay);
+ revents = events;
+ }
+ return revents;
+}
+
+/* -=-=-=-=-=-=-=-=-= module load/unload stuff -=-=-=-=-=-=-=-=-= */
+static int
+init_module(void)
+{
+int error;
+
+ error = cdevsw_add(&rtc_cdevsw);
+ if (error)
+ return error;
+
+ return error;
+}
+
+
+
+static int
+cleanup_module(void)
+{
+ int error;
+ struct rtc_softc *sc;
+
+ sc = rtc_sc;
+ if ( (error=rtc_detach(sc)) !=0) {
+ DLog(Lfail, "%p busy", sc);
+ return error;
+ }
+ error = cdevsw_remove(&rtc_cdevsw);
+ DLog(Linfo, "return %d", error);
+ return error;
+}
+
+static int
+rtc_modeevent(module_t mod, int cmd, void *arg)
+{
+ int error = 0;
+
+ switch (cmd) {
+ case MOD_LOAD:
+ error = init_module();
+ break;
+
+ case MOD_UNLOAD:
+ /* fall through */
+ case MOD_SHUTDOWN:
+ error = cleanup_module();
+ break;
+
+ default: /* we only understand load/unload */
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+