aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2013-02-20 02:51:24 +0100
committerMichael S. Tsirkin <mst@redhat.com>2013-02-27 17:23:22 +0200
commit0e98b436eceb9d31caad898f4983a369c76524e0 (patch)
treec0e4fb98d0c983f3569d3e390ce7b70302ee08c2
parent7feb640cf32d86f91f5a624136345eb6a63eab42 (diff)
downloadqemu-0e98b436eceb9d31caad898f4983a369c76524e0.zip
qemu-0e98b436eceb9d31caad898f4983a369c76524e0.tar.gz
qemu-0e98b436eceb9d31caad898f4983a369c76524e0.tar.bz2
ICH9 LPC: Reset Control Register, basic implementation
This commit does the same for the ICH9 LPC as commit 1ec4ba74 for the PIIX3. For the present we're ignoring the Full Reset (FULL_RST) and System Reset (SYS_RST) bits; the guest can read them back but that's it. Signed-off-by: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/ich9.h11
-rw-r--r--hw/lpc_ich9.c57
2 files changed, 68 insertions, 0 deletions
diff --git a/hw/ich9.h b/hw/ich9.h
index d4509bb..dbc4495 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -49,6 +49,15 @@ typedef struct ICH9LPCState {
/* 10.1 Chipset Configuration registers(Memory Space)
which is pointed by RCBA */
uint8_t chip_config[ICH9_CC_SIZE];
+
+ /*
+ * 13.7.5 RST_CNT---Reset Control Register (LPC I/F---D31:F0)
+ *
+ * register contents and IO memory region
+ */
+ uint8_t rst_cnt;
+ MemoryRegion rst_cnt_mem;
+
/* isa bus */
ISABus *isa_bus;
MemoryRegion rbca_mem;
@@ -103,6 +112,8 @@ typedef struct ICH9LPCState {
#define ICH9_D2P_A2_REVISION 0x92
+/* D31:F0 LPC Processor Interface */
+#define ICH9_RST_CNT_IOPORT 0xCF9
/* D31:F1 LPC controller */
#define ICH9_A2_LPC "ICH9 A2 LPC"
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index e25689b..eceb052 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -466,6 +466,7 @@ static void ich9_lpc_reset(DeviceState *qdev)
ich9_lpc_rcba_update(lpc, rbca_old);
lpc->sci_level = 0;
+ lpc->rst_cnt = 0;
}
static const MemoryRegionOps rbca_mmio_ops = {
@@ -498,6 +499,32 @@ static void ich9_lpc_machine_ready(Notifier *n, void *opaque)
}
}
+/* reset control */
+static void ich9_rst_cnt_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned len)
+{
+ ICH9LPCState *lpc = opaque;
+
+ if (val & 4) {
+ qemu_system_reset_request();
+ return;
+ }
+ lpc->rst_cnt = val & 0xA; /* keep FULL_RST (bit 3) and SYS_RST (bit 1) */
+}
+
+static uint64_t ich9_rst_cnt_read(void *opaque, hwaddr addr, unsigned len)
+{
+ ICH9LPCState *lpc = opaque;
+
+ return lpc->rst_cnt;
+}
+
+static const MemoryRegionOps ich9_rst_cnt_ops = {
+ .read = ich9_rst_cnt_read,
+ .write = ich9_rst_cnt_write,
+ .endianness = DEVICE_LITTLE_ENDIAN
+};
+
static int ich9_lpc_initfn(PCIDevice *d)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
@@ -519,9 +546,32 @@ static int ich9_lpc_initfn(PCIDevice *d)
lpc->machine_ready.notify = ich9_lpc_machine_ready;
qemu_add_machine_init_done_notifier(&lpc->machine_ready);
+ memory_region_init_io(&lpc->rst_cnt_mem, &ich9_rst_cnt_ops, lpc,
+ "lpc-reset-control", 1);
+ memory_region_add_subregion_overlap(pci_address_space_io(d),
+ ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
+ 1);
+
return 0;
}
+static bool ich9_rst_cnt_needed(void *opaque)
+{
+ ICH9LPCState *lpc = opaque;
+
+ return (lpc->rst_cnt != 0);
+}
+
+static const VMStateDescription vmstate_ich9_rst_cnt = {
+ .name = "ICH9LPC/rst_cnt",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(rst_cnt, ICH9LPCState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_ich9_lpc = {
.name = "ICH9LPC",
.version_id = 1,
@@ -535,6 +585,13 @@ static const VMStateDescription vmstate_ich9_lpc = {
VMSTATE_UINT8_ARRAY(chip_config, ICH9LPCState, ICH9_CC_SIZE),
VMSTATE_UINT32(sci_level, ICH9LPCState),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (VMStateSubsection[]) {
+ {
+ .vmsd = &vmstate_ich9_rst_cnt,
+ .needed = ich9_rst_cnt_needed
+ },
+ { 0 }
}
};