1/1

|
[or1ksim #27] Cleanup Ethernet peripheral
by Unknown on Feb 5, 2005 |
Not available! | ||
|
Hi,
This cleans up the ethernet peripheral. I have only done some very simple
optimistion of the eth_clock callback. I'm convinced that the
ethernet_{t,r}x_clock functions could be called less but that would require a
deeper understanding of the core. I'll probably revisit this peripheral
sometime later, but for now this should do.
ChangeLog:
* Cleanup ethernet peripheral, useing the new callbacks.
nog.
-------------- next part --------------
--- peripheral/ethernet.h 2002-07-12 20:20:26.000000000 +0200
+++ ../or1ksim-ac/peripheral/ethernet.h 2005-02-05 15:00:24.000000000 +0100
@@ -21,12 +21,6 @@
#ifndef __OR1KSIM_PERIPHERAL_ETHERNET_H
#define __OR1KSIM_PERIPHERAL_ETHERNET_H
-/* Exported function prototypes */
-void eth_reset( void );
-void eth_clock( void );
-void eth_status( void );
-
-
/* Address space required by one Ethernet MAC */
#define ETH_ADDR_SPACE 0x1000
--- peripheral/ethernet_i.h 2005-02-05 11:25:59.000000000 +0100
+++ ../or1ksim-ac/peripheral/ethernet_i.h 2005-02-05 13:22:29.000000000 +0100
@@ -131,9 +123,6 @@
/* Base address in memory */
oraddr_t baseaddr;
- /* Which Ethernet MAC is this? */
- unsigned eth_number;
-
/* Which DMA controller is this MAC connected to */
unsigned dma;
unsigned tx_channel;
@@ -149,11 +138,14 @@
unsigned long base_vapi_id;
/* RX and TX file names and handles */
- const char *rxfile, *txfile;
+ char *rxfile, *txfile;
int txfd;
int rxfd;
off_t loopback_offset;
+ /* Socket interface name */
+ char *sockif;
+
int rtx_sock;
int rtx_type;
struct ifreq ifr;
--- sim-config.c 2005-02-05 15:08:17.000000000 +0100
+++ ../or1ksim-ac/sim-config.c 2005-02-05 15:03:54.000000000 +0100
@@ -144,9 +146,6 @@
config.vapi.enabled = 0;
strcpy (config.vapi.vapi_fn, "vapi.log");
- /* Ethernet */
- config.nethernets = 0;
-
/* GPIO */
config.ngpios = 0;
@@ -895,16 +899,6 @@
fprintf (f, " tick:{enabled:%i},\n", config.tick.enabled);
- fprintf (f, " nethernets:%i, ethernets:{", config.nethernets);
- comma = 0;
- for (i = 0; i next;
}
- eth_reset();
gpio_reset();
tick_reset();
pm_reset();
@@ -442,7 +440,6 @@
if (config.ic.enabled) ic_clock();
}
- if (config.ethernets) eth_clock();
if (config.ngpios) gpio_clock();
if (config.vapi.enabled && runtime.vapi.enabled) vapi_check();
if (config.debug.gdb_enabled) HandleServerSocket(false); /* block & check_stdin = false */
--- sim.cfg 2005-02-05 15:12:54.000000000 +0100
+++ ../or1ksim-ac/sim.cfg 2005-02-05 15:13:18.000000000 +0100
@@ -663,11 +663,6 @@
This section configures the ETHERNETs
- nethernets =
- make specified number of instances, configure each
- instance within device - enddevice construct.
-
- instance specific:
baseaddr =
address of first ethernet register for this device
@@ -700,19 +695,15 @@
*/
section ethernet
- nethernets = 1
-
- device 0
- baseaddr = 0x92000000
- dma = 0
- irq = 4
- rtx_type = 1
- tx_channel = 0
- rx_channel = 1
- rxfile = "eth0.rx"
- txfile = "eth0.tx"
- sockif = "eth0"
- enddevice
+ baseaddr = 0x92000000
+ dma = 0
+ irq = 4
+ rtx_type = 1
+ tx_channel = 0
+ rx_channel = 1
+ rxfile = "eth0.rx"
+ txfile = "eth0.tx"
+ sockif = "eth0"
end
--- peripheral/eth.c 2005-02-05 11:26:14.000000000 +0100
+++ ../or1ksim-ac/peripheral/eth.c 2005-02-05 15:42:42.000000000 +0100
@@ -48,22 +48,20 @@
#include "crc32.h"
#include "vapi.h"
#include "pic.h"
+#include "sched.h"
#include "debug.h"
-static struct eth_device eths[MAX_ETHERNETS];
+DEFAULT_DEBUG_CHANNEL(eth);
/* simulator interface */
-static void eth_reset_controller( struct eth_device *eth);
static void eth_vapi_read( unsigned long id, unsigned long data, void *dat);
/* register interface */
static void eth_write32( oraddr_t addr, uint32_t value, void *dat );
static uint32_t eth_read32( oraddr_t addr, void *dat );
/* clock */
-static void eth_controller_tx_clock( struct eth_device * );
-static void eth_controller_rx_clock( struct eth_device * );
+static void eth_controller_tx_clock( void * );
+static void eth_controller_rx_clock( void * );
/* utility functions */
-static int eth_find_controller( oraddr_t addr, struct eth_device **eth, oraddr_t *reladdr );
-struct eth_device *eth_find_vapi_device (unsigned long id, unsigned long *which);
static ssize_t eth_read_rx_file( struct eth_device *, void *, size_t );
static void eth_skip_rx_file( struct eth_device *, off_t );
static void eth_rewind_rx_file( struct eth_device *, off_t );
@@ -77,8 +75,9 @@
* TX clock
* Responsible for starting and finishing TX
*/
-void eth_controller_tx_clock( struct eth_device *eth )
+void eth_controller_tx_clock( void *dat )
{
+ struct eth_device *eth = dat;
int breakpoint = 0;
int bAdvance = 1;
#if HAVE_ETH_PHY
@@ -88,13 +87,9 @@
unsigned long read_word;
switch (eth->tx.state) {
- case ETH_TXSTATE_IDLE:
- if ( TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) ) {
-
- /* wait for TxBuffer to be ready */
- debug (3, "TX - entering state WAIT4BD (%ld)\n", eth->tx.bd_index);
- eth->tx.state = ETH_TXSTATE_WAIT4BD;
- }
+ case ETH_TXSTATE_IDLE:
+ debug (3, "TX - entering state WAIT4BD (%ld)\n", eth->tx.bd_index);
+ eth->tx.state = ETH_TXSTATE_WAIT4BD;
break;
case ETH_TXSTATE_WAIT4BD:
/* Read buffer descriptor */
@@ -156,11 +151,6 @@
debug (3, "TX - entering state READFIFO\n");
eth->tx.state = ETH_TXSTATE_READFIFO;
}
- else if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) ) {
- /* stop TX logic */
- debug (3, "TX - entering state IDLE\n");
- eth->tx.state = ETH_TXSTATE_IDLE;
- }
/* stay in this state if (TXEN && !READY) */
break;
@@ -205,8 +195,8 @@
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
- debug (3, "TX - entering state IDLE\n");
- eth->tx.state = ETH_TXSTATE_IDLE;
+ debug (3, "TX - entering state WAIT4BD\n");
+ eth->tx.state = ETH_TXSTATE_WAIT4BD;
debug (3, "send (%ld)bytes OK\n", nwritten);
}
else {
@@ -216,8 +206,8 @@
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
- debug (3, "TX - entering state IDLE\n");
- eth->tx.state = ETH_TXSTATE_IDLE;
+ debug (3, "TX - entering state WAIT4BD\n");
+ eth->tx.state = ETH_TXSTATE_WAIT4BD;
debug (3, "send FAILED!\n");
}
@@ -242,6 +232,9 @@
break;
}
+
+ /* Reschedule */
+ SCHED_ADD( eth_controller_tx_clock, dat, runtime.sim.cycles + 1 );
}
/* ========================================================================= */
@@ -254,8 +247,9 @@
* RX clock
* Responsible for starting and finishing RX
*/
-void eth_controller_rx_clock( struct eth_device *eth )
+void eth_controller_rx_clock( void *dat )
{
+ struct eth_device *eth = dat;
int breakpoint = 0;
long nread;
unsigned long send_word;
@@ -263,10 +257,8 @@
switch (eth->rx.state) {
case ETH_RXSTATE_IDLE:
- if ( TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) ) {
- debug (3, "RX - entering state WAIT4BD (%ld)\n", eth->rx.bd_index);
- eth->rx.state = ETH_RXSTATE_WAIT4BD;
- }
+ debug (3, "RX - entering state WAIT4BD (%ld)\n", eth->rx.bd_index);
+ eth->rx.state = ETH_RXSTATE_WAIT4BD;
break;
case ETH_RXSTATE_WAIT4BD:
@@ -328,8 +320,8 @@
debug( 3, "eth_start_rx(): Packet too small\n" );
eth_rx_next_packet( eth );
- debug (3, "RX - entering state IDLE\n");
- eth->rx.state = ETH_RXSTATE_IDLE;
+ debug (3, "RX - entering state WAIT4BD\n");
+ eth->rx.state = ETH_RXSTATE_WAIT4BD;
break;
}
@@ -442,6 +434,9 @@
}
break;
}
+
+ /* Reschedule */
+ SCHED_ADD( eth_controller_rx_clock, dat, runtime.sim.cycles + 1 );
}
/* ========================================================================= */
@@ -496,61 +491,18 @@
Reset. Initializes all registers to default and places devices in
memory address space.
*/
-void eth_reset()
-{
- static int first_time = 1;
- unsigned i;
-
- if (!config.nethernets)
- return;
-
- if ( first_time )
- memset( eths, 0, sizeof(eths) );
-
- for ( i = 0; i rtx_type == ETH_RTX_SOCK) {
- fprintf (stderr, "Ethernet phy not enabled in this configuration. Configure with --enable-ethphy.\n");
- exit (1);
- }
- eth->eth_number = i;
- eth_reset_controller( eth );
- if ( eth->baseaddr && first_time )
- register_memoryarea( eth->baseaddr, ETH_ADDR_SPACE, 4, 0, eth_read32, eth_write32, NULL );
- }
-
- if ( first_time )
- first_time = 0;
-}
-
-/* ========================================================================= */
-
-
-static void eth_reset_controller(struct eth_device *eth)
+void eth_reset(void *dat)
{
- int i = eth->eth_number;
+ struct eth_device *eth = dat;
#if HAVE_ETH_PHY
int j;
struct sockaddr_ll sll;
#endif /* HAVE_ETH_PHY */
- eth->baseaddr = config.ethernets.baseaddr;
-
if ( eth->baseaddr != 0 ) {
- /* Mark which DMA controller and channels */
- eth->dma = config.ethernets.dma;
- eth->mac_int = config.ethernets.irq;
- eth->tx_channel = config.ethernets.tx_channel;
- eth->rx_channel = config.ethernets.rx_channel;
- eth->rtx_type = config.ethernets.rtx_type;
-
switch (eth->rtx_type) {
case ETH_RTX_FILE:
/* (Re-)open TX/RX files */
- eth->rxfile = config.ethernets.rxfile;
- eth->txfile = config.ethernets.txfile;
-
if ( eth->rxfd > 0 )
close( eth->rxfd );
if ( eth->txfd > 0 )
@@ -587,7 +539,7 @@
/* get interface index number */
debug (3, "RTX getting interface...\n");
memset(&(eth->ifr), 0, sizeof(eth->ifr));
- strncpy(eth->ifr.ifr_name, config.ethernets.sockif, IFNAMSIZ);
+ strncpy(eth->ifr.ifr_name, eth->sockif, IFNAMSIZ);
if (ioctl(eth->rtx_sock, SIOCGIFINDEX, &(eth->ifr)) == -1) {
fprintf( stderr, "SIOCGIFINDEX failed!\n");
return;
@@ -622,6 +574,11 @@
debug (3, "\n");
break;
+#else /* HAVE_ETH_PHY */
+ case ETH_RTX_SOCK:
+ fprintf (stderr, "Ethernet phy not enabled in this configuration. Configure with --enable-ethphy.\n");
+ exit (1);
+ break;
#endif /* HAVE_ETH_PHY */
}
@@ -642,9 +599,8 @@
eth->rx.bd_index = eth->regs.tx_bd_num base_vapi_id = config.ethernets.base_vapi_id;
- vapi_install_multi_handler( eth->base_vapi_id, ETH_NUM_VAPI_IDS, eth_vapi_read, NULL );
+ if (eth->base_vapi_id) {
+ vapi_install_multi_handler( eth->base_vapi_id, ETH_NUM_VAPI_IDS, eth_vapi_read, dat );
}
}
}
@@ -654,54 +610,32 @@
/*
Print register values on stdout
*/
-void eth_status( void )
+void eth_status( void *dat )
{
- unsigned i;
-
- for ( i = 0; i baseaddr == 0 )
- continue;
-
- PRINTF( "\nEthernet MAC %u at 0x%"PRIxADDR":\n", i, eth->baseaddr );
- PRINTF( "MODER : 0x%08lX\n", eth->regs.moder );
- PRINTF( "INT_SOURCE : 0x%08lX\n", eth->regs.int_source );
- PRINTF( "INT_MASK : 0x%08lX\n", eth->regs.int_mask );
- PRINTF( "IPGT : 0x%08lX\n", eth->regs.ipgt );
- PRINTF( "IPGR1 : 0x%08lX\n", eth->regs.ipgr1 );
- PRINTF( "IPGR2 : 0x%08lX\n", eth->regs.ipgr2 );
- PRINTF( "PACKETLEN : 0x%08lX\n", eth->regs.packetlen );
- PRINTF( "COLLCONF : 0x%08lX\n", eth->regs.collconf );
- PRINTF( "TX_BD_NUM : 0x%08lX\n", eth->regs.tx_bd_num );
- PRINTF( "CTRLMODER : 0x%08lX\n", eth->regs.controlmoder );
- PRINTF( "MIIMODER : 0x%08lX\n", eth->regs.miimoder );
- PRINTF( "MIICOMMAND : 0x%08lX\n", eth->regs.miicommand );
- PRINTF( "MIIADDRESS : 0x%08lX\n", eth->regs.miiaddress );
- PRINTF( "MIITX_DATA : 0x%08lX\n", eth->regs.miitx_data );
- PRINTF( "MIIRX_DATA : 0x%08lX\n", eth->regs.miirx_data );
- PRINTF( "MIISTATUS : 0x%08lX\n", eth->regs.miistatus );
- PRINTF( "MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\n",
- eth->mac_address[0], eth->mac_address[1], eth->mac_address[2],
- eth->mac_address[3], eth->mac_address[4], eth->mac_address[5] );
- PRINTF( "HASH0 : 0x%08lX\n", eth->regs.hash0 );
- PRINTF( "HASH1 : 0x%08lX\n", eth->regs.hash1 );
- }
-}
-/* ========================================================================= */
-
-
-/*
- Simulation hook. Must be called every clock cycle to simulate Ethernet MAC.
-*/
-void eth_clock()
-{
- unsigned i;
-
- for ( i = 0; i baseaddr );
+ PRINTF( "MODER : 0x%08lX\n", eth->regs.moder );
+ PRINTF( "INT_SOURCE : 0x%08lX\n", eth->regs.int_source );
+ PRINTF( "INT_MASK : 0x%08lX\n", eth->regs.int_mask );
+ PRINTF( "IPGT : 0x%08lX\n", eth->regs.ipgt );
+ PRINTF( "IPGR1 : 0x%08lX\n", eth->regs.ipgr1 );
+ PRINTF( "IPGR2 : 0x%08lX\n", eth->regs.ipgr2 );
+ PRINTF( "PACKETLEN : 0x%08lX\n", eth->regs.packetlen );
+ PRINTF( "COLLCONF : 0x%08lX\n", eth->regs.collconf );
+ PRINTF( "TX_BD_NUM : 0x%08lX\n", eth->regs.tx_bd_num );
+ PRINTF( "CTRLMODER : 0x%08lX\n", eth->regs.controlmoder );
+ PRINTF( "MIIMODER : 0x%08lX\n", eth->regs.miimoder );
+ PRINTF( "MIICOMMAND : 0x%08lX\n", eth->regs.miicommand );
+ PRINTF( "MIIADDRESS : 0x%08lX\n", eth->regs.miiaddress );
+ PRINTF( "MIITX_DATA : 0x%08lX\n", eth->regs.miitx_data );
+ PRINTF( "MIIRX_DATA : 0x%08lX\n", eth->regs.miirx_data );
+ PRINTF( "MIISTATUS : 0x%08lX\n", eth->regs.miistatus );
+ PRINTF( "MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\n",
+ eth->mac_address[0], eth->mac_address[1], eth->mac_address[2],
+ eth->mac_address[3], eth->mac_address[4], eth->mac_address[5] );
+ PRINTF( "HASH0 : 0x%08lX\n", eth->regs.hash0 );
+ PRINTF( "HASH1 : 0x%08lX\n", eth->regs.hash1 );
}
/* ========================================================================= */
@@ -711,11 +645,8 @@
*/
uint32_t eth_read32( oraddr_t addr, void *dat )
{
- struct eth_device *eth;
- if ( !eth_find_controller( addr, ð, &addr ) ) {
- PRINTF( "eth_read32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr );
- return 0;
- }
+ struct eth_device *eth = dat;
+ addr -= eth->baseaddr;
switch( addr ) {
case ETH_MODER: return eth->regs.moder;
@@ -761,14 +692,30 @@
*/
void eth_write32( oraddr_t addr, uint32_t value, void *dat )
{
- struct eth_device *eth;
- if ( !eth_find_controller( addr, ð, &addr ) ) {
- PRINTF( "eth_write32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr );
- return;
- }
-
+ struct eth_device *eth = dat;
+
+ addr -= eth->baseaddr;
+
switch( addr ) {
- case ETH_MODER: eth->regs.moder = value; if (TEST_FLAG(value, ETH_MODER, RST)) eth_reset(); return;
+ case ETH_MODER:
+
+ if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) &&
+ TEST_FLAG( value, ETH_MODER, RXEN) )
+ SCHED_ADD( eth_controller_rx_clock, dat, runtime.sim.cycles + 1 );
+ else if ( !TEST_FLAG( value, ETH_MODER, RXEN) )
+ SCHED_FIND_REMOVE( eth_controller_rx_clock, dat);
+
+ if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN) &&
+ TEST_FLAG( value, ETH_MODER, TXEN) )
+ SCHED_ADD( eth_controller_tx_clock, dat, runtime.sim.cycles + 1 );
+ else if ( !TEST_FLAG( value, ETH_MODER, TXEN) )
+ SCHED_FIND_REMOVE( eth_controller_tx_clock, dat);
+
+ eth->regs.moder = value;
+
+ if (TEST_FLAG(value, ETH_MODER, RST))
+ eth_reset( dat );
+ return;
case ETH_INT_SOURCE: eth->regs.int_source &= ~value; return;
case ETH_INT_MASK: eth->regs.int_mask = value; return;
case ETH_IPGT: eth->regs.ipgt = value; return;
@@ -819,7 +766,9 @@
static void eth_vapi_read (unsigned long id, unsigned long data, void *dat)
{
unsigned long which;
- struct eth_device *eth = eth_find_vapi_device( id, &which );
+ struct eth_device *eth = dat;
+
+ which = id - eth->base_vapi_id;
debug( 5, "ETH: id %08lx, data %08lx\n", id, data );
@@ -844,142 +793,105 @@
eth->regs.tx_bd_num = value & 0xFF;
eth->rx.bd_index = eth->regs.tx_bd_num = eths.baseaddr) && (addr baseaddr) % 4 != 0 )
- return 0;
-
- *reladdr = addr - (*eth)->baseaddr;
- return 1;
+ struct eth_device *eth = dat;
+ eth->baseaddr = val.addr_val;
}
-/*
- * Convert VAPI id to controller struct and relative address.
- */
-struct eth_device *eth_find_vapi_device( unsigned long id, unsigned long *which )
+void eth_dma(union param_val val, void *dat)
{
- unsigned i;
-
- for ( i=0; i=eths.base_vapi_id) && (id = 0 && val.int_val = 0 && current_device dma = val.addr_val;
}
-void eth_dma (union param_val val, void *dat) {
- if (current_device >= 0 && current_device = 0 && current_device rtx_type = val.int_val;
}
-void eth_rx_channel (union param_val val, void *dat) {
- if (current_device >= 0 && current_device rx_channel = val.int_val;
}
-void eth_tx_channel (union param_val val, void *dat) {
- if (current_device >= 0 && current_device tx_channel = val.int_val;
}
-void eth_rxfile (union param_val val, void *dat) {
- if (current_device >= 0 && current_device rxfile = strdup(val.str_val))) {
+ fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
+ exit(-1);
+ }
}
void eth_txfile(union param_val val, void *dat)
{
- if (current_device >= 0 && current_device txfile = strdup(val.str_val))) {
+ fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
+ exit(-1);
+ }
}
void eth_sockif(union param_val val, void *dat)
{
- if (current_device >= 0 && current_device sockif = strdup(val.str_val))) {
+ fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
+ exit(-1);
+ }
}
void eth_irq(union param_val val, void *dat)
{
- if (current_device >= 0 && current_device mac_int = val.int_val;
}
void eth_vapi_id(union param_val val, void *dat)
{
- if (current_device >= 0 && current_device base_vapi_id = val.int_val;
+}
+
+void *eth_sec_start(void)
+{
+ struct eth_device *new = malloc(sizeof(struct eth_device));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral Eth: Run out of memory\n");
+ exit(-1);
+ }
+
+ return new;
+}
+
+void eth_sec_end(void *dat)
+{
+ struct eth_device *eth = dat;
+
+ register_memoryarea( eth->baseaddr, ETH_ADDR_SPACE, 4, 0, eth_read32, eth_write32, dat );
+ reg_sim_stat( eth_status, dat );
+ reg_sim_reset( eth_reset, dat );
}
void reg_ethernet_sec(void)
{
- struct config_section *sec = reg_config_sec("ethernet", NULL, NULL);
+ struct config_section *sec = reg_config_sec("ethernet", eth_sec_start, eth_sec_end);
- reg_config_param(sec, "nethernets", paramt_int, eth_nethernets);
- reg_config_param(sec, "device", paramt_int, change_device);
reg_config_param(sec, "irq", paramt_int, eth_irq);
- reg_config_param(sec, "enddevice", paramt_int, end_device);
reg_config_param(sec, "baseaddr", paramt_int, eth_baseaddr);
reg_config_param(sec, "dma", paramt_int, eth_dma);
reg_config_param(sec, "rtx_type", paramt_int, eth_rtx_type);
|
|||
1/1

