From 96427263e260d5c31848ceb4e4acfaeb80d13b3d Mon Sep 17 00:00:00 2001 From: "R. Belmont" Date: Sat, 9 Mar 2013 04:05:14 +0000 Subject: [PATCH] (MESS) Apollo updates: [Hans Ostermeyer] * 3c505: fixed rare race conditions (between command response PCPs and receive packet PCPs) * receive command PCP data is now saved in m_rcv_response until receive occurs * improved end of command recognition with set_command_pending * 3c505: using now portable byte order functions from endian.h (lsb_first -> htole16) * 3c505: implemented CMD_CONFIGURE_82586 (to skip broadcast and multicast ethernet packets) * struct pcb_struct is now packed to correct size (byte packing) * added pcb_struct m_rcv_response as a one element receive PCB queue * provide ready signal for the floppy controller * improved mouse behaviour (especially if mouse is not grabbed) * delay response for boot_$volun (find partner node), so that real Apollo Workstations will be prefered as diskless boot server --- src/mess/machine/3c505.c | 735 ++++++++++++++++++---------------- src/mess/machine/apollo.c | 6 +- src/mess/machine/apollo_kbd.c | 36 +- src/mess/machine/apollo_net.c | 4 +- 4 files changed, 426 insertions(+), 355 deletions(-) diff --git a/src/mess/machine/3c505.c b/src/mess/machine/3c505.c index c463bd14750..a980d293153 100644 --- a/src/mess/machine/3c505.c +++ b/src/mess/machine/3c505.c @@ -12,9 +12,11 @@ * - http://lxr.free-electrons.com/source/drivers/net/3c505.c * - http://stason.org/TULARC/pc/network-cards/O/OLIVETTI-Ethernet-NPU-9144-3C505.html * - http://www.bitsavers.org/pdf/3Com/3C500_Mar83.pdf + * - http://www.bitsavers.org/pdf/3Com/1569-03_EtherLink_Plus_Technical_Reference_Jan89.pdf */ #include "machine/3c505.h" +#include #define VERBOSE 0 @@ -26,12 +28,6 @@ static int verbose = VERBOSE; #define MAINCPU "maincpu" -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -//const device_type THREECOM3C505 = threecom3c505_device_config::static_alloc_device_config; - //************************************************************************** // CONSTANTS //************************************************************************** @@ -128,9 +124,9 @@ enum CMD_MC_17 = 0x17, CMD_TRANSMIT_PACKET_18 = 0x18, - CMD_MC_F8 =0xf8, - CMD_MC_F9 =0xf9, - CMD_MC_FA =0xfa, + CMD_MC_F8 = 0xf8, + CMD_TRANSMIT_PACKET_F9 = 0xf9, + CMD_MC_FA = 0xfa, /*adapter PCB commands */ CMD_RESET_RESPONSE = 0x30, @@ -157,7 +153,8 @@ enum CMD_MC_E2_RESPONSE = 0xe2 }; -/* These defines for 'configure' */ +/* defines for 'configure' */ + #define RECV_STATION 0x00 #define RECV_BROAD 0x01 #define RECV_MULTI 0x02 @@ -166,19 +163,15 @@ enum #define INT_LOOPBACK 0x08 #define EXT_LOOPBACK 0x10 -// FIXME: -// #define lsb_first(a) (((a & 255) << 8) | ((a >>8) & 255)) -#define lsb_first(a) (a) - /*************************************************************************** - IMPLEMENTATION -***************************************************************************/ + IMPLEMENTATION + ***************************************************************************/ // device type definition -const device_type THREECOM3C505 = &device_creator; +const device_type THREECOM3C505 = &device_creator ; //------------------------------------------------- -// sc499_device - constructor +// threecom3c505_device - constructor //------------------------------------------------- threecom3c505_device::threecom3c505_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) @@ -194,8 +187,8 @@ threecom3c505_device::threecom3c505_device(const machine_config &mconfig, const void threecom3c505_device::static_set_interface(device_t &device, const threecom3c505_interface &interface) { - threecom3c505_device &threecom3c505 = downcast(device); - static_cast(threecom3c505) = interface; + threecom3c505_device &threecom3c505 = downcast (device); + static_cast (threecom3c505) = interface; } //------------------------------------------------- @@ -207,17 +200,17 @@ void threecom3c505_device::device_start() m_device = this; LOG1(("start 3COM 3C505")); - 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); + 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_timer = m_device->machine().scheduler().timer_alloc(FUNC(static_set_interrupt), this); + m_do_command_timer = m_device->machine().scheduler().timer_alloc(FUNC(static_do_command), this); } //------------------------------------------------- @@ -234,11 +227,11 @@ void threecom3c505_device::device_reset() m_program_buffer.reset(); memset(m_reg, 0, sizeof(m_reg)); - m_status = HCRE; + m_status = HCRE | DIR_; m_control = 0; m_command_index = 0; m_command_pending = 0; - m_mc_f9_pending = 0; + m_wait_for_nak = 0; m_wait_for_ack = 0; m_rx_data_index = 0; m_rx_pending = 0; @@ -249,16 +242,16 @@ void threecom3c505_device::device_reset() m_microcode_version = 0; m_i82586_config = 0; - // FIXME: test data - m_netstat.tot_recv = 1; - m_netstat.tot_xmit = 2; - m_netstat.err_CRC = 3; - m_netstat.err_align = 4; - m_netstat.err_res = 5; - m_netstat.err_ovrrun = 6; + // these will appear in /etc/nodestat -l + m_netstat.tot_recv = 0; + m_netstat.tot_xmit = 0; + m_netstat.err_CRC = 0; + m_netstat.err_align = 0; + m_netstat.err_res = 0; + m_netstat.err_ovrrun = 0; - memset(m_station_address, 0 , sizeof(m_station_address)); - memset(m_multicast_list, 0 , sizeof(m_multicast_list)); + memset(m_station_address, 0, sizeof(m_station_address)); + memset(m_multicast_list, 0, sizeof(m_multicast_list)); set_filter_list(); set_promisc(true); } @@ -339,7 +332,7 @@ void threecom3c505_device::data_buffer::log(const char * title) const if (verbose > 0) { int i; - logerror("%s: %s (length=%02x)", m_device->cpu_context(), title, m_length); + logerror("%s: %s (length=%02x)", m_device->cpu_context(), title, m_length); for (i = 0; i < m_length; i++) { logerror(" %02x", m_data[i]); @@ -386,7 +379,7 @@ void threecom3c505_device::data_buffer_fifo::reset() m_count = 0; } -int threecom3c505_device::data_buffer_fifo::put(const UINT8 data[], const int length) +int threecom3c505_device::data_buffer_fifo::put(const UINT8 data[], const int length) { UINT16 next_index = (m_put_index + 1) % m_size; @@ -437,10 +430,10 @@ int threecom3c505_device::data_buffer_fifo::get(data_buffer *db) void threecom3c505_device::set_filter_list() { - memset(m_filter_list, 0 , sizeof(m_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)); + memset(m_filter_list, 0, sizeof(m_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) { @@ -465,20 +458,9 @@ void threecom3c505_device::set_interrupt(enum line_state state) (*set_irq)(this, state); } irq_state = state; - - // FIXME: hack? - if ( m_command_buffer[0] == CMD_EXECUTE_PROGRAM && state == 1) - { - m_status |= ASF_PCB_END; - } } } -TIMER_CALLBACK( threecom3c505_device::static_set_interrupt ) -{ - reinterpret_cast (ptr)->set_interrupt(ASSERT_LINE); -} - // ------------------------------------- void threecom3c505_device::log_command() @@ -490,7 +472,7 @@ void threecom3c505_device::log_command() switch (m_command_buffer[0]) { case CMD_RESET: // 0x00 - logerror("CMD_RESET"); + logerror("!!! unexpected CMD_RESET"); break; case CMD_CONFIGURE_ADAPTER_MEMORY: // 0x01 logerror("CMD_CONFIGURE_ADAPTER_MEMORY"); @@ -511,7 +493,7 @@ void threecom3c505_device::log_command() logerror("CMD_LOAD_MULTICAST_LIST"); break; case CMD_CLEAR_PROGRAM: // 0x0c - logerror("!!! Unexpected CMD_CLEAR_PROGRAM"); + logerror("!!! unexpected CMD_CLEAR_PROGRAM"); break; case CMD_DOWNLOAD_PROGRAM: // 0x0d logerror("CMD_DOWNLOAD_PROGRAM"); @@ -535,20 +517,20 @@ void threecom3c505_device::log_command() case CMD_MC_F8: // 0xf8 logerror("!!! CMD_MC_F8"); break; - case CMD_MC_F9: // 0xf9 - logerror("CMD_MC_F9"); + case CMD_TRANSMIT_PACKET_F9: // 0xf9 + logerror("CMD_TRANSMIT_PACKET_F9"); break; case CMD_MC_FA: // 0xfa logerror("!!! CMD_MC_FA"); break; default: - logerror("!!! Unexpected Command !!!"); + logerror("!!! unexpected Command"); } switch (m_command_buffer[0]) { - case CMD_MC_F9: // 0xf9 + case CMD_TRANSMIT_PACKET_F9: // 0xf9 logerror(" (%02x, length=00)", m_command_buffer[0]); break; @@ -619,7 +601,7 @@ void threecom3c505_device::log_response() logerror("!!! CMD_MC_E2_RESPONSE"); break; default: - logerror("!!! Unexpected Response !!!"); + logerror("!!! unexpected Response"); } logerror(" (%02x, length=%02x)", m_response.command, m_response.length); for (i = 0; i < m_response.length; i++) @@ -630,121 +612,171 @@ void threecom3c505_device::log_response() } } +/*************************************************************************** + do_receive_command + ***************************************************************************/ + void threecom3c505_device::do_receive_command() { - LOG2(("do_receive_command - data_length=%x rx_pending=%d", - m_rx_data_buffer.get_length(), m_rx_pending)); -#if 0 - if (m_microcode_running && m_microcode_version == APOLLO_MC_VERSION_SR10_4) + // receive pending and no other command is pending + if (m_rx_pending > 0 && !m_command_pending) { - m_response.command = CMD_MC_E1_RESPONSE; - m_response.length = 0; - m_response_length = 0; - m_response_index = 0; + if (m_rx_data_buffer.get_length() == 0 && !m_rx_fifo.is_empty()) + { + m_rx_fifo.get(&m_rx_data_buffer); + } - m_rx_pending++; - } - else -#endif + // receive data available ? + if (m_rx_data_buffer.get_length() > 0) + { + LOG2(("do_receive_command - data_length=%x rx_pending=%d", + m_rx_data_buffer.get_length(), m_rx_pending)); - { - m_response.command = CMD_RECEIVE_PACKET_COMPLETE; // 0x38 - m_response.length = 16; - m_response.data.rcv_resp.buf_ofs = 0; - m_response.data.rcv_resp.buf_seg = 0; - m_response.data.rcv_resp.buf_len = m_rx_data_buffer.get_length(); - m_response.data.rcv_resp.pkt_len = m_rx_data_buffer.get_length(); // (?) - m_response.data.rcv_resp.timeout = 0; // successful completion - m_response.data.rcv_resp.status = m_rx_data_buffer.get_length() > 0 ? 0 : 0xffff; - m_response.data.rcv_resp.timetag = 0L; // TODO + m_rx_pending--; + set_command_pending(1); - m_response_length = m_response.length + 2; - m_response_index = 0; - } + // preset receive response PCB + memcpy(&m_response, &m_rcv_response, sizeof(m_rcv_response)); - m_status |= ACRF; /* adapter command register full */ +// m_response.command = CMD_RECEIVE_PACKET_COMPLETE; // 0x38 +// m_response.length = 16; +// m_response.data.rcv_resp.buf_ofs = htole16(0); +// m_response.data.rcv_resp.buf_seg = htole16(0); +// m_response.data.rcv_resp.buf_len = htole16(buf_len); + m_response.data.rcv_resp.pkt_len = htole16(m_rx_data_buffer.get_length()); + m_response.data.rcv_resp.timeout = htole16(0); // successful completion + m_response.data.rcv_resp.status = htole16(m_rx_data_buffer.get_length() > 0 ? 0 : 0xffff); + m_response.data.rcv_resp.timetag = htole32(0); // TODO: time tag - if (m_control & CMDE) - { - LOG2(("do_receive_command - set_interrupt(%d)", ASSERT_LINE)); - // set_interrupt(ASSERT_LINE); + // compute and check no of bytes to be DMA'ed (must be even) + UINT16 buf_len = le16toh(m_response.data.rcv_resp.buf_len) & ~1; + if (m_rx_data_buffer.get_length() > buf_len) + { + LOG1(("do_receive_command !!! buffer size too small (%d < %d)", buf_len, m_rx_data_buffer.get_length())); + m_response.data.rcv_resp.pkt_len = htole16(buf_len); + m_response.data.rcv_resp.status = 0xffff; + } + else + { + buf_len = (m_rx_data_buffer.get_length() + 1) & ~1; + m_response.data.rcv_resp.buf_len = htole16(buf_len); + } - // interrupt later - m_timer->adjust( attotime::from_usec(10)); + m_response_length = m_response.length + 2; + m_response_index = 0; + + m_status |= ACRF; /* set adapter command register full */ + if (m_control & CMDE) + { + set_interrupt(ASSERT_LINE); + } + } } } -void threecom3c505_device::set_command_pending(int onoff) +/*************************************************************************** + set_command_pending onoff + ***************************************************************************/ + +void threecom3c505_device::set_command_pending(int state) { - m_command_pending = onoff; - LOG2(("set_command_pending %d m_rx_pending=%d m_rx_data_buffer.get_length()=%x%s", - m_command_pending, m_rx_pending, m_rx_data_buffer.get_length(), onoff ? "" :"\n")); + LOG2(("set_command_pending %d -> %d m_wait_for_ack=%d m_wait_for_nak=%d m_rx_pending=%d%s", + m_command_pending, state, m_wait_for_ack, m_wait_for_nak, m_rx_pending, state ? "" :"\n")); //- verbose = onoff ? 1 : 2; - if (!m_command_pending) + switch (state) { + case 0: + // command is no longer pending + m_command_pending = 0; + // clear previous command byte m_command_buffer[0] = 0; - m_mc_f9_pending = 0; m_wait_for_ack = 0; + m_wait_for_nak = 0; - if (m_rx_pending > 0 && m_rx_data_buffer.get_length() > 0) + do_receive_command(); + break; + case 1: + // command is pending + m_command_pending = 1; + break; + case 2: + // wait for nak/ack + if (m_microcode_running && m_microcode_version == APOLLO_MC_VERSION_SR10_4) { - m_rx_pending--; - m_command_pending = 1; - - LOG2(("set_command_pending %d m_rx_pending=%d", m_command_pending, m_rx_pending)); - - do_receive_command(); + m_wait_for_nak = 1; } + else + { + m_wait_for_ack = 1; + } + break; + default: + LOG(("set_command_pending %d unexpected" , state)); + break; } + } /*************************************************************************** do_command ***************************************************************************/ +TIMER_CALLBACK( threecom3c505_device::static_do_command ) +{ + reinterpret_cast (ptr)->do_command(); +} + void threecom3c505_device::do_command() { + pcb_struct &command_pcp = (pcb_struct &) m_command_buffer; + // default to successful completion - m_response.command = m_command_buffer[0] + CMD_RESPONSE_OFFSET; + m_response.command = command_pcp.command + CMD_RESPONSE_OFFSET; m_response.length = 1; m_response.data.failed = 0; // successful completion - switch (m_command_buffer[0]) + switch (command_pcp.command) { case CMD_RESET: // 0x00 -// FIXME: -// device_reset(); + // FIXME: should never occur break; case CMD_CONFIGURE_ADAPTER_MEMORY: // 0x01 - m_i82586_config = m_program_buffer.get_word(1); + // TODO + break; + + case CMD_CONFIGURE_82586: // 0x02 + m_i82586_config = command_pcp.data.raw[0] + (command_pcp.data.raw[1] << 8); break; case CMD_RECEIVE_PACKET: // 0x08 - if (m_rx_data_buffer.get_length() == 0 && !m_rx_fifo.get(&m_rx_data_buffer)) - { - // receive data not yet available - m_rx_pending++; - set_command_pending(0); - } - else - { - do_receive_command(); - } + // preset response PCB from the Receive Command PCB + m_rcv_response.command = CMD_RECEIVE_PACKET_COMPLETE; // 0x38 + m_rcv_response.length = sizeof(struct Rcv_resp); + m_rcv_response.data.rcv_resp.buf_ofs = command_pcp.data.rcv_pkt.buf_ofs; + m_rcv_response.data.rcv_resp.buf_seg = command_pcp.data.rcv_pkt.buf_seg; + m_rcv_response.data.rcv_resp.buf_len = command_pcp.data.rcv_pkt.buf_len; + m_rcv_response.data.rcv_resp.pkt_len = 0; + m_rcv_response.data.rcv_resp.timeout = 0; + m_rcv_response.data.rcv_resp.status = 0; + m_rcv_response.data.rcv_resp.timetag = 0L; // TODO + + m_rx_pending++; + set_command_pending(0); return; // break; - case CMD_MC_F9: + case CMD_TRANSMIT_PACKET_F9: m_response.command = CMD_TRANSMIT_PACKET_COMPLETE; // fall through case CMD_TRANSMIT_PACKET: // 0x09 case CMD_TRANSMIT_PACKET_18: // 0x18 - m_response.length = 8; + m_response.length = sizeof(struct Xmit_resp); m_response.data.xmit_resp.buf_ofs = 0; m_response.data.xmit_resp.buf_seg = 0; m_response.data.xmit_resp.c_stat = 0; // successful completion @@ -752,89 +784,92 @@ void threecom3c505_device::do_command() break; case CMD_EXECUTE_PROGRAM: // 0x0e - m_response.length = 0; - m_microcode_running = 1; - m_microcode_version = m_program_buffer.get_word(1); + // m_response.length = 0; + + // FIXME: hack? + m_status |= ASF_PCB_END; break; case CMD_NETWORK_STATISTICS: // 0x0a m_response.length = sizeof(struct Netstat); - // response data must be LSB first! - m_response.data.netstat.tot_recv = lsb_first(m_netstat.tot_recv); - m_response.data.netstat.tot_xmit = lsb_first(m_netstat.tot_xmit); - m_response.data.netstat.err_CRC = lsb_first(m_netstat.err_CRC); - m_response.data.netstat.err_align = lsb_first(m_netstat.err_align); - m_response.data.netstat.err_res = lsb_first(m_netstat.err_res); - m_response.data.netstat.err_ovrrun = lsb_first(m_netstat.err_ovrrun); + m_response.data.netstat.tot_recv = htole16(m_netstat.tot_recv); + m_response.data.netstat.tot_xmit = htole16(m_netstat.tot_xmit); + m_response.data.netstat.err_CRC = htole16(m_netstat.err_CRC); + m_response.data.netstat.err_align = htole16(m_netstat.err_align); + m_response.data.netstat.err_res = htole16(m_netstat.err_res); + m_response.data.netstat.err_ovrrun = htole16(m_netstat.err_ovrrun); break; case CMD_ADAPTER_INFO: // 0x11 m_response.length = sizeof(struct Info); - // FIXME: replace test data; must be LSB first! + // FIXME: using demo data m_response.data.info.minor_vers = 1; m_response.data.info.major_vers = 2; - m_response.data.info.ROM_cksum = lsb_first(3); - m_response.data.info.RAM_sz = lsb_first(4); - m_response.data.info.free_ofs = lsb_first(5); - m_response.data.info.free_seg = lsb_first(6); + m_response.data.info.ROM_cksum = htole16(3); + m_response.data.info.RAM_sz = htole16(4); + m_response.data.info.free_ofs = htole16(5); + m_response.data.info.free_seg = htole16(6); break; case CMD_LOAD_MULTICAST_LIST:// 0x0b - if (m_command_buffer[1] > sizeof(m_multicast_list) || - (m_command_buffer[1] % ETHERNET_ADDR_SIZE) != 0) + if (command_pcp.length > sizeof(m_multicast_list) + || (command_pcp.length % ETHERNET_ADDR_SIZE) != 0) { - LOG(("CMD_LOAD_MULTICAST_LIST - !!! unexpected data size %d !!!", m_command_buffer[1])); + LOG(("CMD_LOAD_MULTICAST_LIST - unexpected data size %d", command_pcp.length)); } else { - memset(m_multicast_list, 0 , sizeof(m_multicast_list)); - memcpy(m_multicast_list, m_command_buffer+2 , m_command_buffer[1]-2); + memset(m_multicast_list, 0, sizeof(m_multicast_list)); + memcpy(m_multicast_list, command_pcp.data.multicast, command_pcp.length- 2); set_filter_list(); } break; case CMD_SET_STATION_ADDRESS: // 0x10 - if (m_command_buffer[1] != sizeof(m_station_address)) + if (command_pcp.length != sizeof(m_station_address)) { - LOG(("CMD_SET_STATION_ADDRESS - !!! unexpected data size %d !!!", m_command_buffer[1])); - memset(m_station_address, 0 , sizeof(m_station_address)); + LOG(("CMD_SET_STATION_ADDRESS - unexpected data size %d", command_pcp.length)); + memset(m_station_address, 0, sizeof(m_station_address)); } else { - memcpy(m_station_address, m_command_buffer+2 , m_command_buffer[1]); + memcpy(m_station_address, command_pcp.data.eth_addr, command_pcp.length); } set_filter_list(); - set_mac((char *)m_station_address); + set_mac((char *) m_station_address); break; - case CMD_CONFIGURE_82586: // 0x02 - case CMD_DOWNLOAD_PROGRAM: // 0x0d case CMD_MC_17: // 0x17 - default: + m_microcode_running = 1; + break; + + case CMD_DOWNLOAD_PROGRAM: // 0x0d + UINT16 mc_version = m_program_buffer.get_word(1); + switch (mc_version) + { + case APOLLO_MC_VERSION_SR10_2: + case APOLLO_MC_VERSION_SR10_4: + m_microcode_version = mc_version; + break; + default: + m_microcode_version = 0; + LOG(("CMD_DOWNLOAD_PROGRAM - unexpected microcode version %04x", mc_version)); + break; + } + // return microcode version as program id + m_response.length = 2; + m_response.data.raw[0] = m_microcode_version & 0xff; + m_response.data.raw[1] = (m_microcode_version >> 8) & 0xff; break; } m_response_index = 0; m_response_length = m_response.length + 2; - m_status |= ACRF; /* adapter command register full */ + m_status |= ACRF; /* set adapter command register full */ if (m_control & CMDE) { - switch (m_command_buffer[0]) - { - case CMD_NETWORK_STATISTICS: // 0x0a - case CMD_DOWNLOAD_PROGRAM: // 0xd - case CMD_EXECUTE_PROGRAM: // 0x0e - case CMD_ADAPTER_INFO: // 0x11 - // interrupt later - m_timer->adjust( attotime::from_msec(5)); - break; - - default: - // interrupt at once - set_interrupt(ASSERT_LINE); - break; - } + set_interrupt(ASSERT_LINE); } } @@ -848,6 +883,27 @@ int threecom3c505_device::ethernet_packet_is_for_me(const UINT8 mac_address[]) // wireshark filter: eth.addr eq 08:00:1e:01:ae:a5 or eth.dst eq ff:ff:ff:ff:ff:ff or eth.dst eq 09:00:1e:00:00:00 or eth.dst eq 09:00:1e:00:00:01 int i; + static const UINT8 broadcast_address[ETHERNET_ADDR_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + // accept all packets if RECV_PROMISC is set + if (m_i82586_config & RECV_PROMISC) + { + return 1; + } + + // skip Ethernet broadcast packets if RECV_BROAD is not set + if (!(m_i82586_config & RECV_BROAD) && memcmp(mac_address, + broadcast_address, ETHERNET_ADDR_SIZE) == 0) + { + return 0; + } + + // skip Ethernet multicast packets if RECV_MULTI is not set + if (!(m_i82586_config & RECV_MULTI) && (mac_address[0] & 0x01) != 0) + { + return 0; + } + for (i = 0; i + ETHERNET_ADDR_SIZE < sizeof(m_filter_list); i += ETHERNET_ADDR_SIZE) { if (memcmp(mac_address, m_filter_list + i, ETHERNET_ADDR_SIZE) == 0) @@ -862,7 +918,7 @@ int threecom3c505_device::ethernet_packet_is_for_me(const UINT8 mac_address[]) return 1; } } - return 0; + return 0; } /*************************************************************************** @@ -871,6 +927,7 @@ int threecom3c505_device::ethernet_packet_is_for_me(const UINT8 mac_address[]) void threecom3c505_device::recv_cb(UINT8 *data, int length) { + if (length < ETHERNET_ADDR_SIZE || !ethernet_packet_is_for_me(data)) { // skip packet @@ -888,53 +945,45 @@ void threecom3c505_device::recv_cb(UINT8 *data, int length) m_netstat.tot_recv++; LOG2(("recv_cb: data_length=%x m_rx_pending=%d", length, m_rx_pending)); - if (m_rx_data_buffer.get_length() == 0) - { - m_rx_fifo.get(&m_rx_data_buffer); - } - - if (!m_command_pending && m_rx_pending > 0 - && m_rx_data_buffer.get_length() > 0) - { - m_rx_pending--; - set_command_pending(1); - do_receive_command(); - } + do_receive_command(); } } -void threecom3c505_device::write_command_port( UINT8 data) -{ - LOG2(("writing 3C505 command port %02x - m_status=%02x m_control=%02x m_command_index=%02x", data, m_status, m_control, m_command_index)); +/*************************************************************************** + write_command_port +***************************************************************************/ - if ((m_control & HSF_PCB_MASK) != HSF_PCB_END) +void threecom3c505_device::write_command_port(UINT8 data) +{ + LOG2(("writing 3C505 command port %02x - m_status=%02x m_control=%02x m_command_index=%02x", + data, m_status, m_control, m_command_index)); + + if (m_command_index == 0) + { + switch (data) + { + case 0: + LOG2(("!!! writing 3C505 Command Register = %02x", data)); + // spurious data; reset? + break; + + case CMD_TRANSMIT_PACKET_F9: + // read data length from data port (not from command port) + m_tx_data_buffer.reset(); + m_status |= HRDY; /* data register ready */ + m_command_buffer[m_command_index++] = data; + set_command_pending(1); + break; + + default: + m_command_buffer[m_command_index++] = data; + set_command_pending(1); + break; + } + } + else if ((m_control & HSF_PCB_MASK) != HSF_PCB_END) { m_command_buffer[m_command_index++] = data; - m_status |= HCRE; /* command register empty */ - - if (m_command_index == 1) - { - switch (data) - { - case 0: - // spurious data; set command register empty - m_command_index = 0; - m_status |= HCRE; - break; - - case CMD_MC_F9: -// case CMD_MC_FA: - // read data length from data port (not from command port) - m_tx_data_buffer.reset(); - m_status |= HRDY; /* data register ready */ - set_command_pending(1); - break; - - default: - set_command_pending(1); - break; - } - } } else { @@ -966,19 +1015,35 @@ void threecom3c505_device::write_command_port( UINT8 data) m_status |= HRDY; /* data register ready */ break; + case CMD_NETWORK_STATISTICS: // 0x0a + case CMD_EXECUTE_PROGRAM: // 0x0e + case CMD_ADAPTER_INFO: // 0x11 + // delay command execution + m_do_command_timer->adjust(attotime::from_usec(100)); + break; + default: do_command(); break; } } + + m_status |= HCRE; /* command register empty */ } +/*************************************************************************** + read_command_port + ***************************************************************************/ + UINT8 threecom3c505_device::read_command_port() { UINT8 data; + + // the interrupt request is cleared when the Command Register is read + set_interrupt(CLEAR_LINE); + if (m_response_index == 0) { -// set_command_pending(1); data = m_response.command; } else if (m_response_index == 1) @@ -993,27 +1058,25 @@ UINT8 threecom3c505_device::read_command_port() { data = m_response.length + 2; } - else if (m_response_index == m_response_length+1 /*&& m_microcode_running*/) + else if (m_response_index == m_response_length + 1 /*&& m_microcode_running*/) { // FIXME: special for SR10.4 microcode, content doesn't matter? data = 0; // ? m_response_index++; - m_status &= ~ACRF; /* adapter command register no longer full */ + m_status &= ~ACRF; /* the adapter command register is no longer full */ - LOG2(("FIXME: reading 3C505 Command Register at offset %02x with index %02x = %02x", - PORT_COMMAND, m_response_index, data)); + LOG2(("read_command_port: !!! reading 3C505 Command Register = %02x - m_status=%02x m_control=%02x", + data, m_status, m_control)); - if (m_mc_f9_pending == 1) - { - m_mc_f9_pending++; - } + // wait for nak in control register + set_command_pending(2); } else { // should never happen data = 0; // 0xff; - LOG(("UNEXPECTED: reading 3C505 Command Register at offset %02x = %02x", PORT_COMMAND, data)); + LOG(("read_command_port: unexpected reading Command Register at index %04x", m_response_index)); } if (m_response_index <= m_response_length + 1) @@ -1024,12 +1087,6 @@ UINT8 threecom3c505_device::read_command_port() } else if (m_response_index == m_response_length + 1) { - // FIXME: - if (!(m_status & DIR_)) - { - m_status &= ~HRDY; /* data register no longer ready */ - } - log_response(); switch (m_response.command) @@ -1049,36 +1106,33 @@ UINT8 threecom3c505_device::read_command_port() case CMD_TRANSMIT_PACKET_18_COMPLETE: m_netstat.tot_xmit++; - if(!send(m_tx_data_buffer.get_data(), m_tx_data_buffer.get_length())) + if (!send(m_tx_data_buffer.get_data(), m_tx_data_buffer.get_length())) { - // FIXME: failed to send the ethernet packet - LOG(("read_command_port(): failed to send ethernet packet")); + // FIXME: failed to send the Ethernet packet + 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) + (*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")); + // 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_MC_F9) + if (m_command_buffer[0] != CMD_TRANSMIT_PACKET_F9) { -// set_command_pending(0); - m_wait_for_ack = 1; + set_command_pending(2); } break; case CMD_DOWNLOAD_PROGRAM_RESPONSE: m_program_buffer.reset(); -// set_command_pending(0); - m_wait_for_ack = 1; + set_command_pending(2); break; default: -// set_command_pending(0); - m_wait_for_ack = 1; + set_command_pending(2); break; } } @@ -1086,7 +1140,11 @@ UINT8 threecom3c505_device::read_command_port() return data; } -void threecom3c505_device::write_data_port( UINT8 data) +/*************************************************************************** + write_data_port + ***************************************************************************/ + +void threecom3c505_device::write_data_port(UINT8 data) { if (m_control & FLSH) { @@ -1094,7 +1152,7 @@ void threecom3c505_device::write_data_port( UINT8 data) } else if ((m_status & HRDY) == 0) { - // this will happen in ether.dex Test 20/1 + // this happened in ether.dex Test 20/1 LOG(("write_data_port: failed to write tx data (data register not ready), data length=%x status=%x", m_tx_data_buffer.get_length(), m_status)); } @@ -1107,9 +1165,10 @@ void threecom3c505_device::write_data_port( UINT8 data) } #endif - else if (m_command_buffer[0] == CMD_MC_F9) + else if (m_command_buffer[0] == CMD_TRANSMIT_PACKET_F9) { - switch (m_command_index) { + switch (m_command_index) + { case 1: m_command_buffer[m_command_index++] = data; break; @@ -1127,21 +1186,14 @@ void threecom3c505_device::write_data_port( UINT8 data) if (m_tx_data_buffer.get_length() == m_tx_data_length) { // CMD_TRANSMIT_PACKET_COMPLETE -#if 0 - if (m_command_buffer[0] == CMD_MC_F8) - { - // FIXME: what does it do? - LOG(("write_data_port: !!! TODO: CMD_MC_F8 !!! command=%x data length=%x", m_command_buffer[0], m_tx_data_length)); - } -#endif m_tx_data_buffer.log("Tx Data"); do_command(); } break; } } - else if (m_command_buffer[0] == CMD_TRANSMIT_PACKET || - m_command_buffer[0] == CMD_TRANSMIT_PACKET_18) + else if (m_command_buffer[0] == CMD_TRANSMIT_PACKET || // + m_command_buffer[0] == CMD_TRANSMIT_PACKET_18) { if (!m_tx_data_buffer.append(data)) { @@ -1181,7 +1233,7 @@ void threecom3c505_device::write_data_port( UINT8 data) } else { - LOG(("write_data_port: !!! UNEXPECTED !!! command=%x data=%02x", m_command_buffer[0], data)); + LOG(("write_data_port: unexpected command %02x data=%02x", m_command_buffer[0], data)); } if (m_tx_data_buffer.get_length() >= PORT_DATA_FIFO_SIZE @@ -1197,18 +1249,23 @@ void threecom3c505_device::write_data_port( UINT8 data) } } -UINT8 threecom3c505_device::read_data_port(){ +/*************************************************************************** + read_data_port + ***************************************************************************/ + +UINT8 threecom3c505_device::read_data_port() +{ UINT8 data; UINT16 data_length = m_rx_data_buffer.get_length(); // DomainOS will read words (i.e. even number of bytes); must handle packets with odd byte length - UINT16 even_data_length = (data_length+1) & ~1; + UINT16 even_data_length = (data_length + 1) & ~1; if (m_rx_data_index < even_data_length) { // eventually prepend data length (for CMD_MC_E1_RESPONSE) data = m_rx_data_index == -2 ? (data_length & 0xff) : // m_rx_data_index == -1 ? (data_length << 8) : // - m_rx_data_buffer.get(m_rx_data_index); + m_rx_data_buffer.get(m_rx_data_index); m_rx_data_index++; @@ -1217,43 +1274,73 @@ UINT8 threecom3c505_device::read_data_port(){ m_status &= ~HRDY; /* data register no longer ready */ m_rx_data_buffer.log("Rx Data"); m_rx_data_buffer.reset(); -// set_command_pending(0); - m_wait_for_ack = 1; + set_command_pending(2); } } - -#if 0 - else if (m_rx_data_index == data_length && (data_length & 1)) - { - // data length is odd, pad with 0 to next even size - data = 0; - m_rx_data_index++; - LOG(("!!!: padding 3C505 Rx Data with odd data length %2x with value %02x", data_length, data)); - } -#endif - else { // FIXME: should never happen data = 0xff; - m_status &= ~HRDY; /* data register no longer ready */ - set_command_pending(0); - LOG(("UNEXPECTED: reading 3C505 data Register as %02x (data_length=%02x)", data, data_length)); + LOG(("read_data_port: unexpected reading data at index %04x)", m_rx_data_index)); } return data; } -void threecom3c505_device::write_control_port( UINT8 data) -{ - // if (m_device->machine->firstcpu->safe_pcbase() == 0x3C4BAD48) verbose = 3; - // if (m_device->machine->firstcpu->safe_pcbase() == 0x010464DC) verbose = 3; +/*************************************************************************** + write_control_port + ***************************************************************************/ - if (verbose <= 2 && (data & (DMAE | TCEN /*| CMDE*/)) != 0) +void threecom3c505_device::write_control_port(UINT8 data) +{ + switch (data & (ATTN | FLSH)) { - // dma or interrupts enabled - LOG1(("writing 3C505 Control Register at offset %02x = %02x", PORT_CONTROL, data)); + case ATTN: + LOG2(("write_control_port %02x - Soft Reset", data)); + // TODO: soft reset + break; + + case FLSH: + LOG2(("write_control_port %02x - Flush Data Register", data)); + // flush data register + if (data & DIR_) + { + m_status &= ~HRDY; /* data register not ready */ + } + else + { + // download to adapter + m_status |= HRDY; /* data register ready */ + + // flush data register (reset tx data fifo) + // m_tx_data_length = 0; + m_tx_data_buffer.reset(); + } + break; + + case ATTN | FLSH: + LOG2(("write_control_port %02x - Reset Adapter", data)); + device_reset(); + break; + + case 0: + LOG2(("write_control_port %02x", data)); + + // end reset + if ((m_control & (ATTN | FLSH)) == (ATTN | FLSH)) + { + m_status |= ASF_PCB_END; + m_status |= HRDY; /* 20 byte data fifo is empty */ + } + + if (data == DIR_) + { + // why?? dex ether 20 expects HRDY + m_status |= HRDY; /* data register ready */ + } + break; } + // propagate DIR_ from Control to Status register m_status = (m_status & ~DIR_) | (data & DIR_); switch (data & HSF_PCB_MASK) @@ -1264,81 +1351,42 @@ void threecom3c505_device::write_control_port( UINT8 data) set_command_pending(0); } break; + + case HSF_PCB_END: // (HSF2|HSF1) + m_status &= ~ACRF; /* adapter command register is not full */ + // fall through + case HSF_PCB_NAK: // HSF2 if (m_microcode_running) { + if (m_wait_for_nak) + { + set_command_pending(0); + } m_status = (m_status & ~ASF_PCB_MASK) | ASF_PCB_ACK; } break; - case HSF_PCB_END: // (HSF2|HSF1) - m_status &= ~(ATTN | DMAE | ASF_PCB_MASK); - if (m_microcode_running) - { - m_status = (m_status & ~ASF_PCB_MASK) | ASF_PCB_ACK; - } - break; + default: // 0 m_command_index = 0; - m_status |= HCRE; /* command register empty */ - - if (m_command_buffer[0] == CMD_MC_F9) - { - m_mc_f9_pending = 1; -//- verbose = 2; - } - - if (data == 0x00) - { - // hardware reset - m_status |= HRDY; /* data register ready */ - // flush data register (reset tx data fifo) - m_tx_data_length = 0; - // FIXME: Don't do this (but why?) - // m_tx_data_buffer.reset(); - } - else if (data == DIR_) - { - // why?? dex ether 20 expects HRDY - // m_status &= ~HRDY; /* data register not ready */ - m_status |= HRDY; /* data register ready */ - } - else if (data & FLSH) - { - if (data & DIR_) - { - m_status &= ~HRDY; /* data register not ready */ - } - else - { - // flush data register (reset tx data fifo) -// m_tx_data_length = 0; - m_tx_data_buffer.reset(); - m_status |= HRDY; /* data register ready */ - } - } + m_status |= HCRE; /* host command register is empty */ break; } - if ((m_control & (ATTN | FLSH)) == (ATTN | FLSH) && (data & (ATTN | FLSH)) == 0) - { - m_status |= ASF_PCB_END; - } - - if (m_mc_f9_pending == 2) - { - m_mc_f9_pending = 0; - set_command_pending(0); - } - m_control = data; } +/*************************************************************************** + read_status_port + ***************************************************************************/ + UINT8 threecom3c505_device::read_status_port() { UINT8 data = m_status; m_status &= ~ASF_PCB_MASK; - switch (data & ASF_PCB_MASK) { + switch (data & ASF_PCB_MASK) + { case ASF_PCB_END: m_status |= ASF_PCB_ACK; break; @@ -1346,6 +1394,10 @@ UINT8 threecom3c505_device::read_status_port() return data; } +/*************************************************************************** + write_port + ***************************************************************************/ + void threecom3c505_device::write_port(offs_t offset, UINT8 data) { m_reg[offset & 0x0f] = data; @@ -1370,6 +1422,10 @@ 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) { @@ -1384,15 +1440,14 @@ UINT8 threecom3c505_device::read_port(offs_t offset) data = read_command_port(); break; case PORT_STATUS: /* 0x02 read only, 8-bit */ - data=read_status_port(); - - set_interrupt(CLEAR_LINE); + data = read_status_port(); // omit excessive logging if (data == last_data) { UINT32 pc = machine().device(MAINCPU)->safe_pcbase(); - if (pc == last_pc) { + if (pc == last_pc) + { return data; } last_pc = pc; @@ -1405,7 +1460,7 @@ UINT8 threecom3c505_device::read_port(offs_t offset) data = read_data_port(); break; case PORT_CONTROL: /* 0x06 read/write, 8-bit */ - // just return current value + data = m_control; break; default: break; @@ -1431,8 +1486,8 @@ WRITE8_DEVICE_HANDLER( threecom3c505_w ) int threecom3c505_receive(device_t *device, const UINT8 data[], int length) { - downcast (device)->recv_cb((UINT8 *)data,length); - return 1; + downcast (device)->recv_cb((UINT8 *) data, length); + return 1; } void threecom3c505_set_verbose(int on_off) diff --git a/src/mess/machine/apollo.c b/src/mess/machine/apollo.c index fceec7fc7b1..78e546d85dc 100644 --- a/src/mess/machine/apollo.c +++ b/src/mess/machine/apollo.c @@ -440,7 +440,7 @@ READ8_MEMBER(apollo_state::apollo_dma_read_byte){ { SLOG1(("dma read byte at offset %x+%03x = %02x", page_offset, offset, data)); } - +// logerror(" %02x", data); return data; } @@ -460,6 +460,7 @@ WRITE8_MEMBER(apollo_state::apollo_dma_write_byte){ { SLOG1(("dma write byte at offset %x+%03x = %02x", page_offset, offset , data)); } +// logerror(" %02x", data); } READ8_MEMBER(apollo_state::apollo_dma_read_word){ @@ -1409,6 +1410,9 @@ MACHINE_START_MEMBER(apollo_state,apollo) fdc->setup_intrq_cb(pc_fdc_at_device::line_cb(FUNC(apollo_state::fdc_interrupt), this)); fdc->setup_drq_cb(pc_fdc_at_device::line_cb(FUNC(apollo_state::fdc_dma_drq), this)); + // motor is on, floppy disk is ready + fdc->fdc->ready_w(1); + device_start_apollo_ptm (machine().device(APOLLO_PTM_TAG) ); device_start_apollo_sio(machine().device(APOLLO_SIO_TAG)); device_start_apollo_sio2(machine().device(APOLLO_SIO2_TAG)); diff --git a/src/mess/machine/apollo_kbd.c b/src/mess/machine/apollo_kbd.c index 5d17995df9a..8e28ebc2ede 100644 --- a/src/mess/machine/apollo_kbd.c +++ b/src/mess/machine/apollo_kbd.c @@ -255,7 +255,7 @@ void apollo_kbd_device::mouse::read_mouse() { if (m_tx_pending > 0) { - m_tx_pending -= 5; + m_tx_pending -= 5; // we will be called every 5ms } else { @@ -263,6 +263,13 @@ void apollo_kbd_device::mouse::read_mouse() int x = m_device->m_io_mouse2->read(); int y = m_device->m_io_mouse3->read(); + /* sign extend values < 0 */ + if (x & 0x800) + x |= 0xfffff000; + if (y & 0x800) + y |= 0xfffff000; + y = -y; + if (m_last_b < 0) { m_last_b = b; @@ -271,19 +278,24 @@ void apollo_kbd_device::mouse::read_mouse() } else if (b != m_last_b || x != m_last_x || y != m_last_y) { - int dx = x - m_last_x; - int dy = y - m_last_y; UINT8 mouse_data[4]; int mouse_data_size; - LOG2(("read_mouse: b=%02x x=%04x y=%04x dx=%d dy=%d", b, x, y, dx, dy)); + int dx = x - m_last_x; + int dy = y - m_last_y; + + // slow down huge mouse movements + dx = dx > 50 ? 50 : dx < -50 ? -50 : dx; + dy = dy > 50 ? 50 : dy < -50 ? -50 : dy; + + LOG2(("read_mouse: b=%02x x=%d y=%d dx=%d dy=%d", b, x, y, dx, dy)); if (m_device->m_mode == KBD_MODE_0_COMPATIBILITY) { mouse_data[0] = 0xdf; mouse_data[1] = 0xf0 ^ b; mouse_data[2] = dx; - mouse_data[3] = -dy; + mouse_data[3] = dy; mouse_data_size = 4; } else @@ -295,7 +307,7 @@ void apollo_kbd_device::mouse::read_mouse() mouse_data[0] = 0xf0 ^ b; mouse_data[1] = dx; - mouse_data[2] = -dy; + mouse_data[2] = dy; mouse_data_size = 3; } @@ -303,10 +315,10 @@ void apollo_kbd_device::mouse::read_mouse() { // mouse data submitted; update current mouse state m_last_b = b; - m_last_x = x; - m_last_y = y; + m_last_x += dx; + m_last_y += dy; } - m_tx_pending = 100; // mouse data packet will take 50 ms + m_tx_pending = 100; // mouse data packet will take 40 ms } } } @@ -862,7 +874,7 @@ void apollo_kbd_device::poll_callback() } scan_keyboard(); - // Note: we omit extra traffic while keyboard is in Compatibitlit mode + // Note: we omit extra traffic while keyboard is in Compatibility mode if (m_device->m_mode != KBD_MODE_0_COMPATIBILITY) { m_mouse.read_mouse(); @@ -1185,9 +1197,9 @@ INPUT_PORTS_START( apollo_kbd ) PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Center mouse button") PORT_CODE(MOUSECODE_BUTTON2) PORT_START("mouse2") // X-axis - PORT_BIT( 0xfff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) + PORT_BIT( 0xfff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(200) PORT_KEYDELTA(1) PORT_PLAYER(1) PORT_START("mouse3") // Y-axis - PORT_BIT( 0xfff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) + PORT_BIT( 0xfff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(200) PORT_KEYDELTA(1) PORT_PLAYER(1) INPUT_PORTS_END diff --git a/src/mess/machine/apollo_net.c b/src/mess/machine/apollo_net.c index cfcfba8d8fd..4b637ae33a6 100644 --- a/src/mess/machine/apollo_net.c +++ b/src/mess/machine/apollo_net.c @@ -850,7 +850,7 @@ int apollo_netserver_receive(device_t *device, const UINT8 rx_data_buffer[], } else if (current_rx_data_length > 0) { - LOG(("!!!! apollo_netserver_receive: busy - skipped data with length %02x",rx_data_length)); + LOG1(("apollo_netserver_receive: busy - skipped data with length %02x",rx_data_length)); return 0; } else @@ -859,7 +859,7 @@ int apollo_netserver_receive(device_t *device, const UINT8 rx_data_buffer[], current_rx_data_length = rx_data_length; // delay response to multicast requests - int ms = is_apollo_multicast_address(rx_data_buffer) ? 100 : 1; + 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; }