/* * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx. * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) * * This version of the driver is specific to the FADS implementation, * since the board contains control registers external to the processor * for the control of the LevelOne LXT970 transceiver. The MPC860T manual * describes connections using the internal parallel port I/O, which * is basically all of Port D. * * Right now, I am very wasteful with the buffers. I allocate memory * pages and then divide them into 2K frame buffers. This way I know I * have buffers large enough to hold one frame within one buffer descriptor. * Once I get this working, I will use 64 or 128 byte CPM buffers, which * will be much more memory efficient and will easily handle lots of * small packets. * * Much better multiple PHY support by Magnus Damm. * Copyright (c) 2000 Ericsson Radio Systems AB. * * Support for FEC controller of ColdFire processors. * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com) * * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) * Copyright (c) 2004-2006 Macq Electronique SA. */ #include <linux/module.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/ptrace.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/spinlock.h>#include <linux/workqueue.h>#include <linux/bitops.h> #include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/pgtable.h> #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ defined(CONFIG_M5272) || defined(CONFIG_M528x) || \ defined(CONFIG_M520x) || defined(CONFIG_M532x)#include <asm/coldfire.h>#include <asm/mcfsim.h>#include "fec.h"#else#include <asm/8xx_immap.h>#include <asm/mpc8xx.h>#include "commproc.h"#endif #if defined(CONFIG_FEC2)#define FEC_MAX_PORTS 2#else#define FEC_MAX_PORTS 1#endif /* * Define the fixed address of the FEC hardware. */static unsigned int fec_hw[] = {#if defined(CONFIG_M5272) (MCF_MBAR + 0x840),#elif defined(CONFIG_M527x) (MCF_MBAR + 0x1000), (MCF_MBAR + 0x1800),#elif defined(CONFIG_M523x) || defined(CONFIG_M528x) (MCF_MBAR + 0x1000),#elif defined(CONFIG_M520x) (MCF_MBAR+0x30000),#elif defined(CONFIG_M532x) (MCF_MBAR+0xfc030000),#else &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),#endif}; static unsigned char fec_mac_default[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}; /* * Some hardware gets it MAC address out of local flash memory. * if this is non-zero then assume it is the address to get MAC from. */#if defined(CONFIG_NETtel)#define FEC_FLASHMAC 0xf0006006#elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES)#define FEC_FLASHMAC 0xf0006000#elif defined (CONFIG_MTD_KeyTechnology)#define FEC_FLASHMAC 0xffe04000#elif defined(CONFIG_CANCam)#define FEC_FLASHMAC 0xf0020000#elif defined (CONFIG_M5272C3)#define FEC_FLASHMAC (0xffe04000 + 4)#elif defined(CONFIG_MOD5272)#define FEC_FLASHMAC 0xffc0406b#else#define FEC_FLASHMAC 0#endif /* Forward declarations of some structures to support different PHYs*/ typedef struct { uint mii_data; void (*funct)(uint mii_reg, struct net_device *dev);} phy_cmd_t; typedef struct { uint id; char *name; const phy_cmd_t *config; const phy_cmd_t *startup; const phy_cmd_t *ack_int; const phy_cmd_t *shutdown;} phy_info_t; /* The number of Tx and Rx buffers. These are allocated from the page * pool. The code may assume these are power of two, so it it best * to keep them that size. * We don't need to allocate pages for the transmitter. We just use * the skbuffer directly. */#define FEC_ENET_RX_PAGES 8#define FEC_ENET_RX_FRSIZE 2048#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)#define FEC_ENET_TX_FRSIZE 2048#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE)#define TX_RING_SIZE 16 /* Must be power of two */#define TX_RING_MOD_MASK 15 /* for this to work */ #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE)#error "FEC: descriptor ring size constants too large"#endif /* Interrupt events/masks.*/#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ /* The FEC stores dest/src/type, data, and checksum for receive packets. */#define PKT_MAXBUF_SIZE 1518#define PKT_MINBUF_SIZE 64#define PKT_MAXBLR_SIZE 1520 /* * The 5270/5271/5280/5282/532x RX control register also contains maximum frame * size bits. Other FEC hardware does not, so we need to take that into * account when setting it. */#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ defined(CONFIG_M520x) || defined(CONFIG_M532x)#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)#else#define OPT_FRAME_SIZE 0#endif /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and * tx_bd_base always point to the base of the buffer descriptors. The * cur_rx and cur_tx point to the currently available buffer. * The dirty_tx tracks the current buffer that is being sent by the * controller. The cur_tx and dirty_tx are equal under both completely * empty and completely full conditions. The empty/ready indicator in * the buffer descriptor determines the actual condition. */struct fec_enet_private { /* Hardware registers of the FEC device */ volatile fec_t *hwp; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; ushort skb_cur; ushort skb_dirty; /* CPM dual port RAM relative addresses. */ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ cbd_t *tx_bd_base; cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ cbd_t *dirty_tx; /* The ring entries to be free()ed. */ struct net_device_stats stats; uint tx_full; spinlock_t lock; uint phy_id; uint phy_id_done; uint phy_status; uint phy_speed; phy_info_t const *phy; struct work_struct phy_task; uint sequence_done; uint mii_phy_task_queued; uint phy_addr; int index; int opened; int link; int old_link; int full_duplex;}; static int fec_enet_open(struct net_device *dev);static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);static void fec_enet_mii(struct net_device *dev);static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);static void fec_enet_tx(struct net_device *dev);static void fec_enet_rx(struct net_device *dev);static int fec_enet_close(struct net_device *dev);static struct net_device_stats *fec_enet_get_stats(struct net_device *dev);static void set_multicast_list(struct net_device *dev);static void fec_restart(struct net_device *dev, int duplex);static void fec_stop(struct net_device *dev);static void fec_set_mac_address(struct net_device *dev); /* MII processing. We keep this as simple as possible. Requests are * placed on the list (if there is room). When the request is finished * by the MII, an optional function may be called. */typedef struct mii_list { uint mii_regval; void (*mii_func)(uint val, struct net_device *dev); struct mii_list *mii_next;} mii_list_t; #define NMII 20static mii_list_t mii_cmds[NMII];static mii_list_t *mii_free;static mii_list_t *mii_head;static mii_list_t *mii_tail; static int mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *)); /* Make MII read/write commands for the FEC.*/#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ (VAL & 0xffff))#define mk_mii_end 0 /* Transmitter timeout.*/#define TX_TIMEOUT (2*HZ) /* Register definitions for the PHY.*/ #define MII_REG_CR 0 /* Control Register */#define MII_REG_SR 1 /* Status Register */#define MII_REG_PHYIR1 2 /* PHY Identification Register 1 */#define MII_REG_PHYIR2 3 /* PHY Identification Register 2 */#define MII_REG_ANAR 4 /* A-N Advertisement Register */#define MII_REG_ANLPAR 5 /* A-N Link Partner Ability Register */#define MII_REG_ANER 6 /* A-N Expansion Register */#define MII_REG_ANNPTR 7 /* A-N Next Page Transmit Register */#define MII_REG_ANLPRNPR 8 /* A-N Link Partner Received Next Page Reg. */ /* values for phy_status */ #define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */#define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */#define PHY_CONF_SPMASK 0x00f0 /* mask for speed */#define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */#define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */#define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */#define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */ #define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */#define PHY_STAT_FAULT 0x0200 /* 1 remote fault */#define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */#define PHY_STAT_SPMASK 0xf000 /* mask for speed */#define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */#define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */#define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */#define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */ static intfec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev){ struct fec_enet_private *fep; volatile fec_t *fecp; volatile cbd_t *bdp; unsigned short status; fep = netdev_priv(dev); fecp = (volatile fec_t*)dev->base_addr; if (!fep->link) { /* Link is down or autonegotiation is in progress. */ return 1; } /* Fill in a Tx ring entry */ bdp = fep->cur_tx; status = bdp->cbd_sc;#ifndef final_version if (status & BD_ENET_TX_READY) { /* Ooops. All transmit buffers are full. Bail out. * This should not happen, since dev->tbusy should be set. */ printk("%s: tx queue full!.\n", dev->name); return 1; }#endif /* Clear all of the status flags. */ status &= ~BD_ENET_TX_STATS; /* Set buffer length and buffer pointer. */ bdp->cbd_bufaddr = __pa(skb->data); bdp->cbd_datlen = skb->len; /* * On some FEC implementations data must be aligned on * 4-byte boundaries. Use bounce buffers to copy data * and get it aligned. Ugh. */ if (bdp->cbd_bufaddr & 0x3) { unsigned int index; index = bdp - fep->tx_bd_base; memcpy(fep->tx_bounce[index], (void *) bdp->cbd_bufaddr, bdp->cbd_datlen); bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); } /* Save skb pointer. */ fep->tx_skbuff[fep->skb_cur] = skb; fep->stats.tx_bytes += skb->len; fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; /* Push the data cache so the CPM does not get stale memory * data. */ flush_dcache_range((unsigned long)skb->data, (unsigned long)skb->data + skb->len); spin_lock_irq(&fep->lock); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. */ status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); bdp->cbd_sc = status; dev->trans_start = jiffies; /* Trigger transmission start */ fecp->fec_x_des_active = 0; /* If this was the last BD in the ring, start at the beginning again. */ if (status & BD_ENET_TX_WRAP) { bdp = fep->tx_bd_base; } else { bdp++; } if (bdp == fep->dirty_tx) { fep->tx_full = 1; netif_stop_queue(dev); } fep->cur_tx = (cbd_t *)bdp; spin_unlock_irq(&fep->lock); return 0;} static voidfec_timeout(struct net_device *dev){ struct fec_enet_private *fep = netdev_priv(dev); printk("%s: transmit timed out.\n", dev->name); fep->stats.tx_errors++;#ifndef final_version { int i; cbd_t *bdp; printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n", (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "", (unsigned long)fep->dirty_tx, (unsigned long)fep->cur_rx); bdp = fep->tx_bd_base; printk(" tx: %u buffers\n", TX_RING_SIZE); for (i = 0 ; i < TX_RING_SIZE; i++) { printk(" %08x: %04x %04x %08x\n", (uint) bdp, bdp->cbd_sc, bdp->cbd_datlen, (int) bdp->cbd_bufaddr); bdp++; } bdp = fep->rx_bd_base; printk(" rx: %lu buffers\n", (unsigned long) RX_RING_SIZE); for (i = 0 ; i < RX_RING_SIZE; i++) { printk(" %08x: %04x %04x %08x\n", (uint) bdp, bdp->cbd_sc, bdp->cbd_datlen, (int) bdp->cbd_bufaddr); bdp++; } }#endif fec_restart(dev, fep->full_duplex); netif_wake_queue(dev);} /* The interrupt handler. * This is called from the MPC core interrupt. */static irqreturn_tfec_enet_interrupt(int irq, void * dev_id){ struct net_device *dev = dev_id; volatile fec_t *fecp; uint int_events; int handled = 0; fecp = (volatile fec_t*)dev->base_addr; /* Get the interrupt events that caused us to be here. */ while ((int_events = fecp->fec_ievent) != 0) { fecp->fec_ievent = int_events; /* Handle receive event in its own function. */ if (int_events & FEC_ENET_RXF) { handled = 1; fec_enet_rx(dev); } /* Transmit OK, or non-fatal error. Update the buffer descriptors. FEC handles all errors, we just discover them as part of the transmit process. */ if (int_events & FEC_ENET_TXF) { handled = 1; fec_enet_tx(dev); } if (int_events & FEC_ENET_MII) { handled = 1; fec_enet_mii(dev); } } return IRQ_RETVAL(handled);} static voidfec_enet_tx(struct net_device *dev){ struct fec_enet_private *fep; volatile cbd_t *bdp; unsigned short status; struct sk_buff *skb; Lines 1–500 of 2650. Load more
/* * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx. * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) * * This version of the driver is specific to the FADS implementation, * since the board contains control registers external to the processor * for the control of the LevelOne LXT970 transceiver. The MPC860T manual * describes connections using the internal parallel port I/O, which * is basically all of Port D. * * Right now, I am very wasteful with the buffers. I allocate memory * pages and then divide them into 2K frame buffers. This way I know I * have buffers large enough to hold one frame within one buffer descriptor. * Once I get this working, I will use 64 or 128 byte CPM buffers, which * will be much more memory efficient and will easily handle lots of * small packets. * * Much better multiple PHY support by Magnus Damm. * Copyright (c) 2000 Ericsson Radio Systems AB. * * Support for FEC controller of ColdFire processors. * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com) * * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) * Copyright (c) 2004-2006 Macq Electronique SA. */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/bitops.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/pgtable.h> #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ defined(CONFIG_M5272) || defined(CONFIG_M528x) || \ defined(CONFIG_M520x) || defined(CONFIG_M532x) #include <asm/coldfire.h> #include <asm/mcfsim.h> #include "fec.h" #else #include <asm/8xx_immap.h> #include <asm/mpc8xx.h> #include "commproc.h" #endif #if defined(CONFIG_FEC2) #define FEC_MAX_PORTS 2 #else #define FEC_MAX_PORTS 1 #endif /* * Define the fixed address of the FEC hardware. */ static unsigned int fec_hw[] = { #if defined(CONFIG_M5272) (MCF_MBAR + 0x840), #elif defined(CONFIG_M527x) (MCF_MBAR + 0x1000), (MCF_MBAR + 0x1800), #elif defined(CONFIG_M523x) || defined(CONFIG_M528x) (MCF_MBAR + 0x1000), #elif defined(CONFIG_M520x) (MCF_MBAR+0x30000), #elif defined(CONFIG_M532x) (MCF_MBAR+0xfc030000), #else &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), #endif }; static unsigned char fec_mac_default[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; /* * Some hardware gets it MAC address out of local flash memory. * if this is non-zero then assume it is the address to get MAC from. */ #if defined(CONFIG_NETtel) #define FEC_FLASHMAC 0xf0006006 #elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES) #define FEC_FLASHMAC 0xf0006000 #elif defined (CONFIG_MTD_KeyTechnology) #define FEC_FLASHMAC 0xffe04000 #elif defined(CONFIG_CANCam) #define FEC_FLASHMAC 0xf0020000 #elif defined (CONFIG_M5272C3) #define FEC_FLASHMAC (0xffe04000 + 4) #elif defined(CONFIG_MOD5272) #define FEC_FLASHMAC 0xffc0406b #else #define FEC_FLASHMAC 0 #endif /* Forward declarations of some structures to support different PHYs */ typedef struct { uint mii_data; void (*funct)(uint mii_reg, struct net_device *dev); } phy_cmd_t; typedef struct { uint id; char *name; const phy_cmd_t *config; const phy_cmd_t *startup; const phy_cmd_t *ack_int; const phy_cmd_t *shutdown; } phy_info_t; /* The number of Tx and Rx buffers. These are allocated from the page * pool. The code may assume these are power of two, so it it best * to keep them that size. * We don't need to allocate pages for the transmitter. We just use * the skbuffer directly. */ #define FEC_ENET_RX_PAGES 8 #define FEC_ENET_RX_FRSIZE 2048 #define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) #define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) #define FEC_ENET_TX_FRSIZE 2048 #define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) #define TX_RING_SIZE 16 /* Must be power of two */ #define TX_RING_MOD_MASK 15 /* for this to work */ #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) #error "FEC: descriptor ring size constants too large" #endif /* Interrupt events/masks. */ #define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ #define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ #define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ #define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ #define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */ #define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ #define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */ #define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */ #define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ #define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ /* The FEC stores dest/src/type, data, and checksum for receive packets. */ #define PKT_MAXBUF_SIZE 1518 #define PKT_MINBUF_SIZE 64 #define PKT_MAXBLR_SIZE 1520 /* * The 5270/5271/5280/5282/532x RX control register also contains maximum frame * size bits. Other FEC hardware does not, so we need to take that into * account when setting it. */ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ defined(CONFIG_M520x) || defined(CONFIG_M532x) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #else #define OPT_FRAME_SIZE 0 #endif /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and * tx_bd_base always point to the base of the buffer descriptors. The * cur_rx and cur_tx point to the currently available buffer. * The dirty_tx tracks the current buffer that is being sent by the * controller. The cur_tx and dirty_tx are equal under both completely * empty and completely full conditions. The empty/ready indicator in * the buffer descriptor determines the actual condition. */ struct fec_enet_private { /* Hardware registers of the FEC device */ volatile fec_t *hwp; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; ushort skb_cur; ushort skb_dirty; /* CPM dual port RAM relative addresses. */ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ cbd_t *tx_bd_base; cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ cbd_t *dirty_tx; /* The ring entries to be free()ed. */ struct net_device_stats stats; uint tx_full; spinlock_t lock; uint phy_id; uint phy_id_done; uint phy_status; uint phy_speed; phy_info_t const *phy; struct work_struct phy_task; uint sequence_done; uint mii_phy_task_queued; uint phy_addr; int index; int opened; int link; int old_link; int full_duplex; }; static int fec_enet_open(struct net_device *dev); static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); static void fec_enet_mii(struct net_device *dev); static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); static void fec_enet_tx(struct net_device *dev); static void fec_enet_rx(struct net_device *dev); static int fec_enet_close(struct net_device *dev); static struct net_device_stats *fec_enet_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void fec_restart(struct net_device *dev, int duplex); static void fec_stop(struct net_device *dev); static void fec_set_mac_address(struct net_device *dev); /* MII processing. We keep this as simple as possible. Requests are * placed on the list (if there is room). When the request is finished * by the MII, an optional function may be called. */ typedef struct mii_list { uint mii_regval; void (*mii_func)(uint val, struct net_device *dev); struct mii_list *mii_next; } mii_list_t; #define NMII 20 static mii_list_t mii_cmds[NMII]; static mii_list_t *mii_free; static mii_list_t *mii_head; static mii_list_t *mii_tail; static int mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *)); /* Make MII read/write commands for the FEC. */ #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ (VAL & 0xffff)) #define mk_mii_end 0 /* Transmitter timeout. */ #define TX_TIMEOUT (2*HZ) /* Register definitions for the PHY. */ #define MII_REG_CR 0 /* Control Register */ #define MII_REG_SR 1 /* Status Register */ #define MII_REG_PHYIR1 2 /* PHY Identification Register 1 */ #define MII_REG_PHYIR2 3 /* PHY Identification Register 2 */ #define MII_REG_ANAR 4 /* A-N Advertisement Register */ #define MII_REG_ANLPAR 5 /* A-N Link Partner Ability Register */ #define MII_REG_ANER 6 /* A-N Expansion Register */ #define MII_REG_ANNPTR 7 /* A-N Next Page Transmit Register */ #define MII_REG_ANLPRNPR 8 /* A-N Link Partner Received Next Page Reg. */ /* values for phy_status */ #define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */ #define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */ #define PHY_CONF_SPMASK 0x00f0 /* mask for speed */ #define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */ #define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */ #define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */ #define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */ #define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */ #define PHY_STAT_FAULT 0x0200 /* 1 remote fault */ #define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */ #define PHY_STAT_SPMASK 0xf000 /* mask for speed */ #define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */ #define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */ #define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */ #define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */ static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fec_enet_private *fep; volatile fec_t *fecp; volatile cbd_t *bdp; unsigned short status; fep = netdev_priv(dev); fecp = (volatile fec_t*)dev->base_addr; if (!fep->link) { /* Link is down or autonegotiation is in progress. */ return 1; } /* Fill in a Tx ring entry */ bdp = fep->cur_tx; status = bdp->cbd_sc; #ifndef final_version if (status & BD_ENET_TX_READY) { /* Ooops. All transmit buffers are full. Bail out. * This should not happen, since dev->tbusy should be set. */ printk("%s: tx queue full!.\n", dev->name); return 1; } #endif /* Clear all of the status flags. */ status &= ~BD_ENET_TX_STATS; /* Set buffer length and buffer pointer. */ bdp->cbd_bufaddr = __pa(skb->data); bdp->cbd_datlen = skb->len; /* * On some FEC implementations data must be aligned on * 4-byte boundaries. Use bounce buffers to copy data * and get it aligned. Ugh. */ if (bdp->cbd_bufaddr & 0x3) { unsigned int index; index = bdp - fep->tx_bd_base; memcpy(fep->tx_bounce[index], (void *) bdp->cbd_bufaddr, bdp->cbd_datlen); bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); } /* Save skb pointer. */ fep->tx_skbuff[fep->skb_cur] = skb; fep->stats.tx_bytes += skb->len; fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; /* Push the data cache so the CPM does not get stale memory * data. */ flush_dcache_range((unsigned long)skb->data, (unsigned long)skb->data + skb->len); spin_lock_irq(&fep->lock); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. */ status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); bdp->cbd_sc = status; dev->trans_start = jiffies; /* Trigger transmission start */ fecp->fec_x_des_active = 0; /* If this was the last BD in the ring, start at the beginning again. */ if (status & BD_ENET_TX_WRAP) { bdp = fep->tx_bd_base; } else { bdp++; } if (bdp == fep->dirty_tx) { fep->tx_full = 1; netif_stop_queue(dev); } fep->cur_tx = (cbd_t *)bdp; spin_unlock_irq(&fep->lock); return 0; } static void fec_timeout(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); printk("%s: transmit timed out.\n", dev->name); fep->stats.tx_errors++; #ifndef final_version { int i; cbd_t *bdp; printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n", (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "", (unsigned long)fep->dirty_tx, (unsigned long)fep->cur_rx); bdp = fep->tx_bd_base; printk(" tx: %u buffers\n", TX_RING_SIZE); for (i = 0 ; i < TX_RING_SIZE; i++) { printk(" %08x: %04x %04x %08x\n", (uint) bdp, bdp->cbd_sc, bdp->cbd_datlen, (int) bdp->cbd_bufaddr); bdp++; } bdp = fep->rx_bd_base; printk(" rx: %lu buffers\n", (unsigned long) RX_RING_SIZE); for (i = 0 ; i < RX_RING_SIZE; i++) { printk(" %08x: %04x %04x %08x\n", (uint) bdp, bdp->cbd_sc, bdp->cbd_datlen, (int) bdp->cbd_bufaddr); bdp++; } } #endif fec_restart(dev, fep->full_duplex); netif_wake_queue(dev); } /* The interrupt handler. * This is called from the MPC core interrupt. */ static irqreturn_t fec_enet_interrupt(int irq, void * dev_id) { struct net_device *dev = dev_id; volatile fec_t *fecp; uint int_events; int handled = 0; fecp = (volatile fec_t*)dev->base_addr; /* Get the interrupt events that caused us to be here. */ while ((int_events = fecp->fec_ievent) != 0) { fecp->fec_ievent = int_events; /* Handle receive event in its own function. */ if (int_events & FEC_ENET_RXF) { handled = 1; fec_enet_rx(dev); } /* Transmit OK, or non-fatal error. Update the buffer descriptors. FEC handles all errors, we just discover them as part of the transmit process. */ if (int_events & FEC_ENET_TXF) { handled = 1; fec_enet_tx(dev); } if (int_events & FEC_ENET_MII) { handled = 1; fec_enet_mii(dev); } } return IRQ_RETVAL(handled); } static void fec_enet_tx(struct net_device *dev) { struct fec_enet_private *fep; volatile cbd_t *bdp; unsigned short status; struct sk_buff *skb;