summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/i8257.h
blob: a060852c7a2cc909e4f3661108212464d01ab27e (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
// license:BSD-3-Clause
// copyright-holders:Curt Coder
/***************************************************************************

    Intel 8257 DMA Controller emulation

****************************************************************************
                            _____   _____
                 _I/OR   1 |*    \_/     | 40  A7
                 _I/OW   2 |             | 39  A6
                 _MEMR   3 |             | 38  A5
                 _MEMW   4 |             | 37  A4
                  MARK   5 |             | 36  TC
                 READY   6 |             | 35  A3
                  HLDA   7 |             | 34  A2
                 ADSTB   8 |             | 33  A1
                   AEN   9 |             | 32  A0
                   HRQ  10 |     8257    | 31  Vcc
                   _CS  11 |             | 30  D0
                   CLK  12 |             | 29  D1
                 RESET  13 |             | 28  D2
                _DACK2  14 |             | 27  D3
                _DACK3  15 |             | 26  D4
                  DRQ3  16 |             | 25  _DACK0
                  DRQ2  17 |             | 24  _DACK1
                  DRQ1  18 |             | 23  D5
                  DRQ0  19 |             | 22  D6
                   GND  20 |_____________| 21  D7

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

#pragma once

#ifndef __I8257__
#define __I8257__




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

#define MCFG_I8257_OUT_HRQ_CB(_devcb) \
	devcb = &i8257_device::set_out_hrq_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_TC_CB(_devcb) \
	devcb = &i8257_device::set_out_tc_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_IN_MEMR_CB(_devcb) \
	devcb = &i8257_device::set_in_memr_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_MEMW_CB(_devcb) \
	devcb = &i8257_device::set_out_memw_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_IN_IOR_0_CB(_devcb) \
	devcb = &i8257_device::set_in_ior_0_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_IN_IOR_1_CB(_devcb) \
	devcb = &i8257_device::set_in_ior_1_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_IN_IOR_2_CB(_devcb) \
	devcb = &i8257_device::set_in_ior_2_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_IN_IOR_3_CB(_devcb) \
	devcb = &i8257_device::set_in_ior_3_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_IOW_0_CB(_devcb) \
	devcb = &i8257_device::set_out_iow_0_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_IOW_1_CB(_devcb) \
	devcb = &i8257_device::set_out_iow_1_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_IOW_2_CB(_devcb) \
	devcb = &i8257_device::set_out_iow_2_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_IOW_3_CB(_devcb) \
	devcb = &i8257_device::set_out_iow_3_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_DACK_0_CB(_devcb) \
	devcb = &i8257_device::set_out_dack_0_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_DACK_1_CB(_devcb) \
	devcb = &i8257_device::set_out_dack_1_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_DACK_2_CB(_devcb) \
	devcb = &i8257_device::set_out_dack_2_callback(*device, DEVCB_##_devcb);

#define MCFG_I8257_OUT_DACK_3_CB(_devcb) \
	devcb = &i8257_device::set_out_dack_3_callback(*device, DEVCB_##_devcb);

// HACK: the radio86 and alikes require this, is it a bug in the soviet clone or is there something else happening?
#define MCFG_I8257_REVERSE_RW_MODE(_flag) \
		i8257_device::static_set_reverse_rw_mode(*device, _flag);

// ======================> i8257_device

class i8257_device :  public device_t,
						public device_execute_interface
{
public:
	// construction/destruction
	i8257_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );

	DECLARE_WRITE_LINE_MEMBER( hlda_w );
	DECLARE_WRITE_LINE_MEMBER( ready_w );

	DECLARE_WRITE_LINE_MEMBER( dreq0_w );
	DECLARE_WRITE_LINE_MEMBER( dreq1_w );
	DECLARE_WRITE_LINE_MEMBER( dreq2_w );
	DECLARE_WRITE_LINE_MEMBER( dreq3_w );

	template<class _Object> static devcb_base &set_out_hrq_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_hrq_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_tc_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_tc_cb.set_callback(object); }

	template<class _Object> static devcb_base &set_in_memr_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_in_memr_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_memw_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_memw_cb.set_callback(object); }

	template<class _Object> static devcb_base &set_in_ior_0_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_in_ior_0_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_in_ior_1_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_in_ior_1_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_in_ior_2_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_in_ior_2_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_in_ior_3_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_in_ior_3_cb.set_callback(object); }

	template<class _Object> static devcb_base &set_out_iow_0_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_iow_0_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_iow_1_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_iow_1_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_iow_2_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_iow_2_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_iow_3_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_iow_3_cb.set_callback(object); }

	template<class _Object> static devcb_base &set_out_dack_0_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_dack_0_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_dack_1_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_dack_1_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_dack_2_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_dack_2_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_dack_3_callback(device_t &device, _Object object) { return downcast<i8257_device &>(device).m_out_dack_3_cb.set_callback(object); }

	static void static_set_reverse_rw_mode(device_t &device, bool flag) { downcast<i8257_device &>(device).m_reverse_rw = flag; }
protected:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void execute_run() override;

	int m_icount;

private:
	inline void dma_request(int channel, int state);
	inline bool is_request_active(int channel);
	inline void set_hreq(int state);
	inline void set_dack();
	inline void dma_read();
	inline void dma_write();
	inline void advance();
	inline void set_tc(int state);
	bool next_channel();

	bool m_reverse_rw;
	bool m_tc;
	int m_msb;
	int m_hreq;
	int m_hack;
	int m_ready;
	int m_state;
	int m_current_channel;
	int m_last_channel;
	uint8_t m_transfer_mode;
	uint8_t m_status;
	uint8_t m_request;
	uint8_t m_temp;

	devcb_write_line   m_out_hrq_cb;
	devcb_write_line   m_out_tc_cb;

	/* accessors to main memory */
	devcb_read8        m_in_memr_cb;
	devcb_write8       m_out_memw_cb;

	/* channel accessors */
	devcb_read8        m_in_ior_0_cb;
	devcb_read8        m_in_ior_1_cb;
	devcb_read8        m_in_ior_2_cb;
	devcb_read8        m_in_ior_3_cb;
	devcb_write8       m_out_iow_0_cb;
	devcb_write8       m_out_iow_1_cb;
	devcb_write8       m_out_iow_2_cb;
	devcb_write8       m_out_iow_3_cb;
	devcb_write_line   m_out_dack_0_cb;
	devcb_write_line   m_out_dack_1_cb;
	devcb_write_line   m_out_dack_2_cb;
	devcb_write_line   m_out_dack_3_cb;

	struct
	{
		uint16_t m_address;
		uint16_t m_count;
		uint8_t m_mode;
	} m_channel[4];
};


// device type definition
extern const device_type I8257;



#endif