Index: src/southbridge/via/vt8237r/vt8237r_lpc.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_lpc.c	(revision 2975)
+++ src/southbridge/via/vt8237r/vt8237r_lpc.c	(working copy)
@@ -145,8 +145,12 @@
  * Set up the power management capabilities directly into ACPI mode.
  * This avoids having to handle any System Management Interrupts (SMIs).
  */
+ 
+ u8 acpi_sleep_type;
+ 
 static void setup_pm(device_t dev)
 {
+	u16 tmp;
 	/* Debounce LID and PWRBTN# Inputs for 16ms. */
 	pci_write_config8(dev, 0x80, 0x20);
 
@@ -219,8 +223,12 @@
 	/* Disable extended IO traps. */
 	outb(0x0, VT8237R_ACPI_IO_BASE + 0x42);
 
+	tmp = inw(VT8237R_ACPI_IO_BASE + 0x04);
+	acpi_sleep_type = ((tmp & (7 << 10)) >> 10) == 1 ? 3 : 0 ;
+	printk_debug("SLEEP type was %x %x\n", tmp, acpi_sleep_type);
 	/* SCI is generated for RTC/pwrBtn/slpBtn. */
-	outw(0x001, VT8237R_ACPI_IO_BASE + 0x04);
+	tmp |= 1;
+	outw(tmp, VT8237R_ACPI_IO_BASE + 0x04);
 
 	/* FIXME: Intel needs more bit set for C2/C3. */
 
Index: src/cpu/amd/model_fxx/fidvid.c
===================================================================
--- src/cpu/amd/model_fxx/fidvid.c	(revision 2975)
+++ src/cpu/amd/model_fxx/fidvid.c	(working copy)
@@ -71,7 +71,7 @@
 //		dword = 0x00070000; //enable FID/VID change
                 pci_write_config32(PCI_DEV(0, 0x18+i, 3), 0x80, dword);
 
-                dword = 0x00132113;
+                dword = 0x61133113;
                 pci_write_config32(PCI_DEV(0, 0x18+i, 3), 0x84, dword);
 
 	}
Index: src/mainboard/asus/a8v-e_se/Config.lb
===================================================================
--- src/mainboard/asus/a8v-e_se/Config.lb	(revision 2975)
+++ src/mainboard/asus/a8v-e_se/Config.lb	(working copy)
@@ -63,6 +63,7 @@
 ##
 
 driver mainboard.o
+driver wakeup.o
 
 if HAVE_ACPI_TABLES
         object acpi_tables.o
Index: src/mainboard/asus/a8v-e_se/acpi_tables.c
===================================================================
--- src/mainboard/asus/a8v-e_se/acpi_tables.c	(revision 2975)
+++ src/mainboard/asus/a8v-e_se/acpi_tables.c	(working copy)
@@ -109,6 +109,7 @@
 	current += sizeof(acpi_rsdt_t);
 
 	/* clear all table memory */
+
 	memset((void *) start, 0, current - start);
 
 	acpi_write_rsdp(rsdp, rsdt);
@@ -167,3 +168,10 @@
 	printk_info("ACPI: done.\n");
 	return current;
 }
+
+extern u32 wake_vec;
+extern u8 acpi_sleep_type;
+
+int acpi_is_wakeup(void) {
+	return (acpi_sleep_type == 3);
+}
Index: src/mainboard/asus/a8v-e_se/dsdt.asl
===================================================================
--- src/mainboard/asus/a8v-e_se/dsdt.asl	(revision 2975)
+++ src/mainboard/asus/a8v-e_se/dsdt.asl	(working copy)
@@ -44,6 +44,7 @@
 	 */
 	Name (\_S0, Package () {0x00, 0x00, 0x00, 0x00 })
 	Name (\_S5, Package () {0x02, 0x02, 0x00, 0x00 })
+	Name (\_S3, Package () {0x01, 0x01, 0x00, 0x00 })
 
 	/* Root of the bus hierarchy */
 	Scope (\_SB)
Index: src/mainboard/asus/a8v-e_se/wakeup.c
===================================================================
--- src/mainboard/asus/a8v-e_se/wakeup.c	(revision 0)
+++ src/mainboard/asus/a8v-e_se/wakeup.c	(revision 0)
@@ -0,0 +1,262 @@
+//reboot.c from linux
+
+#include <stdint.h>
+#include <string.h>
+#include <arch/io.h>
+
+
+
+int enable_a20(void);
+
+/* The following code and data reboots the machine by switching to real
+   mode and jumping to the BIOS reset entry point, as if the CPU has
+   really been reset.  The previous version asked the keyboard
+   controller to pulse the CPU reset line, which is more thorough, but
+   doesn't work with at least one type of 486 motherboard.  It is easy
+   to stop this code working; hence the copious comments. */
+
+static unsigned long long
+real_mode_gdt_entries [3] =
+{
+	0x0000000000000000ULL,	/* Null descriptor */
+	0x00009a000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
+	0x000092000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
+};
+
+struct Xgt_desc_struct {
+         unsigned short size;
+         unsigned long address __attribute__((packed));
+         unsigned short pad;
+ } __attribute__ ((packed));
+
+static struct Xgt_desc_struct
+real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
+real_mode_idt = { 0x3ff, 0 },
+no_idt = { 0, 0 };
+
+
+/* This is 16-bit protected mode code to disable paging and the cache,
+   switch to real mode and jump to the BIOS reset code.
+
+   The instruction that switches to real mode by writing to CR0 must be
+   followed immediately by a far jump instruction, which set CS to a
+   valid value for real mode, and flushes the prefetch queue to avoid
+   running instructions that have already been decoded in protected
+   mode.
+
+   Clears all the flags except ET, especially PG (paging), PE
+   (protected-mode enable) and TS (task switch for coprocessor state
+   save).  Flushes the TLB after paging has been disabled.  Sets CD and
+   NW, to disable the cache on a 486, and invalidates the cache.  This
+   is more like the state of a 486 after reset.  I don't know if
+   something else should be done for other chips.
+
+   More could be done here to set up the registers as if a CPU reset had
+   occurred; hopefully real BIOSs don't assume much. */
+
+
+//	0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,	/*    orl   $0x60000000,%eax */
+
+static unsigned char real_mode_switch [] =
+{
+	0x66, 0x0f, 0x20, 0xc0,			/*    movl  %cr0,%eax        */
+	0x24, 0x10,				/*    andb  $0x10,al         */
+	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
+};
+static unsigned char jump_to_wakeup [] =
+{
+	0xea, 0x00, 0x00, 0xff, 0xff		/*    ljmp  $0xffff,$0x0000  */
+};
+
+/*
+ * Switch to real mode and then execute the code
+ * specified by the code and length parameters.
+ * We assume that length will aways be less that 100!
+ */ 
+ 
+void acpi_jump_wake(u32 vector)
+{
+u8 tmp;
+	if (enable_a20())
+		die("failed to enable A20\n");
+	
+	* ((u32 *) (jump_to_wakeup+1)) = vector;
+	memcpy ((void *) (0x1000 - sizeof (real_mode_switch) - 100),
+		real_mode_switch, sizeof (real_mode_switch));
+	memcpy ((void *) (0x1000 - 100), jump_to_wakeup, sizeof(jump_to_wakeup));
+
+	/* Set up the IDT for real mode. */
+
+	asm volatile("lidt %0"::"m" (real_mode_idt));
+	
+	/* Set up a GDT from which we can load segment descriptors for real
+	   mode.  The GDT is not used in real mode; it is just needed here to
+	   prepare the descriptors. */
+
+	asm volatile("lgdt %0"::"m" (real_mode_gdt));
+
+	/* Load the data segment registers, and thus the descriptors ready for
+	   real mode.  The base address of each segment is 0x100, 16 times the
+	   selector value being loaded here.  This is so that the segment
+	   registers don't have to be reloaded after switching to real mode:
+	   the values are consistent for real mode operation already. */
+
+	__asm__ __volatile__ ("movl $0x0010,%%eax\n"
+				"\tmovl %%eax,%%ds\n"
+				"\tmovl %%eax,%%es\n"
+				"\tmovl %%eax,%%fs\n"
+				"\tmovl %%eax,%%gs\n"
+				"\tmovl %%eax,%%ss" : : : "eax");
+
+	/* Jump to the 16-bit code that we copied earlier.  It disables paging
+	   and the cache, switches to real mode, and jumps to the BIOS reset
+	   entry point. */
+
+	__asm__ __volatile__ ("ljmp $0x0008,%0"
+				:
+				: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
+}
+
+
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/a20.c
+ *
+ * Enable A20 gate (return -1 on failure)
+ */
+
+//#include "boot.h"
+
+#define MAX_8042_LOOPS	100000
+
+static int empty_8042(void)
+{
+	u8 status;
+	int loops = MAX_8042_LOOPS;
+
+	while (loops--) {
+		udelay(1);
+
+		status = inb(0x64);
+		if (status & 1) {
+			/* Read and discard input data */
+			udelay(1);
+			(void)inb(0x60);
+		} else if (!(status & 2)) {
+			/* Buffers empty, finished! */
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+/* Returns nonzero if the A20 line is enabled.  The memory address
+   used as a test is the int $0x80 vector, which should be safe. */
+
+#define A20_TEST_ADDR	(4*0x80)
+#define A20_TEST_SHORT  32
+#define A20_TEST_LONG	2097152	/* 2^21 */
+
+static int a20_test(int loops)
+{
+	int ok = 0;
+	int saved, ctr;
+
+//	set_fs(0x0000);
+//	set_gs(0xffff);
+
+	saved = ctr =  *((u32*) A20_TEST_ADDR);
+
+	while (loops--) {
+		//wrfs32(++ctr, A20_TEST_ADDR);
+		
+		*((u32*) A20_TEST_ADDR) = ++ctr;
+		
+		udelay(1);	/* Serialize and make delay constant */
+		
+		ok = *((u32 *) A20_TEST_ADDR+0xffff0+0x10) ^ ctr;
+		if (ok)
+			break;
+	}
+
+	*((u32*) A20_TEST_ADDR) = saved;
+	return ok;
+}
+
+/* Quick test to see if A20 is already enabled */
+static int a20_test_short(void)
+{
+	return a20_test(A20_TEST_SHORT);
+}
+
+/* Longer test that actually waits for A20 to come on line; this
+   is useful when dealing with the KBC or other slow external circuitry. */
+static int a20_test_long(void)
+{
+	return a20_test(A20_TEST_LONG);
+}
+
+static void enable_a20_kbc(void)
+{
+	empty_8042();
+
+	outb(0xd1, 0x64);	/* Command write */
+	empty_8042();
+
+	outb(0xdf, 0x60);	/* A20 on */
+	empty_8042();
+}
+
+static void enable_a20_fast(void)
+{
+	u8 port_a;
+
+	port_a = inb(0x92);	/* Configuration port A */
+	port_a |=  0x02;	/* Enable A20 */
+	port_a &= ~0x01;	/* Do not reset machine */
+	outb(port_a, 0x92);
+}
+
+/*
+ * Actual routine to enable A20; return 0 on ok, -1 on failure
+ */
+
+#define A20_ENABLE_LOOPS 255	/* Number of times to try */
+
+int enable_a20(void)
+{
+	int loops = A20_ENABLE_LOOPS;
+
+	while (loops--) {
+		/* First, check to see if A20 is already enabled
+		   (legacy free, etc.) */
+		if (a20_test_short())
+			return 0;
+
+		/* Try enabling A20 through the keyboard controller */
+		empty_8042();
+//if (a20_test_short())
+//	return 0; /* BIOS worked, but with delayed reaction */
+
+		enable_a20_kbc();
+		if (a20_test_long())
+			return 0;
+
+		/* Finally, try enabling the "fast A20 gate" */
+		enable_a20_fast();
+		if (a20_test_long())
+			return 0;
+	}
+
+	return -1;
+}
Index: src/boot/hardwaremain.c
===================================================================
--- src/boot/hardwaremain.c	(revision 2975)
+++ src/boot/hardwaremain.c	(working copy)
@@ -46,6 +46,9 @@
  * Device Enumeration:
  *	In the dev_enumerate() phase, 
  */
+ 
+ extern u32 wake_vec;
+ 
 void hardwaremain(int boot_complete)
 {
 	struct lb_memory *lb_mem;
@@ -87,7 +90,8 @@
 	 * write our configuration tables.
 	 */
 	lb_mem = write_tables();
-
+	if (wake_vec)
+		acpi_jump_wake(wake_vec);
 #if CONFIG_FS_PAYLOAD == 1
 	filo(lb_mem);
 #else
Index: src/arch/i386/boot/tables.c
===================================================================
--- src/arch/i386/boot/tables.c	(revision 2975)
+++ src/arch/i386/boot/tables.c	(working copy)
@@ -60,6 +60,7 @@
 	/* write them in the rom area because DSDT can be large (8K on epia-m) which
 	 * pushes linuxbios table out of first 4K if set up in low table area 
 	 */
+	
 	rom_table_end = write_acpi_tables(rom_table_end);
 	rom_table_end = (rom_table_end+1023) & ~1023;
 
Index: src/arch/i386/boot/acpi.c
===================================================================
--- src/arch/i386/boot/acpi.c	(revision 2975)
+++ src/arch/i386/boot/acpi.c	(working copy)
@@ -293,14 +293,28 @@
 	header->checksum	= acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
 }
 
+u32 wake_vec;
+
 void acpi_create_facs(acpi_facs_t *facs)
 {
+	if (acpi_is_wakeup()) {
+		wake_vec = facs->firmware_waking_vector;
+		printk_debug("OS waking vector is %x\n", wake_vec);
+	}
+	
 	memset( (void *)facs,0, sizeof(acpi_facs_t));
 
 	memcpy(facs->signature,"FACS",4);
 	facs->length = sizeof(acpi_facs_t);
 	facs->hardware_signature = 0;
-	facs->firmware_waking_vector = 0;
+	
+	if (wake_vec) {
+		facs->firmware_waking_vector = wake_vec;
+	} else {
+			facs->firmware_waking_vector = 0;
+			wake_vec = 0;
+	}
+	
 	facs->global_lock = 0;
 	facs->flags = 0;
 	facs->x_firmware_waking_vector_l = 0;

