## Automatically generated incremental diff
## From:   linux-2.2.17-pre4
## To:     linux-2.2.17-pre5
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.2.17-pre4/CREDITS linux/CREDITS
--- linux-2.2.17-pre4/CREDITS	Wed Jun  7 14:26:42 2000
+++ linux/CREDITS	Mon Dec  3 22:06:19 2001
@@ -645,6 +645,10 @@
 S: San Jose, California 95131
 S: USA
 
+N: Kumar Gala
+E: kumar.gala@motorola.com
+D: AltiVec PowerPC support
+
 N: Nigel Gamble
 E: nigel@nrg.org
 E: nigel@sgi.com
@@ -812,6 +816,7 @@
 E: benh@mipsys.com
 D: PowerMac booter (BootX)
 D: Additional PowerBook support
+D: Apple "Core99" machines support (ibook,g4,...)
 S: 22, rue des Marguettes
 S: 75012 Paris
 S: France
@@ -1631,6 +1636,13 @@
 N: Ken Pizzini
 E: ken@halcyon.com
 D: CDROM driver "sonycd535" (Sony CDU-535/531)
+
+N: Matt Porter
+E: mporter@phx.mcd.mot.com
+D: Motorola PowerPC PReP support
+S: 2900 S. Diable Way
+S: Tempe, Arizona 85282
+S: USA
 
 N: Frederic Potter 
 E: Frederic.Potter@masi.ibp.fr 
diff -urN linux-2.2.17-pre4/Makefile linux/Makefile
--- linux-2.2.17-pre4/Makefile	Mon Dec  3 22:06:13 2001
+++ linux/Makefile	Mon Dec  3 22:06:19 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 17
-EXTRAVERSION = pre4
+EXTRAVERSION = pre5
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -urN linux-2.2.17-pre4/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- linux-2.2.17-pre4/arch/ppc/boot/Makefile	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/boot/Makefile	Mon Dec  3 22:06:19 2001
@@ -69,7 +69,7 @@
 zvmlinux.initrd: zvmlinux
 	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=initrd=ramdisk.image.gz \
+		--add-section=initrd=../coffboot/ramdisk.image.gz \
 		--add-section=image=../coffboot/vmlinux.gz \
 		zvmlinux.initrd.tmp zvmlinux.initrd
 	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \
@@ -79,7 +79,7 @@
 		-c -o misc.o misc.c
 	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=initrd=ramdisk.image.gz \
+		--add-section=initrd=../coffboot/ramdisk.image.gz \
 		--add-section=image=../coffboot/vmlinux.gz \
 		zvmlinux.initrd.tmp $@
 	rm zvmlinux.initrd.tmp
diff -urN linux-2.2.17-pre4/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c
--- linux-2.2.17-pre4/arch/ppc/chrpboot/main.c	Tue Jan  4 10:12:12 2000
+++ linux/arch/ppc/chrpboot/main.c	Mon Dec  3 22:06:19 2001
@@ -17,15 +17,16 @@
 #define get_32be(x)	(*(unsigned *)(x))
 
 #define RAM_START	0x00000000
-#define RAM_END		(8<<20)
+#define RAM_END		(64<<20)
 
-#define RAM_FREE	((unsigned long)(_end+0x1000)&~0xFFF)
+#define BOOT_START	((unsigned long)_start)
+#define BOOT_END	((unsigned long)(_end + 0xFFF) & ~0xFFF)
 #define PROG_START	0x00010000
 
 char *avail_ram;
 char *end_avail;
 
-extern char _end[];
+extern char _start[], _end[];
 extern char image_data[];
 extern int image_len;
 extern char initrd_data[];
@@ -48,17 +49,23 @@
 	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
 	a1 = initrd_start;
 	a2 = initrd_size;
-	printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r", initrd_start,
-	       initrd_data,initrd_size);
+	claim(initrd_start, RAM_END - initrd_start, 0);
+	printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n",
+	       initrd_start, initrd_data, initrd_size);
 	memcpy((char *)initrd_start, initrd_data, initrd_size);
-	end_avail = (char *)initrd_start;
-    } else
-	end_avail = (char *) RAM_END;
+    }
     im = image_data;
     len = image_len;
+    /* try and claim our text/data in case of OF bugs */
+    claim(BOOT_START, BOOT_END - BOOT_START, 0);
+    /* claim 4MB starting at PROG_START */
+    claim(PROG_START, (4<<20) - PROG_START, 0);
     dst = (void *) PROG_START;
     if (im[0] == 0x1f && im[1] == 0x8b) {
-	avail_ram = (char *)RAM_FREE;
+	/* claim 512kB for scratch space */
+	avail_ram = (char *) claim(0, 512 << 10, 0x10);
+	end_avail = avail_ram + (512 << 10);
+	printf("avail_ram = %x\n", avail_ram);
 	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
 	gunzip(dst, 0x400000, im, &len);
 	printf("done %u bytes\n\r", len);
diff -urN linux-2.2.17-pre4/arch/ppc/chrpboot/misc.S linux/arch/ppc/chrpboot/misc.S
--- linux-2.2.17-pre4/arch/ppc/chrpboot/misc.S	Tue Apr 14 17:33:57 1998
+++ linux/arch/ppc/chrpboot/misc.S	Mon Dec  3 22:06:19 2001
@@ -9,7 +9,7 @@
 	.text
 
 /*
- * Use the BAT0 registers to map the 1st 8MB of RAM to 0x90000000.
+ * Use the BAT0 registers to map the 1st 8 or 64MB of RAM to 0x90000000.
  */
 	.globl	setup_bats
 setup_bats:
@@ -21,7 +21,7 @@
 	ori	4,4,4			/* set up BAT registers for 601 */
 	li	5,0x7f
 	b	5f
-4:	ori	4,4,0xff		/* set up BAT registers for 604 */
+4:	ori	4,4,0x7ff		/* set up BAT registers for 604 */
 	li	5,2
 	mtdbatu	3,4
 	mtdbatl	3,5
diff -urN linux-2.2.17-pre4/arch/ppc/chrpboot/start.c linux/arch/ppc/chrpboot/start.c
--- linux-2.2.17-pre4/arch/ppc/chrpboot/start.c	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/chrpboot/start.c	Mon Dec  3 22:06:19 2001
@@ -131,6 +131,29 @@
     return args.phandle;
 }
 
+void *
+claim(unsigned int virt, unsigned int size, unsigned int align)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	unsigned int virt;
+	unsigned int size;
+	unsigned int align;
+	void *ret;
+    } args;
+
+    args.service = "claim";
+    args.nargs = 3;
+    args.nret = 1;
+    args.virt = virt;
+    args.size = size;
+    args.align = align;
+    (*prom)(&args);
+    return args.ret;
+}
+
 int
 getprop(void *phandle, const char *name, void *buf, int buflen)
 {
diff -urN linux-2.2.17-pre4/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- linux-2.2.17-pre4/arch/ppc/coffboot/Makefile	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/coffboot/Makefile	Mon Dec  3 22:06:19 2001
@@ -92,11 +92,11 @@
 micoffboot: dummy.o
 	$(LD) -o $@ $(COFF_LD_ARGS) dummy.o $(LIBS)
 
-miboot.image: micoffboot hack-coff
+miboot.image: micoffboot hack-coff vmlinux.gz
 	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=vmlinux.gz micoffboot $@
 	./hack-coff $@
 
-miboot.image.initrd: micoffboot hack-coff
+miboot.image.initrd: micoffboot hack-coff vmlinux.gz ramdisk.image.gz
 	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=vmlinux.gz \
 	--add-section=initrd=ramdisk.image.gz micoffboot $@
 	./hack-coff $@
diff -urN linux-2.2.17-pre4/arch/ppc/coffboot/dummy.c linux/arch/ppc/coffboot/dummy.c
--- linux-2.2.17-pre4/arch/ppc/coffboot/dummy.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/coffboot/dummy.c	Mon Dec  3 22:06:19 2001
@@ -0,0 +1,4 @@
+int main(void)
+{
+	return 0;
+}
diff -urN linux-2.2.17-pre4/arch/ppc/config.in linux/arch/ppc/config.in
--- linux-2.2.17-pre4/arch/ppc/config.in	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/config.in	Mon Dec  3 22:06:19 2001
@@ -90,6 +90,7 @@
 if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
    bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
 fi
+tristate 'Support for /dev/rtc' CONFIG_PPC_RTC
 bool 'Support for PowerMac ADB mouse' CONFIG_ADBMOUSE
 bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
 bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- linux-2.2.17-pre4/arch/ppc/kernel/Makefile	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/kernel/Makefile	Mon Dec  3 22:06:19 2001
@@ -67,7 +67,8 @@
 		$(TOPDIR)/include/asm/ptrace.h
 	$(CC) ${CFLAGS} -S mk_defs.c
 	cp ppc_defs.head ppc_defs.h
-	grep '^#define' mk_defs.s >>ppc_defs.h
+	chmod 755 ppc_defs.h
+	grep '^#define' mk_defs.s >> ppc_defs.h
 	rm mk_defs.s
 
 find_name : find_name.c
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- linux-2.2.17-pre4/arch/ppc/kernel/chrp_setup.c	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/kernel/chrp_setup.c	Mon Dec  3 22:06:19 2001
@@ -685,3 +685,8 @@
 	while ( *s )
 		call_rtas( "display-character", 1, 1, NULL, *s++ );
 }
+
+void chrp_indicator(int x)
+{
+	call_rtas("set-indicator", 3, 1, NULL, 6, 0, x);
+}
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- linux-2.2.17-pre4/arch/ppc/kernel/head.S	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/kernel/head.S	Mon Dec  3 22:06:19 2001
@@ -2832,7 +2832,6 @@
 	stw	r0,20(r1)
 	lis	r4,rtas_data@ha
 	lwz	r4,rtas_data@l(r4)
-	addis	r4,r4,-KERNELBASE@h
 	lis	r6,1f@ha	/* physical return address for rtas */
 	addi	r6,r6,1f@l
 	addis	r6,r6,-KERNELBASE@h
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- linux-2.2.17-pre4/arch/ppc/kernel/pmac_setup.c	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/kernel/pmac_setup.c	Mon Dec  3 22:06:19 2001
@@ -64,6 +64,7 @@
 
 #undef SHOW_GATWICK_IRQS
 
+void pmac_time_init(void);
 unsigned long pmac_get_rtc_time(void);
 int pmac_set_rtc_time(unsigned long nowtime);
 void pmac_read_rtc_time(void);
@@ -308,6 +309,8 @@
 	find_via_cuda();
 	find_via_pmu();
 
+	pmac_nvram_init();
+
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
@@ -402,7 +405,6 @@
 pmac_init2(void))
 {
 	adb_init();
-	pmac_nvram_init();
 	media_bay_init();
 }
 
@@ -642,7 +644,7 @@
 	ppc_md.power_off      = pmac_power_off;
 	ppc_md.halt           = pmac_halt;
 
-	ppc_md.time_init      = NULL;
+	ppc_md.time_init      = pmac_time_init;
 	ppc_md.set_rtc_time   = pmac_set_rtc_time;
 	ppc_md.get_rtc_time   = pmac_get_rtc_time;
 	ppc_md.calibrate_decr = pmac_calibrate_decr;
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/pmac_support.c linux/arch/ppc/kernel/pmac_support.c
--- linux-2.2.17-pre4/arch/ppc/kernel/pmac_support.c	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/kernel/pmac_support.c	Mon Dec  3 22:06:19 2001
@@ -27,18 +27,6 @@
 
 #undef DEBUG
 
-/*
- * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
- */
-static int nvram_naddrs;
-static volatile unsigned char *nvram_addr;
-static volatile unsigned char *nvram_data;
-static int nvram_mult, is_core_99;
-static char* nvram_image;
-static int core99_bank = 0;
-
-extern int pmac_newworld;
-
 #define NVRAM_SIZE		0x2000	/* 8kB of non-volatile RAM */
 
 #define CORE99_SIGNATURE	0x5a
@@ -52,7 +40,6 @@
 #define CORE99_FLASH_CMD_RESET		0xff
 #define CORE99_FLASH_CMD_WRITE_SETUP	0x40
 
-
 /* CHRP NVRAM header */
 struct chrp_header {
   u8		signature;
@@ -69,8 +56,29 @@
   u32			reserved[2];
 };
 
+/*
+ * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
+ */
+static int nvram_naddrs;
+static volatile unsigned char *nvram_addr;
+static volatile unsigned char *nvram_data;
+static int nvram_mult, is_core_99;
+static int core99_bank = 0;
 static int nvram_partitions[3];
 
+/* FIXME: kmalloc fails to allocate the image now that I had to move it
+ *        before time_init(). For now, I allocate a static buffer here
+ *        but it's a waste of space on all but core99 machines
+ */
+#if 0
+static char* nvram_image;
+#else
+__pmac static char nvram_image[NVRAM_SIZE];
+#endif
+
+extern int pmac_newworld;
+
+
 static u8
 chrp_checksum(struct chrp_header* hdr)
 {
@@ -244,11 +252,13 @@
 			printk(KERN_ERR "nvram: no address\n");
 			return;
 		}
+#if 0
 		nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
 		if (!nvram_image) {
 			printk(KERN_ERR "nvram: can't allocate image\n");
 			return;
 		}
+#endif		
 		nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
 #ifdef DEBUG
 		printk("nvram: Checking bank 0...\n");
@@ -322,7 +332,7 @@
 		return req.reply[1];
 	case 1:
 		if (is_core_99)
-			return nvram_image[addr];
+			return nvram_image ? nvram_image[addr] : 0;
 		return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult];
 	case 2:
 		*nvram_addr = addr >> 5;
@@ -347,6 +357,8 @@
 		break;
 	case 1:
 		if (is_core_99) {
+			if (!nvram_image)
+				return;
 			nvram_image[addr] = val;
 			break;
 		}
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
--- linux-2.2.17-pre4/arch/ppc/kernel/pmac_time.c	Wed May  3 17:16:31 2000
+++ linux/arch/ppc/kernel/pmac_time.c	Mon Dec  3 22:06:19 2001
@@ -22,6 +22,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <asm/nvram.h>
 
 #include "time.h"
 
@@ -49,11 +50,35 @@
 /* Bits in IFR and IER */
 #define T1_INT		0x40		/* Timer 1 interrupt */
 
-__pmac
+extern struct timezone sys_tz;
+
+__init
+void pmac_time_init(void)
+{
+	s32 delta = 0;
+	int dst;
+	int i;
+	char tmp[1024];
+	char *p = tmp;
+	
+	delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
+	delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
+	delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
+	if (delta & 0x00800000UL)
+		delta |= 0xFF000000UL;
+	dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
+	printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
+		dst ? "on" : "off");
+	sys_tz.tz_minuteswest = -delta/60;
+	/* I _suppose_ this is 0:off, 1:on */
+	sys_tz.tz_dsttime = dst;
+}
 
+__pmac
 unsigned long pmac_get_rtc_time(void)
 {
 	struct adb_request req;
+	int offset = sys_tz.tz_minuteswest * 60;
 
 	/* Get the time from the RTC */
 	if (adb_controller == 0)
@@ -70,7 +95,7 @@
 			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
 			       req.reply_len);
 		return (req.reply[3] << 24) + (req.reply[4] << 16)
-			+ (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
+			+ (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET + offset;
 	case ADB_VIAPMU:
 		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) {
 			printk("pmac_read_rtc_time: pmu_request failed\n");
@@ -82,7 +107,7 @@
 			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
 			       req.reply_len);
 		return (req.reply[1] << 24) + (req.reply[2] << 16)
-			+ (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET;
+			+ (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET + offset;
 	default:
 		return 0;
 	}
@@ -90,7 +115,39 @@
 
 int pmac_set_rtc_time(unsigned long nowtime)
 {
-	return 0;
+	struct adb_request req;
+
+	nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60;
+
+	/* Set the time in the RTC */
+	if (adb_controller == 0)
+		return 0;
+	/* adb_controller->kind, not adb_hardware, since that doesn't
+	   get set until we call adb_init - paulus. */
+	switch (adb_controller->kind) {
+	case ADB_VIACUDA:
+		if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
+				 nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+			return 0;
+		while (!req.complete)
+			cuda_poll();
+//		if (req.reply_len != 7)
+			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		return 1;
+	case ADB_VIAPMU:
+		if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
+				nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+			return 0;
+		while (!req.complete)
+			pmu_poll();
+		if (req.reply_len != 5)
+			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		return 1;
+	default:
+		return 0;
+	}
 }
 
 /*
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.2.17-pre4/arch/ppc/kernel/ppc_ksyms.c	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon Dec  3 22:06:19 2001
@@ -29,6 +29,7 @@
 #include <asm/spinlock.h>
 #include <asm/dma.h>
 #include <asm/machdep.h>
+#include <asm/nvram.h>
 
 /* Tell string.h we don't want memcpy etc. as cpp defines */
 #define EXPORT_SYMTAB_STROPS
@@ -45,6 +46,9 @@
 extern atomic_t ppc_n_lost_interrupts;
 extern void do_lost_interrupts(unsigned long);
 extern int do_signal(sigset_t *, struct pt_regs *);
+extern unsigned long mktime(unsigned int, unsigned int, unsigned int,
+                            unsigned int, unsigned int, unsigned int);
+extern void to_tm(int tim, struct rtc_time * tm);
 
 long long __ashrdi3(long long, int);
 long long __ashldi3(long long, int);
@@ -222,7 +226,13 @@
 /*#ifdef CONFIG_PMAC */
 EXPORT_SYMBOL(nvram_read_byte);
 EXPORT_SYMBOL(nvram_write_byte);
+EXPORT_SYMBOL(pmac_xpram_read);
+EXPORT_SYMBOL(pmac_xpram_write);
 /*#endif*/ /* CONFIG_PMAC */
+#ifdef CONFIG_PPC_RTC
+EXPORT_SYMBOL(mktime);
+EXPORT_SYMBOL(to_tm);
+#endif
 
 EXPORT_SYMBOL(abs);
 
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- linux-2.2.17-pre4/arch/ppc/kernel/prom.c	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/kernel/prom.c	Mon Dec  3 22:06:19 2001
@@ -96,7 +96,7 @@
 char *bootpath = 0;
 char *bootdevice = 0;
 
-unsigned int rtas_data = 0;   /* virtual pointer */
+unsigned int rtas_data = 0;   /* physical pointer */
 unsigned int rtas_entry = 0;  /* physical pointer */
 unsigned int rtas_size = 0;
 unsigned int old_rtas = 0;
@@ -114,7 +114,7 @@
 
 void drawchar(char c);
 void drawstring(const char *c);
-static void drawhex(unsigned long v);
+void drawhex(unsigned long v);
 static void scrollscreen(void);
 
 static void draw_byte(unsigned char c, long locX, long locY);
@@ -274,6 +274,22 @@
 	}
 }
 
+void
+prom_print_hex(unsigned int v)
+{
+	char buf[16];
+	int i, c;
+
+	for (i = 0; i < 8; ++i) {
+		c = (v >> ((7-i)*4)) & 0xf;
+		c += (c >= 10)? ('a' - 10): '0';
+		buf[i] = c;
+	}
+	buf[i] = ' ';
+	buf[i+1] = 0;
+	prom_print(buf);
+}
+
 unsigned long smp_ibm_chrp_hack __initdata = 0;
 
 /*
@@ -448,15 +464,6 @@
 		RELOC(bootdevice) = PTRUNRELOC(d);
 		mem = ALIGN(mem + strlen(d) + 1);
 	}
-
-	mem = check_display(mem);
-
-	prom_print(RELOC("copying OF device tree..."));
-	mem = copy_device_tree(mem, mem + (1<<20));
-	prom_print(RELOC("done\n"));
-
-
-	RELOC(klimit) = (char *) (mem - offset);
 	
 	prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
 	if (prom_rtas != (void *) -1) {
@@ -468,18 +475,14 @@
 			RELOC(rtas_data) = 0;
 		} else {
 			/*
-			 * We do _not_ want the rtas_data inside the klimit
-			 * boundry since it'll be squashed when we do the
-			 * relocate of the kernel on chrp right after prom_init()
-			 * in head.S.  So, we just pick a spot in memory.
-			 * -- Cort
+			 * Ask OF for some space for RTAS.
 			 */
-#if 0
-			mem = (mem + 4095) & -4096;
-			RELOC(rtas_data) = mem + KERNELBASE;
-			mem += RELOC(rtas_size);
-#endif
-			RELOC(rtas_data) = (6<<20) + KERNELBASE;
+			RELOC(rtas_data) = (unsigned int)
+				call_prom(RELOC("claim"), 3, 1, 0,
+					  RELOC(rtas_size), 0x1000);
+			prom_print(RELOC("rtas at "));
+			prom_print_hex(RELOC(rtas_data));
+			prom_print(RELOC("\n"));
 		}
 		prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
 		{
@@ -491,7 +494,7 @@
 			prom_args.nret = 2;
 			prom_args.args[0] = RELOC("instantiate-rtas");
 			prom_args.args[1] = prom_rtas;
-			prom_args.args[2] = ((void *)(RELOC(rtas_data)-KERNELBASE));
+			prom_args.args[2] = (void *) RELOC(rtas_data);
 			RELOC(prom)(&prom_args);
 			if (prom_args.args[nargs] != 0)
 				i = 0;
@@ -505,6 +508,15 @@
 			prom_print(RELOC(" done\n"));
 	}
 
+	mem = check_display(mem);
+
+	prom_print(RELOC("copying OF device tree..."));
+	/* N.B. do this *after* any claims */
+	mem = copy_device_tree(mem, mem + (1<<20));
+	prom_print(RELOC("done\n"));
+
+	RELOC(klimit) = (char *) (mem - offset);
+
 	/* If we are already running at 0xc0000000, we assume we were loaded by
 	 * an OF bootloader which did set a BAT for us. This breaks OF translate
 	 * so we force phys to be 0
@@ -537,7 +549,7 @@
 	}
 	    
 #ifdef CONFIG_BOOTX_TEXT
-	if (!chrp && RELOC(prom_disp_node) != 0)
+	if (RELOC(prom_disp_node) != 0)
 		setup_disp_fake_bi(RELOC(prom_disp_node));
 #endif
 
@@ -631,10 +643,10 @@
 		RELOC(prom_stdout) = 0;
 		clearscreen();
 		prom_welcome(PTRRELOC(RELOC(disp_bi)), phys);
-		prom_print(RELOC("booting...\n"));
 	}
 #endif
 
+	prom_print(RELOC("booting...\n"));
 	return phys;
 }
 
@@ -762,7 +774,7 @@
 
 		if (RELOC(prom_disp_node) == 0)
 			RELOC(prom_disp_node) = node;
-			
+
 		/* Setup a useable color table when the appropriate
 		 * method is available. Should update this to set-colors */
 		for (i = 0; i < 32; i++)
@@ -841,7 +853,10 @@
 		prom_print(RELOC("Failed to get pitch\n"));
 		return;
 	}
+	if (pitch == 1)
+		pitch = 0x1000;
 	address = len = 0;
+	len = 0xfa000000;
 	call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"), &len, sizeof(len));
 	address = len;
 	if (address == 0) {
@@ -852,22 +867,21 @@
 	/* kludge for valkyrie */
 	if (strcmp(dp->name, "valkyrie") == 0) 
 	    address += 0x1000;
-    }
 #endif
  
-    RELOC(disp_bi) = &fake_bi;
-    bi = PTRRELOC((&fake_bi));
-    RELOC(g_loc_X) = 0;
-    RELOC(g_loc_Y) = 0;
-    RELOC(g_max_loc_X) = width / 8;
-    RELOC(g_max_loc_Y) = height / 16;
-    bi->logicalDisplayBase = (unsigned char *)address;
-    bi->dispDeviceBase = (unsigned char *)address;
-    bi->dispDeviceRowBytes = pitch;
-    bi->dispDeviceDepth = depth;
-    bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
-    bi->dispDeviceRect[2] = width;
-    bi->dispDeviceRect[3] = height;
+	RELOC(disp_bi) = &fake_bi;
+	bi = PTRRELOC((&fake_bi));
+	RELOC(g_loc_X) = 0;
+	RELOC(g_loc_Y) = 0;
+	RELOC(g_max_loc_X) = width / 8;
+	RELOC(g_max_loc_Y) = height / 16;
+	bi->logicalDisplayBase = (unsigned char *)address;
+	bi->dispDeviceBase = (unsigned char *)address;
+	bi->dispDeviceRowBytes = pitch;
+	bi->dispDeviceDepth = depth;
+	bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
+	bi->dispDeviceRect[2] = width;
+	bi->dispDeviceRect[3] = height;
 }
 #endif
 
@@ -1005,31 +1019,17 @@
 finish_device_tree(void)
 {
 	unsigned long mem = (unsigned long) klimit;
-#if 0
-	char* model;
-	
-	/* Here, we decide if we'll use the interrupt-tree (new Core99 code) or not.
-	 * This code was only tested with Core99 machines so far, but should be easily
-	 * adapted to older newworld machines (iMac, B&W G3, Lombard).
-	 */
-	model = get_property(allnodes, "model", 0);
-	if ((boot_infos == 0) && model && (
-		strcmp(model, "PowerBook2,1") == 0 ||
-		strcmp(model, "PowerBook3,1") == 0 ||
-		strcmp(model, "PowerMac2,1") == 0 ||
-		strcmp(model, "PowerMac3,1") == 0))
- 		use_of_interrupt_tree = 1;
-#endif 	
-	/* All newworld machines now use the interrupt tree */
+
+	/* All newworld machines and CHRP now use the interrupt tree */
 	struct device_node *np = allnodes;
-	while(np) {
+	while(np && (_machine == _MACH_Pmac)) {
 		if (get_property(np, "interrupt-parent", 0)) {
 			pmac_newworld = 1;
 			break;
 		}
 		np = np->allnext;
 	}
-	if (boot_infos == 0 && pmac_newworld)
+	if ((_machine == _MACH_chrp) || (boot_infos == 0 && pmac_newworld))
 		use_of_interrupt_tree = 1;
 
 	mem = finish_node(allnodes, mem, NULL);
@@ -1172,6 +1172,25 @@
 		    for (j=2; j<isize; j++)
 		    	interrupts++;
 		}
+		/*
+		 *  On the CHRP LongTrail, ISA interrupts are cascaded through
+		 *  the OpenPIC. For compatibility reasons, ISA interrupts are
+		 *  numbered 0-15 and OpenPIC interrupts start at 16.
+		 *  Hence we have to fixup the interrupt numbers for sources
+		 *  that are attached to the OpenPIC and thus have an
+		 *  interrupt-controller named `open-pic'.
+		 *
+		 *  FIXME: The name of the interrupt-controller node for the
+		 *         `ide' node has no name, although its parent is
+		 *         correctly specified in interrupt-map, so we check
+		 *         for a NULL name as well.
+		 */
+		if (_machine == _MACH_chrp &&
+		    ((node->name && !strcmp(node->name, "open-pic")) ||
+		     !node->name)) {
+		    for (i = 0; i < np->n_intrs; ++i)
+			np->intrs[i].line = openpic_to_irq(np->intrs[i].line);
+		}
 		return mem_start;
 	    }
 	    /* We lookup for an interrupt-map. This code can only handle one interrupt
@@ -2015,6 +2034,15 @@
 	}
 }
 
+void
+here(int n)
+{
+	chrp_indicator(n);
+	if (n == 1)
+		clearscreen();
+	showvalue("here ", n);
+}
+
 __pmac
 void
 drawstring(const char *c)
@@ -2024,7 +2052,7 @@
 }
 
 __pmac
-static void
+void
 drawhex(unsigned long v)
 {
 	static char hex_table[] = "0123456789abcdef";
diff -urN linux-2.2.17-pre4/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- linux-2.2.17-pre4/arch/ppc/kernel/time.c	Tue Oct 26 17:53:39 1999
+++ linux/arch/ppc/kernel/time.c	Mon Dec  3 22:06:19 2001
@@ -106,6 +106,13 @@
 		if ( !smp_processor_id() )
 		{
 			do_timer(regs);
+#if 0
+	/* -- BenH -- I'm removing this for now since it can cause various
+	 *            troubles with local-time RTCs. Now that we have a
+	 *            /dev/rtc that uses ppc_md.set_rtc_time() on mac, it
+	 *            should be possible to program the RTC from userland
+	 *            in all cases.
+	 */
 			/*
 			 * update the rtc when needed
 			 */
@@ -119,6 +126,7 @@
 					/* do it again in 60 s */
 					last_rtc_update = xtime.tv_sec;
 			}
+#endif			
 		}
 	}
 #ifdef __SMP__
diff -urN linux-2.2.17-pre4/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- linux-2.2.17-pre4/arch/ppc/mm/init.c	Mon Dec  3 22:06:13 2001
+++ linux/arch/ppc/mm/init.c	Mon Dec  3 22:06:19 2001
@@ -933,15 +933,21 @@
 				/* On the powerpc, no user access
 				   forces R/W kernel access */
 				f |= _PAGE_USER;
+			map_page(v, p, f);
+			v += PAGE_SIZE;
+			p += PAGE_SIZE;
+		}
+	}
+
 #else	/* CONFIG_8xx */
-            for (i = 0; i < phys_mem.n_regions; ++i) {
-                    v = (ulong)__va(phys_mem.regions[i].address);
-                    p = phys_mem.regions[i].address;
-                    for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
+	for (i = 0; i < phys_mem.n_regions; ++i) {
+		v = (ulong)__va(phys_mem.regions[i].address);
+		p = phys_mem.regions[i].address;
+		for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
                         /* On the MPC8xx, we want the page shared so we
                          * don't get ASID compares on kernel space.
                          */
-                            f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
+			f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
 
                         /* I don't really need the rest of this code, but
                          * I grabbed it because I think the line:
@@ -951,14 +957,14 @@
                          * the MPC8xx, the PAGE_DIRTY takes care of that
                          * for us (along with the RW software state).
                          */
-                            if ((char *) v < _stext || (char *) v >= etext)
-                                    f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
-#endif /* CONFIG_8xx */
+			if ((char *) v < _stext || (char *) v >= etext)
+				f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
 			map_page(v, p, f);
 			v += PAGE_SIZE;
 			p += PAGE_SIZE;
 		}
-	}	    
+	}
+#endif /* CONFIG_8xx */
 }
 
 /* This can get called from ioremap, so don't make it an initfunc, OK? */
@@ -1057,7 +1063,6 @@
 #endif /* CONFIG_GEMINI	*/
 	else /* prep */
 		end_of_DRAM = prep_find_end_of_memory();
-*(unsigned long *)(KERNELBASE) = 0xdeadbeef;	
         hash_init();
         _SDR1 = __pa(Hash) | (Hash_mask >> 10);
 	ioremap_base = 0xf8000000;
@@ -1257,8 +1262,8 @@
 #endif /* CONFIG_BLK_DEV_INITRD */
 #ifndef CONFIG_8xx		  
 			if ( !rtas_data ||
-			     addr < (rtas_data & PAGE_MASK) ||
-			     addr >= (rtas_data+rtas_size))
+			     addr < (rtas_data + KERNELBASE) ||
+			     addr >= (rtas_data + KERNELBASE + rtas_size))
 #endif /* CONFIG_8xx */
 				free_page(addr);
 	}
@@ -1319,6 +1324,7 @@
 	return ret;
 }
 #endif /* CONFIG_MBX */
+
 #ifndef CONFIG_8xx
 /*
  * On systems with Open Firmware, collect information about
@@ -1385,6 +1391,7 @@
 	if (boot_infos == 0) {
 		/* record which bits the prom is using */
 		get_mem_prop("available", &phys_avail);
+		remove_mem_piece(&phys_avail, __max_memory, ~0U, 0);
 		prom_mem = phys_mem;
 		for (i = 0; i < phys_avail.n_regions; ++i)
 			remove_mem_piece(&prom_mem,
diff -urN linux-2.2.17-pre4/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.2.17-pre4/arch/sparc64/kernel/sys_sparc32.c	Wed May  3 17:16:32 2000
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Mon Dec  3 22:06:19 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.107.2.8 2000/02/28 04:09:49 davem Exp $
+/* $Id: sys_sparc32.c,v 1.107.2.9 2000/06/20 17:12:25 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -2488,7 +2488,8 @@
 	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
 	 */
 	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) {
+	while(((unsigned long)ucmsg) <=
+	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
 		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
 		int clen64, clen32;
 
@@ -3689,8 +3690,10 @@
 		err = nfs_getfh32_trans(karg, arg32);
 		break;
 	case NFSCTL_LOCKD:
-		/* No arguments, no translations... */
-		err = 0;
+		/* We still have to copy over the version
+		 * because nfsctl still checks that.
+		 */
+		err = get_user(karg->ca_version, &arg32->ca32_version);
 		break;
 	default:
 		err = -EINVAL;
diff -urN linux-2.2.17-pre4/drivers/block/cmd646.c linux/drivers/block/cmd646.c
--- linux-2.2.17-pre4/drivers/block/cmd646.c	Wed May  3 17:16:33 2000
+++ linux/drivers/block/cmd646.c	Mon Dec  3 22:06:19 2001
@@ -247,5 +247,9 @@
 	(void) pci_write_config_byte(dev, 0x58, 0x3f);
 	(void) pci_write_config_byte(dev, 0x5b, 0x3f);
 
+#ifdef CONFIG_PPC
+	(void) pci_write_config_byte(dev, 0x73, 0xf0);
+#endif /* CONFIG_PPC */
+
 	hwif->dmaproc = &cmd646_dmaproc;
 }
diff -urN linux-2.2.17-pre4/drivers/block/genhd.c linux/drivers/block/genhd.c
--- linux-2.2.17-pre4/drivers/block/genhd.c	Wed Jun  7 14:26:42 2000
+++ linux/drivers/block/genhd.c	Mon Dec  3 22:06:19 2001
@@ -1089,6 +1089,14 @@
     /* ... more stuff */
 };
 
+static inline void mac_fix_string(char *stg, int len)
+{
+	int i;
+
+	for (i = len - 1; i >= 0 && stg[i] == ' '; i--)
+		stg[i] = 0;
+}
+
 static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
 {
 	struct buffer_head *bh;
@@ -1157,18 +1165,31 @@
 		 */
 		if (_machine == _MACH_Pmac) {
 			int goodness = 0;
+
+			mac_fix_string(part->processor, 16);
+			mac_fix_string(part->name, 32);
+			mac_fix_string(part->type, 32);					
 		    
 			if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
 			    && strcasecmp(part->processor, "powerpc") == 0)
 				goodness++;
 
-			if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0) {
+			if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0
+			    || strcasecmp(part->type, "Linux_PPC") == 0) {
+				int i, l;
+
 				goodness++;
-				if ((strcmp(part->name, "/") == 0) ||
-				    (strstr(part->name, "root") != 0)) {
+				l = strlen(part->name);
+				if (strcmp(part->name, "/") == 0)
 					goodness++;
+				for (i = 0; i <= l - 4; ++i) {
+					if (strnicmp(part->name + i, "root",
+						     4) == 0) {
+						goodness += 2;
+						break;
+					}
 				}
-				if (strncmp(part->name, "swap", 4) == 0)
+				if (strnicmp(part->name, "swap", 4) == 0)
 					goodness--;
 			}
 
diff -urN linux-2.2.17-pre4/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- linux-2.2.17-pre4/drivers/block/ide-cd.c	Mon Dec  3 22:06:13 2001
+++ linux/drivers/block/ide-cd.c	Mon Dec  3 22:06:19 2001
@@ -1768,6 +1768,9 @@
 	if (stat)
 		toc->capacity = 0x1fffff;
 
+	HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
+	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
+
 	/* Remember that we've read this stuff. */
 	CDROM_STATE_FLAGS (drive)->toc_valid = 1;
 
diff -urN linux-2.2.17-pre4/drivers/block/ide-floppy.c linux/drivers/block/ide-floppy.c
--- linux-2.2.17-pre4/drivers/block/ide-floppy.c	Wed Jun  7 14:26:42 2000
+++ linux/drivers/block/ide-floppy.c	Mon Dec  3 22:06:19 2001
@@ -1400,6 +1400,13 @@
 
 	*((unsigned short *) &gcw) = id->config;
 
+#ifdef CONFIG_PPC
+	/* kludge for Apple PowerBook internal zip */
+	if ((gcw.device_type == 5) && !strstr(id->model, "CD-ROM")
+	    && strstr(id->model, "ZIP"))
+		gcw.device_type = 0;			
+#endif
+
 #if IDEFLOPPY_DEBUG_INFO
 	printk (KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n");
 	switch (gcw.protocol) {
diff -urN linux-2.2.17-pre4/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c
--- linux-2.2.17-pre4/drivers/block/ide-pmac.c	Wed Jun  7 14:26:42 2000
+++ linux/drivers/block/ide-pmac.c	Mon Dec  3 22:06:19 2001
@@ -5,6 +5,8 @@
  *
  *  Copyright (C) 1998 Paul Mackerras.
  *
+ *  Bits from Benjamin Herrenschmidt
+ *
  *  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
@@ -35,26 +37,101 @@
 #include "ide.h"
 #include "ide_modes.h"
 
-ide_ioreg_t pmac_ide_regbase[MAX_HWIFS];
-int pmac_ide_irq[MAX_HWIFS];
-int pmac_ide_count;
-struct device_node *pmac_ide_node[MAX_HWIFS];
+#undef IDE_PMAC_DEBUG
+
+#define IDE_SYSCLK_NS		30
+#define IDE_SYSCLK_ULTRA_PS	0x1d4c /* (15 * 1000 / 2)*/
+
+struct pmac_ide_hwif {
+	ide_ioreg_t			regbase;
+	int				irq;
+	int				kind;
+	int				aapl_bus_id;
+	struct device_node*		node;
+	u32				timings[2];
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+	volatile struct dbdma_regs*	dma_regs;
+	struct dbdma_cmd*		dma_table;
+#endif
+	
+} pmac_ide[MAX_HWIFS];
+
+static int pmac_ide_count;
+
+enum {
+	controller_ohare,	/* OHare based */
+	controller_heathrow,	/* Heathrow/Paddington */
+	controller_kl_ata3,	/* KeyLargo ATA-3 */
+	controller_kl_ata4	/* KeyLargo ATA-4 */
+};
+
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+
+typedef struct {
+	int	accessTime;
+	int	cycleTime;
+} pmac_ide_timing;
+
+/* Multiword DMA timings */
+static pmac_ide_timing mdma_timings[] =
+{
+    { 215,    480 },	/* Mode 0 */
+    {  80,    150 },	/*      1 */
+    {  70,    120 }	/*      2 */
+};
+
+/* Ultra DMA timings (for use when I know how to calculate them */
+static pmac_ide_timing udma_timings[] =
+{
+    {   0,    114 },	/* Mode 0 */
+    {   0,     75 },	/*      1 */
+    {   0,     55 },	/*      2 */
+    {   100,   45 },	/*      3 */
+    {   100,   25 }	/*      4 */
+};
+
+/* allow up to 256 DBDMA commands per xfer */
+#define MAX_DCMDS	256
+/* Wait 1.5s for disk to answer on IDE bus after
+ * enable operation.
+ * NOTE: There is at least one case I know of a disk that needs about 10sec
+ *       before anwering on the bus. I beleive we could add a kernel command
+ *       line arg to override this delay for such cases.
+ */
+#define IDE_WAKEUP_DELAY_MS	1500
 #define MAX_DCMDS	256	/* allow up to 256 DBDMA commands per xfer */
 
-static void pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif);
+static void pmac_ide_setup_dma(struct device_node *np, int ix);
 static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
-static int pmac_ide_build_dmatable(ide_drive_t *drive, int wr);
+static int pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr);
+static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio);
+static void pmac_ide_selectproc(ide_drive_t *drive);
+
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 #ifdef CONFIG_PMAC_PBOOK
-static int idepmac_notify(struct pmu_sleep_notifier *self, int when);
+static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when);
 struct pmu_sleep_notifier idepmac_sleep_notifier = {
-	idepmac_notify, SLEEP_LEVEL_BLOCK,
+	idepmac_notify_sleep, SLEEP_LEVEL_BLOCK,
 };
 #endif /* CONFIG_PMAC_PBOOK */
 
+static int
+pmac_ide_find(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	ide_ioreg_t base;
+	int i;
+	
+	for (i=0; i<pmac_ide_count; i++) {
+		base = pmac_ide[i].regbase;
+		if (base && base == hwif->io_ports[0])
+			return i;
+	}
+	return -1;
+}
+
 /*
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
@@ -69,7 +146,7 @@
 		return;
 
 	for (ix = 0; ix < MAX_HWIFS; ++ix)
-		if (base == pmac_ide_regbase[ix])
+		if (base == pmac_ide[ix].regbase)
 			break;
 
 	if (ix >= MAX_HWIFS) {
@@ -83,35 +160,130 @@
 		return;
 	}
 
-	/* we check only for -EINVAL meaning that we have found a matching
-	   bay but with the wrong device type */ 
-
-	i = check_media_bay_by_base(base, MB_CD);
-	if (i == -EINVAL)
-		return;
-		
 	for (i = 0; i < 8; ++i)
 		*p++ = base + i * 0x10;
 	*p = base + 0x160;
 	if (irq != NULL)
-		*irq = pmac_ide_irq[ix];
+		*irq = pmac_ide[ix].irq;
+
+	ide_hwifs[ix].tuneproc = pmac_ide_tuneproc;
+	ide_hwifs[ix].selectproc = pmac_ide_selectproc;
+	if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) {
+		ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
+#ifdef CONFIG_PMAC_IDEDMA_AUTO
+		ide_hwifs[ix].autodma = 1;
+#endif
+	}
 }
 
-void pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
+#if 0
+/* This one could be later extended to handle CMD IDE and be used by some kind
+ * of /proc interface. I want to be able to get the devicetree path of a block
+ * device for yaboot configuration
+ */
+struct device_node*
+pmac_ide_get_devnode(ide_drive_t *drive)
 {
-	ide_pio_data_t d;
+	int i = pmac_ide_find(drive);
+	if (i < 0)
+		return NULL;
+	return pmac_ide[i].node;
+}
+#endif
 
-	if (_machine != _MACH_Pmac)
+/* Setup timings for the selected drive (master/slave). I still need to verify if this
+ * is enough, I beleive selectproc will be called whenever an IDE command is started,
+ * but... */
+static void
+pmac_ide_selectproc(ide_drive_t *drive)
+{
+	int i = pmac_ide_find(drive);
+	if (i < 0)
+		return;
+			
+	if (drive->select.all & 0x10)
+		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]);
+	else
+		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]);
+}
+
+/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
+#define SYSCLK_TICKS(t)		(((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
+#define SYSCLK_TICKS_UDMA(t)	(((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS)
+
+/* Calculate PIO timings */
+static void
+pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
+{
+	ide_pio_data_t d;
+	int i;
+	u32 *timings;
+	int accessTicks, recTicks;
+	
+	i = pmac_ide_find(drive);
+	if (i < 0)
 		return;
+		
 	pio = ide_get_best_pio_mode(drive, pio, 4, &d);
-	switch (pio) {
-	case 4:
-		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), 0x211025);
-		break;
-	default:
-		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), 0x2f8526);
-		break;
+	if (drive->select.all & 0x10)
+		timings = &pmac_ide[i].timings[1];
+	else
+		timings = &pmac_ide[i].timings[0];
+
+	if (pmac_ide[i].kind == controller_kl_ata4) {
+		/* The "ata-4" IDE controller of Core99 machines */
+		accessTicks = SYSCLK_TICKS_UDMA(ide_pio_timings[pio].active_time * 1000);
+		recTicks = SYSCLK_TICKS_UDMA(d.cycle_time * 1000) - accessTicks;
+
+		*timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5);
+	} else {
+		/* The old "ata-3" IDE controller */
+		accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time);
+		if (accessTicks < 4)
+			accessTicks = 4;
+		recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4;
+		if (recTicks < 1)
+			recTicks = 1;
+	
+		*timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);
+	}
+	
+#ifdef IDE_PMAC_DEBUG
+	printk("ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n",
+		pio,  *timings);
+#endif	
+		
+	if (drive->select.all == IN_BYTE(IDE_SELECT_REG))
+		pmac_ide_selectproc(drive);
+}
+
+ide_ioreg_t
+pmac_ide_get_base(int index)
+{
+	return pmac_ide[index].regbase;
+}
+
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+
+__initfunc(kdev_t pmac_find_ide_boot(char *bootdevice, int n))
+{
+	int i;
+	
+	/*
+	 * Look through the list of IDE interfaces for this one.
+	 */
+	for (i = 0; i < pmac_ide_count; ++i) {
+		char *name;
+		if (!pmac_ide[i].node || !pmac_ide[i].node->full_name)
+			continue;
+		name = pmac_ide[i].node->full_name;
+		if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
+			/* XXX should cope with the 2nd drive as well... */
+			return MKDEV(ide_majors[i], 0);
+		}
 	}
+
+	return 0;
 }
 
 __initfunc(void
@@ -122,7 +294,7 @@
 	struct device_node *atas;
 	struct device_node *p, **pp, *removables, **rp;
 	unsigned long base;
-	int irq;
+	int irq, big_delay;
 	ide_hwif_t *hwif;
 
 	if (_machine != _MACH_Pmac)
@@ -150,9 +322,11 @@
 	}
 	*rp = NULL;
 	*pp = removables;
+	big_delay = 0;
 
 	for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
 		struct device_node *tp;
+		int *bidp;
 
 		/*
 		 * If this node is not under a mac-io or dbdma node,
@@ -193,32 +367,79 @@
 		} else {
 			irq = np->intrs[0].line;
 		}
-		pmac_ide_regbase[i] = base;
-		pmac_ide_irq[i] = irq;
-		pmac_ide_node[i] = np;
+		pmac_ide[i].regbase = base;
+		pmac_ide[i].irq = irq;
+		pmac_ide[i].node = np;
+		if (device_is_compatible(np, "keylargo-ata")) {
+			if (strcmp(np->name, "ata-4") == 0)
+				pmac_ide[i].kind = controller_kl_ata4;
+			else
+				pmac_ide[i].kind = controller_kl_ata3;
+		} else if (device_is_compatible(np, "heathrow-ata"))
+			pmac_ide[i].kind = controller_heathrow;
+		else
+			pmac_ide[i].kind = controller_ohare;
+
+		bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
+		pmac_ide[i].aapl_bus_id =  bidp ? *bidp : 0;
 
 		if (np->parent && np->parent->name
 		    && strcasecmp(np->parent->name, "media-bay") == 0) {
 			media_bay_set_ide_infos(np->parent,base,irq,i);
-		} else
-			feature_set(np, FEATURE_IDE_enable);
-
+		} else if (pmac_ide[i].kind == controller_ohare) {
+			/* The code below is having trouble on some ohare machines
+			 * (timing related ?). Until I can put my hand on one of these
+			 * units, I keep the old way
+			 */
+			 feature_set(np, FEATURE_IDE0_enable);
+			 feature_set(np, FEATURE_IOBUS_enable);
+		} else {
+			/* This is necessary to enable IDE when net-booting */
+			printk("pmac_ide: enabling IDE bus ID %d\n", pmac_ide[i].aapl_bus_id);
+			switch(pmac_ide[i].aapl_bus_id) {
+			    case 0:
+				feature_set(np, FEATURE_IDE0_reset);
+				feature_set(np, FEATURE_IOBUS_enable);
+				mdelay(10);
+ 				feature_set(np, FEATURE_IDE0_enable);
+				mdelay(10);
+				feature_clear(np, FEATURE_IDE0_reset);
+				break;
+			    case 1:
+				feature_set(np, FEATURE_IDE1_reset);
+				feature_set(np, FEATURE_IOBUS_enable);
+				mdelay(10);
+ 				feature_set(np, FEATURE_IDE1_enable);
+				mdelay(10);
+				feature_clear(np, FEATURE_IDE1_reset);
+				break;
+			    case 2:
+			    	/* This one exists only for KL, I don't know
+				   about any enable bit */
+				feature_set(np, FEATURE_IDE2_reset);
+				mdelay(10);
+				feature_clear(np, FEATURE_IDE2_reset);
+				break;
+			}
+			big_delay = 1;
+		}
 		hwif = &ide_hwifs[i];
 		pmac_ide_init_hwif_ports(hwif->io_ports, base, &hwif->irq);
-		hwif->chipset = ide_generic;
-		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
-		hwif->tuneproc = pmac_ide_tuneproc;
+		hwif->chipset = ide_pmac;
+		hwif->noprobe = (check_media_bay_by_base(base, MB_CD) == -EINVAL);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 		if (np->n_addrs >= 2) {
 			/* has a DBDMA controller channel */
-			pmac_ide_setup_dma(np, hwif);
+			pmac_ide_setup_dma(np, i);
 		}
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 		++i;
 	}
 	pmac_ide_count = i;
+	if (big_delay)
+		mdelay(IDE_WAKEUP_DELAY_MS);
 
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_register_sleep_notifier(&idepmac_sleep_notifier);
@@ -228,26 +449,27 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
 __initfunc(static void
-pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif))
+pmac_ide_setup_dma(struct device_node *np, int ix))
 {
-	hwif->dma_base = (unsigned long) ioremap(np->addrs[1].address, 0x200);
+	pmac_ide[ix].dma_regs =
+		(volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200);
 
 	/*
 	 * Allocate space for the DBDMA commands.
 	 * The +2 is +1 for the stop command and +1 to allow for
 	 * aligning the start address to a multiple of 16 bytes.
 	 */
-	hwif->dmatable = (unsigned long *)
-	       kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL);
-	if (hwif->dmatable == 0) {
+	pmac_ide[ix].dma_table = (struct dbdma_cmd*)
+		kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL);
+	if (pmac_ide[ix].dma_table == 0) {
 		printk(KERN_ERR "%s: unable to allocate DMA command list\n",
-		       hwif->name);
+		       ide_hwifs[ix].name);
 		return;
 	}
 
-	hwif->dmaproc = &pmac_ide_dmaproc;
+	ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
 #ifdef CONFIG_PMAC_IDEDMA_AUTO
-	hwif->autodma = 1;
+	ide_hwifs[ix].autodma = 1;
 #endif
 }
 
@@ -256,19 +478,20 @@
  * for a transfer and sets the DBDMA channel to point to it.
  */
 static int
-pmac_ide_build_dmatable(ide_drive_t *drive, int wr)
+pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
 {
-	ide_hwif_t *hwif = HWIF(drive);
 	struct dbdma_cmd *table, *tstart;
 	int count = 0;
 	struct request *rq = HWGROUP(drive)->rq;
 	struct buffer_head *bh = rq->bh;
 	unsigned int size, addr;
-	volatile struct dbdma_regs *dma
-		= (volatile struct dbdma_regs *) hwif->dma_base;
+	volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs;
 
-	table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(hwif->dmatable);
+	table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table);
 	out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
+	/* Should this be dma->control like in macserial.c ? */
+	while (in_le32(&dma->status) & RUN)
+		udelay(1);
 
 	do {
 		/*
@@ -331,30 +554,274 @@
 	return 1;
 }
 
+
+/* This is fun.  -DaveM */
+#define IDE_SETXFER		0x03
+#define IDE_SETFEATURE		0xef
+#define IDE_DMA2_ENABLE		0x22
+#define IDE_DMA1_ENABLE		0x21
+#define IDE_DMA0_ENABLE		0x20
+#define IDE_UDMA4_ENABLE	0x44
+#define IDE_UDMA3_ENABLE	0x43
+#define IDE_UDMA2_ENABLE	0x42
+#define IDE_UDMA1_ENABLE	0x41
+#define IDE_UDMA0_ENABLE	0x40
+
+static __inline__ unsigned char
+dma_bits_to_command(unsigned char bits)
+{
+	if(bits & 0x04)
+		return IDE_DMA2_ENABLE;
+	if(bits & 0x02)
+		return IDE_DMA1_ENABLE;
+	return IDE_DMA0_ENABLE;
+}
+
+static __inline__ unsigned char
+udma_bits_to_command(unsigned char bits)
+{
+	if(bits & 0x10)
+		return IDE_UDMA4_ENABLE;
+	if(bits & 0x08)
+		return IDE_UDMA3_ENABLE;
+	if(bits & 0x04)
+		return IDE_UDMA2_ENABLE;
+	if(bits & 0x02)
+		return IDE_UDMA1_ENABLE;
+	if(bits & 0x01)
+		return IDE_UDMA0_ENABLE;
+	return 0;
+}
+
+static __inline__ int
+wait_for_ready(ide_drive_t *drive)
+{
+	/* Timeout bumped for some powerbooks */
+	int timeout = 2000;
+	byte stat;
+
+	while(--timeout) {
+		stat = GET_STAT();
+		if(!(stat & BUSY_STAT)) {
+			if (drive->ready_stat == 0)
+				break;
+			else if((stat & drive->ready_stat) || (stat & ERR_STAT))
+				break;
+		}
+		mdelay(1);
+	}
+	if((stat & ERR_STAT) || timeout <= 0) {
+		if (stat & ERR_STAT) {
+			printk("ide_pmace: wait_for_ready, error status: %x\n", stat);
+		}
+		return 1;
+	}
+	return 0;
+}
+
+static int
+pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
+{
+	unsigned long flags;
+	byte old_select;
+	int result = 1;
+
+	save_flags(flags);
+	cli();
+	old_select = IN_BYTE(IDE_SELECT_REG);
+	OUT_BYTE(drive->select.all, IDE_SELECT_REG);
+	udelay(10);
+	OUT_BYTE(IDE_SETXFER, IDE_FEATURE_REG);
+	OUT_BYTE(command, IDE_NSECTOR_REG);
+	if(wait_for_ready(drive)) {
+		printk("pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
+		goto out;
+	}
+	OUT_BYTE(IDE_SETFEATURE, IDE_COMMAND_REG);
+	result = wait_for_ready(drive);
+	if (result)
+		printk("pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
+out:
+	OUT_BYTE(old_select, IDE_SELECT_REG);
+	restore_flags(flags);
+	
+	return result;
+}
+
+/* Calculate MultiWord DMA timings */
+static int
+pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
+{
+	byte bits = drive->id->dma_mword & 0x07;
+	byte feature = dma_bits_to_command(bits);
+	u32 *timings;
+	int cycleTime, accessTime;
+	int accessTicks, recTicks;
+	struct hd_driveid *id = drive->id;
+	
+	/* Set feature on drive */
+    	printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
+	if (pmac_ide_do_setfeature(drive, feature)) {
+	    	printk("%s: Failed !\n", drive->name);
+	    	return 0;
+	}
+	
+	/* which drive is it ? */
+	if (drive->select.all & 0x10)
+		timings = &pmac_ide[idx].timings[1];
+	else
+		timings = &pmac_ide[idx].timings[0];
+
+	/* Calculate accesstime and cycle time */
+	cycleTime = mdma_timings[feature & 0xf].cycleTime;
+	accessTime = mdma_timings[feature & 0xf].accessTime;
+	if ((id->field_valid & 2) && (id->eide_dma_time))
+		cycleTime = id->eide_dma_time;
+	if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150))
+		cycleTime = 150;
+
+	/* For ata-4 controller, we don't know the calculation */
+	if (pmac_ide[idx].kind == controller_kl_ata4) {
+		accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
+		recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
+		*timings = ((*timings) & 0xffe003ff) |
+			(accessTicks | (recTicks << 5)) << 10;
+	} else {
+		int halfTick = 0;
+		int origAccessTime = accessTime;
+		int origCycleTime = cycleTime;
+		
+		accessTicks = SYSCLK_TICKS(accessTime);
+		if (accessTicks < 1)
+			accessTicks = 1;
+		accessTime = accessTicks * IDE_SYSCLK_NS;
+		recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
+		if (recTicks < 1)
+			recTicks = 1;
+		cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
+
+		/* KeyLargo ata-3 don't support the half-tick stuff */
+		if ((pmac_ide[idx].kind != controller_kl_ata3) &&
+			(accessTicks > 1) &&
+			((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
+			((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
+            			halfTick    = 1;
+				accessTicks--;
+		}
+		*timings = ((*timings) & 0x7FF) |
+			(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
+	}
+#ifdef IDE_PMAC_DEBUG
+	printk("ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
+		feature & 0xf, *timings);
+#endif	
+	return 1;
+}
+
+/* Calculate Ultra DMA timings */
+static int
+pmac_ide_udma_enable(ide_drive_t *drive, int idx)
+{
+	byte bits = drive->id->dma_ultra & 0x1f;
+	byte feature = udma_bits_to_command(bits);
+	int cycleTime, accessTime;
+	int rdyToPauseTicks, cycleTicks;
+	u32 *timings;
+	
+	/* Set feature on drive */
+    	printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
+	if (pmac_ide_do_setfeature(drive, feature)) {
+		printk("%s: Failed !\n", drive->name);
+		return 0;
+	}
+
+	/* which drive is it ? */
+	if (drive->select.all & 0x10)
+		timings = &pmac_ide[idx].timings[1];
+	else
+		timings = &pmac_ide[idx].timings[0];
+	
+
+	cycleTime = udma_timings[feature & 0xf].cycleTime;
+	accessTime = udma_timings[feature & 0xf].accessTime;
+
+	rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
+	cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
+	
+	*timings = ((*timings) & 0xe00fffff) |
+			((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
+	return 1;
+}
+
+static int
+pmac_ide_dma_onoff(ide_drive_t *drive, int enable)
+{
+	int ata4, udma, idx;
+	struct hd_driveid *id = drive->id;
+
+	drive->using_dma = 0;
+	
+	idx = pmac_ide_find(drive);
+	if (idx < 0)
+		return 0;
+		
+	if (drive->media == ide_floppy)
+		enable = 0;
+	if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE))
+		enable = 0;
+	if (check_drive_lists(drive, BAD_DMA_DRIVE))
+		enable = 0;
+
+	udma = 0;
+	ata4 = (pmac_ide[idx].kind == controller_kl_ata4);
+			
+	if(enable) {
+		if (ata4 && (drive->media == ide_disk) &&
+		    (id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) {
+			/* UltraDMA modes. */
+			drive->using_dma = pmac_ide_udma_enable(drive, idx);
+		}
+		if (!drive->using_dma && (id->dma_mword & 0x0007)) {
+			/* Normal MultiWord DMA modes. */
+			drive->using_dma = pmac_ide_mdma_enable(drive, idx);
+		}
+		/* Without this, strange things will happen on Keylargo-based
+		 * machines
+		 */
+		OUT_BYTE(0, IDE_CONTROL_REG);
+		if (drive->select.all == IN_BYTE(IDE_SELECT_REG))
+			pmac_ide_selectproc(drive);
+	}
+	return 0;
+}
+
 int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	volatile struct dbdma_regs *dma
-		= (volatile struct dbdma_regs *) hwif->dma_base;
-	int dstat;
+	int ix, dstat;
+	volatile struct dbdma_regs *dma;
+
+	/* Can we stuff a pointer to our intf structure in config_data
+	 * or select_data in hwif ?
+	 */
+	ix = pmac_ide_find(drive);
+	if (ix < 0)
+		return 0;		
+	dma = pmac_ide[ix].dma_regs;
 
 	switch (func) {
 	case ide_dma_on:
-		/* ide-floppy DMA doesn't work yet... */
-		drive->using_dma = drive->media != ide_floppy;
-		break;
 	case ide_dma_off:
-		printk(KERN_INFO "%s: DMA disabled\n", drive->name);
 	case ide_dma_off_quietly:
-		drive->using_dma = 0;
+		pmac_ide_dma_onoff(drive, (func == ide_dma_on));
 		break;
 	case ide_dma_check:
-		/* ide-floppy DMA doesn't work yet... */
-		drive->using_dma = hwif->autodma && drive->media != ide_floppy;
+		if (hwif->autodma)
+			pmac_ide_dma_onoff(drive, 1);
 		break;
 	case ide_dma_read:
 	case ide_dma_write:
-		if (!pmac_ide_build_dmatable(drive, func==ide_dma_write))
+		if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write))
 			return 1;
 		drive->waiting_for_dma = 1;
 		if (drive->media != ide_disk)
@@ -383,11 +850,9 @@
 #ifdef CONFIG_PMAC_PBOOK
 static void idepmac_sleep_disk(int i, unsigned long base)
 {
+	struct device_node* np = pmac_ide[i].node;
 	int j;
 
-	/* Reset to PIO 0 */
-	out_le32((unsigned *)(base + 0x200 + _IO_BASE), 0x2f8526);
-
 	/* FIXME: We only handle the master IDE */
 	if (ide_hwifs[i].drives[0].media == ide_disk) {
 		/* Spin down the drive */
@@ -406,22 +871,61 @@
 				break;
 		}
 	}
+	feature_set(np, FEATURE_IDE0_reset);
+	feature_clear(np, FEATURE_IDE0_enable);
+	switch(pmac_ide[i].aapl_bus_id) {
+	    case 0:
+		feature_set(np, FEATURE_IDE0_reset);
+		feature_clear(np, FEATURE_IDE0_enable);
+		break;
+	    case 1:
+		feature_set(np, FEATURE_IDE1_reset);
+		feature_clear(np, FEATURE_IDE1_enable);
+		break;
+	    case 2:
+		feature_set(np, FEATURE_IDE2_reset);
+		break;
+	}
+	pmac_ide[i].timings[0] = 0;
+	pmac_ide[i].timings[1] = 0;
 }
 
 static void idepmac_wake_disk(int i, unsigned long base)
 {
+	struct device_node* np = pmac_ide[i].node;
 	int j;
 
 	/* Revive IDE disk and controller */
-	feature_set(pmac_ide_node[i], FEATURE_IDE_enable);
-	mdelay(1);
-	feature_set(pmac_ide_node[i], FEATURE_IDE_DiskPower);
-	mdelay(100);
-	feature_set(pmac_ide_node[i], FEATURE_IDE_Reset);
-	mdelay(1);
-	/* Make sure we are still PIO0 */
-	out_le32((unsigned *)(base + 0x200 + _IO_BASE), 0x2f8526);
-	mdelay(100);
+	switch(pmac_ide[i].aapl_bus_id) {
+	    case 0:
+		feature_set(np, FEATURE_IDE0_reset);
+		feature_set(np, FEATURE_IOBUS_enable);
+		mdelay(10);
+ 		feature_set(np, FEATURE_IDE0_enable);
+		mdelay(10);
+		feature_clear(np, FEATURE_IDE0_reset);
+		break;
+	    case 1:
+		feature_set(np, FEATURE_IDE1_reset);
+		feature_set(np, FEATURE_IOBUS_enable);
+		mdelay(10);
+ 		feature_set(np, FEATURE_IDE1_enable);
+		mdelay(10);
+		feature_clear(np, FEATURE_IDE1_reset);
+		break;
+	    case 2:
+	    	/* This one exists only for KL, I don't know
+		   about any enable bit */
+		feature_set(np, FEATURE_IDE2_reset);
+		mdelay(10);
+		feature_clear(np, FEATURE_IDE2_reset);
+		break;
+	}
+	mdelay(IDE_WAKEUP_DELAY_MS);
+
+	/* Reset timings */
+	pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
+	mdelay(10);
 
 	/* Wait up to 10 seconds (enough for recent drives) */
 	for (j = 0; j < 100; j++) {
@@ -439,14 +943,22 @@
 {
 	int timeout;
 
-	timeout = 5000;
+	/* Reset timings */
+	pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
+	mdelay(10);
+
+	timeout = 10000;
 	while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
 		mdelay(1);
 		--timeout;
 	}
 }
 
-static int idepmac_notify(struct pmu_sleep_notifier *self, int when)
+/* Note: We support only master drives for now. This will have to be
+ * improved if we want to handle sleep on the iMacDV where the CD-ROM
+ * is a slave
+ */
+static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	int i, ret;
 	unsigned long base;
@@ -458,27 +970,34 @@
 		break;
 	case PBOOK_SLEEP_NOW:
 		for (i = 0; i < pmac_ide_count; ++i) {
-			if ((base = pmac_ide_regbase[i]) == 0)
+			if ((base = pmac_ide[i].regbase) == 0)
 				continue;
 			/* Disable irq during sleep */
-			disable_irq(pmac_ide_irq[i]);
+			disable_irq(pmac_ide[i].irq);
 			ret = check_media_bay_by_base(base, MB_CD);
-			if (ret == -ENODEV)
+			if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
 				/* not media bay - put the disk to sleep */
 				idepmac_sleep_disk(i, base);
 		}
 		break;
 	case PBOOK_WAKE:
 		for (i = 0; i < pmac_ide_count; ++i) {
-			if ((base = pmac_ide_regbase[i]) == 0)
+			ide_hwif_t *hwif;
+			if ((base = pmac_ide[i].regbase) == 0)
 				continue;
+			hwif = &ide_hwifs[i];
 		        /* We don't handle media bay devices this way */
 			ret = check_media_bay_by_base(base, MB_CD);
-			if (ret == -ENODEV)
+			if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
 				idepmac_wake_disk(i, base);
 			else if (ret == 0)
 				idepmac_wake_bay(i, base);
-			enable_irq(pmac_ide_irq[i]);
+			enable_irq(pmac_ide[i].irq);
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+			if (hwif->drives[0].present && hwif->drives[0].using_dma)
+				pmac_ide_dma_onoff(&hwif->drives[0], 1);
+#endif				
 		}
 		break;
 	}
diff -urN linux-2.2.17-pre4/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- linux-2.2.17-pre4/drivers/block/ide-probe.c	Wed Jun  7 14:26:42 2000
+++ linux/drivers/block/ide-probe.c	Mon Dec  3 22:06:19 2001
@@ -109,8 +109,16 @@
 				}
 				type = ide_cdrom;	/* Early cdrom models used zero */
 			case ide_cdrom:
-				printk ("CDROM");
 				drive->removable = 1;
+#ifdef CONFIG_PPC
+				/* kludge for Apple PowerBook internal zip */
+				if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {
+					printk ("FLOPPY");
+					type = ide_floppy;
+					break;
+				}
+#endif
+				printk ("CDROM");
 				break;
 			case ide_tape:
 				printk ("TAPE");
diff -urN linux-2.2.17-pre4/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
--- linux-2.2.17-pre4/drivers/block/ide-proc.c	Tue Jan  4 10:12:14 2000
+++ linux/drivers/block/ide-proc.c	Mon Dec  3 22:06:19 2001
@@ -333,6 +333,7 @@
 		case ide_rz1000:	name = "rz1000";	break;
 		case ide_trm290:	name = "trm290";	break;
 		case ide_4drives:	name = "4drives";	break;
+		case ide_pmac:		name = "mac-io";	break;
 		default:		name = "(unknown)";	break;
 	}
 	len = sprintf(page, "%s\n", name);
diff -urN linux-2.2.17-pre4/drivers/block/ide.h linux/drivers/block/ide.h
--- linux-2.2.17-pre4/drivers/block/ide.h	Wed Jun  7 14:26:42 2000
+++ linux/drivers/block/ide.h	Mon Dec  3 22:06:19 2001
@@ -306,7 +306,7 @@
 		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
 		ide_qd6580,	ide_umc8672,	ide_ht6560b,
 		ide_pdc4030,	ide_rz1000,	ide_trm290,
-		ide_cmd646,	ide_4drives
+		ide_cmd646,	ide_4drives,	ide_pmac
 	} hwif_chipset_t;
 
 typedef struct ide_pci_devid_s {
diff -urN linux-2.2.17-pre4/drivers/block/rd.c linux/drivers/block/rd.c
--- linux-2.2.17-pre4/drivers/block/rd.c	Wed Jun  7 14:26:42 2000
+++ linux/drivers/block/rd.c	Mon Dec  3 22:06:19 2001
@@ -587,6 +587,9 @@
 	set_fs(fs);
 }
 
+#ifdef CONFIG_MAC_FLOPPY
+int swim3_fd_eject(int devnum);
+#endif
 
 __initfunc(static void rd_load_disk(int n))
 {
@@ -607,6 +610,12 @@
 	if (rd_prompt) {
 #ifdef CONFIG_BLK_DEV_FD
 		floppy_eject();
+#endif
+#ifdef CONFIG_MAC_FLOPPY
+		if(MAJOR(ROOT_DEV) == FLOPPY_MAJOR)
+			swim3_fd_eject(MINOR(ROOT_DEV));
+		else if(MAJOR(real_root_dev) == FLOPPY_MAJOR)
+			swim3_fd_eject(MINOR(real_root_dev));
 #endif
 		printk(KERN_NOTICE
 		       "VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER\n");
diff -urN linux-2.2.17-pre4/drivers/block/swim3.c linux/drivers/block/swim3.c
--- linux-2.2.17-pre4/drivers/block/swim3.c	Wed Mar 10 21:48:46 1999
+++ linux/drivers/block/swim3.c	Mon Dec  3 22:06:19 2001
@@ -808,6 +808,16 @@
 	return err;
 }
 
+int swim3_fd_eject(int devnum)
+{
+	if (devnum >= floppy_count)
+		return -ENODEV;
+	/* Do not check this - this function should ONLY be called early
+	 * in the boot process! */
+	/* if (floppy_states[devnum].ref_count != 1) return -EBUSY; */
+	return fd_eject(&floppy_states[devnum]);
+}
+
 static struct floppy_struct floppy_type =
 	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL };	/*  7 1.44MB 3.5"   */
 
diff -urN linux-2.2.17-pre4/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile
--- linux-2.2.17-pre4/drivers/macintosh/Makefile	Thu Apr 29 12:53:48 1999
+++ linux/drivers/macintosh/Makefile	Mon Dec  3 22:06:19 2001
@@ -36,6 +36,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_PPC_RTC),y)
+  L_OBJS += rtc.o
+else
+  ifeq ($(CONFIG_PPC_RTC),m)
+    M_OBJS += rtc.o
+  endif
+endif
+
 ifdef CONFIG_MAC_KEYBOARD
 L_OBJS += mac_keyb.o
 endif
diff -urN linux-2.2.17-pre4/drivers/macintosh/rtc.c linux/drivers/macintosh/rtc.c
--- linux-2.2.17-pre4/drivers/macintosh/rtc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/macintosh/rtc.c	Mon Dec  3 22:06:19 2001
@@ -0,0 +1,166 @@
+/*
+ * Linux/PowerPC Real Time Clock Driver
+ *
+ * heavily based on:
+ * Linux/SPARC Real Time Clock Driver
+ * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
+ *
+ * This is a little driver that lets a user-level program access
+ * the PPC clocks chip. It is no use unless you
+ * use the modified clock utility.
+ *
+ * Get the modified clock utility from:
+ *   ftp://vger.rutgers.edu/pub/linux/Sparc/userland/clock.c
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+
+/* in kernel/time.c, these prototypes shouldn't be here */
+extern unsigned long mktime(unsigned int, unsigned int, unsigned int,
+                            unsigned int, unsigned int, unsigned int);
+extern void to_tm(int tim, struct rtc_time * tm);
+
+static int rtc_busy = 0;
+
+/* Retrieve the current date and time from the real time clock. */
+void get_rtc_time(struct rtc_time *t)
+{
+	unsigned long nowtime;
+    
+	nowtime = (ppc_md.get_rtc_time)();
+
+	to_tm(nowtime, t);
+
+	t->tm_year -= 1900;
+	t->tm_mon -= 1;
+	t->tm_wday -= 1;
+}
+
+/* Set the current date and time inthe real time clock. */
+void set_rtc_time(struct rtc_time *t)
+{
+	unsigned long nowtime;
+
+	printk(KERN_INFO "rtc.c:set_rtc_time: %04d-%02d-%02d %02d:%02d:%02d.\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+
+	nowtime = mktime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+
+	printk(KERN_INFO "rtc.c:set_rtc_time: set rtc time to %d seconds.\n", nowtime);
+
+	(ppc_md.set_rtc_time)(nowtime);
+}
+
+static long long rtc_lseek(struct file *file, long long offset, int origin)
+{
+	return -ESPIPE;
+}
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct rtc_time rtc_tm;
+
+	switch (cmd)
+	{
+	case RTC_RD_TIME:
+		if (ppc_md.get_rtc_time)
+		{
+			get_rtc_time(&rtc_tm);
+
+			copy_to_user_ret((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time), -EFAULT);
+
+			return 0;
+		}
+		else
+			return -EINVAL;
+
+	case RTC_SET_TIME:
+		if (!capable(CAP_SYS_TIME))
+			return -EPERM;
+
+		if (ppc_md.set_rtc_time)
+		{
+			copy_from_user_ret(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time), -EFAULT);
+
+			set_rtc_time(&rtc_tm);
+
+			return 0;
+		}
+		else
+			return -EINVAL;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int rtc_open(struct inode *inode, struct file *file)
+{
+	if (rtc_busy)
+		return -EBUSY;
+
+	rtc_busy = 1;
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+	MOD_DEC_USE_COUNT;
+	rtc_busy = 0;
+	return 0;
+}
+
+static struct file_operations rtc_fops = {
+	rtc_lseek,
+	NULL,		/* rtc_read */
+	NULL,		/* rtc_write */
+	NULL,		/* rtc_readdir */
+	NULL,		/* rtc_poll */
+	rtc_ioctl,
+	NULL,		/* rtc_mmap */
+	rtc_open,
+	NULL,		/* flush */
+	rtc_release
+};
+
+static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops };
+
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int rtc_init(void))
+#endif
+{
+	int error;
+
+	error = misc_register(&rtc_dev);
+	if (error) {
+		printk(KERN_ERR "rtc: unable to get misc minor\n");
+		return error;
+	}
+
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	misc_deregister(&rtc_dev);
+}
+#endif
diff -urN linux-2.2.17-pre4/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- linux-2.2.17-pre4/drivers/net/3c59x.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/net/3c59x.c	Mon Dec  3 22:06:19 2001
@@ -42,11 +42,15 @@
     - In vortex_error, do_tx_reset and vortex_tx_timeout(Vortex): clear
       tbusy and force a BH rerun to better recover from errors.
 
+    12Jun00 <2.2.16> andrewm
+    - Better handling of shared interrupts
+    - Reset the transmitter in vortex_error() on both maxcollisions and Tx reclaim error
+
     - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.2 for more details.
 */
 
 static char *version =
-"3c59x.c:v0.99H 27May00 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.99H 12Jun00 Donald Becker and others http://www.scyld.com/network/vortex.html\n";
 
 /* "Knobs" that adjust features and parameters. */
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
@@ -1443,8 +1447,8 @@
 		if (tx_status & 0x14)  vp->stats.tx_fifo_errors++;
 		if (tx_status & 0x38)  vp->stats.tx_aborted_errors++;
 		outb(0, ioaddr + TxStatus);
-		if (tx_status & 0x30)
-			do_tx_reset = 1;
+		if (tx_status & 0x3a)	/* TxReset after 16 collisions, despite what the manual says */
+			do_tx_reset = 1;	/* Also reset on reclaim errors */
 		else					/* Merely re-enable the transmitter. */
 			outw(TxEnable, ioaddr + EL3_CMD);
 	}
@@ -1650,14 +1654,14 @@
 	struct device *dev = dev_id;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr;
-	int latency, status;
+	int status;
 	int work_done = max_interrupt_work;
 
-	spin_lock(&vp->lock);
-
 	ioaddr = dev->base_addr;
-	latency = inb(ioaddr + Timer);
+	spin_lock(&vp->lock);
 	status = inw(ioaddr + EL3_STATUS);
+	if ((status & IntLatch) == 0)
+		goto no_int;	/* Happens during shared interrupts */
 
 	if (status & IntReq) {
 		status |= vp->deferred;
@@ -1666,7 +1670,8 @@
 
 	if (vortex_debug > 4)
 		printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
-			   dev->name, status, latency);
+			   dev->name, status, inb(ioaddr + Timer));
+
 	do {
 		if (vortex_debug > 5)
 				printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
@@ -1761,8 +1766,8 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
 			   dev->name, status);
 
+no_int:
 	spin_unlock(&vp->lock);
-	return;
 }
 
 static int vortex_rx(struct device *dev)
diff -urN linux-2.2.17-pre4/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- linux-2.2.17-pre4/drivers/net/dmfe.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/net/dmfe.c	Mon Dec  3 22:06:19 2001
@@ -102,7 +102,7 @@
 #define DMFE_AUTO       8
 
 #define DMFE_TIMER_WUT  jiffies+(HZ*2)/2	/* timer wakeup time : 1 second */
-#define DMFE_TX_TIMEOUT HZ*1.5	/* tx packet time-out time 1.5 s" */
+#define DMFE_TX_TIMEOUT ((HZ*3)/2)	/* tx packet time-out time 1.5 s" */
 
 #define DMFE_DBUG(dbug_now, msg, vaule) if (dmfe_debug || dbug_now) printk("DBUG: %s %x\n", msg, vaule)
 
diff -urN linux-2.2.17-pre4/drivers/net/hdlc.c linux/drivers/net/hdlc.c
--- linux-2.2.17-pre4/drivers/net/hdlc.c	Mon Dec  3 22:06:14 2001
+++ linux/drivers/net/hdlc.c	Mon Dec  3 22:06:19 2001
@@ -41,7 +41,7 @@
 #ifndef MODULE
 static int version_printed=0;
 #endif
-static const char* version = "HDLC support routines revision: 1.0-pre9";
+static const char* version = "HDLC support routines revision: 1.0-pre10";
 
 
 #define CISCO_MULTICAST         0x8f    /* Cisco multicast address */
@@ -139,9 +139,11 @@
 #endif
 
 	case CISCO_KEEPALIVE:
-		if (skb->len != sizeof(cisco_packet)) {
+		if (skb->len != CISCO_PACKET_LEN && 
+		    skb->len != CISCO_BIG_PACKET_LEN) {
 			printk(KERN_INFO "%s: Invalid length of Cisco "
-			       "control packet\n", hdlc->name);
+			       "control packet (%d bytes)\n", hdlc->name, 
+			       skb->len);
 			goto rx_error;
 		}
 
diff -urN linux-2.2.17-pre4/drivers/net/lmc/Makefile linux/drivers/net/lmc/Makefile
--- linux-2.2.17-pre4/drivers/net/lmc/Makefile	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/Makefile	Mon Dec  3 22:06:19 2001
@@ -6,13 +6,13 @@
 
 ifeq ($(CONFIG_LANMEDIA),y)
     O_TARGET := lmc.o
-    O_OBJS = lmc_debug.o lmc_media.o lmc_main.o
+    O_OBJS = lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o
 else
   ifeq ($(CONFIG_LANMEDIA),m)
     MOD_LIST_NAME := NET_MODULES
     M_OBJS := lmc.o
     O_TARGET := lmc.o
-    O_OBJS = lmc_debug.o lmc_media.o lmc_main.o
+    O_OBJS = lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o
   endif
 endif
 
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc.h linux/drivers/net/lmc/lmc.h
--- linux-2.2.17-pre4/drivers/net/lmc/lmc.h	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/lmc.h	Mon Dec  3 22:06:19 2001
@@ -6,7 +6,7 @@
 /*
  * prototypes for everyone
  */
-int lmc_probe(struct device * dev);
+int lmc_probe(struct net_device * dev);
 unsigned lmc_mii_readreg(lmc_softc_t * const sc, unsigned
       			  devaddr, unsigned regno);
 void lmc_mii_writereg(lmc_softc_t * const sc, unsigned devaddr,
@@ -17,6 +17,8 @@
 void lmc_mii_writereg(lmc_softc_t * const, unsigned, unsigned, unsigned);
 void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits);
 void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits);
+
+int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 extern lmc_media_t lmc_ds3_media;
 extern lmc_media_t lmc_ssi_media;
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_debug.c linux/drivers/net/lmc/lmc_debug.c
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_debug.c	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/lmc_debug.c	Mon Dec  3 22:06:19 2001
@@ -1,6 +1,10 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+#include "lmc_ver.h"
 #include "lmc_debug.h"
 
 /*
@@ -45,20 +49,20 @@
 #endif
 }
 
-#ifdef DEBUG
-u_int32_t lmcEventLogIndex = 0;
-u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
-#endif
+inline void lmc_trace(struct net_device *dev, char *msg){
+#ifdef LMC_TRACE
+    unsigned long j = jiffies + 3; /* Wait for 50 ms */
 
-void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
-{
-#ifdef DEBUG
-  lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
-  lmcEventLogBuf[lmcEventLogIndex++] = arg2;
-  lmcEventLogBuf[lmcEventLogIndex++] = arg3;
-  lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
-
-  lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
+    if(in_interrupt()){
+        printk("%s: * %s\n", dev->name, msg);
+//        while(jiffies < j+10)
+//            ;
+    }
+    else {
+        printk("%s: %s\n", dev->name, msg);
+        while(jiffies < j)
+            schedule();
+    }
 #endif
 }
 
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_debug.h linux/drivers/net/lmc/lmc_debug.h
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_debug.h	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/lmc_debug.h	Mon Dec  3 22:06:19 2001
@@ -11,40 +11,7 @@
 #define LMC_CONSOLE_LOG(x,y,z)
 #endif
 
-
-
-/* Debug --- Event log definitions --- */
-/* EVENTLOGSIZE*EVENTLOGARGS needs to be a power of 2 */
-#define LMC_EVENTLOGSIZE 512	/* number of events in eventlog */
-#define LMC_EVENTLOGARGS 4		/* number of args for each event */
-
-/* event indicators */
-#define LMC_EVENT_XMT           1
-#define LMC_EVENT_XMTEND        2
-#define LMC_EVENT_XMTINT        3
-#define LMC_EVENT_RCVINT        4
-#define LMC_EVENT_RCVEND        5
-#define LMC_EVENT_INT           6
-#define LMC_EVENT_XMTINTTMO     7
-#define LMC_EVENT_XMTPRCTMO     8
-#define LMC_EVENT_INTEND        9
-#define LMC_EVENT_RESET1       10
-#define LMC_EVENT_RESET2       11
-#define LMC_EVENT_FORCEDRESET  12
-#define LMC_EVENT_WATCHDOG     13
-#define LMC_EVENT_BADPKTSURGE  14
-
-
-#ifdef DEBUG
-extern u_int32_t lmcEventLogIndex;
-extern u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
-#define LMC_EVENT_LOG(x, y, z) lmcEventLog((x), (y), (z))
-#else
-#define LMC_EVENT_LOG(x,y,z)
-#endif /* end ifdef _DBG_EVENTLOG */
-
-
 void lmcConsoleLog(char *type, unsigned char *ucData, int iLen);
-void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3);
+inline void lmc_trace(struct net_device *dev, char *msg);
 
 #endif
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_ioctl.h linux/drivers/net/lmc/lmc_ioctl.h
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_ioctl.h	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/lmc_ioctl.h	Mon Dec  3 22:06:19 2001
@@ -1,6 +1,6 @@
 #ifndef _LMC_IOCTL_H_
 #define _LMC_IOCTL_H_
-/*	$Id: lmc_ioctl.h,v 1.9 2000/01/21 13:29:47 asj Exp $	*/
+/*	$Id: lmc_ioctl.h,v 1.18 2000/06/06 08:32:12 asj Exp $	*/
 
  /*
   * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
@@ -16,22 +16,20 @@
   * of the GNU Public License version 2, incorporated herein by reference.
   */
 
-#define LMCIOCGINFO         SIOCDEVPRIVATE+3 /* get current state */
-#define LMCIOCSINFO         SIOCDEVPRIVATE+4 /* set state to user values */
-#define LMCIOCSKEEPALIVE    SIOCDEVPRIVATE+5 /* Turn keepalives on/off */
-#ifdef  LMC_DEBUG_FILE
-#define LMCIOCLEARSTATS LMCIOCSINFO + 1 /* Clear debug stats */
-#endif
-#define LMCIOCGETLMCSTATS       LMCIOCSINFO + 3
-#define LMCIOCCLEARLMCSTATS     LMCIOCSINFO + 4
-#define LMCIOCDUMPEVENTLOG      LMCIOCSINFO + 5
-#define LMCIOCGETXINFO          LMCIOCSINFO + 6
-#define LMCIOCSETCIRCUIT        LMCIOCSINFO + 7
-#define LMCIOCUNUSEDATM         LMCIOCSINFO + 8
-#define LMCIOCRESET             LMCIOCSINFO + 9
-#define LMCIOCT1CONTROL         LMCIOCSINFO + 10
+#define LMCIOCGINFO             SIOCDEVPRIVATE+3 /* get current state */
+#define LMCIOCSINFO             SIOCDEVPRIVATE+4 /* set state to user values */
+#define LMCIOCGETLMCSTATS       SIOCDEVPRIVATE+5
+#define LMCIOCCLEARLMCSTATS     SIOCDEVPRIVATE+6
+#define LMCIOCDUMPEVENTLOG      SIOCDEVPRIVATE+7
+#define LMCIOCGETXINFO          SIOCDEVPRIVATE+8
+#define LMCIOCSETCIRCUIT        SIOCDEVPRIVATE+9
+#define LMCIOCUNUSEDATM         SIOCDEVPRIVATE+10
+#define LMCIOCRESET             SIOCDEVPRIVATE+11
+#define LMCIOCMEDIA             SIOCDEVPRIVATE+12
+#define LMCIOCIFTYPE            SIOCDEVPRIVATE+13
+#define LMCIOCXILINX            SIOCDEVPRIVATE+14
 
-#define LMC_CARDTYPE_UNKNOWN    -1
+#define LMC_CARDTYPE_UNKNOWN            -1
 #define LMC_CARDTYPE_HSSI               1       /* probed card is a HSSI card */
 #define LMC_CARDTYPE_DS3                2       /* probed card is a DS3 card */
 #define LMC_CARDTYPE_SSI                3       /* probed card is a SSI card */
@@ -61,6 +59,13 @@
 #define LMC_CTL_CIRCUIT_TYPE_T1 1
 
 /*
+ * IFTYPE defines
+ */
+#define LMC_PPP         1               /* use sppp interface */
+#define LMC_NET         2               /* use direct net interface */
+#define LMC_RAW         3               /* use direct net interface */
+
+/*
  * These are not in the least IOCTL related, but I want them common.
  */
 /*
@@ -68,10 +73,10 @@
  */
 #define LMC_GEP_INIT		0x01 /* 0: */
 #define LMC_GEP_RESET		0x02 /* 1: */
-#define LMC_GEP_LOAD		0x10 /* 4: */
+#define LMC_GEP_MODE		0x10 /* 4: */
 #define LMC_GEP_DP		0x20 /* 5: */
-#define LMC_GEP_SERIAL		0x40 /* 6: serial out */
-#define LMC_GEP_SERIALCLK	0x80 /* 7: serial clock */
+#define LMC_GEP_DATA		0x40 /* 6: serial out */
+#define LMC_GEP_CLK	        0x80 /* 7: serial clock */
 
 /*
  * HSSI GPIO assignments
@@ -80,12 +85,17 @@
 #define LMC_GEP_HSSI_CLOCK	0x08 /* 3: clock source */
 
 /*
- * T1 GPIO assignments
+ * SSI GPIO assignments
  */
 #define LMC_GEP_SSI_GENERATOR	0x04 /* 2: enable prog freq gen serial i/f */
 #define LMC_GEP_SSI_TXCLOCK	0x08 /* 3: provide clock on TXCLOCK output */
 
 /*
+ * T1 GPIO assigments
+ */
+#define LMC_GEP_T1_INT	        0x08 /* 3: Interupt enable */
+
+/*
  * Common MII16 bits
  */
 #define LMC_MII16_LED0         0x0080
@@ -118,6 +128,7 @@
 #define LMC_MII16_DS3_DLOS	0x0040
 #define LMC_MII16_DS3_CRC	0x1000
 #define LMC_MII16_DS3_SCRAM	0x2000
+#define LMC_MII16_DS3_SCRAM_LARS 0x4000
 
 /* Note: 2 pairs of LEDs where swapped by mistake
  * in Xilinx code for DS3 & DS1 adapters */
@@ -176,7 +187,8 @@
 /*
  * And T1, LMC1200
  */
-#define LMC_MII16_T1_UNUSED1    0x0003
+#define LMC_MII16_T1_UNUSED1            0x0001
+#define LMC_MII16_T1_INVERT             0x0002
 #define LMC_MII16_T1_XOE                0x0004
 #define LMC_MII16_T1_RST                0x0008  /* T1 chip reset - RW */
 #define LMC_MII16_T1_Z                  0x0010  /* output impedance T1=1, E1=0 output - RW */
@@ -224,6 +236,15 @@
 #define LMC_T1F_WRITE       0
 #define LMC_T1F_READ        1
 
+enum lmc_st1f_cmd {
+    lmc_st1f_write = 1,
+    lmc_st1f_read = 2,
+    lmc_st1f_inv = 3,
+    lmc_st1f_amisf = 4,
+    lmc_st1f_frac = 5,
+    lmc_st1f_loopt = 6,
+};
+
 typedef struct lmc_st1f_control {
   int command;
   int address;
@@ -231,9 +252,23 @@
   char *data;
 } lmc_t1f_control;
 
+
+
+enum lmc_xilinx_c {
+    lmc_xilinx_reset = 1,
+    lmc_xilinx_load_prom = 2,
+    lmc_xilinx_load = 3
+};
+
+struct lmc_xilinx_control {
+    enum lmc_xilinx_c command;
+    int len;
+    char *data;
+};
+
 /* ------------------ end T1 defs ------------------- */
 
 #define LMC_MII_LedMask                 0x0780
 #define LMC_MII_LedBitPos               7
 
-#endif
\ No newline at end of file
+#endif
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_main.c linux/drivers/net/lmc/lmc_main.c
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_main.c	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/lmc_main.c	Mon Dec  3 22:06:19 2001
@@ -11,7 +11,7 @@
   * With Help By:
   * David Boggs
   * Ron Crane
-  * Allan Cox
+  * Alan Cox
   *
   * This software may be used and distributed according to the terms
   * of the GNU Public License version 2, incorporated herein by reference.
@@ -36,10 +36,11 @@
   *
   */
 
-/* $Id: lmc_main.c,v 1.24 2000/01/21 13:29:48 asj Exp $ */
+/* $Id: lmc_main.c,v 1.44 2000/06/19 16:53:59 asj Exp $ */
 
-#include <linux/version.h>
 #include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -50,12 +51,10 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/delay.h>
 #include <asm/segment.h>
-#include <asm/smp.h>
-
-#if LINUX_VERSION_CODE < 0x20155
-#include <linux/bios32.h>
-#endif
+#include <linux/init.h>
 
 #include <linux/in.h>
 #include <linux/if_arp.h>
@@ -72,64 +71,75 @@
 
 #if LINUX_VERSION_CODE >= 0x20200
 #include <asm/uaccess.h>
-#include <asm/spinlock.h>
-#endif
-
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
-#include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
+//#include <asm/spinlock.h>
+#else				/* 2.0 kernel */
+#define ARPHRD_HDLC 513
 #endif
 
 #define DRIVER_MAJOR_VERSION     1
-#define DRIVER_MINOR_VERSION    33
-#define DRIVER_SUB_VERSION       1
+#define DRIVER_MINOR_VERSION    34
+#define DRIVER_SUB_VERSION       7
 
 #define DRIVER_VERSION  ((DRIVER_MAJOR_VERSION << 8) + DRIVER_MINOR_VERSION)
 
-#include "lmc.h"
 #include "lmc_ver.h"
+#include "lmc.h"
 #include "lmc_var.h"
 #include "lmc_ioctl.h"
 #include "lmc_debug.h"
+#include "lmc_proto.h"
+
 
 static int Lmc_Count = 0;
-static struct device *Lmc_root_dev = NULL;
+static struct net_device *Lmc_root_dev = NULL;
 static u8 cards_found = 0;
 
 static int lmc_first_load = 0;
 
-int lmc_probe_fake(struct device *dev);
-static struct device *lmc_probe1(struct device *dev, int ioaddr, int irq,
-				 int chip_id, int subdevice, int board_idx);
-static int lmc_start_xmit(struct sk_buff *skb, struct device *dev);
-static int lmc_rx(struct device *dev);
-static int lmc_open(struct device *dev);
-static int lmc_close(struct device *dev);
-static struct enet_statistics *lmc_get_stats(struct device *dev);
+int LMC_PKT_BUF_SZ = 1542;
+
+#if LINUX_VERSION_CODE >= 0x20363
+#ifdef MODULE
+static struct pci_device_id lmc_pci_tbl[] __devinitdata = {
+    { 0x1011, 0x009, 0x1376, PCI_ANY_ID, 0, 0, 0},
+    { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, lmc_pci_tbl);
+#endif
+#endif
+
+
+int lmc_probe_fake(struct net_device *dev);
+static struct net_device *lmc_probe1(struct net_device *dev, unsigned long ioaddr, unsigned int irq,
+				 int chip_id, int subdevice, int board_idx, void *pci_dev);
+static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int lmc_rx (struct net_device *dev);
+static int lmc_open(struct net_device *dev);
+static int lmc_close(struct net_device *dev);
+static struct enet_statistics *lmc_get_stats(struct net_device *dev);
 static void lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int lmc_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static int lmc_set_config(struct device *dev, struct ifmap *map);
-static void lmc_initcsrs(lmc_softc_t * const, u32, size_t);
+static int lmc_set_config(struct net_device *dev, struct ifmap *map);
+static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size);
 static void lmc_softreset(lmc_softc_t * const);
-static void lmc_running_reset(struct device *dev);
-static int lmc_ifdown(struct device * const);
+static void lmc_running_reset(struct net_device *dev);
+static int lmc_ifdown(struct net_device * const);
 static void lmc_watchdog(unsigned long data);
-static int lmc_init(struct device * const);
+static int lmc_init(struct net_device * const);
 static void lmc_reset(lmc_softc_t * const sc);
 static void lmc_dec_reset(lmc_softc_t * const sc);
-static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base,size_t csr_size);
+#if LINUX_VERSION_CODE >= 0x20363
+static void lmc_driver_timeout(struct net_device *dev);
+int lmc_setup(void);
+#endif
+
 
 /*
  * linux reserves 16 device specific IOCTLs.  We call them
  * LMCIOC* to control various bits of our world.
  */
-static int lmc_ioctl (struct device *dev, struct ifreq *ifr, int cmd) /*fold00*/
+int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
 {
     lmc_softc_t *sc;
     lmc_ctl_t ctl;
@@ -143,23 +153,25 @@
 
     sc = dev->priv;
 
+    lmc_trace(dev, "lmc_ioctl in");
+
     /*
      * Most functions mess with the structure
      * Disable interupts while we do the polling
      */
-    spin_lock_irqsave(&sc->lmc_lock, flags);
+    LMC_SPIN_LOCK_IRQSAVE(sc);
 
     switch (cmd) {
         /*
          * Return current driver state.  Since we keep this up
          * To date internally, just copy this out to the user.
          */
-    case LMCIOCGINFO:
+    case LMCIOCGINFO: /*fold01*/
         LMC_COPY_TO_USER(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t));
         ret = 0;
         break;
 
-    case LMCIOCSINFO:
+    case LMCIOCSINFO: /*fold01*/
         sp = &((struct ppp_device *) dev)->sppp;
         if (!suser ()) {
             ret = -EPERM;
@@ -177,6 +189,10 @@
 
         if(ctl.crc_length != sc->ictl.crc_length) {
             sc->lmc_media->set_crc_length(sc, ctl.crc_length);
+	    if (sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16)
+		sc->TxDescriptControlInit |=  LMC_TDES_ADD_CRC_DISABLE;
+	    else
+		sc->TxDescriptControlInit &= ~LMC_TDES_ADD_CRC_DISABLE;
         }
 
         if (ctl.keepalive_onoff == LMC_CTL_OFF)
@@ -186,7 +202,39 @@
 
         ret = 0;
         break;
-    case LMCIOCGETXINFO:
+
+    case LMCIOCIFTYPE: /*fold01*/
+        {
+            u_int16_t	old_type = sc->if_type;
+            u_int16_t	new_type;
+
+	    if (!suser ()) {
+		ret = -EPERM;
+		break;
+	    }
+
+	    LMC_COPY_FROM_USER(&new_type, ifr->ifr_data, sizeof(u_int16_t));
+
+            
+	    if (new_type == old_type)
+	    {
+		ret = 0 ;
+		break;				/* no change */
+            }
+            
+            lmc_proto_close(sc);
+            lmc_proto_detach(sc);
+
+            sc->if_type = new_type;
+//            lmc_proto_init(sc);
+            lmc_proto_attach(sc);
+            lmc_proto_open(sc);
+
+	    ret = 0 ;
+	    break ;
+	}
+
+    case LMCIOCGETXINFO: /*fold01*/
         sc->lmc_xinfo.Magic0 = 0xBEEFCAFE;
 
         sc->lmc_xinfo.PciCardType = sc->lmc_cardtype;
@@ -196,7 +244,7 @@
         sc->lmc_xinfo.DriverSubVersion = DRIVER_SUB_VERSION;
         sc->lmc_xinfo.XilinxRevisionNumber =
             lmc_mii_readreg (sc, 0, 3) & 0xf;
-        sc->lmc_xinfo.MaxFrameSize = PKT_BUF_SZ;
+        sc->lmc_xinfo.MaxFrameSize = LMC_PKT_BUF_SZ;
         sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc);
         sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16);
 
@@ -208,7 +256,7 @@
 
         break;
 
-    case LMCIOCGETLMCSTATS:
+    case LMCIOCGETLMCSTATS: /*fold01*/
         if (sc->lmc_cardtype == LMC_CARDTYPE_T1){
             lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_LSB);
             sc->stats.framingBitErrorCount +=
@@ -239,7 +287,7 @@
         ret = 0;
         break;
 
-    case LMCIOCCLEARLMCSTATS:
+    case LMCIOCCLEARLMCSTATS: /*fold01*/
         if (!suser ()){
             ret = -EPERM;
             break;
@@ -253,7 +301,7 @@
         ret = 0;
         break;
 
-    case LMCIOCSETCIRCUIT:
+    case LMCIOCSETCIRCUIT: /*fold01*/
         if (!suser ()){
             ret = -EPERM;
             break;
@@ -271,7 +319,7 @@
 
         break;
 
-    case LMCIOCRESET:
+    case LMCIOCRESET: /*fold01*/
         if (!suser ()){
             ret = -EPERM;
             break;
@@ -282,31 +330,289 @@
         lmc_running_reset (dev);
         printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
 
-        LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));
-
         ret = 0;
         break;
+    case LMCIOCMEDIA: /*fold01*/
+        ret = sc->lmc_media->ioctl(sc, ifr->ifr_data);
+        break;
+    case LMCIOCXILINX: /*fold01*/
+        {
+            struct lmc_xilinx_control xc; /*fold02*/
 
-#ifdef DEBUG
-    case LMCIOCDUMPEVENTLOG:
-        LMC_COPY_TO_USER(ifr->ifr_data, &lmcEventLogIndex, sizeof (u32));
-        LMC_COPY_TO_USER(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf));
+            if (!suser ()){
+                ret = -EPERM;
+                break;
+            }
+
+            /*
+             * Stop the xwitter whlie we restart the hardware
+             */
+            LMC_XMITTER_BUSY(dev);
+
+            LMC_COPY_FROM_USER(&xc, ifr->ifr_data, sizeof (struct lmc_xilinx_control));
+            switch(xc.command){
+            case lmc_xilinx_reset: /*fold02*/
+                {
+                    u16 mii;
+                    mii = lmc_mii_readreg (sc, 0, 16);
+
+                    /*
+                     * Make all of them 0 and make input
+                     */
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    /*
+                     * make the reset output
+                     */
+                    lmc_gpio_mkoutput(sc, LMC_GEP_RESET);
+
+                    /*
+                     * RESET low to force configuration.  This also forces
+                     * the transmitter clock to be internal, but we expect to reset
+                     * that later anyway.
+                     */
+
+                    sc->lmc_gpio &= ~LMC_GEP_RESET;
+                    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
+
+
+                    /*
+                     * hold for more than 10 microseconds
+                     */
+                    udelay(50);
+
+                    sc->lmc_gpio |= LMC_GEP_RESET;
+                    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
+
+
+                    /*
+                     * stop driving Xilinx-related signals
+                     */
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    /* Reset the frammer hardware */
+                    sc->lmc_media->set_link_status (sc, 1);
+                    sc->lmc_media->set_status (sc, NULL);
+//                    lmc_softreset(sc);
+
+                    {
+                        int i;
+                        for(i = 0; i < 5; i++){
+                            lmc_led_on(sc, LMC_DS3_LED0);
+                            mdelay(100);
+                            lmc_led_off(sc, LMC_DS3_LED0);
+                            lmc_led_on(sc, LMC_DS3_LED1);
+                            mdelay(100);
+                            lmc_led_off(sc, LMC_DS3_LED1);
+                            lmc_led_on(sc, LMC_DS3_LED3);
+                            mdelay(100);
+                            lmc_led_off(sc, LMC_DS3_LED3);
+                            lmc_led_on(sc, LMC_DS3_LED2);
+                            mdelay(100);
+                            lmc_led_off(sc, LMC_DS3_LED2);
+                        }
+                    }
+                    
+                    
+
+                    ret = 0x0;
+
+                }
+
+                break;
+            case lmc_xilinx_load_prom: /*fold02*/
+                {
+                    u16 mii;
+                    int timeout = 500000;
+                    mii = lmc_mii_readreg (sc, 0, 16);
+
+                    /*
+                     * Make all of them 0 and make input
+                     */
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    /*
+                     * make the reset output
+                     */
+                    lmc_gpio_mkoutput(sc,  LMC_GEP_DP | LMC_GEP_RESET);
+
+                    /*
+                     * RESET low to force configuration.  This also forces
+                     * the transmitter clock to be internal, but we expect to reset
+                     * that later anyway.
+                     */
+
+                    sc->lmc_gpio &= ~(LMC_GEP_RESET | LMC_GEP_DP);
+                    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
+
+
+                    /*
+                     * hold for more than 10 microseconds
+                     */
+                    udelay(50);
+
+                    sc->lmc_gpio |= LMC_GEP_DP | LMC_GEP_RESET;
+                    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
+
+                    /*
+                     * busy wait for the chip to reset
+                     */
+                    while( (le32_to_cpu(LMC_CSR_READ(sc, csr_gp)) & LMC_GEP_INIT) == 0 &&
+                           (timeout-- > 0))
+                        ;
+
+                    /*
+                     * stop driving Xilinx-related signals
+                     */
+                    lmc_gpio_mkinput(sc, 0xff);
+                    ret = 0x0;
+                    break;
+
+                }
+
+            case lmc_xilinx_load: /*fold02*/
+                {
+                    char *data;
+                    int pos;
+                    int timeout = 500000;
+
+                    if(xc.data == 0x0){
+                            ret = -EINVAL;
+                            break;
+                    }
+
+                    data = kmalloc(xc.len, GFP_KERNEL);
+                    if(data == 0x0){
+                            printk(KERN_WARNING "%s: Failed to allocate memory for copy\n", dev->name);
+                            ret = -ENOMEM;
+                            break;
+                    }
+                    
+                    LMC_COPY_FROM_USER(data, xc.data, xc.len);
+
+                    printk("%s: Starting load of data Len: %d at 0x%p == 0x%p\n", dev->name, xc.len, xc.data, data);
+
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    /*
+                     * Clear the Xilinx and start prgramming from the DEC
+                     */
+
+                    /*
+                     * Set ouput as:
+                     * Reset: 0 (active)
+                     * DP:    0 (active)
+                     * Mode:  1
+                     *
+                     */
+                    sc->lmc_gpio = 0x00;
+                    sc->lmc_gpio &= ~LMC_GEP_DP;
+                    sc->lmc_gpio &= ~LMC_GEP_RESET;
+                    sc->lmc_gpio |=  LMC_GEP_MODE;
+                    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
+
+                    lmc_gpio_mkoutput(sc, LMC_GEP_MODE | LMC_GEP_DP | LMC_GEP_RESET);
+
+                    /*
+                     * Wait at least 10 us 20 to be safe
+                     */
+                    udelay(50);
+
+                    /*
+                     * Clear reset and activate programing lines
+                     * Reset: Input
+                     * DP:    Input
+                     * Clock: Output
+                     * Data:  Output
+                     * Mode:  Output
+                     */
+                    lmc_gpio_mkinput(sc, LMC_GEP_DP | LMC_GEP_RESET);
+
+                    /*
+                     * Set LOAD, DATA, Clock to 1
+                     */
+                    sc->lmc_gpio = 0x00;
+                    sc->lmc_gpio |= LMC_GEP_MODE;
+                    sc->lmc_gpio |= LMC_GEP_DATA;
+                    sc->lmc_gpio |= LMC_GEP_CLK;
+                    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
+                    
+                    lmc_gpio_mkoutput(sc, LMC_GEP_DATA | LMC_GEP_CLK | LMC_GEP_MODE );
+
+                    /*
+                     * busy wait for the chip to reset
+                     */
+                    while( (le32_to_cpu(LMC_CSR_READ(sc, csr_gp)) & LMC_GEP_INIT) == 0 &&
+                           (timeout-- > 0))
+                        ;
+
+                    printk(KERN_DEBUG "%s: Waited %d for the Xilinx to clear it's memory\n", dev->name, 500000-timeout);
+
+                    for(pos = 0; pos < xc.len; pos++){
+                        switch(data[pos]){
+                        case 0:
+                            sc->lmc_gpio &= ~LMC_GEP_DATA; /* Data is 0 */
+                            break;
+                        case 1:
+                            sc->lmc_gpio |= LMC_GEP_DATA; /* Data is 1 */
+                            break;
+                        default:
+                            printk(KERN_WARNING "%s Bad data in xilinx programing data at %d, got %d wanted 0 or 1\n", dev->name, pos, data[pos]);
+                            sc->lmc_gpio |= LMC_GEP_DATA; /* Assume it's 1 */
+                        }
+                        sc->lmc_gpio &= ~LMC_GEP_CLK; /* Clock to zero */
+                        sc->lmc_gpio |= LMC_GEP_MODE;
+                        LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
+                        udelay(1);
+                        
+                        sc->lmc_gpio |= LMC_GEP_CLK; /* Put the clack back to one */
+                        sc->lmc_gpio |= LMC_GEP_MODE;
+                        LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
+                        udelay(1);
+                    }
+                    if((le32_to_cpu(LMC_CSR_READ(sc, csr_gp)) & LMC_GEP_INIT) == 0){
+                        printk(KERN_WARNING "%s: Reprograming FAILED. Needs to be reprogramed. (corrupted data)\n", dev->name);
+                    }
+                    else if((le32_to_cpu(LMC_CSR_READ(sc, csr_gp)) & LMC_GEP_DP) == 0){
+                        printk(KERN_WARNING "%s: Reprograming FAILED. Needs to be reprogramed. (done)\n", dev->name);
+                    }
+                    else {
+                        printk(KERN_DEBUG "%s: Done reprograming Xilinx, %d bits, good luck!\n", dev->name, pos);
+                    }
+
+                    lmc_gpio_mkinput(sc, 0xff);
+                    
+                    sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET;
+                    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+
+                    sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET;
+                    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+
+                    kfree(data);
+                    
+                    ret = 0;
+                    
+                    break;
+                }
+            default: /*fold02*/
+                ret = -EBADE;
+                break;
+            }
+
+            LMC_XMITTER_FREE(dev);
+            sc->lmc_txfull = 0;
 
-        ret = 0;
-        break;
-#endif /* end ifdef _DBG_EVENTLOG */
-    case LMCIOCT1CONTROL:
-        if (sc->lmc_cardtype != LMC_CARDTYPE_T1){
-            ret = -EOPNOTSUPP;
-            break;
         }
         break;
-    default:
-        /* If we don't know what to do, give syncppp a shot. */
-        ret = sppp_do_ioctl (dev, ifr, cmd);
+    default: /*fold01*/
+        /* If we don't know what to do, give the protocol a shot. */
+        ret = lmc_proto_ioctl (sc, ifr, cmd);
+        break;
     }
 
-    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+    LMC_SPIN_UNLOCK_IRQRESTORE(sc); /*fold01*/
+
+    lmc_trace(dev, "lmc_ioctl out");
 
     return ret;
 }
@@ -315,29 +621,35 @@
 /* the watchdog process that cruises around */
 static void lmc_watchdog (unsigned long data) /*fold00*/
 {
-    struct device *dev = (struct device *) data;
+    struct net_device *dev = (struct net_device *) data;
     lmc_softc_t *sc;
     int link_status;
     u_int32_t ticks;
-    LMC_SPIN_FLAGS
+    LMC_SPIN_FLAGS;
 
     sc = dev->priv;
 
-    spin_lock_irqsave(&sc->lmc_lock, flags);
+    lmc_trace(dev, "lmc_watchdog in");
+
+    LMC_SPIN_LOCK_IRQSAVE(sc);
+
+    if(sc->check != 0xBEAFCAFE){
+        printk("LMC: Corrupt net_device stuct, breaking out\n");
+        return;
+    }
+
 
     /* Make sure the tx jabber and rx watchdog are off,
      * and the transmit and recieve processes are running.
      */
 
-    LMC_CSR_WRITE (sc, csr_15, 0x00000011);
+    LMC_CSR_WRITE (sc, csr_15, cpu_to_le32(0x00000011));
     sc->lmc_cmdmode |= TULIP_CMD_TXRUN | TULIP_CMD_RXRUN;
-    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+    LMC_CSR_WRITE (sc, csr_command, cpu_to_le32(sc->lmc_cmdmode));
 
     if (sc->lmc_ok == 0)
         goto kick_timer;
 
-    LMC_EVENT_LOG(LMC_EVENT_WATCHDOG, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));
-
     /* --- begin time out check -----------------------------------
      * check for a transmit interrupt timeout
      * Has the packet xmt vs xmt serviced threshold been exceeded */
@@ -354,26 +666,12 @@
              sc->tx_TimeoutInd)
     {
 
-        LMC_EVENT_LOG(LMC_EVENT_XMTINTTMO, LMC_CSR_READ (sc, csr_status), 0);
-
         sc->tx_TimeoutDisplay = 1;
         sc->stats.tx_TimeoutCnt++;
 
         /* DEC chip is stuck, hit it with a RESET!!!! */
         lmc_running_reset (dev);
 
-
-        /* look at receive & transmit process state to make sure they are running */
-        LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
-
-        /* look at: DSR - 02  for Reg 16
-         *                  CTS - 08
-         *                  DCD - 10
-         *                  RI  - 20
-         * for Reg 17
-         */
-        LMC_EVENT_LOG(LMC_EVENT_RESET2, lmc_mii_readreg (sc, 0, 16), lmc_mii_readreg (sc, 0, 17));
-
         /* reset the transmit timeout detection flag */
         sc->tx_TimeoutInd = 0;
         sc->lastlmc_taint_tx = sc->lmc_taint_tx;
@@ -396,7 +694,7 @@
      * Mark it as down.
      */
     if ((link_status == 0) && (sc->last_link_status != 0)) {
-        printk(KERN_WARNING "%s: link down\n", dev->name);
+        printk(KERN_WARNING "%s: hardware/physical link down\n", dev->name);
         sc->last_link_status = 0;
         /* lmc_reset (sc); Why reset??? The link can go down ok */
 
@@ -409,7 +707,7 @@
      * Bring it back up again.
      */
      if (link_status != 0 && sc->last_link_status == 0) {
-         printk(KERN_WARNING "%s: link up\n", dev->name);
+         printk(KERN_WARNING "%s: hardware/physical link up\n", dev->name);
          sc->last_link_status = 1;
          /* lmc_reset (sc); Again why reset??? */
 
@@ -424,7 +722,7 @@
           * --bbraun
           */
 
-         sppp_reopen (dev);
+         lmc_proto_reopen(sc);
 
      }
 
@@ -435,7 +733,29 @@
      * Poke the transmitter to make sure it
      * never stops, even if we run out of mem
      */
-    LMC_CSR_WRITE(sc, csr_rxpoll, 0);
+    LMC_CSR_WRITE(sc, csr_rxpoll, cpu_to_le32(0));
+
+    /*
+     * Check for code that failed
+     * and try and fix it as appropriate
+     */
+    if(sc->failed_ring == 1){
+        /*
+         * Failed to setup the recv/xmit rin
+         * Try again
+         */
+        sc->failed_ring = 0;
+        lmc_softreset(sc);
+    }
+    if(sc->failed_recv_alloc == 1){
+        /*
+         * We failed to alloc mem in the
+         * interupt halder, go through the rings
+         * and rebuild them
+         */
+        sc->failed_recv_alloc = 0;
+        lmc_softreset(sc);
+    }
 
 
     /*
@@ -443,8 +763,8 @@
      */
 kick_timer:
 
-    ticks = LMC_CSR_READ (sc, csr_gp_timer);
-    LMC_CSR_WRITE (sc, csr_gp_timer, 0xffffffffUL);
+    ticks = le32_to_cpu(LMC_CSR_READ (sc, csr_gp_timer));
+    LMC_CSR_WRITE (sc, csr_gp_timer, cpu_to_le32(0xffffffffUL));
     sc->ictl.ticks = 0x0000ffff - (ticks & 0x0000ffff);
 
     /*
@@ -453,58 +773,87 @@
     sc->timer.expires = jiffies + (HZ);
     add_timer (&sc->timer);
 
-    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+    LMC_SPIN_UNLOCK_IRQRESTORE(sc);
+
+    lmc_trace(dev, "lmc_watchdog out");
 
 }
 
-static int lmc_init(struct device * const dev) /*fold00*/
+static int lmc_init(struct net_device * const dev) /*fold00*/
 {
+    lmc_trace(dev, "lmc_init in");
+    lmc_trace(dev, "lmc_init out");
+	
     return 0;
 }
 
 /* This initializes each card from lmc_probe() */
-static struct device *lmc_probe1 (struct device *dev, int ioaddr, int irq, /*fold00*/
-                                  int chip_id, int subdevice, int board_idx)
+static struct net_device *lmc_probe1 (struct net_device *dev, unsigned long ioaddr, unsigned int irq, /*FOLD00*/
+                                  int chip_id, int subdevice, int board_idx, void *pci_dev)
 {
     lmc_softc_t *sc = NULL;
     u_int16_t AdapModelNum;
-
+#if LINUX_VERSION_CODE >= 0x20363
+    struct pci_dev *pdev = pci_dev;
+    dma_addr_t dma_handle;
+#endif
     /*
      * Allocate our own device structure
      */
-
+    
+#if LINUX_VERSION_CODE < 0x20210 /* Changed in 2.2.16 */
     dev = kmalloc (sizeof (struct ppp_device)+8, GFP_KERNEL);
+#else
+    dev = kmalloc (sizeof (struct net_device)+8, GFP_KERNEL);
+#endif
     if (dev == NULL){
         printk (KERN_ERR "lmc: kmalloc for device failed\n");
         return NULL;
     }
-    memset (dev, 0, sizeof (struct ppp_device));
+    memset (dev, 0, sizeof (struct net_device));
 
-	/*
-	 *	Switch to common hdlc%d naming. We name by type not by vendor
-	 */
-    dev->name = (char *) (((u32) (dev)) + sizeof (struct ppp_device));
+#ifndef GCOM
+    /*
+     *	Switch to common hdlc%d naming. We name by type not by vendor
+     */
+#if LINUX_VERSION_CODE < 0x20210
+    dev->name = ((char *) (dev)) + sizeof (struct ppp_device);
+#elif LINUX_VERSION_CODE < 0x20363
+    dev->name = ((char *) (dev)) + sizeof (struct net_device);
+#endif
+
+#if LINUX_VERSION_CODE >= 0x20200
     dev_alloc_name(dev, "hdlc%d");
+#else
+    sprintf(dev->name, "hdlc%d", Lmc_Count);
+#endif
+    
+#else
+    /*
+     * GCOM uses LMC vendor name so that clients can know which card
+     * to attach to.
+     */
+    dev->name = ((char *) (dev)) + sizeof (struct ppp_device);
+    dev_alloc_name(dev, "lmc%d");
+#endif
 
+    lmc_trace(dev, "lmc_probe1 in");
+    
     Lmc_Count++;
 
     if(lmc_first_load == 0){
         printk(KERN_INFO "Lan Media Corporation WAN Driver Version %d.%d.%d\n",DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION,DRIVER_SUB_VERSION);
-#ifndef MODULE
-        sync_ppp_init();
-#endif
         lmc_first_load = 1;
     }
-
-
-    /* Initialize the sppp layer */
-    sppp_attach ((struct ppp_device *) dev);
-
+    
     /*
      * Allocate space for the private data structure
      */
-
+#if LINUX_VERSION_CODE >= 0x20363
+    sc = pci_alloc_consistent(pdev, sizeof (lmc_softc_t), &dma_handle);
+#else
     sc = kmalloc (sizeof (lmc_softc_t), GFP_KERNEL);
+#endif
     if (sc == NULL) {
         printk (KERN_WARNING "%s: Cannot allocate memory for device state\n",
                 dev->name);
@@ -514,16 +863,37 @@
     dev->priv = sc;
     sc->lmc_device = dev;
     sc->name = dev->name;
-
+    sc->if_type = LMC_PPP;
+    sc->check = 0xBEAFCAFE;
+#if LINUX_VERSION_CODE >= 0x20363
+    sc->pdev = pdev;
+    sc->sc_dma_handle = dma_handle;
+    sc->sc_dma = (lmc_softc_t *) dma_handle;
+#endif
+    
+    dev->base_addr = ioaddr;
+    dev->irq = irq;
+    /*
+     * This will get the protocol layer ready and do any 1 time init's
+     * Must have a valid sc and dev structure
+     */
+    lmc_proto_init(sc);
+    lmc_proto_attach(sc);
     /* Just fill in the entries for the device */
 
     dev->init = lmc_init;
+    dev->type = ARPHRD_HDLC;
     dev->hard_start_xmit = lmc_start_xmit;
     dev->open = lmc_open;
     dev->stop = lmc_close;
     dev->get_stats = lmc_get_stats;
     dev->do_ioctl = lmc_ioctl;
     dev->set_config = lmc_set_config;
+#if LINUX_VERSION_CODE >= 0x20363
+    dev->tx_timeout = lmc_driver_timeout;
+    dev->watchdog_timeo = (HZ); /* 1 second */
+#endif
+
     /*
      * Why were we changing this???
      dev->tx_queue_len = 100;
@@ -531,18 +901,15 @@
 
     /* Init the spin lock so can call it latter */
 
-    spin_lock_init(&sc->lmc_lock);
+    LMC_SPIN_LOCK_INIT(sc);
 
     LMC_SETUP_20_DEV;
-
-    printk ("%s: detected at %#3x, irq %d\n", dev->name, ioaddr, irq);
-
-    dev->base_addr = ioaddr;
-    dev->irq = irq;
+    
+    printk ("%s: detected at %lx, irq %d\n", dev->name, ioaddr, dev->irq);
 
     if (register_netdev (dev) != 0) {
         printk (KERN_ERR "%s: register_netdev failed.\n", dev->name);
-        sppp_detach (dev);
+        lmc_proto_detach(sc);
         kfree (dev->priv);
         kfree (dev);
         return NULL;
@@ -610,14 +977,14 @@
 
     }
     else {
-        printk ("%s: Model number (%d) miscompare for PCI Subsystem ID = 0x%04x\n",
+        /* Print a warning but not a major failure case */
+        printk (KERN_WARNING "%s: Model number (%d) miscompare for PCI Subsystem ID = 0x%04x\n",
                 dev->name, AdapModelNum, subdevice);
-        return (NULL);
     }
     /*
      * reset clock
      */
-    LMC_CSR_WRITE (sc, csr_gp_timer, 0xFFFFFFFFUL);
+    LMC_CSR_WRITE (sc, csr_gp_timer, cpu_to_le32(0xFFFFFFFFUL));
 
     sc->board_idx = board_idx;
 
@@ -631,6 +998,8 @@
     sc->lmc_ok = 0;
     sc->last_link_status = 0;
 
+    lmc_trace(dev, "lmc_probe1 out");
+
     return dev;
 }
 
@@ -638,19 +1007,29 @@
 /* This is the entry point.  This is what is called immediatly. */
 /* This goes out and finds the card */
 
-int lmc_probe_fake(struct device *dev)
+int lmc_probe_fake(struct net_device *dev) /*fold00*/
 {
     lmc_probe(NULL);
     /* Return 1 to unloaded bogus device */
     return 1;
 }
 
-int lmc_probe (struct device *dev) /*fold00*/
+int lmc_probe (struct net_device *dev) /*fold00*/
 {
     int pci_index = 0;
+#if LINUX_VERSION_CODE >= 0x20155
+    unsigned long pci_ioaddr;
+    unsigned int pci_irq_line;
+    struct pci_dev *pdev;
+#if LINUX_VERSION_CODE < 0x20363
+    unsigned short pci_command;
+#endif
+#else
     unsigned char pci_irq_line;
+    u32 pci_ioaddr;
+#endif
     u16 vendor, subvendor, device, subdevice;
-    u32 pci_ioaddr, foundaddr = 0;
+    u32 foundaddr = 0;
     unsigned char pci_bus, pci_device_fn;
     u8 intcf = 0;
 
@@ -674,16 +1053,31 @@
         /* Read the info we need to determine if this is
          * our card or not
          */
-#if LINUX_VERSION_CODE >= 0x20155
-        vendor = pci_find_slot (pci_bus, pci_device_fn)->vendor;
-        device = pci_find_slot (pci_bus, pci_device_fn)->device;
-        pci_irq_line = pci_find_slot (pci_bus, pci_device_fn)->irq;
-        pci_ioaddr = pci_find_slot (pci_bus, pci_device_fn)->base_address[0];
-        pci_read_config_word (pci_find_slot (pci_bus, pci_device_fn),
-                              PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
-        pci_read_config_word (pci_find_slot (pci_bus, pci_device_fn),
-                              PCI_SUBSYSTEM_ID, &subdevice);
-#else
+#if LINUX_VERSION_CODE >= 0x20155 /* 2.2, 2.4 */
+        pdev = pci_find_slot (pci_bus, pci_device_fn);
+        
+        if (!pdev)
+            break;
+
+#if LINUX_VERSION_CODE >= 0x20363
+        if(pci_enable_device(pdev)){
+            break;
+        }
+#endif
+        
+        vendor = pdev->vendor;
+        device = pdev->device;
+        pci_irq_line = pdev->irq;
+#if LINUX_VERSION_CODE < 0x20363 /* 2.2 */
+        pci_ioaddr = pdev->base_address[0];
+        pci_read_config_word (pdev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
+        pci_read_config_word (pdev, PCI_SUBSYSTEM_ID, &subdevice);
+#else /* 2.4 */
+        pci_ioaddr = pci_resource_start (pdev, 0);
+        subvendor = pdev->subsystem_vendor;
+        subdevice = pdev->subsystem_device;
+#endif
+#else /* 2.0 */
         pcibios_read_config_word (pci_bus, pci_device_fn,
                                   PCI_VENDOR_ID, &vendor);
         pcibios_read_config_word (pci_bus, pci_device_fn,
@@ -717,7 +1111,7 @@
             (vendor == CORRECT_VENDOR_ID) &&
             (device == CORRECT_DEV_ID) &&
             ((subvendor == PCI_VENDOR_LMC)  || (subdevice == PCI_VENDOR_LMC))){
-            struct device *cur, *prev = NULL;
+            struct net_device *cur, *prev = NULL;
 
             /* Fix the error, exchange the two values */
             if(subdevice == PCI_VENDOR_LMC){
@@ -725,9 +1119,27 @@
                 subvendor = PCI_VENDOR_LMC ;
             }
 
+            /* Set the bus master bit */
+#if LINUX_VERSION_CODE < 0x20363
+#if LINUX_VERSION_CODE > 0x20155
+            pci_read_config_word(pdev, PCI_COMMAND,
+                                 &pci_command);
+            pci_command |= PCI_COMMAND_MASTER;
+            pci_write_config_word(pdev, PCI_COMMAND,
+                                  pci_command);
+#endif
+            /* Make the call to actually setup this card */
+            dev = lmc_probe1 (dev, pci_ioaddr, pci_irq_line,
+                              device, subdevice, cards_found, 0x0);
+
+#else
+            pci_set_master (pdev);
             /* Make the call to actually setup this card */
             dev = lmc_probe1 (dev, pci_ioaddr, pci_irq_line,
-                              device, subdevice, cards_found);
+                              device, subdevice, cards_found, pdev);
+
+#endif
+
             if (dev == NULL) {
                 printk ("lmc_probe: lmc_probe1 failed\n");
                 goto lmc_probe_next_card;
@@ -769,28 +1181,28 @@
 /* After this is called, packets can be sent.
  * Does not initialize the addresses
  */
-static int lmc_open (struct device *dev) /*fold00*/
+static int lmc_open (struct net_device *dev) /*fold00*/
 {
     lmc_softc_t *sc = dev->priv;
-    int err;
 
-    lmc_dec_reset (sc);
-    lmc_reset (sc);
+    lmc_trace(dev, "lmc_open in");
 
-    LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
-    LMC_EVENT_LOG(LMC_EVENT_RESET2,
-                  lmc_mii_readreg (sc, 0, 16),
-                  lmc_mii_readreg (sc, 0, 17));
+    lmc_led_on(sc, LMC_DS3_LED0);
 
+    lmc_dec_reset (sc);
+    lmc_reset (sc);
 
-    if (sc->lmc_ok)
+    if (sc->lmc_ok){
+        lmc_trace(dev, "lmc_open lmc_ok out");
         return (0);
+    }
 
     lmc_softreset (sc);
 
     /* Since we have to use PCI bus, this should work on x86,alpha,ppc */
     if (request_irq (dev->irq, &lmc_interrupt, SA_SHIRQ, dev->name, dev)){
         printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
+        lmc_trace(dev, "lmc_open irq failed out");
         return -EAGAIN;
     }
     sc->got_irq = 1;
@@ -818,17 +1230,23 @@
         /* disable 32 bit CRC generated by ASIC */
         sc->TxDescriptControlInit |= LMC_TDES_ADD_CRC_DISABLE;
     }
+    sc->lmc_media->set_crc_length(sc, sc->ictl.crc_length);
     /* Acknoledge the Terminal Active and light LEDs */
 
     /* dev->flags |= IFF_UP; */
 
-    err = sppp_open (dev);
-    if (err){
-        return err;
-    }
+    lmc_proto_open(sc);
+
     dev->do_ioctl = lmc_ioctl;
-    dev->tbusy = 0;
+
+
+    LMC_XMITTER_INIT(dev);
+    
+#if LINUX_VERSION_CODE < 0x20363
     dev->start = 1;
+#endif
+    
+    sc->stats.tx_tbusy0++ ;
 
     MOD_INC_USE_COUNT;
 
@@ -845,12 +1263,13 @@
                          | TULIP_STS_TXSTOPPED
                          | TULIP_STS_TXUNDERFLOW
                          | TULIP_STS_RXSTOPPED
+		         | TULIP_STS_RXNOBUF
                         );
-    LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask);
+    LMC_CSR_WRITE (sc, csr_intr, cpu_to_le32(sc->lmc_intrmask));
 
     sc->lmc_cmdmode |= TULIP_CMD_TXRUN;
     sc->lmc_cmdmode |= TULIP_CMD_RXRUN;
-    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+    LMC_CSR_WRITE (sc, csr_command, cpu_to_le32(sc->lmc_cmdmode));
 
     sc->lmc_ok = 1; /* Run watchdog */
 
@@ -870,6 +1289,8 @@
     sc->timer.function = &lmc_watchdog;
     add_timer (&sc->timer);
 
+    lmc_trace(dev, "lmc_open out");
+
     return (0);
 }
 
@@ -877,14 +1298,16 @@
  *  under heavy load
  */
 
-static void lmc_running_reset (struct device *dev) /*fold00*/
+static void lmc_running_reset (struct net_device *dev) /*fold00*/
 {
 
     lmc_softc_t *sc = (lmc_softc_t *) dev->priv;
 
+    lmc_trace(dev, "lmc_runnig_reset in");
+
     /* stop interrupts */
     /* Clear the interrupt mask */
-    LMC_CSR_WRITE (sc, csr_intr, 0x00000000);
+    LMC_CSR_WRITE (sc, csr_intr, cpu_to_le32(0x00000000));
 
     lmc_dec_reset (sc);
     lmc_reset (sc);
@@ -893,15 +1316,20 @@
     sc->lmc_media->set_link_status (sc, 1);
     sc->lmc_media->set_status (sc, NULL);
 
-    dev->flags |= IFF_RUNNING;
-    dev->tbusy = 0;
+    //dev->flags |= IFF_RUNNING;
+    
+    LMC_XMITTER_FREE(dev);
+
     sc->lmc_txfull = 0;
+    sc->stats.tx_tbusy0++ ;
 
     sc->lmc_intrmask = TULIP_DEFAULT_INTR_MASK;
-    LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask);
+    LMC_CSR_WRITE (sc, csr_intr, cpu_to_le32(sc->lmc_intrmask));
 
     sc->lmc_cmdmode |= (TULIP_CMD_TXRUN | TULIP_CMD_RXRUN);
-    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+    LMC_CSR_WRITE (sc, csr_command, cpu_to_le32(sc->lmc_cmdmode));
+
+    lmc_trace(dev, "lmc_runnin_reset_out");
 }
 
 
@@ -909,47 +1337,68 @@
  * This disables the timer for the watchdog and keepalives,
  * and disables the irq for dev.
  */
-static int lmc_close (struct device *dev) /*fold00*/
+static int lmc_close (struct net_device *dev) /*fold00*/
 {
     /* not calling release_region() as we should */
-    lmc_softc_t *sc;
+    lmc_softc_t *sc = dev->priv;
 
+    lmc_trace(dev, "lmc_close in");
+    
     sc = dev->priv;
     sc->lmc_ok = 0;
     sc->lmc_media->set_link_status (sc, 0);
     del_timer (&sc->timer);
-    sppp_close (dev);
+    lmc_proto_close(sc);
     lmc_ifdown (dev);
 
+#if LINUX_VERSION_CODE < 0x20363
+    dev->start = 0;
+#endif
+
+    
+    /*
+     * Let's make sure all the leds are off
+     * when not configured
+     */
+    lmc_led_off(sc, LMC_DS3_LED0);
+    lmc_led_off(sc, LMC_DS3_LED1);
+    lmc_led_off(sc, LMC_DS3_LED2);
+    lmc_led_off(sc, LMC_DS3_LED3);
+
+    lmc_trace(dev, "lmc_close out");
+    
     return 0;
 }
 
 /* Ends the transfer of packets */
 /* When the interface goes down, this is called */
-static int lmc_ifdown (struct device *dev) /*fold00*/
+static int lmc_ifdown (struct net_device *dev) /*fold00*/
 {
     lmc_softc_t *sc = dev->priv;
     u32 csr6;
     int i;
 
+    lmc_trace(dev, "lmc_ifdown in");
+    
     /* Don't let anything else go on right now */
-    dev->start = 0;
-    dev->tbusy = 1;
+    //    dev->start = 0;
+    LMC_XMITTER_BUSY(dev);
+    sc->stats.tx_tbusy1++ ;
 
     /* stop interrupts */
     /* Clear the interrupt mask */
-    LMC_CSR_WRITE (sc, csr_intr, 0x00000000);
+    LMC_CSR_WRITE (sc, csr_intr, cpu_to_le32(0x00000000));
 
     /* Stop Tx and Rx on the chip */
-    csr6 = LMC_CSR_READ (sc, csr_command);
+    csr6 = le32_to_cpu(LMC_CSR_READ (sc, csr_command));
     csr6 &= ~LMC_DEC_ST;		/* Turn off the Transmission bit */
     csr6 &= ~LMC_DEC_SR;		/* Turn off the Recieve bit */
-    LMC_CSR_WRITE (sc, csr_command, csr6);
+    LMC_CSR_WRITE (sc, csr_command, cpu_to_le32(csr6));
 
     dev->flags &= ~IFF_RUNNING;
 
     sc->stats.rx_missed_errors +=
-        LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;
+        le32_to_cpu(LMC_CSR_READ (sc, csr_missed_frames)) & 0xffff;
 
     /* release the interrupt */
     if(sc->got_irq == 1){
@@ -982,7 +1431,10 @@
 
     lmc_led_off (sc, LMC_MII16_LED_ALL);
 
-    dev->tbusy = 0;
+    LMC_XMITTER_FREE(dev);
+    sc->stats.tx_tbusy0++ ;
+
+    lmc_trace(dev, "lmc_ifdown out");
 
     MOD_DEC_USE_COUNT;
     return 0;
@@ -993,31 +1445,34 @@
  */
 static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/
 {
-    struct device *dev = (struct device *) dev_instance;
-    lmc_softc_t *sc;
+    struct net_device *dev = (struct net_device *) dev_instance;
+    lmc_softc_t *sc = dev->priv;
     u32 csr;
     int i;
     s32 stat;
     unsigned int badtx;
     u32 firstcsr;
+    int max_work = LMC_RXDESCS;
+    unsigned long flags;
 
-    sc = dev->priv;
+    lmc_trace(dev, "lmc_interrupt in");
 
-    spin_lock(&sc->lmc_lock);
 
-    if (test_and_set_bit (0, (void *) &dev->interrupt)) {
-        goto lmc_int_fail_out;
-    }
+    LMC_SPIN_LOCK_IRQSAVE(sc);
 
     /*
      * Read the csr to find what interupts we have (if any)
      */
-    csr = LMC_CSR_READ (sc, csr_status);
+    csr = le32_to_cpu(LMC_CSR_READ (sc, csr_status));
 
     /*
      * Make sure this is our interrupt
      */
     if ( ! (csr & sc->lmc_intrmask)) {
+        /*
+         * If it's not make sure it's not a media interupt first
+         */
+        sc->lmc_media->got_interupt(sc);
         goto lmc_int_fail_out;
     }
 
@@ -1025,11 +1480,10 @@
 
     /* always go through this loop at least once */
     while (csr & sc->lmc_intrmask) {
-
         /*
          * Clear interupt bits, we handle all case below
          */
-        LMC_CSR_WRITE (sc, csr_status, csr);
+        LMC_CSR_WRITE (sc, csr_status, cpu_to_le32(csr));
 
         /*
          * One of
@@ -1048,14 +1502,15 @@
             lmc_running_reset (dev);
             break;
         }
-
         
-        if (csr & (TULIP_STS_RXINTR | TULIP_STS_RXNOBUF)) {
-	  lmc_rx (dev);
+        if (csr & TULIP_STS_RXINTR){
+            lmc_trace(dev, "rx interupt");
+            lmc_rx (dev);
+            
         }
-        
         if (csr & (TULIP_STS_TXINTR | TULIP_STS_TXNOBUF | TULIP_STS_TXSTOPPED)) {
 
+	    int		n_compl = 0 ;
             /* reset the transmit timeout detection flag -baz */
             sc->stats.tx_NoCompleteCnt = 0;
 
@@ -1063,15 +1518,15 @@
             i = badtx % LMC_TXDESCS;
 
             while ((badtx < sc->lmc_next_tx)) {
-                stat = sc->lmc_txring[i].status;
+                stat = le32_to_cpu(sc->lmc_txring[i].status);
 
-                LMC_EVENT_LOG (LMC_EVENT_XMTINT, stat, 0);
                 /*
                  * If bit 31 is 1 the tulip owns it break out of the loop
                  */
-                if (stat < 0)
+                if (stat & 0x80000000)
                     break;
 
+		n_compl++ ;		/* i.e., have an empty slot in ring */
                 /*
                  * If we have no skbuff or have cleared it
                  * Already continue to the next buffer
@@ -1096,13 +1551,16 @@
                 else {
                     
 #if LINUX_VERSION_CODE >= 0x20200
-                    sc->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff;
+                    sc->stats.tx_bytes += le32_to_cpu(sc->lmc_txring[i].length) & 0x7ff;
 #endif
                     
                     sc->stats.tx_packets++;
                 }
-                
-                LMC_DEV_KFREE_SKB (sc->lmc_txq[i]);
+
+#if LINUX_VERSION_CODE >= 0x20363 /* 2.4 */
+                pci_unmap_single(sc->pdev, sc->lmc_txring[i].buffer1, sc->lmc_txq[i]->len, PCI_DMA_TODEVICE);
+#endif
+                dev_kfree_skb_irq(sc->lmc_txq[i]);
                 sc->lmc_txq[i] = 0;
 
                 badtx++;
@@ -1115,20 +1573,13 @@
                 badtx += LMC_TXDESCS;
             }
             sc->lmc_txfull = 0;
-            dev->tbusy = 0;
-            mark_bh (NET_BH);  /* Tell Linux to give me more packets */
-
-#ifdef DEBUG
-            sc->stats.dirtyTx = badtx;
-            sc->stats.lmc_next_tx = sc->lmc_next_tx;
-            sc->stats.lmc_txfull = sc->lmc_txfull;
-            sc->stats.tbusy = dev->tbusy;
+            LMC_XMITTER_FREE(dev);
+            sc->stats.tx_tbusy0++ ;
+#if LINUX_VERSION_CODE < 0x20363
+            mark_bh (NET_BH);	/* Tell Linux to give me more packets */
 #endif
             sc->lmc_taint_tx = badtx;
 
-            /*
-             * Why was there a break here???
-             */
         }			/* end handle transmit interrupt */
 
         if (csr & TULIP_STS_SYSERROR) {
@@ -1150,29 +1601,30 @@
             }
             lmc_dec_reset (sc);
             lmc_reset (sc);
-            LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
-            LMC_EVENT_LOG(LMC_EVENT_RESET2,
-                          lmc_mii_readreg (sc, 0, 16),
-                          lmc_mii_readreg (sc, 0, 17));
 
         }
+
+        
+        if(max_work-- <= 0)
+            break;
+        
         /*
          * Get current csr status to make sure
          * we've cleared all interupts
          */
-        csr = LMC_CSR_READ (sc, csr_status);
+        csr = le32_to_cpu(LMC_CSR_READ (sc, csr_status));
     }				/* end interrupt loop */
-    LMC_EVENT_LOG(LMC_EVENT_INT, firstcsr, csr);
-
-    dev->interrupt = 0;
 
 lmc_int_fail_out:
 
-    spin_unlock(&sc->lmc_lock);
+    LMC_SPIN_UNLOCK_IRQRESTORE(sc);
+
+    lmc_trace(dev, "lmc_interrupt out");
+
     return;
 }
 
-static int lmc_start_xmit (struct sk_buff *skb, struct device *dev) /*fold00*/
+static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/
 {
     lmc_softc_t *sc;
     u32 flag;
@@ -1180,13 +1632,11 @@
     int ret = 0;
     LMC_SPIN_FLAGS;
 
-    sc = dev->priv;
+    lmc_trace(dev, "lmc_start_xmit in");
 
-    /* the interface better be up */
-    if ( ! (dev->flags & IFF_UP))
-        return 1;
+    sc = dev->priv;
 
-    spin_lock_irqsave(&sc->lmc_lock, flags);
+    LMC_SPIN_LOCK_IRQSAVE(sc);
 
     /*
      * If the transmitter is busy
@@ -1195,9 +1645,13 @@
      * Poke the chip and try to get it running
      *
      */
-    if (dev->tbusy) {
+#if LINUX_VERSION_CODE < 0x20363
+    if(dev->tbusy != 0){
         u32 csr6;
 
+        printk("%s: Xmitter busy|\n", dev->name);
+
+	sc->stats.tx_tbusy_calls++ ;
         if (jiffies - dev->trans_start < TX_TIMEOUT) {
             ret = 1;
             goto lmc_start_xmit_bug_out;
@@ -1210,24 +1664,15 @@
          * table and starts from scartch
          */
 
-        LMC_EVENT_LOG(LMC_EVENT_XMTPRCTMO,
-                      LMC_CSR_READ (sc, csr_status),
-                      sc->stats.tx_ProcTimeout);
-
         lmc_running_reset (dev);
 
-        LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
-        LMC_EVENT_LOG(LMC_EVENT_RESET2,
-                      lmc_mii_readreg (sc, 0, 16),
-                      lmc_mii_readreg (sc, 0, 17));
-
         /* restart the tx processes */
-        csr6 = LMC_CSR_READ (sc, csr_command);
-        LMC_CSR_WRITE (sc, csr_command, csr6 | 0x0002);
-        LMC_CSR_WRITE (sc, csr_command, csr6 | 0x2002);
+        csr6 = le32_to_cpu(LMC_CSR_READ (sc, csr_command));
+        LMC_CSR_WRITE (sc, csr_command, cpu_to_le32(csr6 | 0x0002));
+        LMC_CSR_WRITE (sc, csr_command, cpu_to_le32(csr6 | 0x2002));
 
         /* immediate transmit */
-        LMC_CSR_WRITE (sc, csr_txpoll, 0);
+        LMC_CSR_WRITE (sc, csr_txpoll, cpu_to_le32(0));
 
         sc->stats.tx_errors++;
         sc->stats.tx_ProcTimeout++;	/* -baz */
@@ -1237,57 +1682,66 @@
         ret = 1;
         goto lmc_start_xmit_bug_out;
     }
-    /* normal path */
+#endif
+    /* normal path, tbusy known to be zero */
 
     entry = sc->lmc_next_tx % LMC_TXDESCS;
 
     sc->lmc_txq[entry] = skb;
+#if LINUX_VERSION_CODE >= 0x20363
+    sc->lmc_txring[entry].buffer1 = pci_map_single (sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+#else
     sc->lmc_txring[entry].buffer1 = virt_to_bus (skb->data);
+#endif
 
     LMC_CONSOLE_LOG("xmit", skb->data, skb->len);
 
+#ifndef GCOM
     /* If the queue is less than half full, don't interrupt */
     if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS / 2)
     {
         /* Do not interrupt on completion of this packet */
         flag = 0x60000000;
-        dev->tbusy = 0;
+        LMC_XMITTER_FREE(dev);
     }
     else if (sc->lmc_next_tx - sc->lmc_taint_tx == LMC_TXDESCS / 2)
     {
         /* This generates an interrupt on completion of this packet */
         flag = 0xe0000000;
-        dev->tbusy = 0;
+        LMC_XMITTER_FREE(dev);
     }
     else if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS - 1)
     {
         /* Do not interrupt on completion of this packet */
         flag = 0x60000000;
-        dev->tbusy = 0;
+        LMC_XMITTER_FREE(dev);
     }
     else
     {
         /* This generates an interrupt on completion of this packet */
         flag = 0xe0000000;
         sc->lmc_txfull = 1;
-        dev->tbusy = 1;
+        LMC_XMITTER_BUSY(dev);
     }
+#else
+    flag = LMC_TDES_INTERRUPT_ON_COMPLETION;
 
-    if ((entry == LMC_TXDESCS - 1))
-    {
-        flag |= 0xe2000000;
-        dev->tbusy = 1;
+    if (sc->lmc_next_tx - sc->lmc_taint_tx >= LMC_TXDESCS - 1)
+    {				/* ring full, go busy */
+        sc->lmc_txfull = 1;
+        LMC_XMITTER_BUSY(dev);
+        sc->stats.tx_tbusy1++ ;
+        LMC_EVENT_LOG(LMC_EVENT_TBUSY1, entry, 0);
     }
-    /* don't pad small packets either */
-    sc->lmc_txring[entry].length = (skb->len) | flag | sc->TxDescriptControlInit;
+#endif
 
-    /* Done above through TxDescControlInit */
-    /*
-     sc->lmc_txring[entry].length = (skb->len) | flag | 0x00800000;
-     if(sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16){
-     sc->lmc_txring[entry].length |= 0x04000000;
-     }
-     */
+
+    if (entry == LMC_TXDESCS - 1)	/* last descriptor in ring */
+	flag |= LMC_TDES_END_OF_RING;	/* flag as such for Tulip */
+
+    /* don't pad small packets either */
+    flag = sc->lmc_txring[entry].length = cpu_to_le32((skb->len) | flag |
+						sc->TxDescriptControlInit);
 
     /* set the transmit timeout flag to be checked in
      * the watchdog timer handler. -baz
@@ -1296,22 +1750,25 @@
     sc->stats.tx_NoCompleteCnt++;
     sc->lmc_next_tx++;
 
-    /* give ownership to the chip */
-    sc->lmc_txring[entry].status = 0x80000000;
+    sc->lmc_txring[entry].status = cpu_to_le32(0x80000000);
 
     /* send now! */
-    LMC_CSR_WRITE (sc, csr_txpoll, 0);
+    LMC_CSR_WRITE (sc, csr_txpoll, cpu_to_le32(0));
 
     dev->trans_start = jiffies;
 
+#if LINUX_VERSION_CODE < 0x20363
 lmc_start_xmit_bug_out:
+#endif
+
+    LMC_SPIN_UNLOCK_IRQRESTORE(sc);
 
-    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+    lmc_trace(dev, "lmc_start_xmit_out");
     return ret;
 }
 
 
-static int lmc_rx (struct device *dev) /*fold00*/
+static int lmc_rx (struct net_device *dev) /*fold00*/
 {
     lmc_softc_t *sc;
     int i;
@@ -1323,45 +1780,44 @@
     struct sk_buff *skb, *nsb;
     u16 len;
 
-    sc = dev->priv;
+    lmc_trace(dev, "lmc_rx in");
 
-    if ( ! (dev->flags & IFF_UP))
-        return 1;
+    sc = dev->priv;
 
-    rxIntLoopCnt = 0;		/* debug -baz */
+    rxIntLoopCnt = 0;
 
     i = sc->lmc_next_rx % LMC_RXDESCS;
     next_rx = sc->lmc_next_rx;
 
-    while (((stat = sc->lmc_rxring[i].status) & LMC_RDES_OWN_BIT) != DESC_OWNED_BY_DC21X4)
+    while (((stat = le32_to_cpu(sc->lmc_rxring[i].status)) & LMC_RDES_OWN_BIT) != DESC_OWNED_BY_DC21X4)
     {
         rxIntLoopCnt++;		/* debug -baz */
-        LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, 0);
-
+        len = ((stat & LMC_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER);
         if ((stat & 0x0300) != 0x0300) {  /* Check first segment and last segment */
             if ((stat & 0x0000ffff) != 0x7fff) {
                 /* Oversized frame */
                 sc->stats.rx_length_errors++;
+                sc->stats.rx_errors++;
                 goto skip_packet;
             }
         }
 
-        if(stat & 0x00000008){ /* Catch a dribbling bit error */
+        if(stat & 0x00000004){ /* Catch a dribbling bit error */
             sc->stats.rx_errors++;
             sc->stats.rx_frame_errors++;
             goto skip_packet;
         }
 
 
-        if(stat & 0x00000004){ /* Catch a CRC error by the Xilinx */
+        if(stat & 0x00000008){ /* Catch a CRC error by the Xilinx */
             sc->stats.rx_errors++;
             sc->stats.rx_crc_errors++;
             goto skip_packet;
         }
 
 
-        len = ((stat & LMC_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER);
-        if (len > PKT_BUF_SZ){
+        if (len > LMC_PKT_BUF_SZ){
+            sc->stats.rx_errors++;
             sc->stats.rx_length_errors++;
             localLengthErrCnt++;
             goto skip_packet;
@@ -1370,6 +1826,7 @@
         if (len < sc->lmc_crcSize + 2) {
             sc->stats.rx_length_errors++;
             sc->stats.rx_SmallPktCnt++;
+            sc->stats.rx_errors++;
             localLengthErrCnt++;
             goto skip_packet;
         }
@@ -1388,19 +1845,29 @@
          */
         
         if(skb == 0x0){
-            nsb = dev_alloc_skb (PKT_BUF_SZ + 2);
+            nsb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2);
             if (nsb) {
                 LMC_SKB_FREE(nsb, 1);
                 sc->lmc_rxq[i] = nsb;
                 nsb->dev = dev;
+#if LINUX_VERSION_CODE >= 0x20363
+                sc->lmc_rxring[i].buffer1 = pci_map_single(sc->pdev, nsb->tail, LMC_PKT_BUF_SZ+2, PCI_DMA_FROMDEVICE);
+#else
                 sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail);
+#endif
             }
+            sc->failed_recv_alloc = 1;
             goto skip_packet;
         }
         
         dev->last_rx = jiffies;
         sc->stats.rx_packets++;
 
+#if LINUX_VERSION_CODE >= 0x20363
+#ifdef LMC_PACKET_LOG
+        pci_dma_sync_single(sc->pdev, sc->lmc_rxring[i].buffer1, len, PCI_DMA_FROMDEVICE);
+#endif
+#endif
         LMC_CONSOLE_LOG("recv", skb->data, len);
 
         /*
@@ -1410,31 +1877,39 @@
          * them into a new buffer??
          */
         
-        if(len > (3*LMC_MTU)/4){
+        if(len > (LMC_MTU - (LMC_MTU>>2))){ /* len > LMC_MTU * 0.75 */
             /*
              * If it's a large packet don't copy it just hand it up
              */
         give_it_anyways:
 
             sc->lmc_rxq[i] = 0x0;
-            sc->lmc_rxring[i].buffer1 = 0x0;
+            sc->lmc_rxring[i].buffer1 = cpu_to_le32(0x0);
 
             skb_put (skb, len);
-            skb->protocol=htons(ETH_P_WAN_PPP);
+            skb->protocol = lmc_proto_type(sc, skb);
+            skb->protocol = htons(ETH_P_WAN_PPP);
             skb->mac.raw = skb->data;
-            skb->nh.raw = skb->data;
+//            skb->nh.raw = skb->data;
             skb->dev = dev;
-            netif_rx(skb);
+#if LINUX_VERSION_CODE >= 0x20363 /* 2.4 */
+            pci_unmap_single(sc->pdev, sc->lmc_rxring[i].buffer1, len, PCI_DMA_FROMDEVICE);
+#endif
+            lmc_proto_netif(sc, skb);
 
             /*
              * This skb will be destroyed by the upper layers, make a new one
              */
-            nsb = dev_alloc_skb (PKT_BUF_SZ + 2);
+            nsb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2);
             if (nsb) {
                 LMC_SKB_FREE(nsb, 1);
                 sc->lmc_rxq[i] = nsb;
                 nsb->dev = dev;
+#if LINUX_VERSION_CODE >= 0x20363
+                sc->lmc_rxring[i].buffer1 = pci_map_single(sc->pdev, nsb->tail, LMC_PKT_BUF_SZ+2, PCI_DMA_FROMDEVICE);
+#else
                 sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail);
+#endif
                 /* Transfered to 21140 below */
             }
             else {
@@ -1447,10 +1922,9 @@
                  * again.  (once a second)
                  */
                 sc->stats.rx_BuffAllocErr++;
+                sc->failed_recv_alloc = 1;
                 goto skip_out_of_mem;
-
             }
-
         }
         else {
             nsb = dev_alloc_skb(len);
@@ -1458,15 +1932,19 @@
                 goto give_it_anyways;
             }
             memcpy(skb_put(nsb, len), skb->data, len);
-            nsb->protocol=htons(ETH_P_WAN_PPP);
+            
+            nsb->protocol = lmc_proto_type(sc, skb);
             nsb->mac.raw = nsb->data;
-            nsb->nh.raw = nsb->data;
+            //            nsb->nh.raw = nsb->data;
             nsb->dev = dev;
-            netif_rx(nsb);
+#if LINUX_VERSION_CODE >= 0x20363 /* 2.4 */
+            pci_unmap_single(sc->pdev, sc->lmc_rxring[i].buffer1, len, PCI_DMA_FROMDEVICE);
+#endif
+            lmc_proto_netif(sc, nsb);
         }
 
     skip_packet:
-        sc->lmc_rxring[i].status = DESC_OWNED_BY_DC21X4;
+        sc->lmc_rxring[i].status = cpu_to_le32(DESC_OWNED_BY_DC21X4);
 
         sc->lmc_next_rx++;
         i = sc->lmc_next_rx % LMC_RXDESCS;
@@ -1475,54 +1953,34 @@
             break;
     }
     
-    /* detect condition for LMC1000 where DSU cable attaches and fills
-     * descriptors with bogus packets
-     */
-    if (localLengthErrCnt > LMC_RXDESCS - 3) {
-        sc->stats.rx_BadPktSurgeCnt++;
-        LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE,
-                      localLengthErrCnt,
-                      sc->stats.rx_BadPktSurgeCnt);
-    }
-
     /* save max count of receive descriptors serviced */
     if (rxIntLoopCnt > sc->stats.rxIntLoopCnt) {
         sc->stats.rxIntLoopCnt = rxIntLoopCnt;	/* debug -baz */
     }
 
-#ifdef DEBUG
-    if (rxIntLoopCnt == 0)
-    {
-        for (i = 0; i < LMC_RXDESCS; i++)
-        {
-            if ((sc->lmc_rxring[i].status & LMC_RDES_OWN_BIT)
-                != DESC_OWNED_BY_DC21X4)
-            {
-                rxIntLoopCnt++;
-            }
-        }
-        LMC_EVENT_LOG(LMC_EVENT_RCVEND, rxIntLoopCnt, 0);
-    }
-#endif
-
 skip_out_of_mem:
 
+    lmc_trace(dev, "lmc_rx out");
+
     return 0;
 }
 
-static struct enet_statistics *lmc_get_stats (struct device *dev) /*fold00*/
+static struct enet_statistics *lmc_get_stats (struct net_device *dev) /*fold00*/
 {
     lmc_softc_t *sc;
     LMC_SPIN_FLAGS;
 
+    lmc_trace(dev, "lmc_get_stats in");
+
     sc = dev->priv;
 
-    spin_lock_irqsave(&sc->lmc_lock, flags);
+    LMC_SPIN_LOCK_IRQSAVE(sc);
+
+    sc->stats.rx_missed_errors += le32_to_cpu(LMC_CSR_READ (sc, csr_missed_frames)) & 0xffff;
 
-    if (dev->start)
-        sc->stats.rx_missed_errors += LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;
+    LMC_SPIN_UNLOCK_IRQRESTORE(sc);
 
-    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+    lmc_trace(dev, "lmc_get_stats out");
 
     return (struct enet_statistics *) &sc->stats;
 }
@@ -1542,7 +2000,8 @@
 
 void cleanup_module (void) /*fold00*/
 {
-    struct device *dev, *next;
+    struct net_device *dev, *next;
+    lmc_softc_t *sc;
 
     /* we have no pointer to our devices, since they are all dynamically
      * allocated.  So, here we loop through all the network devices
@@ -1559,19 +2018,27 @@
 
         /* close the syncppp stuff, and release irq. Close is run on unreg net */
         lmc_close (dev);
-        sppp_detach (dev);
+        
+        sc = dev->priv;
+
+        printk ("%s: detaching from protocol...\n", dev->name);
+        if (sc != NULL)
+            lmc_proto_detach(sc);
 
-        /* Remove the device from the linked list */
         unregister_netdev (dev);
 
         /* Let go of the io region */;
         release_region (dev->base_addr, LMC_REG_RANGE);
 
         /* free our allocated structures. */
+#if LINUX_VERSION_CODE >= 0x20363
+        pci_free_consistent(sc->pdev, sizeof(lmc_softc_t), sc, sc->sc_dma_handle);
+#else
         kfree (dev->priv);
+#endif
         dev->priv = NULL;
 
-        kfree ((struct ppp_device *) dev);
+        kfree (dev);
         dev = NULL;
     }
 
@@ -1587,40 +2054,49 @@
     int command = (0xf6 << 10) | (devaddr << 5) | regno;
     int retval = 0;
 
+    lmc_trace(sc->lmc_device, "lmc_mii_readreg in");
+
     LMC_MII_SYNC (sc);
 
+    lmc_trace(sc->lmc_device, "lmc_mii_readreg: done sync");
+
     for (i = 15; i >= 0; i--)
     {
         int dataval = (command & (1 << i)) ? 0x20000 : 0;
 
-        LMC_CSR_WRITE (sc, csr_9, dataval);
+        LMC_CSR_WRITE (sc, csr_9, cpu_to_le32(dataval));
         lmc_delay ();
         /* __SLOW_DOWN_IO; */
-        LMC_CSR_WRITE (sc, csr_9, dataval | 0x10000);
+        LMC_CSR_WRITE (sc, csr_9, cpu_to_le32(dataval | 0x10000));
         lmc_delay ();
         /* __SLOW_DOWN_IO; */
     }
 
+    lmc_trace(sc->lmc_device, "lmc_mii_readreg: done1");
+
     for (i = 19; i > 0; i--)
     {
-        LMC_CSR_WRITE (sc, csr_9, 0x40000);
+        LMC_CSR_WRITE (sc, csr_9, cpu_to_le32(0x40000));
         lmc_delay ();
         /* __SLOW_DOWN_IO; */
-        retval = (retval << 1) | ((LMC_CSR_READ (sc, csr_9) & 0x80000) ? 1 : 0);
-        LMC_CSR_WRITE (sc, csr_9, 0x40000 | 0x10000);
+        retval = (retval << 1) | (le32_to_cpu((LMC_CSR_READ(sc, csr_9)) & 0x80000) ? 1 : 0);
+        LMC_CSR_WRITE (sc, csr_9, cpu_to_le32(0x40000 | 0x10000));
         lmc_delay ();
         /* __SLOW_DOWN_IO; */
     }
 
+    lmc_trace(sc->lmc_device, "lmc_mii_readreg out");
+
     return (retval >> 1) & 0xffff;
 }
 
-void lmc_mii_writereg (lmc_softc_t * const sc, unsigned devaddr, /*fold00*/
-                       unsigned regno, unsigned data)
+void lmc_mii_writereg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno, unsigned data) /*fold00*/
 {
     int i = 32;
     int command = (0x5002 << 16) | (devaddr << 23) | (regno << 18) | data;
 
+    lmc_trace(sc->lmc_device, "lmc_mii_writereg in");
+
     LMC_MII_SYNC (sc);
 
     i = 31;
@@ -1633,10 +2109,10 @@
         else
             datav = 0x00000;
 
-        LMC_CSR_WRITE (sc, csr_9, datav);
+        LMC_CSR_WRITE (sc, csr_9, cpu_to_le32(datav));
         lmc_delay ();
         /* __SLOW_DOWN_IO; */
-        LMC_CSR_WRITE (sc, csr_9, (datav | 0x10000));
+        LMC_CSR_WRITE (sc, csr_9, cpu_to_le32(datav | 0x10000));
         lmc_delay ();
         /* __SLOW_DOWN_IO; */
         i--;
@@ -1645,20 +2121,24 @@
     i = 2;
     while (i > 0)
     {
-        LMC_CSR_WRITE (sc, csr_9, 0x40000);
+        LMC_CSR_WRITE (sc, csr_9, cpu_to_le32(0x40000));
         lmc_delay ();
         /* __SLOW_DOWN_IO; */
-        LMC_CSR_WRITE (sc, csr_9, 0x50000);
+        LMC_CSR_WRITE (sc, csr_9, cpu_to_le32(0x50000));
         lmc_delay ();
         /* __SLOW_DOWN_IO; */
         i--;
     }
+
+    lmc_trace(sc->lmc_device, "lmc_mii_writereg out");
 }
 
 static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/
 {
     int i;
 
+    lmc_trace(sc->lmc_device, "lmc_softreset in");
+
     /* Initialize the recieve rings and buffers. */
     sc->lmc_txfull = 0;
     sc->lmc_next_rx = 0;
@@ -1678,8 +2158,15 @@
 
         if (sc->lmc_rxq[i] == NULL)
         {
-            skb = dev_alloc_skb (PKT_BUF_SZ + 2);
-            sc->lmc_rxq[i] = skb;
+            skb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2);
+            if(skb == NULL){
+                printk(KERN_WARNING "%s: Failed to allocate receiver ring, will try again\n", sc->name);
+                sc->failed_ring = 1;
+                break;
+            }
+            else{
+                sc->lmc_rxq[i] = skb;
+            }
         }
         else
         {
@@ -1690,77 +2177,120 @@
         LMC_SKB_FREE(skb, 1);
 
         /* owned by 21140 */
-        sc->lmc_rxring[i].status = 0x80000000;
+        sc->lmc_rxring[i].status = cpu_to_le32(0x80000000);
 
         /* used to be PKT_BUF_SZ now uses skb since we loose some to head room */
-        sc->lmc_rxring[i].length = skb->end - skb->data;
+        sc->lmc_rxring[i].length = cpu_to_le32(skb->end - skb->data);
 
         /* use to be tail which is dumb since you're thinking why write
          * to the end of the packj,et but since there's nothing there tail == data
          */
+#if LINUX_VERSION_CODE >= 0x20363
+        sc->lmc_rxring[i].buffer1 = pci_map_single(sc->pdev, skb->data, sc->lmc_rxring[i].length, PCI_DMA_FROMDEVICE);
+        sc->lmc_rxring[i].buffer2 = (u32) &(sc->sc_dma->lmc_rxring[i + 1]);
+#else
         sc->lmc_rxring[i].buffer1 = virt_to_bus (skb->data);
+        sc->lmc_rxring[i].buffer2 = virt_to_bus (&sc->lmc_rxring[i+1]);
 
-        /* This is fair since the structure is static and we have the next address */
-        sc->lmc_rxring[i].buffer2 = virt_to_bus (&sc->lmc_rxring[i + 1]);
+#endif
 
     }
 
     /*
      * Sets end of ring
      */
-    sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */
+    sc->lmc_rxring[i - 1].length |= cpu_to_le32(0x02000000); /* Set end of buffers flag */
+#if LINUX_VERSION_CODE >= 0x20363
+    sc->lmc_rxring[i - 1].buffer2 = (u32) &sc->sc_dma->lmc_rxring[0]; /* Point back to the start */
+    LMC_CSR_WRITE (sc, csr_rxlist, (u32) &sc->sc_dma->lmc_rxring); /* write base address */
+#else
     sc->lmc_rxring[i - 1].buffer2 = virt_to_bus (&sc->lmc_rxring[0]); /* Point back to the start */
     LMC_CSR_WRITE (sc, csr_rxlist, virt_to_bus (sc->lmc_rxring)); /* write base address */
+#endif
 
 
     /* Initialize the transmit rings and buffers */
     for (i = 0; i < LMC_TXDESCS; i++)
     {
+        if (sc->lmc_txq[i] != NULL){		/* have buffer */
+#if LINUX_VERSION_CODE >= 0x20363 /* 2.4 */
+            pci_unmap_single(sc->pdev, sc->lmc_txring[i].buffer1, sc->lmc_txq[i]->len, PCI_DMA_TODEVICE);
+#endif
+            LMC_DEV_KFREE_SKB(sc->lmc_txq[i]);	/* free it */
+            sc->stats.tx_dropped++;      /* We just dropped a packet */
+        }
         sc->lmc_txq[i] = 0;
-        sc->lmc_txring[i].status = 0x00000000;
+        sc->lmc_txring[i].status = cpu_to_le32(0x00000000);
+#if LINUX_VERSION_CODE >= 0x20363
+        sc->lmc_txring[i].buffer2 = (u32) &(sc->sc_dma->lmc_txring[i + 1]);
+#else
         sc->lmc_txring[i].buffer2 = virt_to_bus (&sc->lmc_txring[i + 1]);
+#endif
     }
+    
+#if LINUX_VERSION_CODE >= 0x20363
+    sc->lmc_txring[i - 1].buffer2 = (u32) &sc->sc_dma->lmc_txring[0]; /* Point back to the start */
+    LMC_CSR_WRITE (sc, csr_txlist, (u32) &sc->sc_dma->lmc_txring); /* write base address */
+#else
     sc->lmc_txring[i - 1].buffer2 = virt_to_bus (&sc->lmc_txring[0]);
     LMC_CSR_WRITE (sc, csr_txlist, virt_to_bus (sc->lmc_txring));
+#endif
+    
+    lmc_trace(sc->lmc_device, "lmc_softreset out");
 }
 
-static int lmc_set_config(struct device *dev, struct ifmap *map) /*fold00*/
+static int lmc_set_config(struct net_device *dev, struct ifmap *map) /*fold00*/
 {
+    lmc_trace(dev, "lmc_set_config in");
+    lmc_trace(dev, "lmc_set_config out");
     return -EOPNOTSUPP;
 }
 
-void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits)
+void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/
 {
+    lmc_trace(sc->lmc_device, "lmc_gpio_mkinput in");
     sc->lmc_gpio_io &= ~bits;
-    LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
+    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(TULIP_GP_PINSET | (sc->lmc_gpio_io)));
+    lmc_trace(sc->lmc_device, "lmc_gpio_mkinput out");
 }
 
-void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits)
+void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/
 {
+    lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput in");
     sc->lmc_gpio_io |= bits;
-    LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
+    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(TULIP_GP_PINSET | (sc->lmc_gpio_io)));
+    lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput out");
 }
 
-void lmc_led_on(lmc_softc_t * const sc, u_int32_t led)
+void lmc_led_on(lmc_softc_t * const sc, u_int32_t led) /*fold00*/
 {
-    if((~sc->lmc_miireg16) & led) /* Already on! */
+    lmc_trace(sc->lmc_device, "lmc_led_on in");
+    if((~sc->lmc_miireg16) & led){ /* Already on! */
+        lmc_trace(sc->lmc_device, "lmc_led_on aon out");
         return;
+    }
     
     sc->lmc_miireg16 &= ~led;
     lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+    lmc_trace(sc->lmc_device, "lmc_led_on out");
 }
 
-void lmc_led_off(lmc_softc_t * const sc, u_int32_t led)
+void lmc_led_off(lmc_softc_t * const sc, u_int32_t led) /*fold00*/
 {
-    if(sc->lmc_miireg16 & led) /* Already set don't do anything */
+    lmc_trace(sc->lmc_device, "lmc_led_off in");
+    if(sc->lmc_miireg16 & led){ /* Already set don't do anything */
+        lmc_trace(sc->lmc_device, "lmc_led_off aoff out");
         return;
+    }
     
     sc->lmc_miireg16 |= led;
     lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+    lmc_trace(sc->lmc_device, "lmc_led_off out");
 }
 
-static void lmc_reset(lmc_softc_t * const sc)
+static void lmc_reset(lmc_softc_t * const sc) /*fold00*/
 {
+    lmc_trace(sc->lmc_device, "lmc_reset in");
     sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET;
     lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
 
@@ -1770,15 +2300,15 @@
     /*
      * make some of the GPIO pins be outputs
      */
-    lmc_gpio_mkoutput(sc, LMC_GEP_DP | LMC_GEP_RESET);
+    lmc_gpio_mkoutput(sc, LMC_GEP_RESET);
 
     /*
-     * drive DP and RESET low to force configuration.  This also forces
+     * RESET low to force state reset.  This also forces
      * the transmitter clock to be internal, but we expect to reset
      * that later anyway.
      */
-    sc->lmc_gpio &= ~(LMC_GEP_DP | LMC_GEP_RESET);
-    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+    sc->lmc_gpio &= ~(LMC_GEP_RESET);
+    LMC_CSR_WRITE(sc, csr_gp, cpu_to_le32(sc->lmc_gpio));
 
     /*
      * hold for more than 10 microseconds
@@ -1788,13 +2318,7 @@
     /*
      * stop driving Xilinx-related signals
      */
-    lmc_gpio_mkinput(sc, LMC_GEP_DP | LMC_GEP_RESET);
-
-    /*
-     * busy wait for the chip to reset
-     */
-    while ((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_DP) == 0)
-        ;
+    lmc_gpio_mkinput(sc, LMC_GEP_RESET);
 
     /*
      * Call media specific init routine
@@ -1802,17 +2326,19 @@
     sc->lmc_media->init(sc);
 
     sc->stats.resetCount++;
+    lmc_trace(sc->lmc_device, "lmc_reset out");
 }
 
-static void lmc_dec_reset(lmc_softc_t * const sc)
+static void lmc_dec_reset(lmc_softc_t * const sc) /*fold00*/
 {
     u_int32_t val;
+    lmc_trace(sc->lmc_device, "lmc_dec_reset in");
 
     /*
      * disable all interrupts
      */
     sc->lmc_intrmask = 0;
-    LMC_CSR_WRITE(sc, csr_intr, sc->lmc_intrmask);
+    LMC_CSR_WRITE(sc, csr_intr, cpu_to_le32(sc->lmc_intrmask));
 
     /*
      * Reset the chip with a software reset command.
@@ -1820,9 +2346,16 @@
      * 33MHz that comes to two microseconds but wait a
      * bit longer anyways)
      */
-    LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
+    LMC_CSR_WRITE(sc, csr_busmode, cpu_to_le32(TULIP_BUSMODE_SWRESET));
     udelay(25);
-    sc->lmc_cmdmode = LMC_CSR_READ(sc, csr_command);
+#ifdef __sparc__
+    sc->lmc_busmode = LMC_CSR_READ(sc, cpu_to_le32(csr_busmode));
+    sc->lmc_busmode = 0x00000000;
+    //sc->lmc_busmode = 0x00100000;
+    sc->lmc_busmode &= ~TULIP_BUSMODE_SWRESET;
+    LMC_CSR_WRITE(sc, csr_busmode, cpu_to_le32(sc->lmc_busmode));
+#endif
+    sc->lmc_cmdmode = le32_to_cpu(LMC_CSR_READ(sc, csr_command));
 
     /*
      * We want:
@@ -1848,20 +2381,22 @@
                           | TULIP_CMD_TXTHRSHLDCTL
                         );
 
-    LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode);
+    LMC_CSR_WRITE(sc, csr_command, cpu_to_le32(sc->lmc_cmdmode));
 
     /*
      * disable receiver watchdog and transmit jabber
      */
-    val = LMC_CSR_READ(sc, csr_sia_general);
+    val = le32_to_cpu(LMC_CSR_READ(sc, csr_sia_general));
     val |= (TULIP_WATCHDOG_TXDISABLE | TULIP_WATCHDOG_RXDISABLE);
-    LMC_CSR_WRITE(sc, csr_sia_general, val);
+    LMC_CSR_WRITE(sc, csr_sia_general, cpu_to_le32(val));
 
+    lmc_trace(sc->lmc_device, "lmc_dec_reset out");
 }
 
-static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base,
+static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, /*fold00*/
                          size_t csr_size)
 {
+    lmc_trace(sc->lmc_device, "lmc_initcsrs in");
     sc->lmc_csrs.csr_busmode	        = csr_base +  0 * csr_size;
     sc->lmc_csrs.csr_txpoll		= csr_base +  1 * csr_size;
     sc->lmc_csrs.csr_rxpoll		= csr_base +  2 * csr_size;
@@ -1878,5 +2413,61 @@
     sc->lmc_csrs.csr_13		        = csr_base + 13 * csr_size;
     sc->lmc_csrs.csr_14		        = csr_base + 14 * csr_size;
     sc->lmc_csrs.csr_15		        = csr_base + 15 * csr_size;
+    lmc_trace(sc->lmc_device, "lmc_initcsrs out");
 }
 
+#if LINUX_VERSION_CODE >= 0x20363
+static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/
+    lmc_softc_t *sc;
+    u32 csr6;
+    LMC_SPIN_FLAGS;
+
+    lmc_trace(dev, "lmc_driver_timeout in");
+
+    sc = dev->priv;
+
+    LMC_SPIN_LOCK_IRQSAVE(sc);
+
+    printk("%s: Xmitter busy|\n", dev->name);
+
+    sc->stats.tx_tbusy_calls++ ;
+    if (jiffies - dev->trans_start < TX_TIMEOUT) {
+        goto bug_out;
+    }
+
+    /*
+     * Chip seems to have locked up
+     * Reset it
+     * This whips out all our decriptor
+     * table and starts from scartch
+     */
+
+    lmc_running_reset (dev);
+
+    /* restart the tx processes */
+    csr6 = le32_to_cpu(LMC_CSR_READ (sc, csr_command));
+    LMC_CSR_WRITE (sc, csr_command, cpu_to_le32(csr6 | 0x0002));
+    LMC_CSR_WRITE (sc, csr_command, cpu_to_le32(csr6 | 0x2002));
+
+    /* immediate transmit */
+    LMC_CSR_WRITE (sc, csr_txpoll, cpu_to_le32(0));
+
+    sc->stats.tx_errors++;
+    sc->stats.tx_ProcTimeout++;	/* -baz */
+
+    dev->trans_start = jiffies;
+
+bug_out:
+
+    LMC_SPIN_UNLOCK_IRQRESTORE(sc);
+
+    lmc_trace(dev, "lmc_driver_timout out");
+
+
+}
+
+int lmc_setup(void) { /*fold00*/
+   return lmc_probe(NULL);
+}
+
+#endif
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_media.c linux/drivers/net/lmc/lmc_media.c
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_media.c	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/lmc_media.c	Mon Dec  3 22:06:19 2001
@@ -1,4 +1,4 @@
-/* $Id: lmc_media.c,v 1.9 2000/01/21 13:29:49 asj Exp $ */
+/* $Id: lmc_media.c,v 1.16 2000/06/06 08:32:14 asj Exp $ */
 
 #include <linux/version.h>
 #include <linux/config.h>
@@ -13,7 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <asm/segment.h>
-#include <asm/smp.h>
+//#include <asm/smp.h>
 
 #if LINUX_VERSION_CODE < 0x20155
 #include <linux/bios32.h>
@@ -34,13 +34,14 @@
 
 #if LINUX_VERSION_CODE >= 0x20200
 #include <asm/uaccess.h>
-#include <asm/spinlock.h>
+//#include <asm/spinlock.h>
 #endif
 
-#include "lmc.h"
 #include "lmc_ver.h"
+#include "lmc.h"
 #include "lmc_var.h"
 #include "lmc_ioctl.h"
+#include "lmc_debug.h"
 
 #define CONFIG_LMC_IGNORE_HARDWARE_HANDSHAKE 1
 
@@ -59,7 +60,7 @@
   */
 
 /*
- * For lack of a better place, put the T1 cable stuff here.
+ * For lack of a better place, put the SSI cable stuff here.
  */
 char *lmc_t1_cables[] = {
   "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
@@ -111,12 +112,16 @@
 static void lmc_t1_set_crc_length (lmc_softc_t * const, int);
 static void lmc_t1_set_clock (lmc_softc_t * const, int);
 static void lmc_t1_watchdog (lmc_softc_t * const);
+static int  lmc_t1_ioctl (lmc_softc_t * const, void *);
+static int  lmc_t1_got_interupt (lmc_softc_t * const);
 
 static void lmc_dummy_set_1 (lmc_softc_t * const, int);
 static void lmc_dummy_set2_1 (lmc_softc_t * const, lmc_ctl_t *);
+static int  lmc_dummy_ioctl (lmc_softc_t * const, void *);
+static int  lmc_dummy_got_interupt (lmc_softc_t * const);
 
 static inline void write_av9110_bit (lmc_softc_t *, int);
-static void write_av9110 (lmc_softc_t *, u_int32_t, u_int32_t, u_int32_t,
+static void write_av9110 (lmc_softc_t *, u_int32_t, u_int32_t, u_int32_t, /*fold00*/
 			  u_int32_t, u_int32_t);
 
 lmc_media_t lmc_ds3_media = {
@@ -131,7 +136,9 @@
   lmc_dummy_set_1,		/* set link status */
   lmc_ds3_set_crc_length,	/* set CRC length */
   lmc_dummy_set_1,		/* set T1 or E1 circuit type */
-  lmc_ds3_watchdog
+  lmc_ds3_watchdog,
+  lmc_dummy_ioctl,
+  lmc_dummy_got_interupt,
 };
 
 lmc_media_t lmc_hssi_media = {
@@ -146,7 +153,10 @@
   lmc_hssi_set_link_status,	/* set link status */
   lmc_hssi_set_crc_length,	/* set CRC length */
   lmc_dummy_set_1,		/* set T1 or E1 circuit type */
-  lmc_hssi_watchdog
+  lmc_hssi_watchdog,
+  lmc_dummy_ioctl,
+  lmc_dummy_got_interupt,
+
 };
 
 lmc_media_t lmc_ssi_media = { lmc_ssi_init,	/* special media init stuff */
@@ -160,7 +170,10 @@
   lmc_ssi_set_link_status,	/* set link status */
   lmc_ssi_set_crc_length,	/* set CRC length */
   lmc_dummy_set_1,		/* set T1 or E1 circuit type */
-  lmc_ssi_watchdog
+  lmc_ssi_watchdog,
+  lmc_dummy_ioctl,
+  lmc_dummy_got_interupt,
+
 };
 
 lmc_media_t lmc_t1_media = {
@@ -175,25 +188,38 @@
   lmc_dummy_set_1,		/* set link status */
   lmc_t1_set_crc_length,	/* set CRC length */
   lmc_t1_set_circuit_type,	/* set T1 or E1 circuit type */
-  lmc_t1_watchdog
+  lmc_t1_watchdog,
+  lmc_t1_ioctl,
+  lmc_t1_got_interupt,
+
 };
 
-static void
-lmc_dummy_set_1 (lmc_softc_t * const sc, int a)
+static void lmc_dummy_set_1 (lmc_softc_t * const sc, int a) /*fold00*/
 {
 }
 
-static void
-lmc_dummy_set2_1 (lmc_softc_t * const sc, lmc_ctl_t * a)
+static void lmc_dummy_set2_1 (lmc_softc_t * const sc, lmc_ctl_t * a) /*fold00*/
 {
 }
 
+static int lmc_dummy_ioctl (lmc_softc_t * const sc, void *d) /*fold00*/
+{
+    return -ENOSYS;
+}
+
+static int lmc_dummy_got_interupt (lmc_softc_t * const sc) /*fold00*/
+{
+    return -ENOSYS;
+}
+
+
+
 /*
  *  HSSI methods
  */
 
 static void
-lmc_hssi_init (lmc_softc_t * const sc)
+lmc_hssi_init (lmc_softc_t * const sc) /*fold00*/
 {
   sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5200;
 
@@ -201,7 +227,7 @@
 }
 
 static void
-lmc_hssi_default (lmc_softc_t * const sc)
+lmc_hssi_default (lmc_softc_t * const sc) /*fold00*/
 {
   sc->lmc_miireg16 = LMC_MII16_LED_ALL;
 
@@ -215,7 +241,7 @@
  * always reset the card if needed.
  */
 static void
-lmc_hssi_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+lmc_hssi_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl) /*fold00*/
 {
   if (ctl == NULL)
     {
@@ -246,21 +272,25 @@
  * 1 == internal, 0 == external
  */
 static void
-lmc_hssi_set_clock (lmc_softc_t * const sc, int ie)
+lmc_hssi_set_clock (lmc_softc_t * const sc, int ie) /*fold00*/
 {
+  int old;
+  old = sc->ictl.clock_source;
   if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
     {
       sc->lmc_gpio |= LMC_GEP_HSSI_CLOCK;
       LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
       sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
-      printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
+      if(old != ie)
+        printk (KERN_INFO "%s: clock external\n", sc->name);
     }
   else
     {
       sc->lmc_gpio &= ~(LMC_GEP_HSSI_CLOCK);
       LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
       sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
-      printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
+      if(old != ie)
+        printk (KERN_INFO "%s: clock internal\n", sc->name);
     }
 }
 
@@ -269,7 +299,7 @@
  * 0 == link is down, 1 == link is up.
  */
 static int
-lmc_hssi_get_link_status (lmc_softc_t * const sc)
+lmc_hssi_get_link_status (lmc_softc_t * const sc) /*fold00*/
 {
     /*
      * We're using the same code as SSI since
@@ -279,7 +309,7 @@
 }
 
 static void
-lmc_hssi_set_link_status (lmc_softc_t * const sc, int state)
+lmc_hssi_set_link_status (lmc_softc_t * const sc, int state) /*fold00*/
 {
   if (state == LMC_LINK_UP)
     sc->lmc_miireg16 |= LMC_MII16_HSSI_TA;
@@ -293,26 +323,28 @@
  * 0 == 16bit, 1 == 32bit
  */
 static void
-lmc_hssi_set_crc_length (lmc_softc_t * const sc, int state)
+lmc_hssi_set_crc_length (lmc_softc_t * const sc, int state) /*FOLD00*/
 {
   if (state == LMC_CTL_CRC_LENGTH_32)
     {
       /* 32 bit */
       sc->lmc_miireg16 |= LMC_MII16_HSSI_CRC;
       sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4;
     }
   else
     {
       /* 16 bit */
       sc->lmc_miireg16 &= ~LMC_MII16_HSSI_CRC;
       sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2;
     }
 
   lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
 }
 
 static void
-lmc_hssi_watchdog (lmc_softc_t * const sc)
+lmc_hssi_watchdog (lmc_softc_t * const sc) /*fold00*/
 {
   /* HSSI is blank */
 }
@@ -325,7 +357,7 @@
  * Set cable length
  */
 static void
-lmc_ds3_set_100ft (lmc_softc_t * const sc, int ie)
+lmc_ds3_set_100ft (lmc_softc_t * const sc, int ie) /*fold00*/
 {
   if (ie == LMC_CTL_CABLE_LENGTH_GT_100FT)
     {
@@ -341,7 +373,7 @@
 }
 
 static void
-lmc_ds3_default (lmc_softc_t * const sc)
+lmc_ds3_default (lmc_softc_t * const sc) /*fold00*/
 {
   sc->lmc_miireg16 = LMC_MII16_LED_ALL;
 
@@ -356,7 +388,7 @@
  * always reset the card if needed.
  */
 static void
-lmc_ds3_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+lmc_ds3_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl) /*fold00*/
 {
   if (ctl == NULL)
     {
@@ -387,7 +419,7 @@
 }
 
 static void
-lmc_ds3_init (lmc_softc_t * const sc)
+lmc_ds3_init (lmc_softc_t * const sc) /*fold00*/
 {
   int i;
 
@@ -422,7 +454,7 @@
  * 1 == DS3 payload scrambled, 0 == not scrambled
  */
 static void
-lmc_ds3_set_scram (lmc_softc_t * const sc, int ie)
+lmc_ds3_set_scram (lmc_softc_t * const sc, int ie) /*fold00*/
 {
   if (ie == LMC_CTL_ON)
     {
@@ -442,7 +474,7 @@
  * 0 == link is down, 1 == link is up.
  */
 static int
-lmc_ds3_get_link_status (lmc_softc_t * const sc)
+lmc_ds3_get_link_status (lmc_softc_t * const sc) /*fold00*/
 {
     u_int16_t link_status, link_status_11;
     int ret = 1;
@@ -528,34 +560,30 @@
  * 0 == 16bit, 1 == 32bit
  */
 static void
-lmc_ds3_set_crc_length (lmc_softc_t * const sc, int state)
+lmc_ds3_set_crc_length (lmc_softc_t * const sc, int state) /*FOLD00*/
 {
   if (state == LMC_CTL_CRC_LENGTH_32)
     {
       /* 32 bit */
       sc->lmc_miireg16 |= LMC_MII16_DS3_CRC;
       sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4;
     }
   else
     {
       /* 16 bit */
       sc->lmc_miireg16 &= ~LMC_MII16_DS3_CRC;
       sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2;
     }
 
   lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
 }
 
 static void
-lmc_ds3_watchdog (lmc_softc_t * const sc)
+lmc_ds3_watchdog (lmc_softc_t * const sc) /*fold00*/
 {
-  sc->lmc_miireg16 = lmc_mii_readreg (sc, 0, 16);
-  if (sc->lmc_miireg16 & 0x0018) {
-      printk ("%s: AIS Recieved\n", sc->name);
-      lmc_led_on (sc, LMC_DS3_LED1 | LMC_DS3_LED2);
-  }
-  else{
-  }
+    
 }
 
 
@@ -564,7 +592,7 @@
  */
 
 static void
-lmc_ssi_init (lmc_softc_t * const sc)
+lmc_ssi_init (lmc_softc_t * const sc) /*fold00*/
 {
   u_int16_t mii17;
   int cable;
@@ -580,7 +608,7 @@
 }
 
 static void
-lmc_ssi_default (lmc_softc_t * const sc)
+lmc_ssi_default (lmc_softc_t * const sc) /*fold00*/
 {
   sc->lmc_miireg16 = LMC_MII16_LED_ALL;
 
@@ -600,7 +628,7 @@
  * always reset the card if needed.
  */
 static void
-lmc_ssi_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+lmc_ssi_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl) /*fold00*/
 {
   if (ctl == NULL)
     {
@@ -637,26 +665,30 @@
  * 1 == internal, 0 == external
  */
 static void
-lmc_ssi_set_clock (lmc_softc_t * const sc, int ie)
+lmc_ssi_set_clock (lmc_softc_t * const sc, int ie) /*fold00*/
 {
+  int old;
+  old = ie;
   if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
     {
       sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK);
       LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
       sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
-      printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
+      if(ie != old)
+        printk (KERN_INFO "%s: clock external\n", sc->name);
     }
   else
     {
       sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK;
       LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
       sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
-      printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
+      if(ie != old)
+        printk (KERN_INFO "%s: clock internal\n", sc->name);
     }
 }
 
 static void
-lmc_ssi_set_speed (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+lmc_ssi_set_speed (lmc_softc_t * const sc, lmc_ctl_t * ctl) /*fold00*/
 {
   lmc_ctl_t *ictl = &sc->ictl;
   lmc_av9110_t *av;
@@ -698,7 +730,7 @@
  * 0 == link is down, 1 == link is up.
  */
 static int
-lmc_ssi_get_link_status (lmc_softc_t * const sc)
+lmc_ssi_get_link_status (lmc_softc_t * const sc) /*fold00*/
 {
   u_int16_t link_status;
   u_int32_t ticks;
@@ -741,7 +773,7 @@
       ret = 0;
       if(sc->last_led_err[3] != 1){
           sc->stats.tx_lossOfClockCnt++;
-          printk(KERN_WARNING "%s: Lost Clock Card Down\n", sc->name);
+          printk(KERN_WARNING "%s: Lost Clock, Link Down\n", sc->name);
       }
       sc->last_led_err[3] = 1;
       lmc_led_on (sc, LMC_MII16_LED3);	/* turn ON red LED */
@@ -767,7 +799,7 @@
 
   if(hw_hdsk == 0){
       if(sc->last_led_err[1] != 1)
-          printk(KERN_WARNING "%s: DSR no asserted\n", sc->name);
+          printk(KERN_WARNING "%s: DSR not asserted\n", sc->name);
       sc->last_led_err[1] = 1;
       lmc_led_off(sc, LMC_MII16_LED1);
   }
@@ -786,17 +818,17 @@
 }
 
 static void
-lmc_ssi_set_link_status (lmc_softc_t * const sc, int state)
+lmc_ssi_set_link_status (lmc_softc_t * const sc, int state) /*fold00*/
 {
   if (state == LMC_LINK_UP)
     {
       sc->lmc_miireg16 |= (LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS);
-      printk (LMC_PRINTF_FMT ": asserting DTR and RTS\n", LMC_PRINTF_ARGS);
+//      printk (LMC_PRINTF_FMT ": asserting DTR and RTS\n", LMC_PRINTF_ARGS);
     }
   else
     {
       sc->lmc_miireg16 &= ~(LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS);
-      printk (LMC_PRINTF_FMT ": deasserting DTR and RTS\n", LMC_PRINTF_ARGS);
+//      printk (LMC_PRINTF_FMT ": deasserting DTR and RTS\n", LMC_PRINTF_ARGS);
     }
 
   lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
@@ -807,7 +839,7 @@
  * 0 == 16bit, 1 == 32bit
  */
 static void
-lmc_ssi_set_crc_length (lmc_softc_t * const sc, int state)
+lmc_ssi_set_crc_length (lmc_softc_t * const sc, int state) /*FOLD00*/
 {
   if (state == LMC_CTL_CRC_LENGTH_32)
     {
@@ -832,51 +864,46 @@
  * These are bits to program the ssi frequency generator
  */
 static inline void
-write_av9110_bit (lmc_softc_t * sc, int c)
+write_av9110_bit (lmc_softc_t * sc, int c) /*fold00*/
 {
   /*
    * set the data bit as we need it.
    */
-  sc->lmc_gpio &= ~(LMC_GEP_SERIALCLK);
+  sc->lmc_gpio &= ~(LMC_GEP_CLK);
   if (c & 0x01)
-    sc->lmc_gpio |= LMC_GEP_SERIAL;
+    sc->lmc_gpio |= LMC_GEP_DATA;
   else
-    sc->lmc_gpio &= ~(LMC_GEP_SERIAL);
+    sc->lmc_gpio &= ~(LMC_GEP_DATA);
   LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
 
   /*
    * set the clock to high
    */
-  sc->lmc_gpio |= LMC_GEP_SERIALCLK;
+  sc->lmc_gpio |= LMC_GEP_CLK;
   LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
 
   /*
    * set the clock to low again.
    */
-  sc->lmc_gpio &= ~(LMC_GEP_SERIALCLK);
+  sc->lmc_gpio &= ~(LMC_GEP_CLK);
   LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
 }
 
 static void
-write_av9110 (lmc_softc_t * sc, u_int32_t n, u_int32_t m, u_int32_t v,
+write_av9110 (lmc_softc_t * sc, u_int32_t n, u_int32_t m, u_int32_t v, /*fold00*/
 	      u_int32_t x, u_int32_t r)
 {
   int i;
 
-#if 0
-  printk (LMC_PRINTF_FMT ": speed %u, %d %d %d %d %d\n",
-	  LMC_PRINTF_ARGS, sc->ictl.clock_rate, n, m, v, x, r);
-#endif
-
   sc->lmc_gpio |= LMC_GEP_SSI_GENERATOR;
-  sc->lmc_gpio &= ~(LMC_GEP_SERIAL | LMC_GEP_SERIALCLK);
+  sc->lmc_gpio &= ~(LMC_GEP_DATA | LMC_GEP_CLK);
   LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
 
   /*
    * Set the TXCLOCK, GENERATOR, SERIAL, and SERIALCLK
    * as outputs.
    */
-  lmc_gpio_mkoutput (sc, (LMC_GEP_SERIAL | LMC_GEP_SERIALCLK
+  lmc_gpio_mkoutput (sc, (LMC_GEP_DATA | LMC_GEP_CLK
 			  | LMC_GEP_SSI_GENERATOR));
 
   sc->lmc_gpio &= ~(LMC_GEP_SSI_GENERATOR);
@@ -902,12 +929,12 @@
    * stop driving serial-related signals
    */
   lmc_gpio_mkinput (sc,
-		    (LMC_GEP_SERIAL | LMC_GEP_SERIALCLK
+		    (LMC_GEP_DATA | LMC_GEP_CLK
 		     | LMC_GEP_SSI_GENERATOR));
 }
 
 static void
-lmc_ssi_watchdog (lmc_softc_t * const sc)
+lmc_ssi_watchdog (lmc_softc_t * const sc) /*fold00*/
 {
   u_int16_t mii17;
   struct ssicsr2
@@ -937,24 +964,24 @@
  * The framer regs are multiplexed through MII regs 17 & 18
  *  write the register address to MII reg 17 and the *  data to MII reg 18. */
 static void
-lmc_t1_write (lmc_softc_t * const sc, int a, int d)
+lmc_t1_write (lmc_softc_t * const sc, int a, int d) /*fold00*/
 {
   lmc_mii_writereg (sc, 0, 17, a);
   lmc_mii_writereg (sc, 0, 18, d);
 }
 
-/* Save a warning
+
 static int
-lmc_t1_read (lmc_softc_t * const sc, int a)
+lmc_t1_read (lmc_softc_t * const sc, int a) /*fold00*/
 {
   lmc_mii_writereg (sc, 0, 17, a);
   return lmc_mii_readreg (sc, 0, 18);
 }
-*/
+
 
 
 static void
-lmc_t1_init (lmc_softc_t * const sc)
+lmc_t1_init (lmc_softc_t * const sc) /*fold00*/
 {
   u_int16_t mii16;
   int i;
@@ -962,6 +989,10 @@
   sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1200;
   mii16 = lmc_mii_readreg (sc, 0, 16);
 
+  mii16 &= ~LMC_MII16_T1_XOE;
+  lmc_mii_writereg (sc, 0, 16, mii16);
+  sc->lmc_miireg16 = mii16;
+
   /* reset 8370 */
   mii16 &= ~LMC_MII16_T1_RST;
   lmc_mii_writereg (sc, 0, 16, mii16 | LMC_MII16_T1_RST);
@@ -972,52 +1003,430 @@
   lmc_t1_set_circuit_type(sc, LMC_CTL_CIRCUIT_TYPE_T1);
   mii16 = sc->lmc_miireg16;
 
-  lmc_t1_write (sc, 0x01, 0x1B);	/* CR0     - primary control             */
-  lmc_t1_write (sc, 0x02, 0x42);	/* JAT_CR  - jitter atten config         */
-  lmc_t1_write (sc, 0x14, 0x00);	/* LOOP    - loopback config             */
-  lmc_t1_write (sc, 0x15, 0x00);	/* DL3_TS  - external data link timeslot */
+  /* Clear "foreced alarm" bis */
+  sc->yellow_alarm = 0;
+  sc->red_alarm = 0;
+  sc->blue_alarm = 0;
+
+  /*
+   * CR0
+   * - Set framing too ESF + Force CRC
+   * - Set T1
+   */
+  
+  lmc_t1_write (sc, 0x01, 0x1b);
+  /*
+   * JAT_CR
+   * - set Free Running JCLK and CLAD0
+   * - Reset Elastic store to center
+   * - 64 bit elastic store
+   */
+  lmc_t1_write (sc, 0x02, 0x4b);
+  
+  /*
+   * JAT_CR
+   * - Release Elastic store reset
+   */
+  lmc_t1_write (sc, 0x02, 0x43);
+  
+  /*
+   * Disable all interupts
+   * Except: BOP receive
+   */
+
+  lmc_t1_write (sc, 0x0C, 0x00);
+  lmc_t1_write (sc, 0x0D, 0x00);
+  lmc_t1_write (sc, 0x0E, 0x00);
+  lmc_t1_write (sc, 0x0F, 0x00);
+  lmc_t1_write (sc, 0x10, 0x00);
+  lmc_t1_write (sc, 0x11, 0x00);
+  lmc_t1_write (sc, 0x12, 0x80);
+  lmc_t1_write (sc, 0x13, 0x00);
+  
+  /*
+   * LOOP
+   * - No loopbacks set
+   */
+  lmc_t1_write (sc, 0x14, 0x00);
+  
+  /*
+   * DL3_TS
+   * - Disabled
+   */
+  lmc_t1_write (sc, 0x15, 0x00);
+  
+  /*
+   * PIO
+   * - ONESEC_IO, RDL_IO, TDL_IO, INDY_IO, RFSYNC_IO, RMSYNC_IO
+   *   TFSNYC_IO, TMSYNC_IO: Set for output
+   */
   lmc_t1_write (sc, 0x18, 0xFF);	/* PIO     - programmable I/O            */
+  
+  /*
+   * POE
+   * TDL_OE, RDL_OE: tri state output capable enable
+   * Rest: 2 level output
+   */
   lmc_t1_write (sc, 0x19, 0x30);	/* POE     - programmable OE             */
+  
+  /*
+   * CMUX - Clock Input Mux
+   * RSBCKLI: Normal RSB timebase
+   * TSBCKI: Normal TSB timebase
+   * CLADI: CLAD slaved to transmit
+   * TCKI: Internal CLAD
+   */
   lmc_t1_write (sc, 0x1A, 0x0F);	/* CMUX    - clock input mux             */
+  
+  /*
+   * LIU_CR
+   * RST_LIU: Reset LIU
+   * SQUELCH: Enable squelch
+   * Must be 1: Set to 1
+   */
+  lmc_t1_write (sc, 0x20, 0xC1);	/* LIU_CR  - RX LIU config               */
   lmc_t1_write (sc, 0x20, 0x41);	/* LIU_CR  - RX LIU config               */
-  lmc_t1_write (sc, 0x22, 0x76);	/* RLIU_CR - RX LIU config               */
+  /*
+   * RLIU_CR
+   * WHAT IS GOING ON HERE? USED TO BE 0x76
+   * FRZ_SHORT: don't update on strong signals
+   * AGC: 0x11 normal op
+   * LONG_EYE: normal
+   */
+  lmc_t1_write (sc, 0x22, 0xB1);	/* RLIU_CR - RX LIU config               */
+
+  /*
+   * VGA_MAX
+   * Setting of -20db sesitivity
+   */
+  lmc_t1_write (sc, 0x24, 0x21);
+
+  /*
+   * PRE_EQ
+   * Force off the pre-equilizer
+   * Load 0x26 in VTHRESH
+   */
+  lmc_t1_write (sc, 0x2A, 0xA6);
+
+  /*
+   * GAIN
+   * Equilizer Gain threshholds
+   * Number taken straight from David test code
+   */
+  lmc_t1_write (sc, 0x38, 0x24);  /* RX_TH0  - RX gain threshold 0         */
+  lmc_t1_write (sc, 0x39, 0x28);  /* RX_TH1  - RX gain threshold 0         */
+  lmc_t1_write (sc, 0x3A, 0x2C);  /* RX_TH2  - RX gain threshold 0         */
+  lmc_t1_write (sc, 0x3B, 0x30);  /* RX_TH3  - RX gain threshold 0         */
+  lmc_t1_write (sc, 0x3C, 0x34);  /* RX_TH4  - RX gain threshold 0         */
+
+  /*
+   *  LIU_CR
+   *  Reset the LIU so it'll load the new constants
+   */
+  lmc_t1_write (sc, 0x20, 0x81);  /* LIU_CR  - RX LIU config (reset RLIU)  */
+  lmc_t1_write (sc, 0x20, 0x01);  /* LIU_CR  - RX LIU config (clear reset) */
+  
+  /*
+   * RCR0
+   * Receive B8ZS and 2 out of 4 F-bit errors for reframe
+   */
   lmc_t1_write (sc, 0x40, 0x03);	/* RCR0    - RX config                   */
-  lmc_t1_write (sc, 0x45, 0x00);	/* RALM    - RX alarm config             */
-  lmc_t1_write (sc, 0x46, 0x05);	/* LATCH   - RX alarm/err/cntr latch     */
-  lmc_t1_write (sc, 0x68, 0x40);	/* TLIU_CR - TX LIU config               */
-  lmc_t1_write (sc, 0x70, 0x0D);	/* TCR0    - TX framer config            */
-  lmc_t1_write (sc, 0x71, 0x05);	/* TCR1    - TX config                   */
-  lmc_t1_write (sc, 0x72, 0x0B);	/* TFRM    - TX frame format             */
-  lmc_t1_write (sc, 0x73, 0x00);	/* TERROR  - TX error insert             */
-  lmc_t1_write (sc, 0x74, 0x00);	/* TMAN    - TX manual Sa/FEBE config    */
-  lmc_t1_write (sc, 0x75, 0x00);	/* TALM    - TX alarm signal config      */
-  lmc_t1_write (sc, 0x76, 0x00);	/* TPATT   - TX test pattern config      */
-  lmc_t1_write (sc, 0x77, 0x00);	/* TLB     - TX inband loopback config   */
-  lmc_t1_write (sc, 0x90, 0x05);	/* CLAD_CR - clock rate adapter config   */
+
+  /*
+   * RPATT
+   * Zero the test pattern generator
+   */
+  lmc_t1_write (sc, 0x41, 0x00);
+
+  /*
+   * RLB
+   * Loop back code detector
+   * DN_LEN: Down length is 8 bits
+   * UP_LEN: 5 bits
+   */
+  lmc_t1_write (sc, 0x42, 0x09);
+
+  /*
+   * LBA: Loopback activate
+   * LBA[6]: 1
+   * Loopback activate code
+   */
+  lmc_t1_write (sc, 0x43, 0x08);
+
+  /*
+   * LBD: Loopback deactivate
+   *
+   * Loopback deactivate code
+   */
+  lmc_t1_write (sc, 0x44, 0x24);
+
+  /*
+   * RALM: Receive Alarm Signal Configuration
+   *
+   * Set 0 which seems to be narmal alarms
+   */
+  lmc_t1_write (sc, 0x45, 0x00);
+
+  /*
+   * LATCH: Alarm/Error/Cournetr Latch register
+   *
+   * STOP_CNT: Stop error counters durring RLOF/RLOS/RAIS
+   */
+  lmc_t1_write (sc, 0x46, 0x08);
+
+  /*
+   * TLIU_CR: Transmit LIU Control Register
+   *
+   * TERM: External Transmit termination
+   * LBO: No line buildout
+   * Pulse shape from N8370DSE: 3-66
+   * // PULSE: 000 = 0 - 133ft 100 ohm twisted pair T1 DSX
+   * PULSE: 111 = Long Haul FCC Part 68 100 ohm twisted T1 CSU/NCTE
+   */
+  
+  lmc_t1_write (sc, 0x68, 0x4E);
+
+  /*
+   * TCR0: Transmit Framer Configuration
+   *
+   * TFRAME: 1101 == ESF + Froce CRC
+   */
+  lmc_t1_write (sc, 0x70, 0x0D);
+
+  /*
+   * TCR1: Transmit Configuration Registers
+   *
+   * TLOFA: 2 out of 4 bit errors = LOF
+   * TZCS: 000VB0VB Table 3-20 page 3-72
+   */
+  lmc_t1_write (sc, 0x71, 0x05);
+
+  /*
+   * TFRM: Transmit Frame Format
+   *
+   * INS_MF: Insert Multiframe aligement
+   * INS_CRC: Insert CRC
+   * INS_FBIT: Insert Framing
+   */
+  lmc_t1_write (sc, 0x72, 0x0B);
+
+  /*
+   * TERROR
+   *
+   * Don't xmit any errors
+   */
+  lmc_t1_write (sc, 0x73, 0x00);
+
+  /*
+   * TMAN: Tranimit Mahual Sa-byte/FEBE configuration
+   */
+  lmc_t1_write (sc, 0x74, 0x00);
+
+
+  /*
+   * TALM: Transmit Alarm Signal Configuration
+   *
+   * Don't use any of these auto alarms
+   */
+  lmc_t1_write (sc, 0x75, 0x00);
+
+
+  /*
+   * TPATT: Transmit Pattern Canfiguration
+   *
+   * No special test patterns
+   */
+  lmc_t1_write (sc, 0x76, 0x00);
+
+  /*
+   * TLB: Transmit Inband Loopback Codhe Configuration
+   *
+   * Not enabled
+   */
+  lmc_t1_write (sc, 0x77, 0x00);
+
+  /*
+   * CLAD_CR: Clack Rate Adapter Configuration
+   *
+   * LFGAIN: Loop filter gain 1/2^6
+   */
+  lmc_t1_write (sc, 0x90, 0x06);	/* CLAD_CR - clock rate adapter config   */
+
+  /*
+   * CSEL: CLAD Frequency Select
+   *
+   * CLADV: 0000 - 1024 kHz
+   * CLADO: 0101 - 1544 kHz
+   */
   lmc_t1_write (sc, 0x91, 0x05);	/* CSEL    - clad freq sel               */
-  lmc_t1_write (sc, 0xA6, 0x00);	/* DL1_CTL - DL1 control                 */
+
+  /*
+   * CPHASE: CLAD Phase detector
+   */
+  lmc_t1_write (sc, 0x92, 0x00);
+
+  /*
+   * CTEST: Clad Test
+   *
+   * No tests
+   */
+  lmc_t1_write (sc, 0x93, 0x00);
+
+  /*
+   * BOP: Bop receiver
+   *
+   * Enable, 25 messages receive, 25 send, BOP has priority over FDL
+   */
+  lmc_t1_write (sc, 0xA0, 0xea);        /* BOP     - Bit oriented protocol xcvr  */
+
+  /*
+   * Setup required to activae BOP.
+   * See table: 3-22 page 3-87
+   * See at the end
+   */
+  lmc_t1_write (sc, 0xA4, 0x40);        /* DL1_TS  - DL1 time slot enable        */
+  lmc_t1_write (sc, 0xA5, 0x00);        /* DL1_BIT - DL1 bit enable              */
+  lmc_t1_write (sc, 0xA6, 0x03);        /* DL1_CTL - DL1 control                 */
+  lmc_t1_write (sc, 0xA7, 0x00);        /* RDL1_FFC - DL1 FIFO Size */
+  lmc_t1_write (sc, 0xAB, 0x00);        /* TDL1_FFC - DL1 Empty Control*/
+
+  /*
+   * PRM: FDL PRM Messages
+   *
+   * Disable all automatic FDL messages
+   */
+  
+  lmc_t1_write (sc, 0xAA, 0x00);        /* PRM     - performance report message  */
+
+  /*
+   * DLC2 Control
+   *
+   * TDL2_EN: Disable transmit
+   * RDL2_EN: Disable receive
+   */
   lmc_t1_write (sc, 0xB1, 0x00);	/* DL2_CTL - DL2 control                 */
+  /*
+   * SBI_CR: System Bus Interface Configuration
+   *
+   * SBI_OE: Enable system bus
+   * SBI: T1 at 1544 with 24+fbit Page 3-113
+   */
   lmc_t1_write (sc, 0xD0, 0x47);	/* SBI_CR  - sys bus iface config        */
-  lmc_t1_write (sc, 0xD1, 0x70);	/* RSB_CR  - RX sys bus config           */
+  /*
+   * RSB_CR: Receive System Bus Coniguration
+   *
+   * SIG_OFF: RPCMO signalling off
+   * RPCM_NEG: Output on falling edge
+   * RSYN_NEG: Output sync an negative edge of clock
+   *
+   */
+  lmc_t1_write (sc, 0xD1, 0x70);
+
+  /*
+   * TSB_CR: Transmit System Bus  Configuration
+   *
+   * TPCM_NEG: Tranimettr multiframe follows TSB
+   * TSYN_NEG: TFSYNC or TMSYNC on falling edge output
+   */
   lmc_t1_write (sc, 0xD4, 0x30);	/* TSB_CR  - TX sys bus config           */
+
   for (i = 0; i < 32; i++)
     {
       lmc_t1_write (sc, 0x0E0 + i, 0x00);	/* SBCn - sys bus per-channel ctl    */
       lmc_t1_write (sc, 0x100 + i, 0x00);	/* TPCn - TX per-channel ctl         */
       lmc_t1_write (sc, 0x180 + i, 0x00);	/* RPCn - RX per-channel ctl         */
     }
+  for (i=1; i<25; i++)
+      lmc_t1_write (sc, 0x0E0 + i, 0x01);       /* SBCn - sys bus per-channel ctl    */
   for (i = 1; i < 25; i++)
     {
       lmc_t1_write (sc, 0x0E0 + i, 0x0D);	/* SBCn - sys bus per-channel ctl    */
     }
 
+  /*
+   * Seems to get lost sometimes
+   */
+  lmc_t1_write (sc, 0xA4, 0x40);        /* DL1_TS  - DL1 time slot enable        */
+  lmc_t1_write (sc, 0xA5, 0x00);        /* DL1_BIT - DL1 bit enable              */
+  lmc_t1_write (sc, 0xA6, 0x03);        /* DL1_CTL - DL1 control                 */
+  lmc_t1_write (sc, 0xA7, 0x00);        /* RDL1_FFC - DL1 FIFO Size */
+  lmc_t1_write (sc, 0xAB, 0x00);        /* TDL1_FFC - DL1 Empty Control*/
+
+  /*
+   * Basic setup is done, now setup modes like SF AMI, and
+   * Fractional T1.
+   */
+
+  if(sc->t1_amisf != 0){
+      /*
+       * Set ami line codeing
+       */
+      lmc_t1_write (sc, 0x40, 0x83);
+      lmc_t1_write (sc, 0x71, 0x07); // 0x03 is ami
+
+      /*
+       * Set SF framing
+       */
+      lmc_t1_write (sc, 0x70, 0x04);
+      lmc_t1_write (sc, 0x72, 0x09);
+      lmc_t1_write (sc, 0x01, 0x09);
+
+      lmc_t1_write (sc, 0x46,0x00);
+      lmc_t1_write (sc, 0xa6,0x00);
+      lmc_t1_write (sc, 0xa0,0x00);
+
+      /* Setup Loopback */
+      lmc_t1_write (sc, 0x0d, 0xc0);
+      lmc_t1_write (sc, 0x42, 0x09);
+      lmc_t1_write (sc, 0x43, 0x08);
+      lmc_t1_write (sc, 0x44, 0x24);
+
+
+      if(sc->t1_amisf == 2 && sc->t1_frac_mask == 0){
+          sc->t1_frac_mask = 0xfffffffe;
+      }
+  }
+
+  if(sc->t1_frac_mask){
+      u32 mask = sc->t1_frac_mask;
+      int i;
+      int onoff;
+      for(i = 24; i >= 1; i--){
+          onoff = mask & 0x1;
+          mask >>= 1;
+          if(onoff == 0){
+              lmc_t1_write(sc, 0x0e0+i,0x01);
+              lmc_t1_write(sc, 0x100+i,0x20);
+              lmc_t1_write(sc, 0x140+i,0x7f);
+          }
+          else{
+              lmc_t1_write(sc, 0x0e0+i,0x0D);
+              lmc_t1_write(sc, 0x100+i,0x00);
+              lmc_t1_write(sc, 0x140+i,0x00);
+          }
+      }
+      mii16 |= LMC_MII16_T1_INVERT;
+      lmc_mii_writereg (sc, 0, 16, mii16);
+  }
+  else {
+      mii16 &= ~LMC_MII16_T1_INVERT; /* Unless we're on AMI SF don't invert */
+  }
+
+  if(sc->t1_loop_time){
+	  lmc_t1_write(sc, 0x02, 0xa3);
+  }
+
+  lmc_gpio_mkoutput(sc, LMC_GEP_T1_INT);
+  sc->lmc_gpio |= LMC_GEP_T1_INT;
+  LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+
   mii16 |= LMC_MII16_T1_XOE;
   lmc_mii_writereg (sc, 0, 16, mii16);
   sc->lmc_miireg16 = mii16;
 }
 
 static void
-lmc_t1_default (lmc_softc_t * const sc)
+lmc_t1_default (lmc_softc_t * const sc) /*fold00*/
 {
   sc->lmc_miireg16 = LMC_MII16_LED_ALL;
   sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
@@ -1029,7 +1438,7 @@
 /* * Given a user provided state, set ourselves up to match it.  This will * always reset the card if needed.
  */
 static void
-lmc_t1_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+lmc_t1_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl) /*fold00*/
 {
   if (ctl == NULL)
     {
@@ -1053,7 +1462,7 @@
  * return hardware link status.
  * 0 == link is down, 1 == link is up.
  */ static int
-lmc_t1_get_link_status (lmc_softc_t * const sc)
+lmc_t1_get_link_status (lmc_softc_t * const sc) /*fold00*/
 {
     u_int16_t link_status;
     int ret = 1;
@@ -1067,19 +1476,23 @@
    * led3 red    = Loss of Signal (LOS) or out of frame (OOF)
    *               conditions detected on T3 receive signal
    */
-    
+    lmc_trace(sc->lmc_device, "lmc_t1_get_link_status in");
     lmc_led_on(sc, LMC_DS3_LED2);
 
     lmc_mii_writereg (sc, 0, 17, T1FRAMER_ALARM1_STATUS);
     link_status = lmc_mii_readreg (sc, 0, 18);
 
 
-    if (link_status & T1F_RAIS) {			/* turn on blue LED */
+    if ((link_status & T1F_RAIS) || sc->blue_alarm) {			/* turn on blue LED */
         ret = 0;
         if(sc->last_led_err[1] != 1){
             printk(KERN_WARNING "%s: Receive AIS/Blue Alarm. Far end in RED alarm\n", sc->name);
         }
+        if(sc->blue_alarm != 0){
+            sc->blue_alarm--;
+        }
         lmc_led_on(sc, LMC_DS3_LED1);
+        
         sc->last_led_err[1] = 1;
     }
     else {
@@ -1091,20 +1504,26 @@
     }
 
     /*
-     * Yellow Alarm is nasty evil stuff, looks at data patterns
+     * AMI: Yellow Alarm is nasty evil stuff, looks at data patterns
      * inside the channel and confuses it with HDLC framing
      * ignore all yellow alarms.
      *
+     * B8ZS: RAI/Yellow alarm is implemented via a continous BOP
+     * message.
+     *
      * Do listen to MultiFrame Yellow alarm which while implemented
      * different ways isn't in the channel and hence somewhat
      * more reliable
      */
 
-    if (link_status & T1F_RMYEL) {
+    if ((link_status & T1F_RMYEL) || sc->yellow_alarm) {
         ret = 0;
         if(sc->last_led_err[0] != 1){
             printk(KERN_WARNING "%s: Receive Yellow AIS Alarm\n", sc->name);
         }
+        if(sc->yellow_alarm > 0){
+            sc->yellow_alarm--;
+        }
         lmc_led_on(sc, LMC_DS3_LED0);
         sc->last_led_err[0] = 1;
     }
@@ -1120,10 +1539,21 @@
      * Loss of signal and los of frame
      * Use the green bit to identify which one lit the led
      */
-    if(link_status & T1F_RLOF){
+    if((link_status & T1F_RLOF) || sc->red_alarm){
         ret = 0;
         if(sc->last_led_err[3] != 1){
-            printk(KERN_WARNING "%s: Local Red Alarm: Loss of Framing\n", sc->name);
+            printk(KERN_WARNING "%s: Local Red Alarm: Loss of Framing (LOF)\n", sc->name);
+            /*
+             * Send AIS/Yellow
+             * So send continuous AIS/Yellom BOP messages
+             */
+            if(!sc->t1_amisf){
+                lmc_t1_write (sc, 0xA0, 0xee); /* Cont BOP */
+                lmc_t1_write (sc, 0xA1, 0x00); /* 0x00 is AIS/yellow BOP */
+            }
+        }
+        if(sc->red_alarm != 0){
+            sc->red_alarm--;
         }
         lmc_led_on(sc, LMC_DS3_LED3);
         sc->last_led_err[3] = 1;
@@ -1132,16 +1562,34 @@
     else {
         if(sc->last_led_err[3] != 0){
             printk(KERN_WARNING "%s: End Red Alarm (LOF)\n", sc->name);
+            /*
+             * Stop sending continuous BOP
+             * hence end yellow alarm
+             */
+            if(!sc->t1_amisf){
+                lmc_t1_write (sc, 0xA0, 0xea); /* Normal 25 BOP */
+            }
         }
         if( ! (link_status & T1F_RLOS))
             lmc_led_off(sc, LMC_DS3_LED3);
         sc->last_led_err[3] = 0;
     }
     
-    if(link_status & T1F_RLOS){
+    if((link_status & T1F_RLOS) || sc->red_alarm){
         ret = 0;
         if(sc->last_led_err[2] != 1){
-            printk(KERN_WARNING "%s: Local Red Alarm: Loss of Signal\n", sc->name);
+            printk(KERN_WARNING "%s: Local Red Alarm: Loss of Signal (LOS)\n", sc->name);
+            /*
+             * Send AIS/Yellow
+             * So send continuous AIS/Yellom BOP messages
+             */
+            if(!sc->t1_amisf){
+                lmc_t1_write (sc, 0xA0, 0xee); /* Cont BOP */
+                lmc_t1_write (sc, 0xA1, 0x00); /* 0x00 is AIS/yellow BOP */
+            }
+        }
+        if(sc->red_alarm != 0){
+            sc->red_alarm--;
         }
         lmc_led_on(sc, LMC_DS3_LED3);
         sc->last_led_err[2] = 1;
@@ -1150,6 +1598,14 @@
     else {
         if(sc->last_led_err[2] != 0){
             printk(KERN_WARNING "%s: End Red Alarm (LOS)\n", sc->name);
+            /*
+             * Stop sending continuous BOP
+             * hence end yellow alarm
+             */
+            if(!sc->t1_amisf){
+                lmc_t1_write (sc, 0xA0, 0xea); /* Normal 25 BOP */
+            }
+
         }
         if( ! (link_status & T1F_RLOF))
             lmc_led_off(sc, LMC_DS3_LED3);
@@ -1161,6 +1617,9 @@
     lmc_mii_writereg (sc, 0, 17, T1FRAMER_ALARM2_STATUS);
     sc->lmc_xinfo.t1_alarm2_status = lmc_mii_readreg (sc, 0, 18);
 
+    
+    lmc_trace(sc->lmc_device, "lmc_t1_get_link_status out");
+
     return ret;
 }
 
@@ -1168,17 +1627,19 @@
  * 1 == T1 Circuit Type , 0 == E1 Circuit Type
  */
 static void
-lmc_t1_set_circuit_type (lmc_softc_t * const sc, int ie)
+lmc_t1_set_circuit_type (lmc_softc_t * const sc, int ie) /*fold00*/
 {
+  int old;
+  old = sc->ictl.circuit_type;
   if (ie == LMC_CTL_CIRCUIT_TYPE_T1) {
-      sc->lmc_miireg16 |= LMC_MII16_T1_Z;
       sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_T1;
-      printk(KERN_INFO "%s: In T1 Mode\n", sc->name);
+      if(old != sc->ictl.circuit_type)
+          printk(KERN_INFO "%s: In T1 Mode\n", sc->name);
   }
   else {
-      sc->lmc_miireg16 &= ~LMC_MII16_T1_Z;
       sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_E1;
-      printk(KERN_INFO "%s: In E1 Mode\n", sc->name);
+      if(old != sc->ictl.circuit_type)
+          printk(KERN_INFO "%s: In E1 Mode (non functional)\n", sc->name);
   }
 
   lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
@@ -1188,7 +1649,7 @@
 /*
  * 0 == 16bit, 1 == 32bit */
 static void
-lmc_t1_set_crc_length (lmc_softc_t * const sc, int state)
+lmc_t1_set_crc_length (lmc_softc_t * const sc, int state) /*fold00*/
 {
   if (state == LMC_CTL_CRC_LENGTH_32)
     {
@@ -1213,31 +1674,167 @@
  * 1 == internal, 0 == external
  */
 static void
-lmc_t1_set_clock (lmc_softc_t * const sc, int ie)
+lmc_t1_set_clock (lmc_softc_t * const sc, int ie) /*fold00*/
 {
-  if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
-    {
-      sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK);
-      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
-      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
-      printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
-    }
-  else
-    {
-      sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK;
-      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
-      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
-      printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
-    }
+    /*
+     * Not set this way, done through T1 specific IOCTL
+     */
 }
 
-static void
-lmc_t1_watchdog (lmc_softc_t * const sc)
+static void lmc_t1_watchdog (lmc_softc_t * const sc) /*fold00*/
 {
+        if(sc->loop_timer != 0){
+                sc->loop_timer--;
+                if(sc->loop_timer == 0){
+                        if(lmc_t1_read(sc, 0x014) != 0x00){
+                                printk(KERN_DEBUG "%s: Timeout: Loop down\n", sc->name);
+                                lmc_t1_write(sc, 0x014, 0x00);
+                                /*
+                                 * If we're not loop timed
+                                 * go back to intelnal clack
+                                 */
+                                if(! sc->t1_loop_time){
+                                    lmc_t1_write(sc, 0x02, 0x4b);
+                                }
+                        }
+                }
+        }
+        /*
+         * Check for BOP messages on A2 rev boards
+         */
+        lmc_t1_got_interupt (sc);
+}
+
+static int lmc_t1_ioctl (lmc_softc_t * const sc, void *d) /*fold00*/
+{
+        struct lmc_st1f_control ctl;
+        int ret;
+
+        LMC_COPY_FROM_USER(&ctl, d, sizeof (struct lmc_st1f_control));
+
+        switch(ctl.command){
+        case lmc_st1f_write:
+                lmc_t1_write(sc, ctl.address, ctl.value);
+                ret = 0;
+                break;
+        case lmc_st1f_read:
+                ctl.value = lmc_t1_read(sc, ctl.address) & 0xff;
+                LMC_COPY_TO_USER(d, &ctl, sizeof (struct lmc_st1f_control));
+                ret = 0;
+                break;
+        case lmc_st1f_inv:
+                if(ctl.value == 1){
+                  sc->lmc_miireg16 |= LMC_MII16_T1_INVERT;
+                  lmc_mii_writereg (sc, 0, 16,   sc->lmc_miireg16);
+                  printk("%s: Request to invert data\n", sc->name);
+                }
+                else {
+                  sc->lmc_miireg16 &= ~LMC_MII16_T1_INVERT;
+                  lmc_mii_writereg (sc, 0, 16,   sc->lmc_miireg16);
+                  printk("%s: Request to non-invert data\n", sc->name);
+                }
+                ret = 0;
+                break;
+        case lmc_st1f_amisf:
+                sc->t1_amisf = ctl.value;
+                if(sc->lmc_ok){
+                 lmc_t1_init(sc);
+                }
+                ret = 0;
+                break;
+        case lmc_st1f_frac:
+                LMC_COPY_FROM_USER(&sc->t1_frac_mask, ctl.data, sizeof (u32));
+                if(sc->lmc_ok){
+                 lmc_t1_init(sc);
+                }
+                ret = 0;
+                break;
+        case lmc_st1f_loopt:
+		sc->t1_loop_time = ctl.value;
+		if(sc->lmc_ok){
+			lmc_t1_init(sc);
+		}
+		ret = 0;
+		break;
+        default:
+        ret = -ENOSYS;
+        }
+
+        return ret;
 }
 
-static void
-lmc_set_protocol (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+static int lmc_t1_got_interupt (lmc_softc_t * const sc) /*fold00*/
+{
+        u8 reg;
+
+        /* And it with the mask in case we're polling
+         * and we have want the int disabsled
+         */
+        reg = lmc_t1_read(sc, 0x00a) & lmc_t1_read(sc, 0x12);
+
+        if(reg & 0x80){
+//                printk(KERN_DEBUG "%s: Got Inbound BOP message 0x%02x\n", sc->name, lmc_t1_read(sc, 0x0a2) & 0x3f);
+                switch(lmc_t1_read(sc, 0x0a2) & 0x3f) {
+                case 0x00: /* Yellow Alarm */
+                        sc->yellow_alarm = 5; /* Start Yellow Alarm for 3 seconds */
+                        break;
+
+                case 0x07: /* Loop up */
+                        printk(KERN_DEBUG "%s: BOP: Loop up\n", sc->name);
+                        sc->loop_timer = 305;
+                        lmc_t1_write(sc, 0x002, 0xa3); /* Enter loop timeing */
+                        lmc_t1_write(sc, 0x014, 0x04); /* Loop towards net */
+                        break;
+                        
+                case 0x0b: /* Pay load loop back */
+                        printk(KERN_DEBUG "%s: BOP: Payload Loop up\n", sc->name);
+                        sc->loop_timer = 305;
+                        lmc_t1_write(sc, 0x014, 0x08);
+                        break;
+                        
+                case 0x1a:
+                case 0x1c: /* Loop down T1.409, etc */
+                case 0x1d: /* Loop down T1.403 */
+                        printk(KERN_DEBUG "%s: BOP: Loop down\n", sc->name);
+                        lmc_t1_write(sc, 0x014, 0x00); /* Loop down */
+                        /*
+                         * If we're not loop timed
+                         * go back to intelnal clack
+                         */
+                        if(! sc->t1_loop_time){
+                            lmc_t1_write(sc, 0x02, 0x4b);
+                        }
+
+                        break;
+
+                }
+        }
+
+        reg = lmc_t1_read(sc, 0x005) & lmc_t1_read(sc, 0x0d);
+        
+        if(reg & 0x04){
+            printk(KERN_DEBUG "%s: Inband: Loop up\n", sc->name);
+            sc->loop_timer = 305;
+            lmc_t1_write(sc, 0x002, 0xa3); /* Enter loop timeing */
+            lmc_t1_write(sc, 0x014, 0x04); /* Loop up */
+        }
+        if(reg & 0x08){
+            printk(KERN_DEBUG "%s: Inband: Loop down\n", sc->name);
+            lmc_t1_write(sc, 0x014, 0x00);
+            /*
+             * If we're not loop timed
+             * go back to intelnal clack
+             */
+            if(! sc->t1_loop_time){
+                lmc_t1_write(sc, 0x02, 0x4b);
+            }
+        }
+        
+        return 0;
+}
+
+
+static void lmc_set_protocol (lmc_softc_t * const sc, lmc_ctl_t * ctl) /*fold00*/
 {
   if (ctl == 0)
     {
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_proto.c linux/drivers/net/lmc/lmc_proto.c
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_proto.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/lmc/lmc_proto.c	Mon Dec  3 22:06:19 2001
@@ -0,0 +1,270 @@
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  *
+  * With Help By:
+  * David Boggs
+  * Ron Crane
+  * Allan Cox
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU Public License version 2, incorporated herein by reference.
+  *
+  * Driver for the LanMedia LMC5200, LMC5245, LMC1000, LMC1200 cards.
+  */
+
+#include <linux/version.h>
+//#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/segment.h>
+#include <asm/smp.h>
+
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include "../syncppp.h"
+#include <linux/inet.h>
+#include <linux/tqueue.h>
+#include <linux/proc_fs.h>
+
+#include "lmc_ver.h"
+#include "lmc.h"
+#include "lmc_var.h"
+#include "lmc_debug.h"
+#include "lmc_ioctl.h"
+#include "lmc_proto.h"
+//#include "lmc_proto_raw.h"
+
+/*
+ * The compile-time variable SPPPSTUP causes the module to be
+ * compiled without referencing any of the sync ppp routines.
+ */
+#ifdef SPPPSTUB
+#define SYNC_PPP_init() (void)0
+#define SPPP_detach(d)	(void)0
+#define SPPP_open(d)	0
+#define SPPP_reopen(d)	(void)0
+#define SPPP_close(d)	(void)0
+#define SPPP_attach(d)	(void)0
+#define SPPP_do_ioctl(d,i,c)	-EOPNOTSUPP
+#else
+#if LINUX_VERSION_CODE < 0x20211
+#define SYNC_PPP_init	sync_ppp_init
+#define SPPP_attach(x)	sppp_attach((struct ppp_device *)(x)->lmc_device)
+#define SPPP_detach(x)	sppp_detach((x)->lmc_device)
+#define SPPP_open(x)	sppp_open((x)->lmc_device)
+#define SPPP_reopen(x)	sppp_reopen((x)->lmc_device)
+#define SPPP_close(x)	sppp_close((x)->lmc_device)
+#define SPPP_do_ioctl(x, y, z)	sppp_do_ioctl((x)->lmc_device, (y), (z))
+#else
+#define SYNC_PPP_init	sync_ppp_init
+#define SPPP_attach(x)	sppp_attach((x)->pd)
+#define SPPP_detach(x)	sppp_detach((x)->pd->dev)
+#define SPPP_open(x)	sppp_open((x)->pd->dev)
+#define SPPP_reopen(x)	sppp_reopen((x)->pd->dev)
+#define SPPP_close(x)	sppp_close((x)->pd->dev)
+#define SPPP_do_ioctl(x, y, z)	sppp_do_ioctl((x)->pd->dev, (y), (z))
+#endif
+#endif
+
+static int lmc_first_ppp_load = 0;
+
+// init
+void lmc_proto_init(lmc_softc_t *sc) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_init in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        if(lmc_first_ppp_load == 0) {
+            lmc_first_ppp_load = 1;
+#ifndef MODULE
+            SYNC_PPP_init();
+#endif
+        }
+        
+#if LINUX_VERSION_CODE >= 0x20210
+        sc->pd = kmalloc(sizeof(struct ppp_device), GFP_KERNEL);
+        sc->pd->dev = sc->lmc_device;
+#endif
+        sc->if_ptr = sc->pd;
+        break;
+    case LMC_RAW:
+        break;
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_init out");
+}
+
+// attach
+void lmc_proto_attach(lmc_softc_t *sc) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_attach in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        {
+            struct net_device *dev = sc->lmc_device;
+            SPPP_attach(sc);
+            dev->do_ioctl = lmc_ioctl;
+        }
+        break;
+    case LMC_NET:
+        {
+            struct net_device *dev = sc->lmc_device;
+            /*
+             * They set a few basics because they don't use sync_ppp
+             */
+            dev->flags |= IFF_POINTOPOINT;
+            dev->hard_header = 0;
+            dev->hard_header_len = 0;
+            dev->addr_len = 0;
+        }
+    case LMC_RAW: /* Setup the task queue, maybe we should notify someone? */
+        {
+        }
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_attach out");
+}
+
+// detach
+void lmc_proto_detach(lmc_softc_t *sc) /*FOLD00*/
+{
+    switch(sc->if_type){
+    case LMC_PPP:
+        SPPP_detach(sc);
+        break;
+    case LMC_RAW: /* Tell someone we're detaching? */
+        break;
+    default:
+        break;
+    }
+
+}
+
+// reopen
+void lmc_proto_reopen(lmc_softc_t *sc) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_reopen in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        SPPP_reopen(sc);
+        break;
+    case LMC_RAW: /* Reset the interface after being down, prerape to receive packets again */
+        break;
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_reopen out");
+}
+
+
+// ioctl
+int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_ioctl out");
+    switch(sc->if_type){
+    case LMC_PPP:
+        return SPPP_do_ioctl (sc, ifr, cmd);
+        break;
+    default:
+        return -EOPNOTSUPP;
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_ioctl out");
+}
+
+// open
+void lmc_proto_open(lmc_softc_t *sc) /*FOLD00*/
+{
+    int ret;
+
+    lmc_trace(sc->lmc_device, "lmc_proto_open in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        ret = SPPP_open(sc);
+        if(ret < 0)
+            printk("%s: syncPPP open failed: %d\n", sc->name, ret);
+        break;
+    case LMC_RAW: /* We're about to start getting packets! */
+        break;
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_open out");
+}
+
+// close
+
+void lmc_proto_close(lmc_softc_t *sc) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_close in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        SPPP_close(sc);
+        break;
+    case LMC_RAW: /* Interface going down */
+        break;
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_close out");
+}
+
+unsigned short lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_type in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        return htons(ETH_P_WAN_PPP);
+        break;
+    case LMC_NET:
+        return htons(ETH_P_802_2);
+        break;
+    case LMC_RAW: /* Packet type for skbuff kind of useless */
+        return htons(ETH_P_802_2);
+        break;
+    default:
+        printk(KERN_WARNING "%s: No protocol set for this interface, assuming 802.2 (which is wrong!!)\n", sc->name);
+        return htons(ETH_P_802_2);
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_tye out");
+
+}
+
+void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_netif in");
+    switch(sc->if_type){
+    case LMC_PPP:
+    case LMC_NET:
+    default:
+        netif_rx(skb);
+        break;
+    case LMC_RAW:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_netif out");
+}
+
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_proto.h linux/drivers/net/lmc/lmc_proto.h
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_proto.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/lmc/lmc_proto.h	Mon Dec  3 22:06:19 2001
@@ -0,0 +1,15 @@
+#ifndef _LMC_PROTO_H_
+#define _LMC_PROTO_H_
+
+void lmc_proto_init(lmc_softc_t *sc);
+void lmc_proto_attach(lmc_softc_t *sc);
+void lmc_proto_detach(lmc_softc_t *sc);
+void lmc_proto_reopen(lmc_softc_t *sc);
+int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd);
+void lmc_proto_open(lmc_softc_t *sc);
+void lmc_proto_close(lmc_softc_t *sc);
+unsigned short lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb);
+void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb);
+int lmc_skb_rawpackets(char *buf, char **start, off_t offset, int len, int unused);
+
+#endif
\ No newline at end of file
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_var.h linux/drivers/net/lmc/lmc_var.h
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_var.h	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/lmc_var.h	Mon Dec  3 22:06:19 2001
@@ -1,7 +1,7 @@
 #ifndef _LMC_VAR_H_
 #define _LMC_VAR_H_
 
-/* $Id: lmc_var.h,v 1.14 2000/01/21 13:29:50 asj Exp $ */
+/* $Id: lmc_var.h,v 1.24 2000/06/16 23:37:16 asj Exp $ */
 
  /*
   * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
@@ -18,6 +18,7 @@
   */
 
 #include <linux/timer.h>
+#include <linux/version.h>
 
 #ifndef __KERNEL__
 typedef signed char s8;
@@ -32,6 +33,14 @@
 typedef signed long long s64;
 typedef unsigned long long u64;
 
+#if LINUX_VERSION_CODE >= 0x20363
+struct timer_list {
+};
+#endif
+
+typedef u32 spinlock_t;
+typedef u32 dma_addr_t;
+
 #define BITS_PER_LONG 32 
 
 #endif
@@ -44,7 +53,7 @@
 typedef struct lmc___media lmc_media_t;
 typedef struct lmc___ctl lmc_ctl_t;
 
-#define lmc_csrptr_t	u32
+#define lmc_csrptr_t    unsigned long
 #define u_int16_t	u16
 #define u_int8_t	u8
 #define tulip_uint32_t	u32
@@ -69,13 +78,13 @@
 #define LMC_CSR_READ(sc, csr) \
 	inl((sc)->lmc_csrs.csr)
 #define LMC_CSR_WRITE(sc, reg, val) \
-	outl(val, (sc)->lmc_csrs.reg)
+	outl((val), (sc)->lmc_csrs.reg)
 
-#ifdef _LINUX_DELAY_H
-	#define SLOW_DOWN_IO udelay(2);
-	#undef __SLOW_DOWN_IO
-	#define __SLOW_DOWN_IO udelay(2);
-#endif
+//#ifdef _LINUX_DELAY_H
+//	#define SLOW_DOWN_IO udelay(2);
+//	#undef __SLOW_DOWN_IO
+//	#define __SLOW_DOWN_IO udelay(2);
+//#endif
 
 #define DELAY(n) SLOW_DOWN_IO
 
@@ -83,10 +92,10 @@
 
 /* This macro sync's up with the mii so that reads and writes can take place */
 #define LMC_MII_SYNC(sc) do {int n=32; while( n >= 0 ) { \
-		LMC_CSR_WRITE((sc), csr_9, 0x20000); \
+                LMC_CSR_WRITE((sc), csr_9, 0x20000); \
 		lmc_delay(); \
 		LMC_CSR_WRITE((sc), csr_9, 0x30000); \
-		lmc_delay(); \
+                lmc_delay(); \
 		n--; }} while(0);
 
 struct lmc_regfile_t {
@@ -242,6 +251,8 @@
 	void	(* set_crc_length)(lmc_softc_t * const, int);
         void    (* set_circuit_type)(lmc_softc_t * const, int);
         void	(* watchdog)(lmc_softc_t * const);
+        int     (* ioctl)(lmc_softc_t * const, void *);
+        int     (* got_interupt)(lmc_softc_t * const);
 };
 
 
@@ -254,32 +265,32 @@
  */
 struct lmc_statistics
 {
-        int     rx_packets;             /* total packets received       */
-        int     tx_packets;             /* total packets transmitted    */
-	int     rx_bytes;
-        int     tx_bytes;
+        unsigned long     rx_packets;             /* total packets received       */
+        unsigned long     tx_packets;             /* total packets transmitted    */
+	unsigned long     rx_bytes;
+        unsigned long     tx_bytes;
         
-        int     rx_errors;              /* bad packets received         */
-        int     tx_errors;              /* packet transmit problems     */
-        int     rx_dropped;             /* no space in linux buffers    */
-        int     tx_dropped;             /* no space available in linux  */
-        int     multicast;              /* multicast packets received   */
-        int     collisions;
+        unsigned long     rx_errors;              /* bad packets received         */
+        unsigned long     tx_errors;              /* packet transmit problems     */
+        unsigned long     rx_dropped;             /* no space in linux buffers    */
+        unsigned long     tx_dropped;             /* no space available in linux  */
+        unsigned long     multicast;              /* multicast packets received   */
+        unsigned long     collisions;
 
         /* detailed rx_errors: */
-        int     rx_length_errors;
-        int     rx_over_errors;         /* receiver ring buff overflow  */
-        int     rx_crc_errors;          /* recved pkt with crc error    */
-        int     rx_frame_errors;        /* recv'd frame alignment error */
-        int     rx_fifo_errors;         /* recv'r fifo overrun          */
-        int     rx_missed_errors;       /* receiver missed packet       */
+        unsigned long     rx_length_errors;
+        unsigned long     rx_over_errors;         /* receiver ring buff overflow  */
+        unsigned long     rx_crc_errors;          /* recved pkt with crc error    */
+        unsigned long     rx_frame_errors;        /* recv'd frame alignment error */
+        unsigned long     rx_fifo_errors;         /* recv'r fifo overrun          */
+        unsigned long     rx_missed_errors;       /* receiver missed packet       */
 
         /* detailed tx_errors */
-        int     tx_aborted_errors;
-        int     tx_carrier_errors;
-        int     tx_fifo_errors;
-        int     tx_heartbeat_errors;
-        int     tx_window_errors;
+        unsigned long     tx_aborted_errors;
+        unsigned long     tx_carrier_errors;
+        unsigned long     tx_fifo_errors;
+        unsigned long     tx_heartbeat_errors;
+        unsigned long     tx_window_errors;
 
         /* for cslip etc */
         unsigned long rx_compressed;
@@ -296,6 +307,9 @@
         u_int32_t       tx_MaxXmtsB4Int;
         u_int32_t       tx_TimeoutCnt;
         u_int32_t       tx_OutOfSyncPtr;
+        u_int32_t       tx_tbusy0;
+        u_int32_t       tx_tbusy1;
+        u_int32_t       tx_tbusy_calls;
         u_int32_t       resetCount;
         u_int32_t       lmc_txfull;
         u_int32_t       tbusy;
@@ -353,10 +367,11 @@
  * forward decl
  */
 struct lmc___softc {
+        void                   *if_ptr;   /* General purpose pointer (used by SPPP >= 2.4) */
 	char                   *name;
 	u8			board_idx;
 	struct lmc_statistics   stats;
-	struct device          *lmc_device;
+	struct net_device          *lmc_device;
 
 	int                     hang, rxdesc, bad_packet, some_counter;
 	u_int32_t               txgo;
@@ -371,9 +386,12 @@
 	u_int32_t		lmc_gpio;	/* state of outputs */
 	struct sk_buff*		lmc_txq[LMC_TXDESCS];
 	struct sk_buff*		lmc_rxq[LMC_RXDESCS];
+	volatile
 	struct tulip_desc_t	lmc_rxring[LMC_RXDESCS];
+	volatile
 	struct tulip_desc_t	lmc_txring[LMC_TXDESCS];
 	unsigned int		lmc_next_rx, lmc_next_tx;
+	volatile
 	unsigned int		lmc_taint_tx, lmc_taint_rx;
 	int			lmc_tx_start, lmc_txfull;
 	int			lmc_txbusy;
@@ -382,27 +400,49 @@
 	int			last_link_status;
 	int			lmc_cardtype;
 	u_int32_t               last_frameerr;
-	lmc_media_t	       *lmc_media;
+        lmc_media_t	       *lmc_media;
 	struct timer_list	timer;
 	lmc_ctl_t		ictl;
 	u_int32_t		TxDescriptControlInit;  
-	struct device		*next_module;   /* Link to the next module  */
+	struct net_device      *next_module;   /* Link to the next module  */
 	int                     tx_TimeoutInd; /* additional driver state */
 	int                     tx_TimeoutDisplay;
 	unsigned int		lastlmc_taint_tx;
 	int                     lasttx_packets;
 	u_int32_t		tx_clockState;
 	u_int32_t		lmc_crcSize;
-	LMC_XINFO		lmc_xinfo; 
-	char                    lmc_yel, lmc_blue, lmc_red; /* for T1 and DS3 */
+	LMC_XINFO		lmc_xinfo;
         char                    lmc_timing; /* for HSSI and SSI */
         int                     got_irq;
 
         char                    last_led_err[4];
+        char                    yellow_alarm; /* Time in seconds to run yellow alarm for */
+        char                    red_alarm;    /* Time in seconds to run red alarm for */
+        char                    blue_alarm;   /* Time in seconds to run blue alarm for */
 
 #if LINUX_VERSION_CODE >= 0x20200
 	spinlock_t              lmc_lock;
 #endif
+#if LINUX_VERSION_CODE >= 0x20363
+        struct pci_dev          *pdev;
+        dma_addr_t              sc_dma_handle;
+        struct lmc___softc      *sc_dma;
+#endif
+        u_int16_t               if_type;       /* PPP or NET */
+        struct ppp_device       *pd;
+
+        /* Failure cases */
+        u8                       failed_ring;
+        u8                       failed_recv_alloc;
+
+        /* T1 Specicfic Variable */
+        u16                      loop_timer; /* Time out loop up requests */
+        u8                       t1_amisf;
+        u32                      t1_frac_mask;
+        u8                       t1_loop_time;
+
+        /* Structure check */
+        u32                     check;
 };
 
 #define LMC_PCI_TIME 1
diff -urN linux-2.2.17-pre4/drivers/net/lmc/lmc_ver.h linux/drivers/net/lmc/lmc_ver.h
--- linux-2.2.17-pre4/drivers/net/lmc/lmc_ver.h	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lmc/lmc_ver.h	Mon Dec  3 22:06:19 2001
@@ -29,8 +29,25 @@
   *
   */
 
+#if LINUX_VERSION_CODE < 0x20363
+#define net_device device
+#define dev_kfree_skb_irq LMC_DEV_KFREE_SKB
+#endif
+
+#if LINUX_VERSION_CODE < 0x20363
+#define LMC_XMITTER_BUSY(x) (x)->tbusy = 1
+#define LMC_XMITTER_FREE(x) (x)->tbusy = 0
+#define LMC_XMITTER_INIT(x) (x)->tbusy = 0
+#else
+#define LMC_XMITTER_BUSY(x) netif_stop_queue(x)
+#define LMC_XMITTER_FREE(x) netif_wake_queue(x)
+#define LMC_XMITTER_INIT(x) netif_start_queue(x)
+
+#endif
+
+
 #if LINUX_VERSION_CODE < 0x20100
-typedef unsigned int u_int32_t;
+//typedef unsigned int u_int32_t;
 
 #define  LMC_SETUP_20_DEV {\
                              int indx; \
@@ -41,7 +58,11 @@
                           dev->pa_addr = 0; \
                           dev->pa_brdaddr = 0; \
                           dev->pa_mask = 0xFCFFFFFF; \
-                          dev->pa_alen = 4;		/* IP addr.  sizeof(u32) */
+    dev->pa_alen = 4;		/* IP addr.  sizeof(u32) */
+
+#define cpu_to_le32(x) (x)
+#define le32_to_cpu(x) (x)
+#define le16_to_cpu(x) (x)
 
 #else
 
@@ -73,20 +94,20 @@
 #define LMC_SKB_FREE(skb, val)
 #endif
 
-#define LMC_SPIN_FLAGS                unsigned long flags;
 
-#if (LINUX_VERSION_CODE >= 0x20200)
+#if LINUX_VERSION_CODE >= 0x20200
 
+#define LMC_SPIN_FLAGS                unsigned long flags;
 #define LMC_SPIN_LOCK_INIT(x)         spin_lock_init(&(x)->lmc_lock);
 #define LMC_SPIN_UNLOCK(x)            ((x)->lmc_lock = SPIN_LOCK_UNLOCKED)
 #define LMC_SPIN_LOCK_IRQSAVE(x)      spin_lock_irqsave (&(x)->lmc_lock, flags);
 #define LMC_SPIN_UNLOCK_IRQRESTORE(x) spin_unlock_irqrestore (&(x)->lmc_lock, flags);
 #else
-#define LMC_SPIN_FLAGS
-#define LMC_SPIN_LOCK_INIT(x)
-#define LMC_SPIN_UNLOCK(x)
-#define LMC_SPIN_LOCK_IRQSAVE(x)
-#define LMC_SPIN_UNLOCK_IRQRESTORE(x)
+#define LMC_SPIN_FLAGS                unsigned long flags;
+#define LMC_SPIN_LOCK_INIT(x)         
+#define LMC_SPIN_UNLOCK(x)            
+#define LMC_SPIN_LOCK_IRQSAVE(x)      save_flags(flags); cli();
+#define LMC_SPIN_UNLOCK_IRQRESTORE(x) restore_flags(flags); 
 #endif
 
 
@@ -105,3 +126,19 @@
 
 
 #endif
+
+#if LINUX_VERSION_CODE >= 0x20200
+#else
+#define mdelay(x) { int j; for(j = 0; j < x; j++){ udelay(1000); } }
+
+#endif
+
+/*
+ * See DMA-mapping.txt for info
+ */
+
+#if LINUX_VERSION_CODE < 0x20363
+#else
+#define LMC_PCI_ALLOC_CONSISTENT(x, y, z) pci_alloc_consistent(x, y, z)
+#endif
+
diff -urN linux-2.2.17-pre4/drivers/net/mace.c linux/drivers/net/mace.c
--- linux-2.2.17-pre4/drivers/net/mace.c	Mon Aug  9 12:04:57 1999
+++ linux/drivers/net/mace.c	Mon Dec  3 22:06:19 2001
@@ -266,7 +266,11 @@
     /* done changing address */
     out_8(&mb->iac, 0);
 
+#ifndef CONFIG_MACE_AAUI_PORT
     out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
+#else
+    out_8(&mb->plscc, PORTSEL_AUI + ENPLSIO);
+#endif /* CONFIG_MACE_AAUI_PORT */
 }
 
 static void __mace_set_address(struct device *dev, void *addr)
diff -urN linux-2.2.17-pre4/drivers/scsi/st.c linux/drivers/scsi/st.c
--- linux-2.2.17-pre4/drivers/scsi/st.c	Wed May  3 17:16:45 2000
+++ linux/drivers/scsi/st.c	Mon Dec  3 22:06:19 2001
@@ -11,7 +11,7 @@
   Copyright 1992 - 2000 Kai Makisara
 		 email Kai.Makisara@metla.fi
 
-  Last modified: Wed Feb  2 22:04:05 2000 by makisara@kai.makisara.local
+  Last modified: Sat Jun 17 17:29:35 2000 by makisara@kai.makisara.local
   Some small formal changes - aeb, 950809
 */
 
@@ -896,7 +896,7 @@
 scsi_tape_flush(struct file * filp)
 {
     int result = 0, result2;
-    static unsigned char cmd[10];
+    unsigned char cmd[10];
     Scsi_Cmnd * SCpnt;
     Scsi_Tape * STp;
     ST_mode * STm;
@@ -1060,7 +1060,7 @@
     ssize_t i, do_count, blks, retval, transfer;
     int write_threshold;
     int doing_write = 0;
-    static unsigned char cmd[10];
+    unsigned char cmd[10];
     const char *b_point;
     Scsi_Cmnd * SCpnt = NULL;
     Scsi_Tape * STp;
@@ -1380,7 +1380,7 @@
 read_tape(struct inode *inode, long count, Scsi_Cmnd **aSCpnt)
 {
     int transfer, blks, bytes;
-    static unsigned char cmd[10];
+    unsigned char cmd[10];
     Scsi_Cmnd *SCpnt;
     Scsi_Tape *STp;
     ST_mode * STm;
diff -urN linux-2.2.17-pre4/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- linux-2.2.17-pre4/drivers/sound/es1370.c	Wed May  3 17:16:45 2000
+++ linux/drivers/sound/es1370.c	Mon Dec  3 22:06:19 2001
@@ -1993,7 +1993,7 @@
 		return 0;
 
 	case SNDCTL_DSP_GETOSPACE:
-		if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac1(s)) != 0)
+		if (!(s->ctrl & CTRL_DAC1_EN) && (val = prog_dmabuf_dac1(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
diff -urN linux-2.2.17-pre4/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- linux-2.2.17-pre4/drivers/sound/es1371.c	Mon Dec  3 22:06:14 2001
+++ linux/drivers/sound/es1371.c	Mon Dec  3 22:06:19 2001
@@ -2564,7 +2564,7 @@
 		return 0;
 
 	case SNDCTL_DSP_GETOSPACE:
-		if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac1(s)) != 0)
+		if (!(s->ctrl & CTRL_DAC1_EN) && (val = prog_dmabuf_dac1(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
diff -urN linux-2.2.17-pre4/include/linux/hdlc.h linux/include/linux/hdlc.h
--- linux-2.2.17-pre4/include/linux/hdlc.h	Mon Dec  3 22:06:14 2001
+++ linux/include/linux/hdlc.h	Mon Dec  3 22:06:20 2001
@@ -128,6 +128,8 @@
 	u16 rel;		/* reliability */
 	u32 time;
 }__attribute__ ((packed)) cisco_packet;
+#define	CISCO_PACKET_LEN	18
+#define	CISCO_BIG_PACKET_LEN	20
 
 
 
diff -urN linux-2.2.17-pre4/include/linux/openpic.h linux/include/linux/openpic.h
--- linux-2.2.17-pre4/include/linux/openpic.h	Tue Jan  4 10:12:25 2000
+++ linux/include/linux/openpic.h	Mon Dec  3 22:06:20 2001
@@ -262,8 +262,12 @@
      *  Interrupt Source Registers
      */
 
-#define OPENPIC_SENSE_POLARITY			0x00800000	/* Undoc'd */
+#define OPENPIC_POLARITY_POSITIVE		0x00800000
+#define OPENPIC_POLARITY_NEGATIVE		0x00000000
+#define OPENPIC_POLARITY_MASK			0x00800000
 #define OPENPIC_SENSE_LEVEL			0x00400000
+#define OPENPIC_SENSE_EDGE			0x00000000
+#define OPENPIC_SENSE_MASK			0x00400000
 
 
     /*
diff -urN linux-2.2.17-pre4/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.2.17-pre4/include/linux/sched.h	Wed May  3 17:16:52 2000
+++ linux/include/linux/sched.h	Mon Dec  3 22:06:20 2001
@@ -291,7 +291,6 @@
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 	unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
 	int swappable:1;
-	int trashing_mem:1;
 /* process credentials */
 	uid_t uid,euid,suid,fsuid;
 	gid_t gid,egid,sgid,fsgid;
@@ -382,7 +381,7 @@
 /* utime */	{0,0,0,0},0, \
 /* per CPU times */ {0, }, {0, }, \
 /* flt */	0,0,0,0,0,0, \
-/* swp */	0,0, \
+/* swp */	0, \
 /* process credentials */					\
 /* uid etc */	0,0,0,0,0,0,0,0,				\
 /* suppl grps*/ 0, {0,},					\
diff -urN linux-2.2.17-pre4/include/net/snmp.h linux/include/net/snmp.h
--- linux-2.2.17-pre4/include/net/snmp.h	Sun Oct  4 10:19:39 1998
+++ linux/include/net/snmp.h	Mon Dec  3 22:06:20 2001
@@ -178,6 +178,7 @@
 	unsigned long	OfoPruned;
 	unsigned long	OutOfWindowIcmps; 
 	unsigned long	LockDroppedIcmps; 
+	unsigned long	SockMallocOOM; 
 };
  	
 #endif
diff -urN linux-2.2.17-pre4/include/net/sock.h linux/include/net/sock.h
--- linux-2.2.17-pre4/include/net/sock.h	Mon Aug  9 12:05:13 1999
+++ linux/include/net/sock.h	Mon Dec  3 22:06:20 2001
@@ -717,6 +717,10 @@
 extern struct sk_buff		*sock_wmalloc(struct sock *sk,
 					      unsigned long size, int force,
 					      int priority);
+
+extern struct sk_buff		*sock_wmalloc_err(struct sock *sk,
+					      unsigned long size, int force,
+					      int priority, int *err);
 extern struct sk_buff		*sock_rmalloc(struct sock *sk,
 					      unsigned long size, int force,
 					      int priority);
diff -urN linux-2.2.17-pre4/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.2.17-pre4/mm/vmscan.c	Mon Dec  3 22:06:14 2001
+++ linux/mm/vmscan.c	Mon Dec  3 22:06:20 2001
@@ -380,6 +380,8 @@
 static int do_try_to_free_pages(unsigned int gfp_mask)
 {
 	int priority;
+	int ret = 0;
+	int swapcount;
 	int count = SWAP_CLUSTER_MAX;
 
 	lock_kernel();
@@ -390,6 +392,7 @@
 	priority = 6;
 	do {
 		while (shrink_mmap(priority, gfp_mask)) {
+			ret = 1;
 			if (!--count)
 				goto done;
 		}
@@ -397,15 +400,18 @@
 		/* Try to get rid of some shared memory pages.. */
 		if (gfp_mask & __GFP_IO) {
 			while (shm_swap(priority, gfp_mask)) {
+				ret = 1;
 				if (!--count)
 					goto done;
 			}
 		}
 
 		/* Then, try to page stuff out.. */
+		swapcount = count;
 		while (swap_out(priority, gfp_mask)) {
-			if (!--count)
-				goto done;
+			ret = 1;
+			if (!--swapcount)
+				break;
 		}
 
 		shrink_dcache_memory(priority, gfp_mask);
@@ -417,7 +423,7 @@
 		printk("VM: do_try_to_free_pages failed for %s...\n",
 				current->comm);
 	/* Return success if we freed a page. */
-	return priority >= 0;
+	return ret;
 }
 
 /*
diff -urN linux-2.2.17-pre4/net/core/sock.c linux/net/core/sock.c
--- linux-2.2.17-pre4/net/core/sock.c	Mon May 10 09:55:25 1999
+++ linux/net/core/sock.c	Mon Dec  3 22:06:20 2001
@@ -566,6 +566,31 @@
 			skb->sk = sk;
 			return skb;
 		}
+		net_statistics.SockMallocOOM++; 
+	}
+	return NULL;
+}
+
+/*
+ * Allocate memory from the sockets send buffer, telling caller about real OOM. 
+ * err is only set for oom, not for socket buffer overflow.
+ */ 
+struct sk_buff *sock_wmalloc_err(struct sock *sk, unsigned long size, int force, int priority, int *err)
+{
+	*err = 0; 
+	/* Note: overcommitment possible */ 
+	if (force || atomic_read(&sk->wmem_alloc) < sk->sndbuf) {
+		struct sk_buff * skb;
+		*err = -ENOMEM; 
+		skb = alloc_skb(size, priority);
+		if (skb) {
+			*err = 0;
+			atomic_add(skb->truesize, &sk->wmem_alloc);
+			skb->destructor = sock_wfree;
+			skb->sk = sk;
+			return skb;
+		}
+		net_statistics.SockMallocOOM++; 
 	}
 	return NULL;
 }
@@ -583,6 +608,7 @@
 			skb->sk = sk;
 			return skb;
 		}
+		net_statistics.SockMallocOOM++; 
 	}
 	return NULL;
 }
@@ -602,6 +628,7 @@
 		if (mem)
 			return mem;
 		atomic_sub(size, &sk->omem_alloc);
+		net_statistics.SockMallocOOM++; 
 	}
 	return NULL;
 }
diff -urN linux-2.2.17-pre4/net/ipv4/proc.c linux/net/ipv4/proc.c
--- linux-2.2.17-pre4/net/ipv4/proc.c	Wed Jun  7 14:26:44 2000
+++ linux/net/ipv4/proc.c	Mon Dec  3 22:06:20 2001
@@ -359,8 +359,8 @@
 	len = sprintf(buffer,
 		      "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
 		      " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
-		      " OutOfWindowIcmps LockDroppedIcmps\n" 	
-		      "TcpExt: %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+		      " OutOfWindowIcmps LockDroppedIcmps SockMallocOOM\n" 	
+		      "TcpExt: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
 		      net_statistics.SyncookiesSent,
 		      net_statistics.SyncookiesRecv,
 		      net_statistics.SyncookiesFailed,
@@ -369,7 +369,8 @@
 		      net_statistics.RcvPruned,
 		      net_statistics.OfoPruned,
 		      net_statistics.OutOfWindowIcmps,
-		      net_statistics.LockDroppedIcmps);
+		      net_statistics.LockDroppedIcmps,
+		      net_statistics.SockMallocOOM);
 
 	if (offset >= len)
 	{
diff -urN linux-2.2.17-pre4/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- linux-2.2.17-pre4/net/ipv4/tcp.c	Mon Dec  3 22:06:14 2001
+++ linux/net/ipv4/tcp.c	Mon Dec  3 22:06:20 2001
@@ -697,40 +697,38 @@
 }
 
 /*
- *	Wait for more memory for a socket
- *
- *	If we got here an allocation has failed on us. We cannot
- *	spin here or we may block the very code freeing memory
- *	for us.
+ *	Wait for more memory for a socket.
+ *	Special case is err == -ENOMEM, in this case just sleep a bit waiting
+ *	for the system to free up some memory. 
  */
-static void wait_for_tcp_memory(struct sock * sk)
+static void wait_for_tcp_memory(struct sock * sk, int err)
 {
 	release_sock(sk);
 	if (!tcp_memory_free(sk)) {
 		struct wait_queue wait = { current, NULL };
+
 		sk->socket->flags &= ~SO_NOSPACE;
 		add_wait_queue(sk->sleep, &wait);
 		for (;;) {
 			if (signal_pending(current))
 				break;
 			current->state = TASK_INTERRUPTIBLE;
-			if (tcp_memory_free(sk))
+			if (tcp_memory_free(sk) && !err)
 				break;
 			if (sk->shutdown & SEND_SHUTDOWN)
 				break;
 			if (sk->err)
 				break;
-			schedule();
+			if (!err) 
+				schedule();
+			else {
+				schedule_timeout(1); 
+				break;
+			} 	
 		}
 		current->state = TASK_RUNNING;
 		remove_wait_queue(sk->sleep, &wait);
 	}
-	else
-	{
-		/* Yield time to the memory freeing paths */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
-	}
 	lock_sock(sk);
 }
 
@@ -924,7 +922,7 @@
 				tmp += copy;
 				queue_it = 0;
 			}
-			skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
+			skb = sock_wmalloc_err(sk, tmp, 0, GFP_KERNEL, &err);
 
 			/* If we didn't get any memory, we need to sleep. */
 			if (skb == NULL) {
@@ -937,8 +935,10 @@
 					err = -ERESTARTSYS;
 					goto do_interrupted;
 				}
-				tcp_push_pending_frames(sk, tp);
-				wait_for_tcp_memory(sk);
+				/* In OOM that would fail anyways so do not bother. */ 
+				if (!err) 
+					tcp_push_pending_frames(sk, tp);
+				wait_for_tcp_memory(sk, err);
 
 				/* If SACK's were formed or PMTU events happened,
 				 * we must find out about it.
diff -urN linux-2.2.17-pre4/scripts/Configure linux/scripts/Configure
--- linux-2.2.17-pre4/scripts/Configure	Wed Jun  7 14:26:44 2000
+++ linux/scripts/Configure	Mon Dec  3 22:06:20 2001
@@ -542,7 +542,7 @@
   echo "# Using defaults found in" $DEFAULTS
   echo "#"
   . $DEFAULTS
-  sed -e 's/# \(.*\) is not.*/\1=n/' < $DEFAULTS > .config-is-not.$$
+  sed -e 's/# \(CONFIG_[^ ]*\) is not.*/\1=n/' <$DEFAULTS >.config-is-not.$$
   . .config-is-not.$$
   rm .config-is-not.$$
 else
