* [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator.
@ 2009-06-18 10:56 Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 01/18] acpi.c: make qemu_system_device_hot_add piix independent Isaku Yamahata
` (18 more replies)
0 siblings, 19 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:56 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
This patch series is for spliting out piix specific part from pc emulator
ot make it easier to implement other pc chipset emulator.
Its motivation is to support 128+ PCI slot and
to support MMCFG and PCIe port emulator,
then eventually PCIe native direct attach support including
PCIe native functionality like AER.
This requires newer chipset emulation than piix.
I'm implementing q35 chipset based one.
Although I haven't finished it, I'll send it out for reference to show
what I'm working on.
Isaku Yamahata (18):
acpi.c: make qemu_system_device_hot_add piix independent.
acpi.c: split out pc smbus routines from acpi.c into pc_smbus.c
acpi.c: split out apm register emulation.
acpi.c: make qemu_system_powerdown() piix independent.
acpi: add acpi constants from linux header files and use them.
acpi.c: split acpi.c into the common part and the piix4 part.
pc.c: Make smm enable/disable function i440fx independent.
pc.c: remove unnecessary global variables, pit and ioapic..
pc.c: remove a global variable, floppy_controller.
pc.c: remove a global variable, RTCState *rtc_state.
pc.c: introduce a function to allocate cpu irq.
pc.c: make pc_init1() not refer ferr_irq directly.
pc.c: split out cpu initialization from pc_init1() into
pc_cpus_init().
pc.c: split out memory allocation from pc_init1() into
pc_memory_init()
pc.c: split out vga initialization from pc_init1() into
pc_vga_init().
pc.c: split out basic device init from pc_init1() into
pc_basic_device_init()
pc.c: split out pci device init from pc_init1() into
pc_pci_device_init()
pc.c: split out piix specific part from pc.c into pc_piix.c
Makefile.target | 2 +
hw/acpi.c | 728 ++-----------------------------------------------------
hw/acpi.h | 85 +++++++
hw/acpi_piix4.c | 580 ++++++++++++++++++++++++++++++++++++++++++++
hw/pc.c | 295 ++++++++---------------
hw/pc.h | 41 +++-
hw/pc_apm.c | 92 +++++++
hw/pc_apm.h | 39 +++
hw/pc_piix.c | 210 ++++++++++++++++
hw/pc_smbus.c | 179 ++++++++++++++
hw/pc_smbus.h | 43 ++++
hw/piix_pci.c | 8 +-
sysemu.h | 3 +-
13 files changed, 1390 insertions(+), 915 deletions(-)
create mode 100644 hw/acpi.h
create mode 100644 hw/acpi_piix4.c
create mode 100644 hw/pc_apm.c
create mode 100644 hw/pc_apm.h
create mode 100644 hw/pc_piix.c
create mode 100644 hw/pc_smbus.c
create mode 100644 hw/pc_smbus.h
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 01/18] acpi.c: make qemu_system_device_hot_add piix independent.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 02/18] acpi.c: split out pc smbus routines from acpi.c into pc_smbus.c Isaku Yamahata
` (17 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
introruce piix4_device_hot_add() for piix4 specific code
and make qemu_system_device_hot_add() generic.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/acpi.c | 20 ++++++++++++++++++--
hw/pc.c | 2 +-
hw/pc.h | 7 +++++--
sysemu.h | 3 ++-
4 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/hw/acpi.c b/hw/acpi.c
index fccae69..5928fe7 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -714,7 +714,9 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
#endif
}
-void qemu_system_hot_add_init(void)
+static void piix4_device_hot_add(int bus, int slot, int state);
+
+void piix4_acpi_system_hot_add_init(void)
{
register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
register_ioport_read(GPE_BASE, 4, 1, gpe_readb, &gpe);
@@ -724,6 +726,8 @@ void qemu_system_hot_add_init(void)
register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL);
register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, NULL);
+
+ qemu_system_device_hot_add_register(piix4_device_hot_add);
}
static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
@@ -738,7 +742,7 @@ static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
p->down |= (1 << slot);
}
-void qemu_system_device_hot_add(int bus, int slot, int state)
+static void piix4_device_hot_add(int bus, int slot, int state)
{
pci0_status.up = 0;
pci0_status.down = 0;
@@ -752,6 +756,18 @@ void qemu_system_device_hot_add(int bus, int slot, int state)
}
}
+static qemu_system_device_hot_add_t device_hot_add_callback;
+void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback)
+{
+ device_hot_add_callback = callback;
+}
+
+void qemu_system_device_hot_add(int pcibus, int slot, int state)
+{
+ if (device_hot_add_callback)
+ device_hot_add_callback(pcibus, slot, state);
+}
+
struct acpi_table_header
{
char signature [4]; /* ACPI signature (4 ASCII characters) */
diff --git a/hw/pc.c b/hw/pc.c
index 143b697..a848d8d 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1066,7 +1066,7 @@ static void pc_init1(ram_addr_t ram_size,
pci_nic_init(pci_bus, nd, -1, "ne2k_pci");
}
- qemu_system_hot_add_init();
+ piix4_acpi_system_hot_add_init();
if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
fprintf(stderr, "qemu: too many IDE bus\n");
diff --git a/hw/pc.h b/hw/pc.h
index 0afffa2..9fbae20 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -108,11 +108,14 @@ extern int acpi_enabled;
extern char *acpi_tables;
extern size_t acpi_tables_len;
+void acpi_bios_init(void);
+int acpi_table_add(const char *table_desc);
+
+/* acpi_piix.c */
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
qemu_irq sci_irq);
void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
-void acpi_bios_init(void);
-int acpi_table_add(const char *table_desc);
+void piix4_acpi_system_hot_add_init(void);
/* hpet.c */
extern int no_hpet;
diff --git a/sysemu.h b/sysemu.h
index fe24415..403b35e 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -194,7 +194,8 @@ extern int drive_add(const char *file, const char *fmt, ...);
extern int drive_init(struct drive_opt *arg, int snapshot, void *machine);
/* acpi */
-void qemu_system_hot_add_init(void);
+typedef void (*qemu_system_device_hot_add_t)(int pcibus, int slot, int state);
+void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback);
void qemu_system_device_hot_add(int pcibus, int slot, int state);
/* device-hotplug */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 02/18] acpi.c: split out pc smbus routines from acpi.c into pc_smbus.c
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 01/18] acpi.c: make qemu_system_device_hot_add piix independent Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 03/18] acpi.c: split out apm register emulation Isaku Yamahata
` (16 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Split out pc smbus routines from acpi.c into pc_smbus.c and
use it.
The split out smbus emulation will be used later.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
Makefile.target | 2 +
hw/acpi.c | 164 +++------------------------------------------------
hw/pc_smbus.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/pc_smbus.h | 43 +++++++++++++
4 files changed, 232 insertions(+), 156 deletions(-)
create mode 100644 hw/pc_smbus.c
create mode 100644 hw/pc_smbus.h
diff --git a/Makefile.target b/Makefile.target
index 0159bf7..c1ebb61 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -573,6 +573,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
OBJS+= ide.o pckbd.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
+OBJS+= pc_smbus.o
OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
OBJS += device-hotplug.o pci-hotplug.o smbios.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
@@ -608,6 +609,7 @@ OBJS+= mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
OBJS+= g364fb.o jazz_led.o dp8393x.o
OBJS+= ide.o gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
+OBJS+= pc_smbus.o
OBJS+= piix_pci.o parallel.o cirrus_vga.o pcspk.o $(SOUND_HW)
OBJS+= mipsnet.o
OBJS+= pflash_cfi01.o
diff --git a/hw/acpi.c b/hw/acpi.c
index 5928fe7..787b6d9 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -18,6 +18,7 @@
*/
#include "hw.h"
#include "pc.h"
+#include "pc_smbus.h"
#include "pci.h"
#include "qemu-timer.h"
#include "sysemu.h"
@@ -41,15 +42,9 @@ typedef struct PIIX4PMState {
uint8_t apms;
QEMUTimer *tmr_timer;
int64_t tmr_overflow_time;
- i2c_bus *smbus;
- uint8_t smb_stat;
- uint8_t smb_ctl;
- uint8_t smb_cmd;
- uint8_t smb_addr;
- uint8_t smb_data0;
- uint8_t smb_data1;
- uint8_t smb_data[32];
- uint8_t smb_index;
+
+ PCSMBus smb;
+
qemu_irq irq;
} PIIX4PMState;
@@ -67,14 +62,6 @@ typedef struct PIIX4PMState {
#define ACPI_ENABLE 0xf1
#define ACPI_DISABLE 0xf0
-#define SMBHSTSTS 0x00
-#define SMBHSTCNT 0x02
-#define SMBHSTCMD 0x03
-#define SMBHSTADD 0x04
-#define SMBHSTDAT0 0x05
-#define SMBHSTDAT1 0x06
-#define SMBBLKDAT 0x07
-
static PIIX4PMState *pm_state;
static uint32_t get_pmtmr(PIIX4PMState *s)
@@ -279,141 +266,6 @@ static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
#endif
}
-static void smb_transaction(PIIX4PMState *s)
-{
- uint8_t prot = (s->smb_ctl >> 2) & 0x07;
- uint8_t read = s->smb_addr & 0x01;
- uint8_t cmd = s->smb_cmd;
- uint8_t addr = s->smb_addr >> 1;
- i2c_bus *bus = s->smbus;
-
-#ifdef DEBUG
- printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
-#endif
- switch(prot) {
- case 0x0:
- smbus_quick_command(bus, addr, read);
- break;
- case 0x1:
- if (read) {
- s->smb_data0 = smbus_receive_byte(bus, addr);
- } else {
- smbus_send_byte(bus, addr, cmd);
- }
- break;
- case 0x2:
- if (read) {
- s->smb_data0 = smbus_read_byte(bus, addr, cmd);
- } else {
- smbus_write_byte(bus, addr, cmd, s->smb_data0);
- }
- break;
- case 0x3:
- if (read) {
- uint16_t val;
- val = smbus_read_word(bus, addr, cmd);
- s->smb_data0 = val;
- s->smb_data1 = val >> 8;
- } else {
- smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
- }
- break;
- case 0x5:
- if (read) {
- s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
- } else {
- smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
- }
- break;
- default:
- goto error;
- }
- return;
-
- error:
- s->smb_stat |= 0x04;
-}
-
-static void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- PIIX4PMState *s = opaque;
- addr &= 0x3f;
-#ifdef DEBUG
- printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
-#endif
- switch(addr) {
- case SMBHSTSTS:
- s->smb_stat = 0;
- s->smb_index = 0;
- break;
- case SMBHSTCNT:
- s->smb_ctl = val;
- if (val & 0x40)
- smb_transaction(s);
- break;
- case SMBHSTCMD:
- s->smb_cmd = val;
- break;
- case SMBHSTADD:
- s->smb_addr = val;
- break;
- case SMBHSTDAT0:
- s->smb_data0 = val;
- break;
- case SMBHSTDAT1:
- s->smb_data1 = val;
- break;
- case SMBBLKDAT:
- s->smb_data[s->smb_index++] = val;
- if (s->smb_index > 31)
- s->smb_index = 0;
- break;
- default:
- break;
- }
-}
-
-static uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val;
-
- addr &= 0x3f;
- switch(addr) {
- case SMBHSTSTS:
- val = s->smb_stat;
- break;
- case SMBHSTCNT:
- s->smb_index = 0;
- val = s->smb_ctl & 0x1f;
- break;
- case SMBHSTCMD:
- val = s->smb_cmd;
- break;
- case SMBHSTADD:
- val = s->smb_addr;
- break;
- case SMBHSTDAT0:
- val = s->smb_data0;
- break;
- case SMBHSTDAT1:
- val = s->smb_data1;
- break;
- case SMBBLKDAT:
- val = s->smb_data[s->smb_index++];
- if (s->smb_index > 31)
- s->smb_index = 0;
- break;
- default:
- val = 0;
- break;
- }
-#ifdef DEBUG
- printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
-#endif
- return val;
-}
-
static void pm_io_space_update(PIIX4PMState *s)
{
uint32_t pm_io_base;
@@ -541,18 +393,18 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
pci_conf[0x90] = smb_io_base | 1;
pci_conf[0x91] = smb_io_base >> 8;
pci_conf[0xd2] = 0x09;
- register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
- register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
+ register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
+ register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
- s->smbus = i2c_init_bus(NULL, "i2c");
+ pc_smbus_init(&s->smb);
s->irq = sci_irq;
qemu_register_reset(piix4_reset, 0, s);
- return s->smbus;
+ return s->smb.smbus;
}
#if defined(TARGET_I386)
diff --git a/hw/pc_smbus.c b/hw/pc_smbus.c
new file mode 100644
index 0000000..0ccbd4e
--- /dev/null
+++ b/hw/pc_smbus.c
@@ -0,0 +1,179 @@
+/*
+ * PC SMBus implementation
+ * splitted from acpi.c
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pc_smbus.h"
+#include "pci.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "i2c.h"
+#include "smbus.h"
+#include "kvm.h"
+#include "acpi.h"
+
+/* no save/load? */
+
+#define SMBHSTSTS 0x00
+#define SMBHSTCNT 0x02
+#define SMBHSTCMD 0x03
+#define SMBHSTADD 0x04
+#define SMBHSTDAT0 0x05
+#define SMBHSTDAT1 0x06
+#define SMBBLKDAT 0x07
+
+static void smb_transaction(PCSMBus *s)
+{
+ uint8_t prot = (s->smb_ctl >> 2) & 0x07;
+ uint8_t read = s->smb_addr & 0x01;
+ uint8_t cmd = s->smb_cmd;
+ uint8_t addr = s->smb_addr >> 1;
+ i2c_bus *bus = s->smbus;
+
+#ifdef DEBUG
+ printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+#endif
+ switch(prot) {
+ case 0x0:
+ smbus_quick_command(bus, addr, read);
+ break;
+ case 0x1:
+ if (read) {
+ s->smb_data0 = smbus_receive_byte(bus, addr);
+ } else {
+ smbus_send_byte(bus, addr, cmd);
+ }
+ break;
+ case 0x2:
+ if (read) {
+ s->smb_data0 = smbus_read_byte(bus, addr, cmd);
+ } else {
+ smbus_write_byte(bus, addr, cmd, s->smb_data0);
+ }
+ break;
+ case 0x3:
+ if (read) {
+ uint16_t val;
+ val = smbus_read_word(bus, addr, cmd);
+ s->smb_data0 = val;
+ s->smb_data1 = val >> 8;
+ } else {
+ smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
+ }
+ break;
+ case 0x5:
+ if (read) {
+ s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
+ } else {
+ smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
+ }
+ break;
+ default:
+ goto error;
+ }
+ return;
+
+ error:
+ s->smb_stat |= 0x04;
+}
+
+void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ PCSMBus *s = opaque;
+ addr &= 0x3f;
+#ifdef DEBUG
+ printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+ switch(addr) {
+ case SMBHSTSTS:
+ s->smb_stat = 0;
+ s->smb_index = 0;
+ break;
+ case SMBHSTCNT:
+ s->smb_ctl = val;
+ if (val & 0x40)
+ smb_transaction(s);
+ break;
+ case SMBHSTCMD:
+ s->smb_cmd = val;
+ break;
+ case SMBHSTADD:
+ s->smb_addr = val;
+ break;
+ case SMBHSTDAT0:
+ s->smb_data0 = val;
+ break;
+ case SMBHSTDAT1:
+ s->smb_data1 = val;
+ break;
+ case SMBBLKDAT:
+ s->smb_data[s->smb_index++] = val;
+ if (s->smb_index > 31)
+ s->smb_index = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+{
+ PCSMBus *s = opaque;
+ uint32_t val;
+
+ addr &= 0x3f;
+ switch(addr) {
+ case SMBHSTSTS:
+ val = s->smb_stat;
+ break;
+ case SMBHSTCNT:
+ s->smb_index = 0;
+ val = s->smb_ctl & 0x1f;
+ break;
+ case SMBHSTCMD:
+ val = s->smb_cmd;
+ break;
+ case SMBHSTADD:
+ val = s->smb_addr;
+ break;
+ case SMBHSTDAT0:
+ val = s->smb_data0;
+ break;
+ case SMBHSTDAT1:
+ val = s->smb_data1;
+ break;
+ case SMBBLKDAT:
+ val = s->smb_data[s->smb_index++];
+ if (s->smb_index > 31)
+ s->smb_index = 0;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+#ifdef DEBUG
+ printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+ return val;
+}
+
+void pc_smbus_init(PCSMBus *smb)
+{
+ smb->smbus = i2c_init_bus(NULL, "i2c");
+}
diff --git a/hw/pc_smbus.h b/hw/pc_smbus.h
new file mode 100644
index 0000000..5e5a66f
--- /dev/null
+++ b/hw/pc_smbus.h
@@ -0,0 +1,43 @@
+/*
+ * QEMU PC SMBUS controller Emulation
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This is based on piix_pci.c, but heavily modified.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+#ifndef PC_SMBUS_H
+#define PC_SMBUS_H
+
+typedef struct PCSMBus {
+ i2c_bus *smbus;
+
+ uint8_t smb_stat;
+ uint8_t smb_ctl;
+ uint8_t smb_cmd;
+ uint8_t smb_addr;
+ uint8_t smb_data0;
+ uint8_t smb_data1;
+ uint8_t smb_data[32];
+ uint8_t smb_index;
+} PCSMBus;
+
+void pc_smbus_init(PCSMBus *smb);
+void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val);
+uint32_t smb_ioport_readb(void *opaque, uint32_t addr);
+
+#endif /* !PC_SMBUS_H */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 03/18] acpi.c: split out apm register emulation.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 01/18] acpi.c: make qemu_system_device_hot_add piix independent Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 02/18] acpi.c: split out pc smbus routines from acpi.c into pc_smbus.c Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 04/18] acpi.c: make qemu_system_powerdown() piix independent Isaku Yamahata
` (15 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Split out apm register emulation for acpi.c into pc_apm.c.
The apm emulation will be used later.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
Makefile.target | 4 +-
hw/acpi.c | 60 ++++++++++-------------------------
hw/pc_apm.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/pc_apm.h | 39 +++++++++++++++++++++++
4 files changed, 150 insertions(+), 45 deletions(-)
create mode 100644 hw/pc_apm.c
create mode 100644 hw/pc_apm.h
diff --git a/Makefile.target b/Makefile.target
index c1ebb61..1ab708b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -573,7 +573,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
OBJS+= ide.o pckbd.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
-OBJS+= pc_smbus.o
+OBJS+= pc_smbus.o pc_apm.o
OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
OBJS += device-hotplug.o pci-hotplug.o smbios.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
@@ -609,7 +609,7 @@ OBJS+= mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
OBJS+= g364fb.o jazz_led.o dp8393x.o
OBJS+= ide.o gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
-OBJS+= pc_smbus.o
+OBJS+= pc_smbus.o pc_apm.o
OBJS+= piix_pci.o parallel.o cirrus_vga.o pcspk.o $(SOUND_HW)
OBJS+= mipsnet.o
OBJS+= pflash_cfi01.o
diff --git a/hw/acpi.c b/hw/acpi.c
index 787b6d9..75544e8 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -18,6 +18,7 @@
*/
#include "hw.h"
#include "pc.h"
+#include "pc_apm.h"
#include "pc_smbus.h"
#include "pci.h"
#include "qemu-timer.h"
@@ -38,8 +39,9 @@ typedef struct PIIX4PMState {
uint16_t pmsts;
uint16_t pmen;
uint16_t pmcntrl;
- uint8_t apmc;
- uint8_t apms;
+
+ APMState apm;
+
QEMUTimer *tmr_timer;
int64_t tmr_overflow_time;
@@ -217,46 +219,20 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
return val;
}
-static void pm_smi_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void apm_ctrl_changed(uint32_t val, void *arg)
{
- PIIX4PMState *s = opaque;
- addr &= 1;
-#ifdef DEBUG
- printf("pm_smi_writeb addr=0x%x val=0x%02x\n", addr, val);
-#endif
- if (addr == 0) {
- s->apmc = val;
-
- /* ACPI specs 3.0, 4.7.2.5 */
- if (val == ACPI_ENABLE) {
- s->pmcntrl |= SCI_EN;
- } else if (val == ACPI_DISABLE) {
- s->pmcntrl &= ~SCI_EN;
- }
+ PIIX4PMState *s = arg;
- if (s->dev.config[0x5b] & (1 << 1)) {
- cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
- }
- } else {
- s->apms = val;
+ /* ACPI specs 3.0, 4.7.2.5 */
+ if (val == ACPI_ENABLE) {
+ s->pmcntrl |= SCI_EN;
+ } else if (val == ACPI_DISABLE) {
+ s->pmcntrl &= ~SCI_EN;
}
-}
-static uint32_t pm_smi_readb(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val;
-
- addr &= 1;
- if (addr == 0) {
- val = s->apmc;
- } else {
- val = s->apms;
+ if (s->dev.config[0x5b] & (1 << 1)) {
+ cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
}
-#ifdef DEBUG
- printf("pm_smi_readb addr=0x%x val=0x%02x\n", addr, val);
-#endif
- return val;
}
static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
@@ -302,8 +278,7 @@ static void pm_save(QEMUFile* f,void *opaque)
qemu_put_be16s(f, &s->pmsts);
qemu_put_be16s(f, &s->pmen);
qemu_put_be16s(f, &s->pmcntrl);
- qemu_put_8s(f, &s->apmc);
- qemu_put_8s(f, &s->apms);
+ apm_save(f, &s->apm);
qemu_put_timer(f, s->tmr_timer);
qemu_put_be64(f, s->tmr_overflow_time);
}
@@ -323,8 +298,7 @@ static int pm_load(QEMUFile* f,void* opaque,int version_id)
qemu_get_be16s(f, &s->pmsts);
qemu_get_be16s(f, &s->pmen);
qemu_get_be16s(f, &s->pmcntrl);
- qemu_get_8s(f, &s->apmc);
- qemu_get_8s(f, &s->apms);
+ apm_load(f, &s->apm);
qemu_get_timer(f, s->tmr_timer);
s->tmr_overflow_time=qemu_get_be64(f);
@@ -372,8 +346,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
pci_conf[0x40] = 0x01; /* PM io base read only bit */
- register_ioport_write(0xb2, 2, 1, pm_smi_writeb, s);
- register_ioport_read(0xb2, 2, 1, pm_smi_readb, s);
+ /* APM */
+ apm_init(&s->apm, apm_ctrl_changed, s);
register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
diff --git a/hw/pc_apm.c b/hw/pc_apm.c
new file mode 100644
index 0000000..dac43fb
--- /dev/null
+++ b/hw/pc_apm.c
@@ -0,0 +1,92 @@
+/*
+ * QEMU PC APM controller Emulation
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This is split out from acpi.c
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "pc_apm.h"
+#include "hw.h"
+#include "isa.h"
+
+//#define DEBUG
+
+/* fixed I/O location */
+#define APM_CNT_IOPORT 0xb2
+#define APM_STS_IOPORT 0xb3
+
+static void *apm_arg;
+static apm_ctrl_changed_t apm_callback;
+
+static void apm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ APMState *apm = opaque;
+ addr &= 1;
+#ifdef DEBUG
+ printf("apm_ioport_writeb addr=0x%x val=0x%02x\n", addr, val);
+#endif
+ if (addr == 0) {
+ apm->apmc = val;
+
+ if (apm_callback) {
+ apm_callback(val, apm_arg);
+ }
+ } else {
+ apm->apms = val;
+ }
+}
+
+static uint32_t apm_ioport_readb(void *opaque, uint32_t addr)
+{
+ APMState *apm = opaque;
+ uint32_t val;
+
+ addr &= 1;
+ if (addr == 0) {
+ val = apm->apmc;
+ } else {
+ val = apm->apms;
+ }
+#ifdef DEBUG
+ printf("apm_ioport_readb addr=0x%x val=0x%02x\n", addr, val);
+#endif
+ return val;
+}
+
+void apm_save(QEMUFile *f, APMState *apm)
+{
+ qemu_put_8s(f, &apm->apmc);
+ qemu_put_8s(f, &apm->apms);
+}
+
+void apm_load(QEMUFile *f, APMState *apm)
+{
+ qemu_get_8s(f, &apm->apmc);
+ qemu_get_8s(f, &apm->apms);
+}
+
+void apm_init(APMState *apm, apm_ctrl_changed_t callback, void *arg)
+{
+ apm_callback = callback;
+ apm_arg = arg;
+
+ /* ioport 0xb2, 0xb3 */
+ register_ioport_write(APM_CNT_IOPORT, 2, 1, apm_ioport_writeb, apm);
+ register_ioport_read(APM_CNT_IOPORT, 2, 1, apm_ioport_readb, apm);
+}
diff --git a/hw/pc_apm.h b/hw/pc_apm.h
new file mode 100644
index 0000000..9f4120c
--- /dev/null
+++ b/hw/pc_apm.h
@@ -0,0 +1,39 @@
+/*
+ * QEMU PC APM controller Emulation
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#ifndef PC_APM_H
+#define PC_APM_H
+
+#include <stdint.h>
+#include "qemu-common.h"
+
+typedef struct APMState {
+ uint8_t apmc;
+ uint8_t apms;
+} APMState;
+
+typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg);
+void apm_init(APMState *s, apm_ctrl_changed_t callback, void *arg);
+
+void apm_save(QEMUFile *f, APMState *apm);
+void apm_load(QEMUFile *f, APMState *apm);
+
+#endif /* PC_APM_H */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 04/18] acpi.c: make qemu_system_powerdown() piix independent.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (2 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 03/18] acpi.c: split out apm register emulation Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 05/18] acpi: add acpi constants from linux header files and use them Isaku Yamahata
` (14 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Make qemu_system_powerdown() piix independent by
registering callback function.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/acpi.c | 29 +++++++++++++++++++++++++----
hw/acpi.h | 29 +++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 4 deletions(-)
create mode 100644 hw/acpi.h
diff --git a/hw/acpi.c b/hw/acpi.c
index 75544e8..66cc4b2 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -323,6 +323,18 @@ static void piix4_reset(void *opaque)
}
}
+#if defined(TARGET_I386)
+static void piix4_pm_powerdown(void *arg)
+{
+ PIIX4PMState *pm_state = (PIIX4PMState*) arg;
+
+ if (pm_state->pmen & PWRBTN_EN) {
+ pm_state->pmsts |= PWRBTN_EN;
+ pm_update_sci(pm_state);
+ }
+}
+#endif
+
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
qemu_irq sci_irq)
{
@@ -377,18 +389,27 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
pc_smbus_init(&s->smb);
s->irq = sci_irq;
qemu_register_reset(piix4_reset, 0, s);
+ qemu_system_powerdown_register(piix4_pm_powerdown, pm_state);
return s->smb.smbus;
}
#if defined(TARGET_I386)
+static qemu_powerdown_t qemu_powerdown_callback;
+static void *qemu_powerdown_arg;
+
+void qemu_system_powerdown_register(qemu_powerdown_t callback, void *arg)
+{
+ qemu_powerdown_callback = callback;
+ qemu_powerdown_arg = arg;
+}
+
void qemu_system_powerdown(void)
{
- if (!pm_state) {
+ if (!qemu_powerdown_callback) {
qemu_system_shutdown_request();
- } else if (pm_state->pmen & PWRBTN_EN) {
- pm_state->pmsts |= PWRBTN_EN;
- pm_update_sci(pm_state);
+ } else {
+ qemu_powerdown_callback(qemu_powerdown_arg);
}
}
#endif
diff --git a/hw/acpi.h b/hw/acpi.h
new file mode 100644
index 0000000..884512c
--- /dev/null
+++ b/hw/acpi.h
@@ -0,0 +1,29 @@
+#ifndef QEMU_HW_ACPI_H
+#define QEMU_HW_ACPI_H
+/*
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#if defined(TARGET_I386)
+typedef void (*qemu_powerdown_t)(void *arg);
+void qemu_system_powerdown_register(qemu_powerdown_t callback, void *arg);
+#else
+#define qemu_system_powerdown_register(callback, arg) do { } while (0)
+#endif
+
+#endif /* !QEMU_HW_ACPI_H */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 05/18] acpi: add acpi constants from linux header files and use them.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (3 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 04/18] acpi.c: make qemu_system_powerdown() piix independent Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 06/18] acpi.c: split acpi.c into the common part and the piix4 part Isaku Yamahata
` (13 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
add acpi constants from linux header files and
replace the old constants with them.
The acpi constants will be used by other file.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/acpi.c | 55 ++++++++++++++++++++++++-------------------------------
hw/acpi.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+), 31 deletions(-)
diff --git a/hw/acpi.c b/hw/acpi.c
index 66cc4b2..4d0690e 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -29,9 +29,6 @@
//#define DEBUG
-/* i82731AB (PIIX4) compatible power management function */
-#define PM_FREQ 3579545
-
#define ACPI_DBG_IO_ADDR 0xb044
typedef struct PIIX4PMState {
@@ -50,17 +47,6 @@ typedef struct PIIX4PMState {
qemu_irq irq;
} PIIX4PMState;
-#define RSM_STS (1 << 15)
-#define PWRBTN_STS (1 << 8)
-#define RTC_EN (1 << 10)
-#define PWRBTN_EN (1 << 8)
-#define GBL_EN (1 << 5)
-#define TMROF_EN (1 << 0)
-
-#define SCI_EN (1 << 0)
-
-#define SUS_EN (1 << 13)
-
#define ACPI_ENABLE 0xf1
#define ACPI_DISABLE 0xf0
@@ -69,7 +55,7 @@ static PIIX4PMState *pm_state;
static uint32_t get_pmtmr(PIIX4PMState *s)
{
uint32_t d;
- d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
+ d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, ticks_per_sec);
return d & 0xffffff;
}
@@ -78,9 +64,9 @@ static int get_pmsts(PIIX4PMState *s)
int64_t d;
int pmsts;
pmsts = s->pmsts;
- d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
+ d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, ticks_per_sec);
if (d >= s->tmr_overflow_time)
- s->pmsts |= TMROF_EN;
+ s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
return s->pmsts;
}
@@ -91,11 +77,16 @@ static void pm_update_sci(PIIX4PMState *s)
pmsts = get_pmsts(s);
sci_level = (((pmsts & s->pmen) &
- (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
+ (ACPI_BITMASK_RT_CLOCK_ENABLE |
+ ACPI_BITMASK_POWER_BUTTON_ENABLE |
+ ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
+ ACPI_BITMASK_TIMER_ENABLE)) != 0);
qemu_set_irq(s->irq, sci_level);
/* schedule a timer interruption if needed */
- if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
- expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ);
+ if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+ !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
+ expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec,
+ PM_TIMER_FREQUENCY);
qemu_mod_timer(s->tmr_timer, expire_time);
} else {
qemu_del_timer(s->tmr_timer);
@@ -118,9 +109,10 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
int64_t d;
int pmsts;
pmsts = get_pmsts(s);
- if (pmsts & val & TMROF_EN) {
+ if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
/* if TMRSTS is reset, then compute the new overflow time */
- d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
+ d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+ ticks_per_sec);
s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
}
s->pmsts &= ~val;
@@ -134,8 +126,8 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
case 0x04:
{
int sus_typ;
- s->pmcntrl = val & ~(SUS_EN);
- if (val & SUS_EN) {
+ s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
+ if (val & ACPI_BITMASK_SLEEP_ENABLE) {
/* change suspend type */
sus_typ = (val >> 10) & 7;
switch(sus_typ) {
@@ -143,9 +135,10 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
qemu_system_shutdown_request();
break;
case 1:
- /* RSM_STS should be set on resume. Pretend that resume
- was caused by power button */
- s->pmsts |= (RSM_STS | PWRBTN_STS);
+ /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
+ Pretend that resume was caused by power button */
+ s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
+ ACPI_BITMASK_POWER_BUTTON_STATUS);
qemu_system_reset_request();
#if defined(TARGET_I386)
cmos_set_s3_resume();
@@ -225,9 +218,9 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
/* ACPI specs 3.0, 4.7.2.5 */
if (val == ACPI_ENABLE) {
- s->pmcntrl |= SCI_EN;
+ s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
} else if (val == ACPI_DISABLE) {
- s->pmcntrl &= ~SCI_EN;
+ s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
}
if (s->dev.config[0x5b] & (1 << 1)) {
@@ -328,8 +321,8 @@ static void piix4_pm_powerdown(void *arg)
{
PIIX4PMState *pm_state = (PIIX4PMState*) arg;
- if (pm_state->pmen & PWRBTN_EN) {
- pm_state->pmsts |= PWRBTN_EN;
+ if (pm_state->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
+ pm_state->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
pm_update_sci(pm_state);
}
}
diff --git a/hw/acpi.h b/hw/acpi.h
index 884512c..d686b50 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -26,4 +26,60 @@ void qemu_system_powerdown_register(qemu_powerdown_t callback, void *arg);
#define qemu_system_powerdown_register(callback, arg) do { } while (0)
#endif
+/* from linux include/acpi/actype.h */
+/* Default ACPI register widths */
+
+#define ACPI_GPE_REGISTER_WIDTH 8
+#define ACPI_PM1_REGISTER_WIDTH 16
+#define ACPI_PM2_REGISTER_WIDTH 8
+#define ACPI_PM_TIMER_WIDTH 32
+
+/* PM Timer ticks per second (HZ) */
+#define PM_TIMER_FREQUENCY 3579545
+
+
+/* ACPI fixed hardware registers */
+
+/* from linux/drivers/acpi/acpica/aclocal.h */
+/* Masks used to access the bit_registers */
+
+/* PM1x_STS */
+#define ACPI_BITMASK_TIMER_STATUS 0x0001
+#define ACPI_BITMASK_BUS_MASTER_STATUS 0x0010
+#define ACPI_BITMASK_GLOBAL_LOCK_STATUS 0x0020
+#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100
+#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200
+#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
+#define ACPI_BITMASK_WAKE_STATUS 0x8000
+
+#define ACPI_BITMASK_ALL_FIXED_STATUS (\
+ ACPI_BITMASK_TIMER_STATUS | \
+ ACPI_BITMASK_BUS_MASTER_STATUS | \
+ ACPI_BITMASK_GLOBAL_LOCK_STATUS | \
+ ACPI_BITMASK_POWER_BUTTON_STATUS | \
+ ACPI_BITMASK_SLEEP_BUTTON_STATUS | \
+ ACPI_BITMASK_RT_CLOCK_STATUS | \
+ ACPI_BITMASK_WAKE_STATUS)
+
+/* PM1x_EN */
+#define ACPI_BITMASK_TIMER_ENABLE 0x0001
+#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE 0x0020
+#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100
+#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200
+#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
+
+/* PM1x_CNT */
+#define ACPI_BITMASK_SCI_ENABLE 0x0001
+#define ACPI_BITMASK_BUS_MASTER_RLD 0x0002
+#define ACPI_BITMASK_GLOBAL_LOCK_RELEASE 0x0004
+#define ACPI_BITMASK_SLEEP_TYPE 0x1C00
+#define ACPI_BITMASK_SLEEP_ENABLE 0x2000
+
+/* PM2_CNT */
+#define ACPI_BITMASK_ARB_DISABLE 0x0001
+
+/* PM_TMR */
+
#endif /* !QEMU_HW_ACPI_H */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 06/18] acpi.c: split acpi.c into the common part and the piix4 part.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (4 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 05/18] acpi: add acpi constants from linux header files and use them Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 07/18] pc.c: Make smm enable/disable function i440fx independent Isaku Yamahata
` (12 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Split acpi.c into the common part and the piix4 specific part.
The common part will be used later.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
Makefile.target | 4 +-
hw/acpi.c | 556 +------------------------------------------
hw/{acpi.c => acpi_piix4.c} | 202 +----------------
3 files changed, 5 insertions(+), 757 deletions(-)
copy hw/{acpi.c => acpi_piix4.c} (73%)
diff --git a/Makefile.target b/Makefile.target
index 1ab708b..2cf55b9 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -573,7 +573,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
OBJS+= ide.o pckbd.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
-OBJS+= pc_smbus.o pc_apm.o
+OBJS+= acpi_piix4.o pc_smbus.o pc_apm.o
OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
OBJS += device-hotplug.o pci-hotplug.o smbios.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
@@ -609,7 +609,7 @@ OBJS+= mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
OBJS+= g364fb.o jazz_led.o dp8393x.o
OBJS+= ide.o gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
-OBJS+= pc_smbus.o pc_apm.o
+OBJS+= acpi_piix4.o pc_smbus.o pc_apm.o
OBJS+= piix_pci.o parallel.o cirrus_vga.o pcspk.o $(SOUND_HW)
OBJS+= mipsnet.o
OBJS+= pflash_cfi01.o
diff --git a/hw/acpi.c b/hw/acpi.c
index 4d0690e..19f5df0 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -18,374 +18,9 @@
*/
#include "hw.h"
#include "pc.h"
-#include "pc_apm.h"
-#include "pc_smbus.h"
#include "pci.h"
-#include "qemu-timer.h"
#include "sysemu.h"
-#include "i2c.h"
-#include "smbus.h"
-#include "kvm.h"
-
-//#define DEBUG
-
-#define ACPI_DBG_IO_ADDR 0xb044
-
-typedef struct PIIX4PMState {
- PCIDevice dev;
- uint16_t pmsts;
- uint16_t pmen;
- uint16_t pmcntrl;
-
- APMState apm;
-
- QEMUTimer *tmr_timer;
- int64_t tmr_overflow_time;
-
- PCSMBus smb;
-
- qemu_irq irq;
-} PIIX4PMState;
-
-#define ACPI_ENABLE 0xf1
-#define ACPI_DISABLE 0xf0
-
-static PIIX4PMState *pm_state;
-
-static uint32_t get_pmtmr(PIIX4PMState *s)
-{
- uint32_t d;
- d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, ticks_per_sec);
- return d & 0xffffff;
-}
-
-static int get_pmsts(PIIX4PMState *s)
-{
- int64_t d;
- int pmsts;
- pmsts = s->pmsts;
- d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, ticks_per_sec);
- if (d >= s->tmr_overflow_time)
- s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
- return s->pmsts;
-}
-
-static void pm_update_sci(PIIX4PMState *s)
-{
- int sci_level, pmsts;
- int64_t expire_time;
-
- pmsts = get_pmsts(s);
- sci_level = (((pmsts & s->pmen) &
- (ACPI_BITMASK_RT_CLOCK_ENABLE |
- ACPI_BITMASK_POWER_BUTTON_ENABLE |
- ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
- ACPI_BITMASK_TIMER_ENABLE)) != 0);
- qemu_set_irq(s->irq, sci_level);
- /* schedule a timer interruption if needed */
- if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
- !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
- expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec,
- PM_TIMER_FREQUENCY);
- qemu_mod_timer(s->tmr_timer, expire_time);
- } else {
- qemu_del_timer(s->tmr_timer);
- }
-}
-
-static void pm_tmr_timer(void *opaque)
-{
- PIIX4PMState *s = opaque;
- pm_update_sci(s);
-}
-
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- PIIX4PMState *s = opaque;
- addr &= 0x3f;
- switch(addr) {
- case 0x00:
- {
- int64_t d;
- int pmsts;
- pmsts = get_pmsts(s);
- if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
- /* if TMRSTS is reset, then compute the new overflow time */
- d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
- ticks_per_sec);
- s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
- }
- s->pmsts &= ~val;
- pm_update_sci(s);
- }
- break;
- case 0x02:
- s->pmen = val;
- pm_update_sci(s);
- break;
- case 0x04:
- {
- int sus_typ;
- s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
- if (val & ACPI_BITMASK_SLEEP_ENABLE) {
- /* change suspend type */
- sus_typ = (val >> 10) & 7;
- switch(sus_typ) {
- case 0: /* soft power off */
- qemu_system_shutdown_request();
- break;
- case 1:
- /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
- Pretend that resume was caused by power button */
- s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
- ACPI_BITMASK_POWER_BUTTON_STATUS);
- qemu_system_reset_request();
-#if defined(TARGET_I386)
- cmos_set_s3_resume();
-#endif
- default:
- break;
- }
- }
- }
- break;
- default:
- break;
- }
-#ifdef DEBUG
- printf("PM writew port=0x%04x val=0x%04x\n", addr, val);
-#endif
-}
-
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val;
-
- addr &= 0x3f;
- switch(addr) {
- case 0x00:
- val = get_pmsts(s);
- break;
- case 0x02:
- val = s->pmen;
- break;
- case 0x04:
- val = s->pmcntrl;
- break;
- default:
- val = 0;
- break;
- }
-#ifdef DEBUG
- printf("PM readw port=0x%04x val=0x%04x\n", addr, val);
-#endif
- return val;
-}
-
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- // PIIX4PMState *s = opaque;
- addr &= 0x3f;
-#ifdef DEBUG
- printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
-#endif
-}
-
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val;
-
- addr &= 0x3f;
- switch(addr) {
- case 0x08:
- val = get_pmtmr(s);
- break;
- default:
- val = 0;
- break;
- }
-#ifdef DEBUG
- printf("PM readl port=0x%04x val=0x%08x\n", addr, val);
-#endif
- return val;
-}
-
-static void apm_ctrl_changed(uint32_t val, void *arg)
-{
- PIIX4PMState *s = arg;
-
- /* ACPI specs 3.0, 4.7.2.5 */
- if (val == ACPI_ENABLE) {
- s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
- } else if (val == ACPI_DISABLE) {
- s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
- }
-
- if (s->dev.config[0x5b] & (1 << 1)) {
- cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
- }
-}
-
-static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-#if defined(DEBUG)
- printf("ACPI: DBG: 0x%08x\n", val);
-#endif
-}
-
-static void pm_io_space_update(PIIX4PMState *s)
-{
- uint32_t pm_io_base;
-
- if (s->dev.config[0x80] & 1) {
- pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
- pm_io_base &= 0xffc0;
-
- /* XXX: need to improve memory and ioport allocation */
-#if defined(DEBUG)
- printf("PM: mapping to 0x%x\n", pm_io_base);
-#endif
- register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
- register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
- register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
- register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
- }
-}
-
-static void pm_write_config(PCIDevice *d,
- uint32_t address, uint32_t val, int len)
-{
- pci_default_write_config(d, address, val, len);
- if (address == 0x80)
- pm_io_space_update((PIIX4PMState *)d);
-}
-
-static void pm_save(QEMUFile* f,void *opaque)
-{
- PIIX4PMState *s = opaque;
-
- pci_device_save(&s->dev, f);
-
- qemu_put_be16s(f, &s->pmsts);
- qemu_put_be16s(f, &s->pmen);
- qemu_put_be16s(f, &s->pmcntrl);
- apm_save(f, &s->apm);
- qemu_put_timer(f, s->tmr_timer);
- qemu_put_be64(f, s->tmr_overflow_time);
-}
-
-static int pm_load(QEMUFile* f,void* opaque,int version_id)
-{
- PIIX4PMState *s = opaque;
- int ret;
-
- if (version_id > 1)
- return -EINVAL;
-
- ret = pci_device_load(&s->dev, f);
- if (ret < 0)
- return ret;
-
- qemu_get_be16s(f, &s->pmsts);
- qemu_get_be16s(f, &s->pmen);
- qemu_get_be16s(f, &s->pmcntrl);
- apm_load(f, &s->apm);
- qemu_get_timer(f, s->tmr_timer);
- s->tmr_overflow_time=qemu_get_be64(f);
-
- pm_io_space_update(s);
-
- return 0;
-}
-
-static void piix4_reset(void *opaque)
-{
- PIIX4PMState *s = opaque;
- uint8_t *pci_conf = s->dev.config;
-
- pci_conf[0x58] = 0;
- pci_conf[0x59] = 0;
- pci_conf[0x5a] = 0;
- pci_conf[0x5b] = 0;
-
- if (kvm_enabled()) {
- /* Mark SMM as already inited (until KVM supports SMM). */
- pci_conf[0x5B] = 0x02;
- }
-}
-
-#if defined(TARGET_I386)
-static void piix4_pm_powerdown(void *arg)
-{
- PIIX4PMState *pm_state = (PIIX4PMState*) arg;
-
- if (pm_state->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
- pm_state->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
- pm_update_sci(pm_state);
- }
-}
-#endif
-
-i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
- qemu_irq sci_irq)
-{
- PIIX4PMState *s;
- uint8_t *pci_conf;
-
- s = (PIIX4PMState *)pci_register_device(bus,
- "PM", sizeof(PIIX4PMState),
- devfn, NULL, pm_write_config);
- pm_state = s;
- pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_3);
- pci_conf[0x06] = 0x80;
- pci_conf[0x07] = 0x02;
- pci_conf[0x08] = 0x03; // revision number
- pci_conf[0x09] = 0x00;
- pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
- pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
- pci_conf[0x3d] = 0x01; // interrupt pin 1
-
- pci_conf[0x40] = 0x01; /* PM io base read only bit */
-
- /* APM */
- apm_init(&s->apm, apm_ctrl_changed, s);
-
- register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
-
- if (kvm_enabled()) {
- /* Mark SMM as already inited to prevent SMM from running. KVM does not
- * support SMM mode. */
- pci_conf[0x5B] = 0x02;
- }
-
- /* XXX: which specification is used ? The i82731AB has different
- mappings */
- pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
- pci_conf[0x63] = 0x60;
- pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
- (serial_hds[1] != NULL ? 0x90 : 0);
-
- pci_conf[0x90] = smb_io_base | 1;
- pci_conf[0x91] = smb_io_base >> 8;
- pci_conf[0xd2] = 0x09;
- register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
- register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
-
- s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
-
- register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
-
- pc_smbus_init(&s->smb);
- s->irq = sci_irq;
- qemu_register_reset(piix4_reset, 0, s);
- qemu_system_powerdown_register(piix4_pm_powerdown, pm_state);
-
- return s->smb.smbus;
-}
+#include "acpi.h"
#if defined(TARGET_I386)
static qemu_powerdown_t qemu_powerdown_callback;
@@ -407,195 +42,6 @@ void qemu_system_powerdown(void)
}
#endif
-#define GPE_BASE 0xafe0
-#define PCI_BASE 0xae00
-#define PCI_EJ_BASE 0xae08
-
-struct gpe_regs {
- uint16_t sts; /* status */
- uint16_t en; /* enabled */
-};
-
-struct pci_status {
- uint32_t up;
- uint32_t down;
-};
-
-static struct gpe_regs gpe;
-static struct pci_status pci0_status;
-
-static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
-{
- if (addr & 1)
- return (val >> 8) & 0xff;
- return val & 0xff;
-}
-
-static uint32_t gpe_readb(void *opaque, uint32_t addr)
-{
- uint32_t val = 0;
- struct gpe_regs *g = opaque;
- switch (addr) {
- case GPE_BASE:
- case GPE_BASE + 1:
- val = gpe_read_val(g->sts, addr);
- break;
- case GPE_BASE + 2:
- case GPE_BASE + 3:
- val = gpe_read_val(g->en, addr);
- break;
- default:
- break;
- }
-
-#if defined(DEBUG)
- printf("gpe read %x == %x\n", addr, val);
-#endif
- return val;
-}
-
-static void gpe_write_val(uint16_t *cur, int addr, uint32_t val)
-{
- if (addr & 1)
- *cur = (*cur & 0xff) | (val << 8);
- else
- *cur = (*cur & 0xff00) | (val & 0xff);
-}
-
-static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val)
-{
- uint16_t x1, x0 = val & 0xff;
- int shift = (addr & 1) ? 8 : 0;
-
- x1 = (*cur >> shift) & 0xff;
-
- x1 = x1 & ~x0;
-
- *cur = (*cur & (0xff << (8 - shift))) | (x1 << shift);
-}
-
-static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- struct gpe_regs *g = opaque;
- switch (addr) {
- case GPE_BASE:
- case GPE_BASE + 1:
- gpe_reset_val(&g->sts, addr, val);
- break;
- case GPE_BASE + 2:
- case GPE_BASE + 3:
- gpe_write_val(&g->en, addr, val);
- break;
- default:
- break;
- }
-
-#if defined(DEBUG)
- printf("gpe write %x <== %d\n", addr, val);
-#endif
-}
-
-static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
-{
- uint32_t val = 0;
- struct pci_status *g = opaque;
- switch (addr) {
- case PCI_BASE:
- val = g->up;
- break;
- case PCI_BASE + 4:
- val = g->down;
- break;
- default:
- break;
- }
-
-#if defined(DEBUG)
- printf("pcihotplug read %x == %x\n", addr, val);
-#endif
- return val;
-}
-
-static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
-{
- struct pci_status *g = opaque;
- switch (addr) {
- case PCI_BASE:
- g->up = val;
- break;
- case PCI_BASE + 4:
- g->down = val;
- break;
- }
-
-#if defined(DEBUG)
- printf("pcihotplug write %x <== %d\n", addr, val);
-#endif
-}
-
-static uint32_t pciej_read(void *opaque, uint32_t addr)
-{
-#if defined(DEBUG)
- printf("pciej read %x\n", addr);
-#endif
- return 0;
-}
-
-static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
-{
-#if defined (TARGET_I386)
- int slot = ffs(val) - 1;
-
- pci_device_hot_remove_success(0, slot);
-#endif
-
-#if defined(DEBUG)
- printf("pciej write %x <== %d\n", addr, val);
-#endif
-}
-
-static void piix4_device_hot_add(int bus, int slot, int state);
-
-void piix4_acpi_system_hot_add_init(void)
-{
- register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
- register_ioport_read(GPE_BASE, 4, 1, gpe_readb, &gpe);
-
- register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
- register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, &pci0_status);
-
- register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL);
- register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, NULL);
-
- qemu_system_device_hot_add_register(piix4_device_hot_add);
-}
-
-static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
-{
- g->sts |= 2;
- p->up |= (1 << slot);
-}
-
-static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
-{
- g->sts |= 2;
- p->down |= (1 << slot);
-}
-
-static void piix4_device_hot_add(int bus, int slot, int state)
-{
- pci0_status.up = 0;
- pci0_status.down = 0;
- if (state)
- enable_device(&pci0_status, &gpe, slot);
- else
- disable_device(&pci0_status, &gpe, slot);
- if (gpe.en & 2) {
- qemu_set_irq(pm_state->irq, 1);
- qemu_set_irq(pm_state->irq, 0);
- }
-}
-
static qemu_system_device_hot_add_t device_hot_add_callback;
void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback)
{
diff --git a/hw/acpi.c b/hw/acpi_piix4.c
similarity index 73%
copy from hw/acpi.c
copy to hw/acpi_piix4.c
index 4d0690e..0f6f656 100644
--- a/hw/acpi.c
+++ b/hw/acpi_piix4.c
@@ -26,6 +26,7 @@
#include "i2c.h"
#include "smbus.h"
#include "kvm.h"
+#include "acpi.h"
//#define DEBUG
@@ -254,6 +255,7 @@ static void pm_io_space_update(PIIX4PMState *s)
}
}
+
static void pm_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
@@ -387,25 +389,6 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
return s->smb.smbus;
}
-#if defined(TARGET_I386)
-static qemu_powerdown_t qemu_powerdown_callback;
-static void *qemu_powerdown_arg;
-
-void qemu_system_powerdown_register(qemu_powerdown_t callback, void *arg)
-{
- qemu_powerdown_callback = callback;
- qemu_powerdown_arg = arg;
-}
-
-void qemu_system_powerdown(void)
-{
- if (!qemu_powerdown_callback) {
- qemu_system_shutdown_request();
- } else {
- qemu_powerdown_callback(qemu_powerdown_arg);
- }
-}
-#endif
#define GPE_BASE 0xafe0
#define PCI_BASE 0xae00
@@ -595,184 +578,3 @@ static void piix4_device_hot_add(int bus, int slot, int state)
qemu_set_irq(pm_state->irq, 0);
}
}
-
-static qemu_system_device_hot_add_t device_hot_add_callback;
-void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback)
-{
- device_hot_add_callback = callback;
-}
-
-void qemu_system_device_hot_add(int pcibus, int slot, int state)
-{
- if (device_hot_add_callback)
- device_hot_add_callback(pcibus, slot, state);
-}
-
-struct acpi_table_header
-{
- char signature [4]; /* ACPI signature (4 ASCII characters) */
- uint32_t length; /* Length of table, in bytes, including header */
- uint8_t revision; /* ACPI Specification minor version # */
- uint8_t checksum; /* To make sum of entire table == 0 */
- char oem_id [6]; /* OEM identification */
- char oem_table_id [8]; /* OEM table identification */
- uint32_t oem_revision; /* OEM revision number */
- char asl_compiler_id [4]; /* ASL compiler vendor ID */
- uint32_t asl_compiler_revision; /* ASL compiler revision number */
-} __attribute__((packed));
-
-char *acpi_tables;
-size_t acpi_tables_len;
-
-static int acpi_checksum(const uint8_t *data, int len)
-{
- int sum, i;
- sum = 0;
- for(i = 0; i < len; i++)
- sum += data[i];
- return (-sum) & 0xff;
-}
-
-int acpi_table_add(const char *t)
-{
- static const char *dfl_id = "QEMUQEMU";
- char buf[1024], *p, *f;
- struct acpi_table_header acpi_hdr;
- unsigned long val;
- size_t off;
-
- memset(&acpi_hdr, 0, sizeof(acpi_hdr));
-
- if (get_param_value(buf, sizeof(buf), "sig", t)) {
- strncpy(acpi_hdr.signature, buf, 4);
- } else {
- strncpy(acpi_hdr.signature, dfl_id, 4);
- }
- if (get_param_value(buf, sizeof(buf), "rev", t)) {
- val = strtoul(buf, &p, 10);
- if (val > 255 || *p != '\0')
- goto out;
- } else {
- val = 1;
- }
- acpi_hdr.revision = (int8_t)val;
-
- if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
- strncpy(acpi_hdr.oem_id, buf, 6);
- } else {
- strncpy(acpi_hdr.oem_id, dfl_id, 6);
- }
-
- if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
- strncpy(acpi_hdr.oem_table_id, buf, 8);
- } else {
- strncpy(acpi_hdr.oem_table_id, dfl_id, 8);
- }
-
- if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
- val = strtol(buf, &p, 10);
- if(*p != '\0')
- goto out;
- } else {
- val = 1;
- }
- acpi_hdr.oem_revision = cpu_to_le32(val);
-
- if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
- strncpy(acpi_hdr.asl_compiler_id, buf, 4);
- } else {
- strncpy(acpi_hdr.asl_compiler_id, dfl_id, 4);
- }
-
- if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
- val = strtol(buf, &p, 10);
- if(*p != '\0')
- goto out;
- } else {
- val = 1;
- }
- acpi_hdr.asl_compiler_revision = cpu_to_le32(val);
-
- if (!get_param_value(buf, sizeof(buf), "data", t)) {
- buf[0] = '\0';
- }
-
- acpi_hdr.length = sizeof(acpi_hdr);
-
- f = buf;
- while (buf[0]) {
- struct stat s;
- char *n = strchr(f, ':');
- if (n)
- *n = '\0';
- if(stat(f, &s) < 0) {
- fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
- goto out;
- }
- acpi_hdr.length += s.st_size;
- if (!n)
- break;
- *n = ':';
- f = n + 1;
- }
-
- if (!acpi_tables) {
- acpi_tables_len = sizeof(uint16_t);
- acpi_tables = qemu_mallocz(acpi_tables_len);
- }
- p = acpi_tables + acpi_tables_len;
- acpi_tables_len += sizeof(uint16_t) + acpi_hdr.length;
- acpi_tables = qemu_realloc(acpi_tables, acpi_tables_len);
-
- acpi_hdr.length = cpu_to_le32(acpi_hdr.length);
- *(uint16_t*)p = acpi_hdr.length;
- p += sizeof(uint16_t);
- memcpy(p, &acpi_hdr, sizeof(acpi_hdr));
- off = sizeof(acpi_hdr);
-
- f = buf;
- while (buf[0]) {
- struct stat s;
- int fd;
- char *n = strchr(f, ':');
- if (n)
- *n = '\0';
- fd = open(f, O_RDONLY);
-
- if(fd < 0)
- goto out;
- if(fstat(fd, &s) < 0) {
- close(fd);
- goto out;
- }
-
- do {
- int r;
- r = read(fd, p + off, s.st_size);
- if (r > 0) {
- off += r;
- s.st_size -= r;
- } else if ((r < 0 && errno != EINTR) || r == 0) {
- close(fd);
- goto out;
- }
- } while(s.st_size);
-
- close(fd);
- if (!n)
- break;
- f = n + 1;
- }
-
- ((struct acpi_table_header*)p)->checksum = acpi_checksum((uint8_t*)p, off);
- /* increase number of tables */
- (*(uint16_t*)acpi_tables) =
- cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
- return 0;
-out:
- if (acpi_tables) {
- free(acpi_tables);
- acpi_tables = NULL;
- }
- return -1;
-}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 07/18] pc.c: Make smm enable/disable function i440fx independent.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (5 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 06/18] acpi.c: split acpi.c into the common part and the piix4 part Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 08/18] pc.c: remove unnecessary global variables, pit and ioapic Isaku Yamahata
` (11 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
make cpu_smm_update() generic to be independent on i440fx by
registering a callback.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 18 +++++++++++++++---
hw/pc.h | 4 +++-
hw/piix_pci.c | 8 +++++---
3 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index a848d8d..b17a33f 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -58,7 +58,6 @@ static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
static PITState *pit;
static IOAPICState *ioapic;
-static PCIDevice *i440fx_state;
typedef struct rom_reset_data {
uint8_t *data;
@@ -118,10 +117,22 @@ uint64_t cpu_get_tsc(CPUX86State *env)
}
/* SMM support */
+
+static cpu_set_smm_t smm_set;
+static void *smm_arg;
+
+void cpu_smm_register(cpu_set_smm_t callback, void *arg)
+{
+ assert(smm_set == NULL);
+ assert(smm_arg == NULL);
+ smm_set = callback;
+ smm_arg = arg;
+}
+
void cpu_smm_update(CPUState *env)
{
- if (i440fx_state && env == first_cpu)
- i440fx_set_smm(i440fx_state, (env->hflags >> HF_SMM_SHIFT) & 1);
+ if (smm_set && smm_arg && env == first_cpu)
+ smm_set(!!(env->hflags && HF_SMM_SHIFT), smm_arg);
}
@@ -848,6 +859,7 @@ static void pc_init1(ram_addr_t ram_size,
ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
int bios_size, isa_bios_size, oprom_area_size;
PCIBus *pci_bus;
+ static PCIDevice *i440fx_state;
int piix3_devfn = -1;
CPUState *env;
qemu_irq *cpu_irq;
diff --git a/hw/pc.h b/hw/pc.h
index 9fbae20..bd711ce 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -103,6 +103,9 @@ extern int fd_bootchk;
void ioport_set_a20(int enable);
int ioport_get_a20(void);
+typedef void (*cpu_set_smm_t)(int smm, void *arg);
+void cpu_smm_register(cpu_set_smm_t callback, void *arg);
+
/* acpi.c */
extern int acpi_enabled;
extern char *acpi_tables;
@@ -126,7 +129,6 @@ int pcspk_audio_init(qemu_irq *pic);
/* piix_pci.c */
PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic);
-void i440fx_set_smm(PCIDevice *d, int val);
int piix3_init(PCIBus *bus, int devfn);
void i440fx_init_memory_mappings(PCIDevice *d);
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 914a65a..e7959f8 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -107,16 +107,16 @@ static void i440fx_update_memory_mappings(PCIDevice *d)
}
}
-void i440fx_set_smm(PCIDevice *d, int val)
+static void i440fx_set_smm(int smm, void *arg)
{
- val = (val != 0);
+ int val = (smm != 0);
+ PCIDevice *d = (PCIDevice*)arg;
if (smm_enabled != val) {
smm_enabled = val;
i440fx_update_memory_mappings(d);
}
}
-
/* XXX: suppress when better memory API. We make the assumption that
no device (in particular the VGA) changes the memory mappings in
the 0xa0000-0x100000 range */
@@ -202,6 +202,8 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
d->config[0x72] = 0x02; /* SMRAM */
register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d);
+ cpu_smm_register(&i440fx_set_smm, d);
+
*pi440fx_state = d;
return b;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 08/18] pc.c: remove unnecessary global variables, pit and ioapic..
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (6 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 07/18] pc.c: Make smm enable/disable function i440fx independent Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 09/18] pc.c: remove a global variable, floppy_controller Isaku Yamahata
` (10 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
remove unnecessary global static variables, pit and ioapic.
They are unnecessarily global so make them local.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index b17a33f..16592e8 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -56,8 +56,6 @@
static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
-static PITState *pit;
-static IOAPICState *ioapic;
typedef struct rom_reset_data {
uint8_t *data;
@@ -868,6 +866,8 @@ static void pc_init1(ram_addr_t ram_size,
BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
BlockDriverState *fd[MAX_FD];
int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
+ PITState *pit;
+ IOAPICState *ioapic = NULL;
if (ram_size >= 0xe0000000 ) {
above_4g_mem_size = ram_size - 0xe0000000;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 09/18] pc.c: remove a global variable, floppy_controller.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (7 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 08/18] pc.c: remove unnecessary global variables, pit and ioapic Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 10/18] pc.c: remove a global variable, RTCState *rtc_state Isaku Yamahata
` (9 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Remove a global variable, floppy_controller.
Since it is unnecessarily global, make it local and pass it as
a function argument.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 16592e8..9055c0d 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -54,7 +54,6 @@
#define MAX_IDE_BUS 2
-static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
typedef struct rom_reset_data {
@@ -264,7 +263,8 @@ static int pc_boot_set(void *opaque, const char *boot_device)
/* 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, BlockDriverState **hd_table,
+ fdctrl_t *floppy_controller)
{
RTCState *s = rtc_state;
int nbds, bds[3] = { 0, };
@@ -866,6 +866,7 @@ static void pc_init1(ram_addr_t ram_size,
BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
BlockDriverState *fd[MAX_FD];
int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
+ fdctrl_t *floppy_controller;
PITState *pit;
IOAPICState *ioapic = NULL;
@@ -1117,7 +1118,8 @@ static void pc_init1(ram_addr_t ram_size,
}
floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
- cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
+ cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
+ floppy_controller);
if (pci_enabled && usb_enabled) {
usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 10/18] pc.c: remove a global variable, RTCState *rtc_state.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (8 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 09/18] pc.c: remove a global variable, floppy_controller Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 11/18] pc.c: introduce a function to allocate cpu irq Isaku Yamahata
` (8 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
remove a global variable, RTCState *rtc_state.
Only the cmos_set_s3_resume_init() needs it global.
So introduce a registering function and make it local.
As for other function which references the variable, pass it
as a function argument.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 25 ++++++++++++++++---------
hw/pc.h | 6 ++++++
2 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 9055c0d..04d61bd 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -54,8 +54,6 @@
#define MAX_IDE_BUS 2
-static RTCState *rtc_state;
-
typedef struct rom_reset_data {
uint8_t *data;
target_phys_addr_t addr;
@@ -199,9 +197,9 @@ static int cmos_get_fd_drive_type(int fd0)
return val;
}
-static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
+static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd,
+ RTCState *s)
{
- RTCState *s = rtc_state;
int cylinders, heads, sectors;
bdrv_get_geometry_hint(hd, &cylinders, &heads, §ors);
rtc_set_memory(s, type_ofs, 47);
@@ -264,9 +262,8 @@ static int pc_boot_set(void *opaque, const char *boot_device)
/* 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,
- fdctrl_t *floppy_controller)
+ fdctrl_t *floppy_controller, RTCState *s)
{
- RTCState *s = rtc_state;
int nbds, bds[3] = { 0, };
int val;
int fd0, fd1, nb;
@@ -355,9 +352,9 @@ static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
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], s);
if (hd_table[1])
- cmos_init_hd(0x1a, 0x24, hd_table[1]);
+ cmos_init_hd(0x1a, 0x24, hd_table[1], s);
val = 0;
for (i = 0; i < 4; i++) {
@@ -867,6 +864,7 @@ static void pc_init1(ram_addr_t ram_size,
BlockDriverState *fd[MAX_FD];
int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
fdctrl_t *floppy_controller;
+ RTCState *rtc_state;
PITState *pit;
IOAPICState *ioapic = NULL;
@@ -1036,6 +1034,7 @@ static void pc_init1(ram_addr_t ram_size,
}
rtc_state = rtc_init(0x70, i8259[8], 2000);
+ cmos_set_s3_resume_init(rtc_state);
qemu_register_boot_set(pc_boot_set, rtc_state);
@@ -1119,7 +1118,7 @@ static void pc_init1(ram_addr_t ram_size,
floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
- floppy_controller);
+ floppy_controller, rtc_state);
if (pci_enabled && usb_enabled) {
usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
@@ -1204,13 +1203,21 @@ static void pc_init_isa(ram_addr_t ram_size,
initrd_filename, 0, cpu_model);
}
+#if defined(TARGET_I386)
/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
BIOS will read it and start S3 resume at POST Entry */
+static RTCState *rtc_state;
+void cmos_set_s3_resume_init(RTCState *s)
+{
+ rtc_state = s;
+}
+
void cmos_set_s3_resume(void)
{
if (rtc_state)
rtc_set_memory(rtc_state, 0xF, 0xFE);
}
+#endif
static QEMUMachine pc_machine = {
.name = "pc",
diff --git a/hw/pc.h b/hw/pc.h
index bd711ce..a18e558 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -95,7 +95,13 @@ RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
int base_year);
void rtc_set_memory(RTCState *s, int addr, int val);
void rtc_set_date(RTCState *s, const struct tm *tm);
+#if defined(TARGET_I386)
+void cmos_set_s3_resume_init(RTCState *s);
void cmos_set_s3_resume(void);
+#else
+static inline void cmos_set_s3_resume_init(RTCState *s) {}
+static inline void cmos_set_s3_resume(void) {}
+#endif
/* pc.c */
extern int fd_bootchk;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 11/18] pc.c: introduce a function to allocate cpu irq.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (9 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 10/18] pc.c: remove a global variable, RTCState *rtc_state Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-21 20:32 ` Blue Swirl
2009-06-18 10:57 ` [Qemu-devel] [PATCH 12/18] pc.c: make pc_init1() not refer ferr_irq directly Isaku Yamahata
` (7 subsequent siblings)
18 siblings, 1 reply; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Introduce a function, pc_allocate_cpu_irq(), to allocate cpu irq
in order to make pic_irq_request() piix independent.
Later piix code will be split out to another file keeping pic_irq_request()
static.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 04d61bd..16e95ec 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -841,6 +841,11 @@ int cpu_is_bsp(CPUState *env)
return env->cpuid_apic_id == 0;
}
+static qemu_irq *pc_allocte_cpu_irq(void)
+{
+ return qemu_allocate_irqs(pic_irq_request, NULL, 1);
+}
+
/* PC hardware initialisation */
static void pc_init1(ram_addr_t ram_size,
const char *boot_device,
@@ -998,7 +1003,7 @@ static void pc_init1(ram_addr_t ram_size,
bochs_bios_init();
- cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
+ cpu_irq = pc_allocte_cpu_irq();
i8259 = i8259_init(cpu_irq[0]);
ferr_irq = i8259[13];
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 12/18] pc.c: make pc_init1() not refer ferr_irq directly.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (10 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 11/18] pc.c: introduce a function to allocate cpu irq Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 13/18] pc.c: split out cpu initialization from pc_init1() into pc_cpus_init() Isaku Yamahata
` (6 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
By introducing a registering function, make pc_init1() not refer to
ferr_irq directly in order to make ferr_irq piix independent.
Later pc_init1() will be split out into another file keeping ferr_irq
static.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 8 +++++++-
hw/pc.h | 2 ++
2 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 16e95ec..eeb56cc 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -84,6 +84,12 @@ static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
/* MSDOS compatibility mode FPU exception support */
static qemu_irq ferr_irq;
+
+void pc_register_ferr_irq(qemu_irq irq)
+{
+ ferr_irq = irq;
+}
+
/* XXX: add IGNNE support */
void cpu_set_ferr(CPUX86State *s)
{
@@ -1005,7 +1011,7 @@ static void pc_init1(ram_addr_t ram_size,
cpu_irq = pc_allocte_cpu_irq();
i8259 = i8259_init(cpu_irq[0]);
- ferr_irq = i8259[13];
+ pc_register_ferr_irq(i8259[13]);
if (pci_enabled) {
pci_bus = i440fx_init(&i440fx_state, i8259);
diff --git a/hw/pc.h b/hw/pc.h
index a18e558..f5f84ad 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -106,6 +106,8 @@ static inline void cmos_set_s3_resume(void) {}
/* pc.c */
extern int fd_bootchk;
+void pc_register_ferr_irq(qemu_irq irq);
+
void ioport_set_a20(int enable);
int ioport_get_a20(void);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 13/18] pc.c: split out cpu initialization from pc_init1() into pc_cpus_init().
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (11 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 12/18] pc.c: make pc_init1() not refer ferr_irq directly Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 14/18] pc.c: split out memory allocation from pc_init1() into pc_memory_init() Isaku Yamahata
` (5 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
split out cpu initialization which is piix independent from pc_init1()
into pc_cpus_init(). Later it will be used.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 51 +++++++++++++++++++++++++++++----------------------
1 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index eeb56cc..880b510 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -847,6 +847,34 @@ int cpu_is_bsp(CPUState *env)
return env->cpuid_apic_id == 0;
}
+static void pc_cpus_init(const char *cpu_model)
+{
+ int i;
+ CPUState *env;
+
+ /* init CPUs */
+ if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+ cpu_model = "qemu64";
+#else
+ cpu_model = "qemu32";
+#endif
+ }
+
+ for(i = 0; i < smp_cpus; i++) {
+ env = cpu_init(cpu_model);
+ if (!env) {
+ fprintf(stderr, "Unable to find x86 CPU definition\n");
+ exit(1);
+ }
+ if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
+ env->cpuid_apic_id = env->cpu_index;
+ apic_init(env);
+ }
+ qemu_register_reset(main_cpu_reset, 0, env);
+ }
+}
+
static qemu_irq *pc_allocte_cpu_irq(void)
{
return qemu_allocate_irqs(pic_irq_request, NULL, 1);
@@ -867,7 +895,6 @@ static void pc_init1(ram_addr_t ram_size,
PCIBus *pci_bus;
static PCIDevice *i440fx_state;
int piix3_devfn = -1;
- CPUState *env;
qemu_irq *cpu_irq;
qemu_irq *i8259;
int index;
@@ -888,27 +915,7 @@ static void pc_init1(ram_addr_t ram_size,
linux_boot = (kernel_filename != NULL);
- /* init CPUs */
- if (cpu_model == NULL) {
-#ifdef TARGET_X86_64
- cpu_model = "qemu64";
-#else
- cpu_model = "qemu32";
-#endif
- }
-
- for(i = 0; i < smp_cpus; i++) {
- env = cpu_init(cpu_model);
- if (!env) {
- fprintf(stderr, "Unable to find x86 CPU definition\n");
- exit(1);
- }
- if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
- env->cpuid_apic_id = env->cpu_index;
- apic_init(env);
- }
- qemu_register_reset(main_cpu_reset, 0, env);
- }
+ pc_cpus_init(cpu_model);
vmport_init();
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 14/18] pc.c: split out memory allocation from pc_init1() into pc_memory_init()
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (12 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 13/18] pc.c: split out cpu initialization from pc_init1() into pc_cpus_init() Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 15/18] pc.c: split out vga initialization from pc_init1() into pc_vga_init() Isaku Yamahata
` (4 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Split out memory allocation and rom/bios loading which doesn't depend
on piix from pc_init1() into pc_memory_init().
Later it will be used.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 71 +++++++++++++++++++++++++++++++++++++++------------------------
1 files changed, 44 insertions(+), 27 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 880b510..3321d88 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -875,36 +875,19 @@ static void pc_cpus_init(const char *cpu_model)
}
}
-static qemu_irq *pc_allocte_cpu_irq(void)
-{
- return qemu_allocate_irqs(pic_irq_request, NULL, 1);
-}
-
-/* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
- const char *boot_device,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename,
- int pci_enabled, const char *cpu_model)
+static void pc_memory_init(ram_addr_t ram_size,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ ram_addr_t *below_4g_mem_size_p,
+ ram_addr_t *above_4g_mem_size_p)
{
char *filename;
int ret, linux_boot, i;
ram_addr_t ram_addr, bios_offset, option_rom_offset;
ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
int bios_size, isa_bios_size, oprom_area_size;
- PCIBus *pci_bus;
- static PCIDevice *i440fx_state;
- int piix3_devfn = -1;
- qemu_irq *cpu_irq;
- qemu_irq *i8259;
- int index;
- BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
- BlockDriverState *fd[MAX_FD];
int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
- fdctrl_t *floppy_controller;
- RTCState *rtc_state;
- PITState *pit;
- IOAPICState *ioapic = NULL;
if (ram_size >= 0xe0000000 ) {
above_4g_mem_size = ram_size - 0xe0000000;
@@ -912,13 +895,11 @@ static void pc_init1(ram_addr_t ram_size,
} else {
below_4g_mem_size = ram_size;
}
+ *above_4g_mem_size_p = above_4g_mem_size;
+ *below_4g_mem_size_p = below_4g_mem_size;
linux_boot = (kernel_filename != NULL);
- pc_cpus_init(cpu_model);
-
- vmport_init();
-
/* allocate RAM */
ram_addr = qemu_ram_alloc(0xa0000);
cpu_register_physical_memory(0, 0xa0000, ram_addr);
@@ -1015,6 +996,42 @@ static void pc_init1(ram_addr_t ram_size,
bios_size, bios_offset | IO_MEM_ROM);
bochs_bios_init();
+}
+
+static qemu_irq *pc_allocte_cpu_irq(void)
+{
+ return qemu_allocate_irqs(pic_irq_request, NULL, 1);
+}
+
+/* PC hardware initialisation */
+static void pc_init1(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename,
+ int pci_enabled, const char *cpu_model)
+{
+ int i;
+ ram_addr_t below_4g_mem_size, above_4g_mem_size;
+ PCIBus *pci_bus;
+ static PCIDevice *i440fx_state;
+ int piix3_devfn = -1;
+ qemu_irq *cpu_irq;
+ qemu_irq *i8259;
+ int index;
+ BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+ BlockDriverState *fd[MAX_FD];
+ fdctrl_t *floppy_controller;
+ RTCState *rtc_state;
+ PITState *pit;
+ IOAPICState *ioapic = NULL;
+
+ pc_cpus_init(cpu_model);
+
+ vmport_init();
+
+ /* allocate ram and load rom/bios */
+ pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
+ &below_4g_mem_size, &above_4g_mem_size);
cpu_irq = pc_allocte_cpu_irq();
i8259 = i8259_init(cpu_irq[0]);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 15/18] pc.c: split out vga initialization from pc_init1() into pc_vga_init().
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (13 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 14/18] pc.c: split out memory allocation from pc_init1() into pc_memory_init() Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 16/18] pc.c: split out basic device init from pc_init1() into pc_basic_device_init() Isaku Yamahata
` (3 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Split out vga initialization which is independent of piix
from pc_init1() as pc_vga_init().
Later it will be used.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 43 ++++++++++++++++++++++++-------------------
1 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 3321d88..76bead4 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1003,7 +1003,29 @@ static qemu_irq *pc_allocte_cpu_irq(void)
return qemu_allocate_irqs(pic_irq_request, NULL, 1);
}
-/* PC hardware initialisation */
+static void pc_vga_init(PCIBus *pci_bus)
+{
+ if (cirrus_vga_enabled) {
+ if (pci_bus) {
+ pci_cirrus_vga_init(pci_bus);
+ } else {
+ isa_cirrus_vga_init();
+ }
+ } else if (vmsvga_enabled) {
+ if (pci_bus)
+ pci_vmsvga_init(pci_bus);
+ else
+ fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
+ } else if (std_vga_enabled) {
+ if (pci_bus) {
+ pci_vga_init(pci_bus, 0, 0);
+ } else {
+ isa_vga_init();
+ }
+ }
+}
+
+* PC hardware initialisation */
static void pc_init1(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
@@ -1049,24 +1071,7 @@ static void pc_init1(ram_addr_t ram_size,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- if (cirrus_vga_enabled) {
- if (pci_enabled) {
- pci_cirrus_vga_init(pci_bus);
- } else {
- isa_cirrus_vga_init();
- }
- } else if (vmsvga_enabled) {
- if (pci_enabled)
- pci_vmsvga_init(pci_bus);
- else
- fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
- } else if (std_vga_enabled) {
- if (pci_enabled) {
- pci_vga_init(pci_bus, 0, 0);
- } else {
- isa_vga_init();
- }
- }
+ pc_vga_init(pci_enabled? pci_bus: NULL);
rtc_state = rtc_init(0x70, i8259[8], 2000);
cmos_set_s3_resume_init(rtc_state);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 16/18] pc.c: split out basic device init from pc_init1() into pc_basic_device_init()
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (14 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 15/18] pc.c: split out vga initialization from pc_init1() into pc_vga_init() Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 17/18] pc.c: split out pci device init from pc_init1() into pc_pci_device_init() Isaku Yamahata
` (2 subsequent siblings)
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Split out basic device, i.e. legacy devices like floppy, initialization
from pc_init1() into pc_basic_device_init().
Later it will be used.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 105 +++++++++++++++++++++++++++++++++-----------------------------
1 files changed, 56 insertions(+), 49 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 76bead4..6886751 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1025,7 +1025,59 @@ static void pc_vga_init(PCIBus *pci_bus)
}
}
-* PC hardware initialisation */
+static void pc_basic_device_init(qemu_irq *i8259,
+ fdctrl_t **floppy_controller,
+ RTCState **rtc_state)
+{
+ int i;
+ BlockDriverState *fd[MAX_FD];
+ PITState *pit;
+
+ register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
+
+ register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
+
+ *rtc_state = rtc_init(0x70, i8259[8], 2000);
+ cmos_set_s3_resume_init(*rtc_state);
+
+ qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+ register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
+ register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
+
+ pit = pit_init(0x40, i8259[0]);
+ pcspk_init(pit);
+ if (!no_hpet) {
+ hpet_init(i8259);
+ }
+
+ for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+ if (serial_hds[i]) {
+ serial_init(serial_io[i], i8259[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_hds[i]);
+ }
+ }
+
+ i8042_init(i8259[1], i8259[12], 0x60);
+ DMA_init(0);
+ for(i = 0; i < MAX_FD; i++) {
+ int index = drive_get_index(IF_FLOPPY, 0, i);
+ if (index != -1)
+ fd[i] = drives_table[index].bdrv;
+ else
+ fd[i] = NULL;
+ }
+ *floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
+}
+
+/* PC hardware initialisation */
static void pc_init1(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
@@ -1041,11 +1093,8 @@ static void pc_init1(ram_addr_t ram_size,
qemu_irq *i8259;
int index;
BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
- BlockDriverState *fd[MAX_FD];
fdctrl_t *floppy_controller;
RTCState *rtc_state;
- PITState *pit;
- IOAPICState *ioapic = NULL;
pc_cpus_init(cpu_model);
@@ -1066,47 +1115,16 @@ static void pc_init1(ram_addr_t ram_size,
pci_bus = NULL;
}
- /* init basic PC hardware */
- register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
-
- register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
-
pc_vga_init(pci_enabled? pci_bus: NULL);
- rtc_state = rtc_init(0x70, i8259[8], 2000);
- cmos_set_s3_resume_init(rtc_state);
-
- qemu_register_boot_set(pc_boot_set, rtc_state);
-
- register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
- register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
+ /* init basic PC hardware */
+ pc_basic_device_init(i8259, &floppy_controller, &rtc_state);
if (pci_enabled) {
- ioapic = ioapic_init();
- }
- pit = pit_init(0x40, i8259[0]);
- pcspk_init(pit);
- if (!no_hpet) {
- hpet_init(i8259);
- }
- if (pci_enabled) {
+ IOAPICState *ioapic = ioapic_init();
pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
}
- for(i = 0; i < MAX_SERIAL_PORTS; i++) {
- if (serial_hds[i]) {
- serial_init(serial_io[i], i8259[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_hds[i]);
- }
- }
-
watchdog_pc_init(pci_bus);
for(i = 0; i < nb_nics; i++) {
@@ -1142,21 +1160,10 @@ static void pc_init1(ram_addr_t ram_size,
}
}
- i8042_init(i8259[1], i8259[12], 0x60);
- DMA_init(0);
#ifdef HAS_AUDIO
audio_init(pci_enabled ? pci_bus : NULL, i8259);
#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;
- }
- floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
-
cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
floppy_controller, rtc_state);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 17/18] pc.c: split out pci device init from pc_init1() into pc_pci_device_init()
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (15 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 16/18] pc.c: split out basic device init from pc_init1() into pc_basic_device_init() Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 18/18] pc.c: split out piix specific part from pc.c into pc_piix.c Isaku Yamahata
2009-06-18 11:00 ` [Qemu-devel] [PATCH] q35 chipset based pc. wip Isaku Yamahata
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Split out pci device initialization from pc_init1() into pc_pci_device_init().
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pc.c | 72 +++++++++++++++++++++++++++++++++++----------------------------
1 files changed, 40 insertions(+), 32 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 6886751..4885f25 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1077,6 +1077,45 @@ static void pc_basic_device_init(qemu_irq *i8259,
*floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
}
+static void pc_pci_device_init(PCIBus *pci_bus)
+{
+ {
+ int max_bus;
+ int bus;
+
+ max_bus = drive_get_max_bus(IF_SCSI);
+ for (bus = 0; bus <= max_bus; bus++) {
+ pci_create_simple(pci_bus, -1, "lsi53c895a");
+ }
+ }
+
+ /* Add virtio block devices */
+ {
+ int index;
+ int unit_id = 0;
+
+ while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
+ pci_create_simple(pci_bus, -1, "virtio-blk-pci");
+ unit_id++;
+ }
+ }
+
+ /* Add virtio balloon device */
+ if (!no_virtio_balloon) {
+ pci_create_simple(pci_bus, -1, "virtio-balloon-pci");
+ }
+
+ /* Add virtio console devices */
+ {
+ int i;
+ for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
+ if (virtcon_hds[i]) {
+ pci_create_simple(pci_bus, -1, "virtio-console-pci");
+ }
+ }
+ }
+}
+
/* PC hardware initialisation */
static void pc_init1(ram_addr_t ram_size,
const char *boot_device,
@@ -1191,38 +1230,7 @@ static void pc_init1(ram_addr_t ram_size,
}
if (pci_enabled) {
- int max_bus;
- int bus;
-
- max_bus = drive_get_max_bus(IF_SCSI);
- for (bus = 0; bus <= max_bus; bus++) {
- pci_create_simple(pci_bus, -1, "lsi53c895a");
- }
- }
-
- /* 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_create_simple(pci_bus, -1, "virtio-blk-pci");
- unit_id++;
- }
- }
-
- /* Add virtio balloon device */
- if (pci_enabled && !no_virtio_balloon) {
- pci_create_simple(pci_bus, -1, "virtio-balloon-pci");
- }
-
- /* 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-pci");
- }
- }
+ pc_pci_device_init(pci_bus);
}
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH 18/18] pc.c: split out piix specific part from pc.c into pc_piix.c
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (16 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 17/18] pc.c: split out pci device init from pc_init1() into pc_pci_device_init() Isaku Yamahata
@ 2009-06-18 10:57 ` Isaku Yamahata
2009-06-18 11:00 ` [Qemu-devel] [PATCH] q35 chipset based pc. wip Isaku Yamahata
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 10:57 UTC (permalink / raw)
To: qemu-devel; +Cc: yamahata
Finally, we can safely split out the piix specific part from pc.c
into pc_piix.c.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
Makefile.target | 2 +-
hw/pc.c | 207 +++++-------------------------------------------------
hw/pc.h | 22 ++++++
hw/pc_piix.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 251 insertions(+), 190 deletions(-)
create mode 100644 hw/pc_piix.c
diff --git a/Makefile.target b/Makefile.target
index 2cf55b9..f2b59f4 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -573,7 +573,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
OBJS+= ide.o pckbd.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
-OBJS+= acpi_piix4.o pc_smbus.o pc_apm.o
+OBJS+= pc_piix.o acpi_piix4.o pc_smbus.o pc_apm.o
OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
OBJS += device-hotplug.o pci-hotplug.o smbios.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
diff --git a/hw/pc.c b/hw/pc.c
index 4885f25..ddcd5e6 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -52,8 +52,6 @@
#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
-#define MAX_IDE_BUS 2
-
typedef struct rom_reset_data {
uint8_t *data;
target_phys_addr_t addr;
@@ -266,9 +264,9 @@ static int pc_boot_set(void *opaque, const char *boot_device)
}
/* 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,
- fdctrl_t *floppy_controller, RTCState *s)
+void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+ const char *boot_device, BlockDriverState **hd_table,
+ fdctrl_t *floppy_controller, RTCState *s)
{
int nbds, bds[3] = { 0, };
int val;
@@ -769,10 +767,6 @@ static void main_cpu_reset(void *opaque)
cpu_reset(env);
}
-static const int ide_iobase[2] = { 0x1f0, 0x170 };
-static const int ide_iobase2[2] = { 0x3f6, 0x376 };
-static const int ide_irq[2] = { 14, 15 };
-
#define NE2000_NB_MAX 6
static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
@@ -785,7 +779,7 @@ static int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
#ifdef HAS_AUDIO
-static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
+void audio_init (PCIBus *pci_bus, qemu_irq *pic)
{
struct soundhw *c;
@@ -803,7 +797,7 @@ static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
}
#endif
-static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
+void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
{
static int nb_ne2k = 0;
@@ -847,7 +841,7 @@ int cpu_is_bsp(CPUState *env)
return env->cpuid_apic_id == 0;
}
-static void pc_cpus_init(const char *cpu_model)
+void pc_cpus_init(const char *cpu_model)
{
int i;
CPUState *env;
@@ -875,12 +869,12 @@ static void pc_cpus_init(const char *cpu_model)
}
}
-static void pc_memory_init(ram_addr_t ram_size,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- ram_addr_t *below_4g_mem_size_p,
- ram_addr_t *above_4g_mem_size_p)
+void pc_memory_init(ram_addr_t ram_size,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ ram_addr_t *below_4g_mem_size_p,
+ ram_addr_t *above_4g_mem_size_p)
{
char *filename;
int ret, linux_boot, i;
@@ -998,12 +992,12 @@ static void pc_memory_init(ram_addr_t ram_size,
bochs_bios_init();
}
-static qemu_irq *pc_allocte_cpu_irq(void)
+qemu_irq *pc_allocte_cpu_irq(void)
{
return qemu_allocate_irqs(pic_irq_request, NULL, 1);
}
-static void pc_vga_init(PCIBus *pci_bus)
+void pc_vga_init(PCIBus *pci_bus)
{
if (cirrus_vga_enabled) {
if (pci_bus) {
@@ -1025,9 +1019,9 @@ static void pc_vga_init(PCIBus *pci_bus)
}
}
-static void pc_basic_device_init(qemu_irq *i8259,
- fdctrl_t **floppy_controller,
- RTCState **rtc_state)
+void pc_basic_device_init(qemu_irq *i8259,
+ fdctrl_t **floppy_controller,
+ RTCState **rtc_state)
{
int i;
BlockDriverState *fd[MAX_FD];
@@ -1077,7 +1071,7 @@ static void pc_basic_device_init(qemu_irq *i8259,
*floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
}
-static void pc_pci_device_init(PCIBus *pci_bus)
+void pc_pci_device_init(PCIBus *pci_bus)
{
{
int max_bus;
@@ -1116,148 +1110,6 @@ static void pc_pci_device_init(PCIBus *pci_bus)
}
}
-/* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
- const char *boot_device,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename,
- int pci_enabled, const char *cpu_model)
-{
- int i;
- ram_addr_t below_4g_mem_size, above_4g_mem_size;
- PCIBus *pci_bus;
- static PCIDevice *i440fx_state;
- int piix3_devfn = -1;
- qemu_irq *cpu_irq;
- qemu_irq *i8259;
- int index;
- BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
- fdctrl_t *floppy_controller;
- RTCState *rtc_state;
-
- pc_cpus_init(cpu_model);
-
- vmport_init();
-
- /* allocate ram and load rom/bios */
- pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
- &below_4g_mem_size, &above_4g_mem_size);
-
- cpu_irq = pc_allocte_cpu_irq();
- i8259 = i8259_init(cpu_irq[0]);
- pc_register_ferr_irq(i8259[13]);
-
- if (pci_enabled) {
- pci_bus = i440fx_init(&i440fx_state, i8259);
- piix3_devfn = piix3_init(pci_bus, -1);
- } else {
- pci_bus = NULL;
- }
-
- pc_vga_init(pci_enabled? pci_bus: NULL);
-
- /* init basic PC hardware */
- pc_basic_device_init(i8259, &floppy_controller, &rtc_state);
-
- if (pci_enabled) {
- IOAPICState *ioapic = ioapic_init();
- pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
- }
-
- 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);
- else
- pci_nic_init(pci_bus, nd, -1, "ne2k_pci");
- }
-
- piix4_acpi_system_hot_add_init();
-
- if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
- fprintf(stderr, "qemu: too many IDE bus\n");
- exit(1);
- }
-
- 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;
- }
-
- if (pci_enabled) {
- pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
- } else {
- for(i = 0; i < MAX_IDE_BUS; i++) {
- isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
- hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
- }
- }
-
-#ifdef HAS_AUDIO
- audio_init(pci_enabled ? pci_bus : NULL, i8259);
-#endif
-
- cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
- floppy_controller, rtc_state);
-
- if (pci_enabled && usb_enabled) {
- usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
- }
-
- if (pci_enabled && acpi_enabled) {
- uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
- i2c_bus *smbus;
-
- /* TODO: Populate SPD eeprom data. */
- smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[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_init(eeprom);
- }
- }
-
- if (i440fx_state) {
- i440fx_init_memory_mappings(i440fx_state);
- }
-
- if (pci_enabled) {
- pc_pci_device_init(pci_bus);
- }
-}
-
-static void pc_init_pci(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, 1, cpu_model);
-}
-
-static void pc_init_isa(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, 0, cpu_model);
-}
-
#if defined(TARGET_I386)
/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
BIOS will read it and start S3 resume at POST Entry */
@@ -1273,26 +1125,3 @@ void cmos_set_s3_resume(void)
rtc_set_memory(rtc_state, 0xF, 0xFE);
}
#endif
-
-static QEMUMachine pc_machine = {
- .name = "pc",
- .desc = "Standard PC",
- .init = pc_init_pci,
- .max_cpus = 255,
- .is_default = 1,
-};
-
-static QEMUMachine isapc_machine = {
- .name = "isapc",
- .desc = "ISA-only PC",
- .init = pc_init_isa,
- .max_cpus = 1,
-};
-
-static void pc_machine_init(void)
-{
- qemu_register_machine(&pc_machine);
- qemu_register_machine(&isapc_machine);
-}
-
-machine_init(pc_machine_init);
diff --git a/hw/pc.h b/hw/pc.h
index f5f84ad..cdd568f 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -108,6 +108,28 @@ extern int fd_bootchk;
void pc_register_ferr_irq(qemu_irq irq);
+void pc_cpus_init(const char *cpu_model);
+void pc_memory_init(ram_addr_t ram_size,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ ram_addr_t *below_4g_mem_size_p,
+ ram_addr_t *above_4g_mem_size_p);
+qemu_irq *pc_allocte_cpu_irq(void);
+void pc_vga_init(PCIBus *pci_bus);
+struct fdctrl_t;
+void pc_basic_device_init(qemu_irq *i8259,
+ struct fdctrl_t **floppy_controller,
+ RTCState **rtc_state);
+void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic);
+#ifdef HAS_AUDIO
+void audio_init (PCIBus *pci_bus, qemu_irq *pic);
+#endif
+void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+ const char *boot_device, BlockDriverState **hd_table,
+ struct fdctrl_t *floppy_controller, RTCState *s);
+void pc_pci_device_init(PCIBus *pci_bus);
+
void ioport_set_a20(int enable);
int ioport_get_a20(void);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
new file mode 100644
index 0000000..59941f5
--- /dev/null
+++ b/hw/pc_piix.c
@@ -0,0 +1,210 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "pc.h"
+#include "fdc.h"
+#include "pci.h"
+#include "block.h"
+#include "sysemu.h"
+#include "audio/audio.h"
+#include "net.h"
+#include "smbus.h"
+#include "boards.h"
+#include "monitor.h"
+#include "fw_cfg.h"
+#include "hpet_emul.h"
+#include "watchdog.h"
+#include "smbios.h"
+
+#define MAX_IDE_BUS 2
+
+static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
+static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
+static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
+
+/* PC hardware initialisation */
+static void pc_init1(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename,
+ int pci_enabled, const char *cpu_model)
+{
+ int i;
+ ram_addr_t below_4g_mem_size, above_4g_mem_size;
+ PCIBus *pci_bus;
+ static PCIDevice *i440fx_state;
+ int piix3_devfn = -1;
+ qemu_irq *cpu_irq;
+ qemu_irq *i8259;
+ int index;
+ BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+ fdctrl_t *floppy_controller;
+ RTCState *rtc_state;
+
+ pc_cpus_init(cpu_model);
+
+ vmport_init();
+
+ /* allocate ram and load rom/bios */
+ pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
+ &below_4g_mem_size, &above_4g_mem_size);
+
+ cpu_irq = pc_allocte_cpu_irq();
+ i8259 = i8259_init(cpu_irq[0]);
+ pc_register_ferr_irq(i8259[13]);
+
+ if (pci_enabled) {
+ pci_bus = i440fx_init(&i440fx_state, i8259);
+ piix3_devfn = piix3_init(pci_bus, -1);
+ } else {
+ pci_bus = NULL;
+ }
+
+ pc_vga_init(pci_enabled? pci_bus: NULL);
+
+ /* init basic PC hardware */
+ pc_basic_device_init(i8259, &floppy_controller, &rtc_state);
+
+ if (pci_enabled) {
+ IOAPICState *ioapic = ioapic_init();
+ pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
+ }
+
+ 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);
+ else
+ pci_nic_init(pci_bus, nd, -1, "ne2k_pci");
+ }
+
+ piix4_acpi_system_hot_add_init();
+
+ if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
+ fprintf(stderr, "qemu: too many IDE bus\n");
+ exit(1);
+ }
+
+ 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;
+ }
+
+ if (pci_enabled) {
+ pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
+ } else {
+ for(i = 0; i < MAX_IDE_BUS; i++) {
+ isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
+ hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+ }
+ }
+
+#ifdef HAS_AUDIO
+ audio_init(pci_enabled ? pci_bus : NULL, i8259);
+#endif
+
+ pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
+ floppy_controller, rtc_state);
+
+ if (pci_enabled && usb_enabled) {
+ usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
+ }
+
+ if (pci_enabled && acpi_enabled) {
+ uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
+ i2c_bus *smbus;
+
+ /* TODO: Populate SPD eeprom data. */
+ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[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_init(eeprom);
+ }
+ }
+
+ if (i440fx_state) {
+ i440fx_init_memory_mappings(i440fx_state);
+ }
+
+ if (pci_enabled) {
+ pc_pci_device_init(pci_bus);
+ }
+}
+
+static void pc_init_pci(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, 1, cpu_model);
+}
+
+static void pc_init_isa(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, 0, cpu_model);
+}
+
+static QEMUMachine pc_machine = {
+ .name = "pc",
+ .desc = "Standard PC",
+ .init = pc_init_pci,
+ .max_cpus = 255,
+ .is_default = 1,
+};
+
+static QEMUMachine isapc_machine = {
+ .name = "isapc",
+ .desc = "ISA-only PC",
+ .init = pc_init_isa,
+ .max_cpus = 1,
+};
+
+static void pc_machine_init(void)
+{
+ qemu_register_machine(&pc_machine);
+ qemu_register_machine(&isapc_machine);
+}
+
+machine_init(pc_machine_init);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [Qemu-devel] [PATCH] q35 chipset based pc. wip.
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
` (17 preceding siblings ...)
2009-06-18 10:57 ` [Qemu-devel] [PATCH 18/18] pc.c: split out piix specific part from pc.c into pc_piix.c Isaku Yamahata
@ 2009-06-18 11:00 ` Isaku Yamahata
18 siblings, 0 replies; 21+ messages in thread
From: Isaku Yamahata @ 2009-06-18 11:00 UTC (permalink / raw)
To: qemu-devel
This patch is under work in progres as it I haven't successed to boot yet.
This patch is sent out to show the intention of the series of patches.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
--
Makefile.target | 1
hw/acpi_ich9.c | 542 +++++++++++++++++++++++++++++++++++++++++++++++++++
hw/acpi_ich9.h | 53 +++++
hw/pc_q35.c | 199 ++++++++++++++++++
hw/pci.h | 60 +++++
hw/pci_ids.h | 25 ++
hw/q35.c | 587 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/q35.h | 213 ++++++++++++++++++++
hw/q35_smbus.c | 177 ++++++++++++++++
9 files changed, 1850 insertions(+), 7 deletions(-)
diff --git a/Makefile.target b/Makefile.target
index 4d0d01f..722c818 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -574,6 +574,7 @@ OBJS+= ide.o pckbd.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
OBJS+= pc_piix.o acpi_piix4.o pc_smbus.o pc_apm.o
+OBJS+= pc_q35.o q35.o q35_smbus.o acpi_ich9.o
OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
OBJS += device-hotplug.o pci-hotplug.o smbios.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
new file mode 100644
index 0000000..83642f8
--- /dev/null
+++ b/hw/acpi_ich9.c
@@ -0,0 +1,542 @@
+/*
+ * ACPI implementation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+/*
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This is based on acpi.c.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "acpi.h"
+
+#include "q35.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define ICH9_DEBUG(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
+#else
+#define ICH9_DEBUG(fmt, ...) do { } while (0)
+#endif
+
+/* XXX where does the constant, ACPI_DBG_IO_ADDR, come from */
+#define ACPI_DBG_IO_ADDR 0xb044
+static void acpi_dbg_writel(void *opaqe, uint32_t addr, uint32_t val)
+{
+ ICH9_DEBUG("%s: 0x%08x\n", __func__, val);
+}
+
+void acpi_dbg_init(void); /* XXX */
+void acpi_dbg_init(void)
+{
+ register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, NULL);
+}
+
+
+static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
+ uint32_t val);
+static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len);
+static void gpe_ioport_writeb(struct ich9_lpc_pm_regs *pm,
+ uint32_t addr, uint32_t val);
+static uint32_t gpe_ioport_readb(struct ich9_lpc_pm_regs *pm,
+ uint32_t addr);
+
+#define ACPI_ENABLE 0x2
+#define ACPI_DISABLE 0x3
+
+static struct ich9_lpc_pm_regs *pm_state;
+
+static uint32_t get_pmtmr(struct ich9_lpc_pm_regs *pm)
+{
+ uint32_t d;
+ d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, ticks_per_sec);
+ return d & 0xffffff;
+}
+
+static int get_pm1_sts(struct ich9_lpc_pm_regs *pm)
+{
+ int64_t d;
+ int pm1_sts;
+ pm1_sts = pm->pm1_sts;
+ d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, ticks_per_sec);
+ if (d >= pm->tmr_overflow_time)
+ pm->pm1_sts |= ACPI_BITMASK_TIMER_STATUS;
+ return pm->pm1_sts;
+}
+
+static void pm_update_sci(struct ich9_lpc_pm_regs *pm)
+{
+ int sci_level, pm1_sts;
+ int64_t expire_time;
+
+ pm1_sts = get_pm1_sts(pm);
+ sci_level = (((pm1_sts & pm->pm1_en) &
+ (ACPI_BITMASK_RT_CLOCK_ENABLE |
+ ACPI_BITMASK_POWER_BUTTON_ENABLE |
+ ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
+ ACPI_BITMASK_TIMER_ENABLE)) != 0);
+ qemu_set_irq(pm->irq, sci_level);
+ /* schedule a timer interruption if needed */
+ if ((pm->pm1_en & ACPI_BITMASK_TIMER_ENABLE) &&
+ !(pm1_sts & ACPI_BITMASK_TIMER_STATUS)) {
+ expire_time = muldiv64(pm->tmr_overflow_time, ticks_per_sec,
+ PM_TIMER_FREQUENCY);
+ qemu_mod_timer(pm->tmr_timer, expire_time);
+ } else {
+ qemu_del_timer(pm->tmr_timer);
+ }
+}
+
+static void pm_tmr_timer(void *opaque)
+{
+ struct ich9_lpc_pm_regs *pm = opaque;
+ pm_update_sci(pm);
+}
+
+static void pm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ struct ich9_lpc_pm_regs *pm = opaque;
+
+ addr &= ICH9_PMIO_MASK;
+ switch (addr) {
+ case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + 7):
+ case ICH9_PMIO_GPE0_EN ... (ICH9_PMIO_GPE0_EN + 7):
+ gpe_ioport_writeb(pm, addr, val);
+ break;
+ default:
+ break;
+ }
+
+ ICH9_DEBUG("%s port=0x%04x val=0x%04x\n", __func__, addr, val);
+
+}
+
+static uint32_t pm_ioport_readb(void *opaque, uint32_t addr)
+{
+ struct ich9_lpc_pm_regs *pm = opaque;
+ uint32_t val = 0;
+
+ addr &= ICH9_PMIO_MASK;
+ switch(addr) {
+ case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + 7):
+ case ICH9_PMIO_GPE0_EN ... (ICH9_PMIO_GPE0_EN + 7):
+ val = gpe_ioport_readb(pm, addr);
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ ICH9_DEBUG("%s port=0x%04x val=0x%04x\n", __func__, addr, val);
+ return val;
+}
+
+static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+ struct ich9_lpc_pm_regs *pm = opaque;
+
+ addr &= ICH9_PMIO_MASK;
+ switch(addr) {
+ case ICH9_PMIO_PM1_STS:
+ {
+ int64_t d;
+ int pm1_sts;
+ pm1_sts = get_pm1_sts(pm);
+ if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
+ /* if TMRSTS is reset, then compute the new overflow time */
+ d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+ ticks_per_sec);
+ pm->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+ }
+ pm->pm1_sts &= ~val;
+ pm_update_sci(pm);
+ }
+ break;
+ case ICH9_PMIO_PM1_EN:
+ pm->pm1_en = val;
+ pm_update_sci(pm);
+ break;
+ case ICH9_PMIO_PM1_CNT:
+ {
+ int sus_typ;
+ pm->pm1_cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
+ if (val & ACPI_BITMASK_SLEEP_ENABLE) {
+ /* change suspend type */
+ sus_typ = (val >> 10) & 7;
+ switch(sus_typ) {
+ case 0: /* soft power off */
+ qemu_system_shutdown_request();
+ break;
+ case 1:
+ /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
+ Pretend that resume was caused by power button */
+ pm->pm1_sts |= (ACPI_BITMASK_WAKE_STATUS |
+ ACPI_BITMASK_POWER_BUTTON_STATUS);
+ qemu_system_reset_request();
+#if defined(TARGET_I386)
+ cmos_set_s3_resume();
+#endif
+ default:
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ pm_ioport_write_fallback(opaque, addr, 2, val);
+ break;
+ }
+ ICH9_DEBUG("%s port=0x%04x val=0x%04x\n", __func__, addr, val);
+}
+
+static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
+{
+ struct ich9_lpc_pm_regs *pm = opaque;
+ uint32_t val;
+
+ addr &= ICH9_PMIO_MASK;
+ switch(addr) {
+ case ICH9_PMIO_PM1_STS:
+ val = get_pm1_sts(pm);
+ break;
+ case ICH9_PMIO_PM1_EN:
+ val = pm->pm1_en;
+ break;
+ case ICH9_PMIO_PM1_CNT:
+ val = pm->pm1_cnt;
+ break;
+ default:
+ val = pm_ioport_read_fallback(opaque, addr, 2);
+ break;
+ }
+ ICH9_DEBUG("%s port=0x%04x val=0x%04x\n", __func__, addr, val);
+ return val;
+}
+
+static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+ // struct ich9_lpc_pm_regs *pm = opaque;
+
+ addr &= ICH9_PMIO_MASK;
+ switch(addr) {
+ default:
+ pm_ioport_write_fallback(opaque, addr, 4, val);
+ break;
+ }
+ ICH9_DEBUG("%s port=0x%04x val=0x%08x\n", __func__, addr, val);
+}
+
+static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
+{
+ struct ich9_lpc_pm_regs *pm = opaque;
+ uint32_t val;
+
+ addr &= ICH9_PMIO_MASK;
+ switch(addr) {
+ case ICH9_PMIO_PM1_TMR:
+ val = get_pmtmr(pm);
+ break;
+
+ default:
+ val = pm_ioport_read_fallback(opaque, addr, 4);
+ break;
+ }
+ ICH9_DEBUG("%s port=0x%04x val=0x%08x\n", __func__, addr, val);
+ return val;
+}
+
+static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
+ uint32_t val)
+{
+ int subsize = (len == 4)? 2: 1;
+ IOPortWriteFunc *ioport_write =
+ (subsize == 2)? pm_ioport_writew: pm_ioport_writeb;
+
+ int i;
+
+ for (i = 0; i < len; i += subsize) {
+ ioport_write(opaque, addr, val);
+ val >>= 8 * subsize;
+ }
+}
+
+static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len)
+{
+ int subsize = (len == 4)? 2: 1;
+ IOPortReadFunc *ioport_read =
+ (subsize == 2)? pm_ioport_readw: pm_ioport_readb;
+
+ uint32_t val;
+ int i;
+
+ val = 0;
+ for (i = 0; i < len; i += subsize) {
+ val <<= 8 * subsize;
+ val |= ioport_read(opaque, addr);
+ }
+
+ return val;
+}
+
+void ich9_pm_iospace_update(struct ich9_lpc_pm_regs *pm, uint32_t pm_io_base)
+{
+ /* XXX: need to improve memory and ioport allocation */
+ ICH9_DEBUG("%s to 0x%x\n", __func__, pm_io_base);
+
+ assert((pm_io_base & ~ICH9_PMIO_MASK) == 0);
+
+ if (pm->pm_io_base != 0)
+ isa_unassign_ioport(pm->pm_io_base, ICH9_PMIO_SIZE);
+
+ /* XXX: tmp hack */
+ if (pm_io_base == 0)
+ return;
+
+ register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_writeb, pm);
+ register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_readb, pm);
+ register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_writew, pm);
+ register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_readw, pm);
+ register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_writel, pm);
+ register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_readl, pm);
+
+ pm->pm_io_base = pm_io_base;
+}
+
+void ich9_pm_save(QEMUFile* f, struct ich9_lpc_pm_regs *pm)
+{
+ qemu_put_be16s(f, &pm->pm1_sts);
+ qemu_put_be16s(f, &pm->pm1_en);
+ qemu_put_be16s(f, &pm->pm1_cnt);
+ qemu_put_timer(f, pm->tmr_timer);
+ qemu_put_be64(f, pm->tmr_overflow_time);
+ qemu_put_be64s(f, &pm->gpe0_sts);
+ qemu_put_be64s(f, &pm->gpe0_en);
+ qemu_put_be32s(f, &pm->smi_en);
+ qemu_put_be32s(f, &pm->smi_sts);
+}
+
+void ich9_pm_load(QEMUFile* f, struct ich9_lpc_pm_regs *pm, int version_id)
+{
+ qemu_get_be16s(f, &pm->pm1_sts);
+ qemu_get_be16s(f, &pm->pm1_en);
+ qemu_get_be16s(f, &pm->pm1_cnt);
+ qemu_get_timer(f, pm->tmr_timer);
+ pm->tmr_overflow_time = qemu_get_be64(f);
+ qemu_get_be64s(f, &pm->gpe0_sts);
+ qemu_get_be64s(f, &pm->gpe0_en);
+ qemu_get_be32s(f, &pm->smi_en);
+ qemu_get_be32s(f, &pm->smi_sts);
+}
+
+static void pm_reset(void *opaque)
+{
+ //struct ich9_lpc_pm_regs *pm = opaque;
+ /* XXX:TODO */
+}
+
+#if defined(TARGET_I386)
+static void pm_powerdown(void *arg)
+{
+ struct ich9_lpc_pm_regs *pm = (struct ich9_lpc_pm_regs*) arg;
+
+ if (pm->pm1_en & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
+ pm->pm1_sts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
+ pm_update_sci(pm);
+ }
+}
+#endif
+
+void ich9_pm_init(struct ich9_lpc_pm_regs *pm, qemu_irq sci_irq)
+{
+ pm->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, pm);
+
+ pm->irq = sci_irq;
+ qemu_register_reset(pm_reset, 0, pm);
+ qemu_system_powerdown_register(pm_powerdown, pm_state);
+}
+
+/* GPE */
+static uint8_t *gpe_ioport_get_ptr(struct ich9_lpc_pm_regs *pm, uint32_t addr)
+{
+ uint8_t *cur = NULL;
+
+ switch (addr) {
+ case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + 7):
+ cur = (uint8_t*)&pm->gpe0_sts;
+ cur += addr - ICH9_PMIO_GPE0_STS;
+ break;
+ case ICH9_PMIO_GPE0_EN ... (ICH9_PMIO_GPE0_EN + 7):
+ cur = (uint8_t*)&pm->gpe0_en;
+ cur += addr - ICH9_PMIO_GPE0_EN;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ return cur;
+}
+
+static void gpe_ioport_writeb(struct ich9_lpc_pm_regs *pm,
+ uint32_t addr, uint32_t val)
+{
+ uint8_t *cur = gpe_ioport_get_ptr(pm, addr);
+
+ val &= 0xff;
+ switch (addr) {
+ case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + 7):
+ *cur = (*cur) & ~val;
+ break;
+ case ICH9_PMIO_GPE0_EN ... (ICH9_PMIO_GPE0_EN + 7):
+ *cur = val;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ ICH9_DEBUG("%s %x <== %d\n", __func__, addr, val);
+}
+
+static uint32_t gpe_ioport_readb(struct ich9_lpc_pm_regs *pm,
+ uint32_t addr)
+{
+ uint8_t *cur = gpe_ioport_get_ptr(pm, addr);
+ uint32_t val = 0;
+
+ if (cur != NULL)
+ val = *cur;
+
+ ICH9_DEBUG("%s %x == %x\n", __func__, addr, val);
+ return val;
+}
+
+#if 0
+/* XXX TODO */
+#define PCI_BASE 0xae00
+#define PCI_EJ_BASE 0xae08
+
+struct pci_status {
+ uint32_t up;
+ uint32_t down;
+};
+
+static struct pci_status pci0_status;
+
+
+static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
+{
+ uint32_t val = 0;
+ struct pci_status *g = opaque;
+ switch (addr) {
+ case PCI_BASE:
+ val = g->up;
+ break;
+ case PCI_BASE + 4:
+ val = g->down;
+ break;
+ default:
+ break;
+ }
+
+ ICH9_DEBUG("%s %x == %x\n", __func__, addr, val);
+ return val;
+}
+
+static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ struct pci_status *g = opaque;
+ switch (addr) {
+ case PCI_BASE:
+ g->up = val;
+ break;
+ case PCI_BASE + 4:
+ g->down = val;
+ break;
+ }
+
+ ICH9_DEBUG("%s %x <== %d\n", __func__, addr, val);
+}
+
+static uint32_t pciej_read(void *opaque, uint32_t addr)
+{
+ ICH9_DEBUG("%s %x\n", __func__, addr);
+ return 0;
+}
+
+static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
+{
+#if defined (TARGET_I386)
+ int slot = ffs(val) - 1;
+
+ pci_device_hot_remove_success(0, slot);
+#endif
+
+ ICH9_DEBUG("%s %x <== %d\n", __func__, addr, val);
+}
+
+
+void ich9_hot_add_init(void)
+{
+ register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
+ register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, &pci0_status);
+
+ register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL);
+ register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, NULL);
+}
+
+static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+{
+ g->sts |= 2;
+ p->up |= (1 << slot);
+}
+
+static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+{
+ g->sts |= 2;
+ p->down |= (1 << slot);
+}
+
+void qemu_system_device_hot_add(int bus, int slot, int state)
+{
+ pci0_status.up = 0;
+ pci0_status.down = 0;
+ if (state)
+ enable_device(&pci0_status, &gpe, slot);
+ else
+ disable_device(&pci0_status, &gpe, slot);
+ if (gpe.en & 2) {
+ qemu_set_irq(pm_state->irq, 1);
+ qemu_set_irq(pm_state->irq, 0);
+ }
+}
+#else
+static void ich9_device_hot_add(int bus, int slot, int state)
+{
+ /* stub */
+}
+
+void ich9_hot_add_init(void)
+{
+ /* stub */
+
+ qemu_system_device_hot_add_register(ich9_device_hot_add);
+}
+#endif
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
new file mode 100644
index 0000000..57a4bfe
--- /dev/null
+++ b/hw/acpi_ich9.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU GMCH/ICH9 LPC PM Emulation
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#ifndef HW_ACPI_ICH9_H
+#define HW_ACPI_ICH9_H
+
+#include <stdint.h>
+
+struct ich9_lpc_pm_regs {
+ uint16_t pm1_sts;
+ uint16_t pm1_en;
+
+ /*
+ * In ich9 spec says that pm1_cnt register is 32bit width and
+ * that the upper 16bits are reserved and unused.
+ * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t.
+ */
+ uint16_t pm1_cnt;
+
+ /* uint32_t pm1_tmr; */
+ QEMUTimer *tmr_timer;
+ int64_t tmr_overflow_time;
+
+ uint64_t gpe0_sts;
+ uint64_t gpe0_en;
+
+ uint32_t smi_en;
+ uint32_t smi_sts;
+
+ qemu_irq irq; /* SCI */
+
+ uint32_t pm_io_base;
+};
+
+#endif /* HW_ACPI_ICH9_H */
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
new file mode 100644
index 0000000..ae539e1
--- /dev/null
+++ b/hw/pc_q35.c
@@ -0,0 +1,199 @@
+/*
+ * Q35 chipset based pc system emulator
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This is based on pc.c, but heavily modified.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "fdc.h"
+#include "pci.h"
+#include "block.h"
+#include "sysemu.h"
+#include "audio/audio.h"
+#include "net.h"
+#include "smbus.h"
+#include "boards.h"
+#include "monitor.h"
+#include "fw_cfg.h"
+#include "hpet_emul.h"
+#include "watchdog.h"
+#include "smbios.h"
+
+#include "q35.h"
+
+#define MAX_IDE_BUS 2
+
+static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
+static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
+static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
+
+/* PC hardware initialisation */
+static void pc_q35_init(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)
+{
+ int i;
+ ram_addr_t below_4g_mem_size, above_4g_mem_size;
+ PCIBus *host_bus;
+ PCIBus *pci_bus;
+ static PCIDevice *gmch_state;
+ int ich9_lpc_devfn = -1;
+ qemu_irq *cpu_irq;
+ qemu_irq *i8259;
+ int index;
+ BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+ IOAPICState *ioapic;
+ fdctrl_t *floppy_controller;
+ RTCState *rtc_state;
+
+ pc_cpus_init(cpu_model);
+
+ vmport_init();
+
+ /* allocate ram and load rom/bios */
+ pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
+ &below_4g_mem_size, &above_4g_mem_size);
+
+
+ cpu_irq = pc_allocte_cpu_irq();
+ i8259 = i8259_init(cpu_irq[0]);
+ pc_register_ferr_irq(i8259[13]);
+
+ host_bus = gmch_init(&gmch_state, i8259);
+ ich9_lpc_devfn = ich9_lpc_init(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
+ ICH9_LPC_FUNC), i8259);
+ pci_bus = ich9_d2pbr_init(host_bus, PCI_DEVFN(ICH9_D2P_BRIDGE_DEV,
+ ICH9_D2P_BRIDGE_FUNC),
+ ICH9_D2P_SECONDARY_DEFAULT);
+
+ pc_vga_init(pci_bus);
+
+ /* init basic PC hardware */
+ pc_basic_device_init(i8259, &floppy_controller, &rtc_state);
+
+ ioapic = ioapic_init();
+ pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
+
+#if 0
+ if (pci_device_init() < 0) {
+ exit(1);
+ }
+#endif
+
+ watchdog_pc_init(pci_bus);
+
+ for(i = 0; i < nb_nics; i++) {
+ NICInfo *nd = &nd_table[i];
+
+ pci_nic_init(pci_bus, nd, -1, "ne2k_pci");
+ }
+
+ ich9_hot_add_init(); /* XXX */
+
+ if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
+ fprintf(stderr, "qemu: too many IDE bus\n");
+ exit(1);
+ }
+
+ 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;
+ }
+
+ /* XXX ich9 supports only SATA */
+ pci_piix3_ide_init(host_bus, hd, -1, i8259);
+
+#ifdef HAS_AUDIO
+ audio_init(pci_bus, i8259);
+#endif
+
+ pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
+ floppy_controller, rtc_state);
+
+ if (usb_enabled) {
+ /* XXX: make ich9 specific add usb_uchi_ich9_init() */
+ usb_uhci_piix4_init(host_bus, -1);
+ }
+
+ if (acpi_enabled) {
+ uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
+ i2c_bus *smbus;
+
+ /* TODO: Populate SPD eeprom data. */
+ /* XXX determine proper smb_io_base */
+ smbus = ich9_smb_init(pci_bus, ich9_lpc_devfn + 3, 0xb100);
+ 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_init(eeprom);
+ }
+ }
+
+ if (gmch_state) {
+ gmch_init_memory_mappings(gmch_state);
+ }
+
+ pc_pci_device_init(pci_bus);
+}
+
+static QEMUMachine pc_q35_machine = {
+ .name = "pc_q35",
+ .desc = "Q35 chipset PC",
+ .init = pc_q35_init,
+ .max_cpus = 255,
+};
+
+static void pc_q35_machine_init(void)
+{
+ qemu_register_machine(&pc_q35_machine);
+}
+
+machine_init(pc_q35_machine_init);
diff --git a/hw/pci.h b/hw/pci.h
index c14ab0f..6c6ddc3 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -161,11 +161,21 @@ typedef struct PCIIORegion {
/* Bits in the PCI Status Register (PCI 2.3 spec) */
#define PCI_STATUS_RESERVED1 0x007
#define PCI_STATUS_INT_STATUS 0x008
-#define PCI_STATUS_CAPABILITIES 0x010
-#define PCI_STATUS_66MHZ 0x020
-#define PCI_STATUS_RESERVED2 0x040
-#define PCI_STATUS_FAST_BACK 0x080
+#define PCI_STATUS_CAPABILITIES 0x10 /* Support Capability List */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
#define PCI_STATUS_DEVSEL 0x600
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
#define PCI_STATUS_RESERVED_MASK_LO (PCI_STATUS_RESERVED1 | \
PCI_STATUS_INT_STATUS | PCI_STATUS_CAPABILITIES | \
@@ -347,22 +357,58 @@ int pci_assign_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp);
void pci_info(Monitor *mon);
+static inline uint8_t
+pci_config_get8(uint8_t *pci_config, uint32_t addr)
+{
+ return pci_config[addr];
+}
+
+static inline uint16_t
+pci_config_get16(uint8_t *pci_config, uint32_t addr)
+{
+ return le16_to_cpup((uint16_t *)&pci_config[addr]);
+}
+
+static inline uint32_t
+pci_config_get32(uint8_t *pci_config, uint32_t addr)
+{
+ return le32_to_cpup((uint32_t *)&pci_config[addr]);
+}
+
+static inline void
+pci_config_set8(uint8_t *pci_config, uint32_t addr, uint8_t val)
+{
+ pci_config[addr] = val;
+}
+
+static inline void
+pci_config_set16(uint8_t *pci_config, uint32_t addr, uint16_t val)
+{
+ cpu_to_le16wu((uint16_t *)&pci_config[addr], val);
+}
+
+static inline void
+pci_config_set32(uint8_t *pci_config, uint32_t addr, uint32_t val)
+{
+ cpu_to_le32wu((uint32_t *)&pci_config[addr], val);
+}
+
static inline void
pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
{
- cpu_to_le16wu((uint16_t *)&pci_config[PCI_VENDOR_ID], val);
+ pci_config_set16(pci_config, PCI_VENDOR_ID, val);
}
static inline void
pci_config_set_device_id(uint8_t *pci_config, uint16_t val)
{
- cpu_to_le16wu((uint16_t *)&pci_config[PCI_DEVICE_ID], val);
+ pci_config_set16(pci_config, PCI_DEVICE_ID, val);
}
static inline void
pci_config_set_class(uint8_t *pci_config, uint16_t val)
{
- cpu_to_le16wu((uint16_t *)&pci_config[PCI_CLASS_DEVICE], val);
+ pci_config_set16(pci_config, PCI_CLASS_DEVICE, val);
}
typedef void (*pci_qdev_initfn)(PCIDevice *dev);
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index f7d0387..4eb6d07 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -33,6 +33,7 @@
#define PCI_CLASS_BRIDGE_HOST 0x0600
#define PCI_CLASS_BRIDGE_ISA 0x0601
#define PCI_CLASS_BRIDGE_PCI 0x0604
+#define PCI_CLASS_BRDIGE_PCI_INF_SUB 0x01
#define PCI_CLASS_BRIDGE_OTHER 0x0680
#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
@@ -40,6 +41,18 @@
#define PCI_CLASS_PROCESSOR_CO 0x0b40
#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
+#define PCI_CLASS_SERIAL_FIREWIRE_OHCI 0x0c0010
+#define PCI_CLASS_SERIAL_ACCESS 0x0c01
+#define PCI_CLASS_SERIAL_SSA 0x0c02
+#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_USB_UHCI 0x0c0300
+#define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310
+#define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320
+#define PCI_CLASS_SERIAL_FIBER 0x0c04
+#define PCI_CLASS_SERIAL_SMBUS 0x0c05
+
#define PCI_CLASS_OTHERS 0xff
/* Vendors and devices. Sort key: vendor first, device next. */
@@ -97,4 +110,16 @@
#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
+#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
+#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
+#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912
+#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913
+#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914
+#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919
+#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930
+#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916
+#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918
+
+#define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0
+
#define PCI_VENDOR_ID_INVALID 0xffff
diff --git a/hw/q35.c b/hw/q35.c
new file mode 100644
index 0000000..beea981
--- /dev/null
+++ b/hw/q35.c
@@ -0,0 +1,587 @@
+/*
+ * QEMU GMCH/ICH9 PCI Bridge Emulation
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This is based on piix_pci.c, but heavily modified.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+/*
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "pc.h"
+#include "pc_apm.h"
+#include "pci.h"
+#include "q35.h"
+
+typedef uint32_t pci_addr_t;
+#include "pci_host.h"
+
+typedef struct GMCHState {
+ PCIHostState host;
+
+ struct PCIDevice *dev;
+} GMCHState;
+
+struct GMCH_PCIDevice {
+ PCIDevice d;
+ GMCHState *gmch;
+
+ target_phys_addr_t isa_page_descs[384 / 4];
+ uint8_t smm_enabled;
+};
+
+static void gmch_addr_writel(void* opaque, uint32_t addr, uint32_t val)
+{
+ GMCHState *s = opaque;
+ s->host.config_reg = val;
+}
+
+static uint32_t gmch_addr_readl(void* opaque, uint32_t addr)
+{
+ GMCHState *s = opaque;
+ return s->host.config_reg;
+}
+
+static void ich9_lpc_set_irq(qemu_irq *pic, int irq_num, int level);
+
+/* return the global irq number corresponding to a given device irq
+ pin. We could also use the bus number to have a more precise
+ mapping. */
+static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+ int slot_addend;
+ slot_addend = (pci_dev->devfn >> 3) - 1;
+ return (irq_num + slot_addend) & 3;
+}
+
+static target_phys_addr_t isa_page_descs[384 / 4];
+
+static target_phys_addr_t isa_page_descs_get(uint32_t addr)
+{
+ return isa_page_descs[
+ (addr - Q35_HOST_BRIDGE_SMARM_C_BASE) >> TARGET_PAGE_BITS];
+}
+
+static void update_pam(PCIDevice *d, uint32_t start, uint8_t r)
+{
+ uint32_t addr;
+
+ // printf("ISA mapping %08x-0x%08x: %d\n", start, end, r);
+ switch(r) {
+ case Q35_HOST_BRIDGE_PAM_WE | Q35_HOST_BRIDGE_PAM_RE:
+ /* RAM */
+ cpu_register_physical_memory(start, Q35_HOST_BRIDGE_PAM_AREA_SIZE,
+ start);
+ break;
+
+ case Q35_HOST_BRIDGE_PAM_RE:
+ /* ROM (XXX: not quite correct) */
+ cpu_register_physical_memory(start, Q35_HOST_BRIDGE_PAM_AREA_SIZE,
+ start | IO_MEM_ROM);
+ break;
+
+ case Q35_HOST_BRIDGE_PAM_WE:
+ case 0:
+ /* XXX: should distinguish read/write cases */
+ for(addr = start; addr < start + Q35_HOST_BRIDGE_PAM_AREA_SIZE;
+ addr += TARGET_PAGE_SIZE) {
+ cpu_register_physical_memory(addr, TARGET_PAGE_SIZE,
+ isa_page_descs_get(addr));
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static uint8_t gmch_get_pam_attr(PCIDevice *d, uint32_t addr, int hi)
+{
+ return (d->config[addr] >> ((!!hi) * 4)) & Q35_HOST_BRIDGE_PAM_MASK;
+}
+
+static void gmch_update_pam(PCIDevice *d, int pam)
+{
+ uint32_t conf_addr = Q35_HOST_BRIDGE_PAM0 + pam;
+ uint32_t phys_addr;
+
+ assert(0 <= pam && pam <= 6);
+
+ if (pam == 0) {
+ update_pam(d, Q35_HOST_BRIDGE_PAM_BIOS_AREA,
+ gmch_get_pam_attr(d, conf_addr, 1));
+ return;
+ }
+
+ phys_addr = Q35_HOST_BRIDGE_PAM_EXPAN_AREA +
+ Q35_HOST_BRIDGE_PAM_EXPAN_AREA * (pam - 1) * 2;
+ update_pam(d, phys_addr, gmch_get_pam_attr(d, conf_addr, 0));
+
+ phys_addr += Q35_HOST_BRIDGE_PAM_AREA_SIZE;
+ update_pam(d, phys_addr, gmch_get_pam_attr(d, conf_addr, 1));
+}
+
+static void gmch_update_memory_mappings(PCIDevice *d)
+{
+ int i;
+
+ for (i = 0; i < 7; i++)
+ gmch_update_pam(d, i);
+}
+
+static void gmch_update_smram(PCIDevice *d)
+{
+ struct GMCH_PCIDevice *gd = (struct GMCH_PCIDevice*)d;
+ uint32_t smram;
+ uint32_t addr;
+
+ smram = d->config[Q35_HOST_BRDIGE_SMRAM];
+ if ((gd->smm_enabled && (smram & Q35_HOST_BRIDGE_SMRAM_G_SMRAME)) ||
+ (smram & Q35_HOST_BRIDGE_SMRAM_D_OPEN)) {
+ cpu_register_physical_memory(Q35_HOST_BRIDGE_SMARM_C_BASE,
+ Q35_HOST_BRIDGE_SMRAM_C_SIZE,
+ Q35_HOST_BRIDGE_SMARM_C_BASE);
+ } else {
+ for(addr = Q35_HOST_BRIDGE_SMARM_C_BASE;
+ addr < Q35_HOST_BRIDGE_SMRAM_C_END;
+ addr += TARGET_PAGE_SIZE) {
+ cpu_register_physical_memory(addr, TARGET_PAGE_SIZE,
+ isa_page_descs_get(addr));
+ }
+ }
+}
+
+static void gmch_set_smm(int smm, void *arg)
+{
+ uint8_t val = (smm != 0);
+ struct GMCH_PCIDevice *gd = (struct GMCH_PCIDevice*)arg;
+
+ if (gd->smm_enabled != val) {
+ gd->smm_enabled = val;
+ gmch_update_smram(&gd->d);
+ }
+}
+
+/* XXX: suppress when better memory API. We make the assumption that
+ no device (in particular the VGA) changes the memory mappings in
+ the 0xa0000-0x100000 =
+ [Q35_HOST_BRIDGE_SMARM_C_BASE, Q35_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END)
+ range */
+void gmch_init_memory_mappings(PCIDevice *d)
+{
+ int i;
+ for(i = 0; i < 96; i++) {
+ isa_page_descs[i] = cpu_get_physical_page_desc(Q35_HOST_BRIDGE_SMARM_C_BASE + i * 0x1000);
+ }
+}
+
+static void gmch_write_config(PCIDevice *d,
+ uint32_t address, uint32_t val, int len)
+{
+ /* XXX: implement SMRAM.D_LOCK */
+ pci_default_write_config(d, address, val, len);
+ if ((address >= 0x59 && address <= 0x5f))
+ gmch_update_memory_mappings(d);
+
+ if (address <= Q35_HOST_BRDIGE_SMRAM &&
+ Q35_HOST_BRDIGE_SMRAM <= address + len)
+ gmch_update_smram(d);
+}
+
+static void gmch_save(QEMUFile* f, void *opaque)
+{
+ struct GMCH_PCIDevice *gd = opaque;
+
+ pci_device_save(&gd->d, f);
+ qemu_put_8s(f, &gd->smm_enabled);
+}
+
+static int gmch_load(QEMUFile* f, void *opaque, int version_id)
+{
+ struct GMCH_PCIDevice *gd = opaque;
+ int ret;
+
+ if (version_id > 2)
+ return -EINVAL;
+
+ ret = pci_device_load(&gd->d, f);
+ if (ret < 0)
+ return ret;
+ gmch_update_memory_mappings(&gd->d);
+
+ qemu_get_8s(f, &gd->smm_enabled);
+ gmch_update_smram(&gd->d);
+
+ return 0;
+}
+
+/* host bridge */
+PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic)
+{
+ PCIBus *b;
+ PCIDevice *d;
+ struct GMCH_PCIDevice *gd;
+ GMCHState *s;
+
+ s = qemu_mallocz(sizeof(GMCHState));
+ b = pci_register_bus(NULL, "pci",
+ ich9_lpc_set_irq, pci_slot_get_pirq, pic, 0,
+ 8 /* PIRQ A-H */);
+ s->host.bus = b;
+
+ register_ioport_write(Q35_HOST_BRIDGE_CONFIG_ADDR,
+ 4, 4, gmch_addr_writel, s);
+ register_ioport_read(Q35_HOST_BRIDGE_CONFIG_ADDR,
+ 4, 4, gmch_addr_readl, s);
+
+ register_ioport_write(Q35_HOST_BRIDGE_CONFIG_DATA,
+ 4, 1, pci_host_data_writeb, s);
+ register_ioport_write(Q35_HOST_BRIDGE_CONFIG_DATA,
+ 4, 2, pci_host_data_writew, s);
+ register_ioport_write(Q35_HOST_BRIDGE_CONFIG_DATA,
+ 4, 4, pci_host_data_writel, s);
+ register_ioport_read(Q35_HOST_BRIDGE_CONFIG_DATA,
+ 4, 1, pci_host_data_readb, s);
+ register_ioport_read(Q35_HOST_BRIDGE_CONFIG_DATA,
+ 4, 2, pci_host_data_readw, s);
+ register_ioport_read(Q35_HOST_BRIDGE_CONFIG_DATA,
+ 4, 4, pci_host_data_readl, s);
+
+ d = pci_register_device(b, Q35_HOST_BRIDGE,
+ sizeof(struct GMCH_PCIDevice), 0,
+ NULL, gmch_write_config);
+ s->dev = d;
+ gd = (struct GMCH_PCIDevice*)d;
+ gd->gmch = s;
+
+ pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
+ pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_Q35_MCH);
+ d->config[PCI_REVISION_ID] = Q35_HOST_BRIDGE_REVISION_DEFUALT;
+ pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
+
+ d->config[Q35_HOST_BRDIGE_SMRAM] = Q35_HOST_BRIDGE_SMRAM_DEFAULT;
+
+ register_savevm(Q35_HOST_BRIDGE, 0, 2, gmch_save, gmch_load, gd);
+ cpu_smm_register(&gmch_set_smm, gd);
+
+ *pgmch_state = d;
+ return b;
+}
+
+/* ICH9 DMI-to-PCI bridge */
+static int ich9_d2pbr_map_irq_fn(PCIDevice *pci_dev, int irq_num)
+{
+ return irq_num;
+}
+
+static void ich9_d2pbr_reset(PCIDevice *d)
+{
+ uint8_t *pci_conf = d->config;
+
+ pci_config_set16(pci_conf, PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_config_set16(pci_conf, PCI_STATUS,
+ PCI_STATUS_DEVSEL_MEDIUM);
+}
+
+static void ich9_d2pbr_save(QEMUFile* f, void *opaque)
+{
+ PCIDevice *d = opaque;
+ pci_device_save(d, f);
+}
+
+static int ich9_d2pbr_load(QEMUFile* f, void *opaque, int version_id)
+{
+ PCIDevice *d = opaque;
+ if (version_id != 2)
+ return -EINVAL;
+ return pci_device_load(d, f);
+}
+
+PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int secondary_bus_num)
+{
+ PCIBus *b;
+ PCIDevice *d;
+ uint8_t *pci_conf;
+
+ b = pci_bridge_create_simple(bus, devfn,
+ PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_0,
+ ich9_d2pbr_map_irq_fn, ICH9_D2P_BRIDGE,
+ secondary_bus_num);
+ if (b == NULL)
+ return NULL;
+
+ d = pci_bus_to_dev(b);
+ register_savevm(ICH9_D2P_BRIDGE, 0, ICH9_D2P_BRIDGE_SAVEVM_VERSION,
+ ich9_d2pbr_save, ich9_d2pbr_load, d);
+
+ /* some command bits are hotwired to 0 for pcie */
+ pci_conf_initw(d, PCI_COMMAND, d->callback[PCI_COMMAND],
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER |
+ PCI_COMMAND_PARITY |
+ PCI_COMMAND_SERR);
+
+ pci_conf = d->config;
+
+ pci_config_set8(pci_conf, PCI_REVISION_ID, ICH9_D2P_A2_REVISION);
+
+ // XXX
+ pci_config_set8(pci_conf, PCI_CLASS_INTERFACE,
+ PCI_CLASS_BRDIGE_PCI_INF_SUB);
+ pci_config_set8(pci_conf, PCI_HEADER_TYPE, PCI_HEADER_TYPE_BRIDGE);
+
+ ich9_d2pbr_reset(d);
+ return b;
+}
+
+
+/* ICH9 LPC PCI to ISA bridge */
+struct ICH9_LPCDevice {
+ PCIDevice d;
+
+ int pci_irq_levels[ICH9_LPC_NB_PIRQS];
+
+ APMState apm;
+ struct ich9_lpc_pm_regs pm;
+};
+
+static struct ICH9_LPCDevice *ich9_pci_to_lpc(PCIDevice *d)
+{
+ return (struct ICH9_LPCDevice*)d;
+}
+
+static struct ICH9_LPCDevice *ich9_lpc;
+
+static void ich9_lpc_reset(struct ICH9_LPCDevice *lpc)
+{
+ uint8_t *pci_conf = lpc->d.config;
+ int i;
+
+ pci_config_set16(pci_conf, PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+ /* XXX capability isn't supported yet */
+ pci_config_set16(pci_conf, PCI_STATUS,
+ PCI_STATUS_DEVSEL_MEDIUM /* | PCI_STATUS_CAPABILITIES */);
+
+ for (i = 0; i < 4; i++) {
+ pci_config_set8(pci_conf, ICH9_LPC_PIRQA_ROUT + 1,
+ ICH9_LPC_PIRQ_ROUT_DEFAULT);
+ }
+ for (i = 0; i < 4; i++) {
+ pci_config_set8(pci_conf, ICH9_LPC_PIRQE_ROUT + 1,
+ ICH9_LPC_PIRQ_ROUT_DEFAULT);
+ }
+ pci_config_set32(pci_conf, ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_DEFAULT);
+ pci_config_set32(pci_conf, ICH9_LPC_RCBA, ICH9_LPC_RCBA_DEFAULT);
+}
+
+static int ich9_lpc_pic_irq(struct ICH9_LPCDevice *lpc, int irq_num)
+{
+ switch (irq_num) {
+ case 0 ... 3:
+ return lpc->d.config[ICH9_LPC_PIRQA_ROUT + irq_num];
+ case 4 ... 7:
+ return lpc->d.config[ICH9_LPC_PIRQE_ROUT + (irq_num - 4)];
+ default:
+ break;
+ }
+ assert(0);
+ return 0;
+}
+
+static void ich9_lpc_set_irq(qemu_irq *pic, int irq_num, int level)
+{
+ int i, pic_irq, pic_level;
+
+ assert(0 <= irq_num && irq_num < 8);
+ ich9_lpc->pci_irq_levels[irq_num] = level;
+
+ /* XXX: check ICH9_LPC_PIRQ_ROUT_IRQEN bit */
+
+ /* now we change the pic irq level according to the piix irq mappings */
+ /* XXX: optimize */
+ pic_irq = ich9_lpc_pic_irq(ich9_lpc, irq_num);
+
+ /* XXX: IRQ 16 - 23 */
+ if (pic_irq < 16) {
+ /* The pic level is the logical OR of all the PCI irqs mapped
+ to it */
+ pic_level = 0;
+ for (i = 0; i < ICH9_LPC_NB_PIRQS; i++) {
+ if (pic_irq == ich9_lpc_pic_irq(ich9_lpc, i)) {
+ pic_level |= ich9_lpc->pci_irq_levels[i];
+ }
+ }
+ qemu_set_irq(pic[pic_irq], pic_level);
+ }
+}
+
+/* APM */
+static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
+{
+#if 0
+ struct ICH9_LPCDevice *lpc = arg;
+
+ /* XXX: TODO */
+/* FADT ACPI_ENABLE/ACPI_DISABLE */
+#define ICH9_APM_ACPI_ENABLE 0x2
+#define ICH9_APM_ACPI_DISABLE 0x3
+
+ /* ACPI specs 3.0, 4.7.2.5 */
+ if (val == ACPI_ENABLE) {
+ lpc->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
+ } else if (val == ACPI_DISABLE) {
+ lpc->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
+ }
+#endif
+
+ /* XXX: TODO */
+ /* SMI_EN = PMBASE + 30
+ * SMI control and enable register
+ */
+#if 0
+ if ((SMI_EN register) & APMC_EN) {
+ cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
+ }
+#endif
+}
+
+/* config:PMBASE */
+static void
+ich9_lpc_pmbase_update(PCIDevice *d, uint32_t addr, uint32_t data, int len)
+{
+ uint32_t pm_io_base = pci_config_get32(d->config, ICH9_LPC_PMBASE);
+ pm_io_base &= ICH9_LPC_PMBASE_BASE_ADDRESS_MASK;
+
+ ich9_pm_iospace_update(&ich9_pci_to_lpc(d)->pm, pm_io_base);
+}
+
+static void ich9_lpc_save(QEMUFile* f, void *opaque)
+{
+ struct ICH9_LPCDevice *lpc = opaque;
+ int i;
+
+ pci_device_save(&lpc->d, f);
+
+ for (i = 0; i < ICH9_LPC_NB_PIRQS; i++)
+ qemu_put_be32(f, lpc->pci_irq_levels[i]);
+
+ ich9_pm_save(f, &lpc->pm);
+}
+
+static int ich9_lpc_load(QEMUFile* f, void *opaque, int version_id)
+{
+ struct ICH9_LPCDevice *lpc = opaque;
+ int ret, i;
+
+ ret = pci_device_load(&lpc->d, f);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ICH9_LPC_NB_PIRQS; i++)
+ lpc->pci_irq_levels[i] = qemu_get_be32(f);
+
+ ich9_pm_load(f, &lpc->pm, version_id);
+ ich9_lpc_pmbase_update(&lpc->d,
+ 0, 0, 0 /* don't care those args */);
+ return 0;
+}
+
+static void ich9_set_sci(void *opaque, int irq_num, int level)
+{
+ /* opaque = pic */
+ assert(irq_num == 0);
+ ich9_lpc_set_irq(opaque, 1/* SCI = PIRQB# */, level);
+}
+
+static qemu_irq *ich9_lpc_allocate_sci_irq(qemu_irq *pic)
+{
+ return qemu_allocate_irqs(ich9_set_sci, pic, 1);
+}
+
+int ich9_lpc_init(PCIBus *bus, int devfn, qemu_irq *pic)
+{
+ struct ICH9_LPCDevice *lpc;
+ uint8_t *pci_conf;
+ qemu_irq *sci_irq;
+
+ assert(devfn == PCI_DEVFN(ICH9_LPC_DEV, ICH9_LPC_FUNC));
+
+ lpc = (struct ICH9_LPCDevice*)pci_register_device(bus, ICH9_A2_LPC,
+ sizeof(*lpc), devfn,
+ NULL, NULL);
+ ich9_lpc = lpc;
+ pci_conf = lpc->d.config;
+
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ICH9_8); // ICH9 LPC
+ pci_config_set8(pci_conf, PCI_REVISION_ID, ICH9_A2_LPC_REVISION);
+ pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
+
+ // header_type = PCI_multifunction, generic
+ pci_config_set8(pci_conf, PCI_HEADER_TYPE,
+ PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION);
+
+ apm_init(&lpc->apm, ich9_apm_ctrl_changed, &lpc);
+
+ sci_irq = ich9_lpc_allocate_sci_irq(pic);
+ ich9_pm_init(&lpc->pm, sci_irq[0]);
+ pci_conf_initl(&lpc->d, ICH9_LPC_PMBASE, ich9_lpc_pmbase_update,
+ ICH9_LPC_PMBASE_DEFAULT);
+ pci_config_set32(lpc->d.config, ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_DEFAULT);
+
+ register_savevm(ICH9_A2_LPC, 0, ICH9_A2_LPC_SAVEVM_VERSION,
+ ich9_lpc_save, ich9_lpc_load, lpc);
+
+ ich9_lpc_reset(lpc);
+
+#if 0
+ /* XXX TODO */
+#define GPE_BASE_PIIX4 0xafe0
+#define ICH9_PMBASE_COMPAT ((GPE_BASE - ICH9_PMIO_GEP0_STS) | ICH9_LPC_PMBASE_RTE)
+ pci_config_set32(pci_conf,ICH9_PMBASE_COMPAT);
+ qemu_acpi_gpe_init(pci_conf[ICH9_LPC_PMBASE] + ICH9_PMIO_GEP0_STS)
+#endif
+ return 0;
+}
diff --git a/hw/q35.h b/hw/q35.h
new file mode 100644
index 0000000..998bcd6
--- /dev/null
+++ b/hw/q35.h
@@ -0,0 +1,213 @@
+/*
+ * q35.h
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef HW_Q35_H
+#define HW_Q35_H
+
+#include "acpi_ich9.h"
+
+void gmch_init_memory_mappings(PCIDevice *d);
+PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic);
+
+PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int secondary_bus_num);
+int ich9_lpc_init(PCIBus *bus, int devfn, qemu_irq *pic);
+
+i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
+
+void ich9_pm_init(struct ich9_lpc_pm_regs *pm, qemu_irq sci_irq);
+void ich9_pm_iospace_update(struct ich9_lpc_pm_regs *pm, uint32_t pm_io_base);
+void ich9_pm_save(QEMUFile* f, struct ich9_lpc_pm_regs *pm);
+void ich9_pm_load(QEMUFile* f, struct ich9_lpc_pm_regs *pm, int version_id);
+
+void ich9_hot_add_init(void);
+
+#define Q35_MASK(bit, ms_bit, ls_bit) ((((uint##bit##_t)1 << (ms_bit)) - 1) & ~(((uint##bit##_t)1 << ls_bit) - 1))
+
+/*
+ * gmch part
+ */
+
+/* PCI configuration */
+#define Q35_HOST_BRIDGE "GMCH"
+
+#define Q35_HOST_BRIDGE_CONFIG_ADDR 0xcf8
+#define Q35_HOST_BRIDGE_CONFIG_DATA 0xcfc
+
+/* D0:F0 configuration space */
+#define Q35_HOST_BRIDGE_REVISION_DEFUALT 0x0
+
+#define Q35_HOST_BRIDGE_PCIEXBAR 0x60 /* 64bit register */
+#define Q35_HOST_BRIDGE_PCIEXBAR_DEFAULT 0xe0000000
+#define Q35_HOST_BRIDGE_PCIEXBAR_ADMSK Q35_MASK(64, 35, 25) /* bit 35:28 */
+#define Q35_HOST_BRIDGE_PCIEXBAR_128ADMSK ((uint64_t)(1 << 26))
+#define Q35_HOST_BRIDGE_PCIEXBAR_64ADMSK ((uint64_t)(1 << 25))
+#define Q35_HOST_BRIDGE_PCIEXBAR_LENGTH ((uint64_t)(0x2 << 1))
+#define Q35_HOST_BRIDGE_PCIEXBAREN ((uint64_t)1)
+
+#define Q35_HOST_BRIDGE_PAM0 0x90
+#define Q35_HOST_BRIDGE_PAM_BIOS_AREA 0xf0000
+#define Q35_HOST_BRIDGE_PAM_AREA_SIZE 0x1000 /* 16KB */
+#define Q35_HOST_BRIDGE_PAM1 0x91
+#define Q35_HOST_BRIDGE_PAM_EXPAN_AREA 0xc0000
+#define Q35_HOST_BRIDGE_PAM2 0x92
+#define Q35_HOST_BRIDGE_PAM3 0x93
+#define Q35_HOST_BRIDGE_PAM4 0x94
+#define Q35_HOST_BRIDGE_PAM5 0x95
+#define Q35_HOST_BRIDGE_PAM_EXBIOS_AREA 0xe0000
+#define Q35_HOST_BRIDGE_PAM6 0x96
+#define Q35_HOST_BRIDGE_PAM_WE_HI ((uint8_t)(0x2 << 4))
+#define Q35_HOST_BRIDGE_PAM_RE_HI ((uint8_t)(0x1 << 4))
+#define Q35_HOST_BRIDGE_PAM_HI_MASK ((uint8_t)(0x3 << 4))
+#define Q35_HOST_BRIDGE_PAM_WE_LO ((uint8_t)0x2)
+#define Q35_HOST_BRIDGE_PAM_RE_LO ((uint8_t)0x1)
+#define Q35_HOST_BRIDGE_PAM_LO_MASK ((uint8_t)0x3)
+#define Q35_HOST_BRIDGE_PAM_WE ((uint8_t)0x2)
+#define Q35_HOST_BRIDGE_PAM_RE ((uint8_t)0x1)
+#define Q35_HOST_BRIDGE_PAM_MASK ((uint8_t)0x3)
+
+
+#define Q35_HOST_BRDIGE_SMRAM 0x9d
+#define Q35_HOST_BRIDGE_SMRAM_DEFAULT ((uint8_t)0x2)
+#define Q35_HOST_BRIDGE_SMRAM_D_OPEN ((uint8_t)(1 << 6))
+#define Q35_HOST_BRIDGE_SMRAM_D_CLS ((uint8_t)(1 << 5))
+#define Q35_HOST_BRIDGE_SMRAM_D_LCK ((uint8_t)(1 << 4))
+#define Q35_HOST_BRIDGE_SMRAM_G_SMRAME ((uint8_t)(1 << 3))
+#define Q35_HOST_BRIDGE_SMRAM_C_BASE_SEG_MASK ((uint8_t)0x7)
+#define Q35_HOST_BRIDGE_SMRAM_C_BASE_SEG ((uint8_t)0x2) /* hardwired to b010 */
+#define Q35_HOST_BRIDGE_SMARM_C_BASE 0xa0000
+#define Q35_HOST_BRIDGE_SMRAM_C_END 0xc0000
+#define Q35_HOST_BRIDGE_SMRAM_C_SIZE 0x20000
+#define Q35_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END 0x100000
+
+#define Q35_HOST_BRIDGE_ESMRAMC 0x9e
+#define Q35_HOST_BRDIGE_ESMRAMC_H_SMRAME ((uint8_t)(1 << 6))
+#define Q35_HOST_BRDIGE_ESMRAMC_E_SMERR ((uint8_t)(1 << 5))
+#define Q35_HOST_BRDIGE_ESMRAMC_SM_CACHE ((uint8_t)(1 << 4))
+#define Q35_HOST_BRDIGE_ESMRAMC_SM_L1 ((uint8_t)(1 << 3))
+#define Q35_HOST_BRDIGE_ESMRAMC_SM_L2 ((uint8_t)(1 << 2))
+#define Q35_HOST_BRDIGE_ESMRAMC_TSEG_SZ_MASK ((uint8_t)(0x3 << 1))
+#define Q35_HOST_BRDIGE_ESMRAMC_TSEG_SZ_1MB ((uint8_t)(0x0 << 1))
+#define Q35_HOST_BRDIGE_ESMRAMC_TSEG_SZ_2MB ((uint8_t)(0x1 << 1))
+#define Q35_HOST_BRDIGE_ESMRAMC_TSEG_SZ_8MB ((uint8_t)(0x2 << 1))
+#define Q35_HOST_BRDIGE_ESMRAMC_T_EN ((uint8_t)1)
+
+
+/*
+ * ich9 part
+ */
+
+/* D30:F0 DMI-to-PCI brdige */
+#define ICH9_D2P_BRIDGE "ICH9 D2P BRIDGE"
+#define ICH9_D2P_BRIDGE_SAVEVM_VERSION 0
+
+#define ICH9_D2P_BRIDGE_DEV 30
+#define ICH9_D2P_BRIDGE_FUNC 0
+
+/* 1 pcie port on gmch and 6 pcie port on ich9,
+ the next bus # is 7 */
+#define ICH9_D2P_SECONDARY_DEFAULT 7
+
+#define ICH9_D2P_A2_REVISION 0x92
+
+
+/* D30:F1 LPC controller */
+#define ICH9_A2_LPC "ICH9 A2 LPC"
+#define ICH9_A2_LPC_SAVEVM_VERSION 0
+
+#define ICH9_LPC_DEV 30
+#define ICH9_LPC_FUNC 1
+
+#define ICH9_A2_LPC_REVISION 0x2
+#define ICH9_LPC_NB_PIRQS 8 /* PCI A-H */
+
+#define ICH9_LPC_PMBASE 0x40
+#define ICH9_LPC_PMBASE_BASE_ADDRESS_MASK Q35_MASK(32, 15, 7)
+#define ICH9_LPC_PMBASE_RTE 0x1
+#define ICH9_LPC_PMBASE_DEFAULT 0x1
+#define ICH9_LPC_ACPI_CTRL 0x44
+#define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80
+#define ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK Q35_MASK(8, 2, 0)
+#define ICH9_LPC_ACPI_CTRL_DEFAULT 0x0
+
+#define ICH9_LPC_PIRQA_ROUT 0x60
+#define ICH9_LPC_PIRQB_ROUT 0x61
+#define ICH9_LPC_PIRQC_ROUT 0x62
+#define ICH9_LPC_PIRQD_ROUT 0x63
+
+#define ICH9_LPC_PIRQE_ROUT 0x68
+#define ICH9_LPC_PIRQF_ROUT 0x69
+#define ICH9_LPC_PIRQG_ROUT 0x6a
+#define ICH9_LPC_PIRQH_ROUT 0x6b
+
+#define ICH9_LPC_PIRQ_ROUT_IRQEN 0x80
+#define ICH9_LPC_PIRQ_ROUT_MASK Q35_MASK(8, 3, 0)
+#define ICH9_LPC_PIRQ_ROUT_DEFAULT 0x1
+
+#define ICH9_LPC_RCBA 0xf0
+#define ICH9_LPC_RCBA_BA_MASK Q35_MASK(32, 31, 14)
+#define ICH9_LPC_RCBA_EN 0x1
+#define ICH9_LPC_RCBA_DEFAULT 0x0
+
+/* D30:F1 power management I/O registers
+ offset from the address ICH9_LPC_PMBASE */
+
+/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */
+#define ICH9_PMIO_SIZE 128
+#define ICH9_PMIO_MASK (ICH9_PMIO_SIZE - 1)
+
+#define ICH9_PMIO_PM1_STS 0x00
+#define ICH9_PMIO_PM1_EN 0x02
+#define ICH9_PMIO_PM1_CNT 0x04
+#define ICH9_PMIO_PM1_TMR 0x08
+#define ICH9_PMIO_GPE0_STS 0x20
+#define ICH9_PMIO_GPE0_EN 0x28
+#define ICH9_PMIO_SMI_EN 0x30
+#define ICH9_PMIO_SMI_STS 0x34
+
+
+/* D30:F3 SMBus controller */
+#define ICH9_A2_SMB_REVISION 0x02
+#define ICH9_SMB_PI 0x00
+
+#define ICH9_SMB_SMBMBAR0 0x10
+#define ICH9_SMB_SMBMBAR1 0x14
+#define ICH9_SMB_SMBM_BAR 0
+#define ICH9_SMB_SMBM_SIZE (1 << 8)
+#define ICH9_SMB_SMB_BASE 0x20
+#define ICH9_SMB_SMB_BASE_BAR 4
+#define ICH9_SMB_SMB_BASE_SIZE (1 << 5)
+#define ICH9_SMB_HOSTC 0x40
+#define ICH9_SMB_HOSTC_SSRESET ((uint8_t)(1 << 3))
+#define ICH9_SMB_HOSTC_I2C_EN ((uint8_t)(1 << 2))
+#define ICH9_SMB_HOSTC_SMB_SMI_EN ((uint8_t)(1 << 1))
+#define ICH9_SMB_HOSTC_HST_EN ((uint8_t)(1 << 0))
+
+/* D30:F3 SMBus I/O and memory mapped I/O registers */
+#define ICH9_SMB_HST_STS 0x00
+#define ICH9_SMB_HST_CNT 0x02
+#define ICH9_SMB_HST_CMD 0x03
+#define ICH9_SMB_XMIT_SLVA 0x04
+#define ICH9_SMB_HST_D0 0x05
+#define ICH9_SMB_HST_D1 0x06
+#define ICH9_SMB_HOST_BLOCK_DB 0x07
+
+
+#endif /* HW_Q35_H */
diff --git a/hw/q35_smbus.c b/hw/q35_smbus.c
new file mode 100644
index 0000000..41804d0
--- /dev/null
+++ b/hw/q35_smbus.c
@@ -0,0 +1,177 @@
+/*
+ * ACPI implementation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+/*
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This is based on acpi.c.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pc_smbus.h"
+#include "pci.h"
+//#include "qemu-timer.h"
+#include "sysemu.h"
+#include "i2c.h"
+#include "smbus.h"
+#include "kvm.h"
+
+#include "q35.h"
+
+typedef struct ICH9_SMBState {
+ PCIDevice dev;
+
+ PCSMBus smb;
+} ICH9_SMBState;
+
+#define ICH9_SMB_SAVEVM_VERSION_CURRENT 0
+
+#if 0
+#define SMBHSTSTS ICH9_SMB_HST_STS
+#define SMBHSTCNT ICH9_SMB_HST_CNT
+#define SMBHSTCMD ICH9_SMB_HST_CMD
+#define SMBHSTADD ICH9_SMB_XMIT_SLVA
+#define SMBHSTDAT0 ICH9_SMB_HST_D0
+#define SMBHSTDAT1 ICH9_SMB_HST_D1
+#define SMBBLKDAT ICH9_SMB_HOST_BLOCK_DB
+#endif
+
+static ICH9_SMBState *ich9_pci_to_smb(PCIDevice* pci_dev)
+{
+ return (ICH9_SMBState*)pci_dev;
+}
+
+
+static void ich9_smb_save(QEMUFile* f,void *opaque)
+{
+ ICH9_SMBState *s = opaque;
+
+ pci_device_save(&s->dev, f);
+}
+
+static int ich9_smb_load(QEMUFile* f,void* opaque,int version_id)
+{
+ ICH9_SMBState *s = opaque;
+ int ret;
+
+ if (version_id > ICH9_SMB_SAVEVM_VERSION_CURRENT)
+ return -EINVAL;
+
+ ret = pci_device_load(&s->dev, f);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void ich9_smb_reset(void *opaque)
+{
+ //ICH9_SMBState *s = opaque;
+ //uint8_t *pci_conf = s->dev.config;
+
+ /* XXX not yet */
+}
+
+static void ich9_smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ ICH9_SMBState *s = opaque;
+ uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+
+ if (hostc & ICH9_SMB_HOSTC_HST_EN && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+ uint32_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
+ smb_ioport_writeb(&s->smb, offset, val);
+ }
+}
+
+static uint32_t ich9_smb_ioport_readb(void *opaque, uint32_t addr)
+{
+ ICH9_SMBState *s = opaque;
+ uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+
+ if (hostc & ICH9_SMB_HOSTC_HST_EN && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+ uint32_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
+ return smb_ioport_readb(&s->smb, offset);
+ }
+
+ return 0xff;
+}
+
+static void ich9_smb_map_ioport(PCIDevice *dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ ICH9_SMBState *s = ich9_pci_to_smb(dev);
+
+ assert(size == ICH9_SMB_SMB_BASE_SIZE);
+ assert(type == PCI_ADDRESS_SPACE_IO);
+
+ register_ioport_write(addr, 64, 1, ich9_smb_ioport_writeb, s);
+ register_ioport_read(addr, 64, 1, ich9_smb_ioport_readb, s);
+}
+
+i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
+{
+ ICH9_SMBState *s;
+ uint8_t *pci_conf;
+
+ s = (ICH9_SMBState *)pci_register_device(bus,
+ "ICH9 SMB", sizeof(ICH9_SMBState),
+ devfn, NULL, NULL);
+ pci_conf = s->dev.config;
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ICH9_6);
+
+ pci_config_set16(pci_conf, PCI_STATUS,
+ PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+ pci_conf_initw(&s->dev, PCI_STATUS, NULL,
+ PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY);
+
+ pci_config_set8(pci_conf, PCI_REVISION_ID, ICH9_A2_SMB_REVISION);
+ pci_config_set8(pci_conf, PCI_CLASS_INTERFACE, ICH9_SMB_PI);
+
+ pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_SMBUS);
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
+
+ /* XXX: D31IP.SMIP in chipset configuration space */
+ pci_config_set8(pci_conf, PCI_INTERRUPT_PIN, 0x01); // interrupt pin 1
+
+ pci_config_set8(pci_conf, ICH9_SMB_HOSTC, 0);
+
+
+ /* XXX:
+ * paralell_hds[0]
+ * serial_hds[0]
+ * serial_hds[0]
+ * fdc
+ */
+
+ // XXX smb_io_base
+ pci_config_set8(pci_conf, ICH9_SMB_HOSTC, 0);
+ /* XXX bar0, bar1: 64bit BAR support*/
+ pci_register_bar(&s->dev, ICH9_SMB_SMB_BASE_BAR,
+ ICH9_SMB_SMB_BASE_SIZE, PCI_ADDRESS_SPACE_IO,
+ &ich9_smb_map_ioport);
+
+ register_savevm("ich9_smb", 0, ICH9_SMB_SAVEVM_VERSION_CURRENT,
+ ich9_smb_save, ich9_smb_load, s);
+
+ pc_smbus_init(&s->smb);
+ qemu_register_reset(ich9_smb_reset, 0, s);
+
+ return s->smb.smbus;
+}
--
yamahata
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [Qemu-devel] [PATCH 11/18] pc.c: introduce a function to allocate cpu irq.
2009-06-18 10:57 ` [Qemu-devel] [PATCH 11/18] pc.c: introduce a function to allocate cpu irq Isaku Yamahata
@ 2009-06-21 20:32 ` Blue Swirl
0 siblings, 0 replies; 21+ messages in thread
From: Blue Swirl @ 2009-06-21 20:32 UTC (permalink / raw)
To: Isaku Yamahata; +Cc: qemu-devel
On 6/18/09, Isaku Yamahata <yamahata@valinux.co.jp> wrote:
> Introduce a function, pc_allocate_cpu_irq(), to allocate cpu irq
> in order to make pic_irq_request() piix independent.
> Later piix code will be split out to another file keeping pic_irq_request()
> static.
>
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
> hw/pc.c | 7 ++++++-
> 1 files changed, 6 insertions(+), 1 deletions(-)
>
> diff --git a/hw/pc.c b/hw/pc.c
> index 04d61bd..16e95ec 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -841,6 +841,11 @@ int cpu_is_bsp(CPUState *env)
> return env->cpuid_apic_id == 0;
> }
>
> +static qemu_irq *pc_allocte_cpu_irq(void)
allocte -> allocate
> - cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
> + cpu_irq = pc_allocte_cpu_irq();
allocte -> allocate
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2009-06-21 20:32 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-18 10:56 [Qemu-devel] [PATCH 00/18] split out piix specific part from pc emulator Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 01/18] acpi.c: make qemu_system_device_hot_add piix independent Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 02/18] acpi.c: split out pc smbus routines from acpi.c into pc_smbus.c Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 03/18] acpi.c: split out apm register emulation Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 04/18] acpi.c: make qemu_system_powerdown() piix independent Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 05/18] acpi: add acpi constants from linux header files and use them Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 06/18] acpi.c: split acpi.c into the common part and the piix4 part Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 07/18] pc.c: Make smm enable/disable function i440fx independent Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 08/18] pc.c: remove unnecessary global variables, pit and ioapic Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 09/18] pc.c: remove a global variable, floppy_controller Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 10/18] pc.c: remove a global variable, RTCState *rtc_state Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 11/18] pc.c: introduce a function to allocate cpu irq Isaku Yamahata
2009-06-21 20:32 ` Blue Swirl
2009-06-18 10:57 ` [Qemu-devel] [PATCH 12/18] pc.c: make pc_init1() not refer ferr_irq directly Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 13/18] pc.c: split out cpu initialization from pc_init1() into pc_cpus_init() Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 14/18] pc.c: split out memory allocation from pc_init1() into pc_memory_init() Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 15/18] pc.c: split out vga initialization from pc_init1() into pc_vga_init() Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 16/18] pc.c: split out basic device init from pc_init1() into pc_basic_device_init() Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 17/18] pc.c: split out pci device init from pc_init1() into pc_pci_device_init() Isaku Yamahata
2009-06-18 10:57 ` [Qemu-devel] [PATCH 18/18] pc.c: split out piix specific part from pc.c into pc_piix.c Isaku Yamahata
2009-06-18 11:00 ` [Qemu-devel] [PATCH] q35 chipset based pc. wip Isaku Yamahata
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).