patch-1.3.57 linux/drivers/char/wdt.c
Next file: linux/drivers/net/arcnet.c
Previous file: linux/drivers/char/wd501p.h
Back to the patch index
Back to the overall index
- Lines: 272
- Date:
Tue Jan 9 11:29:28 1996
- Orig file:
v1.3.56/linux/drivers/char/wdt.c
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file v1.3.56/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
@@ -0,0 +1,271 @@
+/*
+ * Industrial Computer Source WDT500/501 driver for Linux 1.3.x
+ *
+ * (c) Copyright 1995 CymruNET Ltd
+ * Innovation Centre
+ * Singleton Park
+ * Swansea
+ * Wales
+ * UK
+ * SA2 8PP
+ *
+ * http://www.cymru.net
+ *
+ * This driver is provided under the GNU public license, incorporated
+ * herein by reference. The driver is provided without warranty or
+ * support.
+ *
+ * Release 0.04.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mouse.h>
+#include "wd501p.h"
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+static int wdt_is_open=0;
+
+/*
+ * You must set these - there is no sane way to probe for this board.
+ */
+
+int io=0x240;
+int irq=14;
+
+#define WD_TIMO (100*60) /* 1 minute */
+
+/*
+ * Programming suppoort
+ */
+
+static void wdt_ctr_mode(int ctr, int mode)
+{
+ ctr<<=6;
+ ctr|=0x30;
+ ctr|=(mode<<1);
+ outb_p(ctr, WDT_CR);
+}
+
+static void wdt_ctr_load(int ctr, int val)
+{
+ outb_p(val&0xFF, WDT_COUNT0+ctr);
+ outb_p(val>>8, WDT_COUNT0+ctr);
+}
+
+/*
+ * Kernel methods.
+ */
+
+static void wdt_interrupt(int irq, struct pt_regs *regs)
+{
+ /*
+ * Read the status register see what is up and
+ * then printk it.
+ */
+
+ unsigned char status=inb_p(WDT_SR);
+
+ status|=FEATUREMAP1;
+ status&=~FEATUREMAP2;
+
+ printk(KERN_CRIT "WDT status %d\n", status);
+
+ if(!(status&WDC_SR_TGOOD))
+ printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
+ if(!(status&WDC_SR_PSUOVER))
+ printk(KERN_CRIT "PSU over voltage.\n");
+ if(!(status&WDC_SR_PSUUNDR))
+ printk(KERN_CRIT "PSU under voltage.\n");
+ if(!(status&WDC_SR_FANGOOD))
+ printk(KERN_CRIT "Possible fan fault.\n");
+ if(!(status&WDC_SR_WCCR))
+#ifdef SOFTWARE_REBOOT
+#ifdef ONLY_TESTING
+ printk(KERN_CRIT "Would Reboot.\n");
+#else
+ printk(KERN_CRIT "Initiating system reboot.\n");
+ hard_reset_now();
+#endif
+#else
+ printk(KERN_CRIT "Reset in 5ms.\n");
+#endif
+}
+
+
+static int wdt_lseek(struct inode *inode, struct file *file, off_t offset,
+ int origin)
+{
+ return -ESPIPE;
+}
+
+static int wdt_write(struct inode *inode, struct file *file, char *buf, int count)
+{
+ /* Write a watchdog value */
+ inb_p(WDT_DC);
+ wdt_ctr_mode(1,2);
+ wdt_ctr_load(1,WD_TIMO); /* Timeout */
+ outb_p(0, WDT_DC);
+ return count;
+}
+
+/*
+ * Read reports the temperature in farenheit
+ */
+
+static int wdt_read(struct inode *inode, struct file *file, char *buf, int count)
+{
+ unsigned short c=inb_p(WDT_RT);
+ unsigned char cp;
+ int err;
+
+ switch(MINOR(inode->i_rdev))
+ {
+ case TEMP_MINOR:
+ err=verify_area(VERIFY_WRITE, buf, 1);
+ if(err)
+ return err;
+ c*=11;
+ c/=15;
+ cp=c;
+ memcpy_tofs(buf,&cp,1);
+ return 1;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return -EINVAL;
+}
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+ switch(MINOR(inode->i_rdev))
+ {
+ case WATCHDOG_MINOR:
+ if(wdt_is_open)
+ return -EBUSY;
+ MOD_INC_USE_COUNT;
+ /*
+ * Activate
+ */
+
+ wdt_is_open=1;
+ inb_p(WDT_DC); /* Disable */
+ wdt_ctr_mode(0,3);
+ wdt_ctr_mode(1,2);
+ wdt_ctr_mode(2,0);
+ wdt_ctr_load(0, 8948); /* count at 100Hz */
+ wdt_ctr_load(1,WD_TIMO); /* Timeout 120 seconds */
+ wdt_ctr_load(2,65535);
+ outb_p(0, WDT_DC); /* Enable */
+ return 0;
+ case TEMP_MINOR:
+ MOD_INC_USE_COUNT;
+ return 0;
+ default:
+ return -ENODEV;
+ }
+}
+
+static void wdt_release(struct inode *inode, struct file *file)
+{
+ if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+ {
+ inb_p(WDT_DC); /* Disable counters */
+ wdt_ctr_load(2,0); /* 0 length reset pulses now */
+ wdt_is_open=0;
+ }
+ MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+
+static struct file_operations wdt_fops = {
+ wdt_lseek,
+ wdt_read,
+ wdt_write,
+ NULL, /* No Readdir */
+ NULL, /* No Select */
+ wdt_ioctl,
+ NULL, /* No mmap */
+ wdt_open,
+ wdt_release
+};
+
+static struct mouse wdt_mouse=
+{
+ WATCHDOG_MINOR,
+ "wdt",
+ &wdt_fops
+};
+
+static struct mouse temp_mouse=
+{
+ TEMP_MINOR,
+ "temperature",
+ &wdt_fops
+};
+
+#ifdef MODULE
+
+int init_module(void)
+{
+ printk("WDT501-P module at %X(Interrupt %d)\n", io,irq);
+ if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p"))
+ {
+ printk("IRQ %d is not free.\n", irq);
+ return -EIO;
+ }
+ mouse_register(&wdt_mouse);
+#ifdef CONFIG_WDT_501
+ mouse_register(&temp_mouse);
+#endif
+ request_region(io, 8, "wdt501");
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ mouse_deregister(&wdt_mouse);
+#ifdef CONFIG_WDT_501
+ mouse_deregister(&temp_mouse);
+#endif
+ release_region(io,8);
+ free_irq(irq);
+}
+
+#else
+
+int wdt_init(void)
+{
+ printk("WDT500/501-P driver at %X(Interrupt %d)\n", io,irq);
+ if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p"))
+ {
+ printk("IRQ %d is not free.\n", irq);
+ return -EIO;
+ }
+ mouse_register(&wdt_mouse);
+ mouse_register(&temp_mouse);
+ request_region(io, 8, "wdt501");
+ return 0;
+}
+
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this