]> git.proxmox.com Git - mirror_qemu.git/blame - hw/hppa/machine.c
lasi: move parallel port initialisation to machine.c
[mirror_qemu.git] / hw / hppa / machine.c
CommitLineData
813dff13
HD
1/*
2 * QEMU HPPA hardware system emulator.
3 * Copyright 2018 Helge Deller <deller@gmx.de>
4 */
5
6#include "qemu/osdep.h"
2c65db5e 7#include "qemu/datadir.h"
813dff13 8#include "cpu.h"
813dff13
HD
9#include "elf.h"
10#include "hw/loader.h"
813dff13 11#include "qemu/error-report.h"
71e8a915 12#include "sysemu/reset.h"
813dff13 13#include "sysemu/sysemu.h"
b28c4a64 14#include "sysemu/runstate.h"
bcdb9064 15#include "hw/rtc/mc146818rtc.h"
813dff13
HD
16#include "hw/timer/i8254.h"
17#include "hw/char/serial.h"
9701e569 18#include "hw/char/parallel.h"
376b8519 19#include "hw/net/lasi_82596.h"
4a4554c6 20#include "hw/nmi.h"
0db9350e 21#include "hw/pci-host/dino.h"
954f6f75 22#include "lasi.h"
070e9a1e 23#include "hppa_sys.h"
c108cc59 24#include "qemu/units.h"
813dff13 25#include "qapi/error.h"
852c27e2 26#include "net/net.h"
691cbbad 27#include "qemu/log.h"
e07c4f44 28#include "net/net.h"
813dff13 29
a72bd606
HD
30#define MAX_IDE_BUS 2
31
28b71a2e
HD
32#define MIN_SEABIOS_HPPA_VERSION 1 /* require at least this fw version */
33
b28c4a64
HD
34#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
35
36static void hppa_powerdown_req(Notifier *n, void *opaque)
37{
38 hwaddr soft_power_reg = HPA_POWER_BUTTON;
39 uint32_t val;
40
41 val = ldl_be_phys(&address_space_memory, soft_power_reg);
42 if ((val >> 8) == 0) {
43 /* immediately shut down when under hardware control */
44 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
45 return;
46 }
47
48 /* clear bit 31 to indicate that the power switch was pressed. */
49 val &= ~1;
50 stl_be_phys(&address_space_memory, soft_power_reg, val);
51}
52
53static Notifier hppa_system_powerdown_notifier = {
54 .notify = hppa_powerdown_req
55};
56
57
a72bd606
HD
58static ISABus *hppa_isa_bus(void)
59{
60 ISABus *isa_bus;
61 qemu_irq *isa_irqs;
62 MemoryRegion *isa_region;
63
64 isa_region = g_new(MemoryRegion, 1);
65 memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
66 NULL, "isa-io", 0x800);
67 memory_region_add_subregion(get_system_memory(), IDE_HPA,
68 isa_region);
69
70 isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
71 &error_abort);
72 isa_irqs = i8259_init(isa_bus,
73 /* qemu_allocate_irq(dino_set_isa_irq, s, 0)); */
74 NULL);
75 isa_bus_irqs(isa_bus, isa_irqs);
76
77 return isa_bus;
78}
79
80static uint64_t cpu_hppa_to_phys(void *opaque, uint64_t addr)
81{
82 addr &= (0x10000000 - 1);
83 return addr;
84}
85
86static HPPACPU *cpu[HPPA_MAX_CPUS];
87static uint64_t firmware_entry;
813dff13 88
32ff8bf2
HD
89static void fw_cfg_boot_set(void *opaque, const char *boot_device,
90 Error **errp)
91{
92 fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
93}
94
28b71a2e
HD
95static FWCfgState *create_fw_cfg(MachineState *ms)
96{
97 FWCfgState *fw_cfg;
98 uint64_t val;
99
24576007 100 fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4);
28b71a2e
HD
101 fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
102 fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
bfdf22bc 103 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
28b71a2e
HD
104
105 val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
106 fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
107 g_memdup(&val, sizeof(val)), sizeof(val));
108
df5c6a50
HD
109 val = cpu_to_le64(HPPA_TLB_ENTRIES);
110 fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
111 g_memdup(&val, sizeof(val)), sizeof(val));
112
113 val = cpu_to_le64(HPPA_BTLB_ENTRIES);
114 fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
115 g_memdup(&val, sizeof(val)), sizeof(val));
116
b28c4a64
HD
117 val = cpu_to_le64(HPA_POWER_BUTTON);
118 fw_cfg_add_file(fw_cfg, "/etc/power-button-addr",
119 g_memdup(&val, sizeof(val)), sizeof(val));
120
32ff8bf2
HD
121 fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_order[0]);
122 qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
123
28b71a2e
HD
124 return fw_cfg;
125}
126
0d068996
MCA
127static DinoState *dino_init(MemoryRegion *addr_space)
128{
129 DeviceState *dev;
130
131 dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
132 object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
133 &error_fatal);
134 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
135
136 return DINO_PCI_HOST_BRIDGE(dev);
137}
138
813dff13
HD
139static void machine_hppa_init(MachineState *machine)
140{
a72bd606
HD
141 const char *kernel_filename = machine->kernel_filename;
142 const char *kernel_cmdline = machine->kernel_cmdline;
143 const char *initrd_filename = machine->initrd_filename;
2683758c 144 DeviceState *dev, *dino_dev, *lasi_dev;
a72bd606
HD
145 PCIBus *pci_bus;
146 ISABus *isa_bus;
a72bd606
HD
147 char *firmware_filename;
148 uint64_t firmware_low, firmware_high;
149 long size;
150 uint64_t kernel_entry = 0, kernel_low, kernel_high;
151 MemoryRegion *addr_space = get_system_memory();
152 MemoryRegion *rom_region;
a72bd606
HD
153 MemoryRegion *cpu_region;
154 long i;
33decbd2 155 unsigned int smp_cpus = machine->smp.cpus;
4765384c 156 SysBusDevice *s;
a72bd606 157
a72bd606
HD
158 /* Create CPUs. */
159 for (i = 0; i < smp_cpus; i++) {
266a880e 160 char *name = g_strdup_printf("cpu%ld-io-eir", i);
a72bd606
HD
161 cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
162
163 cpu_region = g_new(MemoryRegion, 1);
164 memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
266a880e 165 cpu[i], name, 4);
a72bd606
HD
166 memory_region_add_subregion(addr_space, CPU_HPA + i * 0x1000,
167 cpu_region);
266a880e 168 g_free(name);
a72bd606
HD
169 }
170
a72bd606 171 /* Main memory region. */
b7746b11
PMD
172 if (machine->ram_size > 3 * GiB) {
173 error_report("RAM size is currently restricted to 3GB");
174 exit(EXIT_FAILURE);
175 }
7c59c1e0
IM
176 memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
177
a72bd606 178
376b8519 179 /* Init Lasi chip */
954f6f75 180 lasi_dev = DEVICE(lasi_initfn(addr_space));
2683758c
MCA
181 memory_region_add_subregion(addr_space, LASI_HPA,
182 sysbus_mmio_get_region(
183 SYS_BUS_DEVICE(lasi_dev), 0));
376b8519 184
a72bd606 185 /* Init Dino (PCI host bus chip). */
36f9bbdb 186 dino_dev = DEVICE(dino_init(addr_space));
efdb3ce2
MCA
187 memory_region_add_subregion(addr_space, DINO_HPA,
188 sysbus_mmio_get_region(
189 SYS_BUS_DEVICE(dino_dev), 0));
05245daf 190 pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
a72bd606
HD
191 assert(pci_bus);
192
193 /* Create ISA bus. */
194 isa_bus = hppa_isa_bus();
195 assert(isa_bus);
196
197 /* Realtime clock, used by firmware for PDC_TOD call. */
36f9bbdb 198 mc146818_rtc_init(isa_bus, 2000, NULL);
a72bd606
HD
199
200 /* Serial code setup. */
9bca0edb 201 if (serial_hd(0)) {
a72bd606 202 uint32_t addr = DINO_UART_HPA + 0x800;
a4b74c19
MCA
203 serial_mm_init(addr_space, addr, 0,
204 qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT),
9bca0edb 205 115200, serial_hd(0), DEVICE_BIG_ENDIAN);
a72bd606
HD
206 }
207
9701e569
MCA
208 /* Parallel port */
209 parallel_mm_init(addr_space, LASI_LPT_HPA + 0x800, 0,
210 qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
211 parallel_hds[0]);
212
28b71a2e
HD
213 /* fw_cfg configuration interface */
214 create_fw_cfg(machine);
215
a72bd606 216 /* SCSI disk setup. */
877eb21d
MCA
217 dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
218 lsi53c8xx_handle_legacy_cmdline(dev);
a72bd606 219
4765384c
SS
220 /* Graphics setup. */
221 if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
3e80f690 222 dev = qdev_new("artist");
4765384c 223 s = SYS_BUS_DEVICE(dev);
3c6ef471 224 sysbus_realize_and_unref(s, &error_fatal);
4765384c
SS
225 sysbus_mmio_map(s, 0, LASI_GFX_HPA);
226 sysbus_mmio_map(s, 1, ARTIST_FB_ADDR);
227 }
228
0e6de551 229 /* Network setup. */
c3c3fe47
MCA
230 if (enable_lasi_lan()) {
231 lasi_82596_init(addr_space, LASI_LAN_HPA,
232 qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
233 }
234
a72bd606 235 for (i = 0; i < nb_nics; i++) {
376b8519 236 if (!enable_lasi_lan()) {
0e6de551 237 pci_nic_init_nofail(&nd_table[i], pci_bus, "tulip", NULL);
376b8519 238 }
a72bd606
HD
239 }
240
b28c4a64
HD
241 /* register power switch emulation */
242 qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
243
a72bd606
HD
244 /* Load firmware. Given that this is not "real" firmware,
245 but one explicitly written for the emulation, we might as
246 well load it directly from an ELF image. */
247 firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
b57e3e97 248 machine->firmware ?: "hppa-firmware.img");
a72bd606
HD
249 if (firmware_filename == NULL) {
250 error_report("no firmware provided");
251 exit(1);
252 }
253
4366e1db 254 size = load_elf(firmware_filename, NULL, NULL, NULL,
6cdda0ff 255 &firmware_entry, &firmware_low, &firmware_high, NULL,
a72bd606
HD
256 true, EM_PARISC, 0, 0);
257
258 /* Unfortunately, load_elf sign-extends reading elf32. */
259 firmware_entry = (target_ureg)firmware_entry;
260 firmware_low = (target_ureg)firmware_low;
261 firmware_high = (target_ureg)firmware_high;
262
263 if (size < 0) {
264 error_report("could not load firmware '%s'", firmware_filename);
265 exit(1);
266 }
691cbbad
RH
267 qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
268 "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
269 firmware_low, firmware_high, firmware_entry);
8262863d 270 if (firmware_low < FIRMWARE_START || firmware_high >= FIRMWARE_END) {
a72bd606
HD
271 error_report("Firmware overlaps with memory or IO space");
272 exit(1);
273 }
274 g_free(firmware_filename);
275
276 rom_region = g_new(MemoryRegion, 1);
6a3a2e82
IM
277 memory_region_init_ram(rom_region, NULL, "firmware",
278 (FIRMWARE_END - FIRMWARE_START), &error_fatal);
a72bd606
HD
279 memory_region_add_subregion(addr_space, FIRMWARE_START, rom_region);
280
281 /* Load kernel */
282 if (kernel_filename) {
4366e1db 283 size = load_elf(kernel_filename, NULL, &cpu_hppa_to_phys,
6cdda0ff 284 NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
a72bd606
HD
285 true, EM_PARISC, 0, 0);
286
287 /* Unfortunately, load_elf sign-extends reading elf32. */
288 kernel_entry = (target_ureg) cpu_hppa_to_phys(NULL, kernel_entry);
289 kernel_low = (target_ureg)kernel_low;
290 kernel_high = (target_ureg)kernel_high;
291
292 if (size < 0) {
293 error_report("could not load kernel '%s'", kernel_filename);
294 exit(1);
295 }
691cbbad
RH
296 qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
297 "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
c108cc59
PMD
298 ", size %" PRIu64 " kB\n",
299 kernel_low, kernel_high, kernel_entry, size / KiB);
a72bd606
HD
300
301 if (kernel_cmdline) {
302 cpu[0]->env.gr[24] = 0x4000;
303 pstrcpy_targphys("cmdline", cpu[0]->env.gr[24],
304 TARGET_PAGE_SIZE, kernel_cmdline);
305 }
306
307 if (initrd_filename) {
308 ram_addr_t initrd_base;
f3839fda 309 int64_t initrd_size;
a72bd606
HD
310
311 initrd_size = get_image_size(initrd_filename);
312 if (initrd_size < 0) {
313 error_report("could not load initial ram disk '%s'",
314 initrd_filename);
315 exit(1);
316 }
317
318 /* Load the initrd image high in memory.
319 Mirror the algorithm used by palo:
320 (1) Due to sign-extension problems and PDC,
321 put the initrd no higher than 1G.
322 (2) Reserve 64k for stack. */
bfdf22bc 323 initrd_base = MIN(machine->ram_size, 1 * GiB);
c108cc59 324 initrd_base = initrd_base - 64 * KiB;
a72bd606
HD
325 initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
326
327 if (initrd_base < kernel_high) {
328 error_report("kernel and initial ram disk too large!");
329 exit(1);
330 }
331
332 load_image_targphys(initrd_filename, initrd_base, initrd_size);
333 cpu[0]->env.gr[23] = initrd_base;
334 cpu[0]->env.gr[22] = initrd_base + initrd_size;
335 }
336 }
337
338 if (!kernel_entry) {
339 /* When booting via firmware, tell firmware if we want interactive
340 * mode (kernel_entry=1), and to boot from CD (gr[24]='d')
341 * or hard disc * (gr[24]='c').
342 */
343 kernel_entry = boot_menu ? 1 : 0;
344 cpu[0]->env.gr[24] = machine->boot_order[0];
345 }
346
347 /* We jump to the firmware entry routine and pass the
348 * various parameters in registers. After firmware initialization,
349 * firmware will start the Linux kernel with ramdisk and cmdline.
350 */
bfdf22bc 351 cpu[0]->env.gr[26] = machine->ram_size;
a72bd606
HD
352 cpu[0]->env.gr[25] = kernel_entry;
353
354 /* tell firmware how many SMP CPUs to present in inventory table */
355 cpu[0]->env.gr[21] = smp_cpus;
24576007
HD
356
357 /* tell firmware fw_cfg port */
358 cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
813dff13
HD
359}
360
a0628599 361static void hppa_machine_reset(MachineState *ms)
a72bd606 362{
33decbd2 363 unsigned int smp_cpus = ms->smp.cpus;
a72bd606
HD
364 int i;
365
366 qemu_devices_reset();
367
368 /* Start all CPUs at the firmware entry point.
369 * Monarch CPU will initialize firmware, secondary CPUs
370 * will enter a small idle look and wait for rendevouz. */
371 for (i = 0; i < smp_cpus; i++) {
372 cpu_set_pc(CPU(cpu[i]), firmware_entry);
373 cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
374 }
375
376 /* already initialized by machine_hppa_init()? */
bfdf22bc 377 if (cpu[0]->env.gr[26] == ms->ram_size) {
a72bd606
HD
378 return;
379 }
380
bfdf22bc 381 cpu[0]->env.gr[26] = ms->ram_size;
a72bd606
HD
382 cpu[0]->env.gr[25] = 0; /* no firmware boot menu */
383 cpu[0]->env.gr[24] = 'c';
384 /* gr22/gr23 unused, no initrd while reboot. */
385 cpu[0]->env.gr[21] = smp_cpus;
24576007
HD
386 /* tell firmware fw_cfg port */
387 cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
a72bd606
HD
388}
389
4a4554c6
HD
390static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
391{
392 CPUState *cs;
393
394 CPU_FOREACH(cs) {
395 cpu_interrupt(cs, CPU_INTERRUPT_NMI);
396 }
397}
a72bd606 398
813dff13
HD
399static void machine_hppa_machine_init(MachineClass *mc)
400{
0d98fbb5 401 mc->desc = "HPPA B160L machine";
a72bd606 402 mc->default_cpu_type = TYPE_HPPA_CPU;
813dff13 403 mc->init = machine_hppa_init;
a72bd606 404 mc->reset = hppa_machine_reset;
813dff13 405 mc->block_default_type = IF_SCSI;
a72bd606
HD
406 mc->max_cpus = HPPA_MAX_CPUS;
407 mc->default_cpus = 1;
ea0ac7f6 408 mc->is_default = true;
d23b6caa 409 mc->default_ram_size = 512 * MiB;
813dff13 410 mc->default_boot_order = "cd";
7c59c1e0 411 mc->default_ram_id = "ram";
813dff13
HD
412}
413
4a4554c6
HD
414static void machine_hppa_machine_init_class_init(ObjectClass *oc, void *data)
415{
416 MachineClass *mc = MACHINE_CLASS(oc);
417 machine_hppa_machine_init(mc);
418
419 NMIClass *nc = NMI_CLASS(oc);
420 nc->nmi_monitor_handler = hppa_nmi;
421}
422
423static const TypeInfo machine_hppa_machine_init_typeinfo = {
424 .name = ("hppa" "-machine"),
425 .parent = "machine",
426 .class_init = machine_hppa_machine_init_class_init,
427 .interfaces = (InterfaceInfo[]) {
428 { TYPE_NMI },
429 { }
430 },
431};
432
433static void machine_hppa_machine_init_register_types(void)
434{
435 type_register_static(&machine_hppa_machine_init_typeinfo);
436}
437
438type_init(machine_hppa_machine_init_register_types)