diff mbox series

DEC Tulip programmer

Message ID 34bfdb5d-6670-69b6-1593-1c9ba1112cfb@jecons.de
State New
Headers show
Series DEC Tulip programmer | expand

Commit Message

Heiko Jehmlich Feb. 21, 2021, 9:55 a.m. UTC
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



+    return 0;
+}
+
+
+#else
+#error PCI port I/O access is not supported on this architecture yet.
+#endif
diff mbox series

Patch

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);