diff options
Diffstat (limited to 'src/devices/machine/psion_asic4.cpp')
-rw-r--r-- | src/devices/machine/psion_asic4.cpp | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/src/devices/machine/psion_asic4.cpp b/src/devices/machine/psion_asic4.cpp new file mode 100644 index 00000000000..0ed603eaa74 --- /dev/null +++ b/src/devices/machine/psion_asic4.cpp @@ -0,0 +1,170 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/****************************************************************************** + + Psion ASIC4 + + ASIC4 is a serial protocol slave IC for addressing memory and general + memory-mapped peripherals. It is used in SSDs to convert SIBO serial protocol + signals into addresses within the memory range of the memory pack. ASIC4 was + designed to be a cut-down version of ASIC5 which was the original SIBO serial + protocol slave chip. + + A27 A26 A25 A24 D7 D6 D5 D4 D3 D2 D1 D0 + M Peripheral Id Memory Type No. devices Memory Size + 1 0 0 0 No peripheral 0 0 0 RAM 0 0 1 device 0 0 0 No memory + 0 0 1 Turbo RS232 (16550) 0 0 1 Type 1 Flash 0 1 2 devices 0 0 1 32K + 0 1 0 3Fax 0 1 0 Type 2 Flash 1 0 3 devices 0 1 0 64K + 1 1 1 Extended info in ROM 1 1 0 ROM 1 1 4 devices 0 1 1 128K + 1 0 0 256K + 1 0 1 512K + 1 1 0 1M + +******************************************************************************/ + +#include "emu.h" +#include "psion_asic4.h" + +#define VERBOSE 0 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + + +DEFINE_DEVICE_TYPE(PSION_ASIC4, psion_asic4_device, "psion_asic4", "Psion ASIC4") + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +psion_asic4_device::psion_asic4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, PSION_ASIC4, tag, owner, clock) + , device_memory_interface(mconfig, *this) + , m_space_config("program", ENDIANNESS_LITTLE, 8, 28) +{ +} + + +device_memory_interface::space_config_vector psion_asic4_device::memory_space_config() const +{ + return space_config_vector{ std::make_pair(0, &m_space_config) }; +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void psion_asic4_device::device_start() +{ + m_space = &space(0); + + save_item(NAME(m_addr_latch)); + save_item(NAME(m_addr_writes)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void psion_asic4_device::device_reset() +{ + m_addr_latch = 0x00; + m_addr_writes = 0; +} + + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +void psion_asic4_device::data_w(uint16_t data) +{ + switch (data & 0x300) + { + case NULL_FRAME: + device_reset(); + break; + + case CONTROL_FRAME: + m_sibo_control = data & 0xff; + + // reset address register to LSB + m_addr_writes = 0; + break; + + case DATA_FRAME: + data &= 0xff; + switch (m_sibo_control & 0x0f) + { + case 0x00: // Data register + LOG("%s data_w: Data register %02x\n", machine().describe_context(), data); + m_space->write_byte(m_addr_latch, data); + break; + + case 0x01: // Device Size register + LOG("%s data_w: Device Size register %02x\n", machine().describe_context(), data); + break; + + case 0x02: // Address Increment register + LOG("%s data_w: Address Increment register %02x\n", machine().describe_context(), data); + m_addr_latch = (m_addr_latch & 0xffffff0) | ((m_addr_latch + 1) & 0x0f); + break; + + case 0x03: // Address register + LOG("%s data_w: Address register %02x\n", machine().describe_context(), data); + if (m_addr_writes == 0) + m_addr_latch = 0x00; + m_addr_latch |= data << (m_addr_writes << 3); + m_addr_writes = (m_addr_writes + 1) & 3; + break; + + case 0x07: // Control register + LOG("%s data_w: Control register %02x\n", machine().describe_context(), data); + break; + + default: + LOG("%s data_w: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data); + break; + } + break; + } +} + +uint8_t psion_asic4_device::data_r() +{ + uint8_t data = 0x00; + + switch (m_sibo_control & 0xc0) + { + case 0x40: // SerialSelect + switch (m_sibo_control & 0x0f) + { + case 0x06: // Asic4Id + data = m_info_byte & 0xff; // A4InfoByte + break; + } + break; + + case 0xc0: // SerialRead + switch (m_sibo_control & 0x0f) + { + case 0x00: // Data register + data = m_space->read_byte(m_addr_latch); + LOG("%s data_r: Data register %02x\n", machine().describe_context(), data); + m_addr_latch++; + break; + + case 0x01: // Input register + data = (m_info_byte >> 4) & 0xf0; + LOG("%s data_r: Input register %02x\n", machine().describe_context(), data); + break; + + default: + LOG("%s data_r: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data); + break; + } + break; + } + + return data; +} |