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
|
// license: GPL-2.0+
// copyright-holders: Dirk Best
/***************************************************************************
DMAC
DMA controller used in Amiga systems
***************************************************************************/
#ifndef MAME_MACHINE_DMAC_H
#define MAME_MACHINE_DMAC_H
#pragma once
#include "autoconfig.h"
class amiga_dmac_device : public device_t, public amiga_autoconfig
{
public:
// callbacks
auto cfgout_cb() { return m_cfgout_cb.bind(); }
auto int_cb() { return m_int_cb.bind(); }
auto css_read_cb() { return m_css_read_cb.bind(); }
auto css_write_cb() { return m_css_write_cb.bind(); }
auto csx0_read_cb() { return m_csx0_read_cb.bind(); }
auto csx0_write_cb() { return m_csx0_write_cb.bind(); }
auto csx0_a4_read_cb() { return m_csx0_a4_read_cb.bind(); }
auto csx0_a4_write_cb() { return m_csx0_a4_write_cb.bind(); }
auto csx1_read_cb() { return m_csx1_read_cb.bind(); }
auto csx1_write_cb() { return m_csx1_write_cb.bind(); }
auto sdack_read_cb() { return m_sdack_read_cb.bind(); }
auto sdack_write_cb() { return m_sdack_write_cb.bind(); }
auto xdack_read_cb() { return m_xdack_read_cb.bind(); }
auto xdack_write_cb() { return m_xdack_write_cb.bind(); }
void set_address_space(address_space *space) { m_space = space; }
void set_rom(const char *region) { m_rom.set_tag(region); }
void set_ram(uint16_t *ram) { m_ram = ram; }
// input lines
void configin_w(int state);
void ramsz_w(int state);
void rst_w(int state);
void intx_w(int state);
void sdreq_w(int state);
void xdreq_w(int state);
protected:
amiga_dmac_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool rev1);
virtual void device_start() override ATTR_COLD;
// amiga_autoconfig overrides
virtual void autoconfig_base_address(offs_t address) override;
private:
void map(address_map &map) ATTR_COLD;
TIMER_CALLBACK_MEMBER(update_dma);
void update_interrupts();
void start_dma();
void stop_dma();
uint16_t autoconfig_r(offs_t offset, uint16_t mem_mask);
void autoconfig_w(offs_t offset, uint16_t data, uint16_t mem_mask);
uint16_t istr_r(offs_t offset, uint16_t mem_mask);
uint16_t cntr_r(offs_t offset, uint16_t mem_mask);
void cntr_w(offs_t offset, uint16_t data,uint16_t mem_mask);
void wtc_hi_w(offs_t offset, uint16_t data,uint16_t mem_mask);
void wtc_lo_w(offs_t offset, uint16_t data,uint16_t mem_mask);
void acr_hi_w(offs_t offset, uint16_t data,uint16_t mem_mask);
void acr_lo_w(offs_t offset, uint16_t data,uint16_t mem_mask);
void dawr_w(offs_t offset, uint16_t data,uint16_t mem_mask);
uint8_t css_r(offs_t offset);
void css_w(offs_t offset, uint8_t data);
uint8_t csx0_r(offs_t offset);
void csx0_w(offs_t offset, uint8_t data);
uint8_t csx0_a4_r(offs_t offset);
void csx0_a4_w(offs_t offset, uint8_t data);
uint8_t csx1_r(offs_t offset);
void csx1_w(offs_t offset, uint8_t data);
// strobe register
void st_dma();
uint16_t st_dma_r(offs_t offset, uint16_t mem_mask) { st_dma(); return 0; };
void st_dma_w(offs_t offset, uint16_t data, uint16_t mem_mask) { st_dma(); };
void sp_dma();
uint16_t sp_dma_r(offs_t offset, uint16_t mem_mask) { sp_dma(); return 0; };
void sp_dma_w(offs_t offset, uint16_t data, uint16_t mem_mask) { sp_dma(); };
void cint();
uint16_t cint_r(offs_t offset, uint16_t mem_mask) { cint(); return 0; };
void cint_w(offs_t offset, uint16_t data, uint16_t mem_mask) { cint(); };
void flush();
uint16_t flush_r(offs_t offset, uint16_t mem_mask) { flush(); return 0; };
void flush_w(offs_t offset, uint16_t data, uint16_t mem_mask) { flush(); };
// control register definitions
static constexpr uint16_t CNTR_TCEN = 0x80; // terminal count enable
static constexpr uint16_t CNTR_PREST = 0x40; // peripheral reset
static constexpr uint16_t CNTR_PDMD = 0x20; // peripheral device mode select (1=scsi/0=xt)
static constexpr uint16_t CNTR_INTEN = 0x10; // interrupt enable
static constexpr uint16_t CNTR_DDIR = 0x08; // device direction (1=from host to peripheral)
// interrupt status register definitions
static constexpr uint16_t ISTR_INT_F = 0x80; // interrupt follow
static constexpr uint16_t ISTR_INTS = 0x40; // scsi peripheral interrupt
static constexpr uint16_t ISTR_E_INT = 0x20; // end-of-process interrupt
static constexpr uint16_t ISTR_INT_P = 0x10; // interrupt pending
static constexpr uint16_t ISTR_UE_INT = 0x08; // fifo underrun interrupt
static constexpr uint16_t ISTR_OE_INT = 0x04; // fifo overflow interrupt
static constexpr uint16_t ISTR_FF_FLG = 0x02; // fifo full flag
static constexpr uint16_t ISTR_FE_FLG = 0x01; // fifo empty flag
static constexpr uint16_t ISTR_INT_MASK = 0x6c;
// callbacks
devcb_write_line m_cfgout_cb;
devcb_write_line m_int_cb;
devcb_read8 m_css_read_cb;
devcb_write8 m_css_write_cb;
devcb_read8 m_csx0_read_cb;
devcb_write8 m_csx0_write_cb;
devcb_read8 m_csx0_a4_read_cb;
devcb_write8 m_csx0_a4_write_cb;
devcb_read8 m_csx1_read_cb;
devcb_write8 m_csx1_write_cb;
devcb_read8 m_sdack_read_cb;
devcb_write8 m_sdack_write_cb;
devcb_read8 m_xdack_read_cb;
devcb_write8 m_xdack_write_cb;
optional_memory_region m_rom;
address_space *m_space;
uint16_t *m_ram;
int m_ram_size;
bool m_rev1;
// internal registers
uint16_t m_cntr; // control register
uint16_t m_istr; // interrupt status register
uint32_t m_wtc; // word transfer count
uint32_t m_acr; // address control register
// state of input lines
bool m_intx;
bool m_sdreq;
bool m_xdreq;
emu_timer *m_dma_timer;
// autoconfig state
bool m_autoconfig_dmac_done;
bool m_autoconfig_ram_done;
offs_t m_dmac_address;
offs_t m_ram_address;
};
class amiga_dmac_rev1_device : public amiga_dmac_device
{
public:
amiga_dmac_rev1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
class amiga_dmac_rev2_device : public amiga_dmac_device
{
public:
amiga_dmac_rev2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
// device type declaration
DECLARE_DEVICE_TYPE(AMIGA_DMAC_REV1, amiga_dmac_rev1_device)
DECLARE_DEVICE_TYPE(AMIGA_DMAC_REV2, amiga_dmac_rev2_device)
#endif // MAME_MACHINE_DMAC_H
|