(MESS) apollo: Separate 3c505 out into an ISA16 card. [R. Belmont]

This commit is contained in:
R. Belmont 2014-03-10 02:48:10 +00:00
parent 5d8ceefb5e
commit 7d678bedea
9 changed files with 155 additions and 1463 deletions

2
.gitattributes vendored
View File

@ -8038,10 +8038,8 @@ src/mess/machine/amstr_pc.c svneol=native#text/plain
src/mess/machine/amstrad.c svneol=native#text/plain
src/mess/machine/apollo.c svneol=native#text/plain
src/mess/machine/apollo_dbg.c svneol=native#text/plain
src/mess/machine/apollo_eth.c svneol=native#text/plain
src/mess/machine/apollo_kbd.c svneol=native#text/plain
src/mess/machine/apollo_kbd.h svneol=native#text/plain
src/mess/machine/apollo_net.c svneol=native#text/plain
src/mess/machine/appldriv.c svneol=native#text/plain
src/mess/machine/appldriv.h svneol=native#text/plain
src/mess/machine/apple1.c svneol=native#text/plain

View File

@ -688,8 +688,6 @@ static ADDRESS_MAP_START(dn3500_map, AS_PROGRAM, 32, apollo_state )
AM_RANGE(0x016400, 0x0164ff) AM_READWRITE16(selective_clear_locations_r, selective_clear_locations_w, 0xffffffff )
AM_RANGE(0x017000, 0x017fff) AM_READWRITE16(apollo_address_translation_map_r, apollo_address_translation_map_w, 0xffffffff )
AM_RANGE(0x058000, 0x058007) AM_DEVREADWRITE8_LEGACY(APOLLO_ETH_TAG, threecom3c505_r, threecom3c505_w, 0xffffffff)
AM_RANGE(0x05d800, 0x05dc07) AM_DEVREADWRITE8_LEGACY(APOLLO_SCREEN_TAG, apollo_mcr_r, apollo_mcr_w, 0xffffffff)
AM_RANGE(0xfa0000, 0xfdffff) AM_DEVREADWRITE16_LEGACY(APOLLO_SCREEN_TAG, apollo_mgm_r, apollo_mgm_w, 0xffffffff)
@ -736,8 +734,6 @@ static ADDRESS_MAP_START(dsp3500_map, AS_PROGRAM, 32, apollo_state )
AM_RANGE(0x016400, 0x0164ff) AM_READWRITE16(selective_clear_locations_r, selective_clear_locations_w, 0xffffffff )
AM_RANGE(0x017000, 0x017fff) AM_READWRITE16(apollo_address_translation_map_r, apollo_address_translation_map_w, 0xffffffff )
AM_RANGE(0x058000, 0x058007) AM_DEVREADWRITE8_LEGACY(APOLLO_ETH_TAG, threecom3c505_r, threecom3c505_w, 0xffffffff)
AM_RANGE(ATBUS_IO_BASE, ATBUS_IO_END) AM_READWRITE16(apollo_atbus_io_r, apollo_atbus_io_w, 0xffffffff)
AM_RANGE(0x080000, 0x081fff) AM_ROM /* 3C505 boot ROM */
@ -765,7 +761,6 @@ static ADDRESS_MAP_START(dn3000_map, AS_PROGRAM, 32, apollo_state )
AM_RANGE(0x009400, 0x0094ff) AM_DEVREADWRITE8(APOLLO_PIC1_TAG, pic8259_device, read, write, 0xffffffff)
AM_RANGE(0x009500, 0x0095ff) AM_DEVREADWRITE8(APOLLO_PIC2_TAG, pic8259_device, read, write, 0xffffffff)
AM_RANGE(0x009600, 0x0096ff) AM_READWRITE16(apollo_node_id_r, apollo_node_id_w, 0xffffffff)
AM_RANGE(0x058000, 0x058007) AM_DEVREADWRITE8_LEGACY(APOLLO_ETH_TAG, threecom3c505_r, threecom3c505_w, 0xffffffff)
AM_RANGE(0x05d800, 0x05dc07) AM_DEVREADWRITE8_LEGACY(APOLLO_SCREEN_TAG, apollo_mcr_r, apollo_mcr_w, 0xffffffff)
AM_RANGE(0xfa0000, 0xfdffff) AM_DEVREADWRITE16_LEGACY(APOLLO_SCREEN_TAG, apollo_mgm_r, apollo_mgm_w, 0xffffffff)
@ -803,8 +798,6 @@ static ADDRESS_MAP_START(dsp3000_map, AS_PROGRAM, 32, apollo_state )
AM_RANGE(0x009500, 0x0095ff) AM_DEVREADWRITE8(APOLLO_PIC2_TAG, pic8259_device, read, write, 0xffffffff)
AM_RANGE(0x009600, 0x0096ff) AM_READWRITE16(apollo_node_id_r, apollo_node_id_w, 0xffffffff)
AM_RANGE(0x058000, 0x058007) AM_DEVREADWRITE8_LEGACY(APOLLO_ETH_TAG, threecom3c505_r, threecom3c505_w, 0xffffffff)
AM_RANGE(ATBUS_IO_BASE, ATBUS_IO_END) AM_READWRITE16(apollo_atbus_io_r, apollo_atbus_io_w, 0xffffffff)
AM_RANGE(0x080000, 0x081fff) AM_ROM /* 3C505 boot ROM */
@ -843,8 +836,6 @@ static ADDRESS_MAP_START(dn5500_map, AS_PROGRAM, 32, apollo_state )
AM_RANGE(0x016400, 0x0164ff) AM_READWRITE16(selective_clear_locations_r, selective_clear_locations_w, 0xffffffff )
AM_RANGE(0x017000, 0x017fff) AM_READWRITE16(apollo_address_translation_map_r, apollo_address_translation_map_w, 0xffffffff )
AM_RANGE(0x058000, 0x058007) AM_DEVREADWRITE8_LEGACY(APOLLO_ETH_TAG, threecom3c505_r, threecom3c505_w, 0xffffffff)
AM_RANGE(0x05d800, 0x05dc07) AM_DEVREADWRITE8_LEGACY(APOLLO_SCREEN_TAG, apollo_mcr_r, apollo_mcr_w, 0xffffffff)
AM_RANGE(0xfa0000, 0xfdffff) AM_DEVREADWRITE16_LEGACY(APOLLO_SCREEN_TAG, apollo_mgm_r, apollo_mgm_w, 0xffffffff)
@ -894,8 +885,6 @@ static ADDRESS_MAP_START(dsp5500_map, AS_PROGRAM, 32, apollo_state )
AM_RANGE(0x016400, 0x0164ff) AM_READWRITE16(selective_clear_locations_r, selective_clear_locations_w, 0xffffffff )
AM_RANGE(0x017000, 0x017fff) AM_READWRITE16(apollo_address_translation_map_r, apollo_address_translation_map_w, 0xffffffff )
AM_RANGE(0x058000, 0x058007) AM_DEVREADWRITE8_LEGACY(APOLLO_ETH_TAG, threecom3c505_r, threecom3c505_w, 0xffffffff)
AM_RANGE(ATBUS_IO_BASE, ATBUS_IO_END) AM_READWRITE16(apollo_atbus_io_r, apollo_atbus_io_w, 0xffffffff)
AM_RANGE(0x080000, 0x081fff) AM_ROM /* 3C505 boot ROM */
@ -920,9 +909,6 @@ void apollo_state::machine_reset()
MACHINE_RESET_CALL_MEMBER(apollo);
// set configuration
threecom3c505_set_verbose(apollo_config(APOLLO_CONF_NET_TRACE));
// we can't do this any more
#if 0
if (apollo_config(APOLLO_CONF_NODE_ID))
@ -959,7 +945,6 @@ static void apollo_reset_instr_callback(device_t *device)
// reset the ISA bus devices
apollo->m_isa->reset();
machine.device(APOLLO_ETH_TAG)->reset();
if (!apollo_is_dsp3x00())
{

View File

@ -20,7 +20,6 @@
#include "bus/rs232/rs232.h"
#include "machine/terminal.h"
#include "machine/ram.h"
#include "machine/3c505.h"
#include "machine/6840ptm.h"
#include "machine/n68681.h"
#include "machine/am9517a.h"
@ -289,33 +288,6 @@ UINT16 apollo_csr_get_control_register(void);
UINT16 apollo_csr_get_status_register(void);
void apollo_csr_set_status_register(UINT16 mask, UINT16 data);
/*----------- machine/apollo_eth.c -----------*/
// ethernet transmitter
int apollo_eth_transmit(device_t* device,
const UINT8 data_buffer[], const int data_length);
int apollo_eth_setfilter(device_t *device, int node_id);
// ethernet receiver callback
typedef int (*apollo_eth_receive)(device_t *, const UINT8 *, int);
void apollo_eth_init(device_t *device, apollo_eth_receive rx_data);
/*----------- machine/apollo_net.c -----------*/
// netserver receiver
int apollo_netserver_receive(device_t* device,
const UINT8 rx_data_buffer[], const int rx_data_length);
// transmitter callback
typedef int (*apollo_netserver_transmit)(device_t *, const UINT8 *, int);
void apollo_netserver_init(const char *root_path, apollo_netserver_transmit tx_data);
/*----------- video/apollo.c -----------*/
#define APOLLO_SCREEN_TAG "apollo_screen"

View File

@ -3,7 +3,8 @@
*
* Created on: August 27, 2010
* Author: Hans Ostermeyer
*
* ISA conversion by R. Belmont
*
* Released for general non-commercial use under the MAME license
* Visit http://mamedev.org for licensing and usage restrictions.
*
@ -21,7 +22,7 @@
static int verbose = VERBOSE;
#define LOG(x) { logerror ("%s: ", m_device->cpu_context()); logerror x; logerror ("\n"); }
#define LOG(x) { logerror x; logerror ("\n"); }
#define LOG1(x) { if (verbose > 0) LOG(x)}
#define LOG2(x) { if (verbose > 1) LOG(x)}
@ -184,32 +185,119 @@ enum
#define INT_LOOPBACK 0x08
#define EXT_LOOPBACK 0x10
static INPUT_PORTS_START( tc3c505_port )
PORT_START("IO_BASE")
PORT_DIPNAME( 0x3f0, 0x300, "3C505 I/O base")
PORT_DIPSETTING( 0x010, "010h" )
PORT_DIPSETTING( 0x020, "020h" )
PORT_DIPSETTING( 0x030, "030h" )
PORT_DIPSETTING( 0x040, "040h" )
PORT_DIPSETTING( 0x050, "050h" )
PORT_DIPSETTING( 0x060, "060h" )
PORT_DIPSETTING( 0x070, "070h" )
PORT_DIPSETTING( 0x080, "080h" )
PORT_DIPSETTING( 0x090, "090h" )
PORT_DIPSETTING( 0x0a0, "0a0h" )
PORT_DIPSETTING( 0x0b0, "0b0h" )
PORT_DIPSETTING( 0x0c0, "0c0h" )
PORT_DIPSETTING( 0x0d0, "0d0h" )
PORT_DIPSETTING( 0x0e0, "0e0h" )
PORT_DIPSETTING( 0x0f0, "0f0h" )
PORT_DIPSETTING( 0x100, "0100h" )
PORT_DIPSETTING( 0x110, "0110h" )
PORT_DIPSETTING( 0x120, "0120h" )
PORT_DIPSETTING( 0x130, "0130h" )
PORT_DIPSETTING( 0x140, "0140h" )
PORT_DIPSETTING( 0x150, "0150h" )
PORT_DIPSETTING( 0x160, "0160h" )
PORT_DIPSETTING( 0x170, "0170h" )
PORT_DIPSETTING( 0x180, "0180h" )
PORT_DIPSETTING( 0x190, "0190h" )
PORT_DIPSETTING( 0x1a0, "01a0h" )
PORT_DIPSETTING( 0x1b0, "01b0h" )
PORT_DIPSETTING( 0x1c0, "01c0h" )
PORT_DIPSETTING( 0x1d0, "01d0h" )
PORT_DIPSETTING( 0x1e0, "01e0h" )
PORT_DIPSETTING( 0x1f0, "01f0h" )
PORT_DIPSETTING( 0x200, "0200h" )
PORT_DIPSETTING( 0x210, "0210h" )
PORT_DIPSETTING( 0x220, "0220h" )
PORT_DIPSETTING( 0x230, "0230h" )
PORT_DIPSETTING( 0x240, "0240h" )
PORT_DIPSETTING( 0x250, "0250h" )
PORT_DIPSETTING( 0x260, "0260h" )
PORT_DIPSETTING( 0x270, "0270h" )
PORT_DIPSETTING( 0x280, "0280h" )
PORT_DIPSETTING( 0x290, "0290h" )
PORT_DIPSETTING( 0x2a0, "02a0h" )
PORT_DIPSETTING( 0x2b0, "02b0h" )
PORT_DIPSETTING( 0x2c0, "02c0h" )
PORT_DIPSETTING( 0x2d0, "02d0h" )
PORT_DIPSETTING( 0x2e0, "02e0h" )
PORT_DIPSETTING( 0x2f0, "02f0h" )
PORT_DIPSETTING( 0x300, "0300h" )
PORT_DIPSETTING( 0x310, "0310h" )
PORT_DIPSETTING( 0x320, "0320h" )
PORT_DIPSETTING( 0x330, "0330h" )
PORT_DIPSETTING( 0x340, "0340h" )
PORT_DIPSETTING( 0x350, "0350h" )
PORT_DIPSETTING( 0x360, "0360h" )
PORT_DIPSETTING( 0x370, "0370h" )
PORT_DIPSETTING( 0x380, "0380h" )
PORT_DIPSETTING( 0x390, "0390h" )
PORT_DIPSETTING( 0x3a0, "03a0h" )
PORT_DIPSETTING( 0x3b0, "03b0h" )
PORT_DIPSETTING( 0x3c0, "03c0h" )
PORT_DIPSETTING( 0x3d0, "03d0h" )
PORT_DIPSETTING( 0x3e0, "03e0h" )
PORT_DIPSETTING( 0x3f0, "03f0h" )
PORT_START("IRQ_DRQ")
PORT_DIPNAME( 0x0f, 0x0a, "3C505 IRQ")
PORT_DIPSETTING( 0x03, "IRQ 3" )
PORT_DIPSETTING( 0x04, "IRQ 4" )
PORT_DIPSETTING( 0x05, "IRQ 5" )
PORT_DIPSETTING( 0x06, "IRQ 6" )
PORT_DIPSETTING( 0x07, "IRQ 7" )
PORT_DIPSETTING( 0x09, "IRQ 9" )
PORT_DIPSETTING( 0x0a, "IRQ 10" )
PORT_DIPSETTING( 0x0b, "IRQ 11" )
PORT_DIPSETTING( 0x0c, "IRQ 12" )
PORT_DIPSETTING( 0x0e, "IRQ 14" )
PORT_DIPSETTING( 0x0f, "IRQ 15" )
PORT_DIPNAME( 0x70, 0x00, "3C505 DMA")
PORT_DIPSETTING( 0x10, "DRQ 1" )
PORT_DIPSETTING( 0x30, "DRQ 3" )
PORT_DIPSETTING( 0x50, "DRQ 5" )
PORT_DIPSETTING( 0x60, "DRQ 6" )
PORT_DIPSETTING( 0x70, "DRQ 7" )
INPUT_PORTS_END
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
// device type definition
const device_type THREECOM3C505 = &device_creator<threecom3c505_device> ;
const device_type ISA16_3C505 = &device_creator<threecom3c505_device> ;
//-------------------------------------------------
// threecom3c505_device - constructor
//-------------------------------------------------
threecom3c505_device::threecom3c505_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, THREECOM3C505, "Threecom 3C505", tag, owner, clock, "threecom3c505", __FILE__),
device_network_interface(mconfig, *this, 10.0f)
: device_t(mconfig, ISA16_3C505, "3Com 3C505 Network Adaptor", tag, owner, clock, "3c505", __FILE__),
device_network_interface(mconfig, *this, 10.0f),
device_isa16_card_interface(mconfig, *this),
m_iobase(*this, "IO_BASE"),
m_irqdrq(*this, "IRQ_DRQ")
{
memset(static_cast<threecom3c505_interface *>(this), 0, sizeof(threecom3c505_interface));
}
//-------------------------------------------------
// static_set_interface - set the interface struct
//-------------------------------------------------
void threecom3c505_device::static_set_interface(device_t &device, const threecom3c505_interface &interface)
ioport_constructor threecom3c505_device::device_input_ports() const
{
threecom3c505_device &threecom3c505 = downcast<threecom3c505_device &> (device);
static_cast<threecom3c505_interface &> (threecom3c505) = interface;
return INPUT_PORTS_NAME( tc3c505_port );
}
//-------------------------------------------------
@ -218,20 +306,18 @@ void threecom3c505_device::static_set_interface(device_t &device, const threecom
void threecom3c505_device::device_start()
{
m_device = this;
set_isa_device();
LOG1(("start 3COM 3C505"));
m_installed = false;
m_rx_fifo.start(this, RX_FIFO_SIZE, ETH_BUFFER_SIZE);
m_rx_data_buffer.start(this, ETH_BUFFER_SIZE);
m_tx_data_buffer.start(this, ETH_BUFFER_SIZE);
m_program_buffer.start(this, PGM_BUFFER_SIZE);
if (tx_init != NULL)
{
(*tx_init)(this);
}
m_do_command_timer = m_device->machine().scheduler().timer_alloc(FUNC(static_do_command), this);
m_do_command_timer = timer_alloc(0, NULL);
}
//-------------------------------------------------
@ -275,6 +361,18 @@ void threecom3c505_device::device_reset()
memset(m_multicast_list, 0, sizeof(m_multicast_list));
set_filter_list();
set_promisc(true);
if (!m_installed)
{
int base = m_iobase->read();
m_irq = m_irqdrq->read() & 0xf;
m_drq = (m_irqdrq->read() >> 4) & 0x7;
m_isa->install_device(base, base + ELP_IO_EXTENT - 1, 0, 0, read8_delegate(FUNC(threecom3c505_device::read), this), write8_delegate(FUNC(threecom3c505_device::write), this));
m_installed = true;
}
}
/***************************************************************************
@ -290,16 +388,7 @@ const char *threecom3c505_device::cpu_context()
int s = t / osd_ticks_per_second();
int ms = (t % osd_ticks_per_second()) / 1000;
/* if we have an executing CPU, output data */
if (cpu != NULL)
{
sprintf(statebuf, "%d.%03d %s pc=%08x - %s", s, ms, cpu->tag(),
cpu->safe_pcbase(), tag());
}
else
{
sprintf(statebuf, "%d.%03d", s, ms);
}
sprintf(statebuf, "%d.%03d:%s:", s, ms, tag());
return statebuf;
}
@ -455,14 +544,6 @@ void threecom3c505_device::set_filter_list()
memcpy(m_filter_list, m_station_address, ETHERNET_ADDR_SIZE);
memset(m_filter_list + ETHERNET_ADDR_SIZE, 0xff, ETHERNET_ADDR_SIZE);
memcpy(m_filter_list + ETHERNET_ADDR_SIZE * 2, m_multicast_list, sizeof(m_multicast_list));
if (setfilter != NULL)
{
int node_id = (((m_station_address[3] << 8) + m_station_address[4]) << 8) + m_station_address[5];
LOG2(("set_filter_list node_id=%x",node_id));
(*setfilter)(this, node_id);
}
}
/*-------------------------------------------------
@ -474,9 +555,20 @@ void threecom3c505_device::set_interrupt(enum line_state state)
if (state != irq_state)
{
LOG2(("set_interrupt(%d)",state));
if (set_irq != NULL)
switch (m_irq)
{
(*set_irq)(this, state);
case 3: m_isa->irq3_w(state); break;
case 4: m_isa->irq4_w(state); break;
case 5: m_isa->irq5_w(state); break;
case 6: m_isa->irq6_w(state); break;
case 7: m_isa->irq7_w(state); break;
case 9: m_isa->irq2_w(state); break; // IRQ 9 on ISA16 goes to IRQ 2
case 10: m_isa->irq10_w(state); break;
case 11: m_isa->irq11_w(state); break;
case 12: m_isa->irq12_w(state); break;
case 14: m_isa->irq14_w(state); break;
case 15: m_isa->irq15_w(state); break;
default: logerror("3c505: invalid IRQ %d\n", m_irq); break;
}
irq_state = state;
}
@ -745,12 +837,12 @@ void threecom3c505_device::set_command_pending(int state)
}
/***************************************************************************
do_command
execute the commands (formerly do_command)
***************************************************************************/
TIMER_CALLBACK( threecom3c505_device::static_do_command )
void threecom3c505_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
reinterpret_cast<threecom3c505_device *> (ptr)->do_command();
do_command();
}
void threecom3c505_device::do_command()
@ -1134,13 +1226,6 @@ UINT8 threecom3c505_device::read_command_port()
LOG(("read_command_port(): !!! failed to send Ethernet packet"));
}
if (tx_data != NULL && //
(*tx_data)(this, m_tx_data_buffer.get_data(), m_tx_data_buffer.get_length()) == 0)
{
// FIXME: failed to transmit the Ethernet packet
LOG(("read_command_port(): !!! failed to transmit Ethernet packet"));
}
m_tx_data_buffer.reset();
if (m_command_buffer[0] != CMD_TRANSMIT_PACKET_F9)
{
@ -1420,7 +1505,7 @@ UINT8 threecom3c505_device::read_status_port()
write_port
***************************************************************************/
void threecom3c505_device::write_port(offs_t offset, UINT8 data)
WRITE8_MEMBER(threecom3c505_device::write)
{
m_reg[offset & 0x0f] = data;
LOG2(("writing 3C505 Register at offset %02x = %02x", offset, data));
@ -1448,8 +1533,7 @@ void threecom3c505_device::write_port(offs_t offset, UINT8 data)
read_port
***************************************************************************/
//READ8_DEVICE_HANDLER( threecom3c505_r )
UINT8 threecom3c505_device::read_port(offs_t offset)
READ8_MEMBER(threecom3c505_device::read)
{
// data to omit excessive logging
static UINT8 last_data = 0xff;
@ -1492,27 +1576,3 @@ UINT8 threecom3c505_device::read_port(offs_t offset)
return data;
}
//**************************************************************************
// GLOBAL STUBS
//**************************************************************************
READ8_DEVICE_HANDLER( threecom3c505_r )
{
return downcast<threecom3c505_device *> (device)->read_port(offset);
}
WRITE8_DEVICE_HANDLER( threecom3c505_w )
{
downcast<threecom3c505_device *> (device)->write_port(offset, data);
}
int threecom3c505_receive(device_t *device, const UINT8 data[], int length)
{
downcast<threecom3c505_device *> (device)->recv_cb((UINT8 *) data, length);
return 1;
}
void threecom3c505_set_verbose(int on_off)
{
verbose = on_off == 0 ? 0 : VERBOSE > 1 ? VERBOSE : 1;
}

View File

@ -15,6 +15,7 @@
#define THREECOM3C505_H_
#include "emu.h"
#include "bus/isa/isa.h"
#define CMD_BUFFER_SIZE 100
#define ETH_BUFFER_SIZE 2048
@ -24,44 +25,6 @@
#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)
@ -157,25 +120,25 @@ struct pcb_struct
class threecom3c505_device: public device_t,
public device_network_interface,
public threecom3c505_interface
public device_isa16_card_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);
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
required_ioport m_iobase;
required_ioport m_irqdrq;
private:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
virtual ioport_constructor device_input_ports() const;
const char *cpu_context();
@ -240,7 +203,6 @@ private:
void do_receive_command();
void set_command_pending(int onoff);
void do_command();
int ethernet_packet_is_for_me(const UINT8 mac_address[]);
@ -251,8 +213,8 @@ private:
void write_control_port( UINT8 data);
UINT8 read_status_port();
// pointer to myself (nasty: used for cpu_context)
threecom3c505_device *m_device;
void do_command();
virtual void recv_cb(UINT8 *data, int length);
UINT8 m_reg[16];
@ -297,9 +259,12 @@ private:
enum line_state irq_state;
emu_timer * m_do_command_timer; // timer to delay command execution
bool m_installed;
int m_irq, m_drq;
};
// device type definition
extern const device_type THREECOM3C505;
extern const device_type ISA16_3C505;
#endif /* THREECOM3C505_H_ */

View File

@ -32,6 +32,7 @@
#include "bus/isa/omti8621.h"
#include "bus/isa/sc499.h"
#include "machine/3c505.h"
#define APOLLO_IRQ_VECTOR 0xa0
#define APOLLO_IRQ_PTM 0
@ -782,53 +783,6 @@ WRITE_LINE_MEMBER(apollo_state::sio2_irq_handler)
apollo_pic_set_irq_line(APOLLO_IRQ_SIO2, state);
}
/***************************************************************************
DN3500 3c505 DEVICE Configuration
***************************************************************************/
static void apollo_3c505_set_irq(device_t *device, int state) {
// DLOG2(("apollo_3c505_interrupt: state=%x", state ));
device->machine().driver_data<apollo_state>()->apollo_pic_set_irq_line(APOLLO_IRQ_ETH1, state);
}
static int apollo_3c505_tx_data(device_t *device,
const UINT8 tx_data_buffer[], int tx_data_length) {
// transmit all transmitted packets to the apollo_netserver
apollo_netserver_receive(device, tx_data_buffer, tx_data_length);
// transmit all transmitted packets to the host ethernet (ignore any errors)
return apollo_eth_transmit(device, tx_data_buffer, tx_data_length);
}
static int apollo_3c505_setfilter(device_t *device, int node_id)
{
return apollo_eth_setfilter(device, node_id);
}
static int apollo_3c505_rx_data(device_t *device,
const UINT8 rx_data_buffer[], int rx_data_length) {
// transmit all received packets to the threecom3c505 receiver
return threecom3c505_receive(device, rx_data_buffer, rx_data_length);
}
static void apollo_3c505_tx_init(device_t *device) {
apollo_eth_init(device, apollo_3c505_rx_data);
// setup to receive all packets from the apollo_netserver
apollo_netserver_init(device->machine().options().media_path(), apollo_3c505_rx_data);
}
static THREECOM3C505_INTERFACE(apollo_3c505_config) = {
apollo_3c505_set_irq,
apollo_3c505_tx_init,
apollo_3c505_tx_data,
apollo_3c505_setfilter
};
/***************************************************************************
DN3500 Cartridge Tape DEVICE Configuration
***************************************************************************/
//##########################################################################
// machine/apollo.c - APOLLO DS3500 CPU Board
//##########################################################################
@ -866,6 +820,7 @@ static const isa16bus_interface isabus_intf =
static SLOT_INTERFACE_START(apollo_isa_cards)
SLOT_INTERFACE("wdc", ISA16_OMTI8621) // Combo ESDI/AT floppy controller
SLOT_INTERFACE("ctape", ISA8_SC499) // Archive SC499 cartridge tape
SLOT_INTERFACE("3c505", ISA16_3C505) // 3Com 3C505 Ethernet card
SLOT_INTERFACE_END
MACHINE_CONFIG_FRAGMENT( common )
@ -891,13 +846,11 @@ MACHINE_CONFIG_FRAGMENT( common )
MCFG_ISA16_BUS_CUSTOM_SPACES()
MCFG_ISA16_SLOT_ADD(APOLLO_ISA_TAG, "isa1", apollo_isa_cards, "wdc", false)
MCFG_ISA16_SLOT_ADD(APOLLO_ISA_TAG, "isa2", apollo_isa_cards, "ctape", false)
MCFG_ISA16_SLOT_ADD(APOLLO_ISA_TAG, "isa3", apollo_isa_cards, NULL, false)
MCFG_ISA16_SLOT_ADD(APOLLO_ISA_TAG, "isa3", apollo_isa_cards, "3c505", false)
MCFG_ISA16_SLOT_ADD(APOLLO_ISA_TAG, "isa4", apollo_isa_cards, NULL, false)
MCFG_ISA16_SLOT_ADD(APOLLO_ISA_TAG, "isa5", apollo_isa_cards, NULL, false)
MCFG_ISA16_SLOT_ADD(APOLLO_ISA_TAG, "isa6", apollo_isa_cards, NULL, false)
MCFG_ISA16_SLOT_ADD(APOLLO_ISA_TAG, "isa7", apollo_isa_cards, NULL, false)
MCFG_THREECOM3C505_ADD(APOLLO_ETH_TAG, apollo_3c505_config)
MACHINE_CONFIG_END
// for machines with the keyboard and a graphics head

View File

@ -1,354 +0,0 @@
/*
* apollo_eth.c - APOLLO ethernet proxy
*
* Created on: Sep 19, 2011
* Author: Hans Ostermeyer
*
* Released for general non-commercial use under the MAME license
* Visit http://mamedev.org for licensing and usage restrictions.
*
* see also:
* http://www.linuxjournal.com/article/4659
*
*
* TODO:
* Scrap this unportable stuff, make 3c505 use the core Ethernet layer directly like the 3c503.
*
*/
#define VERBOSE 0
#include "includes/apollo.h"
#if !defined(APOLLO_FOR_LINUX)
int apollo_eth_transmit(device_t *device, const UINT8 data[], int length)
{
return 1;
}
int apollo_eth_setfilter(device_t *device, int node_id)
{
return 0;
}
void apollo_eth_init(device_t *device, apollo_eth_receive rx_data)
{
}
#else /* defined(APOLLO_FOR_LINUX) */
#include "machine/3c505.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/filter.h>
#include <netinet/in.h>
#define ETH_BUFFER_SIZE 2048
// TODO: should be configurable
#define ETH_INTERFACE_NAME "eth0"
//#define ETH_INTERFACE_NAME "vmnet0"
static const char *eth_if_name;
static int eth_if_index = -1;
static int eth_socket = -1;
static UINT8 eth_hw_address[ETHERNET_ADDR_SIZE];
static apollo_eth_receive rx_callback = NULL;
/***************************************************************************
log data
***************************************************************************/
static void log_data(const device_t *device, const char *type,
const UINT8 *data, int data_length) {
if (VERBOSE > 0) {
int i;
logerror("%s - %s: %s (length=%2x)", apollo_cpu_context(
device->machine().firstcpu), device->tag(), type, data_length);
for (i = 0; i < data_length; i++) {
logerror(" %02x", data[i]);
}
logerror("\n");
}
}
/***************************************************************************
apollo_eth_receive_packet
***************************************************************************/
static int apollo_eth_receive_packet(device_t *device)
{
u_char rx_buffer[ETH_BUFFER_SIZE];
int packet_len;
do
{
packet_len = recv(eth_socket, rx_buffer, sizeof(rx_buffer), MSG_TRUNC);
} while (packet_len == -1 && errno == EINTR);
/* Check if an error occurred */
if (packet_len == -1)
{
switch (errno)
{
case EAGAIN:
return 0; /* no packet there */
case ENETDOWN:
// The device on which we're capturing went away.
DLOG1(("apollo_eth_receive_packet: the interface went down (error %d - %s)", errno, strerror(errno)));
return -1;
default:
DLOG(("apollo_eth_receive_packet: recv failed (error %d - %s)", errno, strerror(errno)));
return -1;
}
}
else if (packet_len > sizeof(rx_buffer))
{
DLOG(("apollo_eth_receive_packet: data size (%d) exceeds rx buffer size (%d)!!!", packet_len, (int)sizeof(rx_buffer)));
return -1;
}
log_data(device, "apollo_eth_receive_packet", rx_buffer, packet_len);
/* Call the user supplied callback function */
if (rx_callback != NULL)
{
// threecom3c505_receive(device, tx_data_buffer, tx_data_length);
(*rx_callback)(device, rx_buffer, packet_len);
}
return 1;
}
/***************************************************************************
receive_interrupt
***************************************************************************/
static TIMER_CALLBACK(receive_interrupt)
{
device_t *device = (device_t *) ptr;
/*
* Save the socket's current mode, and put it in non-blocking mode;
* we drain it by reading packets until we get an error
* (which is normally a "nothing more to be read" error).
*/
int save_mode = fcntl(eth_socket, F_GETFL, 0);
if (save_mode == -1)
{
DLOG(("receive_interrupt: fcntl failed (error %d - %s)", errno, strerror(errno)))
}
else if (fcntl(eth_socket, F_SETFL, save_mode | O_NONBLOCK) < 0)
{
DLOG(("receive_interrupt: fcntl failed (error %d - %s)", errno, strerror(errno)))
}
else
{
int i = 0;
while (apollo_eth_receive_packet(device) > 0 && i++ < 4)
;
fcntl(eth_socket, F_SETFL, save_mode);
}
machine.scheduler().timer_set(attotime::from_msec(1), FUNC(receive_interrupt), 0, device);
}
/***************************************************************************
apollo_eth_transmit - transmit an packet to the ethernet
***************************************************************************/
int apollo_eth_transmit(device_t *device, const UINT8 data[], int length) {
if (eth_socket != -1)
{
if (memcmp(data, eth_hw_address, ETHERNET_ADDR_SIZE) == 0)
{
// destination ethernet address is my own mac address
// TODO: should send data to "eth0"
}
if (send(eth_socket, data, length, 0) == -1) {
DLOG(("apollo_eth_transmit: send failed with error %d (%s)", errno, strerror(errno)));
} else {
log_data(device, "apollo_eth_transmit", data, length);
}
}
return 1;
}
/***************************************************************************
apollo_eth_setfilter - set the socket filter
***************************************************************************/
int apollo_eth_setfilter(device_t *device, int node_id)
{
/*
tcpdump -i eth0 -dd ether dst 08:00:1e:01:ae:a5 or ether dst 09:00:1e:00:00:00 or ether dst 09:00:1e:00:00:01 or ether broadcast
(000) ld [2]
(001) jeq #0x1e01aea5 jt 2 jf 4
(002) ldh [0]
(003) jeq #0x800 jt 11 jf 12
(004) jeq #0x1e000000 jt 6 jf 5
(005) jeq #0x1e000001 jt 6 jf 8
(006) ldh [0]
(007) jeq #0x900 jt 11 jf 12
(008) jeq #0xffffffff jt 9 jf 12
(009) ldh [0]
(010) jeq #0xffff jt 11 jf 12
(011) ret #65535
(012) ret #0
*/
static struct sock_filter bpf_code[]= {
{ 0x20, 0, 0, 0x00000002 },
{ 0x15, 0, 2, 0x1e01aea5 },
{ 0x28, 0, 0, 0x00000000 },
{ 0x15, 7, 8, 0x00000800 },
{ 0x15, 1, 0, 0x1e000000 },
{ 0x15, 0, 2, 0x1e000001 },
{ 0x28, 0, 0, 0x00000000 },
{ 0x15, 3, 4, 0x00000900 },
{ 0x15, 0, 3, 0xffffffff },
{ 0x28, 0, 0, 0x00000000 },
{ 0x15, 0, 1, 0x0000ffff },
{ 0x6, 0, 0, 0x0000ffff },
{ 0x6, 0, 0, 0x00000000 }
};
if (eth_socket != -1)
{
struct sock_fprog filter;
filter.len = sizeof(bpf_code) / sizeof(sock_filter);
filter.filter = bpf_code;
// set node id in filter
bpf_code[1].k = (bpf_code[1].k & 0xff000000) | (node_id & 0x00ffffff);
/* Attach the filter to the socket */
if (setsockopt(eth_socket, SOL_SOCKET, SO_ATTACH_FILTER, &filter,
sizeof(filter)) < 0)
{
DLOG(("apollo_eth_setfilter: failed with error %d (%s)", errno, strerror(errno)));
return 0;
}
else
{
DLOG1(("apollo_eth_setfilter: set filter for node id %x", node_id & 0x00ffffff));
}
}
return 1;
}
/***************************************************************************
apollo_eth_init - specify node id and transmitter call back function
***************************************************************************/
void apollo_eth_init(device_t *device, apollo_eth_receive rx_data)
{
rx_callback = rx_data;
eth_if_name = ETH_INTERFACE_NAME;
eth_if_index = -1;
memset(eth_hw_address, 0 , sizeof(eth_hw_address));
// Note: Only processes with effective UID 0 or the CAP_NET_RAW capability may open packet sockets.
// see also: man 7 packet
eth_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (eth_socket == -1)
{
if (errno == EPERM)
{
DLOG(("apollo_eth_init: %s - Ethernet access disabled", strerror(errno)));
}
else
{
DLOG1(("apollo_eth_init: socket failed (error %d - %s)", errno, strerror(errno)));
}
}
else
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, eth_if_name, sizeof(ifr.ifr_name));
// Get interface index
if (ioctl(eth_socket, SIOCGIFINDEX, &ifr) == -1)
{
DLOG(("apollo_eth_init: interface %s not found (error %d - %s)", eth_if_name, errno, strerror(errno)));
close(eth_socket);
eth_socket = -1;
}
else
{
eth_if_index = ifr.ifr_ifindex;
// Get hardware address
memset(&ifr, 0, sizeof(ifr));
(void) strncpy(ifr.ifr_name, eth_if_name, sizeof(ifr.ifr_name));
if (ioctl(eth_socket, SIOCGIFHWADDR, (char *) &ifr) < 0)
{
DLOG(("apollo_eth_init: SIOCGIFHWADDR failed for %s (error %d - %s)", eth_if_name, errno, strerror(errno)));
}
else
{
memcpy(eth_hw_address, ifr.ifr_hwaddr.sa_data, sizeof(eth_hw_address));
}
struct sockaddr_ll sll;
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_ifindex = eth_if_index;
sll.sll_protocol = htons(ETH_P_ALL);
if (bind(eth_socket, (struct sockaddr *) &sll, sizeof(sll)) == -1)
{
DLOG(("apollo_eth_init: bind to interface %s failed (error %d - %s)", eth_if_name, errno, strerror(errno)));
close(eth_socket);
eth_socket = -1;
}
else
{
struct packet_mreq mr;
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = eth_if_index;
mr.mr_type = PACKET_MR_PROMISC;
if (setsockopt(eth_socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)
{
DLOG(("apollo_eth_init: failed to set promiscuous mode (error %d - %s)", errno, strerror(errno)));
close(eth_socket);
eth_socket = -1;
}
else
{
// Set the socket buffer size to the specified value.
// by default request 2M for the ring buffer
int rx_bufsize = 2*1024*1024;
if (setsockopt(eth_socket, SOL_SOCKET, SO_RCVBUF, &rx_bufsize, sizeof(rx_bufsize)) == -1)
{
DLOG(("apollo_eth_init: failed to set buffer size (error %d - %s)", errno, strerror(errno)));
close(eth_socket);
eth_socket = -1;
}
else
{
device->machine().scheduler().timer_set(attotime::from_msec(1), FUNC(receive_interrupt), 0, device);
}
}
}
}
}
}
#endif /* defined(APOLLO_FOR_LINUX) */

View File

@ -1,885 +0,0 @@
/*
* apollo_net.c - simple APOLLO netserver emulation (netman, ARP, IP echo, ...)
*
* Created on: May 12, 2010
* Author: Hans Ostermeyer
*
* Released for general non-commercial use under the MAME license
* Visit http://mamedev.org for licensing and usage restrictions.
*
* see also:
* - http://www.bitsavers.org/pdf/apollo/AEGIS_Internals_and_Data_Structures_Jan86.pdf
*/
#define VERBOSE 0
// FIXME: these three should not be hardcoded
#define NETSERVER_NODE_ID 0x012340
#define NETSERVER_IP_ADDRESS {192,168,2,3} /* 192.168.2.3 */
#define NETSERVER_ROOT_PATH "apollo"
#include "includes/apollo.h"
#include "machine/3c505.h"
struct ethernet_header {
UINT8 dest[6];
UINT8 source[6];
UINT16 proto;
};
struct ip_header
{
UINT8 version;
UINT8 tos;
UINT16 tot_len;
UINT16 id;
UINT16 frag_off;
UINT8 ttl;
UINT8 protocol;
UINT16 check;
UINT32 saddr;
UINT32 daddr;
};
#define ETHERNET_HEADER_SIZE sizeof(ethernet_header)
/* Ethernet protocol ID's */
#define ETHERNET_PACKET_TYPE_IP 0x0800 /* IP */
#define ETHERNET_PACKET_TYPE_ARP 0x0806 /* Address resolution */
#define ETHERNET_PACKET_TYPE_APOLLO 0x8019
#define ETHERNET_APOLLO_PREFIX 0x08001e
#define ETHERNET_APOLLO_DOMAIN_PREFIX 0x09001e
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#define ICMP_ECHO 8 /* Echo Request */
#define PACKET_HEADER_SIZE 64
// #define ETH_BUFFER_SIZE 2000
// Note: these three pathnames are hardcoded in Apollo DomainOS; don't change them
#define APOLLO_NETBOOT_PATH "/sys/net/netboot"
#define APOLLO_SAU7_PATH "/sau7"
#define APOLLO_SAU8_PATH "/sau8"
#define APOLLO_SAU14_PATH "/sau14"
static emu_file *current_file = NULL;
static UINT16 current_sector = 0;
static UINT16 current_last_sector = 0;
static char current_pathname[256];
static UINT8 current_rx_data_buffer[ETH_BUFFER_SIZE];
static int current_rx_data_length;
static apollo_netserver_transmit tx_callback = NULL;
static UINT32 my_node_id;
static UINT8 my_ip_address[4] = NETSERVER_IP_ADDRESS; /* 192.168.2.3 */
static UINT8 my_mac_address[6];
static astring root_path;
// boot_$volun (find partner node)
static UINT8 response_0006[] = {
0x00,0x01, // 0x40:
0x00,0x01,
0x00,0x07, // 0x44: packet type (07 = 06+1)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00
};
static UINT8 list_directory_header[] = {
0x00,0x01, // 0x40:
0x00,0x01,
0x00,0x0d, // 0x44: packet type (0d = 0c+1)
0x00,0x00,0x00,0x00, // 0x46:
0x00,0x01,0x00,0x01,
0x73,0x61,0x6d,0x62,0x61,0x2f,0x73,0x61,0x75,0x37, // "samba/sau7"
0x00,0x00,0x28,0xd8,0x00,0x00,0x00,0x00,
0x75,0x37,0xd8,0xa0,0x76,0x08,0xb5,0x52,
0x75,0x37,0xe6,0xc6,0x75,0x37,0xd8,0xac
};
static UINT8 receive_data_header[] = {
0x00,0x01, // 0x40:
0x00,0x01, // 0x42:
0x00,0x09, // 0x44: packet type (09 = 08+1)
0x00,0x00,0x00,0x00, // 0x46:
0x00,0x13,0xfc,0xaf, // 0x4A: high
0x00,0x13,0xd8,0x00, // 0x4E: low
0x00,0x13,0xd8,0x2a, // 0x52: start
0x00,0x13,0xd8,0x00, // 0x56: current load address
0x00,0x00 // 0x5a:
};
static UINT8 not_found_data_header[] = {
0x00,0x01, // 0x40:
0x00,0x01, // 0x42: ?
0x00,0x13, // 0x44: packet type (13 = 12+1)
0x00,0x0e,0x00,0x07,
0x00,0x12, // 0x4a = string length
0x2f,0x2f,0x73,0x61,0x6d,0x62,0x61,0x2f, 0x73,0x61,0x75,0x37,0x2f,0x78,0x78,0x78, /*//samba/sau7/xxxxx */
0x78,0x78,
0x07,0x48,0x00,0x08,0x07,0x6a,0x00,0x08, 0x07,0x6c,0x00,0x04,0x0c,0x94
};
// boot_$get_uids
static UINT8 response_070a[] = {
0x00,0x01, // 0x40:
0x00,0x01,
0x00,0x0b, // 0x44: packet type (0b = 0a+1)
0x00,0x00,0x00,0x00,
// d993195c (2010-04-28 07:27:15)
0xd9,0x93,0x19,0x5c,0x60,0x04,0x20,0xe8, // FIXME: UID of OS paging file (?)
// 7742b564 (1996-08-14 19:12:59)
0x77,0x42,0xb5,0x64,0xf0,0x04,0x20,0xe8, // 7742B564.F00420E8 is UID of //
0x77,0x42,0xb5,0x64,0xe0,0x04,0x20,0xe8 // 7742B564.E00420E8 is UID of / (resp. //samba)
};
// get (dex) file parameters
static UINT8 response_0718[] = {
0x00,0x01, // 0x40:
0x00,0x01, // 0x42:
0x00,0x19, // 0x44: packet type (19 = 18+1)
0x00,0x00,0x00,0x00, // 0x46:
0x01,
0x01, // 0x4b: systyp (1=dir, 0=file) i.e. is directory
0x90,0x00,
0x77,0x43,0x02,0x58,0xe0,0x04,0x20,0xe8, // 0x4e: source UID
0x00,0x00, // 0x56
0x00,0x00, // 0x58: file type (0x0321 = UASC file)
0x00,0x00,0x00,0x00, // 0x5A:
0x77,0x43,0x02,0x58,0xe8,0x04,0x20,0xe8, // 0x5E: source UID
0x00,0x00,0x10,0x00, // 0x66: file size
0x00,0x00,0x00,0x04, // 0x6A: n sectors (?)
0xd9,0x8f,0xb5,0xef, // 0x6E:
0x80,0x27,0x94,0x1e, // 0x72:
0x77,0x42,0xb5,0x64,0xe0,0x04,0x20,0xe8, // source UID
0x8d,0x15,0x00,0x02,
0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00
};
static UINT8 get_byte(const UINT8 *data) {
return data[0];
}
static void set_byte(UINT8 *data, const UINT8 value) {
data[0] = value;
}
static UINT16 get_word(const UINT8 *data) {
return (data[0] << 8) | data[1];
}
static void set_word(UINT8 *data, const UINT16 value) {
data[0] = value >> 8;
data[1] = value & 0xff;
}
static UINT32 get_3byte(const UINT8 *data) {
return (((data[0] << 8) | data[1]) << 8) | data[2];
}
static void set_3byte(UINT8 *data, const UINT32 value) {
data[0] = (value >> 16) & 0xff;
data[1] = (value >> 8) & 0xff;
data[2] = value & 0xff;
}
static UINT32 get_long(const UINT8 *data) {
return (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
}
static void set_long(UINT8 *data, const UINT32 value) {
data[0] = (value >> 24) & 0xff;
data[1] = (value >> 16) & 0xff;
data[2] = (value >> 8) & 0xff;
data[3] = value & 0xff;
}
static char *get_string(const UINT8 *data) {
static char sb[256];
int i;
int stringLength = get_word(data);
for (i = 0; i < stringLength && i < sizeof(sb) - 1; i++) {
sb[i] = data[i + 2];
}
sb[stringLength] = 0;
return sb;
}
static char *get_file_name(const UINT8 *data) {
char * s = get_string(data);
int i = strlen(s);
while (--i >= 0) {
s[i] = tolower(s[i]);
}
return s;
}
static int get_file_size(const char *path) {
int file_size = 0;
emu_file file(OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
file_error filerr = file.open(path);
if (filerr == FILERR_NONE)
{
file_size = file.size();
file.close();
}
LOG1(("##### %s - file_size=%d",path, file_size));
return file_size;
}
static int is_directory(const char *path) {
int is_directory = 0;
osd_directory *curdir;
if ((curdir = osd_opendir(path)) != NULL)
{
osd_closedir(curdir);
is_directory = 1;
}
LOG1(("##### %s - is_directory=%d",path, is_directory));
return is_directory;
}
static int get_file_type(const char *path) {
if (!is_directory(path)) {
const char *suffix = path + strlen(path);
while (suffix != path && *--suffix != '.') {
}
if (strcmp(suffix, ".cmd") == 0 || strcmp(suffix, ".hlp") == 0) {
return 0x0321; // UASC file
}
}
return 0;
}
static int set_ethernet_header(UINT8 *data, UINT8 client_ethernet_address[6]) {
memcpy(data + 0, client_ethernet_address, 6);
set_3byte(data + 6, ETHERNET_APOLLO_PREFIX);
set_3byte(data + 9, my_node_id);
set_word(data + 12, ETHERNET_PACKET_TYPE_APOLLO);
return ETHERNET_HEADER_SIZE;
}
static int set_packet_header(UINT8 *packet_buffer, UINT32 dest_node_id,
UINT32 source_node_id) {
// --------- apollo header --------------
set_word(packet_buffer, 0xffff);
// set_word(packet_buffer + 2, data_size + PACKET_HEADER_SIZE);
set_word(packet_buffer + 4, 0x00be);
set_word(packet_buffer + 6, 0x0000);
set_word(packet_buffer + 8, 0x0000); // Apollo network number
set_3byte(packet_buffer + 10, ETHERNET_APOLLO_PREFIX);
set_3byte(packet_buffer + 13, dest_node_id);
set_word(packet_buffer + 16, 0x0000);
set_word(packet_buffer + 18, 0x0000);
set_word(packet_buffer + 20, 0x0000);
set_3byte(packet_buffer + 22, ETHERNET_APOLLO_PREFIX);
set_3byte(packet_buffer + 25, source_node_id);
set_word(packet_buffer + 28, 0x0003);
// --------- data header --------------
set_long(packet_buffer + 30, dest_node_id);
set_long(packet_buffer + 34, 0x24000000L);
set_long(packet_buffer + 38, source_node_id);
set_long(packet_buffer + 42, 0x01002400L);
// set_word(packet_buffer + 46, data_size + 0x22);
// set_word(packet_buffer + 48, data_size);
set_word(packet_buffer + 50, 0x0000);
set_word(packet_buffer + 52, 0x0000);
// --------- data --------------
set_word(packet_buffer + 54, 0x0401);
set_word(packet_buffer + 56, 0x0003);
set_word(packet_buffer + 58, 0x20e8);
set_word(packet_buffer + 60, 0x616d);
set_word(packet_buffer + 62, 0x0000);
return PACKET_HEADER_SIZE;
}
static int set_packet(UINT8 *packet_buffer, UINT8 *packet_data,
int packet_data_size) {
set_word(packet_buffer + 2, packet_data_size + PACKET_HEADER_SIZE);
set_word(packet_buffer + 46, packet_data_size + 0x22);
set_word(packet_buffer + 48, packet_data_size);
memcpy(packet_buffer + PACKET_HEADER_SIZE, packet_data, packet_data_size);
return packet_data_size;
}
static int get_packet_size(UINT8 *packet_buffer) {
return get_word(packet_buffer + 2);
}
static int get_dir_data(const char *pathname, UINT8 *packet_buffer) {
int nBytes, lineLength;
char *data_buffer;
osd_directory *curdir;
const osd_directory_entry *dir;
char dir_path[1024];
strcpy(dir_path, root_path);
strcat (dir_path, pathname);
set_packet(packet_buffer, list_directory_header,
sizeof(list_directory_header));
data_buffer = (char *) (packet_buffer + get_packet_size(packet_buffer));
strcpy(data_buffer, "\n\r");
strcat(data_buffer, pathname);
strcat(data_buffer, "\n\r");
if ((curdir = osd_opendir(dir_path)) == NULL)
{
strcat(data_buffer, "Error: failed to open directory ");
strcat(data_buffer, dir_path);
strcat(data_buffer, "\r\n");
}
else
{
osd_closedir(curdir);
// open a path to the netserver directory
file_enumerator path(dir_path);
lineLength = 99;
while ((dir = path.next()) != NULL)
{
LOG1(("##### %d %s", (int)strlen(dir->name), dir->name));
if (strcmp(dir->name, ".") != 0 && strcmp(dir->name, "..") != 0)
{
lineLength += 3 + strlen(dir->name);
if (lineLength > 72) {
strcat(data_buffer, "\n\r");
lineLength = 3 + strlen(dir->name);
}
strcat(data_buffer, " ");
strcat(data_buffer, dir->name);
}
}
strcat(data_buffer, "\n\r");
}
nBytes = strlen(data_buffer);
nBytes = (nBytes + 1) & 0xfffffffe;
set_word(packet_buffer + 2, get_word(packet_buffer + 2) + nBytes);
set_word(packet_buffer + 50, nBytes);
return nBytes + sizeof(list_directory_header);
}
static int get_file_data(const char *pathname, UINT8 *packet_buffer,
UINT16 first_sector, UINT16 last_sector) {
UINT8 *packet_data = packet_buffer + PACKET_HEADER_SIZE;
UINT8 *data_buffer;
int nBytes;
UINT32 fileSize = 0;
file_error filerr;
if(current_file == NULL)
{
current_file = global_alloc(emu_file(root_path, OPEN_FLAG_READ));
// skip leading '/'
filerr = current_file->open( pathname+1);
if (filerr != FILERR_NONE)
{
global_free(current_file);
current_file = NULL;
}
fileSize = current_file == NULL ? 0 : current_file->size();
current_sector = 0;
LOG1(("##### %s - %s filerr=%d fileSize=%d", root_path.cstr(), pathname, filerr, fileSize));
} else {
current_sector++;
}
current_last_sector = last_sector;
if (current_file == NULL)
{
set_packet(packet_buffer, not_found_data_header,
sizeof(not_found_data_header));
set_word(packet_data + 0x0A, strlen(pathname));
strncpy((char *) packet_data + 0x0C, pathname, 0x24);
return sizeof(not_found_data_header);
} else {
set_packet(packet_buffer, receive_data_header,
sizeof(receive_data_header));
data_buffer = (packet_buffer + get_packet_size(packet_buffer));
nBytes = current_file->read(data_buffer, 1024);
if (nBytes < 0) {
nBytes = 0;
}
// help in dex will fail, if size is odd (5.5.2010 - ost)
nBytes = (nBytes + 1) & 0xfffffffe;
if (nBytes < 1024)
{
current_file->close();
global_free(current_file);
current_file = NULL;
}
else if (current_sector == 0) {
// set header addresses from first sector read
UINT32 low = get_long(data_buffer + 0);
UINT32 start = get_long(data_buffer + 4);
UINT32 high = low + fileSize - 1;
set_long(receive_data_header + 0x0A, high);
set_long(receive_data_header + 0x0E, low);
set_long(receive_data_header + 0x12, start);
set_long(receive_data_header + 0x16, low);
set_packet(packet_buffer, receive_data_header,
sizeof(receive_data_header));
}
if (VERBOSE > 1) {
LOG1(("##### %s: 3C505 current address = %0x first/last/current sector = %0x / %0x / %0x",
pathname, get_long(receive_data_header + 0x16), first_sector, last_sector, current_sector));
}
set_long(receive_data_header + 0x16, get_long(receive_data_header + 0x16) + nBytes);
set_word(packet_data + 0x1A, nBytes < 1024 ? 0xffff : current_sector == last_sector ? 0x00ff : 0);
set_word(packet_buffer + 2, get_word(packet_buffer + 2) + nBytes);
set_word(packet_buffer + 50, nBytes);
return nBytes + sizeof(receive_data_header);
}
}
static void log_data(const device_t *device, const char *type,
const UINT8 *data, int data_length) {
if (VERBOSE > 1) {
int i;
logerror("%s - %s: Net Server %s Data (length=%2x)", apollo_cpu_context(
device->machine().firstcpu), device->tag(), type, data_length);
for (i = 0; i < data_length; i++) {
logerror(" %02x", data[i]);
}
logerror("\n");
}
}
static UINT16 get_socket(const UINT8 rx_data_buffer[], int rx_data_length) {
const UINT8 * packet_buffer = rx_data_buffer + ETHERNET_HEADER_SIZE;
int packet_length = rx_data_length - ETHERNET_HEADER_SIZE;
UINT16 socket = packet_length < 0x11 ? 0xffff : get_word(packet_buffer + 0x10); // 0x10: dest socket
return socket;
}
/***************************************************************************
netman server
***************************************************************************/
static int netman_server(const device_t *device,
const UINT8 rx_data_buffer[], int rx_data_length, UINT8 tx_data_buffer[]) {
UINT16 service;
UINT16 node_type; // SAU7, SAU8 or SAU14
char pathname[256];
int tx_data_length;
UINT8 *packet_buffer = tx_data_buffer + ETHERNET_HEADER_SIZE;
UINT32 client_node_id;
UINT8 client_ethernet_address[6];
UINT16 last_sector;
UINT16 first_sector;
client_node_id = get_3byte(rx_data_buffer + 9);
memcpy(client_ethernet_address, rx_data_buffer + 6, 6);
log_data(device, "Rx", rx_data_buffer, rx_data_length);
// strip off the ethernet header;
rx_data_buffer += ETHERNET_HEADER_SIZE;
rx_data_length -= ETHERNET_HEADER_SIZE;
service = (rx_data_length > 0x45) ? get_word(rx_data_buffer + 0x44) : 0xffff;
first_sector = (rx_data_length > 0x6b) ? get_word(rx_data_buffer + 0x6a) : 0;
// FIXME: hack
// last_sector = (rx_data_length > 0x6d) ? get_word(rx_data_buffer + 0x6c) : 0;
last_sector = (rx_data_length > 0x6d) ? get_word(rx_data_buffer + 0x6c) : 0x0f;
set_ethernet_header(tx_data_buffer, client_ethernet_address);
set_packet_header(packet_buffer, client_node_id, my_node_id);
node_type = service >> 8;
switch (service & 0xff) {
case 6: // boot_$volun (find partner node)
DLOG1(("Net Server service=%04x (boot_$volun)", service));
set_packet(packet_buffer, response_0006, sizeof(response_0006));
break;
case 8: // boot_$sysboot (get netboot)
get_file_data(APOLLO_NETBOOT_PATH, packet_buffer, first_sector, last_sector);
DLOG1(("Net Server service=%04x (boot_$sysboot - sector %x of %x-%x)", service, current_sector, first_sector, last_sector));
break;
case 0x0a: // boot_$get_uids (get UIDs for OS paging file, network root and the node entry directory)
set_packet(packet_buffer, response_070a, sizeof(response_070a));
DLOG1(("Net Server service=%04x (boot_$get_uids)", service));
break;
case 0x0c: // boot_$mult_ld (list directory for sau7, SAU8, SAU14)
get_dir_data( node_type == 7 ? APOLLO_SAU7_PATH : node_type == 8 ? APOLLO_SAU8_PATH : APOLLO_SAU14_PATH, packet_buffer);
DLOG1(("Net Server service=%04x (boot_$mult_ld)", service));
break;
case 0x12: // boot_$load (ex /sau7/self_test, domain_os, ...)
strcpy(pathname, node_type == 7 ? APOLLO_SAU7_PATH : node_type == 8 ? APOLLO_SAU8_PATH : APOLLO_SAU14_PATH);
strcat(pathname, "/");
strcat(pathname, get_file_name(rx_data_buffer + 0x48));
get_file_data(pathname, packet_buffer, first_sector, last_sector);
DLOG1(("Net Server service=%04x (boot_$load %s - sector %x of %x-%x)", service, pathname, current_sector, first_sector, last_sector));
break;
case 0x18: // boot_$set_path (set current path and get attributes of current path)
set_packet(packet_buffer, response_0718, sizeof(response_0718));
if (get_long(rx_data_buffer + 0x6e) == 0L && get_long(rx_data_buffer + 0x72) == 0L) {
// reset path name to root dir
strcpy(current_pathname, root_path);
}
// FIXME: why is this necessary???
if (is_directory(current_pathname)) {
strcat(current_pathname, "/");
strcat(current_pathname, get_file_name(rx_data_buffer + 0x48));
}
// 0x4b: systyp (1=dir, 0=file)
set_byte(packet_buffer + 0x4b, is_directory(current_pathname));
set_word(packet_buffer + 0x58, get_file_type(current_pathname));
set_long(packet_buffer + 0x66, get_file_size(current_pathname));
DLOG1(("Net Server service=%04x (boot_$set_path %s)", service, current_pathname + strlen(root_path)));
break;
case 0x1a: // boot_$load_file (?): load /sau7/cmd/startup.cmd, /sau7/cpu.dex, ...
get_file_data(current_pathname + strlen(root_path), packet_buffer, first_sector, last_sector);
DLOG1(("Net Server service=%04x (boot_$load_file %s - sector %x of %x-%x)", service, current_pathname + strlen(root_path), current_sector, first_sector, last_sector));
break;
default:
DLOG(("Net Server - unexpected service %04x", service&0xff));
return 0;
}
set_word(packet_buffer + 0x44, (service & 0xff) + 1); // 0x44: response packet type
tx_data_length = ETHERNET_HEADER_SIZE + get_packet_size(packet_buffer);
log_data(device, "Tx", tx_data_buffer, tx_data_length);
return tx_data_length;
}
static int is_ethernet_broadcast_address(const UINT8 ethernet_header[]) {
return get_3byte(ethernet_header + 0) == 0xffffff && //
get_3byte(ethernet_header + 3) == 0xffffff;
}
static int is_apollo_multicast_address(const UINT8 ethernet_header[]) {
return get_3byte(ethernet_header + 0) == ETHERNET_APOLLO_DOMAIN_PREFIX && //
(get_3byte(ethernet_header + 3) == 0L || get_3byte(ethernet_header + 3) == 1L);
}
static int is_my_ethernet_address(const UINT8 mac_address[]) {
return memcmp(mac_address, my_mac_address, 6) == 0;
}
static int is_my_ip_address(const UINT8 ip_address[]) {
return memcmp (ip_address, my_ip_address, 4) == 0;
}
static int is_my_node_id(const UINT8 node_id[]) {
return get_long(node_id) == my_node_id;
}
static int ethernet_packet_is_for_me(const UINT8 ethernet_packet_header[],
const int data_length) {
return data_length >= ETHERNET_HEADER_SIZE && (
is_ethernet_broadcast_address(ethernet_packet_header) ||
is_apollo_multicast_address(ethernet_packet_header) ||
is_my_ethernet_address(ethernet_packet_header));
}
static int is_apollo_request(const UINT8 ethernet_header[],
const int data_length) {
return data_length >= 0x30 && //
get_word(ethernet_header + 0x0c) == ETHERNET_PACKET_TYPE_APOLLO;
}
static int is_apollo_arp_request(const UINT8 ethernet_header[], const int data_length) {
return data_length >= 0x30 && //
get_word(ethernet_header + 0x0c) == ETHERNET_PACKET_TYPE_ARP && //
get_word(ethernet_header + 0x10) == ETHERNET_PACKET_TYPE_APOLLO && //
is_apollo_multicast_address(ethernet_header) && //
is_my_node_id(ethernet_header + 0x26);
}
static int is_ip_arp_request(const UINT8 ethernet_header[], const int data_length) {
return data_length >= 0x30 && //
get_word(ethernet_header + 0x0c) == ETHERNET_PACKET_TYPE_ARP && //
get_word(ethernet_header + 0x10) == ETHERNET_PACKET_TYPE_IP && //
is_ethernet_broadcast_address(ethernet_header) && //
is_my_ip_address (ethernet_header + 0x26);
}
static int is_ip_echo_request(const UINT8 ethernet_header[], const int data_length) {
return data_length >= 0x30 && //
get_word(ethernet_header + 0x0c) == ETHERNET_PACKET_TYPE_IP && //
get_byte(ethernet_header + 0x22) == ICMP_ECHO && //
is_my_ethernet_address(ethernet_header);
}
static UINT16 in_checksum(UINT8 *ptr, UINT32 nbytes)
{
UINT32 sum = 0;
while (nbytes > 1)
{
// MSB first
sum += (*ptr++) << 8;
sum += *ptr++;
nbytes -=2;
}
if (nbytes == 1)
{
sum += (*ptr++) << 8;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (~sum) & 0xffff;
}
/***************************************************************************
simple ARP Server emulation
***************************************************************************/
static int arp_server(const device_t *device,
const UINT8 rx_data[], int rx_data_length,
UINT8 tx_data[]) {
// static UINT8 arp_response[] = {
// 0x08,0x00,0x1e,0x02,0x61,0x6d, // 0x00: Ethernet address of destination
// 0x08,0x00,0x1e,0x04,0x20,0xe8, // 0x06: Ethernet address of sender
// 0x08,0x06, // 0x0c: Protocol type
// 0x00,0x01, // 0x0e: Hardware address space
// 0x80,0x19, // 0x10: Protocol address space
// 0x06, // 0x12: byte length of each hardware address
// 0x04, // 0x13: byte length of each protocol address
// 0x00,0x02, // 0x14: opcode (ares_op$REQUEST | ares_op$REPLY)
// 0x08,0x00,0x1e,0x04,0x20,0xe8, // 0x16: Hardware address of sender of this packet
// 0x00,0x04,0x20,0xe8, // 0x1c: Protocol address of sender of this packet
// 0x08,0x00,0x1e,0x02,0x61,0x6d, // 0x20: Hardware address of target of this packet (if known)
// 0x00,0x02,0x61,0x6d, // 0x26: Protocol address of target
// ...
// };
UINT16 tx_data_length = rx_data_length;
memcpy(tx_data, rx_data, tx_data_length);
// 0x00: Ethernet address of destination
memcpy(tx_data + 0x00, rx_data + 0x06, 6);
// 0x06: Ethernet address of sender
memcpy(tx_data + 0x06, my_mac_address, 6);
// 0x14: opcode (ares_op$REQUEST | ares_op$REPLY)
set_word(tx_data + 0x14, 2);
// 0x16: Hardware address of sender
memcpy(tx_data + 0x16, my_mac_address, 6);
// 0x1c: Protocol address of sender
memcpy(tx_data + 0x1c, rx_data + 0x26, 4);
// 0x20: Hardware address of target (if known)
memcpy(tx_data + 0x20, rx_data + 0x16, 6);
// 0x26: Protocol address of target
memcpy(tx_data + 0x26, rx_data + 0x1c, 4);
log_data(device, "ARP Rx", rx_data, rx_data_length);
log_data(device, "ARP Tx", tx_data, tx_data_length);
return tx_data_length;
}
/***************************************************************************
simple Echo (ping) Server emulation
***************************************************************************/
static int echo_server(const device_t *device,
const UINT8 rx_data[], int rx_data_length,
UINT8 tx_data[]) {
static const UINT32 ip_offset = sizeof(ethernet_header);
static const UINT32 icmp_offset = ip_offset + sizeof(ip_header);
UINT16 tx_data_length = rx_data_length;
memcpy(tx_data, rx_data, tx_data_length);
// 0x00: Ethernet address of destination
memcpy(tx_data + 0x00, rx_data + 0x06, 6);
// 0x06: Ethernet address of sender
memcpy(tx_data + 0x06, rx_data + 0x00, 6);
// 0x12: ip.id
set_word(tx_data + 0x12, 0x0573);
// 0x18: ip.checksum
set_word(tx_data + 0x18, 0);
set_word(tx_data + 0x18, in_checksum(tx_data + ip_offset, sizeof(ip_header)));
// 0x1a: Protocol address of sender
memcpy(tx_data + 0x1a, rx_data + 0x1e, 4);
// 0x1e: Protocol address of target
memcpy(tx_data + 0x1e, rx_data + 0x1a, 4);
// 0x22: icmp.type
set_byte(tx_data + 0x22, ICMP_ECHOREPLY);
// 0x24: icmp.cksump
set_word(tx_data + 0x24, 0);
set_word(tx_data + 0x24, in_checksum(tx_data + icmp_offset, tx_data_length-icmp_offset));
log_data(device, "Echo Rx", rx_data, rx_data_length);
log_data(device, "Echo Tx", tx_data, tx_data_length);
return tx_data_length;
}
/***************************************************************************
netserver
***************************************************************************/
static int netserver(const device_t *device,
const UINT8 rx_data[], int rx_data_length,
UINT8 tx_data[]) {
if (!ethernet_packet_is_for_me(rx_data, rx_data_length))
return 0; // skip
else if (is_apollo_request(rx_data, rx_data_length))
{
UINT16 socket = get_socket(rx_data, rx_data_length);
switch (socket) {
case 1: // Paging socket
break;
case 2: // File socket
// return file_server(device, rx_data, rx_data_length, tx_data);
break;
case 3: // NETMAN socket
return netman_server(device, rx_data, rx_data_length, tx_data);
case 4: // Information socket
break;
case 5: // Receives internet asknode "who" replies
break;
case 6: // File server overflow socket
break;
case 7: // Software diagnostic socket
break;
case 8: // routing information protocol (RIP) socket
break;
case 9: // Mailbox socket
break;
case 10: // NS Helper socket
break;
case 11: // TCP/IP
break;
case 12: // ?
break;
default:
break;
}
DLOG1(("Net Server - socket %d not yet supported", socket));
return 0;
} else if (is_apollo_arp_request(rx_data, rx_data_length)) {
return arp_server(device, rx_data, rx_data_length, tx_data);
} else if (is_ip_arp_request(rx_data, rx_data_length)) {
return arp_server(device, rx_data, rx_data_length, tx_data);
} else if (is_ip_echo_request(rx_data, rx_data_length)) {
return echo_server(device, rx_data, rx_data_length, tx_data);
} else {
log_data(device, "unexpected Rx", rx_data, rx_data_length);
return 0;
}
}
/***************************************************************************
receive_interrupt
***************************************************************************/
static TIMER_CALLBACK(receive_interrupt) {
device_t *device = (device_t *)ptr;
UINT8 tx_data_buffer[ETH_BUFFER_SIZE];
int tx_data_length = netserver(device, current_rx_data_buffer, current_rx_data_length, tx_data_buffer);
DLOG2(("Net Server rx/tx_data_length = %x/%x current_sector=%x current_last_sector=%x",
current_rx_data_length, tx_data_length, current_sector, current_last_sector ));
if (tx_data_length > 0 && tx_callback != NULL) {
// threecom3c505_receive(device, tx_data_buffer, tx_data_length);
(*tx_callback)(device, tx_data_buffer, tx_data_length);
}
if (current_file != NULL && current_sector < current_last_sector)
{
// more packets pending
machine.scheduler().timer_set(attotime::from_msec(1), FUNC(receive_interrupt), 0, device);
} else {
current_rx_data_length = 0;
}
}
/***************************************************************************
apollo_netserver_receive - receive and process an ethernet packet
***************************************************************************/
int apollo_netserver_receive(device_t *device, const UINT8 rx_data_buffer[],
int rx_data_length)
{
if (!ethernet_packet_is_for_me(rx_data_buffer, rx_data_length))
{
return 1; // skip packet
}
else if (current_rx_data_length > 0)
{
LOG1(("apollo_netserver_receive: busy - skipped data with length %02x",rx_data_length));
return 0;
}
else
{
memcpy(current_rx_data_buffer, rx_data_buffer, rx_data_length);
current_rx_data_length = rx_data_length;
// delay response to multicast requests
int ms = is_apollo_multicast_address(rx_data_buffer) ? 1000 : 1;
device->machine().scheduler().timer_set(attotime::from_msec(ms), FUNC(receive_interrupt), 0, device);
return 1;
}
}
/***************************************************************************
apollo_netserver_init - specify the transmitter call back function
***************************************************************************/
void apollo_netserver_init(const char *root_path, apollo_netserver_transmit tx_data)
{
::root_path.cat(root_path);
::root_path.cat(PATH_SEPARATOR);
::root_path.cat(NETSERVER_ROOT_PATH);
::tx_callback = tx_data;
my_node_id = NETSERVER_NODE_ID;
set_3byte(my_mac_address, ETHERNET_APOLLO_PREFIX);
set_3byte(my_mac_address + 3, my_node_id);
current_rx_data_length = 0;
}

View File

@ -901,8 +901,6 @@ $(MESSOBJ)/apollo.a: \
$(MESS_DRIVERS)/apollo.o \
$(MESS_VIDEO)/apollo.o \
$(MESS_MACHINE)/apollo_dbg.o \
$(MESS_MACHINE)/apollo_eth.o \
$(MESS_MACHINE)/apollo_net.o \
$(MESS_MACHINE)/apollo_kbd.o \
$(MESS_MACHINE)/3c505.o \
$(MESS_MACHINE)/apollo.o \