OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_52/] [or1ksim/] [peripheral/] [eth.c] - Diff between revs 1429 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1429 Rev 1765
/* ethernet.c -- Simulation of Ethernet MAC
/* ethernet.c -- Simulation of Ethernet MAC
   Copyright (C) 2001 by Erez Volk, erez@opencores.org
   Copyright (C) 2001 by Erez Volk, erez@opencores.org
                         Ivan Guzvinec, ivang@opencores.org
                         Ivan Guzvinec, ivang@opencores.org
 
 
   This file is part of OpenRISC 1000 Architectural Simulator.
   This file is part of OpenRISC 1000 Architectural Simulator.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
*/
 
 
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>   
#include <sys/stat.h>   
#include <fcntl.h>      
#include <fcntl.h>      
#include <sys/poll.h>   
#include <sys/poll.h>   
#include <sys/time.h>   
#include <sys/time.h>   
#include <unistd.h>     
#include <unistd.h>     
#include <errno.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/in.h>
 
 
#include "config.h"
#include "config.h"
 
 
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#endif
 
 
#include "port.h"
#include "port.h"
#include "arch.h"
#include "arch.h"
#include "config.h"
#include "config.h"
#include "abstract.h"
#include "abstract.h"
#include "ethernet_i.h"
#include "ethernet_i.h"
#include "dma.h"
#include "dma.h"
#include "sim-config.h"
#include "sim-config.h"
#include "fields.h"
#include "fields.h"
#include "crc32.h"
#include "crc32.h"
#include "vapi.h"
#include "vapi.h"
#include "pic.h"
#include "pic.h"
#include "sched.h"
#include "sched.h"
#include "debug.h"
#include "debug.h"
 
 
/* simulator interface */
/* simulator interface */
static void eth_vapi_read( unsigned long id, unsigned long data, void *dat);
static void eth_vapi_read( unsigned long id, unsigned long data, void *dat);
/* register interface */
/* register interface */
static void eth_write32( oraddr_t addr, uint32_t value, void *dat );
static void eth_write32( oraddr_t addr, uint32_t value, void *dat );
static uint32_t eth_read32( oraddr_t addr, void *dat );
static uint32_t eth_read32( oraddr_t addr, void *dat );
/* clock */
/* clock */
static void eth_controller_tx_clock( void * );
static void eth_controller_tx_clock( void * );
static void eth_controller_rx_clock( void * );
static void eth_controller_rx_clock( void * );
/* utility functions */
/* utility functions */
static ssize_t eth_read_rx_file( struct eth_device *, void *, size_t );
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_skip_rx_file( struct eth_device *, off_t );
static void eth_rewind_rx_file( struct eth_device *, off_t );
static void eth_rewind_rx_file( struct eth_device *, off_t );
static void eth_rx_next_packet( struct eth_device * );
static void eth_rx_next_packet( struct eth_device * );
static void eth_write_tx_bd_num( struct eth_device *, unsigned long value );
static void eth_write_tx_bd_num( struct eth_device *, unsigned long value );
/* ========================================================================= */
/* ========================================================================= */
/*  TX LOGIC                                                                 */
/*  TX LOGIC                                                                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
 
 
/*
/*
 * TX clock
 * TX clock
 * Responsible for starting and finishing TX
 * Responsible for starting and finishing TX
 */
 */
void eth_controller_tx_clock( void *dat )
void eth_controller_tx_clock( void *dat )
{
{
    struct eth_device *eth = dat;
    struct eth_device *eth = dat;
    int breakpoint = 0;
    int breakpoint = 0;
    int bAdvance   = 1;
    int bAdvance   = 1;
#if HAVE_ETH_PHY
#if HAVE_ETH_PHY
    struct sockaddr_ll sll;
    struct sockaddr_ll sll;
#endif /* HAVE_ETH_PHY */
#endif /* HAVE_ETH_PHY */
    long nwritten;
    long nwritten;
    unsigned long read_word;
    unsigned long read_word;
 
 
    switch (eth->tx.state) {
    switch (eth->tx.state) {
    case ETH_TXSTATE_IDLE:
    case ETH_TXSTATE_IDLE:
        debug (3, "TX - entering state WAIT4BD (%ld)\n", eth->tx.bd_index);
        debug (3, "TX - entering state WAIT4BD (%ld)\n", eth->tx.bd_index);
        eth->tx.state = ETH_TXSTATE_WAIT4BD;
        eth->tx.state = ETH_TXSTATE_WAIT4BD;
        break;
        break;
    case ETH_TXSTATE_WAIT4BD:
    case ETH_TXSTATE_WAIT4BD:
        /* Read buffer descriptor */
        /* Read buffer descriptor */
        eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index];
        eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index];
        eth->tx.bd_addr = eth->regs.bd_ram[eth->tx.bd_index + 1];
        eth->tx.bd_addr = eth->regs.bd_ram[eth->tx.bd_index + 1];
 
 
        if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, READY ) ) {
        if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, READY ) ) {
            /*****************/
            /*****************/
            /* initialize TX */
            /* initialize TX */
            eth->tx.bytes_left = eth->tx.packet_length = GET_FIELD( eth->tx.bd, ETH_TX_BD, LENGTH );
            eth->tx.bytes_left = eth->tx.packet_length = GET_FIELD( eth->tx.bd, ETH_TX_BD, LENGTH );
            eth->tx.bytes_sent = 0;
            eth->tx.bytes_sent = 0;
 
 
            /*   Initialize error status bits */
            /*   Initialize error status bits */
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, DEFER );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, DEFER );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, COLLISION );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, COLLISION );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, RETRANSMIT );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, RETRANSMIT );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, UNDERRUN );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, UNDERRUN );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, NO_CARRIER );
            CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, NO_CARRIER );
            SET_FIELD ( eth->tx.bd, ETH_TX_BD, RETRY, 0 );
            SET_FIELD ( eth->tx.bd, ETH_TX_BD, RETRY, 0 );
 
 
            /* Find out minimum length */
            /* Find out minimum length */
            if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, PAD ) ||
            if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, PAD ) ||
                 TEST_FLAG( eth->regs.moder, ETH_MODER, PAD ) )
                 TEST_FLAG( eth->regs.moder, ETH_MODER, PAD ) )
                eth->tx.minimum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL );
                eth->tx.minimum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL );
            else
            else
                eth->tx.minimum_length = eth->tx.packet_length;
                eth->tx.minimum_length = eth->tx.packet_length;
 
 
            /* Find out maximum length */
            /* Find out maximum length */
            if ( TEST_FLAG( eth->regs.moder, ETH_MODER, HUGEN ) )
            if ( TEST_FLAG( eth->regs.moder, ETH_MODER, HUGEN ) )
                eth->tx.maximum_length = eth->tx.packet_length;
                eth->tx.maximum_length = eth->tx.packet_length;
            else
            else
                eth->tx.maximum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL );
                eth->tx.maximum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL );
 
 
            /* Do we need CRC on this packet? */
            /* Do we need CRC on this packet? */
            if ( TEST_FLAG( eth->regs.moder, ETH_MODER, CRCEN ) ||
            if ( TEST_FLAG( eth->regs.moder, ETH_MODER, CRCEN ) ||
                 (TEST_FLAG( eth->tx.bd, ETH_TX_BD, CRC) &&
                 (TEST_FLAG( eth->tx.bd, ETH_TX_BD, CRC) &&
                  TEST_FLAG( eth->tx.bd, ETH_TX_BD, LAST)) )
                  TEST_FLAG( eth->tx.bd, ETH_TX_BD, LAST)) )
                eth->tx.add_crc = 1;
                eth->tx.add_crc = 1;
            else
            else
                eth->tx.add_crc = 0;
                eth->tx.add_crc = 0;
 
 
            if ( TEST_FLAG( eth->regs.moder, ETH_MODER, DLYCRCEN ) )
            if ( TEST_FLAG( eth->regs.moder, ETH_MODER, DLYCRCEN ) )
                eth->tx.crc_dly = 1;
                eth->tx.crc_dly = 1;
            else
            else
                eth->tx.crc_dly = 0;
                eth->tx.crc_dly = 0;
            /* XXX - For now we skip CRC calculation */
            /* XXX - For now we skip CRC calculation */
 
 
            debug( 3, "Ethernet: Starting TX of %lu bytes (min. %u, max. %u)\n",
            debug( 3, "Ethernet: Starting TX of %lu bytes (min. %u, max. %u)\n",
                   eth->tx.packet_length, eth->tx.minimum_length,
                   eth->tx.packet_length, eth->tx.minimum_length,
                   eth->tx.maximum_length );
                   eth->tx.maximum_length );
 
 
            if (eth->rtx_type == ETH_RTX_FILE) {
            if (eth->rtx_type == ETH_RTX_FILE) {
                /* write packet length to file */
                /* write packet length to file */
                nwritten = write( eth->txfd, &(eth->tx.packet_length), sizeof(eth->tx.packet_length) );
                nwritten = write( eth->txfd, &(eth->tx.packet_length), sizeof(eth->tx.packet_length) );
            }
            }
 
 
            /************************************************/
            /************************************************/
            /* start transmit with reading packet into FIFO */
            /* start transmit with reading packet into FIFO */
                debug (3, "TX - entering state READFIFO\n");
                debug (3, "TX - entering state READFIFO\n");
            eth->tx.state = ETH_TXSTATE_READFIFO;
            eth->tx.state = ETH_TXSTATE_READFIFO;
        }
        }
 
 
        /* stay in this state if (TXEN && !READY) */
        /* stay in this state if (TXEN && !READY) */
        break;
        break;
    case ETH_TXSTATE_READFIFO:
    case ETH_TXSTATE_READFIFO:
#if 1
#if 1
        if ( eth->tx.bytes_sent < eth->tx.packet_length ) {
        if ( eth->tx.bytes_sent < eth->tx.packet_length ) {
            read_word = eval_direct32(eth->tx.bytes_sent + eth->tx.bd_addr, &breakpoint, 0, 0);
            read_word = eval_direct32(eth->tx.bytes_sent + eth->tx.bd_addr, &breakpoint, 0, 0);
            eth->tx_buff[eth->tx.bytes_sent]   = (unsigned char)(read_word >> 24);
            eth->tx_buff[eth->tx.bytes_sent]   = (unsigned char)(read_word >> 24);
            eth->tx_buff[eth->tx.bytes_sent+1] = (unsigned char)(read_word >> 16);
            eth->tx_buff[eth->tx.bytes_sent+1] = (unsigned char)(read_word >> 16);
            eth->tx_buff[eth->tx.bytes_sent+2] = (unsigned char)(read_word >> 8);
            eth->tx_buff[eth->tx.bytes_sent+2] = (unsigned char)(read_word >> 8);
            eth->tx_buff[eth->tx.bytes_sent+3] = (unsigned char)(read_word);
            eth->tx_buff[eth->tx.bytes_sent+3] = (unsigned char)(read_word);
            eth->tx.bytes_sent += 4;
            eth->tx.bytes_sent += 4;
        }
        }
#else
#else
        if ( eth->tx.bytes_sent < eth->tx.packet_length ) {
        if ( eth->tx.bytes_sent < eth->tx.packet_length ) {
            eth->tx_buff[eth->tx.bytes_sent] = eval_direct8(eth->tx.bytes_sent + eth->tx.bd_addr, &breakpoint, 0, 0);
            eth->tx_buff[eth->tx.bytes_sent] = eval_direct8(eth->tx.bytes_sent + eth->tx.bd_addr, &breakpoint, 0, 0);
            eth->tx.bytes_sent += 1;
            eth->tx.bytes_sent += 1;
        }
        }
#endif
#endif
        else {
        else {
            debug (3, "TX - entering state TRANSMIT\n");
            debug (3, "TX - entering state TRANSMIT\n");
            eth->tx.state = ETH_TXSTATE_TRANSMIT;
            eth->tx.state = ETH_TXSTATE_TRANSMIT;
        }
        }
        break;
        break;
    case ETH_TXSTATE_TRANSMIT:
    case ETH_TXSTATE_TRANSMIT:
        /* send packet */
        /* send packet */
        switch (eth->rtx_type) {
        switch (eth->rtx_type) {
        case ETH_RTX_FILE:
        case ETH_RTX_FILE:
            nwritten = write( eth->txfd, eth->tx_buff, eth->tx.packet_length );
            nwritten = write( eth->txfd, eth->tx_buff, eth->tx.packet_length );
            break;
            break;
#if HAVE_ETH_PHY
#if HAVE_ETH_PHY
        case ETH_RTX_SOCK:
        case ETH_RTX_SOCK:
            memset(&sll, 0, sizeof(sll));
            memset(&sll, 0, sizeof(sll));
            sll.sll_ifindex = eth->ifr.ifr_ifindex;
            sll.sll_ifindex = eth->ifr.ifr_ifindex;
            nwritten = sendto(eth->rtx_sock, eth->tx_buff, eth->tx.packet_length, 0, (struct sockaddr *)&sll, sizeof(sll));
            nwritten = sendto(eth->rtx_sock, eth->tx_buff, eth->tx.packet_length, 0, (struct sockaddr *)&sll, sizeof(sll));
#endif /* HAVE_ETH_PHY */
#endif /* HAVE_ETH_PHY */
        }
        }
 
 
        /* set BD status */
        /* set BD status */
        if (nwritten == eth->tx.packet_length) {
        if (nwritten == eth->tx.packet_length) {
            CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
            CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
            SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
            SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
            debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
            debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
 
 
            debug (3, "TX - entering state WAIT4BD\n");
            debug (3, "TX - entering state WAIT4BD\n");
            eth->tx.state = ETH_TXSTATE_WAIT4BD;
            eth->tx.state = ETH_TXSTATE_WAIT4BD;
            debug (3, "send (%ld)bytes OK\n", nwritten);
            debug (3, "send (%ld)bytes OK\n", nwritten);
        }
        }
        else {
        else {
            /* XXX - implement retry mechanism here! */
            /* XXX - implement retry mechanism here! */
            CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
            CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
            CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION);
            CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION);
            SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
            SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
            debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
            debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
 
 
            debug (3, "TX - entering state WAIT4BD\n");
            debug (3, "TX - entering state WAIT4BD\n");
            eth->tx.state = ETH_TXSTATE_WAIT4BD;
            eth->tx.state = ETH_TXSTATE_WAIT4BD;
            debug (3, "send FAILED!\n");
            debug (3, "send FAILED!\n");
        }
        }
 
 
        eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd;
        eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd;
 
 
        /* generate OK interrupt */
        /* generate OK interrupt */
        if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXE_M) ||
        if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXE_M) ||
             TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXB_M) )
             TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXB_M) )
        {
        {
            if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, IRQ ) )
            if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, IRQ ) )
                report_interrupt( eth->mac_int );
                report_interrupt( eth->mac_int );
        }
        }
 
 
        /* advance to next BD */
        /* advance to next BD */
        if (bAdvance) {
        if (bAdvance) {
            if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, WRAP ) ||
            if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, WRAP ) ||
                            eth->tx.bd_index >= ETH_BD_COUNT )
                            eth->tx.bd_index >= ETH_BD_COUNT )
                eth->tx.bd_index = 0;
                eth->tx.bd_index = 0;
            else
            else
                eth->tx.bd_index += 2;
                eth->tx.bd_index += 2;
        }
        }
 
 
        break;
        break;
    }
    }
 
 
    /* Reschedule */
    /* Reschedule */
    SCHED_ADD( eth_controller_tx_clock, dat, 1 );
    SCHED_ADD( eth_controller_tx_clock, dat, 1 );
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/* ========================================================================= */
/* ========================================================================= */
/*  RX LOGIC                                                                 */
/*  RX LOGIC                                                                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
 
 
/*
/*
 * RX clock
 * RX clock
 * Responsible for starting and finishing RX
 * Responsible for starting and finishing RX
 */
 */
void eth_controller_rx_clock( void *dat )
void eth_controller_rx_clock( void *dat )
{
{
    struct eth_device *eth = dat;
    struct eth_device *eth = dat;
    int breakpoint = 0;
    int breakpoint = 0;
    long nread;
    long nread;
    unsigned long send_word;
    unsigned long send_word;
 
 
 
 
    switch (eth->rx.state) {
    switch (eth->rx.state) {
    case ETH_RXSTATE_IDLE:
    case ETH_RXSTATE_IDLE:
        debug (3, "RX - entering state WAIT4BD (%ld)\n", eth->rx.bd_index);
        debug (3, "RX - entering state WAIT4BD (%ld)\n", eth->rx.bd_index);
        eth->rx.state = ETH_RXSTATE_WAIT4BD;
        eth->rx.state = ETH_RXSTATE_WAIT4BD;
        break;
        break;
 
 
    case ETH_RXSTATE_WAIT4BD:
    case ETH_RXSTATE_WAIT4BD:
        eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index];
        eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index];
        eth->rx.bd_addr = eth->regs.bd_ram[eth->rx.bd_index + 1];
        eth->rx.bd_addr = eth->regs.bd_ram[eth->rx.bd_index + 1];
 
 
        if ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, READY ) ) {
        if ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, READY ) ) {
            /*****************/
            /*****************/
            /* Initialize RX */
            /* Initialize RX */
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, MISS );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, MISS );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, INVALID );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, INVALID );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, DRIBBLE );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, DRIBBLE );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, UVERRUN );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, UVERRUN );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, COLLISION );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, COLLISION );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, TOOBIG );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, TOOBIG );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, TOOSHORT );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, TOOSHORT );
 
 
            debug( 3,  "Ethernet: Starting RX\n" );
            debug( 3,  "Ethernet: Starting RX\n" );
 
 
            /* Setup file to read from */
            /* Setup file to read from */
            if ( TEST_FLAG( eth->regs.moder, ETH_MODER, LOOPBCK ) ) {
            if ( TEST_FLAG( eth->regs.moder, ETH_MODER, LOOPBCK ) ) {
                eth->rx.fd = eth->txfd;
                eth->rx.fd = eth->txfd;
                eth->rx.offset = &(eth->loopback_offset);
                eth->rx.offset = &(eth->loopback_offset);
            } else {
            } else {
                eth->rx.fd = eth->rxfd;
                eth->rx.fd = eth->rxfd;
                eth->rx.offset = 0;
                eth->rx.offset = 0;
            }
            }
            debug (3, "RX - entering state RECV\n");
            debug (3, "RX - entering state RECV\n");
            eth->rx.state = ETH_RXSTATE_RECV;
            eth->rx.state = ETH_RXSTATE_RECV;
        }
        }
        else if (!TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN)) {
        else if (!TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN)) {
          debug (3, "RX - entering state IDLE\n");
          debug (3, "RX - entering state IDLE\n");
          eth->rx.state = ETH_RXSTATE_IDLE;
          eth->rx.state = ETH_RXSTATE_IDLE;
        }
        }
        else {
        else {
            nread = recv(eth->rtx_sock, eth->rx_buff, ETH_MAXPL, /*MSG_PEEK | */MSG_DONTWAIT);
            nread = recv(eth->rtx_sock, eth->rx_buff, ETH_MAXPL, /*MSG_PEEK | */MSG_DONTWAIT);
            if (nread > 0) {
            if (nread > 0) {
                SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
                SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
                if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, BUSY_M) )
                if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, BUSY_M) )
                  report_interrupt(eth->mac_int);
                  report_interrupt(eth->mac_int);
            }
            }
        }
        }
        break;
        break;
 
 
    case ETH_RXSTATE_RECV:
    case ETH_RXSTATE_RECV:
        switch (eth->rtx_type) {
        switch (eth->rtx_type) {
        case ETH_RTX_FILE:
        case ETH_RTX_FILE:
            /* Read packet length */
            /* Read packet length */
            if ( eth_read_rx_file( eth, &(eth->rx.packet_length), sizeof(eth->rx.packet_length) )
            if ( eth_read_rx_file( eth, &(eth->rx.packet_length), sizeof(eth->rx.packet_length) )
                     < sizeof(eth->rx.packet_length) ) {
                     < sizeof(eth->rx.packet_length) ) {
                /* TODO: just do what real ethernet would do (some kind of error state) */
                /* TODO: just do what real ethernet would do (some kind of error state) */
                debug (4, "eth_start_rx(): File does not have a packet ready for RX (len = %ld)\n", eth->rx.packet_length );
                debug (4, "eth_start_rx(): File does not have a packet ready for RX (len = %ld)\n", eth->rx.packet_length );
                runtime.sim.cont_run = 0;
                runtime.sim.cont_run = 0;
                break;
                break;
            }
            }
 
 
            /* Packet must be big enough to hold a header */
            /* Packet must be big enough to hold a header */
            if ( eth->rx.packet_length < ETHER_HDR_LEN ){
            if ( eth->rx.packet_length < ETHER_HDR_LEN ){
                debug( 3,  "eth_start_rx(): Packet too small\n" );
                debug( 3,  "eth_start_rx(): Packet too small\n" );
                eth_rx_next_packet( eth );
                eth_rx_next_packet( eth );
 
 
                debug (3, "RX - entering state WAIT4BD\n");
                debug (3, "RX - entering state WAIT4BD\n");
                eth->rx.state = ETH_RXSTATE_WAIT4BD;
                eth->rx.state = ETH_RXSTATE_WAIT4BD;
                break;
                break;
            }
            }
 
 
            eth->rx.bytes_read = 0;
            eth->rx.bytes_read = 0;
            eth->rx.bytes_left = eth->rx.packet_length;
            eth->rx.bytes_left = eth->rx.packet_length;
 
 
            /* for now Read entire packet into memory */
            /* for now Read entire packet into memory */
            nread = eth_read_rx_file( eth, eth->rx_buff, eth->rx.bytes_left );
            nread = eth_read_rx_file( eth, eth->rx_buff, eth->rx.bytes_left );
            if ( nread < eth->rx.bytes_left ) {
            if ( nread < eth->rx.bytes_left ) {
                debug (3, "Read %ld from %ld. Error!\n", nread, eth->rx.bytes_left);
                debug (3, "Read %ld from %ld. Error!\n", nread, eth->rx.bytes_left);
                eth->rx.error = 1;
                eth->rx.error = 1;
                break;
                break;
            }
            }
 
 
            eth->rx.packet_length = nread;
            eth->rx.packet_length = nread;
            eth->rx.bytes_left = nread;
            eth->rx.bytes_left = nread;
            eth->rx.bytes_read = 0;
            eth->rx.bytes_read = 0;
 
 
            debug (3, "RX - entering state WRITEFIFO\n");
            debug (3, "RX - entering state WRITEFIFO\n");
            eth->rx.state = ETH_RXSTATE_WRITEFIFO;
            eth->rx.state = ETH_RXSTATE_WRITEFIFO;
 
 
            break;
            break;
 
 
        case ETH_RTX_SOCK:
        case ETH_RTX_SOCK:
            nread = recv(eth->rtx_sock, eth->rx_buff, ETH_MAXPL, MSG_DONTWAIT);
            nread = recv(eth->rtx_sock, eth->rx_buff, ETH_MAXPL, MSG_DONTWAIT);
 
 
            if (nread == 0)
            if (nread == 0)
                break;
                break;
            else if (nread < 0) {
            else if (nread < 0) {
                if ( errno != EAGAIN ) {
                if ( errno != EAGAIN ) {
                    debug (3, "recv() FAILED!\n");
                    debug (3, "recv() FAILED!\n");
                    break;
                    break;
                }
                }
                else break;
                else break;
            }
            }
            /* If not promiscouos mode, check the destination address */
            /* If not promiscouos mode, check the destination address */
            if (!TEST_FLAG(eth->regs.moder, ETH_MODER, PRO)) {
            if (!TEST_FLAG(eth->regs.moder, ETH_MODER, PRO)) {
                if (TEST_FLAG(eth->regs.moder, ETH_MODER, IAM) && (eth->rx_buff[0] & 1)) {
                if (TEST_FLAG(eth->regs.moder, ETH_MODER, IAM) && (eth->rx_buff[0] & 1)) {
                /* Nothing for now */
                /* Nothing for now */
                }
                }
 
 
                if (eth->mac_address[5] != eth->rx_buff[0] ||
                if (eth->mac_address[5] != eth->rx_buff[0] ||
                    eth->mac_address[4] != eth->rx_buff[1] ||
                    eth->mac_address[4] != eth->rx_buff[1] ||
                    eth->mac_address[3] != eth->rx_buff[2] ||
                    eth->mac_address[3] != eth->rx_buff[2] ||
                    eth->mac_address[2] != eth->rx_buff[3] ||
                    eth->mac_address[2] != eth->rx_buff[3] ||
                    eth->mac_address[1] != eth->rx_buff[4] ||
                    eth->mac_address[1] != eth->rx_buff[4] ||
                    eth->mac_address[0] != eth->rx_buff[5])
                    eth->mac_address[0] != eth->rx_buff[5])
                    break;
                    break;
            }
            }
 
 
            eth->rx.packet_length = nread;
            eth->rx.packet_length = nread;
            eth->rx.bytes_left = nread;
            eth->rx.bytes_left = nread;
            eth->rx.bytes_read = 0;
            eth->rx.bytes_read = 0;
 
 
            debug (3, "RX - entering state WRITEFIFO\n");
            debug (3, "RX - entering state WRITEFIFO\n");
            eth->rx.state = ETH_RXSTATE_WRITEFIFO;
            eth->rx.state = ETH_RXSTATE_WRITEFIFO;
 
 
            break;
            break;
        case ETH_RTX_VAPI:
        case ETH_RTX_VAPI:
            break;
            break;
        }
        }
        break;
        break;
 
 
    case ETH_RXSTATE_WRITEFIFO:
    case ETH_RXSTATE_WRITEFIFO:
#if 1
#if 1
        send_word = ((unsigned long)eth->rx_buff[eth->rx.bytes_read]   << 24) |
        send_word = ((unsigned long)eth->rx_buff[eth->rx.bytes_read]   << 24) |
                    ((unsigned long)eth->rx_buff[eth->rx.bytes_read+1] << 16) |
                    ((unsigned long)eth->rx_buff[eth->rx.bytes_read+1] << 16) |
                    ((unsigned long)eth->rx_buff[eth->rx.bytes_read+2] << 8)  |
                    ((unsigned long)eth->rx_buff[eth->rx.bytes_read+2] << 8)  |
                    ((unsigned long)eth->rx_buff[eth->rx.bytes_read+3] );
                    ((unsigned long)eth->rx_buff[eth->rx.bytes_read+3] );
        set_direct32( eth->rx.bd_addr + eth->rx.bytes_read, send_word, &breakpoint, 0, 0);
        set_direct32( eth->rx.bd_addr + eth->rx.bytes_read, send_word, &breakpoint, 0, 0);
        /* update counters */
        /* update counters */
        debug (3, "Write %ld, left %ld - %08lXd\n", eth->rx.bytes_read,
        debug (3, "Write %ld, left %ld - %08lXd\n", eth->rx.bytes_read,
               eth->rx.bytes_left, send_word);
               eth->rx.bytes_left, send_word);
        eth->rx.bytes_left -= 4;
        eth->rx.bytes_left -= 4;
        eth->rx.bytes_read += 4;
        eth->rx.bytes_read += 4;
#else
#else
        set_direct8( eth->rx.bd_addr + eth->rx.bytes_read, eth->rx_buff[eth->rx.bytes_read], &breakpoint, 0, 0);
        set_direct8( eth->rx.bd_addr + eth->rx.bytes_read, eth->rx_buff[eth->rx.bytes_read], &breakpoint, 0, 0);
        eth->rx.bytes_left -= 1;
        eth->rx.bytes_left -= 1;
        eth->rx.bytes_read += 1;
        eth->rx.bytes_read += 1;
#endif
#endif
 
 
        if ( eth->rx.bytes_left <= 0 ) {
        if ( eth->rx.bytes_left <= 0 ) {
            /* Write result to bd */
            /* Write result to bd */
            SET_FIELD( eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length );
            SET_FIELD( eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length );
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, READY);
            CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, READY);
            SET_FLAG( eth->regs.int_source, ETH_INT_SOURCE, RXB);
            SET_FLAG( eth->regs.int_source, ETH_INT_SOURCE, RXB);
            debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
            debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
 
 
            if ( eth->rx.packet_length < (GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL ) - 4) )
            if ( eth->rx.packet_length < (GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL ) - 4) )
                SET_FLAG( eth->rx.bd, ETH_RX_BD, TOOSHORT);
                SET_FLAG( eth->rx.bd, ETH_RX_BD, TOOSHORT);
            if ( eth->rx.packet_length > GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL ) )
            if ( eth->rx.packet_length > GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL ) )
                SET_FLAG( eth->rx.bd, ETH_RX_BD, TOOBIG);
                SET_FLAG( eth->rx.bd, ETH_RX_BD, TOOBIG);
 
 
            eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
            eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
 
 
            /* advance to next BD */
            /* advance to next BD */
            if ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, WRAP ) || eth->rx.bd_index >= ETH_BD_COUNT )
            if ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, WRAP ) || eth->rx.bd_index >= ETH_BD_COUNT )
                eth->rx.bd_index = eth->regs.tx_bd_num << 1;
                eth->rx.bd_index = eth->regs.tx_bd_num << 1;
            else
            else
                eth->rx.bd_index += 2;
                eth->rx.bd_index += 2;
 
 
            if ( ( TEST_FLAG( eth->regs.int_mask, ETH_INT_MASK, RXB_M ) ) &&
            if ( ( TEST_FLAG( eth->regs.int_mask, ETH_INT_MASK, RXB_M ) ) &&
                 ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, IRQ )              ) ) {
                 ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, IRQ )              ) ) {
                report_interrupt( eth->mac_int );
                report_interrupt( eth->mac_int );
            }
            }
 
 
            /* ready to receive next packet */
            /* ready to receive next packet */
                debug (3, "RX - entering state IDLE\n");
                debug (3, "RX - entering state IDLE\n");
            eth->rx.state = ETH_RXSTATE_IDLE;
            eth->rx.state = ETH_RXSTATE_IDLE;
        }
        }
        break;
        break;
    }
    }
 
 
    /* Reschedule */
    /* Reschedule */
    SCHED_ADD( eth_controller_rx_clock, dat, 1 );
    SCHED_ADD( eth_controller_rx_clock, dat, 1 );
}
}
 
 
/* ========================================================================= */
/* ========================================================================= */
/* Move to next RX BD */
/* Move to next RX BD */
void eth_rx_next_packet( struct eth_device *eth )
void eth_rx_next_packet( struct eth_device *eth )
{
{
    /* Skip any possible leftovers */
    /* Skip any possible leftovers */
    if ( eth->rx.bytes_left )
    if ( eth->rx.bytes_left )
        eth_skip_rx_file( eth, eth->rx.bytes_left );
        eth_skip_rx_file( eth, eth->rx.bytes_left );
}
}
/* "Skip" bytes in RX file */
/* "Skip" bytes in RX file */
void eth_skip_rx_file( struct eth_device *eth, off_t count )
void eth_skip_rx_file( struct eth_device *eth, off_t count )
{
{
    eth->rx.offset += count;
    eth->rx.offset += count;
}
}
 
 
/* Move RX file position back */
/* Move RX file position back */
void eth_rewind_rx_file( struct eth_device *eth, off_t count )
void eth_rewind_rx_file( struct eth_device *eth, off_t count )
{
{
    eth->rx.offset -= count;
    eth->rx.offset -= count;
}
}
/*
/*
 * Utility function to read from the ethernet RX file
 * Utility function to read from the ethernet RX file
 * This function moves the file pointer to the current place in the packet before reading
 * This function moves the file pointer to the current place in the packet before reading
 */
 */
ssize_t eth_read_rx_file( struct eth_device *eth, void *buf, size_t count )
ssize_t eth_read_rx_file( struct eth_device *eth, void *buf, size_t count )
{
{
    ssize_t result;
    ssize_t result;
 
 
    if ( eth->rx.fd <= 0 ) {
    if ( eth->rx.fd <= 0 ) {
        debug( 3,  "Ethernet: No RX file\n" );
        debug( 3,  "Ethernet: No RX file\n" );
        return 0;
        return 0;
    }
    }
 
 
    if ( eth->rx.offset )
    if ( eth->rx.offset )
        if ( lseek( eth->rx.fd, *(eth->rx.offset), SEEK_SET ) == (off_t)-1 ) {
        if ( lseek( eth->rx.fd, *(eth->rx.offset), SEEK_SET ) == (off_t)-1 ) {
            debug( 3,  "Ethernet: Error seeking RX file\n" );
            debug( 3,  "Ethernet: Error seeking RX file\n" );
            return 0;
            return 0;
        }
        }
 
 
    result = read( eth->rx.fd, buf, count );
    result = read( eth->rx.fd, buf, count );
    debug (4, "Ethernet: read result = %d \n", result);
    debug (4, "Ethernet: read result = %d \n", result);
    if ( eth->rx.offset && result >= 0 )
    if ( eth->rx.offset && result >= 0 )
        *(eth->rx.offset) += result;
        *(eth->rx.offset) += result;
 
 
    return result;
    return result;
}
}
 
 
/* ========================================================================= */
/* ========================================================================= */
 
 
/*
/*
  Reset. Initializes all registers to default and places devices in
  Reset. Initializes all registers to default and places devices in
         memory address space.
         memory address space.
*/
*/
void eth_reset(void *dat)
void eth_reset(void *dat)
{
{
    struct eth_device *eth = dat;
    struct eth_device *eth = dat;
#if HAVE_ETH_PHY
#if HAVE_ETH_PHY
    int j;
    int j;
    struct sockaddr_ll sll;
    struct sockaddr_ll sll;
#endif /* HAVE_ETH_PHY */
#endif /* HAVE_ETH_PHY */
 
 
    if ( eth->baseaddr != 0 ) {
    if ( eth->baseaddr != 0 ) {
        switch (eth->rtx_type) {
        switch (eth->rtx_type) {
        case ETH_RTX_FILE:
        case ETH_RTX_FILE:
            /* (Re-)open TX/RX files */
            /* (Re-)open TX/RX files */
            if ( eth->rxfd > 0 )
            if ( eth->rxfd > 0 )
                close( eth->rxfd );
                close( eth->rxfd );
            if ( eth->txfd > 0 )
            if ( eth->txfd > 0 )
                close( eth->txfd );
                close( eth->txfd );
            eth->rxfd = eth->txfd = -1;
            eth->rxfd = eth->txfd = -1;
 
 
            if ( (eth->rxfd = open( eth->rxfile, O_RDONLY )) < 0 )
            if ( (eth->rxfd = open( eth->rxfile, O_RDONLY )) < 0 )
                fprintf( stderr, "Cannot open Ethernet RX file \"%s\"\n", eth->rxfile );
                fprintf( stderr, "Cannot open Ethernet RX file \"%s\"\n", eth->rxfile );
            if ( (eth->txfd = open( eth->txfile,
            if ( (eth->txfd = open( eth->txfile,
                                    O_RDWR | O_CREAT | O_APPEND
                                    O_RDWR | O_CREAT | O_APPEND
 
 
#if defined(O_SYNC)     /* BSD / Mac OS X manual doesn't know about O_SYNC */
#if defined(O_SYNC)     /* BSD / Mac OS X manual doesn't know about O_SYNC */
                                                                        | O_SYNC
                                                                        | O_SYNC
#endif
#endif
                                                                        ,
                                                                        ,
                                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) < 0 )
                                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) < 0 )
                fprintf( stderr, "Cannot open Ethernet TX file \"%s\"\n", eth->txfile );
                fprintf( stderr, "Cannot open Ethernet TX file \"%s\"\n", eth->txfile );
            eth->loopback_offset = lseek( eth->txfd, 0, SEEK_END );
            eth->loopback_offset = lseek( eth->txfd, 0, SEEK_END );
 
 
            break;
            break;
#if HAVE_ETH_PHY
#if HAVE_ETH_PHY
        case ETH_RTX_SOCK:
        case ETH_RTX_SOCK:
            /* (Re-)open TX/RX sockets */
            /* (Re-)open TX/RX sockets */
            if (eth->rtx_sock != 0)
            if (eth->rtx_sock != 0)
                break;
                break;
 
 
            debug (3, "RTX oppening socket...\n");
            debug (3, "RTX oppening socket...\n");
            eth->rtx_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
            eth->rtx_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
            if (eth->rtx_sock == -1) {
            if (eth->rtx_sock == -1) {
                fprintf( stderr, "Cannot open rtx_sock.\n");
                fprintf( stderr, "Cannot open rtx_sock.\n");
                return;
                return;
            }
            }
 
 
            /* get interface index number */
            /* get interface index number */
            debug (3, "RTX getting interface...\n");
            debug (3, "RTX getting interface...\n");
            memset(&(eth->ifr), 0, sizeof(eth->ifr));
            memset(&(eth->ifr), 0, sizeof(eth->ifr));
            strncpy(eth->ifr.ifr_name, eth->sockif, IFNAMSIZ);
            strncpy(eth->ifr.ifr_name, eth->sockif, IFNAMSIZ);
            if (ioctl(eth->rtx_sock, SIOCGIFINDEX, &(eth->ifr)) == -1) {
            if (ioctl(eth->rtx_sock, SIOCGIFINDEX, &(eth->ifr)) == -1) {
                fprintf( stderr, "SIOCGIFINDEX failed!\n");
                fprintf( stderr, "SIOCGIFINDEX failed!\n");
                return;
                return;
            }
            }
            debug (3, "RTX Socket Interface : %d\n", eth->ifr.ifr_ifindex);
            debug (3, "RTX Socket Interface : %d\n", eth->ifr.ifr_ifindex);
 
 
            /* Bind to interface... */
            /* Bind to interface... */
            debug (3, "Binding to the interface ifindex=%d\n", eth->ifr.ifr_ifindex);
            debug (3, "Binding to the interface ifindex=%d\n", eth->ifr.ifr_ifindex);
            memset(&sll, 0xff, sizeof(sll));
            memset(&sll, 0xff, sizeof(sll));
            sll.sll_family = AF_PACKET;    /* allways AF_PACKET */
            sll.sll_family = AF_PACKET;    /* allways AF_PACKET */
            sll.sll_protocol = htons(ETH_P_ALL);
            sll.sll_protocol = htons(ETH_P_ALL);
            sll.sll_ifindex = eth->ifr.ifr_ifindex;
            sll.sll_ifindex = eth->ifr.ifr_ifindex;
            if (bind(eth->rtx_sock, (struct sockaddr *)&sll, sizeof(sll)) == -1) {
            if (bind(eth->rtx_sock, (struct sockaddr *)&sll, sizeof(sll)) == -1) {
                fprintf( stderr, "Error bind().\n");
                fprintf( stderr, "Error bind().\n");
                return;
                return;
            }
            }
 
 
            /* first, flush all received packets. */
            /* first, flush all received packets. */
            debug (3, "Flush");
            debug (3, "Flush");
            do {
            do {
                fd_set fds;
                fd_set fds;
                struct timeval t;
                struct timeval t;
 
 
                debug( 3, ".");
                debug( 3, ".");
                FD_ZERO(&fds);
                FD_ZERO(&fds);
                FD_SET(eth->rtx_sock, &fds);
                FD_SET(eth->rtx_sock, &fds);
                memset(&t, 0, sizeof(t));
                memset(&t, 0, sizeof(t));
                j = select(FD_SETSIZE, &fds, NULL, NULL, &t);
                j = select(FD_SETSIZE, &fds, NULL, NULL, &t);
                if (j > 0)
                if (j > 0)
                    recv(eth->rtx_sock, eth->rx_buff, j, 0);
                    recv(eth->rtx_sock, eth->rx_buff, j, 0);
            } while (j);
            } while (j);
            debug (3, "\n");
            debug (3, "\n");
 
 
            break;
            break;
#else /* HAVE_ETH_PHY */
#else /* HAVE_ETH_PHY */
        case ETH_RTX_SOCK:
        case ETH_RTX_SOCK:
            fprintf (stderr, "Ethernet phy not enabled in this configuration.  Configure with --enable-ethphy.\n");
            fprintf (stderr, "Ethernet phy not enabled in this configuration.  Configure with --enable-ethphy.\n");
            exit (1);
            exit (1);
            break;
            break;
#endif /* HAVE_ETH_PHY */
#endif /* HAVE_ETH_PHY */
        }
        }
 
 
        /* Set registers to default values */
        /* Set registers to default values */
        memset( &(eth->regs), 0, sizeof(eth->regs) );
        memset( &(eth->regs), 0, sizeof(eth->regs) );
        eth->regs.moder = 0x0000A000;
        eth->regs.moder = 0x0000A000;
        eth->regs.ipgt = 0x00000012;
        eth->regs.ipgt = 0x00000012;
        eth->regs.ipgr1 = 0x0000000C;
        eth->regs.ipgr1 = 0x0000000C;
        eth->regs.ipgr2 = 0x00000012;
        eth->regs.ipgr2 = 0x00000012;
        eth->regs.packetlen = 0x003C0600;
        eth->regs.packetlen = 0x003C0600;
        eth->regs.collconf = 0x000F003F;
        eth->regs.collconf = 0x000F003F;
        eth->regs.miimoder = 0x00000064;
        eth->regs.miimoder = 0x00000064;
        eth->regs.tx_bd_num = 0x00000040;
        eth->regs.tx_bd_num = 0x00000040;
 
 
        /* Initialize TX/RX status */
        /* Initialize TX/RX status */
        memset( &(eth->tx), 0, sizeof(eth->tx) );
        memset( &(eth->tx), 0, sizeof(eth->tx) );
        memset( &(eth->rx), 0, sizeof(eth->rx) );
        memset( &(eth->rx), 0, sizeof(eth->rx) );
        eth->rx.bd_index = eth->regs.tx_bd_num << 1;
        eth->rx.bd_index = eth->regs.tx_bd_num << 1;
 
 
        /* Initialize VAPI */
        /* Initialize VAPI */
        if (eth->base_vapi_id) {
        if (eth->base_vapi_id) {
            vapi_install_multi_handler( eth->base_vapi_id, ETH_NUM_VAPI_IDS, eth_vapi_read, dat );
            vapi_install_multi_handler( eth->base_vapi_id, ETH_NUM_VAPI_IDS, eth_vapi_read, dat );
        }
        }
    }
    }
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/*
/*
  Print register values on stdout
  Print register values on stdout
*/
*/
void eth_status( void *dat )
void eth_status( void *dat )
{
{
    struct eth_device *eth = dat;
    struct eth_device *eth = dat;
 
 
    PRINTF( "\nEthernet MAC at 0x%"PRIxADDR":\n", eth->baseaddr );
    PRINTF( "\nEthernet MAC at 0x%"PRIxADDR":\n", eth->baseaddr );
    PRINTF( "MODER        : 0x%08lX\n", eth->regs.moder );
    PRINTF( "MODER        : 0x%08lX\n", eth->regs.moder );
    PRINTF( "INT_SOURCE   : 0x%08lX\n", eth->regs.int_source );
    PRINTF( "INT_SOURCE   : 0x%08lX\n", eth->regs.int_source );
    PRINTF( "INT_MASK     : 0x%08lX\n", eth->regs.int_mask );
    PRINTF( "INT_MASK     : 0x%08lX\n", eth->regs.int_mask );
    PRINTF( "IPGT         : 0x%08lX\n", eth->regs.ipgt );
    PRINTF( "IPGT         : 0x%08lX\n", eth->regs.ipgt );
    PRINTF( "IPGR1        : 0x%08lX\n", eth->regs.ipgr1 );
    PRINTF( "IPGR1        : 0x%08lX\n", eth->regs.ipgr1 );
    PRINTF( "IPGR2        : 0x%08lX\n", eth->regs.ipgr2 );
    PRINTF( "IPGR2        : 0x%08lX\n", eth->regs.ipgr2 );
    PRINTF( "PACKETLEN    : 0x%08lX\n", eth->regs.packetlen );
    PRINTF( "PACKETLEN    : 0x%08lX\n", eth->regs.packetlen );
    PRINTF( "COLLCONF     : 0x%08lX\n", eth->regs.collconf );
    PRINTF( "COLLCONF     : 0x%08lX\n", eth->regs.collconf );
    PRINTF( "TX_BD_NUM    : 0x%08lX\n", eth->regs.tx_bd_num );
    PRINTF( "TX_BD_NUM    : 0x%08lX\n", eth->regs.tx_bd_num );
    PRINTF( "CTRLMODER    : 0x%08lX\n", eth->regs.controlmoder );
    PRINTF( "CTRLMODER    : 0x%08lX\n", eth->regs.controlmoder );
    PRINTF( "MIIMODER     : 0x%08lX\n", eth->regs.miimoder );
    PRINTF( "MIIMODER     : 0x%08lX\n", eth->regs.miimoder );
    PRINTF( "MIICOMMAND   : 0x%08lX\n", eth->regs.miicommand );
    PRINTF( "MIICOMMAND   : 0x%08lX\n", eth->regs.miicommand );
    PRINTF( "MIIADDRESS   : 0x%08lX\n", eth->regs.miiaddress );
    PRINTF( "MIIADDRESS   : 0x%08lX\n", eth->regs.miiaddress );
    PRINTF( "MIITX_DATA   : 0x%08lX\n", eth->regs.miitx_data );
    PRINTF( "MIITX_DATA   : 0x%08lX\n", eth->regs.miitx_data );
    PRINTF( "MIIRX_DATA   : 0x%08lX\n", eth->regs.miirx_data );
    PRINTF( "MIIRX_DATA   : 0x%08lX\n", eth->regs.miirx_data );
    PRINTF( "MIISTATUS    : 0x%08lX\n", eth->regs.miistatus );
    PRINTF( "MIISTATUS    : 0x%08lX\n", eth->regs.miistatus );
    PRINTF( "MAC Address  : %02X:%02X:%02X:%02X:%02X:%02X\n",
    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[0], eth->mac_address[1], eth->mac_address[2],
           eth->mac_address[3], eth->mac_address[4], eth->mac_address[5] );
           eth->mac_address[3], eth->mac_address[4], eth->mac_address[5] );
    PRINTF( "HASH0        : 0x%08lX\n", eth->regs.hash0 );
    PRINTF( "HASH0        : 0x%08lX\n", eth->regs.hash0 );
    PRINTF( "HASH1        : 0x%08lX\n", eth->regs.hash1 );
    PRINTF( "HASH1        : 0x%08lX\n", eth->regs.hash1 );
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/*
/*
  Read a register
  Read a register
*/
*/
uint32_t eth_read32( oraddr_t addr, void *dat )
uint32_t eth_read32( oraddr_t addr, void *dat )
{
{
    struct eth_device *eth = dat;
    struct eth_device *eth = dat;
    addr -= eth->baseaddr;
    addr -= eth->baseaddr;
 
 
    switch( addr ) {
    switch( addr ) {
    case ETH_MODER: return eth->regs.moder;
    case ETH_MODER: return eth->regs.moder;
    case ETH_INT_SOURCE: return eth->regs.int_source;
    case ETH_INT_SOURCE: return eth->regs.int_source;
    case ETH_INT_MASK: return eth->regs.int_mask;
    case ETH_INT_MASK: return eth->regs.int_mask;
    case ETH_IPGT: return eth->regs.ipgt;
    case ETH_IPGT: return eth->regs.ipgt;
    case ETH_IPGR1: return eth->regs.ipgr1;
    case ETH_IPGR1: return eth->regs.ipgr1;
    case ETH_IPGR2: return eth->regs.ipgr2;
    case ETH_IPGR2: return eth->regs.ipgr2;
    case ETH_PACKETLEN: return eth->regs.packetlen;
    case ETH_PACKETLEN: return eth->regs.packetlen;
    case ETH_COLLCONF: return eth->regs.collconf;
    case ETH_COLLCONF: return eth->regs.collconf;
    case ETH_TX_BD_NUM: return eth->regs.tx_bd_num;
    case ETH_TX_BD_NUM: return eth->regs.tx_bd_num;
    case ETH_CTRLMODER: return eth->regs.controlmoder;
    case ETH_CTRLMODER: return eth->regs.controlmoder;
    case ETH_MIIMODER: return eth->regs.miimoder;
    case ETH_MIIMODER: return eth->regs.miimoder;
    case ETH_MIICOMMAND: return eth->regs.miicommand;
    case ETH_MIICOMMAND: return eth->regs.miicommand;
    case ETH_MIIADDRESS: return eth->regs.miiaddress;
    case ETH_MIIADDRESS: return eth->regs.miiaddress;
    case ETH_MIITX_DATA: return eth->regs.miitx_data;
    case ETH_MIITX_DATA: return eth->regs.miitx_data;
    case ETH_MIIRX_DATA: return eth->regs.miirx_data;
    case ETH_MIIRX_DATA: return eth->regs.miirx_data;
    case ETH_MIISTATUS: return eth->regs.miistatus;
    case ETH_MIISTATUS: return eth->regs.miistatus;
    case ETH_MAC_ADDR0: return (((unsigned long)eth->mac_address[3]) << 24) |
    case ETH_MAC_ADDR0: return (((unsigned long)eth->mac_address[3]) << 24) |
                               (((unsigned long)eth->mac_address[2]) << 16) |
                               (((unsigned long)eth->mac_address[2]) << 16) |
                               (((unsigned long)eth->mac_address[1]) << 8) |
                               (((unsigned long)eth->mac_address[1]) << 8) |
                                 (unsigned long)eth->mac_address[0];
                                 (unsigned long)eth->mac_address[0];
    case ETH_MAC_ADDR1: return (((unsigned long)eth->mac_address[5]) << 8) |
    case ETH_MAC_ADDR1: return (((unsigned long)eth->mac_address[5]) << 8) |
                                 (unsigned long)eth->mac_address[4];
                                 (unsigned long)eth->mac_address[4];
    case ETH_HASH0: return eth->regs.hash0;
    case ETH_HASH0: return eth->regs.hash0;
    case ETH_HASH1: return eth->regs.hash1;
    case ETH_HASH1: return eth->regs.hash1;
    /*case ETH_DMA_RX_TX: return eth_rx( eth );*/
    /*case ETH_DMA_RX_TX: return eth_rx( eth );*/
    }
    }
 
 
    if ( (addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE) )
    if ( (addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE) )
        return eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4];
        return eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4];
 
 
    PRINTF( "eth_read32( 0x%"PRIxADDR" ): Illegal address\n",
    PRINTF( "eth_read32( 0x%"PRIxADDR" ): Illegal address\n",
            addr + eth->baseaddr );
            addr + eth->baseaddr );
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
    return 0;
    return 0;
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/*
/*
  Write a register
  Write a register
*/
*/
void eth_write32( oraddr_t addr, uint32_t value, void *dat )
void eth_write32( oraddr_t addr, uint32_t value, void *dat )
{
{
    struct eth_device *eth = dat;
    struct eth_device *eth = dat;
 
 
    addr -= eth->baseaddr;
    addr -= eth->baseaddr;
 
 
    switch( addr ) {
    switch( addr ) {
    case ETH_MODER:
    case ETH_MODER:
 
 
        if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) &&
        if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) &&
             TEST_FLAG( value, ETH_MODER, RXEN) )
             TEST_FLAG( value, ETH_MODER, RXEN) )
            SCHED_ADD( eth_controller_rx_clock, dat, 1 );
            SCHED_ADD( eth_controller_rx_clock, dat, 1 );
        else if ( !TEST_FLAG( value, ETH_MODER, RXEN) )
        else if ( !TEST_FLAG( value, ETH_MODER, RXEN) )
            SCHED_FIND_REMOVE( eth_controller_rx_clock, dat);
            SCHED_FIND_REMOVE( eth_controller_rx_clock, dat);
 
 
        if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN) &&
        if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN) &&
             TEST_FLAG( value, ETH_MODER, TXEN) )
             TEST_FLAG( value, ETH_MODER, TXEN) )
            SCHED_ADD( eth_controller_tx_clock, dat, 1 );
            SCHED_ADD( eth_controller_tx_clock, dat, 1 );
        else if ( !TEST_FLAG( value, ETH_MODER, TXEN) )
        else if ( !TEST_FLAG( value, ETH_MODER, TXEN) )
            SCHED_FIND_REMOVE( eth_controller_tx_clock, dat);
            SCHED_FIND_REMOVE( eth_controller_tx_clock, dat);
 
 
        eth->regs.moder = value;
        eth->regs.moder = value;
 
 
        if (TEST_FLAG(value, ETH_MODER, RST))
        if (TEST_FLAG(value, ETH_MODER, RST))
            eth_reset( dat );
            eth_reset( dat );
        return;
        return;
    case ETH_INT_SOURCE: eth->regs.int_source &= ~value; return;
    case ETH_INT_SOURCE: eth->regs.int_source &= ~value; return;
    case ETH_INT_MASK: eth->regs.int_mask = value; return;
    case ETH_INT_MASK: eth->regs.int_mask = value; return;
    case ETH_IPGT: eth->regs.ipgt = value; return;
    case ETH_IPGT: eth->regs.ipgt = value; return;
    case ETH_IPGR1: eth->regs.ipgr1 = value; return;
    case ETH_IPGR1: eth->regs.ipgr1 = value; return;
    case ETH_IPGR2: eth->regs.ipgr2 = value; return;
    case ETH_IPGR2: eth->regs.ipgr2 = value; return;
    case ETH_PACKETLEN: eth->regs.packetlen = value; return;
    case ETH_PACKETLEN: eth->regs.packetlen = value; return;
    case ETH_COLLCONF: eth->regs.collconf = value; return;
    case ETH_COLLCONF: eth->regs.collconf = value; return;
    case ETH_TX_BD_NUM: eth_write_tx_bd_num( eth, value ); return;
    case ETH_TX_BD_NUM: eth_write_tx_bd_num( eth, value ); return;
    case ETH_CTRLMODER: eth->regs.controlmoder = value; return;
    case ETH_CTRLMODER: eth->regs.controlmoder = value; return;
    case ETH_MIIMODER: eth->regs.miimoder = value; return;
    case ETH_MIIMODER: eth->regs.miimoder = value; return;
    case ETH_MIICOMMAND: eth->regs.miicommand = value; return;
    case ETH_MIICOMMAND: eth->regs.miicommand = value; return;
    case ETH_MIIADDRESS: eth->regs.miiaddress = value; return;
    case ETH_MIIADDRESS: eth->regs.miiaddress = value; return;
    case ETH_MIITX_DATA: eth->regs.miitx_data = value; return;
    case ETH_MIITX_DATA: eth->regs.miitx_data = value; return;
    case ETH_MIIRX_DATA: eth->regs.miirx_data = value; return;
    case ETH_MIIRX_DATA: eth->regs.miirx_data = value; return;
    case ETH_MIISTATUS: eth->regs.miistatus = value; return;
    case ETH_MIISTATUS: eth->regs.miistatus = value; return;
    case ETH_MAC_ADDR0:
    case ETH_MAC_ADDR0:
        eth->mac_address[0] = value & 0xFF;
        eth->mac_address[0] = value & 0xFF;
        eth->mac_address[1] = (value >> 8) & 0xFF;
        eth->mac_address[1] = (value >> 8) & 0xFF;
        eth->mac_address[2] = (value >> 16) & 0xFF;
        eth->mac_address[2] = (value >> 16) & 0xFF;
        eth->mac_address[3] = (value >> 24) & 0xFF;
        eth->mac_address[3] = (value >> 24) & 0xFF;
        return;
        return;
    case ETH_MAC_ADDR1:
    case ETH_MAC_ADDR1:
        eth->mac_address[4] = value & 0xFF;
        eth->mac_address[4] = value & 0xFF;
        eth->mac_address[5] = (value >> 8) & 0xFF;
        eth->mac_address[5] = (value >> 8) & 0xFF;
        return;
        return;
    case ETH_HASH0: eth->regs.hash0 = value; return;
    case ETH_HASH0: eth->regs.hash0 = value; return;
    case ETH_HASH1: eth->regs.hash1 = value; return;
    case ETH_HASH1: eth->regs.hash1 = value; return;
 
 
    /*case ETH_DMA_RX_TX: eth_tx( eth, value ); return;*/
    /*case ETH_DMA_RX_TX: eth_tx( eth, value ); return;*/
    }
    }
 
 
    if ( (addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE) ) {
    if ( (addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE) ) {
        eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
        eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
        return;
        return;
    }
    }
 
 
    PRINTF( "eth_write32( 0x%"PRIxADDR" ): Illegal address\n",
    PRINTF( "eth_write32( 0x%"PRIxADDR" ): Illegal address\n",
            addr + eth->baseaddr );
            addr + eth->baseaddr );
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
    return;
    return;
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/*
/*
 *   VAPI connection to outside
 *   VAPI connection to outside
 */
 */
static void eth_vapi_read (unsigned long id, unsigned long data, void *dat)
static void eth_vapi_read (unsigned long id, unsigned long data, void *dat)
{
{
    unsigned long which;
    unsigned long which;
    struct eth_device *eth = dat;
    struct eth_device *eth = dat;
 
 
    which = id - eth->base_vapi_id;
    which = id - eth->base_vapi_id;
 
 
    debug( 5, "ETH: id %08lx, data %08lx\n", id, data );
    debug( 5, "ETH: id %08lx, data %08lx\n", id, data );
 
 
    if ( !eth ) {
    if ( !eth ) {
        debug( 1, "ETH: VAPI ID %08lx is not ours!\n", id );
        debug( 1, "ETH: VAPI ID %08lx is not ours!\n", id );
        return;
        return;
    }
    }
 
 
    switch( which ) {
    switch( which ) {
    case ETH_VAPI_DATA:
    case ETH_VAPI_DATA:
        break;
        break;
    case ETH_VAPI_CTRL:
    case ETH_VAPI_CTRL:
        break;
        break;
    }
    }
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/* When TX_BD_NUM is written, also reset current RX BD index */
/* When TX_BD_NUM is written, also reset current RX BD index */
void eth_write_tx_bd_num( struct eth_device *eth, unsigned long value )
void eth_write_tx_bd_num( struct eth_device *eth, unsigned long value )
{
{
    eth->regs.tx_bd_num = value & 0xFF;
    eth->regs.tx_bd_num = value & 0xFF;
    eth->rx.bd_index = eth->regs.tx_bd_num << 1;
    eth->rx.bd_index = eth->regs.tx_bd_num << 1;
}
}
 
 
/* ========================================================================= */
/* ========================================================================= */
 
 
/*-----------------------------------------------[ Ethernet configuration ]---*/
/*-----------------------------------------------[ Ethernet configuration ]---*/
void eth_baseaddr(union param_val val, void *dat)
void eth_baseaddr(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  eth->baseaddr = val.addr_val;
  eth->baseaddr = val.addr_val;
}
}
 
 
void eth_dma(union param_val val, void *dat)
void eth_dma(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  eth->dma = val.addr_val;
  eth->dma = val.addr_val;
}
}
 
 
void eth_rtx_type(union param_val val, void *dat)
void eth_rtx_type(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  eth->rtx_type = val.int_val;
  eth->rtx_type = val.int_val;
}
}
 
 
void eth_rx_channel(union param_val val, void *dat)
void eth_rx_channel(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  eth->rx_channel = val.int_val;
  eth->rx_channel = val.int_val;
}
}
 
 
void eth_tx_channel(union param_val val, void *dat)
void eth_tx_channel(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  eth->tx_channel = val.int_val;
  eth->tx_channel = val.int_val;
}
}
 
 
void eth_rxfile(union param_val val, void *dat)
void eth_rxfile(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  if(!(eth->rxfile = strdup(val.str_val))) {
  if(!(eth->rxfile = strdup(val.str_val))) {
    fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
    fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
    exit(-1);
    exit(-1);
  }
  }
}
}
 
 
void eth_txfile(union param_val val, void *dat)
void eth_txfile(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  if(!(eth->txfile = strdup(val.str_val))) {
  if(!(eth->txfile = strdup(val.str_val))) {
    fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
    fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
    exit(-1);
    exit(-1);
  }
  }
}
}
 
 
void eth_sockif(union param_val val, void *dat)
void eth_sockif(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  if(!(eth->sockif = strdup(val.str_val))) {
  if(!(eth->sockif = strdup(val.str_val))) {
    fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
    fprintf(stderr, "Peripheral Ethernet: Run out of memory\n");
    exit(-1);
    exit(-1);
  }
  }
}
}
 
 
void eth_irq(union param_val val, void *dat)
void eth_irq(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  eth->mac_int = val.int_val;
  eth->mac_int = val.int_val;
}
}
 
 
void eth_vapi_id(union param_val val, void *dat)
void eth_vapi_id(union param_val val, void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
  eth->base_vapi_id = val.int_val;
  eth->base_vapi_id = val.int_val;
}
}
 
 
void *eth_sec_start(void)
void *eth_sec_start(void)
{
{
  struct eth_device *new = malloc(sizeof(struct eth_device));
  struct eth_device *new = malloc(sizeof(struct eth_device));
 
 
  if(!new) {
  if(!new) {
    fprintf(stderr, "Peripheral Eth: Run out of memory\n");
    fprintf(stderr, "Peripheral Eth: Run out of memory\n");
    exit(-1);
    exit(-1);
  }
  }
 
 
  return new;
  return new;
}
}
 
 
void eth_sec_end(void *dat)
void eth_sec_end(void *dat)
{
{
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
 
 
  register_memoryarea( eth->baseaddr, ETH_ADDR_SPACE, 4, 0, eth_read32, eth_write32, dat );
  register_memoryarea( eth->baseaddr, ETH_ADDR_SPACE, 4, 0, eth_read32, eth_write32, dat );
  reg_sim_stat( eth_status, dat );
  reg_sim_stat( eth_status, dat );
  reg_sim_reset( eth_reset, dat );
  reg_sim_reset( eth_reset, dat );
}
}
 
 
void reg_ethernet_sec(void)
void reg_ethernet_sec(void)
{
{
  struct config_section *sec = reg_config_sec("ethernet", eth_sec_start, eth_sec_end);
  struct config_section *sec = reg_config_sec("ethernet", eth_sec_start, eth_sec_end);
 
 
  reg_config_param(sec, "irq", paramt_int, eth_irq);
  reg_config_param(sec, "irq", paramt_int, eth_irq);
  reg_config_param(sec, "baseaddr", paramt_int, eth_baseaddr);
  reg_config_param(sec, "baseaddr", paramt_int, eth_baseaddr);
  reg_config_param(sec, "dma", paramt_int, eth_dma);
  reg_config_param(sec, "dma", paramt_int, eth_dma);
  reg_config_param(sec, "rtx_type", paramt_int, eth_rtx_type);
  reg_config_param(sec, "rtx_type", paramt_int, eth_rtx_type);
  reg_config_param(sec, "rx_channel", paramt_int, eth_rx_channel);
  reg_config_param(sec, "rx_channel", paramt_int, eth_rx_channel);
  reg_config_param(sec, "tx_channel", paramt_int, eth_tx_channel);
  reg_config_param(sec, "tx_channel", paramt_int, eth_tx_channel);
  reg_config_param(sec, "rxfile", paramt_str, eth_rxfile);
  reg_config_param(sec, "rxfile", paramt_str, eth_rxfile);
  reg_config_param(sec, "txfile", paramt_str, eth_txfile);
  reg_config_param(sec, "txfile", paramt_str, eth_txfile);
  reg_config_param(sec, "sockif", paramt_str, eth_sockif);
  reg_config_param(sec, "sockif", paramt_str, eth_sockif);
  reg_config_param(sec, "vapi_id", paramt_int, eth_vapi_id);
  reg_config_param(sec, "vapi_id", paramt_int, eth_vapi_id);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.