|
|
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"
1.1.1.2 root 37: #include "arch_init.h"
38: #include "blockdev.h"
1.1 root 39:
40: #define MAX_IDE_BUS 2
41:
42: static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
43: static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
44: static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
45:
46: static void ioapic_init(IsaIrqState *isa_irq_state)
47: {
48: DeviceState *dev;
49: SysBusDevice *d;
50: unsigned int i;
51:
52: dev = qdev_create(NULL, "ioapic");
53: qdev_init_nofail(dev);
54: d = sysbus_from_qdev(dev);
55: sysbus_mmio_map(d, 0, 0xfec00000);
56:
57: for (i = 0; i < IOAPIC_NUM_PINS; i++) {
58: isa_irq_state->ioapic[i] = qdev_get_gpio_in(dev, i);
59: }
60: }
61:
62: /* PC hardware initialisation */
63: static void pc_init1(ram_addr_t ram_size,
64: const char *boot_device,
65: const char *kernel_filename,
66: const char *kernel_cmdline,
67: const char *initrd_filename,
68: const char *cpu_model,
69: int pci_enabled)
70: {
71: int i;
72: ram_addr_t below_4g_mem_size, above_4g_mem_size;
73: PCIBus *pci_bus;
74: PCII440FXState *i440fx_state;
75: int piix3_devfn = -1;
76: qemu_irq *cpu_irq;
77: qemu_irq *isa_irq;
78: qemu_irq *i8259;
79: qemu_irq *cmos_s3;
80: qemu_irq *smi_irq;
81: IsaIrqState *isa_irq_state;
82: DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
83: FDCtrl *floppy_controller;
84: BusState *idebus[MAX_IDE_BUS];
85: ISADevice *rtc_state;
86:
87: pc_cpus_init(cpu_model);
88:
89: vmport_init();
90:
91: /* allocate ram and load rom/bios */
92: pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
93: &below_4g_mem_size, &above_4g_mem_size);
94:
95: cpu_irq = pc_allocate_cpu_irq();
96: i8259 = i8259_init(cpu_irq[0]);
97: isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
98: isa_irq_state->i8259 = i8259;
99: if (pci_enabled) {
100: ioapic_init(isa_irq_state);
101: }
102: isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
103:
104: if (pci_enabled) {
105: pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
106: } else {
107: pci_bus = NULL;
1.1.1.2 root 108: i440fx_state = NULL;
1.1 root 109: isa_bus_new(NULL);
110: }
111: isa_bus_irqs(isa_irq);
112:
1.1.1.3 ! root 113: pc_register_ferr_irq(isa_get_irq(13));
1.1 root 114:
115: pc_vga_init(pci_enabled? pci_bus: NULL);
116:
117: /* init basic PC hardware */
118: pc_basic_device_init(isa_irq, &floppy_controller, &rtc_state);
119:
120: for(i = 0; i < nb_nics; i++) {
121: NICInfo *nd = &nd_table[i];
122:
123: if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
124: pc_init_ne2k_isa(nd);
125: else
126: pci_nic_init_nofail(nd, "e1000", NULL);
127: }
128:
129: if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
130: fprintf(stderr, "qemu: too many IDE bus\n");
131: exit(1);
132: }
133:
134: for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
135: hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
136: }
137:
138: if (pci_enabled) {
139: PCIDevice *dev;
140: dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
141: idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
142: idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
143: } else {
144: for(i = 0; i < MAX_IDE_BUS; i++) {
145: ISADevice *dev;
146: dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
147: hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
148: idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
149: }
150: }
151:
1.1.1.2 root 152: audio_init(isa_irq, pci_enabled ? pci_bus : NULL);
1.1 root 153:
154: pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
155: idebus[0], idebus[1], floppy_controller, rtc_state);
156:
157: if (pci_enabled && usb_enabled) {
158: usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
159: }
160:
161: if (pci_enabled && acpi_enabled) {
162: uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
163: i2c_bus *smbus;
164:
165: cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
166: smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
167: /* TODO: Populate SPD eeprom data. */
168: smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
1.1.1.3 ! root 169: isa_get_irq(9), *cmos_s3, *smi_irq,
1.1 root 170: kvm_enabled());
171: for (i = 0; i < 8; i++) {
172: DeviceState *eeprom;
173: eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
174: qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
175: qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
176: qdev_init_nofail(eeprom);
177: }
178: }
179:
180: if (i440fx_state) {
181: i440fx_init_memory_mappings(i440fx_state);
182: }
183:
184: if (pci_enabled) {
185: pc_pci_device_init(pci_bus);
186: }
187: }
188:
189: static void pc_init_pci(ram_addr_t ram_size,
190: const char *boot_device,
191: const char *kernel_filename,
192: const char *kernel_cmdline,
193: const char *initrd_filename,
194: const char *cpu_model)
195: {
196: pc_init1(ram_size, boot_device,
197: kernel_filename, kernel_cmdline,
198: initrd_filename, cpu_model, 1);
199: }
200:
201: static void pc_init_isa(ram_addr_t ram_size,
202: const char *boot_device,
203: const char *kernel_filename,
204: const char *kernel_cmdline,
205: const char *initrd_filename,
206: const char *cpu_model)
207: {
208: if (cpu_model == NULL)
209: cpu_model = "486";
210: pc_init1(ram_size, boot_device,
211: kernel_filename, kernel_cmdline,
212: initrd_filename, cpu_model, 0);
213: }
214:
215: static QEMUMachine pc_machine = {
1.1.1.2 root 216: .name = "pc-0.14",
1.1 root 217: .alias = "pc",
218: .desc = "Standard PC",
219: .init = pc_init_pci,
220: .max_cpus = 255,
221: .is_default = 1,
222: };
223:
1.1.1.2 root 224: static QEMUMachine pc_machine_v0_13 = {
225: .name = "pc-0.13",
226: .desc = "Standard PC",
227: .init = pc_init_pci,
228: .max_cpus = 255,
229: .compat_props = (GlobalProperty[]) {
230: {
231: .driver = "virtio-9p-pci",
232: .property = "vectors",
233: .value = stringify(0),
234: },{
235: .driver = "VGA",
236: .property = "rombar",
237: .value = stringify(0),
238: },{
239: .driver = "vmware-svga",
240: .property = "rombar",
241: .value = stringify(0),
242: },{
243: .driver = "PCI",
244: .property = "command_serr_enable",
245: .value = "off",
246: },
247: { /* end of list */ }
248: },
249: };
250:
1.1 root 251: static QEMUMachine pc_machine_v0_12 = {
252: .name = "pc-0.12",
253: .desc = "Standard PC",
254: .init = pc_init_pci,
255: .max_cpus = 255,
256: .compat_props = (GlobalProperty[]) {
257: {
258: .driver = "virtio-serial-pci",
259: .property = "max_ports",
260: .value = stringify(1),
261: },{
262: .driver = "virtio-serial-pci",
263: .property = "vectors",
264: .value = stringify(0),
1.1.1.2 root 265: },{
266: .driver = "VGA",
267: .property = "rombar",
268: .value = stringify(0),
269: },{
270: .driver = "vmware-svga",
271: .property = "rombar",
272: .value = stringify(0),
273: },{
274: .driver = "PCI",
275: .property = "command_serr_enable",
276: .value = "off",
1.1 root 277: },
278: { /* end of list */ }
279: }
280: };
281:
282: static QEMUMachine pc_machine_v0_11 = {
283: .name = "pc-0.11",
284: .desc = "Standard PC, qemu 0.11",
285: .init = pc_init_pci,
286: .max_cpus = 255,
287: .compat_props = (GlobalProperty[]) {
288: {
289: .driver = "virtio-blk-pci",
290: .property = "vectors",
291: .value = stringify(0),
292: },{
293: .driver = "virtio-serial-pci",
294: .property = "max_ports",
295: .value = stringify(1),
296: },{
297: .driver = "virtio-serial-pci",
298: .property = "vectors",
299: .value = stringify(0),
300: },{
301: .driver = "ide-drive",
302: .property = "ver",
303: .value = "0.11",
304: },{
305: .driver = "scsi-disk",
306: .property = "ver",
307: .value = "0.11",
308: },{
309: .driver = "PCI",
310: .property = "rombar",
311: .value = stringify(0),
1.1.1.2 root 312: },{
313: .driver = "PCI",
314: .property = "command_serr_enable",
315: .value = "off",
1.1 root 316: },
317: { /* end of list */ }
318: }
319: };
320:
321: static QEMUMachine pc_machine_v0_10 = {
322: .name = "pc-0.10",
323: .desc = "Standard PC, qemu 0.10",
324: .init = pc_init_pci,
325: .max_cpus = 255,
326: .compat_props = (GlobalProperty[]) {
327: {
328: .driver = "virtio-blk-pci",
329: .property = "class",
330: .value = stringify(PCI_CLASS_STORAGE_OTHER),
331: },{
332: .driver = "virtio-serial-pci",
333: .property = "class",
334: .value = stringify(PCI_CLASS_DISPLAY_OTHER),
335: },{
336: .driver = "virtio-serial-pci",
337: .property = "max_ports",
338: .value = stringify(1),
339: },{
340: .driver = "virtio-serial-pci",
341: .property = "vectors",
342: .value = stringify(0),
343: },{
344: .driver = "virtio-net-pci",
345: .property = "vectors",
346: .value = stringify(0),
347: },{
348: .driver = "virtio-blk-pci",
349: .property = "vectors",
350: .value = stringify(0),
351: },{
352: .driver = "ide-drive",
353: .property = "ver",
354: .value = "0.10",
355: },{
356: .driver = "scsi-disk",
357: .property = "ver",
358: .value = "0.10",
359: },{
360: .driver = "PCI",
361: .property = "rombar",
362: .value = stringify(0),
1.1.1.2 root 363: },{
364: .driver = "PCI",
365: .property = "command_serr_enable",
366: .value = "off",
1.1 root 367: },
368: { /* end of list */ }
369: },
370: };
371:
372: static QEMUMachine isapc_machine = {
373: .name = "isapc",
374: .desc = "ISA-only PC",
375: .init = pc_init_isa,
376: .max_cpus = 1,
377: };
378:
379: static void pc_machine_init(void)
380: {
381: qemu_register_machine(&pc_machine);
1.1.1.2 root 382: qemu_register_machine(&pc_machine_v0_13);
1.1 root 383: qemu_register_machine(&pc_machine_v0_12);
384: qemu_register_machine(&pc_machine_v0_11);
385: qemu_register_machine(&pc_machine_v0_10);
386: qemu_register_machine(&isapc_machine);
387: }
388:
389: machine_init(pc_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.