From ac01e295c00e6a9631c22b4432484105ef7f706c Mon Sep 17 00:00:00 2001 From: Ted Green Date: Tue, 8 Jan 2019 12:39:03 -0700 Subject: [PATCH] smc91c9x: Added initial MAC filter and fixed multicast address filtering. WIP. (nw) --- src/devices/machine/smc91c9x.cpp | 21 ++++++++++++++++++--- src/devices/machine/smc91c9x.h | 13 +++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/devices/machine/smc91c9x.cpp b/src/devices/machine/smc91c9x.cpp index d3ac80003df..21fcb11d1f7 100644 --- a/src/devices/machine/smc91c9x.cpp +++ b/src/devices/machine/smc91c9x.cpp @@ -71,6 +71,7 @@ smc91c9x_device::smc91c9x_device(const machine_config &mconfig, device_type type } const u8 smc91c9x_device::ETH_BROADCAST[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +const u8 smc91c9x_device::WMS_OUI[] = { 0x00, 0xA0, 0xAF }; //------------------------------------------------- // device_start - device-specific startup @@ -338,15 +339,21 @@ int smc91c9x_device::address_filter(u8 *buf) return ADDR_MULTICAST; u32 const crc = util::crc32_creator::simple(buf, 6); - m_rx_hash = (crc >> 26); + // The hash is based on the top 6 MSBs of the CRC + // The CRC needs to be inverted and reflected + m_rx_hash = 0x0; + for (int i = 0; i < 6; i++) + m_rx_hash |= (((~crc) >> i) & 1) << (5 - i); u64 multicast_addr = *(u64*)&m_reg[B3_MT0_1]; - if (BIT(multicast_addr, 63 - m_rx_hash)) + if (BIT(multicast_addr, m_rx_hash)) { - LOGMASKED(LOG_FILTER, "address_filter accepted (logical address match) %02x-%02x-%02x-%02x-%02x-%02x\n", + LOGMASKED(LOG_FILTER, "address_filter accepted (multicast address match) %02x-%02x-%02x-%02x-%02x-%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); return ADDR_MULTICAST; } + LOGMASKED(LOG_FILTER, "address_filter rejected multicast %02x-%02x-%02x-%02x-%02x-%02x crc: %08x hash: %02x multi: %16ullx\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], crc, m_rx_hash, *(u64*)&m_reg[B3_MT0_1]); } else { @@ -385,6 +392,14 @@ int smc91c9x_device::recv_start_cb(u8 *buf, int length) return 0; } + // discard packets not from WMS + if (memcmp(WMS_OUI, &buf[6], 3)) + { + LOGMASKED(LOG_RX, "received non-WMS packet OUI: %02x:%02x:%02x length %d discarded\n", buf[6], buf[7], buf[8], length); + + return 0; + } + // Check for active transmission if (m_tx_active) { diff --git a/src/devices/machine/smc91c9x.h b/src/devices/machine/smc91c9x.h index c05f06d1a5e..51b520fe971 100644 --- a/src/devices/machine/smc91c9x.h +++ b/src/devices/machine/smc91c9x.h @@ -217,6 +217,7 @@ private: static constexpr unsigned ETHER_BUFFER_SIZE = 256 * 6; static const u8 ETH_BROADCAST[]; + static const u8 WMS_OUI[]; // mmu @@ -275,8 +276,8 @@ private: void reset_queued_tx() { m_queued_tx_t = m_queued_tx_h = 0; }; void push_queued_tx(const u8 &data) { m_queued_tx[m_queued_tx_h++] = data; m_queued_tx_h &= FIFO_SIZE - 1; }; u8 pop_queued_tx() { u8 val = m_queued_tx[m_queued_tx_t++]; m_queued_tx_t &= FIFO_SIZE - 1; return val; }; - bool empty_queued_tx() { return m_queued_tx_h == m_queued_tx_t; }; - u8 curr_queued_tx() { return m_queued_tx[m_queued_tx_t]; }; + bool empty_queued_tx() const { return m_queued_tx_h == m_queued_tx_t; }; + u8 curr_queued_tx() const { return m_queued_tx[m_queued_tx_t]; }; // FIFO for completed transmit packets u8 m_completed_tx[FIFO_SIZE]; @@ -284,8 +285,8 @@ private: void reset_completed_tx() { m_completed_tx_t = m_completed_tx_h = 0; }; void push_completed_tx(const u8 &data) { m_completed_tx[m_completed_tx_h++] = data; m_completed_tx_h &= FIFO_SIZE - 1; }; u8 pop_completed_tx() { u8 val = m_completed_tx[m_completed_tx_t++]; m_completed_tx_t &= FIFO_SIZE - 1; return val; }; - bool empty_completed_tx() { return m_completed_tx_h == m_completed_tx_t; }; - u8 curr_completed_tx() { return m_completed_tx[m_completed_tx_t]; }; + bool empty_completed_tx() const { return m_completed_tx_h == m_completed_tx_t; }; + u8 curr_completed_tx() const { return m_completed_tx[m_completed_tx_t]; }; // FIFO for completed receive packets u8 m_completed_rx[FIFO_SIZE]; @@ -293,8 +294,8 @@ private: void reset_completed_rx() { m_completed_rx_t = m_completed_rx_h = 0; }; void push_completed_rx(const u8 &data) { m_completed_rx[m_completed_rx_h++] = data; m_completed_rx_h &= FIFO_SIZE - 1; }; u8 pop_completed_rx() { u8 val = m_completed_rx[m_completed_rx_t++]; m_completed_rx_t &= FIFO_SIZE - 1; return val; }; - bool empty_completed_rx() { return m_completed_rx_h == m_completed_rx_t; }; - u8 curr_completed_rx() { return m_completed_rx[m_completed_rx_t]; }; + bool empty_completed_rx() const { return m_completed_rx_h == m_completed_rx_t; }; + u8 curr_completed_rx() const { return m_completed_rx[m_completed_rx_t]; }; };