175610155SAndreas Färber /*
275610155SAndreas Färber * QEMU PPC PREP hardware System Emulator
375610155SAndreas Färber *
475610155SAndreas Färber * Copyright (c) 2003-2007 Jocelyn Mayer
534b9b557SHervé Poussineau * Copyright (c) 2017 Hervé Poussineau
675610155SAndreas Färber *
775610155SAndreas Färber * Permission is hereby granted, free of charge, to any person obtaining a copy
875610155SAndreas Färber * of this software and associated documentation files (the "Software"), to deal
975610155SAndreas Färber * in the Software without restriction, including without limitation the rights
1075610155SAndreas Färber * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1175610155SAndreas Färber * copies of the Software, and to permit persons to whom the Software is
1275610155SAndreas Färber * furnished to do so, subject to the following conditions:
1375610155SAndreas Färber *
1475610155SAndreas Färber * The above copyright notice and this permission notice shall be included in
1575610155SAndreas Färber * all copies or substantial portions of the Software.
1675610155SAndreas Färber *
1775610155SAndreas Färber * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1875610155SAndreas Färber * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1975610155SAndreas Färber * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2075610155SAndreas Färber * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2175610155SAndreas Färber * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2275610155SAndreas Färber * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2375610155SAndreas Färber * THE SOFTWARE.
2475610155SAndreas Färber */
2571e8a915SMarkus Armbruster
260d75590dSPeter Maydell #include "qemu/osdep.h"
27819ce6b2SPhilippe Mathieu-Daudé #include "hw/rtc/m48t59.h"
280d09e41aSPaolo Bonzini #include "hw/block/fdc.h"
2975610155SAndreas Färber #include "net/net.h"
300d09e41aSPaolo Bonzini #include "hw/isa/isa.h"
3175610155SAndreas Färber #include "hw/pci/pci.h"
3275610155SAndreas Färber #include "hw/pci/pci_host.h"
330d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h"
3475610155SAndreas Färber #include "hw/boards.h"
353e80f690SMarkus Armbruster #include "qapi/error.h"
36c525436eSMarkus Armbruster #include "qemu/error-report.h"
3775610155SAndreas Färber #include "qemu/log.h"
3875610155SAndreas Färber #include "hw/loader.h"
39bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
400d09e41aSPaolo Bonzini #include "hw/isa/pc87312.h"
41b2ce76a0SThomas Huth #include "hw/qdev-properties.h"
4234b9b557SHervé Poussineau #include "sysemu/kvm.h"
4371e8a915SMarkus Armbruster #include "sysemu/reset.h"
44659f7f65SPaolo Bonzini #include "trace.h"
4597c42c3cSAndreas Färber #include "elf.h"
46ab3dd749SPhilippe Mathieu-Daudé #include "qemu/units.h"
472b163972SMartin Kletzander #include "audio/audio.h"
4875610155SAndreas Färber
4975610155SAndreas Färber /* SMP is not enabled, for now */
5075610155SAndreas Färber #define MAX_CPUS 1
5175610155SAndreas Färber
5234b9b557SHervé Poussineau #define CFG_ADDR 0xf0000510
5334b9b557SHervé Poussineau
5475610155SAndreas Färber #define KERNEL_LOAD_ADDR 0x01000000
5575610155SAndreas Färber #define INITRD_LOAD_ADDR 0x01800000
5675610155SAndreas Färber
5775610155SAndreas Färber #define NVRAM_SIZE 0x2000
5875610155SAndreas Färber
fw_cfg_boot_set(void * opaque,const char * boot_device,Error ** errp)5934b9b557SHervé Poussineau static void fw_cfg_boot_set(void *opaque, const char *boot_device,
6034b9b557SHervé Poussineau Error **errp)
6134b9b557SHervé Poussineau {
6234b9b557SHervé Poussineau fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
6334b9b557SHervé Poussineau }
6434b9b557SHervé Poussineau
ppc_prep_reset(void * opaque)6575610155SAndreas Färber static void ppc_prep_reset(void *opaque)
6675610155SAndreas Färber {
6775610155SAndreas Färber PowerPCCPU *cpu = opaque;
6875610155SAndreas Färber
6975610155SAndreas Färber cpu_reset(CPU(cpu));
7030d0647bSNicholas Piggin cpu_ppc_tb_reset(&cpu->env);
7175610155SAndreas Färber }
7275610155SAndreas Färber
73848696bfSKirill Batuzov
7431688246SHervé Poussineau /*****************************************************************************/
7531688246SHervé Poussineau /* NVRAM helpers */
nvram_read(Nvram * nvram,uint32_t addr)7631688246SHervé Poussineau static inline uint32_t nvram_read(Nvram *nvram, uint32_t addr)
7731688246SHervé Poussineau {
785904bca8SHervé Poussineau NvramClass *k = NVRAM_GET_CLASS(nvram);
7931688246SHervé Poussineau return (k->read)(nvram, addr);
8031688246SHervé Poussineau }
8131688246SHervé Poussineau
nvram_write(Nvram * nvram,uint32_t addr,uint32_t val)8231688246SHervé Poussineau static inline void nvram_write(Nvram *nvram, uint32_t addr, uint32_t val)
8331688246SHervé Poussineau {
845904bca8SHervé Poussineau NvramClass *k = NVRAM_GET_CLASS(nvram);
8531688246SHervé Poussineau (k->write)(nvram, addr, val);
8631688246SHervé Poussineau }
8731688246SHervé Poussineau
NVRAM_set_byte(Nvram * nvram,uint32_t addr,uint8_t value)8831688246SHervé Poussineau static void NVRAM_set_byte(Nvram *nvram, uint32_t addr, uint8_t value)
8931688246SHervé Poussineau {
9031688246SHervé Poussineau nvram_write(nvram, addr, value);
9131688246SHervé Poussineau }
9231688246SHervé Poussineau
NVRAM_get_byte(Nvram * nvram,uint32_t addr)9331688246SHervé Poussineau static uint8_t NVRAM_get_byte(Nvram *nvram, uint32_t addr)
9431688246SHervé Poussineau {
9531688246SHervé Poussineau return nvram_read(nvram, addr);
9631688246SHervé Poussineau }
9731688246SHervé Poussineau
NVRAM_set_word(Nvram * nvram,uint32_t addr,uint16_t value)9831688246SHervé Poussineau static void NVRAM_set_word(Nvram *nvram, uint32_t addr, uint16_t value)
9931688246SHervé Poussineau {
10031688246SHervé Poussineau nvram_write(nvram, addr, value >> 8);
10131688246SHervé Poussineau nvram_write(nvram, addr + 1, value & 0xFF);
10231688246SHervé Poussineau }
10331688246SHervé Poussineau
NVRAM_get_word(Nvram * nvram,uint32_t addr)10431688246SHervé Poussineau static uint16_t NVRAM_get_word(Nvram *nvram, uint32_t addr)
10531688246SHervé Poussineau {
10631688246SHervé Poussineau uint16_t tmp;
10731688246SHervé Poussineau
10831688246SHervé Poussineau tmp = nvram_read(nvram, addr) << 8;
10931688246SHervé Poussineau tmp |= nvram_read(nvram, addr + 1);
11031688246SHervé Poussineau
11131688246SHervé Poussineau return tmp;
11231688246SHervé Poussineau }
11331688246SHervé Poussineau
NVRAM_set_lword(Nvram * nvram,uint32_t addr,uint32_t value)11431688246SHervé Poussineau static void NVRAM_set_lword(Nvram *nvram, uint32_t addr, uint32_t value)
11531688246SHervé Poussineau {
11631688246SHervé Poussineau nvram_write(nvram, addr, value >> 24);
11731688246SHervé Poussineau nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
11831688246SHervé Poussineau nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
11931688246SHervé Poussineau nvram_write(nvram, addr + 3, value & 0xFF);
12031688246SHervé Poussineau }
12131688246SHervé Poussineau
NVRAM_set_string(Nvram * nvram,uint32_t addr,const char * str,uint32_t max)12231688246SHervé Poussineau static void NVRAM_set_string(Nvram *nvram, uint32_t addr, const char *str,
12331688246SHervé Poussineau uint32_t max)
12431688246SHervé Poussineau {
12531688246SHervé Poussineau int i;
12631688246SHervé Poussineau
12731688246SHervé Poussineau for (i = 0; i < max && str[i] != '\0'; i++) {
12831688246SHervé Poussineau nvram_write(nvram, addr + i, str[i]);
12931688246SHervé Poussineau }
13031688246SHervé Poussineau nvram_write(nvram, addr + i, str[i]);
13131688246SHervé Poussineau nvram_write(nvram, addr + max - 1, '\0');
13231688246SHervé Poussineau }
13331688246SHervé Poussineau
NVRAM_crc_update(uint16_t prev,uint16_t value)13431688246SHervé Poussineau static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
13531688246SHervé Poussineau {
13631688246SHervé Poussineau uint16_t tmp;
13731688246SHervé Poussineau uint16_t pd, pd1, pd2;
13831688246SHervé Poussineau
13931688246SHervé Poussineau tmp = prev >> 8;
14031688246SHervé Poussineau pd = prev ^ value;
14131688246SHervé Poussineau pd1 = pd & 0x000F;
14231688246SHervé Poussineau pd2 = ((pd >> 4) & 0x000F) ^ pd1;
14331688246SHervé Poussineau tmp ^= (pd1 << 3) | (pd1 << 8);
14431688246SHervé Poussineau tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
14531688246SHervé Poussineau
14631688246SHervé Poussineau return tmp;
14731688246SHervé Poussineau }
14831688246SHervé Poussineau
NVRAM_compute_crc(Nvram * nvram,uint32_t start,uint32_t count)14931688246SHervé Poussineau static uint16_t NVRAM_compute_crc (Nvram *nvram, uint32_t start, uint32_t count)
15031688246SHervé Poussineau {
15131688246SHervé Poussineau uint32_t i;
15231688246SHervé Poussineau uint16_t crc = 0xFFFF;
15331688246SHervé Poussineau int odd;
15431688246SHervé Poussineau
15531688246SHervé Poussineau odd = count & 1;
15631688246SHervé Poussineau count &= ~1;
15731688246SHervé Poussineau for (i = 0; i != count; i++) {
15831688246SHervé Poussineau crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
15931688246SHervé Poussineau }
16031688246SHervé Poussineau if (odd) {
16131688246SHervé Poussineau crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
16231688246SHervé Poussineau }
16331688246SHervé Poussineau
16431688246SHervé Poussineau return crc;
16531688246SHervé Poussineau }
16631688246SHervé Poussineau
16731688246SHervé Poussineau #define CMDLINE_ADDR 0x017ff000
16831688246SHervé Poussineau
PPC_NVRAM_set_params(Nvram * nvram,uint16_t NVRAM_size,const char * arch,uint32_t RAM_size,int boot_device,uint32_t kernel_image,uint32_t kernel_size,const char * cmdline,uint32_t initrd_image,uint32_t initrd_size,uint32_t NVRAM_image,int width,int height,int depth)16931688246SHervé Poussineau static int PPC_NVRAM_set_params (Nvram *nvram, uint16_t NVRAM_size,
17031688246SHervé Poussineau const char *arch,
17131688246SHervé Poussineau uint32_t RAM_size, int boot_device,
17231688246SHervé Poussineau uint32_t kernel_image, uint32_t kernel_size,
17331688246SHervé Poussineau const char *cmdline,
17431688246SHervé Poussineau uint32_t initrd_image, uint32_t initrd_size,
17531688246SHervé Poussineau uint32_t NVRAM_image,
17631688246SHervé Poussineau int width, int height, int depth)
17731688246SHervé Poussineau {
17831688246SHervé Poussineau uint16_t crc;
17931688246SHervé Poussineau
18031688246SHervé Poussineau /* Set parameters for Open Hack'Ware BIOS */
18131688246SHervé Poussineau NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
18231688246SHervé Poussineau NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
18331688246SHervé Poussineau NVRAM_set_word(nvram, 0x14, NVRAM_size);
18431688246SHervé Poussineau NVRAM_set_string(nvram, 0x20, arch, 16);
18531688246SHervé Poussineau NVRAM_set_lword(nvram, 0x30, RAM_size);
18631688246SHervé Poussineau NVRAM_set_byte(nvram, 0x34, boot_device);
18731688246SHervé Poussineau NVRAM_set_lword(nvram, 0x38, kernel_image);
18831688246SHervé Poussineau NVRAM_set_lword(nvram, 0x3C, kernel_size);
18931688246SHervé Poussineau if (cmdline) {
19031688246SHervé Poussineau /* XXX: put the cmdline in NVRAM too ? */
19131688246SHervé Poussineau pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR,
19231688246SHervé Poussineau cmdline);
19331688246SHervé Poussineau NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
19431688246SHervé Poussineau NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
19531688246SHervé Poussineau } else {
19631688246SHervé Poussineau NVRAM_set_lword(nvram, 0x40, 0);
19731688246SHervé Poussineau NVRAM_set_lword(nvram, 0x44, 0);
19831688246SHervé Poussineau }
19931688246SHervé Poussineau NVRAM_set_lword(nvram, 0x48, initrd_image);
20031688246SHervé Poussineau NVRAM_set_lword(nvram, 0x4C, initrd_size);
20131688246SHervé Poussineau NVRAM_set_lword(nvram, 0x50, NVRAM_image);
20231688246SHervé Poussineau
20331688246SHervé Poussineau NVRAM_set_word(nvram, 0x54, width);
20431688246SHervé Poussineau NVRAM_set_word(nvram, 0x56, height);
20531688246SHervé Poussineau NVRAM_set_word(nvram, 0x58, depth);
20631688246SHervé Poussineau crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
20731688246SHervé Poussineau NVRAM_set_word(nvram, 0xFC, crc);
20831688246SHervé Poussineau
20931688246SHervé Poussineau return 0;
21031688246SHervé Poussineau }
21131688246SHervé Poussineau
prep_set_cmos_checksum(DeviceState * dev,void * opaque)21234b9b557SHervé Poussineau static int prep_set_cmos_checksum(DeviceState *dev, void *opaque)
21334b9b557SHervé Poussineau {
21434b9b557SHervé Poussineau uint16_t checksum = *(uint16_t *)opaque;
21534b9b557SHervé Poussineau
216c50be9e1SPhilippe Mathieu-Daudé if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
21755c86cb8SPhilippe Mathieu-Daudé MC146818RtcState *rtc = MC146818_RTC(dev);
2182d4bd81eSPhilippe Mathieu-Daudé mc146818rtc_set_cmos_data(rtc, 0x2e, checksum & 0xff);
2192d4bd81eSPhilippe Mathieu-Daudé mc146818rtc_set_cmos_data(rtc, 0x3e, checksum & 0xff);
2202d4bd81eSPhilippe Mathieu-Daudé mc146818rtc_set_cmos_data(rtc, 0x2f, checksum >> 8);
2212d4bd81eSPhilippe Mathieu-Daudé mc146818rtc_set_cmos_data(rtc, 0x3f, checksum >> 8);
22229551fdcSThomas Huth
22329551fdcSThomas Huth object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(rtc),
224d2623129SMarkus Armbruster "date");
22534b9b557SHervé Poussineau }
22634b9b557SHervé Poussineau return 0;
22734b9b557SHervé Poussineau }
22834b9b557SHervé Poussineau
ibm_40p_init(MachineState * machine)22934b9b557SHervé Poussineau static void ibm_40p_init(MachineState *machine)
23034b9b557SHervé Poussineau {
231cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: "openbios-ppc";
232053b7086SThomas Huth MachineClass *mc = MACHINE_GET_CLASS(machine);
23334b9b557SHervé Poussineau CPUPPCState *env = NULL;
23434b9b557SHervé Poussineau uint16_t cmos_checksum;
23534b9b557SHervé Poussineau PowerPCCPU *cpu;
2360358687bSMark Cave-Ayland DeviceState *dev, *i82378_dev;
2370f080859SMark Cave-Ayland SysBusDevice *pcihost, *s;
23834b9b557SHervé Poussineau Nvram *m48t59 = NULL;
23934b9b557SHervé Poussineau PCIBus *pci_bus;
24096927c74SMarkus Armbruster ISADevice *isa_dev;
24134b9b557SHervé Poussineau ISABus *isa_bus;
24234b9b557SHervé Poussineau void *fw_cfg;
24334b9b557SHervé Poussineau uint32_t kernel_base = 0, initrd_base = 0;
24434b9b557SHervé Poussineau long kernel_size = 0, initrd_size = 0;
24534b9b557SHervé Poussineau char boot_device;
24634b9b557SHervé Poussineau
2479df480dbSCédric Le Goater if (kvm_enabled()) {
2489df480dbSCédric Le Goater error_report("machine %s does not support the KVM accelerator",
2499df480dbSCédric Le Goater MACHINE_GET_CLASS(machine)->name);
2509df480dbSCédric Le Goater exit(EXIT_FAILURE);
2519df480dbSCédric Le Goater }
2529df480dbSCédric Le Goater
25334b9b557SHervé Poussineau /* init CPU */
25423ec69ecSIgor Mammedov cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
25534b9b557SHervé Poussineau env = &cpu->env;
25634b9b557SHervé Poussineau if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
25734b9b557SHervé Poussineau error_report("only 6xx bus is supported on this machine");
25834b9b557SHervé Poussineau exit(1);
25934b9b557SHervé Poussineau }
26034b9b557SHervé Poussineau
26134b9b557SHervé Poussineau /* Set time-base frequency to 100 Mhz */
26234b9b557SHervé Poussineau cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
26334b9b557SHervé Poussineau qemu_register_reset(ppc_prep_reset, cpu);
26434b9b557SHervé Poussineau
26534b9b557SHervé Poussineau /* PCI host */
2663e80f690SMarkus Armbruster dev = qdev_new("raven-pcihost");
26734b9b557SHervé Poussineau qdev_prop_set_string(dev, "bios-name", bios_name);
26834b9b557SHervé Poussineau qdev_prop_set_uint32(dev, "elf-machine", PPC_ELF_MACHINE);
26934b9b557SHervé Poussineau pcihost = SYS_BUS_DEVICE(dev);
270d2623129SMarkus Armbruster object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev));
2713c6ef471SMarkus Armbruster sysbus_realize_and_unref(pcihost, &error_fatal);
27234b9b557SHervé Poussineau pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0"));
27334b9b557SHervé Poussineau if (!pci_bus) {
27434b9b557SHervé Poussineau error_report("could not create PCI host controller");
27534b9b557SHervé Poussineau exit(1);
27634b9b557SHervé Poussineau }
27734b9b557SHervé Poussineau
27834b9b557SHervé Poussineau /* PCI -> ISA bridge */
2792237af5eSBernhard Beschow i82378_dev = DEVICE(pci_new(PCI_DEVFN(11, 0), "i82378"));
280*59ae6bcdSPhilippe Mathieu-Daudé qdev_realize_and_unref(i82378_dev, BUS(pci_bus), &error_fatal);
2810358687bSMark Cave-Ayland qdev_connect_gpio_out(i82378_dev, 0,
2820f3e0c6fSCédric Le Goater qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_INT));
2832237af5eSBernhard Beschow
2840358687bSMark Cave-Ayland sysbus_connect_irq(pcihost, 0, qdev_get_gpio_in(i82378_dev, 15));
2850358687bSMark Cave-Ayland isa_bus = ISA_BUS(qdev_get_child_bus(i82378_dev, "isa.0"));
28634b9b557SHervé Poussineau
28734b9b557SHervé Poussineau /* Memory controller */
28896927c74SMarkus Armbruster isa_dev = isa_new("rs6000-mc");
28996927c74SMarkus Armbruster dev = DEVICE(isa_dev);
29034b9b557SHervé Poussineau qdev_prop_set_uint32(dev, "ram-size", machine->ram_size);
29196927c74SMarkus Armbruster isa_realize_and_unref(isa_dev, isa_bus, &error_fatal);
29234b9b557SHervé Poussineau
2932e8f8518SPhilippe Mathieu-Daudé /* RTC */
29496927c74SMarkus Armbruster isa_dev = isa_new(TYPE_MC146818_RTC);
29596927c74SMarkus Armbruster dev = DEVICE(isa_dev);
2961dbe3d19SArtyom Tarasenko qdev_prop_set_int32(dev, "base_year", 1900);
29796927c74SMarkus Armbruster isa_realize_and_unref(isa_dev, isa_bus, &error_fatal);
2982e8f8518SPhilippe Mathieu-Daudé
29934b9b557SHervé Poussineau /* initialize CMOS checksums */
30034b9b557SHervé Poussineau cmos_checksum = 0x6aa9;
30134b9b557SHervé Poussineau qbus_walk_children(BUS(isa_bus), prep_set_cmos_checksum, NULL, NULL, NULL,
30234b9b557SHervé Poussineau &cmos_checksum);
30334b9b557SHervé Poussineau
30434b9b557SHervé Poussineau /* add some more devices */
30534b9b557SHervé Poussineau if (defaults_enabled()) {
30634b9b557SHervé Poussineau m48t59 = NVRAM(isa_create_simple(isa_bus, "isa-m48t59"));
30734b9b557SHervé Poussineau
30896927c74SMarkus Armbruster isa_dev = isa_new("cs4231a");
30996927c74SMarkus Armbruster dev = DEVICE(isa_dev);
31034b9b557SHervé Poussineau qdev_prop_set_uint32(dev, "iobase", 0x830);
31134b9b557SHervé Poussineau qdev_prop_set_uint32(dev, "irq", 10);
3122b163972SMartin Kletzander
3132b163972SMartin Kletzander if (machine->audiodev) {
3142b163972SMartin Kletzander qdev_prop_set_string(dev, "audiodev", machine->audiodev);
3152b163972SMartin Kletzander }
31696927c74SMarkus Armbruster isa_realize_and_unref(isa_dev, isa_bus, &error_fatal);
31734b9b557SHervé Poussineau
31896927c74SMarkus Armbruster isa_dev = isa_new("pc87312");
31996927c74SMarkus Armbruster dev = DEVICE(isa_dev);
32034b9b557SHervé Poussineau qdev_prop_set_uint32(dev, "config", 12);
32196927c74SMarkus Armbruster isa_realize_and_unref(isa_dev, isa_bus, &error_fatal);
32234b9b557SHervé Poussineau
32396927c74SMarkus Armbruster isa_dev = isa_new("prep-systemio");
32496927c74SMarkus Armbruster dev = DEVICE(isa_dev);
32534b9b557SHervé Poussineau qdev_prop_set_uint32(dev, "ibm-planar-id", 0xfc);
32634b9b557SHervé Poussineau qdev_prop_set_uint32(dev, "equipment", 0xc0);
32796927c74SMarkus Armbruster isa_realize_and_unref(isa_dev, isa_bus, &error_fatal);
32834b9b557SHervé Poussineau
329877eb21dSMark Cave-Ayland dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(1, 0),
330877eb21dSMark Cave-Ayland "lsi53c810"));
331877eb21dSMark Cave-Ayland lsi53c8xx_handle_legacy_cmdline(dev);
3320358687bSMark Cave-Ayland qdev_connect_gpio_out(dev, 0, qdev_get_gpio_in(i82378_dev, 13));
33334b9b557SHervé Poussineau
33434b9b557SHervé Poussineau /* XXX: s3-trio at PCI_DEVFN(2, 0) */
33534b9b557SHervé Poussineau pci_vga_init(pci_bus);
33634b9b557SHervé Poussineau
3374c717216SDavid Woodhouse /* First PCNET device at PCI_DEVFN(3, 0) */
3384c717216SDavid Woodhouse pci_init_nic_in_slot(pci_bus, mc->default_nic, NULL, "3");
3394c717216SDavid Woodhouse pci_init_nic_devices(pci_bus, mc->default_nic);
34034b9b557SHervé Poussineau }
34134b9b557SHervé Poussineau
34234b9b557SHervé Poussineau /* Prepare firmware configuration for OpenBIOS */
3433e80f690SMarkus Armbruster dev = qdev_new(TYPE_FW_CFG_MEM);
3440f080859SMark Cave-Ayland fw_cfg = FW_CFG(dev);
3450f080859SMark Cave-Ayland qdev_prop_set_uint32(dev, "data_width", 1);
3460f080859SMark Cave-Ayland qdev_prop_set_bit(dev, "dma_enabled", false);
3470f080859SMark Cave-Ayland object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
348d2623129SMarkus Armbruster OBJECT(fw_cfg));
3490f080859SMark Cave-Ayland s = SYS_BUS_DEVICE(dev);
3503c6ef471SMarkus Armbruster sysbus_realize_and_unref(s, &error_fatal);
3510f080859SMark Cave-Ayland sysbus_mmio_map(s, 0, CFG_ADDR);
3520f080859SMark Cave-Ayland sysbus_mmio_map(s, 1, CFG_ADDR + 2);
35334b9b557SHervé Poussineau
35434b9b557SHervé Poussineau if (machine->kernel_filename) {
35534b9b557SHervé Poussineau /* load kernel */
35634b9b557SHervé Poussineau kernel_base = KERNEL_LOAD_ADDR;
35734b9b557SHervé Poussineau kernel_size = load_image_targphys(machine->kernel_filename,
35834b9b557SHervé Poussineau kernel_base,
35934b9b557SHervé Poussineau machine->ram_size - kernel_base);
36034b9b557SHervé Poussineau if (kernel_size < 0) {
36134b9b557SHervé Poussineau error_report("could not load kernel '%s'",
36234b9b557SHervé Poussineau machine->kernel_filename);
36334b9b557SHervé Poussineau exit(1);
36434b9b557SHervé Poussineau }
36534b9b557SHervé Poussineau fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
36634b9b557SHervé Poussineau fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
36734b9b557SHervé Poussineau /* load initrd */
36834b9b557SHervé Poussineau if (machine->initrd_filename) {
36934b9b557SHervé Poussineau initrd_base = INITRD_LOAD_ADDR;
37034b9b557SHervé Poussineau initrd_size = load_image_targphys(machine->initrd_filename,
37134b9b557SHervé Poussineau initrd_base,
37234b9b557SHervé Poussineau machine->ram_size - initrd_base);
37334b9b557SHervé Poussineau if (initrd_size < 0) {
37434b9b557SHervé Poussineau error_report("could not load initial ram disk '%s'",
37534b9b557SHervé Poussineau machine->initrd_filename);
37634b9b557SHervé Poussineau exit(1);
37734b9b557SHervé Poussineau }
37834b9b557SHervé Poussineau fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base);
37934b9b557SHervé Poussineau fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
38034b9b557SHervé Poussineau }
38134b9b557SHervé Poussineau if (machine->kernel_cmdline && *machine->kernel_cmdline) {
38234b9b557SHervé Poussineau fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
38334b9b557SHervé Poussineau pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
38434b9b557SHervé Poussineau machine->kernel_cmdline);
38534b9b557SHervé Poussineau fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
38634b9b557SHervé Poussineau machine->kernel_cmdline);
38734b9b557SHervé Poussineau fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
38834b9b557SHervé Poussineau strlen(machine->kernel_cmdline) + 1);
38934b9b557SHervé Poussineau }
39034b9b557SHervé Poussineau boot_device = 'm';
39134b9b557SHervé Poussineau } else {
39297ec4d21SPaolo Bonzini boot_device = machine->boot_config.order[0];
39334b9b557SHervé Poussineau }
39434b9b557SHervé Poussineau
395fe6b6346SLike Xu fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus);
39634b9b557SHervé Poussineau fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size);
39734b9b557SHervé Poussineau fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_PREP);
39834b9b557SHervé Poussineau
39934b9b557SHervé Poussineau fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width);
40034b9b557SHervé Poussineau fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
40134b9b557SHervé Poussineau fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
40234b9b557SHervé Poussineau
40334b9b557SHervé Poussineau fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, NANOSECONDS_PER_SECOND);
40434b9b557SHervé Poussineau fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device);
40534b9b557SHervé Poussineau qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
40634b9b557SHervé Poussineau
40734b9b557SHervé Poussineau /* Prepare firmware configuration for Open Hack'Ware */
40834b9b557SHervé Poussineau if (m48t59) {
409ead2b283SPaolo Bonzini PPC_NVRAM_set_params(m48t59, NVRAM_SIZE, "PREP", machine->ram_size,
41034b9b557SHervé Poussineau boot_device,
41134b9b557SHervé Poussineau kernel_base, kernel_size,
41234b9b557SHervé Poussineau machine->kernel_cmdline,
41334b9b557SHervé Poussineau initrd_base, initrd_size,
41434b9b557SHervé Poussineau /* XXX: need an option to load a NVRAM image */
41534b9b557SHervé Poussineau 0,
41634b9b557SHervé Poussineau graphic_width, graphic_height, graphic_depth);
41734b9b557SHervé Poussineau }
41834b9b557SHervé Poussineau }
41934b9b557SHervé Poussineau
ibm_40p_machine_init(MachineClass * mc)42034b9b557SHervé Poussineau static void ibm_40p_machine_init(MachineClass *mc)
42134b9b557SHervé Poussineau {
42234b9b557SHervé Poussineau mc->desc = "IBM RS/6000 7020 (40p)",
42334b9b557SHervé Poussineau mc->init = ibm_40p_init;
42434b9b557SHervé Poussineau mc->max_cpus = 1;
425d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 128 * MiB;
42634b9b557SHervé Poussineau mc->block_default_type = IF_SCSI;
42734b9b557SHervé Poussineau mc->default_boot_order = "c";
42823ec69ecSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("604");
4294cb25fbbSMark Cave-Ayland mc->default_display = "std";
430053b7086SThomas Huth mc->default_nic = "pcnet";
4312b163972SMartin Kletzander
4322b163972SMartin Kletzander machine_add_audiodev_property(mc);
43334b9b557SHervé Poussineau }
43434b9b557SHervé Poussineau
43534b9b557SHervé Poussineau DEFINE_MACHINE("40p", ibm_40p_machine_init)
436