Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / drivers / macio.c
diff --git a/qemu/roms/openbios/drivers/macio.c b/qemu/roms/openbios/drivers/macio.c
new file mode 100644 (file)
index 0000000..f54bc86
--- /dev/null
@@ -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();
+}