Resent-Date: Fri, 8 Jan 1999 08:01:14 +0100 (MET)
Sender: schmitz@lbl.gov
Date: Thu, 07 Jan 1999 23:01:11 -0800
From: Michael Schmitz <MSchmitz@lbl.gov>
Organization: Tinoco Lab, UC Berkekely / Lawrence Berkeley Laboratory
To: Jes Sorensen <Jes.Sorensen@cern.ch>
CC: Thomas Bogendoerfer <tsbogend@alpha.franken.de>,
        linux-m68k@lists.linux-m68k.org
Subject: Re: 2.2.0pre4
References: <199901051142.MAA04541@valhall.cern.ch> <m0zxaNm-000lUEC@schmitzm.hip.berkeley.edu> <19990107010913.B3871@alpha.franken.de> <369408ED.FFA76EC@lbl.gov> <d34sq3mqum.fsf@valhall.cern.ch>
Resent-From: linux-m68k@phil.uni-sb.de

This is a multi-part message in MIME format.
--------------28E0BC49A93D2D9229D6DF71
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Jes Sorensen wrote:
> Ok, I'll apply it then - complaints from Linus goes to your private
> mailbox ;-)
> 
> Michael can you send me an uptodate patch relative to 2.2.0pre4.

Attached to this e-mail. Hope netscrap doesn't mess up this time ...

	Michael
--------------28E0BC49A93D2D9229D6DF71
Content-Type: application/octet-stream; name="mac-2.2.pre4-sonic"
Content-Transfer-Encoding: x-uuencode
Content-Disposition: attachment; filename="mac-2.2.pre4-sonic"

--- linux-2.2.0pre4/drivers/net/sonic.h.org	Thu Jul 17 08:45:23 1997
+++ linux-2.2.0pre4/drivers/net/sonic.h	Thu Jan  7 20:57:47 1999
@@ -9,22 +9,15 @@
  * and pad structure members must be exchanged. Also, the structures
  * need to be changed accordingly to the bus size. 
  *
+ * 981229 MSch:	did just that for the 68k Mac port (32 bit, big endian),
+ *		see CONFIG_MACSONIC branch below.
+ *
  */
 
 #ifndef SONIC_H
 #define SONIC_H
 
 /*
- * Macros to access SONIC registers
- */
-#define SONIC_READ(reg) \
-	*((volatile unsigned int *)base_addr+reg)
-
-#define SONIC_WRITE(reg,val) \
-	*((volatile unsigned int *)base_addr+reg) = val
-
-
-/*
  * SONIC register offsets
  */
  
@@ -223,6 +216,108 @@
 #define	SONIC_END_OF_LINKS	0x0001
 
 
+#ifdef CONFIG_MACSONIC
+/* Big endian like structures on Mac
+ * (680x0)
+ */
+
+typedef struct {
+  u32 rx_bufadr_l;	/* receive buffer ptr */
+  u32 rx_bufadr_h;
+
+  u32 rx_bufsize_l;	/* no. of words in the receive buffer */
+  u32 rx_bufsize_h;
+} sonic_rr_t;
+
+/*
+ * Sonic receive descriptor. Receive descriptors are
+ * kept in a linked list of these structures.
+ */
+
+typedef struct {
+  SREGS_PAD(pad0);
+  u16 rx_status;	/* status after reception of a packet */
+  SREGS_PAD(pad1);
+  u16 rx_pktlen;	/* length of the packet incl. CRC */
+  
+  /*
+   * Pointers to the location in the receive buffer area (RBA)
+   * where the packet resides. A packet is always received into
+   * a contiguous piece of memory.
+   */
+  SREGS_PAD(pad2);
+  u16 rx_pktptr_l;
+  SREGS_PAD(pad3);
+  u16 rx_pktptr_h;
+
+  SREGS_PAD(pad4);
+  u16 rx_seqno;	/* sequence no. */
+
+  SREGS_PAD(pad5);
+  u16 link;		/* link to next RDD (end if EOL bit set) */
+
+  /*
+   * Owner of this descriptor, 0= driver, 1=sonic
+   */
+  
+  SREGS_PAD(pad6);
+  u16 in_use;	
+
+  caddr_t rda_next;		/* pointer to next RD */
+} sonic_rd_t;
+
+
+/*
+ * Describes a Transmit Descriptor
+ */
+typedef struct {
+  SREGS_PAD(pad0);		
+  u16 tx_status;	/* status after transmission of a packet */
+  SREGS_PAD(pad1);		
+  u16 tx_config;	/* transmit configuration for this packet */
+  SREGS_PAD(pad2);		
+  u16 tx_pktsize;	/* size of the packet to be transmitted */
+  SREGS_PAD(pad3);		
+  u16 tx_frag_count;	/* no. of fragments */
+
+  SREGS_PAD(pad4);		
+  u16 tx_frag_ptr_l;
+  SREGS_PAD(pad5);		
+  u16 tx_frag_ptr_h;
+  SREGS_PAD(pad6);		
+  u16 tx_frag_size;
+  
+  SREGS_PAD(pad7);		
+  u16 link;		/* ptr to next descriptor */
+} sonic_td_t;
+
+
+/*
+ * Describes an entry in the CAM Descriptor Area.
+ */
+
+typedef struct {
+  SREGS_PAD(pad0);
+  u16 cam_entry_pointer;
+  SREGS_PAD(pad1);
+  u16 cam_cap0;
+  SREGS_PAD(pad2);
+  u16 cam_cap1;
+  SREGS_PAD(pad3);
+  u16 cam_cap2;
+} sonic_cd_t;
+
+#define CAM_DESCRIPTORS 16
+
+
+typedef struct {
+  sonic_cd_t cam_desc[CAM_DESCRIPTORS];
+  SREGS_PAD(pad);
+  u16 cam_enable;
+} sonic_cda_t;
+
+#else /* original declarations, little endian 32 bit */
+
 /*
  * structure definitions
  */
@@ -242,9 +337,9 @@
 
 typedef struct {
   u16 rx_status;	/* status after reception of a packet */
-  u16 pad0;
+  SREGS_PAD(pad0);
   u16 rx_pktlen;	/* length of the packet incl. CRC */
-  u16 pad1;
+  SREGS_PAD(pad1);
   
   /*
    * Pointers to the location in the receive buffer area (RBA)
@@ -252,22 +347,22 @@
    * a contiguous piece of memory.
    */
   u16 rx_pktptr_l;
-  u16 pad2;
+  SREGS_PAD(pad2);
   u16 rx_pktptr_h;
-  u16 pad3;
+  SREGS_PAD(pad3);
 
   u16 rx_seqno;	/* sequence no. */
-  u16 pad4;
+  SREGS_PAD(pad4);
 
   u16 link;		/* link to next RDD (end if EOL bit set) */
-  u16 pad5;
+  SREGS_PAD(pad5);
 
   /*
    * Owner of this descriptor, 0= driver, 1=sonic
    */
   
   u16 in_use;	
-  u16 pad6;
+  SREGS_PAD(pad6);
 
   caddr_t rda_next;		/* pointer to next RD */
 } sonic_rd_t;
@@ -278,23 +373,23 @@
  */
 typedef struct {
   u16 tx_status;	/* status after transmission of a packet */
-  u16 pad0;		
+  SREGS_PAD(pad0);
   u16 tx_config;	/* transmit configuration for this packet */
-  u16 pad1;		
+  SREGS_PAD(pad1);
   u16 tx_pktsize;	/* size of the packet to be transmitted */
-  u16 pad2;		
+  SREGS_PAD(pad2);
   u16 tx_frag_count;	/* no. of fragments */
-  u16 pad3;		
+  SREGS_PAD(pad3);
 
   u16 tx_frag_ptr_l;
-  u16 pad4;		
+  SREGS_PAD(pad4);
   u16 tx_frag_ptr_h;
-  u16 pad5;		
+  SREGS_PAD(pad5);
   u16 tx_frag_size;
-  u16 pad6;		
+  SREGS_PAD(pad6);
   
   u16 link;		/* ptr to next descriptor */
-  u16 pad7;		
+  SREGS_PAD(pad7);
 } sonic_td_t;
 
 
@@ -304,13 +399,13 @@
 
 typedef struct {
   u16 cam_entry_pointer;
-  u16 pad;
-  u16 cam_frag2;
-  u16 pad2;
-  u16 cam_frag1;
-  u16 pad1;
-  u16 cam_frag0;
-  u16 pad0;
+  SREGS_PAD(pad0);
+  u16 cam_cap0;
+  SREGS_PAD(pad1);
+  u16 cam_cap1;
+  SREGS_PAD(pad2);
+  u16 cam_cap2;
+  SREGS_PAD(pad3);
 } sonic_cd_t;
 
 #define CAM_DESCRIPTORS 16
@@ -319,8 +414,65 @@
 typedef struct {
   sonic_cd_t cam_desc[CAM_DESCRIPTORS];
   u16 cam_enable;
-  u16 pad;
+  SREGS_PAD(pad);
 } sonic_cda_t;
+#endif	/* endianness */ 
+
+/*
+ * Some tunables for the buffer areas. Power of 2 is required
+ * the current driver uses one receive buffer for each descriptor.
+ *
+ * MSch: use more buffer space for the slow m68k Macs!
+ */
+#ifdef CONFIG_MACSONIC
+#define SONIC_NUM_RRS    32             /* number of receive resources */
+#define SONIC_NUM_RDS    SONIC_NUM_RRS  /* number of receive descriptors */
+#define SONIC_NUM_TDS    32      /* number of transmit descriptors */
+#else
+#define SONIC_NUM_RRS    16             /* number of receive resources */
+#define SONIC_NUM_RDS    SONIC_NUM_RRS  /* number of receive descriptors */
+#define SONIC_NUM_TDS    16      /* number of transmit descriptors */
+#endif
+#define SONIC_RBSIZE   1520      /* size of one resource buffer */
+
+#define SONIC_RDS_MASK   (SONIC_NUM_RDS-1)
+#define SONIC_TDS_MASK   (SONIC_NUM_TDS-1)
+
+
+/* Information that need to be kept for each board. */
+struct sonic_local {
+    sonic_cda_t   cda;                     /* virtual CPU address of CDA */
+    sonic_td_t    tda[SONIC_NUM_TDS];      /* transmit descriptor area */
+    sonic_rr_t    rra[SONIC_NUM_RRS];      /* receive resource arrea */
+    sonic_rd_t    rda[SONIC_NUM_RDS];      /* receive descriptor area */
+    struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */
+    unsigned int  tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */
+    unsigned char *rba;                    /* start of receive buffer areas */    
+    unsigned int  cda_laddr;               /* logical DMA address of CDA */    
+    unsigned int  tda_laddr;               /* logical DMA address of TDA */
+    unsigned int  rra_laddr;               /* logical DMA address of RRA */    
+    unsigned int  rda_laddr;               /* logical DMA address of RDA */
+    unsigned int  rba_laddr;               /* logical DMA address of RBA */
+    unsigned int  cur_rra;                 /* current indexes to resource areas */
+    unsigned int  cur_rx;
+    unsigned int  cur_tx;
+    unsigned int  dirty_tx;                /* last unacked transmit packet */
+    char tx_full;
+    struct enet_statistics stats;
+};
+
+/* Index to functions, as function prototypes. */
+
+static int sonic_open(struct device *dev);
+static int sonic_send_packet(struct sk_buff *skb, struct device *dev);
+static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void sonic_rx(struct device *dev);
+static int sonic_close(struct device *dev);
+static struct enet_statistics *sonic_get_stats(struct device *dev);
+static void sonic_multicast_list(struct device *dev);
+static int sonic_init(struct device *dev);
 
+static const char *version =
+	"sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n";
 
 #endif /* SONIC_H */
--- linux-2.2.0pre4/drivers/net/Makefile.org	Mon Jan  4 07:15:31 1999
+++ linux-2.2.0pre4/drivers/net/Makefile	Thu Jan  7 20:53:46 1999
@@ -868,10 +868,10 @@
 endif
 
 ifeq ($(CONFIG_MIPS_JAZZ_SONIC),y)
-L_OBJS += sonic.o
+L_OBJS += jazzsonic.o
 else
   ifeq ($(CONFIG_MIPS_JAZZ_SONIC),m)
-    M_OBJS += sonic.o
+    M_OBJS += jazzsonic.o
   endif
 endif
 
@@ -989,6 +989,10 @@
 
 ifeq ($(CONFIG_MACE),y)
 L_OBJS += mace.o
+endif
+
+ifeq ($(CONFIG_MACSONIC),y)
+L_OBJS += macsonic.o
 endif
 
 ifeq ($(CONFIG_BMAC),y)
--- linux-2.2.0pre4/drivers/net/Space.c.org	Mon Jan  4 03:30:42 1999
+++ linux-2.2.0pre4/drivers/net/Space.c	Thu Jan  7 20:56:01 1999
@@ -113,6 +113,7 @@
 extern int tc515_probe(struct device *dev);
 extern int lance_probe(struct device *dev);
 extern int rcpci_probe(struct device *);
+extern int mac_onboard_sonic_probe(struct device *dev);
 
 /* Gigabit Ethernet adapters */
 extern int yellowfin_probe(struct device *dev);
@@ -411,6 +412,9 @@
 #endif
 #ifdef CONFIG_HPLANCE		/* HP300 internal Ethernet */
 	{hplance_probe, 0},
+#endif
+#ifdef CONFIG_MACSONIC		/* Mac 68k Quadra builtin Ethernet */ 
+	{mac_onboard_sonic_probe, 0},
 #endif
 	{NULL, 0},
 };
--- linux-2.2.0pre4/drivers/net/macsonic.c.org	Thu Jan  7 20:53:46 1999
+++ linux-2.2.0pre4/drivers/net/macsonic.c	Thu Jan  7 21:16:09 1999
@@ -0,0 +1,485 @@
+/*
+ * macsonic.c
+ *
+ * (C) 1998 Alan Cox
+ *
+ * Debugging Andreas Ehliar, Michael Schmitz
+ *
+ * Based on code
+ * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de)
+ * 
+ * This driver is based on work from Andreas Busse, but most of
+ * the code is rewritten.
+ * 
+ * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
+ *
+ * A driver for the Mac onboard Sonic ethernet chip.
+ *
+ * 98/12/21 MSch: judged from tests on Q800, it's basically working, 
+ *		  but eating up both receive and transmit resources
+ *		  and duplicating packets. Needs more testing.
+ *
+ * 99/01/03 MSch: upgraded to version 0.92 of the core driver, fixed.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/nubus.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/macintosh.h>
+
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <config/macsonic.h>
+
+#define SREGS_PAD(n)    u16 n;
+
+#include "sonic.h"
+
+extern int mac_onboard_sonic_probe(void);
+
+static int setup_debug = -1;
+static int setup_offset = -1;
+static int setup_shift = -1;
+
+/*
+ * This seems to be the right default for the Q800
+ */
+
+static int reg_offset = 0;
+static int reg_shift = 0;
+
+/*
+ * Macros to access SONIC registers
+ */
+ 
+#define MAC_SONIC_REGISTERS	0x50F0A000
+#define MAC_SONIC_PROM_BASE	0x50f08000
+#define MAC_SONIC_IRQ		9	/* Nubus 9 */
+
+/*
+ *    FIXME: We may need to invert the byte ordering. These should
+ *      be ok for other aspects as they are uncached spaces.
+ *      The original macros from jazzsonic.c works for me
+ *      on my LC 630, YMMV /Andreas Ehliar
+ */
+
+#if 0
+#define SONIC_READ(reg) \
+	*((volatile unsigned int *)base_addr+((reg)<<2)+2)
+
+#define SONIC_WRITE(reg,val) \
+	*((volatile unsigned int *)base_addr+((reg)<<2)+2) = val
+#else
+#define SONIC_READ(reg) \
+	*((volatile unsigned int *)base_addr+reg)
+
+#define SONIC_WRITE(reg,val) \
+	*((volatile unsigned int *)base_addr+reg) = val
+#endif
+
+#define SONIC_READ_PROM(addr) \
+	*((volatile unsigned char *)prom_addr+addr)
+/*
+ * Function : mac_sonic_setup(char *str, int *ints)
+ *
+ * Purpose : booter command line initialization of the overrides array,
+ *
+ * Inputs : str - unused, ints - array of integer parameters with ints[0]
+ *	equal to the number of ints.
+ *
+ * Currently unused in the new driver; need to add settable parameters to the 
+ * detect function.
+ *
+ */
+
+void mac_sonic_setup(char *str, int *ints) {
+	/* Format of macsonic parameter is:
+	 *   macsonic=<debug>,<offset>,<shift>
+	 * Negative values mean don't change.
+	 */
+	
+	/* Grmbl... the standard parameter parsing can't handle negative numbers
+	 * :-( So let's do it ourselves!
+	 */
+
+	int i = ints[0]+1, fact;
+
+	while( str && (isdigit(*str) || *str == '-') && i <= 10) {
+		if (*str == '-')
+			fact = -1, ++str;
+		else
+			fact = 1;
+		ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
+		if ((str = strchr( str, ',' )) != NULL)
+			++str;
+	}
+	ints[0] = i-1;
+	
+	if (ints[0] < 1) {
+		printk( "mac_sonic_setup: no arguments!\n" );
+		return;
+	}
+
+	if (ints[0] >= 1) {
+	       	/* 0 <= n <= 2 */
+		if (ints[1] >= 0 && ints[1] <= 8)
+			setup_debug = ints[1];
+		else if (ints[1] > 16)
+			printk( "mac_sonic_setup: invalid debug level %d !\n", ints[1] );
+	}
+	if (ints[0] >= 2) {
+	       	/* 0 <= n <= 2 */
+		if (ints[2] >= 0 && ints[2] <= 16)
+			setup_offset = ints[2];
+		else if (ints[2] > 16)
+			printk( "mac_sonic_setup: invalid offset %d !\n", ints[2] );
+	}
+	if (ints[0] >= 3) {
+	       	/* 0 <= n <= 2 */
+		if (ints[3] >= 0 && ints[3] <= 16)
+			setup_shift = ints[3];
+		else if (ints[3] > 16)
+			printk( "mac_sonic_setup: invalid shift %d !\n", ints[3] );
+	}
+}
+
+static int sonic_debug = 0;
+
+/*
+ * For reversing the PROM address
+ */
+
+static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14,
+				    1, 9, 5, 13, 3, 11, 7, 15};
+
+__initfunc(int mac_onboard_sonic_probe(void))
+{
+	struct device *dev;
+	unsigned int silicon_revision;
+	unsigned int val;
+	struct sonic_local *lp;
+	int i;
+	int base_addr = MAC_SONIC_REGISTERS;
+	int prom_addr = MAC_SONIC_PROM_BASE;
+	static int one=0;
+	
+	if (!MACH_IS_MAC)
+		return -ENODEV;
+
+	if(++one!=1)	/* Only one is allowed */
+		return -ENODEV;
+
+	printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
+
+	if (macintosh_config->ether_type != MAC_ETHER_SONIC)
+	{
+		printk("none.\n");
+		return -ENODEV;
+	}
+	
+	printk("yes\n");
+	
+	if (setup_debug >= 0)
+	  sonic_debug = setup_debug;
+
+	/*
+	 * This may depend on the actual Mac model ... works for me.
+	 */
+	reg_offset = 
+	  (setup_offset >= 0) ? setup_offset : 0;
+	reg_shift = 
+	  (setup_shift >= 0) ? setup_shift : 0;
+
+	/*
+	 * get the Silicon Revision ID. If this is one of the known
+	 * one assume that we found a SONIC ethernet controller at
+	 * the expected location.
+	 * (This is not implemented in the Macintosh driver yet; need
+	 * to collect values from various sources. Mine is 0x4 ...)
+	 */
+
+	silicon_revision = SONIC_READ(SONIC_SR);
+	if (sonic_debug > 1)
+		printk("SONIC Silicon Revision = 0x%04x\n", silicon_revision);
+
+	/*
+	 * We need to allocate sonic_local later on, making sure it's
+	 * aligned on a 64k boundary. So, no space for dev->priv allocated
+	 * here ...
+	 */
+	dev = init_etherdev(0,0);
+	
+	if(dev==NULL)
+		return -ENOMEM;
+
+	printk("%s: %s found at 0x%08x, ",
+	       dev->name, "SONIC ethernet", base_addr);
+
+	if (sonic_debug > 1)
+		printk("using offset %d shift %d,", reg_offset, reg_shift);
+
+	/* Fill in the 'dev' fields. */
+	dev->base_addr = base_addr;
+	dev->irq = MAC_SONIC_IRQ;
+
+	/*
+	 * Put the sonic into software reset, then
+	 * retrieve and print the ethernet address.
+	 */
+
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+
+	/*
+	 *        We can't trust MacOS to initialise things it seems.
+	 */
+
+	if (sonic_debug > 1)
+		printk("SONIC_DCR was %X\n",SONIC_READ(SONIC_DCR));
+	
+	SONIC_WRITE(SONIC_DCR,
+		    SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS | SONIC_DCR_DW);
+
+	/*
+	 *  We don't want floating spare IRQ's around, not on
+	 *  level triggered systems!
+	 *  Strange though - writing to the ISR only clears currently
+	 *  pending IRQs, but doesn't disable them... Does this make 
+	 *  a difference?? Seems it does ...
+	 */
+#if 1
+	SONIC_WRITE(SONIC_ISR,0x7fff);
+	SONIC_WRITE(SONIC_IMR,0);
+#else
+	SONIC_WRITE(SONIC_ISR, SONIC_IMR_DEFAULT);
+#endif
+	
+	/* This is how it is done in jazzsonic.c
+	 * It doesn't seem to work here though.
+	 */
+	if (sonic_debug > 2) {
+		printk("Retreiving CAM entry 0. This should be the HW address.\n");
+		
+		SONIC_WRITE(SONIC_CEP, 0);
+		for (i = 0; i < 3; i++)
+		{
+			val = SONIC_READ(SONIC_CAP0 - i);
+			dev->dev_addr[i * 2] = val;
+			dev->dev_addr[i * 2 + 1] = val >> 8;
+		}
+
+		printk("HW Address from CAM 0: ");
+		for (i = 0; i < 6; i++)
+		{
+			printk("%2.2x", dev->dev_addr[i]);
+			if (i < 5)
+				printk(":");
+		}
+		printk("\n");
+
+		printk("Retreiving CAM entry 15. Another candidate...\n");
+
+		/*
+		 * MacOS seems to use CAM entry 15 ...
+		 */
+	       	SONIC_WRITE(SONIC_CEP, 15);
+		for (i = 0; i < 3; i++)
+		{
+			val = SONIC_READ(SONIC_CAP0 - i);
+			dev->dev_addr[i * 2] = val;
+			dev->dev_addr[i * 2 + 1] = val >> 8;
+		}
+
+		printk("HW Address from CAM 15: ");
+		for (i = 0; i < 6; i++)
+		{
+			printk("%2.2x", dev->dev_addr[i]);
+			if (i < 5)
+				printk(":");
+		}
+		printk("\n");
+	}
+
+	/*
+	 * if we can read the PROM, we're safe :-)
+	 */
+	if (sonic_debug > 1)
+		printk("Retreiving HW address from the PROM: ");
+
+	for(i=0;i<6;i++){
+                dev->dev_addr[i]=SONIC_READ_PROM(i);
+        }                             
+	if (sonic_debug > 1) {
+	        for (i = 0; i < 6; i++)
+		{
+			printk("%2.2x", dev->dev_addr[i]);
+			if (i <	5)
+				printk(":");
+		}
+		printk("\n");
+	}
+	/*
+	 *                If its not one of these we have
+	 *          screwed up on this Mac model
+	 */
+
+	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+	{
+		/*
+		 * Try bit reversed
+		 */
+		for(i=0;i<6;i++){
+			val = SONIC_READ_PROM(i);
+			dev->dev_addr[i]=(nibbletab[val & 0xf] << 4) | 
+					  nibbletab[(val >> 4) &0xf];
+		}
+		if (sonic_debug > 1) {
+			printk("Trying bit reversed:  ");
+			for (i = 0; i < 6; i++)
+			{
+				printk("%2.2x", dev->dev_addr[i]);
+				if (i < 5)
+					printk(":");
+			}
+			printk("\n");
+		}
+		if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+		    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+		    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+		{
+		        /*
+			 * Still nonsense ... messed up someplace!
+			 */
+			printk("ERROR (INVALID MAC)\n");
+			return -EIO;
+		}
+	}
+
+	printk(" MAC ");
+	for (i = 0; i < 6; i++)
+	{
+		printk("%2.2x", dev->dev_addr[i]);
+		if (i < 5)
+			printk(":");
+	}
+
+	printk(" IRQ %d\n", MAC_SONIC_IRQ);
+
+	/* Initialize the device structure. */
+	if (dev->priv == NULL)
+	{
+		if (sonic_debug > 2) {
+			printk("Allocating memory for dev->priv aka lp\n");
+			printk("Memory to allocate: %d\n",sizeof(*lp));
+		}
+		/*
+		 * the memory be located in the same 64kb segment
+		 */
+		lp = NULL;
+		i = 0;
+		do
+		{
+			lp = (struct sonic_local *) kmalloc(sizeof(*lp), GFP_KERNEL);
+			if ((unsigned long) lp >> 16 != ((unsigned long) lp + sizeof(*lp)) >> 16)
+			{
+				/* FIXME, free the memory later */
+				kfree(lp);
+				lp = NULL;
+			}
+		}
+		while (lp == NULL && i++ < 20);
+
+		if (lp == NULL)
+		{
+			printk("%s: couldn't allocate memory for descriptors\n",
+			       dev->name);
+			return -ENOMEM;
+		}
+
+		if (sonic_debug > 2) {
+			printk("Memory allocated after %d tries\n",i);
+		}
+
+		/* XXX sonic_local has the TDA, RRA, RDA, don't cache */
+		kernel_set_cachemode((u32)lp, 8192, KERNELMAP_NOCACHE_SER);
+		memset(lp, 0, sizeof(struct sonic_local));
+
+		lp->cda_laddr = (u32)lp;
+		if (sonic_debug > 2) {
+			printk("memory allocated for sonic at 0x%x\n",lp);
+		}
+		lp->tda_laddr = lp->cda_laddr + sizeof(lp->cda);
+		lp->rra_laddr = lp->tda_laddr + sizeof(lp->tda);
+		lp->rda_laddr = lp->rra_laddr + sizeof(lp->rra);
+
+		/* allocate receive buffer area */
+		/* FIXME, maybe we should use skbs */
+		if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL)
+		{
+			printk("%s: couldn't allocate receive buffers\n", dev->name);
+			return -ENOMEM;
+		}
+		/* XXX RBA written by Sonic, not cached either */
+		kernel_set_cachemode((u32)lp->rba, 6*8192, KERNELMAP_NOCACHE_SER);
+		lp->rba_laddr = (u32)lp->rba;
+		flush_cache_all();
+		dev->priv = (struct sonic_local *) lp;
+	}
+	lp = (struct sonic_local *) dev->priv;
+	dev->open = sonic_open;
+	dev->stop = sonic_close;
+	dev->hard_start_xmit = sonic_send_packet;
+	dev->get_stats = sonic_get_stats;
+	dev->set_multicast_list = &sonic_multicast_list;
+
+	/* Fill in the fields of the device structure with ethernet values. */
+	ether_setup(dev);
+	return 0;
+}
+
+/*
+ *    SONIC uses a nubus IRQ
+ */
+
+#define sonic_request_irq(irq, vec, flags, name, dev) \
+		nubus_request_irq(irq, dev, vec)
+#define sonic_free_irq(irq,id)	nubus_free_irq(irq)
+
+/*
+ *    No funnies on memory mapping.
+ */
+
+#define sonic_chiptomem(x)	(x)
+
+/*
+ *    No VDMA on a Macintosh. So we need request no such facility.
+ */
+
+#define vdma_alloc(x,y)		((u32)(x))
+#define vdma_free(x)
+#define PHYSADDR(x)		(x)
+
+#include "sonic.c"
--- linux-2.2.0pre4/drivers/net/jazzsonic.c.org	Thu Jan  7 20:53:46 1999
+++ linux-2.2.0pre4/drivers/net/jazzsonic.c	Thu Jan  7 20:59:05 1999
@@ -0,0 +1,266 @@
+/*
+ * jazzsonic.c
+ *
+ * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * 
+ * This driver is based on work from Andreas Busse, but most of
+ * the code is rewritten.
+ * 
+ * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
+ *
+ * A driver for the onboard Sonic ethernet controller on Mips Jazz
+ * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and
+ * perhaps others, too)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#define SREGS_PAD(n)    u16 n;
+
+#include "sonic.h"
+
+/*
+ * Macros to access SONIC registers
+ */
+#define SONIC_READ(reg) \
+	*((volatile unsigned int *)base_addr+reg)
+
+#define SONIC_WRITE(reg,val) \
+	*((volatile unsigned int *)base_addr+reg) = val
+
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifdef SONIC_DEBUG
+static unsigned int sonic_debug = SONIC_DEBUG;
+#else 
+static unsigned int sonic_debug = 1;
+#endif
+
+/*
+ * Base address and interupt of the SONIC controller on JAZZ boards
+ */
+static struct {
+    unsigned int port;
+    unsigned int irq;
+} sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}};
+
+/*
+ * We cannot use station (ethernet) address prefixes to detect the
+ * sonic controller since these are board manufacturer depended.
+ * So we check for known Silicon Revision IDs instead. 
+ */
+static unsigned short known_revisions[] =
+{
+  0x04,				/* Mips Magnum 4000 */
+  0xffff			/* end of list */
+};
+
+/* Index to functions, as function prototypes. */
+
+extern int sonic_probe(struct device *dev);
+static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq);
+
+
+/*
+ * Probe for a SONIC ethernet controller on a Mips Jazz board.
+ * Actually probing is superfluous but we're paranoid.
+ */
+__initfunc(int sonic_probe(struct device *dev))
+{
+    unsigned int base_addr = dev ? dev->base_addr : 0;
+    int i;
+
+    /*
+     * Don't probe if we're not running on a Jazz board.
+     */
+    if (mips_machgroup != MACH_GROUP_JAZZ)
+	return -ENODEV;
+    if (base_addr >= KSEG0)	/* Check a single specified location. */
+	return sonic_probe1(dev, base_addr, dev->irq);
+    else if (base_addr != 0)	/* Don't probe at all. */
+	return -ENXIO;
+    
+    for (i = 0; sonic_portlist[i].port; i++) {
+	int base_addr = sonic_portlist[i].port;
+	if (check_region(base_addr, 0x100))
+	    continue;
+	if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0)
+	    return 0;
+    }
+    return -ENODEV;
+}
+
+__initfunc(static int sonic_probe1(struct device *dev,
+                                   unsigned int base_addr, unsigned int irq))
+{
+    static unsigned version_printed = 0;
+    unsigned int silicon_revision;
+    unsigned int val;
+    struct sonic_local *lp;
+    int i;
+    
+    /*
+     * get the Silicon Revision ID. If this is one of the known
+     * one assume that we found a SONIC ethernet controller at
+     * the expected location.
+     */
+    silicon_revision = SONIC_READ(SONIC_SR);
+    if (sonic_debug > 1)
+      printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision);
+
+    i = 0;
+    while ((known_revisions[i] != 0xffff) &&
+	   (known_revisions[i] != silicon_revision))
+      i++;
+	
+    if (known_revisions[i] == 0xffff) {
+	printk("SONIC ethernet controller not found (0x%4x)\n",
+	       silicon_revision);
+	return -ENODEV;
+    }
+    
+    request_region(base_addr, 0x100, "SONIC");
+    
+    /* Allocate a new 'dev' if needed. */
+    if (dev == NULL)
+      dev = init_etherdev(0, sizeof(struct sonic_local));
+
+    if (sonic_debug  &&  version_printed++ == 0)
+      printk(version);
+
+    printk("%s: %s found at 0x%08x, ",
+	   dev->name, "SONIC ethernet", base_addr);
+
+    /* Fill in the 'dev' fields. */
+    dev->base_addr = base_addr;
+    dev->irq = irq;
+
+    /*
+     * Put the sonic into software reset, then
+     * retrieve and print the ethernet address.
+     */
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
+    SONIC_WRITE(SONIC_CEP,0);
+    for (i=0; i<3; i++) {
+	val = SONIC_READ(SONIC_CAP0-i);
+	dev->dev_addr[i*2] = val;
+	dev->dev_addr[i*2+1] = val >> 8;
+    }
+
+    printk("HW Address ");
+    for (i = 0; i < 6; i++) {
+	printk("%2.2x", dev->dev_addr[i]);
+	if (i<5)
+	  printk(":");
+    }
+    
+    printk(" IRQ %d\n", irq);
+    
+    /* Initialize the device structure. */
+    if (dev->priv == NULL) {
+	/*
+	 * the memory be located in the same 64kb segment
+	 */
+	lp = NULL;
+	i = 0;
+	do {
+	    lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL);
+	    if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) {
+		/* FIXME, free the memory later */
+		kfree (lp);
+		lp = NULL;
+	    }
+	} while (lp == NULL && i++ < 20);
+	
+	if (lp == NULL) {
+	    printk ("%s: couldn't allocate memory for descriptors\n",
+	            dev->name);
+	    return -ENOMEM;
+	}
+	
+	memset(lp, 0, sizeof(struct sonic_local));
+	
+	/* get the virtual dma address */
+	lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp));
+	if (lp->cda_laddr == ~0UL) {
+	    printk ("%s: couldn't get DMA page entry for descriptors\n",
+	            dev->name);
+	    return -ENOMEM;
+	}
+
+	lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
+	lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
+	lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
+	
+	/* allocate receive buffer area */
+	/* FIXME, maybe we should use skbs */
+	if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) {
+	    printk ("%s: couldn't allocate receive buffers\n",dev->name);
+	    return -ENOMEM;
+	}
+	
+	/* get virtual dma address */
+	if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) {
+	    printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name);
+	    return -ENOMEM;
+	}
+	
+	/* now convert pointer to KSEG1 pointer */
+	lp->rba = (char *)KSEG1ADDR(lp->rba);
+	flush_cache_all();
+	dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
+    }
+
+    lp = (struct sonic_local *)dev->priv;
+    dev->open = sonic_open;
+    dev->stop = sonic_close;
+    dev->hard_start_xmit = sonic_send_packet;
+    dev->get_stats	= sonic_get_stats;
+    dev->set_multicast_list = &sonic_multicast_list;
+
+    /*
+     * clear tally counter
+     */
+    SONIC_WRITE(SONIC_CRCT,0xffff);
+    SONIC_WRITE(SONIC_FAET,0xffff);
+    SONIC_WRITE(SONIC_MPT,0xffff);
+
+    /* Fill in the fields of the device structure with ethernet values. */
+    ether_setup(dev);
+    return 0;
+}
+
+/*
+ *      SONIC uses a normal IRQ
+ */
+#define sonic_request_irq       request_irq
+#define sonic_free_irq          free_irq
+
+#define sonic_chiptomem(x)      KSEG1ADDR(vdma_log2phys(x))
+
+#include "sonic.c"
--- linux-2.2.0pre4/drivers/net/sonic.c.org	Thu Jul 30 12:03:45 1998
+++ linux-2.2.0pre4/drivers/net/sonic.c	Thu Jan  7 20:57:47 1999
@@ -1,290 +1,23 @@
 /*
  * sonic.c
  *
- * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de)
+ * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  * 
  * This driver is based on work from Andreas Busse, but most of
  * the code is rewritten.
  * 
  * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
  *
- * A driver for the onboard Sonic ethernet controller on Mips Jazz
- * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and
- * perhaps others, too)
+ *    Core code included by system sonic drivers
  */
 
-static const char *version =
-	"sonic.c:v0.10 6.7.96 tsbogend@bigbug.franken.de\n";
-
 /*
  * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
  * National Semiconductors data sheet for the DP83932B Sonic Ethernet
  * controller, and the files "8390.c" and "skeleton.c" in this directory.
  */
 
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <asm/bootinfo.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/pgtable.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
-#include <linux/errno.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include "sonic.h"
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifdef SONIC_DEBUG
-static unsigned int sonic_debug = SONIC_DEBUG;
-#else 
-static unsigned int sonic_debug = 2;
-#endif
-
-/*
- * Some tunables for the buffer areas. Power of 2 is required
- * the current driver uses one receive buffer for each descriptor.
- */
-#define SONIC_NUM_RRS    16             /* number of receive resources */
-#define SONIC_NUM_RDS    SONIC_NUM_RRS  /* number of receive descriptors */
-#define SONIC_NUM_TDS    16      /* number of transmit descriptors */
-#define SONIC_RBSIZE   1520      /* size of one resource buffer */
-
-#define SONIC_RDS_MASK   (SONIC_NUM_RDS-1)
-#define SONIC_TDS_MASK   (SONIC_NUM_TDS-1)
 
-/*
- * Base address and interupt of the SONIC controller on JAZZ boards
- */
-static struct {
-    unsigned int port;
-    unsigned int irq;
-    } sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}};
-
-
-/* Information that need to be kept for each board. */
-struct sonic_local {
-    sonic_cda_t   cda;                     /* virtual CPU address of CDA */
-    sonic_td_t    tda[SONIC_NUM_TDS];      /* transmit descriptor area */
-    sonic_rr_t    rra[SONIC_NUM_RRS];      /* receive resource arrea */
-    sonic_rd_t    rda[SONIC_NUM_RDS];      /* receive descriptor area */
-    struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */
-    unsigned int  tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */
-    unsigned char *rba;                    /* start of receive buffer areas */    
-    unsigned int  cda_laddr;               /* logical DMA address of CDA */    
-    unsigned int  tda_laddr;               /* logical DMA address of TDA */
-    unsigned int  rra_laddr;               /* logical DMA address of RRA */    
-    unsigned int  rda_laddr;               /* logical DMA address of RDA */
-    unsigned int  rba_laddr;               /* logical DMA address of RBA */
-    unsigned int  cur_tx, cur_rx;          /* current indexes to resource areas */
-    unsigned int  dirty_tx,cur_rra;        /* last unacked transmit packet */
-    char tx_full;
-    struct enet_statistics stats;
-};
-
-/*
- * We cannot use station (ethernet) address prefixes to detect the
- * sonic controller since these are board manufacturer depended.
- * So we check for known Silicon Revision IDs instead. 
- */
-static unsigned short known_revisions[] =
-{
-  0x04,				/* Mips Magnum 4000 */
-  0xffff			/* end of list */
-};
-
-/* Index to functions, as function prototypes. */
-
-extern int sonic_probe(struct device *dev);
-static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq);
-static int sonic_open(struct device *dev);
-static int sonic_send_packet(struct sk_buff *skb, struct device *dev);
-static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void sonic_rx(struct device *dev);
-static int sonic_close(struct device *dev);
-static struct enet_statistics *sonic_get_stats(struct device *dev);
-static void sonic_multicast_list(struct device *dev);
-static int sonic_init(struct device *dev);
-
-
-/*
- * Probe for a SONIC ethernet controller on a Mips Jazz board.
- * Actually probing is superfluous but we're paranoid.
- */
-__initfunc(int sonic_probe(struct device *dev))
-{
-    unsigned int base_addr = dev ? dev->base_addr : 0;
-    int i;
-
-    /*
-     * Don't probe if we're not running on a Jazz board.
-     */
-    if (mips_machgroup != MACH_GROUP_JAZZ)
-	return -ENODEV;
-    if (base_addr > 0x1ff)	/* Check a single specified location. */
-	return sonic_probe1(dev, base_addr, dev->irq);
-    else if (base_addr != 0)	/* Don't probe at all. */
-	return -ENXIO;
-    
-    for (i = 0; sonic_portlist[i].port; i++) {
-	int base_addr = sonic_portlist[i].port;
-	if (check_region(base_addr, 0x100))
-	    continue;
-	if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0)
-	    return 0;
-    }
-    return -ENODEV;
-}
-
-__initfunc(static int sonic_probe1(struct device *dev,
-                                   unsigned int base_addr, unsigned int irq))
-{
-    static unsigned version_printed = 0;
-    unsigned int silicon_revision;
-    unsigned int val;
-    struct sonic_local *lp;
-    int i;
-    
-    /*
-     * get the Silicon Revision ID. If this is one of the known
-     * one assume that we found a SONIC ethernet controller at
-     * the expected location.
-     */
-    silicon_revision = SONIC_READ(SONIC_SR);
-    if (sonic_debug > 1)
-      printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision);
-
-    i = 0;
-    while ((known_revisions[i] != 0xffff) &&
-	   (known_revisions[i] != silicon_revision))
-      i++;
-	
-    if (known_revisions[i] == 0xffff) {
-	printk("SONIC ethernet controller not found (0x%4x)\n",
-	       silicon_revision);
-	return -ENODEV;
-    }
-    
-    request_region(base_addr, 0x100, "SONIC");
-    
-    /* Allocate a new 'dev' if needed. */
-    if (dev == NULL)
-      dev = init_etherdev(0, sizeof(struct sonic_local));
-
-    if (sonic_debug  &&  version_printed++ == 0)
-      printk(version);
-
-    printk("%s: %s found at 0x%08x, ",
-	   dev->name, "SONIC ethernet", base_addr);
-
-    /* Fill in the 'dev' fields. */
-    dev->base_addr = base_addr;
-    dev->irq = irq;
-
-    /*
-     * Put the sonic into software reset, then
-     * retrieve and print the ethernet address.
-     */
-    SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
-    SONIC_WRITE(SONIC_CEP,0);
-    for (i=0; i<3; i++) {
-	val = SONIC_READ(SONIC_CAP0-i);
-	dev->dev_addr[i*2] = val;
-	dev->dev_addr[i*2+1] = val >> 8;
-    }
-
-    printk("HW Address ");
-    for (i = 0; i < 6; i++) {
-	printk("%2.2x", dev->dev_addr[i]);
-	if (i<5)
-	  printk(":");
-    }
-    
-    printk(" IRQ %d\n", irq);
-    
-    /* Initialize the device structure. */
-    if (dev->priv == NULL) {
-	/*
-	 * the memory be located in the same 64kb segment
-	 */
-	lp = NULL;
-	i = 0;
-	do {
-	    lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL);
-	    if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) {
-		/* FIXME, free the memory later */
-		kfree (lp);
-		lp = NULL;
-	    }
-	} while (lp == NULL && i++ < 20);
-	
-	if (lp == NULL) {
-	    printk ("%s: couldn't allocate memory for descriptors\n",
-	            dev->name);
-	    return -ENOMEM;
-	}
-	
-	memset(lp, 0, sizeof(struct sonic_local));
-	
-	/* get the virtual dma address */
-	lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp));
-	if (lp->cda_laddr == ~0UL) {
-	    printk ("%s: couldn't get DMA page entry for descriptors\n",
-	            dev->name);
-	    return -ENOMEM;
-	}
-
-	lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
-	lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
-	lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
-	
-	/* allocate receive buffer area */
-	/* FIXME, maybe we should use skbs */
-	if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) {
-	    printk ("%s: couldn't allocate receive buffers\n",dev->name);
-	    return -ENOMEM;
-	}
-	
-	/* get virtual dma address */
-	if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) {
-	    printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name);
-	    return -ENOMEM;
-	}
-	
-	/* now convert pointer to KSEG1 pointer */
-	lp->rba = (char *)KSEG1ADDR(lp->rba);
-	flush_cache_all();
-	dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
-    }
-
-    lp = (struct sonic_local *)dev->priv;
-    dev->open = sonic_open;
-    dev->stop = sonic_close;
-    dev->hard_start_xmit = sonic_send_packet;
-    dev->get_stats	= sonic_get_stats;
-    dev->set_multicast_list = &sonic_multicast_list;
-
-    /* Fill in the fields of the device structure with ethernet values. */
-    ether_setup(dev);
-    return 0;
-}
 
 /*
  * Open/initialize the SONIC controller.
@@ -308,8 +41,8 @@
  * covering another bug otherwise corrupting data.  This doesn't mean
  * this glue works ok under all situations.
  */
-//    if (request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {
-    if (request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) {
+//    if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {
+    if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) {
 	printk ("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
 	return EAGAIN;
     }
@@ -351,7 +84,7 @@
     SONIC_WRITE(SONIC_IMR,0);
     SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
 
-    free_irq(dev->irq, dev);			/* release the IRQ */
+    sonic_free_irq(dev->irq, dev);		/* release the IRQ */
 
     return 0;
 }
@@ -424,11 +157,6 @@
     lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff;
     lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
     lp->tda[entry].tx_frag_size  = length;
-    
-    /* if there are already packets queued, allow sending serveral packets at once */
-    if (lp->dirty_tx != lp->cur_tx)
-	lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS;
-    
     lp->cur_tx++;
     lp->stats.tx_bytes += length;
     
@@ -479,20 +207,23 @@
     
     if (status & SONIC_INT_TXDN) {
 	int dirty_tx = lp->dirty_tx;
-	
+
 	while (dirty_tx < lp->cur_tx) {
 	    int entry = dirty_tx & SONIC_TDS_MASK;
 	    int status = lp->tda[entry].tx_status;
-	    
+
 	    if (sonic_debug > 3)
 	      printk ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n",
 		      status,lp->cur_tx,lp->dirty_tx);
-	    
-	    if (status == 0)
-	      break;			/* It still hasn't been Txed */
+
+	    if (status == 0) {
+		/* It still hasn't been Txed, kick the sonic again */
+		SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP);		
+		break;
+	    }
 
 	    /* put back EOL and free descriptor */
-	    lp->tda[entry].link |= SONIC_END_OF_LINKS;
+	    lp->tda[entry].tx_frag_count = 0;
 	    lp->tda[entry].tx_status = 0;
 
 	    if (status & 0x0001)
@@ -574,27 +305,25 @@
 {
     unsigned int base_addr = dev->base_addr;
     struct sonic_local *lp = (struct sonic_local *)dev->priv;
-    int entry = lp->cur_rx & SONIC_RDS_MASK;
+    sonic_rd_t *rd = &lp->rda[lp->cur_rx & SONIC_RDS_MASK];
     int status;
 
-    while(lp->rda[entry].in_use == 0)
-    {
+    while (rd->in_use == 0) {
 	struct sk_buff *skb;
 	int pkt_len;
 	unsigned char *pkt_ptr;
 	
-	status = lp->rda[entry].rx_status;
+	status = rd->rx_status;
 	if (sonic_debug > 3)
-	  printk ("status %x, cur_rx %d, cur_rra %d\n",status,lp->cur_rx,lp->cur_rra);
+	  printk ("status %x, cur_rx %d, cur_rra %x\n",status,lp->cur_rx,lp->cur_rra);
 	if (status & SONIC_RCR_PRX) {	    
-	    pkt_len = lp->rda[entry].rx_pktlen;
-	    pkt_ptr = (char *)KSEG1ADDR(vdma_log2phys((lp->rda[entry].rx_pktptr_h << 16) +
-						      lp->rda[entry].rx_pktptr_l));
+	    pkt_len = rd->rx_pktlen;
+	    pkt_ptr = (char *)sonic_chiptomem((rd->rx_pktptr_h << 16) +
+						      rd->rx_pktptr_l);
 	    
 	    if (sonic_debug > 3)
-	      printk ("pktptr %p (rba %p) h:%x l:%x, rra h:%x l:%x bsize h:%x l:%x\n", pkt_ptr,lp->rba,
-		      lp->rda[entry].rx_pktptr_h,lp->rda[entry].rx_pktptr_l,
-		      lp->rra[lp->cur_rra & 15].rx_bufadr_h,lp->rra[lp->cur_rra & 15].rx_bufadr_l,
+	      printk ("pktptr %p (rba %p) h:%x l:%x, bsize h:%x l:%x\n", pkt_ptr,lp->rba,
+		      rd->rx_pktptr_h,rd->rx_pktptr_l,
 		      SONIC_READ(SONIC_RBWC1),SONIC_READ(SONIC_RBWC0));
 	
 	    /* Malloc up new buffer. */
@@ -620,21 +349,26 @@
 	    if (status & SONIC_RCR_CRCR) lp->stats.rx_crc_errors++;
 	}
 	
-	lp->rda[entry].in_use = 1;
-	entry = (++lp->cur_rx) & SONIC_RDS_MASK;
+	rd->in_use = 1;
+	rd = &lp->rda[(++lp->cur_rx) & SONIC_RDS_MASK];
 	/* now give back the buffer to the receive buffer area */
 	if (status & SONIC_RCR_LPKT) {
 	    /*
 	     * this was the last packet out of the current receice buffer
 	     * give the buffer back to the SONIC
 	     */
-	    SONIC_WRITE(SONIC_RWP,(lp->rra_laddr + (++lp->cur_rra & 15) * sizeof(sonic_rr_t)) & 0xffff);
-	}
+	    lp->cur_rra += sizeof(sonic_rr_t);
+	    if (lp->cur_rra > (lp->rra_laddr + (SONIC_NUM_RRS-1) * sizeof(sonic_rr_t)))
+		lp->cur_rra = lp->rra_laddr;
+	    SONIC_WRITE(SONIC_RWP, lp->cur_rra & 0xffff);
+	} else
+	    printk ("%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",dev->name);
     }
-  
-    /* If any worth-while packets have been received, dev_rint()
-     has done a mark_bh(NET_BH) for us and will work on them
-     when we get to the bottom-half routine. */
+    /*
+     * If any worth-while packets have been received, dev_rint()
+     * has done a mark_bh(NET_BH) for us and will work on them
+     * when we get to the bottom-half routine.
+     */
     return;
 }
 
@@ -689,16 +423,15 @@
 	    for (i = 1; i <= dev->mc_count; i++) {
 		addr = dmi->dmi_addr;
 		dmi = dmi->next;
-		lp->cda.cam_desc[i].cam_frag2 = addr[1] << 8 | addr[0];
-		lp->cda.cam_desc[i].cam_frag1 = addr[3] << 8 | addr[2];
-		lp->cda.cam_desc[i].cam_frag0 = addr[5] << 8 | addr[4];
+		lp->cda.cam_desc[i].cam_cap0 = addr[1] << 8 | addr[0];
+		lp->cda.cam_desc[i].cam_cap1 = addr[3] << 8 | addr[2];
+		lp->cda.cam_desc[i].cam_cap2 = addr[5] << 8 | addr[4];
 		lp->cda.cam_enable |= (1 << i);
 	    }
-	    /* number of CAM entries to load */
-	    SONIC_WRITE(SONIC_CDC,dev->mc_count+1);
+	    SONIC_WRITE(SONIC_CDC,16);
 	    /* issue Load CAM command */
 	    SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff);	    
-	    SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM);	    
+	    SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM);
 	}
     }
     
@@ -736,7 +469,6 @@
     SONIC_WRITE(SONIC_CMD,0);
     SONIC_WRITE(SONIC_CMD,SONIC_CR_RXDIS);
 
-
     /*
      * initialize the receive resource area
      */
@@ -761,7 +493,7 @@
     SONIC_WRITE(SONIC_URRA,lp->rra_laddr >> 16);
     SONIC_WRITE(SONIC_EOBC,(SONIC_RBSIZE-2) >> 1);
     
-    lp->cur_rra = SONIC_NUM_RRS - 2;
+    lp->cur_rra = lp->rra_laddr + (SONIC_NUM_RRS-1) * sizeof(sonic_rr_t);
 
     /* load the resource pointers */
     if (sonic_debug > 3)
@@ -796,7 +528,6 @@
     /* fix last descriptor */
     lp->rda[SONIC_NUM_RDS-1].link = lp->rda_laddr;
     lp->cur_rx = 0;
-    
     SONIC_WRITE(SONIC_URDA,lp->rda_laddr >> 16);
     SONIC_WRITE(SONIC_CRDA,lp->rda_laddr & 0xffff);
     
@@ -816,13 +547,14 @@
 
     SONIC_WRITE(SONIC_UTDA,lp->tda_laddr >> 16);
     SONIC_WRITE(SONIC_CTDA,lp->tda_laddr & 0xffff);
+    lp->cur_tx = lp->dirty_tx = 0;
     
     /*
      * put our own address to CAM desc[0]
      */
-    lp->cda.cam_desc[0].cam_frag2 = dev->dev_addr[1] << 8 | dev->dev_addr[0];
-    lp->cda.cam_desc[0].cam_frag1 = dev->dev_addr[3] << 8 | dev->dev_addr[2];
-    lp->cda.cam_desc[0].cam_frag0 = dev->dev_addr[5] << 8 | dev->dev_addr[4];
+    lp->cda.cam_desc[0].cam_cap0 = dev->dev_addr[1] << 8 | dev->dev_addr[0];
+    lp->cda.cam_desc[0].cam_cap1 = dev->dev_addr[3] << 8 | dev->dev_addr[2];
+    lp->cda.cam_desc[0].cam_cap2 = dev->dev_addr[5] << 8 | dev->dev_addr[4];
     lp->cda.cam_enable = 1;
     
     for (i=0; i < 16; i++)
@@ -832,7 +564,7 @@
      * initialize CAM registers
      */
     SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff);
-    SONIC_WRITE(SONIC_CDC,1);
+    SONIC_WRITE(SONIC_CDC,16);
     
     /*
      * load the CAM

--------------28E0BC49A93D2D9229D6DF71--

