summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/8237dma.h
blob: 864aba746ada9e6ea0bcefc1a55c4c0e02c1d406 (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
/***************************************************************************

    Intel 8237 Programmable DMA Controller emulation

    Copyright Nicola Salmoria and the MAME Team.
    Visit http://mamedev.org for licensing and usage restrictions.

****************************************************************************
                            _____   _____
                 _I/OR   1 |*    \_/     | 40  A7
                 _I/OW   2 |             | 39  A6
                 _MEMR   3 |             | 38  A5
                 _MEMW   4 |             | 37  A4
                         5 |             | 36  _EOP
                 READY   6 |             | 35  A3
                  HLDA   7 |             | 34  A2
                 ADSTB   8 |             | 33  A1
                   AEN   9 |             | 32  A0
                   HRQ  10 |     8237    | 31  Vcc
                   _CS  11 |             | 30  DB0
                   CLK  12 |             | 29  DB1
                 RESET  13 |             | 28  DB2
                 DACK2  14 |             | 27  DB3
                 DACK3  15 |             | 26  DB4
                 DREQ3  16 |             | 25  DACK0
                 DREQ2  17 |             | 24  DACK1
                 DREQ1  18 |             | 23  DB5
                 DREQ0  19 |             | 22  DB6
                   GND  20 |_____________| 21  DB7

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

#pragma once

#ifndef __I8237__
#define __I8237__

#include "emu.h"



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

#define MCFG_I8237_ADD(_tag, _clock, _config) \
	MCFG_DEVICE_ADD(_tag, I8237, _clock) \
	MCFG_DEVICE_CONFIG(_config)

#define I8237_INTERFACE(_name) \
	const i8237_interface (_name) =


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


// ======================> i8237_interface

struct i8237_interface
{
	devcb_write_line	m_out_hrq_cb;
	devcb_write_line	m_out_eop_cb;

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

	/* channel accessors */
	devcb_read8			m_in_ior_cb[4];
	devcb_write8		m_out_iow_cb[4];
	devcb_write_line	m_out_dack_cb[4];
};



// ======================> i8237_device

class i8237_device :  public device_t,
                      public i8237_interface
{
public:
    // construction/destruction
    i8237_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

	/* register access */
	UINT8 i8237_r(UINT32 offset);
	void i8237_w(UINT32 offset, UINT8 data);

	/* hold acknowledge */
	void i8237_hlda_w(UINT8 state) { m_hlda = state; }

	/* data request */
	void i8237_drq_write(int channel, int state);

	void i8237_timerproc();

protected:
    // device-level overrides
    virtual void device_config_complete();
    virtual void device_start();
    virtual void device_reset();
    virtual void device_post_load() { }
    virtual void device_clock_changed() { }

	static TIMER_CALLBACK( i8237_timerproc_callback );
	static TIMER_CALLBACK( receive_event_callback );

private:

	void i8237_do_read();
	void i8237_do_write();
	void i8237_advance();
	void i8327_set_dack(int channel);

	/* States that the i8237 device can be in */
	enum dma8237_state
	{
		DMA8237_SI,			/* Idle state */
		DMA8237_S0,			/* HRQ has been triggered, waiting to receive HLDA */
	//  DMA8237_SW,         /* Wait state */
		DMA8237_SC,			/* Cascade mode, waiting for peripheral */

		/* Normal transfer states */
		DMA8237_S1,			/* Output A8-A15; only used when A8-A15 really needs to be output */
		DMA8237_S2,			/* Output A0-A7 */
		DMA8237_S3,			/* Initiate read; skipped in compressed timing. On the S2->S3 transition DACK is set. */
		DMA8237_S4,			/* Perform read/write */

		/* Memory to memory transfer states */
		DMA8237_S11,		/* Output A8-A15 */
	//  DMA8237_S12,        /* Output A0-A7 */
	//  DMA8237_S13,        /* Initiate read */
	//  DMA8237_S14,        /* Perform read/write */
	//  DMA8237_S21,        /* Output A8-A15 */
	//  DMA8237_S22,        /* Output A0-A7 */
	//  DMA8237_S23,        /* Initiate read */
	//  DMA8237_S24,        /* Perform read/write */
	};

	devcb_resolved_write_line	m_out_hrq_func;
	devcb_resolved_write_line	m_out_eop_func;
	devcb_resolved_read8		m_in_memr_func;
	devcb_resolved_write8		m_out_memw_func;

	emu_timer *m_timer;

	struct
	{
		devcb_resolved_read8		m_in_ior_func;
		devcb_resolved_write8		m_out_iow_func;
		devcb_resolved_write_line	m_out_dack_func;
		UINT16 m_base_address;
		UINT16 m_base_count;
		UINT16 m_address;
		UINT16 m_count;
		UINT8 m_mode;
		int m_high_address_changed;
	} m_chan[4];

	UINT32 m_msb : 1;
	UINT32 m_eop : 1;
	UINT8 m_temp;
	UINT8 m_temporary_data;
	UINT8 m_command;
	UINT8 m_drq;
	UINT8 m_mask;
	UINT8 m_hrq;
	UINT8 m_hlda;

	/* bits  0- 3 :  Terminal count for channels 0-3
     * bits  4- 7 :  Transfer in progress for channels 0-3 */
	UINT8 m_status;

	dma8237_state m_state;		/* State the device is currently in */
	int m_service_channel;		/* Channel we will be servicing */
	int m_last_service_channel;	/* Previous channel we serviced; used to determine channel priority. */
};


// device type definition
extern const device_type I8237;



/***************************************************************************
    PROTOTYPES
***************************************************************************/

/* register access */
READ8_DEVICE_HANDLER( i8237_r );
WRITE8_DEVICE_HANDLER( i8237_w );

/* hold acknowledge */
WRITE_LINE_DEVICE_HANDLER( i8237_hlda_w );

/* ready */
WRITE_LINE_DEVICE_HANDLER( i8237_ready_w );

/* data request */
WRITE_LINE_DEVICE_HANDLER( i8237_dreq0_w );
WRITE_LINE_DEVICE_HANDLER( i8237_dreq1_w );
WRITE_LINE_DEVICE_HANDLER( i8237_dreq2_w );
WRITE_LINE_DEVICE_HANDLER( i8237_dreq3_w );

/* end of process */
WRITE_LINE_DEVICE_HANDLER( i8237_eop_w );

#endif