summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/arch/sparc32/openbios.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/arch/sparc32/openbios.c')
-rw-r--r--qemu/roms/openbios/arch/sparc32/openbios.c1005
1 files changed, 1005 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/sparc32/openbios.c b/qemu/roms/openbios/arch/sparc32/openbios.c
new file mode 100644
index 000000000..6f4ee454e
--- /dev/null
+++ b/qemu/roms/openbios/arch/sparc32/openbios.c
@@ -0,0 +1,1005 @@
+/* tag: openbios forth environment, executable code
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "drivers/drivers.h"
+#include "asm/types.h"
+#include "dict.h"
+#include "kernel/kernel.h"
+#include "kernel/stack.h"
+#include "arch/common/nvram.h"
+#include "packages/nvram.h"
+#include "../../drivers/timer.h" // XXX
+#include "libopenbios/sys_info.h"
+#include "openbios.h"
+#include "boot.h"
+#include "romvec.h"
+#include "openprom.h"
+#include "psr.h"
+#include "libopenbios/video.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+#include "arch/sparc32/ofmem_sparc32.h"
+
+#define MEMORY_SIZE (128*1024) /* 128K ram for hosted system */
+#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+#define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
+
+int qemu_machine_type;
+
+struct hwdef {
+ uint64_t iommu_base, slavio_base;
+ uint64_t intctl_base, counter_base, nvram_base, ms_kb_base, serial_base;
+ unsigned long fd_offset, counter_offset, intr_offset;
+ unsigned long aux1_offset, aux2_offset;
+ uint64_t dma_base, esp_base, le_base;
+ uint64_t tcx_base;
+ int intr_ncpu;
+ int mid_offset;
+ int machine_id_low, machine_id_high;
+};
+
+static const struct hwdef hwdefs[] = {
+ /* SS-5 */
+ {
+ .iommu_base = 0x10000000,
+ .tcx_base = 0x50000000,
+ .slavio_base = 0x71000000,
+ .ms_kb_base = 0x71000000,
+ .serial_base = 0x71100000,
+ .nvram_base = 0x71200000,
+ .fd_offset = 0x00400000,
+ .counter_offset = 0x00d00000,
+ .intr_offset = 0x00e00000,
+ .intr_ncpu = 1,
+ .aux1_offset = 0x00900000,
+ .aux2_offset = 0x00910000,
+ .dma_base = 0x78400000,
+ .esp_base = 0x78800000,
+ .le_base = 0x78c00000,
+ .mid_offset = 0,
+ .machine_id_low = 32,
+ .machine_id_high = 63,
+ },
+ /* SS-10, SS-20 */
+ {
+ .iommu_base = 0xfe0000000ULL,
+ .tcx_base = 0xe20000000ULL,
+ .slavio_base = 0xff1000000ULL,
+ .ms_kb_base = 0xff1000000ULL,
+ .serial_base = 0xff1100000ULL,
+ .nvram_base = 0xff1200000ULL,
+ .fd_offset = 0x00700000, // 0xff1700000ULL,
+ .counter_offset = 0x00300000, // 0xff1300000ULL,
+ .intr_offset = 0x00400000, // 0xff1400000ULL,
+ .intr_ncpu = 4,
+ .aux1_offset = 0x00800000, // 0xff1800000ULL,
+ .aux2_offset = 0x00a01000, // 0xff1a01000ULL,
+ .dma_base = 0xef0400000ULL,
+ .esp_base = 0xef0800000ULL,
+ .le_base = 0xef0c00000ULL,
+ .mid_offset = 8,
+ .machine_id_low = 64,
+ .machine_id_high = 65,
+ },
+ /* SS-600MP */
+ {
+ .iommu_base = 0xfe0000000ULL,
+ .tcx_base = 0xe20000000ULL,
+ .slavio_base = 0xff1000000ULL,
+ .ms_kb_base = 0xff1000000ULL,
+ .serial_base = 0xff1100000ULL,
+ .nvram_base = 0xff1200000ULL,
+ .fd_offset = -1,
+ .counter_offset = 0x00300000, // 0xff1300000ULL,
+ .intr_offset = 0x00400000, // 0xff1400000ULL,
+ .intr_ncpu = 4,
+ .aux1_offset = 0x00800000, // 0xff1800000ULL,
+ .aux2_offset = 0x00a01000, // 0xff1a01000ULL, XXX should not exist
+ .dma_base = 0xef0081000ULL,
+ .esp_base = 0xef0080000ULL,
+ .le_base = 0xef0060000ULL,
+ .mid_offset = 8,
+ .machine_id_low = 66,
+ .machine_id_high = 66,
+ },
+};
+
+static const struct hwdef *hwdef;
+
+void setup_timers(void)
+{
+}
+
+void udelay(unsigned int usecs)
+{
+}
+
+void mdelay(unsigned int msecs)
+{
+}
+
+static void mb86904_init(void)
+{
+ PUSH(32);
+ fword("encode-int");
+ push_str("cache-line-size");
+ fword("property");
+
+ PUSH(512);
+ fword("encode-int");
+ push_str("cache-nlines");
+ fword("property");
+
+ PUSH(0x23);
+ fword("encode-int");
+ push_str("mask_rev");
+ fword("property");
+}
+
+static void tms390z55_init(void)
+{
+ push_str("");
+ fword("encode-string");
+ push_str("ecache-parity?");
+ fword("property");
+
+ push_str("");
+ fword("encode-string");
+ push_str("bfill?");
+ fword("property");
+
+ push_str("");
+ fword("encode-string");
+ push_str("bcopy?");
+ fword("property");
+
+ push_str("");
+ fword("encode-string");
+ push_str("cache-physical?");
+ fword("property");
+
+ PUSH(0xf);
+ fword("encode-int");
+ PUSH(0xf8fffffc);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(4);
+ fword("encode-int");
+ fword("encode+");
+
+ PUSH(0xf);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0xf8c00000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x1000);
+ fword("encode-int");
+ fword("encode+");
+
+ PUSH(0xf);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0xf8000000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x1000);
+ fword("encode-int");
+ fword("encode+");
+
+ PUSH(0xf);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0xf8800000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x1000);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+}
+
+static void rt625_init(void)
+{
+ PUSH(32);
+ fword("encode-int");
+ push_str("cache-line-size");
+ fword("property");
+
+ PUSH(512);
+ fword("encode-int");
+ push_str("cache-nlines");
+ fword("property");
+
+}
+
+static void bad_cpu_init(void)
+{
+ printk("This CPU is not supported yet, freezing.\n");
+ for(;;);
+}
+
+struct cpudef {
+ unsigned long iu_version;
+ const char *name;
+ int psr_impl, psr_vers, impl, vers;
+ int dcache_line_size, dcache_lines, dcache_assoc;
+ int icache_line_size, icache_lines, icache_assoc;
+ int ecache_line_size, ecache_lines, ecache_assoc;
+ int mmu_nctx;
+ void (*initfn)(void);
+};
+
+static const struct cpudef sparc_defs[] = {
+ {
+ .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
+ .name = "FMI,MB86900",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
+ .name = "FMI,MB86904",
+ .psr_impl = 0,
+ .psr_vers = 4,
+ .impl = 0,
+ .vers = 4,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x200,
+ .dcache_assoc = 1,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x200,
+ .icache_assoc = 1,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x4000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x100,
+ .initfn = mb86904_init,
+ },
+ {
+ .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
+ .name = "FMI,MB86907",
+ .psr_impl = 0,
+ .psr_vers = 5,
+ .impl = 0,
+ .vers = 5,
+ .dcache_line_size = 0x20,
+ .dcache_lines = 0x200,
+ .dcache_assoc = 1,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x200,
+ .icache_assoc = 1,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x4000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x100,
+ .initfn = mb86904_init,
+ },
+ {
+ .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
+ .name = "LSI,L64811",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
+ .name = "CY,CY7C601",
+ .psr_impl = 1,
+ .psr_vers = 1,
+ .impl = 1,
+ .vers = 1,
+ .mmu_nctx = 0x10,
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
+ .name = "CY,CY7C611",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x40000000,
+ .name = "TI,TMS390Z55",
+ .psr_impl = 4,
+ .psr_vers = 0,
+ .impl = 0,
+ .vers = 4,
+ .dcache_line_size = 0x20,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x40,
+ .icache_lines = 0x40,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x41000000,
+ .name = "TI,TMS390S10",
+ .psr_impl = 4,
+ .psr_vers = 1,
+ .impl = 4,
+ .vers = 1,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x80,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x42000000,
+ .name = "TI,TMS390S10",
+ .psr_impl = 4,
+ .psr_vers = 2,
+ .impl = 4,
+ .vers = 2,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x80,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x43000000,
+ .name = "TI,TMS390S10",
+ .psr_impl = 4,
+ .psr_vers = 3,
+ .impl = 4,
+ .vers = 3,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x80,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x44000000,
+ .name = "TI,TMS390S10",
+ .psr_impl = 4,
+ .psr_vers = 4,
+ .impl = 4,
+ .vers = 4,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x80,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x1e000000,
+ .name = "Ross,RT625",
+ .psr_impl = 1,
+ .psr_vers = 14,
+ .impl = 1,
+ .vers = 7,
+ .dcache_line_size = 0x20,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x40,
+ .icache_lines = 0x40,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = rt625_init,
+ },
+ {
+ .iu_version = 0x1f000000,
+ .name = "Ross,RT620",
+ .psr_impl = 1,
+ .psr_vers = 15,
+ .impl = 1,
+ .vers = 7,
+ .dcache_line_size = 0x20,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x40,
+ .icache_lines = 0x40,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = rt625_init,
+ },
+ {
+ .iu_version = 0x20000000,
+ .name = "BIT,B5010",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x50000000,
+ .name = "MC,MN10501",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
+ .name = "Weitek,W8601",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0xf2000000,
+ .name = "GR,LEON2",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0xf3000000,
+ .name = "GR,LEON3",
+ .initfn = bad_cpu_init,
+ },
+};
+
+static const struct cpudef *
+id_cpu(void)
+{
+ unsigned long iu_version;
+ unsigned int i;
+
+ asm("rd %%psr, %0\n"
+ : "=r"(iu_version) :);
+ iu_version &= 0xff000000;
+
+ for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) {
+ if (iu_version == sparc_defs[i].iu_version)
+ return &sparc_defs[i];
+ }
+ printk("Unknown cpu (psr %lx), freezing!\n", iu_version);
+ for (;;);
+}
+
+static void setup_cpu(int mid_offset)
+{
+ uint32_t temp;
+ unsigned int i;
+ const struct cpudef *cpu;
+
+ // Add cpus
+ temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
+
+ printk("CPUs: %x", temp);
+ cpu = id_cpu();
+ printk(" x %s\n", cpu->name);
+ for (i = 0; i < temp; i++) {
+ push_str("/");
+ fword("find-device");
+
+ fword("new-device");
+
+ push_str(cpu->name);
+ fword("device-name");
+
+ push_str("cpu");
+ fword("device-type");
+
+ PUSH(cpu->psr_impl);
+ fword("encode-int");
+ push_str("psr-implementation");
+ fword("property");
+
+ PUSH(cpu->psr_vers);
+ fword("encode-int");
+ push_str("psr-version");
+ fword("property");
+
+ PUSH(cpu->impl);
+ fword("encode-int");
+ push_str("implementation");
+ fword("property");
+
+ PUSH(cpu->vers);
+ fword("encode-int");
+ push_str("version");
+ fword("property");
+
+ PUSH(4096);
+ fword("encode-int");
+ push_str("page-size");
+ fword("property");
+
+ PUSH(cpu->dcache_line_size);
+ fword("encode-int");
+ push_str("dcache-line-size");
+ fword("property");
+
+ PUSH(cpu->dcache_lines);
+ fword("encode-int");
+ push_str("dcache-nlines");
+ fword("property");
+
+ PUSH(cpu->dcache_assoc);
+ fword("encode-int");
+ push_str("dcache-associativity");
+ fword("property");
+
+ PUSH(cpu->icache_line_size);
+ fword("encode-int");
+ push_str("icache-line-size");
+ fword("property");
+
+ PUSH(cpu->icache_lines);
+ fword("encode-int");
+ push_str("icache-nlines");
+ fword("property");
+
+ PUSH(cpu->icache_assoc);
+ fword("encode-int");
+ push_str("icache-associativity");
+ fword("property");
+
+ PUSH(cpu->ecache_line_size);
+ fword("encode-int");
+ push_str("ecache-line-size");
+ fword("property");
+
+ PUSH(cpu->ecache_lines);
+ fword("encode-int");
+ push_str("ecache-nlines");
+ fword("property");
+
+ PUSH(cpu->ecache_assoc);
+ fword("encode-int");
+ push_str("ecache-associativity");
+ fword("property");
+
+ PUSH(2);
+ fword("encode-int");
+ push_str("ncaches");
+ fword("property");
+
+ PUSH(cpu->mmu_nctx);
+ fword("encode-int");
+ push_str("mmu-nctx");
+ fword("property");
+
+ PUSH(8);
+ fword("encode-int");
+ push_str("sparc-version");
+ fword("property");
+
+ push_str("");
+ fword("encode-string");
+ push_str("cache-coherence?");
+ fword("property");
+
+ PUSH(i + mid_offset);
+ fword("encode-int");
+ push_str("mid");
+ fword("property");
+
+ cpu->initfn();
+
+ fword("finish-device");
+ }
+}
+
+static void dummy_mach_init(uint64_t base)
+{
+}
+
+struct machdef {
+ uint16_t machine_id;
+ const char *banner_name;
+ const char *model;
+ const char *name;
+ void (*initfn)(uint64_t base);
+};
+
+static const struct machdef sun4m_defs[] = {
+ {
+ .machine_id = 32,
+ .banner_name = "SPARCstation 5",
+ .model = "SUNW,501-3059",
+ .name = "SUNW,SPARCstation-5",
+ .initfn = ss5_init,
+ },
+ {
+ .machine_id = 33,
+ .banner_name = "SPARCstation Voyager",
+ .model = "SUNW,501-2581",
+ .name = "SUNW,SPARCstation-Voyager",
+ .initfn = dummy_mach_init,
+ },
+ {
+ .machine_id = 34,
+ .banner_name = "SPARCstation LX",
+ .model = "SUNW,501-2031",
+ .name = "SUNW,SPARCstation-LX",
+ .initfn = dummy_mach_init,
+ },
+ {
+ .machine_id = 35,
+ .banner_name = "SPARCstation 4",
+ .model = "SUNW,501-2572",
+ .name = "SUNW,SPARCstation-4",
+ .initfn = ss5_init,
+ },
+ {
+ .machine_id = 36,
+ .banner_name = "SPARCstation Classic",
+ .model = "SUNW,501-2326",
+ .name = "SUNW,SPARCstation-Classic",
+ .initfn = dummy_mach_init,
+ },
+ {
+ .machine_id = 37,
+ .banner_name = "Tadpole S3 GX",
+ .model = "S3",
+ .name = "Tadpole_S3GX",
+ .initfn = ss5_init,
+ },
+ {
+ .machine_id = 64,
+ .banner_name = "SPARCstation 10 (1 X 390Z55)",
+ .model = "SUNW,S10,501-2365",
+ .name = "SUNW,SPARCstation-10",
+ .initfn = ob_eccmemctl_init,
+ },
+ {
+ .machine_id = 65,
+ .banner_name = "SPARCstation 20 (1 X 390Z55)",
+ .model = "SUNW,S20,501-2324",
+ .name = "SUNW,SPARCstation-20",
+ .initfn = ob_eccmemctl_init,
+ },
+ {
+ .machine_id = 66,
+ .banner_name = "SPARCsystem 600(1 X 390Z55)",
+ .model = NULL,
+ .name = "SUNW,SPARCsystem-600",
+ .initfn = ob_eccmemctl_init,
+ },
+};
+
+static const struct machdef *
+id_machine(uint16_t machine_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(sun4m_defs)/sizeof(struct machdef); i++) {
+ if (machine_id == sun4m_defs[i].machine_id)
+ return &sun4m_defs[i];
+ }
+ printk("Unknown machine (ID %d), freezing!\n", machine_id);
+ for (;;);
+}
+
+static void setup_machine(uint64_t base)
+{
+ uint16_t machine_id;
+ const struct machdef *mach;
+
+ machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
+ mach = id_machine(machine_id);
+
+ push_str("/");
+ fword("find-device");
+ push_str(mach->banner_name);
+ fword("encode-string");
+ push_str("banner-name");
+ fword("property");
+
+ if (mach->model) {
+ push_str(mach->model);
+ fword("encode-string");
+ push_str("model");
+ fword("property");
+ }
+ push_str(mach->name);
+ fword("encode-string");
+ push_str("name");
+ fword("property");
+
+ mach->initfn(base);
+}
+
+/* Add /uuid */
+static void setup_uuid(void)
+{
+ static uint8_t qemu_uuid[16];
+
+ fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
+
+ printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
+ qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
+ qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
+ qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
+ qemu_uuid[15]);
+
+ push_str("/");
+ fword("find-device");
+
+ PUSH((long)&qemu_uuid);
+ PUSH(16);
+ fword("encode-bytes");
+ push_str("uuid");
+ fword("property");
+}
+
+static void setup_stdio(void)
+{
+ char nographic;
+ const char *stdin, *stdout;
+
+ fw_cfg_read(FW_CFG_NOGRAPHIC, &nographic, 1);
+ if (nographic) {
+ obp_stdin = PROMDEV_TTYA;
+ obp_stdout = PROMDEV_TTYA;
+ stdin = "ttya";
+ stdout = "ttya";
+ } else {
+ obp_stdin = PROMDEV_KBD;
+ obp_stdout = PROMDEV_SCREEN;
+ stdin = "keyboard";
+ stdout = "screen";
+ }
+
+ push_str(stdin);
+ push_str("input-device");
+ fword("$setenv");
+
+ push_str(stdout);
+ push_str("output-device");
+ fword("$setenv");
+
+ obp_stdin_path = stdin;
+ obp_stdout_path = stdout;
+}
+
+static void init_memory(void)
+{
+ phys_addr_t phys;
+ ucell virt;
+
+ /* Claim the memory from OFMEM */
+ phys = ofmem_claim_phys(-1, MEMORY_SIZE, PAGE_SIZE);
+ if (!phys)
+ printk("panic: not enough physical memory on host system.\n");
+
+ virt = ofmem_claim_virt(OF_CODE_START - MEMORY_SIZE, MEMORY_SIZE, 0);
+ if (!virt)
+ printk("panic: not enough virtual memory on host system.\n");
+
+ /* Generate the mapping (and lock translation into the TLBs) */
+ ofmem_map(phys, virt, MEMORY_SIZE, ofmem_arch_default_translation_mode(phys));
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator
+ */
+
+ PUSH(virt);
+ PUSH(virt + MEMORY_SIZE);
+}
+
+static void
+arch_init( void )
+{
+ char *cmdline;
+ const char *kernel_cmdline;
+ uint32_t temp;
+ uint16_t machine_id;
+ char buf[256];
+ unsigned long mem_size;
+
+ fw_cfg_init();
+
+ fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
+ buf[4] = '\0';
+
+ printk("Configuration device id %s", buf);
+
+ temp = fw_cfg_read_i32(FW_CFG_ID);
+ machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
+
+ printk(" version %d machine id %d\n", temp, machine_id);
+
+ if (temp != 1) {
+ printk("Incompatible configuration device version, freezing\n");
+ for(;;);
+ }
+
+ graphic_depth = fw_cfg_read_i16(FW_CFG_SUN4M_DEPTH);
+
+ openbios_init();
+ modules_init();
+ ob_init_mmu();
+ ob_init_iommu(hwdef->iommu_base);
+#ifdef CONFIG_DRIVER_OBIO
+ mem_size = fw_cfg_read_i32(FW_CFG_RAM_SIZE);
+ ob_obio_init(hwdef->slavio_base, hwdef->fd_offset,
+ hwdef->counter_offset, hwdef->intr_offset, hwdef->intr_ncpu,
+ hwdef->aux1_offset, hwdef->aux2_offset,
+ mem_size);
+
+ setup_machine(hwdef->slavio_base);
+
+ nvconf_init();
+#endif
+#ifdef CONFIG_DRIVER_SBUS
+#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
+ setup_video();
+#endif
+ ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type);
+#endif
+ device_end();
+
+ setup_cpu(hwdef->mid_offset);
+
+ setup_stdio();
+ /* Initialiase openprom romvec */
+ romvec = init_openprom();
+
+ kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
+ if (kernel_size) {
+ kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
+
+ /* Mark the kernel memory as in use */
+ ofmem_claim_phys(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0);
+ ofmem_claim_virt(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0);
+ }
+
+ kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
+ if (kernel_cmdline) {
+ cmdline = strdup(kernel_cmdline);
+ obp_arg.argv[1] = cmdline;
+ } else {
+ cmdline = strdup("");
+ }
+ qemu_cmdline = (uint32_t)cmdline;
+
+ /* Setup nvram variables */
+ push_str("/options");
+ fword("find-device");
+ push_str(cmdline);
+ fword("encode-string");
+ push_str("boot-file");
+ fword("property");
+
+ boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
+
+ switch (boot_device) {
+ case 'a':
+ push_str("floppy");
+ break;
+ case 'c':
+ push_str("disk");
+ break;
+ default:
+ case 'd':
+ push_str("cdrom:d cdrom");
+ break;
+ case 'n':
+ push_str("net");
+ break;
+ }
+
+ fword("encode-string");
+ push_str("boot-device");
+ fword("property");
+
+ device_end();
+
+ bind_func("platform-boot", boot );
+ bind_func("(go)", go );
+
+ /* Set up other properties */
+ push_str("/chosen");
+ fword("find-device");
+
+ setup_uuid();
+
+ /* Enable interrupts */
+ temp = get_psr();
+ temp = (temp & ~PSR_PIL) | (13 << 8); /* Enable CPU timer interrupt (level 14) */
+ put_psr(temp);
+}
+
+extern struct _console_ops arch_console_ops;
+
+int openbios(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
+ if (hwdefs[i].machine_id_low <= qemu_machine_type &&
+ hwdefs[i].machine_id_high >= qemu_machine_type) {
+ hwdef = &hwdefs[i];
+ break;
+ }
+ }
+ if (!hwdef)
+ for(;;); // Internal inconsistency, hang
+
+#ifdef CONFIG_DEBUG_CONSOLE
+ init_console(arch_console_ops);
+#endif
+ /* Make sure we setup OFMEM before the MMU as we need malloc() to setup page tables */
+ ofmem_init();
+
+#ifdef CONFIG_DRIVER_SBUS
+ init_mmu_swift();
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ escc_uart_init(hwdef->serial_base | (CONFIG_SERIAL_PORT? 0ULL: 4ULL),
+ CONFIG_SERIAL_SPEED);
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
+ kbd_init(hwdef->ms_kb_base);
+#endif
+#endif
+
+ collect_sys_info(&sys_info);
+
+ dict = (unsigned char *)sys_info.dict_start;
+ dicthead = (cell)sys_info.dict_end;
+ last = sys_info.dict_last;
+ dictlimit = sys_info.dict_limit;
+
+ forth_init();
+
+#ifdef CONFIG_DEBUG_BOOT
+ printk("forth started.\n");
+ printk("initializing memory...");
+#endif
+
+ init_memory();
+
+#ifdef CONFIG_DEBUG_BOOT
+ printk("done\n");
+#endif
+
+ PUSH_xt( bind_noname_func(arch_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+
+ if (!PC) {
+ printk("panic: no dictionary entry point.\n");
+ return -1;
+ }
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("done (%d bytes).\n", dicthead);
+ printk("Jumping to dictionary...\n");
+#endif
+
+ enterforth((xt_t)PC);
+
+ free(dict);
+ return 0;
+}