diff -u --recursive --new-file v2.2.0-pre9/linux/Makefile linux/Makefile
--- v2.2.0-pre9/linux/Makefile	Wed Jan 20 23:14:04 1999
+++ linux/Makefile	Sat Jan 23 10:45:12 1999
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION =-final
+EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v2.2.0-pre9/linux/arch/alpha/Makefile	Tue Jan 19 11:32:50 1999
+++ linux/arch/alpha/Makefile	Sun Jan 24 21:29:52 1999
@@ -49,7 +49,11 @@
     ifeq ($(have_mcpu_ev6),y)
       CFLAGS := $(CFLAGS) -mcpu=ev6
     else
-      CFLAGS := $(CFLAGS) -mcpu=pca56
+      ifeq ($(have_mcpu_pca56),y)
+        CFLAGS := $(CFLAGS) -mcpu=pca56
+      else
+        CFLAGS := $(CFLAGS) -mcpu=ev56
+      endif
     endif
   endif
 endif
@@ -71,6 +75,9 @@
  endif
  ifeq ($(CONFIG_ALPHA_POLARIS),y)
    CFLAGS := $(CFLAGS) -Wa,-m21164pc
+ endif
+ ifeq ($(CONFIG_ALPHA_TSUNAMI),y)
+   CFLAGS := $(CFLAGS) -Wa,-mev6
  endif
 endif
 
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.2.0-pre9/linux/arch/alpha/kernel/entry.S	Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/kernel/entry.S	Thu Jan 21 11:26:30 1999
@@ -10,7 +10,7 @@
 #define rti	.long PAL_rti
 #define SIGCHLD 20
 
-#define NR_SYSCALLS 370
+#define NR_SYSCALLS 371
 
 /*
  * These offsets must match with alpha_mv in <asm/machvec.h>.
@@ -1138,4 +1138,4 @@
 	.quad sys_getcwd
 	.quad sys_capget
 	.quad sys_capset
-	.quad sys_ni_syscall			/* 370 */
+	.quad sys_sendfile			/* 370 */
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/alpha/kernel/sys_rx164.c linux/arch/alpha/kernel/sys_rx164.c
--- v2.2.0-pre9/linux/arch/alpha/kernel/sys_rx164.c	Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/kernel/sys_rx164.c	Sun Jan 24 21:29:53 1999
@@ -211,8 +211,6 @@
  * The System Vector
  */
 
-#define POLARIS_IACK_SC	POLARIS_IACK_BASE /* hack, move to header */
-
 struct alpha_machine_vector rx164_mv __initmv = {
 	vector_name:		"RX164",
 	DO_EV5_MMU,
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/alpha/kernel/sys_sio.c linux/arch/alpha/kernel/sys_sio.c
--- v2.2.0-pre9/linux/arch/alpha/kernel/sys_sio.c	Tue Dec 22 14:16:53 1998
+++ linux/arch/alpha/kernel/sys_sio.c	Thu Jan 21 11:26:30 1999
@@ -232,7 +232,7 @@
 	 * selected... :-(
 	 */
 	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-	sio_pci_fixup(noname_map_irq, 0x0b0a0f0e);
+	sio_pci_fixup(noname_map_irq, 0x0b0a0f0d);
 	sio_fixup_irq_levels(sio_collect_irq_levels());
         enable_ide(0x26e);
 }
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/alpha/lib/semaphore.S linux/arch/alpha/lib/semaphore.S
--- v2.2.0-pre9/linux/arch/alpha/lib/semaphore.S	Tue Jan 19 11:32:50 1999
+++ linux/arch/alpha/lib/semaphore.S	Mon Jan 25 10:55:20 1999
@@ -77,7 +77,6 @@
 	.ent	__down_failed_interruptible
 __down_failed_interruptible:
 	ldgp	$29,0($27)
-	ldgp	$29,0($27)
 	lda	$30, -20*8($30)
 	stq	$28, 0*8($30)
 	stq	$0, 1*8($30)
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.2.0-pre9/linux/arch/i386/kernel/setup.c	Wed Jan 20 23:14:04 1999
+++ linux/arch/i386/kernel/setup.c	Thu Jan 21 11:28:40 1999
@@ -341,6 +341,13 @@
 	*memory_start_p = memory_start;
 	*memory_end_p = memory_end;
 
+#ifdef __SMP__
+	/*
+	 *	Save possible boot-time SMP configuration:
+	 */
+	init_smp_config();
+#endif
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (LOADER_TYPE) {
 		initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.2.0-pre9/linux/arch/i386/kernel/smp.c	Wed Jan 20 23:14:04 1999
+++ linux/arch/i386/kernel/smp.c	Thu Jan 21 11:28:40 1999
@@ -37,19 +37,8 @@
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
 #include <linux/smp_lock.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
-#include <asm/pgtable.h>
-#include <asm/bitops.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_MTRR
-#  include <asm/mtrr.h>
-#endif
-
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
+#include <asm/mtrr.h>
 
 #include "irq.h"
 
@@ -100,21 +89,6 @@
 spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
 
 /*
- *	Why isn't this somewhere standard ??
- *
- * Maybe because this procedure is horribly buggy, and does
- * not deserve to live.  Think about signedness issues for five
- * seconds to see why.		- Linus
- */
-
-extern __inline int max(int a,int b)
-{
-	if (a>b)
-		return a;
-	return b;
-}
-
-/*
  * function prototypes:
  */
 static void cache_APIC_registers (void);
@@ -168,6 +142,11 @@
 #endif
 
 /*
+ * IA s/w dev Vol 3, Section 7.4
+ */
+#define APIC_DEFAULT_PHYS_BASE 0xfee00000
+
+/*
  *	Setup routine for controlling SMP activation
  *
  *	Command-line option of "nosmp" or "maxcpus=0" will disable SMP
@@ -197,19 +176,11 @@
 	apic_write(APIC_EOI, 0);
 }
 
-#ifdef CONFIG_X86_VISWS_APIC
 /*
- * hacky!
+ * Intel MP BIOS table parsing routines:
  */
-int __init smp_scan_config(unsigned long base, unsigned long length)
-{
-	cpu_present_map |= 2; /* or in id 1 */
-	apic_version[1] |= 0x10; /* integrated APIC */
-	num_processors = 2;
 
-	return 1;
-} 
-#else
+#ifndef CONFIG_X86_VISWS_APIC
 /*
  *	Checksum an MP configuration block.
  */
@@ -429,7 +400,7 @@
  *	Scan the memory blocks for an SMP configuration block.
  */
 
-int __init smp_scan_config(unsigned long base, unsigned long length)
+static int __init smp_scan_config(unsigned long base, unsigned long length)
 {
 	unsigned long *bp=phys_to_virt(base);
 	struct intel_mp_floating *mpf;
@@ -463,7 +434,7 @@
 					unsigned long cfg;
 
 					/* local APIC has default address */
-					mp_lapic_addr = 0xFEE00000;
+					mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
 					/*
 					 *	We need to know what the local
 					 *	APIC id of the boot CPU is!
@@ -579,7 +550,76 @@
 
 	return 0;
 }
+
+void __init init_intel_smp (void)
+{
+	/*
+	 * FIXME: Linux assumes you have 640K of base ram..
+	 * this continues the error...
+	 *
+	 * 1) Scan the bottom 1K for a signature
+	 * 2) Scan the top 1K of base RAM
+	 * 3) Scan the 64K of bios
+	 */
+	if (!smp_scan_config(0x0,0x400) &&
+	    !smp_scan_config(639*0x400,0x400) &&
+	    !smp_scan_config(0xF0000,0x10000)) {
+		/*
+		 * If it is an SMP machine we should know now, unless the
+		 * configuration is in an EISA/MCA bus machine with an
+		 * extended bios data area. 
+		 *
+		 * there is a real-mode segmented pointer pointing to the
+		 * 4K EBDA area at 0x40E, calculate and scan it here.
+		 *
+		 * NOTE! There are Linux loaders that will corrupt the EBDA
+		 * area, and as such this kind of SMP config may be less
+		 * trustworthy, simply because the SMP table may have been
+		 * stomped on during early boot. These loaders are buggy and
+		 * should be fixed.
+		 */
+		unsigned int address;
+
+		address = *(unsigned short *)phys_to_virt(0x40E);
+		address<<=4;
+		smp_scan_config(address, 0x1000);
+		if (smp_found_config)
+			printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");
+	}
+}
+
+#else
+
+/*
+ * The Visual Workstation is Intel MP compliant in the hardware
+ * sense, but it doesnt have a BIOS(-configuration table).
+ * No problem for Linux.
+ */
+void __init init_visws_smp(void)
+{
+	smp_found_config = 1;
+
+	cpu_present_map |= 2; /* or in id 1 */
+	apic_version[1] |= 0x10; /* integrated APIC */
+	apic_version[0] |= 0x10;
+
+	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+} 
+
+#endif
+
+/*
+ * - Intel MP Configuration Table
+ * - or SGI Visual Workstation configuration
+ */
+void __init init_smp_config (void)
+{
+#ifndef CONFIG_VISWS
+	init_intel_smp();
+#else
+	init_visws_smp();
 #endif
+}
 
 /*
  *	Trampoline 80x86 program as an array.
@@ -674,6 +714,26 @@
  	value &= ~APIC_TPRI_MASK;	/* Set Task Priority to 'accept all' */
  	apic_write(APIC_TASKPRI,value);
 
+	/*
+	 * Set arbitrarion priority to 0
+	 */
+ 	value = apic_read(APIC_ARBPRI);
+ 	value &= ~APIC_ARBPRI_MASK;
+ 	apic_write(APIC_ARBPRI, value);
+
+	/*
+	 * Set the logical destination ID to 'all', just to be safe.
+	 * also, put the APIC into flat delivery mode.
+	 */
+ 	value = apic_read(APIC_LDR);
+	value &= ~APIC_LDR_MASK;
+	value |= SET_APIC_LOGICAL_ID(0xff);
+ 	apic_write(APIC_LDR,value);
+
+ 	value = apic_read(APIC_DFR);
+	value |= SET_APIC_DFR(0xf);
+ 	apic_write(APIC_DFR, value);
+
 	udelay(100);			/* B safe */
 	ack_APIC_irq();
 	udelay(100);
@@ -681,14 +741,11 @@
 
 unsigned long __init init_smp_mappings(unsigned long memory_start)
 {
-	unsigned long apic_phys, ioapic_phys;
+	unsigned long apic_phys;
 
 	memory_start = PAGE_ALIGN(memory_start);
 	if (smp_found_config) {
 		apic_phys = mp_lapic_addr;
-#ifdef CONFIG_X86_IO_APIC
-		ioapic_phys = mp_ioapic_addr;
-#endif
 	} else {
 		/*
 		 * set up a fake all zeroes page to simulate the
@@ -697,17 +754,27 @@
 		 * this way if some buggy code writes to this page ...
 		 */
 		apic_phys = __pa(memory_start);
-		ioapic_phys = __pa(memory_start+PAGE_SIZE);
-		memset((void *)memory_start, 0, 2*PAGE_SIZE);
-		memory_start += 2*PAGE_SIZE;
+		memset((void *)memory_start, 0, PAGE_SIZE);
+		memory_start += PAGE_SIZE;
 	}
+	set_fixmap(FIX_APIC_BASE,apic_phys);
+	printk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
 
 #ifdef CONFIG_X86_IO_APIC
-	set_fixmap(FIX_APIC_BASE,apic_phys);
-	set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
+	{
+		unsigned long ioapic_phys;
 
-	printk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
-	printk("mapped IOAPIC to %08lx (%08lx)\n", fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
+		if (smp_found_config) {
+			ioapic_phys = mp_ioapic_addr;
+		} else {
+			ioapic_phys = __pa(memory_start);
+			memset((void *)memory_start, 0, PAGE_SIZE);
+			memory_start += PAGE_SIZE;
+		}
+		set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
+		printk("mapped IOAPIC to %08lx (%08lx)\n",
+				fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
+	}
 #endif
 
 	return memory_start;
@@ -925,8 +992,7 @@
 	apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); 			/* Target chip     	*/
 	cfg=apic_read(APIC_ICR);
 	cfg&=~0xCDFFF;								/* Clear bits 		*/
-	cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG
-		| APIC_DEST_ASSERT | APIC_DEST_DM_INIT);
+	cfg |= (APIC_DEST_LEVELTRIG | APIC_DEST_ASSERT | APIC_DEST_DM_INIT);
 	apic_write(APIC_ICR, cfg);						/* Send IPI */
 
 	udelay(200);
@@ -937,8 +1003,7 @@
 	apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i));			/* Target chip     	*/
 	cfg=apic_read(APIC_ICR);
 	cfg&=~0xCDFFF;								/* Clear bits 		*/
-	cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG
-				| APIC_DEST_DM_INIT);
+	cfg |= (APIC_DEST_LEVELTRIG | APIC_DEST_DM_INIT);
 	apic_write(APIC_ICR, cfg);						/* Send IPI */
 
 	/*
@@ -974,9 +1039,7 @@
 		apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i));			/* Target chip     	*/
 		cfg=apic_read(APIC_ICR);
 		cfg&=~0xCDFFF;								/* Clear bits 		*/
-		cfg |= (APIC_DEST_FIELD
-			| APIC_DEST_DM_STARTUP
-			| (start_eip >> 12));						/* Boot on the stack 	*/
+		cfg |= (APIC_DEST_DM_STARTUP | (start_eip >> 12));						/* Boot on the stack 	*/
 		SMP_PRINTK(("Before start apic_write.\n"));
 		apic_write(APIC_ICR, cfg);						/* Kick the second 	*/
 
@@ -1099,7 +1162,6 @@
 void __init smp_boot_cpus(void)
 {
 	int i;
-	unsigned long cfg;
 
 #ifdef CONFIG_MTRR
 	/*  Must be done before other processors booted  */
@@ -1134,20 +1196,20 @@
 
 	cpu_number_map[boot_cpu_id] = 0;
 
-#ifdef CONFIG_X86_IO_APIC
 	/*
-	 *	If we don't conform to the Intel MPS standard, get out
-	 *	of here now!
+	 * If we couldnt find an SMP configuration at boot time,
+	 * get out of here now!
 	 */
 
 	if (!smp_found_config)
 	{
 		printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n");
+#ifndef CONFIG_VISWS
 		io_apic_irqs = 0;
+#endif
 		cpu_online_map = cpu_present_map;
 		goto smp_done;
 	}
-#endif
 
 	/*
 	 *	If SMP should be disabled, then really disable it!
@@ -1246,29 +1308,34 @@
 	 *	Cleanup possible dangling ends...
 	 */
 
-	/*
-	 *	Install writable page 0 entry.
-	 */
-
-	cfg = pg0[0];
-	pg0[0] = 3;	/* writeable, present, addr 0 */
-	local_flush_tlb();
+#ifndef CONFIG_VISWS
+	{
+		unsigned long cfg;
 
-	/*
-	 *	Paranoid:  Set warm reset code and vector here back
-	 *	to default values.
-	 */
+		/*
+		 *	Install writable page 0 entry.
+		 */
+		cfg = pg0[0];
+		pg0[0] = 3;	/* writeable, present, addr 0 */
+		local_flush_tlb();
+	
+		/*
+		 *	Paranoid:  Set warm reset code and vector here back
+		 *	to default values.
+		 */
 
-	CMOS_WRITE(0, 0xf);
+		CMOS_WRITE(0, 0xf);
 
-	*((volatile long *) phys_to_virt(0x467)) = 0;
+		*((volatile long *) phys_to_virt(0x467)) = 0;
 
-	/*
-	 *	Restore old page 0 entry.
-	 */
+		/*
+		 *	Restore old page 0 entry.
+		 */
 
-	pg0[0] = cfg;
-	local_flush_tlb();
+		pg0[0] = cfg;
+		local_flush_tlb();
+	}
+#endif
 
 	/*
 	 *	Allow the user to impress friends.
@@ -1301,15 +1368,16 @@
 	SMP_PRINTK(("Boot done.\n"));
 
 	cache_APIC_registers();
-#ifdef CONFIG_X86_IO_APIC
+#ifndef CONFIG_VISWS
 	/*
 	 * Here we can be sure that there is an IO-APIC in the system. Let's
 	 * go and set it up:
 	 */
 	if (!skip_ioapic_setup) 
 		setup_IO_APIC();
-smp_done:
 #endif
+
+smp_done:
 }
 
 
@@ -1393,7 +1461,7 @@
 	unsigned int cfg;
 
 	cfg = __get_ICR();
-	cfg |= APIC_DEST_FIELD|APIC_DEST_DM_FIXED|shortcut|vector;
+	cfg |= APIC_DEST_DM_FIXED|shortcut|vector;
 
 	return cfg;
 }
@@ -1903,7 +1971,7 @@
 		((long)(t2-t1)/LOOPS)/(1000000/HZ),
 		((long)(t2-t1)/LOOPS)%(1000000/HZ)  );
 
-	printk("..... APIC bus clock speed is %ld.%04ld MHz.\n",
+	printk("..... system bus clock speed is %ld.%04ld MHz.\n",
 		calibration_result/(1000000/HZ),
 		calibration_result%(1000000/HZ)  );
 #undef LOOPS
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.2.0-pre9/linux/arch/i386/mm/init.c	Fri Jan  1 12:58:19 1999
+++ linux/arch/i386/mm/init.c	Thu Jan 21 11:28:40 1999
@@ -279,39 +279,6 @@
  * kernel.
  * It may also hold the MP configuration table when we are booting SMP.
  */
-#ifdef __SMP__
-	/*
-	 * FIXME: Linux assumes you have 640K of base ram..
-	 * this continues the error...
-	 *
-	 * 1) Scan the bottom 1K for a signature
-	 * 2) Scan the top 1K of base RAM
-	 * 3) Scan the 64K of bios
-	 */
-	if (!smp_scan_config(0x0,0x400) &&
-	    !smp_scan_config(639*0x400,0x400) &&
-	    !smp_scan_config(0xF0000,0x10000)) {
-		/*
-		 * If it is an SMP machine we should know now, unless the
-		 * configuration is in an EISA/MCA bus machine with an
-		 * extended bios data area. 
-		 *
-		 * there is a real-mode segmented pointer pointing to the
-		 * 4K EBDA area at 0x40E, calculate and scan it here.
-		 *
-		 * NOTE! There are Linux loaders that will corrupt the EBDA
-		 * area, and as such this kind of SMP config may be less
-		 * trustworthy, simply because the SMP table may have been
-		 * stomped on during early boot. These loaders are buggy and
-		 * should be fixed.
-		 */
-		address = *(unsigned short *)phys_to_virt(0x40E);
-		address<<=4;
-		smp_scan_config(address, 0x1000);
-		if (smp_found_config)
-			printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");
-	}
-#endif
 	start_mem = PAGE_ALIGN(start_mem);
 	address = PAGE_OFFSET;
 	pg_dir = swapper_pg_dir;
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- v2.2.0-pre9/linux/drivers/block/ide-pci.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/block/ide-pci.c	Sun Jan 24 21:54:35 1999
@@ -150,22 +150,15 @@
  */
 __initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name))
 {
-	unsigned int addressbios = 0;
-
-	pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addressbios);
-
 	switch(dev->device) {
 		case PCI_DEVICE_ID_ARTOP_ATP850UF:
 		case PCI_DEVICE_ID_PROMISE_20246:
-			pci_write_config_byte(dev, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_ENABLE);
-			printk("%s: ROM enabled ", name);
-
-			if (!addressbios) {
-				printk("but no address\n");
-			} else {
-				printk("at 0x%08x\n", addressbios);
+			if (dev->rom_address) {
+				pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+					dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+				printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
 			}
-
+			
 			if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID) {
 				unsigned char irq1 = 0, irq2 = 0;
 
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.2.0-pre9/linux/drivers/char/bttv.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/bttv.c	Sun Jan 24 21:54:35 1999
@@ -535,6 +535,8 @@
 	{ 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
         /* AVerMedia TVCapture 98 */
 	{ 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
+        /* Aimslab VHX */
+        { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
 };
 #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
 
@@ -764,7 +766,7 @@
 	/* NTSC */
 	{ 28636363,
           768, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
-          910, 128, 754, 0x1a, 144},
+          910, 128, 910, 0x1a, 144},
 /*
 	{ 28636363,
           640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
@@ -815,10 +817,6 @@
 	DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po));
 	DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe));
         
-	/* setup proper VBI capture length for given video mode */
-	btwrite(tvnorms[btv->win.norm].vbipack, BT848_VBI_PACK_SIZE);
-	btwrite(1, BT848_VBI_PACK_DEL);
-        
 	*(po++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(po++)=0;
 	for (i=0; i<16; i++) 
 	{
@@ -1281,6 +1279,8 @@
 	btwrite(tvn->adelay, BT848_ADELAY);
 	btwrite(tvn->bdelay, BT848_BDELAY);
 	btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
+	btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE);
+	btwrite(1, BT848_VBI_PACK_DEL);
 
         btv->pll.pll_ofreq = tvn->Fsc;
         set_pll(btv);
@@ -2880,7 +2880,9 @@
 
 		} else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) {
 			btv->type=BTTV_STB;
-
+		} else 
+		        if (I2CRead(&(btv->i2c), I2C_VHX)>=0) {
+			        btv->type=BTTV_VHX;
 		} else {
 			if (I2CRead(&(btv->i2c), 0x80)>=0) /* check for msp34xx */
 				btv->type = BTTV_MIROPRO;
@@ -2938,6 +2940,9 @@
                 case TDA9850:
                         init_tda9850(&(btv->i2c));
                         break; 
+                case TDA9840:
+                        init_tda9840(&(btv->i2c));
+                        break; 
                 case TDA8425:
                         init_tda8425(&(btv->i2c));
                         break;
@@ -2977,6 +2982,9 @@
 		case BTTV_AVERMEDIA98: 
 			strcat(btv->video_dev.name,"(AVerMedia TVCapture 98)");
 			break;
+		case BTTV_VHX:
+			strcpy(btv->video_dev.name,"BT848(Aimslab-VHX)");
+ 			break;
 	}
 	printk("%s\n",btv->video_dev.name);
 	audio(btv, AUDIO_MUTE);
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.2.0-pre9/linux/drivers/char/bttv.h	Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/bttv.h	Sun Jan 24 21:54:35 1999
@@ -21,7 +21,7 @@
 #ifndef _BTTV_H_
 #define _BTTV_H_
 
-#define BTTV_VERSION_CODE 0x000520
+#define BTTV_VERSION_CODE 0x000523
 
 #include <linux/types.h>
 #include <linux/wait.h>
@@ -37,8 +37,7 @@
 
 #define MAX_GBUFFERS	2
 #define RISCMEM_LEN	(32744*2)
-#define VBI_MAXLINES    19
-#define VBIBUF_SIZE     (2048*VBI_MAXLINES*2)
+#define VBIBUF_SIZE     65536
 
 /* maximum needed buffer size for extended VBI frame mode capturing */
 #define BTTV_MAX_FBUF	0x190000
@@ -207,6 +206,7 @@
 #define BTTV_MIROPRO       0x0b
 #define BTTV_ADSTECH_TV    0x0c
 #define BTTV_AVERMEDIA98   0x0d
+#define BTTV_VHX   	   0x0e
 
 #define AUDIO_TUNER        0x00
 #define AUDIO_RADIO        0x01
@@ -227,6 +227,7 @@
 #define I2C_TDA8425        0x82
 #define I2C_HAUPEE         0xa0
 #define I2C_STBEE          0xae
+#define I2C_VHX 	   0xc0
 
 #define TDA9840_SW	   0x00
 #define TDA9840_LVADJ	   0x02
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.2.0-pre9/linux/drivers/char/mem.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/char/mem.c	Sun Jan 24 21:55:04 1999
@@ -4,6 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/miscdevice.h>
 #include <linux/tpqic02.h>
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c
--- v2.2.0-pre9/linux/drivers/char/msp3400.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/msp3400.c	Sun Jan 24 21:58:50 1999
@@ -83,7 +83,7 @@
 
 	/* thread */
 	struct task_struct  *thread;
-	struct semaphore    *wait;
+	struct wait_queue   *wq;
 	struct semaphore    *notify;
 	int                  active,restart,rmmod;
 
@@ -500,14 +500,12 @@
 {
 	struct msp3400c *msp = (struct msp3400c*)data;   /* XXX alpha ??? */
 
-	if (!msp->active)
-		up(msp->wait);    
+	wake_up_interruptible(&msp->wq);
 }
 
 static int msp3400c_thread(void *data)
 {
 	struct msp3400c *msp = data;
-	struct semaphore sem = MUTEX_LOCKED;
     
 	struct CARRIER_DETECT *cd;
 	int                   count, max1,max2,val1,val2, val,this;
@@ -525,7 +523,7 @@
 	current->fs->umask = 0;
 	strcpy(current->comm,"msp3400");
 
-	msp->wait   = &sem;
+	msp->wq     = NULL;
 	msp->thread = current;
 
 #ifdef __SMP__
@@ -541,7 +539,7 @@
 			goto done;
 		if (debug > 1)
 			printk("msp3400: thread: sleep\n");
-		down_interruptible(&sem);
+		interruptible_sleep_on(&msp->wq);
 		if (debug > 1)
 			printk("msp3400: thread: wakeup\n");
 		if (msp->rmmod || signal_pending(current))
@@ -735,7 +733,6 @@
 
 done:
 	dprintk("msp3400: thread: exit\n");
-	msp->wait   = NULL;
 	msp->active = 0;
 	msp->thread = NULL;
 
@@ -777,6 +774,7 @@
 			goto done;
 		dprintk("msp3410: thread: sleep\n");
 		down_interruptible(&sem);
+		sem.owner = 0;
 		dprintk("msp3410: thread: wakeup\n");
 		if (msp->rmmod)
 			goto done;
@@ -1072,12 +1070,12 @@
 
 	/* startup control thread */
 	MOD_INC_USE_COUNT;
+	msp->wq     = NULL;
 	msp->notify = &sem;
 	kernel_thread(msp3400c_thread, (void *)msp, 0);
 	down(&sem);
 	msp->notify = NULL;
-	if (!msp->active)
-		up(msp->wait);
+	wake_up_interruptible(&msp->wq);
 
 	printk(KERN_INFO "msp3400: init: chip=%s",device->name);
 	if (msp->nicam)
@@ -1109,8 +1107,7 @@
 	{
 		msp->notify = &sem;
 		msp->rmmod = 1;
-		if (!msp->active)
-			up(msp->wait);
+		wake_up_interruptible(&msp->wq);
 		down(&sem);
 		msp->notify = NULL;
 	}
@@ -1158,10 +1155,9 @@
 		/* channels switching step two -- trigger sound carrier scan */
 		msp->watch_stereo=0;
 		del_timer(&msp->wake_stereo);
-		if (!msp->active)
-			up(msp->wait);
-		else
+		if (msp->active)
 			msp->restart = 1;
+		wake_up_interruptible(&msp->wq);
 		break;
 
 	case MSP_GET_VOLUME:
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.2.0-pre9/linux/drivers/char/pc_keyb.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/char/pc_keyb.c	Thu Jan 21 14:00:21 1999
@@ -79,11 +79,11 @@
 #define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
 
 #define MAX_RETRIES	60		/* some aux operations take long time*/
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-# define AUX_IRQ	9		/* Jensen is odd indeed */
-#else
+
+#ifndef AUX_IRQ
 # define AUX_IRQ	12
 #endif
+
 #endif /* CONFIG_PSMOUSE */
 
 /*
@@ -811,7 +811,7 @@
 	if (--aux_count)
 		return 0;
 	kbd_write_cmd(AUX_INTS_OFF);			    /* Disable controller ints */
-	kbd_write(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG);
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE);
 	free_irq(AUX_IRQ, AUX_DEV);
 	return 0;
 }
@@ -831,7 +831,7 @@
 		aux_count--;
 		return -EBUSY;
 	}
-	kbd_write(KBD_CCMD_MOUSE_ENABLE, KBD_CNTL_REG);	/* Enable the
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE);	/* Enable the
 							   auxiliary port on
 							   controller. */
 	aux_write_dev(AUX_ENABLE_DEV); /* Enable aux device */
@@ -950,14 +950,14 @@
 	queue->proc_list = NULL;
 
 #ifdef INITIALIZE_MOUSE
-	kbd_write(KBD_CCMD_MOUSE_ENABLE, KBD_CNTL_REG);	/* Enable Aux. */
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE);	/* Enable Aux. */
 	aux_write_dev(AUX_SET_SAMPLE);
 	aux_write_dev(100);			/* 100 samples/sec */
 	aux_write_dev(AUX_SET_RES);
 	aux_write_dev(3);			/* 8 counts per mm */
 	aux_write_dev(AUX_SET_SCALE21);		/* 2:1 scaling */
 #endif /* INITIALIZE_MOUSE */
-	kbd_write(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG); /* Disable aux device. */
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
 	kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
 
 	return 0;
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- v2.2.0-pre9/linux/drivers/net/ibmtr.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/net/ibmtr.c	Sun Jan 24 22:04:02 1999
@@ -801,10 +801,10 @@
 	struct tok_info *ti;
 	struct device *dev;
 
+	dev = dev_id;
 #if TR_VERBOSE
 	DPRINTK("Int from tok_driver, dev : %p\n",dev);
 #endif
-	dev = dev_id;
 	ti  = (struct tok_info *) dev->priv;
 
       	/* Disable interrupts till processing is finished */
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.2.0-pre9/linux/drivers/net/irda/irport.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/irport.c	Sun Jan 24 21:55:04 1999
@@ -53,7 +53,6 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/errno.h>
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c
--- v2.2.0-pre9/linux/drivers/net/irda/uircc.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/uircc.c	Sun Jan 24 21:55:04 1999
@@ -42,7 +42,6 @@
 #include <linux/malloc.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.2.0-pre9/linux/drivers/net/ne2k-pci.c	Tue Jul 21 00:15:31 1998
+++ linux/drivers/net/ne2k-pci.c	Sun Jan 24 22:04:02 1999
@@ -70,6 +70,7 @@
 	{0x4a14, 0x5000, "NetVin NV5000SC"},
 	{0x1106, 0x0926, "Via 82C926"},
 	{0x10bd, 0x0e34, "SureCom NE34"},
+	{0x1050, 0x5a5a, "Winbond"},
 	{0,}
 };
 
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.2.0-pre9/linux/drivers/scsi/megaraid.h	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/megaraid.h	Mon Jan 25 16:05:12 1999
@@ -1,6 +1,8 @@
 #ifndef __MEGARAID_H__
 #define __MEGARAID_H__
 
+#include <linux/version.h>
+
 #define IN_ISR                  0x80000000L
 #define NO_INTR                 0x40000000L
 #define IN_TIMEOUT              0x20000000L
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c
--- v2.2.0-pre9/linux/drivers/sound/ad1816.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/sound/ad1816.c	Sun Jan 24 22:04:02 1999
@@ -1,6 +1,6 @@
 /*
 
-AD1816 lowlevel sound driver for Linux 2.1.128 (and above)
+AD1816 lowlevel sound driver for Linux 2.2.0 and above
 
 Copyright (C) 1998 by Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
 Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
@@ -32,16 +32,18 @@
 
 -------------------------------------------------------------------------------
 
-version: 1.1
-cvs: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.24.2.8 1998/12/04 16:39:46 tek Exp $
+version: 1.2
+cvs: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.28 1999/01/16 19:01:36 tek Exp $
 status: experimental
-date: 1998/12/04
+date: 1999/01/16
 
 Changes:
 	Oleg Drokin: Some cleanup of load/unload functions.    1998/11/24
 	
 	Thorsten Knabe: attach and unload rewritten, 
 	some argument checks added                             1998/11/30
+
+	Thorsten Knabe: Buggy isa bridge workaround added      1999/01/16
 */
 
 #include <linux/config.h>
@@ -164,7 +166,9 @@
 	save_flags (flags); 
 	cli ();
 	
-	disable_dma(audio_devs[dev]->dmap_in->dma);
+	if(!isa_dma_bridge_buggy) {
+	        disable_dma(audio_devs[dev]->dmap_in->dma);
+	}
 	
 	buffer=inb(devc->base+9);
 	if (buffer & 0x01) {
@@ -172,8 +176,10 @@
 		outb(buffer & ~0x01,devc->base+9); 
 	}
 
-	enable_dma(audio_devs[dev]->dmap_in->dma);
-	
+	if(!isa_dma_bridge_buggy) {
+	        enable_dma(audio_devs[dev]->dmap_in->dma);
+	}
+
 	/* Clear interrupt status */
 	outb (~0x40, devc->base+1);	
 	
@@ -195,15 +201,20 @@
 	/* Mute pcm output */
 	ad_write(devc, 4, ad_read(devc,4)|0x8080);
 
-	disable_dma(audio_devs[dev]->dmap_out->dma);
-	
+	if(!isa_dma_bridge_buggy) {
+	        disable_dma(audio_devs[dev]->dmap_out->dma);
+	}
+
 	buffer=inb(devc->base+8);
 	if (buffer & 0x01) {
 		/* disable capture */
 		outb(buffer & ~0x01,devc->base+8); 
 	}
-	enable_dma(audio_devs[dev]->dmap_out->dma);
-	
+
+	if(!isa_dma_bridge_buggy) {
+	        enable_dma(audio_devs[dev]->dmap_out->dma);
+	}
+
 	/* Clear interrupt status */
 	outb ((unsigned char)~0x80, devc->base+1);	
 
@@ -707,11 +718,11 @@
 
 static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
 {
-	0x6464,			/* Master Volume */
+	0x4343,			/* Master Volume */
 	0x3232,			/* Bass */
 	0x3232,			/* Treble */
 	0x0000,			/* FM */
-	0x6464,			/* PCM */
+	0x4343,			/* PCM */
 	0x0000,			/* PC Speaker */
 	0x0000,			/* Ext Line */
 	0x0000,			/* Mic */
@@ -1080,7 +1091,13 @@
 	int tmp;
 	
 	printk("ad1816: AD1816 sounddriver Copyright (C) 1998 by Thorsten Knabe\n");
-	printk("ad1816: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.24.2.8 1998/12/04 16:39:46 tek Exp $\n");
+	printk("ad1816: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.28 1999/01/16 19:01:36 tek Exp $\n");
+	printk("ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, isadmabug=%d\n",
+	       hw_config->io_base,
+	       hw_config->irq,
+	       hw_config->dma,
+	       hw_config->dma2,
+	       isa_dma_bridge_buggy);
 
 	if (check_region (io_base, 16)) {
 		printk ("ad1816: I/O port 0x%03x not free\n", io_base);
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.2.0-pre9/linux/drivers/sound/sb_card.c	Fri Nov 27 13:09:25 1998
+++ linux/drivers/sound/sb_card.c	Sun Jan 24 22:04:02 1999
@@ -136,6 +136,7 @@
 int pas2 = 0;	/* Set pas2=1 to load this as support for pas2 */
 int sm_games = 0;	/* Mixer - see sb_mixer.c */
 int acer = 0;	/* Do acer notebook init */
+int esstype = 0;	/* ESS chip type */
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
@@ -147,6 +148,7 @@
 MODULE_PARM(trix, "i");
 MODULE_PARM(pas2, "i");
 MODULE_PARM(sm_games, "i");
+MODULE_PARM(esstype, "i");
 
 void *smw_free = NULL;
 
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.2.0-pre9/linux/drivers/sound/sb_common.c	Tue Jan 19 11:32:52 1999
+++ linux/drivers/sound/sb_common.c	Sun Jan 24 22:04:02 1999
@@ -645,10 +645,6 @@
 				}
 			}
 		}
-#if defined(__SMP__)
-		/* Skip IRQ detection if SMP (doesn't work) */
-		devc->irq_ok = 1;
-#else
 		if (devc->major == 4 && devc->minor <= 11 )	/* Won't work */
 			devc->irq_ok = 1;
 		else
@@ -671,7 +667,6 @@
 				DDB(printk("IRQ test OK (IRQ%d)\n", devc->irq));
 			}
 		}
-#endif				/* __SMP__ */
 	}			/* IRQ setup */
 	request_region(hw_config->io_base, 16, "soundblaster");
 
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/sound/sb_ess.c linux/drivers/sound/sb_ess.c
--- v2.2.0-pre9/linux/drivers/sound/sb_ess.c	Tue Jan 19 11:32:52 1999
+++ linux/drivers/sound/sb_ess.c	Mon Jan 25 13:44:17 1999
@@ -2,8 +2,6 @@
  * Created: 9-Jan-1999
  *
  * TODO: 	consistency speed calculations!!
- *			what's the sample rate when duplex? Docs contradict.
- *			I broke IRQ detection for non-SMP machines
  * ????:	Did I break MIDI support?
  *
  * This files contains ESS chip specifics. It's based on the existing ESS
@@ -19,6 +17,10 @@
  * be one of 0, 1 or 3, dma16 can be one of 0, 1, 3 or 5. DMA 5 is a 16 bit
  * DMA channel, while the others are 8 bit..
  *
+ * ESS detection isn't full proof (yet). If it fails an additional module
+ * parameter esstype can be specified to be one of the following:
+ * 688, 1688, 1868, 1869, 1788, 1887, 1888
+ *
  * History:
  *
  * Rolf Fokkens	(Dec 20 1998):	ES188x recording level support on a per
@@ -77,6 +79,9 @@
  * Oh, and this is another trap: in ES1887 docs mixer register 0x70 is decribed
  * as if it's exactly the same as register 0xa1. This is *NOT* true. The
  * description of 0x70 in ES1869 docs is accurate however.
+ * Well, the assumption about ES1869 was wrong: register 0x70 is very much
+ * like register 0xa1, except that bit 7 is allways 1, whatever you want
+ * it to be.
  *
  * When using audio 2 mixer register 0x72 seems te be meaningless. Only 0xa2
  * has effect.
@@ -85,6 +90,16 @@
  * the fact that register 0x78 isn't reset is great when you wanna change back
  * to single dma operation (simplex): audio 2 is still operation, and uses the
  * same dma as audio 1: your ess changes into a funny echo machine.
+ *
+ * Received the new that ES1688 is detected as a ES1788. Did some thinking:
+ * the ES1887 detection scheme suggests in step 2 to try if bit 3 of register
+ * 0x64 can be changed. This is inaccurate, first I inverted the * check: "If
+ * can be modified, it's a 1688", which lead to a correct detection
+ * of my ES1887. It resulted however in bad detection of 1688 (reported by mail)
+ * and 1868 (if no PnP detection first): they result in a 1788 being detected.
+ * I don't have docs on 1688, but I do have docs on 1868: The documentation is
+ * probably inaccurate in the fact that I should check bit 2, not bit 3. This
+ * is what I do now.
  */
 
 /*
@@ -141,14 +156,14 @@
  * ES1946	yes		This is a PCI chip; not handled by this driver
  */
 
-#include <linux/delay.h>
-
 #include "sound_config.h"
 #include "sb_mixer.h"
 #include "sb.h"
 
 #include "sb_ess.h"
 
+extern int esstype; /* module parameter in sb_card.c */
+
 #ifdef FKS_LOGGING
 static void ess_show_mixerregs (sb_devc *devc);
 #endif
@@ -255,10 +270,10 @@
 	int retval;
 
 	speed   = *speedp;
-	divider = (clock + speed / 2) / *speedp;
+	divider = (clock + speed / 2) / speed;
 	retval  = revert - divider;
-	if (retval > 127) {
-		retval  = 127;
+	if (retval > revert - 1) {
+		retval  = revert - 1;
 		divider = revert - retval;
 	}
 	/* This line is suggested. Must be wrong I think
@@ -299,60 +314,59 @@
 
 /*
  * Depending on the audiochannel ESS devices can
- * have different clock settings.
+ * have different clock settings. These are made consistent for duplex
+ * however.
  * callers of ess_speed only do an audionum suggestion, which means
  * input suggests 1, output suggests 2. This suggestion is only true
  * however when doing duplex.
  */
-static void ess_speed (sb_devc *devc, int audionum)
+static void ess_common_speed (sb_devc *devc, int *speedp, int *divp)
 {
-	int choice;
-	int speed = devc->speed;
-	int clock1, clock2;
-	int rev1, rev2;
-	int div;
-
-	if (!devc->duplex) audionum = 1;
+	int diff = 0, div, choice;
 
-	if (audionum == 1) {
-		rev1	= 128;
-		clock1	= 397700;
-		rev2	= 256;
-		clock2	= 795500;
+	if (devc->duplex) {
+		/*
+		 * The 0x80 is important for the first audio channel
+		 */
+		div = 0x80 | ess_calc_div (795500, 128, speedp, &diff);
 	} else {
-		rev1	= 128;
-		clock1	= 793800;
-		rev2	= 128;
-		clock2	= 768000;
+		choice = ess_calc_best_speed (397700, 128, 795500, 256, &div, speedp);
+		if (choice == 2) div |= 0x80;
 	}
-	choice = ess_calc_best_speed
-			(clock1, rev1, clock2, rev2, &div, &speed);
+	*divp = div;
+}
+
+static void ess_speed (sb_devc *devc, int audionum)
+{
+	int speed;
+	int div, div2;
+
+	ess_common_speed (devc, &(devc->speed), &div);
 
 #ifdef FKS_REG_LOGGING
-printk (KERN_INFO "FKS: ess_speed (%d) b speed = %d, div=%x\n", audionum, speed, div);
+printk (KERN_INFO "FKS: ess_speed (%d) b speed = %d, div=%x\n", audionum, devc->speed, div);
 #endif
 
-	if (choice == 2) div |= 0x80;
+	/* Set filter roll-off to 90% of speed/2 */
+	speed = (devc->speed * 9) / 20;
+
+	div2 = 256 - 7160000 / (speed * 82);
+
+	if (!devc->duplex) audionum = 1;
 
 	if (audionum == 1) {
 		/* Change behaviour of register A1 *
 		sb_chg_mixer(devc, 0x71, 0x20, 0x20)
 		* For ES1869 only??? */
 		ess_write (devc, 0xa1, div);
+		ess_write (devc, 0xa2, div2);
 	} else {
 		ess_setmixer (devc, 0x70, div);
-	}
-
-	/* Set filter roll-off to 90% of speed/2 */
-	speed = (speed * 9) / 20;
-
-	div = 256 - 7160000 / (speed * 82);
-
-	if (audionum == 1) {
-		ess_write (devc, 0xa2, div);
-	} else {
-		ess_write (devc, 0xa2, div);
-		ess_setmixer (devc, 0x72, div);
+		/*
+		 * FKS: fascinating: 0x72 doesn't seem to work.
+		 */
+		ess_write (devc, 0xa2, div2);
+		ess_setmixer (devc, 0x72, div2);
 	}
 }
 
@@ -442,7 +456,9 @@
 	sb_devc *devc = audio_devs[dev]->devc;
 	unsigned char bits;
 
+/* FKS: qqq
 	sb_dsp_reset(devc);
+*/
 
 	/*
 	 * Auto-Initialize:
@@ -626,31 +642,19 @@
 	devc->trigger_bits = bits | bits_16;
 }
 
-/*
- * FKS: Change this!! it's the old routine!
- */
 static int ess_audio_set_speed(int dev, int speed)
 {
 	sb_devc *devc = audio_devs[dev]->devc;
-	int divider;
+	int minspeed, maxspeed, dummydiv;
 
-	if (speed > 0)
-	{
-		if (speed < 5000)
-			speed = 5000;
-		if (speed > 48000)
-			speed = 48000;
+	if (speed > 0) {
+		minspeed = (devc->duplex ? 6215  : 5000 );
+		maxspeed = (devc->duplex ? 44100 : 48000);
+		if (speed < minspeed) speed = minspeed;
+		if (speed > maxspeed) speed = maxspeed;
+
+		ess_common_speed (devc, &speed, &dummydiv);
 
-		if (speed > 22000)
-		{
-			divider = (795500 + speed / 2) / speed;
-			speed = (795500 + divider / 2) / divider;
-		}
-		else
-		{
-			divider = (397700 + speed / 2) / speed;
-			speed = (397700 + divider / 2) / divider;
-		}
 		devc->speed = speed;
 	}
 	return devc->speed;
@@ -972,7 +976,7 @@
 	unsigned char cfg;
 	int ess_major = 0, ess_minor = 0;
 	int i;
-	static char name[100];
+	static char name[100], modelname[10];
 
 	/*
 	 * Try to detect ESS chips.
@@ -1022,13 +1026,42 @@
 	if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
 		char *chip = NULL;
 
-		if ((ess_minor & 0x0f) < 8) {
+		if (esstype) {
+			int submodel = -1;
+
+			switch (esstype) {
+			case 688:
+				submodel = 0x00;
+				break;
+			case 1688:
+				submodel = 0x08;
+				break;
+			case 1868:
+				submodel = SUBMDL_ES1868;
+				break;
+			case 1869:
+				submodel = SUBMDL_ES1869;
+				break;
+			case 1788:
+				submodel = SUBMDL_ES1788;
+				break;
+			case 1887:
+				submodel = SUBMDL_ES1887;
+				break;
+			case 1888:
+				submodel = SUBMDL_ES1888;
+				break;
+			};
+			if (submodel != -1) {
+				devc->submodel = submodel;
+				sprintf (modelname, "ES%d", esstype);
+				chip = modelname;
+			};
+		};
+		if (chip == NULL && (ess_minor & 0x0f) < 8) {
 			chip = "ES688";
 		};
-#ifdef FKS_LOGGING
-printk(KERN_INFO "FKS: mixer_reset\n");
-		ess_setmixer (devc, 0x00, 0x00);
-#endif
+
 		if (chip == NULL) {
 			int type;
 
@@ -1049,7 +1082,24 @@
 				break;
 			};
 		};
-		if (chip == NULL && !ess_probe(devc, 0x64, (1 << 3))) {
+#if 0
+		/*
+		 * this one failed:
+		 * the probing of bit 4 is another thought: from ES1788 and up, all
+		 * chips seem to have hardware volume control. Bit 4 is readonly to
+		 * check if a hardware volume interrupt has fired.
+		 * Cause ES688/ES1688 don't have this feature, bit 4 might be writeable
+		 * for these chips.
+		 */
+		if (chip == NULL && !ess_probe(devc, 0x64, (1 << 4))) {
+#endif
+		/*
+		 * the probing of bit 2 is my idea. The ES1887 docs want me to probe
+		 * bit 3. This results in ES1688 being detected as ES1788.
+		 * Bit 2 is for "Enable HWV IRQE", but as ES(1)688 chips don't have
+		 * HardWare Volume, I think they don't have this IRQE.
+		 */
+		if (chip == NULL && ess_probe(devc, 0x64, (1 << 2))) {
 			if (ess_probe (devc, 0x70, 0x7f)) {
 				if (ess_probe (devc, 0x64, (1 << 5))) {
 					chip = "ES1887";
diff -u --recursive --new-file v2.2.0-pre9/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c
--- v2.2.0-pre9/linux/drivers/sound/sb_mixer.c	Tue Jan 19 11:32:52 1999
+++ linux/drivers/sound/sb_mixer.c	Sat Jan 23 10:45:25 1999
@@ -425,7 +425,6 @@
 			if (devc->model == MDL_ESS && ess_set_recmask (devc, &devmask)) {
 				break;
 			};
-printk (KERN_INFO "FKS: set_recmask not handled by ess_set_recmask\n");
 			if (devmask != SOUND_MASK_MIC &&
 				devmask != SOUND_MASK_LINE &&
 				devmask != SOUND_MASK_CD)
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/coda/cnode.c linux/fs/coda/cnode.c
--- v2.2.0-pre9/linux/fs/coda/cnode.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/coda/cnode.c	Mon Jan 25 10:28:35 1999
@@ -83,19 +83,21 @@
         }
 
 	cnp = ITOC(*inode);
-	if  ( cnp->c_magic == 0 ) {
-		memset(cnp, 0, (int) sizeof(struct coda_inode_info));
-		cnp->c_fid = *fid;
-		cnp->c_magic = CODA_CNODE_MAGIC;
-		cnp->c_flags = 0;
-		cnp->c_vnode = *inode;
-		INIT_LIST_HEAD(&(cnp->c_cnhead));
-		INIT_LIST_HEAD(&(cnp->c_volrootlist));
-	} else {
-	        cnp->c_flags = 0;
-		printk("coda_cnode make on initialized inode %ld, %s!\n",
-		       (*inode)->i_ino, coda_f2s(&cnp->c_fid));
-	}
+       if  ( cnp->c_magic != 0 ) {
+               printk("coda_cnode make on initialized inode %ld, old %s new
+%s!\n",
+                      (*inode)->i_ino, coda_f2s(&cnp->c_fid), coda_f2s2(fid));
+               iput(*inode);
+               return -ENOENT;
+        }
+ 
+       memset(cnp, 0, (int) sizeof(struct coda_inode_info));
+       cnp->c_fid = *fid;
+       cnp->c_magic = CODA_CNODE_MAGIC;
+       cnp->c_flags = 0;
+       cnp->c_vnode = *inode;
+       INIT_LIST_HEAD(&(cnp->c_cnhead));
+       INIT_LIST_HEAD(&(cnp->c_volrootlist));
 
 	/* fill in the inode attributes */
 	if ( coda_f2i(fid) != ino ) {
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/coda/coda_linux.c linux/fs/coda/coda_linux.c
--- v2.2.0-pre9/linux/fs/coda/coda_linux.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/coda/coda_linux.c	Mon Jan 25 10:28:35 1999
@@ -30,8 +30,19 @@
 int coda_print_entry = 0; 
 int coda_access_cache = 1;
 
-/* caller must allocate 36 byte string ! */
+/* print a fid */
 char * coda_f2s(ViceFid *f)
+{
+	static char s[60];
+	if ( f ) {
+		sprintf(s, "(%-#lx,%-#lx,%-#lx)", 
+			 f->Volume, f->Vnode, f->Unique);
+	}
+	return s;
+}
+
+/* print another fid */
+char * coda_f2s2(ViceFid *f)
 {
 	static char s[60];
 	if ( f ) {
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.2.0-pre9/linux/fs/coda/dir.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/coda/dir.c	Mon Jan 25 10:28:35 1999
@@ -1,3 +1,4 @@
+
 /*
  * Directory operations for Coda filesystem
  * Original version: (C) 1996 P. Braam and M. Callahan
@@ -834,12 +835,19 @@
 		if ( !vdirent->d_reclen ) {
 			printk("CODA: Invalid directory, cfino: %ld\n", 
 			       filp->f_dentry->d_inode->i_ino);
+			result = -EINVAL;
 			break;
 		}
                 pos += (unsigned int) vdirent->d_reclen;
 		i++;
         } 
 
+       if ( i >= 1024 ) {
+               printk("Repeating too much in readdir %ld\n", 
+                      filp->f_dentry->d_inode->i_ino);
+               result = -EINVAL;
+       }
+
 exit:
         CODA_FREE(buff, DIR_BUFSIZE);
         return result;
@@ -853,18 +861,35 @@
 	struct coda_inode_info *cii;
 	ENTRY;
 
-	if (inode) {
-		if (is_bad_inode(inode))
-			return 0;
-		cii = ITOC(de->d_inode);
-		if (cii->c_flags & C_PURGE) 
-			valid = 0;
-		if (cii->c_flags & C_FLUSH) {
-			coda_flag_inode_children(inode, C_FLUSH);
-			valid = 0;
-		}
+	if (!inode)
+		return 1;
+
+	cii = ITOC(de->d_inode);
+	if (coda_isroot(inode))
+		return 1;
+	if (is_bad_inode(inode))
+		return 0;
+
+	if (! (cii->c_flags & (C_PURGE | C_FLUSH)) )
+		return valid;
+
+	shrink_dcache_parent(de);
+
+	if (de->d_count > 1) {
+		/* pretend it's valid, but don't change the flags */
+		CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n",
+		       de->d_inode->i_ino, coda_f2s(&cii->c_fid));
+		return 1;
 	}
-	return valid ||  coda_isroot(de->d_inode);
+
+	/* propagate for a flush */
+	if (cii->c_flags & C_FLUSH) 
+		coda_flag_inode_children(inode, C_FLUSH);
+
+	/* clear the flags. */
+	cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
+
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/dcache.c linux/fs/dcache.c
--- v2.2.0-pre9/linux/fs/dcache.c	Tue Jan 19 11:32:52 1999
+++ linux/fs/dcache.c	Mon Jan 25 11:29:49 1999
@@ -480,17 +480,6 @@
 	char * str;
 	struct dentry *dentry;
 
-	/*
-	 * Prune the dcache if there are too many unused dentries.
-	 */
-	if (dentry_stat.nr_unused > 3*(nr_inodes >> 1)) {
-#ifdef DCACHE_DEBUG
-printk("d_alloc: %d unused, pruning dcache\n", dentry_stat.nr_unused);
-#endif
-		prune_dcache(8);
-		free_inode_memory(8);
-	}
-
 	dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); 
 	if (!dentry)
 		return NULL;
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/inode.c linux/fs/inode.c
--- v2.2.0-pre9/linux/fs/inode.c	Thu Jan  7 15:11:38 1999
+++ linux/fs/inode.c	Mon Jan 25 14:58:38 1999
@@ -354,36 +354,28 @@
 	return found;
 }
 
+static void shrink_dentry_inodes(int goal)
+{
+	int found;
+
+	spin_unlock(&inode_lock);
+	found = select_dcache(goal, 0);
+	if (found < goal)
+		found = goal;
+	prune_dcache(found);
+	spin_lock(&inode_lock);
+}
+
 /*
  * Searches the inodes list for freeable inodes,
- * possibly shrinking the dcache before or after.
+ * shrinking the dcache before (and possible after,
+ * if we're low)
  */
 static void try_to_free_inodes(int goal)
 {
-	int retry = 1, found;
-
-	/*
-	 * Check whether to preshrink the dcache ...
-	 */
-	if (inodes_stat.preshrink)
-		goto preshrink;
-
-	retry = 0;
-	do {
-		if (free_inodes(goal))
-			break;
-		/*
-		 * If we didn't free any inodes, do a limited
-		 * pruning of the dcache to help the next time.
-		 */
-	preshrink:
-		spin_unlock(&inode_lock);
-		found = select_dcache(goal, 0);
-		if (found < goal)
-			found = goal;
-		prune_dcache(found);
-		spin_lock(&inode_lock);
-	} while (retry--);
+	shrink_dentry_inodes(goal);
+	if (!free_inodes(goal))
+		shrink_dentry_inodes(goal);
 }
 
 /*
@@ -408,6 +400,21 @@
 {
 	struct inode * inode;
 
+	/*
+	 * Check whether to restock the unused list.
+	 */
+	if (inodes_stat.preshrink) {
+		struct list_head *tmp;
+		try_to_free_inodes(8);
+		tmp = inode_unused.next;
+		if (tmp != &inode_unused) {
+			inodes_stat.nr_free_inodes--;
+			list_del(tmp);
+			inode = list_entry(tmp, struct inode, i_list);
+			return inode;
+		}
+	}
+		
 	spin_unlock(&inode_lock);
 	inode = (struct inode *)__get_free_page(GFP_KERNEL);
 	if (inode) {
@@ -512,6 +519,12 @@
 	sb->s_op->read_inode(inode);
 }
 
+/*
+ * This is called by things like the networking layer
+ * etc that want to get an inode without any inode
+ * number, or filesystems that allocate new inodes with
+ * no pre-existing information.
+ */
 struct inode * get_empty_inode(void)
 {
 	static unsigned long last_ino = 0;
@@ -519,11 +532,6 @@
 	struct list_head * tmp;
 
 	spin_lock(&inode_lock);
-	/*
-	 * Check whether to restock the unused list.
-	 */
-	if (inodes_stat.nr_free_inodes < 16)
-		try_to_free_inodes(8);
 	tmp = inode_unused.next;
 	if (tmp != &inode_unused) {
 		list_del(tmp);
@@ -629,25 +637,18 @@
 	struct inode * inode;
 
 	spin_lock(&inode_lock);
-	if (!inodes_stat.nr_free_inodes)
-		goto restock;
-search:
 	inode = find_inode(sb, ino, head);
-	if (!inode) {
-		return get_new_inode(sb, ino, head);
+	if (inode) {
+		spin_unlock(&inode_lock);
+		wait_on_inode(inode);
+		return inode;
 	}
-	spin_unlock(&inode_lock);
-	wait_on_inode(inode);
-	return inode;
-
 	/*
-	 * We restock the freelist before calling find,
-	 * in order to avoid repeating the search.
-	 * (The unused list usually won't be empty.)
+	 * get_new_inode() will do the right thing, releasing
+	 * the inode lock and re-trying the search in case it
+	 * had to block at any point.
 	 */
-restock:
-	try_to_free_inodes(8);
-	goto search;
+	return get_new_inode(sb, ino, head);
 }
 
 void insert_inode_hash(struct inode *inode)
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/namei.c linux/fs/namei.c
--- v2.2.0-pre9/linux/fs/namei.c	Wed Jan 20 23:14:06 1999
+++ linux/fs/namei.c	Sun Jan 24 21:48:39 1999
@@ -678,9 +678,12 @@
 	if (flag & O_CREAT) {
 		struct dentry *dir;
 
-		error = -EEXIST;
-		if (dentry->d_inode && (flag & O_EXCL))
+		if (dentry->d_inode) {
+			if (!(flag & O_EXCL))
+				goto nocreate;
+			error = -EEXIST;
 			goto exit;
+		}
 
 		dir = lock_parent(dentry);
 		if (!check_parent(dir, dentry)) {
@@ -723,6 +726,7 @@
 			goto exit;
 	}
 
+nocreate:
 	error = -ENOENT;
 	inode = dentry->d_inode;
 	if (!inode)
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/nfsd/nfscache.c linux/fs/nfsd/nfscache.c
--- v2.2.0-pre9/linux/fs/nfsd/nfscache.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/nfsd/nfscache.c	Sun Jan 24 21:54:35 1999
@@ -268,8 +268,10 @@
 	if (!(rp = rqstp->rq_cacherep) || cache_disabled)
 		return;
 
+	len = resp->len - (statp - resp->base);
+	
 	/* Don't cache excessive amounts of data and XDR failures */
-	if (!statp || (len = resp->buf - statp) > (256 >> 2)) {
+	if (!statp || len > (256 >> 2)) {
 		rp->c_state = RC_UNUSED;
 		return;
 	}
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.2.0-pre9/linux/fs/proc/array.c	Wed Jan 20 23:14:06 1999
+++ linux/fs/proc/array.c	Mon Jan 25 10:23:31 1999
@@ -14,7 +14,7 @@
  *                      EVERY character on the current page.
  *                      <middelin@polyware.iaf.nl>
  *
- * Danny ter Haar    :	added cpuinfo 
+ * Danny ter Haar    :	added cpuinfo
  *			<dth@cistron.nl>
  *
  * Alessandro Rubini :  profile extension.
@@ -33,13 +33,13 @@
  *                      and /proc/<pid>/cpu extension
  *                      <forissier@isia.cma.fr>
  *			- Incorporation and non-SMP safe operation
- *			of forissier patch in 2.1.78 by 
+ *			of forissier patch in 2.1.78 by
  *			Hans Marcus <crowbar@concepts.nl>
  *
  * aeb@cwi.nl        :  /proc/partitions
  *
  *
- * Alan Cox	     :  security fixes. 
+ * Alan Cox	     :  security fixes.
  *			<Alan.Cox@linux.org>
  *
  * Andi Kleen	     :  Race Fixes. 	
@@ -142,7 +142,7 @@
 };
 
 struct inode_operations proc_kcore_inode_operations = {
-	&proc_kcore_operations, 
+	&proc_kcore_operations,
 };
 
 /*
@@ -198,7 +198,7 @@
 			return -EINVAL;
 	}
 #endif
-  
+
 	memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer));
 	return count;
 }
@@ -210,7 +210,7 @@
 };
 
 struct inode_operations proc_profile_inode_operations = {
-	&proc_profile_operations, 
+	&proc_profile_operations,
 };
 
 
@@ -388,29 +388,29 @@
 	return sprintf(buffer, "%s\n", saved_command_line);
 }
 
-/* 
+/*
  * Caller must release_mm the mm_struct later.
- * You don't get any access to init_mm. 
- */ 
-static struct mm_struct *get_mm_and_lock(int pid) 
-{ 
-	struct mm_struct *mm = NULL;  
-	struct task_struct *tsk; 
+ * You don't get any access to init_mm.
+ */
+static struct mm_struct *get_mm_and_lock(int pid)
+{
+	struct mm_struct *mm = NULL;
+	struct task_struct *tsk;
 
-	read_lock(&tasklist_lock); 
-	tsk = find_task_by_pid(pid); 
+	read_lock(&tasklist_lock);
+	tsk = find_task_by_pid(pid);
 	if (tsk && tsk->mm && tsk->mm != &init_mm)
-		mmget(mm = tsk->mm);  
+		mmget(mm = tsk->mm);
 	read_unlock(&tasklist_lock);
-	if (mm != NULL) 
-		down(&mm->mmap_sem); 
-	return mm; 
+	if (mm != NULL)
+		down(&mm->mmap_sem);
+	return mm;
 }
 
 static void release_mm(struct mm_struct *mm)
 {
-	up(&mm->mmap_sem); 
-	mmput(mm); 
+	up(&mm->mmap_sem);
+	mmput(mm);
 }
 
 static unsigned long get_phys_addr(struct mm_struct *mm, unsigned long ptr)
@@ -423,7 +423,7 @@
 		return 0;
 	/* Check for NULL pgd .. shouldn't happen! */
 	if (!mm->pgd) {
-		printk(KERN_DEBUG "missing pgd for mm %p\n", mm); 
+		printk(KERN_DEBUG "missing pgd for mm %p\n", mm);
 		return 0;
 	}
 
@@ -480,12 +480,12 @@
 
 static int get_env(int pid, char * buffer)
 {
-	struct mm_struct *mm; 
-	int res = 0; 
+	struct mm_struct *mm;
+	int res = 0;
 
-	mm = get_mm_and_lock(pid); 
-	if (mm) {  
-		res = get_array(mm, mm->env_start, mm->env_end, buffer); 
+	mm = get_mm_and_lock(pid);
+	if (mm) {
+		res = get_array(mm, mm->env_start, mm->env_end, buffer);
 		release_mm(mm);
 	}
 	return res;
@@ -493,14 +493,14 @@
 
 static int get_arg(int pid, char * buffer)
 {
-	struct mm_struct *mm; 
-	int res = 0; 
+	struct mm_struct *mm;
+	int res = 0;
 
-	mm = get_mm_and_lock(pid); 
+	mm = get_mm_and_lock(pid);
 	if (mm) {
-		res = get_array(mm, mm->arg_start, mm->arg_end, buffer); 
-		release_mm(mm); 
-	} 
+		res = get_array(mm, mm->arg_start, mm->arg_end, buffer);
+		release_mm(mm);
+	}
 	return res;
 }
 
@@ -754,14 +754,14 @@
 {
 	struct mm_struct * mm = p->mm;
 
-	if (!mm) 
+	if (!mm)
 		return buffer;
 	if (mm != &init_mm) {
 		struct vm_area_struct * vma;
 		unsigned long data = 0, stack = 0;
 		unsigned long exec = 0, lib = 0;
 
-		down(&mm->mmap_sem); 
+		down(&mm->mmap_sem);
 		for (vma = mm->mmap; vma; vma = vma->vm_next) {
 			unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
 			if (!vma->vm_file) {
@@ -779,7 +779,7 @@
 				lib += len;
 			}
 		}	
-		up(&mm->mmap_sem); 
+		up(&mm->mmap_sem);
 		buffer += sprintf(buffer,
 			"VmSize:\t%8lu kB\n"
 			"VmLck:\t%8lu kB\n"
@@ -849,35 +849,31 @@
 			    cap_t(p->cap_effective));
 }
 
-static struct task_struct *grab_task(int pid, struct task_struct *dst) 
+static struct task_struct *grab_task(int pid)
 {
-	struct task_struct *tsk = current; 
-	if (pid != tsk->pid) { 
+	struct task_struct *tsk = current;
+	if (pid != tsk->pid) {
 		read_lock(&tasklist_lock);
 		tsk = find_task_by_pid(pid);
-		if (tsk) { 
-			memcpy(dst, tsk, sizeof(struct task_struct));
-			tsk = dst;
-			if (tsk->mm && tsk->mm != &init_mm) 
-				mmget(tsk->mm);
-		}
+		if (tsk && tsk->mm && tsk->mm != &init_mm)
+			mmget(tsk->mm);
 		read_unlock(&tasklist_lock);
 	}	
-	return tsk; 
+	return tsk;
 }
 
 static void release_task(struct task_struct *tsk)
 {
 	if (tsk != current && tsk->mm && tsk->mm != &init_mm)
-		mmput(tsk->mm); 
+		mmput(tsk->mm);
 }
 
 static int get_status(int pid, char * buffer)
 {
 	char * orig = buffer;
-	struct task_struct *tsk, mytask;
+	struct task_struct *tsk;
 	
-	tsk = grab_task(pid, &mytask); 
+	tsk = grab_task(pid);
 	if (!tsk)
 		return 0;
 	buffer = task_name(tsk, buffer);
@@ -885,13 +881,13 @@
 	buffer = task_mem(tsk, buffer);
 	buffer = task_sig(tsk, buffer);
 	buffer = task_cap(tsk, buffer);
-	release_task(tsk); 
+	release_task(tsk);
 	return buffer - orig;
 }
 
 static int get_stat(int pid, char * buffer)
 {
-	struct task_struct *tsk, mytask;
+	struct task_struct *tsk;
 	unsigned long vsize, eip, esp, wchan;
 	long priority, nice;
 	int tty_pgrp;
@@ -899,8 +895,8 @@
 	char state;
 	int res;
 
-	tsk = grab_task(pid, &mytask);  
-	if (!tsk) 
+	tsk = grab_task(pid);
+	if (!tsk)
 		return 0;
 	state = *get_task_state(tsk);
 	vsize = eip = esp = 0;
@@ -908,10 +904,10 @@
 		struct vm_area_struct *vma;
 
 		down(&tsk->mm->mmap_sem);
-		for (vma = tsk->mm->mmap; vma; vma = vma->vm_next) {  
+		for (vma = tsk->mm->mmap; vma; vma = vma->vm_next) {
 			vsize += vma->vm_end - vma->vm_start;
 		}
-		up(&tsk->mm->mmap_sem); 
+		up(&tsk->mm->mmap_sem);
 		
 		eip = KSTK_EIP(tsk);
 		esp = KSTK_ESP(tsk);
@@ -1061,8 +1057,8 @@
 	int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
 	struct mm_struct *mm;
 
-	mm = get_mm_and_lock(pid); 
-	if (mm) { 
+	mm = get_mm_and_lock(pid);
+	if (mm) {
 		struct vm_area_struct * vma = mm->mmap;
 
 		while (vma) {
@@ -1084,7 +1080,7 @@
 				drs += pages;
 			vma = vma->vm_next;
 		}
-		release_mm(mm); 
+		release_mm(mm);
 	}
 	return sprintf(buffer,"%d %d %d %d %d %d %d\n",
 		       size, resident, share, trs, lrs, drs, dt);
@@ -1122,7 +1118,7 @@
 
 #define MAPS_LINE_MAX	MAPS_LINE_MAX8
 
-/* FIXME: this does not do proper mm locking */  
+/* FIXME: this does not do proper mm locking */
 static ssize_t read_maps (int pid, struct file * file, char * buf,
 			  size_t count, loff_t *ppos)
 {
@@ -1170,7 +1166,7 @@
 		int flags;
 		kdev_t dev;
 		unsigned long ino;
-		int maxlen = (sizeof(void*) == 4) ? 
+		int maxlen = (sizeof(void*) == 4) ?
 			MAPS_LINE_MAX4 :  MAPS_LINE_MAX8;
 		int len;
 
@@ -1254,10 +1250,10 @@
 #ifdef __SMP__
 static int get_pidcpu(int pid, char * buffer)
 {
-	struct task_struct * tsk, mytask;
+	struct task_struct * tsk;
 	int i, len;
 
-	tsk = grab_task(pid, &mytask);
+	tsk = grab_task(pid);
 	if (!tsk)
 		return 0;
 
@@ -1272,7 +1268,7 @@
 			tsk->per_cpu_utime[cpu_logical_map(i)],
 			tsk->per_cpu_stime[cpu_logical_map(i)]);
 
-	release_task(tsk); 
+	release_task(tsk);
 	return len;
 }
 #endif
@@ -1399,10 +1395,9 @@
 	read_lock(&tasklist_lock);
 	
 	/*
-	 *	Grab the lock, find the task, save the uid and 
+	 *	Grab the lock, find the task, save the uid and
 	 *	check it has an mm still (ie its not dead)
 	 */
-	 
 	p = find_task_by_pid(pid);
 	if(p)
 	{
diff -u --recursive --new-file v2.2.0-pre9/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.2.0-pre9/linux/fs/vfat/namei.c	Wed Jan 20 23:14:06 1999
+++ linux/fs/vfat/namei.c	Thu Jan 21 11:46:36 1999
@@ -1657,9 +1657,9 @@
 			drop_aliases(new_dentry);
 		}
 		res = vfat_remove_entry(new_dir,&sinfo,new_inode);
+		if (res)
+			goto rename_done;
 	}
-	if (res)
-		goto rename_done;
 
 	/* Serious lossage here. FAT uses braindead inode numbers scheme,
 	 * so we can't simply cannibalize the entry. It means that we have
diff -u --recursive --new-file v2.2.0-pre9/linux/include/asm-alpha/core_polaris.h linux/include/asm-alpha/core_polaris.h
--- v2.2.0-pre9/linux/include/asm-alpha/core_polaris.h	Wed Jan 13 15:00:43 1999
+++ linux/include/asm-alpha/core_polaris.h	Sun Jan 24 21:29:53 1999
@@ -27,6 +27,8 @@
 #define		POLARIS_DENSE_IO_BASE		(IDENT_ADDR + 0xf9fc000000)
 #define		POLARIS_DENSE_CONFIG_BASE	(IDENT_ADDR + 0xf9fe000000)
 
+#define		POLARIS_IACK_SC			POLARIS_IACK_BASE
+
 /* The Polaris command/status registers live in PCI Config space for
  * bus 0/device 0.  As such, they may be bytes, words, or doublewords.
  */
diff -u --recursive --new-file v2.2.0-pre9/linux/include/asm-alpha/jensen.h linux/include/asm-alpha/jensen.h
--- v2.2.0-pre9/linux/include/asm-alpha/jensen.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-alpha/jensen.h	Thu Jan 21 13:59:39 1999
@@ -7,6 +7,9 @@
  * Defines for the AlphaPC EISA IO and memory address space.
  */
 
+/* The Jensen is strange */
+#define AUX_IRQ (9)
+
 /*
  * NOTE! The memory operations do not set any memory barriers, as it's
  * not needed for cases like a frame buffer that is essentially memory-like.
diff -u --recursive --new-file v2.2.0-pre9/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v2.2.0-pre9/linux/include/asm-alpha/unistd.h	Wed Jan 13 15:00:43 1999
+++ linux/include/asm-alpha/unistd.h	Thu Jan 21 11:26:30 1999
@@ -307,6 +307,7 @@
 #define __NR_getcwd			367
 #define __NR_capget			368
 #define __NR_capset			369
+#define __NR_sendfile			370
 
 #if defined(__LIBRARY__) && defined(__GNUC__)
 
diff -u --recursive --new-file v2.2.0-pre9/linux/include/asm-i386/cobalt.h linux/include/asm-i386/cobalt.h
--- v2.2.0-pre9/linux/include/asm-i386/cobalt.h	Wed Jan 20 23:14:06 1999
+++ linux/include/asm-i386/cobalt.h	Sun Jan 24 21:55:04 1999
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #ifndef __I386_COBALT_H
 #define __I386_COBALT_H
 
diff -u --recursive --new-file v2.2.0-pre9/linux/include/asm-i386/i82489.h linux/include/asm-i386/i82489.h
--- v2.2.0-pre9/linux/include/asm-i386/i82489.h	Wed Jan 20 23:14:06 1999
+++ linux/include/asm-i386/i82489.h	Thu Jan 21 11:28:40 1999
@@ -14,12 +14,15 @@
 #define		APIC_TASKPRI	0x80
 #define			APIC_TPRI_MASK		0xFF
 #define		APIC_ARBPRI	0x90
+#define			APIC_ARBPRI_MASK	0xFF
 #define		APIC_PROCPRI	0xA0
 #define		APIC_EOI	0xB0
 #define			APIC_EIO_ACK		0x0		/* Write this to the EOI register */
 #define		APIC_RRR	0xC0
 #define		APIC_LDR	0xD0
+#define			APIC_LDR_MASK		(0xFF<<24)
 #define			GET_APIC_LOGICAL_ID(x)	(((x)>>24)&0xFF)
+#define			SET_APIC_LOGICAL_ID(x)	(((x)<<24))
 #define		APIC_DFR	0xE0
 #define			GET_APIC_DFR(x)		(((x)>>28)&0x0F)
 #define			SET_APIC_DFR(x)		((x)<<28)
@@ -36,7 +39,6 @@
 #define			APIC_ESR_RECVILL	0x00040
 #define			APIC_ESR_ILLREGA	0x00080
 #define		APIC_ICR	0x300
-#define			APIC_DEST_FIELD		0x00000
 #define			APIC_DEST_SELF		0x40000
 #define			APIC_DEST_ALLINC	0x80000
 #define			APIC_DEST_ALLBUT	0xC0000
diff -u --recursive --new-file v2.2.0-pre9/linux/include/asm-i386/lithium.h linux/include/asm-i386/lithium.h
--- v2.2.0-pre9/linux/include/asm-i386/lithium.h	Wed Jan 20 23:14:06 1999
+++ linux/include/asm-i386/lithium.h	Sun Jan 24 21:56:35 1999
@@ -1,6 +1,8 @@
 #ifndef __I386_LITHIUM_H
 #define __I386_LITHIUM_H
 
+#include <linux/config.h>
+
 /*
  * Lithium is the I/O ASIC on the SGI 320 and 540 Visual Workstations
  */
@@ -16,6 +18,7 @@
 #define	LI_PCI_BUSNUM	0x44			/* lo8: primary, hi8: sub */
 #define LI_PCI_INTEN    0x46
 
+#ifdef CONFIG_X86_VISWS_APIC
 /* More special purpose macros... */
 extern __inline void li_pcia_write16(unsigned long reg, unsigned short v)
 {
@@ -36,5 +39,7 @@
 {
 	return *((volatile unsigned short *)(LI_PCIB_VADDR+reg));
 }
+#endif
 
 #endif
+
diff -u --recursive --new-file v2.2.0-pre9/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v2.2.0-pre9/linux/include/asm-i386/smp.h	Wed Jan 20 23:14:06 1999
+++ linux/include/asm-i386/smp.h	Mon Jan 25 16:04:20 1999
@@ -163,7 +163,7 @@
  */
  
 extern int smp_found_config;
-extern int smp_scan_config(unsigned long, unsigned long);
+extern void init_smp_config(void);
 extern unsigned long smp_alloc_memory(unsigned long mem_base);
 extern unsigned char boot_cpu_id;
 extern unsigned long cpu_present_map;
diff -u --recursive --new-file v2.2.0-pre9/linux/include/linux/coda.h linux/include/linux/coda.h
--- v2.2.0-pre9/linux/include/linux/coda.h	Tue Dec 22 14:16:58 1998
+++ linux/include/linux/coda.h	Mon Jan 25 10:28:35 1999
@@ -1,8 +1,59 @@
+/* 
+   You may distribute this file under either of the two licenses that
+   follow at your discretion.
+*/
+
+/* BLURB lgpl
+
+                           Coda File System
+                              Release 5
+
+          Copyright (c) 1987-1999 Carnegie Mellon University
+                  Additional copyrights listed below
+
+This code is distributed "AS IS" without warranty of any kind under
+the terms of the GNU Library General Public Licence Version 2, as
+shown in the file LICENSE, or under the license shown below. The
+technical and financial contributors to Coda are listed in the file
+CREDITS.
+
+                        Additional copyrights 
+*/
+
+/*
+
+            Coda: an Experimental Distributed File System
+                             Release 4.0
+
+          Copyright (c) 1987-1999 Carnegie Mellon University
+                         All Rights Reserved
+
+Permission  to  use, copy, modify and distribute this software and its
+documentation is hereby granted,  provided  that  both  the  copyright
+notice  and  this  permission  notice  appear  in  all  copies  of the
+software, derivative works or  modified  versions,  and  any  portions
+thereof, and that both notices appear in supporting documentation, and
+that credit is given to Carnegie Mellon University  in  all  documents
+and publicity pertaining to direct or indirect use of this code or its
+derivatives.
+
+CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
+SOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
+FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
+DISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
+RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
+ANY DERIVATIVE WORK.
+
+Carnegie  Mellon  encourages  users  of  this  software  to return any
+improvements or extensions that  they  make,  and  to  grant  Carnegie
+Mellon the rights to redistribute these changes without encumbrance.
+*/
 
 /*
  *
  * Based on cfs.h from Mach, but revamped for increased simplicity.
- * Linux modifications by Peter Braam, Aug 1996
+ * Linux modifications by 
+ * Peter Braam, Aug 1996
  */
 
 #ifndef _CODA_HEADER_
@@ -178,8 +229,12 @@
 #ifndef _CODACRED_T_
 #define _CODACRED_T_
 struct coda_cred {
-    vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/
-    vgid_t cr_groupid,     cr_egid, cr_sgid, cr_fsgid; /* same for groups */
+	vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid;
+	vgid_t cr_groupid,     cr_egid, cr_sgid, cr_fsgid;
+#if   defined(CODA_SUPPORTS_SUPPLEMENTARY_GROUPS)
+	int    cr_nsupgps;
+	vgid_t cr_supgps[NGROUPS];
+#endif        /* defined(CODA_SUPPORTS_SUPPLEMENTARY_GROUPS) */
 };
 #endif 
 
diff -u --recursive --new-file v2.2.0-pre9/linux/include/linux/coda_linux.h linux/include/linux/coda_linux.h
--- v2.2.0-pre9/linux/include/linux/coda_linux.h	Tue Dec 22 14:16:58 1998
+++ linux/include/linux/coda_linux.h	Mon Jan 25 10:28:35 1999
@@ -46,6 +46,7 @@
 /* this file:  heloers */
 static __inline__ struct ViceFid *coda_i2f(struct inode *);
 char *coda_f2s(ViceFid *f);
+char *coda_f2s2(ViceFid *f);
 int coda_isroot(struct inode *i);
 int coda_fid_is_volroot(struct ViceFid *);
 int coda_fid_is_weird(struct ViceFid *fid);
diff -u --recursive --new-file v2.2.0-pre9/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.2.0-pre9/linux/include/linux/videodev.h	Tue Jan 19 11:32:53 1999
+++ linux/include/linux/videodev.h	Sun Jan 24 22:05:07 1999
@@ -2,6 +2,7 @@
 #define __LINUX_VIDEODEV_H
 
 #include <linux/types.h>
+#include <linux/version.h>
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.2.0-pre9/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.2.0-pre9/linux/include/net/irda/irda.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irda.h	Sun Jan 24 21:55:04 1999
@@ -25,6 +25,7 @@
 #ifndef IRDA_H
 #define IRDA_H
 
+#include <linux/config.h>
 #include <linux/skbuff.h>
 
 #ifndef TRUE
diff -u --recursive --new-file v2.2.0-pre9/linux/mm/filemap.c linux/mm/filemap.c
--- v2.2.0-pre9/linux/mm/filemap.c	Wed Jan 20 23:14:07 1999
+++ linux/mm/filemap.c	Mon Jan 25 10:47:11 1999
@@ -125,7 +125,7 @@
 	struct page * page;
 	int count;
 
-	count = (limit << 1) >> priority;
+	count = limit >> priority;
 
 	page = mem_map + clock;
 	do {
@@ -147,7 +147,6 @@
 			clock = page - mem_map;
 		}
 		
-		count--;
 		referenced = test_and_clear_bit(PG_referenced, &page->flags);
 
 		if (PageLocked(page))
@@ -159,6 +158,8 @@
 		/* We can't free pages unless there's just one user */
 		if (atomic_read(&page->count) != 1)
 			continue;
+
+		count--;
 
 		/*
 		 * Is it a page swap page? If so, we want to
diff -u --recursive --new-file v2.2.0-pre9/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.2.0-pre9/linux/mm/page_alloc.c	Wed Jan 20 23:14:07 1999
+++ linux/mm/page_alloc.c	Mon Jan 25 11:13:20 1999
@@ -155,12 +155,12 @@
 	change_bit((index) >> (1+(order)), (area)->map)
 #define CAN_DMA(x) (PageDMA(x))
 #define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT))
-#define RMQUEUE(order, dma) \
+#define RMQUEUE(order, gfp_mask) \
 do { struct free_area_struct * area = free_area+order; \
      unsigned long new_order = order; \
 	do { struct page *prev = memory_head(area), *ret = prev->next; \
 		while (memory_head(area) != ret) { \
-			if (!dma || CAN_DMA(ret)) { \
+			if (!(gfp_mask & __GFP_DMA) || CAN_DMA(ret)) { \
 				unsigned long map_nr; \
 				(prev->next = ret->next)->prev = prev; \
 				map_nr = ret - mem_map; \
@@ -198,45 +198,45 @@
 	if (order >= NR_MEM_LISTS)
 		goto nopage;
 
-	if (gfp_mask & __GFP_WAIT) {
-		if (in_interrupt()) {
-			static int count = 0;
-			if (++count < 5) {
-				printk("gfp called nonatomically from interrupt %p\n",
-					__builtin_return_address(0));
-			}
-			goto nopage;
+#ifdef ATOMIC_MEMORY_DEBUGGING
+	if ((gfp_mask & __GFP_WAIT) && in_interrupt()) {
+		static int count = 0;
+		if (++count < 5) {
+			printk("gfp called nonatomically from interrupt %p\n",
+				__builtin_return_address(0));
 		}
+		goto nopage;
+	}
+#endif
 
-		/*
-		 * If this is a recursive call, we'd better
-		 * do our best to just allocate things without
-		 * further thought.
-		 */
-		if (!(current->flags & PF_MEMALLOC)) {
-			int freed;
-
-			if (nr_free_pages > freepages.min) {
-				if (!low_on_memory)
-					goto ok_to_allocate;
-				if (nr_free_pages >= freepages.high) {
-					low_on_memory = 0;
-					goto ok_to_allocate;
-				}
+	/*
+	 * If this is a recursive call, we'd better
+	 * do our best to just allocate things without
+	 * further thought.
+	 */
+	if (!(current->flags & PF_MEMALLOC)) {
+		int freed;
+
+		if (nr_free_pages > freepages.min) {
+			if (!low_on_memory)
+				goto ok_to_allocate;
+			if (nr_free_pages >= freepages.high) {
+				low_on_memory = 0;
+				goto ok_to_allocate;
 			}
+		}
 
-			low_on_memory = 1;
-			current->flags |= PF_MEMALLOC;
-			freed = try_to_free_pages(gfp_mask);
-			current->flags &= ~PF_MEMALLOC;
+		low_on_memory = 1;
+		current->flags |= PF_MEMALLOC;
+		freed = try_to_free_pages(gfp_mask);
+		current->flags &= ~PF_MEMALLOC;
 
-			if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
-				goto nopage;
-		}
+		if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
+			goto nopage;
 	}
 ok_to_allocate:
 	spin_lock_irqsave(&page_alloc_lock, flags);
-	RMQUEUE(order, (gfp_mask & GFP_DMA));
+	RMQUEUE(order, gfp_mask);
 	spin_unlock_irqrestore(&page_alloc_lock, flags);
 
 	/*
diff -u --recursive --new-file v2.2.0-pre9/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.2.0-pre9/linux/mm/vmscan.c	Wed Jan 20 23:14:07 1999
+++ linux/mm/vmscan.c	Mon Jan 25 11:08:56 1999
@@ -368,6 +368,54 @@
 }
 
 /*
+ * We need to make the locks finer granularity, but right
+ * now we need this so that we can do page allocations
+ * without holding the kernel lock etc.
+ *
+ * We want to try to free "count" pages, and we need to 
+ * cluster them so that we get good swap-out behaviour. See
+ * the "free_memory()" macro for details.
+ */
+static int do_try_to_free_pages(unsigned int gfp_mask)
+{
+	int priority;
+	int count = SWAP_CLUSTER_MAX;
+
+	lock_kernel();
+
+	/* Always trim SLAB caches when memory gets low. */
+	kmem_cache_reap(gfp_mask);
+
+	priority = 6;
+	do {
+		while (shrink_mmap(priority, gfp_mask)) {
+			if (!--count)
+				goto done;
+		}
+
+		/* Try to get rid of some shared memory pages.. */
+		if (gfp_mask & __GFP_IO) {
+			while (shm_swap(priority, gfp_mask)) {
+				if (!--count)
+					goto done;
+			}
+		}
+
+		/* Then, try to page stuff out.. */
+		while (swap_out(priority, gfp_mask)) {
+			if (!--count)
+				goto done;
+		}
+
+		shrink_dcache_memory(priority, gfp_mask);
+	} while (--priority >= 0);
+done:
+	unlock_kernel();
+
+	return priority >= 0;
+}
+
+/*
  * Before we start the kernel thread, print out the 
  * kswapd initialization message (otherwise the init message 
  * may be printed in the middle of another driver's init 
@@ -388,6 +436,8 @@
        printk ("Starting kswapd v%.*s\n", i, s);
 }
 
+static struct task_struct *kswapd_process;
+
 /*
  * The background pageout daemon, started as a kernel thread
  * from the init process. 
@@ -404,10 +454,13 @@
  */
 int kswapd(void *unused)
 {
-	current->session = 1;
-	current->pgrp = 1;
-	strcpy(current->comm, "kswapd");
-	sigfillset(&current->blocked);
+	struct task_struct *tsk = current;
+
+	kswapd_process = tsk;
+	tsk->session = 1;
+	tsk->pgrp = 1;
+	strcpy(tsk->comm, "kswapd");
+	sigfillset(&tsk->blocked);
 	
 	/*
 	 * Tell the memory management that we're a "memory allocator",
@@ -421,78 +474,52 @@
 	 * us from recursively trying to free more memory as we're
 	 * trying to free the first piece of memory in the first place).
 	 */
-	current->flags |= PF_MEMALLOC;
+	tsk->flags |= PF_MEMALLOC;
 
 	while (1) {
-		int tmo;
-
 		/*
 		 * Wake up once a second to see if we need to make
-		 * more memory available. When we get into a low
-		 * memory situation, we start waking up more often.
+		 * more memory available.
 		 *
-		 * We consider "freepages.low" to be low on memory,
-		 * but we also try to be aggressive if other processes
-		 * are low on memory and would otherwise block when
-		 * calling __get_free_page().
+		 * If we actually get into a low-memory situation,
+		 * the processes needing more memory will wake us
+		 * up on a more timely basis.
 		 */
-		tmo = HZ;
-		if (nr_free_pages < freepages.high) {
-			if (nr_free_pages < freepages.low || low_on_memory) {
-				if (try_to_free_pages(GFP_KSWAPD))
-					tmo = (HZ+9)/10;
-			}
-		}
+		do {
+			if (nr_free_pages >= freepages.high)
+				break;
+
+			if (!do_try_to_free_pages(GFP_KSWAPD))
+				break;
+		} while (!tsk->need_resched);
 		run_task_queue(&tq_disk);
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(tmo);
+		tsk->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(HZ);
 	}
 }
 
 /*
- * We need to make the locks finer granularity, but right
- * now we need this so that we can do page allocations
- * without holding the kernel lock etc.
+ * Called by non-kswapd processes when they want more
+ * memory.
  *
- * We want to try to free "count" pages, and we need to 
- * cluster them so that we get good swap-out behaviour. See
- * the "free_memory()" macro for details.
+ * In a perfect world, this should just wake up kswapd
+ * and return. We don't actually want to swap stuff out
+ * from user processes, because the locking issues are
+ * nasty to the extreme (file write locks, and MM locking)
+ *
+ * One option might be to let kswapd do all the page-out
+ * and VM page table scanning that needs locking, and this
+ * process thread could do just the mmap shrink stage that
+ * can be done by just dropping cached pages without having
+ * any deadlock issues.
  */
 int try_to_free_pages(unsigned int gfp_mask)
 {
-	int priority;
-	int count = SWAP_CLUSTER_MAX;
-
-	lock_kernel();
-
-	/* Always trim SLAB caches when memory gets low. */
-	kmem_cache_reap(gfp_mask);
+	int retval = 1;
 
-	priority = 6;
-	do {
-		while (shrink_mmap(priority, gfp_mask)) {
-			if (!--count)
-				goto done;
-		}
-
-		/* Try to get rid of some shared memory pages.. */
-		if (gfp_mask & __GFP_IO) {
-			while (shm_swap(priority, gfp_mask)) {
-				if (!--count)
-					goto done;
-			}
-		}
-
-		/* Then, try to page stuff out.. */
-		while (swap_out(priority, gfp_mask)) {
-			if (!--count)
-				goto done;
-		}
-
-		shrink_dcache_memory(priority, gfp_mask);
-	} while (--priority >= 0);
-done:
-	unlock_kernel();
-
-	return priority >= 0;
+	wake_up_process(kswapd_process);
+	if (gfp_mask & __GFP_WAIT)
+		retval = do_try_to_free_pages(gfp_mask);
+	return retval;
 }
+	
diff -u --recursive --new-file v2.2.0-pre9/linux/net/decnet/README linux/net/decnet/README
--- v2.2.0-pre9/linux/net/decnet/README	Tue Dec 22 14:16:59 1998
+++ linux/net/decnet/README	Sun Jan 24 22:05:07 1999
@@ -4,9 +4,12 @@
 For information on the Linux DECnet Project and the latest progress,
 look at the project home page:
 
-http://www-sigproc.eng.cam.ac.uk/~sjw44/
+http://www.sucs.swan.ac.uk/~rohan/DECnet/
 
 To contribute either mail <SteveW@ACM.org> or post on one of the Linux
-mailing lists (either linux-net or netdev).
+mailing lists (either linux-net or netdev). DECnet for Linux will not
+be distributed as part of the 2.2.xx kernel series. It is available as a
+patch from the above site. Expect DECnet to arrive as part of the standard 
+kernel distribution early in the 2.3.xx series.
 
 Steve Whitehouse <SteveW@ACM.org>
diff -u --recursive --new-file v2.2.0-pre9/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
--- v2.2.0-pre9/linux/net/ipv4/fib_semantics.c	Mon Oct  5 13:13:48 1998
+++ linux/net/ipv4/fib_semantics.c	Sun Jan 24 21:54:35 1999
@@ -984,7 +984,7 @@
 			      flags, 0, 0, 0,
 			      mask, 0, 0, 0);
 	}
-	memset(buffer+len, 0, 127-len);
+	memset(buffer+len, ' ', 127-len);
 	buffer[127] = '\n';
 }
 
diff -u --recursive --new-file v2.2.0-pre9/linux/net/ipv4/ip_masq_mfw.c linux/net/ipv4/ip_masq_mfw.c
--- v2.2.0-pre9/linux/net/ipv4/ip_masq_mfw.c	Thu Jan  7 15:11:41 1999
+++ linux/net/ipv4/ip_masq_mfw.c	Mon Jan 25 10:10:58 1999
@@ -79,7 +79,7 @@
 };
 
 
-static struct semaphore mfw_sema;
+static struct semaphore mfw_sema = MUTEX;
 #ifdef __SMP__
 static rwlock_t mfw_lock = RW_LOCK_UNLOCKED;
 #endif
@@ -748,7 +748,6 @@
 
 __initfunc(int ip_mfw_init(void))
 {
-	sema_init(&mfw_sema, 1);
 	return register_ip_masq_mod ((mmod_self=&mfw_mod));
 }
 
diff -u --recursive --new-file v2.2.0-pre9/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.2.0-pre9/linux/net/ipv4/tcp_input.c	Wed Jan 20 23:14:07 1999
+++ linux/net/ipv4/tcp_input.c	Fri Jan 22 09:16:09 1999
@@ -1691,7 +1691,7 @@
 		do {	net_statistics.OfoPruned += skb->len; 
 			kfree_skb(skb);
 			skb = __skb_dequeue_tail(&tp->out_of_order_queue);
-		} while((skb = __skb_dequeue_tail(&tp->out_of_order_queue)) != NULL);
+		} while(skb != NULL);
 
 		/* Reset SACK state.  A conforming SACK implementation will
 		 * do the same at a timeout based retransmit.  When a connection
diff -u --recursive --new-file v2.2.0-pre9/linux/net/irda/irlpt/irlpt_common.c linux/net/irda/irlpt/irlpt_common.c
--- v2.2.0-pre9/linux/net/irda/irlpt/irlpt_common.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlpt/irlpt_common.c	Sun Jan 24 21:55:05 1999
@@ -24,7 +24,6 @@
  *
  ********************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h> 
 
 #include <asm/segment.h>
diff -u --recursive --new-file v2.2.0-pre9/linux/net/irda/irlpt/irlpt_srvr_fsm.c linux/net/irda/irlpt/irlpt_srvr_fsm.c
--- v2.2.0-pre9/linux/net/irda/irlpt/irlpt_srvr_fsm.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlpt/irlpt_srvr_fsm.c	Sun Jan 24 21:55:05 1999
@@ -17,8 +17,6 @@
  *
  ********************************************************************/
 
-#include <linux/config.h>
-
 #include <net/irda/iriap.h>
 #include <net/irda/irlmp.h>
 #include <net/irda/irttp.h>
diff -u --recursive --new-file v2.2.0-pre9/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c
--- v2.2.0-pre9/linux/net/irda/irsysctl.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irsysctl.c	Sun Jan 24 21:55:05 1999
@@ -22,6 +22,7 @@
  *     
  ********************************************************************/
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/ctype.h>
 #include <linux/sysctl.h>
