/*
* Network device driver for the MACE ethernet controller on
* Apple Powermacs. Assumes it's under a DBDMA controller.
*
* Copyright (C) 1996 Paul Mackerras.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/crc32.h>
#include <linux/spinlock.h>
#include <linux/bitrev.h>
#include <asm/prom.h>
#include <asm/dbdma.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/macio.h>
#include "mace.h"
static int port_aaui = -1;
#define N_RX_RING 8
#define N_TX_RING 6
#define MAX_TX_ACTIVE 1
#define NCMDS_TX 1 /* dma commands per element in tx ring */
#define RX_BUFLEN (ETH_FRAME_LEN + 8)
#define TX_TIMEOUT HZ /* 1 second */
/* Chip rev needs workaround on HW & multicast addr change */
#define BROKEN_ADDRCHG_REV 0x0941
/* Bits in transmit DMA status */
#define TX_DMA_ERR 0x80
struct mace_data {
volatile struct mace __iomem *mace;
volatile struct dbdma_regs __iomem *tx_dma;
int tx_dma_intr;
volatile struct dbdma_regs __iomem *rx_dma;
int rx_dma_intr;
volatile struct dbdma_cmd *tx_cmds; /* xmit dma command list */
volatile struct dbdma_cmd *rx_cmds; /* recv dma command list */
struct sk_buff *rx_bufs[N_RX_RING];
int rx_fill;
int rx_empty;
struct sk_buff *tx_bufs[N_TX_RING];
int tx_fill;
int tx_empty;
unsigned char maccc;
unsigned char tx_fullup;
unsigned char tx_active;
unsigned char tx_bad_runt;
struct timer_list tx_timeout;
int timeout_active;
int port_aaui;
int chipid;
struct macio_dev *mdev;
spinlock_t lock;
};
/*
* Number of bytes of private data per MACE: allow enough for
* the rx and tx dma commands plus a branch dma command each,
* and another 16 bytes to allow us to align the dma command
* buffers on a 16 byte boundary.
*/
#define PRIV_BYTES (sizeof(struct mace_data) \
+ (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
static void mace_set_multicast(struct net_device *dev);
static void mace_reset(struct net_device *dev);
static int mace_set_address(struct net_device *dev, void *addr);
static irqreturn_t mace_interrupt(int irq, void *dev_id);
static irqreturn_t mace_txdma_intr(int irq, void *dev_id);
static irqreturn_t mace_rxdma_intr(int irq, void *dev_id);
static void mace_set_timeout(struct net_device *dev);
static void mace_tx_timeout(unsigned long data);
static inline void dbdma_reset(volatile struct dbdma_regs __iomem *dma);
static inline void mace_clean_rings(struct mace_data *mp);
static void __mace_set_address(struct net_device *dev, void *addr);
/*
* If we can't get a skbuff when we need it, we use this area for DMA.
*/
static unsigned char *dummy_buf;
static const struct net_device_ops mace_netdev_ops = {
.ndo_open = mace_open,
.ndo_stop = mace_close,
.ndo_start_xmit = mace_xmit_start,
.ndo_set_multicast_list = mace_set_multicast,
.ndo_set_mac_address = mace_set_address,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
{
struct device_node *mace = macio_get_of_node(mdev);
struct net_device *dev;
struct mace_data *mp;
const unsigned char *addr;
int j, rev, rc = -EBUSY;
if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
mace->full_name);
return -ENODEV;
}
addr = of_get_property(mace, "mac-address", NULL);
if (addr == NULL) {
addr = of_get_property(mace, "local-mac-address", NULL);
if (addr == NULL) {
printk(KERN_ERR "Can't get mac-address for MACE %s\n",
mace->full_name);
return -ENODEV;
}
}
/*
* lazy