summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/i82371eb_acpi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/i82371eb_acpi.cpp')
-rw-r--r--src/devices/machine/i82371eb_acpi.cpp322
1 files changed, 306 insertions, 16 deletions
diff --git a/src/devices/machine/i82371eb_acpi.cpp b/src/devices/machine/i82371eb_acpi.cpp
index 35b42b9c501..649f5126b99 100644
--- a/src/devices/machine/i82371eb_acpi.cpp
+++ b/src/devices/machine/i82371eb_acpi.cpp
@@ -15,8 +15,10 @@
#define LOG_IO (1U << 1) // log PCI register accesses
#define LOG_TODO (1U << 2) // log unimplemented registers
#define LOG_MAP (1U << 3) // log full remaps (verbose)
+#define LOG_ACPI (1U << 4) // log ACPI internals
+#define LOG_ACPIEX (1U << 5) // verbose ACPI internals
-#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_MAP)
+#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_ACPI | LOG_ACPIEX)
//#define LOG_OUTPUT_FUNC osd_printf_warning
#include "logmacro.h"
@@ -24,8 +26,11 @@
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
+#define LOGACPI(...) LOGMASKED(LOG_ACPI, __VA_ARGS__)
+#define LOGACPIEX(...) LOGMASKED(LOG_ACPIEX, __VA_ARGS__)
DEFINE_DEVICE_TYPE(I82371EB_ACPI, i82371eb_acpi_device, "i82371eb_acpi", "Intel 82371EB PIIX4E Power Management and ACPI")
+DEFINE_DEVICE_TYPE(ACPI_PIIX4, acpi_piix4_device, "acpi_piix4", "ACPI PIIX4")
i82371eb_acpi_device::i82371eb_acpi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: pci_device(mconfig, I82371EB_ACPI, tag, owner, clock)
@@ -38,17 +43,11 @@ i82371eb_acpi_device::i82371eb_acpi_device(const machine_config &mconfig, const
set_ids(0x80867113, 0x02, 0x068000, 0x00);
}
-void i82371eb_acpi_device::device_add_mconfig(machine_config &config)
-{
-
-}
-
void i82371eb_acpi_device::config_map(address_map &map)
{
pci_device::config_map(map);
- // TODO: has interrupt pin
- map(0x10, 0xd7).unmaprw();
- map(0x10, 0xd7).rw(FUNC(i82371eb_acpi_device::unmap_log_r), FUNC(i82371eb_acpi_device::unmap_log_w));
+ map(0x40, 0xd7).unmaprw();
+ map(0x40, 0xd7).rw(FUNC(i82371eb_acpi_device::unmap_log_r), FUNC(i82371eb_acpi_device::unmap_log_w));
// I/O space
map(0x40, 0x43).rw(FUNC(i82371eb_acpi_device::pmba_r), FUNC(i82371eb_acpi_device::pmba_w));
map(0x58, 0x5b).rw(FUNC(i82371eb_acpi_device::devactb_r), FUNC(i82371eb_acpi_device::devactb_w));
@@ -59,9 +58,6 @@ void i82371eb_acpi_device::config_map(address_map &map)
map(0xd2, 0xd2).rw(FUNC(i82371eb_acpi_device::smbhstcfg_r), FUNC(i82371eb_acpi_device::smbhstcfg_w));
}
-void i82371eb_acpi_device::io_map(address_map &map)
-{
-}
void i82371eb_acpi_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
@@ -76,8 +72,7 @@ void i82371eb_acpi_device::map_extra(uint64_t memory_window_start, uint64_t memo
if (m_pmiose)
{
LOGMAP("- PMBA %04x-%04x\n", m_pmba, m_pmba + 0x3f);
- // TODO: subset, should map up to 0x3f only (and current lpc-acpi don't)
- m_acpi->map_device(memory_window_start, memory_window_end, 0, memory_space, io_window_start, m_pmba + 0x3f, m_pmba, io_space);
+ io_space->install_device(m_pmba, m_pmba | 0x3f, *m_acpi, &acpi_piix4_device::map);
}
const bool iose = bool(BIT(command, 0));
@@ -96,6 +91,11 @@ void i82371eb_acpi_device::device_start()
{
pci_device::device_start();
+ status = 0x0280;
+ command = 0;
+ command_mask = 1;
+
+ // INTA#
intr_pin = 1;
#if 0
@@ -202,11 +202,301 @@ void i82371eb_acpi_device::smbhstcfg_w(u8 data)
u8 i82371eb_acpi_device::unmap_log_r(offs_t offset)
{
- LOGTODO("I82371EB_ACPI Unemulated [%02x] R\n", offset + 0x10);
+ LOGTODO("I82371EB_ACPI Unemulated [%02x] R\n", offset + 0x40);
return 0;
}
void i82371eb_acpi_device::unmap_log_w(offs_t offset, u8 data)
{
- LOGTODO("I82371EB_ACPI Unemulated [%02x] %02x W\n", offset + 0x10, data);
+ LOGTODO("I82371EB_ACPI Unemulated [%02x] %02x W\n", offset + 0x40, data);
+}
+
+/*
+ * ACPI Power Management internals
+ */
+
+acpi_piix4_device::acpi_piix4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ACPI_PIIX4, tag, owner, clock)
+{
+}
+
+void acpi_piix4_device::device_start()
+{
+ save_item(NAME(m_pmsts));
+ save_item(NAME(m_pmen));
+ save_item(NAME(m_pmcntrl));
+ save_item(NAME(m_gpsts));
+ save_item(NAME(m_gpen));
+ save_item(NAME(m_pcntrl));
+ save_item(NAME(m_glbsts));
+ save_item(NAME(m_devsts));
+ save_item(NAME(m_glben));
+ save_item(NAME(m_glbctl));
+ save_item(NAME(m_devctl));
+ save_item(NAME(m_gporeg));
+
+}
+
+void acpi_piix4_device::device_reset()
+{
+ m_pmsts = 0;
+ m_pmen = 0;
+ m_pmcntrl = 0;
+ m_gpsts = 0;
+ m_gpen = 0;
+ m_pcntrl = 0;
+ m_glbsts = 0;
+ m_devsts[0] = m_devsts[1] = 0;
+ m_glben = 0;
+ m_glbctl[0] = m_glbctl[1] = 0;
+ m_devctl[0] = m_devctl[1] = 0;
+
+ m_gporeg[0] = 0x7fff;
+ m_gporeg[1] = 0xbfff;
+}
+
+void acpi_piix4_device::map(address_map &map)
+{
+ // Power Management Status
+ map(0x00, 0x01).lrw16(
+ NAME([this] () { return m_pmsts; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ m_pmsts &= ~(data & 0x8d31);
+ })
+ );
+ // Power Management Resume Enable
+ map(0x02, 0x03).lrw16(
+ NAME([this] () { return m_pmen; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_pmen);
+ LOGACPI("PMEN: %04x & %04x\n", data, mem_mask);
+ LOGACPIEX("\tRTC_EN %d PWRBTN_EN %d GBL_EN %d TMROF_EN %d\n"
+ , BIT(data, 10)
+ , BIT(data, 8)
+ , BIT(data, 5)
+ , BIT(data, 0)
+ );
+ })
+ );
+ // Power Management Control
+ map(0x04, 0x05).lrw16(
+ NAME([this] (offs_t offset) { return m_pmcntrl; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_pmcntrl);
+ LOGACPI("PMCNTRL: %04x & %04x\n", data, mem_mask);
+ LOGACPIEX("\tSUS_EN %d SUS_TYPE %d GBL_RLS %d BRLD_EN_BM %d SCI_EN %d\n"
+ , BIT(data, 13)
+ , (data >> 10) & 7
+ , BIT(data, 2)
+ , BIT(data, 1)
+ , BIT(data, 0)
+ );
+ })
+ );
+ // Power Management Timer
+ map(0x08, 0x0b).lr16(
+ NAME([this] (offs_t offset) {
+ const u32 tmr_val = machine().time().as_ticks(clock());
+ // TODO: resets with PCI reset
+ // TODO: sets TMROF_STS to 1 on bit 23 transitions, generates a SCI irq with TMROF_EN
+ LOGACPI("PMTMR%d: %08x\n", offset, tmr_val);
+ if (offset)
+ return (tmr_val >> 16) & 0xff;
+
+ return tmr_val & 0xffff;
+ })
+ );
+ // General Purpose Status
+ map(0x0c, 0x0d).lrw16(
+ NAME([this] () { return m_gpsts; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ m_gpsts &= ~(data & 0xf81);
+ })
+ );
+ // General Purpose Enable
+ map(0x0e, 0x0f).lrw16(
+ NAME([this] (offs_t offset) { return m_gpen; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_gpen);
+ LOGACPI("GPEN: %04x & %04x\n", data, mem_mask);
+ LOGACPIEX("\tLID_EN %d RI_EN %d GPI_EN %d USB_EN %d THRM_EN %d\n"
+ , BIT(data, 11)
+ , BIT(data, 10)
+ , BIT(data, 9)
+ , BIT(data, 8)
+ , BIT(data, 0)
+ );
+ })
+ );
+ // Processor Control (I/O)
+ map(0x10, 0x11).lr16(NAME([this] () {
+ // CC_STS (r/o)
+ if (!machine().side_effects_disabled())
+ LOGACPI("PCNTRL: CC_STS read\n");
+ return 0x0002;
+ }));
+ map(0x12, 0x13).lrw16(
+ NAME([this] () { return m_pcntrl; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_pcntrl);
+ LOGACPI("PCNTRL: %04x & %04x\n", data, mem_mask);
+ LOGACPIEX("\tCLKRUN_EN %d STPCLK_EN %d SLEEP_EN %d BST_EN %d CC_EN %d THT_EN %d THTL_DTY %f%\n"
+ , BIT(data, 13)
+ , BIT(data, 12)
+ , BIT(data, 11)
+ , BIT(data, 10)
+ , BIT(data, 9)
+ , BIT(data, 4)
+ // NOTE: setting 0 <reserved>
+ , ((data >> 1) & 7) * 12.5
+ );
+ })
+ );
+ // Processor Level 2/3
+ map(0x14, 0x15).lr16(
+ NAME([this] (offs_t offset, u16 mem_mask) {
+ if (!machine().side_effects_disabled())
+ {
+ LOGACPI("PLVL%d read\n", offset + 2);
+ // Must be byte access
+ if (mem_mask == 0xffff)
+ LOG("\tInvalid word access!\n");
+ }
+ return 0;
+ })
+ );
+ // Global Status
+ map(0x18, 0x19).lrw16(
+ NAME([this] () { return m_glbsts; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ // ---- x--- ---- ---- IRQ Resume Status
+ // ---- -x-- ---- ---- External SMI Status (wc) EXTSMI# asserted
+ // ---- ---x ---- ---- Global Standby Status (wc)
+ if (ACCESSING_BITS_8_15)
+ {
+ // IRQ_RMS_STS
+ m_glbsts &= ~(0x0800);
+ m_glbsts |= (BIT(data, 11) << 11);
+ // EXTSMI_STS
+ if (BIT(data, 10))
+ m_glbsts &= ~(1 << 10);
+ // GSTBY_STS
+ if (BIT(data, 8))
+ m_glbsts &= ~(1 << 8);
+ }
+ // ---- ---- x--- ---- GP Status (r/o) '1' if any GPSTS bits goes high
+ // ---- ---- -x-- ---- PM1 Status (r/o) '1' if any PMSTS bits goes high
+ // ---- ---- --x- ---- APM Status (wc)
+ // ---- ---- ---x ---- All Devices Status (r/o), '1' if any DEVSTS bits goes high
+ // ---- ---- ---- -x-- P4MA Status (wc)
+ // ---- ---- ---- --x- Legacy USB Status (wc)
+ // ---- ---- ---- ---x BIOS Status (wc)
+ if (ACCESSING_BITS_0_7)
+ {
+ m_glbsts &= ~(data & 0x27);
+ }
+ LOG("GBLSTS %04x & %04x -> %04x\n", data, mem_mask, m_glbsts);
+ })
+ );
+ // Device Status
+ // [1] TRP_STS_DEV Trap Status Bits
+ // [0] IDL_STS_DEV Idle Status Bits
+ map(0x1c, 0x1f).lrw16(
+ NAME([this] (offs_t offset) { return m_devsts[offset]; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ const u16 wc_mask = offset ? 0x3fff : 0xfff;
+ m_devsts[offset] &= ~(data & wc_mask);
+ })
+ );
+ // Global Enable
+ map(0x20, 0x21).lrw16(
+ NAME([this] () { return m_glben; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_glben);
+ LOGACPI("GLBEN %04x & %04x\n");
+ LOGACPIEX("\tBATLOW_EN %d IRQ_RSM_EN %d EXTSMI_EN %d GSTBY_EN %d P4MA_EN %d BM_TRP_EN %d BIOS_EN %d LEGACY_USB_EN %d\n"
+ , BIT(data, 15)
+ , BIT(data, 11)
+ , BIT(data, 10)
+ , BIT(data, 8)
+ , BIT(data, 4)
+ , BIT(data, 3)
+ , BIT(data, 1)
+ , BIT(data, 0)
+ );
+ })
+ );
+ // Global Control
+ map(0x28, 0x2b).lrw16(
+ NAME([this] (offs_t offset) { return m_glbctl[offset]; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_glbctl[offset]);
+ LOGACPI("GLBCTL%d %04x & %04x\n", offset, data, mem_mask);
+ if (offset)
+ {
+ // NOTE: EOS gets automatically cleared on SMI#
+ LOGACPIEX("\tGSTBY_SELB %d LID_POL %d SM_FREEZE %d EOS %d\n"
+ , BIT(data, 10)
+ , BIT(data, 9)
+ , BIT(data, 8)
+ , BIT(data, 0)
+ );
+ }
+ else
+ {
+ LOGACPIEX("\tGSTBY_CNT %d GSTBY_SELA %d THRM_POL %d RIOS_RLS %d SMI_EN %d\n"
+ , (data >> 9) & 0x7f
+ , BIT(data, 8)
+ , BIT(data, 2)
+ , BIT(data, 1)
+ , BIT(data, 0)
+ );
+ }
+ // GSTBY
+ // BA
+ // 11 4 seconds
+ // 10 4 msec
+ // 01 4 minutes
+ // 00 32 seconds (default)
+ })
+ );
+ // Device Control
+ // bits 31:28 <reserved>
+ map(0x2c, 0x2f).lrw16(
+ NAME([this] (offs_t offset) { return m_devctl[offset]; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_devctl[offset]);
+ LOGACPI("DEVCTL%d %04x & %04x\n", offset, data, mem_mask);
+ })
+ );
+ // General Purpose Input
+ // bits 23:22 <reserved>, [0x33] not hooked up (assume reserved too)
+ map(0x30, 0x33).lr16(
+ NAME([this] (offs_t offset, u16 mem_mask) {
+ if (!machine().side_effects_disabled())
+ {
+ LOGACPI("GPIREG%d read\n", offset);
+ if (mem_mask == 0xffff)
+ LOG("\tInvalid word access!\n");
+ }
+ return 0;
+ })
+ );
+ map(0x34, 0x37).lrw16(
+ NAME([this] (offs_t offset, u16 mem_mask) {
+ if (!machine().side_effects_disabled())
+ {
+ LOGACPI("GPOREG%d read\n", offset);
+ if (mem_mask == 0xffff)
+ LOG("\tInvalid word access!\n");
+ }
+ return m_gporeg[offset];
+ }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_gporeg[offset]);
+ LOGACPI("GPOREG%d write %04x & %04x\n", offset, data, mem_mask);
+ if (mem_mask == 0xffff)
+ LOG("\tInvalid word access!\n");
+ })
+ );
}