📄 mips_malta.c
字号:
/* SWITCH Register */ case 0x00200: break; /* JMPRS Register */ case 0x00210: break; /* LEDBAR Register */ /* XXX: implement a 8-LED array */ case 0x00408: s->leds = val & 0xff; break; /* ASCIIWORD Register */ case 0x00410: snprintf(s->display_text, 9, "%08X", val); malta_fpga_update_display(s); break; /* ASCIIPOS0 to ASCIIPOS7 Registers */ case 0x00418: case 0x00420: case 0x00428: case 0x00430: case 0x00438: case 0x00440: case 0x00448: case 0x00450: s->display_text[(saddr - 0x00418) >> 3] = (char) val; malta_fpga_update_display(s); break; /* SOFTRES Register */ case 0x00500: if (val == 0x42) qemu_system_reset_request (); break; /* BRKRES Register */ case 0x00508: s->brk = val & 0xff; break; /* UART Registers are handled directly by the serial device */ /* GPOUT Register */ case 0x00a00: s->gpout = val & 0xff; break; /* I2COE Register */ case 0x00b08: s->i2coe = val & 0x03; break; /* I2COUT Register */ case 0x00b10: eeprom24c0x_write(val & 0x02, val & 0x01); s->i2cout = val; break; /* I2CSEL Register */ case 0x00b18: s->i2csel = val & 0x01; break; default:#if 0 printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n", addr);#endif break; }}static CPUReadMemoryFunc *malta_fpga_read[] = { malta_fpga_readl, malta_fpga_readl, malta_fpga_readl};static CPUWriteMemoryFunc *malta_fpga_write[] = { malta_fpga_writel, malta_fpga_writel, malta_fpga_writel};static void malta_fpga_reset(void *opaque){ MaltaFPGAState *s = opaque; s->leds = 0x00; s->brk = 0x0a; s->gpout = 0x00; s->i2cin = 0x3; s->i2coe = 0x0; s->i2cout = 0x3; s->i2csel = 0x1; s->display_text[8] = '\0'; snprintf(s->display_text, 9, " "); malta_fpga_update_display(s);}static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env){ MaltaFPGAState *s; CharDriverState *uart_chr; int malta; s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState)); malta = cpu_register_io_memory(0, malta_fpga_read, malta_fpga_write, s); cpu_register_physical_memory(base, 0x900, malta); cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta); s->display = qemu_chr_open("vc"); qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n"); qemu_chr_printf(s->display, "+--------+\r\n"); qemu_chr_printf(s->display, "+ +\r\n"); qemu_chr_printf(s->display, "+--------+\r\n"); qemu_chr_printf(s->display, "\n"); qemu_chr_printf(s->display, "Malta ASCII\r\n"); qemu_chr_printf(s->display, "+--------+\r\n"); qemu_chr_printf(s->display, "+ +\r\n"); qemu_chr_printf(s->display, "+--------+\r\n"); uart_chr = qemu_chr_open("vc"); qemu_chr_printf(uart_chr, "CBUS UART\r\n"); s->uart = serial_mm_init(base + 0x900, 3, env->irq[2], uart_chr, 1); malta_fpga_reset(s); qemu_register_reset(malta_fpga_reset, s); return s;}/* Audio support */#ifdef HAS_AUDIOstatic void audio_init (PCIBus *pci_bus){ struct soundhw *c; int audio_enabled = 0; for (c = soundhw; !audio_enabled && c->name; ++c) { audio_enabled = c->enabled; } if (audio_enabled) { AudioState *s; s = AUD_init (); if (s) { for (c = soundhw; c->name; ++c) { if (c->enabled) c->init.init_pci (pci_bus, s); } } }}#endif/* Network support */static void network_init (PCIBus *pci_bus){ int i; NICInfo *nd; for(i = 0; i < nb_nics; i++) { nd = &nd_table[i]; if (!nd->model) { nd->model = "pcnet"; } if (i == 0 && strcmp(nd->model, "pcnet") == 0) { /* The malta board has a PCNet card using PCI SLOT 11 */ pci_nic_init(pci_bus, nd, 88); } else { pci_nic_init(pci_bus, nd, -1); } }}/* ROM and pseudo bootloader The following code implements a very very simple bootloader. It first loads the registers a0 to a3 to the values expected by the OS, and then jump at the kernel address. The bootloader should pass the locations of the kernel arguments and environment variables tables. Those tables contain the 32-bit address of NULL terminated strings. The environment variables table should be terminated by a NULL address. For a simpler implementation, the number of kernel arguments is fixed to two (the name of the kernel and the command line), and the two tables are actually the same one. The registers a0 to a3 should contain the following values: a0 - number of kernel arguments a1 - 32-bit address of the kernel arguments table a2 - 32-bit address of the environment variables table a3 - RAM size in bytes*/static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry){ uint32_t *p; /* Small bootloader */ p = (uint32_t *) (phys_ram_base + bios_offset); stl_raw(p++, 0x0bf00160); /* j 0x1fc00580 */ stl_raw(p++, 0x00000000); /* nop */ /* YAMON service vector */ stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580); /* start: */ stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c); /* print_count: */ stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580); /* start: */ stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800); /* flush_cache: */ stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808); /* print: */ stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800); /* reg_cpu_isr: */ stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800); /* unred_cpu_isr: */ stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800); /* reg_ic_isr: */ stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800); /* unred_ic_isr: */ stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800); /* reg_esr: */ stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800); /* unreg_esr: */ stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800); /* getchar: */ stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800); /* syscon_read: */ /* Second part of the bootloader */ p = (uint32_t *) (phys_ram_base + bios_offset + 0x580); stl_raw(p++, 0x24040002); /* addiu a0, zero, 2 */ stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */ stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff)); /* ori sp, sp, low(ENVP_ADDR) */ stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */ stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a1, low(ENVP_ADDR) */ stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */ stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */ stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(ram_size) */ stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(ram_size) */ /* Load BAR registers as done by YAMON */ stl_raw(p++, 0x3c09b400); /* lui t1, 0xb400 */#ifdef TARGET_WORDS_BIGENDIAN stl_raw(p++, 0x3c08df00); /* lui t0, 0xdf00 */#else stl_raw(p++, 0x340800df); /* ori t0, r0, 0x00df */#endif stl_raw(p++, 0xad280068); /* sw t0, 0x0068(t1) */ stl_raw(p++, 0x3c09bbe0); /* lui t1, 0xbbe0 */#ifdef TARGET_WORDS_BIGENDIAN stl_raw(p++, 0x3c08c000); /* lui t0, 0xc000 */#else stl_raw(p++, 0x340800c0); /* ori t0, r0, 0x00c0 */#endif stl_raw(p++, 0xad280048); /* sw t0, 0x0048(t1) */#ifdef TARGET_WORDS_BIGENDIAN stl_raw(p++, 0x3c084000); /* lui t0, 0x4000 */#else stl_raw(p++, 0x34080040); /* ori t0, r0, 0x0040 */#endif stl_raw(p++, 0xad280050); /* sw t0, 0x0050(t1) */#ifdef TARGET_WORDS_BIGENDIAN stl_raw(p++, 0x3c088000); /* lui t0, 0x8000 */#else stl_raw(p++, 0x34080080); /* ori t0, r0, 0x0080 */#endif stl_raw(p++, 0xad280058); /* sw t0, 0x0058(t1) */#ifdef TARGET_WORDS_BIGENDIAN stl_raw(p++, 0x3c083f00); /* lui t0, 0x3f00 */#else stl_raw(p++, 0x3408003f); /* ori t0, r0, 0x003f */#endif stl_raw(p++, 0xad280060); /* sw t0, 0x0060(t1) */#ifdef TARGET_WORDS_BIGENDIAN stl_raw(p++, 0x3c08c100); /* lui t0, 0xc100 */#else stl_raw(p++, 0x340800c1); /* ori t0, r0, 0x00c1 */#endif stl_raw(p++, 0xad280080); /* sw t0, 0x0080(t1) */#ifdef TARGET_WORDS_BIGENDIAN stl_raw(p++, 0x3c085e00); /* lui t0, 0x5e00 */#else stl_raw(p++, 0x3408005e); /* ori t0, r0, 0x005e */#endif stl_raw(p++, 0xad280088); /* sw t0, 0x0088(t1) */ /* Jump to kernel code */ stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */ stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */ stl_raw(p++, 0x03e00008); /* jr ra */ stl_raw(p++, 0x00000000); /* nop */ /* YAMON subroutines */ p = (uint32_t *) (phys_ram_base + bios_offset + 0x800); stl_raw(p++, 0x03e00008); /* jr ra */ stl_raw(p++, 0x24020000); /* li v0,0 */ /* 808 YAMON print */ stl_raw(p++, 0x03e06821); /* move t5,ra */ stl_raw(p++, 0x00805821); /* move t3,a0 */ stl_raw(p++, 0x00a05021); /* move t2,a1 */ stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */ stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */ stl_raw(p++, 0x10800005); /* beqz a0,834 */ stl_raw(p++, 0x00000000); /* nop */ stl_raw(p++, 0x0ff0021c); /* jal 870 */ stl_raw(p++, 0x00000000); /* nop */ stl_raw(p++, 0x08000205); /* j 814 */ stl_raw(p++, 0x00000000); /* nop */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -