Annotation of qemu/hw/xtensa_lx60.c, revision 1.1

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);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.