⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dev_sb1250_ethernet.c

📁 一个很好的嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  *********************************************************************    *  SB1250_ETHERNET    *    *  CFE Ethernet Driver		File: DEV_SB1250_ETHERNET.C    *      *  Author:  Mitch Lichtenberg    *      *  This is the console monitor Ethernet driver for the SB1250    *      *********************************************************************      *    *  Copyright 2000,2001,2002,2003    *  Broadcom Corporation. All rights reserved.    *      *  This software is furnished under license and may be used and     *  copied only in accordance with the following terms and     *  conditions.  Subject to these conditions, you may download,     *  copy, install, use, modify and distribute modified or unmodified     *  copies of this software in source and/or binary form.  No title     *  or ownership is transferred hereby.    *      *  1) Any source code used, modified or distributed must reproduce     *     and retain this copyright notice and list of conditions     *     as they appear in the source file.    *      *  2) No right is granted to use any trade name, trademark, or     *     logo of Broadcom Corporation.  The "Broadcom Corporation"     *     name may not be used to endorse or promote products derived     *     from this software without the prior written permission of     *     Broadcom Corporation.    *      *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR     *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT     *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN     *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES     *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF     *     THE POSSIBILITY OF SUCH DAMAGE.    ********************************************************************* */#undef SIBYTE_HDR_FEATURES	/* we want all constants here */#include "cfe.h"#include "sbmips.h"#include "env_subr.h"#include "net_enet.h"#include "sb1250_defs.h"#include "sb1250_regs.h"#include "sb1250_mac.h"#include "sb1250_dma.h"#include "mii.h"/*  *********************************************************************    *  Simple types    ********************************************************************* */#ifdef __long64typedef volatile uint64_t sbeth_port_t;typedef uint64_t sbeth_physaddr_t;#define SBETH_PORT(x) PHYS_TO_K1(x)#elsetypedef volatile uint32_t sbeth_port_t;typedef uint32_t sbeth_physaddr_t;#define SBETH_PORT(x) PHYS_TO_K1(x)#endif#define SBETH_READCSR(t) (*((volatile uint64_t *) (t)))#define SBETH_WRITECSR(t,v) *((volatile uint64_t *) (t)) = (v)#define SBETH_MAX_TXDESCR	8#define SBETH_MAX_RXDESCR	8#define SBETH_MIN_RCV_RING	4#define SBETH_PKTPOOL_SIZE	16#define SBETH_DMA_CHANNELS	1#define SBETH_PKT_SIZE	        (ENET_MAX_PKT+ENET_CRC_SIZE)#define SBETH_PKTBUF_SIZE	2048#if CFG_L2_RAM#define SBETH_VTOP(x) ((sbeth_physaddr_t)0xD0000000 + (sbeth_physaddr_t)(x))#else#define SBETH_VTOP(x) (K1_TO_PHYS((sbeth_physaddr_t)(x)))#endiftypedef enum { sbeth_speed_10, sbeth_speed_100, 	       sbeth_speed_1000 } sbeth_speed_t;typedef enum { sbeth_duplex_half,	       sbeth_duplex_full } sbeth_duplex_t;typedef enum { sbeth_fc_disabled, sbeth_fc_frame,	       sbeth_fc_collision, sbeth_fc_carrier } sbeth_fc_t;typedef enum { sbeth_state_uninit, sbeth_state_off, sbeth_state_on, 	       sbeth_state_broken } sbeth_state_t;typedef uint64_t  sbeth_enetaddr_t;typedef struct sbeth_s sbeth_t;		/* forward reference */static int sbeth_setspeed(sbeth_t *s,sbeth_speed_t speed);static int sbeth_set_duplex(sbeth_t *s,sbeth_duplex_t duplex,sbeth_fc_t fc);#define SBETH_MIIPOLL_TIMER	(4*CFE_HZ)/*  *********************************************************************    *  Descriptor structure    ********************************************************************* */typedef struct sbdmadscr_s {    uint64_t  dscr_a;    uint64_t  dscr_b;} sbdmadscr_t;/*  *********************************************************************    *  DMA structure    ********************************************************************* */typedef struct sbethdma_s {    /*      * This stuff is used to identify the channel and the registers     * associated with it.     */    sbeth_t         *sbdma_eth;	        /* back pointer to associated MAC */    int              sbdma_channel;	/* channel number */    int		     sbdma_txdir;       /* direction (1=transmit) */    int		     sbdma_maxdescr;	/* total # of descriptors in ring */    sbeth_port_t     sbdma_config0;	/* DMA config register 0 */    sbeth_port_t     sbdma_config1;	/* DMA config register 1 */    sbeth_port_t     sbdma_dscrbase;	/* Descriptor base address */    sbeth_port_t     sbdma_dscrcnt;     /* Descriptor count register */    sbeth_port_t     sbdma_curdscr;	/* current descriptor address */    /*     * This stuff is for maintenance of the ring     */    sbdmadscr_t     *sbdma_dscrtable;	/* base of descriptor table */    sbdmadscr_t     *sbdma_dscrtable_end; /* end of descriptor table */    void            **sbdma_ctxtable;   /* context table, one per descr */    int		     sbdma_onring;	/* count of packets on ring */    sbeth_physaddr_t sbdma_dscrtable_phys; /* and also the phys addr */    sbdmadscr_t     *sbdma_addptr;	/* next dscr for sw to add */    sbdmadscr_t     *sbdma_remptr;	/* next dscr for sw to remove */    void	   (*sbdma_upcall)(void *ifctx,int chan,void *ctx,				   uint64_t status,unsigned int length);} sbethdma_t;typedef struct sbeth_pkt_s {    struct sbeth_pkt_s *next;    void *devctx;    unsigned char *buffer;    int length;    /* packet data goes here */} sbeth_pkt_t;/*  *********************************************************************    *  Ethernet controller structure    ********************************************************************* */struct sbeth_s {    cfe_devctx_t    *sbe_devctx;    sbeth_port_t     sbe_baseaddr;	/* base address */    sbeth_state_t    sbe_state;         /* current state */    sbeth_port_t     sbe_macenable;	/* MAC Enable Register */    sbeth_port_t     sbe_maccfg;	/* MAC Configuration Register */    sbeth_port_t     sbe_fifocfg;	/* FIFO configuration register */    sbeth_port_t     sbe_framecfg;	/* Frame configuration register */    sbeth_port_t     sbe_rxfilter;	/* receive filter register */    sbeth_port_t     sbe_isr;		/* Interrupt status register */    sbeth_port_t     sbe_imr;		/* Interrupt mask register */    sbeth_port_t     sbe_mdio;		/* PHY control stuff */    sbeth_speed_t    sbe_speed;		/* current speed */    sbeth_duplex_t   sbe_duplex;	/* current duplex */    sbeth_fc_t       sbe_fc;		/* current flow control setting */    int		     sbe_rxflags;	/* received packet flags */    int		     sbe_autospeed;	/* true for automatic speed setting */    int		     sbe_curspeed;	/* value for GET SPEED ioctl */    int		     sbe_loopback;	/* IOCTL LOOPBACK stuff */    int		     sbe_linkstat;	/* Current link status */    sbethdma_t       sbe_txdma[SBETH_DMA_CHANNELS];	/* one for each channel */    sbethdma_t       sbe_rxdma[SBETH_DMA_CHANNELS];    void	    *sbe_ifctx;    int              sbe_minrxring;	/* min packets to keep on RX ring */    sbeth_pkt_t	    *sbe_rxqueue;	/* received packet queue */    sbeth_pkt_t     *sbe_freelist;	/* free packet list */    unsigned char   *sbe_pktpool;    unsigned char    sbe_hwaddr[ENET_ADDR_LEN];    int		     sbe_phyaddr;    uint32_t	     sbe_phyvendor;    uint32_t	     sbe_phydevice;    int		     sbe_zerormon;    uint32_t	     sbe_phy_oldbmsr;    uint32_t	     sbe_phy_oldbmcr;    uint32_t	     sbe_phy_oldanlpar;    uint32_t	     sbe_phy_oldk1stsr;    int64_t	     sbe_linkstat_timer;    int		     fifo_mode;		/* true if in packet fifo mode */};/*  *********************************************************************    *  Prototypes    ********************************************************************* */static int sbeth_transmit(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg);static int sbeth_addrcvbuf(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg);static int sbeth_initctx(sbeth_t *s,unsigned long baseaddr,void *ifctx);static void sbeth_start(sbeth_t *s);static void sbeth_stop(sbeth_t *s);static void sbeth_initfreelist(sbeth_t *s);static sbeth_pkt_t *sbeth_alloc_pkt(sbeth_t *s);static void sbeth_free_pkt(sbeth_t *s,sbeth_pkt_t *pkt);static void sbeth_tx_callback(void *ifctx,int chan,void *ctx,			      uint64_t status,unsigned int pktsize);static void sbeth_rx_callback(void *ifctx,int chan,void *ctx,			      uint64_t status,unsigned int pktsize);static void sbeth_fillrxring(sbeth_t *s,int chan);static void sb1250_ether_probe(cfe_driver_t *drv,			       unsigned long probe_a, unsigned long probe_b, 			       void *probe_ptr);static void sbeth_setaddr(sbeth_t *s,uint8_t *addr);/*  *********************************************************************    *  Macros    ********************************************************************* */#define sbdma_nextbuf(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \			  (d)->sbdma_dscrtable : (d)->f+1)#define SBDMA_CACHESIZE 32		/* wants to be somewhere else */#define SBDMA_NUMCACHEBLKS(x) ((x+SBDMA_CACHESIZE-1)/SBDMA_CACHESIZE)#define STRAP_PHY1	0x0800#define STRAP_NCMODE	0x0400#define STRAP_MANMSCFG	0x0200#define STRAP_ANENABLE	0x0100#define STRAP_MSVAL	0x0080#define STRAP_1KHDXADV	0x0010#define STRAP_1KFDXADV	0x0008#define STRAP_100ADV	0x0004#define STRAP_SPEEDSEL	0x0000#define STRAP_SPEED100	0x0001#define PHYSUP_SPEED1000 0x10#define PHYSUP_SPEED100  0x08#define PHYSUP_SPEED10   0x00#define PHYSUP_LINKUP	 0x04#define PHYSUP_FDX       0x02#define M_MAC_MDIO_DIR_OUTPUT	0		/* for clarity *//* ********************************************************************** *//*  *********************************************************************    *  SBETH_MII_SYNC(s)    *      *  Synchronize with the MII - send a pattern of bits to the MII    *  that will guarantee that it is ready to accept a command.    *      *  Input parameters:     *  	   s - sbmac structure    *  	       *  Return value:    *  	   nothing    ********************************************************************* */static void sbeth_mii_sync(sbeth_t *s){    int cnt;    uint64_t bits;    int mac_mdio_genc;    mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;    bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;    SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);    for (cnt = 0; cnt < 32; cnt++) {	SBETH_WRITECSR(s->sbe_mdio,bits | M_MAC_MDC | mac_mdio_genc);	SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);	}}/*  *********************************************************************    *  SBETH_MII_SENDDATA(s,data,bitcnt)    *      *  Send some bits to the MII.  The bits to be sent are right-    *  justified in the 'data' parameter.    *      *  Input parameters:     *  	   s - sbmac structure    *  	   data - data to send    *  	   bitcnt - number of bits to send    ********************************************************************* */static void sbeth_mii_senddata(sbeth_t *s,unsigned int data, int bitcnt){    int i;    uint64_t bits;    unsigned int curmask;    int mac_mdio_genc;    mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;    bits = M_MAC_MDIO_DIR_OUTPUT;    SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);    curmask = 1 << (bitcnt - 1);    for (i = 0; i < bitcnt; i++) {	if (data & curmask) bits |= M_MAC_MDIO_OUT;	else bits &= ~M_MAC_MDIO_OUT;	SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);	SBETH_WRITECSR(s->sbe_mdio,bits | M_MAC_MDC | mac_mdio_genc);	SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);	curmask >>= 1;	}}/*  *********************************************************************    *  SBETH_MII_READ(s,phyaddr,regidx)    *      *  Read a PHY register.    *      *  Input parameters:     *  	   s - sbmac structure    *  	   phyaddr - PHY's address    *  	   regidx = index of register to read    *  	       *  Return value:    *  	   value read, or 0 if an error occured.    ********************************************************************* */static unsigned int sbeth_mii_read(sbeth_t *s,int phyaddr,int regidx){    int idx;    int error;    int regval;    int mac_mdio_genc;    /*     * Synchronize ourselves so that the PHY knows the next     * thing coming down is a command     */    sbeth_mii_sync(s);    /*     * Send the data to the PHY.  The sequence is     * a "start" command (2 bits)     * a "read" command (2 bits)     * the PHY addr (5 bits)     * the register index (5 bits)     */    sbeth_mii_senddata(s,MII_COMMAND_START, 2);    sbeth_mii_senddata(s,MII_COMMAND_READ, 2);    sbeth_mii_senddata(s,phyaddr, 5);    sbeth_mii_senddata(s,regidx, 5);    mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;    /*      * Switch the port around without a clock transition.     */    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);    /*     * Send out a clock pulse to signal we want the status     */    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);    /*      * If an error occured, the PHY will signal '1' back     */    error = SBETH_READCSR(s->sbe_mdio) & M_MAC_MDIO_IN;    /*      * Issue an 'idle' clock pulse, but keep the direction     * the same.     */    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);    regval = 0;    for (idx = 0; idx < 16; idx++) {	regval <<= 1;	if (error == 0) {	    if (SBETH_READCSR(s->sbe_mdio) & M_MAC_MDIO_IN) regval |= 1;	    }	SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);	SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);	}    /* Switch back to output */    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);    if (error == 0) return regval;    return 0;}/*  *********************************************************************    *  SBETH_MII_WRITE(s,phyaddr,regidx,regval)    *      *  Write a value to a PHY register.    *      *  Input parameters:     *  	   s - sbmac structure    *  	   phyaddr - PHY to use    *  	   regidx - register within the PHY    *  	   regval - data to write to register    *  	       *  Return value:    *  	   nothing    ********************************************************************* */void sbeth_mii_write(sbeth_t *s,int phyaddr,int regidx,		     unsigned int regval);void sbeth_mii_write(sbeth_t *s,int phyaddr,int regidx,

⌨️ 快捷键说明

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