memory_bus: Move (un)map_flash_region into par master

Now that the map/unmap_flash functions are only called from memory-
mapped chip drivers, we can safely move the hooks into the parallel
masters.

This also allows us to move the code away from the globals in
`flashprog.c` into a new `memory_bus.c`.

Change-Id: Ic476cf4d96200232900537b997e1d07bb4e8b809
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/72522
Reviewed-by: Riku Viitanen <riku.viitanen@protonmail.com>
diff --git a/Makefile b/Makefile
index 1a9fb47..6da3458 100644
--- a/Makefile
+++ b/Makefile
@@ -383,7 +383,7 @@
 ###############################################################################
 # Flash chip drivers and bus support infrastructure.
 
-CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
+CHIP_OBJS = memory_bus.o jedec.o stm50.o w39.o w29ee011.o \
 	sst28sf040.o 82802ab.o \
 	sst49lfxxxc.o sst_fwhub.o edi.o flashchips.o spi.o spi25.o spi25_statusreg.o \
 	spi95.o opaque.o sfdp.o en29lv640b.o at45db.o \
diff --git a/atapromise.c b/atapromise.c
index a6e2d12..0dcb8c2 100644
--- a/atapromise.c
+++ b/atapromise.c
@@ -55,6 +55,7 @@
 
 static void atapromise_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr);
 static uint8_t atapromise_chip_readb(const struct flashctx *flash, const chipaddr addr);
+static void *atapromise_map(const char *descr, uintptr_t phys_addr, size_t len);
 
 static const struct par_master par_master_atapromise = {
 	.chip_readb	= atapromise_chip_readb,
@@ -65,6 +66,7 @@
 	.chip_writew	= fallback_chip_writew,
 	.chip_writel	= fallback_chip_writel,
 	.chip_writen	= fallback_chip_writen,
+	.map_flash	= atapromise_map,
 };
 
 static void *atapromise_map(const char *descr, uintptr_t phys_addr, size_t len)
@@ -169,5 +171,4 @@
 	.type			= PCI,
 	.devs.dev		= ata_promise,
 	.init			= atapromise_init,
-	.map_flash_region	= atapromise_map,
 };
diff --git a/atavia.c b/atavia.c
index e96c808..34d7b73 100644
--- a/atavia.c
+++ b/atavia.c
@@ -56,6 +56,7 @@
 
 static void atavia_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr);
 static uint8_t atavia_chip_readb(const struct flashctx *flash, const chipaddr addr);
+static void *atavia_map(const char *descr, uintptr_t phys_addr, size_t len);
 static const struct par_master lpc_master_atavia = {
 	.chip_readb	= atavia_chip_readb,
 	.chip_readw	= fallback_chip_readw,
@@ -65,6 +66,7 @@
 	.chip_writew	= fallback_chip_writew,
 	.chip_writel	= fallback_chip_writel,
 	.chip_writen	= fallback_chip_writen,
+	.map_flash	= atavia_map,
 };
 
 static void *atavia_offset = NULL;
@@ -191,5 +193,4 @@
 	.type			= PCI,
 	.devs.dev		= ata_via,
 	.init			= atavia_init,
-	.map_flash_region	= atavia_map,
 };
diff --git a/dummyflasher.c b/dummyflasher.c
index 0195fbd..a469d6d 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -113,6 +113,8 @@
 static uint32_t dummy_chip_readl(const struct flashctx *flash, const chipaddr addr);
 static void dummy_chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len);
 static bool dummy_spi_probe_opcode(const struct flashctx *flash, uint8_t opcode);
+static void *dummy_map(const char *descr, uintptr_t phys_addr, size_t len);
+static void dummy_unmap(void *virt_addr, size_t len);
 
 static const struct spi_master spi_master_dummyflasher = {
 	.features	= SPI_MASTER_4BA,
@@ -134,6 +136,8 @@
 	.chip_writew	= dummy_chip_writew,
 	.chip_writel	= dummy_chip_writel,
 	.chip_writen	= dummy_chip_writen,
+	.map_flash	= dummy_map,
+	.unmap_flash	= dummy_unmap,
 };
 
 static int dummy_shutdown(void *data)
@@ -1205,6 +1209,4 @@
 				/* FIXME */
 	.devs.note		= "Dummy device, does nothing and logs all accesses\n",
 	.init			= dummy_init,
-	.map_flash_region	= dummy_map,
-	.unmap_flash_region	= dummy_unmap,
 };
diff --git a/flashprog.c b/flashprog.c
index e1049f3..a9bba8f 100644
--- a/flashprog.c
+++ b/flashprog.c
@@ -207,27 +207,6 @@
 	return ret;
 }
 
-void *programmer_map_flash_region(const char *descr, uintptr_t phys_addr, size_t len)
-{
-	void *ret;
-	if (programmer->map_flash_region)
-		ret = programmer->map_flash_region(descr, phys_addr, len);
-	else
-		ret = fallback_map(descr, phys_addr, len);
-	msg_gspew("%s: mapping %s from 0x%0*" PRIxPTR " to 0x%0*" PRIxPTR "\n",
-		  __func__, descr, PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t) ret);
-	return ret;
-}
-
-void programmer_unmap_flash_region(void *virt_addr, size_t len)
-{
-	if (programmer->unmap_flash_region)
-		programmer->unmap_flash_region(virt_addr, len);
-	else
-		fallback_unmap(virt_addr, len);
-	msg_gspew("%s: unmapped 0x%0*" PRIxPTR "\n", __func__, PRIxPTR_WIDTH, (uintptr_t)virt_addr);
-}
-
 void programmer_delay(unsigned int usecs)
 {
 	if (usecs > 0) {
@@ -546,61 +525,6 @@
 	return first_len;
 }
 
-void finish_memory_access(struct flashctx *flash)
-{
-	if (flash->virtual_registers != (chipaddr)ERROR_PTR) {
-		programmer_unmap_flash_region((void *)flash->virtual_registers, flash->chip->total_size * 1024);
-		flash->physical_registers = 0;
-		flash->virtual_registers = (chipaddr)ERROR_PTR;
-	}
-
-	if (flash->virtual_memory != (chipaddr)ERROR_PTR) {
-		programmer_unmap_flash_region((void *)flash->virtual_memory, flash->chip->total_size * 1024);
-		flash->physical_memory = 0;
-		flash->virtual_memory = (chipaddr)ERROR_PTR;
-	}
-}
-
-int prepare_memory_access(struct flashctx *flash, enum preparation_steps prep)
-{
-	/* Init pointers to the fail-safe state to distinguish them later from legit values. */
-	flash->virtual_memory = (chipaddr)ERROR_PTR;
-	flash->virtual_registers = (chipaddr)ERROR_PTR;
-
-	/* FIXME: This avoids mapping (and unmapping) of flash chip definitions with size 0.
-	 * These are used for various probing-related hacks that would not map successfully anyway and should be
-	 * removed ASAP. */
-	if (flash->chip->total_size == 0)
-		return 0;
-
-	const chipsize_t size = flash->chip->total_size * 1024;
-	uintptr_t base = flashbase ? flashbase : (0xffffffff - size + 1);
-	void *addr = programmer_map_flash_region(flash->chip->name, base, size);
-	if (addr == ERROR_PTR) {
-		msg_perr("Could not map flash chip %s at 0x%0*" PRIxPTR ".\n",
-			 flash->chip->name, PRIxPTR_WIDTH, base);
-		return 1;
-	}
-	flash->physical_memory = base;
-	flash->virtual_memory = (chipaddr)addr;
-
-	/* FIXME: Special function registers normally live 4 MByte below flash space, but it might be somewhere
-	 * completely different on some chips and programmers, or not mappable at all.
-	 * Ignore these problems for now and always report success. */
-	if (flash->chip->feature_bits & FEATURE_REGISTERMAP) {
-		base = 0xffffffff - size - 0x400000 + 1;
-		addr = programmer_map_flash_region("flash chip registers", base, size);
-		if (addr == ERROR_PTR) {
-			msg_pdbg2("Could not map flash chip registers %s at 0x%0*" PRIxPTR ".\n",
-				 flash->chip->name, PRIxPTR_WIDTH, base);
-			return 0;
-		}
-		flash->physical_registers = base;
-		flash->virtual_registers = (chipaddr)addr;
-	}
-	return 0;
-}
-
 /*
  * Return a string corresponding to the bustype parameter.
  * Memory is obtained with malloc() and must be freed with free() by the caller.
@@ -743,7 +667,7 @@
 		  flash->chip->vendor, flash->chip->name, flash->chip->total_size, tmp);
 	free(tmp);
 #if CONFIG_INTERNAL == 1
-	if (flash->physical_memory != 0 && programmer->map_flash_region == physmap)
+	if (flash->physical_memory != 0 && mst->par.map_flash == physmap)
 		msg_cinfo("mapped at physical address 0x%0*" PRIxPTR ".\n",
 			  PRIxPTR_WIDTH, flash->physical_memory);
 	else
diff --git a/include/chipdrivers.h b/include/chipdrivers.h
index 8c4ecba..10090d8 100644
--- a/include/chipdrivers.h
+++ b/include/chipdrivers.h
@@ -215,7 +215,7 @@
 void decode_range_spi25_bit_cmp(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
 void decode_range_spi25_2x_block(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
 
-/* flashprog.c */
+/* memory_bus.c */
 int prepare_memory_access(struct flashctx *, enum preparation_steps);
 void finish_memory_access(struct flashctx *);
 
diff --git a/include/flash.h b/include/flash.h
index c71b1d9..fad5750 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -56,8 +56,6 @@
 
 int register_shutdown(int (*function) (void *data), void *data);
 int shutdown_free(void *data);
-void *programmer_map_flash_region(const char *descr, uintptr_t phys_addr, size_t len);
-void programmer_unmap_flash_region(void *virt_addr, size_t len);
 void programmer_delay(unsigned int usecs);
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
diff --git a/include/programmer.h b/include/programmer.h
index 5d80b56..286516d 100644
--- a/include/programmer.h
+++ b/include/programmer.h
@@ -50,9 +50,6 @@
 
 	int (*init) (void);
 
-	void *(*map_flash_region) (const char *descr, uintptr_t phys_addr, size_t len);
-	void (*unmap_flash_region) (void *virt_addr, size_t len);
-
 	void (*delay) (unsigned int usecs);
 };
 
@@ -414,6 +411,10 @@
 	uint16_t (*chip_readw) (const struct flashctx *flash, const chipaddr addr);
 	uint32_t (*chip_readl) (const struct flashctx *flash, const chipaddr addr);
 	void (*chip_readn) (const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len);
+
+	void *(*map_flash) (const char *descr, uintptr_t phys_addr, size_t len);
+	void (*unmap_flash) (void *virt_addr, size_t len);
+
 	int (*shutdown)(void *data);
 	void *data;
 };
diff --git a/internal.c b/internal.c
index f8de4a7..5d85758 100644
--- a/internal.c
+++ b/internal.c
@@ -84,6 +84,8 @@
 	.chip_writew	= internal_chip_writew,
 	.chip_writel	= internal_chip_writel,
 	.chip_writen	= fallback_chip_writen,
+	.map_flash	= physmap,
+	.unmap_flash	= physunmap,
 };
 
 enum chipbustype internal_buses_supported = BUS_NONE;
@@ -362,6 +364,4 @@
 	.type			= OTHER,
 	.devs.note		= NULL,
 	.init			= internal_init,
-	.map_flash_region	= physmap,
-	.unmap_flash_region	= physunmap,
 };
diff --git a/memory_bus.c b/memory_bus.c
new file mode 100644
index 0000000..304766d
--- /dev/null
+++ b/memory_bus.c
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the flashprog project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "flash.h"
+#include "programmer.h"
+
+#include "chipdrivers.h"
+
+static void *programmer_map_flash_region(const struct flashctx *flash, const char *descr,
+					 uintptr_t phys_addr, size_t len)
+{
+	void *ret;
+	if (flash->mst->par.map_flash)
+		ret = flash->mst->par.map_flash(descr, phys_addr, len);
+	else
+		ret = fallback_map(descr, phys_addr, len);
+	msg_gspew("%s: mapping %s from 0x%0*" PRIxPTR " to 0x%0*" PRIxPTR "\n",
+		  __func__, descr, PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t) ret);
+	return ret;
+}
+
+static void programmer_unmap_flash_region(const struct flashctx *flash, void *virt_addr, size_t len)
+{
+	if (flash->mst->par.unmap_flash)
+		flash->mst->par.unmap_flash(virt_addr, len);
+	else
+		fallback_unmap(virt_addr, len);
+	msg_gspew("%s: unmapped 0x%0*" PRIxPTR "\n", __func__, PRIxPTR_WIDTH, (uintptr_t)virt_addr);
+}
+
+int prepare_memory_access(struct flashctx *flash, enum preparation_steps prep)
+{
+	/* Init pointers to the fail-safe state to distinguish them later from legit values. */
+	flash->virtual_memory = (chipaddr)ERROR_PTR;
+	flash->virtual_registers = (chipaddr)ERROR_PTR;
+
+	/*
+	 * FIXME: This avoids mapping (and unmapping) of flash chip definitions with size 0.
+	 * These are used for various probing-related hacks that would not map successfully
+	 * anyway and should be removed ASAP.
+	 */
+	if (flash->chip->total_size == 0)
+		return 0;
+
+	const chipsize_t size = flash->chip->total_size * 1024;
+	uintptr_t base = flashbase ? flashbase : (0xffffffff - size + 1);
+	void *addr = programmer_map_flash_region(flash, flash->chip->name, base, size);
+	if (addr == ERROR_PTR) {
+		msg_perr("Could not map flash chip %s at 0x%0*" PRIxPTR ".\n",
+			 flash->chip->name, PRIxPTR_WIDTH, base);
+		return 1;
+	}
+	flash->physical_memory = base;
+	flash->virtual_memory = (chipaddr)addr;
+
+	/*
+	 * FIXME: Special function registers normally live 4 MByte below flash space,
+	 * but it might be somewhere completely different on some chips and programmers,
+	 * or not mappable at all. Ignore these problems for now and always report success.
+	 */
+	if (flash->chip->feature_bits & FEATURE_REGISTERMAP) {
+		base = 0xffffffff - size - 0x400000 + 1;
+		addr = programmer_map_flash_region(flash, "flash chip registers", base, size);
+		if (addr == ERROR_PTR) {
+			msg_pdbg2("Could not map flash chip registers %s at 0x%0*" PRIxPTR ".\n",
+				 flash->chip->name, PRIxPTR_WIDTH, base);
+			return 0;
+		}
+		flash->physical_registers = base;
+		flash->virtual_registers = (chipaddr)addr;
+	}
+	return 0;
+}
+
+void finish_memory_access(struct flashctx *flash)
+{
+	const size_t size = flashprog_flash_getsize(flash);
+
+	if (flash->virtual_registers != (chipaddr)ERROR_PTR) {
+		programmer_unmap_flash_region(flash, (void *)flash->virtual_registers, size);
+		flash->physical_registers = 0;
+		flash->virtual_registers = (chipaddr)ERROR_PTR;
+	}
+
+	if (flash->virtual_memory != (chipaddr)ERROR_PTR) {
+		programmer_unmap_flash_region(flash, (void *)flash->virtual_memory, size);
+		flash->physical_memory = 0;
+		flash->virtual_memory = (chipaddr)ERROR_PTR;
+	}
+}
diff --git a/meson.build b/meson.build
index 940f113..f1905f8 100644
--- a/meson.build
+++ b/meson.build
@@ -61,6 +61,7 @@
   'jedec.c',
   'layout.c',
   'libflashprog.c',
+  'memory_bus.c',
   'opaque.c',
   'parallel.c',
   'print.c',
diff --git a/serprog.c b/serprog.c
index 3525df7..458fa91 100644
--- a/serprog.c
+++ b/serprog.c
@@ -343,6 +343,7 @@
 				  const chipaddr addr);
 static void serprog_chip_readn(const struct flashctx *flash, uint8_t *buf,
 			       const chipaddr addr, size_t len);
+static void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len);
 static const struct par_master par_master_serprog = {
 	.chip_readb	= serprog_chip_readb,
 	.chip_readw	= fallback_chip_readw,
@@ -352,6 +353,7 @@
 	.chip_writew	= fallback_chip_writew,
 	.chip_writel	= fallback_chip_writel,
 	.chip_writen	= fallback_chip_writen,
+	.map_flash	= serprog_map,
 };
 
 static enum chipbustype serprog_buses_supported = BUS_NONE;
@@ -1007,6 +1009,5 @@
 				/* FIXME */
 	.devs.note		= "All programmer devices speaking the serprog protocol\n",
 	.init			= serprog_init,
-	.map_flash_region	= serprog_map,
 	.delay			= serprog_delay,
 };