j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 1 | /* |
aurel32 | 4d7ca41 | 2009-01-07 23:38:59 +0000 | [diff] [blame] | 2 | * QEMU OldWorld PowerMac (currently ~G3 Beige) hardware System Emulator |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright (c) 2004-2007 Fabrice Bellard |
| 5 | * Copyright (c) 2007 Jocelyn Mayer |
| 6 | * |
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 8 | * of this software and associated documentation files (the "Software"), to deal |
| 9 | * in the Software without restriction, including without limitation the rights |
| 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 11 | * copies of the Software, and to permit persons to whom the Software is |
| 12 | * furnished to do so, subject to the following conditions: |
| 13 | * |
| 14 | * The above copyright notice and this permission notice shall be included in |
| 15 | * all copies or substantial portions of the Software. |
| 16 | * |
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 23 | * THE SOFTWARE. |
| 24 | */ |
pbrook | 87ecb68 | 2007-11-17 17:14:51 +0000 | [diff] [blame] | 25 | #include "hw.h" |
| 26 | #include "ppc.h" |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 27 | #include "ppc_mac.h" |
aurel32 | 28ce5ce | 2009-01-30 20:39:32 +0000 | [diff] [blame] | 28 | #include "mac_dbdma.h" |
pbrook | 87ecb68 | 2007-11-17 17:14:51 +0000 | [diff] [blame] | 29 | #include "nvram.h" |
| 30 | #include "pc.h" |
| 31 | #include "sysemu.h" |
| 32 | #include "net.h" |
| 33 | #include "isa.h" |
| 34 | #include "pci.h" |
| 35 | #include "boards.h" |
blueswir1 | 271dd5e | 2008-12-24 20:29:16 +0000 | [diff] [blame] | 36 | #include "fw_cfg.h" |
blueswir1 | 7fa9ae1 | 2009-01-12 17:40:23 +0000 | [diff] [blame] | 37 | #include "escc.h" |
Gerd Hoffmann | 977e124 | 2009-08-20 15:22:20 +0200 | [diff] [blame] | 38 | #include "ide.h" |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 39 | |
ths | e4bcb14 | 2007-12-02 04:51:10 +0000 | [diff] [blame] | 40 | #define MAX_IDE_BUS 2 |
aurel32 | a748ab6 | 2008-12-20 23:40:35 +0000 | [diff] [blame] | 41 | #define VGA_BIOS_SIZE 65536 |
blueswir1 | 271dd5e | 2008-12-24 20:29:16 +0000 | [diff] [blame] | 42 | #define CFG_ADDR 0xf0000510 |
| 43 | |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 44 | /* temporary frame buffer OSI calls for the video.x driver. The right |
| 45 | solution is to modify the driver to use VGA PCI I/Os */ |
| 46 | /* XXX: to be removed. This is no way related to emulation */ |
| 47 | static int vga_osi_call (CPUState *env) |
| 48 | { |
| 49 | static int vga_vbl_enabled; |
| 50 | int linesize; |
| 51 | |
Blue Swirl | b11ebf6 | 2009-08-16 11:54:37 +0000 | [diff] [blame] | 52 | #if 0 |
| 53 | printf("osi_call R5=%016" PRIx64 "\n", ppc_dump_gpr(env, 5)); |
| 54 | #endif |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 55 | |
| 56 | /* same handler as PearPC, coming from the original MOL video |
| 57 | driver. */ |
| 58 | switch(env->gpr[5]) { |
| 59 | case 4: |
| 60 | break; |
| 61 | case 28: /* set_vmode */ |
| 62 | if (env->gpr[6] != 1 || env->gpr[7] != 0) |
| 63 | env->gpr[3] = 1; |
| 64 | else |
| 65 | env->gpr[3] = 0; |
| 66 | break; |
| 67 | case 29: /* get_vmode_info */ |
| 68 | if (env->gpr[6] != 0) { |
| 69 | if (env->gpr[6] != 1 || env->gpr[7] != 0) { |
| 70 | env->gpr[3] = 1; |
| 71 | break; |
| 72 | } |
| 73 | } |
| 74 | env->gpr[3] = 0; |
| 75 | env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */ |
| 76 | env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */ |
| 77 | env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */ |
| 78 | env->gpr[7] = 85 << 16; /* refresh rate */ |
| 79 | env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */ |
| 80 | linesize = ((graphic_depth + 7) >> 3) * graphic_width; |
| 81 | linesize = (linesize + 3) & ~3; |
| 82 | env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */ |
| 83 | break; |
| 84 | case 31: /* set_video power */ |
| 85 | env->gpr[3] = 0; |
| 86 | break; |
| 87 | case 39: /* video_ctrl */ |
| 88 | if (env->gpr[6] == 0 || env->gpr[6] == 1) |
| 89 | vga_vbl_enabled = env->gpr[6]; |
| 90 | env->gpr[3] = 0; |
| 91 | break; |
| 92 | case 47: |
| 93 | break; |
| 94 | case 59: /* set_color */ |
| 95 | /* R6 = index, R7 = RGB */ |
| 96 | env->gpr[3] = 0; |
| 97 | break; |
| 98 | case 64: /* get color */ |
| 99 | /* R6 = index */ |
| 100 | env->gpr[3] = 0; |
| 101 | break; |
| 102 | case 116: /* set hwcursor */ |
| 103 | /* R6 = x, R7 = y, R8 = visible, R9 = data */ |
| 104 | break; |
| 105 | default: |
Blue Swirl | b11ebf6 | 2009-08-16 11:54:37 +0000 | [diff] [blame] | 106 | fprintf(stderr, "unsupported OSI call R5=%016" PRIx64 "\n", |
j_mayer | aae9366 | 2007-11-24 02:56:36 +0000 | [diff] [blame] | 107 | ppc_dump_gpr(env, 5)); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 108 | break; |
| 109 | } |
| 110 | |
| 111 | return 1; /* osi_call handled */ |
| 112 | } |
| 113 | |
blueswir1 | 513f789 | 2009-03-08 09:51:29 +0000 | [diff] [blame] | 114 | static int fw_cfg_boot_set(void *opaque, const char *boot_device) |
| 115 | { |
| 116 | fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); |
| 117 | return 0; |
| 118 | } |
| 119 | |
Paul Brook | fbe1b59 | 2009-05-13 17:56:25 +0100 | [diff] [blame] | 120 | static void ppc_heathrow_init (ram_addr_t ram_size, |
aliguori | 3023f33 | 2009-01-16 19:04:14 +0000 | [diff] [blame] | 121 | const char *boot_device, |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 122 | const char *kernel_filename, |
| 123 | const char *kernel_cmdline, |
| 124 | const char *initrd_filename, |
| 125 | const char *cpu_model) |
| 126 | { |
bellard | aaed909 | 2007-11-10 15:15:54 +0000 | [diff] [blame] | 127 | CPUState *env = NULL, *envs[MAX_CPUS]; |
Paul Brook | 5cea859 | 2009-05-30 00:52:44 +0100 | [diff] [blame] | 128 | char *filename; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 129 | qemu_irq *pic, **heathrow_irqs; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 130 | int linux_boot, i; |
pbrook | b584726 | 2009-04-10 02:24:36 +0000 | [diff] [blame] | 131 | ram_addr_t ram_offset, bios_offset, vga_bios_offset; |
blueswir1 | 7373048 | 2009-01-24 12:00:23 +0000 | [diff] [blame] | 132 | uint32_t kernel_base, initrd_base; |
| 133 | int32_t kernel_size, initrd_size; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 134 | PCIBus *pci_bus; |
| 135 | MacIONVRAMState *nvr; |
| 136 | int vga_bios_size, bios_size; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 137 | int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index; |
blueswir1 | 7fa9ae1 | 2009-01-12 17:40:23 +0000 | [diff] [blame] | 138 | int escc_mem_index, ide_mem_index[2]; |
blueswir1 | 513f789 | 2009-03-08 09:51:29 +0000 | [diff] [blame] | 139 | uint16_t ppc_boot_device; |
Gerd Hoffmann | f455e98 | 2009-08-28 15:47:03 +0200 | [diff] [blame] | 140 | DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; |
blueswir1 | 271dd5e | 2008-12-24 20:29:16 +0000 | [diff] [blame] | 141 | void *fw_cfg; |
aurel32 | 28ce5ce | 2009-01-30 20:39:32 +0000 | [diff] [blame] | 142 | void *dbdma; |
pbrook | 4465449 | 2009-04-10 00:26:15 +0000 | [diff] [blame] | 143 | uint8_t *vga_bios_ptr; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 144 | |
| 145 | linux_boot = (kernel_filename != NULL); |
| 146 | |
| 147 | /* init CPUs */ |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 148 | if (cpu_model == NULL) |
aurel32 | f2fde45 | 2008-12-20 23:39:46 +0000 | [diff] [blame] | 149 | cpu_model = "G3"; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 150 | for (i = 0; i < smp_cpus; i++) { |
bellard | aaed909 | 2007-11-10 15:15:54 +0000 | [diff] [blame] | 151 | env = cpu_init(cpu_model); |
| 152 | if (!env) { |
| 153 | fprintf(stderr, "Unable to find PowerPC CPU definition\n"); |
| 154 | exit(1); |
| 155 | } |
aurel32 | b0fb43d | 2009-01-14 14:48:04 +0000 | [diff] [blame] | 156 | /* Set time-base frequency to 16.6 Mhz */ |
| 157 | cpu_ppc_tb_init(env, 16600000UL); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 158 | env->osi_call = vga_osi_call; |
Jan Kiszka | a08d436 | 2009-06-27 09:25:07 +0200 | [diff] [blame] | 159 | qemu_register_reset(&cpu_ppc_reset, env); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 160 | envs[i] = env; |
| 161 | } |
| 162 | |
| 163 | /* allocate RAM */ |
aurel32 | 6b4079f | 2009-01-13 19:08:10 +0000 | [diff] [blame] | 164 | if (ram_size > (2047 << 20)) { |
| 165 | fprintf(stderr, |
| 166 | "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n", |
| 167 | ((unsigned int)ram_size / (1 << 20))); |
| 168 | exit(1); |
| 169 | } |
| 170 | |
aurel32 | a748ab6 | 2008-12-20 23:40:35 +0000 | [diff] [blame] | 171 | ram_offset = qemu_ram_alloc(ram_size); |
| 172 | cpu_register_physical_memory(0, ram_size, ram_offset); |
| 173 | |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 174 | /* allocate and load BIOS */ |
aurel32 | a748ab6 | 2008-12-20 23:40:35 +0000 | [diff] [blame] | 175 | bios_offset = qemu_ram_alloc(BIOS_SIZE); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 176 | if (bios_name == NULL) |
blueswir1 | 992e5ac | 2008-12-24 20:23:51 +0000 | [diff] [blame] | 177 | bios_name = PROM_FILENAME; |
Paul Brook | 5cea859 | 2009-05-30 00:52:44 +0100 | [diff] [blame] | 178 | filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); |
blueswir1 | 992e5ac | 2008-12-24 20:23:51 +0000 | [diff] [blame] | 179 | cpu_register_physical_memory(PROM_ADDR, BIOS_SIZE, bios_offset | IO_MEM_ROM); |
| 180 | |
| 181 | /* Load OpenBIOS (ELF) */ |
Paul Brook | 5cea859 | 2009-05-30 00:52:44 +0100 | [diff] [blame] | 182 | if (filename) { |
| 183 | bios_size = load_elf(filename, 0, NULL, NULL, NULL); |
| 184 | qemu_free(filename); |
| 185 | } else { |
| 186 | bios_size = -1; |
| 187 | } |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 188 | if (bios_size < 0 || bios_size > BIOS_SIZE) { |
Paul Brook | 5cea859 | 2009-05-30 00:52:44 +0100 | [diff] [blame] | 189 | hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 190 | exit(1); |
| 191 | } |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 192 | |
| 193 | /* allocate and load VGA BIOS */ |
aurel32 | a748ab6 | 2008-12-20 23:40:35 +0000 | [diff] [blame] | 194 | vga_bios_offset = qemu_ram_alloc(VGA_BIOS_SIZE); |
pbrook | 4465449 | 2009-04-10 00:26:15 +0000 | [diff] [blame] | 195 | vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset); |
Paul Brook | 5cea859 | 2009-05-30 00:52:44 +0100 | [diff] [blame] | 196 | filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME); |
| 197 | if (filename) { |
| 198 | vga_bios_size = load_image(filename, vga_bios_ptr + 8); |
| 199 | qemu_free(filename); |
| 200 | } else { |
| 201 | vga_bios_size = -1; |
| 202 | } |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 203 | if (vga_bios_size < 0) { |
| 204 | /* if no bios is present, we can still work */ |
Paul Brook | 5cea859 | 2009-05-30 00:52:44 +0100 | [diff] [blame] | 205 | fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", |
| 206 | VGABIOS_FILENAME); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 207 | vga_bios_size = 0; |
| 208 | } else { |
| 209 | /* set a specific header (XXX: find real Apple format for NDRV |
| 210 | drivers) */ |
pbrook | 4465449 | 2009-04-10 00:26:15 +0000 | [diff] [blame] | 211 | vga_bios_ptr[0] = 'N'; |
| 212 | vga_bios_ptr[1] = 'D'; |
| 213 | vga_bios_ptr[2] = 'R'; |
| 214 | vga_bios_ptr[3] = 'V'; |
| 215 | cpu_to_be32w((uint32_t *)(vga_bios_ptr + 4), vga_bios_size); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 216 | vga_bios_size += 8; |
Alexander Graf | a7b022e | 2009-07-26 06:31:15 +0000 | [diff] [blame] | 217 | |
| 218 | /* Round to page boundary */ |
| 219 | vga_bios_size = (vga_bios_size + TARGET_PAGE_SIZE - 1) & |
| 220 | TARGET_PAGE_MASK; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 221 | } |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 222 | |
| 223 | if (linux_boot) { |
aurel32 | 36bee1e | 2009-01-26 10:22:15 +0000 | [diff] [blame] | 224 | uint64_t lowaddr = 0; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 225 | kernel_base = KERNEL_LOAD_ADDR; |
aurel32 | 36bee1e | 2009-01-26 10:22:15 +0000 | [diff] [blame] | 226 | /* Now we can load the kernel. The first step tries to load the kernel |
| 227 | supposing PhysAddr = 0x00000000. If that was wrong the kernel is |
| 228 | loaded again, the new PhysAddr being computed from lowaddr. */ |
| 229 | kernel_size = load_elf(kernel_filename, kernel_base, NULL, &lowaddr, NULL); |
| 230 | if (kernel_size > 0 && lowaddr != KERNEL_LOAD_ADDR) { |
| 231 | kernel_size = load_elf(kernel_filename, (2 * kernel_base) - lowaddr, |
Blue Swirl | 660f11b | 2009-07-31 21:16:51 +0000 | [diff] [blame] | 232 | NULL, NULL, NULL); |
aurel32 | 36bee1e | 2009-01-26 10:22:15 +0000 | [diff] [blame] | 233 | } |
blueswir1 | 52f163b | 2008-12-24 20:30:01 +0000 | [diff] [blame] | 234 | if (kernel_size < 0) |
| 235 | kernel_size = load_aout(kernel_filename, kernel_base, |
| 236 | ram_size - kernel_base); |
| 237 | if (kernel_size < 0) |
| 238 | kernel_size = load_image_targphys(kernel_filename, |
| 239 | kernel_base, |
| 240 | ram_size - kernel_base); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 241 | if (kernel_size < 0) { |
Paul Brook | 2ac7117 | 2009-05-08 02:35:15 +0100 | [diff] [blame] | 242 | hw_error("qemu: could not load kernel '%s'\n", |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 243 | kernel_filename); |
| 244 | exit(1); |
| 245 | } |
| 246 | /* load initrd */ |
| 247 | if (initrd_filename) { |
| 248 | initrd_base = INITRD_LOAD_ADDR; |
pbrook | dcac967 | 2009-04-09 20:05:49 +0000 | [diff] [blame] | 249 | initrd_size = load_image_targphys(initrd_filename, initrd_base, |
| 250 | ram_size - initrd_base); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 251 | if (initrd_size < 0) { |
Paul Brook | 2ac7117 | 2009-05-08 02:35:15 +0100 | [diff] [blame] | 252 | hw_error("qemu: could not load initial ram disk '%s'\n", |
| 253 | initrd_filename); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 254 | exit(1); |
| 255 | } |
| 256 | } else { |
| 257 | initrd_base = 0; |
| 258 | initrd_size = 0; |
| 259 | } |
balrog | 6ac0e82 | 2007-10-31 01:54:04 +0000 | [diff] [blame] | 260 | ppc_boot_device = 'm'; |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 261 | } else { |
| 262 | kernel_base = 0; |
| 263 | kernel_size = 0; |
| 264 | initrd_base = 0; |
| 265 | initrd_size = 0; |
j_mayer | 28c5af5 | 2007-11-11 01:50:45 +0000 | [diff] [blame] | 266 | ppc_boot_device = '\0'; |
j_mayer | 0d913fd | 2007-11-11 14:44:28 +0000 | [diff] [blame] | 267 | for (i = 0; boot_device[i] != '\0'; i++) { |
j_mayer | 28c5af5 | 2007-11-11 01:50:45 +0000 | [diff] [blame] | 268 | /* TOFIX: for now, the second IDE channel is not properly |
j_mayer | 0d913fd | 2007-11-11 14:44:28 +0000 | [diff] [blame] | 269 | * used by OHW. The Mac floppy disk are not emulated. |
j_mayer | 28c5af5 | 2007-11-11 01:50:45 +0000 | [diff] [blame] | 270 | * For now, OHW cannot boot from the network. |
| 271 | */ |
| 272 | #if 0 |
j_mayer | 0d913fd | 2007-11-11 14:44:28 +0000 | [diff] [blame] | 273 | if (boot_device[i] >= 'a' && boot_device[i] <= 'f') { |
| 274 | ppc_boot_device = boot_device[i]; |
j_mayer | 28c5af5 | 2007-11-11 01:50:45 +0000 | [diff] [blame] | 275 | break; |
j_mayer | 0d913fd | 2007-11-11 14:44:28 +0000 | [diff] [blame] | 276 | } |
j_mayer | 28c5af5 | 2007-11-11 01:50:45 +0000 | [diff] [blame] | 277 | #else |
j_mayer | 0d913fd | 2007-11-11 14:44:28 +0000 | [diff] [blame] | 278 | if (boot_device[i] >= 'c' && boot_device[i] <= 'd') { |
| 279 | ppc_boot_device = boot_device[i]; |
j_mayer | 28c5af5 | 2007-11-11 01:50:45 +0000 | [diff] [blame] | 280 | break; |
j_mayer | 0d913fd | 2007-11-11 14:44:28 +0000 | [diff] [blame] | 281 | } |
j_mayer | 28c5af5 | 2007-11-11 01:50:45 +0000 | [diff] [blame] | 282 | #endif |
| 283 | } |
| 284 | if (ppc_boot_device == '\0') { |
aurel32 | 8a901de | 2009-01-13 19:07:59 +0000 | [diff] [blame] | 285 | fprintf(stderr, "No valid boot device for G3 Beige machine\n"); |
j_mayer | 28c5af5 | 2007-11-11 01:50:45 +0000 | [diff] [blame] | 286 | exit(1); |
| 287 | } |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 288 | } |
| 289 | |
| 290 | isa_mem_base = 0x80000000; |
j_mayer | aae9366 | 2007-11-24 02:56:36 +0000 | [diff] [blame] | 291 | |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 292 | /* Register 2 MB of ISA IO space */ |
| 293 | isa_mmio_init(0xfe000000, 0x00200000); |
| 294 | |
| 295 | /* XXX: we register only 1 output pin for heathrow PIC */ |
| 296 | heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *)); |
| 297 | heathrow_irqs[0] = |
| 298 | qemu_mallocz(smp_cpus * sizeof(qemu_irq) * 1); |
| 299 | /* Connect the heathrow PIC outputs to the 6xx bus */ |
| 300 | for (i = 0; i < smp_cpus; i++) { |
| 301 | switch (PPC_INPUT(env)) { |
| 302 | case PPC_FLAGS_INPUT_6xx: |
| 303 | heathrow_irqs[i] = heathrow_irqs[0] + (i * 1); |
| 304 | heathrow_irqs[i][0] = |
| 305 | ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; |
| 306 | break; |
| 307 | default: |
Paul Brook | 2ac7117 | 2009-05-08 02:35:15 +0100 | [diff] [blame] | 308 | hw_error("Bus model not supported on OldWorld Mac machine\n"); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 309 | } |
| 310 | } |
| 311 | |
| 312 | /* init basic PC hardware */ |
| 313 | if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { |
Paul Brook | 2ac7117 | 2009-05-08 02:35:15 +0100 | [diff] [blame] | 314 | hw_error("Only 6xx bus is supported on heathrow machine\n"); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 315 | } |
| 316 | pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs); |
| 317 | pci_bus = pci_grackle_init(0xfec00000, pic); |
Paul Brook | fbe1b59 | 2009-05-13 17:56:25 +0100 | [diff] [blame] | 318 | pci_vga_init(pci_bus, vga_bios_offset, vga_bios_size); |
j_mayer | aae9366 | 2007-11-24 02:56:36 +0000 | [diff] [blame] | 319 | |
aurel32 | aeeb69c | 2009-01-14 14:47:56 +0000 | [diff] [blame] | 320 | escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0], |
blueswir1 | 7fa9ae1 | 2009-01-12 17:40:23 +0000 | [diff] [blame] | 321 | serial_hds[1], ESCC_CLOCK, 4); |
j_mayer | aae9366 | 2007-11-24 02:56:36 +0000 | [diff] [blame] | 322 | |
aliguori | cb457d7 | 2009-01-13 19:47:10 +0000 | [diff] [blame] | 323 | for(i = 0; i < nb_nics; i++) |
Markus Armbruster | 5607c38 | 2009-06-18 15:14:08 +0200 | [diff] [blame] | 324 | pci_nic_init(&nd_table[i], "ne2k_pci", NULL); |
j_mayer | 0d913fd | 2007-11-11 14:44:28 +0000 | [diff] [blame] | 325 | |
ths | e4bcb14 | 2007-12-02 04:51:10 +0000 | [diff] [blame] | 326 | |
| 327 | if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { |
| 328 | fprintf(stderr, "qemu: too many IDE bus\n"); |
| 329 | exit(1); |
| 330 | } |
aurel32 | bd4524e | 2009-03-07 21:35:21 +0000 | [diff] [blame] | 331 | |
| 332 | /* First IDE channel is a MAC IDE on the MacIO bus */ |
Gerd Hoffmann | f455e98 | 2009-08-28 15:47:03 +0200 | [diff] [blame] | 333 | hd[0] = drive_get(IF_IDE, 0, 0); |
| 334 | hd[1] = drive_get(IF_IDE, 0, 1); |
aurel32 | bd4524e | 2009-03-07 21:35:21 +0000 | [diff] [blame] | 335 | dbdma = DBDMA_init(&dbdma_mem_index); |
| 336 | ide_mem_index[0] = -1; |
| 337 | ide_mem_index[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]); |
ths | e4bcb14 | 2007-12-02 04:51:10 +0000 | [diff] [blame] | 338 | |
aurel32 | bd4524e | 2009-03-07 21:35:21 +0000 | [diff] [blame] | 339 | /* Second IDE channel is a CMD646 on the PCI bus */ |
Gerd Hoffmann | f455e98 | 2009-08-28 15:47:03 +0200 | [diff] [blame] | 340 | hd[0] = drive_get(IF_IDE, 1, 0); |
| 341 | hd[1] = drive_get(IF_IDE, 1, 1); |
aurel32 | bd4524e | 2009-03-07 21:35:21 +0000 | [diff] [blame] | 342 | hd[3] = hd[2] = NULL; |
| 343 | pci_cmd646_ide_init(pci_bus, hd, 0); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 344 | |
| 345 | /* cuda also initialize ADB */ |
| 346 | cuda_init(&cuda_mem_index, pic[0x12]); |
| 347 | |
| 348 | adb_kbd_init(&adb_bus); |
| 349 | adb_mouse_init(&adb_bus); |
j_mayer | aae9366 | 2007-11-24 02:56:36 +0000 | [diff] [blame] | 350 | |
blueswir1 | 68af3f2 | 2009-02-07 10:48:26 +0000 | [diff] [blame] | 351 | nvr = macio_nvram_init(&nvram_mem_index, 0x2000, 4); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 352 | pmac_format_nvram_partition(nvr, 0x2000); |
| 353 | |
blueswir1 | 4ebcf88 | 2009-02-01 12:01:04 +0000 | [diff] [blame] | 354 | macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem_index, |
| 355 | dbdma_mem_index, cuda_mem_index, nvr, 2, ide_mem_index, |
| 356 | escc_mem_index); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 357 | |
| 358 | if (usb_enabled) { |
Gerd Hoffmann | 5b19d9a | 2009-08-31 14:24:03 +0200 | [diff] [blame] | 359 | usb_ohci_init_pci(pci_bus, -1); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 360 | } |
| 361 | |
| 362 | if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) |
| 363 | graphic_depth = 15; |
| 364 | |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 365 | /* No PCI init: the BIOS will do it */ |
| 366 | |
blueswir1 | 271dd5e | 2008-12-24 20:29:16 +0000 | [diff] [blame] | 367 | fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); |
| 368 | fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); |
| 369 | fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); |
| 370 | fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW); |
blueswir1 | 513f789 | 2009-03-08 09:51:29 +0000 | [diff] [blame] | 371 | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); |
| 372 | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); |
| 373 | if (kernel_cmdline) { |
| 374 | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR); |
| 375 | pstrcpy_targphys(CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline); |
| 376 | } else { |
| 377 | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); |
| 378 | } |
| 379 | fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); |
| 380 | fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); |
| 381 | fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device); |
Laurent Vivier | 7f1aec5 | 2009-08-08 10:19:24 +0000 | [diff] [blame] | 382 | |
| 383 | fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); |
| 384 | fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); |
| 385 | fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); |
| 386 | |
blueswir1 | 513f789 | 2009-03-08 09:51:29 +0000 | [diff] [blame] | 387 | qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 388 | } |
| 389 | |
Anthony Liguori | f80f9ec | 2009-05-20 18:38:09 -0500 | [diff] [blame] | 390 | static QEMUMachine heathrow_machine = { |
aurel32 | 4d7ca41 | 2009-01-07 23:38:59 +0000 | [diff] [blame] | 391 | .name = "g3beige", |
aliguori | 4b32e16 | 2008-10-07 20:34:35 +0000 | [diff] [blame] | 392 | .desc = "Heathrow based PowerMAC", |
| 393 | .init = ppc_heathrow_init, |
balrog | 3d878ca | 2008-10-28 10:59:59 +0000 | [diff] [blame] | 394 | .max_cpus = MAX_CPUS, |
Anthony Liguori | 0c25743 | 2009-05-21 20:41:01 -0500 | [diff] [blame] | 395 | .is_default = 1, |
j_mayer | 3cbee15 | 2007-10-28 23:42:18 +0000 | [diff] [blame] | 396 | }; |
Anthony Liguori | f80f9ec | 2009-05-20 18:38:09 -0500 | [diff] [blame] | 397 | |
| 398 | static void heathrow_machine_init(void) |
| 399 | { |
| 400 | qemu_register_machine(&heathrow_machine); |
| 401 | } |
| 402 | |
| 403 | machine_init(heathrow_machine_init); |