diff options
Diffstat (limited to 'qemu/roms/openbios/drivers/macio.c')
-rw-r--r-- | qemu/roms/openbios/drivers/macio.c | 281 |
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(); +} |