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

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 345 to Rev 346
    Reverse comparison

Rev 345 → Rev 346

/trunk/or1ksim/peripheral/ethernet.c
29,7 → 29,7
#include <unistd.h>
#include <errno.h>
 
#include "ethernet.h"
#include "ethernet_i.h"
#include "dma.h"
#include "trace.h"
#include "sim-config.h"
43,17 → 43,27
static unsigned long eth_read32( unsigned long addr );
static void eth_controller_tx_clock( struct eth_device * );
static void eth_controller_rx_clock( struct eth_device * );
static void eth_start_tx( struct eth_device * );
static void eth_finish_tx( struct eth_device * );
static void eth_start_rx( struct eth_device * );
static void eth_finish_rx( struct eth_device * );
 
static void eth_write_rx_bd_adr( struct eth_device *, unsigned long value );
static unsigned long eth_rx( struct eth_device * );
static void eth_tx( struct eth_device *, unsigned long );
static void eth_rx_next_packet( struct eth_device * );
 
static ssize_t eth_initialize_tx_crc( struct eth_device * );
static ssize_t eth_write_tx_file_and_accumulate_crc( struct eth_device *, const 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_rewind_rx_file( struct eth_device *, off_t );
 
static int eth_find_controller( unsigned long addr, struct eth_device **eth, unsigned long *reladdr );
static void eth_close_files( struct eth_device *eth );
 
 
 
/* Reset. Initializes all registers to default and places devices in memory address space. */
void eth_reset()
{
125,7 → 135,6
eth->rxfd = eth->txfd = -1;
}
 
 
/* Print register values on stdout */
void eth_status( void )
{
154,8 → 163,9
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_ADDR0 : 0x%08lX\n", eth->regs.mac_addr0 );
printf( "MAC_ADDR1 : 0x%08lX\n", eth->regs.mac_addr1 );
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] );
}
}
 
212,9 → 222,12
case ETH_MIITX_DATA: return eth->regs.miitx_data;
case ETH_MIIRX_DATA: return eth->regs.miirx_data;
case ETH_MIISTATUS: return eth->regs.miistatus;
case ETH_MAC_ADDR0: return eth->regs.mac_addr0;
case ETH_MAC_ADDR1: return eth->regs.mac_addr1;
 
case ETH_MAC_ADDR0: return (((unsigned long)eth->mac_address[3]) << 24) |
(((unsigned long)eth->mac_address[2]) << 16) |
(((unsigned long)eth->mac_address[1]) << 8) |
(unsigned long)eth->mac_address[0];
case ETH_MAC_ADDR1: return (((unsigned long)eth->mac_address[5]) << 8) |
(unsigned long)eth->mac_address[4];
case ETH_DMA_RX_TX: return eth_rx( eth );
}
 
253,8 → 266,16
case ETH_MIITX_DATA: eth->regs.miitx_data = value; return;
case ETH_MIIRX_DATA: eth->regs.miirx_data = value; return;
case ETH_MIISTATUS: eth->regs.miistatus = value; return;
case ETH_MAC_ADDR0: eth->regs.mac_addr0 = value; return;
case ETH_MAC_ADDR1: eth->regs.mac_addr1 = value; return;
case ETH_MAC_ADDR0:
eth->mac_address[0] = value & 0xFF;
eth->mac_address[1] = (value >> 8) & 0xFF;
eth->mac_address[2] = (value >> 16) & 0xFF;
eth->mac_address[3] = (value >> 24) & 0xFF;
return;
case ETH_MAC_ADDR1:
eth->mac_address[4] = value & 0xFF;
eth->mac_address[5] = (value >> 8) & 0xFF;
return;
 
case ETH_DMA_RX_TX: eth_tx( eth, value ); return;
}
352,7 → 373,7
bytes[3] = (unsigned char)((data ) & 0xFF);
/* And "transmit" */
written = write( eth->txfd, bytes, send_count );
written = eth_write_tx_file_and_accumulate_crc( eth, bytes, send_count );
if ( written > 0 ) {
eth->tx.bytes_left -= written;
eth->tx.bytes_sent += written;
375,7 → 396,7
send_count = eth->tx.minimum_length - eth->tx.packet_length;
bytes[0] = 0;
while ( send_count -- )
if ( write( eth->txfd, bytes, 1 ) < 1 ) {
if ( eth_write_tx_file_and_accumulate_crc( eth, bytes, 1 ) < 1 ) {
printf( "Ethernet: Error writing padding to \"%s\"\n", send_count, eth->txfile );
eth->tx.error = 1;
cont_run = 0;
397,6 → 418,10
}
 
 
/*
* TX clock
* Responsible for starting and finishing TX
*/
void eth_controller_tx_clock( struct eth_device *eth )
{
if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) ||
407,94 → 432,135
return;
 
/* If this is the first time, initialize TX state */
if ( !eth->tx.working ) {
/* Read buffer descriptor */
eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index];
if ( !eth->tx.working )
eth_start_tx( eth );
 
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, READY ) ) {
eth->tx.bytes_left = eth->tx.packet_length = GET_FIELD( eth->tx.bd, ETH_TX_BD, LENGTH );
eth->tx.bytes_sent = 0;
/* Check for end of transmission */
if ( eth->tx.working && (eth->tx.error || eth->tx.bytes_sent >= eth->tx.packet_length) )
eth_finish_tx( eth );
}
 
/* Initialize error status bits */
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, RETRANSMIT );
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, UNDERRUN );
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, NO_CARRIER );
SET_FIELD( eth->tx.bd, ETH_TX_BD, RETRY, 0 );
 
/* Find out minimum length */
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, PAD ) ||
TEST_FLAG( eth->regs.moder, ETH_MODER, PAD ) )
eth->tx.minimum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL );
else
eth->tx.minimum_length = eth->tx.packet_length;
/* Initialize state for packet transmission */
void eth_start_tx( struct eth_device *eth )
{
unsigned long length_with_crc;
/* Read buffer descriptor */
eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index];
 
/* Find out maximum length */
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, HUGEN ) )
eth->tx.maximum_length = eth->tx.packet_length;
else
eth->tx.maximum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL );
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, READY ) ) {
eth->tx.bytes_left = eth->tx.packet_length = GET_FIELD( eth->tx.bd, ETH_TX_BD, LENGTH );
eth->tx.bytes_sent = 0;
 
/* Do we need CRC on this packet? */
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, LAST)) )
eth->tx.crc = 1;
else
eth->tx.crc = 0;
/* Initialize error status bits */
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, RETRANSMIT );
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, UNDERRUN );
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, NO_CARRIER );
SET_FIELD( eth->tx.bd, ETH_TX_BD, RETRY, 0 );
 
dprintf(( "Ethernet: Starting TX of %u bytes (min. %u, max. %u)\n", eth->tx.packet_length,
eth->tx.minimum_length, eth->tx.maximum_length ));
/* Find out minimum length */
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, PAD ) ||
TEST_FLAG( eth->regs.moder, ETH_MODER, PAD ) )
eth->tx.minimum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL );
else
eth->tx.minimum_length = eth->tx.packet_length;
 
/* Write "header" to file */
write( eth->txfd, &(eth->tx.packet_length), sizeof(eth->tx.packet_length) );
/* Find out maximum length */
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, HUGEN ) )
eth->tx.maximum_length = eth->tx.packet_length;
else
eth->tx.maximum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL );
 
/* Tell DMA to start work */
set_dma_req_i( eth->dma, eth->tx_channel );
/* Do we need CRC on this packet? */
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, LAST)) )
eth->tx.add_crc = 1;
else
eth->tx.add_crc = 0;
eth_initialize_tx_crc( eth );
 
/* Signal to ourselves */
eth->tx.working = 1;
eth->tx.waiting_for_ack = 0;
}
dprintf(( "Ethernet: Starting TX of %u bytes (min. %u, max. %u)\n", eth->tx.packet_length,
eth->tx.minimum_length, eth->tx.maximum_length ));
 
/* Write "header" to file */
length_with_crc = eth->tx.add_crc ? (eth->tx.packet_length + 4) : eth->tx.packet_length;
write( eth->txfd, &length_with_crc, sizeof(length_with_crc) );
 
/* Tell DMA to start work */
set_dma_req_i( eth->dma, eth->tx_channel );
 
/* Signal to ourselves */
eth->tx.working = 1;
eth->tx.waiting_for_ack = 0;
}
}
 
/* Check for end of transmission */
if ( eth->tx.working && (eth->tx.error || eth->tx.bytes_sent >= eth->tx.packet_length) ) {
/*
 
/* Handle termination of sent packet */
void eth_finish_tx( struct eth_device *eth )
{
/*
* TODO:
* handle error state!
* somehow notify user (or does DMA take care of that?)
*/
 
if ( !eth->tx.waiting_for_ack ) {
dprintf(( "Ethernet: TX of %u bytes: %s\n", eth->tx.packet_length,
eth->tx.error ? "Error" : "Done" ));
if ( !eth->tx.waiting_for_ack ) {
dprintf(( "Ethernet: TX of %u bytes: %s\n", eth->tx.packet_length,
eth->tx.error ? "Error" : "Done" ));
 
/* Add CRC if needed */
if ( eth->tx.add_crc )
write( eth->txfd, &(eth->tx.crc_value), sizeof(eth->tx.crc_value) );
/* Write result to bd */
eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd;
/* Write result to bd */
eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd;
/* DMA flow control */
set_dma_nd_i( eth->dma, eth->tx_channel );
eth->tx.waiting_for_ack = 1;
}
else if ( check_dma_ack_o( eth->dma, eth->tx_channel ) ) {
clear_dma_nd_i( eth->dma, eth->tx_channel );
clear_dma_req_i( eth->dma, eth->tx_channel );
/* DMA flow control */
set_dma_nd_i( eth->dma, eth->tx_channel );
eth->tx.waiting_for_ack = 1;
}
else if ( check_dma_ack_o( eth->dma, eth->tx_channel ) ) {
clear_dma_nd_i( eth->dma, eth->tx_channel );
clear_dma_req_i( eth->dma, eth->tx_channel );
 
eth->tx.working = eth->tx.waiting_for_ack = 0;
eth->tx.working = eth->tx.waiting_for_ack = 0;
/* advance to next BD */
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, WRAP ) ||
eth->tx.bd_index >= ETH_BD_COUNT )
eth->tx.bd_index = 0;
else
++ eth->tx.bd_index;
}
/* advance to next BD */
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, WRAP ) ||
eth->tx.bd_index >= ETH_BD_COUNT )
eth->tx.bd_index = 0;
else
++ eth->tx.bd_index;
}
}
 
 
/* Initialize calculation of packet CRC */
ssize_t eth_initialize_tx_crc( struct eth_device *eth )
{
eth->tx.crc_value = 0xFFFFFFFF;
}
 
/* Write to TX file and update CRC value */
ssize_t eth_write_tx_file_and_accumulate_crc( struct eth_device *eth, const void *buf, size_t count )
{
ssize_t written = write( eth->txfd, buf, count );
if ( written > 0 ) {
/* TODO: Calculate CRC */
}
return written;
}
 
 
/*
* Clock for RX
* Responsible for starting and finisihing RX
*/
void eth_controller_rx_clock( struct eth_device *eth )
{
if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN ) ||
505,81 → 571,19
return;
 
/* If this is the first time, initialize RX state */
if ( !eth->rx.working ) {
/* Read buffer descriptor */
eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index];
if ( !eth->rx.working )
eth_start_rx( eth );
 
if ( TEST_FLAG( eth->rx.bd, ETH_TX_BD, READY ) ) {
/* Initialize error status bits */
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, DEFER );
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, COLLISION );
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, RETRANSMIT );
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, UNDERRUN );
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, NO_CARRIER );
SET_FIELD( eth->rx.bd, ETH_TX_BD, RETRY, 0 );
 
dprintf(( "Ethernet: Starting RX\n" ));
/* Setup file to read from */
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, LOOPBCK ) ) {
eth->rx.fd = eth->txfd;
eth->rx.offset = &(eth->loopback_offset);
} else {
eth->rx.fd = eth->rxfd;
eth->rx.offset = 0;
}
 
/* Read packet length */
if ( eth_read_rx_file( eth, &(eth->rx.packet_length), sizeof(eth->rx.packet_length) )
< sizeof(eth->rx.packet_length) ) {
/* TODO: just do what real ethernet would do */
printf( "eth_controller_rx_clock(): File does not have a packet ready for RX\n" );
cont_run = 0;
}
eth->rx.bytes_read = 0;
eth->rx.bytes_left = eth->rx.packet_length;
/* Tell DMA to start work */
set_dma_req_i( eth->dma, eth->rx_channel );
 
/* Signal to ourselves */
eth->rx.working = 1;
eth->rx.waiting_for_ack = 0;
}
}
 
/* Check for end of packet */
if ( eth->rx.working && (eth->rx.error || eth->rx.bytes_read >= eth->rx.packet_length) ) {
if ( !eth->rx.waiting_for_ack ) {
dprintf(( "Ethernet: RX of %u bytes: %s\n", eth->rx.packet_length,
eth->rx.error ? "Error" : "Done" ));
/* Write result to bd */
SET_FIELD( eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length );
eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
/* DMA flow control */
set_dma_nd_i( eth->dma, eth->rx_channel );
eth->rx.waiting_for_ack = 1;
}
else if ( check_dma_ack_o( eth->dma, eth->rx_channel ) ) {
clear_dma_nd_i( eth->dma, eth->rx_channel );
clear_dma_req_i( eth->dma, eth->rx_channel );
 
eth->rx.working = eth->rx.waiting_for_ack = 0;
/* advance to next BD */
if ( TEST_FLAG( eth->rx.bd, ETH_TX_BD, WRAP ) ||
eth->rx.bd_index >= ETH_BD_COUNT )
eth->rx.bd_index = eth->regs.rx_bd_adr;
else
++ eth->rx.bd_index;
}
}
if ( eth->rx.working && (eth->rx.error || eth->rx.bytes_read >= eth->rx.packet_length) )
eth_finish_rx( eth );
}
 
 
 
/*
* Utility function to read from the ethernet RX file
* 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 result;
602,3 → 606,141
 
return result;
}
 
 
/* "Skip" bytes in RX file */
void eth_skip_rx_file( struct eth_device *eth, off_t count )
{
eth->rx.offset += count;
}
 
/* Move RX file position back */
void eth_rewind_rx_file( struct eth_device *eth, off_t count )
{
eth->rx.offset -= count;
}
 
 
/* Initialize RX */
void eth_start_rx( struct eth_device *eth )
{
struct ether_header header;
static const unsigned char bcast_address[ETH_HLEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/* Read buffer descriptor */
eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index];
 
if ( TEST_FLAG( eth->rx.bd, ETH_TX_BD, READY ) ) {
/* Initialize error status bits */
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, DEFER );
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, COLLISION );
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, RETRANSMIT );
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, UNDERRUN );
CLEAR_FLAG( eth->rx.bd, ETH_TX_BD, NO_CARRIER );
SET_FIELD( eth->rx.bd, ETH_TX_BD, RETRY, 0 );
 
dprintf(( "Ethernet: Starting RX\n" ));
/* Setup file to read from */
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, LOOPBCK ) ) {
eth->rx.fd = eth->txfd;
eth->rx.offset = &(eth->loopback_offset);
} else {
eth->rx.fd = eth->rxfd;
eth->rx.offset = 0;
}
 
/* Read packet length */
if ( eth_read_rx_file( eth, &(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) */
printf( "eth_start_rx(): File does not have a packet ready for RX\n" );
cont_run = 0;
return;
}
 
/* Packet must be big enough to hold a header */
if ( eth->rx.packet_length < ETH_HLEN ){
dprintf(( "eth_start_rx(): Packet too small\n" ));
eth_rx_next_packet( eth );
return;
}
 
if ( eth_read_rx_file( eth, &header, ETH_HLEN ) < ETH_HLEN ) {
printf( "eth_start_rx(): Error reading packet header\n" );
cont_run = 0;
return;
}
 
/* We haven't formally "received" the header yet */
eth_rewind_rx_file( eth, ETH_HLEN );
eth->rx.bytes_read = 0;
eth->rx.bytes_left = eth->rx.packet_length;
/* Unless promiscous, don't accept all packets */
if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, PRO ) ) {
int for_us = (memcmp( header.ether_dhost, eth->mac_address, ETH_HLEN ) == 0);
int for_all = (memcmp( header.ether_dhost, bcast_address, ETH_HLEN ) == 0);
int good = for_us || (for_all && !TEST_FLAG( eth->regs.moder, ETH_MODER, BRO ) );
if ( !good ) {
dprintf(( "eth_start_rx(): Packet destination is %02X:%02X:%02X:%02X:%02X:%02x, rejecting\n",
header.ether_dhost[0], header.ether_dhost[1], header.ether_dhost[2],
header.ether_dhost[3], header.ether_dhost[4], header.ether_dhost[5] ));
eth_rx_next_packet( eth );
return;
}
}
 
/* TODO: Check CRC */
/* Tell DMA to start work */
set_dma_req_i( eth->dma, eth->rx_channel );
 
/* Signal to ourselves */
eth->rx.working = 1;
eth->rx.waiting_for_ack = 0;
}
}
 
 
/* Finish RX */
void eth_finish_rx( struct eth_device *eth )
{
if ( !eth->rx.waiting_for_ack ) {
dprintf(( "Ethernet: RX of %u bytes: %s\n", eth->rx.packet_length,
eth->rx.error ? "Error" : "Done" ));
/* Write result to bd */
SET_FIELD( eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length );
eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
/* DMA flow control */
set_dma_nd_i( eth->dma, eth->rx_channel );
eth->rx.waiting_for_ack = 1;
}
else if ( check_dma_ack_o( eth->dma, eth->rx_channel ) ) {
clear_dma_nd_i( eth->dma, eth->rx_channel );
clear_dma_req_i( eth->dma, eth->rx_channel );
 
eth->rx.working = eth->rx.waiting_for_ack = 0;
 
eth_rx_next_packet( eth );
}
}
 
 
/* Move to next RX BD */
void eth_rx_next_packet( struct eth_device *eth )
{
/* Skip any possible leftovers */
if ( eth->rx.bytes_left )
eth_skip_rx_file( eth, eth->rx.bytes_left );
/* advance to next BD */
if ( TEST_FLAG( eth->rx.bd, ETH_TX_BD, WRAP ) ||
eth->rx.bd_index >= ETH_BD_COUNT )
eth->rx.bd_index = eth->regs.rx_bd_adr;
else
++ eth->rx.bd_index;
}
/trunk/or1ksim/peripheral/ethernet.h
18,6 → 18,9
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#ifndef __OR1KSIM_PERIPHERAL_ETHERNET_H
#define __OR1KSIM_PERIPHERAL_ETHERNET_H
 
/* Exported function prototypes */
void eth_reset( void );
void eth_clock( void );
130,72 → 133,5
 
 
 
/* Implementatino of Ethernet MAC Registers and State */
struct eth_device
{
/* Base address in memory */
unsigned long baseaddr;
 
/* Which Ethernet MAC is this? */
unsigned eth_number;
 
/* Which DMA controller is this MAC connected to */
unsigned dma;
unsigned tx_channel;
unsigned rx_channel;
 
/* RX and TX file names and handles */
const char *rxfile, *txfile;
int txfd;
int rxfd;
off_t loopback_offset;
 
/* Current TX state */
struct
{
unsigned long bd_index;
unsigned long bd;
unsigned working, waiting_for_ack, error;
unsigned packet_length;
unsigned minimum_length, maximum_length;
unsigned crc;
unsigned bytes_left, bytes_sent;
} tx;
 
/* Current RX state */
struct
{
unsigned long bd_index;
unsigned long bd;
int fd;
off_t *offset;
unsigned working, error, waiting_for_ack;
unsigned packet_length, bytes_read, bytes_left;
} rx;
 
/* Visible registers */
struct
{
unsigned long moder;
unsigned long int_source;
unsigned long int_mask;
unsigned long ipgt;
unsigned long ipgr1;
unsigned long ipgr2;
unsigned long packetlen;
unsigned long collconf;
unsigned long rx_bd_adr;
unsigned long controlmoder;
unsigned long miimoder;
unsigned long miicommand;
unsigned long miiaddress;
unsigned long miitx_data;
unsigned long miirx_data;
unsigned long miistatus;
unsigned long mac_addr0;
unsigned long mac_addr1;
/* Buffer descriptors */
unsigned long bd_ram[ETH_BD_SPACE / 4];
} regs;
};
#endif /* __OR1KSIM_PERIPHERAL_ETHERNET_H */
/trunk/or1ksim/peripheral/ethernet_i.h
0,0 → 1,158
/* ethernet_i.h -- Definition of internal types and structures for Ethernet MAC
Copyright (C) 2001 Erez Volk, erez@mailandnews.comopencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#ifndef __OR1KSIM_PERIPHERAL_ETHERNET_I_H
#define __OR1KSIM_PERIPHERAL_ETHERNET_I_H
 
#include "ethernet.h"
#include "config.h"
 
/*
* Ethernet protocol definitions
*/
#if HAVE_NET_ETHERNET_H
# include <net/ethernet.h>
#else /* !HAVE_NET_ETHERNET_H -*/
 
#include <sys/types.h>
 
#define ETH_ALEN 6
 
struct ether_addr
{
u_int8_t ether_addr_octet[ETH_ALEN];
};
 
struct ether_header
{
u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */
u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */
u_int16_t ether_type; /* packet type ID field */
};
 
/* Ethernet protocol ID's */
#define ETHERTYPE_PUP 0x0200 /* Xerox PUP */
#define ETHERTYPE_IP 0x0800 /* IP */
#define ETHERTYPE_ARP 0x0806 /* Address resolution */
#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */
 
#define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */
#define ETHER_TYPE_LEN 2 /* bytes in type field */
#define ETHER_CRC_LEN 4 /* bytes in CRC field */
#define ETHER_HDR_LEN ETH_HLEN /* total octets in header */
#define ETHER_MIN_LEN (ETH_ZLEN + ETHER_CRC_LEN) /* min packet length */
#define ETHER_MAX_LEN (ETH_FRAME_LEN + ETHER_CRC_LEN) /* max packet length */
 
/* make sure ethenet length is valid */
#define ETHER_IS_VALID_LEN(foo) \
((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
 
/*
* The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
* (type-ETHERTYPE_TRAIL)*512 bytes of data followed
* by an ETHER type (as given above) and then the (variable-length) header.
*/
#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */
#define ETHERTYPE_NTRAILER 16
 
#define ETHERMTU ETH_DATA_LEN
#define ETHERMIN (ETHER_MIN_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
 
#endif /* HAVE_NET_ETHERNET_H */
 
 
/*
* Implementatino of Ethernet MAC Registers and State
*/
struct eth_device
{
/* Base address in memory */
unsigned long baseaddr;
 
/* Which Ethernet MAC is this? */
unsigned eth_number;
 
/* Which DMA controller is this MAC connected to */
unsigned dma;
unsigned tx_channel;
unsigned rx_channel;
 
/* Our address */
unsigned char mac_address[ETH_ALEN];
 
/* RX and TX file names and handles */
const char *rxfile, *txfile;
int txfd;
int rxfd;
off_t loopback_offset;
 
/* Current TX state */
struct
{
unsigned long bd_index;
unsigned long bd;
unsigned working, waiting_for_ack, error;
unsigned packet_length;
unsigned minimum_length, maximum_length;
unsigned add_crc;
unsigned long crc_value;
unsigned bytes_left, bytes_sent;
} tx;
 
/* Current RX state */
struct
{
unsigned long bd_index;
unsigned long bd;
int fd;
off_t *offset;
unsigned working, error, waiting_for_ack;
unsigned packet_length, bytes_read, bytes_left;
} rx;
 
/* Visible registers */
struct
{
unsigned long moder;
unsigned long int_source;
unsigned long int_mask;
unsigned long ipgt;
unsigned long ipgr1;
unsigned long ipgr2;
unsigned long packetlen;
unsigned long collconf;
unsigned long rx_bd_adr;
unsigned long controlmoder;
unsigned long miimoder;
unsigned long miicommand;
unsigned long miiaddress;
unsigned long miitx_data;
unsigned long miirx_data;
unsigned long miistatus;
/* Buffer descriptors */
unsigned long bd_ram[ETH_BD_SPACE / 4];
} regs;
};
 
 
 
 
#endif /* __OR1KSIM_PERIPHERAL_ETHERNET_I_H */

powered by: WebSVN 2.1.0

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