osd/osdnet.cpp: Removed dependency from OSD network device to libemu. (#12058)

* This allows save states to be created and loaded when network interfaces are present.
* device_network_interface may need some more attention to get save states taken while receiving a packet to work properly.
This commit is contained in:
Vas Crabb 2024-02-25 02:25:23 +11:00 committed by GitHub
parent d1501f28eb
commit d98993d7ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 264 additions and 132 deletions

View File

@ -60,6 +60,8 @@ function osdmodulesbuild()
MAME_DIR .. "src/osd/interface/inputman.h",
MAME_DIR .. "src/osd/interface/inputseq.cpp",
MAME_DIR .. "src/osd/interface/inputseq.h",
MAME_DIR .. "src/osd/interface/nethandler.cpp",
MAME_DIR .. "src/osd/interface/nethandler.h",
MAME_DIR .. "src/osd/modules/debugger/debug_module.h",
MAME_DIR .. "src/osd/modules/debugger/debuggdbstub.cpp",
MAME_DIR .. "src/osd/modules/debugger/debugimgui.cpp",

View File

@ -53,7 +53,7 @@ void el2_3c503_device::device_start() {
}
void el2_3c503_device::device_reset() {
memcpy(m_prom, m_dp8390->get_mac(), 6);
memcpy(m_prom, &m_dp8390->get_mac()[0], 6);
memset(&m_regs, 0, sizeof(m_regs));
m_regs.bcfr = 0x80; // port 0x300
m_regs.pcfr = 0x20; // address 0xcc000

View File

@ -16,8 +16,8 @@ void ne1000_device::device_add_mconfig(machine_config &config)
m_dp8390->mem_write_callback().set(FUNC(ne1000_device::ne1000_mem_write));
}
ne1000_device::ne1000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, NE1000, tag, owner, clock),
ne1000_device::ne1000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, NE1000, tag, owner, clock),
device_isa8_card_interface(mconfig, *this),
m_dp8390(*this, "dp8390d"),
m_irq(0)
@ -38,7 +38,7 @@ void ne1000_device::device_start() {
}
void ne1000_device::device_reset() {
memcpy(m_prom, m_dp8390->get_mac(), 6);
memcpy(m_prom, &m_dp8390->get_mac()[0], 6);
m_irq = ioport("CONFIG")->read() & 3;
}

View File

@ -16,8 +16,8 @@ void ne2000_device::device_add_mconfig(machine_config &config)
m_dp8390->mem_write_callback().set(FUNC(ne2000_device::ne2000_mem_write));
}
ne2000_device::ne2000_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
: device_t(mconfig, NE2000, tag, owner, clock),
ne2000_device::ne2000_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
device_t(mconfig, NE2000, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
m_dp8390(*this, "dp8390d"),
m_irq(0)
@ -38,7 +38,7 @@ void ne2000_device::device_start() {
}
void ne2000_device::device_reset() {
memcpy(m_prom, m_dp8390->get_mac(), 6);
memcpy(m_prom, &m_dp8390->get_mac()[0], 6);
m_irq = ioport("CONFIG")->read() & 3;
}

View File

@ -215,7 +215,7 @@ void pdslc_macconilc_device::device_start()
void nubus_mac8390_device::device_reset()
{
m_dp83902->dp8390_reset(0);
memcpy(m_prom, m_dp83902->get_mac(), 6);
memcpy(m_prom, &m_dp83902->get_mac()[0], 6);
}
void nubus_mac8390_device::asntm3b_ram_w(offs_t offset, u8 data)

View File

@ -53,8 +53,9 @@ void x68k_neptune_device::device_start()
m_slot->space().install_readwrite_handler(0xece000,0xece3ff, read16s_delegate(*this, FUNC(x68k_neptune_device::x68k_neptune_port_r)), write16s_delegate(*this, FUNC(x68k_neptune_device::x68k_neptune_port_w)), 0xffffffff);
}
void x68k_neptune_device::device_reset() {
memcpy(m_prom, m_dp8390->get_mac(), 6);
void x68k_neptune_device::device_reset()
{
memcpy(m_prom, &m_dp8390->get_mac()[0], 6);
}
uint16_t x68k_neptune_device::x68k_neptune_port_r(offs_t offset, uint16_t mem_mask)

View File

@ -82,7 +82,7 @@ void seeq8003_device::device_reset()
// TODO: deassert RxDC and TxRET
if (m_dev)
if (has_net_device())
m_out_txrdy(1);
interrupt();
@ -427,7 +427,7 @@ void seeq80c03_device::send_complete_cb(int result)
else
{
// assume transmit failure and no device means loss of carrier
if ((m_control & CTL_TNC) && !m_dev)
if ((m_control & CTL_TNC) && !has_net_device())
m_flags |= FLAGS_TNC;
}
}

View File

@ -533,7 +533,7 @@ bool i82586_base_device::address_filter(u8 *mac)
}
// individual address
if (!memcmp(mac, get_mac(), cfg_address_length()))
if (!memcmp(mac, &get_mac()[0], cfg_address_length()))
{
LOGMASKED(LOG_FILTER, "address_filter accepted: individual address match\n");
@ -950,7 +950,7 @@ bool i82586_device::cu_transmit(u32 command)
// optionally insert source, destination address and length (14 bytes)
if (!cfg_no_src_add_ins())
{
const char *mac = get_mac();
const std::array<u8, 6> &mac = get_mac();
u32 data;
// insert destination address (6 bytes)
@ -1054,7 +1054,7 @@ bool i82586_device::cu_dump()
memcpy(&buf[0x00], &m_cfg_bytes[0], CFG_SIZE);
// individual address
memcpy(&buf[0x0c], get_mac(), 6);
memcpy(&buf[0x0c], &get_mac()[0], 6);
// hash register
*(u64 *)&buf[0x24] = m_mac_multi;
@ -1584,7 +1584,7 @@ bool i82596_device::cu_transmit(u32 command)
// optionally insert destination, source and length (14 bytes)
if (!cfg_no_src_add_ins())
{
const char *mac = get_mac();
const std::array<u8, 6> &mac = get_mac();
u32 data;
// insert destination address (6 bytes)
@ -1719,7 +1719,7 @@ bool i82596_device::cu_dump()
memcpy(&buf[0x02], &m_cfg_bytes[2], 9);
// individual address
memcpy(&buf[0x0c], get_mac(), 6);
memcpy(&buf[0x0c], &get_mac()[0], 6);
// hash register
*(u64 *)&buf[0x24] = m_mac_multi;
@ -1730,7 +1730,7 @@ bool i82596_device::cu_dump()
memcpy(&buf[0x00], &m_cfg_bytes[2], 12);
// individual address
memcpy(&buf[0x0e], get_mac(), 6);
memcpy(&buf[0x0e], &get_mac()[0], 6);
// hash register
*(u64 *)&buf[0x26] = m_mac_multi;
@ -1827,7 +1827,7 @@ u16 i82596_device::ru_execute(u8 *buf, int length)
// TODO: increment alignment error counter
// set multicast status
if (mode() != MODE_82586 && memcmp(buf, get_mac(), cfg_address_length()))
if (mode() != MODE_82586 && memcmp(buf, &get_mac()[0], cfg_address_length()))
status |= RFD_S_MULTICAST;
// fetch initial rbd address from rfd

View File

@ -3,16 +3,21 @@
#include "emu.h"
#include "dinetwork.h"
#include "osdnet.h"
#include <algorithm>
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;
// Convert to Mibps to Bps
m_bandwidth = bandwidth << (20 - 3);
m_mtu = mtu;
memset(m_mac, 0, 6);
m_intf = -1;
m_loopback_control = false;
}
@ -21,17 +26,25 @@ device_network_interface::~device_network_interface()
{
}
void device_network_interface::interface_pre_start()
{
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));
}
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_load()
{
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 fcs)
{
// TODO: enable this check when other devices implement delayed transmit
@ -65,6 +78,25 @@ int device_network_interface::send(u8 *buf, int len, int fcs)
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);
@ -85,7 +117,7 @@ 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), result);
@ -98,28 +130,36 @@ TIMER_CALLBACK_MEMBER(device_network_interface::recv_complete)
// start receiving data from the network again
if (m_dev && !m_loopback_control)
m_dev->start();
start_net_device();
}
void device_network_interface::set_promisc(bool promisc)
{
m_promisc = promisc;
if(m_dev) m_dev->set_promisc(promisc);
if (m_dev)
m_dev->set_promisc(promisc);
}
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));
if (m_dev)
m_dev->set_mac(&m_mac[0]);
}
void device_network_interface::set_interface(int id)
{
if(m_dev)
m_dev->stop();
// Set device polling time to transfer time for one mtu
m_dev.reset(open_netdev(id, this, (int)(m_bandwidth / m_mtu)));
if(!m_dev) {
if (m_dev)
stop_net_device();
m_dev.reset(open_netdev(id, *this));
if (m_dev)
{
if (!m_loopback_control)
start_net_device();
}
else
{
device().logerror("Network interface %d not found\n", id);
id = -1;
}
@ -136,8 +176,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();
}
}

View File

@ -3,30 +3,31 @@
#ifndef MAME_EMU_DINETWORK_H
#define MAME_EMU_DINETWORK_H
class osd_netdev;
#include "interface/nethandler.h"
class device_network_interface : public device_interface
class osd_network_device;
class device_network_interface : public device_interface, public osd::network_handler
{
public:
device_network_interface(const machine_config &mconfig, device_t &device, u32 bandwidth, u32 mtu = 1500);
virtual ~device_network_interface();
void interface_pre_start() override;
void interface_post_start() override;
void interface_post_start() override ATTR_COLD;
void interface_post_load() override ATTR_COLD;
void set_interface(int id);
void set_interface(int id) ATTR_COLD;
void set_promisc(bool promisc);
void set_mac(const u8 *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, int fcs = 0);
// TODO: de-virtualise this when existing devices implement delayed receive
virtual void recv_cb(u8 *buf, int len);
virtual void recv_cb(u8 *buf, int len) override;
// delayed transmit/receive handlers
virtual void send_complete_cb(int result) {}
@ -34,19 +35,25 @@ public:
virtual void recv_complete_cb(int result) {}
protected:
TIMER_CALLBACK_MEMBER(send_complete);
TIMER_CALLBACK_MEMBER(recv_complete);
bool has_net_device() const noexcept { return bool(m_dev); }
bool m_promisc;
char m_mac[6];
// bandwidth in bytes per second
u32 m_bandwidth;
// maximum transmission unit, used for device polling time
u32 m_mtu;
std::unique_ptr<osd_netdev> m_dev;
int m_intf;
bool m_loopback_control;
private:
TIMER_CALLBACK_MEMBER(poll_device);
TIMER_CALLBACK_MEMBER(send_complete);
TIMER_CALLBACK_MEMBER(recv_complete);
void start_net_device();
void stop_net_device();
std::unique_ptr<osd_network_device> m_dev;
emu_timer *m_poll_timer;
emu_timer *m_send_timer;
emu_timer *m_recv_timer;
};

View File

@ -87,9 +87,9 @@ void network_manager::config_save(config_type cfg_type, util::xml::data_node *pa
{
node->set_attribute("tag", network.device().tag());
node->set_attribute_int("interface", network.get_interface());
const char *mac = network.get_mac();
const std::array<u8, 6> &mac = network.get_mac();
char mac_addr[6 * 3];
sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", u8(mac[0]), u8(mac[1]), u8(mac[2]), u8(mac[3]), u8(mac[4]), u8(mac[5]));
sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
node->set_attribute("mac", mac_addr);
}
}

View File

@ -205,13 +205,12 @@ void macquadra_state::field_interrupts()
void macquadra_state::machine_start()
{
const u8 *MAC = (u8 *)m_sonic->get_mac();
m_dafb->set_turboscsi1_device(m_ncr1);
m_dafb->set_turboscsi2_device(nullptr);
// MAC PROM is stored with a bit swizzle and must match one of 2
// Apple-assigned OUI blocks 00:05:02 or 08:00:07
const std::array<u8, 6> &MAC = m_sonic->get_mac();
m_mac[0] = bitswap<8>(0x00, 0, 1, 2, 3, 7, 6, 5, 4);
m_mac[1] = bitswap<8>(0x05, 0, 1, 2, 3, 7, 6, 5, 4);
m_mac[2] = bitswap<8>(0x02, 0, 1, 2, 3, 7, 6, 5, 4);

View File

@ -106,9 +106,9 @@ void quadra800_state::machine_start()
{
m_djmemc->set_ram_info((u32 *) m_ram->pointer(), m_ram->size());
const u8 *MAC = (u8 *)m_sonic->get_mac();
// MAC PROM is stored with a bit swizzle and must match one of 2
// Apple-assigned OUI blocks 00:05:02 or 08:00:07
const std::array<u8, 6> &MAC = m_sonic->get_mac();
m_mac[0] = bitswap<8>(0x08, 0, 1, 2, 3, 7, 6, 5, 4);
m_mac[1] = bitswap<8>(0x00, 0, 1, 2, 3, 7, 6, 5, 4);
m_mac[2] = bitswap<8>(0x07, 0, 1, 2, 3, 7, 6, 5, 4);

View File

@ -0,0 +1,24 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***************************************************************************
nethandler.cpp
OSD interface to virtual networking handlers
***************************************************************************/
#include "nethandler.h"
#include <algorithm>
namespace osd {
network_handler::network_handler() noexcept
: m_promisc(false)
{
std::fill(std::begin(m_mac), std::end(m_mac), 0);
}
} // namespace osd

View File

@ -0,0 +1,47 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***************************************************************************
nethandler.h
OSD interface to virtual networking handlers
***************************************************************************/
#ifndef MAME_OSD_INTERFACE_NETHANDLER_H
#define MAME_OSD_INTERFACE_NETHANDLER_H
#pragma once
#include "osdcomm.h"
#include <array>
namespace osd {
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// base for virtual network interface handler
class network_handler
{
public:
network_handler() noexcept;
virtual void recv_cb(u8 *buf, int len) = 0;
std::array<u8, 6> const &get_mac() noexcept { return m_mac; }
bool get_promisc() noexcept { return m_promisc; }
protected:
~network_handler() = default;
bool m_promisc;
std::array<u8, 6> m_mac;
};
} // namespace osd
#endif // MAME_OSD_INTERFACE_NETHANDLER_H

View File

@ -7,10 +7,11 @@
#if defined(OSD_NET_USE_PCAP)
#include "emu.h"
#include "dinetwork.h"
#include "osdnet.h"
#include "modules/lib/osdlib.h"
#include "osdnet.h"
#include "osdcore.h" // osd_printf_*
#include "util/strformat.h" // string_format
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
#include <windows.h>
@ -100,7 +101,8 @@ public:
static pcap_module *module = nullptr;
#ifdef SDLMAME_MACOSX
struct netdev_pcap_context {
struct netdev_pcap_context
{
uint8_t *pkt;
int len;
pcap_t *p;
@ -112,16 +114,18 @@ struct netdev_pcap_context {
};
#endif
class netdev_pcap : public osd_netdev
class netdev_pcap : public osd_network_device
{
public:
netdev_pcap(const char *name, class device_network_interface *ifdev, int rate);
netdev_pcap(const char *name, class network_handler &ifdev);
~netdev_pcap();
virtual int send(uint8_t *buf, int len) override;
virtual void set_mac(const char *mac) override;
virtual void set_mac(const uint8_t *mac) override;
protected:
virtual int recv_dev(uint8_t **buf) override;
private:
pcap_t *m_p;
#ifdef SDLMAME_MACOSX
@ -131,7 +135,8 @@ private:
};
#ifdef SDLMAME_MACOSX
static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user;
if(!ctx->p) return;
@ -156,8 +161,8 @@ static void *netdev_pcap_blocker(void *arg) {
}
#endif
netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate)
: osd_netdev(ifdev, rate)
netdev_pcap::netdev_pcap(const char *name, class network_handler &ifdev)
: osd_network_device(ifdev)
{
char errbuf[PCAP_ERRBUF_SIZE];
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
@ -177,7 +182,7 @@ netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev
m_p = nullptr;
return;
}
netdev_pcap::set_mac(get_mac());
netdev_pcap::set_mac(&get_mac()[0]);
#ifdef SDLMAME_MACOSX
m_ctx.head = 0;
@ -187,7 +192,7 @@ netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev
#endif
}
void netdev_pcap::set_mac(const char *mac)
void netdev_pcap::set_mac(const uint8_t *mac)
{
struct bpf_program fp;
if(!m_p) return;
@ -256,8 +261,8 @@ netdev_pcap::~netdev_pcap()
static CREATE_NETDEV(create_pcap)
{
auto *dev = new netdev_pcap(ifname, ifdev, rate);
return dynamic_cast<osd_netdev *>(dev);
auto *dev = new netdev_pcap(ifname, ifdev);
return dynamic_cast<osd_network_device *>(dev);
}
int pcap_module::init(osd_interface &osd, const osd_options &options)

View File

@ -17,11 +17,13 @@
#include <cerrno>
#endif
#include "emu.h"
#include "dinetwork.h"
#include "osdcore.h" // osd_printf_verbose
#include "osdfile.h" // PATH_SEPARATOR
#include "osdnet.h"
#include "unicode.h"
#include "util/hashing.h" // crc32_creator
#ifdef __linux__
#define IFF_TAP 0x0002
#define IFF_NO_PI 0x1000
@ -58,16 +60,18 @@ public:
class netdev_tap : public osd_netdev
class netdev_tap : public osd_network_device
{
public:
netdev_tap(const char *name, class device_network_interface *ifdev, int rate);
netdev_tap(const char *name, class network_handler &ifdev);
~netdev_tap();
int send(uint8_t *buf, int len) override;
void set_mac(const char *mac) override;
void set_mac(const uint8_t *mac) override;
protected:
int recv_dev(uint8_t **buf) override;
private:
#if defined(_WIN32)
HANDLE m_handle = INVALID_HANDLE_VALUE;
@ -81,8 +85,8 @@ private:
uint8_t m_buf[2048];
};
netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, int rate)
: osd_netdev(ifdev, rate)
netdev_tap::netdev_tap(const char *name, class network_handler &ifdev)
: osd_network_device(ifdev)
{
#ifdef __linux__
struct ifreq ifr;
@ -141,7 +145,7 @@ netdev_tap::~netdev_tap()
#endif
}
void netdev_tap::set_mac(const char *mac)
void netdev_tap::set_mac(const uint8_t *mac)
{
memcpy(m_mac, mac, 6);
}
@ -338,7 +342,7 @@ int netdev_tap::recv_dev(uint8_t **buf)
// are in promiscuous mode or got a packet with our mac.
do {
len = read(m_fd, m_buf, sizeof(m_buf));
} while((len > 0) && memcmp(get_mac(), m_buf, 6) && !get_promisc() && !(m_buf[0] & 1));
} while((len > 0) && memcmp(&get_mac()[0], m_buf, 6) && !get_promisc() && !(m_buf[0] & 1));
if (len > 0)
len = finalise_frame(m_buf, len);
@ -350,8 +354,8 @@ int netdev_tap::recv_dev(uint8_t **buf)
static CREATE_NETDEV(create_tap)
{
auto *dev = new netdev_tap(ifname, ifdev, rate);
return dynamic_cast<osd_netdev *>(dev);
auto *dev = new netdev_tap(ifname, ifdev);
return dynamic_cast<osd_network_device *>(dev);
}
int taptun_module::init(osd_interface &osd, const osd_options &options)

View File

@ -1,16 +1,16 @@
// license:BSD-3-Clause
// copyright-holders:Carl
#include "emu.h"
#include "osdnet.h"
#include "dinetwork.h"
#include "interface/nethandler.h"
static class std::vector<std::unique_ptr<osd_netdev::entry_t>> netdev_list;
static std::vector<std::unique_ptr<osd_network_device::entry_t>> netdev_list;
void add_netdev(const char *name, const char *description, create_netdev func)
{
auto entry = std::make_unique<osd_netdev::entry_t>();
auto entry = std::make_unique<osd_network_device::entry_t>();
entry->id = netdev_list.size();
strncpy(entry->name, name, 255);
entry->name[255] = '\0';
@ -25,56 +25,50 @@ void clear_netdev()
netdev_list.clear();
}
const std::vector<std::unique_ptr<osd_netdev::entry_t>>& get_netdev_list()
const std::vector<std::unique_ptr<osd_network_device::entry_t>>& get_netdev_list()
{
return netdev_list;
}
class osd_netdev *open_netdev(int id, class device_network_interface *ifdev, int rate)
osd_network_device *open_netdev(int id, osd::network_handler &ifdev)
{
for(auto &entry : netdev_list)
if(entry->id==id)
return entry->func(entry->name, ifdev, rate);
return entry->func(entry->name, ifdev);
return nullptr;
}
osd_netdev::osd_netdev(class device_network_interface *ifdev, int rate)
{
m_dev = ifdev;
m_timer = ifdev->device().timer_alloc(FUNC(osd_netdev::recv), this);
m_timer->adjust(attotime::from_hz(rate), 0, attotime::from_hz(rate));
}
osd_netdev::~osd_netdev()
osd_network_device::osd_network_device(osd::network_handler &ifdev)
: m_dev(ifdev)
, m_stopped(true)
{
}
void osd_netdev::start()
osd_network_device::~osd_network_device()
{
m_timer->enable(true);
}
void osd_netdev::stop()
void osd_network_device::start()
{
m_timer->enable(false);
m_stopped = false;
}
int osd_netdev::send(uint8_t *buf, int len)
void osd_network_device::stop()
{
return 0;
m_stopped = true;
}
void osd_netdev::recv(int32_t param)
void osd_network_device::poll()
{
uint8_t *buf;
int len;
//const char atalkmac[] = { 0x09, 0x00, 0x07, 0xff, 0xff, 0xff };
while(m_timer->enabled() && (len = recv_dev(&buf)))
while(!m_stopped && (len = recv_dev(&buf)))
{
#if 0
if(buf[0] & 1)
{
if(memcmp("\xff\xff\xff\xff\xff\xff", buf, 6) && memcmp(atalkmac, buf, 6) && !m_dev->mcast_chk(buf, len)) continue;
if(memcmp("\xff\xff\xff\xff\xff\xff", buf, 6) && memcmp(atalkmac, buf, 6) && !m_dev.mcast_chk(buf, len)) continue;
}
else {
//const unsigned char *ourmac = (const unsigned char *)get_mac();
@ -83,35 +77,36 @@ void osd_netdev::recv(int32_t param)
}
#endif
m_dev->recv_cb(buf, len);
m_dev.recv_cb(buf, len);
}
}
int osd_netdev::recv_dev(uint8_t **buf)
int osd_network_device::send(uint8_t *buf, int len)
{
return 0;
}
void osd_netdev::set_mac(const char *mac)
int osd_network_device::recv_dev(uint8_t **buf)
{
return 0;
}
void osd_network_device::set_mac(const uint8_t *mac)
{
}
void osd_netdev::set_promisc(bool promisc)
void osd_network_device::set_promisc(bool promisc)
{
}
bool osd_netdev::get_promisc()
bool osd_network_device::get_promisc()
{
if(m_dev)
return m_dev->get_promisc();
return false;
return m_dev.get_promisc();
}
const char *osd_netdev::get_mac()
const std::array<uint8_t, 6> &osd_network_device::get_mac()
{
if(m_dev)
return m_dev->get_mac();
return "\0\0\0\0\0\0";
return m_dev.get_mac();
}
int netdev_count()

View File

@ -5,14 +5,21 @@
#pragma once
#include "osdcomm.h"
#include <algorithm>
#include <array>
#include <memory>
#include <vector>
class osd_netdev;
#define CREATE_NETDEV(name) class osd_netdev *name(const char *ifname, class device_network_interface *ifdev, int rate)
typedef class osd_netdev *(*create_netdev)(const char *ifname, class device_network_interface *ifdev, int rate);
namespace osd { class network_handler; }
class osd_network_device;
class osd_netdev
#define CREATE_NETDEV(name) osd_network_device *name(const char *ifname, osd::network_handler &ifdev)
typedef osd_network_device *(*create_netdev)(const char *ifname, osd::network_handler &ifdev);
class osd_network_device
{
public:
struct entry_t
@ -28,32 +35,33 @@ public:
char description[256];
create_netdev func = nullptr;
};
osd_netdev(class device_network_interface *ifdev, int rate);
virtual ~osd_netdev();
osd_network_device(osd::network_handler &ifdev);
virtual ~osd_network_device();
void start();
void stop();
void poll();
virtual int send(uint8_t *buf, int len);
virtual void set_mac(const char *mac);
virtual void set_mac(const uint8_t *mac);
virtual void set_promisc(bool promisc);
const char *get_mac();
const std::array<uint8_t, 6> &get_mac();
bool get_promisc();
protected:
virtual int recv_dev(uint8_t **buf);
private:
void recv(int32_t param);
class device_network_interface *m_dev;
emu_timer *m_timer;
osd::network_handler &m_dev;
bool m_stopped;
};
class osd_netdev *open_netdev(int id, class device_network_interface *ifdev, int rate);
osd_network_device *open_netdev(int id, osd::network_handler &ifdev);
void add_netdev(const char *name, const char *description, create_netdev func);
void clear_netdev();
const std::vector<std::unique_ptr<osd_netdev::entry_t>>& get_netdev_list();
const std::vector<std::unique_ptr<osd_network_device::entry_t>>& get_netdev_list();
int netdev_count();
void osd_list_network_adapters();