diff loadtools/flutil.c @ 405:a212b4968b29

fc-loadtool flash: another refactoring: geometry vs. command set
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Tue, 17 Jun 2014 00:33:05 +0000
parents 7602443edf0d
children f2cc551e597f
line wrap: on
line diff
--- a/loadtools/flutil.c	Mon Jun 16 01:15:17 2014 +0000
+++ b/loadtools/flutil.c	Tue Jun 17 00:33:05 2014 +0000
@@ -9,6 +9,8 @@
 #include "flash.h"
 
 extern struct flash_bank_info flash_bank_info[2];
+extern struct flash_cmdset flash_cmdset_amd;
+extern struct flash_cmdset flash_cmdset_intel;
 
 static int
 cfi_read_byte(bi, off, ret16p)
@@ -37,29 +39,17 @@
 	return(0);
 }
 
-static int
-cfi_id_return_to_read_mode(bi)
-	struct flash_bank_info *bi;
-{
-	if (do_w16(bi->base_addr + 0xAAA, 0xF0)) {
-		fprintf(stderr,
-	"unexpected response to w16 when resetting flash to read mode!\n");
-		return(-1);
-	}
-	return(0);
-}
-
 flash_get_cfi(bank)
 {
 	struct flash_bank_info *bi;
-	struct cfi_info *cfi;
+	struct flash_geom *geom;
 	struct flash_region_desc *reg;
 	int nr;
-	uint16_t rdval;
+	uint16_t rdval, cmdset_id;
 	uint32_t size_check;
 
 	bi = flash_bank_info + bank;
-	if (bi->cfi)
+	if (bi->geom)
 		return(0);
 	printf("Performing CFI query\n");
 	if (do_w16(bi->base_addr + 0xAA, 0x98)) {
@@ -71,7 +61,7 @@
 		return(-1);
 	if (rdval != 'Q') {
 noqry:		fprintf(stderr, "error: no QRY response from flash\n");
-		cfi_id_return_to_read_mode(bi);
+		amd_reset_cmd(bi);
 		return(-1);
 	}
 	if (cfi_read_byte(bi, 0x11, &rdval) < 0)
@@ -82,35 +72,52 @@
 		return(-1);
 	if (rdval != 'Y')
 		goto noqry;
-	cfi = malloc(sizeof(struct cfi_info));
-	if (!cfi) {
+	if (cfi_read_twobyte(bi, 0x13, &cmdset_id) < 0)
+		return(-1);
+	if (!bi->ops) {
+		switch (cmdset_id) {
+		case 2:
+			bi->ops = &flash_cmdset_amd;
+			break;
+#if 0
+		case 3:
+			bi->ops = &flash_cmdset_intel;
+			break;
+#endif
+		default:
+			fprintf(stderr, "error: command set %04X unsupported\n",
+				cmdset_id);
+			amd_reset_cmd(bi);
+			return(-1);
+		}
+	}
+	geom = malloc(sizeof(struct flash_geom));
+	if (!geom) {
 		fprintf(stderr,
-		"unable to malloc buffer for flash bank %d CFI structure\n",
+	"unable to malloc buffer for flash bank %d CFI geometry structure\n",
 			bank);
-		cfi_id_return_to_read_mode(bi);
-		return(-1);
-	}
-	if (cfi_read_twobyte(bi, 0x13, &cfi->cmdset_style) < 0) {
-free_and_immed_out:
-		free(cfi);
+		bi->ops->reset_cmd(bi);
 		return(-1);
 	}
 	/* total device size */
-	if (cfi_read_byte(bi, 0x27, &rdval) < 0)
-		goto free_and_immed_out;
+	if (cfi_read_byte(bi, 0x27, &rdval) < 0) {
+free_and_immed_out:
+		free(geom);
+		return(-1);
+	}
 	if (rdval < 20 || rdval > 24) {
 		fprintf(stderr,
 			"error: CFI reports unreasonable device size\n");
 free_and_clean_out:
-		free(cfi);
-		cfi_id_return_to_read_mode(bi);
+		free(geom);
+		bi->ops->reset_cmd(bi);
 		return(-1);
 	}
-	cfi->total_size = 1 << rdval;
-	if (cfi->total_size > bi->bank_desc->align_size) {
+	geom->total_size = 1 << rdval;
+	if (geom->total_size > bi->bank_desc->align_size) {
 		fprintf(stderr,
 	"error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n",
-			(u_long) cfi->total_size, bi->bank_desc->align_size);
+			(u_long) geom->total_size, bi->bank_desc->align_size);
 		goto free_and_clean_out;
 	}
 	if (cfi_read_byte(bi, 0x2C, &rdval) < 0)
@@ -120,11 +127,11 @@
 			"error: CFI reports unreasonable # of erase regions\n");
 		goto free_and_clean_out;
 	}
-	cfi->nregions = rdval;
-	cfi->total_sectors = 0;
+	geom->nregions = rdval;
+	geom->total_sectors = 0;
 	size_check = 0;
-	for (nr = 0; nr < cfi->nregions; nr++) {
-		reg = cfi->regions + nr;
+	for (nr = 0; nr < geom->nregions; nr++) {
+		reg = geom->regions + nr;
 		if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0)
 			goto free_and_immed_out;
 		if (rdval > 255) {
@@ -134,7 +141,7 @@
 			goto free_and_clean_out;
 		}
 		reg->nsectors = rdval + 1;
-		cfi->total_sectors += reg->nsectors;
+		geom->total_sectors += reg->nsectors;
 		if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0)
 			goto free_and_immed_out;
 		if (rdval < 0x20 || rdval > 0x400) {
@@ -146,31 +153,30 @@
 		reg->sector_size = rdval << 8;
 		size_check += reg->sector_size * reg->nsectors;
 	}
-	if (cfi_id_return_to_read_mode(bi) < 0) {
+	if (bi->ops->reset_cmd(bi) < 0) {
 		/* error msg already printed */
-		free(cfi);
+		free(geom);
 		return(-1);
 	}
-	if (size_check != cfi->total_size) {
+	if (size_check != geom->total_size) {
 		fprintf(stderr,
 "CFI error: added size of erase regions (%lx) != reported devive size (%lx)\n",
-			(u_long) size_check, (u_long) cfi->total_size);
-		free(cfi);
+			(u_long) size_check, (u_long) geom->total_size);
+		free(geom);
 		return(-1);
 	}
 	/* all checks passed */
-	bi->cfi = cfi;
+	bi->geom = geom;
 	printf(
-"CFI query successful: total size %lx, %u sectors, command set style %04X\n\n",
-		(u_long) cfi->total_size, cfi->total_sectors,
-		cfi->cmdset_style);
+"CFI query successful: total size %lx, %u sectors, command set style %04X\n",
+		(u_long) geom->total_size, geom->total_sectors, cmdset_id);
 	return(1);
 }
 
 get_flash_sector_table(bank)
 {
 	struct flash_bank_info *bi;
-	struct cfi_info *cfi;
+	struct flash_geom *geom;
 	struct flash_region_desc *reg;
 	struct sector_info *sp;
 	uint32_t offset;
@@ -182,9 +188,9 @@
 	i = flash_get_cfi(bank);
 	if (i < 0)
 		return(i);
-	cfi = bi->cfi;
+	geom = bi->geom;
 	sp = (struct sector_info *) malloc(sizeof(struct sector_info)
-						* (cfi->total_sectors + 1));
+						* (geom->total_sectors + 1));
 	if (!sp) {
 		fprintf(stderr,
 		"unable to malloc buffer for flash bank %d sector table\n",
@@ -194,8 +200,8 @@
 	bi->sectors = sp;
 	/* now fill it */
 	offset = 0;
-	for (nr = 0; nr < cfi->nregions; nr++) {
-		reg = cfi->regions + nr;
+	for (nr = 0; nr < geom->nregions; nr++) {
+		reg = geom->regions + nr;
 		for (i = 0; i < reg->nsectors; i++) {
 			sp->start = offset;
 			sp->size = reg->sector_size;
@@ -204,12 +210,12 @@
 		}
 	}
 	/* sanity checks */
-	if (sp - bi->sectors != cfi->total_sectors) {
+	if (sp - bi->sectors != geom->total_sectors) {
 		fprintf(stderr,
 	"BUG in get_flash_sector_table(): wrong # of sectors at the end\n");
 		abort();
 	}
-	if (offset != cfi->total_size) {
+	if (offset != geom->total_size) {
 		fprintf(stderr,
 		"BUG in get_flash_sector_table(): wrong offset at the end\n");
 		abort();
@@ -233,7 +239,7 @@
 	if (get_flash_sector_table(bank) < 0)
 		return(-1);
 	bi = flash_bank_info + bank;
-	printf("%u sectors in flash bank %d:\n", bi->cfi->total_sectors, bank);
+	printf("%u sectors in flash bank %d:\n", bi->geom->total_sectors, bank);
 	printf("Offset    Size\n");
 	for (sp = bi->sectors; sp->size; sp++)
 		printf("%08lX  %lx\n", (u_long) sp->start, (u_long) sp->size);