summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralex <alex@openbsd.org>1999-04-28 23:20:51 +0000
committeralex <alex@openbsd.org>1999-04-28 23:20:51 +0000
commitd1a9dd451f366c45425d6fd5127995a6480a91c7 (patch)
tree85b29f144f18eaad992784af2bd1079c1c2243d2
parentplease use Ar macros when describing option flags, too (diff)
downloadwireguard-openbsd-d1a9dd451f366c45425d6fd5127995a6480a91c7.tar.xz
wireguard-openbsd-d1a9dd451f366c45425d6fd5127995a6480a91c7.zip
Added wdt driver for the Industrial Computer Source PCI-WDT50x watchdog
timers.
-rw-r--r--etc/etc.i386/MAKEDEV15
-rw-r--r--share/man/man4/man4.i386/Makefile4
-rw-r--r--share/man/man4/man4.i386/wdt.4114
-rw-r--r--share/man/man8/man8.i386/MAKEDEV.84
-rw-r--r--sys/arch/i386/conf/GENERIC4
-rw-r--r--sys/arch/i386/i386/conf.c11
-rw-r--r--sys/dev/pci/files.pci7
-rw-r--r--sys/dev/pci/pcidevs6
-rw-r--r--sys/dev/pci/pcidevs.h4
-rw-r--r--sys/dev/pci/pcidevs_data.h12
-rw-r--r--sys/dev/pci/wdt.c607
-rw-r--r--sys/dev/pci/wdt50x.h49
12 files changed, 827 insertions, 10 deletions
diff --git a/etc/etc.i386/MAKEDEV b/etc/etc.i386/MAKEDEV
index 87dffc55d5a..cb8c2922e35 100644
--- a/etc/etc.i386/MAKEDEV
+++ b/etc/etc.i386/MAKEDEV
@@ -1,6 +1,6 @@
#!/bin/sh -
#
-# $OpenBSD: MAKEDEV,v 1.69 1999/01/11 15:14:44 niklas Exp $
+# $OpenBSD: MAKEDEV,v 1.70 1999/04/28 23:20:51 alex Exp $
# $NetBSD: MAKEDEV,v 1.40 1996/03/31 00:50:47 perry Exp $
#
# Copyright (c) 1990 The Regents of the University of California.
@@ -86,6 +86,7 @@
# xfs* XFS filesystem devices
# bktr0 video capturing
# tuner0 tuner device
+# wdt0 watchdog timer
#
PATH=/sbin:/usr/sbin:/bin:/usr/bin
@@ -118,7 +119,7 @@ all)
sh MAKEDEV ipl tun0 tun1 tun2
sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9
sh MAKEDEV speaker lkm mms0 lms0 pms0 audio joy0 joy1 apm local
- sh MAKEDEV random uk0 uk1 ss0 ss1 pctr bktr0 tuner0
+ sh MAKEDEV random uk0 uk1 ss0 ss1 pctr bktr0 tuner0 wdt0
sh MAKEDEV fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H
sh MAKEDEV fd1 fd1B fd1C fd1D fd1E fd1F fd1G fd1H
sh MAKEDEV xfs0 music
@@ -267,7 +268,7 @@ fd*)
umask 77
;;
-ccd*|sd*|wd*|raid*)
+ccd*|sd*|wd[0-9]*|raid*)
umask 2 ; unit=`expr $i : '.*d\(.*\)'`
case $i in
ccd*) name=ccd; blk=16; chr=18;;
@@ -685,6 +686,14 @@ tuner*)
chmod 0644 tuner$unit
;;
+wdt*)
+ unit=`expr $i : 'wdt\(.*\)'`
+ rm -f wdt$unit
+ mknod wdt$unit c 55 $unit
+ chown root.operator wdt$unit
+ chmod 0440 wdt$unit
+ ;;
+
local)
umask 0
test -s MAKEDEV.local && sh MAKEDEV.local
diff --git a/share/man/man4/man4.i386/Makefile b/share/man/man4/man4.i386/Makefile
index aab9ff7517a..eb874b92d9e 100644
--- a/share/man/man4/man4.i386/Makefile
+++ b/share/man/man4/man4.i386/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.25 1998/11/19 09:33:12 deraadt Exp $
+# $OpenBSD: Makefile,v 1.26 1999/04/28 23:20:54 alex Exp $
# from: @(#)Makefile 5.1 (Berkeley) 2/12/91
# Id: Makefile,v 1.4 1995/12/14 05:41:38 deraadt Exp $
MAN= intro.4 aha.4 ahb.4 aic.4 apm.4 aria.4 ast.4 autoconf.4 bktr.4 boca.4
MAN+= bt.4 com.4 cy.4 fdc.4 iy.4 lms.4 lpt.4 mcd.4 mem.4 mms.4
-MAN+= npx.4 pctr.4 pms.4 rtfps.4 scd.4 sea.4 speaker.4 uha.4 wdc.4
+MAN+= npx.4 pctr.4 pms.4 rtfps.4 scd.4 sea.4 speaker.4 uha.4 wdc.4 wdt.4
MAN+= eg.4 el.4 ie.4 joy.4 le.4 wt.4
MAN+= gus.4 pss.4 sb.4 wss.4
MAN+= xf86.4
diff --git a/share/man/man4/man4.i386/wdt.4 b/share/man/man4/man4.i386/wdt.4
new file mode 100644
index 00000000000..f6dadfd2e04
--- /dev/null
+++ b/share/man/man4/man4.i386/wdt.4
@@ -0,0 +1,114 @@
+.\" Copyright (c) 1998,1999 Alex Nash
+.\" 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.
+.\"
+.\" $OpenBSD: wdt.4,v 1.1 1999/04/28 23:20:56 alex Exp $
+.\"
+.Dd April 25, 1999
+.Dt WDT 4 i386
+.Os
+.Sh NAME
+.Nm wdt
+.Nd ICS PCI-WDT500/501 watchdog timer device driver
+.Sh SYNOPSIS
+.Cd option WDT_DISABLE_BUZZER
+.Cd wdt0 at pci? dev ? function ?
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Industrial Computer Source
+PCI-WDT500 and PCI-WDT501 boards.
+.Pp
+For PCI-WDT500 boards, basic watchdog timer functionality is supported.
+For PCI-WDT501 boards, additional access to the onboard buzzer,
+isolated inputs, temperature, and power supply monitors is provided.
+To disable the onboard buzzer on PCI-WDT501 boards, add the
+.Em WDT_DISABLE_BUZZER
+option to your kernel configuration.
+.Pp
+By default the watchdog timer is set to 30 seconds and is refreshed
+by the kernel's timeout processing. If the kernel crashes, the watchdog
+timer is not reset and the system will reboot (assuming a proper connection
+is made between the WDT50x and motherboard). Alternatively, the watchdog
+can be reinitialized via a userland process which insures that process
+scheduling, not just kernel timeout processing, is still taking place.
+See the
+.Dv WIOCSCHED
+.Xr ioctl 2
+below for more information.
+.Sh INTERFACE
+The
+.Nm
+driver is controlled via
+.Xr ioctl 2
+calls to
+.Pa /dev/wdt0 .
+The following commands are supported:
+.Bl -tag -width WIOCGETSTATE
+.It Dv WIOCGETSTATE
+Returns the current temperature and board status into the
+wdt_state structure pointer passed to
+.Xr ioctl 2 .
+See
+.Aq Pa dev/pci/wdt50x.h
+for the definition of the wdt_state structure and state bits.
+.It Dv WIOCSCHED
+Places the process into an infinite loop (interrupted only via a signal)
+to guarantee process scheduling. The driver utilizes the process'
+context to reinitialize the watchdog timeout. Should process
+scheduling fail, the timeout will not be reinitialized and the system
+will be rebooted. Note that it is possible to force a reboot by sending
+a SIGSTOP signal to a process in
+.Dv WIOCSCHED
+and waiting for the watchdog timer to expire.
+Since
+.Dv WIOCSCHED
+can have such dramatic consequences, it may only be issued by superuser
+processes regardless of the permissions on
+.Pa /dev/wdt0 .
+.El
+.Sh FILES
+.Bl -tag -width /usr/include/dev/pci/wdt50x.h -compact
+.It Pa /dev/wdt0
+Watchdog control device.
+.It Pa /usr/include/dev/pci/wdt50x.h
+Structure and ioctl definitions to interface with the
+.Nm
+driver.
+.El
+.Sh SEE ALSO
+.Xr ioctl 2
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 2.6 .
+.Sh BUGS
+The ioctl interface isn't generic.
+.Pp
+It's unwise to combine
+.Nm
+with
+.Xr ddb 4
+since the latter may prevent the former from resetting the
+watchdog timeout before it expires.
diff --git a/share/man/man8/man8.i386/MAKEDEV.8 b/share/man/man8/man8.i386/MAKEDEV.8
index c510093d3c0..79548ac7f91 100644
--- a/share/man/man8/man8.i386/MAKEDEV.8
+++ b/share/man/man8/man8.i386/MAKEDEV.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.6 1999/04/26 21:05:17 alex Exp $
+.\" $OpenBSD: MAKEDEV.8,v 1.7 1999/04/28 23:20:57 alex Exp $
.\"
.\" Copyright (c) 1997, Jason Downs. All rights reserved.
.\"
@@ -174,6 +174,8 @@ devices
SCSI scanners
.It Ar bktr#
Brooktree 848 driver
+.It Ar wdt#
+watchdog timer
.El
.Pp
.Sh FILES
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC
index 35444bf47b6..ec5ce965681 100644
--- a/sys/arch/i386/conf/GENERIC
+++ b/sys/arch/i386/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.107 1999/03/31 18:33:26 deraadt Exp $
+# $OpenBSD: GENERIC,v 1.108 1999/04/28 23:20:58 alex Exp $
# $NetBSD: GENERIC,v 1.48 1996/05/20 18:17:23 mrg Exp $
#
# GENERIC -- everything that's currently supported
@@ -251,6 +251,8 @@ bktr0 at pci? dev ? function ?
#joy0 at isa? port 0x201
joy* at isapnp?
+#wdt0 at pci? dev ? function ? # Ind Computer Source PCI-WDT50x driver
+
pseudo-device pctr 1
pseudo-device sequencer 1
#pseudo-device raid 4 # RAIDframe disk driver
diff --git a/sys/arch/i386/i386/conf.c b/sys/arch/i386/i386/conf.c
index 3da43ee76a4..f1fd62fb6ed 100644
--- a/sys/arch/i386/i386/conf.c
+++ b/sys/arch/i386/i386/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.51 1999/01/11 14:28:57 niklas Exp $ */
+/* $OpenBSD: conf.c,v 1.52 1999/04/28 23:20:59 alex Exp $ */
/* $NetBSD: conf.c,v 1.75 1996/05/03 19:40:20 christos Exp $ */
/*
@@ -131,6 +131,12 @@ int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
(dev_type_stop((*))) enodev, 0, seltrue, \
dev_init(c,n,mmap) }
+/* open, close, read, ioctl */
+#define cdev_wdt_init(c, n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, seltrue, (dev_type_mmap((*))) enodev }
+
#define mmread mmrw
#define mmwrite mmrw
@@ -187,6 +193,8 @@ cdev_decl(xfs_dev);
#endif
#include "bktr.h"
cdev_decl(bktr);
+#include "wdt.h"
+cdev_decl(wdt);
#include "ksyms.h"
cdev_decl(ksyms);
@@ -278,6 +286,7 @@ struct cdevsw cdevsw[] =
cdev_midi_init(NMIDI,midi), /* 52: MIDI I/O */
cdev_midi_init(NSEQUENCER,sequencer), /* 53: sequencer I/O */
cdev_disk_init(NRAID,raid), /* 54: RAIDframe disk driver */
+ cdev_wdt_init(NWDT,wdt), /* 55: WDT50x watchdog timer */
};
int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index 3ad868d459b..ab0064d5db6 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pci,v 1.37 1999/03/11 18:20:13 jason Exp $
+# $OpenBSD: files.pci,v 1.38 1999/04/28 23:20:59 alex Exp $
# $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $
#
# Config file and device description for machine-independent PCI code.
@@ -156,3 +156,8 @@ file dev/pci/aeon.c aeon
device wb: ether, ifnet
attach wb at pci
file dev/pci/if_wb.c wb
+
+# Industrial Computer Source WDT-50x
+device wdt: pcibus
+attach wdt at pci
+file dev/pci/wdt.c wdt needs-flag
diff --git a/sys/dev/pci/pcidevs b/sys/dev/pci/pcidevs
index a1de6f74504..5f174be0385 100644
--- a/sys/dev/pci/pcidevs
+++ b/sys/dev/pci/pcidevs
@@ -1,4 +1,4 @@
-$OpenBSD: pcidevs,v 1.131 1999/03/23 08:17:16 deraadt Exp $
+$OpenBSD: pcidevs,v 1.132 1999/04/28 23:21:00 alex Exp $
/* $NetBSD: pcidevs,v 1.30 1997/06/24 06:20:24 thorpej Exp $ */
@@ -509,6 +509,7 @@ vendor TEKRAM2 0x1de1 Tekram Technology (2nd ID)
vendor 3DLABS 0x3d3d 3D Labs
vendor AVANCE2 0x4005 Avance Logic (2nd ID)
vendor ADDTRON 0x4033 Addtron
+vendor INDCOMPSRC 0x494f Industrial Computer Source
vendor NETVIN 0x4a14 NetVin
vendor BUSLOGIC2 0x4b10 Buslogic (2nd ID)
vendor S3 0x5333 S3
@@ -880,6 +881,9 @@ product IBM 0x0036 0x0036 Miami/PCI
/* IDT products */
product IDT 77201 0x0001 77201/77211 ATM (NICStAR)
+/* Industrial Computer Source */
+product INDCOMPSRC WDT50x 0x22c0 WDT 50x Watchdog Timer
+
/* Integrated Micro Solutions products */
product IMS 8849 0x8849 8849
diff --git a/sys/dev/pci/pcidevs.h b/sys/dev/pci/pcidevs.h
index 925671caed7..662c385e65a 100644
--- a/sys/dev/pci/pcidevs.h
+++ b/sys/dev/pci/pcidevs.h
@@ -514,6 +514,7 @@
#define PCI_VENDOR_3DLABS 0x3d3d /* 3D Labs */
#define PCI_VENDOR_AVANCE2 0x4005 /* Avance Logic (2nd ID) */
#define PCI_VENDOR_ADDTRON 0x4033 /* Addtron */
+#define PCI_VENDOR_INDCOMPSRC 0x494f /* Industrial Computer Source */
#define PCI_VENDOR_NETVIN 0x4a14 /* NetVin */
#define PCI_VENDOR_BUSLOGIC2 0x4b10 /* Buslogic (2nd ID) */
#define PCI_VENDOR_S3 0x5333 /* S3 */
@@ -885,6 +886,9 @@
/* IDT products */
#define PCI_PRODUCT_IDT_77201 0x0001 /* 77201/77211 ATM (NICStAR) */
+/* Industrial Computer Source products */
+#define PCI_PRODUCT_INDCOMPSRC_WDT50x 0x22c0 /* WDT 50x Watchdog Timer */
+
/* Integrated Micro Solutions products */
#define PCI_PRODUCT_IMS_8849 0x8849 /* 8849 */
diff --git a/sys/dev/pci/pcidevs_data.h b/sys/dev/pci/pcidevs_data.h
index 73e8332ee87..465dde65577 100644
--- a/sys/dev/pci/pcidevs_data.h
+++ b/sys/dev/pci/pcidevs_data.h
@@ -1431,6 +1431,12 @@ struct pci_knowndev pci_knowndevs[] = {
"77201/77211 ATM (NICStAR)",
},
{
+ PCI_VENDOR_INDCOMPSRC, PCI_PRODUCT_INDCOMPSRC_WDT50x,
+ 0,
+ "Industrial Computer Source",
+ "WDT 50x Watchdog Timer",
+ },
+ {
PCI_VENDOR_IMS, PCI_PRODUCT_IMS_8849,
0,
"Integrated Micro Solutions",
@@ -5931,6 +5937,12 @@ struct pci_knowndev pci_knowndevs[] = {
NULL,
},
{
+ PCI_VENDOR_INDCOMPSRC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Industrial Computer Source",
+ NULL,
+ },
+ {
PCI_VENDOR_NETVIN, 0,
PCI_KNOWNDEV_NOPROD,
"NetVin",
diff --git a/sys/dev/pci/wdt.c b/sys/dev/pci/wdt.c
new file mode 100644
index 00000000000..941b4fceb1f
--- /dev/null
+++ b/sys/dev/pci/wdt.c
@@ -0,0 +1,607 @@
+/*-
+ * Copyright (c) 1998,1999 Alex Nash
+ * 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.
+ *
+ * $OpenBSD: wdt.c,v 1.1 1999/04/28 23:21:04 alex Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <machine/bus.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include "wdt50x.h"
+#include "wdt.h"
+
+#if NWDT > 0
+
+struct wdt_softc {
+ /* wdt_dev must be the first item in the struct */
+ struct device wdt_dev;
+
+ /* feature set: 0 = none 1 = temp, buzzer, etc. */
+ int features;
+
+ /* unit number (unlikely more than one would be present though) */
+ int unit;
+
+ /* how many processes are in WIOCSCHED */
+ unsigned procs;
+
+ /* watchdog timeout */
+ unsigned timeout_secs;
+
+ /* device access through bus space */
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+};
+
+/* externally visible functions */
+int wdtprobe __P((struct device *, void *, void *));
+void wdtattach __P((struct device *, struct device *, void *));
+int wdtopen __P((dev_t, int, int, struct proc *));
+int wdtclose __P((dev_t, int, int, struct proc *));
+int wdtioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+
+/* static functions */
+static int wdt_is501 __P((struct wdt_softc *wdt));
+static void wdt_8254_count __P((struct wdt_softc *wdt, int counter, u_int16_t v));
+static void wdt_8254_mode __P((struct wdt_softc *wdt, int counter, int mode));
+static void wdt_set_timeout __P((struct wdt_softc *wdt, unsigned seconds));
+static void wdt_timeout __P((void *arg));
+static void wdt_init_timer __P((struct wdt_softc *wdt));
+static void wdt_buzzer_off __P((struct wdt_softc *wdt));
+static int wdt_read_temperature __P((struct wdt_softc *wdt));
+static int wdt_read_status __P((struct wdt_softc *wdt));
+static void wdt_display_status __P((struct wdt_softc *wdt));
+static int wdt_get_state __P((struct wdt_softc *wdt, struct wdt_state *state));
+static void wdt_shutdown __P((void *arg));
+static int wdt_sched __P((struct wdt_softc *wdt, struct proc *p));
+static void wdt_timer_disable __P((struct wdt_softc *wdt));
+static void wdt_timer_enable __P((struct wdt_softc *wdt, unsigned seconds));
+#if WDT_DISABLE_BUZZER
+static void wdt_buzzer_disable __P((struct wdt_softc *wdt));
+#else
+static void wdt_buzzer_enable __P((struct wdt_softc *wdt));
+#endif
+
+struct cfattach wdt_ca = {
+ sizeof(struct wdt_softc), wdtprobe, wdtattach
+};
+
+struct cfdriver wdt_cd = {
+ NULL, "wdt", DV_DULL
+};
+
+/*
+ * 8254 counter mappings
+ */
+#define WDT_8254_TC_LO 0 /* low 16 bits of timeout counter */
+#define WDT_8254_TC_HI 1 /* high 16 bits of timeout counter */
+#define WDT_8254_BUZZER 2
+
+/*
+ * WDT500/501 ports
+ */
+#define WDT_8254_BASE 0
+#define WDT_8254_CTL (WDT_8254_BASE + 3)
+#define WDT_DISABLE_TIMER 7
+#define WDT_ENABLE_TIMER 7
+
+/*
+ * WDT501 specific ports
+ */
+#define WDT_STATUS_REG 4
+#define WDT_START_BUZZER 4
+#define WDT_TEMPERATURE 5
+#define WDT_STOP_BUZZER 5
+
+#define UNIT(dev) (minor(dev))
+
+int
+wdtprobe (parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
+
+ if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INDCOMPSRC ||
+ PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INDCOMPSRC_WDT50x)
+ return(0);
+
+ return(1);
+}
+
+void
+wdtattach (parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct wdt_softc *wdt = (struct wdt_softc *)self;
+ struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
+ int unit;
+ bus_size_t iosize;
+ bus_addr_t iobase;
+
+ wdt->iot = pa->pa_iot;
+
+ unit = wdt->wdt_dev.dv_unit;
+
+ /* retrieve the I/O region (BAR2) */
+ if (pci_io_find(pa->pa_pc, pa->pa_tag, 0x18, &iobase,
+ &iosize) != 0) {
+ printf("wdt%d: couldn't find PCI I/O region\n", unit);
+ return;
+ }
+
+ /* sanity check I/O size */
+ if (iosize != (bus_size_t)16) {
+ printf("wdt%d: invalid I/O region size\n", unit);
+ return;
+ }
+
+ /* map I/O region */
+ if (bus_space_map(pa->pa_iot, iobase, iosize, 0, &wdt->ioh) != 0) {
+ printf("wdt%d: couldn't map PCI I/O region\n", unit);
+ return;
+ }
+
+ /* initialize the watchdog timer structure */
+ wdt->unit = unit;
+ wdt->procs = 0;
+
+ /* check the feature set available */
+ if (wdt_is501(wdt))
+ wdt->features = 1;
+ else
+ wdt->features = 0;
+
+ /*
+ * register a callback for system shutdown
+ * (we need to disable the watchdog timer during shutdown)
+ */
+ if (shutdownhook_establish(wdt_shutdown, wdt) == NULL)
+ return;
+
+ if (wdt->features) {
+ /*
+ * turn off the buzzer, it may have been activated
+ * by a previous timeout
+ */
+ wdt_buzzer_off(wdt);
+
+#ifdef WDT_DISABLE_BUZZER
+ wdt_buzzer_disable(wdt);
+#else
+ wdt_buzzer_enable(wdt);
+#endif
+ }
+
+ /* initialize the timer modes and the lower 16-bit counter */
+ wdt_init_timer(wdt);
+
+ /*
+ * it appears the timeout queue isn't processed until the
+ * kernel has fully booted, so we set the first timeout
+ * far in advance, and subsequent timeouts at the normal
+ * 30 second interval
+ */
+ wdt_timer_enable(wdt, 90/*seconds*/);
+ wdt->timeout_secs = 30;
+
+ printf("\n");
+ wdt_display_status(wdt);
+}
+
+int
+wdtopen (dev_t dev, int flags, int fmt, struct proc *p)
+{
+ if (UNIT(dev) >= wdt_cd.cd_ndevs)
+ return(ENXIO);
+
+ return(0);
+}
+
+int
+wdtclose (dev_t dev, int flags, int fmt, struct proc *p)
+{
+ return(0);
+}
+
+int
+wdtioctl (dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
+{
+ struct wdt_softc *wdt = wdt_cd.cd_devs[UNIT(dev)];
+ int error;
+
+ switch (cmd) {
+ case WIOCSCHED:
+ error = wdt_sched(wdt, p);
+ break;
+
+ case WIOCGETSTATE:
+ if (wdt->features)
+ error = wdt_get_state(wdt,
+ (struct wdt_state *)arg);
+ else
+ error = ENXIO;
+ break;
+
+ default:
+ error = ENXIO;
+ break;
+ }
+
+ return(error);
+}
+
+/*
+ * wdt_is501
+ *
+ * Returns non-zero if the card is a 501 model.
+ */
+static int
+wdt_is501 (struct wdt_softc *wdt)
+{
+ /*
+ * It makes too much sense to detect the card type
+ * by the device ID, so we have to resort to testing
+ * the presence of a register to determine the type.
+ */
+ int v = bus_space_read_1(wdt->iot, wdt->ioh, WDT_TEMPERATURE);
+
+ /* XXX may not be reliable */
+ if (v == 0 || v == 0xFF)
+ return(0);
+
+ return(1);
+}
+
+/*
+ * wdt_8254_count
+ *
+ * Loads the specified counter with the 16-bit value 'v'.
+ */
+static void
+wdt_8254_count (struct wdt_softc *wdt, int counter, u_int16_t v)
+{
+ bus_space_write_1(wdt->iot, wdt->ioh,
+ WDT_8254_BASE + counter, v & 0xFF);
+ bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_BASE + counter, v >> 8);
+}
+
+/*
+ * wdt_8254_mode
+ *
+ * Sets the mode of the specified counter.
+ */
+static void
+wdt_8254_mode (struct wdt_softc *wdt, int counter, int mode)
+{
+ bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_CTL,
+ (counter << 6) | 0x30 | (mode << 1));
+}
+
+/*
+ * wdt_set_timeout
+ *
+ * Load the watchdog timer with the specified number of seconds.
+ */
+static void
+wdt_set_timeout (struct wdt_softc *wdt, unsigned seconds)
+{
+ /* 8254 has been programmed with a 2ms period */
+ u_int16_t v = (u_int16_t)seconds * 50;
+
+ /* disable the timer */
+ (void)bus_space_read_1(wdt->iot, wdt->ioh, WDT_DISABLE_TIMER);
+
+ /* load the new timeout count */
+ wdt_8254_count(wdt, WDT_8254_TC_HI, v);
+
+ /* enable the timer */
+ bus_space_write_1(wdt->iot, wdt->ioh, WDT_ENABLE_TIMER, 0);
+}
+
+/*
+ * wdt_timeout
+ *
+ * Kernel timeout handler. This function is called every
+ * wdt->timeout_secs / 2 seconds. It reloads the watchdog
+ * counters in one of two ways:
+ *
+ * - If there are one or more processes sleeping in a
+ * WIOCSCHED ioctl(), they are woken up to perform
+ * the counter reload.
+ * - If no processes are sleeping in WIOCSCHED, the
+ * counters are reloaded from here.
+ *
+ * Finally, another timeout is scheduled for wdt->timeout_secs
+ * from now.
+ */
+static void
+wdt_timeout (void *arg)
+{
+ struct wdt_softc *wdt = (struct wdt_softc *)arg;
+
+ /* reload counters from proc in WIOCSCHED ioctl()? */
+ if (wdt->procs)
+ wakeup(wdt);
+ else
+ wdt_set_timeout(wdt, wdt->timeout_secs);
+
+ /* schedule another timeout in half the countdown time */
+ timeout(wdt_timeout, arg, wdt->timeout_secs * hz / 2);
+}
+
+/*
+ * wdt_timer_disable
+ *
+ * Disables the watchdog timer and cancels the scheduled (if any)
+ * kernel timeout.
+ */
+static void
+wdt_timer_disable (struct wdt_softc *wdt)
+{
+ (void)bus_space_read_1(wdt->iot, wdt->ioh, WDT_DISABLE_TIMER);
+ untimeout(wdt_timeout, wdt);
+}
+
+/*
+ * wdt_timer_enable
+ *
+ * Enables the watchdog timer to expire in the specified number
+ * of seconds. If 'seconds' is outside the range 2-1800, it
+ * is silently clamped to be within range.
+ */
+static void
+wdt_timer_enable (struct wdt_softc *wdt, unsigned seconds)
+{
+ int s;
+
+ /* clamp range */
+ if (seconds < 2)
+ seconds = 2;
+
+ if (seconds > 1800)
+ seconds = 1800;
+
+ /* block out the timeout handler */
+ s = splclock();
+
+ wdt_timer_disable(wdt);
+ wdt->timeout_secs = seconds;
+
+ timeout(wdt_timeout, wdt, hz * seconds / 2);
+ wdt_set_timeout(wdt, seconds);
+
+ /* re-enable clock interrupts */
+ splx(s);
+}
+
+/*
+ * wdt_init_timer
+ *
+ * Configure the modes for the watchdog counters and initialize
+ * the low 16-bits of the watchdog counter to have a period of
+ * approximately 1/50th of a second.
+ */
+static void
+wdt_init_timer (struct wdt_softc *wdt)
+{
+ wdt_8254_mode(wdt, WDT_8254_TC_LO, 3);
+ wdt_8254_mode(wdt, WDT_8254_TC_HI, 2);
+ wdt_8254_count(wdt, WDT_8254_TC_LO, 41666);
+}
+
+/*******************************************************************
+ * WDT501 specific functions
+ *******************************************************************/
+
+/*
+ * wdt_buzzer_off
+ *
+ * Turns the buzzer off.
+ */
+static void
+wdt_buzzer_off (struct wdt_softc *wdt)
+{
+ bus_space_write_1(wdt->iot, wdt->ioh, WDT_STOP_BUZZER, 0);
+}
+
+#ifndef WDT_DISABLE_BUZZER
+/*
+ * wdt_buzzer_enable
+ *
+ * Enables the buzzer when the watchdog counter expires.
+ */
+static void
+wdt_buzzer_enable (struct wdt_softc *wdt)
+{
+ bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_BUZZER, 1);
+ wdt_8254_mode(wdt, WDT_8254_BUZZER, 1);
+}
+#else
+/*
+ * wdt_buzzer_disable
+ *
+ * Disables the buzzer from sounding when the watchdog counter
+ * expires.
+ */
+static void
+wdt_buzzer_disable (struct wdt_softc *wdt)
+{
+ wdt_8254_mode(wdt, WDT_8254_BUZZER, 0);
+}
+#endif
+
+/*
+ * wdt_read_temperature
+ *
+ * Returns the temperature (in Fahrenheit) from the board.
+ */
+static int
+wdt_read_temperature (struct wdt_softc *wdt)
+{
+ unsigned v = bus_space_read_1(wdt->iot, wdt->ioh, WDT_TEMPERATURE);
+
+ return((v * 11) / 15 + 7);
+}
+
+/*
+ * wdt_read_status
+ *
+ * Returns the status register bits minus the counter refresh
+ * and IRQ generated bits.
+ */
+static int
+wdt_read_status (struct wdt_softc *wdt)
+{
+ /* mask off counter refresh & IRQ generated bits */
+ return(bus_space_read_1(wdt->iot, wdt->ioh, WDT_STATUS_REG) & 0x7E);
+}
+
+/*
+ * wdt_display_status
+ *
+ * Displays the current timeout, temperature, and power supply
+ * over/undervoltages to the console.
+ */
+static void
+wdt_display_status (struct wdt_softc *wdt)
+{
+ if (wdt->features) {
+ int status = wdt_read_status(wdt);
+ int temp = wdt_read_temperature(wdt);
+
+ printf("wdt%d: WDT501 timeout %d secs, temp %d F",
+ wdt->unit, wdt->timeout_secs, temp);
+
+ /* overvoltage bit is active low */
+ if ((status & WDT_SR_PS_OVER) == 0)
+ printf(" <PS overvoltage>");
+
+ /* undervoltage bit is active low */
+ if ((status & WDT_SR_PS_UNDER) == 0)
+ printf(" <PS undervoltage>");
+ } else {
+ printf("wdt%d: WDT500 timeout %d secs",
+ wdt->unit, wdt->timeout_secs);
+ }
+
+ printf("\n");
+}
+
+/*
+ * wdt_get_state
+ *
+ * Returns the temperature and status bits.
+ */
+static int
+wdt_get_state (struct wdt_softc *wdt, struct wdt_state *state)
+{
+ state->temperature = wdt_read_temperature(wdt);
+ state->status = wdt_read_status(wdt);
+
+ return(0);
+}
+
+/*
+ * wdt_shutdown
+ *
+ * Disables the watchdog timer at system shutdown time.
+ */
+static void
+wdt_shutdown (void *arg)
+{
+ struct wdt_softc *wdt = (struct wdt_softc *)arg;
+
+ wdt_timer_disable(wdt);
+}
+
+/*
+ * wdt_sched
+ *
+ * Put the process into an infinite loop in which:
+ *
+ * - The process sleeps, waiting for a wakeup() from the timeout()
+ * handler.
+ * - When awakened, the process reloads the watchdog counter and
+ * repeats the loop.
+ *
+ * The only way the loop can be broken is if the process is interrupted
+ * via a signal.
+ *
+ * The whole point of this is to cause a watchdog timeout to be
+ * generated if processes are no longer being scheduled.
+ */
+static int
+wdt_sched (struct wdt_softc *wdt, struct proc *p)
+{
+ int error;
+ int s;
+
+ /*
+ * Regardless of the device permissions, you must be
+ * root to do this -- a process which is STOPPED
+ * while in this function can cause a reboot to occur
+ * if the counters aren't reloaded within wdt->timeout_secs
+ * seconds.
+ */
+ if ((error = suser(p->p_ucred, &p->p_acflag)))
+ return(error);
+
+ /* block out the timeout handler */
+ s = splclock();
+
+ /* indicate that we are sleeping */
+ ++wdt->procs;
+
+ /* loop until the process is signaled */
+ while (1) {
+ error = tsleep(wdt, PCATCH | PSWP, "wdtsch", 0);
+
+ wdt_set_timeout(wdt, wdt->timeout_secs);
+
+ if (error != 0)
+ break;
+ }
+
+ /* remove sleeping indication */
+ --wdt->procs;
+
+ /* re-enable timeout handler */
+ splx(s);
+
+ return(error);
+}
+
+#endif /* NWDT > 0 */
diff --git a/sys/dev/pci/wdt50x.h b/sys/dev/pci/wdt50x.h
new file mode 100644
index 00000000000..84d0ad520b3
--- /dev/null
+++ b/sys/dev/pci/wdt50x.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 1998,1999 Alex Nash
+ * 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.
+ *
+ * $OpenBSD: wdt50x.h,v 1.1 1999/04/28 23:21:05 alex Exp $
+ */
+
+#ifndef WDT_H
+#define WDT_H
+
+#include <sys/ioccom.h>
+
+struct wdt_state {
+ int temperature; /* temperature in fahrenheit */
+ int status; /* see WDT_SR_xxx flags */
+};
+
+#define WDT_SR_TEMP_GOOD 0x02 /* temperature good (active high) */
+#define WDT_SR_ISO_IN0 0x04 /* isolated input #0 */
+#define WDT_SR_ISO_IN1 0x08 /* isolated input #1 */
+#define WDT_SR_FAN 0x10 /* fan good (active low) */
+#define WDT_SR_PS_OVER 0x20 /* power overvoltage (active low) */
+#define WDT_SR_PS_UNDER 0x40 /* power undervoltage (active low) */
+
+#define WIOCSCHED _IO('w', 1)
+#define WIOCGETSTATE _IOR('r', 2, struct wdt_state)
+
+#endif /* WDT_H */