Skip to content

Commit

Permalink
am79c90: delay interrupt after initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
pmackinlay committed Jan 31, 2025
1 parent 45cd9fe commit 29bcc72
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
34 changes: 26 additions & 8 deletions src/devices/machine/am79c90.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
* CMOS Local Area Network Controller for Ethernet (C-LANCE).
*
* Sources:
* - Am7990 Local Area Network Controller for Ethernet (LANCE), Publication #05698, Rev. C, June 1990, Advanced Micro Devices
* - Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE), Publication #17881, Rev. C, January 1998, Advanced Micro Devices
*
* http://bitsavers.org/components/amd/Am7990/Am7990.pdf
* http://bitsavers.org/components/amd/Am7990/Am79c90.pdf
*
* TODO
* TODO:
* - external loopback
* - hp9k/3xx diagnostic failures
*
Expand Down Expand Up @@ -64,6 +63,7 @@ am7990_device_base::am7990_device_base(const machine_config &mconfig, device_typ
, m_intr_out_cb(*this)
, m_dma_in_cb(*this, 0)
, m_dma_out_cb(*this)
, m_interrupt(nullptr)
, m_transmit_poll(nullptr)
, m_intr_out_state(1)
{
Expand All @@ -84,6 +84,7 @@ constexpr attotime am7990_device_base::TX_POLL_PERIOD;

void am7990_device_base::device_start()
{
m_interrupt = timer_alloc(FUNC(am7990_device_base::interrupt), this);
m_transmit_poll = timer_alloc(FUNC(am7990_device_base::transmit_poll), this);
m_transmit_poll->adjust(TX_POLL_PERIOD, 0, TX_POLL_PERIOD);

Expand Down Expand Up @@ -123,15 +124,20 @@ void am7990_device_base::device_reset()
update_interrupts();
}

void am7990_device_base::update_interrupts()
void am7990_device_base::interrupt(s32 param)
{
m_intr_out_cb(param);
}

void am7990_device_base::update_interrupts(attotime const delay)
{
if (m_csr[0] & CSR0_INEA)
{
// update intr
if (bool(m_csr[0] & CSR0_INTR) == m_intr_out_state)
{
m_intr_out_state = !m_intr_out_state;
m_intr_out_cb(m_intr_out_state);
m_interrupt->adjust(delay, m_intr_out_state);

if (!m_intr_out_state)
LOG("interrupt asserted\n");
Expand All @@ -143,7 +149,7 @@ void am7990_device_base::update_interrupts()
if (!m_intr_out_state)
{
m_intr_out_state = !m_intr_out_state;
m_intr_out_cb(m_intr_out_state);
m_interrupt->adjust(delay, m_intr_out_state);
}
}
}
Expand Down Expand Up @@ -543,6 +549,8 @@ void am7990_device_base::regs_w(offs_t offset, u16 data)
{
LOGMASKED(LOG_REG, "regs_w csr%d data 0x%04x (%s)\n", m_rap, data, machine().describe_context());

attotime delay = attotime::zero;

switch (m_rap)
{
case 0: // Control/Status
Expand Down Expand Up @@ -571,7 +579,17 @@ void am7990_device_base::regs_w(offs_t offset, u16 data)
if ((data & CSR0_INIT) && !(m_csr[0] & CSR0_INIT))
{
if (m_csr[0] & CSR0_STOP)
{
initialize();

/*
* Initialization reads 12 words from the bus using single
* word DMA transfers. Allow 2 cycles for bus acquisition
* and release, plus 6 cycles for each single word DMA
* transfer.
*/
delay = attotime::from_ticks((1 + 6 + 1) * 12, clock());
}
else
m_csr[0] |= m_idon ? CSR0_IDON : CSR0_INIT;
}
Expand Down Expand Up @@ -649,7 +667,7 @@ void am7990_device_base::regs_w(offs_t offset, u16 data)
else
m_csr[0] &= ~CSR0_INTR;

update_interrupts();
update_interrupts(delay);
break;

case 1: // Least significant 15 bits of the Initialization Block
Expand Down
6 changes: 4 additions & 2 deletions src/devices/machine/am79c90.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ class am7990_device_base : public device_t, public device_network_interface

// device helpers
void initialize();
void update_interrupts();
void interrupt(s32 param);
void update_interrupts(attotime const delay = attotime::zero);
int receive(u8 *buf, int length);
TIMER_CALLBACK_MEMBER(transmit_poll);
void transmit_poll(s32 param);
void transmit();
bool address_filter(u8 *buf);

Expand Down Expand Up @@ -163,6 +164,7 @@ class am7990_device_base : public device_t, public device_network_interface
u8 m_tx_ring_pos;
u16 m_tx_md[4];

emu_timer *m_interrupt;
emu_timer *m_transmit_poll;
int m_intr_out_state;
bool m_idon;
Expand Down

0 comments on commit 29bcc72

Please sign in to comment.