summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/ibm21s850.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/ibm21s850.cpp')
-rw-r--r--src/devices/machine/ibm21s850.cpp161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/devices/machine/ibm21s850.cpp b/src/devices/machine/ibm21s850.cpp
new file mode 100644
index 00000000000..c77d3077a01
--- /dev/null
+++ b/src/devices/machine/ibm21s850.cpp
@@ -0,0 +1,161 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*************************************************************
+
+ IBM 21S850 IEEE-1394 400Mb/s 1-Port PHY
+ IBM 21S851 IEEE-1394 400Mb/s 3-Port PHY
+
+ Skeleton device
+
+**************************************************************/
+
+#include "emu.h"
+#include "ibm21s850.h"
+
+#define LOG_READS (1U << 1)
+#define LOG_WRITES (1U << 2)
+#define LOG_UNKNOWNS (1U << 3)
+#define LOG_ALL (LOG_READS | LOG_WRITES | LOG_UNKNOWNS)
+
+#define VERBOSE (LOG_ALL)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(IBM21S850, ibm21s850_device, "ibm21s850", "IBM 21S850 IEEE-1394 1-Port PHY")
+DEFINE_DEVICE_TYPE(IBM21S851, ibm21s851_device, "ibm21s851", "IBM 21S850 IEEE-1394 3-Port PHY")
+
+ibm21s85x_base_device::ibm21s85x_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_reset_cb(*this)
+{
+}
+
+ibm21s850_device::ibm21s850_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ibm21s85x_base_device(mconfig, IBM21S850, tag, owner, clock)
+{
+}
+
+ibm21s851_device::ibm21s851_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ibm21s85x_base_device(mconfig, IBM21S851, tag, owner, clock)
+{
+}
+
+void ibm21s85x_base_device::device_start()
+{
+ save_item(NAME(m_regs));
+
+ m_reset_timer = timer_alloc(FUNC(ibm21s85x_base_device::reset_tick), this);
+}
+
+void ibm21s85x_base_device::device_reset()
+{
+ memset(m_regs, 0, 0x10);
+
+ m_regs[ROOT_OFFS] |= ROOT_MASK; // Root node
+ m_regs[GAP_COUNT_OFFS] |= 0x3f; // Initial reset value
+ m_regs[SPEED_OFFS] |= SPEED_400MBIT << SPEED_SHIFT; // 21S850 and 21S851 both indicate maximum 400Mb/s rate
+ m_regs[ENHANCED_REGS_OFFS] |= ENHANCED_REGS_MASK; // 21S850 and 21S851 both have an enhanced register map
+ m_regs[CABLE_PWR_OFFS] |= CABLE_PWR_MASK; // Cable is powered
+ m_regs[CONNECTION1_OFFS] |= CONNECTION1_MASK; // Port 1 connected
+ m_regs[ARB_PHASE_OFFS] |= PHASE_BUS_RESET << ARB_PHASE_OFFS; // Power up in Bus Reset phase
+
+ power_on_reset();
+}
+
+void ibm21s850_device::device_reset()
+{
+ ibm21s85x_base_device::device_reset();
+
+ m_regs[NUM_PORTS_OFFS] |= 0x01; // 1 port available
+ m_regs[ENV_OFFS] |= 1 << ENV_SHIFT; // Cable PHY environment
+ m_regs[REG_COUNT_OFFS] |= 0x09; // 9 registers following the standard block on 21S850
+}
+
+void ibm21s851_device::device_reset()
+{
+ ibm21s85x_base_device::device_reset();
+
+ m_regs[NUM_PORTS_OFFS] |= 0x03; // 3 port available
+ m_regs[ENV_OFFS] |= 1 << ENV_SHIFT; // Cable PHY environment
+ m_regs[REG_COUNT_OFFS] |= 0x0b; // 11 registers following the standard block on 21S851
+}
+
+TIMER_CALLBACK_MEMBER(ibm21s85x_base_device::reset_tick)
+{
+ if (param)
+ {
+ m_reset_cb(0);
+ m_reset_timer->adjust(attotime::never);
+ }
+ else
+ {
+ m_reset_cb(1);
+ m_reset_timer->adjust(attotime::from_usec(26266), 1); // RC reset circuit, 3.3V in, 2.3V out, 10KOhm resistor, 2.2uF capacitor
+ }
+}
+
+uint8_t ibm21s85x_base_device::read(offs_t offset)
+{
+ if (offset < 0x10)
+ {
+ LOGMASKED(LOG_READS, "%s: Register %02x read: %02x\n", machine().describe_context(), offset, m_regs[offset]);
+ return m_regs[offset];
+ }
+ LOGMASKED(LOG_READS | LOG_UNKNOWNS, "%s: Unknown Register (%02x) read\n", machine().describe_context(), offset);
+ return 0;
+}
+
+void ibm21s85x_base_device::power_on_reset()
+{
+ m_reset_timer->adjust(attotime::zero, 0);
+}
+
+void ibm21s85x_base_device::write(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ default:
+ LOGMASKED(LOG_WRITES, "%s: Register %02x write (ignored): %02x\n", machine().describe_context(), offset, data);
+ break;
+ case 0x01:
+ LOGMASKED(LOG_WRITES, "%s: Register 01 write: %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_WRITES, "%s: Root Hold-off: %d\n", machine().describe_context(), (data & ROOT_HOLD_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Initiate Bus Reset: %d\n", machine().describe_context(), (data & BUS_RESET_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Gap Offset: %02x\n", machine().describe_context(), data & GAP_COUNT_MASK);
+ if (data & BUS_RESET_MASK)
+ {
+ data &= ~BUS_RESET_MASK;
+ }
+ m_regs[offset] = data;
+ break;
+ case 0x0d:
+ LOGMASKED(LOG_WRITES, "%s: Register 0d write: %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_WRITES, "%s: Enable L-P Selftest: %d\n", machine().describe_context(), (data & LP_TEST_EN_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Enable Ack Accel Arbitration: %d\n", machine().describe_context(), (data & ACK_ACCEL_EN_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Enable Multi-Speed Concat: %d\n", machine().describe_context(), (data & MULTISP_CONCAT_EN_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Mask LPS Bit: %d\n", machine().describe_context(), (data & MASK_LPS_MASK) ? 1 : 0);
+ m_regs[offset] = data;
+ break;
+ case 0x0e:
+ LOGMASKED(LOG_WRITES, "%s: Register 0e write: %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_WRITES, "%s: Enable Tx/Rx Timeout: %d\n", machine().describe_context(), (data & EN_TIMEOUT_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Ignore Unplug: %d\n", machine().describe_context(), (data & IGNORE_UNPLUG_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Override CMC: %d\n", machine().describe_context(), (data & OVERRIDE_CMC_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Software CMC: %d\n", machine().describe_context(), (data & SOFT_CMC_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Disable Port 1: %d\n", machine().describe_context(), (data & DISABLE_P1_MASK) ? 1 : 0);
+ m_regs[offset] = data;
+ break;
+ case 0x0f:
+ LOGMASKED(LOG_WRITES, "%s: Register 0f write: %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_WRITES, "%s: Soft POR: %d\n", machine().describe_context(), (data & SOFT_POR_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Send PHY-Link Diag (SID) Packet: %d\n", machine().describe_context(), (data & SEND_PL_DIAG_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Degate Ack_Acc_Arb: %d\n", machine().describe_context(), (data & ACK_ACCEL_SYNC_MASK) ? 1 : 0);
+ LOGMASKED(LOG_WRITES, "%s: Initiate Short Bus Reset: %d\n", machine().describe_context(), (data & ISBR_MASK) ? 1 : 0);
+ if (data & SOFT_POR_MASK)
+ {
+ data &= ~SOFT_POR_MASK;
+ power_on_reset();
+ }
+ m_regs[offset] = data;
+ break;
+ }
+}