summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitbang_spi.c124
-rw-r--r--cli_classic.c26
-rw-r--r--flash.h12
-rw-r--r--flashrom.c39
-rw-r--r--ichspi.c12
-rw-r--r--mcp6x_spi.c4
-rw-r--r--nicintel_spi.c4
-rw-r--r--ogp_spi.c4
-rw-r--r--opaque.c59
-rw-r--r--programmer.c69
-rw-r--r--programmer.h32
-rw-r--r--rayer_spi.c4
-rw-r--r--spi.c75
-rw-r--r--spi25.c4
14 files changed, 217 insertions, 251 deletions
diff --git a/bitbang_spi.c b/bitbang_spi.c
index 5ee52f5..51fc9c6 100644
--- a/bitbang_spi.c
+++ b/bitbang_spi.c
@@ -25,42 +25,37 @@
#include "programmer.h"
#include "spi.h"
-/* Length of half a clock period in usecs. */
-static int bitbang_spi_half_period;
-
-static const struct bitbang_spi_master *bitbang_spi_master = NULL;
-
/* Note that CS# is active low, so val=0 means the chip is active. */
-static void bitbang_spi_set_cs(int val)
+static void bitbang_spi_set_cs(const const struct bitbang_spi_master *master, int val)
{
- bitbang_spi_master->set_cs(val);
+ master->set_cs(val);
}
-static void bitbang_spi_set_sck(int val)
+static void bitbang_spi_set_sck(const const struct bitbang_spi_master *master, int val)
{
- bitbang_spi_master->set_sck(val);
+ master->set_sck(val);
}
-static void bitbang_spi_set_mosi(int val)
+static void bitbang_spi_set_mosi(const const struct bitbang_spi_master *master, int val)
{
- bitbang_spi_master->set_mosi(val);
+ master->set_mosi(val);
}
-static int bitbang_spi_get_miso(void)
+static int bitbang_spi_get_miso(const const struct bitbang_spi_master *master)
{
- return bitbang_spi_master->get_miso();
+ return master->get_miso();
}
-static void bitbang_spi_request_bus(void)
+static void bitbang_spi_request_bus(const const struct bitbang_spi_master *master)
{
- if (bitbang_spi_master->request_bus)
- bitbang_spi_master->request_bus();
+ if (master->request_bus)
+ master->request_bus();
}
-static void bitbang_spi_release_bus(void)
+static void bitbang_spi_release_bus(const const struct bitbang_spi_master *master)
{
- if (bitbang_spi_master->release_bus)
- bitbang_spi_master->release_bus();
+ if (master->release_bus)
+ master->release_bus();
}
static int bitbang_spi_send_command(struct flashctx *flash,
@@ -78,67 +73,59 @@ static const struct spi_programmer spi_programmer_bitbang = {
.write_256 = default_spi_write_256,
};
-int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod)
+#if 0 // until it is needed
+static int bitbang_spi_shutdown(const struct bitbang_spi_master *master)
{
+ /* FIXME: Run bitbang_spi_release_bus here or per command? */
+ return 0;
+}
+#endif
+
+int bitbang_spi_init(const struct bitbang_spi_master *master)
+{
+ struct spi_programmer pgm = spi_programmer_bitbang;
/* BITBANG_SPI_INVALID is 0, so if someone forgot to initialize ->type,
* we catch it here. Same goes for missing initialization of bitbanging
* functions.
*/
if (!master || master->type == BITBANG_SPI_INVALID || !master->set_cs ||
- !master->set_sck || !master->set_mosi || !master->get_miso) {
+ !master->set_sck || !master->set_mosi || !master->get_miso ||
+ (master->request_bus && !master->release_bus) ||
+ (!master->request_bus && master->release_bus)) {
msg_perr("Incomplete SPI bitbang master setting!\n"
"Please report a bug at flashrom@flashrom.org\n");
- return 1;
- }
- if (bitbang_spi_master) {
- msg_perr("SPI bitbang master already initialized!\n"
- "Please report a bug at flashrom@flashrom.org\n");
- return 1;
+ return ERROR_FLASHROM_BUG;
}
- bitbang_spi_master = master;
- bitbang_spi_half_period = halfperiod;
+ pgm.data = master;
+ register_spi_programmer(&pgm);
- register_spi_programmer(&spi_programmer_bitbang);
-
- /* FIXME: Run bitbang_spi_request_bus here or in programmer init? */
- bitbang_spi_set_cs(1);
- bitbang_spi_set_sck(0);
- bitbang_spi_set_mosi(0);
- return 0;
-}
-
-int bitbang_spi_shutdown(const struct bitbang_spi_master *master)
-{
- if (!bitbang_spi_master) {
- msg_perr("Shutting down an uninitialized SPI bitbang master!\n"
- "Please report a bug at flashrom@flashrom.org\n");
- return 1;
- }
- if (master != bitbang_spi_master) {
- msg_perr("Shutting down a mismatched SPI bitbang master!\n"
- "Please report a bug at flashrom@flashrom.org\n");
- return 1;
- }
-
- /* FIXME: Run bitbang_spi_release_bus here or per command? */
- bitbang_spi_master = NULL;
+ /* Only mess with the bus if we're sure nobody else uses it. */
+ bitbang_spi_request_bus(master);
+ bitbang_spi_set_cs(master, 1);
+ bitbang_spi_set_sck(master, 0);
+ bitbang_spi_set_mosi(master, 0);
+ /* FIXME: Release SPI bus here and request it again for each command or
+ * don't release it now and only release it on programmer shutdown?
+ */
+ bitbang_spi_release_bus(master);
return 0;
}
-static uint8_t bitbang_spi_readwrite_byte(uint8_t val)
+static uint8_t bitbang_spi_rw_byte(const struct bitbang_spi_master *master,
+ uint8_t val)
{
uint8_t ret = 0;
int i;
for (i = 7; i >= 0; i--) {
- bitbang_spi_set_mosi((val >> i) & 1);
- programmer_delay(bitbang_spi_half_period);
- bitbang_spi_set_sck(1);
+ bitbang_spi_set_mosi(master, (val >> i) & 1);
+ programmer_delay(master->half_period);
+ bitbang_spi_set_sck(master, 1);
ret <<= 1;
- ret |= bitbang_spi_get_miso();
- programmer_delay(bitbang_spi_half_period);
- bitbang_spi_set_sck(0);
+ ret |= bitbang_spi_get_miso(master);
+ programmer_delay(master->half_period);
+ bitbang_spi_set_sck(master, 0);
}
return ret;
}
@@ -149,23 +136,24 @@ static int bitbang_spi_send_command(struct flashctx *flash,
unsigned char *readarr)
{
int i;
+ const struct bitbang_spi_master *master = flash->pgm->spi.data;
/* FIXME: Run bitbang_spi_request_bus here or in programmer init?
* Requesting and releasing the SPI bus is handled in here to allow the
* programmer to use its own SPI engine for native accesses.
*/
- bitbang_spi_request_bus();
- bitbang_spi_set_cs(0);
+ bitbang_spi_request_bus(master);
+ bitbang_spi_set_cs(master, 0);
for (i = 0; i < writecnt; i++)
- bitbang_spi_readwrite_byte(writearr[i]);
+ bitbang_spi_rw_byte(master, writearr[i]);
for (i = 0; i < readcnt; i++)
- readarr[i] = bitbang_spi_readwrite_byte(0);
+ readarr[i] = bitbang_spi_rw_byte(master, 0);
- programmer_delay(bitbang_spi_half_period);
- bitbang_spi_set_cs(1);
- programmer_delay(bitbang_spi_half_period);
+ programmer_delay(master->half_period);
+ bitbang_spi_set_cs(master, 1);
+ programmer_delay(master->half_period);
/* FIXME: Run bitbang_spi_release_bus here or in programmer init? */
- bitbang_spi_release_bus();
+ bitbang_spi_release_bus(master);
return 0;
}
diff --git a/cli_classic.c b/cli_classic.c
index bb8c29f..543b644 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -172,7 +172,7 @@ int main(int argc, char *argv[])
struct flashctx flashes[3];
struct flashctx *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;
@@ -444,17 +444,21 @@ int main(int argc, char *argv[])
ret = 1;
goto out_shutdown;
}
- tempstr = flashbuses_to_text(buses_supported);
- msg_pdbg("This programmer supports the following protocols: %s.\n",
+ tempstr = flashbuses_to_text(get_buses_supported());
+ msg_pdbg("The following protocols are supported: %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) {
@@ -472,6 +476,7 @@ int main(int argc, char *argv[])
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");
@@ -486,6 +491,7 @@ int main(int argc, char *argv[])
"contain garbage.\n");
return read_flash_to_file(&flashes[0], filename);
}
+#endif
ret = 1;
goto out_shutdown;
} else if (!chip_to_probe) {
@@ -502,7 +508,7 @@ int main(int argc, char *argv[])
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(fill_flash->pgm->buses_supported & fill_flash->bustype, size) &&
(!force)) {
fprintf(stderr, "Chip is too big for this programmer "
"(-V gives details). Use --force to override.\n");
diff --git a/flash.h b/flash.h
index 29ba193..e21a986 100644
--- a/flash.h
+++ b/flash.h
@@ -171,6 +171,7 @@ struct flashctx {
chipaddr virtual_memory;
/* Some flash devices have an additional register space. */
chipaddr virtual_registers;
+ struct registered_programmer *pgm;
};
#define TEST_UNTESTED 0
@@ -224,14 +225,13 @@ enum write_granularity {
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 flashctx *flash);
int read_memmapped(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int erase_flash(struct flashctx *flash);
-int probe_flash(int startchip, struct flashctx *fill_flash, int force);
+int probe_flash(struct registered_programmer *pgm, int startchip, struct flashctx *fill_flash, int force);
int read_flash_to_file(struct flashctx *flash, const char *filename);
int min(int a, int b);
int max(int a, int b);
@@ -256,6 +256,13 @@ int write_buf_to_file(unsigned char *buf, unsigned long size, const char *filena
/* Something happened that shouldn't happen, we'll abort. */
#define ERROR_FATAL -0xee
+#define ERROR_FLASHROM_BUG -200
+/* We reached one of the hardcoded limits of flashrom. This can be fixed by
+ * increasing the limit of a compile-time allocation or by switching to dynamic
+ * allocation.
+ * Note: If this warning is triggered, check first for runaway registrations.
+ */
+#define ERROR_FLASHROM_LIMIT -201
/* cli_output.c */
/* Let gcc and clang check for correct printf-style format strings. */
@@ -297,4 +304,5 @@ int spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int
int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds);
uint32_t spi_get_valid_read_addr(struct flashctx *flash);
+enum chipbustype get_buses_supported(void);
#endif /* !__FLASH_H__ */
diff --git a/flashrom.c b/flashrom.c
index f7a17d1..f1a6165 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -46,9 +46,6 @@ static enum programmer programmer = PROGRAMMER_INVALID;
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 @@ int programmer_init(enum programmer prog, char *param)
.fwh = 0xffffffff,
.spi = 0xffffffff,
};
- buses_supported = BUS_NONE;
/* Default to top aligned flash at 4 GB. */
flashbase = 0;
/* Registering shutdown functions is now allowed. */
@@ -361,44 +357,44 @@ void programmer_unmap_flash_region(void *virt_addr, size_t len)
void chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
{
- par_programmer->chip_writeb(flash, val, addr);
+ flash->pgm->par.chip_writeb(flash, val, addr);
}
void chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr)
{
- par_programmer->chip_writew(flash, val, addr);
+ flash->pgm->par.chip_writew(flash, val, addr);
}
void chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr)
{
- par_programmer->chip_writel(flash, val, addr);
+ flash->pgm->par.chip_writel(flash, val, addr);
}
void chip_writen(const struct flashctx *flash, uint8_t *buf, chipaddr addr,
size_t len)
{
- par_programmer->chip_writen(flash, buf, addr, len);
+ flash->pgm->par.chip_writen(flash, buf, addr, len);
}
uint8_t chip_readb(const struct flashctx *flash, const chipaddr addr)
{
- return par_programmer->chip_readb(flash, addr);
+ return flash->pgm->par.chip_readb(flash, addr);
}
uint16_t chip_readw(const struct flashctx *flash, const chipaddr addr)
{
- return par_programmer->chip_readw(flash, addr);
+ return flash->pgm->par.chip_readw(flash, addr);
}
uint32_t chip_readl(const struct flashctx *flash, const chipaddr addr)
{
- return par_programmer->chip_readl(flash, addr);
+ return flash->pgm->par.chip_readl(flash, addr);
}
void chip_readn(const struct flashctx *flash, uint8_t *buf, chipaddr addr,
size_t len)
{
- par_programmer->chip_readn(flash, buf, addr, len);
+ flash->pgm->par.chip_readn(flash, buf, addr, len);
}
void programmer_delay(int usecs)
@@ -942,7 +938,8 @@ int check_max_decode(enum chipbustype buses, uint32_t size)
return 1;
}
-int probe_flash(int startchip, struct flashctx *fill_flash, int force)
+int probe_flash(struct registered_programmer *pgm, int startchip,
+ struct flashctx *fill_flash, int force)
{
const struct flashchip *flash;
unsigned long base = 0;
@@ -954,20 +951,9 @@ int probe_flash(int startchip, struct flashctx *fill_flash, int force)
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;
- if (!buses_common) {
- msg_gspew("Probing for %s %s, %d kB: skipped. ",
- flash->vendor, flash->name, flash->total_size);
- tmp = flashbuses_to_text(buses_supported);
- msg_gspew("Host bus type %s ", tmp);
- free(tmp);
- tmp = flashbuses_to_text(flash->bustype);
- msg_gspew("and chip bus type %s are incompatible.",
- tmp);
- free(tmp);
- msg_gspew("\n");
+ buses_common = pgm->buses_supported & flash->bustype;
+ if (!buses_common)
continue;
- }
msg_gdbg("Probing for %s %s, %d kB: ",
flash->vendor, flash->name, flash->total_size);
if (!flash->probe && !force) {
@@ -981,6 +967,7 @@ int probe_flash(int startchip, struct flashctx *fill_flash, int force)
/* Start filling in the dynamic data. */
memcpy(fill_flash, flash, sizeof(struct flashchip));
+ fill_flash->pgm = pgm;
base = flashbase ? flashbase : (0xffffffff - size + 1);
fill_flash->virtual_memory = (chipaddr)programmer_map_flash_region("flash chip", base, size);
diff --git a/ichspi.c b/ichspi.c
index 6bcea45..163ecf1 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -635,7 +635,7 @@ static void ich_set_bbar(uint32_t min_addr)
/* 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 @@ static void ich_read_data(uint8_t *data, int len, int reg0_off)
/* 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)
@@ -960,9 +960,9 @@ static int run_opcode(const struct flashctx *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;
}
@@ -1297,7 +1297,7 @@ static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf,
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 */
@@ -1336,7 +1336,7 @@ static int ich_hwseq_write(struct flashctx *flash, uint8_t *buf,
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 */
diff --git a/mcp6x_spi.c b/mcp6x_spi.c
index d2c31be..23f39a5 100644
--- a/mcp6x_spi.c
+++ b/mcp6x_spi.c
@@ -98,6 +98,7 @@ static const struct bitbang_spi_master bitbang_spi_master_mcp6x = {
.get_miso = mcp6x_bitbang_get_miso,
.request_bus = mcp6x_request_spibus,
.release_bus = mcp6x_release_spibus,
+ .half_period = 0,
};
int mcp6x_spi_init(int want_spi)
@@ -159,8 +160,7 @@ int mcp6x_spi_init(int want_spi)
(status >> MCP6X_SPI_GRANT) & 0x1);
mcp_gpiostate = status & 0xff;
- /* Zero halfperiod delay. */
- if (bitbang_spi_init(&bitbang_spi_master_mcp6x, 0)) {
+ if (bitbang_spi_init(&bitbang_spi_master_mcp6x)) {
/* This should never happen. */
msg_perr("MCP6X bitbang SPI master init failed!\n");
return 1;
diff --git a/nicintel_spi.c b/nicintel_spi.c
index aacd68c..f9432ec 100644
--- a/nicintel_spi.c
+++ b/nicintel_spi.c
@@ -137,6 +137,7 @@ static const struct bitbang_spi_master bitbang_spi_master_nicintel = {
.get_miso = nicintel_bitbang_get_miso,
.request_bus = nicintel_request_spibus,
.release_bus = nicintel_release_spibus,
+ .half_period = 1,
};
static int nicintel_spi_shutdown(void *data)
@@ -181,8 +182,7 @@ int nicintel_spi_init(void)
if (register_shutdown(nicintel_spi_shutdown, NULL))
return 1;
- /* 1 usec halfperiod delay for now. */
- if (bitbang_spi_init(&bitbang_spi_master_nicintel, 1))
+ if (bitbang_spi_init(&bitbang_spi_master_nicintel))
return 1;
return 0;
diff --git a/ogp_spi.c b/ogp_spi.c
index dbaa57a..812420c 100644
--- a/ogp_spi.c
+++ b/ogp_spi.c
@@ -91,6 +91,7 @@ static const struct bitbang_spi_master bitbang_spi_master_ogp = {
.get_miso = ogp_bitbang_get_miso,
.request_bus = ogp_request_spibus,
.release_bus = ogp_release_spibus,
+ .half_period = 0,
};
static int ogp_spi_shutdown(void *data)
@@ -136,8 +137,7 @@ int ogp_spi_init(void)
if (register_shutdown(ogp_spi_shutdown, NULL))
return 1;
- /* no delay for now. */
- if (bitbang_spi_init(&bitbang_spi_master_ogp, 0))
+ if (bitbang_spi_init(&bitbang_spi_master_ogp))
return 1;
return 0;
diff --git a/opaque.c b/opaque.c
index 43ddb07..6acaa63 100644
--- a/opaque.c
+++ b/opaque.c
@@ -30,70 +30,37 @@
#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 flashctx *flash)
{
- if (!opaque_programmer->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 flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
{
- if (!opaque_programmer->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 flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
{
- if (!opaque_programmer->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 flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
{
- if (!opaque_programmer->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)
+int 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",
+ msg_perr("%s called with incomplete programmer definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
__func__);
- return;
+ return ERROR_FLASHROM_BUG;
}
- opaque_programmer = pgm;
- buses_supported |= BUS_PROG;
+ rpgm.buses_supported = BUS_PROG;
+ rpgm.opaque = *pgm;
+ return register_programmer(&rpgm);
}
diff --git a/programmer.c b/programmer.c
index 2928d68..3b4def0 100644
--- a/programmer.c
+++ b/programmer.c
@@ -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)
{
@@ -52,13 +39,7 @@ void fallback_unmap(void *virt_addr, size_t len)
{
}
-/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
-uint8_t noop_chip_readb(const struct flashctx *flash, const chipaddr addr)
-{
- return 0xff;
-}
-
-/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
+/* No-op chip_writeb() for parallel style drivers not supporting writes */
void noop_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
{
}
@@ -115,8 +96,50 @@ void fallback_chip_readn(const struct flashctx *flash, uint8_t *buf,
return;
}
-void register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses)
+int register_par_programmer(const struct par_programmer *pgm,
+ const enum chipbustype buses)
+{
+ struct registered_programmer rpgm;
+ if (!pgm->chip_writeb || !pgm->chip_writew || !pgm->chip_writel ||
+ !pgm->chip_writen || !pgm->chip_readb || !pgm->chip_readw ||
+ !pgm->chip_readl || !pgm->chip_readn) {
+ msg_perr("%s called with incomplete programmer definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
+ __func__);
+ return ERROR_FLASHROM_BUG;
+ }
+
+ rpgm.buses_supported = buses;
+ rpgm.par = *pgm;
+ return 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;
+
+/* This function copies the struct registered_programmer parameter. */
+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 ERROR_FLASHROM_LIMIT;
+ }
+ registered_programmers[registered_programmer_count] = *pgm;
+ registered_programmer_count++;
+
+ return 0;
+}
+
+enum chipbustype get_buses_supported(void)
{
- par_programmer = pgm;
- buses_supported |= buses;
+ int i;
+ enum chipbustype ret = BUS_NONE;
+
+ for (i = 0; i < registered_programmer_count; i++)
+ ret |= registered_programmers[i].buses_supported;
+
+ return ret;
}
diff --git a/programmer.h b/programmer.h
index 9942686..a40d037 100644
--- a/programmer.h
+++ b/programmer.h
@@ -133,6 +133,8 @@ struct bitbang_spi_master {
int (*get_miso) (void);
void (*request_bus) (void);
void (*release_bus) (void);
+ /* Length of half a clock period in usecs. */
+ unsigned int half_period;
};
#if CONFIG_INTERNAL == 1
@@ -208,6 +210,7 @@ void internal_delay(int usecs);
#if NEED_PCI == 1
/* pcidev.c */
+// FIXME: These need to be local, not global
extern uint32_t io_base_addr;
extern struct pci_access *pacc;
extern struct pci_dev *pcidev_dev;
@@ -427,8 +430,7 @@ int rayer_spi_init(void);
#endif
/* bitbang_spi.c */
-int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod);
-int bitbang_spi_shutdown(const struct bitbang_spi_master *master);
+int bitbang_spi_init(const struct bitbang_spi_master *master);
/* buspirate_spi.c */
#if CONFIG_BUSPIRATE_SPI == 1
@@ -452,6 +454,7 @@ struct decode_sizes {
uint32_t fwh;
uint32_t spi;
};
+// FIXME: These need to be local, not global
extern struct decode_sizes max_rom_decode;
extern int programmer_may_write;
extern unsigned long flashbase;
@@ -498,7 +501,6 @@ enum spi_controller {
SPI_CONTROLLER_SERPROG,
#endif
};
-extern const int spi_programmer_count;
#define MAX_DATA_UNSPECIFIED 0
#define MAX_DATA_READ_UNLIMITED 64 * 1024
@@ -514,15 +516,15 @@ struct spi_programmer {
/* Optimized functions for this programmer */
int (*read)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*write_256)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+ const void *data;
};
-extern const struct spi_programmer *spi_programmer;
int default_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
int default_spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds);
int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int default_spi_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
-void register_spi_programmer(const struct spi_programmer *programmer);
+int register_spi_programmer(const struct spi_programmer *programmer);
/* ichspi.c */
#if CONFIG_INTERNAL == 1
@@ -570,15 +572,14 @@ struct opaque_programmer {
int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*write) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*erase) (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen);
+ const void *data;
};
-extern const struct opaque_programmer *opaque_programmer;
-void register_opaque_programmer(const struct opaque_programmer *pgm);
+int 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 flashctx *flash, const chipaddr addr);
void noop_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr);
void fallback_chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr);
void fallback_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr);
@@ -595,9 +596,20 @@ struct par_programmer {
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);
+ const void *data;
};
-extern const struct par_programmer *par_programmer;
-void register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses);
+int 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
diff --git a/rayer_spi.c b/rayer_spi.c
index 417fde9..0011bc0 100644
--- a/rayer_spi.c
+++ b/rayer_spi.c
@@ -92,6 +92,7 @@ static const struct bitbang_spi_master bitbang_spi_master_rayer = {
.set_sck = rayer_bitbang_set_sck,
.set_mosi = rayer_bitbang_set_mosi,
.get_miso = rayer_bitbang_get_miso,
+ .half_period = 0,
};
int rayer_spi_init(void)
@@ -171,8 +172,7 @@ int rayer_spi_init(void)
/* Get the initial value before writing to any line. */
lpt_outbyte = INB(lpt_iobase);
- /* Zero halfperiod delay. */
- if (bitbang_spi_init(&bitbang_spi_master_rayer, 0))
+ if (bitbang_spi_init(&bitbang_spi_master_rayer))
return 1;
return 0;
diff --git a/spi.c b/spi.c
index 02c83f7..b2d3eb0 100644
--- a/spi.c
+++ b/spi.c
@@ -1,7 +1,7 @@
/*
* This file is part of the flashrom project.
*
- * Copyright (C) 2007, 2008, 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2007, 2008, 2009, 2010, 2011 Carl-Daniel Hailfinger
* Copyright (C) 2008 coresystems GmbH
*
* This program is free software; you can redistribute it and/or modify
@@ -30,43 +30,17 @@
#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(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt, const unsigned char *writearr,
unsigned char *readarr)
{
- if (!spi_programmer->command) {
- msg_perr("%s called, but SPI is unsupported on this "
- "hardware. Please report a bug at "
- "flashrom@flashrom.org\n", __func__);
- return 1;
- }
-
- return spi_programmer->command(flash, writecnt, readcnt, writearr,
+ return flash->pgm->spi.command(flash, writecnt, readcnt, writearr,
readarr);
}
int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds)
{
- if (!spi_programmer->multicommand) {
- msg_perr("%s called, but SPI is unsupported on this "
- "hardware. Please report a bug at "
- "flashrom@flashrom.org\n", __func__);
- return 1;
- }
-
- return spi_programmer->multicommand(flash, cmds);
+ return flash->pgm->spi.multicommand(flash, cmds);
}
int default_spi_send_command(struct flashctx *flash, unsigned int writecnt,
@@ -104,7 +78,7 @@ int default_spi_send_multicommand(struct flashctx *flash,
int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
unsigned int len)
{
- unsigned int max_data = spi_programmer->max_data_read;
+ unsigned 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 "
@@ -117,7 +91,7 @@ int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
int default_spi_write_256(struct flashctx *flash, uint8_t *buf,
unsigned int start, unsigned int len)
{
- unsigned int max_data = spi_programmer->max_data_write;
+ unsigned 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 "
@@ -131,12 +105,6 @@ int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
unsigned int len)
{
unsigned int addrbase = 0;
- if (!spi_programmer->read) {
- msg_perr("%s called, but SPI read is unsupported on this "
- "hardware. Please report a bug at "
- "flashrom@flashrom.org\n", __func__);
- return 1;
- }
/* Check if the chip fits between lowest valid and highest possible
* address. Highest possible address with the current SPI implementation
@@ -157,7 +125,7 @@ int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
"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);
}
/*
@@ -170,14 +138,7 @@ int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
int spi_chip_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start,
unsigned int len)
{
- if (!spi_programmer->write_256) {
- msg_perr("%s called, but SPI page write is unsupported on this "
- "hardware. Please report a bug at "
- "flashrom@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);
}
/*
@@ -187,7 +148,7 @@ int spi_chip_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start,
*/
uint32_t spi_get_valid_read_addr(struct flashctx *flash)
{
- switch (spi_programmer->type) {
+ switch (flash->pgm->spi.type) {
#if CONFIG_INTERNAL == 1
#if defined(__i386__) || defined(__x86_64__)
case SPI_CONTROLLER_ICH7:
@@ -200,8 +161,22 @@ uint32_t spi_get_valid_read_addr(struct flashctx *flash)
}
}
-void register_spi_programmer(const struct spi_programmer *pgm)
+int register_spi_programmer(const struct spi_programmer *pgm)
{
- spi_programmer = pgm;
- buses_supported |= BUS_SPI;
+ struct registered_programmer rpgm;
+
+ if (!pgm->write_256 || !pgm->read || !pgm->command ||
+ !pgm->multicommand ||
+ ((pgm->command == default_spi_send_command) &&
+ (pgm->multicommand == default_spi_send_multicommand))) {
+ msg_perr("%s called with incomplete programmer definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
+ __func__);
+ return ERROR_FLASHROM_BUG;
+ }
+
+
+ rpgm.buses_supported = BUS_SPI;
+ rpgm.spi = *pgm;
+ return register_programmer(&rpgm);
}
diff --git a/spi25.c b/spi25.c
index 1e3bed9..3ce7f08 100644
--- a/spi25.c
+++ b/spi25.c
@@ -179,7 +179,7 @@ int probe_spi_rdid4(struct flashctx *flash)
/* 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:
@@ -1120,7 +1120,7 @@ int spi_aai_write(struct flashctx *flash, uint8_t *buf, unsigned int start,
.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:
OpenPOWER on IntegriCloud