summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/drivers/macio.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/drivers/macio.c')
-rw-r--r--qemu/roms/openbios/drivers/macio.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/qemu/roms/openbios/drivers/macio.c b/qemu/roms/openbios/drivers/macio.c
new file mode 100644
index 000000000..f54bc86dc
--- /dev/null
+++ b/qemu/roms/openbios/drivers/macio.c
@@ -0,0 +1,281 @@
+/*
+ * derived from mol/mol.c,
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "arch/common/nvram.h"
+#include "packages/nvram.h"
+#include "libopenbios/bindings.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "drivers/drivers.h"
+#include "macio.h"
+#include "cuda.h"
+#include "escc.h"
+#include "drivers/pci.h"
+
+#define OW_IO_NVRAM_SIZE 0x00020000
+#define OW_IO_NVRAM_OFFSET 0x00060000
+#define OW_IO_NVRAM_SHIFT 4
+
+#define NW_IO_NVRAM_SIZE 0x00004000
+#define NW_IO_NVRAM_OFFSET 0xfff04000
+
+#define IO_OPENPIC_SIZE 0x00040000
+#define IO_OPENPIC_OFFSET 0x00040000
+
+static char *nvram;
+
+static int macio_nvram_shift(void)
+{
+ int nvram_flat;
+
+ if (is_oldworld())
+ return OW_IO_NVRAM_SHIFT;
+
+ nvram_flat = fw_cfg_read_i32(FW_CFG_PPC_NVRAM_FLAT);
+ return nvram_flat ? 0 : 1;
+}
+
+int
+macio_get_nvram_size(void)
+{
+ int shift = macio_nvram_shift();
+ if (is_oldworld())
+ return OW_IO_NVRAM_SIZE >> shift;
+ else
+ return NW_IO_NVRAM_SIZE >> shift;
+}
+
+static unsigned long macio_nvram_offset(void)
+{
+ unsigned long r;
+
+ /* Hypervisor tells us where NVRAM lies */
+ r = fw_cfg_read_i32(FW_CFG_PPC_NVRAM_ADDR);
+ if (r)
+ return r;
+
+ /* Fall back to hardcoded addresses */
+ if (is_oldworld())
+ return OW_IO_NVRAM_OFFSET;
+
+ return NW_IO_NVRAM_OFFSET;
+}
+
+static unsigned long macio_nvram_size(void)
+{
+ if (is_oldworld())
+ return OW_IO_NVRAM_SIZE;
+ else
+ return NW_IO_NVRAM_SIZE;
+}
+
+void macio_nvram_init(const char *path, phys_addr_t addr)
+{
+ phandle_t chosen, aliases;
+ phandle_t dnode;
+ int props[2];
+ char buf[64];
+ unsigned long nvram_size, nvram_offset;
+
+ nvram_offset = macio_nvram_offset();
+ nvram_size = macio_nvram_size();
+
+ nvram = (char*)addr + nvram_offset;
+ snprintf(buf, sizeof(buf), "%s/nvram", path);
+ nvram_init(buf);
+ dnode = find_dev(buf);
+ set_int_property(dnode, "#bytes", arch_nvram_size() );
+ props[0] = __cpu_to_be32(nvram_offset);
+ props[1] = __cpu_to_be32(nvram_size);
+ set_property(dnode, "reg", (char *)&props, sizeof(props));
+ set_property(dnode, "device_type", "nvram", 6);
+ NEWWORLD(set_property(dnode, "compatible", "nvram,flash", 12));
+
+ chosen = find_dev("/chosen");
+ push_str(buf);
+ fword("open-dev");
+ set_int_property(chosen, "nvram", POP());
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "nvram", buf, strlen(buf) + 1);
+}
+
+#ifdef DUMP_NVRAM
+static void
+dump_nvram(void)
+{
+ int i, j;
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 16; j++)
+ printk ("%02x ", nvram[(i*16+j)<<4]);
+ printk (" ");
+ for (j = 0; j < 16; j++)
+ if (isprint(nvram[(i*16+j)<<4]))
+ printk("%c", nvram[(i*16+j)<<4]);
+ else
+ printk(".");
+ printk ("\n");
+ }
+}
+#endif
+
+
+void
+macio_nvram_put(char *buf)
+{
+ int i;
+ unsigned int it_shift = macio_nvram_shift();
+
+ for (i=0; i < arch_nvram_size(); i++)
+ nvram[i << it_shift] = buf[i];
+#ifdef DUMP_NVRAM
+ printk("new nvram:\n");
+ dump_nvram();
+#endif
+}
+
+void
+macio_nvram_get(char *buf)
+{
+ int i;
+ unsigned int it_shift = macio_nvram_shift();
+
+ for (i=0; i< arch_nvram_size(); i++)
+ buf[i] = nvram[i << it_shift];
+
+#ifdef DUMP_NVRAM
+ printk("current nvram:\n");
+ dump_nvram();
+#endif
+}
+
+static void
+openpic_init(const char *path, phys_addr_t addr)
+{
+ phandle_t dnode;
+ int props[2];
+ char buf[128];
+
+ push_str(path);
+ fword("find-device");
+ fword("new-device");
+ push_str("interrupt-controller");
+ fword("device-name");
+
+ snprintf(buf, sizeof(buf), "%s/interrupt-controller", path);
+ dnode = find_dev(buf);
+ set_property(dnode, "device_type", "open-pic", 9);
+ set_property(dnode, "compatible", "chrp,open-pic", 14);
+ set_property(dnode, "built-in", "", 0);
+ props[0] = __cpu_to_be32(IO_OPENPIC_OFFSET);
+ props[1] = __cpu_to_be32(IO_OPENPIC_SIZE);
+ set_property(dnode, "reg", (char *)&props, sizeof(props));
+ set_int_property(dnode, "#interrupt-cells", 2);
+ set_int_property(dnode, "#address-cells", 0);
+ set_property(dnode, "interrupt-controller", "", 0);
+ set_int_property(dnode, "clock-frequency", 4166666);
+
+ fword("finish-device");
+}
+
+DECLARE_NODE(ob_macio, INSTALL_OPEN, sizeof(int), "Tmac-io");
+
+/* ( str len -- addr ) */
+
+static void
+ob_macio_decode_unit(void *private)
+{
+ ucell addr;
+
+ const char *arg = pop_fstr_copy();
+
+ addr = strtol(arg, NULL, 16);
+
+ free((char*)arg);
+
+ PUSH(addr);
+}
+
+/* ( addr -- str len ) */
+
+static void
+ob_macio_encode_unit(void *private)
+{
+ char buf[8];
+
+ ucell addr = POP();
+
+ snprintf(buf, sizeof(buf), "%x", addr);
+
+ push_str(buf);
+}
+
+NODE_METHODS(ob_macio) = {
+ { "decode-unit", ob_macio_decode_unit },
+ { "encode-unit", ob_macio_encode_unit },
+};
+
+static void
+ob_unin_init(void)
+{
+ phandle_t dnode;
+ int props[2];
+
+ push_str("/");
+ fword("find-device");
+ fword("new-device");
+ push_str("uni-n");
+ fword("device-name");
+
+ dnode = find_dev("/uni-n");
+ set_property(dnode, "device_type", "memory-controller", 18);
+ set_property(dnode, "compatible", "uni-north", 10);
+ set_int_property(dnode, "device-rev", 0);
+ props[0] = __cpu_to_be32(0xf8000000);
+ props[1] = __cpu_to_be32(0x1000000);
+ set_property(dnode, "reg", (char *)&props, sizeof(props));
+
+ fword("finish-device");
+}
+
+void
+ob_macio_heathrow_init(const char *path, phys_addr_t addr)
+{
+ phandle_t aliases;
+
+ REGISTER_NODE(ob_macio);
+ aliases = find_dev("/aliases");
+ set_property(aliases, "mac-io", path, strlen(path) + 1);
+
+ cuda_init(path, addr);
+ macio_nvram_init(path, addr);
+ escc_init(path, addr);
+ macio_ide_init(path, addr, 2);
+}
+
+void
+ob_macio_keylargo_init(const char *path, phys_addr_t addr)
+{
+ phandle_t aliases;
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "mac-io", path, strlen(path) + 1);
+
+ cuda_init(path, addr);
+ /* The NewWorld NVRAM is not located in the MacIO device */
+ macio_nvram_init("", 0);
+ escc_init(path, addr);
+ macio_ide_init(path, addr, 2);
+ openpic_init(path, addr);
+ ob_unin_init();
+}