[flashrom] [PATCH] Register opaque and parallel/LPC/FWH programmers

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Wed Nov 2 04:36:03 CET 2011


Just to show how it should look like once all type-specific programmer
registration patches are applied.

The generic programmer registration patch will live on top of this.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: flashrom-register_all_programmers/flash.h
===================================================================
--- flashrom-register_all_programmers/flash.h	(Revision 1457)
+++ flashrom-register_all_programmers/flash.h	(Arbeitskopie)
@@ -62,8 +62,9 @@
 	BUS_LPC		= 1 << 1,
 	BUS_FWH		= 1 << 2,
 	BUS_SPI		= 1 << 3,
+	BUS_PROG	= 1 << 4,
 	BUS_NONSPI	= BUS_PARALLEL | BUS_LPC | BUS_FWH,
-	BUS_UNKNOWN	= BUS_PARALLEL | BUS_LPC | BUS_FWH | BUS_SPI,
+	BUS_UNKNOWN	= BUS_PARALLEL | BUS_LPC | BUS_FWH | BUS_SPI | BUS_PROG,
 };
 
 /*
Index: flashrom-register_all_programmers/drkaiser.c
===================================================================
--- flashrom-register_all_programmers/drkaiser.c	(Revision 1457)
+++ flashrom-register_all_programmers/drkaiser.c	(Arbeitskopie)
@@ -39,6 +39,19 @@
 
 static uint8_t *drkaiser_bar;
 
+static const struct par_programmer par_programmer_drkaiser = {
+		.chip_readb		= drkaiser_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= drkaiser_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int drkaiser_shutdown(void *data)
 {
 	physunmap(drkaiser_bar, DRKAISER_MEMMAP_SIZE);
@@ -64,7 +77,8 @@
 	drkaiser_bar = physmap("Dr. Kaiser PC-Waechter flash memory",
 			       addr, DRKAISER_MEMMAP_SIZE);
 
-	buses_supported = BUS_PARALLEL;
+	register_par_programmer(&par_programmer_drkaiser, BUS_PARALLEL);
+	max_rom_decode.parallel = 131072;
 
 	if (register_shutdown(drkaiser_shutdown, NULL))
 		return 1;
Index: flashrom-register_all_programmers/it87spi.c
===================================================================
--- flashrom-register_all_programmers/it87spi.c	(Revision 1457)
+++ flashrom-register_all_programmers/it87spi.c	(Arbeitskopie)
@@ -192,7 +192,7 @@
 	free(portpos);
 	exit_conf_mode_ite(port);
 	it8716f_flashport = flashport;
-	if (buses_supported & BUS_SPI)
+	if (internal_buses_supported & BUS_SPI)
 		msg_pdbg("Overriding chipset SPI with IT87 SPI.\n");
 	/* FIXME: Add the SPI bus or replace the other buses with it? */
 	register_spi_programmer(&spi_programmer_it87xx);
Index: flashrom-register_all_programmers/gfxnvidia.c
===================================================================
--- flashrom-register_all_programmers/gfxnvidia.c	(Revision 1457)
+++ flashrom-register_all_programmers/gfxnvidia.c	(Arbeitskopie)
@@ -61,6 +61,19 @@
 	{},
 };
 
+static const struct par_programmer par_programmer_gfxnvidia = {
+		.chip_readb		= gfxnvidia_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= gfxnvidia_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int gfxnvidia_shutdown(void *data)
 {
 	physunmap(nvidia_bar, GFXNVIDIA_MEMMAP_SIZE);
@@ -94,7 +107,7 @@
 	reg32 &= ~(1 << 0);
 	rpci_write_long(pcidev_dev, 0x50, reg32);
 
-	buses_supported = BUS_PARALLEL;
+	register_par_programmer(&par_programmer_gfxnvidia, BUS_PARALLEL);
 
 	/* Write/erase doesn't work. */
 	programmer_may_write = 0;
Index: flashrom-register_all_programmers/serprog.c
===================================================================
--- flashrom-register_all_programmers/serprog.c	(Revision 1457)
+++ flashrom-register_all_programmers/serprog.c	(Arbeitskopie)
@@ -309,6 +309,21 @@
 	.write_256	= default_spi_write_256,
 };
 
+static const struct par_programmer par_programmer_serprog = {
+		.chip_readb		= serprog_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= serprog_chip_readn,
+		.chip_writeb		= serprog_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
+static enum chipbustype serprog_buses_supported = BUS_NONE;
+
 int serprog_init(void)
 {
 	uint16_t iface;
@@ -400,11 +415,13 @@
 
 	if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) {
 		msg_perr("Error: NAK to query interface version\n");
+		// FIXME: Clean up and return an error instead.
 		exit(1);
 	}
 
 	if (iface != 1) {
 		msg_perr("Error: Unknown interface version: %d\n", iface);
+		// FIXME: Clean up and return an error instead.
 		exit(1);
 	}
 
@@ -412,28 +429,34 @@
 
 	if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) {
 		msg_perr("Error: query command map not supported\n");
+		// FIXME: Clean up and return an error instead.
 		exit(1);
 	}
 
 	sp_check_avail_automatic = 1;
 
-
+	/* FIXME: This assumes that serprog device bustypes are always
+	 * identical with flashrom bustype enums and that they all fit
+	 * in a single byte.
+	 */
 	if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) {
 		msg_perr("Warning: NAK to query supported buses\n");
 		c = BUS_NONSPI;	/* A reasonable default for now. */
 	}
-	buses_supported = c;
+	serprog_buses_supported = c;
+
 	msg_pdbg(MSGHEADER "Bus support: parallel=%s, LPC=%s, FWH=%s, SPI=%s\n",
 		 (c & BUS_PARALLEL) ? "on" : "off",
 		 (c & BUS_LPC) ? "on" : "off",
 		 (c & BUS_FWH) ? "on" : "off",
 		 (c & BUS_SPI) ? "on" : "off");
 	/* Check for the minimum operational set of commands. */
-	if (buses_supported & BUS_SPI) {
+	if (serprog_buses_supported & BUS_SPI) {
 		uint8_t bt = BUS_SPI;
 		if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) {
 			msg_perr("Error: SPI operation not supported while the "
 				 "bustype is SPI\n");
+			// FIXME: Clean up and return an error instead.
 			exit(1);
 		}
 		/* Success of any of these commands is optional. We don't need
@@ -461,21 +484,22 @@
 			spi_programmer_serprog.max_data_read = v;
 			msg_pdbg(MSGHEADER "Maximum read-n length is %d\n", v);
 		}
-		bt = buses_supported;
+		bt = serprog_buses_supported;
 		sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL);
-		register_spi_programmer(&spi_programmer_serprog);
 	}
 
-	if (buses_supported & BUS_NONSPI) {
+	if (serprog_buses_supported & BUS_NONSPI) {
 		if (sp_check_commandavail(S_CMD_O_INIT) == 0) {
 			msg_perr("Error: Initialize operation buffer "
 				 "not supported\n");
+			// FIXME: Clean up and return an error instead.
 			exit(1);
 		}
 
 		if (sp_check_commandavail(S_CMD_O_DELAY) == 0) {
 			msg_perr("Error: Write to opbuf: "
 				 "delay not supported\n");
+			// FIXME: Clean up and return an error instead.
 			exit(1);
 		}
 
@@ -483,17 +507,20 @@
 
 		if (sp_check_commandavail(S_CMD_R_BYTE) == 0) {
 			msg_perr("Error: Single byte read not supported\n");
+			// FIXME: Clean up and return an error instead.
 			exit(1);
 		}
 		/* This could be translated to single byte reads (if missing),
 		 * but now we don't support that. */
 		if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) {
 			msg_perr("Error: Read n bytes not supported\n");
+			// FIXME: Clean up and return an error instead.
 			exit(1);
 		}
 		if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) {
 			msg_perr("Error: Write to opbuf: "
 				 "write byte not supported\n");
+			// FIXME: Clean up and return an error instead.
 			exit(1);
 		}
 
@@ -513,6 +540,7 @@
 			if (!sp_write_n_buf) {
 				msg_perr("Error: cannot allocate memory for "
 					 "Write-n buffer\n");
+				// FIXME: Clean up and return an error instead.
 				exit(1);
 			}
 			sp_write_n_bytes = 0;
@@ -551,11 +579,13 @@
 		if (sp_check_commandavail(S_CMD_O_EXEC) == 0) {
 			msg_perr("Error: Execute operation buffer not "
 				 "supported\n");
+			// FIXME: Clean up and return an error instead.
 			exit(1);
 		}
 
 		if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) {
 			msg_perr("Error: NAK to initialize operation buffer\n");
+			// FIXME: Clean up and return an error instead.
 			exit(1);
 		}
 
@@ -572,6 +602,11 @@
 	sp_streamed_transmit_ops = 0;
 	sp_streamed_transmit_bytes = 0;
 	sp_opbuf_usage = 0;
+	if (serprog_buses_supported & BUS_SPI)
+		register_spi_programmer(&spi_programmer_serprog);
+	if (serprog_buses_supported & BUS_NONSPI)
+		register_par_programmer(&par_programmer_serprog,
+					serprog_buses_supported & BUS_NONSPI);
 	return 0;
 }
 
Index: flashrom-register_all_programmers/nicrealtek.c
===================================================================
--- flashrom-register_all_programmers/nicrealtek.c	(Revision 1457)
+++ flashrom-register_all_programmers/nicrealtek.c	(Arbeitskopie)
@@ -36,6 +36,19 @@
 	{},
 };
 
+static const struct par_programmer par_programmer_nicrealtek = {
+		.chip_readb		= nicrealtek_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= nicrealtek_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int nicrealtek_shutdown(void *data)
 {
 	/* FIXME: We forgot to disable software access again. */
@@ -50,7 +63,7 @@
 
 	io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, nics_realtek);
 
-	buses_supported = BUS_PARALLEL;
+	register_par_programmer(&par_programmer_nicrealtek, BUS_PARALLEL);
 
 	if (register_shutdown(nicrealtek_shutdown, NULL))
 		return 1;
Index: flashrom-register_all_programmers/satamv.c
===================================================================
--- flashrom-register_all_programmers/satamv.c	(Revision 1457)
+++ flashrom-register_all_programmers/satamv.c	(Arbeitskopie)
@@ -41,6 +41,19 @@
 #define PCI_BAR2_CONTROL		0x00c08
 #define GPIO_PORT_CONTROL		0x104f0
 
+static const struct par_programmer par_programmer_satamv = {
+		.chip_readb		= satamv_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= satamv_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int satamv_shutdown(void *data)
 {
 	physunmap(mv_bar, 0x20000);
@@ -137,7 +150,7 @@
 	mv_iobar = tmp & 0xffff;
 	msg_pspew("Activating I/O BAR at 0x%04x\n", mv_iobar);
 
-	buses_supported = BUS_PARALLEL;
+	register_par_programmer(&par_programmer_satamv, BUS_PARALLEL);
 
 	/* 512 kByte with two 8-bit latches, and
 	 * 4 MByte with additional 3-bit latch. */
Index: flashrom-register_all_programmers/Makefile
===================================================================
--- flashrom-register_all_programmers/Makefile	(Revision 1457)
+++ flashrom-register_all_programmers/Makefile	(Arbeitskopie)
@@ -242,7 +242,7 @@
 CHIP_OBJS = jedec.o stm50flw0x0x.o w39.o w29ee011.o \
 	sst28sf040.o m29f400bt.o 82802ab.o pm49fl00x.o \
 	sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o sharplhf00l04.o \
-	a25.o at25.o
+	a25.o at25.o opaque.o
 
 LIB_OBJS = layout.o
 
Index: flashrom-register_all_programmers/dummyflasher.c
===================================================================
--- flashrom-register_all_programmers/dummyflasher.c	(Revision 1457)
+++ flashrom-register_all_programmers/dummyflasher.c	(Arbeitskopie)
@@ -75,6 +75,21 @@
 	.write_256	= dummy_spi_write_256,
 };
 
+static const struct par_programmer par_programmer_dummy = {
+		.chip_readb		= dummy_chip_readb,
+		.chip_readw		= dummy_chip_readw,
+		.chip_readl		= dummy_chip_readl,
+		.chip_readn		= dummy_chip_readn,
+		.chip_writeb		= dummy_chip_writeb,
+		.chip_writew		= dummy_chip_writew,
+		.chip_writel		= dummy_chip_writel,
+		.chip_writen		= dummy_chip_writen,
+		.map_flash_region	= dummy_map,
+		.unmap_flash_region	= dummy_unmap,
+};
+
+enum chipbustype dummy_buses_supported = BUS_NONE;
+
 static int dummy_shutdown(void *data)
 {
 	msg_pspew("%s\n", __func__);
@@ -108,24 +123,29 @@
 	/* Convert the parameters to lowercase. */
 	tolower_string(bustext);
 
-	buses_supported = BUS_NONE;
+	dummy_buses_supported = BUS_NONE;
 	if (strstr(bustext, "parallel")) {
-		buses_supported |= BUS_PARALLEL;
+		dummy_buses_supported |= BUS_PARALLEL;
 		msg_pdbg("Enabling support for %s flash.\n", "parallel");
 	}
 	if (strstr(bustext, "lpc")) {
-		buses_supported |= BUS_LPC;
+		dummy_buses_supported |= BUS_LPC;
 		msg_pdbg("Enabling support for %s flash.\n", "LPC");
 	}
 	if (strstr(bustext, "fwh")) {
-		buses_supported |= BUS_FWH;
+		dummy_buses_supported |= BUS_FWH;
 		msg_pdbg("Enabling support for %s flash.\n", "FWH");
 	}
+	if (dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH))
+		register_par_programmer(&par_programmer_dummy,
+					dummy_buses_supported &
+						(BUS_PARALLEL | BUS_LPC |
+						 BUS_FWH));
 	if (strstr(bustext, "spi")) {
 		register_spi_programmer(&spi_programmer_dummyflasher);
 		msg_pdbg("Enabling support for %s flash.\n", "SPI");
 	}
-	if (buses_supported == BUS_NONE)
+	if (dummy_buses_supported == BUS_NONE)
 		msg_pdbg("Support for all flash bus types disabled.\n");
 	free(bustext);
 
Index: flashrom-register_all_programmers/cli_classic.c
===================================================================
--- flashrom-register_all_programmers/cli_classic.c	(Revision 1457)
+++ flashrom-register_all_programmers/cli_classic.c	(Arbeitskopie)
@@ -443,7 +443,10 @@
 		ret = 1;
 		goto out_shutdown;
 	}
+	msg_pdbg("This programmer supports the following protocols: %s.\n",
+		 flashbuses_to_text(buses_supported));
 
+
 	for (i = 0; i < ARRAY_SIZE(flashes); i++) {
 		startchip = probe_flash(startchip, &flashes[i], 0);
 		if (startchip == -1)
Index: flashrom-register_all_programmers/internal.c
===================================================================
--- flashrom-register_all_programmers/internal.c	(Revision 1457)
+++ flashrom-register_all_programmers/internal.c	(Arbeitskopie)
@@ -127,6 +127,21 @@
 int is_laptop = 0;
 int laptop_ok = 0;
 
+static const struct par_programmer par_programmer_internal = {
+		.chip_readb		= internal_chip_readb,
+		.chip_readw		= internal_chip_readw,
+		.chip_readl		= internal_chip_readl,
+		.chip_readn		= internal_chip_readn,
+		.chip_writeb		= internal_chip_writeb,
+		.chip_writew		= internal_chip_writew,
+		.chip_writel		= internal_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= physmap,
+		.unmap_flash_region	= physunmap,
+};
+
+enum chipbustype internal_buses_supported = BUS_NONE;
+
 static int internal_shutdown(void *data)
 {
 	release_io_perms();
@@ -191,9 +206,10 @@
 		return 1;
 
 	/* Default to Parallel/LPC/FWH flash devices. If a known host controller
-	 * is found, the init routine sets the buses_supported bitfield.
+	 * is found, the host controller init routine sets the
+	 * internal_buses_supported bitfield.
 	 */
-	buses_supported = BUS_NONSPI;
+	internal_buses_supported = BUS_NONSPI;
 
 	/* Initialize PCI access for flash enables */
 	pacc = pci_alloc();	/* Get the pci_access structure */
@@ -287,6 +303,7 @@
 	 * Besides that, we don't check the board enable return code either.
 	 */
 #if defined(__i386__) || defined(__x86_64__) || defined (__mips)
+	register_par_programmer(&par_programmer_internal, internal_buses_supported);
 	return 0;
 #else
 	msg_perr("Your platform is not supported yet for the internal "
Index: flashrom-register_all_programmers/ichspi.c
===================================================================
--- flashrom-register_all_programmers/ichspi.c	(Revision 1457)
+++ flashrom-register_all_programmers/ichspi.c	(Arbeitskopie)
@@ -1523,7 +1523,7 @@
 	ich_spibar = physmap("VT8237S MMIO registers", mmio_base, 0x70);
 
 	/* Not sure if it speaks all these bus protocols. */
-	buses_supported = BUS_LPC | BUS_FWH;
+	internal_buses_supported = BUS_LPC | BUS_FWH;
 	register_spi_programmer(&spi_programmer_via);
 
 	msg_pdbg("0x00: 0x%04x     (SPIS)\n", mmio_readw(ich_spibar + 0));
Index: flashrom-register_all_programmers/opaque.c
===================================================================
--- flashrom-register_all_programmers/opaque.c	(Revision 0)
+++ flashrom-register_all_programmers/opaque.c	(Revision 0)
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2011 Carl-Daniel Hailfinger
+ *
+ * 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
+ */
+
+/*
+ * Contains the opaque programmer framework.
+ * An opaque programmer is a programmer which does not provide direct access
+ * to the flash chip and which abstracts all flash chip properties into a
+ * programmer specific interface.
+ */
+
+#include <strings.h>
+#include <string.h>
+#include "flash.h"
+#include "flashchips.h"
+#include "chipdrivers.h"
+#include "programmer.h"
+
+const struct opaque_programmer opaque_programmer_none = {
+	.max_data_read = MAX_DATA_UNSPECIFIED,
+	.max_data_write = MAX_DATA_UNSPECIFIED,
+	.probe = NULL,
+	.read = NULL,
+	.write = NULL,
+};
+
+const struct opaque_programmer *opaque_programmer = &opaque_programmer_none;
+
+int probe_opaque(struct flashchip *flash)
+{
+	if (!opaque_programmer->probe) {
+		msg_perr("%s called, but this is not an opaque programmer. "
+			 "Please report a bug at flashrom at flashrom.org\n",
+			 __func__);
+		return 0;
+	}
+
+	return opaque_programmer->probe(flash);
+}
+
+int read_opaque(struct flashchip *flash, uint8_t *buf, int start, int len)
+{
+	if (!opaque_programmer->read) {
+		msg_perr("%s called, but this is not an opaque programmer. "
+			 "Please report a bug at flashrom at flashrom.org\n",
+			 __func__);
+		return 1;
+	}
+	return opaque_programmer->read(flash, buf, start, len);
+}
+
+int write_opaque(struct flashchip *flash, uint8_t *buf, int start, int len)
+{
+	if (!opaque_programmer->write) {
+		msg_perr("%s called, but this is not an opaque programmer. "
+			 "Please report a bug at flashrom at flashrom.org\n",
+			 __func__);
+		return 1;
+	}
+	return opaque_programmer->write(flash, buf, start, len);
+}
+
+int erase_opaque(struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen)
+{
+	if (!opaque_programmer->erase) {
+		msg_perr("%s called, but this is not an opaque programmer. "
+			 "Please report a bug at flashrom at flashrom.org\n",
+			 __func__);
+		return 1;
+	}
+	return opaque_programmer->erase(flash, blockaddr, blocklen);
+}
+
+void register_opaque_programmer(const struct opaque_programmer *pgm)
+{
+	opaque_programmer = pgm;
+	buses_supported |= BUS_PROG;
+}
Index: flashrom-register_all_programmers/nicnatsemi.c
===================================================================
--- flashrom-register_all_programmers/nicnatsemi.c	(Revision 1457)
+++ flashrom-register_all_programmers/nicnatsemi.c	(Arbeitskopie)
@@ -35,6 +35,19 @@
 	{},
 };
 
+static const struct par_programmer par_programmer_nicnatsemi = {
+		.chip_readb		= nicnatsemi_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= nicnatsemi_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int nicnatsemi_shutdown(void *data)
 {
 	pci_cleanup(pacc);
@@ -48,7 +61,7 @@
 
 	io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, nics_natsemi);
 
-	buses_supported = BUS_PARALLEL;
+	register_par_programmer(&par_programmer_nicnatsemi, BUS_PARALLEL);
 
 	/* The datasheet shows address lines MA0-MA16 in one place and MA0-MA15
 	 * in another. My NIC has MA16 connected to A16 on the boot ROM socket
Index: flashrom-register_all_programmers/it85spi.c
===================================================================
--- flashrom-register_all_programmers/it85spi.c	(Revision 1457)
+++ flashrom-register_all_programmers/it85spi.c	(Arbeitskopie)
@@ -257,8 +257,10 @@
 	INDIRECT_A3(shm_io_base, (base >> 24));
 #endif
 #ifdef LPC_MEMORY
-	base = (chipaddr)programmer_map_flash_region("it85 communication",
-						     0xFFFFF000, 0x1000);
+	/* FIXME: We should block accessing that region for anything else.
+	 * Major TODO here, and it will be a lot of work.
+	 */
+	base = (chipaddr)physmap("it85 communication", 0xFFFFF000, 0x1000);
 	msg_pdbg("%s():%d base=0x%08x\n", __func__, __LINE__,
 	         (unsigned int)base);
 	ce_high = (unsigned char *)(base + 0xE00);  /* 0xFFFFFE00 */
@@ -285,18 +287,26 @@
 {
 	int ret;
 
-	if (!(buses_supported & BUS_FWH)) {
+	if (!(internal_buses_supported & BUS_FWH)) {
 		msg_pdbg("%s():%d buses not support FWH\n", __func__, __LINE__);
 		return 1;
 	}
 	ret = it85xx_spi_common_init(s);
 	msg_pdbg("FWH: %s():%d ret=%d\n", __func__, __LINE__, ret);
 	if (!ret) {
-		msg_pdbg("%s():%d buses_supported=0x%x\n", __func__, __LINE__,
-		          buses_supported);
-		if (buses_supported & BUS_FWH)
-			msg_pdbg("Overriding chipset SPI with IT85 FWH|SPI.\n");
-		/* Really leave FWH enabled? */
+		msg_pdbg("%s: internal_buses_supported=0x%x\n", __func__,
+		          internal_buses_supported);
+		/* Check for FWH because IT85 listens to FWH cycles.
+		 * FIXME: The big question is whether FWH cycles are necessary
+		 * for communication even if LPC_IO is defined.
+		 */
+		if (internal_buses_supported & BUS_FWH)
+			msg_pdbg("Registering IT85 SPI.\n");
+		/* FIXME: Really leave FWH enabled? We can't use this region
+		 * anymore since accessing it would mess up IT85 communication.
+		 * If we decide to disable FWH for this region, we should print
+		 * a debug message about it.
+		 */
 		/* Set this as SPI controller. */
 		register_spi_programmer(&spi_programmer_it85xx);
 	}
Index: flashrom-register_all_programmers/atahpt.c
===================================================================
--- flashrom-register_all_programmers/atahpt.c	(Revision 1457)
+++ flashrom-register_all_programmers/atahpt.c	(Arbeitskopie)
@@ -40,6 +40,19 @@
 	{},
 };
 
+static const struct par_programmer par_programmer_atahpt = {
+		.chip_readb		= atahpt_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= atahpt_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int atahpt_shutdown(void *data)
 {
 	/* Flash access is disabled automatically by PCI restore. */
@@ -61,7 +74,7 @@
 	reg32 |= (1 << 24);
 	rpci_write_long(pcidev_dev, REG_FLASH_ACCESS, reg32);
 
-	buses_supported = BUS_PARALLEL;
+	register_par_programmer(&par_programmer_atahpt, BUS_PARALLEL);
 
 	if (register_shutdown(atahpt_shutdown, NULL))
 		return 1;
Index: flashrom-register_all_programmers/flashchips.c
===================================================================
--- flashrom-register_all_programmers/flashchips.c	(Revision 1457)
+++ flashrom-register_all_programmers/flashchips.c	(Arbeitskopie)
@@ -8872,8 +8872,30 @@
 		.read		= read_memmapped,
 		.voltage	= {3000, 3600}, /* Also has 12V fast program */
 	},
-
+#if defined(CONFIG_INTERNAL) && (defined(__i386__) || defined(__x86_64__))
 	{
+		.vendor		= "Programmer",
+		.name		= "Opaque flash chip",
+		.bustype	= BUS_PROG,
+		.manufacture_id	= PROGMANUF_ID,
+		.model_id	= PROGDEV_ID,
+		.total_size	= 0,
+		.page_size	= 256,
+		/* probe is assumed to work, rest will be filled in by probe */
+		.tested		= TEST_OK_PROBE,
+		.probe		= probe_opaque,
+		/* eraseblock sizes will be set by the probing function */
+		.block_erasers	=
+		{
+			{
+				.block_erase = erase_opaque,
+			}
+		},
+		.write		= write_opaque,
+		.read		= read_opaque,
+	},
+#endif // defined(CONFIG_INTERNAL) && (defined(__i386__) || defined(__x86_64__))
+	{
 		.vendor		= "AMIC",
 		.name		= "unknown AMIC SPI chip",
 		.bustype	= BUS_SPI,
@@ -9005,6 +9027,7 @@
 		.probe		= probe_spi_rdid,
 		.write		= NULL,
 	},
+
 	{
 		.vendor		= "Generic",
 		.name		= "unknown SPI chip (REMS)",
Index: flashrom-register_all_programmers/flashchips.h
===================================================================
--- flashrom-register_all_programmers/flashchips.h	(Revision 1457)
+++ flashrom-register_all_programmers/flashchips.h	(Arbeitskopie)
@@ -646,4 +646,7 @@
 #define WINBOND_W49V002A	0xB0
 #define WINBOND_W49V002FA	0x32
 
+#define PROGMANUF_ID		0xFFFE	/* dummy ID for opaque chips behind a programmer */
+#define PROGDEV_ID		0x01	/* dummy ID for opaque chips behind a programmer */
+
 #endif /* !FLASHCHIPS_H */
Index: flashrom-register_all_programmers/nic3com.c
===================================================================
--- flashrom-register_all_programmers/nic3com.c	(Revision 1457)
+++ flashrom-register_all_programmers/nic3com.c	(Arbeitskopie)
@@ -55,6 +55,19 @@
 	{},
 };
 
+static const struct par_programmer par_programmer_nic3com = {
+		.chip_readb		= nic3com_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= nic3com_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int nic3com_shutdown(void *data)
 {
 	/* 3COM 3C90xB cards need a special fixup. */
@@ -96,8 +109,8 @@
 	 */
 	OUTW(SELECT_REG_WINDOW + 0, io_base_addr + INT_STATUS);
 
-	buses_supported = BUS_PARALLEL;
 	max_rom_decode.parallel = 128 * 1024;
+	register_par_programmer(&par_programmer_nic3com, BUS_PARALLEL);
 
 	if (register_shutdown(nic3com_shutdown, NULL))
 		return 1;
Index: flashrom-register_all_programmers/satasii.c
===================================================================
--- flashrom-register_all_programmers/satasii.c	(Revision 1457)
+++ flashrom-register_all_programmers/satasii.c	(Arbeitskopie)
@@ -42,6 +42,19 @@
 	{},
 };
 
+static const struct par_programmer par_programmer_satasii = {
+		.chip_readb		= satasii_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= satasii_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int satasii_shutdown(void *data)
 {
 	physunmap(sii_bar, SATASII_MEMMAP_SIZE);
@@ -76,7 +89,7 @@
 	if ((id != 0x0680) && (!(pci_mmio_readl(sii_bar) & (1 << 26))))
 		msg_pinfo("Warning: Flash seems unconnected.\n");
 
-	buses_supported = BUS_PARALLEL;
+	register_par_programmer(&par_programmer_satasii, BUS_PARALLEL);
 
 	if (register_shutdown(satasii_shutdown, NULL))
 		return 1;
Index: flashrom-register_all_programmers/chipset_enable.c
===================================================================
--- flashrom-register_all_programmers/chipset_enable.c	(Revision 1457)
+++ flashrom-register_all_programmers/chipset_enable.c	(Arbeitskopie)
@@ -213,7 +213,7 @@
 	uint16_t old, new;
 	uint16_t xbcs = 0x4e;	/* X-Bus Chip Select register. */
 
-	buses_supported = BUS_PARALLEL;
+	internal_buses_supported = BUS_PARALLEL;
 
 	old = pci_read_word(dev, xbcs);
 
@@ -303,7 +303,7 @@
 	 * FWH_DEC_EN1, but they are called FB_SEL1, FB_SEL2, FB_DEC_EN1 and
 	 * FB_DEC_EN2.
 	 */
-	buses_supported = BUS_FWH;
+	internal_buses_supported = BUS_FWH;
 	return enable_flash_ich(dev, name, 0x4e);
 }
 
@@ -412,9 +412,9 @@
 	msg_pdbg("\nMaximum FWH chip size: 0x%x bytes", max_rom_decode.fwh);
 
 	/* If we're called by enable_flash_ich_dc_spi, it will override
-	 * buses_supported anyway.
+	 * internal_buses_supported anyway.
 	 */
-	buses_supported = BUS_FWH;
+	internal_buses_supported = BUS_FWH;
 	return enable_flash_ich(dev, name, 0xdc);
 }
 
@@ -434,7 +434,7 @@
 	if (new != old)
 		rpci_write_byte(dev, 0xd9, new);
 
-	buses_supported = BUS_FWH;
+	internal_buses_supported = BUS_FWH;
 	return 0;
 }
 
@@ -468,12 +468,11 @@
 	bnt = mmio_readl(rcrb + 0x3410);
 	if (bnt & 0x02) {
 		/* If strapped to LPC, no SPI initialization is required */
-		buses_supported = BUS_FWH;
+		internal_buses_supported = BUS_FWH;
 		return 0;
 	}
 
 	/* This adds BUS_SPI */
-	buses_supported = BUS_SPI;
 	if (ich_init_spi(dev, tmp, rcrb, 7) != 0) {
 		if (!ret)
 			ret = ERROR_NONFATAL;
@@ -556,7 +555,7 @@
 	 * time. At least not with our current code. So we prevent searching
 	 * on ICH7 when the southbridge is strapped to LPC
 	 */
-	buses_supported = BUS_FWH;
+	internal_buses_supported = BUS_FWH;
 	if (ich_generation == 7) {
 		if (bbs == 0x03) {
 			/* If strapped to LPC, no further SPI initialization is
@@ -564,7 +563,7 @@
 			return ret;
 		} else {
 			/* Disable LPC/FWH if strapped to PCI or SPI */
-			buses_supported = 0;
+			internal_buses_supported = BUS_NONE;
 		}
 	}
 
@@ -667,7 +666,7 @@
 #define CS5530_ENABLE_SA2320		(1 << 2)
 #define CS5530_ENABLE_SA20		(1 << 6)
 
-	buses_supported = BUS_PARALLEL;
+	internal_buses_supported = BUS_PARALLEL;
 	/* Decode 0x000E0000-0x000FFFFF (128 kB), not just 64 kB, and
 	 * decode 0xFF000000-0xFFFFFFFF (16 MB), not just 256 kB.
 	 * FIXME: Should we really touch the low mapping below 1 MB? Flashrom
@@ -820,7 +819,7 @@
 				 (prot & 0xfffff800) + (((prot & 0x7fc) << 8) | 0x3ff));
 	}
 
-	buses_supported = BUS_LPC | BUS_FWH;
+	internal_buses_supported = BUS_LPC | BUS_FWH;
 
 	ret = sb600_probe_spi(dev);
 
@@ -914,7 +913,7 @@
 {
 	uint8_t tmp;
 
-	buses_supported = BUS_PARALLEL;
+	internal_buses_supported = BUS_PARALLEL;
 
 	tmp = INB(0xc06);
 	tmp |= 0x1;
@@ -1014,7 +1013,7 @@
 	switch ((val >> 5) & 0x3) {
 	case 0x0:
 		ret = enable_flash_mcp55(dev, name);
-		buses_supported = BUS_LPC;
+		internal_buses_supported = BUS_LPC;
 		msg_pdbg("Flash bus type is LPC\n");
 		break;
 	case 0x2:
@@ -1022,7 +1021,7 @@
 		/* SPI is added in mcp6x_spi_init if it works.
 		 * Do we really want to disable LPC in this case?
 		 */
-		buses_supported = BUS_NONE;
+		internal_buses_supported = BUS_NONE;
 		msg_pdbg("Flash bus type is SPI\n");
 		msg_pinfo("SPI on this chipset is WIP. Please report any "
 			  "success or failure by mailing us the verbose "
@@ -1030,7 +1029,7 @@
 		break;
 	default:
 		/* Should not happen. */
-		buses_supported = BUS_NONE;
+		internal_buses_supported = BUS_NONE;
 		msg_pdbg("Flash bus type is unknown (none)\n");
 		msg_pinfo("Something went wrong with bus type detection.\n");
 		goto out_msg;
@@ -1323,7 +1322,6 @@
 	struct pci_dev *dev = NULL;
 	int ret = -2;		/* Nothing! */
 	int i;
-	char *s;
 
 	/* Now let's try to find the chipset we have... */
 	for (i = 0; chipset_enables[i].vendor_name != NULL; i++) {
@@ -1375,9 +1373,5 @@
 		}
 	}
 
-	s = flashbuses_to_text(buses_supported);
-	msg_pinfo("This chipset supports the following protocols: %s.\n", s);
-	free(s);
-
 	return ret;
 }
Index: flashrom-register_all_programmers/nicintel.c
===================================================================
--- flashrom-register_all_programmers/nicintel.c	(Revision 1457)
+++ flashrom-register_all_programmers/nicintel.c	(Arbeitskopie)
@@ -43,6 +43,19 @@
 
 #define CSR_FCR 0x0c
 
+static const struct par_programmer par_programmer_nicintel = {
+		.chip_readb		= nicintel_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= nicintel_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
 static int nicintel_shutdown(void *data)
 {
 	physunmap(nicintel_control_bar, NICINTEL_CONTROL_MEMMAP_SIZE);
@@ -93,9 +106,8 @@
 	 */
 	pci_rmmio_writew(0x0001, nicintel_control_bar + CSR_FCR);
 
-	buses_supported = BUS_PARALLEL;
-
 	max_rom_decode.parallel = NICINTEL_MEMMAP_SIZE;
+	register_par_programmer(&par_programmer_nicintel, BUS_PARALLEL);
 
 	return 0;
 
Index: flashrom-register_all_programmers/flashrom.c
===================================================================
--- flashrom-register_all_programmers/flashrom.c	(Revision 1457)
+++ flashrom-register_all_programmers/flashrom.c	(Arbeitskopie)
@@ -66,16 +66,6 @@
 	{
 		.name			= "internal",
 		.init			= internal_init,
-		.map_flash_region	= physmap,
-		.unmap_flash_region	= physunmap,
-		.chip_readb		= internal_chip_readb,
-		.chip_readw		= internal_chip_readw,
-		.chip_readl		= internal_chip_readl,
-		.chip_readn		= internal_chip_readn,
-		.chip_writeb		= internal_chip_writeb,
-		.chip_writew		= internal_chip_writew,
-		.chip_writel		= internal_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -84,16 +74,6 @@
 	{
 		.name			= "dummy",
 		.init			= dummy_init,
-		.map_flash_region	= dummy_map,
-		.unmap_flash_region	= dummy_unmap,
-		.chip_readb		= dummy_chip_readb,
-		.chip_readw		= dummy_chip_readw,
-		.chip_readl		= dummy_chip_readl,
-		.chip_readn		= dummy_chip_readn,
-		.chip_writeb		= dummy_chip_writeb,
-		.chip_writew		= dummy_chip_writew,
-		.chip_writel		= dummy_chip_writel,
-		.chip_writen		= dummy_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -102,16 +82,6 @@
 	{
 		.name			= "nic3com",
 		.init			= nic3com_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= nic3com_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= nic3com_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -122,16 +92,6 @@
 		.name			= "nicrealtek",
 		//.name			= "nicsmc1211",
 		.init			= nicrealtek_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= nicrealtek_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= nicrealtek_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -140,16 +100,6 @@
 	{
 		.name			= "nicnatsemi",
 		.init			= nicnatsemi_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= nicnatsemi_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= nicnatsemi_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -158,16 +108,6 @@
 	{
 		.name			= "gfxnvidia",
 		.init			= gfxnvidia_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= gfxnvidia_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= gfxnvidia_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -176,16 +116,6 @@
 	{
 		.name			= "drkaiser",
 		.init			= drkaiser_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= drkaiser_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= drkaiser_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -194,16 +124,6 @@
 	{
 		.name			= "satasii",
 		.init			= satasii_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= satasii_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= satasii_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -212,16 +132,6 @@
 	{
 		.name			= "atahpt",
 		.init			= atahpt_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= atahpt_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= atahpt_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -230,16 +140,6 @@
 	{
 		.name			= "ft2232_spi",
 		.init			= ft2232_spi_init,
-		.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
@@ -248,16 +148,6 @@
 	{
 		.name			= "serprog",
 		.init			= serprog_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= serprog_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= serprog_chip_readn,
-		.chip_writeb		= serprog_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= serprog_delay,
 	},
 #endif
@@ -266,16 +156,6 @@
 	{
 		.name			= "buspirate_spi",
 		.init			= buspirate_spi_init,
-		.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
@@ -284,16 +164,6 @@
 	{
 		.name			= "dediprog",
 		.init			= dediprog_init,
-		.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
@@ -302,16 +172,6 @@
 	{
 		.name			= "rayer_spi",
 		.init			= rayer_spi_init,
-		.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
@@ -320,16 +180,6 @@
 	{
 		.name			= "nicintel",
 		.init			= nicintel_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= nicintel_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= nicintel_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -338,16 +188,6 @@
 	{
 		.name			= "nicintel_spi",
 		.init			= nicintel_spi_init,
-		.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
@@ -356,16 +196,6 @@
 	{
 		.name			= "ogp_spi",
 		.init			= ogp_spi_init,
-		.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
@@ -374,16 +204,6 @@
 	{
 		.name			= "satamv",
 		.init			= satamv_init,
-		.map_flash_region	= fallback_map,
-		.unmap_flash_region	= fallback_unmap,
-		.chip_readb		= satamv_chip_readb,
-		.chip_readw		= fallback_chip_readw,
-		.chip_readl		= fallback_chip_readl,
-		.chip_readn		= fallback_chip_readn,
-		.chip_writeb		= satamv_chip_writeb,
-		.chip_writew		= fallback_chip_writew,
-		.chip_writel		= fallback_chip_writel,
-		.chip_writen		= fallback_chip_writen,
 		.delay			= internal_delay,
 	},
 #endif
@@ -392,16 +212,6 @@
 	{
 		.name			= "linux_spi",
 		.init			= linux_spi_init,
-		.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
@@ -502,53 +312,52 @@
 void *programmer_map_flash_region(const char *descr, unsigned long phys_addr,
 				  size_t len)
 {
-	return programmer_table[programmer].map_flash_region(descr,
-							     phys_addr, len);
+	return par_programmer->map_flash_region(descr, phys_addr, len);
 }
 
 void programmer_unmap_flash_region(void *virt_addr, size_t len)
 {
-	programmer_table[programmer].unmap_flash_region(virt_addr, len);
+	par_programmer->unmap_flash_region(virt_addr, len);
 }
 
 void chip_writeb(uint8_t val, chipaddr addr)
 {
-	programmer_table[programmer].chip_writeb(val, addr);
+	par_programmer->chip_writeb(val, addr);
 }
 
 void chip_writew(uint16_t val, chipaddr addr)
 {
-	programmer_table[programmer].chip_writew(val, addr);
+	par_programmer->chip_writew(val, addr);
 }
 
 void chip_writel(uint32_t val, chipaddr addr)
 {
-	programmer_table[programmer].chip_writel(val, addr);
+	par_programmer->chip_writel(val, addr);
 }
 
 void chip_writen(uint8_t *buf, chipaddr addr, size_t len)
 {
-	programmer_table[programmer].chip_writen(buf, addr, len);
+	par_programmer->chip_writen(buf, addr, len);
 }
 
 uint8_t chip_readb(const chipaddr addr)
 {
-	return programmer_table[programmer].chip_readb(addr);
+	return par_programmer->chip_readb(addr);
 }
 
 uint16_t chip_readw(const chipaddr addr)
 {
-	return programmer_table[programmer].chip_readw(addr);
+	return par_programmer->chip_readw(addr);
 }
 
 uint32_t chip_readl(const chipaddr addr)
 {
-	return programmer_table[programmer].chip_readl(addr);
+	return par_programmer->chip_readl(addr);
 }
 
 void chip_readn(uint8_t *buf, chipaddr addr, size_t len)
 {
-	programmer_table[programmer].chip_readn(buf, addr, len);
+	par_programmer->chip_readn(buf, addr, len);
 }
 
 void programmer_delay(int usecs)
@@ -1156,7 +965,7 @@
 		return -1;
 
 #if CONFIG_INTERNAL == 1
-	if (programmer_table[programmer].map_flash_region == physmap)
+	if (par_programmer->map_flash_region == physmap)
 		snprintf(location, sizeof(location), "at physical address 0x%lx", base);
 	else
 #endif
Index: flashrom-register_all_programmers/programmer.c
===================================================================
--- flashrom-register_all_programmers/programmer.c	(Revision 1457)
+++ flashrom-register_all_programmers/programmer.c	(Arbeitskopie)
@@ -19,7 +19,23 @@
  */
 
 #include "flash.h"
+#include "programmer.h"
 
+static const struct par_programmer par_programmer_none = {
+		.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,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+};
+
+const struct par_programmer *par_programmer = &par_programmer_none;
+
 /* No-op shutdown() for programmers which don't need special handling */
 int noop_shutdown(void)
 {
@@ -96,3 +112,9 @@
 		buf[i] = chip_readb(addr + i);
 	return;
 }
+
+void register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses)
+{
+	par_programmer = pgm;
+	buses_supported |= buses;
+}
Index: flashrom-register_all_programmers/programmer.h
===================================================================
--- flashrom-register_all_programmers/programmer.h	(Revision 1457)
+++ flashrom-register_all_programmers/programmer.h	(Arbeitskopie)
@@ -91,18 +91,6 @@
 
 	int (*init) (void);
 
-	void * (*map_flash_region) (const char *descr, unsigned long phys_addr,
-				    size_t len);
-	void (*unmap_flash_region) (void *virt_addr, size_t len);
-
-	void (*chip_writeb) (uint8_t val, chipaddr addr);
-	void (*chip_writew) (uint16_t val, chipaddr addr);
-	void (*chip_writel) (uint32_t val, chipaddr addr);
-	void (*chip_writen) (uint8_t *buf, chipaddr addr, size_t len);
-	uint8_t (*chip_readb) (const chipaddr addr);
-	uint16_t (*chip_readw) (const chipaddr addr);
-	uint32_t (*chip_readl) (const chipaddr addr);
-	void (*chip_readn) (uint8_t *buf, const chipaddr addr, size_t len);
 	void (*delay) (int usecs);
 };
 
@@ -304,6 +292,7 @@
 extern int force_boardmismatch;
 void probe_superio(void);
 int register_superio(struct superio s);
+extern enum chipbustype internal_buses_supported;
 int internal_init(void);
 void internal_chip_writeb(uint8_t val, chipaddr addr);
 void internal_chip_writew(uint16_t val, chipaddr addr);
@@ -358,7 +347,23 @@
 uint16_t fallback_chip_readw(const chipaddr addr);
 uint32_t fallback_chip_readl(const chipaddr addr);
 void fallback_chip_readn(uint8_t *buf, const chipaddr addr, size_t len);
+struct par_programmer {
+	void (*chip_writeb) (uint8_t val, chipaddr addr);
+	void (*chip_writew) (uint16_t val, chipaddr addr);
+	void (*chip_writel) (uint32_t val, chipaddr addr);
+	void (*chip_writen) (uint8_t *buf, chipaddr addr, size_t len);
+	uint8_t (*chip_readb) (const chipaddr addr);
+	uint16_t (*chip_readw) (const chipaddr addr);
+	uint32_t (*chip_readl) (const chipaddr addr);
+	void (*chip_readn) (uint8_t *buf, const chipaddr addr, size_t len);
 
+	void *(*map_flash_region) (const char *descr, unsigned long phys_addr,
+				   size_t len);
+	void (*unmap_flash_region) (void *virt_addr, size_t len);
+};
+extern const struct par_programmer *par_programmer;
+void register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses);
+
 /* dummyflasher.c */
 #if CONFIG_DUMMY == 1
 int dummy_init(void);
@@ -601,6 +606,19 @@
 int wbsio_check_for_spi(void);
 #endif
 
+/* opaque.c */
+struct opaque_programmer {
+	int max_data_read;
+	int max_data_write;
+	/* Specific functions for this programmer */
+	int (*probe) (struct flashchip *flash);
+	int (*read) (struct flashchip *flash, uint8_t *buf, int start, int len);
+	int (*write) (struct flashchip *flash, uint8_t *buf, int start, int len);
+	int (*erase) (struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen);
+};
+extern const struct opaque_programmer *opaque_programmer;
+void register_opaque_programmer(const struct opaque_programmer *pgm);
+
 /* serprog.c */
 #if CONFIG_SERPROG == 1
 int serprog_init(void);
Index: flashrom-register_all_programmers/chipdrivers.h
===================================================================
--- flashrom-register_all_programmers/chipdrivers.h	(Revision 1457)
+++ flashrom-register_all_programmers/chipdrivers.h	(Arbeitskopie)
@@ -58,6 +58,12 @@
 int spi_write_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize);
 int spi_aai_write(struct flashchip *flash, uint8_t *buf, int start, int len);
 
+/* opaque.c */
+int probe_opaque(struct flashchip *flash);
+int read_opaque(struct flashchip *flash, uint8_t *buf, int start, int len);
+int write_opaque(struct flashchip *flash, uint8_t *buf, int start, int len);
+int erase_opaque(struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen);
+
 /* a25.c */
 int spi_prettyprint_status_register_amic_a25l05p(struct flashchip *flash);
 int spi_prettyprint_status_register_amic_a25l40p(struct flashchip *flash);
Index: flashrom-register_all_programmers/print.c
===================================================================
--- flashrom-register_all_programmers/print.c	(Revision 1457)
+++ flashrom-register_all_programmers/print.c	(Arbeitskopie)
@@ -49,6 +49,8 @@
 			ret = strcat_realloc(ret, "FWH, ");
 		if (bustype & BUS_SPI)
 			ret = strcat_realloc(ret, "SPI, ");
+		if (bustype & BUS_PROG)
+			ret = strcat_realloc(ret, "Programmer-specific, ");
 		if (bustype == BUS_NONE)
 			ret = strcat_realloc(ret, "None, ");
 	}
Index: flashrom-register_all_programmers/board_enable.c
===================================================================
--- flashrom-register_all_programmers/board_enable.c	(Revision 1457)
+++ flashrom-register_all_programmers/board_enable.c	(Arbeitskopie)
@@ -425,7 +425,7 @@
 	/* Check if at least one flash segment is enabled. */
 	if (tmp & 0xf0) {
 		/* The IT8705F will respond to LPC cycles and translate them. */
-		buses_supported = BUS_PARALLEL;
+		internal_buses_supported = BUS_PARALLEL;
 		/* Flash ROM I/F Writes Enable */
 		tmp |= 0x04;
 		msg_pdbg("Enabling IT8705F flash ROM interface write.\n");


-- 
http://www.hailfinger.org/





More information about the flashrom mailing list