mame/src/mess/machine/3c505.h
2013-03-09 04:09:45 +00:00

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_ */