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.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-register_all_programmers_register_generic/flash.h =================================================================== --- flashrom-register_all_programmers_register_generic/flash.h (Revision 1463) +++ flashrom-register_all_programmers_register_generic/flash.h (Arbeitskopie) @@ -153,6 +153,7 @@ /* Some flash devices have an additional register space. */ chipaddr virtual_memory; chipaddr virtual_registers; + struct registered_programmer *pgm; };
#define TEST_UNTESTED 0 @@ -197,14 +198,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); @@ -271,4 +271,5 @@ int spi_send_multicommand(struct spi_command *cmds); uint32_t spi_get_valid_read_addr(void);
+enum chipbustype get_buses_supported(void); #endif /* !__FLASH_H__ */ Index: flashrom-register_all_programmers_register_generic/cli_classic.c =================================================================== --- flashrom-register_all_programmers_register_generic/cli_classic.c (Revision 1463) +++ flashrom-register_all_programmers_register_generic/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(®istered_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/ichspi.c =================================================================== --- flashrom-register_all_programmers_register_generic/ichspi.c (Revision 1463) +++ flashrom-register_all_programmers_register_generic/ichspi.c (Arbeitskopie) @@ -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 */ Index: flashrom-register_all_programmers_register_generic/opaque.c =================================================================== --- flashrom-register_all_programmers_register_generic/opaque.c (Revision 1463) +++ flashrom-register_all_programmers_register_generic/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@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@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@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@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@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/spi.c =================================================================== --- flashrom-register_all_programmers_register_generic/spi.c (Revision 1463) +++ flashrom-register_all_programmers_register_generic/spi.c (Arbeitskopie) @@ -194,6 +194,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/programmer.c =================================================================== --- flashrom-register_all_programmers_register_generic/programmer.c (Revision 1463) +++ flashrom-register_all_programmers_register_generic/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 @@ -113,6 +113,38 @@
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/flashrom.c =================================================================== --- flashrom-register_all_programmers_register_generic/flashrom.c (Revision 1463) +++ flashrom-register_all_programmers_register_generic/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. */ @@ -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/programmer.h =================================================================== --- flashrom-register_all_programmers_register_generic/programmer.h (Revision 1463) +++ flashrom-register_all_programmers_register_generic/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); @@ -341,31 +341,6 @@ 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); @@ -632,6 +607,42 @@ 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 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); +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);