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
|
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_MACHINE_EDLC_H
#define MAME_MACHINE_EDLC_H
#pragma once
class seeq8003_device :
public device_t,
public device_network_interface
{
public:
// callback configuration
auto out_int_cb() { return m_out_int.bind(); }
auto out_rxrdy_cb() { return m_out_rxrdy.bind(); }
auto out_txrdy_cb() { return m_out_txrdy.bind(); }
seeq8003_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
// command/status interface
void map(address_map &map);
u8 read(offs_t offset);
void write(offs_t offset, u8 data);
void reset_w(int state);
// data interface
u8 fifo_r();
int rxeof_r();
void fifo_w(u8 data);
void txeof_w(int state);
protected:
// device_t overrides
virtual void device_start() override;
virtual void device_reset() override;
// device_network_interface overrides
virtual int recv_start_cb(u8 *buf, int length) override;
// command/status registers
template <unsigned N> void station_address_w(u8 data) { m_station_address[N] = data; }
u8 rx_status_r();
u8 tx_status_r();
void rx_command_w(u8 data) { m_rx_command = data; }
void tx_command_w(u8 data) { m_tx_command = data & TXC_M; }
// helpers
void transmit(void *ptr, int param);
int receive(u8 *buf, int length);
void interrupt(void *ptr = nullptr, int param = 0);
bool address_filter(u8 *address);
void dump_bytes(u8 *buf, int length);
// constants and masks
static const unsigned MAX_FRAME_SIZE = 1518;
static const u32 FCS_RESIDUE = 0xdebb20e3;
enum rx_status_mask : u8
{
RXS_V = 0x01, // received frame with overflow error
RXS_C = 0x02, // received frame with crc error
RXS_D = 0x04, // received frame with dribble error
RXS_S = 0x08, // received short frame
RXS_E = 0x10, // received end of frame
RXS_G = 0x20, // received good frame
RXS_O = 0x80, // old/new status
RXS_M = 0x3f, // interrupt mask
};
enum rx_command_mask : u8
{
RXC_V = 0x01, // interrupt on receive overflow error
RXC_C = 0x02, // interrupt on receive crc error
RXC_D = 0x04, // interrupt on receive dribble error
RXC_S = 0x08, // interrupt on short frame
RXC_E = 0x10, // interrupt on end of frame
RXC_G = 0x20, // interrupt on good frame
RXC_M = 0xc0, // match mode
};
enum rx_match_mask : u8
{
RXC_M0 = 0x00, // receiver disable
RXC_M1 = 0x40, // receive all frames
RXC_M2 = 0x80, // receive station or broadcast frames
RXC_M3 = 0xc0, // receive station, broadcast/multicast frames
};
enum tx_status_mask : u8
{
TXS_U = 0x01, // transmit underflow
TXS_C = 0x02, // transmit collision
TXS_R = 0x04, // 16 transmission attempts
TXS_S = 0x08, // transmission successful
TXS_O = 0x80, // old/new status
TXS_M = 0x0f, // interrupt mask
};
enum tx_command_mask : u8
{
TXC_U = 0x01, // interrupt on transmit underflow
TXC_C = 0x02, // interrupt on transmit collision
TXC_R = 0x04, // interrupt on 16 transmission attempts
TXC_S = 0x08, // interrupt on transmit success
TXC_M = 0x0f, // write mask
};
private:
emu_timer *m_tx_timer;
emu_timer *m_int_timer;
// device state
devcb_write_line m_out_int;
devcb_write_line m_out_rxrdy;
devcb_write_line m_out_txrdy;
int m_int_state;
int m_reset_state;
u8 m_station_address[6];
u8 m_rx_status;
u8 m_tx_status;
u8 m_rx_command;
u8 m_tx_command;
util::fifo<u8, MAX_FRAME_SIZE> m_rx_fifo;
util::fifo<u8, MAX_FRAME_SIZE> m_tx_fifo;
};
DECLARE_DEVICE_TYPE(SEEQ8003, seeq8003_device)
#endif // MAME_MACHINE_EDLC_H
|