From 13685a15034ea64cf0c11eaddc050f77a7e3d0f2 Mon Sep 17 00:00:00 2001 From: knu Date: Mon, 3 Apr 2000 15:28:30 +0000 Subject: 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. --- emulators/rtc/Makefile | 59 ++++++++ emulators/rtc/files/Makefile | 50 +++++++ emulators/rtc/files/rtc.c | 288 ++++++++++++++++++++++++++++++++++++++++ emulators/rtc/files/rtc.h | 9 ++ emulators/rtc/files/rtc.sh | 8 ++ emulators/rtc/files/rtc_linux.c | 70 ++++++++++ emulators/rtc/files/test.c | 56 ++++++++ emulators/rtc/pkg-comment | 1 + emulators/rtc/pkg-descr | 4 + emulators/rtc/pkg-plist | 8 ++ 10 files changed, 553 insertions(+) create mode 100644 emulators/rtc/Makefile create mode 100644 emulators/rtc/files/Makefile create mode 100644 emulators/rtc/files/rtc.c create mode 100644 emulators/rtc/files/rtc.h create mode 100644 emulators/rtc/files/rtc.sh create mode 100644 emulators/rtc/files/rtc_linux.c create mode 100644 emulators/rtc/files/test.c create mode 100644 emulators/rtc/pkg-comment create mode 100644 emulators/rtc/pkg-descr create mode 100644 emulators/rtc/pkg-plist (limited to 'emulators') diff --git a/emulators/rtc/Makefile b/emulators/rtc/Makefile new file mode 100644 index 0000000..c9ad042 --- /dev/null +++ b/emulators/rtc/Makefile @@ -0,0 +1,59 @@ +# New ports collection makefile for: rtc +# Version required: 2000.03.28 +# Date created: 28 March 2000 +# Whom: Akinori MUSHA aka knu +# +# $FreeBSD$ +# + +DISTNAME= rtc-2000.03.28 +CATEGORIES= emulators linux +MASTER_SITES= # none +DISTFILES= # none + +MAINTAINER= freebsd-emulation@FreeBSD.org + +WRKSRC= ${WRKDIR}/files + +LINUX_DIR= /compat/linux +KMODDIR= ${PREFIX}/modules + +CDEV_MAJOR= 202 +DEVFILE= /dev/rtc + +STARTUP= rtc.sh +MAKE_ARGS= KMODDIR="${KMODDIR}" CDEV_MAJOR="${CDEV_MAJOR}" +PLIST_SUB= DEVFILE="${DEVFILE}" CDEV_MAJOR="${CDEV_MAJOR}" RTC_H_DIR="${RTC_H_DIR}" + +.include + +.if ${OSVERSION} < 400013 +BROKEN= "Systems prior to 400013 is out of support" +.endif + +.if !exists(/sys/Makefile) +BROKEN= "Kernel source files required" +.endif + +do-fetch: + @${ECHO} "I don't fetch anything..." + +do-extract: + @${MKDIR} ${WRKSRC} + @${SED} -e 's,@@PREFIX@@,${PREFIX},' \ + ${FILESDIR}/${STARTUP} > ${WRKDIR}/${STARTUP} + @cd ${FILESDIR} && ${CP} Makefile *.[ch] ${WRKSRC}/ + +pre-install: + ${MKDIR} ${KMODDIR} + +post-install: + ${RM} -f ${DEVFILE} + mknod ${DEVFILE} c ${CDEV_MAJOR} 0 + ${INSTALL_DATA} ${WRKSRC}/rtc.h ${PREFIX}/include/ + ${MKDIR} ${PREFIX}/share/examples/rtc + ${INSTALL_DATA} ${WRKSRC}/test.c ${PREFIX}/share/examples/rtc/ + @${ECHO} "Installing ${PREFIX}/etc/rc.d/${STARTUP} startup file."; + ${INSTALL_SCRIPT} ${WRKDIR}/${STARTUP} ${PREFIX}/etc/rc.d/ + +.include diff --git a/emulators/rtc/files/Makefile b/emulators/rtc/files/Makefile new file mode 100644 index 0000000..4176d4f --- /dev/null +++ b/emulators/rtc/files/Makefile @@ -0,0 +1,50 @@ +# Copyright 2000 Vladimir N.Silyaev +# All rights reserved. +# +# 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. +# + +SYS?= /sys +NOMAN= YES +KMOD= rtc +CDEV_MAJOR?= 202 +DEVNAME= ${KMOD} +SRCS= rtc.c rtc_linux.c vnode_if.h + + +INCLUDE= -I${.CURDIR} -I${SYS} + +CFLAGS+= ${INCLUDE} -DCDEV_MAJOR_=${CDEV_MAJOR} + +all: vnode_if.h + +@: + @${ECHO} ${.TARGET} "->" ${SYS} + @ln -s ${SYS} ${.TARGET} + +#afterinstall: device + +device: + rm -f /dev/${DEVNAME} + mknod /dev/${DEVNAME} c ${CDEV_MAJOR} 0 + +.include diff --git a/emulators/rtc/files/rtc.c b/emulators/rtc/files/rtc.c new file mode 100644 index 0000000..9623b2f --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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); +} + + diff --git a/emulators/rtc/files/rtc.h b/emulators/rtc/files/rtc.h new file mode 100644 index 0000000..d3a151e --- /dev/null +++ b/emulators/rtc/files/rtc.h @@ -0,0 +1,9 @@ +#ifndef RTC_H +#define RTC_H + + +#define RTCIO_PIE_ON _IO('p', 0x05) +#define RTCIO_IRQP_SET _IO('p', 0x0c) + +#endif /* RTC_H */ + diff --git a/emulators/rtc/files/rtc.sh b/emulators/rtc/files/rtc.sh new file mode 100644 index 0000000..a39569c --- /dev/null +++ b/emulators/rtc/files/rtc.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +kmod=@@PREFIX@@/modules/rtc.ko + +if [ -x $kmod ]; then + echo -n ' rtc' + kldload $kmod +fi diff --git a/emulators/rtc/files/rtc_linux.c b/emulators/rtc/files/rtc_linux.c new file mode 100644 index 0000000..2eb04a4 --- /dev/null +++ b/emulators/rtc/files/rtc_linux.c @@ -0,0 +1,70 @@ +/* + * 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_linux.c,v 1.5 2000/01/23 22:29:50 vsilyaev Exp $ + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "rtc.h" + +#define DEBUG 0 +#if DEBUG +#define DEB(x) x +#else /* !DEBUG */ +#define DEB(x) +#endif /* DEBUG */ + +#define LINUX_IOCTL_SET(n,low,high) \ +static linux_ioctl_function_t linux_ioctl_##n; \ +static struct linux_ioctl_handler n##_handler = {linux_ioctl_##n, low, high }; \ +SYSINIT(n##register, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &n##_handler); \ +SYSUNINIT(n##unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &n##_handler); + +#define LINUX_RTC_PIE_ON 0x7005 +#define LINUX_RTC_IRQP_SET 0x700C + +LINUX_IOCTL_SET(rtc, 0x7000, 0x70ff); + +static int +linux_ioctl_rtc(struct proc *p, struct linux_ioctl_args *args) +{ + switch (args->cmd & 0xffff) { + case LINUX_RTC_PIE_ON: + args->cmd=RTCIO_PIE_ON; + return ioctl(p, (struct ioctl_args*)args); + case LINUX_RTC_IRQP_SET: + args->cmd=RTCIO_IRQP_SET; + return ioctl(p, (struct ioctl_args*)args); + } + return (ENOIOCTL); +} diff --git a/emulators/rtc/files/test.c b/emulators/rtc/files/test.c new file mode 100644 index 0000000..664441c --- /dev/null +++ b/emulators/rtc/files/test.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "rtc.h" + + +int main(void) +{ + int rtc; + fd_set rset; + int i,rc; + int ntests=100; + struct timeval tv; + struct timeval begin,end,delta; + + + rtc = open("/dev/rtc", O_RDONLY); + if (rtc<0) { + perror("/dec/rtc"); + return 1; + } + + rc = ioctl(rtc, RTCIO_IRQP_SET, 512); + if (rc<0) { + perror("/dev/rtc"); + return 1; + } + + rc = ioctl(rtc, RTCIO_PIE_ON, NULL); + if (rc<0) { + perror("/dev/rtc"); + return 1; + } + + gettimeofday(&begin, NULL); + for (i=0; i