109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28fb6b090SJeff Kirsher /*
38fb6b090SJeff Kirsher * Network device driver for the MACE ethernet controller on
48fb6b090SJeff Kirsher * Apple Powermacs. Assumes it's under a DBDMA controller.
58fb6b090SJeff Kirsher *
68fb6b090SJeff Kirsher * Copyright (C) 1996 Paul Mackerras.
78fb6b090SJeff Kirsher */
88fb6b090SJeff Kirsher
98fb6b090SJeff Kirsher #include <linux/module.h>
108fb6b090SJeff Kirsher #include <linux/kernel.h>
118fb6b090SJeff Kirsher #include <linux/netdevice.h>
128fb6b090SJeff Kirsher #include <linux/etherdevice.h>
138fb6b090SJeff Kirsher #include <linux/delay.h>
148fb6b090SJeff Kirsher #include <linux/string.h>
158fb6b090SJeff Kirsher #include <linux/timer.h>
168fb6b090SJeff Kirsher #include <linux/init.h>
178fb6b090SJeff Kirsher #include <linux/interrupt.h>
188fb6b090SJeff Kirsher #include <linux/crc32.h>
198fb6b090SJeff Kirsher #include <linux/spinlock.h>
208fb6b090SJeff Kirsher #include <linux/bitrev.h>
218fb6b090SJeff Kirsher #include <linux/slab.h>
2265fddcfcSMike Rapoport #include <linux/pgtable.h>
238fb6b090SJeff Kirsher #include <asm/dbdma.h>
248fb6b090SJeff Kirsher #include <asm/io.h>
258fb6b090SJeff Kirsher #include <asm/macio.h>
268fb6b090SJeff Kirsher
278fb6b090SJeff Kirsher #include "mace.h"
288fb6b090SJeff Kirsher
298fb6b090SJeff Kirsher static int port_aaui = -1;
308fb6b090SJeff Kirsher
318fb6b090SJeff Kirsher #define N_RX_RING 8
328fb6b090SJeff Kirsher #define N_TX_RING 6
338fb6b090SJeff Kirsher #define MAX_TX_ACTIVE 1
348fb6b090SJeff Kirsher #define NCMDS_TX 1 /* dma commands per element in tx ring */
358fb6b090SJeff Kirsher #define RX_BUFLEN (ETH_FRAME_LEN + 8)
368fb6b090SJeff Kirsher #define TX_TIMEOUT HZ /* 1 second */
378fb6b090SJeff Kirsher
388fb6b090SJeff Kirsher /* Chip rev needs workaround on HW & multicast addr change */
398fb6b090SJeff Kirsher #define BROKEN_ADDRCHG_REV 0x0941
408fb6b090SJeff Kirsher
418fb6b090SJeff Kirsher /* Bits in transmit DMA status */
428fb6b090SJeff Kirsher #define TX_DMA_ERR 0x80
438fb6b090SJeff Kirsher
448fb6b090SJeff Kirsher struct mace_data {
458fb6b090SJeff Kirsher volatile struct mace __iomem *mace;
468fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *tx_dma;
478fb6b090SJeff Kirsher int tx_dma_intr;
488fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rx_dma;
498fb6b090SJeff Kirsher int rx_dma_intr;
508fb6b090SJeff Kirsher volatile struct dbdma_cmd *tx_cmds; /* xmit dma command list */
518fb6b090SJeff Kirsher volatile struct dbdma_cmd *rx_cmds; /* recv dma command list */
528fb6b090SJeff Kirsher struct sk_buff *rx_bufs[N_RX_RING];
538fb6b090SJeff Kirsher int rx_fill;
548fb6b090SJeff Kirsher int rx_empty;
558fb6b090SJeff Kirsher struct sk_buff *tx_bufs[N_TX_RING];
568fb6b090SJeff Kirsher int tx_fill;
578fb6b090SJeff Kirsher int tx_empty;
588fb6b090SJeff Kirsher unsigned char maccc;
598fb6b090SJeff Kirsher unsigned char tx_fullup;
608fb6b090SJeff Kirsher unsigned char tx_active;
618fb6b090SJeff Kirsher unsigned char tx_bad_runt;
628fb6b090SJeff Kirsher struct timer_list tx_timeout;
638fb6b090SJeff Kirsher int timeout_active;
648fb6b090SJeff Kirsher int port_aaui;
658fb6b090SJeff Kirsher int chipid;
668fb6b090SJeff Kirsher struct macio_dev *mdev;
678fb6b090SJeff Kirsher spinlock_t lock;
688fb6b090SJeff Kirsher };
698fb6b090SJeff Kirsher
708fb6b090SJeff Kirsher /*
718fb6b090SJeff Kirsher * Number of bytes of private data per MACE: allow enough for
728fb6b090SJeff Kirsher * the rx and tx dma commands plus a branch dma command each,
738fb6b090SJeff Kirsher * and another 16 bytes to allow us to align the dma command
748fb6b090SJeff Kirsher * buffers on a 16 byte boundary.
758fb6b090SJeff Kirsher */
768fb6b090SJeff Kirsher #define PRIV_BYTES (sizeof(struct mace_data) \
778fb6b090SJeff Kirsher + (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
788fb6b090SJeff Kirsher
798fb6b090SJeff Kirsher static int mace_open(struct net_device *dev);
808fb6b090SJeff Kirsher static int mace_close(struct net_device *dev);
81e6ce3822SYueHaibing static netdev_tx_t mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
828fb6b090SJeff Kirsher static void mace_set_multicast(struct net_device *dev);
838fb6b090SJeff Kirsher static void mace_reset(struct net_device *dev);
848fb6b090SJeff Kirsher static int mace_set_address(struct net_device *dev, void *addr);
858fb6b090SJeff Kirsher static irqreturn_t mace_interrupt(int irq, void *dev_id);
868fb6b090SJeff Kirsher static irqreturn_t mace_txdma_intr(int irq, void *dev_id);
878fb6b090SJeff Kirsher static irqreturn_t mace_rxdma_intr(int irq, void *dev_id);
888fb6b090SJeff Kirsher static void mace_set_timeout(struct net_device *dev);
89de892f8fSKees Cook static void mace_tx_timeout(struct timer_list *t);
908fb6b090SJeff Kirsher static inline void dbdma_reset(volatile struct dbdma_regs __iomem *dma);
918fb6b090SJeff Kirsher static inline void mace_clean_rings(struct mace_data *mp);
926c8dc12cSMichael Ellerman static void __mace_set_address(struct net_device *dev, const void *addr);
938fb6b090SJeff Kirsher
948fb6b090SJeff Kirsher /*
958fb6b090SJeff Kirsher * If we can't get a skbuff when we need it, we use this area for DMA.
968fb6b090SJeff Kirsher */
978fb6b090SJeff Kirsher static unsigned char *dummy_buf;
988fb6b090SJeff Kirsher
998fb6b090SJeff Kirsher static const struct net_device_ops mace_netdev_ops = {
1008fb6b090SJeff Kirsher .ndo_open = mace_open,
1018fb6b090SJeff Kirsher .ndo_stop = mace_close,
1028fb6b090SJeff Kirsher .ndo_start_xmit = mace_xmit_start,
103afc4b13dSJiri Pirko .ndo_set_rx_mode = mace_set_multicast,
1048fb6b090SJeff Kirsher .ndo_set_mac_address = mace_set_address,
1058fb6b090SJeff Kirsher .ndo_validate_addr = eth_validate_addr,
1068fb6b090SJeff Kirsher };
1078fb6b090SJeff Kirsher
mace_probe(struct macio_dev * mdev,const struct of_device_id * match)10897c71ad4SBill Pemberton static int mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
1098fb6b090SJeff Kirsher {
1108fb6b090SJeff Kirsher struct device_node *mace = macio_get_of_node(mdev);
1118fb6b090SJeff Kirsher struct net_device *dev;
1128fb6b090SJeff Kirsher struct mace_data *mp;
1138fb6b090SJeff Kirsher const unsigned char *addr;
1146c8dc12cSMichael Ellerman u8 macaddr[ETH_ALEN];
1158fb6b090SJeff Kirsher int j, rev, rc = -EBUSY;
1168fb6b090SJeff Kirsher
1178fb6b090SJeff Kirsher if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
118f7ce9103SRob Herring printk(KERN_ERR "can't use MACE %pOF: need 3 addrs and 3 irqs\n",
119f7ce9103SRob Herring mace);
1208fb6b090SJeff Kirsher return -ENODEV;
1218fb6b090SJeff Kirsher }
1228fb6b090SJeff Kirsher
1238fb6b090SJeff Kirsher addr = of_get_property(mace, "mac-address", NULL);
1248fb6b090SJeff Kirsher if (addr == NULL) {
1258fb6b090SJeff Kirsher addr = of_get_property(mace, "local-mac-address", NULL);
1268fb6b090SJeff Kirsher if (addr == NULL) {
127f7ce9103SRob Herring printk(KERN_ERR "Can't get mac-address for MACE %pOF\n",
128f7ce9103SRob Herring mace);
1298fb6b090SJeff Kirsher return -ENODEV;
1308fb6b090SJeff Kirsher }
1318fb6b090SJeff Kirsher }
1328fb6b090SJeff Kirsher
1338fb6b090SJeff Kirsher /*
1348fb6b090SJeff Kirsher * lazy allocate the driver-wide dummy buffer. (Note that we
1358fb6b090SJeff Kirsher * never have more than one MACE in the system anyway)
1368fb6b090SJeff Kirsher */
1378fb6b090SJeff Kirsher if (dummy_buf == NULL) {
1388fb6b090SJeff Kirsher dummy_buf = kmalloc(RX_BUFLEN+2, GFP_KERNEL);
139e404decbSJoe Perches if (dummy_buf == NULL)
1408fb6b090SJeff Kirsher return -ENOMEM;
1418fb6b090SJeff Kirsher }
1428fb6b090SJeff Kirsher
1438fb6b090SJeff Kirsher if (macio_request_resources(mdev, "mace")) {
1448fb6b090SJeff Kirsher printk(KERN_ERR "MACE: can't request IO resources !\n");
1458fb6b090SJeff Kirsher return -EBUSY;
1468fb6b090SJeff Kirsher }
1478fb6b090SJeff Kirsher
1488fb6b090SJeff Kirsher dev = alloc_etherdev(PRIV_BYTES);
1498fb6b090SJeff Kirsher if (!dev) {
1508fb6b090SJeff Kirsher rc = -ENOMEM;
1518fb6b090SJeff Kirsher goto err_release;
1528fb6b090SJeff Kirsher }
1538fb6b090SJeff Kirsher SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
1548fb6b090SJeff Kirsher
1558fb6b090SJeff Kirsher mp = netdev_priv(dev);
1568fb6b090SJeff Kirsher mp->mdev = mdev;
1578fb6b090SJeff Kirsher macio_set_drvdata(mdev, dev);
1588fb6b090SJeff Kirsher
1598fb6b090SJeff Kirsher dev->base_addr = macio_resource_start(mdev, 0);
1608fb6b090SJeff Kirsher mp->mace = ioremap(dev->base_addr, 0x1000);
1618fb6b090SJeff Kirsher if (mp->mace == NULL) {
1628fb6b090SJeff Kirsher printk(KERN_ERR "MACE: can't map IO resources !\n");
1638fb6b090SJeff Kirsher rc = -ENOMEM;
1648fb6b090SJeff Kirsher goto err_free;
1658fb6b090SJeff Kirsher }
1668fb6b090SJeff Kirsher dev->irq = macio_irq(mdev, 0);
1678fb6b090SJeff Kirsher
1688fb6b090SJeff Kirsher rev = addr[0] == 0 && addr[1] == 0xA0;
1698fb6b090SJeff Kirsher for (j = 0; j < 6; ++j) {
1706c8dc12cSMichael Ellerman macaddr[j] = rev ? bitrev8(addr[j]): addr[j];
1718fb6b090SJeff Kirsher }
1726c8dc12cSMichael Ellerman eth_hw_addr_set(dev, macaddr);
1738fb6b090SJeff Kirsher mp->chipid = (in_8(&mp->mace->chipid_hi) << 8) |
1748fb6b090SJeff Kirsher in_8(&mp->mace->chipid_lo);
1758fb6b090SJeff Kirsher
1768fb6b090SJeff Kirsher
1778fb6b090SJeff Kirsher mp = netdev_priv(dev);
1788fb6b090SJeff Kirsher mp->maccc = ENXMT | ENRCV;
1798fb6b090SJeff Kirsher
1808fb6b090SJeff Kirsher mp->tx_dma = ioremap(macio_resource_start(mdev, 1), 0x1000);
1818fb6b090SJeff Kirsher if (mp->tx_dma == NULL) {
1828fb6b090SJeff Kirsher printk(KERN_ERR "MACE: can't map TX DMA resources !\n");
1838fb6b090SJeff Kirsher rc = -ENOMEM;
1848fb6b090SJeff Kirsher goto err_unmap_io;
1858fb6b090SJeff Kirsher }
1868fb6b090SJeff Kirsher mp->tx_dma_intr = macio_irq(mdev, 1);
1878fb6b090SJeff Kirsher
1888fb6b090SJeff Kirsher mp->rx_dma = ioremap(macio_resource_start(mdev, 2), 0x1000);
1898fb6b090SJeff Kirsher if (mp->rx_dma == NULL) {
1908fb6b090SJeff Kirsher printk(KERN_ERR "MACE: can't map RX DMA resources !\n");
1918fb6b090SJeff Kirsher rc = -ENOMEM;
1928fb6b090SJeff Kirsher goto err_unmap_tx_dma;
1938fb6b090SJeff Kirsher }
1948fb6b090SJeff Kirsher mp->rx_dma_intr = macio_irq(mdev, 2);
1958fb6b090SJeff Kirsher
1968fb6b090SJeff Kirsher mp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(mp + 1);
1978fb6b090SJeff Kirsher mp->rx_cmds = mp->tx_cmds + NCMDS_TX * N_TX_RING + 1;
1988fb6b090SJeff Kirsher
1998fb6b090SJeff Kirsher memset((char *) mp->tx_cmds, 0,
2008fb6b090SJeff Kirsher (NCMDS_TX*N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd));
201de892f8fSKees Cook timer_setup(&mp->tx_timeout, mace_tx_timeout, 0);
2028fb6b090SJeff Kirsher spin_lock_init(&mp->lock);
2038fb6b090SJeff Kirsher mp->timeout_active = 0;
2048fb6b090SJeff Kirsher
2058fb6b090SJeff Kirsher if (port_aaui >= 0)
2068fb6b090SJeff Kirsher mp->port_aaui = port_aaui;
2078fb6b090SJeff Kirsher else {
2088fb6b090SJeff Kirsher /* Apple Network Server uses the AAUI port */
2098fb6b090SJeff Kirsher if (of_machine_is_compatible("AAPL,ShinerESB"))
2108fb6b090SJeff Kirsher mp->port_aaui = 1;
2118fb6b090SJeff Kirsher else {
2128fb6b090SJeff Kirsher #ifdef CONFIG_MACE_AAUI_PORT
2138fb6b090SJeff Kirsher mp->port_aaui = 1;
2148fb6b090SJeff Kirsher #else
2158fb6b090SJeff Kirsher mp->port_aaui = 0;
2168fb6b090SJeff Kirsher #endif
2178fb6b090SJeff Kirsher }
2188fb6b090SJeff Kirsher }
2198fb6b090SJeff Kirsher
2208fb6b090SJeff Kirsher dev->netdev_ops = &mace_netdev_ops;
2218fb6b090SJeff Kirsher
2228fb6b090SJeff Kirsher /*
2238fb6b090SJeff Kirsher * Most of what is below could be moved to mace_open()
2248fb6b090SJeff Kirsher */
2258fb6b090SJeff Kirsher mace_reset(dev);
2268fb6b090SJeff Kirsher
2278fb6b090SJeff Kirsher rc = request_irq(dev->irq, mace_interrupt, 0, "MACE", dev);
2288fb6b090SJeff Kirsher if (rc) {
2298fb6b090SJeff Kirsher printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
2308fb6b090SJeff Kirsher goto err_unmap_rx_dma;
2318fb6b090SJeff Kirsher }
2328fb6b090SJeff Kirsher rc = request_irq(mp->tx_dma_intr, mace_txdma_intr, 0, "MACE-txdma", dev);
2338fb6b090SJeff Kirsher if (rc) {
2348fb6b090SJeff Kirsher printk(KERN_ERR "MACE: can't get irq %d\n", mp->tx_dma_intr);
2358fb6b090SJeff Kirsher goto err_free_irq;
2368fb6b090SJeff Kirsher }
2378fb6b090SJeff Kirsher rc = request_irq(mp->rx_dma_intr, mace_rxdma_intr, 0, "MACE-rxdma", dev);
2388fb6b090SJeff Kirsher if (rc) {
2398fb6b090SJeff Kirsher printk(KERN_ERR "MACE: can't get irq %d\n", mp->rx_dma_intr);
2408fb6b090SJeff Kirsher goto err_free_tx_irq;
2418fb6b090SJeff Kirsher }
2428fb6b090SJeff Kirsher
2438fb6b090SJeff Kirsher rc = register_netdev(dev);
2448fb6b090SJeff Kirsher if (rc) {
2458fb6b090SJeff Kirsher printk(KERN_ERR "MACE: Cannot register net device, aborting.\n");
2468fb6b090SJeff Kirsher goto err_free_rx_irq;
2478fb6b090SJeff Kirsher }
2488fb6b090SJeff Kirsher
2498fb6b090SJeff Kirsher printk(KERN_INFO "%s: MACE at %pM, chip revision %d.%d\n",
2508fb6b090SJeff Kirsher dev->name, dev->dev_addr,
2518fb6b090SJeff Kirsher mp->chipid >> 8, mp->chipid & 0xff);
2528fb6b090SJeff Kirsher
2538fb6b090SJeff Kirsher return 0;
2548fb6b090SJeff Kirsher
2558fb6b090SJeff Kirsher err_free_rx_irq:
2568fb6b090SJeff Kirsher free_irq(macio_irq(mdev, 2), dev);
2578fb6b090SJeff Kirsher err_free_tx_irq:
2588fb6b090SJeff Kirsher free_irq(macio_irq(mdev, 1), dev);
2598fb6b090SJeff Kirsher err_free_irq:
2608fb6b090SJeff Kirsher free_irq(macio_irq(mdev, 0), dev);
2618fb6b090SJeff Kirsher err_unmap_rx_dma:
2628fb6b090SJeff Kirsher iounmap(mp->rx_dma);
2638fb6b090SJeff Kirsher err_unmap_tx_dma:
2648fb6b090SJeff Kirsher iounmap(mp->tx_dma);
2658fb6b090SJeff Kirsher err_unmap_io:
2668fb6b090SJeff Kirsher iounmap(mp->mace);
2678fb6b090SJeff Kirsher err_free:
2688fb6b090SJeff Kirsher free_netdev(dev);
2698fb6b090SJeff Kirsher err_release:
2708fb6b090SJeff Kirsher macio_release_resources(mdev);
2718fb6b090SJeff Kirsher
2728fb6b090SJeff Kirsher return rc;
2738fb6b090SJeff Kirsher }
2748fb6b090SJeff Kirsher
mace_remove(struct macio_dev * mdev)275*9db22353SDawei Li static void mace_remove(struct macio_dev *mdev)
2768fb6b090SJeff Kirsher {
2778fb6b090SJeff Kirsher struct net_device *dev = macio_get_drvdata(mdev);
2788fb6b090SJeff Kirsher struct mace_data *mp;
2798fb6b090SJeff Kirsher
2808fb6b090SJeff Kirsher BUG_ON(dev == NULL);
2818fb6b090SJeff Kirsher
2828fb6b090SJeff Kirsher macio_set_drvdata(mdev, NULL);
2838fb6b090SJeff Kirsher
2848fb6b090SJeff Kirsher mp = netdev_priv(dev);
2858fb6b090SJeff Kirsher
2868fb6b090SJeff Kirsher unregister_netdev(dev);
2878fb6b090SJeff Kirsher
2888fb6b090SJeff Kirsher free_irq(dev->irq, dev);
2898fb6b090SJeff Kirsher free_irq(mp->tx_dma_intr, dev);
2908fb6b090SJeff Kirsher free_irq(mp->rx_dma_intr, dev);
2918fb6b090SJeff Kirsher
2928fb6b090SJeff Kirsher iounmap(mp->rx_dma);
2938fb6b090SJeff Kirsher iounmap(mp->tx_dma);
2948fb6b090SJeff Kirsher iounmap(mp->mace);
2958fb6b090SJeff Kirsher
2968fb6b090SJeff Kirsher free_netdev(dev);
2978fb6b090SJeff Kirsher
2988fb6b090SJeff Kirsher macio_release_resources(mdev);
2998fb6b090SJeff Kirsher }
3008fb6b090SJeff Kirsher
dbdma_reset(volatile struct dbdma_regs __iomem * dma)3018fb6b090SJeff Kirsher static void dbdma_reset(volatile struct dbdma_regs __iomem *dma)
3028fb6b090SJeff Kirsher {
3038fb6b090SJeff Kirsher int i;
3048fb6b090SJeff Kirsher
3058fb6b090SJeff Kirsher out_le32(&dma->control, (WAKE|FLUSH|PAUSE|RUN) << 16);
3068fb6b090SJeff Kirsher
3078fb6b090SJeff Kirsher /*
3088fb6b090SJeff Kirsher * Yes this looks peculiar, but apparently it needs to be this
3098fb6b090SJeff Kirsher * way on some machines.
3108fb6b090SJeff Kirsher */
3118fb6b090SJeff Kirsher for (i = 200; i > 0; --i)
312f5718726SDavid Gibson if (le32_to_cpu(dma->control) & RUN)
3138fb6b090SJeff Kirsher udelay(1);
3148fb6b090SJeff Kirsher }
3158fb6b090SJeff Kirsher
mace_reset(struct net_device * dev)3168fb6b090SJeff Kirsher static void mace_reset(struct net_device *dev)
3178fb6b090SJeff Kirsher {
3188fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
3198fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
3208fb6b090SJeff Kirsher int i;
3218fb6b090SJeff Kirsher
3228fb6b090SJeff Kirsher /* soft-reset the chip */
3238fb6b090SJeff Kirsher i = 200;
3248fb6b090SJeff Kirsher while (--i) {
3258fb6b090SJeff Kirsher out_8(&mb->biucc, SWRST);
3268fb6b090SJeff Kirsher if (in_8(&mb->biucc) & SWRST) {
3278fb6b090SJeff Kirsher udelay(10);
3288fb6b090SJeff Kirsher continue;
3298fb6b090SJeff Kirsher }
3308fb6b090SJeff Kirsher break;
3318fb6b090SJeff Kirsher }
3328fb6b090SJeff Kirsher if (!i) {
3338fb6b090SJeff Kirsher printk(KERN_ERR "mace: cannot reset chip!\n");
3348fb6b090SJeff Kirsher return;
3358fb6b090SJeff Kirsher }
3368fb6b090SJeff Kirsher
3378fb6b090SJeff Kirsher out_8(&mb->imr, 0xff); /* disable all intrs for now */
3388fb6b090SJeff Kirsher i = in_8(&mb->ir);
3398fb6b090SJeff Kirsher out_8(&mb->maccc, 0); /* turn off tx, rx */
3408fb6b090SJeff Kirsher
3418fb6b090SJeff Kirsher out_8(&mb->biucc, XMTSP_64);
3428fb6b090SJeff Kirsher out_8(&mb->utr, RTRD);
3438fb6b090SJeff Kirsher out_8(&mb->fifocc, RCVFW_32 | XMTFW_16 | XMTFWU | RCVFWU | XMTBRST);
3448fb6b090SJeff Kirsher out_8(&mb->xmtfc, AUTO_PAD_XMIT); /* auto-pad short frames */
3458fb6b090SJeff Kirsher out_8(&mb->rcvfc, 0);
3468fb6b090SJeff Kirsher
3478fb6b090SJeff Kirsher /* load up the hardware address */
3488fb6b090SJeff Kirsher __mace_set_address(dev, dev->dev_addr);
3498fb6b090SJeff Kirsher
3508fb6b090SJeff Kirsher /* clear the multicast filter */
3518fb6b090SJeff Kirsher if (mp->chipid == BROKEN_ADDRCHG_REV)
3528fb6b090SJeff Kirsher out_8(&mb->iac, LOGADDR);
3538fb6b090SJeff Kirsher else {
3548fb6b090SJeff Kirsher out_8(&mb->iac, ADDRCHG | LOGADDR);
3558fb6b090SJeff Kirsher while ((in_8(&mb->iac) & ADDRCHG) != 0)
3568fb6b090SJeff Kirsher ;
3578fb6b090SJeff Kirsher }
3588fb6b090SJeff Kirsher for (i = 0; i < 8; ++i)
3598fb6b090SJeff Kirsher out_8(&mb->ladrf, 0);
3608fb6b090SJeff Kirsher
3618fb6b090SJeff Kirsher /* done changing address */
3628fb6b090SJeff Kirsher if (mp->chipid != BROKEN_ADDRCHG_REV)
3638fb6b090SJeff Kirsher out_8(&mb->iac, 0);
3648fb6b090SJeff Kirsher
3658fb6b090SJeff Kirsher if (mp->port_aaui)
3668fb6b090SJeff Kirsher out_8(&mb->plscc, PORTSEL_AUI + ENPLSIO);
3678fb6b090SJeff Kirsher else
3688fb6b090SJeff Kirsher out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
3698fb6b090SJeff Kirsher }
3708fb6b090SJeff Kirsher
__mace_set_address(struct net_device * dev,const void * addr)3716c8dc12cSMichael Ellerman static void __mace_set_address(struct net_device *dev, const void *addr)
3728fb6b090SJeff Kirsher {
3738fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
3748fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
3756c8dc12cSMichael Ellerman const unsigned char *p = addr;
3766c8dc12cSMichael Ellerman u8 macaddr[ETH_ALEN];
3778fb6b090SJeff Kirsher int i;
3788fb6b090SJeff Kirsher
3798fb6b090SJeff Kirsher /* load up the hardware address */
3808fb6b090SJeff Kirsher if (mp->chipid == BROKEN_ADDRCHG_REV)
3818fb6b090SJeff Kirsher out_8(&mb->iac, PHYADDR);
3828fb6b090SJeff Kirsher else {
3838fb6b090SJeff Kirsher out_8(&mb->iac, ADDRCHG | PHYADDR);
3848fb6b090SJeff Kirsher while ((in_8(&mb->iac) & ADDRCHG) != 0)
3858fb6b090SJeff Kirsher ;
3868fb6b090SJeff Kirsher }
3878fb6b090SJeff Kirsher for (i = 0; i < 6; ++i)
3886c8dc12cSMichael Ellerman out_8(&mb->padr, macaddr[i] = p[i]);
3896c8dc12cSMichael Ellerman
3906c8dc12cSMichael Ellerman eth_hw_addr_set(dev, macaddr);
3916c8dc12cSMichael Ellerman
3928fb6b090SJeff Kirsher if (mp->chipid != BROKEN_ADDRCHG_REV)
3938fb6b090SJeff Kirsher out_8(&mb->iac, 0);
3948fb6b090SJeff Kirsher }
3958fb6b090SJeff Kirsher
mace_set_address(struct net_device * dev,void * addr)3968fb6b090SJeff Kirsher static int mace_set_address(struct net_device *dev, void *addr)
3978fb6b090SJeff Kirsher {
3988fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
3998fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
4008fb6b090SJeff Kirsher unsigned long flags;
4018fb6b090SJeff Kirsher
4028fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
4038fb6b090SJeff Kirsher
4048fb6b090SJeff Kirsher __mace_set_address(dev, addr);
4058fb6b090SJeff Kirsher
4068fb6b090SJeff Kirsher /* note: setting ADDRCHG clears ENRCV */
4078fb6b090SJeff Kirsher out_8(&mb->maccc, mp->maccc);
4088fb6b090SJeff Kirsher
4098fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
4108fb6b090SJeff Kirsher return 0;
4118fb6b090SJeff Kirsher }
4128fb6b090SJeff Kirsher
mace_clean_rings(struct mace_data * mp)4138fb6b090SJeff Kirsher static inline void mace_clean_rings(struct mace_data *mp)
4148fb6b090SJeff Kirsher {
4158fb6b090SJeff Kirsher int i;
4168fb6b090SJeff Kirsher
4178fb6b090SJeff Kirsher /* free some skb's */
4188fb6b090SJeff Kirsher for (i = 0; i < N_RX_RING; ++i) {
4198fb6b090SJeff Kirsher if (mp->rx_bufs[i] != NULL) {
4208fb6b090SJeff Kirsher dev_kfree_skb(mp->rx_bufs[i]);
4218fb6b090SJeff Kirsher mp->rx_bufs[i] = NULL;
4228fb6b090SJeff Kirsher }
4238fb6b090SJeff Kirsher }
4248fb6b090SJeff Kirsher for (i = mp->tx_empty; i != mp->tx_fill; ) {
4258fb6b090SJeff Kirsher dev_kfree_skb(mp->tx_bufs[i]);
4268fb6b090SJeff Kirsher if (++i >= N_TX_RING)
4278fb6b090SJeff Kirsher i = 0;
4288fb6b090SJeff Kirsher }
4298fb6b090SJeff Kirsher }
4308fb6b090SJeff Kirsher
mace_open(struct net_device * dev)4318fb6b090SJeff Kirsher static int mace_open(struct net_device *dev)
4328fb6b090SJeff Kirsher {
4338fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
4348fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
4358fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
4368fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
4378fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp;
4388fb6b090SJeff Kirsher int i;
4398fb6b090SJeff Kirsher struct sk_buff *skb;
4408fb6b090SJeff Kirsher unsigned char *data;
4418fb6b090SJeff Kirsher
4428fb6b090SJeff Kirsher /* reset the chip */
4438fb6b090SJeff Kirsher mace_reset(dev);
4448fb6b090SJeff Kirsher
4458fb6b090SJeff Kirsher /* initialize list of sk_buffs for receiving and set up recv dma */
4468fb6b090SJeff Kirsher mace_clean_rings(mp);
4478fb6b090SJeff Kirsher memset((char *)mp->rx_cmds, 0, N_RX_RING * sizeof(struct dbdma_cmd));
4488fb6b090SJeff Kirsher cp = mp->rx_cmds;
4498fb6b090SJeff Kirsher for (i = 0; i < N_RX_RING - 1; ++i) {
4501d266430SPradeep A Dalvi skb = netdev_alloc_skb(dev, RX_BUFLEN + 2);
4518fb6b090SJeff Kirsher if (!skb) {
4528fb6b090SJeff Kirsher data = dummy_buf;
4538fb6b090SJeff Kirsher } else {
4548fb6b090SJeff Kirsher skb_reserve(skb, 2); /* so IP header lands on 4-byte bdry */
4558fb6b090SJeff Kirsher data = skb->data;
4568fb6b090SJeff Kirsher }
4578fb6b090SJeff Kirsher mp->rx_bufs[i] = skb;
458f5718726SDavid Gibson cp->req_count = cpu_to_le16(RX_BUFLEN);
459f5718726SDavid Gibson cp->command = cpu_to_le16(INPUT_LAST + INTR_ALWAYS);
460f5718726SDavid Gibson cp->phy_addr = cpu_to_le32(virt_to_bus(data));
4618fb6b090SJeff Kirsher cp->xfer_status = 0;
4628fb6b090SJeff Kirsher ++cp;
4638fb6b090SJeff Kirsher }
4648fb6b090SJeff Kirsher mp->rx_bufs[i] = NULL;
465f5718726SDavid Gibson cp->command = cpu_to_le16(DBDMA_STOP);
4668fb6b090SJeff Kirsher mp->rx_fill = i;
4678fb6b090SJeff Kirsher mp->rx_empty = 0;
4688fb6b090SJeff Kirsher
4698fb6b090SJeff Kirsher /* Put a branch back to the beginning of the receive command list */
4708fb6b090SJeff Kirsher ++cp;
471f5718726SDavid Gibson cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS);
472f5718726SDavid Gibson cp->cmd_dep = cpu_to_le32(virt_to_bus(mp->rx_cmds));
4738fb6b090SJeff Kirsher
4748fb6b090SJeff Kirsher /* start rx dma */
4758fb6b090SJeff Kirsher out_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
4768fb6b090SJeff Kirsher out_le32(&rd->cmdptr, virt_to_bus(mp->rx_cmds));
4778fb6b090SJeff Kirsher out_le32(&rd->control, (RUN << 16) | RUN);
4788fb6b090SJeff Kirsher
4798fb6b090SJeff Kirsher /* put a branch at the end of the tx command list */
4808fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * N_TX_RING;
481f5718726SDavid Gibson cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS);
482f5718726SDavid Gibson cp->cmd_dep = cpu_to_le32(virt_to_bus(mp->tx_cmds));
4838fb6b090SJeff Kirsher
4848fb6b090SJeff Kirsher /* reset tx dma */
4858fb6b090SJeff Kirsher out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
4868fb6b090SJeff Kirsher out_le32(&td->cmdptr, virt_to_bus(mp->tx_cmds));
4878fb6b090SJeff Kirsher mp->tx_fill = 0;
4888fb6b090SJeff Kirsher mp->tx_empty = 0;
4898fb6b090SJeff Kirsher mp->tx_fullup = 0;
4908fb6b090SJeff Kirsher mp->tx_active = 0;
4918fb6b090SJeff Kirsher mp->tx_bad_runt = 0;
4928fb6b090SJeff Kirsher
4938fb6b090SJeff Kirsher /* turn it on! */
4948fb6b090SJeff Kirsher out_8(&mb->maccc, mp->maccc);
4958fb6b090SJeff Kirsher /* enable all interrupts except receive interrupts */
4968fb6b090SJeff Kirsher out_8(&mb->imr, RCVINT);
4978fb6b090SJeff Kirsher
4988fb6b090SJeff Kirsher return 0;
4998fb6b090SJeff Kirsher }
5008fb6b090SJeff Kirsher
mace_close(struct net_device * dev)5018fb6b090SJeff Kirsher static int mace_close(struct net_device *dev)
5028fb6b090SJeff Kirsher {
5038fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
5048fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
5058fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
5068fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
5078fb6b090SJeff Kirsher
5088fb6b090SJeff Kirsher /* disable rx and tx */
5098fb6b090SJeff Kirsher out_8(&mb->maccc, 0);
5108fb6b090SJeff Kirsher out_8(&mb->imr, 0xff); /* disable all intrs */
5118fb6b090SJeff Kirsher
5128fb6b090SJeff Kirsher /* disable rx and tx dma */
513f5718726SDavid Gibson rd->control = cpu_to_le32((RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
514f5718726SDavid Gibson td->control = cpu_to_le32((RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
5158fb6b090SJeff Kirsher
5168fb6b090SJeff Kirsher mace_clean_rings(mp);
5178fb6b090SJeff Kirsher
5188fb6b090SJeff Kirsher return 0;
5198fb6b090SJeff Kirsher }
5208fb6b090SJeff Kirsher
mace_set_timeout(struct net_device * dev)5218fb6b090SJeff Kirsher static inline void mace_set_timeout(struct net_device *dev)
5228fb6b090SJeff Kirsher {
5238fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
5248fb6b090SJeff Kirsher
5258fb6b090SJeff Kirsher if (mp->timeout_active)
5268fb6b090SJeff Kirsher del_timer(&mp->tx_timeout);
5278fb6b090SJeff Kirsher mp->tx_timeout.expires = jiffies + TX_TIMEOUT;
5288fb6b090SJeff Kirsher add_timer(&mp->tx_timeout);
5298fb6b090SJeff Kirsher mp->timeout_active = 1;
5308fb6b090SJeff Kirsher }
5318fb6b090SJeff Kirsher
mace_xmit_start(struct sk_buff * skb,struct net_device * dev)532e6ce3822SYueHaibing static netdev_tx_t mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
5338fb6b090SJeff Kirsher {
5348fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
5358fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
5368fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp, *np;
5378fb6b090SJeff Kirsher unsigned long flags;
5388fb6b090SJeff Kirsher int fill, next, len;
5398fb6b090SJeff Kirsher
5408fb6b090SJeff Kirsher /* see if there's a free slot in the tx ring */
5418fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
5428fb6b090SJeff Kirsher fill = mp->tx_fill;
5438fb6b090SJeff Kirsher next = fill + 1;
5448fb6b090SJeff Kirsher if (next >= N_TX_RING)
5458fb6b090SJeff Kirsher next = 0;
5468fb6b090SJeff Kirsher if (next == mp->tx_empty) {
5478fb6b090SJeff Kirsher netif_stop_queue(dev);
5488fb6b090SJeff Kirsher mp->tx_fullup = 1;
5498fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
5508fb6b090SJeff Kirsher return NETDEV_TX_BUSY; /* can't take it at the moment */
5518fb6b090SJeff Kirsher }
5528fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
5538fb6b090SJeff Kirsher
5548fb6b090SJeff Kirsher /* partially fill in the dma command block */
5558fb6b090SJeff Kirsher len = skb->len;
5568fb6b090SJeff Kirsher if (len > ETH_FRAME_LEN) {
5578fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: xmit frame too long (%d)\n", len);
5588fb6b090SJeff Kirsher len = ETH_FRAME_LEN;
5598fb6b090SJeff Kirsher }
5608fb6b090SJeff Kirsher mp->tx_bufs[fill] = skb;
5618fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * fill;
562f5718726SDavid Gibson cp->req_count = cpu_to_le16(len);
563f5718726SDavid Gibson cp->phy_addr = cpu_to_le32(virt_to_bus(skb->data));
5648fb6b090SJeff Kirsher
5658fb6b090SJeff Kirsher np = mp->tx_cmds + NCMDS_TX * next;
5668fb6b090SJeff Kirsher out_le16(&np->command, DBDMA_STOP);
5678fb6b090SJeff Kirsher
5688fb6b090SJeff Kirsher /* poke the tx dma channel */
5698fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
5708fb6b090SJeff Kirsher mp->tx_fill = next;
5718fb6b090SJeff Kirsher if (!mp->tx_bad_runt && mp->tx_active < MAX_TX_ACTIVE) {
5728fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
5738fb6b090SJeff Kirsher out_le16(&cp->command, OUTPUT_LAST);
5748fb6b090SJeff Kirsher out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
5758fb6b090SJeff Kirsher ++mp->tx_active;
5768fb6b090SJeff Kirsher mace_set_timeout(dev);
5778fb6b090SJeff Kirsher }
5788fb6b090SJeff Kirsher if (++next >= N_TX_RING)
5798fb6b090SJeff Kirsher next = 0;
5808fb6b090SJeff Kirsher if (next == mp->tx_empty)
5818fb6b090SJeff Kirsher netif_stop_queue(dev);
5828fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
5838fb6b090SJeff Kirsher
5848fb6b090SJeff Kirsher return NETDEV_TX_OK;
5858fb6b090SJeff Kirsher }
5868fb6b090SJeff Kirsher
mace_set_multicast(struct net_device * dev)5878fb6b090SJeff Kirsher static void mace_set_multicast(struct net_device *dev)
5888fb6b090SJeff Kirsher {
5898fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
5908fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
5918fb6b090SJeff Kirsher int i;
5928fb6b090SJeff Kirsher u32 crc;
5938fb6b090SJeff Kirsher unsigned long flags;
5948fb6b090SJeff Kirsher
5958fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
5968fb6b090SJeff Kirsher mp->maccc &= ~PROM;
5978fb6b090SJeff Kirsher if (dev->flags & IFF_PROMISC) {
5988fb6b090SJeff Kirsher mp->maccc |= PROM;
5998fb6b090SJeff Kirsher } else {
6008fb6b090SJeff Kirsher unsigned char multicast_filter[8];
6018fb6b090SJeff Kirsher struct netdev_hw_addr *ha;
6028fb6b090SJeff Kirsher
6038fb6b090SJeff Kirsher if (dev->flags & IFF_ALLMULTI) {
6048fb6b090SJeff Kirsher for (i = 0; i < 8; i++)
6058fb6b090SJeff Kirsher multicast_filter[i] = 0xff;
6068fb6b090SJeff Kirsher } else {
6078fb6b090SJeff Kirsher for (i = 0; i < 8; i++)
6088fb6b090SJeff Kirsher multicast_filter[i] = 0;
6098fb6b090SJeff Kirsher netdev_for_each_mc_addr(ha, dev) {
6108fb6b090SJeff Kirsher crc = ether_crc_le(6, ha->addr);
6118fb6b090SJeff Kirsher i = crc >> 26; /* bit number in multicast_filter */
6128fb6b090SJeff Kirsher multicast_filter[i >> 3] |= 1 << (i & 7);
6138fb6b090SJeff Kirsher }
6148fb6b090SJeff Kirsher }
6158fb6b090SJeff Kirsher #if 0
6168fb6b090SJeff Kirsher printk("Multicast filter :");
6178fb6b090SJeff Kirsher for (i = 0; i < 8; i++)
6188fb6b090SJeff Kirsher printk("%02x ", multicast_filter[i]);
6198fb6b090SJeff Kirsher printk("\n");
6208fb6b090SJeff Kirsher #endif
6218fb6b090SJeff Kirsher
6228fb6b090SJeff Kirsher if (mp->chipid == BROKEN_ADDRCHG_REV)
6238fb6b090SJeff Kirsher out_8(&mb->iac, LOGADDR);
6248fb6b090SJeff Kirsher else {
6258fb6b090SJeff Kirsher out_8(&mb->iac, ADDRCHG | LOGADDR);
6268fb6b090SJeff Kirsher while ((in_8(&mb->iac) & ADDRCHG) != 0)
6278fb6b090SJeff Kirsher ;
6288fb6b090SJeff Kirsher }
6298fb6b090SJeff Kirsher for (i = 0; i < 8; ++i)
6308fb6b090SJeff Kirsher out_8(&mb->ladrf, multicast_filter[i]);
6318fb6b090SJeff Kirsher if (mp->chipid != BROKEN_ADDRCHG_REV)
6328fb6b090SJeff Kirsher out_8(&mb->iac, 0);
6338fb6b090SJeff Kirsher }
6348fb6b090SJeff Kirsher /* reset maccc */
6358fb6b090SJeff Kirsher out_8(&mb->maccc, mp->maccc);
6368fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
6378fb6b090SJeff Kirsher }
6388fb6b090SJeff Kirsher
mace_handle_misc_intrs(struct mace_data * mp,int intr,struct net_device * dev)6398fb6b090SJeff Kirsher static void mace_handle_misc_intrs(struct mace_data *mp, int intr, struct net_device *dev)
6408fb6b090SJeff Kirsher {
6418fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
6428fb6b090SJeff Kirsher static int mace_babbles, mace_jabbers;
6438fb6b090SJeff Kirsher
6448fb6b090SJeff Kirsher if (intr & MPCO)
6458fb6b090SJeff Kirsher dev->stats.rx_missed_errors += 256;
6468fb6b090SJeff Kirsher dev->stats.rx_missed_errors += in_8(&mb->mpc); /* reading clears it */
6478fb6b090SJeff Kirsher if (intr & RNTPCO)
6488fb6b090SJeff Kirsher dev->stats.rx_length_errors += 256;
6498fb6b090SJeff Kirsher dev->stats.rx_length_errors += in_8(&mb->rntpc); /* reading clears it */
6508fb6b090SJeff Kirsher if (intr & CERR)
6518fb6b090SJeff Kirsher ++dev->stats.tx_heartbeat_errors;
6528fb6b090SJeff Kirsher if (intr & BABBLE)
6538fb6b090SJeff Kirsher if (mace_babbles++ < 4)
6548fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: babbling transmitter\n");
6558fb6b090SJeff Kirsher if (intr & JABBER)
6568fb6b090SJeff Kirsher if (mace_jabbers++ < 4)
6578fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: jabbering transceiver\n");
6588fb6b090SJeff Kirsher }
6598fb6b090SJeff Kirsher
mace_interrupt(int irq,void * dev_id)6608fb6b090SJeff Kirsher static irqreturn_t mace_interrupt(int irq, void *dev_id)
6618fb6b090SJeff Kirsher {
6628fb6b090SJeff Kirsher struct net_device *dev = (struct net_device *) dev_id;
6638fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
6648fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
6658fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
6668fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp;
6678fb6b090SJeff Kirsher int intr, fs, i, stat, x;
6688fb6b090SJeff Kirsher int xcount, dstat;
6698fb6b090SJeff Kirsher unsigned long flags;
6708fb6b090SJeff Kirsher /* static int mace_last_fs, mace_last_xcount; */
6718fb6b090SJeff Kirsher
6728fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
6738fb6b090SJeff Kirsher intr = in_8(&mb->ir); /* read interrupt register */
6748fb6b090SJeff Kirsher in_8(&mb->xmtrc); /* get retries */
6758fb6b090SJeff Kirsher mace_handle_misc_intrs(mp, intr, dev);
6768fb6b090SJeff Kirsher
6778fb6b090SJeff Kirsher i = mp->tx_empty;
6788fb6b090SJeff Kirsher while (in_8(&mb->pr) & XMTSV) {
6798fb6b090SJeff Kirsher del_timer(&mp->tx_timeout);
6808fb6b090SJeff Kirsher mp->timeout_active = 0;
6818fb6b090SJeff Kirsher /*
6828fb6b090SJeff Kirsher * Clear any interrupt indication associated with this status
6838fb6b090SJeff Kirsher * word. This appears to unlatch any error indication from
6848fb6b090SJeff Kirsher * the DMA controller.
6858fb6b090SJeff Kirsher */
6868fb6b090SJeff Kirsher intr = in_8(&mb->ir);
6878fb6b090SJeff Kirsher if (intr != 0)
6888fb6b090SJeff Kirsher mace_handle_misc_intrs(mp, intr, dev);
6898fb6b090SJeff Kirsher if (mp->tx_bad_runt) {
6908fb6b090SJeff Kirsher fs = in_8(&mb->xmtfs);
6918fb6b090SJeff Kirsher mp->tx_bad_runt = 0;
6928fb6b090SJeff Kirsher out_8(&mb->xmtfc, AUTO_PAD_XMIT);
6938fb6b090SJeff Kirsher continue;
6948fb6b090SJeff Kirsher }
695f5718726SDavid Gibson dstat = le32_to_cpu(td->status);
6968fb6b090SJeff Kirsher /* stop DMA controller */
6978fb6b090SJeff Kirsher out_le32(&td->control, RUN << 16);
6988fb6b090SJeff Kirsher /*
6998fb6b090SJeff Kirsher * xcount is the number of complete frames which have been
7008fb6b090SJeff Kirsher * written to the fifo but for which status has not been read.
7018fb6b090SJeff Kirsher */
7028fb6b090SJeff Kirsher xcount = (in_8(&mb->fifofc) >> XMTFC_SH) & XMTFC_MASK;
7038fb6b090SJeff Kirsher if (xcount == 0 || (dstat & DEAD)) {
7048fb6b090SJeff Kirsher /*
7058fb6b090SJeff Kirsher * If a packet was aborted before the DMA controller has
7068fb6b090SJeff Kirsher * finished transferring it, it seems that there are 2 bytes
7078fb6b090SJeff Kirsher * which are stuck in some buffer somewhere. These will get
7088fb6b090SJeff Kirsher * transmitted as soon as we read the frame status (which
7098fb6b090SJeff Kirsher * reenables the transmit data transfer request). Turning
7108fb6b090SJeff Kirsher * off the DMA controller and/or resetting the MACE doesn't
7118fb6b090SJeff Kirsher * help. So we disable auto-padding and FCS transmission
7128fb6b090SJeff Kirsher * so the two bytes will only be a runt packet which should
7138fb6b090SJeff Kirsher * be ignored by other stations.
7148fb6b090SJeff Kirsher */
7158fb6b090SJeff Kirsher out_8(&mb->xmtfc, DXMTFCS);
7168fb6b090SJeff Kirsher }
7178fb6b090SJeff Kirsher fs = in_8(&mb->xmtfs);
7188fb6b090SJeff Kirsher if ((fs & XMTSV) == 0) {
7198fb6b090SJeff Kirsher printk(KERN_ERR "mace: xmtfs not valid! (fs=%x xc=%d ds=%x)\n",
7208fb6b090SJeff Kirsher fs, xcount, dstat);
7218fb6b090SJeff Kirsher mace_reset(dev);
7228fb6b090SJeff Kirsher /*
7238fb6b090SJeff Kirsher * XXX mace likes to hang the machine after a xmtfs error.
724dbedd44eSJoe Perches * This is hard to reproduce, resetting *may* help
7258fb6b090SJeff Kirsher */
7268fb6b090SJeff Kirsher }
7278fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * i;
728f5718726SDavid Gibson stat = le16_to_cpu(cp->xfer_status);
7298fb6b090SJeff Kirsher if ((fs & (UFLO|LCOL|LCAR|RTRY)) || (dstat & DEAD) || xcount == 0) {
7308fb6b090SJeff Kirsher /*
7318fb6b090SJeff Kirsher * Check whether there were in fact 2 bytes written to
7328fb6b090SJeff Kirsher * the transmit FIFO.
7338fb6b090SJeff Kirsher */
7348fb6b090SJeff Kirsher udelay(1);
7358fb6b090SJeff Kirsher x = (in_8(&mb->fifofc) >> XMTFC_SH) & XMTFC_MASK;
7368fb6b090SJeff Kirsher if (x != 0) {
7378fb6b090SJeff Kirsher /* there were two bytes with an end-of-packet indication */
7388fb6b090SJeff Kirsher mp->tx_bad_runt = 1;
7398fb6b090SJeff Kirsher mace_set_timeout(dev);
7408fb6b090SJeff Kirsher } else {
7418fb6b090SJeff Kirsher /*
7428fb6b090SJeff Kirsher * Either there weren't the two bytes buffered up, or they
7438fb6b090SJeff Kirsher * didn't have an end-of-packet indication.
7448fb6b090SJeff Kirsher * We flush the transmit FIFO just in case (by setting the
7458fb6b090SJeff Kirsher * XMTFWU bit with the transmitter disabled).
7468fb6b090SJeff Kirsher */
7478fb6b090SJeff Kirsher out_8(&mb->maccc, in_8(&mb->maccc) & ~ENXMT);
7488fb6b090SJeff Kirsher out_8(&mb->fifocc, in_8(&mb->fifocc) | XMTFWU);
7498fb6b090SJeff Kirsher udelay(1);
7508fb6b090SJeff Kirsher out_8(&mb->maccc, in_8(&mb->maccc) | ENXMT);
7518fb6b090SJeff Kirsher out_8(&mb->xmtfc, AUTO_PAD_XMIT);
7528fb6b090SJeff Kirsher }
7538fb6b090SJeff Kirsher }
7548fb6b090SJeff Kirsher /* dma should have finished */
7558fb6b090SJeff Kirsher if (i == mp->tx_fill) {
7568fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: tx ring ran out? (fs=%x xc=%d ds=%x)\n",
7578fb6b090SJeff Kirsher fs, xcount, dstat);
7588fb6b090SJeff Kirsher continue;
7598fb6b090SJeff Kirsher }
7608fb6b090SJeff Kirsher /* Update stats */
7618fb6b090SJeff Kirsher if (fs & (UFLO|LCOL|LCAR|RTRY)) {
7628fb6b090SJeff Kirsher ++dev->stats.tx_errors;
7638fb6b090SJeff Kirsher if (fs & LCAR)
7648fb6b090SJeff Kirsher ++dev->stats.tx_carrier_errors;
7658fb6b090SJeff Kirsher if (fs & (UFLO|LCOL|RTRY))
7668fb6b090SJeff Kirsher ++dev->stats.tx_aborted_errors;
7678fb6b090SJeff Kirsher } else {
7688fb6b090SJeff Kirsher dev->stats.tx_bytes += mp->tx_bufs[i]->len;
7698fb6b090SJeff Kirsher ++dev->stats.tx_packets;
7708fb6b090SJeff Kirsher }
7715f5a8c75SYang Wei dev_consume_skb_irq(mp->tx_bufs[i]);
7728fb6b090SJeff Kirsher --mp->tx_active;
7738fb6b090SJeff Kirsher if (++i >= N_TX_RING)
7748fb6b090SJeff Kirsher i = 0;
7758fb6b090SJeff Kirsher #if 0
7768fb6b090SJeff Kirsher mace_last_fs = fs;
7778fb6b090SJeff Kirsher mace_last_xcount = xcount;
7788fb6b090SJeff Kirsher #endif
7798fb6b090SJeff Kirsher }
7808fb6b090SJeff Kirsher
7818fb6b090SJeff Kirsher if (i != mp->tx_empty) {
7828fb6b090SJeff Kirsher mp->tx_fullup = 0;
7838fb6b090SJeff Kirsher netif_wake_queue(dev);
7848fb6b090SJeff Kirsher }
7858fb6b090SJeff Kirsher mp->tx_empty = i;
7868fb6b090SJeff Kirsher i += mp->tx_active;
7878fb6b090SJeff Kirsher if (i >= N_TX_RING)
7888fb6b090SJeff Kirsher i -= N_TX_RING;
7898fb6b090SJeff Kirsher if (!mp->tx_bad_runt && i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE) {
7908fb6b090SJeff Kirsher do {
7918fb6b090SJeff Kirsher /* set up the next one */
7928fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * i;
7938fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
7948fb6b090SJeff Kirsher out_le16(&cp->command, OUTPUT_LAST);
7958fb6b090SJeff Kirsher ++mp->tx_active;
7968fb6b090SJeff Kirsher if (++i >= N_TX_RING)
7978fb6b090SJeff Kirsher i = 0;
7988fb6b090SJeff Kirsher } while (i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE);
7998fb6b090SJeff Kirsher out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
8008fb6b090SJeff Kirsher mace_set_timeout(dev);
8018fb6b090SJeff Kirsher }
8028fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
8038fb6b090SJeff Kirsher return IRQ_HANDLED;
8048fb6b090SJeff Kirsher }
8058fb6b090SJeff Kirsher
mace_tx_timeout(struct timer_list * t)806de892f8fSKees Cook static void mace_tx_timeout(struct timer_list *t)
8078fb6b090SJeff Kirsher {
808de892f8fSKees Cook struct mace_data *mp = from_timer(mp, t, tx_timeout);
809de892f8fSKees Cook struct net_device *dev = macio_get_drvdata(mp->mdev);
8108fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
8118fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
8128fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
8138fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp;
8148fb6b090SJeff Kirsher unsigned long flags;
8158fb6b090SJeff Kirsher int i;
8168fb6b090SJeff Kirsher
8178fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
8188fb6b090SJeff Kirsher mp->timeout_active = 0;
8198fb6b090SJeff Kirsher if (mp->tx_active == 0 && !mp->tx_bad_runt)
8208fb6b090SJeff Kirsher goto out;
8218fb6b090SJeff Kirsher
8228fb6b090SJeff Kirsher /* update various counters */
8238fb6b090SJeff Kirsher mace_handle_misc_intrs(mp, in_8(&mb->ir), dev);
8248fb6b090SJeff Kirsher
8258fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty;
8268fb6b090SJeff Kirsher
8278fb6b090SJeff Kirsher /* turn off both tx and rx and reset the chip */
8288fb6b090SJeff Kirsher out_8(&mb->maccc, 0);
8298fb6b090SJeff Kirsher printk(KERN_ERR "mace: transmit timeout - resetting\n");
8308fb6b090SJeff Kirsher dbdma_reset(td);
8318fb6b090SJeff Kirsher mace_reset(dev);
8328fb6b090SJeff Kirsher
8338fb6b090SJeff Kirsher /* restart rx dma */
834f5718726SDavid Gibson cp = bus_to_virt(le32_to_cpu(rd->cmdptr));
8358fb6b090SJeff Kirsher dbdma_reset(rd);
8368fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
8378fb6b090SJeff Kirsher out_le32(&rd->cmdptr, virt_to_bus(cp));
8388fb6b090SJeff Kirsher out_le32(&rd->control, (RUN << 16) | RUN);
8398fb6b090SJeff Kirsher
8408fb6b090SJeff Kirsher /* fix up the transmit side */
8418fb6b090SJeff Kirsher i = mp->tx_empty;
8428fb6b090SJeff Kirsher mp->tx_active = 0;
8438fb6b090SJeff Kirsher ++dev->stats.tx_errors;
8448fb6b090SJeff Kirsher if (mp->tx_bad_runt) {
8458fb6b090SJeff Kirsher mp->tx_bad_runt = 0;
8468fb6b090SJeff Kirsher } else if (i != mp->tx_fill) {
8473dfe3486SYang Yingliang dev_kfree_skb_irq(mp->tx_bufs[i]);
8488fb6b090SJeff Kirsher if (++i >= N_TX_RING)
8498fb6b090SJeff Kirsher i = 0;
8508fb6b090SJeff Kirsher mp->tx_empty = i;
8518fb6b090SJeff Kirsher }
8528fb6b090SJeff Kirsher mp->tx_fullup = 0;
8538fb6b090SJeff Kirsher netif_wake_queue(dev);
8548fb6b090SJeff Kirsher if (i != mp->tx_fill) {
8558fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * i;
8568fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
8578fb6b090SJeff Kirsher out_le16(&cp->command, OUTPUT_LAST);
8588fb6b090SJeff Kirsher out_le32(&td->cmdptr, virt_to_bus(cp));
8598fb6b090SJeff Kirsher out_le32(&td->control, (RUN << 16) | RUN);
8608fb6b090SJeff Kirsher ++mp->tx_active;
8618fb6b090SJeff Kirsher mace_set_timeout(dev);
8628fb6b090SJeff Kirsher }
8638fb6b090SJeff Kirsher
8648fb6b090SJeff Kirsher /* turn it back on */
8658fb6b090SJeff Kirsher out_8(&mb->imr, RCVINT);
8668fb6b090SJeff Kirsher out_8(&mb->maccc, mp->maccc);
8678fb6b090SJeff Kirsher
8688fb6b090SJeff Kirsher out:
8698fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
8708fb6b090SJeff Kirsher }
8718fb6b090SJeff Kirsher
mace_txdma_intr(int irq,void * dev_id)8728fb6b090SJeff Kirsher static irqreturn_t mace_txdma_intr(int irq, void *dev_id)
8738fb6b090SJeff Kirsher {
8748fb6b090SJeff Kirsher return IRQ_HANDLED;
8758fb6b090SJeff Kirsher }
8768fb6b090SJeff Kirsher
mace_rxdma_intr(int irq,void * dev_id)8778fb6b090SJeff Kirsher static irqreturn_t mace_rxdma_intr(int irq, void *dev_id)
8788fb6b090SJeff Kirsher {
8798fb6b090SJeff Kirsher struct net_device *dev = (struct net_device *) dev_id;
8808fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
8818fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
8828fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp, *np;
8838fb6b090SJeff Kirsher int i, nb, stat, next;
8848fb6b090SJeff Kirsher struct sk_buff *skb;
8858fb6b090SJeff Kirsher unsigned frame_status;
8868fb6b090SJeff Kirsher static int mace_lost_status;
8878fb6b090SJeff Kirsher unsigned char *data;
8888fb6b090SJeff Kirsher unsigned long flags;
8898fb6b090SJeff Kirsher
8908fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
8918fb6b090SJeff Kirsher for (i = mp->rx_empty; i != mp->rx_fill; ) {
8928fb6b090SJeff Kirsher cp = mp->rx_cmds + i;
893f5718726SDavid Gibson stat = le16_to_cpu(cp->xfer_status);
8948fb6b090SJeff Kirsher if ((stat & ACTIVE) == 0) {
8958fb6b090SJeff Kirsher next = i + 1;
8968fb6b090SJeff Kirsher if (next >= N_RX_RING)
8978fb6b090SJeff Kirsher next = 0;
8988fb6b090SJeff Kirsher np = mp->rx_cmds + next;
8998fb6b090SJeff Kirsher if (next != mp->rx_fill &&
900f5718726SDavid Gibson (le16_to_cpu(np->xfer_status) & ACTIVE) != 0) {
9018fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: lost a status word\n");
9028fb6b090SJeff Kirsher ++mace_lost_status;
9038fb6b090SJeff Kirsher } else
9048fb6b090SJeff Kirsher break;
9058fb6b090SJeff Kirsher }
906f5718726SDavid Gibson nb = le16_to_cpu(cp->req_count) - le16_to_cpu(cp->res_count);
9078fb6b090SJeff Kirsher out_le16(&cp->command, DBDMA_STOP);
9088fb6b090SJeff Kirsher /* got a packet, have a look at it */
9098fb6b090SJeff Kirsher skb = mp->rx_bufs[i];
9108fb6b090SJeff Kirsher if (!skb) {
9118fb6b090SJeff Kirsher ++dev->stats.rx_dropped;
9128fb6b090SJeff Kirsher } else if (nb > 8) {
9138fb6b090SJeff Kirsher data = skb->data;
9148fb6b090SJeff Kirsher frame_status = (data[nb-3] << 8) + data[nb-4];
9158fb6b090SJeff Kirsher if (frame_status & (RS_OFLO|RS_CLSN|RS_FRAMERR|RS_FCSERR)) {
9168fb6b090SJeff Kirsher ++dev->stats.rx_errors;
9178fb6b090SJeff Kirsher if (frame_status & RS_OFLO)
9188fb6b090SJeff Kirsher ++dev->stats.rx_over_errors;
9198fb6b090SJeff Kirsher if (frame_status & RS_FRAMERR)
9208fb6b090SJeff Kirsher ++dev->stats.rx_frame_errors;
9218fb6b090SJeff Kirsher if (frame_status & RS_FCSERR)
9228fb6b090SJeff Kirsher ++dev->stats.rx_crc_errors;
9238fb6b090SJeff Kirsher } else {
9248fb6b090SJeff Kirsher /* Mace feature AUTO_STRIP_RCV is on by default, dropping the
9258fb6b090SJeff Kirsher * FCS on frames with 802.3 headers. This means that Ethernet
9268fb6b090SJeff Kirsher * frames have 8 extra octets at the end, while 802.3 frames
9278fb6b090SJeff Kirsher * have only 4. We need to correctly account for this. */
9288fb6b090SJeff Kirsher if (*(unsigned short *)(data+12) < 1536) /* 802.3 header */
9298fb6b090SJeff Kirsher nb -= 4;
9308fb6b090SJeff Kirsher else /* Ethernet header; mace includes FCS */
9318fb6b090SJeff Kirsher nb -= 8;
9328fb6b090SJeff Kirsher skb_put(skb, nb);
9338fb6b090SJeff Kirsher skb->protocol = eth_type_trans(skb, dev);
9348fb6b090SJeff Kirsher dev->stats.rx_bytes += skb->len;
9358fb6b090SJeff Kirsher netif_rx(skb);
9368fb6b090SJeff Kirsher mp->rx_bufs[i] = NULL;
9378fb6b090SJeff Kirsher ++dev->stats.rx_packets;
9388fb6b090SJeff Kirsher }
9398fb6b090SJeff Kirsher } else {
9408fb6b090SJeff Kirsher ++dev->stats.rx_errors;
9418fb6b090SJeff Kirsher ++dev->stats.rx_length_errors;
9428fb6b090SJeff Kirsher }
9438fb6b090SJeff Kirsher
9448fb6b090SJeff Kirsher /* advance to next */
9458fb6b090SJeff Kirsher if (++i >= N_RX_RING)
9468fb6b090SJeff Kirsher i = 0;
9478fb6b090SJeff Kirsher }
9488fb6b090SJeff Kirsher mp->rx_empty = i;
9498fb6b090SJeff Kirsher
9508fb6b090SJeff Kirsher i = mp->rx_fill;
9518fb6b090SJeff Kirsher for (;;) {
9528fb6b090SJeff Kirsher next = i + 1;
9538fb6b090SJeff Kirsher if (next >= N_RX_RING)
9548fb6b090SJeff Kirsher next = 0;
9558fb6b090SJeff Kirsher if (next == mp->rx_empty)
9568fb6b090SJeff Kirsher break;
9578fb6b090SJeff Kirsher cp = mp->rx_cmds + i;
9588fb6b090SJeff Kirsher skb = mp->rx_bufs[i];
9598fb6b090SJeff Kirsher if (!skb) {
96031a4c8b8SPradeep A. Dalvi skb = netdev_alloc_skb(dev, RX_BUFLEN + 2);
9618fb6b090SJeff Kirsher if (skb) {
9628fb6b090SJeff Kirsher skb_reserve(skb, 2);
9638fb6b090SJeff Kirsher mp->rx_bufs[i] = skb;
9648fb6b090SJeff Kirsher }
9658fb6b090SJeff Kirsher }
966f5718726SDavid Gibson cp->req_count = cpu_to_le16(RX_BUFLEN);
9678fb6b090SJeff Kirsher data = skb? skb->data: dummy_buf;
968f5718726SDavid Gibson cp->phy_addr = cpu_to_le32(virt_to_bus(data));
9698fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
9708fb6b090SJeff Kirsher out_le16(&cp->command, INPUT_LAST + INTR_ALWAYS);
9718fb6b090SJeff Kirsher #if 0
972f5718726SDavid Gibson if ((le32_to_cpu(rd->status) & ACTIVE) != 0) {
9738fb6b090SJeff Kirsher out_le32(&rd->control, (PAUSE << 16) | PAUSE);
9748fb6b090SJeff Kirsher while ((in_le32(&rd->status) & ACTIVE) != 0)
9758fb6b090SJeff Kirsher ;
9768fb6b090SJeff Kirsher }
9778fb6b090SJeff Kirsher #endif
9788fb6b090SJeff Kirsher i = next;
9798fb6b090SJeff Kirsher }
9808fb6b090SJeff Kirsher if (i != mp->rx_fill) {
9818fb6b090SJeff Kirsher out_le32(&rd->control, ((RUN|WAKE) << 16) | (RUN|WAKE));
9828fb6b090SJeff Kirsher mp->rx_fill = i;
9838fb6b090SJeff Kirsher }
9848fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
9858fb6b090SJeff Kirsher return IRQ_HANDLED;
9868fb6b090SJeff Kirsher }
9878fb6b090SJeff Kirsher
98814448e2fSFabian Frederick static const struct of_device_id mace_match[] =
9898fb6b090SJeff Kirsher {
9908fb6b090SJeff Kirsher {
9918fb6b090SJeff Kirsher .name = "mace",
9928fb6b090SJeff Kirsher },
9938fb6b090SJeff Kirsher {},
9948fb6b090SJeff Kirsher };
9958fb6b090SJeff Kirsher MODULE_DEVICE_TABLE (of, mace_match);
9968fb6b090SJeff Kirsher
9978fb6b090SJeff Kirsher static struct macio_driver mace_driver =
9988fb6b090SJeff Kirsher {
9998fb6b090SJeff Kirsher .driver = {
10008fb6b090SJeff Kirsher .name = "mace",
10018fb6b090SJeff Kirsher .owner = THIS_MODULE,
10028fb6b090SJeff Kirsher .of_match_table = mace_match,
10038fb6b090SJeff Kirsher },
10048fb6b090SJeff Kirsher .probe = mace_probe,
10058fb6b090SJeff Kirsher .remove = mace_remove,
10068fb6b090SJeff Kirsher };
10078fb6b090SJeff Kirsher
10088fb6b090SJeff Kirsher
mace_init(void)10098fb6b090SJeff Kirsher static int __init mace_init(void)
10108fb6b090SJeff Kirsher {
10118fb6b090SJeff Kirsher return macio_register_driver(&mace_driver);
10128fb6b090SJeff Kirsher }
10138fb6b090SJeff Kirsher
mace_cleanup(void)10148fb6b090SJeff Kirsher static void __exit mace_cleanup(void)
10158fb6b090SJeff Kirsher {
10168fb6b090SJeff Kirsher macio_unregister_driver(&mace_driver);
10178fb6b090SJeff Kirsher
10188fb6b090SJeff Kirsher kfree(dummy_buf);
10198fb6b090SJeff Kirsher dummy_buf = NULL;
10208fb6b090SJeff Kirsher }
10218fb6b090SJeff Kirsher
10228fb6b090SJeff Kirsher MODULE_AUTHOR("Paul Mackerras");
10238fb6b090SJeff Kirsher MODULE_DESCRIPTION("PowerMac MACE driver.");
10248fb6b090SJeff Kirsher module_param(port_aaui, int, 0);
10258fb6b090SJeff Kirsher MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
10268fb6b090SJeff Kirsher MODULE_LICENSE("GPL");
10278fb6b090SJeff Kirsher
10288fb6b090SJeff Kirsher module_init(mace_init);
10298fb6b090SJeff Kirsher module_exit(mace_cleanup);
1030