/*
* Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
*
* Copyright (c) 2003 Intracom S.A.
* by Pantelis Antoniou <panto@intracom.gr>
*
* Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
* and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
*
* Released under the GPL
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.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/init.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/dma-mapping.h>
#include <asm/8xx_immap.h>
#include <asm/pgtable.h>
#include <asm/mpc8xx.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/commproc.h>
#include "fec_8xx.h"
/*************************************************/
#define FEC_MAX_MULTICAST_ADDRS 64
/*************************************************/
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
MODULE_DESCRIPTION("Motorola 8xx FEC ethernet driver");
MODULE_LICENSE("GPL");
int fec_8xx_debug = -1; /* -1 == use FEC_8XX_DEF_MSG_ENABLE as value */
module_param(fec_8xx_debug, int, 0);
MODULE_PARM_DESC(fec_8xx_debug,
"FEC 8xx bitmapped debugging message enable value");
/*************************************************/
/*
* Delay to wait for FEC reset command to complete (in us)
*/
#define FEC_RESET_DELAY 50
/*****************************************************************************************/
static void fec_whack_reset(fec_t * fecp)
{
int i;
/*
* Whack a reset. We should wait for this.
*/
FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
for (i = 0;
(FR(fecp, ecntrl) & FEC_ECNTRL_RESET) != 0 && i < FEC_RESET_DELAY;
i++)
udelay(1);
if (i == FEC_RESET_DELAY)
printk(KERN_WARNING "FEC Reset timeout!\n");
}
/****************************************************************************/
/*
* Transmitter timeout.
*/
#define TX_TIMEOUT (2*HZ)
/****************************************************************************/
/*
* Returns the CRC needed when filling in the hash table for
* multicast group filtering
* pAddr must point to a MAC address (6 bytes)
*/
static __u32 fec_mulicast_calc_crc(char *pAddr)
{
u8 byte;
int byte_count;
int bit_count;
__u32 crc = 0xffffffff;
u8 msb;
for (byte_count = 0; byte_count < 6; byte_count++) {
byte = pAddr[byte_count];
for (bit_count = 0; bit_count < 8; bit_count++) {
msb = crc >> 31;
crc <<= 1;
if (msb ^ (byte & 0x1)) {
crc ^= FEC_CRC_POLY;
}
byte >>= 1;
}
}
return (crc);
}
/*
* Set or clear the multicast filter for this adaptor.
* Skeleton taken from sunlance driver.
* The CPM Ethernet implementation allows Multicast as well as individual
* MAC address filtering. Some of the drivers check to make sure it is
* a group multicast address, and discard those that are not. I guess I
* will do the same for now, but just remove the test if you want
* individual filtering as well (do the upper net layers want or support
* this kind of feature?).
*/
static void fec_set_multicast_list(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
fec_t *fecp = fep->fecp;
struct dev_mc_list *pmc;
__u32 crc