mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
dmac_0448: sony news dmac (nw)
This commit is contained in:
parent
8b057af7a9
commit
7912047486
@ -2939,6 +2939,8 @@ files {
|
||||
createMESSProjects(_target, _subtarget, "news_r3k")
|
||||
files {
|
||||
MAME_DIR .. "src/mame/drivers/news_r3k.cpp",
|
||||
MAME_DIR .. "src/mame/machine/dmac_0448.cpp",
|
||||
MAME_DIR .. "src/mame/machine/dmac_0448.h",
|
||||
MAME_DIR .. "src/mame/machine/news_kbd.cpp",
|
||||
MAME_DIR .. "src/mame/machine/news_kbd.h",
|
||||
}
|
||||
|
189
src/mame/machine/dmac_0448.cpp
Normal file
189
src/mame/machine/dmac_0448.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
/*
|
||||
* Sony NEWS DMAC 0448 device.
|
||||
*
|
||||
* Sources:
|
||||
* - https://github.com/NetBSD/src/blob/trunk/sys/arch/newsmips/dev/dmac_0448.h
|
||||
*
|
||||
* TODO:
|
||||
* - 16 and 32 bit transfers
|
||||
* - terminal count handling
|
||||
* - save state
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "dmac_0448.h"
|
||||
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(DMAC_0448, dmac_0448_device, "dmac_0448", "Sony DMA Controller 0448")
|
||||
|
||||
dmac_0448_device::dmac_0448_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, DMAC_0448, tag, owner, clock)
|
||||
, m_bus(*this, finder_base::DUMMY_TAG, -1, 32)
|
||||
, m_out_int(*this)
|
||||
, m_dma_r(*this)
|
||||
, m_dma_w(*this)
|
||||
{
|
||||
}
|
||||
|
||||
void dmac_0448_device::map(address_map &map)
|
||||
{
|
||||
map(0x2, 0x2).r(FUNC(dmac_0448_device::cstat_r));
|
||||
map(0x3, 0x3).w(FUNC(dmac_0448_device::cctl_w));
|
||||
map(0x4, 0x4).rw(FUNC(dmac_0448_device::ctrcl_r), FUNC(dmac_0448_device::ctrcl_w));
|
||||
map(0x5, 0x5).rw(FUNC(dmac_0448_device::ctrcm_r), FUNC(dmac_0448_device::ctrcm_w));
|
||||
map(0x6, 0x6).rw(FUNC(dmac_0448_device::ctrch_r), FUNC(dmac_0448_device::ctrch_w));
|
||||
map(0x7, 0x7).rw(FUNC(dmac_0448_device::ctag_r), FUNC(dmac_0448_device::ctag_w));
|
||||
map(0x8, 0x8).rw(FUNC(dmac_0448_device::cwid_r), FUNC(dmac_0448_device::cwid_w));
|
||||
map(0x9, 0x9).rw(FUNC(dmac_0448_device::cofsl_r), FUNC(dmac_0448_device::cofsl_w));
|
||||
map(0xa, 0xa).rw(FUNC(dmac_0448_device::cofsh_r), FUNC(dmac_0448_device::cofsh_w));
|
||||
|
||||
map(0xc, 0xd).rw(FUNC(dmac_0448_device::cmap_r), FUNC(dmac_0448_device::cmap_w));
|
||||
map(0xe, 0xe).w(FUNC(dmac_0448_device::gsel_w));
|
||||
map(0xf, 0xf).r(FUNC(dmac_0448_device::gstat_r));
|
||||
}
|
||||
|
||||
void dmac_0448_device::device_start()
|
||||
{
|
||||
m_out_int.resolve();
|
||||
|
||||
m_dma_r.resolve_all_safe(0);
|
||||
m_dma_w.resolve_all_safe();
|
||||
|
||||
m_irq_check = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dmac_0448_device::irq_check), this));
|
||||
m_dma_check = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dmac_0448_device::dma_check), this));
|
||||
|
||||
m_out_int_state = false;
|
||||
m_gsel = 0;
|
||||
m_gstat = 0;
|
||||
}
|
||||
|
||||
void dmac_0448_device::device_reset()
|
||||
{
|
||||
m_irq_check->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
void dmac_0448_device::set_irq_line(int number, int state)
|
||||
{
|
||||
u8 const mask = 1U << (number * 2);
|
||||
|
||||
if (state)
|
||||
m_gstat |= mask;
|
||||
else
|
||||
m_gstat &= ~mask;
|
||||
|
||||
m_irq_check->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
void dmac_0448_device::irq_check(void *ptr, s32 param)
|
||||
{
|
||||
bool const out_int_stat = bool(m_gstat & 0x55);
|
||||
|
||||
if (out_int_stat != m_out_int_state)
|
||||
{
|
||||
m_out_int_state = out_int_stat;
|
||||
m_out_int(m_out_int_state);
|
||||
}
|
||||
}
|
||||
|
||||
void dmac_0448_device::set_drq_line(int channel, int state)
|
||||
{
|
||||
u8 const mask = 1U << ((channel * 2) + 1);
|
||||
|
||||
if (state)
|
||||
m_gstat |= mask;
|
||||
else
|
||||
m_gstat &= ~mask;
|
||||
|
||||
if (state)
|
||||
m_dma_check->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
void dmac_0448_device::cctl_w(u8 data)
|
||||
{
|
||||
if ((data & CS_ENABLE) && !(m_channel[m_gsel].cctl & CS_ENABLE))
|
||||
{
|
||||
LOG("transfer started address 0x%08x count 0x%x\n",
|
||||
u32(m_channel[m_gsel].cmap[m_channel[m_gsel].ctag]) << 12 | m_channel[m_gsel].cofs, m_channel[m_gsel].ctrc);
|
||||
}
|
||||
m_channel[m_gsel].cctl = data;
|
||||
|
||||
m_dma_check->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
void dmac_0448_device::dma_check(void *ptr, s32 param)
|
||||
{
|
||||
bool active = false;
|
||||
|
||||
for (unsigned channel = 0; channel < 4; channel++)
|
||||
{
|
||||
// check drq active
|
||||
if (!BIT(m_gstat, (channel * 2) + 1))
|
||||
continue;
|
||||
|
||||
dma_channel &dma = m_channel[channel];
|
||||
|
||||
// check channel enabled
|
||||
if (!(dma.cctl & CS_ENABLE))
|
||||
return;
|
||||
|
||||
// check transfer count
|
||||
if (!dma.ctrc)
|
||||
return;
|
||||
|
||||
// TODO: confirm if this is correct
|
||||
u32 const address = u32(dma.cmap[dma.ctag]) << 12 | dma.cofs;
|
||||
|
||||
// perform dma transfer
|
||||
if (dma.cctl & CS_MODE)
|
||||
{
|
||||
// device to memory
|
||||
u8 const data = m_dma_r[channel]();
|
||||
|
||||
LOG("dma_r data 0x%02x address 0x%08x\n", data, address);
|
||||
|
||||
m_bus->write_byte(address, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// memory to device
|
||||
u8 const data = m_bus->read_byte(address);
|
||||
|
||||
LOG("dma_w data 0x%02x address 0x%08x\n", data, address);
|
||||
|
||||
m_dma_w[channel](data);
|
||||
}
|
||||
|
||||
// increment offset
|
||||
if (dma.cofs == 0xfff)
|
||||
{
|
||||
// advance to next page
|
||||
dma.cofs = 0;
|
||||
dma.ctag++;
|
||||
}
|
||||
else
|
||||
dma.cofs++;
|
||||
|
||||
// decrement count
|
||||
dma.ctrc--;
|
||||
|
||||
// set terminal count flag
|
||||
if (!dma.ctrc)
|
||||
{
|
||||
LOG("transfer complete\n");
|
||||
dma.cstat |= CS_TCZ;
|
||||
|
||||
// TODO: terminal count interrupt?
|
||||
}
|
||||
|
||||
if (BIT(m_gstat, (channel * 2) + 1))
|
||||
active = true;
|
||||
}
|
||||
|
||||
if (active)
|
||||
m_dma_check->adjust(attotime::zero);
|
||||
}
|
99
src/mame/machine/dmac_0448.h
Normal file
99
src/mame/machine/dmac_0448.h
Normal file
@ -0,0 +1,99 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_MACHINE_DMAC_0448_H
|
||||
#define MAME_MACHINE_DMAC_0448_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class dmac_0448_device : public device_t
|
||||
{
|
||||
public:
|
||||
dmac_0448_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
// configuration
|
||||
template <typename T> void set_bus(T &&tag, int spacenum) { m_bus.set_tag(std::forward<T>(tag), spacenum); }
|
||||
auto out_int_cb() { return m_out_int.bind(); }
|
||||
template <unsigned Channel> auto dma_r_cb() { return m_dma_r[Channel].bind(); }
|
||||
template <unsigned Channel> auto dma_w_cb() { return m_dma_w[Channel].bind(); }
|
||||
|
||||
// line handlers
|
||||
template <unsigned IRQ> void irq(int state) { set_irq_line(IRQ, state); }
|
||||
template <unsigned DRQ> void drq(int state) { set_drq_line(DRQ, state); }
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
protected:
|
||||
// device_t overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
void set_irq_line(int number, int state);
|
||||
void set_drq_line(int channel, int state);
|
||||
|
||||
u8 cstat_r() { return m_channel[m_gsel].cstat; }
|
||||
u8 ctrcl_r() { return u8(m_channel[m_gsel].ctrc >> 0); }
|
||||
u8 ctrcm_r() { return u8(m_channel[m_gsel].ctrc >> 8); }
|
||||
u8 ctrch_r() { return u8(m_channel[m_gsel].ctrc >> 16); }
|
||||
u8 ctag_r() { return m_channel[m_gsel].ctag; }
|
||||
u8 cwid_r() { return m_channel[m_gsel].cwid; }
|
||||
u8 cofsl_r() { return u8(m_channel[m_gsel].cofs >> 0); }
|
||||
u8 cofsh_r() { return u8(m_channel[m_gsel].cofs >> 8); }
|
||||
u16 cmap_r() { return m_channel[m_gsel].cmap[m_channel[m_gsel].ctag]; }
|
||||
u8 gstat_r() { return m_gstat; }
|
||||
|
||||
void cctl_w(u8 data);
|
||||
void ctrcl_w(u8 data) { m_channel[m_gsel].ctrc = (m_channel[m_gsel].ctrc & 0xffff00U) | (u32(data) << 0); }
|
||||
void ctrcm_w(u8 data) { m_channel[m_gsel].ctrc = (m_channel[m_gsel].ctrc & 0xff00ffU) | (u32(data) << 8); }
|
||||
void ctrch_w(u8 data) { m_channel[m_gsel].ctrc = (m_channel[m_gsel].ctrc & 0x00ffffU) | (u32(data) << 16); }
|
||||
void ctag_w(u8 data) { m_channel[m_gsel].ctag = data; }
|
||||
void cwid_w(u8 data) { m_channel[m_gsel].cwid = data; }
|
||||
void cofsl_w(u8 data) { m_channel[m_gsel].cofs = (m_channel[m_gsel].cofs & 0xff00U) | (u16(data) << 0); }
|
||||
void cofsh_w(u8 data) { m_channel[m_gsel].cofs = (m_channel[m_gsel].cofs & 0x00ffU) | (u16(data & 0x0f) << 8); }
|
||||
void cmap_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_channel[m_gsel].cmap[m_channel[m_gsel].ctag]); }
|
||||
void gsel_w(u8 data) { m_gsel = data; }
|
||||
|
||||
void irq_check(void *ptr = nullptr, s32 param = 0);
|
||||
void dma_check(void *ptr = nullptr, s32 param = 0);
|
||||
|
||||
required_address_space m_bus;
|
||||
|
||||
devcb_write_line m_out_int;
|
||||
devcb_read8::array<4> m_dma_r;
|
||||
devcb_write8::array<4> m_dma_w;
|
||||
|
||||
emu_timer *m_irq_check;
|
||||
emu_timer *m_dma_check;
|
||||
|
||||
enum cstat_mask : u8
|
||||
{
|
||||
CS_ENABLE = 0x01, // channel enable
|
||||
CS_MODE = 0x02, // transfer to memory
|
||||
CS_RESET = 0x04, // reset channel
|
||||
CS_ZINTEN = 0x08, // terminal count interrupt?
|
||||
CS_APAD = 0x10, // auto pad
|
||||
CS_AFIX = 0x20,
|
||||
CS_A28 = 0x40,
|
||||
CS_TCZ = 0x80, // transfer count zero?
|
||||
};
|
||||
|
||||
struct dma_channel
|
||||
{
|
||||
u8 cstat; // channel status
|
||||
u8 cctl; // channel control
|
||||
u32 ctrc; // channel counter
|
||||
u8 ctag; // channel tag
|
||||
u8 cwid; // channel width
|
||||
u16 cofs; // channel offset
|
||||
u16 cmap[256];
|
||||
}
|
||||
m_channel[4];
|
||||
u8 m_gsel; // channel select
|
||||
u8 m_gstat; // general status
|
||||
|
||||
bool m_out_int_state;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(DMAC_0448, dmac_0448_device)
|
||||
|
||||
#endif // MAME_MACHINE_DMAC_0448_H
|
Loading…
Reference in New Issue
Block a user