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