Skip to content

Commit 29bcc72

Browse files
committed
am79c90: delay interrupt after initialization
1 parent 45cd9fe commit 29bcc72

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

src/devices/machine/am79c90.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
* CMOS Local Area Network Controller for Ethernet (C-LANCE).
77
*
88
* Sources:
9+
* - Am7990 Local Area Network Controller for Ethernet (LANCE), Publication #05698, Rev. C, June 1990, Advanced Micro Devices
10+
* - Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE), Publication #17881, Rev. C, January 1998, Advanced Micro Devices
911
*
10-
* http://bitsavers.org/components/amd/Am7990/Am7990.pdf
11-
* http://bitsavers.org/components/amd/Am7990/Am79c90.pdf
12-
*
13-
* TODO
12+
* TODO:
1413
* - external loopback
1514
* - hp9k/3xx diagnostic failures
1615
*
@@ -64,6 +63,7 @@ am7990_device_base::am7990_device_base(const machine_config &mconfig, device_typ
6463
, m_intr_out_cb(*this)
6564
, m_dma_in_cb(*this, 0)
6665
, m_dma_out_cb(*this)
66+
, m_interrupt(nullptr)
6767
, m_transmit_poll(nullptr)
6868
, m_intr_out_state(1)
6969
{
@@ -84,6 +84,7 @@ constexpr attotime am7990_device_base::TX_POLL_PERIOD;
8484

8585
void am7990_device_base::device_start()
8686
{
87+
m_interrupt = timer_alloc(FUNC(am7990_device_base::interrupt), this);
8788
m_transmit_poll = timer_alloc(FUNC(am7990_device_base::transmit_poll), this);
8889
m_transmit_poll->adjust(TX_POLL_PERIOD, 0, TX_POLL_PERIOD);
8990

@@ -123,15 +124,20 @@ void am7990_device_base::device_reset()
123124
update_interrupts();
124125
}
125126

126-
void am7990_device_base::update_interrupts()
127+
void am7990_device_base::interrupt(s32 param)
128+
{
129+
m_intr_out_cb(param);
130+
}
131+
132+
void am7990_device_base::update_interrupts(attotime const delay)
127133
{
128134
if (m_csr[0] & CSR0_INEA)
129135
{
130136
// update intr
131137
if (bool(m_csr[0] & CSR0_INTR) == m_intr_out_state)
132138
{
133139
m_intr_out_state = !m_intr_out_state;
134-
m_intr_out_cb(m_intr_out_state);
140+
m_interrupt->adjust(delay, m_intr_out_state);
135141

136142
if (!m_intr_out_state)
137143
LOG("interrupt asserted\n");
@@ -143,7 +149,7 @@ void am7990_device_base::update_interrupts()
143149
if (!m_intr_out_state)
144150
{
145151
m_intr_out_state = !m_intr_out_state;
146-
m_intr_out_cb(m_intr_out_state);
152+
m_interrupt->adjust(delay, m_intr_out_state);
147153
}
148154
}
149155
}
@@ -543,6 +549,8 @@ void am7990_device_base::regs_w(offs_t offset, u16 data)
543549
{
544550
LOGMASKED(LOG_REG, "regs_w csr%d data 0x%04x (%s)\n", m_rap, data, machine().describe_context());
545551

552+
attotime delay = attotime::zero;
553+
546554
switch (m_rap)
547555
{
548556
case 0: // Control/Status
@@ -571,7 +579,17 @@ void am7990_device_base::regs_w(offs_t offset, u16 data)
571579
if ((data & CSR0_INIT) && !(m_csr[0] & CSR0_INIT))
572580
{
573581
if (m_csr[0] & CSR0_STOP)
582+
{
574583
initialize();
584+
585+
/*
586+
* Initialization reads 12 words from the bus using single
587+
* word DMA transfers. Allow 2 cycles for bus acquisition
588+
* and release, plus 6 cycles for each single word DMA
589+
* transfer.
590+
*/
591+
delay = attotime::from_ticks((1 + 6 + 1) * 12, clock());
592+
}
575593
else
576594
m_csr[0] |= m_idon ? CSR0_IDON : CSR0_INIT;
577595
}
@@ -649,7 +667,7 @@ void am7990_device_base::regs_w(offs_t offset, u16 data)
649667
else
650668
m_csr[0] &= ~CSR0_INTR;
651669

652-
update_interrupts();
670+
update_interrupts(delay);
653671
break;
654672

655673
case 1: // Least significant 15 bits of the Initialization Block

src/devices/machine/am79c90.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ class am7990_device_base : public device_t, public device_network_interface
3434

3535
// device helpers
3636
void initialize();
37-
void update_interrupts();
37+
void interrupt(s32 param);
38+
void update_interrupts(attotime const delay = attotime::zero);
3839
int receive(u8 *buf, int length);
39-
TIMER_CALLBACK_MEMBER(transmit_poll);
40+
void transmit_poll(s32 param);
4041
void transmit();
4142
bool address_filter(u8 *buf);
4243

@@ -163,6 +164,7 @@ class am7990_device_base : public device_t, public device_network_interface
163164
u8 m_tx_ring_pos;
164165
u16 m_tx_md[4];
165166

167+
emu_timer *m_interrupt;
166168
emu_timer *m_transmit_poll;
167169
int m_intr_out_state;
168170
bool m_idon;

0 commit comments

Comments
 (0)