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)27597c71ad4SBill Pemberton static int 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 return 0;
3018fb6b090SJeff Kirsher }
3028fb6b090SJeff Kirsher
dbdma_reset(volatile struct dbdma_regs __iomem * dma)3038fb6b090SJeff Kirsher static void dbdma_reset(volatile struct dbdma_regs __iomem *dma)
3048fb6b090SJeff Kirsher {
3058fb6b090SJeff Kirsher int i;
3068fb6b090SJeff Kirsher
3078fb6b090SJeff Kirsher out_le32(&dma->control, (WAKE|FLUSH|PAUSE|RUN) << 16);
3088fb6b090SJeff Kirsher
3098fb6b090SJeff Kirsher /*
3108fb6b090SJeff Kirsher * Yes this looks peculiar, but apparently it needs to be this
3118fb6b090SJeff Kirsher * way on some machines.
3128fb6b090SJeff Kirsher */
3138fb6b090SJeff Kirsher for (i = 200; i > 0; --i)
314f5718726SDavid Gibson if (le32_to_cpu(dma->control) & RUN)
3158fb6b090SJeff Kirsher udelay(1);
3168fb6b090SJeff Kirsher }
3178fb6b090SJeff Kirsher
mace_reset(struct net_device * dev)3188fb6b090SJeff Kirsher static void mace_reset(struct net_device *dev)
3198fb6b090SJeff Kirsher {
3208fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
3218fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
3228fb6b090SJeff Kirsher int i;
3238fb6b090SJeff Kirsher
3248fb6b090SJeff Kirsher /* soft-reset the chip */
3258fb6b090SJeff Kirsher i = 200;
3268fb6b090SJeff Kirsher while (--i) {
3278fb6b090SJeff Kirsher out_8(&mb->biucc, SWRST);
3288fb6b090SJeff Kirsher if (in_8(&mb->biucc) & SWRST) {
3298fb6b090SJeff Kirsher udelay(10);
3308fb6b090SJeff Kirsher continue;
3318fb6b090SJeff Kirsher }
3328fb6b090SJeff Kirsher break;
3338fb6b090SJeff Kirsher }
3348fb6b090SJeff Kirsher if (!i) {
3358fb6b090SJeff Kirsher printk(KERN_ERR "mace: cannot reset chip!\n");
3368fb6b090SJeff Kirsher return;
3378fb6b090SJeff Kirsher }
3388fb6b090SJeff Kirsher
3398fb6b090SJeff Kirsher out_8(&mb->imr, 0xff); /* disable all intrs for now */
3408fb6b090SJeff Kirsher i = in_8(&mb->ir);
3418fb6b090SJeff Kirsher out_8(&mb->maccc, 0); /* turn off tx, rx */
3428fb6b090SJeff Kirsher
3438fb6b090SJeff Kirsher out_8(&mb->biucc, XMTSP_64);
3448fb6b090SJeff Kirsher out_8(&mb->utr, RTRD);
3458fb6b090SJeff Kirsher out_8(&mb->fifocc, RCVFW_32 | XMTFW_16 | XMTFWU | RCVFWU | XMTBRST);
3468fb6b090SJeff Kirsher out_8(&mb->xmtfc, AUTO_PAD_XMIT); /* auto-pad short frames */
3478fb6b090SJeff Kirsher out_8(&mb->rcvfc, 0);
3488fb6b090SJeff Kirsher
3498fb6b090SJeff Kirsher /* load up the hardware address */
3508fb6b090SJeff Kirsher __mace_set_address(dev, dev->dev_addr);
3518fb6b090SJeff Kirsher
3528fb6b090SJeff Kirsher /* clear the multicast filter */
3538fb6b090SJeff Kirsher if (mp->chipid == BROKEN_ADDRCHG_REV)
3548fb6b090SJeff Kirsher out_8(&mb->iac, LOGADDR);
3558fb6b090SJeff Kirsher else {
3568fb6b090SJeff Kirsher out_8(&mb->iac, ADDRCHG | LOGADDR);
3578fb6b090SJeff Kirsher while ((in_8(&mb->iac) & ADDRCHG) != 0)
3588fb6b090SJeff Kirsher ;
3598fb6b090SJeff Kirsher }
3608fb6b090SJeff Kirsher for (i = 0; i < 8; ++i)
3618fb6b090SJeff Kirsher out_8(&mb->ladrf, 0);
3628fb6b090SJeff Kirsher
3638fb6b090SJeff Kirsher /* done changing address */
3648fb6b090SJeff Kirsher if (mp->chipid != BROKEN_ADDRCHG_REV)
3658fb6b090SJeff Kirsher out_8(&mb->iac, 0);
3668fb6b090SJeff Kirsher
3678fb6b090SJeff Kirsher if (mp->port_aaui)
3688fb6b090SJeff Kirsher out_8(&mb->plscc, PORTSEL_AUI + ENPLSIO);
3698fb6b090SJeff Kirsher else
3708fb6b090SJeff Kirsher out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
3718fb6b090SJeff Kirsher }
3728fb6b090SJeff Kirsher
__mace_set_address(struct net_device * dev,const void * addr)3736c8dc12cSMichael Ellerman static void __mace_set_address(struct net_device *dev, const void *addr)
3748fb6b090SJeff Kirsher {
3758fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
3768fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
3776c8dc12cSMichael Ellerman const unsigned char *p = addr;
3786c8dc12cSMichael Ellerman u8 macaddr[ETH_ALEN];
3798fb6b090SJeff Kirsher int i;
3808fb6b090SJeff Kirsher
3818fb6b090SJeff Kirsher /* load up the hardware address */
3828fb6b090SJeff Kirsher if (mp->chipid == BROKEN_ADDRCHG_REV)
3838fb6b090SJeff Kirsher out_8(&mb->iac, PHYADDR);
3848fb6b090SJeff Kirsher else {
3858fb6b090SJeff Kirsher out_8(&mb->iac, ADDRCHG | PHYADDR);
3868fb6b090SJeff Kirsher while ((in_8(&mb->iac) & ADDRCHG) != 0)
3878fb6b090SJeff Kirsher ;
3888fb6b090SJeff Kirsher }
3898fb6b090SJeff Kirsher for (i = 0; i < 6; ++i)
3906c8dc12cSMichael Ellerman out_8(&mb->padr, macaddr[i] = p[i]);
3916c8dc12cSMichael Ellerman
3926c8dc12cSMichael Ellerman eth_hw_addr_set(dev, macaddr);
3936c8dc12cSMichael Ellerman
3948fb6b090SJeff Kirsher if (mp->chipid != BROKEN_ADDRCHG_REV)
3958fb6b090SJeff Kirsher out_8(&mb->iac, 0);
3968fb6b090SJeff Kirsher }
3978fb6b090SJeff Kirsher
mace_set_address(struct net_device * dev,void * addr)3988fb6b090SJeff Kirsher static int mace_set_address(struct net_device *dev, void *addr)
3998fb6b090SJeff Kirsher {
4008fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
4018fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
4028fb6b090SJeff Kirsher unsigned long flags;
4038fb6b090SJeff Kirsher
4048fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
4058fb6b090SJeff Kirsher
4068fb6b090SJeff Kirsher __mace_set_address(dev, addr);
4078fb6b090SJeff Kirsher
4088fb6b090SJeff Kirsher /* note: setting ADDRCHG clears ENRCV */
4098fb6b090SJeff Kirsher out_8(&mb->maccc, mp->maccc);
4108fb6b090SJeff Kirsher
4118fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
4128fb6b090SJeff Kirsher return 0;
4138fb6b090SJeff Kirsher }
4148fb6b090SJeff Kirsher
mace_clean_rings(struct mace_data * mp)4158fb6b090SJeff Kirsher static inline void mace_clean_rings(struct mace_data *mp)
4168fb6b090SJeff Kirsher {
4178fb6b090SJeff Kirsher int i;
4188fb6b090SJeff Kirsher
4198fb6b090SJeff Kirsher /* free some skb's */
4208fb6b090SJeff Kirsher for (i = 0; i < N_RX_RING; ++i) {
4218fb6b090SJeff Kirsher if (mp->rx_bufs[i] != NULL) {
4228fb6b090SJeff Kirsher dev_kfree_skb(mp->rx_bufs[i]);
4238fb6b090SJeff Kirsher mp->rx_bufs[i] = NULL;
4248fb6b090SJeff Kirsher }
4258fb6b090SJeff Kirsher }
4268fb6b090SJeff Kirsher for (i = mp->tx_empty; i != mp->tx_fill; ) {
4278fb6b090SJeff Kirsher dev_kfree_skb(mp->tx_bufs[i]);
4288fb6b090SJeff Kirsher if (++i >= N_TX_RING)
4298fb6b090SJeff Kirsher i = 0;
4308fb6b090SJeff Kirsher }
4318fb6b090SJeff Kirsher }
4328fb6b090SJeff Kirsher
mace_open(struct net_device * dev)4338fb6b090SJeff Kirsher static int mace_open(struct net_device *dev)
4348fb6b090SJeff Kirsher {
4358fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
4368fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
4378fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
4388fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
4398fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp;
4408fb6b090SJeff Kirsher int i;
4418fb6b090SJeff Kirsher struct sk_buff *skb;
4428fb6b090SJeff Kirsher unsigned char *data;
4438fb6b090SJeff Kirsher
4448fb6b090SJeff Kirsher /* reset the chip */
4458fb6b090SJeff Kirsher mace_reset(dev);
4468fb6b090SJeff Kirsher
4478fb6b090SJeff Kirsher /* initialize list of sk_buffs for receiving and set up recv dma */
4488fb6b090SJeff Kirsher mace_clean_rings(mp);
4498fb6b090SJeff Kirsher memset((char *)mp->rx_cmds, 0, N_RX_RING * sizeof(struct dbdma_cmd));
4508fb6b090SJeff Kirsher cp = mp->rx_cmds;
4518fb6b090SJeff Kirsher for (i = 0; i < N_RX_RING - 1; ++i) {
4521d266430SPradeep A Dalvi skb = netdev_alloc_skb(dev, RX_BUFLEN + 2);
4538fb6b090SJeff Kirsher if (!skb) {
4548fb6b090SJeff Kirsher data = dummy_buf;
4558fb6b090SJeff Kirsher } else {
4568fb6b090SJeff Kirsher skb_reserve(skb, 2); /* so IP header lands on 4-byte bdry */
4578fb6b090SJeff Kirsher data = skb->data;
4588fb6b090SJeff Kirsher }
4598fb6b090SJeff Kirsher mp->rx_bufs[i] = skb;
460f5718726SDavid Gibson cp->req_count = cpu_to_le16(RX_BUFLEN);
461f5718726SDavid Gibson cp->command = cpu_to_le16(INPUT_LAST + INTR_ALWAYS);
462f5718726SDavid Gibson cp->phy_addr = cpu_to_le32(virt_to_bus(data));
4638fb6b090SJeff Kirsher cp->xfer_status = 0;
4648fb6b090SJeff Kirsher ++cp;
4658fb6b090SJeff Kirsher }
4668fb6b090SJeff Kirsher mp->rx_bufs[i] = NULL;
467f5718726SDavid Gibson cp->command = cpu_to_le16(DBDMA_STOP);
4688fb6b090SJeff Kirsher mp->rx_fill = i;
4698fb6b090SJeff Kirsher mp->rx_empty = 0;
4708fb6b090SJeff Kirsher
4718fb6b090SJeff Kirsher /* Put a branch back to the beginning of the receive command list */
4728fb6b090SJeff Kirsher ++cp;
473f5718726SDavid Gibson cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS);
474f5718726SDavid Gibson cp->cmd_dep = cpu_to_le32(virt_to_bus(mp->rx_cmds));
4758fb6b090SJeff Kirsher
4768fb6b090SJeff Kirsher /* start rx dma */
4778fb6b090SJeff Kirsher out_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
4788fb6b090SJeff Kirsher out_le32(&rd->cmdptr, virt_to_bus(mp->rx_cmds));
4798fb6b090SJeff Kirsher out_le32(&rd->control, (RUN << 16) | RUN);
4808fb6b090SJeff Kirsher
4818fb6b090SJeff Kirsher /* put a branch at the end of the tx command list */
4828fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * N_TX_RING;
483f5718726SDavid Gibson cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS);
484f5718726SDavid Gibson cp->cmd_dep = cpu_to_le32(virt_to_bus(mp->tx_cmds));
4858fb6b090SJeff Kirsher
4868fb6b090SJeff Kirsher /* reset tx dma */
4878fb6b090SJeff Kirsher out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
4888fb6b090SJeff Kirsher out_le32(&td->cmdptr, virt_to_bus(mp->tx_cmds));
4898fb6b090SJeff Kirsher mp->tx_fill = 0;
4908fb6b090SJeff Kirsher mp->tx_empty = 0;
4918fb6b090SJeff Kirsher mp->tx_fullup = 0;
4928fb6b090SJeff Kirsher mp->tx_active = 0;
4938fb6b090SJeff Kirsher mp->tx_bad_runt = 0;
4948fb6b090SJeff Kirsher
4958fb6b090SJeff Kirsher /* turn it on! */
4968fb6b090SJeff Kirsher out_8(&mb->maccc, mp->maccc);
4978fb6b090SJeff Kirsher /* enable all interrupts except receive interrupts */
4988fb6b090SJeff Kirsher out_8(&mb->imr, RCVINT);
4998fb6b090SJeff Kirsher
5008fb6b090SJeff Kirsher return 0;
5018fb6b090SJeff Kirsher }
5028fb6b090SJeff Kirsher
mace_close(struct net_device * dev)5038fb6b090SJeff Kirsher static int mace_close(struct net_device *dev)
5048fb6b090SJeff Kirsher {
5058fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
5068fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
5078fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
5088fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
5098fb6b090SJeff Kirsher
5108fb6b090SJeff Kirsher /* disable rx and tx */
5118fb6b090SJeff Kirsher out_8(&mb->maccc, 0);
5128fb6b090SJeff Kirsher out_8(&mb->imr, 0xff); /* disable all intrs */
5138fb6b090SJeff Kirsher
5148fb6b090SJeff Kirsher /* disable rx and tx dma */
515f5718726SDavid Gibson rd->control = cpu_to_le32((RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
516f5718726SDavid Gibson td->control = cpu_to_le32((RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
5178fb6b090SJeff Kirsher
5188fb6b090SJeff Kirsher mace_clean_rings(mp);
5198fb6b090SJeff Kirsher
5208fb6b090SJeff Kirsher return 0;
5218fb6b090SJeff Kirsher }
5228fb6b090SJeff Kirsher
mace_set_timeout(struct net_device * dev)5238fb6b090SJeff Kirsher static inline void mace_set_timeout(struct net_device *dev)
5248fb6b090SJeff Kirsher {
5258fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
5268fb6b090SJeff Kirsher
5278fb6b090SJeff Kirsher if (mp->timeout_active)
5288fb6b090SJeff Kirsher del_timer(&mp->tx_timeout);
5298fb6b090SJeff Kirsher mp->tx_timeout.expires = jiffies + TX_TIMEOUT;
5308fb6b090SJeff Kirsher add_timer(&mp->tx_timeout);
5318fb6b090SJeff Kirsher mp->timeout_active = 1;
5328fb6b090SJeff Kirsher }
5338fb6b090SJeff Kirsher
mace_xmit_start(struct sk_buff * skb,struct net_device * dev)534e6ce3822SYueHaibing static netdev_tx_t mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
5358fb6b090SJeff Kirsher {
5368fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
5378fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
5388fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp, *np;
5398fb6b090SJeff Kirsher unsigned long flags;
5408fb6b090SJeff Kirsher int fill, next, len;
5418fb6b090SJeff Kirsher
5428fb6b090SJeff Kirsher /* see if there's a free slot in the tx ring */
5438fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
5448fb6b090SJeff Kirsher fill = mp->tx_fill;
5458fb6b090SJeff Kirsher next = fill + 1;
5468fb6b090SJeff Kirsher if (next >= N_TX_RING)
5478fb6b090SJeff Kirsher next = 0;
5488fb6b090SJeff Kirsher if (next == mp->tx_empty) {
5498fb6b090SJeff Kirsher netif_stop_queue(dev);
5508fb6b090SJeff Kirsher mp->tx_fullup = 1;
5518fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
5528fb6b090SJeff Kirsher return NETDEV_TX_BUSY; /* can't take it at the moment */
5538fb6b090SJeff Kirsher }
5548fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
5558fb6b090SJeff Kirsher
5568fb6b090SJeff Kirsher /* partially fill in the dma command block */
5578fb6b090SJeff Kirsher len = skb->len;
5588fb6b090SJeff Kirsher if (len > ETH_FRAME_LEN) {
5598fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: xmit frame too long (%d)\n", len);
5608fb6b090SJeff Kirsher len = ETH_FRAME_LEN;
5618fb6b090SJeff Kirsher }
5628fb6b090SJeff Kirsher mp->tx_bufs[fill] = skb;
5638fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * fill;
564f5718726SDavid Gibson cp->req_count = cpu_to_le16(len);
565f5718726SDavid Gibson cp->phy_addr = cpu_to_le32(virt_to_bus(skb->data));
5668fb6b090SJeff Kirsher
5678fb6b090SJeff Kirsher np = mp->tx_cmds + NCMDS_TX * next;
5688fb6b090SJeff Kirsher out_le16(&np->command, DBDMA_STOP);
5698fb6b090SJeff Kirsher
5708fb6b090SJeff Kirsher /* poke the tx dma channel */
5718fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
5728fb6b090SJeff Kirsher mp->tx_fill = next;
5738fb6b090SJeff Kirsher if (!mp->tx_bad_runt && mp->tx_active < MAX_TX_ACTIVE) {
5748fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
5758fb6b090SJeff Kirsher out_le16(&cp->command, OUTPUT_LAST);
5768fb6b090SJeff Kirsher out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
5778fb6b090SJeff Kirsher ++mp->tx_active;
5788fb6b090SJeff Kirsher mace_set_timeout(dev);
5798fb6b090SJeff Kirsher }
5808fb6b090SJeff Kirsher if (++next >= N_TX_RING)
5818fb6b090SJeff Kirsher next = 0;
5828fb6b090SJeff Kirsher if (next == mp->tx_empty)
5838fb6b090SJeff Kirsher netif_stop_queue(dev);
5848fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
5858fb6b090SJeff Kirsher
5868fb6b090SJeff Kirsher return NETDEV_TX_OK;
5878fb6b090SJeff Kirsher }
5888fb6b090SJeff Kirsher
mace_set_multicast(struct net_device * dev)5898fb6b090SJeff Kirsher static void mace_set_multicast(struct net_device *dev)
5908fb6b090SJeff Kirsher {
5918fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
5928fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
5938fb6b090SJeff Kirsher int i;
5948fb6b090SJeff Kirsher u32 crc;
5958fb6b090SJeff Kirsher unsigned long flags;
5968fb6b090SJeff Kirsher
5978fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
5988fb6b090SJeff Kirsher mp->maccc &= ~PROM;
5998fb6b090SJeff Kirsher if (dev->flags & IFF_PROMISC) {
6008fb6b090SJeff Kirsher mp->maccc |= PROM;
6018fb6b090SJeff Kirsher } else {
6028fb6b090SJeff Kirsher unsigned char multicast_filter[8];
6038fb6b090SJeff Kirsher struct netdev_hw_addr *ha;
6048fb6b090SJeff Kirsher
6058fb6b090SJeff Kirsher if (dev->flags & IFF_ALLMULTI) {
6068fb6b090SJeff Kirsher for (i = 0; i < 8; i++)
6078fb6b090SJeff Kirsher multicast_filter[i] = 0xff;
6088fb6b090SJeff Kirsher } else {
6098fb6b090SJeff Kirsher for (i = 0; i < 8; i++)
6108fb6b090SJeff Kirsher multicast_filter[i] = 0;
6118fb6b090SJeff Kirsher netdev_for_each_mc_addr(ha, dev) {
6128fb6b090SJeff Kirsher crc = ether_crc_le(6, ha->addr);
6138fb6b090SJeff Kirsher i = crc >> 26; /* bit number in multicast_filter */
6148fb6b090SJeff Kirsher multicast_filter[i >> 3] |= 1 << (i & 7);
6158fb6b090SJeff Kirsher }
6168fb6b090SJeff Kirsher }
6178fb6b090SJeff Kirsher #if 0
6188fb6b090SJeff Kirsher printk("Multicast filter :");
6198fb6b090SJeff Kirsher for (i = 0; i < 8; i++)
6208fb6b090SJeff Kirsher printk("%02x ", multicast_filter[i]);
6218fb6b090SJeff Kirsher printk("\n");
6228fb6b090SJeff Kirsher #endif
6238fb6b090SJeff Kirsher
6248fb6b090SJeff Kirsher if (mp->chipid == BROKEN_ADDRCHG_REV)
6258fb6b090SJeff Kirsher out_8(&mb->iac, LOGADDR);
6268fb6b090SJeff Kirsher else {
6278fb6b090SJeff Kirsher out_8(&mb->iac, ADDRCHG | LOGADDR);
6288fb6b090SJeff Kirsher while ((in_8(&mb->iac) & ADDRCHG) != 0)
6298fb6b090SJeff Kirsher ;
6308fb6b090SJeff Kirsher }
6318fb6b090SJeff Kirsher for (i = 0; i < 8; ++i)
6328fb6b090SJeff Kirsher out_8(&mb->ladrf, multicast_filter[i]);
6338fb6b090SJeff Kirsher if (mp->chipid != BROKEN_ADDRCHG_REV)
6348fb6b090SJeff Kirsher out_8(&mb->iac, 0);
6358fb6b090SJeff Kirsher }
6368fb6b090SJeff Kirsher /* reset maccc */
6378fb6b090SJeff Kirsher out_8(&mb->maccc, mp->maccc);
6388fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
6398fb6b090SJeff Kirsher }
6408fb6b090SJeff Kirsher
mace_handle_misc_intrs(struct mace_data * mp,int intr,struct net_device * dev)6418fb6b090SJeff Kirsher static void mace_handle_misc_intrs(struct mace_data *mp, int intr, struct net_device *dev)
6428fb6b090SJeff Kirsher {
6438fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
6448fb6b090SJeff Kirsher static int mace_babbles, mace_jabbers;
6458fb6b090SJeff Kirsher
6468fb6b090SJeff Kirsher if (intr & MPCO)
6478fb6b090SJeff Kirsher dev->stats.rx_missed_errors += 256;
6488fb6b090SJeff Kirsher dev->stats.rx_missed_errors += in_8(&mb->mpc); /* reading clears it */
6498fb6b090SJeff Kirsher if (intr & RNTPCO)
6508fb6b090SJeff Kirsher dev->stats.rx_length_errors += 256;
6518fb6b090SJeff Kirsher dev->stats.rx_length_errors += in_8(&mb->rntpc); /* reading clears it */
6528fb6b090SJeff Kirsher if (intr & CERR)
6538fb6b090SJeff Kirsher ++dev->stats.tx_heartbeat_errors;
6548fb6b090SJeff Kirsher if (intr & BABBLE)
6558fb6b090SJeff Kirsher if (mace_babbles++ < 4)
6568fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: babbling transmitter\n");
6578fb6b090SJeff Kirsher if (intr & JABBER)
6588fb6b090SJeff Kirsher if (mace_jabbers++ < 4)
6598fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: jabbering transceiver\n");
6608fb6b090SJeff Kirsher }
6618fb6b090SJeff Kirsher
mace_interrupt(int irq,void * dev_id)6628fb6b090SJeff Kirsher static irqreturn_t mace_interrupt(int irq, void *dev_id)
6638fb6b090SJeff Kirsher {
6648fb6b090SJeff Kirsher struct net_device *dev = (struct net_device *) dev_id;
6658fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
6668fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
6678fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
6688fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp;
6698fb6b090SJeff Kirsher int intr, fs, i, stat, x;
6708fb6b090SJeff Kirsher int xcount, dstat;
6718fb6b090SJeff Kirsher unsigned long flags;
6728fb6b090SJeff Kirsher /* static int mace_last_fs, mace_last_xcount; */
6738fb6b090SJeff Kirsher
6748fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
6758fb6b090SJeff Kirsher intr = in_8(&mb->ir); /* read interrupt register */
6768fb6b090SJeff Kirsher in_8(&mb->xmtrc); /* get retries */
6778fb6b090SJeff Kirsher mace_handle_misc_intrs(mp, intr, dev);
6788fb6b090SJeff Kirsher
6798fb6b090SJeff Kirsher i = mp->tx_empty;
6808fb6b090SJeff Kirsher while (in_8(&mb->pr) & XMTSV) {
6818fb6b090SJeff Kirsher del_timer(&mp->tx_timeout);
6828fb6b090SJeff Kirsher mp->timeout_active = 0;
6838fb6b090SJeff Kirsher /*
6848fb6b090SJeff Kirsher * Clear any interrupt indication associated with this status
6858fb6b090SJeff Kirsher * word. This appears to unlatch any error indication from
6868fb6b090SJeff Kirsher * the DMA controller.
6878fb6b090SJeff Kirsher */
6888fb6b090SJeff Kirsher intr = in_8(&mb->ir);
6898fb6b090SJeff Kirsher if (intr != 0)
6908fb6b090SJeff Kirsher mace_handle_misc_intrs(mp, intr, dev);
6918fb6b090SJeff Kirsher if (mp->tx_bad_runt) {
6928fb6b090SJeff Kirsher fs = in_8(&mb->xmtfs);
6938fb6b090SJeff Kirsher mp->tx_bad_runt = 0;
6948fb6b090SJeff Kirsher out_8(&mb->xmtfc, AUTO_PAD_XMIT);
6958fb6b090SJeff Kirsher continue;
6968fb6b090SJeff Kirsher }
697f5718726SDavid Gibson dstat = le32_to_cpu(td->status);
6988fb6b090SJeff Kirsher /* stop DMA controller */
6998fb6b090SJeff Kirsher out_le32(&td->control, RUN << 16);
7008fb6b090SJeff Kirsher /*
7018fb6b090SJeff Kirsher * xcount is the number of complete frames which have been
7028fb6b090SJeff Kirsher * written to the fifo but for which status has not been read.
7038fb6b090SJeff Kirsher */
7048fb6b090SJeff Kirsher xcount = (in_8(&mb->fifofc) >> XMTFC_SH) & XMTFC_MASK;
7058fb6b090SJeff Kirsher if (xcount == 0 || (dstat & DEAD)) {
7068fb6b090SJeff Kirsher /*
7078fb6b090SJeff Kirsher * If a packet was aborted before the DMA controller has
7088fb6b090SJeff Kirsher * finished transferring it, it seems that there are 2 bytes
7098fb6b090SJeff Kirsher * which are stuck in some buffer somewhere. These will get
7108fb6b090SJeff Kirsher * transmitted as soon as we read the frame status (which
7118fb6b090SJeff Kirsher * reenables the transmit data transfer request). Turning
7128fb6b090SJeff Kirsher * off the DMA controller and/or resetting the MACE doesn't
7138fb6b090SJeff Kirsher * help. So we disable auto-padding and FCS transmission
7148fb6b090SJeff Kirsher * so the two bytes will only be a runt packet which should
7158fb6b090SJeff Kirsher * be ignored by other stations.
7168fb6b090SJeff Kirsher */
7178fb6b090SJeff Kirsher out_8(&mb->xmtfc, DXMTFCS);
7188fb6b090SJeff Kirsher }
7198fb6b090SJeff Kirsher fs = in_8(&mb->xmtfs);
7208fb6b090SJeff Kirsher if ((fs & XMTSV) == 0) {
7218fb6b090SJeff Kirsher printk(KERN_ERR "mace: xmtfs not valid! (fs=%x xc=%d ds=%x)\n",
7228fb6b090SJeff Kirsher fs, xcount, dstat);
7238fb6b090SJeff Kirsher mace_reset(dev);
7248fb6b090SJeff Kirsher /*
7258fb6b090SJeff Kirsher * XXX mace likes to hang the machine after a xmtfs error.
726dbedd44eSJoe Perches * This is hard to reproduce, resetting *may* help
7278fb6b090SJeff Kirsher */
7288fb6b090SJeff Kirsher }
7298fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * i;
730f5718726SDavid Gibson stat = le16_to_cpu(cp->xfer_status);
7318fb6b090SJeff Kirsher if ((fs & (UFLO|LCOL|LCAR|RTRY)) || (dstat & DEAD) || xcount == 0) {
7328fb6b090SJeff Kirsher /*
7338fb6b090SJeff Kirsher * Check whether there were in fact 2 bytes written to
7348fb6b090SJeff Kirsher * the transmit FIFO.
7358fb6b090SJeff Kirsher */
7368fb6b090SJeff Kirsher udelay(1);
7378fb6b090SJeff Kirsher x = (in_8(&mb->fifofc) >> XMTFC_SH) & XMTFC_MASK;
7388fb6b090SJeff Kirsher if (x != 0) {
7398fb6b090SJeff Kirsher /* there were two bytes with an end-of-packet indication */
7408fb6b090SJeff Kirsher mp->tx_bad_runt = 1;
7418fb6b090SJeff Kirsher mace_set_timeout(dev);
7428fb6b090SJeff Kirsher } else {
7438fb6b090SJeff Kirsher /*
7448fb6b090SJeff Kirsher * Either there weren't the two bytes buffered up, or they
7458fb6b090SJeff Kirsher * didn't have an end-of-packet indication.
7468fb6b090SJeff Kirsher * We flush the transmit FIFO just in case (by setting the
7478fb6b090SJeff Kirsher * XMTFWU bit with the transmitter disabled).
7488fb6b090SJeff Kirsher */
7498fb6b090SJeff Kirsher out_8(&mb->maccc, in_8(&mb->maccc) & ~ENXMT);
7508fb6b090SJeff Kirsher out_8(&mb->fifocc, in_8(&mb->fifocc) | XMTFWU);
7518fb6b090SJeff Kirsher udelay(1);
7528fb6b090SJeff Kirsher out_8(&mb->maccc, in_8(&mb->maccc) | ENXMT);
7538fb6b090SJeff Kirsher out_8(&mb->xmtfc, AUTO_PAD_XMIT);
7548fb6b090SJeff Kirsher }
7558fb6b090SJeff Kirsher }
7568fb6b090SJeff Kirsher /* dma should have finished */
7578fb6b090SJeff Kirsher if (i == mp->tx_fill) {
7588fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: tx ring ran out? (fs=%x xc=%d ds=%x)\n",
7598fb6b090SJeff Kirsher fs, xcount, dstat);
7608fb6b090SJeff Kirsher continue;
7618fb6b090SJeff Kirsher }
7628fb6b090SJeff Kirsher /* Update stats */
7638fb6b090SJeff Kirsher if (fs & (UFLO|LCOL|LCAR|RTRY)) {
7648fb6b090SJeff Kirsher ++dev->stats.tx_errors;
7658fb6b090SJeff Kirsher if (fs & LCAR)
7668fb6b090SJeff Kirsher ++dev->stats.tx_carrier_errors;
7678fb6b090SJeff Kirsher if (fs & (UFLO|LCOL|RTRY))
7688fb6b090SJeff Kirsher ++dev->stats.tx_aborted_errors;
7698fb6b090SJeff Kirsher } else {
7708fb6b090SJeff Kirsher dev->stats.tx_bytes += mp->tx_bufs[i]->len;
7718fb6b090SJeff Kirsher ++dev->stats.tx_packets;
7728fb6b090SJeff Kirsher }
7735f5a8c75SYang Wei dev_consume_skb_irq(mp->tx_bufs[i]);
7748fb6b090SJeff Kirsher --mp->tx_active;
7758fb6b090SJeff Kirsher if (++i >= N_TX_RING)
7768fb6b090SJeff Kirsher i = 0;
7778fb6b090SJeff Kirsher #if 0
7788fb6b090SJeff Kirsher mace_last_fs = fs;
7798fb6b090SJeff Kirsher mace_last_xcount = xcount;
7808fb6b090SJeff Kirsher #endif
7818fb6b090SJeff Kirsher }
7828fb6b090SJeff Kirsher
7838fb6b090SJeff Kirsher if (i != mp->tx_empty) {
7848fb6b090SJeff Kirsher mp->tx_fullup = 0;
7858fb6b090SJeff Kirsher netif_wake_queue(dev);
7868fb6b090SJeff Kirsher }
7878fb6b090SJeff Kirsher mp->tx_empty = i;
7888fb6b090SJeff Kirsher i += mp->tx_active;
7898fb6b090SJeff Kirsher if (i >= N_TX_RING)
7908fb6b090SJeff Kirsher i -= N_TX_RING;
7918fb6b090SJeff Kirsher if (!mp->tx_bad_runt && i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE) {
7928fb6b090SJeff Kirsher do {
7938fb6b090SJeff Kirsher /* set up the next one */
7948fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * i;
7958fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
7968fb6b090SJeff Kirsher out_le16(&cp->command, OUTPUT_LAST);
7978fb6b090SJeff Kirsher ++mp->tx_active;
7988fb6b090SJeff Kirsher if (++i >= N_TX_RING)
7998fb6b090SJeff Kirsher i = 0;
8008fb6b090SJeff Kirsher } while (i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE);
8018fb6b090SJeff Kirsher out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
8028fb6b090SJeff Kirsher mace_set_timeout(dev);
8038fb6b090SJeff Kirsher }
8048fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
8058fb6b090SJeff Kirsher return IRQ_HANDLED;
8068fb6b090SJeff Kirsher }
8078fb6b090SJeff Kirsher
mace_tx_timeout(struct timer_list * t)808de892f8fSKees Cook static void mace_tx_timeout(struct timer_list *t)
8098fb6b090SJeff Kirsher {
810de892f8fSKees Cook struct mace_data *mp = from_timer(mp, t, tx_timeout);
811de892f8fSKees Cook struct net_device *dev = macio_get_drvdata(mp->mdev);
8128fb6b090SJeff Kirsher volatile struct mace __iomem *mb = mp->mace;
8138fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *td = mp->tx_dma;
8148fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
8158fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp;
8168fb6b090SJeff Kirsher unsigned long flags;
8178fb6b090SJeff Kirsher int i;
8188fb6b090SJeff Kirsher
8198fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
8208fb6b090SJeff Kirsher mp->timeout_active = 0;
8218fb6b090SJeff Kirsher if (mp->tx_active == 0 && !mp->tx_bad_runt)
8228fb6b090SJeff Kirsher goto out;
8238fb6b090SJeff Kirsher
8248fb6b090SJeff Kirsher /* update various counters */
8258fb6b090SJeff Kirsher mace_handle_misc_intrs(mp, in_8(&mb->ir), dev);
8268fb6b090SJeff Kirsher
8278fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty;
8288fb6b090SJeff Kirsher
8298fb6b090SJeff Kirsher /* turn off both tx and rx and reset the chip */
8308fb6b090SJeff Kirsher out_8(&mb->maccc, 0);
8318fb6b090SJeff Kirsher printk(KERN_ERR "mace: transmit timeout - resetting\n");
8328fb6b090SJeff Kirsher dbdma_reset(td);
8338fb6b090SJeff Kirsher mace_reset(dev);
8348fb6b090SJeff Kirsher
8358fb6b090SJeff Kirsher /* restart rx dma */
836f5718726SDavid Gibson cp = bus_to_virt(le32_to_cpu(rd->cmdptr));
8378fb6b090SJeff Kirsher dbdma_reset(rd);
8388fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
8398fb6b090SJeff Kirsher out_le32(&rd->cmdptr, virt_to_bus(cp));
8408fb6b090SJeff Kirsher out_le32(&rd->control, (RUN << 16) | RUN);
8418fb6b090SJeff Kirsher
8428fb6b090SJeff Kirsher /* fix up the transmit side */
8438fb6b090SJeff Kirsher i = mp->tx_empty;
8448fb6b090SJeff Kirsher mp->tx_active = 0;
8458fb6b090SJeff Kirsher ++dev->stats.tx_errors;
8468fb6b090SJeff Kirsher if (mp->tx_bad_runt) {
8478fb6b090SJeff Kirsher mp->tx_bad_runt = 0;
8488fb6b090SJeff Kirsher } else if (i != mp->tx_fill) {
849*3dfe3486SYang Yingliang dev_kfree_skb_irq(mp->tx_bufs[i]);
8508fb6b090SJeff Kirsher if (++i >= N_TX_RING)
8518fb6b090SJeff Kirsher i = 0;
8528fb6b090SJeff Kirsher mp->tx_empty = i;
8538fb6b090SJeff Kirsher }
8548fb6b090SJeff Kirsher mp->tx_fullup = 0;
8558fb6b090SJeff Kirsher netif_wake_queue(dev);
8568fb6b090SJeff Kirsher if (i != mp->tx_fill) {
8578fb6b090SJeff Kirsher cp = mp->tx_cmds + NCMDS_TX * i;
8588fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
8598fb6b090SJeff Kirsher out_le16(&cp->command, OUTPUT_LAST);
8608fb6b090SJeff Kirsher out_le32(&td->cmdptr, virt_to_bus(cp));
8618fb6b090SJeff Kirsher out_le32(&td->control, (RUN << 16) | RUN);
8628fb6b090SJeff Kirsher ++mp->tx_active;
8638fb6b090SJeff Kirsher mace_set_timeout(dev);
8648fb6b090SJeff Kirsher }
8658fb6b090SJeff Kirsher
8668fb6b090SJeff Kirsher /* turn it back on */
8678fb6b090SJeff Kirsher out_8(&mb->imr, RCVINT);
8688fb6b090SJeff Kirsher out_8(&mb->maccc, mp->maccc);
8698fb6b090SJeff Kirsher
8708fb6b090SJeff Kirsher out:
8718fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
8728fb6b090SJeff Kirsher }
8738fb6b090SJeff Kirsher
mace_txdma_intr(int irq,void * dev_id)8748fb6b090SJeff Kirsher static irqreturn_t mace_txdma_intr(int irq, void *dev_id)
8758fb6b090SJeff Kirsher {
8768fb6b090SJeff Kirsher return IRQ_HANDLED;
8778fb6b090SJeff Kirsher }
8788fb6b090SJeff Kirsher
mace_rxdma_intr(int irq,void * dev_id)8798fb6b090SJeff Kirsher static irqreturn_t mace_rxdma_intr(int irq, void *dev_id)
8808fb6b090SJeff Kirsher {
8818fb6b090SJeff Kirsher struct net_device *dev = (struct net_device *) dev_id;
8828fb6b090SJeff Kirsher struct mace_data *mp = netdev_priv(dev);
8838fb6b090SJeff Kirsher volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
8848fb6b090SJeff Kirsher volatile struct dbdma_cmd *cp, *np;
8858fb6b090SJeff Kirsher int i, nb, stat, next;
8868fb6b090SJeff Kirsher struct sk_buff *skb;
8878fb6b090SJeff Kirsher unsigned frame_status;
8888fb6b090SJeff Kirsher static int mace_lost_status;
8898fb6b090SJeff Kirsher unsigned char *data;
8908fb6b090SJeff Kirsher unsigned long flags;
8918fb6b090SJeff Kirsher
8928fb6b090SJeff Kirsher spin_lock_irqsave(&mp->lock, flags);
8938fb6b090SJeff Kirsher for (i = mp->rx_empty; i != mp->rx_fill; ) {
8948fb6b090SJeff Kirsher cp = mp->rx_cmds + i;
895f5718726SDavid Gibson stat = le16_to_cpu(cp->xfer_status);
8968fb6b090SJeff Kirsher if ((stat & ACTIVE) == 0) {
8978fb6b090SJeff Kirsher next = i + 1;
8988fb6b090SJeff Kirsher if (next >= N_RX_RING)
8998fb6b090SJeff Kirsher next = 0;
9008fb6b090SJeff Kirsher np = mp->rx_cmds + next;
9018fb6b090SJeff Kirsher if (next != mp->rx_fill &&
902f5718726SDavid Gibson (le16_to_cpu(np->xfer_status) & ACTIVE) != 0) {
9038fb6b090SJeff Kirsher printk(KERN_DEBUG "mace: lost a status word\n");
9048fb6b090SJeff Kirsher ++mace_lost_status;
9058fb6b090SJeff Kirsher } else
9068fb6b090SJeff Kirsher break;
9078fb6b090SJeff Kirsher }
908f5718726SDavid Gibson nb = le16_to_cpu(cp->req_count) - le16_to_cpu(cp->res_count);
9098fb6b090SJeff Kirsher out_le16(&cp->command, DBDMA_STOP);
9108fb6b090SJeff Kirsher /* got a packet, have a look at it */
9118fb6b090SJeff Kirsher skb = mp->rx_bufs[i];
9128fb6b090SJeff Kirsher if (!skb) {
9138fb6b090SJeff Kirsher ++dev->stats.rx_dropped;
9148fb6b090SJeff Kirsher } else if (nb > 8) {
9158fb6b090SJeff Kirsher data = skb->data;
9168fb6b090SJeff Kirsher frame_status = (data[nb-3] << 8) + data[nb-4];
9178fb6b090SJeff Kirsher if (frame_status & (RS_OFLO|RS_CLSN|RS_FRAMERR|RS_FCSERR)) {
9188fb6b090SJeff Kirsher ++dev->stats.rx_errors;
9198fb6b090SJeff Kirsher if (frame_status & RS_OFLO)
9208fb6b090SJeff Kirsher ++dev->stats.rx_over_errors;
9218fb6b090SJeff Kirsher if (frame_status & RS_FRAMERR)
9228fb6b090SJeff Kirsher ++dev->stats.rx_frame_errors;
9238fb6b090SJeff Kirsher if (frame_status & RS_FCSERR)
9248fb6b090SJeff Kirsher ++dev->stats.rx_crc_errors;
9258fb6b090SJeff Kirsher } else {
9268fb6b090SJeff Kirsher /* Mace feature AUTO_STRIP_RCV is on by default, dropping the
9278fb6b090SJeff Kirsher * FCS on frames with 802.3 headers. This means that Ethernet
9288fb6b090SJeff Kirsher * frames have 8 extra octets at the end, while 802.3 frames
9298fb6b090SJeff Kirsher * have only 4. We need to correctly account for this. */
9308fb6b090SJeff Kirsher if (*(unsigned short *)(data+12) < 1536) /* 802.3 header */
9318fb6b090SJeff Kirsher nb -= 4;
9328fb6b090SJeff Kirsher else /* Ethernet header; mace includes FCS */
9338fb6b090SJeff Kirsher nb -= 8;
9348fb6b090SJeff Kirsher skb_put(skb, nb);
9358fb6b090SJeff Kirsher skb->protocol = eth_type_trans(skb, dev);
9368fb6b090SJeff Kirsher dev->stats.rx_bytes += skb->len;
9378fb6b090SJeff Kirsher netif_rx(skb);
9388fb6b090SJeff Kirsher mp->rx_bufs[i] = NULL;
9398fb6b090SJeff Kirsher ++dev->stats.rx_packets;
9408fb6b090SJeff Kirsher }
9418fb6b090SJeff Kirsher } else {
9428fb6b090SJeff Kirsher ++dev->stats.rx_errors;
9438fb6b090SJeff Kirsher ++dev->stats.rx_length_errors;
9448fb6b090SJeff Kirsher }
9458fb6b090SJeff Kirsher
9468fb6b090SJeff Kirsher /* advance to next */
9478fb6b090SJeff Kirsher if (++i >= N_RX_RING)
9488fb6b090SJeff Kirsher i = 0;
9498fb6b090SJeff Kirsher }
9508fb6b090SJeff Kirsher mp->rx_empty = i;
9518fb6b090SJeff Kirsher
9528fb6b090SJeff Kirsher i = mp->rx_fill;
9538fb6b090SJeff Kirsher for (;;) {
9548fb6b090SJeff Kirsher next = i + 1;
9558fb6b090SJeff Kirsher if (next >= N_RX_RING)
9568fb6b090SJeff Kirsher next = 0;
9578fb6b090SJeff Kirsher if (next == mp->rx_empty)
9588fb6b090SJeff Kirsher break;
9598fb6b090SJeff Kirsher cp = mp->rx_cmds + i;
9608fb6b090SJeff Kirsher skb = mp->rx_bufs[i];
9618fb6b090SJeff Kirsher if (!skb) {
96231a4c8b8SPradeep A. Dalvi skb = netdev_alloc_skb(dev, RX_BUFLEN + 2);
9638fb6b090SJeff Kirsher if (skb) {
9648fb6b090SJeff Kirsher skb_reserve(skb, 2);
9658fb6b090SJeff Kirsher mp->rx_bufs[i] = skb;
9668fb6b090SJeff Kirsher }
9678fb6b090SJeff Kirsher }
968f5718726SDavid Gibson cp->req_count = cpu_to_le16(RX_BUFLEN);
9698fb6b090SJeff Kirsher data = skb? skb->data: dummy_buf;
970f5718726SDavid Gibson cp->phy_addr = cpu_to_le32(virt_to_bus(data));
9718fb6b090SJeff Kirsher out_le16(&cp->xfer_status, 0);
9728fb6b090SJeff Kirsher out_le16(&cp->command, INPUT_LAST + INTR_ALWAYS);
9738fb6b090SJeff Kirsher #if 0
974f5718726SDavid Gibson if ((le32_to_cpu(rd->status) & ACTIVE) != 0) {
9758fb6b090SJeff Kirsher out_le32(&rd->control, (PAUSE << 16) | PAUSE);
9768fb6b090SJeff Kirsher while ((in_le32(&rd->status) & ACTIVE) != 0)
9778fb6b090SJeff Kirsher ;
9788fb6b090SJeff Kirsher }
9798fb6b090SJeff Kirsher #endif
9808fb6b090SJeff Kirsher i = next;
9818fb6b090SJeff Kirsher }
9828fb6b090SJeff Kirsher if (i != mp->rx_fill) {
9838fb6b090SJeff Kirsher out_le32(&rd->control, ((RUN|WAKE) << 16) | (RUN|WAKE));
9848fb6b090SJeff Kirsher mp->rx_fill = i;
9858fb6b090SJeff Kirsher }
9868fb6b090SJeff Kirsher spin_unlock_irqrestore(&mp->lock, flags);
9878fb6b090SJeff Kirsher return IRQ_HANDLED;
9888fb6b090SJeff Kirsher }
9898fb6b090SJeff Kirsher
99014448e2fSFabian Frederick static const struct of_device_id mace_match[] =
9918fb6b090SJeff Kirsher {
9928fb6b090SJeff Kirsher {
9938fb6b090SJeff Kirsher .name = "mace",
9948fb6b090SJeff Kirsher },
9958fb6b090SJeff Kirsher {},
9968fb6b090SJeff Kirsher };
9978fb6b090SJeff Kirsher MODULE_DEVICE_TABLE (of, mace_match);
9988fb6b090SJeff Kirsher
9998fb6b090SJeff Kirsher static struct macio_driver mace_driver =
10008fb6b090SJeff Kirsher {
10018fb6b090SJeff Kirsher .driver = {
10028fb6b090SJeff Kirsher .name = "mace",
10038fb6b090SJeff Kirsher .owner = THIS_MODULE,
10048fb6b090SJeff Kirsher .of_match_table = mace_match,
10058fb6b090SJeff Kirsher },
10068fb6b090SJeff Kirsher .probe = mace_probe,
10078fb6b090SJeff Kirsher .remove = mace_remove,
10088fb6b090SJeff Kirsher };
10098fb6b090SJeff Kirsher
10108fb6b090SJeff Kirsher
mace_init(void)10118fb6b090SJeff Kirsher static int __init mace_init(void)
10128fb6b090SJeff Kirsher {
10138fb6b090SJeff Kirsher return macio_register_driver(&mace_driver);
10148fb6b090SJeff Kirsher }
10158fb6b090SJeff Kirsher
mace_cleanup(void)10168fb6b090SJeff Kirsher static void __exit mace_cleanup(void)
10178fb6b090SJeff Kirsher {
10188fb6b090SJeff Kirsher macio_unregister_driver(&mace_driver);
10198fb6b090SJeff Kirsher
10208fb6b090SJeff Kirsher kfree(dummy_buf);
10218fb6b090SJeff Kirsher dummy_buf = NULL;
10228fb6b090SJeff Kirsher }
10238fb6b090SJeff Kirsher
10248fb6b090SJeff Kirsher MODULE_AUTHOR("Paul Mackerras");
10258fb6b090SJeff Kirsher MODULE_DESCRIPTION("PowerMac MACE driver.");
10268fb6b090SJeff Kirsher module_param(port_aaui, int, 0);
10278fb6b090SJeff Kirsher MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
10288fb6b090SJeff Kirsher MODULE_LICENSE("GPL");
10298fb6b090SJeff Kirsher
10308fb6b090SJeff Kirsher module_init(mace_init);
10318fb6b090SJeff Kirsher module_exit(mace_cleanup);
1032