mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
edlc: add 80c03 support (nw)
This commit is contained in:
parent
6f3f0b805e
commit
bed1c30c1c
@ -18,8 +18,7 @@
|
||||
*
|
||||
* TODO:
|
||||
* - RxDC (discard) and TxRET (retransmit) logic
|
||||
* - 80c03 support
|
||||
* - testing
|
||||
* - 80c03 inter-packet gap (undocumented)
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -33,12 +32,13 @@
|
||||
//#define VERBOSE (LOG_GENERAL|LOG_FRAMES|LOG_FILTER)
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SEEQ8003, seeq8003_device, "seeq8003", "SEEQ 8003 EDLC")
|
||||
DEFINE_DEVICE_TYPE(SEEQ8003, seeq8003_device, "seeq8003", "SEEQ 8003 EDLC")
|
||||
DEFINE_DEVICE_TYPE(SEEQ80C03, seeq80c03_device, "seeq80c03", "SEEQ 80C03 EDLC")
|
||||
|
||||
static const u8 ETH_BROADCAST[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
seeq8003_device::seeq8003_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SEEQ8003, tag, owner, clock)
|
||||
seeq8003_device::seeq8003_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, device_network_interface(mconfig, *this, 10.0f)
|
||||
, m_out_int(*this)
|
||||
, m_out_rxrdy(*this)
|
||||
@ -46,6 +46,11 @@ seeq8003_device::seeq8003_device(machine_config const &mconfig, char const *tag,
|
||||
{
|
||||
}
|
||||
|
||||
seeq8003_device::seeq8003_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: seeq8003_device(mconfig, SEEQ8003, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
void seeq8003_device::device_start()
|
||||
{
|
||||
m_out_int.resolve_safe();
|
||||
@ -107,14 +112,7 @@ int seeq8003_device::recv_start_cb(u8 *buf, int length)
|
||||
|
||||
void seeq8003_device::map(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
|
||||
map(0, 0).w(FUNC(seeq8003_device::station_address_w<0>));
|
||||
map(1, 1).w(FUNC(seeq8003_device::station_address_w<1>));
|
||||
map(2, 2).w(FUNC(seeq8003_device::station_address_w<2>));
|
||||
map(3, 3).w(FUNC(seeq8003_device::station_address_w<3>));
|
||||
map(4, 4).w(FUNC(seeq8003_device::station_address_w<4>));
|
||||
map(5, 5).w(FUNC(seeq8003_device::station_address_w<5>));
|
||||
map(0, 5).rw(FUNC(seeq8003_device::unused_r), FUNC(seeq8003_device::station_address_w));
|
||||
map(6, 6).rw(FUNC(seeq8003_device::rx_status_r), FUNC(seeq8003_device::rx_command_w));
|
||||
map(7, 7).rw(FUNC(seeq8003_device::tx_status_r), FUNC(seeq8003_device::tx_command_w));
|
||||
}
|
||||
@ -136,12 +134,10 @@ void seeq8003_device::write(offs_t offset, u8 data)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: station_address_w<0>(data); break;
|
||||
case 1: station_address_w<1>(data); break;
|
||||
case 2: station_address_w<2>(data); break;
|
||||
case 3: station_address_w<3>(data); break;
|
||||
case 4: station_address_w<4>(data); break;
|
||||
case 5: station_address_w<5>(data); break;
|
||||
case 0: case 1: case 2:
|
||||
case 3: case 4: case 5:
|
||||
station_address_w(offset, data);
|
||||
break;
|
||||
case 6: rx_command_w(data); break;
|
||||
case 7: tx_command_w(data); break;
|
||||
}
|
||||
@ -189,7 +185,9 @@ u8 seeq8003_device::fifo_r()
|
||||
|
||||
int seeq8003_device::rxeof_r()
|
||||
{
|
||||
return m_rx_fifo.queue_length() == 1;
|
||||
// HACK: should be asserted while the last byte is being read from the fifo
|
||||
// but doing it when the fifo is empty makes emulation simpler
|
||||
return m_rx_fifo.empty();
|
||||
}
|
||||
|
||||
void seeq8003_device::fifo_w(u8 data)
|
||||
@ -246,6 +244,20 @@ u8 seeq8003_device::tx_status_r()
|
||||
return data;
|
||||
}
|
||||
|
||||
void seeq8003_device::rx_command_w(u8 data)
|
||||
{
|
||||
LOG("rx_command_w 0x%02x (%s)\n", data, machine().describe_context());
|
||||
|
||||
m_rx_command = data;
|
||||
}
|
||||
|
||||
void seeq8003_device::tx_command_w(u8 data)
|
||||
{
|
||||
LOG("tx_command_w 0x%02x (%s)\n", data, machine().describe_context());
|
||||
|
||||
m_tx_command = data;
|
||||
}
|
||||
|
||||
void seeq8003_device::transmit(void *ptr, int param)
|
||||
{
|
||||
if (m_tx_fifo.queue_length())
|
||||
@ -257,12 +269,20 @@ void seeq8003_device::transmit(void *ptr, int param)
|
||||
while (!m_tx_fifo.empty())
|
||||
buf[length++] = m_tx_fifo.dequeue();
|
||||
|
||||
// transmit packet autopad
|
||||
if (mode_tx_pad() && (length < 60))
|
||||
while (length < 60)
|
||||
buf[length++] = 0;
|
||||
|
||||
// compute and append fcs
|
||||
u32 const fcs = util::crc32_creator::simple(buf, length);
|
||||
buf[length++] = (fcs >> 0) & 0xff;
|
||||
buf[length++] = (fcs >> 8) & 0xff;
|
||||
buf[length++] = (fcs >> 16) & 0xff;
|
||||
buf[length++] = (fcs >> 24) & 0xff;
|
||||
if (mode_tx_crc())
|
||||
{
|
||||
u32 const fcs = util::crc32_creator::simple(buf, length);
|
||||
buf[length++] = (fcs >> 0) & 0xff;
|
||||
buf[length++] = (fcs >> 8) & 0xff;
|
||||
buf[length++] = (fcs >> 16) & 0xff;
|
||||
buf[length++] = (fcs >> 24) & 0xff;
|
||||
}
|
||||
|
||||
LOG("transmitting frame length %d\n", length);
|
||||
dump_bytes(buf, length);
|
||||
@ -303,7 +323,8 @@ int seeq8003_device::receive(u8 *buf, int length)
|
||||
m_rx_status |= RXS_G;
|
||||
|
||||
// enqueue from buffer
|
||||
for (unsigned i = 0; i < length - 4; i++)
|
||||
unsigned const fcs_bytes = mode_rx_crc() ? 0 : 4;
|
||||
for (unsigned i = 0; i < length - fcs_bytes; i++)
|
||||
m_rx_fifo.enqueue(buf[i]);
|
||||
|
||||
// enable rx fifo
|
||||
@ -334,15 +355,7 @@ bool seeq8003_device::address_filter(u8 *address)
|
||||
|
||||
if ((m_rx_command & RXC_M) == RXC_M1)
|
||||
{
|
||||
LOG("address_filter accepted: promiscuous mode enabled\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ethernet broadcast
|
||||
if (!memcmp(address, ETH_BROADCAST, 6))
|
||||
{
|
||||
LOGMASKED(LOG_FILTER, "address_filter accepted: broadcast\n");
|
||||
LOGMASKED(LOG_FILTER, "address_filter accepted: promiscuous mode enabled\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -355,6 +368,14 @@ bool seeq8003_device::address_filter(u8 *address)
|
||||
return true;
|
||||
}
|
||||
|
||||
// ethernet broadcast
|
||||
if (!memcmp(address, ETH_BROADCAST, 6))
|
||||
{
|
||||
LOGMASKED(LOG_FILTER, "address_filter accepted: broadcast\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ethernet multicast
|
||||
if (((m_rx_command & RXC_M) == RXC_M3) && (address[0] & 0x1))
|
||||
{
|
||||
@ -366,6 +387,244 @@ bool seeq8003_device::address_filter(u8 *address)
|
||||
return false;
|
||||
}
|
||||
|
||||
seeq80c03_device::seeq80c03_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: seeq8003_device(mconfig, SEEQ80C03, tag, owner, clock)
|
||||
, m_regbank(*this, "regbank")
|
||||
{
|
||||
}
|
||||
|
||||
void seeq80c03_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
ADDRESS_MAP_BANK(config, m_regbank).set_map(&seeq80c03_device::map_reg).set_options(ENDIANNESS_NATIVE, 8, 5, 8);
|
||||
}
|
||||
|
||||
void seeq80c03_device::device_start()
|
||||
{
|
||||
seeq8003_device::device_start();
|
||||
|
||||
save_item(NAME(m_tx_cc));
|
||||
save_item(NAME(m_cc));
|
||||
save_item(NAME(m_flags));
|
||||
save_item(NAME(m_control));
|
||||
save_item(NAME(m_config));
|
||||
save_item(NAME(m_multicast_filter));
|
||||
}
|
||||
|
||||
void seeq80c03_device::device_reset()
|
||||
{
|
||||
seeq8003_device::device_reset();
|
||||
|
||||
m_tx_cc = 0;
|
||||
m_cc = 0;
|
||||
m_flags = 0;
|
||||
m_control = 0;
|
||||
m_config = 0;
|
||||
m_multicast_filter = 0;
|
||||
}
|
||||
|
||||
void seeq80c03_device::send_complete_cb(int result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
if (m_control & CTL_SQE)
|
||||
m_flags |= FLAGS_SQE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume transmit failure and no device means loss of carrier
|
||||
if ((m_control & CTL_TNC) && !m_dev)
|
||||
m_flags |= FLAGS_TNC;
|
||||
}
|
||||
}
|
||||
|
||||
void seeq80c03_device::map(address_map &map)
|
||||
{
|
||||
map(0, 7).m(m_regbank, FUNC(address_map_bank_device::amap8));
|
||||
}
|
||||
|
||||
void seeq80c03_device::map_reg(address_map &map)
|
||||
{
|
||||
map(0x00, 0x05).w(FUNC(seeq80c03_device::station_address_w));
|
||||
|
||||
map(0x08, 0x11).w(FUNC(seeq80c03_device::multicast_filter_w));
|
||||
map(0x12, 0x12).nopw(); // TODO: inter-packet gap
|
||||
map(0x13, 0x13).w(FUNC(seeq80c03_device::control_w));
|
||||
map(0x14, 0x14).w(FUNC(seeq80c03_device::config_w));
|
||||
|
||||
map(0x00, 0x00).r(FUNC(seeq80c03_device::tx_ccl_r)).mirror(0x18);
|
||||
map(0x01, 0x01).r(FUNC(seeq80c03_device::tx_cch_r)).mirror(0x18);
|
||||
map(0x02, 0x02).r(FUNC(seeq80c03_device::ccl_r)).mirror(0x18);
|
||||
map(0x03, 0x03).r(FUNC(seeq80c03_device::cch_r)).mirror(0x18);
|
||||
map(0x04, 0x04).r(FUNC(seeq80c03_device::test_r)).mirror(0x18);
|
||||
map(0x05, 0x05).r(FUNC(seeq80c03_device::flags_r)).mirror(0x18);
|
||||
|
||||
map(0x06, 0x06).rw(FUNC(seeq80c03_device::rx_status_r), FUNC(seeq80c03_device::rx_command_w)).mirror(0x18);
|
||||
map(0x07, 0x07).rw(FUNC(seeq80c03_device::tx_status_r), FUNC(seeq80c03_device::tx_command_w)).mirror(0x18);
|
||||
}
|
||||
|
||||
u8 seeq80c03_device::read(offs_t offset)
|
||||
{
|
||||
u8 data = 0xff;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0: data = tx_ccl_r(); break;
|
||||
case 1: data = tx_cch_r(); break;
|
||||
case 2: data = ccl_r(); break;
|
||||
case 3: data = cch_r(); break;
|
||||
case 4: data = test_r(); break;
|
||||
case 5: data = flags_r(); break;
|
||||
case 6: data = rx_status_r(); break;
|
||||
case 7: data = tx_status_r(); break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void seeq80c03_device::write(offs_t offset, u8 data)
|
||||
{
|
||||
switch (m_tx_command & TXC_B)
|
||||
{
|
||||
case 0x00:
|
||||
switch (offset)
|
||||
{
|
||||
case 0: case 1: case 2:
|
||||
case 3: case 4: case 5:
|
||||
station_address_w(offset, data);
|
||||
break;
|
||||
case 6: rx_command_w(data); break;
|
||||
case 7: tx_command_w(data); break;
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
switch (offset)
|
||||
{
|
||||
case 0: case 1: case 2:
|
||||
case 3: case 4: case 5:
|
||||
multicast_filter_w(offset, data);
|
||||
break;
|
||||
case 6: rx_command_w(data); break;
|
||||
case 7: tx_command_w(data); break;
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
switch (offset)
|
||||
{
|
||||
case 0: case 1:
|
||||
multicast_filter_w(offset + 8, data);
|
||||
break;
|
||||
case 2: break; // TODO: inter-packet gap
|
||||
case 3: control_w(data); break;
|
||||
case 4: config_w(data); break;
|
||||
case 6: rx_command_w(data); break;
|
||||
case 7: tx_command_w(data); break;
|
||||
}
|
||||
break;
|
||||
case 0x60:
|
||||
switch (offset)
|
||||
{
|
||||
case 6: rx_command_w(data); break;
|
||||
case 7: tx_command_w(data); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void seeq80c03_device::multicast_filter_w(offs_t offset, u8 data)
|
||||
{
|
||||
unsigned const shift = (offset < 6) ? (offset * 8) : ((offset - 2) * 8);
|
||||
|
||||
m_multicast_filter &= ~(u64(0xff) << shift);
|
||||
m_multicast_filter |= u64(data) << shift;
|
||||
}
|
||||
|
||||
void seeq80c03_device::tx_command_w(u8 data)
|
||||
{
|
||||
seeq8003_device::tx_command_w(data);
|
||||
|
||||
m_regbank->set_bank((data >> 5) & 3);
|
||||
}
|
||||
|
||||
void seeq80c03_device::control_w(u8 data)
|
||||
{
|
||||
LOG("control_w 0x%02x (%s)\n", data, machine().describe_context());
|
||||
|
||||
if ((m_control & CTL_TCC) && !(data & CTL_TCC))
|
||||
m_tx_cc = 0;
|
||||
if ((m_control & CTL_CC) && !(data & CTL_CC))
|
||||
m_cc = 0;
|
||||
if ((m_control & CTL_SQE) && !(data & CTL_SQE))
|
||||
m_flags &= ~FLAGS_SQE;
|
||||
if ((m_control & CTL_TNC) && !(data & CTL_TNC))
|
||||
m_flags &= ~FLAGS_TNC;
|
||||
|
||||
m_control = data;
|
||||
}
|
||||
|
||||
void seeq80c03_device::config_w(u8 data)
|
||||
{
|
||||
LOG("config_w 0x%02x (%s)\n", data, machine().describe_context());
|
||||
|
||||
m_config = data;
|
||||
}
|
||||
|
||||
bool seeq80c03_device::address_filter(u8 *address)
|
||||
{
|
||||
LOGMASKED(LOG_FILTER, "address_filter testing destination address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
address[0], address[1], address[2], address[3], address[4], address[5]);
|
||||
|
||||
if ((m_rx_command & RXC_M) == RXC_M1)
|
||||
{
|
||||
LOGMASKED(LOG_FILTER, "address_filter accepted: promiscuous mode enabled\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// station address
|
||||
if (m_config & CFG_GAM)
|
||||
{
|
||||
if (!memcmp(address, m_station_address, 5) && !(((address[5] ^ m_station_address[5]) & 0xf0)))
|
||||
{
|
||||
LOGMASKED(LOG_FILTER, "address_filter accepted: station address match\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (!memcmp(address, m_station_address, 6))
|
||||
{
|
||||
LOGMASKED(LOG_FILTER, "address_filter accepted: station address match\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ethernet broadcast
|
||||
if (!memcmp(address, ETH_BROADCAST, 6))
|
||||
{
|
||||
LOGMASKED(LOG_FILTER, "address_filter accepted: broadcast\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ethernet multicast
|
||||
if (((m_rx_command & RXC_M) == RXC_M3) && (address[0] & 0x1))
|
||||
{
|
||||
// multicast hash filter
|
||||
if (m_control & CTL_MHF)
|
||||
{
|
||||
u32 const crc = util::crc32_creator::simple(address, 6);
|
||||
|
||||
if (!BIT(m_multicast_filter, crc & 63))
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGMASKED(LOG_FILTER, "address_filter accepted: multicast address match\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void seeq8003_device::dump_bytes(u8 *buf, int length)
|
||||
{
|
||||
if (VERBOSE & LOG_FRAMES)
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/bankdev.h"
|
||||
|
||||
class seeq8003_device :
|
||||
public device_t,
|
||||
public device_network_interface
|
||||
@ -18,19 +20,23 @@ public:
|
||||
|
||||
seeq8003_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
|
||||
|
||||
// command/status interface
|
||||
void map(address_map &map);
|
||||
u8 read(offs_t offset);
|
||||
void write(offs_t offset, u8 data);
|
||||
void reset_w(int state);
|
||||
// register interface
|
||||
virtual void map(address_map &map);
|
||||
virtual u8 read(offs_t offset);
|
||||
virtual void write(offs_t offset, u8 data);
|
||||
|
||||
// data interface
|
||||
u8 fifo_r();
|
||||
// input and output lines
|
||||
int rxeof_r();
|
||||
void fifo_w(u8 data);
|
||||
void reset_w(int state);
|
||||
void txeof_w(int state);
|
||||
|
||||
// fifo interface
|
||||
u8 fifo_r();
|
||||
void fifo_w(u8 data);
|
||||
|
||||
protected:
|
||||
seeq8003_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock = 0);
|
||||
|
||||
// device_t overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
@ -38,20 +44,28 @@ protected:
|
||||
// device_network_interface overrides
|
||||
virtual int recv_start_cb(u8 *buf, int length) override;
|
||||
|
||||
// command/status registers
|
||||
template <unsigned N> void station_address_w(u8 data) { m_station_address[N] = data; }
|
||||
// register read handlers
|
||||
u8 unused_r() { return 0xff; }
|
||||
u8 rx_status_r();
|
||||
u8 tx_status_r();
|
||||
void rx_command_w(u8 data) { m_rx_command = data; }
|
||||
void tx_command_w(u8 data) { m_tx_command = data & TXC_M; }
|
||||
|
||||
// register write handlers
|
||||
void station_address_w(offs_t offset, u8 data) { m_station_address[offset] = data; }
|
||||
void rx_command_w(u8 data);
|
||||
virtual void tx_command_w(u8 data);
|
||||
|
||||
// helpers
|
||||
void transmit(void *ptr, int param);
|
||||
int receive(u8 *buf, int length);
|
||||
void interrupt(void *ptr = nullptr, int param = 0);
|
||||
bool address_filter(u8 *address);
|
||||
virtual bool address_filter(u8 *address);
|
||||
void dump_bytes(u8 *buf, int length);
|
||||
|
||||
// 80c03 option helpers
|
||||
virtual bool mode_tx_pad() const { return false; }
|
||||
virtual bool mode_tx_crc() const { return true; }
|
||||
virtual bool mode_rx_crc() const { return false; }
|
||||
|
||||
// constants and masks
|
||||
static const unsigned MAX_FRAME_SIZE = 1518;
|
||||
static const u32 FCS_RESIDUE = 0xdebb20e3;
|
||||
@ -102,10 +116,9 @@ protected:
|
||||
TXC_R = 0x04, // interrupt on 16 transmission attempts
|
||||
TXC_S = 0x08, // interrupt on transmit success
|
||||
|
||||
TXC_M = 0x0f, // write mask
|
||||
TXC_B = 0x60, // register bank select (80c03 only)
|
||||
};
|
||||
|
||||
private:
|
||||
emu_timer *m_tx_timer;
|
||||
emu_timer *m_int_timer;
|
||||
|
||||
@ -126,6 +139,88 @@ private:
|
||||
util::fifo<u8, MAX_FRAME_SIZE> m_tx_fifo;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SEEQ8003, seeq8003_device)
|
||||
class seeq80c03_device : public seeq8003_device
|
||||
{
|
||||
public:
|
||||
seeq80c03_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
|
||||
|
||||
// register interface
|
||||
virtual void map(address_map &map) override;
|
||||
virtual u8 read(offs_t offset) override;
|
||||
virtual void write(offs_t offset, u8 data) override;
|
||||
|
||||
protected:
|
||||
// device_t overrides
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_network_interface overrides
|
||||
virtual void send_complete_cb(int result) override;
|
||||
|
||||
// banked register map
|
||||
void map_reg(address_map &map);
|
||||
|
||||
// register read handlers
|
||||
u8 tx_ccl_r() { return u8(m_tx_cc >> 0); }
|
||||
u8 tx_cch_r() { return u8(m_tx_cc >> 8); }
|
||||
u8 ccl_r() { return u8(m_cc >> 0); }
|
||||
u8 cch_r() { return u8(m_cc >> 8); }
|
||||
u8 test_r() { return 0; }
|
||||
u8 flags_r() { return m_flags; }
|
||||
|
||||
// register write handlers
|
||||
void multicast_filter_w(offs_t offset, u8 data);
|
||||
virtual void tx_command_w(u8 data) override;
|
||||
void control_w(u8 data);
|
||||
void config_w(u8 data);
|
||||
|
||||
// helpers
|
||||
virtual bool address_filter(u8 *address) override;
|
||||
|
||||
// 80c03 option helpers
|
||||
virtual bool mode_tx_pad() const override { return bool(m_config & CFG_TPA); }
|
||||
virtual bool mode_tx_crc() const override { return !bool(m_config & CFG_TNC); }
|
||||
virtual bool mode_rx_crc() const override { return bool(m_config & CFG_RXC); }
|
||||
|
||||
required_device<address_map_bank_device> m_regbank;
|
||||
|
||||
enum flags_mask : u8
|
||||
{
|
||||
FLAGS_SQE = 0x01,
|
||||
FLAGS_TNC = 0x02, // txen_no_carrier
|
||||
};
|
||||
enum control_mask : u8
|
||||
{
|
||||
CTL_TCC = 0x01, // transmit collision counter
|
||||
CTL_CC = 0x02, // collision counter
|
||||
CTL_SQE = 0x04, // sqe function
|
||||
CTL_MHF = 0x08, // multicast hash filter
|
||||
CTL_DRF = 0x10, // discard short frames
|
||||
CTL_TNC = 0x20, // txen_no_carrier function
|
||||
};
|
||||
enum config_mask : u8
|
||||
{
|
||||
CFG_GAM = 0x01, // group address
|
||||
CFG_TPA = 0x02, // transmit packet autopad
|
||||
CFG_TNP = 0x04, // transmit no preamble
|
||||
CFG_RTD = 0x08, // receive own transmit disable
|
||||
CFG_TNC = 0x10, // transmit no crc
|
||||
CFG_FDX = 0x20, // full duplex
|
||||
CFG_RXC = 0x40, // receive crc
|
||||
CFG_FRD = 0x80, // fast receive discard
|
||||
};
|
||||
u16 m_tx_cc;
|
||||
u16 m_cc;
|
||||
u8 m_flags;
|
||||
|
||||
u8 m_control;
|
||||
u8 m_config;
|
||||
|
||||
u64 m_multicast_filter;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SEEQ8003, seeq8003_device)
|
||||
DECLARE_DEVICE_TYPE(SEEQ80C03, seeq80c03_device)
|
||||
|
||||
#endif // MAME_MACHINE_EDLC_H
|
||||
|
Loading…
Reference in New Issue
Block a user