mirror of
https://github.com/holub/mame
synced 2025-04-25 09:50:04 +03:00
Merge pull request #1373 from JoakimLarsson/fccpu30_10
Added interrupt support in DUSCC device, Force CPU30 board driver and…
This commit is contained in:
commit
aff04e4c60
@ -27,8 +27,11 @@
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define LOGR(x) LOG(x)
|
||||
#define LOGPRINT(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define LOG(x)
|
||||
#define LOGR(x)
|
||||
#define LOGINT(x) LOGPRINT(x)
|
||||
#define LOGSETUP(x) LOGPRINT(x)
|
||||
#if VERBOSE == 2
|
||||
#define logerror printf
|
||||
#endif
|
||||
@ -231,42 +234,42 @@ static INT32 ow_ofs = 0;
|
||||
|
||||
void pit68230_device::wr_pitreg_pgcr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_pgcr = data;
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_psrr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_psrr = data;
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_paddr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_paddr = data;
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_pbddr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_pbddr = data;
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_pcddr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_pcddr = data;
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_pivr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": Not implemented yet\n", FUNCNAME, data, m_owner->tag()));
|
||||
LOG(("%s(%02x) \"%s\": Not implemented yet\n", FUNCNAME, data, tag()));
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_pacr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_pacr = data;
|
||||
// callbacks
|
||||
/*PACR in Mode 0
|
||||
@ -289,13 +292,13 @@ void pit68230_device::wr_pitreg_pacr(UINT8 data)
|
||||
|
||||
void pit68230_device::wr_pitreg_pbcr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_pbcr = data;
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_padr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_padr |= (data & m_paddr);
|
||||
// callbacks
|
||||
m_pa_out_cb ((offs_t)0, m_padr);
|
||||
@ -303,7 +306,7 @@ void pit68230_device::wr_pitreg_padr(UINT8 data)
|
||||
|
||||
void pit68230_device::wr_pitreg_pbdr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_pbdr |= (data & m_pbddr);
|
||||
// callbacks
|
||||
m_pb_out_cb ((offs_t)0, m_pbdr & m_pbddr);
|
||||
@ -311,7 +314,7 @@ void pit68230_device::wr_pitreg_pbdr(UINT8 data)
|
||||
|
||||
void pit68230_device::wr_pitreg_pcdr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_pcdr |= (data & m_pcddr);
|
||||
// callbacks
|
||||
m_pc_out_cb ((offs_t)0, m_pcdr);
|
||||
@ -319,7 +322,7 @@ void pit68230_device::wr_pitreg_pcdr(UINT8 data)
|
||||
|
||||
void pit68230_device::wr_pitreg_psr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_psr = data;
|
||||
}
|
||||
|
||||
@ -395,7 +398,7 @@ void pit68230_device::wr_pitreg_tcr(UINT8 data)
|
||||
int pen = 0;
|
||||
int sqr = 0;
|
||||
|
||||
LOG(("%s(%02x) %s\n", FUNCNAME, data, m_owner->tag()));
|
||||
LOG(("%s(%02x) %s\n", FUNCNAME, data, tag()));
|
||||
m_tcr = data;
|
||||
switch (m_tcr & REG_TCR_TOUT_TIACK_MASK)
|
||||
{
|
||||
@ -440,40 +443,41 @@ void pit68230_device::wr_pitreg_tcr(UINT8 data)
|
||||
|
||||
void pit68230_device::wr_pitreg_tivr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, m_owner->tag()));
|
||||
LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, tag()));
|
||||
m_tivr = data;
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_cprh(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_cpr &= ~0xff0000;
|
||||
m_cpr |= ((data << 16) & 0xff0000);
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_cprm(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_cpr &= ~0x00ff00;
|
||||
m_cpr |= ((data << 8) & 0x00ff00);
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_cprl(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
|
||||
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
|
||||
m_cpr &= ~0x0000ff;
|
||||
m_cpr |= ((data << 0) & 0x0000ff);
|
||||
}
|
||||
|
||||
void pit68230_device::wr_pitreg_tsr(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, m_owner->tag()));
|
||||
LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, tag()));
|
||||
m_tsr = data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER (pit68230_device::write)
|
||||
{
|
||||
LOG(("%s %s \n",tag(), FUNCNAME));
|
||||
LOG(("\"%s\" %s: Register write '%02x' -> [%02x]\n", tag(), FUNCNAME, data, offset ));
|
||||
LOGSETUP((" * %s Reg %02x <- %02x \n", tag(), offset, data));
|
||||
switch (offset) {
|
||||
case PIT_68230_PGCR: wr_pitreg_pgcr(data); break;
|
||||
case PIT_68230_PSRR: wr_pitreg_psrr(data); break;
|
||||
|
@ -31,12 +31,16 @@
|
||||
* external hardware. It is expressly forbidden to change register bits, except those defined for the user.
|
||||
*
|
||||
*/
|
||||
#include "fga002.h"
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define LOGPRINT(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define LOG(x)
|
||||
#define LOGR(x)
|
||||
#define LOGSETUP(x)
|
||||
#define LOGINT(x) LOGPRINT(x)
|
||||
#define LOGVEC(x)
|
||||
#define LOGLVL(x)
|
||||
#define LOGIACK(x) LOGPRINT(x)
|
||||
#if VERBOSE == 2
|
||||
#define logerror printf
|
||||
#endif
|
||||
@ -49,6 +53,8 @@
|
||||
#define LLFORMAT "%lld"
|
||||
#endif
|
||||
|
||||
#include "fga002.h"
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
@ -65,22 +71,48 @@ const device_type FGA002 = &device_creator<fga002_device>;
|
||||
|
||||
fga002_device::fga002_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant, const char *shortname, const char *source)
|
||||
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
|
||||
, m_out_int_cb(*this)
|
||||
, m_liack4_cb(*this)
|
||||
, m_liack5_cb(*this)
|
||||
, m_liack6_cb(*this)
|
||||
, m_liack7_cb(*this)
|
||||
, m_irq_level((UINT8)0)
|
||||
{
|
||||
for (auto & elem : m_int_state)
|
||||
elem = 0;
|
||||
}
|
||||
|
||||
fga002_device::fga002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, FGA002, "FGA-002", tag, owner, clock, "fga002", __FILE__)
|
||||
, m_out_int_cb(*this)
|
||||
, m_liack4_cb(*this)
|
||||
, m_liack5_cb(*this)
|
||||
, m_liack6_cb(*this)
|
||||
, m_liack7_cb(*this)
|
||||
, m_irq_level((UINT8)0)
|
||||
{
|
||||
for (auto & elem : m_int_state)
|
||||
elem = 0;
|
||||
}
|
||||
|
||||
void fga002_device::device_start()
|
||||
{
|
||||
LOG(("%s\n", FUNCNAME));
|
||||
|
||||
// resolve callbacks
|
||||
m_out_int_cb.resolve_safe();
|
||||
m_liack4_cb.resolve_safe(0);
|
||||
m_liack5_cb.resolve_safe(0);
|
||||
m_liack6_cb.resolve_safe(0);
|
||||
m_liack7_cb.resolve_safe(0);
|
||||
|
||||
// Timers
|
||||
fga_timer = timer_alloc(TIMER_ID_FGA);
|
||||
|
||||
save_pointer (NAME (m_fga002), sizeof(m_fga002));
|
||||
|
||||
// Interrupts
|
||||
save_item(NAME(m_int_state));
|
||||
}
|
||||
|
||||
void fga002_device::device_reset()
|
||||
@ -103,6 +135,14 @@ void fga002_device::device_reset()
|
||||
m_fga002[FGA_ISSYSFAIL] = 0x80;
|
||||
m_fga002[FGA_ISFMB0MES] = 0x80;
|
||||
m_fga002[FGA_ISFMB1MES] = 0x80;
|
||||
m_fga002[FGA_ISLOCAL0] = 0x80;
|
||||
m_fga002[FGA_ISLOCAL1] = 0x80;
|
||||
m_fga002[FGA_ISLOCAL2] = 0x80;
|
||||
m_fga002[FGA_ISLOCAL3] = 0x80;
|
||||
m_fga002[FGA_ISLOCAL4] = 0x80;
|
||||
m_fga002[FGA_ISLOCAL5] = 0x80;
|
||||
m_fga002[FGA_ISLOCAL6] = 0x80;
|
||||
m_fga002[FGA_ISLOCAL7] = 0x80;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -134,7 +174,163 @@ void fga002_device::device_timer (emu_timer &timer, device_timer_id id, INT32 pa
|
||||
}
|
||||
}
|
||||
|
||||
/* The FGA002 Interrupts
|
||||
|
||||
The FGA-002 Gate Array provides high end support for interrupt functionality. It manages interrupt sources
|
||||
within the gate array as well as external sources connected to the gate array. The FGA-002 Gate Array is an
|
||||
efficient interface for various interrupt sources to the local CPU, and supports up to 18 external interrupters.
|
||||
|
||||
Interrupt inputs provided for external interrupt sources (exclusive of the VMEbus interrupt inputs) offer
|
||||
maximum flexibility as they may be configured to be level/edge sensitive or low/high active. The control of
|
||||
these features is performed by two bits contained in the extended interrupt control registers. The Interrupt
|
||||
Auto Clear bit in the extended interrupt control register determines, whether the interrupt of an edge sensitive
|
||||
input is cleared automatically during the interrupt acknowledge cycle or has to be cleared by the interrupt
|
||||
service routine. Each interrupt source is bound to an individual interrupt channel which has its own assigned
|
||||
vector number. The interrupt channels are configured by the Interrupt Control Registers where a 3 bit code for
|
||||
the level and a bit for enable/disable control are stored. Each interrupt channel may be programmed to interrupt
|
||||
the processor at any level.
|
||||
|
||||
The vector table of the gate array is a group of 64 vectors. The two most significant bits of the 8 bit vector
|
||||
are programmable via register bits. The rest of the bits are assigned by gate array hardware. Not all of the
|
||||
64 vectors are used in the present gate array, and those not used are reserved for future extensions.
|
||||
|
||||
The following groups of interrupt sources are supported:
|
||||
1. Internal Interrupt Sources
|
||||
- DMA CONTROLLER
|
||||
- TIMER
|
||||
- FORCE MESSAGE BROADCAST -FMB-
|
||||
- PARITY ERROR
|
||||
- 8 MAILBOXES
|
||||
2. External Interrupt Sources
|
||||
Onboard interrupts:
|
||||
- LOCAL 0-7 inputs
|
||||
- ABORT Key input
|
||||
- ACFAIL input
|
||||
- SYSFAIL input
|
||||
VMEbus interrupts:
|
||||
- 7 VMEbus interrupt inputs
|
||||
*/
|
||||
|
||||
// TODO: Add more intrrupts sources in priority order, 18 in total.
|
||||
const fga_irq_t fga002_device::m_irq_sources[] = {
|
||||
{INT_LOCAL0, FGA_ISLOCAL0, FGA_ICRLOCAL0 },
|
||||
{INT_LOCAL1, FGA_ISLOCAL1, FGA_ICRLOCAL1 },
|
||||
{INT_LOCAL2, FGA_ISLOCAL2, FGA_ICRLOCAL2 },
|
||||
{INT_LOCAL3, FGA_ISLOCAL3, FGA_ICRLOCAL3 },
|
||||
{INT_LOCAL4, FGA_ISLOCAL4, FGA_ICRLOCAL4 },
|
||||
{INT_LOCAL5, FGA_ISLOCAL5, FGA_ICRLOCAL5 },
|
||||
{INT_LOCAL6, FGA_ISLOCAL6, FGA_ICRLOCAL6 },
|
||||
{INT_LOCAL7, FGA_ISLOCAL7, FGA_ICRLOCAL7 }
|
||||
};
|
||||
|
||||
|
||||
void fga002_device::trigger_interrupt(UINT8 data)
|
||||
{
|
||||
UINT8 icr = 0;
|
||||
|
||||
LOGINT(("%s(%02x)\n", FUNCNAME, data));
|
||||
|
||||
/* The Interrupt Control Register (ICR*) bit, must be set for the correspondning channel */
|
||||
// TODO: Support programmable assert level for interrupt source
|
||||
switch(data)
|
||||
{
|
||||
case INT_LOCAL0: icr = m_fga002[FGA_ICRLOCAL0]; m_fga002[FGA_ISLOCAL0] = 0x00; break;
|
||||
case INT_LOCAL1: icr = m_fga002[FGA_ICRLOCAL1]; m_fga002[FGA_ISLOCAL1] = 0x00; break;
|
||||
case INT_LOCAL2: icr = m_fga002[FGA_ICRLOCAL2]; m_fga002[FGA_ISLOCAL2] = 0x00; break;
|
||||
case INT_LOCAL3: icr = m_fga002[FGA_ICRLOCAL3]; m_fga002[FGA_ISLOCAL3] = 0x00; break;
|
||||
case INT_LOCAL4: icr = m_fga002[FGA_ICRLOCAL4]; m_fga002[FGA_ISLOCAL4] = 0x00; break;
|
||||
case INT_LOCAL5: icr = m_fga002[FGA_ICRLOCAL5]; m_fga002[FGA_ISLOCAL5] = 0x00; break;
|
||||
case INT_LOCAL6: icr = m_fga002[FGA_ICRLOCAL6]; m_fga002[FGA_ISLOCAL6] = 0x00; break;
|
||||
case INT_LOCAL7: icr = m_fga002[FGA_ICRLOCAL7]; m_fga002[FGA_ISLOCAL7] = 0x00; break;
|
||||
default: LOGINT((" - interrupt source %d - not supported", data)); return;
|
||||
}
|
||||
if ((icr & REG_ICR_ENABLE) == 0 || (icr & REG_ICR_LVL_MSK) == 0)
|
||||
{
|
||||
LOGINT((" - The Interrupt Control Register bit for channel %02x is not set or level is 0, blocking attempt to interrupt\n", data));
|
||||
return;
|
||||
}
|
||||
m_irq_level = icr & REG_ICR_LVL_MSK;
|
||||
LOGINT((" - Interrupt Level %d, caused by ICR %02x with vector %02x\n", m_irq_level, icr, data ));
|
||||
|
||||
// trigger intrrupt to CPU through board driver callback.
|
||||
m_out_int_cb(ASSERT_LINE);
|
||||
}
|
||||
|
||||
IRQ_CALLBACK_MEMBER(fga002_device::iack)
|
||||
{
|
||||
int vec = M68K_INT_ACK_AUTOVECTOR;
|
||||
int vec_found = 0;
|
||||
int level;
|
||||
|
||||
LOGIACK(("%s %s()\n", tag(), FUNCNAME));
|
||||
for (level = 7; level > 0; level--)
|
||||
{
|
||||
LOGLVL(("\n LEVEL %d\n", level));
|
||||
// Find first interrupt on this level to acknowledge
|
||||
LOGLVL(("Vec Status[val] Control[val]\n"));
|
||||
for (auto & elem : m_irq_sources)
|
||||
{
|
||||
LOGLVL((" %02x %02x[%02x] %02x[%02x]\n",
|
||||
elem.vector,
|
||||
elem.status, m_fga002[elem.status],
|
||||
elem.control, m_fga002[elem.control]));
|
||||
// Right level?
|
||||
LOGLVL(("Level %02x == ICR %02x is %s\n", level, m_fga002[elem.control] & REG_ICR_LVL_MSK, ((m_fga002[elem.control] & REG_ICR_LVL_MSK) == level) ? "true!" : "false.."));
|
||||
if ((m_fga002[elem.control] & REG_ICR_LVL_MSK) == level)
|
||||
{
|
||||
// Pending interrupt?
|
||||
LOGLVL(("ISx %02x interrupt is %s\n", m_fga002[elem.status], (m_fga002[elem.status] & REG_ISLOCAL_IRQ) ? "cleared though.." : "pending!"));
|
||||
if ((m_fga002[elem.status] & REG_ISLOCAL_IRQ) == 0)
|
||||
{
|
||||
if (vec_found == 0)
|
||||
{
|
||||
vec = elem.vector; // Assume internal vector
|
||||
LOGVEC((" - org vec:%02x ", vec));
|
||||
switch (vec)
|
||||
{
|
||||
// Assuming that the attached device is returning -1 (INT_ACK_AUTOVECTOR) if no vector is provided, then we keep internal vector
|
||||
// TODO: Add device specific parameter that maps devices no-vector response to INT_ACK_AUTOVECTOR (and preferably INT_ACK_NOVECTOR)
|
||||
case INT_LOCAL4: if (( (m_fga002[FGA_LOCALIACK] & REG_LIACK_LOCAL4_MSK) >> 0) != REG_LIACK_INT_IACK ) vec = m_liack4_cb(); break;
|
||||
case INT_LOCAL5: if (( (m_fga002[FGA_LOCALIACK] & REG_LIACK_LOCAL5_MSK) >> 2) != REG_LIACK_INT_IACK ) vec = m_liack5_cb(); break;
|
||||
case INT_LOCAL6: if (( (m_fga002[FGA_LOCALIACK] & REG_LIACK_LOCAL6_MSK) >> 4) != REG_LIACK_INT_IACK ) vec = m_liack6_cb(); break;
|
||||
case INT_LOCAL7: if (( (m_fga002[FGA_LOCALIACK] & REG_LIACK_LOCAL7_MSK) >> 6) != REG_LIACK_INT_IACK ) vec = m_liack7_cb(); break;
|
||||
// All other devices uses the vector provided by the FGA.
|
||||
default: break; /* Since we need the vector for the switch statement the default job is already done */
|
||||
}
|
||||
LOGVEC(("dev:%02x ", vec));
|
||||
if (vec == INT_ACK_AUTOVECTOR) vec = INT_EMPTY;
|
||||
LOGVEC(("avec:%02x ", vec));
|
||||
|
||||
// Add vector page bits and return vector
|
||||
vec = (vec & 0x3f) | ((m_fga002[FGA_CTL3] & REG_CTL3_VECTORBITS7_6) << 4);
|
||||
LOGVEC(("pvec:%02x\n", vec));
|
||||
|
||||
LOGVEC((" - Interrupt Acknowledge Vector %02x\n", vec));
|
||||
/* TODO:
|
||||
- Support auto clear of interrupt source and level triggered
|
||||
*/
|
||||
vec_found = 1;
|
||||
}
|
||||
else{
|
||||
m_irq_level = level;
|
||||
LOGIACK((" - Interrupt Acknowledge Vector %02x, next interrupt has level %02x\n", vec, m_irq_level));
|
||||
m_out_int_cb(CLEAR_LINE);
|
||||
return vec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGIACK((" - Interrupt Acknowledge Vector %02x, next interrupt is off %02x\n", vec, m_irq_level));
|
||||
m_out_int_cb(CLEAR_LINE);
|
||||
return vec;
|
||||
}
|
||||
|
||||
int fga002_device::get_irq_level()
|
||||
{
|
||||
LOGINT(("%s %s() - %02x\n", tag(), FUNCNAME, m_irq_level));
|
||||
return m_irq_level;
|
||||
}
|
||||
|
||||
/* The FGA002 Timer
|
||||
|
||||
@ -277,13 +473,13 @@ UINT8 fga002_device::do_fga002reg_tim0count_r()
|
||||
*/
|
||||
void fga002_device::do_fga002reg_icrtim0_w(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
LOGINT(("%s(%02x)\n", FUNCNAME, data));
|
||||
m_fga002[FGA_ICRTIM0] = data;
|
||||
}
|
||||
|
||||
UINT8 fga002_device::do_fga002reg_icrtim0_r()
|
||||
{
|
||||
LOG(("%s() %02x\n", FUNCNAME, m_fga002[FGA_ICRTIM0]));
|
||||
LOGINT(("%s() %02x\n", FUNCNAME, m_fga002[FGA_ICRTIM0]));
|
||||
return m_fga002[FGA_ICRTIM0];
|
||||
}
|
||||
|
||||
@ -295,19 +491,129 @@ UINT8 fga002_device::do_fga002reg_icrtim0_r()
|
||||
*/
|
||||
void fga002_device::do_fga002reg_istim0_w(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
LOGINT(("%s(%02x)\n", FUNCNAME, data));
|
||||
m_fga002[FGA_ISTIM0] &= ~REG_ISTIM0_TIM_INT; // Clear timer interrupt status
|
||||
}
|
||||
|
||||
UINT8 fga002_device::do_fga002reg_istim0_r()
|
||||
{
|
||||
LOG(("%s() %02x\n", FUNCNAME, m_fga002[FGA_ISTIM0]));
|
||||
LOGINT(("%s() %02x\n", FUNCNAME, m_fga002[FGA_ISTIM0]));
|
||||
return m_fga002[FGA_ISTIM0];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FGA-002 interrupt support
|
||||
*/
|
||||
void fga002_device::do_fga002reg_localiack_w(UINT8 data)
|
||||
{
|
||||
m_fga002[FGA_LOCALIACK] = data;
|
||||
|
||||
#if VERBOSE
|
||||
const char *liack[] = {"internal", "no", "external 1us", "external 500ns"};
|
||||
|
||||
LOGINT(("%s(%02x)\n", FUNCNAME, data));
|
||||
LOGINT(("- LOCAL7: %s vector\n", liack[(data >> 6) & 0x03]));
|
||||
LOGINT(("- LOCAL6: %s vector\n", liack[(data >> 4) & 0x03]));
|
||||
LOGINT(("- LOCAL5: %s vector\n", liack[(data >> 2) & 0x03]));
|
||||
LOGINT(("- LOCAL4: %s vector\n", liack[(data >> 0) & 0x03]));
|
||||
#endif
|
||||
}
|
||||
|
||||
UINT8 fga002_device::do_fga002reg_localiack_r()
|
||||
{
|
||||
UINT8 ret = m_fga002[FGA_LOCALIACK];
|
||||
LOGINT(("%s() <- %02x\n", FUNCNAME, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
UINT8 fga002_device::do_fga002reg_ctl3_r()
|
||||
{
|
||||
UINT8 ret = m_fga002[FGA_CTL3];
|
||||
LOGINT(("%s() <- %02x\n", FUNCNAME, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fga002_device::do_fga002reg_ctl3_w(UINT8 data)
|
||||
{
|
||||
m_fga002[FGA_CTL3] = data;
|
||||
LOGINT(("%s(%02x)\n", FUNCNAME, data));
|
||||
}
|
||||
|
||||
// Local Interrupt control register methods
|
||||
UINT8 fga002_device::do_fga002reg_icrlocal0_r(){ UINT8 ret = m_fga002[FGA_ICRLOCAL0]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_icrlocal1_r(){ UINT8 ret = m_fga002[FGA_ICRLOCAL1]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_icrlocal2_r(){ UINT8 ret = m_fga002[FGA_ICRLOCAL2]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_icrlocal3_r(){ UINT8 ret = m_fga002[FGA_ICRLOCAL3]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_icrlocal4_r(){ UINT8 ret = m_fga002[FGA_ICRLOCAL4]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_icrlocal5_r(){ UINT8 ret = m_fga002[FGA_ICRLOCAL5]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_icrlocal6_r(){ UINT8 ret = m_fga002[FGA_ICRLOCAL6]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_icrlocal7_r(){ UINT8 ret = m_fga002[FGA_ICRLOCAL7]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
|
||||
void fga002_device::do_fga002reg_icrlocal0_w(UINT8 data){ m_fga002[FGA_ICRLOCAL0] = data; LOGINT(("%s(%02x)\n", FUNCNAME, data)); }
|
||||
void fga002_device::do_fga002reg_icrlocal1_w(UINT8 data){ m_fga002[FGA_ICRLOCAL1] = data; LOGINT(("%s(%02x)\n", FUNCNAME, data)); }
|
||||
void fga002_device::do_fga002reg_icrlocal2_w(UINT8 data){ m_fga002[FGA_ICRLOCAL2] = data; LOGINT(("%s(%02x)\n", FUNCNAME, data)); }
|
||||
void fga002_device::do_fga002reg_icrlocal3_w(UINT8 data){ m_fga002[FGA_ICRLOCAL3] = data; LOGINT(("%s(%02x)\n", FUNCNAME, data)); }
|
||||
void fga002_device::do_fga002reg_icrlocal4_w(UINT8 data){ m_fga002[FGA_ICRLOCAL4] = data; LOGINT(("%s(%02x)\n", FUNCNAME, data)); }
|
||||
void fga002_device::do_fga002reg_icrlocal5_w(UINT8 data){ m_fga002[FGA_ICRLOCAL5] = data; LOGINT(("%s(%02x)\n", FUNCNAME, data)); }
|
||||
void fga002_device::do_fga002reg_icrlocal6_w(UINT8 data){ m_fga002[FGA_ICRLOCAL6] = data; LOGINT(("%s(%02x)\n", FUNCNAME, data)); }
|
||||
void fga002_device::do_fga002reg_icrlocal7_w(UINT8 data){ m_fga002[FGA_ICRLOCAL7] = data; LOGINT(("%s(%02x)\n", FUNCNAME, data)); }
|
||||
|
||||
// Local Interrupt Status Register methods
|
||||
UINT8 fga002_device::do_fga002reg_islocal0_r(){ UINT8 ret = m_fga002[FGA_ISLOCAL0]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_islocal1_r(){ UINT8 ret = m_fga002[FGA_ISLOCAL1]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_islocal2_r(){ UINT8 ret = m_fga002[FGA_ISLOCAL2]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_islocal3_r(){ UINT8 ret = m_fga002[FGA_ISLOCAL3]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_islocal4_r(){ UINT8 ret = m_fga002[FGA_ISLOCAL4]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_islocal5_r(){ UINT8 ret = m_fga002[FGA_ISLOCAL5]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_islocal6_r(){ UINT8 ret = m_fga002[FGA_ISLOCAL6]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
UINT8 fga002_device::do_fga002reg_islocal7_r(){ UINT8 ret = m_fga002[FGA_ISLOCAL7]; LOGINT(("%s() <- %02x\n", FUNCNAME, ret)); return ret; }
|
||||
|
||||
void fga002_device::islocal_w(int status, int vector, int control, int data)
|
||||
{
|
||||
m_fga002[status] = m_fga002[control] & REG_ICR_EDGE ? 0x80 : 0x00;
|
||||
LOGINT(("%s(%02x)\n", FUNCNAME, m_fga002[status]));
|
||||
}
|
||||
|
||||
// TODO: support level triggered interrupts, only edge triggered interrupts are supported atm
|
||||
void fga002_device::do_fga002reg_islocal0_w(UINT8 data){ LOGINT(("%s\n", FUNCNAME)); islocal_w( FGA_ISLOCAL0, INT_LOCAL0, FGA_ICRLOCAL0, data ); }
|
||||
void fga002_device::do_fga002reg_islocal1_w(UINT8 data){ LOGINT(("%s\n", FUNCNAME)); islocal_w( FGA_ISLOCAL1, INT_LOCAL1, FGA_ICRLOCAL1, data ); }
|
||||
void fga002_device::do_fga002reg_islocal2_w(UINT8 data){ LOGINT(("%s\n", FUNCNAME)); islocal_w( FGA_ISLOCAL2, INT_LOCAL2, FGA_ICRLOCAL2, data ); }
|
||||
void fga002_device::do_fga002reg_islocal3_w(UINT8 data){ LOGINT(("%s\n", FUNCNAME)); islocal_w( FGA_ISLOCAL3, INT_LOCAL3, FGA_ICRLOCAL3, data ); }
|
||||
void fga002_device::do_fga002reg_islocal4_w(UINT8 data){ LOGINT(("%s\n", FUNCNAME)); islocal_w( FGA_ISLOCAL4, INT_LOCAL4, FGA_ICRLOCAL4, data ); m_liack4_cb(); } /* terminate device IRQ */
|
||||
void fga002_device::do_fga002reg_islocal5_w(UINT8 data){ LOGINT(("%s\n", FUNCNAME)); islocal_w( FGA_ISLOCAL5, INT_LOCAL5, FGA_ICRLOCAL5, data ); m_liack5_cb(); }
|
||||
void fga002_device::do_fga002reg_islocal6_w(UINT8 data){ LOGINT(("%s\n", FUNCNAME)); islocal_w( FGA_ISLOCAL6, INT_LOCAL6, FGA_ICRLOCAL6, data ); m_liack6_cb(); }
|
||||
void fga002_device::do_fga002reg_islocal7_w(UINT8 data){ LOGINT(("%s\n", FUNCNAME)); islocal_w( FGA_ISLOCAL6, INT_LOCAL7, FGA_ICRLOCAL7, data ); m_liack7_cb(); }
|
||||
|
||||
// Local IRQ callbacks
|
||||
// TODO: support level triggered interrupts, ICR bit 6, only edge triggered interrupts are supported atm
|
||||
// TODO: support programmable assertion levels ICR bit 5, a call to this function assumes assertion atm
|
||||
void fga002_device::lirq_w(int status, int vector, int control, int state)
|
||||
{
|
||||
LOGINT((" - %s\n", state == ASSERT_LINE ? "Asserted" : "Cleared"));
|
||||
if (state == ASSERT_LINE)
|
||||
{
|
||||
m_fga002[status] &= ~REG_ISLOCAL_IRQ;
|
||||
trigger_interrupt(vector);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fga002[status] |= REG_ISLOCAL_IRQ;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER (fga002_device::lirq0_w) { LOGINT(("%s\n", FUNCNAME)); lirq_w( FGA_ISLOCAL0, INT_LOCAL0, FGA_ICRLOCAL0, state ); }
|
||||
WRITE_LINE_MEMBER (fga002_device::lirq1_w) { LOGINT(("%s\n", FUNCNAME)); lirq_w( FGA_ISLOCAL1, INT_LOCAL1, FGA_ICRLOCAL1, state ); }
|
||||
WRITE_LINE_MEMBER (fga002_device::lirq2_w) { LOGINT(("%s\n", FUNCNAME)); lirq_w( FGA_ISLOCAL2, INT_LOCAL2, FGA_ICRLOCAL2, state ); }
|
||||
WRITE_LINE_MEMBER (fga002_device::lirq3_w) { LOGINT(("%s\n", FUNCNAME)); lirq_w( FGA_ISLOCAL3, INT_LOCAL3, FGA_ICRLOCAL3, state ); }
|
||||
WRITE_LINE_MEMBER (fga002_device::lirq4_w) { LOGINT(("%s\n", FUNCNAME)); lirq_w( FGA_ISLOCAL4, INT_LOCAL4, FGA_ICRLOCAL4, state ); }
|
||||
WRITE_LINE_MEMBER (fga002_device::lirq5_w) { LOGINT(("%s\n", FUNCNAME)); lirq_w( FGA_ISLOCAL5, INT_LOCAL5, FGA_ICRLOCAL5, state ); }
|
||||
WRITE_LINE_MEMBER (fga002_device::lirq6_w) { LOGINT(("%s\n", FUNCNAME)); lirq_w( FGA_ISLOCAL6, INT_LOCAL6, FGA_ICRLOCAL6, state ); }
|
||||
WRITE_LINE_MEMBER (fga002_device::lirq7_w) { LOGINT(("%s\n", FUNCNAME)); lirq_w( FGA_ISLOCAL7, INT_LOCAL7, FGA_ICRLOCAL7, state ); }
|
||||
|
||||
WRITE8_MEMBER (fga002_device::write){
|
||||
LOG(("%s[%04x] <- %02x - ", FUNCNAME, offset, data));
|
||||
LOGSETUP((" * %s Reg %04x <- %02x\n", tag(), offset, data));
|
||||
switch(offset)
|
||||
{
|
||||
case FGA_SPECIALENA : LOG(("FGA_SPECIALENA - not implemented\n")); m_fga002[FGA_SPECIALENA] = data; break;
|
||||
@ -340,7 +646,7 @@ WRITE8_MEMBER (fga002_device::write){
|
||||
case FGA_ICRFMB1REF : LOG(("FGA_ICRFMB1REF - not implemented\n")); m_fga002[FGA_ICRFMB1REF] = data; break;
|
||||
case FGA_ICRFMB0MES : LOG(("FGA_ICRFMB0MES - not implemented\n")); m_fga002[FGA_ICRFMB0MES] = data; break;
|
||||
case FGA_ICRFMB1MES : LOG(("FGA_ICRFMB1MES - not implemented\n")); m_fga002[FGA_ICRFMB1MES] = data; break;
|
||||
case FGA_CTL3 : LOG(("FGA_CTL3 - not implemented\n")); m_fga002[FGA_CTL3] = data; break;
|
||||
case FGA_CTL3 : do_fga002reg_ctl3_w(data); break;
|
||||
case FGA_CTL4 : LOG(("FGA_CTL4 - not implemented\n")); m_fga002[FGA_CTL4] = data; break;
|
||||
case FGA_ICRPARITY : LOG(("FGA_ICRPARITY - not implemented\n")); m_fga002[FGA_ICRPARITY] = data; break;
|
||||
case FGA_AUXPINCTL : LOG(("FGA_AUXPINCTL - not implemented\n")); m_fga002[FGA_AUXPINCTL] = data; break;
|
||||
@ -354,14 +660,14 @@ WRITE8_MEMBER (fga002_device::write){
|
||||
case FGA_ICRABORT : LOG(("FGA_ICRABORT - not implemented\n")); m_fga002[FGA_ICRABORT] = data; break;
|
||||
case FGA_ICRACFAIL : LOG(("FGA_ICRACFAIL - not implemented\n")); m_fga002[FGA_ICRACFAIL] = data; break;
|
||||
case FGA_ICRSYSFAIL : LOG(("FGA_ICRSYSFAIL - not implemented\n")); m_fga002[FGA_ICRSYSFAIL] = data; break;
|
||||
case FGA_ICRLOCAL0 : LOG(("FGA_ICRLOCAL0 - not implemented\n")); m_fga002[FGA_ICRLOCAL0] = data; break;
|
||||
case FGA_ICRLOCAL1 : LOG(("FGA_ICRLOCAL1 - not implemented\n")); m_fga002[FGA_ICRLOCAL1] = data; break;
|
||||
case FGA_ICRLOCAL2 : LOG(("FGA_ICRLOCAL2 - not implemented\n")); m_fga002[FGA_ICRLOCAL2] = data; break;
|
||||
case FGA_ICRLOCAL3 : LOG(("FGA_ICRLOCAL3 - not implemented\n")); m_fga002[FGA_ICRLOCAL3] = data; break;
|
||||
case FGA_ICRLOCAL4 : LOG(("FGA_ICRLOCAL4 - not implemented\n")); m_fga002[FGA_ICRLOCAL4] = data; break;
|
||||
case FGA_ICRLOCAL5 : LOG(("FGA_ICRLOCAL5 - not implemented\n")); m_fga002[FGA_ICRLOCAL5] = data; break;
|
||||
case FGA_ICRLOCAL6 : LOG(("FGA_ICRLOCAL6 - not implemented\n")); m_fga002[FGA_ICRLOCAL6] = data; break;
|
||||
case FGA_ICRLOCAL7 : LOG(("FGA_ICRLOCAL7 - not implemented\n")); m_fga002[FGA_ICRLOCAL7] = data; break;
|
||||
case FGA_ICRLOCAL0 : do_fga002reg_icrlocal0_w(data); break;
|
||||
case FGA_ICRLOCAL1 : do_fga002reg_icrlocal1_w(data); break;
|
||||
case FGA_ICRLOCAL2 : do_fga002reg_icrlocal2_w(data); break;
|
||||
case FGA_ICRLOCAL3 : do_fga002reg_icrlocal3_w(data); break;
|
||||
case FGA_ICRLOCAL4 : do_fga002reg_icrlocal4_w(data); break;
|
||||
case FGA_ICRLOCAL5 : do_fga002reg_icrlocal5_w(data); break;
|
||||
case FGA_ICRLOCAL6 : do_fga002reg_icrlocal6_w(data); break;
|
||||
case FGA_ICRLOCAL7 : do_fga002reg_icrlocal7_w(data); break;
|
||||
case FGA_ENAMCODE : LOG(("FGA_ENAMCODE - not implemented\n")); m_fga002[FGA_ENAMCODE] = data; break;
|
||||
case FGA_CTL10 : LOG(("FGA_CTL10 - not implemented\n")); m_fga002[FGA_CTL10] = data; break;
|
||||
case FGA_CTL11 : LOG(("FGA_CTL11 - not implemented\n")); m_fga002[FGA_CTL11] = data; break;
|
||||
@ -379,7 +685,7 @@ WRITE8_MEMBER (fga002_device::write){
|
||||
case FGA_DMA_GENERAL : LOG(("FGA_DMA_GENERAL - not implemented\n")); m_fga002[FGA_DMA_GENERAL] = data; break;
|
||||
case FGA_CTL12 : LOG(("FGA_CTL12 - not implemented\n")); m_fga002[FGA_CTL12] = data; break;
|
||||
case FGA_LIOTIMING : LOG(("FGA_LIOTIMING - not implemented\n")); m_fga002[FGA_LIOTIMING] = data; break;
|
||||
case FGA_LOCALIACK : LOG(("FGA_LOCALIACK - not implemented\n")); m_fga002[FGA_LOCALIACK] = data; break;
|
||||
case FGA_LOCALIACK : do_fga002reg_localiack_w(data);
|
||||
case FGA_FMBCTL : LOG(("FGA_FMBCTL - not implemented\n")); m_fga002[FGA_FMBCTL] = data; break;
|
||||
case FGA_FMBAREA : LOG(("FGA_FMBAREA - not implemented\n")); m_fga002[FGA_FMBAREA] = data; break;
|
||||
case FGA_AUXSRCSTART : LOG(("FGA_AUXSRCSTART - not implemented\n")); m_fga002[FGA_AUXSRCSTART] = data; break;
|
||||
@ -390,7 +696,15 @@ WRITE8_MEMBER (fga002_device::write){
|
||||
case FGA_CTL14 : LOG(("FGA_CTL14 - not implemented\n")); m_fga002[FGA_CTL14] = data; break;
|
||||
case FGA_CTL15 : LOG(("FGA_CTL15 - not implemented\n")); m_fga002[FGA_CTL15] = data; break;
|
||||
case FGA_CTL16 : LOG(("FGA_CTL16 - not implemented\n")); m_fga002[FGA_CTL16] = data; break;
|
||||
case FGA_ISTIM0 : do_fga002reg_istim0_w(data); break;
|
||||
case FGA_ISTIM0 : do_fga002reg_istim0_w(data); break;
|
||||
case FGA_ISLOCAL0 : do_fga002reg_islocal0_w(data); break;
|
||||
case FGA_ISLOCAL1 : do_fga002reg_islocal1_w(data); break;
|
||||
case FGA_ISLOCAL2 : do_fga002reg_islocal2_w(data); break;
|
||||
case FGA_ISLOCAL3 : do_fga002reg_islocal3_w(data); break;
|
||||
case FGA_ISLOCAL4 : do_fga002reg_islocal4_w(data); break;
|
||||
case FGA_ISLOCAL5 : do_fga002reg_islocal5_w(data); break;
|
||||
case FGA_ISLOCAL6 : do_fga002reg_islocal6_w(data); break;
|
||||
case FGA_ISLOCAL7 : do_fga002reg_islocal7_w(data); break;
|
||||
case FGA_ISDMANORM : LOG(("FGA_ISDMANORM - not implemented\n")); m_fga002[FGA_ISDMANORM] = data; break;
|
||||
case FGA_ISDMAERR : LOG(("FGA_ISDMAERR - not implemented\n")); m_fga002[FGA_ISDMAERR] = data; break;
|
||||
case FGA_ISFMB0REF : LOG(("FGA_ISFMB0REF - not implemented\n")); m_fga002[FGA_ISFMB0REF] = data; break;
|
||||
@ -443,7 +757,7 @@ READ8_MEMBER (fga002_device::read){
|
||||
case FGA_ICRFMB1REF : ret = m_fga002[FGA_ICRFMB1REF]; LOG(("FGA_ICRFMB1REF returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRFMB0MES : ret = m_fga002[FGA_ICRFMB0MES]; LOG(("FGA_ICRFMB0MES returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRFMB1MES : ret = m_fga002[FGA_ICRFMB1MES]; LOG(("FGA_ICRFMB1MES returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_CTL3 : ret = m_fga002[FGA_CTL3]; LOG(("FGA_CTL3 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_CTL3 : ret = do_fga002reg_ctl3_r(); break;
|
||||
case FGA_CTL4 : ret = m_fga002[FGA_CTL4]; LOG(("FGA_CTL4 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRPARITY : ret = m_fga002[FGA_ICRPARITY]; LOG(("FGA_ICRPARITY returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_AUXPINCTL : ret = m_fga002[FGA_AUXPINCTL]; LOG(("FGA_AUXPINCTL returns %02x - not implemented\n", ret)); break;
|
||||
@ -457,14 +771,14 @@ READ8_MEMBER (fga002_device::read){
|
||||
case FGA_ICRABORT : ret = m_fga002[FGA_ICRABORT]; LOG(("FGA_ICRABORT returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRACFAIL : ret = m_fga002[FGA_ICRACFAIL]; LOG(("FGA_ICRACFAIL returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRSYSFAIL : ret = m_fga002[FGA_ICRSYSFAIL]; LOG(("FGA_ICRSYSFAIL returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL0 : ret = m_fga002[FGA_ICRLOCAL0]; LOG(("FGA_ICRLOCAL0 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL1 : ret = m_fga002[FGA_ICRLOCAL1]; LOG(("FGA_ICRLOCAL1 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL2 : ret = m_fga002[FGA_ICRLOCAL2]; LOG(("FGA_ICRLOCAL2 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL3 : ret = m_fga002[FGA_ICRLOCAL3]; LOG(("FGA_ICRLOCAL3 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL4 : ret = m_fga002[FGA_ICRLOCAL4]; LOG(("FGA_ICRLOCAL4 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL5 : ret = m_fga002[FGA_ICRLOCAL5]; LOG(("FGA_ICRLOCAL5 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL6 : ret = m_fga002[FGA_ICRLOCAL6]; LOG(("FGA_ICRLOCAL6 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL7 : ret = m_fga002[FGA_ICRLOCAL7]; LOG(("FGA_ICRLOCAL7 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ICRLOCAL0 : ret = do_fga002reg_icrlocal0_r(); break;
|
||||
case FGA_ICRLOCAL1 : ret = do_fga002reg_icrlocal1_r(); break;
|
||||
case FGA_ICRLOCAL2 : ret = do_fga002reg_icrlocal2_r(); break;
|
||||
case FGA_ICRLOCAL3 : ret = do_fga002reg_icrlocal3_r(); break;
|
||||
case FGA_ICRLOCAL4 : ret = do_fga002reg_icrlocal4_r(); break;
|
||||
case FGA_ICRLOCAL5 : ret = do_fga002reg_icrlocal5_r(); break;
|
||||
case FGA_ICRLOCAL6 : ret = do_fga002reg_icrlocal6_r(); break;
|
||||
case FGA_ICRLOCAL7 : ret = do_fga002reg_icrlocal7_r(); break;
|
||||
case FGA_ENAMCODE : ret = m_fga002[FGA_ENAMCODE]; LOG(("FGA_ENAMCODE returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_CTL10 : ret = m_fga002[FGA_CTL10]; LOG(("FGA_CTL10 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_CTL11 : ret = m_fga002[FGA_CTL11]; LOG(("FGA_CTL11 returns %02x - not implemented\n", ret)); break;
|
||||
@ -482,7 +796,7 @@ READ8_MEMBER (fga002_device::read){
|
||||
case FGA_DMA_GENERAL : ret = m_fga002[FGA_DMA_GENERAL]; LOG(("FGA_DMA_GENERAL returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_CTL12 : ret = m_fga002[FGA_CTL12]; LOG(("FGA_CTL12 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_LIOTIMING : ret = m_fga002[FGA_LIOTIMING]; LOG(("FGA_LIOTIMING returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_LOCALIACK : ret = m_fga002[FGA_LOCALIACK]; LOG(("FGA_LOCALIACK returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_LOCALIACK : ret = do_fga002reg_localiack_r(); break;
|
||||
case FGA_FMBCTL : ret = m_fga002[FGA_FMBCTL]; LOG(("FGA_FMBCTL returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_FMBAREA : ret = m_fga002[FGA_FMBAREA]; LOG(("FGA_FMBAREA returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_AUXSRCSTART : ret = m_fga002[FGA_AUXSRCSTART]; LOG(("FGA_AUXSRCSTART returns %02x - not implemented\n", ret)); break;
|
||||
@ -493,7 +807,15 @@ READ8_MEMBER (fga002_device::read){
|
||||
case FGA_CTL14 : ret = m_fga002[FGA_CTL14]; LOG(("FGA_CTL14 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_CTL15 : ret = m_fga002[FGA_CTL15]; LOG(("FGA_CTL15 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_CTL16 : ret = m_fga002[FGA_CTL16]; LOG(("FGA_CTL16 returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ISTIM0 : ret = do_fga002reg_istim0_r(); break;
|
||||
case FGA_ISTIM0 : ret = do_fga002reg_istim0_r(); break;
|
||||
case FGA_ISLOCAL0 : ret = do_fga002reg_islocal0_r(); break;
|
||||
case FGA_ISLOCAL1 : ret = do_fga002reg_islocal1_r(); break;
|
||||
case FGA_ISLOCAL2 : ret = do_fga002reg_islocal2_r(); break;
|
||||
case FGA_ISLOCAL3 : ret = do_fga002reg_islocal3_r(); break;
|
||||
case FGA_ISLOCAL4 : ret = do_fga002reg_islocal4_r(); break;
|
||||
case FGA_ISLOCAL5 : ret = do_fga002reg_islocal5_r(); break;
|
||||
case FGA_ISLOCAL6 : ret = do_fga002reg_islocal6_r(); break;
|
||||
case FGA_ISLOCAL7 : ret = do_fga002reg_islocal7_r(); break;
|
||||
case FGA_ISDMANORM : ret = m_fga002[FGA_ISDMANORM]; LOG(("FGA_ISDMANORM returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ISDMAERR : ret = m_fga002[FGA_ISDMAERR]; LOG(("FGA_ISDMAERR returns %02x - not implemented\n", ret)); break;
|
||||
case FGA_ISFMB0REF : ret = m_fga002[FGA_ISFMB0REF]; LOG(("FGA_ISFMB0REF returns %02x - not implemented\n", ret)); break;
|
||||
|
@ -4,8 +4,36 @@
|
||||
#define __FGA002_H__
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/m68000/m68000.h" // The FGA002 is designed for the 68K interrupt PL0-PL2 signalling, however used on Sparc and x86 boards too
|
||||
|
||||
#define MCFG_FGA002_ADD(_tag, _clock) MCFG_DEVICE_ADD(_tag, FGA002, _clock)
|
||||
#ifndef VERBOSE
|
||||
#define LOG(x)
|
||||
#endif
|
||||
|
||||
#define MCFG_FGA002_ADD(_tag, _clock) MCFG_DEVICE_ADD(_tag, FGA002, _clock)
|
||||
|
||||
// LOCAL IRQ callbacks
|
||||
#define MCFG_FGA002_OUT_INT_CB(_devcb) \
|
||||
devcb = &fga002_device::set_out_int_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_FGA002_OUT_LIACK4_CB(_devcb) \
|
||||
devcb = &fga002_device::set_liack4_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_FGA002_OUT_LIACK5_CB(_devcb) \
|
||||
devcb = &fga002_device::set_liack5_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_FGA002_OUT_LIACK6_CB(_devcb) \
|
||||
devcb = &fga002_device::set_liack6_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_FGA002_OUT_LIACK7_CB(_devcb) \
|
||||
devcb = &fga002_device::set_liack7_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
// type for array of mapping of FGA registers that assembles an IRQ source
|
||||
typedef struct {
|
||||
int vector;
|
||||
int status;
|
||||
int control;
|
||||
} fga_irq_t;
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
@ -14,6 +42,7 @@
|
||||
// ======================> fga002_device
|
||||
|
||||
class fga002_device : public device_t
|
||||
// ,public device_z80daisy_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
@ -22,15 +51,57 @@ class fga002_device : public device_t
|
||||
|
||||
DECLARE_WRITE8_MEMBER (write);
|
||||
DECLARE_READ8_MEMBER (read);
|
||||
protected:
|
||||
|
||||
void lirq_w(int status, int vector, int control, int state);
|
||||
DECLARE_WRITE_LINE_MEMBER( lirq0_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( lirq1_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( lirq2_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( lirq3_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( lirq4_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( lirq5_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( lirq6_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( lirq7_w );
|
||||
|
||||
IRQ_CALLBACK_MEMBER(iack);
|
||||
int acknowledge();
|
||||
int get_irq_level();
|
||||
|
||||
template<class _Object> static devcb_base &set_out_int_callback(device_t &device, _Object object) { return downcast<fga002_device &>(device).m_out_int_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_liack4_callback(device_t &device, _Object object) { return downcast<fga002_device &>(device).m_liack4_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_liack5_callback(device_t &device, _Object object) { return downcast<fga002_device &>(device).m_liack5_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_liack6_callback(device_t &device, _Object object) { return downcast<fga002_device &>(device).m_liack6_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_liack7_callback(device_t &device, _Object object) { return downcast<fga002_device &>(device).m_liack7_cb.set_callback(object); }
|
||||
|
||||
// interrupt sources in prio order if on same interrupt level. TODO: Add all sources
|
||||
const static fga_irq_t m_irq_sources[];
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
#if 0
|
||||
// device_z80daisy_interface overrides
|
||||
virtual int z80daisy_irq_state() override;
|
||||
virtual int z80daisy_irq_ack() override;
|
||||
virtual void z80daisy_irq_reti() override;
|
||||
#endif
|
||||
virtual void device_timer (emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
private:
|
||||
|
||||
devcb_write_line m_out_int_cb;
|
||||
devcb_read8 m_liack4_cb;
|
||||
devcb_read8 m_liack5_cb;
|
||||
devcb_read8 m_liack6_cb;
|
||||
devcb_read8 m_liack7_cb;
|
||||
int m_int_state[0x08]; // interrupt state
|
||||
|
||||
private:
|
||||
|
||||
UINT8 m_tim0count;
|
||||
UINT8 m_fga002[0x500];
|
||||
|
||||
UINT8 do_fga002reg_ctl3_r();
|
||||
void do_fga002reg_ctl3_w(UINT8 data);
|
||||
|
||||
/* Timer functions */
|
||||
UINT8 do_fga002reg_tim0preload_r();
|
||||
void do_fga002reg_tim0preload_w(UINT8 data);
|
||||
@ -74,6 +145,90 @@ class fga002_device : public device_t
|
||||
REG_ISTIM0_TIM_INT = 0x80,
|
||||
};
|
||||
|
||||
/* Interrupt support */
|
||||
UINT8 m_irq_level;
|
||||
UINT8 do_fga002reg_localiack_r();
|
||||
void do_fga002reg_localiack_w(UINT8 data);
|
||||
|
||||
UINT8 do_fga002reg_islocal0_r();
|
||||
UINT8 do_fga002reg_islocal1_r();
|
||||
UINT8 do_fga002reg_islocal2_r();
|
||||
UINT8 do_fga002reg_islocal3_r();
|
||||
UINT8 do_fga002reg_islocal4_r();
|
||||
UINT8 do_fga002reg_islocal5_r();
|
||||
UINT8 do_fga002reg_islocal6_r();
|
||||
UINT8 do_fga002reg_islocal7_r();
|
||||
|
||||
void islocal_w(int status, int vector, int control, int data);
|
||||
void do_fga002reg_islocal0_w(UINT8 data);
|
||||
void do_fga002reg_islocal1_w(UINT8 data);
|
||||
void do_fga002reg_islocal2_w(UINT8 data);
|
||||
void do_fga002reg_islocal3_w(UINT8 data);
|
||||
void do_fga002reg_islocal4_w(UINT8 data);
|
||||
void do_fga002reg_islocal5_w(UINT8 data);
|
||||
void do_fga002reg_islocal6_w(UINT8 data);
|
||||
void do_fga002reg_islocal7_w(UINT8 data);
|
||||
|
||||
UINT8 do_fga002reg_icrlocal0_r();
|
||||
UINT8 do_fga002reg_icrlocal1_r();
|
||||
UINT8 do_fga002reg_icrlocal2_r();
|
||||
UINT8 do_fga002reg_icrlocal3_r();
|
||||
UINT8 do_fga002reg_icrlocal4_r();
|
||||
UINT8 do_fga002reg_icrlocal5_r();
|
||||
UINT8 do_fga002reg_icrlocal6_r();
|
||||
UINT8 do_fga002reg_icrlocal7_r();
|
||||
void do_fga002reg_icrlocal0_w(UINT8 data);
|
||||
void do_fga002reg_icrlocal1_w(UINT8 data);
|
||||
void do_fga002reg_icrlocal2_w(UINT8 data);
|
||||
void do_fga002reg_icrlocal3_w(UINT8 data);
|
||||
void do_fga002reg_icrlocal4_w(UINT8 data);
|
||||
void do_fga002reg_icrlocal5_w(UINT8 data);
|
||||
void do_fga002reg_icrlocal6_w(UINT8 data);
|
||||
void do_fga002reg_icrlocal7_w(UINT8 data);
|
||||
|
||||
void trigger_interrupt(UINT8 data);
|
||||
void check_interrupts();
|
||||
|
||||
enum {
|
||||
REG_ISLOCAL_IRQ = 0x80
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_CTL3_VECTORBITS7_6 = 0x0c
|
||||
};
|
||||
|
||||
enum{
|
||||
REG_LIACK_LOCAL4_MSK = 0x03,
|
||||
REG_LIACK_LOCAL5_MSK = 0x0c, // >> 2 to use patterns below
|
||||
REG_LIACK_LOCAL6_MSK = 0x30, // >> 4 to use patterns below
|
||||
REG_LIACK_LOCAL7_MSK = 0xc0, // >> 6 to use patterns below
|
||||
REG_LIACK_INT_IACK = 0x00, // Assumes bits to be right adjusted
|
||||
REG_LIACK_EXT_IACK1 = 0x01,
|
||||
REG_LIACK_EXT_IACK2 = 0x02,
|
||||
REG_LIACK_EXT_IACK3 = 0x03,
|
||||
};
|
||||
|
||||
enum{
|
||||
INT_LOCAL0 = 0x30,
|
||||
INT_LOCAL1 = 0x31,
|
||||
INT_LOCAL2 = 0x32,
|
||||
INT_LOCAL3 = 0x33,
|
||||
INT_LOCAL4 = 0x34,
|
||||
INT_LOCAL5 = 0x35,
|
||||
INT_LOCAL6 = 0x36,
|
||||
INT_LOCAL7 = 0x37,
|
||||
INT_EMPTY = 0x3F,
|
||||
INT_ACK_AUTOVECTOR = -1,
|
||||
};
|
||||
|
||||
enum{
|
||||
REG_ICR_LVL_MSK = 0x07,
|
||||
REG_ICR_ENABLE = 0x08,
|
||||
REG_ICR_AUTOCLR = 0x10,
|
||||
REG_ICR_ACTIVITY = 0x20,
|
||||
REG_ICR_EDGE = 0x40,
|
||||
};
|
||||
|
||||
/* Register offsets */
|
||||
enum {
|
||||
FGA_ICRMBOX0 = 0x0000,
|
||||
@ -145,33 +300,40 @@ class fga002_device : public device_t
|
||||
FGA_FMBAREA = 0x033c,
|
||||
FGA_AUXSRCSTART = 0x0340,
|
||||
FGA_AUXDSTSTART = 0x0344,
|
||||
FGA_AUXSRCTERM = 0x0348,
|
||||
FGA_AUXDSTTERM = 0x034c,
|
||||
FGA_CTL13 = 0x0350,
|
||||
FGA_CTL14 = 0x0354,
|
||||
FGA_CTL15 = 0x0358,
|
||||
FGA_CTL16 = 0x035c,
|
||||
FGA_SPECIALENA = 0x0424,
|
||||
FGA_ISTIM0 = 0x04a0,
|
||||
FGA_ISDMANORM = 0x04b0,
|
||||
FGA_ISDMAERR = 0x04b4,
|
||||
FGA_ISFMB0REF = 0x04b8,
|
||||
FGA_ISFMB1REF = 0x04bc,
|
||||
FGA_ISPARITY = 0x04c0,
|
||||
FGA_DMARUNCTL = 0x04c4,
|
||||
FGA_ISABORT = 0x04c8,
|
||||
FGA_ISACFAIL = 0x04cc,
|
||||
FGA_ISFMB0MES = 0x04e0,
|
||||
FGA_ISFMB1MES = 0x04e4,
|
||||
FGA_ISSYSFAIL = 0x04d0,
|
||||
FGA_ABORTPIN = 0x04d4,
|
||||
FGA_RSVMECALL = 0x04f0,
|
||||
FGA_RSKEYRES = 0x04f4,
|
||||
FGA_RSCPUCALL = 0x04f8,
|
||||
FGA_RSLOCSW = 0x04fc,
|
||||
FGA_TIM0COUNT = 0x0c00,
|
||||
FGA_AUXSRCTERM = 0x0348,
|
||||
FGA_AUXDSTTERM = 0x034c,
|
||||
FGA_CTL13 = 0x0350,
|
||||
FGA_CTL14 = 0x0354,
|
||||
FGA_CTL15 = 0x0358,
|
||||
FGA_CTL16 = 0x035c,
|
||||
FGA_SPECIALENA = 0x0424,
|
||||
FGA_ISLOCAL0 = 0x0480,
|
||||
FGA_ISLOCAL1 = 0x0484,
|
||||
FGA_ISLOCAL2 = 0x0488,
|
||||
FGA_ISLOCAL3 = 0x048C,
|
||||
FGA_ISLOCAL4 = 0x0490,
|
||||
FGA_ISLOCAL5 = 0x0494,
|
||||
FGA_ISLOCAL6 = 0x0498,
|
||||
FGA_ISLOCAL7 = 0x049C,
|
||||
FGA_ISTIM0 = 0x04a0,
|
||||
FGA_ISDMANORM = 0x04b0,
|
||||
FGA_ISDMAERR = 0x04b4,
|
||||
FGA_ISFMB0REF = 0x04b8,
|
||||
FGA_ISFMB1REF = 0x04bc,
|
||||
FGA_ISPARITY = 0x04c0,
|
||||
FGA_DMARUNCTL = 0x04c4,
|
||||
FGA_ISABORT = 0x04c8,
|
||||
FGA_ISACFAIL = 0x04cc,
|
||||
FGA_ISFMB0MES = 0x04e0,
|
||||
FGA_ISFMB1MES = 0x04e4,
|
||||
FGA_ISSYSFAIL = 0x04d0,
|
||||
FGA_ABORTPIN = 0x04d4,
|
||||
FGA_RSVMECALL = 0x04f0,
|
||||
FGA_RSKEYRES = 0x04f4,
|
||||
FGA_RSCPUCALL = 0x04f8,
|
||||
FGA_RSLOCSW = 0x04fc,
|
||||
FGA_TIM0COUNT = 0x0c00,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -87,8 +87,14 @@ DONE (x) (p=partly) NMOS CMOS
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define LOGPRINT(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define LOG(x)
|
||||
#define LOGR(x)
|
||||
#define LOGTX(x)
|
||||
#define LOGRX(x)
|
||||
#define LOGSETUP(x)
|
||||
#define LOGINT(x) LOGPRINT(x)
|
||||
|
||||
#if VERBOSE > 1
|
||||
#define logerror printf
|
||||
#endif
|
||||
@ -264,7 +270,8 @@ void duscc_device::device_reset()
|
||||
|
||||
/*
|
||||
* Interrupt Control
|
||||
A single interrupt output (IRON) is provided which is activated upon the occurrence of any of the following conditions:
|
||||
|
||||
A single interrupt output (IRQN) is provided which is activated upon the occurrence of any of the following conditions:
|
||||
- Channel A external or CIT special condition
|
||||
- Channel B external or CIT special condition
|
||||
- Channel A RxlTx error or special condition
|
||||
@ -273,6 +280,7 @@ void duscc_device::device_reset()
|
||||
- Channel B TxRDY
|
||||
- Channel A RxRDY
|
||||
- Channel B RxRDY
|
||||
|
||||
Each of the above conditions occupies a bit in the General Status Register (GSR). If ICR[2] is set, the eight conditions are encoded
|
||||
into three bits which are inserted into bits [2:0] or [4:2] of the interrupt vector register. This forms the content of the IVRM during
|
||||
an interrupt acknowledge cycle. Unmodified and modified vectors can read directly through specified registers. Two of the conditions
|
||||
@ -288,26 +296,26 @@ void duscc_device::device_reset()
|
||||
IER, CTCR[?] could be programmed to enable or disable an interrupt upon the CfT zero count condition. The interrupt priorities
|
||||
within a channel are fixed. Priority between channels is controlled by ICR[7:6]. Reier to Table 8 and ICR[7:6].
|
||||
|
||||
The ICR contains the master interrupt enables for each channel (ICR[I] andICR[OJ) which must be set if the corresponding channel
|
||||
The ICR contains the master interrupt enables for each channel (ICR[1] and ICR[O]) which must be set if the corresponding channel
|
||||
is to cause an interrupt. The CPU vector mode is specified by ICR[5:4] which selects either vectored or non-vectored operation. If
|
||||
vectored mode is selected, the content of the IVR or IVRM is placed on the data bus when lACK is activated. If ICR[2] is set, the content
|
||||
of IVRM is output which contains the content of IVR and the encoded status of the interrupting condition.
|
||||
Upon receiving an interrupt acknowledge, the DUSCC locks its current interrupt status until the end of the acknowledge cycle.
|
||||
If it has an active interrupt pending, it responds with the appropriate vector and then asserts DTACKN. If it does not have an interrupt, it
|
||||
propagates the acknowledge through its X2/1DCN output if this function is programmed in PCRA[7]; otherwise, the IACKN is
|
||||
propagates the acknowledge through its X2/IDCN output if this function is programmed in PCRA[7]; otherwise, the IACKN is
|
||||
ignored. Locking the interrupt status at the leading edge of IACKN prevents a device at a High position in the interrupt daisy chain from
|
||||
responding to an lACK issued for a lower priority device while the acknowledge is being propagated to that device.*/
|
||||
|
||||
//-------------------------------------------------
|
||||
// z80daisy_irq_state - get interrupt status
|
||||
//-------------------------------------------------
|
||||
|
||||
int duscc_device::z80daisy_irq_state()
|
||||
{
|
||||
int state = 0;
|
||||
|
||||
LOG(("%s %s A:[%02x][%02x][%02x][%02x] B:[%02x][%02x][%02x][%02x] ",tag(), FUNCNAME,
|
||||
m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
|
||||
m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]));
|
||||
LOGINT(("%s %s A:[%02x][%02x][%02x][%02x] B:[%02x][%02x][%02x][%02x] ",tag(), FUNCNAME,
|
||||
m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
|
||||
m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]));
|
||||
|
||||
// loop over all interrupt sources
|
||||
for (auto & elem : m_int_state)
|
||||
@ -321,7 +329,7 @@ int duscc_device::z80daisy_irq_state()
|
||||
state |= elem;
|
||||
}
|
||||
|
||||
LOG(("Interrupt State %02x\n", state));
|
||||
LOGINT((" - Interrupt State %02x\n", state));
|
||||
|
||||
return state;
|
||||
}
|
||||
@ -333,7 +341,7 @@ int duscc_device::z80daisy_irq_state()
|
||||
|
||||
int duscc_device::z80daisy_irq_ack()
|
||||
{
|
||||
LOG(("%s %s()\n",tag(), FUNCNAME));
|
||||
LOGINT(("%s %s()\n",tag(), FUNCNAME));
|
||||
|
||||
// loop over all interrupt sources
|
||||
for (auto & elem : m_int_state)
|
||||
@ -344,12 +352,21 @@ int duscc_device::z80daisy_irq_ack()
|
||||
// clear interrupt, switch to the IEO state, and update the IRQs
|
||||
elem = Z80_DAISY_IEO;
|
||||
check_interrupts();
|
||||
|
||||
return m_ivrm;
|
||||
LOGINT((" - Found an INT request, "));
|
||||
if ((m_icr & REG_ICR_VEC_MODE_MASK) == REG_ICR_VEC_MODE_NONE)
|
||||
{
|
||||
LOGINT(("but ICR set to use autovector, returning -1\n"));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGINT(("returning IVRM: %02x\n", m_ivrm ));
|
||||
return m_ivrm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_ivrm;
|
||||
LOGINT((" - Found NO INT request, returning -1\n"));
|
||||
return -1; // Signal no-vector, same as autovector but caller should know the difference
|
||||
}
|
||||
|
||||
|
||||
@ -359,7 +376,7 @@ int duscc_device::z80daisy_irq_ack()
|
||||
|
||||
void duscc_device::z80daisy_irq_reti()
|
||||
{
|
||||
LOG(("%s %s \n",tag(), FUNCNAME));
|
||||
LOGINT(("%s %s \n",tag(), FUNCNAME));
|
||||
|
||||
// loop over all interrupt sources
|
||||
for (auto & elem : m_int_state)
|
||||
@ -376,15 +393,25 @@ void duscc_device::z80daisy_irq_reti()
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER( duscc_device::iack )
|
||||
{
|
||||
LOGINT(("%s %s - returning vector:%02x\n",tag(), FUNCNAME, m_ivrm));
|
||||
int vec = z80daisy_irq_ack();
|
||||
z80daisy_irq_reti();
|
||||
return vec;
|
||||
}
|
||||
|
||||
void duscc_device::check_interrupts()
|
||||
{
|
||||
LOG(("%s %s()\n",tag(), FUNCNAME));
|
||||
LOGINT(("%s %s()\n",tag(), FUNCNAME));
|
||||
int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
|
||||
|
||||
// "If no interrupt is pending, an H'FF' is output when reading the IVRM."
|
||||
if (state == 0)
|
||||
if (state == CLEAR_LINE)
|
||||
m_ivrm = 0xff;
|
||||
|
||||
// Provide the IRQN interrupt request signal level to the connected device (ie a CPU or an interrupt controller)
|
||||
// The CPU can issue an IACK cycle but is not required to do so, it may read the status and vectors by software
|
||||
m_out_int_cb(state);
|
||||
}
|
||||
|
||||
@ -395,7 +422,7 @@ void duscc_device::check_interrupts()
|
||||
|
||||
void duscc_device::reset_interrupts()
|
||||
{
|
||||
LOG(("%s %s - not implemented \n",tag(), FUNCNAME));
|
||||
LOGINT(("%s %s\n",tag(), FUNCNAME));
|
||||
|
||||
// reset internal interrupt sources
|
||||
for (auto & elem : m_int_state)
|
||||
@ -407,7 +434,7 @@ void duscc_device::reset_interrupts()
|
||||
check_interrupts();
|
||||
}
|
||||
|
||||
UINT8 duscc_device::modify_vector(UINT8 vec, int i, UINT8 src)
|
||||
UINT8 duscc_device::modify_vector(UINT8 vec, int index, UINT8 src)
|
||||
{
|
||||
/*
|
||||
Interrupt Vector Modification
|
||||
@ -424,22 +451,26 @@ UINT8 duscc_device::modify_vector(UINT8 vec, int i, UINT8 src)
|
||||
1 1 1 Ch B external or C/T status
|
||||
--------------------------------------------------
|
||||
*/
|
||||
LOG(("%s %s - not implemented\n",tag(), FUNCNAME));
|
||||
//TODO: Prevent modification if no vector has been programmed, even if it is the default vector.
|
||||
LOGINT(("%s %c %s, vec:%02x src=%02x\n",tag(), 'A' + index, FUNCNAME, vec, src));
|
||||
|
||||
// TODO: Prevent modification if no vector has been programmed, even if it is the default vector.
|
||||
if ((m_icr & REG_ICR_VEC_MOD) != 0) // Affect vector?
|
||||
{
|
||||
// Modify vector according to "Vector Include Status" bit (REG_ICR_V2V4_MOD)
|
||||
if ((m_icr & REG_ICR_V2V4_MOD) != 0)
|
||||
{ // Affect V2-V4
|
||||
{ // Affect V2-V4
|
||||
LOGINT((" - Affect V2-V4 with status"));
|
||||
vec &= 0x07 << 3;
|
||||
vec |= src << 3;
|
||||
}
|
||||
else // Affect V0-V2
|
||||
{
|
||||
LOGINT((" - Affect V0-V2 with status"));
|
||||
vec &= 0x07 << 0;
|
||||
vec |= src << 0;
|
||||
}
|
||||
}
|
||||
LOGINT((" - Returning vector %02x\n", vec));
|
||||
return vec;
|
||||
}
|
||||
|
||||
@ -448,10 +479,10 @@ UINT8 duscc_device::modify_vector(UINT8 vec, int i, UINT8 src)
|
||||
This group of registers define mechanisms for communications between the DUSCC and the processor and contain the device status
|
||||
information. Four registers, available for each channel, and four common device registers comprise this group which consists of
|
||||
the following:
|
||||
1. Interrupt Enable Register (IERA/B).
|
||||
1. Interrupt Enable Register (IERA/B). - checked by trigger_interrupt
|
||||
2. Receiver Status Register (RSRA/B).
|
||||
3. Transmitter and Receiver Status Register (TRSRA/B).
|
||||
4. Input and Coutnermmer Status Register (ICTSRA/B).
|
||||
4. Input and Counter/timer Status Register (ICTSRA/B).
|
||||
5. interrupt Vector Register (IVR) and Modified Interrupt Vector Register (IVRM).
|
||||
6. Interrupt control register (lCR).
|
||||
7. General status register (GSR)
|
||||
@ -467,12 +498,13 @@ void duscc_device::trigger_interrupt(int index, int state)
|
||||
UINT8 source = 0;
|
||||
int priority_level = 0;
|
||||
|
||||
LOG(("%s %s:%c %02x \n",FUNCNAME, tag(), 'A' + index, state));
|
||||
LOGINT(("%s %s:%c %02x \n",FUNCNAME, tag(), 'A' + index, state));
|
||||
|
||||
/* The Interrup Controll Register (ICR) bits, must be set for the correspondning channel */
|
||||
// ICR Check is probably by the caller but we check again to be sure
|
||||
if ((m_icr & (index == CHANNEL_A ? REG_ICR_CHA : REG_ICR_CHB)) == 0)
|
||||
{
|
||||
LOG(("The Interrupt Control Register [%02x] bit for this channel is not set, blocking attempt to interrupt\n", m_icr));
|
||||
LOGINT(("The Interrupt Control Register [%02x] bit for this channel is not set, blocking attempt to interrupt\n", m_icr));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -483,7 +515,7 @@ void duscc_device::trigger_interrupt(int index, int state)
|
||||
case REG_ICR_PRIO_BHI: priority_level = state + (index == CHANNEL_A ? 4 : 0); break;
|
||||
case REG_ICR_PRIO_AINT: priority_level = state * 2 + (index == CHANNEL_A ? 0 : 1); break;
|
||||
case REG_ICR_PRIO_BINT: priority_level = state * 2 + (index == CHANNEL_A ? 1 : 0); break;
|
||||
default: logerror("Programming error, please report/fix\n"); // Will not happen
|
||||
default: logerror("DUSCC Programming error, please report/fix\n"); // Will not happen
|
||||
}
|
||||
|
||||
// Vector modification requested?
|
||||
@ -492,6 +524,10 @@ void duscc_device::trigger_interrupt(int index, int state)
|
||||
|
||||
// trigger interrupt
|
||||
m_int_state[priority_level] |= Z80_DAISY_INT;
|
||||
LOGINT((" - Interrupt Priority Level %d, caused by Source %02x with vector %02x\n",priority_level, source, m_ivrm ));
|
||||
|
||||
// check for interupts
|
||||
check_interrupts();
|
||||
}
|
||||
|
||||
READ8_MEMBER( duscc_device::read )
|
||||
@ -639,8 +675,6 @@ void duscc_channel::device_start()
|
||||
save_item(NAME(m_dtr));
|
||||
save_item(NAME(m_rts));
|
||||
save_item(NAME(m_sync));
|
||||
|
||||
// device_serial_interface::register_save_state(machine().save(), this);
|
||||
}
|
||||
|
||||
|
||||
@ -718,7 +752,8 @@ void duscc_channel::device_timer(emu_timer &timer, device_timer_id id, int param
|
||||
if ( ( (m_ctcr & REG_CTCR_ZERO_DET_INT) == 1 ) &&
|
||||
( (m_uart->m_icr & (m_index == duscc_device::CHANNEL_A ? duscc_device::REG_ICR_CHA : duscc_device::REG_ICR_CHB) ) != 0) )
|
||||
{
|
||||
//trigger_interrupt();
|
||||
LOG(("Zero Detect Interrupt pending\n"));
|
||||
m_uart->trigger_interrupt(m_index, INT_EXTCTSTAT);
|
||||
}
|
||||
|
||||
// Preload or rollover?
|
||||
@ -943,7 +978,7 @@ void duscc_channel::tra_callback()
|
||||
else
|
||||
{
|
||||
LOG((LLFORMAT " %s() \"%s \"Channel %c Failed to transmit \n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index));
|
||||
logerror("%s \"%s \"Channel %c Failed to transmit\n", FUNCNAME, m_owner->tag(), 'A' + m_index);
|
||||
logerror("%s Channel %c Failed to transmit\n", FUNCNAME, 'A' + m_index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -998,7 +1033,7 @@ void duscc_channel::rcv_complete()
|
||||
|
||||
receive_register_extract();
|
||||
data = get_received_char();
|
||||
LOG((LLFORMAT " %s() \"%s \"Channel %c Received Data %c\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, data));
|
||||
LOGINT((LLFORMAT " %s() \"%s \"Channel %c Received Data %c\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, data));
|
||||
receive_data(data);
|
||||
}
|
||||
|
||||
@ -1203,8 +1238,8 @@ UINT8 duscc_channel::do_dusccreg_rxfifo_r()
|
||||
{
|
||||
UINT8 data = 0;
|
||||
|
||||
LOG(("%s\n", FUNCNAME));
|
||||
LOG((" - RX rp:%d wp:%d sz:%d\n", m_rx_fifo_rp, m_rx_fifo_wp, m_rx_fifo_sz));
|
||||
LOGINT(("%s\n", FUNCNAME));
|
||||
LOGRX((" - RX rp:%d wp:%d sz:%d\n", m_rx_fifo_rp, m_rx_fifo_wp, m_rx_fifo_sz));
|
||||
|
||||
/* So is there a character in the FIFO? */
|
||||
if (m_rx_fifo_rp != m_rx_fifo_wp)
|
||||
@ -1213,12 +1248,12 @@ UINT8 duscc_channel::do_dusccreg_rxfifo_r()
|
||||
m_rx_error_fifo[m_rx_fifo_rp] = 0; // Loose the old errors
|
||||
m_rx_fifo_rp_step();
|
||||
m_rsr |= (m_rx_error_fifo[m_rx_fifo_rp] & (REG_RSR_CHAR_COMPARE | REG_RSR_FRAMING_ERROR | REG_RSR_PARITY_ERROR)); // Get new errors
|
||||
LOG((" - RX reading out data:%02x '%c'\n", data, isalnum(data) ? data : ' '));
|
||||
LOGINT((" - RX reading out data:%02x '%c'\n", data, isalnum(data) ? data : ' '));
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("- RX FIFO empty despite RxREADY\n");
|
||||
LOG(("- RX FIFO empty despite RxREADY\n"));
|
||||
LOGINT(("- RX FIFO empty despite RxREADY\n"));
|
||||
}
|
||||
|
||||
return (UINT8) data;
|
||||
@ -1265,14 +1300,16 @@ UINT8 duscc_channel::do_dusccreg_ictsr_r()
|
||||
*/
|
||||
UINT8 duscc_channel::do_dusccreg_gsr_r()
|
||||
{
|
||||
LOGR(("%s <- %02x\n", FUNCNAME, m_uart->m_gsr));
|
||||
return (UINT8) m_uart->m_gsr;
|
||||
static UINT8 old_gsr = 0;
|
||||
if (m_uart->m_gsr != old_gsr) LOG(("%s <- %02x\n", FUNCNAME, m_uart->m_gsr));
|
||||
old_gsr = m_uart->m_gsr;
|
||||
return m_uart->m_gsr;
|
||||
}
|
||||
|
||||
UINT8 duscc_channel::do_dusccreg_ier_r()
|
||||
{
|
||||
LOGR(("%s <- %02x\n", FUNCNAME, m_uart->m_ier));
|
||||
return (UINT8) 0;
|
||||
LOGINT(("%s <- %02x\n", FUNCNAME, m_ier));
|
||||
return (UINT8) m_ier;
|
||||
}
|
||||
|
||||
UINT8 duscc_channel::do_dusccreg_cid_r()
|
||||
@ -1647,7 +1684,7 @@ void duscc_channel::do_dusccreg_ttr_w(UINT8 data)
|
||||
case REG_TTR_TXCLK_32X_OTHER: LOG(("32x other channel C/T - not implemented\n")); break;
|
||||
case REG_TTR_TXCLK_2X_OWN: LOG(("2x own channel C/T - not implemented\n")); break;
|
||||
case REG_TTR_TXCLK_32X_OWN: LOG(("32x own channel C/T - not implemented\n")); break;
|
||||
default: LOG(("Wrong programming\n")); break; // Should never happen
|
||||
default: LOG(("DUSCC: Wrong programming\n")); break; // Should never happen
|
||||
}
|
||||
|
||||
LOG(("- BRG Tx rate %u assuming a 14.7456MHz CLK crystal\n", get_baudrate(m_ttr & REG_TTR_BRG_RATE_MASK)));
|
||||
@ -1656,7 +1693,7 @@ void duscc_channel::do_dusccreg_ttr_w(UINT8 data)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Receiver Parameter Resgister (RPRA, RPRB)
|
||||
/* Receiver Parameter Register (RPRA, RPRB)
|
||||
[7] SYN Stripping - This bit controls the DUSCC processing in COP modes of SYN 'character patterns' that occur after the initial
|
||||
character synchronization. Refer to Detailed Operation of the receiver for details and definition of SYN 'patterns', and their
|
||||
accumulation of FCS.
|
||||
@ -1783,7 +1820,7 @@ void duscc_channel::do_dusccreg_rtr_w(UINT8 data)
|
||||
case REG_RTR_RXCLK_DPLL_32X_EXT:LOG(("DPLL, source = 32X External - not implemented\n")); break;
|
||||
case REG_RTR_RXCLK_DPLL_32X_BRG:LOG(("DPLL, source = 32X BRG - not implemented\n")); break;
|
||||
case REG_RTR_RXCLK_DPLL_32X_CT: LOG(("DPLL, source = 32X C/T - not implemented\n")); break;
|
||||
default: LOG(("Wrong programming\n")); break; // Should never happen
|
||||
default: LOG(("DUSCC: Wrong programming\n")); break; // Should never happen
|
||||
}
|
||||
|
||||
LOG(("- BRG Rx rate %u assuming a 14.7456MHz CLK crystal\n", get_baudrate(m_rtr & REG_RTR_BRG_RATE_MASK)));
|
||||
@ -1875,7 +1912,7 @@ void duscc_channel::do_dusccreg_omr_w(UINT8 data)
|
||||
*/
|
||||
void duscc_channel::do_dusccreg_pcr_w(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x) Pin Configuration Register\n", FUNCNAME, data));
|
||||
LOG(("%c %s(%02x)\n", 'A' + m_index, FUNCNAME, data));
|
||||
m_pcr = data;
|
||||
LOG(("- The X2/IDCN pin is %s\n", m_index == duscc_device::CHANNEL_B ? "ignored for channel B" :
|
||||
((m_pcr & REG_PCR_X2_IDC) ? "crystal input" : "daisy chain interrupt output")));
|
||||
@ -1889,7 +1926,7 @@ void duscc_channel::do_dusccreg_pcr_w(UINT8 data)
|
||||
case REG_PCR_RTXC_CNTR_OUT: LOG(("- a counter/timer output\n")); break;
|
||||
case REG_PCR_RTXC_TXCLK_OUT:LOG(("- a Tx clock output\n")); break;
|
||||
case REG_PCR_RTXC_RXCLK_OUT:LOG(("- a Rx clock output\n")); break;
|
||||
default: LOG(("Wrong programming\n")); break; // Should never happen
|
||||
default: LOG(("DUSCC: Wrong programming\n")); break; // Should never happen
|
||||
}
|
||||
LOG(("- The TRxC pin is "));
|
||||
switch( m_pcr & REG_PCR_TRXC_MASK )
|
||||
@ -1919,7 +1956,7 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
|
||||
int rate;
|
||||
|
||||
m_ccr = data;
|
||||
LOG(("%s\n", FUNCNAME));
|
||||
LOG(("%c %s(%02x)\n", 'A' + m_index, FUNCNAME, data));
|
||||
switch(m_ccr)
|
||||
{
|
||||
// TRANSMITTER COMMANDS
|
||||
@ -1929,7 +1966,7 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
|
||||
Also clears the transmitter status bits (TRSR[7:4]) and resets the TxRDY
|
||||
status bit (GSR[I] or GSR[5] for Channels A and B, respectively).
|
||||
The counter/timer and other registers are not affected*/
|
||||
case REG_CCR_RESET_TX: LOG(("- Reset Tx\n"));
|
||||
case REG_CCR_RESET_TX: LOGINT(("- Reset Tx\n"));
|
||||
set_tra_rate(0);
|
||||
m_tx_fifo_wp = m_tx_fifo_rp = 0;
|
||||
m_trsr &= 0x0f;
|
||||
@ -1939,7 +1976,7 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
|
||||
/* Enable transmitter. Enables transmitter operation, conditioned by the state of
|
||||
the CTS ENABLE Tx bit, TPR[2]. Has no effect if invoked when the transmitter has
|
||||
previously been enabled.*/
|
||||
case REG_CCR_ENABLE_TX: LOG(("- Enable Tx\n"));
|
||||
case REG_CCR_ENABLE_TX: LOGINT(("- Enable Tx\n"));
|
||||
m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
|
||||
m_tra = 1;
|
||||
set_tra_rate(m_brg_tx_rate);
|
||||
@ -1950,7 +1987,7 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
|
||||
currently in the FIFO, or any loaded subsequently prior to attaining an empty condition,
|
||||
will be transmitted.
|
||||
TODO: let all the chararcters be transmitted before shutting down shifter */
|
||||
case REG_CCR_DISABLE_TX: LOG(("- Disable Tx\n"));
|
||||
case REG_CCR_DISABLE_TX: LOGINT(("- Disable Tx\n"));
|
||||
set_tra_rate(0);
|
||||
m_tra = 0;
|
||||
m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
|
||||
@ -1962,7 +1999,7 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
|
||||
clears the data path, and clears the receiver status (RSR[7:0], TRSR[3:0], and either
|
||||
GSR[O] or GSR[4] for Channels A and B, respectively). The counter/timer and other
|
||||
registers are not affected.*/
|
||||
case REG_CCR_RESET_RX: LOG(("- Reset Rx\n"));
|
||||
case REG_CCR_RESET_RX: LOGINT(("- Reset Rx\n"));
|
||||
set_rcv_rate(0);
|
||||
m_rx_fifo_wp = m_rx_fifo_rp = 0;
|
||||
m_trsr &= 0xf0;
|
||||
@ -1973,14 +2010,14 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
|
||||
/* Enable receiver. Causes receiver operation to begin, conditioned by the state of the DCD
|
||||
ENABLED Rx bit, RPR[2]. Receiver goes into START, SYN, or FLAG search mode depending on
|
||||
channel protocol mode. Has no effect if invoked when the receiver has previously been enabled.*/
|
||||
case REG_CCR_ENABLE_RX: LOG(("- Enable Rx\n"));
|
||||
case REG_CCR_ENABLE_RX: LOGINT(("- Enable Rx\n"));
|
||||
m_rcv = 1;
|
||||
set_rcv_rate(m_brg_rx_rate);
|
||||
break;
|
||||
|
||||
/* Disable receiver. Terminates operation of the receiver. Any character currently being assembled
|
||||
will be lost. Does not affect FIFO or any status.*/
|
||||
case REG_CCR_DISABLE_RX: LOG(("- Disable Rx\n"));
|
||||
case REG_CCR_DISABLE_RX: LOGINT(("- Disable Rx\n"));
|
||||
m_rcv = 0;
|
||||
m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
|
||||
break;
|
||||
@ -2018,8 +2055,7 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
|
||||
|
||||
void duscc_channel::do_dusccreg_txfifo_w(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x)'%c'\n", FUNCNAME,data, isalnum(data) ? data : ' '));
|
||||
LOG((" - TX wp:%d rp:%d sz:%d\n", m_tx_fifo_wp, m_tx_fifo_rp, m_tx_fifo_sz));
|
||||
LOGTX((" - TX %s(%02x)'%c'\n", FUNCNAME,data, isalnum(data) ? data : ' '));
|
||||
|
||||
/* Tx FIFO is full or...? */
|
||||
if (m_tx_fifo_wp + 1 == m_tx_fifo_rp || ( (m_tx_fifo_wp + 1 == m_tx_fifo_sz) && (m_tx_fifo_rp == 0) ))
|
||||
@ -2053,7 +2089,13 @@ void duscc_channel::do_dusccreg_txfifo_w(UINT8 data)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
|
||||
if (m_omr & REG_OMR_TXRDY_ACTIVATED) // TXRDY on FIFO empty?
|
||||
{
|
||||
if (m_tx_fifo_wp == m_tx_fifo_rp) // TXFIFO empty?
|
||||
m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
|
||||
}
|
||||
else // TXRDY on FIFO not full
|
||||
m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -2072,7 +2114,7 @@ void duscc_channel::do_dusccreg_txfifo_w(UINT8 data)
|
||||
message is received. Asserted status bits can be programmed to generate an interrupt (see Interrupt Enable Register).*/
|
||||
void duscc_channel::do_dusccreg_rsr_w(UINT8 data)
|
||||
{
|
||||
LOG(("%s: %02x\n", FUNCNAME, data));
|
||||
LOG(("%c %s(%02x)\n", 'A' + m_index, FUNCNAME, data));
|
||||
m_rsr &= ~data; // Clear only bits which are 1:s
|
||||
return;
|
||||
}
|
||||
@ -2091,7 +2133,7 @@ void duscc_channel::do_dusccreg_ictsr_w(UINT8 data)
|
||||
return;
|
||||
}
|
||||
|
||||
/* This register provides a 'quick look' at the overall status of both channels of the DUSCC. A write to this register with ls at the
|
||||
/* The GSR register provides a 'quick look' at the overall status of both channels of the DUSCC. A write to this register with ls at the
|
||||
corresponding bit pOSitions causes TxRDY (bits 5 and 1) and/or RxRDY (bits 4 and 0) to be reset. The other status bits can be reset
|
||||
only by resetting the individual status bits that they point to.
|
||||
[7] Channel 8 External or Coutnerrrimer Status - This bit indicates that one of the following status bits is asserted: ICTSRB[6:4].
|
||||
@ -2112,7 +2154,7 @@ void duscc_channel::do_dusccreg_ictsr_w(UINT8 data)
|
||||
receiver' command is invoked.*/
|
||||
void duscc_channel::do_dusccreg_gsr_w(UINT8 data)
|
||||
{
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
LOG(("%c %s(%02x)\n", 'A' + m_index, FUNCNAME, data));
|
||||
m_uart->m_gsr &= (data & REG_GSR_XXREADY_MASK); // Reset only XXREADY bits, the rest needs to be reset by the source
|
||||
return; // TODO: Check of the XXREADY source bits should be reset too
|
||||
}
|
||||
@ -2122,8 +2164,16 @@ void duscc_channel::do_dusccreg_gsr_w(UINT8 data)
|
||||
condition for an interrupt to be generated is that the channel's master interrupt enabled bit, ICR[O] or ICR[1], be asserted.*/
|
||||
void duscc_channel::do_dusccreg_ier_w(UINT8 data)
|
||||
{
|
||||
LOGINT(("%c %s(%02x)\n", 'A' + m_index, FUNCNAME, data));
|
||||
if (REG_IER_DCD_CTS & (data ^ m_ier)) LOGINT(("- DCD/CTS interrups %s\n", (data & REG_IER_DCD_CTS) ? "enabled" : "disabled" ));
|
||||
if (REG_IER_TXRDY & (data ^ m_ier)) LOGINT(("- TXRDY interrupts %s\n", (data & REG_IER_TXRDY) ? "enabled" : "disabled" ));
|
||||
if (REG_IER_TRSR73 & (data ^ m_ier)) LOGINT(("- TRSR73 interrupts %s\n", (data & REG_IER_TRSR73) ? "enabled" : "disabled" ));
|
||||
if (REG_IER_RXRDY & (data ^ m_ier)) LOGINT(("- RXRDY interrupts %s\n", (data & REG_IER_RXRDY) ? "enabled" : "disabled" ));
|
||||
if (REG_IER_RSR76 & (data ^ m_ier)) LOGINT(("- RSR76 interrupts %s\n", (data & REG_IER_RSR76) ? "enabled" : "disabled" ));
|
||||
if (REG_IER_RSR54 & (data ^ m_ier)) LOGINT(("- RSR54 interrupts %s\n", (data & REG_IER_RSR54) ? "enabled" : "disabled" ));
|
||||
if (REG_IER_RSR32 & (data ^ m_ier)) LOGINT(("- RSR32 interrupts %s\n", (data & REG_IER_RSR32) ? "enabled" : "disabled" ));
|
||||
if (REG_IER_RSR10 & (data ^ m_ier)) LOGINT(("- RSR10 interrupts %s\n", (data & REG_IER_RSR10) ? "enabled" : "disabled" ));
|
||||
m_ier = data;
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
m_uart->check_interrupts();
|
||||
return;
|
||||
}
|
||||
@ -2139,6 +2189,12 @@ void duscc_channel::do_dusccreg_icr_w(UINT8 data)
|
||||
{
|
||||
m_uart->m_icr = data;
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
if (duscc_device::REG_ICR_CHB & (data ^ m_uart->m_icr)) LOG(("- Channel B interrupts %s\n", (data & duscc_device::REG_ICR_CHB) ? "enabled" : "disabled" ));
|
||||
if (duscc_device::REG_ICR_CHA & (data ^ m_uart->m_icr)) LOG(("- Channel A interrupts %s\n", (data & duscc_device::REG_ICR_CHA) ? "enabled" : "disabled" ));
|
||||
if (duscc_device::REG_ICR_VEC_MOD & (data ^ m_uart->m_icr)) LOG(("- Vector is %s\n", (data & duscc_device::REG_ICR_VEC_MOD) ? "modified" : "unmodified" ));
|
||||
if (duscc_device::REG_ICR_V2V4_MOD & (data ^ m_uart->m_icr)) LOG(("- Vector bits %s modified\n", (data & duscc_device::REG_ICR_V2V4_MOD) ? "4:2" : "2:0" ));
|
||||
// TODO: LOG the other bits as well
|
||||
m_uart->m_icr = data;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2173,7 +2229,8 @@ UINT8 duscc_channel::read(offs_t &offset)
|
||||
{
|
||||
UINT8 data = 0;
|
||||
int reg = (offset | m_a7) & ~0x20; // Add extended rgisters and remove the channel B bit from offset
|
||||
|
||||
LOG(("\"%s\" %s: %c : Register read '%02x' <- [%02x]", m_owner->tag(), FUNCNAME, 'A' + m_index, data, reg ));
|
||||
LOGR((" * %c Reg %02x -> %02x \n", 'A' + m_index, reg, data));
|
||||
switch (reg)
|
||||
{
|
||||
case REG_CMR1: data = do_dusccreg_cmr1_r(); break;
|
||||
@ -2207,10 +2264,10 @@ UINT8 duscc_channel::read(offs_t &offset)
|
||||
// CDUSCC Extended registers - requires A7 to be set through REG_SEA
|
||||
case REG_CID: data = do_dusccreg_cid_r(); break;
|
||||
default:
|
||||
logerror(" \"%s\" %s: %c : Unsupported RRx register:%02x\n", m_owner->tag(), FUNCNAME, 'A' + m_index, reg);
|
||||
logerror("%s: %c : Unsupported RRx register:%02x\n", FUNCNAME, 'A' + m_index, reg);
|
||||
}
|
||||
|
||||
//LOG(("%s \"%s\": %c : Register R%d read '%02x'\n", FUNCNAME, m_owner->tag(), 'A' + m_index, reg, data));
|
||||
LOGR(("%s \"%s\": %c : Register R%d read '%02x'\n", FUNCNAME, m_owner->tag(), 'A' + m_index, reg, data));
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -2222,7 +2279,7 @@ void duscc_channel::write(UINT8 data, offs_t &offset)
|
||||
{
|
||||
int reg = (offset | m_a7) & ~0x20; // Add extended rgisters and remove the channel B bit from offset
|
||||
|
||||
LOG((" * %c Reg %02x <- %02x \n", 'A' + m_index, reg, data));
|
||||
LOGSETUP((" * %c Reg %02x <- %02x \n", 'A' + m_index, reg, data));
|
||||
LOG(("\"%s\" %s: %c : Register write '%02x' -> [%02x]", m_owner->tag(), FUNCNAME, 'A' + m_index, data, reg ));
|
||||
switch (reg)
|
||||
{
|
||||
@ -2266,7 +2323,7 @@ void duscc_channel::write(UINT8 data, offs_t &offset)
|
||||
case REG_TELR: LOG(("REG_TELR\n")); break;
|
||||
|
||||
default:
|
||||
logerror(" \"%s\" %s: %c : Unsupported WRx register:%02x(%02x)\n", m_owner->tag(), FUNCNAME, 'A' + m_index, reg, data);
|
||||
logerror("%s: %c : Unsupported WRx register:%02x(%02x)\n", FUNCNAME, 'A' + m_index, reg, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2278,7 +2335,6 @@ UINT8 duscc_channel::m_rx_fifo_rp_data()
|
||||
m_rx_fifo_rp_step();
|
||||
data = m_rx_data_fifo[m_rx_fifo_rp];
|
||||
m_rx_fifo_rp = old_rp;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -2294,7 +2350,8 @@ void duscc_channel::m_rx_fifo_rp_step()
|
||||
// check if FIFO is empty
|
||||
if (m_rx_fifo_rp == m_rx_fifo_wp)
|
||||
{
|
||||
// no more characters available in the FIFO
|
||||
// no more characters available in the FIFO
|
||||
LOGINT(("Clear RXRDY in GSR because FIFO is emptied\n"));
|
||||
m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
|
||||
}
|
||||
}
|
||||
@ -2316,7 +2373,7 @@ void duscc_channel::m_tx_fifo_rp_step()
|
||||
void duscc_channel::receive_data(UINT8 data)
|
||||
{
|
||||
LOG(("\"%s\": %c : Receive Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, data));
|
||||
#
|
||||
|
||||
if (m_rx_fifo_wp + 1 == m_rx_fifo_rp || ( (m_rx_fifo_wp + 1 == m_rx_fifo_sz) && (m_rx_fifo_rp == 0) ))
|
||||
{
|
||||
// receive overrun error detected
|
||||
@ -2328,6 +2385,7 @@ void duscc_channel::receive_data(UINT8 data)
|
||||
{
|
||||
m_rx_data_fifo[m_rx_fifo_wp] = data;
|
||||
m_rsr &= ~REG_RSR_OVERRUN_ERROR;
|
||||
LOGINT((" - Setting RXRDY in GSR for channel %c\n", 'A' + m_index));
|
||||
m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
|
||||
|
||||
m_rx_fifo_wp++;
|
||||
@ -2336,8 +2394,19 @@ void duscc_channel::receive_data(UINT8 data)
|
||||
m_rx_fifo_wp = 0;
|
||||
}
|
||||
|
||||
// if (m_eir & REG_IER_)
|
||||
|
||||
if (m_uart->m_icr & (m_index == duscc_device::CHANNEL_A ? duscc_device::REG_ICR_CHA : duscc_device::REG_ICR_CHB))
|
||||
{
|
||||
if (m_ier & REG_IER_RXRDY)
|
||||
{
|
||||
if (m_omr & REG_OMR_RXRDY_ACTIVATED) // interrupt on FIFO full and...
|
||||
{
|
||||
if (m_rx_fifo_rp == m_rx_fifo_wp) // FIFO full?
|
||||
m_uart->trigger_interrupt(m_index, INT_RXREADY);
|
||||
}
|
||||
else
|
||||
m_uart->trigger_interrupt(m_index, INT_RXREADY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,9 @@
|
||||
#define MCFG_DUSCC_OUT_RTXCB_CB(_devcb) \
|
||||
devcb = &duscc_device::set_out_rtxcb_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_DUSCC_OUT_INT_CB(_devcb) \
|
||||
devcb = &duscc_device::set_out_int_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
@ -620,6 +623,7 @@ public:
|
||||
template<class _Object> static devcb_base &set_out_syncb_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_syncb_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_out_rtxcb_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_rtxcb_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_out_trxcb_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_trxcb_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_out_int_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_int_cb.set_callback(object); }
|
||||
|
||||
static void configure_channels(device_t &device, int rxa, int txa, int rxb, int txb)
|
||||
{
|
||||
@ -636,7 +640,12 @@ public:
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
|
||||
// interrupt acknowledge
|
||||
// int m1_r();
|
||||
DECLARE_READ8_MEMBER( iack );
|
||||
|
||||
// device_z80daisy_interface overrides
|
||||
virtual int z80daisy_irq_state() override;
|
||||
virtual int z80daisy_irq_ack() override;
|
||||
virtual void z80daisy_irq_reti() override;
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( rxa_w ) { m_chanA->write_rx(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( rxb_w ) { m_chanB->write_rx(state); }
|
||||
@ -662,11 +671,6 @@ protected:
|
||||
virtual void device_reset() override;
|
||||
virtual machine_config_constructor device_mconfig_additions() const override;
|
||||
|
||||
// device_z80daisy_interface overrides
|
||||
virtual int z80daisy_irq_state() override;
|
||||
virtual int z80daisy_irq_ack() override;
|
||||
virtual void z80daisy_irq_reti() override;
|
||||
|
||||
// internal interrupt management
|
||||
void check_interrupts();
|
||||
void reset_interrupts();
|
||||
@ -720,7 +724,6 @@ protected:
|
||||
|
||||
devcb_write_line m_out_int_cb;
|
||||
|
||||
|
||||
int m_int_state[8]; // interrupt state
|
||||
|
||||
int m_variant;
|
||||
@ -731,15 +734,17 @@ protected:
|
||||
|
||||
enum
|
||||
{
|
||||
REG_ICR_CHB = 0x01,
|
||||
REG_ICR_CHA = 0x02,
|
||||
REG_ICR_VEC_MOD = 0x04,
|
||||
REG_ICR_V2V4_MOD = 0x08,
|
||||
REG_ICR_PRIO_MASK = 0xC0,
|
||||
REG_ICR_PRIO_AHI = 0x00,
|
||||
REG_ICR_PRIO_BHI = 0x40,
|
||||
REG_ICR_PRIO_AINT = 0x80,
|
||||
REG_ICR_PRIO_BINT = 0xC0,
|
||||
REG_ICR_CHB = 0x01,
|
||||
REG_ICR_CHA = 0x02,
|
||||
REG_ICR_VEC_MOD = 0x04,
|
||||
REG_ICR_V2V4_MOD = 0x08,
|
||||
REG_ICR_VEC_MODE_MASK = 0x30,
|
||||
REG_ICR_VEC_MODE_NONE = 0x30,
|
||||
REG_ICR_PRIO_MASK = 0xC0,
|
||||
REG_ICR_PRIO_AHI = 0x00,
|
||||
REG_ICR_PRIO_BHI = 0x40,
|
||||
REG_ICR_PRIO_AINT = 0x80,
|
||||
REG_ICR_PRIO_BINT = 0xC0,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -130,7 +130,7 @@
|
||||
* FFF00000-FFFFFFFF Reserved
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Interrupt sources MVME
|
||||
* Interrupt sources CPU30
|
||||
* ----------------------------------------------------------
|
||||
* Description Device Lvl IRQ VME board
|
||||
* /Board Vector Address
|
||||
@ -141,9 +141,39 @@
|
||||
*
|
||||
* ----------------------------------------------------------
|
||||
*
|
||||
* PIT #1 hardware wiring
|
||||
* ----------------------------------------------------------
|
||||
* PA0-PA3 Rotary Switch 1 input
|
||||
* PA4-PA7 Rotary Switch 2 input
|
||||
* H1-H4 User I/O via optional B5 or optional 5-row VME P2 connector
|
||||
* PB0-PB2 Floppy Disk Drive Control output
|
||||
* PB3-PB4 Floppy Disk Drive Control input
|
||||
* PB5 Floppy Disk Drive Control output
|
||||
* PB6-PB7 DMAC control
|
||||
* PC0,PC1 User I/O via optional B5 or optional 5-row VME P2 connector
|
||||
* PC4,PC7 User I/O via optional B5 or optional 5-row VME P2 connector
|
||||
* PC2 Reserved
|
||||
* PC3 Timer interrupt request
|
||||
* PC5 Port Interrupt Request
|
||||
* PC6 68882 FPCP Sense
|
||||
*
|
||||
* PIT #2 hardware setup wiring
|
||||
* ----------------------------------------------------------
|
||||
* PA0-PA7 User I/O via optional B5 or optional 5-row VME P2 connector
|
||||
* H1-H4 User I/O via optional B5 or optional 5-row VME P2 connector
|
||||
* PB0-PB2 Memory Size
|
||||
* PB3-PB7 Board ID
|
||||
* PC0-PC1 Hardware ID
|
||||
* PC2 Status of write protection for (default and optional) Boot PROMs
|
||||
* PC3 Timer Interrupt request
|
||||
* PC4 Status of write protection for SYSTEM-Flash Memory
|
||||
* PC5 DMA control
|
||||
* PC6 Flash programming voltage control
|
||||
* PC7 Reserved
|
||||
*
|
||||
* DMAC Channel Assignments
|
||||
* ----------------------------------------------------------
|
||||
* Channel MVME147
|
||||
* Channel SYS68K/CPU30
|
||||
* ----------------------------------------------------------
|
||||
*
|
||||
*
|
||||
@ -168,7 +198,11 @@
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define LOGPRINT(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define LOG(x)
|
||||
#define LOGR(x)
|
||||
#define LOGSETUP(x)
|
||||
#define LOGINT(x) LOGPRINT(x)
|
||||
#if VERBOSE >= 2
|
||||
#define logerror printf
|
||||
#endif
|
||||
@ -197,9 +231,24 @@ fccpu30_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
DECLARE_READ32_MEMBER (bootvect_r);
|
||||
DECLARE_WRITE32_MEMBER (bootvect_w);
|
||||
|
||||
/* Interrupt support */
|
||||
// IRQ_CALLBACK_MEMBER(maincpu_iack_callback);
|
||||
DECLARE_WRITE_LINE_MEMBER(fga_irq_callback);
|
||||
UINT8 fga_irq_state;
|
||||
// int fga_irq_vector;
|
||||
int fga_irq_level;
|
||||
|
||||
/* Rotary switch PIT input */
|
||||
DECLARE_READ8_MEMBER (rotary_rd);
|
||||
DECLARE_READ8_MEMBER (flop_dmac_r);
|
||||
DECLARE_WRITE8_MEMBER (flop_dmac_w);
|
||||
DECLARE_READ8_MEMBER (pit1c_r);
|
||||
DECLARE_WRITE8_MEMBER (pit1c_w);
|
||||
DECLARE_READ8_MEMBER (pit2a_r);
|
||||
DECLARE_WRITE8_MEMBER (pit2a_w);
|
||||
DECLARE_READ8_MEMBER (board_mem_id_rd);
|
||||
DECLARE_READ8_MEMBER (pit2c_r);
|
||||
DECLARE_WRITE8_MEMBER (pit2c_w);
|
||||
|
||||
/* VME bus accesses */
|
||||
//DECLARE_READ16_MEMBER (vme_a24_r);
|
||||
@ -219,6 +268,9 @@ private:
|
||||
|
||||
required_device<fga002_device> m_fga002;
|
||||
|
||||
// Helper functions
|
||||
void update_irq_to_maincpu();
|
||||
|
||||
// Pointer to System ROMs needed by bootvect_r and masking RAM buffer for post reset accesses
|
||||
UINT32 *m_sysrom;
|
||||
UINT32 m_sysram[2];
|
||||
@ -231,6 +283,7 @@ static ADDRESS_MAP_START (fccpu30_mem, AS_PROGRAM, 32, fccpu30_state)
|
||||
AM_RANGE (0x00000008, 0x003fffff) AM_RAM /* 4 Mb RAM */
|
||||
AM_RANGE (0xff000000, 0xff7fffff) AM_ROM AM_REGION("roms", 0x000000)
|
||||
AM_RANGE (0xff802000, 0xff8021ff) AM_DEVREADWRITE8("duscc", duscc68562_device, read, write, 0xffffffff) /* Port 1&2 - Dual serial port DUSCC */
|
||||
AM_RANGE (0xff802200, 0xff8023ff) AM_DEVREADWRITE8("duscc2", duscc68562_device, read, write, 0xffffffff) /* Port 3&4 - Dual serial port DUSCC */
|
||||
AM_RANGE (0xff800c00, 0xff800dff) AM_DEVREADWRITE8("pit1", pit68230_device, read, write, 0xffffffff)
|
||||
AM_RANGE (0xff800e00, 0xff800fff) AM_DEVREADWRITE8("pit2", pit68230_device, read, write, 0xffffffff)
|
||||
AM_RANGE (0xffc00000, 0xffcfffff) AM_RAM AM_SHARE ("nvram") /* On-board SRAM with battery backup (nvram) */
|
||||
@ -336,6 +389,39 @@ READ8_MEMBER (fccpu30_state::rotary_rd){
|
||||
return 0xff; // TODO: make this configurable from commandline or artwork
|
||||
}
|
||||
|
||||
// PIT#1 Port B TODO: implement floppy and dma control
|
||||
READ8_MEMBER (fccpu30_state::flop_dmac_r){
|
||||
LOG(("%s\n", FUNCNAME));
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER (fccpu30_state::flop_dmac_w){
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
}
|
||||
|
||||
// PIT#1 Port C TODO: implement timer+port interrupts and 68882 sense
|
||||
// TODO: Connect PC0, PC1, PC4 and PC7 to B5 and/or P2 connector
|
||||
READ8_MEMBER (fccpu30_state::pit1c_r){
|
||||
LOG(("%s\n", FUNCNAME));
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER (fccpu30_state::pit1c_w){
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
}
|
||||
|
||||
// PIT#2 Port A TODO: Connect to B5 and /or P2 connector
|
||||
READ8_MEMBER (fccpu30_state::pit2a_r){
|
||||
LOG(("%s\n", FUNCNAME));
|
||||
logerror("Unsupported user i/o on PIT2 port A detected\n");
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER (fccpu30_state::pit2a_w){
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
logerror("Unsupported user i/o on PIT2 port A detected\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* PI/T #2 Factory settings
|
||||
* B0-B2 Shared Memory Size - From these lines, the on-board Shared RAM capacity can be read in by software.
|
||||
@ -359,6 +445,16 @@ READ8_MEMBER (fccpu30_state::board_mem_id_rd){
|
||||
return 0x36; // CPU-26 1Mb 36 MHz
|
||||
}
|
||||
|
||||
// PIT#2 Port C TODO: implement timer interrupt, DMA i/o, memory control and Hardware ID
|
||||
READ8_MEMBER (fccpu30_state::pit2c_r){
|
||||
LOG(("%s\n", FUNCNAME));
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER (fccpu30_state::pit2c_w){
|
||||
LOG(("%s(%02x)\n", FUNCNAME, data));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Dummy VME access methods until the VME bus device is ready for use */
|
||||
READ16_MEMBER (fccpu30_state::vme_a24_r){
|
||||
@ -380,6 +476,34 @@ WRITE16_MEMBER (fccpu30_state::vme_a16_w){
|
||||
}
|
||||
#endif
|
||||
|
||||
WRITE_LINE_MEMBER(fccpu30_state::fga_irq_callback)
|
||||
{
|
||||
LOGINT(("%s(%02x)\n", FUNCNAME, state));
|
||||
|
||||
fga_irq_state = state;
|
||||
fga_irq_level = m_fga002->get_irq_level();
|
||||
LOGINT((" - FGA irq level %02x\n", fga_irq_level));
|
||||
update_irq_to_maincpu();
|
||||
}
|
||||
|
||||
void fccpu30_state::update_irq_to_maincpu()
|
||||
{
|
||||
LOGINT(("%s()\n", FUNCNAME));
|
||||
LOGINT((" - fga_irq_level: %02x\n", fga_irq_level));
|
||||
LOGINT((" - fga_irq_state: %02x\n", fga_irq_state));
|
||||
switch (fga_irq_level & 0x07)
|
||||
{
|
||||
case 1: m_maincpu->set_input_line(M68K_IRQ_1, fga_irq_state); break;
|
||||
case 2: m_maincpu->set_input_line(M68K_IRQ_2, fga_irq_state); break;
|
||||
case 3: m_maincpu->set_input_line(M68K_IRQ_3, fga_irq_state); break;
|
||||
case 4: m_maincpu->set_input_line(M68K_IRQ_4, fga_irq_state); break;
|
||||
case 5: m_maincpu->set_input_line(M68K_IRQ_5, fga_irq_state); break;
|
||||
case 6: m_maincpu->set_input_line(M68K_IRQ_6, fga_irq_state); break;
|
||||
case 7: m_maincpu->set_input_line(M68K_IRQ_7, fga_irq_state); break;
|
||||
default: logerror("Programmatic error in %s, please report\n", FUNCNAME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Machine configuration
|
||||
*/
|
||||
@ -387,40 +511,106 @@ static MACHINE_CONFIG_START (fccpu30, fccpu30_state)
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD ("maincpu", M68030, XTAL_25MHz)
|
||||
MCFG_CPU_PROGRAM_MAP (fccpu30_mem)
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("fga002", fga002_device, iack)
|
||||
MCFG_NVRAM_ADD_0FILL("nvram")
|
||||
|
||||
/* Terminal Port config */
|
||||
MCFG_DUSCC68562_ADD("duscc", DUSCC_CLOCK, 0, 0, 0, 0 )
|
||||
MCFG_DUSCC_OUT_TXDA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_txd))
|
||||
MCFG_DUSCC_OUT_DTRA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_dtr))
|
||||
MCFG_DUSCC_OUT_RTSA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_rts))
|
||||
/* Force CPU30 series of boards has up to four serial ports, p1-p4, the FGA boot uses p4 as console and subsequent
|
||||
firmware uses p1 as console and in an operating system environment there may be user login shells on the other.
|
||||
|
||||
MCFG_RS232_PORT_ADD ("rs232trm", default_rs232_devices, "terminal")
|
||||
In order to use more than just one terminal MAME supports serial socket servers to which it is possible to
|
||||
connect a telnet terminal to. The general syntax to open a socket server from the command prompts is:
|
||||
|
||||
mame fccpu30 -window -rs232p4 null_modem -bitbngr socket.127.0.0.1:1001
|
||||
|
||||
At the opening screen, before the board starts to execute code, start up the telnet client and give 127.0.0.1:1001 as host
|
||||
It is also possible to enumerate more than one terminal server in order to have several terminal session attached.
|
||||
|
||||
mame fccpu30 -window -rs232p4 null_modem -bitbngr1 socket.127.0.0.1:1001 -rs232p1 null_modem -bitbngr2 socket.127.0.0.1:1002
|
||||
|
||||
Now just start up the telnet clients with 127.0.0.1:1001 and 127.0.0.1:1002 as hosts and you have control of input for each port.
|
||||
*/
|
||||
|
||||
#define RS232P1_TAG "rs232p1"
|
||||
#define RS232P2_TAG "rs232p2"
|
||||
#define RS232P3_TAG "rs232p3"
|
||||
#define RS232P4_TAG "rs232p4"
|
||||
|
||||
MCFG_DUSCC68562_ADD("duscc", DUSCC_CLOCK, 0, 0, 0, 0 )
|
||||
/* Port 1 on Port B */
|
||||
MCFG_DUSCC_OUT_TXDB_CB(DEVWRITELINE(RS232P1_TAG, rs232_port_device, write_txd))
|
||||
MCFG_DUSCC_OUT_DTRB_CB(DEVWRITELINE(RS232P1_TAG, rs232_port_device, write_dtr))
|
||||
MCFG_DUSCC_OUT_RTSB_CB(DEVWRITELINE(RS232P1_TAG, rs232_port_device, write_rts))
|
||||
/* Port 4 on Port A */
|
||||
MCFG_DUSCC_OUT_TXDA_CB(DEVWRITELINE(RS232P4_TAG, rs232_port_device, write_txd))
|
||||
MCFG_DUSCC_OUT_DTRA_CB(DEVWRITELINE(RS232P4_TAG, rs232_port_device, write_dtr))
|
||||
MCFG_DUSCC_OUT_RTSA_CB(DEVWRITELINE(RS232P4_TAG, rs232_port_device, write_rts))
|
||||
/* DUSCC1 interrupt signal REQN is connected to LOCAL IRQ4 of the FGA-002 and level is programmable */
|
||||
MCFG_DUSCC_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq4_w))
|
||||
|
||||
MCFG_DUSCC68562_ADD("duscc2", DUSCC_CLOCK, 0, 0, 0, 0 )
|
||||
/* Port 2 on Port A */
|
||||
MCFG_DUSCC_OUT_TXDA_CB(DEVWRITELINE(RS232P2_TAG, rs232_port_device, write_txd))
|
||||
MCFG_DUSCC_OUT_DTRA_CB(DEVWRITELINE(RS232P2_TAG, rs232_port_device, write_dtr))
|
||||
MCFG_DUSCC_OUT_RTSA_CB(DEVWRITELINE(RS232P2_TAG, rs232_port_device, write_rts))
|
||||
/* Port 3 on Port B */
|
||||
MCFG_DUSCC_OUT_TXDB_CB(DEVWRITELINE(RS232P3_TAG, rs232_port_device, write_txd))
|
||||
MCFG_DUSCC_OUT_DTRB_CB(DEVWRITELINE(RS232P3_TAG, rs232_port_device, write_dtr))
|
||||
MCFG_DUSCC_OUT_RTSB_CB(DEVWRITELINE(RS232P3_TAG, rs232_port_device, write_rts))
|
||||
/* DUSCC2 interrupt signal REQN is connected to LOCAL IRQ5 of the FGA-002 and level is programmable */
|
||||
MCFG_DUSCC_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq5_w))
|
||||
|
||||
MCFG_RS232_PORT_ADD (RS232P1_TAG, default_rs232_devices, nullptr)
|
||||
MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("duscc", duscc68562_device, rxb_w))
|
||||
MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("duscc", duscc68562_device, ctsb_w))
|
||||
|
||||
MCFG_RS232_PORT_ADD (RS232P2_TAG, default_rs232_devices, nullptr)
|
||||
MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("duscc2", duscc68562_device, rxa_w))
|
||||
MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("duscc2", duscc68562_device, ctsa_w))
|
||||
|
||||
MCFG_RS232_PORT_ADD (RS232P3_TAG, default_rs232_devices, nullptr)
|
||||
MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("duscc2", duscc68562_device, rxb_w))
|
||||
MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("duscc2", duscc68562_device, ctsb_w))
|
||||
|
||||
MCFG_RS232_PORT_ADD (RS232P4_TAG, default_rs232_devices, nullptr)
|
||||
MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("duscc", duscc68562_device, rxa_w))
|
||||
MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("duscc", duscc68562_device, ctsa_w))
|
||||
|
||||
MCFG_DUSCC68562_ADD("duscc2", DUSCC_CLOCK, 0, 0, 0, 0 )
|
||||
|
||||
/* PIT Parallel Interface and Timer device, assuming strapped for on board clock */
|
||||
/* PIT Parallel Interface and Timer device, assumed strapped for on board clock */
|
||||
MCFG_DEVICE_ADD ("pit1", PIT68230, XTAL_16MHz / 2) // The PIT clock is not verified on schema but reversed from behaviour
|
||||
MCFG_PIT68230_PA_INPUT_CB(READ8(fccpu30_state, rotary_rd))
|
||||
MCFG_PIT68230_PB_INPUT_CB(READ8(fccpu30_state, flop_dmac_r))
|
||||
MCFG_PIT68230_PB_OUTPUT_CB(WRITE8(fccpu30_state, flop_dmac_w))
|
||||
MCFG_PIT68230_PC_INPUT_CB(READ8(fccpu30_state, pit1c_r))
|
||||
MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(fccpu30_state, pit1c_w))
|
||||
// MCFG_PIT68230_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq2_w)) // Interrupts not yet supported by 68230
|
||||
|
||||
MCFG_DEVICE_ADD ("pit2", PIT68230, XTAL_16MHz / 2) // Th PIT clock is not verified on schema but reversed from behaviour
|
||||
MCFG_PIT68230_PB_INPUT_CB(READ8(fccpu30_state, board_mem_id_rd))
|
||||
MCFG_PIT68230_PA_INPUT_CB(READ8(fccpu30_state, pit2a_r))
|
||||
MCFG_PIT68230_PA_OUTPUT_CB(WRITE8(fccpu30_state, pit2a_w))
|
||||
MCFG_PIT68230_PC_INPUT_CB(READ8(fccpu30_state, pit2c_r))
|
||||
MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(fccpu30_state, pit2c_w))
|
||||
// MCFG_PIT68230_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq3_w)) // Interrupts not yet supported by 68230
|
||||
|
||||
/* FGA-002, Force Gate Array */
|
||||
MCFG_FGA002_ADD("fga002", 0)
|
||||
MCFG_FGA002_OUT_INT_CB(WRITELINE(fccpu30_state, fga_irq_callback))
|
||||
MCFG_FGA002_OUT_LIACK4_CB(DEVREAD8("duscc", duscc_device, iack))
|
||||
MCFG_FGA002_OUT_LIACK5_CB(DEVREAD8("duscc2", duscc_device, iack))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/* ROM definitions */
|
||||
ROM_START (fccpu30)
|
||||
ROM_REGION32_BE(0x900000, "roms", 0)
|
||||
|
||||
// Boots with Board ID set to: 0x36
|
||||
#if 1
|
||||
// Boots with Board ID set to: 0x36 (FGA002 BOOT and VMEPROM on terminal P4)
|
||||
ROM_LOAD16_BYTE("CPU33LO.BIN", 0x000001, 0x40000, CRC (49895fdf) SHA1 (733abd144c95225a2faf920490e31df2a27f8e03))
|
||||
ROM_LOAD16_BYTE("CPU33UP.BIN", 0x000000, 0x40000, CRC (cfe75e94) SHA1 (d40e0635a48607be25f7c58c74b53b7e58fe735d))
|
||||
|
||||
// Boots with Board ID set to: 0x36 (no display yet)
|
||||
#if 0
|
||||
// Boots with Board ID set to: 0x36 (FGA002 BOOT on terminal P4, "Wait until harddisk is up to speed " on terminal P1)
|
||||
#else
|
||||
ROM_LOAD32_BYTE("CPU30LL.BIN", 0x000003, 0x20000, CRC (a03ebf46) SHA1 (48fa0268cb10e20679c093e02574dbd9925f95d1))
|
||||
ROM_LOAD32_BYTE("CPU30LO.BIN", 0x000002, 0x20000, CRC (fefa88ed) SHA1 (71a9ad807c0c2da5c6f6a6dc68c73ad8b52f3ea9))
|
||||
ROM_LOAD32_BYTE("CPU30UP.BIN", 0x000001, 0x20000, CRC (dfed1f68) SHA1 (71478a77d5ab5da0fabcd78e69537919b560e3b8))
|
||||
@ -436,44 +626,139 @@ ROM_END
|
||||
*
|
||||
* FGA-002 Bootprom version 3.1 is released May 28, 1990, coprighted by FORCE Computers Gmbh
|
||||
*
|
||||
* Bootprom PIT setup sequence
|
||||
* 0a 00 <- read port A without side effects
|
||||
* 0b 00 <- read port B without side effects
|
||||
* 10 00 -> TCR - Timer Control register: Disable timer
|
||||
* 13 ff -> CPRH - Counter Preload Regsiter High
|
||||
* 14 ff -> CPRM - Counter Preload Regsiter Mid
|
||||
* 15 ff -> CPRL - Counter Preload Regsiter Low
|
||||
* 10 01 -> TCR - Timer Control register: Enable timer
|
||||
* ------ init ends -------- clock: 4217
|
||||
*
|
||||
* To start VMEPROM, the rotary switches must both be set to 'F' (PI/T #1 port A)
|
||||
*
|
||||
* ------ next config -------- clock: 1964222
|
||||
* 10 00 -> TCR - Timer Control register: Disable timer
|
||||
* 17 00 -> CRH - Counter Register High
|
||||
* 18 00 -> CRM - Counter Register Medium
|
||||
* 19 00 -> CRL - Counter Register Low
|
||||
*
|
||||
* DUSCC #1 channel A setup sequence
|
||||
* 0f 00 -> REG_CCR - reset Tx Command
|
||||
* 0f 40 -> REG_CCR - reset Rx Command
|
||||
* 00 07 -> REG_CMR1 - Async mode
|
||||
* 01 38 -> REG_CMR2 - Normal polled or interrupt mode, no DMA
|
||||
* 04 7f -> REG_TPR - Tx 8 bits, CTS and RTS, 1 STOP bit
|
||||
* 06 1b -> REG_RPR - Rx RTS, 8 bits, no DCD, no parity
|
||||
* 05 3d -> REG_TTR - Tx BRG 9600 (assuming a 14.7456 crystal)
|
||||
* 07 2d -> REG_RTR - Rx BRG 9600 (assuming a 14.7456 crystal)
|
||||
* 0e 27 -> REG_PCR - TRxC = RxCLK 1x, RTxC is input, RTS, GPO2, crystal oscillator connected to X2
|
||||
* 0b f1 -> REG_OMR - RTS low, OUT1 = OUT2 = high, RxRdy asserted for each character,
|
||||
* TxRdy asserted on threshold, Same Tx Residual Character Length as for REG_TPR
|
||||
* 0f 00 -> REG_CCR - reset Tx Command
|
||||
* 0f 40 -> REG_CCR - reset Rx Command
|
||||
* 0f 02 -> REG_CCR - enable Tx Command
|
||||
* 0f 42 -> REG_CCR - enable Rx Command
|
||||
* Bootprom PIT setup sequence - To start VMEPROM, the rotary switches must both be set to 'F' (PI/T #1 port A)
|
||||
* --------------------------------------------------------------------------------------------------------------
|
||||
* :pit1 Reg 10 -> ff PAAR - read port A of PIT1 without side effects
|
||||
|
||||
* :pit2 Reg 10 -> 36 PBAR - read port B of PIT2 without side effects
|
||||
* :pit2 Reg 10 <- 00 TCR - PC3/PC7 is I/O, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer disabled
|
||||
* :pit2 Reg 13 <- ff CPRH - Counter Preload Regsiter High
|
||||
* :pit2 Reg 14 <- ff CPRM - Counter Preload Regsiter Mid
|
||||
* :pit2 Reg 15 <- ff CPRL - Counter Preload Regsiter Low
|
||||
* :pit2 Reg 10 <- 01 TCR - PC3/PC7 is I/O, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer enabled
|
||||
* :pit2 Reg 10 <- 00 TCR - PC3/PC7 is I/O, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer disabled
|
||||
* :pit2 Reg -> ff CNTRH - Current value of timer high byte
|
||||
* :pit2 Reg -> b3 CNTRM - Current value of timer mid byte
|
||||
* :pit2 Reg -> 70 CNTRL - Current value of timer low byte
|
||||
|
||||
* :pit1 Reg 10 <- e0 TCR - PC3 is TOUT, PC7 is I/O, Interrupts enabled, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer disabled
|
||||
* :pit1 Reg 00 <- 20 PGCR -
|
||||
* :pit1 Reg 01 <- 08 PSRR -
|
||||
* :pit1 Reg 06 <- c0 PACR -
|
||||
* :pit1 Reg 02 <- 00 PADDR -
|
||||
* :pit1 Reg 07 <- c0 PBCR -
|
||||
* :pit1 Reg 09 <- 00 PBDR -
|
||||
* :pit1 Reg 03 <- 00 PBDDR -
|
||||
* :pit1 Reg 0c <- 17 PCDR -
|
||||
* :pit1 Reg 04 <- 17 PCDDR -
|
||||
* :pit1 Reg 15 <- e2 CPRL -
|
||||
* :pit1 Reg 14 <- 04 CPRM -
|
||||
* :pit1 Reg 13 <- 00 CPRH -
|
||||
* :pit1 Reg 11 <- f2 TIVR -
|
||||
* :pit1 Reg 10 <- 41 TCR - PC3 is SQW at TOUT, PC7 is I/O, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer enabled
|
||||
|
||||
* :pit2 Reg 10 <- e2 PC3 is TOUT, PC7 is I/O, Interrupts enabled, PC2 is timer enable/disable, CLK and prescaler, Preload timer on 0 (zero), Timer disabled
|
||||
* :pit2 Reg 00 <- 1e PGCR
|
||||
* :pit2 Reg 01 <- 08 PSRR
|
||||
* :pit2 Reg 06 <- c0 PACR
|
||||
* :pit2 Reg 02 <- 00 PADDR
|
||||
* :pit2 Reg 07 <- c0 PBCR
|
||||
* :pit2 Reg 03 <- 00 PBDDR
|
||||
* :pit2 Reg 04 <- 00 PCDDR
|
||||
* :pit2 Reg 15 <- 08 CPRL
|
||||
* :pit2 Reg 14 <- 00 CPRM
|
||||
* :pit2 Reg 13 <- 00 CPRH
|
||||
* :pit2 Reg 11 <- f3 TIVR
|
||||
* :pit2 Reg 10 <- e3 PC3 is TOUT, PC7 is I/O, Interrupts enabled, PC2 is timer enable/disable, CLK and prescaler, Preload timer on 0 (zero), Timer enabled
|
||||
|
||||
* DUSCC #1 channel A setup 1 sequence FGA-002 firmware (polled i/o)
|
||||
* A Reg 0f <- 00 - reset Tx Command
|
||||
* A Reg 0f <- 40 - reset Rx Command
|
||||
* A Reg 00 <- 07 - Async mode
|
||||
* A Reg 01 <- 38 - Normal polled or interrupt mode, no DMA
|
||||
* A Reg 04 <- 7f - Tx 8 bits, CTS and RTS, 1 STOP bit
|
||||
* A Reg 06 <- 1b - Rx RTS, 8 bits, no DCD, no parity
|
||||
* A Reg 05 <- 3d - Tx BRG 9600 (assuming a 14.7456 crystal)
|
||||
* A Reg 07 <- 2d - Rx BRG 9600 (assuming a 14.7456 crystal)
|
||||
* A Reg 0e <- 27 - TRxC = RxCLK 1x, RTxC is input, RTS, GPO2, crystal oscillator connected to X2
|
||||
* A Reg 0b <- f1 - RTS low, OUT1 = OUT2 = high, RxRdy asserted on FIFO not empty
|
||||
* TxRdy asserted on FIFO not empty, Same Tx Residual Character Length as for REG_TPR
|
||||
* A Reg 0f <- 00 - reset Tx Command
|
||||
* A Reg 0f <- 40 - reset Rx Command
|
||||
* A Reg 0f <- 02 - enable Tx Command
|
||||
* A Reg 0f <- 42 - enable Rx Command
|
||||
*--- end of setup sequence ---
|
||||
* loop:
|
||||
* read <- REG_GSR
|
||||
* until something needs attention
|
||||
*
|
||||
* DUSCC #1 channel A & B setup 2 sequence CPU-33 VMEPROM with PDOS (interrupt driven i/o)
|
||||
* A Reg 0f <- 00 - reset Tx Command
|
||||
* A Reg 0f <- 40 - reset Rx Command
|
||||
* A Reg 00 <- 07 - Async mode
|
||||
* A Reg 01 <- 38 - Normal polled or interrupt mode, no DMA
|
||||
* A Reg 04 <- 7f - Tx 8 bits, CTS and RTS, 1 STOP bit
|
||||
* A Reg 06 <- 1b - Rx RTS, 8 bits, no DCD, no parity
|
||||
* A Reg 0b <- e1 - RTS low, OUT1 = OUT2 = high, RxRdy asserted on FIFO not empty
|
||||
* TxRdy asserted on FIFO not full, Same Tx Residual Character Length as for REG_TPR
|
||||
* A Reg 0e <- 27 - TRxC = RxCLK 1x, RTxC is input, RTS, GPO2, crystal oscillator connected to X2
|
||||
* A Reg 07 <- 2d - Rx BRG 9600 (assuming a 14.7456 crystal)
|
||||
* A Reg 05 <- 3d - Tx BRG 9600 (assuming a 14.7456 crystal)
|
||||
* A Reg 1c <- 10 - RXRDY interrupts enabled
|
||||
* A Reg 1e <- 1c - Interrupt vector
|
||||
* A Reg 1f <- 83 - Interleaved prio with A high, no status in vector, enable interrupts for A & B channel
|
||||
* A Reg 0f <- 00 - reset Tx Command
|
||||
* A Reg 0f <- 02 - enable Tx Command
|
||||
* A Reg 0f <- 40 - reset Rx Command
|
||||
* A Reg 0f <- 42 - enable Rx Command
|
||||
* Repeated setup for channel B
|
||||
*
|
||||
* FGA setup
|
||||
void fga002_device::do_fga002reg_icrtim0_w(UINT8)(00)
|
||||
void fga002_device::do_fga002reg_ctl3_w(UINT8)(0c)
|
||||
void fga002_device::do_fga002reg_icrlocal0_w(UINT8)(00)
|
||||
void fga002_device::do_fga002reg_icrlocal1_w(UINT8)(00)
|
||||
void fga002_device::do_fga002reg_icrlocal2_w(UINT8)(00)
|
||||
void fga002_device::do_fga002reg_icrlocal3_w(UINT8)(00)
|
||||
void fga002_device::do_fga002reg_icrlocal4_w(UINT8)(00)
|
||||
void fga002_device::do_fga002reg_icrlocal5_w(UINT8)(00)
|
||||
void fga002_device::do_fga002reg_icrlocal6_w(UINT8)(00)
|
||||
void fga002_device::do_fga002reg_icrlocal7_w(UINT8)(00)
|
||||
|
||||
* A Reg 10 <- 20
|
||||
UINT8 duscc_channel::do_dusccreg_rxfifo_r()
|
||||
- RX rp:0 wp:1 sz:4
|
||||
- RX reading out data:6e 'n'
|
||||
|
||||
UINT8 duscc_channel::do_dusccreg_rxfifo_r()
|
||||
- RX rp:1 wp:2 sz:4
|
||||
- RX reading out data:6e 'n'
|
||||
* A Reg 10 <- 6e
|
||||
* A Reg 10 <- 0d
|
||||
* A Reg 10 <- 0a
|
||||
void fga002_device::do_fga002reg_icrlocal2_w(UINT8)(4d)
|
||||
void fga002_device::do_fga002reg_icrlocal4_w(UINT8)(1c)
|
||||
* A Reg 0f <- 00
|
||||
* A Reg 0f <- 40
|
||||
* A Reg 00 <- 07
|
||||
* A Reg 01 <- 38
|
||||
* A Reg 04 <- 7f
|
||||
* A Reg 06 <- 1b
|
||||
* A Reg 0b <- e1
|
||||
* A Reg 0e <- 27
|
||||
* A Reg 07 <- 2d
|
||||
* A Reg 05 <- 3d
|
||||
* A Reg 1c <- 10
|
||||
void duscc_channel::do_dusccreg_ier_w(UINT8)(10)
|
||||
- RXRDY interrupts enabled
|
||||
:duscc void duscc_device::check_interrupts()()
|
||||
:duscc virtual int duscc_device::z80daisy_irq_state() A:[00][00][00][00] B:[00][00][00][00] Interrupt State 00
|
||||
void fga002_device::trigger_interrupt(UINT8)(34)
|
||||
Interrupt Level 4, caused by ICR 1c with vector 34
|
||||
void fga002_device::check_interrupts()()
|
||||
:fga002 virtual int fga002_device::z80daisy_irq_state() Level 0-7:[00][00] [00][00] [01][00] [00][00]
|
||||
void fccpu30_state::fga_irq_callback(int)(01)
|
||||
void fga002_device::check_interrupts()()
|
||||
*/
|
||||
|
||||
/* Driver */
|
||||
|
Loading…
Reference in New Issue
Block a user