usb: cdc_ether: Add new product id for the 5AE profile
[linux-2.6.git] / drivers / net / mac89x0.c
index 8472b71..669b317 100644 (file)
@@ -73,8 +73,6 @@ static char *version =
    or override something. */
 #include <linux/module.h>
 
-#define PRINTK(x) printk x
-
 /*
   Sources:
 
@@ -90,7 +88,6 @@ static char *version =
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/nubus.h>
 #include <linux/errno.h>
@@ -99,9 +96,10 @@ static char *version =
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/gfp.h>
 
 #include <asm/system.h>
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/hwtest.h>
 #include <asm/macints.h>
@@ -112,7 +110,6 @@ static unsigned int net_debug = NET_DEBUG;
 
 /* Information that need to be kept for each board. */
 struct net_local {
-       struct net_device_stats stats;
        int chip_type;          /* one of: CS8900, CS8920, CS8920M */
        char chip_revision;     /* revision letter of the chip ('A'...) */
        int send_cmd;           /* the propercommand used to send a packet. */
@@ -128,8 +125,8 @@ struct net_local {
 extern void reset_chip(struct net_device *dev);
 #endif
 static int net_open(struct net_device *dev);
-static int     net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t net_interrupt(int irq, void *dev_id);
 static void set_multicast_list(struct net_device *dev);
 static void net_rx(struct net_device *dev);
 static int net_close(struct net_device *dev);
@@ -168,6 +165,17 @@ writereg(struct net_device *dev, int portno, int value)
        nubus_writew(swab16(value), dev->mem_start + portno);
 }
 
+static const struct net_device_ops mac89x0_netdev_ops = {
+       .ndo_open               = net_open,
+       .ndo_stop               = net_close,
+       .ndo_start_xmit         = net_send_packet,
+       .ndo_get_stats          = net_get_stats,
+       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_mac_address    = set_mac_address,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+};
+
 /* Probe for the CS8900 card in slot E.  We won't bother looking
    anywhere else until we have a really good reason to do so. */
 struct net_device * __init mac89x0_probe(int unit)
@@ -182,6 +190,9 @@ struct net_device * __init mac89x0_probe(int unit)
        unsigned short sig;
        int err = -ENODEV;
 
+       if (!MACH_IS_MAC)
+               return ERR_PTR(-ENODEV);
+
        dev = alloc_etherdev(sizeof(struct net_local));
        if (!dev)
                return ERR_PTR(-ENOMEM);
@@ -191,8 +202,6 @@ struct net_device * __init mac89x0_probe(int unit)
                netdev_boot_setup_check(dev);
        }
 
-       SET_MODULE_OWNER(dev);
-
        if (once_is_enough)
                goto out;
        once_is_enough = 1;
@@ -212,8 +221,8 @@ struct net_device * __init mac89x0_probe(int unit)
                int card_present;
 
                local_irq_save(flags);
-               card_present = hwreg_present((void*) ioaddr+4)
-                 && hwreg_present((void*) ioaddr + DATA_PORT);
+               card_present = (hwreg_present((void*) ioaddr+4) &&
+                               hwreg_present((void*) ioaddr + DATA_PORT));
                local_irq_restore(flags);
 
                if (!card_present)
@@ -274,25 +283,17 @@ struct net_device * __init mac89x0_probe(int unit)
         }
 
        dev->irq = SLOT2IRQ(slot);
-       printk(" IRQ %d ADDR ", dev->irq);
 
-       /* print the ethernet address. */
-       for (i = 0; i < ETH_ALEN; i++)
-               printk("%2.2x%s", dev->dev_addr[i],
-                      ((i < ETH_ALEN-1) ? ":" : ""));
-       printk("\n");
+       /* print the IRQ and ethernet address. */
+
+       printk(" IRQ %d ADDR %pM\n", dev->irq, dev->dev_addr);
 
-       dev->open               = net_open;
-       dev->stop               = net_close;
-       dev->hard_start_xmit = net_send_packet;
-       dev->get_stats  = net_get_stats;
-       dev->set_multicast_list = &set_multicast_list;
-       dev->set_mac_address = &set_mac_address;
+       dev->netdev_ops         = &mac89x0_netdev_ops;
 
        err = register_netdev(dev);
        if (err)
                goto out1;
-       return 0;
+       return NULL;
 out1:
        nubus_writew(0, dev->base_addr + ADD_PORT);
 out:
@@ -335,7 +336,7 @@ net_open(struct net_device *dev)
        writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) & ~ENABLE_IRQ);
 
        /* Grab the interrupt */
-       if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev))
+       if (request_irq(dev->irq, net_interrupt, 0, "cs89x0", dev))
                return -EAGAIN;
 
        /* Set up the IRQ - Apparently magic */
@@ -374,64 +375,46 @@ net_open(struct net_device *dev)
 static int
 net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-       if (dev->tbusy) {
-               /* If we get here, some higher level has decided we are broken.
-                  There should really be a "kick me" function call instead. */
-               int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 5)
-                       return 1;
-               if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
-                          tx_done(dev) ? "IRQ conflict" : "network cable problem");
-               /* Try to restart the adaptor. */
-               dev->tbusy=0;
-               dev->trans_start = jiffies;
-       }
-
-       /* Block a timer-based transmit from overlapping.  This could better be
-          done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-               printk("%s: Transmitter access conflict.\n", dev->name);
-       else {
-               struct net_local *lp = netdev_priv(dev);
-               unsigned long flags;
-
-               if (net_debug > 3)
-                       printk("%s: sent %d byte packet of type %x\n",
-                              dev->name, skb->len,
-                              (skb->data[ETH_ALEN+ETH_ALEN] << 8)
-                              | skb->data[ETH_ALEN+ETH_ALEN+1]);
-
-               /* keep the upload from being interrupted, since we
-                   ask the chip to start transmitting before the
-                   whole packet has been completely uploaded. */
-               local_irq_save(flags);
+       struct net_local *lp = netdev_priv(dev);
+       unsigned long flags;
 
-               /* initiate a transmit sequence */
-               writereg(dev, PP_TxCMD, lp->send_cmd);
-               writereg(dev, PP_TxLength, skb->len);
+       if (net_debug > 3)
+               printk("%s: sent %d byte packet of type %x\n",
+                      dev->name, skb->len,
+                      (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+                      | skb->data[ETH_ALEN+ETH_ALEN+1]);
 
-               /* Test to see if the chip has allocated memory for the packet */
-               if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
-                       /* Gasp!  It hasn't.  But that shouldn't happen since
-                          we're waiting for TxOk, so return 1 and requeue this packet. */
-                       local_irq_restore(flags);
-                       return 1;
-               }
+       /* keep the upload from being interrupted, since we
+          ask the chip to start transmitting before the
+          whole packet has been completely uploaded. */
+       local_irq_save(flags);
+       netif_stop_queue(dev);
 
-               /* Write the contents of the packet */
-               memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
+       /* initiate a transmit sequence */
+       writereg(dev, PP_TxCMD, lp->send_cmd);
+       writereg(dev, PP_TxLength, skb->len);
 
+       /* Test to see if the chip has allocated memory for the packet */
+       if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+               /* Gasp!  It hasn't.  But that shouldn't happen since
+                  we're waiting for TxOk, so return 1 and requeue this packet. */
                local_irq_restore(flags);
-               dev->trans_start = jiffies;
+               return NETDEV_TX_BUSY;
        }
+
+       /* Write the contents of the packet */
+       skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame),
+                                 skb->len+1);
+
+       local_irq_restore(flags);
        dev_kfree_skb (skb);
 
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t net_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        struct net_local *lp;
@@ -441,9 +424,6 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                printk ("net_interrupt(): irq %d for unknown device.\n", irq);
                return IRQ_NONE;
        }
-       if (dev->interrupt)
-               printk("%s: Re-entering the interrupt handler.\n", dev->name);
-       dev->interrupt = 1;
 
        ioaddr = dev->base_addr;
        lp = netdev_priv(dev);
@@ -463,14 +443,18 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                        net_rx(dev);
                        break;
                case ISQ_TRANSMITTER_EVENT:
-                       lp->stats.tx_packets++;
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);        /* Inform upper layers. */
-                       if ((status & TX_OK) == 0) lp->stats.tx_errors++;
-                       if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
-                       if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
-                       if (status & TX_LATE_COL) lp->stats.tx_window_errors++;
-                       if (status & TX_16_COL) lp->stats.tx_aborted_errors++;
+                       dev->stats.tx_packets++;
+                       netif_wake_queue(dev);
+                       if ((status & TX_OK) == 0)
+                               dev->stats.tx_errors++;
+                       if (status & TX_LOST_CRS)
+                               dev->stats.tx_carrier_errors++;
+                       if (status & TX_SQE_ERROR)
+                               dev->stats.tx_heartbeat_errors++;
+                       if (status & TX_LATE_COL)
+                               dev->stats.tx_window_errors++;
+                       if (status & TX_16_COL)
+                               dev->stats.tx_aborted_errors++;
                        break;
                case ISQ_BUFFER_EVENT:
                        if (status & READY_FOR_TX) {
@@ -479,8 +463,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                                    That shouldn't happen since we only ever
                                    load one packet.  Shrug.  Do the right
                                    thing anyway. */
-                               dev->tbusy = 0;
-                               mark_bh(NET_BH);        /* Inform upper layers. */
+                               netif_wake_queue(dev);
                        }
                        if (status & TX_UNDERRUN) {
                                if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
@@ -490,14 +473,13 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                         }
                        break;
                case ISQ_RX_MISS_EVENT:
-                       lp->stats.rx_missed_errors += (status >>6);
+                       dev->stats.rx_missed_errors += (status >> 6);
                        break;
                case ISQ_TX_COL_EVENT:
-                       lp->stats.collisions += (status >>6);
+                       dev->stats.collisions += (status >> 6);
                        break;
                }
        }
-       dev->interrupt = 0;
        return IRQ_HANDLED;
 }
 
@@ -505,19 +487,22 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 static void
 net_rx(struct net_device *dev)
 {
-       struct net_local *lp = netdev_priv(dev);
        struct sk_buff *skb;
        int status, length;
 
        status = readreg(dev, PP_RxStatus);
        if ((status & RX_OK) == 0) {
-               lp->stats.rx_errors++;
-               if (status & RX_RUNT) lp->stats.rx_length_errors++;
-               if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++;
-               if (status & RX_CRC_ERROR) if (!(status & (RX_EXTRA_DATA|RX_RUNT)))
+               dev->stats.rx_errors++;
+               if (status & RX_RUNT)
+                               dev->stats.rx_length_errors++;
+               if (status & RX_EXTRA_DATA)
+                               dev->stats.rx_length_errors++;
+               if ((status & RX_CRC_ERROR) &&
+                   !(status & (RX_EXTRA_DATA|RX_RUNT)))
                        /* per str 172 */
-                       lp->stats.rx_crc_errors++;
-               if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++;
+                       dev->stats.rx_crc_errors++;
+               if (status & RX_DRIBBLE)
+                               dev->stats.rx_frame_errors++;
                return;
        }
 
@@ -526,13 +511,13 @@ net_rx(struct net_device *dev)
        skb = alloc_skb(length, GFP_ATOMIC);
        if (skb == NULL) {
                printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-               lp->stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                return;
        }
        skb_put(skb, length);
-       skb->dev = dev;
 
-       memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
+       skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame),
+                               length);
 
        if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
                                  dev->name, length,
@@ -541,9 +526,8 @@ net_rx(struct net_device *dev)
 
         skb->protocol=eth_type_trans(skb,dev);
        netif_rx(skb);
-       dev->last_rx = jiffies;
-       lp->stats.rx_packets++;
-       lp->stats.rx_bytes += length;
+       dev->stats.rx_packets++;
+       dev->stats.rx_bytes += length;
 }
 
 /* The inverse routine to net_open(). */
@@ -571,16 +555,15 @@ net_close(struct net_device *dev)
 static struct net_device_stats *
 net_get_stats(struct net_device *dev)
 {
-       struct net_local *lp = netdev_priv(dev);
        unsigned long flags;
 
        local_irq_save(flags);
        /* Update the statistics from the device registers. */
-       lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
-       lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
+       dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
+       dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
        local_irq_restore(flags);
 
-       return &lp->stats;
+       return &dev->stats;
 }
 
 static void set_multicast_list(struct net_device *dev)
@@ -590,9 +573,7 @@ static void set_multicast_list(struct net_device *dev)
        if(dev->flags&IFF_PROMISC)
        {
                lp->rx_mode = RX_ALL_ACCEPT;
-       }
-       else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
-       {
+       } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) {
                /* The multicast-accept list is initialized to accept-all, and we
                   rely on higher-level filtering for now. */
                lp->rx_mode = RX_MULTCAST_ACCEPT;
@@ -611,8 +592,6 @@ static void set_multicast_list(struct net_device *dev)
 static int set_mac_address(struct net_device *dev, void *addr)
 {
        int i;
-       if (dev->start)
-               return -EBUSY;
        printk("%s: Setting MAC address to ", dev->name);
        for (i = 0; i < 6; i++)
                printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
@@ -633,7 +612,7 @@ module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)");
 MODULE_LICENSE("GPL");
 
-int
+int __init
 init_module(void)
 {
        net_debug = debug;
@@ -653,14 +632,3 @@ cleanup_module(void)
        free_netdev(dev_cs89x0);
 }
 #endif /* MODULE */
-
-/*
- * Local variables:
- *  compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o mac89x0.o mac89x0.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  c-indent-level: 8
- *  tab-width: 8
- * End:
- *
- */