| 1 | /* |
| 2 | * QEMU PC System Emulator |
| 3 | * |
| 4 | * Copyright (c) 2003-2004 Fabrice Bellard |
| 5 | * |
| 6 | * SPDX-License-Identifier: MIT |
| 7 | */ |
| 8 | |
| 9 | #include "qemu/osdep.h" |
| 10 | |
| 11 | #include "qemu/units.h" |
| 12 | #include "qemu/error-report.h" |
| 13 | #include "hw/char/parallel-isa.h" |
| 14 | #include "hw/dma/i8257.h" |
| 15 | #include "hw/i386/pc.h" |
| 16 | #include "hw/ide/isa.h" |
| 17 | #include "hw/ide/ide-bus.h" |
| 18 | #include "system/kvm.h" |
| 19 | #include "hw/i386/kvm/clock.h" |
| 20 | #include "hw/xen/xen-x86.h" |
| 21 | #include "system/xen.h" |
| 22 | #include "hw/rtc/mc146818rtc.h" |
| 23 | #include "target/i386/cpu.h" |
| 24 | |
| 25 | static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; |
| 26 | static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; |
| 27 | static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; |
| 28 | |
| 29 | |
| 30 | static void pc_init_isa(MachineState *machine) |
| 31 | { |
| 32 | PCMachineState *pcms = PC_MACHINE(machine); |
| 33 | PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); |
| 34 | X86MachineState *x86ms = X86_MACHINE(machine); |
| 35 | MemoryRegion *system_memory = get_system_memory(); |
| 36 | MemoryRegion *system_io = get_system_io(); |
| 37 | ISABus *isa_bus; |
| 38 | uint32_t irq; |
| 39 | GSIState *gsi_state; |
| 40 | MemoryRegion *ram_memory; |
| 41 | DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; |
| 42 | int i; |
| 43 | |
| 44 | bool valid_cpu_type = false; |
| 45 | static const char * const valid_cpu_types[] = { |
| 46 | X86_CPU_TYPE_NAME("486"), |
| 47 | X86_CPU_TYPE_NAME("athlon"), |
| 48 | X86_CPU_TYPE_NAME("kvm32"), |
| 49 | X86_CPU_TYPE_NAME("pentium"), |
| 50 | X86_CPU_TYPE_NAME("pentium2"), |
| 51 | X86_CPU_TYPE_NAME("pentium3"), |
| 52 | X86_CPU_TYPE_NAME("qemu32"), |
| 53 | }; |
| 54 | |
| 55 | /* |
| 56 | * The isapc machine is supposed to represent a legacy ISA-only PC with a |
| 57 | * 32-bit processor. For historical reasons the machine can still accept |
| 58 | * almost any valid processor, but this is now deprecated in 10.2. Emit |
| 59 | * a warning if anyone tries to use a deprecated CPU. |
| 60 | */ |
| 61 | for (i = 0; i < ARRAY_SIZE(valid_cpu_types); i++) { |
| 62 | if (!strcmp(machine->cpu_type, valid_cpu_types[i])) { |
| 63 | valid_cpu_type = true; |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | if (!valid_cpu_type) { |
| 68 | warn_report("cpu type %s is deprecated for isapc machine", machine->cpu_type); |
| 69 | } |
| 70 | |
| 71 | if (machine->ram_size > 3.5 * GiB) { |
| 72 | error_report("Too much memory for this machine: %" PRId64 " MiB, " |
| 73 | "maximum 3584 MiB", machine->ram_size / MiB); |
| 74 | exit(1); |
| 75 | } |
| 76 | |
| 77 | /* |
| 78 | * There is no RAM split for the isapc machine |
| 79 | */ |
| 80 | if (xen_enabled()) { |
| 81 | xen_hvm_init_pc(pcms, &ram_memory); |
| 82 | } else { |
| 83 | ram_memory = machine->ram; |
| 84 | |
| 85 | pcms->max_ram_below_4g = 3.5 * GiB; |
| 86 | x86ms->above_4g_mem_size = 0; |
| 87 | x86ms->below_4g_mem_size = machine->ram_size; |
| 88 | } |
| 89 | |
| 90 | x86_cpus_init(x86ms, pcmc->default_cpu_version); |
| 91 | |
| 92 | if (kvm_enabled()) { |
| 93 | kvmclock_create(pcmc->kvmclock_create_always); |
| 94 | } |
| 95 | |
| 96 | /* allocate ram and load rom/bios */ |
| 97 | if (!xen_enabled()) { |
| 98 | pc_memory_init(pcms, system_memory, system_memory, 0); |
| 99 | } else { |
| 100 | assert(machine->ram_size == x86ms->below_4g_mem_size + |
| 101 | x86ms->above_4g_mem_size); |
| 102 | |
| 103 | if (machine->kernel_filename != NULL) { |
| 104 | /* For xen HVM direct kernel boot, load linux here */ |
| 105 | xen_load_linux(pcms); |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | gsi_state = pc_gsi_create(&x86ms->gsi, false); |
| 110 | |
| 111 | isa_bus = isa_bus_new(NULL, system_memory, system_io, |
| 112 | &error_abort); |
| 113 | isa_bus_register_input_irqs(isa_bus, x86ms->gsi); |
| 114 | |
| 115 | x86ms->rtc = isa_new(TYPE_MC146818_RTC); |
| 116 | qdev_prop_set_int32(DEVICE(x86ms->rtc), "base_year", 2000); |
| 117 | isa_realize_and_unref(x86ms->rtc, isa_bus, &error_fatal); |
| 118 | irq = object_property_get_uint(OBJECT(x86ms->rtc), "irq", |
| 119 | &error_fatal); |
| 120 | isa_connect_gpio_out(ISA_DEVICE(x86ms->rtc), 0, irq); |
| 121 | |
| 122 | i8257_dma_init(OBJECT(machine), isa_bus, 0); |
| 123 | pcms->hpet_enabled = false; |
| 124 | |
| 125 | if (x86ms->pic == ON_OFF_AUTO_ON || x86ms->pic == ON_OFF_AUTO_AUTO) { |
| 126 | pc_i8259_create(isa_bus, gsi_state->i8259_irq); |
| 127 | } |
| 128 | |
| 129 | if (tcg_enabled()) { |
| 130 | x86_register_ferr_irq(x86ms->gsi[13]); |
| 131 | } |
| 132 | |
| 133 | pc_vga_init(isa_bus, NULL); |
| 134 | |
| 135 | /* init basic PC hardware */ |
| 136 | pc_basic_device_init(pcms, isa_bus, x86ms->gsi, x86ms->rtc, |
| 137 | !MACHINE_CLASS(pcmc)->no_floppy, 0x4); |
| 138 | |
| 139 | pc_nic_init(pcmc, isa_bus, NULL); |
| 140 | |
| 141 | ide_drive_get(hd, ARRAY_SIZE(hd)); |
| 142 | for (i = 0; i < MAX_IDE_BUS; i++) { |
| 143 | ISADevice *dev; |
| 144 | char busname[] = "ide.0"; |
| 145 | dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], |
| 146 | ide_irq[i], |
| 147 | hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); |
| 148 | /* |
| 149 | * The ide bus name is ide.0 for the first bus and ide.1 for the |
| 150 | * second one. |
| 151 | */ |
| 152 | busname[4] = '0' + i; |
| 153 | pcms->idebus[i] = qdev_get_child_bus(DEVICE(dev), busname); |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | static void isapc_machine_options(MachineClass *m) |
| 158 | { |
| 159 | PCMachineClass *pcmc = PC_MACHINE_CLASS(m); |
| 160 | |
| 161 | m->desc = "ISA-only PC"; |
| 162 | m->max_cpus = 1; |
| 163 | m->option_rom_has_mr = true; |
| 164 | m->rom_file_has_mr = false; |
| 165 | pcmc->pci_enabled = false; |
| 166 | pcmc->has_acpi_build = false; |
| 167 | pcmc->smbios_defaults = false; |
| 168 | pcmc->gigabyte_align = false; |
| 169 | pcmc->smbios_legacy_mode = true; |
| 170 | pcmc->has_reserved_memory = false; |
| 171 | m->default_nic = "ne2k_isa"; |
| 172 | m->default_cpu_type = X86_CPU_TYPE_NAME("486"); |
| 173 | m->no_floppy = !module_object_class_by_name(TYPE_ISA_FDC); |
| 174 | m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL); |
| 175 | } |
| 176 | |
| 177 | DEFINE_PC_MACHINE(isapc, "isapc", pc_init_isa, |
| 178 | isapc_machine_options); |