summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/mediagx_cs5530_bridge.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/mediagx_cs5530_bridge.cpp')
-rw-r--r--src/devices/machine/mediagx_cs5530_bridge.cpp562
1 files changed, 562 insertions, 0 deletions
diff --git a/src/devices/machine/mediagx_cs5530_bridge.cpp b/src/devices/machine/mediagx_cs5530_bridge.cpp
new file mode 100644
index 00000000000..8fc90f2bedd
--- /dev/null
+++ b/src/devices/machine/mediagx_cs5530_bridge.cpp
@@ -0,0 +1,562 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+[Cyrix/National Semiconductor/AMD] [MediaGX/Geode] [Cx/CS]5530 bridge implementation (southbridge)
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "mediagx_cs5530_bridge.h"
+
+#include "speaker.h"
+
+#define LOG_MAP (1U << 1) // log full remaps
+
+#define VERBOSE (LOG_GENERAL | LOG_MAP)
+//#define LOG_OUTPUT_FUNC osd_printf_warning
+
+#include "logmacro.h"
+
+#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
+
+DEFINE_DEVICE_TYPE(MEDIAGX_CS5530_BRIDGE, mediagx_cs5530_bridge_device, "mediagx_cs5530_bridge", "MediaGX CS5530 Bridge")
+
+mediagx_cs5530_bridge_device::mediagx_cs5530_bridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pci_device(mconfig, MEDIAGX_CS5530_BRIDGE, tag, owner, clock)
+// , m_smi_callback(*this)
+// , m_nmi_callback(*this)
+// , m_stpclk_callback(*this)
+ , m_boot_state_hook(*this)
+ , m_rtcale(*this)
+ , m_rtccs_read(*this, 0xff)
+ , m_rtccs_write(*this)
+ , m_host_cpu(*this, finder_base::DUMMY_TAG)
+ , m_ide(*this, finder_base::DUMMY_TAG)
+ , m_kbdc(*this, finder_base::DUMMY_TAG)
+ , m_pic8259_master(*this, "pic8259_master")
+ , m_pic8259_slave(*this, "pic8259_slave")
+ , m_dma8237_1(*this, "dma8237_1")
+ , m_dma8237_2(*this, "dma8237_2")
+ , m_pit8254(*this, "pit8254")
+ , m_isabus(*this, "isabus")
+ , m_speaker(*this, "speaker")
+{
+}
+
+void mediagx_cs5530_bridge_device::device_add_mconfig(machine_config &config)
+{
+ // 8254-equivalent
+ PIT8254(config, m_pit8254);
+ m_pit8254->set_clk<0>(4772720 / 4); // heartbeat IRQ
+ m_pit8254->out_handler<0>().set(FUNC(mediagx_cs5530_bridge_device::at_pit8254_out0_changed));
+ m_pit8254->set_clk<1>(4772720 / 4); // DRAM refresh
+ m_pit8254->out_handler<1>().set(FUNC(mediagx_cs5530_bridge_device::at_pit8254_out1_changed));
+ m_pit8254->set_clk<2>(4772720 / 4); // PIO port C pin 4, and speaker polling enough
+ m_pit8254->out_handler<2>().set(FUNC(mediagx_cs5530_bridge_device::at_pit8254_out2_changed));
+
+ // 8237-equivalent
+ AM9517A(config, m_dma8237_1, XTAL(14'318'181) / 3);
+ m_dma8237_1->out_hreq_callback().set(m_dma8237_2, FUNC(am9517a_device::dreq0_w));
+ m_dma8237_1->out_eop_callback().set(FUNC(mediagx_cs5530_bridge_device::at_dma8237_out_eop));
+ m_dma8237_1->in_memr_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_dma_read_byte));
+ m_dma8237_1->out_memw_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_dma_write_byte));
+ m_dma8237_1->in_ior_callback<0>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_0_dack_r));
+ m_dma8237_1->in_ior_callback<1>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_1_dack_r));
+ m_dma8237_1->in_ior_callback<2>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_2_dack_r));
+ m_dma8237_1->in_ior_callback<3>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_3_dack_r));
+ m_dma8237_1->out_iow_callback<0>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_0_dack_w));
+ m_dma8237_1->out_iow_callback<1>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_1_dack_w));
+ m_dma8237_1->out_iow_callback<2>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_2_dack_w));
+ m_dma8237_1->out_iow_callback<3>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_3_dack_w));
+ m_dma8237_1->out_dack_callback<0>().set(FUNC(mediagx_cs5530_bridge_device::pc_dack0_w));
+ m_dma8237_1->out_dack_callback<1>().set(FUNC(mediagx_cs5530_bridge_device::pc_dack1_w));
+ m_dma8237_1->out_dack_callback<2>().set(FUNC(mediagx_cs5530_bridge_device::pc_dack2_w));
+ m_dma8237_1->out_dack_callback<3>().set(FUNC(mediagx_cs5530_bridge_device::pc_dack3_w));
+
+ AM9517A(config, m_dma8237_2, XTAL(14'318'181) / 3);
+ m_dma8237_2->out_hreq_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_dma_hrq_changed));
+ m_dma8237_2->in_memr_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_dma_read_word));
+ m_dma8237_2->out_memw_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_dma_write_word));
+ m_dma8237_2->in_ior_callback<1>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_5_dack_r));
+ m_dma8237_2->in_ior_callback<2>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_6_dack_r));
+ m_dma8237_2->in_ior_callback<3>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_7_dack_r));
+ m_dma8237_2->out_iow_callback<1>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_5_dack_w));
+ m_dma8237_2->out_iow_callback<2>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_6_dack_w));
+ m_dma8237_2->out_iow_callback<3>().set(FUNC(mediagx_cs5530_bridge_device::pc_dma8237_7_dack_w));
+ m_dma8237_2->out_dack_callback<0>().set(FUNC(mediagx_cs5530_bridge_device::pc_dack4_w));
+ m_dma8237_2->out_dack_callback<1>().set(FUNC(mediagx_cs5530_bridge_device::pc_dack5_w));
+ m_dma8237_2->out_dack_callback<2>().set(FUNC(mediagx_cs5530_bridge_device::pc_dack6_w));
+ m_dma8237_2->out_dack_callback<3>().set(FUNC(mediagx_cs5530_bridge_device::pc_dack7_w));
+
+ // 8259A-equivalent
+ PIC8259(config, m_pic8259_master);
+ m_pic8259_master->out_int_callback().set_inputline(m_host_cpu, 0);
+ m_pic8259_master->in_sp_callback().set_constant(1);
+ m_pic8259_master->read_slave_ack_callback().set(FUNC(mediagx_cs5530_bridge_device::get_slave_ack));
+
+ PIC8259(config, m_pic8259_slave);
+ m_pic8259_slave->out_int_callback().set(m_pic8259_master, FUNC(pic8259_device::ir2_w));
+ m_pic8259_slave->in_sp_callback().set_constant(0);
+
+ SPEAKER(config, "mono").front_center();
+ SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50);
+
+ ISA16(config, m_isabus, 0);
+ m_isabus->irq3_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq3_w));
+ m_isabus->irq4_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq4_w));
+ m_isabus->irq5_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq5_w));
+ m_isabus->irq6_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq6_w));
+ m_isabus->irq7_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq7_w));
+ m_isabus->irq2_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq9_w));
+ m_isabus->irq10_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq10_w));
+ m_isabus->irq11_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq11_w));
+ m_isabus->irq12_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq12m_w));
+ m_isabus->irq14_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq14_w));
+ m_isabus->irq15_callback().set(FUNC(mediagx_cs5530_bridge_device::pc_irq15_w));
+ m_isabus->iochck_callback().set(FUNC(mediagx_cs5530_bridge_device::iochck_w));
+}
+
+void mediagx_cs5530_bridge_device::device_config_complete()
+{
+ auto isabus = m_isabus.finder_target();
+ isabus.first.subdevice<isa16_device>(isabus.second)->set_memspace(m_host_cpu, AS_PROGRAM);
+ isabus.first.subdevice<isa16_device>(isabus.second)->set_iospace(m_host_cpu, AS_IO);
+
+ pci_device::device_config_complete();
+}
+
+void mediagx_cs5530_bridge_device::device_reset()
+{
+ pci_device::device_reset();
+
+ command = 0x0000;
+ status = 0x0280;
+
+ m_nmi_enabled = false;
+}
+
+void mediagx_cs5530_bridge_device::config_map(address_map &map)
+{
+ pci_device::config_map(map);
+// map(0x40, 0x42) PCI Function Control
+// map(0x43, 0x43) USB Shadow
+// map(0x44, 0x44) Reset Control
+
+// map(0x50, 0x50) PIT Control/ISA CLK divider
+// map(0x51, 0x51) ISA I/O Recovery Control
+// map(0x52, 0x52) ROM/AT Logic Control
+// map(0x53, 0x53) Alternate CPU Support
+// map(0x5a, 0x5b) Decode Control
+ map(0x5a, 0x5b).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_decode_control[offset];
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_decode_control[offset] = data;
+ remap_cb();
+ })
+ );
+// map(0x5c, 0x5d) PCI Interrupt Steering
+
+// map(0x70, 0x71) GPCS Base Address
+// map(0x72, 0x72) GPCS Control
+
+// map(0x80, 0x83) Power Management Enable
+// map(0x84, 0x87) Second Level Power Management Status Mirror (r/o)
+// map(0x88, 0x89) General Purpose Timer 1 Count/Control
+// map(0x8a, 0x8b) General Purpose Timer 2 Count/Control
+// map(0x8c, 0x8c) IRQ Speedup Timer Count
+// map(0x8d, 0x8d) Video Speedup Timer Count
+// map(0x8e, 0x8e) VGA Timer COunt
+
+// map(0x90, 0x90) GPIO Pin Direction
+// map(0x91, 0x91) GPIO Pin Data
+// map(0x92, 0x92) GPIO Control 1
+// map(0x93, 0x93) Miscellaneous Device Control
+// map(0x94, 0x95) Suspend Modulation OFF/ON Count
+// map(0x96, 0x96) Suspend Configuration
+// map(0x97, 0x97) GPIO Control 2
+
+// map(0x98, 0x99) Primary HDD Idle Timer Count
+// map(0x9a, 0x9b) Floppy Disk Idle Timer Count
+// map(0x9c, 0x9d) Parallel / Serial Idle Timer Count
+// map(0x9e, 0x9f) Keyboard / Mouse Idle Timer Count
+// map(0xa0, 0xa5) User Defined Device # Idle Timer Count
+// map(0xa6, 0xa7) Video Idle Timer Count
+// map(0xa8, 0xa9) Video Overflow Count
+// map(0xac, 0xad) Secondary HDD Idle Timer Count
+// map(0xae, 0xae) CPU Suspend Command (w/o)
+// map(0xaf, 0xaf) Suspend Notebook Command (w/o)
+
+// map(0xb4, 0xb7) Floppy Port Shadows (r/o)
+// map(0xb8, 0xb8) DMA Shadow (r/o)
+// map(0xb9, 0xb9) PIC Shadow (r/o)
+// map(0xba, 0xba) PIT Shadow (r/o)
+// map(0xbb, 0xbb) RTC Index Shadow (r/o)
+// map(0xbc, 0xbc) Clock Stop Control
+
+// map(0xc0, 0xcb) User Defined Device # Base Address
+// map(0xcc, 0xce) User Defined Device # Control
+
+// map(0xd0, 0xd0) Software SMI (w/o)
+// map(0xec, 0xec) Timer Test
+
+// map(0xf4, 0xf7) Second Level Power Management Status
+}
+
+// TODO: keyboard & RTC ports should map thru map_extra subtractive/positive decoding
+void mediagx_cs5530_bridge_device::internal_io_map(address_map &map)
+{
+ map(0x0000, 0x001f).rw("dma8237_1", FUNC(am9517a_device::read), FUNC(am9517a_device::write));
+ map(0x0020, 0x0021).rw("pic8259_master", FUNC(pic8259_device::read), FUNC(pic8259_device::write));
+ map(0x0040, 0x005f).rw("pit8254", FUNC(pit8254_device::read), FUNC(pit8254_device::write));
+ map(0x0060, 0x0060).rw(m_kbdc, FUNC(kbdc8042_device::port60_r), FUNC(kbdc8042_device::port60_w));
+ map(0x0061, 0x0061).rw(FUNC(mediagx_cs5530_bridge_device::at_portb_r), FUNC(mediagx_cs5530_bridge_device::at_portb_w));
+ map(0x0064, 0x0064).rw(m_kbdc, FUNC(kbdc8042_device::port64_r), FUNC(kbdc8042_device::port64_w));
+ map(0x0070, 0x0070).lw8(
+ NAME([this] (u8 data) {
+ m_nmi_enabled = BIT(data, 7);
+ // TODO: trap write for RTC shadow reg
+ m_rtcale(data);
+ })
+ );
+ map(0x0071, 0x0071).lrw8(
+ NAME([this] () {
+ return m_rtccs_read();
+ }),
+ NAME([this] (u8 data) {
+ m_rtccs_write(data);
+ })
+ );
+ map(0x0080, 0x008f).rw(FUNC(mediagx_cs5530_bridge_device::at_page8_r), FUNC(mediagx_cs5530_bridge_device::at_page8_w));
+ // TODO: port decoding driven by PCI register $52
+ map(0x0092, 0x0092).lrw8(
+ NAME([this] () {
+ //LOG("Fast init $92 read\n");
+ return m_fast_init;
+ }),
+ NAME([this] (u8 data) {
+ LOG("Fast init $92 write %02x\n", data);
+ m_host_cpu->set_input_line(INPUT_LINE_A20, BIT(data, 1));
+ m_fast_init = data;
+ })
+ );
+ map(0x00a0, 0x00a1).rw("pic8259_slave", FUNC(pic8259_device::read), FUNC(pic8259_device::write));
+ map(0x00c0, 0x00df).rw(FUNC(mediagx_cs5530_bridge_device::at_dma8237_2_r), FUNC(mediagx_cs5530_bridge_device::at_dma8237_2_w));
+// map(0x04d0, 0x04d1).rw(FUNC(mediagx_cs5530_bridge_device::eisa_irq_read), FUNC(mediagx_cs5530_bridge_device::eisa_irq_write));
+ // map(0x00e0, 0x00ef) MCA bus (cfr. Bochs) or PnP
+ map(0x00ea, 0x00eb).lw8(NAME([] (offs_t offset, u8 data) { }));
+// map(0x121c, 0x121f) ACPI Timer count register (on rev 1.3+)
+}
+
+void mediagx_cs5530_bridge_device::pc_irq1_w(int state) { m_pic8259_master->ir1_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq3_w(int state) { m_pic8259_master->ir3_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq4_w(int state) { m_pic8259_master->ir4_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq5_w(int state) { m_pic8259_master->ir5_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq6_w(int state) { m_pic8259_master->ir6_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq7_w(int state) { m_pic8259_master->ir7_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq8n_w(int state) { m_pic8259_slave->ir0_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq9_w(int state) { m_pic8259_slave->ir1_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq10_w(int state) { m_pic8259_slave->ir2_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq11_w(int state) { m_pic8259_slave->ir3_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq12m_w(int state) { m_pic8259_slave->ir4_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq14_w(int state) { m_pic8259_slave->ir6_w(state); }
+void mediagx_cs5530_bridge_device::pc_irq15_w(int state) { m_pic8259_slave->ir7_w(state); }
+
+uint8_t mediagx_cs5530_bridge_device::get_slave_ack(offs_t offset)
+{
+ if (offset == 2) // IRQ = 2
+ return m_pic8259_slave->acknowledge();
+
+ return 0x00;
+}
+
+void mediagx_cs5530_bridge_device::at_pit8254_out0_changed(int state)
+{
+ if (m_pic8259_master)
+ m_pic8259_master->ir0_w(state);
+}
+
+void mediagx_cs5530_bridge_device::at_pit8254_out1_changed(int state)
+{
+ if (state)
+ m_refresh = !m_refresh;
+}
+
+void mediagx_cs5530_bridge_device::at_pit8254_out2_changed(int state)
+{
+ m_pit_out2 = state ? 1 : 0;
+ m_speaker->level_w(m_at_spkrdata & m_pit_out2);
+}
+
+void mediagx_cs5530_bridge_device::at_speaker_set_spkrdata(uint8_t data)
+{
+ m_at_spkrdata = data ? 1 : 0;
+ m_speaker->level_w(m_at_spkrdata & m_pit_out2);
+}
+
+uint8_t mediagx_cs5530_bridge_device::at_portb_r()
+{
+ uint8_t data = m_at_speaker;
+
+ data &= ~0xd0; /* AT BIOS don't likes this being set */
+ /* 0x10 is the dram refresh line bit on the 5170, just a timer here, 15.085us. */
+ data |= m_refresh ? 0x10 : 0;
+ if (m_pit_out2)
+ data |= 0x20;
+ else
+ data &= ~0x20; /* ps2m30 wants this */
+
+ return data;
+}
+
+void mediagx_cs5530_bridge_device::at_portb_w(uint8_t data)
+{
+ m_at_speaker = data;
+ m_pit8254->write_gate2(BIT(data, 0));
+ at_speaker_set_spkrdata(BIT(data, 1));
+ m_channel_check = BIT(data, 3);
+ if (m_channel_check)
+ m_host_cpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
+}
+
+void mediagx_cs5530_bridge_device::iochck_w(int state)
+{
+ if (!state && !m_channel_check && m_nmi_enabled)
+ m_host_cpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+}
+
+uint8_t mediagx_cs5530_bridge_device::at_page8_r(offs_t offset)
+{
+ uint8_t data = m_at_pages[offset % 0x10];
+
+ switch (offset % 8)
+ {
+ case 1:
+ data = m_dma_offset[BIT(offset, 3)][2];
+ break;
+ case 2:
+ data = m_dma_offset[BIT(offset, 3)][3];
+ break;
+ case 3:
+ data = m_dma_offset[BIT(offset, 3)][1];
+ break;
+ case 7:
+ data = m_dma_offset[BIT(offset, 3)][0];
+ break;
+ }
+ return data;
+}
+
+void mediagx_cs5530_bridge_device::at_page8_w(offs_t offset, uint8_t data)
+{
+ m_at_pages[offset % 0x10] = data;
+
+ switch (offset % 8)
+ {
+ case 0:
+ m_boot_state_hook((offs_t)0, data);
+ break;
+ case 1:
+ m_dma_offset[BIT(offset, 3)][2] = data;
+ break;
+ case 2:
+ m_dma_offset[BIT(offset, 3)][3] = data;
+ break;
+ case 3:
+ m_dma_offset[BIT(offset, 3)][1] = data;
+ break;
+ case 7:
+ m_dma_offset[BIT(offset, 3)][0] = data;
+ break;
+ }
+}
+
+void mediagx_cs5530_bridge_device::pc_dma_hrq_changed(int state)
+{
+ m_host_cpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
+
+ /* Assert HLDA */
+ m_dma8237_2->hack_w(state);
+}
+
+uint8_t mediagx_cs5530_bridge_device::pc_dma_read_byte(offs_t offset)
+{
+ address_space &prog_space = m_host_cpu->space(AS_PROGRAM); // get the right address space
+ if (m_dma_channel == -1)
+ return 0xff;
+ uint8_t result;
+ offs_t page_offset = ((offs_t)m_dma_offset[0][m_dma_channel]) << 16;
+
+ result = prog_space.read_byte(page_offset + offset);
+ return result;
+}
+
+void mediagx_cs5530_bridge_device::pc_dma_write_byte(offs_t offset, uint8_t data)
+{
+ address_space &prog_space = m_host_cpu->space(AS_PROGRAM); // get the right address space
+ if (m_dma_channel == -1)
+ return;
+ offs_t page_offset = ((offs_t)m_dma_offset[0][m_dma_channel]) << 16;
+
+ prog_space.write_byte(page_offset + offset, data);
+}
+
+uint8_t mediagx_cs5530_bridge_device::pc_dma_read_word(offs_t offset)
+{
+ address_space &prog_space = m_host_cpu->space(AS_PROGRAM); // get the right address space
+ if (m_dma_channel == -1)
+ return 0xff;
+ uint16_t result;
+ offs_t page_offset = ((offs_t)m_dma_offset[1][m_dma_channel & 3]) << 16;
+
+ result = prog_space.read_word((page_offset & 0xfe0000) | (offset << 1));
+ m_dma_high_byte = result & 0xFF00;
+
+ return result & 0xFF;
+}
+
+void mediagx_cs5530_bridge_device::pc_dma_write_word(offs_t offset, uint8_t data)
+{
+ address_space &prog_space = m_host_cpu->space(AS_PROGRAM); // get the right address space
+ if (m_dma_channel == -1)
+ return;
+ offs_t page_offset = ((offs_t)m_dma_offset[1][m_dma_channel & 3]) << 16;
+
+ prog_space.write_word((page_offset & 0xfe0000) | (offset << 1), m_dma_high_byte | data);
+}
+
+uint8_t mediagx_cs5530_bridge_device::pc_dma8237_0_dack_r() { return m_isabus->dack_r(0); }
+uint8_t mediagx_cs5530_bridge_device::pc_dma8237_1_dack_r() { return m_isabus->dack_r(1); }
+uint8_t mediagx_cs5530_bridge_device::pc_dma8237_2_dack_r() { return m_isabus->dack_r(2); }
+uint8_t mediagx_cs5530_bridge_device::pc_dma8237_3_dack_r() { return m_isabus->dack_r(3); }
+uint8_t mediagx_cs5530_bridge_device::pc_dma8237_5_dack_r() { return m_isabus->dack_r(5); }
+uint8_t mediagx_cs5530_bridge_device::pc_dma8237_6_dack_r() { return m_isabus->dack_r(6); }
+uint8_t mediagx_cs5530_bridge_device::pc_dma8237_7_dack_r() { return m_isabus->dack_r(7); }
+
+void mediagx_cs5530_bridge_device::pc_dma8237_0_dack_w(uint8_t data) { m_isabus->dack_w(0, data); }
+void mediagx_cs5530_bridge_device::pc_dma8237_1_dack_w(uint8_t data) { m_isabus->dack_w(1, data); }
+void mediagx_cs5530_bridge_device::pc_dma8237_2_dack_w(uint8_t data) { m_isabus->dack_w(2, data); }
+void mediagx_cs5530_bridge_device::pc_dma8237_3_dack_w(uint8_t data) { m_isabus->dack_w(3, data); }
+void mediagx_cs5530_bridge_device::pc_dma8237_5_dack_w(uint8_t data) { m_isabus->dack_w(5, data); }
+void mediagx_cs5530_bridge_device::pc_dma8237_6_dack_w(uint8_t data) { m_isabus->dack_w(6, data); }
+void mediagx_cs5530_bridge_device::pc_dma8237_7_dack_w(uint8_t data) { m_isabus->dack_w(7, data); }
+
+void mediagx_cs5530_bridge_device::at_dma8237_out_eop(int state)
+{
+ m_cur_eop = state == ASSERT_LINE;
+ if (m_dma_channel != -1)
+ m_isabus->eop_w(m_dma_channel, m_cur_eop ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void mediagx_cs5530_bridge_device::pc_select_dma_channel(int channel, bool state)
+{
+ m_isabus->dack_line_w(channel, state);
+
+ if (!state)
+ {
+ m_dma_channel = channel;
+ if (m_cur_eop)
+ m_isabus->eop_w(channel, ASSERT_LINE);
+ }
+ else if (m_dma_channel == channel)
+ {
+ m_dma_channel = -1;
+ if (m_cur_eop)
+ m_isabus->eop_w(channel, CLEAR_LINE);
+ }
+}
+
+void mediagx_cs5530_bridge_device::pc_dack0_w(int state) { pc_select_dma_channel(0, state); }
+void mediagx_cs5530_bridge_device::pc_dack1_w(int state) { pc_select_dma_channel(1, state); }
+void mediagx_cs5530_bridge_device::pc_dack2_w(int state) { pc_select_dma_channel(2, state); }
+void mediagx_cs5530_bridge_device::pc_dack3_w(int state) { pc_select_dma_channel(3, state); }
+void mediagx_cs5530_bridge_device::pc_dack4_w(int state) { m_dma8237_1->hack_w( state ? 0 : 1); } // it's inverted
+void mediagx_cs5530_bridge_device::pc_dack5_w(int state) { pc_select_dma_channel(5, state); }
+void mediagx_cs5530_bridge_device::pc_dack6_w(int state) { pc_select_dma_channel(6, state); }
+void mediagx_cs5530_bridge_device::pc_dack7_w(int state) { pc_select_dma_channel(7, state); }
+
+uint8_t mediagx_cs5530_bridge_device::at_dma8237_2_r(offs_t offset)
+{
+ return m_dma8237_2->read(offset / 2);
+}
+
+void mediagx_cs5530_bridge_device::at_dma8237_2_w(offs_t offset, uint8_t data)
+{
+ m_dma8237_2->write(offset / 2, data);
+}
+
+void mediagx_cs5530_bridge_device::map_bios(address_space *memory_space, uint32_t start, uint32_t end)
+{
+ uint32_t mask = m_region->bytes() - 1;
+ memory_space->install_rom(start, end, m_region->base() + (start & mask));
+}
+
+void mediagx_cs5530_bridge_device::map_extra(
+ uint64_t memory_window_start,
+ uint64_t memory_window_end,
+ uint64_t memory_offset,
+ address_space *memory_space,
+ uint64_t io_window_start,
+ uint64_t io_window_end,
+ uint64_t io_offset,
+ address_space *io_space)
+{
+ m_isabus->remap(AS_PROGRAM, 0, 1 << 24);
+ map_bios(memory_space, 0xffffffff - m_region->bytes() + 1, 0xffffffff);
+ // TODO: BIOS window conditions + BIOS ROM
+ if (BIT(m_decode_control[1], 5))
+ LOGMAP("BIOS ROM positive decode\n");
+ map_bios(memory_space, 0x000e0000, 0x000fffff);
+
+ m_isabus->remap(AS_IO, 0, 0xffff);
+ io_space->install_device(0, 0xffff, *this, &mediagx_cs5530_bridge_device::internal_io_map);
+
+ if (BIT(m_decode_control[0], 0))
+ LOGMAP("RTC positive decode $070 & $071\n");
+
+ if (BIT(m_decode_control[0], 1))
+ {
+ LOGMAP("KBDC positive decode $060 & $064 (mailbox $62 & $66 %s)\n", BIT(m_decode_control[1], 7) ? "enabled" : "disabled");
+ }
+
+ if (BIT(m_decode_control[0], 2))
+ LOGMAP("COM1 positive decode $3f8-$3ff\n");
+
+ if (BIT(m_decode_control[0], 3))
+ LOGMAP("COM2 positive decode $2f8-$2ff\n");
+
+ if (BIT(m_decode_control[0], 4))
+ LOGMAP("COM3 positive decode $3e8-$3ef\n");
+
+ if (BIT(m_decode_control[0], 5))
+ LOGMAP("COM4 positive decode $2e8-$2ef\n");
+
+ if (BIT(m_decode_control[0], 6))
+ LOGMAP("Primary FDC positive decode $3f2-$3f5 & $3f7\n");
+
+ if (BIT(m_decode_control[0], 7))
+ LOGMAP("Secondary FDC positive decode $372-$375 & $377\n");
+
+ if (BIT(m_decode_control[1], 0))
+ LOGMAP("LPT1 positive decode $378-$37f & $778-$77a\n");
+
+ if (BIT(m_decode_control[1], 1))
+ LOGMAP("LPT2 positive decode $278-$27f & $678-$67a\n");
+
+ if (BIT(m_decode_control[1], 2))
+ LOGMAP("LPT3 positive decode $3bc-$3be & $7bc-$7be\n");
+
+ if (BIT(m_decode_control[1], 4))
+ {
+ LOGMAP("Secondary IDE positive decode $170-$177 & $376-$377\n");
+ io_space->install_device(0, 0xffff, *m_ide, &mediagx_cs5530_ide_device::secondary_ide_map);
+ }
+
+ if (BIT(m_decode_control[1], 3))
+ {
+ LOGMAP("Primary IDE positive decode $1f0-$1f7 & $3f6-$3f7\n");
+ io_space->install_device(0, 0xffff, *m_ide, &mediagx_cs5530_ide_device::primary_ide_map);
+ }
+}