summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-04-19 08:18:45 -0400
committer AJR <ajrhacker@users.noreply.github.com>2019-04-19 08:22:29 -0400
commit7ad4b4d1949aa978fa023cf3d3182ea8ed29edc6 (patch)
treeea34a25f22a74cd560bfd703a70657bba663da23
parent64b78571137faf9a553acfa3d36032ae76a2262e (diff)
hd63450: More accurate IRQ handling with a tidier interface
-rw-r--r--src/devices/bus/vme/vme_fcscsi.cpp36
-rw-r--r--src/devices/bus/vme/vme_fcscsi.h6
-rw-r--r--src/devices/machine/hd63450.cpp83
-rw-r--r--src/devices/machine/hd63450.h14
-rw-r--r--src/mame/drivers/esq5505.cpp39
-rw-r--r--src/mame/drivers/x68k.cpp41
-rw-r--r--src/mame/includes/x68k.h5
7 files changed, 112 insertions, 112 deletions
diff --git a/src/devices/bus/vme/vme_fcscsi.cpp b/src/devices/bus/vme/vme_fcscsi.cpp
index e48f058d4db..f5d8378cb89 100644
--- a/src/devices/bus/vme/vme_fcscsi.cpp
+++ b/src/devices/bus/vme/vme_fcscsi.cpp
@@ -242,12 +242,7 @@ void vme_fcscsi1_card_device::update_irq_to_maincpu() {
void vme_fcscsi1_card_device::cpu_space_map(address_map &map)
{
map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map));
- map(0xfffff4, 0xfffff5).lr16("dmac irq", [this]() -> u16 {
- dmac_irq_state = 0;
- u16 vector = B41 ? dmac_irq_vector : 0x18+2;
- update_irq_to_maincpu();
- return vector;
- });
+ map(0xfffff5, 0xfffff5).r(m_dmac, FUNC(hd63450_device::iack));
}
FLOPPY_FORMATS_MEMBER( vme_fcscsi1_card_device::floppy_formats )
@@ -301,8 +296,7 @@ void vme_fcscsi1_card_device::device_add_mconfig(machine_config &config)
HD63450(config, m_dmac, CPU_CRYSTAL / 2, "maincpu"); // MC68450 compatible
m_dmac->set_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2));
m_dmac->set_burst_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50));
- m_dmac->dma_end().set(FUNC(vme_fcscsi1_card_device::dma_end));
- m_dmac->dma_error().set(FUNC(vme_fcscsi1_card_device::dma_error));
+ m_dmac->irq_callback().set(FUNC(vme_fcscsi1_card_device::dma_irq));
//m_dmac->dma_read<0>().set(FUNC(vme_fcscsi1_card_device::scsi_read_byte)); // ch 0 = SCSI
//m_dmac->dma_write<0>().set(FUNC(vme_fcscsi1_card_device::scsi_write_byte));
m_dmac->dma_read<1>().set(FUNC(vme_fcscsi1_card_device::fdc_read_byte)); // ch 1 = fdc
@@ -420,12 +414,12 @@ WRITE8_MEMBER (vme_fcscsi1_card_device::led_w){
return;
}
-WRITE8_MEMBER(vme_fcscsi1_card_device::dma_end)
+WRITE_LINE_MEMBER(vme_fcscsi1_card_device::dma_irq)
{
- if (data != 0)
+ if(state != CLEAR_LINE)
{
+ logerror("DMAC IRQ, vector = %x\n", m_dmac->iack());
dmac_irq_state = 1;
- dmac_irq_vector = m_dmac->get_vector(offset);
}
else
{
@@ -435,25 +429,9 @@ WRITE8_MEMBER(vme_fcscsi1_card_device::dma_end)
update_irq_to_maincpu();
}
-WRITE8_MEMBER(vme_fcscsi1_card_device::dma_error)
+WRITE_LINE_MEMBER(vme_fcscsi1_card_device::fdc_irq)
{
- if(data != 0)
- {
- logerror("DMAC error, vector = %x\n", m_dmac->get_error_vector(offset));
- dmac_irq_state = 1;
- dmac_irq_vector = m_dmac->get_vector(offset);
- }
- else
- {
- dmac_irq_state = 0;
- }
-
- update_irq_to_maincpu();
-}
-
-WRITE8_MEMBER(vme_fcscsi1_card_device::fdc_irq)
-{
- if (data != 0)
+ if (state != 0)
{
fdc_irq_state = 1;
}
diff --git a/src/devices/bus/vme/vme_fcscsi.h b/src/devices/bus/vme/vme_fcscsi.h
index 02f22d1eaa1..fa0622f8c99 100644
--- a/src/devices/bus/vme/vme_fcscsi.h
+++ b/src/devices/bus/vme/vme_fcscsi.h
@@ -32,15 +32,13 @@ protected:
uint8_t fdc_irq_state;
uint8_t dmac_irq_state;
- int dmac_irq_vector;
private:
//dmac
- DECLARE_WRITE8_MEMBER(dma_end);
- DECLARE_WRITE8_MEMBER(dma_error);
+ DECLARE_WRITE_LINE_MEMBER(dma_irq);
//fdc
- DECLARE_WRITE8_MEMBER(fdc_irq);
+ DECLARE_WRITE_LINE_MEMBER(fdc_irq);
DECLARE_READ8_MEMBER(fdc_read_byte);
DECLARE_WRITE8_MEMBER(fdc_write_byte);
DECLARE_FLOPPY_FORMATS(floppy_formats);
diff --git a/src/devices/machine/hd63450.cpp b/src/devices/machine/hd63450.cpp
index 25932cec032..44343895fa9 100644
--- a/src/devices/machine/hd63450.cpp
+++ b/src/devices/machine/hd63450.cpp
@@ -16,8 +16,8 @@ DEFINE_DEVICE_TYPE(HD63450, hd63450_device, "hd63450", "Hitachi HD63450 DMAC")
hd63450_device::hd63450_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HD63450, tag, owner, clock),
+ m_irq_callback(*this),
m_dma_end(*this),
- m_dma_error(*this),
m_dma_read{{*this}, {*this}, {*this}, {*this}},
m_dma_write{{*this}, {*this}, {*this}, {*this}},
m_cpu(*this, finder_base::DUMMY_TAG)
@@ -43,8 +43,8 @@ hd63450_device::hd63450_device(const machine_config &mconfig, const char *tag, d
void hd63450_device::device_start()
{
// resolve callbacks
- m_dma_end.resolve();
- m_dma_error.resolve_safe();
+ m_irq_callback.resolve_safe();
+ m_dma_end.resolve_safe();
for (auto &cb : m_dma_read)
cb.resolve();
for (auto &cb : m_dma_write)
@@ -77,10 +77,13 @@ void hd63450_device::device_start()
save_item(NAME(m_transfer_size));
save_item(NAME(m_halted));
save_item(NAME(m_drq_state));
+ save_item(NAME(m_irq_channel));
}
void hd63450_device::device_reset()
{
+ // Device is reset by pulling /BEC0-/BEC2 all low for 10 clocks
+
for (int x = 0; x < 4; x++)
{
m_reg[x].niv = 0x0f;
@@ -97,6 +100,9 @@ void hd63450_device::device_reset()
m_timer[x]->adjust(attotime::never);
m_halted[x] = 0;
}
+
+ m_irq_channel = -1;
+ m_irq_callback(CLEAR_LINE);
}
READ16_MEMBER(hd63450_device::read)
@@ -166,6 +172,9 @@ WRITE16_MEMBER(hd63450_device::write)
// Clearing ERR also resets CER (which is otherwise read-only)
if ((data & 0x1000) != 0)
m_reg[channel].cer = 0;
+
+ if ((m_reg[channel].csr & 0xf2) == 0)
+ clear_irq(channel);
}
break;
case 0x02: // DCR / OCR
@@ -317,11 +326,7 @@ void hd63450_device::dma_transfer_abort(int channel)
LOG("DMA#%i: Transfer aborted\n",channel);
m_timer[channel]->adjust(attotime::never);
- m_reg[channel].csr |= 0x90; // channel error
- m_reg[channel].csr &= ~0x08; // channel no longer active
- m_reg[channel].cer = 0x11;
- m_reg[channel].ccr &= ~0xc0;
- m_dma_error((offs_t)3, m_reg[channel].ccr & 0x08);
+ set_error(channel, 0x11);
}
void hd63450_device::dma_transfer_halt(int channel)
@@ -467,11 +472,21 @@ void hd63450_device::single_transfer(int x)
m_cpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
}
- if (!m_dma_end.isnull())
- m_dma_end((offs_t)x, m_reg[x].ccr & 0x08);
+ m_dma_end((offs_t)x, 0);
+ set_irq(x);
}
}
+void hd63450_device::set_error(int channel, uint8_t code)
+{
+ m_reg[channel].csr |= 0x90; // channel error
+ m_reg[channel].csr &= ~0x08; // channel no longer active
+ m_reg[channel].cer = code;
+ m_reg[channel].ccr &= ~0xc0;
+
+ set_irq(channel);
+}
+
WRITE_LINE_MEMBER(hd63450_device::drq0_w)
{
bool ostate = m_drq_state[0];
@@ -529,12 +544,52 @@ WRITE_LINE_MEMBER(hd63450_device::drq3_w)
m_timer[3]->adjust(attotime::never);
}
-int hd63450_device::get_vector(int channel)
+void hd63450_device::set_irq(int channel)
{
- return m_reg[channel].niv;
+ if ((m_reg[channel].ccr & 0x08) == 0)
+ return;
+
+ if (m_irq_channel == -1)
+ {
+ m_irq_channel = channel;
+ m_irq_callback(ASSERT_LINE);
+ }
+ else if ((m_reg[channel].cpr & 0x03) < (m_reg[m_irq_channel].cpr & 0x03))
+ m_irq_channel = channel;
}
-int hd63450_device::get_error_vector(int channel)
+void hd63450_device::clear_irq(int channel)
{
- return m_reg[channel].eiv;
+ if (m_irq_channel != channel)
+ return;
+
+ for (int pri = m_reg[channel].cpr & 0x03; pri <= 3; pri++)
+ {
+ for (int offset = 1; offset <= 3; offset++)
+ {
+ if ((m_reg[(channel + offset) & 3].ccr & 0x08) != 0 &&
+ (m_reg[(channel + offset) & 3].csr & 0xf2) != 0)
+ {
+ m_irq_channel = (channel + offset) & 3;
+ return;
+ }
+ }
+ }
+
+ m_irq_channel = -1;
+ m_irq_callback(CLEAR_LINE);
+}
+
+uint8_t hd63450_device::iack()
+{
+ if (m_irq_channel != -1)
+ {
+ if ((m_reg[m_irq_channel].csr & 0x10) != 0)
+ return m_reg[m_irq_channel].eiv;
+ else
+ return m_reg[m_irq_channel].niv;
+ }
+
+ // Spurious interrupt (no response actually)
+ return 0x18;
}
diff --git a/src/devices/machine/hd63450.h b/src/devices/machine/hd63450.h
index cf0381937bf..63e32c5a5d6 100644
--- a/src/devices/machine/hd63450.h
+++ b/src/devices/machine/hd63450.h
@@ -20,8 +20,8 @@ public:
hd63450_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ auto irq_callback() { return m_irq_callback.bind(); }
auto dma_end() { return m_dma_end.bind(); }
- auto dma_error() { return m_dma_error.bind(); }
template<int Ch> auto dma_read() { return m_dma_read[Ch].bind(); }
template<int Ch> auto dma_write() { return m_dma_write[Ch].bind(); }
@@ -47,11 +47,10 @@ public:
DECLARE_WRITE_LINE_MEMBER(drq1_w);
DECLARE_WRITE_LINE_MEMBER(drq2_w);
DECLARE_WRITE_LINE_MEMBER(drq3_w);
+ uint8_t iack();
void single_transfer(int x);
void set_timer(int channel, const attotime &tm);
- int get_vector(int channel);
- int get_error_vector(int channel);
protected:
// device-level overrides
@@ -81,8 +80,8 @@ private:
uint8_t gcr; // [3f] General Control Register (R/W)
};
+ devcb_write_line m_irq_callback;
devcb_write8 m_dma_end;
- devcb_write8 m_dma_error;
devcb_read8 m_dma_read[4];
devcb_write8 m_dma_write[4];
@@ -97,6 +96,8 @@ private:
required_device<cpu_device> m_cpu;
bool m_drq_state[4];
+ int8_t m_irq_channel;
+
// tell if a channel is in use
bool dma_in_progress(int channel) const { return (m_reg[channel].csr & 0x08) != 0; }
@@ -105,6 +106,11 @@ private:
void dma_transfer_halt(int channel);
void dma_transfer_continue(int channel);
void dma_transfer_start(int channel);
+ void set_error(int channel, uint8_t code);
+
+ // interrupt helpers
+ void set_irq(int channel);
+ void clear_irq(int channel);
};
DECLARE_DEVICE_TYPE(HD63450, hd63450_device)
diff --git a/src/mame/drivers/esq5505.cpp b/src/mame/drivers/esq5505.cpp
index 3aa75ca76ab..9cfc251f3cc 100644
--- a/src/mame/drivers/esq5505.cpp
+++ b/src/mame/drivers/esq5505.cpp
@@ -229,9 +229,7 @@ private:
uint8_t m_duart_io;
uint8_t otis_irq_state;
uint8_t dmac_irq_state;
- int dmac_irq_vector;
uint8_t duart_irq_state;
- int duart_irq_vector;
void update_irq_to_maincpu();
@@ -246,8 +244,7 @@ private:
uint16_t m_analog_values[8];
//dmac
- DECLARE_WRITE8_MEMBER(dma_end);
- DECLARE_WRITE8_MEMBER(dma_error);
+ DECLARE_WRITE_LINE_MEMBER(dma_irq);
};
FLOPPY_FORMATS_MEMBER( esq5505_state::floppy_formats )
@@ -257,8 +254,8 @@ FLOPPY_FORMATS_END
void esq5505_state::cpu_space_map(address_map &map)
{
map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map));
- map(0xfffff4, 0xfffff5).lr16("dmac irq", [this]() -> u16 { return dmac_irq_vector; });
- map(0xfffff6, 0xfffff7).lr16("duart irq", [this]() -> u16 { return duart_irq_vector; });
+ map(0xfffff5, 0xfffff5).r(m_dmac, FUNC(hd63450_device::iack));
+ map(0xfffff7, 0xfffff7).r(m_duart, FUNC(mc68681_device::get_irq_vector));
}
void esq5505_state::machine_start()
@@ -448,12 +445,11 @@ WRITE_LINE_MEMBER(esq5505_state::duart_irq_handler)
// printf("\nDUART IRQ: state %d vector %d\n", state, vector);
if (state == ASSERT_LINE)
{
- duart_irq_vector = m_duart->get_irq_vector();
duart_irq_state = 1;
}
else
{
- duart_irq_state = 0;
+ duart_irq_state = 0;
}
update_irq_to_maincpu();
}
@@ -524,30 +520,12 @@ WRITE_LINE_MEMBER(esq5505_state::duart_tx_b)
m_panel->rx_w(state);
}
-WRITE8_MEMBER(esq5505_state::dma_end)
+WRITE_LINE_MEMBER(esq5505_state::dma_irq)
{
- if (data != 0)
+ if (state != CLEAR_LINE)
{
- //printf("DMAC IRQ, vector = %x\n", m_dmac->get_vector(offset));
+ logerror("DMAC error, vector = %x\n", m_dmac->iack());
dmac_irq_state = 1;
- dmac_irq_vector = m_dmac->get_vector(offset);
- }
- else
- {
- dmac_irq_state = 0;
- }
-
- // printf("IRQ update from DMAC: have OTIS=%d, DMAC=%d, DUART=%d\n", otis_irq_state, dmac_irq_state, duart_irq_state);
- update_irq_to_maincpu();
-}
-
-WRITE8_MEMBER(esq5505_state::dma_error)
-{
- if(data != 0)
- {
- logerror("DMAC error, vector = %x\n", m_dmac->get_error_vector(offset));
- dmac_irq_state = 1;
- dmac_irq_vector = m_dmac->get_vector(offset);
}
else
{
@@ -683,8 +661,7 @@ void esq5505_state::eps(machine_config &config)
m_dmac->set_cpu_tag(m_maincpu);
m_dmac->set_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2));
m_dmac->set_burst_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50));
- m_dmac->dma_end().set(FUNC(esq5505_state::dma_end));
- m_dmac->dma_error().set(FUNC(esq5505_state::dma_error));
+ m_dmac->irq_callback().set(FUNC(esq5505_state::dma_irq));
m_dmac->dma_read<0>().set(m_fdc, FUNC(wd1772_device::data_r)); // ch 0 = fdc, ch 1 = 340001 (ADC?)
m_dmac->dma_write<0>().set(m_fdc, FUNC(wd1772_device::data_w));
}
diff --git a/src/mame/drivers/x68k.cpp b/src/mame/drivers/x68k.cpp
index bbc00fd67ef..e77750dcb06 100644
--- a/src/mame/drivers/x68k.cpp
+++ b/src/mame/drivers/x68k.cpp
@@ -313,7 +313,7 @@ TIMER_CALLBACK_MEMBER(x68k_state::scc_ack)
{
m_mouse.irqactive = 1;
m_current_vector[5] = 0x54;
- m_current_irq_line = 5;
+ //m_current_irq_line = 5;
m_maincpu->set_input_line(5,ASSERT_LINE);
}
}
@@ -680,7 +680,7 @@ WRITE_LINE_MEMBER( x68k_state::fdc_irq )
{
m_current_vector[1] = m_ioc.fdcvector;
m_ioc.irqstatus |= 0x80;
- m_current_irq_line = 1;
+ //m_current_irq_line = 1;
LOGMASKED(LOG_FDC, "FDC: IRQ triggered\n");
m_maincpu->set_input_line(1, ASSERT_LINE);
}
@@ -998,37 +998,24 @@ WRITE16_MEMBER(x68k_state::exp_w)
set_bus_error((offset << 1) + 0xeafa00, 1, mem_mask);
}
-void x68k_state::dma_irq(int channel)
+WRITE_LINE_MEMBER(x68k_state::dma_irq)
{
- m_current_vector[3] = m_hd63450->get_vector(channel);
- m_current_irq_line = 3;
- LOGMASKED(LOG_SYS, "DMA#%i: DMA End (vector 0x%02x)\n",channel,m_current_vector[3]);
- m_maincpu->set_input_line(3,ASSERT_LINE);
+ if (state != CLEAR_LINE)
+ {
+ //m_current_irq_line = 3;
+ LOGMASKED(LOG_SYS, "DMA IRQ (vector 0x%02x)\n", m_hd63450->iack());
+ }
+ m_maincpu->set_input_line(3, state);
}
WRITE8_MEMBER(x68k_state::dma_end)
{
- if(data != 0)
- {
- dma_irq(offset);
- }
if(offset == 0)
{
m_fdc_tc->adjust(attotime::from_usec(1), 0, attotime::never);
}
}
-WRITE8_MEMBER(x68k_state::dma_error)
-{
- if(data != 0)
- {
- m_current_vector[3] = m_hd63450->get_error_vector(offset);
- m_current_irq_line = 3;
- LOGMASKED(LOG_SYS, "DMA#%i: DMA Error (vector 0x%02x)\n",offset,m_current_vector[3]);
- m_maincpu->set_input_line(3,ASSERT_LINE);
- }
-}
-
WRITE_LINE_MEMBER(x68k_state::fm_irq)
{
if(state == CLEAR_LINE)
@@ -1104,7 +1091,7 @@ void x68k_state::cpu_space_map(address_map &map)
map.global_mask(0xffffff);
map(0xfffff3, 0xfffff3).r(FUNC(x68k_state::int_ack<1>));
map(0xfffff5, 0xfffff5).r(FUNC(x68k_state::int_ack<2>));
- map(0xfffff7, 0xfffff7).r(FUNC(x68k_state::int_ack<3>));
+ map(0xfffff7, 0xfffff7).r(m_hd63450, FUNC(hd63450_device::iack));
map(0xfffff9, 0xfffff9).r(FUNC(x68k_state::int_ack<4>));
map(0xfffffb, 0xfffffb).r(FUNC(x68k_state::int_ack<5>));
map(0xfffffd, 0xfffffd).r(FUNC(x68k_state::mfp_ack));
@@ -1117,7 +1104,7 @@ WRITE_LINE_MEMBER(x68ksupr_state::scsi_irq)
if(state != 0)
{
m_current_vector[1] = 0x6c;
- m_current_irq_line = 1;
+ //m_current_irq_line = 1;
m_maincpu->set_input_line(1,ASSERT_LINE);
}
}
@@ -1383,7 +1370,7 @@ void x68k_state::floppy_load_unload(bool load, floppy_image_device *dev)
{
m_current_vector[1] = 0x61;
m_ioc.irqstatus |= 0x40;
- m_current_irq_line = 1;
+ //m_current_irq_line = 1;
m_maincpu->set_input_line(1,ASSERT_LINE); // Disk insert/eject interrupt
LOGMASKED(LOG_FDC, "IOC: Disk image inserted\n");
}
@@ -1403,7 +1390,7 @@ void x68k_state::floppy_unload(floppy_image_device *dev)
TIMER_CALLBACK_MEMBER(x68k_state::net_irq)
{
m_current_vector[2] = 0xf9;
- m_current_irq_line = 2;
+ //m_current_irq_line = 2;
m_maincpu->set_input_line(2,ASSERT_LINE);
}
@@ -1594,8 +1581,8 @@ void x68k_state::x68000_base(machine_config &config)
HD63450(config, m_hd63450, 40_MHz_XTAL / 4, "maincpu");
m_hd63450->set_clocks(attotime::from_usec(2), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2));
m_hd63450->set_burst_clocks(attotime::from_usec(2), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50));
+ m_hd63450->irq_callback().set(FUNC(x68k_state::dma_irq));
m_hd63450->dma_end().set(FUNC(x68k_state::dma_end));
- m_hd63450->dma_error().set(FUNC(x68k_state::dma_error));
m_hd63450->dma_read<0>().set("upd72065", FUNC(upd72065_device::dma_r));
m_hd63450->dma_write<0>().set("upd72065", FUNC(upd72065_device::dma_w));
diff --git a/src/mame/includes/x68k.h b/src/mame/includes/x68k.h
index 2712344c67f..c12110b5399 100644
--- a/src/mame/includes/x68k.h
+++ b/src/mame/includes/x68k.h
@@ -229,7 +229,7 @@ protected:
} m_mdctrl;
uint8_t m_ppi_port[3];
int m_current_vector[8];
- uint8_t m_current_irq_line;
+ //uint8_t m_current_irq_line;
int m_led_state;
emu_timer* m_mouse_timer;
emu_timer* m_led_timer;
@@ -270,9 +270,8 @@ protected:
DECLARE_WRITE_LINE_MEMBER(mfp_irq_callback);
//dmac
- void dma_irq(int channel);
+ DECLARE_WRITE_LINE_MEMBER(dma_irq);
DECLARE_WRITE8_MEMBER(dma_end);
- DECLARE_WRITE8_MEMBER(dma_error);
int read_mouse();
void set_adpcm();