📄 dev_sb1250_ethernet.c
字号:
/* ********************************************************************* * 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 + -