Patchwork [RFC] Network console for coreboot

login
register
about
Submitter Rudolf Marek
Date 2010-05-30 19:33:54
Message ID <4C02BDA2.1030101@assembler.cz>
Download mbox | patch
Permalink /patch/1428/
State Superseded
Headers show

Comments

Rudolf Marek - 2010-05-30 19:33:54
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello all,

Maybe this story should be for coreboot blog ;)

I have a very short serial cable and therefore I had to always connect the
coreboot machine to the notebook which is bit annoying if I use my workstation
for development.

You may ask how send packets if we have no RAM? Good question so far I know two
answers:

1) use some card with internal SRAM

I know only one... RTL 8029AS which is a NE 2000 compatible PCI card. It has
like 16kb SRAM which is only accessible through PIO.

2) Use some other PCI card with a memory space for packet descriptors, maybe the
sideport memory could work - this is just an idea not tested

Rest was relatively simple. I took the PCI NE2000 driver from gpxe sources, made
it bit more simple (b.c) all routines takes as an argument the IO address of the
card.

How it works:

1) before uart init call net_init() which just setup the BAR0 on card to IOport
0xe00 enable the IO decoding of the card

2) in uart_tx_byte write the byte to card SRAM

3) after the print is done, construct the packet, with fixed MAC and fixed IP,
variable length. The IP payload is UDP packet (src port 6667 dest 6666) The UDP
payload is our text which is already there. Thefore invoke the transmit jut to
transmit it ;)

4) If the PCI slot with the card is bellow some bridge, then situation does
not differ too much. In my case, the first part of the boot is the card on BUS0
but later the PCI slot bus is moved to separate bus (chipset has some bit for
this). Because the bridge has subtractive decoding, the output still works
regardless of the IO forwarding range. The only problem is if coreboot wants to
write new address to BAR0. I solved that by simple hack - I did small PCI driver
which just tells coreboot  the card has fixed and assigned IO resource.

Here is how it looks in linux:

00:13.1 PCI bridge: VIA Technologies, Inc. VT8237A PCI to PCI Bridge (prog-if 01
[Subtractive decode])
	Bus: primary=00, secondary=05, subordinate=05, sec-latency=0
	I/O behind bridge: 00001000-00001fff
	Memory behind bridge: f1200000-f12fffff


05:06.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8029(AS)
	Flags: medium devsel, IRQ 16
	I/O ports at 0e00 [size=32]
	Kernel driver in use: ne2k-pci
	Kernel modules: ne2k-pci

And here how it looks if I catch the output with netcat:

$nc -u -l -p 6666

TEST

coreboot-4.0-r5577M Sun May 30 20:21:52 CEST 2010 starting...
now booting...



INIT detected from  --- { APICID = 00 NODEID = 00 COREID = 00} ---

Issuing SOFT_RESET...
soft reset
TEST

coreboot-4.0-r5577M Sun May 30 20:21:52 CEST 2010 starting...
now booting...
Enabling routing table for node 00 done.
Enabling UP settings
Disabling read/write/fill probes for UP... done.
coherent_ht_finalize
done

<---- snip ---->

Post relocation: addr: 0x00000000000eca00 memsz: 0x0000000000013600 filesz:
0x0000000000009a8e
using LZMA
[ 0x00000000000eca00, 0000000000100000, 0x0000000000100000) <- 00000000fff97c70
dest 000eca00, end 00100000, bouncebuffer 1def0000
Loaded segments
Jumping to boot code at fdfae
entry    = 0x000fdfae
lb_start = 0x00100000
lb_size  = 0x00080000
adjust   = 0x1de70000
buffer   = 0x1def0000
     elf_boot_notes = 0x00118ab0
adjusted_boot_notes = 0x1df88ab0


It goes allright through the boot. Now some questions:

5) The b.c file is from GPXE project and this particular file is under two
Clause BSD license which is compatible with GPL. Can we include this or some
other rewrite needs to be done?

6) SMP? I think we will need some locking ?

7) In case you are wondering where to get RTL8029AS pci card. I asked one big
czech ISP and they found like 20 of this cards. If some of coreboot developers
wants some I can mail it to you with a price of the mail and paypal fee.

8) Someone has free time to fix this patch to something more pretty?


Thanks,
Rudolf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkwCvaEACgkQ3J9wPJqZRNWngQCePOCPktBDBv2VP4SDSrLxFa/N
44MAoJe+hgnp8ZJicifwfFgnZSkJw+dW
=BQN9
-----END PGP SIGNATURE-----
Rudolf Marek - 2010-05-31 19:05:31
I made bit more extended version on http://blogs.coreboot.org

Thanks,
Rudolf
Joseph Smith - 2010-05-31 19:22:25
On 05/31/2010 03:05 PM, Rudolf Marek wrote:
> I made bit more extended version on http://blogs.coreboot.org
>
Sweet :-)
That is really cool Rudolf :-)

Patch

Index: src/mainboard/asus/m2v-mx_se/romstage.c
===================================================================
--- src/mainboard/asus/m2v-mx_se/romstage.c	(revision 5577)
+++ src/mainboard/asus/m2v-mx_se/romstage.c	(working copy)
@@ -99,6 +99,10 @@ 
 
 #define SB_VFSMAF 0
 
+static void init_net2(void) {
+}
+
+
 /* this function might fail on some K8 CPUs with errata #181 */
 static void ldtstop_sb(void)
 {
@@ -160,11 +164,16 @@ 
 	it8712f_kill_watchdog();
 	it8712f_enable_3vsbsw();
 	uart_init();
+	init_net();
 	console_init();
+
+
 	enable_rom_decode();
 
 	printk(BIOS_INFO, "now booting... \n");
+	//ns8390_transmit(1, "D", 0xe000);
 
+
 	if (bist == 0)
 		bsp_apicid = init_cpus(cpu_init_detectedx, sysinfo);
 
@@ -200,6 +209,7 @@ 
 		printk(BIOS_DEBUG, "FAILED!\n");
 	}
 
+
 	/* the HT settings needs to be OK, because link freq chnage may cause HT disconnect */
 	/* allow LDT STOP asserts */
 	vt8237_sb_enable_fid_vid();
Index: src/console/printk.c
===================================================================
--- src/console/printk.c	(revision 5577)
+++ src/console/printk.c	(working copy)
@@ -28,6 +28,7 @@ 
 	va_start(args, fmt);
 	i = vtxprintf(console_tx_byte, fmt, args);
 	va_end(args);
+	ns8390_transmit(0xe00);
 
 	console_tx_flush();
 
Index: src/console/uart8250_console.c
===================================================================
--- src/console/uart8250_console.c	(revision 5577)
+++ src/console/uart8250_console.c	(working copy)
@@ -1,7 +1,13 @@ 
 #include <console/console.h>
 #include <uart8250.h>
 #include <pc80/mc146818rtc.h>
+#include <arch/io.h>
+#include <device/pci.h>
 
+//#include "b.c"
+
+#include "../arch/i386/lib/b.c"
+
 /* Base Address */
 #ifndef CONFIG_TTYS0_BASE
 #define CONFIG_TTYS0_BASE 0x3f8
@@ -35,11 +41,26 @@ 
 	if(get_option(&b_index,"baud_rate")==0) {
 		divisor=div[b_index];
 	}
+
 	uart8250_init(CONFIG_TTYS0_BASE, divisor, CONFIG_TTYS0_LCS);
+	
+#ifdef __PRE_RAM__ 
+//	init_net();
+#endif
 }
 
+
+//static void ns8390_transmit( unsigned int len, const unsigned char *p,
+//unsigned int eth_nic_base);
+
+
 static void ttyS0_tx_byte(unsigned char data)
 {
+	unsigned char d = data;
+#ifdef __PRE_RAM__ 
+//	ns8390_transmit(1, &d, 0xe000);
+#endif
+	append_data(&d, 1, 0xe00);
 	uart8250_tx_byte(CONFIG_TTYS0_BASE, data);
 }
 
Index: src/pc80/serial.c
===================================================================
--- src/pc80/serial.c	(revision 5577)
+++ src/pc80/serial.c	(working copy)
@@ -64,8 +64,16 @@ 
 	;
 }
 
+
+static void ns8390_transmit( unsigned int len, const unsigned char *p,
+unsigned int eth_nic_base);
+
 static void uart_tx_byte(unsigned char data)
 {
+	char d = data;
+//#ifdef __PRE_RAM__ 
+//	ns8390_transmit(1, &d, 0xe000);
+//#endif
 	uart_wait_to_tx_byte();
 	outb(data, CONFIG_TTYS0_BASE + UART_TBR);
 	/* Make certain the data clears the fifos */
Index: src/arch/i386/lib/b.c
===================================================================
--- src/arch/i386/lib/b.c	(revision 0)
+++ src/arch/i386/lib/b.c	(revision 0)
@@ -0,0 +1,324 @@ 
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/io.h>
+
+
+#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)
+
+
+#define FILE_LICENSE(a) 
+
+//char gnode_addr[6] = { 0x08,0x00,0x20,0xC0,0xFF,0xEE};
+
+//typedef unsigned long Address;
+
+#include "ns8390.h"
+//FILE_LICENCE(BSD2);
+//static unsigned char eth_flags;
+//static unsigned short eth_nic_base;
+//static unsigned char  eth_rx_start, eth_tx_start;
+#define MEM_SIZE MEM_32768
+#define TX_START 64
+#define RX_START (64 + D8390_TXBUF_SIZE)
+
+//static Address eth_bmem, eth_rmem;
+//static unsigned char eth_drain_receiver;
+
+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);
+	
+}
+
+
+static void eth_pio_write(const 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);
+
+	//if (eth_flags & FLAG_16BIT)
+//		cnt = (cnt + 1) >> 1;
+
+	while (cnt--) {
+		//if (eth_flags & FLAG_16BIT) {
+//			outw(*((unsigned short *) src),
+//			     eth_nic_base + NE_ASIC_OFFSET + NE_DATA);
+//			src += 2;
+		//} else
+			outb(*(src++), eth_nic_base + NE_ASIC_OFFSET + NE_DATA);
+	}
+
+	/* wait for operation finish */
+	while ((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) != D8390_ISR_RDC) {
+//		printk(BIOS_DEBUG, "WRITE\n"); 
+		}
+		
+
+}
+
+ void append_data(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);
+
+}
+
+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);
+	//if (eth_flags & FLAG_16BIT)
+//		outb(0x49, eth_nic_base + D8390_P0_DCR);
+	//else
+		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);
+
+//		outb(nic->node_addr[i], 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);
+	//enable_multicast(eth_nic_base);
+}
+
+
+static unsigned long compute_ip_checksum(void *addr, unsigned long length)
+{
+	uint8_t *ptr;
+	volatile union {
+		uint8_t  byte[2];
+		uint16_t word;
+	} value;
+	unsigned long sum;
+	unsigned long i;
+	/* In the most straight forward way possible,
+	 * compute an ip style checksum.
+	 */
+	sum = 0;
+	ptr = addr;
+	for(i = 0; i < length; i++) {
+		unsigned long v;
+		v = ptr[i];
+		if (i & 1) {
+			v <<= 8;
+		}
+		/* Add the new value */
+		sum += v;
+		/* Wrap around the carry */
+		if (sum > 0xFFFF) {
+			sum = (sum + (sum >> 16)) & 0xFFFF;
+		}
+	}
+	value.byte[0] = sum & 0xff;
+	value.byte[1] = (sum >> 8) & 0xff;
+	return (~value.word) & 0xFFFF;
+}
+
+
+
+static void ns8390_tx_header(unsigned int eth_nic_base, int pktlen) {
+	unsigned short chksum;
+
+	unsigned char hdr[] = { 
+		/*
+		 * ETHERNET HDR
+		 */
+		// destination macaddr
+		0x00, 0x13, 0xd4, 0x76, 0xa2, 0xac,
+//		00:13:f7:0b:7f:36
+//		0x00, 0x13, 0xf7, 0x0b, 0x7f, 0x36, 
+
+//		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+		/* source mac, might be overwritten when copied to SRAM*/
+		0x08, 0x00, 0x20, 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, 0xa, 0x0, 0x1, 0xfd, 
+		/* IP0, IP1, IP2, IP3  */
+		0xa, 0x0, 0x1, 27, 
+//81.0.237.101
+//		81, 0x0, 237, 101, 
+//		255, 255, 255, 255, 
+		/*
+		 * UDP HDR
+		 */
+
+		/*  SRC PORT DST PORT  (2bytes each), ulen, uchksum (must be zero or correct */
+//		0x7a, 0x69, 0x7a, 0x69, 0x00, 0x9, 0x00, 0x00, 
+		0x1a, 0x0b, 0x1a, 0x0a, 0x00, 0x9, 0x00, 0x00, 
+	};
+
+	hdr[24] = 0;
+	hdr[25] = 0;
+
+
+	hdr[16] = ((28 + pktlen) >> 8) & 0xff;
+	hdr[17] = (28 + pktlen) & 0xff;
+
+	hdr[38] = (8 + pktlen) >> 8;
+	hdr[39] = 8 + pktlen;
+
+	chksum = compute_ip_checksum(&hdr[14], 20);
+//	printf("%x\n", (unsigned int) chksum);
+
+	hdr[25] = chksum >> 8;
+	hdr[24] = chksum;
+
+	eth_pio_write(hdr, (TX_START << 8), sizeof(hdr), eth_nic_base);
+}
+
+ void ns8390_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);
+
+//	eth_pio_write((unsigned char *) p, (TX_START << 8) + 42, len, eth_nic_base);
+
+	// 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);
+/*
+	{
+	unsigned int xx = inb(eth_nic_base + D8390_P0_TSR);
+	if (xx!=3)
+	printf("INB %x\n", xx);
+
+	}
+*/
+
+}
+
+
+/* 
+ * i think this piece need rework
+ * problems:
+ * - uses far too much resources like mem etc (static data is fine but everything else rather not
+ */
+
+static int nepci_probe(unsigned int eth_nic_base) {
+	int i;
+	unsigned char c;
+
+	//for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
+		//eth_flags = FLAG_PIO | FLAG_16BIT;
+		//eth_memsize = MEM_16384;
+
+		//eth_tx_start = 32;
+
+		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;
+}
+
+
Index: src/arch/i386/lib/printk_init.c
===================================================================
--- src/arch/i386/lib/printk_init.c	(revision 5577)
+++ src/arch/i386/lib/printk_init.c	(working copy)
@@ -21,8 +21,63 @@ 
 #include <console/vtxprintf.h>
 #include <uart8250.h>
 
+#include <device/pci_def.h> 
+#include <arch/io.h> 
+#include <device/pnp_def.h> 
+#include <arch/romcc_io.h> 
+
+
+#include "b.c"
+
+
+ void init_net(void) {
+
+	device_t dev;
+
+	/* Power management controller 
+	dev = pci_locate_device(PCI_ID(0x1106,
+				       0xb188), 0);
+
+	pci_write_config8(dev, 0x4, 0x0);
+
+
+	dev = pci_locate_device(PCI_ID(0x1106,
+				       0x337b), 0);
+
+	pci_write_config8(dev, 0x4, 0x0);
+*/
+	/* Power management controller */
+	dev = pci_locate_device(PCI_ID(0x10ec,
+				       0x8029), 0);
+
+//	printk(BIOS_DEBUG, "NET INIT\n");
+
+	if (dev == PCI_DEV_INVALID)
+		return ;
+
+//	printk(BIOS_DEBUG, "NET INIT FOUND\n");
+
+	pci_write_config32(dev, 0x10, 0xe00 | 1 );
+	pci_write_config8(dev, 0x4, 0x1);
+
+	nepci_probe(0xe00);
+//	printk(BIOS_DEBUG, "NET INIT FOUND - probe\n");
+
+	append_data("TEST", 4, 0xe00);
+//	printk(BIOS_DEBUG, "APPEND\n");
+//	eth_pio_write("TEST", (TX_START << 8) + 42, 4, 0xe000);
+	ns8390_transmit(0xe00);
+//	printk(BIOS_DEBUG, "XMIT\n");
+}
+
+
 static void console_tx_byte(unsigned char byte)
 {
+unsigned char d = byte;
+#ifdef __PRE_RAM__ 
+	append_data(&d, 1, 0xe00);
+#endif
+
 	if (byte == '\n')
 		uart8250_tx_byte(CONFIG_TTYS0_BASE, '\r');
 
@@ -41,6 +96,6 @@ 
 	va_start(args, fmt);
 	i = vtxprintf(console_tx_byte, fmt, args);
 	va_end(args);
-
+	ns8390_transmit(0xe00);
 	return i;
 }
Index: src/drivers/sil/3114/sil_sata.c
===================================================================
--- src/drivers/sil/3114/sil_sata.c	(revision 5577)
+++ src/drivers/sil/3114/sil_sata.c	(working copy)
@@ -15,33 +15,33 @@ 
 #include <device/pci_ids.h>
 #include <device/pci_ops.h>
 
-static void si_sata_init(struct device *dev)
+static void read_resources(struct device *dev)
 {
-	uint32_t dword;
-	/* enable change device id and class id */
-	dword = pci_read_config32(dev,0x40);
-	dword |= (1<<0);
-	pci_write_config32(dev, 0x40, dword);
-	/* Set IDE Class, Native mode, two drives per channel */
-	dword = 0x01018f00;
-	pci_write_config32(dev, 0x08, dword);
-	/* disable change device id and class id*/
-	dword = pci_read_config32(dev,0x40);
-	dword &= ~(1<<0);
-	pci_write_config32(dev, 0x40, dword);
-	printk(BIOS_INFO, "SIL3114 set to IDE compatible mode\n");
+	struct resource *res;
+
+	/* Fix the I/O Resources of the USB2.0 Interface */
+	res = new_resource(dev, PCI_BASE_ADDRESS_0);
+	res->base = 0xe00;
+	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   = pci_dev_read_resources,
+	.read_resources   = read_resources,
 	.set_resources    = pci_dev_set_resources,
 	.enable_resources = pci_dev_enable_resources,
-	.init             = si_sata_init,
+	.init             = 0,
 	.scan_bus         = 0,
 };
 
 static const struct pci_driver si_sata_driver __pci_driver = {
         .ops    = &si_sata_ops,
-        .vendor = 0x1095,
-        .device = 0x3114,
+        .vendor = 0x10ec,
+        .device = 0x8029,
 };
Index: src/drivers/sil/3114/Makefile.inc
===================================================================
--- src/drivers/sil/3114/Makefile.inc	(revision 5577)
+++ src/drivers/sil/3114/Makefile.inc	(working copy)
@@ -1 +1 @@ 
-driver-$(CONFIG_DRIVERS_SIL) += sil_sata.o
+driver-y += sil_sata.o