[coreboot] Patch RE: coreboot for C3/CN400 (Luke) - Long Lines Fixed

Harrison, Jon (SELEX GALILEO, UK) jon.harrison at selexgalileo.com
Wed Jun 24 14:44:30 CEST 2009


Sorry Long lines were wrapped in last post

Index: src/include/device/pci_ids.h
===================================================================
--- src/include/device/pci_ids.h	(revision 1)
+++ src/include/device/pci_ids.h	(working copy)
@@ -1198,6 +1198,14 @@
 #define PCI_DEVICE_ID_VIA_CN700_VLINK	0x7314
 #define PCI_DEVICE_ID_VIA_CN700_BRIDGE	0xB198
 #define PCI_DEVICE_ID_VIA_CN700_VGA	0x3344
+#define PCI_DEVICE_ID_VIA_CN400_AGP	0x0259
+#define PCI_DEVICE_ID_VIA_CN400_ERR	0x1259
+#define PCI_DEVICE_ID_VIA_CN400_HOST	0x2259
+#define PCI_DEVICE_ID_VIA_CN400_MEMCTRL	0x3259
+#define PCI_DEVICE_ID_VIA_CN400_PM	0x4259
+#define PCI_DEVICE_ID_VIA_CN400_VLINK	0x7259
+#define PCI_DEVICE_ID_VIA_CN400_BRIDGE	0xB198
+#define PCI_DEVICE_ID_VIA_CN400_VGA	0x3118
 
 #define PCI_VENDOR_ID_SIEMENS           0x110A
 #define PCI_DEVICE_ID_SIEMENS_DSCC4     0x2102
Index: src/mainboard/via/epia-n/dsdt.c
===================================================================
--- src/mainboard/via/epia-n/dsdt.c	(revision 0)
+++ src/mainboard/via/epia-n/dsdt.c	(revision 0)
@@ -0,0 +1,142 @@
+/*
+ * 
+ * Intel ACPI Component Architecture
+ * ASL Optimizing Compiler version 20060127 [Apr 23 2006]
+ * Copyright (C) 2000 - 2006 Intel Corporation
+ * Supports ACPI Specification Revision 3.0a
+ * 
+ * Compilation of "dsdt.asl" - Wed Sep  6 11:36:08 2006
+ * 
+ * C source code output
+ *
+ */
+unsigned char AmlCode[] =
+{
+    0x44,0x53,0x44,0x54,0xF0,0x03,0x00,0x00,  /* 00000000    "DSDT...."
*/
+    0x01,0x03,0x4C,0x58,0x42,0x49,0x4F,0x53,  /* 00000008    "..LXBIOS"
*/
+    0x4C,0x58,0x42,0x2D,0x44,0x53,0x44,0x54,  /* 00000010    "LXB-DSDT"
*/
+    0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL"
*/
+    0x27,0x01,0x06,0x20,0x10,0x12,0x5F,0x50,  /* 00000020    "'.. .._P"
*/
+    0x52,0x5F,0x5B,0x83,0x0B,0x43,0x50,0x55,  /* 00000028    "R_[..CPU"
*/
+    0x30,0x00,0x10,0x04,0x00,0x00,0x06,0x08,  /* 00000030    "0......."
*/
+    0x5F,0x53,0x30,0x5F,0x12,0x06,0x04,0x00,  /* 00000038    "_S0_...."
*/
+    0x00,0x00,0x00,0x08,0x5F,0x53,0x35,0x5F,  /* 00000040    "...._S5_"
*/
+    0x12,0x08,0x04,0x0A,0x02,0x0A,0x02,0x00,  /* 00000048    "........"
*/
+    0x00,0x10,0x4E,0x39,0x5F,0x53,0x42,0x5F,  /* 00000050    "..N9_SB_"
*/
+    0x5B,0x82,0x44,0x06,0x4C,0x4E,0x4B,0x41,  /* 00000058    "[.D.LNKA"
*/
+    0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,  /* 00000060    "._HID.A."
*/
+    0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x01,  /* 00000068    "..._UID."
*/
+    0x14,0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,  /* 00000070    ".._STA.."
*/
+    0x0A,0x0B,0x14,0x1A,0x5F,0x43,0x52,0x53,  /* 00000078    "...._CRS"
*/
+    0x00,0x08,0x42,0x55,0x46,0x46,0x11,0x09,  /* 00000080    "..BUFF.."
*/
+    0x0A,0x06,0x23,0x20,0x00,0x18,0x79,0x00,  /* 00000088    "..# ..y."
*/
+    0xA4,0x42,0x55,0x46,0x46,0x14,0x1A,0x5F,  /* 00000090    ".BUFF.._"
*/
+    0x50,0x52,0x53,0x00,0x08,0x42,0x55,0x46,  /* 00000098    "PRS..BUF"
*/
+    0x46,0x11,0x09,0x0A,0x06,0x23,0x20,0x06,  /* 000000A0    "F....# ."
*/
+    0x18,0x79,0x00,0xA4,0x42,0x55,0x46,0x46,  /* 000000A8    ".y..BUFF"
*/
+    0x14,0x06,0x5F,0x53,0x52,0x53,0x01,0x14,  /* 000000B0    ".._SRS.."
*/
+    0x06,0x5F,0x44,0x49,0x53,0x00,0x5B,0x82,  /* 000000B8    "._DIS.[."
*/
+    0x45,0x06,0x4C,0x4E,0x4B,0x42,0x08,0x5F,  /* 000000C0    "E.LNKB._"
*/
+    0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,  /* 000000C8    "HID.A..."
*/
+    0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,  /* 000000D0    "._UID..."
*/
+    0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,  /* 000000D8    "._STA..."
*/
+    0x0B,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00,  /* 000000E0    "..._CRS."
*/
+    0x08,0x42,0x55,0x46,0x46,0x11,0x09,0x0A,  /* 000000E8    ".BUFF..."
*/
+    0x06,0x23,0x00,0x02,0x18,0x79,0x00,0xA4,  /* 000000F0    ".#...y.."
*/
+    0x42,0x55,0x46,0x46,0x14,0x1A,0x5F,0x50,  /* 000000F8    "BUFF.._P"
*/
+    0x52,0x53,0x00,0x08,0x42,0x55,0x46,0x46,  /* 00000100    "RS..BUFF"
*/
+    0x11,0x09,0x0A,0x06,0x23,0x20,0x06,0x18,  /* 00000108    "....# .."
*/
+    0x79,0x00,0xA4,0x42,0x55,0x46,0x46,0x14,  /* 00000110    "y..BUFF."
*/
+    0x06,0x5F,0x53,0x52,0x53,0x01,0x14,0x06,  /* 00000118    "._SRS..."
*/
+    0x5F,0x44,0x49,0x53,0x00,0x5B,0x82,0x45,  /* 00000120    "_DIS.[.E"
*/
+    0x06,0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48,  /* 00000128    ".LNKC._H"
*/
+    0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,  /* 00000130    "ID.A...."
*/
+    0x5F,0x55,0x49,0x44,0x0A,0x03,0x14,0x09,  /* 00000138    "_UID...."
*/
+    0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0B,  /* 00000140    "_STA...."
*/
+    0x14,0x1A,0x5F,0x43,0x52,0x53,0x00,0x08,  /* 00000148    ".._CRS.."
*/
+    0x42,0x55,0x46,0x46,0x11,0x09,0x0A,0x06,  /* 00000150    "BUFF...."
*/
+    0x23,0x00,0x02,0x18,0x79,0x00,0xA4,0x42,  /* 00000158    "#...y..B"
*/
+    0x55,0x46,0x46,0x14,0x1A,0x5F,0x50,0x52,  /* 00000160    "UFF.._PR"
*/
+    0x53,0x00,0x08,0x42,0x55,0x46,0x46,0x11,  /* 00000168    "S..BUFF."
*/
+    0x09,0x0A,0x06,0x23,0x20,0x06,0x18,0x79,  /* 00000170    "...# ..y"
*/
+    0x00,0xA4,0x42,0x55,0x46,0x46,0x14,0x06,  /* 00000178    "..BUFF.."
*/
+    0x5F,0x53,0x52,0x53,0x01,0x14,0x06,0x5F,  /* 00000180    "_SRS..._"
*/
+    0x44,0x49,0x53,0x00,0x5B,0x82,0x45,0x06,  /* 00000188    "DIS.[.E."
*/
+    0x4C,0x4E,0x4B,0x44,0x08,0x5F,0x48,0x49,  /* 00000190    "LNKD._HI"
*/
+    0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,  /* 00000198    "D.A...._"
*/
+    0x55,0x49,0x44,0x0A,0x04,0x14,0x09,0x5F,  /* 000001A0    "UID...._"
*/
+    0x53,0x54,0x41,0x00,0xA4,0x0A,0x0B,0x14,  /* 000001A8    "STA....."
*/
+    0x1A,0x5F,0x43,0x52,0x53,0x00,0x08,0x42,  /* 000001B0    "._CRS..B"
*/
+    0x55,0x46,0x46,0x11,0x09,0x0A,0x06,0x23,  /* 000001B8    "UFF....#"
*/
+    0x20,0x00,0x18,0x79,0x00,0xA4,0x42,0x55,  /* 000001C0    " ..y..BU"
*/
+    0x46,0x46,0x14,0x1A,0x5F,0x50,0x52,0x53,  /* 000001C8    "FF.._PRS"
*/
+    0x00,0x08,0x42,0x55,0x46,0x46,0x11,0x09,  /* 000001D0    "..BUFF.."
*/
+    0x0A,0x06,0x23,0x20,0x06,0x18,0x79,0x00,  /* 000001D8    "..# ..y."
*/
+    0xA4,0x42,0x55,0x46,0x46,0x14,0x06,0x5F,  /* 000001E0    ".BUFF.._"
*/
+    0x53,0x52,0x53,0x01,0x14,0x06,0x5F,0x44,  /* 000001E8    "SRS..._D"
*/
+    0x49,0x53,0x00,0x5B,0x82,0x4B,0x1F,0x50,  /* 000001F0    "IS.[.K.P"
*/
+    0x43,0x49,0x30,0x08,0x5F,0x48,0x49,0x44,  /* 000001F8    "CI0._HID"
*/
+    0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F,0x41,  /* 00000200    ".A...._A"
*/
+    0x44,0x52,0x00,0x08,0x5F,0x55,0x49,0x44,  /* 00000208    "DR.._UID"
*/
+    0x00,0x08,0x5F,0x42,0x42,0x4E,0x00,0x08,  /* 00000210    ".._BBN.."
*/
+    0x5F,0x50,0x52,0x54,0x12,0x43,0x1D,0x20,  /* 00000218    "_PRT.C. "
*/
+    0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0A,0x00,  /* 00000220    "........"
*/
+    0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,  /* 00000228    ".LNKA..."
*/
+    0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x01,0x4C,  /* 00000230    ".......L"
*/
+    0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,  /* 00000238    "NKB....."
*/
+    0xFF,0xFF,0x0A,0x00,0x0A,0x02,0x4C,0x4E,  /* 00000240    "......LN"
*/
+    0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,  /* 00000248    "KC......"
*/
+    0xFF,0x0A,0x00,0x0A,0x03,0x4C,0x4E,0x4B,  /* 00000250    ".....LNK"
*/
+    0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 00000258    "D......."
*/
+    0x0D,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,  /* 00000260    "...LNKB."
*/
+    0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0D,0x00,  /* 00000268    "........"
*/
+    0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,  /* 00000270    ".LNKC..."
*/
+    0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x02,  /* 00000278    "........"
*/
+    0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,  /* 00000280    "LNKD...."
*/
+    0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x03,0x4C,  /* 00000288    ".......L"
*/
+    0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,  /* 00000290    "NKA....."
*/
+    0xFF,0xFF,0x10,0x00,0x00,0x4C,0x4E,0x4B,  /* 00000298    ".....LNK"
*/
+    0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 000002A0    "A......."
*/
+    0x10,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00,  /* 000002A8    "...LNKB."
*/
+    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x10,0x00,  /* 000002B0    "........"
*/
+    0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12,  /* 000002B8    "..LNKC.."
*/
+    0x0E,0x04,0x0C,0xFF,0xFF,0x10,0x00,0x0A,  /* 000002C0    "........"
*/
+    0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D,  /* 000002C8    ".LNKD..."
*/
+    0x04,0x0C,0xFF,0xFF,0x11,0x00,0x00,0x4C,  /* 000002D0    ".......L"
*/
+    0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,  /* 000002D8    "NKA....."
*/
+    0xFF,0xFF,0x11,0x00,0x01,0x4C,0x4E,0x4B,  /* 000002E0    ".....LNK"
*/
+    0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,  /* 000002E8    "B......."
*/
+    0x11,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x43,  /* 000002F0    "....LNKC"
*/
+    0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x11,  /* 000002F8    "........"
*/
+    0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44,0x00,  /* 00000300    "...LNKD."
*/
+    0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x12,0x00,  /* 00000308    "........"
*/
+    0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,  /* 00000310    ".LNKA..."
*/
+    0x04,0x0C,0xFF,0xFF,0x12,0x00,0x01,0x4C,  /* 00000318    ".......L"
*/
+    0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,  /* 00000320    "NKB....."
*/
+    0xFF,0xFF,0x12,0x00,0x0A,0x02,0x4C,0x4E,  /* 00000328    "......LN"
*/
+    0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,  /* 00000330    "KC......"
*/
+    0xFF,0x12,0x00,0x0A,0x03,0x4C,0x4E,0x4B,  /* 00000338    ".....LNK"
*/
+    0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 00000340    "D......."
*/
+    0x13,0x00,0x00,0x4C,0x4E,0x4B,0x41,0x00,  /* 00000348    "...LNKA."
*/
+    0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x13,0x00,  /* 00000350    "........"
*/
+    0x01,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,  /* 00000358    ".LNKB..."
*/
+    0x04,0x0C,0xFF,0xFF,0x13,0x00,0x0A,0x02,  /* 00000360    "........"
*/
+    0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04,  /* 00000368    "LNKC...."
*/
+    0x0C,0xFF,0xFF,0x13,0x00,0x0A,0x03,0x4C,  /* 00000370    ".......L"
*/
+    0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,  /* 00000378    "NKD....."
*/
+    0xFF,0xFF,0x14,0x00,0x00,0x4C,0x4E,0x4B,  /* 00000380    ".....LNK"
*/
+    0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 00000388    "B......."
*/
+    0x14,0x00,0x01,0x4C,0x4E,0x4B,0x43,0x00,  /* 00000390    "...LNKC."
*/
+    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x14,0x00,  /* 00000398    "........"
*/
+    0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,0x12,  /* 000003A0    "..LNKD.."
*/
+    0x0E,0x04,0x0C,0xFF,0xFF,0x14,0x00,0x0A,  /* 000003A8    "........"
*/
+    0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,  /* 000003B0    ".LNKA..."
*/
+    0x04,0x0C,0xFF,0xFF,0x01,0x00,0x00,0x4C,  /* 000003B8    ".......L"
*/
+    0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,  /* 000003C0    "NKA....."
*/
+    0xFF,0xFF,0x01,0x00,0x01,0x4C,0x4E,0x4B,  /* 000003C8    ".....LNK"
*/
+    0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,  /* 000003D0    "B......."
*/
+    0x01,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x43,  /* 000003D8    "....LNKC"
*/
+    0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01,  /* 000003E0    "........"
*/
+    0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44,0x00,  /* 000003E8    "...LNKD."
*/
+
+};
Index: src/mainboard/via/epia-n/fadt.c
===================================================================
--- src/mainboard/via/epia-n/fadt.c	(revision 0)
+++ src/mainboard/via/epia-n/fadt.c	(revision 0)
@@ -0,0 +1,155 @@
+/*
+ * ACPI - create the Fixed ACPI Description Tables (FADT)
+ * (C) Copyright 2004 Nick Barker <nick.barker9 at btinternet.com>
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+
+#include <string.h>
+#include <arch/acpi.h>
+
+void acpi_create_fadt(acpi_fadt_t *fadt,acpi_facs_t *facs,void *dsdt){
+	acpi_header_t *header=&(fadt->header);
+
+	memset((void *)fadt,0,sizeof(acpi_fadt_t));
+	memcpy(header->signature,"FACP",4);
+	header->length = 244;
+	header->revision = 1;
+	memcpy(header->oem_id,OEM_ID,6);
+	memcpy(header->oem_table_id,"COREBOOT",8);
+	memcpy(header->asl_compiler_id,ASLC,4);
+	header->asl_compiler_revision=0;
+
+	fadt->firmware_ctrl=facs;
+	fadt->dsdt= dsdt;
+	fadt->preferred_pm_profile=0;
+	fadt->sci_int=5;
+	fadt->smi_cmd = 0;
+	fadt->acpi_enable = 0;
+	fadt->acpi_disable = 0;
+	fadt->s4bios_req = 0x0;
+	fadt->pstate_cnt = 0x0;
+
+	fadt->pm1a_evt_blk = 0x400;
+	fadt->pm1b_evt_blk = 0x0;
+	fadt->pm1a_cnt_blk = 0x404;
+	fadt->pm1b_cnt_blk = 0x0;
+	fadt->pm2_cnt_blk = 0x0;
+	fadt->pm_tmr_blk = 0x408;
+	fadt->gpe0_blk = 0x420;
+	fadt->gpe1_blk = 0x0;
+
+	fadt->pm1_evt_len = 4;
+	fadt->pm1_cnt_len = 2;
+	fadt->pm2_cnt_len = 0;
+	fadt->pm_tmr_len = 4;
+	fadt->gpe0_blk_len = 4;
+	fadt->gpe1_blk_len = 0;
+	fadt->gpe1_base = 0;
+	fadt->cst_cnt = 0;
+	fadt->p_lvl2_lat = 90;
+	fadt->p_lvl3_lat = 900;
+	fadt->flush_size = 0;
+	fadt->flush_stride = 0;
+	fadt->duty_offset = 0;
+	fadt->duty_width = 1;
+	fadt->day_alrm = 125;
+	fadt->mon_alrm = 126;
+	fadt->century = 50;
+	fadt->iapc_boot_arch = 0x1;
+	fadt->flags = 0x4a5;
+
+	fadt->reset_reg.space_id = 0;
+	fadt->reset_reg.bit_width = 0;
+	fadt->reset_reg.bit_offset = 0;
+	fadt->reset_reg.resv = 0;
+	fadt->reset_reg.addrl = 0x0;
+	fadt->reset_reg.addrh = 0x0;
+
+	fadt->reset_value = 0;
+	fadt->x_firmware_ctl_l = facs;
+	fadt->x_firmware_ctl_h = 0;
+	fadt->x_dsdt_l = dsdt;
+	fadt->x_dsdt_h = 0;
+
+	fadt->x_pm1a_evt_blk.space_id = 1;
+	fadt->x_pm1a_evt_blk.bit_width = 4;
+	fadt->x_pm1a_evt_blk.bit_offset = 0;
+	fadt->x_pm1a_evt_blk.resv = 0;
+	fadt->x_pm1a_evt_blk.addrl = 0x400;
+	fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+
+	fadt->x_pm1b_evt_blk.space_id = 1;
+	fadt->x_pm1b_evt_blk.bit_width = 4;
+	fadt->x_pm1b_evt_blk.bit_offset = 0;
+	fadt->x_pm1b_evt_blk.resv = 0;
+	fadt->x_pm1b_evt_blk.addrl = 0x0;
+	fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+
+	fadt->x_pm1a_cnt_blk.space_id = 1;
+	fadt->x_pm1a_cnt_blk.bit_width = 2;
+	fadt->x_pm1a_cnt_blk.bit_offset = 0;
+	fadt->x_pm1a_cnt_blk.resv = 0;
+	fadt->x_pm1a_cnt_blk.addrl = 0x404;
+	fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+
+	fadt->x_pm1b_cnt_blk.space_id = 1;
+	fadt->x_pm1b_cnt_blk.bit_width = 2;
+	fadt->x_pm1b_cnt_blk.bit_offset = 0;
+	fadt->x_pm1b_cnt_blk.resv = 0;
+	fadt->x_pm1b_cnt_blk.addrl = 0x0;
+	fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+
+	fadt->x_pm2_cnt_blk.space_id = 1;
+	fadt->x_pm2_cnt_blk.bit_width = 0;
+	fadt->x_pm2_cnt_blk.bit_offset = 0;
+	fadt->x_pm2_cnt_blk.resv = 0;
+	fadt->x_pm2_cnt_blk.addrl = 0x0;
+	fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+
+	fadt->x_pm_tmr_blk.space_id = 1;
+	fadt->x_pm_tmr_blk.bit_width = 4;
+	fadt->x_pm_tmr_blk.bit_offset = 0;
+	fadt->x_pm_tmr_blk.resv = 0;
+	fadt->x_pm_tmr_blk.addrl = 0x408;
+	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+
+	fadt->x_gpe0_blk.space_id = 1;
+	fadt->x_gpe0_blk.bit_width = 0;
+	fadt->x_gpe0_blk.bit_offset = 0;
+	fadt->x_gpe0_blk.resv = 0;
+	fadt->x_gpe0_blk.addrl = 0x420;
+	fadt->x_gpe0_blk.addrh = 0x0;
+
+
+	fadt->x_gpe1_blk.space_id = 1;
+	fadt->x_gpe1_blk.bit_width = 0;
+	fadt->x_gpe1_blk.bit_offset = 0;
+	fadt->x_gpe1_blk.resv = 0;
+	fadt->x_gpe1_blk.addrl = 0x0;
+	fadt->x_gpe1_blk.addrh = 0x0;
+
+	header->checksum = acpi_checksum((void *)fadt,
sizeof(acpi_fadt_t));
+
+}
Index: src/mainboard/via/epia-n/Config.lb
===================================================================
--- src/mainboard/via/epia-n/Config.lb	(revision 0)
+++ src/mainboard/via/epia-n/Config.lb	(revision 0)
@@ -0,0 +1,195 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2008 VIA Technologies, Inc.
+## (Written by Aaron Lwe <aaron.lwe at gmail.com> for VIA)
+##
+## 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.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+##
+
+## XIP_ROM_SIZE must be a power of 2.
+default XIP_ROM_SIZE = 64 * 1024
+
+include /config/nofailovercalculation.lb
+
+##
+## Set all of the defaults for an x86 architecture
+##
+arch i386 end
+
+##
+## Build the objects we have code for in this directory.
+##
+
+driver mainboard.o
+if HAVE_PIRQ_TABLE object irq_tables.o end
+
+object vgabios.o
+
+if HAVE_MP_TABLE object mptable.o end
+
+if HAVE_ACPI_TABLES
+	object fadt.o
+	object dsdt.o
+	object acpi_tables.o
+end
+makerule ./failover.E
+	depends "$(MAINBOARD)/../../../arch/i386/lib/failover.c
../romcc"
+	action "../romcc -E -O --label-prefix=failover -I$(TOP)/src -I.
$(CPPFLAGS) $(MAINBOARD)/../../../arch/i386/lib/failover.c -o $@"
+end
+makerule ./failover.inc
+	depends "$(MAINBOARD)/../../../arch/i386/lib/failover.c
../romcc"
+	action "../romcc    -O --label-prefix=failover -I$(TOP)/src -I.
$(CPPFLAGS) $(MAINBOARD)/../../../arch/i386/lib/failover.c -o $@"
+end
+makerule ./auto.E
+	depends	"$(MAINBOARD)/auto.c option_table.h ../romcc"
+	action	"../romcc -E -mcpu=c3 -O -I$(TOP)/src -I. $(CPPFLAGS)
$(MAINBOARD)/auto.c -o $@"
+end
+makerule ./auto.inc
+	depends "$(MAINBOARD)/auto.c option_table.h ../romcc"
+	action	"../romcc    -mcpu=c3 -O -I$(TOP)/src -I. $(CPPFLAGS)
$(MAINBOARD)/auto.c -o $@"
+end
+
+##
+## Build our 16 bit and 32 bit coreboot entry code
+##
+mainboardinit cpu/x86/16bit/entry16.inc
+mainboardinit cpu/x86/32bit/entry32.inc
+ldscript /cpu/x86/16bit/entry16.lds
+ldscript /cpu/x86/32bit/entry32.lds
+
+##
+## Build our reset vector (This is where coreboot is entered)
+##
+if USE_FALLBACK_IMAGE
+	mainboardinit cpu/x86/16bit/reset16.inc
+	ldscript /cpu/x86/16bit/reset16.lds
+else
+	mainboardinit cpu/x86/32bit/reset32.inc
+	ldscript /cpu/x86/32bit/reset32.lds
+end
+
+### Should this be in the northbridge code?
+mainboardinit arch/i386/lib/cpu_reset.inc
+
+##
+## Include an id string (For safe flashing)
+##
+mainboardinit arch/i386/lib/id.inc
+ldscript /arch/i386/lib/id.lds
+
+###
+### This is the early phase of coreboot startup 
+### Things are delicate and we test to see if we should
+### failover to another image.
+###
+if USE_FALLBACK_IMAGE
+	ldscript /arch/i386/lib/failover.lds
+	mainboardinit ./failover.inc
+end
+
+###
+### O.k. We aren't just an intermediary anymore!
+###
+
+##
+## Setup RAM
+##
+
+mainboardinit cpu/x86/fpu/enable_fpu.inc
+mainboardinit cpu/x86/mmx/enable_mmx.inc
+mainboardinit ./auto.inc
+mainboardinit cpu/x86/mmx/disable_mmx.inc
+
+dir /pc80
+config chip.h
+
+chip northbridge/via/cn400			# Northbridge
+
+  device apic_cluster 0 on			# APIC cluster
+    chip cpu/via/model_c3			# VIA C3
+      device apic 0 on end			# APIC
+    end
+  end
+
+  device pci_domain 0 on			# PCI domain
+    device pci 0.0 on end			# AGP Bridge
+    device pci 0.1 on end			# Error Reporting
+    device pci 0.2 on end			# Host Bus Control
+    device pci 0.3 on end			# Memory Controller
+    device pci 0.4 on end			# Power Management
+    device pci 0.7 on end			# V-Link Controller
+    device pci 1.0 on end			# PCI Bridge
+    chip southbridge/via/vt8237r		# Southbridge
+      # Enable both IDE channels.
+      register "ide0_enable" = "1"
+      register "ide1_enable" = "1"
+      # Both cables are 40pin.
+      register "ide0_80pin_cable" = "0"
+      register "ide1_80pin_cable" = "0"
+      device pci f.0 on end			# IDE
+      register "fn_ctrl_lo" = "0x80"
+      register "fn_ctrl_hi" = "0x1d"
+      device pci 10.0 on end			# OHCI
+      device pci 10.1 on end			# OHCI
+      device pci 10.2 on end			# OHCI
+      device pci 10.3 on end			# OHCI
+      device pci 10.4 on end			# EHCI
+      device pci 11.0 on			# Southbridge LPC
+        chip superio/winbond/w83697hf		# Super I/O
+          device pnp 2e.0 off			# Floppy
+            io 0x60 = 0x3f0
+            irq 0x70 = 6
+            drq 0x74 = 2
+          end
+          device pnp 2e.1 off			# Parallel Port
+            io 0x60 = 0x378
+            irq 0x70 = 7
+            drq 0x74 = 3
+          end
+          device pnp 2e.2 on			# COM1
+            io 0x60 = 0x3f8
+            irq 0x70 = 4
+          end
+          device pnp 2e.3 off			# COM2
+            io 0x60 = 0x2f8
+            irq 0x70 = 3
+          end
+          device pnp 2e.6 off			# IR Port
+            io 0x60 = 0x000
+          end
+          device pnp 2e.7 off			# GPIO 1
+            io 0x60 = 0x201			# 0x201
+          end
+          device pnp 2e.8 off			# GPIO 5
+            io 0x60 = 0x330			# 0x330
+          end
+          device pnp 2e.9 off			# GPIO 2, 3,and 4
+            io 0x60 = 0x000			#
+          end
+          device pnp 2e.a off			# ACPI
+            io 0x60 = 0x000			#
+          end
+          device pnp 2e.b on			# HWM
+            io 0x60 = 0x290
+          end
+        end
+      end
+      device pci 11.5 off end			# AC'97 audio
+      # device pci 11.6 off end			# AC'97 Modem
+      device pci 12.0 on end			# Ethernet
+    end
+  end
+end
Index: src/mainboard/via/epia-n/irq_tables.c
===================================================================
--- src/mainboard/via/epia-n/irq_tables.c	(revision 0)
+++ src/mainboard/via/epia-n/irq_tables.c	(revision 0)
@@ -0,0 +1,34 @@
+/* This file was generated by getpir.c, do not modify! 
+   (but if you do, please run checkpir on it to verify)
+ * Contains the IRQ Routing Table dumped directly from your memory,
which BIOS sets up
+ *
+ * Documentation at : http://www.microsoft.com/hwdev/busbios/PCIIRQ.HTM
+*/
+
+#include <arch/pirq_routing.h>
+
+const struct irq_routing_table intel_irq_routing_table = {
+	PIRQ_SIGNATURE,  /* u32 signature */
+	PIRQ_VERSION,    /* u16 version   */
+	32+16*5,	 /* there can be total 5 devices on the bus */
+	0x00,		 /* Where the interrupt router lies (bus) */
+	(0x00<<3)|0x0,   /* Where the interrupt router lies (dev) */
+	0xc20,		 /* IRQs devoted exclusively to PCI usage */
+	0,		 /* Vendor */
+	0,		 /* Device */
+	0,		 /* Crap (miniport) */
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+	0x68,         /*  u8 checksum , this hase to set to some value
that would give 0 after the sum of all bytes for this structure
(including checksum) */
+	{
+		/* bus,     dev|fn,   {link, bitmap}, {link, bitmap},
{link, bitmap}, {link, bitmap},  slot, rfu */
+		{0x00,(0x14<<3)|0x0, {{0x02, 0xdeb8}, {0x03, 0xdeb8},
{0x04, 0xdeb8}, {0x01, 0x0deb8}}, 0x1, 0x0},
+		{0x00,(0x13<<3)|0x0, {{0x01, 0xdeb8}, {0x02, 0xdeb8},
{0x03, 0xdeb8}, {0x04, 0x0deb8}}, 0x2, 0x0},
+		{0x00,(0x0a<<3)|0x0, {{0x04, 0xdeb8}, {0x01, 0xdeb8},
{0x02, 0xdeb8}, {0x03, 0x0deb8}}, 0x3, 0x0},
+		{0x00,(0x0d<<3)|0x0, {{0x02, 0xdeb8}, {0x03, 0xdeb8},
{0x04, 0xdeb8}, {0x01, 0x0deb8}}, 0x4, 0x0},
+		{0x00,(0x01<<3)|0x0, {{0x01, 0xdeb8}, {0x02, 0xdeb8},
{0x03, 0xdeb8}, {0x04, 0x0deb8}}, 0x0, 0x0},
+	}
+};
+unsigned long write_pirq_routing_table(unsigned long addr)
+{
+        return copy_pirq_routing_table(addr);
+}
Index: src/mainboard/via/epia-n/Options.lb
===================================================================
--- src/mainboard/via/epia-n/Options.lb	(revision 0)
+++ src/mainboard/via/epia-n/Options.lb	(revision 0)
@@ -0,0 +1,122 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2008 VIA Technologies, Inc.
+## (Written by Aaron Lwe <aaron.lwe at gmail.com> for VIA)
+##
+## 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.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+##
+
+uses HAVE_MP_TABLE
+uses CONFIG_CBFS
+uses HAVE_PIRQ_TABLE
+uses HAVE_FAILOVER_BOOT
+uses USE_FAILOVER_IMAGE
+uses USE_FALLBACK_IMAGE
+uses HAVE_FALLBACK_BOOT
+uses HAVE_HARD_RESET
+uses HAVE_OPTION_TABLE
+uses USE_OPTION_TABLE
+uses CONFIG_ROM_PAYLOAD
+uses IRQ_SLOT_COUNT
+uses MAINBOARD
+uses MAINBOARD_VENDOR
+uses MAINBOARD_PART_NUMBER
+uses COREBOOT_EXTRA_VERSION
+uses ARCH
+uses CONFIG_LB_MEM_TOPK
+uses FALLBACK_SIZE
+uses STACK_SIZE
+uses HEAP_SIZE
+uses ROM_SIZE
+uses ROM_SECTION_SIZE
+uses ROM_IMAGE_SIZE
+uses ROM_SECTION_SIZE
+uses ROM_SECTION_OFFSET
+uses CONFIG_ROM_PAYLOAD_START
+uses CONFIG_COMPRESSED_PAYLOAD_NRV2B
+uses CONFIG_COMPRESSED_PAYLOAD_LZMA
+uses PAYLOAD_SIZE
+uses _ROMBASE
+uses _RAMBASE
+uses XIP_ROM_SIZE
+uses XIP_ROM_BASE
+uses HAVE_MP_TABLE
+uses HAVE_ACPI_TABLES
+uses HAVE_ACPI_RESUME
+uses CROSS_COMPILE
+uses CC
+uses HOSTCC
+uses OBJCOPY
+uses DEFAULT_CONSOLE_LOGLEVEL
+uses MAXIMUM_CONSOLE_LOGLEVEL
+uses CONFIG_CONSOLE_SERIAL8250
+uses CONFIG_UDELAY_TSC
+uses CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2
+uses CONFIG_PCI_ROM_RUN
+uses CONFIG_CONSOLE_VGA
+uses CONFIG_MAX_PCI_BUSES
+uses TTYS0_BAUD
+uses CONFIG_VIDEO_MB
+uses CONFIG_IOAPIC
+uses CONFIG_COMPRESS
+
+#default CONFIG_LB_MEM_TOPK = 4 * 1024
+default ROM_SIZE = 512 * 1024
+default CONFIG_COMPRESS = 1
+default CONFIG_IOAPIC = 0
+default CONFIG_VIDEO_MB = 64
+default CONFIG_CONSOLE_SERIAL8250 = 1
+default CONFIG_PCI_ROM_RUN = 0
+default CONFIG_CONSOLE_VGA = 0
+default HAVE_FAILOVER_BOOT = 0
+default USE_FAILOVER_IMAGE = 0
+default HAVE_FALLBACK_BOOT = 1
+default HAVE_MP_TABLE = 0
+default CONFIG_UDELAY_TSC = 1
+default CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2 = 1
+default HAVE_HARD_RESET = 0
+default HAVE_PIRQ_TABLE = 1
+default IRQ_SLOT_COUNT = 9
+default HAVE_ACPI_TABLES = 0
+default HAVE_OPTION_TABLE = 1
+default ROM_IMAGE_SIZE = 67 * 1024
+default PAYLOAD_SIZE = 125 * 1024
+default FALLBACK_SIZE = ROM_IMAGE_SIZE + PAYLOAD_SIZE
+default USE_FALLBACK_IMAGE = 1
+default STACK_SIZE = 8 * 1024
+default HEAP_SIZE = 16 * 1024
+#default USE_OPTION_TABLE = !USE_FALLBACK_IMAGE
+default USE_OPTION_TABLE = 0
+default _RAMBASE = 0x00004000
+default CONFIG_ROM_PAYLOAD = 1
+default CROSS_COMPILE = ""
+default CC = "$(CROSS_COMPILE)gcc -m32 -fno-stack-protector"
+default HOSTCC = "gcc"
+
+##
+## Set this to the max PCI bus number you would ever use for PCI config
I/O.
+## Setting this number very high will make pci_locate_device() take a
long
+## time when it can't find a device.
+##
+default CONFIG_MAX_PCI_BUSES = 3
+
+
+#
+# CBFS
+#
+#
+default CONFIG_CBFS=0
+end
Index: src/mainboard/via/epia-n/vgachip.h
===================================================================
--- src/mainboard/via/epia-n/vgachip.h	(revision 0)
+++ src/mainboard/via/epia-n/vgachip.h	(revision 0)
@@ -0,0 +1,15 @@
+#ifndef _PC80_VGABIOS
+#define _PC80_VGABIOS
+
+extern struct chip_control pc80_vgabios_control;
+
+struct pc80_vgabios_config {
+	int nothing;
+};
+
+void vga_enable_console(void);
+void do_vgabios(void);
+void setup_realmode_idt(void);
+void write_protect_vgabios(void);
+
+#endif /* _PC80_VGABIOS */
Index: src/mainboard/via/epia-n/failover.c
===================================================================
--- src/mainboard/via/epia-n/failover.c	(revision 0)
+++ src/mainboard/via/epia-n/failover.c	(revision 0)
@@ -0,0 +1,34 @@
+#define ASSEMBLY 1
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+#include "arch/romcc_io.h"
+#include "pc80/mc146818rtc_early.c"
+
+static unsigned long main(unsigned long bist)
+{
+#if 0
+	/* This is the primary cpu how should I boot? */
+	if (do_normal_boot()) {
+		goto normal_image;
+	}
+	else {
+		goto fallback_image;
+	}
+ normal_image:
+	asm volatile ("jmp __normal_image" 
+		: /* outputs */ 
+		: "a" (bist) /* inputs */
+		: /* clobbers */
+		);
+ cpu_reset:
+	asm volatile ("jmp __cpu_reset"
+		: /* outputs */ 
+		: "a"(bist) /* inputs */
+		: /* clobbers */
+		);
+ fallback_image:
+#endif
+	return bist;
+}
Index: src/mainboard/via/epia-n/auto.c
===================================================================
--- src/mainboard/via/epia-n/auto.c	(revision 0)
+++ src/mainboard/via/epia-n/auto.c	(revision 0)
@@ -0,0 +1,166 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 VIA Technologies, Inc.
+ * (Written by Aaron Lwe <aaron.lwe at gmail.com> for VIA)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#define ASSEMBLY 1
+
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+#include <device/pnp_def.h>
+#include <arch/romcc_io.h>
+#include <arch/hlt.h>
+#include "pc80/serial.c"
+#include "arch/i386/lib/console.c"
+#include "ram/ramtest.c"
+#include "northbridge/via/cn400/raminit.h"
+#include "cpu/x86/mtrr/earlymtrr.c"
+#include "cpu/x86/bist.h"
+#include "pc80/udelay_io.c"
+#include "lib/delay.c"
+#include "cpu/x86/lapic/boot_cpu.c"
+#include "southbridge/via/vt8237r/vt8237r_early_smbus.c"
+#include "superio/winbond/w83697hf/w83697hf_early_serial.c"
+
+#define SERIAL_DEV PNP_DEV(0x2e, W83697HF_SP1)
+
+/*
+ * NOOB ::			
+ * d0f0 - Device 0 Function 0 etc. 
+ */
+static const struct mem_controller ctrl = {
+	.d0f0 = 0x0000,
+	.d0f2 = 0x2000,
+	.d0f3 = 0x3000,
+	.d0f4 = 0x4000,
+	.d0f7 = 0x7000,
+	.d1f0 = 0x8000,
+	.channel0 = { 0x50 },
+};
+
+
+static void memreset_setup(void)
+{
+}
+
+static inline int spd_read_byte(unsigned device, unsigned address)
+{
+	return smbus_read_byte(device, address);
+}
+
+#include "northbridge/via/cn400/raminit.c"
+
+static void enable_mainboard_devices(void)
+{
+	device_t dev;
+	u8 reg;
+ 
+ 	dev = pci_locate_device(PCI_ID(0x1106, 0x7259), 0);
+	if (dev == PCI_DEV_INVALID)
+		die("Northbridge V-Link not found!!!\n");
+	pci_write_config8(dev, 0x4F, 0x01);
+	pci_write_config8(dev, 0x48, 0x13);
+	
+	
+	dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_VT8237R_LPC), 0);
+	if (dev == PCI_DEV_INVALID)
+		die("Southbridge not found!!!\n");
+
+	/* bit=0 means enable function (per VT8237R datasheet)
+	 *   7 17.6 MC97
+	 *   6 17.5 AC97
+	 *   5 16.1 USB 2
+	 *   4 16.0 USB 1
+	 *   3 15.0 SATA and PATA
+	 *   2 16.2 USB 3
+	 *   1 16.4 USB EHCI
+	 */
+	pci_write_config8(dev, 0x50, 0x80);
+
+	/*bit=0 means enable internal function (per VT8237R datasheet)
+	 *   7 USB Device Mode
+	 *bit=1 means enable internal function (per VT8237R datasheet)
+	 *   6 Reserved
+	 *   5 LAN Controller Clock Gating
+	 *   4 LAN Controller
+	 *   3 Internal RTC
+	 *   2 Internal PS2 Mouse
+	 *   1 Internal KBC Configuration
+	 *   0 Internal Keyboard Controller
+	 */
+	pci_write_config8(dev, 0x51, 0x1d);
+}
+
+static void enable_shadow_ram(void) 
+{
+	unsigned char shadowreg;
+	
+	shadowreg = pci_read_config8(ctrl.d0f3, 0x82);
+	/* 0xf0000-0xfffff Read/Write*/
+	shadowreg |= 0x30;
+	pci_write_config8(ctrl.d0f3, 0x82, shadowreg);
+}
+
+static void main(unsigned long bist)
+{
+	unsigned long x;
+	device_t dev;
+
+	/* Enable multifunction for northbridge. */
+	pci_write_config8(ctrl.d0f0, 0x4f, 0x01);
+
+	w83697hf_set_clksel_48(SERIAL_DEV);
+
+	w83697hf_enable_serial(SERIAL_DEV, TTYS0_BASE);
+
+	uart_init();
+	console_init();
+
+	print_spew("In auto.c:main()\r\n");
+
+	enable_smbus();
+	smbus_fixup(&ctrl);
+
+	/* Halt if there was a built-in self test failure. */
+	report_bist_failure(bist);
+
+	print_debug("Enabling mainboard devices\r\n");
+	enable_mainboard_devices();
+
+	print_debug("Enable F-ROM Shadow RAM\r\n");
+	enable_shadow_ram();
+	
+	/* setup cpu */
+	print_debug("Setup CPU Interface\r\n");
+	c3_cpu_setup(ctrl.d0f2);	
+
+
+	ddr_ram_setup();
+
+	if (bist == 0) {
+		print_debug("doing early_mtrr\r\n");
+		early_mtrr_init();
+	}
+	
+	//ram_check(0, 640 * 1024);
+
+	print_spew("Leaving auto.c:main()\r\n");
+}
Index: src/mainboard/via/epia-n/chip.h
===================================================================
--- src/mainboard/via/epia-n/chip.h	(revision 0)
+++ src/mainboard/via/epia-n/chip.h	(revision 0)
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 VIA Technologies, Inc.
+ * (Written by Aaron Lwe <aaron.lwe at gmail.com> for VIA)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+extern struct chip_operations mainboard_ops;
+
+struct mainboard_config {
+	int nothing;
+};
Index: src/mainboard/via/epia-n/vgabios.c
===================================================================
--- src/mainboard/via/epia-n/vgabios.c	(revision 0)
+++ src/mainboard/via/epia-n/vgabios.c	(revision 0)
@@ -0,0 +1,839 @@
+#include <console/console.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#undef __KERNEL__
+#include <arch/io.h>
+//#include <printk.h>
+#include <string.h>
+#include "vgachip.h"
+
+/* vgabios.c. Derived from: */
+
+/*------------------------------------------------------------ -*- C
-*-
+ *  2 Kernel Monte a.k.a. Linux loading Linux on x86
+ *
+ *  Erik Arjan Hendriks <hendriks at lanl.gov>
+ *
+ *  This version is a derivative of the original two kernel monte
+ *  which is (C) 2000 Scyld.
+ *
+ *  Copyright (C) 2000 Scyld Computing Corporation
+ *
+ *  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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
+ *
+ * Portions related to the alpha architecture are:
+ *
+ *  Copyright(C) 2001 University of California.  LA-CC Number 01-67.
+ *  This software has been authored by an employee or employees of the
+ *  University of California, operator of the Los Alamos National
+ *  Laboratory under Contract No.  W-7405-ENG-36 with the U.S.
+ *  Department of Energy.  The U.S. Government has rights to use,
+ *  reproduce, and distribute this software. If the software is
+ *  modified to produce derivative works, such modified software should
+ *  be clearly marked, so as not to confuse it with the version
+ *  available from LANL.
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU General Public License, incorporated herein by
+ *  reference to http://www.gnu.org/licenses/gpl.html.
+ *
+ *  This software is provided by the author(s) "as is" and any express
+ *  or implied warranties, including, but not limited to, the implied
+ *  warranties of merchantability and fitness for a particular purpose
+ *  are disclaimed.  In no event shall the author(s) be liable for any
+ *  direct, indirect, incidental, special, exemplary, or consequential
+ *  damages (including, but not limited to, procurement of substitute
+ *  goods or services; loss of use, data, or profits; or business
+ *  interruption) however caused and on any theory of liability,
+ *  whether in contract, strict liability, or tort (including
+ *  negligence or otherwise) arising in any way out of the use of this
+ *  software, even if advised of the possibility of such damage.
+ *
+ *  $Id: vgabios.c,v 1.5 2004/10/06 17:33:52 rminnich Exp $
+
*--------------------------------------------------------------------*/
+
+/* Modified to be a self sufficient plug in so that it can be used 
+   without reliance on other parts of core coreboot 
+   (C) 2005 Nick.Barker9 at btinternet.com
+
+  Used initially for epia-m where there are problems getting the bios
+  emulator to successfully run this bios.
+*/
+
+/* Declare a temporary global descriptor table - necessary because the
+   Core part of the bios no longer sets up any 16 bit segments */
+__asm__ (
+	/* pointer to original gdt */
+	"gdtarg:			\n"
+	"	.word	gdt_limit	\n"
+	"	.long	gdt	       	\n"		
+
+	/* compute the table limit */
+	"__mygdt_limit = __mygdt_end - __mygdt - 1	\n"
+
+	"__mygdtaddr:			\n"
+	"	.word	__mygdt_limit  	\n"
+	"	.long	__mygdt	       	\n"
+
+	"__mygdt: 		       	\n"
+	/* selgdt 0, unused */
+	"	.word	0x0000, 0x0000	\n"
+	"	.byte	0x00, 0x00, 0x00, 0x00	\n"
+
+	/* selgdt 8, unused */
+	"	.word	0x0000, 0x0000	       	\n"
+	"	.byte	0x00, 0x00, 0x00, 0x00	\n"
+
+	/* selgdt 0x10, flat code segment */
+	"	.word	0xffff, 0x0000	       	\n"
+	"	.byte	0x00, 0x9b, 0xcf, 0x00	\n"	
+
+	/* selgdt 0x18, flat data segment */
+	"	.word	0xffff, 0x0000	       	\n"
+	"	.byte	0x00, 0x93, 0xcf, 0x00	\n"
+
+	/* selgdt 0x20, unused */
+	"	.word	0x0000, 0x0000	       	\n"
+	"	.byte	0x00, 0x00, 0x00, 0x00	\n"
+
+        /* selgdt 0x28 16-bit 64k code at 0x00000000 */
+	"	.word	0xffff, 0x0000	       	\n"
+	"	.byte	0, 0x9a, 0, 0	       	\n"
+
+	/* selgdt 0x30 16-bit 64k data at 0x00000000 */
+	"	.word	0xffff, 0x0000	       	\n"
+	"	.byte	0, 0x92, 0, 0	       	\n"
+
+	"__mygdt_end:				\n"
+);
+
+/* Declare a pointer to where our idt is going to be i.e. at mem zero
*/
+__asm__ ("__myidt:		\n"
+	 /* 16-bit limit */
+	 "	.word 1023	\n"
+	 /* 24-bit base */
+	 "	.long 0		\n"
+	 "	.word 0		\n"
+);
+
+/* The address arguments to this function are PHYSICAL ADDRESSES */ 
+static void real_mode_switch_call_vga(unsigned long devfn)
+{
+	__asm__ __volatile__ (
+		// paranoia -- does ecx get saved? not sure. This is 
+		// the easiest safe thing to do.
+		"	pushal			\n"
+		/* save the stack */
+		"	mov 	%esp, __stack	\n"
+		"	jmp 	1f		\n"
+		"__stack: .long 0		\n"
+		"1:\n"
+		/* get devfn into %ecx */
+		"	movl    %esp, %ebp	\n"
+		"	movl    8(%ebp), %ecx	\n"
+		/* load 'our' gdt */
+		"	lgdt	%cs:__mygdtaddr	\n"
+
+		/*  This configures CS properly for real mode. */
+		"	ljmp	$0x28, $__rms_16bit\n"
+		"__rms_16bit:		  	\n"
+		"	.code16			\n"
+		/* 16 bit code from here on... */
+
+		/* Load the segment registers w/ properly configured
segment
+		 * descriptors.  They will retain these configurations
(limits,
+		 * writability, etc.) once protected mode is turned off.
*/
+		"	mov	$0x30, %ax	\n"
+		"	mov	%ax, %ds       	\n"
+		"	mov	%ax, %es       	\n"
+		"	mov	%ax, %fs       	\n"
+		"	mov	%ax, %gs       	\n"
+		"	mov	%ax, %ss       	\n"
+
+		/* Turn off protection (bit 0 in CR0) */
+		"	movl	%cr0, %eax	\n"
+		"	andl	$0xFFFFFFFE, %eax \n"
+		"	movl	%eax, %cr0	\n"
+
+		/* Now really going into real mode */
+		"	ljmp	$0,  $__rms_real\n"
+		"__rms_real:			\n"
+
+		/* put the stack at the end of page zero. 
+		 * that way we can easily share it between real and
protected, 
+		 * since the 16-bit ESP at segment 0 will work for any
case. 
+		/* Setup a stack */
+		"	mov	$0x0, %ax	\n"
+		"	mov	%ax, %ss	\n"
+		"	movl	$0x1000, %eax	\n"
+		"	movl	%eax, %esp	\n"
+
+		/* Load our 16 it idt */
+		"	xor	%ax, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	lidt	__myidt		\n"
+
+		/* Dump zeros in the other segregs */
+		"	mov	%ax, %es       	\n"
+		"	mov	%ax, %fs       	\n"
+		"	mov	%ax, %gs       	\n"
+		"	mov	$0x40, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	mov	%cx, %ax	\n"
+
+		/* run VGA BIOS at 0xc000:0003 */
+		"	lcall	$0xc000, $0x0003\n"
+
+		/* if we got here, just about done. 
+		 * Need to get back to protected mode */
+		"	movl	%cr0, %eax	\n"
+		"	orl	$0x0000001, %eax\n" /* PE = 1 */
+		"	movl	%eax, %cr0	\n"
+
+		/* Now that we are in protected mode jump to a 32 bit
code segment. */
+		"	data32	ljmp	$0x10, $vgarestart\n"
+		"vgarestart:\n"
+		"	.code32\n"
+		"	movw	$0x18, %ax     	\n"
+		"	mov	%ax, %ds       	\n"
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+		"	mov	%ax, %ss	\n"
+
+		/* restore proper gdt and idt */
+		"	lgdt	%cs:gdtarg	\n"
+		"	lidt	idtarg		\n"
+
+		".globl vga_exit		\n"
+		"vga_exit:			\n"
+		"	mov	__stack, %esp	\n"
+		"	popal			\n"
+		);
+}
+
+__asm__ (".text\n""real_mode_switch_end:\n");
+extern char real_mode_switch_end[];
+
+/* call vga bios int 10 function 0x4f14 to enable main console 
+   epia-m does not always autosence the main console so forcing it on
is good !! */ 
+void vga_enable_console()
+{
+	__asm__ __volatile__ (
+		/* paranoia -- does ecx get saved? not sure. This is 
+		 * the easiest safe thing to do. */
+		"	pushal			\n"
+		/* save the stack */
+		"	mov	%esp, __stack	\n"
+
+		/* load 'our' gdt */
+		"	lgdt 	%cs:__mygdtaddr	\n"
+
+		/*  This configures CS properly for real mode. */
+		"	ljmp 	$0x28, $__vga_ec_16bit\n"
+		"__vga_ec_16bit:		\n"
+		"	.code16			\n"
+		/* 16 bit code from here on... */
+
+		/* Load the segment registers w/ properly configured
segment
+		 * descriptors.  They will retain these configurations
(limits,
+		 * writability, etc.) once protected mode is turned off.
*/
+		"	mov	$0x30, %ax     	\n"
+		"	mov	%ax, %ds       	\n"
+		"	mov	%ax, %es       	\n"
+		"	mov	%ax, %fs       	\n"
+		"	mov	%ax, %gs       	\n"
+		"	mov	%ax, %ss       	\n"
+
+		/* Turn off protection (bit 0 in CR0) */
+		"	movl	%cr0, %eax     	\n"
+		"	andl	$0xFFFFFFFE, %eax\n"
+		"	movl	%eax, %cr0     	\n"
+
+		/* Now really going into real mode */
+		"	ljmp	$0, $__vga_ec_real \n"
+		"__vga_ec_real:                  \n"
+
+		/* put the stack at the end of page zero. 
+		 * that way we can easily share it between real and
protected, 
+		 * since the 16-bit ESP at segment 0 will work for any
case. 
+		/* Setup a stack */
+		"	mov	$0x0, %ax	\n"
+		"	mov	%ax, %ss	\n"
+		"	movl	$0x1000, %eax	\n"
+		"	movl	%eax, %esp	\n"
+
+		/* debugging for RGM */
+		"	mov	$0x11, %al	\n"
+		"	outb	%al, $0x80	\n"
+
+		/* Load our 16 it idt */
+		"	xor	%ax, %ax       	\n"
+		"	mov	%ax, %ds	\n"
+		"	lidt	__myidt		\n"
+
+		/* Dump zeros in the other segregs */
+		"	mov	%ax, %ds	\n"
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+
+		/* ask bios to enable main console */
+		/* set up for int 10 call - values found from X server
+		 * bios call routines */
+		"	movw	$0x4f14,%ax	\n"
+		"	movw	$0x8003,%bx	\n"
+		"	movw	$1, %cx		\n"
+		"	movw	$0, %dx		\n"
+		"	movw	$0, %di		\n"
+		"	int	$0x10		\n"
+
+		"	movb	$0x55, %al	\n"
+		"	outb	%al, $0x80	\n"
+
+		/* if we got here, just about done. 
+		 * Need to get back to protected mode */
+		"	movl	%cr0, %eax	\n"
+		"	orl	$0x0000001, %eax\n" /* PE = 1 */
+		"	movl	%eax, %cr0	\n"
+
+		/* Now that we are in protected mode jump to a 32 bit
code segment. */
+		"	data32	ljmp	$0x10, $vga_ec_restart\n"
+		"vga_ec_restart:\n"
+		"	.code32\n"
+		"	movw	$0x18, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+		"	mov	%ax, %ss	\n"
+
+		/* restore proper gdt and idt */
+		"	lgdt	%cs:gdtarg 	\n"
+		"	lidt	idtarg		\n"
+		"	.globl	vga__ec_exit	\n"
+		"vga_ec_exit:\n"
+		"	mov	__stack, %esp	\n"
+		"	popal\n"
+		);
+}
+
+void do_vgabios(void)
+{
+	device_t dev;
+	unsigned long busdevfn;
+	unsigned int rom = 0;
+	unsigned char *buf;
+	unsigned int size = 64*1024;
+	int i;
+	
+	/* clear vga bios data area */
+	for (i = 0x400; i < 0x500; i++) {
+		*(unsigned char *) i = 0;
+	}
+
+	dev = dev_find_class(PCI_CLASS_DISPLAY_VGA<<8 , 0);
+
+	if (!dev) {
+		printk_debug("NO VGA FOUND\n");
+		return;
+	}
+	printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor,
dev->device);
+
+	/* declare rom address here - keep any config data out of the
way
+	 * of core LXB stuff */
+
+	rom = 0xfffc0000;
+	pci_write_config32(dev, PCI_ROM_ADDRESS, rom|1);
+	printk_debug("rom base, size: %x\n", rom);
+
+	buf = (unsigned char *) rom;
+	if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
+		memcpy((void *) 0xc0000, buf, size);
+
+		write_protect_vgabios();  // in northbridge
+
+	  	// check signature again
+		buf = (unsigned char *) 0xc0000;
+		if (buf[0]==0x55 && buf[1]==0xAA) {
+			busdevfn = (dev->bus->secondary << 8) |
dev->path.pci.devfn;
+			printk_debug("bus/devfn = %#x\n", busdevfn);
+
+		    	real_mode_switch_call_vga(busdevfn);
+		} else
+			printk_debug("Failed to copy VGA BIOS to
0xc0000\n");
+	} else 
+		printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0],
buf[1]);
+
+	pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
+}
+
+
+// we had hoped to avoid this. 
+// this is a stub IDT only. It's main purpose is to ignore calls 
+// to the BIOS. 
+// no longer. Dammit. We have to respond to these.
+struct realidt {
+	unsigned short offset, cs;
+}; 
+
+// from a handy writeup that andrey found.
+
+// handler. 
+// There are some assumptions we can make here. 
+// First, the Top Of Stack (TOS) is located on the top of page zero. 
+// we can share this stack between real and protected mode. 
+// that simplifies a lot of things ...
+// we'll just push all the registers on the stack as longwords, 
+// and pop to protected mode. 
+// second, since this only ever runs as part of coreboot, 
+// we know all the segment register values -- so we don't save any.
+// keep the handler that calls things small. It can do a call to 
+// more complex code in coreboot itself. This helps a lot as we don't
+// have to do address fixup in this little stub, and calls are absolute
+// so the handler is relocatable.
+void handler(void)
+{
+	__asm__ __volatile__ ( 
+		"	.code16		\n"
+		"idthandle:		\n"
+		"	pushal		\n"
+		"	movb 	$0, %al	\n"
+		"	ljmp 	$0, $callbiosint16\n"
+		"end_idthandle:		\n"
+		"	.code32		\n"
+		);
+}
+
+void debughandler(void)
+{
+	__asm__ __volatile__ ( 
+		"	.code16		\n"
+		"debughandle:		\n"
+		"	pushw	%cx	\n"
+		"	movw	$250, %cx \n"
+		"dbh1:			\n"
+		"	loop	dbh1	\n"
+		"	popw	%cx	\n"
+		"	iret		\n"
+		"end_debughandle:	\n"
+		".code32		\n"
+		);
+}
+
+// Calling conventions. The first C function is called with this stuff
+// on the stack. They look like value parameters, but note that if you
+// modify them they will go back to the INTx function modified. 
+// the C function will call the biosint function with these as
+// REFERENCE parameters. In this way, we can easily get 
+// returns back to the INTx caller (i.e. vgabios)
+void callbiosint(void)
+{
+	__asm__ __volatile__ (
+		"	.code16		\n"
+		"callbiosint16:		\n"
+		"	push	%ds	\n"
+		"	push	%es	\n"
+		"	push	%fs	\n"
+		"	push	%gs	\n"
+		// clean up the int #. To save space we put it in the
lower
+		// byte. But the top 24 bits are junk. 
+		"	andl	$0xff, %eax\n"
+		// this push does two things:
+		// - put the INT # on the stack as a parameter
+		// - provides us with a temp for the %cr0 mods.
+		"	pushl	%eax	\n"
+		"	movl    %cr0, %eax\n"
+		"	orl	$0x00000001, %eax\n" /* PE = 1 */
+		"	movl	%eax, %cr0\n"
+		/* Now that we are in protected mode jump to a 32 bit
code segment. */
+		"	data32  ljmp    $0x10, $biosprotect\n"
+		"biosprotect:		\n"
+		"	.code32		\n"
+		"	movw	$0x18, %ax          \n"
+		"	mov	%ax, %ds          \n"
+		"	mov	%ax, %es          \n"
+		"	mov	%ax, %fs          \n"
+		"	mov	%ax, %gs          \n"
+		"	mov	%ax, %ss          \n"
+		"	lidt	idtarg         \n"
+		"	call	biosint	\n"
+		// back to real mode ...
+		"	ljmp	$0x28, $__rms_16bit2\n"
+		"__rms_16bit2:			\n"
+		"	.code16			\n"
+		/* 16 bit code from here on... */
+		/* Load the segment registers w/ properly configured
segment
+		 * descriptors.  They will retain these configurations
(limits,
+		 * writability, etc.) once protected mode is turned off.
*/
+		"	mov	$0x30, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+		"	mov	%ax, %ss	\n"
+		
+		/* Turn off protection (bit 0 in CR0) */
+		"	movl	%cr0, %eax		\n"
+		"	andl	$0xFFFFFFFE, %eax	\n"
+		"	movl	%eax, %cr0		\n"
+
+		/* Now really going into real mode */
+		"	ljmp $0,  $__rms_real2	\n"
+		"__rms_real2:			\n"
+
+		/* Setup a stack
+		 * FixME: where is esp? */
+		"	mov	$0x0, %ax       \n"
+		"	mov	%ax, %ss	\n"
+
+		/* ebugging for RGM */
+		"	mov	$0x11, %al	\n"
+		"	outb	%al, $0x80	\n"
+
+		/* Load our 16 it idt */
+		"	xor	%ax, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	lidt	__myidt		\n"
+
+		/* Dump zeros in the other segregs */
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+		"	mov	$0x40, %ax	\n"
+		"	mov	%ax, %ds	\n"
+
+		/* pop the INT # that you pushed earlier */
+		"	popl	%eax		\n"
+		"	pop	%gs		\n"
+		"	pop	%fs		\n"
+		"	pop	%es		\n"
+		"	pop	%ds		\n"
+		"	popal			\n"
+		"	iret			\n"
+		"	.code32			\n"
+		);
+}
+
+enum {
+	PCIBIOS = 0x1a, 
+	MEMSIZE = 0x12
+};
+
+int pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long
*pebp,
+	    unsigned long *pesp, unsigned long *pebx, unsigned long
*pedx,
+	    unsigned long *pecx, unsigned long *peax, unsigned long
*pflags);
+
+int handleint21(unsigned long *pedi, unsigned long *pesi, unsigned long
*pebp,
+		unsigned long *pesp, unsigned long *pebx, unsigned long
*pedx,
+		unsigned long *pecx, unsigned long *peax, unsigned long
*pflags
+        );
+
+extern void vga_exit(void);
+
+int biosint(unsigned long intnumber,
+	    unsigned long gsfs, unsigned long dses,
+	    unsigned long edi, unsigned long esi,
+	    unsigned long ebp, unsigned long esp, 
+	    unsigned long ebx, unsigned long edx, 
+	    unsigned long ecx, unsigned long eax, 
+	    unsigned long cs_ip, unsigned short stackflags)
+{
+	unsigned long ip; 
+	unsigned long cs; 
+	unsigned long flags;
+	int ret = -1;
+	
+	ip = cs_ip & 0xffff;
+	cs = cs_ip >> 16;
+	flags = stackflags;
+	
+	printk_debug("biosint: INT# 0x%lx\n", intnumber);
+	printk_debug("biosint: eax 0x%lx ebx 0x%lx ecx 0x%lx edx
0x%lx\n", 
+		      eax, ebx, ecx, edx);
+	printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi
0x%lx\n",
+		     ebp, esp, edi, esi);
+	printk_debug("biosint:  ip 0x%x   cs 0x%x  flags 0x%x\n",
+		     ip, cs, flags);
+
+	// cases in a good compiler are just as good as your own tables.

+	switch (intnumber) {
+	case 0 ... 15:
+		// These are not BIOS service, but the CPU-generated
exceptions
+		printk_info("biosint: Oops, exception %u\n", intnumber);
+		if (esp < 0x1000) {
+			printk_debug("Stack contents: ");
+			while (esp < 0x1000) {
+				printk_debug("0x%04x ", *(unsigned short
*) esp);
+				esp += 2;
+			}
+			printk_debug("\n");
+		}
+		printk_debug("biosint: Bailing out\n");
+		// "longjmp"
+		vga_exit();
+		break;
+		
+	case PCIBIOS:
+		ret = pcibios( &edi, &esi, &ebp, &esp, 
+			       &ebx, &edx, &ecx, &eax, &flags);
+		break;
+	case MEMSIZE: 
+		// who cares. 
+		eax = 64 * 1024;
+		ret = 0;
+		break;
+	case 0x15:
+		ret=handleint21( &edi, &esi, &ebp, &esp, 
+				&ebx, &edx, &ecx, &eax, &flags);
+		break;
+	default:
+		printk_info("BIOSINT: Unsupport int #0x%x\n", 
+			    intnumber);
+		break;
+	}
+	if (ret)
+		flags |= 1; // carry flags
+	else
+		flags &= ~1;
+	stackflags = flags;
+	return ret;
+} 
+
+
+void setup_realmode_idt(void) 
+{
+	extern unsigned char idthandle, end_idthandle;
+	extern unsigned char debughandle, end_debughandle;
+
+	int i;
+	struct realidt *idts = (struct realidt *) 0;
+	int codesize = &end_idthandle - &idthandle;
+	unsigned char *intbyte, *codeptr;
+	
+	// for each int, we create a customized little handler
+	// that just pushes %ax, puts the int # in %al, 
+	// then calls the common interrupt handler. 
+	// this necessitated because intel didn't know much about 
+	// architecture when they did the 8086 (it shows)
+	// (hmm do they know anymore even now :-)
+	// obviously you can see I don't really care about memory 
+	// efficiency. If I did I would probe back through the stack
+	// and get it that way. But that's really disgusting.
+	for (i = 0; i < 256; i++) {
+		idts[i].cs = 0;
+		codeptr = (char*) 4096 + i * codesize;
+		idts[i].offset = (unsigned) codeptr;
+		memcpy(codeptr, &idthandle, codesize);
+		intbyte = codeptr + 3;
+		*intbyte = i;
+	}
+	
+	// fixed entry points
+	
+	// VGA BIOSes tend to hardcode f000:f065 as the previous handler
of
+	// int10. 
+	// calling convention here is the same as INTs, we can reuse
+	// the int entry code.
+	codeptr = (char*) 0xff065;
+	memcpy(codeptr, &idthandle, codesize);
+	intbyte = codeptr + 3;
+	*intbyte = 0x42; /* int42 is the relocated int10 */
+
+	/* debug handler - useful to set a programmable delay between
instructions if the
+	   TF bit is set upon call to real mode */
+	idts[1].cs = 0;
+	idts[1].offset = 16384;
+	memcpy(16384, &debughandle, &end_debughandle - &debughandle);
+
+	
+}
+
+
+
+enum {
+	CHECK = 0xb001,
+	FINDDEV = 0xb102,
+	READCONFBYTE = 0xb108,
+	READCONFWORD = 0xb109,
+	READCONFDWORD = 0xb10a,
+	WRITECONFBYTE = 0xb10b,
+	WRITECONFWORD = 0xb10c,
+	WRITECONFDWORD = 0xb10d
+};
+
+// errors go in AH. Just set these up so that word assigns
+// will work. KISS. 
+enum {
+	PCIBIOS_NODEV = 0x8600,
+	PCIBIOS_BADREG = 0x8700
+};
+
+int
+pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp, 
+	unsigned long *pesp, unsigned long *pebx, unsigned long *pedx, 
+	unsigned long *pecx, unsigned long *peax, unsigned long *pflags)
+{
+	unsigned long edi = *pedi;
+	unsigned long esi = *pesi;
+	unsigned long ebp = *pebp;
+	unsigned long esp = *pesp;
+	unsigned long ebx = *pebx;
+	unsigned long edx = *pedx;
+	unsigned long ecx = *pecx;
+	unsigned long eax = *peax;
+	unsigned long flags = *pflags;
+	unsigned short func = (unsigned short) eax;
+	int retval = 0;
+	unsigned short devid, vendorid, devfn;
+	short devindex; /* Use short to get rid of gabage in upper half
of 32-bit register */
+	unsigned char bus;
+	device_t dev;
+	
+	switch(func) {
+	case  CHECK:
+		*pedx = 0x4350;
+		*pecx = 0x2049;
+		retval = 0;
+		break;
+	case FINDDEV:
+	{
+		devid = *pecx;
+		vendorid = *pedx;
+		devindex = *pesi;
+		dev = 0;
+		while ((dev = dev_find_device(vendorid, devid, dev))) {
+			if (devindex <= 0)
+				break;
+			devindex--;
+		}
+		if (dev) {
+			unsigned short busdevfn;
+			*peax = 0;
+			// busnum is an unsigned char;
+			// devfn is an int, so we mask it off. 
+			busdevfn = (dev->bus->secondary << 8)
+				| (dev->path.pci.devfn & 0xff);
+			printk_debug("0x%x: return 0x%x\n", func,
busdevfn);
+			*pebx = busdevfn;
+			retval = 0;
+		} else {
+			*peax = PCIBIOS_NODEV;
+			retval = -1;
+		}
+	}
+	break;
+	case READCONFDWORD:
+	case READCONFWORD:
+	case READCONFBYTE:
+	case WRITECONFDWORD:
+	case WRITECONFWORD:
+	case WRITECONFBYTE:
+	{
+		unsigned long dword;
+		unsigned short word;
+		unsigned char byte;
+		unsigned char reg;
+		
+		devfn = *pebx & 0xff;
+		bus = *pebx >> 8;
+		reg = *pedi;
+		dev = dev_find_slot(bus, devfn);
+		if (! dev) {
+			printk_debug("0x%x: BAD DEVICE bus %d devfn
0x%x\n", func, bus, devfn);
+			// idiots. the pcibios guys assumed you'd never
pass a bad bus/devfn!
+			*peax = PCIBIOS_BADREG;
+			retval = -1;
+		}
+		switch(func) {
+		case READCONFBYTE:
+			byte = pci_read_config8(dev, reg);
+			*pecx = byte;
+			break;
+		case READCONFWORD:
+			word = pci_read_config16(dev, reg);
+			*pecx = word;
+			break;
+		case READCONFDWORD:
+			dword = pci_read_config32(dev, reg);
+			*pecx = dword;
+			break;
+		case WRITECONFBYTE:
+			byte = *pecx;
+			pci_write_config8(dev, reg, byte);
+			break;
+		case WRITECONFWORD:
+			word = *pecx;
+			pci_write_config16(dev, reg, word);
+			break;
+		case WRITECONFDWORD:
+			dword = *pecx;
+			pci_write_config32(dev, reg, dword);
+			break;
+		}
+		
+		if (retval) 
+			retval = PCIBIOS_BADREG;
+		printk_debug("0x%x: bus %d devfn 0x%x reg 0x%x val
0x%lx\n",
+			     func, bus, devfn, reg, *pecx);
+		*peax = 0;
+		retval = 0;
+	}
+	break;
+	default:
+		printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n",
func);
+		break;
+	}
+	
+	return retval;
+} 
+
+int handleint21(unsigned long *edi, unsigned long *esi, unsigned long
*ebp,
+		unsigned long *esp, unsigned long *ebx, unsigned long
*edx,
+		unsigned long *ecx, unsigned long *eax, unsigned long
*flags)
+{
+	int res=-1;
+	switch(*eax&0xffff)
+	{
+	case 0x5f19:
+		break;
+	case 0x5f18:
+		*eax=0x5f;
+		*ebx=0x545; // MCLK = 133, 32M frame buffer, 256 M main
memory
+		*ecx=0x060;
+		res=0;
+		break;
+	case 0x5f00:
+		*eax = 0x8600;
+		break;
+	case 0x5f01:
+		*eax = 0x5f;
+		*ecx = (*ecx & 0xffffff00 ) | 2; // panel type =  2 =
1024 * 768
+		res = 0;
+		break;
+	case 0x5f02:
+		*eax=0x5f;
+		*ebx= (*ebx & 0xffff0000) | 2;
+		*ecx= (*ecx & 0xffff0000) | 0x401;  // PAL + crt only 
+		*edx= (*edx & 0xffff0000) | 0;  // TV Layout - default
+		res=0;
+		break;
+	case 0x5f0f:
+		*eax=0x860f;
+		break;
+	}
+	return res;
+}
Index: src/mainboard/via/epia-n/dsdt.asl
===================================================================
--- src/mainboard/via/epia-n/dsdt.asl	(revision 0)
+++ src/mainboard/via/epia-n/dsdt.asl	(revision 0)
@@ -0,0 +1,257 @@
+/*
+ * Minimalist ACPI DSDT table for EPIA-M / MII
+ * (C) Copyright 2004 Nick Barker <Nick.Barker9 at btinternet.com>
+ *
+ * 
+ */
+
+DefinitionBlock ("DSDT.aml", "DSDT", 1, "LXBIOS", "LXB-DSDT", 1)
+{
+	/*  
+	 * Define the main processor
+	 */
+	Scope (\_PR)
+	{
+		Processor (\_PR.CPU0, 0x00, 0x00000410, 0x06) {}
+	}
+
+	/* For now only define 2 power states:
+	 *  - S0 which is fully on
+	 *  - S5 which is soft off
+	 * any others would involve declaring the wake up methods
+	 */
+	Name (\_S0, Package () {0x00, 0x00, 0x00, 0x00 })
+	Name (\_S5, Package () {0x02, 0x02, 0x00, 0x00 })
+
+	/* Root of the bus hierarchy */
+	Scope (\_SB)
+    	{
+		/* Define how interrupt Link A is plumbed in */ 
+		Device (LNKA)
+		{
+			Name (_HID, EisaId ("PNP0C0F"))
+			Name (_UID, 0x01)
+			/* Status - always return ready */
+			Method (_STA, 0, NotSerialized)
+			{
+				Return (0x0B)
+ 			}
+			/* Current Resources - return irq set up in BIOS
*/  
+			Method (_CRS, 0, NotSerialized)
+			{
+				Name (BUFF, ResourceTemplate ()
+				{
+					IRQ (Level, ActiveLow, Shared)
{5}
+				})
+				Return (BUFF)
+                	}
+			/* Possible Resources - return the range of irqs
+ 			 * we are using for PCI - only here to keep
Linux ACPI
+			 * happy 
+			 */
+			Method (_PRS, 0, NotSerialized)
+			{
+				Name (BUFF, ResourceTemplate ()
+                    		{
+					IRQ (Level, ActiveLow, Shared)
{5,9,10}
+                    		})
+                    		Return (BUFF)
+                	}
+			/* Set Resources - dummy function to keep Linux
ACPI happy
+                         * Linux is more than happy not to tinker with
irq
+			 * assignments as long as the CRS and STA
functions 
+			 * return good values
+			 */
+			Method (_SRS, 1, NotSerialized ) {}
+			/* Disable - dummy function to keep Linux ACPI
happy */
+			Method (_DIS, 0, NotSerialized ) {}
+ 
+		} // End of LNKA 
+
+		/* Define how interrupt Link B is plumbed in */ 
+		Device (LNKB)
+		{
+			Name (_HID, EisaId ("PNP0C0F"))
+			Name (_UID, 0x02)
+			/* Status - always return ready */
+			Method (_STA, 0, NotSerialized)
+			{
+				Return (0x0B)
+ 			}
+			/* Current Resources - return irq set up in BIOS
*/  
+			Method (_CRS, 0, NotSerialized)
+			{
+				Name (BUFF, ResourceTemplate ()
+				{
+					IRQ (Level, ActiveLow, Shared)
{9}
+				})
+				Return (BUFF)
+                	}
+			/* Possible Resources - return the range of irqs
+			 * we are using for PCI - only here to keep
Linux ACPI
+			 * happy 
+			 */
+			Method (_PRS, 0, NotSerialized)
+			{
+				Name (BUFF, ResourceTemplate ()
+                    		{
+					IRQ (Level, ActiveLow, Shared)
{5,9,10}
+                    		})
+                    		Return (BUFF)
+                	}
+			/* Set Resources - dummy function to keep Linux
ACPI happy
+                         * Linux is more than happy not to tinker with
irq
+			 * assignments as long as the CRS and STA
functions 
+			 * return good values
+			 */
+			Method (_SRS, 1, NotSerialized ) {}
+			/* Disable - dummy function to keep Linux ACPI
happy */
+			Method (_DIS, 0, NotSerialized ) {}
+ 
+		} // End of LNKB
+
+		/* Define how interrupt Link C is plumbed in */ 
+		Device (LNKC)
+		{
+			Name (_HID, EisaId ("PNP0C0F"))
+			Name (_UID, 0x03)
+			/* Status - always return ready */
+			Method (_STA, 0, NotSerialized)
+			{
+				Return (0x0B)
+ 			}
+			/* Current Resources - return irq set up in BIOS
*/  
+			Method (_CRS, 0, NotSerialized)
+			{
+				Name (BUFF, ResourceTemplate ()
+				{
+					IRQ (Level, ActiveLow, Shared)
{9}
+				})
+				Return (BUFF)
+                	}
+			/* Possible Resources - return the range of irqs
+			 * we are using for PCI - only here to keep
Linux ACPI
+			 * happy 
+			 */
+			Method (_PRS, 0, NotSerialized)
+			{
+				Name (BUFF, ResourceTemplate ()
+                    		{
+					IRQ (Level, ActiveLow, Shared)
{5,9,10}
+                    		})
+                    		Return (BUFF)
+                	}
+			/* Set Resources - dummy function to keep Linux
ACPI happy
+                         * Linux is more than happy not to tinker with
irq
+			 * assignments as long as the CRS and STA
functions 
+			 * return good values
+			 */
+			Method (_SRS, 1, NotSerialized ) {}
+			/* Disable - dummy function to keep Linux ACPI
happy */
+			Method (_DIS, 0, NotSerialized ) {}
+ 
+		} // End of LNKC
+
+		/* Define how interrupt Link D is plumbed in */ 
+		Device (LNKD)
+		{
+			Name (_HID, EisaId ("PNP0C0F"))
+			Name (_UID, 0x04)
+			/* Status - always return ready */
+			Method (_STA, 0, NotSerialized)
+			{
+				Return (0x0B)
+ 			}
+			/* Current Resources - return irq set up in BIOS
*/  
+			Method (_CRS, 0, NotSerialized)
+			{
+				Name (BUFF, ResourceTemplate ()
+				{
+					IRQ (Level, ActiveLow, Shared)
{5}
+				})
+				Return (BUFF)
+                	}
+			/* Possible Resources - return the range of irqs
+			 * we are using for PCI - only here to keep
Linux ACPI
+			 * happy 
+			 */
+			Method (_PRS, 0, NotSerialized)
+			{
+				Name (BUFF, ResourceTemplate ()
+                    		{
+					IRQ (Level, ActiveLow, Shared)
{5,9,10}
+                    		})
+                    		Return (BUFF)
+                	}
+			/* Set Resources - dummy function to keep Linux
ACPI happy
+                         * Linux is more than happy not to tinker with
irq
+			 * assignments as long as the CRS and STA
functions 
+			 * return good values
+			 */
+			Method (_SRS, 1, NotSerialized ) {}
+			/* Disable - dummy function to keep Linux ACPI
happy */
+			Method (_DIS, 0, NotSerialized ) {}
+ 
+		} // End of LNKD 
+
+ 
+		/* top PCI device */
+		Device (PCI0)
+		{
+			Name (_HID, EisaId ("PNP0A03"))
+			Name (_ADR, 0x00)
+			Name (_UID, 0x00)
+			Name (_BBN, 0x00)
+
+			/* PCI Routing Table */
+			Name (_PRT, Package () {
+				/* Epia-MII 6000e cardbus: */
+				Package () {0x000AFFFF, 0x00, LNKA,
0x00}, // Cardbus Link A
+				Package () {0x000AFFFF, 0x01, LNKB,
0x00}, // Cardbus Link B
+				Package () {0x000AFFFF, 0x02, LNKC,
0x00}, // Cardbus Link C
+				Package () {0x000AFFFF, 0x03, LNKD,
0x00}, // Cardbus Link D
+
+				Package () {0x000DFFFF, 0x00, LNKB,
0x00}, // Firewire Link B
+				Package () {0x000DFFFF, 0x01, LNKC,
0x00}, // Firewire Link C
+				Package () {0x000DFFFF, 0x02, LNKD,
0x00}, // Firewire Linc D
+				Package () {0x000DFFFF, 0x03, LNKA,
0x00}, // Firewire Link A
+
+				Package () {0x0010FFFF, 0x00, LNKA,
0x00}, // USB Link A
+				Package () {0x0010FFFF, 0x01, LNKB,
0x00}, // USB Link B
+				Package () {0x0010FFFF, 0x02, LNKC,
0x00}, // USB Link C
+				Package () {0x0010FFFF, 0x03, LNKD,
0x00}, // USB Link D
+
+				Package () {0x0011FFFF, 0x00, LNKA,
0x00}, // vt8623 Link A
+				Package () {0x0011FFFF, 0x01, LNKB,
0x00}, // vt8623 Link B
+				Package () {0x0011FFFF, 0x02, LNKC,
0x00}, // vt8623 Link C
+				Package () {0x0011FFFF, 0x03, LNKD,
0x00}, // vt8623 Link D
+
+				Package () {0x0012FFFF, 0x00, LNKA,
0x00}, // LAN Link A 
+				Package () {0x0012FFFF, 0x01, LNKB,
0x00}, // LAN Link B
+				Package () {0x0012FFFF, 0x02, LNKC,
0x00}, // LAN Link C
+				Package () {0x0012FFFF, 0x03, LNKD,
0x00}, // LAN Link D
+
+				Package () {0x0013FFFF, 0x00, LNKA,
0x00}, // Riser slot LinkA 
+				Package () {0x0013FFFF, 0x01, LNKB,
0x00}, // Riser slot LinkB
+				Package () {0x0013FFFF, 0x02, LNKC,
0x00}, // Riser slot LinkC
+				Package () {0x0013FFFF, 0x03, LNKD,
0x00}, // Riser slot LinkD
+
+				Package () {0x0014FFFF, 0x00, LNKB,
0x00}, // Slot 1, Link B
+				Package () {0x0014FFFF, 0x01, LNKC,
0x00}, // Slot 1, Link C
+				Package () {0x0014FFFF, 0x02, LNKD,
0x00}, // Slot 1, Link D
+				Package () {0x0014FFFF, 0x03, LNKA,
0x00}, // Slot 1, Link A
+                
+				Package () {0x0001FFFF, 0x00, LNKA,
0x00}, // VGA Link A
+				Package () {0x0001FFFF, 0x01, LNKB,
0x00}, // VGA Link B
+				Package () {0x0001FFFF, 0x02, LNKC,
0x00}, // VGA Link C
+				Package () {0x0001FFFF, 0x03, LNKD,
0x00} // VGA Link D
+
+            		})
+
+
+		} // End of PCI0
+
+	} // End of _SB
+
+} // End of Definition Block
+
Index: src/mainboard/via/epia-n/cmos.layout
===================================================================
--- src/mainboard/via/epia-n/cmos.layout	(revision 0)
+++ src/mainboard/via/epia-n/cmos.layout	(revision 0)
@@ -0,0 +1,74 @@
+entries
+
+#start-bit length  config config-ID    name
+#0            8       r       0        seconds
+#8            8       r       0        alarm_seconds
+#16           8       r       0        minutes
+#24           8       r       0        alarm_minutes
+#32           8       r       0        hours
+#40           8       r       0        alarm_hours
+#48           8       r       0        day_of_week
+#56           8       r       0        day_of_month
+#64           8       r       0        month
+#72           8       r       0        year
+#80           4       r       0        rate_select
+#84           3       r       0        REF_Clock
+#87           1       r       0        UIP
+#88           1       r       0        auto_switch_DST
+#89           1       r       0        24_hour_mode
+#90           1       r       0        binary_values_enable
+#91           1       r       0        square-wave_out_enable
+#92           1       r       0        update_finished_enable
+#93           1       r       0        alarm_interrupt_enable
+#94           1       r       0        periodic_interrupt_enable
+#95           1       r       0        disable_clock_updates
+#96         288       r       0        temporary_filler
+0          384       r       0        reserved_memory
+384          1       e       4        boot_option
+385          1       e       4        last_boot
+386          1       e       1        ECC_memory
+388          4       r       0        reboot_bits
+392          3       e       5        baud_rate
+400          1       e       1        power_on_after_fail
+412          4       e       6        debug_level
+416          4       e       7        boot_first
+420          4       e       7        boot_second
+424          4       e       7        boot_third
+428          4       h       0        boot_index
+432	     8       h       0        boot_countdown
+1008         16      h       0        check_sum
+
+enumerations
+
+#ID value   text
+1     0     Disable
+1     1     Enable
+2     0     Enable
+2     1     Disable
+4     0     Fallback
+4     1     Normal
+5     0     115200
+5     1     57600
+5     2     38400
+5     3     19200
+5     4     9600
+5     5     4800
+5     6     2400
+5     7     1200
+6     6     Notice
+6     7     Info
+6     8     Debug
+6     9     Spew
+7     0     Network
+7     1     HDD
+7     2     Floppy
+7     8     Fallback_Network
+7     9     Fallback_HDD
+7     10    Fallback_Floppy
+#7     3     ROM
+
+checksums
+
+checksum 392 1007 1008
+
+
Index: src/mainboard/via/epia-n/mainboard.c
===================================================================
--- src/mainboard/via/epia-n/mainboard.c	(revision 0)
+++ src/mainboard/via/epia-n/mainboard.c	(revision 0)
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 VIA Technologies, Inc.
+ * (Written by Aaron Lwe <aaron.lwe at gmail.com> for VIA)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#include <device/device.h>
+#include "chip.h"
+
+struct chip_operations mainboard_ops = {
+	CHIP_NAME("VIA EPIA-N Mainboard")
+};
Index: src/northbridge/via/cn400/Config.lb
===================================================================
--- src/northbridge/via/cn400/Config.lb	(revision 0)
+++ src/northbridge/via/cn400/Config.lb	(revision 0)
@@ -0,0 +1,9 @@
+uses HAVE_HIGH_TABLES
+
+config chip.h
+
+driver northbridge.o
+driver agp.o
+driver vga.o
+
+default HAVE_HIGH_TABLES=1
Index: src/northbridge/via/cn400/raminit.c
===================================================================
--- src/northbridge/via/cn400/raminit.c	(revision 0)
+++ src/northbridge/via/cn400/raminit.c	(revision 0)
@@ -0,0 +1,827 @@
+/*
+ * (C) Copyright 2005 Nick Barker <nick.barker9 at btinternet.com>
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* 
+  Automatically detect and set up ddr dram on the CLE266 chipset.
+  Assumes DDR memory, though chipset also supports SDRAM
+  Assumes at least 266Mhz memory as no attempt is made to clock
+  the chipset down if slower memory is installed.
+  So far tested on:
+	256 Mb 266Mhz 1 Bank (i.e. single sided)
+	256 Mb 266Mhz 2 Bank (i.e. double sided)
+	512 Mb 266Mhz 2 Bank (i.e. double sided)
+*/
+/* ported and enhanced from assembler level code in coreboot v1 */
+
+#include <spd.h>
+#include <sdram_mode.h>
+#include <delay.h>
+#include <cpu/x86/mtrr.h>
+#include "cn400.h"
+
+static void dimm_read(unsigned long bank,unsigned long x) 
+{
+	//unsigned long eax; 
+	volatile unsigned long y;
+	//eax =  x;
+	y = * (volatile unsigned long *) (x+ bank) ;
+
+}
+
+
+static void print_val(char *str, int val)
+{
+	print_debug(str);
+	print_debug_hex8(val);
+}
+
+/**
+ * Configure the bus between the CPU and the northbridge. This might be
able to 
+ * be moved to post-ram code in the future. For the most part, these
registers
+ * should not be messed around with. These are too complex to explain
short of
+ * copying the datasheets into the comments, but most of these values
are from
+ * the BIOS Porting Guide, so they should work on any board. If they
don't,
+ * try the values from your factory BIOS.
+ *
+ * TODO: Changing the DRAM frequency doesn't work (hard lockup).
+ *
+ * @param dev The northbridge's CPU Host Interface (D0F2).
+ */
+static void c3_cpu_setup(device_t dev)
+{
+	/* Host bus interface registers (D0F2 0x50-0x67) */
+	/* Taken from CN700 and updated from running CN400 */
+	
+	/* Host Bus I/O Circuit (see datasheet) */
+	/* Host Address Pullup/down Driving */
+	pci_write_config8(dev, 0x70, 0x33);
+	pci_write_config8(dev, 0x71, 0x44);
+	pci_write_config8(dev, 0x72, 0x33);
+	pci_write_config8(dev, 0x73, 0x44);
+	
+	/* Output Delay Stagger Control */
+	pci_write_config8(dev, 0x74, 0x70);
+	
+	/* AGTL+ I/O Circuit */
+	pci_write_config8(dev, 0x75, 0x08);
+	
+	/* AGTL+ Compensation Status */
+	pci_write_config8(dev, 0x76, 0x74);
+	
+	/* AGTL+ Auto Compensation Offest */
+	pci_write_config8(dev, 0x77, 0x00);
+	
+	/* Request phase control */
+	pci_write_config8(dev, 0x50, 0xA8);
+
+	/* Line DRDY# Timing Control */
+	pci_write_config8(dev, 0x60, 0x00);
+	pci_write_config8(dev, 0x61, 0x00);
+	pci_write_config8(dev, 0x62, 0x00);
+	
+	/* QW DRDY# Timing Control */
+	pci_write_config8(dev, 0x63, 0x00);
+	pci_write_config8(dev, 0x64, 0x00);
+	pci_write_config8(dev, 0x65, 0x00);
+	
+	/* Read Line Burst DRDY# Timing Control */
+	pci_write_config8(dev, 0x66, 0x00);
+	pci_write_config8(dev, 0x67, 0x00);
+	
+	/* CPU Interface Control */
+	pci_write_config8(dev, 0x51, 0xFE);
+	pci_write_config8(dev, 0x52, 0xEF);
+	
+	/* Arbitration */
+	pci_write_config8(dev, 0x53, 0x88);
+		
+	/* Write Policy & Reorder Latecy */
+	pci_write_config8(dev, 0x56, 0x00);
+	
+	/* Delivery-Trigger Control */
+	pci_write_config8(dev, 0x58, 0x00);
+		
+	/* IPI Control */
+	pci_write_config8(dev, 0x59, 0x30);
+	
+	/* CPU Misc Control */
+	pci_write_config8(dev, 0x5C, 0x00);
+	
+	/* Write Policy */
+	pci_write_config8(dev, 0x5d, 0xb2);
+	
+	/* Bandwidth Timer */
+	pci_write_config8(dev, 0x5e, 0x88);
+	
+	/* CPU Miscellaneous Control */
+	pci_write_config8(dev, 0x5f, 0xc7);
+	
+	/* CPU Miscellaneous Control */
+	pci_write_config8(dev, 0x55, 0x28);
+	
+}
+ 
+static void ddr_ram_setup(void) 
+{
+	//device_t north;
+	uint8_t b, c, bank, ma;
+	uint16_t i;
+	unsigned long bank_address;
+	
+	
+	print_debug("CN400 RAM init starting\r\n");	
+
+	//north = pci_locate_device(PCI_ID(0x1106, 0x7259), 0);
+	pci_write_config8(ctrl.d0f7, 0x75, 0x08);
+	
+		
+	/* No  Interleaving or Multi Page */
+	//north = pci_locate_device(PCI_ID(0x1106, 0x3259), 0);
+	pci_write_config8(ctrl.d0f3, 0x69, 0x00);
+	pci_write_config8(ctrl.d0f3, 0x6b, 0x10);	
+	
+/*
+    DRAM MA Map Type  Device 0  Fn3 Offset 50-51
+
+    Determine memory addressing based on the module's memory technology
and
+    arrangement.  See Table 4-9 of Intel's 82443GX datasheet for
details.
+
+    Bank 1/0 MA map type   50[7-5]
+    Bank 1/0 command rate  50[4]
+    Bank 3/2 MA map type   50[3-1]
+    Bank 3/2 command rate  50[0]
+
+
+    Read SPD byte 17, Number of banks on SDRAM device.
+*/
+	c = 0;
+	b = smbus_read_byte(0x50, SPD_NUM_BANKS_PER_SDRAM);
+	//print_val("Detecting Memory\r\nNumber of Banks ",b);
+
+	// Only supporting 4 bank chips just now
+	if( b == 4 ){
+		/*
+    		Read SPD byte 3, Number of row addresses.
+		*/
+		c = 0;
+		bank = 0x40;
+		b = smbus_read_byte(0x50, SPD_NUM_ROWS);
+		//print_val("\r\nNumber of Rows ", b);
+		
+		if( b >= 0x0d ){	// 256/512Mb
+		
+			if (b == 0x0e)
+				bank = 0x48;
+			else
+				bank = 0x44;
+			 
+			/*
+    			Read SPD byte 13, Primary DRAM width.
+			*/
+			b = smbus_read_byte(0x50,
SPD_PRIMARY_SDRAM_WIDTH);
+			//print_val("\r\nPrimary DRAM width", b);
+			if( b != 4 )   // not 64/128Mb (x4)
+				c = 0x80;  // 256Mb
+		}
+
+		/*
+    		Read SPD byte 4, Number of column addresses.
+		*/		
+		b = smbus_read_byte(0x50, SPD_NUM_COLUMNS);
+		//print_val("\r\nNo Columns ",b);
+		if( b == 10 || b == 11 || b == 12) c |= 0x60;   // 10/11
bit col addr
+		if( b == 9 ) c |= 0x40;           // 9 bit col addr
+		if( b == 8 ) c |= 0x20;           // 8 bit col addr
+
+		//print_val("\r\nMA type ", c);
+		pci_write_config8(ctrl.d0f3, 0x50, c);
+
+	}
+/*	else
+	{
+		die("DRAM module size is not supported by CN400\r\n");
+	}
+*/
+
+/*
+    DRAM bank size.  See 4.3.1 pg 35
+
+    5a->5d  set to end address for each bank.  1 bit == 32MB
+    5a = bank 0
+    5b = bank 0 + b1
+    5c = bank 0 + b1 + b2
+    5d = bank 0 + b1 + b2 + b3
+*/
+
+	// Read SPD byte 31 Module bank density
+	//c = 0;
+	b = smbus_read_byte(0x50, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
+	if( b & 0x02 )
+	{ 
+		c = 0x40;         				// 2GB
+		bank |= 0x02;
+	}
+	else if( b & 0x01) 
+	{
+		c = 0x20;    					// 1GB
+		if (bank == 0x48) bank |= 0x01;
+		else bank |= 0x03;
+	}
+	else if( b & 0x80)
+	{
+		c = 0x10;    					// 512MB
+		if (bank == 0x44) bank |= 0x02;
+	}
+	else if( b & 0x40) 
+	{	
+		c = 0x08;    					// 256MB
+		if (bank == 0x44) bank |= 0x01;
+		else bank |= 0x03;
+	} 
+	else if( b & 0x20)
+	{
+		c = 0x04;    					// 128MB
+		if (bank == 0x40) bank |= 0x02;
+	}
+	else if( b & 0x10)
+	{
+		c = 0x02;    					// 64MB
+		bank |= 0x01;
+	}
+	else if( b & 0x08) c = 0x01;    	// 32MB
+	else c = 0x01;                  	// Error, use default
+
+	//print_val("\r\nBank 0 (*32 Mb) ",c);
+
+	// set bank zero size
+	pci_write_config8(ctrl.d0f3, 0x40, c);
+	
+	// SPD byte 5  # of physical banks
+	b = smbus_read_byte(0x50, SPD_NUM_DIMM_BANKS);
+
+	//print_val("\r\nNo Physical Banks ",b);
+	if( b == 2)
+	{
+		c <<=1;
+		bank |= 0x80;
+		//print_val("\r\nTotal Memory (*32 Mb) ",c);
+	}
+/*	else
+	{
+		die("Only a single DIMM is supported by EPIA-N(L)\r\n");

+	}
+*/
+	// set banks 1,2,3...
+	pci_write_config8(ctrl.d0f3, 0x41,c);
+	pci_write_config8(ctrl.d0f3, 0x42,c);
+	pci_write_config8(ctrl.d0f3, 0x43,c);
+	pci_write_config8(ctrl.d0f3, 0x44,c);
+	pci_write_config8(ctrl.d0f3, 0x45,c);
+	pci_write_config8(ctrl.d0f3, 0x46,c);
+	pci_write_config8(ctrl.d0f3, 0x47,c);
+	
+	ma = bank;
+		
+	/* Read SPD byte 18 CAS Latency */
+	b = smbus_read_byte(0x50, SPD_ACCEPTABLE_CAS_LATENCIES);
+/*	print_debug("\r\nCAS Supported ");
+	if(b & 0x04)
+		print_debug("2 ");
+	if(b & 0x08)
+		print_debug("2.5 ");
+	if(b & 0x10)
+		print_debug("3");
+
+	c = smbus_read_byte(0x50, SPD_MIN_CYCLE_TIME_AT_CAS_MAX);
+	print_val("\r\nCycle time at CL X     (nS)", c);
+	c = smbus_read_byte(0x50, SPD_SDRAM_CYCLE_TIME_2ND);
+	print_val("\r\nCycle time at CL X-0.5 (nS)", c);
+	c = smbus_read_byte(0x50, SPD_SDRAM_CYCLE_TIME_3RD);
+	print_val("\r\nCycle time at CL X-1   (nS)", c);
+*/	
+	bank = smbus_read_byte(0x50, SPD_MIN_CYCLE_TIME_AT_CAS_MAX);
+
+	/* Setup DRAM Cycle Time */
+	if ( bank <= 0x50 ) bank = 0x14;
+	else if (bank <= 0x60) bank = 0x18;
+	else bank = 0x1E;
+		
+	if( b & 0x10 ){             // DDR offering optional CAS 3
+		//print_debug("\r\nStarting at CAS 3");
+		c = 0x30;
+		/* see if we can better it */
+		if( b & 0x08 ){     // DDR mandatory CAS 2.5
+			if( smbus_read_byte(0x50,
SPD_SDRAM_CYCLE_TIME_2ND) <= bank ){ // we can manage max MHz at CAS 2.5
+				//print_debug("\r\nWe can do CAS 2.5");
+				c = 0x20;
+			}
+		}
+		if( b & 0x04 ){     // DDR mandatory CAS 2
+			if( smbus_read_byte(0x50,
SPD_SDRAM_CYCLE_TIME_3RD) <= bank ){ // we can manage max Mhz at CAS 2
+				//print_debug("\r\nWe can do CAS 2");
+				c = 0x10;
+			}
+		}
+	}else{                     // no optional CAS values just 2 &
2.5
+		//print_debug("\r\nStarting at CAS 2.5");
+		c = 0x20;          // assume CAS 2.5
+		if( b & 0x04){      // Should always happen
+			if( smbus_read_byte(0x50,
SPD_SDRAM_CYCLE_TIME_2ND) <= bank){ // we can manage max Mhz at CAS 2
+				//print_debug("\r\nWe can do CAS 2");
+				c = 0x10;
+			}
+		}
+	}	
+
+/*
+    DRAM Timing  Device 0  Fn 3 Offset 56
+
+    RAS Pulse width 56[7,6]
+    CAS Latency     56[5,4]
+    Row pre-charge  56[1,0]
+
+         SDR  DDR
+      00  1T   -
+      01  2T   2T
+      10  3T   2.5T
+      11  -    3T
+
+    RAS/CAS delay   56[3,2]
+
+    Determine row pre-charge time (tRP)
+
+
+    Read SPD byte 27, min row pre-charge time.
+*/
+
+	b = smbus_read_byte(0x50, SPD_MIN_ROW_PRECHARGE_TIME);
+	
+	//print_val("\r\ntRP ",b);
+	if ( b >= (5 * bank)) {
+		c |= 0x03;		// set tRP = 5T
+	}
+	else if ( b >= (4 * bank)) {
+		c |= 0x02;		// set tRP = 4T
+	}
+	else if ( b >= (3 * bank)) {
+		c |= 0x01;		// set tRP = 3T
+	}
+
+/*
+    Determine RAS to CAS delay (tRCD)
+
+    Read SPD byte 29, min row pre-charge time.
+*/
+
+	b = smbus_read_byte(0x50, SPD_MIN_RAS_TO_CAS_DELAY);
+	//print_val("\r\ntRCD ",b);
+
+	if ( b >= (5 * bank)) c |= 0x0C;		// set tRCD = 5T
+	else if ( b >= (4 * bank)) c |= 0x08;	// set tRCD = 4T
+	else if ( b >= (3 * bank)) c |= 0x04;	// set tRCD = 3T
+
+/*
+    Determine RAS pulse width (tRAS)
+
+
+    Read SPD byte 30, device min active to pre-charge time.
+*/
+
+	b = smbus_read_byte(0x50, SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
+	//print_val("\r\ntRAS ",b);
+	if ( b >= (9 * bank)) c |= 0xC0;		// set tRAS = 9T
+	else if ( b >= (8 * bank)) c |= 0x80;	// set tRAS = 8T
+	else if ( b >= (7 * bank)) c |= 0x40;	// set tRAS = 7T
+	
+	/* Write DRAM Timing All Banks I */
+	pci_write_config8(ctrl.d0f3, 0x56, c);
+	
+	/* TWrite DRAM Timing All Banks II */
+	pci_write_config8(ctrl.d0f3, 0x57, 0x1a);
+	
+	/* Enable DIMM Ranks */
+	//pci_write_config8(ctrl.d0f3, 0x48, ma);
+	//udelay(200);
+	
+
+	/* DRAM arbitration timer */
+	pci_write_config8(ctrl.d0f3, 0x65, 0x99);
+	
+/*
+    CPU Frequency  Device 0 Function 2 Offset 54
+
+	CPU FSB Operating Frequency (bits 7:5)
+	      000 : 100MHz    001 : 133MHz
+	      010 : 200MHz    
+	      011->111 : Reserved
+		  
+	SDRAM BL8 (4)
+*/	
+	pci_write_config8(ctrl.d0f3, 0x54, 0x38);
+	
+/*
+    DRAM Clock  Device 0 Fn 3 Offset 68
+*/
+	bank = smbus_read_byte(0x50, SPD_MIN_CYCLE_TIME_AT_CAS_MAX);
+
+	/* Setup DRAM Cycle Time */
+	if ( bank <= 0x50 )
+	{
+		/* DRAM DDR Control Alert! Alert! See also c3_cpu_setup
*/
+		/* This sets to 133MHz FSB / DDR400. */
+		pci_write_config8(ctrl.d0f3, 0x68, 0x85);
+	}
+	else if (bank <= 0x60)
+	{
+		/* DRAM DDR Control Alert! Alert! This hardwires to */
+		/* 133MHz FSB / DDR333.  See also c3_cpu_setup */
+		pci_write_config8(ctrl.d0f3, 0x68, 0x81);
+	}
+	else 
+	{
+		/* DRAM DDR Control Alert! Alert! This hardwires to */
+		/* 133MHz FSB / DDR266.  See also c3_cpu_setup */
+		pci_write_config8(ctrl.d0f3, 0x68, 0x80);
+	}
+
+	/* Delay >= 100ns after DRAM Frequency adjust, See 4.1.1.3 pg 15
*/
+	udelay(200);
+
+/*
+    Determine bank interleave
+
+    Read SPD byte 17, Number of banks on SDRAM device.
+*/
+	c = 0x0F;
+	b = smbus_read_byte(0x50, SPD_NUM_BANKS_PER_SDRAM);
+	if( b == 4) c |= 0x80;
+	else if (b == 2) c |= 0x40;
+
+	/* 4-Way Interleave With Multi-Paging (From Running System)*/
+	pci_write_config8(ctrl.d0f3, 0x69, c);
+	
+	/* DRAM Arbitration Control */
+	pci_write_config8(ctrl.d0f3, 0x66, 0x82);
+
+	/* DRAM Control */
+	pci_write_config8(ctrl.d0f3, 0x6e, 0x00);
+	
+	/* Disable refresh for now */
+	pci_write_config8(ctrl.d0f3, 0x6a, 0x00);
+
+
+
+	/* DRAM Clock Control */
+	pci_write_config8(ctrl.d0f3, 0x6c, 0x00);
+
+	/* DRAM Bus Turn-Around Setting */
+	pci_write_config8(ctrl.d0f3, 0x60, 0x01);
+	
+	/* Disable DRAM refresh */
+	pci_write_config8(ctrl.d0f3,0x6a,0x0);
+
+
+	/* Memory Pads Driving and Range Select */
+	pci_write_config8(ctrl.d0f3, 0xe2, 0xAA);
+	pci_write_config8(ctrl.d0f3, 0xe3, 0x00);
+	pci_write_config8(ctrl.d0f3, 0xe4, 0x99);
+
+	/* DRAM signal timing control */
+	pci_write_config8(ctrl.d0f3, 0x74, 0x99);	
+	pci_write_config8(ctrl.d0f3, 0x76, 0x09);
+
+	pci_write_config8(ctrl.d0f3, 0xe0, 0xAA);
+	pci_write_config8(ctrl.d0f3, 0xe1, 0x00);
+	pci_write_config8(ctrl.d0f3, 0xe6, 0x00);
+	pci_write_config8(ctrl.d0f3, 0xe8, 0xEE);
+	pci_write_config8(ctrl.d0f3, 0xea, 0xEE);
+
+
+	/* SPD byte 5  # of physical banks */
+	b = smbus_read_byte(0x50, SPD_NUM_DIMM_BANKS) -1;
+	c = b | 0x40;
+
+	pci_write_config8(ctrl.d0f3, 0xb0, c);
+	
+	/* Enable DIMM Ranks */
+	pci_write_config8(ctrl.d0f3, 0x48, ma);
+	udelay(200);
+
+		
+	for( bank = 0 , bank_address=0; bank <= b ; bank++) {
+/*
+    DDR init described in Via VT8623 BIOS Porting Guide.  Pg 28
(4.2.3.1)
+*/
+
+		/* NOP command enable */
+		c = pci_read_config8(ctrl.d0f3, DRAM_MISC_CTL);
+		c &= 0xf8;		/* Clear bits 2-0. */
+		c |= RAM_COMMAND_NOP;
+		pci_write_config8(ctrl.d0f3, DRAM_MISC_CTL, c);		
+
+		/* read a double word from any address of the dimm */
+		dimm_read(bank_address,0x1f000);
+		//udelay(200);
+
+		/* All bank precharge Command Enable */
+		c = pci_read_config8(ctrl.d0f3, DRAM_MISC_CTL);
+		c &= 0xf8;		/* Clear bits 2-0. */
+		c |= RAM_COMMAND_PRECHARGE;
+		pci_write_config8(ctrl.d0f3, DRAM_MISC_CTL, c);		
+		dimm_read(bank_address,0x1f000);
+
+
+		/* MSR Enable Low DIMM*/
+		c = pci_read_config8(ctrl.d0f3, DRAM_MISC_CTL);
+		c &= 0xf8;		/* Clear bits 2-0. */
+		c |= RAM_COMMAND_MSR_LOW;
+		pci_write_config8(ctrl.d0f3, DRAM_MISC_CTL, c);		
+		dimm_read(bank_address,0x2000);
+		udelay(1);
+		dimm_read(bank_address,0x800);
+		udelay(1);
+
+		/* All banks precharge Command Enable */
+		c = pci_read_config8(ctrl.d0f3, DRAM_MISC_CTL);
+		c &= 0xf8;		/* Clear bits 2-0. */
+		c |= RAM_COMMAND_PRECHARGE;
+		pci_write_config8(ctrl.d0f3, DRAM_MISC_CTL, c);		
+		dimm_read(bank_address,0x1f200);
+
+		/* CBR Cycle Enable */
+		c = pci_read_config8(ctrl.d0f3, DRAM_MISC_CTL);
+		c &= 0xf8;		/* Clear bits 2-0. */
+		c |= RAM_COMMAND_CBR;
+		pci_write_config8(ctrl.d0f3, DRAM_MISC_CTL, c);		
+
+		/* Read 8 times */
+		dimm_read(bank_address,0x1f300);
+		udelay(100);
+		dimm_read(bank_address,0x1f400);
+		udelay(100);
+		dimm_read(bank_address,0x1f500);
+		udelay(100);
+		dimm_read(bank_address,0x1f600);
+		udelay(100);
+		dimm_read(bank_address,0x1f700);
+		udelay(100);
+		dimm_read(bank_address,0x1f800);
+		udelay(100);
+		dimm_read(bank_address,0x1f900);
+		udelay(100);
+		dimm_read(bank_address,0x1fa00);
+		udelay(100);
+
+		/* MSR Enable */
+		c = pci_read_config8(ctrl.d0f3, DRAM_MISC_CTL);
+		c &= 0xf8;		/* Clear bits 2-0. */
+		c |= RAM_COMMAND_MSR_LOW;
+		pci_write_config8(ctrl.d0f3, DRAM_MISC_CTL, c);		
+
+/* 
+    Mode Register Definition
+    with adjustement so that address calculation is correct - 64 bit
technology, therefore
+    a0-a2 refer to byte within a 64 bit long word, and a3 is the first
address line presented
+    to DIMM as a row or column address.
+
+    MR[9-7]   CAS Latency
+    MR[6]     Burst Type 0 = sequential, 1 = interleaved
+    MR[5-3]   burst length 001 = 2, 010 = 4, 011 = 8, others reserved
+    MR[0-2]   dont care 
+
+    CAS Latency 
+    000       reserved
+    001       reserved
+    010       2
+    011       3
+    100       reserved
+    101       1.5
+    110       2.5
+    111       reserved
+
+    CAS 2     0101011000 = 0x158
+    CAS 2.5   1101011000 = 0x358
+    CAS 3     0111011000 = 0x1d8
+
+*/
+		c = pci_read_config8(ctrl.d0f3, 0x56);
+		if( (c & 0x30) == 0x10 )
+			dimm_read(bank_address,0x150);
+		else if((c & 0x30) == 0x20 )
+			dimm_read(bank_address,0x350);
+		else
+			dimm_read(bank_address,0x1d0);
+
+		//dimm_read(bank_address,0x350);
+
+		/* Normal SDRAM Mode */
+		c = pci_read_config8(ctrl.d0f3, DRAM_MISC_CTL);
+		c &= 0xf8;		/* Clear bits 2-0. */
+		c |= RAM_COMMAND_NORMAL;
+		pci_write_config8(ctrl.d0f3, DRAM_MISC_CTL, c);
+				
+		bank_address = pci_read_config8(ctrl.d0f3,0x40+bank) *
0x2000000;
+	} // end of for each bank
+
+	/* DQS Input Adjust */
+	//c = pci_read_config8(ctrl.d0f3, 0x6b);
+	//c |= 0x80;
+	//pci_write_config8(ctrl.d0f3, 0x6b, c);
+	
+	/* Set DQS A/B Input delay to defaults */
+	pci_write_config8(ctrl.d0f3, 0x7A, 0xA1);
+	pci_write_config8(ctrl.d0f3, 0x7B, 0x62);
+	pci_write_config8(ctrl.d0f3, 0x72, 0x29);
+	pci_write_config8(ctrl.d0f3, 0x73, 0x99);	
+	
+	//c = pci_read_config8(ctrl.d0f3, 0x6b);
+	//c &= 0x7F;
+	//pci_write_config8(ctrl.d0f3, 0x6b, c);
+	
+
+	/* DQS Output Adjust (data strobe output delay). */
+	//c = pci_read_config8(ctrl.d0f3, 0x6b);
+	//c |= 0x40;
+	//pci_write_config8(ctrl.d0f3, 0x6b, c);
+
+	/* SPD byte 5  # of physical banks */
+	b = smbus_read_byte(0x50, SPD_NUM_DIMM_BANKS) -1;
+	
+	/* determine low bond */
+	if( b == 2)
+		bank_address = pci_read_config8(ctrl.d0f3,0x40) *
0x2000000;
+	else
+		bank_address = 0;
+
+	for(i = 0x50 ; i < 0x0ff; i++){
+		//c = i ^ (i>>1);			// convert to
gray code
+		pci_write_config8(ctrl.d0f3,0x70,i);
+		// clear
+		*(volatile unsigned long*)(0x4000) = 0;
+		*(volatile unsigned long*)(0x4100+bank_address) = 0;
+		*(volatile unsigned long*)(0x4200) = 0;
+		*(volatile unsigned long*)(0x4300+bank_address) = 0;
+		*(volatile unsigned long*)(0x4400) = 0;
+		*(volatile unsigned long*)(0x4500+bank_address) = 0;
+
+
+		// fill
+		*(volatile unsigned long*)(0x4000) = 0x12345678;
+		*(volatile unsigned long*)(0x4100+bank_address) =
0x81234567;
+		*(volatile unsigned long*)(0x4200) = 0x78123456;
+		*(volatile unsigned long*)(0x4300+bank_address) =
0x67812345;
+		*(volatile unsigned long*)(0x4400) = 0x56781234;
+		*(volatile unsigned long*)(0x4500+bank_address) =
0x45678123;
+
+			// verify
+		if( *(volatile unsigned long*)(0x4000) != 0x12345678)
+			continue;
+
+		if( *(volatile unsigned long*)(0x4100+bank_address) !=
0x81234567)
+			continue;
+
+		if( *(volatile unsigned long*)(0x4200) != 0x78123456)
+			continue;
+
+		if( *(volatile unsigned long*)(0x4300+bank_address) !=
0x67812345)
+			continue;
+
+		if( *(volatile unsigned long*)(0x4400) != 0x56781234)
+			continue;
+
+		if( *(volatile unsigned long*)(0x4500+bank_address) !=
0x45678123)
+			continue;
+
+		// if everything verified then found low bond
+		break;
+		
+	}
+	print_val("\r\nLow Bond ",i);	
+	if( i < 0xff ){ 
+		c = i++;
+		for(  ; i <0xff ; i++){
+ 			//pci_write_config8(ctrl.d0f3,0x70,i ^ (i>>1) );
+			pci_write_config8(ctrl.d0f3,0x70, i);
+			// clear
+			*(volatile unsigned long*)(0x8000) = 0;
+			*(volatile unsigned long*)(0x8100+bank_address)
= 0;
+			*(volatile unsigned long*)(0x8200) = 0x0;
+			*(volatile unsigned long*)(0x8300+bank_address)
= 0;
+			*(volatile unsigned long*)(0x8400) = 0x0;
+			*(volatile unsigned long*)(0x8500+bank_address)
= 0;
+
+			// fill
+			*(volatile unsigned long*)(0x8000) = 0x12345678;
+			*(volatile unsigned long*)(0x8100+bank_address)
= 0x81234567;
+			*(volatile unsigned long*)(0x8200) = 0x78123456;
+			*(volatile unsigned long*)(0x8300+bank_address)
= 0x67812345;
+			*(volatile unsigned long*)(0x8400) = 0x56781234;
+			*(volatile unsigned long*)(0x8500+bank_address)
= 0x45678123;
+
+			// verify
+			if( *(volatile unsigned long*)(0x8000) !=
0x12345678)
+				break;
+
+			if( *(volatile unsigned
long*)(0x8100+bank_address) != 0x81234567)
+				break;
+
+			if( *(volatile unsigned long*)(0x8200) !=
0x78123456)
+				break;
+
+			if( *(volatile unsigned
long*)(0x8300+bank_address) != 0x67812345)
+				break;
+
+			if( *(volatile unsigned long*)(0x8400) !=
0x56781234)
+				break;
+
+			if( *(volatile unsigned
long*)(0x8500+bank_address) != 0x45678123)
+				break;
+
+		}
+		print_val("  High Bond ",i);
+		print_debug("\r\n");
+		c = ((i - c)<<1)/3 + c;
+		print_val("  Setting DQS delay",c);
+		print_debug("\r\n");
+		//c = c ^ (c>>1);		// convert to gray code
+		pci_write_config8(ctrl.d0f3,0x70,c);
+		// pci_write_config8(ctrl.d0f3,0x70,0x67);
+	}else{
+		//print_debug("Setting DQS Delay default\r\n");
+		pci_write_config8(ctrl.d0f3,0x70,0x67);
+	}
+
+	/* Set DQS ChB Output to the default */
+	pci_write_config8(ctrl.d0f3, 0x71, 0x6c);
+	
+	/* Disable DQS Output Adjust */
+	//b = pci_read_config8(ctrl.d0f3, 0x6b);
+	//b &= 0xbf;
+	//pci_write_config8(ctrl.d0f3, 0x6b, b);
+	
+	b = pci_read_config8(ctrl.d0f3, 0x69);
+	b |= 0x10;
+	pci_write_config8(ctrl.d0f3, 0x69, b);
+	
+	pci_write_config8(ctrl.d0f3, 0x79, 0x11);
+
+
+/*
+    DRAM refresh rate  Device 0 F3 Offset 6a
+	TODO :: Fix for different DRAM technologies 
+	other than 512Mb and DRAM Freq 
+    Units of 16 DRAM clock cycles. 
+*/
+
+	pci_write_config8(ctrl.d0f3,0x6a,0x6C);
+	
+	/* Open Up the Rest of the Shadow RAM */
+	pci_write_config8(ctrl.d0f3,0x80,0xff);
+	pci_write_config8(ctrl.d0f3,0x81,0xff);
+	
+
+	/* pci */
+	//north = pci_locate_device(PCI_ID(0x1106, 0x7259), 0);
+	pci_write_config8(ctrl.d0f7, 0x70,0x82);
+	pci_write_config8(ctrl.d0f7,0x73,0x01);
+	pci_write_config8(ctrl.d0f7,0x76,0x50);
+
+	pci_write_config8(ctrl.d0f7,0x71,0xc8);
+	
+    print_debug("CN400 Init done\r\n");
+
+	/* Graphics Control Basic Init. */
+	//north = pci_locate_device(PCI_ID(0x1106, 0x3259), 0);
+	pci_write_config8(ctrl.d0f3, 0xb0, 0xFf);
+	pci_write_config8(ctrl.d0f3, 0xb1, 0xAA);
+	pci_write_config8(ctrl.d0f3, 0xb2, 0xAA);
+	pci_write_config8(ctrl.d0f3, 0xb3, 0x5A);
+	pci_write_config8(ctrl.d0f3, 0xb4, 0x0f);
+	
+	/* AGP Controller Interface Basic Init */
+	pci_write_config8(ctrl.d0f3, 0xc0, 0x3b);
+	
+	/* VGA device, Basic frame Buffer Init. */
+	pci_write_config8(ctrl.d0f3, 0xa0, 0x01);
+	/* Bit 7 = Enable VGA When Set to 1 */
+	pci_write_config8(ctrl.d0f3, 0xa1, 0xef);
+	pci_write_config8(ctrl.d0f3, 0xa4, 0x00);
+
+}	
Index: src/northbridge/via/cn400/vgachip.h
===================================================================
--- src/northbridge/via/cn400/vgachip.h	(revision 0)
+++ src/northbridge/via/cn400/vgachip.h	(revision 0)
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood at gmail.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#ifndef _PC80_VGABIOS
+#define _PC80_VGABIOS
+
+extern struct chip_control pc80_vgabios_control;
+
+struct pc80_vgabios_config {
+	int nothing;
+};
+
+void vga_enable_console(void);
+void do_vgabios(void);
+void setup_realmode_idt(void);
+void write_protect_vgabios(void);
+
+#endif /* _PC80_VGABIOS */
Index: src/northbridge/via/cn400/agp.c
===================================================================
--- src/northbridge/via/cn400/agp.c	(revision 0)
+++ src/northbridge/via/cn400/agp.c	(revision 0)
@@ -0,0 +1,173 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood at gmail.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "chip.h"
+#include "northbridge.h"
+#include "cn400.h"
+
+/* This is the main AGP device, and only one used when configured for
AGP 2.0 */
+static void agp_init(device_t dev)
+{
+	u32 reg32;
+
+	/* Some of this may not be necessary (should be handled by the
OS). */
+	printk_debug("Enabling AGP.\n");
+
+	/* Allow R/W access to AGP registers. */
+	pci_write_config8(dev, 0x4d, 0x15);
+
+	/* Setup PCI latency timer. */
+	pci_write_config8(dev, 0xd, 0x8);
+
+	/*
+	 * Set to AGP 3.0 Mode, which should theoretically render the
rest of
+	 * the registers set here pointless.
+	 */
+	pci_write_config8(dev, 0x84, 0xb);
+
+	/* AGP Request Queue Size */
+	pci_write_config8(dev, 0x4a, 0x1f);
+
+	/*
+	 * AGP Hardware Support (default 0xc4)
+	 * 7: AGP SBA Enable (1 to Enable)
+	 * 6: AGP Enable
+	 * 5: Reserved
+	 * 4: Fast Write Enable
+	 * 3: AGP8X Mode Enable
+	 * 2: AGP4X Mode Enable
+	 * 1: AGP2X Mode Enable
+	 * 0: AGP1X Mode Enable
+	 */
+	pci_write_config8(dev, 0x4b, 0xc4);
+
+	/* Enable AGP Backdoor */
+	pci_write_config8(dev, 0xb5, 0x03);
+
+	/* Set aperture to 32 MB. */
+	/* TODO: Use config option, explain how it works. */
+	pci_write_config32(dev, 0x94, 0x00010f38);
+	/* Set GART Table Base Address (31:12). */
+	pci_write_config32(dev, 0x98, (0x1558 << 12));
+	/* Set AGP Aperture Base. */
+	pci_write_config32(dev, 0x10, 0xf8000008);
+
+	/* Enable CPU/PMSTR GART Access. */
+	reg32 = pci_read_config8(dev, 0xbf);
+	reg32 |= 0x80;
+	pci_write_config8(dev, 0xbf, reg32);
+
+	/* Enable AGP Aperture. */
+	reg32 = pci_read_config32(dev, 0x94);
+	reg32 |= (3 << 7);
+	pci_write_config32(dev, 0x90, reg32);
+
+	/* AGP Control */
+	pci_write_config8(dev, 0xbc, 0x21);
+	pci_write_config8(dev, 0xbd, 0xd2);
+
+	/*
+	 * AGP Pad, driving strength, and delay control. All this should
be
+	 * constant, seeing as the VGA controller is onboard.
+	 */
+	pci_write_config8(dev, 0x40, 0xc7);
+	pci_write_config8(dev, 0x41, 0xdb);
+	pci_write_config8(dev, 0x42, 0x10);
+	pci_write_config8(dev, 0x43, 0xdb);
+	pci_write_config8(dev, 0x44, 0x24);
+
+	/* AGPC CKG Control */
+	pci_write_config8(dev, 0xc0, 0x02);
+	pci_write_config8(dev, 0xc1, 0x02);
+}
+
+static const struct device_operations agp_operations = {
+	.read_resources   = cn400_noop,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = agp_init,
+	.ops_pci          = 0,
+};
+
+static const struct pci_driver agp_driver __pci_driver = {
+	.ops    = &agp_operations,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_CN400_AGP,
+};
+
+/*
+ * This is the AGP 3.0 "bridge" @Bus 0 Device 1 Func 0. When using AGP
3.0, the
+ * config in this device takes presidence. We configure both just to be
safe.
+ */
+static void agp_bridge_init(device_t dev)
+{
+	printk_debug("Setting up AGP bridge device\n");
+
+	pci_write_config16(dev, 0x4, 0x0007);
+
+	/* Secondary Bus Number */
+	pci_write_config8(dev, 0x19, 0x01);
+	/* Subordinate Bus Number */
+	pci_write_config8(dev, 0x1a, 0x01);
+	/* I/O Base */
+	pci_write_config8(dev, 0x1c, 0xd0);
+	/* I/O Limit */
+	pci_write_config8(dev, 0x1d, 0xd0);
+
+	/* Memory Base */
+	pci_write_config16(dev, 0x20, 0xfb00);
+	/* Memory Limit */
+	pci_write_config16(dev, 0x22, 0xfcf0);
+	/* Prefetchable Memory Base */
+	pci_write_config16(dev, 0x24, 0xf400);
+	/* Prefetchable Memory Limit */
+	pci_write_config16(dev, 0x26, 0xf7f0);
+	/* Enable VGA Compatible Memory/IO Range */
+	pci_write_config8(dev, 0x3e, 0x08);
+
+	/* Second PCI Bus Control (see datasheet) */
+	pci_write_config8(dev, 0x40, 0x83);
+	pci_write_config8(dev, 0x41, 0x43);
+	pci_write_config8(dev, 0x42, 0xe2);
+	pci_write_config8(dev, 0x43, 0x44);
+	pci_write_config8(dev, 0x44, 0x34);
+	pci_write_config8(dev, 0x45, 0x72);
+}
+
+static const struct device_operations agp_bridge_operations = {
+	.read_resources   = cn400_noop,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_bus_enable_resources,
+	.init             = agp_bridge_init,
+	.scan_bus         = pci_scan_bridge,
+	.ops_pci          = 0,
+};
+
+static const struct pci_driver agp_bridge_driver __pci_driver = {
+	.ops    = &agp_bridge_operations,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_CN400_BRIDGE,
+};
Index: src/northbridge/via/cn400/northbridge.c
===================================================================
--- src/northbridge/via/cn400/northbridge.c	(revision 0)
+++ src/northbridge/via/cn400/northbridge.c	(revision 0)
@@ -0,0 +1,275 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 VIA Technologies, Inc.
+ * (Written by Aaron Lwe <aaron.lwe at gmail.com> for VIA)
+ * Copyright (C) 2007 Corey Osgood <corey.osgood at gmail.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/cpu.h>
+#include "chip.h"
+#include "northbridge.h"
+#include "cn400.h"
+
+static void memctrl_init(device_t dev)
+{
+	device_t vlink_dev;
+	u16 reg16;
+	u8 ranks, pagec, paged, pagee, pagef, shadowreg;
+
+	/* Set up the VGA framebuffer size. */
+	reg16 = (log2(CONFIG_VIDEO_MB) << 12) | (1 << 15);
+	pci_write_config16(dev, 0xa0, reg16);
+
+	/* Set up VGA timers. */
+	pci_write_config8(dev, 0xa2, 0x44);
+
+	for (ranks = 0x4b; ranks >= 0x48; ranks--) {
+		if (pci_read_config8(dev, ranks)) {
+			ranks -= 0x48;
+			break;
+		}
+	}
+	if (ranks == 0x47)
+		ranks = 0x00;
+	reg16 = 0xaae0;
+	reg16 |= ranks;
+	/* GMINT Misc. FrameBuffer rank */
+	pci_write_config16(dev, 0xb0, reg16);
+	/* AGPCINT Misc. */
+	pci_write_config8(dev, 0xb8, 0x08);
+
+	/* Shadow RAM */
+	pagec = 0xff, paged = 0xff, pagee = 0xff, pagef = 0x30;
+	/* PAGE C, D, E are all read write enable */
+	pci_write_config8(dev, 0x80, pagec);
+	pci_write_config8(dev, 0x81, paged);
+	pci_write_config8(dev, 0x82, pagee);
+	/* PAGE F are read/writable */
+	shadowreg = pci_read_config8(dev, 0x83);
+	shadowreg |= pagef;
+	pci_write_config8(dev, 0x83, shadowreg);
+	/* vlink mirror */
+	vlink_dev = dev_find_device(PCI_VENDOR_ID_VIA,
+				    PCI_DEVICE_ID_VIA_CN400_VLINK, 0);
+	if (vlink_dev) {
+		pci_write_config8(vlink_dev, 0x61, pagec);
+		pci_write_config8(vlink_dev, 0x62, paged);
+		pci_write_config8(vlink_dev, 0x64, pagee);
+
+		shadowreg = pci_read_config8(vlink_dev, 0x63);
+		shadowreg |= pagef;
+		pci_write_config8(vlink_dev, 0x63, shadowreg);
+	}
+}
+
+static const struct device_operations memctrl_operations = {
+	.read_resources = cn400_noop,
+	.init           = memctrl_init,
+};
+
+static const struct pci_driver memctrl_driver __pci_driver = {
+	.ops    = &memctrl_operations,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_CN400_MEMCTRL,
+};
+
+static void pci_domain_read_resources(device_t dev)
+{
+	struct resource *resource;
+
+	printk_spew("Entering cn400 pci_domain_read_resources.\n");
+
+	/* Initialize the system wide I/O space constraints. */
+	resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
+	resource->limit = 0xffffUL;
+	resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
+	    IORESOURCE_ASSIGNED;
+
+	/* Initialize the system wide memory resources constraints. */
+	resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+	resource->limit = 0xffffffffULL;
+	resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
+	    IORESOURCE_ASSIGNED;
+
+	printk_spew("Leaving cn400 pci_domain_read_resources.\n");
+}
+
+static void ram_resource(device_t dev, unsigned long index,
+			 unsigned long basek, unsigned long sizek)
+{
+	struct resource *resource;
+
+	if (!sizek)
+		return;
+
+	resource = new_resource(dev, index);
+	resource->base = ((resource_t) basek) << 10;
+	resource->size = ((resource_t) sizek) << 10;
+	resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE |
+	    IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+}
+
+static void tolm_test(void *gp, struct device *dev, struct resource
*new)
+{
+	struct resource **best_p = gp;
+	struct resource *best;
+
+	best = *best_p;
+	if (!best || (best->base > new->base))
+		best = new;
+	*best_p = best;
+}
+
+static u32 find_pci_tolm(struct bus *bus)
+{
+	struct resource *min;
+	u32 tolm;
+
+	print_debug("Entering find_pci_tolm\n");
+
+	min = 0;
+	search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM,
+			     tolm_test, &min);
+	tolm = 0xffffffffUL;
+	if (min && tolm > min->base)
+		tolm = min->base;
+
+	print_debug("Leaving find_pci_tolm\n");
+
+	return tolm;
+}
+
+#if HAVE_HIGH_TABLES==1
+/* maximum size of high tables in KB */
+#define HIGH_TABLES_SIZE 64
+extern uint64_t high_tables_base, high_tables_size;
+#endif
+
+static void pci_domain_set_resources(device_t dev)
+{
+	/* The order is important to find the correct RAM size. */
+	static const u8 ramregs[] = { 0x43, 0x42, 0x41, 0x40 };
+	device_t mc_dev;
+	u32 pci_tolm;
+
+	printk_spew("Entering cn400 pci_domain_set_resources.\n");
+
+	pci_tolm = find_pci_tolm(&dev->link[0]);
+	mc_dev = dev_find_device(PCI_VENDOR_ID_VIA,
+				 PCI_DEVICE_ID_VIA_CN400_MEMCTRL, 0);
+
+	if (mc_dev) {
+		unsigned long tomk, tolmk;
+		unsigned char rambits;
+		int i, idx;
+
+		/*
+		 * Once the register value is not zero, the RAM size is
+		 * this register's value multiply 64 * 1024 * 1024.
+		 */
+		for (rambits = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) {
+			rambits = pci_read_config8(mc_dev, ramregs[i]);
+			if (rambits != 0)
+				break;
+		}
+
+		tomk = rambits * 64 * 1024;
+		printk_spew("tomk is 0x%x\n", tomk);
+		/* Compute the Top Of Low Memory (TOLM), in Kb. */
+		tolmk = pci_tolm >> 10;
+		if (tolmk >= tomk) {
+			/* The PCI hole does does not overlap the
memory. */
+			tolmk = tomk;
+		}
+
+#if HAVE_HIGH_TABLES == 1
+		high_tables_base = (tolmk - HIGH_TABLES_SIZE) * 1024;
+		high_tables_size = HIGH_TABLES_SIZE* 1024;
+		printk_debug("tom: %lx, high_tables_base: %llx,
high_tables_size: %llx\n", tomk*1024, high_tables_base,
high_tables_size);
+#endif
+
+		/* Report the memory regions. */
+		idx = 10;
+		/* TODO: Hole needed? */
+		ram_resource(dev, idx++, 0, 640);	/* First 640k */
+		/* Leave a hole for VGA, 0xa0000 - 0xc0000 */
+		ram_resource(dev, idx++, 768,
+			     (tolmk - 768 - CONFIG_VIDEO_MB * 1024));
+	}
+	assign_resources(&dev->link[0]);
+}
+
+static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
+{
+	printk_debug("Entering cn400 pci_domain_scan_bus.\n");
+
+	max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
+	return max;
+}
+
+static const struct device_operations pci_domain_ops = {
+	.read_resources   = pci_domain_read_resources,
+	.set_resources    = pci_domain_set_resources,
+	.enable_resources = enable_childrens_resources,
+	.init             = 0,
+	.scan_bus         = pci_domain_scan_bus,
+};
+
+static void cpu_bus_init(device_t dev)
+{
+	initialize_cpus(&dev->link[0]);
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+
+static const struct device_operations cpu_bus_ops = {
+	.read_resources   = cpu_bus_noop,
+	.set_resources    = cpu_bus_noop,
+	.enable_resources = cpu_bus_noop,
+	.init             = cpu_bus_init,
+	.scan_bus         = 0,
+};
+
+static void enable_dev(struct device *dev)
+{
+	printk_spew("In cn400 enable_dev for device %s.\n",
dev_path(dev));
+
+	/* Set the operations if it is a special bus type. */
+	if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
+		dev->ops = &pci_domain_ops;
+		pci_set_method(dev);
+	} else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
+		dev->ops = &cpu_bus_ops;
+	}
+}
+
+struct chip_operations northbridge_via_cn400_ops = {
+	CHIP_NAME("VIA CN400 Northbridge")
+	.enable_dev = enable_dev,
+};
Index: src/northbridge/via/cn400/chip.h
===================================================================
--- src/northbridge/via/cn400/chip.h	(revision 0)
+++ src/northbridge/via/cn400/chip.h	(revision 0)
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood at gmail.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+struct northbridge_via_cn400_config {
+};
+
+extern struct chip_operations northbridge_via_cn400_ops;
Index: src/northbridge/via/cn400/raminit.h
===================================================================
--- src/northbridge/via/cn400/raminit.h	(revision 0)
+++ src/northbridge/via/cn400/raminit.h	(revision 0)
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey_osgood at verizon.net>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#ifndef RAMINIT_H
+#define RAMINIT_H
+
+#define DIMM_SOCKETS 1		/* Only one works, for now. */
+
+struct mem_controller {
+	device_t d0f0, d0f2, d0f3, d0f4, d0f7, d1f0;
+	u8 channel0[DIMM_SOCKETS];
+};
+
+#endif
Index: src/northbridge/via/cn400/cn400.h
===================================================================
--- src/northbridge/via/cn400/cn400.h	(revision 0)
+++ src/northbridge/via/cn400/cn400.h	(revision 0)
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood at gmail.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#ifndef __ROMCC__
+static void cn400_noop()
+{
+}
+#endif
+
+/* VGA stuff */
+#define SR_INDEX		0x3c4
+#define SR_DATA			0x3c5
+#define CRTM_INDEX		0x3b4
+#define CRTM_DATA		0x3b5
+#define CRTC_INDEX		0x3d4
+#define CRTC_DATA		0x3d5
+
+/* Memory controller registers */
+#define RANK0_END		0x40
+#define RANK1_END		0x41
+#define RANK2_END		0x42
+#define RANK3_END		0x43
+
+#define DDR_PAGE_CTL			0x69
+#define DRAM_REFRESH_COUNTER	0x6a
+#define DRAM_MISC_CTL			0x6b
+#define CH_A_DQS_OUTPUT_DELAY	0x70
+#define CH_A_MD_OUTPUT_DELAY	0x71
+
+/* RAM init commands */
+#define RAM_COMMAND_NORMAL		(const char) 0x00
+#define RAM_COMMAND_NOP			(const char) 0x01
+#define RAM_COMMAND_PRECHARGE	(const char) 0x02
+#define RAM_COMMAND_MSR_LOW		(const char) 0x03
+#define RAM_COMMAND_CBR			(const char) 0x04
+#define RAM_COMMAND_MSR_HIGH	(const char) 0x05
Index: src/northbridge/via/cn400/vgabios.c
===================================================================
--- src/northbridge/via/cn400/vgabios.c	(revision 0)
+++ src/northbridge/via/cn400/vgabios.c	(revision 0)
@@ -0,0 +1,839 @@
+#include <console/console.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#undef __KERNEL__
+#include <arch/io.h>
+//#include <printk.h>
+#include <string.h>
+#include "vgachip.h"
+
+/* vgabios.c. Derived from: */
+
+/*------------------------------------------------------------ -*- C
-*-
+ *  2 Kernel Monte a.k.a. Linux loading Linux on x86
+ *
+ *  Erik Arjan Hendriks <hendriks at lanl.gov>
+ *
+ *  This version is a derivative of the original two kernel monte
+ *  which is (C) 2000 Scyld.
+ *
+ *  Copyright (C) 2000 Scyld Computing Corporation
+ *
+ *  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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
+ *
+ * Portions related to the alpha architecture are:
+ *
+ *  Copyright(C) 2001 University of California.  LA-CC Number 01-67.
+ *  This software has been authored by an employee or employees of the
+ *  University of California, operator of the Los Alamos National
+ *  Laboratory under Contract No.  W-7405-ENG-36 with the U.S.
+ *  Department of Energy.  The U.S. Government has rights to use,
+ *  reproduce, and distribute this software. If the software is
+ *  modified to produce derivative works, such modified software should
+ *  be clearly marked, so as not to confuse it with the version
+ *  available from LANL.
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU General Public License, incorporated herein by
+ *  reference to http://www.gnu.org/licenses/gpl.html.
+ *
+ *  This software is provided by the author(s) "as is" and any express
+ *  or implied warranties, including, but not limited to, the implied
+ *  warranties of merchantability and fitness for a particular purpose
+ *  are disclaimed.  In no event shall the author(s) be liable for any
+ *  direct, indirect, incidental, special, exemplary, or consequential
+ *  damages (including, but not limited to, procurement of substitute
+ *  goods or services; loss of use, data, or profits; or business
+ *  interruption) however caused and on any theory of liability,
+ *  whether in contract, strict liability, or tort (including
+ *  negligence or otherwise) arising in any way out of the use of this
+ *  software, even if advised of the possibility of such damage.
+ *
+ *  $Id: vgabios.c,v 1.5 2004/10/06 17:33:52 rminnich Exp $
+
*--------------------------------------------------------------------*/
+
+/* Modified to be a self sufficient plug in so that it can be used 
+   without reliance on other parts of coreboot's core
+   (C) 2005 Nick.Barker9 at btinternet.com
+
+  Used initially for epia-m where there are problems getting the bios
+  emulator to successfully run this bios.
+*/
+
+/* Declare a temporary global descriptor table - necessary because the
+   Core part of the bios no longer sets up any 16 bit segments */
+__asm__ (
+	/* pointer to original gdt */
+	"gdtarg:			\n"
+	"	.word	gdt_limit	\n"
+	"	.long	gdt	       	\n"		
+
+	/* compute the table limit */
+	"__mygdt_limit = __mygdt_end - __mygdt - 1	\n"
+
+	"__mygdtaddr:			\n"
+	"	.word	__mygdt_limit  	\n"
+	"	.long	__mygdt	       	\n"
+
+	"__mygdt: 		       	\n"
+	/* selgdt 0, unused */
+	"	.word	0x0000, 0x0000	\n"
+	"	.byte	0x00, 0x00, 0x00, 0x00	\n"
+
+	/* selgdt 8, unused */
+	"	.word	0x0000, 0x0000	       	\n"
+	"	.byte	0x00, 0x00, 0x00, 0x00	\n"
+
+	/* selgdt 0x10, flat code segment */
+	"	.word	0xffff, 0x0000	       	\n"
+	"	.byte	0x00, 0x9b, 0xcf, 0x00	\n"	
+
+	/* selgdt 0x18, flat data segment */
+	"	.word	0xffff, 0x0000	       	\n"
+	"	.byte	0x00, 0x93, 0xcf, 0x00	\n"
+
+	/* selgdt 0x20, unused */
+	"	.word	0x0000, 0x0000	       	\n"
+	"	.byte	0x00, 0x00, 0x00, 0x00	\n"
+
+        /* selgdt 0x28 16-bit 64k code at 0x00000000 */
+	"	.word	0xffff, 0x0000	       	\n"
+	"	.byte	0, 0x9a, 0, 0	       	\n"
+
+	/* selgdt 0x30 16-bit 64k data at 0x00000000 */
+	"	.word	0xffff, 0x0000	       	\n"
+	"	.byte	0, 0x92, 0, 0	       	\n"
+
+	"__mygdt_end:				\n"
+);
+
+/* Declare a pointer to where our idt is going to be i.e. at mem zero
*/
+__asm__ ("__myidt:		\n"
+	 /* 16-bit limit */
+	 "	.word 1023	\n"
+	 /* 24-bit base */
+	 "	.long 0		\n"
+	 "	.word 0		\n"
+);
+
+/* The address arguments to this function are PHYSICAL ADDRESSES */ 
+static void real_mode_switch_call_vga(unsigned long devfn)
+{
+	__asm__ __volatile__ (
+		// paranoia -- does ecx get saved? not sure. This is 
+		// the easiest safe thing to do.
+		"	pushal			\n"
+		/* save the stack */
+		"	mov 	%esp, __stack	\n"
+		"	jmp 	1f		\n"
+		"__stack: .long 0		\n"
+		"1:\n"
+		/* get devfn into %ecx */
+		"	movl    %esp, %ebp	\n"
+		"	movl    8(%ebp), %ecx	\n"
+		/* load 'our' gdt */
+		"	lgdt	%cs:__mygdtaddr	\n"
+
+		/*  This configures CS properly for real mode. */
+		"	ljmp	$0x28, $__rms_16bit\n"
+		"__rms_16bit:		  	\n"
+		"	.code16			\n"
+		/* 16 bit code from here on... */
+
+		/* Load the segment registers w/ properly configured
segment
+		 * descriptors.  They will retain these configurations
(limits,
+		 * writability, etc.) once protected mode is turned off.
*/
+		"	mov	$0x30, %ax	\n"
+		"	mov	%ax, %ds       	\n"
+		"	mov	%ax, %es       	\n"
+		"	mov	%ax, %fs       	\n"
+		"	mov	%ax, %gs       	\n"
+		"	mov	%ax, %ss       	\n"
+
+		/* Turn off protection (bit 0 in CR0) */
+		"	movl	%cr0, %eax	\n"
+		"	andl	$0xFFFFFFFE, %eax \n"
+		"	movl	%eax, %cr0	\n"
+
+		/* Now really going into real mode */
+		"	ljmp	$0,  $__rms_real\n"
+		"__rms_real:			\n"
+
+		/* put the stack at the end of page zero. 
+		 * that way we can easily share it between real and
protected, 
+		 * since the 16-bit ESP at segment 0 will work for any
case. 
+		/* Setup a stack */
+		"	mov	$0x0, %ax	\n"
+		"	mov	%ax, %ss	\n"
+		"	movl	$0x1000, %eax	\n"
+		"	movl	%eax, %esp	\n"
+
+		/* Load our 16 it idt */
+		"	xor	%ax, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	lidt	__myidt		\n"
+
+		/* Dump zeros in the other segregs */
+		"	mov	%ax, %es       	\n"
+		"	mov	%ax, %fs       	\n"
+		"	mov	%ax, %gs       	\n"
+		"	mov	$0x40, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	mov	%cx, %ax	\n"
+
+		/* run VGA BIOS at 0xc000:0003 */
+		"	lcall	$0xc000, $0x0003\n"
+
+		/* if we got here, just about done. 
+		 * Need to get back to protected mode */
+		"	movl	%cr0, %eax	\n"
+		"	orl	$0x0000001, %eax\n" /* PE = 1 */
+		"	movl	%eax, %cr0	\n"
+
+		/* Now that we are in protected mode jump to a 32 bit
code segment. */
+		"	data32	ljmp	$0x10, $vgarestart\n"
+		"vgarestart:\n"
+		"	.code32\n"
+		"	movw	$0x18, %ax     	\n"
+		"	mov	%ax, %ds       	\n"
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+		"	mov	%ax, %ss	\n"
+
+		/* restore proper gdt and idt */
+		"	lgdt	%cs:gdtarg	\n"
+		"	lidt	idtarg		\n"
+
+		".globl vga_exit		\n"
+		"vga_exit:			\n"
+		"	mov	__stack, %esp	\n"
+		"	popal			\n"
+		);
+}
+
+__asm__ (".text\n""real_mode_switch_end:\n");
+extern char real_mode_switch_end[];
+
+/* call vga bios int 10 function 0x4f14 to enable main console 
+   epia-m does not always autosence the main console so forcing it on
is good !! */ 
+void vga_enable_console()
+{
+	__asm__ __volatile__ (
+		/* paranoia -- does ecx get saved? not sure. This is 
+		 * the easiest safe thing to do. */
+		"	pushal			\n"
+		/* save the stack */
+		"	mov	%esp, __stack	\n"
+
+		/* load 'our' gdt */
+		"	lgdt 	%cs:__mygdtaddr	\n"
+
+		/*  This configures CS properly for real mode. */
+		"	ljmp 	$0x28, $__vga_ec_16bit\n"
+		"__vga_ec_16bit:		\n"
+		"	.code16			\n"
+		/* 16 bit code from here on... */
+
+		/* Load the segment registers w/ properly configured
segment
+		 * descriptors.  They will retain these configurations
(limits,
+		 * writability, etc.) once protected mode is turned off.
*/
+		"	mov	$0x30, %ax     	\n"
+		"	mov	%ax, %ds       	\n"
+		"	mov	%ax, %es       	\n"
+		"	mov	%ax, %fs       	\n"
+		"	mov	%ax, %gs       	\n"
+		"	mov	%ax, %ss       	\n"
+
+		/* Turn off protection (bit 0 in CR0) */
+		"	movl	%cr0, %eax     	\n"
+		"	andl	$0xFFFFFFFE, %eax\n"
+		"	movl	%eax, %cr0     	\n"
+
+		/* Now really going into real mode */
+		"	ljmp	$0, $__vga_ec_real \n"
+		"__vga_ec_real:                  \n"
+
+		/* put the stack at the end of page zero. 
+		 * that way we can easily share it between real and
protected, 
+		 * since the 16-bit ESP at segment 0 will work for any
case. 
+		/* Setup a stack */
+		"	mov	$0x0, %ax	\n"
+		"	mov	%ax, %ss	\n"
+		"	movl	$0x1000, %eax	\n"
+		"	movl	%eax, %esp	\n"
+
+		/* debugging for RGM */
+		"	mov	$0x11, %al	\n"
+		"	outb	%al, $0x80	\n"
+
+		/* Load our 16 it idt */
+		"	xor	%ax, %ax       	\n"
+		"	mov	%ax, %ds	\n"
+		"	lidt	__myidt		\n"
+
+		/* Dump zeros in the other segregs */
+		"	mov	%ax, %ds	\n"
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+
+		/* ask bios to enable main console */
+		/* set up for int 10 call - values found from X server
+		 * bios call routines */
+		"	movw	$0x4f14,%ax	\n"
+		"	movw	$0x8003,%bx	\n"
+		"	movw	$1, %cx		\n"
+		"	movw	$0, %dx		\n"
+		"	movw	$0, %di		\n"
+		"	int	$0x10		\n"
+
+		"	movb	$0x55, %al	\n"
+		"	outb	%al, $0x80	\n"
+
+		/* if we got here, just about done. 
+		 * Need to get back to protected mode */
+		"	movl	%cr0, %eax	\n"
+		"	orl	$0x0000001, %eax\n" /* PE = 1 */
+		"	movl	%eax, %cr0	\n"
+
+		/* Now that we are in protected mode jump to a 32 bit
code segment. */
+		"	data32	ljmp	$0x10, $vga_ec_restart\n"
+		"vga_ec_restart:\n"
+		"	.code32\n"
+		"	movw	$0x18, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+		"	mov	%ax, %ss	\n"
+
+		/* restore proper gdt and idt */
+		"	lgdt	%cs:gdtarg 	\n"
+		"	lidt	idtarg		\n"
+		"	.globl	vga__ec_exit	\n"
+		"vga_ec_exit:\n"
+		"	mov	__stack, %esp	\n"
+		"	popal\n"
+		);
+}
+
+void do_vgabios(void)
+{
+	device_t dev;
+	unsigned long busdevfn;
+	unsigned int rom = 0;
+	unsigned char *buf;
+	unsigned int size = 64*1024;
+	int i;
+	
+	/* clear vga bios data area */
+	for (i = 0x400; i < 0x500; i++) {
+		*(unsigned char *) i = 0;
+	}
+
+	dev = dev_find_class(PCI_CLASS_DISPLAY_VGA<<8 , 0);
+
+	if (!dev) {
+		printk_debug("NO VGA FOUND\n");
+		return;
+	}
+	printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor,
dev->device);
+
+	/* declare rom address here - keep any config data out of the
way
+	 * of core LXB stuff */
+
+	rom = 0xfff80000;
+	pci_write_config32(dev, PCI_ROM_ADDRESS, rom|1);
+	printk_debug("rom base, size: %x\n", rom);
+
+	buf = (unsigned char *) rom;
+	if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
+		memcpy((void *) 0xc0000, buf, size);
+
+		write_protect_vgabios();  // in northbridge
+
+	  	// check signature again
+		buf = (unsigned char *) 0xc0000;
+		if (buf[0]==0x55 && buf[1]==0xAA) {
+			busdevfn = (dev->bus->secondary << 8) |
dev->path.pci.devfn;
+			printk_debug("bus/devfn = %#x\n", busdevfn);
+
+		    	real_mode_switch_call_vga(busdevfn);
+		} else
+			printk_debug("Failed to copy VGA BIOS to
0xc0000\n");
+	} else 
+		printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0],
buf[1]);
+
+	pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
+}
+
+
+// we had hoped to avoid this. 
+// this is a stub IDT only. It's main purpose is to ignore calls 
+// to the BIOS. 
+// no longer. Dammit. We have to respond to these.
+struct realidt {
+	unsigned short offset, cs;
+}; 
+
+// from a handy writeup that andrey found.
+
+// handler. 
+// There are some assumptions we can make here. 
+// First, the Top Of Stack (TOS) is located on the top of page zero. 
+// we can share this stack between real and protected mode. 
+// that simplifies a lot of things ...
+// we'll just push all the registers on the stack as longwords, 
+// and pop to protected mode. 
+// second, since this only ever runs as part of coreboot, 
+// we know all the segment register values -- so we don't save any.
+// keep the handler that calls things small. It can do a call to 
+// more complex code in coreboot itself. This helps a lot as we don't
+// have to do address fixup in this little stub, and calls are absolute
+// so the handler is relocatable.
+void handler(void)
+{
+	__asm__ __volatile__ ( 
+		"	.code16		\n"
+		"idthandle:		\n"
+		"	pushal		\n"
+		"	movb 	$0, %al	\n"
+		"	ljmp 	$0, $callbiosint16\n"
+		"end_idthandle:		\n"
+		"	.code32		\n"
+		);
+}
+
+void debughandler(void)
+{
+	__asm__ __volatile__ ( 
+		"	.code16		\n"
+		"debughandle:		\n"
+		"	pushw	%cx	\n"
+		"	movw	$250, %cx \n"
+		"dbh1:			\n"
+		"	loop	dbh1	\n"
+		"	popw	%cx	\n"
+		"	iret		\n"
+		"end_debughandle:	\n"
+		".code32		\n"
+		);
+}
+
+// Calling conventions. The first C function is called with this stuff
+// on the stack. They look like value parameters, but note that if you
+// modify them they will go back to the INTx function modified. 
+// the C function will call the biosint function with these as
+// REFERENCE parameters. In this way, we can easily get 
+// returns back to the INTx caller (i.e. vgabios)
+void callbiosint(void)
+{
+	__asm__ __volatile__ (
+		"	.code16		\n"
+		"callbiosint16:		\n"
+		"	push	%ds	\n"
+		"	push	%es	\n"
+		"	push	%fs	\n"
+		"	push	%gs	\n"
+		// clean up the int #. To save space we put it in the
lower
+		// byte. But the top 24 bits are junk. 
+		"	andl	$0xff, %eax\n"
+		// this push does two things:
+		// - put the INT # on the stack as a parameter
+		// - provides us with a temp for the %cr0 mods.
+		"	pushl	%eax	\n"
+		"	movl    %cr0, %eax\n"
+		"	orl	$0x00000001, %eax\n" /* PE = 1 */
+		"	movl	%eax, %cr0\n"
+		/* Now that we are in protected mode jump to a 32 bit
code segment. */
+		"	data32  ljmp    $0x10, $biosprotect\n"
+		"biosprotect:		\n"
+		"	.code32		\n"
+		"	movw	$0x18, %ax          \n"
+		"	mov	%ax, %ds          \n"
+		"	mov	%ax, %es          \n"
+		"	mov	%ax, %fs          \n"
+		"	mov	%ax, %gs          \n"
+		"	mov	%ax, %ss          \n"
+		"	lidt	idtarg         \n"
+		"	call	biosint	\n"
+		// back to real mode ...
+		"	ljmp	$0x28, $__rms_16bit2\n"
+		"__rms_16bit2:			\n"
+		"	.code16			\n"
+		/* 16 bit code from here on... */
+		/* Load the segment registers w/ properly configured
segment
+		 * descriptors.  They will retain these configurations
(limits,
+		 * writability, etc.) once protected mode is turned off.
*/
+		"	mov	$0x30, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+		"	mov	%ax, %ss	\n"
+		
+		/* Turn off protection (bit 0 in CR0) */
+		"	movl	%cr0, %eax		\n"
+		"	andl	$0xFFFFFFFE, %eax	\n"
+		"	movl	%eax, %cr0		\n"
+
+		/* Now really going into real mode */
+		"	ljmp $0,  $__rms_real2	\n"
+		"__rms_real2:			\n"
+
+		/* Setup a stack
+		 * FixME: where is esp? */
+		"	mov	$0x0, %ax       \n"
+		"	mov	%ax, %ss	\n"
+
+		/* ebugging for RGM */
+		"	mov	$0x11, %al	\n"
+		"	outb	%al, $0x80	\n"
+
+		/* Load our 16 it idt */
+		"	xor	%ax, %ax	\n"
+		"	mov	%ax, %ds	\n"
+		"	lidt	__myidt		\n"
+
+		/* Dump zeros in the other segregs */
+		"	mov	%ax, %es	\n"
+		"	mov	%ax, %fs	\n"
+		"	mov	%ax, %gs	\n"
+		"	mov	$0x40, %ax	\n"
+		"	mov	%ax, %ds	\n"
+
+		/* pop the INT # that you pushed earlier */
+		"	popl	%eax		\n"
+		"	pop	%gs		\n"
+		"	pop	%fs		\n"
+		"	pop	%es		\n"
+		"	pop	%ds		\n"
+		"	popal			\n"
+		"	iret			\n"
+		"	.code32			\n"
+		);
+}
+
+enum {
+	PCIBIOS = 0x1a, 
+	MEMSIZE = 0x12
+};
+
+int pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long
*pebp,
+	    unsigned long *pesp, unsigned long *pebx, unsigned long
*pedx,
+	    unsigned long *pecx, unsigned long *peax, unsigned long
*pflags);
+
+int handleint21(unsigned long *pedi, unsigned long *pesi, unsigned long
*pebp,
+		unsigned long *pesp, unsigned long *pebx, unsigned long
*pedx,
+		unsigned long *pecx, unsigned long *peax, unsigned long
*pflags
+        );
+
+extern void vga_exit(void);
+
+int biosint(unsigned long intnumber,
+	    unsigned long gsfs, unsigned long dses,
+	    unsigned long edi, unsigned long esi,
+	    unsigned long ebp, unsigned long esp, 
+	    unsigned long ebx, unsigned long edx, 
+	    unsigned long ecx, unsigned long eax, 
+	    unsigned long cs_ip, unsigned short stackflags)
+{
+	unsigned long ip; 
+	unsigned long cs; 
+	unsigned long flags;
+	int ret = -1;
+	
+	ip = cs_ip & 0xffff;
+	cs = cs_ip >> 16;
+	flags = stackflags;
+	
+	printk_debug("biosint: INT# 0x%lx\n", intnumber);
+	printk_debug("biosint: eax 0x%lx ebx 0x%lx ecx 0x%lx edx
0x%lx\n", 
+		      eax, ebx, ecx, edx);
+	printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi
0x%lx\n",
+		     ebp, esp, edi, esi);
+	printk_debug("biosint:  ip 0x%x   cs 0x%x  flags 0x%x\n",
+		     ip, cs, flags);
+
+	// cases in a good compiler are just as good as your own tables.

+	switch (intnumber) {
+	case 0 ... 15:
+		// These are not BIOS service, but the CPU-generated
exceptions
+		printk_info("biosint: Oops, exception %u\n", intnumber);
+		if (esp < 0x1000) {
+			printk_debug("Stack contents: ");
+			while (esp < 0x1000) {
+				printk_debug("0x%04x ", *(unsigned short
*) esp);
+				esp += 2;
+			}
+			printk_debug("\n");
+		}
+		printk_debug("biosint: Bailing out\n");
+		// "longjmp"
+		vga_exit();
+		break;
+		
+	case PCIBIOS:
+		ret = pcibios( &edi, &esi, &ebp, &esp, 
+			       &ebx, &edx, &ecx, &eax, &flags);
+		break;
+	case MEMSIZE: 
+		// who cares. 
+		eax = 64 * 1024;
+		ret = 0;
+		break;
+	case 0x15:
+		ret=handleint21( &edi, &esi, &ebp, &esp, 
+				&ebx, &edx, &ecx, &eax, &flags);
+		break;
+	default:
+		printk_info("BIOSINT: Unsupport int #0x%x\n", 
+			    intnumber);
+		break;
+	}
+	if (ret)
+		flags |= 1; // carry flags
+	else
+		flags &= ~1;
+	stackflags = flags;
+	return ret;
+} 
+
+
+void setup_realmode_idt(void) 
+{
+	extern unsigned char idthandle, end_idthandle;
+	extern unsigned char debughandle, end_debughandle;
+
+	int i;
+	struct realidt *idts = (struct realidt *) 0;
+	int codesize = &end_idthandle - &idthandle;
+	unsigned char *intbyte, *codeptr;
+	
+	// for each int, we create a customized little handler
+	// that just pushes %ax, puts the int # in %al, 
+	// then calls the common interrupt handler. 
+	// this necessitated because intel didn't know much about 
+	// architecture when they did the 8086 (it shows)
+	// (hmm do they know anymore even now :-)
+	// obviously you can see I don't really care about memory 
+	// efficiency. If I did I would probe back through the stack
+	// and get it that way. But that's really disgusting.
+	for (i = 0; i < 256; i++) {
+		idts[i].cs = 0;
+		codeptr = (char*) 4096 + i * codesize;
+		idts[i].offset = (unsigned) codeptr;
+		memcpy(codeptr, &idthandle, codesize);
+		intbyte = codeptr + 3;
+		*intbyte = i;
+	}
+	
+	// fixed entry points
+	
+	// VGA BIOSes tend to hardcode f000:f065 as the previous handler
of
+	// int10. 
+	// calling convention here is the same as INTs, we can reuse
+	// the int entry code.
+	codeptr = (char*) 0xff065;
+	memcpy(codeptr, &idthandle, codesize);
+	intbyte = codeptr + 3;
+	*intbyte = 0x42; /* int42 is the relocated int10 */
+
+	/* debug handler - useful to set a programmable delay between
instructions if the
+	   TF bit is set upon call to real mode */
+	idts[1].cs = 0;
+	idts[1].offset = 16384;
+	memcpy(16384, &debughandle, &end_debughandle - &debughandle);
+
+	
+}
+
+
+
+enum {
+	CHECK = 0xb001,
+	FINDDEV = 0xb102,
+	READCONFBYTE = 0xb108,
+	READCONFWORD = 0xb109,
+	READCONFDWORD = 0xb10a,
+	WRITECONFBYTE = 0xb10b,
+	WRITECONFWORD = 0xb10c,
+	WRITECONFDWORD = 0xb10d
+};
+
+// errors go in AH. Just set these up so that word assigns
+// will work. KISS. 
+enum {
+	PCIBIOS_NODEV = 0x8600,
+	PCIBIOS_BADREG = 0x8700
+};
+
+int
+pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp, 
+	unsigned long *pesp, unsigned long *pebx, unsigned long *pedx, 
+	unsigned long *pecx, unsigned long *peax, unsigned long *pflags)
+{
+	unsigned long edi = *pedi;
+	unsigned long esi = *pesi;
+	unsigned long ebp = *pebp;
+	unsigned long esp = *pesp;
+	unsigned long ebx = *pebx;
+	unsigned long edx = *pedx;
+	unsigned long ecx = *pecx;
+	unsigned long eax = *peax;
+	unsigned long flags = *pflags;
+	unsigned short func = (unsigned short) eax;
+	int retval = 0;
+	unsigned short devid, vendorid, devfn;
+	short devindex; /* Use short to get rid of garbage in upper half
of 32-bit register */
+	unsigned char bus;
+	device_t dev;
+	
+	switch(func) {
+	case  CHECK:
+		*pedx = 0x4350;
+		*pecx = 0x2049;
+		retval = 0;
+		break;
+	case FINDDEV:
+	{
+		devid = *pecx;
+		vendorid = *pedx;
+		devindex = *pesi;
+		dev = 0;
+		while ((dev = dev_find_device(vendorid, devid, dev))) {
+			if (devindex <= 0)
+				break;
+			devindex--;
+		}
+		if (dev) {
+			unsigned short busdevfn;
+			*peax = 0;
+			// busnum is an unsigned char;
+			// devfn is an int, so we mask it off. 
+			busdevfn = (dev->bus->secondary << 8)
+				| (dev->path.pci.devfn & 0xff);
+			printk_debug("0x%x: return 0x%x\n", func,
busdevfn);
+			*pebx = busdevfn;
+			retval = 0;
+		} else {
+			*peax = PCIBIOS_NODEV;
+			retval = -1;
+		}
+	}
+	break;
+	case READCONFDWORD:
+	case READCONFWORD:
+	case READCONFBYTE:
+	case WRITECONFDWORD:
+	case WRITECONFWORD:
+	case WRITECONFBYTE:
+	{
+		unsigned long dword;
+		unsigned short word;
+		unsigned char byte;
+		unsigned char reg;
+		
+		devfn = *pebx & 0xff;
+		bus = *pebx >> 8;
+		reg = *pedi;
+		dev = dev_find_slot(bus, devfn);
+		if (! dev) {
+			printk_debug("0x%x: BAD DEVICE bus %d devfn
0x%x\n", func, bus, devfn);
+			// idiots. the pcibios guys assumed you'd never
pass a bad bus/devfn!
+			*peax = PCIBIOS_BADREG;
+			retval = -1;
+		}
+		switch(func) {
+		case READCONFBYTE:
+			byte = pci_read_config8(dev, reg);
+			*pecx = byte;
+			break;
+		case READCONFWORD:
+			word = pci_read_config16(dev, reg);
+			*pecx = word;
+			break;
+		case READCONFDWORD:
+			dword = pci_read_config32(dev, reg);
+			*pecx = dword;
+			break;
+		case WRITECONFBYTE:
+			byte = *pecx;
+			pci_write_config8(dev, reg, byte);
+			break;
+		case WRITECONFWORD:
+			word = *pecx;
+			pci_write_config16(dev, reg, word);
+			break;
+		case WRITECONFDWORD:
+			dword = *pecx;
+			pci_write_config32(dev, reg, dword);
+			break;
+		}
+		
+		if (retval) 
+			retval = PCIBIOS_BADREG;
+		printk_debug("0x%x: bus %d devfn 0x%x reg 0x%x val
0x%lx\n",
+			     func, bus, devfn, reg, *pecx);
+		*peax = 0;
+		retval = 0;
+	}
+	break;
+	default:
+		printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n",
func);
+		break;
+	}
+	
+	return retval;
+} 
+
+int handleint21(unsigned long *edi, unsigned long *esi, unsigned long
*ebp,
+		unsigned long *esp, unsigned long *ebx, unsigned long
*edx,
+		unsigned long *ecx, unsigned long *eax, unsigned long
*flags)
+{
+	int res=-1;
+	switch(*eax&0xffff)
+	{
+	case 0x5f19:
+		break;
+	case 0x5f18:
+		*eax=0x5f;
+		*ebx=0x545; // MCLK = 133, 32M frame buffer, 256 M main
memory
+		*ecx=0x060;
+		res=0;
+		break;
+	case 0x5f00:
+		*eax = 0x8600;
+		break;
+	case 0x5f01:
+		*eax = 0x5f;
+		*ecx = (*ecx & 0xffffff00 ) | 2; // panel type =  2 =
1024 * 768
+		res = 0;
+		break;
+	case 0x5f02:
+		*eax=0x5f;
+		*ebx= (*ebx & 0xffff0000) | 2;
+		*ecx= (*ecx & 0xffff0000) | 0x401;  // PAL + crt only 
+		*edx= (*edx & 0xffff0000) | 0;  // TV Layout - default
+		res=0;
+		break;
+	case 0x5f0f:
+		*eax=0x860f;
+		break;
+	}
+	return res;
+}
Index: src/northbridge/via/cn400/northbridge.h
===================================================================
--- src/northbridge/via/cn400/northbridge.h	(revision 0)
+++ src/northbridge/via/cn400/northbridge.h	(revision 0)
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood at gmail.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#ifndef NORTHBRIDGE_VIA_CN400_H
+#define NORTHBRIDGE_VIA_CN400_H
+
+extern unsigned int cn400_scan_root_bus(device_t root, unsigned int
max);
+
+#endif /* NORTHBRIDGE_VIA_CN400_H */
Index: src/northbridge/via/cn400/vga.c
===================================================================
--- src/northbridge/via/cn400/vga.c	(revision 0)
+++ src/northbridge/via/cn400/vga.c	(revision 0)
@@ -0,0 +1,123 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood at gmail.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+/*
+ * Note: Some of the VGA control registers are located on the memory
+ * controller. Registers are set both in raminit.c and northbridge.c.
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/cpu.h>
+#include "chip.h"
+#include "northbridge.h"
+#include "cn400.h"
+#include "vgachip.h"
+
+void write_protect_vgabios(void)
+{
+	/* Don't bother for now. */
+}
+
+static void vga_init(device_t dev)
+{
+	u8 reg8;
+
+	print_debug("Copying BOCHS BIOS to 0xf000\n");
+	/*
+	 * Copy BOCHS BIOS from 4G-ROM_SIZE-64k (in flash) to 0xf0000
(in RAM)
+	 * This is for compatibility with the VGA ROM's BIOS callbacks.
+	 */
+	memcpy(0xf0000, (0xffffffff - ROM_SIZE - 0xffff), 0x10000);
+
+	printk_debug("Initializing VGA\n");
+
+	/* Set memory rate to 200 MHz. */
+	outb(0x3d, CRTM_INDEX);
+	reg8 = inb(CRTM_DATA);
+	reg8 &= 0x0f;
+	reg8 |= (0x1 << 4);
+	outb(0x3d, CRTM_INDEX);
+	outb(reg8, CRTM_DATA);
+
+	/* Set framebuffer size. */
+	reg8 = (CONFIG_VIDEO_MB / 4);
+	outb(0x39, SR_INDEX);
+	outb(reg8, SR_DATA);
+
+	pci_write_config8(dev, 0x04, 0x07);
+	pci_write_config8(dev, 0x0d, 0x20);
+	pci_write_config32(dev, 0x10, 0xf4000008);
+	pci_write_config32(dev, 0x14, 0xfb000000);
+
+	printk_debug("INSTALL REAL-MODE IDT\n");
+	setup_realmode_idt();
+	printk_debug("DO THE VGA BIOS\n");
+	do_vgabios();
+	/* VGA seems to work without this, but crash & burn with it. */
+	// printk_debug("Enable VGA console\n");
+	// vga_enable_console();
+
+	/* It's not clear if these need to be programmed before or after
+	 * the VGA BIOS runs. Try both, clean up later. */
+	/* Set memory rate to 200 MHz (again). */
+	outb(0x3d, CRTM_INDEX);
+	reg8 = inb(CRTM_DATA);
+	reg8 &= 0x0f;
+	reg8 |= (0x1 << 4);
+	outb(0x3d, CRTM_INDEX);
+	outb(reg8, CRTM_DATA);
+
+	/* Set framebuffer size (again). */
+	reg8 = (CONFIG_VIDEO_MB / 4);
+	outb(0x39, SR_INDEX);
+	outb(reg8, SR_DATA);
+
+	/* Clear the BOCHS BIOS out of memory, so it doesn't confuse
Linux. */
+	memset(0xf0000, 0, 0x10000);
+}
+
+static void vga_read_resources(device_t dev)
+{
+	dev->rom_address = 0xfff80000;
+	dev->on_mainboard = 1;
+	pci_dev_read_resources(dev);
+}
+
+static const struct device_operations vga_operations = {
+	.read_resources   = vga_read_resources,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = vga_init,
+	.ops_pci          = 0,
+};
+
+static const struct pci_driver vga_driver __pci_driver = {
+	.ops    = &vga_operations,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_CN400_VGA,
+};
Index: targets/via/epia-n/Config-abuild.lb
===================================================================
--- targets/via/epia-n/Config-abuild.lb	(revision 0)
+++ targets/via/epia-n/Config-abuild.lb	(revision 0)
@@ -0,0 +1,21 @@
+# This will make a target directory of ./VENDOR_MAINBOARD
+
+target VENDOR_MAINBOARD
+mainboard VENDOR/MAINBOARD
+
+option CC="CROSSCC"
+option CROSS_COMPILE="CROSS_PREFIX"
+option HOSTCC="CROSS_HOSTCC"
+
+__COMPRESSION__
+__LOGLEVEL__
+
+option ROM_SIZE=512*1024
+
+romimage "fallback" 
+	option USE_FALLBACK_IMAGE=1
+	option ROM_IMAGE_SIZE=0x20000
+	option COREBOOT_EXTRA_VERSION=".0-fallback"
+	payload __PAYLOAD__
+end
+buildrom ./coreboot.rom ROM_SIZE "fallback"
Index: targets/via/epia-n/Config.lb
===================================================================
--- targets/via/epia-n/Config.lb	(revision 0)
+++ targets/via/epia-n/Config.lb	(revision 0)
@@ -0,0 +1,49 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2008 VIA Technologies, Inc.
+## (Written by Aaron Lwe <aaron.lwe at gmail.com> for VIA)
+##
+## 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.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+##
+
+target via_epia_n
+mainboard via/epia-n
+
+option MAXIMUM_CONSOLE_LOGLEVEL=10
+option DEFAULT_CONSOLE_LOGLEVEL=10
+option CONFIG_CONSOLE_SERIAL8250=1
+
+# coreboot C code runs at this location in RAM
+option _RAMBASE=0x00004000
+
+#
+# Generate the final ROM like this:
+# cat vgabios bochsbios coreboot.rom > coreboot.rom.final
+#
+#option ROM_SIZE = (512 * 1024) - (64 * 1024) - (64 * 1024)
+
+romimage "image"
+	option COREBOOT_EXTRA_VERSION = "-epia_n"
+	payload ../../../../../payloads/filo/build/filo.elf
+end
+
+romimage "fallback"
+	option COREBOOT_EXTRA_VERSION = "-epia_n-fallback"
+	payload ../../../../../payloads/filo/build/filo.elf
+end
+
+#buildrom ./coreboot.rom ROM_SIZE "image" "fallback"
+buildrom ./coreboot.rom FALLBACK_SIZE "image" "fallback" 

-----Original Message-----
From: Carl-Daniel Hailfinger [mailto:c-d.hailfinger.devel.2006 at gmx.net] 
Sent: 24 June 2009 11:32
To: Harrison, Jon (SELEX GALILEO, UK)
Cc: Peter Stuge; bari; coreboot at coreboot.org
Subject: Re: [coreboot] coreboot for C3/CN400 (Luke)

                    *** WARNING ***

 This message has originated outside your organisation,
  either from an external partner or the Global Internet. 
      Keep this in mind if you answer this message.


On 24.06.2009 12:17, Harrison, Jon (SELEX GALILEO, UK) wrote:
> I've made a bit of progress, now getting beyond the basic RAM init.
>   

RAM init is one of the big obstacles in finishing a port. If RAM works
reliably for you, please send your code to the list.

Regards,
Carl-Daniel

-- 
http://www.hailfinger.org/


SELEX Sensors and Airborne Systems Limited
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 3EL
A company registered in England & Wales.  Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************





More information about the coreboot mailing list