summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2019-02-12 18:09:47 +0700
committer Patrick Mackinlay <pmackinlay@hotmail.com>2019-02-12 18:09:47 +0700
commita035eafdfef3b744d85ab905465e458e0a65eeb6 (patch)
treebf7e3723b169b7fb4c3843209ab4a3fa44ad55cf
parent71c134c887e30f71ad273fc71dbbcf1feec743e2 (diff)
jazz: wip checkpoint (nw)
At this point, jazz can start Windows NT 4.0 from cdrom, but crashes launching the session manager just prior to running setup.
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/machine/i82357.cpp307
-rw-r--r--src/devices/machine/i82357.h91
-rw-r--r--src/mame/drivers/jazz.cpp259
-rw-r--r--src/mame/includes/jazz.h37
-rw-r--r--src/mame/machine/jazz_mct_adr.cpp261
-rw-r--r--src/mame/machine/jazz_mct_adr.h125
8 files changed, 1025 insertions, 68 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index a68236ab223..6d1c8a96ba9 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -3857,3 +3857,15 @@ if (MACHINES["DC7085"]~=null) then
MAME_DIR .. "src/devices/machine/dc7085.h",
}
end
+
+---------------------------------------------------
+--
+--@src/devices/machine/i82357.h,MACHINES["I82357"] = true
+---------------------------------------------------
+
+if (MACHINES["I82357"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/i82357.cpp",
+ MAME_DIR .. "src/devices/machine/i82357.h",
+ }
+end
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 359e714b7aa..3b9fbab4243 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -682,6 +682,7 @@ MACHINES["IOPTIMER"] = true
MACHINES["Z8038"] = true
MACHINES["AIC6250"] = true
MACHINES["DC7085"] = true
+MACHINES["I82357"] = true
--------------------------------------------------
-- specify available bus cores
diff --git a/src/devices/machine/i82357.cpp b/src/devices/machine/i82357.cpp
new file mode 100644
index 00000000000..9b3be9c0905
--- /dev/null
+++ b/src/devices/machine/i82357.cpp
@@ -0,0 +1,307 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * An implementation of the Intel 82357 Integrated System Peripheral.
+ *
+ * This device was one part of the 3-chip Intel 82350 EISA bus chipset.
+ *
+ * Sources:
+ *
+ * http://bitsavers.org/components/intel/_dataBooks/1996_Intel_Peripheral_Components.pdf
+ *
+ * TODO
+ * - expose everything to an actual EISA bus
+ * - 32-bit dma functionality
+ *
+ */
+
+#include "emu.h"
+#include "i82357.h"
+
+#define LOG_GENERAL (1U << 0)
+
+//#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(I82357, i82357_device, "i82357", "Intel 82357 Integrated System Peripheral")
+
+i82357_device::i82357_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, I82357, tag, owner, clock)
+ , m_pic(*this, "pic%u", 0)
+ , m_pit(*this, "pit%u", 0)
+ , m_dma(*this, "dma%u", 0)
+ , m_out_rtc(*this)
+ , m_out_nmi(*this)
+ , m_out_spkr(*this)
+{
+}
+
+void i82357_device::device_add_mconfig(machine_config &config)
+{
+ PIC8259(config, m_pic[0], 0);
+ m_pic[0]->in_sp_callback().set_constant(1);
+ m_pic[0]->read_slave_ack_callback().set(
+ [this](offs_t offset)
+ {
+ if (offset == 2)
+ return m_pic[1]->acknowledge();
+
+ return u32(0);
+ });
+
+ PIC8259(config, m_pic[1], 0);
+ m_pic[1]->out_int_callback().set(m_pic[0], FUNC(pic8259_device::ir2_w));
+ m_pic[1]->in_sp_callback().set_constant(0);
+
+ PIT8254(config, m_pit[0], 0);
+ PIT8254(config, m_pit[1], 0);
+
+ // timer 1 counter 0: system timer
+ m_pit[0]->set_clk<0>(clock() / 12);
+ m_pit[0]->out_handler<0>().set(m_pic[0], FUNC(pic8259_device::ir0_w));
+
+ // timer 1 counter 1: refresh request
+ m_pit[0]->set_clk<1>(clock() / 12);
+ m_pit[0]->out_handler<1>().set(
+ [this](int state)
+ {
+ // FIXME: not accurate, but good enough to pass diagnostic
+ if (state)
+ m_nmi_reg ^= NMI_REFRESH;
+
+ m_pit[1]->write_gate2(state);
+ });
+
+ // timer 1 counter 2: speaker
+ m_pit[0]->set_clk<2>(clock() / 12);
+ m_pit[0]->out_handler<2>().set(
+ [this](int state)
+ {
+ if (state)
+ m_nmi_reg |= NMI_T1C2_STATE;
+ else
+ m_nmi_reg &= ~NMI_T1C2_STATE;
+
+ m_out_spkr((m_nmi_reg & NMI_T1C2_STATE) && (m_nmi_reg & NMI_SPEAKER_DATA));
+ });
+
+ // timer 2 counter 0: fail-safe timer
+ m_pit[1]->set_clk<0>(clock() / 48);
+ m_pit[1]->out_handler<0>().set(
+ [this](int state)
+ {
+ if (state && (m_nmi_ext & NMI_EXT_EN_FAILSAFE))
+ {
+ m_nmi_ext |= NMI_EXT_FAILSAFE;
+
+ m_nmi_check->adjust(attotime::zero);
+ }
+ });
+
+ // timer 2 counter 1: does not exist
+
+ // timer 2 counter 2: cpu speed control
+ m_pit[1]->set_clk<2>(8_MHz_XTAL);
+ //m_pit[1]->out_handler<2>().set();
+
+ EISA_DMA(config, m_dma[0], clock() / 3);
+ EISA_DMA(config, m_dma[1], clock() / 3);
+ m_dma[1]->out_dack_callback<0>().set(m_dma[0], FUNC(eisa_dma_device::hack_w)).invert();
+}
+
+void i82357_device::map(address_map &map)
+{
+ map(0x000, 0x00f).rw(m_dma[0], FUNC(eisa_dma_device::read), FUNC(eisa_dma_device::write));
+ map(0x020, 0x021).rw(m_pic[0], FUNC(pic8259_device::read), FUNC(pic8259_device::write));
+ map(0x040, 0x043).rw(m_pit[0], FUNC(pit8254_device::read), FUNC(pit8254_device::write));
+ map(0x048, 0x04b).rw(m_pit[1], FUNC(pit8254_device::read), FUNC(pit8254_device::write));
+
+ // FIXME: also 0x065 - "NMI Status"
+ map(0x061, 0x061).rw(FUNC(i82357_device::nmi_reg_r), FUNC(i82357_device::nmi_reg_w));
+
+ // NMI Enable Register (0x70, 72, 74, 76)
+ map(0x070, 0x077).lw8("nmi_rtc",
+ [this](address_space &space, offs_t offset, u8 data)
+ {
+ m_nmi_enabled = !BIT(data, 7);
+
+ m_out_rtc(space, 0, data & 0x7f);
+
+ m_nmi_check->adjust(attotime::zero);
+ }).umask64(0xff);
+
+ map(0x081, 0x081).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page<2>), FUNC(eisa_dma_device::set_address_page<2>));
+ map(0x082, 0x082).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page<3>), FUNC(eisa_dma_device::set_address_page<3>));
+ map(0x083, 0x083).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page<1>), FUNC(eisa_dma_device::set_address_page<1>));
+ map(0x087, 0x087).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page<0>), FUNC(eisa_dma_device::set_address_page<0>));
+ map(0x089, 0x089).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page<2>), FUNC(eisa_dma_device::set_address_page<2>));
+ map(0x08a, 0x08a).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page<3>), FUNC(eisa_dma_device::set_address_page<3>));
+ map(0x08b, 0x08b).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page<1>), FUNC(eisa_dma_device::set_address_page<1>));
+ map(0x08f, 0x08f).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page<0>), FUNC(eisa_dma_device::set_address_page<0>));
+
+ // TODO: also 0xa4, a8, ac, b0, b4, b8, bc
+ map(0x0a0, 0x0a1).rw(m_pic[1], FUNC(pic8259_device::read), FUNC(pic8259_device::write));
+ map(0x0c0, 0x0df).rw(m_dma[1], FUNC(eisa_dma_device::read), FUNC(eisa_dma_device::write)).umask16(0x00ff);
+
+ map(0x401, 0x401).rw(m_dma[0], FUNC(eisa_dma_device::get_count_high<0>), FUNC(eisa_dma_device::set_count_high<0>));
+ map(0x403, 0x403).rw(m_dma[0], FUNC(eisa_dma_device::get_count_high<1>), FUNC(eisa_dma_device::set_count_high<1>));
+ map(0x405, 0x405).rw(m_dma[0], FUNC(eisa_dma_device::get_count_high<2>), FUNC(eisa_dma_device::set_count_high<2>));
+ map(0x407, 0x407).rw(m_dma[0], FUNC(eisa_dma_device::get_count_high<3>), FUNC(eisa_dma_device::set_count_high<3>));
+
+ //map(0x40a, 0x40a); // DMA1 Set Chaining Mode (w)/Interrupt Status (r)
+ //map(0x40b, 0x40b); // DMA1 Ext Write Mode (w)
+ //map(0x40c, 0x40c); // Chain Buffer Control
+ //map(0x40d, 0x40d); // Stepping Level Register (ro)
+ //map(0x40e, 0x40e); // ISP Test Register
+ //map(0x40f, 0x40f); // ISP Test Register
+
+ map(0x461, 0x461).rw(FUNC(i82357_device::nmi_ext_r), FUNC(i82357_device::nmi_ext_w));
+ map(0x462, 0x462).lw8("nmi_ioport",
+ [this](u8 data)
+ {
+ if (m_nmi_ext & NMI_EXT_EN_IOPORT)
+ {
+ m_nmi_ext |= NMI_EXT_IOPORT;
+
+ m_nmi_check->adjust(attotime::zero);
+ }
+ });
+ //map(0x464, 0x464); // Last 32-bit bus master granted (L)
+
+ map(0x481, 0x481).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page_high<2>), FUNC(eisa_dma_device::set_address_page_high<2>));
+ map(0x482, 0x482).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page_high<3>), FUNC(eisa_dma_device::set_address_page_high<3>));
+ map(0x483, 0x483).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page_high<1>), FUNC(eisa_dma_device::set_address_page_high<1>));
+ map(0x487, 0x487).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page_high<0>), FUNC(eisa_dma_device::set_address_page_high<0>));
+ map(0x489, 0x489).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page_high<2>), FUNC(eisa_dma_device::set_address_page_high<2>));
+ map(0x48a, 0x48a).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page_high<3>), FUNC(eisa_dma_device::set_address_page_high<3>));
+ map(0x48b, 0x48b).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page_high<1>), FUNC(eisa_dma_device::set_address_page_high<1>));
+ map(0x48f, 0x48f).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page_high<0>), FUNC(eisa_dma_device::set_address_page_high<0>));
+
+ map(0x4c2, 0x4c2).rw(m_dma[1], FUNC(eisa_dma_device::get_count_high<0>), FUNC(eisa_dma_device::set_count_high<0>));
+ map(0x4c6, 0x4c6).rw(m_dma[1], FUNC(eisa_dma_device::get_count_high<1>), FUNC(eisa_dma_device::set_count_high<1>));
+ map(0x4ca, 0x4ca).rw(m_dma[1], FUNC(eisa_dma_device::get_count_high<2>), FUNC(eisa_dma_device::set_count_high<2>));
+ map(0x4ce, 0x4ce).rw(m_dma[1], FUNC(eisa_dma_device::get_count_high<3>), FUNC(eisa_dma_device::set_count_high<3>));
+ map(0x4d0, 0x4d1).lrw8("elcr",
+ [this](offs_t offset) { return m_elcr[offset]; },
+ [this](offs_t offset, u8 data) { m_elcr[offset] = data; });
+
+ //map(0x4d4, 0x4d4); // DMA2 Set Chaining Mode
+ //map(0x4d6, 0x4d6); // DMA2 Ext Write Mode Register
+
+ map(0x4e0, 0x4e3).rw(m_dma[0], FUNC(eisa_dma_device::get_stop<0>), FUNC(eisa_dma_device::set_stop<0>));
+ map(0x4e4, 0x4e7).rw(m_dma[0], FUNC(eisa_dma_device::get_stop<1>), FUNC(eisa_dma_device::set_stop<1>));
+ map(0x4e8, 0x4eb).rw(m_dma[0], FUNC(eisa_dma_device::get_stop<2>), FUNC(eisa_dma_device::set_stop<2>));
+ map(0x4ec, 0x4ef).rw(m_dma[0], FUNC(eisa_dma_device::get_stop<3>), FUNC(eisa_dma_device::set_stop<3>));
+
+ map(0x4f0, 0x4f3).rw(m_dma[1], FUNC(eisa_dma_device::get_stop<0>), FUNC(eisa_dma_device::set_stop<0>)); // reserved
+ map(0x4f4, 0x4f7).rw(m_dma[1], FUNC(eisa_dma_device::get_stop<1>), FUNC(eisa_dma_device::set_stop<1>));
+ map(0x4f8, 0x4fb).rw(m_dma[1], FUNC(eisa_dma_device::get_stop<2>), FUNC(eisa_dma_device::set_stop<2>));
+ map(0x4fc, 0x4ff).rw(m_dma[1], FUNC(eisa_dma_device::get_stop<3>), FUNC(eisa_dma_device::set_stop<3>));
+}
+
+void i82357_device::device_start()
+{
+ m_out_rtc.resolve_safe();
+ m_out_nmi.resolve_safe();
+ m_out_spkr.resolve_safe();
+
+ m_nmi_check = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(i82357_device::nmi_check), this));
+}
+
+void i82357_device::device_reset()
+{
+ m_elcr[0] = 0;
+ m_elcr[1] = 0;
+
+ m_nmi_enabled = true;
+ m_nmi_reg = 0;
+ m_nmi_ext = 0;
+
+ m_nmi_check->adjust(attotime::zero);
+}
+
+void i82357_device::nmi_reg_w(u8 data)
+{
+ m_pit[0]->write_gate2(!!(data & NMI_T1C2_GATE));
+
+ // clear parity nmi
+ if (data & NMI_PARITY_DISABLE)
+ m_nmi_reg &= ~NMI_PARITY;
+
+ // clear iochk nmi
+ if (data & NMI_IOCHK_DISABLE)
+ m_nmi_reg &= ~NMI_IOCHK;
+
+ m_nmi_reg = (m_nmi_reg & ~NMI_WMASK) | (data & NMI_WMASK);
+
+ // update speaker state
+ m_out_spkr((m_nmi_reg & NMI_T1C2_STATE) && (m_nmi_reg & NMI_SPEAKER_DATA));
+
+ m_nmi_check->adjust(attotime::zero);
+}
+
+void i82357_device::nmi_ext_w(u8 data)
+{
+ if (!(data & NMI_EXT_EN_IOPORT))
+ m_nmi_ext &= ~NMI_EXT_IOPORT;
+
+ if (!(data & NMI_EXT_EN_TIMEOUT))
+ m_nmi_ext &= ~NMI_EXT_TIMEOUT;
+
+ if (!(data & NMI_EXT_EN_FAILSAFE))
+ m_nmi_ext &= ~NMI_EXT_FAILSAFE;
+
+ m_nmi_ext = (m_nmi_ext & ~NMI_EXT_WMASK) | (data & NMI_EXT_WMASK);
+
+ m_nmi_check->adjust(attotime::zero);
+}
+
+WRITE_LINE_MEMBER(i82357_device::in_iochk)
+{
+ if (!state && !(m_nmi_reg & NMI_PARITY_DISABLE))
+ {
+ m_nmi_reg |= NMI_IOCHK;
+
+ m_nmi_check->adjust(attotime::zero);
+ }
+ else
+ m_nmi_reg &= ~NMI_IOCHK;
+}
+
+WRITE_LINE_MEMBER(i82357_device::in_parity)
+{
+ if (!state && !(m_nmi_reg & NMI_IOCHK_DISABLE))
+ {
+ m_nmi_reg |= NMI_PARITY;
+
+ m_nmi_check->adjust(attotime::zero);
+ }
+ else
+ m_nmi_reg &= ~NMI_PARITY;
+}
+
+TIMER_CALLBACK_MEMBER(i82357_device::nmi_check)
+{
+ if (m_nmi_enabled)
+ {
+ if ((m_nmi_reg & NMI_NMI) || (m_nmi_ext & NMI_EXT_NMI))
+ {
+ if (!m_out_nmi_asserted)
+ {
+ m_out_nmi_asserted = true;
+ m_out_nmi(1);
+ }
+
+ return;
+ }
+ }
+
+ // disabled or no source
+ if (m_out_nmi_asserted)
+ {
+ m_out_nmi_asserted = false;
+ m_out_nmi(0);
+ }
+}
diff --git a/src/devices/machine/i82357.h b/src/devices/machine/i82357.h
new file mode 100644
index 00000000000..3c5a7756061
--- /dev/null
+++ b/src/devices/machine/i82357.h
@@ -0,0 +1,91 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_MACHINE_I82357_H
+#define MAME_MACHINE_I82357_H
+
+#pragma once
+
+#include "machine/pic8259.h"
+#include "machine/pit8253.h"
+#include "machine/am9517a.h"
+
+class i82357_device : public device_t
+{
+public:
+ i82357_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ auto out_rtc_cb() { return m_out_rtc.bind(); }
+ auto out_int_cb() { return subdevice<pic8259_device>("pic0")->out_int_callback(); }
+ auto out_nmi_cb() { return m_out_nmi.bind(); }
+ auto out_spkr_cb() { return m_out_spkr.bind(); }
+
+ u32 eisa_irq_ack() { return m_pic[0]->acknowledge(); }
+
+ DECLARE_WRITE_LINE_MEMBER(in_iochk);
+ DECLARE_WRITE_LINE_MEMBER(in_parity);
+
+ void map(address_map &map);
+
+protected:
+ // standard device_t overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ void nmi_reg_w(u8 data);
+ void nmi_ext_w(u8 data);
+ u8 nmi_reg_r() { return m_nmi_reg; }
+ u8 nmi_ext_r() { return m_nmi_ext; }
+
+ TIMER_CALLBACK_MEMBER(nmi_check);
+
+private:
+ required_device_array<pic8259_device, 2> m_pic;
+ required_device_array<pit8254_device, 2> m_pit;
+ required_device_array<eisa_dma_device, 2> m_dma;
+
+ devcb_write8 m_out_rtc;
+ devcb_write_line m_out_nmi;
+ devcb_write_line m_out_spkr;
+
+ enum nmi_reg_mask : u8
+ {
+ NMI_T1C2_GATE = 0x01,
+ NMI_SPEAKER_DATA = 0x02,
+ NMI_PARITY_DISABLE = 0x04,
+ NMI_IOCHK_DISABLE = 0x08,
+ NMI_REFRESH = 0x10,
+ NMI_T1C2_STATE = 0x20,
+ NMI_IOCHK = 0x40,
+ NMI_PARITY = 0x80,
+
+ NMI_WMASK = 0x0f,
+ NMI_NMI = 0xc0,
+ };
+ enum nmi_ext_mask : u8
+ {
+ NMI_EXT_BUS_RESET = 0x01, // bus reset (read/write)
+ NMI_EXT_EN_IOPORT = 0x02,
+ NMI_EXT_EN_FAILSAFE = 0x04,
+ NMI_EXT_EN_TIMEOUT = 0x08,
+ NMI_EXT_8US_TIMEOUT = 0x10, // 8us EISA bus master timeout occurred
+ NMI_EXT_IOPORT = 0x20, // NMI I/O port interrupt pending
+ NMI_EXT_TIMEOUT = 0x40, // EISA bus master timeout occurred, NMI requested
+ NMI_EXT_FAILSAFE = 0x80, // Fail-safe timer is active, NMI requested
+
+ NMI_EXT_WMASK = 0x0f,
+ NMI_EXT_NMI = 0xe0,
+ };
+ u8 m_elcr[2];
+
+ emu_timer *m_nmi_check;
+ bool m_out_nmi_asserted;
+ bool m_nmi_enabled;
+ u8 m_nmi_reg;
+ u8 m_nmi_ext;
+};
+
+DECLARE_DEVICE_TYPE(I82357, i82357_device)
+
+#endif // MAME_MACHINE_I82357_H
diff --git a/src/mame/drivers/jazz.cpp b/src/mame/drivers/jazz.cpp
index 4a8d5a52d84..a0b78f504b7 100644
--- a/src/mame/drivers/jazz.cpp
+++ b/src/mame/drivers/jazz.cpp
@@ -13,7 +13,10 @@
* http://www.sensi.org/~alec/mips/mips-history.html
*
* TODO
- * - everything (skeleton only)
+ * - make it boot Windows NT
+ * - big-endian support for RISC/os
+ * - EISA bus and slots
+ * - slotify and improve graphics board
*
* Unconfirmed parts lists from ARCSystem reference design (which appears to
* be very similar or identical to the Jazz system) taken from:
@@ -69,35 +72,110 @@ void jazz_state::machine_reset()
void jazz_state::init_common()
{
- // map the configured ram
- m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram->mask(), m_ram->pointer());
+ // map the configured ram and vram
+ m_cpu->space(0).install_ram(0x00000000, 0x00000000 | m_ram->mask(), m_ram->pointer());
+ m_cpu->space(0).install_ram(0x40000000, 0x40000000 | m_vram->mask(), m_vram->pointer());
}
void jazz_state::jazz_common_map(address_map &map)
{
map(0x1fc00000, 0x1fc3ffff).r(m_flash, FUNC(amd_28f020_device::read));
- // FIXME: lots of guesswork and assumptions here for now
+ map(0x40000000, 0x407fffff).ram().share("vram"); // local video memory
+ map(0x60000000, 0x6000013f).lr8("video_rom",
+ [](offs_t offset)
+ {
+ /*
+ * Board_Identifier, PROM_Stride, PROM_Width, PROM_Size
+ * 0=JazzVideoG300, 1=JazzVideoG364, 2=JazzVideoVxl, 0x10=MipsVideoG364, 0x11=MaximumJazzVideo (jazzvideog364 osc period == 123077, MipsVideoG364 = 200000)
+ * Test_Byte_0 - Test_Byte_3
+ * VideoMemorySize, VideoControlSize
+ * CodeOffset, CodeSize
+ * ID string
+ */
+ /*
+ static u8 const jazz_g364[] =
+ {
+ 0x01, 0x08, 0x01, 0x20, 'J', 'a', 'z', 'z',
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 'J', 'a', 'z', 'z', ' ', 'G', '3', '6',
+ '4', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ static u8 const mips_g364[] =
+ {
+ 0x10, 0x08, 0x01, 0x20, 'J', 'a', 'z', 'z',
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 'M', 'i', 'p', 's', ' ', 'G', '3', '6',
+ '4', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ */
+
+ static u8 const bogus_g364[] =
+ {
+ 0x10, 0x00, 0x00, 0x00, 'J', 'a', 'z', 'z',
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 'M', 'i', 'p', 's', ' ', 'G', '3', '6',
+ '4', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ return bogus_g364[offset];
+ }).umask64(0xff);
+
+ map(0x60080000, 0x60081fff).m(m_ramdac, FUNC(g364_device::map)); // local video control
+ map(0x60180000, 0x60180007).lw32("g364_reset", [this](u32 data) { m_ramdac->reset(); });
+
map(0x80000000, 0x80000fff).m(m_mct_adr, FUNC(jazz_mct_adr_device::map));
- map(0x80001000, 0x80001fff).m(m_network, FUNC(dp83932c_device::map));
- //map(0x80002000, 0x80002fff).m(m_scsi, FUNC(ncr5390_device::map)).umask32(0x000000ff);
- map(0x80003000, 0x80003fff).m(m_fdc, FUNC(n82077aa_device::map));
- //map(0x80004000, 0x80004fff).rw(m_rtc, FUNC(mc146818_device::read), FUNC(mc146818_device::write));
- //map(0x80005000, 0x80005fff).m() // keyboard/mouse
- //map(0x80006000, 0x80006fff).m() // serial1
- //map(0x80007000, 0x80007fff).m() // serial2
- //map(0x80008000, 0x80008fff).m() // parallel
- map(0x80009000, 0x80009fff).ram().share("nvram"); // unprotected?
- map(0x8000a000, 0x8000afff).ram().share("nvram"); // protected?
- map(0x8000b000, 0x8000bfff).ram().share("nvram"); // read-only? also sonic IO access?
+
+ map(0x80001000, 0x800010ff).m(m_network, FUNC(dp83932c_device::map)).umask32(0x0000ffff);
+ map(0x80002000, 0x8000200f).m(m_scsi, FUNC(ncr53c94_device::map));
+ map(0x80003000, 0x8000300f).m(m_fdc, FUNC(n82077aa_device::map));
+ map(0x80004000, 0x80004007).lrw8("rtc",
+ [this](address_space &space, offs_t offset) { return m_rtc->read(space, 1); },
+ [this](address_space &space, offs_t offset, u8 data) { m_rtc->write(space, 1, data); }).umask64(0xff);
+ map(0x80005000, 0x80005007).rw(m_kbdc, FUNC(at_keyboard_controller_device::data_r), FUNC(at_keyboard_controller_device::data_w)).umask64(0x00ff);
+ map(0x80005000, 0x80005007).rw(m_kbdc, FUNC(at_keyboard_controller_device::status_r), FUNC(at_keyboard_controller_device::command_w)).umask64(0xff00);
+ map(0x80006000, 0x80006007).rw(m_ace[0], FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w));
+ map(0x80007000, 0x80007007).rw(m_ace[1], FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w));
+ map(0x80008000, 0x80008007).rw(m_lpt, FUNC(pc_lpt_device::read), FUNC(pc_lpt_device::write)).umask64(0xffffffff);
+ map(0x80009000, 0x8000afff).ram().share("nvram"); // 9000-9fff unprotected/a000-afff protected?
+ map(0x8000b000, 0x8000b007).lr8("mac", [this](offs_t offset)
+ {
+ // mac address and checksum
+ static u8 const mac[] = { 0x00, 0x00, 0x6b, 0x12, 0x34, 0x56, 0x00, 0xf7 };
+
+ return mac[offset];
+ });
+ // 3 4k pages of nvram: read/write, protected, read-only
+ // last page holds ethernet mac and checksum in bytes 0-7
+
//map(0x8000c000, 0x8000cfff) // sound
- map(0x8000d000, 0x8000dfff).noprw(); // dummy dma device?
+ //map(0x8000d000, 0x8000dfff).noprw(); // dummy dma device?
+ map(0x8000d600, 0x8000d607).nopw();
+
+ map(0x8000f000, 0x8000f007).lrw8(
+ "led",
+ [this]() { return m_led; },
+ [this](u8 data)
+ {
+ logerror("led 0x%02x (%s)\n", data, machine().describe_context());
+ m_led = data;
+ }).umask64(0xff);
- map(0x8000f000, 0x8000f001).rw(FUNC(jazz_state::led_r), FUNC(jazz_state::led_w));
+ // lots of byte data written to 800
+ //map(0x800e0000, 0x800fffff).m() // dram config
- //map(0x800e0000, 0x800e0000).rw(FUNC(jazz_state::dram_config_r), FUNC(jazz_state::dram_config_w));
+ map(0x90000000, 0x90ffffff).m(m_isp, FUNC(i82357_device::map));
- map(0xe0800000, 0xe0bfffff).ram().share("vram"); // framebuffer?
+ //map(0x91000000, 0x91ffffff).m();
+ //map(0x92000000, 0x92ffffff).m(); // EISA I/O ports?
+ //map(0x93000000, 0x93ffffff).m(); // EISA memory
+
+ map(0xf0000000, 0xf0000007).r(m_mct_adr, FUNC(jazz_mct_adr_device::isr_r)).umask64(0xffff);
+ map(0xf0000000, 0xf0000007).rw(m_mct_adr, FUNC(jazz_mct_adr_device::imr_r), FUNC(jazz_mct_adr_device::imr_w)).umask64(0xffff0000);
map(0xfff00000, 0xfff3ffff).r(m_flash, FUNC(amd_28f020_device::read)); // mirror?
}
@@ -108,46 +186,62 @@ static void jazz_scsi_devices(device_slot_interface &device)
device.option_add("cdrom", NSCSI_CDROM);
}
+FLOPPY_FORMATS_MEMBER(jazz_state::floppy_formats)
+ FLOPPY_PC_FORMAT
+FLOPPY_FORMATS_END
+
void jazz_state::jazz(machine_config &config)
{
- m_maincpu->set_addrmap(AS_PROGRAM, &jazz_state::jazz_common_map);
+ R4000(config, m_cpu, 50_MHz_XTAL);
+ m_cpu->set_addrmap(0, &jazz_state::jazz_common_map);
- RAM(config, m_ram, 0);
- m_ram->set_default_size("8M");
- m_ram->set_extra_options("16M,32M,64M,128M,256M");
+ RAM(config, m_ram);
+ m_ram->set_default_size("16M");
+ m_ram->set_extra_options("32M,64M,128M,256M");
m_ram->set_default_value(0);
RAM(config, m_vram);
m_vram->set_default_size("2M");
m_vram->set_default_value(0);
- // FIXME: may require big and little endian variants
+ // local bus dma, timer and interrupt controller
JAZZ_MCT_ADR(config, m_mct_adr, 0);
+ m_mct_adr->set_bus(m_cpu, 0);
+ m_mct_adr->out_int_dma_cb().set_inputline(m_cpu, INPUT_LINE_IRQ0);
+ m_mct_adr->out_int_device_cb().set_inputline(m_cpu, INPUT_LINE_IRQ1);
+ m_mct_adr->out_int_timer_cb().set_inputline(m_cpu, INPUT_LINE_IRQ4);
+ m_mct_adr->eisa_iack_cb().set(m_isp, FUNC(i82357_device::eisa_irq_ack));
// scsi bus and devices
- NSCSI_BUS(config, m_scsibus, 0);
-
- nscsi_connector &harddisk(NSCSI_CONNECTOR(config, "scsi:0", 0));
- jazz_scsi_devices(harddisk);
- harddisk.set_default_option("harddisk");
+ NSCSI_BUS(config, m_scsibus);
+ NSCSI_CONNECTOR(config, "scsi:0", jazz_scsi_devices, "harddisk");
+ NSCSI_CONNECTOR(config, "scsi:1", jazz_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", jazz_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", jazz_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", jazz_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", jazz_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", jazz_scsi_devices, "cdrom");
- nscsi_connector &cdrom(NSCSI_CONNECTOR(config, "scsi:6", 0));
- jazz_scsi_devices(cdrom);
- cdrom.set_default_option("cdrom");
+ // scsi host adapter
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr53c94", NCR53C94).clock(24_MHz_XTAL).machine_config(
+ [this](device_t *device)
+ {
+ ncr53c94_device &adapter = downcast<ncr53c94_device &>(*device);
- jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:1", 0));
- jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:2", 0));
- jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:3", 0));
- jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:4", 0));
- jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:5", 0));
+ adapter.irq_handler_cb().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<5>));;
+ adapter.drq_handler_cb().set(m_mct_adr, FUNC(jazz_mct_adr_device::drq<0>));
- // scsi host adapter
- nscsi_connector &adapter(NSCSI_CONNECTOR(config, "scsi:7", 0));
- adapter.option_add_internal("host", NCR53C90A);
- adapter.set_default_option("host");
- adapter.set_fixed(true);
+ subdevice<jazz_mct_adr_device>(":mct_adr")->dma_r_cb<0>().set(adapter, FUNC(ncr53c94_device::dma_r));
+ subdevice<jazz_mct_adr_device>(":mct_adr")->dma_w_cb<0>().set(adapter, FUNC(ncr53c94_device::dma_w));
+ });
+ // floppy controller and drive
N82077AA(config, m_fdc, 24_MHz_XTAL);
+ m_fdc->intrq_wr_callback().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<1>));
+ m_fdc->drq_wr_callback().set(m_mct_adr, FUNC(jazz_mct_adr_device::drq<1>));
+ FLOPPY_CONNECTOR(config, "fdc:0", "35hd", FLOPPY_35_HD, true, jazz_state::floppy_formats).enable_sound(false);
+ m_mct_adr->dma_r_cb<1>().set(m_fdc, FUNC(n82077aa_device::dma_r));
+ m_mct_adr->dma_w_cb<1>().set(m_fdc, FUNC(n82077aa_device::dma_w));
MC146818(config, m_rtc, 32.768_kHz_XTAL);
@@ -155,57 +249,112 @@ void jazz_state::jazz(machine_config &config)
AMD_28F020(config, m_flash);
- // pc keyboard controller?
+ // pc keyboard connector
pc_kbdc_device &kbdc(PC_KBDC(config, "pc_kbdc", 0));
- kbdc.out_clock_cb().set(m_kbdc, FUNC(at_keyboard_controller_device::kbd_clk_w));
- kbdc.out_data_cb().set(m_kbdc, FUNC(at_keyboard_controller_device::kbd_data_w));
+ kbdc.out_clock_cb().set(m_kbdc, FUNC(ps2_keyboard_controller_device::kbd_clk_w));
+ kbdc.out_data_cb().set(m_kbdc, FUNC(ps2_keyboard_controller_device::kbd_data_w));
// keyboard port
pc_kbdc_slot_device &kbd(PC_KBDC_SLOT(config, "kbd", 0));
pc_at_keyboards(kbd);
- kbd.set_default_option(STR_KBD_IBM_PC_AT_84);
+ kbd.set_default_option(STR_KBD_MICROSOFT_NATURAL);
kbd.set_pc_kbdc_slot(&kbdc);
- // at keyboard controller
- AT_KEYBOARD_CONTROLLER(config, m_kbdc, 12_MHz_XTAL);
- m_kbdc->hot_res().set_inputline(m_maincpu, INPUT_LINE_RESET);
+ // keyboard controller
+ PS2_KEYBOARD_CONTROLLER(config, m_kbdc, 12_MHz_XTAL);
+ //m_kbdc->hot_res().set_inputline(m_cpu, INPUT_LINE_RESET);
+ m_kbdc->hot_res().set([this](int state) { if (!state) m_cpu->reset(); });
m_kbdc->kbd_clk().set(kbdc, FUNC(pc_kbdc_device::clock_write_from_mb));
m_kbdc->kbd_data().set(kbdc, FUNC(pc_kbdc_device::data_write_from_mb));
+ m_kbdc->kbd_irq().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<6>));;
+
+ //m_kbdc->mouse_clk().set();
+ //m_kbdc->mouse_data().set();
+ m_kbdc->mouse_irq().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<7>));
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(78643200, 1280, 0, 1280, 1024, 0, 1024);
m_screen->set_screen_update("g364", FUNC(g364_device::screen_update));
+ m_screen->screen_vblank().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<3>)); // maybe?
G364(config, m_ramdac, 5_MHz_XTAL); // FIXME: guessed clock
m_ramdac->set_screen(m_screen);
m_ramdac->set_vram(m_vram);
+ // WD16C552 (two 16550 + pc_lpt)
+ NS16550(config, m_ace[0], 4233600);
+ rs232_port_device &serial0(RS232_PORT(config, "serial0", default_rs232_devices, nullptr));
+
+ m_ace[0]->out_dtr_callback().set(serial0, FUNC(rs232_port_device::write_dtr));
+ m_ace[0]->out_rts_callback().set(serial0, FUNC(rs232_port_device::write_rts));
+ m_ace[0]->out_tx_callback().set(serial0, FUNC(rs232_port_device::write_txd));
+ m_ace[0]->out_int_callback().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<8>));
+
+ serial0.cts_handler().set(m_ace[0], FUNC(ns16550_device::cts_w));
+ serial0.dcd_handler().set(m_ace[0], FUNC(ns16550_device::dcd_w));
+ serial0.dsr_handler().set(m_ace[0], FUNC(ns16550_device::dsr_w));
+ serial0.ri_handler().set(m_ace[0], FUNC(ns16550_device::ri_w));
+ serial0.rxd_handler().set(m_ace[0], FUNC(ns16550_device::rx_w));
+
+ NS16550(config, m_ace[1], 8_MHz_XTAL);
+ rs232_port_device &serial1(RS232_PORT(config, "serial1", default_rs232_devices, nullptr));
+
+ m_ace[1]->out_dtr_callback().set(serial1, FUNC(rs232_port_device::write_dtr));
+ m_ace[1]->out_rts_callback().set(serial1, FUNC(rs232_port_device::write_rts));
+ m_ace[1]->out_tx_callback().set(serial1, FUNC(rs232_port_device::write_txd));
+ m_ace[1]->out_int_callback().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<9>));
+
+ serial1.cts_handler().set(m_ace[1], FUNC(ns16550_device::cts_w));
+ serial1.dcd_handler().set(m_ace[1], FUNC(ns16550_device::dcd_w));
+ serial1.dsr_handler().set(m_ace[1], FUNC(ns16550_device::dsr_w));
+ serial1.ri_handler().set(m_ace[1], FUNC(ns16550_device::ri_w));
+ serial1.rxd_handler().set(m_ace[1], FUNC(ns16550_device::rx_w));
+
+ PC_LPT(config, m_lpt, 0);
+ m_lpt->irq_handler().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<0>));
+
+ // TODO: sound, interrupt 2, drq 2(l) & 3(r)
+
+ // buzzer
+ SPEAKER(config, "mono").front_center();
+ SPEAKER_SOUND(config, m_buzzer);
+ m_buzzer->add_route(ALL_OUTPUTS, "mono", 0.50);
+
DP83932C(config, m_network, 20_MHz_XTAL);
+ m_network->out_int_cb().set(m_mct_adr, FUNC(jazz_mct_adr_device::irq<4>));
m_network->set_ram(RAM_TAG);
+
+ I82357(config, m_isp, 14.318181_MHz_XTAL);
+ m_isp->out_rtc_cb().set(m_rtc, FUNC(mc146818_device::write));
+ m_isp->out_int_cb().set_inputline(m_cpu, INPUT_LINE_IRQ2);
+ m_isp->out_nmi_cb().set_inputline(m_cpu, INPUT_LINE_IRQ3);
+ m_isp->out_spkr_cb().set(m_buzzer, FUNC(speaker_sound_device::level_w));
+
+ // TODO: 4 EISA slots
}
void jazz_state::mmr4000be(machine_config &config)
{
- R4000BE(config, m_maincpu, 50_MHz_XTAL);
-
jazz(config);
+
+ m_cpu->set_config(r4000_device::CONFIG_BE, r4000_device::CONFIG_BE);
}
void jazz_state::mmr4000le(machine_config &config)
{
- R4000LE(config, m_maincpu, 50_MHz_XTAL);
-
jazz(config);
+
+ m_cpu->set_config(0, r4000_device::CONFIG_BE);
}
ROM_START(mmr4000be)
- ROM_REGION32_BE(0x40000, "flash", 0)
+ ROM_REGION64_BE(0x40000, "flash", 0)
ROM_SYSTEM_BIOS(0, "riscos", "R4000 RISC/os PROM")
ROMX_LOAD("riscos.bin", 0x00000, 0x40000, CRC(cea6bc8f) SHA1(3e47b4ad5d1a0c7aac649e6aef3df1bf86fc938b), ROM_BIOS(0))
ROM_END
ROM_START(mmr4000le)
- ROM_REGION32_LE(0x40000, "flash", 0)
+ ROM_REGION64_LE(0x40000, "flash", 0)
ROM_SYSTEM_BIOS(0, "ntprom", "R4000 Windows NT PROM")
ROMX_LOAD("ntprom.bin", 0x00000, 0x40000, CRC(d91018d7) SHA1(316de17820192c89b8ee6d9936ab8364a739ca53), ROM_BIOS(0))
ROM_END
diff --git a/src/mame/includes/jazz.h b/src/mame/includes/jazz.h
index 3bf5e801908..a3274d07526 100644
--- a/src/mame/includes/jazz.h
+++ b/src/mame/includes/jazz.h
@@ -6,7 +6,7 @@
#pragma once
-#include "cpu/mips/mips3.h"
+#include "cpu/mips/r4000.h"
// memory
#include "machine/ram.h"
@@ -17,14 +17,21 @@
#include "machine/jazz_mct_adr.h"
#include "machine/dp83932c.h"
#include "machine/mc146818.h"
+#include "machine/ins8250.h"
#include "machine/ncr5390.h"
#include "machine/upd765.h"
#include "machine/at_keybc.h"
+#include "machine/pc_lpt.h"
+#include "machine/i82357.h"
// video
#include "screen.h"
#include "video/ims_cvc.h"
+// audio
+#include "sound/spkrdev.h"
+#include "speaker.h"
+
// busses and connectors
#include "machine/nscsi_bus.h"
#include "machine/nscsi_cd.h"
@@ -33,17 +40,20 @@
#include "bus/pc_kbd/pc_kbdc.h"
#include "bus/pc_kbd/keyboards.h"
+#include "imagedev/floppy.h"
+#include "formats/pc_dsk.h"
+
class jazz_state : public driver_device
{
public:
jazz_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
- , m_maincpu(*this, "cpu")
+ , m_cpu(*this, "cpu")
, m_ram(*this, "ram")
, m_vram(*this, "vram")
, m_mct_adr(*this, "mct_adr")
, m_scsibus(*this, "scsi")
- , m_scsi(*this, "scsi:7:host")
+ , m_scsi(*this, "scsi:7:ncr53c94")
, m_fdc(*this, "fdc")
, m_rtc(*this, "rtc")
, m_nvram(*this, "nvram")
@@ -52,6 +62,10 @@ public:
, m_network(*this, "net")
, m_screen(*this, "screen")
, m_ramdac(*this, "g364")
+ , m_ace(*this, "ace%u", 0)
+ , m_lpt(*this, "lpt")
+ , m_isp(*this, "isp")
+ , m_buzzer(*this, "buzzer")
{
}
@@ -65,32 +79,35 @@ protected:
// machine config
void jazz(machine_config &config);
+
public:
void mmr4000be(machine_config &config);
void mmr4000le(machine_config &config);
void init_common();
+ DECLARE_FLOPPY_FORMATS(floppy_formats);
+
protected:
// devices
- required_device<mips3_device> m_maincpu;
+ required_device<r4000_device> m_cpu;
required_device<ram_device> m_ram;
required_device<ram_device> m_vram;
required_device<jazz_mct_adr_device> m_mct_adr;
required_device<nscsi_bus_device> m_scsibus;
- required_device<ncr5390_device> m_scsi;
+ required_device<ncr53c94_device> m_scsi;
required_device<n82077aa_device> m_fdc;
required_device<mc146818_device> m_rtc;
required_device<nvram_device> m_nvram;
required_device<amd_28f020_device> m_flash;
- required_device<at_keyboard_controller_device> m_kbdc;
+ required_device<ps2_keyboard_controller_device> m_kbdc;
required_device<dp83932c_device> m_network;
required_device<screen_device> m_screen;
required_device<g364_device> m_ramdac;
-
- // helpers
- u8 led_r() { return m_led; }
- void led_w(const u8 data) { logerror("led 0x%02x\n", data); m_led = data; }
+ required_device_array<ns16550_device, 2> m_ace;
+ required_device<pc_lpt_device> m_lpt;
+ required_device<i82357_device> m_isp;
+ required_device<speaker_sound_device> m_buzzer;
private:
// machine state
diff --git a/src/mame/machine/jazz_mct_adr.cpp b/src/mame/machine/jazz_mct_adr.cpp
index e14075f3f3f..1ae2c109d2b 100644
--- a/src/mame/machine/jazz_mct_adr.cpp
+++ b/src/mame/machine/jazz_mct_adr.cpp
@@ -20,7 +20,10 @@
* http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/arc/jazz/
*
* TODO
- * - everything (skeleton only)
+ * - proper width dma
+ * - dma address translation errors
+ * - I/O cache
+ * - revision 2 device
*/
#include "emu.h"
@@ -33,19 +36,271 @@ DEFINE_DEVICE_TYPE(JAZZ_MCT_ADR, jazz_mct_adr_device, "jazz_mct_adr", "Jazz MCT-
jazz_mct_adr_device::jazz_mct_adr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, JAZZ_MCT_ADR, tag, owner, clock)
+ , m_bus(*this, finder_base::DUMMY_TAG, -1, 64)
+ , m_out_int_dma(*this)
+ , m_out_int_device(*this)
+ , m_out_int_timer(*this)
+ , m_eisa_iack(*this)
+ , m_dma_r{ *this, *this, *this, *this }
+ , m_dma_w{ *this, *this, *this, *this }
{
}
void jazz_mct_adr_device::map(address_map &map)
{
- map(0x000, 0x003).lr32("config", [](){ return 0x00000000; });
- map(0x008, 0x00b).lr32("revision", [](){ return 0xf0000000; });
+ map(0x000, 0x007).lrw32("configuration", [this](){ return m_config; }, [this](u32 data) { m_config = data; });
+ map(0x008, 0x00f).lr32("revision_level", [](){ return 1; });
+ map(0x010, 0x017).lr32("invalid_address", []() { return 0; });
+ map(0x018, 0x01f).lrw32("translation_base", [this]() { return m_trans_tbl_base; }, [this](u32 data) { LOG("tbl base 0x%08x\n", data); m_trans_tbl_base = data; });
+ map(0x020, 0x027).lrw32("translation_limit", [this]() { return m_trans_tbl_limit; }, [this](u32 data) { m_trans_tbl_limit = data; });
+ map(0x028, 0x02f).lrw32("translation_invalidate", []() { return 0; }, [](u32 data) { });
+ map(0x030, 0x037).lw32("cache_maintenance", [this](u32 data) { m_ioc_maint = data; });
+ map(0x038, 0x03f).lr32("remote_failed_address", []() { return 0; });
+ map(0x040, 0x047).lr32("memory_failed_address", []() { return 0; });
+ map(0x048, 0x04f).lw32("io_cache_physical_tag", [this](u32 data) { m_ioc_physical_tag = data; });
+ map(0x050, 0x057).lw32("io_cache_logical_tag", [this](u32 data) { m_ioc_logical_tag = data; });
+ map(0x058, 0x05f).lrw32("io_cache_byte_mask",
+ // FIXME: hack to pass diagnostics
+ [this]()
+ {
+ u32 const data = m_ioc_byte_mask;
+
+ if (data == 0xffffffff)
+ m_ioc_byte_mask = 0;
+ return data;
+ },
+ [this](u32 data) { m_ioc_byte_mask |= data; });
+ map(0x060, 0x067).lw32("io_cache_buffer_window_lo", [this](u32 data)
+ {
+ // FIXME: hack to pass diagnostics
+ if (m_ioc_logical_tag == 0x80000001 && m_ioc_byte_mask == 0x0f0f0f0f)
+ {
+ u32 const address = (m_ioc_physical_tag & ~0x1) + ((m_ioc_maint & 0x3) << 3);
+
+ m_bus->write_dword(address, data);
+ }
+ });
+ // io_cache_buffer_window_hi
+ map(0x070, 0x0ef).lrw32("remote_speed",
+ [this](offs_t offset) { return m_remote_speed[offset >> 1]; },
+ [this](offs_t offset, u32 data) { m_remote_speed[offset >> 1] = data; });
+ // parity_diagnostic_lo
+ // parity_diagnostic_hi
+ map(0x100, 0x1ff).lrw32("dma_reg",
+ [this](offs_t offset) { return m_dma_reg[offset >> 1]; },
+ [this](offs_t offset, u32 data)
+ {
+ unsigned const reg = offset >> 1;
+
+ LOG("dma_reg %d data 0x%08x (%s)\n", offset, data, machine().describe_context());
+
+ m_dma_reg[reg] = data;
+
+ if ((reg == REG_ENABLE) && (data & DMA_ENABLE))
+ LOG("dma started address 0x%08x count %d\n", translate_address(m_dma_reg[(0 << 2) + REG_ADDRESS]), m_dma_reg[(0 << 2) + REG_COUNT]);
+ });
+ map(0x200, 0x207).lr32("interrupt_source", []() { return 0; });
+ map(0x208, 0x20f).lr32("error_type", []() { return 0; });
+ map(0x210, 0x217).lrw32("refresh_rate", [this]() { return m_memory_refresh_rate; }, [this](u32 data) { m_memory_refresh_rate = data; });
+ // refresh_counter
+ map(0x220, 0x227).lrw32("system_security", [this]() { return m_nvram_protect; }, [this](u32 data) { LOG("nvram_protect 0x%08x (%s)\n", data, machine().describe_context()); m_nvram_protect = data; });
+ map(0x228, 0x22f).lw32("interrupt_interval", [this](u32 data)
+ {
+ LOG("timer_w 0x%08x\n", data);
+
+ attotime interval = attotime::from_ticks((data + 1) & 0x1ff, 1000);
+
+ m_interval_timer->adjust(interval, 0, interval);
+ });
+ map(0x230, 0x237).lr32("interval_timer", [this]() { if (m_out_int_timer_asserted) { m_out_int_timer_asserted = false; m_out_int_timer(0); } return 0; });
+ map(0x238, 0x23b).lr32("interrupt_acknowledge", [this]() { return m_eisa_iack(); });
}
void jazz_mct_adr_device::device_start()
{
+ m_out_int_dma.resolve();
+ m_out_int_device.resolve();
+ m_out_int_timer.resolve();
+ m_eisa_iack.resolve();
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_dma_r[i].resolve_safe(0xff);
+ m_dma_w[i].resolve_safe();
+ }
+
+ m_config = 0x104; // REV1, REV2 is 0x410
+
+ m_ioc_maint = 0;
+ m_ioc_physical_tag = 0;
+ m_ioc_logical_tag = 0;
+ m_trans_tbl_base = 0;
+ m_trans_tbl_limit = 0;
+ m_ioc_byte_mask = 0;
+
+ for (u32 &val : m_remote_speed)
+ val = 0x7;
+
+ for (u32 &val : m_dma_reg)
+ val = 0;
+
+ m_memory_refresh_rate = 0x18186;
+ m_nvram_protect = 0x7;
+
+ m_irq_check = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(jazz_mct_adr_device::irq_check), this));
+ m_dma_check = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(jazz_mct_adr_device::dma_check), this));
+ m_interval_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(jazz_mct_adr_device::interval_timer), this));
+
+ m_out_int_timer_asserted = false;
+ m_out_int_device_asserted = false;
}
void jazz_mct_adr_device::device_reset()
{
+ m_isr = 0;
+ m_imr = 0; // 0x10;
+
+ m_interval_timer->adjust(attotime::from_usec(1), 0, attotime::from_usec(1));
+}
+
+void jazz_mct_adr_device::set_irq_line(int irq, int state)
+{
+ if ((irq != 3) && (m_isr & (1 << irq)) ^ (state << irq))
+ LOG("set_irq_line %d state %d m_imr 0x%04x\n", irq, state, m_imr);
+
+ if (state)
+ m_isr |= (1 << irq);
+ else
+ m_isr &= ~(1 << irq);
+
+ m_irq_check->adjust(attotime::zero);
+}
+
+TIMER_CALLBACK_MEMBER(jazz_mct_adr_device::irq_check)
+{
+ if (bool(m_isr & m_imr) != m_out_int_device_asserted)
+ {
+ m_out_int_device_asserted = bool(m_isr & m_imr);
+
+ m_out_int_device(m_out_int_device_asserted ? 1 : 0);
+ }
+}
+
+u16 jazz_mct_adr_device::isr_r()
+{
+ u16 const pending = m_isr & m_imr;
+
+ // FIXME: really?
+ //m_out_int_device(CLEAR_LINE);
+
+ for (u16 irq = 0; irq < 16; irq++)
+ if (BIT(pending, irq))
+ return (irq + 1) << 2;
+
+ return 0;
+}
+
+void jazz_mct_adr_device::imr_w(u16 data)
+{
+ LOG("imr_w 0x%04x (%s)\n", data, machine().describe_context());
+
+ m_imr = data;
+
+ m_irq_check->adjust(attotime::zero);
+}
+
+TIMER_CALLBACK_MEMBER(jazz_mct_adr_device::interval_timer)
+{
+ //m_out_int_timer(CLEAR_LINE);
+ if (!m_out_int_timer_asserted)
+ {
+ m_out_int_timer_asserted = true;
+ m_out_int_timer(1);
+ }
+}
+
+void jazz_mct_adr_device::set_drq_line(int channel, int state)
+{
+ m_drq_active[channel] = state == ASSERT_LINE;
+
+ if (state)
+ m_dma_check->adjust(attotime::zero);
+}
+
+TIMER_CALLBACK_MEMBER(jazz_mct_adr_device::dma_check)
+{
+ bool active = false;
+
+ for (int channel = 0; channel < 4; channel++)
+ {
+ if (!m_drq_active[channel])
+ continue;
+
+ // reg 0x00: 0x00000011 - mode (ch0) (WIDTH16 | ATIME_80)
+ // reg 0x20: 0x0000000a - mode (ch1) (WIDTH8 | ATIME_120)
+ // reg 0x18: 0x00000f20 - address
+ // reg 0x10: 0x00000024 - count
+ // reg 0x08: 0x00000001 - enable (ENABLE | !WRITE)
+
+ // check channel enabled
+ if (!(m_dma_reg[(channel << 2) + REG_ENABLE] & DMA_ENABLE))
+ return;
+
+ // check transfer count
+ if (!m_dma_reg[(channel << 2) + REG_COUNT])
+ return;
+
+ u32 const address = translate_address(m_dma_reg[(channel << 2) + REG_ADDRESS]);
+
+ // perform dma transfer
+ if (m_dma_reg[(channel << 2) + REG_ENABLE] & DMA_DIRECTION)
+ {
+ u8 const data = m_bus->read_byte(address);
+
+ //LOG("dma_w data 0x%02x address 0x%08x\n", data, m_dma_reg[(number << 2) + 3]);
+
+ m_dma_w[channel](data);
+ }
+ else
+ {
+ u8 const data = m_dma_r[channel]();
+
+ //LOG("dma_r data 0x%02x address 0x%08x\n", data, m_dma_reg[(number << 2) + 3]);
+
+ m_bus->write_byte(address, data);
+ }
+
+ // increment address, decrement count
+ m_dma_reg[(channel << 2) + REG_ADDRESS]++;
+ m_dma_reg[(channel << 2) + REG_COUNT]--;
+
+ // set terminal count flag
+ if (!m_dma_reg[(channel << 2) + REG_COUNT])
+ {
+ m_dma_reg[(channel << 2) + REG_ENABLE] |= DMA_TERMINAL_COUNT;
+
+ // TODO: dma interrupts
+ if (m_dma_reg[(channel << 2) + REG_ENABLE] & DMA_INTERRUPT_ENABLE)
+ logerror("dma interrupt enable - interrupt expected\n");
+ }
+
+ if (m_drq_active[channel])
+ active = true;
+ }
+
+ if (active)
+ m_dma_check->adjust(attotime::zero);
+}
+
+u32 jazz_mct_adr_device::translate_address(u32 logical_address)
+{
+ u32 page = logical_address >> 12;
+ if (page < (m_trans_tbl_limit) >> 3)
+ {
+ u32 entry_address = (m_trans_tbl_base & 0x7fffffff) + page * 8;
+
+ return m_bus->read_dword(entry_address) | (logical_address & 0xfff);
+ }
+ else
+ return 0; // FIXME: address error
}
diff --git a/src/mame/machine/jazz_mct_adr.h b/src/mame/machine/jazz_mct_adr.h
index dd2b651d25c..ff51813c7dc 100644
--- a/src/mame/machine/jazz_mct_adr.h
+++ b/src/mame/machine/jazz_mct_adr.h
@@ -11,12 +11,137 @@ class jazz_mct_adr_device : public device_t
public:
jazz_mct_adr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ // configuration
+ template <typename T> void set_bus(T &&tag, int spacenum) { m_bus.set_tag(std::forward<T>(tag), spacenum); }
+
+ auto out_int_dma_cb() { return m_out_int_dma.bind(); }
+ auto out_int_device_cb() { return m_out_int_device.bind(); }
+ auto out_int_timer_cb() { return m_out_int_timer.bind(); }
+ auto eisa_iack_cb() { return m_eisa_iack.bind(); }
+
+ template <unsigned DMA> auto dma_r_cb() { return m_dma_r[DMA].bind(); }
+ template <unsigned DMA> auto dma_w_cb() { return m_dma_w[DMA].bind(); }
+
+ template <unsigned IRQ> DECLARE_WRITE_LINE_MEMBER(irq) { set_irq_line(IRQ, state); }
+ template <unsigned DRQ> DECLARE_WRITE_LINE_MEMBER(drq) { set_drq_line(DRQ, state); }
+
virtual void map(address_map &map);
+ u16 isr_r();
+ u16 imr_r() { return m_imr; }
+ void imr_w(u16 data);
+
protected:
// device_t overrides
virtual void device_start() override;
virtual void device_reset() override;
+
+private:
+ void set_irq_line(int number, int state);
+ void set_drq_line(int channel, int state);
+
+ TIMER_CALLBACK_MEMBER(irq_check);
+ TIMER_CALLBACK_MEMBER(dma_check);
+ TIMER_CALLBACK_MEMBER(interval_timer);
+
+ u32 translate_address(u32 logical_address);
+
+ required_address_space m_bus;
+
+ devcb_write_line m_out_int_dma;
+ devcb_write_line m_out_int_device;
+ devcb_write_line m_out_int_timer;
+ devcb_read32 m_eisa_iack;
+
+ devcb_read8 m_dma_r[4];
+ devcb_write8 m_dma_w[4];
+ bool m_drq_active[4];
+
+ emu_timer *m_irq_check;
+ emu_timer *m_dma_check;
+ emu_timer *m_interval_timer;
+
+ enum isr_mask : u16
+ {
+ ISR_PRINTER = 0x0001,
+ ISR_FLOPPY = 0x0002,
+ ISR_SOUND = 0x0004,
+ ISR_VIDEO = 0x0008,
+ ISR_NETWORK = 0x0010,
+ ISR_SCSI = 0x0020,
+ ISR_KEYBOARD = 0x0040,
+ ISR_MOUSE = 0x0080,
+ ISR_SERIAL0 = 0x0100,
+ ISR_SERIAL1 = 0x0200,
+ };
+ u16 m_isr; // local bus interrupt source
+ u16 m_imr; // local bus interrupt mask
+
+ u32 m_config;
+
+ enum dma_register : unsigned
+ {
+ REG_MODE = 0,
+ REG_ENABLE = 1,
+ REG_COUNT = 2,
+ REG_ADDRESS = 3,
+ };
+ enum dma_mode_mask : u32
+ {
+ DMA_ACCESS_TIME = 0x00000007,
+ DMA_TRANSFER_WIDTH = 0x00000018,
+ DMA_INTERRUPT_ENABLE = 0x00000020,
+ DMA_BURST_MODE = 0x00000040,
+ DMA_FAST_DMA_CYCLE = 0x00000080,
+ };
+ enum dma_access_time : u32
+ {
+ ACCESS_40NS = 0x00,
+ ACCESS_80NS = 0x01,
+ ACCESS_120NS = 0x02,
+ ACCESS_160NS = 0x03,
+ ACCESS_200NS = 0x04,
+ ACCESS_240NS = 0x05,
+ ACCESS_280NS = 0x06,
+ ACCESS_320NS = 0x07,
+ };
+ enum dma_transfer_width : u32
+ {
+ WIDTH_8BITS = 0x08,
+ WIDTH_16BITS = 0x10,
+ WIDTH_32BITS = 0x18,
+ };
+ enum dma_enable_mask : u32
+ {
+ DMA_ENABLE = 0x00000001,
+ DMA_DIRECTION = 0x00000002, // 1 == write to device
+ DMA_TERMINAL_COUNT = 0x00000100,
+ DMA_MEMORY_ERROR = 0x00000200,
+ DMA_TRANSLATION_ERROR = 0x00000400,
+ };
+ enum dma_interrupt_source : u32
+ {
+ DMA_INTERRUPT_PENDING = 0x000000ff,
+ DMA_PARITY_ERROR = 0x00000100,
+ DMA_ADDRESS_ERROR = 0000000200,
+ DMA_CACHE_FLUSH_ERROR = 0x00000400,
+ };
+
+ u32 m_trans_tbl_base;
+ u32 m_trans_tbl_limit;
+ u32 m_ioc_maint;
+ u32 m_ioc_physical_tag;
+ u32 m_ioc_logical_tag;
+ u32 m_ioc_byte_mask;
+ u32 m_remote_speed[16];
+ u32 m_dma_reg[32];
+ u32 m_memory_refresh_rate;
+ u32 m_nvram_protect;
+
+ u32 m_dma_address[4];
+
+ bool m_out_int_timer_asserted;
+ bool m_out_int_device_asserted;
};
// device type definition