]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/ppc_prep.c
Introduce TCP live migration protocol
[mirror_qemu.git] / hw / ppc_prep.c
index 7cb92c77fb3a9addb5a680c8ce32c240ea50768b..944935d2988e855c3af17d900a31946f12cd09e2 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "vl.h"
+#include "hw.h"
+#include "nvram.h"
+#include "pc.h"
+#include "fdc.h"
+#include "net.h"
+#include "sysemu.h"
+#include "isa.h"
+#include "pci.h"
+#include "ppc.h"
+#include "boards.h"
+#include "qemu-log.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
 /* SMP is not enabled, for now */
 #define MAX_CPUS 1
 
+#define MAX_IDE_BUS 2
+
 #define BIOS_FILENAME "ppc_rom.bin"
 #define KERNEL_LOAD_ADDR 0x01000000
 #define INITRD_LOAD_ADDR 0x01800000
 
-extern int loglevel;
-extern FILE *logfile;
-
 #if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
 #define DEBUG_PPC_IO
 #endif
@@ -104,7 +113,7 @@ static uint32_t speaker_ioport_read (void *opaque, uint32_t addr)
 static void _PPC_intack_write (void *opaque,
                                target_phys_addr_t addr, uint32_t value)
 {
-    //    printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
+//    printf("%s: 0x" PADDRX " => 0x%08" PRIx32 "\n", __func__, addr, value);
 }
 
 static always_inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
@@ -113,7 +122,7 @@ static always_inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
 
     if (addr == 0xBFFFFFF0)
         retval = pic_intack_read(isa_pic);
-    //   printf("%s: 0x%08x <= %d\n", __func__, addr, retval);
+//   printf("%s: 0x" PADDRX " <= %08" PRIx32 "\n", __func__, addr, retval);
 
     return retval;
 }
@@ -183,7 +192,7 @@ static struct {
 static void PPC_XCSR_writeb (void *opaque,
                              target_phys_addr_t addr, uint32_t value)
 {
-    printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
+    printf("%s: 0x" PADDRX " => 0x%08" PRIx32 "\n", __func__, addr, value);
 }
 
 static void PPC_XCSR_writew (void *opaque,
@@ -192,7 +201,7 @@ static void PPC_XCSR_writew (void *opaque,
 #ifdef TARGET_WORDS_BIGENDIAN
     value = bswap16(value);
 #endif
-    printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
+    printf("%s: 0x" PADDRX " => 0x%08" PRIx32 "\n", __func__, addr, value);
 }
 
 static void PPC_XCSR_writel (void *opaque,
@@ -201,14 +210,14 @@ static void PPC_XCSR_writel (void *opaque,
 #ifdef TARGET_WORDS_BIGENDIAN
     value = bswap32(value);
 #endif
-    printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
+    printf("%s: 0x" PADDRX " => 0x%08" PRIx32 "\n", __func__, addr, value);
 }
 
 static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
 {
     uint32_t retval = 0;
 
-    printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
+    printf("%s: 0x" PADDRX " <= %08" PRIx32 "\n", __func__, addr, retval);
 
     return retval;
 }
@@ -217,7 +226,7 @@ static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
 {
     uint32_t retval = 0;
 
-    printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
+    printf("%s: 0x" PADDRX " <= %08" PRIx32 "\n", __func__, addr, retval);
 #ifdef TARGET_WORDS_BIGENDIAN
     retval = bswap16(retval);
 #endif
@@ -229,7 +238,7 @@ static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
 {
     uint32_t retval = 0;
 
-    printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
+    printf("%s: 0x" PADDRX " <= %08" PRIx32 "\n", __func__, addr, retval);
 #ifdef TARGET_WORDS_BIGENDIAN
     retval = bswap32(retval);
 #endif
@@ -252,6 +261,7 @@ static CPUReadMemoryFunc *PPC_XCSR_read[] = {
 
 /* Fake super-io ports for PREP platform (Intel 82378ZB) */
 typedef struct sysctrl_t {
+    qemu_irq reset_irq;
     m48t59_t *nvram;
     uint8_t state;
     uint8_t syscontrol;
@@ -270,7 +280,8 @@ static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
 {
     sysctrl_t *sysctrl = opaque;
 
-    PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
+    PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
+                   val);
     sysctrl->fake_io[addr - 0x0398] = val;
 }
 
@@ -278,7 +289,7 @@ static uint32_t PREP_io_read (void *opaque, uint32_t addr)
 {
     sysctrl_t *sysctrl = opaque;
 
-    PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE,
+    PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
                    sysctrl->fake_io[addr - 0x0398]);
     return sysctrl->fake_io[addr - 0x0398];
 }
@@ -287,13 +298,16 @@ static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
 {
     sysctrl_t *sysctrl = opaque;
 
-    PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
+    PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n",
+                   addr - PPC_IO_BASE, val);
     switch (addr) {
     case 0x0092:
         /* Special port 92 */
         /* Check soft reset asked */
         if (val & 0x01) {
-            //            cpu_interrupt(first_cpu, PPC_INTERRUPT_RESET);
+            qemu_irq_raise(sysctrl->reset_irq);
+        } else {
+            qemu_irq_lower(sysctrl->reset_irq);
         }
         /* Check LE mode */
         if (val & 0x02) {
@@ -341,8 +355,8 @@ static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
         sysctrl->contiguous_map = val & 0x01;
         break;
     default:
-        printf("ERROR: unaffected IO port write: %04lx => %02x\n",
-               (long)addr, val);
+        printf("ERROR: unaffected IO port write: %04" PRIx32
+               " => %02" PRIx32"\n", addr, val);
         break;
     }
 }
@@ -404,10 +418,11 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
         retval = sysctrl->contiguous_map;
         break;
     default:
-        printf("ERROR: unaffected IO port: %04lx read\n", (long)addr);
+        printf("ERROR: unaffected IO port: %04" PRIx32 " read\n", addr);
         break;
     }
-    PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, retval);
+    PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n",
+                   addr - PPC_IO_BASE, retval);
 
     return retval;
 }
@@ -456,7 +471,7 @@ static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr,
 #ifdef TARGET_WORDS_BIGENDIAN
     value = bswap16(value);
 #endif
-    PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr, value);
+    PPC_IO_DPRINTF("0x" PADDRX " => 0x%08" PRIx32 "\n", addr, value);
     cpu_outw(NULL, addr, value);
 }
 
@@ -470,7 +485,7 @@ static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr)
 #ifdef TARGET_WORDS_BIGENDIAN
     ret = bswap16(ret);
 #endif
-    PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr, ret);
+    PPC_IO_DPRINTF("0x" PADDRX " <= 0x%08" PRIx32 "\n", addr, ret);
 
     return ret;
 }
@@ -484,7 +499,7 @@ static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr,
 #ifdef TARGET_WORDS_BIGENDIAN
     value = bswap32(value);
 #endif
-    PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr, value);
+    PPC_IO_DPRINTF("0x" PADDRX " => 0x%08" PRIx32 "\n", addr, value);
     cpu_outl(NULL, addr, value);
 }
 
@@ -498,7 +513,7 @@ static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr)
 #ifdef TARGET_WORDS_BIGENDIAN
     ret = bswap32(ret);
 #endif
-    PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr, ret);
+    PPC_IO_DPRINTF("0x" PADDRX " <= 0x%08" PRIx32 "\n", addr, ret);
 
     return ret;
 }
@@ -518,23 +533,27 @@ CPUReadMemoryFunc *PPC_prep_io_read[] = {
 #define NVRAM_SIZE        0x2000
 
 /* PowerPC PREP hardware initialisation */
-static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
-                           DisplayState *ds, const char **fd_filename,
-                           int snapshot, const char *kernel_filename,
+static void ppc_prep_init (ram_addr_t ram_size, int vga_ram_size,
+                           const char *boot_device, DisplayState *ds,
+                           const char *kernel_filename,
                            const char *kernel_cmdline,
                            const char *initrd_filename,
                            const char *cpu_model)
 {
-    CPUState *env, *envs[MAX_CPUS];
+    CPUState *env = NULL, *envs[MAX_CPUS];
     char buf[1024];
-    m48t59_t *nvram;
+    nvram_t nvram;
+    m48t59_t *m48t59;
     int PPC_io_memory;
     int linux_boot, i, nb_nics1, bios_size;
     unsigned long bios_offset;
     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
-    ppc_def_t *def;
     PCIBus *pci_bus;
     qemu_irq *i8259;
+    int ppc_boot_device;
+    int index;
+    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    BlockDriverState *fd[MAX_FD];
 
     sysctrl = qemu_mallocz(sizeof(sysctrl_t));
     if (sysctrl == NULL)
@@ -543,20 +562,22 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
     linux_boot = (kernel_filename != NULL);
 
     /* init CPUs */
-    env = cpu_init();
     if (cpu_model == NULL)
         cpu_model = "default";
-    ppc_find_by_name(cpu_model, &def);
-    if (def == NULL) {
-        cpu_abort(env, "Unable to find PowerPC CPU definition\n");
-    }
     for (i = 0; i < smp_cpus; i++) {
-        cpu_ppc_register(env, def);
-        cpu_ppc_reset(env);
-        /* Set time-base frequency to 100 Mhz */
-        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
+            exit(1);
+        }
+        if (env->flags & POWERPC_FLAG_RTC_CLK) {
+            /* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */
+            cpu_ppc_tb_init(env, 7812500UL);
+        } else {
+            /* Set time-base frequency to 100 Mhz */
+            cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+        }
         qemu_register_reset(&cpu_ppc_reset, env);
-        register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
         envs[i] = env;
     }
 
@@ -573,6 +594,9 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
         cpu_abort(env, "qemu: could not load PPC PREP bios '%s'\n", buf);
         exit(1);
     }
+    if (env->nip < 0xFFF80000 && bios_size < 0x00100000) {
+        cpu_abort(env, "PowerPC 601 / 620 / 970 need a 1MB BIOS\n");
+    }
     bios_size = (bios_size + 0xfff) & ~0xfff;
     cpu_register_physical_memory((uint32_t)(-bios_size),
                                  bios_size, bios_offset | IO_MEM_ROM);
@@ -600,12 +624,24 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
             initrd_base = 0;
             initrd_size = 0;
         }
-        boot_device = 'm';
+        ppc_boot_device = 'm';
     } else {
         kernel_base = 0;
         kernel_size = 0;
         initrd_base = 0;
         initrd_size = 0;
+        ppc_boot_device = '\0';
+        /* For now, OHW cannot boot from the network. */
+        for (i = 0; boot_device[i] != '\0'; i++) {
+            if (boot_device[i] >= 'a' && boot_device[i] <= 'f') {
+                ppc_boot_device = boot_device[i];
+                break;
+            }
+        }
+        if (ppc_boot_device == '\0') {
+            fprintf(stderr, "No valid boot device for Mac99 machine\n");
+            exit(1);
+        }
     }
 
     isa_mem_base = 0xc0000000;
@@ -628,7 +664,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
     //    pit = pit_init(0x40, i8259[0]);
     rtc_init(0x70, i8259[8]);
 
-    serial_init(0x3f8, i8259[4], serial_hds[0]);
+    serial_init(0x3f8, i8259[4], 115200, serial_hds[0]);
     nb_nics1 = nb_nics;
     if (nb_nics1 > NE2000_NB_MAX)
         nb_nics1 = NE2000_NB_MAX;
@@ -641,21 +677,43 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
         }
     }
 
-    for(i = 0; i < 2; i++) {
+    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++) {
+        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+        if (index != -1)
+            hd[i] = drives_table[index].bdrv;
+        else
+            hd[i] = NULL;
+    }
+
+    for(i = 0; i < MAX_IDE_BUS; i++) {
         isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
-                     bs_table[2 * i], bs_table[2 * i + 1]);
+                     hd[2 * i],
+                    hd[2 * i + 1]);
     }
     i8042_init(i8259[1], i8259[12], 0x60);
     DMA_init(1);
     //    AUD_init();
     //    SB16_init();
 
-    fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table);
+    for(i = 0; i < MAX_FD; i++) {
+        index = drive_get_index(IF_FLOPPY, 0, i);
+        if (index != -1)
+            fd[i] = drives_table[index].bdrv;
+        else
+            fd[i] = NULL;
+    }
+    fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
 
     /* Register speaker port */
     register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
     register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
     /* Register fake IO ports for PREP */
+    sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
     register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
     register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
     /* System control ports */
@@ -678,13 +736,16 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
         usb_ohci_init_pci(pci_bus, 3, -1);
     }
 
-    nvram = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
-    if (nvram == NULL)
+    m48t59 = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
+    if (m48t59 == NULL)
         return;
-    sysctrl->nvram = nvram;
+    sysctrl->nvram = m48t59;
 
     /* Initialise NVRAM */
-    PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
+    nvram.opaque = m48t59;
+    nvram.read_fn = &m48t59_read;
+    nvram.write_fn = &m48t59_write;
+    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "PREP", ram_size, ppc_boot_device,
                          kernel_base, kernel_size,
                          kernel_cmdline,
                          initrd_base, initrd_size,
@@ -697,7 +758,9 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
 }
 
 QEMUMachine prep_machine = {
-    "prep",
-    "PowerPC PREP platform",
-    ppc_prep_init,
+    .name = "prep",
+    .desc = "PowerPC PREP platform",
+    .init = ppc_prep_init,
+    .ram_require = BIOS_SIZE + VGA_RAM_SIZE,
+    .max_cpus = 1,
 };