|
||||||||||
On Wed, 25 Jun 2003, Mike Tancsa wrote: > Thanks for the reply! Is it possible to post the diffs ? phk at freebsd dot org > said he would commit the diffs to RELENG_4 if someone could provide a patch > set. Attached to this message: - diff for sys/i386/i386/elan_mmcr.c from FreeBSD 4.8 - watchdog.h that goes in sys/sys/watchdog.h I have tested this under FreeBSD 4.8-RELEASE using watchdog-test from http://wleiden.webweaving.org:8080/svn/node-config/soekris/watchdog/watchdog-test.c and the watchdog reset the box properly in the last test. HTH, Manuel | ||||||||||
/*-
* Copyright (c) 2003 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.
* 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.
*
* $FreeBSD: /repoman/r/ncvs/src/sys/sys/watchdog.h,v 1.1 2003/02/27 21:07:36 phk Exp $
*/
#ifndef _SYS_WATCHDOG_H
#define _SYS__WATCHDOG_H
#include <sys/ioccom.h>
#define WDIOCPATPAT _IOW('W', 42, u_int)
#define WD_ACTIVE 0x8000000
/*
* Watchdog reset, timeout set to value in WD_INTERVAL field.
* The kernel will arm the watchdog and unless the userland
* program calls WDIOCPATPAT again before the timer expires
* the system will reinitialize.
*/
#define WD_PASSIVE 0x0400000
/*
* Set the watchdog in passive mode.
* The kernel will chose an appropriate timeout duration and
* periodically reset the timer provided everything looks all
* right to the kernel.
*/
#define WD_INTERVAL 0x00000ff
/*
* Mask for duration bits.
* The watchdog will have a nominal patience of 2^N * nanoseconds.
* Example: N == 30 gives a patience of 2^30 nanoseconds ~= 1 second.
* 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
#define WD_TO_125MS 27
#define WD_TO_250MS 28
#define WD_TO_500MS 29
#define WD_TO_1SEC 30
#define WD_TO_2SEC 31
#define WD_TO_4SEC 32
#define WD_TO_8SEC 33
#define WD_TO_16SEC 34
#define WD_TO_32SEC 35
#endif /* _SYS_WATCHDOG_H */ | ||||||||||
--- sys/i386/i386/elan-mmcr.c.orig Mon Jun 9 13:11:58 2003
+++ sys/i386/i386/elan-mmcr.c Mon Jun 9 13:14:12 2003
@@ -25,6 +25,7 @@
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/time.h>
+#include <sys/watchdog.h>
#include <machine/md_var.h>
@@ -126,8 +127,71 @@
}
static int
+elan_watchdog(u_int spec)
+{
+ 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 = imax(u - 5, 24);
+ v = 2 << (u - 24);
+ v |= 0xc000;
+
+ /*
+ * There is a bug in some silicon which prevents us from
+ * writing to the WDTMRCTL register if the GP echo mode is
+ * enabled. GP echo mode on the other hand is desirable
+ * for other reasons. Save and restore the GP echo mode
+ * around our hardware tom-foolery.
+ */
+ u = elan_mmcr[0xc00 / 2];
+ elan_mmcr[0xc00 / 2] = 0;
+ if (v != cur) {
+ /* Clear the ENB bit */
+ elan_mmcr[0xcb0 / 2] = 0x3333;
+ elan_mmcr[0xcb0 / 2] = 0xcccc;
+ elan_mmcr[0xcb0 / 2] = 0;
+
+ /* Set new value */
+ elan_mmcr[0xcb0 / 2] = 0x3333;
+ elan_mmcr[0xcb0 / 2] = 0xcccc;
+ elan_mmcr[0xcb0 / 2] = v;
+ cur = v;
+ } else {
+ /* Just reset timer */
+ elan_mmcr[0xcb0 / 2] = 0xaaaa;
+ elan_mmcr[0xcb0 / 2] = 0x5555;
+ }
+ elan_mmcr[0xc00 / 2] = u;
+ return (0);
+ case WD_PASSIVE:
+ return (EOPNOTSUPP);
+ case 0:
+ u = elan_mmcr[0xc00 / 2];
+ elan_mmcr[0xc00 / 2] = 0;
+ elan_mmcr[0xcb0 / 2] = 0x3333;
+ elan_mmcr[0xcb0 / 2] = 0xcccc;
+ elan_mmcr[0xcb0 / 2] = 0x4080;
+ elan_mmcr[0xc00 / 2] = u;
+ cur = 0;
+ return (0);
+ default:
+ return (EINVAL);
+ }
+}
+
+static int
elan_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
{
+ if (cmd == WDIOCPATPAT)
+ return elan_watchdog(*((u_int*)arg));
+
return(ENOENT);
} |