- Initial checkin of the freebios2 tree


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@784 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
diff --git a/src/arch/i386/include/arch/asm.h b/src/arch/i386/include/arch/asm.h
new file mode 100644
index 0000000..ea63e2d
--- /dev/null
+++ b/src/arch/i386/include/arch/asm.h
@@ -0,0 +1,30 @@
+#ifndef ASM_H
+#define	ASM_H
+
+#define ASSEMBLER
+
+/*
+ * Bootstrap code for the STPC Consumer
+ * Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
+ *
+ * $Id$
+ *
+ */
+
+#define	I386_ALIGN_TEXT	0
+#define	I386_ALIGN_DATA	0
+
+/*
+ *	XXX
+ */
+#ifdef __ELF__
+#define	EXT(x)		x
+#else
+#define	EXT(x)		_ ## x
+#endif
+
+#define	STATIC(x)	.align I386_ALIGN_TEXT; EXT(x): 
+#define	GLOBAL(x)	.globl EXT(x); STATIC(x)
+#define	ENTRY(x)	.text; GLOBAL(x)
+
+#endif /* ASM_H */
diff --git a/src/arch/i386/include/arch/boot/boot.h b/src/arch/i386/include/arch/boot/boot.h
new file mode 100644
index 0000000..3ff51c3
--- /dev/null
+++ b/src/arch/i386/include/arch/boot/boot.h
@@ -0,0 +1,8 @@
+#ifndef ASM_I386_BOOT_H
+#define ASM_I386_BOOT_H
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_386
+
+#endif /* ASM_I386_BOOT_H */
diff --git a/src/arch/i386/include/arch/intel.h b/src/arch/i386/include/arch/intel.h
new file mode 100644
index 0000000..df6604e
--- /dev/null
+++ b/src/arch/i386/include/arch/intel.h
@@ -0,0 +1,369 @@
+/*
+This software and ancillary information (herein called SOFTWARE )
+called LinuxBIOS          is made available under the terms described
+here.  The SOFTWARE has been approved for release with associated
+LA-CC Number 00-34   .  Unless otherwise indicated, 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.  The public may copy, distribute, prepare derivative works
+and publicly display this SOFTWARE without charge, provided that this
+Notice and any statement of authorship are reproduced on all copies.
+Neither the Government nor the University makes any warranty, express
+or implied, or assumes any liability or responsibility for the use of
+this SOFTWARE.  If 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.
+ */
+/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
+ * rminnich@lanl.gov
+ */
+
+
+#ifndef ROM_INTEL_H
+#define	ROM_INTEL_H
+
+/*
+ * Bootstrap code for the Intel
+ *
+ * $Id$
+ *
+ */
+
+/* 
+ *	Config registers. 
+ */
+/* yeah, yeah, I know these are macros, which is bad. Don't forget: 
+ * we have almost no assembly, so I am not worrying just yet about this. 
+ * we'll fix it someday if we care. My guess is we won't.
+ */
+
+/* well we want functions. But first we want to see it work at all. */
+#undef FUNCTIONS
+#ifndef FUNCTIONS
+
+
+#define RET_LABEL(label)	\
+	jmp label##_done
+
+#define CALL_LABEL(label)	\
+	jmp label		;\
+label##_done:
+
+#define CALLSP(func) \
+	lea	0f, %esp	; \
+	jmp func		; \
+0:
+
+#define RETSP \
+	jmp *%esp
+
+
+#define DELAY(x) mov x, %ecx ;\
+        1: loop 1b ;\
+
+
+	/*
+	 * Macro:	PCI_WRITE_CONFIG_BYTE
+	 * Arguments:	%eax address to write to (includes bus, device, function, &offset)
+	 *              %dl byte to write
+	 *
+	 * Results:	none
+	 *
+	 * Trashed:	%eax, %edx
+	 * Effects:	writes a single byte to pci config space
+	 *
+	 * Notes:	This routine is optimized for minimal register usage.
+	 *              And the tricks it does cannot scale beyond writing a single byte.
+	 *               
+	 *              What it does is almost simple.
+	 *              It preserves %eax (baring special bits) until it is written
+	 *              out to the appropriate port.  And hides the data byte
+	 *              in the high half of edx.
+	 *
+	 *              In %edx[3] it stores the byte to write.
+	 *              In %edx[2] it stores the lower three bits of the address.
+	 */
+
+
+#define PCI_WRITE_CONFIG_BYTE \
+	shll $8,   %edx		; \
+	movb %al,  %dl		; \
+	andb $0x3, %dl		; \
+	shll $16,  %edx		; \
+	\
+	orl  $0x80000000, %eax	; \
+	andl $0xfffffffc, %eax	; \
+	movw $0xcf8, %dx	; \
+	outl %eax,  %dx		; \
+	\
+	shrl $16,  %edx		; \
+	movb %dh,  %al		; \
+	movb $0,   %dh		; \
+	addl $0xcfc, %edx	; \
+	outb %al,  %dx
+
+
+	/*
+	 * Macro:	PCI_WRITE_CONFIG_WORD
+	 * Arguments:	%eax address to write to (includes bus, device, function, &offset)
+	 *              %ecx word to write
+	 *
+	 * Results:	none
+	 *
+	 * Trashed:	%eax, %edx
+	 * Preserved:   %ecx
+	 * Effects:	writes a single byte to pci config space
+	 *
+	 * Notes:	This routine is optimized for minimal register usage.
+	 *               
+	 *              What it does is almost simple.
+	 *              It preserves %eax (baring special bits) until it is written
+	 *              out to the appropriate port.  And hides the least significant
+	 *              bits of the address in the high half of edx.
+	 *
+	 *              In %edx[2] it stores the lower three bits of the address.
+	 */
+
+
+#define PCI_WRITE_CONFIG_WORD \
+	movb %al,  %dl		; \
+	andl $0x3, %edx		; \
+	shll $16,  %edx		; \
+	\
+	orl  $0x80000000, %eax	; \
+	andl $0xfffffffc, %eax	; \
+	movw $0xcf8, %dx	; \
+	outl %eax,  %dx		; \
+	\
+	shrl $16,  %edx		; \
+	movl %ecx, %eax		; \
+	addl $0xcfc, %edx	; \
+	outw %ax,  %dx
+
+
+
+	/*
+	 * Macro:	PCI_WRITE_CONFIG_DWORD
+	 * Arguments:	%eax address to write to (includes bus, device, function, &offset)
+	 *              %ecx dword to write
+	 *
+	 * Results:	none
+	 *
+	 * Trashed:	%eax, %edx
+	 * Preserved:   %ecx
+	 * Effects:	writes a single byte to pci config space
+	 *
+	 * Notes:	This routine is optimized for minimal register usage.
+	 *               
+	 *              What it does is almost simple.
+	 *              It preserves %eax (baring special bits) until it is written
+	 *              out to the appropriate port.  And hides the least significant
+	 *              bits of the address in the high half of edx.
+	 *
+	 *              In %edx[2] it stores the lower three bits of the address.
+	 */
+
+
+#define PCI_WRITE_CONFIG_DWORD \
+	movb %al,  %dl		; \
+	andl $0x3, %edx		; \
+	shll $16,  %edx		; \
+	\
+	orl  $0x80000000, %eax	; \
+	andl $0xfffffffc, %eax	; \
+	movw $0xcf8, %dx	; \
+	outl %eax,  %dx		; \
+	\
+	shrl $16,  %edx		; \
+	movl %ecx, %eax		; \
+	addl $0xcfc, %edx	; \
+	outl %eax,  %dx
+
+
+
+	
+	/*
+	 * Macro:	PCI_READ_CONFIG_BYTE
+	 * Arguments:	%eax address to read from (includes bus, device, function, &offset)
+	 *
+	 * Results:	%al Byte read
+	 *
+	 * Trashed:	%eax, %edx
+	 * Effects:	reads a single byte from pci config space
+	 *
+	 * Notes:	This routine is optimized for minimal register usage.
+	 *               
+	 *              What it does is almost simple.
+	 *              It preserves %eax (baring special bits) until it is written
+	 *              out to the appropriate port.  And hides the least significant
+	 *              bits of the address in the high half of edx.
+	 *
+	 *              In %edx[2] it stores the lower three bits of the address.
+	 */
+
+
+#define PCI_READ_CONFIG_BYTE \
+	movb %al,  %dl		; \
+	andl $0x3, %edx		; \
+	shll $16,  %edx		; \
+	\
+	orl  $0x80000000, %eax	; \
+	andl $0xfffffffc, %eax	; \
+	movw $0xcf8, %dx	; \
+	outl %eax,  %dx		; \
+	\
+	shrl $16,  %edx		; \
+	addl $0xcfc, %edx	; \
+	inb  %dx,  %al
+
+
+
+	/*
+	 * Macro:	PCI_READ_CONFIG_WORD
+	 * Arguments:	%eax address to read from (includes bus, device, function, &offset)
+	 *
+	 * Results:	%ax word read
+	 *
+	 * Trashed:	%eax, %edx
+	 * Effects:	reads a 2 bytes from pci config space
+	 *
+	 * Notes:	This routine is optimized for minimal register usage.
+	 *               
+	 *              What it does is almost simple.
+	 *              It preserves %eax (baring special bits) until it is written
+	 *              out to the appropriate port.  And hides the least significant
+	 *              bits of the address in the high half of edx.
+	 *
+	 *              In %edx[2] it stores the lower three bits of the address.
+	 */
+
+
+#define PCI_READ_CONFIG_WORD \
+	movb %al,  %dl		; \
+	andl $0x3, %edx		; \
+	shll $16,  %edx		; \
+	\
+	orl  $0x80000000, %eax	; \
+	andl $0xfffffffc, %eax	; \
+	movw $0xcf8, %dx	; \
+	outl %eax,  %dx		; \
+	\
+	shrl $16,  %edx		; \
+	addl $0xcfc, %edx	; \
+	inw  %dx,  %ax
+
+
+
+	/*
+	 * Macro:	PCI_READ_CONFIG_DWORD
+	 * Arguments:	%eax address to read from (includes bus, device, function, &offset)
+	 *
+	 * Results:	%eax
+	 *
+	 * Trashed:	%edx
+	 * Effects:	reads 4 bytes from pci config space
+	 *
+	 * Notes:	This routine is optimized for minimal register usage.
+	 *               
+	 *              What it does is almost simple.
+	 *              It preserves %eax (baring special bits) until it is written
+	 *              out to the appropriate port.  And hides the least significant
+	 *              bits of the address in the high half of edx.
+	 *
+	 *              In %edx[2] it stores the lower three bits of the address.
+	 */
+
+
+#define PCI_READ_CONFIG_DWORD \
+	movb %al,  %dl		; \
+	andl $0x3, %edx		; \
+	shll $16,  %edx		; \
+	\
+	orl  $0x80000000, %eax	; \
+	andl $0xfffffffc, %eax	; \
+	movw $0xcf8, %dx	; \
+	outl %eax,  %dx		; \
+	\
+	shrl $16,  %edx		; \
+	addl $0xcfc, %edx	; \
+	inl  %dx,  %eax
+
+
+
+
+#define CS_READ(which)  \
+                 mov  $0x80000000,%eax ; \
+                 mov  which,%ax ; \
+                 and  $0xfc,%al            /* clear bits 1-0 */ ; \
+                 mov  $0xcf8,%dx           /* port 0xcf8 ?*/ ; \
+                 outl  %eax,%dx             /* open up CS config */ ; \
+                 add  $0x4,%dl             /* 0xcfc data port 0 */ ; \
+                 mov  which,%al ; \
+                 and  $0x3,%al             /* only bits 1-0 */ ; \
+                 add  %al,%dl ; \
+                 inb   %dx,%al              /* read  */ ; \
+
+
+#define CS_WRITE(which, data)  \
+                 mov  $0x80000000,%eax       /* 32bit word with bit 31 set */ ; \
+                 mov  which,%ax             /* put the reg# in the low part */ ; \
+                 and  $0xfc,%al             /* dword align the reg# */ ; \
+                 mov  $0xcf8,%dx            /* enable port  */ ; \
+                 outl  %eax,%dx ; \
+                 add  $0x4,%dl             /* 1st data port */ ; \
+                 mov  which,%ax             /* register# */ ; \
+                 and  $0x3,%ax ; \
+                 add  %al,%dl ; \
+		 mov  data, %al ; \
+                 outb  %al,%dx                /* write to reg */ 
+
+#define REGBIS(which, bis) \
+	CS_READ(which) ;\
+	movb bis, %cl ;\
+	orb %al, %cl ;\
+	CS_WRITE(which, %cl)
+
+#define REGBIC(which, bic) \
+	CS_READ(which) ;\
+	movb bic, %cl ;\
+	notb %cl ;\
+	andb %al, %cl ;\
+	CS_WRITE(which, %cl)
+
+
+/* macro to BIC and BIS a reg. calls read a reg,
+ * does a BIC and then a BIS on it.
+ * to clear no bits, make BIC 0.
+ * to set no bits, make BIS 0
+ */
+#define REGBICBIS(which, bic, bis) \
+	CS_READ(which) ;\
+	movb bic, %cl ;\
+	notb %cl ;\
+	andb %cl, %al ;\
+	movb bis, %cl ;\
+	orb %al, %cl ;\
+	CS_WRITE(which, %cl)
+
+#else
+NO FUNCTIONS YET!
+#endif
+
+
+
+/* originally this macro was from STPC BIOS */
+#define	intel_chip_post_macro(value)			 \
+	movb	$value, %al				; \
+	outb	%al, $0x80
+
+#define INTEL_PDATA_MAGIC 0xdeadbeef
+
+/* SLOW_DOWN_IO is a delay we can use that is roughly cpu neutral,
+ * and can be used before memory or timer chips come up.
+ * Since this hits the isa bus it's roughly
+ */
+#define SLOW_DOWN_IO inb $0x80, %al
+
+#endif /* ROM_INTEL_H */
diff --git a/src/arch/i386/include/arch/io.h b/src/arch/i386/include/arch/io.h
new file mode 100644
index 0000000..bcba9a9
--- /dev/null
+++ b/src/arch/i386/include/arch/io.h
@@ -0,0 +1,76 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+/*
+ * This file contains the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl and the "string versions" of the same
+ * (insb/insw/insl/outsb/outsw/outsl).
+ *
+ * This file is not meant to be obfuscating: it's just complicated
+ * to (a) handle it all in a way that makes gcc able to optimize it
+ * as well as possible and (b) trying to avoid writing the same thing
+ * over and over again with slight variations and possibly making a
+ * mistake somewhere.
+ */
+
+ /*
+  *  Bit simplified and optimized by Jan Hubicka
+  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
+  */
+
+/*
+ * Talk about misusing macros..
+ */
+#define __OUT1(s,x) \
+extern inline void out##s(unsigned x value, unsigned short port) {
+
+#define __OUT2(s,s1,s2) \
+__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
+
+#define __OUT(s,s1,x) \
+__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } 
+
+#define __IN1(s) \
+extern inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
+
+#define __IN2(s,s1,s2) \
+__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
+
+#define __IN(s,s1,i...) \
+__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 
+
+#define __INS(s) \
+extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+{ __asm__ __volatile__ ("cld ; rep ; ins" #s \
+: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
+
+#define __OUTS(s) \
+extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+{ __asm__ __volatile__ ("cld ; rep ; outs" #s \
+: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
+
+#define RETURN_TYPE unsigned char
+__IN(b,"")
+#undef RETURN_TYPE
+#define RETURN_TYPE unsigned short
+__IN(w,"")
+#undef RETURN_TYPE
+#define RETURN_TYPE unsigned int
+__IN(l,"")
+#undef RETURN_TYPE
+
+__OUT(b,"b",char)
+__OUT(w,"w",short)
+__OUT(l,,int)
+
+__INS(b)
+__INS(w)
+__INS(l)
+
+__OUTS(b)
+__OUTS(w)
+__OUTS(l)
+
+
+#endif
+
diff --git a/src/arch/i386/include/arch/pciconf.h b/src/arch/i386/include/arch/pciconf.h
new file mode 100644
index 0000000..8695ee2
--- /dev/null
+++ b/src/arch/i386/include/arch/pciconf.h
@@ -0,0 +1,9 @@
+#ifndef PCI_CONF_REG_INDEX
+
+// These are defined in the PCI spec, and hence are theoretically
+// inclusive of ANYTHING that uses a PCI bus. 
+#define	PCI_CONF_REG_INDEX	0xcf8
+#define	PCI_CONF_REG_DATA	0xcfc
+#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where))
+
+#endif
diff --git a/src/arch/i386/include/arch/pirq_routing.h b/src/arch/i386/include/arch/pirq_routing.h
new file mode 100644
index 0000000..215c4e5
--- /dev/null
+++ b/src/arch/i386/include/arch/pirq_routing.h
@@ -0,0 +1,54 @@
+#ifndef ARCH_PIRQ_ROUTING_H
+#define ARCH_PIRQ_ROUTING_H
+
+#include <stdint.h>
+
+#define PIRQ_SIGNATURE	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
+#define PIRQ_VERSION 0x0100
+
+struct irq_info {
+	uint8_t bus, devfn;			/* Bus, device and function */
+	struct {
+		uint8_t link;			/* IRQ line ID, chipset dependent, 0=not routed */
+		uint16_t bitmap;		/* Available IRQs */
+	} __attribute__((packed)) irq[4];
+	uint8_t slot;				/* Slot number, 0=onboard */
+	uint8_t rfu;
+} __attribute__((packed));
+
+#if defined(IRQ_SLOT_COUNT)
+#define IRQ_SLOTS_COUNT IRQ_SLOT_COUNT
+#elif (__GNUC__ < 3)
+#define IRQ_SLOTS_COUNT 1
+#else
+#define IRQ_SLOTS_COUNT
+#endif
+
+struct irq_routing_table {
+	uint32_t signature;			/* PIRQ_SIGNATURE should be here */
+	uint16_t version;			/* PIRQ_VERSION */
+	uint16_t size;				/* Table size in bytes */
+	uint8_t  rtr_bus, rtr_devfn;		/* Where the interrupt router lies */
+	uint16_t exclusive_irqs;		/* IRQs devoted exclusively to PCI usage */
+	uint16_t rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
+	uint32_t miniport_data;			/* Crap */
+	uint8_t  rfu[11];
+	uint8_t  checksum;			/* Modulo 256 checksum must give zero */
+	struct irq_info slots[IRQ_SLOTS_COUNT];
+} __attribute__((packed));
+
+extern const struct irq_routing_table intel_irq_routing_table;
+
+#if defined(DEBUG) && defined(HAVE_PIRQ_TABLE)
+void check_pirq_routing_table(void);
+#else
+#define check_pirq_routing_table() do {} while(0)
+#endif
+
+#if defined(HAVE_PIRQ_TABLE)
+unsigned long copy_pirq_routing_table(unsigned long start);
+#else
+#define copy_pirq_routing_table(start) (start)
+#endif
+
+#endif /* ARCH_PIRQ_ROUTING_H */
diff --git a/src/arch/i386/include/arch/rom_segs.h b/src/arch/i386/include/arch/rom_segs.h
new file mode 100644
index 0000000..b51a805
--- /dev/null
+++ b/src/arch/i386/include/arch/rom_segs.h
@@ -0,0 +1,10 @@
+#ifndef ROM_SEGS_H
+#define ROM_SEGS_H
+
+#define ROM_CODE_SEG 0x08
+#define ROM_DATA_SEG 0x10
+
+#define CACHE_RAM_CODE_SEG 0x18
+#define CACHE_RAM_DATA_SEG 0x20
+
+#endif /* ROM_SEGS_H */
diff --git a/src/arch/i386/include/arch/romcc_io.h b/src/arch/i386/include/arch/romcc_io.h
new file mode 100644
index 0000000..02cc272
--- /dev/null
+++ b/src/arch/i386/include/arch/romcc_io.h
@@ -0,0 +1,84 @@
+static void outb(unsigned char value, unsigned short port)
+{
+	__builtin_outb(value, port);
+}
+
+static void outw(unsigned short value, unsigned short port)
+{
+	__builtin_outw(value, port);
+}
+
+static void outl(unsigned int value, unsigned short port)
+{
+	__builtin_outl(value, port);
+}
+
+
+static unsigned char inb(unsigned short port)
+{
+	return __builtin_inb(port);
+}
+
+
+static unsigned char inw(unsigned short port)
+{
+	return __builtin_inw(port);
+}
+
+static unsigned char inl(unsigned short port)
+{
+	return __builtin_inl(port);
+}
+
+static void hlt(void)
+{
+	__builtin_hlt();
+}
+
+static unsigned int config_cmd(unsigned char bus, unsigned devfn, unsigned where)
+{
+	return 0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3);
+}
+
+static unsigned char pcibios_read_config_byte(
+	unsigned char bus, unsigned devfn, unsigned where)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	return inb(0xCFC + (where & 3));
+}
+
+static unsigned short pcibios_read_config_word(
+	unsigned char bus, unsigned devfn, unsigned where)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	return inw(0xCFC + (where & 2));
+}
+
+static unsigned int pcibios_read_config_dword(
+	unsigned char bus, unsigned devfn, unsigned where)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	return inl(0xCFC);
+}
+
+
+static void pcibios_write_config_byte(
+	unsigned char bus, unsigned devfn, unsigned where, unsigned char value)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	outb(value, 0xCFC + (where & 3));
+}
+
+static void pcibios_write_config_word(
+	unsigned char bus, unsigned devfn, unsigned where, unsigned short value)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	outw(value, 0xCFC + (where & 2));
+}
+
+static void pcibios_write_config_dword(
+	unsigned char bus, unsigned devfn, unsigned where, unsigned int value)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	outl(value, 0xCFC);
+}
diff --git a/src/arch/i386/include/arch/smp/mpspec.h b/src/arch/i386/include/arch/smp/mpspec.h
new file mode 100644
index 0000000..305276e
--- /dev/null
+++ b/src/arch/i386/include/arch/smp/mpspec.h
@@ -0,0 +1,282 @@
+#ifndef __ASM_MPSPEC_H
+#define __ASM_MPSPEC_H
+
+#ifdef HAVE_MP_TABLE
+
+/*
+ * Structure definitions for SMP machines following the
+ * Intel Multiprocessing Specification 1.1 and 1.4.
+ */
+
+/*
+ * This tag identifies where the SMP configuration
+ * information is. 
+ */
+ 
+#define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_')
+
+/*
+ * a maximum of 16 APICs with the current APIC ID architecture.
+ */
+#define MAX_APICS 16
+
+
+#define SMP_FLOATING_TABLE_LEN sizeof(struct intel_mp_floating)
+
+struct intel_mp_floating
+{
+	char mpf_signature[4];		/* "_MP_" 			*/
+	unsigned long mpf_physptr;	/* Configuration table address	*/
+	unsigned char mpf_length;	/* Our length (paragraphs)	*/
+	unsigned char mpf_specification;/* Specification version	*/
+	unsigned char mpf_checksum;	/* Checksum (makes sum 0)	*/
+	unsigned char mpf_feature1;	/* Standard or configuration ? 	*/
+	unsigned char mpf_feature2;	/* Bit7 set for IMCR|PIC	*/
+	unsigned char mpf_feature3;	/* Unused (0)			*/
+	unsigned char mpf_feature4;	/* Unused (0)			*/
+	unsigned char mpf_feature5;	/* Unused (0)			*/
+};
+
+struct mp_config_table
+{
+	char mpc_signature[4];
+#define MPC_SIGNATURE "PCMP"
+	unsigned short mpc_length;	/* Size of table */
+	char  mpc_spec;			/* 0x01 */
+	char  mpc_checksum;
+	char  mpc_oem[8];
+	char  mpc_productid[12];
+	unsigned long mpc_oemptr;	/* 0 if not present */
+	unsigned short mpc_oemsize;	/* 0 if not present */
+	unsigned short mpc_entry_count;
+	unsigned long mpc_lapic;	/* APIC address */
+	unsigned short mpe_length;	/* Extended Table size */
+	unsigned char mpe_checksum;	/* Extended Table checksum */
+	unsigned char reserved;
+};
+
+/* Followed by entries */
+
+#define	MP_PROCESSOR	0
+#define	MP_BUS		1
+#define	MP_IOAPIC	2
+#define	MP_INTSRC	3
+#define	MP_LINTSRC	4
+
+struct mpc_config_processor
+{
+	unsigned char mpc_type;
+	unsigned char mpc_apicid;	/* Local APIC number */
+	unsigned char mpc_apicver;	/* Its versions */
+	unsigned char mpc_cpuflag;
+#define MPC_CPU_ENABLED		1	/* Processor is available */
+#define MPC_CPU_BOOTPROCESSOR	2	/* Processor is the BP */
+	unsigned long mpc_cpufeature;		
+#define MPC_CPU_STEPPING_MASK 0x0F
+#define MPC_CPU_MODEL_MASK	0xF0
+#define MPC_CPU_FAMILY_MASK	0xF00
+	unsigned long mpc_featureflag;	/* CPUID feature value */
+	unsigned long mpc_reserved[2];
+};
+
+struct mpc_config_bus
+{
+	unsigned char mpc_type;
+	unsigned char mpc_busid;
+	unsigned char mpc_bustype[6] __attribute((packed));
+};
+
+#define BUSTYPE_EISA	"EISA"
+#define BUSTYPE_ISA	"ISA"
+#define BUSTYPE_INTERN	"INTERN"	/* Internal BUS */
+#define BUSTYPE_MCA	"MCA"
+#define BUSTYPE_VL	"VL"		/* Local bus */
+#define BUSTYPE_PCI	"PCI"
+#define BUSTYPE_PCMCIA	"PCMCIA"
+
+struct mpc_config_ioapic
+{
+	unsigned char mpc_type;
+	unsigned char mpc_apicid;
+	unsigned char mpc_apicver;
+	unsigned char mpc_flags;
+#define MPC_APIC_USABLE		0x01
+	unsigned long mpc_apicaddr;
+};
+
+struct mpc_config_intsrc
+{
+	unsigned char mpc_type;
+	unsigned char mpc_irqtype;
+	unsigned short mpc_irqflag;
+	unsigned char mpc_srcbus;
+	unsigned char mpc_srcbusirq;
+	unsigned char mpc_dstapic;
+	unsigned char mpc_dstirq;
+};
+
+enum mp_irq_source_types {
+	mp_INT = 0,
+	mp_NMI = 1,
+	mp_SMI = 2,
+	mp_ExtINT = 3
+};
+
+#define MP_IRQ_POLARITY_DEFAULT	0x0
+#define MP_IRQ_POLARITY_HIGH	0x1
+#define MP_IRQ_POLARITY_LOW	0x3
+#define MP_IRQ_POLARITY_MASK    0x3
+#define MP_IRQ_TRIGGER_DEFAULT	0x0
+#define MP_IRQ_TRIGGER_EDGE	0x4
+#define MP_IRQ_TRIGGER_LEVEL	0xc
+#define MP_IRQ_TRIGGER_MASK     0xc
+
+
+struct mpc_config_lintsrc
+{
+	unsigned char mpc_type;
+	unsigned char mpc_irqtype;
+	unsigned short mpc_irqflag;
+	unsigned char mpc_srcbusid;
+	unsigned char mpc_srcbusirq;
+	unsigned char mpc_destapic;	
+#define MP_APIC_ALL	0xFF
+	unsigned char mpc_destapiclint;
+};
+
+/*
+ *	Default configurations
+ *
+ *	1	2 CPU ISA 82489DX
+ *	2	2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining
+ *	3	2 CPU EISA 82489DX
+ *	4	2 CPU MCA 82489DX
+ *	5	2 CPU ISA+PCI
+ *	6	2 CPU EISA+PCI
+ *	7	2 CPU MCA+PCI
+ */
+
+#define MAX_IRQ_SOURCES 128
+#define MAX_MP_BUSSES 32
+enum mp_bustype {
+	MP_BUS_ISA,
+	MP_BUS_EISA,
+	MP_BUS_PCI,
+	MP_BUS_MCA
+};
+
+/* Followed by entries */
+
+#define	MPE_SYSTEM_ADDRESS_SPACE	0x80
+#define	MPE_BUS_HIERARCHY		0x81
+#define	MPE_COMPATIBILITY_ADDRESS_SPACE	0x82
+
+struct mp_exten_config {
+	unsigned char mpe_type;
+	unsigned char mpe_length;
+};
+
+typedef struct mp_exten_config *mpe_t;
+
+struct mp_exten_system_address_space {
+	unsigned char mpe_type;
+	unsigned char mpe_length;
+	unsigned char mpe_busid;
+	unsigned char mpe_address_type;
+#define ADDRESS_TYPE_IO       0
+#define ADDRESS_TYPE_MEM      1
+#define ADDRESS_TYPE_PREFETCH 2
+	unsigned int  mpe_address_base_low;
+	unsigned int  mpe_address_base_high;
+	unsigned int  mpe_address_length_low;
+	unsigned int  mpe_address_length_high;
+};
+
+struct mp_exten_bus_hierarchy {
+	unsigned char mpe_type;
+	unsigned char mpe_length;
+	unsigned char mpe_busid;
+	unsigned char mpe_bus_info;
+#define BUS_SUBTRACTIVE_DECODE 1
+	unsigned char mpe_parent_busid;
+	unsigned char reserved[3];
+};
+
+struct mp_exten_compatibility_address_space {
+	unsigned char mpe_type;
+	unsigned char mpe_length;
+	unsigned char mpe_busid;
+	unsigned char mpe_address_modifier;
+#define ADDRESS_RANGE_SUBTRACT 1
+#define ADDRESS_RANGE_ADD      0
+	unsigned int  mpe_range_list;
+#define RANGE_LIST_IO_ISA	0	
+	/* X100 - X3FF
+	 * X500 - X7FF
+	 * X900 - XBFF
+	 * XD00 - XFFF
+	 */
+#define RANGE_LIST_IO_VGA	1
+	/* X3B0 - X3BB
+	 * X3C0 - X3DF
+	 * X7B0 - X7BB
+	 * X7C0 - X7DF
+	 * XBB0 - XBBB
+	 * XBC0 - XBDF
+	 * XFB0 - XFBB
+	 * XFC0 - XCDF
+	 */
+};
+
+/* Default local apic addr */
+#define LAPIC_ADDR 0xFEE00000
+
+void *smp_next_mpc_entry(struct mp_config_table *mc);
+void *smp_next_mpe_entry(struct mp_config_table *mc);
+
+void smp_write_processor(struct mp_config_table *mc,
+	unsigned char apicid, unsigned char apicver,
+	unsigned char cpuflag, unsigned int cpufeature,
+	unsigned int featureflag);
+void smp_write_processors(struct mp_config_table *mc, 
+	unsigned long *processor_map);
+void smp_write_bus(struct mp_config_table *mc,
+	unsigned char id, unsigned char *bustype);
+void smp_write_ioapic(struct mp_config_table *mc,
+	unsigned char id, unsigned char ver, 
+	unsigned long apicaddr);
+void smp_write_intsrc(struct mp_config_table *mc,
+	unsigned char irqtype, unsigned short irqflag,
+	unsigned char srcbus, unsigned char srcbusirq,
+	unsigned char dstapic, unsigned char dstirq);
+void smp_write_lintsrc(struct mp_config_table *mc,
+	unsigned char irqtype, unsigned short irqflag,
+	unsigned char srcbusid, unsigned char srcbusirq,
+	unsigned char destapic, unsigned char destapiclint);
+void smp_write_address_space(struct mp_config_table *mc,
+	unsigned char busid, unsigned char address_type,
+	unsigned int address_base_low, unsigned int address_base_high,
+	unsigned int address_length_low, unsigned int address_length_high);
+void smp_write_bus_hierarchy(struct mp_config_table *mc,
+	unsigned char busid, unsigned char bus_info,
+	unsigned char parent_busid);
+void smp_write_compatibility_address_space(struct mp_config_table *mc,
+	unsigned char busid, unsigned char address_modifier,
+	unsigned int range_list);
+unsigned char smp_compute_checksum(void *v, int len);
+void *smp_write_floating_table(unsigned long addr);
+unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map);
+
+/* A table (per mainboard) listing the initial apicid of each cpu. */
+extern unsigned long initial_apicid[MAX_CPUS];
+
+#else /* HAVE_MP_TABLE */
+static inline 
+unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map)
+{
+	return addr;
+}
+#endif /* HAVE_MP_TABLE */
+
+#endif
+
diff --git a/src/arch/i386/include/bitops.h b/src/arch/i386/include/bitops.h
new file mode 100644
index 0000000..fae2045
--- /dev/null
+++ b/src/arch/i386/include/bitops.h
@@ -0,0 +1,20 @@
+#ifndef I386_BITOPS_H
+#define I386_BITOPS_H
+
+/**
+ * log2 - Find the truncated log base 2 of x
+ */
+
+static inline unsigned long log2(unsigned long x)
+{
+	unsigned long r = 0;
+	__asm__(
+		"bsrl %1, %0\n\t"
+		"jnz 1f\n\t"
+		"movl $-1, %0\n\t"
+		"1:\n\t"
+		: "=r" (r) : "r" (x));
+	return r;
+		
+}
+#endif /* I386_BITOPS_H */
diff --git a/src/arch/i386/include/stddef.h b/src/arch/i386/include/stddef.h
new file mode 100644
index 0000000..4bf6b0a
--- /dev/null
+++ b/src/arch/i386/include/stddef.h
@@ -0,0 +1,15 @@
+#ifndef I386_STDDEF_H
+#define I386_STDDEF_H
+
+typedef long ptrdiff_t;
+typedef unsigned long size_t;
+typedef long ssize_t;
+
+typedef int wchar_t;
+typedef unsigned int wint_t;
+
+#define NULL 0
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif /* I386_STDDEF_H */
diff --git a/src/arch/i386/include/stdint.h b/src/arch/i386/include/stdint.h
new file mode 100644
index 0000000..58d7519
--- /dev/null
+++ b/src/arch/i386/include/stdint.h
@@ -0,0 +1,52 @@
+#ifndef I386_STDINT_H
+#define I386_STDINT_H
+
+/* Exact integral types */
+typedef unsigned char      uint8_t;
+typedef signed char        int8_t; 
+
+typedef unsigned short     uint16_t;
+typedef signed short       int16_t;
+
+typedef unsigned int       uint32_t;
+typedef signed int         int32_t;
+
+typedef unsigned long long uint64_t;
+typedef signed long long   int64_t;
+
+/* Small types */
+typedef unsigned char      uint_least8_t;
+typedef signed char        int_least8_t; 
+
+typedef unsigned short     uint_least16_t;
+typedef signed short       int_least16_t;
+
+typedef unsigned int       uint_least32_t;
+typedef signed int         int_least32_t;
+
+typedef unsigned long long uint_least64_t;
+typedef signed long long   int_least64_t;
+
+/* Fast Types */
+typedef unsigned char      uint_fast8_t;
+typedef signed char        int_fast8_t; 
+
+typedef unsigned int       uint_fast16_t;
+typedef signed int         int_fast16_t;
+
+typedef unsigned int       uint_fast32_t;
+typedef signed int         int_fast32_t;
+
+typedef unsigned long long uint_fast64_t;
+typedef signed long long   int_fast64_t;
+
+/* Types for `void *' pointers.  */
+typedef int                intptr_t;
+typedef unsigned int       uintptr_t;
+
+/* Largest integral types */
+typedef long long int      intmax_t;
+typedef unsigned long long uintmax_t;
+
+
+#endif /* I386_STDINT_H */