qdev scsi bus infrastructure
[qemu] / hw / ppc_prep.c
index 1d6634c..b98c6c2 100644 (file)
@@ -31,6 +31,7 @@
 #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
 
 #if defined (HARD_DEBUG_PPC_IO)
-#define PPC_IO_DPRINTF(fmt, args...)                     \
+#define PPC_IO_DPRINTF(fmt, ...)                         \
 do {                                                     \
-    if (loglevel & CPU_LOG_IOPORT) {                     \
-        fprintf(logfile, "%s: " fmt, __func__ , ##args); \
+    if (qemu_loglevel_mask(CPU_LOG_IOPORT)) {            \
+        qemu_log("%s: " fmt, __func__ , ## __VA_ARGS__); \
     } else {                                             \
-        printf("%s : " fmt, __func__ , ##args);          \
+        printf("%s : " fmt, __func__ , ## __VA_ARGS__);  \
     }                                                    \
 } while (0)
 #elif defined (DEBUG_PPC_IO)
-#define PPC_IO_DPRINTF(fmt, args...)                     \
-do {                                                     \
-    if (loglevel & CPU_LOG_IOPORT) {                     \
-        fprintf(logfile, "%s: " fmt, __func__ , ##args); \
-    }                                                    \
-} while (0)
+#define PPC_IO_DPRINTF(fmt, ...) qemu_log_mask(CPU_LOG_IOPORT, ## __VA_ARGS__)
 #else
-#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
+#define PPC_IO_DPRINTF(fmt, ...) do { } while (0)
 #endif
 
 /* Constants for devices init */
@@ -84,9 +79,11 @@ static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
 /* ISA IO ports bridge */
 #define PPC_IO_BASE 0x80000000
 
+#if 0
 /* Speaker port 0x61 */
-int speaker_data_on;
-int dummy_refresh_clock;
+static int speaker_data_on;
+static int dummy_refresh_clock;
+#endif
 
 static void speaker_ioport_write (void *opaque, uint32_t addr, uint32_t val)
 {
@@ -113,16 +110,16 @@ 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)
 {
     uint32_t retval = 0;
 
-    if (addr == 0xBFFFFFF0)
+    if ((addr & 0xf) == 0)
         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;
 }
@@ -192,7 +189,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,
@@ -201,7 +198,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,
@@ -210,14 +207,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;
 }
@@ -226,7 +223,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
@@ -238,7 +235,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
@@ -280,7 +277,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;
 }
 
@@ -288,7 +286,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];
 }
@@ -297,7 +295,8 @@ 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 */
@@ -353,8 +352,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;
     }
 }
@@ -416,10 +415,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;
 }
@@ -468,7 +468,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);
 }
 
@@ -482,7 +482,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;
 }
@@ -496,7 +496,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);
 }
 
@@ -510,18 +510,18 @@ 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;
 }
 
-CPUWriteMemoryFunc *PPC_prep_io_write[] = {
+static CPUWriteMemoryFunc *PPC_prep_io_write[] = {
     &PPC_prep_io_writeb,
     &PPC_prep_io_writew,
     &PPC_prep_io_writel,
 };
 
-CPUReadMemoryFunc *PPC_prep_io_read[] = {
+static CPUReadMemoryFunc *PPC_prep_io_read[] = {
     &PPC_prep_io_readb,
     &PPC_prep_io_readw,
     &PPC_prep_io_readl,
@@ -530,8 +530,8 @@ 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,
-                           const char *boot_device, DisplayState *ds,
+static void ppc_prep_init (ram_addr_t ram_size,
+                           const char *boot_device,
                            const char *kernel_filename,
                            const char *kernel_cmdline,
                            const char *initrd_filename,
@@ -543,15 +543,16 @@ static void ppc_prep_init (int ram_size, int vga_ram_size,
     m48t59_t *m48t59;
     int PPC_io_memory;
     int linux_boot, i, nb_nics1, bios_size;
-    unsigned long bios_offset;
+    ram_addr_t ram_offset, bios_offset;
     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
     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)
-        return;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -564,51 +565,59 @@ static void ppc_prep_init (int ram_size, int vga_ram_size,
             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
             exit(1);
         }
-        /* Set time-base frequency to 100 Mhz */
-        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+        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;
     }
 
     /* allocate RAM */
-    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+    ram_offset = qemu_ram_alloc(ram_size);
+    cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = ram_size + vga_ram_size;
+    bios_offset = qemu_ram_alloc(BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = BIOS_FILENAME;
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
-    bios_size = load_image(buf, phys_ram_base + bios_offset);
+    bios_size = get_image_size(buf);
+    if (bios_size > 0 && bios_size <= BIOS_SIZE) {
+        target_phys_addr_t bios_addr;
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        bios_addr = (uint32_t)(-bios_size);
+        cpu_register_physical_memory(bios_addr, bios_size,
+                                     bios_offset | IO_MEM_ROM);
+        bios_size = load_image_targphys(buf, bios_addr, bios_size);
+    }
     if (bios_size < 0 || bios_size > BIOS_SIZE) {
-        cpu_abort(env, "qemu: could not load PPC PREP bios '%s'\n", buf);
-        exit(1);
+        hw_error("qemu: could not load PPC PREP bios '%s'\n", buf);
     }
     if (env->nip < 0xFFF80000 && bios_size < 0x00100000) {
-        cpu_abort(env, "PowerPC 601 / 620 / 970 need a 1MB BIOS\n");
+        hw_error("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);
 
     if (linux_boot) {
         kernel_base = KERNEL_LOAD_ADDR;
         /* now we can load the kernel */
-        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
+        kernel_size = load_image_targphys(kernel_filename, kernel_base,
+                                          ram_size - kernel_base);
         if (kernel_size < 0) {
-            cpu_abort(env, "qemu: could not load kernel '%s'\n",
-                      kernel_filename);
+            hw_error("qemu: could not load kernel '%s'\n", kernel_filename);
             exit(1);
         }
         /* load initrd */
         if (initrd_filename) {
             initrd_base = INITRD_LOAD_ADDR;
-            initrd_size = load_image(initrd_filename,
-                                     phys_ram_base + initrd_base);
+            initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                                              ram_size - initrd_base);
             if (initrd_size < 0) {
-                cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
+                hw_error("qemu: could not load initial ram disk '%s'\n",
                           initrd_filename);
-                exit(1);
             }
         } else {
             initrd_base = 0;
@@ -636,8 +645,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size,
 
     isa_mem_base = 0xc0000000;
     if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
-        cpu_abort(env, "Only 6xx bus is supported on PREP machine\n");
-        exit(1);
+        hw_error("Only 6xx bus is supported on PREP machine\n");
     }
     i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
     pci_bus = pci_prep_init(i8259);
@@ -648,35 +656,56 @@ static void ppc_prep_init (int ram_size, int vga_ram_size,
     cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
 
     /* init basic PC hardware */
-    pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size,
-                 vga_ram_size, 0, 0);
+    pci_vga_init(pci_bus, 0, 0);
     //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
     //    pit = pit_init(0x40, i8259[0]);
-    rtc_init(0x70, i8259[8]);
+    rtc_init(0x70, i8259[8], 2000);
 
-    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;
     for(i = 0; i < nb_nics1; i++) {
-        if (nd_table[i].model == NULL
-            || strcmp(nd_table[i].model, "ne2k_isa") == 0) {
+        if (nd_table[i].model == NULL) {
+           nd_table[i].model = "ne2k_isa";
+        }
+        if (strcmp(nd_table[i].model, "ne2k_isa") == 0) {
             isa_ne2000_init(ne2000_io[i], i8259[ne2000_irq[i]], &nd_table[i]);
         } else {
-            pci_nic_init(pci_bus, &nd_table[i], -1);
+            pci_nic_init(pci_bus, &nd_table[i], -1, "ne2k_pci");
         }
     }
 
-    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);
@@ -727,7 +756,8 @@ static void ppc_prep_init (int ram_size, int vga_ram_size,
 }
 
 QEMUMachine prep_machine = {
-    "prep",
-    "PowerPC PREP platform",
-    ppc_prep_init,
+    .name = "prep",
+    .desc = "PowerPC PREP platform",
+    .init = ppc_prep_init,
+    .max_cpus = MAX_CPUS,
 };