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/rtos/ecos-2.0/packages/devs/eth/mips
    from Rev 27 to Rev 174
    Reverse comparison

Rev 27 → Rev 174

/atlas/v2_0/cdl/atlas_eth_drivers.cdl
0,0 → 1,102
# ====================================================================
#
# atlas_eth_drivers.cdl
#
# Ethernet drivers - platform dependent support for MIPS Atlas
# board using a Philips SAA9730 IO chip.
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): msalter
# Original data: msalter
# Contributors:
# Date: 2000-12-04
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_DEVS_ETH_MIPS_ATLAS {
display "MIPS Atlas ethernet driver"
 
parent CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_HAL_MIPS_ATLAS
 
implements CYGHWR_NET_DRIVERS
implements CYGHWR_NET_DRIVER_ETH0
include_dir .
include_files ; # none _exported_ whatsoever
description "Ethernet driver for MIPS Atlas boards w/ SAA9730."
compile -library=libextras.a if_atlas.c if_buffers.S
 
cdl_component CYGSEM_MIPS_ATLAS_SET_ESA {
display "Set the ethernet station address"
flavor bool
default_value 0
description "Enabling this option will allow the ethernet
station address to be forced to the value set by the
configuration. This may be required if the hardware does
not include a serial EEPROM for the ESA."
 
cdl_option CYGDAT_MIPS_ATLAS_ESA {
display "The ethernet station address"
flavor data
default_value {"{0x00, 0xd0, 0xa0, 0x00, 0x00, 0x10}"}
description "The ethernet station address"
}
}
 
cdl_component CYGPKG_DEVS_ETH_MIPS_ATLAS_OPTIONS {
display "MIPS Atlas ethernet driver build options"
flavor none
no_define
 
cdl_option CYGPKG_DEVS_ETH_MIPS_ATLAS_CFLAGS_ADD {
display "Additional compiler flags"
flavor data
no_define
default_value { "-D_KERNEL -D__ECOS" }
description "
This option modifies the set of compiler flags for
building the MIPS Atlas ethernet driver package.
These flags are used in addition
to the set of global flags."
}
}
}
 
/atlas/v2_0/ChangeLog
0,0 → 1,82
2003-03-21 Nick Garnett <nickg@balti.calivar.com>
 
* src/saa9730.h:
* src/if_atlas.c:
Many small changes to make this driver work correctly in eCos.
 
2003-03-13 Nick Garnett <nickg@balti.calivar.com>
 
* cdl/atlas_eth_drivers.cdl:
Changed CYGPKG_DEVS_ETH_ARM_ATLAS_OPTIONS to
CYGPKG_DEVS_ETH_MIPS_ATLAS_OPTIONS.
 
* src/if_atlas.c (atlas_saa9730_init): ifdeffed out bogus code to
set MAC address in non-redboot configuration just to make it
compile. Note that there are other problems with this driver in
eCos.
 
2002-06-14 Gary Thomas <gary@chez-thomas.org>
 
* src/if_atlas.c:
Need to include <pkgconf/io_eth_drivers.h> for proper configuration
of stand-alone (polled) vs. system (interrupt driven) mode.
 
2001-10-18 Jonathan Larmour <jlarmour@redhat.com>
 
* src/if_atlas.c: net_debug is no longer used.
 
2001-10-05 Jesper Skov <jskov@redhat.com>
 
* src/if_atlas.c: Use new HAL endian conversion macros.
 
* src/saa9730.h: Deleted endian conversion macros.
 
2001-02-15 Nick Garnett <nickg@cygnus.co.uk>
 
* src/saa9730.h:
* src/if_atlas.c:
Added support for getting RX interrupts. This is solely for the
purposes of doing Ctrl-C processing in RedBoot, more work would be
needed to get full eCos driver support going.
 
2001-01-30 Gary Thomas <gthomas@redhat.com>
 
* src/if_atlas.c: New RedBoot config data layout.
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================
 
/atlas/v2_0/src/if_atlas.c
0,0 → 1,1054
//==========================================================================
//
// dev/if_atlas.c
//
// Ethernet device driver for MIPS Atlas using Philips SAA9730
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Nick Garnett <nickg@calivar.com>
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting the copyright
// holders.
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD or other sources,
// and are covered by the appropriate copyright disclaimers included herein.
//
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): msalter
// Contributors: msalter, nickg
// Date: 2000-12-06
// Purpose:
// Description: hardware driver for SAA9730 ethernet
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
// Ethernet device driver for MIPS Atlas
// Based on SAA9730
 
#include <pkgconf/system.h>
#include <pkgconf/devs_eth_mips_atlas.h>
#include <pkgconf/io_eth_drivers.h>
 
#ifdef CYGPKG_NET
#include <pkgconf/net.h>
#include <cyg/kernel/kapi.h>
#endif
#include <cyg/infra/cyg_type.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_endian.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/hal_cache.h>
#include <cyg/hal/hal_if.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/drv_api.h>
#include <cyg/io/eth/netdev.h>
#include <cyg/io/eth/eth_drv.h>
 
#ifdef CYGPKG_IO_PCI
#include <cyg/io/pci.h>
// So we can check the validity of the PCI window against the MLTs opinion,
// and thereby what the malloc heap consumes willy-nilly:
#include CYGHWR_MEMORY_LAYOUT_H
#else
#error "Need PCI package here"
#endif
 
#ifndef CYGSEM_MIPS_ATLAS_SET_ESA
#ifdef CYGPKG_REDBOOT
#include <pkgconf/redboot.h>
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
#include <redboot.h>
#include <flash_config.h>
RedBoot_config_option("Network hardware address [MAC]",
atlas_esa,
ALWAYS_ENABLED, true,
CONFIG_ESA, 0
);
#endif
#endif
#endif
 
// SAA9730 LAN definitions
#include "saa9730.h"
 
// Exported statistics and the like
#include <cyg/io/eth/eth_drv_stats.h>
 
#ifndef CYGPKG_REDBOOT
//#define DEBUG
#endif
#define db_printf diag_printf
 
#define ETHER_ADDR_LEN 6
 
static unsigned poll_count = 0; // for bug workaround
static void __tx_poll(struct eth_drv_sc *sc);
 
struct saa9730_priv_data {
int active;
cyg_uint32 vector;
cyg_handle_t interrupt_handle;
cyg_interrupt interrupt_object;
cyg_uint32 devid; // PCI device id
cyg_uint32 base; // PCI memory map base
void *ndp;
 
// index of next RX buffer
cyg_uint8 next_rx_bindex;
 
// index of next packet within RX buffer
cyg_uint8 next_rx_pindex;
 
// index of next TX buffer
cyg_uint8 next_tx_bindex;
 
// index of next packet within TX buffer
cyg_uint8 next_tx_pindex;
 
cyg_uint32 *tx_buffer[SAA9730_BUFFERS][SAA9730_TXPKTS_PER_BUFFER];
cyg_uint32 *rx_buffer[SAA9730_BUFFERS][SAA9730_RXPKTS_PER_BUFFER];
 
int tx_busy;
unsigned long tx_key[SAA9730_BUFFERS][SAA9730_TXPKTS_PER_BUFFER];
int tx_used[SAA9730_BUFFERS];
 
} saa9730_priv_data;
 
ETH_DRV_SC(atlas_sc,
&saa9730_priv_data, // Driver specific data
"eth0", // Name for this interface
saa9730_start,
saa9730_stop,
saa9730_control,
saa9730_can_send,
saa9730_send,
saa9730_recv,
saa9730_deliver, // "pseudoDSR" called from fast net thread
saa9730_poll,
saa9730_int_vector);
 
NETDEVTAB_ENTRY(atlas_netdev,
"atlas",
atlas_saa9730_init,
&atlas_sc);
 
#ifdef CYGSEM_MIPS_ATLAS_SET_ESA
static unsigned char enaddr[] = CYGDAT_MIPS_ATLAS_ESA;
#else
static unsigned char enaddr[ETHER_ADDR_LEN];
#endif
 
static void saa9730_poll(struct eth_drv_sc *sc);
 
// This ISR is called when the ethernet interrupt occurs
static int
saa9730_isr(cyg_vector_t vector, cyg_addrword_t data)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)data;
unsigned long __base = spd->base;
 
#ifndef CYGPKG_REDBOOT
SAA9730_EVM_IER_SW &= ~(SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
SAA9730_EVM_ISR = SAA9730_EVM_LAN_INT;
cyg_drv_interrupt_mask(vector);
#endif
#ifdef DEBUG
db_printf("saa9730_isr\n");
#endif
return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR
}
 
#ifndef CYGPKG_REDBOOT
static
void saa9730_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)data;
struct cyg_netdevtab_entry *ndp = (struct cyg_netdevtab_entry *)(spd->ndp);
struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);
#ifdef DEBUG
db_printf("saa9730_dsr\n");
#endif
 
eth_drv_dsr(vector, count, (cyg_addrword_t)sc);
}
#endif
 
static int
saa9730_int_vector(struct eth_drv_sc *sc)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
 
return spd->vector;
}
 
static void
__init_buffers(struct saa9730_priv_data *spd)
{
extern char cyg_io_atlas_2kbuffers[];
cyg_uint32 *bufp = (cyg_uint32 *)CYGARC_UNCACHED_ADDRESS((unsigned)cyg_io_atlas_2kbuffers);
int i, j;
 
for (i = 0; i < SAA9730_BUFFERS; i++) {
for (j = 0; j < SAA9730_RXPKTS_PER_BUFFER; j++) {
memset(bufp, 0, 2048);
spd->rx_buffer[i][j] = bufp;
bufp += SAA9730_PACKET_SIZE/sizeof(*bufp);
}
}
for (i = 0; i < SAA9730_BUFFERS; i++) {
for (j = 0; j < SAA9730_TXPKTS_PER_BUFFER; j++) {
memset(bufp, 0, 2048);
*bufp = CYG_CPU_TO_LE32(TX_EMPTY);
spd->tx_buffer[i][j] = bufp;
bufp += SAA9730_PACKET_SIZE/sizeof(*bufp);
}
}
 
spd->next_rx_pindex = 0;
spd->next_rx_bindex = 0;
spd->next_tx_pindex = 0;
spd->next_tx_bindex = 0;
}
 
static void
__select_buffer(struct saa9730_priv_data *spd, int buf_nr)
{
unsigned long __base = spd->base;
cyg_uint32 *p;
int i;
 
// Enable RX buffer
for (i = 0; i < SAA9730_RXPKTS_PER_BUFFER; i++) {
p = spd->rx_buffer[buf_nr][i];
*p = CYG_CPU_TO_LE32(RX_READY);
}
 
if (buf_nr)
SAA9730_OK2USE |= SAA9730_OK2USE_RXB;
else
SAA9730_OK2USE |= SAA9730_OK2USE_RXA;
 
}
 
static void
__init_cam(struct saa9730_priv_data *spd)
{
unsigned long __base = spd->base;
cyg_uint32 abuf[3]; // room for 2 copies of mac address
int i,j,cam_offset;
 
// make 2 contiguous copies of mac addr
memcpy((char *)abuf, enaddr, 6);
memcpy((char *)abuf + 6, enaddr, 6);
 
// Setting up the address compare regs is weird because you have
// to access by word addresses even though addresses don't have
// an integral number of words.
cam_offset = 0;
for (i = 0; i < SAA9730_CAM_ENTRIES; i++) {
for (j = 0; j < 3; j++, cam_offset++) {
SAA9730_CAMADR = cam_offset;
SAA9730_CAMDAT = CYG_CPU_TO_BE32(abuf[j]);
}
}
}
 
static void
__stop_dma(struct saa9730_priv_data *spd)
{
unsigned long __base = spd->base;
 
// Stop DMA
SAA9730_DMACTL &= ~(SAA9730_DMACTL_ENRX | SAA9730_DMACTL_ENTX);
 
// Stop tx/rx
SAA9730_TXCTL &= ~SAA9730_TXCTL_ENTX;
SAA9730_RXCTL &= ~SAA9730_RXCTL_ENRX;
 
// Set DMA and MAC reset bits
SAA9730_DMATST |= SAA9730_DMATST_RESET;
SAA9730_MACCTL |= SAA9730_MACCTL_RESET;
}
 
 
static void
__init_dma(struct saa9730_priv_data *spd)
{
unsigned long __base = spd->base;
 
__stop_dma(spd);
 
// reset DMA engine
SAA9730_DMATST |= SAA9730_DMATST_RESET;
 
// setup buffers
SAA9730_TXBUFA = CYGARC_PHYSICAL_ADDRESS((unsigned long)spd->tx_buffer[0][0]);
SAA9730_TXBUFB = CYGARC_PHYSICAL_ADDRESS((unsigned long)spd->tx_buffer[1][0]);
SAA9730_RXBUFA = CYGARC_PHYSICAL_ADDRESS((unsigned long)spd->rx_buffer[0][0]);
SAA9730_RXBUFB = CYGARC_PHYSICAL_ADDRESS((unsigned long)spd->rx_buffer[1][0]);
 
SAA9730_PKTCNT = ((SAA9730_TXPKTS_PER_BUFFER << 24) |
(SAA9730_TXPKTS_PER_BUFFER << 16) |
(SAA9730_RXPKTS_PER_BUFFER << 8) |
(SAA9730_RXPKTS_PER_BUFFER << 0));
 
SAA9730_OK2USE = 0;
 
__select_buffer(spd, 0);
 
// initialize DMA control register
SAA9730_DMACTL = SAA9730_DMACTL_BLKINT |
SAA9730_DMACTL_MAXXFER_ANY |
SAA9730_DMACTL_ENDIAN_LITTLE;
 
SAA9730_DMACTL |= SAA9730_DMACTL_RXINT;
SAA9730_DMACTL |= (1<<SAA9730_DMACTL_RXINTCNT_SHIFT);
SAA9730_DMACTL &= ~SAA9730_DMACTL_BLKINT;
 
#ifndef CYGPKG_REDBOOT
SAA9730_DMACTL |= SAA9730_DMACTL_TXINT;
#endif
SAA9730_TIMOUT = 200;
 
// accept broadcast packets */
SAA9730_CAMCTL = SAA9730_CAMCTL_BROADCAST |
SAA9730_CAMCTL_COMPARE;
 
SAA9730_TXCTL = 0;
SAA9730_RXCTL |= SAA9730_RXCTL_STRIPCRC;
 
SAA9730_CAMENA = 1;
 
}
 
static void
__check_mii(struct saa9730_priv_data *spd)
{
unsigned long __base = spd->base;
cyg_uint32 opmode;
 
#ifdef DEBUG
db_printf("__check_mii\n");
#endif
// spin till station is not busy
while (SAA9730_MDCTL & SAA9730_MDCTL_BUSY)
;
 
// set PHY address = 'STATUS'
SAA9730_MDCTL = SAA9730_MDCTL_BUSY |
(PHY_ADDRESS << SAA9730_MDCTL_PHY_SHIFT) |
PHY_STATUS;
 
// spin till station is not busy
while (SAA9730_MDCTL & SAA9730_MDCTL_BUSY)
;
 
hal_delay_us(1000);
 
// check the link status
if (SAA9730_MDDATA & PHY_STATUS_LINK_UP) {
 
SAA9730_MDCTL = SAA9730_MDCTL_BUSY |
(PHY_ADDRESS << SAA9730_MDCTL_PHY_SHIFT) |
PHY_REG31;
 
// spin till station is not busy
while (SAA9730_MDCTL & SAA9730_MDCTL_BUSY)
;
 
hal_delay_us(1000);
 
opmode = (SAA9730_MDDATA & PHY_REG31_OPMODE_MSK) >> PHY_REG31_OPMODE_SHIFT;
 
#ifdef DEBUG
db_printf("MII mode %d\n", opmode);
#endif
 
if ((opmode == OPMODE_10BASET_FULLDUPLEX) ||
(opmode == OPMODE_100BASEX_FULLDUPLEX))
SAA9730_MACCTL = SAA9730_MACCTL_CONMODE_FORCE_MII | SAA9730_MACCTL_FULLDUP;
else
SAA9730_MACCTL = SAA9730_MACCTL_CONMODE_FORCE_MII;
}
#ifdef DEBUG
else
db_printf("Link is down\n");
#endif
}
 
 
static void
saa9730_reset(struct saa9730_priv_data *spd)
{
unsigned long __base = spd->base;
 
__init_buffers(spd);
 
__base = spd->base;
// Stop DMA
SAA9730_DMACTL &= ~(SAA9730_DMACTL_ENRX | SAA9730_DMACTL_ENTX);
 
// Stop tx/rx
SAA9730_TXCTL &= ~SAA9730_TXCTL_ENTX;
SAA9730_RXCTL &= ~SAA9730_RXCTL_ENRX;
 
// Set DMA and MAC reset bits
SAA9730_DMATST |= SAA9730_DMATST_RESET;
SAA9730_MACCTL |= SAA9730_MACCTL_RESET;
 
__init_cam(spd);
__init_dma(spd);
__check_mii(spd);
 
spd->tx_busy = 0;
}
 
 
static bool
atlas_saa9730_init(struct cyg_netdevtab_entry *tab)
{
static int initialized = 0; // only probe PCI et al *once*
struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
 
#ifdef DEBUG
db_printf("atlas_saa9730_init\n");
#endif
 
if (0 == initialized) {
cyg_pci_device_id devid;
cyg_pci_device dev_info;
 
cyg_pci_init();
 
devid = CYG_PCI_NULL_DEVID;
 
if (cyg_pci_find_device(CYG_PCI_VENDOR_PHILIPS, 0x9730, &devid) ) {
 
spd->devid = devid;
 
cyg_pci_get_device_info(devid, &dev_info);
 
if (!cyg_pci_configure_device(&dev_info)) {
#ifdef DEBUG
db_printf("Failed to configure eth device\n");
#endif
return false;
}
 
// Philips SAA9730 implements only one function memory mapped
// into a single contigous memory region.
//
// According to spec. the BAR#1 is to be used for memory mapped IO.
spd->base = dev_info.base_map[1];
 
// FIXME! All IO units share an interrupt
spd->vector = CYGNUM_HAL_INTERRUPT_INTB;
 
// Setup timing stuff
cyg_hal_plf_pci_cfg_write_byte(CYG_PCI_DEV_GET_BUS(devid),
CYG_PCI_DEV_GET_DEVFN(devid),
CYG_PCI_CFG_LATENCY_TIMER, 0x20);
cyg_hal_plf_pci_cfg_write_byte(CYG_PCI_DEV_GET_BUS(devid),
CYG_PCI_DEV_GET_DEVFN(devid),
CYG_PCI_CFG_MIN_GNT, 9);
cyg_hal_plf_pci_cfg_write_byte(CYG_PCI_DEV_GET_BUS(devid),
CYG_PCI_DEV_GET_DEVFN(devid),
CYG_PCI_CFG_MAX_LAT, 24);
#ifdef DEBUG
db_printf("eth0 found: bus[%d] dev[%d] base[%x] vector[%d]\n",
CYG_PCI_DEV_GET_BUS(devid),
CYG_PCI_DEV_GET_DEV(CYG_PCI_DEV_GET_DEVFN(devid)),
spd->base, spd->vector);
#endif
 
spd->ndp = tab;
#ifndef CYGPKG_REDBOOT
cyg_drv_interrupt_create(
spd->vector,
0, // Priority - unused
(CYG_ADDRWORD)spd, // Data item passed to ISR & DSR
saa9730_isr, // ISR
saa9730_dsr, // DSR
&spd->interrupt_handle, // handle to intr obj
&spd->interrupt_object ); // space for int obj
 
cyg_drv_interrupt_attach(spd->interrupt_handle);
cyg_drv_interrupt_acknowledge(spd->vector);
cyg_drv_interrupt_unmask(spd->vector);
#endif
{
// When in Redboot we want to get RX interrupts. These
// will be picked up by the default interrupt handler and
// checked for ^C.
unsigned long __base = spd->base;
SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
SAA9730_EVM_IER |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
SAA9730_EVM_ISR |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
}
 
#ifdef DEBUG
db_printf(" **** Device enabled for I/O and Memory and Bus Master\n");
#endif
 
} else {
#ifdef DEBUG
db_printf("eth0 not found\n");
#endif
}
 
saa9730_stop(sc);
spd->active = 0;
 
initialized = 1;
}
 
// Fetch hardware address
#if defined(CYGPKG_REDBOOT) && \
defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \
!defined(CYGSEM_MIPS_ATLAS_SET_ESA)
flash_get_config("atlas_esa", enaddr, CONFIG_ESA);
#else
#define CONFIG_ESA 6
CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET,
"atlas_esa", enaddr, CONFIG_ESA );
#ifdef DEBUG
db_printf("ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
enaddr[0],enaddr[1],enaddr[2],enaddr[3],enaddr[4],enaddr[5]);
#endif
#endif
 
saa9730_reset(spd);
 
// Initialize upper level driver
(sc->funs->eth_drv->init)(sc, enaddr);
 
return true;
}
 
static void
saa9730_stop(struct eth_drv_sc *sc)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
unsigned long __base = spd->base;
 
// Stop DMA
SAA9730_DMACTL &= ~(SAA9730_DMACTL_ENRX | SAA9730_DMACTL_ENTX);
 
// Stop tx/rx
SAA9730_TXCTL &= ~SAA9730_TXCTL_ENTX;
SAA9730_RXCTL &= ~SAA9730_RXCTL_ENRX;
 
// Set DMA and MAC reset bits
SAA9730_DMATST |= SAA9730_DMATST_RESET;
SAA9730_MACCTL |= SAA9730_MACCTL_RESET;
 
spd->active = 0;
}
 
static void
__do_start(struct saa9730_priv_data *spd)
{
unsigned long __base = spd->base;
int i;
 
spd->active = 1;
spd->tx_busy = 0;
 
for (i = 0; i < SAA9730_BUFFERS; i++)
spd->tx_used[i] = 0;
 
// for tx, turn on MAC first
SAA9730_TXCTL |= SAA9730_TXCTL_ENTX;
SAA9730_DMACTL |= SAA9730_DMACTL_ENTX;
 
// for rx, turn on DMA first
SAA9730_DMACTL |= SAA9730_DMACTL_ENRX;
SAA9730_RXCTL |= SAA9730_RXCTL_ENRX;
 
__select_buffer(spd, spd->next_rx_bindex);
}
 
//
// This function is called to "start up" the interface. It may be called
// multiple times, even when the hardware is already running. It will be
// called whenever something "hardware oriented" changes and should leave
// the hardware ready to send/receive packets.
//
static void
saa9730_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
 
if (spd->active)
saa9730_stop(sc);
 
__do_start(spd);
}
 
//
// This routine is called to perform special "control" opertions
//
static int
saa9730_control(struct eth_drv_sc *sc, unsigned long key,
void *data, int data_length)
{
switch (key) {
case ETH_DRV_SET_MAC_ADDRESS:
return 0;
break;
default:
return 1;
break;
}
}
 
//
// This routine is called to see if it is possible to send another packet.
// It will return non-zero if a transmit is possible, zero otherwise.
//
static int
saa9730_can_send(struct eth_drv_sc *sc)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
unsigned long __base = spd->base;
 
__tx_poll(sc);
 
if (spd->next_tx_bindex == 0 && (SAA9730_OK2USE & SAA9730_OK2USE_TXA))
return 0;
 
if (spd->next_tx_bindex == 1 && (SAA9730_OK2USE & SAA9730_OK2USE_TXB))
return 0;
 
return 1;
}
 
 
static int tx_poll_count;
 
//
// This routine is called to send data to the hardware.
static void
saa9730_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
int total_len, unsigned long key)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
unsigned long __base = spd->base;
int bindex, pindex;
cyg_uint32 pktlen = total_len;
cyg_uint8 *pktdata, *to_p;
volatile cyg_uint32 *pktstat ;
struct eth_drv_sg *last_sg;
 
#ifdef DEBUG
db_printf("saa9730_send: %d sg's, %d bytes, KEY %x\n",
sg_len, total_len, key );
#endif
 
if (!spd->active)
return;
 
bindex = spd->next_tx_bindex;
pindex = spd->next_tx_pindex;
 
spd->next_tx_pindex++;
if (spd->next_tx_pindex >= SAA9730_TXPKTS_PER_BUFFER) {
spd->next_tx_pindex = 0;
spd->next_tx_bindex ^= 1;
}
 
pktstat = spd->tx_buffer[bindex][pindex];
if (bindex == 0 && (SAA9730_OK2USE & SAA9730_OK2USE_TXA))
return;
 
if (bindex == 1 && (SAA9730_OK2USE & SAA9730_OK2USE_TXB))
return;
 
spd->tx_key[bindex][pindex] = key;
spd->tx_used[bindex] += 1;
 
pktdata = (cyg_uint8 *)((unsigned)pktstat + 4);
 
// Copy from the sglist into the tx buffer
to_p = pktdata;
 
for (last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++) {
cyg_uint8 *from_p;
int l;
from_p = (cyg_uint8 *)(sg_list->buf);
l = sg_list->len;
 
if (l > total_len)
l = total_len;
 
memcpy((unsigned char *)to_p, from_p, l);
to_p += l;
total_len -= l;
 
if (total_len < 0)
break; // Should exit via sg_last normally
}
 
// pad to minimum size
if (pktlen < SAA9730_MIN_PACKET_SIZE) {
memset(to_p, 0, SAA9730_MIN_PACKET_SIZE-pktlen);
pktlen = SAA9730_MIN_PACKET_SIZE;
}
 
// Set transmit status WORD for hardware (LAN-DMA-ENGINE)
*pktstat = CYG_CPU_TO_LE32(TX_READY | pktlen);
 
// start hardware
if (bindex == 0)
SAA9730_OK2USE |= SAA9730_OK2USE_TXA;
else
SAA9730_OK2USE |= SAA9730_OK2USE_TXB;
 
if (!spd->tx_busy) {
tx_poll_count = 0;
spd->tx_busy = bindex + 1;
}
}
 
 
static void
__check_rxstate(struct saa9730_priv_data *spd)
{
unsigned long __base = spd->base;
cyg_uint32 status, flag, size;
cyg_uint32 *pkt;
int i, j;
 
#ifdef DEBUG
db_printf("__check_rxstate\n");
#endif
 
#ifdef CYGPKG_REDBOOT
// Clear SAA9730 LAN interrupt and re-enable interrupts.
SAA9730_EVM_ISR = SAA9730_EVM_LAN_INT;
SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
#endif
if ((SAA9730_DBGRXS & SAA9730_DBGRXS_RXDII_MASK) == SAA9730_DBGRXS_RXDII_ERROR) {
// re-init driver and controller
#ifdef DEBUG
db_printf("DBGRXS: reset\n");
#endif
saa9730_reset(spd);
__do_start(spd);
return;
}
 
// Check RX packet status
for (i = 0; i < SAA9730_BUFFERS; i++) {
for (j = 1; j < SAA9730_RXPKTS_PER_BUFFER; j++) {
pkt = spd->rx_buffer[i][j];
status = CYG_LE32_TO_CPU(*pkt);
size = status & RXPACKET_STATUS_SIZE_MASK;
flag = status & RXPACKET_STATUS_FLAG_MASK;
if (flag == RX_INVALID_STAT || size > 1514 || *(pkt - 1)) {
// re-init driver and controller
#ifdef DEBUG
db_printf("rxpkt: reset\n");
#endif
saa9730_reset(spd);
__do_start(spd);
return;
}
}
}
}
 
 
static void
__tx_poll(struct eth_drv_sc *sc)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
int bindex, pindex;
volatile cyg_uint32 *pktstat;
cyg_uint32 status;
 
if (!spd->tx_busy)
return;
 
bindex = spd->tx_busy - 1;
pindex = spd->tx_used[bindex] - 1; // watch last pkt in buffer
 
pktstat = spd->tx_buffer[bindex][pindex];
 
status = CYG_LE32_TO_CPU(*pktstat);
if ((status & TXPACKET_STATUS_FLAG_MASK) != TX_HWDONE) {
 
hal_delay_us(1000);
 
if (++tx_poll_count > 1000) {
// reset
 
for (pindex = 0; pindex < spd->tx_used[bindex]; pindex++)
(sc->funs->eth_drv->tx_done)(sc, spd->tx_key[bindex][pindex], 1);
 
bindex ^= 1;
 
for (pindex = 0; pindex < spd->tx_used[bindex]; pindex++)
(sc->funs->eth_drv->tx_done)(sc, spd->tx_key[bindex][pindex], 1);
 
saa9730_reset(spd);
__do_start(spd);
}
return;
}
 
for (pindex = 0; pindex < spd->tx_used[bindex]; pindex++) {
/* Check for error. */
pktstat = spd->tx_buffer[bindex][pindex];
status = CYG_LE32_TO_CPU(*pktstat);
 
if (status & TXPACKET_STATUS_ERROR) {
if (status & TXPACKET_STATUS_EXDEFER)
db_printf("tx deferred\n");
 
if (status & TXPACKET_STATUS_LATECOLLERR)
db_printf("tx late collision\n");
 
if (status & TXPACKET_STATUS_LOSTCARRIER)
db_printf("tx no carrier\n");
 
if (status & TXPACKET_STATUS_UNDERRUN)
db_printf("tx underrun\n");
 
if (status & TXPACKET_STATUS_SQERR)
db_printf("tx sq\n");
}
/* free the space */
*pktstat = CYG_CPU_TO_LE32(TX_EMPTY);
 
(sc->funs->eth_drv->tx_done)(sc, spd->tx_key[bindex][pindex], 1 /* status */);
}
 
tx_poll_count = 0;
spd->tx_used[bindex] = 0;
bindex ^= 1;
if (spd->tx_used[bindex])
spd->tx_busy = bindex + 1;
else
spd->tx_busy = 0;
}
 
 
static void
__rx_poll(struct eth_drv_sc *sc)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
int bindex, pindex, done;
volatile cyg_uint32 *pkt;
cyg_uint32 status, pktlen;
 
#ifdef DEBUG
db_printf("__rx_poll\n");
#endif
if (!spd->active)
return;
 
done = 0;
while (!done) {
// index of next packet buffer
bindex = spd->next_rx_bindex;
 
// index of next packet within buffer
pindex = spd->next_rx_pindex;
 
pkt = spd->rx_buffer[bindex][pindex];
 
// stop now if no more packets
if (((status = CYG_LE32_TO_CPU(*pkt)) & RXPACKET_STATUS_FLAG_MASK) == RX_READY)
break;
#ifdef DEBUG
db_printf("__rx_poll pkt %08x status %08x\n",pkt,status);
#endif
// if this is the first packet in a buffer, switch the SAA9730 to
// use the next buffer for subsequent incoming packets.
if (pindex == 0)
__select_buffer(spd, bindex == 0);
// check for good packet
if (status & RXPACKET_STATUS_GOOD) {
 
pktlen = status & RXPACKET_STATUS_SIZE_MASK ;
 
if (pktlen > 0) {
(sc->funs->eth_drv->recv)(sc, pktlen);
// done = 1;
}
}
#ifdef DEBUG
else
db_printf("rx bad: %08x %08x\n",pkt,status);
#endif
/* go to next packet in sequence */
spd->next_rx_pindex++;
if (spd->next_rx_pindex >= SAA9730_RXPKTS_PER_BUFFER) {
spd->next_rx_pindex = 0;
spd->next_rx_bindex++;
if (spd->next_rx_bindex >= SAA9730_BUFFERS)
spd->next_rx_bindex = 0;
}
}
 
if (((poll_count++) % 100) == 0)
__check_rxstate(spd);
}
 
 
static void
saa9730_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
volatile cyg_uint32 *pkt;
cyg_uint32 pktlen, status;
struct eth_drv_sg *last_sg;
 
if (!spd->active)
return;
 
pkt = spd->rx_buffer[spd->next_rx_bindex][spd->next_rx_pindex];
 
status = CYG_LE32_TO_CPU(*pkt);
if (status & RXPACKET_STATUS_GOOD) {
// packet is good
pktlen = status & RXPACKET_STATUS_SIZE_MASK;
 
if (pktlen > 0) {
int total_len;
cyg_uint8 *from_p;
 
// check we have memory to copy into; we would be called even if
// caller was out of memory in order to maintain our state.
if (0 == sg_len || 0 == sg_list)
return; // caller was out of mbufs
 
total_len = pktlen;
from_p = (cyg_uint8 *)((unsigned)pkt + 4);
 
for (last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++) {
cyg_uint8 *to_p;
int l;
to_p = (cyg_uint8 *)(sg_list->buf);
l = sg_list->len;
 
if (0 >= l || 0 == to_p)
return; // caller was out of mbufs
 
if (l > total_len)
l = total_len;
 
memcpy(to_p, (unsigned char *)from_p, l);
from_p += l;
total_len -= l;
}
}
}
}
 
static inline void
__do_deliver(struct eth_drv_sc *sc)
{
// First pass any rx data up the stack
__rx_poll(sc);
 
// Then scan for completed Txen and inform the stack
__tx_poll(sc);
}
 
static void
saa9730_poll(struct eth_drv_sc *sc)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
 
#ifndef CYGPKG_REDBOOT
cyg_drv_interrupt_mask(spd->vector);
#endif
 
(void)saa9730_isr(spd->vector, (cyg_addrword_t)spd);
 
__do_deliver(sc);
 
cyg_drv_interrupt_acknowledge(spd->vector);
 
#ifndef CYGPKG_REDBOOT
cyg_drv_interrupt_unmask(spd->vector);
#endif
}
 
 
// The deliver function (ex-DSR) handles the ethernet [logical] processing
static void
saa9730_deliver(struct eth_drv_sc *sc)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
unsigned long __base = spd->base;
 
if (spd->active)
__do_deliver(sc);
 
cyg_drv_interrupt_acknowledge(spd->vector);
 
#ifndef CYGPKG_REDBOOT
// Clear SAA9730 LAN interrupt and re-enable interrupts.
SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
cyg_drv_interrupt_unmask(spd->vector);
#endif
}
 
 
/atlas/v2_0/src/if_buffers.S
0,0 → 1,64
// #========================================================================
// #
// # if_buffers.S
// #
// # Declare a chunk of 4Kbyte aligned memory for use by bus-mastering
// # PCI ethernet device.
// #
// #========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
// #========================================================================
// ######DESCRIPTIONBEGIN####
// #
// # Author(s): msalter
// # Contributors: msalter
// # Date: 2000-11-03
// # Purpose:
// # Description: This file defines a chunk of 2Kbyte aligned memory for use
// # by bus-mastering PCI ethernet device.
// #
// #####DESCRIPTIONEND####
// #
// #========================================================================
 
#include "saa9730.h"
 
.bss
.p2align(11)
.globl cyg_io_atlas_2kbuffers
cyg_io_atlas_2kbuffers:
.rept (SAA9730_RXPKTS_PER_BUFFER + SAA9730_TXPKTS_PER_BUFFER) \
* SAA9730_BUFFERS * SAA9730_PACKET_SIZE
.byte 0
.endr
/atlas/v2_0/src/saa9730.h
0,0 → 1,364
#ifndef CYGONCE_DEVS_ETH_MIPS_ATLAS_SAA9730_H
#define CYGONCE_DEVS_ETH_MIPS_ATLAS_SAA9730_H
/*==========================================================================
//
// saa9730.h
// Philips SAA9730 IO Chip Ethernet Interface
//
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Nick Garnett <nickg@calivar.com>
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting the copyright
// holders.
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): msalter
// Contributors: msalter, nickg
// Date: 2000-12-09
// Description: Definitions for Philips SAA9730 Ethernet module.
//
//####DESCRIPTIONEND####
*/
 
// QS6612 PHY definitions
 
#define PHY_CONTROL 0
#define PHY_STATUS 1
#define PHY_REG31 31
 
#define PHY_CONTROL_RESET (1 << 15)
#define PHY_CONTROL_AUTO_NEG (1 << 12)
#define PHY_CONTROL_RESTART_AUTO_NEG (1 << 9)
 
#define PHY_STATUS_LINK_UP (1 << 2)
 
#define PHY_REG31_OPMODE_SHIFT 2
#define PHY_REG31_OPMODE_MSK (7 << PHY_REG31_OPMODE_SHIFT)
 
#define OPMODE_AUTONEGOTIATE 0
#define OPMODE_10BASET_HALFDUPLEX 1
#define OPMODE_100BASEX_HALFDUPLEX 2
#define OPMODE_REPEATER_MODE 3
#define OPMODE_UNDEFINED 4
#define OPMODE_10BASET_FULLDUPLEX 5
#define OPMODE_100BASEX_FULLDUPLEX 6
#define OPMODE_ISOLATE 7
 
#define QS6612_PHY_ADDRESS 0
#define PHY_ADDRESS QS6612_PHY_ADDRESS
 
// Number of 6-byte entries in the CAM
#define SAA9730_CAM_ENTRIES 10
 
// TX and RX packet size fixed at 2k bytes by hw
#define SAA9730_PACKET_SIZE 2048
 
// Number of TX buffers = number of RX buffers = 2,
// which is fixed according to HW requirements
#define SAA9730_BUFFERS 2
 
// Number of RX packets per RX buffer
#define SAA9730_RXPKTS_PER_BUFFER 2
 
// Number of TX packets per TX buffer
#define SAA9730_TXPKTS_PER_BUFFER 1
 
// Minimum packet size
#define SAA9730_MIN_PACKET_SIZE 60
 
// owner ship bit
#define SAA9730_BLOCK_OWNED_BY_SYSTEM 0
#define SAA9730_BLOCK_OWNED_BY_HARDWARE 1
 
// Default Rcv interrupt count
#define SAA9730_DEFAULT_RCV_INTERRUPT_CNT 4
 
// Default maxium transmit retry
#define SAA9730_DEFAULT_MAX_TXM_RETRY 16
 
// Default time out value
#define SAA9730_DEFAULT_TIME_OUT_CNT 200
 
// MAX map registers
#define SAA9730__MAX_MAP_REGISTERS 64
 
// Defines used by Interrupt code
#define SAA9730_DMA_PACKET_SIZE 2048
#define SAA9730_VALID_PACKET 0xC0000000
#define SAA9730_FRAME_TYPELEN_OFFSET 12
#define SAA9730_ETH_MIN_FRAME_SIZE 60
#define SAA9730_DEST_ADDR_SIZE 6
#define SAA9730_SRC_ADDR_SIZE 6
#define SAA9730_TYPE_LEN_SIZE 2
 
// MAC receive error
#define SAA9730_MAC_GOOD_RX (0x00004000) << 11
#define SAA9730_MAC_RCV_ALIGN_ERROR (0x00000100) << 11
#define SAA9730_MAC_RCV_CRC_ERROR (0x00000200) << 11
#define SAA9730_MAC_RCV_OVERFLOW (0x00000400) << 11
 
// This number is arbitrary and can be increased if needed
#define SAA9730_MAX_MULTICAST_ADDRESSES 20
 
// SAA9730 Event Manager Registers
#define SAA9730_EVM_ISR *((volatile unsigned *)(__base + 0x02000))
#define SAA9730_EVM_IER *((volatile unsigned *)(__base + 0x02004))
#define SAA9730_EVM_IMR *((volatile unsigned *)(__base + 0x02008))
 
#define SAA9730_EVM_IER_SW *((volatile unsigned *)(__base + 0x0202c))
 
#define SAA9730_EVM_LAN_INT (1<<16) // LAN interrupt bit
#define SAA9730_EVM_MASTER (1<<0) // Master interrupt bit
 
// SAA9730 LAN Registers
#define SAA9730_TXBUFA *((volatile unsigned *)(__base + 0x20400)) // TX buffer A
 
#define SAA9730_TXBUFB *((volatile unsigned *)(__base + 0x20404)) // TX buffer B
 
#define SAA9730_RXBUFA *((volatile unsigned *)(__base + 0x20408)) // RX buffer A
 
#define SAA9730_RXBUFB *((volatile unsigned *)(__base + 0x2040C)) // RX buffer B
 
#define SAA9730_PKTCNT *((volatile unsigned *)(__base + 0x20410)) // Packet count
 
#define SAA9730_OK2USE *((volatile unsigned *)(__base + 0x20414)) // OK-to-use
# define SAA9730_OK2USE_TXA 8
# define SAA9730_OK2USE_TXB 4
# define SAA9730_OK2USE_RXA 2
# define SAA9730_OK2USE_RXB 1
 
#define SAA9730_DMACTL *((volatile unsigned *)(__base + 0x20418)) // DMA control
# define SAA9730_DMACTL_BLKINT (1 << 31)
# define SAA9730_DMACTL_MAXXFER_ANY (0 << 18)
# define SAA9730_DMACTL_MAXXFER_8 (1 << 18)
# define SAA9730_DMACTL_MAXXFER_32 (2 << 18)
# define SAA9730_DMACTL_MAXXFER_64 (3 << 18)
# define SAA9730_DMACTL_ENDIAN_LITTLE (0 << 16)
# define SAA9730_DMACTL_ENDIAN_2143 (1 << 16)
# define SAA9730_DMACTL_ENDIAN_4321 (2 << 16)
# define SAA9730_DMACTL_RXINTCNT_SHIFT 8
# define SAA9730_DMACTL_RXINTCNT_MSK (0xff << SAA9730_DMACTL_RXINTCNT_SHIFT)
# define SAA9730_DMACTL_ENTX (1 << 7)
# define SAA9730_DMACTL_ENRX (1 << 6)
# define SAA9730_DMACTL_RXFULL (1 << 5)
# define SAA9730_DMACTL_RXTOINT (1 << 4)
# define SAA9730_DMACTL_RXINT (1 << 3)
# define SAA9730_DMACTL_TXINT (1 << 2)
# define SAA9730_DMACTL_MACTXINT (1 << 1)
# define SAA9730_DMACTL_MACRXINT (1 << 0)
 
#define SAA9730_TIMOUT *((volatile unsigned *)(__base + 0x2041C)) // Time out
 
#define SAA9730_DMASTA *((volatile unsigned *)(__base + 0x20420)) // DMA status
# define SAA9730_DMASTA_TXABADR_MSK (1 << 19)
# define SAA9730_DMASTA_TXBBADR_MSK (1 << 18)
# define SAA9730_DMASTA_RXABADR_MSK (1 << 17)
# define SAA9730_DMASTA_RXBBADR_MSK (1 << 16)
# define SAA9730_DMASTA_RXBBADR_SHIFT 8
# define SAA9730_DMASTA_RXPCKCNT_MASK (0xff << SAA9730_DMASTA_RXPCKCNT_SHIFT)
# define SAA9730_DMASTA_TXMACBUSY_MSK (1 << 7)
# define SAA9730_DMASTA_RXAFULL_MSK (1 << 6)
# define SAA9730_DMASTA_RXBFULL_MSK (1 << 5)
# define SAA9730_DMASTA_RXTOINT_MSK (1 << 4)
# define SAA9730_DMASTA_RXINT_MSK (1 << 3)
# define SAA9730_DMASTA_TXINT_MSK (1 << 2)
# define SAA9730_DMASTA_MACTXINT_MSK (1 << 1)
# define SAA9730_DMASTA_MACRXINT_MSK (1 << 0)
 
#define SAA9730_DMATST *((volatile unsigned *)(__base + 0x20424)) // DMA loop back
# define SAA9730_DMATST_LPBACK (1 << 24)
# define SAA9730_DMATST_RESET 1
 
#define SAA9730_PAUSE *((volatile unsigned *)(__base + 0x20430)) // Pause count
 
#define SAA9730_REMPAUSE *((volatile unsigned *)(__base + 0x20434)) // Remote Pause count
 
#define SAA9730_MACCTL *((volatile unsigned *)(__base + 0x20440)) // MAC control
# define SAA9730_MACCTL_MISSRINT (1 << 13)
# define SAA9730_MACCTL_MISSROLL (1 << 10)
# define SAA9730_MACCTL_LOOP10 (1 << 7)
# define SAA9730_MACCTL_CONMODE_AUTOMATIC (0 << 5)
# define SAA9730_MACCTL_CONMODE_FORCE_10MB (1 << 5)
# define SAA9730_MACCTL_CONMODE_FORCE_MII (2 << 5)
# define SAA9730_MACCTL_LPBACK (1 << 4)
# define SAA9730_MACCTL_FULLDUP (1 << 3)
# define SAA9730_MACCTL_RESET (1 << 2)
# define SAA9730_MACCTL_HALTNOW (1 << 1)
# define SAA9730_MACCTL_HALTREQ (1 << 0)
 
#define SAA9730_CAMCTL *((volatile unsigned *)(__base + 0x20444)) // CAM control
# define SAA9730_CAMCTL_COMPARE (1 << 4)
# define SAA9730_CAMCTL_NEGATE (1 << 3)
# define SAA9730_CAMCTL_BROADCAST (1 << 2)
# define SAA9730_CAMCTL_MULTICAST (1 << 1)
# define SAA9730_CAMCTL_UNICAST (1 << 0)
 
#define SAA9730_TXCTL *((volatile unsigned *)(__base + 0x20448)) // TX control
# define SAA9730_TXCTL_COMPLINT (1 << 14)
# define SAA9730_TXCTL_TXPARINT (1 << 13)
# define SAA9730_TXCTL_LATECOLLINT (1 << 12)
# define SAA9730_TXCTL_EXCOLLINT (1 << 11)
# define SAA9730_TXCTL_CARRIERINT (1 << 10)
# define SAA9730_TXCTL_DEFERINT (1 << 9)
# define SAA9730_TXCTL_UNDERINT (1 << 8)
# define SAA9730_TXCTL_MII10 (1 << 7)
# define SAA9730_TXCTL_SDPAUSE (1 << 6)
# define SAA9730_TXCTL_NOEXDEF (1 << 5)
# define SAA9730_TXCTL_FBACK (1 << 4)
# define SAA9730_TXCTL_NOCRC (1 << 3)
# define SAA9730_TXCTL_NOPAD (1 << 2)
# define SAA9730_TXCTL_TXHALT (1 << 1)
# define SAA9730_TXCTL_ENTX (1 << 0)
 
#define SAA9730_TXSTA *((volatile unsigned *)(__base + 0x2044C)) // TX status
# define SAA9730_TXSTA_SQERR (1 << 16)
# define SAA9730_TXSTA_TXHALTED (1 << 15)
# define SAA9730_TXSTA_COMPLETION (1 << 14)
# define SAA9730_TXSTA_PARITYERR (1 << 13)
# define SAA9730_TXSTA_LATECOLLERR (1 << 12)
# define SAA9730_TXSTA_WAS10MB (1 << 11)
# define SAA9730_TXSTA_LOSTCARRIER (1 << 10)
# define SAA9730_TXSTA_EXDEFER (1 << 9)
# define SAA9730_TXSTA_UNDERRUN (1 << 8)
# define SAA9730_TXSTA_INTERRUPT (1 << 7)
# define SAA9730_TXSTA_PAUSED (1 << 6)
# define SAA9730_TXSTA_DEFERRED (1 << 5)
# define SAA9730_TXSTA_EXCOLL (1 << 4)
# define SAA9730_TXSTA_COLLISIONS_MASK 0xf
 
#define SAA9730_RXCTL *((volatile unsigned *)(__base + 0x20450)) // RX control
# define SAA9730_RXCTL_ENGOOD (1 << 14)
# define SAA9730_RXCTL_ENPARITY (1 << 13)
# define SAA9730_RXCTL_ENLONGERR (1 << 11)
# define SAA9730_RXCTL_ENOVER (1 << 10)
# define SAA9730_RXCTL_ENCRCERR (1 << 9)
# define SAA9730_RXCTL_ENALIGN (1 << 8)
# define SAA9730_RXCTL_IGNORECRC (1 << 6)
# define SAA9730_RXCTL_PASSCTL (1 << 5)
# define SAA9730_RXCTL_STRIPCRC (1 << 4)
# define SAA9730_RXCTL_SHORTEN (1 << 3)
# define SAA9730_RXCTL_LONGEN (1 << 2)
# define SAA9730_RXCTL_RXHALT (1 << 1)
# define SAA9730_RXCTL_ENRX (1 << 0)
 
#define SAA9730_RXSTA *((volatile unsigned *)(__base + 0x20454)) // RX status
# define SAA9730_RXSTA_HALTED (1 << 15)
# define SAA9730_RXSTA_GOOD (1 << 14)
# define SAA9730_RXSTA_PARITY (1 << 13)
# define SAA9730_RXSTA_LONGERR (1 << 11)
# define SAA9730_RXSTA_OVERFLOW (1 << 10)
# define SAA9730_RXSTA_CRCERR (1 << 9)
# define SAA9730_RXSTA_ALIGNERR (1 << 8)
# define SAA9730_RXSTA_WAS10MB (1 << 7)
# define SAA9730_RXSTA_INTERRUPT (1 << 6)
# define SAA9730_RXSTA_CONTROLRCV (1 << 5)
 
#define SAA9730_MDDATA *((volatile unsigned *)(__base + 0x20458)) // PHY mgmt data
# define SAA9730_MDDATA_DATA_MASK (0xffff << SAA9730_MDDATA_DATA_SHIFT)
 
#define SAA9730_MDCTL *((volatile unsigned *)(__base + 0x2045C)) // PHY mgmt control
# define SAA9730_MDCTL_PRESUP (1 << 12)
# define SAA9730_MDCTL_BUSY (1 << 11)
# define SAA9730_MDCTL_WRITE (1 << 10)
# define SAA9730_MDCTL_PHY_SHIFT 5
# define SAA9730_MDCTL_PHY_MASK (0x1f << SAA9730_MDCTL_PHY_SHIFT)
# define SAA9730_MDCTL_ADDR_MASK 0x1f
 
#define SAA9730_CAMADR *((volatile unsigned *)(__base + 0x20460)) // CAM address
# define SAA9730_CAMADR_ADDRESS_MASK (0x1ff << SAA9730_CAMADR_ADDRESS_SHIFT)
 
#define SAA9730_CAMDAT *((volatile unsigned *)(__base + 0x20464)) // CAM data
 
#define SAA9730_CAMENA *((volatile unsigned *)(__base + 0x20468)) // CAM enable
# define SAA9730_CAMENA_ENABLE_MASK (0x3fffff << SAA9730_CAMENA_ENABLE_SHIFT)
 
#define SAA9730_DBGRXS *((volatile unsigned *)(__base + 0x20508)) // DEBUG
# define SAA9730_DBGRXS_RXPI_MASK (0x3ff << 16)
# define SAA9730_DBGRXS_RXPI_ERROR (0x001 << 16)
# define SAA9730_DBGRXS_RXDII_MASK 0x1ff
# define SAA9730_DBGRXS_RXDII_ERROR 8
 
 
#define SAA9730_DBGRXFIFO *((volatile unsigned *)(__base + 0x20510)) // DEBUG
 
#define SAA9730_DBGLANSTA *((volatile unsigned *)(__base + 0x20514)) // DEBUG
 
// ******** Packet control/status **********
 
#define TXPACKET_CTL_FLAG_MASK (0x3 << 30)
# define TX_EMPTY (0 << 30)
# define TX_READY (2 << 30)
# define TX_HWDONE (3 << 30)
 
# define TXPACKET_CTL_IRQ_MASK (1 << 29)
# define TXPACKET_CTL_NOCRC_MASK (1 << 28)
# define TXPACKET_CTL_NOPAD_MASK (1 << 27)
# define TXPACKET_CTL_SIZE_MASK 0x7ff
 
#define TXPACKET_STATUS_FLAG_MASK (0x3 << 30)
# define TXPACKET_STATUS_SQERR (1 << 27)
# define TXPACKET_STATUS_TXHALTED (1 << 26)
# define TXPACKET_STATUS_COMPLETION (1 << 25)
# define TXPACKET_STATUS_PARITYERR (1 << 24)
# define TXPACKET_STATUS_LATECOLLERR (1 << 23)
# define TXPACKET_STATUS_WAS10MB (1 << 22)
# define TXPACKET_STATUS_LOSTCARRIER (1 << 21)
# define TXPACKET_STATUS_EXDEFER (1 << 20)
# define TXPACKET_STATUS_UNDERRUN (1 << 19)
# define TXPACKET_STATUS_COLLISIONS_SHIFT 11
# define TXPACKET_STATUS_COLLISIONS_MASK (0x1f << TXPACKET_STATUS_COLLISIONS_SHIFT)
# define TXPACKET_STATUS_SIZE_MASK 0x7ff
 
# define TXPACKET_STATUS_ERROR (TXPACKET_STATUS_EXDEFER | \
TXPACKET_STATUS_LATECOLLERR | \
TXPACKET_STATUS_LOSTCARRIER | \
TXPACKET_STATUS_UNDERRUN | \
TXPACKET_STATUS_SQERR)
 
# define RXPACKET_STATUS_FLAG_MASK (0x3 << 30)
# define RX_NDIS (0 << 30)
# define RX_INVALID_STAT (1 << 30)
# define RX_READY (2 << 30)
# define RX_HWDONE (3 << 30)
 
# define RXPACKET_STATUS_GOOD (1 << 25)
# define RXPACKET_STATUS_PARITY (1 << 24)
# define RXPACKET_STATUS_LONGERR (1 << 22)
# define RXPACKET_STATUS_OVERFLOW (1 << 21)
# define RXPACKET_STATUS_CRCERR (1 << 20)
# define RXPACKET_STATUS_ALIGNERR (1 << 19)
# define RXPACKET_STATUS_WAS10MB (1 << 18)
# define RXPACKET_STATUS_SIZE_MASK 0x7ff
 
#endif // CYGONCE_DEVS_ETH_MIPS_ATLAS_SAA9730_H
/ocelot/v2_0/cdl/mips_rm7000_ocelot_eth_drivers.cdl
0,0 → 1,113
# ====================================================================
#
# ocelot_eth_drivers.cdl
#
# Ethernet drivers - support for i82559 ethernet controller
# on the PMC-Sierra Ocelot board.
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): jskov
# Contributors: jskov
# Date: 2001-01-25
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_DEVS_ETH_MIPS_RM7000_OCELOT {
display "PMC-Sierra Ocelot board ethernet driver"
description "Ethernet driver for PMC-Sierra Ocelot board."
 
parent CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_HAL_MIPS_RM7000_OCELOT
 
include_dir cyg/io
 
# FIXME: This really belongs in the INTEL_I82559 package
cdl_interface CYGINT_DEVS_ETH_INTEL_I82559_REQUIRED {
display "Intel i82559 ethernet driver required"
}
 
define_proc {
puts $::cdl_system_header "/***** ethernet driver proc output start *****/"
puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_INTEL_I82559_INL <cyg/io/devs_eth_mips_rm7000_ocelot.inl>"
puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_INTEL_I82559_CFG <pkgconf/devs_eth_mips_rm7000_ocelot.h>"
puts $::cdl_system_header "/***** ethernet driver proc output end *****/"
}
 
cdl_component CYGPKG_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0 {
display "Ocelot ethernet port 0 driver"
flavor bool
default_value 1
description "
This option includes the ethernet device driver for the
Ocelot port 0 - that is the connector on the front of
the board."
 
implements CYGHWR_NET_DRIVERS
implements CYGHWR_NET_DRIVER_ETH0
implements CYGINT_DEVS_ETH_INTEL_I82559_REQUIRED
 
cdl_option CYGDAT_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0_NAME {
display "Device name for the ETH0 ethernet port 0 driver"
flavor data
default_value {"\"eth0\""}
description "
This option sets the name of the ethernet device for the
Ocelot port 0."
}
 
cdl_component CYGSEM_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0_SET_ESA {
display "Set the ethernet station address"
flavor bool
default_value 0
description "Enabling this option will allow the ethernet
station address to be forced to the value set by the
configuration. This may be required if the hardware does
not include a serial EEPROM for the ESA."
cdl_option CYGDAT_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0_ESA {
display "The ethernet station address"
flavor data
default_value {"{0x08, 0x88, 0x12, 0x34, 0x56, 0x78}"}
description "The ethernet station address"
}
}
}
}
/ocelot/v2_0/include/devs_eth_mips_rm7000_ocelot.inl
0,0 → 1,118
//==========================================================================
//
// devs/eth/mips/ocelot/include/devs_eth_mips_rm7000_ocelot.inl
//
// Ocelot ethernet I/O definitions.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jskov
// Contributors:jskov
// Date: 2001-01-25
// Purpose: Ocelot ethernet defintions
//####DESCRIPTIONEND####
//==========================================================================
 
#include <cyg/hal/hal_intr.h> // CYGNUM_HAL_INTERRUPT_ETHR
 
#ifdef CYGPKG_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0
 
#ifndef CYGSEM_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0_SET_ESA
# define CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM 0
# define CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_WITHOUT_CRC
#endif
 
#define CYGHWR_INTEL_I82559_PCI_MEM_MAP_BASE (CYGARC_UNCACHED_ADDRESS(0x0ff00000))
#define CYGHWR_INTEL_I82559_PCI_MEM_MAP_SIZE 0x00100000
 
static I82559 i82559_eth0_priv_data = {
#ifdef CYGSEM_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0_SET_ESA
hardwired_esa: 1,
mac_address: CYGDAT_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0_ESA
#else
hardwired_esa: 0,
#endif
};
 
ETH_DRV_SC(i82559_sc0,
&i82559_eth0_priv_data, // Driver specific data
CYGDAT_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0_NAME, // Name for device
i82559_start,
i82559_stop,
i82559_ioctl,
i82559_can_send,
i82559_send,
i82559_recv,
i82559_deliver,
i82559_poll,
i82559_int_vector
);
 
NETDEVTAB_ENTRY(i82559_netdev0,
"i82559_" CYGDAT_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0_NAME,
i82559_init,
&i82559_sc0);
 
#endif // CYGPKG_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0
 
 
// These arrays are used for sanity checking of pointers
I82559 *
i82559_priv_array[CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0
&i82559_eth0_priv_data,
#endif
};
 
#ifdef CYGDBG_USE_ASSERTS
// These are only used when assertions are enabled
cyg_netdevtab_entry_t *
i82559_netdev_array[CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0
&i82559_netdev0,
#endif
};
 
struct eth_drv_sc *
i82559_sc_array[CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_RM7000_OCELOT_ETH0
&i82559_sc0,
#endif
};
#endif // CYGDBG_USE_ASSERTS
 
// EOF devs_eth_mips_rm7000_ocelot.inl
/ocelot/v2_0/ChangeLog
0,0 → 1,54
2001-06-22 Jesper Skov <jskov@redhat.com>
 
* cdl/mips_rm7000_ocelot_eth_drivers.cdl: Default to getting ESA
from EEPROM.
 
* include/devs_eth_mips_rm7000_ocelot.inl: Tell driver to expect
EEPROM without CRC.
 
2001-03-02 Jesper Skov <jskov@redhat.com>
 
* include/devs_eth_mips_rm7000_ocelot.inl: Define controller PCI
details.
 
2001-11-29 Jesper Skov <jskov@redhat.com>
 
* cdl/mips_rm7000_ocelot_eth_drivers.cdl: Platform specific
information required to use the generic i82559 driver for the
Ocelot platform.
* include/devs_eth_mips_rm7000_ocelot.inl: Same.
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================
/vrc4375/v2_0/cdl/vrc4375_eth_drivers.cdl
0,0 → 1,116
# ====================================================================
#
# vrc4375_eth_drivers.cdl
#
# Ethernet drivers - support for i21143 ethernet controller
# on the NEC VRC4375 "Blue Nile" board.
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): hmt
# Contributors:
# Date: 2001-09-17
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_DEVS_ETH_MIPS_VRC4375 {
display "NEC vrc4375 ethernet driver"
description "
Ethernet driver for vrc4375 'Blue Nile' board with one Intel
i21143 Ethernet controller attached via the PCI bus."
 
parent CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_HAL_MIPS_VR4300_VRC4375
 
include_dir cyg/io
 
cdl_interface CYGINT_DEVS_ETH_INTEL_I21143_REQUIRED {
display "Intel i21143 ethernet driver required"
}
 
define_proc {
puts $::cdl_system_header "/***** ethernet driver proc output start *****/"
puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_INTEL_I21143_INL <cyg/io/devs_eth_vrc4375.inl>"
puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_INTEL_I21143_CFG <pkgconf/devs_eth_mips_vrc4375.h>"
puts $::cdl_system_header "/***** ethernet driver proc output end *****/"
}
 
cdl_component CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH0 {
display "Vrc4375 ethernet port 0 driver"
flavor bool
default_value 1
description "
This option includes the ethernet device driver for the
vrc4375Engine or vrc4375Bridge port 0 - that is the connector one
slot in from the corner of the board, or the only connector
depending on your particular hardware."
 
implements CYGHWR_NET_DRIVERS
implements CYGHWR_NET_DRIVER_ETH0
implements CYGINT_DEVS_ETH_INTEL_I21143_REQUIRED
 
cdl_option CYGDAT_DEVS_ETH_MIPS_VRC4375_ETH0_NAME {
display "Device name for the ethernet port 0 driver"
flavor data
default_value {"\"eth0\""}
description "
This option sets the name of the ethernet device for the
ethernet port 0."
}
 
cdl_component CYGSEM_DEVS_ETH_MIPS_VRC4375_ETH0_SET_ESA {
display "Set the ethernet station address"
flavor bool
description "Enabling this option will allow the ethernet
station address to be forced to the value set by the
configuration. This may be required if the hardware does
not include a serial EEPROM for the ESA."
cdl_option CYGDAT_DEVS_ETH_MIPS_VRC4375_ETH0_ESA {
display "The ethernet station address"
flavor data
default_value {"{0x00, 0x12, 0x34, 0x55, 0x55, 0x66}"}
description "The ethernet station address"
}
}
}
}
 
# EOF vrc4375_eth_drivers.cdl
/vrc4375/v2_0/include/devs_eth_vrc4375.inl
0,0 → 1,127
//==========================================================================
//
// devs/eth/mips/vrc4375/..../include/devs_eth_vrc4375.inl
//
// vrc4375 ethernet I/O definitions.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt
// Contributors:
// Date: 2001-09-17
// Purpose: vrc4375 ethernet defintions
//####DESCRIPTIONEND####
//==========================================================================
 
// --------------------------------------------------------------
// Construct the interface
 
#ifdef CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH0
 
static I21143 i21143_eth0_priv_data = {
#ifdef CYGSEM_DEVS_ETH_MIPS_VRC4375_ETH0_SET_ESA
hardwired_esa: 1,
mac_address: CYGDAT_DEVS_ETH_MIPS_VRC4375_ETH0_ESA
#else
hardwired_esa: 0,
#endif
};
 
ETH_DRV_SC(i21143_sc0,
&i21143_eth0_priv_data, // Driver specific data
CYGDAT_DEVS_ETH_MIPS_VRC4375_ETH0_NAME, // Name for device
i21143_start,
i21143_stop,
i21143_ioctl,
i21143_can_send,
i21143_send,
i21143_recv,
i21143_deliver,
i21143_poll,
i21143_int_vector
);
 
NETDEVTAB_ENTRY(i21143_netdev0,
"i21143_" CYGDAT_DEVS_ETH_MIPS_VRC4375_ETH0_NAME,
i21143_init,
&i21143_sc0);
 
#endif // CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH0
 
// --------------------------------------------------------------
// These arrays are used for sanity checking of pointers
I21143 *
i21143_priv_array[CYGNUM_DEVS_ETH_INTEL_I21143_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH0
&i21143_eth0_priv_data,
#endif
#ifdef CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH1
&i21143_eth1_priv_data,
#endif
};
 
#ifdef CYGDBG_USE_ASSERTS
// These are only used when assertions are enabled
cyg_netdevtab_entry_t *
i21143_netdev_array[CYGNUM_DEVS_ETH_INTEL_I21143_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH0
&i21143_netdev0,
#endif
#ifdef CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH1
&i21143_netdev1,
#endif
};
 
struct eth_drv_sc *
i21143_sc_array[CYGNUM_DEVS_ETH_INTEL_I21143_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH0
&i21143_sc0,
#endif
#ifdef CYGPKG_DEVS_ETH_MIPS_VRC4375_ETH1
&i21143_sc1,
#endif
};
#endif // CYGDBG_USE_ASSERTS
 
// --------------------------------------------------------------
// Debugging
 
//#define CYGDBG_DEVS_ETH_INTEL_I21143_CHATTER 1
 
// --------------------------------------------------------------
 
// EOF devs_eth_vrc4375.inl
/vrc4375/v2_0/ChangeLog
0,0 → 1,41
2001-09-27 Hugo Tyson <hmt@redhat.com>
 
* cdl/vrc4375_eth_drivers.cdl: New file.
* include/devs_eth_vrc4375.inl: New file.
Instantiation data for the Intel 21143 Ethernet Device driver,
as used in the NEC MIPS vrc4375 'Blue Nile' board.
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================
/idt79s334a/v2_0/cdl/refidt334_eth_drivers.cdl
0,0 → 1,149
# ====================================================================
#
# refidt334_eth_drivers.cdl
#
# Ethernet drivers
# Intel PRO/100+ platform specific support for IDT MIPS 334
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): Tim Michals
# Original data: hmt
# Contributors:
# Date: 2003-02-13
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_DEVS_ETH_MIPS_REFIDT334 {
display "MIPS IDT 79RC32334 reference platform ethernet driver"
description "Ethernet driver for MIPS IDT 79RC32334 reference platform."
 
parent CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_HAL_MIPS_IDT32334_REFIDT334
 
include_dir cyg/io
 
# FIXME: This really belongs in the INTEL_I82559 package
cdl_interface CYGINT_DEVS_ETH_INTEL_I82559_REQUIRED {
display "Intel i82559 ethernet driver required"
}
 
define_proc {
puts $::cdl_system_header "/***** ethernet driver proc output start *****/"
puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_INTEL_I82559_INL <cyg/io/devs_eth_refidt334.inl>"
puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_INTEL_I82559_CFG <pkgconf/devs_eth_mips_refidt334.h>"
puts $::cdl_system_header "/***** ethernet driver proc output end *****/"
}
 
cdl_component CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0 {
display "IDT 79RC32334 ethernet port 0 driver"
flavor bool
default_value 1
 
implements CYGHWR_NET_DRIVERS
implements CYGHWR_NET_DRIVER_ETH0
implements CYGINT_DEVS_ETH_INTEL_I82559_REQUIRED
 
cdl_option CYGDAT_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0_NAME {
display "Device name for the ETH0 ethernet port 0 driver"
flavor data
default_value {"\"eth0\""}
description "
This option sets the name of the ethernet device for the
i82559 ethernet port 0."
}
 
cdl_component CYGSEM_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0_SET_ESA {
display "Set the ethernet station address"
flavor bool
default_value 0
description "Enabling this option will allow the ethernet
station address to be forced to the value set by the
configuration. This may be required if the hardware does
not include a serial EEPROM for the ESA."
cdl_option CYGDAT_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0_ESA {
display "The ethernet station address"
flavor data
default_value {"{0x08, 0x00, 0x00, 0x00, 0x00, 0x01}"}
description "The ethernet station address"
}
}
}
cdl_component CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1 {
display "IDT 79RC32334 ethernet port 1 driver"
flavor bool
default_value 1
 
implements CYGHWR_NET_DRIVERS
implements CYGHWR_NET_DRIVER_ETH1
implements CYGINT_DEVS_ETH_INTEL_I82559_REQUIRED
 
cdl_option CYGDAT_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1_NAME {
display "Device name for the ETH0 ethernet port 1 driver"
flavor data
default_value {"\"eth1\""}
description "
This option sets the name of the ethernet device for the
i82559 ethernet port 1."
}
 
cdl_component CYGSEM_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1_SET_ESA {
display "Set the ethernet station address"
flavor bool
default_value 0
description "Enabling this option will allow the ethernet
station address to be forced to the value set by the
configuration. This may be required if the hardware does
not include a serial EEPROM for the ESA."
cdl_option CYGDAT_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1_ESA {
display "The ethernet station address"
flavor data
default_value {"{0x08, 0x00, 0x00, 0x00, 0x00, 0x02}"}
description "The ethernet station address"
}
}
}
 
}
 
# EOF refidt334_eth_drivers.cdl
/idt79s334a/v2_0/include/devs_eth_refidt334.inl
0,0 → 1,173
//==========================================================================
//
// devs_eth_refidt334.inl
//
// IDT79S334a i82559 ethernet I/O definitions.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Tim Michals
// Contributors:jskov
// Date: 2003-02-13
// Purpose: IDT79s334A i82559 ethernet defintions
//####DESCRIPTIONEND####
//==========================================================================
 
#include <cyg/hal/hal_intr.h> // CYGNUM_HAL_INTERRUPT_ETHR
 
#if 1 < CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT
#define CYGHWR_DEVS_ETH_INTEL_I82559_DEMUX_ALL
#endif // multiple devs, so demux_all needed
 
 
#if defined(CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0) || defined(CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1)
 
#define CYGHWR_INTEL_I82559_PCI_MEM_MAP_BASE 0xa0100000
#define CYGHWR_INTEL_I82559_PCI_MEM_MAP_SIZE 0x100000 //CYGMEM_SECTION_pci_window_SIZE
 
#define CYGHWR_INTEL_I82559_PCI_VIRT_TO_BUS( _x_ ) (((cyg_uint32)(_x_))|0)
#define CYGHWR_INTEL_I82559_PCI_BUS_TO_VIRT( _x_ ) (((cyg_uint32)(_x_))&~0)
#endif
 
 
#ifdef CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0
 
static I82559 i82559_eth0_priv_data = {
#ifdef CYGSEM_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0_SET_ESA
hardwired_esa: 1,
mac_address: CYGSEM_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0_SET_ESA
#else
hardwired_esa: 0,
#endif
};
 
ETH_DRV_SC(i82559_sc0,
&i82559_eth0_priv_data, // Driver specific data
CYGDAT_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0_NAME, // Name for device
i82559_start,
i82559_stop,
i82559_ioctl,
i82559_can_send,
i82559_send,
i82559_recv,
i82559_deliver,
i82559_poll,
i82559_int_vector
);
 
NETDEVTAB_ENTRY(i82559_netdev0,
"i82559_" CYGDAT_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0_NAME,
i82559_init,
&i82559_sc0);
 
#endif // CYGPKG_DEVS_ETH_XXX_ETH0
 
 
 
 
#ifdef CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1
 
static I82559 i82559_eth1_priv_data = {
#ifdef CYGSEM_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1_SET_ESA
hardwired_esa:2,
mac_address: CYGSEM_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1_SET_ESA
#else
hardwired_esa: 0,
#endif
};
 
ETH_DRV_SC(i82559_sc1,
&i82559_eth1_priv_data, // Driver specific data
CYGDAT_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1_NAME, // Name for device
i82559_start,
i82559_stop,
i82559_ioctl,
i82559_can_send,
i82559_send,
i82559_recv,
i82559_deliver,
i82559_poll,
i82559_int_vector
);
 
NETDEVTAB_ENTRY(i82559_netdev1,
"i82559_" CYGDAT_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1_NAME,
i82559_init,
&i82559_sc1);
 
#endif // CYGPKG_DEVS_ETH_XXX_ETH1
 
 
 
 
// These arrays are used for sanity checking of pointers
I82559 *
i82559_priv_array[CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0
&i82559_eth0_priv_data,
#endif
#ifdef CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1
&i82559_eth1_priv_data,
#endif
};
 
#ifdef CYGDBG_USE_ASSERTS
// These are only used when assertions are enabled
cyg_netdevtab_entry_t *
i82559_netdev_array[CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0
&i82559_netdev0,
#endif
 
#ifdef CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1
&i82559_netdev1,
#endif
 
};
 
struct eth_drv_sc *
i82559_sc_array[CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH0
&i82559_sc0,
#endif
#ifdef CYGPKG_DEVS_ETH_MIPS_REFIDT334_I82559_ETH1
&i82559_sc1,
#endif
};
#endif
 
// EOF devs_eth_refidt334.inl
/idt79s334a/v2_0/ChangeLog
0,0 → 1,39
2003-02-13 Tim Michals <t.michals@attbi.com>
2003-02-13 Jonathan Larmour <jifl@eCosCentric.com>
 
* New package - support for MIPS IDT 79s334a board.
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================
/malta/v2_0/cdl/mips_mips32_malta_eth_drivers.cdl
0,0 → 1,130
# ====================================================================
#
# malta_eth_drivers.cdl
#
# Ethernet drivers - support for AMD PCnet ethernet controller
# on the MIPS MALTA board.
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): jskov
# Contributors: jskov
# Date: 2001-04-02
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_DEVS_ETH_MIPS_MIPS32_MALTA {
display "MIPS MALTA board ethernet driver"
description "Ethernet driver for MIPS MALTA board."
 
parent CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_HAL_MIPS_MALTA
 
include_dir cyg/io
 
# FIXME: This really belongs in the AMD_PCNET package
cdl_interface CYGINT_DEVS_ETH_AMD_PCNET_REQUIRED {
display "AMD PCNET ethernet driver required"
}
 
define_proc {
puts $::cdl_system_header "/***** ethernet driver proc output start *****/"
puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_AMD_PCNET_INL <cyg/io/devs_eth_mips_mips32_malta.inl>"
puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_AMD_PCNET_CFG <pkgconf/devs_eth_mips_mips32_malta.h>"
puts $::cdl_system_header "/***** ethernet driver proc output end *****/"
}
 
cdl_component CYGPKG_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0 {
display "MALTA ethernet port 0 driver"
flavor bool
default_value 1
description "
This option includes the ethernet device driver for the
MALTA port 0."
 
implements CYGHWR_NET_DRIVERS
implements CYGHWR_NET_DRIVER_ETH0
implements CYGINT_DEVS_ETH_AMD_PCNET_REQUIRED
 
cdl_option CYGNUM_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_RX_RING_SIZE {
display "Size of RX ring for ETH0"
flavor data
default_value 4
legal_values { 4 8 16 32 64 128 }
description "
This option sets the size of the RX ring."
}
 
cdl_option CYGNUM_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_TX_RING_SIZE {
display "Size of TX ring for ETH0"
flavor data
default_value 16
legal_values { 4 8 16 32 64 128 }
description "
This option sets the size of the TX ring."
}
 
cdl_option CYGDAT_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_NAME {
display "Device name for the ETH0 ethernet port 0 driver"
flavor data
default_value {"\"eth0\""}
description "
This option sets the name of the ethernet device for the
MALTA port 0."
}
 
cdl_component CYGSEM_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_SET_ESA {
display "Set the ethernet station address"
flavor bool
default_value 0
description "Enabling this option will allow the ethernet
station address to be forced to the value set by the
configuration. This may be required if the hardware does
not include a serial EEPROM for the ESA."
cdl_option CYGDAT_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_ESA {
display "The ethernet station address"
flavor data
default_value {"{0x08, 0x88, 0x12, 0x34, 0x56, 0x78}"}
description "The ethernet station address"
}
}
}
}
/malta/v2_0/include/devs_eth_mips_mips32_malta.inl
0,0 → 1,109
//==========================================================================
//
// devs/eth/mips/malta/include/devs_eth_mips_mips32_malta.inl
//
// Malta ethernet I/O definitions.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jskov
// Contributors:jskov
// Date: 2001-04-02
// Purpose: Malta ethernet defintions
//####DESCRIPTIONEND####
//==========================================================================
 
#include <cyg/hal/hal_intr.h> // CYGNUM_HAL_INTERRUPT_ETHR
 
#ifdef __WANT_CONFIG
 
#define CYGHWR_AMD_PCNET_PCI_MEM_MAP_BASE CYGARC_UNCACHED_ADDRESS((cyg_uint32)(&CYGMEM_SECTION_pci_window[0]))
#define CYGHWR_AMD_PCNET_PCI_MEM_MAP_SIZE ((cyg_uint32)(CYGMEM_SECTION_pci_window_SIZE))
 
#endif // __WANT_CONFIG
 
 
#ifdef __WANT_DEVS
 
#ifdef CYGPKG_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0
 
static pcnet_priv_data amd_pcnet_eth0_priv_data = {
#ifdef CYGSEM_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_SET_ESA
esa : CYGDAT_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_ESA,
hardwired_esa : true,
#else
hardwired_esa : false,
#endif
config_esa : NULL,
rx_ring : NULL,
rx_ring_cnt : (1<<2) /*CYGNUM_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_RX_RING_SIZE*/,
rx_ring_log_cnt : 2,
tx_ring : NULL,
tx_ring_cnt : (1<<2) /*CYGNUM_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_TX_RING_SIZE*/,
tx_ring_log_cnt : 2,
};
 
ETH_DRV_SC(amd_pcnet_sc,
&amd_pcnet_eth0_priv_data, // Driver specific data
CYGDAT_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_NAME,
pcnet_start,
pcnet_stop,
pcnet_control,
pcnet_can_send,
pcnet_send,
pcnet_recv,
pcnet_deliver, // "pseudoDSR" called from fast net thread
pcnet_poll, // poll function, encapsulates ISR and DSR
pcnet_int_vector);
 
NETDEVTAB_ENTRY(pcnet_netdev,
"pcnet_" CYGDAT_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0_NAME,
amd_pcnet_init,
&amd_pcnet_sc);
#endif // CYGPKG_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0
 
// These arrays are used for sanity checking of pointers
struct pcnet_priv_data *
pcnet_priv_array[CYGNUM_DEVS_ETH_AMD_PCNET_DEV_COUNT] = {
#ifdef CYGPKG_DEVS_ETH_MIPS_MIPS32_MALTA_ETH0
&amd_pcnet_eth0_priv_data,
#endif
};
 
#endif // __WANT_DEVS
 
// EOF devs_eth_mips_mips32_malta.inl
/malta/v2_0/ChangeLog
0,0 → 1,70
2001-07-26 Jesper Skov <jskov@redhat.com>
 
* include/devs_eth_mips_mips32_malta.inl: Removed ESA init
definition again now driver has been fixed.
 
2001-07-24 Jesper Skov <jskov@redhat.com>
 
* include/devs_eth_mips_mips32_malta.inl
(CYGHWR_AMD_PCNET_BROKEN_ESA_INIT): Defined.
 
2001-07-18 Jesper Skov <jskov@redhat.com>
 
* cdl/mips_mips32_malta_eth_drivers.cdl: Default to use eeprom ESA.
 
2001-07-12 Jesper Skov <jskov@redhat.com>
 
* include/devs_eth_mips_mips32_malta.inl: Let driver find base and
interrupt details. Updated esa options.
 
2001-06-27 Jesper Skov <jskov@redhat.com>
 
* cdl/mips_mips32_malta_eth_drivers.cdl: Implements net drivers.
 
2001-04-23 Mark Salter <msalter@redhat.com>
 
* include/devs_eth_mips_mips32_malta.inl: Adjust base address to
match changed PCI allocation base. This should really be gotten
at runtime from the PCI interface, not from a build time constant.
 
2001-04-03 Jesper Skov <jskov@redhat.com>
 
* cdl/mips_mips32_malta_eth_drivers.cdl: Platform specific
information required to use the generic AMD PCNet driver for the
Malta platform.
* include/devs_eth_mips_mips32_malta.inl: Same.
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================
/upd985xx/v2_0/cdl/upd985xx_eth_drivers.cdl
0,0 → 1,205
# ====================================================================
#
# upd985xx_eth_drivers.cdl
#
# Ethernet drivers
# NEC uPD985xx device specific support
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): hmt
# Original data: hmt
# Contributors: gthomas
# Date: 2001-06-28
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_DEVS_ETH_MIPS_UPD985XX {
display "NEC uPD985xx ethernet driver"
 
parent CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_IO_ETH_DRIVERS
active_if CYGPKG_HAL_MIPS_UPD985XX
 
implements CYGHWR_NET_DRIVER_ETH0
 
implements CYGHWR_NET_DRIVERS
include_dir cyg/devs/eth
 
description "Ethernet driver for NEC uPD985xx devices."
compile -library=libextras.a if_upd985xx.c
 
cdl_option CYGDBG_DEVS_ETH_MIPS_UPD985XX_CHATTER {
display "Prints ethernet device status info during startup"
default_value 0
description "
The ethernet device initialization code can print lots of info
to confirm that it has booted correctly."
}
 
cdl_option CYGNUM_DEVS_ETH_MIPS_UPD985XX_DEV_COUNT {
display "Number of supported interfaces."
#legal_values 1
#default_value 1
calculated 1
flavor data
description "
This option selects the number of ethernet interfaces to
be supported by the driver."
}
 
cdl_component CYGPKG_DEVS_ETH_MIPS_UPD985XX_ETH0 {
display "Ethernet port 0 driver"
flavor bool
calculated 1
description "
This option includes the ethernet device driver for
port 0 - that is the only connector
depending on your particular hardware."
 
 
cdl_option CYGDAT_DEVS_ETH_UPD985XX_ETH0_NAME {
display "Device name for the ethernet port 0 driver"
flavor data
default_value {"\"eth0\""}
description "
This option sets the name of the ethernet device for the
ethernet port 0."
}
 
cdl_component CYGSEM_DEVS_ETH_UPD985XX_ETH0_SET_ESA {
display "Set the ethernet station address"
flavor bool
default_value false
requires !CYGSEM_DEVS_ETH_UPD985XX_ETH0_GET_EEPROM_ESA
description "Enabling this option will allow the ethernet
station address to be forced to the value set by the
configuration. This may be required if the hardware does
not include a serial EEPROM for the ESA."
cdl_option CYGDAT_DEVS_ETH_UPD985XX_ETH0_ESA {
display "The ethernet station address"
flavor data
default_value {"{0x00, 0xBA, 0xCA, 0xDD, 0x1E, 0xDD}"}
description "The ethernet station address"
}
}
 
cdl_option CYGSEM_DEVS_ETH_UPD985XX_ETH0_GET_EEPROM_ESA {
display "Get the ethernet station address from EEPROM"
flavor bool
default_value !CYGSEM_DEVS_ETH_UPD985XX_ETH0_SET_ESA
requires !CYGSEM_DEVS_ETH_UPD985XX_ETH0_SET_ESA
description "Enabling this option will allow the ethernet
station address to be read from a serial EEPROM (such as 93C06,
93C46...). If this is not valid, your application must set the
ESA manually via an ioctl() call or similar."
}
}
 
cdl_component CYGPKG_DEVS_ETH_MIPS_UPD985XX_OPTIONS {
display "NEC uPD985xx ethernet driver build options"
flavor none
no_define
 
cdl_option CYGPKG_DEVS_ETH_MIPS_UPD985XX_CFLAGS_ADD {
display "Additional compiler flags"
flavor data
no_define
default_value { "-D_KERNEL -D__ECOS" }
description "
This option modifies the set of compiler flags for
building the NEC uPD985xx ethernet driver
package. These flags are used in addition to the set of
global flags."
}
}
 
cdl_component CYGPKG_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS {
display "Workarounds for Ethernet Hardware bugs "
flavor bool
default_value 1
description "
This component controls whether code workarounds for the numerous
hardware bugs in the uPD98503 Ethernet device are included.
These might not all be necessary depending on the speed and mode in
which the interface is used. Please refer to the manufacturer's
Behaviour Analysis Report to make your decision about which of
these options to enable or disable.
The default is to enable all workarounds for best reliability."
 
cdl_option CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_S1 {
display "S1 - CPU to IBUS write restriction"
flavor bool
default_value 1
description "Enable a workaround for hardware bug S1"
}
cdl_component CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2 {
display "E1,E2 - Status queue corruption and MAC filtering"
flavor bool
default_value 1
description "Enable a workaround for hardware bugs E1 and/or E2."
 
cdl_option CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2_E2ONLY {
display "Do not set device in promisc mode - solve E2 only"
flavor bool
default_value 1
description "Work around bug E2 only - do not set the device
in promiscuous mode by default.
Setting this option prevents the work around
for bug E1."
}
}
cdl_option CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E3 {
display "E3 - Transmit descriptor error"
flavor bool
default_value 1
description "Enable a workaround for hardware bug E3"
}
cdl_option CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E8 {
display "E8 - Transmission error under abnormal conditions"
flavor bool
default_value 1
description "Enable a workaround for hardware bug E8"
}
}
}
 
# EOF upd985xx_eth_drivers.cdl
/upd985xx/v2_0/include/upd985xx_eth.h
0,0 → 1,465
#ifndef CYGONCE_HAL_UPD985XX_ETH_H
#define CYGONCE_HAL_UPD985XX_ETH_H
//==========================================================================
//
// upd985xx_eth.h
//
// Architecture specific abstractions for the on-chip ethernet
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt, nickg
// Contributors: nickg
// Date: 2001-06-28
// Purpose: Define architecture abstractions
// Description: This file contains any extra or modified definitions for
// this variant of the architecture's ethernet controller.
// Usage: #include <cyg/io/upd985xx_eth.h>
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <cyg/hal/var_arch.h>
 
// --------------------------------------------------------------------------
// By default we use the definition of UPD985XX_SYSETH_REG( n ) from
// var_arch.h - if we port to a KORVA with multiple ethernet controllers we
// will have to vary this to account for the different base addresses.
 
// (the noise at the end of these lines is the default value)
//
// Table 5-2. MAC Control Register Map
//
#define ETH_MACC1 UPD985XX_SYSETH_REG( 0x000) // MAC configuration register 1 R/W 0000_0000H
#define ETH_MACC2 UPD985XX_SYSETH_REG( 0x004) // MAC configuration register 2 R/W 0000_0000H
#define ETH_IPGT UPD985XX_SYSETH_REG( 0x008) // Back-to-Back IPG register R/W 0000_0013H
#define ETH_IPGR UPD985XX_SYSETH_REG( 0x00C) // Non Back-to-Back IPG register R/W 0000_0E13H
#define ETH_CLRT UPD985XX_SYSETH_REG( 0x010) // Collision register R/W 0000_370FH
#define ETH_LMAX UPD985XX_SYSETH_REG( 0x014) // Max packet length register R/W 0000_0600H
// N/A UPD985XX_SYSETH_REG( 0x018) // Reserved for future use - -
#define ETH_RETX UPD985XX_SYSETH_REG( 0x020) // Retry count register R/W 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x024) // Reserved for future use - -
#define ETH_LSA2 UPD985XX_SYSETH_REG( 0x054) // Station Address register 2 R/W 0000_0000H
#define ETH_LSA1 UPD985XX_SYSETH_REG( 0x058) // Station Address register 1 R/W 0000_0000H
#define ETH_PTVR UPD985XX_SYSETH_REG( 0x05C) // Pause timer value read register R 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x060) // Reserved for future use - -
#define ETH_VLTP UPD985XX_SYSETH_REG( 0x064) // VLAN type register R/W 0000_0000H
#define ETH_MIIC UPD985XX_SYSETH_REG( 0x080) // MII configuration register R/W 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x084) // Reserved for future use - -
#define ETH_MCMD UPD985XX_SYSETH_REG( 0x094) // MII command register W 0000_0000H
#define ETH_MADR UPD985XX_SYSETH_REG( 0x098) // MII address register R/W 0000_0000H
#define ETH_MWTD UPD985XX_SYSETH_REG( 0x09C) // MII write data register R/W 0000_0000H
#define ETH_MRDD UPD985XX_SYSETH_REG( 0x0A0) // MII read data register R 0000_0000H
#define ETH_MIND UPD985XX_SYSETH_REG( 0x0A4) // MII indicator register R 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x0A8) // Reserved for future use - -
#define ETH_AFR UPD985XX_SYSETH_REG( 0x0C8) // Address Filtering register R/W 0000_0000H
#define ETH_HT1 UPD985XX_SYSETH_REG( 0x0CC) // Hash table register 1 R/W 0000_0000H
#define ETH_HT2 UPD985XX_SYSETH_REG( 0x0D0) // Hash table register 2 R/W 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x0D4) // Reserved for future use - -
#define ETH_CAR1 UPD985XX_SYSETH_REG( 0x0DC) // Carry register 1 R/W 0000_0000H
#define ETH_CAR2 UPD985XX_SYSETH_REG( 0x0E0) // Carry register 2 R/W 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x0E4) // Reserved for future use - -
#define ETH_CAM1 UPD985XX_SYSETH_REG( 0x130) // Carry mask register 1 R/W 0000_0000H
#define ETH_CAM2 UPD985XX_SYSETH_REG( 0x134) // Carry mask register 2 R/W 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x138) // Reserved for future use - -
//
// Table 5-3. Statistics Counter Register Map
//
#define ETH_RBYT UPD985XX_SYSETH_REG( 0x140) // Receive Byte Counter R/W
#define ETH_RPKT UPD985XX_SYSETH_REG( 0x144) // Receive Packet Counter R/W
#define ETH_RFCS UPD985XX_SYSETH_REG( 0x148) // Receive FCS Error Counter R/W
#define ETH_RMCA UPD985XX_SYSETH_REG( 0x14C) // Receive Multicast Packet Counter R/W
#define ETH_RBCA UPD985XX_SYSETH_REG( 0x150) // Receive Broadcast Packet Counter R/W
#define ETH_RXCF UPD985XX_SYSETH_REG( 0x154) // Receive Control Frame Packet Counter R/W
#define ETH_RXPF UPD985XX_SYSETH_REG( 0x158) // Receive PAUSE Frame Packet Counter R/W
#define ETH_RXUO UPD985XX_SYSETH_REG( 0x15C) // Receive Unknown OP code Counter R/W
#define ETH_RALN UPD985XX_SYSETH_REG( 0x160) // Receive Alignment Error Counter R/W
#define ETH_RFLR UPD985XX_SYSETH_REG( 0x164) // Receive Frame Length Out of Range Counter R/W
#define ETH_RCDE UPD985XX_SYSETH_REG( 0x168) // Receive Code Error Counter R/W
#define ETH_RFCR UPD985XX_SYSETH_REG( 0x16C) // Receive False Carrier Counter R/W
#define ETH_RUND UPD985XX_SYSETH_REG( 0x170) // Receive Undersize Packet Counter R/W
#define ETH_ROVR UPD985XX_SYSETH_REG( 0x174) // Receive Oversize Packet Counter R/W
#define ETH_RFRG UPD985XX_SYSETH_REG( 0x178) // Receive Error Undersize Packet Counter R/W
#define ETH_RJBR UPD985XX_SYSETH_REG( 0x17C) // Receive Error Oversize Packet Counter R/W
#define ETH_R64 UPD985XX_SYSETH_REG( 0x180) // Receive 64 Byte Frame Counter R/W
#define ETH_R127 UPD985XX_SYSETH_REG( 0x184) // Receive 65 to 127 Byte Frame Counter R/W
#define ETH_R255 UPD985XX_SYSETH_REG( 0x188) // Receive 128 to 255 Byte Frame Counter R/W
#define ETH_R511 UPD985XX_SYSETH_REG( 0x18C) // Receive 256 to 511 Byte Frame Counter R/W
#define ETH_R1K UPD985XX_SYSETH_REG( 0x190) // Receive 512 to 1023 Byte Frame Counter R/W
#define ETH_RMAX UPD985XX_SYSETH_REG( 0x194) // Receive Over 1023 Byte Frame Counter R/W
#define ETH_RVBT UPD985XX_SYSETH_REG( 0x198) // Receive Valid Byte Counter R/W
#define ETH_TBYT UPD985XX_SYSETH_REG( 0x1C0) // Transmit Byte Counter R/W
#define ETH_TPCT UPD985XX_SYSETH_REG( 0x1C4) // Transmit Packet Counter R/W
#define ETH_TFCS UPD985XX_SYSETH_REG( 0x1C8) // Transmit CRC Error Packet Counter R/W
#define ETH_TMCA UPD985XX_SYSETH_REG( 0x1CC) // Transmit Multicast Packet Counter R/W
#define ETH_TBCA UPD985XX_SYSETH_REG( 0x1D0) // Transmit Broadcast Packet Counter R/W
#define ETH_TUCA UPD985XX_SYSETH_REG( 0x1D4) // Transmit Unicast Packet Counter R/W
#define ETH_TXPF UPD985XX_SYSETH_REG( 0x1D8) // Transmit PAUSE control Frame Counter R/W
#define ETH_TDFR UPD985XX_SYSETH_REG( 0x1DC) // Transmit Single Deferral Packet Counter R/W
#define ETH_TXDF UPD985XX_SYSETH_REG( 0x1E0) // Transmit Excessive Deferral Packet Counter R/W
#define ETH_TSCL UPD985XX_SYSETH_REG( 0x1E4) // Transmit Single Collision Packet Counter R/W
#define ETH_TMCL UPD985XX_SYSETH_REG( 0x1E8) // Transmit Multiple collision Packet Counter R/W
#define ETH_TLCL UPD985XX_SYSETH_REG( 0x1EC) // Transmit Late Collision Packet Counter R/W
#define ETH_TXCL UPD985XX_SYSETH_REG( 0x1F0) // Transmit Excessive Collision Packet Counter R/W
#define ETH_TNCL UPD985XX_SYSETH_REG( 0x1F4) // Transmit Total Collision Counter R/W
#define ETH_TCSE UPD985XX_SYSETH_REG( 0x1F8) // Transmit Carrier Sense Error Counter R/W
#define ETH_TIME UPD985XX_SYSETH_REG( 0x1FC) // Transmit Internal MAC Error Counter R/W
//
// Table 5-4. DMA and FIFO Management Registers Map
//
#define ETH_TXCR UPD985XX_SYSETH_REG( 0x200) // Transmit Configuration Register R/W 0000_0000H
#define ETH_TXFCR UPD985XX_SYSETH_REG( 0x204) // Transmit FIFO Control Register R/W FFFF_40C0H
#define ETH_TXDTR UPD985XX_SYSETH_REG( 0x208) // Transmit Data Register W 0000_0000H
#define ETH_TXSR UPD985XX_SYSETH_REG( 0x20C) // Transmit Status Register R 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x210) // Reserved for future use - -
#define ETH_TXDPR UPD985XX_SYSETH_REG( 0x214) // Transmit Descriptor Pointer R/W 0000_0000H
#define ETH_RXCR UPD985XX_SYSETH_REG( 0x218) // Receive Configuration Register R/W 0000_0000H
#define ETH_RXFCR UPD985XX_SYSETH_REG( 0x21C) // Receive FIFO Control Register R/W C040_0040H
#define ETH_RXDTR UPD985XX_SYSETH_REG( 0x220) // Receive Data Register R 0000_0000H
#define ETH_RXSR UPD985XX_SYSETH_REG( 0x224) // Receive Status Register R 0000_0000H
// N/A UPD985XX_SYSETH_REG( 0x228) // Reserved for future use - -
#define ETH_RXDPR UPD985XX_SYSETH_REG( 0x22C) // Receive Descriptor Pointer R/W 0000_0000H
#define ETH_RXPDR UPD985XX_SYSETH_REG( 0x230) // Receive Pool Descriptor Register R/W 0000_0000H
//
// Table 5-5. Interrupt and Configuration Registers Map
//
#define ETH_CCR UPD985XX_SYSETH_REG( 0x234) // Configuration Register R/W 0000_0000H
#define ETH_ISR UPD985XX_SYSETH_REG( 0x238) // Interrupt Service Register R 0000_0000H
#define ETH_MSR UPD985XX_SYSETH_REG( 0x23C) // Mask Serves Register R/W 0000_0000H
 
// --------------------------------------------------------------------------
// Now the fields within all those registers...
//
// Table 5-2. MAC Control Register Map
//
// ETH_MACC1 0x000 MAC configuration register 1 R/W 0000_0000H
#define ETH_MACC1_MACLB (1<<14) // MAC loopback: 0
#define ETH_MACC1_TXFC (1<<11) // Transmit flow control enable: 0
#define ETH_MACC1_RXFC (1<<10) // Receive flow control enable: 0
#define ETH_MACC1_SRXEN (1<< 9) // Receive enable: 0
#define ETH_MACC1_PARF (1<< 8) // Control packet pass: 0
#define ETH_MACC1_PUREP (1<< 7) // Pure preamble: 0
#define ETH_MACC1_FLCHT (1<< 6) // Length field check: 0
#define ETH_MACC1_NOBO (1<< 5) // No Back Off: 0
#define ETH_MACC1_CRCEN (1<< 3) // CRC append enable: 0
#define ETH_MACC1_PADEN (1<< 2) // PAD append enable: 0
#define ETH_MACC1_FDX (1<< 1) // Full duplex enable: 0
#define ETH_MACC1_HUGEN (1<< 0) // Large packet enable: 0
// ETH_MACC2 0x004 MAC configuration register 2 R/W 0000_0000H
#define ETH_MACC2_MCRST (1<<10) // MAC Control Block software reset: 0
#define ETH_MACC2_RFRST (1<< 9) // Receive Function Block software reset: 0
#define ETH_MACC2_TFRST (1<< 8) // Transmit Function Block software reset: 0
#define ETH_MACC2_BPNB (1<< 6) // Back Pressure No Back Off: 0
#define ETH_MACC2_APD (1<< 5) // Auto VLAN PAD: 0
#define ETH_MACC2_VPD (1<< 4) // VLAN PAD mode: 0
 
// ETH_IPGT 0x008 Back-to-Back IPG register R/W 0000_0013H
// ETH_IPGR 0x00C Non Back-to-Back IPG register R/W 0000_0E13H
// ETH_CLRT 0x010 Collision register R/W 0000_370FH
// ETH_LMAX 0x014 Max packet length register R/W 0000_0600H
// N/A 0x018 Reserved for future use - -
// ETH_RETX 0x020 Retry count register R/W 0000_0000H
// N/A 0x024 Reserved for future use - -
// ETH_LSA2 0x054 Station Address register 2 R/W 0000_0000H
// ETH_LSA1 0x058 Station Address register 1 R/W 0000_0000H
// ETH_PTVR 0x05C Pause timer value read register R 0000_0000H
// N/A 0x060 Reserved for future use - -
// ETH_VLTP 0x064 VLAN type register R/W 0000_0000H
#define ETH_VLTP_VLTP (0x00008100) // magic number from example
// ETH_MIIC 0x080 MII configuration register R/W 0000_0000H
#define ETH_MIIC_MIRST (1<<15) // MII Management Interface Block software reset
#define ETH_MIIC_CLKS (0x0C) // 3:2 CLKS Select frequency range:
#define ETH_MIIC_25 (0x00) // 00: HCLK is equal to 25 MHz
#define ETH_MIIC_33 (0x04) // 01: HCLK is less than or equal to 33 MHz
#define ETH_MIIC_50 (0x08) // 10: HCLK is less than or equal to 50 MHz
#define ETH_MIIC_66 (0x0C) // 11: HCLK is less than or equal to 66 MHz
// ETH_MCMD 0x094 MII command register W 0000_0000H
#define ETH_MCMD_SCANC (1<< 1) // SCAN command: 0
#define ETH_MCMD_RSTAT (1<< 0) // MII management read: 0
// ETH_MADR 0x098 MII address register R/W 0000_0000H
#define ETH_MADR_PHY_ADDR_SHIFT (8)
// ETH_MWTD 0x09C MII write data register R/W 0000_0000H
// ETH_MRDD 0x0A0 MII read data register R 0000_0000H
// ETH_MIND 0x0A4 MII indicator register R 0000_0000H
#define ETH_MIND_NVALID (1<< 2) // SCAN command start status: 0
#define ETH_MIND_SCANA (1<< 1) // SCAN command active: 0
#define ETH_MIND_BUSY (1<< 0) // BUSY: 0
// ETH_AFR 0x0C8 Address Filtering register R/W 0000_0000H
#define ETH_AFR_PRO (1<< 3) // Promiscuous mode: 0
#define ETH_AFR_PRM (1<< 2) // Accept Multicast: 0
#define ETH_AFR_AMC (1<< 1) // Accept Multicast ( qualified ): 0
#define ETH_AFR_ABC (1<< 0) // Accept Broadcast: 0
// ETH_HT1 0x0CC Hash table register 1 R/W 0000_0000H
// ETH_HT2 0x0D0 Hash table register 2 R/W 0000_0000H
// ETH_CAR1 0x0DC Carry register 1 R/W 0000_0000H
// ETH_CAR2 0x0E0 Carry register 2 R/W 0000_0000H
// ETH_CAM1 0x130 Carry mask register 1 R/W 0000_0000H
// ETH_CAM2 0x134 Carry mask register 2 R/W 0000_0000H
//
// Table 5-3. Statistics Counter Register Map
// <snip>
//
// Table 5-4. DMA and FIFO Management Registers Map
//
// ETH_TXCR 0x200 Transmit Configuration Register R/W 0000_0000H
#define ETH_TXCR_TXE (1<<31) // Transmit Enable:
#define ETH_TXCR_DTBS_SHIFT (16) // 18:16 DMA Transmit Burst Size:
#define ETH_TXCR_DTBS (0x70000) // 18:16 DMA Transmit Burst Size:
#define ETH_TXCR_DTBS_1 (0x00000) // 000: 1 Word (4 bytes)
#define ETH_TXCR_DTBS_2 (0x10000) // 001: 2 Word (8 bytes)
#define ETH_TXCR_DTBS_4 (0x20000) // 010: 4 Word (16 bytes)
#define ETH_TXCR_DTBS_8 (0x30000) // 011: 8 Word (32 bytes)
#define ETH_TXCR_DTBS_16 (0x40000) // 100: 16 Word (64 bytes)
#define ETH_TXCR_DTBS_32 (0x50000) // 101: 32 Word (128 bytes)
#define ETH_TXCR_DTBS_64 (0x60000) // 110: 64 Word (256 bytes)
#define ETH_TXCR_AFCE (1<< 0) // Auto Flow Control Enable:
// ETH_TXFCR 0x204 Transmit FIFO Control Register R/W FFFF_40C0H
#define ETH_TXFCR_TPTV_SHIFT (16) // 31:16 Transmit Pause Timer Value: FFFFH
#define ETH_TXFCR_TPTV (0xffff0000) // 31:16 Transmit Pause Timer Value: FFFFH
#define ETH_TXFCR_TX_DRTH_SHIFT (10) // 15:10 Transmit Drain Threshold Level: 10H
#define ETH_TXFCR_TX_DRTH (0x0000fc00) // 15:10 Transmit Drain Threshold Level: 10H
#define ETH_TXFCR_TX_FLTH_SHIFT (2) // 7:2 Transmit Fill Threshold Level: 03H
#define ETH_TXFCR_TX_FLTH (0x000000fc) // 7:2 Transmit Fill Threshold Level: 03H
#define ETH_TXFCR_TPTV_DEFAULT (0x10000000) // default 0x1000 slot time (1slot:512bit)
#define ETH_TXFCR_TX_DRTH_DEFAULT (0x00002000) // 001000b (8long, 32byte)
#define ETH_TXFCR_TX_FLTH_DEFAULT (0x000000c0) // default 110000b (48word, 192byte)
// ETH_TXDTR 0x208 Transmit Data Register W 0000_0000H
// ETH_TXSR 0x20C Transmit Status Register R 0000_0000H
#define ETH_TXSR_CSE (1<<31) // Carrier lost was detected during the transmission 0
#define ETH_TXSR_TBP (1<<30) // Back pressure occurred when the packet was received 0
#define ETH_TXSR_TPP (1<<29) // A packet request during the PAUSE operation was transmitted 0
#define ETH_TXSR_TPCF (1<<28) // A PAUSE control frame was transmitted 0
#define ETH_TXSR_TCFR (1<<27) // A control frame was transmitted 0
#define ETH_TXSR_TUDR (1<<26) // The TPUR pin was set high and aborted. Note 2 0
#define ETH_TXSR_TGNT (1<<25) // A huge packet was transmitted and aborted. 0
#define ETH_TXSR_LCOL (1<<24) // Collision occurred
#define ETH_TXSR_ECOL (1<<23) // Excess collisions
#define ETH_TXSR_TEDFR (1<<22) // Excess deferred
#define ETH_TXSR_TDFR (1<<21) // Transmission deferral occurred
#define ETH_TXSR_TBRO (1<<20) // A broadcast packet was transmitted. 0
#define ETH_TXSR_TMUL (1<<19) // A multicast packet was transmitted. 0
#define ETH_TXSR_TDONE (1<<18) // Transmission was completed. 0
#define ETH_TXSR_TFLOR (1<<17) // Value of the length field was huge
#define ETH_TXSR_TFLER (1<<16) // Value of the length field didn~t match the actual data count
#define ETH_TXSR_TCRCE (1<<15) // Attached CRC didn~t match the internal generated CRC
 
#define ETH_TXSR_TCBC_SHIFT (11) // 14:11 collisions for the previous transmission
#define ETH_TXSR_TCBC (0x7800) // 14:11 collisions for the previous transmission
#define ETH_TXSR_TBYT_SHIFT (0) // 10:0 transmitted bytes not including collided bytes
#define ETH_TXSR_TBYT (0x07FF) // 10:0 transmitted bytes not including collided bytes
 
// ETH_RXCR UPD985XX_SYSETH_REG( 0x218) // Receive Configuration Register R/W 0000_0000H
#define ETH_RXCR_RXE (1<<31) // Receive Enable:
#define ETH_RXCR_DRBS_SHIFT (16) // 18:16 DRBS DMA Transmit Burst Size: 0
#define ETH_RXCR_DRBS (0x70000) //
#define ETH_RXCR_DRBS_1 (0x00000) // 000: 1 Word (4 bytes)
#define ETH_RXCR_DRBS_2 (0x10000) // 001: 2 Word (8 bytes)
#define ETH_RXCR_DRBS_4 (0x20000) // 010: 4 Word (16 bytes)
#define ETH_RXCR_DRBS_8 (0x30000) // 011: 8 Word (32 bytes)
#define ETH_RXCR_DRBS_16 (0x40000) // 100: 16 Word (64 bytes)
#define ETH_RXCR_DRBS_32 (0x50000) // 101: 32 Word (128 bytes)
#define ETH_RXCR_DRBS_64 (0x60000) // 110: 64 Word (256 bytes)
 
// ETH_RXFCR 0x21C Receive FIFO Control Register R/W C040_0040H
#define ETH_RXFCR_UWM (0xfc000000) // 31:26 Upper Water Mark: 30H
#define ETH_RXFCR_UWM_SHIFT (26) // 31:26 Upper Water Mark: 30H
#define ETH_RXFCR_LWM (0x00fc0000) // 23:18 Lower Water Mark: 10H
#define ETH_RXFCR_LWM_SHIFT (18) // 23:18 Lower Water Mark: 10H
#define ETH_RXFCR_RX_DRTH (0x000000fc) // 7: 2 Receive Drain Threshold Level 10H
#define ETH_RXFCR_RX_DRTH_SHIFT (2) // 7: 2 Receive Drain Threshold Level 10H
#define ETH_RXFCR_UWM_DEFAULT (0xE0000000) // default 110000b ( 48word, 192byte )
#define ETH_RXFCR_LWM_DEFAULT (0x00400000) // default 010000b (16word, 64byte)
#define ETH_RXFCR_DRTH16W (0x00000040) // default 010000b (16word, 64byte)
 
// ETH_RXDTR 0x220 Receive Data Register R 0000_0000H
// ETH_RXSR 0x224 Receive Status Register R 0000_0000H
#define ETH_RXSR_RLENE (1<<31) // A toosmall or toolarge packet was received.
#define ETH_RXSR_VLAN (1<<30) // A VLAN was received.
#define ETH_RXSR_USOP (1<<29) // A control frame containing an unknown OP code was received.
#define ETH_RXSR_PRCF (1<<28) // A control frame containing the PAUSE OP code was received.
#define ETH_RXSR_RCFR (1<<27) // A control frame was received.
#define ETH_RXSR_DBNB (1<<26) // An alignment error occurred.
#define ETH_RXSR_RBRO (1<<25) // A broadcast packet was received. 0
#define ETH_RXSR_RMUL (1<<24) // A multicast packet was received. 0
#define ETH_RXSR_RXOK (1<<23) // A good packet was received.
#define ETH_RXSR_RLOR (1<<22) // The value of the length field was huge
#define ETH_RXSR_RLER (1<<21) // The value of the length field didn~t match
#define ETH_RXSR_RCRCE (1<<20) // A CRC error occurred. 0
#define ETH_RXSR_RCV (1<<19) // RXER was detected. 0
#define ETH_RXSR_CEPS (1<<18) // A False Carrier was detected. 0
#define ETH_RXSR_REPS (1<<17) // A packet which had a preamble and SFD only or one data nibble
#define ETH_RXSR_PAIG (1<<16) //
#define ETH_RXSR_RBYT (0xffff) // 15:0 The received byte count 0
#define ETH_RXSR_RBYT_SHIFT (0) // 15:0 The received byte count 0
// ETH_RXDPR 0x22C Receive Descriptor Register R/W 0000_0000H
// ETH_RXPDR 0x230 Receive Pool Descriptor Register R/W 0000_0000H
#define ETH_RXPDR_AL (0x70000000) // 30:28 AL[2:0] Alert Level 0H
#define ETH_RXPDR_AL_SHIFT (28)
#define ETH_RXPDR_RNOD (0xffff) // 15:0 Remaining Number of Descriptor 0H
#define ETH_RXPDR_RNOD_SHIFT (0)
//
// Table 5-5. Interrupt and Configuration Registers Map
//
// ETH_CCR 0x234 Configuration Register R/W 0000_0000H
#define ETH_CCR_SRT (1) // Software Reset (cleared automatically to '0')
// ETH_ISR 0x238 Interrupt Service Register R 0000_0000H
#define ETH_ISR_XMTDN (1<<15) // Transmit Done
#define ETH_ISR_TBDR (1<<14) // Transmit Buffer Descriptor Request at Null
#define ETH_ISR_TFLE (1<<13) // Transmit Frame Length Exceed
#define ETH_ISR_UR (1<<12) // Underrun
#define ETH_ISR_TABR (1<<11) // Transmit Aborted
#define ETH_ISR_TCFRI (1<<10) // Control Frame Transmit
#define ETH_ISR_RCVDN (1<<7 ) // Receive Done
#define ETH_ISR_RBDRS (1<<6 ) // Receive Buffer Descriptor Request at alert level
#define ETH_ISR_RBDRU (1<<5 ) // Receive Buffer Descriptor Request at zero
#define ETH_ISR_OF (1<<4 ) // Overflow
#define ETH_ISR_LFAL (1<<3 ) // Link Failed
#define ETH_ISR_CARRY (1<<0 ) // Carry Flag:
// ETH_MSR 0x23C Mask Serves Register R/W 0000_0000H
// As above
 
// --------------------------------------------------------------------------
// And the "buffer descriptor" control structures in RAM...
 
 
#define ETH_BUF_LAST (1<<31) // Last Descriptor
#define ETH_BUF_D_L (1<<30) // Data Buffer / Link Pointer
#define ETH_BUF_D_L_DATA (1<<30) // Data Buffer / Link Pointer
#define ETH_BUF_D_L_LINK (0<<30) // Data Buffer / Link Pointer
#define ETH_BUF_OWN (1<<29) // Owner 1:Ethernet Controller 0: VR4120A
#define ETH_BUF_OWN_ETH (1<<29)
#define ETH_BUF_OWN_CPU (0<<29)
 
#define ETH_BUF_DBRWE (1<<28) // Buffer Access Error
#define ETH_BUF_OK (1<<16) // Tx or Rx OK
#define ETH_BUF_SIZE (0xffff) // Byte Count
#define ETH_BUF_TX_TUDR (1<<27) // Transmit Underrun Error
#define ETH_BUF_TX_CSE (1<<26) // Carrier Sense Lost Error
#define ETH_BUF_TX_LCOL (1<<25) // Late Collision
#define ETH_BUF_TX_ECOL (1<<24) // Excessive Collision
#define ETH_BUF_TX_EDFR (1<<23) // Excessive Deferral
#define ETH_BUF_TX_TGNT (1<<18) // Transmit Giant Frame
#define ETH_BUF_TX_HBF (1<<17) // Heart Beat Fail for ENDEC mode
#define ETH_BUF_RX_OVRN (1<<24) // Overrun Error
#define ETH_BUF_RX_RUNT (1<<23) // Runt packet
#define ETH_BUF_RX_FRGE (1<<22) // Fragment Error
#define ETH_BUF_RX_RCV (1<<21) // Detects RXER
#define ETH_BUF_RX_FC (1<<20) // False Carrier
#define ETH_BUF_RX_CRCE (1<<19) // CRC Error
#define ETH_BUF_RX_FAE (1<<18) // Frame Alignment Error
#define ETH_BUF_RX_RFLE (1<<17) // Receive Frame Length Error
 
#define ETH_BUF_RX_FTYP (0x0e000000) // 27:25 Frame Type[2:0]
#define ETH_BUF_RX_FTYP_SHIFT (25) // 27:25 Frame Type[2:0]
// I don't think we need to know these...
// 000 Broadcast Frame
// 001 Multicast Frame
// 010 Unicast Frame
// 011 VLAN Frame
// 100 PAUSE control frame
// 101 Control Frame (except pause)
// 11x Reserved for future use
 
 
// --------------------------------------------------------------------------
// MII stuff for talking to the separate PHY
// Initially this was a SEEQ NQ80225 but now it is a LU3X31T-T64.
 
//#define SEEQ_DEVICE_PHYS_ADDRESS (1) // this from the board documentation
#define LU3X31T_DEVICE_PHYS_ADDRESS (2)
 
#define ETH_MADR_PHY_DEVICE_PHYS_ADDRESS \
(LU3X31T_DEVICE_PHYS_ADDRESS << ETH_MADR_PHY_ADDR_SHIFT)
 
// I don't know how much they have in common, but I think MII is pretty
// standard, and the "mandated" registers ought to be common.
 
#define PHY_CONTROL_REG (0)
#define PHY_STATUS_REG (1)
#define PHY_ID_ONE (2)
#define PHY_ID_TWO (3)
#define PHY_AUTONEG_ADVERT (4)
#define PHY_AUTONEG_REMOTE (5)
#define PHY_STATUS_DETECT_REG (18)
 
#define PHY_CONTROL_RESET (1<<15)
#define PHY_CONTROL_LOOPBACK (1<<14)
#define PHY_CONTROL_SPEED100 (1<<13)
#define PHY_CONTROL_AUTONEG_EN (1<<12)
#define PHY_CONTROL_POWERDOWN (1<<11)
#define PHY_CONTROL_MII_DIS (1<<10)
#define PHY_CONTROL_AUTONEG_RST (1<< 9)
#define PHY_CONTROL_DPLX_FULL (1<< 8)
#define PHY_CONTROL_COLLTEST (1<< 7)
#define PHY_STATUS_CAP_T4 (1<<15)
#define PHY_STATUS_CAP_100TXF (1<<14)
#define PHY_STATUS_CAP_100TXH (1<<13)
#define PHY_STATUS_CAP_10TF (1<<12)
#define PHY_STATUS_CAP_10TH (1<<11)
#define PHY_STATUS_CAP_SUPR (1<< 6)
#define PHY_STATUS_AUTONEG_ACK (1<< 5)
#define PHY_STATUS_REMOTEFAULT (1<< 4)
#define PHY_STATUS_CAP_AUTONEG (1<< 3)
#define PHY_STATUS_LINK_OK (1<< 2)
#define PHY_STATUS_JABBER (1<< 1)
#define PHY_STATUS_EXTREGS (1<< 0)
 
// These are the same for both AUTONEG registers
#define PHY_AUTONEG_NEXT (1<<15)
#define PHY_AUTONEG_ACK (1<<14)
#define PHY_AUTONEG_REMOTEFAULT (1<<13)
#define PHY_AUTONEG_100BASET4 (1<< 9)
#define PHY_AUTONEG_100BASETX_FDX (1<< 8)
#define PHY_AUTONEG_100BASETX_HDX (1<< 7)
#define PHY_AUTONEG_10BASET_FDX (1<< 6)
#define PHY_AUTONEG_10BASET_HDX (1<< 5)
#define PHY_AUTONEG_CSMA_802_3 (1<< 0)
 
#if 0
// Others are undocumented
#define PHY_STATUS_DETECT_SPEED100 (1<< 7)
#define PHY_STATUS_DETECT_DPLX_FULL (1<< 6)
#endif
 
// Phew!
// --------------------------------------------------------------------------
#endif // CYGONCE_HAL_UPD985XX_ETH_H
// End of upd985xx_eth.h
/upd985xx/v2_0/ChangeLog
0,0 → 1,265
2002-06-14 Gary Thomas <gary@chez-thomas.org>
 
* src/if_upd985xx.c:
Need to include <pkgconf/io_eth_drivers.h> for proper configuration
of stand-alone (polled) vs. system (interrupt driven) mode.
 
2001-09-13 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (upd985xx_eth_upd985xx_init): Fake an ESA if
we see all ones from the EEPROM as well as all zeros.
 
2001-08-30 Hugo Tyson <hmt@redhat.com>
 
* cdl/upd985xx_eth_drivers.cdl: Make the "..._E2ONLY" workaround
option on by default since this is how it will be used - the CPU
load does suffer somewhat if promisc mode is set in the hardware.
This should be unset to allow the workaround for E1 at 100Mbit.
 
2001-08-30 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (PacketRxReady): Re-write the manual
implementation of ESA matching for workaround E1E2 when the device
is in promiscuous mode. It was having problems with the previous
version; this works better.
 
2001-08-24 Hugo Tyson <hmt@redhat.com>
 
* cdl/upd985xx_eth_drivers.cdl: Configury for an alternate case
where we workaround hardware bug E2 only, as a subset of the E1E2
complete fix. Added more description to the options too.
 
* src/if_upd985xx.c (eth_upd985xx_configure): Handle an alternate
case where we workaround hardware bug E2 only. This means leaving
the device in normal mode (unless set to promisc) and doing MAC
address filtering by hand anyway.
 
2001-08-20 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c: Guard all entrypoints that can mess with
hardware state by "active" check. If the net is included in an
app, but not used, it is init'd but not started - this can leave a
pending interrupt from RedBoot's use of the network to take us
completely by surprise. So init() acks and masks the interrupt,
can_send(), recv() and deliver() now demur if not active.
Also some additional STATIC's on entrypoint functions.
 
2001-08-16 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (upd985xx_eth_upd985xx_init): If the EEPROM
contains nothing (or isn't fitted?) fake an ESA so we can get
RedBoot going on the board without special configury.
 
2001-08-16 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (eth_upd985xx_configure): Use smaller numbers
for the Tx Fill Threshold [TX_FLTH] and DMA Tx Burst Size [DTBS]
because the hardware is even more broken than first throught -
this is new information on fault E4. I also tagged this with the
name of the option we would use if this were cdl controlled - but
since it's just setup I see no need to change it, so no CDL.
 
2001-08-16 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (TxDone): Since it still wedged occasionally,
with an "out of rx buffers" status but nothing else, this is a
much simplified workaround for bug E8. If we see the suspect
transmit status, simply reset the whole subsystem there and then.
This leaves it in far more of a known state. It's neater anyway.
 
2001-08-15 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (eth_upd985xx_send): Small hacks to recover
from various wedged states with bogus or unexpected ETH_ISR
values... 0x80000000: We detect this in the deliver routine and
totally reset the system. "out of rx buffers" with no "good rx":
we unmask and check for all these RX interrupts, not just "good
rx". Also PacketRxReady() shortcuts to resetting the receive
engine when it sees the problem. I suspect these might be caused
by the E8 workaround below, perhaps introducing some race
condition with turning off the receiver just when it rx'd - and of
course E1E2 means it receives far more packets.
 
2001-08-07 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c: Workaround various bugs in the hardware;
these workarounds are conditionally compiled via CDL options named
CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_xxx in general; 'xxx'
is the reference for the mis-feature. All are enabled by default.
 
To summarize:
(eth_upd985xx_reset): xxx=S1: insert reads between writes to the
device to avoid a possible deadlock; macro FLUSH_WRITES().
(PacketRxReady): xxx=E1E2: we set the device in promiscuous mode
always, and implement ESA matching in code. The cost is small.
If promisc mode is set by the stack, we pass all packets.
(eth_upd985xx_send): xxx=E3: we copy any transmit that uses 3 or
more SGs into a static contiguous buffer and transmit from that
thus using only one buffer descriptor.
(eth_upd985xx_send):
(TxDone): xxx=E8: we make a note that a tx ended badly and when
starting the next tx, we disable and reset the transmitter.
 
* cdl/upd985xx_eth_drivers.cdl: New subcomponent for controlling
these workarounds: CYGPKG_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS.
"Workarounds for Ethernet Hardware bugs"
 
2001-07-16 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (PacketRxReady): Test for, rather than assert,
packet size in range. The hardware can report a tiny packet as
AOK, with no bad in the status, despite the doc's reassurances.
 
2001-07-13 Hugo Tyson <hmt@redhat.com>
 
* cdl/upd985xx_eth_drivers.cdl: Turn off the startup chatter.
 
2001-07-13 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (TxDone): Test a few more bits for tx
complete; it turns out you can get tx underruns when the CPU us
heavily loaded, as in the tcp_echo tests with high load.
 
2001-07-13 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (eth_upd985xx_send): Use HAL_DCACHE_STORE()
rather than syncing the whole of cache every sglist entry(=mbuf).
Turns out the cache op must be cache line aligned to work on the
4120, boo, unlike other MIPS and unlike the doc, even.
 
2001-07-12 Hugo Tyson <hmt@redhat.com>
 
* cdl/upd985xx_eth_drivers.cdl (CYGPKG_DEVS_ETH_MIPS_UPD985XX_ETH0):
Whole new section to address configuring the source of the MAC
address. Also allows configury of the device's name ("eth0") for
cohabitation with additional devices.
 
* src/if_upd985xx.c (upd985xx_eth_upd985xx_init): Pick up the ESA
from EEPROM if it's available, also support a fixed ESA from CDL
configuration land. A few minor changes to the structure
initialization to accommodate this; also pick up the interrupt
vector from struct init.
(eth_set_mac_address): New routine available via the ioctl()
entry, for use when neither a fixed nor EEPROM address is
available.
 
2001-07-12 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (NUM_RXBUFS): Reduce NUM_RXBUFS to 8; IME
fewer results in lost rx's in typical systems. Enlarge rx buffers
slightly, to accommodate oversize VLAN packets. 128 bytes extra
should be enough. Implemented eth_upd985xx_configure() selection
of promiscuous mode and allow oversize packets - up to the allowed
oversize. Otherwise we would get confused if a packet ate more
than 1 rx buffer.
 
2001-07-12 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c: Tidy up debug print defaults; make functions
static; add a few extra statistics to the device object; pass a
p_eth_upd985xx around more consistently for if we switch to
multiple devices in future; comment out mii_write(); handle
stopping the device with a tx pending; remove some commented-out
templates copied from another driver; and fill in SNMP statistics.
In other words, many minor changes.
 
2001-07-11 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c (PacketRxReady): Recover from running out of
receive buffers. All very dodgy, but it seems to work.
Additional efforts are also made to reset the device, having
realized how hard it is to re-initialize the receive engine once
it has been awakened.
 
2001-07-11 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c: Efficient Rx now essentially working, with a
simple circular buffer, always linked into a ring, and one entry
of which is always NULL,NULL to bring the rx machinery to a halt.
If it reaches thus far the rx mechanism seems to jam; will deal
with that next.
 
2001-07-09 Hugo Tyson <hmt@redhat.com>
 
* src/if_upd985xx.c: Rejigged version of the rx buffer system;
still not working properly, still not a good match for the
hardware's elusive semantics. Committed anyway, to keep it around
for reference.
(eth_upd985xx_status): Also removed all the cruft about
renegotiating line status; it's not needed.
 
2001-07-06 Hugo Tyson <hmt@redhat.com>
 
* include/upd985xx_eth.h (ETH_MADR_PHY_DEVICE_PHYS_ADDRESS):
Change name of PHY address symbol to generic not SEEQ.
Comment out the non-standard symbols for useful bits that the
previous PHY device supported.
 
* src/if_upd985xx.c (eth_upd985xx_reset): If there is a valid ESA
in the MAC already, run with it - it would have come from the
not-fitted serial EEPROM, via some different registers.
(upd985xx_eth_upd985xx_init): Moved the call to reset about to
accommodate this.
(eth_upd985xx_status): Omit renegotiation of link properties and
use the intersection of the capabilities bits to report what
speed, duplex, we are running at. More portable.
(mii_write):
(mii_read): Change name of PHY address symbol to generic not SEEQ
'cos the board has changed.
 
2001-07-06 Hugo Tyson <hmt@redhat.com>
 
* ChangeLog:
* cdl/upd985xx_eth_drivers.cdl:
* include/upd985xx_eth.h:
* src/if_upd985xx.c:
New files. Initial checkin of limping along version of
NEC upd985xx ethernet driver.
 
Limitations:
ESA is hard coded.
It talks to the PHY just to make sure - helped with debug anyway.
No SNMP data exported.
No ioctl() for promiscuous mode or VLAN mode.
Only one TX at once.
Only one RX buffer, so no RX until serviced.
It seems to loose interrupts - inevitably, for an eth device - and
there's no "catchup" defense against this yet.
 
It's oriented to the "old" (already) board - so the particular PHY
and GPIO layout.
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================
/upd985xx/v2_0/src/if_upd985xx.c
0,0 → 1,1621
//==========================================================================
//
// if_upd985xx.c
//
// Ethernet drivers
// NEC UPD985XX device ethernet specific support
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD or other sources,
// and are covered by the appropriate copyright disclaimers included herein.
//
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt, gthomas
// Contributors:
// Date: 2001-06-28
// Purpose:
// Description: hardware driver for uPD985xx ethernet devices
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/system.h>
#include <pkgconf/devs_eth_mips_upd985xx.h>
#include <pkgconf/io_eth_drivers.h>
 
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/hal_cache.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/drv_api.h>
#include <cyg/io/eth/netdev.h>
#include <cyg/io/eth/eth_drv.h>
 
#ifdef CYGPKG_NET
#include <pkgconf/net.h>
#include <net/if.h> /* Needed for struct ifnet */
#else
#include <cyg/hal/hal_if.h>
#endif
 
#include <cyg/devs/eth/upd985xx_eth.h>
 
#include <cyg/io/eth/eth_drv_stats.h>
 
// ------------------------------------------------------------------------
 
#ifdef CYGDBG_DEVS_ETH_MIPS_UPD985XX_CHATTER
#define nDEBUG_TRAFFIC // This one prints stuff as packets come and go
#define nDEBUG_IOCTL // ioctl() call printing
#define DEBUG // Startup printing mainly
#endif
 
#define os_printf diag_printf
#define db_printf diag_printf
 
#define STATIC static
 
// ------------------------------------------------------------------------
// I/O access macros as inlines for later changes to >1 device?
//
// (If we need to do this, then these macros would *assume* the
// presence of a valid p_eth_upd985xx just like we always have)
 
static inline void OUTL( volatile cyg_uint32 *io_address, cyg_uint32 value )
{ *io_address = value; }
 
static inline cyg_uint32 INL( volatile cyg_uint32 *io_address )
{ return *io_address; }
 
// These map cachable addresses to uncachable ones and vice versa.
// This is all fixed on MIPS. 8-9xxxxxxx uncachable, A-Bxxxxxxx cachable.
#define VIRT_TO_BUS( _x_ ) virt_to_bus((cyg_uint32)(_x_))
static inline cyg_uint8 *virt_to_bus(cyg_uint32 p_memory)
{
return (cyg_uint8 *)(0xa0000000u + (p_memory & ~0xe0000000u));
}
#define BUS_TO_VIRT( _x_ ) bus_to_virt((cyg_uint32)(_x_))
static inline cyg_uint8 *bus_to_virt(cyg_uint32 p_memory)
{
return (cyg_uint8 *)(0x80000000u + (p_memory & ~0xe0000000u));
}
 
 
// ------------------------------------------------------------------------
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_S1
#define FLUSH_WRITES() CYG_MACRO_START \
(void) INL( ETH_RXSR ); \
CYG_MACRO_END
#else
#define FLUSH_WRITES() CYG_EMPTY_STATEMENT
#endif
 
// ------------------------------------------------------------------------
//
// DEVICES AND PACKET QUEUES
//
// ------------------------------------------------------------------------
 
// 128 bytes extra for VLAN packets should be enough; AFAICT usually the
// encapsulation is only 4 or 10 bytes extra.
#define MAX_ETHERNET_PACKET_SIZE 1536 // Ethernet Rx packet size
#define MAX_OVERSIZE_PACKET_SIZE 1664 // VLAN Rx packet size
#define MAX_RX_PACKET_SIZE MAX_OVERSIZE_PACKET_SIZE
 
#define NUM_RXBUFS (8)
 
// This one is the hardware definition.
struct bufdesc {
volatile cyg_uint32 attr;
cyg_uint8 *ptr;
};
 
// Rx databuffer.
STATIC cyg_uint8 rx_databuf[ NUM_RXBUFS ] [ MAX_RX_PACKET_SIZE ];
 
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E3
// Tx databuffer
STATIC cyg_uint8 tx_databuf[ MAX_RX_PACKET_SIZE ];
#endif
 
struct eth_upd985xx {
cyg_uint8 active, index, tx_busy, mac_addr_ok;
cyg_uint8 vector; // interrupt numbers are small
cyg_uint8 phy_status; // from PHY_STATUS_ flags below
cyg_uint8 hardwired_esa;
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2
cyg_uint8 promisc;
#endif
cyg_uint8 mac_address[6];
 
cyg_handle_t interrupt_handle;
cyg_interrupt interrupt_object;
 
struct cyg_netdevtab_entry *ndp;
 
// these shall hold uncached addresses of the structures following...
volatile struct bufdesc *txring;
volatile struct bufdesc *rxring_active;
volatile struct bufdesc *rxring_next;
int rxring_active_index;
int rxring_next_index;
cyg_uint32 intrs;
cyg_uint32 tx_keys[1];
 
// -----------------------------------------------------------------
// Statistics counters
cyg_uint32 count_rx_resource;
cyg_uint32 count_rx_restart;
cyg_uint32 count_interrupts;
cyg_uint32 count_bad_isr_restarts;
cyg_uint32 count_bad_tx_completion;
 
// -----------------------------------------------------------------
// DO NOT ACCESS THESE DIRECTLY - THE DEVICE HAS TO SEE THEM UNCACHED
 
// Initially, enough for one whole transmission to be described in one go,
// plus a null link on the end.
struct bufdesc tx_bufdesc[ MAX_ETH_DRV_SG + 2 ];
 
// Pending rx buffers, of full size.
struct bufdesc rx_bufdesc[ NUM_RXBUFS+1 ];
 
// -----------------------------------------------------------------
};
 
struct eth_upd985xx eth_upd985xx[CYGNUM_DEVS_ETH_MIPS_UPD985XX_DEV_COUNT] = {
{
index: 0,
vector: CYGNUM_HAL_INTERRUPT_ETHER,
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2
promisc: 0,
#endif
#ifdef CYGSEM_DEVS_ETH_UPD985XX_ETH0_SET_ESA
hardwired_esa: 1,
mac_address: CYGDAT_DEVS_ETH_UPD985XX_ETH0_ESA,
mac_addr_ok: 1,
#else
hardwired_esa: 0,
mac_addr_ok: 0,
#endif
}
};
 
// eth0
 
ETH_DRV_SC(upd985xx_sc0,
&eth_upd985xx[0], // Driver specific data
CYGDAT_DEVS_ETH_UPD985XX_ETH0_NAME, // name for this interface
eth_upd985xx_start,
eth_upd985xx_stop,
eth_upd985xx_ioctl,
eth_upd985xx_can_send,
eth_upd985xx_send,
eth_upd985xx_recv,
eth_upd985xx_deliver,
eth_upd985xx_poll,
eth_upd985xx_int_vector
);
 
NETDEVTAB_ENTRY(upd985xx_netdev0,
"upd985xx-" CYGDAT_DEVS_ETH_UPD985XX_ETH0_NAME,
upd985xx_eth_upd985xx_init,
&upd985xx_sc0);
 
 
// This is in a macro so that if more devices arrive it can easily be changed
#define CHECK_NDP_SC_LINK() CYG_MACRO_START \
CYG_ASSERT( ((void *)ndp == (void *)&upd985xx_netdev0), "Bad ndp" ); \
CYG_ASSERT( ((void *)sc == (void *)&upd985xx_sc0), "Bad sc" ); \
CYG_ASSERT( (void *)p_eth_upd985xx == sc->driver_private, \
"sc pointer bad" ); \
CYG_ASSERT( (void *)p_eth_upd985xx == (void *)&eth_upd985xx[0], \
"bad p_eth_upd985x" ); \
CYG_MACRO_END
 
#define NUM_ELEMENTS( _x_ ) (sizeof( (_x_) ) / sizeof( (_x_[0]) ) )
 
// ------------------------------------------------------------------------
//
// FUNCTION PROTOTYPES
//
// ------------------------------------------------------------------------
STATIC void InitRxRing(struct eth_upd985xx* p_eth_upd985xx);
STATIC void NextRxRing(struct eth_upd985xx* p_eth_upd985xx);
STATIC void InitTxRing(struct eth_upd985xx* p_eth_upd985xx);
STATIC void ResetTxRing(struct eth_upd985xx* p_eth_upd985xx);
 
#ifdef CYGPKG_NET
STATIC int eth_upd985xx_configure(struct eth_upd985xx* p_eth_upd985xx,
int promisc, int oversized);
#endif
 
STATIC void PacketRxReady(struct eth_upd985xx* p_eth_upd985xx);
STATIC void TxDone(struct eth_upd985xx* p_eth_upd985xx);
 
#define PHY_STATUS_LINK (1)
#define PHY_STATUS_FDX (2)
#define PHY_STATUS_100MBPS (4)
STATIC int eth_upd985xx_status( struct eth_upd985xx *p_eth_upd985xx );
STATIC int eth_set_mac_address( struct eth_upd985xx *p_eth_upd985xx, void *data );
 
// ------------------------------------------------------------------------
//
// MII ACCESS TO PHY DEVICE
//
// ------------------------------------------------------------------------
 
STATIC cyg_bool mii_read( cyg_uint32 reg, cyg_uint32 *pvalue,
struct eth_upd985xx *p_eth_upd985xx )
{
int i = 1000;
// wait a bit for it to be idle
while ( 0 != ((ETH_MIND_NVALID | ETH_MIND_SCANA | ETH_MIND_BUSY)
& INL(ETH_MIND)) )
if ( --i < 0 )
return false;
// Tell it the register address and PHY address
OUTL( ETH_MADR, ETH_MADR_PHY_DEVICE_PHYS_ADDRESS | reg );
OUTL( ETH_MCMD, ETH_MCMD_RSTAT ); // "do a read"
// wait for the read to complete
while ( 0 != ((ETH_MIND_NVALID | ETH_MIND_SCANA | ETH_MIND_BUSY)
& INL(ETH_MIND)) )
if ( --i < 0 )
return false;
// so get the data
*pvalue = INL( ETH_MRDD );
return true;
}
 
#if 0
STATIC cyg_bool mii_write( cyg_uint32 reg, cyg_uint32 value,
struct eth_upd985xx *p_eth_upd985xx )
{
int i = 1000;
// wait a bit for it to be idle
while ( 0 != ((ETH_MIND_NVALID | ETH_MIND_SCANA | ETH_MIND_BUSY)
& INL(ETH_MIND)) )
if ( --i < 0 )
return false;
// Tell it the register address and PHY address
OUTL( ETH_MADR, ETH_MADR_PHY_DEVICE_PHYS_ADDRESS | reg );
// And write the data:
OUTL( ETH_MWTD, value );
// wait a bit for it to be idle
while ( 0 != ((ETH_MIND_NVALID | ETH_MIND_SCANA | ETH_MIND_BUSY)
& INL(ETH_MIND)) )
if ( --i < 0 )
return false;
return true;
}
#endif
 
// ------------------------------------------------------------------------
//
// INTERRUPT HANDLERS
//
// ------------------------------------------------------------------------
 
STATIC cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_drv_interrupt_mask( vector );
 
return CYG_ISR_CALL_DSR; // schedule DSR
}
 
// ------------------------------------------------------------------------
// This is a callback from the higher level thread in consequence of the DSR
STATIC void
eth_upd985xx_deliver(struct eth_drv_sc *sc)
{
register int intrs;
struct eth_upd985xx *p_eth_upd985xx;
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
 
p_eth_upd985xx->count_interrupts++;
 
intrs = INL( ETH_ISR ); // Read-clear
// Acknowledge once at the start anyway to prevent an interrupt loop in
// case of a transient - interrupts latch in the interrupt controller
// as well as in the ethernet device.
cyg_drv_interrupt_acknowledge(p_eth_upd985xx->vector);
 
#ifdef DEBUG_TRAFFIC
os_printf("\n[[[[[[[ Deliver intrs = %x\n", intrs );
#endif
 
// Guard possible external entry points
if ( ! p_eth_upd985xx->active )
return; // without unmasking the interrupt
 
while ( intrs ) {
if ( 0xffff0000 & intrs ) {
// Then something very bad has happened
p_eth_upd985xx->count_bad_isr_restarts++;
CYG_ASSERT ( p_eth_upd985xx->active, "Device not active!" );
eth_upd985xx_stop( sc );
eth_upd985xx_start( sc, NULL, 0 );
intrs = INL( ETH_ISR ); // Read-clear
}
p_eth_upd985xx->intrs = intrs;
if ( ( ETH_ISR_XMTDN | ETH_ISR_TABR ) & intrs ) {
// Scan for completed Txen and inform the stack
TxDone(p_eth_upd985xx);
}
if ( ( ETH_ISR_RCVDN | ETH_ISR_RBDRS | ETH_ISR_RBDRU ) & intrs ) {
// Pass any rx data up the stack
PacketRxReady(p_eth_upd985xx);
}
// Now we have made the interrupt causes go away, acknowledge and
// *then* read the ISR again. That way the race can result in a
// spurious interrupt rather than a lost interrupt.
cyg_drv_interrupt_acknowledge(p_eth_upd985xx->vector);
intrs = INL( ETH_ISR ); // Read-clear
#ifdef DEBUG_TRAFFIC
if ( intrs )
os_printf("------- Again intrs = %x\n", intrs );
#endif
}
#ifdef DEBUG_TRAFFIC
os_printf("]]]]]]]] Done intrs = %x\n\n", intrs );
#endif
 
cyg_drv_interrupt_unmask(p_eth_upd985xx->vector);
}
 
// ------------------------------------------------------------------------
// Device table entry to operate the chip in a polled mode.
// Only diddle the interface we were asked to!
 
STATIC void
eth_upd985xx_poll(struct eth_drv_sc *sc)
{
struct eth_upd985xx *p_eth_upd985xx;
 
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
 
// As it happens, this driver always requests the DSR to be called:
(void)eth_isr( p_eth_upd985xx->vector, (cyg_addrword_t)sc );
eth_upd985xx_deliver( sc );
}
 
// ------------------------------------------------------------------------
// Determine interrupt vector used by a device - for attaching GDB stubs
// packet handler.
STATIC int
eth_upd985xx_int_vector(struct eth_drv_sc *sc)
{
struct eth_upd985xx *p_eth_upd985xx;
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
return (p_eth_upd985xx->vector);
}
 
// ------------------------------------------------------------------------
 
STATIC int
eth_set_mac_address( struct eth_upd985xx *p_eth_upd985xx, void *data )
{
cyg_uint8 *p = (cyg_uint8 *)data;
cyg_uint8 *mac_address;
 
mac_address = &p_eth_upd985xx->mac_address[0];
 
mac_address[5] = p[5];
mac_address[4] = p[4];
mac_address[3] = p[3];
mac_address[2] = p[2];
mac_address[1] = p[1];
mac_address[0] = p[0];
 
p_eth_upd985xx->mac_addr_ok = 1;
 
// Set the ESA in the device regs
OUTL( ETH_LSA2,
(p_eth_upd985xx->mac_address[1]) |
(p_eth_upd985xx->mac_address[0] << 8 ) );
OUTL( ETH_LSA1,
(p_eth_upd985xx->mac_address[5]) |
(p_eth_upd985xx->mac_address[4] << 8 ) |
(p_eth_upd985xx->mac_address[3] << 16 ) |
(p_eth_upd985xx->mac_address[2] << 24) );
 
return 0; // OK
}
 
// ------------------------------------------------------------------------
 
STATIC void
eth_upd985xx_reset( struct eth_upd985xx *p_eth_upd985xx )
{
int i;
 
// Reset whole device: Software Reset (clears automatically)
OUTL( ETH_CCR, ETH_CCR_SRT );
for ( i = 0; i < 10000; i++ ) /* nothing */;
// Reset internal units
OUTL( ETH_MACC2, ETH_MACC2_MCRST | ETH_MACC2_RFRST | ETH_MACC2_TFRST );
for ( i = 0; i < 10000; i++ ) /* nothing */;
FLUSH_WRITES();
OUTL( ETH_MACC2, 0 ); // (and release reset)
// Enable CRC adding, padding
FLUSH_WRITES();
OUTL( ETH_MACC1,
ETH_MACC1_CRCEN | ETH_MACC1_PADEN |
ETH_MACC1_TXFC | ETH_MACC1_RXFC | ETH_MACC1_PARF );
FLUSH_WRITES();
OUTL( ETH_MACC2, ETH_MACC2_APD ); // Auto VLAN pad
FLUSH_WRITES();
OUTL( ETH_HT1, 0 );
FLUSH_WRITES();
OUTL( ETH_HT2, 0 );
 
// Enable rx of broadcasts, multicasts, but not promiscuous...
FLUSH_WRITES();
#if defined( CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2 ) && \
!defined( CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2_E2ONLY )
// Unless we are faking it.
OUTL( ETH_AFR, ETH_AFR_ABC | ETH_AFR_PRM | ETH_AFR_PRO );
#else
OUTL( ETH_AFR, ETH_AFR_ABC | ETH_AFR_PRM );
#endif
 
FLUSH_WRITES();
OUTL( ETH_IPGT, 0x00000013 );
FLUSH_WRITES();
OUTL( ETH_IPGR, 0x00000e13 );
FLUSH_WRITES();
OUTL( ETH_CLRT, 0x0000380f );
FLUSH_WRITES();
OUTL( ETH_LMAX, MAX_ETHERNET_PACKET_SIZE );
 
// Select a clock for the MII
FLUSH_WRITES();
OUTL( ETH_MIIC, ETH_MIIC_66 ); // Example code sets to 66.
// Set VLAN type reg
FLUSH_WRITES();
OUTL( ETH_VLTP, ETH_VLTP_VLTP );
 
// Set the ESA in the device regs
if ( p_eth_upd985xx->mac_addr_ok ) {
FLUSH_WRITES();
OUTL( ETH_LSA2,
(p_eth_upd985xx->mac_address[1]) |
(p_eth_upd985xx->mac_address[0] << 8 ) );
FLUSH_WRITES();
OUTL( ETH_LSA1,
(p_eth_upd985xx->mac_address[5]) |
(p_eth_upd985xx->mac_address[4] << 8 ) |
(p_eth_upd985xx->mac_address[3] << 16 ) |
(p_eth_upd985xx->mac_address[2] << 24) );
}
 
FLUSH_WRITES();
OUTL( ETH_RXFCR, ETH_RXFCR_UWM_DEFAULT |
ETH_RXFCR_LWM_DEFAULT | ETH_RXFCR_DRTH16W );
 
FLUSH_WRITES();
// Fault E4 - use only 32 for FLTH, not the previously recommended 48 (words)
// Tag: CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E4
// but no config opt is provided.
OUTL( ETH_TXFCR, ETH_TXFCR_TPTV_DEFAULT |
ETH_TXFCR_TX_DRTH_DEFAULT | (32 << ETH_TXFCR_TX_FLTH_SHIFT) );
 
// Transmit and receive config regs we hit when enabling those
// functions separately, and the wet string end of the receiver
// which is controlled by MACC1 |= ETH_MACC1_SRXEN;
 
// Tx and Rx interrupts enabled internally;
// Tx done/aborted, and rx OK.
FLUSH_WRITES();
OUTL( ETH_MSR, ETH_ISR_XMTDN | ETH_ISR_TABR |
ETH_ISR_RCVDN | ETH_ISR_RBDRS | ETH_ISR_RBDRU );
FLUSH_WRITES();
}
 
// ------------------------------------------------------------------------
//
// NETWORK INTERFACE INITIALIZATION
//
// ------------------------------------------------------------------------
STATIC bool
upd985xx_eth_upd985xx_init(struct cyg_netdevtab_entry * ndp)
{
struct eth_drv_sc *sc;
cyg_uint8 *mac_address;
struct eth_upd985xx *p_eth_upd985xx;
 
#ifdef DEBUG
db_printf("upd985xx_eth_upd985xx_init\n");
#endif
 
sc = (struct eth_drv_sc *)(ndp->device_instance);
p_eth_upd985xx = (struct eth_upd985xx *)(sc->driver_private);
 
CHECK_NDP_SC_LINK();
 
p_eth_upd985xx->tx_busy = 0;
 
// record the net dev pointer
p_eth_upd985xx->ndp = (void *)ndp;
 
mac_address = &p_eth_upd985xx->mac_address[0];
 
#ifdef CYGSEM_DEVS_ETH_UPD985XX_ETH0_GET_EEPROM_ESA
if ( ! p_eth_upd985xx->hardwired_esa ) {
cyg_uint8 *p;
union macar {
struct {
cyg_uint32 macar1, macar2, macar3;
} integers;
cyg_uint8 bytes[12];
} eeprom;
 
eeprom.integers.macar1 = INL( MACAR1 ); // MAC Address Register 1
eeprom.integers.macar2 = INL( MACAR2 ); // MAC Address Register 2
eeprom.integers.macar3 = INL( MACAR3 ); // MAC Address Register 3
 
if ( (0 != eeprom.integers.macar1 ||
0 != eeprom.integers.macar2 ||
0 != eeprom.integers.macar3 )
&&
(0xffffffff != eeprom.integers.macar1 ||
0xffffffff != eeprom.integers.macar2 ||
0xffffffff != eeprom.integers.macar3 ) ) {
// Then we have good data in the EEPROM
#ifdef DEBUG
os_printf( "EEPROM data %08x %08x %08x\n",
eeprom.integers.macar1,
eeprom.integers.macar2,
eeprom.integers.macar3 );
#endif
p = &eeprom.bytes[0]; // pick up either set of ESA info
if ( 1 == p_eth_upd985xx->index )
p += 6;
 
mac_address[5] = p[5];
mac_address[4] = p[4];
mac_address[3] = p[3];
mac_address[2] = p[2];
mac_address[1] = p[1];
mac_address[0] = p[0];
p_eth_upd985xx->mac_addr_ok = 1;
}
else {
// Fake it so we can get RedBoot going on a board with no EEPROM
mac_address[0] = 0;
mac_address[1] = 0xBA;
mac_address[2] = 0xD0;
mac_address[3] = 0xEE;
mac_address[4] = 0x00;
mac_address[5] = p_eth_upd985xx->index;
p_eth_upd985xx->mac_addr_ok = 1;
}
}
#endif // CYGSEM_DEVS_ETH_UPD985XX_ETH0_GET_EEPROM_ESA
// Init the underlying hardware and insert the ESA:
eth_upd985xx_reset(p_eth_upd985xx);
 
#ifdef DEBUG
os_printf("MAC Address %s, ESA = %02X %02X %02X %02X %02X %02X\n",
p_eth_upd985xx->mac_addr_ok ? "OK" : "**BAD**",
mac_address[0], mac_address[1], mac_address[2], mac_address[3],
mac_address[4], mac_address[5]);
#endif
 
// Set up the pointers to data structures
InitTxRing(p_eth_upd985xx);
 
// Construct the interrupt handler
p_eth_upd985xx->active = 0;
cyg_drv_interrupt_acknowledge(p_eth_upd985xx->vector);
cyg_drv_interrupt_mask(p_eth_upd985xx->vector);
cyg_drv_interrupt_create(
p_eth_upd985xx->vector,
0, // Priority - unused
(CYG_ADDRWORD)sc, // Data item passed to ISR & DSR
eth_isr, // ISR
eth_drv_dsr, // DSR (generic)
&p_eth_upd985xx->interrupt_handle, // handle to intr obj
&p_eth_upd985xx->interrupt_object ); // space for int obj
 
cyg_drv_interrupt_attach(p_eth_upd985xx->interrupt_handle);
 
// Initialize upper level driver
if ( p_eth_upd985xx->mac_addr_ok )
(sc->funs->eth_drv->init)(sc, &(p_eth_upd985xx->mac_address[0]) );
else
(sc->funs->eth_drv->init)(sc, 0 );
return (1);
}
 
// ------------------------------------------------------------------------
//
// Function : eth_upd985xx_start
//
// ------------------------------------------------------------------------
STATIC void
eth_upd985xx_start( struct eth_drv_sc *sc,
unsigned char *enaddr, int flags )
{
struct eth_upd985xx *p_eth_upd985xx;
cyg_uint32 ss;
#ifdef CYGPKG_NET
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
#endif
 
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
 
#ifdef DEBUG
os_printf("eth_upd985xx_start %d flg %x\n", p_eth_upd985xx->index, *(int *)p_eth_upd985xx );
#endif
 
if ( p_eth_upd985xx->active )
eth_upd985xx_stop( sc );
 
p_eth_upd985xx->active = 1;
#ifdef CYGPKG_NET
/* Enable promiscuous mode if requested, reception of oversized frames always.
* The latter is needed for VLAN support and shouldn't hurt even if we're not
* using VLANs.
*/
eth_upd985xx_configure(p_eth_upd985xx, !!(ifp->if_flags & IFF_PROMISC), 1);
#endif
 
// renegotiate link status
p_eth_upd985xx->phy_status = eth_upd985xx_status( p_eth_upd985xx );
 
if ( p_eth_upd985xx->phy_status & PHY_STATUS_FDX ) {
cyg_uint32 ss;
// then enable full duplex in the MAC
ss = INL( ETH_MACC1 );
ss |= ETH_MACC1_FDX;
OUTL( ETH_MACC1, ss );
}
 
#ifdef DEBUG
{
int status = p_eth_upd985xx->phy_status;
os_printf("eth_upd985xx_start %d Link = %s, %s Mbps, %s Duplex\n",
p_eth_upd985xx->index,
status & PHY_STATUS_LINK ? "Up" : "Down",
status & PHY_STATUS_100MBPS ? "100" : "10",
status & PHY_STATUS_FDX ? "Full" : "Half"
);
}
#endif
 
 
// Start the receive engine
p_eth_upd985xx->count_rx_restart++;
// Initialize all but one buffer: [B0,B1,B2,...Bx,NULL,LINK]
InitRxRing( p_eth_upd985xx );
// Point the hardware at the list of buffers
OUTL( ETH_RXDPR, (cyg_uint32)p_eth_upd985xx->rxring_active );
// Tell it about the buffers via the rx descriptor count
OUTL( ETH_RXPDR, ETH_RXPDR_AL | (NUM_RXBUFS-1) );
// Ack any pending interrupts from the system
p_eth_upd985xx->intrs = INL( ETH_ISR ); // Read-clear
// Start the rx.
OUTL( ETH_RXCR, ETH_RXCR_RXE | ETH_RXCR_DRBS_16 );
 
// Enable the wet string end of the receiver
ss = INL( ETH_MACC1 );
ss |= ETH_MACC1_SRXEN;
OUTL( ETH_MACC1, ss );
 
// And unmask the interrupt
cyg_drv_interrupt_acknowledge(p_eth_upd985xx->vector);
cyg_drv_interrupt_unmask(p_eth_upd985xx->vector);
}
 
// ------------------------------------------------------------------------
//
// Function : eth_upd985xx_status; 10/100 and Full/Half Duplex (FDX/HDX)
//
// ------------------------------------------------------------------------
STATIC int eth_upd985xx_status( struct eth_upd985xx *p_eth_upd985xx )
{
int status;
int i, j;
// Some of these bits latch and only reflect "the truth" on a 2nd reading.
// So read and discard.
mii_read( PHY_CONTROL_REG, &i, p_eth_upd985xx );
mii_read( PHY_STATUS_REG, &i, p_eth_upd985xx );
// Use the "and" of the local and remote capabilities words to infer
// what is selected:
status = 0;
if ( mii_read( PHY_STATUS_REG, &i, p_eth_upd985xx ) ) {
if ( PHY_STATUS_LINK_OK & i )
status |= PHY_STATUS_LINK;
}
if ( mii_read( PHY_AUTONEG_ADVERT, &j, p_eth_upd985xx ) &&
mii_read( PHY_AUTONEG_REMOTE, &i, p_eth_upd985xx ) ) {
#if defined( DEBUG_TRAFFIC ) || defined( DEBUG_IOCTL )
os_printf( "MII: capabilities are %04x, %04x; common %04x\n",
i, j, i & j );
#endif
j &= i; // select only common capabilities
 
if ( (PHY_AUTONEG_100BASET4 |
PHY_AUTONEG_100BASETX_FDX |
PHY_AUTONEG_100BASETX_HDX) & j )
status |= PHY_STATUS_100MBPS;
if ( (PHY_AUTONEG_100BASETX_FDX | PHY_AUTONEG_10BASET_FDX) & j )
status |= PHY_STATUS_FDX;
}
return status;
}
 
// ------------------------------------------------------------------------
//
// Function : eth_upd985xx_stop
//
// ------------------------------------------------------------------------
 
STATIC void eth_upd985xx_stop( struct eth_drv_sc *sc )
{
struct eth_upd985xx *p_eth_upd985xx;
 
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
 
// No more interrupts
cyg_drv_interrupt_acknowledge(p_eth_upd985xx->vector);
cyg_drv_interrupt_mask(p_eth_upd985xx->vector);
 
#ifdef DEBUG
os_printf("eth_upd985xx_stop %d flg %x\n", p_eth_upd985xx->index, *(int *)p_eth_upd985xx );
#endif
 
p_eth_upd985xx->active = 0; // stop people tormenting it
 
if ( p_eth_upd985xx->tx_busy ) {
// Then it is finshed now, by force:
cyg_uint32 key = p_eth_upd985xx->tx_keys[ 0 ];
// Turn off the transmitter (before the callback to the stack).
OUTL( ETH_TXCR, 0 );
#ifdef DEBUG_TRAFFIC
os_printf("Stop: tidying up TX, KEY %x\n", key );
#endif
// Leave tx_busy true so no recursion can occur here.
// Then tell the stack we are done:
if ( key ) {
(sc->funs->eth_drv->tx_done)( sc, key, 0 );
}
}
p_eth_upd985xx->tx_keys[ 0 ] = 0;
p_eth_upd985xx->tx_busy = p_eth_upd985xx->active = 0;
 
eth_upd985xx_reset(p_eth_upd985xx);
 
ResetTxRing( p_eth_upd985xx );
}
 
 
// ------------------------------------------------------------------------
//
// Function : InitRxRing
//
// ------------------------------------------------------------------------
STATIC void InitRxRing(struct eth_upd985xx* p_eth_upd985xx)
{
int i;
struct bufdesc *bp;
 
// first just blat the various flags and addresses: the first N
// bufdescs point to data buffers, the last one is NULL.
bp = (struct bufdesc *)VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[0] );
// Record the initial active buffer:
p_eth_upd985xx->rxring_active = bp;
p_eth_upd985xx->rxring_active_index = 0;
for ( i = 0; i < NUM_RXBUFS - 1; i++, bp++ ) {
bp->ptr = VIRT_TO_BUS( &rx_databuf[i][0] );
bp->attr = ( ETH_BUF_D_L_DATA | ETH_BUF_OWN_CPU
| (ETH_BUF_SIZE & sizeof( rx_databuf[0] )) );
}
CYG_ASSERT( i == NUM_RXBUFS-1, "Penultimate rx buffer index mismatch" );
CYG_ASSERT( (cyg_uint8 *)bp ==
VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[NUM_RXBUFS-1] ),
"Penultimate rx buffer address mismatch" );
 
// NULL out the penultimate one
bp->ptr = NULL;
bp->attr = 0;
// And record it as next one to use
p_eth_upd985xx->rxring_next = bp;
p_eth_upd985xx->rxring_next_index = NUM_RXBUFS-1;
 
// Step on to the extra entry at the end which makes a ring:
bp++;
CYG_ASSERT( (cyg_uint8 *)bp ==
VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[NUM_RXBUFS] ),
"Ultimate rx buffer address mismatch" );
 
// Link the Ultimate back to the start
bp->ptr = (cyg_uint8 *)p_eth_upd985xx->rxring_active; // Zeroth entry
bp->attr = ETH_BUF_D_L_LINK;
 
// All done.
}
 
 
// ------------------------------------------------------------------------
//
// Function : NextRxRing
//
// ------------------------------------------------------------------------
 
STATIC void NextRxRing(struct eth_upd985xx* p_eth_upd985xx )
{
volatile struct bufdesc *next, *dead;
int iactive;
int inext;
 
iactive = p_eth_upd985xx->rxring_active_index;
inext = p_eth_upd985xx->rxring_next_index;
 
// Preconditions:
CYG_ASSERT( 0 <= inext && inext < NUM_RXBUFS, "Bad inext" );
CYG_ASSERT( 0 <= iactive && iactive < NUM_RXBUFS, "Bad iactive" );
CYG_ASSERT( VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[ inext ] )
== (cyg_uint8 *)p_eth_upd985xx->rxring_next, "Next rx_bufdesc bad" );
CYG_ASSERT( VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[ iactive ] )
== (cyg_uint8 *)p_eth_upd985xx->rxring_active, "Active rx_bufdesc bad" );
CYG_ASSERT( ETH_BUF_D_L_LINK == p_eth_upd985xx->rxring_next->attr, "Next not a link" );
CYG_ASSERT( ETH_BUF_D_L_DATA & p_eth_upd985xx->rxring_active->attr, "Active not data" );
CYG_ASSERT( NULL == p_eth_upd985xx->rxring_next->ptr, "Next not NULL" );
CYG_ASSERT( VIRT_TO_BUS( &rx_databuf[iactive][0] ) ==
p_eth_upd985xx->rxring_active->ptr, "Active bad data pointer" );
CYG_ASSERT( (iactive - 1 == inext) || (0 == iactive && NUM_RXBUFS - 1 == inext),
"Chasing pointers mismatch" );
 
// Select the new bufdesc to be active - ie. next to scan for reception:
if ( ++iactive >= NUM_RXBUFS )
iactive = 0;
dead = p_eth_upd985xx->rxring_active; // the one that just died
// Step ahead the new active buffer:
p_eth_upd985xx->rxring_active = (volatile struct bufdesc *)
VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[ iactive ] );
p_eth_upd985xx->rxring_active_index = iactive;
 
// Blow away the currently active entry; we have dealt with it already
// and it is needed for an end stop to the ring:
dead->ptr = NULL;
dead->attr = 0;
// Select the next bufdesc to enliven
next = p_eth_upd985xx->rxring_next;
next->ptr = VIRT_TO_BUS( &rx_databuf[inext][0] );
next->attr = ( ETH_BUF_D_L_DATA | ETH_BUF_OWN_CPU
| (ETH_BUF_SIZE & sizeof( rx_databuf[0] )) );
 
// And update the external info to reflect this:
if ( ++inext >= NUM_RXBUFS )
inext = 0;
next = (volatile struct bufdesc *)
VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[ inext ] );
 
p_eth_upd985xx->rxring_next = next;
p_eth_upd985xx->rxring_next_index = inext;
 
// Postconditions:
CYG_ASSERT( 0 <= inext && inext < NUM_RXBUFS, "Bad inext" );
CYG_ASSERT( 0 <= iactive && iactive < NUM_RXBUFS, "Bad iactive" );
CYG_ASSERT( VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[ inext ] )
== (cyg_uint8 *)p_eth_upd985xx->rxring_next, "Next rx_bufdesc bad" );
CYG_ASSERT( VIRT_TO_BUS( &p_eth_upd985xx->rx_bufdesc[ iactive ] )
== (cyg_uint8 *)p_eth_upd985xx->rxring_active, "Active rx_bufdesc bad" );
CYG_ASSERT( ETH_BUF_D_L_LINK == p_eth_upd985xx->rxring_next->attr, "Next not a link" );
CYG_ASSERT( ETH_BUF_D_L_DATA & p_eth_upd985xx->rxring_active->attr, "Active not data" );
CYG_ASSERT( NULL == p_eth_upd985xx->rxring_next->ptr, "Next not NULL" );
CYG_ASSERT( VIRT_TO_BUS( &rx_databuf[iactive][0] ) ==
p_eth_upd985xx->rxring_active->ptr, "Active bad data pointer" );
CYG_ASSERT( (iactive - 1 == inext) || (0 == iactive && NUM_RXBUFS - 1 == inext),
"Chasing pointers mismatch" );
}
 
// ------------------------------------------------------------------------
//
// Function : PacketRxReady (Called from delivery thread)
//
// ------------------------------------------------------------------------
STATIC void PacketRxReady(struct eth_upd985xx* p_eth_upd985xx)
{
struct cyg_netdevtab_entry *ndp;
struct eth_drv_sc *sc;
cyg_uint32 ss, length;
cyg_bool reset_required = 0;
 
ndp = (struct cyg_netdevtab_entry *)(p_eth_upd985xx->ndp);
sc = (struct eth_drv_sc *)(ndp->device_instance);
 
CHECK_NDP_SC_LINK();
 
#ifdef DEBUG_TRAFFIC
ss = INL( ETH_RXSR );
os_printf("PacketRxReady: RXSR %x\n", ss );
#endif
 
if ( ETH_ISR_RBDRU & p_eth_upd985xx->intrs )
reset_required = 1; // Out of buffers
if ( ! ETH_ISR_RCVDN & p_eth_upd985xx->intrs )
reset_required = 1; // or if no reception completed, reset anyway
 
// For all ready rx blocks...
do {
volatile struct bufdesc *bp;
 
bp = p_eth_upd985xx->rxring_active; // Current rx candidate
 
ss = bp->attr;
#ifdef DEBUG_TRAFFIC
os_printf("PacketRxReady attr %x at %x\n", ss, bp );
#endif
if ( ETH_BUF_OWN_CPU == (ETH_BUF_OWN & ss) ) {
// Then the packet is untouched...
break;
}
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2
// Perform address recognition by hand, hardware is in promisc mode
// (we have settable "software" promisc mode too of course)
if ( ETH_BUF_OK & ss ) {
cyg_uint8 *esa = (cyg_uint8 *)bp->ptr; // (this is a non-cachable address)
int ok = 0;
if ( p_eth_upd985xx->promisc )
ok = 1; // accept the packet
else
if ( p_eth_upd985xx->mac_address[0] == esa[0] &&
p_eth_upd985xx->mac_address[1] == esa[1] &&
p_eth_upd985xx->mac_address[2] == esa[2] &&
p_eth_upd985xx->mac_address[3] == esa[3] &&
p_eth_upd985xx->mac_address[4] == esa[4] &&
p_eth_upd985xx->mac_address[5] == esa[5] )
ok = 1; // Then they are equal - accept
else
if ( 0xff == esa[0] &&
0xff == esa[1] &&
0xff == esa[2] &&
0xff == esa[3] &&
0xff == esa[4] &&
0xff == esa[5] )
ok = 1; // Then they are equal - accept
 
if ( !ok )
ss = 0; // Easiest way...
}
#endif
if ( ETH_BUF_OK & ss ) {
length = ETH_BUF_SIZE & ss;
#ifdef DEBUG_TRAFFIC
os_printf("PacketRxReady found a packet size %d attr %x\n", length, ss );
#endif
// Asserts for the length in-range can fire, with good status
// in the block, so be defensive here instead. Belt and braces.
if ( 63 < length && length <= MAX_RX_PACKET_SIZE ) {
CYG_ASSERT( ETH_BUF_D_L_DATA == (ETH_BUF_D_L & ss), "Not data buffer" );
CYG_ASSERT( length > 63, "Tiny packet" );
CYG_ASSERT( length <= MAX_RX_PACKET_SIZE, "Too big packet" );
CYG_ASSERT( ETH_BUF_LAST & ss, "Not last buffer" );
(sc->funs->eth_drv->recv)( sc, length );
} // Else drop it on the floor.
}
 
// Step along to the next buffer descriptor...
NextRxRing( p_eth_upd985xx );
if ( ! reset_required ) {
// And tell the device it can have a biscuit:
OUTL( ETH_RXPDR, ETH_RXPDR_AL | 1 );
 
// Now, before moving on to the next packet, find out if receptions
// had caught up with us before adding that new buffer:
ss = INL( ETH_RXPDR );
ss &= ETH_RXPDR_RNOD;
ss >>= ETH_RXPDR_RNOD_SHIFT;
if ( 1 >= ss ) {
// Then it was zero before. So the rx engine is stopped.
#ifdef DEBUG_TRAFFIC
os_printf( "***ZERO rx buffers were left\n" );
#endif
reset_required = 1;
}
// Otherwise we carry on as usual.
}
} while ( 1 );
 
if ( reset_required ) {
p_eth_upd985xx->count_rx_resource++;
// Disable the wet string end of the receiver
ss = INL( ETH_MACC1 );
ss &=~ETH_MACC1_SRXEN;
OUTL( ETH_MACC1, ss );
// Disable the DMA engine
OUTL( ETH_RXCR, 0 );
// Reset the RxRing from scratch
InitRxRing( p_eth_upd985xx );
// Point the hardware at the list of buffers
OUTL( ETH_RXDPR, (cyg_uint32)p_eth_upd985xx->rxring_active );
// Tell it about the buffers via the rx descriptor count:
ss = INL( ETH_RXPDR );
ss &= ETH_RXPDR_RNOD;
ss >>= ETH_RXPDR_RNOD_SHIFT;
// This awful register *increments* by what you write, even if the
// machinery is halted. Vile filthy evil rubbish.
OUTL( ETH_RXPDR, ETH_RXPDR_AL | ((NUM_RXBUFS-1) - ss) );
ss = INL( ETH_RXPDR );
CYG_ASSERT( (ETH_RXPDR_AL | (NUM_RXBUFS-1)) == ss, "RXPDR not right" );
// Start the rx.
OUTL( ETH_RXCR, ETH_RXCR_RXE | ETH_RXCR_DRBS_16 );
// Enable the wet string end of the receiver
ss = INL( ETH_MACC1 );
ss |= ETH_MACC1_SRXEN;
OUTL( ETH_MACC1, ss );
// All done.
#ifdef DEBUG_TRAFFIC
os_printf( "***Rx Machine restarted\n" );
#endif
}
}
 
// and the callback function
 
STATIC void
eth_upd985xx_recv( struct eth_drv_sc *sc,
struct eth_drv_sg *sg_list, int sg_len )
{
struct eth_upd985xx *p_eth_upd985xx;
int total_len;
struct eth_drv_sg *last_sg;
cyg_uint8 *from_p;
volatile struct bufdesc *bp;
 
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
// Guard possible external entry points
if ( ! p_eth_upd985xx->active )
return;
 
bp = p_eth_upd985xx->rxring_active; // Current rx candidate
 
#ifdef DEBUG_TRAFFIC
os_printf("Rx status %x\n", bp->attr );
#endif
 
if ( 0 == (ETH_BUF_OK & bp->attr) )
return;
total_len = ETH_BUF_SIZE & bp->attr;
#ifdef DEBUG_TRAFFIC
os_printf("Rx %d %x (status %x): %d sg's, %d bytes\n",
p_eth_upd985xx->index, (int)p_eth_upd985xx,
bp->attr,
sg_len, total_len);
#endif
 
// Copy the data to the network stack
from_p = bp->ptr; // (this is a non-cachable address)
 
// check we have memory to copy into; we would be called even if
// caller was out of memory in order to maintain our state.
if ( 0 == sg_len || 0 == sg_list )
return; // caller was out of mbufs
 
CYG_ASSERT( 0 < sg_len, "sg_len underflow" );
CYG_ASSERT( MAX_ETH_DRV_SG >= sg_len, "sg_len overflow" );
 
for ( last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++ ) {
cyg_uint8 *to_p;
int l;
to_p = (cyg_uint8 *)(sg_list->buf);
l = sg_list->len;
 
CYG_ASSERT( 0 <= l, "sg length -ve" );
 
if ( 0 >= l || 0 == to_p )
return; // caller was out of mbufs
 
if ( l > total_len )
l = total_len;
 
memcpy( to_p, from_p, l );
from_p += l;
total_len -= l;
}
 
CYG_ASSERT( 0 == total_len, "total_len mismatch in rx" );
CYG_ASSERT( last_sg == sg_list, "sg count mismatch in rx" );
CYG_ASSERT( bp->ptr < from_p, "from_p wild in rx" );
CYG_ASSERT( bp->ptr + MAX_RX_PACKET_SIZE >= from_p,
"from_p overflow in rx" );
}
 
 
// ------------------------------------------------------------------------
//
// Function : InitTxRing
//
// ------------------------------------------------------------------------
STATIC void InitTxRing(struct eth_upd985xx* p_eth_upd985xx)
{
int i;
volatile struct bufdesc *bp;
p_eth_upd985xx->txring =
(struct bufdesc *)VIRT_TO_BUS( &p_eth_upd985xx->tx_bufdesc[0] );
 
bp = p_eth_upd985xx->txring;
 
for ( i = 0; i < NUM_ELEMENTS( p_eth_upd985xx->tx_bufdesc ); i++, bp++ ) {
bp->ptr = NULL;
bp->attr = 0;
}
// Last one is a NULL link
bp--;
bp->ptr = NULL;
bp->attr = ETH_BUF_D_L_LINK;
 
ResetTxRing(p_eth_upd985xx);
}
 
// ------------------------------------------------------------------------
//
// Function : ResetTxRing
//
// ------------------------------------------------------------------------
STATIC void ResetTxRing(struct eth_upd985xx* p_eth_upd985xx)
{
int i;
volatile struct bufdesc *bp;
bp = p_eth_upd985xx->txring;
for ( i = 0; i < NUM_ELEMENTS( p_eth_upd985xx->tx_bufdesc ) - 1; i++, bp++ ) {
bp->attr =
ETH_BUF_LAST |
ETH_BUF_D_L_DATA |
ETH_BUF_OWN_CPU |
(ETH_BUF_SIZE & 0);
}
}
 
// ------------------------------------------------------------------------
//
// Function : TxDone (Called from delivery thread)
//
// This returns Tx's from the Tx Machine to the stack (ie. reports
// completion) - allowing for missed interrupts, and so on.
// ------------------------------------------------------------------------
 
STATIC void TxDone(struct eth_upd985xx* p_eth_upd985xx)
{
struct cyg_netdevtab_entry *ndp;
struct eth_drv_sc *sc;
 
ndp = (struct cyg_netdevtab_entry *)(p_eth_upd985xx->ndp);
sc = (struct eth_drv_sc *)(ndp->device_instance);
 
CHECK_NDP_SC_LINK();
 
if ( p_eth_upd985xx->tx_busy ) {
cyg_uint32 ss;
 
ss = INL( ETH_TXSR ); // Get tx status
if ( ss & (ETH_TXSR_CSE |
ETH_TXSR_TUDR |
ETH_TXSR_TGNT |
ETH_TXSR_LCOL |
ETH_TXSR_ECOL |
ETH_TXSR_TEDFR |
ETH_TXSR_TDFR |
ETH_TXSR_TBRO |
ETH_TXSR_TMUL |
ETH_TXSR_TDONE ) ) {
// Then it finished; somehow...
cyg_uint32 key = p_eth_upd985xx->tx_keys[ 0 ];
// Turn off the transmitter (before the callback to the stack).
OUTL( ETH_TXCR, 0 );
 
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E8
// Must take action after certain types of tx failure:
if ( ss & (ETH_TXSR_TUDR |
ETH_TXSR_LCOL |
ETH_TXSR_ECOL) ) {
p_eth_upd985xx->count_bad_tx_completion++;
CYG_ASSERT ( p_eth_upd985xx->active, "Device not active!" );
eth_upd985xx_stop( sc );
eth_upd985xx_start( sc, NULL, 0 );
key = 0; // Important! Stop above already fed it back.
}
#endif
 
#ifdef DEBUG_TRAFFIC
os_printf("TxDone %d %x: KEY %x\n",
p_eth_upd985xx->index, (int)p_eth_upd985xx, key );
#endif
// Finished, ready for the next one
p_eth_upd985xx->tx_keys[ 0 ] = 0;
p_eth_upd985xx->tx_busy = 0;
// Then tell the stack we are done:
if (key) {
(sc->funs->eth_drv->tx_done)( sc, key,
0 == (p_eth_upd985xx->intrs & ETH_ISR_TABR) );
}
}
}
}
 
 
// ------------------------------------------------------------------------
//
// Function : eth_upd985xx_can_send
//
// ------------------------------------------------------------------------
 
STATIC int
eth_upd985xx_can_send(struct eth_drv_sc *sc)
{
struct eth_upd985xx *p_eth_upd985xx;
 
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
 
// Guard possible external entry points
if ( ! p_eth_upd985xx->active )
return 0;
 
return ! p_eth_upd985xx->tx_busy;
}
 
// ------------------------------------------------------------------------
//
// Function : eth_upd985xx_send
//
// ------------------------------------------------------------------------
 
STATIC void
eth_upd985xx_send(struct eth_drv_sc *sc,
struct eth_drv_sg *sg_list, int sg_len, int total_len,
unsigned long key)
{
struct eth_upd985xx *p_eth_upd985xx;
struct eth_drv_sg *last_sg;
volatile struct bufdesc *bp;
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E3
struct eth_drv_sg local_sg[2];
#endif
 
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
 
#ifdef DEBUG_TRAFFIC
os_printf("Tx %d %x: %d sg's, %d bytes, KEY %x\n",
p_eth_upd985xx->index, (int)p_eth_upd985xx, sg_len, total_len, key );
#endif
 
if ( ! p_eth_upd985xx->active )
return; // device inactive, no return
CYG_ASSERT( ! p_eth_upd985xx->tx_busy, "Can't send when busy!" );
 
p_eth_upd985xx->tx_busy++;
 
p_eth_upd985xx->tx_keys[0] = key;
bp = &p_eth_upd985xx->txring[0]; // Current free tx
CYG_ASSERT( 0 < sg_len, "sg_len underflow" );
CYG_ASSERT( MAX_ETH_DRV_SG >= sg_len, "sg_len overflow" );
 
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E3
// We must copy any Tx that is more than two SGs into just one buffer.
if ( sg_len > 2 ) {
cyg_uint8 *from_p, *to_p;
to_p = &tx_databuf[0]; // normal cached address
if ( sizeof( tx_databuf ) < total_len )
total_len = sizeof( tx_databuf );
for ( last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++ ) {
int l;
 
from_p = (cyg_uint8 *)(sg_list->buf); // normal cached address
l = sg_list->len;
if ( l > total_len )
l = total_len;
 
memcpy( to_p, from_p, l ); // All in cached memory
to_p += l;
total_len -= l;
 
if ( 0 > total_len )
break; // Should exit via sg_last normally
}
 
// Set up SGs describing the single tx buffer
total_len = to_p - &tx_databuf[0];
local_sg[0].buf = (CYG_ADDRESS)&tx_databuf[0];
local_sg[0].len = (CYG_ADDRWORD)total_len;
local_sg[1].buf = (CYG_ADDRESS)0;
local_sg[1].len = (CYG_ADDRWORD)0;
 
// And make the subsequent code use it.
sg_len = 1;
sg_list = &local_sg[0];
}
#endif
 
for ( last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++ ) {
cyg_uint8 *from_p;
int l;
from_p = (cyg_uint8 *)(sg_list->buf); // normal cached address
l = sg_list->len;
 
if ( l > total_len )
l = total_len;
 
// Ensure the mbuf contents really is in RAM where DMA can see it.
// (Must round to cache lines apparantly for 4120)
HAL_DCACHE_STORE( ((CYG_ADDRESS)from_p) &~(HAL_DCACHE_LINE_SIZE-1),
l + HAL_DCACHE_LINE_SIZE );
bp->ptr = VIRT_TO_BUS( from_p ); // uncached real RAM address
bp->attr &=~(ETH_BUF_LAST | ETH_BUF_SIZE);
bp->attr |= ETH_BUF_SIZE & l;
bp->attr |= ETH_BUF_D_L_DATA;
 
total_len -= l;
bp++;
 
if ( 0 > total_len )
break; // Should exit via sg_last normally
}
 
CYG_ASSERT( bp > &p_eth_upd985xx->txring[0], "bp underflow" );
CYG_ASSERT( bp < &p_eth_upd985xx->txring[
NUM_ELEMENTS(p_eth_upd985xx->tx_bufdesc)
], "bp underflow" );
 
bp--;
bp->attr |= ETH_BUF_LAST;
 
// Make the rest be null links
for ( bp++; bp <
&p_eth_upd985xx->txring[NUM_ELEMENTS(p_eth_upd985xx->tx_bufdesc)];
bp++ ) {
bp->attr = ETH_BUF_D_L_LINK;
bp->ptr = NULL;
}
 
CYG_ASSERT( 0 == total_len, "length mismatch in tx" );
CYG_ASSERT( last_sg == sg_list, "sg count mismatch in tx" );
 
// And start off the tx system
 
// Point the hardware at the list of buffers
OUTL( ETH_TXDPR, (cyg_uint32)p_eth_upd985xx->txring );
// and start the tx.
 
// Fault E4 - use only 8 for DTBS, not the previously recommended 16.
// Tag: CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E4
// but no config opt is provided.
 
// Fault E7: ETH_TXCR_AFCE must not be used.
// Tag: CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E7
// but no config opt is provided.
 
OUTL( ETH_TXCR, ETH_TXCR_TXE | ETH_TXCR_DTBS_8 /* | ETH_TXCR_AFCE */ );
}
 
#ifdef CYGPKG_NET
// ------------------------------------------------------------------------
//
// Function : eth_upd985xx_configure
//
// Return : 0 = It worked.
// non0 = It failed.
// ------------------------------------------------------------------------
 
STATIC int
eth_upd985xx_configure(struct eth_upd985xx* p_eth_upd985xx, int promisc, int oversized)
{
int ss;
 
// We implement permission of oversize packets by changing LMAX (rather
// than enabling HUGEN in ETH_MACC1) because we rely on only one
// reception per rx descriptor. General oversize packets could eat
// many rx descriptors and we would become ...confused.
 
// Sanity check the numbers we're about to use.
CYG_ASSERT( sizeof( rx_databuf[0] ) >= MAX_OVERSIZE_PACKET_SIZE,
"Oversize packet would overflow rx buffer" );
CYG_ASSERT( sizeof( rx_databuf[0] ) >= MAX_ETHERNET_PACKET_SIZE,
"Ethernet packet would overflow rx buffer" );
if ( oversized )
OUTL( ETH_LMAX, MAX_OVERSIZE_PACKET_SIZE );
else
OUTL( ETH_LMAX, MAX_ETHERNET_PACKET_SIZE );
 
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2
ss = promisc ? 1 : 0; // avoid unused var warning
p_eth_upd985xx->promisc = ss;
#ifdef CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2_E2ONLY
// Then we must also set the mode in the chip
ss = INL( ETH_AFR );
if ( promisc )
ss |= ETH_AFR_PRO;
else
ss &=~ETH_AFR_PRO;
OUTL( ETH_AFR, ss );
#endif // CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2_E2ONLY
#else
ss = INL( ETH_AFR );
if ( promisc )
ss |= ETH_AFR_PRO;
else
ss &=~ETH_AFR_PRO;
OUTL( ETH_AFR, ss );
#endif
return 0; // OK
}
#endif
 
// ------------------------------------------------------------------------
//
// Function : eth_upd985xx_ioctl
//
// ------------------------------------------------------------------------
STATIC int
eth_upd985xx_ioctl(struct eth_drv_sc *sc, unsigned long key,
void *data, int data_length)
{
struct eth_upd985xx *p_eth_upd985xx;
 
p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;
 
#ifdef DEBUG_IOCTL
db_printf( "eth_upd985xx_ioctl: device eth%d at %x; key is 0x%x, data at %x[%d]\n",
p_eth_upd985xx->index, p_eth_upd985xx, key, data, data_length );
#endif
 
// DO NOT guard possible external entry points - want to be able eg. to
// set a mac address of a down interface before bringing it up!
 
switch ( key ) {
 
#ifdef ETH_DRV_SET_MAC_ADDRESS
case ETH_DRV_SET_MAC_ADDRESS:
if ( 6 != data_length )
return -2;
return eth_set_mac_address( p_eth_upd985xx, data );
#endif
 
#ifdef ETH_DRV_GET_IF_STATS_UD
case ETH_DRV_GET_IF_STATS_UD: // UD == UPDATE
#endif
// drop through
#ifdef ETH_DRV_GET_IF_STATS
case ETH_DRV_GET_IF_STATS:
#endif
#if defined(ETH_DRV_GET_IF_STATS) || defined (ETH_DRV_GET_IF_STATS_UD)
{
struct ether_drv_stats *p = (struct ether_drv_stats *)data;
int i;
 
// Chipset entry is no longer supported; RFC1573.
for ( i = 0; i < SNMP_CHIPSET_LEN; i++ )
p->snmp_chipset[i] = 0;
 
// This perhaps should be a config opt, so you can make up your own
// description, or supply it from the instantiation.
strcpy( p->description, "NEC uPD985xx on-chip ethernet (CANDY)" );
// CYG_ASSERT( 48 > strlen(p->description), "Description too long" );
 
i = eth_upd985xx_status( p_eth_upd985xx );
 
if ( !( i & PHY_STATUS_LINK) ) {
p->operational = 2; // LINK DOWN
p->duplex = 1; // UNKNOWN
p->speed = 0;
}
else {
p->operational = 3; // LINK UP
p->duplex = (i & PHY_STATUS_FDX) ? 3 : 2; // 2 = SIMPLEX, 3 = DUPLEX
p->speed = ((i & PHY_STATUS_100MBPS) ? 100 : 10) * 1000000;
}
 
// Admit to it...
p->supports_dot3 = true;
 
// Those commented out are not available on this chip.
p->tx_good = INL( ETH_TPCT ) ;
p->tx_max_collisions = INL( ETH_TXCL ) ;
p->tx_late_collisions = INL( ETH_TLCL ) ;
//p->tx_underrun = INL( ) ;
p->tx_carrier_loss = INL( ETH_TCSE ) ;
p->tx_deferred = INL( ETH_TDFR ) +
INL( ETH_TXDF ) ;
//p->tx_sqetesterrors = INL( ) ;
p->tx_single_collisions = INL( ETH_TSCL ) ;
p->tx_mult_collisions = INL( ETH_TMCL ) ;
p->tx_total_collisions = INL( ETH_TSCL ) +
INL( ETH_TMCL ) +
INL( ETH_TLCL ) +
INL( ETH_TXCL ) ;
p->rx_good = INL( ETH_RPKT ) ;
p->rx_crc_errors = INL( ETH_RFCS ) ;
p->rx_align_errors = INL( ETH_RALN ) ;
p->rx_resource_errors = p_eth_upd985xx->count_rx_resource;
//p->rx_overrun_errors = INL( ) ;
//p->rx_collisions = INL( ) ;
p->rx_short_frames = INL( ETH_RUND ) ;
p->rx_too_long_frames = INL( ETH_ROVR ) ;
p->rx_symbol_errors = INL( ETH_RXUO ) ;
 
p->interrupts = p_eth_upd985xx->count_interrupts;
p->rx_count = INL( ETH_RBYT ) ;
p->rx_deliver = INL( ETH_RPKT ) ;
p->rx_resource = p_eth_upd985xx->count_rx_resource;
p->rx_restart = p_eth_upd985xx->count_rx_resource +
p_eth_upd985xx->count_rx_restart;
p->tx_count = INL( ETH_TBYT ) ;
p->tx_complete = INL( ETH_TPCT ) ;
p->tx_dropped = INL( ETH_TNCL ) ;
p->tx_queue_len = 1;
return 0; // OK
}
#endif
 
default:
break;
}
return -1;
}
 
// ------------------------------------------------------------------------
 
// EOF if_upd985xx.c

powered by: WebSVN 2.1.0

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