[flashrom] [PATCH] generic programmer registration

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Sat Nov 12 16:05:50 CET 2011


Am 11.11.2011 07:42 schrieb Carl-Daniel Hailfinger:
> Please note that this patch breaks every programmer except hwseq because
> we're not passing struct flashchip around yet. To get this working, the
> following changes have to be made:
> - Pass struct flashchip * everywhere (or struct flashctx *), see my
> other patch for that
> - Change parallel-style and SPI programmers to use flash->pgm... instead
> of par_programmer->... and spi_programmer->...
>
> This compiles and should help you review it, but it is not for merge
> until the "struct flashchip * everywhere" patch is in.
> Some code has been removed with #if 0 because I wanted to discuss
> removing it. The final patch will have no #if 0 at all.

This is the complete (hopefully working) patch... the #if 0 is still
there, and the "add struct flashchip * everywhere" patch is mixed in to
get it working.

Once the "struct flashctx *" patch at
http://patchwork.coreboot.org/patch/3452/ is merged, I can repost this
patch on top of it.

NOT FOR MERGE, just for testing.

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

Index: flashrom-register_all_programmers_register_generic_structflashchip/flash.h
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/flash.h	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/flash.h	(Arbeitskopie)
@@ -44,14 +44,6 @@
 void *programmer_map_flash_region(const char *descr, unsigned long phys_addr,
 				  size_t len);
 void programmer_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 programmer_delay(int usecs);
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@@ -153,6 +145,7 @@
 	/* Some flash devices have an additional register space. */
 	chipaddr virtual_memory;
 	chipaddr virtual_registers;
+	struct registered_programmer *pgm;
 };
 
 #define TEST_UNTESTED	0
@@ -186,6 +179,15 @@
 
 extern const struct flashchip flashchips[];
 
+void chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+void chip_writew(const struct flashchip *flash, uint16_t val, chipaddr addr);
+void chip_writel(const struct flashchip *flash, uint32_t val, chipaddr addr);
+void chip_writen(const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len);
+uint8_t chip_readb(const struct flashchip *flash, const chipaddr addr);
+uint16_t chip_readw(const struct flashchip *flash, const chipaddr addr);
+uint32_t chip_readl(const struct flashchip *flash, const chipaddr addr);
+void chip_readn(const struct flashchip *flash, uint8_t *buf, const chipaddr addr, size_t len);
+
 /* print.c */
 char *flashbuses_to_text(enum chipbustype bustype);
 void print_supported(void);
@@ -197,14 +199,13 @@
 	write_gran_1byte,
 	write_gran_256bytes,
 };
-extern enum chipbustype buses_supported;
 extern int verbose;
 extern const char flashrom_version[];
 extern char *chip_to_probe;
 void map_flash_registers(struct flashchip *flash);
 int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len);
 int erase_flash(struct flashchip *flash);
-int probe_flash(int startchip, struct flashchip *fill_flash, int force);
+int probe_flash(struct registered_programmer *pgm, int startchip, struct flashchip *fill_flash, int force);
 int read_flash_to_file(struct flashchip *flash, const char *filename);
 int min(int a, int b);
 int max(int a, int b);
@@ -266,9 +267,10 @@
 	const unsigned char *writearr;
 	unsigned char *readarr;
 };
-int spi_send_command(unsigned int writecnt, unsigned int readcnt,
+int spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr);
-int spi_send_multicommand(struct spi_command *cmds);
-uint32_t spi_get_valid_read_addr(void);
+int spi_send_multicommand(struct flashchip *flash, struct spi_command *cmds);
+uint32_t spi_get_valid_read_addr(struct flashchip *flash);
 
+enum chipbustype get_buses_supported(void);
 #endif				/* !__FLASH_H__ */
Index: flashrom-register_all_programmers_register_generic_structflashchip/drkaiser.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/drkaiser.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/drkaiser.c	(Arbeitskopie)
@@ -39,6 +39,8 @@
 
 static uint8_t *drkaiser_bar;
 
+static void drkaiser_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t drkaiser_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_drkaiser = {
 		.chip_readb		= drkaiser_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -84,12 +86,12 @@
 	return 0;
 }
 
-void drkaiser_chip_writeb(uint8_t val, chipaddr addr)
+static void drkaiser_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	pci_mmio_writeb(val, drkaiser_bar + (addr & DRKAISER_MEMMAP_MASK));
 }
 
-uint8_t drkaiser_chip_readb(const chipaddr addr)
+static uint8_t drkaiser_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	return pci_mmio_readb(drkaiser_bar + (addr & DRKAISER_MEMMAP_MASK));
 }
Index: flashrom-register_all_programmers_register_generic_structflashchip/it87spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/it87spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/it87spi.c	(Arbeitskopie)
@@ -103,7 +103,7 @@
 	return;
 }
 
-static int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int it8716f_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			const unsigned char *writearr, unsigned char *readarr);
 static int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf,
 				 int start, int len);
@@ -247,7 +247,7 @@
  * commands with the address in inverse wire order. That's why the register
  * ordering in case 4 and 5 may seem strange.
  */
-static int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int it8716f_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			const unsigned char *writearr, unsigned char *readarr)
 {
 	uint8_t busy, writeenc;
@@ -318,19 +318,19 @@
 	int i, result;
 	chipaddr bios = flash->virtual_memory;
 
-	result = spi_write_enable();
+	result = spi_write_enable(flash);
 	if (result)
 		return result;
 	/* FIXME: The command below seems to be redundant or wrong. */
 	OUTB(0x06, it8716f_flashport + 1);
 	OUTB(((2 + (fast_spi ? 1 : 0)) << 4), it8716f_flashport);
 	for (i = 0; i < flash->page_size; i++)
-		chip_writeb(buf[i], bios + start + i);
+		chip_writeb(flash, buf[i], bios + start + i);
 	OUTB(0, it8716f_flashport);
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 1-10 ms, so wait in 1 ms steps.
 	 */
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 		programmer_delay(1000);
 	return 0;
 }
Index: flashrom-register_all_programmers_register_generic_structflashchip/jedec.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/jedec.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/jedec.c	(Arbeitskopie)
@@ -37,17 +37,17 @@
 	return (val ^ (val >> 1)) & 0x1;
 }
 
-static void toggle_ready_jedec_common(chipaddr dst, int delay)
+static void toggle_ready_jedec_common(const struct flashchip *flash, chipaddr dst, int delay)
 {
 	unsigned int i = 0;
 	uint8_t tmp1, tmp2;
 
-	tmp1 = chip_readb(dst) & 0x40;
+	tmp1 = chip_readb(flash, dst) & 0x40;
 
 	while (i++ < 0xFFFFFFF) {
 		if (delay)
 			programmer_delay(delay);
-		tmp2 = chip_readb(dst) & 0x40;
+		tmp2 = chip_readb(flash, dst) & 0x40;
 		if (tmp1 == tmp2) {
 			break;
 		}
@@ -57,9 +57,9 @@
 		msg_cdbg("%s: excessive loops, i=0x%x\n", __func__, i);
 }
 
-void toggle_ready_jedec(chipaddr dst)
+void toggle_ready_jedec(const struct flashchip *flash, chipaddr dst)
 {
-	toggle_ready_jedec_common(dst, 0);
+	toggle_ready_jedec_common(flash, dst, 0);
 }
 
 /* Some chips require a minimum delay between toggle bit reads.
@@ -69,12 +69,12 @@
  * Given that erase is slow on all chips, it is recommended to use 
  * toggle_ready_jedec_slow in erase functions.
  */
-static void toggle_ready_jedec_slow(chipaddr dst)
+static void toggle_ready_jedec_slow(const struct flashchip *flash, chipaddr dst)
 {
-	toggle_ready_jedec_common(dst, 8 * 1000);
+	toggle_ready_jedec_common(flash, dst, 8 * 1000);
 }
 
-void data_polling_jedec(chipaddr dst, uint8_t data)
+void data_polling_jedec(const struct flashchip *flash, chipaddr dst, uint8_t data)
 {
 	unsigned int i = 0;
 	uint8_t tmp;
@@ -82,7 +82,7 @@
 	data &= 0x80;
 
 	while (i++ < 0xFFFFFFF) {
-		tmp = chip_readb(dst) & 0x80;
+		tmp = chip_readb(flash, dst) & 0x80;
 		if (tmp == data) {
 			break;
 		}
@@ -113,9 +113,9 @@
 static void start_program_jedec_common(struct flashchip *flash, unsigned int mask)
 {
 	chipaddr bios = flash->virtual_memory;
-	chip_writeb(0xAA, bios + (0x5555 & mask));
-	chip_writeb(0x55, bios + (0x2AAA & mask));
-	chip_writeb(0xA0, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0xA0, bios + (0x5555 & mask));
 }
 
 static int probe_jedec_common(struct flashchip *flash, unsigned int mask)
@@ -150,57 +150,57 @@
 	/* Reset chip to a clean slate */
 	if ((flash->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET)
 	{
-		chip_writeb(0xAA, bios + (0x5555 & mask));
+		chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 		if (probe_timing_exit)
 			programmer_delay(10);
-		chip_writeb(0x55, bios + (0x2AAA & mask));
+		chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 		if (probe_timing_exit)
 			programmer_delay(10);
 	}
-	chip_writeb(0xF0, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xF0, bios + (0x5555 & mask));
 	if (probe_timing_exit)
 		programmer_delay(probe_timing_exit);
 
 	/* Issue JEDEC Product ID Entry command */
-	chip_writeb(0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 	if (probe_timing_enter)
 		programmer_delay(10);
-	chip_writeb(0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 	if (probe_timing_enter)
 		programmer_delay(10);
-	chip_writeb(0x90, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x90, bios + (0x5555 & mask));
 	if (probe_timing_enter)
 		programmer_delay(probe_timing_enter);
 
 	/* Read product ID */
-	id1 = chip_readb(bios);
-	id2 = chip_readb(bios + 0x01);
+	id1 = chip_readb(flash, bios);
+	id2 = chip_readb(flash, bios + 0x01);
 	largeid1 = id1;
 	largeid2 = id2;
 
 	/* Check if it is a continuation ID, this should be a while loop. */
 	if (id1 == 0x7F) {
 		largeid1 <<= 8;
-		id1 = chip_readb(bios + 0x100);
+		id1 = chip_readb(flash, bios + 0x100);
 		largeid1 |= id1;
 	}
 	if (id2 == 0x7F) {
 		largeid2 <<= 8;
-		id2 = chip_readb(bios + 0x101);
+		id2 = chip_readb(flash, bios + 0x101);
 		largeid2 |= id2;
 	}
 
 	/* Issue JEDEC Product ID Exit command */
 	if ((flash->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET)
 	{
-		chip_writeb(0xAA, bios + (0x5555 & mask));
+		chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 		if (probe_timing_exit)
 			programmer_delay(10);
-		chip_writeb(0x55, bios + (0x2AAA & mask));
+		chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 		if (probe_timing_exit)
 			programmer_delay(10);
 	}
-	chip_writeb(0xF0, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xF0, bios + (0x5555 & mask));
 	if (probe_timing_exit)
 		programmer_delay(probe_timing_exit);
 
@@ -209,17 +209,17 @@
 		msg_cdbg(", id1 parity violation");
 
 	/* Read the product ID location again. We should now see normal flash contents. */
-	flashcontent1 = chip_readb(bios);
-	flashcontent2 = chip_readb(bios + 0x01);
+	flashcontent1 = chip_readb(flash, bios);
+	flashcontent2 = chip_readb(flash, bios + 0x01);
 
 	/* Check if it is a continuation ID, this should be a while loop. */
 	if (flashcontent1 == 0x7F) {
 		flashcontent1 <<= 8;
-		flashcontent1 |= chip_readb(bios + 0x100);
+		flashcontent1 |= chip_readb(flash, bios + 0x100);
 	}
 	if (flashcontent2 == 0x7F) {
 		flashcontent2 <<= 8;
-		flashcontent2 |= chip_readb(bios + 0x101);
+		flashcontent2 |= chip_readb(flash, bios + 0x101);
 	}
 
 	if (largeid1 == flashcontent1)
@@ -246,22 +246,22 @@
 	        delay_us = 10;
 
 	/*  Issue the Sector Erase command   */
-	chip_writeb(0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x80, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x80, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
 
-	chip_writeb(0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x30, bios + page);
+	chip_writeb(flash, 0x30, bios + page);
 	programmer_delay(delay_us);
 
 	/* wait for Toggle bit ready         */
-	toggle_ready_jedec_slow(bios);
+	toggle_ready_jedec_slow(flash, bios);
 
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -276,22 +276,22 @@
 	        delay_us = 10;
 
 	/*  Issue the Sector Erase command   */
-	chip_writeb(0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x80, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x80, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
 
-	chip_writeb(0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x50, bios + block);
+	chip_writeb(flash, 0x50, bios + block);
 	programmer_delay(delay_us);
 
 	/* wait for Toggle bit ready         */
-	toggle_ready_jedec_slow(bios);
+	toggle_ready_jedec_slow(flash, bios);
 
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -305,21 +305,21 @@
 	        delay_us = 10;
 
 	/*  Issue the JEDEC Chip Erase command   */
-	chip_writeb(0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x80, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x80, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
 
-	chip_writeb(0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
 	programmer_delay(delay_us);
-	chip_writeb(0x10, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x10, bios + (0x5555 & mask));
 	programmer_delay(delay_us);
 
-	toggle_ready_jedec_slow(bios);
+	toggle_ready_jedec_slow(flash, bios);
 
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -341,10 +341,10 @@
 	start_program_jedec_common(flash, mask);
 
 	/* transfer data from source to destination */
-	chip_writeb(*src, dst);
-	toggle_ready_jedec(bios);
+	chip_writeb(flash, *src, dst);
+	toggle_ready_jedec(flash, bios);
 
-	if (chip_readb(dst) != *src && tried++ < MAX_REFLASH_TRIES) {
+	if (chip_readb(flash, dst) != *src && tried++ < MAX_REFLASH_TRIES) {
 		goto retry;
 	}
 
@@ -395,12 +395,12 @@
 	for (i = 0; i < page_size; i++) {
 		/* If the data is 0xFF, don't program it */
 		if (*src != 0xFF)
-			chip_writeb(*src, dst);
+			chip_writeb(flash, *src, dst);
 		dst++;
 		src++;
 	}
 
-	toggle_ready_jedec(dst - 1);
+	toggle_ready_jedec(flash, dst - 1);
 
 	dst = d;
 	src = s;
Index: flashrom-register_all_programmers_register_generic_structflashchip/gfxnvidia.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/gfxnvidia.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/gfxnvidia.c	(Arbeitskopie)
@@ -61,6 +61,8 @@
 	{},
 };
 
+static void gfxnvidia_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t gfxnvidia_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_gfxnvidia = {
 		.chip_readb		= gfxnvidia_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -112,12 +114,12 @@
 	return 0;
 }
 
-void gfxnvidia_chip_writeb(uint8_t val, chipaddr addr)
+static void gfxnvidia_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	pci_mmio_writeb(val, nvidia_bar + (addr & GFXNVIDIA_MEMMAP_MASK));
 }
 
-uint8_t gfxnvidia_chip_readb(const chipaddr addr)
+static uint8_t gfxnvidia_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	return pci_mmio_readb(nvidia_bar + (addr & GFXNVIDIA_MEMMAP_MASK));
 }
Index: flashrom-register_all_programmers_register_generic_structflashchip/nicrealtek.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/nicrealtek.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/nicrealtek.c	(Arbeitskopie)
@@ -36,6 +36,8 @@
 	{},
 };
 
+static void nicrealtek_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t nicrealtek_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_nicrealtek = {
 		.chip_readb		= nicrealtek_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -69,7 +71,7 @@
 	return 0;
 }
 
-void nicrealtek_chip_writeb(uint8_t val, chipaddr addr)
+static void nicrealtek_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	/* Output addr and data, set WE to 0, set OE to 1, set CS to 0,
 	 * enable software access.
@@ -83,7 +85,7 @@
 	     io_base_addr + BIOS_ROM_ADDR);
 }
 
-uint8_t nicrealtek_chip_readb(const chipaddr addr)
+static uint8_t nicrealtek_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	uint8_t val;
 
Index: flashrom-register_all_programmers_register_generic_structflashchip/bitbang_spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/bitbang_spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/bitbang_spi.c	(Arbeitskopie)
@@ -63,7 +63,7 @@
 		bitbang_spi_master->release_bus();
 }
 
-static int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int bitbang_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr);
 
 static const struct spi_programmer spi_programmer_bitbang = {
@@ -141,7 +141,7 @@
 	return ret;
 }
 
-static int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int bitbang_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr)
 {
 	int i;
Index: flashrom-register_all_programmers_register_generic_structflashchip/serprog.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/serprog.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/serprog.c	(Arbeitskopie)
@@ -299,7 +299,8 @@
 	return 0;
 }
 
-static int serprog_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int serprog_spi_send_command(struct flashchip *flash,
+				    unsigned int writecnt, unsigned int readcnt,
 				    const unsigned char *writearr,
 				    unsigned char *readarr);
 static int serprog_spi_read(struct flashchip *flash, uint8_t *buf, int start,
@@ -314,6 +315,9 @@
 	.write_256	= default_spi_write_256,
 };
 
+static void serprog_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t serprog_chip_readb(const struct flashchip *flash, const chipaddr addr);
+static void serprog_chip_readn(const struct flashchip *flash, uint8_t *buf, const chipaddr addr, size_t len);
 static const struct par_programmer par_programmer_serprog = {
 		.chip_readb		= serprog_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -680,7 +684,7 @@
 	}
 }
 
-void serprog_chip_writeb(uint8_t val, chipaddr addr)
+static void serprog_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	msg_pspew("%s\n", __func__);
 	if (sp_max_write_n) {
@@ -711,7 +715,7 @@
 	}
 }
 
-uint8_t serprog_chip_readb(const chipaddr addr)
+static uint8_t serprog_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	unsigned char c;
 	unsigned char buf[3];
@@ -757,7 +761,7 @@
 }
 
 /* The externally called version that makes sure that max_read_n is obeyed. */
-void serprog_chip_readn(uint8_t * buf, const chipaddr addr, size_t len)
+static void serprog_chip_readn(const struct flashchip *flash, uint8_t * buf, const chipaddr addr, size_t len)
 {
 	size_t lenm = len;
 	chipaddr addrm = addr;
@@ -792,7 +796,7 @@
 	sp_prev_was_write = 0;
 }
 
-static int serprog_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int serprog_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			     const unsigned char *writearr,
 			     unsigned char *readarr)
 {
@@ -830,7 +834,7 @@
 	for (i = 0; i < len; i += cur_len) {
 		int ret;
 		cur_len = min(max_read, (len - i));
-		ret = spi_nbyte_read(start + i, buf + i, cur_len);
+		ret = spi_nbyte_read(flash, start + i, buf + i, cur_len);
 		if (ret)
 			return ret;
 	}
Index: flashrom-register_all_programmers_register_generic_structflashchip/w39.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/w39.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/w39.c	(Arbeitskopie)
@@ -26,7 +26,7 @@
 	chipaddr wrprotect = flash->virtual_registers + offset + 2;
 	uint8_t locking;
 
-	locking = chip_readb(wrprotect);
+	locking = chip_readb(flash, wrprotect);
 	msg_cdbg("Lock status of block at 0x%08x is ", offset);
 	switch (locking & 0x7) {
 	case 0:
@@ -64,7 +64,7 @@
 	chipaddr wrprotect = flash->virtual_registers + offset + 2;
 	uint8_t locking;
 
-	locking = chip_readb(wrprotect);
+	locking = chip_readb(flash, wrprotect);
 	/* Read or write lock present? */
 	if (locking & ((1 << 2) | (1 << 0))) {
 		/* Lockdown active? */
@@ -73,7 +73,7 @@
 			return -1;
 		} else {
 			msg_cdbg("Unlocking block at 0x%08x\n", offset);
-			chip_writeb(0, wrprotect);
+			chip_writeb(flash, 0, wrprotect);
 		}
 	}
 
@@ -86,18 +86,18 @@
 	uint8_t val;
 
 	/* Product Identification Entry */
-	chip_writeb(0xAA, bios + 0x5555);
-	chip_writeb(0x55, bios + 0x2AAA);
-	chip_writeb(0x90, bios + 0x5555);
+	chip_writeb(flash, 0xAA, bios + 0x5555);
+	chip_writeb(flash, 0x55, bios + 0x2AAA);
+	chip_writeb(flash, 0x90, bios + 0x5555);
 	programmer_delay(10);
 
 	/* Read something, maybe hardware lock bits */
-	val = chip_readb(bios + offset);
+	val = chip_readb(flash, bios + offset);
 
 	/* Product Identification Exit */
-	chip_writeb(0xAA, bios + 0x5555);
-	chip_writeb(0x55, bios + 0x2AAA);
-	chip_writeb(0xF0, bios + 0x5555);
+	chip_writeb(flash, 0xAA, bios + 0x5555);
+	chip_writeb(flash, 0x55, bios + 0x2AAA);
+	chip_writeb(flash, 0xF0, bios + 0x5555);
 	programmer_delay(10);
 
 	return val;
Index: flashrom-register_all_programmers_register_generic_structflashchip/sst49lfxxxc.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/sst49lfxxxc.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/sst49lfxxxc.c	(Arbeitskopie)
@@ -26,8 +26,8 @@
 static int write_lockbits_block_49lfxxxc(struct flashchip *flash, unsigned long address, unsigned char bits)
 {
 	unsigned long lock = flash->virtual_registers + address + 2;
-	msg_cdbg("lockbits at address=0x%08lx is 0x%01x\n", lock, chip_readb(lock));
-	chip_writeb(bits, lock);
+	msg_cdbg("lockbits at address=0x%08lx is 0x%01x\n", lock, chip_readb(flash, lock));
+	chip_writeb(flash, bits, lock);
 
 	return 0;
 }
@@ -64,8 +64,8 @@
 	uint8_t status;
 	chipaddr bios = flash->virtual_memory;
 
-	chip_writeb(0x30, bios);
-	chip_writeb(0xD0, bios + address);
+	chip_writeb(flash, 0x30, bios);
+	chip_writeb(flash, 0xD0, bios + address);
 
 	status = wait_82802ab(flash);
 	print_status_82802ab(status);
Index: flashrom-register_all_programmers_register_generic_structflashchip/sharplhf00l04.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/sharplhf00l04.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/sharplhf00l04.c	(Arbeitskopie)
@@ -33,18 +33,18 @@
 	uint8_t status;
 
 	// clear status register
-	chip_writeb(0x50, bios);
+	chip_writeb(flash, 0x50, bios);
 	status = wait_82802ab(flash);
 	print_status_82802ab(status);
 	// clear write protect
 	msg_cspew("write protect is at 0x%lx\n", (wrprotect));
-	msg_cspew("write protect is 0x%x\n", chip_readb(wrprotect));
-	chip_writeb(0, wrprotect);
-	msg_cspew("write protect is 0x%x\n", chip_readb(wrprotect));
+	msg_cspew("write protect is 0x%x\n", chip_readb(flash, wrprotect));
+	chip_writeb(flash, 0, wrprotect);
+	msg_cspew("write protect is 0x%x\n", chip_readb(flash, wrprotect));
 
 	// now start it
-	chip_writeb(0x20, bios);
-	chip_writeb(0xd0, bios);
+	chip_writeb(flash, 0x20, bios);
+	chip_writeb(flash, 0xd0, bios);
 	programmer_delay(10);
 	// now let's see what the register is
 	status = wait_82802ab(flash);
Index: flashrom-register_all_programmers_register_generic_structflashchip/a25.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/a25.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/a25.c	(Arbeitskopie)
@@ -33,7 +33,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	spi_prettyprint_status_register_amic_a25_srwd(status);
@@ -49,7 +49,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	spi_prettyprint_status_register_amic_a25_srwd(status);
@@ -64,7 +64,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	spi_prettyprint_status_register_amic_a25_srwd(status);
@@ -82,7 +82,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	spi_prettyprint_status_register_amic_a25_srwd(status);
Index: flashrom-register_all_programmers_register_generic_structflashchip/satamv.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/satamv.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/satamv.c	(Arbeitskopie)
@@ -41,6 +41,8 @@
 #define PCI_BAR2_CONTROL		0x00c08
 #define GPIO_PORT_CONTROL		0x104f0
 
+static void satamv_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t satamv_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_satamv = {
 		.chip_readb		= satamv_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -183,13 +185,13 @@
 }
 
 /* FIXME: Prefer direct access to BAR2 if BAR2 is active. */
-void satamv_chip_writeb(uint8_t val, chipaddr addr)
+static void satamv_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	satamv_indirect_chip_writeb(val, addr);
 }
 
 /* FIXME: Prefer direct access to BAR2 if BAR2 is active. */
-uint8_t satamv_chip_readb(const chipaddr addr)
+static uint8_t satamv_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	return satamv_indirect_chip_readb(addr);
 }
Index: flashrom-register_all_programmers_register_generic_structflashchip/dummyflasher.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/dummyflasher.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/dummyflasher.c	(Arbeitskopie)
@@ -60,10 +60,18 @@
 
 static int spi_write_256_chunksize = 256;
 
-static int dummy_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int dummy_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		      const unsigned char *writearr, unsigned char *readarr);
 static int dummy_spi_write_256(struct flashchip *flash, uint8_t *buf,
 			       int start, int len);
+static void dummy_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static void dummy_chip_writew(const struct flashchip *flash, uint16_t val, chipaddr addr);
+static void dummy_chip_writel(const struct flashchip *flash, uint32_t val, chipaddr addr);
+static void dummy_chip_writen(const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len);
+static uint8_t dummy_chip_readb(const struct flashchip *flash, const chipaddr addr);
+static uint16_t dummy_chip_readw(const struct flashchip *flash, const chipaddr addr);
+static uint32_t dummy_chip_readl(const struct flashchip *flash, const chipaddr addr);
+static void dummy_chip_readn(const struct flashchip *flash, uint8_t *buf, const chipaddr addr, size_t len);
 
 static const struct spi_programmer spi_programmer_dummyflasher = {
 	.type		= SPI_CONTROLLER_DUMMY,
@@ -263,22 +271,22 @@
 		  __func__, (unsigned long)len, virt_addr);
 }
 
-void dummy_chip_writeb(uint8_t val, chipaddr addr)
+static void dummy_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	msg_pspew("%s: addr=0x%lx, val=0x%02x\n", __func__, addr, val);
 }
 
-void dummy_chip_writew(uint16_t val, chipaddr addr)
+static void dummy_chip_writew(const struct flashchip *flash, uint16_t val, chipaddr addr)
 {
 	msg_pspew("%s: addr=0x%lx, val=0x%04x\n", __func__, addr, val);
 }
 
-void dummy_chip_writel(uint32_t val, chipaddr addr)
+static void dummy_chip_writel(const struct flashchip *flash, uint32_t val, chipaddr addr)
 {
 	msg_pspew("%s: addr=0x%lx, val=0x%08x\n", __func__, addr, val);
 }
 
-void dummy_chip_writen(uint8_t *buf, chipaddr addr, size_t len)
+static void dummy_chip_writen(const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len)
 {
 	size_t i;
 	msg_pspew("%s: addr=0x%lx, len=0x%08lx, writing data (hex):",
@@ -290,25 +298,25 @@
 	}
 }
 
-uint8_t dummy_chip_readb(const chipaddr addr)
+static uint8_t dummy_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	msg_pspew("%s:  addr=0x%lx, returning 0xff\n", __func__, addr);
 	return 0xff;
 }
 
-uint16_t dummy_chip_readw(const chipaddr addr)
+static uint16_t dummy_chip_readw(const struct flashchip *flash, const chipaddr addr)
 {
 	msg_pspew("%s:  addr=0x%lx, returning 0xffff\n", __func__, addr);
 	return 0xffff;
 }
 
-uint32_t dummy_chip_readl(const chipaddr addr)
+static uint32_t dummy_chip_readl(const struct flashchip *flash, const chipaddr addr)
 {
 	msg_pspew("%s:  addr=0x%lx, returning 0xffffffff\n", __func__, addr);
 	return 0xffffffff;
 }
 
-void dummy_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
+static void dummy_chip_readn(const struct flashchip *flash, uint8_t *buf, const chipaddr addr, size_t len)
 {
 	msg_pspew("%s:  addr=0x%lx, len=0x%lx, returning array of 0xff\n",
 		  __func__, addr, (unsigned long)len);
@@ -513,7 +521,7 @@
 }
 #endif
 
-static int dummy_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int dummy_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		      const unsigned char *writearr, unsigned char *readarr)
 {
 	int i;
Index: flashrom-register_all_programmers_register_generic_structflashchip/sst_fwhub.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/sst_fwhub.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/sst_fwhub.c	(Arbeitskopie)
@@ -29,7 +29,7 @@
 	chipaddr registers = flash->virtual_registers;
 	uint8_t blockstatus;
 
-	blockstatus = chip_readb(registers + offset + 2);
+	blockstatus = chip_readb(flash, registers + offset + 2);
 	msg_cdbg("Lock status for 0x%06x (size 0x%06x) is %02x, ",
 		     offset, flash->page_size, blockstatus);
 	switch (blockstatus & 0x3) {
@@ -59,7 +59,7 @@
 
 	if (blockstatus) {
 		msg_cdbg("Trying to clear lock for 0x%06x... ", offset);
-		chip_writeb(0, registers + offset + 2);
+		chip_writeb(flash, 0, registers + offset + 2);
 
 		blockstatus = check_sst_fwhub_block_lock(flash, offset);
 		msg_cdbg("%s\n", (blockstatus) ? "failed" : "OK");
Index: flashrom-register_all_programmers_register_generic_structflashchip/cli_classic.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/cli_classic.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/cli_classic.c	(Arbeitskopie)
@@ -172,7 +172,7 @@
 	struct flashchip flashes[3];
 	struct flashchip *fill_flash;
 	const char *name;
-	int namelen, opt, i;
+	int namelen, opt, i, j;
 	int startchip = 0, chipcount = 0, option_index = 0, force = 0;
 #if CONFIG_PRINT_WIKI == 1
 	int list_supported_wiki = 0;
@@ -443,17 +443,21 @@
 		ret = 1;
 		goto out_shutdown;
 	}
-	tempstr = flashbuses_to_text(buses_supported);
+	tempstr = flashbuses_to_text(get_buses_supported());
 	msg_pdbg("This programmer supports the following protocols: %s.\n",
 		 tempstr);
 	free(tempstr);
 
-	for (i = 0; i < ARRAY_SIZE(flashes); i++) {
-		startchip = probe_flash(startchip, &flashes[i], 0);
-		if (startchip == -1)
-			break;
-		chipcount++;
-		startchip++;
+	for (j = 0; j < registered_programmer_count; j++) {
+		startchip = 0;
+		for (i = 0; i < ARRAY_SIZE(flashes); i++) {
+			startchip = probe_flash(&registered_programmers[j],
+						startchip, &flashes[i], 0);
+			if (startchip == -1)
+				break;
+			chipcount++;
+			startchip++;
+		}
 	}
 
 	if (chipcount > 1) {
@@ -471,6 +475,7 @@
 			printf("Note: flashrom can never write if the flash "
 			       "chip isn't found automatically.\n");
 		}
+#if 0 // FIXME: What happens for a forced chip read if multiple compatible programmers are registered?
 		if (force && read_it && chip_to_probe) {
 			printf("Force read (-f -r -c) requested, pretending "
 			       "the chip is there:\n");
@@ -485,6 +490,7 @@
 			       "contain garbage.\n");
 			return read_flash_to_file(&flashes[0], filename);
 		}
+#endif
 		ret = 1;
 		goto out_shutdown;
 	} else if (!chip_to_probe) {
@@ -501,7 +507,7 @@
 	check_chip_supported(fill_flash);
 
 	size = fill_flash->total_size * 1024;
-	if (check_max_decode((buses_supported & fill_flash->bustype), size) &&
+	if (check_max_decode((get_buses_supported() & fill_flash->bustype), size) &&
 	    (!force)) {
 		fprintf(stderr, "Chip is too big for this programmer "
 			"(-V gives details). Use --force to override.\n");
Index: flashrom-register_all_programmers_register_generic_structflashchip/at25.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/at25.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/at25.c	(Arbeitskopie)
@@ -61,7 +61,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	spi_prettyprint_status_register_atmel_at25_srpl(status);
@@ -84,7 +84,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	spi_prettyprint_status_register_atmel_at25_srpl(status);
@@ -103,7 +103,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	msg_cdbg("Chip status register: Status Register Write Protect (WPEN) "
@@ -127,7 +127,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	msg_cdbg("Chip status register: Status Register Write Protect (WPEN) "
@@ -151,7 +151,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 
 	spi_prettyprint_status_register_atmel_at25_srpl(status);
@@ -168,7 +168,7 @@
 	uint8_t status;
 	int result;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	/* If block protection is disabled, stop here. */
 	if ((status & (3 << 2)) == 0)
 		return 0;
@@ -195,7 +195,7 @@
 		msg_cerr("spi_write_status_register failed\n");
 		return result;
 	}
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	if ((status & (3 << 2)) != 0) {
 		msg_cerr("Block protection could not be disabled!\n");
 		return 1;
@@ -223,7 +223,7 @@
 	uint8_t status;
 	int result;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	/* If block protection is disabled, stop here. */
 	if ((status & 0x6c) == 0)
 		return 0;
@@ -244,7 +244,7 @@
 		msg_cerr("spi_write_status_register failed\n");
 		return result;
 	}
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	if ((status & 0x6c) != 0) {
 		msg_cerr("Block protection could not be disabled!\n");
 		return 1;
@@ -257,7 +257,7 @@
 	uint8_t status;
 	int result;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	/* If block protection is disabled, stop here. */
 	if ((status & 0x7c) == 0)
 		return 0;
@@ -278,7 +278,7 @@
 		msg_cerr("spi_write_status_register failed\n");
 		return result;
 	}
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	if ((status & 0x7c) != 0) {
 		msg_cerr("Block protection could not be disabled!\n");
 		return 1;
Index: flashrom-register_all_programmers_register_generic_structflashchip/internal.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/internal.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/internal.c	(Arbeitskopie)
@@ -127,6 +127,13 @@
 int is_laptop = 0;
 int laptop_ok = 0;
 
+static void internal_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static void internal_chip_writew(const struct flashchip *flash, uint16_t val, chipaddr addr);
+static void internal_chip_writel(const struct flashchip *flash, uint32_t val, chipaddr addr);
+static uint8_t internal_chip_readb(const struct flashchip *flash, const chipaddr addr);
+static uint16_t internal_chip_readw(const struct flashchip *flash, const chipaddr addr);
+static uint32_t internal_chip_readl(const struct flashchip *flash, const chipaddr addr);
+static void internal_chip_readn(const struct flashchip *flash, uint8_t *buf, const chipaddr addr, size_t len);
 static const struct par_programmer par_programmer_internal = {
 		.chip_readb		= internal_chip_readb,
 		.chip_readw		= internal_chip_readw,
@@ -324,37 +331,37 @@
 }
 #endif
 
-void internal_chip_writeb(uint8_t val, chipaddr addr)
+static void internal_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	mmio_writeb(val, (void *) addr);
 }
 
-void internal_chip_writew(uint16_t val, chipaddr addr)
+static void internal_chip_writew(const struct flashchip *flash, uint16_t val, chipaddr addr)
 {
 	mmio_writew(val, (void *) addr);
 }
 
-void internal_chip_writel(uint32_t val, chipaddr addr)
+static void internal_chip_writel(const struct flashchip *flash, uint32_t val, chipaddr addr)
 {
 	mmio_writel(val, (void *) addr);
 }
 
-uint8_t internal_chip_readb(const chipaddr addr)
+static uint8_t internal_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	return mmio_readb((void *) addr);
 }
 
-uint16_t internal_chip_readw(const chipaddr addr)
+static uint16_t internal_chip_readw(const struct flashchip *flash, const chipaddr addr)
 {
 	return mmio_readw((void *) addr);
 }
 
-uint32_t internal_chip_readl(const chipaddr addr)
+static uint32_t internal_chip_readl(const struct flashchip *flash, const chipaddr addr)
 {
 	return mmio_readl((void *) addr);
 }
 
-void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
+static void internal_chip_readn(const struct flashchip *flash, uint8_t *buf, const chipaddr addr, size_t len)
 {
 	memcpy(buf, (void *)addr, len);
 	return;
Index: flashrom-register_all_programmers_register_generic_structflashchip/ichspi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/ichspi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/ichspi.c	(Arbeitskopie)
@@ -228,7 +228,7 @@
 static int find_preop(OPCODES *op, uint8_t preop);
 static int generate_opcodes(OPCODES * op);
 static int program_opcodes(OPCODES *op, int enable_undo);
-static int run_opcode(OPCODE op, uint32_t offset,
+static int run_opcode(const struct flashchip *flash, OPCODE op, uint32_t offset,
 		      uint8_t datalength, uint8_t * data);
 
 /* for pairing opcodes with their required preop */
@@ -635,7 +635,7 @@
 
 /* Read len bytes from the fdata/spid register into the data array.
  *
- * Note that using len > spi_programmer->max_data_read will return garbage or
+ * Note that using len > flash->pgm->spi.max_data_read will return garbage or
  * may even crash.
  */
  static void ich_read_data(uint8_t *data, int len, int reg0_off)
@@ -653,7 +653,7 @@
 
 /* Fill len bytes from the data array into the fdata/spid registers.
  *
- * Note that using len > spi_programmer->max_data_write will trash the registers
+ * Note that using len > flash->pgm->spi.max_data_write will trash the registers
  * following the data registers.
  */
 static void ich_fill_data(const uint8_t *data, int len, int reg0_off)
@@ -956,13 +956,13 @@
 	return 0;
 }
 
-static int run_opcode(OPCODE op, uint32_t offset,
+static int run_opcode(const struct flashchip *flash, OPCODE op, uint32_t offset,
 		      uint8_t datalength, uint8_t * data)
 {
 	/* max_data_read == max_data_write for all Intel/VIA SPI masters */
-	uint8_t maxlength = spi_programmer->max_data_read;
+	uint8_t maxlength = flash->pgm->spi.max_data_read;
 
-	if (spi_programmer->type == SPI_CONTROLLER_NONE) {
+	if (ich_generation == CHIPSET_ICH_UNKNOWN) {
 		msg_perr("%s: unsupported chipset\n", __func__);
 		return -1;
 	}
@@ -983,7 +983,7 @@
 	}
 }
 
-static int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int ich_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		    const unsigned char *writearr, unsigned char *readarr)
 {
 	int result;
@@ -1076,7 +1076,7 @@
 		count = readcnt;
 	}
 
-	result = run_opcode(*opcode, addr, count, data);
+	result = run_opcode(flash, *opcode, addr, count, data);
 	if (result) {
 		msg_pdbg("Running OPCODE 0x%02x failed ", opcode->opcode);
 		if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
@@ -1295,7 +1295,7 @@
 	REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
 
 	while (len > 0) {
-		block_len = min(len, opaque_programmer->max_data_read);
+		block_len = min(len, flash->pgm->opaque.max_data_read);
 		ich_hwseq_set_addr(addr);
 		hsfc = REGREAD16(ICH9_REG_HSFC);
 		hsfc &= ~HSFC_FCYCLE; /* set read operation */
@@ -1333,7 +1333,7 @@
 
 	while (len > 0) {
 		ich_hwseq_set_addr(addr);
-		block_len = min(len, opaque_programmer->max_data_write);
+		block_len = min(len, flash->pgm->opaque.max_data_write);
 		ich_fill_data(buf, block_len, ICH9_REG_FDATA0);
 		hsfc = REGREAD16(ICH9_REG_HSFC);
 		hsfc &= ~HSFC_FCYCLE; /* clear operation */
@@ -1353,7 +1353,7 @@
 	return 0;
 }
 
-static int ich_spi_send_multicommand(struct spi_command *cmds)
+static int ich_spi_send_multicommand(struct flashchip *flash, struct spi_command *cmds)
 {
 	int ret = 0;
 	int i;
@@ -1403,7 +1403,7 @@
 			 * preoppos matched, this is a normal opcode.
 			 */
 		}
-		ret = ich_spi_send_command(cmds->writecnt, cmds->readcnt,
+		ret = ich_spi_send_command(flash, cmds->writecnt, cmds->readcnt,
 					   cmds->writearr, cmds->readarr);
 		/* Reset the type of all opcodes to non-atomic. */
 		for (i = 0; i < 8; i++)
Index: flashrom-register_all_programmers_register_generic_structflashchip/82802ab.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/82802ab.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/82802ab.c	(Arbeitskopie)
@@ -47,18 +47,18 @@
 	int shifted = (flash->feature_bits & FEATURE_ADDR_SHIFTED) != 0;
 
 	/* Reset to get a clean state */
-	chip_writeb(0xFF, bios);
+	chip_writeb(flash, 0xFF, bios);
 	programmer_delay(10);
 
 	/* Enter ID mode */
-	chip_writeb(0x90, bios);
+	chip_writeb(flash, 0x90, bios);
 	programmer_delay(10);
 
-	id1 = chip_readb(bios + (0x00 << shifted));
-	id2 = chip_readb(bios + (0x01 << shifted));
+	id1 = chip_readb(flash, bios + (0x00 << shifted));
+	id2 = chip_readb(flash, bios + (0x01 << shifted));
 
 	/* Leave ID mode */
-	chip_writeb(0xFF, bios);
+	chip_writeb(flash, 0xFF, bios);
 
 	programmer_delay(10);
 
@@ -71,8 +71,8 @@
 	 * Read the product ID location again. We should now see normal
 	 * flash contents.
 	 */
-	flashcontent1 = chip_readb(bios + (0x00 << shifted));
-	flashcontent2 = chip_readb(bios + (0x01 << shifted));
+	flashcontent1 = chip_readb(flash, bios + (0x00 << shifted));
+	flashcontent2 = chip_readb(flash, bios + (0x01 << shifted));
 
 	if (id1 == flashcontent1)
 		msg_cdbg(", id1 is normal flash content");
@@ -94,15 +94,15 @@
 	uint8_t status;
 	chipaddr bios = flash->virtual_memory;
 
-	chip_writeb(0x70, bios);
-	if ((chip_readb(bios) & 0x80) == 0) {	// it's busy
-		while ((chip_readb(bios) & 0x80) == 0) ;
+	chip_writeb(flash, 0x70, bios);
+	if ((chip_readb(flash, bios) & 0x80) == 0) {	// it's busy
+		while ((chip_readb(flash, bios) & 0x80) == 0) ;
 	}
 
-	status = chip_readb(bios);
+	status = chip_readb(flash, bios);
 
 	/* Reset to get a clean state */
-	chip_writeb(0xFF, bios);
+	chip_writeb(flash, 0xFF, bios);
 
 	return status;
 }
@@ -113,7 +113,7 @@
 	//chipaddr wrprotect = flash->virtual_registers + page + 2;
 
 	for (i = 0; i < flash->total_size * 1024; i+= flash->page_size)
-		chip_writeb(0, flash->virtual_registers + i + 2);
+		chip_writeb(flash, 0, flash->virtual_registers + i + 2);
 
 	return 0;
 }
@@ -125,11 +125,11 @@
 	uint8_t status;
 
 	// clear status register
-	chip_writeb(0x50, bios + page);
+	chip_writeb(flash, 0x50, bios + page);
 
 	// now start it
-	chip_writeb(0x20, bios + page);
-	chip_writeb(0xd0, bios + page);
+	chip_writeb(flash, 0x20, bios + page);
+	chip_writeb(flash, 0xd0, bios + page);
 	programmer_delay(10);
 
 	// now let's see what the register is
@@ -148,8 +148,8 @@
 
 	for (i = 0; i < len; i++) {
 		/* transfer data from source to destination */
-		chip_writeb(0x40, dst);
-		chip_writeb(*src++, dst++);
+		chip_writeb(flash, 0x40, dst);
+		chip_writeb(flash, *src++, dst++);
 		wait_82802ab(flash);
 	}
 
@@ -164,13 +164,13 @@
 	int i;
 
 	/* Clear status register */
-	chip_writeb(0x50, bios);
+	chip_writeb(flash, 0x50, bios);
 
 	/* Read identifier codes */
-	chip_writeb(0x90, bios);
+	chip_writeb(flash, 0x90, bios);
 
 	/* Read master lock-bit */
-	mcfg = chip_readb(bios + 0x3);
+	mcfg = chip_readb(flash, bios + 0x3);
 	msg_cdbg("master lock is ");
 	if (mcfg) {
 		msg_cdbg("locked!\n");
@@ -181,7 +181,7 @@
 
 	/* Read block lock-bits */
 	for (i = 0; i < flash->total_size * 1024; i+= (64 * 1024)) {
-		bcfg = chip_readb(bios + i + 2); // read block lock config
+		bcfg = chip_readb(flash, bios + i + 2); // read block lock config
 		msg_cdbg("block lock at %06x is %slocked!\n", i, bcfg ? "" : "un");
 		if (bcfg) {
 			need_unlock = 1;
@@ -189,14 +189,14 @@
 	}
 
 	/* Reset chip */
-	chip_writeb(0xFF, bios);
+	chip_writeb(flash, 0xFF, bios);
 
 	/* Unlock: clear block lock-bits, if needed */
 	if (can_unlock && need_unlock) {
 		msg_cdbg("Unlock: ");
-		chip_writeb(0x60, bios);
-		chip_writeb(0xD0, bios);
-		chip_writeb(0xFF, bios);
+		chip_writeb(flash, 0x60, bios);
+		chip_writeb(flash, 0xD0, bios);
+		chip_writeb(flash, 0xFF, bios);
 		msg_cdbg("Done!\n");
 	}
 
@@ -220,10 +220,10 @@
 	wait_82802ab(flash);
 
 	/* Read identifier codes */
-	chip_writeb(0x90, bios);
+	chip_writeb(flash, 0x90, bios);
 
 	/* Read master lock-bit */
-	mcfg = chip_readb(bios + 0x3);
+	mcfg = chip_readb(flash, bios + 0x3);
 	msg_cdbg("master lock is ");
 	if (mcfg) {
 		msg_cdbg("locked!\n");
@@ -235,7 +235,7 @@
 	/* Read block lock-bits, 8 * 8 KB + 15 * 64 KB */
 	for (i = 0; i < flash->total_size * 1024;
 	     i += (i >= (64 * 1024) ? 64 * 1024 : 8 * 1024)) {
-		bcfg = chip_readb(bios + i + 2); /* read block lock config */
+		bcfg = chip_readb(flash, bios + i + 2); /* read block lock config */
 		msg_cdbg("block lock at %06x is %slocked!\n", i,
 			 bcfg ? "" : "un");
 		if (bcfg)
@@ -243,14 +243,14 @@
 	}
 
 	/* Reset chip */
-	chip_writeb(0xFF, bios);
+	chip_writeb(flash, 0xFF, bios);
 
 	/* Unlock: clear block lock-bits, if needed */
 	if (can_unlock && need_unlock) {
 		msg_cdbg("Unlock: ");
-		chip_writeb(0x60, bios);
-		chip_writeb(0xD0, bios);
-		chip_writeb(0xFF, bios);
+		chip_writeb(flash, 0x60, bios);
+		chip_writeb(flash, 0xD0, bios);
+		chip_writeb(flash, 0xFF, bios);
 		wait_82802ab(flash);
 		msg_cdbg("Done!\n");
 	}
Index: flashrom-register_all_programmers_register_generic_structflashchip/nicnatsemi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/nicnatsemi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/nicnatsemi.c	(Arbeitskopie)
@@ -35,6 +35,8 @@
 	{},
 };
 
+static void nicnatsemi_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t nicnatsemi_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_nicnatsemi = {
 		.chip_readb		= nicnatsemi_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -74,7 +76,7 @@
 	return 0;
 }
 
-void nicnatsemi_chip_writeb(uint8_t val, chipaddr addr)
+static void nicnatsemi_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	OUTL((uint32_t)addr & 0x0001FFFF, io_base_addr + BOOT_ROM_ADDR);
 	/*
@@ -88,7 +90,7 @@
 	OUTB(val, io_base_addr + BOOT_ROM_DATA);
 }
 
-uint8_t nicnatsemi_chip_readb(const chipaddr addr)
+static uint8_t nicnatsemi_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	OUTL(((uint32_t)addr & 0x0001FFFF), io_base_addr + BOOT_ROM_ADDR);
 	/*
Index: flashrom-register_all_programmers_register_generic_structflashchip/opaque.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/opaque.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/opaque.c	(Arbeitskopie)
@@ -30,70 +30,62 @@
 #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,
-	.erase = NULL,
-};
-
-const struct opaque_programmer *opaque_programmer = &opaque_programmer_none;
-
 int probe_opaque(struct flashchip *flash)
 {
-	if (!opaque_programmer->probe) {
+	if (!flash->pgm->opaque.probe) {
 		msg_perr("%s called before register_opaque_programmer. "
 			 "Please report a bug at flashrom at flashrom.org\n",
 			 __func__);
 		return 0;
 	}
 
-	return opaque_programmer->probe(flash);
+	return flash->pgm->opaque.probe(flash);
 }
 
 int read_opaque(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
-	if (!opaque_programmer->read) {
+	if (!flash->pgm->opaque.read) {
 		msg_perr("%s called before register_opaque_programmer. "
 			 "Please report a bug at flashrom at flashrom.org\n",
 			 __func__);
 		return 1;
 	}
-	return opaque_programmer->read(flash, buf, start, len);
+	return flash->pgm->opaque.read(flash, buf, start, len);
 }
 
 int write_opaque(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
-	if (!opaque_programmer->write) {
+	if (!flash->pgm->opaque.write) {
 		msg_perr("%s called before register_opaque_programmer. "
 			 "Please report a bug at flashrom at flashrom.org\n",
 			 __func__);
 		return 1;
 	}
-	return opaque_programmer->write(flash, buf, start, len);
+	return flash->pgm->opaque.write(flash, buf, start, len);
 }
 
 int erase_opaque(struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen)
 {
-	if (!opaque_programmer->erase) {
+	if (!flash->pgm->opaque.erase) {
 		msg_perr("%s called before register_opaque_programmer. "
 			 "Please report a bug at flashrom at flashrom.org\n",
 			 __func__);
 		return 1;
 	}
-	return opaque_programmer->erase(flash, blockaddr, blocklen);
+	return flash->pgm->opaque.erase(flash, blockaddr, blocklen);
 }
 
 void register_opaque_programmer(const struct opaque_programmer *pgm)
 {
+	struct registered_programmer rpgm;
+
 	if (!pgm->probe || !pgm->read || !pgm->write || !pgm->erase) {
 		msg_perr("%s called with one of probe/read/write/erase being "
 			 "NULL. Please report a bug at flashrom at flashrom.org\n",
 			 __func__);
 		return;
 	}
-	opaque_programmer = pgm;
-	buses_supported |= BUS_PROG;
+	rpgm.buses_supported = BUS_PROG;
+	rpgm.opaque = *pgm;
+	register_programmer(&rpgm);
 }
Index: flashrom-register_all_programmers_register_generic_structflashchip/dediprog.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/dediprog.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/dediprog.c	(Arbeitskopie)
@@ -317,7 +317,7 @@
 	return ret;
 }
 
-static int dediprog_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int dediprog_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			const unsigned char *writearr, unsigned char *readarr)
 {
 	int ret;
Index: flashrom-register_all_programmers_register_generic_structflashchip/spi25.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/spi25.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/spi25.c	(Arbeitskopie)
@@ -29,13 +29,13 @@
 #include "programmer.h"
 #include "spi.h"
 
-static int spi_rdid(unsigned char *readarr, int bytes)
+static int spi_rdid(struct flashchip *flash, unsigned char *readarr, int bytes)
 {
 	static const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID };
 	int ret;
 	int i;
 
-	ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr);
+	ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
 	if (ret)
 		return ret;
 	msg_cspew("RDID returned");
@@ -45,20 +45,20 @@
 	return 0;
 }
 
-static int spi_rems(unsigned char *readarr)
+static int spi_rems(struct flashchip *flash, unsigned char *readarr)
 {
 	unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 };
 	uint32_t readaddr;
 	int ret;
 
-	ret = spi_send_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
+	ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
 	if (ret == SPI_INVALID_ADDRESS) {
 		/* Find the lowest even address allowed for reads. */
-		readaddr = (spi_get_valid_read_addr() + 1) & ~1;
+		readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
 		cmd[1] = (readaddr >> 16) & 0xff,
 		cmd[2] = (readaddr >> 8) & 0xff,
 		cmd[3] = (readaddr >> 0) & 0xff,
-		ret = spi_send_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
+		ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
 	}
 	if (ret)
 		return ret;
@@ -66,21 +66,21 @@
 	return 0;
 }
 
-static int spi_res(unsigned char *readarr, int bytes)
+static int spi_res(struct flashchip *flash, unsigned char *readarr, int bytes)
 {
 	unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 };
 	uint32_t readaddr;
 	int ret;
 	int i;
 
-	ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr);
+	ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
 	if (ret == SPI_INVALID_ADDRESS) {
 		/* Find the lowest even address allowed for reads. */
-		readaddr = (spi_get_valid_read_addr() + 1) & ~1;
+		readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
 		cmd[1] = (readaddr >> 16) & 0xff,
 		cmd[2] = (readaddr >> 8) & 0xff,
 		cmd[3] = (readaddr >> 0) & 0xff,
-		ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr);
+		ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
 	}
 	if (ret)
 		return ret;
@@ -91,13 +91,13 @@
 	return 0;
 }
 
-int spi_write_enable(void)
+int spi_write_enable(struct flashchip *flash)
 {
 	static const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN };
 	int result;
 
 	/* Send WREN (Write Enable) */
-	result = spi_send_command(sizeof(cmd), 0, cmd, NULL);
+	result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
 
 	if (result)
 		msg_cerr("%s failed\n", __func__);
@@ -105,12 +105,12 @@
 	return result;
 }
 
-int spi_write_disable(void)
+int spi_write_disable(struct flashchip *flash)
 {
 	static const unsigned char cmd[JEDEC_WRDI_OUTSIZE] = { JEDEC_WRDI };
 
 	/* Send WRDI (Write Disable) */
-	return spi_send_command(sizeof(cmd), 0, cmd, NULL);
+	return spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
 }
 
 static int probe_spi_rdid_generic(struct flashchip *flash, int bytes)
@@ -119,7 +119,7 @@
 	uint32_t id1;
 	uint32_t id2;
 
-	if (spi_rdid(readarr, bytes)) {
+	if (spi_rdid(flash, readarr, bytes)) {
 		return 0;
 	}
 
@@ -177,7 +177,7 @@
 	/* Some SPI controllers do not support commands with writecnt=1 and
 	 * readcnt=4.
 	 */
-	switch (spi_programmer->type) {
+	switch (flash->pgm->spi.type) {
 #if CONFIG_INTERNAL == 1
 #if defined(__i386__) || defined(__x86_64__)
 	case SPI_CONTROLLER_IT87XX:
@@ -199,7 +199,7 @@
 	unsigned char readarr[JEDEC_REMS_INSIZE];
 	uint32_t id1, id2;
 
-	if (spi_rems(readarr)) {
+	if (spi_rems(flash, readarr)) {
 		return 0;
 	}
 
@@ -242,7 +242,7 @@
 	/* Check if RDID is usable and does not return 0xff 0xff 0xff or
 	 * 0x00 0x00 0x00. In that case, RES is pointless.
 	 */
-	if (!spi_rdid(readarr, 3) && memcmp(readarr, allff, 3) &&
+	if (!spi_rdid(flash, readarr, 3) && memcmp(readarr, allff, 3) &&
 	    memcmp(readarr, all00, 3)) {
 		msg_cdbg("Ignoring RES in favour of RDID.\n");
 		return 0;
@@ -250,13 +250,13 @@
 	/* Check if REMS is usable and does not return 0xff 0xff or
 	 * 0x00 0x00. In that case, RES is pointless.
 	 */
-	if (!spi_rems(readarr) && memcmp(readarr, allff, JEDEC_REMS_INSIZE) &&
+	if (!spi_rems(flash, readarr) && memcmp(readarr, allff, JEDEC_REMS_INSIZE) &&
 	    memcmp(readarr, all00, JEDEC_REMS_INSIZE)) {
 		msg_cdbg("Ignoring RES in favour of REMS.\n");
 		return 0;
 	}
 
-	if (spi_res(readarr, 1)) {
+	if (spi_res(flash, readarr, 1)) {
 		return 0;
 	}
 
@@ -279,7 +279,7 @@
 	unsigned char readarr[2];
 	uint32_t id1, id2;
 
-	if (spi_res(readarr, 2)) {
+	if (spi_res(flash, readarr, 2)) {
 		return 0;
 	}
 
@@ -298,7 +298,7 @@
 	return 1;
 }
 
-uint8_t spi_read_status_register(void)
+uint8_t spi_read_status_register(struct flashchip *flash)
 {
 	static const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR };
 	/* FIXME: No workarounds for driver/hardware bugs in generic code. */
@@ -306,7 +306,7 @@
 	int ret;
 
 	/* Read Status Register */
-	ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr);
+	ret = spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, readarr);
 	if (ret)
 		msg_cerr("RDSR failed!\n");
 
@@ -414,7 +414,7 @@
 {
 	uint8_t status;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
 	switch (flash->manufacture_id) {
 	case ST_ID:
@@ -465,7 +465,7 @@
 		.readarr	= NULL,
 	}};
 	
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution\n",
 			__func__);
@@ -475,7 +475,7 @@
 	 * This usually takes 1-85 s, so wait in 1 s steps.
 	 */
 	/* FIXME: We assume spi_read_status_register will never fail. */
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 		programmer_delay(1000 * 1000);
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -502,7 +502,7 @@
 		.readarr	= NULL,
 	}};
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution\n", __func__);
 		return result;
@@ -511,7 +511,7 @@
 	 * This usually takes 1-85 s, so wait in 1 s steps.
 	 */
 	/* FIXME: We assume spi_read_status_register will never fail. */
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 		programmer_delay(1000 * 1000);
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -543,7 +543,7 @@
 		.readarr	= NULL,
 	}};
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
@@ -552,7 +552,7 @@
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 100-4000 ms, so wait in 100 ms steps.
 	 */
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 		programmer_delay(100 * 1000);
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -589,7 +589,7 @@
 		.readarr	= NULL,
 	}};
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
@@ -598,7 +598,7 @@
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 100-4000 ms, so wait in 100 ms steps.
 	 */
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 		programmer_delay(100 * 1000);
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -633,7 +633,7 @@
 		.readarr	= NULL,
 	}};
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
@@ -642,7 +642,7 @@
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 100-4000 ms, so wait in 100 ms steps.
 	 */
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 		programmer_delay(100 * 1000);
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -675,7 +675,7 @@
 		.readarr	= NULL,
 	}};
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
@@ -684,7 +684,7 @@
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 15-800 ms, so wait in 10 ms steps.
 	 */
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 		programmer_delay(10 * 1000);
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -710,13 +710,13 @@
 	return spi_chip_erase_c7(flash);
 }
 
-int spi_write_status_enable(void)
+int spi_write_status_enable(struct flashchip *flash)
 {
 	static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR };
 	int result;
 
 	/* Send EWSR (Enable Write Status Register). */
-	result = spi_send_command(sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL);
+	result = spi_send_command(flash, sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL);
 
 	if (result)
 		msg_cerr("%s failed\n", __func__);
@@ -751,7 +751,7 @@
 		.readarr	= NULL,
 	}};
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution\n",
 			__func__);
@@ -766,7 +766,7 @@
 	 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
 	 */
 	programmer_delay(100 * 1000);
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) {
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) {
 		if (++i > 490) {
 			msg_cerr("Error: WIP bit after WRSR never cleared\n");
 			return TIMEOUT_ERROR;
@@ -799,7 +799,7 @@
 		.readarr	= NULL,
 	}};
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution\n",
 			__func__);
@@ -814,7 +814,7 @@
 	 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
 	 */
 	programmer_delay(100 * 1000);
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) {
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) {
 		if (++i > 490) {
 			msg_cerr("Error: WIP bit after WRSR never cleared\n");
 			return TIMEOUT_ERROR;
@@ -840,7 +840,7 @@
 	return ret;
 }
 
-int spi_byte_program(int addr, uint8_t databyte)
+int spi_byte_program(struct flashchip *flash, int addr, uint8_t databyte)
 {
 	int result;
 	struct spi_command cmds[] = {
@@ -867,7 +867,7 @@
 		.readarr	= NULL,
 	}};
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
@@ -875,7 +875,7 @@
 	return result;
 }
 
-int spi_nbyte_program(int addr, uint8_t *bytes, int len)
+int spi_nbyte_program(struct flashchip *flash, int addr, uint8_t *bytes, int len)
 {
 	int result;
 	/* FIXME: Switch to malloc based on len unless that kills speed. */
@@ -914,7 +914,7 @@
 
 	memcpy(&cmd[4], bytes, len);
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
@@ -931,7 +931,7 @@
 	uint8_t status;
 	int result;
 
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	/* If block protection is disabled, stop here. */
 	if ((status & 0x3c) == 0)
 		return 0;
@@ -942,7 +942,7 @@
 		msg_cerr("spi_write_status_register failed\n");
 		return result;
 	}
-	status = spi_read_status_register();
+	status = spi_read_status_register(flash);
 	if ((status & 0x3c) != 0) {
 		msg_cerr("Block protection could not be disabled!\n");
 		return 1;
@@ -950,7 +950,7 @@
 	return 0;
 }
 
-int spi_nbyte_read(int address, uint8_t *bytes, int len)
+int spi_nbyte_read(struct flashchip *flash, int address, uint8_t *bytes, int len)
 {
 	const unsigned char cmd[JEDEC_READ_OUTSIZE] = {
 		JEDEC_READ,
@@ -960,7 +960,7 @@
 	};
 
 	/* Send Read */
-	return spi_send_command(sizeof(cmd), len, cmd, bytes);
+	return spi_send_command(flash, sizeof(cmd), len, cmd, bytes);
 }
 
 /*
@@ -992,7 +992,7 @@
 		lenhere = min(start + len, (i + 1) * page_size) - starthere;
 		for (j = 0; j < lenhere; j += chunksize) {
 			toread = min(chunksize, lenhere - j);
-			rc = spi_nbyte_read(starthere + j, buf + starthere - start + j, toread);
+			rc = spi_nbyte_read(flash, starthere + j, buf + starthere - start + j, toread);
 			if (rc)
 				break;
 		}
@@ -1037,10 +1037,10 @@
 		lenhere = min(start + len, (i + 1) * page_size) - starthere;
 		for (j = 0; j < lenhere; j += chunksize) {
 			towrite = min(chunksize, lenhere - j);
-			rc = spi_nbyte_program(starthere + j, buf + starthere - start + j, towrite);
+			rc = spi_nbyte_program(flash, starthere + j, buf + starthere - start + j, towrite);
 			if (rc)
 				break;
-			while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+			while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 				programmer_delay(10);
 		}
 		if (rc)
@@ -1062,10 +1062,10 @@
 	int i, result = 0;
 
 	for (i = start; i < start + len; i++) {
-		result = spi_byte_program(i, buf[i - start]);
+		result = spi_byte_program(flash, i, buf[i - start]);
 		if (result)
 			return 1;
-		while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+		while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 			programmer_delay(10);
 	}
 
@@ -1104,7 +1104,7 @@
 		.readarr	= NULL,
 	}};
 
-	switch (spi_programmer->type) {
+	switch (flash->pgm->spi.type) {
 #if CONFIG_INTERNAL == 1
 #if defined(__i386__) || defined(__x86_64__)
 	case SPI_CONTROLLER_IT87XX:
@@ -1150,7 +1150,7 @@
 	}
 
 
-	result = spi_send_multicommand(cmds);
+	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during start command execution\n",
 			 __func__);
@@ -1159,7 +1159,7 @@
 		 */
 		return result;
 	}
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+	while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 		programmer_delay(10);
 
 	/* We already wrote 2 bytes in the multicommand step. */
@@ -1169,15 +1169,15 @@
 	while (pos < start + len - 1) {
 		cmd[1] = buf[pos++ - start];
 		cmd[2] = buf[pos++ - start];
-		spi_send_command(JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
-		while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+		spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
+		while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
 			programmer_delay(10);
 	}
 
 	/* Use WRDI to exit AAI mode. This needs to be done before issuing any
 	 * other non-AAI command.
 	 */
-	spi_write_disable();
+	spi_write_disable(flash);
 
 	/* Write remaining byte (if any). */
 	if (pos < start + len) {
Index: flashrom-register_all_programmers_register_generic_structflashchip/pm49fl00x.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/pm49fl00x.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/pm49fl00x.c	(Arbeitskopie)
@@ -22,7 +22,7 @@
 
 #include "flash.h"
 
-static void write_lockbits_49fl00x(chipaddr bios, int size,
+static void write_lockbits_49fl00x(const struct flashchip *flash, chipaddr bios, int size,
 			    unsigned char bits, int block_size)
 {
 	int i, left = size;
@@ -32,18 +32,18 @@
 		if (block_size == 16384 && i % 2)
 			continue;
 
-		chip_writeb(bits, bios + (i * block_size) + 2);
+		chip_writeb(flash, bits, bios + (i * block_size) + 2);
 	}
 }
 
 int unlock_49fl00x(struct flashchip *flash)
 {
-	write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 0, flash->page_size);
+	write_lockbits_49fl00x(flash, flash->virtual_registers, flash->total_size * 1024, 0, flash->page_size);
 	return 0;
 }
 
 int lock_49fl00x(struct flashchip *flash)
 {
-	write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 1, flash->page_size);
+	write_lockbits_49fl00x(flash, flash->virtual_registers, flash->total_size * 1024, 1, flash->page_size);
 	return 0;
 }
Index: flashrom-register_all_programmers_register_generic_structflashchip/it85spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/it85spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/it85spi.c	(Arbeitskopie)
@@ -270,7 +270,7 @@
 	return 0;
 }
 
-static int it85xx_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int it85xx_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			const unsigned char *writearr, unsigned char *readarr);
 
 static const struct spi_programmer spi_programmer_it85xx = {
@@ -320,7 +320,7 @@
  *   3. read date from LPC/FWH address 0xffff_fdxxh (drive CE# low and get
  *      data from MISO)
  */
-static int it85xx_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int it85xx_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			const unsigned char *writearr, unsigned char *readarr)
 {
 	int i;
Index: flashrom-register_all_programmers_register_generic_structflashchip/buspirate_spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/buspirate_spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/buspirate_spi.c	(Arbeitskopie)
@@ -86,7 +86,7 @@
 	return 0;
 }
 
-static int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int buspirate_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr);
 
 static const struct spi_programmer spi_programmer_buspirate = {
@@ -291,7 +291,7 @@
 	return 0;
 }
 
-static int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int buspirate_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr)
 {
 	static unsigned char *buf = NULL;
Index: flashrom-register_all_programmers_register_generic_structflashchip/linux_spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/linux_spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/linux_spi.c	(Arbeitskopie)
@@ -34,7 +34,7 @@
 static int fd = -1;
 
 static int linux_spi_shutdown(void *data);
-static int linux_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int linux_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			const unsigned char *txbuf, unsigned char *rxbuf);
 static int linux_spi_read(struct flashchip *flash, uint8_t *buf, int start,
 			  int len);
@@ -107,7 +107,7 @@
 	return 0;
 }
 
-static int linux_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int linux_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			const unsigned char *txbuf, unsigned char *rxbuf)
 {
 	struct spi_ioc_transfer msg[2] = {
Index: flashrom-register_all_programmers_register_generic_structflashchip/w29ee011.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/w29ee011.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/w29ee011.c	(Arbeitskopie)
@@ -38,29 +38,29 @@
 	}
 
 	/* Issue JEDEC Product ID Entry command */
-	chip_writeb(0xAA, bios + 0x5555);
+	chip_writeb(flash, 0xAA, bios + 0x5555);
 	programmer_delay(10);
-	chip_writeb(0x55, bios + 0x2AAA);
+	chip_writeb(flash, 0x55, bios + 0x2AAA);
 	programmer_delay(10);
-	chip_writeb(0x80, bios + 0x5555);
+	chip_writeb(flash, 0x80, bios + 0x5555);
 	programmer_delay(10);
-	chip_writeb(0xAA, bios + 0x5555);
+	chip_writeb(flash, 0xAA, bios + 0x5555);
 	programmer_delay(10);
-	chip_writeb(0x55, bios + 0x2AAA);
+	chip_writeb(flash, 0x55, bios + 0x2AAA);
 	programmer_delay(10);
-	chip_writeb(0x60, bios + 0x5555);
+	chip_writeb(flash, 0x60, bios + 0x5555);
 	programmer_delay(10);
 
 	/* Read product ID */
-	id1 = chip_readb(bios);
-	id2 = chip_readb(bios + 0x01);
+	id1 = chip_readb(flash, bios);
+	id2 = chip_readb(flash, bios + 0x01);
 
 	/* Issue JEDEC Product ID Exit command */
-	chip_writeb(0xAA, bios + 0x5555);
+	chip_writeb(flash, 0xAA, bios + 0x5555);
 	programmer_delay(10);
-	chip_writeb(0x55, bios + 0x2AAA);
+	chip_writeb(flash, 0x55, bios + 0x2AAA);
 	programmer_delay(10);
-	chip_writeb(0xF0, bios + 0x5555);
+	chip_writeb(flash, 0xF0, bios + 0x5555);
 	programmer_delay(10);
 
 	msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
Index: flashrom-register_all_programmers_register_generic_structflashchip/atahpt.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/atahpt.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/atahpt.c	(Arbeitskopie)
@@ -40,6 +40,8 @@
 	{},
 };
 
+static void atahpt_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t atahpt_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_atahpt = {
 		.chip_readb		= atahpt_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -80,13 +82,13 @@
 	return 0;
 }
 
-void atahpt_chip_writeb(uint8_t val, chipaddr addr)
+static void atahpt_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR);
 	OUTB(val, io_base_addr + BIOS_ROM_DATA);
 }
 
-uint8_t atahpt_chip_readb(const chipaddr addr)
+static uint8_t atahpt_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR);
 	return INB(io_base_addr + BIOS_ROM_DATA);
Index: flashrom-register_all_programmers_register_generic_structflashchip/nic3com.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/nic3com.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/nic3com.c	(Arbeitskopie)
@@ -55,6 +55,8 @@
 	{},
 };
 
+static void nic3com_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t nic3com_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_nic3com = {
 		.chip_readb		= nic3com_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -116,13 +118,13 @@
 	return 0;
 }
 
-void nic3com_chip_writeb(uint8_t val, chipaddr addr)
+static void nic3com_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR);
 	OUTB(val, io_base_addr + BIOS_ROM_DATA);
 }
 
-uint8_t nic3com_chip_readb(const chipaddr addr)
+static uint8_t nic3com_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR);
 	return INB(io_base_addr + BIOS_ROM_DATA);
Index: flashrom-register_all_programmers_register_generic_structflashchip/spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/spi.c	(Arbeitskopie)
@@ -30,45 +30,33 @@
 #include "programmer.h"
 #include "spi.h"
 
-const struct spi_programmer spi_programmer_none = {
-	.type = SPI_CONTROLLER_NONE,
-	.max_data_read = MAX_DATA_UNSPECIFIED,
-	.max_data_write = MAX_DATA_UNSPECIFIED,
-	.command = NULL,
-	.multicommand = NULL,
-	.read = NULL,
-	.write_256 = NULL,
-};
-
-const struct spi_programmer *spi_programmer = &spi_programmer_none;
-
-int spi_send_command(unsigned int writecnt, unsigned int readcnt,
+int spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr)
 {
-	if (!spi_programmer->command) {
+	if (!flash->pgm->spi.command) {
 		msg_perr("%s called, but SPI is unsupported on this "
 			 "hardware. Please report a bug at "
 			 "flashrom at flashrom.org\n", __func__);
 		return 1;
 	}
 
-	return spi_programmer->command(writecnt, readcnt,
+	return flash->pgm->spi.command(flash, writecnt, readcnt,
 						      writearr, readarr);
 }
 
-int spi_send_multicommand(struct spi_command *cmds)
+int spi_send_multicommand(struct flashchip *flash, struct spi_command *cmds)
 {
-	if (!spi_programmer->multicommand) {
+	if (!flash->pgm->spi.multicommand) {
 		msg_perr("%s called, but SPI is unsupported on this "
 			 "hardware. Please report a bug at "
 			 "flashrom at flashrom.org\n", __func__);
 		return 1;
 	}
 
-	return spi_programmer->multicommand(cmds);
+	return flash->pgm->spi.multicommand(flash, cmds);
 }
 
-int default_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+int default_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			     const unsigned char *writearr, unsigned char *readarr)
 {
 	struct spi_command cmd[] = {
@@ -84,14 +72,14 @@
 		.readarr = NULL,
 	}};
 
-	return spi_send_multicommand(cmd);
+	return spi_send_multicommand(flash, cmd);
 }
 
-int default_spi_send_multicommand(struct spi_command *cmds)
+int default_spi_send_multicommand(struct flashchip *flash, struct spi_command *cmds)
 {
 	int result = 0;
 	for (; (cmds->writecnt || cmds->readcnt) && !result; cmds++) {
-		result = spi_send_command(cmds->writecnt, cmds->readcnt,
+		result = spi_send_command(flash, cmds->writecnt, cmds->readcnt,
 					  cmds->writearr, cmds->readarr);
 	}
 	return result;
@@ -99,7 +87,7 @@
 
 int default_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
-	int max_data = spi_programmer->max_data_read;
+	int max_data = flash->pgm->spi.max_data_read;
 	if (max_data == MAX_DATA_UNSPECIFIED) {
 		msg_perr("%s called, but SPI read chunk size not defined "
 			 "on this hardware. Please report a bug at "
@@ -111,7 +99,7 @@
 
 int default_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
-	int max_data = spi_programmer->max_data_write;
+	int max_data = flash->pgm->spi.max_data_write;
 	if (max_data == MAX_DATA_UNSPECIFIED) {
 		msg_perr("%s called, but SPI write chunk size not defined "
 			 "on this hardware. Please report a bug at "
@@ -124,7 +112,7 @@
 int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
 	int addrbase = 0;
-	if (!spi_programmer->read) {
+	if (!flash->pgm->spi.read) {
 		msg_perr("%s called, but SPI read is unsupported on this "
 			 "hardware. Please report a bug at "
 			 "flashrom at flashrom.org\n", __func__);
@@ -135,7 +123,7 @@
 	 * address. Highest possible address with the current SPI implementation
 	 * means 0xffffff, the highest unsigned 24bit number.
 	 */
-	addrbase = spi_get_valid_read_addr();
+	addrbase = spi_get_valid_read_addr(flash);
 	if (addrbase + flash->total_size * 1024 > (1 << 24)) {
 		msg_perr("Flash chip size exceeds the allowed access window. ");
 		msg_perr("Read will probably fail.\n");
@@ -150,7 +138,7 @@
 			 "access window.\n");
 		msg_perr("Read will probably return garbage.\n");
 	}
-	return spi_programmer->read(flash, buf, addrbase + start, len);
+	return flash->pgm->spi.read(flash, buf, addrbase + start, len);
 }
 
 /*
@@ -162,14 +150,14 @@
 /* real chunksize is up to 256, logical chunksize is 256 */
 int spi_chip_write_256(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
-	if (!spi_programmer->write_256) {
+	if (!flash->pgm->spi.write_256) {
 		msg_perr("%s called, but SPI page write is unsupported on this "
 			 "hardware. Please report a bug at "
 			 "flashrom at flashrom.org\n", __func__);
 		return 1;
 	}
 
-	return spi_programmer->write_256(flash, buf, start, len);
+	return flash->pgm->spi.write_256(flash, buf, start, len);
 }
 
 /*
@@ -177,9 +165,9 @@
  * be the lowest allowed address for all commands which take an address.
  * This is a programmer limitation.
  */
-uint32_t spi_get_valid_read_addr(void)
+uint32_t spi_get_valid_read_addr(struct flashchip *flash)
 {
-	switch (spi_programmer->type) {
+	switch (flash->pgm->spi.type) {
 #if CONFIG_INTERNAL == 1
 #if defined(__i386__) || defined(__x86_64__)
 	case SPI_CONTROLLER_ICH7:
@@ -194,6 +182,9 @@
 
 void register_spi_programmer(const struct spi_programmer *pgm)
 {
-	spi_programmer = pgm;
-	buses_supported |= BUS_SPI;
+	struct registered_programmer rpgm;
+
+	rpgm.buses_supported = BUS_SPI;
+	rpgm.spi = *pgm;
+	register_programmer(&rpgm);
 }
Index: flashrom-register_all_programmers_register_generic_structflashchip/ft2232_spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/ft2232_spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/ft2232_spi.c	(Arbeitskopie)
@@ -144,7 +144,7 @@
 	return 0;
 }
 
-static int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int ft2232_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr);
 
 static const struct spi_programmer spi_programmer_ft2232 = {
@@ -342,7 +342,7 @@
 }
 
 /* Returns 0 upon success, a negative number upon errors. */
-static int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int ft2232_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr)
 {
 	struct ftdi_context *ftdic = &ftdic_context;
Index: flashrom-register_all_programmers_register_generic_structflashchip/satasii.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/satasii.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/satasii.c	(Arbeitskopie)
@@ -42,6 +42,8 @@
 	{},
 };
 
+static void satasii_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t satasii_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_satasii = {
 		.chip_readb		= satasii_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -95,7 +97,7 @@
 	return 0;
 }
 
-void satasii_chip_writeb(uint8_t val, chipaddr addr)
+static void satasii_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	uint32_t ctrl_reg, data_reg;
 
@@ -112,7 +114,7 @@
 	while (pci_mmio_readl(sii_bar) & (1 << 25)) ;
 }
 
-uint8_t satasii_chip_readb(const chipaddr addr)
+static uint8_t satasii_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	uint32_t ctrl_reg;
 
Index: flashrom-register_all_programmers_register_generic_structflashchip/wbsio_spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/wbsio_spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/wbsio_spi.c	(Arbeitskopie)
@@ -60,7 +60,7 @@
 	return flashport;
 }
 
-static int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int wbsio_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		      const unsigned char *writearr, unsigned char *readarr);
 static int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
 
@@ -110,7 +110,7 @@
  * Would one more byte of RAM in the chip (to get all 24 bits) really make
  * such a big difference?
  */
-static int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int wbsio_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		      const unsigned char *writearr, unsigned char *readarr)
 {
 	int i;
Index: flashrom-register_all_programmers_register_generic_structflashchip/sst28sf040.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/sst28sf040.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/sst28sf040.c	(Arbeitskopie)
@@ -34,13 +34,13 @@
 {
 	chipaddr bios = flash->virtual_memory;
 
-	chip_readb(bios + 0x1823);
-	chip_readb(bios + 0x1820);
-	chip_readb(bios + 0x1822);
-	chip_readb(bios + 0x0418);
-	chip_readb(bios + 0x041B);
-	chip_readb(bios + 0x0419);
-	chip_readb(bios + 0x040A);
+	chip_readb(flash, bios + 0x1823);
+	chip_readb(flash, bios + 0x1820);
+	chip_readb(flash, bios + 0x1822);
+	chip_readb(flash, bios + 0x0418);
+	chip_readb(flash, bios + 0x041B);
+	chip_readb(flash, bios + 0x0419);
+	chip_readb(flash, bios + 0x040A);
 
 	return 0;
 }
@@ -49,13 +49,13 @@
 {
 	chipaddr bios = flash->virtual_memory;
 
-	chip_readb(bios + 0x1823);
-	chip_readb(bios + 0x1820);
-	chip_readb(bios + 0x1822);
-	chip_readb(bios + 0x0418);
-	chip_readb(bios + 0x041B);
-	chip_readb(bios + 0x0419);
-	chip_readb(bios + 0x041A);
+	chip_readb(flash, bios + 0x1823);
+	chip_readb(flash, bios + 0x1820);
+	chip_readb(flash, bios + 0x1822);
+	chip_readb(flash, bios + 0x0418);
+	chip_readb(flash, bios + 0x041B);
+	chip_readb(flash, bios + 0x0419);
+	chip_readb(flash, bios + 0x041A);
 
 	return 0;
 }
@@ -65,11 +65,11 @@
 	chipaddr bios = flash->virtual_memory;
 
 	/* This command sequence is very similar to erase_block_82802ab. */
-	chip_writeb(AUTO_PG_ERASE1, bios);
-	chip_writeb(AUTO_PG_ERASE2, bios + address);
+	chip_writeb(flash, AUTO_PG_ERASE1, bios);
+	chip_writeb(flash, AUTO_PG_ERASE2, bios + address);
 
 	/* wait for Toggle bit ready */
-	toggle_ready_jedec(bios);
+	toggle_ready_jedec(flash, bios);
 
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -90,11 +90,11 @@
 			continue;
 		}
 		/*issue AUTO PROGRAM command */
-		chip_writeb(AUTO_PGRM, dst);
-		chip_writeb(*src++, dst++);
+		chip_writeb(flash, AUTO_PGRM, dst);
+		chip_writeb(flash, *src++, dst++);
 
 		/* wait for Toggle bit ready */
-		toggle_ready_jedec(bios);
+		toggle_ready_jedec(flash, bios);
 	}
 
 	return 0;
@@ -104,11 +104,11 @@
 {
 	chipaddr bios = flash->virtual_memory;
 
-	chip_writeb(CHIP_ERASE, bios);
-	chip_writeb(CHIP_ERASE, bios);
+	chip_writeb(flash, CHIP_ERASE, bios);
+	chip_writeb(flash, CHIP_ERASE, bios);
 
 	programmer_delay(10);
-	toggle_ready_jedec(bios);
+	toggle_ready_jedec(flash, bios);
 
 	/* FIXME: Check the status register for errors. */
 	return 0;
Index: flashrom-register_all_programmers_register_generic_structflashchip/stm50flw0x0x.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/stm50flw0x0x.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/stm50flw0x0x.c	(Arbeitskopie)
@@ -60,8 +60,8 @@
 		// unlock each 4k-sector
 		for (j = 0; j < 0x10000; j += 0x1000) {
 			msg_cdbg("unlocking at 0x%x\n", offset + j);
-			chip_writeb(unlock_sector, wrprotect + offset + j);
-			if (chip_readb(wrprotect + offset + j) != unlock_sector) {
+			chip_writeb(flash, unlock_sector, wrprotect + offset + j);
+			if (chip_readb(flash, wrprotect + offset + j) != unlock_sector) {
 				msg_cerr("Cannot unlock sector @ 0x%x\n",
 				       offset + j);
 				return -1;
@@ -69,8 +69,8 @@
 		}
 	} else {
 		msg_cdbg("unlocking at 0x%x\n", offset);
-		chip_writeb(unlock_sector, wrprotect + offset);
-		if (chip_readb(wrprotect + offset) != unlock_sector) {
+		chip_writeb(flash, unlock_sector, wrprotect + offset);
+		if (chip_readb(flash, wrprotect + offset) != unlock_sector) {
 			msg_cerr("Cannot unlock sector @ 0x%x\n", offset);
 			return -1;
 		}
@@ -99,10 +99,10 @@
 	chipaddr bios = flash->virtual_memory + sector;
 
 	// clear status register
-	chip_writeb(0x50, bios);
+	chip_writeb(flash, 0x50, bios);
 	// now start it
-	chip_writeb(0x32, bios);
-	chip_writeb(0xd0, bios);
+	chip_writeb(flash, 0x32, bios);
+	chip_writeb(flash, 0xd0, bios);
 	programmer_delay(10);
 
 	wait_82802ab(flash);
Index: flashrom-register_all_programmers_register_generic_structflashchip/nicintel.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/nicintel.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/nicintel.c	(Arbeitskopie)
@@ -43,6 +43,8 @@
 
 #define CSR_FCR 0x0c
 
+static void nicintel_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+static uint8_t nicintel_chip_readb(const struct flashchip *flash, const chipaddr addr);
 static const struct par_programmer par_programmer_nicintel = {
 		.chip_readb		= nicintel_chip_readb,
 		.chip_readw		= fallback_chip_readw,
@@ -117,12 +119,12 @@
 	return 1;
 }
 
-void nicintel_chip_writeb(uint8_t val, chipaddr addr)
+static void nicintel_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 	pci_mmio_writeb(val, nicintel_bar + (addr & NICINTEL_MEMMAP_MASK));
 }
 
-uint8_t nicintel_chip_readb(const chipaddr addr)
+static uint8_t nicintel_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	return pci_mmio_readb(nicintel_bar + (addr & NICINTEL_MEMMAP_MASK));
 }
Index: flashrom-register_all_programmers_register_generic_structflashchip/sb600spi.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/sb600spi.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/sb600spi.c	(Arbeitskopie)
@@ -88,7 +88,7 @@
 		;
 }
 
-static int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+static int sb600_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		      const unsigned char *writearr, unsigned char *readarr)
 {
 	int count;
Index: flashrom-register_all_programmers_register_generic_structflashchip/programmer.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/programmer.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/programmer.c	(Arbeitskopie)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the flashrom project.
  *
- * Copyright (C) 2009,2010 Carl-Daniel Hailfinger
+ * Copyright (C) 2009,2010,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
@@ -21,19 +21,6 @@
 #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,
-};
-
-const struct par_programmer *par_programmer = &par_programmer_none;
-
 /* No-op shutdown() for programmers which don't need special handling */
 int noop_shutdown(void)
 {
@@ -53,66 +40,98 @@
 }
 
 /* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
-uint8_t noop_chip_readb(const chipaddr addr)
+uint8_t noop_chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
 	return 0xff;
 }
 
 /* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
-void noop_chip_writeb(uint8_t val, chipaddr addr)
+void noop_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
 }
 
 /* Little-endian fallback for drivers not supporting 16 bit accesses */
-void fallback_chip_writew(uint16_t val, chipaddr addr)
+void fallback_chip_writew(const struct flashchip *flash, uint16_t val, chipaddr addr)
 {
-	chip_writeb(val & 0xff, addr);
-	chip_writeb((val >> 8) & 0xff, addr + 1);
+	chip_writeb(flash, val & 0xff, addr);
+	chip_writeb(flash, (val >> 8) & 0xff, addr + 1);
 }
 
 /* Little-endian fallback for drivers not supporting 16 bit accesses */
-uint16_t fallback_chip_readw(const chipaddr addr)
+uint16_t fallback_chip_readw(const struct flashchip *flash, const chipaddr addr)
 {
 	uint16_t val;
-	val = chip_readb(addr);
-	val |= chip_readb(addr + 1) << 8;
+	val = chip_readb(flash, addr);
+	val |= chip_readb(flash, addr + 1) << 8;
 	return val;
 }
 
 /* Little-endian fallback for drivers not supporting 32 bit accesses */
-void fallback_chip_writel(uint32_t val, chipaddr addr)
+void fallback_chip_writel(const struct flashchip *flash, uint32_t val, chipaddr addr)
 {
-	chip_writew(val & 0xffff, addr);
-	chip_writew((val >> 16) & 0xffff, addr + 2);
+	chip_writew(flash, val & 0xffff, addr);
+	chip_writew(flash, (val >> 16) & 0xffff, addr + 2);
 }
 
 /* Little-endian fallback for drivers not supporting 32 bit accesses */
-uint32_t fallback_chip_readl(const chipaddr addr)
+uint32_t fallback_chip_readl(const struct flashchip *flash, const chipaddr addr)
 {
 	uint32_t val;
-	val = chip_readw(addr);
-	val |= chip_readw(addr + 2) << 16;
+	val = chip_readw(flash, addr);
+	val |= chip_readw(flash, addr + 2) << 16;
 	return val;
 }
 
-void fallback_chip_writen(uint8_t *buf, chipaddr addr, size_t len)
+void fallback_chip_writen(const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len)
 {
 	size_t i;
 	for (i = 0; i < len; i++)
-		chip_writeb(buf[i], addr + i);
+		chip_writeb(flash, buf[i], addr + i);
 	return;
 }
 
-void fallback_chip_readn(uint8_t *buf, chipaddr addr, size_t len)
+void fallback_chip_readn(const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len)
 {
 	size_t i;
 	for (i = 0; i < len; i++)
-		buf[i] = chip_readb(addr + i);
+		buf[i] = chip_readb(flash, addr + i);
 	return;
 }
 
 void register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses)
 {
-	par_programmer = pgm;
-	buses_supported |= buses;
+	struct registered_programmer rpgm;
+
+	rpgm.buses_supported = buses;
+	rpgm.par = *pgm;
+	register_programmer(&rpgm);
 }
+
+/* The limit of 4 is totally arbitrary. */
+#define PROGRAMMERS_MAX 4
+struct registered_programmer registered_programmers[PROGRAMMERS_MAX];
+int registered_programmer_count = 0;
+
+int register_programmer(struct registered_programmer *pgm)
+{
+	if (registered_programmer_count >= PROGRAMMERS_MAX) {
+		msg_perr("Tried to register more than %i programmer "
+			 "interfaces.\n", PROGRAMMERS_MAX);
+		return 1;
+	}
+	registered_programmers[registered_programmer_count] = *pgm;
+	registered_programmer_count++;
+
+	return 0;
+}
+
+enum chipbustype get_buses_supported(void)
+{
+	int i;
+	enum chipbustype ret = BUS_NONE;
+
+	for (i = 0; i < registered_programmer_count; i++)
+		ret |= registered_programmers[i].buses_supported;
+
+	return ret;
+}
Index: flashrom-register_all_programmers_register_generic_structflashchip/flashrom.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/flashrom.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/flashrom.c	(Arbeitskopie)
@@ -46,9 +46,6 @@
 
 static char *programmer_param = NULL;
 
-/* Supported buses for the current programmer. */
-enum chipbustype buses_supported;
-
 /*
  * Programmers supporting multiple buses can have differing size limits on
  * each bus. Store the limits for each bus in a common struct.
@@ -314,7 +311,6 @@
 		.fwh		= 0xffffffff,
 		.spi		= 0xffffffff,
 	};
-	buses_supported = BUS_NONE;
 	/* Default to top aligned flash at 4 GB. */
 	flashbase = 0;
 	/* Registering shutdown functions is now allowed. */
@@ -359,44 +355,44 @@
 	programmer_table[programmer].unmap_flash_region(virt_addr, len);
 }
 
-void chip_writeb(uint8_t val, chipaddr addr)
+void chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr)
 {
-	par_programmer->chip_writeb(val, addr);
+	flash->pgm->par.chip_writeb(flash, val, addr);
 }
 
-void chip_writew(uint16_t val, chipaddr addr)
+void chip_writew(const struct flashchip *flash, uint16_t val, chipaddr addr)
 {
-	par_programmer->chip_writew(val, addr);
+	flash->pgm->par.chip_writew(flash, val, addr);
 }
 
-void chip_writel(uint32_t val, chipaddr addr)
+void chip_writel(const struct flashchip *flash, uint32_t val, chipaddr addr)
 {
-	par_programmer->chip_writel(val, addr);
+	flash->pgm->par.chip_writel(flash, val, addr);
 }
 
-void chip_writen(uint8_t *buf, chipaddr addr, size_t len)
+void chip_writen(const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len)
 {
-	par_programmer->chip_writen(buf, addr, len);
+	flash->pgm->par.chip_writen(flash, buf, addr, len);
 }
 
-uint8_t chip_readb(const chipaddr addr)
+uint8_t chip_readb(const struct flashchip *flash, const chipaddr addr)
 {
-	return par_programmer->chip_readb(addr);
+	return flash->pgm->par.chip_readb(flash, addr);
 }
 
-uint16_t chip_readw(const chipaddr addr)
+uint16_t chip_readw(const struct flashchip *flash, const chipaddr addr)
 {
-	return par_programmer->chip_readw(addr);
+	return flash->pgm->par.chip_readw(flash, addr);
 }
 
-uint32_t chip_readl(const chipaddr addr)
+uint32_t chip_readl(const struct flashchip *flash, const chipaddr addr)
 {
-	return par_programmer->chip_readl(addr);
+	return flash->pgm->par.chip_readl(flash, addr);
 }
 
-void chip_readn(uint8_t *buf, chipaddr addr, size_t len)
+void chip_readn(const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len)
 {
-	par_programmer->chip_readn(buf, addr, len);
+	flash->pgm->par.chip_readn(flash, buf, addr, len);
 }
 
 void programmer_delay(int usecs)
@@ -414,7 +410,7 @@
 
 int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
-	chip_readn(buf, flash->virtual_memory + start, len);
+	chip_readn(flash, buf, flash->virtual_memory + start, len);
 
 	return 0;
 }
@@ -936,7 +932,8 @@
 	return 1;
 }
 
-int probe_flash(int startchip, struct flashchip *fill_flash, int force)
+int probe_flash(struct registered_programmer *pgm, int startchip,
+		struct flashchip *fill_flash, int force)
 {
 	const struct flashchip *flash;
 	unsigned long base = 0;
@@ -948,11 +945,12 @@
 	for (flash = flashchips + startchip; flash && flash->name; flash++) {
 		if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0)
 			continue;
-		buses_common = buses_supported & flash->bustype;
+		buses_common = pgm->buses_supported & flash->bustype;
 		if (!buses_common) {
+#if 0 // Does not really make sense anymore if we use a programmer-centric walk.
 			msg_gspew("Probing for %s %s, %d kB: skipped. ",
 			         flash->vendor, flash->name, flash->total_size);
-			tmp = flashbuses_to_text(buses_supported);
+			tmp = flashbuses_to_text(get_buses_supported());
 			msg_gspew("Host bus type %s ", tmp);
 			free(tmp);
 			tmp = flashbuses_to_text(flash->bustype);
@@ -960,6 +958,7 @@
 				  tmp);
 			free(tmp);
 			msg_gspew("\n");
+#endif
 			continue;
 		}
 		msg_gdbg("Probing for %s %s, %d kB: ",
@@ -975,6 +974,7 @@
 
 		/* Start filling in the dynamic data. */
 		*fill_flash = *flash;
+		fill_flash->pgm = pgm;
 
 		base = flashbase ? flashbase : (0xffffffff - size + 1);
 		fill_flash->virtual_memory = (chipaddr)programmer_map_flash_region("flash chip", base, size);
Index: flashrom-register_all_programmers_register_generic_structflashchip/programmer.h
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/programmer.h	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/programmer.h	(Arbeitskopie)
@@ -93,8 +93,8 @@
 
 	int (*init) (void);
 
-	void * (*map_flash_region) (const char *descr, unsigned long phys_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);
 
 	void (*delay) (int usecs);
@@ -300,13 +300,6 @@
 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);
-void internal_chip_writel(uint32_t val, chipaddr addr);
-uint8_t internal_chip_readb(const chipaddr addr);
-uint16_t internal_chip_readw(const chipaddr addr);
-uint32_t internal_chip_readl(const chipaddr addr);
-void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len);
 #endif
 
 /* hwaccess.c */
@@ -341,91 +334,46 @@
 void rmmio_valw(void *addr);
 void rmmio_vall(void *addr);
 
-/* programmer.c */
-int noop_shutdown(void);
-void *fallback_map(const char *descr, unsigned long phys_addr, size_t len);
-void fallback_unmap(void *virt_addr, size_t len);
-uint8_t noop_chip_readb(const chipaddr addr);
-void noop_chip_writeb(uint8_t val, chipaddr addr);
-void fallback_chip_writew(uint16_t val, chipaddr addr);
-void fallback_chip_writel(uint32_t val, chipaddr addr);
-void fallback_chip_writen(uint8_t *buf, chipaddr addr, size_t len);
-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);
-};
-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);
 void *dummy_map(const char *descr, unsigned long phys_addr, size_t len);
 void dummy_unmap(void *virt_addr, size_t len);
-void dummy_chip_writeb(uint8_t val, chipaddr addr);
-void dummy_chip_writew(uint16_t val, chipaddr addr);
-void dummy_chip_writel(uint32_t val, chipaddr addr);
-void dummy_chip_writen(uint8_t *buf, chipaddr addr, size_t len);
-uint8_t dummy_chip_readb(const chipaddr addr);
-uint16_t dummy_chip_readw(const chipaddr addr);
-uint32_t dummy_chip_readl(const chipaddr addr);
-void dummy_chip_readn(uint8_t *buf, const chipaddr addr, size_t len);
 #endif
 
 /* nic3com.c */
 #if CONFIG_NIC3COM == 1
 int nic3com_init(void);
-void nic3com_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t nic3com_chip_readb(const chipaddr addr);
 extern const struct pcidev_status nics_3com[];
 #endif
 
 /* gfxnvidia.c */
 #if CONFIG_GFXNVIDIA == 1
 int gfxnvidia_init(void);
-void gfxnvidia_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t gfxnvidia_chip_readb(const chipaddr addr);
 extern const struct pcidev_status gfx_nvidia[];
 #endif
 
 /* drkaiser.c */
 #if CONFIG_DRKAISER == 1
 int drkaiser_init(void);
-void drkaiser_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t drkaiser_chip_readb(const chipaddr addr);
 extern const struct pcidev_status drkaiser_pcidev[];
 #endif
 
 /* nicrealtek.c */
 #if CONFIG_NICREALTEK == 1
 int nicrealtek_init(void);
-void nicrealtek_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t nicrealtek_chip_readb(const chipaddr addr);
 extern const struct pcidev_status nics_realtek[];
 #endif
 
 /* nicnatsemi.c */
 #if CONFIG_NICNATSEMI == 1
 int nicnatsemi_init(void);
-void nicnatsemi_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t nicnatsemi_chip_readb(const chipaddr addr);
 extern const struct pcidev_status nics_natsemi[];
 #endif
 
 /* nicintel.c */
 #if CONFIG_NICINTEL == 1
 int nicintel_init(void);
-void nicintel_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t nicintel_chip_readb(const chipaddr addr);
 extern const struct pcidev_status nics_intel[];
 #endif
 
@@ -444,24 +392,18 @@
 /* satamv.c */
 #if CONFIG_SATAMV == 1
 int satamv_init(void);
-void satamv_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t satamv_chip_readb(const chipaddr addr);
 extern const struct pcidev_status satas_mv[];
 #endif
 
 /* satasii.c */
 #if CONFIG_SATASII == 1
 int satasii_init(void);
-void satasii_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t satasii_chip_readb(const chipaddr addr);
 extern const struct pcidev_status satas_sii[];
 #endif
 
 /* atahpt.c */
 #if CONFIG_ATAHPT == 1
 int atahpt_init(void);
-void atahpt_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t atahpt_chip_readb(const chipaddr addr);
 extern const struct pcidev_status ata_hpt[];
 #endif
 
@@ -556,7 +498,6 @@
 	SPI_CONTROLLER_SERPROG,
 #endif
 };
-extern const int spi_programmer_count;
 
 #define MAX_DATA_UNSPECIFIED 0
 #define MAX_DATA_READ_UNLIMITED 64 * 1024
@@ -565,19 +506,18 @@
 	enum spi_controller type;
 	int max_data_read;
 	int max_data_write;
-	int (*command)(unsigned int writecnt, unsigned int readcnt,
+	int (*command)(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 		   const unsigned char *writearr, unsigned char *readarr);
-	int (*multicommand)(struct spi_command *cmds);
+	int (*multicommand)(struct flashchip *flash, struct spi_command *cmds);
 
 	/* Optimized functions for this programmer */
 	int (*read)(struct flashchip *flash, uint8_t *buf, int start, int len);
 	int (*write_256)(struct flashchip *flash, uint8_t *buf, int start, int len);
 };
 
-extern const struct spi_programmer *spi_programmer;
-int default_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+int default_spi_send_command(struct flashchip *flash, unsigned int writecnt, unsigned int readcnt,
 			     const unsigned char *writearr, unsigned char *readarr);
-int default_spi_send_multicommand(struct spi_command *cmds);
+int default_spi_send_multicommand(struct flashchip *flash, struct spi_command *cmds);
 int default_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
 int default_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int len);
 void register_spi_programmer(const struct spi_programmer *programmer);
@@ -632,12 +572,44 @@
 extern const struct opaque_programmer *opaque_programmer;
 void register_opaque_programmer(const struct opaque_programmer *pgm);
 
+/* programmer.c */
+int noop_shutdown(void);
+void *fallback_map(const char *descr, unsigned long phys_addr, size_t len);
+void fallback_unmap(void *virt_addr, size_t len);
+uint8_t noop_chip_readb(const struct flashchip *flash, const chipaddr addr);
+void noop_chip_writeb(const struct flashchip *flash, uint8_t val, chipaddr addr);
+void fallback_chip_writew(const struct flashchip *flash, uint16_t val, chipaddr addr);
+void fallback_chip_writel(const struct flashchip *flash, uint32_t val, chipaddr addr);
+void fallback_chip_writen(const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len);
+uint16_t fallback_chip_readw(const struct flashchip *flash, const chipaddr addr);
+uint32_t fallback_chip_readl(const struct flashchip *flash, const chipaddr addr);
+void fallback_chip_readn(const struct flashchip *flash, uint8_t *buf, const chipaddr addr, size_t len);
+struct par_programmer {
+	void (*chip_writeb) (const struct flashchip *flash, uint8_t val, chipaddr addr);
+	void (*chip_writew) (const struct flashchip *flash, uint16_t val, chipaddr addr);
+	void (*chip_writel) (const struct flashchip *flash, uint32_t val, chipaddr addr);
+	void (*chip_writen) (const struct flashchip *flash, uint8_t *buf, chipaddr addr, size_t len);
+	uint8_t (*chip_readb) (const struct flashchip *flash, const chipaddr addr);
+	uint16_t (*chip_readw) (const struct flashchip *flash, const chipaddr addr);
+	uint32_t (*chip_readl) (const struct flashchip *flash, const chipaddr addr);
+	void (*chip_readn) (const struct flashchip *flash, uint8_t *buf, const chipaddr addr, size_t len);
+};
+void register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses);
+struct registered_programmer {
+	enum chipbustype buses_supported;
+	union {
+		struct par_programmer par;
+		struct spi_programmer spi;
+		struct opaque_programmer opaque;
+	};
+};
+extern struct registered_programmer registered_programmers[];
+extern int registered_programmer_count;
+int register_programmer(struct registered_programmer *pgm);
+
 /* serprog.c */
 #if CONFIG_SERPROG == 1
 int serprog_init(void);
-void serprog_chip_writeb(uint8_t val, chipaddr addr);
-uint8_t serprog_chip_readb(const chipaddr addr);
-void serprog_chip_readn(uint8_t *buf, const chipaddr addr, size_t len);
 void serprog_delay(int usecs);
 #endif
 
Index: flashrom-register_all_programmers_register_generic_structflashchip/chipdrivers.h
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/chipdrivers.h	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/chipdrivers.h	(Arbeitskopie)
@@ -33,8 +33,8 @@
 int probe_spi_rems(struct flashchip *flash);
 int probe_spi_res1(struct flashchip *flash);
 int probe_spi_res2(struct flashchip *flash);
-int spi_write_enable(void);
-int spi_write_disable(void);
+int spi_write_enable(struct flashchip *flash);
+int spi_write_disable(struct flashchip *flash);
 int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_d7(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
@@ -44,16 +44,16 @@
 int spi_chip_write_1(struct flashchip *flash, uint8_t *buf, int start, int len);
 int spi_chip_write_256(struct flashchip *flash, uint8_t *buf, int start, int len);
 int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len);
-uint8_t spi_read_status_register(void);
+uint8_t spi_read_status_register(struct flashchip *flash);
 int spi_write_status_register(struct flashchip *flash, int status);
 void spi_prettyprint_status_register_bit(uint8_t status, int bit);
 void spi_prettyprint_status_register_bp3210(uint8_t status, int bp);
 void spi_prettyprint_status_register_welwip(uint8_t status);
 int spi_prettyprint_status_register(struct flashchip *flash);
 int spi_disable_blockprotect(struct flashchip *flash);
-int spi_byte_program(int addr, uint8_t databyte);
-int spi_nbyte_program(int addr, uint8_t *bytes, int len);
-int spi_nbyte_read(int addr, uint8_t *bytes, int len);
+int spi_byte_program(struct flashchip *flash, int addr, uint8_t databyte);
+int spi_nbyte_program(struct flashchip *flash, int addr, uint8_t *bytes, int len);
+int spi_nbyte_read(struct flashchip *flash, int addr, uint8_t *bytes, int len);
 int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize);
 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);
@@ -95,9 +95,9 @@
 
 /* jedec.c */
 uint8_t oddparity(uint8_t val);
-void toggle_ready_jedec(chipaddr dst);
-void data_polling_jedec(chipaddr dst, uint8_t data);
-int write_byte_program_jedec(chipaddr bios, uint8_t *src,
+void toggle_ready_jedec(struct flashchip *flash, chipaddr dst);
+void data_polling_jedec(struct flashchip *flash, chipaddr dst, uint8_t data);
+int write_byte_program_jedec(struct flashchip *flash, chipaddr bios, uint8_t *src,
 			     chipaddr dst);
 int probe_jedec(struct flashchip *flash);
 int write_jedec(struct flashchip *flash, uint8_t *buf, int start, int len);
@@ -111,7 +111,7 @@
 int block_erase_m29f400bt(struct flashchip *flash, unsigned int start, unsigned int len);
 int block_erase_chip_m29f400bt(struct flashchip *flash, unsigned int start, unsigned int len);
 int write_m29f400bt(struct flashchip *flash, uint8_t *buf, int start, int len);
-void protect_m29f400bt(chipaddr bios);
+void protect_m29f400bt(struct flashchip *flash, chipaddr bios);
 
 /* pm49fl00x.c */
 int unlock_49fl00x(struct flashchip *flash);
Index: flashrom-register_all_programmers_register_generic_structflashchip/m29f400bt.c
===================================================================
--- flashrom-register_all_programmers_register_generic_structflashchip/m29f400bt.c	(Revision 1463)
+++ flashrom-register_all_programmers_register_generic_structflashchip/m29f400bt.c	(Arbeitskopie)
@@ -35,17 +35,17 @@
 	chipaddr dst = flash->virtual_memory + start;
 
 	for (i = 0; i < len; i++) {
-		chip_writeb(0xAA, bios + 0xAAA);
-		chip_writeb(0x55, bios + 0x555);
-		chip_writeb(0xA0, bios + 0xAAA);
+		chip_writeb(flash, 0xAA, bios + 0xAAA);
+		chip_writeb(flash, 0x55, bios + 0x555);
+		chip_writeb(flash, 0xA0, bios + 0xAAA);
 
 		/* transfer data from source to destination */
-		chip_writeb(*src, dst);
-		toggle_ready_jedec(dst);
+		chip_writeb(flash, *src, dst);
+		toggle_ready_jedec(flash, dst);
 #if 0
 		/* We only want to print something in the error case. */
 		msg_cerr("Value in the flash at address 0x%lx = %#x, want %#x\n",
-		     (dst - bios), chip_readb(dst), *src);
+		     (dst - bios), chip_readb(flash, dst), *src);
 #endif
 		dst++;
 		src++;
@@ -60,21 +60,21 @@
 	chipaddr bios = flash->virtual_memory;
 	uint8_t id1, id2;
 
-	chip_writeb(0xAA, bios + 0xAAA);
-	chip_writeb(0x55, bios + 0x555);
-	chip_writeb(0x90, bios + 0xAAA);
+	chip_writeb(flash, 0xAA, bios + 0xAAA);
+	chip_writeb(flash, 0x55, bios + 0x555);
+	chip_writeb(flash, 0x90, bios + 0xAAA);
 
 	programmer_delay(10);
 
-	id1 = chip_readb(bios);
+	id1 = chip_readb(flash, bios);
 	/* The data sheet says id2 is at (bios + 0x01) and id2 listed in
 	 * flash.h does not match. It should be possible to use JEDEC probe.
 	 */
-	id2 = chip_readb(bios + 0x02);
+	id2 = chip_readb(flash, bios + 0x02);
 
-	chip_writeb(0xAA, bios + 0xAAA);
-	chip_writeb(0x55, bios + 0x555);
-	chip_writeb(0xF0, bios + 0xAAA);
+	chip_writeb(flash, 0xAA, bios + 0xAAA);
+	chip_writeb(flash, 0x55, bios + 0x555);
+	chip_writeb(flash, 0xF0, bios + 0xAAA);
 
 	programmer_delay(10);
 
@@ -90,16 +90,16 @@
 {
 	chipaddr bios = flash->virtual_memory;
 
-	chip_writeb(0xAA, bios + 0xAAA);
-	chip_writeb(0x55, bios + 0x555);
-	chip_writeb(0x80, bios + 0xAAA);
+	chip_writeb(flash, 0xAA, bios + 0xAAA);
+	chip_writeb(flash, 0x55, bios + 0x555);
+	chip_writeb(flash, 0x80, bios + 0xAAA);
 
-	chip_writeb(0xAA, bios + 0xAAA);
-	chip_writeb(0x55, bios + 0x555);
-	chip_writeb(0x10, bios + 0xAAA);
+	chip_writeb(flash, 0xAA, bios + 0xAAA);
+	chip_writeb(flash, 0x55, bios + 0x555);
+	chip_writeb(flash, 0x10, bios + 0xAAA);
 
 	programmer_delay(10);
-	toggle_ready_jedec(bios);
+	toggle_ready_jedec(flash, bios);
 
 	/* FIXME: Check the status register for errors. */
 	return 0;
@@ -110,16 +110,16 @@
 	chipaddr bios = flash->virtual_memory;
 	chipaddr dst = bios + start;
 
-	chip_writeb(0xAA, bios + 0xAAA);
-	chip_writeb(0x55, bios + 0x555);
-	chip_writeb(0x80, bios + 0xAAA);
+	chip_writeb(flash, 0xAA, bios + 0xAAA);
+	chip_writeb(flash, 0x55, bios + 0x555);
+	chip_writeb(flash, 0x80, bios + 0xAAA);
 
-	chip_writeb(0xAA, bios + 0xAAA);
-	chip_writeb(0x55, bios + 0x555);
-	chip_writeb(0x30, dst);
+	chip_writeb(flash, 0xAA, bios + 0xAAA);
+	chip_writeb(flash, 0x55, bios + 0x555);
+	chip_writeb(flash, 0x30, dst);
 
 	programmer_delay(10);
-	toggle_ready_jedec(bios);
+	toggle_ready_jedec(flash, bios);
 
 	/* FIXME: Check the status register for errors. */
 	return 0;


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





More information about the flashrom mailing list