diff options
-rw-r--r-- | src/mame/mame.lst | 1 | ||||
-rw-r--r-- | src/mame/sun/sun1.cpp | 148 | ||||
-rw-r--r-- | src/mame/sun/sun1_cpu.cpp | 408 | ||||
-rw-r--r-- | src/mame/sun/sun1_cpu.h | 69 | ||||
-rw-r--r-- | src/mame/sun/sun1_mmu.cpp | 309 | ||||
-rw-r--r-- | src/mame/sun/sun1_mmu.h | 73 |
6 files changed, 889 insertions, 119 deletions
diff --git a/src/mame/mame.lst b/src/mame/mame.lst index be2a973a831..71d5b50f36e 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -43703,7 +43703,6 @@ sothello tonton @source:sun/sun1.cpp -multibox sun1 @source:sun/sun2.cpp diff --git a/src/mame/sun/sun1.cpp b/src/mame/sun/sun1.cpp index 8b6f25422d3..b3ce3ee78f4 100644 --- a/src/mame/sun/sun1.cpp +++ b/src/mame/sun/sun1.cpp @@ -8,6 +8,7 @@ Sun-1 Processor(s): 68000 + P/N: 270-0001 Notes: Large black desktop boxes with 17" monitors. Uses the original Stanford-designed video board and a parallel microswitch keyboard (type 1) and @@ -55,14 +56,18 @@ 04/04/2011 Modernised, added terminal keyboard. + TODO: + - graphic cards + - network cards + - storage cards + ****************************************************************************/ #include "emu.h" -#include "bus/rs232/rs232.h" -#include "cpu/m68000/m68000.h" -#include "machine/am9513.h" -#include "machine/z80sio.h" +#include "sun1_cpu.h" + +#include "bus/multibus/multibus.h" namespace { @@ -71,144 +76,51 @@ class sun1_state : public driver_device public: sun1_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_iouart(*this, "iouart") - , m_p_ram(*this, "p_ram") + , m_bus(*this, "slot") { } void sun1(machine_config &config); - void cyb(machine_config &config); private: - void sun1_mem(address_map &map) ATTR_COLD; - void cyb_mem(address_map &map) ATTR_COLD; + virtual void machine_start() override ATTR_COLD; virtual void machine_reset() override ATTR_COLD; - required_device<cpu_device> m_maincpu; - required_device<upd7201_device> m_iouart; - required_shared_ptr<uint16_t> m_p_ram; + required_device<multibus_device> m_bus; }; - -void sun1_state::sun1_mem(address_map &map) +void sun1_state::machine_start() { - map.unmap_value_high(); - map(0x00000000, 0x001fffff).ram().share("p_ram"); // 512 KB RAM / ROM at boot - map(0x00200000, 0x00203fff).rom().region("monitor", 0); - map(0x00600000, 0x00600007).mirror(0x1ffff8).rw(m_iouart, FUNC(upd7201_device::ba_cd_r), FUNC(upd7201_device::ba_cd_w)).umask16(0xff00); - map(0x00800000, 0x00800003).mirror(0x1ffffc).rw("timer", FUNC(am9513_device::read16), FUNC(am9513_device::write16)); - map(0x00a00000, 0x00bfffff).unmaprw(); // page map - map(0x00c00000, 0x00dfffff).unmaprw(); // segment map - map(0x00e00000, 0x00ffffff).unmaprw(); // context register } -void sun1_state::cyb_mem(address_map &map) -{ - sun1_mem(map); - map(0x00400000, 0x00403fff).rom().region("cyb", 0); -} - -/* Input ports */ -static INPUT_PORTS_START( sun1 ) -INPUT_PORTS_END - - void sun1_state::machine_reset() { - uint8_t* user1 = memregion("monitor")->base(); - - memcpy((uint8_t*)m_p_ram.target(),user1,0x4000); } - -void sun1_state::sun1(machine_config &config) +static void sun1_cards(device_slot_interface &device) { - /* basic machine hardware */ - M68000(config, m_maincpu, 16_MHz_XTAL / 2); - m_maincpu->set_addrmap(AS_PROGRAM, &sun1_state::sun1_mem); - - am9513_device &timer(AM9513(config, "timer", 16_MHz_XTAL / 4)); - timer.fout_cb().set("timer", FUNC(am9513_device::gate1_w)); - timer.out1_cb().set_nop(); // Watchdog; generates BERR/Reset - timer.out2_cb().set_inputline(m_maincpu, M68K_IRQ_6); // User timer - timer.out3_cb().set_inputline(m_maincpu, M68K_IRQ_7); // Refresh timer (2 ms) - timer.out4_cb().set(m_iouart, FUNC(upd7201_device::rxca_w)); - timer.out4_cb().append(m_iouart, FUNC(upd7201_device::txca_w)); - timer.out5_cb().set(m_iouart, FUNC(upd7201_device::rxcb_w)); - timer.out5_cb().append(m_iouart, FUNC(upd7201_device::txcb_w)); - - UPD7201(config, m_iouart, 16_MHz_XTAL / 4); - m_iouart->out_txda_callback().set("rs232a", FUNC(rs232_port_device::write_txd)); - m_iouart->out_dtra_callback().set("rs232a", FUNC(rs232_port_device::write_dtr)); - m_iouart->out_rtsa_callback().set("rs232a", FUNC(rs232_port_device::write_rts)); - m_iouart->out_txdb_callback().set("rs232b", FUNC(rs232_port_device::write_txd)); - m_iouart->out_dtrb_callback().set("rs232b", FUNC(rs232_port_device::write_dtr)); - m_iouart->out_rtsb_callback().set("rs232b", FUNC(rs232_port_device::write_rts)); - m_iouart->out_int_callback().set_inputline(m_maincpu, M68K_IRQ_5); - - rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, "terminal")); - rs232a.rxd_handler().set(m_iouart, FUNC(upd7201_device::rxa_w)); - rs232a.cts_handler().set(m_iouart, FUNC(upd7201_device::ctsa_w)); - rs232a.dcd_handler().set(m_iouart, FUNC(upd7201_device::dcda_w)); - - rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr)); - rs232b.rxd_handler().set(m_iouart, FUNC(upd7201_device::rxb_w)); - rs232b.cts_handler().set(m_iouart, FUNC(upd7201_device::ctsb_w)); - rs232b.dcd_handler().set(m_iouart, FUNC(upd7201_device::dcdb_w)); + device.option_add("sun1cpu", MULTIBUS_SUN1CPU); } -void sun1_state::cyb(machine_config &config) +void sun1_state::sun1(machine_config &config) { - sun1(config); - m_maincpu->set_addrmap(AS_PROGRAM, &sun1_state::cyb_mem); + // FIXME: CPU board can optionally drive Multibus clocks + MULTIBUS(config, m_bus, 19.6608_MHz_XTAL / 2); + + // slot 1 is physically located at top, only slots 1-3 have P2 + MULTIBUS_SLOT(config, "slot:1", sun1_cards, nullptr, false); // memory expansion 2 + MULTIBUS_SLOT(config, "slot:2", sun1_cards, nullptr, false); // memory expansion 1 + MULTIBUS_SLOT(config, "slot:3", sun1_cards, "sun1cpu", false); // processor + MULTIBUS_SLOT(config, "slot:4", sun1_cards, nullptr, false); // bus master 1 + MULTIBUS_SLOT(config, "slot:5", sun1_cards, nullptr, false); // bus master 2 + MULTIBUS_SLOT(config, "slot:6", sun1_cards, nullptr, false); // multibus memory, optional + MULTIBUS_SLOT(config, "slot:7", sun1_cards, nullptr, false); // graphics } -/* ROM definition */ -ROM_START( sun1 ) - ROM_REGION16_BE(0x4000, "monitor", 0) - ROM_DEFAULT_BIOS("1.0") - - ROM_SYSTEM_BIOS(0, "1.0", "Sun Monitor 1.0") - ROMX_LOAD("v10.8.bin", 0x0000, 0x2000, CRC(3528a0f8) SHA1(be437dd93d1a44eccffa6f5e05935119482beab0), ROM_SKIP(1) | ROM_BIOS(0)) - ROMX_LOAD("v10.0.bin", 0x0001, 0x2000, CRC(1ad4c52a) SHA1(4bc1a19e8f202378d5d7baa8b95319275c040a6d), ROM_SKIP(1) | ROM_BIOS(0)) - - ROM_SYSTEM_BIOS(1, "diag", "Interactive Tests") - ROMX_LOAD("8mhzdiag.8.bin", 0x0000, 0x2000, CRC(808a549e) SHA1(d2aba014a5507c1538f2c1a73e1d2524f28034f4), ROM_SKIP(1) | ROM_BIOS(1)) - ROMX_LOAD("8mhzdiag.0.bin", 0x0001, 0x2000, CRC(7a92d506) SHA1(5df3800f7083293fc01bb6a7e7538ad425bbebfb), ROM_SKIP(1) | ROM_BIOS(1)) - - ROM_REGION(0x0a40, "gfx", 0) - ROM_LOAD("gfxu605.g4.bin", 0x0000, 0x0200, CRC(274b7b3d) SHA1(40d8be2cfcbd03512a05925991bb5030d5d4b5e9)) - ROM_LOAD("gfxu308.g21.bin", 0x0200, 0x0200, CRC(35a6eed8) SHA1(25cb2dd8e5343cd7927c3045eb4cb96dc9935a37)) - ROM_LOAD("gfxu108.g20.bin", 0x0400, 0x0200, CRC(ecee335e) SHA1(5f4d32dc918af15872cd6e700a04720caeb6c657)) - ROM_LOAD("gfxu105.g0.bin", 0x0600, 0x0200, CRC(8e1a24b3) SHA1(dad2821c3a3137ad69e78b6fc29ab582e5d78646)) - ROM_LOAD("gfxu104.g1.bin", 0x0800, 0x0200, CRC(86f7a483) SHA1(8eb3778f5497741cd4345e81ff1a903c9a63c8bb)) - ROM_LOAD("gfxu307.g61.bin", 0x0a00, 0x0020, CRC(b190f25d) SHA1(80fbdc843f1eb68a2d3713499f04d99dab88ce83)) - ROM_LOAD("gfxu107.g60.bin", 0x0a20, 0x0020, CRC(425d3a98) SHA1(9ae4ce3761c2f995d00bed8d752c55224d274062)) - - ROM_REGION(0x0240, "cpu", 0) - ROM_LOAD("cpuu503.p2.bin", 0x0000, 0x0200, CRC(12d9a6be) SHA1(fca99f9c5afc630ac67cbd4e5ba4e5242b826848)) - ROM_LOAD("cpuu602.p1.bin", 0x0200, 0x0020, CRC(ee1e5a14) SHA1(0d3346cb3b647fa2475bd7b4fa36ea6ecfdaf805)) - ROM_LOAD("cpuu502.p0.bin", 0x0220, 0x0020, CRC(20eb1183) SHA1(9b268792b28d858d6b6a1b6c4148af88a8d6b735)) -ROM_END - -ROM_START( multibox ) - ROM_REGION16_BE(0x4000, "monitor", 0) - // "Sun Network Monitor, Version 0.10" - ROM_LOAD16_BYTE("cybu103-sun10v.bin", 0x0000, 0x2000, CRC(32e53691) SHA1(5b0a3c4b5352d4c19067d9eb4db6cd1f76427892)) - ROM_LOAD16_BYTE("cybu101-sun10v.bin", 0x0001, 0x2000, CRC(900b725c) SHA1(90343de9e64ff8227c7e58c9d4df02783ecf5a76)) - - ROM_REGION16_BE(0x4000, "cyb", 0) - // "CYB Monitor - Version 2.1 6/23/84" - ROM_LOAD16_BYTE("cybu104-autov.bin", 0x0000, 0x2000, CRC(46570c0e) SHA1(42ad96ffb7cb0e2d9c0aa0ace283ff646eaa4584)) - ROM_LOAD16_BYTE("cybu102-autov.bin", 0x0001, 0x2000, CRC(6198c5f6) SHA1(7d880395c4da03ac5130905c850ad638cd4b86e9)) +ROM_START(sun1) ROM_END } // anonymous namespace - -/* Driver */ - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1982, sun1, 0, 0, sun1, sun1, sun1_state, empty_init, "Sun Microsystems", "Sun-1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) -COMP( 1984, multibox, 0, 0, cyb, sun1, sun1_state, empty_init, "CYB Systems", "Multibox", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1982, sun1, 0, 0, sun1, 0, sun1_state, empty_init, "Sun Microsystems", "Sun-1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) diff --git a/src/mame/sun/sun1_cpu.cpp b/src/mame/sun/sun1_cpu.cpp new file mode 100644 index 00000000000..8d329dc4096 --- /dev/null +++ b/src/mame/sun/sun1_cpu.cpp @@ -0,0 +1,408 @@ +// license:BSD-3-Clause +// copyright-holders:Miodrag Milanovic, Patrick Mackinlay + +/* + * This device emulates the Multibus Sun-1 CPU board, which consists of the + * following key components: + * + * - 68000 CPU @ 8/10MHz + * - Sun-1 memory management unit + * - 256KiB RAM + up to 32KiB EPROM + * - Am9513 system timing controller + * - i8247/μPD7201 dual UART + * + * Sources: + * - Sun-1 System Reference Manual, Draft Version 1.0, July 27, 1982, Sun Microsystems, Inc. + * - Sun 68000 Board User's Manual, Revision B, February 1983, Sun Microsystems Inc. + * + * TODO: + * - second generation Sun-1.5 variant + * - variants from other companies + * - keyboard, mouse + * - jumpers + */ + +/* + * WIP: + * - bios 1: "t" enters CYB monitor + * - bios 6: top 3 bits of parallel register control tests + */ + +#include "emu.h" + +#include "sun1_cpu.h" + +#include "bus/rs232/rs232.h" +#include "machine/clock.h" + +#define LOG_DOG (1U << 2) + +//#define VERBOSE (LOG_GENERAL|LOG_DOG) +#include "logmacro.h" + +enum irq_mask : u8 +{ + WATCHDOG = 0x80, +}; + +DEFINE_DEVICE_TYPE(MULTIBUS_SUN1CPU, sun1cpu_device, "sun1cpu", "Sun-1 CPU") + +sun1cpu_device::sun1cpu_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + : device_t(mconfig, MULTIBUS_SUN1CPU, tag, owner, clock) + , device_multibus_interface(mconfig, *this) + , m_cpu(*this, "cpu") + , m_mmu(*this, "mmu") + , m_duart(*this, "duart") + , m_stc(*this, "stc") + , m_boot(*this, "boot") +{ +} + +ROM_START(sun1) + /* + * These different firmware versions expect slightly different hardware/timer + * configurations and probably come from CPU boards that were made or modified + * by other companies. The standard configuration according to the available + * documentation should be: + * + * - stc @ 5MHz + * - counter 1: watchdog (@2.98ms) + * - counter 2: user irq 6 + * - cuonter 3: refresh irq 7 (@2ms) + * - counter 4: uarta (16x baud) + * - counter 5: uartb (16x baud) + * + * Most of these firmware versions do not configure timer 1 as a watchdog, and + * probably rely on a dedicated watchdog timer circuit like that described in + * the VSI schematics instead. + * + * The "aj" firmware is quite different: it does not use the STC for the DUART + * clocks, and uses counter 5 for refresh. + * + */ + ROM_SYSTEM_BIOS(0, "sun1", "Sun Monitor, Version 1.0") // osc=16, div=4 + ROM_SYSTEM_BIOS(1, "cyb", "Sun Network Monitor, Version 0.10 (CYB)") // osc=16, div=4 + ROM_SYSTEM_BIOS(2, "test", "Interactive Tests") // osc=16, div=2 + ROM_SYSTEM_BIOS(3, "fti10_11", "Sun Monitor, Version 1.1 (FTI10)") // osc=19.6, div=8 + ROM_SYSTEM_BIOS(4, "fti10_10", "Sun Monitor, Version 1.0 (FTI10)") // osc=19.6, div=8 + ROM_SYSTEM_BIOS(5, "smi10", "Sun Monitor, Version 1.1 (SMI10)") // osc=19.6, div=4, watchdog=1 + ROM_SYSTEM_BIOS(6, "aj", "Sun-1 Workstation Monitor; PROM 1&3: Rev AJ; PROM 2&4: Rev AJ") // osc=20, div=4, watchdog=1 + + /* + * The prom0 region at 0x02'0000 holds the primary firmware, and is also + * readable from address 0x00'0000 until boot mode is disabled. + */ + ROM_REGION16_BE(0x4000, "prom0", ROMREGION_ERASEFF) + + // stc @ 4MHz (16MHz / 4) + // counter 3 mode 0b22 load=8000 == 2ms + // counter 4 mode 0b22 load=13 + // counter 5 mode 0b22 load=13 + ROMX_LOAD("v10.8.u103", 0x0000, 0x2000, CRC(3528a0f8) SHA1(be437dd93d1a44eccffa6f5e05935119482beab0), ROM_SKIP(1) | ROM_BIOS(0)) + ROMX_LOAD("v10.0.u101", 0x0001, 0x2000, CRC(1ad4c52a) SHA1(4bc1a19e8f202378d5d7baa8b95319275c040a6d), ROM_SKIP(1) | ROM_BIOS(0)) + + // Sun Network Monitor, Version 0.10 + // stc @ 4MHz (16MHz / 4) + // counter 3 mode 0b22 load=8000 == 2ms + // counter 4 mode 0b22 load=13 + // counter 5 mode 0b22 load=13 + ROMX_LOAD("cybu103-sun10v.u103", 0x0000, 0x2000, CRC(32e53691) SHA1(5b0a3c4b5352d4c19067d9eb4db6cd1f76427892), ROM_SKIP(1) | ROM_BIOS(1)) + ROMX_LOAD("cybu101-sun10v.u101", 0x0001, 0x2000, CRC(900b725c) SHA1(90343de9e64ff8227c7e58c9d4df02783ecf5a76), ROM_SKIP(1) | ROM_BIOS(1)) + + // Interactive Tests + // stc @ 8MHz (16MHz / 2) + // counter 3 mode 0b22 load=16000 == 2ms + // counter 4 mode 0b22 load=26 + // counter 5 mode 0b22 load=26 + ROMX_LOAD("8mhzdiag.8.u103", 0x0000, 0x2000, CRC(808a549e) SHA1(d2aba014a5507c1538f2c1a73e1d2524f28034f4), ROM_SKIP(1) | ROM_BIOS(2)) + ROMX_LOAD("8mhzdiag.0.u101", 0x0001, 0x2000, CRC(7a92d506) SHA1(5df3800f7083293fc01bb6a7e7538ad425bbebfb), ROM_SKIP(1) | ROM_BIOS(2)) + + // Sun Monitor, Version 1.1 + // stc @ 2.4576MHz (19.6MHz / 8) + // counter 3 mode 0b22 load=4915 == ~2ms + // counter 4 mode 0b22 load=8 + // counter 5 mode 0b22 load=8 + ROMX_LOAD("fti10_11.u103", 0x0000, 0x1000, CRC(1a5befa5) SHA1(cd7fc4c88a76ae393ada6a3f427993fbacb8a9c6), ROM_SKIP(1) | ROM_BIOS(3)) + ROMX_LOAD("fti10_11.u101", 0x0001, 0x1000, CRC(ac733618) SHA1(baff471248b355d761a5dab375fc88d861cb6853), ROM_SKIP(1) | ROM_BIOS(3)) + + // Sun Monitor, Version 1.0 + // stc @ 2.4576MHz (19.6MHz / 8) + // counter 3 mode 0b22 load=4915 == ~2ms + // counter 4 mode 0b22 load=8 + // counter 5 mode 0b22 load=8 + ROMX_LOAD("fti10_10.u103", 0x0000, 0x1000, CRC(fb5e599b) SHA1(5ab1ac61034aac956fd6e39b964996e0f9d0da97), ROM_SKIP(1) | ROM_BIOS(4)) + ROMX_LOAD("fti10_10.u101", 0x0001, 0x1000, CRC(e7371fd6) SHA1(5a377a4363b59c5508f941c356d8827594a72dc8), ROM_SKIP(1) | ROM_BIOS(4)) + + // Sun Monitor, Version 1.1 + // stc @ 4.9152MHz (19.6MHz / 4) + // counter 1 mode 0621 load=7568 == ~3ms + // counter 3 mode 0622 load=4915 == ~2ms + // counter 4 mode 0b22 load=16 + // counter 5 mode 0b22 load=16 + ROMX_LOAD("smi10_11.u103", 0x0000, 0x1000, CRC(89e1a6ed) SHA1(2dfcba08fb6e4582e05b803c4507419c25dbdaa8), ROM_SKIP(1) | ROM_BIOS(5)) + ROMX_LOAD("smi10_11.u101", 0x0001, 0x1000, CRC(432db053) SHA1(99a54a653f18b914ae15f230a35ac55c5d076a4c), ROM_SKIP(1) | ROM_BIOS(5)) + + // PROM 1&3: Rev AJ + // stc @ 5MHz (20MHz / 4) + // counter 1 mode 0621 load=7450 == 2.98ms + // counter 5 mode 0622 load=5000 == 2ms + // uarts fixed @ 9600 + ROMX_LOAD("sun1c_1h.u103", 0x0000, 0x2000, CRC(4c58de6c) SHA1(f417a0a013d4ca3aaf565b0e7a88dcf3da1347c1), ROM_SKIP(1) | ROM_BIOS(6)) + ROMX_LOAD("sun1c_1l.u101", 0x0001, 0x2000, CRC(41c47355) SHA1(a38df286ab8ba9a462862ab1cc9fa28b79fb9949), ROM_SKIP(1) | ROM_BIOS(6)) + + /* + * The prom1 region at 0x04'0000 holds secondary/optional diagnostic or + * boot firmware. + */ + ROM_REGION16_BE(0x4000, "prom1", ROMREGION_ERASEFF) + + // CYB Monitor - Version 2.1 6/23/84 + ROMX_LOAD("cybu104-autov.u104", 0x0000, 0x2000, CRC(46570c0e) SHA1(42ad96ffb7cb0e2d9c0aa0ace283ff646eaa4584), ROM_SKIP(1) | ROM_BIOS(1)) + ROMX_LOAD("cybu102-autov.u102", 0x0001, 0x2000, CRC(6198c5f6) SHA1(7d880395c4da03ac5130905c850ad638cd4b86e9), ROM_SKIP(1) | ROM_BIOS(1)) + + // PROM 2&4: Rev AJ + ROMX_LOAD("sun1c_2h.u104", 0x0000, 0x2000, CRC(b5cbcb2b) SHA1(8f906dbdc9b2af90bc8f942eebe7006be0ff4e86), ROM_SKIP(1) | ROM_BIOS(6)) + ROMX_LOAD("sun1c_2l.u102", 0x0001, 0x2000, CRC(dc82578b) SHA1(65bf18a8a40171ec08137a0c446da3b272b9ccbc), ROM_SKIP(1) | ROM_BIOS(6)) + + // TODO: move the following firmware to a graphics card + ROM_REGION(0x10000, "gfx", ROMREGION_ERASEFF) + ROM_LOAD("gfxu605.g4.bin", 0x0000, 0x0200, CRC(274b7b3d) SHA1(40d8be2cfcbd03512a05925991bb5030d5d4b5e9)) + ROM_LOAD("gfxu308.g21.bin", 0x0200, 0x0200, CRC(35a6eed8) SHA1(25cb2dd8e5343cd7927c3045eb4cb96dc9935a37)) + ROM_LOAD("gfxu108.g20.bin", 0x0400, 0x0200, CRC(ecee335e) SHA1(5f4d32dc918af15872cd6e700a04720caeb6c657)) + ROM_LOAD("gfxu105.g0.bin", 0x0600, 0x0200, CRC(8e1a24b3) SHA1(dad2821c3a3137ad69e78b6fc29ab582e5d78646)) + ROM_LOAD("gfxu104.g1.bin", 0x0800, 0x0200, CRC(86f7a483) SHA1(8eb3778f5497741cd4345e81ff1a903c9a63c8bb)) + ROM_LOAD("gfxu307.g61.bin", 0x0a00, 0x0020, CRC(b190f25d) SHA1(80fbdc843f1eb68a2d3713499f04d99dab88ce83)) + ROM_LOAD("gfxu107.g60.bin", 0x0a20, 0x0020, CRC(425d3a98) SHA1(9ae4ce3761c2f995d00bed8d752c55224d274062)) + + ROM_REGION(0x10000, "cpu", ROMREGION_ERASEFF) + ROM_LOAD("cpuu503.p2.bin", 0x0000, 0x0200, CRC(12d9a6be) SHA1(fca99f9c5afc630ac67cbd4e5ba4e5242b826848)) + ROM_LOAD("cpuu602.p1.bin", 0x0200, 0x0020, CRC(ee1e5a14) SHA1(0d3346cb3b647fa2475bd7b4fa36ea6ecfdaf805)) + ROM_LOAD("cpuu502.p0.bin", 0x0220, 0x0020, CRC(20eb1183) SHA1(9b268792b28d858d6b6a1b6c4148af88a8d6b735)) +ROM_END + +const tiny_rom_entry *sun1cpu_device::device_rom_region() const +{ + return ROM_NAME(sun1); +} + +static INPUT_PORTS_START(sun1) +INPUT_PORTS_END + +ioport_constructor sun1cpu_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(sun1); +} + +void sun1cpu_device::device_start() +{ + save_item(NAME(m_irq)); + save_item(NAME(m_watchdog)); + save_item(NAME(m_parity)); + + m_cpu->space(AS_PROGRAM).specific(m_cpu_mem); + m_cpu->space(m68000_device::AS_CPU_SPACE).specific(m_cpu_spc); + + m_irq = 0; +} + +void sun1cpu_device::device_reset() +{ + // HACK: configure oscillator, divisor and watchdog type to match selected + // firmware until more accurate board type/configuration can be determined + XTAL oscillator = 16_MHz_XTAL; + unsigned divisor = 4; + m_watchdog = false; + + switch (system_bios()) + { + case 1: + case 2: + break; + case 3: + divisor = 2; + break; + case 4: + case 5: + oscillator = 19.6608_MHz_XTAL; + divisor = 8; + break; + case 6: + oscillator = 19.6608_MHz_XTAL; + m_watchdog = true; + break; + case 7: + oscillator = 20_MHz_XTAL; + m_watchdog = true; + break; + } + + // configure cpu, stc and duart clocks + m_cpu->set_clock(oscillator / 2); + m_stc->set_clock(oscillator / divisor); + m_duart->set_clock(oscillator / divisor); + + m_parity = false; + + if (!boot()) + { + m_cpu->set_current_mmu(this); + + // disable interrupts + for (unsigned i = 0; i < 7; i++) + if (BIT(m_irq, i)) + m_cpu->set_input_line(M68K_IRQ_1 + i, CLEAR_LINE); + + m_boot.select(0); + } +} + +void sun1cpu_device::device_add_mconfig(machine_config &config) +{ + M68000(config, m_cpu, 0); + m_cpu->set_current_mmu(this); + m_cpu->set_addrmap(AS_PROGRAM, &sun1cpu_device::cpu_mem); + + // route multibus interrupts 1..4 to cpu + int_callback<1>().set(FUNC(sun1cpu_device::irq_w<M68K_IRQ_1>)).invert(); + int_callback<2>().set(FUNC(sun1cpu_device::irq_w<M68K_IRQ_2>)).invert(); + int_callback<3>().set(FUNC(sun1cpu_device::irq_w<M68K_IRQ_3>)).invert(); + int_callback<4>().set(FUNC(sun1cpu_device::irq_w<M68K_IRQ_4>)).invert(); + + SUN1MMU(config, m_mmu); + m_mmu->error().set( + [this](int state) + { + // check multibus access pending + if (state == sun1mmu_device::MMU_DEFER) + { + if (!m_watchdog || (m_irq & WATCHDOG)) + { + LOGMASKED(LOG_DOG, "watchdog bus error\n"); + m_cpu->trigger_bus_error(); + m_mmu->reset(); + } + else + m_cpu->defer_access(); + } + else + m_cpu->trigger_bus_error(); + }); + + // default configuration (1=watchdog, 2=user, 3=refresh, 4=uarta, 5=uartb) + AM9513(config, m_stc, 0); + m_stc->fout_cb().set(m_stc, FUNC(am9513_device::gate1_w)); + m_stc->out1_cb().set(FUNC(sun1cpu_device::watchdog_w)); + m_stc->out2_cb().set(FUNC(sun1cpu_device::irq_w<M68K_IRQ_6>)); + m_stc->out3_cb().set(FUNC(sun1cpu_device::irq_w<M68K_IRQ_7>)); + m_stc->out4_cb().set(m_duart, FUNC(upd7201_device::rxca_w)); + m_stc->out4_cb().append(m_duart, FUNC(upd7201_device::txca_w)); + m_stc->out5_cb().set(m_duart, FUNC(upd7201_device::rxcb_w)); + m_stc->out5_cb().append(m_duart, FUNC(upd7201_device::txcb_w)); + + if (false) + { + // TODO: "aj" firmware has refresh on counter 5, and fixed-speed uarts + m_stc->out3_cb().set_nop(); + m_stc->out4_cb().set_nop(); + m_stc->out5_cb().set(FUNC(sun1cpu_device::irq_w<M68K_IRQ_7>)); + + // assume duart rxc/txc driven at 9600baud (x16 clock) + CLOCK(config, "duart_clock", 9600 * 16).signal_handler().set( + [this](int state) + { + m_duart->txca_w(state); + m_duart->rxca_w(state); + m_duart->txcb_w(state); + m_duart->rxcb_w(state); + }); + } + + // port A: txd, rxd, rts, cts, dsr, dtr + // port B: txd, rxd + UPD7201(config, m_duart, 0); + m_duart->out_txda_callback().set("rs232a", FUNC(rs232_port_device::write_txd)); + m_duart->out_dtra_callback().set("rs232a", FUNC(rs232_port_device::write_dtr)); + m_duart->out_rtsa_callback().set("rs232a", FUNC(rs232_port_device::write_rts)); + m_duart->out_txdb_callback().set("rs232b", FUNC(rs232_port_device::write_txd)); + m_duart->out_int_callback().set(FUNC(sun1cpu_device::irq_w<M68K_IRQ_5>)); + + rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, "terminal")); + rs232a.rxd_handler().set(m_duart, FUNC(upd7201_device::rxa_w)); + rs232a.cts_handler().set(m_duart, FUNC(upd7201_device::ctsa_w)); + rs232a.dcd_handler().set(m_duart, FUNC(upd7201_device::dcda_w)); + + rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr)); + rs232b.rxd_handler().set(m_duart, FUNC(upd7201_device::rxb_w)); +} + +void sun1cpu_device::device_config_complete() +{ + m_mmu.lookup()->set_space<0>(m_cpu, AS_PROGRAM); + m_mmu.lookup()->set_space<1>(m_cpu, m68000_device::AS_CPU_SPACE); + m_mmu.lookup()->set_space<2>(m_bus, AS_PROGRAM); + m_mmu.lookup()->set_space<3>(m_bus, AS_IO); +} + +void sun1cpu_device::cpu_mem(address_map &map) +{ + map(0x00'0000, 0x03'ffff).ram(); + + map(0x00'0000, 0x1f'ffff).view(m_boot); + m_boot[0](0x00'0000, 0x00'3fff).mirror(0x03'c000).rom().region("prom0", 0); + + map(0x20'0000, 0x20'3fff).mirror(0x03'c000).rom().region("prom0", 0).w(FUNC(sun1cpu_device::prom0_w)); + map(0x40'0000, 0x40'3fff).mirror(0x03'c000).rom().region("prom1", 0); + map(0x60'0000, 0x60'0007).mirror(0x1ffff8).rw(m_duart, FUNC(upd7201_device::ba_cd_r), FUNC(upd7201_device::ba_cd_w)).umask16(0xff00); + map(0x80'0000, 0x80'0003).mirror(0x1ffffc).rw(m_stc, FUNC(am9513_device::read16), FUNC(am9513_device::write16)); + map(0xa0'0000, 0xbf'ffff).rw(m_mmu, FUNC(sun1mmu_device::page_r), FUNC(sun1mmu_device::page_w)); + map(0xc0'0000, 0xdf'ffff).rw(m_mmu, FUNC(sun1mmu_device::segment_r), FUNC(sun1mmu_device::segment_w)); + map(0xe0'0000, 0xe0'0001).mirror(0x1f'fffe).r(FUNC(sun1cpu_device::parallel_r)); + map(0xe0'0000, 0xe0'0001).mirror(0x1f'fffe).w(m_mmu, FUNC(sun1mmu_device::context_w)); +} + +void sun1cpu_device::watchdog_w(int state) +{ + if (state) + m_irq |= WATCHDOG; + else + m_irq &= ~WATCHDOG; + + if (!BIT(m_irq, 6)) + { + if (state) + { + LOGMASKED(LOG_DOG, "watchdog reset\n"); + reset(); + } + } +} + +template <unsigned N> void sun1cpu_device::irq_w(int state) +{ + if (state) + m_irq |= 1U << (N - M68K_IRQ_1); + else + m_irq &= ~(1U << (N - M68K_IRQ_1)); + + if (!boot()) + m_cpu->set_input_line(N, state); +} + +void sun1cpu_device::prom0_w(u16 data) +{ + m_parity = BIT(data, 0); + + if (boot()) + { + LOG("boot mode disabled (%s)\n", machine().describe_context()); + + m_cpu->set_current_mmu(m_mmu); + + // enable interrupts + for (unsigned i = 0; i < 7; i++) + if (BIT(m_irq, i)) + m_cpu->set_input_line(M68K_IRQ_1 + i, ASSERT_LINE); + + m_boot.disable(); + } +} diff --git a/src/mame/sun/sun1_cpu.h b/src/mame/sun/sun1_cpu.h new file mode 100644 index 00000000000..c50a15dbb66 --- /dev/null +++ b/src/mame/sun/sun1_cpu.h @@ -0,0 +1,69 @@ +// license:BSD-3-Clause +// copyright-holders:Miodrag Milanovic, Patrick Mackinlay + +#ifndef MAME_SUN_SUN1_CPU_H +#define MAME_SUN_SUN1_CPU_H + +#pragma once + +#include "sun1_mmu.h" + +#include "bus/multibus/multibus.h" +#include "cpu/m68000/m68000.h" +#include "machine/am9513.h" +#include "machine/z80sio.h" + +class sun1cpu_device + : public device_t + , public device_multibus_interface + , public m68000_device::mmu +{ +public: + sun1cpu_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + +protected: + // device_t implementation + virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_config_complete() override ATTR_COLD; + virtual ioport_constructor device_input_ports() const override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + void cpu_mem(address_map &map); + + void prom0_w(u16 data); + u16 parallel_r() { return 0x1fff; } + + void watchdog_w(int state); + template <unsigned N> void irq_w(int state); + + // m68000_device::mmu boot mode implementation + virtual u16 read_program(offs_t logical, u16 mem_mask) override { return m_cpu_mem.read_word(logical, mem_mask); } + virtual void write_program(offs_t logical, u16 data, u16 mem_mask) override { m_cpu_mem.write_word(logical, data, mem_mask); } + virtual u16 read_data(offs_t logical, u16 mem_mask) override { return m_cpu_mem.read_word(logical, mem_mask); } + virtual void write_data(offs_t logical, u16 data, u16 mem_mask) override { m_cpu_mem.write_word(logical, data, mem_mask); } + virtual u16 read_cpu(offs_t logical, u16 mem_mask) override { return m_cpu_spc.read_word(logical, mem_mask); } + virtual void set_super(bool super) override {} + + bool boot() const { return m_boot.entry().has_value(); } + +private: + required_device<m68000_device> m_cpu; + required_device<sun1mmu_device> m_mmu; + required_device<upd7201_device> m_duart; + required_device<am9513_device> m_stc; + + memory_view m_boot; + + memory_access<24, 1, 0, ENDIANNESS_BIG>::specific m_cpu_mem; + memory_access<24, 1, 0, ENDIANNESS_BIG>::specific m_cpu_spc; + + u8 m_irq; + bool m_watchdog; + bool m_parity; +}; + +DECLARE_DEVICE_TYPE(MULTIBUS_SUN1CPU, sun1cpu_device) + +#endif // MAME_SUN_SUN1_CPU_H diff --git a/src/mame/sun/sun1_mmu.cpp b/src/mame/sun/sun1_mmu.cpp new file mode 100644 index 00000000000..8691e4f132a --- /dev/null +++ b/src/mame/sun/sun1_mmu.cpp @@ -0,0 +1,309 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * This device emulates the Sun-1 memory management unit. + * + * Sources: + * - Sun-1 System Reference Manual, Draft Version 1.0, July 27, 1982, Sun Microsystems, Inc. + * - Sun 68000 Board User's Manual, Revision B, February 1983, Sun Microsystems Inc. + * + * TODO: + * - everything + */ + +#include "emu.h" + +#include "sun1_mmu.h" + +#define VERBOSE (LOG_GENERAL) +#include "logmacro.h" + +enum segment_mask : u16 +{ + SEGMENT_PPTR = 0x003f, + SEGMENT_PROT = 0x0f00, + SEGMENT_CTXT = 0xf000, +}; +enum page_mask : u16 +{ + PAGE_ADDR = 0x0fff, + PAGE_TYPE = 0x3000, // 0=on-board memory, 1=nonexistent, 2=multibus memory, 3=multibus i/o + PAGE_MOD = 0x4000, + PAGE_ACC = 0x8000, +}; +enum mode_mask : unsigned +{ + P_R = 0x04, // read + P_W = 0x02, // write + P_X = 0x01, // execute + + P_RX = P_R | P_X, + P_RW = P_R | P_W, + P_RWX = P_R | P_W | P_X, +}; + +DEFINE_DEVICE_TYPE(SUN1MMU, sun1mmu_device, "sun1mmu", "Sun-1 MMU") + +sun1mmu_device::sun1mmu_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + : device_t(mconfig, SUN1MMU, tag, owner, clock) + , m_space{ + {*this, finder_base::DUMMY_TAG, 0}, + {*this, finder_base::DUMMY_TAG, 1}, + {*this, finder_base::DUMMY_TAG, 2}, + {*this, finder_base::DUMMY_TAG, 3}, + } + , m_error(*this) + , m_context(0) + , m_segment{} + , m_page{} + , m_super(true) +{ +} + +void sun1mmu_device::device_start() +{ + save_item(NAME(m_context)); + save_item(NAME(m_segment)); + save_item(NAME(m_page)); + save_item(NAME(m_stall)); + save_item(NAME(m_super)); + + m_space[0]->specific(m_cpu_mem); + m_space[1]->specific(m_cpu_spc); + m_space[2]->specific(m_bus_mem); + m_space[3]->specific(m_bus_pio); +} + +void sun1mmu_device::device_reset() +{ + m_stall = false; +} + +static bool access(bool const super, unsigned const code, unsigned const mode) +{ + static constexpr unsigned protection[2][16] = + { + // user mode + { + 0 , 0 , 0 , 0 , 0 , 0 , P_R , P_R , + P_RW , P_RW , P_RX , P_RWX, P_RX , P_RX , P_X , P_RWX, + }, + // supervisor mode + { + 0 , P_X , P_R , P_RX , P_RW , P_RWX, P_R , P_RW , + P_R , P_RW , P_RW , P_RW , P_RX , P_RWX, P_RWX, P_RWX, + }, + }; + + return protection[super][code] & mode; +} + +void sun1mmu_device::context_w(u16 data) +{ + LOG("context 0x%04x (%s)\n", data, machine().describe_context()); + + m_context = data & 0xf000U; +} + +u16 sun1mmu_device::segment_r(offs_t offset) +{ + return m_context | m_segment[m_context >> 12][BIT(offset, 14, 6)]; +} + +void sun1mmu_device::segment_w(offs_t offset, u16 data, u16 mem_mask) +{ + LOG("segment[0x%x][0x%02x] 0x%04x (%s)\n", m_context >> 12, BIT(offset, 14, 6), data, machine().describe_context()); + + m_segment[m_context >> 12][BIT(offset, 14, 6)] = data & 0x0fffU; +} + +u16 sun1mmu_device::page_r(offs_t offset) +{ + u16 const segment = m_segment[m_context >> 12][BIT(offset, 14, 6)]; + + return m_page[(segment & SEGMENT_PPTR) << 4 | BIT(offset, 10, 4)]; +} + +void sun1mmu_device::page_w(offs_t offset, u16 data, u16 mem_mask) +{ + u16 const segment = m_segment[m_context >> 12][BIT(offset, 14, 6)]; + + LOG("page[0x%03x] 0x%04x (%s)\n", (segment & SEGMENT_PPTR) << 4 | BIT(offset, 10, 4), data, machine().describe_context()); + + m_page[(segment & SEGMENT_PPTR) << 4 | BIT(offset, 10, 4)] = data; +} + +std::optional<std::pair<unsigned, offs_t>> sun1mmu_device::translate(offs_t const logical, unsigned const mode) +{ + // check for mapped address + if (logical < 0x20'0000) + { + u16 const segment = m_segment[m_context >> 12][BIT(logical, 15, 6)]; + + // check segment map error + if (access(m_super, BIT(segment, 8, 4), mode) || machine().side_effects_disabled()) + { + u16 &page = m_page[(segment & SEGMENT_PPTR) << 4 | BIT(logical, 11, 4)]; + + // update reference and modify bits + if (!machine().side_effects_disabled()) + { + if (mode & P_W) + page |= PAGE_ACC | PAGE_MOD; + else + page |= PAGE_ACC; + } + + return std::pair<unsigned, offs_t>(BIT(page, 12, 2), (page & PAGE_ADDR) << 11 | BIT(logical, 0, 11)); + } + else + LOG("segment map error 0x%08x context %d segment 0x%04x mode %c (%s)\n", + logical, m_context, segment, (mode == P_R) ? 'R' : (mode == P_W) ? 'W' : 'X', machine().describe_context()); + } + else if (m_super || machine().side_effects_disabled()) + // unmapped supervisor access + return std::pair<unsigned, offs_t>(0, logical); + else + LOG("system space error 0x%08x (%s)\n", logical, machine().describe_context()); + + // protection error + return std::nullopt; +} + +template <bool Execute> u16 sun1mmu_device::mmu_read(offs_t logical, u16 mem_mask) +{ + u16 data = 0; + + if (m_stall) + { + m_error(MMU_DEFER); + + return data; + } + + auto const t = translate(logical, Execute ? P_X : P_R); + + if (t.has_value()) + { + auto const [type, physical] = t.value(); + u16 flags = 0; + + switch (type) + { + case 0: + // on-board memory + data = m_cpu_mem.read_word(physical, mem_mask); + break; + case 1: + // nonexistent + LOG("nonexistent_r 0x%08x translated 0x%08x (%s)\n", logical, physical, machine().describe_context()); + m_error(MMU_ERROR); + break; + case 2: + // multibus memory + std::tie(data, flags) = m_bus_mem.read_word_flags(physical, mem_mask); + if (flags) + { + LOG("multibus_r mem 0x%08x translated 0x%08x (%s)\n", logical, physical, machine().describe_context()); + m_stall = true; + m_error(MMU_DEFER); + } + break; + case 3: + // mutibus i/o + std::tie(data, flags) = m_bus_pio.read_word_flags(physical, mem_mask); + if (flags) + { + LOG("multibus_r i/o 0x%08x translated 0x%08x (%s)\n", logical, physical, machine().describe_context()); + m_stall = true; + m_error(MMU_DEFER); + } + break; + } + } + else + m_error(MMU_ERROR); + + return data; +} + +void sun1mmu_device::mmu_write(offs_t logical, u16 data, u16 mem_mask) +{ + if (m_stall) + { + m_error(MMU_DEFER); + + return; + } + + auto const t = translate(logical, P_W); + + if (t.has_value()) + { + auto const [type, physical] = t.value(); + + switch (type) + { + case 0: + // on-board memory + m_cpu_mem.write_word(physical, data, mem_mask); + break; + case 1: + // nonexistent + LOG("nonexistent write 0x%08x translated 0x%08x (%s)\n", logical, physical, machine().describe_context()); + m_error(MMU_ERROR); + break; + case 2: + // multibus memory + if (m_bus_mem.write_word_flags(physical, data, mem_mask)) + { + LOG("multibus_w mem 0x%08x translated 0x%08x (%s)\n", logical, physical, machine().describe_context()); + m_stall = true; + m_error(MMU_DEFER); + } + break; + case 3: + // mutibus i/o + if (m_bus_pio.write_word_flags(physical, data, mem_mask)) + { + LOG("multibus_w i/o 0x%08x translated 0x%08x (%s)\n", logical, physical, machine().describe_context()); + m_stall = true; + m_error(MMU_DEFER); + } + break; + } + } + else + m_error(MMU_ERROR); +} + +u16 sun1mmu_device::read_program(offs_t logical, u16 mem_mask) +{ + return mmu_read<true>(logical, mem_mask); +} + +void sun1mmu_device::write_program(offs_t logical, u16 data, u16 mem_mask) +{ + mmu_write(logical, data, mem_mask); +} + +u16 sun1mmu_device::read_data(offs_t logical, u16 mem_mask) +{ + return mmu_read<false>(logical, mem_mask); +} + +void sun1mmu_device::write_data(offs_t logical, u16 data, u16 mem_mask) +{ + mmu_write(logical, data, mem_mask); +} + +u16 sun1mmu_device::read_cpu(offs_t logical, u16 mem_mask) +{ + return m_cpu_spc.read_word(logical, mem_mask); +} + +void sun1mmu_device::set_super(bool super) +{ + m_super = super; +} diff --git a/src/mame/sun/sun1_mmu.h b/src/mame/sun/sun1_mmu.h new file mode 100644 index 00000000000..12e0e98c06b --- /dev/null +++ b/src/mame/sun/sun1_mmu.h @@ -0,0 +1,73 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +#ifndef MAME_SUN_SUN1_MMU_H +#define MAME_SUN_SUN1_MMU_H + +#pragma once + +#include "cpu/m68000/m68000.h" + +class sun1mmu_device + : public device_t + , public m68000_device::mmu +{ +public: + template <unsigned N, typename T> void set_space(T &&tag, int spacenum) { m_space[N].set_tag(std::forward<T>(tag), spacenum); } + template <unsigned N> void set_space(device_t &base, char const *tag, int spacenum) { m_space[N].set_tag(base, tag, spacenum); } + + enum error_type : unsigned + { + MMU_DEFER = 0, // invalid multibus access + MMU_ERROR = 1, // bus error (system space, segment protection, nonexistent page) + }; + auto error() { return m_error.bind(); } + + sun1mmu_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0); + + // register access + void context_w(u16 data); + u16 segment_r(offs_t offset); + void segment_w(offs_t offset, u16 data, u16 mem_mask); + u16 page_r(offs_t offset); + void page_w(offs_t offset, u16 data, u16 mem_mask); + +protected: + // device_t implementation + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + // m68000_device::mmu implementation + virtual u16 read_program(offs_t addr, u16 mem_mask) override; + virtual void write_program(offs_t addr, u16 data, u16 mem_mask) override; + virtual u16 read_data(offs_t addr, u16 mem_mask) override; + virtual void write_data(offs_t addr, u16 data, u16 mem_mask) override; + virtual u16 read_cpu(offs_t addr, u16 mem_mask) override; + virtual void set_super(bool super) override; + + std::optional<std::pair<unsigned, offs_t>> translate(offs_t const address, unsigned const mode); + template <bool Execute> u16 mmu_read(offs_t logical, u16 mem_mask); + void mmu_write(offs_t logical, u16 data, u16 mem_mask); + +private: + required_address_space m_space[4]; + devcb_write_line m_error; + + memory_access<24, 1, 0, ENDIANNESS_BIG>::specific m_cpu_mem; + memory_access<24, 1, 0, ENDIANNESS_BIG>::specific m_cpu_spc; + + // only 20 of the possible 24 memory address lines are connected + memory_access<20, 1, 0, ENDIANNESS_LITTLE>::specific m_bus_mem; + memory_access<16, 1, 0, ENDIANNESS_LITTLE>::specific m_bus_pio; + + u16 m_context; + u16 m_segment[16][64]; + u16 m_page[1024]; + + bool m_stall; + bool m_super; +}; + +DECLARE_DEVICE_TYPE(SUN1MMU, sun1mmu_device) + +#endif // MAME_SUN_SUN1_MMU_H |