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

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 450 to Rev 451
    Reverse comparison

Rev 450 → Rev 451

/openrisc/trunk/or1ksim/doc/or1ksim.info
2261,6 → 2261,26
device configured for the system (*note Ethernet TUN/TAP
Interface: Ethernet TUN/TAP Interface.)
 
`phy_addr = VALUE'
VALUE specifies the address for emulated ethernet PHY (default 0).
If there are multiple Ethernet peripherals, they should each have a
different PHY value.
 
`dummy_crc = 0|1'
If 1 (true, the default), the length of the data transferred to
the core will be increased by 4 bytes, as though the CRC were
included.
 
Note: This is for historical consistency with the OpenRISC
Ethernet hardware MAC, which passes on the CRC in the data
packet. This is unusual behavior for a MAC, but the OpenRISC
Linux device drivers have been written to expect it.
 
`phy_addr = VALUE'
VALUE specifies the address for emulated ethernet PHY (default 0).
If there are multiple Ethernet peripherals, they should each have a
different PHY value.
 
`vapi_id = VALUE'
VALUE specifies the value of the Verification API (VAPI) base
address to be used with the Ethernet PHY. *Note Verification API:
2267,12 → 2287,7
Verification API, for more details, which details the use of the
VAPI with the DMA controller.
 
`phy_addr = VALUE'
VALUE specifies the address for emulated ethernet PHY (default 0).
If there are multiple Ethernet peripherals, they should each have a
different PHY value.
 
 

File: or1ksim.info, Node: GPIO Configuration, Next: Display Interface Configuration, Prev: Ethernet Configuration, Up: Peripheral Configuration
 
4106,6 → 4121,8
(line 6)
* doze mode (power management register): Power Management Configuration.
(line 15)
* dummy_crc (Ethernet configuration): Ethernet Configuration.
(line 104)
* dv (Interactive CLI): Interactive Command Line.
(line 124)
* dynamic clock gating (power management register): Power Management Configuration.
4381,7 → 4398,7
* persistent TAP device creation: Setting Up a Persistent TAP device.
(line 6)
* phy_addr: Ethernet Configuration.
(line 105)
(line 99)
* PIC configuration: Interrupt Configuration.
(line 6)
* pio (ATA/ATAPI device configuration): Disc Interface Configuration.
4685,7 → 4702,7
* vapi_id (debug interface configuration): Debug Interface Configuration.
(line 43)
* vapi_id (DMA configuration) <1>: Ethernet Configuration.
(line 99)
(line 119)
* vapi_id (DMA configuration): DMA Configuration. (line 38)
* vapi_id (GPIO configuration): GPIO Configuration. (line 32)
* vapi_id (UART configuration): UART Configuration. (line 85)
4748,23 → 4765,23
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
Node: GPIO Configuration86324
Node: Display Interface Configuration87957
Node: Frame Buffer Configuration90266
Node: Keyboard Configuration92130
Node: Disc Interface Configuration94368
Node: Generic Peripheral Configuration99472
Node: Interactive Command Line101767
Node: Verification API108741
Node: Code Internals113171
Node: Coding Conventions113754
Node: Global Data Structures118181
Node: Concepts120838
Ref: Output Redirection120983
Ref: Interrupts Internal121521
Node: Internal Debugging122674
Node: Regression Testing123198
Node: GNU Free Documentation License126987
Node: Index149394

End Tag Table
/openrisc/trunk/or1ksim/doc/or1ksim.texi
2736,6 → 2736,30
persistent TAP device configured for the system (@pxref{Ethernet TUN/TAP
Interface, , Ethernet TUN/TAP Interface})
 
@item phy_addr = @var{value}
@cindex @code{phy_addr}
@var{value} specifies the address for emulated ethernet PHY (default
0). If there are multiple Ethernet peripherals, they should each have a
different PHY value.
 
@item dummy_crc = 0|1
@cindex @code{dummy_crc} (Ethernet configuration)
If 1 (true, the default), the length of the data transferred to the core
will be increased by 4 bytes, as though the CRC were included.
 
@quotation Note
This is for historical consistency with the OpenRISC Ethernet hardware
MAC, which passes on the CRC in the data packet. This is unusual
behavior for a MAC, but the OpenRISC Linux device drivers have been
written to expect it.
@end quotation
 
@item phy_addr = @var{value}
@cindex @code{phy_addr}
@var{value} specifies the address for emulated ethernet PHY (default
0). If there are multiple Ethernet peripherals, they should each have a
different PHY value.
 
@item vapi_id = @var{value}
@cindex @code{vapi_id} (DMA configuration)
@var{value} specifies the value of the Verification API (VAPI) base
2743,12 → 2767,6
Verification API}, for more details, which details the use of the VAPI
with the DMA controller.
 
@item phy_addr = @var{value}
@cindex @code{phy_addr}
@var{value} specifies the address for emulated ethernet PHY (default
0). If there are multiple Ethernet peripherals, they should each have a
different PHY value.
 
@end table
 
@node GPIO Configuration
/openrisc/trunk/or1ksim/doc/version.texi
1,4 → 1,4
@set UPDATED 10 December 2010
@set UPDATED 15 December 2010
@set UPDATED-MONTH December 2010
@set EDITION 2010-12-15
@set VERSION 2010-12-15
/openrisc/trunk/or1ksim/ChangeLog
1,8 → 1,27
2010-12-15 Jeremy Bennett <jeremy@jeremybennett.com>
 
* peripheral/eth.c <RTX_RESCHED_PERIOD>: Added.
(eth_controller_tx_clock, eth_controller_rx_clock): Reschedule for
RTX_RESCHED_PERIOD.
(eth_controller_tx_clock): dummy_crc parameter controls whether
CRC is added.
(eth_ignore_tap_packet): Deleted.
(eth_ignore_tap_packets): Added (based on eth_ignore_tap_packet).
(eth_reset): I/O opening moved into eth_open_if.
(eth_open_if, eth_open_file_if, eth_open_tap_if): Created.
(eth_regname): Created.
(eth_read32, eth_write32): Unified debug printing.
(eth_dummy_crc): Created.
(eth_sec_start): Initialize dummy_crc.
(reg_ethernet_sec): Add dummy_crc parameter.
* doc/or1ksim.texi: Updated Ethernet configuration section for
dummy_crc.
 
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.
* peripheral/eth.c <mac_broadcast>: 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.
/openrisc/trunk/or1ksim/peripheral/eth.c
70,6 → 70,8
# define ETH_DEBUG 1
#endif
 
/*! Period (clock cycles) for rescheduling Rx and Tx controllers. */
#define RTX_RESCHED_PERIOD 1
 
/*! MAC address that is always accepted. */
static const unsigned char mac_broadcast[ETHER_ADDR_LEN] =
94,6 → 96,7
unsigned char mac_address[ETHER_ADDR_LEN]; /* Ext HW address */
unsigned long int phy_addr; /* Int HW address */
unsigned long int mac_int; /* interrupt line number */
int dummy_crc; /* Flag indicating if we add CRC */
int int_line_stat; /* interrupt line status */
 
/* External interface deatils */
141,141 → 144,7
};
 
 
 
/* -------------------------------------------------------------------------- */
/*!Emulate MIIM transaction to ethernet PHY
 
@param[in] eth Ethernet device datastruture. */
/* -------------------------------------------------------------------------- */
static void
eth_miim_trans (struct eth_device *eth)
{
switch (eth->regs.miicommand)
{
case ((1 << ETH_MIICOMM_WCDATA_OFFSET)):
/* Perhaps something to emulate here later, but for now do nothing */
break;
case ((1 << ETH_MIICOMM_RSTAT_OFFSET)):
/*
printf("or1ksim: eth_miim_trans: phy %d\n",(int)
((eth->regs.miiaddress >> ETH_MIIADDR_FIAD_OFFSET)&
ETH_MIIADDR_FIAD_MASK));
printf("or1ksim: eth_miim_trans: reg %d\n",(int)
((eth->regs.miiaddress >> ETH_MIIADDR_RGAD_OFFSET)&
ETH_MIIADDR_RGAD_MASK));
*/
/*First check if it's the correct PHY to address */
if (((eth->regs.miiaddress >> ETH_MIIADDR_FIAD_OFFSET)&
ETH_MIIADDR_FIAD_MASK) == eth->phy_addr)
{
/* Correct PHY - now switch based on the register address in the PHY*/
switch ((eth->regs.miiaddress >> ETH_MIIADDR_RGAD_OFFSET)&
ETH_MIIADDR_RGAD_MASK)
{
case MII_BMCR:
eth->regs.miirx_data = BMCR_FULLDPLX;
break;
case MII_BMSR:
eth->regs.miirx_data = BMSR_LSTATUS | BMSR_ANEGCOMPLETE |
BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL;
break;
case MII_PHYSID1:
eth->regs.miirx_data = 0x22; /* Micrel PHYID */
break;
case MII_PHYSID2:
eth->regs.miirx_data = 0x1613; /* Micrel PHYID */
break;
case MII_ADVERTISE:
eth->regs.miirx_data = ADVERTISE_FULL;
break;
case MII_LPA:
eth->regs.miirx_data = LPA_DUPLEX | LPA_100;
break;
case MII_EXPANSION:
eth->regs.miirx_data = 0;
break;
case MII_CTRL1000:
eth->regs.miirx_data = 0;
break;
case MII_STAT1000:
eth->regs.miirx_data = 0;
break;
case MII_ESTATUS:
eth->regs.miirx_data = 0;
break;
case MII_DCOUNTER:
eth->regs.miirx_data = 0;
break;
case MII_FCSCOUNTER:
eth->regs.miirx_data = 0;
break;
case MII_NWAYTEST:
eth->regs.miirx_data = 0;
break;
case MII_RERRCOUNTER:
eth->regs.miirx_data = 0;
break;
case MII_SREVISION:
eth->regs.miirx_data = 0;
break;
case MII_RESV1:
eth->regs.miirx_data = 0;
break;
case MII_LBRERROR:
eth->regs.miirx_data = 0;
break;
case MII_PHYADDR:
eth->regs.miirx_data = eth->phy_addr;
break;
case MII_RESV2:
eth->regs.miirx_data = 0;
break;
case MII_TPISTATUS:
eth->regs.miirx_data = 0;
break;
case MII_NCONFIG:
eth->regs.miirx_data = 0;
break;
default:
eth->regs.miirx_data = 0xffff;
break;
}
}
else
{
eth->regs.miirx_data = 0xffff; /* PHY doesn't exist, read all 1's */
}
 
break;
 
case ((1 << ETH_MIICOMM_SCANS_OFFSET)):
/* From MAC's datasheet:
A host initiates the Scan Status Operation by asserting the SCANSTAT
signal. The MIIM performs a continuous read operation of the PHY
Status register. The PHY is selected by the FIAD[4:0] signals. The
link status LinkFail signal is asserted/deasserted by the MIIM module
and reflects the link status bit of the PHY Status register. The
signal NVALID is used for qualifying the validity of the LinkFail
signals and the status data PRSD[15:0]. These signals are invalid
until the first scan status operation ends. During the scan status
operation, the BUSY signal is asserted until the last read is
performed (the scan status operation is stopped).
 
So for now - do nothing, leave link status indicator as permanently
with link.
*/
 
break;
default:
break;
}
} /* eth_miim_trans () */
 
 
 
/* -------------------------------------------------------------------------- */
/*!Write an Ethernet packet to a FILE interface.
 
This writes a single Ethernet packet to a FILE interface. The format is to
538,7 → 407,7
}
 
/* Wake up again after 1 ticks (was 10, changed by Julius). */
SCHED_ADD (eth_controller_tx_clock, dat, 1);
SCHED_ADD (eth_controller_tx_clock, dat, RTX_RESCHED_PERIOD);
 
} /* eth_controller_tx_clock () */
 
789,10 → 658,15
#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);
 
The OpenRISC MAC hardware passes on the CRC (which it should not). The
Linux drivers have been written to expect a value (which they ignore). So
for consistency, we pretend the length is 4 bytes longer.
 
This is now controlled by a configuration parameter, dummy_crc. For
backwards compatibility, it defaults to TRUE. */
SET_FIELD (bd_info, ETH_RX_BD, LENGTH,
packet_length + (eth->dummy_crc ? 4 : 0));
CLEAR_FLAG (bd_info, ETH_RX_BD, READY);
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
830,51 → 704,69
 
 
/* -------------------------------------------------------------------------- */
/*!Ignore a packet from the outside world.
/*!Ignore a packet from the TAP interface.
 
We don't have a BD ready, so any packets waiting should be thrown away.
 
@param[in] eth The Ethernet data structure. */
@param[in] eth The Ethernet data structure.
 
@return 1 (TRUE) if more or more packets were discarded, zero otherwise. */
/* -------------------------------------------------------------------------- */
static void
eth_ignore_packet (struct eth_device *eth)
static int
eth_ignore_tap_packets (struct eth_device *eth)
{
unsigned char buf[ETH_MAXPL];
ssize_t nread = eth_read_packet (eth, buf);
int result = 0;
int n;
/* Read packets until there are none left. */
do
{
struct pollfd fds[1];
 
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))
/* Poll to see if there is anything to be read. */
fds[0].fd = eth->rtx_fd;
fds[0].events = POLLIN;
n = poll (fds, 1, 0);
if (n < 0)
{
if (eth->int_line_stat)
/* Give up with a warning if poll fails */
fprintf (stderr,
"Warning: Poll error while emptying TAP: %s: ignored.\n",
strerror (errno));
return result;
}
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
{
unsigned char buf[ETH_MAXPL];
ssize_t nread = eth_read_packet (eth, buf);
 
if (nread < 0)
{
fprintf (stderr, "Warning: Interrupt active during ignore.\n");
/* Give up with a warning if read fails */
fprintf (stderr,
"Warning: Read of when Ethernet busy failed %s.\n",
strerror (errno));
return result;
}
else
else if (nread > 0)
{
/* Record that a packet was thrown away. */
result = 1;
#if ETH_DEBUG
printf ("Ethernet Rx BUSY interrupt\n");
printf ("Ethernet discarding %d bytes from TAP while BD full.\n",
nread);
#endif
report_interrupt (eth->mac_int);
eth->int_line_stat = 1;
}
}
}
} /* eth_ignore_packet () */
while (n > 0);
 
return result;
 
} /* eth_ignore_tap_packets () */
 
 
/* -------------------------------------------------------------------------- */
/*!Rx clock function.
 
916,29 → 808,55
@note We don't do this for file I/O, since it would discard
everything immediately! */
eth_ignore_packet (eth);
if (eth_ignore_tap_packets (eth))
{
/* A packet has been thrown away, so mark the INT_SOURCE
register accordingly. */
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
 
/* 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 ("Ethernet Rx BUSY interrupt\n");
#endif
report_interrupt (eth->mac_int);
eth->int_line_stat = 1;
}
}
}
}
}
 
/* 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);
SCHED_ADD (eth_controller_rx_clock, dat, RTX_RESCHED_PERIOD);
 
} /* eth_controller_rx_clock () */
 
 
/* ========================================================================= */
/* -------------------------------------------------------------------------- */
/*!VAPI connection to outside.
 
/* ========================================================================= */
Used for remote testing of the interface. Currently does nothing.
 
 
/*
* VAPI connection to outside
*/
@param[in] id The VAPI ID to use.
@param[in] data Any data associated (unused here).
@param[in] dat The Ethernet data structure, cast to a void pointer. */
/* -------------------------------------------------------------------------- */
static void
eth_vapi_read (unsigned long id, unsigned long data, void *dat)
eth_vapi_read (unsigned long int id,
unsigned long int data,
void *dat)
{
unsigned long which;
unsigned long int which;
struct eth_device *eth = dat;
 
which = id - eth->base_vapi_id;
957,123 → 875,202
}
}
 
 
/* -------------------------------------------------------------------------- */
/*!Reset the Ethernet.
/*!Print register values on stdout
 
Open the correct type of simulation interface to the outside world.
 
Initialize all registers to default and places devices in memory address
space.
 
@param[in] dat The Ethernet interface data structure. */
/* -------------------------------------------------------------------------- */
static void
eth_reset (void *dat)
eth_status (void *dat)
{
struct eth_device *eth = dat;
struct ifreq ifr;
 
#if ETH_DEBUG
printf ("Resetting Ethernet\n");
PRINTF ("\nEthernet MAC at 0x%" PRIxADDR ":\n", 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[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);
 
} /* eth_status () */
 
 
/* -------------------------------------------------------------------------- */
/*!Open the external file interface to the Ethernet
 
The data is represented by an input and an output file.
 
@param[in] eth The Ethernet interface data structure. */
/* -------------------------------------------------------------------------- */
static void
eth_open_file_if (struct eth_device *eth)
{
/* (Re-)open TX/RX files */
if (eth->rxfd >= 0)
{
close (eth->rxfd);
}
 
if (eth->txfd >= 0)
{
close (eth->txfd);
}
 
eth->rxfd = -1;
eth->txfd = -1;
 
eth->rxfd = open (eth->rxfile, O_RDONLY);
if (eth->rxfd < 0)
{
fprintf (stderr, "Warning: Cannot open Ethernet RX file \"%s\": %s\n",
eth->rxfile, strerror (errno));
}
 
eth->txfd = open (eth->txfile,
#if defined(O_SYNC) /* BSD/MacOS X doesn't know about O_SYNC */
O_SYNC |
#endif
/* Nothing to do if we do not have a base address set.
O_RDWR | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (eth->txfd < 0)
{
fprintf (stderr, "Warning: Cannot open Ethernet TX file \"%s\": %s\n",
eth->txfile, strerror (errno));
}
} /* eth_open_file_if () */
 
TODO: Surely this should test for being enabled? */
if (0 == eth->baseaddr)
 
/* -------------------------------------------------------------------------- */
/*!Open the external TAP interface to the Ethernet
 
Packets are transferred over a TAP/TUN interface. We assume a persistent
tap interface has been set up and is owned by the user, so they can open
and manipulate it. See the User Guide for details of setting this up.
 
@todo We don't flush the TAP interface. Should we?
 
@param[in] eth The Ethernet interface data structure. */
/* -------------------------------------------------------------------------- */
static void
eth_open_tap_if (struct eth_device *eth)
{
struct ifreq ifr;
 
/* We don't support re-opening. If it's open, it stays open. */
if (eth->rtx_fd >= 0)
{
return;
}
 
switch (eth->rtx_type)
/* Open the TUN/TAP device */
eth->rtx_fd = open ("/dev/net/tun", O_RDWR);
if( eth->rtx_fd < 0 )
{
case ETH_RTX_FILE:
fprintf (stderr, "Warning: Failed to open TUN/TAP device: %s\n",
strerror (errno));
eth->rtx_fd = -1;
return;
}
 
/* (Re-)open TX/RX files */
if (eth->rxfd >= 0)
{
close (eth->rxfd);
}
/* Turn it into a specific TAP device. If we haven't specified a specific
(persistent) device, one will be created, but that requires superuser, or
at least CAP_NET_ADMIN capabilities. */
memset (&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy (ifr.ifr_name, eth->tap_dev, IFNAMSIZ);
 
if (eth->txfd >= 0)
{
close (eth->txfd);
}
if (ioctl (eth->rtx_fd, TUNSETIFF, (void *) &ifr) < 0)
{
fprintf (stderr, "Warning: Failed to set TAP device: %s\n",
strerror (errno));
close (eth->rtx_fd);
eth->rtx_fd = -1;
return;
}
#if ETH_DEBUG
PRINTF ("Opened TAP %s\n", ifr.ifr_name);
#endif
} /* eth_open_tap_if () */
 
eth->rxfd = -1;
eth->txfd = -1;
 
eth->rxfd = open (eth->rxfile, O_RDONLY);
if (eth->rxfd < 0)
{
fprintf (stderr, "Warning: Cannot open Ethernet RX file \"%s\": %s\n",
eth->rxfile, strerror (errno));
}
/* -------------------------------------------------------------------------- */
/*!Open the external interface to the Ethernet
 
eth->txfd = open (eth->txfile,
#if defined(O_SYNC) /* BSD/MacOS X doesn't know about O_SYNC */
O_SYNC |
#endif
O_RDWR | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (eth->txfd < 0)
{
fprintf (stderr, "Warning: Cannot open Ethernet TX file \"%s\": %s\n",
eth->txfile, strerror (errno));
}
Calls the appropriate function for the interface type.
 
@param[in] eth The Ethernet interface data structure. */
/* -------------------------------------------------------------------------- */
static void
eth_open_if (struct eth_device *eth)
{
switch (eth->rtx_type)
{
case ETH_RTX_FILE: eth_open_file_if (eth); break;
case ETH_RTX_TAP: eth_open_tap_if (eth); break;
 
default:
fprintf (stderr, "Unknown Ethernet interface: ignored.\n");
break;
}
} /* eth_open_if () */
 
case ETH_RTX_TAP:
 
/* (Re-)open TAP interface if necessary */
if (eth->rtx_fd != 0)
{
break;
}
/* -------------------------------------------------------------------------- */
/*!Reset the Ethernet.
 
/* Open the TUN/TAP device */
eth->rtx_fd = open ("/dev/net/tun", O_RDWR);
if( eth->rtx_fd < 0 )
{
fprintf (stderr, "Warning: Failed to open TUN/TAP device: %s\n",
strerror (errno));
eth->rtx_fd = 0;
return;
}
Open the correct type of simulation interface to the outside world.
 
/* Turn it into a specific TAP device. If we haven't specified a
specific (persistent) device, one will be created, but that requires
superuser, or at least CAP_NET_ADMIN capabilities. */
memset (&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy (ifr.ifr_name, eth->tap_dev, IFNAMSIZ);
Initialize all registers to default and places devices in memory address
space.
 
if (ioctl (eth->rtx_fd, TUNSETIFF, (void *) &ifr) < 0)
{
fprintf (stderr, "Warning: Failed to set TAP device: %s\n",
strerror (errno));
close (eth->rtx_fd);
eth->rtx_fd = 0;
return;
}
@param[in] dat The Ethernet interface data structure. */
/* -------------------------------------------------------------------------- */
static void
eth_reset (void *dat)
{
struct eth_device *eth = dat;
 
#if ETH_DEBUG
PRINTF ("Opened TAP %s\n", ifr.ifr_name);
printf ("Resetting Ethernet\n");
#endif
/* Do we need to flush any packets? */
break;
 
/* Nothing to do if we do not have a base address set, or we are not
enabled. */
if (!eth->enabled || (0 == eth->baseaddr))
{
return;
}
 
eth_open_if (eth);
 
/* 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 = 0x00000040;
eth->regs.moder = 0x0000A000; /* Padding & CRC enabled */
eth->regs.ipgt = 0x00000012; /* Half duplex (matches MODER) */
eth->regs.ipgr1 = 0x0000000C; /* Recommended value */
eth->regs.ipgr2 = 0x00000012; /* Recommended value */
eth->regs.packetlen = 0x003C0600; /* MINFL 60, MAXFL 1,536 bytes */
eth->regs.collconf = 0x000F003F; /* MAXRET 15, COLLVALID 63 */
eth->regs.tx_bd_num = 0x00000040; /* Max Tx BD */
eth->regs.miimoder = 0x00000064; /* Send preamble, CLKDIV 100 */
 
/* Reset TX/RX BD indexes. The Rx BD indexes start after the Tx BD indexes. */
eth->tx_bd_index = 0;
1091,302 → 1088,447
} /* eth_reset () */
 
 
/*
Print register values on stdout
*/
static void
eth_status (void *dat)
#if ETH_DEBUG
/* -------------------------------------------------------------------------- */
/*!Map a register address to its name
 
@param[in[ addr The address of the register to name (offset from base).
 
@return The name of the register. */
/* -------------------------------------------------------------------------- */
static char *
eth_regname (oraddr_t addr)
{
struct eth_device *eth = dat;
static char bdstr[8]; /* For "BD[nnn]" */
 
PRINTF ("\nEthernet MAC at 0x%" PRIxADDR ":\n", 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[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);
}
switch (addr)
{
case ETH_MODER: return "MODER";
case ETH_INT_SOURCE: return "INT_SOURCE";
case ETH_INT_MASK: return "INT_MASK";
case ETH_IPGT: return "IPGT";
case ETH_IPGR1: return "IPGR1";
case ETH_IPGR2: return "IPGR2";
case ETH_PACKETLEN: return "PACKETLEN";
case ETH_COLLCONF: return "COLLCONF";
case ETH_TX_BD_NUM: return "TX_BD_NUM";
case ETH_CTRLMODER: return "CTRLMODER";
case ETH_MIIMODER: return "MIIMODER";
case ETH_MIICOMMAND: return "MIICOMMAND";
case ETH_MIIADDRESS: return "MIIADDRESS";
case ETH_MIITX_DATA: return "MIITX_DATA";
case ETH_MIIRX_DATA: return "MIIRX_DATA";
case ETH_MIISTATUS: return "MIISTATUS";
case ETH_MAC_ADDR0: return "MAC_ADDR0";
case ETH_MAC_ADDR1: return "MAC_ADDR1";
case ETH_HASH0: return "HASH0";
case ETH_HASH1: return "HASH1";
 
/* ========================================================================= */
default:
/* Buffer descriptors are a special case. */
if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
{
sprintf (bdstr, "BD[%.3d]", (addr - ETH_BD_BASE) / 4);
return bdstr;
}
else
{
return "INVALID";
}
}
} /* eth_regname () */
#endif
 
 
/*
Read a register
*/
/* -------------------------------------------------------------------------- */
/*!Read a register
 
@param[in] addr The address of the register to read (offset from base).
@param[in] dat The Ethernet interface data structure, cast to a void
pointer.
 
@return The value read. */
/* -------------------------------------------------------------------------- */
static uint32_t
eth_read32 (oraddr_t addr, void *dat)
eth_read32 (oraddr_t addr,
void *dat)
{
struct eth_device *eth = dat;
uint32_t res;
 
switch (addr)
{
case ETH_MODER: res = eth->regs.moder; break;
case ETH_INT_SOURCE: res = eth->regs.int_source; break;
case ETH_INT_MASK: res = eth->regs.int_mask; break;
case ETH_IPGT: res = eth->regs.ipgt; break;
case ETH_IPGR1: res = eth->regs.ipgr1; break;
case ETH_IPGR2: res = eth->regs.ipgr2; break;
case ETH_PACKETLEN: res = eth->regs.packetlen; break;
case ETH_COLLCONF: res = eth->regs.collconf; break;
case ETH_TX_BD_NUM: res = eth->regs.tx_bd_num; break;
case ETH_CTRLMODER: res = eth->regs.controlmoder; break;
case ETH_MIIMODER: res = eth->regs.miimoder; break;
case ETH_MIICOMMAND: res = eth->regs.miicommand; break;
case ETH_MIIADDRESS: res = eth->regs.miiaddress; break;
case ETH_MIITX_DATA: res = eth->regs.miitx_data; break;
case ETH_MIIRX_DATA: res = eth->regs.miirx_data; break;
case ETH_MIISTATUS: res = eth->regs.miistatus; break;
case ETH_MAC_ADDR0:
res =
(((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];
break;
case ETH_MAC_ADDR1:
res =
(((unsigned long) eth->mac_address[0]) << 8) |
(unsigned long) eth->mac_address[1];
break;
case ETH_HASH0: res = eth->regs.hash0; break;
case ETH_HASH1: res = eth->regs.hash1; break;
 
default:
/* Buffer descriptors are a special case. */
if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
{
res = eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4];
break;
}
else
{
fprintf (stderr,
"Warning: eth_read32( 0x%" PRIxADDR " ): Illegal address\n",
addr + eth->baseaddr);
res = 0;
}
}
 
#if ETH_DEBUG
/* Only trace registers of particular interest */
switch (addr)
{
case ETH_MODER:
return eth->regs.moder;
case ETH_INT_SOURCE:
return eth->regs.int_source;
case ETH_INT_MASK:
return eth->regs.int_mask;
case ETH_IPGT:
return eth->regs.ipgt;
case ETH_IPGR1:
return eth->regs.ipgr1;
case ETH_IPGR2:
return eth->regs.ipgr2;
case ETH_PACKETLEN:
return eth->regs.packetlen;
case ETH_COLLCONF:
return eth->regs.collconf;
case ETH_TX_BD_NUM:
return eth->regs.tx_bd_num;
case ETH_CTRLMODER:
return eth->regs.controlmoder;
case ETH_MIIMODER:
return eth->regs.miimoder;
case ETH_MIICOMMAND:
return eth->regs.miicommand;
case ETH_MIIADDRESS:
return eth->regs.miiaddress;
case ETH_MIITX_DATA:
return eth->regs.miitx_data;
case ETH_MIIRX_DATA:
/*printf("or1ksim: read MIIM RX: 0x%x\n",(int)eth->regs.miirx_data);*/
return eth->regs.miirx_data;
case ETH_MIISTATUS:
return eth->regs.miistatus;
case ETH_MAC_ADDR0:
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[0]) << 8) |
(unsigned long) eth->mac_address[1];
case ETH_HASH0:
return eth->regs.hash0;
case ETH_HASH1:
return eth->regs.hash1;
/*case ETH_DMA_RX_TX: return eth_rx( eth ); */
printf ("eth_read32: %s = 0x%08lx\n", eth_regname (addr),
(unsigned long int) res);
}
#endif
 
if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
return eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4];
return res;
 
PRINTF ("eth_read32( 0x%" PRIxADDR " ): Illegal address\n",
addr + eth->baseaddr);
return 0;
}
} /* eth_read32 () */
 
/* ========================================================================= */
 
/* -------------------------------------------------------------------------- */
/*!Emulate MIIM transaction to ethernet PHY
 
/*
Write a register
*/
@param[in] eth Ethernet device datastruture. */
/* -------------------------------------------------------------------------- */
static void
eth_miim_trans (struct eth_device *eth)
{
switch (eth->regs.miicommand)
{
case ((1 << ETH_MIICOMM_WCDATA_OFFSET)):
/* Perhaps something to emulate here later, but for now do nothing */
break;
case ((1 << ETH_MIICOMM_RSTAT_OFFSET)):
/*First check if it's the correct PHY to address */
if (((eth->regs.miiaddress >> ETH_MIIADDR_FIAD_OFFSET)&
ETH_MIIADDR_FIAD_MASK) == eth->phy_addr)
{
/* Correct PHY - now switch based on the register address in the PHY*/
switch ((eth->regs.miiaddress >> ETH_MIIADDR_RGAD_OFFSET)&
ETH_MIIADDR_RGAD_MASK)
{
case MII_BMCR:
eth->regs.miirx_data = BMCR_FULLDPLX;
break;
case MII_BMSR:
eth->regs.miirx_data = BMSR_LSTATUS | BMSR_ANEGCOMPLETE |
BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL;
break;
case MII_PHYSID1:
eth->regs.miirx_data = 0x22; /* Micrel PHYID */
break;
case MII_PHYSID2:
eth->regs.miirx_data = 0x1613; /* Micrel PHYID */
break;
case MII_ADVERTISE:
eth->regs.miirx_data = ADVERTISE_FULL;
break;
case MII_LPA:
eth->regs.miirx_data = LPA_DUPLEX | LPA_100;
break;
case MII_EXPANSION:
eth->regs.miirx_data = 0;
break;
case MII_CTRL1000:
eth->regs.miirx_data = 0;
break;
case MII_STAT1000:
eth->regs.miirx_data = 0;
break;
case MII_ESTATUS:
eth->regs.miirx_data = 0;
break;
case MII_DCOUNTER:
eth->regs.miirx_data = 0;
break;
case MII_FCSCOUNTER:
eth->regs.miirx_data = 0;
break;
case MII_NWAYTEST:
eth->regs.miirx_data = 0;
break;
case MII_RERRCOUNTER:
eth->regs.miirx_data = 0;
break;
case MII_SREVISION:
eth->regs.miirx_data = 0;
break;
case MII_RESV1:
eth->regs.miirx_data = 0;
break;
case MII_LBRERROR:
eth->regs.miirx_data = 0;
break;
case MII_PHYADDR:
eth->regs.miirx_data = eth->phy_addr;
break;
case MII_RESV2:
eth->regs.miirx_data = 0;
break;
case MII_TPISTATUS:
eth->regs.miirx_data = 0;
break;
case MII_NCONFIG:
eth->regs.miirx_data = 0;
break;
default:
eth->regs.miirx_data = 0xffff;
break;
}
}
else
{
eth->regs.miirx_data = 0xffff; /* PHY doesn't exist, read all 1's */
}
 
break;
 
case ((1 << ETH_MIICOMM_SCANS_OFFSET)):
/* From MAC's datasheet:
A host initiates the Scan Status Operation by asserting the SCANSTAT
signal. The MIIM performs a continuous read operation of the PHY
Status register. The PHY is selected by the FIAD[4:0] signals. The
link status LinkFail signal is asserted/deasserted by the MIIM module
and reflects the link status bit of the PHY Status register. The
signal NVALID is used for qualifying the validity of the LinkFail
signals and the status data PRSD[15:0]. These signals are invalid
until the first scan status operation ends. During the scan status
operation, the BUSY signal is asserted until the last read is
performed (the scan status operation is stopped).
 
So for now - do nothing, leave link status indicator as permanently
with link.
*/
 
break;
default:
break;
}
} /* eth_miim_trans () */
 
 
 
/* -------------------------------------------------------------------------- */
/*!Write a register
 
@param[in] addr The address of the register to read (offset from base).
@param[in] value The value to write.
@param[in] dat The Ethernet interface data structure, cast to a void
pointer. */
/* -------------------------------------------------------------------------- */
static void
eth_write32 (oraddr_t addr, uint32_t value, void *dat)
{
struct eth_device *eth = dat;
unsigned char buf[ETH_MAXPL];
 
#if ETH_DEBUG
/* Only trace registers of particular interest */
switch (addr)
{
case ETH_MODER:
#if ETH_DEBUG
printf("eth_write32: MODER 0x%x\n",value);
case ETH_INT_SOURCE:
case ETH_INT_MASK:
case ETH_IPGT:
case ETH_IPGR1:
case ETH_IPGR2:
case ETH_PACKETLEN:
case ETH_COLLCONF:
case ETH_TX_BD_NUM:
case ETH_CTRLMODER:
case ETH_MAC_ADDR0:
case ETH_MAC_ADDR1:
printf ("eth_write32: %s = 0x%08lx\n", eth_regname (addr),
(unsigned long int) value);
}
#endif
 
switch (addr)
{
case ETH_MODER:
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN) &&
TEST_FLAG (value, ETH_MODER, RXEN))
{
// Reset RX BD index
eth->rx_bd_index = eth->regs.tx_bd_num << 1;
// Clear TAP
{
/* Poll to see if there is data to read */
struct pollfd fds[1];
int n;
int nread;
fds[0].fd = eth->rtx_fd;
fds[0].events = POLLIN;
do {
n = poll (fds, 1, 0);
if (n < 0)
{
fprintf (stderr, "Warning: Poll in while emptying TAP: %s: ignored.\n",
strerror (errno));
}
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
{
nread = read (eth->rtx_fd, buf, ETH_MAXPL);
if (nread < 0)
{
fprintf (stderr,
"Warning: Read failed %s: ignored\n",
strerror (errno));
}
}
} while (n > 0);
}
/* Enabling receive, flush any oustanding input (TAP only), reset
the BDs and schedule the Rx controller on the next clock
cycle. */
if (ETH_RTX_TAP == eth->rtx_type)
{
(void) eth_ignore_tap_packets (eth);
}
 
eth->rx_bd_index = eth->regs.tx_bd_num * 2;
SCHED_ADD (eth_controller_rx_clock, dat, 1);
}
else if (!TEST_FLAG (value, ETH_MODER, RXEN) &&
TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
{
/* Disabling Rx, so stop scheduling the Rx controller. */
SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
}
 
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
TEST_FLAG (value, ETH_MODER, TXEN))
{
/* Enabling transmit, reset the BD and schedule the Tx controller on
the next clock cycle. */
eth->tx_bd_index = 0;
SCHED_ADD (eth_controller_tx_clock, dat, 1);
}
else if (!TEST_FLAG (value, ETH_MODER, TXEN) &&
TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN))
SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
{
/* Disabling Tx, so stop scheduling the Tx controller. */
SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
}
 
eth->regs.moder = value;
/* Reset the interface if so requested. */
if (TEST_FLAG (value, ETH_MODER, RST))
{
eth_reset (dat);
}
 
if (TEST_FLAG (value, ETH_MODER, RST))
eth_reset (dat);
return;
eth->regs.moder = value; /* Update the register */
break;
 
case ETH_INT_SOURCE:
#if ETH_DEBUG
printf("eth_write32: INT_SOURCE 0x%x\n",value);
#endif
eth->regs.int_source &= ~value;
// Clear IRQ line if all interrupt sources have been dealt with
/* Clear IRQ line if all interrupt sources have been dealt with
 
@todo Is this really right? */
if (!(eth->regs.int_source & eth->regs.int_mask) && eth->int_line_stat)
{
clear_interrupt (eth->mac_int);
eth->int_line_stat = 0;
}
return;
break;
 
case ETH_INT_MASK:
#if ETH_DEBUG
printf("eth_write32: INT_MASK 0x%x\n",value);
#endif
eth->regs.int_mask = value;
 
/* If we enable interrupts, the core is not currently processing an
interrupt, and there is an interrupt pending, then report that
interrupt.
 
Otherwise clear down the interrupt.
 
@todo Is this really right. */
if ((eth->regs.int_source & eth->regs.int_mask) && !eth->int_line_stat)
report_interrupt (eth->mac_int);
else
if (eth->int_line_stat)
{
clear_interrupt (eth->mac_int);
eth->int_line_stat = 0;
}
return;
case ETH_IPGT:
eth->regs.ipgt = value;
return;
case ETH_IPGR1:
eth->regs.ipgr1 = value;
return;
case ETH_IPGR2:
eth->regs.ipgr2 = value;
return;
case ETH_PACKETLEN:
eth->regs.packetlen = value;
return;
case ETH_COLLCONF:
eth->regs.collconf = value;
return;
{
report_interrupt (eth->mac_int);
}
else if (eth->int_line_stat)
{
clear_interrupt (eth->mac_int);
eth->int_line_stat = 0;
}
break;
 
case ETH_IPGT: eth->regs.ipgt = value; break;
case ETH_IPGR1: eth->regs.ipgr1 = value; break;
case ETH_IPGR2: eth->regs.ipgr2 = value; break;
case ETH_PACKETLEN: eth->regs.packetlen = value; break;
case ETH_COLLCONF: eth->regs.collconf = value; break;
 
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;
return;
case ETH_CTRLMODER:
eth->regs.controlmoder = value;
return;
case ETH_MIIMODER:
eth->regs.miimoder = value;
return;
eth->rx_bd_index = eth->regs.tx_bd_num * 2;
break;
 
case ETH_CTRLMODER: eth->regs.controlmoder = value; break;
case ETH_MIIMODER: eth->regs.miimoder = value; break;
 
case ETH_MIICOMMAND:
eth->regs.miicommand = value;
/* Perform MIIM transaction, if required */
eth_miim_trans (eth);
return;
case ETH_MIIADDRESS:
eth->regs.miiaddress = value;
return;
case ETH_MIITX_DATA:
eth->regs.miitx_data = value;
return;
case ETH_MIIRX_DATA:
/* Register is R/O
eth->regs.miirx_data = value;
*/
return;
case ETH_MIISTATUS:
/* Register is R/O
eth->regs.miistatus = value;
*/
return;
break;
 
case ETH_MIIADDRESS: eth->regs.miiaddress = value; break;
case ETH_MIITX_DATA: eth->regs.miitx_data = value; break;
case ETH_MIIRX_DATA: /* Register is R/O */ break;
case ETH_MIISTATUS: /* Register is R/O */ break;
 
case ETH_MAC_ADDR0:
eth->mac_address[5] = value & 0xFF;
eth->mac_address[4] = (value >> 8) & 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;
break;
 
case ETH_MAC_ADDR1:
eth->mac_address[1] = value & 0xFF;
eth->mac_address[0] = (value >> 8) & 0xFF;
return;
case ETH_HASH0:
eth->regs.hash0 = value;
return;
case ETH_HASH1:
eth->regs.hash1 = value;
return;
eth->mac_address[1] = value & 0xFF;
eth->mac_address[0] = (value >> 8) & 0xFF;
break;
 
/*case ETH_DMA_RX_TX: eth_tx( eth, value ); return; */
}
case ETH_HASH0: eth->regs.hash0 = value; break;
case ETH_HASH1: eth->regs.hash1 = value; break;
 
if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
{
eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
return;
default:
if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
{
eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
}
else
{
fprintf (stderr,
"Warning: eth_write32( 0x%" PRIxADDR " ): Illegal address\n",
addr + eth->baseaddr);
}
break;
}
} /* eth_write32 () */
 
PRINTF ("eth_write32( 0x%" PRIxADDR " ): Illegal address\n",
addr + eth->baseaddr);
return;
}
 
/* ========================================================================= */
 
 
/* ========================================================================= */
 
 
 
/* ========================================================================= */
 
/*-----------------------------------------------[ Ethernet configuration ]---*/
 
 
/*---------------------------------------------------------------------------*/
/*!Enable or disable the Ethernet interface
 
1620,26 → 1762,68
} /* eth_tap_dev() */
 
 
/*---------------------------------------------------------------------------*/
/*!Set the PHY address
 
Used to identify different physical interfaces (important for MII).
 
@param[in] val The value to use.
@param[in] dat The config data structure */
/*---------------------------------------------------------------------------*/
static void
eth_vapi_id (union param_val val,
eth_phy_addr (union param_val val,
void *dat)
{
struct eth_device *eth = dat;
eth->phy_addr = val.int_val & ETH_MIIADDR_FIAD_MASK;
 
} /* eth_phy_addr () */
 
 
/*---------------------------------------------------------------------------*/
/*!Enable or disable a dummy CRC
 
The MAC should not report anything about the CRC back to the core. However
the hardware implementation of the OpenRISC MAC does, and the Linux drivers
have been written to expect the value (which they ignore).
 
Setting this parameter causes a dummy CRC to be added. For consistency with
the hardware, its default setting is TRUE.
 
@param[in] val The value to use
@param[in] dat The config data structure */
/*---------------------------------------------------------------------------*/
static void
eth_dummy_crc (union param_val val,
void *dat)
{
struct eth_device *eth = dat;
eth->base_vapi_id = val.int_val;
}
 
eth->dummy_crc = val.int_val;
 
} /* eth_dummy_crc() */
 
 
/*---------------------------------------------------------------------------*/
/*!Set the VAPI id
 
Used for remote testing of the interface.
 
@param[in] val The value to use.
@param[in] dat The config data structure */
/*---------------------------------------------------------------------------*/
static void
eth_phy_addr (union param_val val,
void *dat)
eth_vapi_id (union param_val val,
void *dat)
{
struct eth_device *eth = dat;
eth->phy_addr = val.int_val & ETH_MIIADDR_FIAD_MASK;
}
eth->base_vapi_id = val.int_val;
 
} /* eth_vapi_id () */
 
 
/*---------------------------------------------------------------------------*/
/*!Initialize a new Ethernet configuration
/*!Start the initialization of a new Ethernet configuration
 
ALL parameters are set explicitly to default values. */
/*---------------------------------------------------------------------------*/
1664,16 → 1848,24
new->rtx_type = ETH_RTX_FILE;
new->rx_channel = 0;
new->tx_channel = 0;
new->rtx_fd = 0;
new->rtx_fd = -1;
new->rxfile = strdup ("eth_rx");
new->txfile = strdup ("eth_tx");
new->tap_dev = strdup ("");
new->phy_addr = 0;
new->dummy_crc = 1;
new->base_vapi_id = 0;
new->phy_addr = 0;
 
return new;
}
 
} /* eth_sec_start () */
 
 
/*---------------------------------------------------------------------------*/
/*!Complete the initialization of a new Ethernet configuration
 
ALL parameters are set explicitly to default values. */
/*---------------------------------------------------------------------------*/
static void
eth_sec_end (void *dat)
{
1702,9 → 1894,10
reg_mem_area (eth->baseaddr, ETH_ADDR_SPACE, 0, &ops);
reg_sim_stat (eth_status, dat);
reg_sim_reset (eth_reset, dat);
}
 
} /* eth_sec_end () */
 
 
/*---------------------------------------------------------------------------*/
/*!Register a new Ethernet configuration */
/*---------------------------------------------------------------------------*/
1724,8 → 1917,8
reg_config_param (sec, "rxfile", PARAMT_STR, eth_rxfile);
reg_config_param (sec, "txfile", PARAMT_STR, eth_txfile);
reg_config_param (sec, "tap_dev", PARAMT_STR, eth_tap_dev);
reg_config_param (sec, "phy_addr", PARAMT_INT, eth_phy_addr);
reg_config_param (sec, "dummy_crc", PARAMT_INT, eth_dummy_crc);
reg_config_param (sec, "vapi_id", PARAMT_INT, eth_vapi_id);
reg_config_param (sec, "phy_addr", PARAMT_INT, eth_phy_addr);
 
} /* reg_ethernet_sec() */
 

powered by: WebSVN 2.1.0

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