Patchwork rommcc bugs

login
register
about
Submitter Rudolf Marek
Date 2010-06-16 21:28:03
Message ID <4C1941E3.8000605@assembler.cz>
Download mbox | patch
Permalink /patch/1517/
State Not Applicable
Headers show

Comments

Rudolf Marek - 2010-06-16 21:28:03
Ah sorry I forgot one more file. Now it should be better.

But yes I got same error.

Thanks,
Rudolf
Myles Watson - 2010-06-16 21:55:40
Sorry Rudolf, I forgot to copy the list.

It looks like romcc doesn't support unsigned char there.  I did this:

- outb(datxa, eth_nic_base + NE_ASIC_OFFSET + NE_DATA);
+ outb((char)datxa, eth_nic_base + NE_ASIC_OFFSET + NE_DATA);

And it compiles again.

Here's the code from romcc.c:

static struct triple *int_const(
	struct compile_state *state, struct type *type, ulong_t value)
{
	struct triple *result;
	switch(type->type & TYPE_MASK) {
	case TYPE_CHAR:
	case TYPE_INT:   case TYPE_UINT:
	case TYPE_LONG:  case TYPE_ULONG:
		break;
	default:
		internal_error(state, 0, "constant for unknown type");
	}
	result = triple(state, OP_INTCONST, type, 0, 0);
	result->u.cval = value;
	return result;
}

Thanks,
Myles
Rudolf Marek - 2010-06-16 22:03:05
Hm,

It does not work here. If i change it I still got

marekr2@kiur:~/dilna/coreboot$ make
     GEN        build.h
     ROMCC      romstage.inc
ne2k.c:83.0: warning:  "comment next line causes stuff to compile again"
ne2k.c:126.0: warning:  "Add timeout"
romstage.c:74.0:
Internal compiler error: constant for unknown type
make: *** [build/mainboard/soyo/sy-6ba-plus-iii/romstage.inc] Aborted

outb((char)datxa, eth_nic_base + NE_ASIC_OFFSET + NE_DATA);


this is how it looks now. Maybe you changed more?

Thanks,

Rudolf
Myles Watson - 2010-06-16 22:14:11
On Wed, Jun 16, 2010 at 4:03 PM, Rudolf Marek <r.marek@assembler.cz> wrote:
> Hm,
>
> It does not work here. If i change it I still got

You're right.  I added TYPE_UCHAR:

before:
       case TYPE_CHAR:
       case TYPE_INT:   case TYPE_UINT:

after:
       case TYPE_CHAR: case TYPE_UCHAR:
       case TYPE_INT:   case TYPE_UINT:

I don't know how safe that is, but it seems like it should work.  I
don't know the difference between constants that are unsigned or
signed characters.  In the past it's been better to work around romcc
than modify it unless Eric helps.

Sorry for the confusion.  I thought I changed it back before I tried it last.

Thanks,
Myles

Patch

Index: src/include/ip_checksum.h
===================================================================
--- src/include/ip_checksum.h	(revision 5631)
+++ src/include/ip_checksum.h	(working copy)
@@ -1,7 +1,10 @@ 
 #ifndef IP_CHECKSUM_H
 #define IP_CHECKSUM_H
 
+#ifndef __ROMCC__
 unsigned long compute_ip_checksum(void *addr, unsigned long length);
 unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new);
-
+void str2ip(const char *str, unsigned char *ip);
+void str2mac(const char *str, unsigned char *mac);
+#endif
 #endif /* IP_CHECKSUM_H */
Index: src/include/console/ne2k.h
===================================================================
--- src/include/console/ne2k.h	(revision 0)
+++ src/include/console/ne2k.h	(revision 0)
@@ -0,0 +1,27 @@ 
+#ifndef _NE2K_H__
+#define _NE2K_H__
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Rudolf Marek <r.marek@assembler.cz>
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef __ROMCC__
+void ne2k_append_data(unsigned char *d, int len, unsigned int base);
+int ne2k_init(unsigned int eth_nic_base);
+void ne2k_transmit(unsigned int eth_nic_base);
+#endif
+#endif /* _NE2K_H */
Index: src/include/console/console.h
===================================================================
--- src/include/console/console.h	(revision 5631)
+++ src/include/console/console.h	(working copy)
@@ -131,6 +131,10 @@ 
 
 #include <pc80/serial.c>
 
+#if CONFIG_CONSOLE_NE2K
+#include "lib/ne2k.c"
+#endif
+
 /* __ROMCC__ */
 static void __console_tx_byte(unsigned char byte)
 {
@@ -191,10 +195,18 @@ 
 	if (console_loglevel >= loglevel) {
 		unsigned char ch;
 		while((ch = *str++) != '\0') {
+#if CONFIG_CONSOLE_NE2K
+			unsigned char *ptr;
+			ptr = (unsigned char *) (str - 1);
+			ne2k_append_data(ptr, 1, CONFIG_CONSOLE_NE2K_IO_PORT);
+#endif
 			if (ch == '\n')
 				__console_tx_byte('\r');
 			__console_tx_byte(ch);
 		}
+#if CONFIG_CONSOLE_NE2K
+		ne2k_transmit(CONFIG_CONSOLE_NE2K_IO_PORT);
+#endif
 	}
 }
 
Index: src/mainboard/soyo/sy-6ba-plus-iii/romstage.c
===================================================================
--- src/mainboard/soyo/sy-6ba-plus-iii/romstage.c	(revision 5631)
+++ src/mainboard/soyo/sy-6ba-plus-iii/romstage.c	(working copy)
@@ -54,6 +54,8 @@ 
 
 	it8671f_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE);
 	uart_init();
+	//ne2k_init(CONFIG_CONSOLE_NE2K_IO_PORT);
+
 	console_init();
 	report_bist_failure(bist);
 
Index: src/mainboard/asus/p2b/romstage.c.orig
===================================================================
Index: src/mainboard/asus/p2b/acpi_tables.c
===================================================================
Index: src/mainboard/asus/p2b/dsdt.asl
===================================================================
Index: src/console/Kconfig
===================================================================
--- src/console/Kconfig	(revision 5631)
+++ src/console/Kconfig	(working copy)
@@ -1,5 +1,4 @@ 
 menu "Console options"
-
 # TODO: Rename to SERIAL_CONSOLE once Kconfig transition is complete.
 config CONSOLE_SERIAL8250
 	bool "Serial port console output"
@@ -130,6 +129,48 @@ 
 	help
 	  If not selected, the last adapter found will be used.
 
+config CONSOLE_NE2K
+	bool "Network console over NE2000 compatible Ethernet adapter"
+	default y
+	help
+	  Send coreboot debug output to a Ethernet console, it works
+	  same way as Linux netconsole, packets are received to UDP
+	  port 6666 on IP/MAC specified with options bellow.
+
+config CONSOLE_NE2K_DST_MAC
+	depends on CONSOLE_NE2K
+	string "Destination MAC address of remote system"
+	default "00:13:d4:76:a2:ac"
+	help
+	  Type in either MAC address of logging system or MAC address
+	  of the router.
+
+config CONSOLE_NE2K_DST_IP
+	depends on CONSOLE_NE2K
+	string "Destination IP of logging system"
+	default "10.0.1.27"
+	help
+	  This is IP adress of the system running for example
+	  netcat command to dump the packets.
+
+config CONSOLE_NE2K_SRC_IP
+	depends on CONSOLE_NE2K
+	string "IP adress of Coreboot system"
+	default "10.0.1.253"
+	help
+	  This is the IP of the Coreboot system
+
+config CONSOLE_NE2K_IO_PORT
+	depends on CONSOLE_NE2K
+	hex "NE2000 adapter fixed IO port address"
+	default 0xe00
+	help
+	  This is the IO port address for the IO port
+	  on the card, please select some non-conflicting region,
+	  32 bytes of IO spaces will be used (and align on 32 bytes
+	  boundary)
+
+
 choice
 	prompt "Maximum console log level"
 	default MAXIMUM_CONSOLE_LOGLEVEL_8
Index: src/console/ne2k_console.c
===================================================================
--- src/console/ne2k_console.c	(revision 0)
+++ src/console/ne2k_console.c	(revision 0)
@@ -0,0 +1,37 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, Inc.
+ * Copyright (C) 2010 Rudolf Marek <r.marek@assembler.cz>
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <console/ne2k.h>
+
+static void ne2k_tx_byte(unsigned char data)
+{
+	ne2k_append_data(&data, 1, CONFIG_CONSOLE_NE2K_IO_PORT);
+}
+
+static void ne2k_tx_flush(void)
+{
+	ne2k_transmit(CONFIG_CONSOLE_NE2K_IO_PORT);
+}
+
+static const struct console_driver ne2k_console __console = {
+	.tx_byte = ne2k_tx_byte,
+	.tx_flush = ne2k_tx_flush,
+};
Index: src/console/console.c
===================================================================
--- src/console/console.c	(revision 5631)
+++ src/console/console.c	(working copy)
@@ -7,11 +7,14 @@ 
 #include <arch/hlt.h>
 #include <arch/io.h>
 
+#if CONFIG_CONSOLE_NE2K
+#include <console/ne2k.h>
+#endif
+
 #ifndef __PRE_RAM__
 #include <string.h>
 #include <pc80/mc146818rtc.h>
 
-
 /* initialize the console */
 void console_init(void)
 {
@@ -99,6 +102,10 @@ 
 
 void console_init(void)
 {
+
+#if CONFIG_CONSOLE_NE2K
+	ne2k_init(CONFIG_CONSOLE_NE2K_IO_PORT);
+#endif
 	static const char console_test[] =
 		"\n\ncoreboot-"
 		COREBOOT_VERSION
Index: src/console/Makefile.inc
===================================================================
--- src/console/Makefile.inc	(revision 5631)
+++ src/console/Makefile.inc	(working copy)
@@ -15,6 +15,7 @@ 
 driver-$(CONFIG_CONSOLE_BTEXT) += btext_console.o
 driver-$(CONFIG_CONSOLE_BTEXT) += font-8x16.o
 driver-$(CONFIG_CONSOLE_LOGBUF) += logbuf_console.o
+driver-$(CONFIG_CONSOLE_NE2K) += ne2k_console.o
 
 $(obj)/console/console.o : $(obj)/build.h
 $(obj)/console/console.initobj.o : $(obj)/build.h
Index: src/lib/ne2k.c
===================================================================
--- src/lib/ne2k.c	(revision 0)
+++ src/lib/ne2k.c	(revision 0)
@@ -0,0 +1,473 @@ 
+/*
+ETHERBOOT -  BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters
+  Date: May/94
+
+ This code is based heavily on David Greenman's if_ed.c driver
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+  This software may be used, modified, copied, distributed, and sold, in
+  both source and binary form provided that the above copyright and these
+  terms are retained. Under no circumstances are the authors responsible for
+  the proper functioning of this software, nor do the authors assume any
+  responsibility for damages incurred with its use.
+
+Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
+Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
+3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
+SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
+3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
+RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
+  parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
+SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02
+  based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
+
+(C) Rudolf Marek <r.marek@assembler.cz> Simplify for RTL8029, Add coreboot glue logic
+
+*/
+
+#define ETH_ALEN		6	/* Size of Ethernet address */
+#define ETH_HLEN		14	/* Size of ethernet header */
+#define	ETH_ZLEN		60	/* Minimum packet */
+#define	ETH_FRAME_LEN		1514	/* Maximum packet */
+#define ETH_DATA_ALIGN		2	/* Amount needed to align the data after an ethernet header */
+#define	ETH_MAX_MTU		(ETH_FRAME_LEN-ETH_HLEN)
+
+#include "ns8390.h"
+#include <ip_checksum.h>
+#include <console/ne2k.h>
+#include <arch/io.h>
+//#include <arch/romcc_io.h>
+
+#define MEM_SIZE MEM_32768
+#define TX_START 64
+#define RX_START (64 + D8390_TXBUF_SIZE)
+
+static unsigned int get_count(unsigned int eth_nic_base) {
+	unsigned int ret;
+	outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1,
+	     eth_nic_base + D8390_P0_COMMAND);
+
+	ret = inb(eth_nic_base + 8 + 0) | (inb(eth_nic_base + 8 + 1) << 8);
+
+	outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0,
+	     eth_nic_base + D8390_P0_COMMAND);
+	return ret;
+}
+
+static void set_count(unsigned int eth_nic_base, unsigned int what) {
+	
+	outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1,
+	     eth_nic_base + D8390_P0_COMMAND);
+
+	outb(what & 0xff,eth_nic_base + 8);
+	outb((what >> 8) & 0xff,eth_nic_base + 8 + 1);
+
+	outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0,
+	     eth_nic_base + D8390_P0_COMMAND);
+	
+}
+void eth_pio_write_byte(unsigned char datxa,unsigned short dst,unsigned int eth_nic_base)
+{
+	outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);  
+	outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR); 
+	outb(1, eth_nic_base + D8390_P0_RBCR0);            
+	outb(0, eth_nic_base + D8390_P0_RBCR1);             
+                                                             
+	outb(dst, eth_nic_base + D8390_P0_RSAR0);             
+	outb(dst >> 8, eth_nic_base + D8390_P0_RSAR1);         
+                                                                       
+	outb(D8390_COMMAND_RD1 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND); 
+#warning "comment next line causes stuff to compile again"
+	outb(datxa, eth_nic_base + NE_ASIC_OFFSET + NE_DATA);
+       
+	while ((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) != D8390_ISR_RDC)   
+		;                                                                      
+
+}
+static unsigned char eth_pio_read_byte(unsigned int src,
+				unsigned int eth_nic_base) {
+
+	outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+	outb(0, eth_nic_base + D8390_P0_RBCR0);
+	outb(1, eth_nic_base + D8390_P0_RBCR1);
+
+	outb(src, eth_nic_base + D8390_P0_RSAR0);
+	outb(src >> 8, eth_nic_base + D8390_P0_RSAR1);
+
+	outb(D8390_COMMAND_RD0 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+	return inb(eth_nic_base + NE_ASIC_OFFSET + NE_DATA);
+}
+
+static void eth_pio_write(unsigned char *src, unsigned int dst, unsigned int cnt,
+				unsigned int eth_nic_base) {
+
+	outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+	outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
+
+	outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+
+	outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
+
+	outb(dst, eth_nic_base + D8390_P0_RSAR0);
+
+	outb(dst >> 8, eth_nic_base + D8390_P0_RSAR1);
+
+	outb(D8390_COMMAND_RD1 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+	while (cnt--) {
+			outb(*(src++), eth_nic_base + NE_ASIC_OFFSET + NE_DATA);
+	}
+
+#warning "Add timeout"
+	/* wait for operation finish */
+	while ((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) != D8390_ISR_RDC)
+		;
+}
+
+void ne2k_append_data(unsigned char *d, int len, unsigned int base) {
+	eth_pio_write(d, (TX_START << 8) + 42 + get_count(base), len, base);
+	set_count(base, get_count(base)+len);
+}
+
+#ifdef __ROMCC__
+/* varition of compute_ip_checksum which works on SRAM */
+unsigned long compute_ip_checksum_from_sram(unsigned short offset, unsigned short length,
+					unsigned int eth_nic_base)
+{
+	unsigned long sum;
+	unsigned long i;
+	/* In the most straight forward way possible,
+	 * compute an ip style checksum.
+	 */
+	sum = 0;
+	for(i = 0; i < length; i++) {
+		unsigned long v;
+		v = eth_pio_read_byte((TX_START << 8)+i, eth_nic_base);
+		if (i & 1) {
+			v <<= 8;
+		}
+		/* Add the new value */
+		sum += v;
+		/* Wrap around the carry */
+		if (sum > 0xFFFF) {
+			sum = (sum + (sum >> 16)) & 0xFFFF;
+		}
+	}
+	return   (~((sum & 0xff) | (sum >> 8) & 0xff)) & 0xffff;
+}
+
+
+void str2ip_load(const char *str, unsigned short offset, unsigned int eth_nic_base)
+#else
+void str2ip(const char *str, unsigned char *ip)
+#endif
+{
+	unsigned char c, i = 0;
+	unsigned char acc = 0;
+
+	do {
+		c = str[i];
+		if ((c >= '0') && (c <= '9')) {
+			acc *= 10;
+			acc += (c - '0');
+		} else {
+#ifdef __ROMCC__
+			eth_pio_write_byte(acc, (TX_START << 8)+offset, eth_nic_base);
+			offset++;
+#else
+			*ip++ = acc;
+#endif
+			acc = 0;
+		}
+		i++;
+	} while (c != '\0');
+}
+
+#ifdef __ROMCC__
+void str2mac_load(const char *str, unsigned short offset, unsigned int eth_nic_base)
+#else
+void str2mac(const char *str, unsigned char *mac)
+#endif
+{
+
+	unsigned char c, i = 0;
+	unsigned char acc = 0;
+	do {
+
+		c = str[i];
+		if ((c >= '0') && (c <= '9')) {
+			acc *= 16;
+			acc += (c - '0');
+		} else if ((c >= 'a') && (c <= 'f')) {
+			acc *= 16;
+			acc += ((c - 'a') + 10) ;
+		} if ((c >= 'A') && (c <= 'F')) {
+			acc *= 16;
+			acc += ((c - 'A') + 10) ;
+		} else {
+#ifdef __ROMCC__
+			eth_pio_write_byte(acc, ((TX_START << 8)+offset), eth_nic_base);
+			offset++;
+#else
+			*mac++ = acc;
+#endif
+			acc = 0;
+		}
+
+		i++;
+	} while (c != '\0');
+}
+
+
+#ifndef __ROMCC__
+static void ns8390_tx_header(unsigned int eth_nic_base, int pktlen) {
+	unsigned short chksum;
+	unsigned char hdr[] = {
+#else
+static const unsigned char hdr[] = {
+#endif
+		/*
+		 * ETHERNET HDR
+		 */
+
+		// destination macaddr
+		0x02, 0x00, 0x00, 0x00, 0x00, 0x01,
+		/* source mac */
+		0x02, 0x00, 0x00, 0xC0, 0xFF, 0xEE, 
+		/* ethtype (IP) */
+		0x08, 0x00,
+		/* 
+		 * IP HDR 
+		 */
+		0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 
+		/* TTL, proto (UDP), chksum_hi, chksum_lo, IP0, IP1, IP2, IP3, */
+		0x40, 0x11, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x1,
+		/* IP0, IP1, IP2, IP3  */
+		0xff, 0xff, 0xff, 0xff,
+		/*
+		 * UDP HDR
+		 */
+		/*  SRC PORT DST PORT  (2bytes each), ulen, uchksum (must be zero or correct */
+		0x1a, 0x0b, 0x1a, 0x0a, 0x00, 0x9, 0x00, 0x00, 
+	};
+	
+#ifndef __ROMCC__
+	str2mac(CONFIG_CONSOLE_NE2K_DST_MAC,  &hdr[0]);
+	str2ip(CONFIG_CONSOLE_NE2K_DST_IP, &hdr[30]);
+	str2ip(CONFIG_CONSOLE_NE2K_SRC_IP, &hdr[26]);
+
+	/* zero checksum */
+	hdr[24] = 0;
+	hdr[25] = 0;
+
+	/* update IP packet len */
+	hdr[16] = ((28 + pktlen) >> 8) & 0xff;
+	hdr[17] = (28 + pktlen) & 0xff;
+
+	/* update UDP len */
+	hdr[38] = (8 + pktlen) >> 8;
+	hdr[39] = 8 + pktlen;
+
+	chksum = compute_ip_checksum(&hdr[14], 20);
+
+	hdr[25] = chksum >> 8;
+	hdr[24] = chksum;
+	eth_pio_write(hdr, (TX_START << 8), sizeof(hdr), eth_nic_base);
+}
+
+
+#else
+
+/* ROMCC madness */
+static void ns8390_tx_header(unsigned int eth_nic_base, int pktlen)
+{
+	unsigned short chksum;
+
+	eth_pio_write(hdr, (TX_START << 8), sizeof(hdr), eth_nic_base);
+
+	str2mac_load(CONFIG_CONSOLE_NE2K_DST_MAC, 0, eth_nic_base);
+
+	str2ip_load(CONFIG_CONSOLE_NE2K_DST_IP, 30, eth_nic_base);
+	str2ip_load(CONFIG_CONSOLE_NE2K_SRC_IP, 26, eth_nic_base);
+	/* zero checksum */
+	eth_pio_write_byte(0, (TX_START << 8)+24, eth_nic_base);
+	eth_pio_write_byte(0, (TX_START << 8)+25, eth_nic_base);
+
+	/* update IP packet len */
+	eth_pio_write_byte(((28 + pktlen) >> 8) & 0xff, (TX_START << 8)+16, eth_nic_base);
+	eth_pio_write_byte( (28 + pktlen) & 0xff, (TX_START << 8)+17, eth_nic_base);
+
+	/* update UDP len */
+	eth_pio_write_byte((8 + pktlen) >> 8, (TX_START << 8)+38, eth_nic_base);
+	eth_pio_write_byte( 8 + pktlen, (TX_START << 8)+39, eth_nic_base);
+
+	chksum = compute_ip_checksum_from_sram(14, 20, eth_nic_base);
+
+	eth_pio_write_byte(chksum, (TX_START << 8)+24, eth_nic_base);
+	eth_pio_write_byte(chksum >> 8, (TX_START << 8)+25, eth_nic_base);
+}
+
+#endif
+
+void ne2k_transmit(unsigned int eth_nic_base) {
+	unsigned int pktsize;
+	unsigned int len = get_count(eth_nic_base);
+	int cnt = 10000;
+
+	// so place whole header inside chip buffer
+	ns8390_tx_header(eth_nic_base, len);
+
+	// commit sending now
+	outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+	outb(TX_START, eth_nic_base + D8390_P0_TPSR);
+
+	pktsize = 42 + len;
+	if (pktsize < 64) 
+		pktsize = 64;
+
+	outb(pktsize, eth_nic_base + D8390_P0_TBCR0);
+	outb(pktsize >> 8, eth_nic_base + D8390_P0_TBCR1);
+
+	outb(D8390_ISR_PTX, eth_nic_base + D8390_P0_ISR);
+
+	outb(D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+	/* wait for operation finish */
+	while ((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_PTX) != D8390_ISR_PTX) {
+			//intk(BIOS_DEBUG, "TX\n"); 
+			if (cnt == 0) {
+				//printk(BIOS_DEBUG, "TX timeout\n"); 
+				break;
+			}
+			cnt --;
+		}
+
+	set_count(eth_nic_base, 0);
+}
+
+#ifdef __PRE_RAM__
+
+#include <arch/romcc_io.h>
+
+static void ns8390_reset(unsigned int eth_nic_base)
+{
+	int i;
+
+	outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+	     D8390_COMMAND_STP, eth_nic_base + D8390_P0_COMMAND);
+
+	outb(0x48, eth_nic_base + D8390_P0_DCR);
+	outb(0, eth_nic_base + D8390_P0_RBCR0);
+	outb(0, eth_nic_base + D8390_P0_RBCR1);
+	outb(0x20, eth_nic_base + D8390_P0_RCR);
+	outb(2, eth_nic_base + D8390_P0_TCR);
+	outb(TX_START, eth_nic_base + D8390_P0_TPSR);
+	outb(RX_START, eth_nic_base + D8390_P0_PSTART);
+	outb(MEM_SIZE, eth_nic_base + D8390_P0_PSTOP);
+	outb(MEM_SIZE - 1, eth_nic_base + D8390_P0_BOUND);
+	outb(0xFF, eth_nic_base + D8390_P0_ISR);
+	outb(0, eth_nic_base + D8390_P0_IMR);
+
+	outb(D8390_COMMAND_PS1 |
+	     D8390_COMMAND_RD2 | D8390_COMMAND_STP,
+	     eth_nic_base + D8390_P0_COMMAND);
+
+	for (i = 0; i < ETH_ALEN; i++)
+		outb(0x0C, eth_nic_base + D8390_P1_PAR0 + i);
+
+	for (i = 0; i < ETH_ALEN; i++)
+		outb(0xFF, eth_nic_base + D8390_P1_MAR0 + i);
+
+	outb(RX_START, eth_nic_base + D8390_P1_CURR);
+	outb(D8390_COMMAND_PS0 |
+	     D8390_COMMAND_RD2 | D8390_COMMAND_STA,
+	     eth_nic_base + D8390_P0_COMMAND);
+	outb(0xFF, eth_nic_base + D8390_P0_ISR);
+	outb(0, eth_nic_base + D8390_P0_TCR);
+	outb(4, eth_nic_base + D8390_P0_RCR);
+	set_count(eth_nic_base, 0);
+}
+
+
+int ne2k_init(unsigned int eth_nic_base) {
+
+	device_t dev;
+	unsigned char c;
+
+	/* Power management controller */
+	dev = pci_locate_device(PCI_ID(0x10ec,
+				       0x8029), 0);
+
+	if (dev == PCI_DEV_INVALID)
+		return 0;
+
+	pci_write_config32(dev, 0x10, eth_nic_base | 1 );
+	pci_write_config8(dev, 0x4, 0x1);
+
+
+	c = inb(eth_nic_base + NE_ASIC_OFFSET + NE_RESET);
+	outb(c, eth_nic_base + NE_ASIC_OFFSET + NE_RESET);
+
+	(void) inb(0x84);
+
+	outb(D8390_COMMAND_STP | D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
+	outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR); 
+
+	outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR); 
+	outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
+	outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
+
+	ns8390_reset(eth_nic_base);
+	return 1;
+}
+
+#else
+
+#include <delay.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arch/io.h>
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+static void read_resources(struct device *dev)
+{
+	struct resource *res;
+
+	/* Fix the I/O Resources of the USB2.0 Interface */
+	res = new_resource(dev, PCI_BASE_ADDRESS_0);
+	res->base = CONFIG_CONSOLE_NE2K_IO_PORT;
+	res->size = 32;
+	res->align = 5;
+	res->gran = 5;
+	res->limit = res->base + res->size - 1;
+	res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_STORED |
+		     		IORESOURCE_ASSIGNED;
+	return;
+}
+
+
+static struct device_operations si_sata_ops  = {
+	.read_resources   = read_resources,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = 0,
+	.scan_bus         = 0,
+};
+
+static const struct pci_driver si_sata_driver __pci_driver = {
+        .ops    = &si_sata_ops,
+        .vendor = 0x10ec,
+        .device = 0x8029,
+};
+
+#endif
Index: src/lib/Makefile.inc
===================================================================
--- src/lib/Makefile.inc	(revision 5631)
+++ src/lib/Makefile.inc	(working copy)
@@ -22,6 +22,9 @@ 
 initobj-y += cbfs.o
 initobj-y += lzma.o
 #initobj-y += lzmadecode.o
+initobj-$(CONFIG_CONSOLE_NE2K) += ne2k.o
+initobj-$(CONFIG_CONSOLE_NE2K) += compute_ip_checksum.o
+driver-$(CONFIG_CONSOLE_NE2K) += ne2k.o
 
 obj-$(CONFIG_USBDEBUG) += usbdebug.o
 
Index: src/lib/ns8390.h
===================================================================
--- src/lib/ns8390.h	(revision 0)
+++ src/lib/ns8390.h	(revision 0)
@@ -0,0 +1,110 @@ 
+/**************************************************************************
+ETHERBOOT -  BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters
+  Date: Jun/94
+
+**************************************************************************/
+
+//FILE_LICENCE ( BSD2 );
+
+#define VENDOR_NONE	0
+#define VENDOR_WD	1
+#define VENDOR_NOVELL	2
+#define VENDOR_3COM	3
+
+#define FLAG_PIO	0x01
+#define FLAG_16BIT	0x02
+#define FLAG_790	0x04
+
+#define MEM_8192	32
+#define MEM_16384	64
+#define MEM_32768	128
+
+#define	ISA_MAX_ADDR	0x400
+
+/**************************************************************************
+NE1000/2000 definitions
+**************************************************************************/
+#define NE_ASIC_OFFSET	0x10
+#define NE_RESET	0x0F		/* Used to reset card */
+#define NE_DATA		0x00		/* Used to read/write NIC mem */
+
+#define COMPEX_RL2000_TRIES	200
+
+/**************************************************************************
+8390 Register Definitions
+**************************************************************************/
+#define D8390_P0_COMMAND	0x00
+#define D8390_P0_PSTART		0x01
+#define D8390_P0_PSTOP		0x02
+#define D8390_P0_BOUND		0x03
+#define D8390_P0_TSR		0x04
+#define	D8390_P0_TPSR		0x04
+#define D8390_P0_TBCR0		0x05
+#define D8390_P0_TBCR1		0x06
+#define D8390_P0_ISR		0x07
+#define D8390_P0_RSAR0		0x08
+#define D8390_P0_RSAR1		0x09
+#define D8390_P0_RBCR0		0x0A
+#define D8390_P0_RBCR1		0x0B
+#define D8390_P0_RSR		0x0C
+#define D8390_P0_RCR		0x0C
+#define D8390_P0_TCR		0x0D
+#define D8390_P0_DCR		0x0E
+#define D8390_P0_IMR		0x0F
+#define D8390_P1_COMMAND	0x00
+#define D8390_P1_PAR0		0x01
+#define D8390_P1_PAR1		0x02
+#define D8390_P1_PAR2		0x03
+#define D8390_P1_PAR3		0x04
+#define D8390_P1_PAR4		0x05
+#define D8390_P1_PAR5		0x06
+#define D8390_P1_CURR		0x07
+#define D8390_P1_MAR0		0x08
+
+#define D8390_COMMAND_PS0	0x0		/* Page 0 select */
+#define D8390_COMMAND_PS1	0x40		/* Page 1 select */
+#define D8390_COMMAND_PS2	0x80		/* Page 2 select */
+#define	D8390_COMMAND_RD2	0x20		/* Remote DMA control */
+#define D8390_COMMAND_RD1	0x10
+#define D8390_COMMAND_RD0	0x08
+#define D8390_COMMAND_TXP	0x04		/* transmit packet */
+#define D8390_COMMAND_STA	0x02		/* start */
+#define D8390_COMMAND_STP	0x01		/* stop */
+
+#define D8390_RCR_MON		0x20		/* monitor mode */
+
+#define D8390_DCR_FT1		0x40
+#define D8390_DCR_LS		0x08		/* Loopback select */
+#define D8390_DCR_WTS		0x01		/* Word transfer select */
+
+#define D8390_ISR_PRX		0x01		/* successful recv */
+#define D8390_ISR_PTX		0x02		/* successful xmit */
+#define D8390_ISR_RXE		0x04		/* receive error */
+#define D8390_ISR_TXE		0x08		/* transmit error */
+#define D8390_ISR_OVW		0x10		/* Overflow */
+#define D8390_ISR_CNT		0x20		/* Counter overflow */
+#define D8390_ISR_RDC		0x40		/* Remote DMA complete */
+#define D8390_ISR_RST		0x80		/* reset */
+
+#define D8390_RSTAT_PRX		0x01		/* successful recv */
+#define D8390_RSTAT_CRC		0x02		/* CRC error */
+#define D8390_RSTAT_FAE		0x04		/* Frame alignment error */
+#define D8390_RSTAT_OVER	0x08		/* FIFO overrun */
+
+#define D8390_TXBUF_SIZE	6
+#define D8390_RXBUF_END		32
+#define D8390_PAGE_SIZE         256
+
+struct ringbuffer {
+	unsigned char status;
+	unsigned char next;
+	unsigned short len;
+};
+/*
+ * Local variables:
+ *  c-basic-offset: 8
+ * End:
+ */
+
Index: src/arch/i386/lib/printk_init.c
===================================================================
--- src/arch/i386/lib/printk_init.c	(revision 5631)
+++ src/arch/i386/lib/printk_init.c	(working copy)
@@ -21,8 +21,17 @@ 
 #include <console/vtxprintf.h>
 #include <uart8250.h>
 
+#if CONFIG_CONSOLE_NE2K
+#include <console/ne2k.h>
+#endif
+
 static void console_tx_byte(unsigned char byte)
 {
+#if CONFIG_CONSOLE_NE2K
+#ifdef __PRE_RAM__
+	ne2k_append_data(&byte, 1, CONFIG_CONSOLE_NE2K_IO_PORT);
+#endif
+#endif
 	if (byte == '\n')
 		uart8250_tx_byte(CONFIG_TTYS0_BASE, '\r');
 
@@ -41,6 +50,8 @@ 
 	va_start(args, fmt);
 	i = vtxprintf(console_tx_byte, fmt, args);
 	va_end(args);
-
+#if CONFIG_CONSOLE_NE2K
+	ne2k_transmit(CONFIG_CONSOLE_NE2K_IO_PORT);
+#endif
 	return i;
 }
Index: Makefile
===================================================================
--- Makefile	(revision 5631)
+++ Makefile	(working copy)
@@ -292,7 +292,7 @@ 
 CFLAGS += -Wwrite-strings -Wredundant-decls -Wno-trigraphs
 CFLAGS += -Wstrict-aliasing -Wshadow
 ifeq ($(CONFIG_WARNINGS_ARE_ERRORS),y)
-CFLAGS += -Werror
+#CFLAGS += -Werror
 endif
 CFLAGS += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer