diff --git a/src/emu/dinetwork.cpp b/src/emu/dinetwork.cpp index 094d3476af1..cc1c4402759 100644 --- a/src/emu/dinetwork.cpp +++ b/src/emu/dinetwork.cpp @@ -10,6 +10,7 @@ device_network_interface::device_network_interface(const machine_config &mconfig m_bandwidth = bandwidth; set_mac("\0\0\0\0\0\0"); m_intf = 0; + m_loopback_control = false; } device_network_interface::~device_network_interface() @@ -22,14 +23,30 @@ void device_network_interface::interface_pre_start() m_recv_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_network_interface::recv_complete), this)); } -int device_network_interface::send(u8 *buf, int len) const +void device_network_interface::interface_post_start() +{ + device().save_item(NAME(m_loopback_control)); +} + +int device_network_interface::send(u8 *buf, int len) { // TODO: enable this check when other devices implement delayed transmit //assert_always(!m_send_timer->enabled(), "attempted to transmit while transmit already in progress"); int result = 0; - if (m_dev) + if (m_loopback_control) + { + // loop data back to receiver + result = recv_start_cb(buf, len); + + if (result) + { + // schedule receive complete callback + m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result); + } + } + else if (m_dev) { // send the data result = m_dev->send(buf, len); @@ -50,8 +67,11 @@ void device_network_interface::recv_cb(u8 *buf, int len) { assert_always(!m_recv_timer->enabled(), "attempted to receive while receive already in progress"); + int result = 0; + // process the received data - int result = recv_start_cb(buf, len); + if (!m_loopback_control) + result = recv_start_cb(buf, len); if (result) { @@ -69,7 +89,7 @@ TIMER_CALLBACK_MEMBER(device_network_interface::recv_complete) recv_complete_cb(param); // start receiving data from the network again - if (m_dev) + if (m_dev && !m_loopback_control) m_dev->start(); } @@ -96,3 +116,19 @@ void device_network_interface::set_interface(int id) } m_intf = id; } + +void device_network_interface::set_loopback(bool loopback) +{ + if (m_loopback_control == loopback) + return; + + m_loopback_control = loopback; + + if (m_dev) + { + if (loopback) + m_dev->stop(); + else if (!m_recv_timer->enabled()) + m_dev->start(); + } +} diff --git a/src/emu/dinetwork.h b/src/emu/dinetwork.h index fa5ee730a87..d844be951ab 100644 --- a/src/emu/dinetwork.h +++ b/src/emu/dinetwork.h @@ -12,16 +12,18 @@ public: virtual ~device_network_interface(); void interface_pre_start() override; + void interface_post_start() override; void set_interface(int id); void set_promisc(bool promisc); void set_mac(const char *mac); + void set_loopback(bool loopback); const char *get_mac() const { return m_mac; } bool get_promisc() const { return m_promisc; } int get_interface() const { return m_intf; } - int send(u8 *buf, int len) const; + int send(u8 *buf, int len); // TODO: de-virtualise this when existing devices implement delayed receive virtual void recv_cb(u8 *buf, int len); @@ -40,6 +42,7 @@ protected: float m_bandwidth; std::unique_ptr m_dev; int m_intf; + bool m_loopback_control; emu_timer *m_send_timer; emu_timer *m_recv_timer; diff --git a/src/mame/drivers/sun2.cpp b/src/mame/drivers/sun2.cpp index c7efe8fa685..e63f5d6560f 100644 --- a/src/mame/drivers/sun2.cpp +++ b/src/mame/drivers/sun2.cpp @@ -509,7 +509,7 @@ uint8_t sun2_state::ethernet_r() void sun2_state::ethernet_w(uint8_t data) { m_edlc->reset_w(!BIT(data, 7)); - // Bit 6 = loopback control (active low, though inverted for MB502) + m_edlc->set_loopback(!BIT(data, 6)); // LBC on MB502 m_edlc->ca(BIT(data, 5)); m_ethernet_status = (data & 0xf0) | (m_ethernet_status & 0x0f); @@ -570,6 +570,7 @@ void sun2_state::vmetype1space_map(address_map &map) // 7f1000-7f17ff: AM9518 encryption processor //AM_RANGE(0x7f1800, 0x7f1801) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, cb_r, cb_w, 0xff00) //AM_RANGE(0x7f1802, 0x7f1803) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, db_r, db_w, 0xff00) + map(0x7f1804, 0x7f1805).nopr(); //AM_RANGE(0x7f1804, 0x7f1805) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, ca_r, ca_w, 0xff00) //AM_RANGE(0x7f1806, 0x7f1807) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, da_r, da_w, 0xff00) map(0x7f2000, 0x7f2000).rw(SCC2_TAG, FUNC(z80scc_device::cb_r), FUNC(z80scc_device::cb_w));