|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions are met: ! 7: * * Redistributions of source code must retain the above copyright ! 8: * notice, this list of conditions and the following disclaimer. ! 9: * * Redistributions in binary form must reproduce the above copyright ! 10: * notice, this list of conditions and the following disclaimer in the ! 11: * documentation and/or other materials provided with the distribution. ! 12: * * Neither the name of the Open Source and Linux Lab nor the ! 13: * names of its contributors may be used to endorse or promote products ! 14: * derived from this software without specific prior written permission. ! 15: * ! 16: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ! 17: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ! 20: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ! 22: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ! 23: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ! 24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ! 25: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! 26: */ ! 27: ! 28: #include "sysemu.h" ! 29: #include "boards.h" ! 30: #include "loader.h" ! 31: #include "elf.h" ! 32: #include "memory.h" ! 33: #include "exec-memory.h" ! 34: #include "pc.h" ! 35: #include "sysbus.h" ! 36: #include "flash.h" ! 37: #include "xtensa_bootparam.h" ! 38: ! 39: typedef struct LxBoardDesc { ! 40: size_t flash_size; ! 41: size_t flash_sector_size; ! 42: size_t sram_size; ! 43: } LxBoardDesc; ! 44: ! 45: typedef struct Lx60FpgaState { ! 46: MemoryRegion iomem; ! 47: uint32_t leds; ! 48: uint32_t switches; ! 49: } Lx60FpgaState; ! 50: ! 51: static void lx60_fpga_reset(void *opaque) ! 52: { ! 53: Lx60FpgaState *s = opaque; ! 54: ! 55: s->leds = 0; ! 56: s->switches = 0; ! 57: } ! 58: ! 59: static uint64_t lx60_fpga_read(void *opaque, target_phys_addr_t addr, ! 60: unsigned size) ! 61: { ! 62: Lx60FpgaState *s = opaque; ! 63: ! 64: switch (addr) { ! 65: case 0x0: /*build date code*/ ! 66: return 0x09272011; ! 67: ! 68: case 0x4: /*processor clock frequency, Hz*/ ! 69: return 10000000; ! 70: ! 71: case 0x8: /*LEDs (off = 0, on = 1)*/ ! 72: return s->leds; ! 73: ! 74: case 0xc: /*DIP switches (off = 0, on = 1)*/ ! 75: return s->switches; ! 76: } ! 77: return 0; ! 78: } ! 79: ! 80: static void lx60_fpga_write(void *opaque, target_phys_addr_t addr, ! 81: uint64_t val, unsigned size) ! 82: { ! 83: Lx60FpgaState *s = opaque; ! 84: ! 85: switch (addr) { ! 86: case 0x8: /*LEDs (off = 0, on = 1)*/ ! 87: s->leds = val; ! 88: break; ! 89: ! 90: case 0x10: /*board reset*/ ! 91: if (val == 0xdead) { ! 92: qemu_system_reset_request(); ! 93: } ! 94: break; ! 95: } ! 96: } ! 97: ! 98: static const MemoryRegionOps lx60_fpga_ops = { ! 99: .read = lx60_fpga_read, ! 100: .write = lx60_fpga_write, ! 101: .endianness = DEVICE_NATIVE_ENDIAN, ! 102: }; ! 103: ! 104: static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, ! 105: target_phys_addr_t base) ! 106: { ! 107: Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState)); ! 108: ! 109: memory_region_init_io(&s->iomem, &lx60_fpga_ops, s, ! 110: "lx60.fpga", 0x10000); ! 111: memory_region_add_subregion(address_space, base, &s->iomem); ! 112: lx60_fpga_reset(s); ! 113: qemu_register_reset(lx60_fpga_reset, s); ! 114: return s; ! 115: } ! 116: ! 117: static void lx60_net_init(MemoryRegion *address_space, ! 118: target_phys_addr_t base, ! 119: target_phys_addr_t descriptors, ! 120: target_phys_addr_t buffers, ! 121: qemu_irq irq, NICInfo *nd) ! 122: { ! 123: DeviceState *dev; ! 124: SysBusDevice *s; ! 125: MemoryRegion *ram; ! 126: ! 127: dev = qdev_create(NULL, "open_eth"); ! 128: qdev_set_nic_properties(dev, nd); ! 129: qdev_init_nofail(dev); ! 130: ! 131: s = sysbus_from_qdev(dev); ! 132: sysbus_connect_irq(s, 0, irq); ! 133: memory_region_add_subregion(address_space, base, ! 134: sysbus_mmio_get_region(s, 0)); ! 135: memory_region_add_subregion(address_space, descriptors, ! 136: sysbus_mmio_get_region(s, 1)); ! 137: ! 138: ram = g_malloc(sizeof(*ram)); ! 139: memory_region_init_ram(ram, NULL, "open_eth.ram", 16384); ! 140: memory_region_add_subregion(address_space, buffers, ram); ! 141: } ! 142: ! 143: static uint64_t translate_phys_addr(void *env, uint64_t addr) ! 144: { ! 145: return cpu_get_phys_page_debug(env, addr); ! 146: } ! 147: ! 148: static void lx60_reset(void *env) ! 149: { ! 150: cpu_reset(env); ! 151: } ! 152: ! 153: static void lx_init(const LxBoardDesc *board, ! 154: ram_addr_t ram_size, const char *boot_device, ! 155: const char *kernel_filename, const char *kernel_cmdline, ! 156: const char *initrd_filename, const char *cpu_model) ! 157: { ! 158: #ifdef TARGET_WORDS_BIGENDIAN ! 159: int be = 1; ! 160: #else ! 161: int be = 0; ! 162: #endif ! 163: MemoryRegion *system_memory = get_system_memory(); ! 164: CPUState *env = NULL; ! 165: MemoryRegion *ram, *rom, *system_io; ! 166: DriveInfo *dinfo; ! 167: pflash_t *flash = NULL; ! 168: int n; ! 169: ! 170: if (!cpu_model) { ! 171: cpu_model = "dc232b"; ! 172: } ! 173: ! 174: for (n = 0; n < smp_cpus; n++) { ! 175: env = cpu_init(cpu_model); ! 176: if (!env) { ! 177: fprintf(stderr, "Unable to find CPU definition\n"); ! 178: exit(1); ! 179: } ! 180: env->sregs[PRID] = n; ! 181: qemu_register_reset(lx60_reset, env); ! 182: /* Need MMU initialized prior to ELF loading, ! 183: * so that ELF gets loaded into virtual addresses ! 184: */ ! 185: cpu_reset(env); ! 186: } ! 187: ! 188: ram = g_malloc(sizeof(*ram)); ! 189: memory_region_init_ram(ram, NULL, "lx60.dram", ram_size); ! 190: memory_region_add_subregion(system_memory, 0, ram); ! 191: ! 192: system_io = g_malloc(sizeof(*system_io)); ! 193: memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024); ! 194: memory_region_add_subregion(system_memory, 0xf0000000, system_io); ! 195: lx60_fpga_init(system_io, 0x0d020000); ! 196: if (nd_table[0].vlan) { ! 197: lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, ! 198: xtensa_get_extint(env, 1), nd_table); ! 199: } ! 200: ! 201: if (!serial_hds[0]) { ! 202: serial_hds[0] = qemu_chr_new("serial0", "null", NULL); ! 203: } ! 204: ! 205: serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0), ! 206: 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); ! 207: ! 208: dinfo = drive_get(IF_PFLASH, 0, 0); ! 209: if (dinfo) { ! 210: flash = pflash_cfi01_register(0xf8000000, ! 211: NULL, "lx60.io.flash", board->flash_size, ! 212: dinfo->bdrv, board->flash_sector_size, ! 213: board->flash_size / board->flash_sector_size, ! 214: 4, 0x0000, 0x0000, 0x0000, 0x0000, be); ! 215: if (flash == NULL) { ! 216: fprintf(stderr, "Unable to mount pflash\n"); ! 217: exit(1); ! 218: } ! 219: } ! 220: ! 221: /* Use presence of kernel file name as 'boot from SRAM' switch. */ ! 222: if (kernel_filename) { ! 223: rom = g_malloc(sizeof(*rom)); ! 224: memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); ! 225: memory_region_add_subregion(system_memory, 0xfe000000, rom); ! 226: ! 227: /* Put kernel bootparameters to the end of that SRAM */ ! 228: if (kernel_cmdline) { ! 229: size_t cmdline_size = strlen(kernel_cmdline) + 1; ! 230: size_t bp_size = sizeof(BpTag[4]) + cmdline_size; ! 231: uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff; ! 232: ! 233: env->regs[2] = tagptr; ! 234: ! 235: tagptr = put_tag(tagptr, 0x7b0b, 0, NULL); ! 236: if (cmdline_size > 1) { ! 237: tagptr = put_tag(tagptr, 0x1001, ! 238: cmdline_size, kernel_cmdline); ! 239: } ! 240: tagptr = put_tag(tagptr, 0x7e0b, 0, NULL); ! 241: } ! 242: uint64_t elf_entry; ! 243: uint64_t elf_lowaddr; ! 244: int success = load_elf(kernel_filename, translate_phys_addr, env, ! 245: &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0); ! 246: if (success > 0) { ! 247: env->pc = elf_entry; ! 248: } ! 249: } else { ! 250: if (flash) { ! 251: MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash); ! 252: MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); ! 253: ! 254: memory_region_init_alias(flash_io, "lx60.flash", ! 255: flash_mr, 0, board->flash_size); ! 256: memory_region_add_subregion(system_memory, 0xfe000000, ! 257: flash_io); ! 258: } ! 259: } ! 260: } ! 261: ! 262: static void xtensa_lx60_init(ram_addr_t ram_size, ! 263: const char *boot_device, ! 264: const char *kernel_filename, const char *kernel_cmdline, ! 265: const char *initrd_filename, const char *cpu_model) ! 266: { ! 267: static const LxBoardDesc lx60_board = { ! 268: .flash_size = 0x400000, ! 269: .flash_sector_size = 0x10000, ! 270: .sram_size = 0x20000, ! 271: }; ! 272: lx_init(&lx60_board, ram_size, boot_device, ! 273: kernel_filename, kernel_cmdline, ! 274: initrd_filename, cpu_model); ! 275: } ! 276: ! 277: static void xtensa_lx200_init(ram_addr_t ram_size, ! 278: const char *boot_device, ! 279: const char *kernel_filename, const char *kernel_cmdline, ! 280: const char *initrd_filename, const char *cpu_model) ! 281: { ! 282: static const LxBoardDesc lx200_board = { ! 283: .flash_size = 0x1000000, ! 284: .flash_sector_size = 0x20000, ! 285: .sram_size = 0x2000000, ! 286: }; ! 287: lx_init(&lx200_board, ram_size, boot_device, ! 288: kernel_filename, kernel_cmdline, ! 289: initrd_filename, cpu_model); ! 290: } ! 291: ! 292: static QEMUMachine xtensa_lx60_machine = { ! 293: .name = "lx60", ! 294: .desc = "lx60 EVB (dc232b)", ! 295: .init = xtensa_lx60_init, ! 296: .max_cpus = 4, ! 297: }; ! 298: ! 299: static QEMUMachine xtensa_lx200_machine = { ! 300: .name = "lx200", ! 301: .desc = "lx200 EVB (dc232b)", ! 302: .init = xtensa_lx200_init, ! 303: .max_cpus = 4, ! 304: }; ! 305: ! 306: static void xtensa_lx_machines_init(void) ! 307: { ! 308: qemu_register_machine(&xtensa_lx60_machine); ! 309: qemu_register_machine(&xtensa_lx200_machine); ! 310: } ! 311: ! 312: machine_init(xtensa_lx_machines_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.