qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine
@ 2023-09-30 13:23 Thomas Huth
  2023-09-30 13:23 ` [PATCH 1/5] hw/m68k/next-cube: Mirror BIOS to address 0 Thomas Huth
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Thomas Huth @ 2023-09-30 13:23 UTC (permalink / raw)
  To: qemu-devel, Mark Cave-Ayland; +Cc: Laurent Vivier

Mark Cave-Ayland recently asked me about the ESP patches for the
next-cube machine that I once posted a long time ago, but never
got it merged (since Mark is currently working on improving the
ESP device). With his help, I dusted off the ESP patch, but we
had to discover that the firmware also wants to see the NIC
device in the MMIO region, otherwise it often crashes or hangs.
So here's now the current set of patches for the next-cube machine.
Both, the ESP SCSI controller and the NIC do not properly work
yet, but at least the next-cube firmware gets much further now
during it selftest, so I think this is a good base for future
work and experiments.

Thomas Huth (5):
  hw/m68k/next-cube: Mirror BIOS to address 0
  hw/scsi/esp: Work around problem with PIO data read for the NeXT-Cube
    machine
  m68k: Instantiate the ESP SCSI controller for the NeXTcube machine
  hw/m68k/next-cube: Remove unused NEXTDMA_EN code
  m68k: Add NeXTcube network controller

 hw/m68k/next-cube.c         | 194 +++++++++----
 hw/net/meson.build          |   1 +
 hw/net/next-net.c           | 538 ++++++++++++++++++++++++++++++++++++
 hw/scsi/esp.c               |   2 +-
 include/hw/m68k/next-cube.h |  10 +
 5 files changed, 692 insertions(+), 53 deletions(-)
 create mode 100644 hw/net/next-net.c

-- 
2.41.0



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] hw/m68k/next-cube: Mirror BIOS to address 0
  2023-09-30 13:23 [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Thomas Huth
@ 2023-09-30 13:23 ` Thomas Huth
  2023-09-30 13:23 ` [PATCH 2/5] hw/scsi/esp: Work around problem with PIO data read for the NeXT-Cube machine Thomas Huth
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Huth @ 2023-09-30 13:23 UTC (permalink / raw)
  To: qemu-devel, Mark Cave-Ayland; +Cc: Laurent Vivier

The ROM is also available at address 0, so add a proper mirror
for this address.

Signed-off-by: Thomas Huth <huth@tuxfamily.org>
---
 hw/m68k/next-cube.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c
index 5d244b3b95..4ab9a5ec98 100644
--- a/hw/m68k/next-cube.c
+++ b/hw/m68k/next-cube.c
@@ -945,6 +945,7 @@ static void next_cube_init(MachineState *machine)
     M68kCPU *cpu;
     CPUM68KState *env;
     MemoryRegion *rom = g_new(MemoryRegion, 1);
+    MemoryRegion *rom2 = g_new(MemoryRegion, 1);
     MemoryRegion *dmamem = g_new(MemoryRegion, 1);
     MemoryRegion *bmapm1 = g_new(MemoryRegion, 1);
     MemoryRegion *bmapm2 = g_new(MemoryRegion, 1);
@@ -998,9 +999,10 @@ static void next_cube_init(MachineState *machine)
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0200e000);
 
     /* Load ROM here */
-    /* still not sure if the rom should also be mapped at 0x0*/
     memory_region_init_rom(rom, NULL, "next.rom", 0x20000, &error_fatal);
     memory_region_add_subregion(sysmem, 0x01000000, rom);
+    memory_region_init_alias(rom2, NULL, "next.rom2", rom, 0x0, 0x20000);
+    memory_region_add_subregion(sysmem, 0x0, rom2);
     if (load_image_targphys(bios_name, 0x01000000, 0x20000) < 8) {
         if (!qtest_enabled()) {
             error_report("Failed to load firmware '%s'.", bios_name);
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] hw/scsi/esp: Work around problem with PIO data read for the NeXT-Cube machine
  2023-09-30 13:23 [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Thomas Huth
  2023-09-30 13:23 ` [PATCH 1/5] hw/m68k/next-cube: Mirror BIOS to address 0 Thomas Huth
@ 2023-09-30 13:23 ` Thomas Huth
  2023-09-30 13:23 ` [PATCH 3/5] m68k: Instantiate the ESP SCSI controller for the NeXTcube machine Thomas Huth
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Huth @ 2023-09-30 13:23 UTC (permalink / raw)
  To: qemu-devel, Mark Cave-Ayland; +Cc: Laurent Vivier

The NeXT-Cube bios uses this mode in its selftest, and without
decreasing the amount of bytes in the fifo here, the selftest
fails.

Signed-off-by: Thomas Huth <huth@tuxfamily.org>
---
 hw/scsi/esp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index e52188d022..0d54efe826 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -961,7 +961,7 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
                 (s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
             /* Data out.  */
             qemu_log_mask(LOG_UNIMP, "esp: PIO data read not implemented\n");
-            s->rregs[ESP_FIFO] = 0;
+            s->rregs[ESP_FIFO] = esp_fifo_pop(&s->fifo);
         } else {
             if ((s->rregs[ESP_RSTAT] & 0x7) == STAT_DI) {
                 if (s->ti_size) {
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] m68k: Instantiate the ESP SCSI controller for the NeXTcube machine
  2023-09-30 13:23 [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Thomas Huth
  2023-09-30 13:23 ` [PATCH 1/5] hw/m68k/next-cube: Mirror BIOS to address 0 Thomas Huth
  2023-09-30 13:23 ` [PATCH 2/5] hw/scsi/esp: Work around problem with PIO data read for the NeXT-Cube machine Thomas Huth
@ 2023-09-30 13:23 ` Thomas Huth
  2023-09-30 13:23 ` [PATCH 4/5] hw/m68k/next-cube: Remove unused NEXTDMA_EN code Thomas Huth
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Huth @ 2023-09-30 13:23 UTC (permalink / raw)
  To: qemu-devel, Mark Cave-Ayland; +Cc: Laurent Vivier

The NeXTcube uses a NCR 53C90 SCSI interface for its disks, so we should
be able to use the ESP controller from QEMU here. The code here has been
basically taken from Bryce Lanham's GSoC 2011 contribution, except for
the next_scsi_init() function which has been rewritte as a replacement
for the esp_init() function (that has been removed quite a while ago).

Note that SCSI is not working yet. The ESP code likely needs some more
fixes first and there still might be some bugs left in they way we wire
it up for the NeXT-Cube machine.

Signed-off-by: Thomas Huth <huth@tuxfamily.org>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
 hw/m68k/next-cube.c | 116 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 109 insertions(+), 7 deletions(-)

diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c
index 4ab9a5ec98..50f2cd0c61 100644
--- a/hw/m68k/next-cube.c
+++ b/hw/m68k/next-cube.c
@@ -90,10 +90,13 @@ struct NeXTPC {
 
     uint32_t scr1;
     uint32_t scr2;
-    uint8_t scsi_csr_1;
-    uint8_t scsi_csr_2;
     uint32_t int_mask;
     uint32_t int_status;
+    uint8_t scsi_csr_1;
+    uint8_t scsi_csr_2;
+
+    qemu_irq scsi_reset;
+    qemu_irq scsi_dma;
 
     NextRtc rtc;
 };
@@ -466,7 +469,7 @@ static void scr_writeb(NeXTPC *s, hwaddr addr, uint32_t value)
             DPRINTF("SCSICSR FIFO Flush\n");
             /* will have to add another irq to the esp if this is needed */
             /* esp_puflush_fifo(esp_g); */
-            /* qemu_irq_pulse(s->scsi_dma); */
+            qemu_irq_pulse(s->scsi_dma);
         }
 
         if (value & SCSICSR_ENABLE) {
@@ -486,9 +489,9 @@ static void scr_writeb(NeXTPC *s, hwaddr addr, uint32_t value)
         if (value & SCSICSR_RESET) {
             DPRINTF("SCSICSR Reset\n");
             /* I think this should set DMADIR. CPUDMA and INTMASK to 0 */
-            /* qemu_irq_raise(s->scsi_reset); */
-            /* s->scsi_csr_1 &= ~(SCSICSR_INTMASK |0x80|0x1); */
-
+            qemu_irq_raise(s->scsi_reset);
+            s->scsi_csr_1 &= ~(SCSICSR_INTMASK |0x80|0x1);
+            qemu_irq_lower(s->scsi_reset);
         }
         if (value & SCSICSR_DMADIR) {
             DPRINTF("SCSICSR DMAdir\n");
@@ -496,10 +499,11 @@ static void scr_writeb(NeXTPC *s, hwaddr addr, uint32_t value)
         if (value & SCSICSR_CPUDMA) {
             DPRINTF("SCSICSR CPUDMA\n");
             /* qemu_irq_raise(s->scsi_dma); */
-
             s->int_status |= 0x4000000;
         } else {
+            /* fprintf(stderr,"SCSICSR CPUDMA disabled\n"); */
             s->int_status &= ~(0x4000000);
+            /* qemu_irq_lower(s->scsi_dma); */
         }
         if (value & SCSICSR_INTMASK) {
             DPRINTF("SCSICSR INTMASK\n");
@@ -828,6 +832,102 @@ static void next_irq(void *opaque, int number, int level)
     }
 }
 
+static void nextdma_write(void *opaque, uint8_t *buf, int size, int type)
+{
+    uint32_t base_addr;
+    int irq = 0;
+    uint8_t align = 16;
+    NeXTState *next_state = NEXT_MACHINE(qdev_get_machine());
+
+    if (type == NEXTDMA_ENRX || type == NEXTDMA_ENTX) {
+        align = 32;
+    }
+    /* Most DMA is supposedly 16 byte aligned */
+    if ((size % align) != 0) {
+        size -= size % align;
+        size += align;
+    }
+
+    /*
+     * prom sets the dma start using initbuf while the bootloader uses next
+     * so we check to see if initbuf is 0
+     */
+    if (next_state->dma[type].next_initbuf == 0) {
+        base_addr = next_state->dma[type].next;
+    } else {
+        base_addr = next_state->dma[type].next_initbuf;
+    }
+
+    cpu_physical_memory_write(base_addr, buf, size);
+
+    next_state->dma[type].next_initbuf = 0;
+
+    /* saved limit is checked to calculate packet size
+        by both the rom and netbsd */
+    next_state->dma[type].saved_limit = (next_state->dma[type].next + size);
+    next_state->dma[type].saved_next  = (next_state->dma[type].next);
+
+    /*32 bytes under savedbase seems to be some kind of register
+    of which the purpose is unknown as of yet*/
+    //stl_phys(s->rx_dma.base-32,0xFFFFFFFF);
+
+    if (!(next_state->dma[type].csr & DMA_SUPDATE)) {
+        next_state->dma[type].next  = next_state->dma[type].start;
+        next_state->dma[type].limit = next_state->dma[type].stop;
+    }
+
+    /* Set dma registers and raise an irq */
+    next_state->dma[type].csr |= DMA_COMPLETE; /* DON'T CHANGE THIS! */
+
+    switch (type) {
+    case NEXTDMA_SCSI:
+        irq = NEXT_SCSI_DMA_I;
+        break;
+    }
+
+    next_irq(opaque, irq, 1);
+    next_irq(opaque, irq, 0);
+}
+
+static void nextscsi_read(void *opaque, uint8_t *buf, int len)
+{
+    DPRINTF("SCSI READ: %x\n", len);
+    abort();
+}
+
+static void nextscsi_write(void *opaque, uint8_t *buf, int size)
+{
+    DPRINTF("SCSI WRITE: %i\n", size);
+    nextdma_write(opaque, buf, size, NEXTDMA_SCSI);
+}
+
+static void next_scsi_init(DeviceState *pcdev, M68kCPU *cpu)
+{
+    struct NeXTPC *next_pc = NEXT_PC(pcdev);
+    DeviceState *dev;
+    SysBusDevice *sysbusdev;
+    SysBusESPState *sysbus_esp;
+    ESPState *esp;
+
+    dev = qdev_new(TYPE_SYSBUS_ESP);
+    sysbus_esp = SYSBUS_ESP(dev);
+    esp = &sysbus_esp->esp;
+    esp->dma_memory_read = nextscsi_read;
+    esp->dma_memory_write = nextscsi_write;
+    esp->dma_opaque = pcdev;
+    sysbus_esp->it_shift = 0;
+    esp->dma_enabled = 1;
+    sysbusdev = SYS_BUS_DEVICE(dev);
+    sysbus_realize_and_unref(sysbusdev, &error_fatal);
+    sysbus_connect_irq(sysbusdev, 0, qdev_get_gpio_in(pcdev, NEXT_SCSI_I));
+    sysbus_mmio_map(sysbusdev, 0, 0x2114000);
+
+    next_pc->scsi_reset = qdev_get_gpio_in(dev, 0);
+    next_pc->scsi_dma = qdev_get_gpio_in(dev, 1);
+
+    scsi_bus_legacy_handle_cmdline(&esp->bus);
+}
+
 static void next_escc_init(DeviceState *pcdev)
 {
     DeviceState *dev;
@@ -1026,6 +1126,7 @@ static void next_cube_init(MachineState *machine)
     /* TODO: */
     /* Network */
     /* SCSI */
+    next_scsi_init(pcdev, cpu);
 
     /* DMA */
     memory_region_init_io(dmamem, NULL, &dma_ops, machine, "next.dma", 0x5000);
@@ -1038,6 +1139,7 @@ static void next_machine_class_init(ObjectClass *oc, void *data)
 
     mc->desc = "NeXT Cube";
     mc->init = next_cube_init;
+    mc->block_default_type = IF_SCSI;
     mc->default_ram_size = RAM_SIZE;
     mc->default_ram_id = "next.ram";
     mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] hw/m68k/next-cube: Remove unused NEXTDMA_EN code
  2023-09-30 13:23 [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Thomas Huth
                   ` (2 preceding siblings ...)
  2023-09-30 13:23 ` [PATCH 3/5] m68k: Instantiate the ESP SCSI controller for the NeXTcube machine Thomas Huth
@ 2023-09-30 13:23 ` Thomas Huth
  2023-09-30 13:23 ` [PATCH 5/5] m68k: Add NeXTcube network controller Thomas Huth
  2023-10-04  9:11 ` [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Mark Cave-Ayland
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Huth @ 2023-09-30 13:23 UTC (permalink / raw)
  To: qemu-devel, Mark Cave-Ayland; +Cc: Laurent Vivier

The network code should reside in a separate file, so remove the
related handlers from next-cube.c.

Signed-off-by: Thomas Huth <huth@tuxfamily.org>
---
 hw/m68k/next-cube.c | 42 ------------------------------------------
 1 file changed, 42 deletions(-)

diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c
index 50f2cd0c61..d9a0dca07f 100644
--- a/hw/m68k/next-cube.c
+++ b/hw/m68k/next-cube.c
@@ -589,8 +589,6 @@ static const MemoryRegionOps scr_ops = {
 
 #define NEXTDMA_SCSI(x)      (0x10 + x)
 #define NEXTDMA_FD(x)        (0x10 + x)
-#define NEXTDMA_ENTX(x)      (0x110 + x)
-#define NEXTDMA_ENRX(x)      (0x150 + x)
 #define NEXTDMA_CSR          0x0
 #define NEXTDMA_NEXT         0x4000
 #define NEXTDMA_LIMIT        0x4004
@@ -605,37 +603,6 @@ static void dma_writel(void *opaque, hwaddr addr, uint64_t value,
     NeXTState *next_state = NEXT_MACHINE(opaque);
 
     switch (addr) {
-    case NEXTDMA_ENRX(NEXTDMA_CSR):
-        if (value & DMA_DEV2M) {
-            next_state->dma[NEXTDMA_ENRX].csr |= DMA_DEV2M;
-        }
-
-        if (value & DMA_SETENABLE) {
-            /* DPRINTF("SCSI DMA ENABLE\n"); */
-            next_state->dma[NEXTDMA_ENRX].csr |= DMA_ENABLE;
-        }
-        if (value & DMA_SETSUPDATE) {
-            next_state->dma[NEXTDMA_ENRX].csr |= DMA_SUPDATE;
-        }
-        if (value & DMA_CLRCOMPLETE) {
-            next_state->dma[NEXTDMA_ENRX].csr &= ~DMA_COMPLETE;
-        }
-
-        if (value & DMA_RESET) {
-            next_state->dma[NEXTDMA_ENRX].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
-                                                  DMA_ENABLE | DMA_DEV2M);
-        }
-        /* DPRINTF("RXCSR \tWrite: %x\n",value); */
-        break;
-    case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
-        next_state->dma[NEXTDMA_ENRX].next_initbuf = value;
-        break;
-    case NEXTDMA_ENRX(NEXTDMA_NEXT):
-        next_state->dma[NEXTDMA_ENRX].next = value;
-        break;
-    case NEXTDMA_ENRX(NEXTDMA_LIMIT):
-        next_state->dma[NEXTDMA_ENRX].limit = value;
-        break;
     case NEXTDMA_SCSI(NEXTDMA_CSR):
         if (value & DMA_DEV2M) {
             next_state->dma[NEXTDMA_SCSI].csr |= DMA_DEV2M;
@@ -692,15 +659,6 @@ static uint64_t dma_readl(void *opaque, hwaddr addr, unsigned int size)
     case NEXTDMA_SCSI(NEXTDMA_CSR):
         DPRINTF("SCSI DMA CSR READ\n");
         return next_state->dma[NEXTDMA_SCSI].csr;
-    case NEXTDMA_ENRX(NEXTDMA_CSR):
-        return next_state->dma[NEXTDMA_ENRX].csr;
-    case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
-        return next_state->dma[NEXTDMA_ENRX].next_initbuf;
-    case NEXTDMA_ENRX(NEXTDMA_NEXT):
-        return next_state->dma[NEXTDMA_ENRX].next;
-    case NEXTDMA_ENRX(NEXTDMA_LIMIT):
-        return next_state->dma[NEXTDMA_ENRX].limit;
-
     case NEXTDMA_SCSI(NEXTDMA_NEXT):
         return next_state->dma[NEXTDMA_SCSI].next;
     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] m68k: Add NeXTcube network controller
  2023-09-30 13:23 [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Thomas Huth
                   ` (3 preceding siblings ...)
  2023-09-30 13:23 ` [PATCH 4/5] hw/m68k/next-cube: Remove unused NEXTDMA_EN code Thomas Huth
@ 2023-09-30 13:23 ` Thomas Huth
  2023-10-04  9:11 ` [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Mark Cave-Ayland
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Huth @ 2023-09-30 13:23 UTC (permalink / raw)
  To: qemu-devel, Mark Cave-Ayland; +Cc: Laurent Vivier

The device is based on Bryce's code from GSoC 2011 that can be found here:

 https://github.com/blanham/qemu-NeXT/blob/next-cube/hw/next-net.c

The network boot unfortunately does not work yet (the firmware
successfully can send out packets, but still have problems receiving
the answer of the BOOTP server), but the code is also required to
avoid that the firmware hangs or crashes during its selftest, so it
makes sense to include this in the current shape already.

Signed-off-by: Thomas Huth <huth@tuxfamily.org>
---
 hw/m68k/next-cube.c         |  32 ++-
 hw/net/meson.build          |   1 +
 hw/net/next-net.c           | 538 ++++++++++++++++++++++++++++++++++++
 include/hw/m68k/next-cube.h |  10 +
 4 files changed, 579 insertions(+), 2 deletions(-)
 create mode 100644 hw/net/next-net.c

diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c
index d9a0dca07f..bd12007a9f 100644
--- a/hw/m68k/next-cube.c
+++ b/hw/m68k/next-cube.c
@@ -28,6 +28,7 @@
 #include "ui/console.h"
 #include "target/m68k/cpu.h"
 #include "migration/vmstate.h"
+#include "net/net.h"
 
 /* #define DEBUG_NEXT */
 #ifdef DEBUG_NEXT
@@ -908,6 +909,32 @@ static void next_escc_init(DeviceState *pcdev)
     sysbus_mmio_map(s, 0, 0x2118000);
 }
 
+static void nextnet_init(DeviceState *pcdev)
+{
+    DeviceState *dev;
+    SysBusDevice *sbd;
+    NICInfo *ni = &nd_table[0];
+    int i;
+
+    dev = qdev_new(TYPE_NEXT_NET);
+    if (ni->used) {
+        qemu_check_nic_model(ni, TYPE_NEXT_NET);
+        qdev_set_nic_properties(dev, ni);
+    }
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+    sbd = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(sbd, 0, 0x02000110);
+    sysbus_mmio_map(sbd, 1, 0x02004100);
+    sysbus_mmio_map(sbd, 2, 0x02004310);
+    sysbus_mmio_map(sbd, 3, 0x02106000);
+
+    /* Set up TX/RX and DMA irqs */
+    for (i = 0; i < NEXTNET_NUM_IRQS; i++) {
+        sysbus_connect_irq(sbd, i, qdev_get_gpio_in(pcdev, NEXTNET_TX_I_DMA +i));
+    }
+}
+
 static void next_pc_reset(DeviceState *dev)
 {
     NeXTPC *s = NEXT_PC(dev);
@@ -1081,14 +1108,15 @@ static void next_cube_init(MachineState *machine)
     /* Serial */
     next_escc_init(pcdev);
 
-    /* TODO: */
-    /* Network */
     /* SCSI */
     next_scsi_init(pcdev, cpu);
 
     /* DMA */
     memory_region_init_io(dmamem, NULL, &dma_ops, machine, "next.dma", 0x5000);
     memory_region_add_subregion(sysmem, 0x02000000, dmamem);
+
+    /* Network */
+    nextnet_init(pcdev);
 }
 
 static void next_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/net/meson.build b/hw/net/meson.build
index 2632634df3..8812d62f34 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -42,6 +42,7 @@ system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
 
 system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
 system_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
+system_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-net.c'))
 specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_llan.c'))
 system_ss.add(when: 'CONFIG_XILINX_ETHLITE', if_true: files('xilinx_ethlite.c'))
 
diff --git a/hw/net/next-net.c b/hw/net/next-net.c
new file mode 100644
index 0000000000..67a7bf580b
--- /dev/null
+++ b/hw/net/next-net.c
@@ -0,0 +1,538 @@
+/*
+ * QEMU NeXT Network (MB8795) emulation
+ *
+ * Copyright (c) 2011 Bryce Lanham
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/irq.h"
+#include "hw/m68k/next-cube.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-properties.h"
+#include "net/net.h"
+
+/* debug NeXT ethernet */
+// #define DEBUG_NET
+
+#ifdef DEBUG_NET
+#define DPRINTF(fmt, ...) \
+    do { printf("NET: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+/* names could be better */
+typedef struct NextDMA {
+    uint32_t csr;
+    uint32_t savedbase;
+    uint32_t savedlimit;
+
+    uint32_t baser;
+    uint32_t base;
+    uint32_t limit;
+    uint32_t chainbase;
+    uint32_t chainlimit;
+    uint32_t basew;
+} NextDMA;
+
+typedef struct NextNetState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mr[4];
+    qemu_irq irq[NEXTNET_NUM_IRQS];
+    uint8_t mac[6];
+
+    NICState *nic;
+    NICConf conf;
+
+    NextDMA tx_dma;
+    uint8_t tx_stat;
+    uint8_t tx_mask;
+    uint8_t tx_mode;
+
+    NextDMA rx_dma;
+    uint8_t rx_stat;
+    uint8_t rx_mask;
+    uint8_t rx_mode;
+
+    uint8_t rst_mode;
+} NextNetState;
+
+#define NEXT_NET(obj) OBJECT_CHECK(NextNetState, (obj), TYPE_NEXT_NET)
+
+static ssize_t nextnet_rx(NetClientState *nc, const uint8_t *buf, size_t size);
+
+
+static uint64_t nextnet_mmio_rd_dma(void *opaque, hwaddr addr, unsigned size)
+{
+    NextNetState *s = (NextNetState *)opaque;
+
+    g_assert(size == 4);
+
+    addr += 0x110;
+    switch (addr) {
+    case 0x110:
+        DPRINTF("TXCSR Read\n");
+        return s->tx_dma.csr;
+    case 0x150:
+        DPRINTF("RXCSR Read %x\n", s->rx_dma.csr);
+        return s->rx_dma.csr;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static void nextnet_mmio_wr_dma(void *opaque, hwaddr addr, uint64_t value,
+                                unsigned size)
+{
+    NextNetState *s = (NextNetState *)opaque;
+
+    g_assert(size == 4);
+
+    addr += 0x110;
+    switch (addr) {
+    case 0x110:
+        if (value & DMA_SETENABLE) {
+            size_t len = (0xFFFFFFF & s->tx_dma.limit) - s->tx_dma.base;
+            uint8_t buf[len]; /* needs to be in dma struct? */
+
+            DPRINTF("TXDMA ENABLE: %x len: %zu\n", s->tx_dma.base, len);
+            cpu_physical_memory_read(s->tx_dma.base, buf, len);
+
+            qemu_send_packet(qemu_get_queue(s->nic), buf, len);
+            s->tx_dma.csr |= DMA_COMPLETE | DMA_SUPDATE;
+            s->tx_stat = 0x80;
+
+            qemu_set_irq(s->irq[NEXTNET_TX_I_DMA], true);
+        }
+        if (value & DMA_SETSUPDATE) {
+            s->tx_dma.csr |= DMA_SUPDATE;
+        }
+        if (value & DMA_CLRCOMPLETE) {
+            s->tx_dma.csr &= ~DMA_COMPLETE;
+            qemu_set_irq(s->irq[NEXTNET_TX_I_DMA], false); /* TODO: OK here? */
+        }
+        if (value & DMA_RESET) {
+            s->tx_dma.csr &= ~(DMA_COMPLETE | DMA_SUPDATE | DMA_ENABLE);
+        }
+        break;
+
+    case 0x150:
+        if (value & DMA_DEV2M) {
+            DPRINTF("RX Dev to Memory\n");
+        }
+
+        if (value & DMA_SETENABLE) {
+            s->rx_dma.csr |= DMA_ENABLE;
+        }
+        if (value & DMA_SETSUPDATE) {
+            s->rx_dma.csr |= DMA_SUPDATE;
+        }
+
+        if (value & DMA_CLRCOMPLETE) {
+            s->rx_dma.csr &= ~DMA_COMPLETE;
+            qemu_set_irq(s->irq[NEXTNET_RX_I_DMA], false); /* TODO: OK here? */
+        }
+        if (value & DMA_RESET) {
+            s->rx_dma.csr &= ~(DMA_COMPLETE | DMA_SUPDATE | DMA_ENABLE);
+        }
+
+        DPRINTF("RXCSR \tWrite: %"HWADDR_PRIx"\n", value);
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static const MemoryRegionOps nextnet_mmio_ops_dma = {
+    .read = nextnet_mmio_rd_dma,
+    .write = nextnet_mmio_wr_dma,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t nextnet_mmio_rd_chan1(void *opaque, hwaddr addr, unsigned size)
+{
+    NextNetState *s = (NextNetState *)opaque;
+
+    g_assert(size == 4);
+
+    addr += 0x4100;
+    switch (addr) {
+    case 0x4100:
+        DPRINTF("SAVEDBASE Read\n");
+        return s->tx_dma.savedbase;
+    case 0x4104:
+        DPRINTF("SAVELIMIT Read\n");
+        return s->tx_dma.savedlimit;
+    case 0x4114:
+        DPRINTF("TXLIMIT Read\n");
+        return s->tx_dma.limit;
+    case 0x4140:
+        return s->rx_dma.savedbase;
+    case 0x4144:
+        // DPRINTF("SAVELIMIT %x @ %x\n",s->rx_dma.savedlimit, s->pc);
+        return s->rx_dma.savedlimit;
+    default:
+        DPRINTF("NET Read l @ %x\n", (unsigned int)addr);
+        return 0;
+    }
+}
+
+static void nextnet_mmio_wr_chan1(void *opaque, hwaddr addr, uint64_t val,
+                                  unsigned size)
+{
+    NextNetState *s = (NextNetState *)opaque;
+    uint32_t value = val;
+
+    g_assert(size == 4);
+
+    addr += 0x4100;
+    switch (addr) {
+    case 0x4100:
+        DPRINTF("Write l @ %x with %x\n", (unsigned int)addr, value);
+        s->tx_dma.savedbase = value;
+        break;
+    case 0x4104:
+        DPRINTF("Write l @ %x with %x\n", (unsigned int)addr, value);
+        s->tx_dma.savedlimit = value;
+        break;
+    case 0x4110:
+        DPRINTF("Write l @ %x with %x\n", (unsigned int)addr, value);
+        s->tx_dma.base = value;
+        break;
+    case 0x4114:
+        DPRINTF("Write l @ %x with %x\n", (unsigned int)addr, value);
+        s->tx_dma.limit = value;
+        break;
+    case 0x4150:
+        // DPRINTF("Write l @ %x with %x\n",addr,value);
+        s->rx_dma.base = value;
+        // s->rx_dma.savedbase = value;
+        break;
+    case 0x4154:
+        s->rx_dma.limit = value;
+        // DPRINTF("Write l @ %x with %x\n",addr,value);
+        break;
+    case 0x4158:
+        s->rx_dma.chainbase = value;
+        // DPRINTF("Write l @ %x with %x\n",addr,value);
+        break;
+    case 0x415c:
+        s->rx_dma.chainlimit = value;
+        // DPRINTF("Write l @ %x with %x\n",addr,value);
+        //DPRINTF("Pointer write %x w %x\n",addr,value);
+        break;
+    default:
+        DPRINTF("Write l @ %x with %x\n", (unsigned int)addr, value);
+    }
+}
+
+static const MemoryRegionOps nextnet_mmio_ops_chan1 = {
+    .read = nextnet_mmio_rd_chan1,
+    .write = nextnet_mmio_wr_chan1,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t nextnet_mmio_rd_chan2(void *opaque, hwaddr addr, unsigned size)
+{
+    NextNetState *s = (NextNetState *)opaque;
+
+    g_assert(size == 4);
+
+    addr += 0x4310;
+    switch (addr) {
+    case 0x4310:
+        DPRINTF("TXBASE Read\n");
+        /* FUTURE :return nextdma_read(device, addr); */
+        return s->tx_dma.basew;
+    default:
+        DPRINTF("NET Read l @ %x\n", (unsigned int)addr);
+        return 0;
+    }
+}
+
+static void nextnet_mmio_wr_chan2(void *opaque, hwaddr addr, uint64_t val,
+                                  unsigned size)
+{
+    NextNetState *s = (NextNetState *)opaque;
+
+    g_assert(size == 4);
+
+    addr += 0x4310;
+    switch (addr) {
+    case 0x4310:
+        DPRINTF("Write l @ %x with %"HWADDR_PRIx"\n", (unsigned int)addr, val);
+        s->tx_dma.base = val;
+        /* FUTURE :nextdma_write(device, addr, value); */
+        break;
+    default:
+        DPRINTF("Write l @ %x with %"HWADDR_PRIx"\n", (unsigned int)addr, val);
+    }
+}
+
+static const MemoryRegionOps nextnet_mmio_ops_chan2 = {
+    .read = nextnet_mmio_rd_chan2,
+    .write = nextnet_mmio_wr_chan2,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+/* It's likely that all register reads are bytes, while all CSR r/w are longs */
+static uint64_t nextnet_mmio_rd_cnf(void *opaque, hwaddr addr, unsigned size)
+{
+    NextNetState *s = (NextNetState *)opaque;
+
+    g_assert(size == 1);
+
+    addr += 0x6000;
+
+    switch (addr) {
+    case 0x6000: /* TXSTAT */
+        DPRINTF("TXSTAT \tRead\n");
+        return s->tx_stat;
+    case 0x6001:
+        DPRINTF("TXMASK \tRead\n");
+        return s->tx_mask;
+    case 0x6002:
+        DPRINTF("RXSTAT \tRead %x\n", s->rx_stat);
+        return s->rx_stat;
+    case 0x6003:
+        // DPRINTF("RXMASK \tRead\n");
+        return s->rx_mask;
+    case 0x6004:
+        DPRINTF("TXMODE \tRead\n");
+        return s->tx_mode;
+    case 0x6005:
+        // DPRINTF("RXMODE \tRead\n");
+        return s->rx_mode;
+    case 0x6006:
+        DPRINTF("RSTMODE \tRead\n");
+        return s->rst_mode;
+    default:
+        DPRINTF("NET Read B @ %x\n", (unsigned int)addr);
+        return 0;
+    }
+}
+
+#define NET_TXSTAT_CLEAR 0xFF
+#define NET_RXSTAT_CLEAR 0xFF
+static void nextnet_mmio_wr_cnf(void *opaque, hwaddr addr, uint64_t val,
+                                unsigned size)
+{
+    NextNetState *s = (NextNetState *)opaque;
+    uint32_t value = val;
+
+    g_assert(size == 1);
+
+    addr += 0x6000;
+
+    switch (addr) {
+    case 0x6000:
+        DPRINTF("TXSTAT \tWrite: %x\n", value);
+        if (value == NET_TXSTAT_CLEAR) {
+            s->tx_stat = 0x80;
+        } else {
+            s->tx_stat = value;
+        }
+        break;
+    case 0x6001:
+        DPRINTF("TXMASK \tWrite: %x\n", value);
+        s->tx_mask = value;
+        break;
+    case 0x6002:
+        // DPRINTF("RXSTAT \tWrite: %x\n", value);
+        if (value == NET_RXSTAT_CLEAR) {
+            s->rx_stat = 0x80;
+        } else {
+            s->rx_stat = value;
+        }
+        break;
+    case 0x6003:
+        // DPRINTF("RXMASK \tWrite: %x\n", value);
+        s->rx_mask = value;
+        break;
+    case 0x6004:
+        DPRINTF("TXMODE \tWrite: %x\n", value);
+        s->tx_mode = value;
+        break;
+    case 0x6005:
+        // DPRINTF("RXMODE \tWrite: %x\n", value);
+        s->rx_mode = value;
+        break;
+    case 0x6006:
+        DPRINTF("RSTMODE \tWrite: %x\n", value);
+        s->rst_mode = value;
+        break;
+    case 0x600d:
+        s->mac[(addr & 0xF) - 8] = value;
+        DPRINTF("Set MAC ADDR %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", s->mac[0],
+                s->mac[1], s->mac[2], s->mac[3], s->mac[4], s->mac[5]);
+        qemu_macaddr_default_if_unset((MACAddr *)&s->mac);
+        break;
+    case 0x6008:
+    case 0x6009:
+    case 0x600a:
+    case 0x600b:
+    case 0x600c:
+        s->mac[(addr & 0xF) - 8] = value;
+        break;
+    case 0x6010:
+    case 0x6011:
+    case 0x6012:
+    case 0x6013:
+    case 0x6014:
+        break;
+    default:
+        DPRINTF(" Write B @ %x with %x\n", (unsigned int)addr, value);
+        g_assert_not_reached();
+    }
+}
+
+static const MemoryRegionOps nextnet_mmio_ops_cnf = {
+    .read = nextnet_mmio_rd_cnf,
+    .write = nextnet_mmio_wr_cnf,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static bool nextnet_can_rx(NetClientState *nc)
+{
+    NextNetState *s = qemu_get_nic_opaque(nc);
+
+    return (s->rx_mode & 0x3) != 0;
+}
+
+static ssize_t nextnet_rx(NetClientState *nc, const uint8_t *buf, size_t size)
+{
+    NextNetState *s = qemu_get_nic_opaque(nc);
+
+    DPRINTF("received packet %zu\n", size);
+
+    /* Ethernet DMA is supposedly 32 byte aligned */
+    if ((size % 32) != 0) {
+        size -= size % 32;
+        size += 32;
+    }
+
+    /* Write the packet into memory */
+    cpu_physical_memory_write(s->rx_dma.base, buf, size);
+
+    /*
+     * Saved limit is checked to calculate packet size by both the rom
+     * and netbsd
+     */
+    s->rx_dma.savedlimit = (s->rx_dma.base + size);
+    s->rx_dma.savedbase = (s->rx_dma.base);
+
+    /*
+     * 32 bytes under savedbase seems to be some kind of register
+     * of which the purpose is unknown as of yet
+     */
+    //stl_phys(s->rx_dma.base-32, 0xFFFFFFFF);
+
+    if ((s->rx_dma.csr & DMA_SUPDATE)) {
+        s->rx_dma.base = s->rx_dma.chainbase;
+        s->rx_dma.limit = s->rx_dma.chainlimit;
+    }
+    /* we received a packet */
+    s->rx_stat = 0x80;
+
+    /* Set dma registers and raise an irq */
+    s->rx_dma.csr |= DMA_COMPLETE; /* DON'T CHANGE THIS! */
+    qemu_set_irq(s->irq[NEXTNET_RX_I_DMA], true);
+
+    return size;
+}
+
+static NetClientInfo nextnet_info = {
+    .type = NET_CLIENT_DRIVER_NIC,
+    .size = sizeof(NICState),
+    .receive = nextnet_rx,
+    .can_receive = nextnet_can_rx,
+    .receive = nextnet_rx,
+};
+
+static void nextnet_realize(DeviceState *dev, Error **errp)
+{
+    NextNetState *s = NEXT_NET(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    uint8_t mac[6] = { 0x00, 0x00, 0x0f, 0x00, 0xf3, 0x02 };
+    int i;
+
+    memcpy(&s->mac, mac, 6);  
+    s->nic = qemu_new_nic(&nextnet_info, &s->conf, "NeXT MB8795", dev->id, s);
+    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->mac);
+
+    /* Init device register spaces */
+    memory_region_init_io(&s->mr[0], NULL, &nextnet_mmio_ops_dma, s,
+                          "next.net.dma", 0x60);
+    sysbus_init_mmio(sbd, &s->mr[0]);
+    memory_region_init_io(&s->mr[1], NULL, &nextnet_mmio_ops_chan1, s,
+                          "next.net.chan1", 0x80);
+    sysbus_init_mmio(sbd, &s->mr[1]);
+    memory_region_init_io(&s->mr[2], NULL, &nextnet_mmio_ops_chan2, s,
+                          "next.net.chan2", 0x60);
+    sysbus_init_mmio(sbd, &s->mr[2]);
+    memory_region_init_io(&s->mr[3], NULL, &nextnet_mmio_ops_cnf, s,
+                          "next.net.cnf", 0x20);
+    sysbus_init_mmio(sbd, &s->mr[3]);
+
+    for (i = 0; i < NEXTNET_NUM_IRQS; i++) {
+        sysbus_init_irq(sbd, &s->irq[i]);
+    }
+}
+
+static Property nextnet_properties[] = {
+    DEFINE_NIC_PROPERTIES(NextNetState, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void nextnet_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
+    dc->realize = nextnet_realize;
+    dc->desc = "NeXT Ethernet Controller";
+    device_class_set_props(dc, nextnet_properties);
+}
+
+static const TypeInfo nextnet_typeinfo = {
+    .name          = TYPE_NEXT_NET,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(NextNetState),
+    .class_init    = nextnet_class_init,
+};
+
+static void nextnet_register_types(void)
+{
+    type_register_static(&nextnet_typeinfo);
+}
+
+type_init(nextnet_register_types)
diff --git a/include/hw/m68k/next-cube.h b/include/hw/m68k/next-cube.h
index 43577282d1..710b90e4b2 100644
--- a/include/hw/m68k/next-cube.h
+++ b/include/hw/m68k/next-cube.h
@@ -16,6 +16,16 @@
 
 #define TYPE_NEXTKBD "next-kbd"
 
+#define TYPE_NEXT_NET "next-net"
+
+enum nextnet_irqs {
+    NEXTNET_TX_I_DMA,
+    NEXTNET_RX_I_DMA,
+    NEXTNET_TX_I,
+    NEXTNET_RX_I,
+    NEXTNET_NUM_IRQS
+};
+
 enum next_dma_chan {
     NEXTDMA_FD,
     NEXTDMA_ENRX,
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine
  2023-09-30 13:23 [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Thomas Huth
                   ` (4 preceding siblings ...)
  2023-09-30 13:23 ` [PATCH 5/5] m68k: Add NeXTcube network controller Thomas Huth
@ 2023-10-04  9:11 ` Mark Cave-Ayland
  5 siblings, 0 replies; 7+ messages in thread
From: Mark Cave-Ayland @ 2023-10-04  9:11 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel; +Cc: Laurent Vivier

On 30/09/2023 14:23, Thomas Huth wrote:

> Mark Cave-Ayland recently asked me about the ESP patches for the
> next-cube machine that I once posted a long time ago, but never
> got it merged (since Mark is currently working on improving the
> ESP device). With his help, I dusted off the ESP patch, but we
> had to discover that the firmware also wants to see the NIC
> device in the MMIO region, otherwise it often crashes or hangs.
> So here's now the current set of patches for the next-cube machine.
> Both, the ESP SCSI controller and the NIC do not properly work
> yet, but at least the next-cube firmware gets much further now
> during it selftest, so I think this is a good base for future
> work and experiments.
> 
> Thomas Huth (5):
>    hw/m68k/next-cube: Mirror BIOS to address 0
>    hw/scsi/esp: Work around problem with PIO data read for the NeXT-Cube
>      machine
>    m68k: Instantiate the ESP SCSI controller for the NeXTcube machine
>    hw/m68k/next-cube: Remove unused NEXTDMA_EN code
>    m68k: Add NeXTcube network controller
> 
>   hw/m68k/next-cube.c         | 194 +++++++++----
>   hw/net/meson.build          |   1 +
>   hw/net/next-net.c           | 538 ++++++++++++++++++++++++++++++++++++
>   hw/scsi/esp.c               |   2 +-
>   include/hw/m68k/next-cube.h |  10 +
>   5 files changed, 692 insertions(+), 53 deletions(-)
>   create mode 100644 hw/net/next-net.c

Thanks Thomas! So... just looking at this series (along with the existing NeXT 
files), it is obvious that the NeXT code hasn't been touched for some time. The 
problem I see with trying to bring the code in line with our current standards is 
that there are still quite a lot of experimental parts within it, so it's not always 
even clear what the correct behaviour should be without quite a bit of 
experimentation and testing.

If the plan is to keep the NeXT code and to work on it over time, then I'm inclined 
to say merge this series as-is so at least it provides test cases for hardware such 
as ESP, brings upstream up-to-date with Bryce's original work, and allow a future 
cleanup. So on this basis:

Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>


ATB,

Mark.



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-10-04  9:14 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-30 13:23 [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Thomas Huth
2023-09-30 13:23 ` [PATCH 1/5] hw/m68k/next-cube: Mirror BIOS to address 0 Thomas Huth
2023-09-30 13:23 ` [PATCH 2/5] hw/scsi/esp: Work around problem with PIO data read for the NeXT-Cube machine Thomas Huth
2023-09-30 13:23 ` [PATCH 3/5] m68k: Instantiate the ESP SCSI controller for the NeXTcube machine Thomas Huth
2023-09-30 13:23 ` [PATCH 4/5] hw/m68k/next-cube: Remove unused NEXTDMA_EN code Thomas Huth
2023-09-30 13:23 ` [PATCH 5/5] m68k: Add NeXTcube network controller Thomas Huth
2023-10-04  9:11 ` [PATCH 0/5] m68k: Instantiate ESP and next-net in the next-cube machine Mark Cave-Ayland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).