URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 701 to Rev 702
- ↔ Reverse comparison
Rev 701 → Rev 702
/trunk/or1ksim/sim.cfg
110,7 → 110,7
name = "FLASH" |
ce = 0 |
baseaddr = 0x00000000 |
size = 0x000200000 |
size = 0x00200000 |
delayr = 10 |
delayw = -1 |
enddevice |
118,8 → 118,8
device 1 |
name = "RAM" |
ce = 1 |
baseaddr = 0x04000000 |
size = 0x04000000 |
baseaddr = 0x40000000 |
size = 0x00200000 |
delayr = 2 |
delayw = 4 |
enddevice |
354,7 → 354,7
|
section sim |
/* verbose = 1 */ |
debug = 0 |
debug = 3 |
profile = 0 |
prof_fn = "sim.profile" |
mprofile = 0 |
513,7 → 513,7
*/ |
|
section debug |
enabled = 0 |
enabled = 1 |
gdb_enabled = 0 |
server_port = 9999 |
vapi_id = 0xFFFF |
535,7 → 535,7
*/ |
|
section mc |
enabled = 1 |
enabled = 0 |
baseaddr = 0x60000000 |
POC = 0x00000008 /* Power on configuration register */ |
end |
647,9 → 647,9
*/ |
|
section ethernet |
nethernets = 0 |
nethernets = 1 |
|
/* |
|
device 0 |
baseaddr = 0x88000000 |
dma = 0 |
658,7 → 658,7
rxfile = "/tmp/eth0.rx" |
txfile = "/tmp/eth0.tx" |
enddevice |
*/ |
|
end |
|
/* GPIO SECTION |
/trunk/or1ksim/cpu/common/stats.c
76,7 → 76,7
{ |
int i = 0; |
|
debug(3,"adddstats start\n"); |
debug(7,"adddstats start\n"); |
|
while((dstats[i].insn1 != item1 || dstats[i].insn2 != item2) && (i < DSTATS_LEN) && dstats[i].insn1 >= 0) i++; |
|
/trunk/or1ksim/testbench/eth.c
1,20 → 1,20
/* Ethernet test */ |
|
#include "spr_defs.h" |
#include "support.h" |
|
typedef long off_t; |
|
#include "../peripheral/fields.h" |
#include "../peripheral/dma.h" |
#include "../peripheral/ethernet.h" |
|
#define ETH_BASE 0x88000000LU |
#define DMA_BASE 0x90000000LU |
#define ETH_INT_LINE 0x15 |
|
typedef volatile unsigned long *REGISTER; |
|
REGISTER |
eth_moder = (unsigned long *)(ETH_BASE + ETH_MODER), |
eth_moder = (unsigned long *)(ETH_BASE + ETH_MODER), |
eth_int_source = (unsigned long *)(ETH_BASE + ETH_INT_SOURCE), |
eth_int_mask = (unsigned long *)(ETH_BASE + ETH_INT_MASK), |
eth_ipgt = (unsigned long *)(ETH_BASE + ETH_IPGT), |
32,27 → 32,30
eth_miistatus = (unsigned long *)(ETH_BASE + ETH_MIISTATUS), |
eth_mac_addr0 = (unsigned long *)(ETH_BASE + ETH_MAC_ADDR0), |
eth_mac_addr1 = (unsigned long *)(ETH_BASE + ETH_MAC_ADDR1), |
eth_bd_base = (unsigned long *)(ETH_BASE + ETH_BD_BASE), |
dma_csr = (unsigned long *)(DMA_BASE + DMA_CSR), |
dma_int_msk_a = (unsigned long *)(DMA_BASE + DMA_INT_MSK_A), |
dma_int_msk_b = (unsigned long *)(DMA_BASE + DMA_INT_MSK_B), |
dma_int_src_a = (unsigned long *)(DMA_BASE + DMA_INT_SRC_A), |
dma_int_src_b = (unsigned long *)(DMA_BASE + DMA_INT_SRC_B), |
dma_ch0_csr = (unsigned long *)(DMA_BASE + DMA_CH_BASE + DMA_CH_CSR), |
dma_ch0_sz = (unsigned long *)(DMA_BASE + DMA_CH_BASE + DMA_CH_SZ), |
dma_ch0_a0 = (unsigned long *)(DMA_BASE + DMA_CH_BASE + DMA_CH_A0), |
dma_ch0_am0 = (unsigned long *)(DMA_BASE + DMA_CH_BASE + DMA_CH_AM0), |
dma_ch0_a1 = (unsigned long *)(DMA_BASE + DMA_CH_BASE + DMA_CH_A1), |
dma_ch0_am1 = (unsigned long *)(DMA_BASE + DMA_CH_BASE + DMA_CH_AM1), |
dma_ch0_desc = (unsigned long *)(DMA_BASE + DMA_CH_BASE + DMA_CH_DESC); |
eth_bd_base = (unsigned long *)(ETH_BASE + ETH_BD_BASE); |
|
struct DMA_DESCRIPTOR |
unsigned int_happend; |
unsigned char r_packet[0x1000]; |
unsigned char s_packet[1003]; |
|
|
void interrupt_handler() |
{ |
unsigned long csr; |
unsigned long adr0; |
unsigned long adr1; |
unsigned long next; |
}; |
unsigned x; |
printf ("Int\n"); |
switch (*eth_int_source & 0xf) { |
case 0x1: printf ("Transmit Error.\n"); break; |
case 0x2: printf ("Receive Buffer\n");break; |
case 0x4: printf ("Receive Frame\n");break; |
case 0x8: printf ("Busy\n"); break; |
case 0x0: printf ("Modem Status.\n"); break; |
default: |
printf ("Invalid iir @ %i\n", __LINE__); |
exit (1); |
} |
mtspr(SPR_PICSR, 0); |
int_happend = 1; |
} |
|
static void set_mac( void ) |
{ |
63,51 → 66,113
static void transmit_one_packet( void ) |
{ |
unsigned i; |
unsigned char packet[1003]; |
struct DMA_DESCRIPTOR desc; |
|
|
/* Initialize packet */ |
for ( i = 0; i < sizeof(packet); ++ i ) |
packet[i] = (unsigned char)i; |
for ( i = 0; i < sizeof(s_packet); ++ i ) |
s_packet[i] = (unsigned char)i; |
|
/* Set Ethernet BD size */ |
*eth_bd_base = sizeof(packet) << ETH_TX_BD_LENGTH_OFFSET; |
/* Set Ethernet BD */ |
SET_FIELD(eth_bd_base[0], ETH_TX_BD, LENGTH, sizeof(s_packet)); |
eth_bd_base[1] = (unsigned long)s_packet; |
|
/* Set dma stuff */ |
desc.csr = 1600; /* transfer size; Ethernet will stop the DMA after packet is sent */ |
desc.adr0 = (unsigned long)packet; |
desc.adr1 = ETH_BASE + ETH_DMA_RX_TX; |
desc.csr |= FLAG_MASK( DMA_DESC_CSR, EOL ) | FLAG_MASK( DMA_DESC_CSR, INC_SRC ); |
desc.next = 0xDEADDEADUL; /* just to help debugging */ |
*dma_ch0_sz = 1UL << DMA_CH_SZ_CHK_SZ_OFFSET; /* Chunk size = 1 word */ |
*dma_ch0_desc = (unsigned long)&desc; /* Tell DMA channel where the descriptor is */ |
/* Start Ethernet */ |
SET_FLAG(eth_bd_base[0], ETH_TX_BD, READY); |
SET_FLAG(*eth_moder, ETH_MODER, TXEN); |
|
/* Now wait till sent */ |
while ( TEST_FLAG( eth_bd_base[0], ETH_TX_BD, READY ) ); |
CLEAR_FLAG(*eth_moder, ETH_MODER, TXEN); |
} |
|
/* Start DMA (it will wait for request from Ethernet) */ |
*dma_ch0_csr = FLAG_MASK( DMA_CH_CSR, CH_EN ) /* Enable channel */ | |
FLAG_MASK( DMA_CH_CSR, USE_ED ) /* Use linked lists */ | |
FLAG_MASK( DMA_CH_CSR, MODE ) /* Wait for HW handshake */ | |
FLAG_MASK( DMA_CH_CSR, DST_SEL ) /* Interface 1 is the destination (meaningless for simulation) */; |
static void transmit_one_packet_int( void ) |
{ |
unsigned i; |
|
/* Initialize packet */ |
for ( i = 0; i < sizeof(s_packet); ++ i ) |
s_packet[i] = (unsigned char)i; |
|
/* Set Ethernet BD */ |
SET_FIELD(eth_bd_base[2], ETH_TX_BD, LENGTH, sizeof(s_packet)); |
eth_bd_base[3] = (unsigned long)s_packet; |
|
/* Start Ethernet */ |
*eth_bd_base |= FLAG_MASK( ETH_TX_BD, READY ); /* signal BD as ready */ |
*eth_moder |= FLAG_MASK( ETH_MODER, TXEN ) | FLAG_MASK( ETH_MODER, DMAEN ); |
SET_FLAG(eth_bd_base[2], ETH_TX_BD, READY); |
SET_FLAG(*eth_moder, ETH_MODER, TXEN); |
} |
|
/* Now wait till DMA finishes */ |
while ( TEST_FLAG( *dma_ch0_csr, DMA_CH_CSR, BUSY ) ) |
; |
|
static void receive_one_packet(void) |
{ |
unsigned int i; |
unsigned int len; |
|
eth_bd_base[*eth_tx_bd_num + 1] = (unsigned long)r_packet; |
|
SET_FLAG(eth_bd_base[*eth_tx_bd_num], ETH_RX_BD, READY); |
SET_FLAG(*eth_moder, ETH_MODER, RXEN); |
|
while ( TEST_FLAG( eth_bd_base[*eth_tx_bd_num], ETH_RX_BD, READY ) ); |
CLEAR_FLAG(*eth_moder, ETH_MODER, RXEN); |
|
len = GET_FIELD(eth_bd_base[*eth_tx_bd_num], ETH_RX_BD, LENGTH); |
for (i=0; i<len; i++) |
if (r_packet[i] != (unsigned char)i) |
{ |
printf("Failed at byte %d. expect %d, received %d\n", i, i, r_packet[i]); |
exit(1); |
} |
} |
|
static void receive_one_packet_int(void) |
{ |
unsigned int i; |
unsigned int len; |
|
eth_bd_base[*eth_tx_bd_num + 3] = (unsigned long)r_packet; |
|
SET_FLAG(eth_bd_base[*eth_tx_bd_num + 2], ETH_RX_BD, READY); |
SET_FLAG(*eth_moder, ETH_MODER, RXEN); |
|
while ( TEST_FLAG( eth_bd_base[*eth_tx_bd_num + 2], ETH_RX_BD, READY ) ); |
CLEAR_FLAG(*eth_moder, ETH_MODER, RXEN); |
|
len = GET_FIELD(eth_bd_base[*eth_tx_bd_num + 2], ETH_RX_BD, LENGTH); |
for (i=0; i<len; i++) |
if (r_packet[i] != (unsigned char)i) |
{ |
printf("Failed at byte %d. expect %d, received %d\n", i, i, r_packet[i]); |
exit(1); |
} |
} |
|
int main() |
{ |
printf( "Starting Ethernet test\n" ); |
|
set_mac(); |
transmit_one_packet(); |
|
/* non iterrupt test */ |
transmit_one_packet(); |
receive_one_packet(); |
|
/* interrupt test */ |
excpt_int = (unsigned long)interrupt_handler; |
/* Enable interrupts */ |
mtspr (SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE); |
mtspr (SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << ETH_INT_LINE)); |
|
|
|
transmit_one_packet_int(); |
/* |
while (!int_happend); |
receive_one_packet_int(); |
while (!int_happend); |
*/ |
|
printf( "Ending Ethernet test\n" ); |
|
report (0xdeaddead); |
report (0xdeaddead); |
return 0; |
} |
|
/trunk/or1ksim/peripheral/Makefile.in
105,7 → 105,7
host_os = @host_os@ |
|
noinst_LIBRARIES = libperipheral.a |
libperipheral_a_SOURCES = 16450.c dma.c mc.c ethernet.c crc32.c gpio.c vga.c fb.c ps2kbd.c |
libperipheral_a_SOURCES = 16450.c dma.c mc.c eth.c crc32.c gpio.c vga.c fb.c ps2kbd.c |
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs |
CONFIG_HEADER = ../config.h |
CONFIG_CLEAN_FILES = |
117,8 → 117,8
LDFLAGS = @LDFLAGS@ |
LIBS = @LIBS@ |
libperipheral_a_LIBADD = |
libperipheral_a_OBJECTS = 16450.o dma.o mc.o ethernet.o crc32.o gpio.o \ |
vga.o fb.o ps2kbd.o |
libperipheral_a_OBJECTS = 16450.o dma.o mc.o eth.o crc32.o gpio.o vga.o \ |
fb.o ps2kbd.o |
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
CCLD = $(CC) |
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ |
129,7 → 129,7
|
TAR = gtar |
GZIP_ENV = --best |
DEP_FILES = .deps/16450.P .deps/crc32.P .deps/dma.P .deps/ethernet.P \ |
DEP_FILES = .deps/16450.P .deps/crc32.P .deps/dma.P .deps/eth.P \ |
.deps/fb.P .deps/gpio.P .deps/mc.P .deps/ps2kbd.P .deps/vga.P |
SOURCES = $(libperipheral_a_SOURCES) |
OBJECTS = $(libperipheral_a_OBJECTS) |
/trunk/or1ksim/peripheral/eth.c
23,7 → 23,6
#include <stdio.h> |
#include <string.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <sys/stat.h> |
#include <fcntl.h> |
#include <sys/poll.h> |
38,9 → 37,10
#include "fields.h" |
#include "crc32.h" |
|
|
static struct eth_device eths[MAX_ETHERNETS]; |
|
/* simulator interface */ |
static void eth_reset_controller( struct eth_device *eth); |
/* register interface */ |
static void eth_write32( unsigned long addr, unsigned long value ); |
static unsigned long eth_read32( unsigned long addr ); |
49,9 → 49,13
static void eth_controller_rx_clock( struct eth_device * ); |
/* utility functions */ |
static int eth_find_controller( unsigned long addr, struct eth_device **eth, unsigned long *reladdr ); |
|
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 void eth_rx_next_packet( struct eth_device * ); |
static void eth_write_tx_bd_num( struct eth_device *, unsigned long value ); |
/* ========================================================================= */ |
/* TX LOGIC */ |
/* TX LOGIC */ |
/*---------------------------------------------------------------------------*/ |
|
/* |
60,88 → 64,155
*/ |
void eth_controller_tx_clock( struct eth_device *eth ) |
{ |
unsigned long breakpoint = 0; |
int breakpoint = 0; |
int bAdvance = 1; |
struct sockaddr_ll sll; |
|
long nwritten; |
unsigned long read_word; |
|
switch (eth->tx.state) { |
case ETH_TXSTATE_IDLE: |
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) || (eth->txfd <= 0) ) { |
|
/* wait for TxBuffer to be ready */ |
eth->tx.state = ETH_TXSTATE_WAIT4BD; |
} |
break; |
case ETH_TXSTATE_IDLE: |
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) ) { |
|
/* wait for TxBuffer to be ready */ |
debug (3, "TX - entering state WAIT4BD\n"); |
eth->tx.state = ETH_TXSTATE_WAIT4BD; |
} |
break; |
case ETH_TXSTATE_WAIT4BD: |
/* Read buffer descriptor */ |
eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index]; |
eth->tx.bd_addr = eth->regs.bd_ram[eth->tx.bd_index + 1]; |
|
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, READY ) ) { |
/*****************/ |
/* initialize TX */ |
eth->tx.bytes_left = eth->tx.packet_length = GET_FIELD( eth->tx.bd, ETH_TX_BD, LENGTH ); |
eth->tx.bytes_sent = 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 ); |
|
/* 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; |
|
/* 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 ); |
|
/* 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 ); |
|
debug( 3, "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) ); |
|
/************************************************/ |
/* start transmit with reading packet into FIFO */ |
eth->tx.state = ETH_TXSTATE_READFIFO; |
} |
else if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) ) { |
/* stop TX logic */ |
eth->tx.state = ETH_TXSTATE_IDLE; |
} |
|
/* stay in this state if (TXEN && !READY) */ |
break; |
/* Read buffer descriptor */ |
eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index]; |
eth->tx.bd_addr = eth->regs.bd_ram[eth->tx.bd_index + 1]; |
|
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, READY ) ) { |
/*****************/ |
/* initialize TX */ |
eth->tx.bytes_left = eth->tx.packet_length = GET_FIELD( eth->tx.bd, ETH_TX_BD, LENGTH ); |
eth->tx.bytes_sent = 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 ); |
|
/* 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; |
|
/* 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 ); |
|
/* 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; |
|
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, DLYCRCEN ) ) |
eth->tx.crc_dly = 1; |
else |
eth->tx.crc_dly = 0; |
/* XXX - For now we skip CRC calculation */ |
|
debug( 3, "Ethernet: Starting TX of %u bytes (min. %u, max. %u)\n", eth->tx.packet_length, |
eth->tx.minimum_length, eth->tx.maximum_length ); |
|
if (eth->rtx_type == ETH_RTX_FILE) { |
/* write packet length to file */ |
nwritten = write( eth->txfd, &(eth->tx.packet_length), sizeof(eth->tx.packet_length) ); |
} |
|
/************************************************/ |
/* start transmit with reading packet into FIFO */ |
debug (3, "TX - entering state READFIFO\n"); |
eth->tx.state = ETH_TXSTATE_READFIFO; |
} |
else if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN ) ) { |
/* stop TX logic */ |
debug (3, "TX - entering state IDLE\n"); |
eth->tx.state = ETH_TXSTATE_IDLE; |
} |
|
/* stay in this state if (TXEN && !READY) */ |
break; |
case ETH_TXSTATE_READFIFO: |
if ( eth->tx.bytes_sent < eth->tx.packet_length ) { |
eth->tx_buff[eth->tx.bytes_sent\4] = eval_mem32(eth->tx.bytes_sent + eth->tx.bd_addr, &breakpoint) |
eth->tx.bytes_sent += 4; |
} |
else { |
eth->tx.state = ETH_TXSTATE_TRANSMIT; |
} |
break; |
if ( eth->tx.bytes_sent < eth->tx.packet_length ) { |
read_word = eval_mem32(eth->tx.bytes_sent + eth->tx.bd_addr, &breakpoint); |
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+2] = (unsigned char)(read_word >> 8); |
eth->tx_buff[eth->tx.bytes_sent+3] = (unsigned char)(read_word); |
eth->tx.bytes_sent += 4; |
} |
else { |
debug (3, "TX - entering state TRANSMIT\n"); |
eth->tx.state = ETH_TXSTATE_TRANSMIT; |
} |
break; |
case ETH_TXSTATE_TRANSMIT: |
write( eth->txfd, eth->tx_buff, eth->tx.packet_length ); |
eth->tx.state = ETH_TXSTATE_IDLE; |
break; |
/* send packet */ |
switch (eth->rtx_type) { |
case ETH_RTX_FILE: |
nwritten = write( eth->txfd, eth->tx_buff, eth->tx.packet_length ); |
break; |
case ETH_RTX_SOCK: |
memset(&sll, 0, sizeof(sll)); |
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)); |
break; |
} |
|
/* set BD status */ |
if (nwritten == eth->tx.packet_length) { |
CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY); |
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB); |
|
debug (3, "TX - entering state IDLE\n"); |
eth->tx.state = ETH_TXSTATE_IDLE; |
debug (3, "send (%d)bytes OK\n", nwritten); |
} |
else { |
/* XXX - implement retry mechanism here! */ |
CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY); |
CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION); |
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE); |
|
debug (3, "TX - entering state IDLE\n"); |
eth->tx.state = ETH_TXSTATE_IDLE; |
debug (3, "send FAILED!\n"); |
} |
|
eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd; |
|
/* advance to next BD */ |
if (bAdvance) { |
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 += 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; |
} |
} |
/* ========================================================================= */ |
148,7 → 219,7
|
|
/* ========================================================================= */ |
/* RX LOGIC */ |
/* RX LOGIC */ |
/*---------------------------------------------------------------------------*/ |
|
/* |
157,23 → 228,203
*/ |
void eth_controller_rx_clock( struct eth_device *eth ) |
{ |
int i; |
int breakpoint = 0; |
long nread; |
unsigned long send_word; |
|
fd_set rfds; |
|
switch (eth->rx.state) { |
case ETH_RXSTATE_IDLE: |
break; |
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) ) { |
debug (3, "RX - entering state WAIT4BD\n"); |
eth->rx.state = ETH_RXSTATE_WAIT4BD; |
} |
break; |
|
case ETH_RXSTATE_WAIT4BD: |
break; |
eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index]; |
eth->rx.bd_addr = eth->regs.bd_ram[eth->rx.bd_index + 1]; |
|
if ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, READY ) ) { |
/*****************/ |
/* Initialize RX */ |
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, DRIBBLE ); |
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, TOOBIG ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, TOOSHORT ); |
|
debug( 3, "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; |
} |
debug (3, "RX - entering state RECV\n"); |
eth->rx.state = ETH_RXSTATE_RECV; |
} |
else { |
nread = recv(eth->rtx_sock, eth->rx_buff, ETH_MAXPL, MSG_PEEK); |
if (nread > 0) { |
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY); |
} |
} |
break; |
|
case ETH_RXSTATE_RECV: |
break; |
switch (eth->rtx_type) { |
case ETH_RTX_FILE: |
/* 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) */ |
debug (4, "eth_start_rx(): File does not have a packet ready for RX\n" ); |
cont_run = 0; |
break; |
} |
|
/* Packet must be big enough to hold a header */ |
if ( eth->rx.packet_length < ETH_HLEN ){ |
debug( 3, "eth_start_rx(): Packet too small\n" ); |
eth_rx_next_packet( eth ); |
|
debug (3, "RX - entering state IDLE\n"); |
eth->rx.state = ETH_RXSTATE_IDLE; |
break; |
} |
|
eth->rx.bytes_read = 0; |
eth->rx.bytes_left = eth->rx.packet_length; |
|
/* for now Read entire packet into memory */ |
nread = eth_read_rx_file( eth, eth->rx_buff, eth->rx.bytes_left ); |
if ( nread < eth->rx.bytes_left ) |
debug (3, "Read %d from %d. Error!\n", nread, eth->rx.bytes_left); |
eth->rx.error = 1; |
break; |
|
case ETH_RTX_SOCK: |
nread = recv(eth->rtx_sock, eth->rx_buff, ETH_MAXPL, MSG_DONTWAIT); |
if (nread < 0) { |
if ( errno != EAGAIN ) { |
debug (3, "recv() FAILED!\n"); |
break; |
} |
else { |
break; |
} |
} |
eth->rx.bytes_left = nread; |
eth->rx.bytes_read = 0; |
|
debug (3, "RX - entering state WRITEFIFO\n"); |
eth->rx.state = ETH_RXSTATE_WRITEFIFO; |
|
break; |
} |
break; |
|
case ETH_RXSTATE_WRITEFIFO: |
break; |
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+2] << 8) | |
((unsigned long)eth->rx_buff[eth->rx.bytes_read+3] ); |
set_mem32( eth->rx.bd_addr + eth->rx.bytes_read, send_word, &breakpoint); |
|
/* update counters */ |
debug (3, "Write %d, left %d - %08lXd\n", eth->rx.bytes_read, eth->rx.bytes_left, send_word); |
eth->rx.bytes_left -= 4; |
eth->rx.bytes_read += 4; |
if ( eth->rx.bytes_left <= 0 ) { |
/* Write result to bd */ |
SET_FIELD( eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, READY); |
SET_FLAG( eth->regs.int_source, ETH_INT_SOURCE, RXF); |
|
if ( eth->rx.packet_length < GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL ) ) |
SET_FLAG( eth->rx.bd, ETH_RX_BD, TOOBIG); |
if ( eth->rx.packet_length > GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL ) ) |
SET_FLAG( eth->rx.bd, ETH_RX_BD, TOOSHORT); |
|
eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd; |
|
/* advance to next BD */ |
if ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, WRAP ) || eth->rx.bd_index >= ETH_BD_COUNT ) |
eth->tx.bd_index = eth->regs.tx_bd_num; |
else |
eth->tx.bd_index += 2; |
|
if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, RXF_M) ) { |
report_interrupt( eth->mac_int ); |
} |
|
/* ready to receive next packet */ |
debug (3, "RX - entering state IDLE\n"); |
eth->rx.state = ETH_RXSTATE_IDLE; |
} |
break; |
} |
} |
|
/* ========================================================================= */ |
/* 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 ); |
} |
/* "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; |
} |
/* |
* 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; |
|
if ( eth->rx.fd <= 0 ) { |
debug( 3, "Ethernet: No RX file\n" ); |
return 0; |
} |
|
if ( eth->rx.offset ) |
if ( lseek( eth->rx.fd, *(eth->rx.offset), SEEK_SET ) == (off_t)-1 ) { |
debug( 3, "Ethernet: Error seeking RX file\n" ); |
return 0; |
} |
|
result = read( eth->rx.fd, buf, count ); |
|
if ( eth->rx.offset && result >= 0 ) |
*(eth->rx.offset) += result; |
|
return result; |
} |
|
/* ========================================================================= */ |
|
/* |
Reset. Initializes all registers to default and places devices in |
memory address space. |
Reset. Initializes all registers to default and places devices in |
memory address space. |
*/ |
void eth_reset() |
{ |
181,61 → 432,134
unsigned i; |
|
if (!config.nethernets) |
return; |
return; |
|
if ( first_time ) { |
memset( eths, 0, sizeof(eths) ); |
first_time = 0; |
memset( eths, 0, sizeof(eths) ); |
first_time = 0; |
} |
|
for ( i = 0; i < MAX_ETHERNETS; ++ i ) { |
struct eth_device *eth = &(eths[i]); |
|
eth->eth_number = i; |
eth->baseaddr = config.ethernets[i].baseaddr; |
|
if ( eth->baseaddr != 0 ) { |
/* Mark which DMA controller and channels */ |
eth->dma = config.ethernets[i].dma; |
eth->tx_channel = config.ethernets[i].tx_channel; |
eth->rx_channel = config.ethernets[i].rx_channel; |
|
/* (Re-)open TX/RX files */ |
eth->rxfile = config.ethernets[i].rxfile; |
eth->txfile = config.ethernets[i].txfile; |
eth_close_files( eth ); |
if ( (eth->rxfd = open( eth->rxfile, O_RDONLY )) < 0 ) |
fprintf( stderr, "Cannot open Ethernet RX file \"%s\"\n", eth->rxfile ); |
if ( (eth->txfd = open( eth->txfile, |
O_RDWR | O_CREAT | O_APPEND | O_SYNC, |
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) < 0 ) |
fprintf( stderr, "Cannot open Ethernet TX file \"%s\"\n", eth->txfile ); |
eth->loopback_offset = lseek( eth->txfd, 0, SEEK_END ); |
|
/* Set registers to default values */ |
memset( &(eth->regs), 0, sizeof(eth->regs) ); |
eth->regs.moder = 0x0000A000; |
eth->regs.ipgt = 0x00000012; |
eth->regs.ipgr1 = 0x0000000C; |
eth->regs.ipgr2 = 0x00000012; |
eth->regs.packetlen = 0x003C0600; |
eth->regs.collconf = 0x000F003F; |
eth->regs.miimoder = 0x00000064; |
eth->regs.tx_tb_num = 0x00000080; |
|
/* Initialize TX/RX status */ |
memset( &(eth->tx), 0, sizeof(eth->tx) ); |
memset( &(eth->rx), 0, sizeof(eth->rx) ); |
eth->rx.bd_index = eth->regs.tx_bd_num; |
|
/* Register memory range */ |
register_memoryarea( eth->baseaddr, ETH_ADDR_SPACE, 4, eth_read32, eth_write32 ); |
} |
struct eth_device *eth = &(eths[i]); |
|
eth->eth_number = i; |
eth_reset_controller( eth ); |
} |
} |
/* ========================================================================= */ |
|
|
static void eth_reset_controller(struct eth_device *eth) |
{ |
int i = eth->eth_number; |
int j; |
struct sockaddr_ll sll; |
|
eth->baseaddr = config.ethernets[i].baseaddr; |
|
if ( eth->baseaddr != 0 ) { |
/* Mark which DMA controller and channels */ |
eth->dma = config.ethernets[i].dma; |
eth->tx_channel = config.ethernets[i].tx_channel; |
eth->rx_channel = config.ethernets[i].rx_channel; |
eth->rtx_type = ETH_RTX_SOCK/*config.ethernets[i].rtx_type*/; |
|
switch (eth->rtx_type) { |
case ETH_RTX_FILE: |
/* (Re-)open TX/RX files */ |
eth->rxfile = config.ethernets[i].rxfile; |
eth->txfile = config.ethernets[i].txfile; |
|
if ( eth->rxfd > 0 ) |
close( eth->rxfd ); |
if ( eth->txfd > 0 ) |
close( eth->txfd ); |
eth->rxfd = eth->txfd = -1; |
|
if ( (eth->rxfd = open( eth->rxfile, O_RDONLY )) < 0 ) |
fprintf( stderr, "Cannot open Ethernet RX file \"%s\"\n", eth->rxfile ); |
if ( (eth->txfd = open( eth->txfile, |
O_RDWR | O_CREAT | O_APPEND | O_SYNC, |
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) < 0 ) |
fprintf( stderr, "Cannot open Ethernet TX file \"%s\"\n", eth->txfile ); |
eth->loopback_offset = lseek( eth->txfd, 0, SEEK_END ); |
|
break; |
case ETH_RTX_SOCK: |
/* (Re-)open TX/RX sockets */ |
if (eth->rtx_sock != 0) |
break; |
|
debug (3, "RTX oppening socket...\n"); |
eth->rtx_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); |
if (eth->rtx_sock == -1) { |
fprintf( stderr, "Cannot open rtx_sock.\n"); |
return; |
} |
|
/* get interface index number */ |
debug (3, "RTX getting interface...\n"); |
memset(&(eth->ifr), 0, sizeof(eth->ifr)); |
strncpy(eth->ifr.ifr_name, "lo"/*config.ethernets[i].sock_interface*/, IFNAMSIZ); |
if (ioctl(eth->rtx_sock, SIOCGIFINDEX, &(eth->ifr)) == -1) { |
fprintf( stderr, "SIOCGIFINDEX failed!\n"); |
return; |
} |
debug (3, "RTX Socket Interface : %d\n", eth->ifr.ifr_ifindex); |
|
/* Bind to interface... */ |
debug (3, "Binding to the interface ifindex=%d\n", eth->ifr.ifr_ifindex); |
memset(&sll, 0xff, sizeof(sll)); |
sll.sll_family = AF_PACKET; /* allways AF_PACKET */ |
sll.sll_protocol = htons(ETH_P_ALL); |
sll.sll_ifindex = eth->ifr.ifr_ifindex; |
if (bind(eth->rtx_sock, (struct sockaddr *)&sll, sizeof(sll)) == -1) { |
fprintf( stderr, "Error bind().\n"); |
return; |
} |
|
/* first, flush all received packets. */ |
debug (3, "Flush"); |
do { |
fd_set fds; |
struct timeval t; |
|
debug( 3, "."); |
FD_ZERO(&fds); |
FD_SET(eth->rtx_sock, &fds); |
memset(&t, 0, sizeof(t)); |
j = select(FD_SETSIZE, &fds, NULL, NULL, &t); |
if (j > 0) |
recv(eth->rtx_sock, eth->rx_buff, j, 0); |
} while (j); |
debug (3, "\n"); |
|
break; |
} |
|
/* Set registers to default values */ |
memset( &(eth->regs), 0, sizeof(eth->regs) ); |
eth->regs.moder = 0x0000A000; |
eth->regs.ipgt = 0x00000012; |
eth->regs.ipgr1 = 0x0000000C; |
eth->regs.ipgr2 = 0x00000012; |
eth->regs.packetlen = 0x003C0600; |
eth->regs.collconf = 0x000F003F; |
eth->regs.miimoder = 0x00000064; |
eth->regs.tx_bd_num = 0x00000080; |
|
/* Initialize TX/RX status */ |
memset( &(eth->tx), 0, sizeof(eth->tx) ); |
memset( &(eth->rx), 0, sizeof(eth->rx) ); |
eth->rx.bd_index = eth->regs.tx_bd_num; |
|
/* Register memory range */ |
register_memoryarea( eth->baseaddr, ETH_ADDR_SPACE, 4, eth_read32, eth_write32 ); |
} |
} |
/* ========================================================================= */ |
|
|
/* |
Print register values on stdout |
*/ |
244,31 → 568,31
unsigned i; |
|
for ( i = 0; i < MAX_ETHERNETS; ++ i ) { |
struct eth_device *eth = &(eths[i]); |
|
if ( eth->baseaddr == 0 ) |
continue; |
|
printf( "\nEthernet MAC %u at 0x%08X:\n", i, eth->baseaddr ); |
printf( "MODER : 0x%08lX\n", eth->regs.moder ); |
printf( "INT_SOURCE : 0x%08lX\n", eth->regs.int_source ); |
printf( "INT_MASK : 0x%08lX\n", eth->regs.int_mask ); |
printf( "IPGT : 0x%08lX\n", eth->regs.ipgt ); |
printf( "IPGR1 : 0x%08lX\n", eth->regs.ipgr1 ); |
printf( "IPGR2 : 0x%08lX\n", eth->regs.ipgr2 ); |
printf( "PACKETLEN : 0x%08lX\n", eth->regs.packetlen ); |
printf( "COLLCONF : 0x%08lX\n", eth->regs.collconf ); |
printf( "TX_BD_NUM : 0x%08lX\n", eth->regs.tx_bd_num ); |
printf( "CTRLMODER : 0x%08lX\n", eth->regs.controlmoder ); |
printf( "MIIMODER : 0x%08lX\n", eth->regs.miimoder ); |
printf( "MIICOMMAND : 0x%08lX\n", eth->regs.miicommand ); |
printf( "MIIADDRESS : 0x%08lX\n", eth->regs.miiaddress ); |
printf( "MIITX_DATA : 0x%08lX\n", eth->regs.miitx_data ); |
printf( "MIIRX_DATA : 0x%08lX\n", eth->regs.miirx_data ); |
printf( "MIISTATUS : 0x%08lX\n", eth->regs.miistatus ); |
printf( "MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\n", |
eth->mac_address[0], eth->mac_address[1], eth->mac_address[2], |
eth->mac_address[3], eth->mac_address[4], eth->mac_address[5] ); |
struct eth_device *eth = &(eths[i]); |
|
if ( eth->baseaddr == 0 ) |
continue; |
|
printf( "\nEthernet MAC %u at 0x%08X:\n", i, eth->baseaddr ); |
printf( "MODER : 0x%08lX\n", eth->regs.moder ); |
printf( "INT_SOURCE : 0x%08lX\n", eth->regs.int_source ); |
printf( "INT_MASK : 0x%08lX\n", eth->regs.int_mask ); |
printf( "IPGT : 0x%08lX\n", eth->regs.ipgt ); |
printf( "IPGR1 : 0x%08lX\n", eth->regs.ipgr1 ); |
printf( "IPGR2 : 0x%08lX\n", eth->regs.ipgr2 ); |
printf( "PACKETLEN : 0x%08lX\n", eth->regs.packetlen ); |
printf( "COLLCONF : 0x%08lX\n", eth->regs.collconf ); |
printf( "TX_BD_NUM : 0x%08lX\n", eth->regs.tx_bd_num ); |
printf( "CTRLMODER : 0x%08lX\n", eth->regs.controlmoder ); |
printf( "MIIMODER : 0x%08lX\n", eth->regs.miimoder ); |
printf( "MIICOMMAND : 0x%08lX\n", eth->regs.miicommand ); |
printf( "MIIADDRESS : 0x%08lX\n", eth->regs.miiaddress ); |
printf( "MIITX_DATA : 0x%08lX\n", eth->regs.miitx_data ); |
printf( "MIIRX_DATA : 0x%08lX\n", eth->regs.miirx_data ); |
printf( "MIISTATUS : 0x%08lX\n", eth->regs.miistatus ); |
printf( "MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\n", |
eth->mac_address[0], eth->mac_address[1], eth->mac_address[2], |
eth->mac_address[3], eth->mac_address[4], eth->mac_address[5] ); |
} |
} |
/* ========================================================================= */ |
282,8 → 606,8
unsigned i; |
|
for ( i = 0; i < config.nethernets; ++ i ) { |
eth_controller_tx_clock( &(eths[i]) ); |
eth_controller_rx_clock( &(eths[i]) ); |
eth_controller_tx_clock( &(eths[i]) ); |
eth_controller_rx_clock( &(eths[i]) ); |
} |
} |
/* ========================================================================= */ |
295,9 → 619,9
unsigned long eth_read32( unsigned long addr ) |
{ |
struct eth_device *eth; |
if ( !eth_find_controller( addr, ð, &addr ) ) { |
printf( "eth_read32( 0x%08lX ): Not in registered range(s)\n", addr ); |
return 0; |
if ( !eth_find_controller( addr, ð, &addr ) ) { |
printf( "eth_read32( 0x%08lX ): Not in registered range(s)\n", addr ); |
return 0; |
} |
|
switch( addr ) { |
318,16 → 642,16
case ETH_MIIRX_DATA: return eth->regs.miirx_data; |
case ETH_MIISTATUS: return eth->regs.miistatus; |
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]; |
(((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 ); |
(unsigned long)eth->mac_address[4]; |
/*case ETH_DMA_RX_TX: return eth_rx( eth );*/ |
} |
|
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 ); |
cont_run = 0; |
342,9 → 666,9
void eth_write32( unsigned long addr, unsigned long value ) |
{ |
struct eth_device *eth; |
if ( !eth_find_controller( addr, ð, &addr ) ) { |
printf( "eth_write32( 0x%08lX ): Not in registered range(s)\n", addr ); |
return; |
if ( !eth_find_controller( addr, ð, &addr ) ) { |
printf( "eth_write32( 0x%08lX ): Not in registered range(s)\n", addr ); |
return; |
} |
|
switch( addr ) { |
365,22 → 689,22
case ETH_MIIRX_DATA: eth->regs.miirx_data = value; return; |
case ETH_MIISTATUS: eth->regs.miistatus = 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; |
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; |
eth->mac_address[4] = value & 0xFF; |
eth->mac_address[5] = (value >> 8) & 0xFF; |
return; |
|
/*case ETH_DMA_RX_TX: eth_tx( eth, value ); return;*/ |
} |
|
if ( (addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE) ) { |
eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value; |
return; |
eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value; |
return; |
} |
|
printf( "eth_write32( 0x%08lX ): Illegal address\n", addr + eth->baseaddr ); |
390,6 → 714,14
/* ========================================================================= */ |
|
|
/* 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 ) |
{ |
eth->rx.bd_index = eth->regs.tx_bd_num = value & 0xFF; |
} |
/* ========================================================================= */ |
|
|
/* |
Convert a memory address to a oontroller struct and relative address. |
Return nonzero on success |
400,17 → 732,17
*eth = NULL; |
|
for ( i = 0; i < MAX_ETHERNETS && *eth == NULL; ++ i ) { |
if ( (addr >= eths[i].baseaddr) && (addr < eths[i].baseaddr + ETH_ADDR_SPACE) ) |
*eth = &(eths[i]); |
} |
if ( (addr >= eths[i].baseaddr) && (addr < eths[i].baseaddr + ETH_ADDR_SPACE) ) |
*eth = &(eths[i]); |
} |
|
/* verify we found a controller */ |
if ( *eth == NULL ) |
return 0; |
return 0; |
|
/* Verify legal address */ |
if ( (addr - (*eth)->baseaddr) % 4 != 0 ) |
return 0; |
return 0; |
|
*reladdr = addr - (*eth)->baseaddr; |
return 1; |
/trunk/or1ksim/peripheral/ethernet.h
153,7 → 153,7
/* Field definitions for RX buffer descriptors */ |
#define ETH_RX_BD_LENGTH_OFFSET 16 |
#define ETH_RX_BD_LENGTH_WIDTH 16 |
#define ETH_RX_BD_EMPTY_OFFSET 15 |
#define ETH_RX_BD_READY_OFFSET 15 |
#define ETH_RX_BD_INTERRUPT_OFFSET 14 |
#define ETH_RX_BD_WRAP_OFFSET 13 |
#define ETH_RX_BD_MISS_OFFSET 7 |
163,6 → 163,6
#define ETH_RX_BD_TOOBIG_OFFSET 3 |
#define ETH_RX_BD_TOOSHORT_OFFSET 2 |
#define ETH_RX_BD_CRC_OFFSET 1 |
#define ETH_RX_BD_LATECOLL_OFFSET 0 |
#define ETH_RX_BD_COLLISION_OFFSET 0 |
|
#endif /* __OR1KSIM_PERIPHERAL_ETHERNET_H */ |
/trunk/or1ksim/peripheral/Makefile.am
19,4 → 19,4
# |
|
noinst_LIBRARIES = libperipheral.a |
libperipheral_a_SOURCES = 16450.c dma.c mc.c ethernet.c crc32.c gpio.c vga.c fb.c ps2kbd.c |
libperipheral_a_SOURCES = 16450.c dma.c mc.c eth.c crc32.c gpio.c vga.c fb.c ps2kbd.c |
/trunk/or1ksim/peripheral/ethernet_i.h
23,6 → 23,10
|
#include "ethernet.h" |
#include "config.h" |
#include <netpacket/packet.h> |
#include <sys/ioctl.h> |
#include <sys/socket.h> |
#include <net/if.h> |
|
/* |
* Ethernet protocol definitions |
33,7 → 37,7
|
#include <sys/types.h> |
|
#define ETH_ALEN 6 |
#define ETH_ALEN 6 |
|
struct ether_addr |
{ |
90,6 → 94,12
#define ETH_RXSTATE_WAIT4BD 10 |
#define ETH_RXSTATE_RECV 20 |
#define ETH_RXSTATE_WRITEFIFO 30 |
|
#define ETH_RTX_FILE 0 |
#define ETH_RTX_SOCK 1 |
|
#define ETH_MAXPL 0x10000 |
|
struct eth_device |
{ |
/* Base address in memory */ |
103,8 → 113,11
unsigned tx_channel; |
unsigned rx_channel; |
|
/* Our address */ |
unsigned char mac_address[ETH_ALEN]; |
/* Our address */ |
unsigned char mac_address[ETH_ALEN]; |
|
/* interrupt line */ |
unsigned long mac_int; |
|
/* RX and TX file names and handles */ |
const char *rxfile, *txfile; |
112,6 → 125,11
int rxfd; |
off_t loopback_offset; |
|
int rtx_sock; |
int rtx_type; |
struct ifreq ifr; |
fd_set rfds, wfds; |
|
/* Current TX state */ |
struct |
{ |
120,11 → 138,12
unsigned long bd; |
unsigned long bd_addr; |
unsigned working, waiting_for_dma, error; |
unsigned packet_length; |
long packet_length; |
unsigned minimum_length, maximum_length; |
unsigned add_crc; |
unsigned crc_dly; |
unsigned long crc_value; |
unsigned bytes_left, bytes_sent; |
long bytes_left, bytes_sent; |
} tx; |
|
/* Current RX state */ |
133,10 → 152,11
unsigned long state; |
unsigned long bd_index; |
unsigned long bd; |
unsigned long bd_addr; |
int fd; |
off_t *offset; |
unsigned working, error, waiting_for_dma; |
unsigned packet_length, bytes_read, bytes_left; |
long packet_length, bytes_read, bytes_left; |
} rx; |
|
/* Visible registers */ |
163,9 → 183,9
unsigned long bd_ram[ETH_BD_SPACE / 4]; |
} regs; |
|
unsigned long rx_buff[0x10000]; |
unsigned long tx_buff[0x10000]; |
unsigned long lo_buff[0x10000]; |
unsigned char rx_buff[ETH_MAXPL]; |
unsigned char tx_buff[ETH_MAXPL]; |
unsigned char lo_buff[ETH_MAXPL]; |
}; |
|
|