From 5f7f9c4933cd830174615e820688d157bde952c3 Mon Sep 17 00:00:00 2001 From: Joakim Larsson Edstrom Date: Mon, 4 Sep 2017 22:09:00 +0200 Subject: [PATCH] 68340: deskeletonized the serial module as a device derived from the duart device defined in mc68681.cpp --- src/devices/machine/68340.cpp | 43 ++++---- src/devices/machine/68340.h | 8 +- src/devices/machine/68340ser.cpp | 170 ++++++++++++++++++++++++++++--- src/devices/machine/68340ser.h | 50 ++++++++- 4 files changed, 234 insertions(+), 37 deletions(-) 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