Initialize
[sdk/emulator/qemu.git] / hw / ppc_oldworld.c
1
2 /*
3  * QEMU OldWorld PowerMac (currently ~G3 Beige) hardware System Emulator
4  *
5  * Copyright (c) 2004-2007 Fabrice Bellard
6  * Copyright (c) 2007 Jocelyn Mayer
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 #include "hw.h"
27 #include "ppc.h"
28 #include "ppc_mac.h"
29 #include "mac_dbdma.h"
30 #include "nvram.h"
31 #include "pc.h"
32 #include "sysemu.h"
33 #include "net.h"
34 #include "isa.h"
35 #include "pci.h"
36 #include "usb-ohci.h"
37 #include "boards.h"
38 #include "fw_cfg.h"
39 #include "escc.h"
40 #include "ide.h"
41 #include "loader.h"
42 #include "elf.h"
43 #include "kvm.h"
44 #include "kvm_ppc.h"
45 #include "blockdev.h"
46
47 #define MAX_IDE_BUS 2
48 #define CFG_ADDR 0xf0000510
49
50 static int fw_cfg_boot_set(void *opaque, const char *boot_device)
51 {
52     fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
53     return 0;
54 }
55
56
57 static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
58 {
59     return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
60 }
61
62 static void ppc_heathrow_init (ram_addr_t ram_size,
63                                const char *boot_device,
64                                const char *kernel_filename,
65                                const char *kernel_cmdline,
66                                const char *initrd_filename,
67                                const char *cpu_model)
68 {
69     CPUState *env = NULL;
70     char *filename;
71     qemu_irq *pic, **heathrow_irqs;
72     int linux_boot, i;
73     ram_addr_t ram_offset, bios_offset;
74     uint32_t kernel_base, initrd_base;
75     int32_t kernel_size, initrd_size;
76     PCIBus *pci_bus;
77     MacIONVRAMState *nvr;
78     int bios_size;
79     int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
80     int escc_mem_index, ide_mem_index[2];
81     uint16_t ppc_boot_device;
82     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
83     void *fw_cfg;
84     void *dbdma;
85
86     linux_boot = (kernel_filename != NULL);
87
88     /* init CPUs */
89     if (cpu_model == NULL)
90         cpu_model = "G3";
91     for (i = 0; i < smp_cpus; i++) {
92         env = cpu_init(cpu_model);
93         if (!env) {
94             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
95             exit(1);
96         }
97         /* Set time-base frequency to 16.6 Mhz */
98         cpu_ppc_tb_init(env,  16600000UL);
99         qemu_register_reset((QEMUResetHandler*)&cpu_reset, env);
100     }
101
102     /* allocate RAM */
103     if (ram_size > (2047 << 20)) {
104         fprintf(stderr,
105                 "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n",
106                 ((unsigned int)ram_size / (1 << 20)));
107         exit(1);
108     }
109
110     ram_offset = qemu_ram_alloc(NULL, "ppc_heathrow.ram", ram_size);
111     cpu_register_physical_memory(0, ram_size, ram_offset);
112
113     /* allocate and load BIOS */
114     bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.bios", BIOS_SIZE);
115     if (bios_name == NULL)
116         bios_name = PROM_FILENAME;
117     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
118     cpu_register_physical_memory(PROM_ADDR, BIOS_SIZE, bios_offset | IO_MEM_ROM);
119
120     /* Load OpenBIOS (ELF) */
121     if (filename) {
122         bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
123                              1, ELF_MACHINE, 0);
124         qemu_free(filename);
125     } else {
126         bios_size = -1;
127     }
128     if (bios_size < 0 || bios_size > BIOS_SIZE) {
129         hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name);
130         exit(1);
131     }
132
133     if (linux_boot) {
134         uint64_t lowaddr = 0;
135         int bswap_needed;
136
137 #ifdef BSWAP_NEEDED
138         bswap_needed = 1;
139 #else
140         bswap_needed = 0;
141 #endif
142         kernel_base = KERNEL_LOAD_ADDR;
143         kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
144                                NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
145         if (kernel_size < 0)
146             kernel_size = load_aout(kernel_filename, kernel_base,
147                                     ram_size - kernel_base, bswap_needed,
148                                     TARGET_PAGE_SIZE);
149         if (kernel_size < 0)
150             kernel_size = load_image_targphys(kernel_filename,
151                                               kernel_base,
152                                               ram_size - kernel_base);
153         if (kernel_size < 0) {
154             hw_error("qemu: could not load kernel '%s'\n",
155                       kernel_filename);
156             exit(1);
157         }
158         /* load initrd */
159         if (initrd_filename) {
160             initrd_base = INITRD_LOAD_ADDR;
161             initrd_size = load_image_targphys(initrd_filename, initrd_base,
162                                               ram_size - initrd_base);
163             if (initrd_size < 0) {
164                 hw_error("qemu: could not load initial ram disk '%s'\n",
165                          initrd_filename);
166                 exit(1);
167             }
168         } else {
169             initrd_base = 0;
170             initrd_size = 0;
171         }
172         ppc_boot_device = 'm';
173     } else {
174         kernel_base = 0;
175         kernel_size = 0;
176         initrd_base = 0;
177         initrd_size = 0;
178         ppc_boot_device = '\0';
179         for (i = 0; boot_device[i] != '\0'; i++) {
180             /* TOFIX: for now, the second IDE channel is not properly
181              *        used by OHW. The Mac floppy disk are not emulated.
182              *        For now, OHW cannot boot from the network.
183              */
184 #if 0
185             if (boot_device[i] >= 'a' && boot_device[i] <= 'f') {
186                 ppc_boot_device = boot_device[i];
187                 break;
188             }
189 #else
190             if (boot_device[i] >= 'c' && boot_device[i] <= 'd') {
191                 ppc_boot_device = boot_device[i];
192                 break;
193             }
194 #endif
195         }
196         if (ppc_boot_device == '\0') {
197             fprintf(stderr, "No valid boot device for G3 Beige machine\n");
198             exit(1);
199         }
200     }
201
202     isa_mem_base = 0x80000000;
203
204     /* Register 2 MB of ISA IO space */
205     isa_mmio_init(0xfe000000, 0x00200000);
206
207     /* XXX: we register only 1 output pin for heathrow PIC */
208     heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
209     heathrow_irqs[0] =
210         qemu_mallocz(smp_cpus * sizeof(qemu_irq) * 1);
211     /* Connect the heathrow PIC outputs to the 6xx bus */
212     for (i = 0; i < smp_cpus; i++) {
213         switch (PPC_INPUT(env)) {
214         case PPC_FLAGS_INPUT_6xx:
215             heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);
216             heathrow_irqs[i][0] =
217                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
218             break;
219         default:
220             hw_error("Bus model not supported on OldWorld Mac machine\n");
221         }
222     }
223
224     /* init basic PC hardware */
225     if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
226         hw_error("Only 6xx bus is supported on heathrow machine\n");
227     }
228     pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
229     pci_bus = pci_grackle_init(0xfec00000, pic);
230     pci_vga_init(pci_bus);
231
232     escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
233                                serial_hds[1], ESCC_CLOCK, 4);
234
235     for(i = 0; i < nb_nics; i++)
236         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
237
238
239     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
240         fprintf(stderr, "qemu: too many IDE bus\n");
241         exit(1);
242     }
243
244     /* First IDE channel is a MAC IDE on the MacIO bus */
245     hd[0] = drive_get(IF_IDE, 0, 0);
246     hd[1] = drive_get(IF_IDE, 0, 1);
247     dbdma = DBDMA_init(&dbdma_mem_index);
248     ide_mem_index[0] = -1;
249     ide_mem_index[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]);
250
251     /* Second IDE channel is a CMD646 on the PCI bus */
252     hd[0] = drive_get(IF_IDE, 1, 0);
253     hd[1] = drive_get(IF_IDE, 1, 1);
254     hd[3] = hd[2] = NULL;
255     pci_cmd646_ide_init(pci_bus, hd, 0);
256
257     /* cuda also initialize ADB */
258     cuda_init(&cuda_mem_index, pic[0x12]);
259
260     adb_kbd_init(&adb_bus);
261     adb_mouse_init(&adb_bus);
262
263     nvr = macio_nvram_init(&nvram_mem_index, 0x2000, 4);
264     pmac_format_nvram_partition(nvr, 0x2000);
265
266     macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem_index,
267                dbdma_mem_index, cuda_mem_index, nvr, 2, ide_mem_index,
268                escc_mem_index);
269
270     if (usb_enabled) {
271         usb_ohci_init_pci(pci_bus, -1);
272     }
273
274     if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
275         graphic_depth = 15;
276
277     /* No PCI init: the BIOS will do it */
278
279     fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
280     fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
281     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
282     fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW);
283     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
284     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
285     if (kernel_cmdline) {
286         fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
287         pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
288     } else {
289         fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
290     }
291     fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base);
292     fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
293     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device);
294
295     fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width);
296     fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
297     fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
298
299     fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled());
300     if (kvm_enabled()) {
301 #ifdef CONFIG_KVM
302         uint8_t *hypercall;
303
304         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
305         hypercall = qemu_malloc(16);
306         kvmppc_get_hypercall(env, hypercall, 16);
307         fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
308         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
309 #endif
310     } else {
311         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
312     }
313
314     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
315 }
316
317 static QEMUMachine heathrow_machine = {
318     .name = "g3beige",
319     .desc = "Heathrow based PowerMAC",
320     .init = ppc_heathrow_init,
321     .max_cpus = MAX_CPUS,
322 #ifndef TARGET_PPC64
323     .is_default = 1,
324 #endif
325 };
326
327 static void heathrow_machine_init(void)
328 {
329     qemu_register_machine(&heathrow_machine);
330 }
331
332 machine_init(heathrow_machine_init);