ds5k133: Preliminary LANCE DMA hookup [R. Belmont]

If you can parse this comment from the Linux driver, please help :)

 * The IOASIC LANCE devices use a shared memory region.  This region
 * as seen from the CPU is (max) 128 kB long and has to be on an 128 kB
 * boundary.  The LANCE sees this as a 64 kB long continuous memory
 * region.
 *
 * The LANCE's DMA address is used as an index in this buffer and DMA
 * takes place in bursts of eight 16-bit words which are packed into
 * four 32-bit words by the IOASIC.  This leads to a strange padding:
 * 16 bytes of valid data followed by a 16 byte gap :-(.

I get the first part, which is that since the DMA engine works in words and
LANCE works in half-words that each half-word for LANCE is packed into one
word from the CPU's point of view.  The second part not so much.
This commit is contained in:
arbee 2019-01-06 22:20:47 -05:00
parent cd48a8d419
commit 26412cd829
3 changed files with 62 additions and 3 deletions

View File

@ -103,6 +103,7 @@ public:
protected:
DECLARE_READ_LINE_MEMBER(brcond0_r) { return ASSERT_LINE; }
DECLARE_WRITE_LINE_MEMBER(ioga_irq_w);
DECLARE_WRITE_LINE_MEMBER(dz_irq_w);
DECLARE_READ32_MEMBER(cfb_r);
DECLARE_WRITE32_MEMBER(cfb_w);
@ -238,9 +239,9 @@ READ32_MEMBER(decstation_state::cfb_r)
{
uint32_t addr = offset << 2;
// logerror("cfb_r: reading at %x\n", addr);
//logerror("cfb_r: reading at %x\n", addr);
if (addr < 0x800000)
if (addr < 0x80000)
{
return m_vrom_ptr[addr>>2] & 0xff;
}
@ -551,6 +552,11 @@ WRITE_LINE_MEMBER(decstation_state::ioga_irq_w)
m_maincpu->set_input_line(INPUT_LINE_IRQ3, state);
}
WRITE_LINE_MEMBER(decstation_state::dz_irq_w)
{
m_maincpu->set_input_line(INPUT_LINE_IRQ2, state);
}
void decstation_state::machine_start()
{
if (m_vrom)
@ -562,6 +568,8 @@ void decstation_state::machine_start()
void decstation_state::machine_reset()
{
m_ioga->set_dma_space(&m_maincpu->space(AS_PROGRAM));
m_copy_src = 1;
m_entry = 0;
m_stage = 0;
@ -662,6 +670,8 @@ MACHINE_CONFIG_START(decstation_state::kn01)
m_scantimer->configure_scanline(FUNC(decstation_state::scanline_timer), "screen", 0, 1);
DC7085(config, m_dz, 0);
m_dz->int_cb().set(FUNC(decstation_state::dz_irq_w));
m_dz->ch1_tx_cb().set("dc7085:ch1", FUNC(dc7085_channel::rx_w));
AM79C90(config, m_lance, XTAL(12'500'000));
@ -684,6 +694,8 @@ MACHINE_CONFIG_START(decstation_state::kn02ba)
AM79C90(config, m_lance, XTAL(12'500'000));
m_lance->intr_out().set("ioga", FUNC(dec_ioga_device::lance_irq_w));
m_lance->dma_in().set("ioga", FUNC(dec_ioga_device::lance_dma_r));
m_lance->dma_out().set("ioga", FUNC(dec_ioga_device::lance_dma_w));
DECSTATION_IOGA(config, m_ioga, XTAL(12'500'000));
m_ioga->irq_out().set(FUNC(decstation_state::ioga_irq_w));

View File

@ -10,10 +10,18 @@
#include "emu.h"
#include "decioga.h"
#define LOG_DMA (1U << 0)
#define LOG_LANCE_DMA (1U << 1)
#define VERBOSE (LOG_DMA|LOG_LANCE_DMA)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(DECSTATION_IOGA, dec_ioga_device, "decioga", "DECstation I/O Gate Array")
void dec_ioga_device::map(address_map &map)
{
map(0x040000, 0x0400ff).rw(FUNC(dec_ioga_device::dmaptr_r), FUNC(dec_ioga_device::dmaptr_w));
map(0x040100, 0x040103).rw(FUNC(dec_ioga_device::csr_r), FUNC(dec_ioga_device::csr_w));
map(0x040110, 0x040113).rw(FUNC(dec_ioga_device::intr_r), FUNC(dec_ioga_device::intr_w));
map(0x040120, 0x040123).rw(FUNC(dec_ioga_device::imsk_r), FUNC(dec_ioga_device::imsk_w));
@ -91,6 +99,17 @@ WRITE32_MEMBER(dec_ioga_device::imsk_w)
COMBINE_DATA(&m_imsk);
}
READ32_MEMBER(dec_ioga_device::dmaptr_r)
{
return m_dmaptrs[offset/4];
}
WRITE32_MEMBER(dec_ioga_device::dmaptr_w)
{
COMBINE_DATA(&m_dmaptrs[offset/4]);
LOGMASKED(LOG_DMA, "DECIOGA: %08x to DMA pointer %x (addr %x)\n", data, offset/4, offset*4);
}
WRITE_LINE_MEMBER(dec_ioga_device::rtc_irq_w)
{
if (state == ASSERT_LINE)
@ -138,3 +157,21 @@ WRITE_LINE_MEMBER(dec_ioga_device::scc1_irq_w)
}
recalc_irq();
}
// DMA handlers
void dec_ioga_device::set_dma_space(address_space *space)
{
m_maincpu_space = space;
}
READ16_MEMBER(dec_ioga_device::lance_dma_r)
{
LOGMASKED(LOG_LANCE_DMA, "lance_dma_r: %08x (phys %08x)\n", offset, (offset<<1) + (m_dmaptrs[2]>>3));
return m_maincpu_space->read_word((offset<<1) + (m_dmaptrs[2]>>3));
}
WRITE16_MEMBER(dec_ioga_device::lance_dma_w)
{
LOGMASKED(LOG_LANCE_DMA, "lance_dma_w: %04x to %08x\n", data, offset);
m_maincpu_space->write_word((offset<<1) + (m_dmaptrs[2]>>3), data);
}

View File

@ -28,6 +28,11 @@ public:
// multiplex irq output
auto irq_out() { return m_irq_out_cb.bind(); }
// DMA interface
void set_dma_space(address_space *space);
DECLARE_READ16_MEMBER(lance_dma_r);
DECLARE_WRITE16_MEMBER(lance_dma_w);
protected:
virtual void device_start() override;
virtual void device_reset() override;
@ -38,9 +43,14 @@ protected:
DECLARE_WRITE32_MEMBER(intr_w);
DECLARE_READ32_MEMBER(imsk_r);
DECLARE_WRITE32_MEMBER(imsk_w);
DECLARE_READ32_MEMBER(dmaptr_r);
DECLARE_WRITE32_MEMBER(dmaptr_w);
address_space *m_maincpu_space;
private:
uint32_t m_csr, m_intr, m_imsk;
u32 m_csr, m_intr, m_imsk;
u32 m_dmaptrs[0x10];
devcb_write_line m_irq_out_cb;