When running without firmware ROM using Virtual Open Firmware we need
to do some hardware initialisation and provide the device tree as the
machine firmware would normally do.

Signed-off-by: BALATON Zoltan <bala...@eik.bme.hu>
---
 MAINTAINERS              |   1 +
 hw/ppc/pegasos2.c        | 140 +++++++++++++++++++++++++++++++++------
 pc-bios/dtb/meson.build  |   1 +
 pc-bios/dtb/pegasos1.dtb | Bin 0 -> 857 bytes
 pc-bios/dtb/pegasos1.dts | 125 ++++++++++++++++++++++++++++++++++
 5 files changed, 246 insertions(+), 21 deletions(-)
 create mode 100644 pc-bios/dtb/pegasos1.dtb
 create mode 100644 pc-bios/dtb/pegasos1.dts

diff --git a/MAINTAINERS b/MAINTAINERS
index b3f9f2680b..473ffabf22 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1595,6 +1595,7 @@ F: hw/ppc/pegasos2.c
 F: hw/pci-host/mv64361.c
 F: hw/pci-host/mv643xx.h
 F: include/hw/pci-host/mv64361.h
+F: pc-bios/dtb/pegasos[12].dt[sb]
 
 amigaone
 M: BALATON Zoltan <bala...@eik.bme.hu>
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index a88d93ae04..c9a35198e9 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -84,6 +84,7 @@ struct PegasosMachineState {
     uint64_t initrd_size;
 };
 
+static void *pegasos1_build_fdt(PegasosMachineState *pm, int *fdt_size);
 static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size);
 
 static void pegasos_cpu_reset(void *opaque)
@@ -314,6 +315,82 @@ static void pegasos_init(MachineState *machine)
     }
 }
 
+static void pegasos_superio_write(uint8_t addr, uint8_t val)
+{
+    cpu_physical_memory_write(0xfe0003f0, &addr, 1);
+    cpu_physical_memory_write(0xfe0003f1, &val, 1);
+}
+
+static void pegasos1_pci_config_write(PegasosMachineState *pm, int bus,
+                                      uint32_t addr, uint32_t len, uint32_t 
val)
+{
+    addr |= BIT(31);
+    cpu_physical_memory_write(0xfec00cf8, &addr, 4);
+    cpu_physical_memory_write(0xfee00cfc, &val, len);
+}
+
+static void pegasos1_chipset_reset(PegasosMachineState *pm)
+{
+    uint8_t elcr = 0x2e;
+    cpu_physical_memory_write(0xfe0004d1, &elcr, sizeof(elcr));
+
+    pegasos1_pci_config_write(pm, 0, PCI_COMMAND, 2, PCI_COMMAND_IO |
+                              PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x9);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+                              0x50, 1, 0x6);
+    pegasos_superio_write(0xf4, 0xbe);
+    pegasos_superio_write(0xf6, 0xef);
+    pegasos_superio_write(0xf7, 0xfc);
+    pegasos_superio_write(0xf2, 0x14);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+                              0x51, 1, 0x3d);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+                              0x55, 1, 0x90);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+                              0x56, 1, 0x99);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+                              0x57, 1, 0x90);
+
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x10e);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+                              PCI_CLASS_PROG, 1, 0xf);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+                              0x40, 1, 0xb);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+                              0x50, 4, 0x17171717);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+                              PCI_COMMAND, 2, 0x87);
+
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 2) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x409);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 2) << 8) |
+                              PCI_COMMAND, 2, 0x7);
+
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 3) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x409);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 3) << 8) |
+                              PCI_COMMAND, 2, 0x7);
+
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x9);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
+                              0x48, 4, 0x2001);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
+                              0x41, 1, 0);
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
+                              0x90, 4, 0x1000);
+
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 5) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x309);
+
+    pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 6) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x309);
+}
+
 static uint32_t pegasos2_mv_reg_read(PegasosMachineState *pm,
                                      uint32_t addr, uint32_t len)
 {
@@ -357,12 +434,6 @@ static void pegasos2_pci_config_write(PegasosMachineState 
*pm, int bus,
     pegasos2_mv_reg_write(pm, pcicfg + 4, len, val);
 }
 
-static void pegasos2_superio_write(uint8_t addr, uint8_t val)
-{
-    cpu_physical_memory_write(0xfe0003f0, &addr, 1);
-    cpu_physical_memory_write(0xfe0003f1, &val, 1);
-}
-
 static void pegasos2_chipset_reset(PegasosMachineState *pm)
 {
     pegasos2_mv_reg_write(pm, 0, 4, 0x28020ff);
@@ -379,10 +450,10 @@ static void pegasos2_chipset_reset(PegasosMachineState 
*pm)
                               PCI_INTERRUPT_LINE, 2, 0x9);
     pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
                               0x50, 1, 0x6);
-    pegasos2_superio_write(0xf4, 0xbe);
-    pegasos2_superio_write(0xf6, 0xef);
-    pegasos2_superio_write(0xf7, 0xfc);
-    pegasos2_superio_write(0xf2, 0x14);
+    pegasos_superio_write(0xf4, 0xbe);
+    pegasos_superio_write(0xf6, 0xef);
+    pegasos_superio_write(0xf7, 0xfc);
+    pegasos_superio_write(0xf2, 0x14);
     pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
                               0x50, 1, 0x2);
     pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
@@ -432,7 +503,7 @@ static void pegasos2_chipset_reset(PegasosMachineState *pm)
 static void pegasos_machine_reset(MachineState *machine, ResetType type)
 {
     PegasosMachineState *pm = PEGASOS_MACHINE(machine);
-    void *fdt;
+    void *fdt = NULL;
     uint32_t c[2];
     uint64_t d[2];
     int sz;
@@ -440,13 +511,22 @@ static void pegasos_machine_reset(MachineState *machine, 
ResetType type)
     qemu_devices_reset(type);
     if (!pm->vof) {
         return; /* Firmware should set up machine so nothing to do */
-    } else if (pm->type == PEGASOS1) {
-        error_report("VOF is not supported by this machine");
-        exit(1);
     }
 
     /* Otherwise, set up devices that board firmware would normally do */
-    pegasos2_chipset_reset(pm);
+    switch (pm->type) {
+    case PEGASOS1:
+        pegasos1_chipset_reset(pm);
+        fdt = pegasos1_build_fdt(pm, &sz);
+        break;
+    case PEGASOS2:
+        pegasos2_chipset_reset(pm);
+        fdt = pegasos2_build_fdt(pm, &sz);
+        break;
+    }
+    if (!fdt) {
+        exit(1);
+    }
 
     /* Device tree and VOF set up */
     vof_init(pm->vof, machine->ram_size, &error_fatal);
@@ -465,11 +545,6 @@ static void pegasos_machine_reset(MachineState *machine, 
ResetType type)
         exit(1);
     }
 
-    fdt = pegasos2_build_fdt(pm, &sz);
-    if (!fdt) {
-        exit(1);
-    }
-
     /* Set memory size */
     c[0] = 0;
     c[1] = cpu_to_be32(machine->ram_size);
@@ -761,6 +836,8 @@ static struct {
     const char *name;
     void (*dtf)(PCIBus *bus, PCIDevice *d, FDTInfo *fi);
 } device_map[] = {
+    { "pci10cc,660", "host", NULL },
+    { "pci10cc,661", "host", NULL },
     { "pci11ab,6460", "host", NULL },
     { "pci1106,571", "ide", dt_ide },
     { "pci1106,3044", "firewire", NULL },
@@ -846,7 +923,7 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void 
*opaque)
         qemu_fdt_setprop_cell(fi->fdt, node->str, "interrupts",
                               pci_get_byte(&d->config[PCI_INTERRUPT_PIN]));
     }
-    /* Pegasos2 firmware has subsystem-id amd subsystem-vendor-id swapped */
+    /* Pegasos firmware has subsystem-id and subsystem-vendor-id swapped */
     qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-vendor-id",
                           pci_get_word(&d->config[PCI_SUBSYSTEM_ID]));
     qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-id",
@@ -935,6 +1012,27 @@ static void *load_dtb(const char *filename, int *fdt_size)
     return fdt;
 }
 
+static void *pegasos1_build_fdt(PegasosMachineState *pm, int *fdt_size)
+{
+    FDTInfo fi;
+    PCIBus *pci_bus;
+    void *fdt = load_dtb("pegasos1.dtb", fdt_size);
+
+    if (!fdt) {
+        return NULL;
+    }
+    qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos");
+
+    add_cpu_info(fdt, pm->cpu, pm->bus_freq_hz);
+
+    fi.fdt = fdt;
+    fi.path = "/pci@80000000";
+    pci_bus = PCI_BUS(qdev_get_child_bus(pm->nb, "pci.0"));
+    pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
+
+    return fdt;
+}
+
 static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size)
 {
     FDTInfo fi;
diff --git a/pc-bios/dtb/meson.build b/pc-bios/dtb/meson.build
index cea76c0aa1..4c9504ea5b 100644
--- a/pc-bios/dtb/meson.build
+++ b/pc-bios/dtb/meson.build
@@ -1,6 +1,7 @@
 dtbs = [
   'bamboo.dtb',
   'canyonlands.dtb',
+  'pegasos1.dtb',
   'pegasos2.dtb',
   'petalogix-ml605.dtb',
   'petalogix-s3adsp1800.dtb',
diff --git a/pc-bios/dtb/pegasos1.dtb b/pc-bios/dtb/pegasos1.dtb
new file mode 100644
index 
0000000000000000000000000000000000000000..3b863b25288a59bcede9459ff42afad713dde741
GIT binary patch
literal 857
zcmZ8fO>Yx15OvxjK&T3w=^-c=RCQ5Ogp}S|g(^KkM8yI1P<g$Rbd_D(wKuI&2~qwB
z2PCfWU-%<P`~ZlU=k<oRBR$W&=lQVL`*U;oONjLkLWqG7Yv0*FXFOp%X25>1Ue)2P
zwH4Vq`;8bw1HZ>;t21Y#4($Qs>6oU{8xI*8@T`9T8sbOnw^Lh4-5HhX(Mm_{-ksVl
z)<#k543FN8J7aT6ZanN9FMLHMid)8#w$22?9P@Cm<{Ue{7yY!q`;sNG#%QTC<4J?o
zyrj~&#eOd+b^U#g+qE9l=58l32d?gA=i#Evk%Mn^%78T-ar4cvKZ`unPh?(rIUyvm
zp(f1s<Z@XAE#z61?+<#l1@(XbHt#{YIS+BeaUS$&_<8Hk*Y`L0=jCr^^*-L<<eHaH
z3^vr@g}yXD0>mX2*md1FhM>Vd@`{15zY&OI5A?*GZ_uJ49eCK4S?0+5L{U+Ak<mr2
z=(Ji`5~azg5RMg}8!d)!UmuPR-|SqF&Wu~p)JT`DSVmsC+*T-XG!<Q+Us3GcRd_p9
s7&S{Kj?U+#)j|w*U+pEiuE@E$trDqb+FTZtO-VSZr{qOC_eluFKX>nfX#fBK

literal 0
HcmV?d00001

diff --git a/pc-bios/dtb/pegasos1.dts b/pc-bios/dtb/pegasos1.dts
new file mode 100644
index 0000000000..e5ef9db866
--- /dev/null
+++ b/pc-bios/dtb/pegasos1.dts
@@ -0,0 +1,125 @@
+/*
+ * QEMU Pegasos1 Device Tree Source
+ *
+ * Copyright 2025 BALATON Zoltan
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This is partial source, more info will be filled in by board code.
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       device_type = "chrp";
+       model = "Pegasos";
+       revision = "1A";
+       CODEGEN,vendor = "bplan GmbH";
+       CODEGEN,board = "Pegasos";
+       CODEGEN,description = "Pegasos CHRP PowerPC System";
+
+       openprom {
+               model = "Pegasos,0.1b123";
+       };
+
+       chosen {
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0 0>;
+       };
+
+       cpus {
+               #size-cells     = <0>;
+               #address-cells  = <1>;
+               #cpus           = <1>;
+       };
+
+       failsafe {
+               device_type = "serial";
+       };
+
+       pci@80000000 {
+               device_type = "pci";
+               #address-cells = <3>;
+               #size-cells = <2>;
+               clock-frequency = <33333333>;
+               8259-interrupt-acknowledge = <0xfef00000>;
+               reg = <0x80000000 0x7f000000>;
+               ranges = <0x01000000 0 0x00000000 0xfe000000 0 0x00800000
+                         0x02000000 0 0x80000000 0x80000000 0 0x7d000000
+                         0x02000000 0 0xfd000000 0xfd000000 0 0x01000000>;
+               bus-range = <0 0>;
+
+               isa@7 {
+                       vendor-id       = <0x1106>;
+                       device-id       = <0x8231>;
+                       revision-id     = <0x10>;
+                       class-code      = <0x60100>;
+                       /* Pegasos firmware has subsystem-id and */
+                       /* subsystem-vendor-id swapped */
+                       subsystem-id    = <0x1af4>;
+                       subsystem-vendor-id = <0x1100>;
+                       reg = <0x3800 0 0 0 0>;
+                       device_type     = "isa";
+                       #address-cells  = <2>;
+                       #size-cells     = <1>;
+                       eisa-slots      = <0>;
+                       clock-frequency = <8333333>;
+                       slot-names      = <0>;
+
+                       serial@i2f8 {
+                               device_type     = "serial";
+                               reg             = <1 0x2f8 8>;
+                               interrupts      = <3 0>;
+                               clock-frequency = <0>;
+                       };
+
+                       8042@i60 {
+                               device_type     = "";
+                               reg             = <1 0x60 5>;
+                               clock-frequency = <0>;
+                               interrupt-controller = "";
+                               #address-cells  = <1>;
+                               #size-cells     = <0>;
+                               #interrupt-cells = <2>;
+
+                       };
+
+                       keyboard@i60 {
+                               device_type     = "keyboard";
+                               reg             = <1 0x60 5>;
+                               interrupts      = <1 0>;
+                       };
+
+                       rtc@i70 {
+                               device_type     = "rtc";
+                               reg             = <1 0x70 2>;
+                               interrupts      = <8 0>;
+                               clock-frequency = <0>;
+                               compatible      = "ds1385-rtc";
+                       };
+
+                       timer@i40 {
+                               device_type     = "timer";
+                               reg             = <1 0x40 8>;
+                               clock-frequency = <0>;
+                       };
+
+                       fdc@i3f0 {
+                               device_type     = "fdc";
+                               reg             = <1 0x3f0 8>;
+                               interrupts      = <6 0>;
+                               clock-frequency = <0>;
+                       };
+
+                       lpt@i3bc {
+                               device_type     = "lpt";
+                               reg             = <1 0x3bc 8>;
+                               interrupts      = <7 0>;
+                               clock-frequency = <0>;
+                       };
+               };
+       };
+};
-- 
2.41.3


Reply via email to