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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
/*
* threecom3c505.h - 3COM 3C505 ethernet controller
*
* Created on: August 27, 2010
* Author: Hans Ostermeyer
*
* Released for general non-commercial use under the MAME license
* Visit http://mamedev.org for licensing and usage restrictions.
*
*/
#pragma once
#ifndef THREECOM3C505_H_
#define THREECOM3C505_H_
#include "emu.h"
#define CMD_BUFFER_SIZE 100
#define ETH_BUFFER_SIZE 2048
#define PGM_BUFFER_SIZE 0x2000
#define ETHERNET_ADDR_SIZE 6 /* size of ethernet addr */
#define RX_FIFO_SIZE 32
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
DECLARE_READ8_DEVICE_HANDLER( threecom3c505_r );
DECLARE_WRITE8_DEVICE_HANDLER( threecom3c505_w );
int threecom3c505_receive(device_t *device, const UINT8 *data, int length);
void threecom3c505_set_verbose(int on_off);
//**************************************************************************
// DEVICE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_THREECOM3C505_ADD(_tag, _interface) \
MCFG_DEVICE_ADD(_tag, THREECOM3C505, 0) \
threecom3c505_device::static_set_interface(*device, _interface);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
typedef void (*threecom3c505_set_irq)(device_t *, int);
typedef void (*threecom3c505_tx_init)(device_t *);
typedef int (*threecom3c505_tx_data)(device_t *, const UINT8 *, int);
typedef int (*threecom3c505_setfilter)(device_t *, int);
struct threecom3c505_interface
{
threecom3c505_set_irq set_irq;
threecom3c505_tx_init tx_init;
threecom3c505_tx_data tx_data;
threecom3c505_setfilter setfilter;
};
#define THREECOM3C505_INTERFACE(name) const struct threecom3c505_interface (name)
// ======================> PCB data structure
#pragma pack(1)
struct Memconf
{
UINT16 cmd_q, rcv_q, mcast, frame, rcv_b, progs;
};
struct Rcv_pkt
{
UINT16 buf_ofs, buf_seg, buf_len, timeout;
};
struct Xmit_pkt
{
UINT16 buf_ofs, buf_seg, pkt_len;
};
struct Rcv_resp
{
UINT16 buf_ofs, buf_seg, buf_len, pkt_len, timeout, status;
UINT32 timetag;
};
struct Xmit_resp
{
UINT16 buf_ofs, buf_seg, c_stat, status;
};
struct Netstat
{
UINT32 tot_recv, tot_xmit;
UINT16 err_CRC, err_align, err_res, err_ovrrun;
};
struct Selftest
{
UINT16 error;
union
{
UINT16 ROM_cksum;
struct
{
UINT16 ofs, seg;
} RAM;
UINT16 i82586;
} failure;
};
struct Info
{
UINT8 minor_vers, major_vers;
UINT16 ROM_cksum, RAM_sz, free_ofs, free_seg;
};
struct Memdump
{
UINT16 size, off, seg;
};
/*
Primary Command Block. The most important data structure. All communication
between the host and the adapter is done with these. (Except for the actual
Ethernet data, which has different packaging.)
*/
struct pcb_struct
{
UINT8 command;
UINT8 length;
union
{
struct Memconf memconf;
UINT16 configure;
struct Rcv_pkt rcv_pkt;
struct Xmit_pkt xmit_pkt;
UINT8 multicast[10][6];
UINT8 eth_addr[6];
INT16 failed;
struct Rcv_resp rcv_resp;
struct Xmit_resp xmit_resp;
struct Netstat netstat;
struct Selftest selftest;
struct Info info;
struct Memdump memdump;
UINT8 raw[62];
} data;
};
#pragma pack()
// ======================> threecom3c505_device
class threecom3c505_device: public device_t,
public device_network_interface,
public threecom3c505_interface
{
public:
// construction/destruction
threecom3c505_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
static void static_set_interface(device_t &device, const threecom3c505_interface &interface);
void recv_cb(UINT8 *buf, int len);
// device register I/O
UINT8 read_port(offs_t offset);
void write_port(offs_t offset, UINT8 data);
private:
// device-level overrides
virtual void device_start();
virtual void device_reset();
const char *cpu_context();
class data_buffer_fifo;
/* data buffer */
class data_buffer
{
friend class data_buffer_fifo;
public:
data_buffer();
void start(threecom3c505_device *device, INT32 size);
void reset();
int append(UINT8 data);
UINT8 get(int i) { return m_data[i]; };
UINT16 get_word(int i) { return (m_data[i*2+1] << 8) + m_data[i*2]; };
int is_empty() {return m_length == 0; };
int is_full() {return m_length >= m_size; };
UINT16 get_length() { return m_length; };
UINT16 get_size() { return m_size; };
UINT8 *get_data() { return m_data; };
void copy(data_buffer *db) const;
void log(const char *title) const;
private:
threecom3c505_device *m_device; // pointer back to our device
UINT16 m_length;
UINT16 m_size;
UINT8 *m_data;
};
/* data_buffer fifo (used to buffer the received data) */
class data_buffer_fifo
{
public:
data_buffer_fifo();
void start(threecom3c505_device *device, INT32 size, INT32 db_size);
void reset();
int put(const UINT8 data[], const int length);
int get(data_buffer *db);
int is_empty () { return m_get_index == m_put_index; }
int is_full () { return ((m_put_index + 1) % m_size) == m_get_index; }
private:
threecom3c505_device *m_device; // pointer back to our device
UINT16 m_size;
UINT16 m_count;
UINT16 m_get_index;
UINT16 m_put_index;
data_buffer *m_db[RX_FIFO_SIZE];
};
void set_filter_list();
void set_interrupt(enum line_state state);
static TIMER_CALLBACK( static_do_command );
void log_command();
void log_response();
void log_tx_data();
void log_rx_data();
void do_receive_command();
void set_command_pending(int onoff);
void do_command();
int ethernet_packet_is_for_me(const UINT8 mac_address[]);
void write_command_port( UINT8 data);
UINT8 read_command_port();
void write_data_port( UINT8 data);
UINT8 read_data_port();
void write_control_port( UINT8 data);
UINT8 read_status_port();
// pointer to myself (nasty: used for cpu_context)
threecom3c505_device *m_device;
UINT8 m_reg[16];
UINT8 m_status;
UINT8 m_control;
UINT8 m_command_buffer[CMD_BUFFER_SIZE];
int m_command_index;
int m_command_pending;
int m_wait_for_ack;
int m_wait_for_nak;
data_buffer_fifo m_rx_fifo;
data_buffer m_rx_data_buffer; // the ethernet receive buffer
int m_rx_data_index;
int m_rx_pending;
data_buffer m_tx_data_buffer; // the ethernet transmit buffer
int m_tx_data_length;
data_buffer m_program_buffer; // the program data buffer
int m_program_length;
pcb_struct m_response;
int m_response_length;
int m_response_index;
pcb_struct m_rcv_response;
UINT16 m_microcode_version;
UINT16 m_microcode_running;
UINT16 m_i82586_config;
struct Netstat m_netstat;
UINT8 m_station_address[ETHERNET_ADDR_SIZE];
UINT8 m_multicast_list[ETHERNET_ADDR_SIZE*2];
UINT8 m_filter_list[ETHERNET_ADDR_SIZE*4];
enum line_state irq_state;
emu_timer * m_do_command_timer; // timer to delay command execution
};
// device type definition
extern const device_type THREECOM3C505;
#endif /* THREECOM3C505_H_ */
|