]> git.proxmox.com Git - qemu.git/blobdiff - hw/mips_malta.c
Merge remote-tracking branch 'spice/spice.v39' into staging
[qemu.git] / hw / mips_malta.c
index 748c0789703b663209fe9430d26e0236c6524f0c..ed2a483c9bdd587f0186a1f501ae4f723fdbd9b5 100644 (file)
 #include "block.h"
 #include "flash.h"
 #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 "audio/audio.h"
+#include "arch_init.h"
 #include "boards.h"
 #include "qemu-log.h"
 #include "mips-bios.h"
 #include "ide.h"
 #include "loader.h"
 #include "elf.h"
+#include "mc146818rtc.h"
+#include "blockdev.h"
 
 //#define DEBUG_BOARD_INIT
 
-#ifdef TARGET_MIPS64
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
-#else
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
-#endif
-
-#define ENVP_ADDR (int32_t)0x80002000
-#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
-
+#define ENVP_ADDR              0x80002000l
 #define ENVP_NB_ENTRIES                16
 #define ENVP_ENTRY_SIZE                256
 
@@ -71,7 +68,7 @@ typedef struct {
     SerialState *uart;
 } MaltaFPGAState;
 
-static PITState *pit;
+static ISADevice *pit;
 
 static struct _loaderparams {
     int ram_size;
@@ -117,7 +114,7 @@ static void malta_fpga_update_display(void *opaque)
 #  define logout(fmt, ...) ((void)0)
 #endif
 
-struct eeprom24c0x {
+struct _eeprom24c0x_t {
   uint8_t tick;
   uint8_t address;
   uint8_t command;
@@ -129,9 +126,9 @@ struct eeprom24c0x {
   uint8_t contents[256];
 };
 
-typedef struct eeprom24c0x a_eeprom24c0x;
+typedef struct _eeprom24c0x_t eeprom24c0x_t;
 
-static a_eeprom24c0x eeprom = {
+static eeprom24c0x_t eeprom = {
     .contents = {
         /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
         /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
@@ -217,7 +214,7 @@ static void eeprom24c0x_write(int scl, int sda)
     eeprom.sda = sda;
 }
 
-static uint32_t malta_fpga_readl(void *opaque, a_target_phys_addr addr)
+static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
 {
     MaltaFPGAState *s = opaque;
     uint32_t val = 0;
@@ -230,7 +227,7 @@ static uint32_t malta_fpga_readl(void *opaque, a_target_phys_addr addr)
     /* SWITCH Register */
     case 0x00200:
         val = 0x00000000;              /* All switches closed */
-       break;
+        break;
 
     /* STATUS Register */
     case 0x00208:
@@ -297,14 +294,14 @@ static uint32_t malta_fpga_readl(void *opaque, a_target_phys_addr addr)
     default:
 #if 0
         printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
-               addr);
+                addr);
 #endif
         break;
     }
     return val;
 }
 
-static void malta_fpga_writel(void *opaque, a_target_phys_addr addr,
+static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
                               uint32_t val)
 {
     MaltaFPGAState *s = opaque;
@@ -384,7 +381,7 @@ static void malta_fpga_writel(void *opaque, a_target_phys_addr addr,
     default:
 #if 0
         printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
-               addr);
+                addr);
 #endif
         break;
     }
@@ -431,7 +428,7 @@ static void malta_fpga_led_init(CharDriverState *chr)
     qemu_chr_printf(chr, "+--------+\r\n");
 }
 
-static MaltaFPGAState *malta_fpga_init(a_target_phys_addr base, qemu_irq uart_irq, CharDriverState *uart_chr)
+static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
 {
     MaltaFPGAState *s;
     int malta;
@@ -439,7 +436,8 @@ static MaltaFPGAState *malta_fpga_init(a_target_phys_addr base, qemu_irq uart_ir
     s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
 
     malta = cpu_register_io_memory(malta_fpga_read,
-                                   malta_fpga_write, s);
+                                   malta_fpga_write, s,
+                                   DEVICE_NATIVE_ENDIAN);
 
     cpu_register_physical_memory(base, 0x900, malta);
     /* 0xa00 is less than a page, so will still get the right offsets.  */
@@ -447,7 +445,11 @@ static MaltaFPGAState *malta_fpga_init(a_target_phys_addr base, qemu_irq uart_ir
 
     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);
+#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
 
     malta_fpga_reset(s);
     qemu_register_reset(malta_fpga_reset, s);
@@ -455,27 +457,6 @@ static MaltaFPGAState *malta_fpga_init(a_target_phys_addr base, qemu_irq uart_ir
     return s;
 }
 
-/* Audio support */
-#ifdef HAS_AUDIO
-static 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) {
-        for (c = soundhw; c->name; ++c) {
-            if (c->enabled) {
-                c->init.init_pci(pci_bus);
-            }
-        }
-    }
-}
-#endif
-
 /* Network support */
 static void network_init(void)
 {
@@ -489,7 +470,7 @@ static void network_init(void)
             /* The malta board has a PCNet card using PCI SLOT 11 */
             default_devaddr = "0b";
 
-        pci_nic_init(nd, "pcnet", default_devaddr);
+        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
     }
 }
 
@@ -655,41 +636,38 @@ static void write_bootloader (CPUState *env, uint8_t *base,
 
 }
 
-static void prom_set(int index, const char *string, ...)
+static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
+                                        const char *string, ...)
 {
-    char buf[ENVP_ENTRY_SIZE];
-    a_target_phys_addr p;
     va_list ap;
     int32_t table_addr;
 
     if (index >= ENVP_NB_ENTRIES)
         return;
 
-    p = ENVP_ADDR + VIRT_TO_PHYS_ADDEND + index * 4;
-
     if (string == NULL) {
-        stl_phys(p, 0);
+        prom_buf[index] = 0;
         return;
     }
 
-    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES
-                 + index * ENVP_ENTRY_SIZE;
-    stl_phys(p, table_addr);
+    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
 
     va_start(ap, string);
-    vsnprintf(buf, ENVP_ENTRY_SIZE, string, ap);
+    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
     va_end(ap);
-    pstrcpy_targphys(table_addr + VIRT_TO_PHYS_ADDEND, ENVP_ENTRY_SIZE, buf);
 }
 
 /* Kernel */
-static int64_t load_kernel (CPUState *env)
+static int64_t load_kernel (void)
 {
-    int64_t kernel_entry, kernel_low, kernel_high;
-    int index = 0;
+    int64_t kernel_entry, kernel_high;
     long initrd_size;
-    a_ram_addr initrd_offset;
+    ram_addr_t initrd_offset;
     int big_endian;
+    uint32_t *prom_buf;
+    long prom_size;
+    int prom_index = 0;
 
 #ifdef TARGET_WORDS_BIGENDIAN
     big_endian = 1;
@@ -697,9 +675,9 @@ static int64_t load_kernel (CPUState *env)
     big_endian = 0;
 #endif
 
-    if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
-                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
-                 (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1) < 0) {
+    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
+                 big_endian, ELF_MACHINE, 1) < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
                 loaderparams.kernel_filename);
         exit(1);
@@ -729,21 +707,27 @@ static int64_t load_kernel (CPUState *env)
         }
     }
 
-    /* Store command line.  */
-    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,
+    /* Setup prom parameters. */
+    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
+    prom_buf = qemu_malloc(prom_size);
+
+    prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
+    if (initrd_size > 0) {
+        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
                  loaderparams.kernel_cmdline);
-    else
-        prom_set(index++, loaderparams.kernel_cmdline);
+    } else {
+        prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
+    }
+
+    prom_set(prom_buf, prom_index++, "memsize");
+    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
+    prom_set(prom_buf, prom_index++, "modetty0");
+    prom_set(prom_buf, prom_index++, "38400n8r");
+    prom_set(prom_buf, prom_index++, NULL);
 
-    /* Setup minimum environment variables */
-    prom_set(index++, "memsize");
-    prom_set(index++, "%i", loaderparams.ram_size);
-    prom_set(index++, "modetty0");
-    prom_set(index++, "38400n8r");
-    prom_set(index++, NULL);
+    rom_add_blob_fixed("prom", prom_buf, prom_size,
+                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
 
     return kernel_entry;
 }
@@ -753,42 +737,47 @@ static void main_cpu_reset(void *opaque)
     CPUState *env = opaque;
     cpu_reset(env);
 
-    /* The bootload does not need to be rewritten as it is located in a
+    /* The bootloader 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 (loaderparams.kernel_filename) {
         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
-        load_kernel (env);
+    }
+}
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUState *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
     }
 }
 
 static
-void mips_malta_init (a_ram_addr ram_size,
+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 *filename;
-    a_ram_addr ram_offset;
-    a_ram_addr bios_offset;
+    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;
-    a_fdctrl *floppy_controller;
-    MaltaFPGAState *malta_fpga;
     qemu_irq *i8259;
+    qemu_irq *cpu_exit_irq;
     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];
+    DriveInfo *fd[MAX_FD];
     int fl_idx = 0;
     int fl_sectors = 0;
+    int be;
 
     /* Make sure the first 3 serial ports are associated with a device. */
     for(i = 0; i < 3; i++) {
@@ -821,8 +810,8 @@ void mips_malta_init (a_ram_addr ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
 
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
@@ -833,8 +822,13 @@ void mips_malta_init (a_ram_addr ram_size,
     cpu_register_physical_memory(0x1fc00000LL,
                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
 
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
     /* FPGA */
-    malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
+    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) {
@@ -843,8 +837,7 @@ void mips_malta_init (a_ram_addr 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));
+        kernel_entry = load_kernel();
         write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
     } else {
         dinfo = drive_get(IF_PFLASH, 0, fl_idx);
@@ -860,7 +853,7 @@ void mips_malta_init (a_ram_addr ram_size,
 #endif
             pflash_cfi01_register(0x1e000000LL, bios_offset,
                                   dinfo->bdrv, 65536, fl_sectors,
-                                  4, 0x0000, 0x0000, 0x0000, 0x0000);
+                                  4, 0x0000, 0x0000, 0x0000, 0x0000, be);
             fl_idx++;
         } else {
             /* Load a BIOS image. */
@@ -897,7 +890,7 @@ void mips_malta_init (a_ram_addr ram_size,
     /* Board ID = 0x420 (Malta Board with CoreLV)
        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
        map to the board ID. */
-    stl_phys(0x1fc00010LL, 0x00000420);
+    stl_p(qemu_get_ram_ptr(bios_offset) + 0x10, 0x00000420);
 
     /* Init internal devices */
     cpu_mips_irq_init_cpu(env);
@@ -908,54 +901,38 @@ void mips_malta_init (a_ram_addr ram_size,
     i8259 = i8259_init(env->irq[2]);
 
     /* Northbridge */
-    pci_bus = pci_gt64120_init(i8259);
+    pci_bus = gt64120_register(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);
-    }
+    ide_drive_get(hd, MAX_IDE_BUS);
 
     piix4_devfn = piix4_init(pci_bus, 80);
     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, 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.  */
-        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, isa_reserve_irq(0));
-    DMA_init(0);
+    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(9),
+                          NULL, NULL, 0);
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(smbus, 8, NULL, 0);
+    pit = pit_init(0x40, 0);
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
 
     /* Super I/O */
-    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]);
+    isa_create_simple("i8042");
+
+    rtc_init(2000, NULL);
+    serial_isa_init(0, serial_hds[0]);
+    serial_isa_init(1, serial_hds[1]);
     if (parallel_hds[0])
-        parallel_init(0x378, isa_reserve_irq(7), parallel_hds[0]);
+        parallel_init(0, parallel_hds[0]);
     for(i = 0; i < MAX_FD; i++) {
-        dinfo = drive_get(IF_FLOPPY, 0, i);
-        fd[i] = dinfo ? dinfo->bdrv : NULL;
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
     }
-    floppy_controller = fdctrl_init_isa(fd);
+    fdctrl_init_isa(fd);
 
     /* Sound card */
-#ifdef HAS_AUDIO
-    audio_init(pci_bus);
-#endif
+    audio_init(NULL, pci_bus);
 
     /* Network card */
     network_init();
@@ -964,9 +941,13 @@ void mips_malta_init (a_ram_addr ram_size,
     if (cirrus_vga_enabled) {
         pci_cirrus_vga_init(pci_bus);
     } else if (vmsvga_enabled) {
-        pci_vmsvga_init(pci_bus);
+        if (!pci_vmsvga_init(pci_bus)) {
+            fprintf(stderr, "Warning: vmware_vga not available,"
+                    " using standard VGA instead\n");
+            pci_vga_init(pci_bus);
+        }
     } else if (std_vga_enabled) {
-        pci_vga_init(pci_bus, 0, 0);
+        pci_vga_init(pci_bus);
     }
 }