mirror of
https://github.com/holub/mame
synced 2025-07-06 18:39:28 +03:00
WIP NEW DEVICE Motorola mc6844 DMA controller (devicified from swtpc09.cpp)
This commit is contained in:
parent
2e1ba819b6
commit
73732ffb39
@ -1895,6 +1895,18 @@ if (MACHINES["MC6843"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/mc6844.h,MACHINES["MC6844"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["MC6844"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/mc6844.cpp",
|
||||
MAME_DIR .. "src/devices/machine/mc6844.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/mc6846.h,MACHINES["MC6846"] = true
|
||||
|
@ -536,6 +536,7 @@ MACHINES["MC14411"] = true
|
||||
MACHINES["MC146818"] = true
|
||||
MACHINES["MC2661"] = true
|
||||
MACHINES["MC6843"] = true
|
||||
MACHINES["MC6844"] = true
|
||||
MACHINES["MC6846"] = true
|
||||
MACHINES["MC6852"] = true
|
||||
MACHINES["MC6854"] = true
|
||||
|
556
src/devices/machine/mc6844.cpp
Normal file
556
src/devices/machine/mc6844.cpp
Normal file
@ -0,0 +1,556 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Joakim Larsson Edström
|
||||
/**********************************************************************
|
||||
|
||||
Motorola 6844 emulation. This code is not yet ready for general use, see TODO list below
|
||||
|
||||
"MC6844 — Direct Memory Access Controller
|
||||
|
||||
This DMAC works with an M6800 MPU Clock Pulse Generator and an I/O Peripheral Controller,
|
||||
such as the units described here, to facilitate direct access to the computer memory by
|
||||
the peripheral, thus by passing MPU interactive time delay.
|
||||
|
||||
General Description
|
||||
|
||||
The MC6844 is operable in three modes: HALT Burst, Cycle Steal and TSC Steal.
|
||||
In the Burst Mode, the MPU is halted by the first transfer request (TxRQ) input and
|
||||
is restarted when the Byte Count Register (BCR) is zero. Each data transfer is synchronized
|
||||
by a pulse input of TxRQ. In the Cycle Steal Mode, the MPU is halted by each TxRQ and
|
||||
is restarted after each one byte of data transferred. In the TSC Steal Mode, DMAC uses the
|
||||
three-state control function of the MPU to control the system bus. One byte of data is
|
||||
transferred during each DMA cycle.
|
||||
|
||||
The DMAC has four channels. A Priority Control Register determines which of the channels
|
||||
is enabled. While data is being transferred on one channel, the other channels are inhibited.
|
||||
When one channel completes transferring, the next will become valid for DMA transfer. The PCR
|
||||
also utilizes a Rotate Control bit. Priority of DMA transfer is normally fixed in sequential
|
||||
order. The highest priority is in #0 Channel and the lowest is in #3. When this bit is in high
|
||||
level, channel priority is rotated such that the just-serviced channel has the lowest priority
|
||||
in the next DMA transfer."
|
||||
|
||||
Source: https://en.wikipedia.org/wiki/File:Motorola_Microcomputer_Components_1978_pg13.jpg
|
||||
|
||||
CREDITS & Prior Work:
|
||||
The base code was ripped out of swtpc09.cpp and deviceified but similar code is also to be found
|
||||
in exidy440.cpp so copyrigt is probably shared among the authors there: Robert Justice, 68bit and
|
||||
Aaron Giles.
|
||||
|
||||
TODO:
|
||||
- Memory to Device transfers
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "mc6844.h"
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
#define LOG_SETUP (1U << 1)
|
||||
#define LOG_INT (1U << 2)
|
||||
#define LOG_STATE (1U << 3)
|
||||
#define LOG_TFR (1U << 4)
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL|LOG_SETUP | LOG_INT | LOG_STATE |LOG_TFR)
|
||||
//#define LOG_OUTPUT_STREAM std::cout
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
|
||||
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
|
||||
#define LOGSTATE(...) LOGMASKED(LOG_STATE, __VA_ARGS__)
|
||||
#define LOGTFR(...) LOGMASKED(LOG_TFR, __VA_ARGS__)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FUNCNAME __func__
|
||||
#else
|
||||
#define FUNCNAME __PRETTY_FUNCTION__
|
||||
#endif
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(MC6844, mc6844_device, "mc6844", "MC6844 DMA")
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// mc6844_device - constructor
|
||||
//-------------------------------------------------
|
||||
mc6844_device::mc6844_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, MC6844, tag, owner, clock)
|
||||
, device_execute_interface(mconfig, *this)
|
||||
, m_out_int_cb(*this)
|
||||
, m_out_txak_cb(*this)
|
||||
, m_out_drq1_cb(*this)
|
||||
, m_out_drq2_cb(*this)
|
||||
, m_in_memr_cb(*this)
|
||||
, m_out_memw_cb(*this)
|
||||
, m_in_ior_cb{ { *this },{ *this },{ *this },{ *this } }
|
||||
, m_out_iow_cb{ { *this },{ *this },{ *this },{ *this } }
|
||||
, m_state(STATE_S0)
|
||||
, m_icount(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_resolve_objects - device-specific setup
|
||||
//-------------------------------------------------
|
||||
void mc6844_device::device_resolve_objects()
|
||||
{
|
||||
m_out_int_cb.resolve_safe();
|
||||
m_out_txak_cb.resolve_safe();
|
||||
m_out_drq1_cb.resolve_safe();
|
||||
m_out_drq2_cb.resolve_safe();
|
||||
m_in_memr_cb.resolve_safe(0);
|
||||
m_out_memw_cb.resolve_safe();
|
||||
|
||||
for(auto &cb : m_in_ior_cb)
|
||||
cb.resolve_safe(0);
|
||||
for(auto &cb : m_out_iow_cb)
|
||||
cb.resolve_safe();
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc6844_device::device_start()
|
||||
{
|
||||
// set our instruction counter
|
||||
set_icountptr(m_icount);
|
||||
|
||||
save_item(NAME(m_m6844_priority));
|
||||
save_item(NAME(m_m6844_interrupt));
|
||||
save_item(NAME(m_m6844_chain));
|
||||
save_item(NAME(m_state));
|
||||
save_item(NAME(m_icount));
|
||||
save_item(NAME(m_current_channel));
|
||||
save_item(NAME(m_last_channel));
|
||||
save_item(NAME(m_dgrnt));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc6844_device::device_reset()
|
||||
{
|
||||
// reset the 6844
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_m6844_channel[i].active = 0;
|
||||
m_m6844_channel[i].control = 0x00;
|
||||
}
|
||||
m_m6844_priority = 0x00;
|
||||
m_m6844_interrupt = 0x00;
|
||||
m_m6844_chain = 0x00;
|
||||
m_state = STATE_SI;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// dma_request -
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc6844_device::dma_request(int channel, int state)
|
||||
{
|
||||
LOG("MC6844 Channel %u DMA Request: %u\n", channel, state);
|
||||
|
||||
m_dreq[channel & 3] = state;
|
||||
|
||||
LOGSTATE("Trigger(1)\n");
|
||||
trigger(1);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute_run -
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc6844_device::execute_run()
|
||||
{
|
||||
do
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case STATE_SI: // IDLE state, will suspend until a DMA request comes through
|
||||
{ // Hi ------> Lo
|
||||
int const priorities[][4] = {{ 1, 2, 3, 0 },
|
||||
{ 2, 3, 0, 1 },
|
||||
{ 3, 0, 1, 2 },
|
||||
{ 0, 1, 2, 3 }};
|
||||
|
||||
LOGSTATE("DMA state SI\n");
|
||||
for (int prio = 0; prio < 4; prio++)
|
||||
{
|
||||
// Rotating or static channel prioritizations
|
||||
int current_channel = priorities[((m_m6844_priority & 0x80) ? m_last_channel : 3) & 3][prio];
|
||||
|
||||
if (m_m6844_channel[current_channel].active == 1 && m_dreq[current_channel] == ASSERT_LINE)
|
||||
{
|
||||
m_current_channel = m_last_channel = current_channel;
|
||||
m_state = STATE_S0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(m_state == STATE_SI)
|
||||
{
|
||||
LOGSTATE("Suspend in SI\n");
|
||||
suspend_until_trigger(1, true);
|
||||
m_icount = 0;
|
||||
}
|
||||
break;
|
||||
case STATE_S0: // Wait for BCR != 0 and Tx EN == 1
|
||||
LOGSTATE("DMA state S0\n");
|
||||
if (m_m6844_channel[m_current_channel].active == 1 &&
|
||||
m_m6844_channel[m_current_channel].counter != 0)
|
||||
{
|
||||
m_state = STATE_S1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGSTATE("Suspend in S0\n");
|
||||
suspend_until_trigger(1, true);
|
||||
m_icount = 0;
|
||||
}
|
||||
break;
|
||||
case STATE_S1: // Wait for Tx RQ == 1
|
||||
LOGSTATE("DMA state S1\n");
|
||||
if (m_dreq[m_current_channel] == ASSERT_LINE)
|
||||
{
|
||||
m_state = STATE_S2;
|
||||
switch(m_m6844_channel[m_current_channel].control & 0x06)
|
||||
{
|
||||
case 0x00: // Mode 2 - single-byte transfer HALT steal mode
|
||||
case 0x02: // Mode 3 - block transfer mode
|
||||
m_out_drq2_cb(ASSERT_LINE);
|
||||
break;
|
||||
case 0x04: // Mode 1 - single-byte transfer TSC steal mode
|
||||
m_out_drq1_cb(ASSERT_LINE);
|
||||
break;
|
||||
default:
|
||||
m_out_drq1_cb(CLEAR_LINE);
|
||||
m_out_drq2_cb(CLEAR_LINE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGSTATE("Suspend in S1\n");
|
||||
suspend_until_trigger(1, true);
|
||||
m_icount = 0;
|
||||
}
|
||||
break;
|
||||
case STATE_S2: // Wait for DGRNT == 1
|
||||
LOGSTATE("DMA state S2\n");
|
||||
if (m_dgrnt == ASSERT_LINE && m_dreq[m_current_channel] == ASSERT_LINE)
|
||||
{
|
||||
m_out_txak_cb(m_current_channel);
|
||||
|
||||
if (m_m6844_channel[m_current_channel].active == 1) //active dma transfer
|
||||
{
|
||||
if (!(m_m6844_channel[m_current_channel].control & 0x01))
|
||||
{
|
||||
//uint8_t data = 0x55;
|
||||
uint8_t data = m_in_ior_cb[m_current_channel]();
|
||||
LOGTFR("DMA%d from device to memory location %04x: <- %02x\n", m_current_channel, m_m6844_channel[m_current_channel].address, data );
|
||||
m_out_memw_cb(m_m6844_channel[m_current_channel].address, data);
|
||||
}
|
||||
else // dma write to device from memory
|
||||
{
|
||||
uint8_t data = 0;
|
||||
LOGTFR("DMA from memory location to device %04x: -> %02x\n", m_m6844_channel[m_current_channel].address, data );
|
||||
//uint8_t data = m_in_memr_cb(m_m6844_channel[m_current_channel].address);
|
||||
//m_out_iow_cb[m_current_channel](data);
|
||||
}
|
||||
|
||||
if (m_m6844_channel[m_current_channel].control & 0x08)
|
||||
{
|
||||
m_m6844_channel[m_current_channel].address--;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_m6844_channel[m_current_channel].address++;
|
||||
}
|
||||
|
||||
m_m6844_channel[m_current_channel].counter--;
|
||||
|
||||
if (m_m6844_channel[m_current_channel].counter == 0)
|
||||
{
|
||||
m_out_drq1_cb(CLEAR_LINE);
|
||||
m_out_drq2_cb(CLEAR_LINE);
|
||||
m_m6844_channel[m_current_channel].control |= 0x80;
|
||||
m6844_update_interrupt();
|
||||
m_state = STATE_SI;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(m_m6844_channel[m_current_channel].control & 0x06)
|
||||
{
|
||||
case 0x00:
|
||||
LOGTFR("Mode 2 - single-byte transfer HALT steal mode\n");
|
||||
m_state = STATE_S1;
|
||||
m_out_drq2_cb(CLEAR_LINE);
|
||||
break;
|
||||
case 0x02:
|
||||
LOGTFR("Mode 3 - block transfer mode\n");
|
||||
m_state = STATE_S2; // Just for clarity, we are still in STATE_S2
|
||||
break;
|
||||
case 0x04:
|
||||
LOGTFR("Mode 1 - single-byte transfer TSC steal mode\n");
|
||||
m_state = STATE_S1;
|
||||
m_out_drq1_cb(CLEAR_LINE);
|
||||
break;
|
||||
default: // Undefined - needs verification on real hardware
|
||||
logerror("MC6844: undefined transfer mode, clearing DMA request\n");
|
||||
m_state = STATE_SI;
|
||||
m_out_drq1_cb(CLEAR_LINE);
|
||||
m_out_drq2_cb(CLEAR_LINE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGSTATE("Suspend in S2\n");
|
||||
suspend_until_trigger(1, true);
|
||||
m_icount = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logerror("MC6844: bad state, please report error\n");
|
||||
break;
|
||||
}
|
||||
|
||||
m_icount--;
|
||||
} while (m_icount > 0);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// READ/WRITE HANDLERS
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// read handler
|
||||
//-------------------------------------------------
|
||||
|
||||
uint8_t mc6844_device::read(offs_t offset)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
// switch off the offset we were given
|
||||
switch (offset)
|
||||
{
|
||||
// upper byte of address
|
||||
case 0x00:
|
||||
case 0x04:
|
||||
case 0x08:
|
||||
case 0x0c:
|
||||
result = m_m6844_channel[offset / 4].address >> 8;
|
||||
break;
|
||||
|
||||
// lower byte of address
|
||||
case 0x01:
|
||||
case 0x05:
|
||||
case 0x09:
|
||||
case 0x0d:
|
||||
result = m_m6844_channel[offset / 4].address & 0xff;
|
||||
break;
|
||||
|
||||
// upper byte of counter
|
||||
case 0x02:
|
||||
case 0x06:
|
||||
case 0x0a:
|
||||
case 0x0e:
|
||||
result = m_m6844_channel[offset / 4].counter >> 8;
|
||||
break;
|
||||
|
||||
// lower byte of counter
|
||||
case 0x03:
|
||||
case 0x07:
|
||||
case 0x0b:
|
||||
case 0x0f:
|
||||
result = m_m6844_channel[offset / 4].counter & 0xff;
|
||||
break;
|
||||
|
||||
// channel control
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
result = m_m6844_channel[offset - 0x10].control;
|
||||
|
||||
// A read here clears the 'DMA end' flag of the
|
||||
// associated channel.
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_m6844_channel[offset - 0x10].control &= ~0x80;
|
||||
if (m_m6844_interrupt & 0x80)
|
||||
m6844_update_interrupt();
|
||||
}
|
||||
break;
|
||||
|
||||
// priority control
|
||||
case 0x14:
|
||||
result = m_m6844_priority;
|
||||
break;
|
||||
|
||||
// interrupt control
|
||||
case 0x15:
|
||||
result = m_m6844_interrupt;
|
||||
break;
|
||||
|
||||
// chaining control
|
||||
case 0x16:
|
||||
result = m_m6844_chain;
|
||||
break;
|
||||
|
||||
// 0x17-0x1f not used
|
||||
default: break;
|
||||
}
|
||||
|
||||
return result & 0xff;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// write() handler
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc6844_device::write(offs_t offset, uint8_t data)
|
||||
{
|
||||
int i;
|
||||
LOGSETUP("DMA write %02x: %02x\n", offset, data);
|
||||
// switch off the offset we were given
|
||||
switch (offset)
|
||||
{
|
||||
// upper byte of address
|
||||
case 0x00:
|
||||
case 0x04:
|
||||
case 0x08:
|
||||
case 0x0c:
|
||||
LOGSETUP(" - upper address byte ch %d: %02x\n", offset / 4, data);
|
||||
m_m6844_channel[offset / 4].address = (m_m6844_channel[offset / 4].address & 0xff) | (data << 8);
|
||||
break;
|
||||
|
||||
// lower byte of address
|
||||
case 0x01:
|
||||
case 0x05:
|
||||
case 0x09:
|
||||
case 0x0d:
|
||||
LOGSETUP(" - lower address byte ch %d: %02x\n", offset / 4, data);
|
||||
m_m6844_channel[offset / 4].address = (m_m6844_channel[offset / 4].address & 0xff00) | (data & 0xff);
|
||||
break;
|
||||
|
||||
// upper byte of counter
|
||||
case 0x02:
|
||||
case 0x06:
|
||||
case 0x0a:
|
||||
case 0x0e:
|
||||
LOGSETUP(" - upper counter byte ch %d: %02x\n", offset / 4, data);
|
||||
m_m6844_channel[offset / 4].counter = (m_m6844_channel[offset / 4].counter & 0xff) | (data << 8);
|
||||
break;
|
||||
|
||||
// lower byte of counter
|
||||
case 0x03:
|
||||
case 0x07:
|
||||
case 0x0b:
|
||||
case 0x0f:
|
||||
LOGSETUP(" - lower counter byte ch %d: %02x\n", offset / 4, data);
|
||||
m_m6844_channel[offset / 4].counter = (m_m6844_channel[offset / 4].counter & 0xff00) | (data & 0xff);
|
||||
break;
|
||||
|
||||
// channel control
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
LOGSETUP(" - control byte ch %d: %02x\n", offset / 4, data);
|
||||
m_m6844_channel[offset - 0x10].control = (m_m6844_channel[offset - 0x10].control & 0xc0) | (data & 0x3f);
|
||||
break;
|
||||
|
||||
// priority control
|
||||
case 0x14:
|
||||
LOGSETUP(" - priority byte: %02x\n", data);
|
||||
m_m6844_priority = data;
|
||||
|
||||
// update each channel
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
// if we're going active...
|
||||
if (!m_m6844_channel[i].active && (data & (1 << i)))
|
||||
{
|
||||
// mark us active
|
||||
m_m6844_channel[i].active = 1;
|
||||
|
||||
// set the DMA busy bit and clear the DMA end bit
|
||||
m_m6844_channel[i].control |= 0x40;
|
||||
m_m6844_channel[i].control &= ~0x80;
|
||||
|
||||
// set the starting address, counter, and time
|
||||
m_m6844_channel[i].start_address = m_m6844_channel[i].address;
|
||||
m_m6844_channel[i].start_counter = m_m6844_channel[i].counter;
|
||||
}
|
||||
|
||||
// if we're going inactive...
|
||||
else if (m_m6844_channel[i].active && !(data & (1 << i)))
|
||||
{
|
||||
//mark us inactive
|
||||
m_m6844_channel[i].active = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// interrupt control
|
||||
case 0x15:
|
||||
LOGSETUP(" - interrupt control: %02x\n", data);
|
||||
m_m6844_interrupt = (m_m6844_interrupt & 0x80) | (data & 0x7f);
|
||||
m6844_update_interrupt();
|
||||
break;
|
||||
|
||||
// chaining control
|
||||
case 0x16:
|
||||
LOGSETUP(" - chaining control: %02x\n", data);
|
||||
m_m6844_chain = data;
|
||||
break;
|
||||
|
||||
// 0x17-0x1f not used
|
||||
default: break;
|
||||
}
|
||||
LOGSTATE("Trigger(1)\n");
|
||||
trigger(1);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// m6844_update_interrupt()
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc6844_device::m6844_update_interrupt()
|
||||
{
|
||||
uint8_t interrupt = 0;
|
||||
|
||||
interrupt |= BIT(m_m6844_channel[0].control, 7) & BIT(m_m6844_interrupt, 0);
|
||||
interrupt |= BIT(m_m6844_channel[1].control, 7) & BIT(m_m6844_interrupt, 1);
|
||||
interrupt |= BIT(m_m6844_channel[2].control, 7) & BIT(m_m6844_interrupt, 2);
|
||||
interrupt |= BIT(m_m6844_channel[3].control, 7) & BIT(m_m6844_interrupt, 3);
|
||||
|
||||
if (interrupt)
|
||||
{
|
||||
if (!(m_m6844_interrupt & 0x80))
|
||||
{
|
||||
// Set interrupt indication bit 7.
|
||||
m_m6844_interrupt |= 0x80;
|
||||
m_out_int_cb(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_m6844_interrupt & 0x80)
|
||||
{
|
||||
// Clear interrupt indication bit 7.
|
||||
m_m6844_interrupt &= 0x7f;
|
||||
m_out_int_cb(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
}
|
148
src/devices/machine/mc6844.h
Normal file
148
src/devices/machine/mc6844.h
Normal file
@ -0,0 +1,148 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Joakim Larsson Edström
|
||||
/***************************************************************************
|
||||
|
||||
Motorola 6844 emulation
|
||||
|
||||
****************************************************************************
|
||||
_____ _____
|
||||
VSS 1 |* \_/ | 40 E
|
||||
*CS / Tx AKBW 2 | | 39 *RESET
|
||||
R / *W 3 | | 38 DGRNT
|
||||
A0 4 | | 37 *DRQ1
|
||||
A1 5 | | 36 *DRQ2
|
||||
A2 6 | | 35 Tx AKA
|
||||
A3 7 | | 34 *TX STB
|
||||
A4 8 | | 33 *IRQ / *DEND
|
||||
A5 9 | | 32 Tx RQ0
|
||||
A6 10 | MC6844 | 31 Tx RQ1
|
||||
A7 11 | | 30 Tx RQ2
|
||||
A8 12 | | 29 Tx RQ3
|
||||
A9 13 | | 28 D0
|
||||
A10 14 | | 27 D1
|
||||
A11 15 | | 26 D2
|
||||
A12 16 | | 25 D3
|
||||
A13 17 | | 24 D4
|
||||
A14 18 | | 23 D5
|
||||
A15 19 | | 22 D6
|
||||
VCC 20 |_____________| 21 D7
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_MACHINE_MC6844_H
|
||||
#define MAME_MACHINE_MC6844_H
|
||||
|
||||
#pragma once
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> mc6844_device
|
||||
|
||||
class mc6844_device : public device_t, public device_execute_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
mc6844_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
auto out_int_callback() { return m_out_int_cb.bind(); }
|
||||
auto out_txak_callback() { return m_out_txak_cb.bind(); }
|
||||
auto out_drq1_callback() { return m_out_drq1_cb.bind(); }
|
||||
auto out_drq2_callback() { return m_out_drq2_cb.bind(); }
|
||||
auto in_memr_callback() { return m_in_memr_cb.bind(); }
|
||||
auto out_memw_callback() { return m_out_memw_cb.bind(); }
|
||||
|
||||
// I/O operations
|
||||
void write(offs_t offset, uint8_t data);
|
||||
uint8_t read(offs_t offset);
|
||||
template <unsigned CH> auto in_ior_callback() { return m_in_ior_cb[CH].bind(); }
|
||||
template <unsigned CH> auto out_iow_callback() { return m_out_iow_cb[CH].bind(); }
|
||||
|
||||
template <unsigned CH> DECLARE_WRITE_LINE_MEMBER( dreq_w ) { dma_request(CH, state); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( dgrnt_w ){ m_dgrnt = state; trigger(1); }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
//virtual void device_validity_check(validity_checker &valid) const override;
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void execute_run() override;
|
||||
|
||||
devcb_write_line m_out_int_cb;
|
||||
devcb_write8 m_out_txak_cb;
|
||||
devcb_write_line m_out_drq1_cb;
|
||||
devcb_write_line m_out_drq2_cb;
|
||||
devcb_read8 m_in_memr_cb;
|
||||
devcb_write8 m_out_memw_cb;
|
||||
devcb_read8 m_in_ior_cb[4];
|
||||
devcb_write8 m_out_iow_cb[4];
|
||||
|
||||
/* channel_data structure holds info about each 6844 DMA channel */
|
||||
struct m6844_channel_data
|
||||
{
|
||||
int active;
|
||||
int address;
|
||||
int counter;
|
||||
// Channel control register.
|
||||
// bit 0: Read / Write mode
|
||||
// bit 1: Mode control B
|
||||
// bit 2: Mode control A
|
||||
// bit 3: Address up (0) / down (1).
|
||||
// bit 4: Not used
|
||||
// bit 5: Not used
|
||||
// bit 6: Busy / Ready. Read only. Set when request
|
||||
// made. Cleared when transfer completed.
|
||||
// bit 7: DMA end flag. Read only? Set when transfer
|
||||
// completed. Cleared when control register
|
||||
// read. Sets IRQ.
|
||||
// Mode control A,B: 0,0 Mode2; 0,1 Mode 3; 1,0 Mode 0;
|
||||
// 1,1 Undefined.
|
||||
uint8_t control;
|
||||
int start_address;
|
||||
int start_counter;
|
||||
};
|
||||
|
||||
/* 6844 description */
|
||||
m6844_channel_data m_m6844_channel[4];
|
||||
uint8_t m_m6844_priority;
|
||||
// Interrupt control register.
|
||||
// Bit 0-3: channel interrupt enable, 1 enabled, 0 masked.
|
||||
// Bit 4-6: unused
|
||||
// Bit 7: Read only. Set to 1 when IRQ asserted. Clear when the
|
||||
// control register associated with the channel that caused the
|
||||
// interrut is read.
|
||||
uint8_t m_m6844_interrupt;
|
||||
uint8_t m_m6844_chain;
|
||||
void m6844_update_interrupt();
|
||||
|
||||
// State machine
|
||||
enum {
|
||||
STATE_SI,
|
||||
STATE_S0,
|
||||
STATE_S1,
|
||||
STATE_S2
|
||||
};
|
||||
|
||||
int m_state;
|
||||
int m_icount;
|
||||
int m_current_channel;
|
||||
int m_last_channel;
|
||||
|
||||
// input states
|
||||
bool m_dgrnt;
|
||||
bool m_dreq[4];
|
||||
private:
|
||||
void dma_request(int channel, int state);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(MC6844, mc6844_device)
|
||||
|
||||
#endif // MAME_MACHINE_MC6844_H
|
Loading…
Reference in New Issue
Block a user