Resent-Date: Mon, 21 Sep 1998 05:07:47 +0200 (MET DST)
X-Sender: ddkilzer@mail.earthlink.net
In-Reply-To: <v03130302b22af56ec212@[38.12.27.86]>
X-Files: Sundays at 8 PM CDT on Fox!
Date: Sun, 20 Sep 1998 22:06:58 -0500
To: Jes Sorensen <Jes.Sorensen@cern.ch>
From: "David D. Kilzer" <ddkilzer@earthlink.net>
Subject: 2.1.120 patch for Mac, part 2
Cc: Linux-m68k Mailing List <linux-m68k@lists.linux-m68k.org>
Resent-From: linux-m68k@phil.uni-sb.de

Hi Jes,

Please find attached the *second* Mac patch for 2.1.120, 
mac-2.1.120-2.diff.gz.  It should be applied *IN ADDITION TO* the 
patch I sent earlier.  Everything included in this patch is from 
Alan Cox's recent 2.1.119 patch.

<ftp://ftp.linux.org.uk//pub/linux/alan/tmp/macdiffs-119.gz>

The attached file is identical to this diff on the Linux-mac68k FTP
site.

<ftp://maclinux.wwaves.com//pub/MacLinux/kernels/src/
  mac-2.1.120-vanilla-980920-2.diff.gz>

Alan has included lots of goodies in this diff, including but not 
limited to:

  o CONFIG_FTRACE (profiling for function call trace) [untested?]

  o CONFIG_M68K_L2_CACHE (support for L2 cache on IIsi, IIcx, IIci 
    and IIfx) [tested on IIfx]

  o CONFIG_MACMACE (MACE ethernet for 660/840 AV Macs) [tested but
    broken on some AV Macs]

  o CONFIG_MACSONIC (SONIC ethernet for the rest of the Quadras)
    [untested and probably broken]

  o CONFIG_M68K_SOFT_FLOAT (removes FPU assembly instructions in
    the kernel when turned on)  [untested?]

  o SYSV filesystem fixes.

  o Nubus /proc support.

I generated this list by looking through his patch.  I may have
inadvertantly left something out or misstated something.

Dave


Earlier in the day David Kilzer wrote:

>Here's patch against 2.1.120 for some Mac-specific stuff.  I've taken the 
>mac-2.1.120-vanilla-980920.diff and removed the more volatile parts of it.
>
><ftp://maclinux.wwaves.com//pub/MacLinux/kernels/src/
>  mac-2.1.120-vanilla-980920.diff.gz>
>
>
>I left out the most recent head.S cleanup patch and the 
>CONFIG_APM/mach_halt/mach_powerdown patches.


diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/Makefile linux-2.1.120-alan/arch/m68k/Makefile
--- linux-2.1.120/arch/m68k/Makefile	Mon Jun  8 11:07:41 1998
+++ linux-2.1.120-alan/arch/m68k/Makefile	Sun Sep 20 20:44:15 1998
@@ -29,6 +29,12 @@
 # without -fno-strength-reduce the 53c7xx.c driver fails ;-(
 CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
 
+# Add profiling for function call trace
+
+ifdef CONFIG_FTRACE
+CFLAGS := $(CFLAGS) -p
+endif
+
 ifdef CONFIG_OPTIMIZE_040
 CFLAGS := $(CFLAGS) -m68040
 endif
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/config.in linux-2.1.120-alan/arch/m68k/config.in
--- linux-2.1.120/arch/m68k/config.in	Mon Sep  7 09:47:04 1998
+++ linux-2.1.120-alan/arch/m68k/config.in	Sun Sep 20 20:44:15 1998
@@ -32,6 +32,7 @@
 bool 'Macintosh support' CONFIG_MAC
 if [ "$CONFIG_MAC" = "y" ]; then
   define_bool CONFIG_NUBUS y
+  define_bool CONFIG_M68K_L2_CACHE y
 fi
 bool 'Apollo support' CONFIG_APOLLO
 bool 'VME (Motorola and BVM) support' CONFIG_VME
@@ -52,6 +53,7 @@
 bool '68030 support' CONFIG_M68030
 bool '68040 support' CONFIG_M68040
 bool '68060 support' CONFIG_M68060
+bool 'User mode software floating point' CONFIG_M68K_SOFT_FLOAT
 if [ "$CONFIG_M68020" = "n" -a "$CONFIG_M68030" = "n" ]; then
   if [ "$CONFIG_M68040" = "y" -a "$CONFIG_M68060" = "n" ]; then
     bool 'Use 68040 specific optimizations' CONFIG_OPTIMIZE_040
@@ -223,6 +225,8 @@
 fi
 if [ "$CONFIG_MAC" = "y" ]; then
   bool 'Mac NS 8390 based ethernet cards' CONFIG_DAYNAPORT
+  bool 'AV Macintosh onboard MACE ethernet' CONFIG_MACMACE
+  bool 'Macintosh onboard SONIC ethernet' CONFIG_MACSONIC
 fi
 if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
   bool 'MVME16x Ethernet support' CONFIG_MVME16x_NET
@@ -373,6 +377,7 @@
 comment 'Kernel hacking'
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+bool 'Kernel function trace support' CONFIG_FTRACE
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 bool 'Remote debugging support' CONFIG_KGDB
 endmenu
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/kernel/entry.S linux-2.1.120-alan/arch/m68k/kernel/entry.S
--- linux-2.1.120/arch/m68k/kernel/entry.S	Wed Sep  2 03:44:42 1998
+++ linux-2.1.120-alan/arch/m68k/kernel/entry.S	Sun Sep 20 20:44:15 1998
@@ -288,10 +288,14 @@
 1:	tstb	%a0@(LTSS_FPCTXT+27*4)
 	jeq	3f
 #endif
+#ifdef CONFIG_M68K_SOFT_FLOAT
+2:
+3:
+#else
 2:	fmovemx	%fp0-%fp7,%a0@(LTSS_FPCTXT)
 	fmoveml	%fpcr/%fpsr/%fpiar,%a0@(LTSS_FPCTXT+24*4)
 3:
-
+#endif
 	/* get pointer to tss struct (a1 contains new task) */
 	movel	%a1,%curptr
 	addl	%d1,%a1
@@ -369,9 +373,14 @@
 1:	tstb	%a1@(LTSS_FPCTXT+27*4)
 	jeq	3f
 #endif	
+#ifdef CONFIG_M68K_SOFT_FLOAT
+2:
+3:
+#else
 2:	fmovemx	%a1@(LTSS_FPCTXT),%fp0-%fp7
 	fmoveml	%a1@(LTSS_FPCTXT+24*4),%fpcr/%fpsr/%fpiar
 3:	frestore %a1@(LTSS_FPCTXT+27*4)
+#endif
 
 	/* restore the kernel stack pointer */
 	movel	%a1@(LTSS_KSP),%sp
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/kernel/process.c linux-2.1.120-alan/arch/m68k/kernel/process.c
--- linux-2.1.120/arch/m68k/kernel/process.c	Sun Sep 20 20:37:03 1998
+++ linux-2.1.120-alan/arch/m68k/kernel/process.c	Sun Sep 20 20:44:15 1998
@@ -186,6 +186,7 @@
 	 */
 	p->tss.fs = get_fs().seg;
 
+#ifndef CONFIG_M68K_SOFT_FLOAT
 	/* Copy the current fpu state */
 	asm volatile ("fsave %0" : : "m" (p->tss.fpstate[0]) : "memory");
 
@@ -196,7 +197,7 @@
 			: "memory");
 	/* Restore the state in case the fpu was busy */
 	asm volatile ("frestore %0" : : "m" (p->tss.fpstate[0]));
-
+#endif
 	return 0;
 }
 
@@ -205,7 +206,9 @@
 int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
 {
   char fpustate[216];
-
+#ifdef CONFIG_M68K_SOFT_FLOAT
+  return 0;
+#else
   /* First dump the fpu context to avoid protocol violation.  */
   asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
   if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
@@ -218,6 +221,7 @@
 		:: "m" (fpu->fpregs[0])
 		: "memory");
   return 1;
+#endif  
 }
 
 /*
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/kernel/setup.c linux-2.1.120-alan/arch/m68k/kernel/setup.c
--- linux-2.1.120/arch/m68k/kernel/setup.c	Sun Sep 20 20:37:04 1998
+++ linux-2.1.120-alan/arch/m68k/kernel/setup.c	Sun Sep 20 20:44:16 1998
@@ -187,11 +187,13 @@
 
 	base_trap_init();
 
+#ifndef CONFIG_M68K_SOFT_FLOAT
 	/* clear the fpu if we have one */
 	if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
 		volatile int zero = 0;
 		asm __volatile__ ("frestore %0" : : "m" (zero));
 	}
+#endif	
 
 	init_task.mm->start_code = PAGE_OFFSET;
 	init_task.mm->end_code = (unsigned long) &_etext;
@@ -292,6 +294,59 @@
 		*memory_end_p += m68k_memory[i].size & MASK_256K;
 }
 
+#ifdef CONFIG_FTRACE
+
+/* XXX FTRACE_LEN is hardcoded in the assembler below XXX */
+
+#define FTRACE_LEN     16384
+unsigned long ftrace_index;
+unsigned long ftrace_enable;
+unsigned long ftrace_buf[FTRACE_LEN];
+
+void do_ftrace(unsigned long);
+
+/* These functions are in assembler so that (a) they can save/restore all
+ * registers, and (b) so that the compiler doesn't include a recursive
+ * _mcount() call in to them.
+ */
+
+__asm__ (".text\n"
+__ALIGN_STR "\n"
+".globl " SYMBOL_NAME_STR(do_ftrace) ";\n"
+SYMBOL_NAME_STR(do_ftrace) ":
+	tst.l (" SYMBOL_NAME_STR(ftrace_enable) ")
+	beq.s 1f
+	move.w %sr,-(%a7)
+	ori.w  #0x700,%sr
+	movem.l %d0/%a0,-(%a7)
+	move.l (" SYMBOL_NAME_STR(ftrace_index) "),%d0
+	lea.l  " SYMBOL_NAME_STR(ftrace_buf) ",%a0
+	move.l 14(%a7),(%a0,%d0*4)
+	addq.l #1,%d0
+	cmpi.l #0x4000,%d0
+	bne.s  2f
+	clr.l  %d0
+2:
+	move.l %d0," SYMBOL_NAME_STR(ftrace_index) "
+	movem.l (%a7)+,%a0/%d0
+	move.w (%a7)+,%sr
+1:
+	rts
+");
+
+
+__asm__ (".text\n"
+__ALIGN_STR "\n"
+".globl " SYMBOL_NAME_STR(_mcount) ";\n"
+SYMBOL_NAME_STR(_mcount) ":
+	move.l (%a7),-(%a7)
+	bsr.s (" SYMBOL_NAME_STR(do_ftrace) ")
+	addq #4,%a7
+	rts
+");
+
+#endif
+
 int get_cpuinfo(char * buffer)
 {
     const char *cpu, *mmu, *fpu;
@@ -319,6 +374,9 @@
 	clockfactor = 0;
     }
 
+#ifdef CONFIG_M68K_SOFT_FLOAT
+	fpu="none(soft float)";
+#else
     if (m68k_fputype & FPU_68881)
 	fpu = "68881";
     else if (m68k_fputype & FPU_68882)
@@ -331,6 +389,7 @@
 	fpu = "Sun FPA";
     else
 	fpu = "none";
+#endif
 
     if (m68k_mmutype & MMU_68851)
 	mmu = "68851";
@@ -416,7 +475,7 @@
 
 void check_bugs(void)
 {
-#ifndef CONFIG_FPU_EMU
+#if !defined(CONFIG_FPU_EMU) && !defined(CONFIG_M68K_SOFT_FLOAT)
 	if (m68k_fputype == 0) {
 		printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
 				"WHICH IS REQUIRED BY LINUX/M68K ***\n" );
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/kernel/signal.c linux-2.1.120-alan/arch/m68k/kernel/signal.c
--- linux-2.1.120/arch/m68k/kernel/signal.c	Mon Sep  7 07:29:13 1998
+++ linux-2.1.120-alan/arch/m68k/kernel/signal.c	Sun Sep 20 20:44:16 1998
@@ -196,6 +196,9 @@
 
 static inline int restore_fpu_state(struct sigcontext *sc)
 {
+#ifdef CONFIG_M68K_SOFT_FLOAT
+	return 0;
+#else	
 	int err = 1;
 
 	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
@@ -236,6 +239,7 @@
 
 out:
 	return err;
+#endif	
 }
 
 #define FPCONTEXT_SIZE	216
@@ -245,6 +249,9 @@
 
 static inline int rt_restore_fpu_state(struct ucontext *uc)
 {
+#ifdef CONFIG_M68K_SOFT_FLOAT
+	return 0;
+#else	
 	unsigned char fpstate[FPCONTEXT_SIZE];
 	int context_size = CPU_IS_060 ? 8 : 0;
 	fpregset_t fpregs;
@@ -299,6 +306,7 @@
 
 out:
 	return err;
+#endif	
 }
 
 static inline int
@@ -547,6 +555,7 @@
 
 static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
 {
+#ifndef CONFIG_M68K_SOFT_FLOAT
 	__asm__ volatile (".chip 68k/68881\n\t"
 			  "fsave %0\n\t"
 			  ".chip 68k"
@@ -570,10 +579,14 @@
 				    "m" (*sc->sc_fpcntl)
 				  : "memory");
 	}
+#endif	
 }
 
 static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
 {
+#ifdef CONFIG_M68K_SOFT_FLOAT
+	return 0;
+#else	
 	unsigned char fpstate[FPCONTEXT_SIZE];
 	int context_size = CPU_IS_060 ? 8 : 0;
 	int err = 0;
@@ -611,6 +624,7 @@
 		err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
 				    context_size);
 	return err;
+#endif	
 }
 
 static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/kernel/traps.c linux-2.1.120-alan/arch/m68k/kernel/traps.c
--- linux-2.1.120/arch/m68k/kernel/traps.c	Tue Jan 13 08:46:57 1998
+++ linux-2.1.120-alan/arch/m68k/kernel/traps.c	Sun Sep 20 20:44:16 1998
@@ -302,6 +302,19 @@
 	unsigned short ssw = fp->un.fmt7.ssw;
 	unsigned long mmusr;
 
+#ifdef CONFIG_FTRACE
+	{
+		unsigned long flags;
+
+		save_flags(flags);
+		cli();
+		do_ftrace(0xfb000000 | ssw);
+		do_ftrace(fp->un.fmt7.faddr);
+		do_ftrace(fp->ptregs.pc);
+		restore_flags(flags);
+	}
+#endif
+
 #ifdef DEBUG
 	printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
         printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,  
@@ -330,6 +343,17 @@
 #endif
 		errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
 			((ssw & RW_040) ? 0 : 2);
+#ifdef CONFIG_FTRACE
+		{
+			unsigned long flags;
+
+			save_flags(flags);
+			cli();
+			do_ftrace(0xfa000000 | errorcode);
+			do_ftrace(mmusr);
+			restore_flags(flags);
+		}
+#endif
 		do_page_fault (&fp->ptregs, addr, errorcode);
 	} else {
 		printk ("68040 access error, ssw=%x\n", ssw);
@@ -400,6 +424,23 @@
 				printk ("Instruction fault at %#010lx\n",
 					fp->ptregs.pc);
 			if (ssw & DF) {
+				errorcode = (mmusr & MMU_I) ? 0 : 1;
+				if (!(ssw & RW) || (ssw & RM))
+				{
+					printk("SSW=%04X\n", ssw);
+					printk("Magic smoke on\n");
+					printk("Faulting for %p\n",
+						fp->un.fmtb.daddr);
+					errorcode |= 2;
+				}
+
+				printk("DPF %p %d\n", fp->un.fmtb.daddr,
+					errorcode);
+				if (do_page_fault (&fp->ptregs,
+						   fp->un.fmtb.daddr,
+						   errorcode) < 0)
+					return;
+
 				printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 					ssw & RW ? "read" : "write",
 					fp->un.fmtb.daddr,
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/mac/config.c linux-2.1.120-alan/arch/m68k/mac/config.c
--- linux-2.1.120/arch/m68k/mac/config.c	Sun Sep 20 20:37:04 1998
+++ linux-2.1.120-alan/arch/m68k/mac/config.c	Sun Sep 20 21:16:05 1998
@@ -83,9 +83,9 @@
 
 /* Mac specific timer functions */
 extern unsigned long mac_gettimeoffset (void);
-extern void mac_gettod (int *, int *, int *, int *, int *, int *);
-extern int mac_hwclk (int, struct hwclk_time *);
-extern int mac_set_clock_mmss (unsigned long);
+static void mac_gettod (int *, int *, int *, int *, int *, int *);
+static int mac_hwclk (int, struct hwclk_time *);
+static int mac_set_clock_mmss (unsigned long);
 extern void via_init_clock(void (*func)(int, void *, struct pt_regs *));
 
 extern void (*kd_mksound)(unsigned int, unsigned int);
@@ -123,7 +123,7 @@
 	mac_reset();
 }
 
-void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
+static void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
 {
 	via_init_clock(vector);
 }
@@ -135,7 +135,7 @@
  * the system time.
  */
 
-void mac_gettod (int *yearp, int *monp, int *dayp,
+static void mac_gettod (int *yearp, int *monp, int *dayp,
 		 int *hourp, int *minp, int *secp)
 {
 	unsigned long time;
@@ -192,7 +192,7 @@
  * TBI: read and write hwclock
  */
 
-int mac_hwclk( int op, struct hwclk_time *t )
+static int mac_hwclk( int op, struct hwclk_time *t )
 {
     return 0;
 }
@@ -201,7 +201,7 @@
  * TBI: set minutes/seconds in hwclock
  */
 
-int mac_set_clock_mmss (unsigned long nowtime)
+static int mac_set_clock_mmss (unsigned long nowtime)
 {
     short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
 
@@ -280,6 +280,22 @@
     return(unknown);
 }
 
+/*
+ *	Flip into 24bit mode for an instant - flushes the L2 cache card. We
+ *	have to disable interrupts for this. Our IRQ handlers will crap 
+ *	themselves if they take an IRQ in 24bit mode!
+ */
+
+static void mac_cache_card_flush(int writeback)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	via_write(via2, vBufB, via_read(via2,vBufB)&~VIA2B_vMode32);
+	via_write(via2, vBufB, via_read(via2,vBufB)|VIA2B_vMode32);
+	restore_flags(flags);
+}
+
 __initfunc(void config_mac(void))
 {
 
@@ -340,7 +356,17 @@
      
     mac_identify();
     mac_report_hardware();
-
+    
+    if(
+    	/* Cache cards */
+        macintosh_config->ident == MAC_MODEL_IICI||
+    	macintosh_config->ident == MAC_MODEL_IISI||
+    	macintosh_config->ident == MAC_MODEL_IICX||
+    	/* On board L2 cache */
+    	macintosh_config->ident == MAC_MODEL_IIFX)
+    {
+    	mach_l2_flush = mac_cache_card_flush;
+    }
     /* goes on forever if timers broken */
 #ifdef MAC_DEBUG_SOUND
     mac_mksound(1000,10);
@@ -351,7 +377,6 @@
      */
 
     nubus_sweep_video();
-
 }	
 
 
@@ -413,12 +438,13 @@
 	{	MAC_MODEL_LCIII,"LC III", MAC_ADB_IISI,	MAC_VIA_IIci,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 
 	/*
-	 *	Quadra (only 68030 ones will actually work!). Not much odd. Video is at
-	 *	0xF9000000, via is like a MacII. We label it differently as some of the
-	 *	stuff connected to VIA2 seems different. Better SCSI chip and onboard
-	 *	ethernet using a NatSemi SONIC except the 840AV which uses an AMD 79C940
-	 *	(MACE). The 700, 900 and 950 have some I/O chips in the wrong place to
-	 *	confuse us. The 840AV has a SCSI location of its own (same as the 660AV).
+	 *	Quadra. Video is at 0xF9000000, via is like a MacII. We label it differently 
+	 *	as some of the stuff connected to VIA2 seems different. Better SCSI chip and 
+	 *	onboard ethernet using a NatSemi SONIC except the 660AV and 840AV which use an 
+	 *	AMD 79C940 (MACE).
+	 *	The 700, 900 and 950 have some I/O chips in the wrong place to
+	 *	confuse us. The 840AV has a SCSI location of its own (same as
+	 *	the 660AV).
 	 */	 
 
 	{	MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE,   MAC_SCC_QUADRA,	MAC_ETHER_NONE,		MAC_NUBUS},
@@ -577,8 +603,7 @@
 	  break;
 
 	}
-
-
+	via_configure_base();
 }
 
 void mac_report_hardware(void)
@@ -590,6 +615,8 @@
 {
 	strcpy(str,"Macintosh ");
 	strcat(str, macintosh_config->name);
+	if(mach_l2_flush && !(via_read(via2, vBufB)&VIA2B_vCDis))
+		strcat(str, "(+L2 cache)");
 }
 
 /*
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/mac/macints.c linux-2.1.120-alan/arch/m68k/mac/macints.c
--- linux-2.1.120/arch/m68k/mac/macints.c	Sun Sep 20 20:37:04 1998
+++ linux-2.1.120-alan/arch/m68k/mac/macints.c	Sun Sep 20 20:44:20 1998
@@ -275,13 +275,8 @@
 	 *		Currently, one interrupt per channel is used, solely
 	 *		to pass the correct async_info as parameter!
 	 */
-#if 0	/* want to install debug/SCC shutup routine until SCC init */
-	sys_request_irq(4, mac_SCC_handler, IRQ_FLG_STD, "INT4", mac_SCC_handler);
-#else
+
 	sys_request_irq(4, mac_debug_handler, IRQ_FLG_STD, "INT4", mac_debug_handler);
-#endif
-	/* Alan uses IRQ 5 for SCC ?? */
-	sys_request_irq(5, mac_debug_handler, IRQ_FLG_STD, "INT5", mac_debug_handler);
 
 	/* level 6 */
 	sys_request_irq(6, mac_bang, IRQ_FLG_LOCK, "offswitch", mac_bang);
@@ -291,25 +286,25 @@
 
 	/* initialize the handler tables for VIAs */
 	for (i = 0; i < 8; i++) {
-		 via1_handler[i].handler = mac_default_handler;
-		 via1_handler[i].dev_id  = NULL;
-		 via1_param[i].flags     = IRQ_FLG_STD;
-		 via1_param[i].devname   = NULL;
-
-		 via2_handler[i].handler = mac_default_handler;
-		 via2_handler[i].dev_id  = NULL;
-		 via2_param[i].flags     = IRQ_FLG_STD;
-		 via2_param[i].devname   = NULL;
-
-		  rbv_handler[i].handler = mac_default_handler;
-		  rbv_handler[i].dev_id  = NULL;
-		  rbv_param[i].flags     = IRQ_FLG_STD;
-		  rbv_param[i].devname   = NULL;
-
-		  scc_handler[i].handler = mac_default_handler;
-		  scc_handler[i].dev_id  = NULL;
-		  scc_param[i].flags     = IRQ_FLG_STD;
-		  scc_param[i].devname   = NULL;
+		via1_handler[i].handler = mac_default_handler;
+		via1_handler[i].dev_id  = NULL;
+		via1_param[i].flags     = IRQ_FLG_STD;
+		via1_param[i].devname   = NULL;
+
+		via2_handler[i].handler = mac_default_handler;
+		via2_handler[i].dev_id  = NULL;
+		via2_param[i].flags     = IRQ_FLG_STD;
+		via2_param[i].devname   = NULL;
+
+		rbv_handler[i].handler = mac_default_handler;
+		rbv_handler[i].dev_id  = NULL;
+		rbv_param[i].flags     = IRQ_FLG_STD;
+		rbv_param[i].devname   = NULL;
+
+		scc_handler[i].handler = mac_default_handler;
+		scc_handler[i].dev_id  = NULL;
+		scc_param[i].flags     = IRQ_FLG_STD;
+		scc_param[i].devname   = NULL;
 
 		/* NUBUS interrupts routed through VIA2 slot 2 - special */
 		nubus_handler[i].handler = nubus_wtf;
@@ -339,16 +334,16 @@
 	via_table[2]     =  NULL;
 	via_table[3]     =  NULL;
 	
-	handler_table[2] =   &rbv_handler[0];
+	handler_table[2] =  &rbv_handler[0];
 	handler_table[3] =  &scc_handler[0];
 	handler_table[4] =  NULL;
 	handler_table[5] =  NULL;
 	handler_table[6] =  NULL;
-	handler_table[7] = &nubus_handler[0];
+	handler_table[7] =  &nubus_handler[0];
 
-	param_table[2]   =   &rbv_param[0];
+	param_table[2]   =  &rbv_param[0];
 	param_table[3]   =  &scc_param[0];
-	param_table[7]   = &nubus_param[0];
+	param_table[7]   =  &nubus_param[0];
 
 	mac_irqs[2]	 =  &rbv_irqs[0];
 	mac_irqs[3]	 =  &scc_irqs[0];
@@ -358,7 +353,8 @@
 	 *	AV Macs: shutup the PSC ints
 	 */
 	if (macintosh_config->ident == MAC_MODEL_C660
-	 || macintosh_config->ident == MAC_MODEL_Q840) {
+	 || macintosh_config->ident == MAC_MODEL_Q840) 
+	{
 		psc_init();
 
 		handler_table[2] = &psc3_handler[0];
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/mac/psc.h linux-2.1.120-alan/arch/m68k/mac/psc.h
--- linux-2.1.120/arch/m68k/mac/psc.h	Mon Jun  8 09:44:27 1998
+++ linux-2.1.120-alan/arch/m68k/mac/psc.h	Sun Sep 20 20:44:20 1998
@@ -1,18 +0,0 @@
-/*
- *	Apple Peripheral System Controller (PSC)
- *
- *	The PSC is used on the AV Macs to control IO functions not handled
- *	by the VIAs (Ethernet, DSP, SCC).
- */
- 
-#define PSCBASE		0x50F31000
-
-#define pIFR3		0x130
-#define pIFR4		0x140
-#define pIFR5		0x150
-#define pIFR6		0x160
-
-#define pIER3		0x134
-#define pIER4		0x144
-#define pIER5		0x154
-#define pIER6		0x164
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/mac/via6522.c linux-2.1.120-alan/arch/m68k/mac/via6522.c
--- linux-2.1.120/arch/m68k/mac/via6522.c	Sun Sep 20 20:37:04 1998
+++ linux-2.1.120-alan/arch/m68k/mac/via6522.c	Sun Sep 20 20:57:19 1998
@@ -16,7 +16,7 @@
 #include <asm/macintosh.h> 
 #include <asm/macints.h> 
 #include "via6522.h"
-#include "psc.h"
+#include <asm/mac_psc.h>
 
 volatile unsigned char *via1=(unsigned char *)VIABASE;
 volatile unsigned char *via2=(unsigned char *)VIABASE2;
@@ -44,9 +44,8 @@
 #define MAC_CLOCK_HIGH		(MAC_CLOCK_TICK>>8)
 
 
-void via_init_clock(void (*func)(int, void *, struct pt_regs *))
+void via_configure_base(void)
 {
-	unsigned char c;
 
 	switch(macintosh_config->via_type)
 	{
@@ -72,6 +71,13 @@
 			break;
 		default:
 	}
+}
+
+
+void via_init_clock(void (*func)(int, void *, struct pt_regs *))
+{	
+	unsigned char c;
+	
 	via1_clock=via_read(via1, vACR);
 	via1_datab=via_read(via1, vBufB);
 
@@ -190,22 +196,23 @@
 #define TICK_SIZE 10000
   
 /* This is always executed with interrupts disabled.  */
+
 unsigned long mac_gettimeoffset (void)
 {
-  unsigned long ticks, offset = 0;
+	unsigned long ticks, offset = 0;
 
-  /* read VIA1 timer 2 current value */
-  ticks = via_read(via1, vT1CL) + (via_read(via1, vT1CH)<<8);
-  /* The probability of underflow is less than 2% */
-  if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
-    /* Check for pending timer interrupt in VIA1 IFR */
-    if (via_read(via1, vIFR) & 0x40)
-      offset = TICK_SIZE;
+	/* read VIA1 timer 2 current value */
+	ticks = via_read(via1, vT1CL) + (via_read(via1, vT1CH)<<8);
+	/* The probability of underflow is less than 2% */
+	if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
+		/* Check for pending timer interrupt in VIA1 IFR */
+		if (via_read(via1, vIFR) & 0x40)
+			offset = TICK_SIZE;
 
-  ticks = MAC_CLOCK_TICK - ticks;
-  ticks = ticks * 10000L / MAC_CLOCK_TICK;
+	ticks = MAC_CLOCK_TICK - ticks;
+	ticks = ticks * 10000L / MAC_CLOCK_TICK;
 
-  return ticks + offset;
+	return ticks + offset;
 }
 
 /*
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/mac/via6522.h linux-2.1.120-alan/arch/m68k/mac/via6522.h
--- linux-2.1.120/arch/m68k/mac/via6522.h	Sun Sep 20 20:37:05 1998
+++ linux-2.1.120-alan/arch/m68k/mac/via6522.h	Sun Sep 20 21:02:01 1998
@@ -48,9 +48,10 @@
  *	Register B has the fun stuff in it
  */
 
+#define VIA2B_vMode32	0x08	/* 24/32bit switch - doubles as cache flush */
 #define VIA2B_vPower	0x04	/* Off switch */
-#define VIA2B_vBusLk	0x02
-#define VIA2B_vCDis	0x01
+#define VIA2B_vBusLk	0x02	/* Nubus in use ?? */
+#define VIA2B_vCDis	0x01	/* Cache disable */
 
 /*
  *	The 6522 via is a 2MHz part, and needs a delay. MacOS seems to
diff -urN -X diff-21.excl linux-2.1.120/arch/m68k/mm/memory.c linux-2.1.120-alan/arch/m68k/mm/memory.c
--- linux-2.1.120/arch/m68k/mm/memory.c	Tue Sep  1 12:55:59 1998
+++ linux-2.1.120-alan/arch/m68k/mm/memory.c	Sun Sep 20 21:04:30 1998
@@ -18,6 +18,7 @@
 #include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/io.h>
+#include <asm/machdep.h>
 #ifdef CONFIG_AMIGA
 #include <asm/amigahw.h>
 #endif
@@ -554,6 +555,14 @@
  * this?). So we have to push first and then additionally to invalidate.
  */
 
+#ifdef CONFIG_M68K_L2_CACHE
+/*
+ *	Jes was worried about performance (urhh ???) so its optional
+ */
+ 
+extern void (*mach_l2_flush)(int) = NULL;
+#endif
+ 
 /*
  * cache_clear() semantics: Clear any cache entries for the area in question,
  * without writing back dirty entries first. This is useful if the data will
@@ -593,6 +602,10 @@
 		      "movec %/d0,%/cacr"
 		      : : "i" (FLUSH_I_AND_D)
 		      : "d0");
+#ifdef CONFIG_M68K_L2_CACHE
+    if(mach_l2_flush)
+    	mach_l2_flush(0);
+#endif
 }
 
 
@@ -641,6 +654,10 @@
 		      "movec %/d0,%/cacr"
 		      : : "i" (FLUSH_I)
 		      : "d0");
+#ifdef CONFIG_M68K_L2_CACHE
+    if(mach_l2_flush)
+    	mach_l2_flush(1);
+#endif
 }
 
 
diff -urN -X diff-21.excl linux-2.1.120/drivers/net/Makefile linux-2.1.120-alan/drivers/net/Makefile
--- linux-2.1.120/drivers/net/Makefile	Thu Jul 30 14:03:35 1998
+++ linux-2.1.120-alan/drivers/net/Makefile	Sun Sep 20 20:44:22 1998
@@ -755,10 +755,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
 
@@ -868,6 +868,14 @@
 
 ifeq ($(CONFIG_MACE),y)
 L_OBJS += mace.o
+endif
+
+ifeq ($(CONFIG_MACMACE),y)
+L_OBJS += macmace.o
+endif
+
+ifeq ($(CONFIG_MACSONIC),y)
+L_OBJS += macsonic.o
 endif
 
 ifeq ($(CONFIG_BMAC),y)
diff -urN -X diff-21.excl linux-2.1.120/drivers/net/Space.c linux-2.1.120-alan/drivers/net/Space.c
--- linux-2.1.120/drivers/net/Space.c	Thu Jul 30 14:03:36 1998
+++ linux-2.1.120-alan/drivers/net/Space.c	Sun Sep 20 20:44:22 1998
@@ -106,6 +106,8 @@
 extern int epic100_probe(struct device *dev);
 extern int rtl8139_probe(struct device *dev);
 extern int hplance_probe(struct device *dev);
+extern int mace68k_probe(struct device *dev);
+extern int mac_onboard_sonic_probe(struct device *dev);
 
 /* Gigabit Ethernet adapters */
 extern int yellowfin_probe(struct device *dev);
@@ -378,6 +380,12 @@
 #endif
 #ifdef CONFIG_HPLANCE		/* HP300 internal Ethernet */
 	{hplance_probe, 0},
+#endif
+#ifdef CONFIG_MACMACE
+	{mace68k_probe, 0},
+#endif
+#ifdef CONFIG_MACSONIC
+	{mac_onboard_sonic_probe, 0},
 #endif
 	{NULL, 0},
 };
diff -urN -X diff-21.excl linux-2.1.120/drivers/net/daynaport.c linux-2.1.120-alan/drivers/net/daynaport.c
--- linux-2.1.120/drivers/net/daynaport.c	Sun Sep 20 20:37:06 1998
+++ linux-2.1.120-alan/drivers/net/daynaport.c	Sun Sep 20 20:44:23 1998
@@ -30,6 +30,8 @@
 #include <linux/nubus.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/hwtest.h>
+#include <linux/delay.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -57,6 +59,13 @@
 static void sane_block_output(struct device *dev, int count,
 						   const unsigned char *buf, const int start_page);
 
+static void slow_sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+						int ring_page);
+static void slow_sane_block_input(struct device *dev, int count,
+						  struct sk_buff *skb, int ring_offset);
+static void slow_sane_block_output(struct device *dev, int count,
+						   const unsigned char *buf, const int start_page);
+
 
 #define WD_START_PG	0x00	/* First page of TX buffer */
 #define WD03_STOP_PG	0x20	/* Last page +1 of RX ring */
@@ -81,11 +90,11 @@
 	int regd;
 	int v;
 	
-	if(nubus_hwreg_present(&ptr[0x00])==0)
+	if(hwreg_present(&ptr[0x00])==0)
 		return -EIO;
-	if(nubus_hwreg_present(&ptr[0x0D<<scale])==0)
+	if(hwreg_present(&ptr[0x0D<<scale])==0)
 		return -EIO;
-	if(nubus_hwreg_present(&ptr[0x0D<<scale])==0)
+	if(hwreg_present(&ptr[0x0D<<scale])==0)
 		return -EIO;
 	ptr[0x00]=E8390_NODMA+E8390_PAGE1+E8390_STOP;
 	regd=ptr[0x0D<<scale];
@@ -136,6 +145,51 @@
 }
 
 /*
+ *	Memory probe for 8390 cards
+ */
+ 
+int apple_8390_mem_probe(volatile unsigned short *p)
+{
+	int i, j;
+	/*
+	 *	Algorithm.
+	 *	1.	Check each block size of memory doesn't fault
+	 *	2.	Write a value to it
+	 *	3.	Check all previous blocks are unaffected
+	 */
+	
+	for(i=0;i<2;i++)
+	{
+		volatile unsigned short *m=p+4096*i;
+		/* Unwriteable - we have a fully decoded card and the
+		   RAM end located */
+		   
+		if(hwreg_present(m)==0)
+			return 8192*i;
+			
+		*m=0xA5A0|i;
+		
+		for(j=0;j<i;j++)
+		{
+			/* Partial decode and wrap ? */
+			if(p[4096*j]!=(0xA5A0|j))
+			{
+				/* This is the first misdecode, so it had
+				   one less page than we tried */
+				return 8192*i;
+			}
+ 			j++;
+ 		}
+ 		/* Ok it still decodes.. move on 8K */
+ 	}
+ 	/* 
+ 	 *	We don't look past 16K. That should cover most cards
+ 	 *	and above 16K there isnt really any gain.
+ 	 */
+ 	return 16384;
+ }
+ 		
+/*
  *    Probe for 8390 cards.  
  *    The ns8390_probe1() routine initializes the card and fills the
  *    station address field. On entry base_addr is set, irq is set
@@ -216,16 +270,21 @@
 	/* Apple, Farallon, Asante */
 	if(id==NS8390_APPLE|| id==NS8390_FARALLON || id==NS8390_ASANTE)
 	{
+		int memsize;
+		
 		dev->base_addr=(int)(nubus_slot_addr(slot)+APPLE_8390_BASE);
 		dev->mem_start=(int)(nubus_slot_addr(slot)+APPLE_8390_MEM);
-		dev->mem_end=dev->mem_start+APPLE_MEMSIZE; /* 8K it seems */
+		
+		memsize = apple_8390_mem_probe((void *)dev->mem_start);
+		
+		dev->mem_end=dev->mem_start+memsize;
 		dev->irq=slot;
 		printk("apple/clone: testing board: ");
 
-		printk("memory - ");		
+		printk("%dK memory - ", memsize>>10);		
 
 		i=(void *)dev->mem_start;
-		memset((void *)i,0xAA, DAYNA_MEMSIZE);
+		memset((void *)i,0xAA, memsize);
 		while(i<(volatile unsigned short *)dev->mem_end)
 		{
 			if(*i!=0xAAAA)
@@ -366,8 +425,15 @@
 			ei_status.get_8390_hdr = &dayna_get_8390_hdr;
 			ei_status.reg_offset = fwrd4_offsets;
 			break;
-		case NS8390_APPLE:	/* Apple/Asante/Farallon */
 		case NS8390_FARALLON:
+		case NS8390_APPLE:	/* Apple/Asante/Farallon */
+			/*      16 bit card, register map is reversed */
+			ei_status.reset_8390 = &ns8390_no_reset;
+			ei_status.block_input = &slow_sane_block_input;
+			ei_status.block_output = &slow_sane_block_output;
+			ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+			ei_status.reg_offset = back4_offsets;
+			break;
 		case NS8390_ASANTE:
 			/*      16 bit card, register map is reversed */
 			ei_status.reset_8390 = &ns8390_no_reset;
@@ -442,7 +508,7 @@
 {
 	unsigned char *target=nubus_slot_addr(dev->irq);
 	if (ei_debug > 1) 
-	printk("Need to reset the NS8390 t=%lu...", jiffies);
+		printk("Need to reset the NS8390 t=%lu...", jiffies);
 	ei_status.txing = 0;
 	/* This write resets the card */
 	target[0xC0000]=0;
@@ -585,12 +651,88 @@
 	}
 }
 
+
 static void sane_block_output(struct device *dev, int count, const unsigned char *buf,
 				int start_page)
 {
 	long shmem = (start_page - WD_START_PG)<<8;
 	
 	memcpy((char *)dev->mem_start+shmem, buf, count);
+}
+
+static void word_memcpy_tocard(void *tp, const void *fp, int count)
+{
+	volatile unsigned short *to = tp;
+	const unsigned short *from = fp;
+	
+	count++;
+	count/=2;
+	
+	while(count--)
+		*to++=*from++;
+}
+
+static void word_memcpy_fromcard(void *tp, const void *fp, int count)
+{
+	unsigned short *to = tp;
+	const volatile unsigned short *from = fp;
+	
+	count++;
+	count/=2;
+	
+	while(count--)
+		*to++=*from++;
+}
+
+static void slow_sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
+	word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
+	/* Register endianism - fix here rather than 8390.c */
+	hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
+}
+
+static void slow_sane_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+	unsigned long xfer_start = xfer_base+dev->mem_start;
+
+	if (xfer_start + count > dev->rmem_end) 
+	{
+		/* We must wrap the input move. */
+		int semi_count = dev->rmem_end - xfer_start;
+		word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
+		count -= semi_count;
+		word_memcpy_fromcard(skb->data + semi_count, 
+			(char *)dev->rmem_start, count);
+	}
+	else
+	{
+		word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, count);
+	}
+}
+
+static void slow_sane_block_output(struct device *dev, int count, const unsigned char *buf,
+				int start_page)
+{
+	long shmem = (start_page - WD_START_PG)<<8;
+	
+	word_memcpy_tocard((char *)dev->mem_start+shmem, buf, count);
+#if 0
+	long shmem = (start_page - WD_START_PG)<<8;
+	volatile unsigned short *to=(unsigned short *)(dev->mem_start+shmem);
+	volatile int p;
+	unsigned short *bp=(unsigned short *)buf;
+	
+	count=(count+1)/2;
+	
+	while(count--)
+	{
+		*to++=*bp++;
+		for(p=0;p<10;p++)
+			p++;
+	}
+#endif	
 }
 
 /*
diff -urN -X diff-21.excl linux-2.1.120/drivers/net/jazzsonic.c linux-2.1.120-alan/drivers/net/jazzsonic.c
--- linux-2.1.120/drivers/net/jazzsonic.c	Wed Dec 31 18:00:00 1969
+++ linux-2.1.120-alan/drivers/net/jazzsonic.c	Sun Sep 20 20:44:23 1998
@@ -0,0 +1,260 @@
+/*
+ * jazzsonic.c
+ *
+ * (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 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>
+
+#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
+
+
+/*
+ * 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 */
+};
+
+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 > 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;
+}
+
+/*
+ *	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))
+
+/* 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
+
+
+#include "sonic.c"
diff -urN -X diff-21.excl linux-2.1.120/drivers/net/macmace.c linux-2.1.120-alan/drivers/net/macmace.c
--- linux-2.1.120/drivers/net/macmace.c	Wed Dec 31 18:00:00 1969
+++ linux-2.1.120-alan/drivers/net/macmace.c	Sun Sep 20 20:44:23 1998
@@ -0,0 +1,791 @@
+/*
+ *	Driver for the Macintosh 68K onboard MACE controller with PSC
+ *	driven DMA. The MACE driver code is derived from mace.c. The
+ *	Mac68k theory of operation is courtesy of the MacBSD wizards.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	Copyright (C) 1996 Paul Mackerras.
+ *	Copyright (C) 1998 Alan Cox <alan@redhat.com>
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/mac_psc.h>
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include "mace.h"
+
+#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 */
+
+/* Bits in transmit DMA status */
+#define TX_DMA_ERR	0x80
+
+/* The MACE is simply wired down on a Mac68K box */
+
+#define MACE_BASE	(void *)(0x50F1C000)
+#define MACE_PROM	(void *)(0x50F08001)
+
+struct mace68k_data
+{
+	volatile struct mace *mace;
+	volatile unsigned char *tx_ring;
+	volatile unsigned char *rx_ring;
+	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;
+};
+
+struct mace_frame
+{
+	u16	len;
+	u16	status;
+	u16	rntpc;
+	u16	rcvcc;
+	u32	pad1;
+	u32	pad2;
+	u8	data[1];	
+	/* And frame continues.. */
+};
+
+#define PRIV_BYTES	sizeof(struct mace68k_data)
+
+static int mace68k_open(struct device *dev);
+static int mace68k_close(struct device *dev);
+static int mace68k_xmit_start(struct sk_buff *skb, struct device *dev);
+static struct net_device_stats *mace68k_stats(struct device *dev);
+static void mace68k_set_multicast(struct device *dev);
+static void mace68k_reset(struct device *dev);
+static int mace68k_set_address(struct 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 device *dev);
+static void mace68k_tx_timeout(unsigned long data);
+
+/*
+ *	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.
+ */
+
+/*
+ *	Load a receive DMA channel with a base address and ring length
+ */
+  
+static void psc_load_rxdma_base(int set, void *base)
+{
+	psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
+	psc_write_long(PSC_ENETRD_ADDR + set, (u32)base);
+	psc_write_long(PSC_ENETRD_LEN + set, N_RX_RING);
+	psc_write_word(PSC_ENETRD_CMD + set, 0x9800);
+}
+
+/*
+ *	Reset the receive DMA subsystem
+ */
+  
+static void mace68k_rxdma_reset(struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	volatile struct mace *mace = mp->mace;
+	u8 mcc = mace->maccc;
+	
+	/*
+	 *	Turn off receive
+	 */
+	 
+	mcc&=~ENRCV;
+	mace->maccc=mcc;
+	
+	/*
+	 *	Program the DMA
+	 */
+	
+	psc_write_word(PSC_ENETRD_CTL, 0x8800);
+	psc_load_rxdma_base(0x0, (void *)virt_to_bus(mp->rx_ring));
+	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));
+	psc_write_word(PSC_ENETRD_CTL, 0x0400);
+	
+	mace->maccc=mcc|ENRCV;
+	
+	psc_write_word(PSC_ENETRD_CTL, 0x9800);
+	psc_write_word(PSC_ENETRD_CTL+0x10, 0x9800);
+}
+
+/*
+ *	Reset the transmit DMA subsystem
+ */
+ 
+static void mace68k_txdma_reset(struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	volatile struct mace *mace = mp->mace;
+	u8 mcc = mace->maccc;
+
+	psc_write_word(PSC_ENETWR_CTL,0x8800);
+	
+	mace->maccc = mcc&~ENXMT;
+	psc_write_word(PSC_ENETWR_CTL,0x400);
+	mace->maccc = mcc;
+}
+
+/*
+ *	Disable DMA
+ */
+ 
+static void mace68k_dma_off(struct 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_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);
+}
+
+
+/*
+ *	The prom nibbles are backwards!
+ */
+ 
+extern inline u8 nibbleflip(u8 v)
+{
+	return ((v&0x0F)<<4)|((v>>4)&0x0F);
+}
+
+/*
+ * 	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 device *unused)
+{
+	int j;
+	static int once=0;
+	struct mace68k_data *mp;
+	unsigned char *addr;
+	struct device *dev;
+	unsigned char checksum = 0;
+	
+	/*
+	 *	There can be only one...
+	 */
+	 
+	if(!once)
+		return -ENODEV;
+	
+	if(macintosh_config->ether_type != MAC_ETHER_MACE)
+		return -ENODEV;
+
+	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;
+	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((u32)mp->rx_ring, 16384, KERNELMAP_NOCACHE_NONSER);	
+	
+	printk(".");	
+	/* The transmit buffer needs to be write through */
+	kernel_set_cachemode((u32)mp->tx_ring, 4096, KERNELMAP_NO_COPYBACK);
+
+	printk(" Ok\n");	
+	dev->irq = IRQ_MAC_MACE;
+	printk(KERN_INFO "%s: MACE at", dev->name);
+
+	/*
+	 *	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.
+	 *
+	 *	Look on the bright side, the powermacs have some proms
+	 *	with the bits backwards.
+	 */
+
+	addr = (void *)MACE_PROM;
+		 
+	for (j = 0; j < 6; ++j)
+	{
+		u8 v=nibbleflip(addr[j<<4]);
+		checksum^=v;
+		dev->dev_addr[j] = v;
+		printk("%c%.2x", (j ? ':' : ' '), dev->dev_addr[j]);
+	}
+	for (; j < 8; ++j)
+	{
+		checksum^=nibbleflip(addr[j<<4]);
+	}
+	
+	if(checksum!=0xFF)
+	{
+		printk(" (invalid checksum)\n");
+		return -ENODEV;
+	}		
+	printk("\n");
+
+	/*
+	 *	The interrupt is fixed and comes off the PSC.
+	 */
+	 
+	if (request_irq(dev->irq, mace68k_interrupt, 0, "mace68k", 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, "mace68k-dma",
+			dev))
+	{
+		printk(KERN_ERR "MACE: can't get irq %d\n", IRQ_MAC_MACE_DMA);
+		return -EAGAIN;
+	}
+
+	
+	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;
+
+	ether_setup(dev);
+
+	mp = (struct mace68k_data *) dev->priv;
+	mp->maccc = ENXMT | ENRCV;
+	mp->dma_intr = IRQ_MAC_MACE_DMA;
+
+	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);
+                                        	
+	mace68k_dma_off(dev);
+
+	return -EAGAIN;
+}
+
+/*
+ *	Reset a MACE controller
+ */
+ 
+static void mace68k_reset(struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	volatile struct mace *mb = mp->mace;
+	int i;
+
+	/* soft-reset the chip */
+	mb->biucc = SWRST;
+	udelay(100);
+
+	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 */
+
+	/* 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];
+
+	/* clear the multicast filter */
+	mb->iac = ADDRCHG | LOGADDR;
+
+	while ((mb->iac & ADDRCHG) != 0);
+	
+	for (i = 0; i < 8; ++i)
+		mb->ladrf = 0;
+
+	mb->plscc = PORTSEL_GPSI + ENPLSIO;
+}
+
+/*
+ *	Load the address on a mace controller.
+ */
+ 
+static int mace68k_set_address(struct 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();
+
+	/* 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];
+	/* 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.
+ */
+ 
+static int mace68k_open(struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	volatile struct mace *mb = mp->mace;
+
+	/* reset the chip */
+	mace68k_reset(dev);
+
+	mp->rx_done = 0;
+	mace68k_rxdma_reset(dev);
+
+	/* Activate the Mac DMA engine */
+
+	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
+ */
+ 
+static int mace68k_close(struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	volatile struct mace *mb = mp->mace;
+
+	/* disable rx and tx */
+	mb->maccc = 0;
+	mb->imr = 0xff;		/* disable all intrs */
+
+	/* disable rx and tx dma */
+
+	mace68k_dma_off(dev);
+	return 0;
+}
+
+static inline void mace68k_set_timeout(struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	unsigned long flags;
+
+	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);
+}
+
+/*
+ *	Transmit a frame
+ */
+ 
+static int mace68k_xmit_start(struct sk_buff *skb, struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	/*
+	 *	This may need atomic types ???
+	 */
+	if(mp->tx_count == 0)
+	{
+		dev->tbusy=1;
+		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 device *dev)
+{
+	struct mace68k_data *p = (struct mace68k_data *) dev->priv;
+	return &p->stats;
+}
+
+/*
+ * CRC polynomial - used in working out multicast filter bits.
+ */
+#define CRC_POLY	0xedb88320
+
+static void mace68k_set_multicast(struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	volatile struct mace *mb = mp->mace;
+	int i, j, k, b;
+	unsigned long crc;
+
+	mp->maccc &= ~PROM;
+	if (dev->flags & IFF_PROMISC)
+	{
+		mp->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
+		{
+			for (i = 0; i < 8; i++)
+				multicast_filter[i] = 0;
+			for (i = 0; i < dev->mc_count; i++)
+			{
+				crc = ~0;
+				for (j = 0; j < 6; ++j)
+				{
+					b = dmi->dmi_addr[j];
+					for (k = 0; k < 8; ++k)
+					{
+						if ((crc ^ b) & 1)
+							crc = (crc >> 1) ^ CRC_POLY;
+						else
+							crc >>= 1;
+						b >>= 1;
+					}
+				}
+				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);
+		
+		for (i = 0; i < 8; ++i)
+			mb->ladrf = multicast_filter[i];
+	}
+	/* reset maccc */
+	mb->maccc = mp->maccc;
+}
+
+/*
+ *	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)
+{
+	volatile struct mace *mb = mp->mace;
+	static int mace68k_babbles, mace68k_jabbers;
+
+	if (intr & MPCO)
+		mp->stats.rx_missed_errors += 256;
+	mp->stats.rx_missed_errors += mb->mpc;	/* reading clears it */
+	if (intr & RNTPCO)
+		mp->stats.rx_length_errors += 256;
+	mp->stats.rx_length_errors += mb->rntpc;	/* reading clears it */
+	if (intr & CERR)
+		++mp->stats.tx_heartbeat_errors;
+	if (intr & BABBLE)
+		if (mace68k_babbles++ < 4)
+			printk(KERN_DEBUG "mace: babbling transmitter\n");
+	if (intr & JABBER)
+		if (mace68k_jabbers++ < 4)
+			printk(KERN_DEBUG "mace: jabbering transceiver\n");
+}
+
+/*
+ *	A transmit error has occured. (We kick the transmit side from
+ *	the DMA completion)
+ */
+ 
+static void mace68k_xmit_error(struct device *dev)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	volatile struct mace *mb = mp->mace;
+	u8 xmtfs, xmtrc;
+	
+	xmtfs = mb->xmtfs;
+	xmtrc = mb->xmtrc;
+	
+	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);
+		}
+		if(xmtfs & RTRY)
+			mp->stats.collisions++;
+	}			
+	mark_bh(NET_BH);
+}
+
+/*
+ *	A receive interrupt occured.
+ */
+ 
+static void mace68k_recv_interrupt(struct device *dev)
+{
+//	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+//	volatile struct mace *mb = mp->mace;
+}
+
+/*
+ *	Process the chip interrupt
+ */
+ 
+static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = (struct device *) dev_id;
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	volatile struct mace *mb = mp->mace;
+	u8 ir;
+	
+	ir = mb->ir;
+	mace68k_handle_misc_intrs(mp, ir);
+	
+	if(ir&XMTINT)
+		mace68k_xmit_error(dev);
+	if(ir&RCVINT)
+		mace68k_recv_interrupt(dev);
+}
+
+static void mace68k_tx_timeout(unsigned long data)
+{
+//	struct device *dev = (struct device *) data;
+//	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+//	volatile struct mace *mb = mp->mace;
+}
+
+/*
+ *	Handle a newly arrived frame
+ */
+ 
+static void mace_dma_rx_frame(struct device *dev, struct mace_frame *mf)
+{
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+	struct sk_buff *skb;
+
+	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))
+		mp->stats.rx_errors++;
+		
+	if(mf->status&RS_CLSN)
+		mp->stats.collisions++;
+	if(mf->status&RS_FRAMERR)
+		mp->stats.rx_frame_errors++;
+	if(mf->status&RS_FCSERR)
+		mp->stats.rx_crc_errors++;
+		
+	skb = dev_alloc_skb(mf->len+2);
+	if(skb==NULL)
+	{
+		mp->stats.rx_dropped++;
+		return;
+	}
+	skb_reserve(skb,2);
+	memcpy(skb_put(skb, mf->len), mf->data, mf->len);
+	
+	skb->protocol = eth_type_trans(skb, dev);
+	netif_rx(skb);
+	mp->stats.rx_packets++;
+	mp->stats.rx_bytes+=mf->len;
+}
+
+/*
+ *	The PSC has passed us a DMA interrupt event.
+ */
+ 
+static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = (struct device *) dev_id;
+	struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+
+	u32 psc_status;
+	
+	/* It seems this must be allowed to stabilise ?? */
+	
+	while((psc_status=psc_read_long(0x0804))!=psc_read_long(0x0804));
+
+	/*
+	 *	Was this an ethernet event ?
+	 */
+	 	
+	if(psc_status&0x60000000)
+	{
+		/*
+		 *	Process the read queue
+		 */
+		 
+		u16 psc_status = psc_read_word(PSC_ENETRD_CTL);
+		
+		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);
+			}
+			
+			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);
+			}
+					
+		}
+		
+		/*
+		 *	Process the write queue
+		 */
+		 
+		psc_status = psc_read_word(PSC_ENETWR_CTL);
+		if(psc_status&0x2000)
+			mace68k_txdma_reset(dev);
+		else if(psc_status&0x0100)
+		{
+			psc_write_word(PSC_ENETWR_CMD+mp->tx_slot, 0x100);
+			mp->tx_slot^=16;
+			mp->tx_count++;
+			dev->tbusy = 0;
+			mark_bh(NET_BH);
+		}
+	}
+}
diff -urN -X diff-21.excl linux-2.1.120/drivers/net/macsonic.c linux-2.1.120-alan/drivers/net/macsonic.c
--- linux-2.1.120/drivers/net/macsonic.c	Wed Dec 31 18:00:00 1969
+++ linux-2.1.120-alan/drivers/net/macsonic.c	Sun Sep 20 20:44:23 1998
@@ -0,0 +1,246 @@
+/*
+ * macsonic.c
+ *
+ * (C) 1998 Alan Cox
+ *
+ * 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.
+ */
+
+#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 <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 "sonic.h"
+
+extern int mac_onboard_sonic_probe(struct device *unused);
+
+/*
+ * Macros to access SONIC registers
+ */
+ 
+#define MAC_SONIC_REGISTERS	0x50F0A000
+#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.
+ */
+
+#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
+
+
+static int sonic_debug = 6;
+
+__initfunc(int mac_onboard_sonic_probe(struct device *unused))
+{
+	struct device *dev;
+	unsigned int silicon_revision;
+	unsigned int val;
+	struct sonic_local *lp;
+	int i;
+	int base_addr = MAC_SONIC_REGISTERS;
+	static int one=0;
+	
+	if(++one!=1)	/* Only one is allowed */
+		return;
+	
+	printk(KERN_INFO "Checking for internal Macintosh ethernet..");
+
+	if (macintosh_config->ether_type != MAC_ETHER_SONIC)
+	{
+		printk("none.\n");
+		return -ENODEV;
+	}
+	
+	printk("yes\n");
+	
+	/*
+	 * 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);
+
+	dev = init_etherdev(0, sizeof(struct sonic_local));
+	if(dev==NULL)
+		return -ENOMEM;
+
+	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 = 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.
+	 */
+
+	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!
+	 */
+
+	SONIC_WRITE(SONIC_ISR, SONIC_IMR_DEFAULT);
+
+	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(":");
+	}
+
+	/*
+	 *                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))
+	{
+		printk("ERROR (INVALID MAC)\n");
+		return -EIO;
+	}
+	printk(" IRQ %d\n", MAC_SONIC_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));
+
+		lp->cda_laddr = (u32)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;
+		}
+		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 -EAGAIN;
+}
+
+/*
+ *    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"
diff -urN -X diff-21.excl linux-2.1.120/drivers/net/sonic.c linux-2.1.120-alan/drivers/net/sonic.c
--- linux-2.1.120/drivers/net/sonic.c	Thu Jul 30 14:03:45 1998
+++ linux-2.1.120-alan/drivers/net/sonic.c	Sun Sep 20 20:44:23 1998
@@ -8,9 +8,8 @@
  * 
  * (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 =
@@ -22,269 +21,7 @@
  * 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.
@@ -293,6 +30,7 @@
  *  registers that "should" only need to be set once at boot, so that
  *  there is non-reboot way to recover if something goes wrong.
  */
+
 static int sonic_open(struct device *dev)
 {
     if (sonic_debug > 2)
@@ -309,7 +47,7 @@
  * 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, SA_INTERRUPT, "sonic", dev)) {
 	printk ("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
 	return EAGAIN;
     }
@@ -351,7 +89,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;
 }
@@ -413,7 +151,6 @@
     lp->tx_skb[entry] = skb;
     
     length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
-    flush_cache_all();
     
     /*
      * Setup the transmit descriptor and issue the transmit command.
@@ -430,10 +167,11 @@
 	lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS;
     
     lp->cur_tx++;
-    lp->stats.tx_bytes += length;
     
     if (sonic_debug > 2)
-      printk("sonic_send_packet: issueing Tx command\n");
+      printk("sonic_send_packet: issuing Tx command\n");
+
+    flush_cache_all();
 
     SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP);
 
@@ -588,8 +326,8 @@
 	  printk ("status %x, cur_rx %d, cur_rra %d\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_ptr = (char *)sonic_chiptomem((lp->rda[entry].rx_pktptr_h << 16) +
+	    		lp->rda[entry].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,
@@ -611,7 +349,6 @@
 	    skb->protocol=eth_type_trans(skb,dev);
 	    netif_rx(skb);			/* pass the packet to upper layers */
 	    lp->stats.rx_packets++;
-	    lp->stats.rx_bytes += pkt_len;
 	    
 	} else {
 	    /* This should only happen, if we enable accepting broken packets. */
@@ -632,7 +369,7 @@
 	}
     }
   
-    /* If any worth-while packets have been received, dev_rint()
+    /* If any worth-while packets have been received, netif_rx()
      has done a mark_bh(NET_BH) for us and will work on them
      when we get to the bottom-half routine. */
     return;
diff -urN -X diff-21.excl linux-2.1.120/drivers/net/sonic.h linux-2.1.120-alan/drivers/net/sonic.h
--- linux-2.1.120/drivers/net/sonic.h	Thu Jul 17 10:45:23 1997
+++ linux-2.1.120-alan/drivers/net/sonic.h	Sun Sep 20 20:44:24 1998
@@ -14,15 +14,6 @@
 #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
@@ -322,5 +313,47 @@
   u16 pad;
 } sonic_cda_t;
 
+/*
+ * 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)
+
+/* 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;
+};
+
+/* 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);
 
 #endif /* SONIC_H */
diff -urN -X diff-21.excl linux-2.1.120/drivers/nubus/nubus.c linux-2.1.120-alan/drivers/nubus/nubus.c
--- linux-2.1.120/drivers/nubus/nubus.c	Mon Sep  7 09:39:17 1998
+++ linux-2.1.120-alan/drivers/nubus/nubus.c	Sun Sep 20 21:13:09 1998
@@ -12,8 +12,11 @@
 #include <asm/setup.h>
 #include <asm/system.h>
 #include <asm/page.h>
+#include <asm/hwtest.h>
 /* for LCIII stuff; better find a general way like MACH_HAS_NUBUS */
 #include <asm/macintosh.h>
+#include <linux/proc_fs.h>
+
 
 #undef LCIII_WEIRDNESS
  
@@ -24,49 +27,6 @@
  *				-- Alan
  */
  
- 
- 
-/* This function tests for the presence of an address, specially a
- * hardware register address. It is called very early in the kernel
- * initialization process, when the VBR register isn't set up yet. On
- * an Atari, it still points to address 0, which is unmapped. So a bus
- * error would cause another bus error while fetching the exception
- * vector, and the CPU would do nothing at all. So we needed to set up
- * a temporary VBR and a vector table for the duration of the test.
- *
- * See the atari/config.c code we nicked it from for more clues.
- */
-
-int nubus_hwreg_present( volatile void *regp )
-{
-    int	ret = 0;
-    long	save_sp, save_vbr;
-    long	tmp_vectors[3];
-    unsigned long flags;
-    
-    save_flags(flags);
-    cli();
-
-    __asm__ __volatile__
-	(	"movec	%/vbr,%2\n\t"
-		"movel	#Lberr1,%4@(8)\n\t"
-                "movec	%4,%/vbr\n\t"
-		"movel	%/sp,%1\n\t"
-		"moveq	#0,%0\n\t"
-		"tstb	%3@\n\t"  
-		"nop\n\t"
-		"moveq	#1,%0\n"
-                "Lberr1:\n\t"
-		"movel	%1,%/sp\n\t"
-		"movec	%2,%/vbr"
-		: "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
-		: "a" (regp), "a" (tmp_vectors)
-                );
-    restore_flags(flags);
-    return( ret );
-}
-
-
 
 /*
  *	Yes this sucks. The ROM can appear on arbitary bytes of the long
@@ -102,7 +62,7 @@
 {
 	unsigned char *p=*ptr;
 	
-	if(len>8192)
+	if(len>65536)
 		printk("rewind of %d!\n", len);
 	while(len)
 	{
@@ -119,7 +79,7 @@
 static void nubus_advance(unsigned char **ptr, int len, int map)
 {
 	unsigned char *p=*ptr;
-	if(len>8192)
+	if(len>65536)
 		printk("advance of %d!\n", len);
 	while(len)
 	{
@@ -373,7 +333,7 @@
 	{
 		rp--;
 		
-		if(!nubus_hwreg_present(rp))
+		if(!hwreg_present(rp))
 			continue;
 			
 		dp=*rp;
@@ -594,6 +554,52 @@
 	return ng;
 }
 
+#ifdef CONFIG_PROC_FS
+
+/*
+ *	/proc for Nubus devices
+ */
+ 
+static int sprint_nubus_config(int slot, char *ptr, int len)
+{
+	if(len<150)
+		return -1;
+	sprintf(ptr, "Device: %s %s\n", nubus_slots[slot].slot_cardname,
+		(nubus_slots[slot].slot_flags&NUBUS_DEVICE_ACTIVE)?
+			"[active]":"[unused]");
+	return strlen(ptr);
+}
+
+int get_nubus_list(char *buf)
+{
+	int nprinted, len, size;
+	int slot;
+#define MSG "\nwarning: page-size limit reached!\n"
+
+	/* reserve same for truncation warning message: */
+	size  = PAGE_SIZE - (strlen(MSG) + 1);
+	len   = sprintf(buf, "Nubus devices found:\n");
+
+	for (slot=0; slot< 16; slot++) 
+	{
+		if(!(nubus_slots[slot].slot_flags&NUBUS_DEVICE_PRESENT))
+			continue;
+		nprinted = sprint_nubus_config(slot, buf + len, size - len);
+		if (nprinted < 0) {
+			return len + sprintf(buf + len, MSG);
+		}
+		len += nprinted;
+	}
+	return len;
+}
+
+static struct proc_dir_entry proc_nubus = {
+	PROC_NUBUS, 5, "nubus",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations
+};
+#endif
+
 void nubus_init(void)
 {
 	/* 
@@ -624,4 +630,7 @@
 	nubus_init_via();
 	printk("Scanning nubus slots.\n");
 	nubus_probe_bus();
+	proc_register(&proc_root, &proc_nubus);
 }
+
+	
diff -urN -X diff-21.excl linux-2.1.120/fs/proc/array.c linux-2.1.120-alan/fs/proc/array.c
--- linux-2.1.120/fs/proc/array.c	Wed Sep  2 03:44:56 1998
+++ linux-2.1.120-alan/fs/proc/array.c	Sun Sep 20 20:44:24 1998
@@ -1224,6 +1224,11 @@
   	        case PROC_PCI:
 			return get_pci_list(page);
 #endif
+
+#ifdef CONFIG_NUBUS
+		case PROC_NUBUS:
+			return get_nubus_list(page);
+#endif			
 			
 		case PROC_CPUINFO:
 			return get_cpuinfo(page);
diff -urN -X diff-21.excl linux-2.1.120/fs/sysv/balloc.c linux-2.1.120-alan/fs/sysv/balloc.c
--- linux-2.1.120/fs/sysv/balloc.c	Sat Aug 24 07:42:56 1996
+++ linux-2.1.120-alan/fs/sysv/balloc.c	Sun Sep 20 20:44:24 1998
@@ -52,8 +52,8 @@
 	 * into this block being freed:
 	 */
 	if (*sb->sv_sb_flc_count == sb->sv_flc_size) {
-		unsigned short * flc_count;
-		unsigned long * flc_blocks;
+		u16 * flc_count;
+		u32 * flc_blocks;
 
 		bh = sv_getblk(sb, sb->s_dev, block);
 		if (!bh) {
@@ -154,8 +154,8 @@
 		return 0;
 	}
 	if (*sb->sv_sb_flc_count == 0) { /* the last block continues the free list */
-		unsigned short * flc_count;
-		unsigned long * flc_blocks;
+		u16 * flc_count;
+		u32 * flc_blocks;
 
 		if (!(bh = sv_bread(sb, sb->s_dev, block))) {
 			printk("sysv_new_block: cannot read free-list block\n");
@@ -247,8 +247,8 @@
 		}
 		/* block = sb->sv_sb_flc_blocks[0], the last block continues the free list */
 		while (1) {
-			unsigned short * flc_count;
-			unsigned long * flc_blocks;
+			u16 * flc_count;
+			u32 * flc_blocks;
 
 			if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
 				printk("sysv_count_free_blocks: new block %d is not in data zone\n",block);
diff -urN -X diff-21.excl linux-2.1.120/fs/sysv/fsync.c linux-2.1.120-alan/fs/sysv/fsync.c
--- linux-2.1.120/fs/sysv/fsync.c	Sat Sep 20 07:26:24 1997
+++ linux-2.1.120-alan/fs/sysv/fsync.c	Sun Sep 20 20:44:24 1998
@@ -26,10 +26,10 @@
 /* Sync one block. The block number is
  * from_coh_ulong(*blockp) if convert=1, *blockp if convert=0.
  */
-static int sync_block (struct inode * inode, unsigned long * blockp, int convert, int wait)
+static int sync_block (struct inode * inode, u32 *blockp, int convert, int wait)
 {
 	struct buffer_head * bh;
-	unsigned long tmp, block;
+	u32 tmp, block;
 	struct super_block * sb;
 
 	block = tmp = *blockp;
@@ -59,11 +59,11 @@
 }
 
 /* Sync one block full of indirect pointers and read it because we'll need it. */
-static int sync_iblock (struct inode * inode, unsigned long * iblockp, int convert,
+static int sync_iblock (struct inode * inode, u32 * iblockp, int convert,
 			struct buffer_head * *bh, int wait)
 {
 	int rc;
-	unsigned long tmp, block;
+	u32 tmp, block;
 
 	*bh = NULL;
 	block = tmp = *iblockp;
@@ -101,7 +101,7 @@
 	return err;
 }
 
-static int sync_indirect(struct inode *inode, unsigned long *iblockp, int convert, int wait)
+static int sync_indirect(struct inode *inode, u32 *iblockp, int convert, int wait)
 {
 	int i;
 	struct buffer_head * ind_bh;
@@ -115,7 +115,7 @@
 	sb = inode->i_sb;
 	for (i = 0; i < sb->sv_ind_per_block; i++) {
 		rc = sync_block (inode,
-				 ((unsigned long *) ind_bh->b_data) + i, sb->sv_convert,
+				 ((u32 *) ind_bh->b_data) + i, sb->sv_convert,
 				 wait);
 		if (rc > 0)
 			break;
@@ -126,7 +126,7 @@
 	return err;
 }
 
-static int sync_dindirect(struct inode *inode, unsigned long *diblockp, int convert,
+static int sync_dindirect(struct inode *inode, u32 *diblockp, int convert,
 			  int wait)
 {
 	int i;
@@ -141,7 +141,7 @@
 	sb = inode->i_sb;
 	for (i = 0; i < sb->sv_ind_per_block; i++) {
 		rc = sync_indirect (inode,
-				    ((unsigned long *) dind_bh->b_data) + i, sb->sv_convert,
+				    ((u32 *) dind_bh->b_data) + i, sb->sv_convert,
 				    wait);
 		if (rc > 0)
 			break;
@@ -152,7 +152,7 @@
 	return err;
 }
 
-static int sync_tindirect(struct inode *inode, unsigned long *tiblockp, int convert,
+static int sync_tindirect(struct inode *inode, u32 *tiblockp, int convert,
 			  int wait)
 {
 	int i;
@@ -167,7 +167,7 @@
 	sb = inode->i_sb;
 	for (i = 0; i < sb->sv_ind_per_block; i++) {
 		rc = sync_dindirect (inode,
-				     ((unsigned long *) tind_bh->b_data) + i, sb->sv_convert,
+				     ((u32 *) tind_bh->b_data) + i, sb->sv_convert,
 				     wait);
 		if (rc > 0)
 			break;
diff -urN -X diff-21.excl linux-2.1.120/fs/sysv/inode.c linux-2.1.120-alan/fs/sysv/inode.c
--- linux-2.1.120/fs/sysv/inode.c	Thu Apr  9 04:51:19 1998
+++ linux-2.1.120-alan/fs/sysv/inode.c	Sun Sep 20 20:44:25 1998
@@ -30,7 +30,7 @@
 #include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/init.h>
-
+#include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
 #if 0
@@ -648,8 +648,8 @@
 static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
 {
 	struct super_block *sb;
-	unsigned long tmp;
-	unsigned long *p;
+	u32 tmp;
+	u32 *p;
 	struct buffer_head * result;
 
 	sb = inode->i_sb;
@@ -684,7 +684,7 @@
 	struct buffer_head * bh, int nr, int create)
 {
 	struct super_block *sb;
-	unsigned long tmp, block;
+	u32 tmp, block;
 	sysv_zone_t *p;
 	struct buffer_head * result;
 
@@ -782,26 +782,43 @@
 	return NULL;
 }
 
+#ifdef __BIG_ENDIAN
+
+static inline unsigned long read3byte (unsigned char * p)
+{
+	return (p[2] | (p[1]<<8) | (p[0]<<16));
+}
+
+static inline void write3byte (unsigned char *p , unsigned long val)
+{
+	p[2]=val&0xFF;
+	p[1]=(val>>8)&0xFF;
+	p[0]=(val>>16)&0xFF;
+}
+
+#else
 
-static inline unsigned long read3byte (char * p)
+static inline unsigned long read3byte (unsigned char * p)
 {
 	return (unsigned long)(*(unsigned short *)p)
 	     | (unsigned long)(*(unsigned char *)(p+2)) << 16;
 }
 
-static inline void write3byte (char * p, unsigned long val)
+static inline void write3byte (unsigned char * p, unsigned long val)
 {
 	*(unsigned short *)p = (unsigned short) val;
 	*(unsigned char *)(p+2) = val >> 16;
 }
 
-static inline unsigned long coh_read3byte (char * p)
+#endif
+
+static inline unsigned long coh_read3byte (unsigned char * p)
 {
 	return (unsigned long)(*(unsigned char *)p) << 16
 	     | (unsigned long)(*(unsigned short *)(p+1));
 }
 
-static inline void coh_write3byte (char * p, unsigned long val)
+static inline void coh_write3byte (unsigned char * p, unsigned long val)
 {
 	*(unsigned char *)p = val >> 16;
 	*(unsigned short *)(p+1) = (unsigned short) val;
diff -urN -X diff-21.excl linux-2.1.120/fs/sysv/truncate.c linux-2.1.120-alan/fs/sysv/truncate.c
--- linux-2.1.120/fs/sysv/truncate.c	Thu Jul  9 03:41:43 1998
+++ linux-2.1.120-alan/fs/sysv/truncate.c	Sun Sep 20 20:44:25 1998
@@ -41,8 +41,8 @@
 {
 	struct super_block * sb;
 	unsigned int i;
-	unsigned long * p;
-	unsigned long block;
+	u32 * p;
+	u32 block;
 	struct buffer_head * bh;
 	int retry = 0;
 
@@ -71,7 +71,7 @@
 	return retry;
 }
 
-static int trunc_indirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
+static int trunc_indirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt)
 {
 	unsigned long indtmp, indblock;
 	struct super_block * sb;
@@ -140,14 +140,14 @@
 	return retry;
 }
 
-static int trunc_dindirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
+static int trunc_dindirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt)
 {
-	unsigned long indtmp, indblock;
+	u32 indtmp, indblock;
 	struct super_block * sb;
 	struct buffer_head * indbh;
 	unsigned int i;
 	sysv_zone_t * ind;
-	unsigned long tmp, block;
+	u32 tmp, block;
 	int retry = 0;
 
 	indblock = indtmp = *p;
@@ -197,14 +197,14 @@
 	return retry;
 }
 
-static int trunc_tindirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
+static int trunc_tindirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt)
 {
-	unsigned long indtmp, indblock;
+	u32 indtmp, indblock;
 	struct super_block * sb;
 	struct buffer_head * indbh;
 	unsigned int i;
 	sysv_zone_t * ind;
-	unsigned long tmp, block;
+	u32 tmp, block;
 	int retry = 0;
 
 	indblock = indtmp = *p;
diff -urN -X diff-21.excl linux-2.1.120/include/asm-m68k/init.h linux-2.1.120-alan/include/asm-m68k/init.h
--- linux-2.1.120/include/asm-m68k/init.h	Wed Sep  9 02:30:04 1998
+++ linux-2.1.120-alan/include/asm-m68k/init.h	Sun Sep 20 20:44:25 1998
@@ -3,7 +3,7 @@
 
 #include <linux/config.h>
 
-#ifndef CONFIG_KGDB
+#if !defined(CONFIG_KGDB) && !defined(CONFIG_FTRACE)
 
 #define __init __attribute__ ((__section__ (".text.init")))
 #define __initdata __attribute__ ((__section__ (".data.init")))
diff -urN -X diff-21.excl linux-2.1.120/include/asm-m68k/mac_psc.h linux-2.1.120-alan/include/asm-m68k/mac_psc.h
--- linux-2.1.120/include/asm-m68k/mac_psc.h	Wed Dec 31 18:00:00 1969
+++ linux-2.1.120-alan/include/asm-m68k/mac_psc.h	Sun Sep 20 20:44:25 1998
@@ -0,0 +1,73 @@
+/*
+ *	Apple Peripheral System Controller (PSC)
+ *
+ *	The PSC is used on the AV Macs to control IO functions not handled
+ *	by the VIAs (Ethernet, DSP, SCC).
+ */
+ 
+#define PSCBASE		0x50F31000
+
+/*
+ *	The IER/IFR registers work like the VIA, except that it has 4
+ *	of them each on different interrupt levels.
+ */
+ 
+#define pIFR3		0x130
+#define pIFR4		0x140
+#define pIFR5		0x150
+#define pIFR6		0x160
+
+#define pIER3		0x134
+#define pIER4		0x144
+#define pIER5		0x154
+#define pIER6		0x164
+
+/*
+ *	Ethernet Control Registers
+ */
+ 
+#define PSC_ENETRD_CTL  0xc10
+#define PSC_ENETWR_CTL  0xc20
+
+/*
+ *	Receive DMA channel (add +0x10 for 2nd channel)
+ */
+ 
+#define PSC_ENETRD_ADDR 0x1020 
+#define PSC_ENETRD_LEN  0x1024
+#define PSC_ENETRD_CMD  0x1028
+
+/*
+ *	Transmit DMA channel (add +0x10 for 2nd channel)
+ */
+ 
+#define PSC_ENETWR_ADDR 0x1040
+#define PSC_ENETWR_LEN  0x1044
+#define PSC_ENETWR_CMD  0x1048
+
+/*
+ *	Access functions
+ */
+ 
+extern volatile unsigned char *psc;
+
+extern inline void psc_write_word(int offset, u16 data)
+{
+	*((volatile u16 *)(psc+offset)) = data;
+}
+
+extern inline void psc_write_long(int offset, u32 data)
+{
+	*((volatile u32 *)(psc+offset)) = data;
+}
+
+extern inline u16 psc_read_word(int offset)
+{
+	return *((volatile u16 *)(psc+offset));
+}
+
+extern inline u32 psc_read_long(int offset)
+{
+	return *((volatile u32 *)(psc+offset));
+}
+
diff -urN -X diff-21.excl linux-2.1.120/include/asm-m68k/machdep.h linux-2.1.120-alan/include/asm-m68k/machdep.h
--- linux-2.1.120/include/asm-m68k/machdep.h	Sun Sep 20 20:37:08 1998
+++ linux-2.1.120-alan/include/asm-m68k/machdep.h	Sun Sep 20 20:44:25 1998
@@ -39,6 +39,7 @@
 extern void (*mach_floppy_setup)(char *, int *);
 extern void (*mach_floppy_eject)(void);
 extern void (*mach_heartbeat) (int);
+extern void (*mach_l2_flush) (int);
 extern int mach_sysrq_key;
 extern int mach_sysrq_shift_state;
 extern int mach_sysrq_shift_mask;
diff -urN -X diff-21.excl linux-2.1.120/include/asm-m68k/segment.h linux-2.1.120-alan/include/asm-m68k/segment.h
--- linux-2.1.120/include/asm-m68k/segment.h	Fri Dec 12 15:36:53 1997
+++ linux-2.1.120-alan/include/asm-m68k/segment.h	Sun Sep 20 20:44:25 1998
@@ -29,11 +29,19 @@
  * Get/set the SFC/DFC registers for MOVES instructions
  */
 
+#ifdef CONFIG_FTRACE
+extern void do_ftrace(unsigned long);
+extern void _mcount (unsigned long n);
+#endif
+
 static inline mm_segment_t get_fs(void)
 {
 	mm_segment_t _v;
 	__asm__ ("movec %/dfc,%0":"=r" (_v.seg):);
-
+#ifdef CONFIG_FTRACE
+	do_ftrace(0xfe000000 | _v.seg);
+	_mcount(0);
+#endif
 	return _v;
 }
 
@@ -48,6 +56,10 @@
 	__asm__ __volatile__ ("movec %0,%/sfc\n\t"
 			      "movec %0,%/dfc\n\t"
 			      : /* no outputs */ : "r" (val.seg) : "memory");
+#ifdef CONFIG_FTRACE
+	do_ftrace(0xff000000 | val.seg);
+	_mcount(0);
+#endif
 }
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
diff -urN -X diff-21.excl linux-2.1.120/include/linux/proc_fs.h linux-2.1.120-alan/include/linux/proc_fs.h
--- linux-2.1.120/include/linux/proc_fs.h	Wed Sep  9 02:30:03 1998
+++ linux-2.1.120-alan/include/linux/proc_fs.h	Sun Sep 20 20:44:26 1998
@@ -23,6 +23,7 @@
 	PROC_CPUINFO,
 	PROC_PCI,
 	PROC_MCA,
+	PROC_NUBUS,
 	PROC_SELF,	/* will change inode # */
 	PROC_NET,
         PROC_SCSI,
diff -urN -X diff-21.excl linux-2.1.120/include/linux/sysv_fs.h linux-2.1.120-alan/include/linux/sysv_fs.h
--- linux-2.1.120/include/linux/sysv_fs.h	Wed Sep  9 03:00:03 1998
+++ linux-2.1.120-alan/include/linux/sysv_fs.h	Sun Sep 20 20:44:26 1998
@@ -37,28 +37,28 @@
    as { byte2, byte3, byte0, byte1 }. We need conversions.
 */
 
-typedef unsigned long coh_ulong;
+typedef u32 coh_ulong;
 
-static inline coh_ulong to_coh_ulong (unsigned long x)
+static inline coh_ulong to_coh_ulong (u32 x)
 {
 	return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
 }
 
-static inline unsigned long from_coh_ulong (coh_ulong x)
+static inline u32 from_coh_ulong (coh_ulong x)
 {
 	return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
 }
 
 /* inode numbers are 16 bit */
 
-typedef unsigned short sysv_ino_t;
+typedef u16 sysv_ino_t;
 
 /* Block numbers are 24 bit, sometimes stored in 32 bit.
    On Coherent FS, they are always stored in PDP-11 manner: the least
    significant 16 bits come last.
 */
 
-typedef unsigned long sysv_zone_t;
+typedef u32 sysv_zone_t;
 
 /* Among the blocks ... */
 /* Xenix FS, Coherent FS: block 0 is the boot block, block 1 the super-block.
@@ -75,36 +75,36 @@
 #define XENIX_NICINOD	100	/* number of inode cache entries */
 #define XENIX_NICFREE	100	/* number of free block list chunk entries */
 struct xenix_super_block {
-	unsigned short s_isize; /* index of first data zone */
-	unsigned long  s_fsize __packed2__; /* total number of zones of this fs */
+	u16		s_isize; /* index of first data zone */
+	u32		s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
-	unsigned short s_nfree;	/* number of free blocks in s_free, <= XENIX_NICFREE */
-	unsigned long  s_free[XENIX_NICFREE]; /* first free block list chunk */
+	u16		s_nfree;	/* number of free blocks in s_free, <= XENIX_NICFREE */
+	u32		s_free[XENIX_NICFREE]; /* first free block list chunk */
 	/* the cache of free inodes: */
-	unsigned short s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
-	sysv_ino_t     s_inode[XENIX_NICINOD]; /* some free inodes */
+	u16		s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
+	sysv_ino_t	s_inode[XENIX_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
-	char	       s_flock;	/* lock during free block list manipulation */
-	char	       s_ilock;	/* lock during inode cache manipulation */
-	char	       s_fmod;	/* super-block modified flag */
-	char	       s_ronly;	/* flag whether fs is mounted read-only */
-	unsigned long  s_time __packed2__; /* time of last super block update */
-	unsigned long  s_tfree __packed2__; /* total number of free zones */
-	unsigned short s_tinode;	/* total number of free inodes */
-	short	       s_dinfo[4];	/* device information ?? */
-	char	       s_fname[6];	/* file system volume name */
-	char	       s_fpack[6];	/* file system pack name */
-	char	       s_clean;		/* set to 0x46 when filesystem is properly unmounted */
-	char	       s_fill[371];
-	long	       s_magic;		/* version of file system */
-	long	       s_type;		/* type of file system: 1 for 512 byte blocks
+	char		s_flock;	/* lock during free block list manipulation */
+	char		s_ilock;	/* lock during inode cache manipulation */
+	char		s_fmod;		/* super-block modified flag */
+	char		s_ronly;	/* flag whether fs is mounted read-only */
+	u32		s_time __packed2__; /* time of last super block update */
+	u32		s_tfree __packed2__; /* total number of free zones */
+	u16		s_tinode;	/* total number of free inodes */
+	s16		s_dinfo[4];	/* device information ?? */
+	char		s_fname[6];	/* file system volume name */
+	char		s_fpack[6];	/* file system pack name */
+	char		s_clean;	/* set to 0x46 when filesystem is properly unmounted */
+	char		s_fill[371];
+	s32		s_magic;	/* version of file system */
+	s32		s_type;		/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
 };
 
 /* Xenix free list block on disk */
 struct xenix_freelist_chunk {
-	unsigned short fl_nfree;	/* number of free blocks in fl_free, <= XENIX_NICFREE] */
-	unsigned long  fl_free[XENIX_NICFREE] __packed2__;
+	u16	fl_nfree;	/* number of free blocks in fl_free, <= XENIX_NICFREE] */
+	u32	fl_free[XENIX_NICFREE] __packed2__;
 };
 
 /* SystemV FS comes in two variants:
@@ -116,116 +116,120 @@
 
 /* SystemV4 super-block data on disk */
 struct sysv4_super_block {
-	unsigned short s_isize; /* index of first data zone */
-	unsigned long  s_fsize;	/* total number of zones of this fs */
+	u16	s_isize;	/* index of first data zone */
+	u16	s_pad0;
+	u32	s_fsize;	/* total number of zones of this fs */
 	/* the start of the free block list: */
-	unsigned short s_nfree;	/* number of free blocks in s_free, <= SYSV_NICFREE */
-	unsigned long  s_free[SYSV_NICFREE]; /* first free block list chunk */
+	u16	s_nfree;	/* number of free blocks in s_free, <= SYSV_NICFREE */
+	u16	s_pad1;
+	u32	s_free[SYSV_NICFREE]; /* first free block list chunk */
 	/* the cache of free inodes: */
-	unsigned short s_ninode; /* number of free inodes in s_inode, <= SYSV_NICINOD */
+	u16	s_ninode;	/* number of free inodes in s_inode, <= SYSV_NICINOD */
+	u16	s_pad2;
 	sysv_ino_t     s_inode[SYSV_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
-	char	       s_flock;	/* lock during free block list manipulation */
-	char	       s_ilock;	/* lock during inode cache manipulation */
-	char	       s_fmod;	/* super-block modified flag */
-	char	       s_ronly;	/* flag whether fs is mounted read-only */
-	unsigned long  s_time;	/* time of last super block update */
-	short	       s_dinfo[4];	/* device information ?? */
-	unsigned long  s_tfree;	/* total number of free zones */
-	unsigned short s_tinode;	/* total number of free inodes */
-	char	       s_fname[6];	/* file system volume name */
-	char	       s_fpack[6];	/* file system pack name */
-	long	       s_fill[12];
-	long	       s_state;		/* file system state: 0x7c269d38-s_time means clean */
-	long	       s_magic;		/* version of file system */
-	long	       s_type;		/* type of file system: 1 for 512 byte blocks
+	char	s_flock;	/* lock during free block list manipulation */
+	char	s_ilock;	/* lock during inode cache manipulation */
+	char	s_fmod;		/* super-block modified flag */
+	char	s_ronly;	/* flag whether fs is mounted read-only */
+	u32	s_time;		/* time of last super block update */
+	s16	s_dinfo[4];	/* device information ?? */
+	u32	s_tfree;	/* total number of free zones */
+	u16	s_tinode;	/* total number of free inodes */
+	u16	s_pad3;
+	char	s_fname[6];	/* file system volume name */
+	char	s_fpack[6];	/* file system pack name */
+	s32	s_fill[12];
+	s32	s_state;	/* file system state: 0x7c269d38-s_time means clean */
+	s32	s_magic;	/* version of file system */
+	s32	s_type;		/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
 };
 
 /* SystemV4 free list block on disk */
 struct sysv4_freelist_chunk {
-	unsigned short fl_nfree;	/* number of free blocks in fl_free, <= SYSV_NICFREE] */
-	unsigned long  fl_free[SYSV_NICFREE];
+	u16 fl_nfree;	/* number of free blocks in fl_free, <= SYSV_NICFREE] */
+	u32  fl_free[SYSV_NICFREE];
 };
 
 /* SystemV2 super-block data on disk */
 struct sysv2_super_block {
-	unsigned short s_isize; /* index of first data zone */
-	unsigned long  s_fsize __packed2__; /* total number of zones of this fs */
+	u16	s_isize; 		/* index of first data zone */
+	u32	s_fsize __packed2__;	/* total number of zones of this fs */
 	/* the start of the free block list: */
-	unsigned short s_nfree;	/* number of free blocks in s_free, <= SYSV_NICFREE */
-	unsigned long  s_free[SYSV_NICFREE]; /* first free block list chunk */
+	u16	s_nfree;		/* number of free blocks in s_free, <= SYSV_NICFREE */
+	u32	s_free[SYSV_NICFREE];	/* first free block list chunk */
 	/* the cache of free inodes: */
-	unsigned short s_ninode; /* number of free inodes in s_inode, <= SYSV_NICINOD */
+	u16	s_ninode;		/* number of free inodes in s_inode, <= SYSV_NICINOD */
 	sysv_ino_t     s_inode[SYSV_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
-	char	       s_flock;	/* lock during free block list manipulation */
-	char	       s_ilock;	/* lock during inode cache manipulation */
-	char	       s_fmod;	/* super-block modified flag */
-	char	       s_ronly;	/* flag whether fs is mounted read-only */
-	unsigned long  s_time __packed2__; /* time of last super block update */
-	short	       s_dinfo[4];	/* device information ?? */
-	unsigned long  s_tfree __packed2__; /* total number of free zones */
-	unsigned short s_tinode;	/* total number of free inodes */
-	char	       s_fname[6];	/* file system volume name */
-	char	       s_fpack[6];	/* file system pack name */
-	long	       s_fill[14];
-	long	       s_state;		/* file system state: 0xcb096f43 means clean */
-	long	       s_magic;		/* version of file system */
-	long	       s_type;		/* type of file system: 1 for 512 byte blocks
+	char	s_flock;		/* lock during free block list manipulation */
+	char	s_ilock;		/* lock during inode cache manipulation */
+	char	s_fmod;			/* super-block modified flag */
+	char	s_ronly;		/* flag whether fs is mounted read-only */
+	u32	s_time __packed2__;	/* time of last super block update */
+	s16	s_dinfo[4];		/* device information ?? */
+	u32	s_tfree __packed2__;	/* total number of free zones */
+	u16	s_tinode;		/* total number of free inodes */
+	char	s_fname[6];		/* file system volume name */
+	char	s_fpack[6];		/* file system pack name */
+	s32	s_fill[14];
+	s32	s_state;		/* file system state: 0xcb096f43 means clean */
+	s32	s_magic;		/* version of file system */
+	s32	s_type;			/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
 };
 
 /* SystemV2 free list block on disk */
 struct sysv2_freelist_chunk {
-	unsigned short fl_nfree;	/* number of free blocks in fl_free, <= SYSV_NICFREE] */
-	unsigned long  fl_free[SYSV_NICFREE] __packed2__;
+	u16	fl_nfree;	/* number of free blocks in fl_free, <= SYSV_NICFREE] */
+	u32	fl_free[SYSV_NICFREE] __packed2__;
 };
 
 /* Coherent super-block data on disk */
 #define COH_NICINOD	100	/* number of inode cache entries */
 #define COH_NICFREE	64	/* number of free block list chunk entries */
 struct coh_super_block {
-	unsigned short s_isize; /* index of first data zone */
-	coh_ulong      s_fsize __packed2__; /* total number of zones of this fs */
+	u16		s_isize;	/* index of first data zone */
+	coh_ulong	s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
-	unsigned short s_nfree;	/* number of free blocks in s_free, <= COH_NICFREE */
-	coh_ulong      s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
+	u16 s_nfree;	/* number of free blocks in s_free, <= COH_NICFREE */
+	coh_ulong	s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
 	/* the cache of free inodes: */
-	unsigned short s_ninode; /* number of free inodes in s_inode, <= COH_NICINOD */
-	sysv_ino_t     s_inode[COH_NICINOD]; /* some free inodes */
+	u16		s_ninode;	/* number of free inodes in s_inode, <= COH_NICINOD */
+	sysv_ino_t	s_inode[COH_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
-	char	       s_flock;	/* lock during free block list manipulation */
-	char	       s_ilock;	/* lock during inode cache manipulation */
-	char	       s_fmod;	/* super-block modified flag */
-	char	       s_ronly;	/* flag whether fs is mounted read-only */
-	coh_ulong      s_time __packed2__; /* time of last super block update */
-	coh_ulong      s_tfree __packed2__; /* total number of free zones */
-	unsigned short s_tinode;	/* total number of free inodes */
-	unsigned short s_interleave_m;	/* interleave factor */
-	unsigned short s_interleave_n;
-	char	       s_fname[6];	/* file system volume name */
-	char	       s_fpack[6];	/* file system pack name */
-	unsigned long  s_unique;	/* zero, not used */
+	char		s_flock;	/* lock during free block list manipulation */
+	char		s_ilock;	/* lock during inode cache manipulation */
+	char		s_fmod;		/* super-block modified flag */
+	char		s_ronly;	/* flag whether fs is mounted read-only */
+	coh_ulong	s_time __packed2__; /* time of last super block update */
+	coh_ulong	s_tfree __packed2__; /* total number of free zones */
+	u16		s_tinode;	/* total number of free inodes */
+	u16		s_interleave_m;	/* interleave factor */
+	u16		s_interleave_n;
+	char		s_fname[6];	/* file system volume name */
+	char		s_fpack[6];	/* file system pack name */
+	u32		s_unique;	/* zero, not used */
 };
 
 /* Coherent free list block on disk */
 struct coh_freelist_chunk {
-	unsigned short fl_nfree;	/* number of free blocks in fl_free, <= COH_NICFREE] */
-	unsigned long  fl_free[COH_NICFREE] __packed2__;
+	u16 fl_nfree;	/* number of free blocks in fl_free, <= COH_NICFREE] */
+	u32  fl_free[COH_NICFREE] __packed2__;
 };
 
 
 /* SystemV/Coherent inode data on disk */
 
 struct sysv_inode {
-	unsigned short i_mode;
-	unsigned short i_nlink;
-	unsigned short i_uid;
-	unsigned short i_gid;
-	unsigned long  i_size;
+	u16 i_mode;
+	u16 i_nlink;
+	u16 i_uid;
+	u16 i_gid;
+	u32 i_size;
 	union { /* directories, regular files, ... */
-		char i_addb[3*(10+1+1+1)+1]; /* zone numbers: max. 10 data blocks,
+		unsigned char i_addb[3*(10+1+1+1)+1]; /* zone numbers: max. 10 data blocks,
 					      * then 1 indirection block,
 					      * then 1 double indirection block,
 					      * then 1 triple indirection block.
@@ -236,14 +240,14 @@
 		/* named pipes on Coherent */
 		struct {
 			char p_addp[30];
-			short p_pnc;
-			short p_prx;
-			short p_pwx;
+			s16 p_pnc;
+			s16 p_prx;
+			s16 p_pwx;
 		} i_p;
 	} i_a;
-	unsigned long i_atime;	/* time of last access */
-	unsigned long i_mtime;	/* time of last modification */
-	unsigned long i_ctime;	/* time of creation */
+	u32 i_atime;	/* time of last access */
+	u32 i_mtime;	/* time of last modification */
+	u32 i_ctime;	/* time of creation */
 };
 
 /* The admissible values for i_mode are listed in <linux/stat.h> :
@@ -301,7 +305,7 @@
 /* The number of inodes per block is
    sb->sv_inodes_per_block = block_size / sizeof(struct sysv_inode) */
 /* The number of indirect pointers per block is
-   sb->sv_ind_per_block = block_size / sizeof(unsigned long) */
+   sb->sv_ind_per_block = block_size / sizeof(u32) */
 
 
 /* SystemV/Coherent directory entry on disk */
diff -urN -X diff-21.excl linux-2.1.120/include/linux/sysv_fs_i.h linux-2.1.120-alan/include/linux/sysv_fs_i.h
--- linux-2.1.120/include/linux/sysv_fs_i.h	Sat Aug 24 07:49:07 1996
+++ linux-2.1.120-alan/include/linux/sysv_fs_i.h	Sun Sep 20 20:44:26 1998
@@ -5,11 +5,11 @@
  * SystemV/Coherent FS inode data in memory
  */
 struct sysv_inode_info {
-	unsigned long i_data[10+1+1+1];	/* zone numbers: max. 10 data blocks,
-					 * then 1 indirection block,
-					 * then 1 double indirection block,
-					 * then 1 triple indirection block.
-					 */
+	u32 i_data[10+1+1+1];	/* zone numbers: max. 10 data blocks,
+				 * then 1 indirection block,
+				 * then 1 double indirection block,
+				 * then 1 triple indirection block.
+				 */
 };
 
 #endif
diff -urN -X diff-21.excl linux-2.1.120/include/linux/sysv_fs_sb.h linux-2.1.120-alan/include/linux/sysv_fs_sb.h
--- linux-2.1.120/include/linux/sysv_fs_sb.h	Wed Feb  4 09:52:43 1998
+++ linux-2.1.120-alan/include/linux/sysv_fs_sb.h	Sun Sep 20 20:44:26 1998
@@ -50,21 +50,21 @@
 	   different superblock layout. */
 	char *         s_sbd1;		/* entire superblock data, for part 1 */
 	char *         s_sbd2;		/* entire superblock data, for part 2 */
-	unsigned short *s_sb_fic_count;	/* pointer to s_sbd->s_ninode */
-        unsigned short *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
-	unsigned short *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
-	unsigned short *s_sb_flc_count;	/* pointer to s_sbd->s_nfree */
-	unsigned long  *s_sb_flc_blocks; /* pointer to s_sbd->s_free */
-	unsigned long  *s_sb_total_free_blocks;/* pointer to s_sbd->s_tfree */
-	unsigned long  *s_sb_time;	/* pointer to s_sbd->s_time */
-	unsigned long  *s_sb_state;	/* pointer to s_sbd->s_state, only FSTYPE_SYSV */
+	u16            *s_sb_fic_count;	/* pointer to s_sbd->s_ninode */
+        u16            *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
+	u16            *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
+	u16            *s_sb_flc_count;	/* pointer to s_sbd->s_nfree */
+	u32	       *s_sb_flc_blocks; /* pointer to s_sbd->s_free */
+	u32            *s_sb_total_free_blocks;/* pointer to s_sbd->s_tfree */
+	u32            *s_sb_time;	/* pointer to s_sbd->s_time */
+	u32            *s_sb_state;	/* pointer to s_sbd->s_state, only FSTYPE_SYSV */
 	/* We keep those superblock entities that don't change here;
 	   this saves us an indirection and perhaps a conversion. */
-	unsigned long  s_firstinodezone; /* index of first inode zone */
-	unsigned long  s_firstdatazone;	/* same as s_sbd->s_isize */
-	unsigned long  s_ninodes;	/* total number of inodes */
-	unsigned long  s_ndatazones;	/* total number of data zones */
-	unsigned long  s_nzones;	/* same as s_sbd->s_fsize */
+	u32            s_firstinodezone; /* index of first inode zone */
+	u32            s_firstdatazone;	/* same as s_sbd->s_isize */
+	u32            s_ninodes;	/* total number of inodes */
+	u32            s_ndatazones;	/* total number of data zones */
+	u32            s_nzones;	/* same as s_sbd->s_fsize */
 };
 /* The fields s_ind_per_block_2_1, s_toobig_block are currently unused. */
 
diff -urN -X diff-21.excl linux-2.1.120/kernel/sched.c linux-2.1.120-alan/kernel/sched.c
--- linux-2.1.120/kernel/sched.c	Mon Sep  7 07:31:10 1998
+++ linux-2.1.120-alan/kernel/sched.c	Sun Sep 20 20:44:27 1998
@@ -561,6 +561,10 @@
 			add_timer(&timer);
 		}
 		get_mmu_context(next);
+#ifdef CONFIG_FTRACE
+		do_ftrace (0xfd000000 | (unsigned long)prev);
+		do_ftrace (0xfc000000 | (unsigned long)next);
+#endif
 		switch_to(prev,next);
 
 		if (timeout)



