#include "mips.h"
#include "mips_cpudevs.h"
#include "pci.h"
-#include "usb-uhci.h"
#include "vmware_vga.h"
#include "qemu-char.h"
#include "sysemu.h"
#include "loader.h"
#include "elf.h"
#include "mc146818rtc.h"
+#include "i8254.h"
#include "blockdev.h"
#include "exec-memory.h"
+#include "sysbus.h" /* SysBusDevice */
//#define DEBUG_BOARD_INIT
#define MAX_IDE_BUS 2
typedef struct {
+ MemoryRegion iomem;
+ MemoryRegion iomem_lo; /* 0 - 0x900 */
+ MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
uint32_t leds;
uint32_t brk;
uint32_t gpout;
SerialState *uart;
} MaltaFPGAState;
+typedef struct {
+ SysBusDevice busdev;
+ qemu_irq *i8259;
+} MaltaState;
+
static ISADevice *pit;
static struct _loaderparams {
eeprom.sda = sda;
}
-static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t malta_fpga_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
MaltaFPGAState *s = opaque;
uint32_t val = 0;
return val;
}
-static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
- uint32_t val)
+static void malta_fpga_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned size)
{
MaltaFPGAState *s = opaque;
uint32_t saddr;
/* ASCIIWORD Register */
case 0x00410:
- snprintf(s->display_text, 9, "%08X", val);
+ snprintf(s->display_text, 9, "%08X", (uint32_t)val);
malta_fpga_update_display(s);
break;
}
}
-static CPUReadMemoryFunc * const malta_fpga_read[] = {
- malta_fpga_readl,
- malta_fpga_readl,
- malta_fpga_readl
-};
-
-static CPUWriteMemoryFunc * const malta_fpga_write[] = {
- malta_fpga_writel,
- malta_fpga_writel,
- malta_fpga_writel
+static const MemoryRegionOps malta_fpga_ops = {
+ .read = malta_fpga_read,
+ .write = malta_fpga_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
static void malta_fpga_reset(void *opaque)
qemu_chr_fe_printf(chr, "+--------+\r\n");
}
-static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
+static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
+ target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
{
MaltaFPGAState *s;
- int malta;
s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
- malta = cpu_register_io_memory(malta_fpga_read,
- malta_fpga_write, s,
- DEVICE_NATIVE_ENDIAN);
+ memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
+ "malta-fpga", 0x100000);
+ memory_region_init_alias(&s->iomem_lo, "malta-fpga",
+ &s->iomem, 0, 0x900);
+ memory_region_init_alias(&s->iomem_hi, "malta-fpga",
+ &s->iomem, 0xa00, 0x10000-0xa00);
- 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);
+ memory_region_add_subregion(address_space, base, &s->iomem_lo);
+ memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
-#ifdef TARGET_WORDS_BIGENDIAN
- s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1, 1);
-#else
- s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1, 0);
-#endif
+ s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
+ 230400, uart_chr, DEVICE_NATIVE_ENDIAN);
malta_fpga_reset(s);
qemu_register_reset(malta_fpga_reset, s);
a3 - RAM size in bytes
*/
-static void write_bootloader (CPUState *env, uint8_t *base,
+static void write_bootloader (CPUMIPSState *env, uint8_t *base,
int64_t kernel_entry)
{
uint32_t *p;
return kernel_entry;
}
-static void malta_mips_config(CPUState *env)
+static void malta_mips_config(CPUMIPSState *env)
{
env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
((smp_cpus * env->nr_threads - 1) << CP0MVPC0_PTC);
static void main_cpu_reset(void *opaque)
{
- CPUState *env = opaque;
- cpu_reset(env);
+ CPUMIPSState *env = opaque;
+ cpu_state_reset(env);
/* The bootloader does not need to be rewritten as it is located in a
read only location. The kernel location and the arguments table
static void cpu_request_exit(void *opaque, int irq, int level)
{
- CPUState *env = cpu_single_env;
+ CPUMIPSState *env = cpu_single_env;
if (env && level) {
cpu_exit(env);
{
char *filename;
pflash_t *fl;
- ram_addr_t ram_offset;
MemoryRegion *system_memory = get_system_memory();
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
target_long bios_size;
int64_t kernel_entry;
PCIBus *pci_bus;
- CPUState *env;
- qemu_irq *i8259;
+ ISABus *isa_bus;
+ CPUMIPSState *env;
+ qemu_irq *isa_irq;
qemu_irq *cpu_exit_irq;
int piix4_devfn;
i2c_bus *smbus;
int fl_sectors = 0;
int be;
+ DeviceState *dev = qdev_create(NULL, "mips-malta");
+ MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
+
+ qdev_init_nofail(dev);
+
/* Make sure the first 3 serial ports are associated with a device. */
for(i = 0; i < 3; i++) {
if (!serial_hds[i]) {
((unsigned int)ram_size / (1 << 20)));
exit(1);
}
- ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
-
- cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
+ memory_region_init_ram(ram, "mips_malta.ram", ram_size);
+ vmstate_register_ram_global(ram);
+ memory_region_add_subregion(system_memory, 0, ram);
#ifdef TARGET_WORDS_BIGENDIAN
be = 1;
be = 0;
#endif
/* FPGA */
- malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
+ malta_fpga_init(system_memory, 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. */
bios = g_new(MemoryRegion, 1);
- memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
+ memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
+ vmstate_register_ram_global(bios);
memory_region_set_readonly(bios, true);
memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
/* Map the bios at two physical locations, as on the real board. */
fl_idx++;
} else {
bios = g_new(MemoryRegion, 1);
- memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
+ memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
+ vmstate_register_ram_global(bios);
memory_region_set_readonly(bios, true);
memory_region_init_alias(bios_alias, "bios.1fc",
bios, 0, BIOS_SIZE);
uint32_t *end = addr + bios_size;
while (addr < end) {
bswap32s(addr);
+ addr++;
}
}
#endif
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
- /* Interrupt controller */
- /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
- i8259 = i8259_init(env->irq[2]);
+ /*
+ * We have a circular dependency problem: pci_bus depends on isa_irq,
+ * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
+ * on piix4, and piix4 depends on pci_bus. To stop the cycle we have
+ * qemu_irq_proxy() adds an extra bit of indirection, allowing us
+ * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
+ */
+ isa_irq = qemu_irq_proxy(&s->i8259, 16);
/* Northbridge */
- pci_bus = gt64120_register(i8259);
+ pci_bus = gt64120_register(isa_irq);
/* Southbridge */
ide_drive_get(hd, MAX_IDE_BUS);
- piix4_devfn = piix4_init(pci_bus, 80);
- isa_bus_irqs(i8259);
+ piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
+
+ /* Interrupt controller */
+ /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
+ s->i8259 = i8259_init(isa_bus, env->irq[2]);
+
+ isa_bus_irqs(isa_bus, s->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, isa_get_irq(9),
- NULL, NULL, 0);
+ pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
+ smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
+ isa_get_irq(NULL, 9), NULL, 0);
/* TODO: Populate SPD eeprom data. */
smbus_eeprom_init(smbus, 8, NULL, 0);
- pit = pit_init(0x40, 0);
+ pit = pit_init(isa_bus, 0x40, 0, NULL);
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
DMA_init(0, cpu_exit_irq);
/* Super I/O */
- isa_create_simple("i8042");
+ isa_create_simple(isa_bus, "i8042");
- rtc_init(2000, NULL);
- serial_isa_init(0, serial_hds[0]);
- serial_isa_init(1, serial_hds[1]);
+ rtc_init(isa_bus, 2000, NULL);
+ serial_isa_init(isa_bus, 0, serial_hds[0]);
+ serial_isa_init(isa_bus, 1, serial_hds[1]);
if (parallel_hds[0])
- parallel_init(0, parallel_hds[0]);
+ parallel_init(isa_bus, 0, parallel_hds[0]);
for(i = 0; i < MAX_FD; i++) {
fd[i] = drive_get(IF_FLOPPY, 0, i);
}
- fdctrl_init_isa(fd);
+ fdctrl_init_isa(isa_bus, fd);
/* Sound card */
- audio_init(NULL, pci_bus);
+ audio_init(isa_bus, pci_bus);
/* Network card */
network_init();
if (cirrus_vga_enabled) {
pci_cirrus_vga_init(pci_bus);
} else if (vmsvga_enabled) {
- if (!pci_vmsvga_init(pci_bus)) {
- fprintf(stderr, "Warning: vmware_vga not available,"
- " using standard VGA instead\n");
- pci_vga_init(pci_bus);
- }
+ pci_vmsvga_init(pci_bus);
} else if (std_vga_enabled) {
pci_vga_init(pci_bus);
}
}
+static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
+{
+ return 0;
+}
+
+static void mips_malta_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mips_malta_sysbus_device_init;
+}
+
+static TypeInfo mips_malta_device = {
+ .name = "mips-malta",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MaltaState),
+ .class_init = mips_malta_class_init,
+};
+
static QEMUMachine mips_malta_machine = {
.name = "malta",
.desc = "MIPS Malta Core LV",
.is_default = 1,
};
+static void mips_malta_register_types(void)
+{
+ type_register_static(&mips_malta_device);
+}
+
static void mips_malta_machine_init(void)
{
qemu_register_machine(&mips_malta_machine);
}
+type_init(mips_malta_register_types)
machine_init(mips_malta_machine_init);