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 + -
显示快捷键?