diff options
author | phk <phk@FreeBSD.org> | 2004-02-28 20:06:59 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2004-02-28 20:06:59 +0000 |
commit | 1208feeaed612f757eca2f482c464e82c6534400 (patch) | |
tree | f6fc64bd55b4b3efe406ada1c01bbd455a6d33c3 /sys | |
parent | 16b9d7e0645903e1ed28f2125d454f594ee7a9f2 (diff) | |
download | FreeBSD-src-1208feeaed612f757eca2f482c464e82c6534400.zip FreeBSD-src-1208feeaed612f757eca2f482c464e82c6534400.tar.gz |
Add a generic watchdog facility which through a single device entry
in /dev controls all available watchdog implementations.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/dev/watchdog/watchdog.c | 89 | ||||
-rw-r--r-- | sys/i386/i386/elan-mmcr.c | 141 | ||||
-rw-r--r-- | sys/sys/watchdog.h | 19 |
4 files changed, 168 insertions, 82 deletions
diff --git a/sys/conf/files b/sys/conf/files index 12576e0..78c0234 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -868,6 +868,7 @@ dev/vx/if_vx.c optional vx dev/vx/if_vx_eisa.c optional vx eisa dev/vx/if_vx_pci.c optional vx pci #dev/wlp/if_wlp.c optional wlp card +dev/watchdog/watchdog.c standard dev/wds/wd7000.c optional wds isa dev/wi/if_wi.c optional wi dev/wi/if_wi_pccard.c optional wi pccard diff --git a/sys/dev/watchdog/watchdog.c b/sys/dev/watchdog/watchdog.c new file mode 100644 index 0000000..a76e3ef --- /dev/null +++ b/sys/dev/watchdog/watchdog.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2004 Poul-Henning Kamp + * 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 + * in this position and unchanged. + * 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 AUTHORS ``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 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. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/watchdog.h> +#include <sys/bus.h> +#include <machine/bus.h> + +static dev_t wd_dev; + +static int +wd_ioctl(dev_t dev __unused, u_long cmd, caddr_t data, + int flags __unused, struct thread *td) +{ + int error; + u_int u; + + if (cmd != WDIOCPATPAT) + return (ENOIOCTL); + u = *(u_int *)data; + if (u & ~(WD_ACTIVE | WD_PASSIVE | WD_INTERVAL)) + return (EINVAL); + if ((u & (WD_ACTIVE | WD_PASSIVE)) == (WD_ACTIVE | WD_PASSIVE)) + return (EINVAL); + if ((u & WD_INTERVAL) == WD_TO_NEVER) + u = 0; + error = EOPNOTSUPP; + EVENTHANDLER_INVOKE(watchdog_list, u, &error); + return (error); +} + +static struct cdevsw wd_cdevsw = { + .d_version = D_VERSION, + .d_ioctl = wd_ioctl, + .d_name = "watchdog", +}; + +static int +watchdog_modevent(module_t mod __unused, int type, void *data __unused) +{ + switch(type) { + case MOD_LOAD: + wd_dev = make_dev(&wd_cdevsw, 0, + UID_ROOT, GID_WHEEL, 0600, _PATH_WATCHDOG); + return 0; + case MOD_UNLOAD: + destroy_dev(wd_dev); + return 0; + case MOD_SHUTDOWN: + return 0; + default: + return EOPNOTSUPP; + } +} + +DEV_MODULE(watchdog, watchdog_modevent, NULL); diff --git a/sys/i386/i386/elan-mmcr.c b/sys/i386/i386/elan-mmcr.c index 80d8759..15e1f5e 100644 --- a/sys/i386/i386/elan-mmcr.c +++ b/sys/i386/i386/elan-mmcr.c @@ -323,75 +323,14 @@ init_AMD_Elan_sc520(void) tc_init(&elan_timecounter); } -static d_ioctl_t elan_ioctl; -static d_mmap_t elan_mmap; - -static struct cdevsw elan_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_ioctl = elan_ioctl, - .d_mmap = elan_mmap, - .d_name = "elan", -}; - static void -elan_drvinit(void) -{ - - /* If no elan found, just return */ - if (mmcrptr == NULL) - return; - - printf("Elan-mmcr driver: MMCR at %p.%s\n", - mmcrptr, -#ifdef CPU_ELAN_PPS - " PPS support." -#else - "" -#endif - ); - - make_dev(&elan_cdevsw, 0, - UID_ROOT, GID_WHEEL, 0600, "elan-mmcr"); - -#ifdef CPU_SOEKRIS - /* Create the error LED on GPIO9 */ - led_cookie[9] = 0x02000c34; - led_dev[9] = led_create(gpio_led, &led_cookie[9], "error"); - - /* Disable the unavailable GPIO pins */ - strcpy(gpio_config, "-----....--..--------..---------"); -#else /* !CPU_SOEKRIS */ - /* We don't know which pins are available so enable them all */ - strcpy(gpio_config, "................................"); -#endif /* CPU_SOEKRIS */ -} - -SYSINIT(elan, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, elan_drvinit, NULL); - -static int -elan_mmap(dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot) -{ - - if (offset >= 0x1000) - return (-1); - *paddr = 0xfffef000; - return (0); -} - -static int -elan_watchdog(u_int spec) +elan_watchdog(void *foo __unused, u_int spec, int *error) { u_int u, v; static u_int cur; - if (spec & ~__WD_LEGAL) - return (EINVAL); - switch (spec & (WD_ACTIVE|WD_PASSIVE)) { - case WD_ACTIVE: - u = spec & WD_INTERVAL; - if (u > 35) - return (EINVAL); + u = spec & WD_INTERVAL; + if (spec && u <= 35) { u = imax(u - 5, 24); v = 2 << (u - 24); v |= 0xc000; @@ -422,10 +361,9 @@ elan_watchdog(u_int spec) elan_mmcr->WDTMRCTL = 0x5555; } elan_mmcr->GPECHO = u; - return (0); - case WD_PASSIVE: - return (EOPNOTSUPP); - case 0: + *error = 0; + return; + } else { u = elan_mmcr->GPECHO; elan_mmcr->GPECHO = 0; elan_mmcr->WDTMRCTL = 0x3333; @@ -434,19 +372,25 @@ elan_watchdog(u_int spec) elan_mmcr->WDTMRCTL = u; elan_mmcr->GPECHO = u; cur = 0; - return (0); - default: - return (EINVAL); + return; } - } static int +elan_mmap(dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot) +{ + + if (offset >= 0x1000) + return (-1); + *paddr = 0xfffef000; + return (0); +} +static int elan_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *tdr) { int error; - error = ENOTTY; + error = ENOIOCTL; #ifdef CPU_ELAN_PPS if (pps_a != 0) @@ -460,14 +404,55 @@ elan_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *tdr) } else { elan_timecounter.tc_poll_pps = NULL; } - if (error != ENOTTY) + if (error != ENOIOCTL) return (error); #endif - if (cmd == WDIOCPATPAT) - return elan_watchdog(*((u_int*)arg)); - - /* Other future ioctl handling here */ return(error); } +static struct cdevsw elan_cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDGIANT, + .d_ioctl = elan_ioctl, + .d_mmap = elan_mmap, + .d_name = "elan", +}; + +static void +elan_drvinit(void) +{ + + /* If no elan found, just return */ + if (mmcrptr == NULL) + return; + + printf("Elan-mmcr driver: MMCR at %p.%s\n", + mmcrptr, +#ifdef CPU_ELAN_PPS + " PPS support." +#else + "" +#endif + ); + + make_dev(&elan_cdevsw, 0, + UID_ROOT, GID_WHEEL, 0600, "elan-mmcr"); + +#ifdef CPU_SOEKRIS + /* Create the error LED on GPIO9 */ + led_cookie[9] = 0x02000c34; + led_dev[9] = led_create(gpio_led, &led_cookie[9], "error"); + + /* Disable the unavailable GPIO pins */ + strcpy(gpio_config, "-----....--..--------..---------"); +#else /* !CPU_SOEKRIS */ + /* We don't know which pins are available so enable them all */ + strcpy(gpio_config, "................................"); +#endif /* CPU_SOEKRIS */ + + EVENTHANDLER_REGISTER(watchdog_list, elan_watchdog, NULL, 0); +} + +SYSINIT(elan, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, elan_drvinit, NULL); + diff --git a/sys/sys/watchdog.h b/sys/sys/watchdog.h index 8cfac00..a67b68b 100644 --- a/sys/sys/watchdog.h +++ b/sys/sys/watchdog.h @@ -30,6 +30,12 @@ #include <sys/ioccom.h> +#ifdef I_HAVE_TOTALLY_LOST_MY_SENSE_OF_HUMOUR +#define _PATH_WATCHDOG "watchdog" +#else +#define _PATH_WATCHDOG "fido" +#endif + #define WDIOCPATPAT _IOW('W', 42, u_int) #define WD_ACTIVE 0x8000000 @@ -56,10 +62,6 @@ * NB: Expect variance in the +/- 10-20% range. */ -#ifdef _KERNEL -#define __WD_LEGAL (WD_ACTIVE | WD_PASSIVE | WD_INTERVAL) -#endif - /* Handy macros for humans not used to power of two nanoseconds */ #define WD_TO_NEVER 0 #define WD_TO_1MS 20 @@ -73,4 +75,13 @@ #define WD_TO_16SEC 34 #define WD_TO_32SEC 35 +#ifdef _KERNEL + +#include <sys/eventhandler.h> + +typedef void (*watchdog_fn)(void *, u_int, int *); + +EVENTHANDLER_DECLARE(watchdog_list, watchdog_fn); +#endif + #endif /* _SYS_WATCHDOG_H */ |