Index: src/mainboard/msi/ms6147/Config.lb
===================================================================
--- src/mainboard/msi/ms6147/Config.lb	(revision 0)
+++ src/mainboard/msi/ms6147/Config.lb	(revision 0)
@@ -0,0 +1,157 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## 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
+##
+
+if USE_FALLBACK_IMAGE
+	default ROM_SECTION_SIZE = FALLBACK_SIZE
+	default ROM_SECTION_OFFSET = (ROM_SIZE - FALLBACK_SIZE)
+else
+	default ROM_SECTION_SIZE = (ROM_SIZE - FALLBACK_SIZE)
+	default ROM_SECTION_OFFSET = 0
+end
+
+default CONFIG_ROM_PAYLOAD_START = (0xffffffff - ROM_SIZE + ROM_SECTION_OFFSET + 1)
+default PAYLOAD_SIZE = (ROM_SECTION_SIZE - ROM_IMAGE_SIZE)
+
+default _ROMBASE = (CONFIG_ROM_PAYLOAD_START + PAYLOAD_SIZE)
+
+default XIP_ROM_SIZE = 64 * 1024
+default XIP_ROM_BASE = (_ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE)
+
+arch i386 end
+driver mainboard.o
+
+if HAVE_PIRQ_TABLE
+	object irq_tables.o
+end
+
+makerule ./failover.E
+	depends "$(MAINBOARD)/../../../arch/i386/lib/failover.c ../romcc"
+	action "../romcc -E -O2 -mcpu=p2 --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 -O2 -mcpu=p2 --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"
+	depends	"$(MAINBOARD)/auto.c ../romcc"
+	action	"../romcc -E -O2 -mcpu=p2 -I$(TOP)/src -I. $(CPPFLAGS) $(MAINBOARD)/auto.c -o $@"
+end
+makerule ./auto.inc
+	# depends "$(MAINBOARD)/auto.c option_table.h ../romcc"
+	depends "$(MAINBOARD)/auto.c ../romcc"
+	action	"../romcc -O2 -mcpu=p2 -I$(TOP)/src -I. $(CPPFLAGS) $(MAINBOARD)/auto.c -o $@"
+end
+
+mainboardinit cpu/x86/16bit/entry16.inc
+mainboardinit cpu/x86/32bit/entry32.inc
+ldscript /cpu/x86/16bit/entry16.lds
+ldscript /cpu/x86/32bit/entry32.lds
+
+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
+
+mainboardinit arch/i386/lib/cpu_reset.inc
+
+mainboardinit arch/i386/lib/id.inc
+ldscript /arch/i386/lib/id.lds
+
+if USE_FALLBACK_IMAGE
+	ldscript /arch/i386/lib/failover.lds
+	mainboardinit ./failover.inc
+end
+
+# Initialise FPU and 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/intel/i440bx		# Northbridge
+  device apic_cluster 0 on		# APIC cluster
+    chip cpu/intel/slot_2		# CPU (FIXME: It's slot 1, actually)
+      device apic 0 on end		# APIC
+    end
+  end
+  device pci_domain 0 on		# PCI domain
+    device pci 0.0 on end		# Host bridge
+    device pci 1.0 on end		# PCI/AGP bridge
+    chip southbridge/intel/i82371eb	# Southbridge
+      device pci 7.0 on			# ISA bridge
+        chip superio/winbond/w83977tf	# Super I/O
+          device pnp 3f0.0 on		# Floppy
+            io 0x60 = 0x3f0
+            irq 0x70 = 6
+            drq 0x74 = 2
+          end
+          device pnp 3f0.1 on		# Parallel port
+            io 0x60 = 0x378
+            irq 0x70 = 7
+            drq 0x74 = 3
+          end
+          device pnp 3f0.2 on		# COM1
+            io 0x60 = 0x3f8
+            irq 0x70 = 4
+          end
+          device pnp 3f0.3 on		# COM2 / IR
+            io 0x60 = 0x2f8
+            irq 0x70 = 3
+          end
+          device pnp 3f0.5 on		# PS/2 keyboard
+            io 0x60 = 0x60
+            io 0x62 = 0x64
+            irq 0x70 = 1		# PS/2 keyboard interrupt
+            irq 0x72 = 12		# PS/2 mouse interrupt
+          end
+          device pnp 3f0.7 on		# GPIO 1
+          end
+          device pnp 3f0.8 on		# GPIO 2
+          end
+          device pnp 3f0.9 off		# GPIO 3
+          end
+          device pnp 3f0.a on		# ACPI
+          end
+        end
+      end
+      device pci 7.1 on	end		# IDE
+      device pci 7.2 on			# USB
+	  	# irq 0x3c = 0x0a
+      end
+      device pci 7.3 on end		# ACPI
+      register "ide0_enable" = "1"
+      register "ide1_enable" = "1"
+      register "ide_legacy_enable" = "1"
+      # Enable UDMA/33 for higher speed if your IDE device(s) support it.
+      register "ide0_drive0_udma33_enable" = "1"
+      register "ide0_drive1_udma33_enable" = "0"
+      register "ide1_drive0_udma33_enable" = "0"
+      register "ide1_drive1_udma33_enable" = "0"
+    end
+  end
+end
Index: src/mainboard/msi/ms6147/raminit.c
===================================================================
--- src/mainboard/msi/ms6147/raminit.c	(revision 0)
+++ src/mainboard/msi/ms6147/raminit.c	(revision 0)
@@ -0,0 +1,926 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
+ * 				 2008 Mats Erik Andersson <mats.andersson@gisladisker.se>
+ *
+ * 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 <spd.h>
+#include <sdram_mode.h>
+#include <delay.h>
+#include "northbridge/intel/i440bx/i440bx.h"
+
+/*-----------------------------------------------------------------------------
+Macros and definitions.
+-----------------------------------------------------------------------------*/
+
+/* Switches for alternative coding. */
+
+/* USE_DIMM2 needs FIXED_PAGESIZE = 1 or DEBUB_RAM_SETUP = 0. */
+/* USE_DIMM3 needs DEBUG_RAM_SETUP = 0. Otherwise the rom image is too large. */
+#define USE_DIMM2			0
+#define USE_DIMM3			0
+#define FIXED_PAGESIZE_4KB	0
+/* This uses a single function to calculate both row sizes of
+ * a double sided SDRAM, and returns a uint16_t typed value.
+ * The alternative is to use two functions, resulting in easier
+ * arithmetic and strangely enough smaller ROM footprint. */
+#define SPD_UNIFIED_SIZE	0
+
+/* Change this to '1' in order to enable debugging output. */
+#define DEBUG_RAM_SETUP 1
+
+/* Debugging macros. */
+#if DEBUG_RAM_SETUP
+#define PRINT_DEBUG(x)		print_debug(x)
+#define PRINT_DEBUG_HEX8(x)	print_debug_hex8(x)
+#define PRINT_DEBUG_HEX16(x)	print_debug_hex16(x)
+#define PRINT_DEBUG_HEX32(x)	print_debug_hex32(x)
+#define DUMPNORTH()		dump_pci_device(PCI_DEV(0, 0, 0))
+#else
+#define PRINT_DEBUG(x)
+#define PRINT_DEBUG_HEX8(x)
+#define PRINT_DEBUG_HEX16(x)
+#define PRINT_DEBUG_HEX32(x)
+#define DUMPNORTH()
+#endif
+
+/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
+#define RAM_COMMAND_NORMAL	0x0
+#define RAM_COMMAND_NOP		0x1
+#define RAM_COMMAND_PRECHARGE	0x2
+#define RAM_COMMAND_MRS		0x3
+#define RAM_COMMAND_CBR		0x4
+
+/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
+ * defined in DRAMC[2:0].
+ *
+ * [0] == Normal        15.625 us ->  15.6 us
+ * [1] == Reduced(.25X)    3.9 us ->   7.8 ns
+ * [2] == Reduced(.5X)     7.8 us ->   7.8 us
+ * [3] == Extended(2x)    31.3 us ->  31.2 us
+ * [4] == Extended(4x)    62.5 us ->  62.4 us
+ * [5] == Extended(8x)     125 us -> 124.8 us
+ */
+static const uint32_t refresh_rate_map[] = {
+	1, 5, 5, 2, 3, 4
+};
+
+/* Table format: register, bitmask, value. */
+static const unsigned int register_values[] = {
+//static const long register_values[] = {
+	/* NBXCFG - NBX Configuration Register
+	 * 0x50 - 0x53
+	 *
+	 * [31:24] SDRAM Row Without ECC
+	 *         0 = ECC components are populated in this row
+	 *         1 = ECC components are not populated in this row
+	 * [23:19] Reserved
+	 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
+	 *         Assertion of DRAM data on host bus occurs...
+	 *         0 = ...one clock after sampling snoop results (default)
+	 *         1 = ...on the same clock the snoop result is being sampled
+	 *             (this mode is faster by one clock cycle)
+	 * [17:17] ECC - EDO static Drive mode
+	 *         0 = Normal mode (default)
+	 *         1 = ECC signals are always driven
+	 * [16:16] IDSEL_REDIRECT
+	 *         0 = IDSEL1 is allocated to this bridge (default)
+	 *         1 = IDSEL7 is allocated to this bridge
+	 * [15:15] WSC# Handshake Disable
+	 *         1 = Uni-processor mode
+	 *         0 = Dual-processor mode with external IOAPIC (default)
+	 * [14:14] Intel Reserved
+	 * [13:12] Host/DRAM Frequency
+	 *         00 = 100 MHz
+	 *         01 = Reserved
+	 *         10 = 66 MHz
+	 *         11 = Reserved
+	 * [11:11] AGP to PCI Access Enable
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [10:10] PCI Agent to Aperture Access Disable
+	 *         1 = Disable
+	 *         0 = Enable (default)
+	 * [09:09] Aperture Access Global Enable
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [08:07] DRAM Data Integrity Mode (DDIM)
+	 *         00 = Non-ECC
+	 *         01 = EC-only
+	 *         10 = ECC Mode
+	 *         11 = ECC Mode with hardware scrubbing enabled
+	 * [06:06] ECC Diagnostic Mode Enable (EDME)
+	 *         1 = Enable
+	 *         0 = Normal operation mode (default)
+	 * [05:05] MDA Present (MDAP)
+	 *         Works in conjunction with the VGA_EN bit.
+	 *         VGA_EN MDAP
+	 *           0     x   All VGA cycles are sent to PCI
+	 *           1     0   All VGA cycles are sent to AGP
+	 *           1     1   All VGA cycles are sent to AGP, except for
+	 *                     cycles in the MDA range.
+	 * [04:04] Reserved
+	 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [02:02] In-Order Queue Depth (IOQD)
+	 *         1 = In-order queue = maximum
+	 *         0 = A7# is sampled asserted (i.e., 0)
+	 * [01:00] Reserved
+	 */
+	// TODO
+	NBXCFG + 0, 0x00, 0x0c,
+	// NBXCFG + 1, 0x00, 0xa0,	/* 66 MHz */
+	NBXCFG + 1, 0x00, 0x80,		/* 100 MHz */
+	NBXCFG + 2, 0x00, 0x00,
+	NBXCFG + 3, 0x00, 0xff,
+
+	/* DRAMC - DRAM Control Register
+	 * 0x57
+	 *
+	 * [7:6] Reserved
+	 * [5:5] Module Mode Configuration (MMCONFIG)
+	 *       TODO
+	 * [4:3] DRAM Type (DT)
+	 *       00 = EDO
+	 *       01 = SDRAM
+	 *       10 = Registered SDRAM
+	 *       11 = Reserved
+	 *       Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
+	 * [2:0] DRAM Refresh Rate (DRR)
+	 *       000 = Refresh disabled
+	 *       001 = 15.6 us
+	 *       010 = 31.2 us
+	 *       011 = 62.4 us
+	 *       100 = 124.8 us
+	 *       101 = 249.6 us
+	 *       110 = Reserved
+	 *       111 = Reserved
+	 */
+	/* Choose SDRAM (not registered), and disable refresh for now. */
+	DRAMC, 0x00, 0x08,
+	/* DRAMT - DRAM Timing (0x03).
+	 * 0x58
+	 *
+	 * [7:2] Reserved
+	 *   [1] EDO RASx# Wait state (RWS)
+	 *   	 0 = 1 tASR
+	 *   	 1 = 2 tASR
+	 *   [0] EDO CASx# Wait state (CWS)
+	 *       0 = 1 Tasc
+	 *       1 = 2 Tasc
+	 */
+	DRAMT, 0x00, 0x03,
+
+	/*
+	 * PAM[6:0] - Programmable Attribute Map Registers
+	 * 0x59 - 0x5f
+	 *
+	 * 0x59 [3:0] Reserved
+	 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
+	 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
+	 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
+	 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
+	 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
+	 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
+	 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
+	 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
+	 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
+	 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS extension
+	 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS extension
+	 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS extension
+	 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS extension
+	 *
+	 * Bit assignment:
+	 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
+	 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
+	 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
+	 * 11 = Read/Write (all access goes to DRAM)
+	 */
+	// TODO
+	PAM0, 0x00, 0x00,
+	PAM1, 0x00, 0x00,
+	PAM2, 0x00, 0x00,
+	PAM3, 0x00, 0x00,
+	PAM4, 0x00, 0x00,
+	PAM5, 0x00, 0x00,
+	PAM6, 0x00, 0x00,
+
+	/* DRB[0:7] - DRAM Row Boundary Registers
+	 * 0x60 - 0x67
+	 *
+	 * An array of 8 byte registers, which hold the ending memory address
+	 * assigned to each pair of DIMMs, in 8MB granularity.   
+	 *
+	 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
+	 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
+	 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
+	 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
+	 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
+	 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
+	 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
+	 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
+	 */
+	/* Set the DRBs to zero for now, this will be fixed later. */
+	DRB0, 0x00, 0x00,
+	DRB1, 0x00, 0x00,
+	DRB2, 0x00, 0x00,
+	DRB3, 0x00, 0x00,
+	DRB4, 0x00, 0x00,
+	DRB5, 0x00, 0x00,
+	DRB6, 0x00, 0x00,
+	DRB7, 0x00, 0x00,
+
+	/* FDHC - Fixed DRAM Hole Control Register
+	 * 0x68
+	 *
+	 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
+	 *
+	 * [7:6] Hole Enable (HEN)
+	 *       00 = None
+	 *       01 = 512 KB - 640 KB (128 KB)
+	 *       10 = 15 MB - 16 MB (1 MB)
+	 *       11 = Reserved
+	 * [5:0] Reserved
+	 */
+	/* No memory holes. */
+	FDHC, 0x00, 0x00,
+
+	/* MBSC - Memory Buffer Strength Control
+	 * 0x69 - 0x6e
+	 */
+	MBSC + 0, 0x00, 0x00,
+	MBSC + 1, 0x00, 0x00,
+	MBSC + 2, 0x00, 0x00,
+	MBSC + 3, 0x00, 0x00,
+	MBSC + 4, 0x00, 0x00,
+	MBSC + 5, 0x00, 0x00,
+	
+	/* RPS - SDRAM Row Page Size Register
+	 * 0x74 - 0x75
+	 *
+	 * Sets the row page size for SDRAM. For EDO memory, the page
+	 * size is fixed at 2 KB.
+	 *
+	 * [15:0] Page Size (PS)
+	 *
+	 *  [1:0] for row 0, DRB[0]
+	 *        00 = 2 kB page size
+	 *        01 = 4 kB
+	 *        10 = 8 kB
+	 *        11 = Illegal
+	 *  [3:2] for row 1, DRB[1]
+	 *  [5:4] for row 2, DRB[2]
+	 *  [7:6] for row 3, DRB[3]
+	 *  [9:8] row 4
+	 *  [11:10] row 5
+	 *  [13:12] row 6
+	 *  [15:14] row 7
+	 */
+	// TODO
+	RPS + 0, 0x00, 0x00,
+	RPS + 1, 0x00, 0x00,
+
+	/* SDRAMC - SDRAM Control Register
+	 * 0x76 - 0x77
+	 *
+	 * [15:10] Reserved
+	 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
+	 *         00 = Illegal
+	 *         01 = Add a clock delay to the lead-off clock count
+	 *         10 = Illegal
+	 *         11 = Illegal
+	 * [07:05] SDRAM Mode Select (SMS)
+	 *         000 = Normal SDRAM Operation (default)
+	 *         001 = NOP Command Enable
+	 *         010 = All Banks Precharge Enable
+	 *         011 = Mode Register Set Enable
+	 *         100 = CBR Enable
+	 *         101 = Reserved
+	 *         110 = Reserved
+	 *         111 = Reserved
+	 * [04:04] SDRAMPWR
+	 *         0 = 3 DIMM configuration
+	 *         1 = 4 DIMM configuration
+	 * [03:03] Leadoff Command Timing (LCT)
+	 *         0 = 4 CS# Clock
+	 *         1 = 3 CS# Clock
+	 * [02:02] CAS# Latency (CL)
+	 *         0 = 3 DCLK CAS# latency
+	 *         1 = 2 DCLK CAS# latency
+	 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
+	 *         0 = 3 clocks between a row activate and a read or write cmd.
+	 *         1 = 2 clocks between a row activate and a read or write cmd.
+	 * [00:00] SDRAM RAS# Precharge (SRP)
+	 *         0 = 3 clocks of RAS# precharge
+	 *         1 = 2 clocks of RAS# precharge
+	 */
+	SDRAMC + 0, 0x00, 0x00,
+	SDRAMC + 1, 0x00, 0x00,
+
+	/* PGPOL - Paging Policy Register
+	 * 0x78 - 0x79
+	 *
+	 * [15:08] Banks per Row (BPR)
+	 *         TODO
+	 *         0 = 2 banks
+	 *         1 = 4 banks
+	 * [07:05] Reserved
+	 * [04:04] Intel Reserved
+	 * [03:00] DRAM Idle Timer (DIT)
+	 *         0000 = 0 clocks
+	 *         0001 = 2 clocks
+	 *         0010 = 4 clocks
+	 *         0011 = 8 clocks
+	 *         0100 = 10 clocks
+	 *         0101 = 12 clocks
+	 *         0110 = 16 clocks
+	 *         0111 = 32 clocks
+	 *         1xxx = Infinite (pages are not closed for idle condition)
+	 */
+	// TODO
+	PGPOL + 0, 0x00, 0x00,
+	PGPOL + 1, 0x00, 0xff,
+
+	/* PMCR - Power Management Control Register
+	 * 0x7a
+	 *
+	 * [07:07] Power Down SDRAM Enable (PDSE)
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [06:06] ACPI Control Register Enable (SCRE)
+	 *         1 = Enable
+	 *         0 = Disable (default)
+	 * [05:05] Suspend Refresh Type (SRT)
+	 *         1 = Self refresh mode
+	 *         0 = CBR fresh mode
+	 * [04:04] Normal Refresh Enable (NREF_EN)
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [03:03] Quick Start Mode (QSTART)
+	 *         1 = Quick start mode for the processor is enabled
+	 * [02:02] Gated Clock Enable (GCLKEN)
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [01:01] AGP Disable (AGP_DIS)
+	 *         1 = Disable
+	 *         0 = Enable
+	 * [00:00] CPU reset without PCIRST enable (CRst_En)
+	 *         1 = Enable
+	 *         0 = Disable
+	 */
+	/* Enable normal refresh and the gated clock. */
+	// TODO: Only do this later?
+	// PMCR, 0x00, 0x14,
+	// PMCR, 0x00, 0x10,
+	PMCR, 0x00, 0x00,
+};
+
+/*-----------------------------------------------------------------------------
+SDRAM configuration functions.
+-----------------------------------------------------------------------------*/
+
+/**
+ * Send the specified RAM command to all DIMMs.
+ *
+ * @param Memory controller
+ * @param TODO
+ * @param TODO
+ */
+static void do_ram_command(const struct mem_controller *ctrl,
+			   uint32_t command, uint32_t addr_offset)
+{
+	char i, dram_known;
+	uint16_t reg;
+
+	/* Support for multiple DIMMs.
+	 * This requires that one read32() is performed
+	 * for each RAM bank/row.
+	 */
+
+	/* Configure the RAM command. */
+	reg = pci_read_config16(ctrl->d0, SDRAMC);
+	reg &= 0xff1f;		/* Clear bits 7-5. */
+	reg |= (uint16_t) (command << 5);
+	pci_write_config16(ctrl->d0, SDRAMC, reg);
+
+	/* RAM_COMMAND_NORMAL affects only the memory controller and
+	   doesn't need to be "sent" to the DIMMs. */
+	if (command == RAM_COMMAND_NORMAL)
+		return;
+
+	/*
+	PRINT_DEBUG("    Sending RAM command 0x");
+	PRINT_DEBUG_HEX16(reg);
+	PRINT_DEBUG(" to 0x");
+	PRINT_DEBUG_HEX32(0 + addr_offset); // FIXME
+	PRINT_DEBUG("\r\n");
+	*/
+
+	/* RAM is populated from the bottom. This variable always
+	 * denotes the beginning of a newly populated block. */
+	dram_known = 0;
+
+	for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
+		/* Is this bank populated? */
+		if (pci_read_config8(ctrl->d0, DRB + i) > dram_known)
+		{
+			/* The DRB# registers count in 8 MB blocks.
+			 * 'dram_known contains the known lower bound of
+			 * the present block. Activate it. */
+			read32( (dram_known * 8 * 1024 * 1024) + addr_offset);
+			PRINT_DEBUG("RAM strobe 0x");
+			PRINT_DEBUG_HEX32(dram_known * 8 * 1024 * 1024 + addr_offset);
+			PRINT_DEBUG("\r\n");
+			/* DRB registers are cumulative, so grab the current value. */
+			dram_known = pci_read_config8(ctrl->d0, DRB + i);
+		};
+
+	}
+}
+
+/*-----------------------------------------------------------------------------
+DIMM-independent configuration functions.
+-----------------------------------------------------------------------------*/
+
+/**
+ * TODO.
+ *
+ * @param Memory controller
+ */
+static void spd_enable_refresh(const struct mem_controller *ctrl)
+{
+	int i, value;
+	uint8_t reg;
+
+	reg = pci_read_config8(ctrl->d0, DRAMC);
+
+	for (i = 0; i < DIMM_SOCKETS; i++) {
+		value = spd_read_byte(ctrl->channel0[i], SPD_REFRESH);
+		if (value < 0)
+			/* Empty socket. */
+			continue;
+
+		/* Effectively, the refresh values are found in {0x00,...,0x05}.
+		 * A wider mask in stead of (value & 0x07) would exceed the defined
+		 * length of refresh_rate_map[].
+		 */
+		reg = (reg & 0xf8) | refresh_rate_map[(value & 0x07)]; 
+		/* reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)]; */
+
+		PRINT_DEBUG("    Enabling refresh (DRAMC = 0x");
+		PRINT_DEBUG_HEX8(reg);
+		PRINT_DEBUG(") for DIMM ");
+		PRINT_DEBUG_HEX8(i);
+		PRINT_DEBUG("\r\n");
+	}
+
+	pci_write_config8(ctrl->d0, DRAMC, reg);
+}
+
+/*-----------------------------------------------------------------------------
+ * Calculation of row sizes.
+ *---------------------------------------------------------------------------*/
+
+#if SPD_UNIFIED_SIZE
+/**
+ * Calculate the sizes of sdram rows.
+ *
+ * @param unsigned char
+ */
+static uint16_t sdram_find_rowsize(unsigned char d)
+{
+	/* Presumption: The value 'd' has either one or two bits set.
+	 * With only one bit set, the size is duplicated. The least significant
+	 * return byte contains the larger size as reported by SPD. */
+
+	/* Start with the least significant bit. */
+	char mask = 1;
+
+	/* Exclude empty card reads (value 0xff).
+	 * The looping will halt since value 0x00 is now excluded. */
+	if ( d == 0x00 || d == 0xff )
+		return 0;
+
+	while (1) /* Loop exits at the first bit set. */
+	{
+		if ( d & mask ) /* Is size 2^(mask+1) MB present? */
+		{
+			/* The looping from least significant bit upwards,
+			 * ensures that (d & ~mask) represent a larger size,
+			 * should the value be non-zero at all. */
+			if ( d & ~mask )
+				/* A mixed size DIMM card has been found. */
+				return ((d & mask) << 8) | (d & ~mask);
+			/* The non-mixed size card demands a duplicate size. */
+			return (d << 8) | d;
+		}
+		/* Shift the mask in order to detect the next larger size. */
+		mask <<= 1;
+	}
+}
+#else
+
+/**
+ * Calculate the smallest size of an sdram row.
+ *
+ * @param unsigned char
+ */
+static unsigned char sdram_find_low_rowsize(unsigned char d)
+{
+	unsigned char mask = 1;
+
+	if ( d == 0x00 || d == 0xff )
+		return 0;
+
+	while (1)
+	{
+		if ( d & mask )
+			/* The smallest size is always found first. */
+			return mask;
+		/* Try the next larger size. */
+		mask <<= 1;
+	}
+}
+
+/**
+ * Calculate the largest size of an sdram row.
+ *
+ * @param unsigned char
+ */
+static unsigned char sdram_find_high_rowsize(unsigned char d)
+{
+	unsigned char mask = 1;
+
+	if ( d == 0x00 || d == 0xff )
+		return 0;
+
+	while (1)
+	{
+		if ( d & mask )
+		{
+			if ( d & ~mask )
+				/* This is indeed a mixed-size sdram card, as the
+				 * larger size is being triggered. */
+				return d & ~mask;
+			/* Either a single sided card, or the banks are symmetrical. */
+			return mask;
+		}
+		mask <<= 1;
+	}
+}
+#endif /* SPD_UNIFIED_SIZE */
+
+static uint8_t update_drbx(uint8_t reg, uint8_t channel, uint8_t drb, uint8_t data)
+{
+	uint8_t d = data;
+#if SPD_UNIFIED_SIZE
+	d += (sdram_find_rowsize(spd_read_byte(channel,31)) >> 1) & 0x007f;
+	pci_write_config8(reg, drb, d);
+
+	/* Is DIMM# a double sided memory device. */
+	if ( spd_read_byte(channel, 5) == 0x02 )
+		d += sdram_find_rowsize(spd_read_byte(channel,31)) >> 9;
+#else
+	d += sdram_find_low_rowsize(spd_read_byte(channel,31)) >> 1;
+	pci_write_config8(reg, drb, d);
+
+	/* Is DIMM# a double sided memory device. */
+	if ( spd_read_byte(channel, 5) == 0x02 )
+		d += sdram_find_high_rowsize(spd_read_byte(channel,31)) >> 1;
+#endif /* SPD_UNIFIED_SIZE */
+	pci_write_config8(reg, drb + 1, d);
+	return d;
+}
+
+/*-----------------------------------------------------------------------------
+Public interface.
+-----------------------------------------------------------------------------*/
+
+/**
+ * TODO.
+ *
+ * @param Memory controller
+ */
+static void sdram_set_registers(const struct mem_controller *ctrl)
+{
+	int i, max;
+	uint8_t reg;
+
+	PRINT_DEBUG("Northbridge prior to SDRAM init:\r\n");
+	DUMPNORTH();
+
+	max = sizeof(register_values) / sizeof(register_values[0]);
+
+	/* Set registers as specified in the register_values[] array. */
+	for (i = 0; i < max; i += 3) {
+		reg = pci_read_config8(ctrl->d0, register_values[i]);
+		reg &= register_values[i + 1];
+		reg |= register_values[i + 2] & ~(register_values[i + 1]);
+		pci_write_config8(ctrl->d0, register_values[i], reg);
+
+#if 0
+		PRINT_DEBUG("    Set register 0x");
+		PRINT_DEBUG_HEX8(register_values[i]);
+		PRINT_DEBUG(" to 0x");
+		PRINT_DEBUG_HEX8(reg);
+		PRINT_DEBUG("\r\n");
+#endif
+	}
+}
+
+/**
+ * TODO.
+ *
+ * @param Memory controller
+ */
+static void sdram_set_spd_registers(const struct mem_controller *ctrl)
+{
+	/* Use only a minimal amount of scratch data in order to
+	 * save precious internal register space under romcc. */
+	uint8_t data;
+
+	/* TODO: Don't hardcode the values here, get info via SPD.
+	 * Implemented for DRB#, */
+
+	/* Map all legacy regions to RAM (read/write). This is required if
+	 * you want to use the RAM area from 768 KB - 1 MB. If the PAM
+	 * registers are not set here appropriately, the RAM in that region
+	 * will not be accessible, thus a RAM check of it will also fail.
+	 */
+	pci_write_config8(ctrl->d0, PAM0, 0x30);
+	pci_write_config16(ctrl->d0, PAM1, 0x3333);
+	pci_write_config32(ctrl->d0, PAM3, 0x33333333);
+	/*
+	pci_write_config8(ctrl->d0, PAM1, 0x33);
+	pci_write_config8(ctrl->d0, PAM2, 0x33);
+	pci_write_config8(ctrl->d0, PAM3, 0x33);
+	pci_write_config8(ctrl->d0, PAM4, 0x33);
+	pci_write_config8(ctrl->d0, PAM5, 0x33);
+	pci_write_config8(ctrl->d0, PAM6, 0x33);
+	*/
+
+	/* Set DRB0-DRB7 dynamically. */
+#if 0
+		print_debug("Density at 0x00: 0x");
+		print_debug_hex8(spd_read_byte(ctrl->channel0[0],31));
+		print_debug(", rows 0x");
+		print_debug_hex8(spd_read_byte(ctrl->channel0[0],5));
+		print_debug("\r\n");
+#elif 0
+		PRINT_DEBUG("Density at 0x00: 0x");
+		PRINT_DEBUG_HEX8(spd_read_byte(ctrl->channel0[0],31));
+		PRINT_DEBUG(", rows 0x");
+		PRINT_DEBUG_HEX8(spd_read_byte(ctrl->channel0[0],5));
+		PRINT_DEBUG("\r\n");
+#endif
+
+	/* The first bank of DIMM0 initializes the size,
+	 * and all other produce a cumulative counter. */
+	data = update_drbx(ctrl->d0, ctrl->channel0[0], DRB0, 0);
+
+#if 0
+		print_debug("Density at 0x01: 0x");
+		print_debug_hex8(spd_read_byte(ctrl->channel0[1],31));
+		print_debug(", rows 0x");
+		print_debug_hex8(spd_read_byte(ctrl->channel0[1],5));
+		print_debug("\r\n");
+#elif 0
+		PRINT_DEBUG("Density at 0x01: 0x");
+		PRINT_DEBUG_HEX8(spd_read_byte(ctrl->channel0[1],31));
+		PRINT_DEBUG(", rows 0x");
+		PRINT_DEBUG_HEX8(spd_read_byte(ctrl->channel0[1],5));
+		PRINT_DEBUG("\r\n");
+#endif
+
+	/* Probe DIMM1. */
+	data = update_drbx(ctrl->d0, ctrl->channel0[1], DRB2, data);
+
+#if USE_DIMM2
+	/* Do an active detection also for DIMM2. */
+	#if 0
+		print_debug("Density at 0x02: 0x");
+		print_debug_hex8(spd_read_byte(ctrl->channel0[2],31));
+		print_debug("\r\n");
+		print_debug(" rows: 0x");
+		print_debug_hex16(sdram_find_rowsize(spd_read_byte(ctrl->channel0[2],31)));
+		print_debug("\r\n");
+	#else
+		PRINT_DEBUG("Density at 0x02: 0x");
+		PRINT_DEBUG_HEX8(spd_read_byte(ctrl->channel0[2],31));
+		PRINT_DEBUG("\r\n");
+		//PRINT_DEBUG(" rows: 0x");
+		//PRINT_DEBUG_HEX16(sdram_find_rowsize(spd_read_byte(ctrl->channel0[2],31)));
+		//PRINT_DEBUG("\r\n");
+	#endif
+
+	/* Now probe for DIMM2. */
+	data = update_drbx(ctrl->d0, ctrl->channel0[2], DRB4, data);
+
+#else
+	/* No detection for DIMM2. Just continue using the cumulative counter.*/
+	pci_write_config8(ctrl->d0, DRB4, data);
+	pci_write_config8(ctrl->d0, DRB5, data);
+#endif /* USE_DIMM2 */
+
+#if USE_DIMM3
+	/* Probe for DIMM3. */
+		//PRINT_DEBUG("Density at 0x03: 0x");
+		//PRINT_DEBUG_HEX16(sdram_find_rowsize(spd_read_byte(ctrl->channel0[3],31)));
+		//PRINT_DEBUG("\r\n");
+	data = update_drbx(ctrl->d0, ctrl->channel0[3], DRB6, data);
+
+#else
+	/* No detection for DIMM3. Just continue using the cumulative counter.*/
+	pci_write_config8(ctrl->d0, DRB6, data);
+	pci_write_config8(ctrl->d0, DRB7, data);
+#endif /* USE_DIMM3 */
+
+	/* TODO: Set DRAMC. Don't enable refresh for now. */
+	pci_write_config8(ctrl->d0, DRAMC, 0x08); /* SDRAM installed */
+
+	/* TODO: Set RPS. */
+	/* pci_write_config16(ctrl->d0, RPS, 0x0001); */
+#if FIXED_PAGESIZE_4KB
+	/* Fixed page size 4 kB.
+	 * Setting page size of an unused bank seems harmless
+	 * in practice, so all eight rows are of size 4 kB. */
+	pci_write_config16(ctrl->d0, RPS, 0x5555);
+#else
+	/* Probed page sizes.
+	 * Memory usage is critical for the fallback image.
+	 * The factor 5 takes care of double sided DIMMs,
+	 * but only in the symmetrical case.
+	 * Setting value as for double sided cards, where
+	 * only a single row exists, seems harmless in practice.
+	 * Legend:	8 columns -> 2 kB -> 0b00
+	 * 			9 columns -> 4 kB -> 0b01
+	 *			10 columns -> 8 kB -> 0b10.
+	 */
+
+	/* DIMM0 */
+	/* This calculation provide correct flags for {8,9,10} columns. */
+	data = 5 * (spd_read_byte(ctrl->channel0[0], 4) - 8);
+
+	/* If the read value was 0xff for empty socket, it needs correction. */
+	if ( data == 0xd3 )
+	{
+		print_debug("DIMM0 empty\r\n");
+		data = 0;
+	};
+	/* Must loose the case of eight address lines before shifting
+	 * a nubble upwards. Therefore the additional factor '16'. */
+	/* DIMM1 */
+	if (spd_read_byte(ctrl->channel0[1], 4) != -1)
+		/* Used socket */
+		data |= 16 * 5 * (spd_read_byte(ctrl->channel0[1], 4) - 8);
+	else
+		/* Empty; no additional flags in RPS. */
+		print_debug("DIMM1 empty\r\n");
+
+	pci_write_config8(ctrl->d0, RPS, data);
+	print_debug("RPS DIMM0/1: 0x");
+	print_debug_hex8(data);
+	print_debug("\r\n");
+
+#  if USE_DIMM2 || USE_DIMM3
+	/* DIMM2 */
+	if (spd_read_byte(ctrl->channel0[2], 4) != -1)
+		data = 5 * (spd_read_byte(ctrl->channel0[2], 4) - 8);
+	else
+		data = 0;
+
+#	if USE_DIMM3
+	/* DIMM3 */
+	if (spd_read_byte(ctrl->channel0[3], 4) != -1)
+		data |= 16 * 5 * (spd_read_byte(ctrl->channel0[3], 4) - 8);
+#	endif /* USE_DIMM3 */
+
+	pci_write_config8(ctrl->d0, RPS + 1, data);
+	print_debug("RPS DIMM2/3: 0x");
+	print_debug_hex8(data);
+	print_debug("\r\n");
+#	else
+	/* Mark page size 2 kB in the unused slots. */
+	pci_write_config8(ctrl->d0, RPS + 1, 0x00);
+
+#  endif /* USE_DIMM2 || USE_DIMM3 */
+
+#endif /* FIXED_PAGESIZE_4KB */
+
+	/* TODO: Set SDRAMC. */
+	// pci_write_config16(ctrl->d0, SDRAMC, 0x010f); // FIXME?
+	pci_write_config16(ctrl->d0, SDRAMC, 0x0103); // Leadoff delay + 3 DCLK
+
+	/* TODO: Set PGPOL. */
+	/* Devices are supposed to contain two banks, until an
+	 * SPD probe says they provide four banks. */
+	data = 0x00;
+
+	if ( spd_read_byte(ctrl->channel0[0], 17) == 0x04 )
+		data |= 0x03;
+	if ( spd_read_byte(ctrl->channel0[1], 17) == 0x04 )
+		data |= (0x03 << 2);
+#if USE_DIMM2 || USE_DIMM3
+	if ( spd_read_byte(ctrl->channel0[2], 17) == 0x04 )
+		data |= (0x03 << 4);
+#endif
+#if USE_DIMM3
+	if ( spd_read_byte(ctrl->channel0[3], 17) == 0x04 )
+		data |= (0x03 << 6);
+#endif
+	/* The value (data << 8) now produces correct bank flags for PGPOL. */
+	// pci_write_config16(ctrl->d0, PGPOL, 0x0107);
+	//pci_write_config16(ctrl->d0, PGPOL, 0x0123);
+	/* The value 0x06 (idle 16 clock periods) is experimental. */
+	pci_write_config16(ctrl->d0, PGPOL, 0x06 | (data << 8));
+
+	/* TODO: Set NBXCFG. */
+	// pci_write_config32(ctrl->d0, NBXCFG, 0x0100220c); // FIXME?
+	/* Interpretation:	'ff' possibly populated rows,
+	 * 					'80' uni-processor, 100 MHz, no AGP, no-ECC,
+	 * 					'04' no USWC, maximum in-order queue.
+	 * Experimental */
+	pci_write_config32(ctrl->d0, NBXCFG, 0xff008004);
+
+	/* TODO: Set PMCR? */
+	// pci_write_config8(ctrl->d0, PMCR, 0x14);
+	pci_write_config8(ctrl->d0, PMCR, 0x10);
+
+	/* TODO? */
+	pci_write_config8(ctrl->d0, PCI_LATENCY_TIMER, 0x40);
+	pci_write_config8(ctrl->d0, DRAMT, 0x03);
+	//pci_write_config8(ctrl->d0, MBSC, 0x03);
+	//pci_write_config32(ctrl->d0, MBSC, 0x0003c003);
+	/* Experimental */
+	pci_write_config32(ctrl->d0, MBSC, 0x00000003);
+	//pci_write_config32(ctrl->d0, MBSC, 0xffffffff);
+	pci_write_config8(ctrl->d0, SCRR, 0x38);
+}
+
+/**
+ * Enable SDRAM.
+ *
+ * @param Number of controllers
+ * @param Memory controller
+ */
+static void sdram_enable(int controllers, const struct mem_controller *ctrl)
+{
+	int i;
+
+	/* 0. Wait until power/voltages and clocks are stable (200us). */
+	udelay(200);
+
+	/* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
+	PRINT_DEBUG("RAM Enable 1: Apply NOP\r\n");
+	do_ram_command(ctrl, RAM_COMMAND_NOP, 0);
+	udelay(200);
+
+	/* 2. Precharge all. Wait tRP. */
+	PRINT_DEBUG("RAM Enable 2: Precharge all\r\n");
+	do_ram_command(ctrl, RAM_COMMAND_PRECHARGE, 0);
+	udelay(1);
+
+	/* 3. Perform 8 refresh cycles. Wait tRC each time. */
+	PRINT_DEBUG("RAM Enable 3: CBR\r\n");
+	for (i = 0; i < 8; i++) {
+		do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
+		udelay(1);
+	}
+
+	/* 4. Mode register set. Wait two memory cycles. */
+	PRINT_DEBUG("RAM Enable 4: Mode register set\r\n");
+	do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0);
+	udelay(2);
+
+	/* 5. Normal operation. */
+	PRINT_DEBUG("RAM Enable 5: Normal operation\r\n");
+	do_ram_command(ctrl, RAM_COMMAND_NORMAL, 0);
+	udelay(1);
+
+	/* 6. Finally enable refresh. */
+	PRINT_DEBUG("RAM Enable 6: Enable refresh\r\n");
+	// pci_write_config8(ctrl->d0, PMCR, 0x10);
+	spd_enable_refresh(ctrl);
+	udelay(1);
+
+	PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
+	DUMPNORTH();
+}
+
+/* vi: set ai sw=4 ts=4 */
Index: src/mainboard/msi/ms6147/irq_tables.c
===================================================================
--- src/mainboard/msi/ms6147/irq_tables.c	(revision 0)
+++ src/mainboard/msi/ms6147/irq_tables.c	(revision 0)
@@ -0,0 +1,46 @@
+/* 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/whdc/archive/pciirq.mspx
+ */
+
+#ifdef GETPIR
+#include "pirq_routing.h"
+#else
+#include <arch/pirq_routing.h>
+#endif
+
+const struct irq_routing_table intel_irq_routing_table = {
+	PIRQ_SIGNATURE,  /* u32 signature */
+	PIRQ_VERSION,    /* u16 version   */
+	32+16*8,	 /* There can be total 8 devices on the bus */
+	0x00,		 /* Where the interrupt router lies (bus) */
+	(0x07<<3)|0x0,   /* Where the interrupt router lies (dev) */
+	0x1c00,		 /* IRQs devoted exclusively to PCI usage */
+	0x8086,		 /* Vendor */
+	0x7000,		 /* Device */
+	0,		 /* Crap (miniport) */
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+	0x20,		 /* u8 checksum. This has to be 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,(0x0e<<3)|0x0, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0x0deb8}}, 0x1, 0x0},
+		{0x00,(0x10<<3)|0x0, {{0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0x0deb8}}, 0x2, 0x0}, 
+		{0x00,(0x12<<3)|0x0, {{0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0x0deb8}}, 0x3, 0x0},
+		{0x00,(0x14<<3)|0x0, {{0x63, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0x0deb8}}, 0x4, 0x0},
+		{0x00,(0x00<<3)|0x0, {{0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x00, 0x0deb8}}, 0x0, 0x0}, /* North bridge */
+		{0x00,(0x07<<3)|0x1, {{0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x00, 0x0deb8}}, 0x0, 0x0}, /* IDE */
+		{0x00,(0x07<<3)|0x2, {{0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x63, 0x0deb8}}, 0x0, 0x0}, /* UHCI */
+		{0x00,(0x01<<3)|0x0, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0x0deb8}}, 0x0, 0x0}, /* AGP bridge */
+	}
+};
+
+unsigned long write_pirq_routing_table(unsigned long addr)
+{
+	return copy_pirq_routing_table(addr);
+}
Index: src/mainboard/msi/ms6147/sdram.c
===================================================================
--- src/mainboard/msi/ms6147/sdram.c	(revision 0)
+++ src/mainboard/msi/ms6147/sdram.c	(revision 0)
@@ -0,0 +1,64 @@
+
+#ifndef RAMINIT_SYSINFO
+        #define RAMINIT_SYSINFO 0
+#endif
+
+static inline void print_debug_sdram_8(const char *strval, uint32_t val)
+{
+#if CONFIG_USE_INIT
+        printk_debug("%s%02x\r\n", strval, val);
+#else
+        print_debug(strval); print_debug_hex8(val); print_debug("\r\n");
+#endif
+}
+
+void sdram_no_memory(void)
+{
+	print_err("No memory!!\r\n");
+	while(1) { 
+		hlt(); 
+	}
+}
+
+/* Setup SDRAM */
+#if RAMINIT_SYSINFO == 1
+void sdram_initialize(int controllers, const struct mem_controller *ctrl, void *sysinfo)
+#else
+//void sdram_initialize(int controllers, const struct mem_controller *ctrl)
+void sdram_initialize(const struct mem_controller *ctrl)
+#endif
+{
+#define controllers 1
+	/* Set the registers we can set once to reasonable values */
+	print_debug_sdram_8("Ram1.",0);
+
+	#if RAMINIT_SYSINFO == 1
+		sdram_set_registers(ctrl, sysinfo);
+	#else
+		sdram_set_registers(ctrl);
+	#endif
+
+	/* Now setup those things we can auto detect */
+    print_debug_sdram_8("Ram2.",0);
+
+	#if RAMINIT_SYSINFO == 1
+		sdram_set_spd_registers(ctrl, sysinfo);
+	#else
+		sdram_set_spd_registers(ctrl);
+	#endif
+
+	/* Now that everything is setup enable the SDRAM.
+	 * Some chipsets do the work for us while on others 
+	 * we need to it by hand.
+	 */
+	print_debug("Ram3\r\n");
+
+	#if RAMINIT_SYSINFO == 1
+		sdram_enable(controllers, ctrl, sysinfo);
+	#else
+		sdram_enable(controllers, ctrl);
+	#endif
+
+	print_debug("Ram4\r\n");
+#undef	controllers
+}
Index: src/mainboard/msi/ms6147/Options.lb
===================================================================
--- src/mainboard/msi/ms6147/Options.lb	(revision 0)
+++ src/mainboard/msi/ms6147/Options.lb	(revision 0)
@@ -0,0 +1,99 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## 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 HAVE_PIRQ_TABLE
+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 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_LZMA
+uses PAYLOAD_SIZE
+uses _ROMBASE
+uses _RAMBASE
+uses XIP_ROM_SIZE
+uses XIP_ROM_BASE
+uses HAVE_MP_TABLE
+uses CROSS_COMPILE
+uses CC
+uses HOSTCC
+uses OBJCOPY
+uses DEFAULT_CONSOLE_LOGLEVEL
+uses MAXIMUM_CONSOLE_LOGLEVEL
+uses CONFIG_CONSOLE_SERIAL8250
+uses TTYS0_BAUD
+uses TTYS0_BASE
+uses TTYS0_LCS
+uses CONFIG_UDELAY_TSC
+uses CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2
+uses MAINBOARD_VENDOR
+uses MAINBOARD_PART_NUMBER
+uses CONFIG_CONSOLE_VGA
+uses CONFIG_PCI_ROM_RUN
+
+default ROM_SIZE = 256 * 1024
+default HAVE_FALLBACK_BOOT = 1
+default HAVE_MP_TABLE = 0
+default HAVE_HARD_RESET = 0
+default CONFIG_UDELAY_TSC = 1
+default CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2 = 1
+default HAVE_PIRQ_TABLE = 1
+default IRQ_SLOT_COUNT = 0		# Override this in targets/*/Config.lb.
+default MAINBOARD_VENDOR = "N/A"	# Override this in targets/*/Config.lb.
+default MAINBOARD_PART_NUMBER = "N/A"	# Override this in targets/*/Config.lb.
+default ROM_IMAGE_SIZE = 64 * 1024
+default FALLBACK_SIZE = 128 * 1024
+default STACK_SIZE = 8 * 1024
+default HEAP_SIZE = 16 * 1024
+default HAVE_OPTION_TABLE = 0
+#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"
+default HOSTCC = "gcc"
+default CONFIG_CONSOLE_SERIAL8250 = 1
+default TTYS0_BAUD = 115200
+default TTYS0_BASE = 0x3f8
+default TTYS0_LCS = 0x3			# 8n1
+default DEFAULT_CONSOLE_LOGLEVEL = 9
+default MAXIMUM_CONSOLE_LOGLEVEL = 9
+default CONFIG_CONSOLE_VGA = 1
+default CONFIG_PCI_ROM_RUN = 1
+
+end
Index: src/mainboard/msi/ms6147/debug.c
===================================================================
--- src/mainboard/msi/ms6147/debug.c	(revision 0)
+++ src/mainboard/msi/ms6147/debug.c	(revision 0)
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
+ * 				 2008 Mats Erik Andersson <mats.andersson@gisladisker.se>
+ *
+ * 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
+ */
+
+/* static void dump_spd_registers(const struct mem_controller *ctrl) */
+static void dump_spd_registers(unsigned int ctrl)
+{
+	int i;
+	print_debug("\r\n");
+	for(i = 0; i < 4; i++) {
+		/* Repeated calculation of device value
+		 * reduces the need of processor registers. */
+			uint16_t j;
+			print_debug("dimm: "); 
+			print_debug_hex8(i); 
+			print_debug(".0: ");
+			print_debug_hex8(ctrl + i);
+			if ( (spd_read_byte(ctrl + i, 1)) < 0) {
+				print_debug(" bad device\r\n");
+				continue;
+			}
+			for(j = 0; j < 256; j++) {
+				if ((j & 0xf) == 0) {
+					print_debug("\r\n");
+					print_debug_hex8(j);
+					print_debug(": ");
+				}
+				if (spd_read_byte(ctrl + i, j) < 0) {
+					print_debug("bad device\r\n");
+					break;
+				}
+				print_debug_hex8(spd_read_byte(ctrl + i, j) & 0xff);
+				print_debug_char(' ');
+				if ( (j & 0x0f) == 0x07 )
+					print_debug_char(' ');
+			}
+			print_debug("\r\n");
+		print_debug("Banks: ");
+		print_debug_hex8(spd_read_byte(ctrl + i, 5));
+		print_debug(", density: ");
+		print_debug_hex8(spd_read_byte(ctrl + i, 31));
+		print_debug(".\r\n");
+	}
+}
+
+#if 0
+void dump_spd_registers(void)
+{
+	unsigned device;
+	device = SMBUS_MEM_DEVICE_START;
+	printk_debug("\n");
+	while(device <= SMBUS_MEM_DEVICE_END) {
+		int status = 0;
+		int i;
+		printk_debug("dimm %02x", device);
+		for(i = 0; (i < 256) && (status == 0); i++) {
+			unsigned char byte;
+			if ((i % 20) == 0) {
+				printk_debug("\n%3d: ", i);
+			}
+			status = smbus_read_byte(device, i, &byte);
+			if (status != 0) {
+				printk_debug("bad device\n");
+				continue;
+			}
+			printk_debug("%02x ", byte);
+		}
+		device += SMBUS_MEM_DEVICE_INC;
+		printk_debug("\n");
+	}
+}
+#endif
Index: src/mainboard/msi/ms6147/chip.h
===================================================================
--- src/mainboard/msi/ms6147/chip.h	(revision 0)
+++ src/mainboard/msi/ms6147/chip.h	(revision 0)
@@ -0,0 +1,22 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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_msi_ms6147_ops;
+struct mainboard_msi_ms6147_config {};
Index: src/mainboard/msi/ms6147/auto.c
===================================================================
--- src/mainboard/msi/ms6147/auto.c	(revision 0)
+++ src/mainboard/msi/ms6147/auto.c	(revision 0)
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 <stdlib.h>
+#include <device/pci_def.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 "southbridge/intel/i82371eb/i82371eb_early_smbus.c"
+#include "northbridge/intel/i440bx/raminit.h"
+#include "mainboard/asus/mew-vm/debug.c"	/* FIXME */
+#include "pc80/udelay_io.c"
+#include "lib/delay.c"
+#include "cpu/x86/mtrr/earlymtrr.c"
+#include <cpu/x86/bist.h>
+#include "superio/winbond/w83977tf/w83977tf_early_serial.c"
+
+#define SERIAL_DEV PNP_DEV(0x3f0, W83977TF_SP1)
+
+static inline int spd_read_byte(unsigned int device, unsigned int address)
+{
+	return smbus_read_byte(device, address);
+}
+
+//#include "northbridge/intel/i440bx/raminit.c"
+#include "mainboard/msi/ms6147/raminit.c"
+//#include "northbridge/intel/i440bx/debug.c"
+#include "mainboard/msi/ms6147/debug.c"
+#include "mainboard/msi/ms6147/sdram.c"
+
+static void main(unsigned long bist)
+{
+	static const struct mem_controller memctrl[] = {
+		{
+			.d0 = PCI_DEV(0, 0, 0),
+			.channel0 = {0x50, 0x51, 0x52, 0x53},
+		}
+	};
+
+	if (bist == 0)
+		early_mtrr_init();
+
+	w83977tf_enable_serial(SERIAL_DEV, TTYS0_BASE);
+	uart_init();
+	console_init();
+	report_bist_failure(bist);
+	enable_smbus();
+	//dump_spd_registers(memctrl[0].channel0[0]);
+	sdram_initialize(memctrl);
+	/* DOS-area */
+	//ram_check(0, 640 * 1024);
+	/* 1MB to 4MB */
+	//ram_check(0x00100000, 0x00400000);
+	/* 1MB to 64MB- */
+	//ram_check(0x00100000, 0x03ffffff);
+	/* Across 64MB boundary */
+	//ram_check(0x03fff000, 0x04000010);
+	/* Just below 128MB */
+	//ram_check(0x07ffff00, 0x07fffff0);
+	/* 1MB to 128MB- */
+	//ram_check(0x00100000, 0x07ffffff);
+}
Index: src/mainboard/msi/ms6147/mainboard.c
===================================================================
--- src/mainboard/msi/ms6147/mainboard.c	(revision 0)
+++ src/mainboard/msi/ms6147/mainboard.c	(revision 0)
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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_msi_ms6147_ops = {
+	CHIP_NAME("MSI MS-6147 Mainboard")
+};
Index: targets/msi/ms6147/Config.lb
===================================================================
--- targets/msi/ms6147/Config.lb	(revision 0)
+++ targets/msi/ms6147/Config.lb	(revision 0)
@@ -0,0 +1,51 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## 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 ms6147
+mainboard msi/ms6147
+
+option ROM_SIZE = 256 * 1024
+
+option MAINBOARD_VENDOR = "MSI"
+option MAINBOARD_PART_NUMBER = "MS-6147"
+
+option IRQ_SLOT_COUNT = 8
+
+option DEFAULT_CONSOLE_LOGLEVEL = 9
+option MAXIMUM_CONSOLE_LOGLEVEL = 9
+
+option CONFIG_CONSOLE_VGA = 1
+option CONFIG_PCI_ROM_RUN = 1
+
+romimage "normal"
+	option USE_FALLBACK_IMAGE = 0
+	option COREBOOT_EXTRA_VERSION = ".Normal"
+	payload /tmp/filo.elf
+	#payload /tmp/etherboot.elf
+end
+
+romimage "fallback"
+	option USE_FALLBACK_IMAGE = 1
+	option COREBOOT_EXTRA_VERSION = ".Fallback"
+	payload /tmp/filo.elf
+	#payload /tmp/etherboot.elf
+end
+
+buildrom ./coreboot.rom ROM_SIZE "normal" "fallback"
