summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/smc91c9x.h
blob: b0695c4f6cb3c581f7f04a4e317bb9f66cb5895f (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
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/*************************************************************************

    SMC91C9X ethernet controller implementation

    by Aaron Giles, Jean-François DEL NERO

**************************************************************************/

#ifndef MAME_MACHINE_SMC91C9X_H
#define MAME_MACHINE_SMC91C9X_H

/***************************************************************************
    TYPE DEFINITIONS
***************************************************************************/

class smc91c9x_device : public device_t,public device_network_interface
{
public:
	template <class Object> devcb_base &set_irq_callback(Object &&cb) { return m_irq_handler.set_callback(std::forward<Object>(cb)); }

	DECLARE_READ16_MEMBER( read );
	DECLARE_WRITE16_MEMBER( write );
	TIMER_CALLBACK_MEMBER(send_frame);

	virtual void recv_cb(uint8_t *data, int length) override;
	void set_link_connected(bool connected) { m_link_unconnected = !connected; };

protected:
	smc91c9x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;

	virtual void device_pre_save(void) override;
	virtual void device_post_load(void) override;

private:
	static constexpr unsigned ETHER_BUFFER_SIZE   = 2048;
	// TODO: 96 device is larger
	static constexpr unsigned ETHER_BUFFERS = 16;
	static constexpr unsigned ETHERNET_ADDR_SIZE = 6;

	// external network is present
	bool m_network_available;

	// mmu
	// The bits in these vectors indicate a packet has been allocated
	u32 m_alloc_rx, m_alloc_tx;
	std::vector<u32> m_comp_tx, m_comp_rx;
	// Fifo for allocated (queued) transmit packets
	std::vector<u32> m_trans_tx;
	// Save vector data and sizes for proper save state restoration
	u32 m_comp_tx_data[ETHER_BUFFERS], m_comp_rx_data[ETHER_BUFFERS], m_trans_tx_data[ETHER_BUFFERS];
	u32 m_comp_tx_size, m_comp_rx_size, m_trans_tx_size;
	// Requests a packet allocation and returns true
	// and sets the packet number if successful
	bool alloc_req(const int tx, int &packet_num);
	// Releases an allocation
	void alloc_release(const int packet_num);
	// Resets the MMU
	void mmu_reset();

	// internal state
	devcb_write_line m_irq_handler;

	// link unconnected
	bool m_link_unconnected;

	/* raw register data and masks */
	uint16_t          m_reg[64];
	uint16_t          m_regmask[64];

	/* IRQ information */
	uint8_t           m_irq_state;

	// Main memory
	uint8_t           m_buffer[ETHER_BUFFER_SIZE * ETHER_BUFFERS];

	/* counters */
	uint32_t          m_sent;
	uint32_t          m_recd;

	emu_timer* m_tx_timer;

	int ethernet_packet_is_for_me(const uint8_t *mac_address);
	int is_broadcast(const uint8_t *mac_address);

	void update_ethernet_irq();
	void update_stats();

	void process_command(uint16_t data);
	void clear_tx_fifo();
	void clear_rx_fifo();

};


class smc91c94_device : public smc91c9x_device
{
public:
	smc91c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class smc91c96_device : public smc91c9x_device
{
public:
	smc91c96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};


DECLARE_DEVICE_TYPE(SMC91C94, smc91c94_device)
DECLARE_DEVICE_TYPE(SMC91C96, smc91c96_device)


/***************************************************************************
    DEVICE CONFIGURATION MACROS
***************************************************************************/

#define MCFG_SMC91C94_ADD(tag) \
	MCFG_DEVICE_ADD((tag), SMC91C94, 0)

#define MCFG_SMC91C94_IRQ_CALLBACK(write) \
	downcast<smc91c94_device &>(*device).set_irq_callback(DEVCB_##write);

#define MCFG_SMC91C96_ADD(tag) \
	MCFG_DEVICE_ADD((tag), SMC91C96, 0)

#define MCFG_SMC91C96_IRQ_CALLBACK(write) \
	downcast<smc91c96_device &>(*device).set_irq_callback(DEVCB_##write);

#endif // MAME_MACHINE_SMC91C9X_H