1 // license:BSD-3-Clause
2 // copyright-holders:Patrick Mackinlay
3 
4 #ifndef MAME_MACHINE_DMAC_0448_H
5 #define MAME_MACHINE_DMAC_0448_H
6 
7 #pragma once
8 
9 class dmac_0448_device : public device_t
10 {
11 public:
12 	dmac_0448_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
13 
14 	// configuration
set_bus(T && tag,int spacenum)15 	template <typename T> void set_bus(T &&tag, int spacenum) { m_bus.set_tag(std::forward<T>(tag), spacenum); }
out_int_cb()16 	auto out_int_cb() { return m_out_int.bind(); }
dma_r_cb()17 	template <unsigned Channel> auto dma_r_cb() { return m_dma_r[Channel].bind(); }
dma_w_cb()18 	template <unsigned Channel> auto dma_w_cb() { return m_dma_w[Channel].bind(); }
19 
20 	// line handlers
irq(int state)21 	template <unsigned IRQ> void irq(int state) { set_irq_line(IRQ, state); }
drq(int state)22 	template <unsigned DRQ> void drq(int state) { set_drq_line(DRQ, state); }
23 
24 	void map(address_map &map);
25 
26 protected:
27 	// device_t overrides
28 	virtual void device_start() override;
29 	virtual void device_reset() override;
30 
31 	void set_irq_line(int number, int state);
32 	void set_drq_line(int channel, int state);
33 
cstat_r()34 	u8 cstat_r() { return m_channel[m_gsel].cstat; }
ctrcl_r()35 	u8 ctrcl_r() { return u8(m_channel[m_gsel].ctrc >> 0); }
ctrcm_r()36 	u8 ctrcm_r() { return u8(m_channel[m_gsel].ctrc >> 8); }
ctrch_r()37 	u8 ctrch_r() { return u8(m_channel[m_gsel].ctrc >> 16); }
ctag_r()38 	u8 ctag_r() { return m_channel[m_gsel].ctag; }
cwid_r()39 	u8 cwid_r() { return m_channel[m_gsel].cwid; }
cofsl_r()40 	u8 cofsl_r() { return u8(m_channel[m_gsel].cofs >> 0); }
cofsh_r()41 	u8 cofsh_r() { return u8(m_channel[m_gsel].cofs >> 8); }
cmap_r()42 	u16 cmap_r() { return m_channel[m_gsel].cmap[m_channel[m_gsel].ctag]; }
gstat_r()43 	u8 gstat_r() { return m_gstat; }
44 
45 	void cctl_w(u8 data);
ctrcl_w(u8 data)46 	void ctrcl_w(u8 data) { m_channel[m_gsel].ctrc = (m_channel[m_gsel].ctrc & 0xffff00U) | (u32(data) << 0); }
ctrcm_w(u8 data)47 	void ctrcm_w(u8 data) { m_channel[m_gsel].ctrc = (m_channel[m_gsel].ctrc & 0xff00ffU) | (u32(data) << 8); }
ctrch_w(u8 data)48 	void ctrch_w(u8 data) { m_channel[m_gsel].ctrc = (m_channel[m_gsel].ctrc & 0x00ffffU) | (u32(data) << 16); }
ctag_w(u8 data)49 	void ctag_w(u8 data) { m_channel[m_gsel].ctag = data; }
cwid_w(u8 data)50 	void cwid_w(u8 data) { m_channel[m_gsel].cwid = data; }
cofsl_w(u8 data)51 	void cofsl_w(u8 data) { m_channel[m_gsel].cofs = (m_channel[m_gsel].cofs & 0xff00U) | (u16(data) << 0); }
cofsh_w(u8 data)52 	void cofsh_w(u8 data) { m_channel[m_gsel].cofs = (m_channel[m_gsel].cofs & 0x00ffU) | (u16(data & 0x0f) << 8); }
cmap_w(offs_t offset,u16 data,u16 mem_mask)53 	void cmap_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_channel[m_gsel].cmap[m_channel[m_gsel].ctag]); }
gsel_w(u8 data)54 	void gsel_w(u8 data) { m_gsel = data; }
55 
56 	void irq_check(void *ptr = nullptr, s32 param = 0);
57 	void dma_check(void *ptr = nullptr, s32 param = 0);
58 
59 	required_address_space m_bus;
60 
61 	devcb_write_line m_out_int;
62 	devcb_read8::array<4> m_dma_r;
63 	devcb_write8::array<4> m_dma_w;
64 
65 	emu_timer *m_irq_check;
66 	emu_timer *m_dma_check;
67 
68 	enum cstat_mask : u8
69 	{
70 		CS_ENABLE = 0x01, // channel enable
71 		CS_MODE   = 0x02, // transfer to memory
72 		CS_RESET  = 0x04, // reset channel
73 		CS_ZINTEN = 0x08, // terminal count interrupt?
74 		CS_APAD   = 0x10, // auto pad
75 		CS_AFIX   = 0x20,
76 		CS_A28    = 0x40,
77 		CS_TCZ    = 0x80, // transfer count zero?
78 	};
79 
80 	struct dma_channel
81 	{
82 		u8 cstat; // channel status
83 		u8 cctl;  // channel control
84 		u32 ctrc; // channel counter
85 		u8 ctag;  // channel tag
86 		u8 cwid;  // channel width
87 		u16 cofs; // channel offset
88 		u16 cmap[256];
89 	}
90 	m_channel[4];
91 	u8 m_gsel;  // channel select
92 	u8 m_gstat; // general status
93 
94 	bool m_out_int_state;
95 };
96 
97 DECLARE_DEVICE_TYPE(DMAC_0448, dmac_0448_device)
98 
99 #endif // MAME_MACHINE_DMAC_0448_H
100