diff options
Diffstat (limited to 'src/devices/machine/tsb12lv01a.cpp')
-rw-r--r-- | src/devices/machine/tsb12lv01a.cpp | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/src/devices/machine/tsb12lv01a.cpp b/src/devices/machine/tsb12lv01a.cpp new file mode 100644 index 00000000000..8c352e16032 --- /dev/null +++ b/src/devices/machine/tsb12lv01a.cpp @@ -0,0 +1,275 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/************************************************************* + + Texas Instruments TSB12LV01A/TSB12LV01AI IEEE 1394-1995 + High-Speed Serial-Bus Link-Layer Controller + + Skeleton device + +**************************************************************/ + +#include "emu.h" +#include "tsb12lv01a.h" + +#define LOG_READS (1U << 1) +#define LOG_WRITES (1U << 2) +#define LOG_UNKNOWNS (1U << 3) +#define LOG_IRQS (1U << 4) +#define LOG_ALL (LOG_READS | LOG_WRITES | LOG_UNKNOWNS | LOG_IRQS) + +#define VERBOSE (LOG_ALL) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(TSB12LV01A, tsb12lv01a_device, "tsb12lv01a", "TSB12LV01A IEEE 1394 Link Controller") + +tsb12lv01a_device::tsb12lv01a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, TSB12LV01A, tag, owner, clock) + , m_int_cb(*this) + , m_phy_read_cb(*this, 0x00) + , m_phy_write_cb(*this) +{ +} + +void tsb12lv01a_device::device_start() +{ + save_item(NAME(m_version)); + save_item(NAME(m_node_address)); + save_item(NAME(m_ctrl)); + save_item(NAME(m_int_status)); + save_item(NAME(m_int_mask)); + save_item(NAME(m_cycle_timer)); + save_item(NAME(m_isoch_port_num)); + save_item(NAME(m_fifo_ctrl)); + save_item(NAME(m_diag_ctrl)); + save_item(NAME(m_phy_access)); + save_item(NAME(m_atf_status)); + save_item(NAME(m_itf_status)); + save_item(NAME(m_grf_status)); +} + +void tsb12lv01a_device::device_reset() +{ + m_version = 0x30313042; + m_node_address = 0xffff0000; + m_ctrl = 0x00000000; + m_int_status = 0x10000000; + m_int_mask = 0x00000000; + m_cycle_timer = 0x00000000; + m_isoch_port_num = 0x00000000; + m_fifo_ctrl = 0x00000000; + m_diag_ctrl = 0x00000000; + m_phy_access = 0x00000000; + m_atf_status = 0x00000000; + m_itf_status = 0x00000000; + m_grf_status = 0x00000000; +} + +void tsb12lv01a_device::phy_reset_w(int state) +{ + if (state) + { + set_interrupt(INT_PHRST); + } +} + +void tsb12lv01a_device::set_interrupt(uint32_t bit) +{ + m_int_status |= bit; + LOGMASKED(LOG_IRQS, "Setting IRQ: %08x\n", bit); + check_interrupts(); +} + +void tsb12lv01a_device::check_interrupts() +{ + const uint32_t active_bits = m_int_status & m_int_mask; + if (active_bits & 0x7fffffff) + m_int_status |= INT_INT; + else + m_int_status &= ~INT_INT; + + const int state = (m_int_status & m_int_mask & INT_INT) ? 1 : 0; + LOGMASKED(LOG_IRQS, "Active IRQs: %08x, %sing IRQ\n", active_bits, state ? "rais" : "lower"); + m_int_cb(state); +} + +void tsb12lv01a_device::reset_tx() +{ + // TODO + set_interrupt(INT_TXRDY); +} + +void tsb12lv01a_device::reset_rx() +{ +} + +void tsb12lv01a_device::clear_atf() +{ + const uint32_t atf_size = (m_fifo_ctrl & FIFO_CTRL_ATF_SIZE_MASK) >> FIFO_CTRL_ATF_SIZE_SHIFT; + m_atf_status &= ~(ATF_STATUS_FULL | ATF_STATUS_CONERR | ATF_STATUS_ADRCOUNTER_MASK | ATF_STATUS_ATFSPACE_MASK); + m_atf_status |= ATF_STATUS_EMPTY; + m_atf_status |= (atf_size << ATF_STATUS_ATFSPACE_SHIFT); +} + +void tsb12lv01a_device::clear_itf() +{ + const uint32_t itf_size = (m_fifo_ctrl & FIFO_CTRL_ITF_SIZE_MASK) >> FIFO_CTRL_ITF_SIZE_SHIFT; + m_itf_status &= ~(ITF_STATUS_FULL | ITF_STATUS_ITFSPACE_MASK); + m_itf_status |= ITF_STATUS_EMPTY; + m_itf_status |= (itf_size << ITF_STATUS_ITFSPACE_SHIFT); +} + +void tsb12lv01a_device::clear_grf() +{ + const uint32_t atf_size = (m_fifo_ctrl & FIFO_CTRL_ATF_SIZE_MASK) >> FIFO_CTRL_ATF_SIZE_SHIFT; + const uint32_t itf_size = (m_fifo_ctrl & FIFO_CTRL_ITF_SIZE_MASK) >> FIFO_CTRL_ITF_SIZE_SHIFT; + const uint32_t grf_size = 0x200 - (atf_size + itf_size); + m_grf_status &= ~(GRF_STATUS_CD | GRF_STATUS_PACCOM | GRF_STATUS_GRFTOTAL_MASK | GRF_STATUS_WRITECOUNT_MASK); + m_grf_status |= GRF_STATUS_EMPTY; + m_grf_status |= grf_size << GRF_STATUS_GRFSIZE_SHIFT; +} + +uint32_t tsb12lv01a_device::read(offs_t offset) +{ + switch (offset) + { + case 0x00: + LOGMASKED(LOG_READS, "%s: TSB12 Version register read: %08x\n", machine().describe_context(), m_version); + return m_version; + case 0x04: + LOGMASKED(LOG_READS, "%s: TSB12 Node Address register read: %08x\n", machine().describe_context(), m_node_address); + return m_node_address; + case 0x08: + LOGMASKED(LOG_READS, "%s: TSB12 Control register read: %08x\n", machine().describe_context(), m_ctrl); + return m_ctrl; + case 0x0c: + LOGMASKED(LOG_READS, "%s: TSB12 Interrupt Status register read: %08x\n", machine().describe_context(), m_int_status); + return m_int_status; + case 0x10: + LOGMASKED(LOG_READS, "%s: TSB12 Interrupt Mask register read: %08x\n", machine().describe_context(), m_int_mask); + return m_int_mask; + case 0x14: + LOGMASKED(LOG_READS, "%s: TSB12 Cycle Timer register read: %08x\n", machine().describe_context(), m_cycle_timer); + return m_cycle_timer; + case 0x18: + LOGMASKED(LOG_READS, "%s: TSB12 Isochronous Receive-Port Number register read: %08x\n", machine().describe_context(), m_isoch_port_num); + return m_isoch_port_num; + case 0x1c: + LOGMASKED(LOG_READS, "%s: TSB12 FIFO Control register read: %08x\n", machine().describe_context(), m_fifo_ctrl); + return m_fifo_ctrl; + case 0x20: + LOGMASKED(LOG_READS, "%s: TSB12 Diagnostic Control register read: %08x\n", machine().describe_context(), m_diag_ctrl); + return m_diag_ctrl; + case 0x24: + LOGMASKED(LOG_READS, "%s: TSB12 Phy-Chip Access register read: %08x\n", machine().describe_context(), m_phy_access); + return m_phy_access; + case 0x30: + LOGMASKED(LOG_READS, "%s: TSB12 Asynchronous Transmit-FIFO (ATF) register read: %08x\n", machine().describe_context(), m_atf_status); + return m_atf_status; + case 0x34: + LOGMASKED(LOG_READS, "%s: TSB12 Isochronous Transmit-FIFO (ITF) register read: %08x\n", machine().describe_context(), m_itf_status); + return m_itf_status; + case 0x3c: + LOGMASKED(LOG_READS, "%s: TSB12 General Receive-FIFO (GRF) register read: %08x\n", machine().describe_context(), m_grf_status); + return m_grf_status; + default: + LOGMASKED(LOG_READS | LOG_UNKNOWNS, "%s: TSB12 Unknown read: %08x\n", machine().describe_context(), offset << 2); + return 0; + } +} + +void tsb12lv01a_device::write(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset) + { + case 0x00: + LOGMASKED(LOG_WRITES, "%s: TSB12 Version register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0x04: + LOGMASKED(LOG_WRITES, "%s: TSB12 Node Address register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0x08: + LOGMASKED(LOG_WRITES, "%s: TSB12 Control register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + if (data & CTRL_RSTTX) + { + data &= ~CTRL_RSTTX; + reset_tx(); + } + if (data & CTRL_RSTRX) + { + data &= ~CTRL_RSTRX; + reset_rx(); + } + COMBINE_DATA(&m_ctrl); + break; + case 0x0c: + LOGMASKED(LOG_WRITES, "%s: TSB12 Interrupt Status register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_int_status &= ~data; + check_interrupts(); + break; + case 0x10: + LOGMASKED(LOG_WRITES, "%s: TSB12 Interrupt Mask register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_int_mask); + check_interrupts(); + break; + case 0x14: + LOGMASKED(LOG_WRITES, "%s: TSB12 Cycle Timer register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0x18: + LOGMASKED(LOG_WRITES, "%s: TSB12 Isochronous Receive-Port Number register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0x1c: + LOGMASKED(LOG_WRITES, "%s: TSB12 FIFO Control register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_fifo_ctrl &= ~FIFO_CTRL_RW_BITS; + m_fifo_ctrl |= data & FIFO_CTRL_RW_BITS; + if (data & FIFO_CTRL_CLRATF) + clear_atf(); + if (data & FIFO_CTRL_CLRITF) + clear_itf(); + if (data & FIFO_CTRL_CLRGRF) + clear_grf(); + break; + case 0x20: + LOGMASKED(LOG_WRITES, "%s: TSB12 Diagnostic Control register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0x24: + LOGMASKED(LOG_WRITES, "%s: TSB12 Phy-Chip Access register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + if (data & PHY_WRPHY) + { + const uint8_t phy_addr = (data & PHY_PHYRGAD_MASK) >> PHY_PHYRGAD_SHIFT; + const uint8_t phy_data = (data & PHY_PHYRGDATA_MASK) >> PHY_PHYRGDATA_SHIFT; + m_phy_write_cb(phy_addr, phy_data); + } + if (data & PHY_RDPHY) + { + const uint8_t phy_addr = (data & PHY_PHYRGAD_MASK) >> PHY_PHYRGAD_SHIFT; + m_phy_access &= ~PHY_PHYRXAD_MASK; + m_phy_access |= phy_addr << PHY_PHYRXAD_SHIFT; + m_phy_access &= ~PHY_PHYRXDATA_MASK; + m_phy_access |= m_phy_read_cb(phy_addr); + + if (phy_addr == 0) + { + } + + m_int_status |= INT_PHYRRX; + check_interrupts(); + } + + m_phy_access &= ~(PHY_PHYRGAD_MASK | PHY_PHYRGDATA_MASK); + m_phy_access |= data & (PHY_PHYRGAD_MASK | PHY_PHYRGDATA_MASK); + break; + case 0x30: + LOGMASKED(LOG_WRITES, "%s: TSB12 Asynchronous Transmit-FIFO (ATF) register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0x34: + LOGMASKED(LOG_WRITES, "%s: TSB12 Isochronous Transmit-FIFO (ITF) register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0x3c: + LOGMASKED(LOG_WRITES, "%s: TSB12 General Receive-FIFO (GRF) register write: %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + default: + LOGMASKED(LOG_WRITES | LOG_UNKNOWNS, "%s: TSB12 Unknown write: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); + break; + } +} |