Line 35... |
Line 35... |
#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"
|
|
|
static struct eth_device eths[MAX_ETHERNETS];
|
static struct eth_device eths[MAX_ETHERNETS];
|
|
|
/* 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);
|
/* register interface */
|
/* register interface */
|
static void eth_write32( unsigned long addr, unsigned long value );
|
static void eth_write32( unsigned long addr, unsigned long value );
|
static unsigned long eth_read32( unsigned long addr );
|
static unsigned long eth_read32( unsigned long 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( unsigned long addr, struct eth_device **eth, unsigned long *reladdr );
|
|
struct eth_device *eth_find_vapi_device (unsigned long id, unsigned *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 * );
|
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 );
|
Line 197... |
Line 200... |
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 (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");
|
}
|
}
|
|
|
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 */
|
|
if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXE_M) ||
|
|
TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXB_M) )
|
|
{
|
|
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, IRQ ) )
|
|
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;
|
}
|
}
|
|
|
/* generate OK interrupt */
|
|
if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXE_M) ||
|
|
TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXB_M) )
|
|
{
|
|
report_interrupt( eth->mac_int );
|
|
}
|
|
|
|
break;
|
break;
|
}
|
}
|
}
|
}
|
/* ========================================================================= */
|
/* ========================================================================= */
|
|
|
Line 346... |
Line 351... |
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 {
|
else break;
|
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 */
|
Line 373... |
Line 376... |
|
|
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:
|
|
|
}
|
}
|
break;
|
break;
|
|
|
case ETH_RXSTATE_WRITEFIFO:
|
case ETH_RXSTATE_WRITEFIFO:
|
#if 1
|
#if 1
|
Line 413... |
Line 418... |
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;
|
eth->rx.bd_index = eth->regs.tx_bd_num;
|
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 ) ) ) {
|
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");
|
Line 616... |
Line 622... |
|
|
/* 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;
|
eth->rx.bd_index = eth->regs.tx_bd_num;
|
|
|
|
/* Initialize VAPI */
|
|
if (config.ethernets[i].base_vapi_id) {
|
|
eth->base_vapi_id = config.ethernets[i].base_vapi_id;
|
|
vapi_install_multi_handler( eth->base_vapi_id, ETH_NUM_VAPI_IDS, eth_vapi_read );
|
|
}
|
}
|
}
|
}
|
}
|
/* ========================================================================= */
|
/* ========================================================================= */
|
|
|
|
|
Line 781... |
Line 793... |
return;
|
return;
|
}
|
}
|
/* ========================================================================= */
|
/* ========================================================================= */
|
|
|
|
|
|
/*
|
|
* VAPI connection to outside
|
|
*/
|
|
static void eth_vapi_read (unsigned long id, unsigned long data)
|
|
{
|
|
unsigned long which;
|
|
struct eth_device *eth = eth_find_vapi_device( id, &which );
|
|
|
|
debug( 5, "ETH: id %08x, data %08x\n", id, data );
|
|
|
|
if ( !eth ) {
|
|
debug( 1, "ETH: VAPI ID %08x is not ours!\n", id );
|
|
return;
|
|
}
|
|
|
|
switch( which ) {
|
|
case ETH_VAPI_DATA:
|
|
break;
|
|
case ETH_VAPI_CTRL:
|
|
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->rx.bd_index = eth->regs.tx_bd_num = value & 0xFF;
|
eth->rx.bd_index = eth->regs.tx_bd_num = value & 0xFF;
|
}
|
}
|
Line 815... |
Line 852... |
|
|
*reladdr = addr - (*eth)->baseaddr;
|
*reladdr = addr - (*eth)->baseaddr;
|
return 1;
|
return 1;
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|
|
/*
|
|
* Convert VAPI id to controller struct and relative address.
|
|
*/
|
|
struct eth_device *eth_find_vapi_device( unsigned long id, unsigned *which )
|
|
{
|
|
unsigned i;
|
|
|
|
for ( i=0; i<config.nethernets; i++) {
|
|
if ( (id>=eths[i].base_vapi_id) && (id < eths[i].base_vapi_id + ETH_NUM_VAPI_IDS)) {
|
|
*which = id - eths[i].base_vapi_id;
|
|
return &(eths[i]);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|