diff -urN -x CVS u-boot/cpu/i386/config.mk u-boot-i386/cpu/i386/config.mk
--- u-boot/cpu/i386/config.mk	Mon Nov 18 01:14:45 2002
+++ u-boot-i386/cpu/i386/config.mk	Fri Nov 22 09:41:51 2002
@@ -21,6 +21,6 @@
 # MA 02111-1307 USA
 #
 
-PLATFORM_RELFLAGS += # -pipe -mpreferred-stack-boundary=2 -fno-builtin -nostdinc -nostdlib
+PLATFORM_RELFLAGS += 
 
-PLATFORM_CPPFLAGS += -march=i386
+PLATFORM_CPPFLAGS += -march=i386 -Werror
diff -urN -x CVS u-boot/cpu/i386/interrupts.c u-boot-i386/cpu/i386/interrupts.c
--- u-boot/cpu/i386/interrupts.c	Mon Nov 18 01:14:45 2002
+++ u-boot-i386/cpu/i386/interrupts.c	Mon Apr 28 10:17:52 2003
@@ -29,22 +29,6 @@
 #include <asm/ibmpc.h>
 
 
-#if 0
-/* done */
-int	interrupt_init     (void);
-void	irq_install_handler(int, interrupt_handler_t *, void *);
-void	irq_free_handler   (int);
-void	enable_interrupts  (void);
-int	disable_interrupts (void);
-
-/* todo */
-void	timer_interrupt    (struct pt_regs *);
-void	external_interrupt (struct pt_regs *);
-void	reset_timer	   (void);
-ulong	get_timer	   (ulong base);
-void	set_timer	   (ulong t);
-
-#endif
 
 struct idt_entry {
 	u16	base_low;
@@ -76,43 +60,30 @@
 static irq_desc_t irq_table[MAX_IRQ];
 
 
-/* syscall stuff, very untested 
- * the current approach which includes copying
- * part of the stack will work badly for 
- * varargs functions.
- * if we were to store the top three words on the
- * stack (eip, ss, eflags) somwhere and add 14 to
- * %esp ....
- */
+
 asm(".globl syscall_entry\n" \
         "syscall_entry:\n" \
-        "movl   12(%esp), %eax\n" \
-	"movl   %esp, %ebx\n" \
-        "addl   $16, %ebx\n" \
-        "pushl  %ebx\n" \
-        "pushl  %eax\n" \
-        "call   do_syscall\n" \
-        "addl   $8, %esp\n" \
-        "iret\n");
+        "popl   %ebx\n"        /* throw away the return address, flags  */ \
+        "popl   %ebx\n"        /* and segment that the INT instruction pushed */ \
+        "popl   %ebx\n"        /* on to the stack */ \
+        "movl   %eax, %ecx\n"  /* load the syscall nr argument*/ \
+        "movl   syscall_tbl, %eax\n" /* load start of syscall table */ \
+        "cmpl   $(11-1), %ecx\n"  /* FixMe: find a way to use NR_SYSCALLS macro here */ \
+        "ja     bad_syscall\n" \
+        "movl   (%eax, %ecx, 4), %eax\n" /* load the handler of the syscall*/ \
+        "test   %eax, %eax\n" /* test for null */ \
+        "je     bad_syscall\n" \
+        "popl   %ecx\n" \
+        "popl   %ebx\n" \
+        "sti    \n" \
+        "jmp    *%eax\n" \
+"bad_syscall: movl $0xffffffff, %eax\n" \
+        "popl   %ecx\n" \
+        "popl   %ebx\n" \
+        "ret");
 
 void __attribute__ ((regparm(0))) syscall_entry(void);
 
-int __attribute__ ((regparm(0))) do_syscall(u32 nr, u32 *stack)
-{
-	if (nr<NR_SYSCALLS) {
-		/* We copy 8 args of the syscall,
-		 * this will be a problem with the 
-		 * printf syscall .... */
-		int (*fp)(u32, u32, u32, u32,
-			  u32, u32, u32, u32);
-		fp = syscall_tbl[nr];
-		return fp(stack[0], stack[1], stack[2], stack[3],
-					     stack[4], stack[5], stack[6], stack[7]);
-	}
-	
-	return -1;
-}
-	
 
 asm ("irq_return:\n"
      "     addl  $4, %esp\n"
diff -urN -x CVS u-boot/cpu/i386/serial.c u-boot-i386/cpu/i386/serial.c
--- u-boot/cpu/i386/serial.c	Mon Nov 18 01:14:45 2002
+++ u-boot-i386/cpu/i386/serial.c	Mon Apr 28 10:21:51 2003
@@ -24,6 +24,7 @@
  * MA 02111-1307 USA
  */
 /*------------------------------------------------------------------------------+ */
+
 /*
  * This source code has been made available to you by IBM on an AS-IS
  * basis.  Anyone receiving this source is licensed under IBM
@@ -89,13 +90,15 @@
 	char *rx_buffer;
 	ulong rx_put;
 	ulong rx_get;
+	int cts;
 } serial_buffer_t;
 
-volatile static serial_buffer_t buf_info;
+volatile serial_buffer_t buf_info;
+static int serial_buffer_active=0;
 #endif
 
 
-static int serial_div (int baudrate )
+static int serial_div(int baudrate)
 {
 	
 	switch (baudrate) {
@@ -112,7 +115,7 @@
 	case 115200:
 		return 1;		
 	}
-	hang ();
+	hang();
 }
 
 
@@ -121,7 +124,7 @@
  * as serial console interface.
  */
 
-int serial_init (void)
+int serial_init(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
 
@@ -134,24 +137,24 @@
 	outb(bdiv, UART0_BASE + UART_DLL);	/* set baudrate divisor */
 	outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */
 	outb(0x03, UART0_BASE + UART_LCR);	/* clear DLAB; set 8 bits, no parity */
-	outb(0x00, UART0_BASE + UART_FCR);	/* disable FIFO */
-	outb(0x00, UART0_BASE + UART_MCR);	/* no modem control DTR RTS */
+	outb(0x01, UART0_BASE + UART_FCR);	/* enable FIFO */
+	outb(0x0b, UART0_BASE + UART_MCR);	/* Set DTR and RTS active */
 	val = inb(UART0_BASE + UART_LSR);	/* clear line status */
 	val = inb(UART0_BASE + UART_RBR);	/* read receive buffer */
 	outb(0x00, UART0_BASE + UART_SCR);	/* set scratchpad */
 	outb(0x00, UART0_BASE + UART_IER);	/* set interrupt enable reg */
 
-	return (0);
+	return 0;
 }
 
 
-void serial_setbrg (void)
+void serial_setbrg(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
 
 	unsigned short bdiv;
 	
-	bdiv = serial_div (gd->baudrate);
+	bdiv = serial_div(gd->baudrate);
 
 	outb(0x80, UART0_BASE + UART_LCR);	/* set DLAB bit */
 	outb(bdiv&0xff, UART0_BASE + UART_DLL);	/* set baudrate divisor */
@@ -160,7 +163,7 @@
 }
 
 
-void serial_putc (const char c)
+void serial_putc(const char c)
 {
 	int i;
 
@@ -169,31 +172,38 @@
 
 	/* check THRE bit, wait for transmiter available */
 	for (i = 1; i < 3500; i++) {
-		if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20)
+		if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20) {
 			break;
-		udelay (100);
+		}
+		udelay(100);
 	}
 	outb(c, UART0_BASE + UART_THR);	/* put character out */
 }
 
 
-void serial_puts (const char *s)
+void serial_puts(const char *s)
 {
 	while (*s) {
-		serial_putc (*s++);
+		serial_putc(*s++);
 	}
 }
 
 
-int serial_getc ()
+int serial_getc(void)
 {
 	unsigned char status = 0;
 
+#if CONFIG_SERIAL_SOFTWARE_FIFO
+	if (serial_buffer_active) {
+		return serial_buffered_getc();
+	}
+#endif
+	
 	while (1) {
 #if defined(CONFIG_HW_WATCHDOG)
-		WATCHDOG_RESET ();	/* Reset HW Watchdog, if needed */
+		WATCHDOG_RESET();	/* Reset HW Watchdog, if needed */
 #endif	/* CONFIG_HW_WATCHDOG */
-		status = inb (UART0_BASE + UART_LSR);
+		status = inb(UART0_BASE + UART_LSR);
 		if ((status & asyncLSRDataReady1) != 0x0) {
 			break;
 		}
@@ -211,11 +221,17 @@
 }
 
 
-int serial_tstc ()
+int serial_tstc(void)
 {
 	unsigned char status;
 
-	status = inb (UART0_BASE + UART_LSR);
+#if CONFIG_SERIAL_SOFTWARE_FIFO
+	if (serial_buffer_active) {
+		return serial_buffered_tstc();
+	}
+#endif
+
+	status = inb(UART0_BASE + UART_LSR);
 	if ((status & asyncLSRDataReady1) != 0x0) {
 		return (1);
 	}
@@ -234,36 +250,50 @@
 
 #if CONFIG_SERIAL_SOFTWARE_FIFO
 
-void serial_isr (void *arg)
+void serial_isr(void *arg)
 {
 	int space;
 	int c;
-	const int rx_get = buf_info.rx_get;
 	int rx_put = buf_info.rx_put;
 
-	if (rx_get <= rx_put) {
-		space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
+	if (buf_info.rx_get <= rx_put) {
+		space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - buf_info.rx_get);
 	} else {
-		space = rx_get - rx_put;
+		space = buf_info.rx_get - rx_put;
 	}
-	while (serial_tstc ()) {
-		c = serial_getc ();
+	
+	while (inb(UART0_BASE + UART_LSR) & 1) {
+		c = inb(UART0_BASE);
 		if (space) {
 			buf_info.rx_buffer[rx_put++] = c;
 			space--;
+			
+			if (rx_put == buf_info.rx_get) {
+				buf_info.rx_get++;
+				if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) {
+					buf_info.rx_get = 0;
+				}
+			}
+			
+			if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) {
+				rx_put = 0;
+				if (0 == buf_info.rx_get) {
+					buf_info.rx_get = 1;
+				}
+			
+			}
+			
 		}
-		if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO)
-			rx_put = 0;
 		if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
 			/* Stop flow by setting RTS inactive */
-			outb(inb (UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
+			outb(inb(UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
 			      UART0_BASE + UART_MCR);
 		}
 	}
 	buf_info.rx_put = rx_put;
 }
 
-void serial_buffered_init (void)
+void serial_buffered_init(void)
 {
 	serial_puts ("Switching to interrupt driven serial input mode.\n");
 	buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
@@ -272,8 +302,10 @@
 
 	if (inb (UART0_BASE + UART_MSR) & 0x10) {
 		serial_puts ("Check CTS signal present on serial port: OK.\n");
+		buf_info.cts = 1;
 	} else {
 		serial_puts ("WARNING: CTS signal not present on serial port.\n");
+		buf_info.cts = 0;
 	}
 
 	irq_install_handler ( VECNUM_U0 /*UART0 *//*int vec */ ,
@@ -283,32 +315,49 @@
 	/* Enable "RX Data Available" Interrupt on UART */
 	/* outb(inb(UART0_BASE + UART_IER) |0x01, UART0_BASE + UART_IER); */
 	outb(0x01, UART0_BASE + UART_IER);
-	/* Set DTR active */
-	outb(inb (UART0_BASE + UART_MCR) | 0x01, UART0_BASE + UART_MCR);
-	/* Start flow by setting RTS active */
-	outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR);
-	/* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */
-	outb((1 << 6) | 1, UART0_BASE + UART_FCR);
+	
+	/* Set DTR and RTS active, enable interrupts  */
+	outb(inb (UART0_BASE + UART_MCR) | 0x0b, UART0_BASE + UART_MCR);
+	
+	/* Setup UART FIFO: RX trigger level: 1 byte, Enable FIFO */
+	outb( /*(1 << 6) |*/  1, UART0_BASE + UART_FCR);
+	
+	serial_buffer_active = 1;
 }
 
 void serial_buffered_putc (const char c)
 {
+	int i;
 	/* Wait for CTS */
 #if defined(CONFIG_HW_WATCHDOG)
 	while (!(inb (UART0_BASE + UART_MSR) & 0x10))
 		WATCHDOG_RESET ();
 #else
-	while (!(inb (UART0_BASE + UART_MSR) & 0x10));
+	if (buf_info.cts)  {
+		for (i=0;i<1000;i++) {
+			if ((inb (UART0_BASE + UART_MSR) & 0x10)) {
+				break;
+			}
+		}
+		if (i!=1000) {
+			buf_info.cts = 0;
+		}
+	} else {
+		if ((inb (UART0_BASE + UART_MSR) & 0x10)) {
+			buf_info.cts = 1;
+		}
+	}
+		
 #endif
 	serial_putc (c);
 }
 
-void serial_buffered_puts (const char *s)
+void serial_buffered_puts(const char *s)
 {
 	serial_puts (s);
 }
 
-int serial_buffered_getc (void)
+int serial_buffered_getc(void)
 {
 	int space;
 	int c;
@@ -322,8 +371,9 @@
 	while (rx_get == buf_info.rx_put);
 #endif
 	c = buf_info.rx_buffer[rx_get++];
-	if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO)
+	if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO) {
 		rx_get = 0;
+	}
 	buf_info.rx_get = rx_get;
 
 	rx_put = buf_info.rx_put;
@@ -340,7 +390,7 @@
 	return c;
 }
 
-int serial_buffered_tstc (void)
+int serial_buffered_tstc(void)
 {
 	return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
 }
@@ -358,7 +408,7 @@
   configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE
 */
 #if (CONFIG_KGDB_SER_INDEX & 2)
-void kgdb_serial_init (void)
+void kgdb_serial_init(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
 
@@ -381,7 +431,7 @@
 }
 
 
-void putDebugChar (const char c)
+void putDebugChar(const char c)
 {
 	if (c == '\n')
 		serial_putc ('\r');
@@ -393,7 +443,7 @@
 }
 
 
-void putDebugStr (const char *s)
+void putDebugStr(const char *s)
 {
 	while (*s) {
 		serial_putc(*s++);
@@ -401,7 +451,7 @@
 }
 
 
-int getDebugChar (void)
+int getDebugChar(void)
 {
 	unsigned char status = 0;
 
@@ -424,34 +474,34 @@
 }
 
 
-void kgdb_interruptible (int yes)
+void kgdb_interruptible(int yes)
 {
 	return;
 }
 
 #else	/* ! (CONFIG_KGDB_SER_INDEX & 2) */
 
-void kgdb_serial_init (void)
+void kgdb_serial_init(void)
 {
 	serial_printf ("[on serial] ");
 }
 
-void putDebugChar (int c)
+void putDebugChar(int c)
 {
 	serial_putc (c);
 }
 
-void putDebugStr (const char *str)
+void putDebugStr(const char *str)
 {
 	serial_puts (str);
 }
 
-int getDebugChar (void)
+int getDebugChar(void)
 {
 	return serial_getc ();
 }
 
-void kgdb_interruptible (int yes)
+void kgdb_interruptible(int yes)
 {
 	return;
 }
diff -urN -x CVS u-boot/doc/TODO-i386 u-boot-i386/doc/TODO-i386
--- u-boot/doc/TODO-i386	Mon Nov 18 01:14:45 2002
+++ u-boot-i386/doc/TODO-i386	Mon Apr 28 10:22:41 2003
@@ -4,14 +4,14 @@
 * setup the BIOS data area and BIOS equipment word to reflect machine config. 
 * Make reset work (from Linux and from the boot prompt)
 * DMA, FDC, RTC, KBC initialization
-* video card support (call BIOS to initialize, use helper routrine in BSP to shadow 
-  video rom if on pci) and PC keyboard
 * split of part of cpu/i386/interrupt.c to cpu/i385/entry.c?
 * re-entry of protected mode from real mode, should be added to realmode_switch.S 
   (and used by INT 10h and INT 16h handlers for console I/O during early
    linux boot...) 
 * missing functions in lib_i386 and cpu/i386
 * speaker beep interface
+* (FIXED) video card support (call BIOS to initialize, use helper routrine in BSP to shadow 
+  video rom if on pci) and PC keyboard
 
 i386 port bugs:
 * IDE does not work 
@@ -36,4 +36,4 @@
 * is it possible to make both the internal serial ports and the 
   ports on the sio work at the same time?
 * ali sio cio lines?
-* On-borad ethernet does not work from Linux
+* FIXED (interrupt issue) On-borad ethernet does not work from Linux 
diff -urN -x CVS u-boot/examples/82559_eeprom.c u-boot-i386/examples/82559_eeprom.c
--- u-boot/examples/82559_eeprom.c	Thu Jan  1 01:00:00 1970
+++ u-boot-i386/examples/82559_eeprom.c	Tue Apr 22 13:24:34 2003
@@ -0,0 +1,354 @@
+
+/*
+ * Copyright 1998-2001 by Donald Becker.
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ * Contact the author for use under other terms.
+ *
+ * This program must be compiled with "-O"!
+ * See the bottom of this file for the suggested compile-command.
+ *
+ * The author may be reached as becker@scyld.com, or C/O
+ *  Scyld Computing Corporation
+ *  410 Severn Ave., Suite 210
+ *  Annapolis MD 21403
+ *
+ * Common-sense licensing statement: Using any portion of this program in
+ * your own program means that you must give credit to the original author
+ * and release the resulting code under the GPL.
+ */
+
+#define _PPC_STRING_H_		/* avoid unnecessary str/mem functions */
+#define _LINUX_STRING_H_	/* avoid unnecessary str/mem functions */
+
+#include <common.h>
+#include <syscall.h>
+#include <asm/io.h>
+
+
+/* Default EEPROM for i82559 */
+static unsigned short default_eeprom[64] = {
+	0x0100, 0x0302, 0x0504, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xffff, 0xffff, 0x40c0, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
+};
+
+static unsigned short eeprom[256];
+
+static int eeprom_size = 64;
+static int eeprom_addr_size = 6;
+
+static int debug = 0;
+
+static inline unsigned short swap16(unsigned short x)
+{
+	return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
+}
+
+
+static inline void *memcpy(void *dst, const void *src, unsigned int len)
+{
+	void * ret = dst;
+	while (len-- > 0) *((char *)dst)++ = *((char *)src)++;
+	return ret;
+}
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD	(5)
+#define EE_READ_CMD		(6)
+#define EE_ERASE_CMD	(7)
+
+/* Serial EEPROM section. */
+#define EE_SHIFT_CLK	0x01	/* EEPROM shift clock. */
+#define EE_CS			0x02	/* EEPROM chip select. */
+#define EE_DATA_WRITE	0x04	/* EEPROM chip data in. */
+#define EE_DATA_READ	0x08	/* EEPROM chip data out. */
+#define EE_ENB			(0x4800 | EE_CS)
+#define EE_WRITE_0		0x4802
+#define EE_WRITE_1		0x4806
+#define EE_OFFSET		14
+
+/* Delay between EEPROM clock transitions. */
+#define eeprom_delay(ee_addr)	inw(ee_addr)
+
+/* Wait for the EEPROM to finish the previous operation. */
+static int eeprom_busy_poll(long ee_ioaddr)
+{
+	int i;
+	outw(EE_ENB, ee_ioaddr);
+	for (i = 0; i < 10000; i++)			/* Typical 2000 ticks */
+		if (inw(ee_ioaddr) & EE_DATA_READ)
+			break;
+	return i;
+}
+
+/* This executes a generic EEPROM command, typically a write or write enable.
+   It returns the data output from the EEPROM, and thus may also be used for
+   reads. */
+static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
+{
+	unsigned retval = 0;
+	long ee_addr = ioaddr + EE_OFFSET;
+
+	if (debug > 1)
+		mon_printf(" EEPROM op 0x%x: ", cmd);
+
+	outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
+
+	/* Shift the command bits out. */
+	do {
+		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
+		outw(dataval, ee_addr);
+		eeprom_delay(ee_addr);
+		if (debug > 2)
+			mon_printf("%X", inw(ee_addr) & 15);
+		outw(dataval | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay(ee_addr);
+		retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
+	} while (--cmd_len >= 0);
+#if 0
+	outw(EE_ENB, ee_addr);
+#endif
+	/* Terminate the EEPROM access. */
+	outw(EE_ENB & ~EE_CS, ee_addr);
+	if (debug > 1)
+		mon_printf(" EEPROM result is 0x%5.5x.\n", retval);
+	return retval;
+}
+
+static int read_eeprom(long ioaddr, int location, int addr_len)
+{
+	return do_eeprom_cmd(ioaddr, ((EE_READ_CMD << addr_len) | location)
+		<< 16 , 3 + addr_len + 16) & 0xffff;
+}
+
+static void write_eeprom(long ioaddr, int index, int value, int addr_len)
+{
+	long ee_ioaddr = ioaddr + EE_OFFSET;
+	int i;
+
+	/* Poll for previous op finished. */
+	eeprom_busy_poll(ee_ioaddr);			/* Typical 0 ticks */
+	/* Enable programming modes. */
+	do_eeprom_cmd(ioaddr, (0x4f << (addr_len-4)), 3 + addr_len);
+	/* Do the actual write. */
+	do_eeprom_cmd(ioaddr,
+				  (((EE_WRITE_CMD<<addr_len) | index)<<16) | (value & 0xffff),
+				  3 + addr_len + 16);
+	/* Poll for write finished. */
+	i = eeprom_busy_poll(ee_ioaddr);			/* Typical 2000 ticks */
+	if (debug)
+		mon_printf(" Write finished after %d ticks.\n", i);
+	/* Disable programming. This command is not instantaneous, so we check
+	   for busy before the next op. */
+	do_eeprom_cmd(ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
+	eeprom_busy_poll(ee_ioaddr);
+}
+
+static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr)
+{
+	unsigned short checksum = 0;
+	int size_test;
+	int i;
+
+	mon_printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr);
+
+	size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27);
+	eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6;
+	eeprom_size = 1 << eeprom_addr_size;
+
+	memcpy(eeprom, default_eeprom, sizeof default_eeprom);
+
+	for (i = 0; i < 3; i++)
+		eeprom[i] = (hwaddr[i*2+1]<<8) + hwaddr[i*2];
+
+	/* Recalculate the checksum. */
+	for (i = 0; i < eeprom_size - 1; i++)
+		checksum += eeprom[i];
+	eeprom[i] = 0xBABA - checksum;
+
+	for (i = 0; i < eeprom_size; i++)
+		write_eeprom(ioaddr, i, eeprom[i], eeprom_addr_size);
+
+	for (i = 0; i < eeprom_size; i++)
+		if (read_eeprom(ioaddr, i, eeprom_addr_size) != eeprom[i]) {
+			mon_printf("failed\n");
+			return 1;
+		}
+
+	mon_printf("done\n");
+	return 0;
+}
+
+static unsigned int hatoi(char *p, char **errp)
+{
+	unsigned int res = 0;
+	
+	while (1) {
+		switch (*p) {
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+			res |= (*p - 'a' + 10);
+			break;
+		case 'A':
+		case 'B':
+		case 'C':
+		case 'D':
+		case 'E':
+		case 'F':
+			res |= (*p - 'A' + 10);
+			break;
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			res |= (*p - '0');
+			break;		
+		default:
+			if (errp) {
+				*errp = p;
+			}
+		return res;
+		}
+		p++;
+		if (*p == 0) {
+			break;
+		}
+		res <<= 4;
+	}
+	
+	if (errp) {
+		*errp = NULL;
+	}
+	
+	return res;
+}
+
+static unsigned char *gethwaddr(char *in, unsigned char *out)
+{
+	char tmp[3];
+	int i;
+	char *err;
+	
+	for (i=0;i<6;i++) {
+		if (in[i*3+2] == 0 && i == 5) {
+			out[i] = hatoi(&in[i*3], &err);
+			if (err) {
+				return NULL;
+			}
+		} else if (in[i*3+2] == ':' && i < 5) {
+			tmp[0] = in[i*3];
+			tmp[1] = in[i*3+1];
+			tmp[2] = 0;
+			out[i] = hatoi(tmp, &err);
+			if (err) {
+				return NULL;
+			}
+		} else {
+			return NULL;
+		}		
+	}
+	
+	return out;
+}
+
+static u32
+read_config_dword(int bus, int dev, int func, int reg)
+{									 
+	u32 res;
+	
+	outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
+	     0xcf8);
+	res = inl(0xcfc);
+	outl(0, 0xcf8); 
+	return res; 
+}
+
+static u16
+read_config_word(int bus, int dev, int func, int reg)
+{									 
+	u32 res;
+	
+	outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
+	     0xcf8);
+	res = inw(0xcfc + (reg & 2));
+	outl(0, 0xcf8); 
+	return res; 
+}
+
+static void
+write_config_word(int bus, int dev, int func, int reg, u16 data)
+{									 
+	
+	outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
+	     0xcf8);
+	outw(data, 0xcfc + (reg & 2));
+	outl(0, 0xcf8); 
+}
+
+
+
+int main (int argc, char *argv[])
+{
+	unsigned char *eth_addr;
+	char buf[6];
+	int instance;
+	
+	if (argc != 2) {
+		mon_printf ("call with base Ethernet address\n");
+		return 1;
+	}
+	
+	
+	eth_addr = gethwaddr(argv[1], buf);
+	if (NULL == eth_addr) {
+		mon_printf ("Can not parse ethernet address\n");
+		return 1;
+	}
+	if (eth_addr[5] & 0x01) {
+		mon_printf("Base Ethernet address must be even\n");
+	}
+		
+	
+	for (instance = 0; instance < 2; instance ++)  {
+		unsigned int io_addr;
+		unsigned char mac[6];
+		int bar1 = read_config_dword(0, 6+instance, 0, 0x14);
+		if (! (bar1 & 1)) {
+			mon_printf("ETH%d is disabled %x\n", instance, bar1);
+		} else {
+			mon_printf("ETH%d IO=0x%04x\n", instance, bar1 & ~3);
+		}
+		io_addr = (bar1 & (~3L));
+		
+		
+		write_config_word(0, 6+instance, 0, 4, 
+				  read_config_word(0, 6+instance, 0, 4) | 1);
+		mon_printf("ETH%d CMD %04x\n", instance,
+			   read_config_word(0, 6+instance, 0, 4));
+		
+		memcpy(mac, eth_addr, 6);
+		mac[5] += instance;
+		
+		mon_printf("got io=%04x, ha=%02x:%02x:%02x:%02x:%02x:%02x\n",
+			   io_addr, mac[0], mac[1], mac[2], 
+			   mac[3], mac[4], mac[5]); 
+		reset_eeprom(io_addr, mac);
+	}
+	return 0;
+}
diff -urN -x CVS u-boot/examples/Makefile u-boot-i386/examples/Makefile
--- u-boot/examples/Makefile	Sat Apr  5 02:54:04 2003
+++ u-boot-i386/examples/Makefile	Mon Apr 28 11:19:11 2003
@@ -1,4 +1,3 @@
-#
 # (C) Copyright 2000
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
@@ -28,6 +27,12 @@
 SREC	= hello_world.srec
 BIN	= hello_world.bin
 
+ifeq ($(ARCH),i386)
+CRT0    = crt0.o
+SREC   += 82559_eeprom.srec
+BIN    += 82559_eeprom.bin
+endif
+
 ifeq ($(ARCH),ppc)
 SREC   += sched.srec
 BIN    += sched.bin
@@ -70,11 +75,11 @@
 all:	.depend $(LIB) $(SREC) $(BIN)
 
 #########################################################################
-$(LIB): .depend $(LIBOBJS)
+$(LIB): .depend $(LIBOBJS) $(CRT0)
 	$(AR) crv $@ $(LIBOBJS)
 
 %.srec:	%.o $(LIB)
-	$(LD) -g -Ttext $(LOAD_ADDR) -o $(<:.o=) -e $(<:.o=) $< $(LIB)
+	$(LD) -g -Ttext $(LOAD_ADDR) -o $(<:.o=) -e start $(CRT0) $< $(LIB)
 	$(OBJCOPY) -O srec $(<:.o=) $@
 
 %.bin:	%.srec
diff -urN -x CVS u-boot/examples/crt0.S u-boot-i386/examples/crt0.S
--- u-boot/examples/crt0.S	Thu Jan  1 01:00:00 1970
+++ u-boot-i386/examples/crt0.S	Tue Apr 15 09:42:49 2003
@@ -0,0 +1,12 @@
+.text
+.globl start
+start:
+        movl   4(%esp), %eax
+        movl   8(%esp), %ebx
+	pushl %ebx
+	pushl %eax
+	call main
+	addl $8, %esp
+	ret
+
+
diff -urN -x CVS u-boot/include/asm-i386/bitops.h u-boot-i386/include/asm-i386/bitops.h
--- u-boot/include/asm-i386/bitops.h	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/include/asm-i386/bitops.h	Fri Nov 22 10:04:07 2002
@@ -5,7 +5,6 @@
  * Copyright 1992, Linus Torvalds.
  */
 
-#include <linux/config.h>
 
 /*
  * These have to be done with inline assembly: that way the bit-setting
diff -urN -x CVS u-boot/include/asm-i386/byteorder.h u-boot-i386/include/asm-i386/byteorder.h
--- u-boot/include/asm-i386/byteorder.h	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/include/asm-i386/byteorder.h	Fri Nov 22 10:05:02 2002
@@ -5,10 +5,6 @@
 
 #ifdef __GNUC__
 
-/* For avoiding bswap on i386 */
-#ifdef __KERNEL__
-#include <linux/config.h>
-#endif
 
 static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
 {
diff -urN -x CVS u-boot/include/asm-i386/ic/sc520.h u-boot-i386/include/asm-i386/ic/sc520.h
--- u-boot/include/asm-i386/ic/sc520.h	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/include/asm-i386/ic/sc520.h	Wed Apr 30 10:33:18 2003
@@ -116,6 +116,11 @@
 #define SC520_UART2CTL		0x0cc4	        /* UART 2 General Control Register */
 #define SC520_UART2STA		0x0cc5	        /* UART 2 General Status Register */
 #define SC520_UART2FCRSHAD	0x0cc6	        /* UART 2 FIFO Control Shadow Register */
+#define SC520_SSICTL            0x0cd0          /* SSI Control */
+#define SC520_SSIXMIT           0x0cd1          /* SSI Transmit */
+#define SC520_SSICMD            0x0cd2          /* SSI Command */
+#define SC520_SSISTA            0x0cd3          /* SSI Status */
+#define SC520_SSIRCV            0x0cd4          /* SSI Receive */
 #define SC520_PICICR		0x0d00		/* Interrupt Control Register */
 #define SC520_MPICMODE		0x0d02		/* Master PIC Interrupt Mode Register */
 #define SC520_SL1PICMODE	0x0d03		/* Slave 1 PIC Interrupt Mode Register */
@@ -195,9 +200,31 @@
 
 /* MMCR Register bits (not all of them :) ) */
 
+/* SSI Stuff */
+#define CTL_CLK_SEL_4           0x00           /* Nominal Bit Rate = 8 MHz    */
+#define CTL_CLK_SEL_8           0x10           /* Nominal Bit Rate = 4 MHz    */
+#define CTL_CLK_SEL_16          0x20           /* Nominal Bit Rate = 2 MHz    */
+#define CTL_CLK_SEL_32          0x30           /* Nominal Bit Rate = 1 MHz    */
+#define CTL_CLK_SEL_64          0x40           /* Nominal Bit Rate = 512 KHz  */
+#define CTL_CLK_SEL_128         0x50           /* Nominal Bit Rate = 256 KHz  */
+#define CTL_CLK_SEL_256         0x60           /* Nominal Bit Rate = 128 KHz  */
+#define CTL_CLK_SEL_512         0x70           /* Nominal Bit Rate = 64 KHz   */
+
+#define TC_INT_ENB              0x08           /* Transaction Complete Interrupt Enable */
+#define PHS_INV_ENB             0x04           /* SSI Inverted Phase Mode Enable */
+#define CLK_INV_ENB    	        0x02           /* SSI Inverted Clock Mode Enable */
+#define MSBF_ENB      	        0x01           /* SSI Most Significant Bit First Mode Enable */
+
+#define SSICMD_CMD_SEL_XMITRCV  0x03           /* Simultaneous Transmit / Receive Transaction */
+#define SSICMD_CMD_SEL_RCV      0x02           /* Receive Transaction */
+#define SSICMD_CMD_SEL_XMIT     0x01           /* Transmit Transaction */
+#define SSISTA_BSY              0x02           /* SSI Busy */
+#define SSISTA_TC_INT           0x01           /* SSI Transaction Complete Interrupt */
+
+
 /* BITS for SC520_ADDDECCTL: */
 #define WPV_INT_ENB		0x80		/* Write-Protect Violation Interrupt Enable */
-#define IO_HOLE_DEST		0x10		/* I/O Hole Access Destination */
+#define IO_HOLE_DEST_PCI	0x10		/* I/O Hole Access Destination */
 #define RTC_DIS			0x04		/* RTC Disable */
 #define UART2_DIS		0x02		/* UART2 Disable */
 #define UART1_DIS		0x01		/* UART1 Disable */
@@ -215,25 +242,64 @@
 #define SC520_ISA_IO_BUS	0x00000000
 #define SC520_ISA_IO_SIZE	0x00001000
 
-/* PCI I/O space from 0x1000 to 0xfdff */
+/* PCI I/O space from 0x1000 to 0xdfff 
+ * (make 0xe000-0xfdff available for stuff like PCCard boot) */
 #define SC520_PCI_IO_PHYS	0x00001000
 #define SC520_PCI_IO_BUS	0x00001000
-#define SC520_PCI_IO_SIZE	0x0000ee00
+#define SC520_PCI_IO_SIZE	0x0000d000
 
 /* system memory from 0x00000000 to 0x0fffffff */
 #define	SC520_PCI_MEMORY_PHYS	0x00000000
 #define	SC520_PCI_MEMORY_BUS	0x00000000
 #define SC520_PCI_MEMORY_SIZE	0x10000000
 
-/* PCI bus memory from 0x10000000 to 0x27ffffff */
+/* PCI bus memory from 0x10000000 to 0x26ffffff 
+ * (make 0x27000000 - 0x27ffffff available for stuff like PCCard boot) */
 #define SC520_PCI_MEM_PHYS	0x10000000
 #define SC520_PCI_MEM_BUS       0x10000000
-#define SC520_PCI_MEM_SIZE	0x18000000
+#define SC520_PCI_MEM_SIZE	0x17000000
 
 /* 0x28000000 - 0x3fffffff is used by the flash banks */
 
 /* 0x40000000 - 0xffffffff is not adressable by the SC520 */
 
+/* priority numbers used for interrupt channel mappings */
+#define SC520_IRQ_DISABLED 0
+#define SC520_IRQ0  1
+#define SC520_IRQ1  2
+#define SC520_IRQ2  4  /* same as IRQ9 */
+#define SC520_IRQ3  11
+#define SC520_IRQ4  12
+#define SC520_IRQ5  13
+#define SC520_IRQ6  21
+#define SC520_IRQ7  22
+#define SC520_IRQ8  3
+#define SC520_IRQ9  4
+#define SC520_IRQ10 5 
+#define SC520_IRQ11 6
+#define SC520_IRQ12 7
+#define SC520_IRQ13 8
+#define SC520_IRQ14 9
+#define SC520_IRQ15 10
+
+
+/* pin number used for PCI interrupt mappings */
+#define SC520_PCI_INTA 0
+#define SC520_PCI_INTB 1
+#define SC520_PCI_INTC 2
+#define SC520_PCI_INTD 3
+#define SC520_PCI_GPIRQ0 4
+#define SC520_PCI_GPIRQ1 5
+#define SC520_PCI_GPIRQ2 6
+#define SC520_PCI_GPIRQ3 7
+#define SC520_PCI_GPIRQ4 8
+#define SC520_PCI_GPIRQ5 9
+#define SC520_PCI_GPIRQ6 10
+#define SC520_PCI_GPIRQ7 11
+#define SC520_PCI_GPIRQ8 12
+#define SC520_PCI_GPIRQ9 13
+#define SC520_PCI_GPIRQ10 14
+
 /* utility functions */
 void write_mmcr_byte(u16 mmcr, u8 data);
 void write_mmcr_word(u16 mmcr, u16 data);
@@ -242,8 +308,11 @@
 u16 read_mmcr_word(u16 mmcr);
 u32 read_mmcr_long(u16 mmcr);
 
+extern int sc520_pci_ints[];
+
 void init_sc520(void);
 unsigned long init_sc520_dram(void);
 void pci_sc520_init(struct pci_controller *hose);
+int pci_sc520_set_irq(int pci_pin, int irq);
 
 #endif
diff -urN -x CVS u-boot/include/asm-i386/io.h u-boot-i386/include/asm-i386/io.h
--- u-boot/include/asm-i386/io.h	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/include/asm-i386/io.h	Fri Nov 22 09:37:57 2002
@@ -1,8 +1,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
-
 /*
  * This file contains the definitions for the x86 IO instructions
  * inb/inw/inl/outb/outw/outl and the "string versions" of the same
diff -urN -x CVS u-boot/include/asm-i386/pci.h u-boot-i386/include/asm-i386/pci.h
--- u-boot/include/asm-i386/pci.h	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/include/asm-i386/pci.h	Fri Nov 29 11:03:49 2002
@@ -27,5 +27,11 @@
 #define _PCI_I386_H_	1
 
 void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data);
+int pci_enable_legacy_video_ports(struct pci_controller* hose);
+int pci_shadow_rom(pci_dev_t dev, unsigned char *dest);
+void pci_remove_rom_window(struct pci_controller* hose, u32 addr);
+u32 pci_get_rom_window(struct pci_controller* hose, int size);
+
+
 
 #endif
diff -urN -x CVS u-boot/include/asm-i386/realmode.h u-boot-i386/include/asm-i386/realmode.h
--- u-boot/include/asm-i386/realmode.h	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/include/asm-i386/realmode.h	Wed Nov 20 14:16:00 2002
@@ -27,5 +27,6 @@
 
 int bios_setup(void);
 int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out);
+int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out);
 
 #endif
diff -urN -x CVS u-boot/include/asm-i386/u-boot-i386.h u-boot-i386/include/asm-i386/u-boot-i386.h
--- u-boot/include/asm-i386/u-boot-i386.h	Wed Mar 12 11:41:10 2003
+++ u-boot-i386/include/asm-i386/u-boot-i386.h	Fri Nov 22 09:35:52 2002
@@ -46,8 +46,15 @@
 int timer_init(void);
 
 /* board/.../... */
-int	board_init(void);
-int	dram_init (void);
+int board_init(void);
+int dram_init(void);
+
+void isa_unmap_rom(u32 addr);
+u32 isa_map_rom(u32 bus_addr, int size);
+
+/* lib_i386/... */
+int video_bios_init(void);
+int video_init(void);
 
 
 #endif	/* _U_BOOT_I386_H_ */
diff -urN -x CVS u-boot/include/asm-i386/u-boot.h u-boot-i386/include/asm-i386/u-boot.h
--- u-boot/include/asm-i386/u-boot.h	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/include/asm-i386/u-boot.h	Tue Apr 15 09:47:31 2003
@@ -43,7 +43,8 @@
 	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps */
 	unsigned long	bi_intfreq;	/* Internal Freq, in MHz */
 	unsigned long	bi_busfreq;	/* Bus Freq, in MHz */
-	unsigned long	bi_baudrate;	/* Console Baudrate */
+	unsigned int	bi_baudrate;	/* Console Baudrate */
+	unsigned long   bi_boot_params;	/* where this board expects params */
 	struct environment_s	       *bi_env;
 	struct				/* RAM configuration */
 	{ 
diff -urN -x CVS u-boot/lib_i386/Makefile u-boot-i386/lib_i386/Makefile
--- u-boot/lib_i386/Makefile	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/lib_i386/Makefile	Wed Nov 20 15:04:11 2002
@@ -25,10 +25,10 @@
 
 LIB	= lib$(ARCH).a
 
-AOBJS	= bios.o realmode_switch.o ic/sc520_asm.o
+AOBJS	= bios.o bios_pci.o realmode_switch.o ic/sc520_asm.o
 
 COBJS	= board.o bios_setup.o i386_linux.o zimage.o realmode.o \
-	  pci_type1.o ic/sc520.o ic/ali512x.o
+	  pci_type1.o pci.o video_bios.o video.o ic/sc520.o ic/ali512x.o
 
 OBJS	= $(AOBJS) $(COBJS)
 
diff -urN -x CVS u-boot/lib_i386/bios.S u-boot-i386/lib_i386/bios.S
--- u-boot/lib_i386/bios.S	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/lib_i386/bios.S	Wed Dec  4 16:42:36 2002
@@ -30,6 +30,8 @@
  *----------------------------------------------------------------------
  */
 
+#include "bios.h"
+
 /*
  * During it's initialization phase, before switching to protected
  * mode, the Linux Kernel makes a few BIOS calls. This won't work
@@ -40,29 +42,13 @@
  * a general purpose replacement for a real BIOS !!
  */
 
-#define OFFS_ES      0
-#define OFFS_GS      2
-#define OFFS_DS      4
-#define OFFS_DI      6
-#define OFFS_SI      8
-#define OFFS_BP      10
-#define OFFS_SP      12
-#define OFFS_BX      14
-#define OFFS_DX      16
-#define OFFS_CX      18
-#define OFFS_AX      20
-#define OFFS_VECTOR  22
-#define OFFS_IP      24
-#define OFFS_CS      26
-#define OFFS_FLAGS   28
-
-#define SEGMENT      0x40
-#define STACK	     0x800  			/* stack at 0x40:0x800 -> 0x800 */
 
 .section .bios, "ax"
 .code16
 .org 0
-
+      	/* a call to f000:0 should warmboot */
+	jmp	realmode_reset
+	
 .globl rm_int00
 rm_int00:
 	pushw	$0
@@ -202,30 +188,23 @@
 	 * stack.
 	 */
 any_interrupt16:
-	pusha					/* save general registers */
-	pushw	%ds				/* save some segments     */
-	pushw	%gs
-	pushw	%es
-	pushw	%ss				/* save callers stack segment .. */
-	popw	%gs				/* ... in gs */
-	movw	$SEGMENT,%ax			/* setup my segments */
-	movw	%ax,%ds
-	movw	%ax,%es
-	movw	%ax,%ss
-	movw	%sp,%bp
-	movw	$STACK,%sp			/* setup BIOS stackpointer */
+        MAKE_BIOS_STACK
 
 gs	movw	OFFS_VECTOR(%bp), %ax
 	cmpw	$0x10, %ax
 	je	Lint_10h         
 	cmpw	$0x11, %ax
 	je	Lint_11h
+	cmpw	$0x12, %ax
+	je	Lint_12h
 	cmpw	$0x13, %ax
 	je	Lint_13h
 	cmpw	$0x15, %ax
 	je	Lint_15h
 	cmpw	$0x16, %ax
 	je	Lint_16h
+	cmpw	$0x1a, %ax
+	je	Lint_1ah
 	movw	$0xffff, %ax
 	jmp	Lout
 Lint_10h:					/* VGA BIOS services */
@@ -234,6 +213,9 @@
 Lint_11h:	
 	call	bios_11h
 	jmp	Lout
+Lint_12h:	
+	call	bios_12h
+	jmp	Lout
 Lint_13h:					/* BIOS disk services */
 	call	bios_13h
 	jmp	Lout
@@ -243,6 +225,9 @@
 Lint_16h:					/* keyboard services */
 	call	bios_16h
 	jmp	Lout
+Lint_1ah:					/* PCI bios */
+	call	bios_1ah
+	jmp	Lout
 Lout:	
 	cmpw	$0, %ax
 	je	Lhandeled
@@ -256,16 +241,7 @@
 	 * we shuls make int 0x10 and int 0x16 work as well))
 	 */
 Lhandeled:
-
-	pushw	%gs				/* restore callers stack segment */
-	popw	%ss
-	movw	%bp,%sp				/* restore stackpointer */
-
-	popw	%es				/* restore segment selectors */
-	popw	%gs
-	popw	%ds
-	
-	popa					/* restore GP registers */
+	RESTORE_CALLERS_STACK
 	addw	$2,%sp				/* dump vector number */
 	iret					/* return from interrupt */
 
@@ -309,7 +285,7 @@
  */
 
 bios_11h:
-	movw	bios_equipment, %ax
+cs	movw	bios_equipment, %ax
 gs	movw	%ax, OFFS_AX(%bp)  
 	xorw	%ax, %ax
 	ret
@@ -317,6 +293,30 @@
 
 /*
  ************************************************************
+ * BIOS 	interrupt 12h -- Get Memory Size
+ ************************************************************
+ */
+bios_12h:
+cs	movw	ram_in_64kb_chunks, %ax
+	cmpw	$0xa, %ax
+	ja	b12_more_than_640k
+	shlw	$6, %ax
+	jmp	b12_return
+b12_more_than_640k:
+	movw	$0x280, %ax
+b12_return:
+gs	movw	%ax, OFFS_AX(%bp)		/* return number of kilobytes in ax */
+
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ************************************************************
  * BIOS interrupt 13h -- Disk services
  ************************************************************
  */
@@ -372,27 +372,28 @@
 	ret
 	
 Lfunc_e801h:					/* Get memory size for >64M Configurations */
-	movw	$ram_in_64kb_chunks, %ax
-	cmpw	$256, %ax
-	ja	Lmore_than_16mb
-	shlw	$6, %ax				/* multiply by 64 */	
-gs	movw	%ax, OFFS_AX(%bp)   		/* return memory size in 1kb chunks in AX and CX */
+cs	movw	ram_in_64kb_chunks, %ax
+	cmpw	$0x100, %ax
+	ja	e801_more_than_16mb
+	shlw	$6, %ax				/* multiply by 64 */
+	subw	$0x400, %ax			/* 1st meg does not count */
+ 	
+gs	movw	%ax, OFFS_AX(%bp)   		/* return memory size between 1M and 16M in 1kb chunks in AX and CX */
 gs	movw	%ax, OFFS_CX(%bp)
-	xorw	%ax, %ax
-gs	movw	%ax, OFFS_BX(%bp)		/* set BX and DX to 0*/
-gs	movw	%ax, OFFS_DX(%bp)	
+gs	movw	$0, OFFS_BX(%bp)		/* set BX and DX to 0*/
+gs	movw	$0, OFFS_DX(%bp)	
 gs	movw	OFFS_FLAGS(%bp), %ax
 	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
 gs	movw	%ax, OFFS_FLAGS(%bp)
 	xorw	%ax, %ax
 	ret
 	
-Lmore_than_16mb:
+e801_more_than_16mb:
 	subw	$0x100, %ax			/* subtract 16MB */	
 	
-gs	movw	$0x3c00, OFFS_AX(%bp)		/* return 0x3c00 (16MB-384k) in AX and CX */
+gs	movw	$0x3c00, OFFS_AX(%bp)		/* return 0x3c00 (16MB-1MB) in AX and CX */
 gs	movw	$0x3c00, OFFS_CX(%bp)
-gs	movw	%ax, OFFS_BX(%bp)		/* set BX and DX to number of 64kb chunks - 256 */
+gs	movw	%ax, OFFS_BX(%bp)		/* set BX and DX to number of 64kb chunks above 16MB */
 gs	movw	%ax, OFFS_DX(%bp)	
 
 gs	movw	OFFS_FLAGS(%bp), %ax
@@ -402,11 +403,15 @@
 	ret
 
 Lfunc_88h:
-	movw	ram_in_64kb_chunks, %ax
-	subw	$16, %ax
+cs	movw	ram_in_64kb_chunks, %ax
+	cmpw	$0x100, %ax
+	jna	b88_not_more_than16
+	movw	$0x100, %ax
+b88_not_more_than16:
 	shlw	$6, %ax
-	
-gs	movw	%ax, OFFS_AX(%bp)		/* return number of kilobytes in ax */
+	subw	$0x400, %ax			/* 1st meg does not count */
+		
+gs	movw	%ax, OFFS_AX(%bp)		/* return number of kilobytes between 16MB and 16MB in ax */
 
 gs	movw	OFFS_FLAGS(%bp), %ax
 	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
@@ -429,6 +434,22 @@
 	movw	$0xffff, %ax
 	ret
 Lfunc_03h:
+	xorw	%ax, %ax			/* do nothing -- function not supported */
+	ret
+
+/*
+ ************************************************************
+ * BIOS interrupt 1ah -- PCI bios
+ ************************************************************
+ */
+bios_1ah:
+gs	movw	OFFS_AX(%bp), %ax
+	cmpb	$0xb1, %ah
+	je	Lfunc_b1h
+	movw	$0xffff, %ax
+	ret
+Lfunc_b1h:
+	call	realmode_pci_bios
 	xorw	%ax, %ax			/* do nothing -- function not supported */
 	ret
 
diff -urN -x CVS u-boot/lib_i386/bios.h u-boot-i386/lib_i386/bios.h
--- u-boot/lib_i386/bios.h	Thu Jan  1 01:00:00 1970
+++ u-boot-i386/lib_i386/bios.h	Thu Nov 21 14:04:35 2002
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engstr?m, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#ifndef _BIOS_H_
+#define _BIOS_H_
+
+#define OFFS_ES      0     /* 16bit */
+#define OFFS_GS      2     /* 16bit */
+#define OFFS_DS      4     /* 16bit */
+#define OFFS_EDI     6     /* 32bit */
+#define OFFS_DI      6     /* low 16 bits of EDI */   
+#define OFFS_ESI     10    /* 32bit */
+#define OFFS_SI      10    /* low 16 bits of ESI */   
+#define OFFS_EBP     14    /* 32bit */
+#define OFFS_BP      14    /* low 16 bits of EBP */
+#define OFFS_ESP     18    /* 32bit */
+#define OFFS_SP      18    /* low 16 bits of ESP */
+#define OFFS_EBX     22    /* 32bit */
+#define OFFS_BX      22    /* low 16 bits of EBX */
+#define OFFS_BL      22    /* low  8 bits of BX */
+#define OFFS_BH      23    /* high 8 bits of BX */
+#define OFFS_EDX     26    /* 32bit */
+#define OFFS_DX      26    /* low 16 bits of EBX */
+#define OFFS_DL      26    /* low  8 bits of BX */
+#define OFFS_DH      27    /* high 8 bits of BX */
+#define OFFS_ECX     30    /* 32bit */
+#define OFFS_CX      30    /* low 16 bits of EBX */
+#define OFFS_CL      30    /* low  8 bits of BX */
+#define OFFS_CH      31    /* high 8 bits of BX */
+#define OFFS_EAX     34    /* 32bit */
+#define OFFS_AX      34    /* low 16 bits of EBX */
+#define OFFS_AL      34    /* low  8 bits of BX */
+#define OFFS_AH      35    /* high 8 bits of BX */
+#define OFFS_VECTOR  38    /* 16bit */
+#define OFFS_IP      40    /* 16bit */
+#define OFFS_CS      42    /* 16bit */
+#define OFFS_FLAGS   44    /* 16bit */   
+
+#define SEGMENT      0x40
+#define STACK	     0x800  			/* stack at 0x40:0x800 -> 0x800 */
+
+/* save general registers */
+/* save some segments     */
+/* save callers stack segment .. */
+/* ... in gs */
+	/* setup my segments */ 
+	/* setup BIOS stackpointer */ 
+	
+#define MAKE_BIOS_STACK \
+	pushal		; \
+	pushw	%ds	; \
+	pushw	%gs	; \
+	pushw	%es	; \
+	pushw	%ss	; \
+	popw	%gs	; \
+	movw	$SEGMENT,%ax ; \
+	movw	%ax,%ds	; \
+	movw	%ax,%es	; \
+	movw	%ax,%ss	; \
+	movw	%sp,%bp	; \
+	movw	$STACK,%sp
+
+#define RESTORE_CALLERS_STACK \
+	pushw	%gs     ;			/* restore callers stack segment */ \
+	popw	%ss     ; \
+	movw	%bp,%sp	;			/* restore stackpointer */ \
+		\
+	popw	%es	;			/* restore segment selectors */ \
+	popw	%gs     ; \
+	popw	%ds     ; \
+		\
+	popal					/* restore GP registers */ 
+
+#endif
diff -urN -x CVS u-boot/lib_i386/bios_pci.S u-boot-i386/lib_i386/bios_pci.S
--- u-boot/lib_i386/bios_pci.S	Thu Jan  1 01:00:00 1970
+++ u-boot-i386/lib_i386/bios_pci.S	Wed Nov 20 14:16:00 2002
@@ -0,0 +1,411 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engstr?m, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * x86 realmode assembly implementation of a PCI BIOS
+ * for platforms that use one PCI hose and configuration 
+ * access type 1. (The common case for low-end PC's)
+ */
+ 
+#include "bios.h"
+
+#define PCI_BIOS_DEBUG
+
+.section .bios, "ax"
+.code16
+.globl realmode_pci_bios_call_entry
+realmode_pci_bios_call_entry:
+	MAKE_BIOS_STACK
+	call realmode_pci_bios
+	RESTORE_CALLERS_STACK
+	ret
+	
+	
+.globl realmode_pci_bios
+realmode_pci_bios:
+gs	movw	OFFS_AX(%bp), %ax
+	cmpb	$1, %al
+	je	pci_bios_present
+	cmpb	$2, %al
+	je	pci_bios_find_device
+	cmpb	$3, %al
+	je	pci_bios_find_class
+	cmpb	$6, %al
+	je	pci_bios_generate_special_cycle
+	cmpb	$8, %al
+	je	pci_bios_read_cfg_byte
+	cmpb	$9, %al
+	je	pci_bios_read_cfg_word
+	cmpb	$10, %al
+	je	pci_bios_read_cfg_dword
+	cmpb	$11, %al
+	je	pci_bios_write_cfg_byte
+	cmpb	$12, %al
+	je	pci_bios_write_cfg_word
+	cmpb	$13, %al
+	je	pci_bios_write_cfg_dword
+	cmpb	$14, %al
+	je	pci_bios_get_irq_routing
+	cmpb	$15, %al
+	je	pci_bios_set_irq
+	jmp	unknown_function
+	
+/*****************************************************************************/
+
+pci_bios_present:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_present
+#endif
+	movl	$0x20494350, %eax
+gs	movl	%eax, OFFS_EDX(%bp)	
+	movb	$0x01, %al
+gs	movb	%al, OFFS_AL(%bp)	/* We support cfg type 1 */ 
+	movw	$0x0210, %ax            /* version 2.10 */	
+gs	movw	%ax, OFFS_BX(%bp)	
+cs	movb	pci_last_bus, %al       /* last bus number */
+gs	movb	%al, OFFS_CL(%bp)	
+	jmp 	clear_carry
+
+/*****************************************************************************/
+
+/* device 0-31, function 0-7 */
+pci_bios_find_device:	
+#ifdef PCI_BIOS_DEBUG
+cs	incl 	num_pci_bios_find_device
+#endif
+gs	movw	OFFS_CX(%bp), %di 
+	shll	$16, %edi
+gs	movw	OFFS_DX(%bp), %di       /* edi now holds device in upper 16 
+                                         * bits and vendor in lower 16 bits */
+gs	movw	OFFS_SI(%bp), %si 	
+	xorw	%bx, %bx                /* start at bus 0 dev 0 function 0 */
+pfd_loop:	
+	xorw	%ax, %ax		/* dword 0 is vendor/device */	
+	call	__pci_bios_select_register		
+	movw	$0xcfc, %dx
+	inl	%dx, %eax
+	cmpl	%edi, %eax		/* our device ? */
+	je	pfd_found_one
+pfd_next_dev:
+	/* check for multi function devices */
+	movw	%bx, %ax
+	andw	$3, %ax
+	jnz	pfd_function_not_zero
+	movw	$0x000c, %ax	
+	call	__pci_bios_select_register		
+	movw	$0xcfe, %dx
+	inb	%dx, %al
+	andb	$0x80, %al
+	jz	pfd_not_multi_function
+pfd_function_not_zero:
+	incw	%bx			/* next function, overflows in to
+					 * device number, then bus number */
+	jmp	pfd_check_bus
+	
+pfd_not_multi_function:
+	andw	$0xfff8, %bx            /* remove function bits */
+	addw	$0x0008, %bx            /* next device, overflows in to bus number */
+pfd_check_bus:	
+cs	movb	pci_last_bus, %ah
+	cmpb	%ah, %bh
+	ja	pfd_not_found
+	jmp	pfd_loop
+pfd_found_one:
+	decw	%si
+	js	pfd_done
+	jmp	pfd_next_dev
+
+pfd_done:
+gs	movw	%bx, OFFS_BX(%bp) 
+	jmp	clear_carry
+
+pfd_not_found:
+	movb	$0x86, %ah              /* device not found */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+pci_bios_find_class:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_find_class
+#endif
+gs	movl	OFFS_ECX(%bp), %edi 
+	andl	$0x00ffffff, %edi       /* edi now holds class-code in lower 24 bits */ 
+gs	movw	OFFS_SI(%bp), %si 	
+	xorw	%bx, %bx                /* start at bus 0 dev 0 function 0 */
+pfc_loop:	
+	movw	$8, %ax			/* dword 8 is class-code high 24bits */	
+	call	__pci_bios_select_register		
+	movw	$0xcfc, %dx
+	inl	%dx, %eax
+	shrl	$8, %eax
+	andl	$0x00ffffff, %eax
+	cmpl	%edi, %eax		/* our device ? */
+	je	pfc_found_one
+pfc_next_dev:
+	/* check for multi function devices */
+	andw	$3, %bx
+	jnz	pfc_function_not_zero
+	movw	$0x000c, %ax	
+	call	__pci_bios_select_register		
+	movw	$0xcfe, %dx
+	inb	%dx, %al
+	andb	$0x80, %al
+	jz	pfc_not_multi_function
+pfc_function_not_zero:
+	incw	%bx			/* next function, overflows in to
+					 * device number, then bus number */
+	jmp	pfc_check_bus
+	
+pfc_not_multi_function:
+	andw	$0xfff8, %bx            /* remove function bits */
+	addw	$0x0008, %bx            /* next device, overflows in to bus number */
+pfc_check_bus:	
+cs	movb	pci_last_bus, %ah
+	cmpb	%ah, %bh
+	ja	pfc_not_found
+	jmp	pfc_loop
+pfc_found_one:
+	decw	%si
+	js	pfc_done
+	jmp	pfc_next_dev
+
+pfc_done:
+gs	movw	%bx, OFFS_BX(%bp) 
+	jmp	clear_carry
+
+pfc_not_found:
+	movb	$0x86, %ah              /* device not found */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+pci_bios_generate_special_cycle:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_generate_special_cycle
+#endif
+	movb	$0x81, %ah              /* function not supported */
+	jmp	set_carry
+	
+/*****************************************************************************/
+
+pci_bios_read_cfg_byte: 
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_read_cfg_byte
+#endif
+	call	pci_bios_select_register	
+gs	movw 	OFFS_DI(%bp), %dx
+	andw	$3, %dx
+	addw	$0xcfc, %dx
+	inb	%dx, %al
+gs	movb	%al, OFFS_CL(%bp)	   
+	jmp 	clear_carry
+
+/*****************************************************************************/
+
+pci_bios_read_cfg_word: 
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_read_cfg_word
+#endif
+	call	pci_bios_select_register
+gs	movw 	OFFS_DI(%bp), %dx
+	andw	$2, %dx
+	addw	$0xcfc, %dx
+	inw	%dx, %ax
+gs	movw	%ax, OFFS_CX(%bp)	   
+	jmp 	clear_carry
+
+
+/*****************************************************************************/
+
+pci_bios_read_cfg_dword: 
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_read_cfg_dword
+#endif
+	call	pci_bios_select_register
+	movw	$0xcfc, %dx
+	inl	%dx, %eax
+gs	movl	%eax, OFFS_ECX(%bp)	    
+	jmp 	clear_carry
+
+/*****************************************************************************/
+
+pci_bios_write_cfg_byte:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_write_cfg_byte
+#endif
+	call	pci_bios_select_register	
+gs	movw 	OFFS_DI(%bp), %dx
+gs	movb	OFFS_CL(%bp), %al
+	andw	$3, %dx
+	addw	$0xcfc, %dx
+	outb	%al, %dx
+	jmp 	clear_carry
+	
+/*****************************************************************************/
+
+pci_bios_write_cfg_word:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_write_cfg_word
+#endif
+	call	pci_bios_select_register	
+gs	movw 	OFFS_DI(%bp), %dx
+gs	movw	OFFS_CX(%bp), %ax
+	andw	$2, %dx
+	addw	$0xcfc, %dx
+	outw	%ax, %dx
+	jmp 	clear_carry
+	
+/*****************************************************************************/
+
+pci_bios_write_cfg_dword:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_write_cfg_dword
+#endif
+	call	pci_bios_select_register	
+gs	movl	OFFS_ECX(%bp), %eax
+	movw	$0xcfc, %dx
+	outl	%eax, %dx
+	jmp 	clear_carry
+
+/*****************************************************************************/
+
+pci_bios_get_irq_routing:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_get_irq_routing
+#endif
+	movb	$0x81, %ah              /* function not supported */
+	jmp	set_carry
+	
+/*****************************************************************************/
+
+pci_bios_set_irq:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_set_irq
+#endif
+	movb	$0x81, %ah              /* function not supported */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+unknown_function:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_unknown_function
+#endif
+	movb	$0x81, %ah              /* function not supported */
+	jmp	set_carry
+
+/*****************************************************************************/
+		
+pci_bios_select_register:
+gs	movw 	OFFS_BX(%bp), %bx
+gs	movw 	OFFS_DI(%bp), %ax
+/* destroys eax, dx */
+__pci_bios_select_register:               /* BX holds device id, AX holds register index */
+	pushl	%ebx
+	andl	$0xfc, %eax
+	andl	$0xffff, %ebx
+	shll	$8, %ebx
+	orl	%ebx, %eax
+	orl	$0x80000000, %eax
+	movw	$0xcf8, %dx
+	outl	%eax, %dx
+	popl	%ebx
+	ret
+
+
+clear_carry:
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+gs	movb	%ah, OFFS_AH(%bp)	
+	ret
+
+set_carry:
+gs	movb	%ah, OFFS_AH(%bp)	
+gs	movw	OFFS_FLAGS(%bp), %ax
+	orw	$1, %ax				/* return carry -- function not supported */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	movw	$-1, %ax
+	ret
+
+/*****************************************************************************/
+
+.globl pci_last_bus
+pci_last_bus:
+	.byte 	0
+
+#ifdef PCI_BIOS_DEBUG
+.globl num_pci_bios_present
+num_pci_bios_present:
+	.long 	0
+	
+.globl num_pci_bios_find_device
+num_pci_bios_find_device:
+	.long 	0
+
+.globl num_pci_bios_find_class
+num_pci_bios_find_class:
+	.long 	0
+
+.globl num_pci_bios_generate_special_cycle
+num_pci_bios_generate_special_cycle: 
+	.long 0
+	
+.globl num_pci_bios_read_cfg_byte
+num_pci_bios_read_cfg_byte:
+	.long 	0
+
+.globl num_pci_bios_read_cfg_word
+num_pci_bios_read_cfg_word:
+	.long 	0
+
+.globl num_pci_bios_read_cfg_dword
+num_pci_bios_read_cfg_dword:
+	.long 	0
+
+.globl num_pci_bios_write_cfg_byte
+num_pci_bios_write_cfg_byte:
+	.long 	0
+
+.globl num_pci_bios_write_cfg_word
+num_pci_bios_write_cfg_word:
+	.long 	0
+
+.globl num_pci_bios_write_cfg_dword
+num_pci_bios_write_cfg_dword:
+	.long 	0
+
+.globl num_pci_bios_get_irq_routing
+num_pci_bios_get_irq_routing:
+	.long 	0
+
+.globl num_pci_bios_set_irq
+num_pci_bios_set_irq:
+	.long 	0
+
+.globl num_pci_bios_unknown_function
+num_pci_bios_unknown_function:
+	.long 	0
+#endif
diff -urN -x CVS u-boot/lib_i386/bios_setup.c u-boot-i386/lib_i386/bios_setup.c
--- u-boot/lib_i386/bios_setup.c	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/lib_i386/bios_setup.c	Wed Nov 20 14:16:00 2002
@@ -32,6 +32,7 @@
  */
 
 #include <common.h>
+#include <pci.h>
 #include <asm/realmode.h>
 #include <asm/io.h>
 
@@ -42,8 +43,13 @@
 #define BIOS_BASE        ((char*)0xf0000)
 #define BIOS_CS          0xf000
 
+/* these are defined in a 16bit segment and needs
+ * to be accessed with the RELOC_16_xxxx() macros below
+ */
 extern u16 ram_in_64kb_chunks;
 extern u16 bios_equipment;
+extern u8  pci_last_bus;
+
 extern void *rm_int00;
 extern void *rm_int01;
 extern void *rm_int02;
@@ -78,6 +84,34 @@
 extern void *rm_int1f;
 extern void *rm_def_int;
 
+extern void *realmode_reset;
+extern void *realmode_pci_bios_call_entry;
+
+static int set_jmp_vector(int entry_point, void *target) 
+{
+	if (entry_point & ~0xffff) {
+		return -1;
+	}
+	
+	if (((u32)target-0xf0000) & ~0xffff) {
+		return -1;
+	}
+	printf("set_jmp_vector: 0xf000:%04x -> %p\n",
+	       entry_point, target);
+	
+	/* jmp opcode */
+	writeb(0xea, 0xf0000 + entry_point);
+	
+	/* offset */
+	writew(((u32)target-0xf0000), 0xf0000 + entry_point + 1);
+	
+	/* segment */
+	writew(0xf000, 0xf0000 + entry_point + 3);
+	
+	return 0;
+}
+
+
 /*
  ************************************************************
  * Install an interrupt vector
@@ -96,11 +130,16 @@
 #endif	
 }
 
+#define RELOC_16_LONG(seg, off) *(u32*)(seg << 4 | (u32)&off) 
+#define RELOC_16_WORD(seg, off) *(u16*)(seg << 4 | (u32)&off) 
+#define RELOC_16_BYTE(seg, off) *(u8*)(seg << 4 | (u32)&off) 
+
 int bios_setup(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
 	static int done=0;	
 	int vector;
+	struct pci_controller *pri_hose;
 	
 	if (done) {
 		return 0;
@@ -169,9 +208,26 @@
 	setvector(0x1e, BIOS_CS, &rm_int1e);
 	setvector(0x1f, BIOS_CS, &rm_int1f);
 
+	set_jmp_vector(0xfff0, &realmode_reset);
+	set_jmp_vector(0xfe6e, &realmode_pci_bios_call_entry);
+	
 	/* fill in data area */
-	ram_in_64kb_chunks = gd->ram_size >> 16;
-	bios_equipment = 0; /* FixMe */
+	RELOC_16_WORD(0xf000, ram_in_64kb_chunks) = gd->ram_size >> 16;
+	RELOC_16_WORD(0xf000, bios_equipment) = 0; /* FixMe */
+	
+	/* If we assume only one PCI hose, this PCI hose
+	 * will own PCI bus #0, and the last PCI bus of 
+	 * that PCI hose will be the last PCI bus in the 
+	 * system. 
+	 * (This, ofcause break on multi hose systems,
+	 *  but our PCI BIOS only support one hose anyway) 
+	 */
+	pri_hose = pci_bus_to_hose(0);
+	if (NULL != pri_hose) {
+		/* fill in last pci bus number for use by the realmode 
+		 * PCI BIOS */
+		RELOC_16_BYTE(0xf000, pci_last_bus) = pri_hose->last_busno;
+	}
 	
 	return 0;
 }
diff -urN -x CVS u-boot/lib_i386/board.c u-boot-i386/lib_i386/board.c
--- u-boot/lib_i386/board.c	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/lib_i386/board.c	Wed Apr 30 11:24:37 2003
@@ -37,6 +37,7 @@
 #include <syscall.h>
 #include <net.h>
 #include <ide.h>
+#include <asm/u-boot-i386.h>
 
 extern long _i386boot_start;	    
 extern long _i386boot_end;	    
@@ -82,21 +83,14 @@
 {
 	DECLARE_GLOBAL_DATA_PTR;
         
-#if 1	
 	/* start malloc area right after the stack */
 	mem_malloc_start = i386boot_bss_start + 
 		i386boot_bss_size + CFG_STACK_SIZE;
 	mem_malloc_start = (mem_malloc_start+3)&~3;
-#else
-	mem_malloc_start = 0x400000;
-#endif	
-#if 1
+	
 	/* Use all available RAM for malloc() */
 	mem_malloc_end = gd->ram_size;
-#else	
-	/* Use only  CONFIG_MALLOC_SIZE bytes of RAM for malloc() */
-	mem_malloc_end = mem_malloc_start + CONFIG_MALLOC_SIZE;
-#endif	
+	
 	mem_malloc_brk = mem_malloc_start;
 
 	return 0;
@@ -323,7 +317,8 @@
 
 	/* allocate syscalls table (console_init_r will fill it in */
 	syscall_tbl = (void **) malloc (NR_SYSCALLS * sizeof (void *));
-
+	memset(syscall_tbl, 0, NR_SYSCALLS * sizeof (void *));
+	
 	/* Initialize the console (after the relocation and devices init) */
 	console_init_r();
 	syscalls_init();
@@ -355,7 +350,7 @@
 #endif
 
 	/* enable exceptions */
-	enable_interrupts ();
+	enable_interrupts();
 	show_boot_progress(0x28);
 
 	/* Must happen after interrupts are initialized since
@@ -369,7 +364,7 @@
 	status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
 #endif
 
-	udelay (20);
+	udelay(20);
 
 	set_timer (0);
 
@@ -399,7 +394,7 @@
 
 #if (CONFIG_COMMANDS & CFG_CMD_DOC)
 	WATCHDOG_RESET();
-	puts ("DOC:   ");
+	puts("DOC:   ");
 	doc_init();
 #endif
 
@@ -428,12 +423,13 @@
 		board_poweroff();
 	}
 #endif
-
+	
+	
 	show_boot_progress(0x29);
 	
 	/* main_loop() can return to retry autoboot, if so just run it again. */
 	for (;;) {
-		main_loop ();
+		main_loop();
 	}
 
 	/* NOTREACHED - no way out of command loop except booting */
diff -urN -x CVS u-boot/lib_i386/ic/sc520.c u-boot-i386/lib_i386/ic/sc520.c
--- u-boot/lib_i386/ic/sc520.c	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/lib_i386/ic/sc520.c	Fri Mar 28 08:48:28 2003
@@ -28,6 +28,7 @@
 #include <common.h>
 #include <config.h>
 #include <pci.h>
+#include <ssi.h>
 #include <asm/io.h>
 #include <asm/pci.h>
 #include <asm/ic/sc520.h>
@@ -235,6 +236,91 @@
 #ifdef CONFIG_PCI
 
 
+static struct {
+	u8 priority;
+	u16 level_reg;
+	u8 level_bit;
+} sc520_irq[] = {
+	{ SC520_IRQ0,  SC520_MPICMODE,  0x01 },
+	{ SC520_IRQ1,  SC520_MPICMODE,  0x02 },
+	{ SC520_IRQ2,  SC520_SL1PICMODE, 0x02 },
+	{ SC520_IRQ3,  SC520_MPICMODE,  0x08 },
+	{ SC520_IRQ4,  SC520_MPICMODE,  0x10 },
+	{ SC520_IRQ5,  SC520_MPICMODE,  0x20 },
+	{ SC520_IRQ6,  SC520_MPICMODE,  0x40 },
+	{ SC520_IRQ7,  SC520_MPICMODE,  0x80 },
+
+	{ SC520_IRQ8,  SC520_SL1PICMODE, 0x01 },
+	{ SC520_IRQ9,  SC520_SL1PICMODE, 0x02 },
+	{ SC520_IRQ10, SC520_SL1PICMODE, 0x04 },
+	{ SC520_IRQ11, SC520_SL1PICMODE, 0x08 },
+	{ SC520_IRQ12, SC520_SL1PICMODE, 0x10 },
+	{ SC520_IRQ13, SC520_SL1PICMODE, 0x20 },
+	{ SC520_IRQ14, SC520_SL1PICMODE, 0x40 },
+	{ SC520_IRQ15, SC520_SL1PICMODE, 0x80 }
+};
+
+
+/* The interrupt used for PCI INTA-INTD  */
+int sc520_pci_ints[15] = { 
+	-1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1
+};
+
+/* utility function to configure a pci interrupt */
+int pci_sc520_set_irq(int pci_pin, int irq) 
+{
+	int i;
+	
+# if 0
+	printf("set_irq(): map INT%c to IRQ%d\n", pci_pin + 'A', irq);
+#endif	
+	if (irq < 0 || irq > 15) {
+		return -1; /* illegal irq */
+	}
+
+	if (pci_pin < 0 || pci_pin > 15) {
+		return -1; /* illegal pci int pin */
+	}
+
+	/* first disable any non-pci interrupt source that use 
+	 * this level */
+	for (i=SC520_GPTMR0MAP;i<=SC520_GP10IMAP;i++) {
+		if (i>=SC520_PCIINTAMAP&&i<=SC520_PCIINTDMAP) {
+			continue;
+		}
+		if (read_mmcr_byte(i) == sc520_irq[irq].priority) {
+			write_mmcr_byte(i, SC520_IRQ_DISABLED);
+		}
+	}
+	
+	/* Set the trigger to level */
+	write_mmcr_byte(sc520_irq[irq].level_reg, 
+			read_mmcr_byte(sc520_irq[irq].level_reg) | sc520_irq[irq].level_bit);
+	
+	
+	if (pci_pin < 4) {
+		/* PCI INTA-INTD */
+		/* route the interrupt */
+		write_mmcr_byte(SC520_PCIINTAMAP + pci_pin, sc520_irq[irq].priority);
+		
+		
+	} else {
+		/* GPIRQ0-GPIRQ10 used for additional PCI INTS */
+		write_mmcr_byte(SC520_GP0IMAP + pci_pin - 4, sc520_irq[irq].priority);
+		
+		/* also set the polarity in this case */
+		write_mmcr_word(SC520_INTPINPOL, 
+				read_mmcr_word(SC520_INTPINPOL) | (1 << (pci_pin-4)));
+		
+	}
+	
+	/* register the pin */		
+	sc520_pci_ints[pci_pin] = irq;
+	
+
+	return 0; /* OK */
+}
 
 void pci_sc520_init(struct pci_controller *hose)
 {
@@ -293,6 +379,7 @@
 }
 
 
+
 #endif
 
 #ifdef CFG_TIMER_SC520
@@ -345,4 +432,67 @@
 
 #endif
 
+int ssi_set_interface(int freq, int lsb_first, int inv_clock, int inv_phase)
+{
+	u8 temp=0;
+
+	if (freq >= 8192) {
+		temp |= CTL_CLK_SEL_4; 
+	} else if (freq >= 4096) {
+		temp |= CTL_CLK_SEL_8;        
+	} else if (freq >= 2048) {
+		temp |= CTL_CLK_SEL_16;  
+	} else if (freq >= 1024) {
+		temp |= CTL_CLK_SEL_32;  
+	} else if (freq >= 512) {
+		temp |= CTL_CLK_SEL_64;
+	} else if (freq >= 256) {
+		temp |= CTL_CLK_SEL_128;
+	} else if (freq >= 128) {
+		temp |= CTL_CLK_SEL_256;
+	} else {
+		temp |= CTL_CLK_SEL_512;
+	}
+	
+	if (!lsb_first) {
+		temp |= MSBF_ENB;
+	}
+		
+	if (inv_clock) {
+		temp |= CLK_INV_ENB;
+	}
+	
+	if (inv_phase) {
+		temp |= PHS_INV_ENB;
+	}
+		
+	write_mmcr_byte(SC520_SSICTL, temp);
+	
+	return 0;
+}
+
+u8 ssi_txrx_byte(u8 data) 
+{
+	write_mmcr_byte(SC520_SSIXMIT, data);
+	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
+	write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_XMITRCV);
+	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
+	return read_mmcr_byte(SC520_SSIRCV);	
+}      
+
+
+void ssi_tx_byte(u8 data) 
+{
+	write_mmcr_byte(SC520_SSIXMIT, data);
+	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY); 
+	write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_XMIT);
+}
+
+u8 ssi_rx_byte(void) 
+{
+	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
+	write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_RCV);
+	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
+	return read_mmcr_byte(SC520_SSIRCV);
+} 
 
diff -urN -x CVS u-boot/lib_i386/pci.c u-boot-i386/lib_i386/pci.c
--- u-boot/lib_i386/pci.c	Thu Jan  1 01:00:00 1970
+++ u-boot-i386/lib_i386/pci.c	Wed Apr 30 12:50:49 2003
@@ -0,0 +1,156 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engstr?m, Omicron Ceti AB, daniel@omicron.se
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#include <common.h> 
+#include <pci.h> 
+#include <asm/io.h> 
+#include <asm/pci.h> 
+
+#ifdef CONFIG_PCI
+#undef PCI_ROM_SCAN_VERBOSE
+
+int pci_shadow_rom(pci_dev_t dev, unsigned char *dest) 
+{
+	struct pci_controller *hose;
+	int res = -1;
+	int i;
+	
+	u32 rom_addr;
+	u32 addr_reg;
+	u32 size;
+	
+	u16 vendor;
+	u16 device;
+	u32 class_code;
+
+	hose = pci_bus_to_hose(PCI_BUS(dev));
+#if 0
+	printf("pci_shadow_rom() asked to shadow device %x to %x\n",
+	       dev, (u32)dest);
+#endif	
+	pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+	pci_read_config_word(dev, PCI_DEVICE_ID, &device);
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_code);
+	
+ 	class_code &= 0xffffff00;
+	class_code >>= 8;
+
+#if 0	
+	printf("PCI Header Vendor %04x device %04x class %06x\n",
+	       vendor, device, class_code);
+#endif	
+	/* Enable the rom addess decoder */
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_MASK);
+	pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addr_reg);
+
+	if (!addr_reg) {
+		/* register unimplemented */
+		printf("pci_chadow_rom: device do not seem to have a rom\n");
+		return -1;
+	}
+	
+	size = (~(addr_reg&PCI_ROM_ADDRESS_MASK))+1;  
+	
+#if 0	
+	printf("ROM is %d bytes\n", size);
+#endif	
+	rom_addr = pci_get_rom_window(hose, size);
+#if 0	
+	printf("ROM mapped at %x \n", rom_addr);
+#endif	
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS, 
+			       pci_phys_to_mem(dev, rom_addr)
+			       |PCI_ROM_ADDRESS_ENABLE);
+
+
+	
+	for (i=rom_addr;i<rom_addr+size; i+=512) {
+		
+		
+		if (readw(i) == 0xaa55) {
+			u32 pci_data;
+#ifdef PCI_ROM_SCAN_VERBOSE
+			printf("ROM signature found\n");
+#endif			
+			pci_data = readw(0x18+i);
+			pci_data += i;
+			
+			if (0==memcmp((void*)pci_data, "PCIR", 4)) {
+#ifdef PCI_ROM_SCAN_VERBOSE				
+				printf("Fount PCI rom image at offset %d\n", i-rom_addr);
+				printf("Vendor %04x device %04x class %06x\n",
+				       readw(pci_data+4), readw(pci_data+6),
+				       readl(pci_data+0x0d)&0xffffff);
+				printf("%s\n", 
+				       (readw(pci_data+0x15) &0x80)?
+				       "Last image":"More images follow");
+				switch 	(readb(pci_data+0x14)) {
+				case 0:
+					printf("X86 code\n");
+					break;
+				case 1:
+					printf("Openfirmware code\n");
+					break;
+				case 2:
+					printf("PARISC code\n");
+					break;
+				}
+				printf("Image size %d\n", readw(pci_data+0x10) * 512);
+#endif				
+				/* FixMe: I think we should compare the class code
+				 * bytes as well but I have no reference on the
+				 * exact order of these bytes in the PCI ROM header */
+				if (readw(pci_data+4) == vendor && 
+				    readw(pci_data+6) == device &&
+				    /* (readl(pci_data+0x0d)&0xffffff) == class_code && */
+				    readb(pci_data+0x14) == 0 /* x86 code image */ ) {
+#ifdef PCI_ROM_SCAN_VERBOSE					
+					printf("Suitable ROM image found, copying\n");
+#endif					
+					memmove(dest, (void*)rom_addr, readw(pci_data+0x10) * 512);
+					res = 0;
+					break;
+					
+				}
+				if (readw(pci_data+0x15) &0x80) {
+					break;
+				}
+			}
+		}
+		
+	}
+	
+#ifdef PCI_ROM_SCAN_VERBOSE
+	if (res) {
+		printf("No suitable image found\n");
+	}
+#endif	
+	/* disable PAR register and PCI device ROM address devocer */
+	pci_remove_rom_window(hose, rom_addr);
+	  	
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+
+	return res;
+}
+
+#endif
diff -urN -x CVS u-boot/lib_i386/realmode.c u-boot-i386/lib_i386/realmode.c
--- u-boot/lib_i386/realmode.c	Fri Nov 22 00:11:52 2002
+++ u-boot-i386/lib_i386/realmode.c	Wed Apr 30 11:23:59 2003
@@ -33,25 +33,33 @@
 
 extern char realmode_enter;
 
-
-int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
+int realmode_setup(void)
 {
-	
-	/* setup out thin bios emulation */
-	if (bios_setup()) {
-		return -1;
-	}
-		
 	/* copy the realmode switch code */
 	if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
 		printf("realmode switch too large (%ld bytes, max is %d)\n", 
-		       i386boot_realmode_size, (int)(REALMODE_MAILBOX-REALMODE_BASE));
+		       i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE));
 		return -1;
 	}
 	
 	memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size);
+	asm("wbinvd\n");
+	
+	return 0;
+}
 		
+int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
+{
 	
+	/* setup out thin bios emulation */
+	if (bios_setup()) {
+		return -1;
+	}
+	
+	if (realmode_setup()) {
+		return -1;
+	}
+		       	
 	in->eip = off;
 	in->xcs = seg;
 	if (3>(in->esp & 0xffff)) {
@@ -59,12 +67,30 @@
 	}
 	
 	memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs));
+	asm("wbinvd\n");
 	
 	__asm__ volatile ( 
 		 "lcall $0x20,%0\n"  : :  "i" (&realmode_enter) );
 
+	asm("wbinvd\n");
 	memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs));
 
 	return out->eax;
+}
+
+
+/* This code is supposed to access a realmode interrupt
+ * it does currently not work for me */
+int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out)
+{
+	/* place two instructions at 0x700 */
+	writeb(0xcd, 0x700);  /* int $lvl */
+	writeb(lvl, 0x701);
+	writeb(0xcb, 0x702);  /* lret */
+	asm("wbinvd\n");
+      
+	enter_realmode(0x00, 0x700, in, out);	
+	
+	return out->eflags&1;
 }
 
diff -urN -x CVS u-boot/lib_i386/realmode_switch.S u-boot-i386/lib_i386/realmode_switch.S
--- u-boot/lib_i386/realmode_switch.S	Mon Nov 18 01:14:46 2002
+++ u-boot-i386/lib_i386/realmode_switch.S	Wed Nov 20 14:16:10 2002
@@ -50,7 +50,6 @@
 
 .section .realmode, "ax"
 .code16
-
 						/* 16bit protected mode code here */
 .globl realmode_enter
 realmode_enter:
diff -urN -x CVS u-boot/lib_i386/video.c u-boot-i386/lib_i386/video.c
--- u-boot/lib_i386/video.c	Thu Jan  1 01:00:00 1970
+++ u-boot-i386/lib_i386/video.c	Wed Apr 30 13:51:50 2003
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engstr?m, Omicron Ceti AB, daniel@omicron.se
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#include <common.h> 
+#include <pci.h> 
+#include <devices.h>
+#include <i8042.h>
+#include <asm/ptrace.h> 
+#include <asm/realmode.h> 
+#include <asm/io.h> 
+#include <asm/pci.h> 
+
+
+/* basic textmode I/O from linux kernel */
+static char *vidmem = (char *)0xb8000;
+static int vidport;
+static int lines, cols;
+static int orig_x, orig_y;
+
+static void scroll(void)
+{
+	int i;
+
+	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+		vidmem[i] = ' ';
+}
+
+static void __video_putc(const char c, int *x, int *y)
+{
+	if (c == '\n') {
+ 		(*x) = 0;
+		if ( ++(*y) >= lines ) {
+			scroll();
+			(*y)--;
+		}
+	} else if (c == '\b') { 
+		if ((*x) != 0) {
+			--(*x);
+			vidmem [ ( (*x) + cols * (*y) ) * 2 ] = ' '; 
+		}
+	} else if (c == '\r') { 
+		(*x) = 0;
+		
+	} else if (c == '\a') { 
+		(*x) = 0;
+	} else if (c == '\t') { 
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+	} else if (c == '\v') { 
+		switch ((*x) % 8) {
+		case 0:
+			__video_putc(' ', x, y);
+		case 7:
+			__video_putc(' ', x, y);
+		case 6:
+			__video_putc(' ', x, y);
+		case 5:
+			__video_putc(' ', x, y);
+		case 4:
+			__video_putc(' ', x, y);
+		case 3:
+			__video_putc(' ', x, y);
+		case 2:
+			__video_putc(' ', x, y);
+		case 1:
+			__video_putc(' ', x, y);
+		}
+	} else if (c == '\f') { 
+		int i;
+		for (i=0;i<lines*cols*2;i+=2) {
+			vidmem[i] = 0;
+		}
+		(*x) = 0;
+		(*y) = 0;
+	} else {
+		vidmem [ ( (*x) + cols * (*y) ) * 2 ] = c; 
+		if ( ++(*x) >= cols ) {
+			(*x) = 0;
+			if ( ++(*y) >= lines ) {
+				scroll();
+				(*y)--;
+			}
+		}
+	}
+}
+
+static void video_putc(const char c)
+{
+	int x,y,pos;
+	
+	x = orig_x;
+	y = orig_y;
+	
+	__video_putc(c, &x, &y);
+
+	orig_x = x;
+	orig_y = y;
+	
+	pos = (x + cols * y) * 2;	/* Update cursor position */
+	outb_p(14, vidport);
+	outb_p(0xff & (pos >> 9), vidport+1);
+	outb_p(15, vidport);
+	outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+static void video_puts(const char *s)
+{
+	int x,y,pos;
+	char c;
+
+	x = orig_x;
+	y = orig_y;
+
+	while ( ( c = *s++ ) != '\0' ) {
+		__video_putc(c, &x, &y);
+	}
+
+	orig_x = x;
+	orig_y = y;
+
+	pos = (x + cols * y) * 2;	/* Update cursor position */
+	outb_p(14, vidport);
+	outb_p(0xff & (pos >> 9), vidport+1);
+	outb_p(15, vidport);
+	outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+int video_init(void)
+{
+	u16 pos;
+	
+	static device_t vga_dev;
+	static device_t kbd_dev;
+	
+	vidmem = (char *) 0xb8000;
+	vidport = 0x3d4;
+
+	lines = 25;
+	cols = 80;
+	
+	outb_p(14, vidport);
+	pos = inb_p(vidport+1);
+	pos <<= 8;
+	outb_p(15, vidport);
+	pos |= inb_p(vidport+1);
+	
+	orig_x = pos%cols;
+	orig_y = pos/cols;
+
+#if 0	
+	printf("pos %x %d %d\n", pos, orig_x, orig_y);
+#endif	
+	if (orig_y > lines) {
+		orig_x = orig_y =0;
+	}
+	
+	
+	memset(&vga_dev, 0, sizeof(vga_dev));
+        strcpy(vga_dev.name, "vga");
+        vga_dev.ext   = 0; 
+        vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+        vga_dev.putc  = video_putc;        /* 'putc' function */
+        vga_dev.puts  = video_puts;        /* 'puts' function */
+        vga_dev.tstc  = NULL;              /* 'tstc' function */
+        vga_dev.getc  = NULL;              /* 'getc' function */
+
+        if (device_register(&vga_dev) == 0) {
+            return 1;
+	}
+	
+	if (i8042_kbd_init()) {
+		return 1;
+	}
+	
+	memset(&kbd_dev, 0, sizeof(kbd_dev));
+        strcpy(kbd_dev.name, "kbd");
+        kbd_dev.ext   = 0; 
+        kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+        kbd_dev.putc  = NULL;        /* 'putc' function */
+        kbd_dev.puts  = NULL;        /* 'puts' function */
+        kbd_dev.tstc  = i8042_tstc;  /* 'tstc' function */
+        kbd_dev.getc  = i8042_getc;  /* 'getc' function */
+
+        if (device_register(&kbd_dev) == 0) {
+            return 1;
+	}
+	return 0;
+}
+
+
+int drv_video_init(void) 
+{
+	if (video_bios_init()) {
+		return 1;
+	}
+	
+	return video_init();
+	
+}
+      
diff -urN -x CVS u-boot/lib_i386/video_bios.c u-boot-i386/lib_i386/video_bios.c
--- u-boot/lib_i386/video_bios.c	Thu Jan  1 01:00:00 1970
+++ u-boot-i386/lib_i386/video_bios.c	Wed Apr 30 12:56:20 2003
@@ -0,0 +1,221 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engstr?m, Omicron Ceti AB, daniel@omicron.se
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#include <common.h> 
+#include <pci.h> 
+#include <malloc.h> 
+#include <asm/ptrace.h> 
+#include <asm/realmode.h> 
+#include <asm/io.h> 
+#include <asm/pci.h> 
+
+#undef PCI_BIOS_DEBUG
+#undef VGA_BIOS_DEBUG
+
+#ifdef	VGA_BIOS_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#ifdef CONFIG_PCI
+
+#ifdef PCI_BIOS_DEBUG
+#define RELOC_16(seg, off) *(u32*)(seg << 4 | (u32)&off) 
+extern u32 num_pci_bios_present;
+extern u32 num_pci_bios_find_device;
+extern u32 num_pci_bios_find_class;
+extern u32 num_pci_bios_generate_special_cycle;
+extern u32 num_pci_bios_read_cfg_byte;
+extern u32 num_pci_bios_read_cfg_word;
+extern u32 num_pci_bios_read_cfg_dword;
+extern u32 num_pci_bios_write_cfg_byte;
+extern u32 num_pci_bios_write_cfg_word;
+extern u32 num_pci_bios_write_cfg_dword;
+extern u32 num_pci_bios_get_irq_routing;
+extern u32 num_pci_bios_set_irq;
+extern u32 num_pci_bios_unknown_function;
+
+void print_bios_bios_stat(void)
+{
+	printf("16 bit functions:\n");
+	printf("pci_bios_present:                %d\n", RELOC_16(0xf000, num_pci_bios_present));
+	printf("pci_bios_find_device:            %d\n", RELOC_16(0xf000, num_pci_bios_find_device));
+	printf("pci_bios_find_class:             %d\n", RELOC_16(0xf000, num_pci_bios_find_class));
+	printf("pci_bios_generate_special_cycle: %d\n", RELOC_16(0xf000, num_pci_bios_generate_special_cycle));	
+	printf("pci_bios_read_cfg_byte:          %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_byte));
+	printf("pci_bios_read_cfg_word:          %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_word));
+	printf("pci_bios_read_cfg_dword:         %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_dword));
+	printf("pci_bios_write_cfg_byte:         %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_byte));
+	printf("pci_bios_write_cfg_word:         %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_word));
+	printf("pci_bios_write_cfg_dword:        %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_dword));
+	printf("pci_bios_get_irq_routing:        %d\n", RELOC_16(0xf000, num_pci_bios_get_irq_routing));
+	printf("pci_bios_set_irq:                %d\n", RELOC_16(0xf000, num_pci_bios_set_irq));
+	printf("pci_bios_unknown_function:       %d\n", RELOC_16(0xf000, num_pci_bios_unknown_function));
+
+}
+#endif
+
+#define PCI_CLASS_VIDEO             3
+#define PCI_CLASS_VIDEO_STD         0
+#define PCI_CLASS_VIDEO_PROG_IF_VGA 0
+
+
+static u32 probe_pci_video(void)
+{
+	pci_dev_t devbusfn;
+	
+	if ((devbusfn = pci_find_class(PCI_CLASS_VIDEO, 
+				       PCI_CLASS_VIDEO_STD, 
+				       PCI_CLASS_VIDEO_PROG_IF_VGA, 0)) != -1) {
+		u32 old;
+		u32 addr;
+		
+		/* PCI video device detected */
+		printf("Found PCI VGA device at %02x.%02x.%x\n", 
+		       PCI_BUS(devbusfn), PCI_DEV(devbusfn), PCI_FUNC(devbusfn));
+		
+		/* Enable I/O decoding as well, PCI viudeo boards
+		 * support I/O accesses, but they provide no
+		 * bar register for this since the ports are fixed.
+		 */
+		pci_write_config_word(devbusfn, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
+		
+		/* Test the ROM decoder, do the device support a rom? */
+		pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &old);		
+		pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_MASK);
+		pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &addr);
+		pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, old);
+				
+		if (!addr) {
+			printf("PCI VGA have no ROM?\n");
+			return 0;
+		}
+		
+		/* device have a rom */
+		if (pci_shadow_rom(devbusfn, (void*)0xc0000)) { 
+			printf("Shadowing of PCI VGA BIOS failed\n");
+			return 0;
+		}
+		
+		/* Now enable lagacy VGA port access */
+		if (pci_enable_legacy_video_ports(pci_bus_to_hose(PCI_BUS(devbusfn)))) {
+			printf("PCI VGA enable failed\n");
+			return 0;
+		}
+				
+	
+		/* return the pci device info, that we'll need later */
+		return PCI_BUS(devbusfn) << 8 | 
+			PCI_DEV(devbusfn) << 3 | (PCI_FUNC(devbusfn)&7);
+	}
+	
+	return 0;
+}
+
+
+#endif
+
+static int probe_isa_video(void)
+{
+	u32 ptr;
+	char *buf;	
+	
+	if (0 == (ptr = isa_map_rom(0xc0000, 0x8000))) {
+		return -1;
+	}
+	if (NULL == (buf=malloc(0x8000))) {
+		isa_unmap_rom(ptr);
+		return -1;
+	}
+	if (readw(ptr) != 0xaa55) {
+		free(buf);
+		isa_unmap_rom(ptr);
+		return -1;
+	}
+	
+	/* shadow the rom */
+	memcpy(buf, (void*)ptr, 0x8000);
+	isa_unmap_rom(ptr);
+	memcpy((void*)0xc0000, buf, 0x8000);
+	
+	free(buf);
+	
+	return 0;
+}
+
+int video_bios_init(void)
+{
+	struct pt_regs regs;
+
+	/* clear the video bios area in case we warmbooted */
+	memset((void*)0xc0000, 0, 0x8000);	
+	memset(&regs, 0, sizeof(struct pt_regs));
+	
+	if (probe_isa_video()) {
+		/* No ISA board found, try the PCI bus */
+		regs.eax = probe_pci_video();
+	}
+	
+	/* Did we succeed in mapping any video bios */
+	if (readw(0xc0000) == 0xaa55) {
+	        int size;
+		int i;
+		u8 sum;
+		
+		PRINTF("Found video bios signature\n");
+		size = 512*readb(0xc0002);
+		PRINTF("size %d\n", size);
+		sum=0;
+		for (i=0;i<size;i++) {
+			sum += readb(0xc0000 + i);
+		}
+		PRINTF("Checksum is %sOK\n",sum?"NOT ":"");
+		if (sum) {
+			return 1;
+		}
+		
+		/* some video bioses (ATI Mach64) seem to think that
+		 * the original int 10 handler is always at
+		 * 0xf000:0xf065 , place an iret instruction there
+		 */
+		writeb(0xcf, 0xff065);
+		
+		regs.esp = 0x8000;
+		regs.xss = 0x2000;
+		enter_realmode(0xc000, 3, &regs, &regs);
+		PRINTF("INT 0x10 vector after:  %04x:%04x\n",
+		       readw(0x42), readw(0x40)); 
+		PRINTF("BIOS returned %scarry\n", regs.eflags & 1?"":"NOT ");
+#ifdef PCI_BIOS_DEBUG		
+		print_bios_bios_stat();
+#endif		
+		return (regs.eflags & 1);
+		
+	}
+	
+	return 1;
+	
+}
+
+
