--- previous/src/ethernet.c 2018/04/24 19:29:51 1.1.1.2 +++ previous/src/ethernet.c 2018/04/24 19:31:14 1.1.1.3 @@ -3,7 +3,7 @@ This file is distributed under the GNU Public License, version 2 or at your option any later version. Read the file gpl.txt for details. - Network adapter for non-turbo NeXT machines. + Network adapter for non-turbo and turbo NeXT machines. */ @@ -13,6 +13,7 @@ #include "configuration.h" #include "sysReg.h" #include "dma.h" +#include "bmap.h" #include "ethernet.h" #include "enet_slirp.h" #include "cycInt.h" @@ -82,17 +83,11 @@ bool enet_stopped; #define RXMODE_ENA_RST 0x04 #define RXMODE_MATCH_MODE 0x03 -#define RX_NOPACKETS 0 // Accept no packets -#define RX_LIMITED 1 // Accept broadcast/limited -#define RX_NORMAL 2 // Accept broadcast/multicast -#define RX_PROMISCUOUS 3 // Accept all packets - #define EN_RESET 0x80 /* w */ void enet_reset(void); - void EN_TX_Status_Read(void) { // 0x02006000 IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.tx_status; Log_Printf(LOG_EN_REG_LEVEL,"[EN] Transmitter status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); @@ -107,7 +102,7 @@ void EN_TX_Status_Write(void) { enet.tx_status&=~(val&0x0F); } - if ((enet.tx_status&enet.tx_mask&0x0F)==0 || (enet.tx_status&enet.tx_mask&0x0F)==TXSTAT_READY) { + if ((enet.tx_status&enet.tx_mask&0x0F)==0) { set_interrupt(INT_EN_TX, RELEASE_INT); } } @@ -121,7 +116,7 @@ void EN_TX_Mask_Write(void) { enet.tx_mask=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; Log_Printf(LOG_EN_REG_LEVEL,"[EN] Transmitter masks write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); - if ((enet.tx_status&enet.tx_mask&0x0F)==0 || (enet.tx_status&enet.tx_mask&0x0F)==TXSTAT_READY) { + if ((enet.tx_status&enet.tx_mask&0x0F)==0) { set_interrupt(INT_EN_TX, RELEASE_INT); } } @@ -251,14 +246,14 @@ void EN_CounterHi_Read(void) { // 0x0200 Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver mode read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); } -void enet_tx_interrupt(Uint8 intr) { +static void enet_tx_interrupt(Uint8 intr) { enet.tx_status|=intr; if (enet.tx_status&enet.tx_mask) { set_interrupt(INT_EN_TX, SET_INT); } } -void enet_rx_interrupt(Uint8 intr) { +static void enet_rx_interrupt(Uint8 intr) { enet.rx_status|=intr; if (enet.rx_status&enet.rx_mask) { set_interrupt(INT_EN_RX, SET_INT); @@ -266,14 +261,26 @@ void enet_rx_interrupt(Uint8 intr) { } /* Functions to find out if we are intended to receive a packet */ -bool recv_multicast(Uint8 *packet) { + +/* Non-turbo */ +#define RX_NOPACKETS 0 // Accept no packets +#define RX_LIMITED 1 // Accept broadcast/limited +#define RX_NORMAL 2 // Accept broadcast/multicast +#define RX_PROMISCUOUS 3 // Accept all packets + +/* Turbo */ +#define RX_ENABLED 0x80 // Accept packets +#define RX_ANY 0x01 // Accept any packets +#define RX_OWN 0x02 // Accept own packets + +static bool recv_multicast(Uint8 *packet) { if (packet[0]&0x01) return true; else return false; } -bool recv_local_multicast(Uint8 *packet) { +static bool recv_local_multicast(Uint8 *packet) { if (packet[0]&0x01 && (packet[0]&0xFE) == enet.mac_addr[0] && packet[1] == enet.mac_addr[1] && @@ -283,7 +290,7 @@ bool recv_local_multicast(Uint8 *packet) return false; } -bool recv_me(Uint8 *packet) { +static bool recv_me(Uint8 *packet) { if (packet[0] == enet.mac_addr[0] && packet[1] == enet.mac_addr[1] && packet[2] == enet.mac_addr[2] && @@ -295,7 +302,19 @@ bool recv_me(Uint8 *packet) { return false; } -bool recv_broadcast(Uint8 *packet) { +static bool recv_me_turbo(Uint8 *packet) { + if (packet[0] == enet.mac_addr[0] && + packet[1] == enet.mac_addr[1] && + packet[2] == enet.mac_addr[2] && + packet[3] == enet.mac_addr[3] && + packet[4] == enet.mac_addr[4] && + packet[5] == enet.mac_addr[5]) + return true; + else + return false; +} + +static bool recv_broadcast(Uint8 *packet) { if (packet[0] == 0xFF && packet[1] == 0xFF && packet[2] == 0xFF && @@ -307,7 +326,25 @@ bool recv_broadcast(Uint8 *packet) { return false; } -bool enet_packet_for_me(Uint8 *packet) { +static bool enet_packet_for_me(Uint8 *packet) { + + if (ConfigureParams.System.bTurbo) { + if (enet.rx_mode&RX_ENABLED) { + if (enet.rx_mode&RX_ANY) { + return true; + } else if (enet.rx_mode&RX_OWN) { + if (recv_broadcast(packet) || recv_me_turbo(packet)) { + return true; + } + } else { + if (recv_broadcast(packet)) { + return true; + } + } + } + return false; + } + switch (enet.rx_mode&RXMODE_MATCH_MODE) { case RX_NOPACKETS: return false; @@ -331,18 +368,6 @@ bool enet_packet_for_me(Uint8 *packet) { } } -bool enet_packet_from_me(Uint8 *packet) { - if (packet[6] == enet.mac_addr[0] && - packet[7] == enet.mac_addr[1] && - packet[8] == enet.mac_addr[2] && - packet[9] == enet.mac_addr[3] && - packet[10] == enet.mac_addr[4] && - packet[11] == enet.mac_addr[5]) - return true; - else - return false; -} - void enet_receive(Uint8 *pkt, int len) { if (enet_packet_for_me(pkt)) { #if 1 /* Hack for short packets from SLIRP */ @@ -353,12 +378,13 @@ void enet_receive(Uint8 *pkt, int len) { #endif memcpy(enet_rx_buffer.data,pkt,len); enet_rx_buffer.size=enet_rx_buffer.limit=len; + enet.tx_status |= TXSTAT_NET_BUSY; } else { Log_Printf(LOG_WARN, "[EN] Packet is not for me."); } } -void print_buf(Uint8 *buf, Uint32 size) { +static void print_buf(Uint8 *buf, Uint32 size) { #if LOG_EN_DATA int i; for (i=0; i15) { - if (enet_tx_buffer.size==old_size && !tx_done) { - Log_Printf(LOG_WARN, "[EN] Sending packet: Error! Transmitter underflow (no EOP)!"); - enet_tx_interrupt(TXSTAT_UNDERFLOW); - enet_tx_buffer.size=0; + if (en_state != EN_DISCONNECTED) { + if (enet.tx_status&TXSTAT_NET_BUSY) { + /* Wait until network is free */ + Log_Printf(LOG_WARN, "[EN] Network is busy. Transmission delayed."); } else { - enet_tx_buffer.size-=15; - } - } - if (tx_done) { - Statusbar_BlinkLed(DEVICE_LED_ENET); - Log_Printf(LOG_EN_LEVEL, "[EN] Sending packet to %02X:%02X:%02X:%02X:%02X:%02X", - enet_tx_buffer.data[0], enet_tx_buffer.data[1], enet_tx_buffer.data[2], - enet_tx_buffer.data[3], enet_tx_buffer.data[4], enet_tx_buffer.data[5]); - print_buf(enet_tx_buffer.data, enet_tx_buffer.size); - if (enet.tx_mode&TXMODE_DIS_LOOP) { - /* Send to real world network */ - if (ConfigureParams.Ethernet.bEthernetConnected) { - enet_slirp_input(enet_tx_buffer.data,enet_tx_buffer.size); + old_size = enet_tx_buffer.size; + tx_done=dma_enet_read_memory(); + if (enet_tx_buffer.size>0) { + enet.tx_status &= ~TXSTAT_TX_RECVD; + if (enet_tx_buffer.size==old_size && !tx_done) { + Log_Printf(LOG_WARN, "[EN] Sending packet: Error! Transmitter underflow (no EOP)!"); + enet_tx_interrupt(TXSTAT_UNDERFLOW); + enet_tx_buffer.size=0; + } else if (enet_tx_buffer.size>15) { + enet_tx_buffer.size-=15; + } else if (tx_done) { + Log_Printf(LOG_WARN, "[EN] Transmitter error: Early EOP!"); + enet_tx_buffer.size=0; + tx_done = false; + } + } + if (tx_done) { + Statusbar_BlinkLed(DEVICE_LED_ENET); + Log_Printf(LOG_EN_LEVEL, "[EN] Sending packet to %02X:%02X:%02X:%02X:%02X:%02X", + enet_tx_buffer.data[0], enet_tx_buffer.data[1], enet_tx_buffer.data[2], + enet_tx_buffer.data[3], enet_tx_buffer.data[4], enet_tx_buffer.data[5]); + print_buf(enet_tx_buffer.data, enet_tx_buffer.size); + if (en_state == EN_LOOPBACK) { + /* Loop back */ + Log_Printf(LOG_WARN, "[EN] Loopback packet."); + enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); + } else { + /* Send to real world network */ + enet_slirp_input(enet_tx_buffer.data,enet_tx_buffer.size); + /* Simultaneously receive packet on thin ethernet */ + if (en_state == EN_THINWIRE) { + enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); + } + } + enet_tx_buffer.size=0; } - enet_tx_buffer.size=0; - } else { - /* Loop back */ - Log_Printf(LOG_WARN, "[EN] Loopback packet."); - enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); - enet_tx_buffer.size=0; } } } @@ -487,9 +566,18 @@ void enet_io(void) { /* AT&T ethernet controller for turbo systems */ #define TXMODE_ENABLE 0x80 #define RXMODE_ENABLE 0x80 +#define TXMODE_LOOP 0x02 +#define TXMODE_TPE 0x04 +#define ENCTRL_TPE 0x40 void EN_Control_Read(void) { // 0x02006006 - IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.reset; + Uint8 val = enet.reset; + if (ConfigureParams.Ethernet.bEthernetConnected && ConfigureParams.Ethernet.bTwistedPair) { + val &= ~ENCTRL_TPE; + } else { + val |= ENCTRL_TPE; + } + IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = val; Log_Printf(LOG_EN_REG_LEVEL,"[newEN] Control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); } @@ -499,16 +587,31 @@ void EN_Control_Write(void) { enet_reset(); } -void new_enet_io(void) { +static int new_enet_state(void) { + if (enet.tx_mode&TXMODE_LOOP) { + return EN_LOOPBACK; + } else if (ConfigureParams.Ethernet.bEthernetConnected) { + if (enet.tx_mode&TXMODE_TPE) { + if (ConfigureParams.Ethernet.bTwistedPair) { + return EN_TWISTEDPAIR; + } + } else { + if (!ConfigureParams.Ethernet.bTwistedPair) { + return EN_THINWIRE; + } + } + } + return EN_DISCONNECTED; +} + +static void new_enet_io(void) { + + en_state = new_enet_state(); + /* Receive packet */ switch (receiver_state) { case RECV_STATE_WAITING: if (enet_rx_buffer.size>0) { - if (!(enet.rx_mode&RXMODE_ENABLE)) { - Log_Printf(LOG_WARN, "[newEN] Receiver disabled. Discarding packet."); - enet_rx_buffer.size = 0; - break; /* Keep waiting until receiver is enabled */ - } Statusbar_BlinkLed(DEVICE_LED_ENET); Log_Printf(LOG_EN_LEVEL, "[newEN] Receiving packet from %02X:%02X:%02X:%02X:%02X:%02X", enet_rx_buffer.data[6], enet_rx_buffer.data[7], enet_rx_buffer.data[8], @@ -516,19 +619,19 @@ void new_enet_io(void) { print_buf(enet_rx_buffer.data, enet_rx_buffer.size); enet_rx_buffer.size+=4; enet_rx_buffer.limit+=4; + rx_chain = false; enet.rx_status&=~RXSTAT_PKT_OK; if (enet_rx_buffer.size0) { + Statusbar_BlinkLed(DEVICE_LED_ENET); + Log_Printf(LOG_EN_LEVEL, "[newEN] Sending packet to %02X:%02X:%02X:%02X:%02X:%02X", + enet_tx_buffer.data[0], enet_tx_buffer.data[1], enet_tx_buffer.data[2], + enet_tx_buffer.data[3], enet_tx_buffer.data[4], enet_tx_buffer.data[5]); + print_buf(enet_tx_buffer.data, enet_tx_buffer.size); + enet.tx_status &= ~TXSTAT_TX_RECVD; + if (en_state == EN_LOOPBACK) { + /* Loop back */ + Log_Printf(LOG_WARN, "[newEN] Loopback packet."); + enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); + } else { + /* Send to real world network */ + enet_slirp_input(enet_tx_buffer.data,enet_tx_buffer.size); + /* Simultaneously receive packet on thin ethernet */ + if (en_state == EN_THINWIRE) { + enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); + } + } + enet_tx_buffer.size=0; + enet_tx_interrupt(TXSTAT_READY); + } + } + } else { /* disconnected - strange, but required by ROM and 2.2 kernel */ + if (ConfigureParams.Ethernet.bEthernetConnected) { + if (!ConfigureParams.Ethernet.bTwistedPair) { + enet_tx_interrupt(TXSTAT_READY); } - enet_tx_buffer.size=0; - enet_tx_interrupt(TXSTAT_READY); } } + enet.tx_status |= TXSTAT_READY; /* really? */ } } @@ -611,7 +730,7 @@ void ENET_IO_Handler(void) { enet_io(); } - CycInt_AddRelativeInterrupt(receiver_state==RECV_STATE_WAITING?ENET_IO_DELAY:ENET_IO_SHORT, INT_CPU_CYCLE, INTERRUPT_ENET_IO); + CycInt_AddRelativeInterruptUs(receiver_state==RECV_STATE_WAITING?ENET_IO_DELAY:ENET_IO_SHORT, 0, INTERRUPT_ENET_IO); } void enet_reset(void) { @@ -620,7 +739,7 @@ void enet_reset(void) { } else if (enet_stopped==true) { Log_Printf(LOG_WARN, "Starting Ethernet Transmitter/Receiver"); enet_stopped=false; - CycInt_AddRelativeInterrupt(ENET_IO_DELAY, INT_CPU_CYCLE, INTERRUPT_ENET_IO); + CycInt_AddRelativeInterruptUs(ENET_IO_DELAY, 0, INTERRUPT_ENET_IO); /* Start SLIRP */ if (ConfigureParams.Ethernet.bEthernetConnected) { enet_slirp_start(); @@ -634,6 +753,7 @@ void Ethernet_Reset(bool hard) { enet_stopped=true; enet_rx_buffer.size=enet_tx_buffer.size=0; enet_rx_buffer.limit=enet_tx_buffer.limit=64*1024; + enet.tx_status=ConfigureParams.System.bTurbo?0:TXSTAT_READY; /* Stop SLIRP */ enet_slirp_stop(); } else {