From 90aa94c9d71014d790833fc83c90539d5e440536 Mon Sep 17 00:00:00 2001 From: angelosa Date: Thu, 14 Dec 2023 00:05:51 +0100 Subject: machine/mediagx_cs5530_bridge.cpp: initial stub for legacy southbridge --- src/devices/machine/mediagx_cs5530_bridge.cpp | 362 ++++++++++++++++++++++++-- src/devices/machine/mediagx_cs5530_bridge.h | 87 ++++++- src/devices/machine/mediagx_host.cpp | 9 + src/mame/misc/matrix.cpp | 23 +- 4 files changed, 460 insertions(+), 21 deletions(-) diff --git a/src/devices/machine/mediagx_cs5530_bridge.cpp b/src/devices/machine/mediagx_cs5530_bridge.cpp index d4ae8ee89bf..5fac539e97b 100644 --- a/src/devices/machine/mediagx_cs5530_bridge.cpp +++ b/src/devices/machine/mediagx_cs5530_bridge.cpp @@ -9,6 +9,8 @@ #include "emu.h" #include "mediagx_cs5530_bridge.h" +#include "speaker.h" + 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) @@ -17,27 +19,98 @@ mediagx_cs5530_bridge_device::mediagx_cs5530_bridge_device(const machine_config // , m_nmi_callback(*this) // , m_stpclk_callback(*this) , m_boot_state_hook(*this) - , m_maincpu(*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_rtcale(*this) + , m_rtccs_read(*this, 0xff) + , m_rtccs_write(*this) + , m_host_cpu(*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") + , 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(isabus.second)->set_memspace(m_maincpu, AS_PROGRAM); - isabus.first.subdevice(isabus.second)->set_iospace(m_maincpu, AS_IO); + isabus.first.subdevice(isabus.second)->set_memspace(m_host_cpu, AS_PROGRAM); + isabus.first.subdevice(isabus.second)->set_iospace(m_host_cpu, AS_IO); pci_device::device_config_complete(); } @@ -48,6 +121,8 @@ void mediagx_cs5530_bridge_device::device_reset() command = 0x0000; status = 0x0280; + + m_nmi_enabled = false; } void mediagx_cs5530_bridge_device::config_map(address_map &map) @@ -58,19 +133,272 @@ void mediagx_cs5530_bridge_device::config_map(address_map &map) 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, 0x003f).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(0x0061, 0x0061).rw(FUNC(mediagx_cs5530_bridge_device::at_portb_r), FUNC(mediagx_cs5530_bridge_device::at_portb_w)); -// map(0x0070, 0x0071) RTC -// map(0x0080, 0x009f).rw(FUNC(mediagx_cs5530_bridge_device::at_page8_r), FUNC(mediagx_cs5530_bridge_device::at_page8_w)); -// map(0x00a0, 0x00bf).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(0x0000, 0x001f).rw("dma8237_1", FUNC(am9517a_device::read), FUNC(am9517a_device::write)); + map(0x0020, 0x003f).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(0x0061, 0x0061).rw(FUNC(mediagx_cs5530_bridge_device::at_portb_r), FUNC(mediagx_cs5530_bridge_device::at_portb_w)); + map(0x0064, 0x0067).nopr(); + 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, 0x009f).rw(FUNC(mediagx_cs5530_bridge_device::at_page8_r), FUNC(mediagx_cs5530_bridge_device::at_page8_w)); + map(0x00a0, 0x00bf).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).noprw(); // 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) +{ + printf("%d %d %d\n",state, m_channel_check, m_nmi_enabled); + 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; diff --git a/src/devices/machine/mediagx_cs5530_bridge.h b/src/devices/machine/mediagx_cs5530_bridge.h index aa450333653..e00dac3357b 100644 --- a/src/devices/machine/mediagx_cs5530_bridge.h +++ b/src/devices/machine/mediagx_cs5530_bridge.h @@ -9,6 +9,10 @@ #include "pci.h" #include "bus/isa/isa.h" +#include "machine/am9517a.h" +#include "machine/pic8259.h" +#include "machine/pit8253.h" +#include "sound/spkrdev.h" class mediagx_cs5530_bridge_device : public pci_device { @@ -24,9 +28,13 @@ public: mediagx_cs5530_bridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto boot_state_hook() { return m_boot_state_hook.bind(); } + auto rtcale() { return m_rtcale.bind(); } + auto rtccs_read() { return m_rtccs_read.bind(); } + auto rtccs_write() { return m_rtccs_write.bind(); } + void pc_irq8n_w(int state); template - void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward(tag)); } + void set_cpu_tag(T &&tag) { m_host_cpu.set_tag(std::forward(tag)); } protected: virtual void device_add_mconfig(machine_config & config) override; virtual void device_config_complete() override; @@ -39,13 +47,88 @@ protected: virtual void config_map(address_map &map) override; private: + void at_pit8254_out0_changed(int state); + void at_pit8254_out1_changed(int state); + void at_pit8254_out2_changed(int state); + uint8_t pc_dma8237_0_dack_r(); + uint8_t pc_dma8237_1_dack_r(); + uint8_t pc_dma8237_2_dack_r(); + uint8_t pc_dma8237_3_dack_r(); + uint8_t pc_dma8237_5_dack_r(); + uint8_t pc_dma8237_6_dack_r(); + uint8_t pc_dma8237_7_dack_r(); + void pc_dma8237_0_dack_w(uint8_t data); + void pc_dma8237_1_dack_w(uint8_t data); + void pc_dma8237_2_dack_w(uint8_t data); + void pc_dma8237_3_dack_w(uint8_t data); + void pc_dma8237_5_dack_w(uint8_t data); + void pc_dma8237_6_dack_w(uint8_t data); + void pc_dma8237_7_dack_w(uint8_t data); + void pc_dack0_w(int state); + void pc_dack1_w(int state); + void pc_dack2_w(int state); + void pc_dack3_w(int state); + void pc_dack4_w(int state); + void pc_dack5_w(int state); + void pc_dack6_w(int state); + void pc_dack7_w(int state); + void at_dma8237_out_eop(int state); + void pc_dma_hrq_changed(int state); + uint8_t pc_dma_read_byte(offs_t offset); + void pc_dma_write_byte(offs_t offset, uint8_t data); + uint8_t pc_dma_read_word(offs_t offset); + void pc_dma_write_word(offs_t offset, uint8_t data); + uint8_t at_portb_r(); + void at_portb_w(uint8_t data); + void at_speaker_set_spkrdata(uint8_t data); + uint8_t get_slave_ack(offs_t offset); + void pc_irq1_w(int state); + void pc_irq3_w(int state); + void pc_irq4_w(int state); + void pc_irq5_w(int state); + void pc_irq6_w(int state); + void pc_irq7_w(int state); + void pc_irq9_w(int state); + void pc_irq10_w(int state); + void pc_irq11_w(int state); + void pc_irq12m_w(int state); + void pc_irq14_w(int state); + void pc_irq15_w(int state); + void iochck_w(int state); + void pc_select_dma_channel(int channel, bool state); + uint8_t at_page8_r(offs_t offset); + void at_page8_w(offs_t offset, uint8_t data); + uint8_t at_dma8237_2_r(offs_t offset); + void at_dma8237_2_w(offs_t offset, uint8_t data); + void map_bios(address_space *memory_space, uint32_t start, uint32_t end); void internal_io_map(address_map &map); devcb_write8 m_boot_state_hook; + devcb_write8 m_rtcale; + devcb_read8 m_rtccs_read; + devcb_write8 m_rtccs_write; - required_device m_maincpu; + required_device m_host_cpu; + required_device m_pic8259_master; + required_device m_pic8259_slave; + required_device m_dma8237_1; + required_device m_dma8237_2; + required_device m_pit8254; required_device m_isabus; + required_device m_speaker; + + uint8_t m_at_spkrdata = 0; + uint8_t m_pit_out2 = 0; + uint8_t m_at_speaker = 0; + bool m_refresh = false; + int m_dma_channel = 0; + bool m_cur_eop = false; + uint8_t m_dma_offset[2][4]; + uint8_t m_at_pages[0x10]{}; + uint16_t m_dma_high_byte = 0; + uint8_t m_channel_check = 0; + bool m_nmi_enabled = false; }; DECLARE_DEVICE_TYPE(MEDIAGX_CS5530_BRIDGE, mediagx_cs5530_bridge_device) diff --git a/src/devices/machine/mediagx_host.cpp b/src/devices/machine/mediagx_host.cpp index c67ba63943f..7d938b28751 100644 --- a/src/devices/machine/mediagx_host.cpp +++ b/src/devices/machine/mediagx_host.cpp @@ -91,4 +91,13 @@ void mediagx_host_device::map_extra( memory_space->install_ram(0x00000000, 0x0009ffff, &m_ram[0x00000000/4]); // memory_space->install_ram(0x000a0000, 0x000bffff, &m_ram[0x000a0000/4]); + // temp + memory_space->install_ram(0x000c0000, 0x000dffff, &m_ram[0x000c0000/4]); + + memory_space->install_ram (0x00100000, 0x00efffff, &m_ram[0x00100000/4]); + // memory hole at 15-16 mbytes + //if(memory_hole_upper) + memory_space->install_ram (0x00f00000, 0x00ffffff, &m_ram[0x00f00000/4]); + + memory_space->install_ram (0x01000000, m_ram_size-1, &m_ram[0x01000000/4]); } diff --git a/src/mame/misc/matrix.cpp b/src/mame/misc/matrix.cpp index 58787e7f178..091b02d916a 100644 --- a/src/mame/misc/matrix.cpp +++ b/src/mame/misc/matrix.cpp @@ -25,6 +25,7 @@ #include "bus/isa/isa_cards.h" #include "cpu/i386/i386.h" +#include "machine/mc146818.h" #include "machine/mediagx_cs5530_bridge.h" #include "machine/mediagx_host.h" #include "machine/pci.h" @@ -38,14 +39,16 @@ class matrix_state : public driver_device { public: matrix_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu") + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_rtc(*this, "rtc") { } void matrix(machine_config &config); private: required_device m_maincpu; + required_device m_rtc; void main_map(address_map &map); }; @@ -64,17 +67,33 @@ void matrix_state::matrix(machine_config &config) // basic machine hardware MEDIAGX(config, m_maincpu, 233'000'000); // Cyrix MediaGX GXm-266GP m_maincpu->set_addrmap(AS_PROGRAM, &matrix_state::main_map); + m_maincpu->set_irq_acknowledge_callback("pci:07.0:pic8259_master", FUNC(pic8259_device::inta_cb)); + + // TODO: from FDC37C93x super I/O + // NOTE: it's not initialized at $3f0 - $370 but accessed anyway, wtf + DS1287(config, m_rtc, 32.768_kHz_XTAL); + m_rtc->set_binary(true); + m_rtc->set_epoch(1980); + m_rtc->irq().set("pci:07.0", FUNC(mediagx_cs5530_bridge_device::pc_irq8n_w)); PCI_ROOT(config, "pci", 0); MEDIAGX_HOST(config, "pci:00.0", 0, "maincpu", 128*1024*1024); + // TODO: no clue about the ID used for this, definitely tested + // Tries to initialize MediaGX F4 -> ISA -> PCI/AGP, failing in all cases + PCI_BRIDGE(config, "pci:01.0", 0, 0x10780000, 0); + //RIVATNT(config, "pci:01.0:00.0", 0); // TODO: unconfirmed PCI space mediagx_cs5530_bridge_device &isa(MEDIAGX_CS5530_BRIDGE(config, "pci:07.0", 0, "maincpu")); isa.boot_state_hook().set([](u8 data) { /* printf("%02x\n", data); */ }); //isa.smi().set_inputline("maincpu", INPUT_LINE_SMI); + isa.rtcale().set([this](u8 data) { m_rtc->address_w(data); }); + isa.rtccs_read().set([this]() { return m_rtc->data_r(); }); + isa.rtccs_write().set([this](u8 data) { m_rtc->data_w(data); }); // TODO: unknown number of ISA slots ISA16_SLOT(config, "isa1", 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false); + } -- cgit v1.2.3