diff options
Diffstat (limited to 'src/emu/dinetwork.cpp')
-rw-r--r-- | src/emu/dinetwork.cpp | 102 |
1 files changed, 70 insertions, 32 deletions
diff --git a/src/emu/dinetwork.cpp b/src/emu/dinetwork.cpp index 0e9c0610566..30e10361c97 100644 --- a/src/emu/dinetwork.cpp +++ b/src/emu/dinetwork.cpp @@ -1,15 +1,24 @@ // license:BSD-3-Clause // copyright-holders:Carl, Miodrag Milanovic + #include "emu.h" -#include "osdnet.h" +#include "dinetwork.h" + +#include "osdepend.h" + +#include <algorithm> + -device_network_interface::device_network_interface(const machine_config &mconfig, device_t &device, float bandwidth) +device_network_interface::device_network_interface(const machine_config &mconfig, device_t &device, u32 bandwidth, u32 mtu) : device_interface(device, "network") + , m_poll_timer(nullptr) + , m_send_timer(nullptr) + , m_recv_timer(nullptr) { - m_promisc = false; - m_bandwidth = bandwidth; - set_mac("\0\0\0\0\0\0"); - m_intf = 0; + // Convert to Mibps to Bps + m_bandwidth = bandwidth << (20 - 3); + m_mtu = mtu; + m_intf = -1; m_loopback_control = false; } @@ -17,18 +26,26 @@ device_network_interface::~device_network_interface() { } -void device_network_interface::interface_pre_start() +void device_network_interface::interface_post_start() { + m_poll_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_network_interface::poll_device), this)); m_send_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_network_interface::send_complete), this)); m_recv_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_network_interface::recv_complete), this)); + + device().save_item(NAME(m_loopback_control)); } -void device_network_interface::interface_post_start() +void device_network_interface::interface_post_load() { - device().save_item(NAME(m_loopback_control)); + if (!m_dev) + m_poll_timer->reset(); + else if (!m_loopback_control && !m_recv_timer->enabled()) + start_net_device(); + else + stop_net_device(); } -int device_network_interface::send(u8 *buf, int len) +int device_network_interface::send(u8 *buf, int len, int fcs) { // TODO: enable this check when other devices implement delayed transmit //if (m_send_timer->enabled()) @@ -44,21 +61,42 @@ int device_network_interface::send(u8 *buf, int len) if (result) { // schedule receive complete callback - m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result); + m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth), result); } } else if (m_dev) { - // send the data - result = m_dev->send(buf, len); + // send the data (excluding fcs) + result = m_dev->send(buf, len - fcs); + if (result) + result += fcs; } // schedule transmit complete callback - m_send_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result); + m_send_timer->adjust(attotime::from_ticks(len, m_bandwidth), result); return result; } +TIMER_CALLBACK_MEMBER(device_network_interface::poll_device) +{ + m_dev->poll(); +} + +void device_network_interface::start_net_device() +{ + // Set device polling time to transfer time for one MTU + m_dev->start(); + const attotime interval = attotime::from_hz(m_bandwidth / m_mtu); + m_poll_timer->adjust(attotime::zero, 0, interval); +} + +void device_network_interface::stop_net_device() +{ + m_poll_timer->reset(); + m_dev->stop(); +} + TIMER_CALLBACK_MEMBER(device_network_interface::send_complete) { send_complete_cb(param); @@ -79,10 +117,10 @@ void device_network_interface::recv_cb(u8 *buf, int len) { // stop receiving more data from the network if (m_dev) - m_dev->stop(); + stop_net_device(); // schedule receive complete callback - m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result); + m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth), result); } } @@ -92,27 +130,27 @@ TIMER_CALLBACK_MEMBER(device_network_interface::recv_complete) // start receiving data from the network again if (m_dev && !m_loopback_control) - m_dev->start(); -} - -void device_network_interface::set_promisc(bool promisc) -{ - m_promisc = promisc; - if(m_dev) m_dev->set_promisc(promisc); + start_net_device(); } -void device_network_interface::set_mac(const char *mac) +void device_network_interface::set_mac(const u8 *mac) { - memcpy(m_mac, mac, 6); - if(m_dev) m_dev->set_mac(m_mac); + std::copy_n(mac, std::size(m_mac), std::begin(m_mac)); } void device_network_interface::set_interface(int id) { - if(m_dev) - m_dev->stop(); - m_dev.reset(open_netdev(id, this, (int)(m_bandwidth*1000000/8.0f/1500))); - if(!m_dev) { + if (m_dev) + stop_net_device(); + + m_dev = device().machine().osd().open_network_device(id, *this); + if (m_dev) + { + if (!m_loopback_control) + start_net_device(); + } + else + { device().logerror("Network interface %d not found\n", id); id = -1; } @@ -129,8 +167,8 @@ void device_network_interface::set_loopback(bool loopback) if (m_dev) { if (loopback) - m_dev->stop(); + stop_net_device(); else if (!m_recv_timer->enabled()) - m_dev->start(); + start_net_device(); } } |