Sorry, forgot to CC.the list.
Updated patch to apply cleanly against latest revision (1151) and
changed the string as pointed out by Rudolf Marek.
Regards,
David
>-----BEGIN PGP SIGNED MESSAGE-----
>Hash: SHA1
>
>Hi thanks for doing that.
>
>Carl-Daniel Hailfinger wrote:
>> Make the satasii driver more robust.
>>
>> Untested.
>>
>> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2...(a)gmx.net>
>>
>> Index: flashrom-satasii_robust/satasii.c
>> ===================================================================
>> --- flashrom-satasii_robust/satasii.c (Revision 1005)
>> +++ flashrom-satasii_robust/satasii.c (Arbeitskopie)
>> @@ -44,6 +44,7 @@
>> Â {
>> Â Â Â uint32_t addr;
>> Â Â Â uint16_t reg_offset;
>> + Â Â uint32_t tmp;
>>
>> Â Â Â get_io_perms();
>>
>> @@ -59,12 +60,19 @@
>> Â Â Â Â Â Â Â reg_offset = 0x50;
>> Â Â Â }
>>
>> - Â Â sii_bar = physmap("SATA SIL registers", addr, 0x100) + reg_offset;
>> + Â Â sii_bar = physmap("SATA SiI registers", addr, 0x100) + reg_offset;
>>
>> Â Â Â /* Check if ROM cycle are OK. */
>> Â Â Â if ((id != 0x0680) && (!(mmio_readl(sii_bar) & (1 << 26))))
>> Â Â Â Â Â Â Â msg_pinfo("Warning: Flash seems unconnected.\n");
>>
>> + Â Â msg_pdbg("Using BAR5 access method.\n");
>> + Â Â tmp = pci_read_long(pcidev_dev, 0x40) & (1 << 1);
>> + Â Â msg_pdbg("BAR5 Indirect Access is %snabled\n", tmp ? "en" : "dis");
>> + Â Â /* This bit has contradicting definitions in the 3512 datasheet. */
>
>this looks strange you get dissnabled or ensabled ;)
>
>> + Â Â tmp = pci_read_long(pcidev_dev, 0x88) & (1 << 16);
>> + Â Â msg_pdbg("BAR5 Access is %snabled\n", tmp ? "en" : "dis");
>
>This Reg is EN_66 in other controllers so I guess it just this and not the
>BA5_EN. It looks like it is driven by strap resistor only anyway.
>
>Interesting would be to test if BA5_EN is not enabled if you can access it
>through indirect access through C0/C4 regs.
>
>Thanks,
>Rudolf
>
>
>> +
>> Â Â Â buses_supported = CHIP_BUSTYPE_PARALLEL;
>>
>> Â Â Â return 0;
>> @@ -81,6 +89,7 @@
>> Â void satasii_chip_writeb(uint8_t val, chipaddr addr)
>> Â {
>> Â Â Â uint32_t ctrl_reg, data_reg;
>> + Â Â int i = 0;
>>
>> Â Â Â while ((ctrl_reg = mmio_readl(sii_bar)) & (1 << 25)) ;
>>
>> @@ -92,12 +101,19 @@
>> Â Â Â mmio_writel(data_reg, (sii_bar + 4));
>> Â Â Â mmio_writel(ctrl_reg, sii_bar);
>>
>> - Â Â while (mmio_readl(sii_bar) & (1 << 25)) ;
>> + Â Â while (mmio_readl(sii_bar) & (1 << 25)) {
>> + Â Â Â Â Â Â if (++i > 10000) {
>> + Â Â Â Â Â Â Â Â Â Â msg_perr("%s: control reg stuck at %08x, aborting\n",
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â __func__, mmio_readl(sii_bar));
>> + Â Â Â Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â }
>> + Â Â }
>> Â }
>>
>> Â uint8_t satasii_chip_readb(const chipaddr addr)
>> Â {
>> Â Â Â uint32_t ctrl_reg;
>> + Â Â int i = 0;
>>
>> Â Â Â while ((ctrl_reg = mmio_readl(sii_bar)) & (1 << 25)) ;
>>
>> @@ -107,7 +123,13 @@
>>
>> Â Â Â mmio_writel(ctrl_reg, sii_bar);
>>
>> - Â Â while (mmio_readl(sii_bar) & (1 << 25)) ;
>> + Â Â while (mmio_readl(sii_bar) & (1 << 25)) {
>> + Â Â Â Â Â Â if (++i > 10000) {
>> + Â Â Â Â Â Â Â Â Â Â msg_perr("%s: control reg stuck at %08x, aborting\n",
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â __func__, mmio_readl(sii_bar));
>> + Â Â Â Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â }
>> + Â Â }
>>
>> Â Â Â return (mmio_readl(sii_bar + 4)) & 0xff;
>> Â }
>>
>>
>-----BEGIN PGP SIGNATURE-----
>Version: GnuPG v1.4.10 (GNU/Linux)
>Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
>
>iEYEARECAAYFAkv4VwUACgkQ3J9wPJqZRNU4BQCfYmc1fp2kmy5SjQHjirrsKP82
>enkAoKQLbvmaCGs6/qNfawamobV7RayX
>=7NEj
>-----END PGP SIGNATURE-----
>
--
David Borg
Am 26.02.2012 02:05 schrieb Stefan Tauner:
> This is not tested very thoroughly, but it compiles and writing the dummy works.
> Most of the transformation is quite obvious and painless (well, it was no pleasure,
> so i would rather not rebase this often. :)
> I have introduced dedicated struct flashchip variables where the functions use the
> chip field a lot and some of those (not) introduced variables may be debatable,
> but one gets at least a feeling how the code would look like with this change.
>
> One major FIXME is: the code allocates "the new field" while probing and copies
> the data from the *const* struct flashchip in the flashchips.c array into it.
> We need to free that sometime... it is probably obvious (scope of fill_flash), but i
> have not looked into it yet and this is my reminder.
I have answered that in annotations.
> Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
Good idea. It was too dangerous to do this directly before 0.9.5, but
now that the tree has reopened, I think we can merge such a patch early
in the cycle (now) and have enough time to get it tested.
> diff --git a/cli_classic.c b/cli_classic.c
> index 972043b..4bce7d7 100644
> --- a/cli_classic.c
> +++ b/cli_classic.c
> @@ -166,6 +166,7 @@ int main(int argc, char *argv[])
> const struct flashchip *flash;
> struct flashctx flashes[3];
> struct flashctx *fill_flash;
> + const struct flashchip *chip;
> const char *name;
> int namelen, opt, i, j;
> int startchip = -1, chipcount = 0, option_index = 0, force = 0;
> @@ -441,11 +442,13 @@ int main(int argc, char *argv[])
> }
> }
>
> + fill_flash = &flashes[0];
Can you move this assignment back to where it was?
> + chip = fill_flash->chip;
And move this assignment together with the other one?
> if (chipcount > 1) {
> printf("Multiple flash chips were detected: \"%s\"",
> - flashes[0].name);
> + chip->name);
Can you please use flashes[0].chip->name here to keep the code
consistent? Besides that, do you have any idea why the current code is
so screwed up? Moving a printf for flashes[0] outside a perfectly
working for loop seems odd to me. It would be nice if you could just let
the loop below start at i=0 and remove the chip name part from the
printf above.
> for (i = 1; i < chipcount; i++)
> - printf(", \"%s\"", flashes[i].name);
> + printf(", \"%s\"", flashes[i].chip->name);
> printf("\nPlease specify which chip to use with the "
> "-c <chipname> option.\n");
> ret = 1;
> @@ -464,7 +467,7 @@ int main(int argc, char *argv[])
> /* This loop just counts compatible controllers. */
> for (j = 0; j < registered_programmer_count; j++) {
> pgm = ®istered_programmers[j];
> - if (pgm->buses_supported & flashes[0].bustype)
> + if (pgm->buses_supported & chip->bustype)
flashes[0].chip->bustype please.
Note to self: This code needs to be audited again if it should really
run against flashes[0] here. It looks odd, at least when looking only at
the patch.
> compatible_programmers++;
> }
> if (compatible_programmers > 1)
> @@ -491,19 +494,17 @@ int main(int argc, char *argv[])
> goto out_shutdown;
> } else if (!chip_to_probe) {
> /* repeat for convenience when looking at foreign logs */
> - tempstr = flashbuses_to_text(flashes[0].bustype);
> + tempstr = flashbuses_to_text(chip->bustype);
> msg_gdbg("Found %s flash chip \"%s\" (%d kB, %s).\n",
> - flashes[0].vendor, flashes[0].name,
> - flashes[0].total_size, tempstr);
> + chip->vendor, chip->name,
> + chip->total_size, tempstr);
And the flashes[0].chip dance again.
> free(tempstr);
> }
>
> - fill_flash = &flashes[0];
> -
> - check_chip_supported(fill_flash);
> + check_chip_supported(chip);
>
> - size = fill_flash->total_size * 1024;
> - if (check_max_decode(fill_flash->pgm->buses_supported & fill_flash->bustype, size) &&
> + size = chip->total_size * 1024;
> + if (check_max_decode(fill_flash->pgm->buses_supported & chip->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 0dac13d..ed64512 100644
> --- a/flash.h
> +++ b/flash.h
> @@ -87,6 +87,7 @@ enum chipbustype {
> #define FEATURE_WRSR_EITHER (FEATURE_WRSR_EWSR | FEATURE_WRSR_WREN)
>
> struct flashctx;
> +typedef int (erasefunc_t)(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
>
> struct flashchip {
> const char *vendor;
> @@ -135,7 +136,7 @@ struct flashchip {
> } eraseblocks[NUM_ERASEREGIONS];
> /* a block_erase function should try to erase one block of size
> * 'blocklen' at address 'blockaddr' and return 0 on success. */
> - int (*block_erase) (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen);
> + erasefunc_t *block_erase;
I really really hate that typedef. I wonder if we could keep the code
here and use typeof() instead of the typedef elsewhere.
> } block_erasers[NUM_ERASEFUNCTIONS];
>
> int (*printlock) (struct flashctx *flash);
> @@ -148,35 +149,14 @@ struct flashchip {
> } voltage;
> };
>
> -/* struct flashctx must always contain struct flashchip at the beginning. */
> struct flashctx {
> - const char *vendor;
> - const char *name;
> - enum chipbustype bustype;
> - uint32_t manufacture_id;
> - uint32_t model_id;
> - int total_size;
> - int page_size;
> - int feature_bits;
> - uint32_t tested;
> - int (*probe) (struct flashctx *flash);
> - int probe_timing;
> - struct block_eraser block_erasers[NUM_ERASEFUNCTIONS];
> - int (*printlock) (struct flashctx *flash);
> - int (*unlock) (struct flashctx *flash);
> - int (*write) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
> - int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
> - struct voltage voltage;
> - /* struct flashchip ends here. */
> -
> + struct flashchip *chip;
Yay!
> chipaddr virtual_memory;
> /* Some flash devices have an additional register space. */
> chipaddr virtual_registers;
> struct registered_programmer *pgm;
> };
>
> -typedef int (erasefunc_t)(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
> -
> #define TEST_UNTESTED 0
>
> #define TEST_OK_PROBE (1 << 0)
> diff --git a/flashrom.c b/flashrom.c
> index cad043b..0b6cca3 100644
> --- a/flashrom.c
> +++ b/flashrom.c
> @@ -522,7 +522,7 @@ char *extract_programmer_param(const char *param_name)
> }
>
> /* Returns the number of well-defined erasers for a chip. */
> -static unsigned int count_usable_erasers(const struct flashctx *flash)
> +static unsigned int count_usable_erasers(const struct flashchip *flash)
Do we want to count usable erasers for the current programmer (for chips
with erase functions limited to certain buses)? If yes, please keep
struct flashctx.
> {
> unsigned int usable_erasefunctions = 0;
> int k;
> @@ -941,32 +942,38 @@ int check_max_decode(enum chipbustype buses, uint32_t size)
> int probe_flash(struct registered_programmer *pgm, int startchip,
> struct flashctx *fill_flash, int force)
> {
> - const struct flashchip *flash;
> + const struct flashchip *chip;
> unsigned long base = 0;
> char location[64];
> uint32_t size;
> enum chipbustype buses_common;
> char *tmp;
>
> - for (flash = flashchips + startchip; flash && flash->name; flash++) {
> - if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0)
> + for (chip = flashchips + startchip; chip && chip->name; chip++) {
> + if (chip_to_probe && strcmp(chip->name, chip_to_probe) != 0)
> continue;
> - buses_common = pgm->buses_supported & flash->bustype;
> + buses_common = pgm->buses_supported & chip->bustype;
> if (!buses_common)
> continue;
> msg_gdbg("Probing for %s %s, %d kB: ",
> - flash->vendor, flash->name, flash->total_size);
> - if (!flash->probe && !force) {
> + chip->vendor, chip->name, chip->total_size);
> + if (!chip->probe && !force) {
> msg_gdbg("failed! flashrom has no probe function for "
> "this flash chip.\n");
> continue;
> }
>
> - size = flash->total_size * 1024;
> + size = chip->total_size * 1024;
> check_max_decode(buses_common, size);
>
> /* Start filling in the dynamic data. */
> - memcpy(fill_flash, flash, sizeof(struct flashchip));
> + /* FIXME: when to free? */
Tricky, but I think we are lucky here because there is only one path
which returns a non-match and that's the only path where we want to
free. I have annotated that place a few hunks below.
> + fill_flash->chip = malloc(sizeof(struct flashchip));
> + if (fill_flash->chip == NULL) {
> + msg_gerr("%s: out of memory.\n", __func__);
> + return -1;
Can we return an explicit code for OOM here or would that screw up the
caller?
> + }
> + memcpy(fill_flash->chip, chip, sizeof(struct flashchip));
> fill_flash->pgm = pgm;
>
> base = flashbase ? flashbase : (0xffffffff - size + 1);
> @@ -985,11 +992,11 @@ int probe_flash(struct registered_programmer *pgm, int startchip,
> * one for this programmer interface and thus no other chip has
> * been found on this interface.
> */
> - if (startchip == 0 && fill_flash->model_id == SFDP_DEVICE_ID) {
> + if (startchip == 0 && chip->model_id == SFDP_DEVICE_ID) {
We used fill_flash for consistency (i.e. only use the rw copy of the
flashchip entry) here, and if we want to keep that consistency, it's
fill_flash->chip->model_id.
> msg_cinfo("===\n"
> "SFDP has autodetected a flash chip which is "
> "not natively supported by flashrom yet.\n");
> - if (count_usable_erasers(fill_flash) == 0)
> + if (count_usable_erasers(chip) == 0)
See the count_usable_erasers comment a few hunks above.
> msg_cinfo("The standard operations read and "
> "verify should work, but to support "
> "erase, write and all other "
> @@ -1010,15 +1017,15 @@ int probe_flash(struct registered_programmer *pgm, int startchip,
> }
>
> if (startchip == 0 ||
> - ((fill_flash->model_id != GENERIC_DEVICE_ID) &&
> - (fill_flash->model_id != SFDP_DEVICE_ID)))
> + ((chip->model_id != GENERIC_DEVICE_ID) &&
> + (chip->model_id != SFDP_DEVICE_ID)))
See above for fill_flash->chip->model_id.
> break;
>
> notfound:
> programmer_unmap_flash_region((void *)fill_flash->virtual_memory, size);
> }
>
> - if (!flash || !flash->name)
> + if (!chip || !chip->name)
Here you have to free flash->chip. No other freeing is needed AFAICS.
> return -1;
>
> #if CONFIG_INTERNAL == 1
> @@ -1028,27 +1035,27 @@ notfound:
> #endif
> snprintf(location, sizeof(location), "on %s", programmer_table[programmer].name);
>
> - tmp = flashbuses_to_text(flash->bustype);
> + tmp = flashbuses_to_text(chip->bustype);
fill_flash->chip->...
> msg_cinfo("%s %s flash chip \"%s\" (%d kB, %s) %s.\n",
> - force ? "Assuming" : "Found", fill_flash->vendor,
> - fill_flash->name, fill_flash->total_size, tmp, location);
> + force ? "Assuming" : "Found", chip->vendor,
> + chip->name, chip->total_size, tmp, location);
dito
> free(tmp);
>
> /* Flash registers will not be mapped if the chip was forced. Lock info
> * may be stored in registers, so avoid lock info printing.
> */
> if (!force)
> - if (fill_flash->printlock)
> - fill_flash->printlock(fill_flash);
> + if (chip->printlock)
dito
> + chip->printlock(fill_flash);
dito
>
> /* Return position of matching chip. */
> - return flash - flashchips;
> + return chip - flashchips;
> }
>
> int verify_flash(struct flashctx *flash, uint8_t *buf)
> @@ -1308,7 +1315,7 @@ static int walk_eraseregions(struct flashctx *flash, int erasefunction,
> return 0;
> }
>
> -static int check_block_eraser(const struct flashctx *flash, int k, int log)
> +static int check_block_eraser(const struct flashchip *flash, int k, int log)
No conversion, please. See below.
> {
> struct block_eraser eraser = flash->block_erasers[k];
>
> @@ -1357,7 +1366,7 @@ int erase_and_write_flash(struct flashctx *flash, uint8_t *oldcontents,
> break;
> }
> msg_cdbg("Trying erase function %i... ", k);
> - if (check_block_eraser(flash, k, 1))
> + if (check_block_eraser(chip, k, 1))
This one is debatable. We know that some chips support certain erase
functions only on some buses, e.g. Sharp LHF00L04 which can do a
full-chip erase only if it is accesses in A/A Mux mode, not in FWH mode.
My mid-term plan is to augment erase functions (and possibly also
read/write/probe) with a list of valid buses for any given function.
> continue;
> usable_erasefunctions--;
> ret = walk_eraseregions(flash, k, &erase_and_write_block_helper,
> @@ -1550,14 +1559,6 @@ int selfcheck(void)
> msg_gerr("Flashchips table miscompilation!\n");
> ret = 1;
> }
> - /* Check that virtual_memory in struct flashctx is placed directly
> - * after the members copied from struct flashchip.
> - */
> - if (sizeof(struct flashchip) !=
> - offsetof(struct flashctx, virtual_memory)) {
> - msg_gerr("struct flashctx broken!\n");
> - ret = 1;
> - }
Glad to lose this hunk!
> for (flash = flashchips; flash && flash->name; flash++)
> if (selfcheck_eraseblocks(flash))
> ret = 1;
> @@ -1642,7 +1643,7 @@ void check_chip_supported(const struct flashctx *flash)
> /* FIXME: This function signature needs to be improved once doit() has a better
> * function signature.
> */
> -int chip_safety_check(struct flashctx *flash, int force, int read_it,
> +int chip_safety_check(const struct flashchip *flash, int force, int read_it,
Can you please make sure that all pointers to struct flashchip are
called "chip"? Otherwise grepping for "chip->" won't return all accesses
to struct flashchip. The same comment applies to other hunks of the
patch as well.
However, chip_safety_check can not be converted to a different calling
convention because we need struct flashctx here. Admittedly we don't
need it right now, but we will need it once programmer_may_write is part
of the programmer struct in struct flashctx.
> int write_it, int erase_it, int verify_it)
> {
> if (!programmer_may_write && (write_it || erase_it)) {
> @@ -1710,9 +1711,10 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
> uint8_t *oldcontents;
> uint8_t *newcontents;
> int ret = 0;
> - unsigned long size = flash->total_size * 1024;
> + const struct flashchip *chip = flash->chip;
> + unsigned long size = chip->total_size * 1024;
>
> - if (chip_safety_check(flash, force, read_it, write_it, erase_it, verify_it)) {
> + if (chip_safety_check(chip, force, read_it, write_it, erase_it, verify_it)) {
No conversion, please. See above.
> msg_cerr("Aborting.\n");
> ret = 1;
> goto out_nofree;
> @@ -1791,7 +1793,7 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
>
> // This should be moved into each flash part's code to do it
> // cleanly. This does the job.
> - handle_romentries(flash, oldcontents, newcontents);
> + handle_romentries(chip, oldcontents, newcontents);
No conversion, please. See two hunks below.
>
> // ////////////////////////////////////////////////////////////
>
> diff --git a/jedec.c b/jedec.c
> index 69c0c0c..5c549a2 100644
> --- a/jedec.c
> +++ b/jedec.c
> @@ -93,7 +93,7 @@ void data_polling_jedec(const struct flashctx *flash, chipaddr dst,
> msg_cdbg("%s: excessive loops, i=0x%x\n", __func__, i);
> }
>
> -static unsigned int getaddrmask(struct flashctx *flash)
> +static unsigned int getaddrmask(const struct flashchip *flash)
Hm yes, const makes sense. In fact, const makes sense in many more places.
> {
> switch (flash->feature_bits & FEATURE_ADDR_MASK) {
> case FEATURE_ADDR_FULL:
> diff --git a/layout.c b/layout.c
> index 90d3cce..f0f7a6f 100644
> --- a/layout.c
> +++ b/layout.c
> @@ -302,7 +302,7 @@ romlayout_t *get_next_included_romentry(unsigned int start)
> return best_entry;
> }
>
> -int handle_romentries(struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents)
> +int handle_romentries(const struct flashchip *flash, uint8_t *oldcontents, uint8_t *newcontents)
Will we have to change this back once we try to merge the layout
patches? In that case, we need some way to get permissible regions from
the programmer, and that would probably be done via the programmer struct.
> {
> unsigned int start = 0;
> romlayout_t *entry;
> diff --git a/spi25.c b/spi25.c
> index b7e8189..2accb6d 100644
> --- a/spi25.c
> +++ b/spi25.c
> @@ -416,22 +416,23 @@ void spi_prettyprint_status_register_sst25vf040b(uint8_t status)
>
> int spi_prettyprint_status_register(struct flashctx *flash)
> {
> + const struct flashchip *chip = flash->chip;
const struct flashchip here, but just struct flashchip in the next hunk.
What's the reason? Same question applies to other hunks of the patch as
well.
> uint8_t status;
>
> status = spi_read_status_register(flash);
> msg_cdbg("Chip status register is %02x\n", status);
> - switch (flash->manufacture_id) {
> + switch (chip->manufacture_id) {
> case ST_ID:
> - if (((flash->model_id & 0xff00) == 0x2000) ||
> - ((flash->model_id & 0xff00) == 0x2500))
> + if (((chip->model_id & 0xff00) == 0x2000) ||
> + ((chip->model_id & 0xff00) == 0x2500))
> spi_prettyprint_status_register_st_m25p(status);
> break;
> case MACRONIX_ID:
> - if ((flash->model_id & 0xff00) == 0x2000)
> + if ((chip->model_id & 0xff00) == 0x2000)
> spi_prettyprint_status_register_st_m25p(status);
> break;
> case SST_ID:
> - switch (flash->model_id) {
> + switch (chip->model_id) {
> case 0x2541:
> spi_prettyprint_status_register_sst25vf016(status);
> break;
> @@ -862,16 +863,17 @@ static int spi_write_status_register_wren(struct flashctx *flash, int status)
>
> int spi_write_status_register(struct flashctx *flash, int status)
> {
> + struct flashchip *chip = flash->chip;
> int ret = 1;
>
> - if (!(flash->feature_bits & (FEATURE_WRSR_WREN | FEATURE_WRSR_EWSR))) {
> + if (!(chip->feature_bits & (FEATURE_WRSR_WREN | FEATURE_WRSR_EWSR))) {
> msg_cdbg("Missing status register write definition, assuming "
> "EWSR is needed\n");
> - flash->feature_bits |= FEATURE_WRSR_EWSR;
> + chip->feature_bits |= FEATURE_WRSR_EWSR;
> }
> - if (flash->feature_bits & FEATURE_WRSR_WREN)
> + if (chip->feature_bits & FEATURE_WRSR_WREN)
> ret = spi_write_status_register_wren(flash, status);
> - if (ret && (flash->feature_bits & FEATURE_WRSR_EWSR))
> + if (ret && (chip->feature_bits & FEATURE_WRSR_EWSR))
> ret = spi_write_status_register_ewsr(flash, status);
> return ret;
> }
I think the next iteration of this patch can go in.
Regards,
Carl-Daniel
--
http://www.hailfinger.org/
Hi Mike,
a few years ago, you asked about IBM lflash (firmware updating of BIOS,
RSA, and BMC hardware under Linux) users on the xcat.org mailing list.
Are you still involved with that project inside IBM, and if not, do you
know anyone I can contact about getting the source code for it or
getting documentation for the hardware interfaces it uses?
Background: I am one of the developers of the open source (GPLv2
license) flashrom utility which can update the firmware/BIOS/EFI of most
x86 mainboards from within a Linux/*BSD/DOS system, and which can also
update the firmware on quite a few network/storage/graphics cards.
We would love to add a driver for IBM RSA/BMC firmware updating to
flashrom, and we have been approached by someone whose company is using
IBM SurePOS all over the world. lflash is apparently almost(?)
impossible to get by for SurePOS, and save rebooting every terminal into
DOS, flashrom seems to be the only choice right now. Writing a flashrom
driver for new hardware is easy (~30 lines of code), and if we can get
documentation for the flashing interface of IBM RSA/BMC, we will do that
ourselves and integrate that driver into the official flashrom sources.
Thanks in advance for your help.
Regards,
Carl-Daniel
Am 31.07.2012 20:52 schrieb Stefan Tauner:
> Helge Wagner's patch that added VIA VX900 chipset support made me look
> closer at the datasheets which led to some concise documentation about
> newer VIA chipsets: http://flashrom.org/VIA
Thanks, that was very helpful. I have updated the wiki with new information.
> Based on that this patch adds full support for VX800/VX820, VX855/VX875
> and VX900, including SPI and LPC. VT8237S was not changed (SPI support
> only) because there is no public datasheet and it is not clear how to
> distinguish between LPC and SPI strapping and investigations in (NDAed)
> documents have not brought up anything conclusively.
>
> enable_flash_vt823x could probably be enhanced too due to various
> yet ignored LPC options of the chipset.
>
> Signed-off-by: Helge Wagner <Helge.Wagner(a)ge.com>
> Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
The more I learn about VIA, the less I'm inclined to change the
behaviour of flashrom substantially directly before a release.
I would like to get a modified version of this patch merged after 0.9.6.
> New version with tiny changes for 0.9.6...
> test status is NT and arguable... but since there are so few VIA users
> out there anyway i think we wont get too many mails anyway.
>
> chipset_enable.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-------
> ichspi.c | 11 +++-----
> programmer.h | 2 +-
> 3 files changed, 75 insertions(+), 18 deletions(-)
>
> diff --git a/chipset_enable.c b/chipset_enable.c
> index 936d7b8..0974427 100644
> --- a/chipset_enable.c
> +++ b/chipset_enable.c
> @@ -6,6 +6,7 @@
> * Copyright (C) 2006 Uwe Hermann <uwe(a)hermann-uwe.de>
> * Copyright (C) 2007,2008,2009 Carl-Daniel Hailfinger
> * Copyright (C) 2009 Kontron Modular Computers GmbH
> + * Copyright (C) 2011, 2012 Stefan Tauner
> *
> * 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
> @@ -508,12 +509,6 @@ static int enable_flash_tunnelcreek(struct pci_dev *dev, const char *name)
> return ret;
> }
>
> -static int enable_flash_vt8237s_spi(struct pci_dev *dev, const char *name)
> -{
> - /* Do we really need no write enable? */
> - return via_init_spi(dev);
> -}
> -
> static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name,
> enum ich_chipset ich_generation)
> {
> @@ -681,16 +676,80 @@ static int enable_flash_vt823x(struct pci_dev *dev, const char *name)
> return -1;
> }
>
> - if (dev->device_id == 0x3227) { /* VT8237R */
> + if (dev->device_id == 0x3227) { /* VT8237 */
If you change that comment, please change it to VT8237/VT8237R.
> /* All memory cycles, not just ROM ones, go to LPC. */
> val = pci_read_byte(dev, 0x59);
> val &= ~0x80;
> rpci_write_byte(dev, 0x59, val);
> }
>
> + internal_buses_supported = BUS_LPC | BUS_FWH;
It's not that easy. Some older VIA chipsets do not support ROMs on
LPC/FWH, or LPC/FWH at all. And unfortunately, not all VIA chipsets
allow you to read the ROM type straps. Please kill this hunk for now.
VT8231 can speak Parallel/LPC
VT8233 can speak Parallel/LPC
VT8233A ???
VT8235 can speak Parallel/LPC/FWH
VT8237A ???
VT8237R can speak LPC/FWH (and is identical to VT8237)
VT8237S can speak LPC/FWH/SPI
CX700 can speak LPC/FWH
VX[89]* can speak LPC/FWH/SPI
Adding that information to the chipset enable functions should be done
in a separate patch. I can do that if you want... it's pretty tricky.
> return 0;
> }
>
> +static int enable_flash_vt_vx(struct pci_dev *dev, const char *name)
> +{
> + struct pci_dev *south_north = pci_dev_find(0x1106, 0xa353);
> + if (south_north == NULL) {
> + msg_perr("Could not find South-North Module Interface Control device!\n");
> + return ERROR_FATAL;
> + }
> +
> + msg_pdbg("Strapped to ");
> + if ((pci_read_byte(south_north, 0x56) & 0x01) == 0) {
> + msg_pdbg("LPC.\n");
> + return enable_flash_vt823x(dev, name);
> + }
> + msg_pdbg("SPI.\n");
> +
> + uint32_t mmio_base;
> + void *mmio_base_physmapped;
> + uint32_t spi_cntl;
> + #define SPI_CNTL_LEN 0x08
> + uint32_t spi0_mm_base = 0;
> + switch(dev->device_id) {
> + case 0x8353: /* VX800/VX820 */
> + spi0_mm_base = pci_read_long(dev, 0xbc) << 8;
> + break;
> + case 0x8409: /* VX855/VX875 */
> + case 0x8410: /* VX900 */
> + mmio_base = pci_read_long(dev, 0xbc) << 8;
> + mmio_base_physmapped = physmap("VIA VX MMIO register", mmio_base, SPI_CNTL_LEN);
> + if (mmio_base_physmapped == ERROR_PTR) {
> + physunmap(mmio_base_physmapped, SPI_CNTL_LEN);
> + return ERROR_FATAL;
> + }
> +
> + /* Offset 0 - Bit 0 holds SPI Bus0 Enable Bit. */
> + spi_cntl = mmio_readl(mmio_base_physmapped) + 0x00;
> + if ((spi_cntl & 0x01) == 0) {
> + msg_pdbg ("SPI Bus0 disabled!\n");
> + physunmap(mmio_base_physmapped, SPI_CNTL_LEN);
> + return ERROR_FATAL;
> + }
> + /* Offset 1-3 has SPI Bus Memory Map Base Address: */
> + spi0_mm_base = spi_cntl & 0xFFFFFF00;
> +
> + /* Offset 4 - Bit 0 holds SPI Bus1 Enable Bit. */
> + spi_cntl = mmio_readl(mmio_base_physmapped) + 0x04;
> + if ((spi_cntl & 0x01) == 1)
> + msg_pdbg2("SPI Bus1 is enabled too.\n");
We don't handle that anywhere, so it should probably spit out some
really loud warning.
> +
> + physunmap(mmio_base_physmapped, SPI_CNTL_LEN);
> + break;
> + default:
> + msg_perr("%s: Unsupported chipset %x:%x!\n", __func__, dev->vendor_id, dev->device_id);
> + return ERROR_FATAL;
> + }
> +
> + return via_init_spi(dev, spi0_mm_base);
> +}
> +
> +static int enable_flash_vt8237s_spi(struct pci_dev *dev, const char *name)
This function needs to die.
> +{
> + return via_init_spi(dev, pci_read_long(dev, 0xbc) << 8);
> +}
> +
> static int enable_flash_cs5530(struct pci_dev *dev, const char *name)
> {
> uint8_t reg8;
> @@ -1263,7 +1322,7 @@ const struct penable chipset_enables[] = {
> {0x1106, 0x0586, OK, "VIA", "VT82C586A/B", enable_flash_amd8111},
> {0x1106, 0x0596, OK, "VIA", "VT82C596", enable_flash_amd8111},
> {0x1106, 0x0686, OK, "VIA", "VT82C686A/B", enable_flash_amd8111},
> - {0x1106, 0x3074, OK, "VIA", "VT8233", enable_flash_vt823x},
> + {0x1106, 0x3074, OK, "VIA", "VT8233/VT8237R", enable_flash_vt823x},
No, that's very likely just a datasheet bug (compare table 4 in VT8237R
datasheet 2.06 to the values mentioned in the detailed register
description for the Bus Control device). Please undo this hunk.
> {0x1106, 0x3147, OK, "VIA", "VT8233A", enable_flash_vt823x},
> {0x1106, 0x3177, OK, "VIA", "VT8235", enable_flash_vt823x},
> {0x1106, 0x3227, OK, "VIA", "VT8237", enable_flash_vt823x},
> @@ -1271,8 +1330,9 @@ const struct penable chipset_enables[] = {
> {0x1106, 0x3372, OK, "VIA", "VT8237S", enable_flash_vt8237s_spi},
> {0x1106, 0x8231, NT, "VIA", "VT8231", enable_flash_vt823x},
> {0x1106, 0x8324, OK, "VIA", "CX700", enable_flash_vt823x},
> - {0x1106, 0x8353, OK, "VIA", "VX800/VX820", enable_flash_vt8237s_spi},
> - {0x1106, 0x8409, OK, "VIA", "VX855/VX875", enable_flash_vt823x},
> + {0x1106, 0x8353, NT, "VIA", "VX800/VX820", enable_flash_vt_vx},
> + {0x1106, 0x8409, NT, "VIA", "VX855/VX875", enable_flash_vt_vx},
> + {0x1106, 0x8410, NT, "VIA", "VX900", enable_flash_vt_vx},
> {0x1166, 0x0200, OK, "Broadcom", "OSB4", enable_flash_osb4},
> {0x1166, 0x0205, OK, "Broadcom", "HT-1000", enable_flash_ht1000},
> {0x17f3, 0x6030, OK, "RDC", "R8610/R3210", enable_flash_rdc_r8610},
> diff --git a/ichspi.c b/ichspi.c
> index 0223ae3..44d659b 100644
> --- a/ichspi.c
> +++ b/ichspi.c
> @@ -1844,19 +1844,16 @@ static const struct spi_programmer spi_programmer_via = {
> .write_aai = default_spi_write_aai,
> };
>
> -int via_init_spi(struct pci_dev *dev)
> +int via_init_spi(struct pci_dev *dev, uint32_t mmio_base)
> {
> - uint32_t mmio_base;
> int i;
>
> - mmio_base = (pci_read_long(dev, 0xbc)) << 8;
> - msg_pdbg("MMIO base at = 0x%x\n", mmio_base);
> - ich_spibar = physmap("VT8237S MMIO registers", mmio_base, 0x70);
> + ich_spibar = physmap("VIA SPI MMIO registers", mmio_base, 0x70);
> + /* Do we really need no write enable? Like the LPC one at D17F0 0x40 */
>
> - /* Not sure if it speaks all these bus protocols. */
> - internal_buses_supported = BUS_LPC | BUS_FWH;
> ich_generation = CHIPSET_ICH7;
> register_spi_programmer(&spi_programmer_via);
> + internal_buses_supported = BUS_SPI;
Please undo the internal_buses_supported change here.
So far, all VIA chipsets with SPI also support LPC/FWH. We could either
call enable_flash_vt823x() on all SPI-capable chipsets as well, and have
LPC/FWH/SPI sorted out automatically by flashrom, or we could try to
read the ROM straps, which may or may not be readable or documented.
>
> msg_pdbg("0x00: 0x%04x (SPIS)\n", mmio_readw(ich_spibar + 0));
> msg_pdbg("0x02: 0x%04x (SPIC)\n", mmio_readw(ich_spibar + 2));
> diff --git a/programmer.h b/programmer.h
> index 5109ed9..ec29ed8 100644
> --- a/programmer.h
> +++ b/programmer.h
> @@ -561,7 +561,7 @@ enum ich_chipset {
> extern uint32_t ichspi_bbar;
> int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
> enum ich_chipset ich_generation);
> -int via_init_spi(struct pci_dev *dev);
> +int via_init_spi(struct pci_dev *dev, uint32_t mmio_base);
>
> /* it85spi.c */
> int it85xx_spi_init(struct superio s);
Regards,
Carl-Daniel
--
http://www.hailfinger.org/
On Wed, 2012-08-15 at 02:10 +0200, Alexander Meyer wrote:
> Hi,
>
> I had problems making flashrom talk to an Arduino as described in
> http://www.flashrom.org/index.php?title=Serprog&redirect=no
>
> It always failed right after this:
> Warning: Automatic command availability check failed for cmd 0x12 -
> won't execute cmd
I am sorry, I was waiting for a Tested-by line that didn't come fast
enough(I don't have the hardware with me so I rely on a user to test my
commits)....
Now the fix should be pushed...
Beside There are issues with the speed with the arduino uno because of
the microcontroller doing the USB<->Serial conversion....
Such issues are absent on the arduino duemillanove.
I'll try to fix it when I have access to my arduino uno again....
Also I have not found the corresponding source code of the firmware
running on that microcontroller: they give a binary in the arduino git
and source code that doesn't seem to correspond to it.
However I've a nearly equivalent(only reset don't work out of the box)
firmware with LUFA alone.
The idea is to fix the reset and then try to fix the serial issues that
occur at higher speeds.
Denis.