OSDN Git Service

[VM][FMTOWNS][DMAC] Work with FM-Towns.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / dmac.cpp
1
2 #include "./dmac.h"
3 #include "debugger.h"
4
5 namespace FMTOWNS {
6 void TOWNS_DMAC::initialize()
7 {
8         UPD71071::initialize();
9 }
10
11 void TOWNS_DMAC::reset()
12 {
13         UPD71071::reset();
14         dma_wrap_reg = 0xff;
15 //      dma_wrap_reg = 0x00;
16         dma_addr_mask = 0xffffffff; // OK?
17 //      dma_addr_mask = 0x000fffff; // OK?
18 //      b16 = 2; // Fixed 16bit.
19 }
20 #if 0
21 void TOWNS_DMAC::write_io16(uint32_t addr, uint32_t data)
22 {
23         pair32_t _d, _bd;
24 //      out_debug_log(_T("OUT16 %04X,%04X"), addr & 0xffff, data & 0xffff);
25 //      if(b16 != 0) {
26         switch(addr & 0x0e) {
27         case 0x06:
28                 if(base == 0) {
29                         _d.d = dma[selch].areg;
30                         _d.w.h = data;
31                         dma[selch].areg = _d.d;
32                 }
33                 _d.d = dma[selch].bareg;
34                 _d.w.h = data;
35                 dma[selch].bareg = _d.d;
36                 return;
37                 break;
38 #if 0
39         case 0x08:
40                 if((data & 0x04) != (cmd & 0x04)) {
41                         if((data & 0x04) == 0) {
42                                 out_debug_log(_T("START TRANSFER:CH=%d CMD=%04X -> %04X AREG=%08X BAREG=%08X CREG=%04X BCREG=%04X"),
43                                                           selch,
44                                                           cmd, data & 0xffff,
45                                                           dma[selch].areg, dma[selch].bareg,
46                                                           dma[selch].creg, dma[selch].bcreg
47                                         );
48                         } else {
49                                 out_debug_log(_T("CLEAR TRANSFER:CH=%d CMD=%04X -> %04X AREG=%08X BAREG=%08X CREG=%04X BCREG=%04X"),
50                                                           selch,
51                                                           cmd, data & 0xffff,
52                                                           dma[selch].areg, dma[selch].bareg,
53                                                           dma[selch].creg, dma[selch].bcreg
54                                         );
55                         }
56                 }
57                 break;
58 #endif
59         default:
60                 break;
61         }
62         UPD71071::write_io16(addr, data);
63 }
64 #endif
65
66 void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data)
67 {
68 //      if((addr & 0x0f) == 0x0c) out_debug_log("WRITE REG: %08X %08X", addr, data);
69 //      out_debug_log("WRITE REG: %04X %02X", addr, data);
70         uint naddr;
71         pair32_t _d;
72         pair32_t _bd;
73         switch(addr & 0x0f) {
74         case 0x00:
75 //              out_debug_log(_T("RESET REG(00h) to %02X"), data);
76                 break;
77         case 0x07:
78                 dma[selch].bareg = manipulate_a_byte_from_dword_le(dma[selch].bareg, 3, data);
79                 if(base == 0) {
80                         dma[selch].areg = manipulate_a_byte_from_dword_le(dma[selch].areg, 3, data);
81                 }
82                 return;
83                 break;
84 #if 0 /* For Debugging */
85         case 0x08:
86                 if((data & 0x04) != (cmd & 0x04)) {
87                         if((data & 0x04) == 0) {
88                                 out_debug_log(_T("START TRANSFER:CH=%d CMD=%04X -> %04X AREG=%08X BAREG=%08X CREG=%04X BCREG=%04X"),
89                                                           selch,
90                                                           cmd, (cmd & 0xff00) | (data & 0x00ff),
91                                                           dma[selch].areg, dma[selch].bareg,
92                                                           dma[selch].creg, dma[selch].bcreg
93                                         );
94                         } else {
95                                 out_debug_log(_T("CLEAR TRANSFER:CH=%d CMD=%04X -> %04X  AREG=%08X BAREG=%08X CREG=%04X BCREG=%04X"),
96                                                           selch,
97                                                           cmd, (cmd & 0xff00) | (data & 0x00ff),
98                                                           dma[selch].areg, dma[selch].bareg,
99                                                           dma[selch].creg, dma[selch].bcreg
100                                         );
101                         }
102                 }
103                 break;
104         case 0x0a:
105 //              if((selch == 3)) {
106 //                      out_debug_log(_T("SET MODE[%d] to %02X"), selch, data);
107 //              }
108                 break;
109         case 0x0e:
110                 if(((data | req) & 0x08) != 0) {
111                         //      out_debug_log(_T("TRANSFER ENABLE@REG0E DATA=%02X"), data);
112                 }
113                 break;
114 #endif
115         default:
116                 break;
117         }
118         UPD71071::write_io8(addr, data);
119 }
120 #if 0
121 uint32_t TOWNS_DMAC::read_io16(uint32_t addr)
122 {
123         switch(addr & 0x0e) {
124         case 0x06:
125                 if(base == 0) {
126                         return ((dma[selch].areg >> 16) & 0xffff);
127                 } else {
128                         return ((dma[selch].bareg >> 16) & 0xffff);
129                 }
130                 break;
131         default:
132 //                      return read_io8(addr & 0x0e);
133                 break;
134         }
135         return UPD71071::read_io16(addr);
136 }
137 #endif
138
139 uint32_t TOWNS_DMAC::read_io8(uint32_t addr)
140 {
141         uint32_t val;
142         pair32_t _d;
143         switch(addr & 0x0f) {
144         case 0x07:
145                 if(base == 0) {
146                         _d.d = dma[selch].areg;
147                 } else {
148                         _d.d = dma[selch].bareg;
149                 }
150                 return (uint32_t)(_d.b.h3);
151                 break;
152         }
153         return UPD71071::read_io8(addr);
154 }
155
156 void TOWNS_DMAC::do_dma_inc_dec_ptr_8bit(int c)
157 {
158         // Note: FM-Towns may extend to 32bit.
159         int32_t incdec = ((dma[c].mode & 0x20) == 0) ? 1 : -1;
160         uint32_t addr = dma[c].areg;
161         uint32_t high_a = addr & 0xff000000;
162         __LIKELY_IF(dma_wrap_reg != 0) {
163                 addr = (addr + incdec) & 0x00ffffff;
164                 addr = addr | high_a;
165         } else {
166                 addr = (addr + incdec) & 0xffffffff;
167         }
168         dma[c].areg = addr;
169 }
170
171 void TOWNS_DMAC::do_dma_inc_dec_ptr_16bit(int c)
172 {
173         // Note: FM-Towns may extend to 32bit.
174         int32_t incdec = ((dma[c].mode & 0x20) == 0) ? 2 : -2;
175         uint32_t addr = dma[c].areg;
176         uint32_t high_a = addr & 0xff000000;
177         __LIKELY_IF(dma_wrap_reg != 0) {
178                 addr = (addr + incdec) & 0x00ffffff;
179                 addr = addr | high_a;
180         } else {
181                 addr = (addr + incdec) & 0xffffffff;
182         }
183         dma[c].areg = addr;
184 }
185
186 #if 0 /* For Debug */
187 bool TOWNS_DMAC::do_dma_epilogue(int c)
188 {
189         if((dma[c].creg == 0) || ((dma[c].endreq) && !(dma[c].end) && ((dma[c].mode & 0xc0) != 0x40))) {  // OK?
190                 // TC
191                 bool is_tc = false;
192                 if((dma[c].end) || (dma[c].endreq)) is_tc = true;
193                 // TC
194                 if(dma[c].bcreg < (dma[c].creg - 1)) {
195                         is_tc = true;
196                 }
197                 if(is_tc) {
198         #if 0
199                         out_debug_log(_T("TRANSFER COMPLETED:CH=%d  AREG=%08X BAREG=%08X CREG=%08X BCREG=%08X"),
200                                                   c,
201                                                   (dma[c].areg & 0xffffffff) ,
202                                                   (dma[c].bareg & 0xffffffff) ,
203                                                   dma[c].creg & 0x00ffffff,
204                                                   dma[c].bcreg & 0x00ffffff
205                                 );
206         #endif
207                 }
208         }
209         return UPD71071::do_dma_epilogue(c);
210 }
211 #endif
212
213 uint32_t TOWNS_DMAC::read_signal(int id)
214 {
215         if(id == SIG_TOWNS_DMAC_WRAP_REG) {
216                 return dma_wrap_reg;
217         } else if(id == SIG_TOWNS_DMAC_ADDR_MASK) {
218                 return dma_addr_mask;
219         }
220         return UPD71071::read_signal(id);
221 }
222
223 void TOWNS_DMAC::write_signal(int id, uint32_t data, uint32_t _mask)
224 {
225         if(id == SIG_TOWNS_DMAC_WRAP_REG) {
226                 dma_wrap_reg = data;
227 //              this->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, data, mask);
228         } else if(id == SIG_TOWNS_DMAC_ADDR_MASK) {
229                 // From eFMR50 / memory.cpp / update_dma_addr_mask()
230                 //dma_addr_mask = data;
231         } else {
232                 // Fallthrough.
233 //              if(id == SIG_UPD71071_CH1) {
234 //                      out_debug_log(_T("DRQ from SCSI %02X %02X"), data, mask);
235 //              }
236                 UPD71071::write_signal(id, data, _mask);
237         }
238 }
239
240
241 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
242 bool TOWNS_DMAC::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
243 {
244         static const _TCHAR *dir[4] = {
245                 _T("VERIFY"), _T("I/O->MEM"), _T("MEM->I/O"), _T("INVALID")
246         };
247         if(buffer == NULL) return false;
248         _TCHAR sbuf[4][512] = {0};
249         for(int i = 0; i < 4; i++) {
250                 my_stprintf_s(sbuf[i], 512,
251                   _T("CH%d AREG=%08X CREG=%04X BAREG=%08X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n"),
252                                           i,
253                                           dma[i].areg,
254                                           dma[i].creg,
255                                           dma[i].bareg,
256                                           dma[i].bcreg,
257                                           ((req | sreq) >> 0) & 1,
258                                           (mask >> 0) & 1,
259                                           dma[i].mode,
260                                           dir[(dma[i].mode >> 2) & 3]
261                         );
262         }
263         {
264                 my_stprintf_s(buffer, buffer_len,
265                                           _T("16Bit=%s ADDR_MASK=%08X ADDR_WRAP=%02X \n")
266                                           _T("SELECT CH=%d BASE=%02X REQ=%02X SREQ=%02X MASK=%02X TC=%02X ")
267                                           _T("CMD=%04X TMP=%04X\n")
268                                           _T("%s")
269                                           _T("%s")
270                                           _T("%s")
271                                           _T("%s"),
272                                           (b16 != 0) ? _T("YES") : _T("NO"), dma_addr_mask, dma_wrap_reg,
273                                           selch, base, req, sreq, mask, tc,
274                                           cmd, tmp,
275                                           sbuf[0],
276                                           sbuf[1],
277                                           sbuf[2],
278                                           sbuf[3]);
279                 return true;
280         }
281         return false;
282 }
283
284 #define STATE_VERSION   3
285
286 bool TOWNS_DMAC::process_state(FILEIO *state_fio, bool loading)
287 {
288         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
289                 return false;
290         }
291         if(!state_fio->StateCheckInt32(this_device_id)) {
292                 return false;
293         }
294         if(!(UPD71071::process_state(state_fio, loading))) {
295                 return false;
296         }
297         state_fio->StateValue(dma_wrap_reg);
298         state_fio->StateValue(dma_addr_mask);
299
300         return true;
301 }
302 }