#include "hpet_emul.h"
#include "watchdog.h"
#include "smbios.h"
+#include "ide.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
#define BIOS_CFG_IOPORT 0x510
#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
+#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
#define MAX_IDE_BUS 2
static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
static PITState *pit;
-static IOAPICState *ioapic;
-static PCIDevice *i440fx_state;
+static PCII440FXState *i440fx_state;
typedef struct rom_reset_data {
uint8_t *data;
qemu_register_reset(option_rom_reset, rrd);
}
+typedef struct isa_irq_state {
+ qemu_irq *i8259;
+ qemu_irq *ioapic;
+} IsaIrqState;
+
+static void isa_irq_handler(void *opaque, int n, int level)
+{
+ IsaIrqState *isa = (IsaIrqState *)opaque;
+
+ if (n < 16) {
+ qemu_set_irq(isa->i8259[n], level);
+ }
+ qemu_set_irq(isa->ioapic[n], level);
+};
+
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
}
/* TSC handling */
uint64_t cpu_get_tsc(CPUX86State *env)
{
- /* Note: when using kqemu, it is more logical to return the host TSC
- because kqemu does not trap the RDTSC instruction for
- performance reasons */
-#ifdef CONFIG_KQEMU
- if (env->kqemu_enabled) {
- return cpu_get_real_ticks();
- } else
-#endif
- {
- return cpu_get_ticks();
- }
+ return cpu_get_ticks();
}
/* SMM support */
/* hd_table must contain 4 block drivers */
static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
- const char *boot_device, BlockDriverState **hd_table)
+ const char *boot_device, DriveInfo **hd_table)
{
RTCState *s = rtc_state;
int nbds, bds[3] = { 0, };
rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
if (hd_table[0])
- cmos_init_hd(0x19, 0x1b, hd_table[0]);
+ cmos_init_hd(0x19, 0x1b, hd_table[0]->bdrv);
if (hd_table[1])
- cmos_init_hd(0x1a, 0x24, hd_table[1]);
+ cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv);
val = 0;
for (i = 0; i < 4; i++) {
geometry. It is always such that: 1 <= sects <= 63, 1
<= heads <= 16, 1 <= cylinders <= 16383. The BIOS
geometry can be different if a translation is done. */
- translation = bdrv_get_translation_hint(hd_table[i]);
+ translation = bdrv_get_translation_hint(hd_table[i]->bdrv);
if (translation == BIOS_ATA_TRANSLATION_AUTO) {
- bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors);
+ bdrv_get_geometry_hint(hd_table[i]->bdrv, &cylinders, &heads, §ors);
if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
/* No translation. */
translation = 0;
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, (uint8_t *)acpi_tables,
acpi_tables_len);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_IRQ0_OVERRIDE, &irq0override, 1);
smbios_table = smbios_get_table(&smbios_len);
if (smbios_table)
uint8_t header[8192];
target_phys_addr_t real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
FILE *f, *fi;
+ char *vmode;
/* Align to 16 bytes as a paranoia measure */
cmdline_size = (strlen(kernel_cmdline)+16) & ~15;
stw_p(header+0x22, cmdline_addr-real_addr);
}
+ /* handle vga= parameter */
+ vmode = strstr(kernel_cmdline, "vga=");
+ if (vmode) {
+ unsigned int video_mode;
+ /* skip "vga=" */
+ vmode += 4;
+ if (!strncmp(vmode, "normal", 6)) {
+ video_mode = 0xffff;
+ } else if (!strncmp(vmode, "ext", 3)) {
+ video_mode = 0xfffe;
+ } else if (!strncmp(vmode, "ask", 3)) {
+ video_mode = 0xfffd;
+ } else {
+ video_mode = strtol(vmode, NULL, 0);
+ }
+ stw_p(header+0x1fa, video_mode);
+ }
+
/* loader type */
/* High nybble = B reserved for Qemu; low nybble is revision number.
If this code is substantially changed, you may want to consider
}
#endif
-static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
+static void pc_init_ne2k_isa(NICInfo *nd)
{
static int nb_ne2k = 0;
if (nb_ne2k == NE2000_NB_MAX)
return;
- isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd);
+ isa_ne2000_init(ne2000_io[nb_ne2k],
+ isa_reserve_irq(ne2000_irq[nb_ne2k]), nd);
nb_ne2k++;
}
return env;
}
-enum {
- COMPAT_DEFAULT = 0,
- COMPAT_0_10, /* compatible with qemu 0.10.x */
-};
-
/* PC hardware initialisation */
static void pc_init1(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_cmdline,
const char *initrd_filename,
const char *cpu_model,
- int pci_enabled,
- int compat_level)
+ int pci_enabled)
{
char *filename;
int ret, linux_boot, i;
ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
int bios_size, isa_bios_size, oprom_area_size;
PCIBus *pci_bus;
- PCIDevice *pci_dev;
+ ISADevice *isa_dev;
int piix3_devfn = -1;
CPUState *env;
qemu_irq *cpu_irq;
+ qemu_irq *isa_irq;
qemu_irq *i8259;
- int index;
- BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+ IsaIrqState *isa_irq_state;
+ DriveInfo *dinfo;
+ DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
BlockDriverState *fd[MAX_FD];
int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
void *fw_cfg;
- const char *virtio_blk_name, *virtio_console_name;
if (ram_size >= 0xe0000000 ) {
above_4g_mem_size = ram_size - 0xe0000000;
continue;
if (model == NULL)
- model = "ne2k_pci";
+ model = "e1000";
snprintf(nic_oprom, sizeof(nic_oprom), "pxe-%s.bin", model);
oprom_area_size += load_option_rom(nic_oprom, 0xc0000 + oprom_area_size,
cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
i8259 = i8259_init(cpu_irq[0]);
- ferr_irq = i8259[13];
+ isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
+ isa_irq_state->i8259 = i8259;
+ isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
if (pci_enabled) {
- pci_bus = i440fx_init(&i440fx_state, i8259);
- piix3_devfn = piix3_init(pci_bus, -1);
+ pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq);
} else {
pci_bus = NULL;
+ isa_bus_new(NULL);
}
+ isa_bus_irqs(isa_irq);
+
+ ferr_irq = isa_reserve_irq(13);
/* init basic PC hardware */
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
}
}
- rtc_state = rtc_init(0x70, i8259[8], 2000);
+ rtc_state = rtc_init(0x70, isa_reserve_irq(8), 2000);
qemu_register_boot_set(pc_boot_set, rtc_state);
register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
if (pci_enabled) {
- ioapic = ioapic_init();
+ isa_irq_state->ioapic = ioapic_init();
}
- pit = pit_init(0x40, i8259[0]);
+ pit = pit_init(0x40, isa_reserve_irq(0));
pcspk_init(pit);
if (!no_hpet) {
- hpet_init(i8259);
- }
- if (pci_enabled) {
- pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
+ hpet_init(isa_irq);
}
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
- serial_init(serial_io[i], i8259[serial_irq[i]], 115200,
+ serial_init(serial_io[i], isa_reserve_irq(serial_irq[i]), 115200,
serial_hds[i]);
}
}
for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
if (parallel_hds[i]) {
- parallel_init(parallel_io[i], i8259[parallel_irq[i]],
+ parallel_init(parallel_io[i], isa_reserve_irq(parallel_irq[i]),
parallel_hds[i]);
}
}
- watchdog_pc_init(pci_bus);
-
for(i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
- pc_init_ne2k_isa(nd, i8259);
+ pc_init_ne2k_isa(nd);
else
- pci_nic_init(nd, "ne2k_pci", NULL);
+ pci_nic_init(nd, "e1000", NULL);
}
piix4_acpi_system_hot_add_init();
}
for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
- index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
- if (index != -1)
- hd[i] = drives_table[index].bdrv;
- else
- hd[i] = NULL;
+ hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
}
if (pci_enabled) {
- pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
+ pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, isa_irq);
} else {
for(i = 0; i < MAX_IDE_BUS; i++) {
- isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
+ isa_ide_init(ide_iobase[i], ide_iobase2[i],
+ isa_reserve_irq(ide_irq[i]),
hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
}
}
- i8042_init(i8259[1], i8259[12], 0x60);
+ isa_dev = isa_create_simple("i8042", 0x60, 0x64, 1, 12);
DMA_init(0);
#ifdef HAS_AUDIO
- audio_init(pci_enabled ? pci_bus : NULL, i8259);
+ audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
#endif
for(i = 0; i < MAX_FD; i++) {
- index = drive_get_index(IF_FLOPPY, 0, i);
- if (index != -1)
- fd[i] = drives_table[index].bdrv;
- else
- fd[i] = NULL;
+ dinfo = drive_get(IF_FLOPPY, 0, i);
+ fd[i] = dinfo ? dinfo->bdrv : NULL;
}
- floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
+ floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd);
cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
i2c_bus *smbus;
/* TODO: Populate SPD eeprom data. */
- smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[9]);
+ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
+ isa_reserve_irq(9));
for (i = 0; i < 8; i++) {
DeviceState *eeprom;
eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
- qdev_set_prop_int(eeprom, "address", 0x50 + i);
- qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256));
+ qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
+ qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
qdev_init(eeprom);
}
}
}
}
- switch (compat_level) {
- case COMPAT_DEFAULT:
- default:
- virtio_blk_name = "virtio-blk-pci";
- virtio_console_name = "virtio-console-pci";
- break;
-
- case COMPAT_0_10:
- virtio_blk_name = "virtio-blk-pci-0-10";
- virtio_console_name = "virtio-console-pci-0-10";
- break;
- }
-
- /* Add virtio block devices */
- if (pci_enabled) {
- int index;
- int unit_id = 0;
-
- while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
- pci_dev = pci_create(virtio_blk_name,
- drives_table[index].devaddr);
- qdev_init(&pci_dev->qdev);
- unit_id++;
- }
- }
-
- /* Add virtio balloon device */
- if (pci_enabled && virtio_balloon) {
- pci_dev = pci_create("virtio-balloon-pci", virtio_balloon_devaddr);
- qdev_init(&pci_dev->qdev);
- }
-
/* Add virtio console devices */
if (pci_enabled) {
for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
if (virtcon_hds[i]) {
- pci_create_simple(pci_bus, -1, virtio_console_name);
+ pci_create_simple(pci_bus, -1, "virtio-console-pci");
}
}
}
{
pc_init1(ram_size, boot_device,
kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model,
- 1, COMPAT_DEFAULT);
+ initrd_filename, cpu_model, 1);
}
static void pc_init_isa(ram_addr_t ram_size,
{
pc_init1(ram_size, boot_device,
kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model,
- 0, COMPAT_DEFAULT);
-}
-
-static void pc_init_pci_0_10(ram_addr_t ram_size,
- const char *boot_device,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- const char *cpu_model)
-{
- pc_init1(ram_size, boot_device,
- kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model,
- 1, COMPAT_0_10);
+ initrd_filename, cpu_model, 0);
}
/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
}
static QEMUMachine pc_machine = {
- .name = "pc",
+ .name = "pc-0.11",
+ .alias = "pc",
.desc = "Standard PC",
.init = pc_init_pci,
.max_cpus = 255,
.is_default = 1,
};
+static QEMUMachine pc_machine_v0_10 = {
+ .name = "pc-0.10",
+ .desc = "Standard PC, qemu 0.10",
+ .init = pc_init_pci,
+ .max_cpus = 255,
+ .compat_props = (CompatProperty[]) {
+ {
+ .driver = "virtio-blk-pci",
+ .property = "class",
+ .value = stringify(PCI_CLASS_STORAGE_OTHER),
+ },{
+ .driver = "virtio-console-pci",
+ .property = "class",
+ .value = stringify(PCI_CLASS_DISPLAY_OTHER),
+ },{
+ .driver = "virtio-net-pci",
+ .property = "vectors",
+ .value = stringify(0),
+ },{
+ .driver = "virtio-blk-pci",
+ .property = "vectors",
+ .value = stringify(0),
+ },
+ { /* end of list */ }
+ },
+};
+
static QEMUMachine isapc_machine = {
.name = "isapc",
.desc = "ISA-only PC",
.max_cpus = 1,
};
-static QEMUMachine pc_0_10_machine = {
- .name = "pc-0-10",
- .desc = "Standard PC compatible with qemu 0.10.x",
- .init = pc_init_pci_0_10,
- .max_cpus = 255,
-};
-
static void pc_machine_init(void)
{
qemu_register_machine(&pc_machine);
+ qemu_register_machine(&pc_machine_v0_10);
qemu_register_machine(&isapc_machine);
-
- /* For compatibility with 0.10.x */
- qemu_register_machine(&pc_0_10_machine);
}
machine_init(pc_machine_init);