Hi flashrom guys,
based on the 3COM NIC programmer I created a new one for DEC Tulip Cards. The IC socket on these cards is 28pin so it supports only chips up to 64kB.
I tested reading with several 27C256 chips (old 386er BIOSes). Therefore I also created two dumb EPROMS in flashchips.
Also I added the ST M29F010B chip, tested on a 3COM NIC.
Best regards
Heiko Jehmlich
diff --git a/Makefile b/Makefile index 6d37d55..af19d25 100644 --- a/Makefile +++ b/Makefile @@ -258,6 +258,11 @@ UNSUPPORTED_FEATURES += CONFIG_NIC3COM=yes else override CONFIG_NIC3COM = no endif +ifeq ($(CONFIG_NICTULIP), yes) +UNSUPPORTED_FEATURES += CONFIG_NICTULIP=yes +else +override CONFIG_NICTULIP = no +endif ifeq ($(CONFIG_GFXNVIDIA), yes) UNSUPPORTED_FEATURES += CONFIG_GFXNVIDIA=yes else @@ -514,6 +519,11 @@ UNSUPPORTED_FEATURES += CONFIG_NIC3COM=yes else override CONFIG_NIC3COM = no endif +ifeq ($(CONFIG_NICTULIP), yes) +UNSUPPORTED_FEATURES += CONFIG_NICTULIP=yes +else +override CONFIG_NICTULIP = no +endif ifeq ($(CONFIG_NICREALTEK), yes) UNSUPPORTED_FEATURES += CONFIG_NICREALTEK=yes else @@ -570,6 +580,11 @@ UNSUPPORTED_FEATURES += CONFIG_NIC3COM=yes else override CONFIG_NIC3COM = no endif +ifeq ($(CONFIG_NICTULIP), yes) +UNSUPPORTED_FEATURES += CONFIG_NICTULIP=yes +else +override CONFIG_NICTULIP = no +endif ifeq ($(CONFIG_GFXNVIDIA), yes) UNSUPPORTED_FEATURES += CONFIG_GFXNVIDIA=yes else @@ -699,6 +714,9 @@ CONFIG_PONY_SPI ?= yes # Always enable 3Com NICs for now. CONFIG_NIC3COM ?= yes
+# Always enable DECchip NICs for now. +CONFIG_NICTULIP ?= yes + # Enable NVIDIA graphics cards. Note: write and erase do not work properly. CONFIG_GFXNVIDIA ?= yes
@@ -826,6 +844,7 @@ endif ifeq ($(CONFIG_ENABLE_LIBPCI_PROGRAMMERS), no) override CONFIG_INTERNAL = no override CONFIG_NIC3COM = no +override CONFIG_NICTULIP = no override CONFIG_GFXNVIDIA = no override CONFIG_SATASII = no override CONFIG_ATAHPT = no @@ -954,6 +973,12 @@ PROGRAMMER_OBJS += nic3com.o NEED_LIBPCI += CONFIG_NIC3COM endif
+ifeq ($(CONFIG_NICTULIP), yes) +FEATURE_CFLAGS += -D'CONFIG_NICTULIP=1' +PROGRAMMER_OBJS += nictulip.o +NEED_LIBPCI += CONFIG_NICTULIP +endif + ifeq ($(CONFIG_GFXNVIDIA), yes) FEATURE_CFLAGS += -D'CONFIG_GFXNVIDIA=1' PROGRAMMER_OBJS += gfxnvidia.o diff --git a/flashchips.c b/flashchips.c index 6d94a12..1491cdc 100644 --- a/flashchips.c +++ b/flashchips.c @@ -57,6 +57,38 @@ const struct flashchip flashchips[] = { */
{ + .vendor = "EPROM", + .name = "27C256", + .bustype = BUS_PARALLEL, + .manufacture_id = GENERIC_MANUF_ID, + .model_id = 0x00, + .total_size = 32, + .page_size = 0, /* unused */ + .feature_bits = 0, + .tested = {.probe = BAD, .read = OK, .erase = BAD, .write = BAD}, + .probe = NULL, + .write = NULL, + .read = read_memmapped, + .voltage = {4500, 5500}, + }, + + { + .vendor = "EPROM", + .name = "27C512", + .bustype = BUS_PARALLEL, + .manufacture_id = GENERIC_MANUF_ID, + .model_id = 0x00, + .total_size = 64, + .page_size = 0, /* unused */ + .feature_bits = 0, + .tested = {.probe = BAD, .read = OK, .erase = BAD, .write = BAD}, + .probe = NULL, + .write = NULL, + .read = read_memmapped, + .voltage = {4500, 5500}, + }, + + { .vendor = "AMD", .name = "Am29F002(N)BB", .bustype = BUS_PARALLEL, @@ -14764,6 +14796,33 @@ const struct flashchip flashchips[] = {
{ .vendor = "ST", + .name = "M29F010B", + .bustype = BUS_PARALLEL, + .manufacture_id = ST_ID, + .model_id = ST_M29F010B, + .total_size = 128, + .page_size = 16 * 1024, + .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, + .tested = TEST_OK_PREW, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* datasheet specifies no timing */ + .block_erasers = + { + { + .eraseblocks = { {16 * 1024, 8} }, + .block_erase = erase_sector_jedec, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = erase_chip_block_jedec, + } + }, + .write = write_jedec_1, + .read = read_memmapped, + .voltage = {4500, 5500}, + }, + + { + .vendor = "ST", .name = "M29F040B", .bustype = BUS_PARALLEL, .manufacture_id = ST_ID, diff --git a/flashchips.h b/flashchips.h index a85fa6a..a3935ce 100644 --- a/flashchips.h +++ b/flashchips.h @@ -838,6 +838,7 @@ #define ST_M50LPW116 0x30 #define ST_M29F002B 0x34 /* Same as M29F002BB */ #define ST_M29F002T 0xB0 /* Same as M29F002BT/M29F002NT/M29F002BNT */ +#define ST_M29F010B 0x20 /* Same as M29F010 */ #define ST_M29F040B 0xE2 /* Same as M29F040 */ #define ST_M29F080 0xF1 #define ST_M29F200BT 0xD3 diff --git a/flashrom.c b/flashrom.c index c89abad..267d0ef 100644 --- a/flashrom.c +++ b/flashrom.c @@ -108,6 +108,18 @@ const struct programmer_entry programmer_table[] = { }, #endif
+#if CONFIG_NICTULIP == 1 + { + .name = "nictulip", + .type = PCI, + .devs.dev = nics_tulip, + .init = nictulip_init, + .map_flash_region = fallback_map, + .unmap_flash_region = fallback_unmap, + .delay = internal_delay, + }, +#endif + #if CONFIG_NICREALTEK == 1 { /* This programmer works for Realtek RTL8139 and SMC 1211. */ diff --git a/programmer.h b/programmer.h index 29a100b..a9608e0 100644 --- a/programmer.h +++ b/programmer.h @@ -37,6 +37,9 @@ enum programmer { #if CONFIG_NIC3COM == 1 PROGRAMMER_NIC3COM, #endif +#if CONFIG_NICTULIP == 1 + PROGRAMMER_NICTULIP, +#endif #if CONFIG_NICREALTEK == 1 PROGRAMMER_NICREALTEK, #endif @@ -410,6 +413,12 @@ int nic3com_init(void); extern const struct dev_entry nics_3com[]; #endif
+/* nictulip.c */ +#if CONFIG_NICTULIP == 1 +int nictulip_init(void); +extern const struct dev_entry nics_tulip[]; +#endif + /* gfxnvidia.c */ #if CONFIG_GFXNVIDIA == 1 int gfxnvidia_init(void); diff --git a/Makefile b/Makefile index 6d37d55..af19d25 100644 --- a/Makefile +++ b/Makefile @@ -258,6 +258,11 @@ UNSUPPORTED_FEATURES += CONFIG_NIC3COM=yes else override CONFIG_NIC3COM = no endif +ifeq ($(CONFIG_NICTULIP), yes) +UNSUPPORTED_FEATURES += CONFIG_NICTULIP=yes +else +override CONFIG_NICTULIP = no +endif ifeq ($(CONFIG_GFXNVIDIA), yes) UNSUPPORTED_FEATURES += CONFIG_GFXNVIDIA=yes else @@ -514,6 +519,11 @@ UNSUPPORTED_FEATURES += CONFIG_NIC3COM=yes else override CONFIG_NIC3COM = no endif +ifeq ($(CONFIG_NICTULIP), yes) +UNSUPPORTED_FEATURES += CONFIG_NICTULIP=yes +else +override CONFIG_NICTULIP = no +endif ifeq ($(CONFIG_NICREALTEK), yes) UNSUPPORTED_FEATURES += CONFIG_NICREALTEK=yes else @@ -570,6 +580,11 @@ UNSUPPORTED_FEATURES += CONFIG_NIC3COM=yes else override CONFIG_NIC3COM = no endif +ifeq ($(CONFIG_NICTULIP), yes) +UNSUPPORTED_FEATURES += CONFIG_NICTULIP=yes +else +override CONFIG_NICTULIP = no +endif ifeq ($(CONFIG_GFXNVIDIA), yes) UNSUPPORTED_FEATURES += CONFIG_GFXNVIDIA=yes else @@ -699,6 +714,9 @@ CONFIG_PONY_SPI ?= yes # Always enable 3Com NICs for now. CONFIG_NIC3COM ?= yes
+# Always enable DECchip NICs for now. +CONFIG_NICTULIP ?= yes + # Enable NVIDIA graphics cards. Note: write and erase do not work properly. CONFIG_GFXNVIDIA ?= yes
@@ -826,6 +844,7 @@ endif ifeq ($(CONFIG_ENABLE_LIBPCI_PROGRAMMERS), no) override CONFIG_INTERNAL = no override CONFIG_NIC3COM = no +override CONFIG_NICTULIP = no override CONFIG_GFXNVIDIA = no override CONFIG_SATASII = no override CONFIG_ATAHPT = no @@ -954,6 +973,12 @@ PROGRAMMER_OBJS += nic3com.o NEED_LIBPCI += CONFIG_NIC3COM endif
+ifeq ($(CONFIG_NICTULIP), yes) +FEATURE_CFLAGS += -D'CONFIG_NICTULIP=1' +PROGRAMMER_OBJS += nictulip.o +NEED_LIBPCI += CONFIG_NICTULIP +endif + ifeq ($(CONFIG_GFXNVIDIA), yes) FEATURE_CFLAGS += -D'CONFIG_GFXNVIDIA=1' PROGRAMMER_OBJS += gfxnvidia.o diff --git a/flashchips.c b/flashchips.c index 6d94a12..1491cdc 100644 --- a/flashchips.c +++ b/flashchips.c @@ -57,6 +57,38 @@ const struct flashchip flashchips[] = { */
{ + .vendor = "EPROM", + .name = "27C256", + .bustype = BUS_PARALLEL, + .manufacture_id = GENERIC_MANUF_ID, + .model_id = 0x00, + .total_size = 32, + .page_size = 0, /* unused */ + .feature_bits = 0, + .tested = {.probe = BAD, .read = OK, .erase = BAD, .write = BAD}, + .probe = NULL, + .write = NULL, + .read = read_memmapped, + .voltage = {4500, 5500}, + }, + + { + .vendor = "EPROM", + .name = "27C512", + .bustype = BUS_PARALLEL, + .manufacture_id = GENERIC_MANUF_ID, + .model_id = 0x00, + .total_size = 64, + .page_size = 0, /* unused */ + .feature_bits = 0, + .tested = {.probe = BAD, .read = OK, .erase = BAD, .write = BAD}, + .probe = NULL, + .write = NULL, + .read = read_memmapped, + .voltage = {4500, 5500}, + }, + + { .vendor = "AMD", .name = "Am29F002(N)BB", .bustype = BUS_PARALLEL, @@ -14764,6 +14796,33 @@ const struct flashchip flashchips[] = {
{ .vendor = "ST", + .name = "M29F010B", + .bustype = BUS_PARALLEL, + .manufacture_id = ST_ID, + .model_id = ST_M29F010B, + .total_size = 128, + .page_size = 16 * 1024, + .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, + .tested = TEST_OK_PREW, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* datasheet specifies no timing */ + .block_erasers = + { + { + .eraseblocks = { {16 * 1024, 8} }, + .block_erase = erase_sector_jedec, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = erase_chip_block_jedec, + } + }, + .write = write_jedec_1, + .read = read_memmapped, + .voltage = {4500, 5500}, + }, + + { + .vendor = "ST", .name = "M29F040B", .bustype = BUS_PARALLEL, .manufacture_id = ST_ID, diff --git a/flashchips.h b/flashchips.h index a85fa6a..a3935ce 100644 --- a/flashchips.h +++ b/flashchips.h @@ -838,6 +838,7 @@ #define ST_M50LPW116 0x30 #define ST_M29F002B 0x34 /* Same as M29F002BB */ #define ST_M29F002T 0xB0 /* Same as M29F002BT/M29F002NT/M29F002BNT */ +#define ST_M29F010B 0x20 /* Same as M29F010 */ #define ST_M29F040B 0xE2 /* Same as M29F040 */ #define ST_M29F080 0xF1 #define ST_M29F200BT 0xD3 diff --git a/flashrom.c b/flashrom.c index c89abad..267d0ef 100644 --- a/flashrom.c +++ b/flashrom.c @@ -108,6 +108,18 @@ const struct programmer_entry programmer_table[] = { }, #endif
+#if CONFIG_NICTULIP == 1 + { + .name = "nictulip", + .type = PCI, + .devs.dev = nics_tulip, + .init = nictulip_init, + .map_flash_region = fallback_map, + .unmap_flash_region = fallback_unmap, + .delay = internal_delay, + }, +#endif + #if CONFIG_NICREALTEK == 1 { /* This programmer works for Realtek RTL8139 and SMC 1211. */ diff --git a/programmer.h b/programmer.h index 29a100b..a9608e0 100644 --- a/programmer.h +++ b/programmer.h @@ -37,6 +37,9 @@ enum programmer { #if CONFIG_NIC3COM == 1 PROGRAMMER_NIC3COM, #endif +#if CONFIG_NICTULIP == 1 + PROGRAMMER_NICTULIP, +#endif #if CONFIG_NICREALTEK == 1 PROGRAMMER_NICREALTEK, #endif @@ -410,6 +413,12 @@ int nic3com_init(void); extern const struct dev_entry nics_3com[]; #endif
+/* nictulip.c */ +#if CONFIG_NICTULIP == 1 +int nictulip_init(void); +extern const struct dev_entry nics_tulip[]; +#endif + /* gfxnvidia.c */ #if CONFIG_GFXNVIDIA == 1 int gfxnvidia_init(void); diff --git a/nictulip.c b/nictulip.c new file mode 100644 index 0000000..bbea36a --- /dev/null +++ b/nictulip.c @@ -0,0 +1,118 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2021 Heiko Jehmlich hje@jecons.de + * + * 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. + */ + +#if defined(__i386__) || defined(__x86_64__) + +#include <stdlib.h> +#include <unistd.h> +#include "flash.h" +#include "programmer.h" +#include "hwaccess.h" + +#define CSR09 (io_base_addr + 0x48) // Boot ROM, serial ROM, and MII management +#define CSR10 (io_base_addr + 0x50) // Boot ROM programming address +#define CSR13 (io_base_addr + 0x68) // SIA connectivity register + +static uint32_t io_base_addr = 0; +static uint16_t id; + +const struct dev_entry nics_tulip[] = { + + {0x1011, 0x0014, OK, "DEC", "Digital Equipment Corporation DECchip 21041 [Tulip Pass 3]" }, + {0x1011, 0x0009, OK, "DEC", "Digital Equipment Corporation DECchip 21140 [FasterNet]" }, + {0x1011, 0x0019, OK, "DEC", "Digital Equipment Corporation DECchip 21143" }, + + {0}, +}; + +static void nictulip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) +{ + uint32_t dword; + + dword = 0; + dword |= 1 << 13; // WRITE command + dword |= 1 << 12; // select BOOT ROM + dword |= val; // write data + OUTL(dword, CSR09); + + // no idea why we need to add 1 here + dword = (addr & 0x3FFFF) + 1; + OUTL(dword, CSR10); +} + +static uint8_t nictulip_readb(const struct flashctx *flash, const chipaddr addr) +{ + uint32_t dword; + + dword = 0; + dword |= 1 << 14; // READ command + dword |= 1 << 12; // select BOOT ROM + OUTL(dword, CSR09); + + // no idea why we need to add 1 here + dword = (addr & 0x3FFFF) + 1; + OUTL(dword, CSR10); + + return (uint8_t) INL(CSR09) & 0xFF; +} + +static int nictulip_shutdown(void *data) +{ + return 0; +} + +static const struct par_master par_master_nictulip = { + .chip_readb = nictulip_readb, + .chip_readw = fallback_chip_readw, + .chip_readl = fallback_chip_readl, + .chip_readn = fallback_chip_readn, + .chip_writeb = nictulip_writeb, + .chip_writew = fallback_chip_writew, + .chip_writel = fallback_chip_writel, + .chip_writen = fallback_chip_writen, +}; + +int nictulip_init(void) +{ + struct pci_dev *dev = NULL; + + if (rget_io_perms()) + return 1; + + dev = pcidev_init(nics_tulip, PCI_BASE_ADDRESS_0); + if (!dev) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); + if (!io_base_addr) + return 1; + + id = dev->device_id; + + if (register_shutdown(nictulip_shutdown, NULL)) + return 1; + + // CSR13 must be 0 before doing any boot ROM access. + OUTL(0, CSR13); + + register_par_master(&par_master_nictulip, BUS_PARALLEL); + return 0; +} + + +#else +#error PCI port I/O access is not supported on this architecture yet. +#endif