1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /***************************************************************************
4 
5     AMD AM9517A/8237A Multimode DMA Controller emulation
6 
7 ****************************************************************************
8                             _____   _____
9                   _IOR   1 |*    \_/     | 40  A7
10                   _IOW   2 |             | 39  A6
11                  _MEMR   3 |             | 38  A5
12                  _MEMW   4 |             | 37  A4
13                      *   5 |             | 36  _EOP
14                  READY   6 |             | 35  A3
15                   HACK   7 |             | 34  A2
16                  ADSTB   8 |             | 33  A1
17                    AEN   9 |             | 32  A0
18                   HREQ  10 |   AM9517A   | 31  Vcc
19                    _CS  11 |    8237A    | 30  DB0
20                    CLK  12 |             | 29  DB1
21                  RESET  13 |             | 28  DB2
22                  DACK2  14 |             | 27  DB3
23                  DACK3  15 |             | 26  DB4
24                  DREQ3  16 |             | 25  DACK0
25                  DREQ2  17 |             | 24  DACK1
26                  DREQ1  18 |             | 23  DB5
27                  DREQ0  19 |             | 22  DB6
28                    Vss  20 |_____________| 21  DB7
29 
30 ***************************************************************************/
31 
32 #ifndef MAME_MACHINE_AM9517_H
33 #define MAME_MACHINE_AM9517_H
34 
35 #pragma once
36 
37 
38 
39 /***************************************************************************
40     TYPE DEFINITIONS
41 ***************************************************************************/
42 
43 // ======================> am9517a_device
44 
45 class am9517a_device :  public device_t,
46 						public device_execute_interface
47 {
48 	friend class pcxport_dmac_device;
49 
50 public:
51 	// construction/destruction
52 	am9517a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
53 
out_hreq_callback()54 	auto out_hreq_callback() { return m_out_hreq_cb.bind(); }
out_eop_callback()55 	auto out_eop_callback() { return m_out_eop_cb.bind(); }
56 
in_memr_callback()57 	auto in_memr_callback() { return m_in_memr_cb.bind(); }
out_memw_callback()58 	auto out_memw_callback() { return m_out_memw_cb.bind(); }
59 
in_ior_callback()60 	template <unsigned C> auto in_ior_callback() { return m_in_ior_cb[C].bind(); }
out_iow_callback()61 	template <unsigned C> auto out_iow_callback() { return m_out_iow_cb[C].bind(); }
out_dack_callback()62 	template <unsigned C> auto out_dack_callback() { return m_out_dack_cb[C].bind(); }
63 
64 	virtual uint8_t read(offs_t offset);
65 	virtual void write(offs_t offset, uint8_t data);
66 
67 	DECLARE_WRITE_LINE_MEMBER( hack_w );
68 	DECLARE_WRITE_LINE_MEMBER( ready_w );
69 	DECLARE_WRITE_LINE_MEMBER( eop_w );
70 
DECLARE_WRITE_LINE_MEMBER(dreq_w)71 	template <unsigned C> DECLARE_WRITE_LINE_MEMBER( dreq_w ) { dma_request(C, state); }
72 	DECLARE_WRITE_LINE_MEMBER( dreq0_w );
73 	DECLARE_WRITE_LINE_MEMBER( dreq1_w );
74 	DECLARE_WRITE_LINE_MEMBER( dreq2_w );
75 	DECLARE_WRITE_LINE_MEMBER( dreq3_w );
76 
77 protected:
78 	am9517a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
79 
80 	// device-level overrides
81 	virtual void device_start() override;
82 	virtual void device_reset() override;
83 	virtual void execute_run() override;
84 
85 	virtual void end_of_process();
86 
87 	virtual void dma_read();
88 	virtual void dma_write();
89 
transfer_size(int const channel)90 	virtual int transfer_size(int const channel) const { return 1; }
91 
92 	int m_icount;
93 	uint32_t m_address_mask;
94 
95 	struct
96 	{
97 		uint32_t m_address;
98 		uint32_t m_count;
99 		uint32_t m_base_address;
100 		uint32_t m_base_count;
101 		uint8_t m_mode;
102 	} m_channel[4];
103 
104 	int m_msb;
105 	int m_hreq;
106 	int m_hack;
107 	int m_ready;
108 	int m_eop;
109 	int m_state;
110 	int m_current_channel;
111 	int m_last_channel;
112 	uint8_t m_command;
113 	uint8_t m_mask;
114 	uint8_t m_status;
115 	uint16_t m_temp;
116 	uint8_t m_request;
117 
118 private:
119 	void dma_request(int channel, int state);
120 	inline bool is_request_active(int channel);
121 	inline bool is_software_request_active(int channel);
122 	inline void set_hreq(int state);
123 	inline void set_dack();
124 	inline void set_eop(int state);
125 	inline int get_state1(bool msb_changed);
126 	inline void dma_advance();
127 
128 	devcb_write_line   m_out_hreq_cb;
129 	devcb_write_line   m_out_eop_cb;
130 
131 	devcb_read8        m_in_memr_cb;
132 	devcb_write8       m_out_memw_cb;
133 
134 	devcb_read8::array<4> m_in_ior_cb;
135 	devcb_write8::array<4> m_out_iow_cb;
136 	devcb_write_line::array<4> m_out_dack_cb;
137 };
138 
139 
140 class v5x_dmau_device : public am9517a_device
141 {
142 public:
143 	// construction/destruction
144 	v5x_dmau_device(const machine_config &mconfig,  const char *tag, device_t *owner, uint32_t clock);
145 
in_mem16r_callback()146 	auto in_mem16r_callback() { return m_in_mem16r_cb.bind(); }
out_mem16w_callback()147 	auto out_mem16w_callback() { return m_out_mem16w_cb.bind(); }
148 
in_io16r_callback()149 	template <unsigned C> auto in_io16r_callback() { return m_in_io16r_cb[C].bind(); }
out_io16w_callback()150 	template <unsigned C> auto out_io16w_callback() { return m_out_io16w_cb[C].bind(); }
151 
152 	virtual uint8_t read(offs_t offset) override;
153 	virtual void write(offs_t offset, uint8_t data) override;
154 
155 protected:
156 	// device-level overrides
157 	virtual void device_start() override;
158 	virtual void device_reset() override;
159 
160 	virtual void dma_read() override;
161 	virtual void dma_write() override;
162 
transfer_size(int const channel)163 	virtual int transfer_size(int const channel) const override { return (m_channel[channel].m_mode & 0x1) ? 2 : 1; }
164 
165 	// 16 bit transfer callbacks
166 	devcb_read16 m_in_mem16r_cb;
167 	devcb_write16 m_out_mem16w_cb;
168 	devcb_read16::array<4> m_in_io16r_cb;
169 	devcb_write16::array<4> m_out_io16w_cb;
170 
171 	int m_selected_channel;
172 	int m_base;
173 	uint8_t m_command_high;
174 };
175 
176 
177 class pcxport_dmac_device : public am9517a_device
178 {
179 public:
180 	// construction/destruction
181 	pcxport_dmac_device(const machine_config &mconfig,  const char *tag, device_t *owner, uint32_t clock);
182 
183 protected:
184 	virtual void device_reset() override;
185 
186 	virtual void end_of_process() override;
187 };
188 
189 class eisa_dma_device : public am9517a_device
190 {
191 public:
192 	eisa_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
193 
get_address_page()194 	template <unsigned Channel> u8 get_address_page() { return m_channel[Channel].m_address >> 16; }
set_address_page(u8 data)195 	template <unsigned Channel> void set_address_page(u8 data)
196 	{
197 		m_channel[Channel].m_base_address = (m_channel[Channel].m_base_address & 0x0000ffffU) | (u32(data) << 16);
198 		m_channel[Channel].m_address = (m_channel[Channel].m_address & 0x0000ffffU) | (u32(data) << 16);
199 	}
200 
get_address_page_high()201 	template <unsigned Channel> u8 get_address_page_high() { return m_channel[Channel].m_address >> 24; }
set_address_page_high(u8 data)202 	template <unsigned Channel> void set_address_page_high(u8 data)
203 	{
204 		m_channel[Channel].m_base_address = (m_channel[Channel].m_base_address & 0x00ffffffU) | (u32(data) << 24);
205 		m_channel[Channel].m_address = (m_channel[Channel].m_address & 0x00ffffffU) | (u32(data) << 24);
206 	}
207 
get_count_high()208 	template <unsigned Channel> u8 get_count_high() { return m_channel[Channel].m_count >> 16; }
set_count_high(u8 data)209 	template <unsigned Channel> void set_count_high(u8 data)
210 	{
211 		m_channel[Channel].m_base_count = (m_channel[Channel].m_base_count & 0x0000ffffU) | (u32(data) << 16);
212 		m_channel[Channel].m_count = (m_channel[Channel].m_count & 0x0000ffffU) | (u32(data) << 16);
213 	}
214 
set_ext_mode(u8 data)215 	void set_ext_mode(u8 data)
216 	{
217 		m_ext_mode[data & 3] = data;
218 	}
219 
get_stop()220 	template <unsigned Channel> u32 get_stop() { return m_stop[Channel]; }
set_stop(offs_t offset,u32 data,u32 mem_mask)221 	template <unsigned Channel> void set_stop(offs_t offset, u32 data, u32 mem_mask)
222 	{
223 		mem_mask &= 0x00fffffcU;
224 		COMBINE_DATA(&m_stop[Channel]);
225 	}
226 
227 protected:
228 	virtual void device_start() override;
229 
230 private:
231 	u32 m_stop[4];
232 	u8 m_ext_mode[4];
233 };
234 
235 // device type definition
236 DECLARE_DEVICE_TYPE(AM9517A,      am9517a_device)
237 DECLARE_DEVICE_TYPE(V5X_DMAU,     v5x_dmau_device)
238 DECLARE_DEVICE_TYPE(PCXPORT_DMAC, pcxport_dmac_device)
239 DECLARE_DEVICE_TYPE(EISA_DMA,     eisa_dma_device)
240 
241 #endif // MAME_MACHINE_AM9517_H
242