i82586: various fixes

* send fcs in loopback mode
* don't store fcs in memory
* don't consume descriptors for bad frames
This commit is contained in:
Patrick Mackinlay 2021-06-01 19:27:34 +07:00
parent ccf73700ae
commit 743dfcf9bd

View File

@ -96,7 +96,7 @@ CFG_PARAMS[] =
{ "number of retries", "maximum number of retries", 15, 7, 0xf0, 4, true },
{ "no crc insertion", "crc appended to frame", 0, 8, 0x10, 4, false },
{ "prefetch bit in rbd", "disabled (valid only in new modes)", 0, 0, 0x80, 7, false },
{ "preamble length", "bytes", 7, 3, 0x30, 4, true },
{ "preamble length", "2^(n+1) bytes", 2, 3, 0x30, 4, true },
{ "preamble until crs", "disabled", 1, 11, 0x01, 0, false },
{ "promiscuous mode", "address filter on", 0, 8, 0x01, 0, false },
{ "padding", "no padding", 0, 8, 0x80, 7, false },
@ -201,6 +201,7 @@ void i82586_base_device::device_reset()
m_ru_state = RU_IDLE;
m_scp_address = SCP_ADDRESS;
m_mac_multi = 0;
}
void i82586_base_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
@ -1000,7 +1001,7 @@ bool i82586_device::cu_transmit(u32 command)
}
// optionally compute/insert ethernet frame check sequence (4 bytes)
if (!cfg_no_crc_insertion() && !cfg_loopback_mode())
if (!cfg_no_crc_insertion())
{
LOG("cu_transmit inserting frame check sequence\n");
@ -1092,8 +1093,8 @@ u16 i82586_device::ru_execute(u8 *buf, int length)
u32 rfd_cs = m_space->read_dword(m_rfd);
u16 status = 0;
// current buffer position and bytes remaining
int position = 0, remaining = length;
// current buffer position and bytes remaining (excluding fcs)
int position = 0, remaining = length - 4;
// set busy status
m_space->write_dword(m_rfd, rfd_cs | RFD_B);
@ -1105,7 +1106,7 @@ u16 i82586_device::ru_execute(u8 *buf, int length)
status |= RFD_S_SHORT;
// set crc status
if (!cfg_loopback_mode() && ~compute_crc(buf, length, cfg_crc16()) != FCS_RESIDUE)
if (~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]);
@ -1187,18 +1188,18 @@ u16 i82586_device::ru_execute(u8 *buf, int length)
void i82586_device::ru_complete(const u16 status)
{
if (status & RFD_OK)
LOG("ru_complete frame received without error\n");
else
LOG("ru_complete frame received with errors status 0x%04x\n", status);
// update receive frame descriptor status
u32 rfd_cs = m_space->read_dword(m_rfd);
m_space->write_dword(m_rfd, (rfd_cs & ~0xffffU) | status);
// if we received without error, or we're saving bad frames, advance to the next rfd
if ((status & RFD_OK) || cfg_save_bad_frames())
{
if (status & RFD_OK)
LOG("ru_complete frame received without error\n");
else
LOG("ru_complete frame received with errors status 0x%04x\n", status);
// update receive frame descriptor status
u32 rfd_cs = m_space->read_dword(m_rfd);
m_space->write_dword(m_rfd, (rfd_cs & ~0xffffU) | status);
if (!(rfd_cs & RFD_EL))
{
// advance to next rfd
@ -1216,17 +1217,19 @@ void i82586_device::ru_complete(const u16 status)
// set frame received status
m_fr = true;
}
// suspend on completion
if (rfd_cs & RFD_S)
{
m_ru_state = RU_SUSPENDED;
m_rnr = true;
}
// suspend on completion
if (rfd_cs & RFD_S)
{
m_ru_state = RU_SUSPENDED;
m_rnr = true;
}
static const char *const RU_STATE_NAME[] = { "IDLE", "SUSPENDED", "NO RESOURCES", nullptr, "READY" };
LOG("ru_complete complete state %s\n", RU_STATE_NAME[m_ru_state]);
static const char *const RU_STATE_NAME[] = { "IDLE", "SUSPENDED", "NO RESOURCES", nullptr, "READY" };
LOG("ru_complete complete state %s\n", RU_STATE_NAME[m_ru_state]);
}
else
LOG("ru_complete discarded frame with errors status 0x%04x\n", status);
}
u32 i82586_device::address(u32 base, int offset, int address, u16 empty)
@ -1827,7 +1830,7 @@ u16 i82596_device::ru_execute(u8 *buf, int length)
}
// set crc status
if (!cfg_loopback_mode() && ~compute_crc(buf, length, cfg_crc16()) != FCS_RESIDUE)
if (~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]);
@ -1970,18 +1973,18 @@ u16 i82596_device::ru_execute(u8 *buf, int length)
void i82596_device::ru_complete(const u16 status)
{
if (status & RFD_OK)
LOG("ru_complete frame received without error\n");
else
LOG("ru_complete frame received with errors status 0x%04x\n", status);
// store status
const u32 rfd_cs = m_space->read_dword(m_rfd);
m_space->write_dword(m_rfd, (rfd_cs & ~0xffffU) | status);
// if we received without error, or we're saving bad frames, advance to the next rfd
if ((rfd_cs & RFD_OK) || cfg_save_bad_frames())
if ((status & RFD_OK) || cfg_save_bad_frames())
{
if (status & RFD_OK)
LOG("ru_complete frame received without error\n");
else
LOG("ru_complete frame received with errors status 0x%04x\n", status);
// update receive frame descriptor status
const u32 rfd_cs = m_space->read_dword(m_rfd);
m_space->write_dword(m_rfd, (rfd_cs & ~0xffffU) | status);
if (!(rfd_cs & RFD_EL))
{
// advance to next rfd
@ -2004,17 +2007,19 @@ void i82596_device::ru_complete(const u16 status)
// set frame received status
m_fr = true;
}
// suspend on completion
if (rfd_cs & RFD_S)
{
m_ru_state = RU_SUSPENDED;
m_rnr = true;
}
// suspend on completion
if (rfd_cs & RFD_S)
{
m_ru_state = RU_SUSPENDED;
m_rnr = true;
}
static const char *const RU_STATE_NAME[] = { "IDLE", "SUSPENDED", "NO RESOURCES", nullptr, "READY", nullptr, nullptr, nullptr, nullptr, nullptr, "NO RESOURCES (RFD)", nullptr, "NO RESOURCES (RBD)" };
LOG("ru_complete complete state %s\n", RU_STATE_NAME[m_ru_state]);
static const char *const RU_STATE_NAME[] = { "IDLE", "SUSPENDED", "NO RESOURCES", nullptr, "READY", nullptr, nullptr, nullptr, nullptr, nullptr, "NO RESOURCES (RFD)", nullptr, "NO RESOURCES (RBD)" };
LOG("ru_complete complete state %s\n", RU_STATE_NAME[m_ru_state]);
}
else
LOG("ru_complete discarded frame with errors status 0x%04x\n", status);
}
u32 i82596_device::address(u32 base, int offset, int address, u16 empty)