Index: Makefile
===================================================================
--- Makefile	(revision 1138)
+++ Makefile	(working copy)
@@ -121,9 +121,13 @@
 ifeq ($(CONFIG_INTERNAL), yes)
 override CONFIG_BITBANG_SPI = yes
 else
+ifeq ($(CONFIG_NICINTEL_SPI), yes)
+override CONFIG_BITBANG_SPI = yes
+else
 CONFIG_BITBANG_SPI ?= no
 endif
 endif
+endif
 
 # Always enable 3Com NICs for now.
 CONFIG_NIC3COM ?= yes
@@ -153,6 +157,9 @@
 # Disable National Semiconductor NICs until support is complete and tested.
 CONFIG_NICNATSEMI ?= no
 
+# Always enable SPI on Intel NICs for now.
+CONFIG_NICINTEL_SPI ?= yes
+
 # Always enable Bus Pirate SPI for now.
 CONFIG_BUSPIRATE_SPI ?= yes
 
@@ -244,6 +251,12 @@
 NEED_PCI := yes
 endif
 
+ifeq ($(CONFIG_NICINTEL_SPI), yes)
+FEATURE_CFLAGS += -D'CONFIG_NICINTEL_SPI=1'
+PROGRAMMER_OBJS += nicintel_spi.o
+NEED_PCI := yes
+endif
+
 ifeq ($(CONFIG_BUSPIRATE_SPI), yes)
 FEATURE_CFLAGS += -D'CONFIG_BUSPIRATE_SPI=1'
 PROGRAMMER_OBJS += buspirate_spi.o
Index: print_wiki.c
===================================================================
--- print_wiki.c	(revision 1138)
+++ print_wiki.c	(working copy)
@@ -296,6 +296,9 @@
 #if CONFIG_ATAHPT == 1
 	print_supported_pcidevs_wiki(ata_hpt);
 #endif
+#if CONFIG_NICINTEL_SPI == 1
+	print_supported_pcidevs_wiki(nics_intel_spi);
+#endif
 	printf("\n|}\n");
 }
 
Index: nicintel_spi.c
===================================================================
--- nicintel_spi.c	(revision 0)
+++ nicintel_spi.c	(revision 0)
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Carl-Daniel Hailfinger
+ * Copyright (C) 2010 Idwer Vollering
+ *
+ * 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
+ */
+
+/*
+Software Developer's Manual:
+http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf
+*/
+
+#include <stdlib.h>
+#include "flash.h"
+#include "programmer.h"
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+
+#define EECD	0x10
+#define FLA	0x1c
+
+/*
+Register bits of EECD.
+
+bit 04, 05: FWE (Flash Write Enable Control)
+00b = not allowed
+01b = flash writes disabled
+10b = flash writes enabled
+11b = not allowed
+*/
+#define FLASH_WRITES_DISABLED	0x10 /* FWE: 10000b */
+#define FLASH_WRITES_ENABLED	0x20 /* FWE: 100000b */
+
+/* Flash Access register bits */
+/* Table 13-9 */
+#define FL_SCK	0
+#define FL_CS	1
+#define FL_SI	2
+#define FL_SO	3
+#define FL_REQ	4
+#define FL_GNT	5
+/* Currently unused */
+//#define FL_BUSY	30
+//#define FL_ER	31
+
+uint8_t *nicintel_spibar;
+
+const struct pcidev_status nics_intel_spi[] = {
+	{PCI_VENDOR_ID_INTEL, 0x107c, OK, "Intel Corporation", "82541PI Gigabit Ethernet Controller"},
+
+	{},
+};
+
+static void nicintel_request_spibus(void)
+{
+	uint32_t tmp;
+
+	tmp = pci_mmio_readl(nicintel_spibar + FLA);
+	tmp |= 1 << FL_REQ;
+	pci_mmio_writel(tmp, nicintel_spibar + FLA);
+
+	/* Wait until we are allowed to use the SPI bus. */
+	while (!(pci_mmio_readl(nicintel_spibar + FLA) & (1 << FL_GNT))) ;
+}
+
+static void nicintel_release_spibus(void)
+{
+	uint32_t tmp;
+
+	tmp = pci_mmio_readl(nicintel_spibar + FLA);
+	tmp &= ~(1 << FL_REQ);
+	pci_mmio_writel(tmp, nicintel_spibar + FLA);
+}
+
+static void nicintel_bitbang_set_cs(int val)
+{
+	uint32_t tmp;
+
+	/*
+	Requesting and releasing the SPI bus is handled in here to allow the
+	chipset to use its own SPI engine for native reads.
+	*/
+	if (val == 0)
+		nicintel_request_spibus();
+
+	tmp = pci_mmio_readl(nicintel_spibar + FLA);
+	tmp &= ~(1 << FL_CS);
+	tmp |= (val << FL_CS);
+	pci_mmio_writel(tmp,  nicintel_spibar + FLA);
+
+	if (val == 1)
+		nicintel_release_spibus();
+}
+
+static void nicintel_bitbang_set_sck(int val)
+{
+	uint32_t tmp;
+
+	tmp = pci_mmio_readl(nicintel_spibar + FLA);
+	tmp &= ~(1 << FL_SCK);
+	tmp |= (val << FL_SCK);
+	pci_mmio_writel(tmp, nicintel_spibar + FLA);
+}
+
+static void nicintel_bitbang_set_mosi(int val)
+{
+	uint32_t tmp;
+
+	tmp = pci_mmio_readl(nicintel_spibar + FLA);
+	tmp &= ~(1 << FL_SI);
+	tmp |= (val << FL_SI);
+	pci_mmio_writel(tmp, nicintel_spibar + FLA);
+}
+
+static int nicintel_bitbang_get_miso(void)
+{
+	uint32_t tmp;
+
+	tmp = pci_mmio_readl(nicintel_spibar + FLA);
+	tmp = (tmp >> FL_SO) & 0x1;
+	return tmp;
+}
+
+static const struct bitbang_spi_master bitbang_spi_master_nicintel = {
+	.type = BITBANG_SPI_MASTER_NICINTEL,
+	.set_cs = nicintel_bitbang_set_cs,
+	.set_sck = nicintel_bitbang_set_sck,
+	.set_mosi = nicintel_bitbang_set_mosi,
+	.get_miso = nicintel_bitbang_get_miso,
+};
+
+int nicintel_spi_init(void)
+{
+	uint32_t tmp;
+
+	get_io_perms();
+
+	io_base_addr = pcidev_init(PCI_VENDOR_ID_INTEL, PCI_BASE_ADDRESS_0, nics_intel_spi);
+
+	nicintel_spibar = physmap("Intel Corporation Gigabit Ethernet Controller equipped with SPI flash", io_base_addr, 4096); 
+	tmp = pci_mmio_readl(nicintel_spibar + EECD);
+	tmp &= ~FLASH_WRITES_DISABLED;
+	tmp |= FLASH_WRITES_ENABLED;
+	pci_mmio_writel(tmp, nicintel_spibar + EECD);
+
+	/* 1 usec halfperiod delay for now. */
+	if (bitbang_spi_init(&bitbang_spi_master_nicintel, 1))
+		return 1;
+
+	buses_supported = CHIP_BUSTYPE_SPI;
+	spi_controller = SPI_CONTROLLER_NICINTEL;
+
+	return 0;
+}
+
+int nicintel_spi_shutdown(void)
+{
+	uint32_t tmp;
+
+	tmp = pci_mmio_readl(nicintel_spibar + EECD);
+	tmp &= ~FLASH_WRITES_ENABLED;
+	tmp |= FLASH_WRITES_DISABLED;
+	pci_mmio_writel(tmp, nicintel_spibar + EECD);
+
+	physunmap(nicintel_spibar, 4096);
+	pci_cleanup(pacc);
+	release_io_perms();
+
+	return 0;
+}
Index: flashrom.8
===================================================================
--- flashrom.8	(revision 1138)
+++ flashrom.8	(working copy)
@@ -189,6 +189,8 @@
 .sp
 .BR "* rayer_spi" " (for SPI flash ROMs attached to a RayeR parport \
 based programmer)"
+.BR "* nicintel_spi" " (for SPI flash ROMs attached to an Intel Corporation Gigabit \
+Ethernet Controller)"
 .sp
 Some programmers have optional or mandatory parameters which are described
 in detail in the
Index: spi.c
===================================================================
--- spi.c	(revision 1138)
+++ spi.c	(working copy)
@@ -136,6 +136,15 @@
 	},
 #endif
 
+#if CONFIG_NICINTEL_SPI == 1
+	{ /* SPI_CONTROLLER_NICINTEL */
+		.command = bitbang_spi_send_command,
+		.multicommand = default_spi_send_multicommand,
+		.read = bitbang_spi_read,
+		.write_256 = bitbang_spi_write_256,
+	},
+#endif
+
 	{}, /* This entry corresponds to SPI_CONTROLLER_INVALID. */
 };
 
Index: flashrom.c
===================================================================
--- flashrom.c	(revision 1138)
+++ flashrom.c	(working copy)
@@ -49,7 +49,7 @@
  * if more than one of them is selected. If only one is selected, it is clear
  * that the user wants that one to become the default.
  */
-#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG+CONFIG_RAYER_SPI > 1
+#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG+CONFIG_RAYER_SPI+CONFIG_NICINTEL_SPI > 1
 #error Please enable either CONFIG_DUMMY or CONFIG_INTERNAL or disable support for all programmers except one.
 #endif
 enum programmer programmer =
@@ -90,6 +90,9 @@
 #if CONFIG_RAYER_SPI == 1
 	PROGRAMMER_RAYER_SPI
 #endif
+#if CONFIG_NICINTEL_SPI == 1
+	PROGRAMMER_NICINTEL_SPI
+#endif
 ;
 #endif
 
@@ -414,6 +417,25 @@
 	},
 #endif
 
+#if CONFIG_NICINTEL_SPI == 1
+	{
+		.name = "nicintel_spi",
+		.init = nicintel_spi_init,
+		.shutdown = nicintel_spi_shutdown,
+		.map_flash_region = fallback_map,
+		.unmap_flash_region = fallback_unmap,
+		.chip_readb = noop_chip_readb,
+		.chip_readw = fallback_chip_readw,
+		.chip_readl = fallback_chip_readl,
+		.chip_readn = fallback_chip_readn,
+		.chip_writeb = noop_chip_writeb,
+		.chip_writew = fallback_chip_writew,
+		.chip_writel = fallback_chip_writel,
+		.chip_writen = fallback_chip_writen,
+		.delay = internal_delay,
+	},
+#endif
+
 	{}, /* This entry corresponds to PROGRAMMER_INVALID. */
 };
 
Index: programmer.h
===================================================================
--- programmer.h	(revision 1138)
+++ programmer.h	(working copy)
@@ -37,10 +37,10 @@
 #if CONFIG_NICREALTEK == 1
 	PROGRAMMER_NICREALTEK,
 	PROGRAMMER_NICREALTEK2,
-#endif	
+#endif
 #if CONFIG_NICNATSEMI == 1
 	PROGRAMMER_NICNATSEMI,
-#endif	
+#endif
 #if CONFIG_GFXNVIDIA == 1
 	PROGRAMMER_GFXNVIDIA,
 #endif
@@ -73,6 +73,9 @@
 #if CONFIG_RAYER_SPI == 1
 	PROGRAMMER_RAYER_SPI,
 #endif
+#if CONFIG_NICINTEL_SPI == 1
+	PROGRAMMER_NICINTEL_SPI,
+#endif
 	PROGRAMMER_INVALID /* This must always be the last entry. */
 };
 
@@ -110,6 +113,9 @@
 #if CONFIG_RAYER_SPI == 1
 	BITBANG_SPI_MASTER_RAYER,
 #endif
+#if CONFIG_NICINTEL_SPI == 1
+	BITBANG_SPI_MASTER_NICINTEL,
+#endif
 #if CONFIG_INTERNAL == 1
 #if defined(__i386__) || defined(__x86_64__)
 	BITBANG_SPI_MASTER_MCP,
@@ -207,7 +213,7 @@
 #endif
 
 /* print.c */
-#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT >= 1
+#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_NICINTEL_SPI >= 1
 void print_supported_pcidevs(const struct pcidev_status *devs);
 #endif
 
@@ -378,6 +384,16 @@
 extern const struct pcidev_status nics_natsemi[];
 #endif
 
+/* nicintel_spi.c */
+#if CONFIG_NICINTEL_SPI == 1
+int nicintel_spi_init(void);
+int nicintel_spi_shutdown(void);
+int nicintel_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+	const unsigned char *writearr, unsigned char *readarr);
+void nicintel_spi_chip_writeb(uint8_t val, chipaddr addr);
+extern const struct pcidev_status nics_intel_spi[];
+#endif
+
 /* satasii.c */
 #if CONFIG_SATASII == 1
 int satasii_init(void);
@@ -494,6 +510,9 @@
 #if CONFIG_RAYER_SPI == 1
 	SPI_CONTROLLER_RAYER,
 #endif
+#if CONFIG_NICINTEL_SPI == 1
+	SPI_CONTROLLER_NICINTEL,
+#endif
 	SPI_CONTROLLER_INVALID /* This must always be the last entry. */
 };
 extern const int spi_programmer_count;
Index: print.c
===================================================================
--- print.c	(revision 1138)
+++ print.c	(working copy)
@@ -264,6 +264,9 @@
 #if CONFIG_FT2232_SPI == 1
 		print_supported_usbdevs(devs_ft2232spi);
 #endif
+#if CONFIG_NICINTEL_SPI == 1
+		print_supported_pcidevs(nics_intel_spi);
+#endif
 }
 
 #if CONFIG_INTERNAL == 1
