|
|
1.1 ! root 1: /* ! 2: * QEMU PC System Emulator ! 3: * ! 4: * Copyright (c) 2003-2004 Fabrice Bellard ! 5: * ! 6: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 7: * of this software and associated documentation files (the "Software"), to deal ! 8: * in the Software without restriction, including without limitation the rights ! 9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 10: * copies of the Software, and to permit persons to whom the Software is ! 11: * furnished to do so, subject to the following conditions: ! 12: * ! 13: * The above copyright notice and this permission notice shall be included in ! 14: * all copies or substantial portions of the Software. ! 15: * ! 16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 22: * THE SOFTWARE. ! 23: */ ! 24: ! 25: #include "hw.h" ! 26: #include "pc.h" ! 27: #include "apic.h" ! 28: #include "pci.h" ! 29: #include "usb-uhci.h" ! 30: #include "usb-ohci.h" ! 31: #include "net.h" ! 32: #include "boards.h" ! 33: #include "ide.h" ! 34: #include "kvm.h" ! 35: #include "sysemu.h" ! 36: #include "sysbus.h" ! 37: ! 38: #define MAX_IDE_BUS 2 ! 39: ! 40: static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; ! 41: static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; ! 42: static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; ! 43: ! 44: static void ioapic_init(IsaIrqState *isa_irq_state) ! 45: { ! 46: DeviceState *dev; ! 47: SysBusDevice *d; ! 48: unsigned int i; ! 49: ! 50: dev = qdev_create(NULL, "ioapic"); ! 51: qdev_init_nofail(dev); ! 52: d = sysbus_from_qdev(dev); ! 53: sysbus_mmio_map(d, 0, 0xfec00000); ! 54: ! 55: for (i = 0; i < IOAPIC_NUM_PINS; i++) { ! 56: isa_irq_state->ioapic[i] = qdev_get_gpio_in(dev, i); ! 57: } ! 58: } ! 59: ! 60: /* PC hardware initialisation */ ! 61: static void pc_init1(ram_addr_t ram_size, ! 62: const char *boot_device, ! 63: const char *kernel_filename, ! 64: const char *kernel_cmdline, ! 65: const char *initrd_filename, ! 66: const char *cpu_model, ! 67: int pci_enabled) ! 68: { ! 69: int i; ! 70: ram_addr_t below_4g_mem_size, above_4g_mem_size; ! 71: PCIBus *pci_bus; ! 72: PCII440FXState *i440fx_state; ! 73: int piix3_devfn = -1; ! 74: qemu_irq *cpu_irq; ! 75: qemu_irq *isa_irq; ! 76: qemu_irq *i8259; ! 77: qemu_irq *cmos_s3; ! 78: qemu_irq *smi_irq; ! 79: IsaIrqState *isa_irq_state; ! 80: DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; ! 81: FDCtrl *floppy_controller; ! 82: BusState *idebus[MAX_IDE_BUS]; ! 83: ISADevice *rtc_state; ! 84: ! 85: pc_cpus_init(cpu_model); ! 86: ! 87: vmport_init(); ! 88: ! 89: /* allocate ram and load rom/bios */ ! 90: pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename, ! 91: &below_4g_mem_size, &above_4g_mem_size); ! 92: ! 93: cpu_irq = pc_allocate_cpu_irq(); ! 94: i8259 = i8259_init(cpu_irq[0]); ! 95: isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state)); ! 96: isa_irq_state->i8259 = i8259; ! 97: if (pci_enabled) { ! 98: ioapic_init(isa_irq_state); ! 99: } ! 100: isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24); ! 101: ! 102: if (pci_enabled) { ! 103: pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size); ! 104: } else { ! 105: pci_bus = NULL; ! 106: isa_bus_new(NULL); ! 107: } ! 108: isa_bus_irqs(isa_irq); ! 109: ! 110: pc_register_ferr_irq(isa_reserve_irq(13)); ! 111: ! 112: pc_vga_init(pci_enabled? pci_bus: NULL); ! 113: ! 114: /* init basic PC hardware */ ! 115: pc_basic_device_init(isa_irq, &floppy_controller, &rtc_state); ! 116: ! 117: for(i = 0; i < nb_nics; i++) { ! 118: NICInfo *nd = &nd_table[i]; ! 119: ! 120: if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) ! 121: pc_init_ne2k_isa(nd); ! 122: else ! 123: pci_nic_init_nofail(nd, "e1000", NULL); ! 124: } ! 125: ! 126: if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { ! 127: fprintf(stderr, "qemu: too many IDE bus\n"); ! 128: exit(1); ! 129: } ! 130: ! 131: for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) { ! 132: hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); ! 133: } ! 134: ! 135: if (pci_enabled) { ! 136: PCIDevice *dev; ! 137: dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); ! 138: idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); ! 139: idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); ! 140: } else { ! 141: for(i = 0; i < MAX_IDE_BUS; i++) { ! 142: ISADevice *dev; ! 143: dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], ! 144: hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); ! 145: idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0"); ! 146: } ! 147: } ! 148: ! 149: pc_audio_init(pci_enabled ? pci_bus : NULL, isa_irq); ! 150: ! 151: pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, ! 152: idebus[0], idebus[1], floppy_controller, rtc_state); ! 153: ! 154: if (pci_enabled && usb_enabled) { ! 155: usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); ! 156: } ! 157: ! 158: if (pci_enabled && acpi_enabled) { ! 159: uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */ ! 160: i2c_bus *smbus; ! 161: ! 162: cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1); ! 163: smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); ! 164: /* TODO: Populate SPD eeprom data. */ ! 165: smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, ! 166: isa_reserve_irq(9), *cmos_s3, *smi_irq, ! 167: kvm_enabled()); ! 168: for (i = 0; i < 8; i++) { ! 169: DeviceState *eeprom; ! 170: eeprom = qdev_create((BusState *)smbus, "smbus-eeprom"); ! 171: qdev_prop_set_uint8(eeprom, "address", 0x50 + i); ! 172: qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256)); ! 173: qdev_init_nofail(eeprom); ! 174: } ! 175: } ! 176: ! 177: if (i440fx_state) { ! 178: i440fx_init_memory_mappings(i440fx_state); ! 179: } ! 180: ! 181: if (pci_enabled) { ! 182: pc_pci_device_init(pci_bus); ! 183: } ! 184: } ! 185: ! 186: static void pc_init_pci(ram_addr_t ram_size, ! 187: const char *boot_device, ! 188: const char *kernel_filename, ! 189: const char *kernel_cmdline, ! 190: const char *initrd_filename, ! 191: const char *cpu_model) ! 192: { ! 193: pc_init1(ram_size, boot_device, ! 194: kernel_filename, kernel_cmdline, ! 195: initrd_filename, cpu_model, 1); ! 196: } ! 197: ! 198: static void pc_init_isa(ram_addr_t ram_size, ! 199: const char *boot_device, ! 200: const char *kernel_filename, ! 201: const char *kernel_cmdline, ! 202: const char *initrd_filename, ! 203: const char *cpu_model) ! 204: { ! 205: if (cpu_model == NULL) ! 206: cpu_model = "486"; ! 207: pc_init1(ram_size, boot_device, ! 208: kernel_filename, kernel_cmdline, ! 209: initrd_filename, cpu_model, 0); ! 210: } ! 211: ! 212: static QEMUMachine pc_machine = { ! 213: .name = "pc-0.13", ! 214: .alias = "pc", ! 215: .desc = "Standard PC", ! 216: .init = pc_init_pci, ! 217: .max_cpus = 255, ! 218: .is_default = 1, ! 219: }; ! 220: ! 221: static QEMUMachine pc_machine_v0_12 = { ! 222: .name = "pc-0.12", ! 223: .desc = "Standard PC", ! 224: .init = pc_init_pci, ! 225: .max_cpus = 255, ! 226: .compat_props = (GlobalProperty[]) { ! 227: { ! 228: .driver = "virtio-serial-pci", ! 229: .property = "max_ports", ! 230: .value = stringify(1), ! 231: },{ ! 232: .driver = "virtio-serial-pci", ! 233: .property = "vectors", ! 234: .value = stringify(0), ! 235: }, ! 236: { /* end of list */ } ! 237: } ! 238: }; ! 239: ! 240: static QEMUMachine pc_machine_v0_11 = { ! 241: .name = "pc-0.11", ! 242: .desc = "Standard PC, qemu 0.11", ! 243: .init = pc_init_pci, ! 244: .max_cpus = 255, ! 245: .compat_props = (GlobalProperty[]) { ! 246: { ! 247: .driver = "virtio-blk-pci", ! 248: .property = "vectors", ! 249: .value = stringify(0), ! 250: },{ ! 251: .driver = "virtio-serial-pci", ! 252: .property = "max_ports", ! 253: .value = stringify(1), ! 254: },{ ! 255: .driver = "virtio-serial-pci", ! 256: .property = "vectors", ! 257: .value = stringify(0), ! 258: },{ ! 259: .driver = "ide-drive", ! 260: .property = "ver", ! 261: .value = "0.11", ! 262: },{ ! 263: .driver = "scsi-disk", ! 264: .property = "ver", ! 265: .value = "0.11", ! 266: },{ ! 267: .driver = "PCI", ! 268: .property = "rombar", ! 269: .value = stringify(0), ! 270: }, ! 271: { /* end of list */ } ! 272: } ! 273: }; ! 274: ! 275: static QEMUMachine pc_machine_v0_10 = { ! 276: .name = "pc-0.10", ! 277: .desc = "Standard PC, qemu 0.10", ! 278: .init = pc_init_pci, ! 279: .max_cpus = 255, ! 280: .compat_props = (GlobalProperty[]) { ! 281: { ! 282: .driver = "virtio-blk-pci", ! 283: .property = "class", ! 284: .value = stringify(PCI_CLASS_STORAGE_OTHER), ! 285: },{ ! 286: .driver = "virtio-serial-pci", ! 287: .property = "class", ! 288: .value = stringify(PCI_CLASS_DISPLAY_OTHER), ! 289: },{ ! 290: .driver = "virtio-serial-pci", ! 291: .property = "max_ports", ! 292: .value = stringify(1), ! 293: },{ ! 294: .driver = "virtio-serial-pci", ! 295: .property = "vectors", ! 296: .value = stringify(0), ! 297: },{ ! 298: .driver = "virtio-net-pci", ! 299: .property = "vectors", ! 300: .value = stringify(0), ! 301: },{ ! 302: .driver = "virtio-blk-pci", ! 303: .property = "vectors", ! 304: .value = stringify(0), ! 305: },{ ! 306: .driver = "ide-drive", ! 307: .property = "ver", ! 308: .value = "0.10", ! 309: },{ ! 310: .driver = "scsi-disk", ! 311: .property = "ver", ! 312: .value = "0.10", ! 313: },{ ! 314: .driver = "PCI", ! 315: .property = "rombar", ! 316: .value = stringify(0), ! 317: }, ! 318: { /* end of list */ } ! 319: }, ! 320: }; ! 321: ! 322: static QEMUMachine isapc_machine = { ! 323: .name = "isapc", ! 324: .desc = "ISA-only PC", ! 325: .init = pc_init_isa, ! 326: .max_cpus = 1, ! 327: }; ! 328: ! 329: static void pc_machine_init(void) ! 330: { ! 331: qemu_register_machine(&pc_machine); ! 332: qemu_register_machine(&pc_machine_v0_12); ! 333: qemu_register_machine(&pc_machine_v0_11); ! 334: qemu_register_machine(&pc_machine_v0_10); ! 335: qemu_register_machine(&isapc_machine); ! 336: } ! 337: ! 338: machine_init(pc_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.