summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/am79c90.h
blob: 258c5f27506a581c17fe5b2271235805cf62c918 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay

#ifndef MAME_MACHINE_AM79C90_H
#define MAME_MACHINE_AM79C90_H

#pragma once

#include "hashing.h"

class am7990_device_base : public device_t, public device_network_interface
{
public:
	auto intr_out() { return m_intr_out_cb.bind(); }
	auto dma_in() { return m_dma_in_cb.bind(); }
	auto dma_out() { return m_dma_out_cb.bind(); }

	DECLARE_READ16_MEMBER(regs_r);
	DECLARE_WRITE16_MEMBER(regs_w);

	void reset_w(int state) { if (!state) device_reset(); }

protected:
	am7990_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0);

	// 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;
	virtual void recv_complete_cb(int result) override;
	virtual void send_complete_cb(int result) override;

	// device helpers
	void initialize();
	void update_interrupts();
	int receive(u8 *buf, int length);
	TIMER_CALLBACK_MEMBER(transmit_poll);
	void transmit();
	bool address_filter(u8 *buf);

	void dma_in(u32 address, u8 *buf, int length);
	void dma_out(u32 address, u8 *buf, int length);
	void dump_bytes(u8 *buf, int length);

	virtual int get_buf_length(u16 data) const = 0;

	// constants and masks
	static constexpr u32 FCS_RESIDUE = 0xdebb20e3;
	static const u8 ETH_BROADCAST[];

	static constexpr u32 INIT_ADDR_MASK = 0xfffffe;
	static constexpr u32 RING_ADDR_MASK = 0xfffff8;
	static constexpr auto TX_POLL_PERIOD = attotime::from_usec(1600);

	enum csr0_mask : u16
	{
		CSR0_INIT = 0x0001, // initialize
		CSR0_STRT = 0x0002, // start
		CSR0_STOP = 0x0004, // stop
		CSR0_TDMD = 0x0008, // transmit demand
		CSR0_TXON = 0x0010, // transmitter on
		CSR0_RXON = 0x0020, // receiver on
		CSR0_INEA = 0x0040, // interrupt enable
		CSR0_INTR = 0x0080, // interrupt flag
		CSR0_IDON = 0x0100, // initialization done
		CSR0_TINT = 0x0200, // transmitter interrupt
		CSR0_RINT = 0x0400, // receiver interrupt
		CSR0_MERR = 0x0800, // memory error
		CSR0_MISS = 0x1000, // missed packet
		CSR0_CERR = 0x2000, // collision error
		CSR0_BABL = 0x4000, // babble
		CSR0_ERR  = 0x8000, // error

		CSR0_ANY_INTR = CSR0_BABL | CSR0_MISS | CSR0_MERR | CSR0_RINT | CSR0_TINT | CSR0_IDON,
		CSR0_ANY_ERR  = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR,
	};

	enum csr3_mask : u16
	{
		CSR3_BCON = 0x0001, // byte control
		CSR3_ACON = 0x0002, // ale control
		CSR3_BSWP = 0x0004, // byte swap

		CSR3_MASK = 0x0007
	};

	enum mode_mask : u16
	{
		MODE_DRX  = 0x0001, // disable the receiver
		MODE_DTX  = 0x0002, // disable the transmitter
		MODE_LOOP = 0x0004, // loopback
		MODE_DTCR = 0x0008, // disable transmit crc
		MODE_COLL = 0x0010, // force collision
		MODE_DRTY = 0x0020, // disable retry
		MODE_INTL = 0x0040, // internal loopback
		MODE_EMBA = 0x0080, // enable modified back-off algorithm (C-LANCE only)
		MODE_PROM = 0x8000, // promiscuous
	};

	enum tmd1_mask : u16
	{
		TMD1_HADR    = 0x00ff, // high order address
		TMD1_ENP     = 0x0100, // end of packet
		TMD1_STP     = 0x0200, // start of packet
		TMD1_DEF     = 0x0400, // deferred
		TMD1_ONE     = 0x0800, // one retry
		TMD1_MORE    = 0x1000, // more than one retry
		TMD1_ADD_FCS = 0x2000, // append fcs (C-LANCE only)
		TMD1_ERR     = 0x4000, // error
		TMD1_OWN     = 0x8000, // owned by lance
	};

	enum tmd3_mask : u16
	{
		TMD3_TDR  = 0x03ff, // time domain reflectometry
		TMD3_RTRY = 0x0400, // retry error
		TMD3_LCAR = 0x0800, // loss of carrier
		TMD3_LCOL = 0x1000, // late collision
		TMD3_RES  = 0x2000,
		TMD3_UFLO = 0x4000, // underflow error
		TMD3_BUFF = 0x8000, // buffer error
	};

	enum rmd1_mask : u16
	{
		RMD1_HADR = 0x00ff, // high order address
		RMD1_ENP  = 0x0100, // end of packet
		RMD1_STP  = 0x0200, // start of packet
		RMD1_BUFF = 0x0400, // buffer error
		RMD1_CRC  = 0x0800, // crc error
		RMD1_OFLO = 0x1000, // overflow error
		RMD1_FRAM = 0x2000, // framing error
		RMD1_ERR  = 0x4000, // error
		RMD1_OWN  = 0x8000, // owned by lance
	};

	enum rmd3_mask : u16
	{
		RMD3_MCNT = 0x0fff, // message byte count
	};

private:
	devcb_write_line m_intr_out_cb;
	devcb_read16 m_dma_in_cb;
	devcb_write16 m_dma_out_cb;

	u16 m_rap;
	u16 m_csr[4];

	u16 m_mode;
	u64 m_logical_addr_filter;
	u8 m_physical_addr[6];

	u32 m_rx_ring_base;
	u8 m_rx_ring_mask;
	u8 m_rx_ring_pos;
	u16 m_rx_md[4];

	u32 m_tx_ring_base;
	u8 m_tx_ring_mask;
	u8 m_tx_ring_pos;
	u16 m_tx_md[4];

	emu_timer *m_transmit_poll;
	int m_intr_out_state;
	bool m_idon;

	// internal loopback buffer
	u8 m_lb_buf[36];
	int m_lb_length;
};

class am7990_device : public am7990_device_base
{
public:
	am7990_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);

protected:
	virtual int get_buf_length(u16 data) const override { return (data == 0xf000) ? 4096 : -s16(0xf000 | data); }
};

class am79c90_device : public am7990_device_base
{
public:
	am79c90_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);

protected:
	virtual int get_buf_length(u16 data) const override { return data ? ((data == 0xf000) ? 4096 : -s16(0xf000 | data)) : 0; }
};

DECLARE_DEVICE_TYPE(AM7990, am7990_device)
DECLARE_DEVICE_TYPE(AM79C90, am79c90_device)

#endif // MAME_MACHINE_AM79C90_H