X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=hw%2Fmips_malta.c;h=0a6eaa479ac748b90eb26ff0b651de677d1ec683;hb=ffabf0371832aa398f647bc18b4d3c50609c1493;hp=36b5f43e6ddc82de10d0da80957b37f23c90dac0;hpb=9414cc6fd35eb08721fc96de17c52b1b0535ba3a;p=qemu diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 36b5f43..0a6eaa4 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -22,13 +22,25 @@ * THE SOFTWARE. */ -#include "vl.h" - -#ifdef TARGET_WORDS_BIGENDIAN -#define BIOS_FILENAME "mips_bios.bin" -#else -#define BIOS_FILENAME "mipsel_bios.bin" -#endif +#include "hw.h" +#include "pc.h" +#include "fdc.h" +#include "net.h" +#include "boards.h" +#include "smbus.h" +#include "block.h" +#include "flash.h" +#include "mips.h" +#include "pci.h" +#include "qemu-char.h" +#include "sysemu.h" +#include "audio/audio.h" +#include "boards.h" +#include "qemu-log.h" +#include "mips-bios.h" +#include "ide.h" + +//#define DEBUG_BOARD_INIT #ifdef TARGET_MIPS64 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL) @@ -42,8 +54,7 @@ #define ENVP_NB_ENTRIES 16 #define ENVP_ENTRY_SIZE 256 -extern int nographic; -extern FILE *logfile; +#define MAX_IDE_BUS 2 typedef struct { uint32_t leds; @@ -60,6 +71,13 @@ typedef struct { static PITState *pit; +static struct _loaderparams { + int ram_size; + const char *kernel_filename; + const char *kernel_cmdline; + const char *initrd_filename; +} loaderparams; + /* Malta FPGA */ static void malta_fpga_update_display(void *opaque) { @@ -67,18 +85,16 @@ static void malta_fpga_update_display(void *opaque) int i; MaltaFPGAState *s = opaque; - if (!nographic) { - for (i = 7 ; i >= 0 ; i--) { - if (s->leds & (1 << i)) - leds_text[i] = '#'; - else - leds_text[i] = ' '; - } - leds_text[8] = '\0'; - - qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text); - qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text); + for (i = 7 ; i >= 0 ; i--) { + if (s->leds & (1 << i)) + leds_text[i] = '#'; + else + leds_text[i] = ' '; } + leds_text[8] = '\0'; + + qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text); + qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text); } /* @@ -94,9 +110,9 @@ static void malta_fpga_update_display(void *opaque) //~ #define DEBUG #if defined(DEBUG) -# define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args) +# define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__) #else -# define logout(fmt, args...) ((void)0) +# define logout(fmt, ...) ((void)0) #endif struct _eeprom24c0x_t { @@ -134,7 +150,7 @@ static eeprom24c0x_t eeprom = { }, }; -static uint8_t eeprom24c0x_read() +static uint8_t eeprom24c0x_read(void) { logout("%u: scl = %u, sda = %u, data = 0x%02x\n", eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data); @@ -372,19 +388,19 @@ static void malta_fpga_writel(void *opaque, target_phys_addr_t addr, } } -static CPUReadMemoryFunc *malta_fpga_read[] = { +static CPUReadMemoryFunc * const malta_fpga_read[] = { malta_fpga_readl, malta_fpga_readl, malta_fpga_readl }; -static CPUWriteMemoryFunc *malta_fpga_write[] = { +static CPUWriteMemoryFunc * const malta_fpga_write[] = { malta_fpga_writel, malta_fpga_writel, malta_fpga_writel }; -void malta_fpga_reset(void *opaque) +static void malta_fpga_reset(void *opaque) { MaltaFPGAState *s = opaque; @@ -398,39 +414,38 @@ void malta_fpga_reset(void *opaque) s->display_text[8] = '\0'; snprintf(s->display_text, 9, " "); - malta_fpga_update_display(s); } -MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env) +static void malta_fpga_led_init(CharDriverState *chr) +{ + qemu_chr_printf(chr, "\e[HMalta LEDBAR\r\n"); + qemu_chr_printf(chr, "+--------+\r\n"); + qemu_chr_printf(chr, "+ +\r\n"); + qemu_chr_printf(chr, "+--------+\r\n"); + qemu_chr_printf(chr, "\n"); + qemu_chr_printf(chr, "Malta ASCII\r\n"); + qemu_chr_printf(chr, "+--------+\r\n"); + qemu_chr_printf(chr, "+ +\r\n"); + qemu_chr_printf(chr, "+--------+\r\n"); +} + +static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr) { MaltaFPGAState *s; - CharDriverState *uart_chr; int malta; s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState)); - malta = cpu_register_io_memory(0, malta_fpga_read, + malta = cpu_register_io_memory(malta_fpga_read, malta_fpga_write, s); cpu_register_physical_memory(base, 0x900, malta); + /* 0xa00 is less than a page, so will still get the right offsets. */ cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta); - if (!nographic) { - 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); - } + s->display = qemu_chr_open("fpga", "vc:320x200", malta_fpga_led_init); + + s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1); malta_fpga_reset(s); qemu_register_reset(malta_fpga_reset, s); @@ -450,13 +465,9 @@ static void audio_init (PCIBus *pci_bus) } 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); + for (c = soundhw; c->name; ++c) { + if (c->enabled) { + c->init.init_pci(pci_bus); } } } @@ -464,22 +475,19 @@ static void audio_init (PCIBus *pci_bus) #endif /* Network support */ -static void network_init (PCIBus *pci_bus) +static void network_init(void) { 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) { + NICInfo *nd = &nd_table[i]; + const char *default_devaddr = NULL; + + if (i == 0 && (!nd->model || 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); - } + default_devaddr = "0b"; + + pci_nic_init(nd, "pcnet", default_devaddr); } } @@ -505,33 +513,34 @@ static void network_init (PCIBus *pci_bus) a3 - RAM size in bytes */ -static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry) +static void write_bootloader (CPUState *env, uint8_t *base, + int64_t kernel_entry) { uint32_t *p; /* Small bootloader */ - p = (uint32_t *) (phys_ram_base + bios_offset); + p = (uint32_t *)base; 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: */ + stl_raw(base + 0x500, 0xbfc00580); /* start: */ + stl_raw(base + 0x504, 0xbfc0083c); /* print_count: */ + stl_raw(base + 0x520, 0xbfc00580); /* start: */ + stl_raw(base + 0x52c, 0xbfc00800); /* flush_cache: */ + stl_raw(base + 0x534, 0xbfc00808); /* print: */ + stl_raw(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */ + stl_raw(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */ + stl_raw(base + 0x540, 0xbfc00800); /* reg_ic_isr: */ + stl_raw(base + 0x544, 0xbfc00800); /* unred_ic_isr: */ + stl_raw(base + 0x548, 0xbfc00800); /* reg_esr: */ + stl_raw(base + 0x54c, 0xbfc00800); /* unreg_esr: */ + stl_raw(base + 0x550, 0xbfc00800); /* getchar: */ + stl_raw(base + 0x554, 0xbfc00800); /* syscon_read: */ /* Second part of the bootloader */ - p = (uint32_t *) (phys_ram_base + bios_offset + 0x580); + p = (uint32_t *) (base + 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) */ @@ -539,10 +548,19 @@ static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t 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 | (env->ram_size >> 16)); /* lui a3, high(env->ram_size) */ - stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff)); /* ori a3, a3, low(env->ram_size) */ + 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 @@ -591,7 +609,7 @@ static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t stl_raw(p++, 0x00000000); /* nop */ /* YAMON subroutines */ - p = (uint32_t *) (phys_ram_base + bios_offset + 0x800); + p = (uint32_t *) (base + 0x800); stl_raw(p++, 0x03e00008); /* jr ra */ stl_raw(p++, 0x24020000); /* li v0,0 */ /* 808 YAMON print */ @@ -637,30 +655,29 @@ static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t static void prom_set(int index, const char *string, ...) { + char buf[ENVP_ENTRY_SIZE]; + target_phys_addr_t p; va_list ap; - int32_t *p; int32_t table_addr; - char *s; if (index >= ENVP_NB_ENTRIES) return; - p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND); - p += index; + p = ENVP_ADDR + VIRT_TO_PHYS_ADDEND + index * 4; if (string == NULL) { - stl_raw(p, 0); + stl_phys(p, 0); return; } - table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE; - s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr); - - stl_raw(p, table_addr); + table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + + index * ENVP_ENTRY_SIZE; + stl_phys(p, table_addr); va_start(ap, string); - vsnprintf (s, ENVP_ENTRY_SIZE, string, ap); + vsnprintf(buf, ENVP_ENTRY_SIZE, string, ap); va_end(ap); + pstrcpy_targphys(table_addr + VIRT_TO_PHYS_ADDEND, ENVP_ENTRY_SIZE, buf); } /* Kernel */ @@ -671,48 +688,50 @@ static int64_t load_kernel (CPUState *env) long initrd_size; ram_addr_t initrd_offset; - if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, - &kernel_entry, &kernel_low, &kernel_high) < 0) { + if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND, + (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low, + (uint64_t *)&kernel_high) < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", - env->kernel_filename); + loaderparams.kernel_filename); exit(1); } /* load initrd */ initrd_size = 0; initrd_offset = 0; - if (env->initrd_filename) { - initrd_size = get_image_size (env->initrd_filename); + if (loaderparams.initrd_filename) { + initrd_size = get_image_size (loaderparams.initrd_filename); if (initrd_size > 0) { initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK; - if (initrd_offset + initrd_size > env->ram_size) { + if (initrd_offset + initrd_size > ram_size) { fprintf(stderr, "qemu: memory too small for initial ram disk '%s'\n", - env->initrd_filename); + loaderparams.initrd_filename); exit(1); } - initrd_size = load_image(env->initrd_filename, - phys_ram_base + initrd_offset); + initrd_size = load_image_targphys(loaderparams.initrd_filename, + initrd_offset, + ram_size - initrd_offset); } if (initrd_size == (target_ulong) -1) { fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", - env->initrd_filename); + loaderparams.initrd_filename); exit(1); } } /* Store command line. */ - prom_set(index++, env->kernel_filename); + prom_set(index++, loaderparams.kernel_filename); if (initrd_size > 0) prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s", PHYS_TO_VIRT(initrd_offset), initrd_size, - env->kernel_cmdline); + loaderparams.kernel_cmdline); else - prom_set(index++, env->kernel_cmdline); + prom_set(index++, loaderparams.kernel_cmdline); /* Setup minimum environment variables */ prom_set(index++, "memsize"); - prom_set(index++, "%i", env->ram_size); + prom_set(index++, "%i", loaderparams.ram_size); prom_set(index++, "modetty0"); prom_set(index++, "38400n8r"); prom_set(index++, NULL); @@ -724,38 +743,52 @@ static void main_cpu_reset(void *opaque) { CPUState *env = opaque; cpu_reset(env); - cpu_mips_register(env, NULL); /* The bootload does not need to be rewritten as it is located in a read only location. The kernel location and the arguments table location does not change. */ - if (env->kernel_filename) { + if (loaderparams.kernel_filename) { env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); load_kernel (env); } } static -void mips_malta_init (int ram_size, int vga_ram_size, int boot_device, - DisplayState *ds, const char **fd_filename, int snapshot, +void mips_malta_init (ram_addr_t ram_size, + const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - char buf[1024]; - unsigned long bios_offset; + char *filename; + ram_addr_t ram_offset; + ram_addr_t bios_offset; + target_long bios_size; int64_t kernel_entry; PCIBus *pci_bus; + ISADevice *isa_dev; CPUState *env; RTCState *rtc_state; - /* fdctrl_t *floppy_controller; */ + fdctrl_t *floppy_controller; MaltaFPGAState *malta_fpga; - int ret; - mips_def_t *def; qemu_irq *i8259; int piix4_devfn; uint8_t *eeprom_buf; i2c_bus *smbus; int i; + DriveInfo *dinfo; + DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; + BlockDriverState *fd[MAX_FD]; + int fl_idx = 0; + int fl_sectors = 0; + + /* Make sure the first 3 serial ports are associated with a device. */ + for(i = 0; i < 3; i++) { + if (!serial_hds[i]) { + char label[32]; + snprintf(label, sizeof(label), "serial%d", i); + serial_hds[i] = qemu_chr_open(label, "null", NULL); + } + } /* init CPUs */ if (cpu_model == NULL) { @@ -765,71 +798,101 @@ void mips_malta_init (int ram_size, int vga_ram_size, int boot_device, cpu_model = "24Kf"; #endif } - if (mips_find_by_name(cpu_model, &def) != 0) - def = NULL; - env = cpu_init(); - cpu_mips_register(env, def); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); + env = cpu_init(cpu_model); + if (!env) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } qemu_register_reset(main_cpu_reset, env); /* allocate RAM */ - cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); + if (ram_size > (256 << 20)) { + fprintf(stderr, + "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n", + ((unsigned int)ram_size / (1 << 20))); + exit(1); + } + ram_offset = qemu_ram_alloc(ram_size); + bios_offset = qemu_ram_alloc(BIOS_SIZE); - /* Map the bios at two physical locations, as on the real board */ - bios_offset = ram_size + vga_ram_size; + + cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM); + + /* Map the bios at two physical locations, as on the real board. */ cpu_register_physical_memory(0x1e000000LL, BIOS_SIZE, bios_offset | IO_MEM_ROM); cpu_register_physical_memory(0x1fc00000LL, BIOS_SIZE, bios_offset | IO_MEM_ROM); /* FPGA */ - malta_fpga = malta_fpga_init(0x1f000000LL, env); - - /* Load a BIOS image unless a kernel image has been specified. */ - if (!kernel_filename) { - snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); - ret = load_image(buf, phys_ram_base + bios_offset); - if (ret < 0 || ret > BIOS_SIZE) { - fprintf(stderr, - "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n", - buf); - exit(1); + malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]); + + /* Load firmware in flash / BIOS unless we boot directly into a kernel. */ + if (kernel_filename) { + /* Write a small bootloader to the flash location. */ + loaderparams.ram_size = ram_size; + loaderparams.kernel_filename = kernel_filename; + loaderparams.kernel_cmdline = kernel_cmdline; + loaderparams.initrd_filename = initrd_filename; + kernel_entry = load_kernel(env); + env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); + write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry); + } else { + dinfo = drive_get(IF_PFLASH, 0, fl_idx); + if (dinfo) { + /* Load firmware from flash. */ + bios_size = 0x400000; + fl_sectors = bios_size >> 16; +#ifdef DEBUG_BOARD_INIT + printf("Register parallel flash %d size " TARGET_FMT_lx " at " + "offset %08lx addr %08llx '%s' %x\n", + fl_idx, bios_size, bios_offset, 0x1e000000LL, + bdrv_get_device_name(dinfo->bdrv), fl_sectors); +#endif + pflash_cfi01_register(0x1e000000LL, bios_offset, + dinfo->bdrv, 65536, fl_sectors, + 4, 0x0000, 0x0000, 0x0000, 0x0000); + fl_idx++; + } else { + /* Load a BIOS image. */ + if (bios_name == NULL) + bios_name = BIOS_FILENAME; + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (filename) { + bios_size = load_image_targphys(filename, 0x1fc00000LL, + BIOS_SIZE); + qemu_free(filename); + } else { + bios_size = -1; + } + if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { + fprintf(stderr, + "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n", + bios_name); + exit(1); + } } /* In little endian mode the 32bit words in the bios are swapped, a neat trick which allows bi-endian firmware. */ #ifndef TARGET_WORDS_BIGENDIAN { - uint32_t *addr; - for (addr = (uint32_t *)(phys_ram_base + bios_offset); - addr < (uint32_t *)(phys_ram_base + bios_offset + ret); - addr++) { - *addr = bswap32(*addr); + uint32_t *addr = qemu_get_ram_ptr(bios_offset);; + uint32_t *end = addr + bios_size; + while (addr < end) { + bswap32s(addr); } } #endif } - /* If a kernel image has been specified, write a small bootloader - to the flash location. */ - if (kernel_filename) { - env->ram_size = ram_size; - env->kernel_filename = kernel_filename; - env->kernel_cmdline = kernel_cmdline; - env->initrd_filename = initrd_filename; - kernel_entry = load_kernel(env); - env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); - write_bootloader(env, bios_offset, kernel_entry); - } - /* Board ID = 0x420 (Malta Board with CoreLV) XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should map to the board ID. */ - stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420); + stl_phys(0x1fc00010LL, 0x00000420); /* Init internal devices */ cpu_mips_irq_init_cpu(env); cpu_mips_clock_init(env); - cpu_mips_irqctrl_init(); /* Interrupt controller */ /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */ @@ -839,30 +902,46 @@ void mips_malta_init (int ram_size, int vga_ram_size, int boot_device, pci_bus = pci_gt64120_init(i8259); /* Southbridge */ + + if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { + fprintf(stderr, "qemu: too many IDE bus\n"); + exit(1); + } + + for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) { + hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); + } + piix4_devfn = piix4_init(pci_bus, 80); - pci_piix4_ide_init(pci_bus, bs_table, piix4_devfn + 1, i8259); + isa_bus_irqs(i8259); + pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); usb_uhci_piix4_init(pci_bus, piix4_devfn + 2); - smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100); + smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_reserve_irq(9)); eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */ for (i = 0; i < 8; i++) { /* TODO: Populate SPD eeprom data. */ - smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256)); + DeviceState *eeprom; + eeprom = qdev_create((BusState *)smbus, "smbus-eeprom"); + qdev_prop_set_uint32(eeprom, "address", 0x50 + i); + qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256)); + qdev_init(eeprom); } - pit = pit_init(0x40, i8259[0]); + pit = pit_init(0x40, isa_reserve_irq(0)); DMA_init(0); /* Super I/O */ - i8042_init(i8259[1], i8259[12], 0x60); - rtc_state = rtc_init(0x70, i8259[8]); - if (serial_hds[0]) - serial_init(0x3f8, i8259[4], serial_hds[0]); - if (serial_hds[1]) - serial_init(0x2f8, i8259[3], serial_hds[1]); + isa_dev = isa_create_simple("i8042"); + + rtc_state = rtc_init(2000); + serial_init(0x3f8, isa_reserve_irq(4), 115200, serial_hds[0]); + serial_init(0x2f8, isa_reserve_irq(3), 115200, serial_hds[1]); if (parallel_hds[0]) - parallel_init(0x378, i8259[7], parallel_hds[0]); - /* XXX: The floppy controller does not work correctly, something is - probably wrong. - floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */ + parallel_init(0x378, isa_reserve_irq(7), parallel_hds[0]); + for(i = 0; i < MAX_FD; i++) { + dinfo = drive_get(IF_FLOPPY, 0, i); + fd[i] = dinfo ? dinfo->bdrv : NULL; + } + floppy_controller = fdctrl_init_isa(fd); /* Sound card */ #ifdef HAS_AUDIO @@ -870,15 +949,28 @@ void mips_malta_init (int ram_size, int vga_ram_size, int boot_device, #endif /* Network card */ - network_init(pci_bus); + network_init(); /* Optional PCI video card */ - pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, - ram_size, vga_ram_size); + if (cirrus_vga_enabled) { + pci_cirrus_vga_init(pci_bus); + } else if (vmsvga_enabled) { + pci_vmsvga_init(pci_bus); + } else if (std_vga_enabled) { + pci_vga_init(pci_bus, 0, 0); + } } -QEMUMachine mips_malta_machine = { - "malta", - "MIPS Malta Core LV", - mips_malta_init, +static QEMUMachine mips_malta_machine = { + .name = "malta", + .desc = "MIPS Malta Core LV", + .init = mips_malta_init, + .is_default = 1, }; + +static void mips_malta_machine_init(void) +{ + qemu_register_machine(&mips_malta_machine); +} + +machine_init(mips_malta_machine_init);