diff -ruNp 836-core-driver-model-old/kernel/power/suspend2_core/driver_model.c 836-core-driver-model-new/kernel/power/suspend2_core/driver_model.c
--- 836-core-driver-model-old/kernel/power/suspend2_core/driver_model.c	1970-01-01 10:00:00.000000000 +1000
+++ 836-core-driver-model-new/kernel/power/suspend2_core/driver_model.c	2004-12-04 17:09:52.394093472 +1100
@@ -0,0 +1,226 @@
+/*
+ * kernel/power/device.c
+ *
+ * Copyright (C) 2004 Nigel Cunningham <ncunningham@linuxmail.org>
+ *
+ * This file is released under the GPLv2.
+ *
+ * Support for the driver model and ACPI sleep states.
+ */
+
+//#define DEBUG_DEVICE_TREE
+
+#include <linux/device.h>
+#include <linux/reboot.h>
+#include <linux/suspend.h>
+#include <linux/pm.h>
+#include <linux/err.h>
+#include "driver_model.h"
+#include "suspend.h"
+
+unsigned long suspend_powerdown_method = 5; /* S5 = off */
+static int suspend_acpi_state_used = 0;
+
+extern struct pm_ops * pm_ops;
+static u32 pm_disk_mode_save;
+
+struct partial_device_tree * suspend_device_tree;
+EXPORT_SYMBOL_GPL(suspend_device_tree);
+
+
+#ifdef CONFIG_ACPI
+extern u32 acpi_leave_sleep_state (u8 sleep_state);
+#endif
+
+void suspend_drivers_resume(int stage)
+{
+	switch (stage) {
+		case SUSPEND_DRIVERS_USED_DEVICES_IRQS_DISABLED:
+			BUG_ON(!irqs_disabled());
+			if (!TEST_ACTION_STATE(SUSPEND_DISABLE_SYSDEV_SUPPORT))
+				sysdev_resume();
+			dpm_power_up_tree(suspend_device_tree);
+			break;
+
+		case SUSPEND_DRIVERS_USED_DEVICES_IRQS_ENABLED:
+			BUG_ON(irqs_disabled());
+			device_resume_tree(suspend_device_tree);
+			break;
+
+		case SUSPEND_DRIVERS_UNUSED_DEVICES_IRQS_DISABLED:
+			BUG_ON(!irqs_disabled());
+			dpm_power_up_tree(&default_device_tree);
+			break;
+
+		case SUSPEND_DRIVERS_UNUSED_DEVICES_IRQS_ENABLED:
+			BUG_ON(irqs_disabled());
+			device_resume_tree(&default_device_tree);
+#ifdef CONFIG_ACPI
+			if (suspend_acpi_state_used)
+				acpi_leave_sleep_state(suspend_acpi_state_used);
+#endif
+			device_resume_tree(&default_device_tree);
+#ifdef CONFIG_ACPI
+			if (suspend_acpi_state_used &&
+				pm_ops && pm_ops->finish)
+				pm_ops->finish(suspend_acpi_state_used);
+#endif
+			break;
+	}
+}
+
+/*	suspend_drivers_suspend
+ *	@stage - one of:
+ *		1: Power down drivers not used in writing the image
+ *		2: Quiesce drivers used in writing the image
+ *		   (prior to making atomic copy)
+ *		3: Power down drivers used in writing the image and
+ *		   enter the suspend mode if configured to do so.
+ *
+ */
+int suspend_drivers_suspend(int stage)
+{
+	int result = 0;
+
+	switch (stage) {
+		case SUSPEND_DRIVERS_UNUSED_DEVICES_IRQS_DISABLED:
+			BUG_ON(!irqs_disabled());
+			result = device_power_down_tree(
+				PM_SUSPEND_DISK, &default_device_tree);
+			break;
+
+		case SUSPEND_DRIVERS_UNUSED_DEVICES_IRQS_ENABLED:
+			BUG_ON(irqs_disabled());
+			result = device_suspend_tree(
+					PM_SUSPEND_DISK, &default_device_tree);
+			break;
+
+		case SUSPEND_DRIVERS_USED_DEVICES_IRQS_DISABLED:
+			BUG_ON(!irqs_disabled());
+			result = device_power_down_tree(PM_SUSPEND_DISK, suspend_device_tree);
+			if (!TEST_ACTION_STATE(SUSPEND_DISABLE_SYSDEV_SUPPORT))
+				sysdev_suspend(PM_SUSPEND_DISK);
+			break;
+
+		case SUSPEND_DRIVERS_USED_DEVICES_IRQS_ENABLED:
+			BUG_ON(irqs_disabled());
+			result = device_suspend_tree(
+					PM_SUSPEND_DISK, suspend_device_tree);
+			break;
+
+		case SUSPEND_DRIVERS_PRE_POWERDOWN: /* Power down system */
+			BUG_ON(irqs_disabled());
+			break;
+	}
+	return result;
+}
+
+void suspend_drivers_cleanup(void)
+{
+	if (pm_ops) pm_ops->pm_disk_mode = pm_disk_mode_save;
+			
+	if (suspend_device_tree) {
+		device_merge_tree(suspend_device_tree, &default_device_tree);
+		device_destroy_tree(suspend_device_tree);
+		suspend_device_tree = NULL;
+	}
+}
+
+int suspend_drivers_init(void)
+{
+	struct class * class;
+	struct class_device * class_dev;
+
+	if (pm_ops) {
+		pm_disk_mode_save = pm_ops->pm_disk_mode;
+		pm_ops->pm_disk_mode = PM_DISK_PLATFORM;
+	}
+			
+	BUG_ON(suspend_device_tree);
+	suspend_device_tree = device_create_tree();
+	if (IS_ERR(suspend_device_tree)) {
+		suspend_device_tree = NULL;
+		return -ENOMEM;
+	}
+	
+	/* Now check for graphics class devices, so we can keep the display on while suspending */
+	class = class_find("graphics");
+	if (class) {
+		list_for_each_entry(class_dev, &class->children, node)
+			device_switch_trees(class_dev->dev, suspend_device_tree);
+		class_put(class);
+	}
+
+	return 0;
+}
+
+static void suspend_enter_acpi_state(u32 state)
+{
+	suspend_acpi_state_used = state;
+
+	if (pm_ops && pm_ops->prepare) {
+		if (!pm_ops->prepare(state)) {
+			if (pm_ops && pm_ops->enter)
+				pm_ops->enter(state);
+			else 
+				printk("Failed to enter state.\n");
+		} else
+			printk("Prepare ops failed.\n");
+	} else
+		printk("No prepare ops.\n");
+}
+
+extern asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user * arg);
+
+static void suspend_power_off(void)
+{
+	sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+			LINUX_REBOOT_CMD_POWER_OFF, NULL);
+
+	prepare_status(1, 0, "Probably not capable for powerdown.");
+	while (1)
+		cpu_relax();
+	/* NOTREACHED */
+}
+
+/*
+ * suspend_power_down
+ * Functionality   : Powers down or reboots the computer once the image
+ *                   has been written to disk.
+ * Key Assumptions : Able to reboot/power down via code called or that
+ *                   the warning emitted if the calls fail will be visible
+ *                   to the user (ie printk resumes devices).
+ * Called From     : do_suspend2_suspend_2
+ */
+
+extern void apm_power_off(void);
+
+void suspend_power_down(void)
+{
+	if (TEST_ACTION_STATE(SUSPEND_REBOOT)) {
+		prepare_status(1, 0, "Ready to reboot.");
+		sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+				LINUX_REBOOT_CMD_RESTART, NULL);
+	}
+
+	suspend_drivers_suspend(SUSPEND_DRIVERS_PRE_POWERDOWN);
+
+	if (suspend_powerdown_method == 3) {
+		prepare_status(1, 0, "Seeking to suspend-to-ram.");
+		suspend_enter_acpi_state(PM_SUSPEND_MEM);
+		prepare_status(1, 0, "Entering S3 failed. Using normal powerdown.");
+	} else if (suspend_powerdown_method == 4) {
+		prepare_status(1, 0, "Seeking to enter ACPI suspend-to-disk state.");
+		suspend_enter_acpi_state(PM_SUSPEND_DISK);
+		prepare_status(1, 0, "Entering S4 failed. Using normal powerdown.");
+	} else
+		prepare_status(1, 0, "Powering down.");
+	
+	/* 
+	 * FIXME: At resume, we'll still think we used S4 if we tried it.
+	 * Does it matter?
+	 */
+	suspend_acpi_state_used = 0;
+	suspend_power_off();
+}
+
