Add infrastructure to probe per bus

Add some infrastructure around per-bus probing functions.  Each function
is provided a private parameter, e.g. the expected length of an ID. This
will allow us to implement probing functions that are only called as of-
ten as necessary. The results will be stored in the `registered_master`
structure, to be compared to database entries later.

The probe_buses() wrapper can be used for chip entries, and allows us to
transition the existing probing functions one by one. Once all functions
have been ported, probe_flash() can be adapted as well and the wrapper
will become obsolete.

Change-Id: I6e82b6d61df50234096ac39acab58a4014203933
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/74899
diff --git a/flashprog.c b/flashprog.c
index 0ab20cb..cf697fb 100644
--- a/flashprog.c
+++ b/flashprog.c
@@ -180,6 +180,15 @@
 		int i = --shutdown_fn_count;
 		ret |= shutdown_fn[i].func(shutdown_fn[i].data);
 	}
+
+	int i;
+	for (i = 0; i < registered_master_count; ++i) {
+		struct found_id *found_id, *next;
+		for (found_id = registered_masters[i].found_ids; found_id; found_id = next) {
+			next = found_id->next;
+			free(found_id);
+		}
+	}
 	registered_master_count = 0;
 
 	return ret;
@@ -619,6 +628,88 @@
 	return 0;
 }
 
+static void probe_bus(struct registered_master *const mst, const enum id_type type)
+{
+	struct found_id **next_ptr;
+	unsigned int i;
+
+	if (mst->probed)
+		return;
+
+	next_ptr = &mst->found_ids;
+	for (i = 0; i < mst->probing.probe_count; ++i) {
+		if (type && type != mst->probing.probes[i].type)
+			continue;
+
+		*next_ptr = mst->probing.probes[i].run(&mst->probing.probes[i], &mst->common);
+
+		/* walk to end in case multiple IDs were found in a single call */
+		while (*next_ptr)
+			next_ptr = &(*next_ptr)->next;
+	}
+
+	mst->probed = true;
+}
+
+static bool chip_on_bus(struct registered_master *const mst, const struct flashprog_chip *const chip)
+{
+	static const char *const id_names[] = {
+		[ID_82802AB]	= "82802AB",
+		[ID_EN29LV640B]	= "EN29LV640B",
+		[ID_JEDEC]	= "JEDEC",
+		[ID_JEDEC_29GL]	= "JEDEC_29GL",
+		[ID_OPAQUE]	= "OPAQUE",
+		[ID_SPI_AT25F]	= "SPI_AT25F",
+		[ID_SPI_RDID]	= "SPI_RDID",
+		[ID_SPI_RDID4]	= "SPI_RDID4",
+		[ID_SPI_REMS]	= "SPI_REMS",
+		[ID_SPI_RES1]	= "SPI_RES1",
+		[ID_SPI_RES2]	= "SPI_RES2",
+		[ID_SPI_RES3]	= "SPI_RES3",
+		[ID_SPI_SFDP]	= "SPI_SFDP",
+		[ID_SPI_ST95]	= "SPI_ST95",
+		[ID_W29EE011]	= "W29EE011",
+		[ID_EDI]	= "EDI",
+	};
+
+	if (chip_to_probe) {
+		/* If we are looking for a particular chip,
+		   limit the probing functions to its type. */
+		probe_bus(mst, chip->id.type);
+	} else {
+		probe_bus(mst, 0);
+	}
+
+	struct found_id *found_id;
+	for (found_id = mst->found_ids; found_id; found_id = found_id->next) {
+		if (found_id->info.id.type != chip->id.type)
+			continue;
+
+		if (found_id->info.id.type < ARRAY_SIZE(id_names))
+			msg_cdbg("%s: id1 0x%02x, id2 0x%02x ",
+				 id_names[found_id->info.id.type],
+				 found_id->info.id.id1, found_id->info.id.id2);
+
+		if (mst->probing.match(chip, &found_id->info))
+			break;
+	}
+
+	msg_cdbg("\n");
+	return !!found_id;
+}
+
+/* wrapper that's used until all probing functions are ported to per-bus probing */
+int probe_buses(struct flashctx *const flash)
+{
+	int i;
+	for (i = 0; i < registered_master_count; ++i) {
+		if (flash->mst.common == &registered_masters[i].common &&
+		    chip_on_bus(&registered_masters[i], flash->chip))
+			return 1;
+	}
+	return 0;
+}
+
 int probe_flash(struct registered_master *mst, int startchip, struct flashctx *flash, int force)
 {
 	const struct flashchip *chip;