summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/tsb12lv01a.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/tsb12lv01a.cpp')
-rw-r--r--src/devices/machine/tsb12lv01a.cpp275
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;
+ }
+}