if_i21143.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,882 行 · 第 1/5 页

C
1,882
字号
//==========================================================================
//
//      if_i21143.c
//
//	Intel 21143 ethernet driver
//
//==========================================================================
//####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
// Contributors: 
// Date:         2000-09-17
// Purpose:      
// Description:  hardware driver for 21143 Intel PRO/100+ ethernet
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <pkgconf/system.h>
#ifdef CYGPKG_IO_ETH_DRIVERS
#include <pkgconf/io_eth_drivers.h>
#endif
#include <pkgconf/devs_eth_intel_i21143.h>

// Config for the instantiating package:
#include CYGDAT_DEVS_ETH_INTEL_I21143_CFG

#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>          // HAL_DCACHE_STORE
#include <cyg/infra/diag.h>
#include <cyg/hal/hal_if.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 */
#endif

#ifdef CYGPKG_IO_PCI
#include <cyg/io/pci.h>
#include CYGHWR_MEMORY_LAYOUT_H
#else
#error "Need PCI package here"
#endif

// ------------------------------------------------------------------------
// Exported statistics and the like
// defined in <cyg/io/eth/eth_drv_stats.h> - already included.

#define KEEP_STATISTICS

#ifdef KEEP_STATISTICS
# define INCR_STAT( _x_ ) (p_i21143->stats. _x_ ++)
#else
# define INCR_STAT( _x_ ) CYG_EMPTY_STATEMENT
#endif

// ------------------------------------------------------------------------
//
//                      DEVICES AND PACKET QUEUES
//
// ------------------------------------------------------------------------

#define RX_DESCRIPTORS (4) // 4 packets.
#define RX_BUFFERS     RX_DESCRIPTORS
#define TX_DESCRIPTORS MAX_ETH_DRV_SG // Enough for one tx, even if fragmented

#define MAX_RX_PACKET_SIZE  1536        // maximum Rx packet size
#define MAX_TX_PACKET_SIZE  1536        // maximum Tx packet size

// ------------------------------------------------------------------------

typedef struct buffer_descriptor {
    volatile cyg_uint32 des0;
    volatile cyg_uint32 des1;
    volatile cyg_uint32 buf1;
    volatile cyg_uint32 buf2;
} BUFDES;


typedef struct i21143 {
    cyg_uint8                           // (split up for atomic byte access)
        found:1,                        // was hardware discovered?
        mac_addr_ok:1,                  // can we bring up?
        active:1,                       // has this if been brung up?
        hardwired_esa:1,                // set if ESA is hardwired via CDL
        spare1:4; 
    cyg_uint8 tx_endbuf;                // transmit in progress flag too
#define NO_TX_IN_PROGRESS (255)
    cyg_uint8  index;                   // 0 or 1 or whatever
    cyg_uint8  line_status;             // line status when last inspected
    cyg_uint32 devid;                   // PCI device id
    cyg_uint32 io_address;              // memory mapped I/O address
    cyg_uint8  mac_address[6];          // mac (hardware) address
    cyg_uint16 phy_autoneg_remote;      // remote link status cache
    void *ndp;                          // Network Device Pointer
    
    int next_rx_descriptor;             // descriptor index for buffers
    volatile BUFDES *rx_ring;           // location of Rx descriptors

    volatile BUFDES *tx_ring;           // location of Tx descriptors
    unsigned long tx_keys[1];           // keys for tx q management

    // Interrupt handling stuff
    cyg_vector_t    vector;             // interrupt vector
    cyg_handle_t    interrupt_handle;   // handle for int.handler
    cyg_interrupt   interrupt_object;

    // Refer to following items only though uncached addresses from the
    // tx_ring and rxring pointers:
    volatile BUFDES _tx[TX_DESCRIPTORS];
    volatile BUFDES _rx[RX_DESCRIPTORS];

    cyg_uint8 _rxbufs[ RX_BUFFERS ] [ MAX_RX_PACKET_SIZE ] ;

#ifdef KEEP_STATISTICS
    struct stats {
        unsigned int tx_good;
        unsigned int tx_max_collisions;
        unsigned int tx_late_collisions;
        unsigned int tx_underrun;
        unsigned int tx_carrier_loss;
        unsigned int tx_deferred;
        unsigned int tx_sqetesterrors;
        unsigned int tx_single_collisions;
        unsigned int tx_mult_collisions;
        unsigned int tx_total_collisions;

        unsigned int rx_good;
        unsigned int rx_crc_errors;
        unsigned int rx_align_errors;
        unsigned int rx_resource_errors;
//        unsigned int rx_overrun_errors;
        unsigned int rx_collisions;
        unsigned int rx_short_frames;
        unsigned int rx_too_long_frames;
        unsigned int rx_symbol_errors;

        unsigned int interrupts;
        unsigned int rx_count;
        unsigned int rx_deliver;
        unsigned int rx_resource;
        unsigned int rx_restart;

        unsigned int tx_count;
        unsigned int tx_complete;
        unsigned int tx_dropped;
    } stats;
#endif // KEEP_STATISTICS
} I21143;

// ------------------------------------------------------------------------
// After defining that, now we can instantiate the device(s):


#include CYGDAT_DEVS_ETH_INTEL_I21143_INL

// ------------------------------------------------------------------------
// Access to cached/uncached/physical memory, to map from CPU-view
// addresses to PCI-bus master's view - however that is:
// 
// We'll use these macros, so that different platforms can define them
// externally:
//  o CYGHWR_PCI_VIRT_TO_BUS( x )
//    - address for the PCI device to use
//  o CYGHWR_CACHED_TO_UNCACHED( x )
//    - access to memory that the PCI device will look at
//  o CYGHWR_BUS_TO_UNCACHED( x )
//    - back from an address in the PCI structures to one for us to look at
//      to see what it said.

#ifndef CYGHWR_PCI_VIRT_TO_BUS
# ifdef CYGARC_PHYSICAL_ADDRESS
#  define CYGHWR_PCI_VIRT_TO_BUS( _x_ ) CYGARC_PHYSICAL_ADDRESS( (_x_) )
# else
#  error No CYGHWR_PCI_VIRT_TO_BUS() defined!
//#define CYGHWR_PCI_VIRT_TO_BUS( _x_ )  (_x_)
# endif
#endif

#ifndef CYGHWR_CACHED_TO_UNCACHED
# ifdef CYGARC_UNCACHED_ADDRESS
#  define CYGHWR_CACHED_TO_UNCACHED( _x_ ) CYGARC_UNCACHED_ADDRESS( (_x_) )
# else   
#  define CYGHWR_CACHED_TO_UNCACHED( _x_ )  (_x_)
# endif
#endif

#ifndef CYGHWR_BUS_TO_UNCACHED
# ifdef CYGARC_UNCACHED_ADDRESS
#  define CYGHWR_BUS_TO_UNCACHED( _x_ ) CYGARC_UNCACHED_ADDRESS( (_x_) )
# else   
#  define CYGHWR_BUS_TO_UNCACHED( _x_ )  (_x_)
# endif
#endif

// ------------------------------------------------------------------------
// Prototypes and declarations

static int pci_init_find_21143s( void );
static int i21143_configure(struct i21143* p_i21143, int promisc);
static void i21143_reset(struct i21143* p_i21143);
static void InitTxRing(struct i21143* p_i21143);
static void InitRxRing(struct i21143* p_i21143);
static void eth_set_mac_address( struct i21143* p_i21143, cyg_uint8 *addr );

static void mii_write_register( int ioaddr, int regnum, int value );
static int mii_read_register( int ioaddr, int regnum );

static int get_eeprom_size( int ioaddr );
static int read_eeprom_word( int ioaddr, int addrbits, int address );

// ------------------------------------------------------------------------
//
//                   21143 GENERAL STATUS REGISTER
//
// ------------------------------------------------------------------------
#define GEN_STATUS_FDX          0x04    // 1 = full duplex, 0 = half
#define GEN_STATUS_100MBPS      0x02    // 1 = 100 Mbps, 0 = 10 Mbps
#define GEN_STATUS_LINK         0x01    // 1 = link up, 0 = link down

// returns status in terms of the above:
static int i21143_status( struct i21143* p_i21143 );

// A cheap check for changes: true if changed, is all:
static int i21143_status_changed( struct i21143* p_i21143 );

// ------------------------------------------------------------------------

#define CYGDAT_DEVS_ETH_DESCRIPTION "Intel i21143 10/100 Ethernet [DEC]"

#define ETH_DEV_DOT3STATSETHERCHIPSET 1,3,6,1,2,1,10,7,8,2,5

// ------------------------------------------------------------------------

#ifdef CYGDBG_DEVS_ETH_INTEL_I21143_CHATTER
#define nDEBUG_TRAFFIC  // This one prints stuff as packets come and go
#define DEBUG          // Startup printing mainly
#define nDEBUG_EE       // Some EEPROM specific retries &c
#define nDEBUG_TRAFFIC_TXDETAILS // tx bufs layout
#define nDEBUG_DUMP_REGS
#define nDEBUG_MAC
#define nDEBUG_STARTSTOPRESET
#endif

// ------------------------------------------------------------------------
// I/O access macros as inlines for type safety

#if (CYG_BYTEORDER == CYG_MSBFIRST)

#define HAL_CTOLE32(x)  ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24) & 0xff))
#define HAL_LE32TOC(x)  ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24) & 0xff))

#define HAL_CTOLE16(x)  ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
#define HAL_LE16TOC(x)  ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))

//static inline void OUTB(cyg_uint8 value, cyg_uint32 io_address)
//{
//    HAL_WRITE_UINT8( io_address, value);
//}
//
//static inline void OUTW(cyg_uint16 value, cyg_uint32 io_address)
//{
//    HAL_WRITE_UINT16( io_address, (((value & 0xff) << 8) | ((value & 0xff00) >> 8)) );
//}

static inline void OUTL(cyg_uint32 value, cyg_uint32 io_address)
{
    HAL_WRITE_UINT32( io_address,
                      ((((value) & 0xff) << 24) | (((value) & 0xff00) << 8) | (((value) & 0xff0000) >> 8) | (((value) >> 24) & 0xff)) );
}

//static inline cyg_uint8 INB(cyg_uint32 io_address)
//{   
//    cyg_uint8 d;
//    HAL_READ_UINT8( io_address, d );
//    return d;
//}
//
//static inline cyg_uint16 INW(cyg_uint32 io_address)
//{
//    cyg_uint16 d;
//    HAL_READ_UINT16( io_address, d );
//    return (((d & 0xff) << 8) | ((d & 0xff00) >> 8));
//}

static inline cyg_uint32 INL(cyg_uint32 io_address)
{
    cyg_uint32 d;
    HAL_READ_UINT32( io_address, d );
    return ((((d) & 0xff) << 24) | (((d) & 0xff00) << 8) | (((d) & 0xff0000) >> 8) | (((d) >> 24) & 0xff));
}
#else

// Maintaining the same styleee as above...
#define HAL_CTOLE32(x)  ((((x))))
#define HAL_LE32TOC(x)  ((((x))))

#define HAL_CTOLE16(x)  ((((x))))
#define HAL_LE16TOC(x)  ((((x))))

//static inline void OUTB(cyg_uint8  value, cyg_uint32 io_address)
//{   HAL_WRITE_UINT8( io_address, value );   }
//
//static inline void OUTW(cyg_uint16 value, cyg_uint32 io_address)
//{   HAL_WRITE_UINT16( io_address, value );   }

static inline void OUTL(cyg_uint32 value, cyg_uint32 io_address)
{   HAL_WRITE_UINT32( io_address, value );   }

//static inline cyg_uint8  INB(cyg_uint32 io_address)
// {   cyg_uint8  _t_; HAL_READ_UINT8(  io_address, _t_ ); return _t_;   }
//
//static inline cyg_uint16 INW(cyg_uint32 io_address)
// {   cyg_uint16 _t_; HAL_READ_UINT16( io_address, _t_ ); return _t_;   }

static inline cyg_uint32 INL(cyg_uint32 io_address)
 {   cyg_uint32 _t_; HAL_READ_UINT32( io_address, _t_ ); return _t_;   }

#endif // byteorder

// ------------------------------------------------------------------------

static inline void udelay(int delay)
{
    CYGACC_CALL_IF_DELAY_US(delay);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?