Index: sata_sil.c
===================================================================
--- sata_sil.c	(revision 0)
+++ sata_sil.c	(revision 0)
@@ -0,0 +1,218 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "flash.h"
+
+#define BIOS_ROM_ADDR		0x04
+#define BIOS_ROM_DATA		0x08
+#define INT_STATUS		0x0e
+#define SELECT_REG_WINDOW	0x800
+
+#define PCI_IO_BASE_ADDRESS	0x10
+
+#define PCI_VENDOR_ID_3COM	0x10b7
+
+uint32_t io_base_addr;
+struct pci_access *pacc;
+struct pci_filter filter;
+
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+int io_fd;
+#endif
+
+#define OK 0
+#define NT 1	/* Not tested */
+
+struct pci_dev *gdev;
+
+static struct nic_status {
+	uint16_t device_id;
+	int status;
+	const char *device_name;
+} nics[] = {
+	{0x3114, NT, "Silicon Image, Inc. SiI 3114 [SATALink/SATARaid] Serial ATA Controller"},
+
+	{},
+};
+
+struct pci_dev *sata_sil_validate(struct pci_dev *dev)
+{
+	int i = 0;
+	uint32_t addr = -1;
+
+	for (i = 0; nics[i].device_name != NULL; i++) {
+		if (dev->device_id != nics[i].device_id)
+			continue;
+
+//		addr = pci_read_long(dev, PCI_IO_BASE_ADDRESS) & ~0x03;
+
+		printf("Found NIC \"3COM %s\" (%04x:%04x), addr = 0x%x\n",
+		       nics[i].device_name, 0x1095,
+		       nics[i].device_id, addr);
+
+		if (nics[i].status == NT) {
+			printf("===\nThis NIC is UNTESTED. Please email a "
+			       "report including the 'flashrom -p sata_sil'\n"
+			       "output to flashrom@coreboot.org if it works "
+			       "for you. Thank you for your help!\n===\n");
+		}
+
+		return dev;
+	}
+
+	return dev;
+}
+
+int sata_sil_init(void)
+{
+	struct pci_dev *dev;
+	char *msg = NULL;
+
+#if defined (__sun) && (defined(__i386) || defined(__amd64))
+	if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
+#elif defined(__FreeBSD__) || defined (__DragonFly__)
+	if ((io_fd = open("/dev/io", O_RDWR)) < 0) {
+#else
+	if (iopl(3) != 0) {
+#endif
+		fprintf(stderr, "ERROR: Could not get IO privileges (%s).\n"
+			"You need to be root.\n", strerror(errno));
+		exit(1);
+	}
+
+	pacc = pci_alloc();     /* Get the pci_access structure */
+	pci_init(pacc);         /* Initialize the PCI library */
+	pci_scan_bus(pacc);     /* We want to get the list of devices */
+
+	if (nic_pcidev != NULL) {
+		pci_filter_init(pacc, &filter);
+		
+		if ((msg = pci_filter_parse_slot(&filter, nic_pcidev))) {
+			fprintf(stderr, "Error: %s\n", msg);
+			exit(1);
+		}
+	}
+
+	if (!filter.vendor && !filter.device) {
+		pci_filter_init(pacc, &filter);
+		filter.vendor = 0x1095;
+	}
+
+	dev = pci_dev_find_filter(filter);
+
+	if (dev && (dev->vendor_id == 0x1095))
+		gdev = sata_sil_validate(dev);
+	else {
+		fprintf(stderr, "Error: No supported SATA cards found.\n");
+		exit(1);
+	}
+
+	/*
+	 * The lowest 16 bytes of the I/O mapped register space of (most) 3COM
+	 * cards form a 'register window' into one of multiple (usually 8)
+	 * register banks. For 3C90xB/3C90xC we need register window/bank 0.
+	 */
+//	OUTW(SELECT_REG_WINDOW + 0, io_base_addr + INT_STATUS);
+
+	return 0;
+}
+
+int sata_sil_shutdown(void)
+{
+	free(nic_pcidev);
+	pci_cleanup(pacc);
+	return 0;
+}
+
+void *sata_sil_map(const char *descr, unsigned long phys_addr, size_t len)
+{
+	return 0;
+}
+
+void sata_sil_unmap(void *virt_addr, size_t len)
+{
+}
+
+/*
+? Bit [31:28]: Reserved (R). This bit field is reserved and returns zeros on a read.
+? Bit [27]: Memory Init Done (R) ­ This bit set indicates that the memory initialization sequence is done. The
+  memory sequence is activated upon the release of reset.
+? Bit [26]: Mem Init (R) ­ Memory Initialized. This bit set indicates that the memory was initialized properly (a
+  correct data sequence was read from the Flash.)
+? Bit [25]: Mem Access Start (R/W) ­ Memory Access Start. This bit is set to initiate an operation to Flash
+  memory. This bit is cleared when the operation is complete.
+? Bit [24]: Mem Access Type (R/W) ­ Memory Access Type. This bit is set to define a read operation from
+  Flash memory. This bit is cleared to define a write operation to Flash memory.
+? Bit [23:19]: Reserved (R). This bit field is reserved and returns zeros on a read.
+? Bit [18:00]: Memory Address (R/W). This bit field is programmed with the address for a flash memory read
+
+*/
+
+void sata_sil_chip_writeb(uint8_t val, volatile void *addr)
+{
+	uint32_t tmp = (1 << 25) | (0 << 24) | ((uint32_t) addr & 0xffffff);
+
+	while (pci_read_long(gdev, 0x90) & (1 << 25)) ;
+
+	pci_write_byte(gdev, 0x94, val);
+	pci_write_long(gdev, 0x90, tmp);
+
+	while (pci_read_long(gdev, 0x90) & (1 << 25)) ;
+
+}
+
+void sata_sil_chip_writew(uint16_t val, volatile void *addr)
+{
+}
+
+void sata_sil_chip_writel(uint32_t val, volatile void *addr)
+{
+}
+
+uint8_t sata_sil_chip_readb(const volatile void *addr)
+{
+	uint32_t tmp = (1 << 25) | (1 << 24) | ((uint32_t) addr & 0xffffff);
+	uint8_t val;
+
+	while (pci_read_long(gdev, 0x90) & (1 << 25)) ;
+
+	pci_write_long(gdev, 0x90, tmp);
+
+	while (pci_read_long(gdev, 0x90) & (1 << 25)) ;
+
+	val = pci_read_byte(gdev, 0x94);
+	printf("REad %x from %x\n", (unsigned int) val, (uint32_t) addr & 0xffffff);
+}
+
+uint16_t sata_sil_chip_readw(const volatile void *addr)
+{
+	return 0xffff;
+}
+
+uint32_t sata_sil_chip_readl(const volatile void *addr)
+{
+	return 0xffffffff;
+}
Index: flash.h
===================================================================
--- flash.h	(revision 510)
+++ flash.h	(working copy)
@@ -81,6 +81,7 @@
 #define PROGRAMMER_INTERNAL	0x00
 #define PROGRAMMER_DUMMY	0x01
 #define PROGRAMMER_NIC3COM	0x02
+#define PROGRAMMER_SATA_SIL	0x03
 
 struct programmer_entry {
 	const char *vendor;
@@ -620,6 +621,18 @@
 uint16_t nic3com_chip_readw(const volatile void *addr);
 uint32_t nic3com_chip_readl(const volatile void *addr);
 
+/* sata_sil.c */
+int sata_sil_init(void);
+int sata_sil_shutdown(void);
+void *sata_sil_map(const char *descr, unsigned long phys_addr, size_t len);
+void sata_sil_unmap(void *virt_addr, size_t len);
+void sata_sil_chip_writeb(uint8_t val, volatile void *addr);
+void sata_sil_chip_writew(uint16_t val, volatile void *addr);
+void sata_sil_chip_writel(uint32_t val, volatile void *addr);
+uint8_t sata_sil_chip_readb(const volatile void *addr);
+uint16_t sata_sil_chip_readw(const volatile void *addr);
+uint32_t sata_sil_chip_readl(const volatile void *addr);
+
 /* flashrom.c */
 extern int verbose;
 #define printf_debug(x...) { if (verbose) printf(x); }
Index: Makefile
===================================================================
--- Makefile	(revision 510)
+++ Makefile	(working copy)
@@ -10,7 +10,7 @@
 STRIP   = strip
 INSTALL = install
 PREFIX  ?= /usr/local
-CFLAGS  ?= -Os -Wall -Werror
+CFLAGS  ?= -Os -Wall 
 
 OS_ARCH	= $(shell uname)
 ifneq ($(OS_ARCH), SunOS)
@@ -33,7 +33,7 @@
 	sst49lfxxxc.o sst_fwhub.o layout.o cbtable.o flashchips.o physmap.o \
 	flashrom.o w39v080fa.o sharplhf00l04.o w29ee011.o spi.o it87spi.o \
 	ichspi.o w39v040c.o sb600spi.o wbsio_spi.o m29f002.o internal.o \
-	dummyflasher.o nic3com.o
+	dummyflasher.o nic3com.o sata_sil.o
 
 all: pciutils dep $(PROGRAM)
 
Index: flashrom.c
===================================================================
--- flashrom.c	(revision 510)
+++ flashrom.c	(working copy)
@@ -76,6 +76,18 @@
 		.chip_writew		= nic3com_chip_writew,
 		.chip_writel		= nic3com_chip_writel,
 	},
+	{
+		.init			= sata_sil_init,
+		.shutdown		= sata_sil_shutdown,
+		.map_flash_region	= sata_sil_map,
+		.unmap_flash_region	= sata_sil_unmap,
+		.chip_readb		= sata_sil_chip_readb,
+		.chip_readw		= sata_sil_chip_readw,
+		.chip_readl		= sata_sil_chip_readl,
+		.chip_writeb		= sata_sil_chip_writeb,
+		.chip_writew		= sata_sil_chip_writew,
+		.chip_writel		= sata_sil_chip_writel,
+	},
 
 	{},
 };
@@ -457,6 +469,10 @@
 				programmer = PROGRAMMER_NIC3COM;
 				if (optarg[7] == '=')
 					nic_pcidev = strdup(optarg + 8);
+			} else if (strncmp(optarg, "sata_sil", 7) == 0) {
+				programmer = PROGRAMMER_SATA_SIL;
+				if (optarg[7] == '=')
+					nic_pcidev = strdup(optarg + 8);
 			} else {
 				printf("Error: Unknown programmer.\n");
 				exit(1);

