1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
// license:BSD-3-Clause
// copyright-holders:Carl, Miodrag Milanovic
#include "emu.h"
#include "osdnet.h"
device_network_interface::device_network_interface(const machine_config &mconfig, device_t &device, float bandwidth)
: device_interface(device, "network")
{
m_promisc = false;
m_bandwidth = bandwidth;
set_mac("\0\0\0\0\0\0");
m_intf = 0;
m_loopback_control = false;
}
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()
{
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_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);
}
// schedule transmit complete callback
m_send_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result);
return result;
}
TIMER_CALLBACK_MEMBER(device_network_interface::send_complete)
{
send_complete_cb(param);
}
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
if (!m_loopback_control)
result = recv_start_cb(buf, len);
if (result)
{
// stop receiving more data from the network
if (m_dev)
m_dev->stop();
// schedule receive complete callback
m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result);
}
}
TIMER_CALLBACK_MEMBER(device_network_interface::recv_complete)
{
recv_complete_cb(param);
// 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);
}
void device_network_interface::set_mac(const char *mac)
{
memcpy(m_mac, mac, 6);
if(m_dev) m_dev->set_mac(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) {
device().logerror("Network interface %d not found\n", id);
id = -1;
}
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();
}
}
|