mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
i82586: functional, ~90% complete (#2498)
* i82586: functional, ~90% complete * added dumping of 82586 configuration * i82586: state save * Changed address handling and filtering.
This commit is contained in:
parent
3e60ab4a04
commit
754240e3b7
File diff suppressed because it is too large
Load Diff
@ -15,22 +15,236 @@ class i82586_base_device :
|
||||
public device_network_interface
|
||||
{
|
||||
public:
|
||||
enum scb_mask
|
||||
{
|
||||
T = 0x00000008, // throttle timers loaded
|
||||
RUS = 0x000000f0, // ru status
|
||||
CUS = 0x00000700, // cu status
|
||||
RNR = 0x00001000, // ru left ready state
|
||||
CNA = 0x00002000, // cu left active state
|
||||
FR = 0x00004000, // ru finished receiving a frame
|
||||
CX = 0x00008000, // cu finished executing a command with its interrupt bit set
|
||||
RUC = 0x00700000, // ru command
|
||||
RESET = 0x00800000, // reset chip (same as hardware reset)
|
||||
CUC = 0x07000000, // cu command
|
||||
ACK_RNR = 0x10000000, // acknowledge ru became became not ready
|
||||
ACK_CNA = 0x20000000, // acknowledge cu became not active
|
||||
ACK_FR = 0x40000000, // acknowledge ru received a frame
|
||||
ACK_CX = 0x80000000 // acknowledge cu completed an action command
|
||||
};
|
||||
|
||||
enum scb_cu_command
|
||||
{
|
||||
CUC_NOP = 0x00000000, // no operation
|
||||
CUC_START = 0x01000000, // start execution of first command on cbl
|
||||
CUC_RESUME = 0x02000000, // resume execution of cu
|
||||
CUC_SUSPEND = 0x03000000, // suspend execution after current command
|
||||
CUC_ABORT = 0x04000000, // abort current command immediately
|
||||
CUC_THROTTLE_D = 0x05000000, // load throttle timers after next terminal count
|
||||
CUC_THROTTLE_I = 0x06000000 // load and restart throttle timers immediately
|
||||
};
|
||||
enum cu_state : u8
|
||||
{
|
||||
CU_IDLE = 0x0, // not executing, not associated with command, initial state
|
||||
CU_SUSPENDED = 0x1, // not executing, associated with command
|
||||
CU_ACTIVE = 0x2 // executing, associated with command
|
||||
};
|
||||
|
||||
enum scb_ru_command
|
||||
{
|
||||
RUC_NOP = 0x00000000, // no operation
|
||||
RUC_START = 0x00100000, // start reception of frames
|
||||
RUC_RESUME = 0x00200000, // resume frame reception
|
||||
RUC_SUSPEND = 0x00300000, // suspend frame reception
|
||||
RUC_ABORT = 0x00400000 // abort receiver operation immediately
|
||||
};
|
||||
enum ru_state : u8
|
||||
{
|
||||
RU_IDLE = 0x0, // no resources, discarding frames, initial state
|
||||
RU_SUSPENDED = 0x1, // has resources, discarding frames
|
||||
RU_NR = 0x2, // no resources, discarding frames, accumulating statistics
|
||||
RU_READY = 0x4, // has resources, storing frames
|
||||
RU_NR_RFD = 0xa, // no receive frame descriptor resources (not 82586 mode)
|
||||
RU_NR_RBD = 0xc // no receive block descriptor resources (not 82586 mode)
|
||||
};
|
||||
|
||||
enum cu_cb_cs_mask
|
||||
{
|
||||
CB_MAXCOL = 0x00000007, // number of collisions (82596 only)
|
||||
CB_A = 0x00001000, // command aborted
|
||||
CB_OK = 0x00002000, // error free completion
|
||||
CB_B = 0x00004000, // busy executing command
|
||||
CB_C = 0x00008000, // command completed
|
||||
CB_CMD = 0x00070000, // command operation code
|
||||
CB_NC = 0x00100000, // no crc insertion (82596 only)
|
||||
CB_SF = 0x00080000, // simplified mode (82596 only)
|
||||
CB_I = 0x20000000, // interrupt after completion
|
||||
CB_S = 0x40000000, // suspend after completion
|
||||
CB_EL = 0x80000000 // end of command list
|
||||
};
|
||||
enum cu_cb_command
|
||||
{
|
||||
CB_NOP = 0x00000000, // no operation
|
||||
CB_IASETUP = 0x00010000, // individual address setup
|
||||
CB_CONFIGURE = 0x00020000, // configure
|
||||
CB_MCSETUP = 0x00030000, // multicast setup
|
||||
CB_TRANSMIT = 0x00040000, // transmit
|
||||
CB_TDREFLECT = 0x00050000, // time domain reflectometer
|
||||
CB_DUMP = 0x00060000, // dump
|
||||
CB_DIAGNOSE = 0x00070000 // diagnose
|
||||
};
|
||||
enum cu_transmit_count_mask
|
||||
{
|
||||
TB_COUNT = 0x3fff,
|
||||
TB_EOF = 0x8000
|
||||
};
|
||||
enum cu_tdreflect_mask
|
||||
{
|
||||
TDR_TIME = 0x07ff, // time until echo
|
||||
TDR_ET_SRT = 0x1000, // short circuit
|
||||
TDR_ET_OPN = 0x2000, // no termination
|
||||
TDR_XCVR_PRB = 0x4000, // transceiver problem
|
||||
TDR_LNK_OK = 0x8000 // no link problem
|
||||
};
|
||||
|
||||
enum ru_rfd_cs_mask
|
||||
{
|
||||
RFD_S_COLLISION = 0x00000001, // receive collision
|
||||
RFD_S_MULTICAST = 0x00000002, // multicast address
|
||||
RFD_S_TRUNCATED = 0x00000020, // frame truncated
|
||||
|
||||
RFD_S_EOP = 0x00000040, // no eop
|
||||
RFD_S_SHORT = 0x00000080, // frame too short
|
||||
RFD_S_OVERRUN = 0x00000100, // dma overrun
|
||||
RFD_S_BUFFER = 0x00000200, // no buffer
|
||||
RFD_S_ALIGN = 0x00000400, // alignment error
|
||||
RFD_S_CRC = 0x00000800, // crc error
|
||||
RFD_S_LENGTH = 0x00001000, // length error
|
||||
|
||||
RFD_ERROR_82586 = 0x00000fc0, // 82586 error bits
|
||||
RFD_ERROR = 0x00001fe1, // everything except multicast
|
||||
|
||||
RFD_OK = 0x00002000, // frame received successfully
|
||||
RFD_B = 0x00004000, // busy receiving frame
|
||||
RFD_C = 0x00008000, // frame reception completed
|
||||
RFD_SF = 0x00080000, // simplified/flexible mode
|
||||
RFD_S = 0x40000000, // suspend after receive
|
||||
RFD_EL = 0x80000000 // end of receive frame list
|
||||
};
|
||||
enum ru_receive_count_mask
|
||||
{
|
||||
RB_COUNT = 0x3fff, // actual count
|
||||
RB_F = 0x4000, // buffer used
|
||||
RB_EOF = 0x8000 // end of frame
|
||||
};
|
||||
enum ru_receive_size_mask
|
||||
{
|
||||
RB_SIZE = 0x3fff, // receive buffer size
|
||||
RB_P = 0x4000, // rbd prefetched (82596 only)
|
||||
RB_EL = 0x8000 // end of rbd list
|
||||
};
|
||||
|
||||
static const u32 SCP_ADDRESS = 0x00fffff4; // the default value of the system configuration pointer
|
||||
static const u32 TBD_EMPTY = 0x0000ffff; // FIXME: datasheet says this field should be "all 1's", but InterPro sets only lower 16 bits (in linear mode)
|
||||
static const u32 RBD_EMPTY = 0x0000ffff;
|
||||
|
||||
static const u32 FCS_RESIDUE = 0xdebb20e3; // the residue after computing the fcs over a complete frame (including fcs)
|
||||
|
||||
template <class Object> static devcb_base &static_set_out_irq_callback(device_t &device, Object &&cb) { return downcast<i82586_base_device &>(device).m_out_irq.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(ca);
|
||||
virtual void recv_cb(u8 *buf, int length) override;
|
||||
|
||||
protected:
|
||||
i82586_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u8 datawidth, u8 addrwidth);
|
||||
i82586_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endian, u8 datawidth, u8 addrwidth);
|
||||
|
||||
// standard device_* overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
// setup and scb
|
||||
virtual void initialise() = 0;
|
||||
virtual void process_scb();
|
||||
virtual void update_scb();
|
||||
|
||||
// command unit
|
||||
virtual void cu_execute();
|
||||
virtual bool cu_iasetup() = 0;
|
||||
virtual bool cu_configure() = 0;
|
||||
virtual bool cu_mcsetup() = 0;
|
||||
virtual bool cu_transmit(u32 command) = 0;
|
||||
virtual bool cu_tdreflect() = 0;
|
||||
virtual bool cu_dump() = 0;
|
||||
|
||||
// receive unit
|
||||
virtual bool address_filter(u8 *mac);
|
||||
virtual void ru_execute(u8 *buf, int length) = 0;
|
||||
|
||||
// helpers
|
||||
void set_irq(bool irq);
|
||||
virtual u32 address(u32 base, int offset, int address) = 0;
|
||||
virtual u32 address(u32 base, int offset, int address, u16 empty) = 0;
|
||||
static u32 compute_crc(u8 *buf, int length, bool crc32);
|
||||
static u64 address_hash(u8 *buf, int length);
|
||||
int fetch_bytes(u8 *buf, u32 src, int length);
|
||||
int store_bytes(u32 dst, u8 *buf, int length);
|
||||
void dump_bytes(u8 *buf, int length);
|
||||
|
||||
// device_* members
|
||||
const address_space_config m_space_config;
|
||||
address_space *m_space;
|
||||
|
||||
devcb_write_line m_out_irq;
|
||||
static const device_timer_id CU_TIMER = 0;
|
||||
static const device_timer_id RU_TIMER = 1;
|
||||
emu_timer *m_cu_timer;
|
||||
emu_timer *m_ru_timer;
|
||||
|
||||
// interrupt state
|
||||
bool m_cx; // command executed (with interrupt)
|
||||
bool m_fr; // frame received
|
||||
bool m_cna; // command unit became inactive
|
||||
bool m_rnr; // receive unit became not ready
|
||||
bool m_irq_state;
|
||||
bool m_initialised;
|
||||
|
||||
// receive/command unit state
|
||||
cu_state m_cu_state; // command unit state
|
||||
ru_state m_ru_state; // receive unit state
|
||||
u32 m_scp_address; // system configuration pointer
|
||||
u32 m_scb_base; // system control block base (segmented modes)
|
||||
u32 m_scb_address; // system control block address (linear mode)
|
||||
u32 m_scb_cs; // current scb command and status
|
||||
u32 m_cba; // current command block address
|
||||
u32 m_rfd; // current receive frame descriptor address
|
||||
|
||||
u64 m_mac_multi; // multicast address hash table
|
||||
u8 m_lb_buf[1528]; // storage for loopback frames
|
||||
int m_lb_length; // length of loopback frame
|
||||
|
||||
// configure parameters
|
||||
enum lb_mode
|
||||
{
|
||||
LOOPBACK_NONE = 0x00,
|
||||
LOOPBACK_INTERNAL = 0x40,
|
||||
LOOPBACK_EXTERNAL = 0x80,
|
||||
LOOPBACK_BOTH = 0xc0 // internal loopback for 82586, external loopback for 82596
|
||||
};
|
||||
virtual u8 cfg_get(int offset) const = 0;
|
||||
virtual void cfg_set(int offset, u8 data) = 0;
|
||||
|
||||
bool cfg_save_bad_frames() const { return BIT(cfg_get(2), 7); }
|
||||
u8 cfg_address_length() const { return (cfg_get(3) & 0x7) % 7; } // "NOTE: 7 is interpreted as 0"
|
||||
bool cfg_no_src_add_ins() const { return BIT(cfg_get(3), 3); }
|
||||
lb_mode cfg_loopback_mode() const { return (lb_mode)(cfg_get(3) & LOOPBACK_BOTH); }
|
||||
bool cfg_promiscuous_mode() const { return BIT(cfg_get(8), 0); }
|
||||
bool cfg_broadcast_disable() const { return BIT(cfg_get(8), 1); }
|
||||
bool cfg_no_crc_insertion() const { return BIT(cfg_get(8), 4); }
|
||||
bool cfg_crc16() const { return BIT(cfg_get(8), 5); }
|
||||
u8 cfg_min_frame_length() const { return cfg_get(10); }
|
||||
};
|
||||
|
||||
class i82586_device : public i82586_base_device
|
||||
@ -38,49 +252,137 @@ class i82586_device : public i82586_base_device
|
||||
public:
|
||||
i82586_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static const int CFG_SIZE = 12;
|
||||
static const int DUMP_SIZE = 170;
|
||||
|
||||
protected:
|
||||
// standard device_* overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// setup and scb
|
||||
virtual void initialise() override;
|
||||
|
||||
// command unit
|
||||
virtual bool cu_iasetup() override;
|
||||
virtual bool cu_configure() override;
|
||||
virtual bool cu_mcsetup() override;
|
||||
virtual bool cu_transmit(u32 command) override;
|
||||
virtual bool cu_tdreflect() override;
|
||||
virtual bool cu_dump() override;
|
||||
|
||||
// receive unit
|
||||
virtual bool address_filter(u8 *mac) override;
|
||||
virtual void ru_execute(u8 *buf, int length) override;
|
||||
|
||||
// helpers
|
||||
virtual u32 address(u32 base, int offset, int address) override { return m_scb_base + m_space->read_word(base + offset); }
|
||||
virtual u32 address(u32 base, int offset, int address, u16 empty) override;
|
||||
|
||||
private:
|
||||
// configure parameters
|
||||
virtual u8 cfg_get(int offset) const override { return m_cfg_bytes[offset]; }
|
||||
virtual void cfg_set(int offset, u8 data) override { m_cfg_bytes[offset] = data; }
|
||||
|
||||
u8 m_cfg_bytes[CFG_SIZE];
|
||||
};
|
||||
|
||||
class i82596_base_device : public i82586_base_device
|
||||
class i82596_device : public i82586_base_device
|
||||
{
|
||||
public:
|
||||
enum sysbus_mask
|
||||
{
|
||||
SYSBUS_M = 0x06,
|
||||
SYSBUS_TRG = 0x08,
|
||||
SYSBUS_LOCK = 0x10,
|
||||
SYSBUS_INT = 0x20,
|
||||
SYSBUS_BE = 0x80
|
||||
};
|
||||
enum sysbus_mode
|
||||
{
|
||||
MODE_82586 = 0x0,
|
||||
MODE_32SEGMENTED = 0x2,
|
||||
MODE_LINEAR = 0x4
|
||||
};
|
||||
|
||||
static const int CFG_SIZE = 14;
|
||||
static const int DUMP_SIZE = 304;
|
||||
|
||||
void port(u32 data); // cpu access interface
|
||||
|
||||
protected:
|
||||
i82596_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u8 datawidth, u8 addrwidth);
|
||||
i82596_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endian, u8 datawidth);
|
||||
|
||||
// standard device_* overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// setup and scb
|
||||
virtual void initialise() override;
|
||||
|
||||
// command unit
|
||||
virtual bool cu_iasetup() override;
|
||||
virtual bool cu_configure() override;
|
||||
virtual bool cu_mcsetup() override;
|
||||
virtual bool cu_transmit(u32 command) override;
|
||||
virtual bool cu_tdreflect() override;
|
||||
virtual bool cu_dump() override;
|
||||
|
||||
// receive unit
|
||||
virtual bool address_filter(u8 *mac) override;
|
||||
virtual void ru_execute(u8 *buf, int length) override;
|
||||
|
||||
// helpers
|
||||
virtual u32 address(u32 base, int offset, int address) override { return (mode() == MODE_LINEAR) ? m_space->read_dword(base + address) : m_scb_base + m_space->read_word(base + offset); }
|
||||
virtual u32 address(u32 base, int offset, int address, u16 empty) override;
|
||||
|
||||
private:
|
||||
// configure parameters
|
||||
virtual u8 cfg_get(int offset) const override { return m_cfg_bytes[offset]; }
|
||||
virtual void cfg_set(int offset, u8 data) override { m_cfg_bytes[offset] = data; }
|
||||
|
||||
bool cfg_crc_in_memory() const { return BIT(cfg_get(11), 2); }
|
||||
bool cfg_mc_all() const { return BIT(cfg_get(11), 5); }
|
||||
bool cfg_multi_ia() const { return BIT(cfg_get(13), 6); }
|
||||
|
||||
// initialisation, configuration and sysbus
|
||||
inline sysbus_mode mode() const { return (sysbus_mode)(m_sysbus & SYSBUS_M); }
|
||||
|
||||
u8 m_cfg_bytes[CFG_SIZE];
|
||||
u8 m_sysbus;
|
||||
u32 m_iscp_address;
|
||||
|
||||
u64 m_mac_multi_ia; // multi-ia address hash table
|
||||
};
|
||||
|
||||
class i82596sx_device : public i82596_base_device
|
||||
class i82596_le16_device : public i82596_device
|
||||
{
|
||||
public:
|
||||
i82596sx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
i82596_le16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
};
|
||||
|
||||
class i82596dx_device : public i82596_base_device
|
||||
class i82596_be16_device : public i82596_device
|
||||
{
|
||||
public:
|
||||
i82596dx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
i82596_be16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
};
|
||||
|
||||
protected:
|
||||
class i82596_le32_device : public i82596_device
|
||||
{
|
||||
public:
|
||||
i82596_le32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
};
|
||||
|
||||
private:
|
||||
class i82596_be32_device : public i82596_device
|
||||
{
|
||||
public:
|
||||
i82596_be32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(I82586, i82586_device)
|
||||
DECLARE_DEVICE_TYPE(I82596SX, i82596sx_device)
|
||||
DECLARE_DEVICE_TYPE(I82596DX, i82596dx_device)
|
||||
DECLARE_DEVICE_TYPE(I82596_LE16, i82596_le16_device)
|
||||
DECLARE_DEVICE_TYPE(I82596_BE16, i82596_be16_device)
|
||||
DECLARE_DEVICE_TYPE(I82596_LE32, i82596_le32_device)
|
||||
DECLARE_DEVICE_TYPE(I82596_BE32, i82596_be32_device)
|
||||
|
||||
#endif // MAME_MACHINE_I82586_H
|
||||
|
Loading…
Reference in New Issue
Block a user