/*
- * i8xx_tco 0.06: TCO timer driver for i8xx chipsets
+ * i8xx_tco 0.07: TCO timer driver for i8xx chipsets
*
* (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
* http://www.kernelconcepts.de
*
* The TCO timer is implemented in the following I/O controller hubs:
* (See the intel documentation on http://developer.intel.com.)
- * 82801AA & 82801AB chip : document number 290655-003, 290677-004,
- * 82801BA & 82801BAM chip : document number 290687-002, 298242-005,
- * 82801CA & 82801CAM chip : document number 290716-001, 290718-001,
- * 82801DB & 82801E chip : document number 290744-001, 273599-001,
- * 82801EB & 82801ER chip : document number 252516-001
+ * 82801AA (ICH) : document number 290655-003, 290677-014,
+ * 82801AB (ICHO) : document number 290655-003, 290677-014,
+ * 82801BA (ICH2) : document number 290687-002, 298242-027,
+ * 82801BAM (ICH2-M) : document number 290687-002, 298242-027,
+ * 82801CA (ICH3-S) : document number 290733-003, 290739-013,
+ * 82801CAM (ICH3-M) : document number 290716-001, 290718-007,
+ * 82801DB (ICH4) : document number 290744-001, 290745-020,
+ * 82801DBM (ICH4-M) : document number 252337-001, 252663-005,
+ * 82801E (C-ICH) : document number 273599-001, 273645-002,
+ * 82801EB (ICH5) : document number 252516-001, 252517-003,
+ * 82801ER (ICH5R) : document number 252516-001, 252517-003,
+ * 82801FB (ICH6) : document number 301473-002, 301474-007,
+ * 82801FR (ICH6R) : document number 301473-002, 301474-007,
+ * 82801FBM (ICH6-M) : document number 301473-002, 301474-007,
+ * 82801FW (ICH6W) : document number 301473-001, 301474-007,
+ * 82801FRW (ICH6RW) : document number 301473-001, 301474-007
*
* 20000710 Nils Faerber
* Initial Version 0.01
* 20030921 Wim Van Sebroeck <wim@iguana.be>
* 0.06 change i810_margin to heartbeat, use module_param,
* added notify system support, renamed module to i8xx_tco.
+ * 20050128 Wim Van Sebroeck <wim@iguana.be>
+ * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
+ * chipsets. Also added support for the "undocumented" ICH7 chipset.
*/
/*
#include "i8xx_tco.h"
/* Module and version information */
-#define TCO_VERSION "0.06"
+#define TCO_VERSION "0.07"
#define TCO_MODULE_NAME "i8xx TCO timer"
#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
#define PFX TCO_MODULE_NAME ": "
*/
tco_timer_keepalive ();
tco_timer_start ();
- return 0;
+ return nonseekable_open(inode, file);
}
static int i8xx_tco_release (struct inode *inode, struct file *file)
return 0;
}
-static ssize_t i8xx_tco_write (struct file *file, const char *data,
+static ssize_t i8xx_tco_write (struct file *file, const char __user *data,
size_t len, loff_t * ppos)
{
- /* Can't seek (pwrite) on this device */
- if (ppos != &file->f_pos)
- return -ESPIPE;
-
/* See if we got the magic character 'V' and reload the timer */
if (len) {
if (!nowayout) {
{
int new_options, retval = -EINVAL;
int new_heartbeat;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
static struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
switch (cmd) {
case WDIOC_GETSUPPORT:
- return copy_to_user((struct watchdog_info *) arg, &ident,
+ return copy_to_user(argp, &ident,
sizeof (ident)) ? -EFAULT : 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
- return put_user (0, (int *) arg);
+ return put_user (0, p);
case WDIOC_KEEPALIVE:
tco_timer_keepalive ();
case WDIOC_SETOPTIONS:
{
- if (get_user (new_options, (int *) arg))
+ if (get_user (new_options, p))
return -EFAULT;
if (new_options & WDIOS_DISABLECARD) {
case WDIOC_SETTIMEOUT:
{
- if (get_user(new_heartbeat, (int *) arg))
+ if (get_user(new_heartbeat, p))
return -EFAULT;
if (tco_timer_set_heartbeat(new_heartbeat))
}
case WDIOC_GETTIMEOUT:
- return put_user(heartbeat, (int *)arg);
+ return put_user(heartbeat, p);
default:
return -ENOIOCTLCMD;
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl);
}
}
/* Set the TCO_EN bit in SMI_EN register */
+ if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
+ printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+ SMI_EN + 1);
+ return 0;
+ }
val1 = inb (SMI_EN + 1);
val1 &= 0xdf;
outb (val1, SMI_EN + 1);
- /* Clear out the (probably old) status */
- outb (0, TCO1_STS);
- outb (3, TCO2_STS);
+ release_region (SMI_EN + 1, 1);
return 1;
}
return 0;
goto out;
}
+ /* Clear out the (probably old) status */
+ outb (0, TCO1_STS);
+ outb (3, TCO2_STS);
+
/* Check that the heartbeat value is within it's range ; if not reset to the default */
if (tco_timer_set_heartbeat (heartbeat)) {
heartbeat = WATCHDOG_HEARTBEAT;
goto unreg_notifier;
}
- tco_timer_keepalive ();
+ tco_timer_stop ();
printk (KERN_INFO PFX "initialized (0x%04x). heartbeat=%d sec (nowayout=%d)\n",
TCOBASE, heartbeat, nowayout);