]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] M68k update (part 27)
authorGeert Uytterhoeven <geert@linux-m68k.org>
Tue, 23 Jul 2002 13:23:00 +0000 (06:23 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Tue, 23 Jul 2002 13:23:00 +0000 (06:23 -0700)
Mac m68k Ethernet driver updates (from 2.4.x)
 - mace68k_probe() got renamed to mace_probe()
 - Add missing MODULE_LICENSE()
 - Add missing register definition for SONIC_DCR2

drivers/net/Space.c
drivers/net/macmace.c
drivers/net/macsonic.c
drivers/net/sonic.h

index 254d256c14eae3d3d1d153a011fe348dd54fab93..41db686b2c6ee9615ef43dc02e20dbd7d3684713 100644 (file)
@@ -99,7 +99,7 @@ extern int bagetlance_probe(struct net_device *);
 extern int mvme147lance_probe(struct net_device *dev);
 extern int tc515_probe(struct net_device *dev);
 extern int lance_probe(struct net_device *dev);
-extern int mace68k_probe(struct net_device *dev);
+extern int mace_probe(struct net_device *dev);
 extern int macsonic_probe(struct net_device *dev);
 extern int mac8390_probe(struct net_device *dev);
 extern int mac89x0_probe(struct net_device *dev);
@@ -354,7 +354,7 @@ static struct devprobe m68k_probes[] __initdata = {
        {mvme147lance_probe, 0},
 #endif
 #ifdef CONFIG_MACMACE          /* Mac 68k Quadra AV builtin Ethernet */
-       {mace68k_probe, 0},
+       {mace_probe, 0},
 #endif
 #ifdef CONFIG_MACSONIC         /* Mac SONIC-based Ethernet of all sorts */ 
        {macsonic_probe, 0},
index 9f792a43f0d7932ebbd0078775eca13ccd06952c..7bab986b43b4334a07de046ca5eb6ebbf095e8a0 100644 (file)
  *
  *     Copyright (C) 1996 Paul Mackerras.
  *     Copyright (C) 1998 Alan Cox <alan@redhat.com>
+ *
+ *     Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver
  */
 
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/string.h>
-#include <linux/timer.h>
 #include <linux/crc32.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_psc.h>
+#include <asm/page.h>
 #include "mace.h"
 
+#define N_TX_RING      1
 #define N_RX_RING      8
-#define N_TX_RING      2
-#define MAX_TX_ACTIVE  1
-#define NCMDS_TX       1       /* dma commands per element in tx ring */
-#define RX_BUFLEN      (ETH_FRAME_LEN + 8)
-#define TX_TIMEOUT     HZ      /* 1 second */
+#define N_RX_PAGES     ((N_RX_RING * 0x0800 + PAGE_SIZE - 1) / PAGE_SIZE)
+#define TX_TIMEOUT     HZ
 
 /* Bits in transmit DMA status */
 #define TX_DMA_ERR     0x80
 #define MACE_BASE      (void *)(0x50F1C000)
 #define MACE_PROM      (void *)(0x50F08001)
 
-struct mace68k_data
-{
+struct mace_data {
        volatile struct mace *mace;
        volatile unsigned char *tx_ring;
+       volatile unsigned char *tx_ring_phys;
        volatile unsigned char *rx_ring;
+       volatile unsigned char *rx_ring_phys;
        int dma_intr;
-       unsigned char maccc;
        struct net_device_stats stats;
-       struct timer_list tx_timeout;
-       int timeout_active;
-       int rx_slot, rx_done;
-       int tx_slot, tx_count;
+       int rx_slot, rx_tail;
+       int tx_slot, tx_sloti, tx_count;
 };
 
-struct mace_frame
-{
+struct mace_frame {
        u16     len;
        u16     status;
        u16     rntpc;
@@ -69,271 +67,226 @@ struct mace_frame
        /* And frame continues.. */
 };
 
-#define PRIV_BYTES     sizeof(struct mace68k_data)
+#define PRIV_BYTES     sizeof(struct mace_data)
 
 extern void psc_debug_dump(void);
 
-static int mace68k_open(struct net_device *dev);
-static int mace68k_close(struct net_device *dev);
-static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *mace68k_stats(struct net_device *dev);
-static void mace68k_set_multicast(struct net_device *dev);
-static void mace68k_reset(struct net_device *dev);
-static int mace68k_set_address(struct net_device *dev, void *addr);
-static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs);
-static void mace68k_set_timeout(struct net_device *dev);
-static void mace68k_tx_timeout(unsigned long data);
+static int mace_open(struct net_device *dev);
+static int mace_close(struct net_device *dev);
+static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *mace_stats(struct net_device *dev);
+static void mace_set_multicast(struct net_device *dev);
+static int mace_set_address(struct net_device *dev, void *addr);
+static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static void mace_tx_timeout(struct net_device *dev);
 
-/*
- *     PSC DMA engine control. As you'd expect on a macintosh its
- *     more like a lawnmower engine supplied without instructions
- *
- *     The basic theory of operation appears to be as follows.
- *
- *     There are two sets of receive DMA registers and two sets
- *     of transmit DMA registers. Instead of the more traditional
- *     "ring buffer" approach the Mac68K DMA engine expects you
- *     to be loading one chain while the other runs, and then
- *     to flip register set. Each entry in the chain is a fixed 
- *     length.
- */
+/* Bit-reverse one byte of an ethernet hardware address. */
+
+static int bitrev(int b)
+{
+       int d = 0, i;
+
+       for (i = 0; i < 8; ++i, b >>= 1) {
+               d = (d << 1) | (b & 1);
+       }
+
+       return d;
+}
 
 /*
- *     Load a receive DMA channel with a base address and ring length
+ * Load a receive DMA channel with a base address and ring length
  */
-  
-static void psc_load_rxdma_base(int set, void *base)
+
+static void mace_load_rxdma_base(struct net_device *dev, int set)
 {
+       struct mace_data *mp = (struct mace_data *) dev->priv;
+
        psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
-       psc_write_long(PSC_ENETRD_ADDR + set, (u32)base);
+       psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys);
        psc_write_long(PSC_ENETRD_LEN + set, N_RX_RING);
        psc_write_word(PSC_ENETRD_CMD + set, 0x9800);
+       mp->rx_tail = 0;
 }
 
 /*
- *     Reset the receive DMA subsystem
+ * Reset the receive DMA subsystem
  */
-  
-static void mace68k_rxdma_reset(struct net_device *dev)
+
+static void mace_rxdma_reset(struct net_device *dev)
 {
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
        volatile struct mace *mace = mp->mace;
-       u8 mcc = mace->maccc;
+       u8 maccc = mace->maccc;
        
-       /*
-        *      Turn off receive
-        */
-        
-       mcc&=~ENRCV;
-       mace->maccc=mcc;
-       
-       /*
-        *      Program the DMA
-        */
+       mace->maccc = maccc & ~ENRCV;
        
        psc_write_word(PSC_ENETRD_CTL, 0x8800);
-       psc_load_rxdma_base(0x0, (void *)virt_to_bus(mp->rx_ring));
+       mace_load_rxdma_base(dev, 0x00);
        psc_write_word(PSC_ENETRD_CTL, 0x0400);
        
        psc_write_word(PSC_ENETRD_CTL, 0x8800);
-       psc_load_rxdma_base(0x10, (void *)virt_to_bus(mp->rx_ring));
+       mace_load_rxdma_base(dev, 0x10);
        psc_write_word(PSC_ENETRD_CTL, 0x0400);
        
-       mace->maccc=mcc|ENRCV;
-       
-#if 0
-       psc_write_word(PSC_ENETRD_CTL, 0x9800);
-       psc_write_word(PSC_ENETRD_CTL+0x10, 0x9800);
-#endif
+       mace->maccc = maccc;
+       mp->rx_slot = 0;
+
+       psc_write_word(PSC_ENETRD_CMD + PSC_SET0, 0x9800);
+       psc_write_word(PSC_ENETRD_CMD + PSC_SET1, 0x9800);
 }
 
 /*
- *     Reset the transmit DMA subsystem
+ * Reset the transmit DMA subsystem
  */
  
-static void mace68k_txdma_reset(struct net_device *dev)
+static void mace_txdma_reset(struct net_device *dev)
 {
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
        volatile struct mace *mace = mp->mace;
-       u8 mcc = mace->maccc;
+       u8 maccc;
 
-       psc_write_word(PSC_ENETWR_CTL,0x8800);
-       
-       mace->maccc = mcc&~ENXMT;
-       psc_write_word(PSC_ENETWR_CTL,0x0400);
-       mace->maccc = mcc;
+       psc_write_word(PSC_ENETWR_CTL, 0x8800);
+
+       maccc = mace->maccc;
+       mace->maccc = maccc & ~ENXMT;
+
+       mp->tx_slot = mp->tx_sloti = 0;
+       mp->tx_count = N_TX_RING;
+
+       psc_write_word(PSC_ENETWR_CTL, 0x0400);
+       mace->maccc = maccc;
 }
 
 /*
- *     Disable DMA
+ * Disable DMA
  */
  
-static void mace68k_dma_off(struct net_device *dev)
+static void mace_dma_off(struct net_device *dev)
 {
        psc_write_word(PSC_ENETRD_CTL, 0x8800);
        psc_write_word(PSC_ENETRD_CTL, 0x1000);
-       psc_write_word(PSC_ENETRD_CMD, 0x1100);
-       psc_write_word(PSC_ENETRD_CMD+0x10, 0x1100);
-                                        
+       psc_write_word(PSC_ENETRD_CMD + PSC_SET0, 0x1100);
+       psc_write_word(PSC_ENETRD_CMD + PSC_SET1, 0x1100);
+
        psc_write_word(PSC_ENETWR_CTL, 0x8800);
        psc_write_word(PSC_ENETWR_CTL, 0x1000);
-       psc_write_word(PSC_ENETWR_CMD, 0x1100);
-       psc_write_word(PSC_ENETWR_CMD+0x10, 0x1100);
-}
-
-/* Bit-reverse one byte of an ethernet hardware address. */
-
-static int bitrev(int b)
-{
-    int d = 0, i;
-
-    for (i = 0; i < 8; ++i, b >>= 1)
-       d = (d << 1) | (b & 1);
-    return d;
+       psc_write_word(PSC_ENETWR_CMD + PSC_SET0, 0x1100);
+       psc_write_word(PSC_ENETWR_CMD + PSC_SET1, 0x1100);
 }
 
 /*
- *     Not really much of a probe. The hardware table tells us if this
- *     model of Macintrash has a MACE (AV macintoshes)
+ * Not really much of a probe. The hardware table tells us if this
+ * model of Macintrash has a MACE (AV macintoshes)
  */
  
-int mace68k_probe(struct net_device *unused)
+int mace_probe(struct net_device *unused)
 {
        int j;
-       static int once;
-       struct mace68k_data *mp;
+       struct mace_data *mp;
        unsigned char *addr;
        struct net_device *dev;
        unsigned char checksum = 0;
+       static int found = 0;
        
-       /*
-        *      There can be only one...
-        */
-        
-       if (once) return -ENODEV;
-       
-       once = 1;
+       if (found || macintosh_config->ether_type != MAC_ETHER_MACE) return -ENODEV;
 
-       if (macintosh_config->ether_type != MAC_ETHER_MACE) return -ENODEV;
+       found = 1;      /* prevent 'finding' one on every device probe */
 
-       printk("MACE ethernet should be present ");
-       
        dev = init_etherdev(0, PRIV_BYTES);
-       if(dev==NULL)
-       {
-               printk("no free memory.\n");
-               return -ENOMEM;
-       }               
-       mp = (struct mace68k_data *) dev->priv;
+       if (!dev) return -ENOMEM;
+
+       mp = (struct mace_data *) dev->priv;
        dev->base_addr = (u32)MACE_BASE;
        mp->mace = (volatile struct mace *) MACE_BASE;
        
-       printk("at 0x%p", mp->mace);
-       
-       /*
-        *      16K RX ring and 4K TX ring should do nicely
-        */
-
-       mp->rx_ring=(void *)__get_free_pages(GFP_KERNEL, 2);
-       mp->tx_ring=(void *)__get_free_page(GFP_KERNEL);
-       
-       printk(".");
-       
-       if(mp->tx_ring==NULL || mp->rx_ring==NULL)
-       {
-               if(mp->tx_ring)
-                       free_page((u32)mp->tx_ring);
-//             if(mp->rx_ring)
-//                     __free_pages(mp->rx_ring,2);
-               printk("\nNo memory for ring buffers.\n");
-               return -ENOMEM;
-       }
-
-       /* We want the receive data to be uncached. We dont care about the
-          byte reading order */
-
-       printk(".");    
-       kernel_set_cachemode((void *)mp->rx_ring, 16384, IOMAP_NOCACHE_NONSER); 
-       
-       printk(".");    
-       /* The transmit buffer needs to be write through */
-       kernel_set_cachemode((void *)mp->tx_ring, 4096, IOMAP_WRITETHROUGH);
-
-       printk(" Ok\n");        
        dev->irq = IRQ_MAC_MACE;
-       printk(KERN_INFO "%s: MACE at", dev->name);
+       mp->dma_intr = IRQ_MAC_MACE_DMA;
 
        /*
-        *      The PROM contains 8 bytes which total 0xFF when XOR'd
-        *      together. Due to the usual peculiar apple brain damage
-        *      the bytes are spaced out in a strange boundary and the
-        *      bits are reversed.
+        * The PROM contains 8 bytes which total 0xFF when XOR'd
+        * together. Due to the usual peculiar apple brain damage
+        * the bytes are spaced out in a strange boundary and the
+        * bits are reversed.
         */
 
        addr = (void *)MACE_PROM;
                 
-       for (j = 0; j < 6; ++j)
-       {
+       for (j = 0; j < 6; ++j) {
                u8 v=bitrev(addr[j<<4]);
-               checksum^=v;
+               checksum ^= v;
                dev->dev_addr[j] = v;
-               printk("%c%.2x", (j ? ':' : ' '), dev->dev_addr[j]);
        }
-       for (; j < 8; ++j)
-       {
-               checksum^=bitrev(addr[j<<4]);
+       for (; j < 8; ++j) {
+               checksum ^= bitrev(addr[j<<4]);
        }
        
-       if(checksum!=0xFF)
-       {
-               printk(" (invalid checksum)\n");
-               return -ENODEV;
-       }               
-       printk("\n");
+       if (checksum != 0xFF) return -ENODEV;
 
        memset(&mp->stats, 0, sizeof(mp->stats));
-       init_timer(&mp->tx_timeout);
-       mp->timeout_active = 0;
 
-       dev->open = mace68k_open;
-       dev->stop = mace68k_close;
-       dev->hard_start_xmit = mace68k_xmit_start;
-       dev->get_stats = mace68k_stats;
-       dev->set_multicast_list = mace68k_set_multicast;
-       dev->set_mac_address = mace68k_set_address;
+       dev->open               = mace_open;
+       dev->stop               = mace_close;
+       dev->hard_start_xmit    = mace_xmit_start;
+       dev->tx_timeout         = mace_tx_timeout;
+       dev->watchdog_timeo     = TX_TIMEOUT;
+       dev->get_stats          = mace_stats;
+       dev->set_multicast_list = mace_set_multicast;
+       dev->set_mac_address    = mace_set_address;
 
        ether_setup(dev);
 
-       mp = (struct mace68k_data *) dev->priv;
-       mp->maccc = ENXMT | ENRCV;
-       mp->dma_intr = IRQ_MAC_MACE_DMA;
+       printk(KERN_INFO "%s: 68K MACE, hardware address %.2X", dev->name, dev->dev_addr[0]);
+       for (j = 1 ; j < 6 ; j++) printk(":%.2X", dev->dev_addr[j]);
+       printk("\n");
 
-       psc_write_word(PSC_ENETWR_CTL, 0x9000);
-       psc_write_word(PSC_ENETRD_CTL, 0x9000);
-       psc_write_word(PSC_ENETWR_CTL, 0x0400);
-       psc_write_word(PSC_ENETRD_CTL, 0x0400);
-                                               
-       /* apple's driver doesn't seem to do this */
-       /* except at driver shutdown time...      */
-#if 0
-       mace68k_dma_off(dev);
-#endif
+       return 0;
+}
+
+/*
+ * Load the address on a mace controller.
+ */
+
+static int mace_set_address(struct net_device *dev, void *addr)
+{
+       unsigned char *p = addr;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
+       volatile struct mace *mb = mp->mace;
+       int i;
+       unsigned long flags;
+       u8 maccc;
+
+       save_flags(flags);
+       cli();
+
+       maccc = mb->maccc;
+
+       /* load up the hardware address */
+       mb->iac = ADDRCHG | PHYADDR;
+       while ((mb->iac & ADDRCHG) != 0);
+       
+       for (i = 0; i < 6; ++i) {
+               mb->padr = dev->dev_addr[i] = p[i];
+       }
+
+       mb->maccc = maccc;
+       restore_flags(flags);
 
        return 0;
 }
 
 /*
- *     Reset a MACE controller
+ * Open the Macintosh MACE. Most of this is playing with the DMA
+ * engine. The ethernet chip is quite friendly.
  */
  
-static void mace68k_reset(struct net_device *dev)
+static int mace_open(struct net_device *dev)
 {
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
        volatile struct mace *mb = mp->mace;
+#if 0
        int i;
 
-       /* soft-reset the chip */
        i = 200;
        while (--i) {
                mb->biucc = SWRST;
@@ -344,18 +297,59 @@ static void mace68k_reset(struct net_device *dev)
                break;
        }
        if (!i) {
-               printk(KERN_ERR "mace: cannot reset chip!\n");
-               return;
+               printk(KERN_ERR "%s: software reset failed!!\n", dev->name);
+               return -EAGAIN;
        }
+#endif
 
        mb->biucc = XMTSP_64;
-       mb->imr = 0xff;         /* disable all intrs for now */
-       i = mb->ir;
-       mb->maccc = 0;          /* turn off tx, rx */
-       mb->utr = RTRD;
-       mb->fifocc = RCVFW_64;
-       mb->xmtfc = AUTO_PAD_XMIT;      /* auto-pad short frames */
+       mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST;
+       mb->xmtfc = AUTO_PAD_XMIT;
+       mb->plscc = PORTSEL_AUI;
+       /* mb->utr = RTRD; */
+
+       if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) {
+               printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq);
+               return -EAGAIN;
+       }
+       if (request_irq(mp->dma_intr, mace_dma_intr, 0, dev->name, dev)) {
+               printk(KERN_ERR "%s: can't get irq %d\n", dev->name, mp->dma_intr);
+               free_irq(dev->irq, dev);
+               return -EAGAIN;
+       }
+
+       /* Allocate the DMA ring buffers */
+
+       mp->rx_ring = (void *) __get_free_pages(GFP_DMA, N_RX_PAGES);
+       mp->tx_ring = (void *) __get_free_pages(GFP_DMA, 0);
+       
+       if (mp->tx_ring==NULL || mp->rx_ring==NULL) {
+               if (mp->rx_ring) free_pages((u32) mp->rx_ring, N_RX_PAGES);
+               if (mp->tx_ring) free_pages((u32) mp->tx_ring, 0);
+               free_irq(dev->irq, dev);
+               free_irq(mp->dma_intr, dev);
+               printk(KERN_ERR "%s: unable to allocate DMA buffers\n", dev->name);
+               return -ENOMEM;
+       }
+
+       mp->rx_ring_phys = (unsigned char *) virt_to_bus(mp->rx_ring);
+       mp->tx_ring_phys = (unsigned char *) virt_to_bus(mp->tx_ring);
+
+       /* We want the Rx buffer to be uncached and the Tx buffer to be writethrough */
+
+       kernel_set_cachemode((void *)mp->rx_ring, N_RX_PAGES * PAGE_SIZE, IOMAP_NOCACHE_NONSER);        
+       kernel_set_cachemode((void *)mp->tx_ring, PAGE_SIZE, IOMAP_WRITETHROUGH);
+
+       mace_dma_off(dev);
+
+       /* Not sure what these do */
+
+       psc_write_word(PSC_ENETWR_CTL, 0x9000);
+       psc_write_word(PSC_ENETRD_CTL, 0x9000);
+       psc_write_word(PSC_ENETWR_CTL, 0x0400);
+       psc_write_word(PSC_ENETRD_CTL, 0x0400);
 
+#if 0
        /* load up the hardware address */
        
        mb->iac = ADDRCHG | PHYADDR;
@@ -374,245 +368,157 @@ static void mace68k_reset(struct net_device *dev)
                mb->ladrf = 0;
 
        mb->plscc = PORTSEL_GPSI + ENPLSIO;
-}
-
-/*
- *     Load the address on a mace controller.
- */
-static int mace68k_set_address(struct net_device *dev, void *addr)
-{
-       unsigned char *p = addr;
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
-       volatile struct mace *mb = mp->mace;
-       int i;
-       unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       mb->maccc = ENXMT | ENRCV;
+       mb->imr = RCVINT;
+#endif
 
-       /* load up the hardware address */
-       mb->iac = ADDRCHG | PHYADDR;
-       while ((mb->iac & ADDRCHG) != 0);
+       mace_rxdma_reset(dev);
+       mace_txdma_reset(dev);
        
-       for (i = 0; i < 6; ++i)
-               mb->padr = dev->dev_addr[i] = p[i];
-       /* note: setting ADDRCHG clears ENRCV */
-       mb->maccc = mp->maccc;
-       restore_flags(flags);
        return 0;
 }
 
 /*
- *     Open the Macintosh MACE. Most of this is playing with the DMA
- *     engine. The ethernet chip is quite friendly.
+ * Shut down the mace and its interrupt channel
  */
  
-static int mace68k_open(struct net_device *dev)
+static int mace_close(struct net_device *dev)
 {
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
        volatile struct mace *mb = mp->mace;
 
-       /* reset the chip */
-       mace68k_reset(dev);
-
-       mp->rx_done = 0;
-       mace68k_rxdma_reset(dev);
+       mb->maccc = 0;          /* disable rx and tx     */
+       mb->imr = 0xFF;         /* disable all irqs      */
+       mace_dma_off(dev);      /* disable rx and tx dma */
 
-       /*
-        *      The interrupt is fixed and comes off the PSC.
-        */
-        
-       if (request_irq(dev->irq, mace68k_interrupt, 0, "68K MACE", dev))
-       {
-               printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
-               return -EAGAIN;
-       }
-
-       /*
-        *      Ditto the DMA interrupt.
-        */
-        
-       if (request_irq(IRQ_MAC_MACE_DMA, mace68k_dma_intr, 0, "68K MACE DMA",
-                       dev))
-       {
-               printk(KERN_ERR "MACE: can't get irq %d\n", IRQ_MAC_MACE_DMA);
-               return -EAGAIN;
-       }
+       free_irq(dev->irq, dev);
+       free_irq(IRQ_MAC_MACE_DMA, dev);
 
-       /* Activate the Mac DMA engine */
+       free_pages((u32) mp->rx_ring, N_RX_PAGES);
+       free_pages((u32) mp->tx_ring, 0);
 
-       mp->tx_slot = 0;                /* Using register set 0 */
-       mp->tx_count = 1;               /* 1 Buffer ready for use */
-       mace68k_txdma_reset(dev);
-       
-       /* turn it on! */
-       mb->maccc = mp->maccc;
-       /* enable all interrupts except receive interrupts */
-       mb->imr = RCVINT;
        return 0;
 }
 
 /*
- *     Shut down the mace and its interrupt channel
+ * Transmit a frame
  */
  
-static int mace68k_close(struct net_device *dev)
+static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
 {
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
-       volatile struct mace *mb = mp->mace;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
 
-       /* disable rx and tx */
-       mb->maccc = 0;
-       mb->imr = 0xff;         /* disable all intrs */
+       /* Stop the queue if the buffer is full */
 
-       /* disable rx and tx dma */
+       if (!mp->tx_count) {
+               netif_stop_queue(dev);
+               return 1;
+       }
+       mp->tx_count--;
+       
+       mp->stats.tx_packets++;
+       mp->stats.tx_bytes += skb->len;
 
-       mace68k_dma_off(dev);
+       /* We need to copy into our xmit buffer to take care of alignment and caching issues */
 
-       free_irq(dev->irq, dev);
-       free_irq(IRQ_MAC_MACE_DMA, dev);
-       return 0;
-}
+       memcpy((void *) mp->tx_ring, skb->data, skb->len);
 
-static inline void mace68k_set_timeout(struct net_device *dev)
-{
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
-       unsigned long flags;
+       /* load the Tx DMA and fire it off */
 
-       save_flags(flags);
-       cli();
-       if (mp->timeout_active)
-               del_timer(&mp->tx_timeout);
-       mp->tx_timeout.expires = jiffies + TX_TIMEOUT;
-       mp->tx_timeout.function = mace68k_tx_timeout;
-       mp->tx_timeout.data = (unsigned long) dev;
-       add_timer(&mp->tx_timeout);
-       mp->timeout_active = 1;
-       restore_flags(flags);
-}
+       psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, (u32)  mp->tx_ring_phys);
+       psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len);
+       psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800);
 
-/*
- *     Transmit a frame
- */
-static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev)
-{
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
-       /*
-        *      This may need atomic types ???
-        */
+       mp->tx_slot ^= 0x10;
 
-       printk("mace68k_xmit_start: mp->tx_count = %d, dev->tbusy = %d, mp->tx_ring = %p (%p)\n",
-               mp->tx_count, dev->tbusy,
-               mp->tx_ring, virt_to_bus(mp->tx_ring));
-       psc_debug_dump();
+       dev_kfree_skb(skb);
 
-       if(mp->tx_count == 0)
-       {
-               dev->tbusy=1;
-               mace68k_dma_intr(IRQ_MAC_MACE_DMA, dev, NULL);
-               return 1;
-       }
-       mp->tx_count--;
-       
-       /*
-        *      FIXME:
-        *      This is hackish. The memcpy probably isnt needed but
-        *      the rules for alignment are not known. Ideally we'd like
-        *      to just blast the skb directly to ethernet. We also don't
-        *      use the ring properly - just a one frame buffer. That
-        *      also requires cache pushes ;).
-        */
-       memcpy((void *)mp->tx_ring, skb, skb->len);
-       psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, virt_to_bus(mp->tx_ring));
-        psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len);
-        psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800);                       
-       mp->stats.tx_packets++;
-       mp->stats.tx_bytes+=skb->len;
-        dev_kfree_skb(skb);
        return 0;
 }
 
-static struct net_device_stats *mace68k_stats(struct net_device *dev)
+static struct net_device_stats *mace_stats(struct net_device *dev)
 {
-       struct mace68k_data *p = (struct mace68k_data *) dev->priv;
+       struct mace_data *p = (struct mace_data *) dev->priv;
        return &p->stats;
 }
 
-static void mace68k_set_multicast(struct net_device *dev)
+static void mace_set_multicast(struct net_device *dev)
 {
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
        volatile struct mace *mb = mp->mace;
-       int i, j, k, b;
+       int i, j;
        u32 crc;
+       u8 maccc;
 
-       mp->maccc &= ~PROM;
-       if (dev->flags & IFF_PROMISC)
-       {
-               mp->maccc |= PROM;
-       } else
-       {
+       maccc = mb->maccc;
+       mb->maccc &= ~PROM;
+
+       if (dev->flags & IFF_PROMISC) {
+               mb->maccc |= PROM;
+       } else {
                unsigned char multicast_filter[8];
                struct dev_mc_list *dmi = dev->mc_list;
 
-               if (dev->flags & IFF_ALLMULTI)
-               {
-                       for (i = 0; i < 8; i++)
-                               multicast_filter[i] = 0xff;
-               } else
-               {
+               if (dev->flags & IFF_ALLMULTI) {
+                       for (i = 0; i < 8; i++) {
+                               multicast_filter[i] = 0xFF;
+                       }
+               } else {
                        for (i = 0; i < 8; i++)
                                multicast_filter[i] = 0;
-                       for (i = 0; i < dev->mc_count; i++)
-                       {
+                       for (i = 0; i < dev->mc_count; i++) {
                                crc = ether_crc_le(6, dmi->dmi_addr);
                                j = crc >> 26;  /* bit number in multicast_filter */
                                multicast_filter[j >> 3] |= 1 << (j & 7);
                                dmi = dmi->next;
                        }
                }
-#if 0
-               printk("Multicast filter :");
-               for (i = 0; i < 8; i++)
-                       printk("%02x ", multicast_filter[i]);
-               printk("\n");
-#endif
 
                mb->iac = ADDRCHG | LOGADDR;
-               while ((mb->iac & ADDRCHG) != 0);
+               while (mb->iac & ADDRCHG);
                
-               for (i = 0; i < 8; ++i)
+               for (i = 0; i < 8; ++i) {
                        mb->ladrf = multicast_filter[i];
+               }
        }
-       /* reset maccc */
-       mb->maccc = mp->maccc;
+
+       mb->maccc = maccc;
 }
 
 /*
- *     Miscellaneous interrupts are handled here. We may end up 
- *     having to bash the chip on the head for bad errors
+ * Miscellaneous interrupts are handled here. We may end up 
+ * having to bash the chip on the head for bad errors
  */
  
-static void mace68k_handle_misc_intrs(struct mace68k_data *mp, int intr)
+static void mace_handle_misc_intrs(struct mace_data *mp, int intr)
 {
        volatile struct mace *mb = mp->mace;
-       static int mace68k_babbles, mace68k_jabbers;
+       static int mace_babbles, mace_jabbers;
 
-       if (intr & MPCO)
+       if (intr & MPCO) {
                mp->stats.rx_missed_errors += 256;
+       }
        mp->stats.rx_missed_errors += mb->mpc;  /* reading clears it */
-       if (intr & RNTPCO)
+
+       if (intr & RNTPCO) {
                mp->stats.rx_length_errors += 256;
+       }
        mp->stats.rx_length_errors += mb->rntpc;        /* reading clears it */
-       if (intr & CERR)
+
+       if (intr & CERR) {
                ++mp->stats.tx_heartbeat_errors;
-       if (intr & BABBLE)
-               if (mace68k_babbles++ < 4)
+       }
+       if (intr & BABBLE) {
+               if (mace_babbles++ < 4) {
                        printk(KERN_DEBUG "mace: babbling transmitter\n");
-       if (intr & JABBER)
-               if (mace68k_jabbers++ < 4)
+               }
+       }
+       if (intr & JABBER) {
+               if (mace_jabbers++ < 4) {
                        printk(KERN_DEBUG "mace: jabbering transceiver\n");
+               }
+       }
 }
 
 /*
@@ -620,191 +526,172 @@ static void mace68k_handle_misc_intrs(struct mace68k_data *mp, int intr)
  *     the DMA completion)
  */
  
-static void mace68k_xmit_error(struct net_device *dev)
+static void mace_xmit_error(struct net_device *dev)
 {
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
        volatile struct mace *mb = mp->mace;
        u8 xmtfs, xmtrc;
        
        xmtfs = mb->xmtfs;
        xmtrc = mb->xmtrc;
        
-       if(xmtfs & XMTSV)
-       {
-               if(xmtfs & UFLO)
-               {
+       if (xmtfs & XMTSV) {
+               if (xmtfs & UFLO) {
                        printk("%s: DMA underrun.\n", dev->name);
                        mp->stats.tx_errors++;
                        mp->stats.tx_fifo_errors++;
-                       mace68k_reset(dev);
+                       mace_txdma_reset(dev);
                }
-               if(xmtfs & RTRY)
+               if (xmtfs & RTRY) {
                        mp->stats.collisions++;
+               }
        }                       
-       mark_bh(NET_BH);
 }
 
 /*
  *     A receive interrupt occurred.
  */
  
-static void mace68k_recv_interrupt(struct net_device *dev)
+static void mace_recv_interrupt(struct net_device *dev)
 {
-//     struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+/*     struct mace_data *mp = (struct mace_data *) dev->priv; */
 //     volatile struct mace *mb = mp->mace;
 }
 
 /*
- *     Process the chip interrupt
+ * Process the chip interrupt
  */
  
-static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev = (struct net_device *) dev_id;
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
        volatile struct mace *mb = mp->mace;
        u8 ir;
        
        ir = mb->ir;
-       mace68k_handle_misc_intrs(mp, ir);
+       mace_handle_misc_intrs(mp, ir);
        
-       if(ir&XMTINT)
-               mace68k_xmit_error(dev);
-       if(ir&RCVINT)
-               mace68k_recv_interrupt(dev);
+       if (ir & XMTINT) {
+               mace_xmit_error(dev);
+       }
+       if (ir & RCVINT) {
+               mace_recv_interrupt(dev);
+       }
 }
 
-static void mace68k_tx_timeout(unsigned long data)
+static void mace_tx_timeout(struct net_device *dev)
 {
-//     struct net_device *dev = (struct net_device *) data;
-//     struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+/*     struct mace_data *mp = (struct mace_data *) dev->priv; */
 //     volatile struct mace *mb = mp->mace;
 }
 
 /*
- *     Handle a newly arrived frame
+ * Handle a newly arrived frame
  */
  
 static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
 {
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
        struct sk_buff *skb;
 
-       if(mf->status&RS_OFLO)
-       {
+       if (mf->status & RS_OFLO) {
                printk("%s: fifo overflow.\n", dev->name);
                mp->stats.rx_errors++;
                mp->stats.rx_fifo_errors++;
        }
-       if(mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR))
+       if (mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR))
                mp->stats.rx_errors++;
                
-       if(mf->status&RS_CLSN)
+       if (mf->status&RS_CLSN) {
                mp->stats.collisions++;
-       if(mf->status&RS_FRAMERR)
+       }
+       if (mf->status&RS_FRAMERR) {
                mp->stats.rx_frame_errors++;
-       if(mf->status&RS_FCSERR)
+       }
+       if (mf->status&RS_FCSERR) {
                mp->stats.rx_crc_errors++;
+       }
                
        skb = dev_alloc_skb(mf->len+2);
-       if(skb==NULL)
-       {
+       if (!skb) {
                mp->stats.rx_dropped++;
                return;
        }
        skb_reserve(skb,2);
        memcpy(skb_put(skb, mf->len), mf->data, mf->len);
        
+       skb->dev = dev;
        skb->protocol = eth_type_trans(skb, dev);
        netif_rx(skb);
        dev->last_rx = jiffies;
        mp->stats.rx_packets++;
-       mp->stats.rx_bytes+=mf->len;
+       mp->stats.rx_bytes += mf->len;
 }
 
 /*
- *     The PSC has passed us a DMA interrupt event.
+ * The PSC has passed us a DMA interrupt event.
  */
  
-static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static void mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev = (struct net_device *) dev_id;
-       struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+       struct mace_data *mp = (struct mace_data *) dev->priv;
+       int left, head;
+       u16 status;
+       u32 baka;
 
-#if 0
-       u32 psc_status;
-       
-       /* It seems this must be allowed to stabilise ?? */
-       
-       while((psc_status=psc_read_long(0x0804))!=psc_read_long(0x0804));
+       /* Not sure what this does */
+
+       while ((baka = psc_read_long(PSC_MYSTERY)) != psc_read_long(PSC_MYSTERY));
+       if (!(baka & 0x60000000)) return;
 
        /*
-        *      Was this an ethernet event ?
+        * Process the read queue
         */
-               
-       if(psc_status&0x60000000)
-       {
-#endif
-               /*
-                *      Process the read queue
-                */
                 
-               u16 psc_status = psc_read_word(PSC_ENETRD_CTL);
+       status = psc_read_word(PSC_ENETRD_CTL);
                
-               printk("mace68k_dma_intr: PSC_ENETRD_CTL = %04X\n", (uint) psc_status);
+       if (status & 0x2000) {
+               mace_rxdma_reset(dev);
+       } else if (status & 0x0100) {
+               psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100);
 
-               if (psc_status & 0x2000) {
-                       mace68k_rxdma_reset(dev);
-                       mp->rx_done = 0;
-               } else if (psc_status & 0x100) {
-                       int left;
-                       
-                       psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100);
-                       left=psc_read_long(PSC_ENETRD_LEN + mp->rx_slot);
-                       /* read packets */      
-                       
-                       while(mp->rx_done < left)
-                       {
-                               struct mace_frame *mf=((struct mace_frame *)
-                                       mp->rx_ring)+mp->rx_done++;
-                               mace_dma_rx_frame(dev, mf);
-                       }
+               left = psc_read_long(PSC_ENETRD_LEN + mp->rx_slot);
+               head = N_RX_RING - left;
+
+               /* Loop through the ring buffer and process new packages */
+
+               while (mp->rx_tail < head) {
+                       mace_dma_rx_frame(dev, (struct mace_frame *) (mp->rx_ring + (mp->rx_tail * 0x0800)));
+                       mp->rx_tail++;
+               }
                        
-                       if(left == 0)   /* Out of DMA room */
-                       {
-                               psc_load_rxdma_base(mp->rx_slot, 
-                                       (void *)virt_to_phys(mp->rx_ring));
-                               mp->rx_slot^=16;
-                               mp->rx_done = 0;
-                       }
-                       else
-                       {
-                               psc_write_word(PSC_ENETRD_CMD+mp->rx_slot,
-                                       0x9800);
-                       }
-                                       
+               /* If we're out of buffers in this ring then switch to */
+               /* the other set, otherwise just reactivate this one.  */
+
+               if (!left) {
+                       mace_load_rxdma_base(dev, mp->rx_slot);
+                       mp->rx_slot ^= 0x10;
+               } else {
+                       psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x9800);
                }
+       }
                
-               /*
-                *      Process the write queue
-                */
-                
-               psc_status = psc_read_word(PSC_ENETWR_CTL);
-               printk("mace68k_dma_intr: PSC_ENETWR_CTL = %04X\n", (uint) psc_status);
-
-               /* apple's driver seems to loop over this until neither */
-               /* condition is true.    - jmt                          */
-
-               if (psc_status & 0x2000) {
-                       mace68k_txdma_reset(dev);
-               } else if (psc_status & 0x0100) {
-                       psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x0100);
-                       mp->tx_slot ^=16;
-                       mp->tx_count++;
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);
-               }
-#if 0
+       /*
+        * Process the write queue
+        */
+
+       status = psc_read_word(PSC_ENETWR_CTL);
+
+       if (status & 0x2000) {
+               mace_txdma_reset(dev);
+       } else if (status & 0x0100) {
+               psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100);
+               mp->tx_sloti ^= 0x10;
+               mp->tx_count++;
+               netif_wake_queue(dev);
        }
-#endif
 }
+
+MODULE_LICENSE("GPL");
index 53270691ea1d0b2343432da0a4c21dbdcd1d2d76..67fa647edfbe5c42cd4fc887dbbf07bf2b47d8f3 100644 (file)
@@ -20,6 +20,9 @@
  *               and duplicating packets. Needs more testing.
  *
  * 99/01/03 MSch: upgraded to version 0.92 of the core driver, fixed.
+ * 
+ * 00/10/31 sammy@oh.verio.com: Updated driver for 2.4 kernels, fixed problems
+ *          on centris.
  */
 
 #include <linux/kernel.h>
@@ -46,6 +49,7 @@
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
+#include <asm/pgalloc.h>
 
 #include <linux/errno.h>
 
 
 #include "sonic.h"
 
+#define SONIC_READ(reg) \
+       nubus_readl(base_addr+(reg))
+#define SONIC_WRITE(reg,val) \
+       nubus_writel((val), base_addr+(reg))
+#define sonic_read(dev, reg) \
+       nubus_readl((dev)->base_addr+(reg))
+#define sonic_write(dev, reg, val) \
+       nubus_writel((val), (dev)->base_addr+(reg))
+
+
 static int sonic_debug;
 static int sonic_version_printed;
 
+static int reg_offset;
+
 extern int macsonic_probe(struct net_device* dev);
 extern int mac_onboard_sonic_probe(struct net_device* dev);
 extern int mac_nubus_sonic_probe(struct net_device* dev);
@@ -95,7 +111,7 @@ enum macsonic_type {
    resource directories */
 #define DAYNA_SONIC_MAC_ADDR   0xffe004
 
-#define SONIC_READ_PROM(addr) readb(prom_addr+addr)
+#define SONIC_READ_PROM(addr) nubus_readb(prom_addr+addr)
 
 int __init macsonic_probe(struct net_device* dev)
 {
@@ -125,36 +141,42 @@ static inline void bit_reverse_addr(unsigned char addr[6])
 
 int __init macsonic_init(struct net_device* dev)
 {
-       struct sonic_local* lp = (struct sonic_local *)dev->priv;
+       struct sonic_local* lp;
        int i;
 
        /* Allocate the entire chunk of memory for the descriptors.
            Note that this cannot cross a 64K boundary. */
        for (i = 0; i < 20; i++) {
                unsigned long desc_base, desc_top;
-               if ((lp->sonic_desc = 
-                    kmalloc(SIZEOF_SONIC_DESC
-                            * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_KERNEL | GFP_DMA)) == NULL) {
+               if((lp = kmalloc(sizeof(struct sonic_local), GFP_KERNEL | GFP_DMA)) == NULL) {
                        printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name);
                        return -ENOMEM;
                }
-               desc_base = (unsigned long) lp->sonic_desc;
-               desc_top = desc_base + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode);
+
+               desc_base = (unsigned long) lp;
+               desc_top = desc_base + sizeof(struct sonic_local);
                if ((desc_top & 0xffff) >= (desc_base & 0xffff))
                        break;
                /* Hmm. try again (FIXME: does this actually work?) */
-               kfree(lp->sonic_desc);
+               kfree(lp);
                printk(KERN_DEBUG
                       "%s: didn't get continguous chunk [%08lx - %08lx], trying again\n",
                       dev->name, desc_base, desc_top);
        }
 
-       if (lp->sonic_desc == NULL) {
+       if (lp == NULL) {
                printk(KERN_ERR "%s: tried 20 times to allocate descriptor buffers, giving up.\n",
                       dev->name);
                return -ENOMEM;
        }                      
 
+       dev->priv = lp;
+
+#if 0
+       /* this code is only here as a curiousity...   mainly, where the 
+          fuck did SONIC_BUS_SCALE come from, and what was it supposed
+          to do?  the normal allocation works great for 32 bit stuffs..  */
+
        /* Now set up the pointers to point to the appropriate places */
        lp->cda = lp->sonic_desc;
        lp->tda = lp->cda + (SIZEOF_SONIC_CDA * SONIC_BUS_SCALE(lp->dma_bitmode));
@@ -163,24 +185,33 @@ int __init macsonic_init(struct net_device* dev)
        lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
                             * SONIC_BUS_SCALE(lp->dma_bitmode));
 
+#endif
+       
+       memset(lp, 0, sizeof(struct sonic_local));
+
+       lp->cda_laddr = (unsigned int)&(lp->cda);
+       lp->tda_laddr = (unsigned int)lp->tda;
+       lp->rra_laddr = (unsigned int)lp->rra;
+       lp->rda_laddr = (unsigned int)lp->rda;
+
        /* FIXME, maybe we should use skbs */
        if ((lp->rba = (char *)
             kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) {
                printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
-               kfree(lp->sonic_desc);
-               lp->sonic_desc = NULL;
                return -ENOMEM;
        }
 
+       lp->rba_laddr = (unsigned int)lp->rba;
+
        {
                int rs, ds;
 
                /* almost always 12*4096, but let's not take chances */
                rs = ((SONIC_NUM_RRS * SONIC_RBSIZE + 4095) / 4096) * 4096;
                /* almost always under a page, but let's not take chances */
-               ds = ((SIZEOF_SONIC_DESC + 4095) / 4096) * 4096;
+               ds = ((sizeof(struct sonic_local) + 4095) / 4096) * 4096;
                kernel_set_cachemode(lp->rba, rs, IOMAP_NOCACHE_SER);
-               kernel_set_cachemode(lp->sonic_desc, ds, IOMAP_NOCACHE_SER);
+               kernel_set_cachemode(lp, ds, IOMAP_NOCACHE_SER);
        }
        
 #if 0
@@ -275,8 +306,8 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
 {
        /* Bwahahaha */
        static int once_is_more_than_enough;
-       struct sonic_local* lp;
        int i;
+       int dma_bitmode;
        
        if (once_is_more_than_enough)
                return -ENODEV;
@@ -333,8 +364,13 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
        if (dev == NULL)
                return -ENOMEM;
 
-       lp = (struct sonic_local*) dev->priv;
-       memset(lp, 0, sizeof(struct sonic_local));
+       if(dev->priv) {
+               printk("%s: warning! sonic entering with priv already allocated!\n",
+                      dev->name);
+               printk("%s: discarding, will attempt to reallocate\n", dev->name);
+               dev->priv = NULL;
+       }
+
        /* Danger!  My arms are flailing wildly!  You *must* set this
            before using sonic_read() */
 
@@ -356,8 +392,11 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
 
        /* The PowerBook's SONIC is 16 bit always. */
        if (macintosh_config->ident == MAC_MODEL_PB520) {
-               lp->reg_offset = 0;
-               lp->dma_bitmode = 0;
+               reg_offset = 0;
+               dma_bitmode = 0;
+       } else if (macintosh_config->ident == MAC_MODEL_C610) {
+               reg_offset = 0;
+               dma_bitmode = 1;
        } else {
                /* Some of the comm-slot cards are 16 bit.  But some
                    of them are not.  The 32-bit cards use offset 2 and
@@ -368,27 +407,41 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
 
                /* Technically this is not necessary since we zeroed
                    it above */
-               lp->reg_offset = 0;
-               lp->dma_bitmode = 0;
+               reg_offset = 0;
+               dma_bitmode = 0;
                sr = sonic_read(dev, SONIC_SR);
                if (sr == 0 || sr == 0xffff) {
-                       lp->reg_offset = 2;
+                       reg_offset = 2;
                        /* 83932 is 0x0004, 83934 is 0x0100 or 0x0101 */
                        sr = sonic_read(dev, SONIC_SR);
-                       lp->dma_bitmode = 1;
+                       dma_bitmode = 1;
                        
                }
                printk(KERN_INFO
                       "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
-                      dev->name, sr, lp->dma_bitmode?32:16, lp->reg_offset);
+                      dev->name, sr, dma_bitmode?32:16, reg_offset);
        }
+       
 
+       /* this carries my sincere apologies -- by the time I got to updating
+          the driver, support for "reg_offsets" appeares nowhere in the sonic
+          code, going back for over a year.  Fortunately, my Mac does't seem
+          to use whatever this was.
 
+          If you know how this is supposed to be implemented, either fix it,
+          or contact me (sammy@oh.verio.com) to explain what it is. --Sam */
+          
+       if(reg_offset) {
+               printk("%s: register offset unsupported.  please fix this if you know what it is.\n", dev->name);
+               return -ENODEV;
+       }
+       
        /* Software reset, then initialize control registers. */
        sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
        sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS |
                    SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS |
-                   (lp->dma_bitmode ? SONIC_DCR_DW : 0));
+                   (dma_bitmode ? SONIC_DCR_DW : 0));
+
        /* This *must* be written back to in order to restore the
            extended programmable output bits */
        sonic_write(dev, SONIC_DCR2, 0);
@@ -452,7 +505,7 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
        u16 sonic_dcr;
        int id;
        int i;
-       int reg_offset, dma_bitmode;
+       int dma_bitmode;
 
        /* Find the first SONIC that hasn't been initialized already */
        while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
@@ -538,8 +591,6 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
        memset(lp, 0, sizeof(struct sonic_local));
        /* Danger!  My arms are flailing wildly!  You *must* set this
            before using sonic_read() */
-       lp->reg_offset = reg_offset;
-       lp->dma_bitmode = dma_bitmode;
        dev->base_addr = base_addr;
        dev->irq = SLOT2IRQ(ndev->board->slot);
 
@@ -552,6 +603,11 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
        printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
               dev->name, sonic_read(dev, SONIC_SR), dma_bitmode?32:16, reg_offset);
 
+       if(reg_offset) {
+               printk("%s: register offset unsupported.  please fix this if you know what it is.\n", dev->name);
+               return -ENODEV;
+       }
+
        /* Software reset, then initialize control registers. */
        sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
        sonic_write(dev, SONIC_DCR, sonic_dcr
@@ -615,6 +671,9 @@ cleanup_module(void)
 #define sonic_chiptomem(bat) (bat)
 #define PHYSADDR(quux) (quux)
 
+#define sonic_request_irq       request_irq
+#define sonic_free_irq          free_irq
+
 #include "sonic.c"
 
 /*
index 73191126b681a696282def4aa19fe28243dc9fc5..d0a80cbc0e73d3d6222904e048c39d3f4629bd19 100644 (file)
@@ -87,6 +87,7 @@
 #define SONIC_FAET              0x2d
 #define SONIC_MPT               0x2e
 
+#define SONIC_DCR2              0x3f
 
 /*
  * SONIC command bits