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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [peripheral/] [eth.c] - Diff between revs 1748 and 1751

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

Rev 1748 Rev 1751
Line 42... Line 42...
#include <netinet/in.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if.h>
 
 
#ifdef HAVE_ETH_PHY
#if HAVE_ETH_PHY
#include <netpacket/packet.h>
#include <netpacket/packet.h>
#endif /* HAVE_ETH_PHY */
#endif /* HAVE_ETH_PHY */
 
 
#ifdef HAVE_NET_ETHERNET_H
#if HAVE_NET_ETHERNET_H
# include <net/ethernet.h>
# include <net/ethernet.h>
#elif defined(HAVE_SYS_ETHERNET_H)
#elif defined(HAVE_SYS_ETHERNET_H)
# include <sys/ethernet.h>
# include <sys/ethernet.h>
#else /* !HAVE_NET_ETHERNET_H && !HAVE_SYS_ETHERNET_H - */
#else /* !HAVE_NET_ETHERNET_H && !HAVE_SYS_ETHERNET_H - */
#include <sys/types.h>
#include <sys/types.h>
Line 66... Line 66...
#include "fields.h"
#include "fields.h"
#include "crc32.h"
#include "crc32.h"
#include "vapi.h"
#include "vapi.h"
#include "pic.h"
#include "pic.h"
#include "sched.h"
#include "sched.h"
#include "debug.h"
 
#include "toplevel-support.h"
#include "toplevel-support.h"
#include "sim-cmd.h"
#include "sim-cmd.h"
 
 
/* Address space required by one Ethernet MAC */
/* Address space required by one Ethernet MAC */
#define ETH_ADDR_SPACE 0x1000
#define ETH_ADDR_SPACE 0x1000
Line 402... Line 401...
  unsigned char tx_buff[ETH_MAXPL];
  unsigned char tx_buff[ETH_MAXPL];
  unsigned char lo_buff[ETH_MAXPL];
  unsigned char lo_buff[ETH_MAXPL];
};
};
 
 
 
 
DEFAULT_DEBUG_CHANNEL (eth);
 
 
 
/* simulator interface */
/* simulator interface */
static void eth_vapi_read (unsigned long id, unsigned long data, void *dat);
static void eth_vapi_read (unsigned long id, unsigned long data, void *dat);
/* register interface */
/* register interface */
static void eth_write32 (oraddr_t addr, uint32_t value, void *dat);
static void eth_write32 (oraddr_t addr, uint32_t value, void *dat);
static uint32_t eth_read32 (oraddr_t addr, void *dat);
static uint32_t eth_read32 (oraddr_t addr, void *dat);
Line 439... Line 436...
  unsigned long read_word;
  unsigned long read_word;
 
 
  switch (eth->tx.state)
  switch (eth->tx.state)
    {
    {
    case ETH_TXSTATE_IDLE:
    case ETH_TXSTATE_IDLE:
      TRACE ("TX - entering state WAIT4BD (%ld)\n", eth->tx.bd_index);
 
      eth->tx.state = ETH_TXSTATE_WAIT4BD;
      eth->tx.state = ETH_TXSTATE_WAIT4BD;
      break;
      break;
    case ETH_TXSTATE_WAIT4BD:
    case ETH_TXSTATE_WAIT4BD:
      /* Read buffer descriptor */
      /* Read buffer descriptor */
      eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index];
      eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index];
Line 492... Line 488...
            eth->tx.crc_dly = 1;
            eth->tx.crc_dly = 1;
          else
          else
            eth->tx.crc_dly = 0;
            eth->tx.crc_dly = 0;
          /* XXX - For now we skip CRC calculation */
          /* XXX - For now we skip CRC calculation */
 
 
          TRACE ("Ethernet: Starting TX of %lu 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)
          if (eth->rtx_type == ETH_RTX_FILE)
            {
            {
              /* write packet length to file */
              /* write packet length to file */
              nwritten =
              nwritten =
                write (eth->txfd, &(eth->tx.packet_length),
                write (eth->txfd, &(eth->tx.packet_length),
                       sizeof (eth->tx.packet_length));
                       sizeof (eth->tx.packet_length));
            }
            }
 
 
            /************************************************/
            /************************************************/
          /* start transmit with reading packet into FIFO */
          /* start transmit with reading packet into FIFO */
          TRACE ("TX - entering state READFIFO\n");
 
          eth->tx.state = ETH_TXSTATE_READFIFO;
          eth->tx.state = ETH_TXSTATE_READFIFO;
        }
        }
 
 
      /* stay in this state if (TXEN && !READY) */
      /* stay in this state if (TXEN && !READY) */
      break;
      break;
Line 537... Line 528...
          eth->tx.bytes_sent += 1;
          eth->tx.bytes_sent += 1;
        }
        }
#endif
#endif
      else
      else
        {
        {
          TRACE ("TX - entering state TRANSMIT\n");
 
          eth->tx.state = ETH_TXSTATE_TRANSMIT;
          eth->tx.state = ETH_TXSTATE_TRANSMIT;
        }
        }
      break;
      break;
    case ETH_TXSTATE_TRANSMIT:
    case ETH_TXSTATE_TRANSMIT:
      /* send packet */
      /* send packet */
Line 563... Line 553...
      /* set BD status */
      /* set BD status */
      if (nwritten == eth->tx.packet_length)
      if (nwritten == eth->tx.packet_length)
        {
        {
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
          TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
 
 
 
          TRACE ("TX - entering state WAIT4BD\n");
 
          eth->tx.state = ETH_TXSTATE_WAIT4BD;
          eth->tx.state = ETH_TXSTATE_WAIT4BD;
          TRACE ("send (%ld)bytes OK\n", nwritten);
 
        }
        }
      else
      else
        {
        {
          /* XXX - implement retry mechanism here! */
          /* XXX - implement retry mechanism here! */
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION);
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION);
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
          TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
 
 
 
          TRACE ("TX - entering state WAIT4BD\n");
 
          eth->tx.state = ETH_TXSTATE_WAIT4BD;
          eth->tx.state = ETH_TXSTATE_WAIT4BD;
          TRACE ("send FAILED!\n");
 
        }
        }
 
 
      eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd;
      eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd;
 
 
      /* generate OK interrupt */
      /* generate OK interrupt */
Line 631... Line 615...
 
 
 
 
  switch (eth->rx.state)
  switch (eth->rx.state)
    {
    {
    case ETH_RXSTATE_IDLE:
    case ETH_RXSTATE_IDLE:
      TRACE ("RX - entering state WAIT4BD (%ld)\n", eth->rx.bd_index);
 
      eth->rx.state = ETH_RXSTATE_WAIT4BD;
      eth->rx.state = ETH_RXSTATE_WAIT4BD;
      break;
      break;
 
 
    case ETH_RXSTATE_WAIT4BD:
    case ETH_RXSTATE_WAIT4BD:
      eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index];
      eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index];
Line 651... Line 634...
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, UVERRUN);
          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, COLLISION);
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
 
 
          TRACE ("Ethernet: Starting RX\n");
 
 
 
          /* Setup file to read from */
          /* Setup file to read from */
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, LOOPBCK))
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, LOOPBCK))
            {
            {
              eth->rx.fd = eth->txfd;
              eth->rx.fd = eth->txfd;
              eth->rx.offset = &(eth->loopback_offset);
              eth->rx.offset = &(eth->loopback_offset);
Line 664... Line 645...
          else
          else
            {
            {
              eth->rx.fd = eth->rxfd;
              eth->rx.fd = eth->rxfd;
              eth->rx.offset = 0;
              eth->rx.offset = 0;
            }
            }
          TRACE ("RX - entering state RECV\n");
 
          eth->rx.state = ETH_RXSTATE_RECV;
          eth->rx.state = ETH_RXSTATE_RECV;
        }
        }
      else if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
      else if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
        {
        {
          TRACE ("RX - entering state IDLE\n");
 
          eth->rx.state = ETH_RXSTATE_IDLE;
          eth->rx.state = ETH_RXSTATE_IDLE;
        }
        }
      else
      else
        {
        {
          nread =
          nread =
Line 697... Line 676...
              (eth, &(eth->rx.packet_length),
              (eth, &(eth->rx.packet_length),
               sizeof (eth->rx.packet_length)) <
               sizeof (eth->rx.packet_length)) <
              sizeof (eth->rx.packet_length))
              sizeof (eth->rx.packet_length))
            {
            {
              /* TODO: just do what real ethernet would do (some kind of error state) */
              /* TODO: just do what real ethernet would do (some kind of error state) */
              TRACE
 
                ("eth_start_rx(): File does not have a packet ready for RX (len = %ld)\n",
 
                 eth->rx.packet_length);
 
              sim_done ();
              sim_done ();
              break;
              break;
            }
            }
 
 
          /* Packet must be big enough to hold a header */
          /* Packet must be big enough to hold a header */
          if (eth->rx.packet_length < ETHER_HDR_LEN)
          if (eth->rx.packet_length < ETHER_HDR_LEN)
            {
            {
              TRACE ("eth_start_rx(): Packet too small\n");
 
              eth_rx_next_packet (eth);
              eth_rx_next_packet (eth);
 
 
              TRACE ("RX - entering state WAIT4BD\n");
 
              eth->rx.state = ETH_RXSTATE_WAIT4BD;
              eth->rx.state = ETH_RXSTATE_WAIT4BD;
              break;
              break;
            }
            }
 
 
          eth->rx.bytes_read = 0;
          eth->rx.bytes_read = 0;
Line 722... Line 696...
 
 
          /* for now Read entire packet into memory */
          /* for now Read entire packet into memory */
          nread = eth_read_rx_file (eth, eth->rx_buff, eth->rx.bytes_left);
          nread = eth_read_rx_file (eth, eth->rx_buff, eth->rx.bytes_left);
          if (nread < eth->rx.bytes_left)
          if (nread < eth->rx.bytes_left)
            {
            {
              TRACE ("Read %ld from %ld. Error!\n", nread,
 
                     eth->rx.bytes_left);
 
              eth->rx.error = 1;
              eth->rx.error = 1;
              break;
              break;
            }
            }
 
 
          eth->rx.packet_length = nread;
          eth->rx.packet_length = nread;
          eth->rx.bytes_left = nread;
          eth->rx.bytes_left = nread;
          eth->rx.bytes_read = 0;
          eth->rx.bytes_read = 0;
 
 
          TRACE ("RX - entering state WRITEFIFO\n");
 
          eth->rx.state = ETH_RXSTATE_WRITEFIFO;
          eth->rx.state = ETH_RXSTATE_WRITEFIFO;
 
 
          break;
          break;
 
 
        case ETH_RTX_SOCK:
        case ETH_RTX_SOCK:
          nread = recv (eth->rtx_sock, eth->rx_buff, ETH_MAXPL, MSG_DONTWAIT);
          nread = recv (eth->rtx_sock, eth->rx_buff, ETH_MAXPL, MSG_DONTWAIT);
 
 
          if (nread == 0)
          if (nread == 0)
            {
            {
              TRACE ("No data read\n");
 
              break;
              break;
            }
            }
          else if (nread < 0)
          else if (nread < 0)
            {
            {
              if (errno != EAGAIN)
              if (errno != EAGAIN)
                {
                {
                  TRACE ("recv() FAILED!\n");
 
                  break;
                  break;
                }
                }
              else
              else
                break;
                break;
            }
            }
Line 777... Line 746...
 
 
          eth->rx.packet_length = nread;
          eth->rx.packet_length = nread;
          eth->rx.bytes_left = nread;
          eth->rx.bytes_left = nread;
          eth->rx.bytes_read = 0;
          eth->rx.bytes_read = 0;
 
 
          TRACE ("RX - entering state WRITEFIFO\n");
 
          eth->rx.state = ETH_RXSTATE_WRITEFIFO;
          eth->rx.state = ETH_RXSTATE_WRITEFIFO;
 
 
          break;
          break;
        case ETH_RTX_VAPI:
        case ETH_RTX_VAPI:
          break;
          break;
Line 794... Line 762...
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 1] << 16) |
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 1] << 16) |
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 2] << 8) |
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 2] << 8) |
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 3]);
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 3]);
      set_direct32 (eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0);
      set_direct32 (eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0);
      /* update counters */
      /* update counters */
      TRACE ("Write %ld, left %ld - %08lXd\n", eth->rx.bytes_read,
 
             eth->rx.bytes_left, send_word);
 
      eth->rx.bytes_left -= 4;
      eth->rx.bytes_left -= 4;
      eth->rx.bytes_read += 4;
      eth->rx.bytes_read += 4;
#else
#else
      set_direct8 (eth->rx.bd_addr + eth->rx.bytes_read,
      set_direct8 (eth->rx.bd_addr + eth->rx.bytes_read,
                   eth->rx_buff[eth->rx.bytes_read], 0, 0);
                   eth->rx_buff[eth->rx.bytes_read], 0, 0);
Line 811... Line 777...
        {
        {
          /* Write result to bd */
          /* Write result to bd */
          SET_FIELD (eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length);
          SET_FIELD (eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length);
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, READY);
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, READY);
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
          TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
 
 
 
          if (eth->rx.packet_length <
          if (eth->rx.packet_length <
              (GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL) - 4))
              (GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL) - 4))
            SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
            SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
          if (eth->rx.packet_length >
          if (eth->rx.packet_length >
Line 836... Line 801...
            {
            {
              report_interrupt (eth->mac_int);
              report_interrupt (eth->mac_int);
            }
            }
 
 
          /* ready to receive next packet */
          /* ready to receive next packet */
          TRACE ("RX - entering state IDLE\n");
 
          eth->rx.state = ETH_RXSTATE_IDLE;
          eth->rx.state = ETH_RXSTATE_IDLE;
        }
        }
      break;
      break;
    }
    }
 
 
Line 874... Line 838...
{
{
  ssize_t result;
  ssize_t result;
 
 
  if (eth->rx.fd <= 0)
  if (eth->rx.fd <= 0)
    {
    {
      TRACE ("Ethernet: No RX file\n");
 
      return 0;
      return 0;
    }
    }
 
 
  if (eth->rx.offset)
  if (eth->rx.offset)
    if (lseek (eth->rx.fd, *(eth->rx.offset), SEEK_SET) == (off_t) - 1)
    if (lseek (eth->rx.fd, *(eth->rx.offset), SEEK_SET) == (off_t) - 1)
      {
      {
        TRACE ("Ethernet: Error seeking RX file\n");
 
        return 0;
        return 0;
      }
      }
 
 
  result = read (eth->rx.fd, buf, count);
  result = read (eth->rx.fd, buf, count);
  TRACE ("Ethernet: read result = %d \n", result);
 
  if (eth->rx.offset && result >= 0)
  if (eth->rx.offset && result >= 0)
    *(eth->rx.offset) += result;
    *(eth->rx.offset) += result;
 
 
  return result;
  return result;
}
}
Line 940... Line 901...
        case ETH_RTX_SOCK:
        case ETH_RTX_SOCK:
          /* (Re-)open TX/RX sockets */
          /* (Re-)open TX/RX sockets */
          if (eth->rtx_sock != 0)
          if (eth->rtx_sock != 0)
            break;
            break;
 
 
          TRACE ("RTX opening socket...\n");
 
          eth->rtx_sock = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
          eth->rtx_sock = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
          if (eth->rtx_sock == -1)
          if (eth->rtx_sock == -1)
            {
            {
              fprintf (stderr, "Cannot open rtx_sock.\n");
              fprintf (stderr, "Cannot open rtx_sock.\n");
              return;
              return;
            }
            }
 
 
          /* get interface index number */
          /* get interface index number */
          TRACE ("RTX getting interface...\n");
 
          memset (&(eth->ifr), 0, sizeof (eth->ifr));
          memset (&(eth->ifr), 0, sizeof (eth->ifr));
          strncpy (eth->ifr.ifr_name, eth->sockif, IFNAMSIZ);
          strncpy (eth->ifr.ifr_name, eth->sockif, IFNAMSIZ);
          if (ioctl (eth->rtx_sock, SIOCGIFINDEX, &(eth->ifr)) == -1)
          if (ioctl (eth->rtx_sock, SIOCGIFINDEX, &(eth->ifr)) == -1)
            {
            {
              fprintf (stderr, "SIOCGIFINDEX failed!\n");
              fprintf (stderr, "SIOCGIFINDEX failed!\n");
              return;
              return;
            }
            }
          TRACE ("RTX Socket Interface : %d\n", eth->ifr.ifr_ifindex);
 
 
 
          /* Bind to interface... */
          /* Bind to interface... */
          TRACE ("Binding to the interface ifindex=%d\n",
 
                 eth->ifr.ifr_ifindex);
 
          memset (&sll, 0xff, sizeof (sll));
          memset (&sll, 0xff, sizeof (sll));
          sll.sll_family = AF_PACKET;   /* allways AF_PACKET */
          sll.sll_family = AF_PACKET;   /* allways AF_PACKET */
          sll.sll_protocol = htons (ETH_P_ALL);
          sll.sll_protocol = htons (ETH_P_ALL);
          sll.sll_ifindex = eth->ifr.ifr_ifindex;
          sll.sll_ifindex = eth->ifr.ifr_ifindex;
          if (bind (eth->rtx_sock, (struct sockaddr *) &sll, sizeof (sll)) ==
          if (bind (eth->rtx_sock, (struct sockaddr *) &sll, sizeof (sll)) ==
Line 974... Line 930...
              fprintf (stderr, "Error bind().\n");
              fprintf (stderr, "Error bind().\n");
              return;
              return;
            }
            }
 
 
          /* first, flush all received packets. */
          /* first, flush all received packets. */
          TRACE ("Flush");
 
          do
          do
            {
            {
              fd_set fds;
              fd_set fds;
              struct timeval t;
              struct timeval t;
 
 
              TRACE (".");
 
              FD_ZERO (&fds);
              FD_ZERO (&fds);
              FD_SET (eth->rtx_sock, &fds);
              FD_SET (eth->rtx_sock, &fds);
              memset (&t, 0, sizeof (t));
              memset (&t, 0, sizeof (t));
              j = select (FD_SETSIZE, &fds, NULL, NULL, &t);
              j = select (FD_SETSIZE, &fds, NULL, NULL, &t);
              if (j > 0)
              if (j > 0)
                recv (eth->rtx_sock, eth->rx_buff, j, 0);
                recv (eth->rtx_sock, eth->rx_buff, j, 0);
            }
            }
          while (j);
          while (j);
          TRACE ("\n");
 
 
 
          break;
          break;
#else /* HAVE_ETH_PHY */
#else /* HAVE_ETH_PHY */
        case ETH_RTX_SOCK:
        case ETH_RTX_SOCK:
          fprintf (stderr,
          fprintf (stderr,
Line 1253... Line 1206...
  unsigned long which;
  unsigned long which;
  struct eth_device *eth = dat;
  struct eth_device *eth = dat;
 
 
  which = id - eth->base_vapi_id;
  which = id - eth->base_vapi_id;
 
 
  TRACE ("ETH: id %08lx, data %08lx\n", id, data);
 
 
 
  if (!eth)
  if (!eth)
    {
    {
      TRACE ("ETH: VAPI ID %08lx is not ours!\n", id);
 
      return;
      return;
    }
    }
 
 
  switch (which)
  switch (which)
    {
    {

powered by: WebSVN 2.1.0

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