1813dff13SHelge Deller /*
2813dff13SHelge Deller * QEMU HPPA hardware system emulator.
3a536f564SHelge Deller * (C) Copyright 2018-2023 Helge Deller <deller@gmx.de>
4a536f564SHelge Deller *
5a536f564SHelge Deller * This work is licensed under the GNU GPL license version 2 or later.
6813dff13SHelge Deller */
7813dff13SHelge Deller
8813dff13SHelge Deller #include "qemu/osdep.h"
92c65db5eSPaolo Bonzini #include "qemu/datadir.h"
10813dff13SHelge Deller #include "cpu.h"
11813dff13SHelge Deller #include "elf.h"
12813dff13SHelge Deller #include "hw/loader.h"
13813dff13SHelge Deller #include "qemu/error-report.h"
1471e8a915SMarkus Armbruster #include "sysemu/reset.h"
15813dff13SHelge Deller #include "sysemu/sysemu.h"
16a9314795SHelge Deller #include "sysemu/qtest.h"
17b28c4a64SHelge Deller #include "sysemu/runstate.h"
18bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
19813dff13SHelge Deller #include "hw/timer/i8254.h"
20*7e6b5497SBernhard Beschow #include "hw/char/serial-mm.h"
219701e569SMark Cave-Ayland #include "hw/char/parallel.h"
22134ba73fSMark Cave-Ayland #include "hw/intc/i8259.h"
23d26c575cSMark Cave-Ayland #include "hw/input/lasips2.h"
24376b8519SHelge Deller #include "hw/net/lasi_82596.h"
254a4554c6SHelge Deller #include "hw/nmi.h"
262ed4faa0SHelge Deller #include "hw/usb.h"
27134ba73fSMark Cave-Ayland #include "hw/pci/pci.h"
287df6f751SHelge Deller #include "hw/pci/pci_device.h"
292ed4faa0SHelge Deller #include "hw/pci-host/astro.h"
300db9350eSMark Cave-Ayland #include "hw/pci-host/dino.h"
3145f569a1SMark Cave-Ayland #include "hw/misc/lasi.h"
32148da670SMark Cave-Ayland #include "hppa_hardware.h"
33c108cc59SPhilippe Mathieu-Daudé #include "qemu/units.h"
34813dff13SHelge Deller #include "qapi/error.h"
35852c27e2SPaolo Bonzini #include "net/net.h"
36691cbbadSRichard Henderson #include "qemu/log.h"
37813dff13SHelge Deller
38f88131d9SHelge Deller #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
3928b71a2eSHelge Deller
40ed35afcbSHelge Deller #define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
41ed35afcbSHelge Deller static hwaddr soft_power_reg;
42b28c4a64SHelge Deller
43932befaaSMark Cave-Ayland #define enable_lasi_lan() 0
44932befaaSMark Cave-Ayland
457df6f751SHelge Deller static DeviceState *lasi_dev;
46932befaaSMark Cave-Ayland
hppa_powerdown_req(Notifier * n,void * opaque)47b28c4a64SHelge Deller static void hppa_powerdown_req(Notifier *n, void *opaque)
48b28c4a64SHelge Deller {
49b28c4a64SHelge Deller uint32_t val;
50b28c4a64SHelge Deller
51b28c4a64SHelge Deller val = ldl_be_phys(&address_space_memory, soft_power_reg);
52b28c4a64SHelge Deller if ((val >> 8) == 0) {
53b28c4a64SHelge Deller /* immediately shut down when under hardware control */
54b28c4a64SHelge Deller qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
55b28c4a64SHelge Deller return;
56b28c4a64SHelge Deller }
57b28c4a64SHelge Deller
58b28c4a64SHelge Deller /* clear bit 31 to indicate that the power switch was pressed. */
59b28c4a64SHelge Deller val &= ~1;
60b28c4a64SHelge Deller stl_be_phys(&address_space_memory, soft_power_reg, val);
61b28c4a64SHelge Deller }
62b28c4a64SHelge Deller
63b28c4a64SHelge Deller static Notifier hppa_system_powerdown_notifier = {
64b28c4a64SHelge Deller .notify = hppa_powerdown_req
65b28c4a64SHelge Deller };
66b28c4a64SHelge Deller
6728f5332aSMark Cave-Ayland /* Fallback for unassigned PCI I/O operations. Avoids MCHK. */
ignore_read(void * opaque,hwaddr addr,unsigned size)6828f5332aSMark Cave-Ayland static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
6928f5332aSMark Cave-Ayland {
7028f5332aSMark Cave-Ayland return 0;
7128f5332aSMark Cave-Ayland }
7228f5332aSMark Cave-Ayland
ignore_write(void * opaque,hwaddr addr,uint64_t v,unsigned size)7328f5332aSMark Cave-Ayland static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
7428f5332aSMark Cave-Ayland {
7528f5332aSMark Cave-Ayland }
7628f5332aSMark Cave-Ayland
7728f5332aSMark Cave-Ayland static const MemoryRegionOps hppa_pci_ignore_ops = {
7828f5332aSMark Cave-Ayland .read = ignore_read,
7928f5332aSMark Cave-Ayland .write = ignore_write,
8028f5332aSMark Cave-Ayland .endianness = DEVICE_BIG_ENDIAN,
8128f5332aSMark Cave-Ayland .valid = {
8228f5332aSMark Cave-Ayland .min_access_size = 1,
8328f5332aSMark Cave-Ayland .max_access_size = 8,
8428f5332aSMark Cave-Ayland },
8528f5332aSMark Cave-Ayland .impl = {
8628f5332aSMark Cave-Ayland .min_access_size = 1,
8728f5332aSMark Cave-Ayland .max_access_size = 8,
8828f5332aSMark Cave-Ayland },
8928f5332aSMark Cave-Ayland };
90b28c4a64SHelge Deller
hppa_isa_bus(hwaddr addr)91f386a16eSRichard Henderson static ISABus *hppa_isa_bus(hwaddr addr)
92a72bd606SHelge Deller {
93a72bd606SHelge Deller ISABus *isa_bus;
94a72bd606SHelge Deller qemu_irq *isa_irqs;
95a72bd606SHelge Deller MemoryRegion *isa_region;
96a72bd606SHelge Deller
97a72bd606SHelge Deller isa_region = g_new(MemoryRegion, 1);
98a72bd606SHelge Deller memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
99a72bd606SHelge Deller NULL, "isa-io", 0x800);
100f386a16eSRichard Henderson memory_region_add_subregion(get_system_memory(), addr, isa_region);
101a72bd606SHelge Deller
102a72bd606SHelge Deller isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
103a72bd606SHelge Deller &error_abort);
104a536f564SHelge Deller isa_irqs = i8259_init(isa_bus, NULL);
1057067887eSPhilippe Mathieu-Daudé isa_bus_register_input_irqs(isa_bus, isa_irqs);
106a72bd606SHelge Deller
107a72bd606SHelge Deller return isa_bus;
108a72bd606SHelge Deller }
109a72bd606SHelge Deller
110e2c41ee5SHelge Deller /*
111e2c41ee5SHelge Deller * Helper functions to emulate RTC clock and DebugOutputPort
112e2c41ee5SHelge Deller */
113e2c41ee5SHelge Deller static time_t rtc_ref;
114e2c41ee5SHelge Deller
io_cpu_read(void * opaque,hwaddr addr,unsigned size)115e2c41ee5SHelge Deller static uint64_t io_cpu_read(void *opaque, hwaddr addr, unsigned size)
116e2c41ee5SHelge Deller {
117e2c41ee5SHelge Deller uint64_t val = 0;
118e2c41ee5SHelge Deller
119e2c41ee5SHelge Deller switch (addr) {
120e2c41ee5SHelge Deller case 0: /* RTC clock */
121e2c41ee5SHelge Deller val = time(NULL);
122e2c41ee5SHelge Deller val += rtc_ref;
123e2c41ee5SHelge Deller break;
124e2c41ee5SHelge Deller case 8: /* DebugOutputPort */
125e2c41ee5SHelge Deller return 0xe9; /* readback */
126e2c41ee5SHelge Deller }
127e2c41ee5SHelge Deller return val;
128e2c41ee5SHelge Deller }
129e2c41ee5SHelge Deller
io_cpu_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)130e2c41ee5SHelge Deller static void io_cpu_write(void *opaque, hwaddr addr,
131e2c41ee5SHelge Deller uint64_t val, unsigned size)
132e2c41ee5SHelge Deller {
133e2c41ee5SHelge Deller unsigned char ch;
134e2c41ee5SHelge Deller Chardev *debugout;
135e2c41ee5SHelge Deller
136e2c41ee5SHelge Deller switch (addr) {
137e2c41ee5SHelge Deller case 0: /* RTC clock */
138e2c41ee5SHelge Deller rtc_ref = val - time(NULL);
139e2c41ee5SHelge Deller break;
140e2c41ee5SHelge Deller case 8: /* DebugOutputPort */
141e2c41ee5SHelge Deller ch = val;
142e2c41ee5SHelge Deller debugout = serial_hd(0);
143e2c41ee5SHelge Deller if (debugout) {
144e2c41ee5SHelge Deller qemu_chr_fe_write_all(debugout->be, &ch, 1);
145e2c41ee5SHelge Deller } else {
146e2c41ee5SHelge Deller fprintf(stderr, "%c", ch);
147e2c41ee5SHelge Deller }
148e2c41ee5SHelge Deller break;
149e2c41ee5SHelge Deller }
150e2c41ee5SHelge Deller }
151e2c41ee5SHelge Deller
152e2c41ee5SHelge Deller static const MemoryRegionOps hppa_io_helper_ops = {
153e2c41ee5SHelge Deller .read = io_cpu_read,
154e2c41ee5SHelge Deller .write = io_cpu_write,
155e2c41ee5SHelge Deller .endianness = DEVICE_BIG_ENDIAN,
156e2c41ee5SHelge Deller .valid = {
157e2c41ee5SHelge Deller .min_access_size = 1,
158e2c41ee5SHelge Deller .max_access_size = 8,
159e2c41ee5SHelge Deller },
160e2c41ee5SHelge Deller .impl = {
161e2c41ee5SHelge Deller .min_access_size = 1,
162e2c41ee5SHelge Deller .max_access_size = 8,
163e2c41ee5SHelge Deller },
164e2c41ee5SHelge Deller };
165e2c41ee5SHelge Deller
166f386a16eSRichard Henderson typedef uint64_t TranslateFn(void *opaque, uint64_t addr);
167e2c41ee5SHelge Deller
linux_kernel_virt_to_phys(void * opaque,uint64_t addr)168f386a16eSRichard Henderson static uint64_t linux_kernel_virt_to_phys(void *opaque, uint64_t addr)
169a72bd606SHelge Deller {
170a72bd606SHelge Deller addr &= (0x10000000 - 1);
171a72bd606SHelge Deller return addr;
172a72bd606SHelge Deller }
173a72bd606SHelge Deller
translate_pa10(void * dummy,uint64_t addr)174f386a16eSRichard Henderson static uint64_t translate_pa10(void *dummy, uint64_t addr)
175f386a16eSRichard Henderson {
176f386a16eSRichard Henderson return (uint32_t)addr;
177f386a16eSRichard Henderson }
178f386a16eSRichard Henderson
translate_pa20(void * dummy,uint64_t addr)179f386a16eSRichard Henderson static uint64_t translate_pa20(void *dummy, uint64_t addr)
180f386a16eSRichard Henderson {
181f386a16eSRichard Henderson return hppa_abs_to_phys_pa2_w0(addr);
182f386a16eSRichard Henderson }
183f386a16eSRichard Henderson
184a72bd606SHelge Deller static HPPACPU *cpu[HPPA_MAX_CPUS];
185a72bd606SHelge Deller static uint64_t firmware_entry;
186813dff13SHelge Deller
fw_cfg_boot_set(void * opaque,const char * boot_device,Error ** errp)18732ff8bf2SHelge Deller static void fw_cfg_boot_set(void *opaque, const char *boot_device,
18832ff8bf2SHelge Deller Error **errp)
18932ff8bf2SHelge Deller {
19032ff8bf2SHelge Deller fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
19132ff8bf2SHelge Deller }
19232ff8bf2SHelge Deller
create_fw_cfg(MachineState * ms,PCIBus * pci_bus,hwaddr addr)193f386a16eSRichard Henderson static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
194f386a16eSRichard Henderson hwaddr addr)
19528b71a2eSHelge Deller {
19628b71a2eSHelge Deller FWCfgState *fw_cfg;
19728b71a2eSHelge Deller uint64_t val;
198069d2966SHelge Deller const char qemu_version[] = QEMU_VERSION;
199bcd4dd4cSHelge Deller MachineClass *mc = MACHINE_GET_CLASS(ms);
2009cf2112bSRichard Henderson int btlb_entries = HPPA_BTLB_ENTRIES(&cpu[0]->env);
201bcd4dd4cSHelge Deller int len;
20228b71a2eSHelge Deller
203f386a16eSRichard Henderson fw_cfg = fw_cfg_init_mem(addr, addr + 4);
20428b71a2eSHelge Deller fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
20528b71a2eSHelge Deller fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
206bfdf22bcSPaolo Bonzini fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
20728b71a2eSHelge Deller
20828b71a2eSHelge Deller val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
20928b71a2eSHelge Deller fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
2100572f011SPhilippe Mathieu-Daudé g_memdup2(&val, sizeof(val)), sizeof(val));
21128b71a2eSHelge Deller
2129cf2112bSRichard Henderson val = cpu_to_le64(HPPA_TLB_ENTRIES - btlb_entries);
213df5c6a50SHelge Deller fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
2140572f011SPhilippe Mathieu-Daudé g_memdup2(&val, sizeof(val)), sizeof(val));
215df5c6a50SHelge Deller
2169cf2112bSRichard Henderson val = cpu_to_le64(btlb_entries);
217bcd4dd4cSHelge Deller fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
2180572f011SPhilippe Mathieu-Daudé g_memdup2(&val, sizeof(val)), sizeof(val));
219bcd4dd4cSHelge Deller
220bcd4dd4cSHelge Deller len = strlen(mc->name) + 1;
221bcd4dd4cSHelge Deller fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
2220572f011SPhilippe Mathieu-Daudé g_memdup2(mc->name, len), len);
223bcd4dd4cSHelge Deller
224ed35afcbSHelge Deller val = cpu_to_le64(soft_power_reg);
225bcd4dd4cSHelge Deller fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
2260572f011SPhilippe Mathieu-Daudé g_memdup2(&val, sizeof(val)), sizeof(val));
227bcd4dd4cSHelge Deller
228e2c41ee5SHelge Deller val = cpu_to_le64(CPU_HPA + 16);
229e2c41ee5SHelge Deller fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
2300572f011SPhilippe Mathieu-Daudé g_memdup2(&val, sizeof(val)), sizeof(val));
231e2c41ee5SHelge Deller
232bcd4dd4cSHelge Deller val = cpu_to_le64(CPU_HPA + 24);
233bcd4dd4cSHelge Deller fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
2340572f011SPhilippe Mathieu-Daudé g_memdup2(&val, sizeof(val)), sizeof(val));
235b28c4a64SHelge Deller
23697ec4d21SPaolo Bonzini fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
23732ff8bf2SHelge Deller qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
23832ff8bf2SHelge Deller
239069d2966SHelge Deller fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
2400572f011SPhilippe Mathieu-Daudé g_memdup2(qemu_version, sizeof(qemu_version)),
241069d2966SHelge Deller sizeof(qemu_version));
242069d2966SHelge Deller
243bcd4dd4cSHelge Deller fw_cfg_add_extra_pci_roots(pci_bus, fw_cfg);
244bcd4dd4cSHelge Deller
24528b71a2eSHelge Deller return fw_cfg;
24628b71a2eSHelge Deller }
24728b71a2eSHelge Deller
lasi_init(void)248e881e3c8SMark Cave-Ayland static LasiState *lasi_init(void)
249e881e3c8SMark Cave-Ayland {
250e881e3c8SMark Cave-Ayland DeviceState *dev;
251e881e3c8SMark Cave-Ayland
252e881e3c8SMark Cave-Ayland dev = qdev_new(TYPE_LASI_CHIP);
253e881e3c8SMark Cave-Ayland sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
254e881e3c8SMark Cave-Ayland
255e881e3c8SMark Cave-Ayland return LASI_CHIP(dev);
256e881e3c8SMark Cave-Ayland }
257e881e3c8SMark Cave-Ayland
dino_init(MemoryRegion * addr_space)2580d068996SMark Cave-Ayland static DinoState *dino_init(MemoryRegion *addr_space)
2590d068996SMark Cave-Ayland {
2600d068996SMark Cave-Ayland DeviceState *dev;
2610d068996SMark Cave-Ayland
2620d068996SMark Cave-Ayland dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
2630d068996SMark Cave-Ayland object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
2640d068996SMark Cave-Ayland &error_fatal);
2650d068996SMark Cave-Ayland sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
2660d068996SMark Cave-Ayland
2670d068996SMark Cave-Ayland return DINO_PCI_HOST_BRIDGE(dev);
2680d068996SMark Cave-Ayland }
2690d068996SMark Cave-Ayland
2707df6f751SHelge Deller /*
2717df6f751SHelge Deller * Step 1: Create CPUs and Memory
2727df6f751SHelge Deller */
machine_HP_common_init_cpus(MachineState * machine)273f386a16eSRichard Henderson static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
274813dff13SHelge Deller {
275a72bd606SHelge Deller MemoryRegion *addr_space = get_system_memory();
27633decbd2SLike Xu unsigned int smp_cpus = machine->smp.cpus;
277f386a16eSRichard Henderson TranslateFn *translate;
278f386a16eSRichard Henderson MemoryRegion *cpu_region;
27992039f61SHelge Deller uint64_t ram_max;
280a72bd606SHelge Deller
281a72bd606SHelge Deller /* Create CPUs. */
282f386a16eSRichard Henderson for (unsigned int i = 0; i < smp_cpus; i++) {
283a72bd606SHelge Deller cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
284f386a16eSRichard Henderson }
285f386a16eSRichard Henderson
286f386a16eSRichard Henderson /*
287f386a16eSRichard Henderson * For now, treat address layout as if PSW_W is clear.
288f386a16eSRichard Henderson * TODO: create a proper hppa64 board model and load elf64 firmware.
289f386a16eSRichard Henderson */
290f386a16eSRichard Henderson if (hppa_is_pa20(&cpu[0]->env)) {
291f386a16eSRichard Henderson translate = translate_pa20;
29292039f61SHelge Deller ram_max = 0xf0000000; /* 3.75 GB (limited by 32-bit firmware) */
293f386a16eSRichard Henderson } else {
294f386a16eSRichard Henderson translate = translate_pa10;
29592039f61SHelge Deller ram_max = 0xf0000000; /* 3.75 GB (32-bit CPU) */
296f386a16eSRichard Henderson }
297f386a16eSRichard Henderson
298ed35afcbSHelge Deller soft_power_reg = translate(NULL, HPA_POWER_BUTTON);
299ed35afcbSHelge Deller
300f386a16eSRichard Henderson for (unsigned int i = 0; i < smp_cpus; i++) {
301f386a16eSRichard Henderson g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
302a72bd606SHelge Deller
303a72bd606SHelge Deller cpu_region = g_new(MemoryRegion, 1);
304a72bd606SHelge Deller memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
305266a880eSPaolo Bonzini cpu[i], name, 4);
306f386a16eSRichard Henderson memory_region_add_subregion(addr_space,
307f386a16eSRichard Henderson translate(NULL, CPU_HPA + i * 0x1000),
308a72bd606SHelge Deller cpu_region);
309813dff13SHelge Deller }
310813dff13SHelge Deller
311e2c41ee5SHelge Deller /* RTC and DebugOutputPort on CPU #0 */
312e2c41ee5SHelge Deller cpu_region = g_new(MemoryRegion, 1);
313e2c41ee5SHelge Deller memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
314e2c41ee5SHelge Deller cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
315f386a16eSRichard Henderson memory_region_add_subregion(addr_space, translate(NULL, CPU_HPA + 16),
316f386a16eSRichard Henderson cpu_region);
317e2c41ee5SHelge Deller
318a72bd606SHelge Deller /* Main memory region. */
31992039f61SHelge Deller if (machine->ram_size > ram_max) {
32092039f61SHelge Deller info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB);
32192039f61SHelge Deller machine->ram_size = ram_max;
322b7746b11SPhilippe Mathieu-Daudé }
3237c59c1e0SIgor Mammedov memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
324f386a16eSRichard Henderson
325f386a16eSRichard Henderson return translate;
3267df6f751SHelge Deller }
3277c59c1e0SIgor Mammedov
3287df6f751SHelge Deller /*
3297df6f751SHelge Deller * Last creation step: Add SCSI discs, NICs, graphics & load firmware
3307df6f751SHelge Deller */
machine_HP_common_init_tail(MachineState * machine,PCIBus * pci_bus,TranslateFn * translate)331f386a16eSRichard Henderson static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
332f386a16eSRichard Henderson TranslateFn *translate)
3337df6f751SHelge Deller {
3347df6f751SHelge Deller const char *kernel_filename = machine->kernel_filename;
3357df6f751SHelge Deller const char *kernel_cmdline = machine->kernel_cmdline;
3367df6f751SHelge Deller const char *initrd_filename = machine->initrd_filename;
337a9314795SHelge Deller const char *firmware = machine->firmware;
3387df6f751SHelge Deller MachineClass *mc = MACHINE_GET_CLASS(machine);
3397df6f751SHelge Deller DeviceState *dev;
3402ed4faa0SHelge Deller PCIDevice *pci_dev;
3417df6f751SHelge Deller char *firmware_filename;
3427df6f751SHelge Deller uint64_t firmware_low, firmware_high;
3437df6f751SHelge Deller long size;
3447df6f751SHelge Deller uint64_t kernel_entry = 0, kernel_low, kernel_high;
3457df6f751SHelge Deller MemoryRegion *addr_space = get_system_memory();
3467df6f751SHelge Deller MemoryRegion *rom_region;
3477df6f751SHelge Deller unsigned int smp_cpus = machine->smp.cpus;
3487df6f751SHelge Deller SysBusDevice *s;
34928b71a2eSHelge Deller
350a72bd606SHelge Deller /* SCSI disk setup. */
351d8a32200SHelge Deller if (drive_get_max_bus(IF_SCSI) >= 0) {
352877eb21dSMark Cave-Ayland dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
353877eb21dSMark Cave-Ayland lsi53c8xx_handle_legacy_cmdline(dev);
354d8a32200SHelge Deller }
355a72bd606SHelge Deller
3564765384cSSven Schnelle /* Graphics setup. */
3574765384cSSven Schnelle if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
358f9bcb2d6SGautam Agrawal vga_interface_created = true;
3593e80f690SMarkus Armbruster dev = qdev_new("artist");
3604765384cSSven Schnelle s = SYS_BUS_DEVICE(dev);
3613c6ef471SMarkus Armbruster sysbus_realize_and_unref(s, &error_fatal);
362f386a16eSRichard Henderson sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA));
363f386a16eSRichard Henderson sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR));
3644765384cSSven Schnelle }
3654765384cSSven Schnelle
3660e6de551SHelge Deller /* Network setup. */
3672a98878fSDavid Woodhouse if (lasi_dev) {
368f386a16eSRichard Henderson lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
3692a98878fSDavid Woodhouse qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
3702a98878fSDavid Woodhouse enable_lasi_lan());
371c3c3fe47SMark Cave-Ayland }
372c3c3fe47SMark Cave-Ayland
3732dfe2f86SDavid Woodhouse pci_init_nic_devices(pci_bus, mc->default_nic);
374a72bd606SHelge Deller
3752ed4faa0SHelge Deller /* BMC board: HP Powerbar SP2 Diva (with console only) */
3762ed4faa0SHelge Deller pci_dev = pci_new(-1, "pci-serial");
3772ed4faa0SHelge Deller if (!lasi_dev) {
3782ed4faa0SHelge Deller /* bind default keyboard/serial to Diva card */
3792ed4faa0SHelge Deller qdev_prop_set_chr(DEVICE(pci_dev), "chardev", serial_hd(0));
3802ed4faa0SHelge Deller }
3812ed4faa0SHelge Deller qdev_prop_set_uint8(DEVICE(pci_dev), "prog_if", 0);
3822ed4faa0SHelge Deller pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
3832ed4faa0SHelge Deller pci_config_set_vendor_id(pci_dev->config, PCI_VENDOR_ID_HP);
3842ed4faa0SHelge Deller pci_config_set_device_id(pci_dev->config, 0x1048);
3852ed4faa0SHelge Deller pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_VENDOR_ID], PCI_VENDOR_ID_HP);
3862ed4faa0SHelge Deller pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */
3872ed4faa0SHelge Deller
3882ed4faa0SHelge Deller /* create a second serial PCI card when running Astro */
389d8a32200SHelge Deller if (serial_hd(1) && !lasi_dev) {
3902ed4faa0SHelge Deller pci_dev = pci_new(-1, "pci-serial-4x");
3912ed4faa0SHelge Deller qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1));
3922ed4faa0SHelge Deller qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2));
3932ed4faa0SHelge Deller qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(3));
3942ed4faa0SHelge Deller qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(4));
3952ed4faa0SHelge Deller pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
3962ed4faa0SHelge Deller }
3972ed4faa0SHelge Deller
3982ed4faa0SHelge Deller /* create USB OHCI controller for USB keyboard & mouse on Astro machines */
39982523f4aSPaolo Bonzini if (!lasi_dev && machine->enable_graphics && defaults_enabled()) {
40082523f4aSPaolo Bonzini USBBus *usb_bus;
40182523f4aSPaolo Bonzini
4022ed4faa0SHelge Deller pci_create_simple(pci_bus, -1, "pci-ohci");
40382523f4aSPaolo Bonzini usb_bus = USB_BUS(object_resolve_type_unambiguous(TYPE_USB_BUS,
40482523f4aSPaolo Bonzini &error_abort));
40582523f4aSPaolo Bonzini usb_create_simple(usb_bus, "usb-kbd");
40682523f4aSPaolo Bonzini usb_create_simple(usb_bus, "usb-mouse");
4072ed4faa0SHelge Deller }
4082ed4faa0SHelge Deller
409b28c4a64SHelge Deller /* register power switch emulation */
410b28c4a64SHelge Deller qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
411b28c4a64SHelge Deller
4127df6f751SHelge Deller /* fw_cfg configuration interface */
413f386a16eSRichard Henderson create_fw_cfg(machine, pci_bus, translate(NULL, FW_CFG_IO_BASE));
4147df6f751SHelge Deller
415a72bd606SHelge Deller /* Load firmware. Given that this is not "real" firmware,
416a72bd606SHelge Deller but one explicitly written for the emulation, we might as
417a9314795SHelge Deller well load it directly from an ELF image. Load the 64-bit
418a9314795SHelge Deller firmware on 64-bit machines by default if not specified
419a9314795SHelge Deller on command line. */
420a9314795SHelge Deller if (!qtest_enabled()) {
421a9314795SHelge Deller if (!firmware) {
422a9314795SHelge Deller firmware = lasi_dev ? "hppa-firmware.img" : "hppa-firmware64.img";
423a9314795SHelge Deller }
424a9314795SHelge Deller firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
425a72bd606SHelge Deller if (firmware_filename == NULL) {
426a72bd606SHelge Deller error_report("no firmware provided");
427a72bd606SHelge Deller exit(1);
428a72bd606SHelge Deller }
429a72bd606SHelge Deller
430f386a16eSRichard Henderson size = load_elf(firmware_filename, NULL, translate, NULL,
4316cdda0ffSAleksandar Markovic &firmware_entry, &firmware_low, &firmware_high, NULL,
432a72bd606SHelge Deller true, EM_PARISC, 0, 0);
433a72bd606SHelge Deller
434a72bd606SHelge Deller if (size < 0) {
435a72bd606SHelge Deller error_report("could not load firmware '%s'", firmware_filename);
436a72bd606SHelge Deller exit(1);
437a72bd606SHelge Deller }
438691cbbadSRichard Henderson qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
439691cbbadSRichard Henderson "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
440a72bd606SHelge Deller firmware_low, firmware_high, firmware_entry);
441f386a16eSRichard Henderson if (firmware_low < translate(NULL, FIRMWARE_START) ||
442f386a16eSRichard Henderson firmware_high >= translate(NULL, FIRMWARE_END)) {
443a72bd606SHelge Deller error_report("Firmware overlaps with memory or IO space");
444a72bd606SHelge Deller exit(1);
445a72bd606SHelge Deller }
446a72bd606SHelge Deller g_free(firmware_filename);
447a9314795SHelge Deller }
448a72bd606SHelge Deller
449a72bd606SHelge Deller rom_region = g_new(MemoryRegion, 1);
4506a3a2e82SIgor Mammedov memory_region_init_ram(rom_region, NULL, "firmware",
4516a3a2e82SIgor Mammedov (FIRMWARE_END - FIRMWARE_START), &error_fatal);
452f386a16eSRichard Henderson memory_region_add_subregion(addr_space,
453f386a16eSRichard Henderson translate(NULL, FIRMWARE_START), rom_region);
454a72bd606SHelge Deller
455a72bd606SHelge Deller /* Load kernel */
456a72bd606SHelge Deller if (kernel_filename) {
457f386a16eSRichard Henderson size = load_elf(kernel_filename, NULL, linux_kernel_virt_to_phys,
4586cdda0ffSAleksandar Markovic NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
459a72bd606SHelge Deller true, EM_PARISC, 0, 0);
460a72bd606SHelge Deller
461f386a16eSRichard Henderson kernel_entry = linux_kernel_virt_to_phys(NULL, kernel_entry);
462a72bd606SHelge Deller
463a72bd606SHelge Deller if (size < 0) {
464a72bd606SHelge Deller error_report("could not load kernel '%s'", kernel_filename);
465a72bd606SHelge Deller exit(1);
466a72bd606SHelge Deller }
467691cbbadSRichard Henderson qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
468691cbbadSRichard Henderson "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
469c108cc59SPhilippe Mathieu-Daudé ", size %" PRIu64 " kB\n",
470c108cc59SPhilippe Mathieu-Daudé kernel_low, kernel_high, kernel_entry, size / KiB);
471a72bd606SHelge Deller
472a72bd606SHelge Deller if (kernel_cmdline) {
473a72bd606SHelge Deller cpu[0]->env.gr[24] = 0x4000;
474a72bd606SHelge Deller pstrcpy_targphys("cmdline", cpu[0]->env.gr[24],
475a72bd606SHelge Deller TARGET_PAGE_SIZE, kernel_cmdline);
476a72bd606SHelge Deller }
477a72bd606SHelge Deller
478a72bd606SHelge Deller if (initrd_filename) {
479a72bd606SHelge Deller ram_addr_t initrd_base;
480f3839fdaSLi Zhijian int64_t initrd_size;
481a72bd606SHelge Deller
482a72bd606SHelge Deller initrd_size = get_image_size(initrd_filename);
483a72bd606SHelge Deller if (initrd_size < 0) {
484a72bd606SHelge Deller error_report("could not load initial ram disk '%s'",
485a72bd606SHelge Deller initrd_filename);
486a72bd606SHelge Deller exit(1);
487a72bd606SHelge Deller }
488a72bd606SHelge Deller
489a72bd606SHelge Deller /* Load the initrd image high in memory.
490a72bd606SHelge Deller Mirror the algorithm used by palo:
491a72bd606SHelge Deller (1) Due to sign-extension problems and PDC,
492a72bd606SHelge Deller put the initrd no higher than 1G.
493a72bd606SHelge Deller (2) Reserve 64k for stack. */
494bfdf22bcSPaolo Bonzini initrd_base = MIN(machine->ram_size, 1 * GiB);
495c108cc59SPhilippe Mathieu-Daudé initrd_base = initrd_base - 64 * KiB;
496a72bd606SHelge Deller initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
497a72bd606SHelge Deller
498a72bd606SHelge Deller if (initrd_base < kernel_high) {
499a72bd606SHelge Deller error_report("kernel and initial ram disk too large!");
500a72bd606SHelge Deller exit(1);
501a72bd606SHelge Deller }
502a72bd606SHelge Deller
503a72bd606SHelge Deller load_image_targphys(initrd_filename, initrd_base, initrd_size);
504a72bd606SHelge Deller cpu[0]->env.gr[23] = initrd_base;
505a72bd606SHelge Deller cpu[0]->env.gr[22] = initrd_base + initrd_size;
506a72bd606SHelge Deller }
507a72bd606SHelge Deller }
508a72bd606SHelge Deller
509a72bd606SHelge Deller if (!kernel_entry) {
510a72bd606SHelge Deller /* When booting via firmware, tell firmware if we want interactive
511a72bd606SHelge Deller * mode (kernel_entry=1), and to boot from CD (gr[24]='d')
512a72bd606SHelge Deller * or hard disc * (gr[24]='c').
513a72bd606SHelge Deller */
51497ec4d21SPaolo Bonzini kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
51597ec4d21SPaolo Bonzini cpu[0]->env.gr[24] = machine->boot_config.order[0];
516a72bd606SHelge Deller }
517a72bd606SHelge Deller
518a72bd606SHelge Deller /* We jump to the firmware entry routine and pass the
519a72bd606SHelge Deller * various parameters in registers. After firmware initialization,
520a72bd606SHelge Deller * firmware will start the Linux kernel with ramdisk and cmdline.
521a72bd606SHelge Deller */
522bfdf22bcSPaolo Bonzini cpu[0]->env.gr[26] = machine->ram_size;
523a72bd606SHelge Deller cpu[0]->env.gr[25] = kernel_entry;
524a72bd606SHelge Deller
525a72bd606SHelge Deller /* tell firmware how many SMP CPUs to present in inventory table */
526a72bd606SHelge Deller cpu[0]->env.gr[21] = smp_cpus;
52724576007SHelge Deller
52824576007SHelge Deller /* tell firmware fw_cfg port */
52924576007SHelge Deller cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
530a72bd606SHelge Deller }
531a72bd606SHelge Deller
5327df6f751SHelge Deller /*
5337df6f751SHelge Deller * Create HP B160L workstation
5347df6f751SHelge Deller */
machine_HP_B160L_init(MachineState * machine)5357df6f751SHelge Deller static void machine_HP_B160L_init(MachineState *machine)
5367df6f751SHelge Deller {
5377df6f751SHelge Deller DeviceState *dev, *dino_dev;
5387df6f751SHelge Deller MemoryRegion *addr_space = get_system_memory();
539f386a16eSRichard Henderson TranslateFn *translate;
5407df6f751SHelge Deller ISABus *isa_bus;
5417df6f751SHelge Deller PCIBus *pci_bus;
5427df6f751SHelge Deller
5437df6f751SHelge Deller /* Create CPUs and RAM. */
544f386a16eSRichard Henderson translate = machine_HP_common_init_cpus(machine);
5457df6f751SHelge Deller
5463d1611bfSHelge Deller if (hppa_is_pa20(&cpu[0]->env)) {
5473d1611bfSHelge Deller error_report("The HP B160L workstation requires a 32-bit "
5483d1611bfSHelge Deller "CPU. Use '-machine C3700' instead.");
5493d1611bfSHelge Deller exit(1);
5503d1611bfSHelge Deller }
5513d1611bfSHelge Deller
5527df6f751SHelge Deller /* Init Lasi chip */
5537df6f751SHelge Deller lasi_dev = DEVICE(lasi_init());
554f386a16eSRichard Henderson memory_region_add_subregion(addr_space, translate(NULL, LASI_HPA),
5557df6f751SHelge Deller sysbus_mmio_get_region(
5567df6f751SHelge Deller SYS_BUS_DEVICE(lasi_dev), 0));
5577df6f751SHelge Deller
5587df6f751SHelge Deller /* Init Dino (PCI host bus chip). */
5597df6f751SHelge Deller dino_dev = DEVICE(dino_init(addr_space));
560f386a16eSRichard Henderson memory_region_add_subregion(addr_space, translate(NULL, DINO_HPA),
5617df6f751SHelge Deller sysbus_mmio_get_region(
5627df6f751SHelge Deller SYS_BUS_DEVICE(dino_dev), 0));
5637df6f751SHelge Deller pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
5647df6f751SHelge Deller assert(pci_bus);
5657df6f751SHelge Deller
5667df6f751SHelge Deller /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
567f386a16eSRichard Henderson isa_bus = hppa_isa_bus(translate(NULL, IDE_HPA));
5687df6f751SHelge Deller assert(isa_bus);
5697df6f751SHelge Deller
5707df6f751SHelge Deller /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
571f386a16eSRichard Henderson serial_mm_init(addr_space, translate(NULL, LASI_UART_HPA + 0x800), 0,
5727df6f751SHelge Deller qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
5737df6f751SHelge Deller serial_hd(0), DEVICE_BIG_ENDIAN);
5747df6f751SHelge Deller
575f386a16eSRichard Henderson serial_mm_init(addr_space, translate(NULL, DINO_UART_HPA + 0x800), 0,
5767df6f751SHelge Deller qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
5777df6f751SHelge Deller serial_hd(1), DEVICE_BIG_ENDIAN);
5787df6f751SHelge Deller
5797df6f751SHelge Deller /* Parallel port */
580f386a16eSRichard Henderson parallel_mm_init(addr_space, translate(NULL, LASI_LPT_HPA + 0x800), 0,
5817df6f751SHelge Deller qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
5827df6f751SHelge Deller parallel_hds[0]);
5837df6f751SHelge Deller
5847df6f751SHelge Deller /* PS/2 Keyboard/Mouse */
5857df6f751SHelge Deller dev = qdev_new(TYPE_LASIPS2);
5867df6f751SHelge Deller sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
5877df6f751SHelge Deller sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
5887df6f751SHelge Deller qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
589f386a16eSRichard Henderson memory_region_add_subregion(addr_space,
590f386a16eSRichard Henderson translate(NULL, LASI_PS2KBD_HPA),
5917df6f751SHelge Deller sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5927df6f751SHelge Deller 0));
593f386a16eSRichard Henderson memory_region_add_subregion(addr_space,
594f386a16eSRichard Henderson translate(NULL, LASI_PS2KBD_HPA + 0x100),
5957df6f751SHelge Deller sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5967df6f751SHelge Deller 1));
5977df6f751SHelge Deller
5987df6f751SHelge Deller /* Add SCSI discs, NICs, graphics & load firmware */
599f386a16eSRichard Henderson machine_HP_common_init_tail(machine, pci_bus, translate);
6007df6f751SHelge Deller }
6017df6f751SHelge Deller
astro_init(void)6022ed4faa0SHelge Deller static AstroState *astro_init(void)
6032ed4faa0SHelge Deller {
6042ed4faa0SHelge Deller DeviceState *dev;
6052ed4faa0SHelge Deller
6062ed4faa0SHelge Deller dev = qdev_new(TYPE_ASTRO_CHIP);
6072ed4faa0SHelge Deller sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
6082ed4faa0SHelge Deller
6092ed4faa0SHelge Deller return ASTRO_CHIP(dev);
6102ed4faa0SHelge Deller }
6112ed4faa0SHelge Deller
6122ed4faa0SHelge Deller /*
6132ed4faa0SHelge Deller * Create HP C3700 workstation
6142ed4faa0SHelge Deller */
machine_HP_C3700_init(MachineState * machine)6152ed4faa0SHelge Deller static void machine_HP_C3700_init(MachineState *machine)
6162ed4faa0SHelge Deller {
6172ed4faa0SHelge Deller PCIBus *pci_bus;
6182ed4faa0SHelge Deller AstroState *astro;
6192ed4faa0SHelge Deller DeviceState *astro_dev;
6202ed4faa0SHelge Deller MemoryRegion *addr_space = get_system_memory();
621f386a16eSRichard Henderson TranslateFn *translate;
6222ed4faa0SHelge Deller
6232ed4faa0SHelge Deller /* Create CPUs and RAM. */
624f386a16eSRichard Henderson translate = machine_HP_common_init_cpus(machine);
6252ed4faa0SHelge Deller
6263d1611bfSHelge Deller if (!hppa_is_pa20(&cpu[0]->env)) {
6273d1611bfSHelge Deller error_report("The HP C3000 workstation requires a 64-bit CPU. "
6283d1611bfSHelge Deller "Use '-machine B160L' instead.");
6293d1611bfSHelge Deller exit(1);
6303d1611bfSHelge Deller }
6313d1611bfSHelge Deller
6322ed4faa0SHelge Deller /* Init Astro and the Elroys (PCI host bus chips). */
6332ed4faa0SHelge Deller astro = astro_init();
6342ed4faa0SHelge Deller astro_dev = DEVICE(astro);
635f386a16eSRichard Henderson memory_region_add_subregion(addr_space, translate(NULL, ASTRO_HPA),
6362ed4faa0SHelge Deller sysbus_mmio_get_region(
6372ed4faa0SHelge Deller SYS_BUS_DEVICE(astro_dev), 0));
6382ed4faa0SHelge Deller pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(astro->elroy[0]), "pci"));
6392ed4faa0SHelge Deller assert(pci_bus);
6402ed4faa0SHelge Deller
6412ed4faa0SHelge Deller /* Add SCSI discs, NICs, graphics & load firmware */
642f386a16eSRichard Henderson machine_HP_common_init_tail(machine, pci_bus, translate);
6432ed4faa0SHelge Deller }
6442ed4faa0SHelge Deller
hppa_machine_reset(MachineState * ms,ResetType type)6451b063fe2SJuraj Marcin static void hppa_machine_reset(MachineState *ms, ResetType type)
646a72bd606SHelge Deller {
64733decbd2SLike Xu unsigned int smp_cpus = ms->smp.cpus;
648a72bd606SHelge Deller int i;
649a72bd606SHelge Deller
6501b063fe2SJuraj Marcin qemu_devices_reset(type);
651a72bd606SHelge Deller
652a72bd606SHelge Deller /* Start all CPUs at the firmware entry point.
653a72bd606SHelge Deller * Monarch CPU will initialize firmware, secondary CPUs
65450ba97e9SHelge Deller * will enter a small idle loop and wait for rendevouz. */
655a72bd606SHelge Deller for (i = 0; i < smp_cpus; i++) {
65650ba97e9SHelge Deller CPUState *cs = CPU(cpu[i]);
65750ba97e9SHelge Deller
65850ba97e9SHelge Deller cpu_set_pc(cs, firmware_entry);
65950ba97e9SHelge Deller cpu[i]->env.psw = PSW_Q;
660a72bd606SHelge Deller cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
66150ba97e9SHelge Deller
66250ba97e9SHelge Deller cs->exception_index = -1;
66350ba97e9SHelge Deller cs->halted = 0;
664a72bd606SHelge Deller }
665a72bd606SHelge Deller
666a72bd606SHelge Deller /* already initialized by machine_hppa_init()? */
667bfdf22bcSPaolo Bonzini if (cpu[0]->env.gr[26] == ms->ram_size) {
668a72bd606SHelge Deller return;
669a72bd606SHelge Deller }
670a72bd606SHelge Deller
671bfdf22bcSPaolo Bonzini cpu[0]->env.gr[26] = ms->ram_size;
672a72bd606SHelge Deller cpu[0]->env.gr[25] = 0; /* no firmware boot menu */
673a72bd606SHelge Deller cpu[0]->env.gr[24] = 'c';
674a72bd606SHelge Deller /* gr22/gr23 unused, no initrd while reboot. */
675a72bd606SHelge Deller cpu[0]->env.gr[21] = smp_cpus;
67624576007SHelge Deller /* tell firmware fw_cfg port */
67724576007SHelge Deller cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
678a72bd606SHelge Deller }
679a72bd606SHelge Deller
hppa_nmi(NMIState * n,int cpu_index,Error ** errp)6804a4554c6SHelge Deller static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
6814a4554c6SHelge Deller {
6824a4554c6SHelge Deller CPUState *cs;
6834a4554c6SHelge Deller
6844a4554c6SHelge Deller CPU_FOREACH(cs) {
6854a4554c6SHelge Deller cpu_interrupt(cs, CPU_INTERRUPT_NMI);
6864a4554c6SHelge Deller }
6874a4554c6SHelge Deller }
688a72bd606SHelge Deller
HP_B160L_machine_init_class_init(ObjectClass * oc,void * data)689790a4428SGavin Shan static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
690790a4428SGavin Shan {
691790a4428SGavin Shan static const char * const valid_cpu_types[] = {
6923d1611bfSHelge Deller TYPE_HPPA_CPU,
6933d1611bfSHelge Deller NULL
6943d1611bfSHelge Deller };
69542cc2bf6SMark Cave-Ayland MachineClass *mc = MACHINE_CLASS(oc);
69642cc2bf6SMark Cave-Ayland NMIClass *nc = NMI_CLASS(oc);
69742cc2bf6SMark Cave-Ayland
6987df6f751SHelge Deller mc->desc = "HP B160L workstation";
699a72bd606SHelge Deller mc->default_cpu_type = TYPE_HPPA_CPU;
700790a4428SGavin Shan mc->valid_cpu_types = valid_cpu_types;
7017df6f751SHelge Deller mc->init = machine_HP_B160L_init;
702a72bd606SHelge Deller mc->reset = hppa_machine_reset;
703813dff13SHelge Deller mc->block_default_type = IF_SCSI;
704a72bd606SHelge Deller mc->max_cpus = HPPA_MAX_CPUS;
705a72bd606SHelge Deller mc->default_cpus = 1;
706ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true;
707d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB;
708813dff13SHelge Deller mc->default_boot_order = "cd";
7097c59c1e0SIgor Mammedov mc->default_ram_id = "ram";
7109f8981a9SThomas Huth mc->default_nic = "tulip";
711813dff13SHelge Deller
7124a4554c6SHelge Deller nc->nmi_monitor_handler = hppa_nmi;
7134a4554c6SHelge Deller }
7144a4554c6SHelge Deller
7157df6f751SHelge Deller static const TypeInfo HP_B160L_machine_init_typeinfo = {
7167df6f751SHelge Deller .name = MACHINE_TYPE_NAME("B160L"),
717c165905cSMark Cave-Ayland .parent = TYPE_MACHINE,
7187df6f751SHelge Deller .class_init = HP_B160L_machine_init_class_init,
7194a4554c6SHelge Deller .interfaces = (InterfaceInfo[]) {
7204a4554c6SHelge Deller { TYPE_NMI },
7214a4554c6SHelge Deller { }
7224a4554c6SHelge Deller },
7234a4554c6SHelge Deller };
7244a4554c6SHelge Deller
HP_C3700_machine_init_class_init(ObjectClass * oc,void * data)725790a4428SGavin Shan static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data)
726790a4428SGavin Shan {
727790a4428SGavin Shan static const char * const valid_cpu_types[] = {
7283d1611bfSHelge Deller TYPE_HPPA64_CPU,
7293d1611bfSHelge Deller NULL
7303d1611bfSHelge Deller };
7312ed4faa0SHelge Deller MachineClass *mc = MACHINE_CLASS(oc);
7322ed4faa0SHelge Deller NMIClass *nc = NMI_CLASS(oc);
7332ed4faa0SHelge Deller
7342ed4faa0SHelge Deller mc->desc = "HP C3700 workstation";
735fd9b04bfSHelge Deller mc->default_cpu_type = TYPE_HPPA64_CPU;
736790a4428SGavin Shan mc->valid_cpu_types = valid_cpu_types;
7372ed4faa0SHelge Deller mc->init = machine_HP_C3700_init;
7382ed4faa0SHelge Deller mc->reset = hppa_machine_reset;
7392ed4faa0SHelge Deller mc->block_default_type = IF_SCSI;
7402ed4faa0SHelge Deller mc->max_cpus = HPPA_MAX_CPUS;
7412ed4faa0SHelge Deller mc->default_cpus = 1;
7422ed4faa0SHelge Deller mc->is_default = false;
7432ed4faa0SHelge Deller mc->default_ram_size = 1024 * MiB;
7442ed4faa0SHelge Deller mc->default_boot_order = "cd";
7452ed4faa0SHelge Deller mc->default_ram_id = "ram";
7462ed4faa0SHelge Deller mc->default_nic = "tulip";
7472ed4faa0SHelge Deller
7482ed4faa0SHelge Deller nc->nmi_monitor_handler = hppa_nmi;
7492ed4faa0SHelge Deller }
7502ed4faa0SHelge Deller
7512ed4faa0SHelge Deller static const TypeInfo HP_C3700_machine_init_typeinfo = {
7522ed4faa0SHelge Deller .name = MACHINE_TYPE_NAME("C3700"),
7532ed4faa0SHelge Deller .parent = TYPE_MACHINE,
7542ed4faa0SHelge Deller .class_init = HP_C3700_machine_init_class_init,
7552ed4faa0SHelge Deller .interfaces = (InterfaceInfo[]) {
7562ed4faa0SHelge Deller { TYPE_NMI },
7572ed4faa0SHelge Deller { }
7582ed4faa0SHelge Deller },
7592ed4faa0SHelge Deller };
7602ed4faa0SHelge Deller
hppa_machine_init_register_types(void)761297d4103SMark Cave-Ayland static void hppa_machine_init_register_types(void)
7624a4554c6SHelge Deller {
7637df6f751SHelge Deller type_register_static(&HP_B160L_machine_init_typeinfo);
7642ed4faa0SHelge Deller type_register_static(&HP_C3700_machine_init_typeinfo);
7654a4554c6SHelge Deller }
7664a4554c6SHelge Deller
767297d4103SMark Cave-Ayland type_init(hppa_machine_init_register_types)
768