summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/edlc.h
blob: 57e52b6159a96ed6354b45e90e38a86f4d5f4336 (plain) (blame)
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