Hi Joseph,
thank you very much. I have added the requirements section to the man page and changed some whitespace and a comment in atapromise.c.
Patch follows at the end of this mail. If you don't have any objections, may I ask you to sign off on that latest iteration, then I'll commit. Thanks again for submitting the patch and for addressing all our concerns.
Regards, Carl-Daniel
On 14.01.2016 13:23, Joseph C. Lehner wrote:
I've addressed the issues you pointed out. Thanks for your input, here is the updated patch.
On 2016-01-13 22:53, Carl-Daniel Hailfinger wrote:
Hi Joseph,
great work!
Your patch would benefit from some changes in general flashrom infrastructure, but we're pretty busy with our main jobs and won't be able to implement that soon. Holding your patch back would be counterproductive, so we've decided to merge it in the next few days.
May I request three changes, though:
- Please default CONFIG_ATAPROMISE to no. This is only temporary until
we have a clean chip size trimming infrastructure.
- Please provide a warning message in atapromise_init similar to the
suggestion below.
- Please write a man page entry for your programmer driver.
Thanks.
On 13.01.2016 14:13, Joseph C. Lehner wrote:
Just a quick update: A16 and A15 on my Ultra100 are connected to GND, so that explains the 32 kB limit. I've updated the docs in the source accordingly and attached the new patch.
Index: flashrom-atapromise/Makefile =================================================================== --- flashrom-atapromise/Makefile (Revision 1915) +++ flashrom-atapromise/Makefile (Arbeitskopie) @@ -227,6 +227,11 @@ else override CONFIG_ATAVIA = no endif +ifeq ($(CONFIG_ATAPROMISE), yes) +UNSUPPORTED_FEATURES += CONFIG_ATAPROMISE=yes +else +override CONFIG_ATAPROMISE = no +endif ifeq ($(CONFIG_IT8212), yes) UNSUPPORTED_FEATURES += CONFIG_IT8212=yes else @@ -449,6 +454,9 @@ # VIA VT6421A LPC memory support CONFIG_ATAVIA ?= yes
+# Promise ATA controller support. +CONFIG_ATAPROMISE ?= no + # Always enable FT2232 SPI dongles for now. CONFIG_FT2232_SPI ?= yes
@@ -626,6 +634,12 @@ NEED_PCI := yes endif
+ifeq ($(CONFIG_ATAPROMISE), yes) +FEATURE_CFLAGS += -D'CONFIG_ATAPROMISE=1' +PROGRAMMER_OBJS += atapromise.o +NEED_PCI := yes +endif + ifeq ($(CONFIG_IT8212), yes) FEATURE_CFLAGS += -D'CONFIG_IT8212=1' PROGRAMMER_OBJS += it8212.o Index: flashrom-atapromise/atapromise.c =================================================================== --- flashrom-atapromise/atapromise.c (Revision 0) +++ flashrom-atapromise/atapromise.c (Arbeitskopie) @@ -0,0 +1,177 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2015 Joseph C. Lehner joseph.c.lehner@gmail.com + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if defined(__i386__) || defined(__x86_64__) + +#include <string.h> +#include <stdlib.h> +#include "flash.h" +#include "programmer.h" +#include "hwaccess.h" + +#define MAX_ROM_DECODE (32 * 1024) +#define ADDR_MASK (MAX_ROM_DECODE - 1) + +/* + * In the absence of any public docs on the PDC2026x family, this programmer was created through a mix of + * reverse-engineering and trial and error. + * + * The only device tested is an Ultra100 controller, but the logic for programming the other 2026x controllers + * is the same, so it should, in theory, work for those as well. + * + * While the tested Ultra100 controller used a 128 kB MX29F001T chip, A16 and A15 showed continuity to ground, + * thus limiting the the programmer on this card to 32 kB. Without other controllers to test this programmer on, + * this is currently a hard limit. Note that ROM files for these controllers are 16 kB only. + * + * Since flashrom does not support accessing flash chips larger than the size limit of the programmer (the + * tested Ultra100 uses a 128 kB MX29F001T chip), the chip size is hackishly adjusted in atapromise_limit_chip. + */ + +static uint32_t io_base_addr = 0; +static uint32_t rom_base_addr = 0; + +static uint8_t *atapromise_bar = NULL; +static size_t rom_size = 0; + +const struct dev_entry ata_promise[] = { + {0x105a, 0x4d38, NT, "Promise", "PDC20262 (FastTrak66/Ultra66)"}, + {0x105a, 0x0d30, NT, "Promise", "PDC20265 (FastTrak100 Lite/Ultra100)"}, + {0x105a, 0x4d30, OK, "Promise", "PDC20267 (FastTrak100/Ultra100)"}, + {0}, +}; + +static void atapromise_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr); +static uint8_t atapromise_chip_readb(const struct flashctx *flash, const chipaddr addr); + +static const struct par_master par_master_atapromise = { + .chip_readb = atapromise_chip_readb, + .chip_readw = fallback_chip_readw, + .chip_readl = fallback_chip_readl, + .chip_readn = fallback_chip_readn, + .chip_writeb = atapromise_chip_writeb, + .chip_writew = fallback_chip_writew, + .chip_writel = fallback_chip_writel, + .chip_writen = fallback_chip_writen, +}; + +void *atapromise_map(const char *descr, uintptr_t phys_addr, size_t len) +{ + /* In case fallback_map ever returns something other than NULL. */ + return NULL; +} + +static void atapromise_limit_chip(struct flashchip *chip) +{ + static uint32_t last_model_id = 0; + unsigned int i, size; + + if (chip->model_id == last_model_id) + return; + + size = chip->total_size * 1024; + if (size > rom_size) { + /* Undefine all block_erasers that don't operate on the whole chip, + * and adjust the eraseblock size of the one that does. + */ + for (i = 0; i < NUM_ERASEFUNCTIONS; ++i) { + if (chip->block_erasers[i].eraseblocks[0].size != size) { + chip->block_erasers[i].eraseblocks[0].count = 0; + chip->block_erasers[i].block_erase = NULL; + } else { + chip->block_erasers[i].eraseblocks[0].size = rom_size; + break; + } + } + + if (i != NUM_ERASEFUNCTIONS) { + chip->total_size = rom_size / 1024; + if (chip->page_size > rom_size) + chip->page_size = rom_size; + } else { + msg_pdbg("Failed to adjust size of chip "%s" (%d kB).\n", chip->name, + chip->total_size); + } + } + + last_model_id = chip->model_id; +} + +int atapromise_init(void) +{ + struct pci_dev *dev = NULL; + + if (rget_io_perms()) + return 1; + + dev = pcidev_init(ata_promise, PCI_BASE_ADDRESS_4); + if (!dev) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_4) & 0xfffe; + if (!io_base_addr) { + return 1; + } + + /* Not exactly sure what this does, because flashing seems to work + * well without it. However, PTIFLASH does it, so we do it too. + */ + OUTB(1, io_base_addr + 0x10); + + rom_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_5); + if (!rom_base_addr) { + msg_pdbg("Failed to read BAR5\n"); + return 1; + } + + rom_size = dev->rom_size > MAX_ROM_DECODE ? MAX_ROM_DECODE : dev->rom_size; + atapromise_bar = (uint8_t*)rphysmap("Promise", rom_base_addr, rom_size); + if (atapromise_bar == ERROR_PTR) { + return 1; + } + + max_rom_decode.parallel = rom_size; + register_par_master(&par_master_atapromise, BUS_PARALLEL); + + msg_pwarn("Do not use this device as a generic programmer. It will leave anything outside\n" + "the first %zu kB of the flash chip in an undefined state. It works fine for the\n" + "purpose of updating the firmware of this device (padding may neccessary).\n", + rom_size / 1024); + + return 0; +} + +static void atapromise_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) +{ + uint32_t data; + + atapromise_limit_chip(flash->chip); + data = (rom_base_addr + (addr & ADDR_MASK)) << 8 | val; + OUTL(data, io_base_addr + 0x14); +} + +static uint8_t atapromise_chip_readb(const struct flashctx *flash, const chipaddr addr) +{ + atapromise_limit_chip(flash->chip); + return pci_mmio_readb(atapromise_bar + (addr & ADDR_MASK)); +} + +#else +#error PCI port I/O access is not supported on this architecture yet. +#endif Index: flashrom-atapromise/flashrom.8.tmpl =================================================================== --- flashrom-atapromise/flashrom.8.tmpl (Revision 1915) +++ flashrom-atapromise/flashrom.8.tmpl (Arbeitskopie) @@ -233,6 +233,8 @@ .sp .BR "* atavia" " (for flash ROMs on VIA VT6421A SATA controllers)" .sp +.BR "* atapromise" " (for flash ROMs on Promise PDC2026x ATA/RAID controllers)" +.sp .BR "* it8212" " (for flash ROMs on ITE IT8212F ATA/RAID controller)" .sp .BR "* ft2232_spi" " (for SPI flash ROMs attached to an FT2232/FT4232H/FT232H family \ @@ -636,7 +638,7 @@ .SS .BR "nic3com" , " nicrealtek" , " nicnatsemi" , " nicintel", " nicintel_eeprom"\ , " nicintel_spi" , " gfxnvidia" , " ogp_spi" , " drkaiser" , " satasii"\ -, " satamv" , " atahpt", " atavia " and " it8212 " programmers +, " satamv" , " atahpt", " atavia ", " atapromise " and " it8212 " programmers .IP These programmers have an option to specify the PCI address of the card your want to use, which must be specified if more than one card supported @@ -669,6 +671,13 @@ For more information please see .URLB https://flashrom.org/VT6421A "its wiki page" . .SS +.BR "atapromise " programmer +.IP +This programmer is currently limited to 32 kB, regardless of the actual size of the flash chip. This stems +from the fact that, on the tested device (a Promise Ultra100), not all of the chip's address lines were +actually connected. You may use this programmer to flash firmware updates, since these are only 16 kB in +size (padding to 32 kB is required). +.SS .BR "nicintel_eeprom " programmer .IP This is the first programmer module in flashrom that does not provide access to NOR flash chips but EEPROMs @@ -1059,8 +1068,8 @@ .BR satasii ", " nicintel ", " nicintel_eeprom " and " nicintel_spi need PCI configuration space read access and raw memory access. .sp -.B satamv -needs PCI configuration space read access, raw I/O port access and raw memory +.BR satamv " and " atapromise +need PCI configuration space read access, raw I/O port access and raw memory access. .sp .B serprog @@ -1076,7 +1085,7 @@ needs no access permissions at all. .sp .BR internal ", " nic3com ", " nicrealtek ", " nicnatsemi ", " -.BR gfxnvidia ", " drkaiser ", " satasii ", " satamv ", " atahpt" and " atavia +.BR gfxnvidia ", " drkaiser ", " satasii ", " satamv ", " atahpt ", " atavia " and " atapromise have to be run as superuser/root, and need additional raw access permission. .sp .BR serprog ", " buspirate_spi ", " dediprog ", " usbblaster_spi ", " ft2232_spi " and " pickit2_spi Index: flashrom-atapromise/flashrom.c =================================================================== --- flashrom-atapromise/flashrom.c (Revision 1915) +++ flashrom-atapromise/flashrom.c (Arbeitskopie) @@ -182,6 +182,18 @@ }, #endif
+#if CONFIG_ATAPROMISE == 1 + { + .name = "atapromise", + .type = PCI, + .devs.dev = ata_promise, + .init = atapromise_init, + .map_flash_region = atapromise_map, + .unmap_flash_region = fallback_unmap, + .delay = internal_delay, + }, +#endif + #if CONFIG_IT8212 == 1 { .name = "it8212", Index: flashrom-atapromise/programmer.h =================================================================== --- flashrom-atapromise/programmer.h (Revision 1915) +++ flashrom-atapromise/programmer.h (Arbeitskopie) @@ -57,6 +57,9 @@ #if CONFIG_ATAVIA == 1 PROGRAMMER_ATAVIA, #endif +#if CONFIG_ATAPROMISE == 1 + PROGRAMMER_ATAPROMISE, +#endif #if CONFIG_IT8212 == 1 PROGRAMMER_IT8212, #endif @@ -460,6 +463,13 @@ extern const struct dev_entry ata_via[]; #endif
+/* atapromise.c */ +#if CONFIG_ATAPROMISE == 1 +int atapromise_init(void); +void *atapromise_map(const char *descr, uintptr_t phys_addr, size_t len); +extern const struct dev_entry ata_promise[]; +#endif + /* it8212.c */ #if CONFIG_IT8212 == 1 int it8212_init(void);