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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc2/] [or1ksim/] [peripheral/] [eth.c] - Diff between revs 1332 and 1350

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 1332 Rev 1350
Line 30... Line 30...
#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
 
#include <inttypes.h>
 
#endif
 
 
 
#include "port.h"
 
#include "arch.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"
Line 46... Line 54...
 
 
/* simulator interface */
/* simulator interface */
static void eth_reset_controller( struct eth_device *eth);
static void eth_reset_controller( struct eth_device *eth);
static void eth_vapi_read( unsigned long id, unsigned long data);
static void eth_vapi_read( unsigned long id, unsigned long data);
/* register interface */
/* register interface */
static void eth_write32( unsigned long addr, unsigned long value );
static void eth_write32( oraddr_t addr, uint32_t value );
static unsigned long eth_read32( unsigned long addr );
static uint32_t eth_read32( oraddr_t addr );
/* clock */
/* clock */
static void eth_controller_tx_clock( struct eth_device * );
static void eth_controller_tx_clock( struct eth_device * );
static void eth_controller_rx_clock( struct eth_device * );
static void eth_controller_rx_clock( struct eth_device * );
/* utility functions */
/* utility functions */
static int eth_find_controller( unsigned long addr, struct eth_device **eth, unsigned long *reladdr );
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);
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 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 * );
Line 82... Line 90...
    switch (eth->tx.state) {
    switch (eth->tx.state) {
        case ETH_TXSTATE_IDLE:
        case ETH_TXSTATE_IDLE:
        if ( TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) ) {
        if ( TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) ) {
 
 
            /* wait for TxBuffer to be ready */
            /* wait for TxBuffer to be ready */
                debug (3, "TX - entering state WAIT4BD (%d)\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 */
Line 132... Line 140...
                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 %u bytes (min. %u, max. %u)\n", eth->tx.packet_length,
            debug( 3, "Ethernet: Starting TX of %lu bytes (min. %u, max. %u)\n",
                   eth->tx.minimum_length, eth->tx.maximum_length );
                   eth->tx.packet_length, eth->tx.minimum_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) );
            }
            }
Line 192... Line 201...
 
 
        /* 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 = %0x\n", eth->regs.int_source);
            debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
 
 
            debug (3, "TX - entering state IDLE\n");
            debug (3, "TX - entering state IDLE\n");
            eth->tx.state = ETH_TXSTATE_IDLE;
            eth->tx.state = ETH_TXSTATE_IDLE;
            debug (3, "send (%d)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 = %0x\n", eth->regs.int_source);
            debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
 
 
            debug (3, "TX - entering state IDLE\n");
            debug (3, "TX - entering state IDLE\n");
            eth->tx.state = ETH_TXSTATE_IDLE;
            eth->tx.state = ETH_TXSTATE_IDLE;
            debug (3, "send FAILED!\n");
            debug (3, "send FAILED!\n");
        }
        }
Line 253... Line 262...
 
 
 
 
    switch (eth->rx.state) {
    switch (eth->rx.state) {
    case ETH_RXSTATE_IDLE:
    case ETH_RXSTATE_IDLE:
        if ( TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) ) {
        if ( TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) ) {
                debug (3, "RX - entering state WAIT4BD (%d)\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:
Line 307... Line 316...
        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 = %d)\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 */
Line 328... Line 337...
            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 %d from %d. 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;
Line 390... Line 399...
                    ((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 %d, left %d - %08lXd\n", eth->rx.bytes_read, eth->rx.bytes_left, send_word);
        debug (3, "Write %ld, left %ld - %08lXd\n", eth->rx.bytes_read,
 
               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;
Line 404... Line 414...
        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 = %0x\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);
Line 652... Line 662...
        struct eth_device *eth = &(eths[i]);
        struct eth_device *eth = &(eths[i]);
 
 
        if ( eth->baseaddr == 0 )
        if ( eth->baseaddr == 0 )
            continue;
            continue;
 
 
        PRINTF( "\nEthernet MAC %u at 0x%08lX:\n", i, eth->baseaddr );
        PRINTF( "\nEthernet MAC %u at 0x%"PRIxADDR":\n", i, 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 );
Line 697... Line 707...
 
 
 
 
/*
/*
  Read a register
  Read a register
*/
*/
unsigned long eth_read32( unsigned long addr )
uint32_t eth_read32( oraddr_t addr )
{
{
    struct eth_device *eth;
    struct eth_device *eth;
    if ( !eth_find_controller( addr, &eth, &addr ) )    {
    if ( !eth_find_controller( addr, &eth, &addr ) )    {
        PRINTF( "eth_read32( 0x%08lX ): Not in registered range(s)\n", addr );
        PRINTF( "eth_read32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr );
        return 0;
        return 0;
    }
    }
 
 
    switch( addr ) {
    switch( addr ) {
    case ETH_MODER: return eth->regs.moder;
    case ETH_MODER: return eth->regs.moder;
Line 736... Line 746...
    }
    }
 
 
    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%08lX ): Illegal address\n", addr + eth->baseaddr );
    PRINTF( "eth_read32( 0x%"PRIxADDR" ): Illegal address\n",
 
            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( unsigned long addr, unsigned long value )
void eth_write32( oraddr_t addr, uint32_t value )
{
{
    struct eth_device *eth;
    struct eth_device *eth;
    if ( !eth_find_controller( addr, &eth, &addr ) )    {
    if ( !eth_find_controller( addr, &eth, &addr ) )    {
        PRINTF( "eth_write32( 0x%08lX ): Not in registered range(s)\n", addr );
        PRINTF( "eth_write32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr );
    return;
    return;
    }
    }
 
 
    switch( addr ) {
    switch( addr ) {
    case ETH_MODER: eth->regs.moder = value; if (TEST_FLAG(value, ETH_MODER, RST)) eth_reset(); return;
    case ETH_MODER: eth->regs.moder = value; if (TEST_FLAG(value, ETH_MODER, RST)) eth_reset(); return;
Line 792... Line 803...
    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%08lX ): Illegal address\n", addr + eth->baseaddr );
    PRINTF( "eth_write32( 0x%"PRIxADDR" ): Illegal address\n",
 
            addr + eth->baseaddr );
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
    return;
    return;
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
Line 807... Line 819...
static void eth_vapi_read (unsigned long id, unsigned long data)
static void eth_vapi_read (unsigned long id, unsigned long data)
{
{
    unsigned long which;
    unsigned long which;
    struct eth_device *eth = eth_find_vapi_device( id, &which );
    struct eth_device *eth = eth_find_vapi_device( id, &which );
 
 
    debug( 5, "ETH: id %08x, data %08x\n", id, data );
    debug( 5, "ETH: id %08lx, data %08lx\n", id, data );
 
 
    if ( !eth ) {
    if ( !eth ) {
        debug( 1, "ETH: VAPI ID %08x 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:
Line 837... Line 849...
 
 
/*
/*
  Convert a memory address to a oontroller struct and relative address.
  Convert a memory address to a oontroller struct and relative address.
  Return nonzero on success
  Return nonzero on success
*/
*/
int eth_find_controller( unsigned long addr, struct eth_device **eth, unsigned long *reladdr )
int eth_find_controller( oraddr_t addr, struct eth_device **eth, oraddr_t *reladdr )
{
{
    unsigned i;
    unsigned i;
    *eth = NULL;
    *eth = NULL;
 
 
    for ( i = 0; i < MAX_ETHERNETS && *eth == NULL; ++ i ) {
    for ( i = 0; i < MAX_ETHERNETS && *eth == NULL; ++ i ) {

powered by: WebSVN 2.1.0

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