<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	v2.6.0-test3 -&gt; 1.1149 
#	include/asm-ppc/pmac_feature.h	1.9     -&gt; 1.10   
#	arch/ppc/syslib/Makefile	1.8     -&gt; 1.9    
#	arch/i386/kernel/head.S	1.27    -&gt; 1.28   
#	include/asm-ppc/macio_asic.h	1.1     -&gt; 1.2     include/asm-ppc/macio.h (moved)
#	drivers/char/watchdog/advantechwdt.c	1.17    -&gt; 1.18   
#	drivers/isdn/hisax/st5481_b.c	1.11    -&gt; 1.12   
#	drivers/isdn/hisax/st5481_d.c	1.10    -&gt; 1.11   
#	drivers/video/cfbimgblt.c	1.27    -&gt; 1.28   
#	drivers/char/watchdog/w83877f_wdt.c	1.17    -&gt; 1.20   
#	drivers/isdn/hisax/st5481_usb.c	1.17    -&gt; 1.18   
#	arch/ppc/platforms/pmac_setup.c	1.29    -&gt; 1.30   
#	drivers/char/watchdog/sbc60xxwdt.c	1.27    -&gt; 1.33   
#	drivers/macintosh/Makefile	1.11    -&gt; 1.12   
#	arch/ppc/platforms/pmac_feature.c	1.17    -&gt; 1.18   
#	               (new)	        -&gt; 1.1     drivers/macintosh/macio_asic.c
#	               (new)	        -&gt; 1.1     include/asm-ppc/of_device.h
#	               (new)	        -&gt; 1.1     arch/ppc/syslib/of_device.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/08/08	torvalds@home.osdl.org	1.1135
# Linux 2.6.0-test3
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1136
# [WATCHDOG] sbc60xxwdt.c patch
# 
# general cleanup of trailing spaces and comments
# fix possible wdt_is_open race
# add KERN_* to printk's
# changed watchdog_info to correctly reflect what the driver offers
# added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT, WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls
# made timeout (the emulated heartbeat) a module_param
# made the keepalive ping an internal subroutine
# added MODULE_AUTHOR and MODULE_DESCRIPTION info
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1137
# [WATCHDOG] sbc60xxwdt patch2
# 
# report default timeout as a number
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1138
# [WATCHDOG] sbc60xxwdt patch3
# 
# make wdt_stop and wdt_start module params
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1139
# [WATCHDOG] sbc60xxwdt patch4
# 
# added extra printk's to report what problem occured
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1140
# [WATCHDOG] sbc60xxwdt.c patch5
# 
# some last clean-ups
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1141
# [WATCHDOG] advantechwdt.c patch2
# 
# some small clean-ups (use PFX + report default timeout as it's value in the MODULE_PARM_DESC)
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1142
# [WATCHDOG] w83877f_wdt patch
# 
# cleanup comments and trailing spaces
# eliminate extra spin_unlock
# add KERN_* tags to printks
# added extra printk's to report what problem occured
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1143
# [WATCHDOG] w83877f_wdt.c patch2
# 
# add CONFIG_WATCHDOG_NOWAYOUT support
# changed watchdog_info to correctly reflect what the driver offers
# added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and WDIOC_SETOPTIONS ioctls
# use module_param
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1144
# [WATCHDOG] w83877f_wdt.c patch3 (add timeout features)
# 
# added WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT ioctls
# made timeout (the emulated heartbeat) a module_param
# made the keepalive ping an internal subroutine
# --------------------------------------------
# 03/08/09	wim@iguana.be	1.1145
# [WATCHDOG] sbc60xxwdt.c patch6
# 
# some small clean-ups: do correct errorhandling
# --------------------------------------------
# 03/08/09	herbert@gondor.apana.org.au	1.1146
# [PATCH] Fix usb interface change in hisax st5481_*
# 
# This makes the HISAX ST5481 driver build again with 2.6.0-test3 where
# the usb_host_config structure has changed.
# --------------------------------------------
# 03/08/09	jgarzik@pobox.com	1.1147
# [PATCH] PATCH 2.6: fix X86_VENDOR_ID offset in head.S
# 
# While reviewing my 2.4 backport of the 2.6 cpu capabilities (including
# the Via RNG support), Mikael Pettersson noticed a bug in both my
# backport, and 2.6:  when NCAPINTS (x86_capability array size) is
# increased, one must adjust the offset in arch/i386/kernel/head.S also.
# 
# Contributed by Mikael Pettersson.
# --------------------------------------------
# 03/08/09	benh@kernel.crashing.org	1.1148
# [PATCH] PowerMac: Ground work for new driver model
# 
# This provides the necessary infrastructure for PowerMac specific drivers
# (and actually some Open Firmware platform drivers on non-PowerMacs as
# well provided somebody port them) to be properly probed &amp; referenced via
# the new driver model and be part of sysfs.
# 
# As-is, this patch doesn't break anything nor change any driver.  I'll
# send you individual driver patches as I clean them up &amp; get them tested
# on as many machines as possible, though I don't expect much problems.
# --------------------------------------------
# 03/08/09	tmolina@cablespeed.com	1.1149
# [PATCH] Re: Linux 2.6.0-test3: logo patch
# 
# The following patch has been floating around forever.  It is required
# for several ARM framebuffer drivers, and several other drivers.  James
# has indicated that this is the correct fix back in May.
# --------------------------------------------
#
diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
--- a/arch/i386/kernel/head.S	Sat Aug  9 16:58:28 2003
+++ b/arch/i386/kernel/head.S	Sat Aug  9 16:58:28 2003
@@ -35,7 +35,7 @@
 #define X86_HARD_MATH	CPU_PARAMS+6
 #define X86_CPUID	CPU_PARAMS+8
 #define X86_CAPABILITY	CPU_PARAMS+12
-#define X86_VENDOR_ID	CPU_PARAMS+28
+#define X86_VENDOR_ID	CPU_PARAMS+36
 
 /*
  * Initialize page tables
diff -Nru a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
--- a/arch/ppc/platforms/pmac_feature.c	Sat Aug  9 16:58:28 2003
+++ b/arch/ppc/platforms/pmac_feature.c	Sat Aug  9 16:58:28 2003
@@ -38,7 +38,6 @@
 #include &lt;asm/io.h&gt;
 #include &lt;asm/prom.h&gt;
 #include &lt;asm/machdep.h&gt;
-#include &lt;asm/macio_asic.h&gt;
 #include &lt;asm/pmac_feature.h&gt;
 #include &lt;asm/dbdma.h&gt;
 #include &lt;asm/pci-bridge.h&gt;
@@ -2187,6 +2186,8 @@
 		macio_chips[0] = macio_chips[1];
 		macio_chips[1] = temp;
 	}
+	macio_chips[0].lbus.index = 0;
+	macio_chips[1].lbus.index = 1;
 
 	return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
 }
diff -Nru a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
--- a/arch/ppc/platforms/pmac_setup.c	Sat Aug  9 16:58:28 2003
+++ b/arch/ppc/platforms/pmac_setup.c	Sat Aug  9 16:58:28 2003
@@ -69,6 +69,7 @@
 #include &lt;asm/btext.h&gt;
 #include &lt;asm/pmac_feature.h&gt;
 #include &lt;asm/time.h&gt;
+#include &lt;asm/of_device.h&gt;
 #include "pmac_pic.h"
 #include "mem_pieces.h"
 
@@ -670,3 +671,29 @@
 	}
 }
 #endif /* CONFIG_BOOTX_TEXT */
+
+static int __init
+pmac_declare_of_platform_devices(void)
+{
+	struct device_node *np;
+
+	np = find_devices("uni-n");
+	if (np) {
+		for (np = np-&gt;child; np != NULL; np = np-&gt;sibling)
+			if (strncmp(np-&gt;name, "i2c", 3) == 0) {
+				of_platform_device_create(np, "uni-n-i2c");
+				break;
+			}
+	}
+
+	np = find_devices("valkyrie");
+	if (np)
+		of_platform_device_create(np, "valkyrie");
+	np = find_devices("platinum");
+	if (np)
+		of_platform_device_create(np, "platinum");
+
+	return 0;
+}
+
+device_initcall(pmac_declare_of_platform_devices);
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile	Sat Aug  9 16:58:28 2003
+++ b/arch/ppc/syslib/Makefile	Sat Aug  9 16:58:28 2003
@@ -27,7 +27,7 @@
 ifeq ($(CONFIG_8xx),y)
 obj-$(CONFIG_PCI)		+= qspan_pci.o i8259.o
 endif
-obj-$(CONFIG_PPC_OF)		+= prom_init.o prom.o
+obj-$(CONFIG_PPC_OF)		+= prom_init.o prom.o of_device.o
 obj-$(CONFIG_PPC_PMAC)		+= open_pic.o indirect_pci.o
 obj-$(CONFIG_PPC_CHRP)		+= open_pic.o indirect_pci.o i8259.o
 obj-$(CONFIG_PPC_PREP)		+= open_pic.o indirect_pci.o i8259.o
diff -Nru a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/syslib/of_device.c	Sat Aug  9 16:58:28 2003
@@ -0,0 +1,249 @@
+#include &lt;linux/config.h&gt;
+#include &lt;linux/string.h&gt;
+#include &lt;linux/kernel.h&gt;
+#include &lt;linux/init.h&gt;
+#include &lt;linux/module.h&gt;
+#include &lt;asm/errno.h&gt;
+#include &lt;asm/of_device.h&gt;
+
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ * 
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices. 
+ */
+const struct of_match *
+of_match_device(const struct of_match *matches, const struct of_device *dev)
+{
+	if (!dev-&gt;node)
+		return NULL;
+	while (matches-&gt;name || matches-&gt;type || matches-&gt;compatible) {
+		int match = 1;
+		if (matches-&gt;name &amp;&amp; matches-&gt;name != OF_ANY_MATCH)
+			match &amp;= dev-&gt;node-&gt;name
+				&amp;&amp; !strcmp(matches-&gt;name, dev-&gt;node-&gt;name);
+		if (matches-&gt;type &amp;&amp; matches-&gt;type != OF_ANY_MATCH)
+			match &amp;= dev-&gt;node-&gt;type
+				&amp;&amp; !strcmp(matches-&gt;type, dev-&gt;node-&gt;type);
+		if (matches-&gt;compatible &amp;&amp; matches-&gt;compatible != OF_ANY_MATCH)
+			match &amp;= device_is_compatible(dev-&gt;node,
+				matches-&gt;compatible);
+		if (match)
+			return matches;
+		matches++;
+	}
+	return NULL;
+}
+
+static int
+of_platform_bus_match(struct device *dev, struct device_driver *drv) 
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+	const struct of_match * matches = of_drv-&gt;match_table;
+
+	if (!matches) 
+		return 0;
+
+	return of_match_device(matches, of_dev) != NULL;
+}
+
+struct bus_type of_platform_bus_type = {
+       name:	"of_platform",
+       match:	of_platform_bus_match,
+};
+
+static int __init
+of_bus_driver_init(void)
+{
+	return bus_register(&amp;of_platform_bus_type);
+}
+
+postcore_initcall(of_bus_driver_init);
+
+static int
+of_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct of_platform_driver *drv;
+	struct of_device *of_dev;
+	const struct of_match *match;
+
+	drv = to_of_platform_driver(dev-&gt;driver);
+	of_dev = to_of_device(dev);
+
+	if (!drv-&gt;probe)
+		return error;
+
+/*	if (!try_module_get(driver-&gt;owner)) {
+		printk(KERN_ERR "Can't get a module reference for %s\n", driver-&gt;name);
+		return error;
+	}
+*/
+	match = of_match_device(drv-&gt;match_table, of_dev);
+	if (match)
+		error = drv-&gt;probe(of_dev, match);
+/*
+ 	module_put(driver-&gt;owner);
+*/	
+	return error;
+}
+
+static int
+of_device_remove(struct device *dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(of_dev-&gt;dev.driver);
+
+	if (drv &amp;&amp; drv-&gt;remove)
+		drv-&gt;remove(of_dev);
+	return 0;
+}
+
+static int
+of_device_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(of_dev-&gt;dev.driver);
+	int error = 0;
+
+	if (drv &amp;&amp; drv-&gt;suspend)
+		error = drv-&gt;suspend(of_dev, state, level);
+	return error;
+}
+
+static int
+of_device_resume(struct device * dev, u32 level)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(of_dev-&gt;dev.driver);
+	int error = 0;
+
+	if (drv &amp;&amp; drv-&gt;resume)
+		error = drv-&gt;resume(of_dev, level);
+	return error;
+}
+
+int
+of_register_driver(struct of_platform_driver *drv)
+{
+	int count = 0;
+
+	/* initialize common driver fields */
+	drv-&gt;driver.name = drv-&gt;name;
+	drv-&gt;driver.bus = &amp;of_platform_bus_type;
+	drv-&gt;driver.probe = of_device_probe;
+	drv-&gt;driver.resume = of_device_resume;
+	drv-&gt;driver.suspend = of_device_suspend;
+	drv-&gt;driver.remove = of_device_remove;
+
+	/* register with core */
+	count = driver_register(&amp;drv-&gt;driver);
+	return count ? count : 1;
+}
+
+void
+of_unregister_driver(struct of_platform_driver *drv)
+{
+	driver_unregister(&amp;drv-&gt;driver);
+}
+
+
+static ssize_t
+dev_show_devspec(struct device *dev, char *buf)
+{
+	struct of_device *ofdev;
+
+	ofdev = to_of_device(dev);
+	return sprintf(buf, "%s", ofdev-&gt;node-&gt;full_name);
+}
+
+static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+
+int
+of_device_register(struct of_device *ofdev)
+{
+	int rc;
+	struct of_device **odprop;
+
+	BUG_ON(ofdev-&gt;node == NULL);
+	
+	odprop = (struct of_device **)get_property(ofdev-&gt;node, "linux,device", NULL);
+	if (!odprop) {
+		struct property *new_prop;
+		
+		new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),
+			GFP_KERNEL);
+		if (new_prop == NULL)
+			return -ENOMEM;
+		new_prop-&gt;name = "linux,device";
+		new_prop-&gt;length = sizeof(sizeof(struct of_device *));
+		new_prop-&gt;value = (unsigned char *)&amp;new_prop[1];
+		odprop = (struct of_device **)new_prop-&gt;value;
+		*odprop = NULL;
+		prom_add_property(ofdev-&gt;node, new_prop);
+	}
+	*odprop = ofdev;
+
+	rc = device_register(&amp;ofdev-&gt;dev);
+	if (rc)
+		return rc;
+
+	device_create_file(&amp;ofdev-&gt;dev, &amp;dev_attr_devspec);
+
+	return 0;
+}
+
+void
+of_device_unregister(struct of_device *ofdev)
+{
+	struct of_device **odprop;
+
+	device_remove_file(&amp;ofdev-&gt;dev, &amp;dev_attr_devspec);
+	device_unregister(&amp;ofdev-&gt;dev);
+
+	odprop = (struct of_device **)get_property(ofdev-&gt;node, "linux,device", NULL);
+	if (odprop)
+		*odprop = NULL;
+}
+
+struct of_device*
+of_platform_device_create(struct device_node *np, const char *bus_id)
+{
+	struct of_device *dev;
+	u32 *reg;
+	
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+	memset(dev, 0, sizeof(*dev));
+
+	dev-&gt;node = np;
+	dev-&gt;dma_mask = 0xffffffffUL;
+	dev-&gt;dev.dma_mask = &amp;dev-&gt;dma_mask;
+	dev-&gt;dev.parent = NULL;
+	dev-&gt;dev.bus = &amp;of_platform_bus_type;
+
+	/* XXX Make something better here ? */
+	snprintf(dev-&gt;dev.name, DEVICE_NAME_SIZE, "Platform device %s", np-&gt;name);
+	reg = (u32 *)get_property(np, "reg", NULL);
+	strlcpy(dev-&gt;dev.bus_id, bus_id, BUS_ID_SIZE);
+
+	if (of_device_register(dev) != 0) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+EXPORT_SYMBOL(of_match_device);
+EXPORT_SYMBOL(of_platform_bus_type);
+EXPORT_SYMBOL(of_register_driver);
+EXPORT_SYMBOL(of_unregister_driver);
+EXPORT_SYMBOL(of_device_register);
+EXPORT_SYMBOL(of_device_unregister);
+EXPORT_SYMBOL(of_platform_device_create);
diff -Nru a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c
--- a/drivers/char/watchdog/advantechwdt.c	Sat Aug  9 16:58:28 2003
+++ b/drivers/char/watchdog/advantechwdt.c	Sat Aug  9 16:58:28 2003
@@ -44,6 +44,7 @@
 #include &lt;asm/system.h&gt;
 
 #define WATCHDOG_NAME "Advantech WDT"
+#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60		/* 60 sec default timeout */
 
 static unsigned long advwdt_is_open;
@@ -70,7 +71,7 @@
 
 static int timeout = WATCHDOG_TIMEOUT;	/* in seconds */
 module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1&lt;= timeout &lt;=63, default=60.");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1&lt;= timeout &lt;=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
 static int nowayout = 1;
@@ -206,7 +207,7 @@
 	if (adv_expect_close == 42) {
 		advwdt_disable();
 	} else {
-		printk(KERN_CRIT WATCHDOG_NAME ": Unexpected close, not stopping watchdog!\n");
+		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
 		advwdt_ping();
 	}
 	clear_bit(0, &amp;advwdt_is_open);
@@ -268,13 +269,13 @@
 
 	if (timeout &lt; 1 || timeout &gt; 63) {
 		timeout = WATCHDOG_TIMEOUT;
-		printk (KERN_INFO WATCHDOG_NAME ": timeout value must be 1&lt;=x&lt;=63, using %d\n",
+		printk (KERN_INFO PFX "timeout value must be 1&lt;=x&lt;=63, using %d\n",
 			timeout);
 	}
 
 	if (wdt_stop != wdt_start) {
 		if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
-			printk (KERN_ERR WATCHDOG_NAME ": I/O address 0x%04x already in use\n",
+			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
 				wdt_stop);
 			ret = -EIO;
 			goto out;
@@ -282,7 +283,7 @@
 	}
 
 	if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
-		printk (KERN_ERR WATCHDOG_NAME ": I/O address 0x%04x already in use\n",
+		printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
 			wdt_start);
 		ret = -EIO;
 		goto unreg_stop;
@@ -290,19 +291,19 @@
 
 	ret = register_reboot_notifier(&amp;advwdt_notifier);
 	if (ret != 0) {
-		printk (KERN_ERR WATCHDOG_NAME ": cannot register reboot notifier (err=%d)\n",
+		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
 			ret);
 		goto unreg_regions;
 	}
 
 	ret = misc_register(&amp;advwdt_miscdev);
 	if (ret != 0) {
-		printk (KERN_ERR WATCHDOG_NAME ": cannot register miscdev on minor=%d (err=%d)\n",
+		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
 			WATCHDOG_MINOR, ret);
 		goto unreg_reboot;
 	}
 
-	printk (KERN_INFO WATCHDOG_NAME ": initialized. timeout=%d sec (nowayout=%d)\n",
+	printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
 		timeout, nowayout);
 
 out:
diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
--- a/drivers/char/watchdog/sbc60xxwdt.c	Sat Aug  9 16:58:28 2003
+++ b/drivers/char/watchdog/sbc60xxwdt.c	Sat Aug  9 16:58:28 2003
@@ -7,51 +7,40 @@
  *	modify it under the terms of the GNU General Public License
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
- *	
- *	The author does NOT admit liability nor provide warranty for 
- *	any of this software. This material is provided "AS-IS" in 
- *      the hope that it may be useful for others.
  *
- *	(c) Copyright 2000    Jakob Oestergaard &lt;jakob@ostenfeld.dk&gt;
+ *	The author does NOT admit liability nor provide warranty for
+ *	any of this software. This material is provided "AS-IS" in
+ *	the hope that it may be useful for others.
+ *
+ *	(c) Copyright 2000    Jakob Oestergaard &lt;jakob@unthought.net&gt;
  *
  *           12/4 - 2000      [Initial revision]
  *           25/4 - 2000      Added /dev/watchdog support
  *           09/5 - 2001      [smj@oro.net] fixed fop_write to "return 1" on success
+ *           12/4 - 2002      [rob@osinvestor.com] eliminate fop_read
+ *                            fix possible wdt_is_open race
+ *                            add CONFIG_WATCHDOG_NOWAYOUT support
+ *                            remove lock_kernel/unlock_kernel pairs
+ *                            added KERN_* to printk's
+ *                            got rid of extraneous comments
+ *                            changed watchdog_info to correctly reflect what the driver offers
+ *                            added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT,
+ *                            WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls
+ *           09/8 - 2003      [wim@iguana.be] cleanup of trailing spaces
+ *                            use module_param
+ *                            made timeout (the emulated heartbeat) a module_param
+ *                            made the keepalive ping an internal subroutine
+ *                            made wdt_stop and wdt_start module params
+ *                            added extra printk's for startup problems
+ *                            added MODULE_AUTHOR and MODULE_DESCRIPTION info
  *
  *
- *  Theory of operation:
- *  A Watchdog Timer (WDT) is a hardware circuit that can 
- *  reset the computer system in case of a software fault.
- *  You probably knew that already.
- *
- *  Usually a userspace daemon will notify the kernel WDT driver
- *  via the /proc/watchdog special device file that userspace is
- *  still alive, at regular intervals.  When such a notification
- *  occurs, the driver will usually tell the hardware watchdog
- *  that everything is in order, and that the watchdog should wait
- *  for yet another little while to reset the system.
- *  If userspace fails (RAM error, kernel bug, whatever), the
- *  notifications cease to occur, and the hardware watchdog will
- *  reset the system (causing a reboot) after the timeout occurs.
- *
- *  This WDT driver is different from the other Linux WDT 
- *  drivers in several ways:
+ *  This WDT driver is different from the other Linux WDT
+ *  drivers in the following ways:
  *  *)  The driver will ping the watchdog by itself, because this
  *      particular WDT has a very short timeout (one second) and it
  *      would be insane to count on any userspace daemon always
  *      getting scheduled within that time frame.
- *  *)  This driver expects the userspace daemon to send a specific
- *      character code ('V') to /dev/watchdog before closing the
- *      /dev/watchdog file.  If the userspace daemon closes the file
- *      without sending this special character, the driver will assume
- *      that the daemon (and userspace in general) died, and will
- *      stop pinging the WDT without disabling it first.  This will
- *      cause a reboot.
- *
- *  Why `V' ?  Well, `V' is the character in ASCII for the value 86,
- *  and we all know that 86 is _the_ most random number in the universe.
- *  Therefore it is the letter that has the slightest chance of occurring
- *  by chance, when the system becomes corrupted.
  *
  */
 
@@ -73,13 +62,19 @@
 #include &lt;asm/system.h&gt;
 
 #define OUR_NAME "sbc60xxwdt"
+#define PFX OUR_NAME ": "
 
 /*
  * You must set these - The driver cannot probe for the settings
  */
- 
-#define WDT_STOP 0x45
-#define WDT_START 0x443
+
+static int wdt_stop = 0x45;
+module_param(wdt_stop, int, 0);
+MODULE_PARM_DESC(wdt_stop, "SBC60xx WDT 'stop' io port (default 0x45)");
+
+static int wdt_start = 0x443;
+module_param(wdt_start, int, 0);
+MODULE_PARM_DESC(wdt_start, "SBC60xx WDT 'start' io port (default 0x443)");
 
 /*
  * The 60xx board can use watchdog timeout values from one second
@@ -92,19 +87,16 @@
 /*
  * We must not require too good response from the userspace daemon.
  * Here we require the userspace daemon to send us a heartbeat
- * char to /dev/watchdog every 10 seconds.
- * If the daemon pulses us every 5 seconds, we can still afford
+ * char to /dev/watchdog every 30 seconds.
+ * If the daemon pulses us every 25 seconds, we can still afford
  * a 5 second scheduling delay on the (high priority) daemon. That
  * should be sufficient for a box under any load.
  */
 
-#define WDT_HEARTBEAT (HZ * 10)
-
-static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
-static unsigned long next_heartbeat;
-static int wdt_is_open;
-static int wdt_expect_close;
+#define WATCHDOG_TIMEOUT 30		/* 30 sec default timeout */
+static int timeout = WATCHDOG_TIMEOUT;	/* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1&lt;=timeout&lt;=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
 static int nowayout = 1;
@@ -115,6 +107,12 @@
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
+static void wdt_timer_ping(unsigned long);
+static struct timer_list timer;
+static unsigned long next_heartbeat;
+static unsigned long wdt_is_open;
+static char wdt_expect_close;
+
 /*
  *	Whack the dog
  */
@@ -122,42 +120,47 @@
 static void wdt_timer_ping(unsigned long data)
 {
 	/* If we got a heartbeat pulse within the WDT_US_INTERVAL
-	 * we agree to ping the WDT 
+	 * we agree to ping the WDT
 	 */
-	if(time_before(jiffies, next_heartbeat)) 
+	if(time_before(jiffies, next_heartbeat))
 	{
-		/* Ping the WDT by reading from WDT_START */
-		inb_p(WDT_START);
+		/* Ping the WDT by reading from wdt_start */
+		inb_p(wdt_start);
 		/* Re-set the timer interval */
 		timer.expires = jiffies + WDT_INTERVAL;
 		add_timer(&amp;timer);
 	} else {
-		printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n");
+		printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
 	}
 }
 
-/* 
+/*
  * Utility routines
  */
 
 static void wdt_startup(void)
 {
-	next_heartbeat = jiffies + WDT_HEARTBEAT;
+	next_heartbeat = jiffies + (timeout * HZ);
 
 	/* Start the timer */
-	timer.expires = jiffies + WDT_INTERVAL;	
+	timer.expires = jiffies + WDT_INTERVAL;
 	add_timer(&amp;timer);
-	printk(OUR_NAME ": Watchdog timer is now enabled.\n");  
+	printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
 }
 
 static void wdt_turnoff(void)
 {
 	/* Stop the timer */
 	del_timer(&amp;timer);
-	inb_p(WDT_STOP);
-	printk(OUR_NAME ": Watchdog timer is now disabled...\n");
+	inb_p(wdt_stop);
+	printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
 }
 
+static void wdt_keepalive(void)
+{
+	/* user land ping */
+	next_heartbeat = jiffies + (timeout * HZ);
+}
 
 /*
  * /dev/watchdog handling
@@ -169,63 +172,58 @@
 	if(ppos != &amp;file-&gt;f_pos)
 		return -ESPIPE;
 
-	/* See if we got the magic character */
-	if(count) 
+	/* See if we got the magic character 'V' and reload the timer */
+	if(count)
 	{
-		size_t ofs;
-
-		/* note: just in case someone wrote the magic character
-		 * five months ago... */
-		wdt_expect_close = 0;
-
-		/* now scan */
-		for(ofs = 0; ofs != count; ofs++) 
+		if (!nowayout)
 		{
-			char c;
-			if(get_user(c, buf+ofs))
-				return -EFAULT;
-			if(c == 'V')
-				wdt_expect_close = 1;
+			size_t ofs;
+
+			/* note: just in case someone wrote the magic character
+			 * five months ago... */
+			wdt_expect_close = 0;
+
+			/* scan to see wether or not we got the magic character */
+			for(ofs = 0; ofs != count; ofs++)
+			{
+				char c;
+				if(get_user(c, buf+ofs))
+					return -EFAULT;
+				if(c == 'V')
+					wdt_expect_close = 42;
+			}
 		}
+
 		/* Well, anyhow someone wrote to us, we should return that favour */
-		next_heartbeat = jiffies + WDT_HEARTBEAT;
-		return 1;
+		wdt_keepalive();
 	}
-	return 0;
+	return count;
 }
 
 static int fop_open(struct inode * inode, struct file * file)
 {
-	switch(minor(inode-&gt;i_rdev)) 
-	{
-		case WATCHDOG_MINOR:
-			/* Just in case we're already talking to someone... */
-			if(wdt_is_open)
-				return -EBUSY;
-			if (nowayout) 
-				__module_get(THIS_MODULE);
-			/* Good, fire up the show */
-			wdt_is_open = 1;
-			wdt_startup();
-			return 0;
+	/* Just in case we're already talking to someone... */
+	if(test_and_set_bit(0, &amp;wdt_is_open))
+		return -EBUSY;
 
-		default:
-			return -ENODEV;
-	}
+	if (nowayout)
+		__module_get(THIS_MODULE);
+
+	/* Good, fire up the show */
+	wdt_startup();
+	return 0;
 }
 
 static int fop_close(struct inode * inode, struct file * file)
 {
-	if(minor(inode-&gt;i_rdev) == WATCHDOG_MINOR) 
-	{
-		if(wdt_expect_close &amp;&amp; !nowayout)
-			wdt_turnoff();
-		else {
-			del_timer(&amp;timer);
-			printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n");
-		}
+	if(wdt_expect_close == 42)
+		wdt_turnoff();
+	else {
+		del_timer(&amp;timer);
+		printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n");
 	}
-	wdt_is_open = 0;
+	clear_bit(0, &amp;wdt_is_open);
+	wdt_expect_close = 0;
 	return 0;
 }
 
@@ -234,20 +232,58 @@
 {
 	static struct watchdog_info ident=
 	{
-		.options = WDIOF_MAGICCLOSE,
+		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
-		.identity = "SB60xx"
+		.identity = "SBC60xx",
 	};
-	
+
 	switch(cmd)
 	{
 		default:
-			return -ENOTTY;
+			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
 			return copy_to_user((struct watchdog_info *)arg, &amp;ident, sizeof(ident))?-EFAULT:0;
+		case WDIOC_GETSTATUS:
+		case WDIOC_GETBOOTSTATUS:
+			return put_user(0, (int *)arg);
 		case WDIOC_KEEPALIVE:
-			next_heartbeat = jiffies + WDT_HEARTBEAT;
+			wdt_keepalive();
 			return 0;
+		case WDIOC_SETOPTIONS:
+		{
+			int new_options, retval = -EINVAL;
+
+			if(get_user(new_options, (int *)arg))
+				return -EFAULT;
+
+			if(new_options &amp; WDIOS_DISABLECARD) {
+				wdt_turnoff();
+				retval = 0;
+			}
+
+			if(new_options &amp; WDIOS_ENABLECARD) {
+				wdt_startup();
+				retval = 0;
+			}
+
+			return retval;
+		}
+		case WDIOC_SETTIMEOUT:
+		{
+			int new_timeout;
+
+			if(get_user(new_timeout, (int *)arg))
+				return -EFAULT;
+
+			if(new_timeout &lt; 1 || new_timeout &gt; 3600) /* arbitrary upper limit */
+				return -EINVAL;
+
+			timeout = new_timeout;
+			wdt_keepalive();
+			/* Fall through */
+		}
+		case WDIOC_GETTIMEOUT:
+			return put_user(timeout, (int *)arg);
 	}
 }
 
@@ -257,13 +293,13 @@
 	.write		= fop_write,
 	.open		= fop_open,
 	.release	= fop_close,
-	.ioctl		= fop_ioctl
+	.ioctl		= fop_ioctl,
 };
 
 static struct miscdevice wdt_miscdev = {
 	.minor = WATCHDOG_MINOR,
 	.name = "watchdog",
-	.fops = &amp;wdt_fops
+	.fops = &amp;wdt_fops,
 };
 
 /*
@@ -273,21 +309,21 @@
 static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
 	void *unused)
 {
-	if(code==SYS_DOWN || code==SYS_HALT) 
+	if(code==SYS_DOWN || code==SYS_HALT)
 		wdt_turnoff();
 	return NOTIFY_DONE;
 }
- 
+
 /*
  *	The WDT needs to learn about soft shutdowns in order to
- *	turn the timebomb registers off. 
+ *	turn the timebomb registers off.
  */
- 
+
 static struct notifier_block wdt_notifier=
 {
 	.notifier_call = wdt_notify_sys,
 	.next = NULL,
-	.priority = 0
+	.priority = 0,
 };
 
 static void __exit sbc60xxwdt_unload(void)
@@ -298,19 +334,41 @@
 	misc_deregister(&amp;wdt_miscdev);
 
 	unregister_reboot_notifier(&amp;wdt_notifier);
-	release_region(WDT_START,1);
-//	release_region(WDT_STOP,1);
+	if ((wdt_stop != 0x45) &amp;&amp; (wdt_stop != wdt_start))
+		release_region(wdt_stop,1);
+	release_region(wdt_start,1);
 }
 
 static int __init sbc60xxwdt_init(void)
 {
 	int rc = -EBUSY;
 
-//	We cannot reserve 0x45 - the kernel already has!
-//	if (!request_region(WDT_STOP, 1, "SBC 60XX WDT"))
-//		goto err_out;
-	if (!request_region(WDT_START, 1, "SBC 60XX WDT"))
-		goto err_out_region1;
+	if(timeout &lt; 1 || timeout &gt; 3600) /* arbitrary upper limit */
+	{
+		timeout = WATCHDOG_TIMEOUT;
+		printk(KERN_INFO PFX "timeout value must be 1&lt;=x&lt;=3600, using %d\n",
+			timeout);
+ 	}
+
+	if (!request_region(wdt_start, 1, "SBC 60XX WDT"))
+	{
+		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+			wdt_start);
+		rc = -EIO;
+		goto err_out;
+	}
+
+	/* We cannot reserve 0x45 - the kernel already has! */
+	if ((wdt_stop != 0x45) &amp;&amp; (wdt_stop != wdt_start))
+	{
+		if (!request_region(wdt_stop, 1, "SBC 60XX WDT"))
+		{
+			printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+				wdt_stop);
+			rc = -EIO;
+			goto err_out_region1;
+		}
+	}
 
 	init_timer(&amp;timer);
 	timer.function = wdt_timer_ping;
@@ -318,27 +376,39 @@
 
 	rc = misc_register(&amp;wdt_miscdev);
 	if (rc)
+	{
+		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+			wdt_miscdev.minor, rc);
 		goto err_out_region2;
+	}
 
 	rc = register_reboot_notifier(&amp;wdt_notifier);
 	if (rc)
+	{
+		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+			rc);
 		goto err_out_miscdev;
+	}
+
+	printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
+		timeout, nowayout);
 
-	printk(KERN_INFO OUR_NAME ": WDT driver for 60XX single board computer initialised.\n");
-	
 	return 0;
 
 err_out_miscdev:
 	misc_deregister(&amp;wdt_miscdev);
 err_out_region2:
-	release_region(WDT_START,1);
+	if ((wdt_stop != 0x45) &amp;&amp; (wdt_stop != wdt_start))
+		release_region(wdt_stop,1);
 err_out_region1:
-	release_region(WDT_STOP,1);
-/* err_out: */
+	release_region(wdt_start,1);
+err_out:
 	return rc;
 }
 
 module_init(sbc60xxwdt_init);
 module_exit(sbc60xxwdt_unload);
 
+MODULE_AUTHOR("Jakob Oestergaard &lt;jakob@unthought.net&gt;");
+MODULE_DESCRIPTION("60xx Single Board Computer Watchdog Timer driver");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c
--- a/drivers/char/watchdog/w83877f_wdt.c	Sat Aug  9 16:58:28 2003
+++ b/drivers/char/watchdog/w83877f_wdt.c	Sat Aug  9 16:58:28 2003
@@ -1,38 +1,36 @@
 /*
- *	W83877F Computer Watchdog Timer driver for Linux 2.4.x
+ *	W83877F Computer Watchdog Timer driver
  *
  *      Based on acquirewdt.c by Alan Cox,
- *           and sbc60xxwdt.c by Jakob Oestergaard &lt;jakob@ostenfeld.dk&gt;
- *     
+ *           and sbc60xxwdt.c by Jakob Oestergaard &lt;jakob@unthought.net&gt;
+ *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
- *	
- *	The authors do NOT admit liability nor provide warranty for 
- *	any of this software. This material is provided "AS-IS" in 
+ *
+ *	The authors do NOT admit liability nor provide warranty for
+ *	any of this software. This material is provided "AS-IS" in
  *      the hope that it may be useful for others.
  *
  *	(c) Copyright 2001    Scott Jennings &lt;linuxdrivers@oro.net&gt;
  *
  *           4/19 - 2001      [Initial revision]
  *           9/27 - 2001      Added spinlocking
- *
- *
- *  Theory of operation:
- *  A Watchdog Timer (WDT) is a hardware circuit that can 
- *  reset the computer system in case of a software fault.
- *  You probably knew that already.
- *
- *  Usually a userspace daemon will notify the kernel WDT driver
- *  via the /proc/watchdog special device file that userspace is
- *  still alive, at regular intervals.  When such a notification
- *  occurs, the driver will usually tell the hardware watchdog
- *  that everything is in order, and that the watchdog should wait
- *  for yet another little while to reset the system.
- *  If userspace fails (RAM error, kernel bug, whatever), the
- *  notifications cease to occur, and the hardware watchdog will
- *  reset the system (causing a reboot) after the timeout occurs.
+ *           4/12 - 2002      [rob@osinvestor.com] Eliminate extra comments
+ *                            Eliminate fop_read
+ *                            Eliminate extra spin_unlock
+ *                            Added KERN_* tags to printks
+ *                            add CONFIG_WATCHDOG_NOWAYOUT support
+ *                            fix possible wdt_is_open race
+ *                            changed watchdog_info to correctly reflect what the driver offers
+ *                            added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT,
+ *                            WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls
+ *           09/8 - 2003      [wim@iguana.be] cleanup of trailing spaces
+ *                            added extra printk's for startup problems
+ *                            use module_param
+ *                            made timeout (the emulated heartbeat) a module_param
+ *                            made the keepalive ping an internal subroutine
  *
  *  This WDT driver is different from most other Linux WDT
  *  drivers in that the driver will ping the watchdog by itself,
@@ -42,6 +40,7 @@
  */
 
 #include &lt;linux/module.h&gt;
+#include &lt;linux/moduleparam.h&gt;
 #include &lt;linux/types.h&gt;
 #include &lt;linux/timer.h&gt;
 #include &lt;linux/jiffies.h&gt;
@@ -57,6 +56,7 @@
 #include &lt;asm/system.h&gt;
 
 #define OUR_NAME "w83877f_wdt"
+#define PFX OUR_NAME ": "
 
 #define ENABLE_W83877F_PORT 0x3F0
 #define ENABLE_W83877F 0x87
@@ -79,13 +79,26 @@
  * char to /dev/watchdog every 30 seconds.
  */
 
-#define WDT_HEARTBEAT (HZ * 30)
+#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1&lt;=timeout&lt;=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
 static void wdt_timer_ping(unsigned long);
 static struct timer_list timer;
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
-static int wdt_expect_close;
+static char wdt_expect_close;
 static spinlock_t wdt_spinlock;
 
 /*
@@ -95,9 +108,9 @@
 static void wdt_timer_ping(unsigned long data)
 {
 	/* If we got a heartbeat pulse within the WDT_US_INTERVAL
-	 * we agree to ping the WDT 
+	 * we agree to ping the WDT
 	 */
-	if(time_before(jiffies, next_heartbeat)) 
+	if(time_before(jiffies, next_heartbeat))
 	{
 		/* Ping the WDT */
 		spin_lock(&amp;wdt_spinlock);
@@ -112,11 +125,11 @@
 		spin_unlock(&amp;wdt_spinlock);
 
 	} else {
-		printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n");
+		printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
 	}
 }
 
-/* 
+/*
  * Utility routines
  */
 
@@ -144,15 +157,15 @@
 
 static void wdt_startup(void)
 {
-	next_heartbeat = jiffies + WDT_HEARTBEAT;
+	next_heartbeat = jiffies + (timeout * HZ);
 
 	/* Start the timer */
-	timer.expires = jiffies + WDT_INTERVAL;	
+	timer.expires = jiffies + WDT_INTERVAL;
 	add_timer(&amp;timer);
 
 	wdt_change(WDT_ENABLE);
 
-	printk(OUR_NAME ": Watchdog timer is now enabled.\n");  
+	printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
 }
 
 static void wdt_turnoff(void)
@@ -162,9 +175,14 @@
 
 	wdt_change(WDT_DISABLE);
 
-	printk(OUR_NAME ": Watchdog timer is now disabled...\n");
+	printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
 }
 
+static void wdt_keepalive(void)
+{
+	/* user land ping */
+	next_heartbeat = jiffies + (timeout * HZ);
+}
 
 /*
  * /dev/watchdog handling
@@ -176,64 +194,55 @@
 	if(ppos != &amp;file-&gt;f_pos)
 		return -ESPIPE;
 
-	/* See if we got the magic character */
-	if(count) 
+	/* See if we got the magic character 'V' and reload the timer */
+	if(count)
 	{
-		size_t ofs;
-
-		/* note: just in case someone wrote the magic character
-		 * five months ago... */
-		wdt_expect_close = 0;
-
-		/* now scan */
-		for(ofs = 0; ofs != count; ofs++)
+		if (!nowayout)
 		{
-			char c;
-			if (get_user(c, buf + ofs))
-				return -EFAULT;
-			if (c == 'V')
-				wdt_expect_close = 1;
+			size_t ofs;
+
+			/* note: just in case someone wrote the magic character
+			 * five months ago... */
+			wdt_expect_close = 0;
+
+			/* scan to see wether or not we got the magic character */
+			for(ofs = 0; ofs != count; ofs++)
+			{
+				char c;
+				if (get_user(c, buf + ofs))
+					return -EFAULT;
+				if (c == 'V')
+					wdt_expect_close = 42;
+			}
 		}
 
 		/* someone wrote to us, we should restart timer */
-		next_heartbeat = jiffies + WDT_HEARTBEAT;
-		return 1;
-	};
-	return 0;
+		wdt_keepalive();
+	}
+	return count;
 }
 
 static int fop_open(struct inode * inode, struct file * file)
 {
-	switch(minor(inode-&gt;i_rdev)) 
-	{
-		case WATCHDOG_MINOR:
-			/* Just in case we're already talking to someone... */
-			if(test_and_set_bit(0, &amp;wdt_is_open)) {
-				/* Davej: Is this unlock bogus? */
-				spin_unlock(&amp;wdt_spinlock);
-				return -EBUSY;
-			}
-			/* Good, fire up the show */
-			wdt_startup();
-			return 0;
+	/* Just in case we're already talking to someone... */
+	if(test_and_set_bit(0, &amp;wdt_is_open))
+		return -EBUSY;
 
-		default:
-			return -ENODEV;
-	}
+	/* Good, fire up the show */
+	wdt_startup();
+	return 0;
 }
 
 static int fop_close(struct inode * inode, struct file * file)
 {
-	if(minor(inode-&gt;i_rdev) == WATCHDOG_MINOR) 
-	{
-		if(wdt_expect_close)
-			wdt_turnoff();
-		else {
-			del_timer(&amp;timer);
-			printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n");
-		}
+	if(wdt_expect_close == 42)
+		wdt_turnoff();
+	else {
+		del_timer(&amp;timer);
+		printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n");
 	}
 	clear_bit(0, &amp;wdt_is_open);
+	wdt_expect_close = 0;
 	return 0;
 }
 
@@ -242,20 +251,58 @@
 {
 	static struct watchdog_info ident=
 	{
-		.options = WDIOF_MAGICCLOSE,
+		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
-		.identity = "W83877F"
+		.identity = "W83877F",
 	};
-	
+
 	switch(cmd)
 	{
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
 			return copy_to_user((struct watchdog_info *)arg, &amp;ident, sizeof(ident))?-EFAULT:0;
+		case WDIOC_GETSTATUS:
+		case WDIOC_GETBOOTSTATUS:
+			return put_user(0, (int *)arg);
 		case WDIOC_KEEPALIVE:
-			next_heartbeat = jiffies + WDT_HEARTBEAT;
+			wdt_keepalive();
 			return 0;
+		case WDIOC_SETOPTIONS:
+		{
+			int new_options, retval = -EINVAL;
+
+			if(get_user(new_options, (int *)arg))
+				return -EFAULT;
+
+			if(new_options &amp; WDIOS_DISABLECARD) {
+				wdt_turnoff();
+				retval = 0;
+			}
+
+			if(new_options &amp; WDIOS_ENABLECARD) {
+				wdt_startup();
+				retval = 0;
+			}
+
+			return retval;
+		}
+		case WDIOC_SETTIMEOUT:
+		{
+			int new_timeout;
+
+			if(get_user(new_timeout, (int *)arg))
+				return -EFAULT;
+
+			if(new_timeout &lt; 1 || new_timeout &gt; 3600) /* arbitrary upper limit */
+				return -EINVAL;
+
+			timeout = new_timeout;
+			wdt_keepalive();
+			/* Fall through */
+		}
+		case WDIOC_GETTIMEOUT:
+			return put_user(timeout, (int *)arg);
 	}
 }
 
@@ -265,13 +312,13 @@
 	.write		= fop_write,
 	.open		= fop_open,
 	.release	= fop_close,
-	.ioctl		= fop_ioctl
+	.ioctl		= fop_ioctl,
 };
 
 static struct miscdevice wdt_miscdev = {
 	.minor	= WATCHDOG_MINOR,
 	.name	= "watchdog",
-	.fops	= &amp;wdt_fops
+	.fops	= &amp;wdt_fops,
 };
 
 /*
@@ -281,21 +328,21 @@
 static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
 	void *unused)
 {
-	if(code==SYS_DOWN || code==SYS_HALT) 
+	if(code==SYS_DOWN || code==SYS_HALT)
 		wdt_turnoff();
 	return NOTIFY_DONE;
 }
- 
+
 /*
  *	The WDT needs to learn about soft shutdowns in order to
- *	turn the timebomb registers off. 
+ *	turn the timebomb registers off.
  */
- 
+
 static struct notifier_block wdt_notifier=
 {
 	.notifier_call = wdt_notify_sys,
 	.next = NULL,
-	.priority = 0
+	.priority = 0,
 };
 
 static void __exit w83877f_wdt_unload(void)
@@ -316,10 +363,28 @@
 
 	spin_lock_init(&amp;wdt_spinlock);
 
+	if(timeout &lt; 1 || timeout &gt; 3600) /* arbitrary upper limit */
+	{
+		timeout = WATCHDOG_TIMEOUT;
+		printk(KERN_INFO PFX "timeout value must be 1&lt;=x&lt;=3600, using %d\n",
+			timeout);
+	}
+
 	if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT"))
+	{
+		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+			ENABLE_W83877F_PORT);
+		rc = -EIO;
 		goto err_out;
+	}
+
 	if (!request_region(WDT_PING, 1, "W8387FF WDT"))
+	{
+		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+			WDT_PING);
+		rc = -EIO;
 		goto err_out_region1;
+	}
 
 	init_timer(&amp;timer);
 	timer.function = wdt_timer_ping;
@@ -327,14 +392,23 @@
 
 	rc = misc_register(&amp;wdt_miscdev);
 	if (rc)
+	{
+		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+			wdt_miscdev.minor, rc);
 		goto err_out_region2;
+	}
 
 	rc = register_reboot_notifier(&amp;wdt_notifier);
 	if (rc)
+	{
+		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+			rc);
 		goto err_out_miscdev;
+	}
+
+	printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
+		timeout, nowayout);
 
-	printk(KERN_INFO OUR_NAME ": WDT driver for W83877F initialised.\n");
-	
 	return 0;
 
 err_out_miscdev:
diff -Nru a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
--- a/drivers/isdn/hisax/st5481_b.c	Sat Aug  9 16:58:28 2003
+++ b/drivers/isdn/hisax/st5481_b.c	Sat Aug  9 16:58:28 2003
@@ -254,7 +254,7 @@
 
 	DBG(4,"");
 
-	altsetting = &amp;(dev-&gt;config-&gt;interface[0].altsetting[3]);
+	altsetting = &amp;(dev-&gt;config-&gt;interface[0]-&gt;altsetting[3]);
 
 	// Allocate URBs and buffers for the B channel out
 	endpoint = &amp;altsetting-&gt;endpoint[EP_B1_OUT - 1 + bcs-&gt;channel * 2];
diff -Nru a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
--- a/drivers/isdn/hisax/st5481_d.c	Sat Aug  9 16:58:28 2003
+++ b/drivers/isdn/hisax/st5481_d.c	Sat Aug  9 16:58:28 2003
@@ -658,7 +658,7 @@
 
 	DBG(2,"");
 
-	altsetting = &amp;(dev-&gt;config-&gt;interface[0].altsetting[3]);
+	altsetting = &amp;(dev-&gt;config-&gt;interface[0]-&gt;altsetting[3]);
 
 	// Allocate URBs and buffers for the D channel out
 	endpoint = &amp;altsetting-&gt;endpoint[EP_D_OUT-1];
diff -Nru a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
--- a/drivers/isdn/hisax/st5481_usb.c	Sat Aug  9 16:58:28 2003
+++ b/drivers/isdn/hisax/st5481_usb.c	Sat Aug  9 16:58:28 2003
@@ -258,7 +258,7 @@
 	}
 
 	
-	altsetting = &amp;(dev-&gt;config-&gt;interface[0].altsetting[3]);	
+	altsetting = &amp;(dev-&gt;config-&gt;interface[0]-&gt;altsetting[3]);	
 
 	// Check if the config is sane
 	if ( altsetting-&gt;desc.bNumEndpoints != 7 ) {
diff -Nru a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
--- a/drivers/macintosh/Makefile	Sat Aug  9 16:58:28 2003
+++ b/drivers/macintosh/Makefile	Sat Aug  9 16:58:28 2003
@@ -4,6 +4,8 @@
 
 # Each configuration option enables a list of files.
 
+obj-$(CONFIG_PPC_PMAC)		+= macio_asic.o
+
 obj-$(CONFIG_PMAC_PBOOK)	+= mediabay.o
 obj-$(CONFIG_MAC_SERIAL)	+= macserial.o
 ifneq ($(CONFIG_MAC),y)
diff -Nru a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/macintosh/macio_asic.c	Sat Aug  9 16:58:28 2003
@@ -0,0 +1,358 @@
+/*
+ * Bus &amp; driver management routines for devices within
+ * a MacIO ASIC. Interface to new driver model mostly
+ * stolen from the PCI version.
+ * 
+ * TODO:
+ * 
+ *  - Don't probe below media bay by default, but instead provide
+ *    some hooks for media bay to dynamically add/remove it's own
+ *    sub-devices.
+ */
+ 
+#include &lt;linux/config.h&gt;
+#include &lt;linux/string.h&gt;
+#include &lt;linux/kernel.h&gt;
+#include &lt;linux/pci.h&gt;
+#include &lt;linux/pci_ids.h&gt;
+#include &lt;linux/init.h&gt;
+#include &lt;linux/module.h&gt;
+#include &lt;asm/machdep.h&gt;
+#include &lt;asm/macio.h&gt;
+#include &lt;asm/pmac_feature.h&gt;
+#include &lt;asm/prom.h&gt;
+#include &lt;asm/pci-bridge.h&gt;
+
+static int
+macio_bus_match(struct device *dev, struct device_driver *drv) 
+{
+	struct macio_dev * macio_dev = to_macio_device(dev);
+	struct macio_driver * macio_drv = to_macio_driver(drv);
+	const struct of_match * matches = macio_drv-&gt;match_table;
+
+	if (!matches) 
+		return 0;
+
+	return of_match_device(matches, &amp;macio_dev-&gt;ofdev) != NULL;
+}
+
+struct bus_type macio_bus_type = {
+       name:	"macio",
+       match:	macio_bus_match,
+};
+
+static int __init
+macio_bus_driver_init(void)
+{
+	return bus_register(&amp;macio_bus_type);
+}
+
+postcore_initcall(macio_bus_driver_init);
+
+static int
+macio_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct macio_driver *drv;
+	struct macio_dev *macio_dev;
+	const struct of_match *match;
+
+	drv = to_macio_driver(dev-&gt;driver);
+	macio_dev = to_macio_device(dev);
+
+	if (!drv-&gt;probe)
+		return error;
+
+/*	if (!try_module_get(driver-&gt;owner)) {
+		printk(KERN_ERR "Can't get a module reference for %s\n", driver-&gt;name);
+		return error;
+	}
+*/
+	match = of_match_device(drv-&gt;match_table, &amp;macio_dev-&gt;ofdev);
+	if (match)
+		error = drv-&gt;probe(macio_dev, match);
+/*
+ 	module_put(driver-&gt;owner);
+*/	
+	return error;
+}
+
+static int
+macio_device_remove(struct device *dev)
+{
+	struct macio_dev * macio_dev = to_macio_device(dev);
+	struct macio_driver * drv = to_macio_driver(macio_dev-&gt;ofdev.dev.driver);
+
+	if (drv &amp;&amp; drv-&gt;remove)
+		drv-&gt;remove(macio_dev);
+	return 0;
+}
+
+static int
+macio_device_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct macio_dev * macio_dev = to_macio_device(dev);
+	struct macio_driver * drv = to_macio_driver(macio_dev-&gt;ofdev.dev.driver);
+	int error = 0;
+
+	if (drv &amp;&amp; drv-&gt;suspend)
+		error = drv-&gt;suspend(macio_dev, state, level);
+	return error;
+}
+
+static int
+macio_device_resume(struct device * dev, u32 level)
+{
+	struct macio_dev * macio_dev = to_macio_device(dev);
+	struct macio_driver * drv = to_macio_driver(macio_dev-&gt;ofdev.dev.driver);
+	int error = 0;
+
+	if (drv &amp;&amp; drv-&gt;resume)
+		error = drv-&gt;resume(macio_dev, level);
+	return error;
+}
+
+/**
+ * macio_add_one_device - Add one device from OF node to the device tree
+ * @chip: pointer to the macio_chip holding the device
+ * @np: pointer to the device node in the OF tree
+ * @in_bay: set to 1 if device is part of a media-bay
+ *
+ * When media-bay is changed to hotswap drivers, this function will
+ * be exposed to the bay driver some way...
+ */
+static struct macio_dev *
+macio_add_one_device(struct macio_chip *chip, struct device *parent,
+		     struct device_node *np, struct macio_dev *in_bay)
+{
+	struct macio_dev *dev;
+	u32 *reg;
+	
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+	memset(dev, 0, sizeof(*dev));
+
+	dev-&gt;bus = &amp;chip-&gt;lbus;
+	dev-&gt;media_bay = in_bay;
+	dev-&gt;ofdev.node = np;
+	dev-&gt;ofdev.dma_mask = 0xffffffffUL;
+	dev-&gt;ofdev.dev.dma_mask = &amp;dev-&gt;ofdev.dma_mask;
+	dev-&gt;ofdev.dev.parent = parent;
+	dev-&gt;ofdev.dev.bus = &amp;macio_bus_type;
+
+	/* XXX Make something better here ? */
+	snprintf(dev-&gt;ofdev.dev.name, DEVICE_NAME_SIZE, "MacIO device %s", np-&gt;name);
+
+	/* MacIO itself has a different reg, we use it's PCI base */
+	if (np == chip-&gt;of_node) {
+		sprintf(dev-&gt;ofdev.dev.bus_id, "%1d.%08lx:%.8s", chip-&gt;lbus.index,
+#ifdef CONFIG_PCI
+			pci_resource_start(chip-&gt;lbus.pdev, 0),
+#else
+			0, /* NuBus may want to do something better here */
+#endif
+			np-&gt;name);
+	} else {
+		reg = (u32 *)get_property(np, "reg", NULL);
+		sprintf(dev-&gt;ofdev.dev.bus_id, "%1d.%08x:%.8s", chip-&gt;lbus.index,
+			reg ? *reg : 0, np-&gt;name);
+	}
+
+	if (of_device_register(&amp;dev-&gt;ofdev) != 0) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+static int
+macio_skip_device(struct device_node *np)
+{
+	if (strncmp(np-&gt;name, "battery", 7) == 0)
+		return 1;
+	if (strncmp(np-&gt;name, "escc-legacy", 11) == 0)
+		return 1;
+	return 0;
+}
+
+/**
+ * macio_pci_add_devices - Adds sub-devices of mac-io to the device tree
+ * @chip: pointer to the macio_chip holding the devices
+ * 
+ * This function will do the job of extracting devices from the
+ * Open Firmware device tree, build macio_dev structures and add
+ * them to the Linux device tree.
+ * 
+ * For now, childs of media-bay are added now as well. This will
+ * change rsn though.
+ */
+static void
+macio_pci_add_devices(struct macio_chip *chip)
+{
+	struct device_node *np;
+	struct macio_dev *rdev, *mdev, *mbdev = NULL, *sdev = NULL;
+	struct device *parent = NULL;
+	
+	/* Add a node for the macio bus itself */
+#ifdef CONFIG_PCI
+	if (chip-&gt;lbus.pdev)
+		parent = &amp;chip-&gt;lbus.pdev-&gt;dev;
+#endif		
+	rdev = macio_add_one_device(chip, parent, chip-&gt;of_node, NULL);
+	if (rdev == NULL)
+		return;
+
+	/* First scan 1st level */
+	for (np = chip-&gt;of_node-&gt;child; np != NULL; np = np-&gt;sibling) {
+		if (!macio_skip_device(np)) {
+			mdev = macio_add_one_device(chip, &amp;rdev-&gt;ofdev.dev, np, NULL);
+			if (strncmp(np-&gt;name, "media-bay", 9) == 0)
+				mbdev = mdev;
+			else if (strncmp(np-&gt;name, "escc", 4) == 0)
+				sdev = mdev;
+		}
+	}
+
+	/* Add media bay devices if any */
+	if (mbdev) {
+		for (np = mbdev-&gt;ofdev.node-&gt;child; np != NULL; np = np-&gt;sibling)
+			if (!macio_skip_device(np))
+				macio_add_one_device(chip, &amp;mbdev-&gt;ofdev.dev, np, mbdev);
+	}
+	/* Add serial ports if any */
+	if (sdev) {
+		for (np = sdev-&gt;ofdev.node-&gt;child; np != NULL; np = np-&gt;sibling)
+			if (!macio_skip_device(np))
+				macio_add_one_device(chip, &amp;sdev-&gt;ofdev.dev, np, NULL);
+	}
+}
+
+
+/**
+ * macio_register_driver - Registers a new MacIO device driver
+ * @drv: pointer to the driver definition structure
+ */
+int
+macio_register_driver(struct macio_driver *drv)
+{
+	int count = 0;
+
+	/* initialize common driver fields */
+	drv-&gt;driver.name = drv-&gt;name;
+	drv-&gt;driver.bus = &amp;macio_bus_type;
+	drv-&gt;driver.probe = macio_device_probe;
+	drv-&gt;driver.resume = macio_device_resume;
+	drv-&gt;driver.suspend = macio_device_suspend;
+	drv-&gt;driver.remove = macio_device_remove;
+
+	/* register with core */
+	count = driver_register(&amp;drv-&gt;driver);
+	return count ? count : 1;
+}
+
+/**
+ * macio_unregister_driver - Unregisters a new MacIO device driver
+ * @drv: pointer to the driver definition structure
+ */
+void
+macio_unregister_driver(struct macio_driver *drv)
+{
+	driver_unregister(&amp;drv-&gt;driver);
+}
+
+#ifdef CONFIG_PCI
+
+static int __devinit
+macio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct device_node* np;
+	struct macio_chip* chip;
+	
+	if (ent-&gt;vendor != PCI_VENDOR_ID_APPLE)
+		return -ENODEV;
+
+	np = pci_device_to_OF_node(pdev);
+	if (np == NULL)
+		return -ENODEV;
+
+	chip = macio_find(np, macio_unknown);
+	if (chip == NULL)
+		return -ENODEV;
+
+	/* XXX Need locking */
+	if (chip-&gt;lbus.pdev == NULL) {
+		chip-&gt;lbus.pdev = pdev;
+		chip-&gt;lbus.chip = chip;
+//		INIT_LIST_HEAD(&amp;chip-&gt;lbus.devices);
+		pci_set_drvdata(pdev, &amp;chip-&gt;lbus);
+		pci_set_master(pdev);
+	}
+
+	printk(KERN_INFO "MacIO PCI driver attached to %s chipset\n",
+		chip-&gt;name);
+
+	macio_pci_add_devices(chip);
+
+	return 0;
+}
+
+static void __devexit
+macio_pci_remove(struct pci_dev* pdev)
+{
+	panic("removing of macio-asic not supported !\n");
+}
+
+/*
+ * MacIO is matched against any Apple ID, it's probe() function
+ * will then decide wether it applies or not
+ */
+static const struct pci_device_id __devinitdata pci_ids [] = { {
+	.vendor =	PCI_VENDOR_ID_APPLE,
+	.device =	PCI_ANY_ID,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+
+	}, { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE (pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver macio_pci_driver = {
+	.name =		(char *) "macio",
+	.id_table =	pci_ids,
+
+	.probe =	macio_pci_probe,
+	.remove =	macio_pci_remove,
+};
+
+#endif /* CONFIG_PCI */
+
+static int __init
+macio_module_init (void) 
+{
+#ifdef CONFIG_PCI
+	int rc;
+
+	rc = pci_module_init(&amp;macio_pci_driver);
+	if (rc)
+		return rc;
+#endif /* CONFIG_PCI */
+	return 0;
+}
+
+/*
+static void __exit
+macio_module_cleanup (void) 
+{	
+#ifdef CONFIG_PCI
+	pci_unregister_driver(&amp;macio_pci_driver);
+#endif
+}
+module_exit(macio_module_cleanup);
+*/
+module_init(macio_module_init);
+
+EXPORT_SYMBOL(macio_register_driver);
+EXPORT_SYMBOL(macio_unregister_driver);
diff -Nru a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
--- a/drivers/video/cfbimgblt.c	Sat Aug  9 16:58:28 2003
+++ b/drivers/video/cfbimgblt.c	Sat Aug  9 16:58:28 2003
@@ -325,7 +325,7 @@
 		else 
 			slow_imageblit(image, p, dst1, fgcolor, bgcolor,
 					start_index, pitch_index);
-	} else if (image-&gt;depth == bpp) 
+	} else if (image-&gt;depth &lt;= bpp) 
 		color_imageblit(image, p, dst1, start_index, pitch_index);
 }
 
diff -Nru a/include/asm-ppc/macio.h b/include/asm-ppc/macio.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ppc/macio.h	Sat Aug  9 16:58:28 2003
@@ -0,0 +1,68 @@
+#ifndef __MACIO_ASIC_H__
+#define __MACIO_ASIC_H__
+
+#include &lt;asm/of_device.h&gt;
+
+extern struct bus_type macio_bus_type;
+
+/* MacIO device driver is defined later */
+struct macio_driver;
+struct macio_chip;
+
+#define MACIO_DEV_COUNT_RESOURCE	8
+#define MACIO_DEV_COUNT_IRQS		8
+
+/*
+ * the macio_bus structure is used to describe a "virtual" bus
+ * within a MacIO ASIC. It's typically provided by a macio_pci_asic
+ * PCI device, but could be provided differently as well (nubus
+ * machines using a fake OF tree).
+ * 
+ * The pdev field can be NULL on non-PCI machines
+ */
+struct macio_bus
+{
+	struct macio_chip	*chip;		/* macio_chip (private use) */
+	int			index;		/* macio chip index in system */
+#ifdef CONFIG_PCI
+	struct pci_dev		*pdev;		/* PCI device hosting this bus */
+#endif	
+};
+
+/*
+ * the macio_dev structure is used to describe a device
+ * within an Apple MacIO ASIC.
+ */
+struct macio_dev
+{
+	struct macio_bus	*bus;		/* macio bus this device is on */
+	struct macio_dev	*media_bay;	/* Device is part of a media bay */
+	struct of_device	ofdev;
+};
+#define	to_macio_device(d) container_of(d, struct macio_dev, ofdev.dev)
+#define	of_to_macio_device(d) container_of(d, struct macio_dev, ofdev)
+
+/*
+ * A driver for a mac-io chip based device
+ */
+struct macio_driver
+{
+	char			*name;
+	struct of_match		*match_table;
+	struct module		*owner;
+
+	int	(*probe)(struct macio_dev* dev, const struct of_match *match);
+	int	(*remove)(struct macio_dev* dev);
+
+	int	(*suspend)(struct macio_dev* dev, u32 state, u32 level);
+	int	(*resume)(struct macio_dev* dev, u32 level);
+	int	(*shutdown)(struct macio_dev* dev);
+
+	struct device_driver	driver;
+};
+#define	to_macio_driver(drv) container_of(drv,struct macio_driver, driver)
+
+extern int macio_register_driver(struct macio_driver *);
+extern void macio_unregister_driver(struct macio_driver *);
+
+#endif /* __MACIO_ASIC_H__ */
diff -Nru a/include/asm-ppc/macio_asic.h b/include/asm-ppc/macio_asic.h
--- a/include/asm-ppc/macio_asic.h	Sat Aug  9 16:58:28 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,80 +0,0 @@
-#ifndef __MACIO_ASIC_H__
-#define __MACIO_ASIC_H__
-
-#include &lt;linux/device.h&gt;
-
-extern struct bus_type macio_bus_type;
-
-/* MacIO device driver is defined later */
-struct macio_driver;
-struct macio_chip;
-
-#define MACIO_DEV_COUNT_RESOURCE	8
-#define MACIO_DEV_COUNT_IRQS		8
-
-/*
- * the macio_bus structure is used to describe a "virtual" bus
- * within a MacIO ASIC. It's typically provided by a macio_pci_asic
- * PCI device, but could be provided differently as well (nubus
- * machines using a fake OF tree).
- */
-struct macio_bus
-{
-	struct macio_chip	*chip;		/* macio_chip (private use) */
-	struct pci_dev		*pdev;		/* PCI device hosting this bus */
-	struct list_head	devices;	/* list of devices on this bus */
-};
-
-/*
- * the macio_dev structure is used to describe a device
- * within an Apple MacIO ASIC.
- */
-struct macio_dev
-{
-	struct macio_bus	*bus;		/* virtual bus this device is on */
-
-	struct device_node	*node;		/* OF node */	
-	struct macio_driver	*driver;	/* which driver allocated this device */
-	void			*driver_data;	/* placeholder for driver specific stuffs */
-	struct resource		resources[MACIO_DEV_COUNT_RESOURCE]; /* I/O */
-	int			irqs[MACIO_DEV_COUNT_IRQS];
-	
-	struct device		dev;		/* Generic device interface */
-};
-#define	to_macio_device(d) container_of(d, struct macio_dev, dev)
-
-/*
- * Struct used for matching a device
- */
-struct macio_match
-{
-	char	*name;
-	char	*type;
-	char	*compatible;
-};
-#define MACIO_ANY_MATCH		((char *)-1L)
-
-/*
- * A driver for a mac-io chip based device
- */
-struct macio_driver
-{
-	struct list_head	node;
-	char			*name;
-	struct macio_match	*match_table;
-
-	int	(*probe)(struct macio_dev* dev, const struct macio_match *match);
-	int	(*remove)(struct macio_dev* dev);
-
-	int	(*suspend)(struct macio_dev* dev, u32 state, u32 level);
-	int	(*resume)(struct macio_dev* dev, u32 level);
-	int	(*shutdown)(struct macio_dev* dev);
-
-	struct device_driver	driver;
-};
-#define	to_macio_driver(drv) container_of(drv,struct macio_driver, driver)
-
-extern int macio_register_driver(struct macio_driver *);
-extern void macio_unregister_driver(struct macio_driver *);
-
-#endif /* __MACIO_ASIC_H__ */
diff -Nru a/include/asm-ppc/of_device.h b/include/asm-ppc/of_device.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ppc/of_device.h	Sat Aug  9 16:58:28 2003
@@ -0,0 +1,70 @@
+#ifndef __OF_DEVICE_H__
+#define __OF_DEVICE_H__
+
+#include &lt;linux/device.h&gt;
+#include &lt;asm/prom.h&gt;
+
+/* 
+ * The of_platform_bus_type is a bus type used by drivers that do not
+ * attach to a macio or similar bus but still use OF probing
+ * mecanism
+ */
+extern struct bus_type of_platform_bus_type;
+
+/* 
+ * The of_device is a kind of "base class" that is a superset of
+ * struct device for use by devices attached to an OF node and
+ * probed using OF properties
+ */
+struct of_device
+{
+	struct device_node	*node;		/* OF device node */
+	u64			dma_mask;	/* DMA mask */
+	struct device		dev;		/* Generic device interface */
+};
+#define	to_of_device(d) container_of(d, struct of_device, dev)
+
+/*
+ * Struct used for matching a device
+ */
+struct of_match
+{
+	char	*name;
+	char	*type;
+	char	*compatible;
+	void	*data;
+};
+#define OF_ANY_MATCH		((char *)-1L)
+
+extern const struct of_match *of_match_device(
+	const struct of_match *matches, const struct of_device *dev);
+
+/*
+ * An of_platform_driver driver is attached to a basic of_device on
+ * the "platform bus" (of_platform_bus_type)
+ */
+struct of_platform_driver
+{
+	char			*name;
+	struct of_match		*match_table;
+	struct module		*owner;
+
+	int	(*probe)(struct of_device* dev, const struct of_match *match);
+	int	(*remove)(struct of_device* dev);
+
+	int	(*suspend)(struct of_device* dev, u32 state, u32 level);
+	int	(*resume)(struct of_device* dev, u32 level);
+	int	(*shutdown)(struct of_device* dev);
+
+	struct device_driver	driver;
+};
+#define	to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver)
+
+extern int of_register_driver(struct of_platform_driver *drv);
+extern void of_unregister_driver(struct of_platform_driver *drv);
+extern int of_device_register(struct of_device *ofdev);
+extern void of_device_unregister(struct of_device *ofdev);
+extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id);
+
+#endif /* __OF_DEVICE_H__ */
+
diff -Nru a/include/asm-ppc/pmac_feature.h b/include/asm-ppc/pmac_feature.h
--- a/include/asm-ppc/pmac_feature.h	Sat Aug  9 16:58:28 2003
+++ b/include/asm-ppc/pmac_feature.h	Sat Aug  9 16:58:28 2003
@@ -31,7 +31,7 @@
 #ifndef __PPC_ASM_PMAC_FEATURE_H
 #define __PPC_ASM_PMAC_FEATURE_H
 
-#include &lt;asm/macio_asic.h&gt;
+#include &lt;asm/macio.h&gt;
 
 /*
  * Known Mac motherboard models
</pre></body></html>