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(a)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