diff options
author | 2018-11-22 14:46:45 +0700 | |
---|---|---|
committer | 2018-11-22 14:46:45 +0700 | |
commit | 3349e3e990ab54cf46cea19180ce36f91bd0281d (patch) | |
tree | b7378a9d5929ad10d092c8b229db0f5917f4f93e | |
parent | 7c932d2b5c86d4ac69f949490be7d347548d5938 (diff) |
am79c90: fixes (nw)
* took over copyright due to near-total rewrite
* tweaked logging
* corrected tx/rx on/off behaviour
* block register access while not stopped
* crc error is an error
-rw-r--r-- | src/devices/machine/am79c90.cpp | 114 | ||||
-rw-r--r-- | src/devices/machine/am79c90.h | 37 |
2 files changed, 76 insertions, 75 deletions
diff --git a/src/devices/machine/am79c90.cpp b/src/devices/machine/am79c90.cpp index 4ea0fd2ba7f..ab447a13d8a 100644 --- a/src/devices/machine/am79c90.cpp +++ b/src/devices/machine/am79c90.cpp @@ -1,13 +1,43 @@ // license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/***************************************************************************** - - AMD Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE) - - TODO: - - Error handling - -*****************************************************************************/ +// copyright-holders:Patrick Mackinlay + +/* + * AMD Am7990 Local Area Network Controller for Ethernet (LANCE) and Am79C90 + * CMOS Local Area Network Controller for Ethernet (C-LANCE). + * + * Sources: + * + * https://datasheet.datasheetarchive.com/originals/distributors/Datasheets-115/DSAP00824.pdf + * + * TODO + * - hp9k/3xx diagnostic failures + * + * _____ _____ + * Vss 1 |* \_/ | 48 Vdd + * DAL7 2 | | 47 DAL8 + * DAL6 3 | | 46 DAL9 + * DAL5 4 | | 45 DAL10 + * DAL4 5 | | 44 DAL11 + * DAL3 6 | | 43 DAL12 + * DAL2 7 | | 42 DAL13 + * DAL1 8 | | 41 DAL14 + * DAL0 9 | | 40 DAL15 + * READ 10 | | 39 A16 + * /INTR 11 | | 38 A17 + * /DALI 12 | Am79C90 | 37 A18 + * /DALI 13 | | 36 A19 + * /DAS 14 | | 35 A20 + * /BM0,BYTE 15 | | 34 A21 + * /BM1,/BUSAKO 16 | | 33 A22 + * /HOLD,/BUSRQ 17 | | 32 A23 + * ALE,/AS 18 | | 31 RX + * /HLDA 19 | | 30 RENA + * /CS 20 | | 29 TX + * ADR 21 | | 28 CLSN + * /READY 22 | | 27 RCLK + * /RESET 23 | | 26 TENA + * Vss 24 |_____________| 25 TCLK + */ #include "emu.h" #include "am79c90.h" @@ -89,8 +119,6 @@ void am7990_device_base::device_reset() m_csr[3] = 0; m_lb_length = 0; - m_transmit_poll->enable(false); - update_interrupts(); } @@ -103,6 +131,7 @@ void am7990_device_base::update_interrupts() { m_intr_out_state = !m_intr_out_state; m_intr_out_cb(m_intr_out_state); + LOG("interrupt asserted\n"); } } else @@ -171,6 +200,8 @@ int am7990_device_base::receive(u8 *buf, int length) u32 const rx_buf_address = (u32(m_rx_md[1] & 0xff) << 16) | m_rx_md[0]; int const rx_buf_length = -s16(m_rx_md[2]); + LOGMASKED(LOG_RXTX, "receive buffer address 0x%06x length %d\n", rx_buf_address, rx_buf_length); + // write the data to memory int const count = std::min(length - offset, rx_buf_length); dma_out(rx_buf_address, &buf[offset], count); @@ -213,7 +244,7 @@ int am7990_device_base::receive(u8 *buf, int length) { LOGMASKED(LOG_RXTX, "receive incorrect fcs 0x%08x\n", ~crc); - m_rx_md[1] |= RMD1_CRC; + m_rx_md[1] |= RMD1_ERR | RMD1_CRC; } } @@ -250,7 +281,7 @@ void am7990_device_base::recv_complete_cb(int result) void am7990_device_base::transmit_poll(void *ptr, s32 param) { // receive pending internal loopback data - if (m_lb_length && (m_mode & MODE_LOOP) && (m_mode & MODE_INTL)) + if (m_lb_length && (m_mode & MODE_LOOP) && (m_mode & MODE_INTL) && (m_csr[0] & CSR0_RXON)) { int const result = receive(m_lb_buf, m_lb_length); m_lb_length = 0; @@ -259,12 +290,17 @@ void am7990_device_base::transmit_poll(void *ptr, s32 param) return; } - u32 const ring_address = (m_tx_ring_base + (m_tx_ring_pos << 3)) & RING_ADDR_MASK; - m_tx_md[1] = m_dma_in_cb(ring_address | 2); + if (m_csr[0] & CSR0_TXON) + { + m_csr[0] &= ~CSR0_TDMD; - // start transmitting if we own the current descriptor - if (m_tx_md[1] & TMD1_OWN) - transmit(); + u32 const ring_address = (m_tx_ring_base + (m_tx_ring_pos << 3)) & RING_ADDR_MASK; + m_tx_md[1] = m_dma_in_cb(ring_address | 2); + + // start transmitting if we own the current descriptor + if (m_tx_md[1] & TMD1_OWN) + transmit(); + } } void am7990_device_base::transmit() @@ -293,7 +329,7 @@ void am7990_device_base::transmit() m_transmit_poll->enable(false); // check whether to append fcs or not - bool const add_fcs = !(m_mode & MODE_DTCR) || ((type() == AM79C90) && (m_tx_md[1] & TMD1_ADD_FCS)); + bool const append_fcs = !(m_mode & MODE_DTCR) || ((type() == AM79C90) && (m_tx_md[1] & TMD1_ADD_FCS)); u8 buf[4096]; int length = 0; @@ -308,6 +344,8 @@ void am7990_device_base::transmit() u32 const tx_buf_address = (u32(m_tx_md[1] & 0xff) << 16) | m_tx_md[0]; u16 const tx_buf_length = -s16(m_tx_md[2]); + LOGMASKED(LOG_RXTX, "transmit buffer address 0x%06x length %d\n", tx_buf_address, tx_buf_length); + // minimum length 100 when chaining, or 64 when not (except for internal loopback mode) if (!length && tx_buf_length < ((m_tx_md[1] & TMD1_ENP) ? 64 : 100) && ((m_mode & (MODE_LOOP | MODE_INTL)) != (MODE_LOOP | MODE_INTL))) logerror("first transmit buffer length %d less than required minimum\n", tx_buf_length); @@ -343,7 +381,6 @@ void am7990_device_base::transmit() // turn off the transmitter m_csr[0] &= ~CSR0_TXON; - m_transmit_poll->enable(false); break; } } @@ -352,7 +389,7 @@ void am7990_device_base::transmit() } // compute and append the fcs - if (add_fcs) + if (append_fcs) { u32 const crc = util::crc32_creator::simple(buf, length); @@ -380,7 +417,7 @@ void am7990_device_base::transmit() return; } - int const fcs_length = add_fcs ? 4 : 0; + int const fcs_length = append_fcs ? 4 : 0; if ((length - fcs_length) < 8 || (length - fcs_length) > 32) { @@ -432,10 +469,8 @@ void am7990_device_base::send_complete_cb(int result) m_csr[0] |= CSR0_TINT | CSR0_INTR; update_interrupts(); - // TODO: back-to-back transmit - - // resume transmit polling - m_transmit_poll->enable(true); + // resume transmit polling (back-to-back) + m_transmit_poll->adjust(attotime::zero, 0, TX_POLL_PERIOD); } READ16_MEMBER(am7990_device_base::regs_r) @@ -444,7 +479,10 @@ READ16_MEMBER(am7990_device_base::regs_r) { LOGMASKED(LOG_REG, "regs_r csr%d data 0x%04x (%s)\n", m_rap, m_csr[m_rap], machine().describe_context()); - return m_csr[m_rap]; + if (m_rap && !(m_csr[0] & CSR0_STOP)) + return space.unmap(); + else + return m_csr[m_rap]; } else return m_rap; @@ -528,14 +566,14 @@ WRITE16_MEMBER(am7990_device_base::regs_w) m_csr[0] &= ~CSR0_TXON; else m_csr[0] |= CSR0_TXON; - - if (m_csr[0] & CSR0_TXON) - m_transmit_poll->enable(true); } // transmit demand - if ((data & CSR0_TDMD) && (m_csr[0] & CSR0_TXON)) + if ((data & CSR0_TDMD) && !(m_csr[0] & CSR0_TDMD)) + { + m_csr[0] |= CSR0_TDMD; m_transmit_poll->adjust(attotime::zero, 0, TX_POLL_PERIOD); + } // ERR == BABL || CERR || MISS || MERR if (m_csr[0] & CSR0_ANY_ERR) @@ -560,7 +598,8 @@ WRITE16_MEMBER(am7990_device_base::regs_w) // Datasheet says "must be zero", but doesn't indicate what // happens if it's written non-zero. Must be writable to pass // system diagnostic on MIPS RS2030. - m_csr[1] = data; + if (m_csr[0] & CSR0_STOP) + m_csr[1] = data; break; case 2: // Most significant 8 bits of the Initialization Block @@ -568,11 +607,13 @@ WRITE16_MEMBER(am7990_device_base::regs_w) // write as zero, while LANCE datasheet just says "reserved". // MIPS RS2030 diagnostic requires these bits to be writable, // so assuming this is older device behaviour. - m_csr[2] = (type() == AM7990) ? data : (data & 0x00ff); + if (m_csr[0] & CSR0_STOP) + m_csr[2] = (type() == AM7990) ? data : (data & 0x00ff); break; case 3: // Bus master interface - m_csr[3] = data & CSR3_MASK; + if (m_csr[0] & CSR0_STOP) + m_csr[3] = data & CSR3_MASK; break; } } @@ -588,10 +629,7 @@ void am7990_device_base::initialize() LOG("INITIALIZE initialization block address 0x%08x\n", init_addr); for (int i = 0; i < 12; i++) - { init_block[i] = m_dma_in_cb(init_addr + i * 2); - LOGMASKED(LOG_INIT, "IADR +%02d: 0x%04x\n", i * 2, init_block[i]); - } m_mode = init_block[0]; @@ -623,8 +661,6 @@ void am7990_device_base::initialize() m_csr[0] |= CSR0_IDON | CSR0_INIT; m_csr[0] &= ~CSR0_STOP; - - m_transmit_poll->enable(false); } void am7990_device_base::dma_in(u32 address, u8 *buf, int length) diff --git a/src/devices/machine/am79c90.h b/src/devices/machine/am79c90.h index ac2e17ee336..0597dbdb944 100644 --- a/src/devices/machine/am79c90.h +++ b/src/devices/machine/am79c90.h @@ -1,40 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/***************************************************************************** - - AMD Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE) - - TODO: - - Error handling - -****************************************************************************** - _____ _____ - Vss 1 |* \_/ | 48 Vdd - DAL7 2 | | 47 DAL8 - DAL6 3 | | 46 DAL9 - DAL5 4 | | 45 DAL10 - DAL4 5 | | 44 DAL11 - DAL3 6 | | 43 DAL12 - DAL2 7 | | 42 DAL13 - DAL1 8 | | 41 DAL14 - DAL0 9 | | 40 DAL15 - READ 10 | | 39 A16 - /INTR 11 | | 38 A17 - /DALI 12 | Am79C90 | 37 A18 - /DALI 13 | | 36 A19 - /DAS 14 | | 35 A20 - /BM0,BYTE 15 | | 34 A21 - /BM1,/BUSAKO 16 | | 33 A22 - /HOLD,/BUSRQ 17 | | 32 A23 - ALE,/AS 18 | | 31 RX - /HLDA 19 | | 30 RENA - /CS 20 | | 29 TX - ADR 21 | | 28 CLSN - /READY 22 | | 27 RCLK - /RESET 23 | | 26 TENA - Vss 24 |_____________| 25 TCLK - -**********************************************************************/ +// copyright-holders:Patrick Mackinlay #ifndef MAME_MACHINE_AM79C90_H #define MAME_MACHINE_AM79C90_H |