From 7b657d9b61f204d27db43d9f9c41fc58a6f6a683 Mon Sep 17 00:00:00 2001 From: AJR Date: Tue, 17 Nov 2020 21:51:06 -0500 Subject: h8_dma: Preliminary support for short address mode --- src/devices/cpu/h8/h83002.cpp | 5 +- src/devices/cpu/h8/h83003.cpp | 8 +- src/devices/cpu/h8/h8_dma.cpp | 182 +++++++++++++++++++++++++++++++++++------- src/devices/cpu/h8/h8_dma.h | 4 + 4 files changed, 168 insertions(+), 31 deletions(-) diff --git a/src/devices/cpu/h8/h83002.cpp b/src/devices/cpu/h8/h83002.cpp index ec385878f1d..664134669c9 100644 --- a/src/devices/cpu/h8/h83002.cpp +++ b/src/devices/cpu/h8/h83002.cpp @@ -40,22 +40,25 @@ void h83002_device::map(address_map &map) map(base | 0xfd10, base | 0xff0f).ram(); - // DMA: only full address mode supported map(base | 0xff20, base | 0xff21).rw("dma:0", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w)); map(base | 0xff22, base | 0xff23).rw("dma:0", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w)); map(base | 0xff24, base | 0xff25).rw("dma:0", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w)); + map(base | 0xff26, base | 0xff26).rw("dma:0", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w)); map(base | 0xff27, base | 0xff27).rw("dma:0", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w)); map(base | 0xff28, base | 0xff29).rw("dma:0", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w)); map(base | 0xff2a, base | 0xff2b).rw("dma:0", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w)); map(base | 0xff2c, base | 0xff2d).rw("dma:0", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w)); + map(base | 0xff2e, base | 0xff2e).rw("dma:0", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w)); map(base | 0xff2f, base | 0xff2f).rw("dma:0", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w)); map(base | 0xff30, base | 0xff31).rw("dma:1", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w)); map(base | 0xff32, base | 0xff33).rw("dma:1", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w)); map(base | 0xff34, base | 0xff35).rw("dma:1", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w)); + map(base | 0xff36, base | 0xff36).rw("dma:1", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w)); map(base | 0xff37, base | 0xff37).rw("dma:1", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w)); map(base | 0xff38, base | 0xff39).rw("dma:1", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w)); map(base | 0xff3a, base | 0xff3b).rw("dma:1", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w)); map(base | 0xff3c, base | 0xff3d).rw("dma:1", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w)); + map(base | 0xff3e, base | 0xff3e).rw("dma:1", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w)); map(base | 0xff3f, base | 0xff3f).rw("dma:1", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w)); map(base | 0xff60, base | 0xff60).rw("timer16", FUNC(h8_timer16_device::tstr_r), FUNC(h8_timer16_device::tstr_w)); diff --git a/src/devices/cpu/h8/h83003.cpp b/src/devices/cpu/h8/h83003.cpp index c7861618208..39829d5de12 100644 --- a/src/devices/cpu/h8/h83003.cpp +++ b/src/devices/cpu/h8/h83003.cpp @@ -41,34 +41,40 @@ void h83003_device::map(address_map &map) map(base | 0xfd10, base | 0xff0f).ram(); - // DMA: only full address mode supported map(base | 0xff20, base | 0xff21).rw("dma:0", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w)); map(base | 0xff22, base | 0xff23).rw("dma:0", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w)); map(base | 0xff24, base | 0xff25).rw("dma:0", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w)); + map(base | 0xff26, base | 0xff26).rw("dma:0", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w)); map(base | 0xff27, base | 0xff27).rw("dma:0", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w)); map(base | 0xff28, base | 0xff29).rw("dma:0", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w)); map(base | 0xff2a, base | 0xff2b).rw("dma:0", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w)); map(base | 0xff2c, base | 0xff2d).rw("dma:0", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w)); + map(base | 0xff2e, base | 0xff2e).rw("dma:0", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w)); map(base | 0xff2f, base | 0xff2f).rw("dma:0", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w)); map(base | 0xff30, base | 0xff31).rw("dma:1", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w)); map(base | 0xff32, base | 0xff33).rw("dma:1", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w)); map(base | 0xff34, base | 0xff35).rw("dma:1", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w)); + map(base | 0xff36, base | 0xff36).rw("dma:1", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w)); map(base | 0xff37, base | 0xff37).rw("dma:1", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w)); map(base | 0xff38, base | 0xff39).rw("dma:1", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w)); map(base | 0xff3a, base | 0xff3b).rw("dma:1", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w)); map(base | 0xff3c, base | 0xff3d).rw("dma:1", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w)); + map(base | 0xff3e, base | 0xff3e).rw("dma:1", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w)); map(base | 0xff3f, base | 0xff3f).rw("dma:1", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w)); map(base | 0xff40, base | 0xff41).rw("dma:2", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w)); map(base | 0xff42, base | 0xff43).rw("dma:2", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w)); map(base | 0xff44, base | 0xff45).rw("dma:2", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w)); + map(base | 0xff46, base | 0xff46).rw("dma:2", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w)); map(base | 0xff47, base | 0xff47).rw("dma:2", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w)); map(base | 0xff48, base | 0xff49).rw("dma:2", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w)); map(base | 0xff4a, base | 0xff4b).rw("dma:2", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w)); map(base | 0xff4c, base | 0xff4d).rw("dma:2", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w)); + map(base | 0xff4e, base | 0xff4e).rw("dma:2", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w)); map(base | 0xff4f, base | 0xff4f).rw("dma:2", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w)); map(base | 0xff50, base | 0xff51).rw("dma:3", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w)); map(base | 0xff52, base | 0xff53).rw("dma:3", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w)); map(base | 0xff54, base | 0xff55).rw("dma:3", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w)); + map(base | 0xff56, base | 0xff56).rw("dma:3", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w)); map(base | 0xff57, base | 0xff57).rw("dma:3", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w)); map(base | 0xff60, base | 0xff60).rw("timer16", FUNC(h8_timer16_device::tstr_r), FUNC(h8_timer16_device::tstr_w)); diff --git a/src/devices/cpu/h8/h8_dma.cpp b/src/devices/cpu/h8/h8_dma.cpp index 7687de7a68d..d70cced09f3 100644 --- a/src/devices/cpu/h8/h8_dma.cpp +++ b/src/devices/cpu/h8/h8_dma.cpp @@ -15,6 +15,10 @@ void h8_dma_device::device_start() { dmach0->set_id(0<<1); dmach1->set_id(1<<1); + + save_item(NAME(dmabcr)); + save_item(NAME(dmawer)); + save_item(NAME(dreq)); } void h8_dma_device::device_reset() @@ -146,6 +150,25 @@ void h8_dma_channel_device::set_info(const char *_intc, int _irq_base, int v0, i void h8_dma_channel_device::device_start() { + save_item(STRUCT_MEMBER(state, source)); + save_item(STRUCT_MEMBER(state, dest)); + save_item(STRUCT_MEMBER(state, incs)); + save_item(STRUCT_MEMBER(state, incd)); + save_item(STRUCT_MEMBER(state, count)); + save_item(STRUCT_MEMBER(state, id)); + save_item(STRUCT_MEMBER(state, autoreq)); + save_item(STRUCT_MEMBER(state, suspended)); + save_item(STRUCT_MEMBER(state, mode_16)); + save_item(NAME(mar)); + save_item(NAME(ioar)); + save_item(NAME(etcr)); + save_item(NAME(dmacr)); + save_item(NAME(dtcr)); + save_item(NAME(dta)); + save_item(NAME(dte)); + save_item(NAME(dtie)); + save_item(NAME(fae)); + save_item(NAME(sae)); } void h8_dma_channel_device::device_reset() @@ -192,16 +215,26 @@ void h8_dma_channel_device::maral_w(offs_t offset, uint16_t data, uint16_t mem_m uint16_t h8_dma_channel_device::ioara_r() { - logerror("iorar_r %04x\n", ioar[0]); return ioar[0]; } +uint8_t h8_dma_channel_device::ioara8_r() +{ + return ioar[0] & 0x00ff; +} + void h8_dma_channel_device::ioara_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&ioar[0]); logerror("ioara_w %04x\n", ioar[0]); } +void h8_dma_channel_device::ioara8_w(uint8_t data) +{ + ioar[0] = data | 0xff00; + logerror("ioara_w %04x\n", ioar[0]); +} + uint16_t h8_dma_channel_device::etcra_r() { logerror("etcra_r %04x\n", etcr[0]); @@ -241,16 +274,26 @@ void h8_dma_channel_device::marbl_w(offs_t offset, uint16_t data, uint16_t mem_m uint16_t h8_dma_channel_device::ioarb_r() { - logerror("ioarb_r %04x\n", ioar[1]); return ioar[1]; } +uint8_t h8_dma_channel_device::ioarb8_r() +{ + return ioar[1] & 0x00ff; +} + void h8_dma_channel_device::ioarb_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&ioar[1]); logerror("ioarb_w %04x\n", ioar[1]); } +void h8_dma_channel_device::ioarb8_w(uint8_t data) +{ + ioar[1] = data | 0xff00; + logerror("ioarb_w %04x\n", ioar[1]); +} + uint16_t h8_dma_channel_device::etcrb_r() { logerror("etcrb_r %04x\n", etcr[1]); @@ -312,35 +355,60 @@ void h8_dma_channel_device::h8h_sync() // update DMACR dmacr = 0; if(BIT(dtcr[0], 6)) dmacr |= 1 << 15; // DTSZ - dmacr |= ((dtcr[0] & 0b110000) >> 4) << 13; // SAID, SAIDE - if(BIT(dtcr[0], 0)) dmacr |= 1 << 11; // BLKE - if(BIT(dtcr[1], 3)) dmacr |= 1 << 12; // BLKDIR (TMS) - dmacr |= ((dtcr[1] & 0b110000) >> 4) << 5; // DAID, DAIDE - if(BIT(dmacr, 11)) { - // Block Transfer Mode - switch(dtcr[1] & 0b111) { // DTS - case 0b000: dmacr |= 0b1000; break; // ITU channel 0 - case 0b001: dmacr |= 0b1001; break; // ITU channel 1 - case 0b010: dmacr |= 0b1010; break; // ITU channel 2 - case 0b011: dmacr |= 0b1011; break; // ITU channel 3 - case 0b110: dmacr |= 0b1000; break; // DREQ falling edge + dmacr |= ((dtcr[0] & 0b110000) >> 4) << 13; // SAID/DTID, SAIDE/RPE + dmacr |= ((dtcr[1] & 0b110000) >> 4) << 5; // DAID/DTID, DAIDE/RPE + + uint8_t _dte = 0; + if(BIT(dtcr[0], 7)) _dte |= 0b01; // DTE + if(BIT(dtcr[1], 7)) _dte |= 0b10; // DTME/DTE + + bool _fae = (dtcr[0] & 0b110) == 0b110; // A channel operates in full address mode when DTS2A and DTS1A are both set to 1. + bool _sae = false; // don't support + uint8_t _dta = 0; // don't support + uint8_t _dtie = 0; + if(_fae) { + // Full address mode + if(BIT(dtcr[0], 3)) _dtie = 0b11; + if(BIT(dtcr[0], 0)) { + // Block Transfer Mode + dmacr |= 1 << 11; // BLKE + if(BIT(dtcr[1], 3)) dmacr |= 1 << 12; // BLKDIR (TMS) + switch(dtcr[1] & 0b111) { // DTP (DTS) + case 0b000: dmacr |= 0b1000; break; // ITU channel 0 + case 0b001: dmacr |= 0b1001; break; // ITU channel 1 + case 0b010: dmacr |= 0b1010; break; // ITU channel 2 + case 0b011: dmacr |= 0b1011; break; // ITU channel 3 + case 0b110: dmacr |= 0b1000; break; // DREQ falling edge + } + } else { + // Normal Mode + switch(dtcr[1] & 0b111) { // DTP (DTS) + case 0b000: dmacr |= 0b0111; break; // Auto-request (burst mode) + case 0b010: dmacr |= 0b0110; break; // Auto-request (cycle-steal mode) + case 0b110: dmacr |= 0b0010; break; // DREQ falling edge + case 0b111: dmacr |= 0b0011; break; // DREQ low-level + } } } else { - // Normal Mode - switch(dtcr[1] & 0b111) { // DTS - case 0b000: dmacr |= 0b0111; break; // Auto-request (burst mode) - case 0b010: dmacr |= 0b0110; break; // Auto-request (cycle-steal mode) - case 0b110: dmacr |= 0b0010; break; // DREQ falling edge - case 0b111: dmacr |= 0b0011; break; // DREQ low-level + // Short address mode + if(BIT(dtcr[0], 3)) _dtie |= 0b01; + if(BIT(dtcr[1], 3)) _dtie |= 0b10; + for(int submodule = 0; submodule < 2; submodule++) { + switch(dtcr[submodule] & 0b111) { // DTP, DTDIR (DTS) + case 0b000: dmacr |= 0b01000 << (submodule ? 0 : 8); break; // ITU channel 0 + case 0b001: dmacr |= 0b01001 << (submodule ? 0 : 8); break; // ITU channel 1 + case 0b010: dmacr |= 0b01010 << (submodule ? 0 : 8); break; // ITU channel 2 + case 0b011: dmacr |= 0b01011 << (submodule ? 0 : 8); break; // ITU channel 3 + //case 0b011: dmacr |= 0b10001 << (submodule ? 0 : 8); break; // A/D converter conversion end (H8/3006) + case 0b100: dmacr |= 0b00100 << (submodule ? 0 : 8); break; // SCI channel 0 transmission data empty + case 0b101: dmacr |= 0b10101 << (submodule ? 0 : 8); break; // SCI channel 0 receive data full + case 0b110: dmacr |= 0b00010 << (submodule ? 0 : 8); break; // DREQ falling edge (B only) + case 0b111: dmacr |= 0b00011 << (submodule ? 0 : 8); break; // DREQ low-level (B only) + } } } - // set_bcr - bool _fae = (dtcr[0] & 0b110) == 0b110; // A channel operates in full address mode when DTS2A and DTS1A are both set to 1. - uint8_t _dta = 0; // don't support - uint8_t _dte = BIT(dtcr[0], 7) ? 0b11 : 0b00; - uint8_t _dtie = BIT(dtcr[0], 3) ? 0b11 : 0b00; - set_bcr(_fae, !_fae, _dta, _dte, _dtie); + set_bcr(_fae, _sae, _dta, _dte, _dtie); start_test(-1); } @@ -382,7 +450,21 @@ bool h8_dma_channel_device::start_test(int vector) if(dte == 0) return false; - throw emu_fatalerror("%s: DMA startup test in short address mode unimplemented.\n", tag()); + if(vector == -1) { + // A has priority over B + if(dte & 2) + start(1); + if(dte & 1) + start(0); + return true; + } else if(dte & 2) { + // DREQ trigger (B only) + if(((dmacr & 0b111) == 0b0010 && vector == DREQ_EDGE) || ((dmacr & 0b111) == 0b0011 && vector == DREQ_LEVEL)) { + state[1].suspended = false; + return true; + } + } + return false; } } @@ -404,7 +486,35 @@ void h8_dma_channel_device::start(int submodule) cpu->set_current_dma(state + submodule); } } else { - throw emu_fatalerror("%s: DMA start in short address mode unimplemented.\n", tag()); + uint8_t cr = submodule ? dmacr & 0x00ff : dmacr >> 8; + state[submodule].mode_16 = cr & 0x80; + state[submodule].autoreq = false; + state[submodule].suspended = true; + int32_t step = state[submodule].mode_16 ? 2 : 1; + if(!(cr & 0x20)) { + // Sequential mode + state[submodule].count = etcr[submodule] ? etcr[submodule] : 0x10000; + state[submodule].incs = cr & 0x40 ? -step : step; + } else if(dtie & (1 << submodule)) { + // Idle mode + state[submodule].count = etcr[submodule] ? etcr[submodule] : 0x10000; + state[submodule].incs = 0; + } else { + // Repeat mode + state[submodule].count = etcr[submodule] & 0x00ff ? etcr[submodule] & 0x00ff : 0x100; + state[submodule].incs = cr & 0x40 ? -step : step; + } + if(cr & 0x10) { + state[submodule].source = 0xff0000 | ioar[submodule]; + state[submodule].dest = mar[submodule]; + state[submodule].incd = state[submodule].incs; + state[submodule].incs = 0; + } else { + state[submodule].source = mar[submodule]; + state[submodule].dest = 0xff0000 | ioar[submodule]; + state[submodule].incd = 0; + } + cpu->set_current_dma(state + submodule); } } @@ -431,6 +541,20 @@ void h8_dma_channel_device::count_done(int submodule) throw emu_fatalerror("%s: DMA end-of-transfer interrupt in full address/normal mode unimplemented.\n", tag()); } } else { - throw emu_fatalerror("%s: DMA count done in short address mode unimplemented.\n", tag()); + uint8_t cr = submodule ? dmacr & 0x00ff : dmacr >> 8; + if((cr & 0x20) && !(dtie & (1 << submodule))) { + // Repeat mode + state[submodule].count = etcr[submodule] & 0x00ff ? etcr[submodule] & 0x00ff : 0x100; + if(cr & 0x10) + state[submodule].dest = mar[submodule]; + else + state[submodule].source = mar[submodule]; + } else { + dte &= ~(1 << submodule); + dmac->clear_dte(state[0].id + submodule); + dtcr[submodule] &= ~0x80; // clear DTE (for H8H) + if(dtie & (1 << submodule)) + throw emu_fatalerror("%s: DMA end-of-transfer interrupt in short address mode unimplemented.\n", tag()); + } } } diff --git a/src/devices/cpu/h8/h8_dma.h b/src/devices/cpu/h8/h8_dma.h index 72d33105349..4a4eeda837b 100644 --- a/src/devices/cpu/h8/h8_dma.h +++ b/src/devices/cpu/h8/h8_dma.h @@ -109,7 +109,9 @@ public: uint16_t maral_r(); void maral_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); uint16_t ioara_r(); + uint8_t ioara8_r(); void ioara_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void ioara8_w(uint8_t data); uint16_t etcra_r(); void etcra_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); uint16_t marbh_r(); @@ -117,7 +119,9 @@ public: uint16_t marbl_r(); void marbl_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); uint16_t ioarb_r(); + uint8_t ioarb8_r(); void ioarb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void ioarb8_w(uint8_t data); uint16_t etcrb_r(); void etcrb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); uint16_t dmacr_r(); -- cgit v1.2.3