ks5000_ether.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,481 行 · 第 1/3 页

C
1,481
字号
//==========================================================================////      ks5000_ether.c////      ////==========================================================================//####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: gthomas, jskov//               Grant Edwards <grante@visi.com>// Date:         2001-07-31// Purpose:      // Description:  ////####DESCRIPTIONEND####////========================================================================*/#include <pkgconf/system.h>#include <pkgconf/devs_eth_arm_ks32c5000.h>#include <pkgconf/io_eth_drivers.h>#include <errno.h>#if defined(CYGPKG_IO)#include <pkgconf/io.h>#include <cyg/io/io.h>#include <cyg/io/devtab.h>#endif// need to provide fake values for errno?#ifndef EIO# define EIO 1#endif#ifndef EINVAL# define EINVAL 2#endif#include <cyg/infra/cyg_type.h>  // Common type definitions and support                                 // including endian-ness#include <cyg/infra/diag.h>#include <cyg/io/eth/netdev.h>#include <cyg/io/eth/eth_drv.h>#include <cyg/io/eth/eth_drv_stats.h>#include <cyg/hal/hal_intr.h>#if defined(CYGPKG_REDBOOT)#include <pkgconf/redboot.h>#endif#ifndef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED#define cyg_drv_interrupt_unmask(v) /* noop */#define cyg_drv_interrupt_mask(v)   /* noop */#define cyg_drv_isr_lock()          /* noop */#define cyg_drv_isr_unlock()        /* noop */#define cyg_drv_mutex_init(m)       /* noop */#define cyg_drv_mutex_lock(m)       /* noop */#define cyg_drv_mutex_unlock(m)     /* noop */#define cyg_drv_dsr_lock()          /* noop */#define cyg_drv_dsr_unlock()        /* noop */#endif#define HavePHYinterrupt 0#include "std.h"#include "ks5000_regs.h"#include "ks5000_ether.h"#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY#include "phy.h"#endif// Set up the level of debug output#if CYGPKG_DEVS_ETH_ARM_KS32C5000_DEBUG_LEVEL > 0#define debug1_printf(args...) diag_printf(args)#else#define debug1_printf(args...) /* noop */#endif#if CYGPKG_DEVS_ETH_ARM_KS32C5000_DEBUG_LEVEL > 1#define debug2_printf(args...) diag_printf(args)#else#define debug2_printf(args...) /* noop */#endif#define Bit(n) (1<<(n))// enable/disable software verification of rx CRC// should be moved to user-controlled valud in CDL file#if defined(CYG_HAL_CPUTYPE_KS32C5000A)#define SoftwareCRC 1#include <cyg/crc/crc.h>#else#define SoftwareCRC 0#endif// --------------------------------------------------------------// RedBoot configuration options for managing ESAs for us// Decide whether to have redboot config vars for it...#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGPKG_REDBOOT_NETWORKING)#include <redboot.h>#include <flash_config.h>#ifdef CYGSEM_DEVS_ETH_ARM_KS32C5000_REDBOOT_HOLDS_ESA_ETH0RedBoot_config_option("Network hardware address [MAC] for eth0",                      eth0_esa_data,                      ALWAYS_ENABLED, true,                      CONFIG_ESA, 0);#endif#endif  // CYGPKG_REDBOOT_NETWORKING && CYGSEM_REDBOOT_FLASH_CONFIG// and initialization code to read them// - independent of whether we are building RedBoot right now:#ifdef CYGPKG_DEVS_ETH_ARM_KS32C5000_REDBOOT_HOLDS_ESA#include <cyg/hal/hal_if.h>#ifndef CONFIG_ESA#define CONFIG_ESA (6)#endif#define CYGHWR_DEVS_ETH_ARM_KS32C5000_GET_ESA( mac_address, ok )                 \CYG_MACRO_START                                                                  \    ok = CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET,              \                                      "eth0_esa_data", mac_address, CONFIG_ESA); \CYG_MACRO_END#endif // CYGPKG_DEVS_ETH_I82559_ETH_REDBOOT_HOLDS_ESA#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY// functions to read/write Phy chip registers via MII interface// on 32c5000.  These need to be non-static since they're used// by PHY-specific routines in a different file.#define PHYREGWRITE	0x0400#define MiiStart       0x0800void MiiStationWrite(U32 RegAddr, U32 PhyAddr, U32 PhyWrData){  STADATA = PhyWrData ;  STACON = RegAddr | (PhyAddr<<5) |  MiiStart | PHYREGWRITE ;  while (STACON & MiiStart)      ;  //debug1_printf("PHY Wr %x:%02x := %04x\n",PhyAddr, RegAddr, PhyWrData) ;}U32 MiiStationRead(U32 RegAddr, U32 PhyAddr){  U32	PhyRdData;  STACON = RegAddr | (PhyAddr<<5) |  MiiStart;  while (STACON & MiiStart)    ;  PhyRdData = STADATA;  //debug1_printf("PHY Rd %x:%02x  %04x\n",PhyAddr,RegAddr,PhyRdData) ;  return PhyRdData ;}#endif// miscellaneous data structurestypedef  BYTE  ETH_ADDR[6] __attribute__((packed));typedef  struct tagETH_HEADER {  ETH_ADDR daddr __attribute__((packed));  ETH_ADDR saddr __attribute__((packed));  WORD type      __attribute__((packed));} ETH_HEADER __attribute__((packed));#define ETH_HEADER_SIZE   14// Tx/Rx common descriptor structuretypedef  struct tagFRAME_DESCRIPTOR {  LWORD FrameDataPtr;  LWORD Reserved;   /*  cf: RX-reserved, TX-Reserved(25bits) + Control bits(7bits) */  LWORD StatusAndFrameLength;  struct tagFRAME_DESCRIPTOR   *NextFD;} FRAME_DESCRIPTOR;typedef struct{  U8 DestinationAddr[6];  U8 SourceAddr[6];  U8 LengthOrType[2];  U8 LLCData[1506];} MAC_FRAME;#if defined(CYGPKG_NET)struct ether_drv_stats ifStats;#endif#if defined(CYGINT_IO_ETH_INT_SUPPORT_REQUIRED)static cyg_drv_mutex_t txMutex;#endiftypedef struct{  LWORD BTxNLErr;  LWORD BTxNOErr;  LWORD BTxEmptyErr;} BDMA_TX_ERR;typedef struct{  LWORD BRxNLErr;  LWORD BRxNOErr;  LWORD BRxMSOErr;  LWORD BRxEmptyErr;  LWORD sBRxSEarly;  LWORD noBufferAvail;  LWORD queueOverflow;  LWORD bad;} BDMA_RX_ERR;// interrupt entry countersU32 ks5000_MAC_Rx_Cnt;U32 ks5000_MAC_Tx_Cnt;U32 ks5000_MAC_Phy_Cnt;U32 ks5000_BDMA_Tx_Isr_Cnt;U32 ks5000_BDMA_Tx_Dsr_Cnt;U32 ks5000_BDMA_Rx_Isr_Cnt;U32 ks5000_BDMA_Rx_Dsr_Cnt;// packet and byte countersstatic U32 MAC_Tx_Pkts;static U32 MAC_Tx_Octets;// static U32 BDMA_Rx_Pkts;// static U32 BDMA_Rx_Octets;// configuration valuesstatic volatile U32 MACConfigVar;static volatile U32 CAMConfigVar = CAMCON_COMP_EN | CAMCON_BROAD_ACC;static volatile U32 MACTxConfigVar =   /* MACTXCON_EN_UNDER | */   MACTXCON_EN_DEFER |  MACTXCON_EN_NCARR |   MACTXCON_EN_EXCOLL |  MACTXCON_EN_LATE_COLL |   MACTXCON_ENTX_PAR |  MACTXCON_EN_COMP;static volatile U32 MACRxConfigVar =   MACRXCON_RX_EN |   MACRXCON_EN_ALIGN |  MACRXCON_EN_CRC_ERR |   MACRXCON_EN_OVER |  MACRXCON_EN_LONG_ERR |   MACRXCON_EN_RX_PAR;static volatile U32 BDMATxConfigVar =    BDMATXCON_MSL111 |  BDMATXCON_STP_SKP |   3;   /* burst size - 1 */#define EtherFramePadding 2#if EtherFramePadding == 0#define BDMARXCON_ALIGN BDMARXCON_WA00#elif EtherFramePadding == 1#define BDMARXCON_ALIGN BDMARXCON_WA01#elif EtherFramePadding == 2#define BDMARXCON_ALIGN BDMARXCON_WA10#elif EtherFramePadding == 3#define BDMARXCON_ALIGN BDMARXCON_WA11#else#error "EtherFramePadding must be 0,1,2 or 3"#endif#if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endianstatic volatile U32 BDMARxConfigVar =   BDMARXCON_DIE |   BDMARXCON_EN |  BDMARXCON_BIG |   BDMARXCON_MA_INC |  BDMARXCON_NOIE |   BDMARXCON_ALIGN |  BDMARXCON_STP_SKP |   15;  /* burst size - 1 */  #else // Little endianstatic volatile U32 BDMARxConfigVar =   BDMARXCON_DIE |   BDMARXCON_EN |  BDMARXCON_LITTLE |   BDMARXCON_MA_INC |  BDMARXCON_NOIE |   BDMARXCON_ALIGN |  BDMARXCON_STP_SKP |   15;  /* burst size - 1 */#endif/* Global variables For BDMA Error Report */static BDMA_TX_ERR BDMATxErrCnt = {0,0,0};static BDMA_RX_ERR BDMARxErrCnt = {0,0,0,0,0};static void Init_TxFrameDescriptorArray(void);static void Init_RxFrameDescriptorArray(void);// number of ethernet buffers should be enough to keep both rx// and tx queues full plus some extras for in-process packets#if defined(CYGPKG_REDBOOT)#define NUM_ETH_BUFFERS 10#define MAX_RX_FRAME_DESCRIPTORS        4     // Max number of Rx Frame Descriptors#define MAX_TX_FRAME_DESCRIPTORS  	4     // Max number of Tx Frame Descriptors#else#define NUM_ETH_BUFFERS 80#define MAX_RX_FRAME_DESCRIPTORS        32     // Max number of Rx Frame Descriptors#define MAX_TX_FRAME_DESCRIPTORS  	32     // Max number of Tx Frame Descriptors#endifstatic FRAME_DESCRIPTOR _rxFrameDescrArray[MAX_RX_FRAME_DESCRIPTORS] __attribute__((aligned(16)));static FRAME_DESCRIPTOR _txFrameDescrArray[MAX_TX_FRAME_DESCRIPTORS] __attribute__((aligned(16)));/* define aliases that will set the no-cache bit */#define rxFrameDescrArray ((FRAME_DESCRIPTOR*)(((unsigned)_rxFrameDescrArray)|0x4000000))#define txFrameDescrArray ((FRAME_DESCRIPTOR*)(((unsigned)_txFrameDescrArray)|0x4000000))static volatile FRAME_DESCRIPTOR *rxReadPointer;static volatile FRAME_DESCRIPTOR *txDonePointer;static volatile FRAME_DESCRIPTOR *txWritePointer;static cyg_drv_mutex_t oldRxMutex;static cyg_drv_cond_t  oldRxCond;static bool configDone;/*---------------------------------------------------------------------- * Data structures used to manage ethernet buffers */#define MAX_ETH_FRAME_SIZE 1520  typedef struct tEthBufferTag{  unsigned char data[MAX_ETH_FRAME_SIZE+8];  unsigned length;  unsigned userData;  struct tEthBufferTag *next;  struct tEthBufferTag *prev;}tEthBuffer;typedef struct {  tEthBuffer *head;  tEthBuffer *tail;}tEthBufQueue;#define EmptyQueue {NULL,NULL}static void ethBufQueueClear(tEthBufQueue *q){  q->head = NULL;  q->tail = NULL;}static tEthBuffer *ethBufQueueGet(tEthBufQueue *q){  tEthBuffer *r;    r = q->head;    if (r)    q->head = r->next;    return r;}static void ethBufQueuePut(tEthBufQueue *q, tEthBuffer *b){  b->next = NULL;    if (!q->head)    {      q->head = b;      q->tail = b;    }  else    {      q->tail->next = b;      q->tail = b;    }}#if 0// not used at the momentstatic bool ethBufQueueEmpty(tEthBufQueue *q){  return q->head != NULL;}#endif/*---------------------------------------------------------------------- * Free pool and routines to manipulate it. */static tEthBuffer __bufferPool[NUM_ETH_BUFFERS] __attribute__((aligned(16)));#define bufferPool ((tEthBuffer*)((unsigned)__bufferPool|0x4000000))static tEthBufQueue freeList;static int freeCount;// do not call from ISR routinestatic void freeBuffer(tEthBuffer *b){  cyg_drv_isr_lock();  ++freeCount;  ethBufQueuePut(&freeList,b);  cyg_drv_isr_unlock();}static int allocFail;void bufferListError(void){  while (1)    ;}// do not call from ISR routinestatic tEthBuffer *allocBuffer(void){  tEthBuffer *r;  cyg_drv_isr_lock();  r = ethBufQueueGet(&freeList);  cyg_drv_isr_unlock();  if (r)    --freeCount;  else    {      ++allocFail;      if (freeCount)        bufferListError();    }  return r;}// call only from ISR routine or initstatic void isrFreeBuffer(tEthBuffer *b){  ++freeCount;  ethBufQueuePut(&freeList,b);}#if 0// not used at the moment// call only from ISR routine or initstatic tEthBuffer *isrAllocBuffer(void){  tEthBuffer *r;  r = ethBufQueueGet(&freeList);  if (r)

⌨️ 快捷键说明

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