OpenCores
no use no use 1/1 no use no use
[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, &eth, &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, &eth, &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);
no use no use 1/1 no use no use
© copyright 1999-2026 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.