mirror of
https://github.com/holub/mame
synced 2025-06-01 02:21:48 +03:00
306 lines
7.0 KiB
C++
306 lines
7.0 KiB
C++
/*
|
|
* threecom3c505.h - 3COM 3C505 ethernet controller
|
|
*
|
|
* Created on: August 27, 2010
|
|
* Author: Hans Ostermeyer
|
|
*
|
|
* Released for general non-commercial use under the MAME license
|
|
* Visit http://mamedev.org for licensing and usage restrictions.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifndef THREECOM3C505_H_
|
|
#define THREECOM3C505_H_
|
|
|
|
#include "emu.h"
|
|
|
|
#define CMD_BUFFER_SIZE 100
|
|
#define ETH_BUFFER_SIZE 2048
|
|
#define PGM_BUFFER_SIZE 0x2000
|
|
|
|
#define ETHERNET_ADDR_SIZE 6 /* size of ethernet addr */
|
|
|
|
#define RX_FIFO_SIZE 32
|
|
|
|
/***************************************************************************
|
|
FUNCTION PROTOTYPES
|
|
***************************************************************************/
|
|
|
|
DECLARE_READ8_DEVICE_HANDLER( threecom3c505_r );
|
|
DECLARE_WRITE8_DEVICE_HANDLER( threecom3c505_w );
|
|
|
|
int threecom3c505_receive(device_t *device, const UINT8 *data, int length);
|
|
|
|
void threecom3c505_set_verbose(int on_off);
|
|
|
|
//**************************************************************************
|
|
// DEVICE CONFIGURATION MACROS
|
|
//**************************************************************************
|
|
|
|
#define MCFG_THREECOM3C505_ADD(_tag, _interface) \
|
|
MCFG_DEVICE_ADD(_tag, THREECOM3C505, 0) \
|
|
threecom3c505_device::static_set_interface(*device, _interface);
|
|
|
|
//**************************************************************************
|
|
// TYPE DEFINITIONS
|
|
//**************************************************************************
|
|
|
|
typedef void (*threecom3c505_set_irq)(device_t *, int);
|
|
typedef void (*threecom3c505_tx_init)(device_t *);
|
|
typedef int (*threecom3c505_tx_data)(device_t *, const UINT8 *, int);
|
|
typedef int (*threecom3c505_setfilter)(device_t *, int);
|
|
|
|
struct threecom3c505_interface
|
|
{
|
|
threecom3c505_set_irq set_irq;
|
|
threecom3c505_tx_init tx_init;
|
|
threecom3c505_tx_data tx_data;
|
|
threecom3c505_setfilter setfilter;
|
|
};
|
|
|
|
#define THREECOM3C505_INTERFACE(name) const struct threecom3c505_interface (name)
|
|
|
|
// ======================> PCB data structure
|
|
|
|
#pragma pack(1)
|
|
|
|
struct Memconf
|
|
{
|
|
UINT16 cmd_q, rcv_q, mcast, frame, rcv_b, progs;
|
|
};
|
|
|
|
struct Rcv_pkt
|
|
{
|
|
UINT16 buf_ofs, buf_seg, buf_len, timeout;
|
|
};
|
|
|
|
struct Xmit_pkt
|
|
{
|
|
UINT16 buf_ofs, buf_seg, pkt_len;
|
|
};
|
|
|
|
struct Rcv_resp
|
|
{
|
|
UINT16 buf_ofs, buf_seg, buf_len, pkt_len, timeout, status;
|
|
UINT32 timetag;
|
|
};
|
|
|
|
struct Xmit_resp
|
|
{
|
|
UINT16 buf_ofs, buf_seg, c_stat, status;
|
|
};
|
|
|
|
struct Netstat
|
|
{
|
|
UINT32 tot_recv, tot_xmit;
|
|
UINT16 err_CRC, err_align, err_res, err_ovrrun;
|
|
};
|
|
|
|
struct Selftest
|
|
{
|
|
UINT16 error;
|
|
union
|
|
{
|
|
UINT16 ROM_cksum;
|
|
struct
|
|
{
|
|
UINT16 ofs, seg;
|
|
} RAM;
|
|
UINT16 i82586;
|
|
} failure;
|
|
};
|
|
|
|
struct Info
|
|
{
|
|
UINT8 minor_vers, major_vers;
|
|
UINT16 ROM_cksum, RAM_sz, free_ofs, free_seg;
|
|
};
|
|
|
|
struct Memdump
|
|
{
|
|
UINT16 size, off, seg;
|
|
};
|
|
|
|
/*
|
|
Primary Command Block. The most important data structure. All communication
|
|
between the host and the adapter is done with these. (Except for the actual
|
|
Ethernet data, which has different packaging.)
|
|
*/
|
|
struct pcb_struct
|
|
{
|
|
UINT8 command;
|
|
UINT8 length;
|
|
union
|
|
{
|
|
struct Memconf memconf;
|
|
UINT16 configure;
|
|
struct Rcv_pkt rcv_pkt;
|
|
struct Xmit_pkt xmit_pkt;
|
|
UINT8 multicast[10][6];
|
|
UINT8 eth_addr[6];
|
|
INT16 failed;
|
|
struct Rcv_resp rcv_resp;
|
|
struct Xmit_resp xmit_resp;
|
|
struct Netstat netstat;
|
|
struct Selftest selftest;
|
|
struct Info info;
|
|
struct Memdump memdump;
|
|
UINT8 raw[62];
|
|
} data;
|
|
};
|
|
|
|
#pragma pack()
|
|
|
|
// ======================> threecom3c505_device
|
|
|
|
class threecom3c505_device: public device_t,
|
|
public device_network_interface,
|
|
public threecom3c505_interface
|
|
{
|
|
public:
|
|
// construction/destruction
|
|
threecom3c505_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
|
|
// static configuration helpers
|
|
static void static_set_interface(device_t &device, const threecom3c505_interface &interface);
|
|
|
|
void recv_cb(UINT8 *buf, int len);
|
|
|
|
// device register I/O
|
|
UINT8 read_port(offs_t offset);
|
|
void write_port(offs_t offset, UINT8 data);
|
|
|
|
private:
|
|
// device-level overrides
|
|
virtual void device_start();
|
|
virtual void device_reset();
|
|
|
|
const char *cpu_context();
|
|
|
|
class data_buffer_fifo;
|
|
|
|
/* data buffer */
|
|
class data_buffer
|
|
{
|
|
friend class data_buffer_fifo;
|
|
|
|
public:
|
|
data_buffer();
|
|
void start(threecom3c505_device *device, INT32 size);
|
|
void reset();
|
|
int append(UINT8 data);
|
|
UINT8 get(int i) { return m_data[i]; };
|
|
UINT16 get_word(int i) { return (m_data[i*2+1] << 8) + m_data[i*2]; };
|
|
int is_empty() {return m_length == 0; };
|
|
int is_full() {return m_length >= m_size; };
|
|
UINT16 get_length() { return m_length; };
|
|
UINT16 get_size() { return m_size; };
|
|
UINT8 *get_data() { return m_data; };
|
|
void copy(data_buffer *db) const;
|
|
void log(const char *title) const;
|
|
|
|
private:
|
|
threecom3c505_device *m_device; // pointer back to our device
|
|
UINT16 m_length;
|
|
UINT16 m_size;
|
|
UINT8 *m_data;
|
|
};
|
|
|
|
/* data_buffer fifo (used to buffer the received data) */
|
|
class data_buffer_fifo
|
|
{
|
|
public:
|
|
data_buffer_fifo();
|
|
void start(threecom3c505_device *device, INT32 size, INT32 db_size);
|
|
void reset();
|
|
int put(const UINT8 data[], const int length);
|
|
int get(data_buffer *db);
|
|
int is_empty () { return m_get_index == m_put_index; }
|
|
int is_full () { return ((m_put_index + 1) % m_size) == m_get_index; }
|
|
private:
|
|
threecom3c505_device *m_device; // pointer back to our device
|
|
UINT16 m_size;
|
|
UINT16 m_count;
|
|
UINT16 m_get_index;
|
|
UINT16 m_put_index;
|
|
data_buffer *m_db[RX_FIFO_SIZE];
|
|
};
|
|
|
|
void set_filter_list();
|
|
void set_interrupt(enum line_state state);
|
|
|
|
static TIMER_CALLBACK( static_do_command );
|
|
|
|
void log_command();
|
|
void log_response();
|
|
void log_tx_data();
|
|
void log_rx_data();
|
|
|
|
void do_receive_command();
|
|
void set_command_pending(int onoff);
|
|
void do_command();
|
|
|
|
int ethernet_packet_is_for_me(const UINT8 mac_address[]);
|
|
|
|
void write_command_port( UINT8 data);
|
|
UINT8 read_command_port();
|
|
void write_data_port( UINT8 data);
|
|
UINT8 read_data_port();
|
|
void write_control_port( UINT8 data);
|
|
UINT8 read_status_port();
|
|
|
|
// pointer to myself (nasty: used for cpu_context)
|
|
threecom3c505_device *m_device;
|
|
|
|
UINT8 m_reg[16];
|
|
|
|
UINT8 m_status;
|
|
UINT8 m_control;
|
|
|
|
UINT8 m_command_buffer[CMD_BUFFER_SIZE];
|
|
int m_command_index;
|
|
int m_command_pending;
|
|
int m_wait_for_ack;
|
|
int m_wait_for_nak;
|
|
|
|
data_buffer_fifo m_rx_fifo;
|
|
|
|
data_buffer m_rx_data_buffer; // the ethernet receive buffer
|
|
int m_rx_data_index;
|
|
int m_rx_pending;
|
|
|
|
data_buffer m_tx_data_buffer; // the ethernet transmit buffer
|
|
int m_tx_data_length;
|
|
|
|
data_buffer m_program_buffer; // the program data buffer
|
|
int m_program_length;
|
|
|
|
pcb_struct m_response;
|
|
int m_response_length;
|
|
int m_response_index;
|
|
|
|
pcb_struct m_rcv_response;
|
|
|
|
UINT16 m_microcode_version;
|
|
UINT16 m_microcode_running;
|
|
|
|
UINT16 m_i82586_config;
|
|
|
|
struct Netstat m_netstat;
|
|
|
|
UINT8 m_station_address[ETHERNET_ADDR_SIZE];
|
|
UINT8 m_multicast_list[ETHERNET_ADDR_SIZE*2];
|
|
UINT8 m_filter_list[ETHERNET_ADDR_SIZE*4];
|
|
|
|
enum line_state irq_state;
|
|
|
|
emu_timer * m_do_command_timer; // timer to delay command execution
|
|
};
|
|
|
|
// device type definition
|
|
extern const device_type THREECOM3C505;
|
|
|
|
#endif /* THREECOM3C505_H_ */
|