6 void TOWNS_DMAC::initialize()
8 UPD71071::initialize();
11 void TOWNS_DMAC::reset()
15 // dma_wrap_reg = 0x00;
16 dma_addr_mask = 0xffffffff; // OK?
17 // dma_addr_mask = 0x000fffff; // OK?
18 for(int i = 0; i < 4; i++) {
22 // b16 = 2; // Fixed 16bit.
25 void TOWNS_DMAC::write_io16(uint32_t addr, uint32_t data)
28 // out_debug_log(_T("OUT16 %04X,%04X"), addr & 0xffff, data & 0xffff);
33 creg_set[selch] = true;
35 bcreg_set[selch] = true;
39 _d.d = dma[selch].areg;
41 dma[selch].areg = _d.d;
43 _d.d = dma[selch].bareg;
45 dma[selch].bareg = _d.d;
50 if((data & 0x04) != (cmd & 0x04)) {
51 if((data & 0x04) == 0) {
52 out_debug_log(_T("START TRANSFER:CH=%d CMD=%04X -> %04X AREG=%08X BAREG=%08X CREG=%04X BCREG=%04X"),
55 dma[selch].areg, dma[selch].bareg,
56 dma[selch].creg, dma[selch].bcreg
59 out_debug_log(_T("CLEAR TRANSFER:CH=%d CMD=%04X -> %04X AREG=%08X BAREG=%08X CREG=%04X BCREG=%04X"),
62 dma[selch].areg, dma[selch].bareg,
63 dma[selch].creg, dma[selch].bcreg
70 UPD71071::write_io16(addr, data);
73 void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data)
75 // if((addr & 0x0f) == 0x0c) out_debug_log("WRITE REG: %08X %08X", addr, data);
76 // out_debug_log("WRITE REG: %04X %02X", addr, data);
82 // out_debug_log(_T("RESET REG(00h) to %02X"), data);
86 // Note: This is *temporaly* workaround for 16bit transfer mode with 8bit bus.
89 creg_set[selch] = true;
91 bcreg_set[selch] = true;
94 dma[selch].bareg = manipulate_a_byte_from_dword_le(dma[selch].bareg, 3, data);
96 dma[selch].areg = manipulate_a_byte_from_dword_le(dma[selch].areg, 3, data);
102 if((data & 0x04) != (cmd & 0x04)) {
103 if((data & 0x04) == 0) {
104 out_debug_log(_T("START TRANSFER:CH=%d CMD=%04X -> %04X AREG=%08X BAREG=%08X CREG=%04X BCREG=%04X"),
106 cmd, (cmd & 0xff00) | (data & 0x00ff),
107 dma[selch].areg, dma[selch].bareg,
108 dma[selch].creg, dma[selch].bcreg
111 out_debug_log(_T("CLEAR TRANSFER:CH=%d CMD=%04X -> %04X AREG=%08X BAREG=%08X CREG=%04X BCREG=%04X"),
113 cmd, (cmd & 0xff00) | (data & 0x00ff),
114 dma[selch].areg, dma[selch].bareg,
115 dma[selch].creg, dma[selch].bcreg
122 // if((selch == 3)) {
123 // out_debug_log(_T("SET MODE[%d] to %02X"), selch, data);
127 if(((data | req) & 0x08) != 0) {
128 // out_debug_log(_T("TRANSFER ENABLE@REG0E DATA=%02X"), data);
132 // Note: This is *temporaly* workaround for 16bit transfer mode with 8bit bus.
135 #if !defined(USE_QUEUED_SCSI_TRANSFER)
136 if((dma[selch].is_16bit) && !(inputs_ube[selch])) {
137 if(creg_set[selch]) {
138 dma[selch].creg <<= 1;
140 creg_set[selch] = false;
142 if(bcreg_set[selch]) {
143 dma[selch].bcreg <<= 1;
145 bcreg_set[selch] = false;
148 bcreg_set[selch] = false;
149 creg_set[selch] = false;
156 UPD71071::write_io8(addr, data);
159 uint32_t TOWNS_DMAC::read_io16(uint32_t addr)
161 switch(addr & 0x0e) {
164 return ((dma[selch].areg >> 16) & 0xffff);
166 return ((dma[selch].bareg >> 16) & 0xffff);
170 // return read_io8(addr & 0x0e);
173 return UPD71071::read_io16(addr);
176 uint32_t TOWNS_DMAC::read_io8(uint32_t addr)
180 switch(addr & 0x0f) {
183 _d.d = dma[selch].areg;
185 _d.d = dma[selch].bareg;
187 return (uint32_t)(_d.b.h3);
190 return UPD71071::read_io8(addr);
193 void TOWNS_DMAC::do_dma_inc_dec_ptr_8bit(int c)
195 // Note: FM-Towns may extend to 32bit.
196 __LIKELY_IF(dma_wrap_reg != 0) {
197 uint32_t high_a = dma[c].areg & 0xff000000;
198 if(dma[c].mode & 0x20) {
199 dma[c].areg = dma[c].areg - 1;
201 dma[c].areg = dma[c].areg + 1;
203 dma[c].areg = ((dma[c].areg & 0x00ffffff) | high_a) & dma_addr_mask;
205 if(dma[c].mode & 0x20) {
206 dma[c].areg = (dma[c].areg - 1) & dma_addr_mask;
208 dma[c].areg = (dma[c].areg + 1) & dma_addr_mask;
213 void TOWNS_DMAC::do_dma_inc_dec_ptr_16bit(int c)
215 // Note: FM-Towns may extend to 32bit.
216 __LIKELY_IF(dma_wrap_reg != 0) {
217 uint32_t high_a = dma[c].areg & 0xff000000;
218 if(dma[c].mode & 0x20) {
219 dma[c].areg = dma[c].areg - 2;
221 dma[c].areg = dma[c].areg + 2;
223 dma[c].areg = ((dma[c].areg & 0x00ffffff) | high_a) & dma_addr_mask;
225 if(dma[c].mode & 0x20) {
226 dma[c].areg = (dma[c].areg - 2) & dma_addr_mask;
228 dma[c].areg = (dma[c].areg + 2) & dma_addr_mask;
233 bool TOWNS_DMAC::do_dma_epilogue(int c)
235 if((dma[c].creg == 0) || ((dma[c].endreq) && !(dma[c].end) && ((dma[c].mode & 0xc0) != 0x40))) { // OK?
238 if((dma[c].end) || (dma[c].endreq)) is_tc = true;
240 if(dma[c].bcreg < (dma[c].creg - 1)) {
245 out_debug_log(_T("TRANSFER COMPLETED:CH=%d AREG=%08X BAREG=%08X CREG=%08X BCREG=%08X"),
247 (dma[c].areg & 0xffffffff) ,
248 (dma[c].bareg & 0xffffffff) ,
249 dma[c].creg & 0x00ffffff,
250 dma[c].bcreg & 0x00ffffff
255 return UPD71071::do_dma_epilogue(c);
258 uint32_t TOWNS_DMAC::read_signal(int id)
260 if(id == SIG_TOWNS_DMAC_WRAP_REG) {
262 } else if(id == SIG_TOWNS_DMAC_ADDR_MASK) {
263 return dma_addr_mask;
265 return UPD71071::read_signal(id);
268 void TOWNS_DMAC::write_signal(int id, uint32_t data, uint32_t _mask)
270 if(id == SIG_TOWNS_DMAC_WRAP_REG) {
272 // this->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, data, mask);
273 } else if(id == SIG_TOWNS_DMAC_ADDR_MASK) {
274 // From eFMR50 / memory.cpp / update_dma_addr_mask()
275 dma_addr_mask = data;
278 // if(id == SIG_UPD71071_CH1) {
279 // out_debug_log(_T("DRQ from SCSI %02X %02X"), data, mask);
281 UPD71071::write_signal(id, data, _mask);
285 void TOWNS_DMAC::do_dma_dev_to_mem_8bit(int c)
289 uint32_t addr = dma[c].areg;
291 val = dma[c].dev->read_dma_io8(0);
293 // update temporary register
294 tmp = (tmp >> 8) | (val << 8);
295 bool _debugging = false;
296 if((d_debugger != NULL) && (__USE_DEBUGGER)) {
297 _debugging = d_debugger->now_device_debugging;
299 __UNLIKELY_IF(_debugging) {
300 d_debugger->write_via_debugger_data8(addr, val);
302 write_via_debugger_data8(addr, val);
306 void TOWNS_DMAC::do_dma_mem_to_dev_8bit(int c)
310 uint32_t addr = dma[c].areg;
312 bool _debugging = false;
313 if((d_debugger != NULL) && (__USE_DEBUGGER)) {
314 _debugging = d_debugger->now_device_debugging;
316 __UNLIKELY_IF(_debugging) {
317 val = d_debugger->read_via_debugger_data8(addr);
319 val = read_via_debugger_data8(addr);
321 // update temporary register
322 tmp = (tmp >> 8) | (val << 8);
324 dma[c].dev->write_dma_io8(0, val);
327 void TOWNS_DMAC::do_dma_dev_to_mem_16bit(int c)
331 uint32_t addr = dma[c].areg;
333 val = dma[c].dev->read_dma_io16(0);
334 // update temporary register
337 bool _debugging = false;
338 if((d_debugger != NULL) && (__USE_DEBUGGER)) {
339 _debugging = d_debugger->now_device_debugging;
342 if((addr & 1) != 0) {
343 // If odd address, write a byte.
344 uint32_t tval = (val >> 8) & 0xff;
345 __UNLIKELY_IF(_debugging) {
346 d_debugger->write_via_debugger_data8(addr, tval);
348 write_via_debugger_data8(addr, tval);
353 __UNLIKELY_IF(_debugging) {
354 d_debugger->write_via_debugger_data16(addr, val);
356 write_via_debugger_data16(addr, val);
361 void TOWNS_DMAC::do_dma_mem_to_dev_16bit(int c)
365 uint32_t addr = dma[c].areg;
367 bool _debugging = false;
368 if((d_debugger != NULL) && (__USE_DEBUGGER)) {
369 _debugging = d_debugger->now_device_debugging;
371 __UNLIKELY_IF(_debugging) {
372 val = d_debugger->read_via_debugger_data16(addr);
374 val = this->read_via_debugger_data16(addr);
376 // if((addr & 1) != 0) {
377 // // If odd address, read a high byte.
378 // val = (val >> 8) & 0xff;
380 // update temporary register
383 dma[c].dev->write_dma_io16(0, val);
387 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
388 bool TOWNS_DMAC::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
390 static const _TCHAR *dir[4] = {
391 _T("VERIFY"), _T("I/O->MEM"), _T("MEM->I/O"), _T("INVALID")
393 if(buffer == NULL) return false;
394 _TCHAR sbuf[4][512] = {0};
395 for(int i = 0; i < 4; i++) {
396 my_stprintf_s(sbuf[i], 512,
397 _T("CH%d AREG=%08X CREG=%04X BAREG=%08X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n"),
403 ((req | sreq) >> 0) & 1,
406 dir[(dma[i].mode >> 2) & 3]
410 my_stprintf_s(buffer, buffer_len,
411 _T("16Bit=%s ADDR_MASK=%08X ADDR_WRAP=%02X \n")
412 _T("SELECT CH=%d BASE=%02X REQ=%02X SREQ=%02X MASK=%02X TC=%02X ")
413 _T("CMD=%04X TMP=%04X\n")
418 (b16 != 0) ? _T("YES") : _T("NO"), dma_addr_mask, dma_wrap_reg,
419 selch, base, req, sreq, mask, tc,
430 #define STATE_VERSION 3
432 bool TOWNS_DMAC::process_state(FILEIO *state_fio, bool loading)
434 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
437 if(!state_fio->StateCheckInt32(this_device_id)) {
440 if(!(UPD71071::process_state(state_fio, loading))) {
443 state_fio->StateValue(dma_wrap_reg);
444 state_fio->StateValue(dma_addr_mask);
445 state_fio->StateArray(creg_set, sizeof(creg_set), 1);
446 state_fio->StateArray(bcreg_set, sizeof(bcreg_set), 1);