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

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/or1ksim
    from Rev 443 to Rev 450
    Reverse comparison

Rev 443 → Rev 450

/configure.ac
28,7 → 28,7
 
# Use a full version number (x.y.z, possibly with "rcn" as a suffix) when
# preparing a release, otherwise use a the date version (yyyy-mm-dd).
AC_INIT([or1ksim], [2010-12-08], [openrisc@opencores.org])
AC_INIT([or1ksim], [2010-12-15], [openrisc@opencores.org])
AC_CONFIG_MACRO_DIR([m4])
 
# Generically use extensions such as _GNU_SOURCE if available.
/doc/or1ksim.info
1,5 → 1,5
This is ../../or1ksim/doc/or1ksim.info, produced by makeinfo version
4.13 from ../../or1ksim/doc/or1ksim.texi.
This is ../../doc/or1ksim.info, produced by makeinfo version 4.13 from
../../doc/or1ksim.texi.
 
INFO-DIR-SECTION Embedded development
START-INFO-DIR-ENTRY
64,7 → 64,7
Unpack the software and create a _separate_ directory in which to build
it:
 
tar jxf or1ksim-2010-12-08.tar.bz2
tar jxf or1ksim-2010-12-15.tar.bz2
mkdir builddir_or1ksim
cd builddir_or1ksim
 
81,7 → 81,7
OpenRISC 1000 32-bit architecture. If this argument is omitted, it will
default to OpenRISC 1000 32-bit with a warning
 
../or1ksim-2010-12-08/configure --target=or32-elf ...
../or1ksim-2010-12-15/configure --target=or32-elf ...
 
There are several other options available, many of which are standard
to GNU `configure' scripts. Use `configure --help' to see all the
520,11 → 520,32
the command line, or via the operating system's signal passing
mechanism.
 
The following, passed at run time, can be used to create an execution
dump.
 
`-t'
`--trace'
Dump instruction just executed and any register/memory location
chaged after each instruction (one line per instruction).
 
Passing a signal `SIGUSR1' while the simulator is running toggles trace
generation. This can be done with the following command, assuming
Or1ksim's executable name is `or32-elf-sim':
 
pkill -SIGUSR1 or32-elf-sim
 
This is useful in the case where trace output is desired after a
significant amount of simulation time, where it would be inconvenient to
generate trace up to that point.
 
If the `pkill' utility is not available, the `kill' utility can be used
if Or1ksim's process number is known. Use the following to determine
the process ID of the `or32-elf-sim' and then send the `SIGUSR1'
command to toggle execution trace generation:
 
ps a | grep or32-elf-sim
kill -SIGUSR1 _process-number_
 

File: or1ksim.info, Node: Simulator Library, Next: Ethernet TUN/TAP Interface, Prev: Trace Generation, Up: Usage
 
3825,7 → 3846,7
(line 60)
* --strict-npc: Standalone Simulator.
(line 100)
* --trace <1>: Trace Generation. (line 12)
* --trace <1>: Trace Generation. (line 15)
* --trace: Standalone Simulator.
(line 39)
* --verbose: Standalone Simulator.
3859,7 → 3880,7
* -q <1>: Profiling Utility. (line 30)
* -q: Standalone Simulator.
(line 29)
* -t <1>: Trace Generation. (line 12)
* -t <1>: Trace Generation. (line 15)
* -t: Standalone Simulator.
(line 39)
* -V: Standalone Simulator.
4686,64 → 4707,64
 

Tag Table:
Node: Top826
Node: Installation1236
Node: Preparation1483
Node: Configuring the Build1778
Node: Build and Install7918
Node: Known Issues8684
Node: Usage9739
Node: Standalone Simulator10005
Node: Profiling Utility14565
Node: Memory Profiling Utility15471
Node: Trace Generation16831
Node: Simulator Library17286
Node: Ethernet TUN/TAP Interface27718
Node: Setting Up a Persistent TAP device28801
Node: Establishing a Bridge29476
Node: Opening the Firewall31159
Node: Disabling Ethernet Filtering31650
Node: Networking from OpenRISC Linux and BusyBox32275
Node: Tearing Down a Bridge33937
Node: Configuration34680
Node: Configuration File Format35292
Node: Configuration File Preprocessing35677
Node: Configuration File Syntax35974
Node: Simulator Configuration38759
Node: Simulator Behavior39050
Node: Verification API Configuration43631
Node: CUC Configuration45571
Node: Core OpenRISC Configuration47563
Node: CPU Configuration48065
Node: Memory Configuration52184
Node: Memory Management Configuration58906
Node: Cache Configuration61283
Node: Interrupt Configuration63669
Node: Power Management Configuration65502
Node: Branch Prediction Configuration66779
Node: Debug Interface Configuration68139
Node: Peripheral Configuration70482
Node: Memory Controller Configuration71108
Node: UART Configuration74888
Node: DMA Configuration78407
Node: Ethernet Configuration80274
Node: GPIO Configuration84919
Node: Display Interface Configuration86552
Node: Frame Buffer Configuration88861
Node: Keyboard Configuration90725
Node: Disc Interface Configuration92963
Node: Generic Peripheral Configuration98067
Node: Interactive Command Line100362
Node: Verification API107336
Node: Code Internals111766
Node: Coding Conventions112349
Node: Global Data Structures116776
Node: Concepts119433
Ref: Output Redirection119578
Ref: Interrupts Internal120116
Node: Internal Debugging121269
Node: Regression Testing121793
Node: GNU Free Documentation License125582
Node: Index147989
Node: Top810
Node: Installation1220
Node: Preparation1467
Node: Configuring the Build1762
Node: Build and Install7902
Node: Known Issues8668
Node: Usage9723
Node: Standalone Simulator9989
Node: Profiling Utility14549
Node: Memory Profiling Utility15455
Node: Trace Generation16815
Node: Simulator Library18057
Node: Ethernet TUN/TAP Interface28489
Node: Setting Up a Persistent TAP device29572
Node: Establishing a Bridge30247
Node: Opening the Firewall31930
Node: Disabling Ethernet Filtering32421
Node: Networking from OpenRISC Linux and BusyBox33046
Node: Tearing Down a Bridge34708
Node: Configuration35451
Node: Configuration File Format36063
Node: Configuration File Preprocessing36448
Node: Configuration File Syntax36745
Node: Simulator Configuration39530
Node: Simulator Behavior39821
Node: Verification API Configuration44402
Node: CUC Configuration46342
Node: Core OpenRISC Configuration48334
Node: CPU Configuration48836
Node: Memory Configuration52955
Node: Memory Management Configuration59677
Node: Cache Configuration62054
Node: Interrupt Configuration64440
Node: Power Management Configuration66273
Node: Branch Prediction Configuration67550
Node: Debug Interface Configuration68910
Node: Peripheral Configuration71253
Node: Memory Controller Configuration71879
Node: UART Configuration75659
Node: DMA Configuration79178
Node: Ethernet Configuration81045
Node: GPIO Configuration85690
Node: Display Interface Configuration87323
Node: Frame Buffer Configuration89632
Node: Keyboard Configuration91496
Node: Disc Interface Configuration93734
Node: Generic Peripheral Configuration98838
Node: Interactive Command Line101133
Node: Verification API108107
Node: Code Internals112537
Node: Coding Conventions113120
Node: Global Data Structures117547
Node: Concepts120204
Ref: Output Redirection120349
Ref: Interrupts Internal120887
Node: Internal Debugging122040
Node: Regression Testing122564
Node: GNU Free Documentation License126353
Node: Index148760

End Tag Table
/doc/version.texi
1,4 → 1,4
@set UPDATED 9 December 2010
@set UPDATED 10 December 2010
@set UPDATED-MONTH December 2010
@set EDITION 2010-12-08
@set VERSION 2010-12-08
@set EDITION 2010-12-15
@set VERSION 2010-12-15
/ChangeLog
1,3 → 1,19
2010-12-15 Jeremy Bennett <jeremy@jeremybennett.com>
 
* configure: Regenerated.
* configure.ac: Updated version.
* peripheral/eth.c <mac_address>: Defined to ff:ff:ff:ff:ff:ff.
<struct eth_device>: loopback_offset removed. State reduced to
just BD indices, buffers removed.
(eth_read_rx_file, eth_skip_rx_file, eth_rx_next_packet): Deleted.
(eth_write_file_packet, eth_write_tap_packet, eth_write_packet)
(eth_blush_bd): Created.
(eth_controller_tx_clock): Completely rewritten.
(eth_read_file_packet, eth_read_tap_packet, eth_read_packet)
(eth_fill_bd, eth_ignore_packet): Created.
(eth_controller_rx_clock): Completely rewritten.
(eth_read32, eth_write32): Rewritten for new data structures.
 
2010-12-09 Julius Baxter <julius@opencores.org>
 
* doc/or1ksim.texi: changed references to or32-uclinux-* to or32-elf-*.
8,7 → 24,7
* toplevel-support.c: <toggle_trace>: New function to toggle the trace
execution control variable.
* toplevel-support.h: <toggle_trace>: Add function prototype.
 
2010-12-08 Jeremy Bennett <jeremy@jeremybennett.com>
 
* configure: Regenerated.
/testsuite/test-code-or1k/configure
1,6 → 1,6
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.65 for or1ksim-testsuite 2010-12-08.
# Generated by GNU Autoconf 2.65 for or1ksim-testsuite 2010-12-15.
#
# Report bugs to <openrisc@opencores.org>.
#
701,8 → 701,8
# Identity of this package.
PACKAGE_NAME='or1ksim-testsuite'
PACKAGE_TARNAME='or1ksim-testsuite'
PACKAGE_VERSION='2010-12-08'
PACKAGE_STRING='or1ksim-testsuite 2010-12-08'
PACKAGE_VERSION='2010-12-15'
PACKAGE_STRING='or1ksim-testsuite 2010-12-15'
PACKAGE_BUGREPORT='openrisc@opencores.org'
PACKAGE_URL=''
 
1424,7 → 1424,7
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures or1ksim-testsuite 2010-12-08 to adapt to many kinds of systems.
\`configure' configures or1ksim-testsuite 2010-12-15 to adapt to many kinds of systems.
 
Usage: $0 [OPTION]... [VAR=VALUE]...
 
1495,7 → 1495,7
 
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of or1ksim-testsuite 2010-12-08:";;
short | recursive ) echo "Configuration of or1ksim-testsuite 2010-12-15:";;
esac
cat <<\_ACEOF
 
1600,7 → 1600,7
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
or1ksim-testsuite configure 2010-12-08
or1ksim-testsuite configure 2010-12-15
generated by GNU Autoconf 2.65
 
Copyright (C) 2009 Free Software Foundation, Inc.
2025,7 → 2025,7
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
 
It was created by or1ksim-testsuite $as_me 2010-12-08, which was
It was created by or1ksim-testsuite $as_me 2010-12-15, which was
generated by GNU Autoconf 2.65. Invocation command line was
 
$ $0 $@
10315,7 → 10315,7
 
# Define the identity of the package.
PACKAGE='or1ksim-testsuite'
VERSION='2010-12-08'
VERSION='2010-12-15'
 
 
cat >>confdefs.h <<_ACEOF
11742,7 → 11742,7
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by or1ksim-testsuite $as_me 2010-12-08, which was
This file was extended by or1ksim-testsuite $as_me 2010-12-15, which was
generated by GNU Autoconf 2.65. Invocation command line was
 
CONFIG_FILES = $CONFIG_FILES
11808,7 → 11808,7
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
or1ksim-testsuite config.status 2010-12-08
or1ksim-testsuite config.status 2010-12-15
configured by $0, generated by GNU Autoconf 2.65,
with options \\"\$ac_cs_config\\"
 
/testsuite/test-code-or1k/configure.ac
24,7 → 24,7
# directory. This uses a different tool chain, so has its own configuration
# script. Process this file with autoconf to produce a configure script.
 
AC_INIT([or1ksim-testsuite], [2010-12-08], [openrisc@opencores.org])
AC_INIT([or1ksim-testsuite], [2010-12-15], [openrisc@opencores.org])
AC_CONFIG_MACRO_DIR([m4])
 
AC_PROG_LIBTOOL
/testsuite/test-code-or1k/ChangeLog
1,3 → 1,8
2010-12-15x Jeremy Bennett <jeremy.bennett@embecosm.com>
 
* configure: Regenerated.
* configure.ac: Updated version.
 
2010-12-08 Jeremy Bennett <jeremy.bennett@embecosm.com>
 
* configure: Regenerated.
/peripheral/eth.c
65,11 → 65,16
 
 
/* Control debug messages */
#define ETH_DEBUG 0
#ifndef ETH_DEBUG
# define ETH_DEBUG 1
#endif
 
 
/*! MAC address that is always accepted. */
static const unsigned char mac_broadcast[ETHER_ADDR_LEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
/* -------------------------------------------------------------------------- */
/*!Structure describing the Ethernet device */
/* -------------------------------------------------------------------------- */
99,40 → 104,15
char *txfile; /* Tx filename */
int txfd; /* Rx file handle */
int rxfd; /* Tx file handle */
off_t loopback_offset; /* Circular buffer offset */
 
/* Info for TAP type connections */
char *tap_dev; /* The TAP device */
int rtx_fd; /* TAP device handle */
 
/* Current TX state */
struct
{
unsigned long int bd_index;
} tx;
/* Indices into the buffer descriptors. */
unsigned long int tx_bd_index;
unsigned long int rx_bd_index;
 
/* Current RX state */
struct
{
enum {
ETH_RXSTATE_IDLE, /* Was set to 0 */
ETH_RXSTATE_WAIT4BD, /* Was set to 10 */
ETH_RXSTATE_RECV, /* Was set to 20 */
ETH_RXSTATE_WRITEFIFO, /* Was set to 30 */
} state;
unsigned long int bd_index;
unsigned long int bd;
unsigned long int bd_addr;
int fd;
off_t *offset;
unsigned int working;
unsigned int waiting_for_dma;
unsigned int error;
long int packet_length;
long int bytes_read;
long int bytes_left;
} rx;
 
/* Visible registers */
struct
{
158,101 → 138,11
/* Buffer descriptors */
unsigned long int bd_ram[ETH_BD_SPACE / 4];
} regs;
 
unsigned char rx_buff[ETH_MAXPL];
unsigned char tx_buff[ETH_MAXPL];
unsigned char lo_buff[ETH_MAXPL];
};
 
 
 
/* -------------------------------------------------------------------------- */
/*!Utility function to read from the ethernet RX file.
 
Helper function when using file I/O.
 
This function moves the file pointer to the current place in the packet
before reading. The Ethernet device datastructure contains the file
descriptor and offset to use.
 
@param[in] eth Ethernet device datastruture.
@param[out] buf Buffer for read data.
@param[in] count Number of bytes to read.
 
@return Number of bytes read, or zero on end-of-file or -1 on error. */
/* -------------------------------------------------------------------------- */
static ssize_t
eth_read_rx_file (struct eth_device *eth,
void *buf,
size_t count)
{
ssize_t result;
 
if (eth->rx.fd <= 0)
{
return 0;
}
 
if (eth->rx.offset)
{
if (lseek (eth->rx.fd, *(eth->rx.offset), SEEK_SET) == (off_t) - 1)
{
return 0;
}
}
 
result = read (eth->rx.fd, buf, count);
 
if (eth->rx.offset && result >= 0)
{
*(eth->rx.offset) += result;
}
 
return result;
 
} /* eth_read_rx_file () */
 
 
/* -------------------------------------------------------------------------- */
/*!Skip bytes in the RX file.
 
Helper function when using file I/O.
 
This just updates the offset pointer in the ethernet device datastructure.
 
@param[in] eth Ethernet device datastruture.
@param[in] count Number of bytes to skip. */
/* -------------------------------------------------------------------------- */
static void
eth_skip_rx_file (struct eth_device *eth,
off_t count)
{
eth->rx.offset += count;
 
} /* eth_skip_rx_file () */
 
 
/* -------------------------------------------------------------------------- */
/* Move to next buffer descriptor in RX file.
 
Helper function when using file I/O.
 
Skip any remaining bytes in the Rx file for this transaction.
 
@param[in] eth Ethernet device datastruture. */
/* -------------------------------------------------------------------------- */
static 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);
}
} /* eth_rx_next_packet () */
 
 
/* -------------------------------------------------------------------------- */
/*!Emulate MIIM transaction to ethernet PHY
 
@param[in] eth Ethernet device datastruture. */
384,140 → 274,215
} /* eth_miim_trans () */
 
 
 
/* -------------------------------------------------------------------------- */
/*!Tx clock function.
/*!Write an Ethernet packet to a FILE interface.
 
The original version had 4 states, which allowed modeling the transfer of
data one byte per cycle.
This writes a single Ethernet packet to a FILE interface. The format is to
write the length, then the data.
 
For now we use only the one state for efficiency. When we find something in
a buffer descriptor, we transmit it. We should wake up for this every 10
cycles.
@param[in] eth Pointer to the relevant Ethernet data structure.
@param[in] buf Where to get the data.
@param[in] length Length of data to write.
 
We also remove numerous calculations that are not needed here.
@return The length if successful, a negative value otherwise. */
/* -------------------------------------------------------------------------- */
static ssize_t
eth_write_file_packet (struct eth_device *eth,
unsigned char *buf,
unsigned long int length)
{
ssize_t nwritten;
 
@todo We should eventually reinstate the one byte per cycle transfer.
/* Write length to file. */
nwritten = write (eth->txfd, &(length), sizeof (length));
if (nwritten != sizeof (length))
{
fprintf (stderr, "ERROR: Failed to write Ethernet packet length: %s.\n",
strerror (errno));
return -1;
}
 
Responsible for starting and completing any TX actions.
/* write data to file */
nwritten = write (eth->txfd, buf, length);
if (nwritten != length)
{
fprintf (stderr, "ERROR: Failed to write Ethernet packet data: %s.\n",
strerror (errno));
return -1;
}
 
@param[in] dat The Ethernet data structure, passed as a void pointer. */
return nwritten;
 
} /* eth_write_file_packet () */
 
 
/* -------------------------------------------------------------------------- */
static void
eth_controller_tx_clock (void *dat)
/*!Write an Ethernet packet to a TAP interface.
 
This writes a single Ethernet packet to a TAP interface.
 
@param[in] eth Pointer to the relevant Ethernet data structure.
@param[in] buf Where to get the data.
@param[in] length Length of data to write.
 
@return The length if successful, a negative value otherwise. */
/* -------------------------------------------------------------------------- */
static ssize_t
eth_write_tap_packet (struct eth_device *eth,
unsigned char *buf,
unsigned long int length)
{
struct eth_device *eth = dat;
ssize_t nwritten;
 
/* First word of BD is flags and length, second is pointer to buffer */
unsigned long int bd_info = eth->regs.bd_ram[eth->tx.bd_index];
unsigned long int bd_addr = eth->regs.bd_ram[eth->tx.bd_index + 1];
#if ETH_DEBUG
int j;
 
/* If we have a buffer ready, get it and transmit it. */
if (TEST_FLAG (bd_info, ETH_TX_BD, READY))
printf ("Writing TAP\n");
printf (" packet %d bytes:", (int) length);
 
for (j = 0; j < length; j++)
{
long int packet_length;
long int bytes_sent;
long int nwritten = 0;
if (0 == (j % 16))
{
printf ("\n");
}
else if (0 == (j % 8))
{
printf (" ");
}
printf ("%.2x ", buf[j]);
}
printf("\nend packet:\n");
#endif
 
/* Get the packet length */
packet_length = GET_FIELD (bd_info, ETH_TX_BD, LENGTH);
/* Write the data to the TAP */
nwritten = write (eth->rtx_fd, buf, length);
if (nwritten != length)
{
fprintf (stderr, "ERROR: Failed to write Ethernet packet data: %s.\n",
strerror (errno));
return -1;
}
 
/* Clear error status bits and retry count. */
CLEAR_FLAG (bd_info, ETH_TX_BD, DEFER);
CLEAR_FLAG (bd_info, ETH_TX_BD, COLLISION);
CLEAR_FLAG (bd_info, ETH_TX_BD, RETRANSMIT);
CLEAR_FLAG (bd_info, ETH_TX_BD, UNDERRUN);
CLEAR_FLAG (bd_info, ETH_TX_BD, NO_CARRIER);
return nwritten;
 
SET_FIELD (bd_info, ETH_TX_BD, RETRY, 0);
} /* eth_write_tap_packet () */
 
/* Copy data from buffer descriptor address into our local tx_buff. */
for (bytes_sent = 0; bytes_sent < packet_length; bytes_sent +=4)
{
unsigned long int read_word =
eval_direct32 (bytes_sent + bd_addr, 0, 0);
 
eth->tx_buff[bytes_sent] = (unsigned char) (read_word >> 24);
eth->tx_buff[bytes_sent + 1] = (unsigned char) (read_word >> 16);
eth->tx_buff[bytes_sent + 2] = (unsigned char) (read_word >> 8);
eth->tx_buff[bytes_sent + 3] = (unsigned char) (read_word);
}
/* -------------------------------------------------------------------------- */
/*!Write an Ethernet packet.
 
/* Send packet according to interface type. */
switch (eth->rtx_type)
{
case ETH_RTX_FILE:
/* write packet length to file */
nwritten =
write (eth->txfd, &(packet_length),
sizeof (packet_length));
/* write data to file */
nwritten = write (eth->txfd, eth->tx_buff, packet_length);
break;
This writes a single Ethernet packet to the outside world from the supplied
buffer. It deals with the different types of external interface.
 
case ETH_RTX_TAP:
#if ETH_DEBUG
{
int j;
@param[in] eth Pointer to the relevant Ethernet data structure.
@param[in] buf Where to get the data.
@param[in] length Length of data to write.
 
printf ("Writing TAP\n");
printf (" packet %d bytes:", (int) packet_length);
@return The length if successful, zero if no packet was available,
a negative value otherwise. */
/* -------------------------------------------------------------------------- */
static ssize_t
eth_write_packet (struct eth_device *eth,
unsigned char *buf,
ssize_t length)
{
/* Send packet according to interface type. */
switch (eth->rtx_type)
{
case ETH_RTX_FILE: return eth_write_file_packet (eth, buf, length);
case ETH_RTX_TAP: return eth_write_tap_packet (eth, buf, length);
 
for (j = 0; j < packet_length; j++)
{
if (0 == (j % 16))
{
printf ("\n");
}
else if (0 == (j % 8))
{
printf (" ");
}
default:
fprintf (stderr, "Unknown Ethernet write interface: ignored.\n");
return (ssize_t) -1;
}
} /* eth_write_packet () */
 
printf ("%.2x ", eth->tx_buff[j]);
}
 
printf("\nend packet:\n");
}
#endif
nwritten = write (eth->rtx_fd, eth->tx_buff, packet_length);
break;
}
/* -------------------------------------------------------------------------- */
/*!Flush a Tx buffer descriptor to the outside world.
 
/* Set BD status. If we didn't write the whole packet, then we retry. */
if (nwritten == packet_length)
{
CLEAR_FLAG (bd_info, ETH_TX_BD, READY);
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
}
else
{
/* Does this retry mechanism really work? */
CLEAR_FLAG (bd_info, ETH_TX_BD, READY);
CLEAR_FLAG (bd_info, ETH_TX_BD, COLLISION);
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
We know the buffer descriptor is full, so write it to the appropriate
outside interface.
 
@param[in] eth The Ethernet data structure. */
/* -------------------------------------------------------------------------- */
static void
eth_flush_bd (struct eth_device *eth)
{
/* First word of BD is flags and length, second is pointer to buffer */
unsigned long int bd_info = eth->regs.bd_ram[eth->tx_bd_index];
unsigned long int bd_addr = eth->regs.bd_ram[eth->tx_bd_index + 1];
unsigned char buf[ETH_MAXPL];
long int packet_length;
long int bytes_sent;
 
/* Get the packet length */
packet_length = GET_FIELD (bd_info, ETH_TX_BD, LENGTH);
 
/* Clear error status bits and retry count. */
CLEAR_FLAG (bd_info, ETH_TX_BD, DEFER);
CLEAR_FLAG (bd_info, ETH_TX_BD, COLLISION);
CLEAR_FLAG (bd_info, ETH_TX_BD, RETRANSMIT);
CLEAR_FLAG (bd_info, ETH_TX_BD, UNDERRUN);
CLEAR_FLAG (bd_info, ETH_TX_BD, NO_CARRIER);
 
SET_FIELD (bd_info, ETH_TX_BD, RETRY, 0);
 
/* Copy data from buffer descriptor address into our local buf. */
for (bytes_sent = 0; bytes_sent < packet_length; bytes_sent +=4)
{
unsigned long int read_word =
eval_direct32 (bytes_sent + bd_addr, 0, 0);
 
buf[bytes_sent] = (unsigned char) (read_word >> 24);
buf[bytes_sent + 1] = (unsigned char) (read_word >> 16);
buf[bytes_sent + 2] = (unsigned char) (read_word >> 8);
buf[bytes_sent + 3] = (unsigned char) (read_word);
}
 
/* Send packet according to interface type and set BD status. If we didn't
write the whole packet, then we retry. */
if (eth_write_packet (eth, buf, packet_length) == packet_length)
{
CLEAR_FLAG (bd_info, ETH_TX_BD, READY);
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
}
else
{
/* Does this retry mechanism really work? */
CLEAR_FLAG (bd_info, ETH_TX_BD, READY);
CLEAR_FLAG (bd_info, ETH_TX_BD, COLLISION);
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
#if ETH_DEBUG
printf ("Transmit retry request.\n");
printf ("Transmit retry request.\n");
#endif
}
}
 
/* Update the flags in the buffer descriptor */
eth->regs.bd_ram[eth->tx.bd_index] = bd_info;
/* Update the flags in the buffer descriptor */
eth->regs.bd_ram[eth->tx_bd_index] = bd_info;
 
/* This looks erroneous. Surely it will conflict with the retry flag */
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
/* Generate interrupt to indicate transfer complete, under the
following criteria all being met:
- either INT_MASK flag for Tx (OK or error) is set
- the bugger descriptor has its IRQ flag set
- there is no interrupt in progress.
 
/* Generate interrupt to indicate transfer complete, under the
following criteria all being met:
- either INT_MASK flag for Tx (OK or error) is set
- the bugger descriptor has its IRQ flag set
- there is no interrupt in progress.
 
@todo We ought to warn if we get here and fail to set an IRQ. */
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 (bd_info, ETH_TX_BD, IRQ) &&
!eth->int_line_stat)
@todo We ought to warn if we get here and fail to set an IRQ. */
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 (bd_info, ETH_TX_BD, IRQ))
{
if (eth->int_line_stat)
{
fprintf (stderr, "Warning: Interrupt active during Tx.\n");
}
else
{
#if ETH_DEBUG
printf ("TRANSMIT interrupt\n");
#endif
524,370 → 489,444
report_interrupt (eth->mac_int);
eth->int_line_stat = 1;
}
else
{
#if ETH_DEBUG
printf ("Failed to send TRANSMIT interrupt\n");
#endif
}
}
 
/* Advance to next BD, wrapping around if appropriate. */
if (TEST_FLAG (bd_info, ETH_TX_BD, WRAP) ||
eth->tx.bd_index >= ETH_BD_COUNT)
{
eth->tx.bd_index = 0;
}
else
{
eth->tx.bd_index += 2;
}
/* Advance to next BD, wrapping around if appropriate. */
if (TEST_FLAG (bd_info, ETH_TX_BD, WRAP) ||
eth->tx_bd_index >= ((eth->regs.tx_bd_num - 1) * 2))
{
eth->tx_bd_index = 0;
}
else
{
eth->tx_bd_index += 2;
}
} /* eth_flush_bd () */
 
/* Wake up again after 1 ticks (was 10, changed by Julius). */
SCHED_ADD (eth_controller_tx_clock, dat, 1);
 
} /* eth_controller_tx_clock () */
 
 
/* -------------------------------------------------------------------------- */
/*!Rx clock function.
/*!Tx clock function.
 
NEEDS WRITING
Responsible for starting and completing any TX actions.
 
The original version had 4 states, which allowed modeling the transfer of
data one byte per cycle.
data one byte per cycle. For now we use only the one state for
efficiency. When we find something in a buffer descriptor, we transmit
it.
 
For now we use only the one state for efficiency. When we find something in
a buffer descriptor, we transmit it. We should wake up for this every 10
cycles.
We reschedule every cycle. There is no point in trying to do anything if
there is an interrupt still being processed by the core.
 
We also remove numerous calculations that are not needed here.
 
@todo We should eventually reinstate the one byte per cycle transfer.
 
Responsible for starting and completing any TX actions.
 
@param[in] dat The Ethernet data structure, passed as a void pointer. */
/* -------------------------------------------------------------------------- */
 
/* ========================================================================= */
 
 
/* ========================================================================= */
/* RX LOGIC */
/*---------------------------------------------------------------------------*/
 
/*
* RX clock
* Responsible for starting and finishing RX
*/
static void
eth_controller_rx_clock (void *dat)
eth_controller_tx_clock (void *dat)
{
struct eth_device *eth = dat;
long nread = 0;
unsigned long send_word;
struct pollfd fds[1];
int n;
 
 
switch (eth->rx.state)
/* Only do anything if there is not an interrupt outstanding. */
if (!eth->int_line_stat)
{
case ETH_RXSTATE_IDLE:
eth->rx.state = ETH_RXSTATE_WAIT4BD;
break;
/* First word of BD is flags. If we have a buffer ready, get it and
transmit it. */
if (TEST_FLAG (eth->regs.bd_ram[eth->tx_bd_index], ETH_TX_BD, READY))
{
eth_flush_bd (eth);
}
}
 
case ETH_RXSTATE_WAIT4BD:
/* Wake up again after 1 ticks (was 10, changed by Julius). */
SCHED_ADD (eth_controller_tx_clock, dat, 1);
 
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_controller_tx_clock () */
 
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);
 
/* 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;
}
eth->rx.state = ETH_RXSTATE_RECV;
/* -------------------------------------------------------------------------- */
/*!Read an Ethernet packet from a FILE interface.
 
}
else if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
{
eth->rx.state = ETH_RXSTATE_IDLE;
}
else
{
/* Poll to see if there is data to read */
struct pollfd fds[1];
int n;
This reads a single Ethernet packet from the outside world via a FILE
interface.
 
fds[0].fd = eth->rtx_fd;
fds[0].events = POLLIN;
n = poll (fds, 1, 0);
if (n < 0)
{
fprintf (stderr, "Warning: Poll of WAIT4BD failed %s: ignored.\n",
strerror (errno));
}
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
{
printf ("Reading TAP and all BDs full = BUSY\n");
nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
The format is 4 bytes of packet length, followed by the packet data.
 
if (nread < 0)
{
fprintf (stderr,
"Warning: Read of WAIT4BD failed %s: ignored\n",
strerror (errno));
}
else if (nread > 0)
{
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
@param[in] eth Pointer to the relevant Ethernet data structure
@param[out] buf Where to put the data
 
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M) &&
!eth->int_line_stat)
{
printf ("ETH_RXSTATE_WAIT4BD BUSY interrupt\n");
report_interrupt (eth->mac_int);
eth->int_line_stat = 1;
}
}
}
}
@return The length if successful, zero if no packet was available
(i.e. EOF), a negative value otherwise. */
/* -------------------------------------------------------------------------- */
static ssize_t
eth_read_file_packet (struct eth_device *eth,
unsigned char *buf)
{
ssize_t packet_length;
ssize_t nread;
 
break;
/* Read packet length. We may be at EOF. */
nread = read (eth->rxfd, &(packet_length), sizeof (packet_length));
 
case ETH_RXSTATE_RECV:
if (0 == nread)
{
return 0; /* No more packets */
}
else if (nread < sizeof (packet_length))
{
fprintf (stderr, "ERROR: Failed to read length from file.\n");
return -1;
}
 
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) */
sim_done ();
break;
}
/* Packet must be big enough to hold a header */
if (packet_length < ETHER_HDR_LEN)
{
fprintf (stderr, "Warning: Ethernet packet length %zd too small.\n",
packet_length);
return -1;
}
 
/* Packet must be big enough to hold a header */
if (eth->rx.packet_length < ETHER_HDR_LEN)
{
eth_rx_next_packet (eth);
/* Read the packet proper. */
nread = read (eth->rxfd, buf, packet_length);
 
eth->rx.state = ETH_RXSTATE_WAIT4BD;
break;
}
if (nread != packet_length)
{
fprintf (stderr, "ERROR: Failed to read packet from file.\n");
return -1;
}
 
eth->rx.bytes_read = 0;
eth->rx.bytes_left = eth->rx.packet_length;
return 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)
{
eth->rx.error = 1;
break;
}
} /* eth_read_file_packet () */
 
eth->rx.packet_length = nread;
eth->rx.bytes_left = nread;
eth->rx.bytes_read = 0;
 
eth->rx.state = ETH_RXSTATE_WRITEFIFO;
/* -------------------------------------------------------------------------- */
/*!Read an Ethernet packet from a FILE interface.
 
break;
This reads a single Ethernet packet from the outside world via a TAP
interface.
 
case ETH_RTX_TAP:
/* Poll to see if there is data to read */
fds[0].fd = eth->rtx_fd;
fds[0].events = POLLIN;
A complete packet is always read, so its length (minus CRC) is the amount
read.
 
@param[in] eth Pointer to the relevant Ethernet data structure
@param[out] buf Where to put the data
 
@return The length if successful, zero if no packet was available,
a negative value otherwise. */
/* -------------------------------------------------------------------------- */
static ssize_t
eth_read_tap_packet (struct eth_device *eth,
unsigned char *buf)
{
struct pollfd fds[1];
int n;
ssize_t packet_length;
 
/* Poll to see if there is data to read */
fds[0].fd = eth->rtx_fd;
fds[0].events = POLLIN;
n = poll (fds, 1, 0);
if (n < 0)
{
fprintf (stderr,
"Warning: Poll of RXTATE_RECV failed %s: ignored.\n",
strerror (errno));
}
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
{
n = poll (fds, 1, 0);
if (n < 0)
{
fprintf (stderr, "Warning: Poll for TAP receive failed %s: ignored.\n",
strerror (errno));
return -1;
}
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
{
/* Data to be read from TAP */
packet_length = read (eth->rtx_fd, buf, ETH_MAXPL);
#if ETH_DEBUG
printf ("Reading TAP. ");
printf ("%d bytes read from TAP.\n", (int) packet_length);
#endif
nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
if (packet_length < 0)
{
fprintf (stderr, "Warning: Read of RXTATE_RECV failed: %s.\n",
strerror (errno));
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXE);
 
/* Signal interrupt if enabled, and no interrupt currently in
progress. */
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXE_M) &&
!eth->int_line_stat)
{
#if ETH_DEBUG
printf ("%d bytes read.\n",(int) nread);
printf ("Ethernet failed receive interrupt\n");
#endif
if (nread < 0)
{
fprintf (stderr,
"Warning: Read of RXTATE_RECV failed %s: ignored\n",
strerror (errno));
report_interrupt (eth->mac_int);
eth->int_line_stat = 1;
}
}
return packet_length;
}
else
{
return 0; /* No packet */
}
} /* eth_read_tap_packet () */
 
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXE);
 
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXE_M) &&
!eth->int_line_stat)
{
printf ("ETH_RXTATE_RECV RXE interrupt\n");
report_interrupt (eth->mac_int);
eth->int_line_stat = 1;
}
}
}
/* -------------------------------------------------------------------------- */
/*!Read an Ethernet packet.
 
/* If not promiscouos mode, check the destination address */
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, PRO) && nread)
{
if (TEST_FLAG (eth->regs.moder, ETH_MODER, IAM)
&& (eth->rx_buff[0] & 1))
{
/* Nothing for now */
}
This reads a single Ethernet packet from the outside world into the
supplied buffer. It deals with the different types of external interface.
 
@param[in] eth Pointer to the relevant Ethernet data structure
@param[out] buf Where to put the data
 
if (((eth->mac_address[5] != eth->rx_buff[0]) &&
(eth->rx_buff[5] != 0xff) ) ||
((eth->mac_address[4] != eth->rx_buff[1]) &&
(eth->rx_buff[4] != 0xff) ) ||
((eth->mac_address[3] != eth->rx_buff[2]) &&
(eth->rx_buff[3] != 0xff) ) ||
((eth->mac_address[2] != eth->rx_buff[3]) &&
(eth->rx_buff[2] != 0xff) ) ||
((eth->mac_address[1] != eth->rx_buff[4]) &&
(eth->rx_buff[1] != 0xff) ) ||
((eth->mac_address[0] != eth->rx_buff[5]) &&
(eth->rx_buff[0] != 0xff)))
{
#if ETH_DEBUG
printf("ETH_RXSTATE dropping packet for %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
eth->rx_buff[0],
eth->rx_buff[1],
eth->rx_buff[2],
eth->rx_buff[3],
eth->rx_buff[4],
eth->rx_buff[5]);
#endif
break;
}
}
@return The length if successful, zero if no packet was available,
a negative value otherwise. */
/* -------------------------------------------------------------------------- */
static ssize_t
eth_read_packet (struct eth_device *eth,
unsigned char *buf)
{
switch (eth->rtx_type)
{
case ETH_RTX_FILE: return eth_read_file_packet (eth, buf);
case ETH_RTX_TAP: return eth_read_tap_packet (eth, buf);
 
eth->rx.packet_length = nread;
eth->rx.bytes_left = nread;
eth->rx.bytes_read = 0;
default:
fprintf (stderr, "Unknown Ethernet read interface: ignored.\n");
return (ssize_t) -1;
}
} /* eth_read_packet () */
 
if (nread)
eth->rx.state = ETH_RXSTATE_WRITEFIFO;
 
break;
case ETH_RTX_VAPI:
break;
/* -------------------------------------------------------------------------- */
/*!Fill a buffer descriptor
 
A buffer descriptor is empty. Attempt to fill it from the outside world.
 
@param[in] eth The Ethernet data structure, passed as a void pointer. */
/* -------------------------------------------------------------------------- */
static void
eth_fill_bd (struct eth_device *eth)
{
 
/* First word of BD is flags and length, second is pointer to buffer */
unsigned long int bd_info = eth->regs.bd_ram[eth->rx_bd_index];
unsigned long int bd_addr = eth->regs.bd_ram[eth->rx_bd_index + 1];
 
long int packet_length;
long int bytes_read;
unsigned char buf[ETH_MAXPL];
 
/* Clear various status bits */
CLEAR_FLAG (bd_info, ETH_RX_BD, MISS);
CLEAR_FLAG (bd_info, ETH_RX_BD, INVALID);
CLEAR_FLAG (bd_info, ETH_RX_BD, DRIBBLE);
CLEAR_FLAG (bd_info, ETH_RX_BD, UVERRUN);
CLEAR_FLAG (bd_info, ETH_RX_BD, COLLISION);
CLEAR_FLAG (bd_info, ETH_RX_BD, TOOBIG);
CLEAR_FLAG (bd_info, ETH_RX_BD, TOOSHORT);
 
/* Loopback is permitted. We believe that Linux never uses it, so we'll
note the attempt and ignore.
@todo We should support this. */
if (TEST_FLAG (eth->regs.moder, ETH_MODER, LOOPBCK))
{
PRINTF ("Ethernet loopback requested.\n");
fprintf (stderr, "ERROR: Loopback not supported. Ignored.\n");
}
packet_length = eth_read_packet (eth, buf);
if (packet_length <= 0)
{
/* Empty packet or error. No more to do here. */
return;
}
/* Got a packet successfully. If not promiscuous mode, check the destination
address is meant for us. */
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, PRO))
{
if (TEST_FLAG (eth->regs.moder, ETH_MODER, IAM))
{
/* There is little documentation of how IAM is supposed to work. It
seems that some mapping function (not defined) maps the address
down to a number in the range 0-63. If that bit is set in
HASH0/HASH1 registers, the packet is accepted. */
fprintf (stderr, "Warning: Individual Address Mode ignored.\n");
}
break;
/* Check for HW address match. */
if ((0 != bcmp (eth->mac_address, buf, ETHER_ADDR_LEN)) &&
(0 != bcmp (mac_broadcast, buf, ETHER_ADDR_LEN)))
{
#if ETH_DEBUG
printf ("packet for %.2x:%.2x:%.2x:%.2x:%.2x:%.2x ignored.\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
#endif
/* Not for us. No more to do here. */
return;
}
}
 
case ETH_RXSTATE_WRITEFIFO:
/* Transfer the buffer into the BD. */
#if ETH_DEBUG
printf("ETH_RXSTATE_WRITEFIFO: writing to RXBD%d: %d bytes @ 0x%.8x\n",
(int) eth->rx.bd_index/2, (int)eth->rx.bytes_left,
(unsigned int)eth->rx.bd_addr);
printf ("writing to Rx BD%d: %d bytes @ 0x%.8x\n",
(int) eth->rx_bd_index / 2, (int) packet_length,
(unsigned int)bd_addr);
#endif
if (eth->rx.bytes_left > 0){
while((int) eth->rx.bytes_left){
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_direct32 (eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0);
/* update counters */
if (eth->rx.bytes_left >= 4)
{
eth->rx.bytes_left -= 4;
eth->rx.bytes_read += 4;
}
else
{
eth->rx.bytes_read += eth->rx.bytes_left;
eth->rx.bytes_left = 0;
}
for (bytes_read = 0; bytes_read < packet_length; bytes_read +=4)
{
unsigned long int send_word =
((unsigned long) buf[bytes_read] << 24) |
((unsigned long) buf[bytes_read + 1] << 16) |
((unsigned long) buf[bytes_read + 2] << 8) |
((unsigned long) buf[bytes_read + 3] );
set_direct32 (bd_addr + bytes_read, send_word, 0, 0);
}
#if ETH_DEBUG
printf("BD filled with 0x%08lx bytes.\n", bytes_read);
#endif
/* Write result to BD.
@todo Why is the length 4 more than the packet length? Is that for
the CRC? */
SET_FIELD (bd_info, ETH_RX_BD, LENGTH, packet_length + 4);
CLEAR_FLAG (bd_info, ETH_RX_BD, READY);
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
eth->regs.bd_ram[eth->rx_bd_index] = bd_info;
/* Advance to next BD. The Rx BDs start after the Tx BDs. */
if (TEST_FLAG (bd_info, ETH_RX_BD, WRAP) ||
(eth->rx_bd_index >= ETH_BD_COUNT))
{
eth->rx_bd_index = eth->regs.tx_bd_num * 2;
}
else
{
eth->rx_bd_index += 2;
}
/* Raise an interrupt if necessary. */
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXB_M) &&
TEST_FLAG (bd_info, ETH_RX_BD, IRQ))
{
if (eth->int_line_stat)
{
fprintf (stderr, "Warning: Interrupt active during Rx.\n");
}
}
else
{
#if ETH_DEBUG
printf("ETH_RXSTATE_WRITEFIFO: bytes read: 0x%.8x\n",
(unsigned int)eth->rx.bytes_read);
printf ("Rx successful receive interrupt\n");
#endif
if (eth->rx.bytes_left <= 0)
{
/* Write result to bd */
SET_FIELD (eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length + 4);
CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, READY);
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
/*
if (eth->rx.packet_length <
(GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL) - 4))
SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
if (eth->rx.packet_length >
GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MAXFL))
SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
*/
eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
report_interrupt (eth->mac_int);
eth->int_line_stat = 1;
}
}
} /* eth_fill_bd () */
 
/* advance to next BD */
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;
else
eth->rx.bd_index += 2;
 
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
/* -------------------------------------------------------------------------- */
/*!Ignore a packet from the outside world.
 
if ((TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXB_M)) &&
(TEST_FLAG (eth->rx.bd, ETH_RX_BD, IRQ)) &&
!eth->int_line_stat)
We don't have a BD ready, so any packets waiting should be thrown away.
 
@param[in] eth The Ethernet data structure. */
/* -------------------------------------------------------------------------- */
static void
eth_ignore_packet (struct eth_device *eth)
{
unsigned char buf[ETH_MAXPL];
ssize_t nread = eth_read_packet (eth, buf);
 
if (nread < 0)
{
fprintf (stderr,
"Warning: Read of when Ethernet busy failed %s.\n",
strerror (errno));
}
else if (nread > 0)
{
/* Record that a packet was thrown away. */
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
PRINTF ("Ethernet discarding %d bytes from TAP while BD full.\n",
nread);
/* Raise an interrupt if necessary. */
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M))
{
if (eth->int_line_stat)
{
fprintf (stderr, "Warning: Interrupt active during ignore.\n");
}
else
{
#if ETH_DEBUG
printf ("ETH_RXSTATE_WRITEFIFO interrupt\n");
printf ("Ethernet Rx BUSY interrupt\n");
#endif
report_interrupt (eth->mac_int);
eth->int_line_stat = 1;
}
}
}
} /* eth_ignore_packet () */
 
/* ready to receive next packet */
eth->rx.state = ETH_RXSTATE_IDLE;
 
/* -------------------------------------------------------------------------- */
/*!Rx clock function.
 
Responsible for starting and completing any RX actions.
 
The original version had 4 states, which allowed modeling the transfer of
data one byte per cycle. For now we use only the one state for
efficiency. When the buffer is empty, we fill it from the external world.
 
We schedule to wake up again each cycle. This means we will get called when
the core is still processing the previous interrupt. To avoid races, we do
nothing until the interrupt is cleared.
 
@todo We should eventually reinstate the one byte per cycle transfer.
 
@param[in] dat The Ethernet data structure, passed as a void pointer. */
/* -------------------------------------------------------------------------- */
static void
eth_controller_rx_clock (void *dat)
{
struct eth_device *eth = dat;
 
/* Only do anything if there is not an interrupt outstanding. */
if (!eth->int_line_stat)
{
/* First word of the BD is flags, where we can test if it's ready. */
if (TEST_FLAG (eth->regs.bd_ram[eth->rx_bd_index], ETH_RX_BD, READY))
{
/* The BD is empty, so we try to fill it with data from the outside
world. */
eth_fill_bd (eth); /* BD ready to be filled. */
}
break;
else if ((TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN)) &&
(ETH_RTX_FILE == eth->rtx_type))
{
/* The BD is full, Rx is enabled and we are reading from an external
TAP interface. We can't take any more, so we'll throw oustanding
input packets on the floor.
@note We don't do this for file I/O, since it would discard
everything immediately! */
eth_ignore_packet (eth);
}
}
 
/* Reschedule. Was 10 ticks when waiting (ETH_RXSTATE_RECV). Now always 1
tick. */
/* Whatever happens, we reschedule a wake up in the future. This used to be
every 10 ticks, but now it is very 1 tick. */
SCHED_ADD (eth_controller_rx_clock, dat, 1);
}
 
} /* eth_controller_rx_clock () */
 
 
/* ========================================================================= */
 
/* ========================================================================= */
982,7 → 1021,6
eth->txfile, strerror (errno));
}
 
eth->loopback_offset = lseek (eth->txfd, 0, SEEK_END);
break;
 
case ETH_RTX_TAP:
1037,14 → 1075,10
eth->regs.miimoder = 0x00000064;
eth->regs.tx_bd_num = 0x00000040;
 
/* Clear TX/RX status and initialize buffer descriptor index. */
memset (&(eth->tx), 0, sizeof (eth->tx));
memset (&(eth->rx), 0, sizeof (eth->rx));
/* Reset TX/RX BD indexes. The Rx BD indexes start after the Tx BD indexes. */
eth->tx_bd_index = 0;
eth->rx_bd_index = eth->regs.tx_bd_num * 2;
 
/* Reset TX/RX BD indexes */
eth->tx.bd_index = 0;
eth->rx.bd_index = eth->regs.tx_bd_num << 1;
 
/* Reset IRQ line status */
eth->int_line_stat = 0;
 
1083,8 → 1117,8
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]);
eth->mac_address[5], eth->mac_address[4], eth->mac_address[3],
eth->mac_address[2], eth->mac_address[1], eth->mac_address[0]);
PRINTF ("HASH0 : 0x%08lX\n", eth->regs.hash0);
PRINTF ("HASH1 : 0x%08lX\n", eth->regs.hash1);
}
1136,13 → 1170,13
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];
return (((unsigned long) eth->mac_address[2]) << 24) |
(((unsigned long) eth->mac_address[3]) << 16) |
(((unsigned long) eth->mac_address[4]) << 8) |
(unsigned long) eth->mac_address[5];
case ETH_MAC_ADDR1:
return (((unsigned long) eth->mac_address[5]) << 8) |
(unsigned long) eth->mac_address[4];
return (((unsigned long) eth->mac_address[0]) << 8) |
(unsigned long) eth->mac_address[1];
case ETH_HASH0:
return eth->regs.hash0;
case ETH_HASH1:
1168,6 → 1202,7
eth_write32 (oraddr_t addr, uint32_t value, void *dat)
{
struct eth_device *eth = dat;
unsigned char buf[ETH_MAXPL];
 
switch (addr)
{
1179,7 → 1214,7
TEST_FLAG (value, ETH_MODER, RXEN))
{
// Reset RX BD index
eth->rx.bd_index = eth->regs.tx_bd_num << 1;
eth->rx_bd_index = eth->regs.tx_bd_num << 1;
// Clear TAP
{
1200,7 → 1235,7
}
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
{
nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
nread = read (eth->rtx_fd, buf, ETH_MAXPL);
if (nread < 0)
{
1221,7 → 1256,7
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
TEST_FLAG (value, ETH_MODER, TXEN))
{
eth->tx.bd_index = 0;
eth->tx_bd_index = 0;
SCHED_ADD (eth_controller_tx_clock, dat, 1);
}
else if (!TEST_FLAG (value, ETH_MODER, TXEN) &&
1279,7 → 1314,7
case ETH_TX_BD_NUM:
/* When TX_BD_NUM is written, also reset current RX BD index */
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;
return;
case ETH_CTRLMODER:
eth->regs.controlmoder = value;
1310,14 → 1345,14
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;
eth->mac_address[5] = value & 0xFF;
eth->mac_address[4] = (value >> 8) & 0xFF;
eth->mac_address[3] = (value >> 16) & 0xFF;
eth->mac_address[2] = (value >> 24) & 0xFF;
return;
case ETH_MAC_ADDR1:
eth->mac_address[4] = value & 0xFF;
eth->mac_address[5] = (value >> 8) & 0xFF;
eth->mac_address[1] = value & 0xFF;
eth->mac_address[0] = (value >> 8) & 0xFF;
return;
case ETH_HASH0:
eth->regs.hash0 = value;
/configure
1,7 → 1,7
#! /bin/sh
# From configure.ac Id: configure.ac 434 2010-11-26 18:45:29Z jeremybennett using automake version AC_ACVERSION.
# From configure.ac Id: configure.ac 440 2010-12-08 19:35:51Z jeremybennett using automake version AC_ACVERSION.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.65 for or1ksim 2010-12-08.
# Generated by GNU Autoconf 2.65 for or1ksim 2010-12-15.
#
# Report bugs to <openrisc@opencores.org>.
#
722,8 → 722,8
# Identity of this package.
PACKAGE_NAME='or1ksim'
PACKAGE_TARNAME='or1ksim'
PACKAGE_VERSION='2010-12-08'
PACKAGE_STRING='or1ksim 2010-12-08'
PACKAGE_VERSION='2010-12-15'
PACKAGE_STRING='or1ksim 2010-12-15'
PACKAGE_BUGREPORT='openrisc@opencores.org'
PACKAGE_URL=''
 
1476,7 → 1476,7
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures or1ksim 2010-12-08 to adapt to many kinds of systems.
\`configure' configures or1ksim 2010-12-15 to adapt to many kinds of systems.
 
Usage: $0 [OPTION]... [VAR=VALUE]...
 
1547,7 → 1547,7
 
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of or1ksim 2010-12-08:";;
short | recursive ) echo "Configuration of or1ksim 2010-12-15:";;
esac
cat <<\_ACEOF
 
1654,7 → 1654,7
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
or1ksim configure 2010-12-08
or1ksim configure 2010-12-15
generated by GNU Autoconf 2.65
 
Copyright (C) 2009 Free Software Foundation, Inc.
2316,7 → 2316,7
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
 
It was created by or1ksim $as_me 2010-12-08, which was
It was created by or1ksim $as_me 2010-12-15, which was
generated by GNU Autoconf 2.65. Invocation command line was
 
$ $0 $@
10717,7 → 10717,7
 
# Define the identity of the package.
PACKAGE='or1ksim'
VERSION='2010-12-08'
VERSION='2010-12-15'
 
 
cat >>confdefs.h <<_ACEOF
13736,7 → 13736,7
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by or1ksim $as_me 2010-12-08, which was
This file was extended by or1ksim $as_me 2010-12-15, which was
generated by GNU Autoconf 2.65. Invocation command line was
 
CONFIG_FILES = $CONFIG_FILES
13802,7 → 13802,7
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
or1ksim config.status 2010-12-08
or1ksim config.status 2010-12-15
configured by $0, generated by GNU Autoconf 2.65,
with options \\"\$ac_cs_config\\"
 

powered by: WebSVN 2.1.0

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