sb1250-mac.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,624 行 · 第 1/5 页

C
2,624
字号
/* * Copyright (C) 2001,2002,2003 Broadcom Corporation * * This program 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 * of the License, or (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. *//*  This driver is designed for the Broadcom SiByte SOC built-in  Ethernet controllers.    Written by Mitch Lichtenberg at Broadcom Corp.*/#define CONFIG_SBMAC_COALESCE/* A few user-configurable values.   These may be modified when a driver module is loaded. */static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */static int noisy_mii = 1;		/* mii status msgs *//* Used to pass the media type, etc.   Both 'options[]' and 'full_duplex[]' should exist for driver   interoperability.   The media type is usually passed in 'options[]'.*/#define MAX_UNITS 3		/* More are supported, limit only on options */#ifdef MODULEstatic int options[MAX_UNITS] = {-1, -1, -1};static int full_duplex[MAX_UNITS] = {-1, -1, -1};#endif#ifdef CONFIG_SBMAC_COALESCEstatic int int_pktcnt = 0;static int int_timeout = 0;#endif/* Operational parameters that usually are not changed. *//* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT  (2*HZ)#include <linux/module.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/init.h>#include <linux/config.h>#include <asm/processor.h>		/* Processor type for cache alignment. */#include <asm/bitops.h>#include <asm/io.h>#include <asm/cache.h>/* This is only here until the firmware is ready.  In that case,   the firmware leaves the ethernet address in the register for us. */#ifdef CONFIG_SIBYTE_STANDALONE#define SBMAC_ETH0_HWADDR "40:00:00:00:01:00"#define SBMAC_ETH1_HWADDR "40:00:00:00:01:01"#define SBMAC_ETH2_HWADDR "40:00:00:00:01:02"#endif/* These identify the driver base version and may not be removed. */#if 0static char version1[] __devinitdata ="sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg\n";#endifMODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)");MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver");MODULE_PARM(debug, "i");MODULE_PARM(noisy_mii, "i");MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(int_pktcnt, "i");MODULE_PARM(int_timeout, "i");#include <asm/sibyte/sb1250.h>#include <asm/sibyte/sb1250_defs.h>#include <asm/sibyte/sb1250_regs.h>#include <asm/sibyte/sb1250_mac.h>#include <asm/sibyte/sb1250_dma.h>#include <asm/sibyte/sb1250_int.h>#include <asm/sibyte/sb1250_scd.h>/********************************************************************** *  Simple types ********************************************************************* */typedef unsigned long sbmac_port_t;typedef enum { sbmac_speed_auto, sbmac_speed_10,	       sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;typedef enum { sbmac_duplex_auto, sbmac_duplex_half,	       sbmac_duplex_full } sbmac_duplex_t;typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame,	       sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t;typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on, 	       sbmac_state_broken } sbmac_state_t;/********************************************************************** *  Macros ********************************************************************* */#define SBDMA_NEXTBUF(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \			  (d)->sbdma_dscrtable : (d)->f+1)#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)#define SBMAC_READCSR(t)	__raw_readq((unsigned long)t)#define SBMAC_WRITECSR(t,v)	__raw_writeq(v, (unsigned long)t) #define SBMAC_MAX_TXDESCR	32#define SBMAC_MAX_RXDESCR	32#define ETHER_ALIGN	2#define ETHER_ADDR_LEN	6#define ENET_PACKET_SIZE	1518 /*#define ENET_PACKET_SIZE	9216 */ /********************************************************************** *  DMA Descriptor structure ********************************************************************* */typedef struct sbdmadscr_s {	uint64_t  dscr_a;	uint64_t  dscr_b;} sbdmadscr_t;typedef unsigned long paddr_t;/********************************************************************** *  DMA Controller structure ********************************************************************* */typedef struct sbmacdma_s {		/* 	 * This stuff is used to identify the channel and the registers	 * associated with it.	 */		struct sbmac_softc *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 */#ifdef CONFIG_SBMAC_COALESCE	int		 sbdma_int_pktcnt;  /* # descriptors rx/tx before interrupt*/	int		 sbdma_int_timeout; /* # usec rx/tx interrupt */#endif	sbmac_port_t     sbdma_config0;	/* DMA config register 0 */	sbmac_port_t     sbdma_config1;	/* DMA config register 1 */	sbmac_port_t     sbdma_dscrbase;	/* Descriptor base address */	sbmac_port_t     sbdma_dscrcnt;     /* Descriptor count register */	sbmac_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 */		struct sk_buff **sbdma_ctxtable;    /* context table, one per descr */		paddr_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 */} sbmacdma_t;/********************************************************************** *  Ethernet softc structure ********************************************************************* */struct sbmac_softc {		/*	 * Linux-specific things	 */		struct net_device *sbm_dev;		/* pointer to linux device */	spinlock_t sbm_lock;		/* spin lock */	struct timer_list sbm_timer;     	/* for monitoring MII */	struct net_device_stats sbm_stats; 	int sbm_devflags;			/* current device flags */	int	     sbm_phy_oldbmsr;	int	     sbm_phy_oldanlpar;	int	     sbm_phy_oldk1stsr;	int	     sbm_phy_oldlinkstat;	int sbm_buffersize;		unsigned char sbm_phys[2];		/*	 * Controller-specific things	 */		unsigned long	sbm_base;          /* MAC's base address */	sbmac_state_t    sbm_state;         /* current state */		sbmac_port_t     sbm_macenable;	/* MAC Enable Register */	sbmac_port_t     sbm_maccfg;	/* MAC Configuration Register */	sbmac_port_t     sbm_fifocfg;	/* FIFO configuration register */	sbmac_port_t     sbm_framecfg;	/* Frame configuration register */	sbmac_port_t     sbm_rxfilter;	/* receive filter register */	sbmac_port_t     sbm_isr;		/* Interrupt status register */	sbmac_port_t     sbm_imr;		/* Interrupt mask register */	sbmac_port_t     sbm_mdio;		/* MDIO register */		sbmac_speed_t    sbm_speed;		/* current speed */	sbmac_duplex_t   sbm_duplex;	/* current duplex */	sbmac_fc_t       sbm_fc;		/* current flow control setting */		unsigned char    sbm_hwaddr[ETHER_ADDR_LEN];		sbmacdma_t       sbm_txdma;		/* for now, only use channel 0 */	sbmacdma_t       sbm_rxdma;	int              rx_hw_checksum;	int 		 sbe_idx;};/********************************************************************** *  Externs ********************************************************************* *//********************************************************************** *  Prototypes ********************************************************************* */static void sbdma_initctx(sbmacdma_t *d,			  struct sbmac_softc *s,			  int chan,			  int txrx,			  int maxdescr);static void sbdma_channel_start(sbmacdma_t *d, int rxtx);static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *m);static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *m);static void sbdma_emptyring(sbmacdma_t *d);static void sbdma_fillring(sbmacdma_t *d);static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d);static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d);static int sbmac_initctx(struct sbmac_softc *s);static void sbmac_channel_start(struct sbmac_softc *s);static void sbmac_channel_stop(struct sbmac_softc *s);static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *,sbmac_state_t);static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff);static uint64_t sbmac_addr2reg(unsigned char *ptr);static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs);static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);static void sbmac_setmulti(struct sbmac_softc *sc);static int sbmac_init(struct net_device *dev, int idx);static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed);static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc);static int sbmac_open(struct net_device *dev);static void sbmac_timer(unsigned long data);static void sbmac_tx_timeout (struct net_device *dev);static struct net_device_stats *sbmac_get_stats(struct net_device *dev);static void sbmac_set_rx_mode(struct net_device *dev);static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int sbmac_close(struct net_device *dev);static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);static void sbmac_mii_sync(struct sbmac_softc *s);static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt);static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx);static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,			    unsigned int regval);/********************************************************************** *  Globals ********************************************************************* */static uint64_t sbmac_orig_hwaddr[MAX_UNITS];/********************************************************************** *  MDIO constants ********************************************************************* */#define	MII_COMMAND_START	0x01#define	MII_COMMAND_READ	0x02#define	MII_COMMAND_WRITE	0x01#define	MII_COMMAND_ACK		0x02#define BMCR_RESET     0x8000#define BMCR_LOOPBACK  0x4000#define BMCR_SPEED0    0x2000#define BMCR_ANENABLE  0x1000#define BMCR_POWERDOWN 0x0800#define BMCR_ISOLATE   0x0400#define BMCR_RESTARTAN 0x0200#define BMCR_DUPLEX    0x0100#define BMCR_COLTEST   0x0080#define BMCR_SPEED1    0x0040#define BMCR_SPEED1000	BMCR_SPEED1#define BMCR_SPEED100	BMCR_SPEED0#define BMCR_SPEED10 	0#define BMSR_100BT4	0x8000#define BMSR_100BT_FDX	0x4000#define BMSR_100BT_HDX  0x2000#define BMSR_10BT_FDX   0x1000#define BMSR_10BT_HDX   0x0800#define BMSR_100BT2_FDX 0x0400#define BMSR_100BT2_HDX 0x0200#define BMSR_1000BT_XSR	0x0100#define BMSR_PRESUP	0x0040#define BMSR_ANCOMPLT	0x0020#define BMSR_REMFAULT	0x0010#define BMSR_AUTONEG	0x0008#define BMSR_LINKSTAT	0x0004#define BMSR_JABDETECT	0x0002#define BMSR_EXTCAPAB	0x0001#define PHYIDR1 	0x2000#define PHYIDR2		0x5C60#define ANAR_NP		0x8000#define ANAR_RF		0x2000#define ANAR_ASYPAUSE	0x0800#define ANAR_PAUSE	0x0400#define ANAR_T4		0x0200#define ANAR_TXFD	0x0100#define ANAR_TXHD	0x0080#define ANAR_10FD	0x0040#define ANAR_10HD	0x0020#define ANAR_PSB	0x0001#define ANLPAR_NP	0x8000#define ANLPAR_ACK	0x4000#define ANLPAR_RF	0x2000#define ANLPAR_ASYPAUSE	0x0800#define ANLPAR_PAUSE	0x0400#define ANLPAR_T4	0x0200#define ANLPAR_TXFD	0x0100#define ANLPAR_TXHD	0x0080#define ANLPAR_10FD	0x0040#define ANLPAR_10HD	0x0020#define ANLPAR_PSB	0x0001	/* 802.3 */#define ANER_PDF	0x0010#define ANER_LPNPABLE	0x0008#define ANER_NPABLE	0x0004#define ANER_PAGERX	0x0002#define ANER_LPANABLE	0x0001#define ANNPTR_NP	0x8000#define ANNPTR_MP	0x2000#define ANNPTR_ACK2	0x1000#define ANNPTR_TOGTX	0x0800#define ANNPTR_CODE	0x0008#define ANNPRR_NP	0x8000#define ANNPRR_MP	0x2000#define ANNPRR_ACK3	0x1000#define ANNPRR_TOGTX	0x0800#define ANNPRR_CODE	0x0008#define K1TCR_TESTMODE	0x0000#define K1TCR_MSMCE	0x1000#define K1TCR_MSCV	0x0800#define K1TCR_RPTR	0x0400#define K1TCR_1000BT_FDX 0x200#define K1TCR_1000BT_HDX 0x100#define K1STSR_MSMCFLT	0x8000#define K1STSR_MSCFGRES	0x4000#define K1STSR_LRSTAT	0x2000#define K1STSR_RRSTAT	0x1000#define K1STSR_LP1KFD	0x0800#define K1STSR_LP1KHD   0x0400#define K1STSR_LPASMDIR	0x0200#define K1SCR_1KX_FDX	0x8000#define K1SCR_1KX_HDX	0x4000#define K1SCR_1KT_FDX	0x2000#define K1SCR_1KT_HDX	0x1000#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	MII_BMCR	0x00 	/* Basic mode control register (rw) */#define	MII_BMSR	0x01	/* Basic mode status register (ro) */#define MII_K1STSR	0x0A	/* 1K Status Register (ro) */#define	MII_ANLPAR	0x05	/* Autonegotiation lnk partner abilities (rw) */#define M_MAC_MDIO_DIR_OUTPUT	0		/* for clarity */#define ENABLE 		1#define DISABLE		0/********************************************************************** *  SBMAC_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 sbmac_mii_sync(struct sbmac_softc *s){	int cnt;	uint64_t bits;	int mac_mdio_genc;	mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;		bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;		SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);		for (cnt = 0; cnt < 32; cnt++) {		SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);		SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);	}}/********************************************************************** *  SBMAC_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 sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt){	int i;	uint64_t bits;	unsigned int curmask;	int mac_mdio_genc;	mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;		bits = M_MAC_MDIO_DIR_OUTPUT;	SBMAC_WRITECSR(s->sbm_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;		SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);		SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);		SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);		curmask >>= 1;	}}/********************************************************************** *  SBMAC_MII_READ(s,phyaddr,regidx) *   *  Read a PHY register. *   *  Input parameters:  *  	   s - sbmac structure *  	   phyaddr - PHY's address *  	   regidx = index of register to read

⌨️ 快捷键说明

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