diff options
Diffstat (limited to 'src/devices/machine/i82586.cpp')
-rw-r--r-- | src/devices/machine/i82586.cpp | 124 |
1 files changed, 46 insertions, 78 deletions
diff --git a/src/devices/machine/i82586.cpp b/src/devices/machine/i82586.cpp index 641793ceb94..3ecd092f0c1 100644 --- a/src/devices/machine/i82586.cpp +++ b/src/devices/machine/i82586.cpp @@ -42,9 +42,6 @@ #include "logmacro.h" -// disable FCS insertion on transmit -#define I82586_FCS 0 - ALLOW_SAVE_TYPE(i82586_base_device::cu_state); ALLOW_SAVE_TYPE(i82586_base_device::ru_state); @@ -126,7 +123,6 @@ i82586_base_device::i82586_base_device(const machine_config &mconfig, device_typ , m_cu_state(CU_IDLE) , m_ru_state(RU_IDLE) , m_scp_address(SCP_ADDRESS) - , m_lb_length(0) { } @@ -169,8 +165,6 @@ void i82586_base_device::device_start() m_cu_timer = timer_alloc(CU_TIMER); m_cu_timer->enable(false); - m_ru_timer = timer_alloc(RU_TIMER); - m_ru_timer->enable(false); save_item(NAME(m_cx)); save_item(NAME(m_fr)); @@ -189,15 +183,11 @@ void i82586_base_device::device_start() save_item(NAME(m_rfd)); save_item(NAME(m_mac_multi)); - - save_item(NAME(m_lb_length)); - save_item(NAME(m_lb_buf)); } void i82586_base_device::device_reset() { m_cu_timer->enable(false); - m_ru_timer->enable(false); m_cx = false; m_fr = false; @@ -209,7 +199,6 @@ void i82586_base_device::device_reset() m_ru_state = RU_IDLE; m_scp_address = SCP_ADDRESS; - m_lb_length = 0; } void i82586_base_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) @@ -219,16 +208,6 @@ void i82586_base_device::device_timer(emu_timer &timer, device_timer_id id, int case CU_TIMER: cu_execute(); break; - - case RU_TIMER: - if (m_lb_length) - { - LOG("device_timer injecting loopback frame length %d\n", m_lb_length); - - recv_cb(m_lb_buf, m_lb_length); - } - m_lb_length = 0; - break; } } @@ -255,6 +234,10 @@ WRITE_LINE_MEMBER(i82586_base_device::ca) int i82586_base_device::recv_start_cb(u8 *buf, int length) { + // discard external packets in loopback mode + if (cfg_loopback_mode()) + return 0; + switch (m_ru_state) { case RU_IDLE: @@ -263,14 +246,7 @@ int i82586_base_device::recv_start_cb(u8 *buf, int length) break; case RU_READY: - if (address_filter(buf)) - { - LOG("recv_cb receiving frame length %d\n", length); - dump_bytes(buf, length); - - return ru_execute(buf, length); - } - break; + return recv_start(buf, length); default: // no resources @@ -281,6 +257,19 @@ int i82586_base_device::recv_start_cb(u8 *buf, int length) return 0; } +int i82586_base_device::recv_start(u8 *buf, int length) +{ + if (address_filter(buf)) + { + LOG("recv_start receiving frame length %d\n", length); + dump_bytes(buf, length); + + return ru_execute(buf, length); + } + + return 0; +} + void i82586_base_device::recv_complete_cb(int result) { ru_complete(result); @@ -977,9 +966,8 @@ bool i82586_device::cu_transmit(u32 command) length += fetch_bytes(&buf[length], tb_address, tbd_count & TB_COUNT); } -#if I82586_FCS // optionally compute/insert ethernet frame check sequence (4 bytes) - if (!cfg_no_crc_insertion()) + if (!cfg_no_crc_insertion() && !cfg_loopback_mode()) { LOG("cu_transmit inserting frame check sequence\n"); @@ -991,21 +979,16 @@ bool i82586_device::cu_transmit(u32 command) buf[length++] = (crc >> 16) & 0xff; buf[length++] = (crc >> 24) & 0xff; } -#endif - if (cfg_loopback_mode() != LOOPBACK_NONE) + if (cfg_loopback_mode()) { LOG("cu_transmit loopback frame length %d\n", length); - if (m_lb_length == 0) - { - memcpy(m_lb_buf, buf, length); - m_lb_length = length; + int status = recv_start(buf, length); + if (status) + ru_complete(status); - m_ru_timer->adjust(attotime::zero); - } - else - LOG("cu_tranmit error: loopback buffer not empty\n"); + cu_complete(CB_OK); return true; } @@ -1089,7 +1072,7 @@ u16 i82586_device::ru_execute(u8 *buf, int length) status |= RFD_S_SHORT; // set crc status - if (~compute_crc(buf, length, cfg_crc16()) != FCS_RESIDUE) + if (!cfg_loopback_mode() && ~compute_crc(buf, length, cfg_crc16()) != FCS_RESIDUE) { LOGMASKED(LOG_FRAMES, "ru_execute crc error computed 0x%08x stored 0x%08x\n", compute_crc(buf, length - 4, cfg_crc16()), *(u32 *)&buf[length - 4]); @@ -1656,9 +1639,8 @@ bool i82596_device::cu_transmit(u32 command) length += fetch_bytes(&buf[length], tb_address, tbd_count & TB_COUNT); } -#if I82586_FCS // optionally compute/insert ethernet frame check sequence (4 bytes) - if (!cfg_no_crc_insertion() && !(command & CB_NC)) + if (!cfg_no_crc_insertion() && !(command & CB_NC) && !cfg_loopback_mode()) { LOG("cu_transmit inserting frame check sequence\n"); @@ -1670,23 +1652,16 @@ bool i82596_device::cu_transmit(u32 command) buf[length++] = (crc >> 16) & 0xff; buf[length++] = (crc >> 24) & 0xff; } -#endif - if (cfg_loopback_mode() != LOOPBACK_NONE) + if (cfg_loopback_mode()) { LOG("cu_transmit loopback frame length %d\n", length); - if (m_lb_length == 0) - { - dump_bytes(buf, length); - - memcpy(m_lb_buf, buf, length); - m_lb_length = length; + int status = recv_start(buf, length); + if (status) + ru_complete(status); - m_ru_timer->adjust(attotime::zero); - } - else - LOG("cu_tranmit error: loopback buffer not empty\n"); + cu_complete(CB_OK); return true; } @@ -1795,25 +1770,17 @@ u16 i82596_device::ru_execute(u8 *buf, int length) // offset into rfd/rbd for linear mode int linear_offset = mode() == MODE_LINEAR ? 4 : 0; - if (!cfg_crc_in_memory()) - { - // compute and append fcs - u32 crc = compute_crc(buf, length, false); - - // append the fcs - buf[length++] = (crc >> 0) & 0xff; - buf[length++] = (crc >> 8) & 0xff; - buf[length++] = (crc >> 16) & 0xff; - buf[length++] = (crc >> 24) & 0xff; - } - // current buffer position and bytes remaining int position = 0, remaining = length; + if (cfg_crc_in_memory()) + remaining -= 4; + // set busy status m_space->write_dword(m_rfd, rfd_cs | RFD_B); - LOG("ru_execute receiving %d bytes using %s mode into rfd 0x%08x\n", length, (mode() == MODE_82586 ? "82586" : ((rfd_cs & RFD_SF) ? "flexible" : "simplified")), m_rfd); + LOG("ru_execute receiving %d bytes using %s mode into rfd 0x%08x\n", + remaining, (mode() == MODE_82586 ? "82586" : ((rfd_cs & RFD_SF) ? "flexible" : "simplified")), m_rfd); // TODO: check length if configured, status bit 12 @@ -1830,7 +1797,7 @@ u16 i82596_device::ru_execute(u8 *buf, int length) } // set crc status - if (~compute_crc(buf, length, cfg_crc16()) != FCS_RESIDUE) + if (!cfg_loopback_mode() && ~compute_crc(buf, length, cfg_crc16()) != FCS_RESIDUE) { LOGMASKED(LOG_FRAMES, "ru_execute crc error computed 0x%08x stored 0x%08x\n", compute_crc(buf, length - 4, cfg_crc16()), *(u32 *)&buf[length - 4]); @@ -1861,30 +1828,31 @@ u16 i82596_device::ru_execute(u8 *buf, int length) u16 rfd_size = m_space->read_word(m_rfd + 10 + linear_offset, RB_SIZE); // increment "no resources" counter - if (rfd_size < length) + if (rfd_size < remaining) m_space->write_dword(m_scb_address + 16 + linear_offset, m_space->read_dword(m_scb_address + 16 + linear_offset) + 1); // truncate/capture the frame - if (length <= rfd_size || cfg_save_bad_frames()) + if (remaining <= rfd_size || cfg_save_bad_frames()) { // compute stored length - int actual = (rfd_size < length) ? rfd_size : length; + int actual = (rfd_size < remaining) ? rfd_size : remaining; LOG("ru_execute storing %d bytes into rfd size %d\n", actual, rfd_size); // store data in rfd store_bytes(m_rfd + 12 + linear_offset, buf, actual); - position += actual; - remaining -= actual; // store actual count, f and eof m_space->write_word(m_rfd + 8 + linear_offset, actual | RB_F | RB_EOF); // set frame received and truncated frame status - status |= RFD_C | (actual < length ? RFD_S_TRUNCATED : 0); + status |= RFD_C | (actual < remaining ? RFD_S_TRUNCATED : 0); + + position += actual; + remaining -= actual; } else - LOG("ru_execute discarding %d byte frame exceeding rfd size %d\n", length, rfd_size); + LOG("ru_execute discarding %d byte frame exceeding rfd size %d\n", remaining, rfd_size); } else { @@ -1895,7 +1863,7 @@ u16 i82596_device::ru_execute(u8 *buf, int length) u16 rfd_size = m_space->read_word(m_rfd + 10 + linear_offset, RB_SIZE); // compute stored length (from rfd_size) - int actual = (rfd_size < length) ? rfd_size : length; + int actual = (rfd_size < remaining) ? rfd_size : remaining; LOG("ru_execute storing %d bytes into rfd size %d\n", actual, rfd_size); |