1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
50static 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
57static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
58{
59 return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
60}
61
62static target_phys_addr_t round_page(target_phys_addr_t addr)
63{
64 return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
65}
66
67static void ppc_heathrow_init (ram_addr_t ram_size,
68 const char *boot_device,
69 const char *kernel_filename,
70 const char *kernel_cmdline,
71 const char *initrd_filename,
72 const char *cpu_model)
73{
74 CPUState *env = NULL;
75 char *filename;
76 qemu_irq *pic, **heathrow_irqs;
77 int linux_boot, i;
78 ram_addr_t ram_offset, bios_offset;
79 uint32_t kernel_base, initrd_base, cmdline_base = 0;
80 int32_t kernel_size, initrd_size;
81 PCIBus *pci_bus;
82 MacIONVRAMState *nvr;
83 int bios_size;
84 int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
85 int escc_mem_index, ide_mem_index[2];
86 uint16_t ppc_boot_device;
87 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
88 void *fw_cfg;
89 void *dbdma;
90
91 linux_boot = (kernel_filename != NULL);
92
93
94 if (cpu_model == NULL)
95 cpu_model = "G3";
96 for (i = 0; i < smp_cpus; i++) {
97 env = cpu_init(cpu_model);
98 if (!env) {
99 fprintf(stderr, "Unable to find PowerPC CPU definition\n");
100 exit(1);
101 }
102
103 cpu_ppc_tb_init(env, 16600000UL);
104 qemu_register_reset((QEMUResetHandler*)&cpu_reset, env);
105 }
106
107
108 if (ram_size > (2047 << 20)) {
109 fprintf(stderr,
110 "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n",
111 ((unsigned int)ram_size / (1 << 20)));
112 exit(1);
113 }
114
115 ram_offset = qemu_ram_alloc(NULL, "ppc_heathrow.ram", ram_size);
116 cpu_register_physical_memory(0, ram_size, ram_offset);
117
118
119 bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.bios", BIOS_SIZE);
120 if (bios_name == NULL)
121 bios_name = PROM_FILENAME;
122 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
123 cpu_register_physical_memory(PROM_ADDR, BIOS_SIZE, bios_offset | IO_MEM_ROM);
124
125
126 if (filename) {
127 bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
128 1, ELF_MACHINE, 0);
129 qemu_free(filename);
130 } else {
131 bios_size = -1;
132 }
133 if (bios_size < 0 || bios_size > BIOS_SIZE) {
134 hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name);
135 exit(1);
136 }
137
138 if (linux_boot) {
139 uint64_t lowaddr = 0;
140 int bswap_needed;
141
142#ifdef BSWAP_NEEDED
143 bswap_needed = 1;
144#else
145 bswap_needed = 0;
146#endif
147 kernel_base = KERNEL_LOAD_ADDR;
148 kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
149 NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
150 if (kernel_size < 0)
151 kernel_size = load_aout(kernel_filename, kernel_base,
152 ram_size - kernel_base, bswap_needed,
153 TARGET_PAGE_SIZE);
154 if (kernel_size < 0)
155 kernel_size = load_image_targphys(kernel_filename,
156 kernel_base,
157 ram_size - kernel_base);
158 if (kernel_size < 0) {
159 hw_error("qemu: could not load kernel '%s'\n",
160 kernel_filename);
161 exit(1);
162 }
163
164 if (initrd_filename) {
165 initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
166 initrd_size = load_image_targphys(initrd_filename, initrd_base,
167 ram_size - initrd_base);
168 if (initrd_size < 0) {
169 hw_error("qemu: could not load initial ram disk '%s'\n",
170 initrd_filename);
171 exit(1);
172 }
173 cmdline_base = round_page(initrd_base + initrd_size);
174 } else {
175 initrd_base = 0;
176 initrd_size = 0;
177 cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
178 }
179 ppc_boot_device = 'm';
180 } else {
181 kernel_base = 0;
182 kernel_size = 0;
183 initrd_base = 0;
184 initrd_size = 0;
185 ppc_boot_device = '\0';
186 for (i = 0; boot_device[i] != '\0'; i++) {
187
188
189
190
191#if 0
192 if (boot_device[i] >= 'a' && boot_device[i] <= 'f') {
193 ppc_boot_device = boot_device[i];
194 break;
195 }
196#else
197 if (boot_device[i] >= 'c' && boot_device[i] <= 'd') {
198 ppc_boot_device = boot_device[i];
199 break;
200 }
201#endif
202 }
203 if (ppc_boot_device == '\0') {
204 fprintf(stderr, "No valid boot device for G3 Beige machine\n");
205 exit(1);
206 }
207 }
208
209 isa_mem_base = 0x80000000;
210
211
212 isa_mmio_init(0xfe000000, 0x00200000);
213
214
215 heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
216 heathrow_irqs[0] =
217 qemu_mallocz(smp_cpus * sizeof(qemu_irq) * 1);
218
219 for (i = 0; i < smp_cpus; i++) {
220 switch (PPC_INPUT(env)) {
221 case PPC_FLAGS_INPUT_6xx:
222 heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);
223 heathrow_irqs[i][0] =
224 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
225 break;
226 default:
227 hw_error("Bus model not supported on OldWorld Mac machine\n");
228 }
229 }
230
231
232 if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
233 hw_error("Only 6xx bus is supported on heathrow machine\n");
234 }
235 pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
236 pci_bus = pci_grackle_init(0xfec00000, pic);
237 pci_vga_init(pci_bus);
238
239 escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
240 serial_hds[1], ESCC_CLOCK, 4);
241
242 for(i = 0; i < nb_nics; i++)
243 pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
244
245
246 ide_drive_get(hd, MAX_IDE_BUS);
247
248
249 dbdma = DBDMA_init(&dbdma_mem_index);
250 ide_mem_index[0] = -1;
251 ide_mem_index[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]);
252
253
254 hd[0] = hd[MAX_IDE_DEVS];
255 hd[1] = hd[MAX_IDE_DEVS + 1];
256 hd[3] = hd[2] = NULL;
257 pci_cmd646_ide_init(pci_bus, hd, 0);
258
259
260 cuda_init(&cuda_mem_index, pic[0x12]);
261
262 adb_kbd_init(&adb_bus);
263 adb_mouse_init(&adb_bus);
264
265 nvr = macio_nvram_init(&nvram_mem_index, 0x2000, 4);
266 pmac_format_nvram_partition(nvr, 0x2000);
267
268 macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem_index,
269 dbdma_mem_index, cuda_mem_index, nvr, 2, ide_mem_index,
270 escc_mem_index);
271
272 if (usb_enabled) {
273 usb_ohci_init_pci(pci_bus, -1);
274 }
275
276 if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
277 graphic_depth = 15;
278
279
280
281 fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
282 fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
283 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
284 fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW);
285 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
286 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
287 if (kernel_cmdline) {
288 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);
289 pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);
290 } else {
291 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
292 }
293 fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base);
294 fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
295 fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device);
296
297 fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width);
298 fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
299 fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
300
301 fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled());
302 if (kvm_enabled()) {
303#ifdef CONFIG_KVM
304 uint8_t *hypercall;
305
306 fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
307 hypercall = qemu_malloc(16);
308 kvmppc_get_hypercall(env, hypercall, 16);
309 fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
310 fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
311#endif
312 } else {
313 fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
314 }
315
316 qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
317}
318
319static QEMUMachine heathrow_machine = {
320 .name = "g3beige",
321 .desc = "Heathrow based PowerMAC",
322 .init = ppc_heathrow_init,
323 .max_cpus = MAX_CPUS,
324#ifndef TARGET_PPC64
325 .is_default = 1,
326#endif
327};
328
329static void heathrow_machine_init(void)
330{
331 qemu_register_machine(&heathrow_machine);
332}
333
334machine_init(heathrow_machine_init);
335