Mercurial > flash_v2
changeset 1255:ab4f9f4b92ce
Add DP83816 ethernet driver - used by TAMS MOAB
| author | gthomas |
|---|---|
| date | Tue, 30 Sep 2003 15:25:30 +0000 |
| parents | 29e672adfc06 |
| children | 05c5347d5941 |
| files | packages/ChangeLog packages/devs/eth/ns/dp83816/current/ChangeLog packages/devs/eth/ns/dp83816/current/cdl/ns_dp83816_eth_drivers.cdl packages/devs/eth/ns/dp83816/current/src/dp83816.h packages/devs/eth/ns/dp83816/current/src/if_dp83816.c packages/devs/eth/powerpc/moab/current/ChangeLog packages/devs/eth/powerpc/moab/current/cdl/moab_eth_drivers.cdl packages/devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl packages/ecos.db packages/hal/powerpc/moab/current/ChangeLog packages/hal/powerpc/moab/current/include/plf_io.h |
| diffstat | 11 files changed, 1045 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,7 @@ +2003-09-30 Gary Thomas <gary@mlbassoc.com> + + * ecos.db: New package - National Semiconductor DP83816 PCI ethernet + 2003-09-19 Gary Thomas <gary@mlbassoc.com> * ecos.db:
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/ns/dp83816/current/ChangeLog @@ -0,0 +1,44 @@ +2003-09-30 Gary Thomas <gary@mlbassoc.com> + + * src/if_dp83816.c: + * src/dp83816.h: + * cdl/ns_dp83816_eth_drivers.cdl: New package - ethernet driver for + National Semiconductor DP83816 PCI + +//=========================================================================== +//####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#### +//=========================================================================== + + +
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/ns/dp83816/current/cdl/ns_dp83816_eth_drivers.cdl @@ -0,0 +1,87 @@ +# ==================================================================== +# +# ns_dp83816_eth_drivers.cdl +# +# Ethernet drivers - device support for NS DP83816 Ethernet +# +# ==================================================================== +#####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 Gary Thomas +## +## 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): gthomas +# Contributors: +# Date: 2003-09-29 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_NS_DP83816 { + display "NS DP83816 ethernet drivers" + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + + implements CYGHWR_NET_DRIVERS + + active_if CYGINT_DEVS_ETH_NS_DP83816_REQUIRED + + include_dir cyg/io + description "Ethernet driver for NS DP83816 ethernet controller." + compile -library=libextras.a if_dp83816.c + + define_proc { + puts $::cdl_header "#include <pkgconf/system.h>"; + puts $::cdl_header "#include CYGDAT_DEVS_ETH_NS_DP83816_CFG"; + } + + cdl_component CYGPKG_DEVS_ETH_NS_DP83816_OPTIONS { + display "DP83816 ethernet driver build options" + flavor none + no_define + + cdl_option CYGPKG_DEVS_ETH_NS_DP83816_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 National Semiconductor (DP839x) ethernet driver package. + These flags are used in addition to the set of global flags." + } + } +}
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/ns/dp83816/current/src/dp83816.h @@ -0,0 +1,273 @@ +//========================================================================== +// +// dev/dp83816.h +// +// National Semiconductor DP83816 ethernet chip +// +//========================================================================== +//####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 Gary Thomas +// +// 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): gthomas +// Contributors: +// Date: 2003-09-29 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <cyg/hal/hal_io.h> +#include <pkgconf/devs_eth_ns_dp83816.h> + +// ------------------------------------------------------------------------ +// Debugging details + +// Set to perms of: +// 0 disables all debug output +// 1 for process debug output +// 2 for added data IO output: get_reg, put_reg +// 4 for packet allocation/free output +// 8 for only startup status, so we can tell we're installed OK +#define DEBUG 0x0 + +#if DEBUG & 1 +#define DEBUG_FUNCTION() do { diag_printf("%s\n", __FUNCTION__); } while (0) +#define DEBUG_LINE() do { diag_printf("%d\n", __LINE__); } while (0) +#else +#define DEBUG_FUNCTION() do {} while(0) +#define DEBUG_LINE() do {} while(0) +#endif + +// ------------------------------------------------------------------------ +// Buffer descriptors +typedef struct dp83816_bd { + struct dp83816_bd *next; // Next descriptor + unsigned long stat; // Buffer status & flags + unsigned char *buf; // Buffer memory + unsigned long key; // Internal use only +} dp83816_bd_t; + +// ------------------------------------------------------------------------ +// Private driver structure +typedef struct dp83816_priv_data { + char *esa_key; // RedBoot 'key' for device ESA + unsigned char enaddr[6]; + int rxnum; // Number of Rx buffers + unsigned char *rxbuf; // Rx buffer space + dp83816_bd_t *rxd; // Rx descriptor pool + int txnum; // Number of Tx buffers + unsigned char *txbuf; // Tx buffer space + dp83816_bd_t *txd; // Tx descriptor pool + cyg_uint8 *base; + int interrupt; // Interrupt vector +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED + cyg_handle_t interrupt_handle; + cyg_interrupt interrupt_object; +#endif + dp83816_bd_t *rxnext; // Next Rx to interrupt + dp83816_bd_t *txfill; // Next Tx to fill + dp83816_bd_t *txint; // Next Tx to interrupt + int txbusy; // Number of busy Tx buffers +} dp83816_priv_data_t; + +// ------------------------------------------------------------------------ +// Macros for accessing DP registers +// These can be overridden by the platform header +// Note: the only accesses used must be 32 bit little endian. + +#ifndef DP_IN +# define DP_IN(_b_, _o_, _d_) HAL_READ_UINT32((cyg_addrword_t)(_b_)+(_o_), (_d_)) +# define DP_OUT(_b_, _o_, _d_) HAL_WRITE_UINT32((cyg_addrword_t)(_b_)+(_o_), (_d_)) +#endif + +// ------------------------------------------------------------------------ +// Macros allowing platform to customize some of the driver details + +#ifndef CYGHWR_NS_DP83816_PLF_RESET +# define CYGHWR_NS_DP83816_PLF_RESET(_b_) do { } while (0) +#endif + +#ifndef CYGHWR_NS_DP83816_PLF_INT_CLEAR +# define CYGHWR_NS_DP83816_PLF_INT_CLEAR(_dp_) +#endif + +#ifndef CYGHWR_NS_DP83816_PLF_INIT +#define CYGHWR_NS_DP83816_PLF_INIT(dp) do { } while (0) +#endif + + +// ------------------------------------------------------------------------ +// Some forward declarations +static void dp83816_poll(struct eth_drv_sc *sc); + +// ------------------------------------------------------------------------ +// Register offsets + +#define DP_CR 0x00 // Command register +#define _CR_RST 0x100 // Chip reset +#define _CR_RXR 0x020 // Rx reset +#define _CR_TXR 0x010 // Tx reset +#define _CR_RXD 0x008 // Rx disable +#define _CR_RXE 0x004 // Rx enable +#define _CR_TXD 0x002 // Tx disable +#define _CR_TXE 0x001 // Tx enable +#define DP_CFG 0x04 // Configuration register +#define _CFG_LNKSTS (1<<31) // Link status +#define _CFG_SPD100 (1<<30) // 100Mb +#define _CFG_FDUP (1<<29) // Full duplex +#define _CFG_POL (1<<28) // 10Mb polarity +#define _CFG_ANDONE (1<<27) // Auto-negotiation done +#define DP_ISR 0x10 // Interrupt status +#define _ISR_TXRCMP (1<<25) // Tx reset complete +#define _ISR_RXRCMP (1<<24) // Rx reset complete +#define _ISR_DPERR (1<<23) // Detected parity error +#define _ISR_SSERR (1<<22) // Signalled system error +#define _ISR_RMABT (1<<21) // Received master abort +#define _ISR_RTABT (1<<20) // Received target abort +#define _ISR_RXSOVR (1<<16) // Rx status FIFO overrun +#define _ISR_HIBERR (1<<15) // High bits set (25-16) +#define _ISR_PHY (1<<14) // PHY interrupt +#define _ISR_PME (1<<13) // Power management event +#define _ISR_SWI (1<<12) // Software interrpt +#define _ISR_MIB (1<<11) // MII service +#define _ISR_TXURN (1<<10) // Tx underrun +#define _ISR_TXIDLE (1<<9) // Tx idle (end of list) +#define _ISR_TXERR (1<<8) // Tx packet error +#define _ISR_TXDESC (1<<7) // Tx descriptor with INTS +#define _ISR_TXOK (1<<6) // Last Tx descriptor done +#define _ISR_RXORN (1<<5) // Rx overrun +#define _ISR_RXIDLE (1<<4) // Rx idle (end of list) +#define _ISR_RXEARLY (1<<3) // Rx early threshold met +#define _ISR_RXERR (1<<2) // Rx packet error +#define _ISR_RXDESC (1<<1) // Rx descriptor with INTS +#define _ISR_RXOK (1<<0) // Last Rx descriptor done +#define DP_IMR 0x14 // Interrupt mask +#define DP_IER 0x18 // Interrupt enable +#define DP_IHR 0x1C // Interrupt hold +#define DP_TXDP 0x20 // Tx descriptor pointer +#define DP_TXCFG 0x24 // Tx configuration +#define _TXCFG_CSI (1<<31) // Ignore carrier sense +#define _TXCFG_HBI (1<<30) // Ignore heartbeat +#define _TXCFG_MLB (1<<29) // Loopback +#define _TXCFG_ATP (1<<28) // Automatic padding +#define _TXCFG_ECRTRY (1<<23) // Excessive collision enable +#define _TXCFG_MXDMA_SHIFT 20 +#define _TXCFG_MXDMA_MASK 0x7 +#define _TXCFG_MXDMA_512 (0x0<<20) +#define _TXCFG_MXDMA_4 (0x1<<20) +#define _TXCFG_MXDMA_8 (0x2<<20) +#define _TXCFG_MXDMA_16 (0x3<<20) +#define _TXCFG_MXDMA_32 (0x4<<20) +#define _TXCFG_MXDMA_64 (0x5<<20) +#define _TXCFG_MXDMA_128 (0x6<<20) +#define _TXCFG_MXDMA_256 (0x7<<20) +#define _TXCFG_FLTH_SHIFT 8 +#define _TXCFG_FLTH_MASK 0x3F +#define _TXCFG_DRTH_SHIFT 0 +#define _TXCFG_DRTH_MASK 0x3F +#define DP_RXDP 0x30 // Rx descriptor pointer +#define DP_RXCFG 0x34 // Rx configuration +#define _RXCFG_AEP (1<<31) // Accept error packets +#define _RXCFG_ARP (1<<30) // Accept runt packets +#define _RXCFG_ATX (1<<28) // Accept Tx packets (loopback) +#define _RXCFG_ALP (1<<27) // Accpet long packets (> 1518 bytes) +#define _RXCFG_MXDMA_SHIFT 20 +#define _RXCFG_MXDMA_MASK 0x7 +#define _RXCFG_MXDMA_512 (0x0<<20) +#define _RXCFG_MXDMA_4 (0x1<<20) +#define _RXCFG_MXDMA_8 (0x2<<20) +#define _RXCFG_MXDMA_16 (0x3<<20) +#define _RXCFG_MXDMA_32 (0x4<<20) +#define _RXCFG_MXDMA_64 (0x5<<20) +#define _RXCFG_MXDMA_128 (0x6<<20) +#define _RXCFG_MXDMA_256 (0x7<<20) +#define _RXCFG_FLTH_SHIFT 8 +#define _RXCFG_FLTH_MASK 0x3F +#define _RXCFG_DRTH_SHIFT 0 +#define _RXCFG_DRTH_MASK 0x3F +#define DP_RFCR 0x48 // Receive filter control +#define _RFCR_RFEN (1<<31) // Rx filter enable +#define _RFCR_AAB (1<<30) // Accept all broadcast +#define _RFCR_AAM (1<<29) // Accept all multicast +#define _RFCR_AAU (1<<28) // Accept all unicast +#define _RFCR_APM (1<<27) // Accept on perfect match +#define _RFCR_APAT (1<<26) // Accept on patern match +#define _RFCR_AARP (1<<22) // Accept ARP +#define _RFCR_MHEN (1<<21) // Multicast hash enable +#define _RFCR_UHEN (1<<20) // Unicast hash enable +#define _RFCR_ULM (1<<19) // U/L bit ignore +#define DP_RFDR 0x4C // Receive filter data register + +// Buffer descriptor status/flags +#define BD_OWN (1<<31) // Owned by producer (Tx=driver, Rx=DP83816) +#define BD_MORE (1<<30) // More descriptors in this frame +#define BD_INTR (1<<29) // Interrupt when this descriptor processed +#define BD_CRC (1<<28) // Include CRC +#define BD_OK (1<<27) // Packet OK +// Tx buffer flags +#define BD_TXA (1<<26) // Tx abort +#define BD_TFU (1<<25) // Tx underrun +#define BD_CRS (1<<24) // Carrier sense lost +#define BD_TD (1<<23) // Transmission deferred +#define BD_ED (1<<22) // Excessive Tx deferrals +#define BD_OWC (1<<21) // Out of window collision +#define BD_EC (1<<20) // Excessive collisions +#define BD_CCNT_MASK 0x0F +#define BD_CCNT_SHIFT 16 // Collision count +// Rx buffer flags +#define BD_RXA (1<<26) // Rx abort +#define BD_RXO (1<<25) // Rx overrun +#define BD_DEST_MASK (3<<23) +#define BD_DEST_REJECT (0<<23) // Packet rejected +#define BD_DEST_UNICAST (1<<23) // Unicast packet +#define BD_DEST_MULTICAST (2<<23) // Multicast packet +#define BD_DEST_BROADCAST (3<<23) // Broadcast packet +#define BD_LONG (1<<22) // Too long packet received +#define BD_RUNT (1<<21) // Runt packet +#define BD_ISE (1<<20) // Illegal symbol +#define BD_CRCE (1<<19) // CRC error +#define BD_FAE (1<<18) // Frame alignment error +#define BD_LBP (1<<17) // Loopback frame +#define BD_COL (1<<16) // Collision during frame +// Length field +#define BD_LENGTH_MASK 0x0FFF + +#define IEEE_8023_MAX_FRAME 1518 // Largest possible ethernet frame +#define IEEE_8023_MIN_FRAME 64 // Smallest possible ethernet frame + +#define _DP83816_BUFSIZE 1540 // Size of buffers
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c @@ -0,0 +1,399 @@ +//========================================================================== +// +// dev/if_dp83816.c +// +// Ethernet device driver for NS DP83816 ethernet controller +// +//========================================================================== +//####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): gthomas +// Contributors: +// Date: 2003-09-29 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/io_eth_drivers.h> + +#include <cyg/infra/cyg_type.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/infra/diag.h> +#include <cyg/hal/drv_api.h> +#include <cyg/hal/hal_if.h> +#include <cyg/io/eth/eth_drv.h> +#include <cyg/io/eth/netdev.h> + +#include "dp83816.h" +#include CYGDAT_DEVS_ETH_NS_DP83816_INL + +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED +// This ISR is called when the ethernet interrupt occurs +static cyg_uint32 +dp83816_isr(cyg_vector_t vector, cyg_addrword_t data) +{ + struct eth_drv_sc *sc = (struct eth_drv_sc *)data; + dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private; + + DEBUG_FUNCTION(); + + cyg_drv_interrupt_mask(dp->interrupt); + cyg_drv_interrupt_acknowledge(dp->interrupt); + return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR +} +#endif // CYGINT_IO_ETH_INT_SUPPORT_REQUIRED + +// The deliver function (ex-DSR) handles the ethernet [logical] processing +static void +dp83816_deliver(struct eth_drv_sc *sc) +{ +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED + dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private; +#endif + + DEBUG_FUNCTION(); + + // Service the interrupt: + dp83816_poll(sc); +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED + // Allow interrupts to happen again + cyg_drv_interrupt_unmask(dp->interrupt); +#endif +} + +static bool +dp83816_init(struct cyg_netdevtab_entry *tab) +{ + struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; + dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private; + cyg_uint8 *base; + cyg_uint32 stat; + dp83816_bd_t *bdp; + unsigned char *bp; + int i, timeout; + bool esa_ok; + unsigned char enaddr[6]; + + // Get physical device address +#ifdef CYGPKG_REDBOOT +#ifdef CYGSEM_REDBOOT_FLASH_CONFIG + esa_ok = flash_get_config(dp->esa_key, enaddr, CONFIG_ESA); +#else + esa_ok = false; +#endif +#else + esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, + dp->esa_key, enaddr, CONFIG_ESA); +#endif + if (!esa_ok) { + // Can't figure out ESA + diag_printf("DP83816 - Warning! ESA unknown\n"); + memcpy(&enaddr, dp->enaddr, sizeof(enaddr)); + } + + DEBUG_FUNCTION(); + + CYGHWR_NS_DP83816_PLF_INIT(dp); + base = dp->base; + if (!base) return false; // No device found + + DP_OUT(base, DP_CR, _CR_RST); // Reset device + timeout = 10000; + do { + DP_IN(base, DP_CR, stat); + } while (((stat & _CR_RST) != 0) && (--timeout > 0)); + if (timeout == 0) { + diag_printf("DP83816 - reset timed out! - stat: %x\n", stat); + return false; + } + // Rx ring + bdp = dp->rxnext = CYGARC_UNCACHED_ADDRESS(dp->rxd); + bp = dp->rxbuf; + for (i = 0; i < dp->rxnum; i++, bdp++) { + bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(bdp+1)); + bdp->stat = _h2le(BD_INTR | _DP83816_BUFSIZE); // Max buffer + bdp->buf = (unsigned char *)_h2le(CYGARC_PHYSICAL_ADDRESS(bp)); + bp += _DP83816_BUFSIZE; + } + bdp--; bdp->next = (dp83816_bd_t *)0; + DP_OUT(dp->base, DP_RXCFG, _RXCFG_MXDMA_128 | ((64/32)<<_RXCFG_DRTH_SHIFT)); + DP_OUT(dp->base, DP_RXDP, CYGARC_PHYSICAL_ADDRESS(dp->rxd)); + // Tx ring + bdp = dp->txfill = dp->txint = CYGARC_UNCACHED_ADDRESS(dp->txd); + bp = dp->txbuf; + for (i = 0; i < dp->txnum; i++, bdp++) { + bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(bdp+1)); + bdp->stat = 0; // Driver owns buffer for now + bdp->buf = (unsigned char *)_h2le(CYGARC_PHYSICAL_ADDRESS(bp)); + bp += _DP83816_BUFSIZE; + } + bdp--; bdp->next = (dp83816_bd_t *)0; + DP_OUT(dp->base, DP_TXCFG, _TXCFG_ATP | + _TXCFG_MXDMA_128 | + ((256/32)<<_TXCFG_FLTH_SHIFT) | + ((512/32)<<_TXCFG_DRTH_SHIFT)); + DP_OUT(dp->base, DP_TXDP, CYGARC_PHYSICAL_ADDRESS(dp->txd)); + dp->txbusy = 0; + // Fill in ESA + for (i = 0; i < 6; i+=2) { + DP_OUT(dp->base, DP_RFCR, i); + DP_OUT(dp->base, DP_RFDR, enaddr[i] | (enaddr[i+1]<<8)); + } + // Setup up acceptance criteria + DP_OUT(dp->base, DP_RFCR, _RFCR_RFEN | _RFCR_AAB | _RFCR_APM); + // Set up interrupts + DP_IN(dp->base, DP_ISR, stat); // Clear any current interrupts + DP_OUT(dp->base, DP_IMR, 0xFFFFFFFF); // Enable them all! + diag_printf("DP83816 - ESA: %02x:%02x:%02x:%02x:%02x:%02x\n", + dp->enaddr[0], dp->enaddr[1], dp->enaddr[2], + dp->enaddr[3], dp->enaddr[4], dp->enaddr[5] ); + +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED + cyg_drv_interrupt_create( + dp->interrupt, + 0, // Priority - unused + (cyg_addrword_t)sc, // Data item passed to ISR & DSR + dp83816_isr, // ISR + eth_drv_dsr, // DSR + &dp->interrupt_handle, // handle to intr obj + &dp->interrupt_object ); // space for int obj + + cyg_drv_interrupt_attach(dp->interrupt_handle); + cyg_drv_interrupt_unmask(dp->interrupt); + DP_OUT(dp->base, DP_IER, 1); +#endif + + // Initialize upper level driver + (sc->funs->eth_drv->init)(sc, enaddr); + + return true; +} + +static void +dp83816_stop(struct eth_drv_sc *sc) +{ + dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private; + + DP_OUT(dp->base, DP_CR, _CR_RXD | _CR_TXD); +} + +// +// 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 +dp83816_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags) +{ + dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private; + + DP_OUT(dp->base, DP_CR, _CR_RXE | _CR_TXE); +} + +// +// This routine is called to perform special "control" opertions +// +static int +dp83816_control(struct eth_drv_sc *sc, unsigned long key, + void *data, int data_len) +{ + 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 +dp83816_can_send(struct eth_drv_sc *sc) +{ + dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private; + + DEBUG_FUNCTION(); + return (dp->txnum - dp->txbusy); +} + +// +// This routine is called to send data to the hardware. It is known a-priori +// that there is free buffer space (dp->tx_next). +// +static void +dp83816_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, + int total_len, unsigned long key) +{ + struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private; + int i, len; + unsigned char *data; + dp83816_bd_t *bdp = dp->txfill; + + DEBUG_FUNCTION(); + + len = total_len; + if (len < IEEE_8023_MIN_FRAME) len = IEEE_8023_MIN_FRAME; + data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->buf)); + for (i = 0; i < sg_len; i++) { + memcpy(data, (unsigned char *)sg_list[i].buf, sg_list[i].len); + data += sg_list[i].len; + } + bdp->key = key; + bdp->stat = _h2le(total_len | BD_OWN | BD_INTR); + dp->txbusy++; + if (bdp->next == (dp83816_bd_t *)0) { + bdp = CYGARC_UNCACHED_ADDRESS(dp->txd); + } else { + bdp++; + } + dp->txfill = bdp; + // Kick the device, in case it went idle + DP_OUT(dp->base, DP_CR, _CR_TXE); +} + +static void +dp83816_TxEvent(struct eth_drv_sc *sc) +{ + struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private; + dp83816_bd_t *bdp = dp->txint; + + DEBUG_FUNCTION(); + while ((_le2h(bdp->stat) & (BD_OWN|BD_INTR)) == BD_INTR) { + // Tell higher level we sent this packet + (sc->funs->eth_drv->tx_done)(sc, bdp->key, 0); + bdp->stat = 0; // retake buffer + dp->txbusy--; + if (bdp->next == (dp83816_bd_t *)0) { + bdp = CYGARC_UNCACHED_ADDRESS(dp->txd); + } else { + bdp++; + } + } + dp->txint = bdp; +} + +// +// This function is called when a packet has been received. It's job is +// to prepare to unload the packet from the hardware. Once the length of +// the packet is known, the upper layer of the driver can be told. When +// the upper layer is ready to unload the packet, the internal function +// 'dp83816_recv' will be called to actually fetch it from the hardware. +// +static void +dp83816_RxEvent(struct eth_drv_sc *sc) +{ + struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private; + dp83816_bd_t *bdp = CYGARC_UNCACHED_ADDRESS(dp->rxd); + int len; + + DEBUG_FUNCTION(); + + while (true) { + if ((_le2h(bdp->stat) & BD_OWN) != 0) { + len = _le2h(bdp->stat) & BD_LENGTH_MASK; + dp->rxnext = bdp; + (sc->funs->eth_drv->recv)(sc, len); + bdp->stat = _h2le(BD_INTR | _DP83816_BUFSIZE); // Give back buffer + } + if (bdp->next == (dp83816_bd_t *)0) { + break; + } else { + bdp++; + } + } +} + +// +// This function is called as a result of the "eth_drv_recv()" call above. +// It's job is to actually fetch data for a packet from the hardware once +// memory buffers have been allocated for the packet. Note that the buffers +// may come in pieces, using a scatter-gather list. This allows for more +// efficient processing in the upper layers of the stack. +// +static void +dp83816_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len) +{ + struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private; + dp83816_bd_t *bdp = dp->rxnext; + unsigned char *data; + int i; + + data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->buf)); + for (i = 0; i < sg_len; i++) { + memcpy((void *)sg_list[i].buf, data, sg_list[i].len); + data += sg_list[i].len; + } +} + +static void +dp83816_poll(struct eth_drv_sc *sc) +{ + struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private; + unsigned long stat; + + DP_IN(dp->base, DP_ISR, stat); + do { + if ((stat & (_ISR_TXDESC|_ISR_TXOK)) != 0) { + dp83816_TxEvent(sc); + } + if ((stat & (_ISR_RXDESC|_ISR_RXOK)) != 0) { + dp83816_RxEvent(sc); + } + if ((stat & (_ISR_HIBERR|_ISR_TXURN|_ISR_RXORN)) != 0) { + diag_printf("DP83816 - major error: %x\n", stat); + } + DP_IN(dp->base, DP_ISR, stat); + } while (stat != 0); +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED + CYGHWR_NS_DP83816_PLF_INT_CLEAR(dp); +#endif +} + +static int +dp83816_int_vector(struct eth_drv_sc *sc) +{ + struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private; + return dp->interrupt; +}
--- a/packages/devs/eth/powerpc/moab/current/ChangeLog +++ b/packages/devs/eth/powerpc/moab/current/ChangeLog @@ -1,3 +1,9 @@ +2003-09-30 Gary Thomas <gary@mlbassoc.com> + + * include/moab_eth_dp83816.inl: + * cdl/moab_eth_drivers.cdl: Add support for 2nd LAN device, based + on National Semiconductor DP83816. + 2003-09-19 Gary Thomas <gary@mlbassoc.com> * include/moab_eth.inl:
--- a/packages/devs/eth/powerpc/moab/current/cdl/moab_eth_drivers.cdl +++ b/packages/devs/eth/powerpc/moab/current/cdl/moab_eth_drivers.cdl @@ -63,7 +63,12 @@ cdl_package CYGPKG_DEVS_ETH_POWERPC_MOAB requires CYGHWR_DEVS_ETH_PHY_DP83847 requires CYGPKG_HAL_POWERPC_MOAB - cdl_option CYGHWR_DEVS_ETH_POWERPC_MOAB_ETH0 { + # FIXME: This really belongs in the NS DP83816 package + cdl_interface CYGINT_DEVS_ETH_NS_DP83816_REQUIRED { + display "NS DP83816 ethernet driver required" + } + + cdl_component CYGHWR_DEVS_ETH_POWERPC_MOAB_ETH0 { display "Include eth0 ethernet device" default_value 1 description " @@ -74,7 +79,7 @@ cdl_package CYGPKG_DEVS_ETH_POWERPC_MOAB implements CYGHWR_DEVS_ETH_POWERPC_PPC405_NET_DRIVERS } - cdl_option CYGHWR_DEVS_ETH_POWERPC_MOAB_ETH1 { + cdl_component CYGHWR_DEVS_ETH_POWERPC_MOAB_ETH1 { display "Include eth1 ethernet device" default_value 1 description " @@ -83,6 +88,60 @@ cdl_package CYGPKG_DEVS_ETH_POWERPC_MOAB implements CYGHWR_NET_DRIVERS implements CYGHWR_NET_DRIVER_ETH1 requires CYGHWR_DEVS_ETH_POWERPC_MOAB_ETH0 + + implements CYGINT_DEVS_ETH_NS_DP83816_REQUIRED + + define_proc { + puts $::cdl_system_header "/***** ethernet driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_NS_DP83816_INL <cyg/io/moab_eth_dp83816.inl>" + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_NS_DP83816_CFG <pkgconf/devs_eth_powerpc_moab.h>" + puts $::cdl_system_header "/***** ethernet driver proc output end *****/" + } + + cdl_option CYGNUM_DEVS_ETH_MOAB_DP83816_TxNUM { + display "Number of output buffers" + flavor data + legal_values 2 to 64 + default_value 16 + description " + This option specifies the number of output buffer packets + to be used for the NS DP83816 ethernet device." + } + + cdl_option CYGNUM_DEVS_ETH_MOAB_DP83816_RxNUM { + display "Number of input buffers" + flavor data + legal_values 2 to 64 + default_value 16 + description " + This option specifies the number of input buffer packets + to be used for the NS DP83816 ethernet device." + } + + cdl_option CYGDAT_DEVS_ETH_MOAB_ETH1_NAME { + display "Device name for the ETH1 ethernet driver" + flavor data + default_value {"\"eth1\""} + description " + This option sets the name of the ethernet device." + } + + cdl_component CYGSEM_DEVS_ETH_MOAB_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_MOAB_ETH1_ESA { + display "The ethernet station address" + flavor data + default_value {"{0x08, 0x88, 0x12, 0x34, 0x56, 0x78}"} + description "The ethernet station address" + } + } } include_dir cyg/io
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl @@ -0,0 +1,157 @@ +//========================================================================== +// +// moab_eth_dp83816.inl +// +// MOAB 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. +// Copyright (C) 2003 Gary Thomas +// +// 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): gthomas +// Contributors: +// Date: 2003-09-29 +// Purpose: MOAB ethernet defintions +//####DESCRIPTIONEND#### +//========================================================================== + +#include <cyg/hal/hal_cache.h> +#include <cyg/io/pci.h> + +#undef DP_IN +#undef DP_OUT +#define DP_IN(_b_, _o_, _d_) HAL_READ_UINT32LE((cyg_addrword_t)(_b_)+(_o_), (_d_)) +#define DP_OUT(_b_, _o_, _d_) HAL_WRITE_UINT32LE((cyg_addrword_t)(_b_)+(_o_), (_d_)) + +#if defined(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]", + eth1_esa, + ALWAYS_ENABLED, true, + CONFIG_ESA, 0 + ); +#endif // CYGSEM_REDBOOT_FLASH_CONFIG +#else +#ifndef CONFIG_ESA +#define CONFIG_ESA 6 +#endif +#endif // CYGPKG_REDBOOT + +static cyg_bool +find_rtl8381x_match_func(cyg_uint16 v, cyg_uint16 d, cyg_uint32 c, void *p) +{ + return ((v == 0x100B) && (d == 0x0020)); +} + +static void +_moab_eth_init(dp83816_priv_data_t *dp) +{ + cyg_pci_device_id devid; + cyg_pci_device dev_info; + + devid = CYG_PCI_NULL_DEVID; + if (cyg_pci_find_matching( &find_rtl8381x_match_func, NULL, &devid )) { + cyg_pci_get_device_info(devid, &dev_info); + cyg_pci_translate_interrupt(&dev_info, &dp->interrupt); + dp->base = (cyg_uint8 *)(dev_info.base_map[0] & ~1); + diag_printf("DP83816 at %p, interrupt: %x\n", dp->base, dp->interrupt); + } +} + +#undef CYGHWR_NS_DP83816_PLF_INIT +#define CYGHWR_NS_DP83816_PLF_INIT(dp) _moab_eth_init(dp) + +// Map a 32 bit host quantity to little endian +unsigned long +_h2le(unsigned long val) +{ + unsigned long res; + unsigned long *addr = &val; + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (res) : "r" (addr), "m" (*addr)); + return res; +} + +// Map a 32 bit little endian quantity to host representation +unsigned long +_le2h(unsigned long val) +{ + unsigned long res; + unsigned long *addr = &val; + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (res) : "r" (addr), "m" (*addr)); + return res; +} + +// Align buffers on a cache boundary +#define RxBUFSIZE CYGNUM_DEVS_ETH_MOAB_DP83816_RxNUM*_DP83816_BUFSIZE +#define TxBUFSIZE CYGNUM_DEVS_ETH_MOAB_DP83816_TxNUM*_DP83816_BUFSIZE +static unsigned char dp83816_eth_rxbufs[RxBUFSIZE] __attribute__((aligned(HAL_DCACHE_LINE_SIZE))); +static unsigned char dp83816_eth_txbufs[TxBUFSIZE] __attribute__((aligned(HAL_DCACHE_LINE_SIZE))); +static dp83816_bd_t dp83816_eth_rxbd[CYGNUM_DEVS_ETH_MOAB_DP83816_RxNUM] __attribute__((aligned(HAL_DCACHE_LINE_SIZE))); +static dp83816_bd_t dp83816_eth_txbd[CYGNUM_DEVS_ETH_MOAB_DP83816_TxNUM] __attribute__((aligned(HAL_DCACHE_LINE_SIZE))); + +static dp83816_priv_data_t dp83816_eth1_priv_data = { + "eth1_esa", + { 0x08, 0x00, 0x3C, 0x29, 0x7A, 0xBA}, // Default ESA + CYGNUM_DEVS_ETH_MOAB_DP83816_RxNUM, // Number of Rx buffers + dp83816_eth_rxbufs, // Rx buffer space + dp83816_eth_rxbd, // Rx buffer headers + CYGNUM_DEVS_ETH_MOAB_DP83816_TxNUM, // Number of Tx buffers + dp83816_eth_txbufs, // Tx buffer space + dp83816_eth_txbd, // Tx buffer headers +}; + +ETH_DRV_SC(dp83816_sc, + &dp83816_eth1_priv_data, // Driver specific data + CYGDAT_DEVS_ETH_MOAB_ETH1_NAME, + dp83816_start, + dp83816_stop, + dp83816_control, + dp83816_can_send, + dp83816_send, + dp83816_recv, + dp83816_deliver, // "pseudoDSR" called from fast net thread + dp83816_poll, // poll function, encapsulates ISR and DSR + dp83816_int_vector); + +NETDEVTAB_ENTRY(dp83816_netdev, + "dp83816_" CYGDAT_DEVS_ETH_MOAB_ETH1_NAME, + dp83816_init, + &dp83816_sc); + +// EOF moab_eth_dp83816.inl
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -1593,6 +1593,14 @@ package CYGPKG_DEVS_ETH_NS_DP83902A { description "Ethernet driver for NS DP83902A controller." } +package CYGPKG_DEVS_ETH_NS_DP83816 { + alias { "NS DP83816 ethernet driver" dp83816_eth_driver } + hardware + directory devs/eth/ns/dp83816 + script ns_dp83816_eth_drivers.cdl + description "Ethernet driver for NS DP83816 controller." +} + package CYGPKG_DEVS_ETH_CL_CS8900A { alias { "Cirrus Logic CS8900A ethernet driver" cs8900a_eth_driver } hardware @@ -5113,6 +5121,7 @@ target moab { CYGPKG_DEVS_FLASH_TOSHIBA_TC58XXX CYGPKG_DEVS_ETH_POWERPC_MOAB CYGPKG_DEVS_ETH_POWERPC_PPC405 + CYGPKG_DEVS_ETH_NS_DP83816 CYGPKG_DEVS_ETH_PHY CYGPKG_IO_PCI CYGPKG_DEVICES_WALLCLOCK_DALLAS_DS1307
--- a/packages/hal/powerpc/moab/current/ChangeLog +++ b/packages/hal/powerpc/moab/current/ChangeLog @@ -1,3 +1,7 @@ +2003-09-30 Gary Thomas <gary@mlbassoc.com> + + * include/plf_io.h (CYGARC_VIRTUAL_ADDRESS): Added. + 2003-09-28 Gary Thomas <gary@mlbassoc.com> * cdl/hal_powerpc_moab.cdl: Remove conflicting constraint - prevented
--- a/packages/hal/powerpc/moab/current/include/plf_io.h +++ b/packages/hal/powerpc/moab/current/include/plf_io.h @@ -60,6 +60,7 @@ // PCI support // #define CYGARC_PHYSICAL_ADDRESS(x) ((unsigned long)(x) & 0x7FFFFFFF) +#define CYGARC_VIRTUAL_ADDRESS(x) ((unsigned long)(x) & 0x7FFFFFFF) // Restrict device [slot] space #define CYG_PCI_MAX_BUS 1 // Only one BUS
