diff --git a/src/devices/machine/68340.cpp b/src/devices/machine/68340.cpp index 1aaa6ee78dd..68f1db3134c 100644 --- a/src/devices/machine/68340.cpp +++ b/src/devices/machine/68340.cpp @@ -1,6 +1,8 @@ // license:BSD-3-Clause // copyright-holders:David Haywood -/* 68340 */ +/* 68340 + * TODO: - convert all modules to devices + */ #include "emu.h" #include "68340.h" @@ -78,23 +80,23 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w ) int base = m68340_base & 0xfffff000; internal->install_readwrite_handler(base + 0x000, base + 0x03f, - read16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_r),this), - write16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_w),this),0xffffffff); + read16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_r),this), + write16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_w),this),0xffffffff); internal->install_readwrite_handler(base + 0x010, base + 0x01f, // Intentionally punches a hole in previous address mapping - read8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_r),this), - write8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_w),this),0xffffffff); + read8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_r),this), + write8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_w),this),0xffffffff); internal->install_readwrite_handler(base + 0x040, base + 0x05f, - read32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_r),this), - write32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_w),this)); + read32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_r),this), + write32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_w),this)); internal->install_readwrite_handler(base + 0x600, base + 0x67f, - read16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_r),this), - write16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_w),this),0xffffffff); + read16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_r),this), + write16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_w),this),0xffffffff); internal->install_readwrite_handler(base + 0x700, base + 0x723, - read32_delegate(FUNC(m68340_cpu_device::m68340_internal_serial_r),this), - write32_delegate(FUNC(m68340_cpu_device::m68340_internal_serial_w),this)); + READ8_DEVICE_DELEGATE(m_serial, m68340_serial, read), + WRITE8_DEVICE_DELEGATE(m_serial, m68340_serial, write),0xffffffff); internal->install_readwrite_handler(base + 0x780, base + 0x7bf, - read32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_r),this), - write32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_w),this)); + read32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_r),this), + write32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_w),this)); } @@ -108,17 +110,27 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w ) } - static ADDRESS_MAP_START( m68340_internal_map, AS_PROGRAM, 32, m68340_cpu_device ) AM_RANGE(0x0003ff00, 0x0003ff03) AM_READWRITE( m68340_internal_base_r, m68340_internal_base_w) ADDRESS_MAP_END +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- +MACHINE_CONFIG_MEMBER( m68340_cpu_device::device_add_mconfig ) + MCFG_DEVICE_ADD("serial", M68340_SERIAL_MODULE, 0) + MCFG_MC68681_IRQ_CALLBACK(DEVWRITELINE("serial", m68340_serial, irq_w)) +MACHINE_CONFIG_END +//************************************************************************** +// LIVE DEVICE +//************************************************************************** m68340_cpu_device::m68340_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : fscpu32_device(mconfig, tag, owner, clock, M68340, 32,32, ADDRESS_MAP_NAME(m68340_internal_map)) + , m_serial(*this, "serial") , m_clock_mode(0) , m_crystal(0) , m_extal(0) @@ -135,7 +147,6 @@ m68340_cpu_device::m68340_cpu_device(const machine_config &mconfig, const char * { m68340SIM = nullptr; m68340DMA = nullptr; - m68340SERIAL = nullptr; m68340TIMER = nullptr; m68340_base = 0; } @@ -165,12 +176,10 @@ void m68340_cpu_device::device_start() m68340SIM = new m68340_sim(); m68340DMA = new m68340_dma(); - m68340SERIAL = new m68340_serial(); m68340TIMER = new m68340_timer(); m68340SIM->reset(); m68340DMA->reset(); - m68340SERIAL->reset(); m68340TIMER->reset(); start_68340_sim(); diff --git a/src/devices/machine/68340.h b/src/devices/machine/68340.h index cd29ad091fa..22ea42cbabc 100644 --- a/src/devices/machine/68340.h +++ b/src/devices/machine/68340.h @@ -51,6 +51,8 @@ class m68340_cpu_device : public fscpu32_device { + friend class m68340_serial; + public: m68340_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -80,8 +82,6 @@ public: WRITE32_MEMBER( m68340_internal_base_w ); READ32_MEMBER( m68340_internal_dma_r ); WRITE32_MEMBER( m68340_internal_dma_w ); - READ32_MEMBER( m68340_internal_serial_r ); - WRITE32_MEMBER( m68340_internal_serial_w ); READ16_MEMBER( m68340_internal_sim_r ); READ8_MEMBER( m68340_internal_sim_ports_r ); READ32_MEMBER( m68340_internal_sim_cs_r ); @@ -104,6 +104,9 @@ public: protected: virtual void device_start() override; virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + required_device m_serial; TIMER_CALLBACK_MEMBER(periodic_interrupt_timer_callback); TIMER_CALLBACK_MEMBER(timer1_callback); @@ -127,7 +130,6 @@ protected: /* 68340 peripheral modules */ m68340_sim* m68340SIM; m68340_dma* m68340DMA; - m68340_serial* m68340SERIAL; m68340_timer* m68340TIMER; uint32_t m68340_base; diff --git a/src/devices/machine/68340ser.cpp b/src/devices/machine/68340ser.cpp index 8a26975cd87..e3b2a382cd3 100644 --- a/src/devices/machine/68340ser.cpp +++ b/src/devices/machine/68340ser.cpp @@ -1,31 +1,171 @@ // license:BSD-3-Clause -// copyright-holders:David Haywood +// copyright-holders:David Haywood, Joakim Larsson Edstrom /* 68340 SERIAL module */ #include "emu.h" #include "68340.h" +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** -READ32_MEMBER( m68340_cpu_device::m68340_internal_serial_r ) +//#define LOG_GENERAL (1U << 0) // Already defined in logmacro.h +#define LOG_SETUP (1U << 1) +#define LOG_READ (1U << 2) +#define LOG_SERIAL (1U << 3) +#define LOG_INT (1U << 4) + +//#define VERBOSE (LOG_SETUP|LOG_READ|LOG_SERIAL|LOG_INT) +#define LOG_OUTPUT_FUNC printf // Needs always to be enabled as the default value 'logerror' is not available here + +#include "logmacro.h" + +//#define LOG(...) LOGMASKED(LOG_GENERAL, __VA_ARGS__) // Already defined in logmacro.h +#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__) +#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__) +#define LOGSERIAL(...) LOGMASKED(LOG_SERIAL, __VA_ARGS__) +#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + +void m68340_serial::device_start() { - assert(m68340SERIAL); - //m68340_serial &serial = *m68340SERIAL; - - int pc = space.device().safe_pc(); - logerror("%08x m68340_internal_serial_r %08x, (%08x)\n", pc, offset*4,mem_mask); - - return 0x00000000; + m_cpu = downcast(owner()); + m68340_serial_device::device_start(); } -WRITE32_MEMBER( m68340_cpu_device::m68340_internal_serial_w ) +READ8_MEMBER( m68340_serial::read ) { - assert(m68340SERIAL); - //m68340_serial &serial = *m68340SERIAL; + LOG("%s\n", FUNCNAME); + int val = 0; - int pc = space.device().safe_pc(); - logerror("%08x m68340_internal_serial_w %08x, %08x (%08x)\n", pc, offset*4,data,mem_mask); + LOGR("%08x %s %08x, (%08x)\n", space.device().safe_pc(), FUNCNAME, offset, mem_mask); + + /*Setting the STP bit stops all clocks within the serial module (including the crystal + or external clock and SCLK), except for the clock from the IMB. The clock from the IMB + remains active to allow CPU32 access to the MCR. The clock stops on the low phase of the + clock and remains stopped until the STP bit is cleared by the CPU32 or a hardware reset. + Accesses to serial module registers while in stop mode produce a bus error. */ + if ( (m_mcrh & REG_MCRH_STP) && offset != REG_MCRH && offset != REG_MCRL) + { + logerror("Attempt to access timer registers while timer clocks are stopped, STP bit in MCR is set!"); + return val; // TODO: Should cause BUSERROR + } + + switch (offset) + { + case REG_MCRH: + val = m_mcrh; + LOGSERIAL("- %08x %s %04x, %04x (%04x) (MCRH - Module Configuration Register High byte)\n", space.device().safe_pc(), FUNCNAME, offset, val, mem_mask); + break; + case REG_MCRL: + val = m_mcrl; + LOGSERIAL("- %08x %s %04x, %04x (%04x) (MCRL - Module Configuration Register Low byte)\n", space.device().safe_pc(), FUNCNAME, offset, val, mem_mask); + break; + case REG_ILR: + val = m_ilr; + LOGSERIAL("- %08x %s %04x, %04x (%04x) (ILR - Interrupt Level Register)\n", space.device().safe_pc(), FUNCNAME, offset, val, mem_mask); + break; + case REG_IVR: + val = m_ivr; + LOGSERIAL("- %08x %s %04x, %04x (%04x) (IVR - Interrupt Vector Register)\n", space.device().safe_pc(), FUNCNAME, offset, val, mem_mask); + break; + } + + + LOGR(" * Reg %02x -> %02x - %s\n", offset, val, + (offset > 0x21) ? "Error - should not happen" : + std::array + {{ + "MCRH", "MCRL", "n/a", "n/a", "ILR", "IVR", "hole", "hole", // 0x00 - 0x07 + "hole", "hole", "hole", "hole", "hole", "hole", "hole", "hole", // 0x08 - 0x0f + "MR1A", "SRA", "n/a", "RBA", "IPCR", "ISR", "n/a", "n/a", // 0x10 - 0x17 + "MR1B", "SRB", "n/a", "RBB", "n/a", "IP", "n/a", "n/a", // 0x18 - 0x1f + "MR2A", "MR2B" }}[offset]); // 0x20 - 0x21 + + return offset >= 0x10 && offset < 0x22 ? m68340_serial_device::read(space, offset - 0x10, mem_mask) : val; } -void m68340_serial::reset() +WRITE8_MEMBER( m68340_serial::write ) +{ + LOG("\n%s\n", FUNCNAME); + LOGSETUP(" * Reg %02x <- %02x - %s\n", offset, data, + (offset > 0x21) ? "Error - should not happen" : + std::array + {{ + "MCRH", "MCRL", "n/a", "n/a", "ILR", "IVR", "hole", "hole", // 0x00 - 0x07 + "hole", "hole", "hole", "hole", "hole", "hole", "hole", "hole", // 0x08 - 0x0f + "MR1A", "CSRA", "CRA", "TBA", "ACR", "IER", "n/a", "n/a", // 0x10 - 0x17 + "MR1B", "CSRB", "CRB", "TBB", "n/a", "OPCR", "OPS", "OPR", // 0x18 - 0x1f + "MR2A", "MR2B" }}[offset]); // 0x20 - 0x21 + + /*Setting the STP bit stops all clocks within the serial module (including the crystal + or external clock and SCLK), except for the clock from the IMB. The clock from the IMB + remains active to allow CPU32 access to the MCR. The clock stops on the low phase of the + clock and remains stopped until the STP bit is cleared by the CPU32 or a hardware reset. + Accesses to serial module registers while in stop mode produce a bus error. */ + if ( (m_mcrh & REG_MCRH_STP) && offset != REG_MCRH && offset != REG_MCRL) + { + logerror("Attempt to access timer registers while timer clocks are stopped, STP bit in MCR is set!"); + return; // TODO: Should cause BUSERROR + } + + switch (offset) + { + case REG_MCRH: + m_mcrh = data; + LOGSERIAL("PC: %08x %s %04x, %04x (%04x) (MCRH - Module Configuration Register High byte)\n", space.device().safe_pc(), FUNCNAME, offset, data, mem_mask); + LOGSERIAL("- Clocks are %s\n", data & REG_MCRH_STP ? "stopped" : "running"); + LOGSERIAL("- Freeze signal %s - not implemented\n", data & REG_MCRH_FRZ1 ? "stops at character boundary" : "is ignored"); + LOGSERIAL("- CTS capture clock: %s - not implemented\n", data & REG_MCRH_ICCS ? "SCLK" : "Crystal"); + break; + case REG_MCRL: + m_mcrl = data; + LOGSERIAL("PC: %08x %s %04x, %04x (%04x) (MCRL - Module Configuration Register Low byte)\n", space.device().safe_pc(), FUNCNAME, offset, data, mem_mask); + LOGSERIAL("- Supervisor registers %s - not implemented\n", data & REG_MCRL_SUPV ? "requries supervisor privileges" : "can be accessed by user privileged software"); + LOGSERIAL("- Interrupt Arbitration level: %02x - not implemented\n", data & REG_MCRL_ARBLV); + break; + case REG_ILR: + m_ilr = data; + LOGSERIAL("PC: %08x %s %04x, %04x (%04x) (ILR - Interrupt Level Register)\n", space.device().safe_pc(), FUNCNAME, offset, data, mem_mask); + LOGSERIAL("- Interrupt Level: %02x\n", data & REG_ILR_MASK); + break; + case REG_IVR: + m_ivr = data; + LOGSERIAL("PC: %08x %s %04x, %04x (%04x) (IVR - Interrupt Vector Register)\n", space.device().safe_pc(), FUNCNAME, offset, data, mem_mask); + LOGSERIAL("- Interrupt Vector: %02x\n", data); + break; + default: + if (offset >= 0x10 && offset < 0x22) m68340_serial_device::write(space, offset - 0x10, data, mem_mask); + } + +} + +WRITE_LINE_MEMBER( m68340_serial::irq_w ) +{ + LOGINT("IRQ!\n%s\n", FUNCNAME); + if (m_ilr > 0) + { + if (((m_cpu->m68340SIM->m_avr_rsr >> (8 + m_ilr)) & 1) != 0) // use autovector ? + { + LOGINT("- Autovector level %d\n", m_ilr); + m_cpu->set_input_line(m_ilr, HOLD_LINE); + } + else // otherwise not... + { + LOGINT("- Vector %02x level %d\n", m_ivr, m_ilr); + m_cpu->set_input_line_and_vector(m_ilr, HOLD_LINE, m_ivr); + } + } +} + +m68340_serial::m68340_serial(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : m68340_serial_device(mconfig, "serial", owner, clock) { } + +DEFINE_DEVICE_TYPE(M68340_SERIAL_MODULE, m68340_serial, "m68340 serial module", "Motorola 68340 Serial Module") diff --git a/src/devices/machine/68340ser.h b/src/devices/machine/68340ser.h index c5fcd028bdd..271b26dafcd 100644 --- a/src/devices/machine/68340ser.h +++ b/src/devices/machine/68340ser.h @@ -5,11 +5,57 @@ #pragma once +#include "machine/mc68681.h" -class m68340_serial +class m68340_cpu_device; + +class m68340_serial : public m68340_serial_device { + friend class m68340_cpu_device; + public: - void reset(); + m68340_serial(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device-level overrides + virtual void device_start() override; + + READ8_MEMBER( read ) override; + WRITE8_MEMBER( write ) override; + DECLARE_WRITE_LINE_MEMBER(irq_w); + +protected: + m68340_cpu_device *m_cpu; + + // Module registers not in the DUART part + uint8_t m_mcrh; + uint8_t m_mcrl; + uint8_t m_ilr; + uint8_t m_ivr; + + enum { + REG_MCRH = 0, + REG_MCRL = 1, + REG_ILR = 4, + REG_IVR = 5, + }; + + enum { + REG_MCRH_STP = 0x80, + REG_MCRH_FRZ1 = 0x40, + REG_MCRH_FRZ2 = 0x20, + REG_MCRH_ICCS = 0x10, + }; + + enum { + REG_MCRL_SUPV = 0x80, + REG_MCRL_ARBLV = 0x0f, + }; + + enum { + REG_ILR_MASK = 0x07 + }; }; +DECLARE_DEVICE_TYPE(M68340_SERIAL_MODULE, m68340_serial) + #endif // MAME_MACHINE_68340SER_H diff --git a/src/devices/machine/68340sim.cpp b/src/devices/machine/68340sim.cpp index 701369269f8..ddc7516b237 100644 --- a/src/devices/machine/68340sim.cpp +++ b/src/devices/machine/68340sim.cpp @@ -18,8 +18,9 @@ #define LOG_DATA (1U << 6) #define LOG_INT (1U << 7) #define LOG_PIT (1U << 8) +#define LOG_CS (1U << 9) -//#define VERBOSE (LOG_SETUP) +//#define VERBOSE (LOG_CS) #define LOG_OUTPUT_FUNC printf // Needs always to be enabled as the default value 'logerror' is not available here #include "logmacro.h" @@ -33,6 +34,7 @@ #define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__) #define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__) #define LOGPIT(...) LOGMASKED(LOG_PIT, __VA_ARGS__) +#define LOGCS(...) LOGMASKED(LOG_CS, __VA_ARGS__) #ifdef _MSC_VER #define FUNCNAME __func__ @@ -45,7 +47,7 @@ READ16_MEMBER( m68340_cpu_device::m68340_internal_sim_r ) LOGR("%s\n", FUNCNAME); assert(m68340SIM); m68340_sim &sim = *m68340SIM; - int val = space.machine().rand(); + int val = 0; int pc = space.device().safe_pc(); switch (offset * 2) @@ -86,14 +88,15 @@ READ16_MEMBER( m68340_cpu_device::m68340_internal_sim_r ) break; default: - LOGSIM("- %08x %s %04x, (%04x)\n", pc, FUNCNAME, offset * 2, mem_mask); + logerror("- %08x %s %04x, (%04x) (unsupported register)\n", pc, FUNCNAME, offset * 2, mem_mask); + LOGSIM("- %08x %s %04x, (%04x) (unsupported register)\n", pc, FUNCNAME, offset * 2, mem_mask); } LOGR(" * Reg %02x -> %02x - %s\n", offset * 2, val, ((offset * 2) >= 0x10 && (offset * 2) < 0x20) || (offset * 2) >= 0x60 ? "Error - should not happen" : std::array {{"MCR", "reserved", "SYNCR", "AVR/RSR", "SWIV/SYPCR", "PICR", "PITR", "SWSR"}}[(offset * 2) <= m68340_sim::REG_AVR_RSR ? offset : offset - 0x10 + 0x04]); - return 0x0000; + return val; } WRITE16_MEMBER( m68340_cpu_device::m68340_internal_sim_w ) @@ -376,14 +379,24 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_sim_cs_w ) { LOG("%s\n", FUNCNAME); offset += m68340_sim::REG_AM_CS0>>2; - LOGSETUP("- %08x %s %08x, %08x (%08x) - not implemented\n", pc, FUNCNAME, offset*4,data,mem_mask); + + if (offset & 1) + { + LOGCS("%08x Base address CS%d %08x, %08x (%08x) ", pc, (offset - 0x10) / 2, offset * 4, data, mem_mask); + LOGCS("- Base: %08x BFC:%02x WP:%d FTE:%d NCS:%d Valid: %s\n", data & 0xffffff00, (data & 0xf0) >> 4, data & 0x08 ? 1 : 0, data & 0x04 ? 1 : 0, data & 0x02 ? 1 : 0, data & 0x01 ? "Yes" : "No"); + } + else + { + LOGCS("%08x Address mask CS%d %08x, %08x (%08x) ", pc, (offset - 0x10) / 2, offset * 4, data, mem_mask); + LOGCS("- Mask: %08x FCM:%02x DD:%d PS: %s\n", data & 0xffffff00, (data & 0xf0) >> 4, (data >> 2) & 0x03, std::array{{"Reserved", "16-Bit", "8-bit", "External DSACK response"}}[data & 0x03]); + } assert(m68340SIM); m68340_sim &sim = *m68340SIM; int pc = space.device().safe_pc(); - switch (offset<<2) + switch (offset << 2) { case m68340_sim::REG_AM_CS0: COMBINE_DATA(&sim.m_am[0]); diff --git a/src/devices/machine/68340tmu.cpp b/src/devices/machine/68340tmu.cpp index ab4443fa818..0fb359dbddf 100644 --- a/src/devices/machine/68340tmu.cpp +++ b/src/devices/machine/68340tmu.cpp @@ -47,7 +47,7 @@ READ16_MEMBER( m68340_cpu_device::m68340_internal_timer_r ) int val = 0; int pc = space.device().safe_pc(); - logerror("%08x m68340_internal_timer_r %08x, (%08x)\n", pc, offset * 2, mem_mask); + LOGR("%08x m68340_internal_timer_r %08x, (%08x)\n", pc, offset * 2, mem_mask); int id = (offset * 2) < 0x40 ? 0 : 1; // Timer1 or Timer2 @@ -257,7 +257,7 @@ WRITE16_MEMBER( m68340_cpu_device::m68340_internal_timer_w ) } int pc = space.device().safe_pc(); - logerror("%08x m68340_internal_timer_w %08x, %08x (%08x)\n", pc, offset * 2, data, mem_mask); + LOG("%08x m68340_internal_timer_w %08x, %08x (%08x)\n", pc, offset * 2, data, mem_mask); } void m68340_timer::reset() diff --git a/src/devices/machine/68340tmu.h b/src/devices/machine/68340tmu.h index 3bcbd844184..8e49914a436 100644 --- a/src/devices/machine/68340tmu.h +++ b/src/devices/machine/68340tmu.h @@ -41,7 +41,7 @@ public: REG_MCR_STP = 0x8000, REG_MCR_FRZ1 = 0x4000, REG_MCR_FRZ2 = 0x2000, - REG_MCR_SUPV = 0x0800, + REG_MCR_SUPV = 0x0080, REG_MCR_ARBLV = 0x000f, }; diff --git a/src/devices/machine/mc68681.cpp b/src/devices/machine/mc68681.cpp index 956dbe2071b..0659dc3dc29 100644 --- a/src/devices/machine/mc68681.cpp +++ b/src/devices/machine/mc68681.cpp @@ -4,17 +4,20 @@ 2681 DUART 68681 DUART 28C94 QUART + 68340 serial module Written by Mariusz Wojcieszek Updated by Jonathan Gevaryahu AKA Lord Nightmare Improved interrupt handling by R. Belmont Rewrite and modernization in progress by R. Belmont + Addition of 68340 serial module support by Edstrom */ #include "emu.h" #include "mc68681.h" //#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC printf #include "logmacro.h" @@ -59,6 +62,7 @@ static const int baud_rate_ACR_1[] = { 75, 110, 134, 150, 300, 600, 1200, 2000, // device type definition DEFINE_DEVICE_TYPE(MC68681, mc68681_device, "mc68681", "MC68681 DUART") DEFINE_DEVICE_TYPE(SC28C94, sc28c94_device, "sc28c94", "SC28C94 QUART") +DEFINE_DEVICE_TYPE(M68340SERIAL, m68340_serial_device, "m68340ser", "M68340 SERIAL MODULE") DEFINE_DEVICE_TYPE(MC68681_CHANNEL, mc68681_channel, "mc68681_channel", "MC68681 DUART channel") @@ -99,6 +103,18 @@ sc28c94_device::sc28c94_device(const machine_config &mconfig, const char *tag, d { } +//-------------------------------------------------------------------------------------------------------------------- +// The read and write methods are meant to catch all differences in the register model between 68681 and 68340 +// serial module. Eg some registers are (re)moved into the 68340 like the vector register. There are also no counter +// in the 68340. The CSR clock register is also different for the external clock modes. The implementation assumes +// that the code knows all of this and will not warn if those registers are accessed as it could be ported code. +// TODO: A lot of subtle differences and also detect misuse of unavailable registers as they should be ignored +//-------------------------------------------------------------------------------------------------------------------- +m68340_serial_device::m68340_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mc68681_base_device(mconfig, M68340SERIAL, tag, owner, clock) +{ +} + //------------------------------------------------- // static_set_clocks - configuration helper to set // the external clocks @@ -171,6 +187,11 @@ MACHINE_CONFIG_MEMBER( sc28c94_device::device_add_mconfig ) MCFG_DEVICE_ADD(CHAND_TAG, MC68681_CHANNEL, 0) MACHINE_CONFIG_END +MACHINE_CONFIG_MEMBER( m68340_serial_device::device_add_mconfig ) + MCFG_DEVICE_ADD(CHANA_TAG, MC68681_CHANNEL, 0) + MCFG_DEVICE_ADD(CHANB_TAG, MC68681_CHANNEL, 0) +MACHINE_CONFIG_END + void mc68681_base_device::update_interrupts() { /* update SR state and update interrupt ISR state for the following bits: @@ -345,6 +366,30 @@ TIMER_CALLBACK_MEMBER( mc68681_base_device::duart_timer_callback ) } +READ8_MEMBER( m68340_serial_device::read ) +{ + uint8_t r = 0; + + switch (offset) + { + case 0x00: /* MR1A - does not share register address with MR2A */ + r = m_chanA->read_MR1(); + break; + case 0x08: /* MR1B - does not share register address with MR2B */ + r = m_chanB->read_MR1(); + break; + case 0x10: /* MR2A - does not share register address with MR1A */ + r = m_chanA->read_MR2(); + break; + case 0x11: /* MR2B - does not share register address with MR1B */ + r = m_chanB->read_MR2(); + break; + default: + r = mc68681_base_device::read(space, offset, mem_mask); + } + return r; +} + READ8_MEMBER( sc28c94_device::read ) { uint8_t r = 0; @@ -477,6 +522,29 @@ READ8_MEMBER( mc68681_base_device::read ) return r; } +WRITE8_MEMBER( m68340_serial_device::write ) +{ + //printf("Duart write %02x -> %02x\n", data, offset); + + switch(offset) + { + case 0x00: /* MR1A - does not share register address with MR2A */ + m_chanA->write_MR1(data); + break; + case 0x08: /* MR1B - does not share register address with MR2B */ + m_chanB->write_MR1(data); + break; + case 0x10: /* MR2A - does not share register address with MR1A */ + m_chanA->write_MR2(data); + break; + case 0x11: /* MR2B - does not share register address with MR1B */ + m_chanB->write_MR2(data); + break; + default: + mc68681_base_device::write(space, offset, data, mem_mask); + } +} + WRITE8_MEMBER( sc28c94_device::write ) { offset &= 0x1f; @@ -810,7 +878,7 @@ void mc68681_channel::rcv_complete() { receive_register_extract(); -// printf("%s ch %d rcv complete\n", tag(), m_ch); + //printf("%s ch %d rcv complete\n", tag(), m_ch); if ( rx_enabled ) { @@ -832,7 +900,7 @@ void mc68681_channel::rcv_complete() void mc68681_channel::tra_complete() { -// printf("%s ch %d Tx complete\n", tag(), m_ch); + //printf("%s ch %d Tx complete\n", tag(), m_ch); tx_ready = 1; SR |= STATUS_TRANSMITTER_READY; @@ -996,7 +1064,7 @@ uint8_t mc68681_channel::read_rx_fifo() { uint8_t rv; -// printf("read_rx_fifo: rx_fifo_num %d\n", rx_fifo_num); + //printf("read_rx_fifo: rx_fifo_num %d\n", rx_fifo_num); if ( rx_fifo_num == 0 ) { @@ -1014,7 +1082,7 @@ uint8_t mc68681_channel::read_rx_fifo() rx_fifo_num--; update_interrupts(); -// printf("Rx read %02x\n", rv); + //printf("Rx read %02x\n", rv); return rv; } @@ -1064,7 +1132,7 @@ void mc68681_channel::write_chan_reg(int reg, uint8_t data) CSR = data; tx_baud_rate = m_uart->calc_baud(m_ch, data & 0xf); rx_baud_rate = m_uart->calc_baud(m_ch, (data>>4) & 0xf); -// printf("%s ch %d CSR %02x Tx baud %d Rx baud %d\n", tag(), m_ch, data, tx_baud_rate, rx_baud_rate); + //printf("%s ch %d CSR %02x Tx baud %d Rx baud %d\n", tag(), m_ch, data, tx_baud_rate, rx_baud_rate); set_rcv_rate(rx_baud_rate); set_tra_rate(tx_baud_rate); break; @@ -1149,7 +1217,7 @@ void mc68681_channel::recalc_framing() break; } -// printf("%s ch %d MR1 %02x MR2 %02x => %d bits / char, %d stop bits, parity %d\n", tag(), m_ch, MR1, MR2, (MR1 & 3)+5, stopbits, parity); + //printf("%s ch %d MR1 %02x MR2 %02x => %d bits / char, %d stop bits, parity %d\n", tag(), m_ch, MR1, MR2, (MR1 & 3)+5, stopbits, parity); set_data_frame(1, (MR1 & 3)+5, parity, stopbits); } @@ -1241,7 +1309,7 @@ void mc68681_channel::write_TX(uint8_t data) printf("Write %02x to TX when TX not ready!\n", data); }*/ - //printf("%s ch %d Tx %02x\n", tag(), m_ch, data); + //printf("%s ch %d Tx %c [%02x]\n", tag(), m_ch, isprint(data) ? data : ' ', data); tx_ready = 0; SR &= ~STATUS_TRANSMITTER_READY; diff --git a/src/devices/machine/mc68681.h b/src/devices/machine/mc68681.h index d1f9d3c96d6..47e15e3c318 100644 --- a/src/devices/machine/mc68681.h +++ b/src/devices/machine/mc68681.h @@ -41,6 +41,10 @@ #define MCFG_SC28C94_D_TX_CALLBACK(_cb) \ devcb = &sc28c94_device::set_d_tx_cb(*device, DEVCB_##_cb); +// M68340SERIAL specific callbacks +#define MCFG_M68340SERIAL_ADD(_tag, _clock) \ + MCFG_DEVICE_ADD(_tag, M68340SERIAL, _clock) + #define MC68681_RX_FIFO_SIZE 3 // forward declaration @@ -71,6 +75,12 @@ public: uint8_t get_chan_CSR(); + // Access methods needed for 68340 serial module register model + uint8_t read_MR1(){ return MR1; } + uint8_t read_MR2(){ return MR2; } + void write_MR1(uint8_t data){ MR1 = data; } + void write_MR2(uint8_t data){ MR2 = data; } + private: /* Registers */ uint8_t CR; /* Command register */ @@ -230,8 +240,23 @@ protected: private: }; +class m68340_serial_device : public mc68681_base_device +{ +public: + m68340_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual DECLARE_READ8_MEMBER(read) override; + virtual DECLARE_WRITE8_MEMBER(write) override; + +protected: + virtual void device_add_mconfig(machine_config &config) override; + +private: +}; + DECLARE_DEVICE_TYPE(MC68681, mc68681_device) DECLARE_DEVICE_TYPE(SC28C94, sc28c94_device) +DECLARE_DEVICE_TYPE(M68340SERIAL, m68340_serial_device) DECLARE_DEVICE_TYPE(MC68681_CHANNEL, mc68681_channel) #endif // MAME_MACHINE_MC68681_H diff --git a/src/mame/drivers/dbox.cpp b/src/mame/drivers/dbox.cpp index 62966abc959..2ed325e9f89 100644 --- a/src/mame/drivers/dbox.cpp +++ b/src/mame/drivers/dbox.cpp @@ -621,7 +621,6 @@ static MACHINE_CONFIG_START( dbox ) //MCFG_MC68340_TOUT2_OUTPUT_CB(DEVWRITELINE("dcs", descrambler_device, txd_receiver)) //MCFG_MC68340_TGATE2_INPUT_CB(DEVREADLINE("dsc", descrambler_device, rxd_receiver)) -#if 0 /* Configure the serial ports */ #define CHA ":rs232" #define CHB ":modem" @@ -632,7 +631,6 @@ static MACHINE_CONFIG_START( dbox ) MCFG_RS232_RXD_HANDLER (DEVWRITELINE (":maincpu:serial", m68340_serial, rx_a_w)) MCFG_RS232_PORT_ADD (CHB, default_rs232_devices, "terminal") MCFG_RS232_RXD_HANDLER (DEVWRITELINE (":maincpu:serial", m68340_serial, rx_b_w)) -#endif /* Add the boot flash */ MCFG_AMD_29F800B_16BIT_ADD("flash")