6 #define EVENT_DMAC_CYCLE 1
8 void TOWNS_DMAC::initialize()
10 UPD71071::initialize();
11 for(int ch = 0; ch < 4; ch++) {
12 is_started[ch] = false;
13 address_aligns_16bit[ch] = true;
14 is_16bit_transfer[ch] = false;
17 event_dmac_cycle = -1;
20 void TOWNS_DMAC::reset()
25 for(int ch = 0; ch < 4; ch++) {
27 is_started[ch] = false;
28 calc_transfer_status(ch);
30 clear_event(this, event_dmac_cycle);
32 for(int ch = 0; ch < 4; ch++) {
33 //write_signals(&outputs_towns_tc[ch], ((tc & (1 << ch)) != 0) ? 0xffffffff : 0);
34 write_signals(&outputs_ube[ch], (is_16bit[ch]) ? 0xffffffff : 0);
39 void TOWNS_DMAC::call_dma(int ch)
41 bool is_use_debugger = false;
42 __LIKELY_IF(__USE_DEBUGGER) {
43 __LIKELY_IF(d_debugger != NULL) {
44 is_use_debugger = d_debugger->now_device_debugging;
47 do_dma_per_channel(ch, is_use_debugger, false);
51 void TOWNS_DMAC::write_io16(uint32_t addr, uint32_t data)
53 __UNLIKELY_IF(b16 == 0) {
54 write_io8(addr, data);
59 dma[selch].bcreg = data;
61 dma[selch].creg = data;
63 // Reset TC bit for towns, by Tsugaru commit ab067790479064efce693f7317af13696cb68d96 . tc &= ~(1 << selch);
64 write_signals(&outputs_towns_tc[selch], 0);
66 case 0x04: // ADDR LOW
67 dma[selch].bareg = (dma[selch].bareg & 0xffff0000) | (data & 0xffff);
69 dma[selch].areg = dma[selch].bareg; // OK? This is from Tsugaru. 20230710 K.O
72 case 0x06: // ADDR HIGH
73 dma[selch].bareg = (dma[selch].bareg & 0x0000ffff) | ((data & 0xffff) << 16);
75 dma[selch].areg = dma[selch].bareg; // OK? This is from Tsugaru. 20230710 K.O
80 if(/*(cmd != cmd_bak) && */((cmd & 0x04) == 0)) {
81 check_start_condition();
87 write_io8((addr & 0x0e) + 0, data & 0x00ff);
88 write_io8((addr & 0x0e) + 1, (data & 0xff00) >> 8); // OK?
93 void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data)
95 // if((addr & 0x0f) == 0x0c) out_debug_log("WRITE REG: %08X %08X", addr, data);
96 // out_debug_log("WRITE REG: %04X %02X", addr, data);
98 uint8_t cmd_bak = cmd;
99 bool need_transfer = false;
100 switch(addr & 0x0f) {
102 UPD71071::write_io8(0, data);
104 clear_event(this, event_dmac_cycle);
106 for(int ch = 0; ch < 4; ch++) {
109 is_started[ch] = false;
111 calc_transfer_status(ch);
114 for(int ch = 0; ch < 4; ch++) {
115 write_signals(&outputs_ube[ch], (is_16bit[ch]) ? 0xffffffff : 0);
117 out_debug_log(_T("RESET from I/O; B16=%s"), ((b16 & 2) != 0) ? _T("16bit") : _T("8bit"));
120 // Reset TC bit for towns, by Tsugaru commit ab067790479064efce693f7317af13696cb68d96 . tc &= ~(1 << selch);
121 write_signals(&outputs_towns_tc[selch], 0);
122 //UPD71071::write_io8(addr, data);
123 dma[selch].bcreg = (dma[selch].bcreg & 0xff00) | data;
125 dma[selch].creg = dma[selch].bcreg; // OK?
129 write_signals(&outputs_towns_tc[selch], 0);
130 //UPD71071::write_io8(addr, data);
131 dma[selch].bcreg = (dma[selch].bcreg & 0x00ff) | (data << 8);
133 dma[selch].creg = dma[selch].bcreg; // OK?
137 dma[selch].bareg = (dma[selch].bareg & 0xffffff00) | data;
139 dma[selch].areg = dma[selch].bareg;
142 if(is_started[selch]) {
143 if(check_address_16bit_bus_changed(selch)) {
150 dma[selch].bareg = (dma[selch].bareg & 0xffff00ff) | (data << 8);
152 dma[selch].areg = dma[selch].bareg;
156 dma[selch].bareg = (dma[selch].bareg & 0xff00ffff) | (data << 16);
158 dma[selch].areg = dma[selch].bareg;
162 dma[selch].bareg = (dma[selch].bareg & 0x00ffffff) | (data << 24);
164 dma[selch].areg = dma[selch].bareg;
170 UPD71071::write_io8(addr, data);
172 if(/*(cmd != cmd_bak) && */((cmd & 0x04) == 0)) {
173 check_start_condition();
179 out_debug_log(_T("CMD CHANGED from %04X to 0x%04X : MAYBE START to TRANSFER"),
181 static const _TCHAR *dir[4] = {
182 _T("VERIFY"), _T("I/O->MEM"), _T("MEM->I/O"), _T("INVALID")
184 for(int ch = 0; ch < 4; ch++) {
186 out_debug_log(_T("CH%d AREG=%08X CREG=%04X BAREG=%08X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s"),
187 ch, dma[ch].areg, dma[ch].creg, dma[ch].bareg, dma[ch].bcreg,
188 ((req | sreq) >> ch) & 1,
191 dir[(dma[ch].mode >> 2) & 3]);
199 // BIT 7,6 : TRANSFER MODE
217 UPD71071::write_io8(addr, data);
223 out_debug_log(_T("MODE CHANGED at CH.%d to 0x%02X Request 16bit=%s CMD=%02X"), selch, dma[selch].mode,
224 (is_16bit_transfer[selch]) ? _T("Yes") : _T("NO"),
226 static const _TCHAR *dir[4] = {
227 _T("VERIFY"), _T("I/O->MEM"), _T("MEM->I/O"), _T("INVALID")
229 out_debug_log(_T("CH%d AREG=%08X CREG=%04X BAREG=%08X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s"),
230 selch, dma[selch].areg, dma[selch].creg, dma[selch].bareg, dma[selch].bcreg,
231 ((req | sreq) >> selch) & 1,
234 dir[(dma[selch].mode >> 2) & 3]);
240 const uint8_t sreq_b = sreq;
241 if(((sreq = data) & 0x0f) != 0) {
242 if(((sreq_b ^ sreq) & 0x0f) != 0) {
244 check_start_condition();
253 const uint8_t _mask_b = mask;
254 const uint8_t bit = 1 << selch;
255 UPD71071::write_io8(addr, data);
257 // Check when mask[selch] has changed,
258 if(((mask ^ _mask_b) & bit) != 0) {
259 check_start_condition();
264 // Add trigger of transfer by SREQ.
265 //need_transfer = (!(_SINGLE_MODE_DMA) && ((cmd & 0x04) == 0));
268 UPD71071::write_io8(addr, data);
271 // if((need_transfer) && ((cmd & 4) == 0)) {
276 uint32_t TOWNS_DMAC::read_io8(uint32_t addr)
279 switch(addr & 0x0f) {
282 val = (dma[selch].bareg >> 24) & 0xff;
284 val = (dma[selch].areg >> 24) & 0xff;
288 val = UPD71071::read_io8(addr);
289 // Q: Is reset TC* ? 20230429 K.O
290 //for(int ch = 0; ch < 4; ch++) {
291 // write_signals(&outputs_towns_tc[ch], 0);
295 val = UPD71071::read_io8(addr);
301 uint32_t TOWNS_DMAC::read_io16(uint32_t addr)
303 __UNLIKELY_IF(b16 == 0) {
304 return read_io8(addr);
306 switch(addr & 0x0e) {
309 return dma[selch].bcreg;
311 return dma[selch].creg;
316 return dma[selch].bareg & 0x0000ffff;
318 return dma[selch].areg & 0x0000ffff;
323 return (dma[selch].bareg & 0xffff0000) >> 16;
325 return (dma[selch].areg & 0xffff0000) >> 16;
335 val = read_io8((addr & 0x0e) + 0) & 0x00ff;
336 val = val | ((read_io8((addr & 0x0e) + 1) & 0xff) << 8); // OK?
340 void TOWNS_DMAC::inc_dec_ptr_a_byte(uint32_t& addr, const bool inc)
342 // Note: FM-Towns may extend to 32bit.
343 // Note: By Tsugaru, commit e5920fdc1ba89ba10172f0954ecf1107bb592919,
344 // ADIR bit (bit 5 of mode register)
345 // has not supported by TOWNS DMAC.
346 // Very tanks to YAMAKAWA-San. - 20230617 K.O
348 // Commiting message is below:
349 // Author: CaptainYS <PEB01130@nifty.com>
350 // AuthorDate: Sat Feb 29 23:43:52 2020 -0500
351 // Commit: CaptainYS <PEB01130@nifty.com>
352 // CommitDate: Sat Feb 29 23:43:52 2020 -0500
355 // Found Device-DMACh correspondence in [2] pp. 56.
356 // Still trying to find the correct sequence of CD-ROM drive
358 // Unit test still temporarily broken.
360 // uint32_t incdec = (inc) ? 1 : UINT32_MAX;
361 const uint32_t incdec = 1;
362 __LIKELY_IF(dma_wrap) {
363 uint32_t high_a = addr & 0xff000000;
364 addr = (addr + incdec) & 0x00ffffff;
365 addr = addr | high_a;
367 addr = (addr + incdec) & 0xffffffff;
371 void TOWNS_DMAC::inc_dec_ptr_two_bytes(uint32_t& addr, const bool inc)
373 // Note: FM-Towns may extend to 32bit.
375 //uint32_t incdec = (inc) ? 2 : (UINT32_MAX - 1);
376 const uint32_t incdec = 2;
377 __LIKELY_IF(dma_wrap) {
378 uint32_t high_a = addr & 0xff000000;
379 addr = (addr + incdec) & 0x00ffffff;
380 addr = addr | high_a;
382 addr = (addr + incdec) & 0xffffffff;
386 uint32_t TOWNS_DMAC::read_8bit_from_device(DEVICE* dev, uint32_t addr, int* wait)
388 __UNLIKELY_IF(dev == nullptr) {
389 if(wait != nullptr) {
395 val = dev->read_dma_io8w(addr, wait);
399 void TOWNS_DMAC::write_8bit_to_device(DEVICE* dev, uint32_t addr, uint32_t data, int* wait)
401 __UNLIKELY_IF(dev == nullptr) {
402 if(wait != nullptr) {
407 dev->write_dma_io8w(addr, data, wait);
410 uint32_t TOWNS_DMAC::read_8bit_from_memory(uint32_t addr, int* wait, const bool is_use_debugger)
412 __UNLIKELY_IF((is_use_debugger) && (d_debugger != NULL)) {
413 return d_debugger->read_via_debugger_data8w(addr, wait);
415 return read_via_debugger_data8w(addr, wait);
419 void TOWNS_DMAC::write_8bit_to_memory(uint32_t addr, uint32_t data, int* wait, const bool is_use_debugger)
421 __UNLIKELY_IF((is_use_debugger) && (d_debugger != NULL)) {
422 d_debugger->write_via_debugger_data8w(addr, data, wait);
424 write_via_debugger_data8w(addr, data, wait);
428 uint32_t TOWNS_DMAC::read_16bit_from_device(DEVICE* dev, uint32_t addr, int* wait)
430 __UNLIKELY_IF(dev == nullptr) {
431 if(wait != nullptr) {
437 val = dev->read_dma_io16w(addr, wait);
441 void TOWNS_DMAC::write_16bit_to_device(DEVICE* dev, uint32_t addr, uint32_t data, int* wait)
443 __UNLIKELY_IF(dev == nullptr) {
444 if(wait != nullptr) {
449 dev->write_dma_io16w(addr, data, wait);
452 uint32_t TOWNS_DMAC::read_16bit_from_memory(uint32_t addr, int* wait, const bool is_use_debugger)
454 __UNLIKELY_IF((is_use_debugger) && (d_debugger != NULL)) {
455 return d_debugger->read_via_debugger_data16w(addr, wait);
457 return read_via_debugger_data16w(addr, wait);
461 void TOWNS_DMAC::write_16bit_to_memory(uint32_t addr, uint32_t data, int* wait, const bool is_use_debugger)
463 __UNLIKELY_IF((is_use_debugger) && (d_debugger != NULL)) {
464 d_debugger->write_via_debugger_data16w(addr, data, wait);
466 write_via_debugger_data16w(addr, data, wait);
470 void TOWNS_DMAC::check_start_condition()
472 for(int ch = 0; ch < 4; ch++) {
473 uint8_t bit = 1 << ch;
474 if(((mask & bit) == 0) && (((req | sreq) & bit) != 0)) {
475 if(!(is_started[ch])) {
476 is_started[ch] = true;
477 calc_transfer_status(selch);
478 write_signals(&outputs_ube[selch], (is_16bit[selch]) ? 0xffffffff : 0x00000000);
479 end_req[selch] = false;
480 __UNLIKELY_IF((event_dmac_cycle < 0) && !(_SINGLE_MODE_DMA)) {
481 register_event(this, EVENT_DMAC_CYCLE, dmac_cycle_us, true, &event_dmac_cycle);
486 is_started[ch] = false;
493 void TOWNS_DMAC::do_dma_16bit(DEVICE* dev, const uint8_t tr_mode, uint32_t& memory_address, const bool compressed, const bool extended, bool is_use_debugger, int& wait)
498 const int wait_compressed = (compressed) ? 5 : 7;
499 switch(tr_mode & 0x0c) {
501 val = read_16bit_from_device(dev, 0, &wait_r);
503 read_16bit_from_memory(memory_address, &wait_w, is_use_debugger);
505 case 0x04: // DEVICE TO MEMORY
506 val = read_16bit_from_device(dev, 0, &wait_r);
508 write_16bit_to_memory(memory_address, val, &wait_w, is_use_debugger);
510 case 0x08: // MEMORY TO DEVICE
511 val = read_16bit_from_memory(memory_address, &wait_r, is_use_debugger);
513 write_16bit_to_device(dev, 0, val, &wait_w);
515 case 0x0c: // MEMORY TO MEMORY : still unimplemented
520 wait += wait_compressed;
522 wait = wait + wait_r + wait_w;
524 // inc_dec_ptr_two_bytes(memory_adderss, !(tr_mode & 0x20));
525 inc_dec_ptr_two_bytes(memory_address, true);
528 void TOWNS_DMAC::do_dma_8bit(DEVICE* dev, const uint8_t tr_mode, uint32_t& memory_address, const bool compressed, const bool extended, bool is_use_debugger, int& wait)
533 const int wait_compressed = (compressed) ? 5 : 7;
534 switch(tr_mode & 0x0c) {
536 val = read_8bit_from_device(dev, 0, &wait_r);
537 tmp = ((tmp & 0xff00) >> 8) | ((val & 0xff) << 8);
538 read_8bit_from_memory(memory_address, &wait_w, is_use_debugger);
540 case 0x04: // DEVICE TO MEMORY
541 val = read_8bit_from_device(dev, 0, &wait_r);
542 tmp = ((tmp & 0xff00) >> 8) | ((val & 0xff) << 8);
543 write_8bit_to_memory(memory_address, val, &wait_w, is_use_debugger);
545 case 0x08: // MEMORY TO DEVICE
546 val = read_8bit_from_memory(memory_address, &wait_r, is_use_debugger);
547 tmp = ((tmp & 0xff00) >> 8) | ((val & 0xff) << 8);
548 write_8bit_to_device(dev, 0, val, &wait_w);
550 case 0x0c: // MEMORY TO MEMORY : still unimplemented
555 wait += wait_compressed;
557 wait = wait + wait_r + wait_w;
559 // inc_dec_ptr_a_byte(memory_address, !(tr_mode & 0x20));
560 inc_dec_ptr_a_byte(memory_address, true);
563 bool TOWNS_DMAC::do_dma_per_channel(int ch, bool is_use_debugger, bool force_exit)
566 uint8_t bit = 1 << c;
568 if(/*((req | sreq) & bit) && !(mask & bit) && */(is_started[c])) {
570 // This is workaround for FM-Towns's SCSI.
572 bool __is_16bit = (is_16bit_transfer[c] || force_16bit_transfer[c]);
573 if(__is_16bit != is_16bit[c]) {
574 is_16bit[c] = __is_16bit;
575 write_signals(&outputs_ube[c], (__is_16bit) ? 0xffffffff : 0x00000000); // Reset UBE
579 bool compressed = ((cmd & 0x08) != 0);
580 bool extended = ((cmd & 0x20) != 0);
581 //while(((req | sreq) & bit) && (dma[c].creg <= dma[c].bcreg)) {
582 if(((req | sreq) & bit) && (dma[c].creg <= dma[c].bcreg)) {
585 __UNLIKELY_IF(!running) {
591 // ToDo: Will check WORD transfer mode for FM-Towns.(mode.bit0 = '1).
592 // 16bit transfer mode
593 do_dma_16bit(dma[c].dev, dma[c].mode, dma[c].areg, compressed, extended, is_use_debugger, wait);
595 // 8bit transfer mode
596 do_dma_8bit(dma[c].dev, dma[c].mode, dma[c].areg, compressed, extended, is_use_debugger, wait);
598 __UNLIKELY_IF(d_cpu != NULL) {
599 d_cpu->set_extra_clock(wait);
602 // Note: At FM-Towns, SCSI's DMAC will be set after
603 // SCSI bus phase become DATA IN/DATA OUT.
604 // Before bus phase became DATA IN/DATA OUT,
605 // DMAC mode and state was unstable (and ASSERTED
606 // DRQ came from SCSI before this state change).
607 // ToDo: Stop correctly before setting.
608 // CHECK COUNT DOWN REACHED.
611 dma[c].creg--; // OK?
612 __UNLIKELY_IF(dma[c].creg > dma[c].bcreg) {
615 uint8_t _mode = dma[c].mode & 0xc0;
617 __UNLIKELY_IF((end_req[c]) && (_mode != 0x40)){ // END_REQ ASSERTED EXCEPTS SINGLE TRANSFER.
618 do_end_sequence(c, false);
619 __LIKELY_IF(_SINGLE_MODE_DMA) {
623 } else __UNLIKELY_IF(is_tc) {
625 do_end_sequence(c, true);
626 __LIKELY_IF((_SINGLE_MODE_DMA) || (_mode == 0x40)) {
632 // IF NOT COUNTDOWN REACHED.
636 // - COUNTDOWN REACHED.
637 // - END_REQ[c] asserted.
638 // - DMA REQ MADE INACTIVE.
639 // -> CLEAR REQ and SREQ bit, ASSERT TC REGISTER.
640 __UNLIKELY_IF((req & bit) == 0) {
641 do_end_sequence(c, false);
642 __UNLIKELY_IF(_SINGLE_MODE_DMA) {
649 // - COUNTDOWN REACHED.
650 // - STOP PER BYTE/WORD TRANSFER.
651 // SOMETHING DON'T ASSERT TC, EXCEPTS COUNT DOWN REACHED TO 0.
652 // -> CLEAR REQ and SREQ bit.
659 // - END_REQ[c] asserted.
660 // - COUNTDOWN REACHED.
663 case 0xC0: // CASCADE
667 __LIKELY_IF(_SINGLE_MODE_DMA) {
671 __UNLIKELY_IF(force_exit) {
679 void TOWNS_DMAC::do_dma_internal()
681 __LIKELY_IF((event_dmac_cycle < 0) || (_SINGLE_MODE_DMA)) {
690 bool is_use_debugger = false;
692 __LIKELY_IF(d_debugger != NULL) {
693 is_use_debugger = d_debugger->now_device_debugging;
696 for(int c = 0; c < 4; c++) {
697 if(do_dma_per_channel(c, is_use_debugger, false)) {
703 void TOWNS_DMAC::do_dma()
707 __UNLIKELY_IF(_SINGLE_MODE_DMA) {
714 void TOWNS_DMAC::event_callback(int event_id, int err)
716 __LIKELY_IF(event_id == EVENT_DMAC_CYCLE) {
720 uint32_t TOWNS_DMAC::read_signal(int id)
722 if(id == SIG_TOWNS_DMAC_WRAP) {
723 return (dma_wrap) ? 0xffffffff : 0;
725 return UPD71071::read_signal(id);
728 void TOWNS_DMAC::write_signal(int id, uint32_t data, uint32_t _mask)
730 if(id == SIG_TOWNS_DMAC_WRAP) {
731 dma_wrap = ((data & _mask) != 0) ? true : false;
732 // this->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, data, mask);
733 } else if((id >= SIG_TOWNS_DMAC_EOT_CH0) && (id <= SIG_TOWNS_DMAC_EOT_CH3)) {
734 int ch = (id - SIG_TOWNS_DMAC_EOT_CH0) & 3;
735 if(((data & _mask) != 0) && !(end_req[ch])){
737 out_debug_log(_T("END#%d ASSERTED"), ch);
738 if(!(_SINGLE_MODE_DMA)) {
739 if((dma[ch].mode & 0xc0) != 0x40) { // WITHOUT SINGLE
740 do_end_sequence(ch, false); // Check immediately.
745 __LIKELY_IF((id >= SIG_UPD71071_CH0) && (id <= SIG_UPD71071_CH3)) {
746 // out_debug_log(_T("DRQ#%d %s"), ch, ((data & _mask) != 0) ? _T("ON ") : _T("OFF"));
747 int ch = (id - SIG_UPD71071_CH0) & 3;
748 uint8_t bit = 1 << ch;
749 uint8_t _mode = dma[ch].mode & 0xc0;
753 if(!(_SINGLE_MODE_DMA)) {
754 check_start_condition();
759 uint8_t _b = req & bit;
761 if(!(_SINGLE_MODE_DMA) && (_b)) { // ON -> OFF
762 check_start_condition();
768 UPD71071::write_signal(id, data, _mask);
774 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
775 bool TOWNS_DMAC::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
777 static const _TCHAR *dir[4] = {
778 _T("VERIFY"), _T("I/O->MEM"), _T("MEM->I/O"), _T("INVALID")
780 if(buffer == NULL) return false;
781 _TCHAR sbuf[4][512] = {0};
782 for(int i = 0; i < 4; i++) {
783 my_stprintf_s(sbuf[i], 512,
784 _T("CH%d AREG=%08X CREG=%04X BAREG=%08X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n"),
790 ((req | sreq) >> 0) & 1,
793 dir[(dma[i].mode >> 2) & 3]
797 my_stprintf_s(buffer, buffer_len,
798 _T("16Bit=%s ADDR_WRAP=%s \n")
799 _T("SELECT CH=%d BASE=%02X REQ=%02X SREQ=%02X MASK=%02X TC=%02X ")
800 _T("CMD=%04X TMP=%04X\n")
805 (b16 != 0) ? _T("YES") : _T("NO"), (dma_wrap) ? _T("YES") : _T("NO"),
806 selch, base, req, sreq, mask, tc,
817 #define STATE_VERSION 10
819 bool TOWNS_DMAC::process_state(FILEIO *state_fio, bool loading)
821 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
824 if(!state_fio->StateCheckInt32(this_device_id)) {
827 if(!(UPD71071::process_state(state_fio, loading))) {
830 state_fio->StateValue(dma_wrap);
831 state_fio->StateArray(is_started, sizeof(is_started), 1);
832 state_fio->StateArray(end_req, sizeof(end_req), 1);
833 state_fio->StateValue(div_count);
835 state_fio->StateValue(event_dmac_cycle);
838 for(int ch = 0; ch < 4; ch++) {
839 calc_transfer_status(ch);