summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/z80dma.h
blob: 02b7866463c888abb0a24ff334dd95ed5e3ee13c (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
// license:BSD-3-Clause
// copyright-holders:Couriersud
/***************************************************************************

    Zilog Z80 DMA Direct Memory Access Controller emulation

****************************************************************************
                            _____   _____
                    A5   1 |*    \_/     | 40  A6
                    A4   2 |             | 39  A7
                    A3   3 |             | 38  IEI
                    A2   4 |             | 37  _INT/_PULSE
                    A1   5 |             | 36  IEO
                    A0   6 |             | 35  D0
                   CLK   7 |             | 34  D1
                   _WR   8 |             | 33  D2
                   _RD   9 |             | 32  D3
                 _IORQ  10 |    Z8410    | 31  D4
                   +5V  11 |             | 30  GND
                 _MREQ  12 |             | 29  D5
                  _BAO  13 |             | 28  D6
                  _BAI  14 |             | 27  D7
               _BUSREQ  15 |             | 26  _M1
             _CE/_WAIT  16 |             | 25  RDY
                   A15  17 |             | 24  A8
                   A14  18 |             | 23  A9
                   A13  19 |             | 22  A10
                   A12  20 |_____________| 21  A11

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

#ifndef MAME_MACHINE_Z80DMA_H
#define MAME_MACHINE_Z80DMA_H

#pragma once

#include "machine/z80daisy.h"


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

#define MCFG_Z80DMA_OUT_BUSREQ_CB(_devcb) \
	downcast<z80dma_device &>(*device).set_out_busreq_callback(DEVCB_##_devcb);

#define MCFG_Z80DMA_OUT_INT_CB(_devcb) \
	downcast<z80dma_device &>(*device).set_out_int_callback(DEVCB_##_devcb);

#define MCFG_Z80DMA_OUT_BAO_CB(_devcb) \
	downcast<z80dma_device &>(*device).set_out_bao_callback(DEVCB_##_devcb);

#define MCFG_Z80DMA_IN_MREQ_CB(_devcb) \
	downcast<z80dma_device &>(*device).set_in_mreq_callback(DEVCB_##_devcb);

#define MCFG_Z80DMA_OUT_MREQ_CB(_devcb) \
	downcast<z80dma_device &>(*device).set_out_mreq_callback(DEVCB_##_devcb);

#define MCFG_Z80DMA_IN_IORQ_CB(_devcb) \
	downcast<z80dma_device &>(*device).set_in_iorq_callback(DEVCB_##_devcb);

#define MCFG_Z80DMA_OUT_IORQ_CB(_devcb) \
	downcast<z80dma_device &>(*device).set_out_iorq_callback(DEVCB_##_devcb);


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


// ======================> z80dma_device

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

	template <class Object> devcb_base &set_out_busreq_callback(Object &&cb) { return m_out_busreq_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_int_callback(Object &&cb) { return m_out_int_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_bao_callback(Object &&cb) { return m_out_bao_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_in_mreq_callback(Object &&cb) { return m_in_mreq_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_mreq_callback(Object &&cb) { return m_out_mreq_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_in_iorq_callback(Object &&cb) { return m_in_iorq_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_iorq_callback(Object &&cb) { return m_out_iorq_cb.set_callback(std::forward<Object>(cb)); }

	uint8_t read();
	void write(uint8_t data);
	DECLARE_READ8_MEMBER( bus_r ) { return read(); }
	DECLARE_WRITE8_MEMBER( bus_w ) { write(data); }

	DECLARE_WRITE_LINE_MEMBER(rdy_w);
	DECLARE_WRITE_LINE_MEMBER(wait_w);
	DECLARE_WRITE_LINE_MEMBER(bai_w);

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

	// device_z80daisy_interface overrides
	virtual int z80daisy_irq_state() override;
	virtual int z80daisy_irq_ack() override;
	virtual void z80daisy_irq_reti() override;

	// internal helpers
	int is_ready();
	void interrupt_check();
	void trigger_interrupt(int level);
	void do_read();
	int do_write();
	void do_transfer_write();
	void do_search();

	TIMER_CALLBACK_MEMBER(timerproc);

	void update_status();

	TIMER_CALLBACK_MEMBER(rdy_write_callback);

	// internal state
	devcb_write_line   m_out_busreq_cb;
	devcb_write_line   m_out_int_cb;
	devcb_write_line   m_out_bao_cb;
	devcb_read8        m_in_mreq_cb;
	devcb_write8       m_out_mreq_cb;
	devcb_read8        m_in_iorq_cb;
	devcb_write8       m_out_iorq_cb;

	emu_timer *m_timer;

	uint16_t  m_regs[(6<<3)+1+1];
	uint8_t   m_num_follow;
	uint8_t   m_cur_follow;
	uint8_t   m_regs_follow[5];
	uint8_t   m_read_num_follow;
	uint8_t   m_read_cur_follow;
	uint8_t   m_read_regs_follow[7];
	uint8_t   m_status;
	uint8_t   m_dma_enabled;

	uint16_t m_addressA;
	uint16_t m_addressB;
	uint16_t m_count;

	int m_rdy;
	int m_force_ready;
	uint8_t m_reset_pointer;

	bool m_is_read;
	uint8_t m_cur_cycle;
	uint8_t m_latch;

	// interrupts
	int m_ip;                   // interrupt pending
	int m_ius;                  // interrupt under service
	uint8_t m_vector;             // interrupt vector
};


// device type definition
DECLARE_DEVICE_TYPE(Z80DMA, z80dma_device)

#endif // MAME_MACHINE_Z80DMA_H