mirror of
https://github.com/holub/mame
synced 2025-04-26 02:07:14 +03:00
Fixed h8 instruction eepmov.b (used r4h instead of r4l) (#2253)
Added support for non-autorequest DMA (DREQ edge, DREQ level) in h8 Added support for H8/300H to h8_dma (previously only H8/300S supported) Added DMA channels to H8/3002 Added RTMCSR register to H8/3002
This commit is contained in:
parent
2a1cc17f33
commit
19823bab94
@ -145,9 +145,9 @@ void h8_device::set_current_dma(h8_dma_state *state)
|
||||
if(!state)
|
||||
logerror("DMA done\n");
|
||||
else
|
||||
logerror("New current dma s=%x d=%x is=%d id=%d count=%x m=%d\n",
|
||||
logerror("New current dma s=%x d=%x is=%d id=%d count=%x m=%d autoreq=%d\n",
|
||||
state->source, state->dest, state->incs, state->incd,
|
||||
state->count, state->mode_16 ? 16 : 8);
|
||||
state->count, state->mode_16 ? 16 : 8, state->autoreq);
|
||||
|
||||
}
|
||||
|
||||
@ -620,7 +620,7 @@ void h8_device::prefetch_done()
|
||||
if(requested_state != -1) {
|
||||
inst_state = requested_state;
|
||||
requested_state = -1;
|
||||
} else if(current_dma)
|
||||
} else if(current_dma && !current_dma->suspended)
|
||||
inst_state = STATE_DMA;
|
||||
else if(current_dtc)
|
||||
inst_state = STATE_DTC;
|
||||
|
@ -176,6 +176,8 @@ macro jsr32 %opc %spreg
|
||||
prefetch_noirq();
|
||||
|
||||
10003 dma
|
||||
if(current_dma->count == 1)
|
||||
dma_device->count_last(current_dma->id);
|
||||
if(current_dma->mode_16) {
|
||||
TMP1 = read16(current_dma->source);
|
||||
write16(current_dma->dest, TMP1);
|
||||
@ -186,6 +188,8 @@ macro jsr32 %opc %spreg
|
||||
current_dma->source += current_dma->incs;
|
||||
current_dma->dest += current_dma->incd;
|
||||
current_dma->count--;
|
||||
if(!current_dma->autoreq)
|
||||
current_dma->suspended = true;
|
||||
if(!current_dma->count) {
|
||||
uint8_t id = current_dma->id;
|
||||
current_dma = nullptr;
|
||||
@ -2441,22 +2445,22 @@ macro jsr32 %opc %spreg
|
||||
prefetch();
|
||||
|
||||
7b5c598f ffffffff 0 eepmov.b - - o
|
||||
while(r8_r(4)) {
|
||||
while(r8_r(4+8)) {
|
||||
TMP1 = read8(r16_r(5));
|
||||
write8(r16_r(6), TMP1);
|
||||
r16_w(5, r16_r(5)+1);
|
||||
r16_w(6, r16_r(6)+1);
|
||||
r8_w(4, r8_r(4)-1);
|
||||
r8_w(4+8, r8_r(4+8)-1);
|
||||
}
|
||||
prefetch();
|
||||
|
||||
7b5c598f ffffffff 0 eepmov.b - - h
|
||||
while(r8_r(4)) {
|
||||
while(r8_r(4+8)) {
|
||||
TMP1 = read8(r32_r(5));
|
||||
write8(r32_r(6), TMP1);
|
||||
r32_w(5, r32_r(5)+1);
|
||||
r32_w(6, r32_r(6)+1);
|
||||
r8_w(4, r8_r(4)-1);
|
||||
r8_w(4+8, r8_r(4+8)-1);
|
||||
}
|
||||
prefetch();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
// copyright-holders:Olivier Galibert
|
||||
#include "emu.h"
|
||||
#include "h83002.h"
|
||||
|
||||
@ -9,6 +9,9 @@ h83002_device::h83002_device(const machine_config &mconfig, const char *tag, dev
|
||||
h8h_device(mconfig, H83002, "H8/3002", tag, owner, clock, "h83002", __FILE__, address_map_delegate(FUNC(h83002_device::map), this)),
|
||||
intc(*this, "intc"),
|
||||
adc(*this, "adc"),
|
||||
dma(*this, "dma"),
|
||||
dma0(*this, "dma:0"),
|
||||
dma1(*this, "dma:1"),
|
||||
port4(*this, "port4"),
|
||||
port6(*this, "port6"),
|
||||
port7(*this, "port7"),
|
||||
@ -24,7 +27,9 @@ h83002_device::h83002_device(const machine_config &mconfig, const char *tag, dev
|
||||
timer16_4(*this, "timer16:4"),
|
||||
sci0(*this, "sci0"),
|
||||
sci1(*this, "sci1"),
|
||||
watchdog(*this, "watchdog")
|
||||
watchdog(*this, "watchdog"),
|
||||
tend0_cb(*this),
|
||||
tend1_cb(*this)
|
||||
{
|
||||
syscr = 0;
|
||||
}
|
||||
@ -32,6 +37,10 @@ h83002_device::h83002_device(const machine_config &mconfig, const char *tag, dev
|
||||
static MACHINE_CONFIG_FRAGMENT(h83002)
|
||||
MCFG_H8H_INTC_ADD("intc")
|
||||
MCFG_H8_ADC_3337_ADD("adc", "intc", 60)
|
||||
MCFG_H8_DMA_ADD("dma")
|
||||
// (H8/2002.pdf) Table 8-11 DMAC Activation Sources
|
||||
MCFG_H8_DMA_CHANNEL_ADD("dma:0", "intc", 44, h8_dma_channel_device::NONE, 24, h8_dma_channel_device::DREQ_EDGE, h8_dma_channel_device::DREQ_LEVEL, 28, 32, 36, 54, 53, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE)
|
||||
MCFG_H8_DMA_CHANNEL_ADD("dma:1", "intc", 46, h8_dma_channel_device::NONE, 24, h8_dma_channel_device::DREQ_EDGE, h8_dma_channel_device::DREQ_LEVEL, 28, 32, 36, 54, 53, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE, h8_dma_channel_device::NONE)
|
||||
MCFG_H8_PORT_ADD("port4", h8_device::PORT_4, 0x00, 0x00)
|
||||
MCFG_H8_PORT_ADD("port6", h8_device::PORT_6, 0x80, 0x80)
|
||||
MCFG_H8_PORT_ADD("port7", h8_device::PORT_7, 0x00, 0x00)
|
||||
@ -53,6 +62,24 @@ MACHINE_CONFIG_END
|
||||
DEVICE_ADDRESS_MAP_START(map, 16, h83002_device)
|
||||
AM_RANGE(0xfffd10, 0xffff0f) AM_RAM
|
||||
|
||||
// DMA: only full address mode supported
|
||||
AM_RANGE(0xffff20, 0xffff21) AM_DEVREADWRITE( "dma:0", h8_dma_channel_device, marah_r, marah_w )
|
||||
AM_RANGE(0xffff22, 0xffff23) AM_DEVREADWRITE( "dma:0", h8_dma_channel_device, maral_r, maral_w )
|
||||
AM_RANGE(0xffff24, 0xffff25) AM_DEVREADWRITE( "dma:0", h8_dma_channel_device, etcra_r, etcra_w )
|
||||
AM_RANGE(0xffff26, 0xffff27) AM_DEVREADWRITE8("dma:0", h8_dma_channel_device, dtcra_r, dtcra_w, 0x00ff )
|
||||
AM_RANGE(0xffff28, 0xffff29) AM_DEVREADWRITE( "dma:0", h8_dma_channel_device, marbh_r, marbh_w )
|
||||
AM_RANGE(0xffff2a, 0xffff2b) AM_DEVREADWRITE( "dma:0", h8_dma_channel_device, marbl_r, marbl_w )
|
||||
AM_RANGE(0xffff2c, 0xffff2d) AM_DEVREADWRITE( "dma:0", h8_dma_channel_device, etcrb_r, etcrb_w )
|
||||
AM_RANGE(0xffff2e, 0xffff2f) AM_DEVREADWRITE8("dma:0", h8_dma_channel_device, dtcrb_r, dtcrb_w, 0x00ff )
|
||||
AM_RANGE(0xffff30, 0xffff31) AM_DEVREADWRITE( "dma:1", h8_dma_channel_device, marah_r, marah_w )
|
||||
AM_RANGE(0xffff32, 0xffff33) AM_DEVREADWRITE( "dma:1", h8_dma_channel_device, maral_r, maral_w )
|
||||
AM_RANGE(0xffff34, 0xffff35) AM_DEVREADWRITE( "dma:1", h8_dma_channel_device, etcra_r, etcra_w )
|
||||
AM_RANGE(0xffff36, 0xffff37) AM_DEVREADWRITE8("dma:1", h8_dma_channel_device, dtcra_r, dtcra_w, 0x00ff )
|
||||
AM_RANGE(0xffff38, 0xffff39) AM_DEVREADWRITE( "dma:1", h8_dma_channel_device, marbh_r, marbh_w )
|
||||
AM_RANGE(0xffff3a, 0xffff3b) AM_DEVREADWRITE( "dma:1", h8_dma_channel_device, marbl_r, marbl_w )
|
||||
AM_RANGE(0xffff3c, 0xffff3d) AM_DEVREADWRITE( "dma:1", h8_dma_channel_device, etcrb_r, etcrb_w )
|
||||
AM_RANGE(0xffff3e, 0xffff3f) AM_DEVREADWRITE8("dma:1", h8_dma_channel_device, dtcrb_r, dtcrb_w, 0x00ff )
|
||||
|
||||
AM_RANGE(0xffff60, 0xffff61) AM_DEVREADWRITE8("timer16", h8_timer16_device, tstr_r, tstr_w, 0xff00)
|
||||
AM_RANGE(0xffff60, 0xffff61) AM_DEVREADWRITE8("timer16", h8_timer16_device, tsyr_r, tsyr_w, 0x00ff)
|
||||
AM_RANGE(0xffff62, 0xffff63) AM_DEVREADWRITE8("timer16", h8_timer16_device, tmdr_r, tmdr_w, 0xff00)
|
||||
@ -94,6 +121,7 @@ DEVICE_ADDRESS_MAP_START(map, 16, h83002_device)
|
||||
|
||||
AM_RANGE(0xffffa8, 0xffffa9) AM_DEVREADWRITE( "watchdog", h8_watchdog_device, wd_r, wd_w )
|
||||
AM_RANGE(0xffffaa, 0xffffab) AM_DEVREADWRITE( "watchdog", h8_watchdog_device, rst_r, rst_w )
|
||||
AM_RANGE(0xffffac, 0xffffad) AM_READWRITE8( rtmcsr_r,rtmcsr_w,0x00ff)
|
||||
|
||||
AM_RANGE(0xffffb0, 0xffffb1) AM_DEVREADWRITE8("sci0", h8_sci_device, smr_r, smr_w, 0xff00)
|
||||
AM_RANGE(0xffffb0, 0xffffb1) AM_DEVREADWRITE8("sci0", h8_sci_device, brr_r, brr_w, 0x00ff)
|
||||
@ -140,7 +168,14 @@ machine_config_constructor h83002_device::device_mconfig_additions() const
|
||||
|
||||
void h83002_device::execute_set_input(int inputnum, int state)
|
||||
{
|
||||
intc->set_input(inputnum, state);
|
||||
if(inputnum == H8_INPUT_LINE_TEND0 && !tend0_cb.isnull())
|
||||
tend0_cb(state);
|
||||
else if(inputnum == H8_INPUT_LINE_TEND1 && !tend1_cb.isnull())
|
||||
tend1_cb(state);
|
||||
else if(inputnum >= H8_INPUT_LINE_DREQ0 && inputnum <= H8_INPUT_LINE_DREQ3)
|
||||
dma->set_input(inputnum, state);
|
||||
else
|
||||
intc->set_input(inputnum, state);
|
||||
}
|
||||
|
||||
int h83002_device::trapa_setup()
|
||||
@ -205,6 +240,10 @@ void h83002_device::internal_update(uint64_t current_time)
|
||||
void h83002_device::device_start()
|
||||
{
|
||||
h8h_device::device_start();
|
||||
dma_device = dma;
|
||||
|
||||
tend0_cb.resolve();
|
||||
tend1_cb.resolve();
|
||||
}
|
||||
|
||||
void h83002_device::device_reset()
|
||||
@ -224,3 +263,15 @@ WRITE8_MEMBER(h83002_device::syscr_w)
|
||||
update_irq_filter();
|
||||
logerror("syscr = %02x\n", data);
|
||||
}
|
||||
|
||||
READ8_MEMBER(h83002_device::rtmcsr_r)
|
||||
{
|
||||
// set bit 7 -- Compare Match Flag (CMF): This status flag indicates that the RTCNT and RTCOR values have matched.
|
||||
return rtmcsr | 0x80;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(h83002_device::rtmcsr_w)
|
||||
{
|
||||
rtmcsr = data;
|
||||
logerror("rtmcsr = %02x\n", data);
|
||||
}
|
||||
|
@ -16,22 +16,37 @@
|
||||
|
||||
#include "h8h.h"
|
||||
#include "h8_adc.h"
|
||||
#include "h8_dma.h"
|
||||
#include "h8_port.h"
|
||||
#include "h8_intc.h"
|
||||
#include "h8_timer16.h"
|
||||
#include "h8_sci.h"
|
||||
#include "h8_watchdog.h"
|
||||
|
||||
#define MCFG_H83002_TEND0_CALLBACK(_devcb) \
|
||||
devcb = &h83002_device::set_tend0_callback(*device, DEVCB_##_devcb);
|
||||
#define MCFG_H83002_TEND1_CALLBACK(_devcb) \
|
||||
devcb = &h83002_device::set_tend1_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
class h83002_device : public h8h_device {
|
||||
public:
|
||||
h83002_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
template<class _Object> static devcb_base &set_tend0_callback(device_t &device, _Object object) { return downcast<h83002_device&>(device).tend0_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_tend1_callback(device_t &device, _Object object) { return downcast<h83002_device&>(device).tend1_cb.set_callback(object); }
|
||||
|
||||
DECLARE_READ8_MEMBER(syscr_r);
|
||||
DECLARE_WRITE8_MEMBER(syscr_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(rtmcsr_r);
|
||||
DECLARE_WRITE8_MEMBER(rtmcsr_w);
|
||||
|
||||
protected:
|
||||
required_device<h8h_intc_device> intc;
|
||||
required_device<h8_adc_device> adc;
|
||||
optional_device<h8_dma_device> dma;
|
||||
optional_device<h8_dma_channel_device> dma0;
|
||||
optional_device<h8_dma_channel_device> dma1;
|
||||
required_device<h8_port_device> port4;
|
||||
required_device<h8_port_device> port6;
|
||||
required_device<h8_port_device> port7;
|
||||
@ -50,6 +65,9 @@ protected:
|
||||
required_device<h8_watchdog_device> watchdog;
|
||||
|
||||
uint8_t syscr;
|
||||
uint8_t rtmcsr;
|
||||
|
||||
devcb_write_line tend0_cb, tend1_cb;
|
||||
|
||||
virtual void update_irq_filter() override;
|
||||
virtual void interrupt_taken() override;
|
||||
|
@ -21,6 +21,7 @@ void h8_dma_device::device_reset()
|
||||
{
|
||||
dmabcr = 0x0000;
|
||||
dmawer = 0x00;
|
||||
dreq[0] = dreq[1] = false;
|
||||
}
|
||||
|
||||
bool h8_dma_device::trigger_dma(int vector)
|
||||
@ -32,6 +33,14 @@ bool h8_dma_device::trigger_dma(int vector)
|
||||
return start0 || start1;
|
||||
}
|
||||
|
||||
void h8_dma_device::count_last(int id)
|
||||
{
|
||||
if(id & 2)
|
||||
dmach1->count_last(id & 1);
|
||||
else
|
||||
dmach0->count_last(id & 1);
|
||||
}
|
||||
|
||||
void h8_dma_device::count_done(int id)
|
||||
{
|
||||
if(id & 2)
|
||||
@ -45,6 +54,26 @@ void h8_dma_device::clear_dte(int id)
|
||||
dmabcr &= ~(0x0010 << id);
|
||||
}
|
||||
|
||||
void h8_dma_device::set_input(int inputnum, int state)
|
||||
{
|
||||
if(inputnum == H8_INPUT_LINE_DREQ0) {
|
||||
if(state == ASSERT_LINE) {
|
||||
dmach0->start_test(h8_dma_channel_device::DREQ_LEVEL);
|
||||
if(!dreq[0])
|
||||
dmach0->start_test(h8_dma_channel_device::DREQ_EDGE);
|
||||
}
|
||||
dreq[0] = (state == ASSERT_LINE);
|
||||
} else if(inputnum == H8_INPUT_LINE_DREQ1) {
|
||||
if(state == ASSERT_LINE) {
|
||||
dmach1->start_test(h8_dma_channel_device::DREQ_LEVEL);
|
||||
if(!dreq[1])
|
||||
dmach1->start_test(h8_dma_channel_device::DREQ_EDGE);
|
||||
}
|
||||
dreq[1] = (state == ASSERT_LINE);
|
||||
} else
|
||||
logerror("input line %d not supported for h8_dma_device\n", inputnum);
|
||||
}
|
||||
|
||||
READ8_MEMBER(h8_dma_device::dmawer_r)
|
||||
{
|
||||
logerror("dmawer_r %02x\n", dmawer);
|
||||
@ -133,7 +162,6 @@ void h8_dma_channel_device::set_id(int id)
|
||||
{
|
||||
state[0].id = id;
|
||||
state[1].id = id | 1;
|
||||
|
||||
}
|
||||
|
||||
READ16_MEMBER(h8_dma_channel_device::marah_r)
|
||||
@ -247,6 +275,75 @@ WRITE16_MEMBER(h8_dma_channel_device::dmacr_w)
|
||||
start_test(-1);
|
||||
}
|
||||
|
||||
// H8H DMA
|
||||
READ8_MEMBER(h8_dma_channel_device::dtcra_r)
|
||||
{
|
||||
logerror("dtcra_r %02x\n", dtcr[0]);
|
||||
return dtcr[0];
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(h8_dma_channel_device::dtcra_w)
|
||||
{
|
||||
dtcr[0] = data;
|
||||
logerror("dtcra_w %02x\n", dtcr[0]);
|
||||
if((dtcr[0] & 0x80) && (dtcr[1] & 0x80)) { // if both DTME and DTE are set, start DMA
|
||||
h8h_sync();
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(h8_dma_channel_device::dtcrb_r)
|
||||
{
|
||||
logerror("dtcrb_r %02x\n", dtcr[1]);
|
||||
return dtcr[1];
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(h8_dma_channel_device::dtcrb_w)
|
||||
{
|
||||
dtcr[1] = data;
|
||||
logerror("dtcrb_w %02x\n", dtcr[1]);
|
||||
if((dtcr[0] & 0x80) && (dtcr[1] & 0x80)) { // if both DTME and DTE are set, start DMA
|
||||
h8h_sync();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
start_test(-1);
|
||||
}
|
||||
|
||||
void h8_dma_channel_device::set_bcr(bool _fae, bool _sae, uint8_t _dta, uint8_t _dte, uint8_t _dtie)
|
||||
{
|
||||
fae = _fae;
|
||||
@ -267,11 +364,18 @@ bool h8_dma_channel_device::start_test(int vector)
|
||||
if(dmacr & 0x0800)
|
||||
throw emu_fatalerror("%s: DMA startup test in full address/block mode unimplemented.\n", tag());
|
||||
else {
|
||||
if((dmacr & 0x0006) == 0x0006) {
|
||||
// Normal Mode
|
||||
if(vector == -1) {
|
||||
start(0);
|
||||
return true;
|
||||
} else
|
||||
throw emu_fatalerror("%s: DMA startup test in full address/normal mode/dreq unimplemented.\n", tag());
|
||||
} else {
|
||||
// DREQ trigger
|
||||
if(((dmacr & 0b111) == 0b0010 && vector == DREQ_EDGE) || ((dmacr & 0b111) == 0b0011 && vector == DREQ_LEVEL)) {
|
||||
state[0].suspended = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(dte == 0)
|
||||
@ -291,6 +395,8 @@ void h8_dma_channel_device::start(int submodule)
|
||||
state[submodule].dest = mar[1];
|
||||
state[submodule].count = etcr[0] ? etcr[0] : 0x10000;
|
||||
state[submodule].mode_16 = dmacr & 0x8000;
|
||||
state[submodule].autoreq = (dmacr & 6) == 6;
|
||||
state[submodule].suspended = !state[submodule].autoreq; // non-auto-request transfers start suspended
|
||||
int32_t step = state[submodule].mode_16 ? 2 : 1;
|
||||
state[submodule].incs = dmacr & 0x2000 ? dmacr & 0x4000 ? -step : step : 0;
|
||||
state[submodule].incd = dmacr & 0x0020 ? dmacr & 0x0040 ? -step : step : 0;
|
||||
@ -301,16 +407,25 @@ void h8_dma_channel_device::start(int submodule)
|
||||
}
|
||||
}
|
||||
|
||||
void h8_dma_channel_device::count_last(int submodule)
|
||||
{
|
||||
logerror("count last on %d\n", submodule);
|
||||
if(!state[submodule].autoreq) // "The TEND signal goes low during the last write cycle."
|
||||
cpu->set_input_line(H8_INPUT_LINE_TEND0 + (state[submodule].id >> 1), ASSERT_LINE);
|
||||
}
|
||||
|
||||
void h8_dma_channel_device::count_done(int submodule)
|
||||
{
|
||||
logerror("count done on %d\n", submodule);
|
||||
if(!state[submodule].autoreq)
|
||||
cpu->set_input_line(H8_INPUT_LINE_TEND0 + (state[submodule].id >> 1), CLEAR_LINE);
|
||||
if(fae) {
|
||||
if(dmacr & 0x0800)
|
||||
throw emu_fatalerror("%s: DMA count done full address/block mode unimplemented.\n", tag());
|
||||
else {
|
||||
dte &= ~1;
|
||||
dmac->clear_dte(state[0].id);
|
||||
dtcr[0] &= ~0x80; // clear DTE (for H8H)
|
||||
if(dtie & 1)
|
||||
throw emu_fatalerror("%s: DMA end-of-transfer interrupt in full address/normal mode unimplemented.\n", tag());
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ struct h8_dma_state {
|
||||
int32_t incs, incd;
|
||||
uint32_t count;
|
||||
int id;
|
||||
bool autoreq; // activate by auto-request
|
||||
bool suspended;
|
||||
bool mode_16;
|
||||
};
|
||||
|
||||
@ -31,6 +33,19 @@ struct h8_dma_state {
|
||||
|
||||
class h8_dma_channel_device;
|
||||
|
||||
enum {
|
||||
// mind the order, all DREQ, TEND need to be sequential
|
||||
H8_INPUT_LINE_DREQ0 = INPUT_LINE_IRQ9 + 1,
|
||||
H8_INPUT_LINE_DREQ1,
|
||||
H8_INPUT_LINE_DREQ2,
|
||||
H8_INPUT_LINE_DREQ3,
|
||||
|
||||
H8_INPUT_LINE_TEND0,
|
||||
H8_INPUT_LINE_TEND1,
|
||||
H8_INPUT_LINE_TEND2,
|
||||
H8_INPUT_LINE_TEND3,
|
||||
};
|
||||
|
||||
class h8_dma_device : public device_t {
|
||||
public:
|
||||
h8_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
@ -43,15 +58,20 @@ public:
|
||||
DECLARE_WRITE16_MEMBER(dmabcr_w);
|
||||
|
||||
bool trigger_dma(int vector);
|
||||
void count_last(int id);
|
||||
void count_done(int id);
|
||||
void clear_dte(int id);
|
||||
|
||||
void set_input(int inputnum, int state);
|
||||
|
||||
protected:
|
||||
required_device<h8_dma_channel_device> dmach0, dmach1;
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
bool dreq[2];
|
||||
|
||||
uint8_t dmawer, dmatcr;
|
||||
uint16_t dmabcr;
|
||||
};
|
||||
@ -96,9 +116,16 @@ public:
|
||||
DECLARE_READ16_MEMBER(dmacr_r);
|
||||
DECLARE_WRITE16_MEMBER(dmacr_w);
|
||||
|
||||
// H8H DMA
|
||||
DECLARE_READ8_MEMBER(dtcra_r);
|
||||
DECLARE_WRITE8_MEMBER(dtcra_w);
|
||||
DECLARE_READ8_MEMBER(dtcrb_r);
|
||||
DECLARE_WRITE8_MEMBER(dtcrb_w);
|
||||
|
||||
void set_id(int id);
|
||||
void set_bcr(bool fae, bool sae, uint8_t dta, uint8_t dte, uint8_t dtie);
|
||||
bool start_test(int vector);
|
||||
void count_last(int submodule);
|
||||
void count_done(int submodule);
|
||||
protected:
|
||||
required_device<h8_dma_device> dmac;
|
||||
@ -112,12 +139,15 @@ protected:
|
||||
|
||||
uint32_t mar[2];
|
||||
uint16_t ioar[2], etcr[2], dmacr;
|
||||
uint8_t dtcr[2]; // H8H
|
||||
uint8_t dta, dte, dtie;
|
||||
bool fae, sae;
|
||||
bool fae; // Full-Address Mode
|
||||
bool sae; // Short-Address Mode
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
void h8h_sync(); // call set_bcr with contents from DTCR
|
||||
void start(int submodule);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user