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