From 04a2c954331d7f7cd2a4b0d4255a7dcc1a76edd1 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Fri, 9 Apr 2021 01:38:27 +0900 Subject: [PATCH] [VM][FMTOWNS][CDROM][DMAC] Apply before commit: Use ACK bus arbiytation to transfer. --- source/src/vm/fmtowns/cdrom.cpp | 166 ++++++++++++++---------------- source/src/vm/fmtowns/cdrom.h | 1 + source/src/vm/fmtowns/dmac.cpp | 207 ++++++++++++++++++++++++++++---------- source/src/vm/fmtowns/dmac.h | 2 + source/src/vm/fmtowns/fmtowns.cpp | 2 + 5 files changed, 234 insertions(+), 144 deletions(-) diff --git a/source/src/vm/fmtowns/cdrom.cpp b/source/src/vm/fmtowns/cdrom.cpp index 2995fee93..bbf107897 100644 --- a/source/src/vm/fmtowns/cdrom.cpp +++ b/source/src/vm/fmtowns/cdrom.cpp @@ -99,8 +99,8 @@ void TOWNS_CDROM::cdrom_debug_log(const char *fmt, ...) void TOWNS_CDROM::initialize() { DEVICE::initialize(); -// __CDROM_DEBUG_LOG = osd->check_feature(_T("_CDROM_DEBUG_LOG")); - __CDROM_DEBUG_LOG = true; + __CDROM_DEBUG_LOG = osd->check_feature(_T("_CDROM_DEBUG_LOG")); +// __CDROM_DEBUG_LOG = true; _USE_CDROM_PREFETCH = osd->check_feature(_T("USE_CDROM_PREFETCH")); force_logging = false; @@ -221,8 +221,8 @@ void TOWNS_CDROM::do_dma_eot(bool by_signal) { static const _TCHAR by_dma[] = _T("SIGNAL"); static const _TCHAR by_event[] = _T("EVENT"); - dma_transfer_phase = false; - dma_transfer = false; +// dma_transfer_phase = false; +// dma_transfer = false; mcu_ready = false; dma_intr = true; @@ -250,6 +250,7 @@ void TOWNS_CDROM::do_dma_eot(bool by_signal) clear_event(this, event_next_sector); clear_event(this, event_seek_completed); status_read_done(false); +// clear_event(this, event_drq); cdrom_debug_log(_T("EOT(%s/DMA)"), (by_signal) ? by_dma : by_event); } else { cdrom_debug_log(_T("NEXT(%s/DMA)"), (by_signal) ? by_dma : by_event); @@ -262,8 +263,12 @@ void TOWNS_CDROM::do_dma_eot(bool by_signal) // status_data_ready(false); } write_signals(&outputs_drq, 0x00000000); - if(!(dma_intr_mask) && (stat_reply_intr)) { - write_mcuint_signals(0xffffffff); + if(dma_transfer_phase) { + dma_transfer_phase = false; + + if(!(dma_intr_mask) && (stat_reply_intr)) { + write_mcuint_signals(0xffffffff); + } } #endif } @@ -304,6 +309,12 @@ void TOWNS_CDROM::write_signal(int id, uint32_t data, uint32_t mask) do_dma_eot(true); } break; + case SIG_TOWNS_CDROM_DMAACK: + if(((data & mask) != 0) && (dma_transfer_phase)) { + force_register_event(this, EVENT_CDROM_DRQ, 1.0 / 8.0, false, event_drq); +// event_callback(EVENT_CDROM_DRQ, 0); + } + break; default: // ToDo: Implement master devices. break; @@ -693,19 +704,24 @@ uint8_t TOWNS_CDROM::read_status() uint32_t TOWNS_CDROM::read_dma_io8(uint32_t addr) { - data_reg = (uint8_t)(databuffer->read() & 0xff); +// bool is_empty = databuffer->empty(); + if(dma_transfer_phase) { + data_reg = (uint8_t)(databuffer->read() & 0xff); + /* if((databuffer->empty()) && (read_length <= 0)) { - //cdrom_debug_log(_T("EOT(DMA) by read_dma_io8()")); - read_length_bak = 0; - // Fallback -#if 0 - event_callback(EVENT_CDROM_EOT, 0); -#else - register_event(this, EVENT_CDROM_EOT, + //cdrom_debug_log(_T("EOT(DMA) by read_dma_io8()")); + read_length_bak = 0; + // Fallback + #if 0 + event_callback(EVENT_CDROM_EOT, 0); + #else + register_event(this, EVENT_CDROM_EOT, // 0.2 * 1.0e6 / ((double)transfer_speed * 150.0e3 ), 1.0e3, false, &event_eot); -#endif + #endif + } + */ } return data_reg; } @@ -719,7 +735,7 @@ void TOWNS_CDROM::write_dma_io8(uint32_t addr, uint32_t data) void TOWNS_CDROM::read_cdrom() { // read_pos = 0; - databuffer->clear(); +// databuffer->clear(); if((cdda_status != CDDA_OFF) && (cdda_status != CDDA_ENDED)) { // @note In SUPER REAL MAHJONG PIV, use PAUSE (A5h) command before reading. // @note 20201110 K.O @@ -767,7 +783,7 @@ void TOWNS_CDROM::read_cdrom() status_parameter_error(false); return; } -// databuffer->clear(); + cdrom_debug_log(_T("READ_CDROM TRACK=%d LBA1=%d LBA2=%d M1/S1/F1=%02X/%02X/%02X M2/S2/F2=%02X/%02X/%02X PAD=%02X DCMD=%02X"), track, lba1, lba2, param_queue[0], param_queue[1], param_queue[2], param_queue[3], param_queue[4], param_queue[5], @@ -776,8 +792,8 @@ void TOWNS_CDROM::read_cdrom() read_length = __remain * logical_block_size(); read_length_bak = read_length; read_sector = lba1; -// dma_transfer_phase = dma_transfer; - pio_transfer_phase = pio_transfer; + dma_transfer_phase = false; + pio_transfer_phase = false; clear_event(this, event_drq); clear_event(this, event_next_sector); clear_event(this, event_seek_completed); @@ -785,7 +801,8 @@ void TOWNS_CDROM::read_cdrom() // Kick a first double usec = get_seek_time(lba1); status_seek = true; - if(usec < 1100.0) usec = 1100.0; + if(usec < 10.0) usec = 10.0; + databuffer->clear(); register_event(this, EVENT_CDROM_SEEK_COMPLETED, usec, false, &event_seek_completed); if(req_status) { // May not need extra status, integrated after reading. 20200906 K.O @@ -1333,14 +1350,14 @@ void TOWNS_CDROM::event_callback(int event_id, int err) clear_event(this, event_time_out); // ToDo: Prefetch 20201116 // if((databuffer->left() < logical_block_size()) && (read_length > 0)) { -// if(!(databuffer->empty()) && (read_length > 0)) { -// register_event(this, EVENT_CDROM_SEEK_COMPLETED, -// (1.0e6 / ((double)transfer_speed * 150.0e3)) * -// 2.0, -// false, -// &event_seek_completed); -// break; // EXIT -// } + if(!(databuffer->empty()) && (read_length > 0)) { + register_event(this, EVENT_CDROM_SEEK_COMPLETED, + (1.0e6 / ((double)transfer_speed * 150.0e3)) * + 2.0, + false, + &event_seek_completed); + break; // EXIT + } if(read_length > 0) { mcu_ready = false; bool stat = false; @@ -1350,90 +1367,49 @@ void TOWNS_CDROM::event_callback(int event_id, int err) // Maybe data has changed to 1Fh from 8Eh. /// 20200926 K.O stat = read_buffer(1); -#if 0 - register_event(this, EVENT_CDROM_NEXT_SECTOR, -// (1.0e6 / ((double)transfer_speed * 150.0e3)) * -// ((double)(physical_block_size())) * -// 0.2, // OK? - 5.0e3, // From TSUGARU - false, &event_next_sector); - } -#else if((stat)) { register_event(this, EVENT_CDROM_NEXT_SECTOR, (1.0e6 / ((double)transfer_speed * 150.0e3)) * ((double)(physical_block_size())) * - 0.5, // OK? + 1.0, // OK? false, &event_next_sector); } //register_event(this, EVENT_CDROM_TIMEOUT, 1000.0e3, false, &event_time_out); } /*else { status_read_done(false); }*/ -#endif break; case EVENT_CDROM_NEXT_SECTOR: event_next_sector = -1; clear_event(this, event_seek_completed); // BIOS FDDFCh(0FC0h:01FCh)- -#if 0 - if(pio_transfer) { - if(read_length <= 0) { - out_debug_log(_T("EOT")); - pio_transfer_phase = false; - dma_transfer_phase = false; -// status_read_done(true); -// set_dma_intr(true); - break; - } - } -#else if(pio_transfer) { set_status(true, 0, TOWNS_CD_STATUS_CMD_ABEND, 0x00, 0x00, 0x00); // OK? set_dma_intr(true); } else { status_data_ready(false); } -#endif // ToDo: Prefetch -#if 0 - if(((cdrom_prefetch) && (databuffer->left() >= logical_block_size())) || - ((databuffer->empty()) && (read_length > 0))) { - if(pio_transfer) { - set_status(true, 0, TOWNS_CD_STATUS_CMD_ABEND, 0x00, 0x00, 0x00); // OK? - set_dma_intr(true); - } else { - status_data_ready(true); - } - register_event(this, EVENT_CDROM_SEEK_COMPLETED, - (1.0e6 / ((double)transfer_speed * 150.0e3)) * - ((double)(physical_block_size())) * - 1.0, // OK? - false, &event_seek_completed); - } else if(read_length > 0) { - // Polling to buffer empty. - register_event(this, EVENT_CDROM_NEXT_SECTOR, - (1.0e6 / ((double)transfer_speed * 150.0e3)) * 8.0, // OK? - false, &event_next_sector); - } - -#else status_seek = true; register_event(this, EVENT_CDROM_SEEK_COMPLETED, (1.0e6 / ((double)transfer_speed * 150.0e3)) * ((double)(physical_block_size())) * - 0.5, // OK? + 1.0, // OK? +// 5.0e3, false, &event_seek_completed); -#endif break; case EVENT_CDROM_DRQ: // ToDo: Buffer OVERFLOW at PIO mode. - - if((dma_transfer_phase) && !(databuffer->empty())) { - write_signals(&outputs_drq, /*(drq_tick) ? 0xffffffff : 0x00000000*/ 0xffffffff); + event_drq = -1; + if(dma_transfer_phase) { + if(!(databuffer->empty())) { + write_signals(&outputs_drq, 0xffffffff); + } else if(read_length > 0) { + // Retry DRQ if buffert empty. + force_register_event(this, EVENT_CDROM_DRQ, 1.0 / 8.0, false, event_drq); + } } - //read_pos++; break; case EVENT_CDROM_EOT: event_eot = -1; @@ -3228,21 +3204,25 @@ void TOWNS_CDROM::write_io8(uint32_t addr, uint32_t data) param_queue[7] = data; break; case 0x06: - if((data & 0x08) != 0) { - dma_transfer = false; - pio_transfer = true; - } - if((data & 0x10) != 0) { - dma_transfer = true; - pio_transfer = false; - } - if((dma_transfer) /*&& !(dma_transfer_phase)*/) { - dma_transfer_phase = true; - force_register_event(this, EVENT_CDROM_DRQ, /*0.25 * 1.0e6 / ((double)transfer_speed * 150.0e3 ) */ 1.0 / 8.0, true, event_drq); - } else if((pio_transfer) && !(pio_transfer_phase)) { - pio_transfer_phase = true; + dma_transfer = ((data & 0x10) != 0) ? true : false; + pio_transfer = ((data & 0x08) != 0) ? true : false; + if(dma_transfer) { + if(!(dma_transfer_phase)) { + if(d_dmac != NULL) { + uint32_t _t = d_dmac->read_signal(SIG_UPD71071_IS_TRANSFERING + 3); + if((_t != 0)) { + dma_transfer_phase = true; + force_register_event(this, EVENT_CDROM_DRQ, 1.0 / 8.0, false, event_drq); + } + } + } + } else if(pio_transfer) { + if(!(pio_transfer_phase)) { + pio_transfer_phase = true; + } } cdrom_debug_log(_T("SET TRANSFER MODE to %02X"), data); +// } break; } } diff --git a/source/src/vm/fmtowns/cdrom.h b/source/src/vm/fmtowns/cdrom.h index ec9af83cc..2f859a015 100644 --- a/source/src/vm/fmtowns/cdrom.h +++ b/source/src/vm/fmtowns/cdrom.h @@ -35,6 +35,7 @@ #define SIG_TOWNS_CDROM_READ_DATA 0x22 #define SIG_TOWNS_CDROM_RESET 0x23 #define SIG_TOWNS_CDROM_DMAINT 0x24 +#define SIG_TOWNS_CDROM_DMAACK 0x25 class SCSI_HOST; class FIFO; diff --git a/source/src/vm/fmtowns/dmac.cpp b/source/src/vm/fmtowns/dmac.cpp index ad397c7c5..56d67718c 100644 --- a/source/src/vm/fmtowns/dmac.cpp +++ b/source/src/vm/fmtowns/dmac.cpp @@ -21,6 +21,64 @@ void TOWNS_DMAC::reset() // b16 = 2; // Fixed 16bit. } +void TOWNS_DMAC::write_io16(uint32_t addr, uint32_t data) +{ + pair32_t _d, _bd; + if(b16 != 0) { + switch(addr & 0x0f) { + case 0x02: + case 0x03: + if(base == 0) { + creg_set[selch] = true; + dma[selch].creg = data & 0xffff; + } + dma[selch].bcreg = data & 0xffff; + bcreg_set[selch] = true; + return; + break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + _d.d = dma[selch].areg; + _bd.d = dma[selch].bareg; + if((addr & 0x0f) < 6) { + if(base == 0) { + _d.w.l = (data & 0xffff); + dma[selch].areg = _d.d; + } + _bd.w.l = (data & 0xffff); + dma[selch].bareg = _bd.d; + } else { + if(base == 0) { + _d.w.h = (data & 0xffff); + dma[selch].areg = _d.d; + } + _bd.w.h = (data & 0xffff); + dma[selch].bareg = _bd.d; + } + break; + case 0x08: + case 0x09: + cmd = data & 0xffff; + if(((data & 0x04) != (cmd & 0x04)) && (selch == 3)) { + if((data & 0x04) == 0) { + out_debug_log(_T("TRANSFER: CMD=%04X -> %04X CH=%d\nADDR=%08X"), cmd, (cmd & 0xff00) | (data & 0xff), selch, dma[selch].areg); + } + } + break; + default: +// write_io8(addr & 0x0e, data); + write_io8(addr, data); + break; + } + } else { + write_io8(addr, data); +// write_io8((addr & 0x0e) + 0, data); +// write_io8((addr & 0x0e) + 1, data); + } +} + void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data) { // if((addr & 0x0f) == 0x0c) out_debug_log("WRITE REG: %08X %08X", addr, data); @@ -41,30 +99,11 @@ void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data) } bcreg_set[selch] = true; break; - case 0x04: - case 0x05: - case 0x06: case 0x07: _d.d = dma[selch].areg; _bd.d = dma[selch].bareg; - switch(addr & 0x0f) { - case 0x04: - _d.b.l = data; - _bd.b.l = data; - break; - case 0x05: - _d.b.h = data; - _bd.b.h = data; - break; - case 0x06: - _d.b.h2 = data; - _bd.b.h2 = data; - break; - case 0x07: - _d.b.h3 = data; - _bd.b.h3 = data; - break; - } + _d.b.h3 = data; + _bd.b.h3 = data; if(base == 0) { dma[selch].areg = _d.d; } @@ -91,7 +130,7 @@ void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data) // Note: This is *temporaly* workaround for 16bit transfer mode with 8bit bus. // 20200318 K.O #if !defined(USE_QUEUED_SCSI_TRANSFER) - if((dma[selch].is_16bit) && (b16)) { + if((dma[selch].is_16bit) && !(inputs_ube[selch])) { if(creg_set[selch]) { dma[selch].creg <<= 1; dma[selch].creg++; @@ -112,39 +151,99 @@ void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data) } UPD71071::write_io8(addr, data); } + +uint32_t TOWNS_DMAC::read_io16(uint32_t addr) +{ + if(b16 != 0) { + switch(addr & 0x0f) { + case 0x02: + case 0x03: + if(base == 0) { + return (dma[selch].creg & 0xffff); + } else { + return (dma[selch].bcreg & 0xffff); + } + break; + case 0x04: + case 0x05: + if(base == 0) { + return (dma[selch].areg & 0xffff); + } else { + return (dma[selch].bareg & 0xffff); + } + break; + case 0x06: + case 0x07: + if(base == 0) { + return ((dma[selch].areg >> 16) & 0xffff); + } else { + return ((dma[selch].bareg >> 16) & 0xffff); + } + break; + case 0x08: + case 0x09: + return (uint32_t)(cmd & 0xffff); + break; + default: + return read_io8(addr); +// return read_io8(addr & 0x0e); + break; + } + } else { + pair16_t _d; + _d.w = 0; + _d.b.l = read_io8(addr); +// _d.b.l = read_io8((addr & 0x0e) + 0); +// _d.b.h = read_io8((addr & 0x0e) + 1); + return (uint32_t)(_d.w); + } +} + uint32_t TOWNS_DMAC::read_io8(uint32_t addr) { uint32_t val; - pair32_t nval; + pair32_t _d; switch(addr & 0x0f) { case 0x01: return (base << 3) | (1 << (selch & 3)); break; - case 0x04: - if(base) { - return dma[selch].bareg & 0xff; - } else { - return dma[selch].areg & 0xff; - } - case 0x05: - if(base) { - return (dma[selch].bareg >> 8) & 0xff; + case 0x02: + case 0x03: + if(base == 0) { + _d.d = dma[selch].creg; +#if !defined(USE_QUEUED_SCSI_TRANSFER) + if((dma[selch].is_16bit) && !(inputs_ube[selch])) { + if(!(creg_set[selch])) { + _d.d >>= 1; + } + } +#endif } else { - return (dma[selch].areg >> 8) & 0xff; + _d.d = dma[selch].bcreg; +#if !defined(USE_QUEUED_SCSI_TRANSFER) + if((dma[selch].is_16bit) && !(inputs_ube[selch])) { + if(!(bcreg_set[selch])) { + _d.d >>= 1; + } + } +#endif } - case 0x06: - if(base) { - return (dma[selch].bareg >> 16) & 0xff; - } else { - return (dma[selch].areg >> 16) & 0xff; + switch(addr & 0x0f) { + case 2: + return _d.b.l; + break; + case 3: + return _d.b.h; + break; } break; case 0x07: - if(base) { - return (dma[selch].bareg >> 24) & 0xff; + if(base == 0) { + _d.d = dma[selch].areg; } else { - return (dma[selch].areg >> 24) & 0xff; + _d.d = dma[selch].bareg; } + return (uint32_t)(_d.b.h3); break; } return UPD71071::read_io8(addr); @@ -241,8 +340,10 @@ void TOWNS_DMAC::do_dma_dev_to_mem_8bit(int c) uint32_t addr = dma[c].areg; reset_ube(c); val = dma[c].dev->read_dma_io8(0); + // update temporary register tmp = (tmp >> 8) | (val << 8); + if(_USE_DEBUGGER) { if(d_debugger != NULL && d_debugger->now_device_debugging) { d_debugger->write_via_debugger_data8(addr, val); @@ -269,9 +370,10 @@ void TOWNS_DMAC::do_dma_mem_to_dev_8bit(int c) } else { val = read_via_debugger_data8(addr); } - dma[c].dev->write_dma_io8(0, val); // update temporary register tmp = (tmp >> 8) | (val << 8); + + dma[c].dev->write_dma_io8(0, val); } void TOWNS_DMAC::do_dma_dev_to_mem_16bit(int c) @@ -281,6 +383,9 @@ void TOWNS_DMAC::do_dma_dev_to_mem_16bit(int c) uint32_t addr = dma[c].areg; set_ube(c); val = dma[c].dev->read_dma_io16(0); + // update temporary register + tmp = val; +/* if((addr & 1) != 0) { // If odd address, write a byte. uint32_t tval = (val >> 8) & 0xff; @@ -294,6 +399,7 @@ void TOWNS_DMAC::do_dma_dev_to_mem_16bit(int c) write_via_debugger_data8(addr, tval); } } else { +*/ // 16bit if(_USE_DEBUGGER) { if(d_debugger != NULL && d_debugger->now_device_debugging) { @@ -304,9 +410,7 @@ void TOWNS_DMAC::do_dma_dev_to_mem_16bit(int c) } else { write_via_debugger_data16(addr, val); } - } - // update temporary register - tmp = val; +// } } void TOWNS_DMAC::do_dma_mem_to_dev_16bit(int c) @@ -324,13 +428,14 @@ void TOWNS_DMAC::do_dma_mem_to_dev_16bit(int c) } else { val = this->read_via_debugger_data16(addr); } - if((addr & 1) != 0) { - // If odd address, read a high byte. - val = (val >> 8) & 0xff; - } - dma[c].dev->write_dma_io16(0, val); +// if((addr & 1) != 0) { +// // If odd address, read a high byte. +// val = (val >> 8) & 0xff; +// } // update temporary register tmp = val; + + dma[c].dev->write_dma_io16(0, val); } @@ -365,7 +470,7 @@ bool TOWNS_DMAC::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len) _T("%s") _T("%s") _T("%s"), - (b16) ? _T("YES") : _T("NO"), dma_addr_mask, dma_wrap_reg, + (b16 != 0) ? _T("YES") : _T("NO"), dma_addr_mask, dma_wrap_reg, selch, base, req, sreq, mask, tc, cmd, tmp, sbuf[0], diff --git a/source/src/vm/fmtowns/dmac.h b/source/src/vm/fmtowns/dmac.h index 15aae1d00..9f53cd3c9 100644 --- a/source/src/vm/fmtowns/dmac.h +++ b/source/src/vm/fmtowns/dmac.h @@ -38,6 +38,8 @@ public: virtual void __FASTCALL write_io8(uint32_t addr, uint32_t data); virtual uint32_t __FASTCALL read_io8(uint32_t addr); + virtual void __FASTCALL write_io16(uint32_t addr, uint32_t data); + virtual uint32_t __FASTCALL read_io16(uint32_t addr); virtual void __FASTCALL write_signal(int id, uint32_t data, uint32_t _mask); virtual uint32_t __FASTCALL read_signal(int id); diff --git a/source/src/vm/fmtowns/fmtowns.cpp b/source/src/vm/fmtowns/fmtowns.cpp index 3fcb87548..d5912dbbe 100644 --- a/source/src/vm/fmtowns/fmtowns.cpp +++ b/source/src/vm/fmtowns/fmtowns.cpp @@ -345,6 +345,8 @@ VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu) dma->set_context_ch3(cdrom); dma->set_context_tc1(scsi, SIG_SCSI_EOT, 0xffffffff); dma->set_context_tc3(cdrom, SIG_TOWNS_CDROM_DMAINT, 0xffffffff); + dma->set_context_ack3(cdrom, SIG_TOWNS_CDROM_DMAACK, 0xffffffff); + dma->set_context_ube1(scsi_host, SIG_SCSI_16BIT_BUS, 0x02); dma->set_context_child_dma(extra_dma); -- 2.11.0