summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/hpc3.h
blob: 508f707bc303614ed9362c81a1205f7ac4f449b0 (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
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
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/**********************************************************************

    SGI HPC3 "High-performance Peripheral Controller" emulation

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

#ifndef MAME_MACHINE_HPC3_H
#define MAME_MACHINE_HPC3_H

#pragma once

#include "machine/hal2.h"
#include "machine/edlc.h"

class hpc3_device : public device_t, public device_memory_interface
{
public:
	enum pbus_space
	{
		AS_PIO0 = 0,
		AS_PIO1,
		AS_PIO2,
		AS_PIO3,
		AS_PIO4,
		AS_PIO5,
		AS_PIO6,
		AS_PIO7,
		AS_PIO8,
		AS_PIO9
	};

	hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	template <typename T>
	hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&hal2_tag)
		: hpc3_device(mconfig, tag, owner, (uint32_t)0)
	{
		set_hal2_tag(std::forward<T>(hal2_tag));
	}

	template <typename T> void set_gio64_space(T &&tag, int spacenum) { m_gio64_space.set_tag(std::forward<T>(tag), spacenum); }
	template <typename T> void set_hal2_tag(T &&tag) { m_hal2.set_tag(std::forward<T>(tag)); }
	template <typename T> void set_enet(T &&tag) { m_enet.set_tag(std::forward<T>(tag)); }

	auto enet_intr_out_cb() { return m_enet_intr_out_cb.bind(); }
	template <int N> auto hd_rd_cb() { return m_hd_rd_cb[N].bind(); }
	template <int N> auto hd_wr_cb() { return m_hd_wr_cb[N].bind(); }
	template <int N> auto hd_dma_rd_cb() { return m_hd_dma_rd_cb[N].bind(); }
	template <int N> auto hd_dma_wr_cb() { return m_hd_dma_wr_cb[N].bind(); }
	template <int N> auto hd_reset_cb() { return m_hd_reset_cb[N].bind(); }
	auto bbram_rd_cb() { return m_bbram_rd_cb.bind(); }
	auto bbram_wr_cb() { return m_bbram_wr_cb.bind(); }
	auto eeprom_dati_cb() { return m_eeprom_dati_cb.bind(); }
	auto eeprom_dato_cb() { return m_eeprom_dato_cb.bind(); }
	auto eeprom_clk_cb() { return m_eeprom_clk_cb.bind(); }
	auto eeprom_cs_cb() { return m_eeprom_cs_cb.bind(); }
	auto eeprom_pre_cb() { return m_eeprom_pre_cb.bind(); }
	auto dma_complete_int_cb() { return m_dma_complete_int_cb.bind(); }

	void map(address_map &map);

	void enet_rxrdy_w(int state);
	void enet_intr_in_w(int state);

	DECLARE_WRITE_LINE_MEMBER(scsi0_drq);
	DECLARE_WRITE_LINE_MEMBER(scsi1_drq);

protected:
	virtual void device_resolve_objects() override;
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param) override;

	virtual space_config_vector memory_space_config() const override;

	enum fifo_type_t : uint32_t
	{
		FIFO_PBUS,
		FIFO_SCSI0,
		FIFO_SCSI1,
		FIFO_ENET_RECV,
		FIFO_ENET_XMIT
	};

	uint32_t enet_r(offs_t offset, uint32_t mem_mask = ~0);
	void enet_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
	uint32_t hd_enet_r(offs_t offset, uint32_t mem_mask = ~0);
	void hd_enet_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
	template <uint32_t index> uint32_t hd_r(offs_t offset, uint32_t mem_mask = ~0);
	template <uint32_t index> void hd_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
	template <fifo_type_t Type> uint32_t fifo_r(offs_t offset);
	template <fifo_type_t Type> void fifo_w(offs_t offset, uint32_t data);
	uint32_t intstat_r();
	uint32_t misc_r();
	void misc_w(uint32_t data);
	uint32_t eeprom_r();
	void eeprom_w(uint32_t data);
	uint32_t pio_data_r(offs_t offset);
	void pio_data_w(offs_t offset, uint32_t data);
	uint32_t pbusdma_r(offs_t offset, uint32_t mem_mask = ~0);
	void pbusdma_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask = ~0);

	uint32_t dma_config_r(offs_t offset, uint32_t mem_mask = ~0);
	void dma_config_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
	uint32_t pio_config_r(offs_t offset, uint32_t mem_mask = ~0);
	void pio_config_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
	uint32_t bbram_r(offs_t offset);
	void bbram_w(offs_t offset, uint32_t data);

	void do_pbus_dma(uint32_t channel);
	void do_scsi_dma(int channel);

	void dump_chain(uint32_t base);
	void fetch_chain(int channel);
	void decrement_chain(int channel);
	void scsi_fifo_flush(int channel);
	void scsi_drq(bool state, int channel);
	//void scsi_dma(int channel);

	void enet_transmit(int param = 0);
	void enet_misc_w(u32 data);
	bool enet_rx_bc_dec(unsigned const count = 1);

	static const device_timer_id TIMER_PBUS_DMA = 0;

	struct pbus_dma_t
	{
		bool m_active;
		uint32_t m_cur_ptr;
		uint32_t m_desc_ptr;
		uint32_t m_desc_flags;
		uint32_t m_next_ptr;
		uint32_t m_bytes_left;
		uint32_t m_config;
		uint32_t m_control;
		emu_timer *m_timer;
	};

	enum
	{
		PBUS_CTRL_ENDIAN    = 0x00000002,
		PBUS_CTRL_RECV      = 0x00000004,
		PBUS_CTRL_FLUSH     = 0x00000008,
		PBUS_CTRL_DMASTART  = 0x00000010,
		PBUS_CTRL_LOAD_EN   = 0x00000020,
		PBUS_CTRL_REALTIME  = 0x00000040,
		PBUS_CTRL_HIGHWATER = 0x0000ff00,
		PBUS_CTRL_FIFO_BEG  = 0x003f0000,
		PBUS_CTRL_FIFO_END  = 0x3f000000,
	};

	enum
	{
		PBUS_DMADESC_EOX  = 0x80000000,
		PBUS_DMADESC_EOXP = 0x40000000,
		PBUS_DMADESC_XIE  = 0x20000000,
		PBUS_DMADESC_IPG  = 0x00ff0000,
		PBUS_DMADESC_TXD  = 0x00008000,
		PBUS_DMADESC_BC   = 0x00003fff,
	};

	enum
	{
		HPC3_DMACTRL_IRQ    = 0x01,
		HPC3_DMACTRL_ENDIAN = 0x02,
		HPC3_DMACTRL_DIR    = 0x04,
		HPC3_DMACTRL_FLUSH  = 0x08,
		HPC3_DMACTRL_ENABLE = 0x10,
		HPC3_DMACTRL_WRMASK = 0x20,
	};

	enum
	{
		ENET_RECV = 0,
		ENET_XMIT = 1
	};

	const address_space_config m_pio_space_config[10];

	required_address_space m_gio64_space;
	address_space *m_pio_space[10];
	required_device<hal2_device> m_hal2;
	required_device<seeq80c03_device> m_enet;

	devcb_write_line m_enet_intr_out_cb;
	devcb_read8::array<2> m_hd_rd_cb;
	devcb_write8::array<2> m_hd_wr_cb;
	devcb_read8::array<2> m_hd_dma_rd_cb;
	devcb_write8::array<2> m_hd_dma_wr_cb;
	devcb_write_line::array<2> m_hd_reset_cb;
	devcb_read8 m_bbram_rd_cb;
	devcb_write8 m_bbram_wr_cb;
	devcb_read_line m_eeprom_dati_cb;
	devcb_write_line m_eeprom_dato_cb;
	devcb_write_line m_eeprom_clk_cb;
	devcb_write_line m_eeprom_cs_cb;
	devcb_write_line m_eeprom_pre_cb;
	devcb_write_line m_dma_complete_int_cb;

	uint32_t m_intstat;
	uint32_t m_misc;
	uint32_t m_cpu_aux_ctrl;

	struct scsi_dma_t
	{
		uint32_t m_cbp;
		uint32_t m_nbdp;
		uint8_t m_ctrl;
		uint32_t m_bc;
		uint16_t m_count;
		uint32_t m_dmacfg;
		uint32_t m_piocfg;
		bool m_drq;
		bool m_big_endian;
		bool m_to_device;
		bool m_active;
	};

	scsi_dma_t m_scsi_dma[2];
	pbus_dma_t m_pbus_dma[8];
	uint32_t m_pio_config[10];

	std::unique_ptr<uint32_t[]> m_pbus_fifo;
	std::unique_ptr<uint32_t[]> m_scsi_fifo[2];
	std::unique_ptr<uint32_t[]> m_enet_fifo[2];

private:
	emu_timer *m_enet_tx_timer;

	enum enet_dma_rx_ctrl : u32
	{
		RXC_ST   = 0x0000'00bf, // edlc receive status
		RXC_LC   = 0x0000'0040, // late receive collision
		RXC_LE   = 0x0000'0100, // receive little endian
		RXC_CA   = 0x0000'0200, // receive channel active
		RXC_CAM  = 0x0000'0400, // receive channel active mask
		RXC_RBO  = 0x0000'0800, // receive buffer overflow

		// individual receive status bits
		RXC_ST_V = 0x0000'0001, // received frame with overflow error
		RXC_ST_C = 0x0000'0002, // received frame with crc error
		RXC_ST_D = 0x0000'0004, // received frame with dribble error
		RXC_ST_S = 0x0000'0008, // received short frame
		RXC_ST_E = 0x0000'0010, // received end of frame
		RXC_ST_G = 0x0000'0020, // received good frame
		RXC_ST_O = 0x0000'0080, // old/new status
	};
	enum enet_dma_tx_ctrl : u32
	{
		TXC_ST   = 0x0000'00ef, // edlc transmit status
		TXC_LC   = 0x0000'0010, // late transmit collision
		TXC_LE   = 0x0000'0100, // transmit little endian
		TXC_CA   = 0x0000'0200, // transmit channel active
		TXC_CAM  = 0x0000'0400, // transmit channel active mask

		// individual transmit status bits
		TXC_ST_U = 0x0000'0001, // transmit underflow
		TXC_ST_C = 0x0000'0002, // transmit collision
		TXC_ST_R = 0x0000'0004, // 16 transmission attempts
		TXC_ST_S = 0x0000'0008, // transmission successful
		TXC_ST_O = 0x0000'0080, // old/new status
	};
	enum enet_dma_bc : u32
	{
		BC_BC   = 0x0000'3fff, // byte count
		BC_TXD  = 0x0000'8000, // transmit done
		BC_IPG  = 0x00ff'0000, // inter-packet gap
		BC_XIE  = 0x2000'0000, // transmit interrupt enable
		BC_EOXP = 0x4000'0000, // end of packet
		BC_EOX  = 0x8000'0000, // end of descriptor chain
	};
	enum enet_enet_misc : u32
	{
		MISC_RESET    = 0x0000'0001, // channel reset
		MISC_INT      = 0x0000'0002, // interrupt
		MISC_LOOPBACK = 0x0000'0004, // loopback
	};

	// ethernet registers
	u32 m_enet_rx_cbp;    // current receive buffer pointer
	u32 m_enet_rx_nbdp;   // next receive buffer descriptor pointer
	u32 m_enet_rx_bc;     // receive byte count
	u32 m_enet_rx_ctrl;   // receive status
	u32 m_enet_rx_gio;    // receive gio fifo pointer
	u32 m_enet_rx_dev;    // receive device fifo pointer
	u32 m_enet_misc;      // reset, clear interrupt, loopback
	u32 m_enet_piocfg;    // pio configuration
	u32 m_enet_dmacfg;    // dma configuration
	u32 m_enet_tx_cbp;    // current transmit buffer pointer
	u32 m_enet_tx_nbdp;   // next transmit buffer descriptor pointer
	u32 m_enet_tx_bc;     // transmit byte count
	u32 m_enet_tx_ctrl;   // transmit status
	u32 m_enet_tx_gio;    // transmit gio fifo pointer
	u32 m_enet_tx_dev;    // transmit device fifo pointer
	u32 m_enet_rx_cbdp;   // current receive buffer descriptor pointer
	u32 m_enet_tx_cpfbdp; // current/previous first transmit buffer descriptor pointer
	u32 m_enet_tx_ppfbdp; // previous/previous? first transmit buffer descriptor pointer
};

DECLARE_DEVICE_TYPE(SGI_HPC3, hpc3_device)

#endif // MAME_MACHINE_HPC3_H