diff -u --recursive --new-file v2.3.24/linux/CREDITS linux/CREDITS
--- v2.3.24/linux/CREDITS	Fri Oct 22 13:21:43 1999
+++ linux/CREDITS	Mon Nov  1 10:31:34 1999
@@ -31,6 +31,12 @@
 S: University of Limerick
 S: Ireland
 
+N: Tigran A. Aivazian
+E: tigran@ocston.org
+W: http://www.ocston.org/~tigran
+D: BFS filesystem
+S: United Kingdom
+
 N: Werner Almesberger
 E: werner.almesberger@lrc.di.epfl.ch
 D: dosfs, LILO, some fd features, various other hacks here and there
@@ -280,6 +286,10 @@
 D: Configuration help text support
 D: Linux CD and Support Giveaway List
 
+N: Erik Inge Bolsų
+E: knan@mo.himolde.no
+D: Misc kernel hacks
+
 N: Zoltan Boszormenyi
 E: zboszor@mol.hu
 D: MTRR emulation with Cyrix style ARR registers
@@ -1772,8 +1782,8 @@
 S: Germany
 
 N: Stephen Rothwell
-E: Stephen.Rothwell@canb.auug.org.au
-W: http://www.canb.auug.org.au/~sfr
+E: sfr@linuxcare.com
+W: http://linuxcare.com.au/sfr
 P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B  91 88 FA D9 C8 40 AA 02
 D: Boot/setup/build work for setup > 2K
 D: Author, APM driver
@@ -2207,9 +2217,10 @@
 N: Tim Waugh
 E: tim@cyberelk.demon.co.uk
 D: Co-architect of the parallel-port sharing system
-S: 4 Fox Close
-S: Bishopstoke
-S: SO50 8NB
+S: 34 Bladon Close
+S: GUILDFORD
+S: Surrey
+S: GU1 1TY
 S: United Kingdom
 
 N: Juergen Weigert
diff -u --recursive --new-file v2.3.24/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.24/linux/Documentation/Configure.help	Wed Oct 27 16:34:12 1999
+++ linux/Documentation/Configure.help	Fri Oct 29 13:19:49 1999
@@ -7970,6 +7970,21 @@
   compiled as a module, and so this could be dangerous. Most everyone
   wants to say Y here.
 
+SCO UnixWare BFS Support
+CONFIG_BFS_FS
+  Boot Filesystem (BFS) is a filesystem used under SCO UnixWare to
+  allow bootloader access the kernel image and other important files
+  during the boot process. It is usually mounted under /stand and
+  corresponds to the slice marked as "STAND" in the UnixWare
+  partition. This is useful if you want to access files on your /stand
+  slice from Linux. If you don't know what it is, say N.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called bfs.o. Note that the filesystem of your root partition (the
+  one containing the directory /) cannot be compiled as a module.
+ 
 ISO 9660 CDROM filesystem support
 CONFIG_ISO9660_FS
   This is the standard filesystem used on CDROMs. It was previously
@@ -9881,7 +9896,7 @@
   lead to all sorts of problems.
 
   You can safely say Y even if your machine doesn't have MTRRs, you'll
-  just add about 3k to your kernel.
+  just add about 9K to your kernel.
 
   See Documentation/mtrr.txt for more information.
 
@@ -9938,9 +9953,15 @@
   APM is a BIOS specification for saving power using several different
   techniques. This is mostly useful for battery powered laptops with
   APM compliant BIOSes. If you say Y here, the system time will be
-  reset after a USER RESUME operation, the /proc/apm device will
-  provide battery status information, and user-space programs will
-  receive notification of APM "events" (e.g., battery status change).
+  reset after a RESUME operation, the /proc/apm device will provide
+  battery status information, and user-space programs will receive
+  notification of APM "events" (e.g. battery status change).
+
+  If you select "Y" here, you can disable actual use of the APM
+  BIOS by passing the "apm=off" option to the kernel at boot time.
+
+  Note that the APM support is almost completely disabled for
+  machines with more than one CPU.
 
   Supporting software is available; for more information, read the
   Battery Powered Linux mini-HOWTO, available from
@@ -9953,9 +9974,7 @@
   This driver does not support the TI 4000M TravelMate and the ACER
   486/DX4/75 because they don't have compliant BIOSes. Many "green"
   desktop machines also don't have compliant BIOSes, and this driver
-  will cause those machines to panic during the boot phase (typically,
-  these machines are using a data segment of 0040, which is reserved
-  for the Linux kernel). 
+  may cause those machines to panic during the boot phase.
 
   If you are running Linux on a laptop, you may also want to read the
   Linux Laptop home page on the WWW at
@@ -13030,7 +13049,7 @@
 # LocalWords:  EBSA chattr RiscOS Winmodem AGP Atomwide DUALSP pcsp robinson CT
 # LocalWords:  SGALAXY Waverider DSPxxx TRXPRO AudioTrix OSWF MOT CFB DSY kbps
 # LocalWords:  tuwien kkudielk LVD mega lun MAXTAGS Gbps arcnet Olicom SKTR SNA
-# LocalWords:  SysKonnect sktr sna etherboot ufs NetBEUI MultiSound MSNDCLAS GX
+# LocalWords:  SysKonnect tms380tr sna etherboot ufs NetBEUI MultiSound MSNDCLAS GX
 # LocalWords:  MSNDINIT MSNDPERM MSNDPIN PNDSPINI PNDSPERM Ensoniq's RetinaZ SS
 # LocalWords:  AudioPCI lspci SonicVibes sonicvibes SPARCs roadrunner CLgen UPA
 # LocalWords:  swansea shtml Zoltrix zoltrix BINUTILS EGCS binutils VIDC DACs
diff -u --recursive --new-file v2.3.24/linux/Documentation/filesystems/00-INDEX linux/Documentation/filesystems/00-INDEX
--- v2.3.24/linux/Documentation/filesystems/00-INDEX	Tue Sep  7 12:14:05 1999
+++ linux/Documentation/filesystems/00-INDEX	Thu Oct 28 14:45:16 1999
@@ -4,6 +4,8 @@
 	- info and mount options for the Acorn Advanced Disc Filing System.
 affs.txt
 	- info and mount options for the Amiga Fast File System.
+bfs.txt
+	- info for the SCO UnixWare Boot Filesystem (BFS).
 coda.txt
 	- description of the CODA filesystem.
 fat_cvf.txt
diff -u --recursive --new-file v2.3.24/linux/Documentation/filesystems/bfs.txt linux/Documentation/filesystems/bfs.txt
--- v2.3.24/linux/Documentation/filesystems/bfs.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/filesystems/bfs.txt	Thu Oct 28 14:45:16 1999
@@ -0,0 +1,54 @@
+The BFS filesystem is used on SCO UnixWare machines for /stand slice.
+There are no special mount options supported by bfs at this time. 
+You can mount it only read-only at this stage. Even if you attempt to
+mount it read-write it will be automatically mounted read-only, unless
+you have enabled "BFS write support" when configuring the kernel.
+
+In order to access /stand partition under Linux you obviously need to
+know the partition number and the kernel must support UnixWare disk slices
+(CONFIG_UNIXWARE_DISKLABEL config option). However BFS support does not
+depend on having UnixWare disklabel support because one can also mount
+BFS filesystem via loopback:
+
+# losetup /dev/loop0 stand.img
+# mount -t bfs /dev/loop0 /mnt/stand
+
+where stand.img is a file containing the image of BFS filesystem. 
+When you have finished using it and umounted you need to also deallocate
+/dev/loop0 device by:
+
+# losetup -d /dev/loop0
+
+You can simplify mounting by just typing:
+
+# mount -t bfs -o loop stand.img /mnt/stand
+
+this will allocate the first available loopback device (and load loop.o 
+kernel module if necessary) automatically. Beware that umount will not
+deallocate /dev/loopN device if /etc/mtab file on your system is a
+symbolic link to /proc/mounts. You will need to do it manually using
+"-d" switch of losetup(8). Read losetup(8) manpage for more info.
+
+To create the BFS image under UnixWare you need to find out first which
+slice contains it. The command prtvtoc(1M) is your friend:
+
+# prtvtoc /dev/rdsk/c0b0t0d0s0
+
+(assuming your root disk is on target=0, lun=0, bus=0, controller=0). Then you
+look for the slice with tag "STAND", which is usually slice 10. With this
+information you can use dd(1) to create the BFS image:
+
+# umount /stand
+# dd if=/dev/rdsk/c0b0t0d0sa of=stand.img bs=512
+
+Just in case, you can verify that you have done the right thing by checking
+the magic number:
+
+# od -Ad -tx4 stand.img | more
+
+The first 4 bytes should be 0x1BADFACE.
+
+If you have any questions or suggestions regarding this BFS implementation
+please contact me:
+
+Tigran A. Aivazian <tigran@ocston.org>.
diff -u --recursive --new-file v2.3.24/linux/Documentation/kernel-parameters.txt linux/Documentation/kernel-parameters.txt
--- v2.3.24/linux/Documentation/kernel-parameters.txt	Sat Oct  9 11:47:50 1999
+++ linux/Documentation/kernel-parameters.txt	Mon Nov  1 10:31:34 1999
@@ -11,7 +11,7 @@
 restrictions referred to are that the relevant option is valid if:
 
     APIC	APIC support is enabled.
-    APM 	Automatic Power Management support is enabled.
+    APM 	Advanced Power Management support is enabled.
     AX25	Appropriate AX.25 support is enabled.
     CD		Appropriate CD support is enabled.
     EIDE	EIDE/ATAPI support is enabled.
@@ -20,6 +20,7 @@
     ISDN	Appropriate ISDN support is enabled.
     JOY 	Appropriate joystick support is enabled.
     LP		Printer support is enabled.
+    LOOP	Loopback device support is enabled.
     MCA 	MCA bus support is enabled.
     MDA 	The MDA console is enabled.
     MOUSE	Appropriate mouse support is enabled.
@@ -65,7 +66,7 @@
 
     AM53C974=		[HW,SCSI]
 
-    apm=		[APM] Automatic Power Management.
+    apm=		[APM] Advanced Power Management.
 
     arcrimi=		[HW,NET]
 
@@ -207,6 +208,9 @@
     ltpc=		[HW]
 
     mac5380=		[HW,SCSI]
+
+    max_loop=[0-255]	[LOOP] States the maximum number of loopback devices
+    			that can be mounted.
 
     maxcpus=		[SMP] States the maximum number of processors that
 			an SMP kernel should make use of.
diff -u --recursive --new-file v2.3.24/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.24/linux/MAINTAINERS	Wed Oct 27 16:34:12 1999
+++ linux/MAINTAINERS	Sat Oct 30 09:42:30 1999
@@ -128,9 +128,10 @@
 
 APM DRIVER
 P:	Stephen Rothwell
-M:	Stephen.Rothwell@canb.auug.org.au
+M:	sfr@linuxcare.com
 L:	linux-laptop@vger.rutgers.edu
-S:	Maintained
+W:	http://linuxcare.com.au/apm/
+S:	Supported
 
 APPLETALK NETWORK LAYER
 P:	Jay Schulist
@@ -145,10 +146,9 @@
 
 ARM PORT
 P:	Russell King
-M:	linux@arm.uk.linux.org
+M:	linux@arm.linux.org.uk
 L:	linux-arm@vger.rutgers.edu
-L:	arm-linux@tardis.ed.ac.uk
-W:	http://www.arm.uk.linux.org/~rmk/armlinux.html
+W:	http://www.arm.linux.org.uk/~rmk/armlinux.html
 S:	Maintained
 
 ARPD SUPPORT
@@ -176,6 +176,13 @@
 W:	http://ftp.bitgate.com/pcwd/
 S:	Maintained
 
+BFS FILE SYSTEM
+P:	Tigran A. Aivazian
+M:	tigran@ocston.org
+L:	linux-kernel@vger.rutgers.edu
+W:	http://www.ocston.org/~tigran/patches/bfs
+S:	Maintained
+
 BUSLOGIC SCSI DRIVER
 P:	Leonard N. Zubkoff
 M:	Leonard N. Zubkoff <lnz@dandelion.com>
@@ -896,6 +903,8 @@
 UDF FILESYSTEM
 P:	Ben Fennema
 M:	bfennema@falcon.csc.calpoly.edu
+P:	Dave Boynton
+M:	dave@trylinux.com
 L:	linux_udf@hootie.lvld.hp.com
 W:	http://www.trylinux.com/projects/udf/index.html
 S:	Maintained
diff -u --recursive --new-file v2.3.24/linux/Makefile linux/Makefile
--- v2.3.24/linux/Makefile	Wed Oct 27 16:34:12 1999
+++ linux/Makefile	Fri Oct 29 15:38:02 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 24
+SUBLEVEL = 25
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -250,9 +250,6 @@
 symlinks:
 	rm -f include/asm
 	( cd include ; ln -sf asm-$(ARCH) asm)
-	@if [ ! -d modules ]; then \
-		mkdir modules; \
-	fi
 	@if [ ! -d include/linux/modules ]; then \
 		mkdir include/linux/modules; \
 	fi
@@ -331,7 +328,11 @@
 
 modules: $(patsubst %, _mod_%, $(SUBDIRS))
 
-$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/MARKER
+modules/MARKER:
+	mkdir modules
+	touch modules/MARKER
+
+$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/MARKER modules/MARKER
 	$(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules
 
 modules_install:
@@ -392,10 +393,8 @@
 	rm -f drivers/sound/bin2hex drivers/sound/hex2hex
 	rm -f net/khttpd/make_times_h
 	rm -f net/khttpd/times.h
-	if [ -d modules ]; then \
-		rm -f core `find modules/ -type f -print`; \
-	fi
 	rm -f submenu*
+	rm -rf modules
 
 mrproper: clean archmrproper
 	rm -f include/linux/autoconf.h include/linux/version.h
@@ -416,7 +415,6 @@
 	rm -f .hdepend scripts/mkdep scripts/split-include
 	rm -f $(TOPDIR)/include/linux/modversions.h
 	rm -rf $(TOPDIR)/include/linux/modules
-	rm -rf modules
 
 distclean: mrproper
 	rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
diff -u --recursive --new-file v2.3.24/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.3.24/linux/arch/arm/Makefile	Fri Oct 22 13:21:43 1999
+++ linux/arch/arm/Makefile	Thu Oct 28 10:16:02 1999
@@ -16,10 +16,10 @@
 OBJCOPY		:= $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
 CPP		:= $(CC) -E
 PERL		:= perl
-LINKFLAGS	:= -X -T arch/arm/vmlinux.lds
+LINKFLAGS	:= -p -X -T arch/arm/vmlinux.lds
 ARCHCC		:= $(word 1,$(CC))
 
-
+AFLAGS		+= -mno-fpu
 CFLAGS_PIPE	:= -pipe
 CFLAGS		:= $(CFLAGS) $(CFLAGS_PIPE)
 
@@ -31,6 +31,15 @@
 CFLAGS		+= -g
 endif
 
+# Ensure this is ld "2.9.4" or later
+NEW_LINKER	:= $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi)
+
+ifneq ($(NEW_LINKER),y)
+dummy:;		@echo '*** 2.3 kernels no longer build correctly with old versions of binutils.'
+		@echo '*** Please upgrade your binutils to 2.9.5.'
+		@false
+endif
+
 
 # GCC 2.7 uses different options to later compilers; sort out which we have
 NEW_GCC		:= $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi)
@@ -55,21 +64,6 @@
 CFLAGS_SA110		:= -m6
 endif
 
-# See if this is ld "2.9.4" or later
-NEW_LINKER		:= $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi)
-
-ifeq ($(NEW_LINKER),y)
-AFLAGS			+= -mno-fpu
-AFLAGS_PROC_CPU_26	:= -mapcs-26
-AFLAGS_PROC_CPU_32v3	:= -mapcs-32 -marmv3m
-AFLAGS_PROC_CPU_32v4	:= -mapcs-32 -marmv4t
-LINKFLAGS		:= -p $(LINKFLAGS)
-else
-AFLAGS_PROC_CPU_26	:= -m3
-AFLAGS_PROC_CPU_32v3	:= -m6
-AFLAGS_PROC_CPU_32v4	:= -m6
-endif
-
 #
 # Select CPU dependent flags
 #
@@ -77,7 +71,7 @@
  PROCESSOR	 = armo
  TEXTADDR	 = 0x02080000
  CFLAGS		+= $(CFLAGS_PROC_CPU_26)
- AFLAGS		+= $(AFLAGS_PROC_CPU_26)
+ AFLAGS		+= -mapcs-26
 endif
 
 ifeq ($(CONFIG_CPU_32),y)
@@ -85,10 +79,10 @@
  TEXTADDR	 = 0xC0008000
  ifeq ($(CONFIG_CPU_32v4),y)
   CFLAGS	+= $(CFLAGS_PROC_CPU_32v4)
-  AFLAGS	+= $(AFLAGS_PROC_CPU_32v4)
+  AFLAGS	+= -mapcs-32 -marmv4
  else
   CFLAGS	+= $(CFLAGS_PROC_CPU_32v3)
-  AFLAGS	+= $(AFLAGS_PROC_CPU_32v3)
+  AFLAGS	+= -mapcs-32 -marmv3m
  endif
  #
  # Exactly one of the following must be selected
@@ -156,7 +150,7 @@
 DRIVERS		+= arch/arm/special/special.a
 
 ifeq ($(CONFIG_NWFPE),y)
-CORE_FILES	+= arch/arm/nwfpe/math-emu.o
+LIBS		:= arch/arm/nwfpe/math-emu.o $(LIBS)
 endif
 
 ifeq ($(CONFIG_ARCH_ACORN),y)
@@ -173,7 +167,7 @@
 # to date before starting compilation
 CONSTANTS	:= constants
 
-constants: dummy
+constants: $(TOPDIR)/include/asm-arm/proc-fns.h dummy
 	@$(MAKE) -C arch/arm/lib constants.h
 
 symlinks: archsymlinks
diff -u --recursive --new-file v2.3.24/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile
--- v2.3.24/linux/arch/arm/boot/compressed/Makefile	Fri Oct 22 13:21:43 1999
+++ linux/arch/arm/boot/compressed/Makefile	Thu Oct 28 10:16:02 1999
@@ -8,7 +8,7 @@
 SYSTEM		 = $(TOPDIR)/vmlinux
 CFLAGS		 = -O2 -DSTDC_HEADERS $(CFLAGS_PROC)
 FONTC		 = $(TOPDIR)/drivers/video/font_acorn_8x8.c
-ZLDFLAGS	 = -X -T vmlinux.lds
+ZLDFLAGS	 = -p -X -T vmlinux.lds
 
 #
 # Architecture dependencies
diff -u --recursive --new-file v2.3.24/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S
--- v2.3.24/linux/arch/arm/boot/compressed/head.S	Fri Oct 22 13:21:43 1999
+++ linux/arch/arm/boot/compressed/head.S	Thu Oct 28 10:16:02 1999
@@ -96,6 +96,8 @@
  */
 reloc_start:	add	r8, r5, r0
 #if 0
+	mov r0, #'\n'
+	bl putc
 	mov r0, r6
 	mov r1, #8
 	bl phex
@@ -139,8 +141,8 @@
 	bl phex
 	mov r0, #'\n'
 	bl putc
-	mov	r0, r4
-	bl	memdump
+	mov r0, r4
+	bl  memdump
 #endif
 		eor	r0, r6, #0x44 << 24	@ SA-110?
 		eor	r0, r0, #0x01 << 16
@@ -155,6 +157,25 @@
 
 phexbuf:	.space	12
 
+#if 0
+		.macro	loadsp,	rb
+		mov	\rb, #0x7c000000
+		.endm
+
+		.macro	writeb,	rb
+		strb	\rb, [r3, #0x3f8]
+		.endm
+#else
+		.macro	loadsp,	rb
+		mov	\rb, #0x03000000
+		orr	\rb, \rb, #0x00010000
+		.endm
+
+		.macro	writeb,	rb
+		strb	\rb, [r3, #0x3f8 << 2]
+		.endm
+#endif
+
 phex:		adr	r3, phexbuf
 		mov	r2, #0
 		strb	r2, [r3, r1]
@@ -169,11 +190,11 @@
 		strb	r2, [r3, r1]
 		b	1b
 
-puts:		mov	r3, #0x7c000000
+puts:		loadsp	r3
 1:		ldrb	r2, [r0], #1
 		teq	r2, #0
 		moveq	pc, lr
-2:		strb	r2, [r3, #0x3f8]
+2:		writeb	r2
 		mov	r1, #0x00020000
 3:		subs	r1, r1, #1
 		bne	3b
@@ -186,7 +207,7 @@
 putc:
 		mov	r2, r0
 		mov	r0, #0
-		mov	r3, #0x7c000000
+		loadsp	r3
 		b	2b
 
 memdump:	mov	r12, r0
diff -u --recursive --new-file v2.3.24/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.3.24/linux/arch/arm/config.in	Wed Oct 27 16:34:12 1999
+++ linux/arch/arm/config.in	Thu Oct 28 10:45:51 1999
@@ -21,6 +21,7 @@
 	 EBSA-110		CONFIG_ARCH_EBSA110 \
 	 FootBridge-based	CONFIG_FOOTBRIDGE" RiscPC
 # 	 SA1100-based		CONFIG_ARCH_SA1100
+
 if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
    bool 'FootBridge in HOST mode' CONFIG_HOST_FOOTBRIDGE
    if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
@@ -45,13 +46,13 @@
 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
    define_bool CONFIG_CPU_SA1100 y
    choice 'SA1100 implementation' \
-	"Brutus			CONFIG_SA1100_BRUTUS \
-	 empeg			CONFIG_SA1100_EMPEG \
-	 Itsy			CONFIG_SA1100_ITSY \
-	 LART			CONFIG_SA1100_LART \
-	 PLEB			CONFIG_SA1100_PLEB \
-	 Victor			CONFIG_SA1100_VICTOR \
-	 Tifon			CONFIG_SA1100_TIFON" Brutus
+	   "Brutus		CONFIG_SA1100_BRUTUS \
+	    Empeg		CONFIG_SA1100_EMPEG \
+	    Itsy		CONFIG_SA1100_ITSY \
+	    LART		CONFIG_SA1100_LART \
+	    PLEB		CONFIG_SA1100_PLEB \
+	    Victor		CONFIG_SA1100_VICTOR \
+	    Tifon		CONFIG_SA1100_TIFON" Brutus
 fi
 
 #
@@ -120,8 +121,6 @@
 else
    define_bool CONFIG_ISA_DMA n
 fi
-
-endmenu
 
 if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP
diff -u --recursive --new-file v2.3.24/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c
--- v2.3.24/linux/arch/arm/kernel/armksyms.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/armksyms.c	Thu Oct 28 10:16:02 1999
@@ -12,6 +12,7 @@
 #include <asm/byteorder.h>
 #include <asm/elf.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
 #include <asm/proc-fns.h>
@@ -98,7 +99,8 @@
 EXPORT_SYMBOL(system_rev);
 EXPORT_SYMBOL(system_serial_low);
 EXPORT_SYMBOL(system_serial_high);
-
+EXPORT_SYMBOL(__bug);
+EXPORT_SYMBOL(__readwrite_bug);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 
@@ -152,8 +154,8 @@
 #ifndef CONFIG_NO_PGT_CACHE
 EXPORT_SYMBOL(quicklists);
 #endif
-EXPORT_SYMBOL(__bad_pmd);
-EXPORT_SYMBOL(__bad_pmd_kernel);
+EXPORT_SYMBOL(__handle_bad_pmd);
+EXPORT_SYMBOL(__handle_bad_pmd_kernel);
 
 	/* string / mem functions */
 EXPORT_SYMBOL_NOVERS(strcpy);
diff -u --recursive --new-file v2.3.24/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c
--- v2.3.24/linux/arch/arm/kernel/bios32.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/bios32.c	Thu Oct 28 10:16:02 1999
@@ -13,16 +13,14 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 
-int have_isa_bridge;
+#include "bios32.h"
 
-int (*pci_irq_fixup)(struct pci_dev *dev);
+static int debug_pci;
+int have_isa_bridge;
 
-extern struct pci_ops *dc21285_init(int pass);
-extern void pcibios_fixup_ebsa285(struct pci_dev *dev);
 extern void hw_init(void);
 
-void
-pcibios_report_device_errors(void)
+void pcibios_report_device_errors(void)
 {
 	struct pci_dev *dev;
 
@@ -31,16 +29,17 @@
 
 		pci_read_config_word(dev, PCI_STATUS, &status);
 
-		if (status & 0xf900) {
-			pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
-			printk(KERN_DEBUG "PCI: %02x:%02x status = %X\n",
-				dev->bus->number, dev->devfn, status);
-		}
+		if ((status & 0xf900) == 0)
+			continue;
+
+		pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
+		printk(KERN_DEBUG "PCI: status %04X on %s\n",
+			status, dev->name);
 	}
 }
 
 /*
- * We don't use this to fix the device, but more our initialisation.
+ * We don't use this to fix the device, but initialisation of it.
  * It's not the correct use for this, but it works.  The actions we
  * take are:
  * - enable only IO
@@ -68,196 +67,108 @@
 	pci_write_config_byte(dev, 0x81, 0x01);
 }
 
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553 },
-	{ 0 }
-};
-
-/*
- * Assign new address to PCI resource.  We hope our resource information
- * is complete.  On the PC, we don't re-assign resources unless we are
- * forced to do so.
- *
- * Expects start=0, end=size-1, flags=resource type.
- */
-
-int __init pcibios_assign_resource(struct pci_dev *dev, int i)
+static void __init pci_fixup_unassign(struct pci_dev *dev)
 {
-	struct resource *r = &dev->resource[i];
-	struct resource *pr = pci_find_parent_resource(dev, r);
-	unsigned long size = r->end + 1;
-	unsigned long flags = 0;
-
-	if (!pr)
-		return -EINVAL;
-	if (r->flags & IORESOURCE_IO) {
-		if (size > 0x100)
-			return -EFBIG;
-		if (allocate_resource(pr, r, size, 0x9000, ~0, 1024))
-			return -EBUSY;
-		flags = PCI_BASE_ADDRESS_SPACE_IO;
-	} else {
-		if (allocate_resource(pr, r, size, 0x00100000, 0x7fffffff, size))
-			return -EBUSY;
-	}
-	if (i < 6)
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4*i, r->start | flags);
-	return 0;
+	dev->resource[0].end -= dev->resource[0].start;
+	dev->resource[0].start = 0;
 }
 
 /*
- * Assign an address to an I/O range.
+ * PCI IDE controllers use non-standard I/O port
+ * decoding, respect it.
  */
-static void __init pcibios_fixup_io_addr(struct pci_dev *dev, struct resource *r, int idx)
+static void __init pci_fixup_ide_bases(struct pci_dev *dev)
 {
-	unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
-	unsigned int size = r->end - r->start + 1;
-	u32 try;
+	struct resource *r;
+	int i;
 
-	/*
-	 * We need to avoid collisions with `mirrored' VGA ports and other strange
-	 * ISA hardware, so we always want the addresses kilobyte aligned.
-	 */
-	if (!size || size > 256) {
-		printk(KERN_ERR "PCI: Cannot assign I/O space to %s, "
-		       "%d bytes are too much.\n", dev->name, size);
+	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
 		return;
-	}
 
-	if (allocate_resource(&ioport_resource, r, size, 0x9000, ~0, 1024)) {
-		printk(KERN_ERR "PCI: Unable to find free %d bytes of I/O "
-			"space for %s.\n", size, dev->name);
-		return;
-	}
-
-	printk("PCI: Assigning I/O space %04lx-%04lx to %s\n",
-		r->start, r->end, dev->name);
-
-	pci_write_config_dword(dev, reg, r->start | PCI_BASE_ADDRESS_SPACE_IO);
-	pci_read_config_dword(dev, reg, &try);
-
-	if ((try & PCI_BASE_ADDRESS_IO_MASK) != r->start) {
-		r->start = 0;
-		pci_write_config_dword(dev, reg, 0);
-		printk(KERN_ERR "PCI: I/O address setup failed, got %04x\n", try);
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		r = dev->resource + i;
+		if ((r->start & ~0x80) == 0x374) {
+			r->start |= 2;
+			r->end = r->start;
+		}
 	}
 }
 
+struct pci_fixup pcibios_fixups[] = {
+	{
+		PCI_FIXUP_HEADER,
+		PCI_VENDOR_ID_WINBOND,	PCI_DEVICE_ID_WINBOND_83C553,
+		pci_fixup_83c553
+	}, {
+		PCI_FIXUP_HEADER,
+		PCI_VENDOR_ID_WINBOND2,	PCI_DEVICE_ID_WINBOND2_89C940F,
+		pci_fixup_unassign
+	}, {
+		PCI_FIXUP_HEADER,
+		PCI_ANY_ID,		PCI_ANY_ID,
+		pci_fixup_ide_bases
+	}, { 0 }
+};
+
 /*
- * Assign an address to an memory range.
+ * Allocate resources for all PCI devices that have been enabled.
+ * We need to do that before we try to fix up anything.
  */
-static void __init pcibios_fixup_mem_addr(struct pci_dev *dev, struct resource *r, int idx)
+static void __init pcibios_claim_resources(void)
 {
-	unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
-	unsigned int size = r->end - r->start + 1;
-	u32 try;
-
-	if (!size) {
-		printk(KERN_ERR "PCI: Cannot assign memory space to %s, "
-		       "%d bytes are too much.\n", dev->name, size);
-		return;
-	}
-
-	if (allocate_resource(&iomem_resource, r, size,
-			      0x00100000, 0x0fffffff, 1024)) {
-		printk(KERN_ERR "PCI: Unable to find free %d bytes of memory "
-			"space for %s.\n", size, dev->name);
-		return;
-	}
-
-	printk("PCI: Assigning memory space %08lx-%08lx to %s\n",
-		r->start, r->end, dev->name);
-
-	pci_write_config_dword(dev, reg, r->start);
-	pci_read_config_dword(dev, reg, &try);
+	struct pci_dev *dev;
+	int idx;
 
-	if (try != r->start) {
-		r->start = 0;
-		pci_write_config_dword(dev, reg, 0);
-		printk(KERN_ERR "PCI: memory address setup failed, "
-		       "got %08x\n", try);
-	}
+	for (dev = pci_devices; dev; dev = dev->next)
+		for (idx = 0; idx < PCI_NUM_RESOURCES; idx++)
+			if (dev->resource[idx].flags &&
+			    dev->resource[idx].start)
+				pci_claim_resource(dev, idx);
 }
 
-#define _PCI_REGION_IO	1
-#define _PCI_REGION_MEM	2
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			struct resource *res, int resource)
+{
+	unsigned long where, size;
+	u32 reg;
+
+	if (debug_pci)
+		printk("PCI: Assigning %3s %08lx to %s\n",
+			res->flags & IORESOURCE_IO ? "IO" : "MEM",
+			res->start, dev->name);
+
+	where = PCI_BASE_ADDRESS_0 + resource * 4;
+	size  = res->end - res->start;
+
+	pci_read_config_dword(dev, where, &reg);
+	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+	pci_write_config_dword(dev, where, reg);
+}
 
-/*
- * Fix up one PCI devices regions, enables and interrupt lines
- */
-static void __init pcibios_fixup_device(struct pci_dev *dev, u16 *cmd)
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
 {
-	int i, has_regions = 0;
-
-	/*
-	 * Fix up the regions.  Any regions which aren't allocated
-	 * are given a free region.
-	 */
-	for (i = 0; i < 6; i++) {
-		struct resource *r = dev->resource + i;
-
-		if (r->flags & IORESOURCE_IO) {
-			has_regions |= _PCI_REGION_IO;
-
-			if (!r->start || r->end == 0xffffffff)
-				pcibios_fixup_io_addr(dev, r, i);
-		} else if (r->end) {
-			has_regions |= _PCI_REGION_MEM;
-
-			if (!r->start)
-				pcibios_fixup_mem_addr(dev, r, i);
-		}
-	}
-
-	switch (dev->class >> 8) {
-	case PCI_CLASS_BRIDGE_ISA:
-	case PCI_CLASS_BRIDGE_EISA:
-		/*
-		 * If this device is an ISA bridge, set the have_isa_bridge
-		 * flag.  We will then go looking for things like keyboard,
-		 * etc
-		 */
-		have_isa_bridge = !0;
-		/* FALL THROUGH */
-
-	default:
-		/*
-		 * Don't enable VGA-compatible cards since they have
-		 * fixed I/O and memory space.
-		 *
-		 * Don't enabled disabled IDE interfaces either because
-		 * some BIOSes may reallocate the same address when they
-		 * find that no devices are attached. 
-		 */
-		if (has_regions & _PCI_REGION_IO &&
-		    !((*cmd) & PCI_COMMAND_IO)) {
-			printk("PCI: Enabling I/O for %s\n", dev->name);
-			*cmd |= PCI_COMMAND_IO;
-		}
-
-		if (has_regions & _PCI_REGION_MEM &&
-		    !((*cmd) & PCI_COMMAND_MEMORY)) {
-			printk("PCI: Enabling memory for %s\n", dev->name);
-			*cmd |= PCI_COMMAND_MEMORY;
-		}
-	}
+	if (debug_pci)
+		printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
 /*
- * Fix base addresses, I/O and memory enables and IRQ's
+ * Called after each bus is probed, but before its children
+ * are examined.
  */
-static void __init pcibios_fixup_devices(void)
+void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 
-	for (dev = pci_devices; dev; dev = dev->next) {
+	for (dev = bus->devices; dev; dev = dev->sibling) {
 		u16 cmd;
 
 		/*
-		 * architecture specific hacks.
-		 * I don't really want this here,
-		 * but I don't see any other place
-		 * for it to live.
+		 * architecture specific hacks. I don't really want
+		 * this here, but I don't see any other place for it
+		 * to live.  Shame the device doesn't support
+		 * capabilities
 		 */
 		if (machine_is_netwinder() &&
 		    dev->vendor == PCI_VENDOR_ID_DEC &&
@@ -266,119 +177,165 @@
 			pci_write_config_dword(dev, 0x40, 0x80000000);
 
 		/*
+		 * If this device is an ISA bridge, set the have_isa_bridge
+		 * flag.  We will then go looking for things like keyboard,
+		 * etc
+		 */
+		if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA ||
+		    dev->class >> 8 == PCI_CLASS_BRIDGE_EISA)
+			have_isa_bridge = !0;
+			
+		/*
 		 * Set latency timer to 32, and a cache line size to 32 bytes.
 		 * Also, set system error enable, parity error enable, and
 		 * fast back to back transaction enable.  Disable ROM.
 		 */
 		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
 		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
-		pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
 
 		cmd |= PCI_COMMAND_FAST_BACK | PCI_COMMAND_SERR |
 		       PCI_COMMAND_PARITY;
 
-		pcibios_fixup_device(dev, &cmd);
-
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+	}
+}
 
-		/*
-		 * now fixup the IRQs, if required
-		 */
-		if (pci_irq_fixup)
-			dev->irq = pci_irq_fixup(dev);
+static u8 __init no_swizzle(struct pci_dev *dev, u8 *pin)
+{
+	return 0;
+}
 
-		/*
-		 * If any remaining IRQs are weird, fix it now.
-		 */
-		if (dev->irq >= NR_IRQS)
-			dev->irq = 0;
+/* ebsa285 host-specific stuff */
+static int irqmap_ebsa285[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
 
-		/*
-		 * catch any drivers still reading this from the
-		 * device itself.  This can be removed once
-		 * all drivers are fixed. (are there any?)
-		 */
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
+static u8 __init ebsa285_swizzle(struct pci_dev *dev, u8 *pin)
+{
+	return PCI_SLOT(dev->devfn);
 }
 
-/*
- * Allocate resources for all PCI devices that have been enabled.
- * We need to do that before we try to fix up anything.
- */
-static void __init pcibios_claim_resources(void)
+static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	struct pci_dev *dev;
-	int idx;
+	return irqmap_ebsa285[(slot + pin) & 3];
+}
 
-	for (dev = pci_devices; dev; dev = dev->next)
-		for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
-			struct resource *a, *r = &dev->resource[idx];
+static struct hw_pci ebsa285_pci __initdata = {
+	dc21285_init,
+	0x9000,
+	0x00100000,
+	ebsa285_swizzle,
+	ebsa285_map_irq
+};
 
-			/*
-			 * Ignore regions that start at 0 or
-			 * end at 0xffffffff
-			 */
-			if (!r->start || r->end == 0xffffffff)
-				continue;
-
-			if (r->flags & IORESOURCE_IO)
-				a = &ioport_resource;
-			else
-				a = &iomem_resource;
-
-			if (request_resource(a, r) < 0)
-				printk(KERN_ERR "PCI: Address space collision "
-					"on region %d of %s\n",
-					idx, dev->name);
-				/* We probably should disable the region,
-				 * shouldn't we?
-				 */
-		}
+/* cats host-specific stuff */
+static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
+
+static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (dev->irq >= 128)
+		return 16 + (dev->irq & 0x1f);
+
+	if (dev->irq >= 1 && dev->irq <= 4)
+		return irqmap_cats[dev->irq - 1];
+
+	if (dev->irq != 0)
+		printk("PCI: device %02x:%02x has unknown irq line %x\n",
+		       dev->bus->number, dev->devfn, dev->irq);
+
+	return -1;
 }
 
-/*
- * Called after each bus is probed, but before its children
- * are examined.
- *
- * No fixup of bus required
- */
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+static struct hw_pci cats_pci __initdata = {
+	dc21285_init,
+	0x9000,
+	0x00100000,
+	no_swizzle,
+	cats_map_irq
+};
+
+/* netwinder host-specific stuff */
+static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
+#define DEV(v,d) ((v)<<16|(d))
+	switch (DEV(dev->vendor, dev->device)) {
+	case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142):
+		return IRQ_NETWINDER_ETHER100;
+
+	case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a):
+		return IRQ_NETWINDER_ETHER10;
+
+	case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553):
+		return 0;
+
+	case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105):
+		return IRQ_ISA_HARDDISK1;
+
+	case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000):
+		return IRQ_NETWINDER_VGA;
+
+	default:
+		printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n",
+			dev->bus->number, dev->devfn,
+			dev->vendor, dev->device);
+		return 0;
+	}
 }
 
+static struct hw_pci netwinder_pci __initdata = {
+	dc21285_init,
+	0x9000,
+	0x00100000,
+	no_swizzle,
+	netwinder_map_irq
+};
+
 void __init pcibios_init(void)
 {
-	struct pci_ops *ops;
+	struct hw_pci *hw_pci = NULL;
+
+	if (machine_is_ebsa285())
+		hw_pci = &ebsa285_pci;
+	else if (machine_is_cats())
+		hw_pci = &cats_pci;
+	else if (machine_is_netwinder())
+		hw_pci = &netwinder_pci;
+
+	if (hw_pci == NULL)
+		return;
 
 	/*
-	 * Pre-initialisation.  Set up the host bridge.
+	 * Set up the host bridge, and scan the bus.
 	 */
-	ops = dc21285_init(0);
+	hw_pci->init();
 
-	printk("PCI: Probing PCI hardware\n");
-
-	pci_scan_bus(0, ops, NULL);
+	/*
+	 * Other architectures don't seem to do this... should we?
+	 */
 	pcibios_claim_resources();
-	pcibios_fixup_devices();
 
 	/*
-	 * Now clear down any PCI error IRQs and
-	 * register the error handler
+	 * Assign any unassigned resources.  Note that we really ought to
+	 * have min/max stuff here - max mem address is 0x0fffffff
 	 */
-	dc21285_init(1);
+	pci_assign_unassigned_resources(hw_pci->io_start, hw_pci->mem_start);
+	pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq);
+	pci_set_bus_ranges();
 
 	/*
-	 * Initialise any other hardware after we've
-	 * got the PCI bus initialised.  We may need
-	 * the PCI bus to talk to this other hardware.
+	 * Initialise any other hardware after we've got the PCI bus
+	 * initialised.  We may need the PCI bus to talk to this other
+	 * hardware.
 	 */
 	hw_init();
 }
 
 char * __init pcibios_setup(char *str)
 {
+	if (!strcmp(str, "debug")) {
+		debug_pci = 1;
+		return NULL;
+	}
 	return str;
 }
diff -u --recursive --new-file v2.3.24/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c
--- v2.3.24/linux/arch/arm/kernel/dec21285.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/dec21285.c	Thu Oct 28 10:16:02 1999
@@ -18,11 +18,12 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 
+#include "bios32.h"
+
 #define MAX_SLOTS		21
 
 extern int setup_arm_irq(int, struct irqaction *);
 extern void pcibios_report_device_errors(void);
-extern int (*pci_irq_fixup)(struct pci_dev *dev);
 
 static unsigned long
 dc21285_base_address(struct pci_dev *dev, int where)
@@ -202,129 +203,53 @@
 	dc21285_error, SA_INTERRUPT, 0, "PCI error", NULL, NULL
 };
 
-static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
-
-static int __init ebsa_irqval(struct pci_dev *dev)
-{
-	u8 pin;
-
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-
-	return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
-}
-
-static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
-
-static int __init cats_irqval(struct pci_dev *dev)
-{
-	if (dev->irq >= 128)
-		return 16 + (dev->irq & 0x1f);
-
-	switch (dev->irq) {
-	case 1 ... 4:
-		return irqmap_cats[dev->irq - 1];
-
-	default:
-		printk("PCI: device %02x:%02x has unknown irq line %x\n",
-		       dev->bus->number, dev->devfn, dev->irq);
-	case 0:
-		break;
-	}
-	return 0;
-}
-
-static int __init netwinder_irqval(struct pci_dev *dev)
-{
-#define DEV(v,d) ((v)<<16|(d))
-	switch (DEV(dev->vendor, dev->device)) {
-	case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142):
-		return IRQ_NETWINDER_ETHER100;
-
-	case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a):
-		return IRQ_NETWINDER_ETHER10;
-
-	case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553):
-		return 0;
-
-	case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105):
-		return IRQ_ISA_HARDDISK1;
-
-	case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000):
-		return IRQ_NETWINDER_VGA;
-
-	default:
-		printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n",
-			dev->bus->number, dev->devfn,
-			dev->vendor, dev->device);
-		return 0;
-	}
-}
-
-struct pci_ops * __init dc21285_init(int pass)
+void __init dc21285_init(void)
 {
 	unsigned int mem_size;
 	unsigned long cntl;
 
-	if (pass == 0) {
-		mem_size = (unsigned int)high_memory - PAGE_OFFSET;
-		*CSR_SDRAMBASEMASK    = (mem_size - 1) & 0x0ffc0000;
-		*CSR_SDRAMBASEOFFSET  = 0;
-		*CSR_ROMBASEMASK      = 0x80000000;
-		*CSR_CSRBASEMASK      = 0;
-		*CSR_CSRBASEOFFSET    = 0;
-		*CSR_PCIADDR_EXTN     = 0;
+	mem_size = (unsigned int)high_memory - PAGE_OFFSET;
+	*CSR_SDRAMBASEMASK    = (mem_size - 1) & 0x0ffc0000;
+	*CSR_SDRAMBASEOFFSET  = 0;
+	*CSR_ROMBASEMASK      = 0x80000000;
+	*CSR_CSRBASEMASK      = 0;
+	*CSR_CSRBASEOFFSET    = 0;
+	*CSR_PCIADDR_EXTN     = 0;
 
 #ifdef CONFIG_HOST_FOOTBRIDGE
-		/*
-		 * Map our SDRAM at a known address in PCI space, just in case
-		 * the firmware had other ideas.  Using a nonzero base is
-		 * necessary, since some VGA cards forcefully use PCI addresses
-		 * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
-		 */
-		*CSR_PCICACHELINESIZE = 0x00002008;
-		*CSR_PCICSRBASE       = 0;
-		*CSR_PCICSRIOBASE     = 0;
-		*CSR_PCISDRAMBASE     = virt_to_bus((void *)PAGE_OFFSET);
-		*CSR_PCIROMBASE       = 0;
-		*CSR_PCICMD           = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-					PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK |
-					PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
-					(1 << 31) | (1 << 29) | (1 << 28) | (1 << 24);
+	/*
+	 * Map our SDRAM at a known address in PCI space, just in case
+	 * the firmware had other ideas.  Using a nonzero base is
+	 * necessary, since some VGA cards forcefully use PCI addresses
+	 * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
+	 */
+	*CSR_PCICACHELINESIZE = 0x00002008;
+	*CSR_PCICSRBASE       = 0;
+	*CSR_PCICSRIOBASE     = 0;
+	*CSR_PCISDRAMBASE     = virt_to_bus((void *)PAGE_OFFSET);
+	*CSR_PCIROMBASE       = 0;
+	*CSR_PCICMD           = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+				PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK |
+				PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
+				(1 << 31) | (1 << 29) | (1 << 28) | (1 << 24);
 #endif
 
-		printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n",
-			*CSR_CLASSREV & 0xff);
+	printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n",
+		*CSR_CLASSREV & 0xff);
 
-		switch (machine_arch_type) {
-		case MACH_TYPE_EBSA285:
-			pci_irq_fixup = ebsa_irqval;
-			break;
-
-		case MACH_TYPE_CATS:
-			pci_irq_fixup = cats_irqval;
-			break;
-
-		case MACH_TYPE_NETWINDER:
-			pci_irq_fixup = netwinder_irqval;
-			break;
-		}
-
-		return &dc21285_ops;
-	} else {
-		/*
-		 * Clear any existing errors - we aren't
-		 * interested in historical data...
-		 */
-		cntl = *CSR_SA110_CNTL & 0xffffde07;
-		*CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
-		cntl = *CSR_PCICMD & 0x0000ffff;
-		*CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24;
-
-		/*
-		 * Initialise PCI error IRQ after we've finished probing
-		 */
-		setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action);
+	pci_scan_bus(0, &dc21285_ops, NULL);
 
-		return NULL;
-	}
+	/*
+	 * Clear any existing errors - we aren't
+	 * interested in historical data...
+	 */
+	cntl = *CSR_SA110_CNTL & 0xffffde07;
+	*CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
+	cntl = *CSR_PCICMD & 0x0000ffff;
+	*CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24;
+
+	/*
+	 * Initialise PCI error IRQ after we've finished probing
+	 */
+	setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action);
 }
diff -u --recursive --new-file v2.3.24/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c
--- v2.3.24/linux/arch/arm/kernel/ecard.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/ecard.c	Fri Oct 29 11:01:12 1999
@@ -888,19 +888,13 @@
 	return (count > cnt) ? cnt : count;
 }
 
-static struct proc_dir_entry proc_ecard_devices = {
-	PROC_BUS_ECARD_DEVICES, 7, "devices",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	get_ecard_dev_info
-};
-
-static struct proc_dir_entry *proc_bus_ecard_dir;
+static struct proc_dir_entry *proc_bus_ecard_dir = NULL;
 
 static void ecard_proc_init(void)
 {
 	proc_bus_ecard_dir = create_proc_entry("ecard", S_IFDIR, proc_bus);
-	proc_register(proc_bus_ecard_dir, &proc_ecard_devices);
+	create_proc_info_entry("devices", 0, proc_bus_ecard_dir,
+		get_ecard_dev_info);
 }
 
 /*
diff -u --recursive --new-file v2.3.24/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.3.24/linux/arch/arm/kernel/setup.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/setup.c	Thu Oct 28 10:16:02 1999
@@ -20,6 +20,7 @@
 #include <linux/blk.h>
 #include <linux/console.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/elf.h>
 #include <asm/hardware.h>
@@ -42,50 +43,74 @@
 
 extern void reboot_setup(char *str, int *ints);
 extern void disable_hlt(void);
-
-struct drive_info_struct { char dummy[32]; } drive_info;
-struct screen_info screen_info = {
- orig_video_lines:	30,
- orig_video_cols:	80,
- orig_video_mode:	0,
- orig_video_ega_bx:	0,
- orig_video_isVGA:	1,
- orig_video_points:	8
-};
-
 extern int root_mountflags;
-extern int _text, _etext, _edata, _end;
+extern int _stext, _text, _etext, _edata, _end;
 
-unsigned char aux_device_present;
-         char elf_platform[ELF_PLATFORM_SIZE];
-unsigned int  elf_hwcap;
-
-/*
- * From head-armv.S
- */
 unsigned int processor_id;
 unsigned int __machine_arch_type;
 unsigned int vram_size;
 unsigned int system_rev;
 unsigned int system_serial_low;
 unsigned int system_serial_high;
-#ifdef MULTI_CPU
-struct processor processor;
-#endif
+unsigned int elf_hwcap;
+
 #ifdef CONFIG_ARCH_ACORN
 unsigned int memc_ctrl_reg;
 unsigned int number_mfm_drives;
 #endif
 
+struct meminfo meminfo;
+
+#ifdef MULTI_CPU
+struct processor processor;
+#endif
+
+struct drive_info_struct { char dummy[32]; } drive_info;
+
+struct screen_info screen_info = {
+ orig_video_lines:	30,
+ orig_video_cols:	80,
+ orig_video_mode:	0,
+ orig_video_ega_bx:	0,
+ orig_video_isVGA:	1,
+ orig_video_points:	8
+};
+
+unsigned char aux_device_present;
+char elf_platform[ELF_PLATFORM_SIZE];
+char saved_command_line[COMMAND_LINE_SIZE];
+
 static struct proc_info_item proc_info;
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
 #define ENDIANNESS ((char)endian_test.l)
 
-/*-------------------------------------------------------------------------
- * Early initialisation routines for various configurable items in the
- * kernel.  Each one either supplies a setup_ function, or defines this
- * symbol to be empty if not configured.
+/*
+ * Standard memory resources
  */
+static struct resource mem_res[] = {
+	{ "System RAM",  0,     0,     IORESOURCE_MEM | IORESOURCE_BUSY },
+	{ "Video RAM",   0,     0,     IORESOURCE_MEM			},
+	{ "Kernel code", 0,     0,     IORESOURCE_MEM			},
+	{ "Kernel data", 0,     0,     IORESOURCE_MEM			}
+};
+
+#define system_ram  mem_res[0]
+#define video_ram   mem_res[1]
+#define kernel_code mem_res[2]
+#define kernel_data mem_res[3]
+
+static struct resource io_res[] = {
+	{ "reserved",    0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY },
+	{ "reserved",    0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY },
+	{ "reserved",    0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY }
+};
+
+#define lp0 io_res[0]
+#define lp1 io_res[1]
+#define lp2 io_res[2]
 
 static void __init setup_processor(void)
 {
@@ -124,55 +149,69 @@
 	cpu_proc_init();
 }
 
-static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
-       char saved_command_line[COMMAND_LINE_SIZE];
+static unsigned long __init memparse(char *ptr, char **retptr)
+{
+	unsigned long ret = simple_strtoul(ptr, retptr, 0);
 
+	switch (**retptr) {
+	case 'M':
+	case 'm':
+		ret <<= 10;
+	case 'K':
+	case 'k':
+		ret <<= 10;
+		(*retptr)++;
+	default:
+		break;
+	}
+	return ret;
+}
+
+/*
+ * Initial parsing of the command line.  We need to pick out the
+ * memory size.  We look for mem=size@start, where start and size
+ * are "size[KkMm]"
+ */
 static void __init
-setup_mem(char *cmd_line, unsigned long *mem_sz)
+parse_cmdline(char **cmdline_p, char *from)
 {
 	char c = ' ', *to = command_line;
-	int len = 0;
-
-	if (!*mem_sz)
-		*mem_sz = MEM_SIZE;
+	int usermem = 0, len = 0;
 
 	for (;;) {
-		if (c == ' ') {
-			if (cmd_line[0] == 'm' &&
-			    cmd_line[1] == 'e' &&
-			    cmd_line[2] == 'm' &&
-			    cmd_line[3] == '=') {
-				*mem_sz = simple_strtoul(cmd_line+4, &cmd_line, 0);
-				switch(*cmd_line) {
-				case 'M':
-				case 'm':
-					*mem_sz <<= 10;
-				case 'K':
-				case 'k':
-					*mem_sz <<= 10;
-					cmd_line++;
-				}
-			}
-			/* if there are two spaces, remove one */
-			if (*cmd_line == ' ') {
-				cmd_line++;
-				continue;
+		if (c == ' ' && !memcmp(from, "mem=", 4)) {
+			unsigned long size, start;
+
+			if (to != command_line)
+				to -= 1;
+
+			/* If the user specifies memory size, we
+			 * blow away any automatically generated
+			 * size.
+			 */
+			if (usermem == 0) {
+				usermem = 1;
+				meminfo.nr_banks = 0;
 			}
+
+			start = 0;
+			size  = memparse(from + 4, &from);
+			if (*from == '@')
+				start = memparse(from + 1, &from);
+
+			meminfo.bank[meminfo.nr_banks].start = start;
+			meminfo.bank[meminfo.nr_banks].size  = size;
+			meminfo.nr_banks += 1;
 		}
-		c = *cmd_line++;
+		c = *from++;
 		if (!c)
 			break;
 		if (COMMAND_LINE_SIZE <= ++len)
 			break;
 		*to++ = c;
 	}
-
 	*to = '\0';
-
-	/* remove trailing spaces */
-	while (*--to == ' ' && to != command_line)
-		*to = '\0';
+	*cmdline_p = command_line;
 }
 
 static void __init
@@ -199,51 +238,90 @@
 static void __init setup_initrd(unsigned int start, unsigned int size)
 {
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (start) {
-		initrd_start = start;
-		initrd_end   = start + size;
-	} else {
-		initrd_start = 0;
-		initrd_end   = 0;
-	}
+	if (start == 0)
+		size = 0;
+	initrd_start = start;
+	initrd_end   = start + size;
 #endif
 }
 
-static void __init check_initrd(unsigned long mem_end)
+/*
+ * Work out our memory regions.  Note that "pfn" is the physical page number
+ * relative to the first physical page, not the physical address itself.
+ */
+static void __init setup_bootmem(void)
 {
+	unsigned int end_pfn, bootmem_end;
+	int bank;
+
+	/*
+	 * Calculate the end of memory.
+	 */
+	for (bank = 0; bank < meminfo.nr_banks; bank++) {
+		if (meminfo.bank[bank].size) {
+			unsigned long end;
+
+			end = meminfo.bank[bank].start +
+			      meminfo.bank[bank].size;
+			if (meminfo.end < end)
+				meminfo.end = end;
+		}
+	}
+
+	bootmem_end = __pa(PAGE_ALIGN((unsigned long)&_end));
+	end_pfn     = meminfo.end >> PAGE_SHIFT;
+
+	/*
+	 * Initialise the boot-time allocator
+	 */
+	bootmem_end += init_bootmem(bootmem_end >> PAGE_SHIFT, end_pfn);
+
+	/*
+	 * Register all available RAM with the bootmem allocator.
+	 * The address is relative to the start of physical memory.
+	 */
+	for (bank = 0; bank < meminfo.nr_banks; bank ++)
+		free_bootmem(meminfo.bank[bank].start, meminfo.bank[bank].size);
+
+	/*
+	 * reserve the following regions:
+	 *  physical page 0 - it contains the exception vectors
+	 *  kernel and the bootmem structure
+	 *  swapper page directory (if any)
+	 *  initrd (if any)
+	 */
+	reserve_bootmem(0, PAGE_SIZE);
+#ifdef CONFIG_CPU_32
+	reserve_bootmem(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(void *));
+#endif
+	reserve_bootmem(__pa(&_stext), bootmem_end - __pa(&_stext));
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_end > mem_end) {
+	if (__pa(initrd_end) > (end_pfn << PAGE_SHIFT)) {
 		printk ("initrd extends beyond end of memory "
-			"(0x%08lx > 0x%08lx) - disabling initrd\n",
-			initrd_end, mem_end);
+			"(0x%08lx > 0x%08x) - disabling initrd\n",
+			__pa(initrd_end), end_pfn << PAGE_SHIFT);
 		initrd_start = 0;
 	}
+
+	if (initrd_start)
+		reserve_bootmem(__pa(initrd_start),
+				initrd_end - initrd_start);
 #endif
 }
 
-/*
- * Standard memory resources
- */
-static struct resource system_ram  = { "System RAM",  0, 0, IORESOURCE_MEM | IORESOURCE_BUSY };
-static struct resource video_ram   = { "Video RAM",   0, 0, IORESOURCE_MEM };
-static struct resource kernel_code = { "Kernel code", 0, 0, IORESOURCE_MEM };
-static struct resource kernel_data = { "Kernel data", 0, 0, IORESOURCE_MEM };
-static struct resource lpt1 = { "reserved", 0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY };
-static struct resource lpt2 = { "reserved", 0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY };
-static struct resource lpt3 = { "reserved", 0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY };
-
-static void __init request_standard_resources(unsigned long end)
+static void __init request_standard_resources(void)
 {
 	kernel_code.start  = __virt_to_bus((unsigned long) &_text);
 	kernel_code.end    = __virt_to_bus((unsigned long) &_etext - 1);
 	kernel_data.start  = __virt_to_bus((unsigned long) &_etext);
 	kernel_data.end    = __virt_to_bus((unsigned long) &_edata - 1);
 	system_ram.start   = __virt_to_bus(PAGE_OFFSET);
-	system_ram.end     = __virt_to_bus(end - 1);
+	system_ram.end     = __virt_to_bus(meminfo.end + PAGE_OFFSET - 1);
 
 	request_resource(&iomem_resource, &system_ram);
 	request_resource(&system_ram, &kernel_code);
 	request_resource(&system_ram, &kernel_data);
+
 	if (video_ram.start != video_ram.end)
 		request_resource(&iomem_resource, &video_ram);
 
@@ -253,17 +331,16 @@
 	 */
 	if (machine_is_ebsa110() || machine_is_riscpc() ||
 	    machine_is_netwinder())
-		request_resource(&ioport_resource, &lpt1);
+		request_resource(&ioport_resource, &lp0);
 	if (machine_is_riscpc())
-		request_resource(&ioport_resource, &lpt2);
+		request_resource(&ioport_resource, &lp1);
 	if (machine_is_ebsa110() || machine_is_netwinder())
-		request_resource(&ioport_resource, &lpt3);
+		request_resource(&ioport_resource, &lp2);
 }
 
-void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)
+void __init setup_arch(char **cmdline_p)
 {
 	struct param_struct *params = (struct param_struct *)PARAMS_BASE;
-	unsigned long memory_end = 0;
 	char *from = default_command_line;
 
 #if defined(CONFIG_ARCH_ARC)
@@ -296,10 +373,6 @@
 	case MACH_TYPE_RISCPC:
 		/* RiscPC can't handle half-word loads and stores */
 		elf_hwcap &= ~HWCAP_HALF;
-		{
-			extern void init_dram_banks(struct param_struct *);
-			init_dram_banks(params);
-		}
 
 		switch (params->u1.s.pages_in_vram) {
 		case 512:
@@ -309,6 +382,17 @@
 		default:
 			break;
 		}
+		{
+			int i;
+
+			for (i = 0; i < 4; i++) {
+				meminfo.bank[i].start = i << 26;
+				meminfo.bank[i].size  =
+					params->u1.s.pages_in_bank[i] *
+					params->u1.s.page_size;
+			}
+			meminfo.nr_banks = 4;
+		}
 #endif
 	case MACH_TYPE_ARCHIMEDES:
 	case MACH_TYPE_A5K:
@@ -347,7 +431,7 @@
 		 */
 		reboot_setup("s", NULL);
 		params = NULL;
-		ORIG_VIDEO_LINES = 25;
+		ORIG_VIDEO_LINES  = 25;
 		ORIG_VIDEO_POINTS = 16;
 		ORIG_Y = 24;
 		video_ram.start = 0x0a0000;
@@ -393,7 +477,11 @@
 	}
 
 	if (params) {
-		memory_end	   = PAGE_SIZE * params->u1.s.nr_pages;
+		if (meminfo.nr_banks == 0) {
+			meminfo.nr_banks      = 1;
+			meminfo.bank[0].start = 0;
+			meminfo.bank[0].size  = params->u1.s.nr_pages << PAGE_SHIFT;
+		}
 		ROOT_DEV	   = to_kdev_t(params->u1.s.rootdev);
 		system_rev	   = params->u1.s.system_rev;
 		system_serial_low  = params->u1.s.system_serial_low;
@@ -413,24 +501,23 @@
 		from = params->commandline;
 	}
 
-	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
-	setup_mem(from, &memory_end);
-
-	memory_end += PAGE_OFFSET;
+	if (meminfo.nr_banks == 0) {
+		meminfo.nr_banks      = 1;
+		meminfo.bank[0].start = 0;
+		meminfo.bank[0].size  = MEM_SIZE;
+	}
 
-	*cmdline_p         = command_line;
 	init_mm.start_code = (unsigned long) &_text;
 	init_mm.end_code   = (unsigned long) &_etext;
 	init_mm.end_data   = (unsigned long) &_edata;
 	init_mm.brk	   = (unsigned long) &_end;
-	*memory_start_p    = (unsigned long) &_end;
-	*memory_end_p      = memory_end;
 
-	request_standard_resources(memory_end);
-	check_initrd(memory_end);
+	/* Save unparsed command line copy for /proc/cmdline */
+	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
+	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	parse_cmdline(cmdline_p, from);
+	setup_bootmem();
+	request_standard_resources();
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
diff -u --recursive --new-file v2.3.24/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c
--- v2.3.24/linux/arch/arm/kernel/sys_arm.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/sys_arm.c	Thu Oct 28 10:16:02 1999
@@ -29,8 +29,6 @@
 /*
  * Constant strings used in inlined functions in header files
  */
-/* proc/system.h */
-const char xchg_str[] = "xchg";
 
 /*
  * sys_pipe() is the normal C calling standard for creating
diff -u --recursive --new-file v2.3.24/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.3.24/linux/arch/arm/kernel/traps.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/traps.c	Thu Oct 28 10:16:02 1999
@@ -34,7 +34,10 @@
   "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
 };
 
-static char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+/* proc/system.h */
+const char xchg_str[] = "xchg";
+
+static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
 static inline void console_verbose(void)
 {
@@ -335,10 +338,11 @@
 	}
 
 #ifdef CONFIG_DEBUG_USER
-	printk(KERN_ERR "[%d] %s: old system call.\n", current->pid, 
-	       current->comm);
+	printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", current->pid, 
+	       current->comm, n);
 #endif
 	force_sig(SIGILL, current);
+	die_if_kernel("Oops", regs, n);
 }
 
 asmlinkage void arm_malalignedptr(const char *str, void *pc, volatile void *ptr)
@@ -385,8 +389,37 @@
 }
 #endif
 
+void __bug(const char *file, int line, void *data)
+{
+	printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
+	if (data)
+		printk(KERN_CRIT"extra data = %p\n", data);
+	*(int *)0 = 0;
+}
+
+void __readwrite_bug(const char *fn)
+{
+	printk("%s called, but not implemented", fn);
+	*(int *)0 = 0;
+}
+
+void __pte_error(const char *file, int line, unsigned long val)
+{
+	printk("%s:%d: bad pte %08lx.\n", file, line, val);
+}
+
+void __pmd_error(const char *file, int line, unsigned long val)
+{
+	printk("%s:%d: bad pmd %08lx.\n", file, line, val);
+}
+
+void __pgd_error(const char *file, int line, unsigned long val)
+{
+	printk("%s:%d: bad pgd %08lx.\n", file, line, val);
+}
+
 asmlinkage void __div0(void)
 {
-	printk("Awooga, division by zero in kernel.\n");
+	printk("Division by zero in kernel.\n");
 	__backtrace();
 }
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.3.24/linux/arch/arm/mm/fault-armv.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/fault-armv.c	Thu Oct 28 14:34:45 1999
@@ -90,6 +90,7 @@
 static unsigned long ai_word;
 static unsigned long ai_multi;
 
+#ifdef CONFIG_SYSCTL
 static int proc_alignment_read(char *page, char **start, off_t off,
 			       int count, int *eof, void *data)
 {
@@ -113,23 +114,18 @@
 	return len;
 }
 
-#ifdef CONFIG_SYSCTL
 /*
  * This needs to be done after sysctl_init, otherwise sys/
  * will be overwritten.
  */
 void __init alignment_init(void)
 {
-	struct proc_dir_entry *e;
-
-	e = create_proc_entry("sys/debug/alignment", S_IFREG | S_IRUGO, NULL);
-
-	if (e)
-		e->read_proc = proc_alignment_read;
+	create_proc_read_entry("sys/debug/alignment", 0, NULL,
+				proc_alignment_read);
 }
 
 __initcall(alignment_init);
-#endif
+#endif /* CONFIG_SYSCTL */
 
 static int
 do_alignment_exception(struct pt_regs *regs)
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/fault-common.c linux/arch/arm/mm/fault-common.c
--- v2.3.24/linux/arch/arm/mm/fault-common.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/fault-common.c	Thu Oct 28 10:16:02 1999
@@ -8,24 +8,6 @@
 
 extern void die(char *msg, struct pt_regs *regs, unsigned int err);
 
-void __bad_pmd(pmd_t *pmd)
-{
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-#ifdef CONFIG_DEBUG_ERRORS
-	__backtrace();
-#endif
-	set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
-}
-
-void __bad_pmd_kernel(pmd_t *pmd)
-{
-	printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
-#ifdef CONFIG_DEBUG_ERRORS
-	__backtrace();
-#endif
-	set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
-}
-
 /*
  * This is useful to dump out the page tables associated with
  * 'addr' in mm 'mm'.
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- v2.3.24/linux/arch/arm/mm/init.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/init.c	Thu Oct 28 10:16:02 1999
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/mm/init.c
  *
- *  Copyright (C) 1995-1999  Russell King
+ *  Copyright (C) 1995-1999 Russell King
  */
 
 #include <linux/config.h>
@@ -18,6 +18,7 @@
 #include <linux/swapctl.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
 #endif
@@ -27,74 +28,95 @@
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 #include <asm/hardware.h>
+#include <asm/setup.h>
 
 #include "map.h"
 
+static unsigned long totalram_pages;
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
-#ifndef CONFIG_NO_PGT_CACHE
-struct pgtable_cache_struct quicklists;
-#endif
 
-extern unsigned long free_area_init(unsigned long, unsigned long);
 extern void show_net_buffers(void);
 
-extern char _etext, _text, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
-
-int do_check_pgt_cache(int low, int high)
-{
-	int freed = 0;
-#ifndef CONFIG_NO_PGT_CACHE
-	if(pgtable_cache_size > high) {
-		do {
-			if(pgd_quicklist)
-				free_pgd_slow(get_pgd_fast()), freed++;
-			if(pmd_quicklist)
-				free_pmd_slow(get_pmd_fast()), freed++;
-			if(pte_quicklist)
-				free_pte_slow(get_pte_fast()), freed++;
-		} while(pgtable_cache_size > low);
-	}
-#endif
-	return freed;
-}
-
 /*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
+ * empty_bad_page is the page that is used for page faults when
+ * linux is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
  * for a process dying in kernel mode, possibly leaving a inode
  * unused etc..
  *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
+ * empty_bad_pte_table is the accompanying page-table: it is
+ * initialized to point to BAD_PAGE entries.
  *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
+ * empty_zero_page is a special page that is used for
+ * zero-initialized data and COW.
  */
-pte_t *empty_bad_page_table;
+struct page *empty_zero_page;
+struct page *empty_bad_page;
+pte_t *empty_bad_pte_table;
 
-pte_t *__bad_pagetable(void)
+pte_t *get_bad_pte_table(void)
 {
-	pte_t bad_page;
+	pte_t v;
 	int i;
 
-	bad_page = BAD_PAGE;
+	v = pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED));
+
 	for (i = 0; i < PTRS_PER_PTE; i++)
-		set_pte(empty_bad_page_table + i, bad_page);
+		set_pte(empty_bad_pte_table + i, v);
 
-	return empty_bad_page_table;
+	return empty_bad_pte_table;
 }
 
-unsigned long *empty_zero_page;
-unsigned long *empty_bad_page;
+void __handle_bad_pmd(pmd_t *pmd)
+{
+	pmd_ERROR(*pmd);
+#ifdef CONFIG_DEBUG_ERRORS
+	__backtrace();
+#endif
+	set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
+}
 
-pte_t __bad_page(void)
+void __handle_bad_pmd_kernel(pmd_t *pmd)
 {
-	memzero (empty_bad_page, PAGE_SIZE);
-	return pte_nocache(pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED)));
+	pmd_ERROR(*pmd);
+#ifdef CONFIG_DEBUG_ERRORS
+	__backtrace();
+#endif
+	set_pmd(pmd, mk_kernel_pmd(get_bad_pte_table()));
 }
 
+#ifndef CONFIG_NO_PGT_CACHE
+struct pgtable_cache_struct quicklists;
+
+int do_check_pgt_cache(int low, int high)
+{
+	int freed = 0;
+
+	if(pgtable_cache_size > high) {
+		do {
+			if(pgd_quicklist) {
+				free_pgd_slow(get_pgd_fast());
+				freed++;
+			}
+			if(pmd_quicklist) {
+				free_pmd_slow(get_pmd_fast());
+				freed++;
+			}
+			if(pte_quicklist) {
+				free_pte_slow(get_pte_fast());
+				 freed++;
+			}
+		} while(pgtable_cache_size > low);
+	}
+	return freed;
+}
+#else
+int do_check_pgt_cache(int low, int high)
+{
+	return 0;
+}
+#endif
+
 void show_mem(void)
 {
 	int free = 0, total = 0, reserved = 0;
@@ -104,23 +126,28 @@
 	printk("Mem-info:\n");
 	show_free_areas();
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	for (page = mem_map, end = mem_map + max_mapnr;
-	     page < end; page++) {
+
+	page = mem_map;
+	end  = mem_map + max_mapnr;
+
+	do {
 		if (PageSkip(page)) {
-			if (page->next_hash < page)
-				break;
 			page = page->next_hash;
+			if (page == NULL)
+				break;
 		}
 		total++;
 		if (PageReserved(page))
 			reserved++;
 		else if (PageSwapCache(page))
 			cached++;
-		else if (!atomic_read(&page->count))
+		else if (!page_count(page))
 			free++;
 		else
 			shared += atomic_read(&page->count) - 1;
-	}
+		page++;
+	} while (page < end);
+
 	printk("%d pages of RAM\n", total);
 	printk("%d free pages\n", free);
 	printk("%d reserved pages\n", reserved);
@@ -138,31 +165,42 @@
 /*
  * paging_init() sets up the page tables...
  */
-unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
+void __init paging_init(void)
 {
-	start_mem = PAGE_ALIGN(start_mem);
-
-	empty_zero_page = (unsigned long *)start_mem;
-	memzero(empty_zero_page, PAGE_SIZE);
-	start_mem += PAGE_SIZE;
-
-	empty_bad_page = (unsigned long *)start_mem;
-	start_mem += PAGE_SIZE;
+	void *zero_page, *bad_page, *bad_table;
 
 #ifdef CONFIG_CPU_32
-	start_mem += PTRS_PER_PTE * BYTES_PER_PTR;
+#define TABLE_OFFSET	(PTRS_PER_PTE)
+#else
+#define TABLE_OFFSET	0
 #endif
-	empty_bad_page_table = (pte_t *)start_mem;
-	start_mem += PTRS_PER_PTE * BYTES_PER_PTR;
-
-	start_mem = setup_page_tables(start_mem, end_mem);
+#define TABLE_SIZE	((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *))
 
+	/*
+	 * allocate what we need for the bad pages
+	 */
+	zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
+	bad_page  = alloc_bootmem_low_pages(PAGE_SIZE);
+	bad_table = alloc_bootmem_low_pages(TABLE_SIZE);
+
+	/*
+	 * initialise the page tables
+	 */
+	pagetable_init();
 	flush_tlb_all();
 
-	end_mem &= PAGE_MASK;
-	high_memory = (void *)end_mem;
+	free_area_init(max_low_pfn);
 
-	return free_area_init(start_mem, end_mem);
+	/*
+	 * finish off the bad pages once
+	 * the mem_map is initialised
+	 */
+	memzero(zero_page, PAGE_SIZE);
+	memzero(bad_page, PAGE_SIZE);
+
+	empty_zero_page = mem_map + MAP_NR(zero_page);
+	empty_bad_page  = mem_map + MAP_NR(bad_page);
+	empty_bad_pte_table = ((pte_t *)bad_table) + TABLE_OFFSET;
 }
 
 static inline void free_unused_mem_map(void)
@@ -184,7 +222,7 @@
 			high = ((unsigned long)page->next_hash) & PAGE_MASK;
 
 		while (low < high) {
-			clear_bit(PG_reserved, &mem_map[MAP_NR(low)].flags);
+			ClearPageReserved(mem_map + MAP_NR(low));
 			low += PAGE_SIZE;
 		}
 	}
@@ -195,67 +233,35 @@
  * memory is free.  This is done after various parts of the system have
  * claimed their memory after the kernel image.
  */
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+void __init mem_init(void)
 {
 	int codepages = 0;
 	int reservedpages = 0;
 	int datapages = 0;
 	int initpages = 0, i, min_nr;
-	unsigned long tmp;
 
-	end_mem      &= PAGE_MASK;
-	high_memory   = (void *)end_mem;
-	max_mapnr     = MAP_NR(end_mem);
-	num_physpages = 0;
+	max_mapnr     = max_low_pfn;
+	high_memory   = (void *)__va(max_low_pfn * PAGE_SIZE);
 
-	/* setup address validity bitmap */
-	start_mem = create_mem_holes(start_mem, end_mem);
-
-	start_mem = PAGE_ALIGN(start_mem);
-
-	/* mark usable pages in the mem_map[] */
-	mark_usable_memory_areas(start_mem, end_mem);
-
-	/* free unused mem_map[] entries */
-	free_unused_mem_map();
-
-#define BETWEEN(w,min,max) ((w) >= (unsigned long)(min) && \
-			    (w) < (unsigned long)(max))
-
-	for (tmp = PAGE_OFFSET; tmp < end_mem ; tmp += PAGE_SIZE) {
-		if (PageSkip(mem_map+MAP_NR(tmp))) {
-			unsigned long next;
-
-			next = mem_map[MAP_NR(tmp)].next_hash - mem_map;
-
-			next = (next << PAGE_SHIFT) + PAGE_OFFSET;
-
-			if (next < tmp || next >= end_mem)
-				break;
-			tmp = next;
-		}
-		num_physpages++;
-		if (PageReserved(mem_map+MAP_NR(tmp))) {
-			if (BETWEEN(tmp, &__init_begin, &__init_end))
-				initpages++;
-			else if (BETWEEN(tmp, &_text, &_etext))
-				codepages++;
-			else if (BETWEEN(tmp, &_etext, &_edata))
-				datapages++;
-			else if (BETWEEN(tmp, &__bss_start, start_mem))
-				datapages++;
-			else
-				reservedpages++;
-			continue;
-		}
-		atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (!initrd_start || !BETWEEN(tmp, initrd_start, initrd_end))
+#ifdef CONFIG_CPU_32
+	/*
+	 * We may have non-contiguous memory.  Setup the PageSkip stuff,
+	 * and mark the areas of mem_map which can be freed
+	 */
+	if (meminfo.nr_banks != 1)
+		create_memmap_holes();
 #endif
-			free_page(tmp);
-	}
 
-#undef BETWEEN
+	/* this will put all unused low memory onto the freelists */
+	totalram_pages += free_all_bootmem();
+
+	/*
+	 * Since our memory may not be contiguous, calculate the
+	 * real number of pages we have in this system
+	 */
+	num_physpages = 0;
+	for (i = 0; i < meminfo.nr_banks; i++)
+		num_physpages += meminfo.bank[i].size >> PAGE_SHIFT;
 
 	printk ("Memory: %luk/%luM available (%dk code, %dk reserved, %dk data, %dk init)\n",
 		 (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
@@ -265,6 +271,9 @@
 		 datapages     << (PAGE_SHIFT-10),
 		 initpages     << (PAGE_SHIFT-10));
 
+	/*
+	 * Correct freepages watermarks
+	 */
 	i = nr_free_pages >> 7;
 	if (PAGE_SIZE < 32768)
 		min_nr = 10;
@@ -288,22 +297,26 @@
 #endif
 }
 
-static void free_area(unsigned long addr, unsigned long end, char *s)
+static inline void free_area(unsigned long addr, unsigned long end, char *s)
 {
 	unsigned int size = (end - addr) >> 10;
+	struct page *page = mem_map + MAP_NR(addr);
 
-	for (; addr < end; addr += PAGE_SIZE) {
-		mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
-		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+	for (; addr < end; addr += PAGE_SIZE, page ++) {
+		ClearPageReserved(page);
+		set_page_count(page, 1);
 		free_page(addr);
+		totalram_pages++;
 	}
 
 	if (size)
 		printk(" %dk %s", size, s);
 }
 
-void free_initmem (void)
+void free_initmem(void)
 {
+	extern char __init_begin, __init_end;
+
 	printk("Freeing unused kernel memory:");
 
 	free_area((unsigned long)(&__init_begin),
@@ -333,28 +346,11 @@
 
 void si_meminfo(struct sysinfo *val)
 {
-	struct page *page, *end;
-
-	val->totalram = 0;
+	val->totalram  = totalram_pages;
 	val->sharedram = 0;
-	val->freeram = nr_free_pages << PAGE_SHIFT;
-	val->bufferram = atomic_read(&buffermem);
-	for (page = mem_map, end = mem_map + max_mapnr;
-	     page < end; page++) {
-		if (PageSkip(page)) {
-			if (page->next_hash < page)
-				break;
-			page = page->next_hash;
-		}
-		if (PageReserved(page))
-			continue;
-		val->totalram++;
-		if (!atomic_read(&page->count))
-			continue;
-		val->sharedram += atomic_read(&page->count) - 1;
-	}
-	val->totalram <<= PAGE_SHIFT;
-	val->sharedram <<= PAGE_SHIFT;
-	val->totalbig = 0;
-	val->freebig = 0;
+	val->freeram   = nr_free_pages;
+	val->bufferram = atomic_read(&buffermem_pages);
+	val->totalhigh = 0;
+	val->freehigh  = 0;
+	val->mem_unit  = PAGE_SIZE;
 }
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/map.h linux/arch/arm/mm/map.h
--- v2.3.24/linux/arch/arm/mm/map.h	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/map.h	Thu Oct 28 10:16:02 1999
@@ -16,17 +16,9 @@
 	    bufferable:1;
 };
 
-struct mem_desc {
-	unsigned long virt_start;
-	unsigned long virt_end;
-};
-
 extern struct map_desc	io_desc[];
 extern unsigned int	io_desc_size;
-extern struct mem_desc	mem_desc[];
-extern unsigned int	mem_desc_size;
 
-extern void mark_usable_memory_areas(unsigned long start, unsigned long end);
-extern unsigned long create_mem_holes(unsigned long start, unsigned long end);
-extern unsigned long setup_page_tables(unsigned long start, unsigned long end);
+extern void create_memmap_holes(void);
+extern void pagetable_init(void);
 
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/mm-armo.c linux/arch/arm/mm/mm-armo.c
--- v2.3.24/linux/arch/arm/mm/mm-armo.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/mm-armo.c	Thu Oct 28 10:16:02 1999
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -18,40 +19,54 @@
 #define MEMC_TABLE_SIZE (256*sizeof(unsigned long))
 #define PGD_TABLE_SIZE	(PTRS_PER_PGD * BYTES_PER_PTR)
 
-/*
- * FIXME: the following over-allocates by 6400%
- */
-static inline void *alloc_table(int size, int prio)
-{
-	if (size != 128)
-		printk("invalid table size\n");
-	return (void *)get_page_8k(prio);
-}
+int page_nr;
+
+extern unsigned long get_page_2k(int prio);
+extern void free_page_2k(unsigned long);
+extern pte_t *get_bad_pte_table(void);
 
 /*
  * Allocate a page table.  Note that we place the MEMC
  * table before the page directory.  This means we can
  * easily get to both tightly-associated data structures
- * with a single pointer.  This function is slightly
- * better - it over-allocates by only 711%
+ * with a single pointer.
+ *
+ * We actually only need 1152 bytes, 896 bytes is wasted.
+ * We could try to fit 7 PTEs into that slot somehow.
  */
 static inline void *alloc_pgd_table(int priority)
 {
-	unsigned long pg8k;
+	unsigned long pg2k;
 
-	pg8k = get_page_8k(priority);
-	if (pg8k)
-		pg8k += MEMC_TABLE_SIZE;
+	pg2k = get_page_2k(priority);
+	if (pg2k)
+		pg2k += MEMC_TABLE_SIZE;
 
-	return (void *)pg8k;
+	return (void *)pg2k;
 }
 
-void free_table(void *table)
+void free_pgd_slow(pgd_t *pgd)
 {
-	unsigned long tbl = (unsigned long)table;
+	unsigned long tbl = (unsigned long)pgd;
+
+	tbl -= MEMC_TABLE_SIZE;
+	free_page_2k(tbl);
+}
+
+/*
+ * FIXME: the following over-allocates by 1600%
+ */
+static inline void *alloc_pte_table(int size, int prio)
+{
+	if (size != 128)
+		printk("invalid table size\n");
+	return (void *)get_page_2k(prio);
+}
 
-	tbl &= ~8191;
-	free_page_8k(tbl);
+void free_pte_slow(pte_t *pte)
+{
+	unsigned long tbl = (unsigned long)pte;
+	free_page_2k(tbl);
 }
 
 pgd_t *get_pgd_slow(void)
@@ -62,9 +77,9 @@
 	if (pgd) {
 		pgd_t *init = pgd_offset(&init_mm, 0);
 		
-		memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+		memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t));
 		memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
-			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 
 		/*
 		 * On ARM, first page must always be allocated
@@ -92,7 +107,7 @@
 nomem_pmd:
 	pmd_free(new_pmd);
 nomem:
-	free_table(pgd);
+	free_pgd_slow(pgd);
 	return NULL;
 }
 
@@ -100,19 +115,19 @@
 {
 	pte_t *pte;
 
-	pte = (pte_t *)alloc_table(PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL);
+	pte = (pte_t *)alloc_pte_table(PTRS_PER_PTE * sizeof(pte_t), GFP_KERNEL);
 	if (pmd_none(*pmd)) {
 		if (pte) {
-			memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR);
-			set_pmd(pmd, mk_pmd(pte));
+			memzero(pte, PTRS_PER_PTE * sizeof(pte_t));
+			set_pmd(pmd, mk_user_pmd(pte));
 			return pte + offset;
 		}
-		set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+		set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
 		return NULL;
 	}
-	free_table((void *)pte);
+	free_pte_slow(pte);
 	if (pmd_bad(*pmd)) {
-		__bad_pmd(pmd);
+		__handle_bad_pmd(pmd);
 		return NULL;
 	}
 	return (pte_t *) pmd_page(*pmd) + offset;
@@ -124,47 +139,22 @@
  * some more work to get it to fit into our separate processor and
  * architecture structure.
  */
-int page_nr;
-
-#define PTE_SIZE	(PTRS_PER_PTE * BYTES_PER_PTR)
-
-static inline void setup_swapper_dir (int index, pte_t *ptep)
+void __init pagetable_init(void)
 {
-	set_pmd (pmd_offset (swapper_pg_dir + index, 0), mk_pmd (ptep));
-}
-
-unsigned long __init
-setup_page_tables(unsigned long start_mem, unsigned long end_mem)
-{
-	unsigned int i;
-	union { unsigned long l; pte_t *pte; } u;
+	pte_t *pte;
+	int i;
 
-	page_nr = MAP_NR(end_mem);
+	page_nr = max_low_pfn;
 
-	/* map in pages for (0x0000 - 0x8000) */
-	u.l = ((start_mem + (PTE_SIZE-1)) & ~(PTE_SIZE-1));
-	start_mem = u.l + PTE_SIZE;
-	memzero (u.pte, PTE_SIZE);
-	u.pte[0] = mk_pte(PAGE_OFFSET + 491520, PAGE_READONLY);
-	setup_swapper_dir (0, u.pte);
+	pte = alloc_bootmem_low_pages(PTRS_PER_PTE * sizeof(pte_t));
+	memzero(pte, PTRS_PER_PTE * sizeof(pte_t));
+	pte[0] = mk_pte_phys(PAGE_OFFSET + 491520, PAGE_READONLY);
+	set_pmd(pmd_offset(swapper_pg_dir, 0), mk_kernel_pmd(pte));
 
 	for (i = 1; i < PTRS_PER_PGD; i++)
 		pgd_val(swapper_pg_dir[i]) = 0;
-
-	return start_mem;
 }
 
-unsigned long __init
-create_mem_holes(unsigned long start, unsigned long end)
+void __init create_memmap_holes(void)
 {
-	return start;
-}
-
-void __init
-mark_usable_memory_areas(unsigned long start_mem, unsigned long end_mem)
-{
-	while (start_mem < end_mem) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-		start_mem += PAGE_SIZE;
-	}
 }
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- v2.3.24/linux/arch/arm/mm/mm-armv.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/mm-armv.c	Thu Oct 28 10:16:02 1999
@@ -1,22 +1,28 @@
 /*
- * arch/arm/mm/mm-armv.c
+ *  linux/arch/arm/mm/mm-armv.c
  *
- * Page table sludge for ARM v3 and v4 processor architectures.
+ *  Page table sludge for ARM v3 and v4 processor architectures.
  *
- * Copyright (C) 1998-1999 Russell King
+ *  Copyright (C) 1998-1999 Russell King
  */
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/io.h>
+#include <asm/setup.h>
 
 #include "map.h"
 
 unsigned long *valid_addr_bitmap;
 
+extern unsigned long get_page_2k(int priority);
+extern void free_page_2k(unsigned long page);
+extern pte_t *get_bad_pte_table(void);
+
 /*
  * need to get a 16k page for level 1
  */
@@ -26,12 +32,12 @@
 	pmd_t *new_pmd;
 
 	if (pgd) {
-		pgd_t *init = pgd_offset(&init_mm, 0);
+		pgd_t *init = pgd_offset_k(0);
 		
-		memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+		memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t));
 		memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
-			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
-		clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR);
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+		clean_cache_area(pgd, PTRS_PER_PGD * sizeof(pgd_t));
 
 		/*
 		 * On ARM, first page must always be allocated
@@ -48,7 +54,7 @@
 				pte_t *new_pte = pte_offset(new_pmd, 0);
 				pte_t *old_pte = pte_offset(old_pmd, 0);
 
-				set_pte (new_pte, *old_pte);
+				set_pte(new_pte, *old_pte);
 			}
 		}
 	}
@@ -61,6 +67,31 @@
 	return NULL;
 }
 
+void free_pgd_slow(pgd_t *pgd)
+{
+	if (pgd) { /* can pgd be NULL? */
+		pmd_t *pmd;
+		pte_t *pte;
+
+		/* pgd is always present and good */
+		pmd = (pmd_t *)pgd;
+		if (pmd_none(*pmd))
+			goto free;
+		if (pmd_bad(*pmd)) {
+			pmd_ERROR(*pmd);
+			pmd_clear(pmd);
+			goto free;
+		}
+
+		pte = pte_offset(pmd, 0);
+		pmd_clear(pmd);
+		pte_free(pte);
+		pmd_free(pmd);
+	}
+free:
+	free_pages((unsigned long) pgd, 2);
+}
+
 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
 {
 	pte_t *pte;
@@ -68,18 +99,18 @@
 	pte = (pte_t *)get_page_2k(GFP_KERNEL);
 	if (pmd_none(*pmd)) {
 		if (pte) {
-			memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR);
-			clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR);
+			memzero(pte, 2 * PTRS_PER_PTE * sizeof(pte_t));
+			clean_cache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
 			pte += PTRS_PER_PTE;
 			set_pmd(pmd, mk_user_pmd(pte));
 			return pte + offset;
 		}
-		set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
+		set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
 		return NULL;
 	}
 	free_page_2k((unsigned long)pte);
 	if (pmd_bad(*pmd)) {
-		__bad_pmd(pmd);
+		__handle_bad_pmd(pmd);
 		return NULL;
 	}
 	return (pte_t *) pmd_page(*pmd) + offset;
@@ -92,23 +123,28 @@
 	pte = (pte_t *)get_page_2k(GFP_KERNEL);
 	if (pmd_none(*pmd)) {
 		if (pte) {
-			memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR);
-			clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR);
+			memzero(pte, 2 * PTRS_PER_PTE * sizeof(pte_t));
+			clean_cache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
 			pte += PTRS_PER_PTE;
 			set_pmd(pmd, mk_kernel_pmd(pte));
 			return pte + offset;
 		}
-		set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
+		set_pmd(pmd, mk_kernel_pmd(get_bad_pte_table()));
 		return NULL;
 	}
 	free_page_2k((unsigned long)pte);
 	if (pmd_bad(*pmd)) {
-		__bad_pmd_kernel(pmd);
+		__handle_bad_pmd_kernel(pmd);
 		return NULL;
 	}
 	return (pte_t *) pmd_page(*pmd) + offset;
 }
 
+void free_pte_slow(pte_t *pte)
+{
+	free_page_2k((unsigned long)(pte - PTRS_PER_PTE));
+}
+
 /*
  * Create a SECTION PGD between VIRT and PHYS in domain
  * DOMAIN with protection PROT
@@ -131,34 +167,22 @@
  * the hardware pte table.
  */
 static inline void
-alloc_init_page(unsigned long *mem, unsigned long virt, unsigned long phys, int domain, int prot)
+alloc_init_page(unsigned long virt, unsigned long phys, int domain, int prot)
 {
 	pmd_t *pmdp;
 	pte_t *ptep;
 
 	pmdp = pmd_offset(pgd_offset_k(virt), virt);
 
-#define PTE_SIZE (PTRS_PER_PTE * BYTES_PER_PTR)
-
 	if (pmd_none(*pmdp)) {
-		unsigned long memory = *mem;
-
-		memory = (memory + PTE_SIZE - 1) & ~(PTE_SIZE - 1);
+		pte_t *ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
+						      sizeof(pte_t));
 
-		ptep = (pte_t *)memory;
-		memzero(ptep, PTE_SIZE);
-		memory += PTE_SIZE;
-
-		ptep = (pte_t *)memory;
-		memzero(ptep, PTE_SIZE);
+		memzero(ptep, 2 * PTRS_PER_PTE * sizeof(pte_t));
+		ptep += PTRS_PER_PTE;
 
 		set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain)));
-
-		*mem = memory + PTE_SIZE;
 	}
-
-#undef PTE_SIZE
-
 	ptep = pte_offset(pmdp, virt);
 
 	set_pte(ptep, mk_pte_phys(phys, __pgprot(prot)));
@@ -169,8 +193,7 @@
  * the clearance is done by the middle-level functions (pmd)
  * rather than the top-level (pgd) functions.
  */
-static inline void
-free_init_section(unsigned long virt)
+static inline void free_init_section(unsigned long virt)
 {
 	pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
 }
@@ -181,8 +204,7 @@
  * are able to cope here with varying sizes and address
  * offsets, and we take full advantage of sections.
  */
-static void __init
-create_mapping(unsigned long *mem_ptr, struct map_desc *md)
+static void __init create_mapping(struct map_desc *md)
 {
 	unsigned long virt, length;
 	int prot_sect, prot_pte;
@@ -205,7 +227,7 @@
 	length = md->length;
 
 	while ((virt & 1048575 || (virt + off) & 1048575) && length >= PAGE_SIZE) {
-		alloc_init_page(mem_ptr, virt, virt + off, md->domain, prot_pte);
+		alloc_init_page(virt, virt + off, md->domain, prot_pte);
 
 		virt   += PAGE_SIZE;
 		length -= PAGE_SIZE;
@@ -219,7 +241,7 @@
 	}
 
 	while (length >= PAGE_SIZE) {
-		alloc_init_page(mem_ptr, virt, virt + off, md->domain, prot_pte);
+		alloc_init_page(virt, virt + off, md->domain, prot_pte);
 
 		virt   += PAGE_SIZE;
 		length -= PAGE_SIZE;
@@ -227,17 +249,15 @@
 }
 
 /*
- * Initial boot-time mapping.  This covers just the
- * zero page, kernel and the flush area.  NB: it
- * must be sorted by virtual address, and no
+ * Initial boot-time mapping.  This covers just the zero page, kernel and
+ * the flush area.  NB: it must be sorted by virtual address, and no
  * virtual address overlaps.
- *  init_map[2..4] are for architectures with small
- *  amounts of banked memory.
+ *  init_map[2..4] are for architectures with banked memory.
  */
 static struct map_desc init_map[] __initdata = {
 	{ 0, 0, PAGE_SIZE,  DOMAIN_USER,   0, 0, 1, 0 }, /* zero page     */
 	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 }, /* kernel memory */
-	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 },
+	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 }, /* (4 banks)	  */
 	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 },
 	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 },
 	{ 0, 0, PGDIR_SIZE, DOMAIN_KERNEL, 1, 0, 1, 1 }, /* cache flush 1 */
@@ -246,19 +266,15 @@
 
 #define NR_INIT_MAPS (sizeof(init_map) / sizeof(init_map[0]))
 
-unsigned long __init
-setup_page_tables(unsigned long start_mem, unsigned long end_mem)
+void __init pagetable_init(void)
 {
 	unsigned long address = 0;
-	int idx = 0;
+	int i;
 
 	/*
-	 * Correct the above mappings
+	 * Setup the above mappings
 	 */
-	init_map[0].physical =
-	init_map[1].physical = __virt_to_phys(PAGE_OFFSET);
-	init_map[1].virtual  = PAGE_OFFSET;
-	init_map[1].length   = end_mem - PAGE_OFFSET;
+	init_map[0].physical = PHYS_OFFSET;
 	init_map[5].physical = FLUSH_BASE_PHYS;
 	init_map[5].virtual  = FLUSH_BASE;
 #ifdef FLUSH_BASE_MINICACHE
@@ -267,109 +283,108 @@
 	init_map[6].length   = PGDIR_SIZE;
 #endif
 
+	for (i = 0; i < meminfo.nr_banks; i++) {
+		init_map[i+1].physical = PHYS_OFFSET + meminfo.bank[i].start;
+		init_map[i+1].virtual  = PAGE_OFFSET + meminfo.bank[i].start;
+		init_map[i+1].length   = meminfo.bank[i].size;
+	}
+
 	/*
-	 * Firstly, go through the initial mappings,
-	 * but clear out any pgdir entries that are
-	 * not in the description.
+	 * Go through the initial mappings, but clear out any
+	 * pgdir entries that are not in the description.
 	 */
+	i = 0;
 	do {
-		if (address < init_map[idx].virtual || idx == NR_INIT_MAPS) {
+		if (address < init_map[i].virtual || i == NR_INIT_MAPS) {
 			free_init_section(address);
 			address += PGDIR_SIZE;
 		} else {
-			create_mapping(&start_mem, init_map + idx);
+			create_mapping(init_map + i);
 
-			address = init_map[idx].virtual + init_map[idx].length;
+			address = init_map[i].virtual + init_map[i].length;
 			address = (address + PGDIR_SIZE - 1) & PGDIR_MASK;
 
 			do {
-				idx += 1;
-			} while (init_map[idx].length == 0 && idx < NR_INIT_MAPS);
+				i += 1;
+			} while (init_map[i].length == 0 && i < NR_INIT_MAPS);
 		}
 	} while (address != 0);
 
 	/*
-	 * Now, create the architecture specific mappings
+	 * Create the architecture specific mappings
 	 */
-	for (idx = 0; idx < io_desc_size; idx++)
-		create_mapping(&start_mem, io_desc + idx);
+	for (i = 0; i < io_desc_size; i++)
+		create_mapping(io_desc + i);
 
 	flush_cache_all();
-
-	return start_mem;
 }
 
 /*
- * The mem_map array can get very big.  Mark the end of the
- * valid mem_map banks with PG_skip, and setup the address
- * validity bitmap.
+ * The mem_map array can get very big.  Mark the end of the valid mem_map
+ * banks with PG_skip, and setup the address validity bitmap.
  */
-unsigned long __init
-create_mem_holes(unsigned long start_mem, unsigned long end_mem)
+void __init create_memmap_holes(void)
 {
+	unsigned int start_pfn, end_pfn = -1;
 	struct page *pg = NULL;
 	unsigned int sz, i;
 
-	if (!machine_is_riscpc())
-		return start_mem;
+	for (i = 0; i < meminfo.nr_banks; i++) {
+		if (meminfo.bank[i].size == 0)
+			continue;
 
-	sz = (end_mem - PAGE_OFFSET) >> 20;
-	sz = (sz + 31) >> 3;
-
-	valid_addr_bitmap = (unsigned long *)start_mem;
-	start_mem += sz;
+		start_pfn = meminfo.bank[i].start >> PAGE_SHIFT;
 
-	memset(valid_addr_bitmap, 0, sz);
+		/*
+		 * subtle here - if we have a full bank, then
+		 * start_pfn == end_pfn, and we don't want to
+		 * set PG_skip, or next_hash
+		 */
+		if (pg && start_pfn != end_pfn) {
+			set_bit(PG_skip, &pg->flags);
+			pg->next_hash = mem_map + start_pfn;
 
-	if (start_mem > mem_desc[0].virt_end)
-		printk(KERN_CRIT "*** Error: RAM bank 0 too small\n");
+			start_pfn = PAGE_ALIGN(__pa(pg + 1));
+			end_pfn   = __pa(pg->next_hash) & PAGE_MASK;
 
-	for (i = 0; i < mem_desc_size; i++) {
-		unsigned int idx, end;
+			if (end_pfn != start_pfn)
+				free_bootmem(start_pfn, end_pfn - start_pfn);
 
-		if (pg) {
-			pg->next_hash = mem_map +
-				 MAP_NR(mem_desc[i].virt_start);
 			pg = NULL;
 		}
 
-		idx = __kern_valid_idx(mem_desc[i].virt_start);
-		end = __kern_valid_idx(mem_desc[i].virt_end);
-
-		do
-			set_bit(idx, valid_addr_bitmap);
-		while (++idx < end);
-
-		if (mem_desc[i].virt_end < end_mem) {
-			pg = mem_map + MAP_NR(mem_desc[i].virt_end);
+		end_pfn = (meminfo.bank[i].start +
+			   meminfo.bank[i].size) >> PAGE_SHIFT;
 
-			set_bit(PG_skip, &pg->flags);
-		}
+		if (end_pfn != meminfo.end >> PAGE_SHIFT)
+			pg = mem_map + end_pfn;
 	}
 
-	if (pg)
+	if (pg) {
+		set_bit(PG_skip, &pg->flags);
 		pg->next_hash = NULL;
-
-	return start_mem;
-}
-
-void __init
-mark_usable_memory_areas(unsigned long start_mem, unsigned long end_mem)
-{
-	/*
-	 * Mark all of memory from the end of kernel to end of memory
-	 */
-	while (start_mem < end_mem) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-		start_mem += PAGE_SIZE;
 	}
 
+#if 0
 	/*
-	 * Mark memory from page 1 to start of the swapper page directory
+	 * setup address validity map
+	 *  - don't think this is used anymore?
 	 */
-	start_mem = PAGE_OFFSET + PAGE_SIZE;
-	while (start_mem < (unsigned long)&swapper_pg_dir) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-		start_mem += PAGE_SIZE;
+	sz = meminfo.end >> (PAGE_SHIFT + 8); /* in MB */
+	sz = (sz + 31) >> 3;
+
+	valid_addr_bitmap = alloc_bootmem(sz);
+	memzero(valid_addr_bitmap, sz);
+
+	for (i = 0; i < meminfo.nr_banks; i++) {
+		int idx, end;
+
+		idx = meminfo.bank[i].start >> 20;
+		end = (meminfo.bank[i].start +
+		       meminfo.bank[i].size) >> 20;
+		do
+			set_bit(idx, valid_addr_bitmap);
+		while (++idx < end);
 	}
-}	
+#endif
+}
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/mm-ebsa110.c linux/arch/arm/mm/mm-ebsa110.c
--- v2.3.24/linux/arch/arm/mm/mm-ebsa110.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/mm-ebsa110.c	Fri Oct 29 11:42:57 1999
@@ -13,17 +13,11 @@
 
 #include "map.h"
  
-struct mem_desc mem_desc[] __initdata = {
-	0, 0
-};
-
-unsigned int __initdata mem_desc_size = 0;
+#define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
 const struct map_desc io_desc[] __initdata = {
 	{ IO_BASE - PGDIR_SIZE, 0xc0000000, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
 	{ IO_BASE             , IO_START  , IO_SIZE   , DOMAIN_IO, 0, 1, 0, 0 }
 };
 
-#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0]))
-
-unsigned int __initdata io_desc_size = SIZEOFMAP;
+unsigned int __initdata io_desc_size = SIZE(io_desc);
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/mm-footbridge.c linux/arch/arm/mm/mm-footbridge.c
--- v2.3.24/linux/arch/arm/mm/mm-footbridge.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/mm-footbridge.c	Fri Oct 29 11:42:57 1999
@@ -17,6 +17,8 @@
 
 #include "map.h"
 
+#define SIZE(x) (sizeof(x) / sizeof(x[0]))
+
 /*
  * The first entry allows us to fiddle with the EEPROM from user-space.
  *  This entry will go away in time, once the fmu32 can mmap() the
@@ -89,17 +91,9 @@
 
 #endif
 
-struct mem_desc mem_desc[] __initdata = {
-	0, 0
-};
-
-unsigned int __initdata mem_desc_size = 0;
-
 struct map_desc io_desc[] __initdata = {
 	MAPPING
 };
-
-#define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
 unsigned int __initdata io_desc_size = SIZE(io_desc);
 
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/mm-nexuspci.c linux/arch/arm/mm/mm-nexuspci.c
--- v2.3.24/linux/arch/arm/mm/mm-nexuspci.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/mm-nexuspci.c	Fri Oct 29 11:42:57 1999
@@ -18,11 +18,7 @@
 
 #include "map.h"
  
-struct mem_desc mem_desc[] __initdata = {
-	0, 0
-};
-
-unsigned int __initdata mem_desc_size = 0;
+#define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
 const struct map_desc io_desc[] __initdata = {
  	{ 0xfff00000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
@@ -32,6 +28,4 @@
  	{ 0xfd000000, 0x88000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }
 };
 
-#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0]))
-
-unsigned int __initdata io_desc_size = SIZEOFMAP;
+unsigned int __initdata io_desc_size = SIZE(io_desc);
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/mm-rpc.c linux/arch/arm/mm/mm-rpc.c
--- v2.3.24/linux/arch/arm/mm/mm-rpc.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/mm-rpc.c	Thu Oct 28 10:16:02 1999
@@ -16,28 +16,6 @@
 
 #define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
-struct mem_desc mem_desc[] __initdata = {
-	{ 0xc0000000, 0xc0000000 },
-	{ 0xc4000000, 0xc4000000 },
-	{ 0xc8000000, 0xc8000000 },
-	{ 0xcc000000, 0xcc000000 }
-};
-
-unsigned int __initdata mem_desc_size = SIZE(mem_desc);
-
-void __init
-init_dram_banks(struct param_struct *params)
-{
-	unsigned int bank;
-
-	for (bank = 0; bank < mem_desc_size; bank++)
-		mem_desc[bank].virt_end += PAGE_SIZE *
-				  params->u1.s.pages_in_bank[bank];
-
-	params->u1.s.nr_pages = mem_desc[3].virt_end - PAGE_OFFSET;
-	params->u1.s.nr_pages /= PAGE_SIZE;
-}
-
 struct map_desc io_desc[] __initdata = {
 	/* VRAM		*/
 	{ SCREEN2_BASE,	SCREEN_START,	2*1048576, DOMAIN_IO, 0, 1, 0, 0 },
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/mm-tbox.c linux/arch/arm/mm/mm-tbox.c
--- v2.3.24/linux/arch/arm/mm/mm-tbox.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/mm-tbox.c	Fri Oct 29 11:42:57 1999
@@ -18,11 +18,7 @@
 
 #include "map.h"
  
-struct mem_desc mem_desc[] __initdata = {
-	0, 0
-};
-
-unsigned int __initdata mem_desc_size = 0;
+#define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
 /*    Logical    Physical
  * 0xffff1000	0x00100000	DMA registers
@@ -60,6 +56,4 @@
  	{ 0xffffe000, 0x00e00000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }
 };
 
-#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0]))
-
-unsigned int __initdata io_desc_size = SIZEOFMAP;
+unsigned int __initdata io_desc_size = SIZE(io_desc);
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/proc-arm2,3.S linux/arch/arm/mm/proc-arm2,3.S
--- v2.3.24/linux/arch/arm/mm/proc-arm2,3.S	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/proc-arm2,3.S	Thu Oct 28 10:16:02 1999
@@ -327,7 +327,7 @@
 arm3_elf_name:	.asciz	"v2"
 		.align
 
-		.section ".proc.info", #alloc
+		.section ".proc.info", #alloc, #execinstr
 
 		.long	0x41560200
 		.long	0xfffffff0
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S
--- v2.3.24/linux/arch/arm/mm/proc-arm6,7.S	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/proc-arm6,7.S	Thu Oct 28 10:16:02 1999
@@ -532,7 +532,7 @@
 		.size	cpu_elf_name, . - cpu_elf_name
 		.align
 
-		.section ".proc.info", #alloc
+		.section ".proc.info", #alloc, #execinstr
 
 		.type	__arm6_proc_info, #object
 __arm6_proc_info:
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S
--- v2.3.24/linux/arch/arm/mm/proc-sa110.S	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/proc-sa110.S	Thu Oct 28 10:16:02 1999
@@ -446,7 +446,8 @@
 		bl	cpu_sa110_flush_tlb_all
 		mcr	p15, 0, ip, c7, c7, 0		@ flush I,D caches
 		mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
-		bic	r0, r0, #1			@ ...............m
+		bic	r0, r0, #0x000f			@ ............wcam
+		bic	r0, r0, #0x1100			@ ...i...s........
 		ldmfd	sp!, {r1, pc}
 /*
  * Purpose : Function pointers used to access above functions - all calls
@@ -546,6 +547,7 @@
 		.align
 
 		.section ".proc.info", #alloc, #execinstr
+
 		.type	__sa110_proc_info,#object
 __sa110_proc_info:
 		.long	0x4401a100
diff -u --recursive --new-file v2.3.24/linux/arch/arm/mm/small_page.c linux/arch/arm/mm/small_page.c
--- v2.3.24/linux/arch/arm/mm/small_page.c	Sat May  8 11:06:57 1999
+++ linux/arch/arm/mm/small_page.c	Thu Oct 28 10:16:02 1999
@@ -21,205 +21,201 @@
 #include <linux/swap.h>
 #include <linux/smp.h>
 
-#if PAGE_SIZE == 4096
-/* 2K blocks */
-#define SMALL_ALLOC_SHIFT	(11)
-#define NAME(x)			x##_2k
-#elif PAGE_SIZE == 32768 || PAGE_SIZE == 16384
-/* 8K blocks */
-#define SMALL_ALLOC_SHIFT	(13)
-#define NAME(x)			x##_8k
-#endif
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
 
-#define SMALL_ALLOC_SIZE	(1 << SMALL_ALLOC_SHIFT)
-#define NR_BLOCKS		(PAGE_SIZE / SMALL_ALLOC_SIZE)
-#define BLOCK_MASK		((1 << NR_BLOCKS) - 1)
-
-#define USED(pg)		((atomic_read(&(pg)->count) >> 8) & BLOCK_MASK)
-#define SET_USED(pg,off)	(atomic_read(&(pg)->count) |= 256 << off)
-#define CLEAR_USED(pg,off)	(atomic_read(&(pg)->count) &= ~(256 << off))
-#define ALL_USED		BLOCK_MASK
-#define IS_FREE(pg,off)		(!(atomic_read(&(pg)->count) & (256 << off)))
-#define SM_PAGE_PTR(page,block)	((struct free_small_page *)((page) + \
-					((block) << SMALL_ALLOC_SHIFT)))
+#define PEDANTIC
 
-#if NR_BLOCKS != 2 && NR_BLOCKS != 4
-#error I only support 2 or 4 blocks per page
-#endif
+/*
+ * Requirement:
+ *  We need to be able to allocate naturally aligned memory of finer
+ *  granularity than the page size.  This is typically used for the
+ *  second level page tables on 32-bit ARMs.
+ *
+ * Theory:
+ *  We "misuse" the Linux memory management system.  We use __get_pages
+ *  to allocate a page and then mark it as reserved.  The Linux memory
+ *  management system will then ignore the "offset", "next_hash" and
+ *  "pprev_hash" entries in the mem_map for this page.
+ *
+ *  We then use a bitstring in the "offset" field to mark which segments
+ *  of the page are in use, and manipulate this as required during the
+ *  allocation and freeing of these small pages.
+ *
+ *  We also maintain a queue of pages being used for this purpose using
+ *  the "next_hash" and "pprev_hash" entries of mem_map;
+ */
 
-struct free_small_page {
-	unsigned long next;
-	unsigned long prev;
+struct order {
+	struct page *queue;
+	unsigned int mask;		/* (1 << shift) - 1		*/
+	unsigned int shift;		/* (1 << shift) size of page	*/
+	unsigned int block_mask;	/* nr_blocks - 1		*/
+	unsigned int all_used;		/* (1 << nr_blocks) - 1		*/
 };
 
-/*
- * To handle allocating small pages, we use the main get_free_page routine,
- * and split the page up into 4.  The page is marked in mem_map as reserved,
- * so it can't be free'd by free_page.  The count field is used to keep track
- * of which sections of this page are allocated.
- */
-static unsigned long small_page_ptr;
 
-static unsigned char offsets[1<<NR_BLOCKS] = {
-	0,	/* 0000 */
-	1,	/* 0001 */
-	0,	/* 0010 */
-	2,	/* 0011 */
-#if NR_BLOCKS == 4
-	0,	/* 0100 */
-	1,	/* 0101 */
-	0,	/* 0110 */
-	3,	/* 0111 */
-	0,	/* 1000 */
-	1,	/* 1001 */
-	0,	/* 1010 */
-	2,	/* 1011 */
-	0,	/* 1100 */
-	1,	/* 1101 */
-	0,	/* 1110 */
-	4	/* 1111 */
+static struct order orders[] = {
+#if PAGE_SIZE == 4096
+	{ NULL, 2047, 11,  1, 0x00000003 }
+#elif PAGE_SIZE == 32768
+	{ NULL, 2047, 11, 15, 0x0000ffff },
+	{ NULL, 8191, 13,  3, 0x0000000f }
+#else
+#error unsupported page size
 #endif
 };
 
-static inline void clear_page_links(unsigned long page)
-{
-	struct free_small_page *fsp;
-	int i;
-
-	for (i = 0; i < NR_BLOCKS; i++) {
-		fsp = SM_PAGE_PTR(page, i);
-		fsp->next = fsp->prev = 0;
-	}
-}
+#define USED_MAP(pg)			((pg)->offset)
+#define TEST_AND_CLEAR_USED(pg,off)	(test_and_clear_bit(off, &(pg)->offset))
+#define SET_USED(pg,off)		(set_bit(off, &(pg)->offset))
 
-static inline void set_page_links_prev(unsigned long page, unsigned long prev)
+static void add_page_to_queue(struct page *page, struct page **p)
 {
-	struct free_small_page *fsp;
-	unsigned int mask;
-	int i;
-
-	if (!page)
-		return;
-
-	mask = USED(&mem_map[MAP_NR(page)]);
-	for (i = 0; i < NR_BLOCKS; i++) {
-		if (mask & (1 << i))
-			continue;
-		fsp = SM_PAGE_PTR(page, i);
-		fsp->prev = prev;
-	}
+#ifdef PEDANTIC
+	if (page->pprev_hash)
+		PAGE_BUG(page);
+#endif
+	page->next_hash = *p;
+	if (*p)
+		(*p)->pprev_hash = &page->next_hash;
+	*p = page;
+	page->pprev_hash = p;
 }
 
-static inline void set_page_links_next(unsigned long page, unsigned long next)
+static void remove_page_from_queue(struct page *page)
 {
-	struct free_small_page *fsp;
-	unsigned int mask;
-	int i;
-
-	if (!page)
-		return;
-
-	mask = USED(&mem_map[MAP_NR(page)]);
-	for (i = 0; i < NR_BLOCKS; i++) {
-		if (mask & (1 << i))
-			continue;
-		fsp = SM_PAGE_PTR(page, i);
-		fsp->next = next;
+	if (page->pprev_hash) {
+		if (page->next_hash)
+			page->next_hash->pprev_hash = page->pprev_hash;
+		*page->pprev_hash = page->next_hash;
+		page->pprev_hash = NULL;
 	}
 }
 
-unsigned long NAME(get_page)(int priority)
+static unsigned long __get_small_page(int priority, struct order *order)
 {
-	struct free_small_page *fsp;
-	unsigned long new_page;
 	unsigned long flags;
 	struct page *page;
 	int offset;
 
 	save_flags(flags);
-	if (!small_page_ptr)
+	if (!order->queue)
 		goto need_new_page;
+
 	cli();
+	page = order->queue;
 again:
-	page = mem_map + MAP_NR(small_page_ptr);
-	offset = offsets[USED(page)];
+#ifdef PEDANTIC
+	if (USED_MAP(page) & ~order->all_used)
+		PAGE_BUG(page);
+#endif
+	offset = ffz(USED_MAP(page));
 	SET_USED(page, offset);
-	new_page = (unsigned long)SM_PAGE_PTR(small_page_ptr, offset);
-	if (USED(page) == ALL_USED) {
-		fsp = (struct free_small_page *)new_page;
-		set_page_links_prev (fsp->next, 0);
-		small_page_ptr = fsp->next;
-	}
+	if (USED_MAP(page) == order->all_used)
+		remove_page_from_queue(page);
 	restore_flags(flags);
-	return new_page;
+
+	return page_address(page) + (offset << order->shift);
 
 need_new_page:
-	new_page = __get_free_page(priority);
-	if (!small_page_ptr) {
-		if (new_page) {
-			set_bit (PG_reserved, &mem_map[MAP_NR(new_page)].flags);
-			clear_page_links (new_page);
-			cli();
-			small_page_ptr = new_page;
-			goto again;
-		}
-		restore_flags(flags);
-		return 0;
+	page = __get_pages(priority, 0);
+	if (!order->queue) {
+		if (!page)
+			goto no_page;
+		SetPageReserved(page);
+		USED_MAP(page) = 0;
+		cli();
+		add_page_to_queue(page, &order->queue);
+	} else {
+		__free_page(page);
+		cli();
+		page = order->queue;
 	}
-	free_page(new_page);
-	cli();
 	goto again;
+
+no_page:
+	restore_flags(flags);
+	return 0;
 }
 
-void NAME(free_page)(unsigned long spage)
+static void __free_small_page(unsigned long spage, struct order *order)
 {
-	struct free_small_page *ofsp, *cfsp;
 	unsigned long flags;
+	unsigned long nr;
 	struct page *page;
-	int offset, oldoffset;
 
-	if (!spage)
-		goto none;
+	nr = MAP_NR(spage);
+	if (nr < max_mapnr) {
+		page = mem_map + nr;
+
+		/*
+		 * The container-page must be marked Reserved
+		 */
+		if (!PageReserved(page) || spage & order->mask)
+			goto non_small;
+
+#ifdef PEDANTIC
+		if (USED_MAP(page) & ~order->all_used)
+			PAGE_BUG(page);
+#endif
+
+		spage = spage >> order->shift;
+		spage &= order->block_mask;
+
+		/*
+		 * the following must be atomic wrt get_page
+		 */
+		save_flags_cli(flags);
 
-	offset = (spage >> SMALL_ALLOC_SHIFT) & (NR_BLOCKS - 1);
-	spage -= offset << SMALL_ALLOC_SHIFT;
+		if (USED_MAP(page) == order->all_used)
+			add_page_to_queue(page, &order->queue);
+
+		if (!TEST_AND_CLEAR_USED(page, spage))
+			goto already_free;
+
+		if (USED_MAP(page) == 0)
+			goto free_page;
 
-	page = mem_map + MAP_NR(spage);
-	if (!PageReserved(page) || !USED(page))
-		goto non_small;
-
-	if (IS_FREE(page, offset))
-		goto free;
-
-	save_flags_cli (flags);
-	oldoffset = offsets[USED(page)];
-	CLEAR_USED(page, offset);
-	ofsp = SM_PAGE_PTR(spage, oldoffset);
-	cfsp = SM_PAGE_PTR(spage, offset);
-
-	if (oldoffset == NR_BLOCKS) { /* going from totally used to mostly used */
-		cfsp->prev = 0;
-		cfsp->next = small_page_ptr;
-		set_page_links_prev (small_page_ptr, spage);
-		small_page_ptr = spage;
-	} else if (!USED(page)) {
-		set_page_links_prev (ofsp->next, ofsp->prev);
-		set_page_links_next (ofsp->prev, ofsp->next);
-		if (spage == small_page_ptr)
-			small_page_ptr = ofsp->next;
-		clear_bit (PG_reserved, &page->flags);
 		restore_flags(flags);
-		free_page (spage);
-	} else
-		*cfsp = *ofsp;
+	}
+	return;
+
+free_page:
+	/*
+	 * unlink the page from the small page queue and free it
+	 */
+	remove_page_from_queue(page);
 	restore_flags(flags);
+	ClearPageReserved(page);
+	__free_page(page);
 	return;
 
 non_small:
-	printk ("Trying to free non-small page from %p\n", __builtin_return_address(0));
-	return;
-free:
-	printk ("Trying to free free small page from %p\n", __builtin_return_address(0));
-none:
+	printk("Trying to free non-small page from %p\n", __builtin_return_address(0));
 	return;
+already_free:
+	printk("Trying to free free small page from %p\n", __builtin_return_address(0));
+}
+
+unsigned long get_page_2k(int priority)
+{
+	return __get_small_page(priority, orders+0);
+}
+
+void free_page_2k(unsigned long spage)
+{
+	__free_small_page(spage, orders+0);
 }
+
+#if PAGE_SIZE > 8192
+unsigned long get_page_8k(int priority)
+{
+	return __get_small_page(priority, orders+1);
+}
+
+void free_page_8k(unsigned long spage)
+{
+	__free_small_page(spage, orders+1);
+}
+#endif
diff -u --recursive --new-file v2.3.24/linux/arch/arm/vmlinux-armo.lds.in linux/arch/arm/vmlinux-armo.lds.in
--- v2.3.24/linux/arch/arm/vmlinux-armo.lds.in	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/vmlinux-armo.lds.in	Thu Oct 28 10:16:02 1999
@@ -7,7 +7,8 @@
 SECTIONS
 {
   . = TEXTADDR;
-  __init_begin = .;
+
+  __init_begin = .;		/* Init code and data		*/
   .text.init : { *(.text.init) }
   __proc_info_begin = .;
   .proc.info : { *(.proc.info) }
@@ -27,43 +28,44 @@
 	*(.init.task)
   }
 
-  _text = .;			/* Text and read-only data */
+  _text = .;			/* Text and read-only data	*/
   .text : {
 	*(.text)
 	*(.fixup)
 	*(.gnu.warning)
 	}
+
   .text.lock : { *(.text.lock) }	/* out-of-line lock text */
   .rodata : { *(.rodata) }
   .kstrtab : { *(.kstrtab) }
 
-  . = ALIGN(16);		/* Exception table */
+  . = ALIGN(16);		/* Exception table		*/
   __start___ex_table = .;
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
 
-  __start___ksymtab = .;	/* Kernel symbol table */
+  __start___ksymtab = .;	/* Kernel symbol table		*/
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
-  .got : { *(.got) }		/* Global offset table */
+  .got : { *(.got) }		/* Global offset table		*/
 
-  _etext = .;			/* End of text section */
+  _etext = .;			/* End of text section		*/
 
-  .data : {			/* Data */
+  .data : {			/* Data				*/
 	*(.data)
 	CONSTRUCTORS
 	}
 
-  _edata = .;			/* End of data section */
+  _edata = .;			/* End of data section		*/
 
-  __bss_start = .;		/* BSS */
+  __bss_start = .;		/* BSS				*/
   .bss : {
 	*(.bss)
 	}
   _end = . ;
 
-  /* Stabs debugging sections.  */
+				/* Stabs debugging sections.	*/
   .stab 0 : { *(.stab) }
   .stabstr 0 : { *(.stabstr) }
   .stab.excl 0 : { *(.stab.excl) }
diff -u --recursive --new-file v2.3.24/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.3.24/linux/arch/i386/kernel/apm.c	Mon Oct 11 15:38:14 1999
+++ linux/arch/i386/kernel/apm.c	Mon Nov  1 13:33:04 1999
@@ -1,8 +1,8 @@
 /* -*- linux-c -*-
  * APM BIOS driver for Linux
- * Copyright 1994-1998 Stephen Rothwell
- *                     (Stephen.Rothwell@canb.auug.org.au)
- * Development of this driver was funded by NEC Australia P/L
+ * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * Initial development of this driver was funded by NEC Australia P/L
  *	and NEC Corporation
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -133,6 +133,12 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 
+/*
+ * Make APM look as much as just another ACPI module as possible..
+ */
+#include <linux/acpi.h>
+
+
 EXPORT_SYMBOL(apm_register_callback);
 EXPORT_SYMBOL(apm_unregister_callback);
 
@@ -1400,6 +1406,11 @@
 			apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
 	}
 
+/* Install our power off handler.. */
+#ifdef CONFIG_APM_POWER_OFF
+	acpi_power_off = apm_power_off;
+#endif
+
 	apm_mainloop();
 	return 0;
 }
@@ -1441,8 +1452,6 @@
  */
 static int __init apm_init(void)
 {
-	static struct proc_dir_entry *ent;
-
 	if (apm_bios_info.version == 0) {
 		printk(KERN_INFO "apm: BIOS not found.\n");
 		return -1;
@@ -1536,9 +1545,7 @@
 	}
 #endif
 
-	ent = create_proc_entry("apm", 0, 0);
-	if (ent != NULL)
-		ent->get_info = apm_get_info;
+ 	create_proc_info_entry("apm", 0, 0, apm_get_info);
 
 	misc_register(&apm_device);
 
diff -u --recursive --new-file v2.3.24/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.3.24/linux/arch/i386/kernel/entry.S	Fri Oct 15 15:25:13 1999
+++ linux/arch/i386/kernel/entry.S	Fri Oct 29 13:19:49 1999
@@ -476,7 +476,7 @@
 	.long SYMBOL_NAME(sys_sigpending)
 	.long SYMBOL_NAME(sys_sethostname)
 	.long SYMBOL_NAME(sys_setrlimit)	/* 75 */
-	.long SYMBOL_NAME(sys_getrlimit)
+	.long SYMBOL_NAME(sys_old_getrlimit)
 	.long SYMBOL_NAME(sys_getrusage)
 	.long SYMBOL_NAME(sys_gettimeofday)
 	.long SYMBOL_NAME(sys_settimeofday)
@@ -591,6 +591,7 @@
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
 	.long SYMBOL_NAME(sys_vfork)            /* 190 */
+	.long SYMBOL_NAME(sys_getrlimit)
 
 	/*
 	 * NOTE!! This doesn't have to be exact - we just have
@@ -598,6 +599,6 @@
 	 * entries. Don't panic if you notice that this hasn't
 	 * been shrunk every time we add a new system call.
 	 */
-	.rept NR_syscalls-190
+	.rept NR_syscalls-191
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -u --recursive --new-file v2.3.24/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.3.24/linux/arch/i386/kernel/i386_ksyms.c	Wed Oct 27 16:34:12 1999
+++ linux/arch/i386/kernel/i386_ksyms.c	Mon Nov  1 13:28:43 1999
@@ -45,6 +45,7 @@
 EXPORT_SYMBOL(disable_irq_nosync);
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(acpi_idle);
+EXPORT_SYMBOL(acpi_power_off);
 
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
diff -u --recursive --new-file v2.3.24/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- v2.3.24/linux/arch/i386/kernel/mca.c	Wed Aug 18 11:25:29 1999
+++ linux/arch/i386/kernel/mca.c	Thu Oct 28 14:34:45 1999
@@ -705,11 +705,11 @@
 
 	if(mca_info == NULL) return;	/* Should never happen */
 
-	proc_register(&proc_mca, &(struct proc_dir_entry) {
+	proc_register(proc_mca, &(struct proc_dir_entry) {
 		PROC_MCA_REGISTERS, 3, "pos", S_IFREG|S_IRUGO,
 		1, 0, 0, 0, &proc_mca_inode_operations,});
 
-	proc_register(&proc_mca, &(struct proc_dir_entry) {
+	proc_register(proc_mca, &(struct proc_dir_entry) {
 		PROC_MCA_MACHINE, 7, "machine", S_IFREG|S_IRUGO,
 		1, 0, 0, 0, &proc_mca_inode_operations,});
 
@@ -745,7 +745,7 @@
 		node->name = mca_info->slot[i].procname;
 		node->mode = S_IFREG | S_IRUGO;
 		node->ops = &proc_mca_inode_operations;
-		proc_register(&proc_mca, node);
+		proc_register(proc_mca, node);
 	}
 
 } /* mca_do_proc_init() */
diff -u --recursive --new-file v2.3.24/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.3.24/linux/arch/i386/kernel/mtrr.c	Sat Oct  9 11:47:50 1999
+++ linux/arch/i386/kernel/mtrr.c	Thu Oct 28 14:34:45 1999
@@ -1516,7 +1516,7 @@
 };
 
 static struct proc_dir_entry proc_root_mtrr = {
-	PROC_MTRR, 4, "mtrr",
+	0, 4, "mtrr",
 	S_IFREG | S_IWUSR | S_IRUGO, 1, 0, 0,
 	0, &proc_mtrr_inode_operations
 };
diff -u --recursive --new-file v2.3.24/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.3.24/linux/arch/i386/kernel/process.c	Wed Oct 27 16:34:12 1999
+++ linux/arch/i386/kernel/process.c	Mon Nov  1 13:32:10 1999
@@ -29,9 +29,6 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
-#include <linux/apm_bios.h>
-#endif
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -67,6 +64,11 @@
 void (*acpi_idle)(void) = NULL;
 
 /*
+ * Power off function, if any
+ */
+void (*acpi_power_off)(void) = NULL;
+
+/*
  * The idle thread. There's no useful work to be
  * done, so just try to conserve power and have a
  * low exit latency (ie sit in a loop waiting for
@@ -310,9 +312,8 @@
 
 void machine_power_off(void)
 {
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
-	apm_power_off();
-#endif
+	if (acpi_power_off)
+		acpi_power_off();
 }
 
 
diff -u --recursive --new-file v2.3.24/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- v2.3.24/linux/arch/i386/kernel/smpboot.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/i386/kernel/smpboot.c	Wed Oct 27 18:40:00 1999
@@ -821,8 +821,9 @@
 		 * could use the real zero-page, but it's safer
 		 * this way if some buggy code writes to this page ...
 		 */
-		apic_phys = __pa(alloc_bootmem_pages(PAGE_SIZE));
+		apic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
 		memset((void *)apic_phys, 0, PAGE_SIZE);
+		apic_phys = __pa(apic_phys);
 	}
 	set_fixmap(FIX_APIC_BASE, apic_phys);
 	dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
@@ -836,8 +837,9 @@
 			if (smp_found_config) {
 				ioapic_phys = mp_ioapics[i].mpc_apicaddr;
 			} else {
-				ioapic_phys = __pa(alloc_bootmem_pages(PAGE_SIZE));
+				ioapic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
 				memset((void *)ioapic_phys, 0, PAGE_SIZE);
+				ioapic_phys = __pa(ioapic_phys);
 			}
 			set_fixmap(idx,ioapic_phys);
 			dprintk("mapped IOAPIC to %08lx (%08lx)\n",
diff -u --recursive --new-file v2.3.24/linux/arch/i386/lib/mmx.c linux/arch/i386/lib/mmx.c
--- v2.3.24/linux/arch/i386/lib/mmx.c	Mon Oct 11 15:38:14 1999
+++ linux/arch/i386/lib/mmx.c	Wed Oct 27 18:30:39 1999
@@ -89,7 +89,7 @@
 	return p;
 }
 
-static void fast_clear_page(long page)
+static void fast_clear_page(void *page)
 {
 	int i;
 	if (!(current->flags & PF_USEDFPU))
@@ -129,7 +129,7 @@
 	stts();
 }
 
-static void fast_copy_page(long to, long from)
+static void fast_copy_page(void *to, void *from)
 {
 	int i;
 	if (!(current->flags & PF_USEDFPU))
@@ -196,7 +196,7 @@
  *	Favour MMX for page clear and copy. 
  */
 
-static void slow_zero_page(long page)
+static void slow_zero_page(void * page)
 {
 	int d0, d1;
 	__asm__ __volatile__( \
@@ -207,7 +207,7 @@
 		:"memory");
 }
  
-void mmx_clear_page(long page)
+void mmx_clear_page(void * page)
 {
 	if(in_interrupt())
 		slow_zero_page(page);
@@ -215,7 +215,7 @@
 		fast_clear_page(page);
 }
 
-static void slow_copy_page(long to, long from)
+static void slow_copy_page(void *to, void *from)
 {
 	int d0, d1, d2;
 	__asm__ __volatile__( \
@@ -227,7 +227,7 @@
 }
   
 
-void mmx_copy_page(long to, long from)
+void mmx_copy_page(void *to, void *from)
 {
 	if(in_interrupt())
 		slow_copy_page(to, from);
diff -u --recursive --new-file v2.3.24/linux/arch/m68k/mac/iop.c linux/arch/m68k/mac/iop.c
--- v2.3.24/linux/arch/m68k/mac/iop.c	Tue Sep  7 12:14:06 1999
+++ linux/arch/m68k/mac/iop.c	Thu Oct 28 14:34:45 1999
@@ -125,21 +125,9 @@
 int iop_scc_present,iop_ism_present;
 
 #ifdef CONFIG_PROC_FS
-
-/*
- * sneaky reuse of the PROC_MAC_VIA inode. It's not needed by via.c
- * anymore so we'll use it to debut the IOPs.
- */
-
-int iop_get_proc_info(char *, char **, off_t, int, int);
-
-static struct proc_dir_entry proc_mac_iop = {
-	PROC_MAC_VIA, 7, "mac_iop",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	&iop_get_proc_info
-};
-
+static int iop_get_proc_info(char *, char **, off_t, int, int);
+#else
+static int iop_get_proc_info(char *, char **, off_t, int, int) {}
 #endif /* CONFIG_PROC_FS */
 
 /* structure for tracking channel listeners */
@@ -315,9 +303,7 @@
 		iop_listeners[IOP_NUM_ISM][i].handler = NULL;
 	}
 
-#ifdef CONFIG_PROC_FS
-	proc_register(&proc_root, &proc_mac_iop);
-#endif
+	create_proc_info_entry("mac_iop",0,0,iop_get_proc_info);
 }
 
 /*
@@ -722,4 +708,5 @@
 	}
 	return (count > cnt) ? cnt : count;
 }
+
 #endif /* CONFIG_PROC_FS */
diff -u --recursive --new-file v2.3.24/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.3.24/linux/arch/mips/config.in	Sat Oct  9 11:47:50 1999
+++ linux/arch/mips/config.in	Thu Oct 28 10:45:51 1999
@@ -177,13 +177,12 @@
          if [ "$CONFIG_SGI" = "y" ]; then
 	 bool '  SGI Seeq ethernet controller support' CONFIG_SGISEEQ
       fi
-	 if [ "$CONFIG_DECSTATION" = "y" ]; then
-            bool '  DEC LANCE ethernet controller support' CONFIG_DECLANCE
-         fi
-	 if [ "$CONFIG_BAGET_MIPS" = "y" ]; then
-	    tristate '  Baget AMD LANCE support' CONFIG_BAGETLANCE
-	    tristate '  Baget Backplane Shared Memory support' CONFIG_BAGETBSM
-	 fi
+      if [ "$CONFIG_DECSTATION" = "y" ]; then
+         bool '  DEC LANCE ethernet controller support' CONFIG_DECLANCE
+      fi
+      if [ "$CONFIG_BAGET_MIPS" = "y" ]; then
+	 tristate '  Baget AMD LANCE support' CONFIG_BAGETLANCE
+	 tristate '  Baget Backplane Shared Memory support' CONFIG_BAGETBSM
       fi
    fi
    endmenu
@@ -206,7 +205,7 @@
 
 
    mainmenu_option next_comment
-   comment comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+   comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
    bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
    if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
diff -u --recursive --new-file v2.3.24/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.3.24/linux/arch/ppc/config.in	Fri Oct 15 15:25:13 1999
+++ linux/arch/ppc/config.in	Thu Oct 28 10:45:51 1999
@@ -5,6 +5,11 @@
 mainmenu_name "Linux/PowerPC Kernel Configuration"
 
 mainmenu_option next_comment
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
+
+mainmenu_option next_comment
 comment 'Platform support'
 define_bool CONFIG_PPC y
 choice 'Processor type' \
@@ -53,14 +58,16 @@
 endmenu
 
 mainmenu_option next_comment
-comment 'General setup'
-
-bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+comment 'Loadable module support'
 bool 'Enable loadable module support' CONFIG_MODULES
 if [ "$CONFIG_MODULES" = "y" ]; then
-  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
-  bool 'Kernel module loader' CONFIG_KMOD
+   bool '  Set version information on all module symbols' CONFIG_MODVERSIONS
+   bool '  Kernel module loader' CONFIG_KMOD
 fi
+endmenu
+
+mainmenu_option next_comment
+comment 'General setup'
 
 if [ "$CONFIG_APUS" = "y" ]; then
   define_bool CONFIG_PCI n
diff -u --recursive --new-file v2.3.24/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.3.24/linux/arch/sparc/config.in	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/config.in	Mon Nov  1 10:31:28 1999
@@ -10,62 +10,55 @@
 endmenu
 
 mainmenu_option next_comment
-comment 'Loadable module support'
-bool 'Enable loadable module support' CONFIG_MODULES
-if [ "$CONFIG_MODULES" = "y" ]; then
-  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
-  bool 'Kernel module loader' CONFIG_KMOD
-fi
-endmenu
-
-mainmenu_option next_comment
 comment 'General setup'
 
 define_bool CONFIG_VT y
 define_bool CONFIG_VT_CONSOLE y
 
-bool 'Support for AP1000 multicomputer' CONFIG_AP1000
 bool 'Symmetric multi-processing support (does not work on sun4/sun4c)' CONFIG_SMP
 
+bool 'Support for AP1000 multicomputer' CONFIG_AP1000
 if [ "$CONFIG_AP1000" = "y" ]; then
-	define_bool CONFIG_NO_KEYBOARD y
-	define_bool CONFIG_FDDI y
-	define_bool CONFIG_APFDDI y
-	define_bool CONFIG_APBLOCK y
-	define_bool CONFIG_APBIF y
-	tristate 'OPIU DDV Driver' CONFIG_DDV
+   define_bool CONFIG_NO_KEYBOARD y
+   define_bool CONFIG_FDDI y
+   define_bool CONFIG_APFDDI y
+   define_bool CONFIG_APBLOCK y
+   define_bool CONFIG_APBIF y
+   tristate '  OPIU DDV Driver' CONFIG_DDV
 else
-	bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
-	if [ "$CONFIG_SUN4" != "y" ]; then
-		bool 'Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
-	fi
-
-	mainmenu_option next_comment
-	comment 'Console drivers'
-	bool 'PROM console' CONFIG_PROM_CONSOLE
-	bool 'Support Frame buffer devices' CONFIG_FB
-	source drivers/video/Config.in
-	endmenu
-
-	# Global things across all Sun machines.
-	define_bool CONFIG_SBUS y
-	define_bool CONFIG_SBUSCHAR y
-	define_bool CONFIG_BUSMOUSE y
-	define_bool CONFIG_SUN_MOUSE y
-	define_bool CONFIG_SERIAL y
-	define_bool CONFIG_SUN_SERIAL y
-	define_bool CONFIG_SERIAL_CONSOLE y
-	define_bool CONFIG_SUN_KEYBOARD y
-	define_bool CONFIG_SUN_CONSOLE y
-	define_bool CONFIG_SUN_AUXIO y
-	define_bool CONFIG_SUN_IO y
-	if [ "$CONFIG_SUN4" != "y" ]; then
-		source drivers/sbus/char/Config.in
-		source drivers/sbus/audio/Config.in
-	fi
+   bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
+   if [ "$CONFIG_SUN4" != "y" ]; then
+      bool '  Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
+   fi
+
+   mainmenu_option next_comment
+   comment 'Console drivers'
+   bool 'PROM console' CONFIG_PROM_CONSOLE
+   bool 'Support Frame buffer devices' CONFIG_FB
+   source drivers/video/Config.in
+   endmenu
+
+   # Global things across all Sun machines.
+   define_bool CONFIG_SBUS y
+   define_bool CONFIG_SBUSCHAR y
+   define_bool CONFIG_BUSMOUSE y
+   define_bool CONFIG_SUN_MOUSE y
+   define_bool CONFIG_SERIAL y
+   define_bool CONFIG_SUN_SERIAL y
+   define_bool CONFIG_SERIAL_CONSOLE y
+   define_bool CONFIG_SUN_KEYBOARD y
+   define_bool CONFIG_SUN_CONSOLE y
+   define_bool CONFIG_SUN_AUXIO y
+   define_bool CONFIG_SUN_IO y
+   if [ "$CONFIG_SUN4" != "y" ]; then
+      source drivers/sbus/char/Config.in
+      source drivers/sbus/audio/Config.in
+   fi
 fi
 
-tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
+fi
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
@@ -78,21 +71,30 @@
 endmenu
 
 mainmenu_option next_comment
+comment 'Loadable module support'
+bool 'Enable loadable module support' CONFIG_MODULES
+if [ "$CONFIG_MODULES" = "y" ]; then
+   bool '  Set version information on all symbols for modules' CONFIG_MODVERSIONS
+   bool '  Kernel module loader' CONFIG_KMOD
+fi
+endmenu
+
+mainmenu_option next_comment
 comment 'Floppy, IDE, and other block devices'
 
 bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD
 
 bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
 if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
-  tristate '   Linear (append) mode' CONFIG_MD_LINEAR
-  tristate '   RAID-0 (striping) mode' CONFIG_MD_STRIPED
-  tristate '   RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
-  tristate '   RAID-4/RAID-5 mode' CONFIG_MD_RAID5
+   tristate '  Linear (append) mode' CONFIG_MD_LINEAR
+   tristate '  RAID-0 (striping) mode' CONFIG_MD_STRIPED
+   tristate '  RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
+   tristate '  RAID-4/RAID-5 mode' CONFIG_MD_RAID5
 fi
 
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
 if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
-  bool '   Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
+   bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
 fi
 
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
@@ -101,7 +103,7 @@
 endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
-	source net/Config.in
+   source net/Config.in
 fi
 
 mainmenu_option next_comment
@@ -109,7 +111,7 @@
 
 tristate 'ISDN support' CONFIG_ISDN
 if [ "$CONFIG_ISDN" != "n" ]; then
-  source drivers/isdn/Config.in
+   source drivers/isdn/Config.in
 fi
 endmenu
 
@@ -119,65 +121,65 @@
 tristate 'SCSI support' CONFIG_SCSI
 
 if [ "$CONFIG_SCSI" != "n" ]; then
-	comment 'SCSI support type (disk, tape, CDrom)'
+   comment 'SCSI support type (disk, tape, CDrom)'
 
-	dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
-	dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
-	dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
-	if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
-	  bool '  Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
-	fi
-	dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
+   dep_tristate '  SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+   dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+   dep_tristate '  SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+   if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
+      bool '    Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+   fi
+   dep_tristate '  SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
 
-	comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
+   comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
 
-	bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
+   bool '  Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
 
-	bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
+   bool '  Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
 
-	mainmenu_option next_comment
-	comment 'SCSI low-level drivers'
+   mainmenu_option next_comment
+   comment 'SCSI low-level drivers'
 
-	bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
-	tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
-	endmenu
+   bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+   tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
+   endmenu
 fi
 endmenu
 
 source drivers/fc4/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
-	mainmenu_option next_comment
-	comment 'Network device support'
+   mainmenu_option next_comment
+   comment 'Network device support'
 
-	bool 'Network device support' CONFIG_NETDEVICES
-	if [ "$CONFIG_NETDEVICES" = "y" ]; then
-		tristate 'Dummy net driver support' CONFIG_DUMMY
-		tristate 'PPP (point-to-point) support' CONFIG_PPP
-		if [ ! "$CONFIG_PPP" = "n" ]; then
-		   comment 'CCP compressors for PPP are only built as modules.'
-		fi
-		tristate 'SLIP (serial line) support' CONFIG_SLIP
-		if [ "$CONFIG_SLIP" != "n" ]; then
-		  bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
-		  bool ' Keepalive and linefill' CONFIG_SLIP_SMART
-		  bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
-		fi
-		tristate 'Sun LANCE support' CONFIG_SUNLANCE
-		tristate 'Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
-		if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-		  tristate 'Sun BigMAC 10/100baseT support' CONFIG_SUNBMAC
-		fi
-		tristate 'Sun QuadEthernet support' CONFIG_SUNQE
-		tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
-#		bool 'FDDI driver support' CONFIG_FDDI
-#		if [ "$CONFIG_FDDI" = "y" ]; then
-#		fi
-		if [ "$CONFIG_ATM" = "y" ]; then
-		  source drivers/atm/Config.in
-		fi
-	fi
-	endmenu
+   bool 'Network device support' CONFIG_NETDEVICES
+   if [ "$CONFIG_NETDEVICES" = "y" ]; then
+      tristate '  Dummy net driver support' CONFIG_DUMMY
+      tristate '  PPP (point-to-point) support' CONFIG_PPP
+      if [ ! "$CONFIG_PPP" = "n" ]; then
+	 comment 'CCP compressors for PPP are only built as modules.'
+      fi
+      tristate '  SLIP (serial line) support' CONFIG_SLIP
+      if [ "$CONFIG_SLIP" != "n" ]; then
+	 bool '    CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
+	 bool '    Keepalive and linefill' CONFIG_SLIP_SMART
+	 bool '    Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
+      fi
+      tristate '  Sun LANCE support' CONFIG_SUNLANCE
+      tristate '  Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+	 tristate '  Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
+      fi
+      tristate '  Sun QuadEthernet support' CONFIG_SUNQE
+      tristate '  MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
+#      bool '  FDDI driver support' CONFIG_FDDI
+#      if [ "$CONFIG_FDDI" = "y" ]; then
+#      fi
+      if [ "$CONFIG_ATM" = "y" ]; then
+	 source drivers/atm/Config.in
+      fi
+   fi
+   endmenu
 fi
 
 # This one must be before the filesystem configs. -DaveM
@@ -185,7 +187,7 @@
 comment 'Unix98 PTY support'
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
-	int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+   int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
 fi
 endmenu
 
@@ -202,4 +204,3 @@
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
-
diff -u --recursive --new-file v2.3.24/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.3.24/linux/arch/sparc64/config.in	Sat Oct  9 11:47:50 1999
+++ linux/arch/sparc64/config.in	Mon Nov  1 10:31:28 1999
@@ -10,15 +10,6 @@
 endmenu
 
 mainmenu_option next_comment
-comment 'Loadable module support'
-bool 'Enable loadable module support' CONFIG_MODULES
-if [ "$CONFIG_MODULES" = "y" ]; then
-  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
-  bool 'Kernel module loader' CONFIG_KMOD
-fi
-endmenu
-
-mainmenu_option next_comment
 comment 'General setup'
 
 define_bool CONFIG_VT y
@@ -49,25 +40,36 @@
 source drivers/sbus/char/Config.in
 source drivers/sbus/audio/Config.in
 
-tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
+fi
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 bool 'Kernel support for Linux/Sparc 32bit binary compatibility' CONFIG_SPARC32_COMPAT
-tristate 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF
 if [ "$CONFIG_SPARC32_COMPAT" != "n" ]; then
-  tristate 'Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32
-  bool 'Kernel support for 32-bit (ie. SunOS) a.out binaries' CONFIG_BINFMT_AOUT32
+   tristate '  Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32
+   bool '  Kernel support for 32-bit (ie. SunOS) a.out binaries' CONFIG_BINFMT_AOUT32
 fi
+tristate 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  tristate 'Solaris binary emulation' CONFIG_SOLARIS_EMUL
+   tristate 'Solaris binary emulation (EXPERIMENTAL)' CONFIG_SOLARIS_EMUL
 fi
 source drivers/parport/Config.in
 dep_tristate '  Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
 if [ "$CONFIG_PCI" = "y" ]; then
-  tristate 'SUNW,envctrl support' CONFIG_ENVCTRL
+   tristate 'SUNW, envctrl support' CONFIG_ENVCTRL
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Loadable module support'
+bool 'Enable loadable module support' CONFIG_MODULES
+if [ "$CONFIG_MODULES" = "y" ]; then
+   bool '  Set version information on all symbols for modules' CONFIG_MODVERSIONS
+   bool '  Kernel module loader' CONFIG_KMOD
 fi
 endmenu
 
@@ -78,41 +80,41 @@
 
 bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
 if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
-  tristate '   Linear (append) mode' CONFIG_MD_LINEAR
-  tristate '   RAID-0 (striping) mode' CONFIG_MD_STRIPED
-  tristate '   RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
-  tristate '   RAID-4/RAID-5 mode' CONFIG_MD_RAID5
+   tristate '  Linear (append) mode' CONFIG_MD_LINEAR
+   tristate '  RAID-0 (striping) mode' CONFIG_MD_STRIPED
+   tristate '  RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
+   tristate '  RAID-4/RAID-5 mode' CONFIG_MD_RAID5
 fi
 
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
 if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
-  bool '   Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
+   bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
 fi
 
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
 tristate 'Network block device support' CONFIG_BLK_DEV_NBD
 
 if [ "$CONFIG_PCI" = "y" ]; then
-	tristate 'Ultra/PCI IDE disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE
-	if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
-	  dep_tristate '   Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
-	  dep_tristate '   Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
-	  dep_tristate '   Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
-	  dep_tristate '   Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
-	  dep_tristate '   SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
-	  define_bool CONFIG_BLK_DEV_IDEPCI y
-	  define_bool CONFIG_BLK_DEV_IDEDMA y
-	  define_bool CONFIG_IDEDMA_AUTO y
-	  define_bool IDEDMA_NEW_DRIVE_LISTINGS y
-	  define_bool CONFIG_BLK_DEV_NS87415 y
-	  define_bool CONFIG_BLK_DEV_CMD646 y
-	fi
+   tristate 'Ultra/PCI IDE disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE
+   if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
+      dep_tristate '  Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
+      dep_tristate '  Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
+      dep_tristate '  Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
+      dep_tristate '  Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
+      dep_tristate '  SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
+      define_bool CONFIG_BLK_DEV_IDEPCI y
+      define_bool CONFIG_BLK_DEV_IDEDMA y
+      define_bool CONFIG_IDEDMA_AUTO y
+      define_bool CONFIG_IDEDMA_NEW_DRIVE_LISTINGS y
+      define_bool CONFIG_BLK_DEV_NS87415 y
+      define_bool CONFIG_BLK_DEV_CMD646 y
+   fi
 fi
 
 endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
-	source net/Config.in
+   source net/Config.in
 fi
 
 mainmenu_option next_comment
@@ -121,95 +123,95 @@
 tristate 'SCSI support' CONFIG_SCSI
 
 if [ "$CONFIG_SCSI" != "n" ]; then
-	comment 'SCSI support type (disk, tape, CDrom)'
+   comment 'SCSI support type (disk, tape, CDrom)'
 
-	dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
-	dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
-	dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
-	if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
-	  bool '  Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
-	fi
-	dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
-
-	comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
-
-	bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
-
-	bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
-
-	mainmenu_option next_comment
-	comment 'SCSI low-level drivers'
-
-	bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
-	tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
-
-	if [ "$CONFIG_PCI" != "n" ]; then
-	  dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
-	  if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
-	    bool '   Enable Tagged Command Queueing (TCQ) by default' CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
-	    int  '   Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 8
-	    bool '   Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N
-	    int  '   Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5
-	  fi
-	  dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
-	  if [ "$CONFIG_SCSI_NCR53C8XX" != "n" ]; then
-	    int  '  default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8
-	    int  '  maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32
-	    int  '  synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 10
-	    bool '  enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE
-	    if [ "$CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS" = "0" ]; then
-	      bool '  not allow targets to disconnect' CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
-	    fi
-	    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-	      bool '  assume boards are SYMBIOS compatible' CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
-	    fi
-	  fi
-          dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
-	fi
+   dep_tristate '  SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+   dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+   dep_tristate '  SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+   if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
+      bool '    Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+   fi
+   dep_tristate '  SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
+
+   comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
+
+   bool '  Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
+
+   bool '  Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
+
+   mainmenu_option next_comment
+   comment 'SCSI low-level drivers'
+
+   bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+   tristate 'PTI Qlogic, ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
+
+   if [ "$CONFIG_PCI" != "n" ]; then
+      dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
+      if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
+	 bool '  Enable tagged command queueing (TCQ) by default' CONFIG_AIC7XXX_TAGGED_QUEUEING Y
+	 int  '  Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 8
+  	 bool '  Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N
+	 int  '  Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5
+      fi
+      dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
+      if [ "$CONFIG_SCSI_NCR53C8XX" != "n" ]; then
+	 int 'default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8
+	 int 'maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32
+	 int 'synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 10
+	 bool '  enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE
+	 if [ "$CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS" = "0" ]; then
+	    bool '  not allow targets to disconnect' CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
+	 fi
+	 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+	    bool '  assume boards are SYMBIOS compatible (EXPERIMENTAL)' CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
+	 fi
+      fi
+      dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
+   fi
 
-	endmenu
+   endmenu
 fi
 endmenu
 
 source drivers/fc4/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
-	mainmenu_option next_comment
-	comment 'Network device support'
+   mainmenu_option next_comment
+   comment 'Network device support'
 
-	bool 'Network device support' CONFIG_NETDEVICES
-	if [ "$CONFIG_NETDEVICES" = "y" ]; then
-		tristate 'Dummy net driver support' CONFIG_DUMMY
-		tristate 'PPP (point-to-point) support' CONFIG_PPP
-		if [ ! "$CONFIG_PPP" = "n" ]; then
-		   comment 'CCP compressors for PPP are only built as modules.'
-		fi
-		tristate 'SLIP (serial line) support' CONFIG_SLIP
-		if [ "$CONFIG_SLIP" != "n" ]; then
-		  bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
-		  bool ' Keepalive and linefill' CONFIG_SLIP_SMART
-		  bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
-		fi
-		bool 'Sun LANCE support' CONFIG_SUNLANCE
-		tristate 'Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
-		if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-		  tristate 'Sun BigMAC 10/100baseT support' CONFIG_SUNBMAC
-		fi
-		tristate 'Sun QuadEthernet support' CONFIG_SUNQE
-		tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
-		if [ "$CONFIG_PCI" = "y" ]; then
-			tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
-			tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
-			tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
-			tristate 'PCI NE2000 support' CONFIG_NE2K_PCI
-			tristate 'EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
-			tristate 'Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
-		fi
-#		bool 'FDDI driver support' CONFIG_FDDI
-#		if [ "$CONFIG_FDDI" = "y" ]; then
-#		fi
-	fi
-	endmenu
+   bool 'Network device support' CONFIG_NETDEVICES
+   if [ "$CONFIG_NETDEVICES" = "y" ]; then
+      tristate '  Dummy net driver support' CONFIG_DUMMY
+      tristate '  PPP (point-to-point) support' CONFIG_PPP
+      if [ ! "$CONFIG_PPP" = "n" ]; then
+	 comment '    CCP compressors for PPP are only built as modules.'
+      fi
+      tristate '  SLIP (serial line) support' CONFIG_SLIP
+      if [ "$CONFIG_SLIP" != "n" ]; then
+	 bool '    CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
+	 bool '    Keepalive and linefill' CONFIG_SLIP_SMART
+	 bool '    Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
+      fi
+      bool '  Sun LANCE support' CONFIG_SUNLANCE
+      tristate '  Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+	 tristate '  Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
+      fi
+      tristate '  Sun QuadEthernet support' CONFIG_SUNQE
+      tristate '  MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
+      if [ "$CONFIG_PCI" = "y" ]; then
+	 tristate '  Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
+	 tristate '  3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
+	 tristate '  RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
+	 tristate '  PCI NE2000 support' CONFIG_NE2K_PCI
+	 tristate '  EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
+	 tristate '  Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
+      fi
+#      bool '  FDDI driver support' CONFIG_FDDI
+#      if [ "$CONFIG_FDDI" = "y" ]; then
+#      fi
+   fi
+endmenu
 fi
 
 # This one must be before the filesystem configs. -DaveM
@@ -217,7 +219,7 @@
 comment 'Unix 98 PTY support'
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
-	int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+   int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
 fi
 endmenu
 
@@ -225,9 +227,9 @@
 comment 'Video For Linux'
 tristate 'Video For Linux' CONFIG_VIDEO_DEV
 if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
-  if [ "$CONFIG_PCI" != "n" ]; then
-    dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
-  fi
+   if [ "$CONFIG_PCI" != "n" ]; then
+      dep_tristate '  BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+   fi
 fi
 endmenu
 
diff -u --recursive --new-file v2.3.24/linux/drivers/acorn/net/Config.in linux/drivers/acorn/net/Config.in
--- v2.3.24/linux/drivers/acorn/net/Config.in	Mon Feb 16 15:49:47 1998
+++ linux/drivers/acorn/net/Config.in	Thu Oct 28 10:16:02 1999
@@ -2,6 +2,6 @@
 # Acorn Network device configuration
 #  These are for Acorn's Expansion card network interfaces
 #
-tristate 'Acorn Ether1 (82586) support' CONFIG_ARM_ETHER1
-tristate 'Acorn/ANT Ether3 (NQ8005) support' CONFIG_ARM_ETHER3
-tristate 'I-cubed EtherH (NS8390) support' CONFIG_ARM_ETHERH
+tristate '  Acorn Ether1 (82586) support' CONFIG_ARM_ETHER1
+tristate '  Acorn/ANT Ether3 (NQ8005) support' CONFIG_ARM_ETHER3
+tristate '  I-cubed EtherH (NS8390) support' CONFIG_ARM_ETHERH
diff -u --recursive --new-file v2.3.24/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.3.24/linux/drivers/block/DAC960.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/block/DAC960.c	Thu Oct 28 14:34:46 1999
@@ -95,11 +95,11 @@
 
 
 /*
-  DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry.
+  DAC960_ProcDirectoryEntry is the DAC960 /proc/driver/rd directory entry.
 */
 
-static PROC_DirectoryEntry_T
-  DAC960_ProcDirectoryEntry;
+static PROC_DirectoryEntry_T *
+  DAC960_ProcDirectoryEntry = NULL;
 
 
 /*
@@ -3466,23 +3466,18 @@
 
 
 /*
-  DAC960_CreateProcEntries creates the /proc/rd/... entries for the DAC960
-  Driver.
+  DAC960_CreateProcEntries creates the /proc/driver/rd/... entries
+  for the DAC960 Driver.
 */
 
 static void DAC960_CreateProcEntries(void)
 {
-  static PROC_DirectoryEntry_T StatusProcEntry;
+  static PROC_DirectoryEntry_T *StatusProcEntry;
   int ControllerNumber;
-  DAC960_ProcDirectoryEntry.name = "rd";
-  DAC960_ProcDirectoryEntry.namelen = strlen(DAC960_ProcDirectoryEntry.name);
-  DAC960_ProcDirectoryEntry.mode = S_IFDIR | S_IRUGO | S_IXUGO;
-  proc_register(&proc_root, &DAC960_ProcDirectoryEntry);
-  StatusProcEntry.name = "status";
-  StatusProcEntry.namelen = strlen(StatusProcEntry.name);
-  StatusProcEntry.mode = S_IFREG | S_IRUGO;
-  StatusProcEntry.read_proc = DAC960_ProcReadStatus;
-  proc_register(&DAC960_ProcDirectoryEntry, &StatusProcEntry);
+  DAC960_ProcDirectoryEntry = create_proc_entry("driver/rd", S_IFDIR, NULL);
+  StatusProcEntry = create_proc_read_entry("status", 0,
+					   DAC960_ProcDirectoryEntry,
+					   DAC960_ProcReadStatus, NULL);
   for (ControllerNumber = 0;
        ControllerNumber < DAC960_ControllerCount;
        ControllerNumber++)
@@ -3495,7 +3490,7 @@
       ControllerProcEntry->name = Controller->ControllerName;
       ControllerProcEntry->namelen = strlen(ControllerProcEntry->name);
       ControllerProcEntry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
-      proc_register(&DAC960_ProcDirectoryEntry, ControllerProcEntry);
+      proc_register(DAC960_ProcDirectoryEntry, ControllerProcEntry);
       InitialStatusProcEntry = &Controller->InitialStatusProcEntry;
       InitialStatusProcEntry->name = "initial_status";
       InitialStatusProcEntry->namelen = strlen(InitialStatusProcEntry->name);
@@ -3529,7 +3524,7 @@
 
 static void DAC960_DestroyProcEntries(void)
 {
-  proc_unregister(&proc_root, DAC960_ProcDirectoryEntry.low_ino);
+  remove_proc_entry("driver/rd", NULL);
 }
 
 
diff -u --recursive --new-file v2.3.24/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.3.24/linux/drivers/block/cpqarray.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/block/cpqarray.c	Thu Oct 28 14:34:46 1999
@@ -161,8 +161,14 @@
 static int revalidate_logvol(kdev_t dev, int maxusage);
 static int revalidate_allvol(kdev_t dev);
 
+#ifdef CONFIG_PROC_FS
 static void ida_procinit(int i);
 static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+#else
+static void ida_procinit(int i) {}
+static int ida_proc_get_info(char *buffer, char **start, off_t offset,
+			     int length, int *eof, void *data) {}
+#endif
 
 static void ida_geninit(struct gendisk *g)
 {
@@ -207,26 +213,21 @@
 };
 
 
+#ifdef CONFIG_PROC_FS
+
 /*
  * Get us a file in /proc/array that says something about each controller.
  * Create /proc/array if it doesn't exist yet.
  */
-static void ida_procinit(int i)
+static void __init ida_procinit(int i)
 {
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *pd;
-
 	if (proc_array == NULL) {
-		proc_array = create_proc_entry("array", S_IFDIR|S_IRUGO|S_IXUGO,
-								&proc_root);
+		proc_array = create_proc_entry("driver/array", S_IFDIR, NULL);
 		if (!proc_array) return;
 	}
 
-	pd = create_proc_entry(hba[i]->devname, S_IFREG|S_IRUGO, proc_array);
-	if (!pd) return;
-	pd->read_proc = ida_proc_get_info;
-	pd->data = hba[i];
-#endif	
+	create_proc_read_entry(hba[i]->devname, 0, proc_array,
+			       ida_proc_get_info, hba[i]);
 }
 
 /*
@@ -311,6 +312,7 @@
 		len = length;
 	return len;
 }
+#endif /* CONFIG_PROC_FS */
 
 #ifdef MODULE
 
@@ -318,7 +320,7 @@
 EXPORT_NO_SYMBOLS;
 
 /* This is a bit of a hack... */
-int init_module(void)
+int __init init_module(void)
 {
 	int i, j;
 	cpqarray_init();
@@ -333,11 +335,14 @@
 	}
 	return 0;
 }
+
 void cleanup_module(void)
 {
 	int i;
 	struct gendisk *g;
 
+	remove_proc_entry("driver/array", NULL);
+
 	for(i=0; i<nr_ctlr; i++) {
 		hba[i]->access.set_intr_mask(hba[i], 0);
 		free_irq(hba[i]->intr, hba[i]);
@@ -359,15 +364,11 @@
 			}
 		}
 	}
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("array", &proc_root);
-#endif
+
 	kfree(ida);
 	kfree(ida_sizes);
 	kfree(ida_hardsizes);
 	kfree(ida_blocksizes);
-
-
 }
 #endif /* MODULE */
 
@@ -375,7 +376,7 @@
  *  This is it.  Find all the controllers and register them.  I really hate
  *  stealing all these major device numbers.
  */
-void cpqarray_init(void)
+void __init cpqarray_init(void)
 {
 	void (*request_fns[MAX_CTLR])(void) = {
 		do_ida_request0, do_ida_request1,
diff -u --recursive --new-file v2.3.24/linux/drivers/block/ide-geometry.c linux/drivers/block/ide-geometry.c
--- v2.3.24/linux/drivers/block/ide-geometry.c	Fri Oct 22 13:21:47 1999
+++ linux/drivers/block/ide-geometry.c	Thu Oct 28 16:11:27 1999
@@ -81,7 +81,6 @@
  */
 static void
 ontrack(ide_drive_t *drive, int heads, int *c, int *h, int *s) {
-	struct hd_driveid *id = drive->id;
 	static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
 	const byte *headp = dm_head_vals;
 	unsigned long total, tracks;
@@ -92,10 +91,7 @@
 	 * 1024*255*63. Now take S=63, H the first in the sequence
 	 * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total.
 	 */
-	if (id)
-		total = id->cyls * id->heads * id->sectors;
-	else
-		total = drive->cyl * drive->head * drive->sect;
+	total = DRIVER(drive)->capacity(drive);
 
 	*s = 63;
 
diff -u --recursive --new-file v2.3.24/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
--- v2.3.24/linux/drivers/block/ide-proc.c	Fri Oct 22 13:21:47 1999
+++ linux/drivers/block/ide-proc.c	Thu Oct 28 14:34:46 1999
@@ -769,31 +769,25 @@
 
 void proc_ide_create(void)
 {
-	struct proc_dir_entry *ent;
 	proc_ide_root = create_proc_entry("ide", S_IFDIR, 0);
 	if (!proc_ide_root) return;
+
 	create_proc_ide_interfaces();
 
-	ent = create_proc_entry("drivers", 0, proc_ide_root);
-	if (!ent) return;
-	ent->read_proc  = proc_ide_read_drivers;
+	create_proc_read_entry("drivers",0,proc_ide_root,
+				proc_ide_read_drivers, NULL);
+
 #ifdef CONFIG_BLK_DEV_ALI15X3
-	if ((ali_display_info) && (ali_proc)) {
-		ent = create_proc_entry("ali", 0, proc_ide_root);
-		ent->get_info = ali_display_info;
-	}
+	if ((ali_display_info) && (ali_proc))
+		create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info);
 #endif /* CONFIG_BLK_DEV_ALI15X3 */
 #ifdef CONFIG_BLK_DEV_SIS5513
-	if ((sis_display_info) && (sis_proc)) {
-		ent = create_proc_entry("sis", 0, proc_ide_root);
-		ent->get_info = sis_display_info;
-	}
+	if ((sis_display_info) && (sis_proc))
+		create_proc_info_entry("sis", 0, proc_ide_root, sis_display_info);
 #endif /* CONFIG_BLK_DEV_SIS5513 */
 #ifdef CONFIG_BLK_DEV_VIA82CXXX
-	if ((via_display_info) && (via_proc)) {
-		ent = create_proc_entry("via", 0, proc_ide_root);
-		ent->get_info = via_display_info;
-	}
+	if ((via_display_info) && (via_proc))
+		create_proc_info_entry("via", 0, proc_ide_root, via_display_info);
 #endif /* CONFIG_BLK_DEV_VIA82CXXX */
 }
 
diff -u --recursive --new-file v2.3.24/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.3.24/linux/drivers/block/ll_rw_blk.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/block/ll_rw_blk.c	Fri Oct 29 10:59:17 1999
@@ -388,9 +388,12 @@
 /*
  * Has to be called with the request spinlock aquired
  */
-static inline void attempt_merge (struct request *req, int max_sectors)
+static inline void attempt_merge (struct request *req,
+				int max_sectors,
+				int max_segments)
 {
 	struct request *next = req->next;
+	int total_segments;
 
 	if (!next)
 		return;
@@ -398,9 +401,15 @@
 		return;
 	if (next->sem || req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors > max_sectors)
 		return;
+	total_segments = req->nr_segments + next->nr_segments;
+	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
+		total_segments--;
+	if (total_segments > max_segments)
+		return;
 	req->bhtail->b_reqnext = next->bh;
 	req->bhtail = next->bhtail;
 	req->nr_sectors += next->nr_sectors;
+	req->nr_segments = total_segments;
 	next->rq_status = RQ_INACTIVE;
 	req->next = next->next;
 	wake_up (&wait_for_request);
@@ -410,7 +419,7 @@
 {
 	unsigned int sector, count;
 	struct request * req;
-	int rw_ahead, max_req, max_sectors;
+	int rw_ahead, max_req, max_sectors, max_segments;
 	unsigned long flags;
 
 	count = bh->b_size >> 9;
@@ -493,6 +502,7 @@
 	 * Try to coalesce the new request with old requests
 	 */
 	max_sectors = get_max_sectors(bh->b_rdev);
+	max_segments = get_max_segments(bh->b_rdev);
 
 	/*
 	 * Now we acquire the request spinlock, we have to be mega careful
@@ -572,14 +582,26 @@
 				continue;
 			/* Can we add it to the end of this request? */
 			if (req->sector + req->nr_sectors == sector) {
+				if (req->bhtail->b_data + req->bhtail->b_size
+				    != bh->b_data) {
+					if (req->nr_segments < max_segments)
+						req->nr_segments++;
+					else continue;
+				}
 				req->bhtail->b_reqnext = bh;
 				req->bhtail = bh;
 			    	req->nr_sectors += count;
 				drive_stat_acct(req, count, 0);
 				/* Can we now merge this req with the next? */
-				attempt_merge(req, max_sectors);
+				attempt_merge(req, max_sectors, max_segments);
 			/* or to the beginning? */
 			} else if (req->sector - count == sector) {
+				if (bh->b_data + bh->b_size
+				    != req->bh->b_data) {
+					if (req->nr_segments < max_segments)
+						req->nr_segments++;
+					else continue;
+				}
 			    	bh->b_reqnext = req->bh;
 			    	req->bh = bh;
 			    	req->buffer = bh->b_data;
@@ -613,6 +635,7 @@
 	req->errors = 0;
 	req->sector = sector;
 	req->nr_sectors = count;
+	req->nr_segments = 1;
 	req->current_nr_sectors = count;
 	req->buffer = bh->b_data;
 	req->sem = NULL;
diff -u --recursive --new-file v2.3.24/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.3.24/linux/drivers/block/loop.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/block/loop.c	Mon Nov  1 10:31:34 1999
@@ -23,9 +23,12 @@
  * Reed H. Petty, rhp@draper.net
  *
  * Maximum number of loop devices now dynamic via max_loop module parameter.
- * Still fixed at 8 devices when compiled into the kernel normally.
  * Russell Kroll <rkroll@exploits.org> 19990701
  * 
+ * Maximum number of loop devices when compiled-in now selectable by passing
+ * max_loop=<1-255> to the kernel on boot.
+ * Erik I. Bolsų, <eriki@himolde.no>, Oct 31, 1999
+ *
  * Still To Fix:
  * - Advisory locking is ignored here. 
  * - Should use an own CAP_* category instead of CAP_SYS_ADMIN 
@@ -723,15 +726,12 @@
 	}
 
 	if ((max_loop < 1) || (max_loop > 255)) {
-		printk (KERN_WARNING "loop: max_loop must be between 1 and 255\n");
-		return -EINVAL;
+		printk (KERN_WARNING "loop: invalid max_loop (must be between 1 and 255), using default (8)\n");
+		max_loop = 8;
 	}
 
-#ifndef MODULE
 	printk(KERN_INFO "loop: registered device at major %d\n", MAJOR_NR);
-#else
 	printk(KERN_INFO "loop: enabling %d loop devices\n", max_loop);
-#endif
 
 	loop_dev = kmalloc (max_loop * sizeof(struct loop_device), GFP_KERNEL);
 	if (!loop_dev) {
@@ -777,4 +777,14 @@
 	kfree (loop_sizes);
 	kfree (loop_blksizes);
 }
+#endif
+
+#ifndef MODULE
+static int __init max_loop_setup(char *str)
+{
+	max_loop = simple_strtol(str,NULL,0);
+	return 1;
+}
+
+__setup("max_loop=", max_loop_setup);
 #endif
diff -u --recursive --new-file v2.3.24/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.3.24/linux/drivers/block/md.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/block/md.c	Thu Oct 28 14:34:46 1999
@@ -872,11 +872,74 @@
 EXPORT_SYMBOL(md_do_sync);
 
 #ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_md = {
-	PROC_MD, 6, "mdstat",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-};
+static int md_status_read_proc(char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	int sz = 0, i, j, size;
+	int begin = 0;
+
+	sz=sprintf( page, "Personalities : ");
+	for (i=0; i<MAX_PERSONALITY; i++)
+		if (pers[i])
+			sz+=sprintf (page+sz, "[%d %s] ", i, pers[i]->name);
+	page[sz-1]='\n';
+
+	sz+=sprintf (page+sz, "read_ahead ");
+	if (read_ahead[MD_MAJOR]==INT_MAX)
+		sz+=sprintf (page+sz, "not set\n");
+	else
+		sz+=sprintf (page+sz, "%d sectors\n", read_ahead[MD_MAJOR]);
+
+	for (i=0; i<MAX_MD_DEV; i++) {
+		if (sz < off) {
+			begin += sz;
+			off -= sz;
+			sz = 0;
+		}
+		if (sz >= off+count) {
+			*eof = 1;
+			break;
+		}
+		sz+=sprintf (page+sz, "md%d : %sactive",
+				i, md_dev[i].pers ? "" : "in");
+
+		if (md_dev[i].pers)
+			sz+=sprintf (page+sz, " %s", md_dev[i].pers->name);
+
+		for (j=0, size=0; j<md_dev[i].nb_dev; j++) {
+			sz+=sprintf (page+sz, " %s",
+				partition_name(md_dev[i].devices[j].dev));
+			size+=md_dev[i].devices[j].size;
+		}
+
+		if (md_dev[i].nb_dev) {
+			if (md_dev[i].pers)
+				sz+=sprintf (page+sz, " %d blocks", md_size[i]);
+			else
+				sz+=sprintf (page+sz, " %d blocks", size);
+		}
+
+		if (!md_dev[i].pers) {
+			sz+=sprintf (page+sz, "\n");
+			continue;
+		}
+
+		if (md_dev[i].pers->max_invalid_dev)
+			sz+=sprintf (page+sz, " maxfault=%ld",
+					MAX_FAULT(md_dev+i));
+
+		sz+=md_dev[i].pers->status (page+sz, i, md_dev+i);
+		sz+=sprintf (page+sz, "\n");
+	}
+
+	sz -= off;
+	*start = page + off;
+	if (sz>count)
+		sz = count;
+	if (sz<0)
+		sz = 0;
+	return sz;
+}
 #endif
 
 static void md_geninit (struct gendisk *gdisk)
@@ -896,7 +959,7 @@
   max_readahead[MD_MAJOR] = md_maxreadahead;
 
 #ifdef CONFIG_PROC_FS
-  proc_register(&proc_root, &proc_md);
+	create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
 #endif
 }
 
@@ -917,61 +980,6 @@
 	return rc;
     }
     return 0;
-}
-
-int get_md_status (char *page)
-{
-  int sz=0, i, j, size;
-
-  sz+=sprintf( page+sz, "Personalities : ");
-  for (i=0; i<MAX_PERSONALITY; i++)
-    if (pers[i])
-      sz+=sprintf (page+sz, "[%d %s] ", i, pers[i]->name);
-
-  page[sz-1]='\n';
-
-  sz+=sprintf (page+sz, "read_ahead ");
-  if (read_ahead[MD_MAJOR]==INT_MAX)
-    sz+=sprintf (page+sz, "not set\n");
-  else
-    sz+=sprintf (page+sz, "%d sectors\n", read_ahead[MD_MAJOR]);
-  
-  for (i=0; i<MAX_MD_DEV; i++)
-  {
-    sz+=sprintf (page+sz, "md%d : %sactive", i, md_dev[i].pers ? "" : "in");
-
-    if (md_dev[i].pers)
-      sz+=sprintf (page+sz, " %s", md_dev[i].pers->name);
-
-    size=0;
-    for (j=0; j<md_dev[i].nb_dev; j++)
-    {
-      sz+=sprintf (page+sz, " %s",
-		   partition_name(md_dev[i].devices[j].dev));
-      size+=md_dev[i].devices[j].size;
-    }
-
-    if (md_dev[i].nb_dev) {
-      if (md_dev[i].pers)
-        sz+=sprintf (page+sz, " %d blocks", md_size[i]);
-      else
-        sz+=sprintf (page+sz, " %d blocks", size);
-    }
-
-    if (!md_dev[i].pers)
-    {
-      sz+=sprintf (page+sz, "\n");
-      continue;
-    }
-
-    if (md_dev[i].pers->max_invalid_dev)
-      sz+=sprintf (page+sz, " maxfault=%ld", MAX_FAULT(md_dev+i));
-
-    sz+=md_dev[i].pers->status (page+sz, i, md_dev+i);
-    sz+=sprintf (page+sz, "\n");
-  }
-
-  return (sz);
 }
 
 int register_md_personality (int p_num, struct md_personality *p)
diff -u --recursive --new-file v2.3.24/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.3.24/linux/drivers/char/Config.in	Fri Oct 22 13:21:47 1999
+++ linux/drivers/char/Config.in	Fri Oct 29 10:59:17 1999
@@ -148,6 +148,10 @@
   if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then
     hex '  Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590
   fi
+  dep_tristate 'Trust FM radio card' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV
+  if [ "$CONFIG_RADIO_TRUST" = "y" ]; then
+    hex '  Trust i/o port (usually 0x350 or 0x358)' CONFIG_RADIO_TRUST_PORT 350
+  fi
   if [ "$CONFIG_PCI" != "n" ]; then
     dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
   fi
diff -u --recursive --new-file v2.3.24/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.3.24/linux/drivers/char/Makefile	Fri Oct 22 13:21:47 1999
+++ linux/drivers/char/Makefile	Fri Oct 29 10:59:17 1999
@@ -261,7 +261,7 @@
 else
   ifeq ($(CONFIG_SOFT_WATCHDOG),m)
   M_OBJS += softdog.o
-  endif   
+  endif
 endif
 
 ifeq ($(CONFIG_PCWATCHDOG),y)
@@ -452,7 +452,15 @@
   ifeq ($(CONFIG_RADIO_AZTECH),m)
   M_OBJS += radio-aztech.o
   endif
-endif                                             
+endif
+
+ifeq ($(CONFIG_RADIO_RTRACK2),y)
+O_OBJS += radio-rtrack2.o
+else
+  ifeq ($(CONFIG_RADIO_RTRACK2),m)
+  M_OBJS += radio-rtrack2.o
+  endif
+endif
 
 ifeq ($(CONFIG_RADIO_SF16FMI),y)
 O_OBJS += radio-sf16fmi.o
@@ -460,23 +468,15 @@
   ifeq ($(CONFIG_RADIO_SF16FMI),m)
   M_OBJS += radio-sf16fmi.o
   endif
-endif                                             
-
-ifeq ($(CONFIG_RADIO_RTRACK),y)
-O_OBJS += radio-aimslab.o
-else
-  ifeq ($(CONFIG_RADIO_RTRACK),m)
-  M_OBJS += radio-aimslab.o
-  endif
-endif                                             
+endif
 
-ifeq ($(CONFIG_RADIO_RTRACK2),y)
-O_OBJS += radio-rtrack2.o
+ifeq ($(CONFIG_RADIO_CADET),y)
+O_OBJS += radio-cadet.o
 else
-  ifeq ($(CONFIG_RADIO_RTRACK2),m)
-  M_OBJS += radio-rtrack2.o
+  ifeq ($(CONFIG_RADIO_CADET),m)
+  M_OBJS += radio-cadet.o
   endif
-endif                                             
+endif
 
 ifeq ($(CONFIG_RADIO_TYPHOON),y)
 O_OBJS += radio-typhoon.o
@@ -484,7 +484,23 @@
   ifeq ($(CONFIG_RADIO_TYPHOON),m)
   M_OBJS += radio-typhoon.o
   endif
-endif                                             
+endif
+
+ifeq ($(CONFIG_RADIO_TERRATEC),y)
+O_OBJS += radio-terratec.o
+else
+  ifeq ($(CONFIG_RADIO_TERRATEC),m)
+  M_OBJS += radio-terratec.o
+  endif
+endif
+
+ifeq ($(CONFIG_RADIO_RTRACK),y)
+O_OBJS += radio-aimslab.o
+else
+  ifeq ($(CONFIG_RADIO_RTRACK),m)
+  M_OBJS += radio-aimslab.o
+  endif
+endif
 
 ifeq ($(CONFIG_RADIO_ZOLTRIX),y)
 O_OBJS += radio-zoltrix.o
@@ -492,15 +508,7 @@
   ifeq ($(CONFIG_RADIO_ZOLTRIX),m)
   M_OBJS += radio-zoltrix.o
   endif
-endif                                             
-
-ifeq ($(CONFIG_RADIO_CADET),y)
-O_OBJS += radio-cadet.o
-else
-  ifeq ($(CONFIG_RADIO_CADET),m)
-  M_OBJS += radio-cadet.o
-  endif
-endif                                             
+endif
 
 ifeq ($(CONFIG_RADIO_MIROPCM20),y)
 O_OBJS += radio-miropcm20.o
@@ -516,13 +524,13 @@
   ifeq ($(CONFIG_RADIO_GEMTEK),m)
   M_OBJS += radio-gemtek.o
   endif
-endif                                             
+endif
 
-ifeq ($(CONFIG_RADIO_TERRATEC),y)
-O_OBJS += radio-terratec.o
+ifeq ($(CONFIG_RADIO_TRUST),y)
+O_OBJS += radio-trust.o
 else
-  ifeq ($(CONFIG_RADIO_TERRATEC),m)
-  M_OBJS += radio-terratec.o
+  ifeq ($(CONFIG_RADIO_TRUST),m)
+  M_OBJS += radio-trust.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.24/linux/drivers/char/h8.c linux/drivers/char/h8.c
--- v2.3.24/linux/drivers/char/h8.c	Sat May 15 15:05:36 1999
+++ linux/drivers/char/h8.c	Thu Oct 28 14:34:46 1999
@@ -3,6 +3,9 @@
  *
  * The H8 is used to deal with the power and thermal environment
  * of a system.
+ *
+ * Fixes:
+ *	June 1999, AV	added releasing /proc/driver/h8
  */
 
 #include <linux/config.h>
@@ -18,10 +21,8 @@
 #include <linux/fcntl.h>
 #include <linux/malloc.h>
 #include <linux/linkage.h>
-#ifdef CONFIG_PROC_FS
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
-#endif
 #include <linux/miscdevice.h>
 #include <linux/lists.h>
 #include <linux/ioport.h>
@@ -58,6 +59,8 @@
 
 #ifdef CONFIG_PROC_FS
 static int   h8_get_info(char *, char **, off_t, int, int);
+#else
+static int   h8_get_info(char *, char **, off_t, int, int) {}
 #endif
 
 /*
@@ -125,12 +128,6 @@
         &h8_fops
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry    h8_proc_entry = {
-        0, 3, "h8", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, h8_get_info
-};
-#endif
-
 union	intr_buf intrbuf;
 int	intr_buf_ptr;
 union   intr_buf xx;	
@@ -321,9 +318,7 @@
         misc_register(&h8_device);
         request_region(h8_base, 8, "h8");
 
-#ifdef CONFIG_PROC_FS
-        proc_register(&proc_root, &h8_proc_entry);
-#endif
+        create_proc_info_entry("driver/h8", 0, NULL, h8_get_info);
 
 	QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *);
 	QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *);
@@ -339,6 +334,7 @@
 
 void cleanup_module(void)
 {
+	remove_proc_entry("driver/h8", NULL);
         misc_deregister(&h8_device);
         release_region(h8_base, 8);
         free_irq(h8_irq, NULL);
@@ -355,9 +351,7 @@
         }
         printk("H8 at 0x%x IRQ %d\n", h8_base, h8_irq);
 
-#ifdef CONFIG_PROC_FS
-        proc_register(&proc_root, &h8_proc_entry);
-#endif
+        create_proc_info_entry("driver/h8", 0, NULL, h8_get_info);
 
         misc_register(&h8_device);
         request_region(h8_base, 8, "h8");
diff -u --recursive --new-file v2.3.24/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.3.24/linux/drivers/char/mem.c	Fri Oct 22 13:21:48 1999
+++ linux/drivers/char/mem.c	Thu Oct 28 13:03:38 1999
@@ -190,10 +190,7 @@
 
 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
 {
-	unsigned long offset = vma->vm_offset;
-
-	if (offset & ~PAGE_MASK)
-		return -ENXIO;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 
 	/*
 	 * Accessing memory above the top the kernel knows about or
diff -u --recursive --new-file v2.3.24/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.3.24/linux/drivers/char/misc.c	Mon Oct 11 15:38:14 1999
+++ linux/drivers/char/misc.c	Thu Oct 28 14:34:46 1999
@@ -76,7 +76,6 @@
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
 extern int dsp56k_init(void);
-extern int nvram_init(void);
 extern int radio_init(void);
 extern int pc110pad_init(void);
 extern int pmu_device_init(void);
@@ -180,13 +179,9 @@
 EXPORT_SYMBOL(misc_register);
 EXPORT_SYMBOL(misc_deregister);
 
-static struct proc_dir_entry *proc_misc;
-
 int __init misc_init(void)
 {
-	proc_misc = create_proc_entry("misc", 0, 0);
-	if (proc_misc)
-		proc_misc->read_proc = misc_read_proc;
+	create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL);
 #ifdef CONFIG_BUSMOUSE
 	bus_mouse_init();
 #endif
@@ -234,9 +229,6 @@
 #endif
 #ifdef CONFIG_ATARI_DSP56K
 	dsp56k_init();
-#endif
-#ifdef CONFIG_NVRAM
-	nvram_init();
 #endif
 #ifdef CONFIG_MISC_RADIO
 	radio_init();
diff -u --recursive --new-file v2.3.24/linux/drivers/char/nvram.c linux/drivers/char/nvram.c
--- v2.3.24/linux/drivers/char/nvram.c	Thu Aug  5 14:34:01 1999
+++ linux/drivers/char/nvram.c	Fri Oct 29 10:58:00 1999
@@ -95,9 +95,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/nvram.h>
 #include <linux/init.h>
-#ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
-#endif
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -351,9 +349,10 @@
 }
 
 
-#ifdef CONFIG_PROC_FS
-
-struct proc_dir_entry *proc_nvram;
+#ifndef CONFIG_PROC_FS
+static int nvram_read_proc( char *buffer, char **start, off_t offset,
+			    int size, int *eof, void *data) { return 0; }
+#else
 
 static int nvram_read_proc( char *buffer, char **start, off_t offset,
 							int size, int *eof, void *data )
@@ -391,7 +390,7 @@
 		}												\
 	} while(0)
 
-#endif
+#endif /* CONFIG_PROC_FS */
 
 static struct file_operations nvram_fops = {
 	nvram_llseek,
@@ -413,7 +412,7 @@
 };
 
 
-int __init nvram_init(void)
+static int __init nvram_init(void)
 {
 	/* First test whether the driver should init at all */
 	if (!CHECK_DRIVER_INIT())
@@ -421,29 +420,18 @@
 
 	printk(KERN_INFO "Non-volatile memory driver v%s\n", NVRAM_VERSION );
 	misc_register( &nvram_dev );
-#ifdef CONFIG_PROC_FS
-	if ((proc_nvram = create_proc_entry( "nvram", 0, 0 )))
-		proc_nvram->read_proc = nvram_read_proc;
-#endif
-	
+	create_proc_read_entry("driver/nvram",0,0,nvram_read_proc,NULL);
 	return( 0 );
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-	return( nvram_init() );
-}
-
-void cleanup_module (void)
+static void __exit nvram_cleanup_module (void)
 {
-#ifdef CONFIG_PROC_FS
-	if (proc_nvram)
-		remove_proc_entry( "nvram", 0 );
-#endif
+	remove_proc_entry( "driver/nvram", 0 );
 	misc_deregister( &nvram_dev );
 }
-#endif
+
+module_init(nvram_init);
+module_exit(nvram_cleanup_module);
 
 
 /*
diff -u --recursive --new-file v2.3.24/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- v2.3.24/linux/drivers/char/ppdev.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/char/ppdev.c	Fri Oct 29 11:05:08 1999
@@ -509,6 +509,7 @@
 	if (!pp)
 		return -ENOMEM;
 
+	memset (pp, 0, sizeof (struct pp_struct));
 	pp->state.mode = IEEE1284_MODE_COMPAT;
 	pp->state.phase = init_phase (pp->state.mode);
 	pp->flags = 0;
diff -u --recursive --new-file v2.3.24/linux/drivers/char/radio-cadet.c linux/drivers/char/radio-cadet.c
--- v2.3.24/linux/drivers/char/radio-cadet.c	Fri Oct 22 13:21:48 1999
+++ linux/drivers/char/radio-cadet.c	Thu Oct 28 16:12:52 1999
@@ -39,7 +39,6 @@
 static __u8 rdsin=0,rdsout=0,rdsstat=0;
 static unsigned char rdsbuf[RDS_BUFFER];
 static int cadet_lock=0;
-static int cadet_probe(void);
 
 /*
  * Signal Strength Threshold Values
@@ -543,22 +542,6 @@
 	NULL
 };
 
-int __init cadet_init(struct video_init *v)
-{
-#ifndef MODULE        
-        if(cadet_probe()<0) {
-	        return EINVAL;
-	}
-#endif
-	if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1)
-		return -EINVAL;
-		
-	request_region(io,2,"cadet");
-	printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io);
-	return 0;
-}
-
-
 #ifndef MODULE
 static int cadet_probe(void)
 {
@@ -578,9 +561,27 @@
 }
 #endif
 
+int __init cadet_init(void)
+{
+#ifndef MODULE        
+	io = cadet_probe ();
+#endif
+
+        if(io < 0) {
+#ifdef MODULE        
+		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+#endif
+	        return EINVAL;
+	}
+	if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1)
+		return -EINVAL;
+		
+	request_region(io,2,"cadet");
+	printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io);
+	return 0;
+}
 
 
-#ifdef MODULE
 
 MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
@@ -589,21 +590,12 @@
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-	if(io==-1)
-	{
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
-		return -EINVAL;
-	}
-	return cadet_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit cadet_cleanup_module(void)
 {
 	video_unregister_device(&cadet_radio);
 	release_region(io,2);
 }
 
-#endif
+module_init(cadet_init);
+module_exit(cadet_cleanup_module);
 
diff -u --recursive --new-file v2.3.24/linux/drivers/char/radio-rtrack2.c linux/drivers/char/radio-rtrack2.c
--- v2.3.24/linux/drivers/char/radio-rtrack2.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/radio-rtrack2.c	Thu Oct 28 16:12:56 1999
@@ -228,8 +228,13 @@
 	NULL
 };
 
-int __init rtrack2_init(struct video_init *v)
+static int __init rtrack2_init(void)
 {
+	if(io==-1)
+	{
+		printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
+		return -EINVAL;
+	}
 	if (check_region(io, 4)) 
 	{
 		printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
@@ -252,8 +257,6 @@
 	return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Ben Pfaff");
 MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
 MODULE_PARM(io, "i");
@@ -261,23 +264,14 @@
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-	if(io==-1)
-	{
-		printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
-		return -EINVAL;
-	}
-	return rtrack2_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit rtrack2_cleanup_module(void)
 {
 	video_unregister_device(&rtrack2_radio);
 	release_region(io,4);
 }
 
-#endif
+module_init(rtrack2_init);
+module_exit(rtrack2_cleanup_module);
 
 /*
   Local variables:
diff -u --recursive --new-file v2.3.24/linux/drivers/char/radio-sf16fmi.c linux/drivers/char/radio-sf16fmi.c
--- v2.3.24/linux/drivers/char/radio-sf16fmi.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/radio-sf16fmi.c	Thu Oct 28 16:13:00 1999
@@ -289,8 +289,13 @@
 	NULL
 };
 
-int __init fmi_init(struct video_init *v)
+static int __init fmi_init(void)
 {
+	if(io==-1)
+	{
+		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+		return -EINVAL;
+	}
 	if (check_region(io, 2)) 
 	{
 		printk(KERN_ERR "fmi: port 0x%x already in use\n", io);
@@ -316,8 +321,6 @@
 	return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
 MODULE_DESCRIPTION("A driver for the SF16MI radio.");
 MODULE_PARM(io, "i");
@@ -325,20 +328,12 @@
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-	if(io==-1)
-	{
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
-		return -EINVAL;
-	}
-	return fmi_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit fmi_cleanup_module(void)
 {
 	video_unregister_device(&fmi_radio);
 	release_region(io,2);
 }
 
-#endif
+module_init(fmi_init);
+module_exit(fmi_cleanup_module);
+
diff -u --recursive --new-file v2.3.24/linux/drivers/char/radio-terratec.c linux/drivers/char/radio-terratec.c
--- v2.3.24/linux/drivers/char/radio-terratec.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/radio-terratec.c	Thu Oct 28 16:13:03 1999
@@ -307,8 +307,13 @@
 	NULL
 };
 
-int __init terratec_init(struct video_init *v)
+static int __init terratec_init(void)
 {
+	if(io==-1)
+	{
+		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+		return -EINVAL;
+	}
 	if (check_region(io, 2)) 
 	{
 		printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io);
@@ -334,8 +339,6 @@
 	return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("R.OFFERMANNS & others");
 MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card.");
 MODULE_PARM(io, "i");
@@ -343,21 +346,13 @@
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-	if(io==-1)
-	{
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
-		return -EINVAL;
-	}
-	return terratec_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit terratec_cleanup_module(void)
 {
 	video_unregister_device(&terratec_radio);
 	release_region(io,2);
 	printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n");	
 }
 
-#endif
+module_init(terratec_init);
+module_exit(terratec_cleanup_module);
+
diff -u --recursive --new-file v2.3.24/linux/drivers/char/radio-trust.c linux/drivers/char/radio-trust.c
--- v2.3.24/linux/drivers/char/radio-trust.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/radio-trust.c	Thu Oct 28 16:13:07 1999
@@ -333,16 +333,12 @@
 	return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
 
 EXPORT_NO_SYMBOLS;
-
-#endif /* MODULE */
 
 static void __exit cleanup_trust_module(void)
 {
diff -u --recursive --new-file v2.3.24/linux/drivers/char/radio-typhoon.c linux/drivers/char/radio-typhoon.c
--- v2.3.24/linux/drivers/char/radio-typhoon.c	Mon May 10 13:00:10 1999
+++ linux/drivers/char/radio-typhoon.c	Fri Oct 29 10:59:17 1999
@@ -72,15 +72,8 @@
 static int typhoon_open(struct video_device *dev, int flags);
 static void typhoon_close(struct video_device *dev);
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-static int typhoon_read_proc(char *buf, char **start, off_t offset, int len,
-	                     int unused);
-#endif
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-int typhoon_init(struct video_init *v);
-#else
-int typhoon_init(struct video_init *v) __init;
+static int typhoon_get_info(char *buf, char **start, off_t offset, int len,
+	                    int unused);
 #endif
 
 static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
@@ -306,8 +299,8 @@
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
 
-static int typhoon_read_proc(char *buf, char **start, off_t offset, int len,
-	              int unused)
+static int typhoon_get_info(char *buf, char **start, off_t offset, int len,
+	              	    int unused)
 {
 	#ifdef MODULE
 	    #define MODULEPROCSTRING "Driver loaded as a module"
@@ -337,53 +330,8 @@
 	return len;
 }
 
-static struct proc_dir_entry typhoon_proc_entry = {
-	0,			/* low_ino: inode is dynamic */
-	13, "radio-typhoon",	/* length of name and name */
-	S_IFREG | S_IRUGO,	/* mode */
-	1, 0, 0,		/* nlinks, owner, group */
-	0,			/* size -- not used */
-	NULL,			/* operations -- use default */
-	&typhoon_read_proc,	/* function used to read data */
-	/* nothing more */
-};
-
 #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
 
-int typhoon_init(struct video_init *v)
-{
-	printk(KERN_INFO BANNER);
-	if (check_region(typhoon_unit.iobase, 8)) {
-		printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
-		       typhoon_unit.iobase);
-		return -EBUSY;
-	}
-
-	typhoon_radio.priv = &typhoon_unit;
-	if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1)
-		return -EINVAL;
-
-	request_region(typhoon_unit.iobase, 8, "typhoon");
-	printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
-	printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
-	       typhoon_unit.mutefreq);
-	typhoon_unit.mutefreq <<= 4;
-
-	/* mute card - prevents noisy bootups */
-	typhoon_mute(&typhoon_unit);
-
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-	
-	if (proc_register(&proc_root, &typhoon_proc_entry))
-	    	printk(KERN_ERR "radio-typhoon: registering /proc/radio-typhoon failed\n");
-
-#endif
-
-	return 0;
-}
-
-#ifdef MODULE
-
 MODULE_AUTHOR("Dr. Henrik Seidel");
 MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
 MODULE_PARM(io, "i");
@@ -394,10 +342,14 @@
 EXPORT_NO_SYMBOLS;
 
 static int io = -1;
+
+#ifdef MODULE
 static unsigned long mutefreq = 0;
+#endif
 
-int init_module(void)
+static int __init typhoon_init(void)
 {
+#ifdef MODULE
 	if (io == -1) {
 		printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n");
 		return -EINVAL;
@@ -410,24 +362,49 @@
 		return -EINVAL;
 	}
 	typhoon_unit.mutefreq = mutefreq;
+#endif /* MODULE */
 
-	return typhoon_init(NULL);
-}
+	printk(KERN_INFO BANNER);
+	io = typhoon_unit.iobase;
+	if (check_region(io, 8)) {
+		printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
+		       typhoon_unit.iobase);
+		return -EBUSY;
+	}
 
-void cleanup_module(void)
-{
+	typhoon_radio.priv = &typhoon_unit;
+	if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1)
+		return -EINVAL;
+
+	request_region(typhoon_unit.iobase, 8, "typhoon");
+	printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
+	printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
+	       typhoon_unit.mutefreq);
+	typhoon_unit.mutefreq <<= 4;
+
+	/* mute card - prevents noisy bootups */
+	typhoon_mute(&typhoon_unit);
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+	if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL,
+				    typhoon_get_info)) 
+	    	printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
+#endif
+
+	return 0;
+}
 
-	if (proc_unregister(&proc_root, typhoon_proc_entry.low_ino))
-	    	printk(KERN_ERR "radio-typhoon: unregistering /proc/radio-typhoon failed\n");
+static void __exit typhoon_cleanup_module(void)
+{
 
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+	remove_proc_entry("driver/radio-typhoon", NULL);
 #endif
 
 	video_unregister_device(&typhoon_radio);
 	release_region(io, 8);
 }
 
-#endif
-
+module_init(typhoon_init);
+module_exit(typhoon_cleanup_module);
 
diff -u --recursive --new-file v2.3.24/linux/drivers/char/radio-zoltrix.c linux/drivers/char/radio-zoltrix.c
--- v2.3.24/linux/drivers/char/radio-zoltrix.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/radio-zoltrix.c	Thu Oct 28 16:13:13 1999
@@ -354,8 +354,12 @@
 	NULL
 };
 
-int __init zoltrix_init(struct video_init *v)
+static int __init zoltrix_init(void)
 {
+	if (io == -1) {
+		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+		return -EINVAL;
+	}
 	if (check_region(io, 2)) {
 		printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
 		return -EBUSY;
@@ -390,8 +394,6 @@
 	return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("C.van Schaik");
 MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus.");
 MODULE_PARM(io, "i");
@@ -399,19 +401,12 @@
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-	if (io == -1) {
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
-		return -EINVAL;
-	}
-	return zoltrix_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit zoltrix_cleanup_module(void)
 {
 	video_unregister_device(&zoltrix_radio);
 	release_region(io, 2);
 }
 
-#endif
+module_init(zoltrix_init);
+module_exit(zoltrix_cleanup_module);
+
diff -u --recursive --new-file v2.3.24/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- v2.3.24/linux/drivers/char/riscom8.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/char/riscom8.c	Thu Oct 28 10:42:02 1999
@@ -75,6 +75,8 @@
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #endif
 
+#define RS_EVENT_WRITE_WAKEUP	0
+
 DECLARE_TASK_QUEUE(tq_riscom);
 
 #define RISCOM_TYPE_NORMAL	1
diff -u --recursive --new-file v2.3.24/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.3.24/linux/drivers/char/serial.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/char/serial.c	Thu Oct 28 10:45:51 1999
@@ -152,12 +152,12 @@
 #endif
 #endif /* NEW_MODULES */
 #include <linux/module.h>
-
+#include <linux/types.h>
 #ifdef LOCAL_HEADERS
 #include "serial_local.h"
 #else
-#include <linux/serialP.h>
 #include <linux/serial.h>
+#include <linux/serialP.h>
 #include <linux/serial_reg.h>
 #include <asm/serial.h>
 static char *serial_version = "4.30";
diff -u --recursive --new-file v2.3.24/linux/drivers/char/specialix.c linux/drivers/char/specialix.c
--- v2.3.24/linux/drivers/char/specialix.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/char/specialix.c	Thu Oct 28 10:42:02 1999
@@ -171,7 +171,8 @@
 
 DECLARE_TASK_QUEUE(tq_specialix);
 
-
+#undef RS_EVENT_WRITE_WAKEUP
+#define RS_EVENT_WRITE_WAKEUP	0
 
 #define SPECIALIX_TYPE_NORMAL	1
 #define SPECIALIX_TYPE_CALLOUT	2
diff -u --recursive --new-file v2.3.24/linux/drivers/char/sx.c linux/drivers/char/sx.c
--- v2.3.24/linux/drivers/char/sx.c	Thu Aug  5 14:47:44 1999
+++ linux/drivers/char/sx.c	Thu Oct 28 10:42:02 1999
@@ -340,6 +340,8 @@
 
 #endif
 
+#undef RS_EVENT_WRITE_WAKEUP
+#define RS_EVENT_WRITE_WAKEUP	0
 
 
 #include "generic_serial.h"
diff -u --recursive --new-file v2.3.24/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.3.24/linux/drivers/char/videodev.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/videodev.c	Thu Oct 28 16:13:20 1999
@@ -57,21 +57,6 @@
 #ifdef CONFIG_VIDEO_PLANB
 extern int init_planbs(struct video_init *);
 #endif
-#ifdef CONFIG_RADIO_RTRACK2
-extern int rtrack2_init(struct video_init *);
-#endif
-#ifdef CONFIG_RADIO_SF16FMI
-extern int fmi_init(struct video_init *);
-#endif
-#ifdef CONFIG_RADIO_TYPHOON
-extern int typhoon_init(struct video_init *);
-#endif
-#ifdef CONFIG_RADIO_CADET
-extern int cadet_init(struct video_init *);
-#endif
-#ifdef CONFIG_RADIO_TERRATEC
-extern int terratec_init(struct video_init *);
-#endif
 #ifdef CONFIG_VIDEO_ZORAN
 extern int init_zoran_cards(struct video_init *);
 #endif
@@ -92,21 +77,6 @@
 #endif	
 #ifdef CONFIG_VIDEO_PLANB
 	{"planb", init_planbs},
-#endif
-#ifdef CONFIG_RADIO_RTRACK2
-	{"RTrack2", rtrack2_init}, 
-#endif
-#ifdef CONFIG_RADIO_SF16FMI
-	{"SF16FMI", fmi_init}, 
-#endif	
-#ifdef CONFIG_RADIO_CADET
-	{"Cadet", cadet_init},
-#endif
-#ifdef CONFIG_RADIO_TYPHOON
-	{"radio-typhoon", typhoon_init},
-#endif
-#ifdef CONFIG_RADIO_TERRATEC
-	{"radio-terratec", terratec_init},
 #endif
 #ifdef CONFIG_VIDEO_ZORAN
 	{"zoran", init_zoran_cards},
diff -u --recursive --new-file v2.3.24/linux/drivers/misc/acpi.c linux/drivers/misc/acpi.c
--- v2.3.24/linux/drivers/misc/acpi.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/misc/acpi.c	Mon Nov  1 13:28:43 1999
@@ -74,6 +74,7 @@
 
 static struct acpi_facp *acpi_facp = NULL;
 static int acpi_fake_facp = 0;
+static struct acpi_facs *acpi_facs = NULL;
 static unsigned long acpi_facp_addr = 0;
 static unsigned long acpi_dsdt_addr = 0;
 
@@ -88,8 +89,19 @@
 static unsigned long acpi_p_lvl3_lat = ~0UL;
 
 /* Initialize to guaranteed harmless port read */
-static unsigned long acpi_p_lvl2 = 0x80;
-static unsigned long acpi_p_lvl3 = 0x80;
+static unsigned long acpi_p_lvl2 = ACPI_P_LVL_DISABLED;
+static unsigned long acpi_p_lvl3 = ACPI_P_LVL_DISABLED;
+
+// bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
+static unsigned long acpi_slp_typ[] = 
+{
+	ACPI_SLP_TYP_DISABLED, /* S0 */
+	ACPI_SLP_TYP_DISABLED, /* S1 */
+	ACPI_SLP_TYP_DISABLED, /* S2 */
+	ACPI_SLP_TYP_DISABLED, /* S3 */
+	ACPI_SLP_TYP_DISABLED, /* S4 */
+	ACPI_SLP_TYP_DISABLED  /* S5 */
+};
 
 static struct ctl_table acpi_table[] =
 {
@@ -125,10 +137,14 @@
 
 	{ACPI_P_LVL2_LAT, "p_lvl2_lat",
 	 &acpi_p_lvl2_lat, sizeof(acpi_p_lvl2_lat),
-	 0600, NULL, &acpi_do_ulong},
+	 0644, NULL, &acpi_do_ulong},
 
 	{ACPI_P_LVL3_LAT, "p_lvl3_lat",
 	 &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat),
+	 0644, NULL, &acpi_do_ulong},
+
+	{ACPI_S5_SLP_TYP, "s5_slp_typ",
+	 &acpi_slp_typ[5], sizeof(acpi_slp_typ[5]),
 	 0600, NULL, &acpi_do_ulong},
 
 	{0}
@@ -136,7 +152,7 @@
 
 static struct ctl_table acpi_dir_table[] =
 {
-	{CTL_ACPI, "acpi", NULL, 0, 0500, acpi_table},
+	{CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table},
 	{0}
 };
 
@@ -379,6 +395,11 @@
 			acpi_facp = (struct acpi_facp*) dt;
 			acpi_facp_addr = *rsdt_entry;
 			acpi_dsdt_addr = acpi_facp->dsdt;
+
+			if (acpi_facp->facs) {
+				acpi_facs = (struct acpi_facs*)
+					acpi_map_table(acpi_facp->facs);
+			}
 		}
 		else {
 			acpi_unmap_table(dt);
@@ -405,6 +426,7 @@
 		acpi_unmap_table((struct acpi_table*) acpi_facp);
 	else
 		kfree(acpi_facp);
+	acpi_unmap_table((struct acpi_table*) acpi_facs);
 }
 
 /*
@@ -575,8 +597,8 @@
 	case 3:
 		pm2_cnt = acpi_facp->pm2_cnt;
 		if (pm2_cnt) {
-			/* Disable PCI arbitration while sleeping,
-			   to avoid DMA corruption? */
+				/* Disable PCI arbitration while sleeping,
+				   to avoid DMA corruption? */
 			outb(inb(pm2_cnt) | ACPI_ARB_DIS, pm2_cnt);
 			inb(acpi_p_lvl3);
 			outb(inb(pm2_cnt) & ~ACPI_ARB_DIS, pm2_cnt);
@@ -602,6 +624,42 @@
 }
 
 /*
+ * Enter system sleep state
+ */
+static void acpi_enter_sx(int state)
+{
+	unsigned long slp_typ = acpi_slp_typ[state];
+	if (slp_typ != ACPI_SLP_TYP_DISABLED) {
+		u16 typa, typb, value;
+
+		// bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
+		typa = (slp_typ >> 8) & 0xff;
+		typb = slp_typ & 0xff;
+
+		typa = ((typa << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK);
+		typb = ((typb << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK);
+
+		// set SLP_TYPa/b and SLP_EN
+		if (acpi_facp->pm1a_cnt) {
+			value = inw(acpi_facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK;
+			outw(value | typa | ACPI_SLP_EN, acpi_facp->pm1a_cnt);
+		}
+		if (acpi_facp->pm1b_cnt) {
+			value = inw(acpi_facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK;
+			outw(value | typb | ACPI_SLP_EN, acpi_facp->pm1b_cnt);
+		}
+	}
+}
+
+/*
+ * Enter soft-off (S5)
+ */
+static void acpi_power_off_handler(void)
+{
+	acpi_enter_sx(5);
+}
+
+/*
  * Claim ACPI I/O ports
  */
 static int acpi_claim_ioports(struct acpi_facp *facp)
@@ -806,7 +864,7 @@
 			 size_t *len)
 {
 	u32 pm1_status = 0, gpe_status = 0;
-	char str[4 * sizeof(u32) + 6];
+	char str[4 * sizeof(u32) + 7];
 	int size;
 
 	if (write)
@@ -879,6 +937,7 @@
 		return 0;
 #endif
 
+	acpi_power_off = acpi_power_off_handler;
 	acpi_idle = acpi_idle_handler;
 
 	return 0;
@@ -890,6 +949,7 @@
 static void __exit acpi_exit(void)
 {
 	acpi_idle = NULL;
+	acpi_power_off = NULL;
 
 	unregister_sysctl_table(acpi_sysctl);
 	acpi_disable(acpi_facp);
diff -u --recursive --new-file v2.3.24/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v2.3.24/linux/drivers/net/3c503.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/3c503.c	Thu Oct 28 16:13:20 1999
@@ -449,7 +449,7 @@
     if (dev->mem_start) {	/* Shared memory transfer */
 	unsigned long dest_addr = dev->mem_start +
 	    ((start_page - ei_status.tx_start_page) << 8);
-	memcpy_toio(dest_addr, buf, count);
+	isa_memcpy_toio(dest_addr, buf, count);
 	outb(EGACFR_NORM, E33G_GACFR);	/* Back to bank1 in case on bank0 */
 	return;
     }
@@ -514,7 +514,7 @@
     unsigned short word;
 
     if (dev->mem_start) {       /* Use the shared memory. */
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	return;
     }
 
@@ -560,12 +560,12 @@
 	if (dev->mem_start + ring_offset + count > end_of_ring) {
 	    /* We must wrap the input move. */
 	    int semi_count = end_of_ring - (dev->mem_start + ring_offset);
-	    memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
+	    isa_memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
 	    count -= semi_count;
-	    memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+	    isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
+		isa_eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
 	}
 	return;
     }
diff -u --recursive --new-file v2.3.24/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
--- v2.3.24/linux/drivers/net/3c507.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/net/3c507.c	Fri Oct 29 13:19:49 1999
@@ -462,7 +462,7 @@
 			return 1;
 		if (net_debug > 1)
 			printk("%s: transmit timed out, %s?  ", dev->name,
-				   readw(shmem+iSCB_STATUS) & 0x8000 ? "IRQ conflict" :
+				   isa_readw(shmem+iSCB_STATUS) & 0x8000 ? "IRQ conflict" :
 				   "network cable problem");
 		/* Try to restart the adaptor. */
 		if (lp->last_restart == lp->stats.tx_packets) {
@@ -472,7 +472,7 @@
 		} else {
 			/* Issue the channel attention signal and hope it "gets better". */
 			if (net_debug > 1) printk("Kicking board.\n");
-			writew(0xf000|CUC_START|RX_START,shmem+iSCB_CMD);
+			isa_writew(0xf000|CUC_START|RX_START,shmem+iSCB_CMD);
 			outb(0, ioaddr + SIGNAL_CA);			/* Issue channel-attn. */
 			lp->last_restart = lp->stats.tx_packets;
 		}
@@ -533,7 +533,7 @@
 
 	spin_lock(&lp->lock);
 
-	status = readw(shmem+iSCB_STATUS);
+	status = isa_readw(shmem+iSCB_STATUS);
 
 	if (net_debug > 4) {
 		printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
@@ -544,7 +544,7 @@
 
 	/* Reap the Tx packet buffers. */
 	while (lp->tx_reap != lp->tx_head) {
-	  unsigned short tx_status = readw(shmem+lp->tx_reap);
+	  unsigned short tx_status = isa_readw(shmem+lp->tx_reap);
 
 	  if (tx_status == 0) {
 		if (net_debug > 5)  printk("Couldn't reap %#x.\n", lp->tx_reap);
@@ -599,11 +599,11 @@
 			printk("%s: Rx unit stopped, status %04x, restarting.\n",
 				   dev->name, status);
 		init_rx_bufs(dev);
-		writew(RX_BUF_START,shmem+iSCB_RFA);
+		isa_writew(RX_BUF_START,shmem+iSCB_RFA);
 		ack_cmd |= RX_START;
 	}
 
-	writew(ack_cmd,shmem+iSCB_CMD);
+	isa_writew(ack_cmd,shmem+iSCB_CMD);
 	outb(0, ioaddr + SIGNAL_CA);			/* Issue channel-attn. */
 
 	/* Clear the latched interrupt. */
@@ -625,7 +625,7 @@
 	dev->start = 0;
 
 	/* Flush the Tx and disable Rx. */
-	writew(RX_SUSPEND | CUC_SUSPEND,shmem+iSCB_CMD);
+	isa_writew(RX_SUSPEND | CUC_SUSPEND,shmem+iSCB_CMD);
 	outb(0, ioaddr + SIGNAL_CA);
 
 	/* Disable the 82586's input to the interrupt line. */
@@ -665,24 +665,24 @@
 
 	  write_ptr = dev->mem_start + cur_rxbuf;
 
-		writew(0x0000,write_ptr);			/* Status */
-		writew(0x0000,write_ptr+=2);			/* Command */
-		writew(cur_rxbuf + RX_BUF_SIZE,write_ptr+=2);	/* Link */
-		writew(cur_rxbuf + 22,write_ptr+=2);		/* Buffer offset */
-		writew(0x0000,write_ptr+=2);			/* Pad for dest addr. */
-		writew(0x0000,write_ptr+=2);
-		writew(0x0000,write_ptr+=2);
-		writew(0x0000,write_ptr+=2);			/* Pad for source addr. */
-		writew(0x0000,write_ptr+=2);
-		writew(0x0000,write_ptr+=2);
-		writew(0x0000,write_ptr+=2);			/* Pad for protocol. */
-
-		writew(0x0000,write_ptr+=2);			/* Buffer: Actual count */
-		writew(-1,write_ptr+=2);			/* Buffer: Next (none). */
-		writew(cur_rxbuf + 0x20 + SCB_base,write_ptr+=2);/* Buffer: Address low */
-		writew(0x0000,write_ptr+=2);
+		isa_writew(0x0000,write_ptr);			/* Status */
+		isa_writew(0x0000,write_ptr+=2);			/* Command */
+		isa_writew(cur_rxbuf + RX_BUF_SIZE,write_ptr+=2);	/* Link */
+		isa_writew(cur_rxbuf + 22,write_ptr+=2);		/* Buffer offset */
+		isa_writew(0x0000,write_ptr+=2);			/* Pad for dest addr. */
+		isa_writew(0x0000,write_ptr+=2);
+		isa_writew(0x0000,write_ptr+=2);
+		isa_writew(0x0000,write_ptr+=2);			/* Pad for source addr. */
+		isa_writew(0x0000,write_ptr+=2);
+		isa_writew(0x0000,write_ptr+=2);
+		isa_writew(0x0000,write_ptr+=2);			/* Pad for protocol. */
+
+		isa_writew(0x0000,write_ptr+=2);			/* Buffer: Actual count */
+		isa_writew(-1,write_ptr+=2);			/* Buffer: Next (none). */
+		isa_writew(cur_rxbuf + 0x20 + SCB_base,write_ptr+=2);/* Buffer: Address low */
+		isa_writew(0x0000,write_ptr+=2);
 		/* Finally, the number of bytes in the buffer. */
-		writew(0x8000 + RX_BUF_SIZE-0x20,write_ptr+=2);
+		isa_writew(0x8000 + RX_BUF_SIZE-0x20,write_ptr+=2);
 
 		lp->rx_tail = cur_rxbuf;
 		cur_rxbuf += RX_BUF_SIZE;
@@ -691,8 +691,8 @@
 	/* Terminate the list by setting the EOL bit, and wrap the pointer to make
 	   the list a ring. */
 	write_ptr = dev->mem_start + lp->rx_tail + 2;
-	writew(0xC000,write_ptr);				/* Command, mark as last. */
-	writew(lp->rx_head,write_ptr+2);			/* Link */
+	isa_writew(0xC000,write_ptr);				/* Command, mark as last. */
+	isa_writew(lp->rx_head,write_ptr+2);			/* Link */
 }
 
 static void init_82586_mem(struct net_device *dev)
@@ -710,13 +710,13 @@
 	init_words[7] = SCB_BASE;
 
 	/* Write the words at 0xfff6 (address-aliased to 0xfffff6). */
-	memcpy_toio(dev->mem_end-10, init_words, 10);
+	isa_memcpy_toio(dev->mem_end-10, init_words, 10);
 
 	/* Write the words at 0x0000. */
-	memcpy_toio(dev->mem_start, init_words + 5, sizeof(init_words) - 10);
+	isa_memcpy_toio(dev->mem_start, init_words + 5, sizeof(init_words) - 10);
 
 	/* Fill in the station address. */
-	memcpy_toio(dev->mem_start+SA_OFFSET, dev->dev_addr,
+	isa_memcpy_toio(dev->mem_start+SA_OFFSET, dev->dev_addr,
 		   sizeof(dev->dev_addr));
 
 	/* The Tx-block list is written as needed.  We just set up the values. */
@@ -734,11 +734,11 @@
 
 	{
 		int boguscnt = 50;
-		while (readw(shmem+iSCB_STATUS) == 0)
+		while (isa_readw(shmem+iSCB_STATUS) == 0)
 			if (--boguscnt == 0) {
 				printk("%s: i82586 initialization timed out with status %04x,"
 					   "cmd %04x.\n", dev->name,
-					   readw(shmem+iSCB_STATUS), readw(shmem+iSCB_CMD));
+					   isa_readw(shmem+iSCB_STATUS), isa_readw(shmem+iSCB_CMD));
 				break;
 			}
 		/* Issue channel-attn -- the 82586 won't start. */
@@ -749,7 +749,7 @@
 	outb(0x84, ioaddr + MISC_CTRL);
 	if (net_debug > 4)
 		printk("%s: Initialized 82586, status %04x.\n", dev->name,
-			   readw(shmem+iSCB_STATUS));
+			   isa_readw(shmem+iSCB_STATUS));
 	return;
 }
 
@@ -761,27 +761,27 @@
 	unsigned long write_ptr = dev->mem_start + tx_block;
 
 	/* Set the write pointer to the Tx block, and put out the header. */
-	writew(0x0000,write_ptr);			/* Tx status */
-	writew(CMD_INTR|CmdTx,write_ptr+=2);		/* Tx command */
-	writew(tx_block+16,write_ptr+=2);		/* Next command is a NoOp. */
-	writew(tx_block+8,write_ptr+=2);			/* Data Buffer offset. */
+	isa_writew(0x0000,write_ptr);			/* Tx status */
+	isa_writew(CMD_INTR|CmdTx,write_ptr+=2);		/* Tx command */
+	isa_writew(tx_block+16,write_ptr+=2);		/* Next command is a NoOp. */
+	isa_writew(tx_block+8,write_ptr+=2);			/* Data Buffer offset. */
 
 	/* Output the data buffer descriptor. */
-	writew(length | 0x8000,write_ptr+=2);		/* Byte count parameter. */
-	writew(-1,write_ptr+=2);			/* No next data buffer. */
-	writew(tx_block+22+SCB_BASE,write_ptr+=2);	/* Buffer follows the NoOp command. */
-	writew(0x0000,write_ptr+=2);			/* Buffer address high bits (always zero). */
+	isa_writew(length | 0x8000,write_ptr+=2);		/* Byte count parameter. */
+	isa_writew(-1,write_ptr+=2);			/* No next data buffer. */
+	isa_writew(tx_block+22+SCB_BASE,write_ptr+=2);	/* Buffer follows the NoOp command. */
+	isa_writew(0x0000,write_ptr+=2);			/* Buffer address high bits (always zero). */
 
 	/* Output the Loop-back NoOp command. */
-	writew(0x0000,write_ptr+=2);			/* Tx status */
-	writew(CmdNOp,write_ptr+=2);			/* Tx command */
-	writew(tx_block+16,write_ptr+=2);		/* Next is myself. */
+	isa_writew(0x0000,write_ptr+=2);			/* Tx status */
+	isa_writew(CmdNOp,write_ptr+=2);			/* Tx command */
+	isa_writew(tx_block+16,write_ptr+=2);		/* Next is myself. */
 
 	/* Output the packet at the write pointer. */
-	memcpy_toio(write_ptr+2, buf, length);
+	isa_memcpy_toio(write_ptr+2, buf, length);
 
 	/* Set the old command link pointing to this send packet. */
-	writew(tx_block,dev->mem_start + lp->tx_cmd_link);
+	isa_isa_writew(tx_block,dev->mem_start + lp->tx_cmd_link);
 	lp->tx_cmd_link = tx_block + 20;
 
 	/* Set the next free tx region. */
@@ -807,13 +807,13 @@
 	ushort boguscount = 10;
 	short frame_status;
 
-	while ((frame_status = readw(shmem+rx_head)) < 0) {   /* Command complete */
+	while ((frame_status = isa_readw(shmem+rx_head)) < 0) {   /* Command complete */
 		unsigned long read_frame = dev->mem_start + rx_head;
-		ushort rfd_cmd = readw(read_frame+2);
-		ushort next_rx_frame = readw(read_frame+4);
-		ushort data_buffer_addr = readw(read_frame+6);
+		ushort rfd_cmd = isa_readw(read_frame+2);
+		ushort next_rx_frame = isa_readw(read_frame+4);
+		ushort data_buffer_addr = isa_readw(read_frame+6);
 		unsigned long data_frame = dev->mem_start + data_buffer_addr;
-		ushort pkt_len = readw(data_frame);
+		ushort pkt_len = isa_readw(data_frame);
 
 		if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
 			|| (pkt_len & 0xC000) != 0xC000) {
@@ -845,7 +845,7 @@
 			skb->dev = dev;
 
 			/* 'skb->data' points to the start of sk_buff data area. */
-			memcpy_fromio(skb_put(skb,pkt_len), data_frame + 10, pkt_len);
+			isa_memcpy_fromio(skb_put(skb,pkt_len), data_frame + 10, pkt_len);
 
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
@@ -853,10 +853,10 @@
 		}
 
 		/* Clear the status word and set End-of-List on the rx frame. */
-		writew(0,read_frame);
-		writew(0xC000,read_frame+2);
+		isa_writew(0,read_frame);
+		isa_writew(0xC000,read_frame+2);
 		/* Clear the end-of-list on the prev. RFD. */
-		writew(0x0000,dev->mem_start + rx_tail + 2);
+		isa_writew(0x0000,dev->mem_start + rx_tail + 2);
 
 		rx_tail = rx_head;
 		rx_head = next_rx_frame;
diff -u --recursive --new-file v2.3.24/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- v2.3.24/linux/drivers/net/ac3200.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/ac3200.c	Fri Oct 29 13:19:49 1999
@@ -293,7 +293,7 @@
 ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - AC_START_PG)<<8);
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 }
 
 /*  Block input and output are easy on shared memory ethercards, the only
@@ -307,12 +307,12 @@
 	if (xfer_start + count > dev->rmem_end) {
 		/* We must wrap the input move. */
 		int semi_count = dev->rmem_end - xfer_start;
-		memcpy_fromio(skb->data, xfer_start, semi_count);
+		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 }
 
@@ -321,7 +321,7 @@
 {
 	unsigned long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8);
 
-	memcpy_toio(shmem, buf, count);
+	isa_memcpy_toio(shmem, buf, count);
 }
 
 static int ac_close_card(struct net_device *dev)
diff -u --recursive --new-file v2.3.24/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
--- v2.3.24/linux/drivers/net/bmac.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/bmac.c	Thu Oct 28 14:34:46 1999
@@ -3,6 +3,9 @@
  * Apple Powermacs.  Assumes it's under a DBDMA controller.
  *
  * Copyright (C) 1998 Randy Gobbel.
+ *
+ * May 1999, Al Viro: proper release of /proc/net/bmac entry, switched to
+ * dynamic procfs inode.
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -1378,14 +1381,7 @@
     
 	if (!bmac_reset_and_enable(dev, 0)) return -ENOMEM;
     
-#ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_BMAC, 4, "bmac",
-			S_IFREG | S_IRUGO, 1, 0, 0,
-			0, &proc_net_inode_operations,
-			bmac_proc_info
-			});
-#endif
+	proc_net_create ("bmac", 0, bmac_proc_info);
 
 	return 0;
 }
@@ -1627,6 +1623,7 @@
 
     bp = (struct bmac_data *) bmac_devs->priv;
     unregister_netdev(bmac_devs);
+    proc_net_remove("bmac");
 
     free_irq(bmac_devs->irq, bmac_misc_intr);
     free_irq(bp->tx_dma_intr, bmac_txdma_intr);
diff -u --recursive --new-file v2.3.24/linux/drivers/net/es3210.c linux/drivers/net/es3210.c
--- v2.3.24/linux/drivers/net/es3210.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/es3210.c	Fri Oct 29 13:19:49 1999
@@ -321,7 +321,7 @@
 es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - ES_START_PG)<<8);
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
 }
 
@@ -339,12 +339,12 @@
 	if (xfer_start + count > dev->rmem_end) {
 		/* Packet wraps over end of ring buffer. */
 		int semi_count = dev->rmem_end - xfer_start;
-		memcpy_fromio(skb->data, xfer_start, semi_count);
+		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 	} else {
 		/* Packet is in one chunk. */
-		memcpy_fromio(skb->data, xfer_start, count);
+		isa_eth_io_copy_and_csum(skb, xfer_start, count, 0);
 	}
 }
 
@@ -354,7 +354,7 @@
 	unsigned long shmem = dev->mem_start + ((start_page - ES_START_PG)<<8);
 
 	count = (count + 3) & ~3;     /* Round up to doubleword */
-	memcpy_toio(shmem, buf, count);
+	isa_memcpy_toio(shmem, buf, count);
 }
 
 static int es_open(struct net_device *dev)
diff -u --recursive --new-file v2.3.24/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v2.3.24/linux/drivers/net/ewrk3.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/ewrk3.c	Fri Oct 29 13:19:49 1999
@@ -829,16 +829,16 @@
 							writeb(0x04, (char *) buf);	/* index byte */
 							buf += 1;
 							writeb(0x00, (char *) (buf + skb->len));	/* Write the XCT flag */
-							memcpy_toio(buf, skb->data, PRELOAD);	/* Write PRELOAD bytes */
+							isa_memcpy_toio(buf, skb->data, PRELOAD);	/* Write PRELOAD bytes */
 							outb(page, EWRK3_TQ);	/* Start sending pkt */
-							memcpy_toio(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD);
+							isa_memcpy_toio(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD);
 							writeb(0xff, (char *) (buf + skb->len));	/* Write the XCT flag */
 						} else {
 							writeb((char) ((skb->len >> 8) & 0xff), (char *) buf);
 							buf += 1;
 							writeb(0x04, (char *) buf);	/* index byte */
 							buf += 1;
-							memcpy_toio((char *) buf, skb->data, skb->len);		/* Write data bytes */
+							isa_memcpy_toio(buf, skb->data, skb->len);		/* Write data bytes */
 							outb(page, EWRK3_TQ);	/* Start sending pkt */
 						}
 					}
@@ -1012,7 +1012,7 @@
 								*p++ = inb(EWRK3_DATA);
 							}
 						} else {
-							memcpy_fromio(p, buf, pkt_len);
+							isa_memcpy_fromio(p, buf, pkt_len);
 						}
 
 						/*
@@ -1737,7 +1737,7 @@
 				}
 			} else {
 				outb(0, EWRK3_MPR);
-				memcpy_fromio(tmp.addr, (char *) (lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3));
+				isa_memcpy_fromio(tmp.addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
 			}
 			ioc->len = (HASH_TABLE_LEN >> 3);
 			if (copy_to_user(ioc->data, tmp.addr, ioc->len)) {
diff -u --recursive --new-file v2.3.24/linux/drivers/net/hamradio/bpqether.c linux/drivers/net/hamradio/bpqether.c
--- v2.3.24/linux/drivers/net/hamradio/bpqether.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/net/hamradio/bpqether.c	Thu Oct 28 14:34:46 1999
@@ -632,14 +632,7 @@
 
 	printk(KERN_INFO "AX.25 ethernet driver version 0.01\n");
 
-#ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_AX25_BPQETHER, 8, "bpqether",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		bpq_get_info
-	});
-#endif
+	proc_net_create ("bpqether", 0, bpq_get_info);
 
 	read_lock_bh(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -673,9 +666,7 @@
 
 	unregister_netdevice_notifier(&bpq_dev_notifier);
 
-#ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_AX25_BPQETHER);
-#endif
+	proc_net_remove ("bpqether");
 
 	for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
 		unregister_netdev(&bpq->axdev);
diff -u --recursive --new-file v2.3.24/linux/drivers/net/hamradio/scc.c linux/drivers/net/hamradio/scc.c
--- v2.3.24/linux/drivers/net/hamradio/scc.c	Wed Aug 18 11:38:50 1999
+++ linux/drivers/net/hamradio/scc.c	Thu Oct 28 14:34:46 1999
@@ -2174,15 +2174,8 @@
 }
 
 #ifdef CONFIG_PROC_FS
-
-struct proc_dir_entry scc_proc_dir_entry = 
-{ 
-	PROC_NET_Z8530, 8, "z8530drv", S_IFREG | S_IRUGO, 1, 0, 0, 0, 
-	&proc_net_inode_operations, scc_net_get_info 
-};
-
-#define scc_net_procfs_init()   proc_net_register(&scc_proc_dir_entry);
-#define scc_net_procfs_remove() proc_net_unregister(PROC_NET_Z8530);
+#define scc_net_procfs_init() proc_net_create("z8530drv",0,scc_net_get_info)
+#define scc_net_procfs_remove() proc_net_remove("z8530drv")
 #else
 #define scc_net_procfs_init()
 #define scc_net_procfs_remove()
diff -u --recursive --new-file v2.3.24/linux/drivers/net/hamradio/yam.c linux/drivers/net/hamradio/yam.c
--- v2.3.24/linux/drivers/net/hamradio/yam.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/hamradio/yam.c	Thu Oct 28 14:34:46 1999
@@ -893,28 +893,17 @@
 }
 
 #ifdef CONFIG_INET
-
-#ifndef PROC_NET_YAM
-#define PROC_NET_YAM (PROC_NET_LAST+10)		/* Sorry again... */
-#endif
-
 #ifdef CONFIG_PROC_FS
-struct proc_dir_entry yam_proc_dir_entry =
-{
-	PROC_NET_YAM, 3, "yam", S_IFREG | S_IRUGO, 1, 0, 0, 0,
-	&proc_net_inode_operations, yam_net_get_info
-};
-
-#define yam_net_procfs_init()   proc_net_register(&yam_proc_dir_entry);
-#define yam_net_procfs_remove() proc_net_unregister(PROC_NET_YAM);
+#define yam_net_procfs_init() proc_net_create("yam",0,yam_net_get_info)
+#define yam_net_procfs_remove() proc_net_remove("yam")
 #else
 #define yam_net_procfs_init()
 #define yam_net_procfs_remove()
-#endif
+#endif /* CONFIG_PROC_FS */
 #else
 #define yam_net_procfs_init()
 #define yam_net_procfs_remove()
-#endif
+#endif /* CONFIG_INET */
 
 /* --------------------------------------------------------------------- */
 
diff -u --recursive --new-file v2.3.24/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
--- v2.3.24/linux/drivers/net/hp-plus.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/hp-plus.c	Fri Oct 29 13:20:35 1999
@@ -361,7 +361,7 @@
 
 	outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
 	outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
-	memcpy_fromio(hdr, dev->mem_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, dev->mem_start, sizeof(struct e8390_pkt_hdr));
 	outw(option_reg, ioaddr + HPP_OPTION);
 	hdr->count = (hdr->count + 3) & ~3;	/* Round up allocation. */
 }
@@ -380,7 +380,7 @@
 	   Also note that we *can't* use eth_io_copy_and_sum() because
 	   it will not always copy "count" bytes (e.g. padded IP).  */
 
-	memcpy_fromio(skb->data, dev->mem_start, count);
+	isa_memcpy_fromio(skb->data, dev->mem_start, count);
 	outw(option_reg, ioaddr + HPP_OPTION);
 }
 
@@ -405,7 +405,7 @@
 
 	outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
 	outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
-	memcpy_toio(dev->mem_start, buf, (count + 3) & ~3);
+	isa_memcpy_toio(dev->mem_start, buf, (count + 3) & ~3);
 	outw(option_reg, ioaddr + HPP_OPTION);
 
 	return;
diff -u --recursive --new-file v2.3.24/linux/drivers/net/lne390.c linux/drivers/net/lne390.c
--- v2.3.24/linux/drivers/net/lne390.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/lne390.c	Fri Oct 29 13:20:35 1999
@@ -316,7 +316,7 @@
 lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - LNE390_START_PG)<<8);
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
 }
 
@@ -334,12 +334,12 @@
 	if (xfer_start + count > dev->rmem_end) {
 		/* Packet wraps over end of ring buffer. */
 		int semi_count = dev->rmem_end - xfer_start;
-		memcpy_fromio(skb->data, xfer_start, semi_count);
+		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 	} else {
 		/* Packet is in one chunk. */
-		memcpy_fromio(skb->data, xfer_start, count);
+		isa_memcpy_fromio(skb->data, xfer_start, count);
 	}
 }
 
@@ -349,7 +349,7 @@
 	unsigned long shmem = dev->mem_start + ((start_page - LNE390_START_PG)<<8);
 
 	count = (count + 3) & ~3;     /* Round up to doubleword */
-	memcpy_toio(shmem, buf, count);
+	isa_memcpy_toio(shmem, buf, count);
 }
 
 static int lne390_open(struct net_device *dev)
diff -u --recursive --new-file v2.3.24/linux/drivers/net/ne3210.c linux/drivers/net/ne3210.c
--- v2.3.24/linux/drivers/net/ne3210.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ne3210.c	Fri Oct 29 13:20:35 1999
@@ -307,7 +307,7 @@
 ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - NE3210_START_PG)<<8);
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
 }
 
@@ -325,12 +325,12 @@
 	if (xfer_start + count > dev->rmem_end) {
 		/* Packet wraps over end of ring buffer. */
 		int semi_count = dev->rmem_end - xfer_start;
-		memcpy_fromio(skb->data, xfer_start, semi_count);
+		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 	} else {
 		/* Packet is in one chunk. */
-		memcpy_fromio(skb->data, xfer_start, count);
+		isa_memcpy_fromio(skb->data, xfer_start, count);
 	}
 }
 
@@ -340,7 +340,7 @@
 	unsigned long shmem = dev->mem_start + ((start_page - NE3210_START_PG)<<8);
 
 	count = (count + 3) & ~3;     /* Round up to doubleword */
-	memcpy_toio(shmem, buf, count);
+	isa_memcpy_toio(shmem, buf, count);
 }
 
 static int ne3210_open(struct net_device *dev)
diff -u --recursive --new-file v2.3.24/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c
--- v2.3.24/linux/drivers/net/sk_mca.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/net/sk_mca.c	Fri Oct 29 13:20:35 1999
@@ -306,7 +306,7 @@
       descr.Flags = 0;
       descr.Len = 0xf000;
       descr.Status = 0;
-      memcpy_toio(dev->mem_start + RAM_TXBASE + (z * sizeof(LANCE_TxDescr)),
+      isa_memcpy_toio(dev->mem_start + RAM_TXBASE + (z * sizeof(LANCE_TxDescr)),
                   &descr, sizeof(LANCE_TxDescr));
       memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
       bufaddr += RAM_BUFSIZE;
@@ -325,9 +325,9 @@
       descr.Flags = RXDSCR_FLAGS_OWN;
       descr.MaxLen = -RAM_BUFSIZE;
       descr.Len = 0;
-      memcpy_toio(dev->mem_start + RAM_RXBASE + (z * sizeof(LANCE_RxDescr)),
+      isa_memcpy_toio(dev->mem_start + RAM_RXBASE + (z * sizeof(LANCE_RxDescr)),
                   &descr, sizeof(LANCE_RxDescr));
-      memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
+      isa_memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
       bufaddr += RAM_BUFSIZE;
     }
   }
@@ -450,7 +450,7 @@
   block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);
   block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);
 
-  memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+  isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
 
   /* initialize LANCE. Implicitly sets up other structures in RAM. */
 
@@ -507,7 +507,7 @@
   while (1)
   {
     /* read descriptor */
-    memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_RxDescr));
+    isa_memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_RxDescr));
  
     /* if we reach a descriptor we do not own, we're done */
     if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0)
@@ -539,7 +539,7 @@
         priv->stat.rx_dropped++;
       else
       {
-        memcpy_fromio(skb_put(skb, descr.Len),
+        isa_memcpy_fromio(skb_put(skb, descr.Len),
                       dev->mem_start + descr.LowAddr, descr.Len);
         skb->dev = dev;
         skb->protocol = eth_type_trans(skb, dev);
@@ -557,7 +557,7 @@
     descr.Flags |= RXDSCR_FLAGS_OWN;
 
     /* update descriptor in shared RAM */
-    memcpy_toio(dev->mem_start + descraddr, &descr, sizeof(LANCE_RxDescr));
+    isa_memcpy_toio(dev->mem_start + descraddr, &descr, sizeof(LANCE_RxDescr));
 
     /* go to next descriptor */
     priv->nextrx++; descraddr += sizeof(LANCE_RxDescr);
@@ -588,7 +588,7 @@
   while (priv->txbusy > 0)
   {
     /* read descriptor */
-    memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_TxDescr));
+    isa_memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_TxDescr));
 
     /* if the LANCE still owns this one, we've worked out all sent packets */
     if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0)
@@ -798,7 +798,7 @@
 
   /* get TX descriptor */
   address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));
-  memcpy_fromio(&descr, dev->mem_start + address, sizeof(LANCE_TxDescr));
+  isa_memcpy_fromio(&descr, dev->mem_start + address, sizeof(LANCE_TxDescr));
 
   /* enter packet length as 2s complement - assure minimum length */
   tmplen = skb->len;
@@ -816,13 +816,13 @@
 
     while (destoffs < tmplen)
     {
-      memcpy_toio(dev->mem_start + descr.LowAddr + destoffs, fill, l);
+      isa_memcpy_toio(dev->mem_start + descr.LowAddr + destoffs, fill, l);
       destoffs += l;
     }
   }
 
   /* do the real data copying */
-  memcpy_toio(dev->mem_start + descr.LowAddr, skb->data, skb->len);
+  isa_memcpy_toio(dev->mem_start + descr.LowAddr, skb->data, skb->len);
 
   /* hand descriptor over to LANCE - this is the first and last chunk */
   descr.Flags = TXDSCR_FLAGS_OWN | TXDSCR_FLAGS_STP | TXDSCR_FLAGS_ENP;
@@ -841,7 +841,7 @@
   dev->tbusy = (priv->txbusy >= TXCOUNT);
 
   /* write descriptor back to RAM */
-  memcpy_toio(dev->mem_start + address, &descr, sizeof(LANCE_TxDescr));
+  isa_memcpy_toio(dev->mem_start + address, &descr, sizeof(LANCE_TxDescr));
 
   /* if no descriptors were active, give the LANCE a hint to read it
      immediately */
@@ -891,7 +891,7 @@
   StopLANCE(dev);
 
   /* ...then modify the initialization block... */
-  memcpy_fromio(&block, dev->mem_start + RAM_INITBASE, sizeof(block));
+  isa_memcpy_fromio(&block, dev->mem_start + RAM_INITBASE, sizeof(block));
   if (dev->flags & IFF_PROMISC)
     block.Mode |= LANCE_INIT_PROM;
   else
@@ -914,7 +914,7 @@
     }
   }
 
-  memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+  isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
 
   /* ...then reinit LANCE with the correct flags */
   InitLANCE(dev);
diff -u --recursive --new-file v2.3.24/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.3.24/linux/drivers/net/smc-ultra.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/smc-ultra.c	Fri Oct 29 13:20:35 1999
@@ -312,9 +312,9 @@
 	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);	/* shmem on */
 #ifdef notdef
 	/* Officially this is what we are doing, but the readl() is faster */
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 #else
-	((unsigned int*)hdr)[0] = readl(hdr_start);
+	((unsigned int*)hdr)[0] = isa_readl(hdr_start);
 #endif
 	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
 }
@@ -333,12 +333,12 @@
 	if (xfer_start + count > dev->rmem_end) {
 		/* We must wrap the input move. */
 		int semi_count = dev->rmem_end - xfer_start;
-		memcpy_fromio(skb->data, xfer_start, semi_count);
+		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 
 	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET);	/* Disable memory. */
@@ -353,7 +353,7 @@
 	/* Enable shared memory. */
 	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
 
-	memcpy_toio(shmem, buf, count);
+	isa_memcpy_toio(shmem, buf, count);
 
 	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
 }
diff -u --recursive --new-file v2.3.24/linux/drivers/net/smc-ultra32.c linux/drivers/net/smc-ultra32.c
--- v2.3.24/linux/drivers/net/smc-ultra32.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/smc-ultra32.c	Fri Oct 29 13:20:35 1999
@@ -314,9 +314,9 @@
 
 #ifdef notdef
 	/* Officially this is what we are doing, but the readl() is faster */
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 #else
-	((unsigned int*)hdr)[0] = readl(hdr_start);
+	((unsigned int*)hdr)[0] = isa_readl(hdr_start);
 #endif
 }
 
@@ -335,21 +335,21 @@
 
 	if ((ring_offset & ~0x1fff) != ((ring_offset + count - 1) & ~0x1fff)) {
 		int semi_count = 8192 - (ring_offset & 0x1FFF);
-		memcpy_fromio(skb->data, xfer_start, semi_count);
+		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
 		if (ring_offset < 96*256) {
 			/* Select next 8KB Window. */
 			ring_offset += semi_count;
 			outb(ei_status.reg0 | ((ring_offset & 0x6000) >> 13), RamReg);
-			memcpy_fromio(skb->data + semi_count, dev->mem_start, count);
+			isa_memcpy_fromio(skb->data + semi_count, dev->mem_start, count);
 		} else {
 			/* Select first 8KB Window. */
 			outb(ei_status.reg0, RamReg);
-			memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+			isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 		}
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 }
 
@@ -364,7 +364,7 @@
 	/* Select first 8KB Window. */
 	outb(ei_status.reg0, RamReg);
 
-	memcpy_toio(xfer_start, buf, count);
+	isa_memcpy_toio(xfer_start, buf, count);
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.24/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.3.24/linux/drivers/net/strip.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/net/strip.c	Thu Oct 28 14:34:46 1999
@@ -118,8 +118,8 @@
 #include <linux/if_arp.h>
 #include <linux/if_strip.h>
 #include <linux/proc_fs.h>
-#include <linux/serialP.h>
 #include <linux/serial.h>
+#include <linux/serialP.h>
 #include <net/arp.h>
 
 #include <linux/ip.h>
@@ -1270,25 +1270,6 @@
     return(calc_start_len(buffer, start, req_offset, req_len, total, buf));
 }
 
-static const char proc_strip_status_name[] = "strip";
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_strip_get_status_info =
-{
-    PROC_NET_STRIP_STATUS,		/* unsigned short low_ino */
-    sizeof(proc_strip_status_name)-1,	/* unsigned short namelen */
-    proc_strip_status_name,		/* const char *name */
-    S_IFREG | S_IRUGO,			/* mode_t mode */
-    1,					/* nlink_t nlink */
-    0, 0, 0,				/* uid_t uid, gid_t gid, unsigned long size */
-    &proc_net_inode_operations,		/* struct inode_operations * ops */
-    &get_status_info,			/* int (*get_info)(...) */
-    NULL,				/* void (*fill_inode)(struct inode *); */
-    NULL, NULL, NULL,			/* struct proc_dir_entry *next, *parent, *subdir; */
-    NULL				/* void *data; */
-};
-#endif /* CONFIG_PROC_FS */
-
 /************************************************************************/
 /* Sending routines							*/
 
@@ -2885,12 +2866,7 @@
     /*
      * Register the status file with /proc
      */
-#ifdef CONFIG_PROC_FS 
-    if (proc_net_register(&proc_strip_get_status_info) != 0)
-    {
-        printk(KERN_ERR "strip: status proc_net_register() failed.\n");
-    }
-#endif
+    proc_net_create ("strip", S_IFREG | S_IRUGO, get_status_info);
 
 #ifdef MODULE
      return status;
@@ -2921,9 +2897,7 @@
         strip_free(struct_strip_list);
 
     /* Unregister with the /proc/net file here. */
-#ifdef CONFIG_PROC_FS
-    proc_net_unregister(PROC_NET_STRIP_STATUS);
-#endif
+    proc_net_remove ("strip");
 
     if ((i = tty_register_ldisc(N_STRIP, NULL)))
         printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
diff -u --recursive --new-file v2.3.24/linux/drivers/net/wan/cycx_drv.c linux/drivers/net/wan/cycx_drv.c
--- v2.3.24/linux/drivers/net/wan/cycx_drv.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/net/wan/cycx_drv.c	Sun Oct 31 00:19:22 1999
@@ -1,9 +1,8 @@
 /*
-* cycx_drv.c	cycx Support Module.
+* cycx_drv.c	Cyclom 2X Support Module.
 *
 *		This module is a library of common hardware-specific
-*		functions used by all Cyclades sync and some async (8x & 16x)
-*		drivers.
+*		functions used by the Cyclades Cyclom 2X sync card.
 *
 * Copyright:	(c) 1998, 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
@@ -16,6 +15,11 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
+* 1999/10/26	acme		use isa_read[bw], isa_write[bw] and isa_memcpy_to
+*				and fromio
+* 1999/10/23	acme		cleanup to only supports cyclom2x: all the other
+*				boards are no longer manufactured by cyclades, if
+*				someone wants to support them... be my guest!
 * 1999/05/28    acme		cycx_intack & cycx_intde gone for good
 * 1999/05/18	acme		lots of unlogged work, submitting to Linus...
 * 1999/01/03	acme		more judicious use of data types
@@ -27,16 +31,16 @@
 *				to ack an int in cycx_drv.c, only handle it in
 *				cyx_isr (or in the other protocols: cyp_isr,
 *				cyf_isr, when they get implemented.
-* Dec 31, 1998	Arnaldo         cycx_data_boot & cycx_code_boot fixed, crossing
+* Dec 31, 1998	acme		cycx_data_boot & cycx_code_boot fixed, crossing
 *				fingers to see x25_configure in cycx_x25.c
 *				work... :)
-* Dec 26, 1998	Arnaldo         load implementation fixed, seems to work! :)
+* Dec 26, 1998	acme		load implementation fixed, seems to work! :)
 *				cycx_2x_dpmbase_options with all the possible
 *				DPM addresses (20).
 *				cycx_intr implemented (test this!)
 *				general code cleanup
 * Dec  8, 1998	Ivan Passos	Cyclom-2X firmware load implementation.
-* Aug  8, 1998	Arnaldo		Initial version.
+* Aug  8, 1998	acme		Initial version.
 */
 
 #ifdef MODULE
@@ -57,11 +61,11 @@
 #include <asm/io.h>		/* for inb(), outb(), etc. */
 
 #define	MOD_VERSION	0
-#define	MOD_RELEASE	2
+#define	MOD_RELEASE	3
 
 #ifdef MODULE
 MODULE_AUTHOR("Arnaldo Carvalho de Melo");
-MODULE_DESCRIPTION("Cyclades Sync Cards Driver.");
+MODULE_DESCRIPTION("Cyclom 2x Sync Card Driver");
 #endif
 
 /* Function Prototypes */
@@ -70,15 +74,12 @@
 void cleanup_module (void);
 
 /* Hardware-specific functions */
-static int cycx_detect (cycxhw_t *hw);
-static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len);
-static int cycx_init (cycxhw_t *hw);
-static int cycx_reset (cycxhw_t *hw);
+static int load_cyc2x (cycxhw_t *hw, cfm_t *cfm, u32 len);
 static void cycx_bootcfg (cycxhw_t *hw);
 
-static int init_cycx_2x (cycxhw_t *hw);
-static int reset_cycx_2x (u32 addr);
-static int detect_cycx_2x (u32 addr);
+static int init_cyc2x (cycxhw_t *hw);
+static int reset_cyc2x (u32 addr);
+static int detect_cyc2x (u32 addr);
 
 /* Miscellaneous functions */
 static void delay_cycx (int sec);
@@ -87,19 +88,25 @@
 
 #define wait_cyc(addr) cycx_exec(addr + CMD_OFFSET)
 
-/* Global Data
- * Note: All data must be explicitly initialized!!! */
+#define cyc2x_readb(b) isa_readb(b)
+#define cyc2x_readw(b) isa_readw(b)
+#define cyc2x_writeb(b, addr) isa_writeb(b, addr)
+#define cyc2x_writew(w, addr) isa_writew(w, addr)
+#define cyc2x_memcpy_toio(addr, buf, len) isa_memcpy_toio((addr), buf, len)
+#define cyc2x_memcpy_fromio(buf, addr, len) isa_memcpy_fromio(buf, (addr), len)
+
+/* Global Data */
 
 /* private data */
 static char modname[] = "cycx_drv";
-static char fullname[] = "Cyclom X Support Module";
+static char fullname[] = "Cyclom 2X Support Module";
 static char copyright[]	= "(c) 1998, 1999 Arnaldo Carvalho de Melo";
 
 /* Hardware configuration options.
  * These are arrays of configuration options used by verification routines.
  * The first element of each array is its size (i.e. number of options).
  */
-static u32 cycx_2x_dpmbase_options[] =
+static u32 cyc2x_dpmbase_options[] =
 {
 	20,
 	0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000, 0xB8000,
@@ -143,32 +150,18 @@
 EXPORT_SYMBOL(cycx_setup);
 int cycx_setup (cycxhw_t *hw, void *cfm, u32 len)
 {
-	u32 *irq_opt = NULL;	/* IRQ options */
-	u32 *dpmbase_opt = NULL;/* DPM window base options */
-	int err = 0;
-
-	if (cycx_detect(hw)) {
-		printk(KERN_ERR "%s: adapter Cyclom %uX not found at "
+	if (!detect_cyc2x(hw->dpmbase)) {
+		printk(KERN_ERR "%s: adapter Cyclom 2X not found at "
 				"address 0x%lX!\n",
-			modname, hw->type, (unsigned long) hw->dpmbase);
+			modname, (unsigned long) hw->dpmbase);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "%s: found Cyclom %uX card at address 0x%lx.\n",
-			 modname, hw->type, (unsigned long) hw->dpmbase);
-
-	switch (hw->type) {
-		case CYCX_2X:
-			irq_opt	= cycx_2x_irq_options;
-			dpmbase_opt = cycx_2x_dpmbase_options;
-			break;
-		default:
-			printk(KERN_ERR "%s: unknown card.\n", modname);
-			return -EINVAL;
-	}
+	printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lx.\n",
+			 modname, (unsigned long) hw->dpmbase);
 
 	/* Verify IRQ configuration options */
-	if (!get_option_index(irq_opt, hw->irq)) {
+	if (!get_option_index(cycx_2x_irq_options, hw->irq)) {
 		printk (KERN_ERR "%s: IRQ %d is illegal!\n", modname, hw->irq);
 		return -EINVAL;
 	} 
@@ -179,60 +172,35 @@
 				modname);
  		return -EINVAL;
 	}
-	else if (!get_option_index(dpmbase_opt, hw->dpmbase)) {
+	else if (!get_option_index(cyc2x_dpmbase_options, hw->dpmbase)) {
 		printk(KERN_ERR "%s: memory address 0x%lX is illegal!\n",
 				modname, (unsigned long) hw->dpmbase);
 		return -EINVAL;
 	}
 
 	hw->dpmsize = CYCX_WINDOWSIZE;
-	/* FIXME! Is this the only amount ever available? */
-	hw->memory = 0x40000;
 
-	cycx_init(hw);
+	init_cyc2x(hw);
 
 	printk(KERN_INFO "%s: dual-port memory window is set at 0x%lX.\n",
 			 modname, (unsigned long) hw->dpmbase);
-	printk(KERN_INFO "%s: found %luK bytes of on-board memory.\n",
-			 modname, (unsigned long) hw->memory / 1024);
 
 	/* Load firmware. If loader fails then shut down adapter */
-	err = cycx_load(hw, cfm, len);
-	if (err) cycx_down(hw);		/* shutdown adapter */
-	return err;
+	return load_cyc2x(hw, cfm, len);
 } 
 
-/* Shut down CYCX: disable shared memory access and interrupts, stop CPU,etc.*/ 
-EXPORT_SYMBOL(cycx_down);
-int cycx_down (cycxhw_t *hw)
-{
-	return 0; /* FIXME: anything needed here? */
-}
-
 /* Enable interrupt generation.  */
 EXPORT_SYMBOL(cycx_inten);
-int cycx_inten (cycxhw_t *hw)
+void cycx_inten (cycxhw_t *hw)
 {
-	switch (hw->type) {
-		case CYCX_2X: writeb (0, hw->dpmbase); break;
-		default: return -EINVAL;
-	}
-
-	return 0;
+	cyc2x_writeb (0, hw->dpmbase);
 }
 
 /* Generate an interrupt to adapter's CPU. */
 EXPORT_SYMBOL(cycx_intr);
-int cycx_intr (cycxhw_t *hw)
+void cycx_intr (cycxhw_t *hw)
 {
-	switch (hw->type) {
-		case CYCX_2X:
-			writew(0, hw->dpmbase + GEN_CYCX_INTR);
-			return 0;
-		default: return -EINVAL;
-	}
-
-	return 0;
+	cyc2x_writew(0, hw->dpmbase + GEN_CYCX_INTR);
 }
 
 /* Execute Adapter Command.
@@ -244,7 +212,7 @@
 	u16 i = 0;
 	/* wait till addr content is zeroed */
 
-	while (readw(addr) != 0) {
+	while (cyc2x_readw(addr)) {
 		udelay(1000);
 		if (++i > 50) return -1;
 	}
@@ -257,8 +225,8 @@
 EXPORT_SYMBOL(cycx_peek);
 int cycx_peek (cycxhw_t *hw, u32 addr, void *buf, u32 len)
 {
-	if (len == 1)	*(u8*)buf = readb (hw->dpmbase + addr);
-	else 		memcpy_fromio(buf, hw->dpmbase + addr, len);
+	if (len == 1)	*(u8*)buf = cyc2x_readb (hw->dpmbase + addr);
+	else 		cyc2x_memcpy_fromio(buf, hw->dpmbase + addr, len);
 
 	return 0;
 }
@@ -268,38 +236,13 @@
 EXPORT_SYMBOL(cycx_poke);
 int cycx_poke (cycxhw_t *hw, u32 addr, void *buf, u32 len)
 {
-	if (len == 1) writeb (*(u8*)buf, hw->dpmbase + addr);
-	else	      memcpy_toio(hw->dpmbase + addr, buf, len);
+	if (len == 1) cyc2x_writeb (*(u8*)buf, hw->dpmbase + addr);
+	else	      cyc2x_memcpy_toio(hw->dpmbase + addr, buf, len);
 
 	return 0;
 }
 
 /* Hardware-Specific Functions */
-/* Detect adapter type.
- * o if adapter type is specified then call detection routine for that adapter
- *   type.  Otherwise call detection routines for every adapter types until
- *   adapter is detected.
- *
- * Notes:
- * 1) Detection tests are destructive! Adapter will be left in shutdown state
- *    after the test. */
-static int cycx_detect (cycxhw_t *hw)
-{
-	int err = 0;
-
-	if (!hw->dpmbase) return -EFAULT;
-
-	switch (hw->type) {
-		case CYCX_2X:
-			if (!detect_cycx_2x(hw->dpmbase)) err = -ENODEV;
-			break;
-		default:
-			if (detect_cycx_2x(hw->dpmbase)) hw->type = CYCX_2X;
-			else err = -ENODEV;
-	}
-
-	return err;
-}
 
 /* Load Aux Routines */
 /* Reset board hardware.
@@ -309,10 +252,10 @@
 	int timeout = 0;
 
 	for (; timeout < 3 ; timeout++) {
-		writew (TEST_PATTERN, addr + 0x10);
+		cyc2x_writew (TEST_PATTERN, addr + 0x10);
 
-		if (readw (addr + 0x10) == TEST_PATTERN)
-			if (readw (addr + 0x10) == TEST_PATTERN) return 1;
+		if (cyc2x_readw (addr + 0x10) == TEST_PATTERN)
+			if (cyc2x_readw (addr + 0x10) == TEST_PATTERN) return 1;
 
 		delay_cycx(1);
 	}
@@ -320,17 +263,6 @@
 	return 0;
 }
 
-/* Reset board hardware. */
-static int cycx_reset(cycxhw_t *hw)
-{
-	/* Reset board */
-	switch (hw->type) {
-		case CYCX_2X: return reset_cycx_2x(hw->dpmbase);
-	}
-
-	return -EINVAL;
-}
-
 /* Load reset code. */
 static void reset_load(u32 addr, u8 *buffer, u32 cnt)
 {
@@ -339,7 +271,7 @@
 
 	for ( i = 0 ; i < cnt ; i++) {
 		for (j = 0 ; j < 50 ; j++); /* Delay - FIXME busy waiting... */
-		writeb(*buffer++, pt_code++);
+		cyc2x_writeb(*buffer++, pt_code++);
 	}
 }
 
@@ -348,8 +280,8 @@
  * o wait for reset code to copy it to right portion of memory */
 static int buffer_load(u32 addr, u8 *buffer, u32 cnt)
 {
-	memcpy_toio(addr + DATA_OFFSET, buffer, cnt);
-	writew(GEN_BOOT_DAT, addr + CMD_OFFSET);
+	cyc2x_memcpy_toio(addr + DATA_OFFSET, buffer, cnt);
+	cyc2x_writew(GEN_BOOT_DAT, addr + CMD_OFFSET);
 	return wait_cyc(addr);
 }
 
@@ -357,14 +289,14 @@
 static void cycx_start (u32 addr)
 {
 	/* put in 0x30 offset the jump instruction to the code entry point */
-	writeb(0xea, addr + 0x30);
-	writeb(0x00, addr + 0x31);
-	writeb(0xc4, addr + 0x32);
-	writeb(0x00, addr + 0x33);
-	writeb(0x00, addr + 0x34);
+	cyc2x_writeb(0xea, addr + 0x30);
+	cyc2x_writeb(0x00, addr + 0x31);
+	cyc2x_writeb(0xc4, addr + 0x32);
+	cyc2x_writeb(0x00, addr + 0x33);
+	cyc2x_writeb(0x00, addr + 0x34);
 
 	/* cmd to start executing code */
-	writew(GEN_START, addr + CMD_OFFSET);
+	cyc2x_writew(GEN_START, addr + CMD_OFFSET);
 }         
 
 /* Load and boot reset code. */
@@ -372,15 +304,15 @@
 {
 	u32 pt_start = addr + START_OFFSET;
 
-        writeb(0xea, pt_start++); /* jmp to f000:3f00 */
-        writeb(0x00, pt_start++);
-        writeb(0xfc, pt_start++);
-        writeb(0x00, pt_start++);
-        writeb(0xf0, pt_start);
+        cyc2x_writeb(0xea, pt_start++); /* jmp to f000:3f00 */
+        cyc2x_writeb(0x00, pt_start++);
+        cyc2x_writeb(0xfc, pt_start++);
+        cyc2x_writeb(0x00, pt_start++);
+        cyc2x_writeb(0xf0, pt_start);
 	reset_load(addr, code, len);
 
 	/* 80186 was in hold, go */
-	writeb(0, addr + START_CPU);
+	cyc2x_writeb(0, addr + START_CPU);
 	delay_cycx(1);
 }
 
@@ -391,14 +323,14 @@
 	u32 i;
 
 	/* boot buffer lenght */
-	writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
-	writew(GEN_DEFPAR, pt_boot_cmd);
+	cyc2x_writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
+	cyc2x_writew(GEN_DEFPAR, pt_boot_cmd);
 
 	if (wait_cyc(addr) < 0) return 2;
 
-	writew(0, pt_boot_cmd + sizeof(u16));
-	writew(0x4000, pt_boot_cmd + 2 * sizeof(u16));
-	writew(GEN_SET_SEG, pt_boot_cmd);
+	cyc2x_writew(0, pt_boot_cmd + sizeof(u16));
+	cyc2x_writew(0x4000, pt_boot_cmd + 2 * sizeof(u16));
+	cyc2x_writew(GEN_SET_SEG, pt_boot_cmd);
 
 	if (wait_cyc(addr) < 0) return 2;
 
@@ -420,14 +352,14 @@
 	u32 i;
 
 	/* boot buffer lenght */
-	writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
-	writew(GEN_DEFPAR, pt_boot_cmd);
+	cyc2x_writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
+	cyc2x_writew(GEN_DEFPAR, pt_boot_cmd);
 
 	if (wait_cyc(addr) == -1) return 2;
 
-	writew(0x0000, pt_boot_cmd + sizeof(u16));
-	writew(0xc400, pt_boot_cmd + 2 * sizeof(u16));
-	writew(GEN_SET_SEG, pt_boot_cmd);
+	cyc2x_writew(0x0000, pt_boot_cmd + sizeof(u16));
+	cyc2x_writew(0xc400, pt_boot_cmd + 2 * sizeof(u16));
+	cyc2x_writew(GEN_SET_SEG, pt_boot_cmd);
 
 	if (wait_cyc(addr) == -1) return 1;
 
@@ -440,22 +372,12 @@
 	return 0;
 }
 
-/* Initialize CYCX hardware: setup memory window, IRQ, etc. */
-static int cycx_init (cycxhw_t *hw)
-{
-	switch (hw->type) {
-		case CYCX_2X: return init_cycx_2x(hw);
-	}
-
-	return -EINVAL;
-}
-
 /* Load adapter from the memory image of the CYCX firmware module. 
  * o verify firmware integrity and compatibility
  * o start adapter up */
-static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
+static int load_cyc2x (cycxhw_t *hw, cfm_t *cfm, u32 len)
 {
-	int i, j, status;
+	int i, j;
 	cycx_header_t *img_hdr;
 	u8 *reset_image,
 	   *data_image,
@@ -469,7 +391,7 @@
 
 	/* Verify firmware signature */
 	if (strcmp(cfm->signature, CFM_SIGNATURE)) {
-		printk(KERN_ERR "%s:cycx_load: not Cyclom-2X firmware!\n",
+		printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n",
 				modname);
 		return -EINVAL;
 	}
@@ -478,7 +400,7 @@
 
 	/* Verify firmware module format version */
 	if (cfm->version != CFM_VERSION) {
-		printk(KERN_ERR "%s:cycx_load: firmware format %u rejected! "
+		printk(KERN_ERR "%s:" __FUNCTION__ ": firmware format %u rejected! "
 				"Expecting %u.\n",
 				modname, cfm->version, CFM_VERSION);
 		return -EINVAL;
@@ -492,7 +414,7 @@
 	if (((len - sizeof(cfm_t) - 1) != cfm->info.codesize) ||
 */
 	if (cksum != cfm->checksum) {
-		printk(KERN_ERR "%s:cycx_load: firmware corrupted!\n", modname);
+		printk(KERN_ERR "%s:" __FUNCTION__ ": firmware corrupted!\n", modname);
 		printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n",
                        len - sizeof(cfm_t) - 1, cfm->info.codesize);
                 printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n",
@@ -504,7 +426,7 @@
 
 	img_hdr = (cycx_header_t*)(((u8*) cfm) + sizeof(cfm_t) - 1);
 #ifdef FIRMWARE_DEBUG
-	printk(KERN_INFO "%s:cycx_load: image sizes\n", modname);
+	printk(KERN_INFO "%s:" __FUNCTION__ ": image sizes\n", modname);
 	printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size);
 	printk(KERN_INFO "  data=%lu\n", img_hdr->data_size);
 	printk(KERN_INFO "  code=%lu\n", img_hdr->code_size);
@@ -521,20 +443,20 @@
 
 	for (i = 0 ; i < 5 ; i++) {
 		/* Reset Cyclom hardware */
-		if ((status = cycx_reset(hw)) != 0) {
+		if (!reset_cyc2x(hw->dpmbase)) {
 			printk(KERN_ERR "%s: dpm problem or board not "
-					"found (%d).\n", modname, status);
+					"found.\n", modname);
 			return -EINVAL;
 		}
 
 		/* Load reset.bin */
                 cycx_reset_boot(hw->dpmbase, reset_image, img_hdr->reset_size);
 		/* reset is waiting for boot */
-		writew(GEN_POWER_ON, pt_cycld);
+		cyc2x_writew(GEN_POWER_ON, pt_cycld);
 		delay_cycx(1);
 
 		for (j = 0 ; j < 3 ; j++)
-			if (!readw(pt_cycld)) goto reset_loaded;
+			if (!cyc2x_readw(pt_cycld)) goto reset_loaded;
 			else delay_cycx(1);
 	}
 
@@ -542,18 +464,16 @@
 	return -EINVAL;
 reset_loaded:
 	/* Load data.bin */
-	if((status = cycx_data_boot(hw->dpmbase, data_image, 
-		                    img_hdr->data_size)) != 0) {
-		printk(KERN_ERR "%s: cannot load data file (%d).\n",
-				modname, status);
+	if(cycx_data_boot(hw->dpmbase, data_image, 
+				       img_hdr->data_size)) {
+		printk(KERN_ERR "%s: cannot load data file.\n", modname);
 		return -EINVAL;
 	}
 
 	/* Load code.bin */
-	if((status = cycx_code_boot(hw->dpmbase, code_image, 
-		                    img_hdr->code_size)) != 0) {
-		printk(KERN_ERR "%s: cannot load code file (%d).\n",
-				modname, status);
+	if(cycx_code_boot(hw->dpmbase, code_image, 
+				       img_hdr->code_size)) {
+		printk(KERN_ERR "%s: cannot load code file.\n", modname);
 		return -EINVAL;
 	}
 
@@ -569,10 +489,7 @@
 	printk(KERN_INFO "%s: firmware loaded!\n", modname);
 
 	/* enable interrupts */
-        if (cycx_inten(hw)) {
-		printk(KERN_ERR "%s: adapter hardware failure!\n", modname);
-		return -EIO;
-	}
+        cycx_inten(hw);
 
 	return 0;
 }
@@ -586,13 +503,15 @@
 static void cycx_bootcfg (cycxhw_t *hw)
 {
 	/* use fixed buffers */
-	writeb(FIXED_BUFFERS, hw->dpmbase + CONF_OFFSET); 
+	cyc2x_writeb(FIXED_BUFFERS, hw->dpmbase + CONF_OFFSET); 
 }
 
 /* Initialize CYCX_2X adapter. */
-static int init_cycx_2x (cycxhw_t *hw)
+static int init_cyc2x (cycxhw_t *hw)
 {
-	if (!detect_cycx_2x(hw->dpmbase)) return -ENODEV;
+	if (!detect_cyc2x(hw->dpmbase))
+		return -ENODEV;
+
 	return 0;
 }
 
@@ -602,12 +521,12 @@
  *	Return 1 if detected o.k. or 0 if failed.
  *	Note:	This test is destructive! Adapter will be left in shutdown
  *		state after the test. */
-static int detect_cycx_2x (u32 addr)
+static int detect_cyc2x (u32 addr)
 {
 	printk(KERN_INFO "%s: looking for a cyclom 2x at 0x%lX...\n",
 			 modname, (unsigned long) addr);
 
-	reset_cycx_2x(addr);
+	reset_cyc2x(addr);
 	return memory_exists(addr);
 }
 
@@ -622,11 +541,11 @@
 }
 
 /* Reset adapter's CPU. */
-static int reset_cycx_2x (u32 addr)
+static int reset_cyc2x (u32 addr)
 {
-	writeb (0, addr + RST_ENABLE);  delay_cycx (2);
-	writeb (0, addr + RST_DISABLE); delay_cycx (2);
-	return memory_exists(addr) ? 0 : 1;
+	cyc2x_writeb (0, addr + RST_ENABLE);  delay_cycx (2);
+	cyc2x_writeb (0, addr + RST_DISABLE); delay_cycx (2);
+	return memory_exists(addr);
 }
 
 /* Delay */
diff -u --recursive --new-file v2.3.24/linux/drivers/net/wan/cycx_main.c linux/drivers/net/wan/cycx_main.c
--- v2.3.24/linux/drivers/net/wan/cycx_main.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/net/wan/cycx_main.c	Sun Oct 31 00:19:22 1999
@@ -1,5 +1,5 @@
 /*
-* cycx_main.c	Cyclades Cyclom X Multiprotocol WAN Link Driver. Main module.
+* cycx_main.c	Cyclades Cyclom 2X WAN Link Driver. Main module.
 *
 * Author:	Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
@@ -40,7 +40,7 @@
 
 #ifdef MODULE
 MODULE_AUTHOR("Arnaldo Carvalho de Melo");
-MODULE_DESCRIPTION("Cyclades Sync Cards Driver.");
+MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver.");
 #endif
 
 /* Defines & Macros */
@@ -73,7 +73,7 @@
 
 /* private data */
 static char drvname[]	= "cyclomx";
-static char fullname[]	= "CYCLOM X(tm) Multiprotocol Driver";
+static char fullname[]	= "CYCLOM 2X(tm) Sync Card Driver";
 static char copyright[]	= "(c) 1998, 1999 Arnaldo Carvalho de Melo";
 static int ncards = CONFIG_CYCLOMX_CARDS;
 static cycx_t *card_array = NULL;	/* adapter data space */
@@ -214,7 +214,6 @@
 	card->hw.irq = (conf->irq == 9) ? 2 : conf->irq;
 	card->hw.dpmbase = conf->maddr;
 	card->hw.dpmsize = CYCX_WINDOWSIZE;
-	card->hw.type = conf->hw_opt[0];
 	card->hw.fwid = CFID_X25_2X;
 	card->lock = SPIN_LOCK_UNLOCKED;
 #if LINUX_VERSION_CODE >= 0x020300
@@ -234,9 +233,7 @@
 	wandev->dma       = wandev->ioport = 0;
 	wandev->maddr     = (unsigned long*)card->hw.dpmbase;
 	wandev->msize     = card->hw.dpmsize;
-	wandev->hw_opt[0] = card->hw.type;
-	wandev->hw_opt[1] = card->hw.pclk;
-	wandev->hw_opt[2] = card->hw.memory;
+	wandev->hw_opt[2] = 0;
 	wandev->hw_opt[3] = card->hw.fwid;
 
 	/* Protocol-specific initialization */
@@ -251,7 +248,6 @@
 	}
 
 	if (err) {
-		cycx_down(&card->hw);
 		free_irq(irq, card);
 		return err;
 	}
@@ -278,7 +274,6 @@
 
 	card = wandev->private;
 	wandev->state = WAN_UNCONFIGURED;
-	cycx_down(&card->hw);
 	printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,wandev->irq);
 	free_irq(wandev->irq, card);
 	return 0;
diff -u --recursive --new-file v2.3.24/linux/drivers/net/wan/cycx_x25.c linux/drivers/net/wan/cycx_x25.c
--- v2.3.24/linux/drivers/net/wan/cycx_x25.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/net/wan/cycx_x25.c	Sun Oct 31 00:19:22 1999
@@ -1,5 +1,5 @@
 /*
-* cycx_x25.c	CYCLOM X Multiprotocol WAN Link Driver.  X.25 module.
+* cycx_x25.c	CYCLOM X WAN Link Driver.  X.25 module.
 *
 * Author:	Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 * Copyright:	(c) 1998, 1999 Arnaldo Carvalho de Melo
@@ -11,6 +11,13 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
+* 1999/10/27	acme		use ARPHRD_HWX25 so that the x25 stack know
+*				that we have a X.25 stack implemented in
+*				firmware onboard
+* 1999/10/18	acme		support for X.25 sockets in if_send,
+*				beware: socket(AF_X25...) IS WORK IN PROGRESS,
+*				TCP/IP over X.25 via wanrouter not affected,
+*				working.
 * 1999/10/09	acme		chan_disc renamed to chan_disconnect,
 * 				began adding support for X.25 sockets:
 * 				conf->protocol in new_if
@@ -52,14 +59,14 @@
 *				memset is put into the unresolved symbols
 *				instead of using the inline memset functions...
 * 1999/01/02    acme 		began chan_connect, chan_send, x25_send
-* Dec 31, 1998	Arnaldo		x25_configure
+* 1998/12/31	acme		x25_configure
 *				this code can be compiled as non module
-* Dec 27, 1998	Arnaldo		code cleanup
+* 1998/12/27	acme		code cleanup
 *				IPX code wiped out! let's decrease code
 *				complexity for now, remember: I'm learning! :)
 *                               bps_to_speed_code OK
-* Dec 26, 1998	Arnaldo		Minimal debug code cleanup
-* Aug 08, 1998	Arnaldo		Initial version.
+* 1998/12/26	acme		Minimal debug code cleanup
+* 1998/08/08	acme		Initial version.
 */
 #define CYCLOMX_X25_DEBUG 1
 
@@ -71,7 +78,7 @@
 #include <linux/malloc.h>	/* kmalloc(), kfree() */
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <asm/byteorder.h>	/* htons(), etc. */
-#include <linux/if_arp.h>       /* ARPHRD_X25 */
+#include <linux/if_arp.h>       /* ARPHRD_HWX25 */
 #include <linux/cyclomx.h>	/* CYCLOM X common user API definitions */
 #include <linux/cycx_x25.h>	/* X.25 firmware API definitions */
 
@@ -137,10 +144,11 @@
 	   x25_disconnect_response (cycx_t *card, u8 link, u8 lcn);
 
 /* channel functions */
-int chan_connect (struct net_device *dev),
-    chan_send (struct net_device *dev, struct sk_buff *skb);
+static int chan_connect (struct net_device *dev),
+    	   chan_send (struct net_device *dev, struct sk_buff *skb);
 
-static void chan_disconnect (struct net_device *dev);
+static void chan_disconnect (struct net_device *dev),
+	    chan_x25_send_event(struct net_device *dev, u8 event);
 
 /* Miscellaneous functions */
 static void set_chan_state (struct net_device *dev, u8 state),
@@ -288,11 +296,11 @@
 	card->wandev.interface	= conf->interface;
 	card->wandev.clocking	= conf->clocking;
 	card->wandev.station	= conf->station;
-	card->isr		= &cyx_isr;
+	card->isr		= cyx_isr;
 	card->exec		= NULL;
-	card->wandev.update	= &update;
-	card->wandev.new_if	= &new_if;
-	card->wandev.del_if	= &del_if;
+	card->wandev.update	= update;
+	card->wandev.new_if	= new_if;
+	card->wandev.del_if	= del_if;
 	card->wandev.state	= WAN_DISCONNECTED;
 	return 0;
 }
@@ -328,7 +336,7 @@
 	x25_channel_t *chan;
 	int err = 0;
 
-	if (conf->name[0] == '\0' || strlen(conf->name) > WAN_IFNAME_SZ) {
+	if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
 		printk(KERN_INFO "%s: invalid interface name!\n",card->devname);
 		return -EINVAL;
 	}
@@ -403,7 +411,7 @@
 
 	/* prepare network device data space for registration */
 	dev->name = chan->name;
-	dev->init = &if_init;
+	dev->init = if_init;
 	dev->priv = chan;
 	return 0;
 }
@@ -411,11 +419,6 @@
 /* Delete logical channel. */
 static int del_if (wan_device_t *wandev, struct net_device *dev)
 {
-	if (!dev) {
-		printk(KERN_ERR "cycx_x25:del_if:dev == NULL!\n");
-		return 0;
-	}
-
 	if (dev->priv) {
 		x25_channel_t *chan = dev->priv;
 
@@ -447,16 +450,16 @@
 	wan_device_t *wandev = &card->wandev;
 
 	/* Initialize device driver entry points */
-	dev->open = &if_open;
-	dev->stop = &if_close;
-	dev->hard_header = &if_header;
-	dev->rebuild_header = &if_rebuild_hdr;
-	dev->hard_start_xmit = &if_send;
-	dev->get_stats = &if_stats;
+	dev->open = if_open;
+	dev->stop = if_close;
+	dev->hard_header = if_header;
+	dev->rebuild_header = if_rebuild_hdr;
+	dev->hard_start_xmit = if_send;
+	dev->get_stats = if_stats;
 
 	/* Initialize media-specific parameters */
 	dev->mtu = X25_CHAN_MTU;
-	dev->type = ARPHRD_X25;		/* ARP h/w type */
+	dev->type = ARPHRD_HWX25;	/* ARP h/w type */
 	dev->hard_header_len = 0;	/* media header length */
 	dev->addr_len = 0;		/* hardware address length */
 
@@ -577,27 +580,57 @@
                         "%s: unsupported Ethertype 0x%04X on interface %s!\n",
                         card->devname, skb->protocol, dev->name);
                 ++chan->ifstats.tx_errors;
-        } else switch (chan->state) {
-		case WAN_DISCONNECTED:
-			if (chan_connect(dev)) {
+        } else if (chan->protocol == ETH_P_IP) {
+		switch (chan->state) {
+			case WAN_DISCONNECTED:
+				if (chan_connect(dev)) {
+					dev->tbusy = 1;
+					return -EBUSY;
+				}
+				/* fall thru */
+			case WAN_CONNECTED:
+				reset_timer(dev);
+				dev->trans_start = jiffies;
 				dev->tbusy = 1;
-				return -EBUSY;
-			}
-			/* fall thru */
-		case WAN_CONNECTED:
-			reset_timer(dev);
-			dev->trans_start = jiffies;
-			dev->tbusy = 1;
 
-			if (chan_send(dev, skb)) {
-				return -EBUSY;
-			}
-			break;
-		default:
-			++chan->ifstats.tx_dropped;	
-			++card->wandev.stats.tx_dropped;
+				if (chan_send(dev, skb))
+					return -EBUSY;
+
+				break;
+			default:
+				++chan->ifstats.tx_dropped;	
+				++card->wandev.stats.tx_dropped;
+		} 
+	} else { /* chan->protocol == ETH_P_X25 */
+		switch (skb->data[0]) {
+			case 0: break;
+			case 1: /* Connect request */
+				chan_connect(dev);
+				goto free_packet;
+		        case 2: /* Disconnect request */
+				chan_disconnect(dev);
+				goto free_packet;
+		        default:
+				printk(KERN_INFO
+				       "%s: unknown %d x25-iface request on %s!\n",
+                       			card->devname, skb->data[0], dev->name);
+               			++chan->ifstats.tx_errors;
+				goto free_packet;
+		}
+
+		skb_pull(skb, 1); /* Remove control byte */
+		reset_timer(dev);
+		dev->trans_start = jiffies;
+		dev->tbusy = 1;
+
+		if (chan_send(dev, skb)) {
+			/* prepare for future retransmissions */
+			skb_push(skb, 1);
+			return -EBUSY;
+		}
 	}
 
+free_packet:
 	dev_kfree_skb(skb);
 	return 0;
 }
@@ -733,7 +766,8 @@
 		/* Allocate new socket buffer */
 		int bufsize = bitm ? dev->mtu : pktlen;
 
-		if ((skb = dev_alloc_skb(bufsize +
+		if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
+					 bufsize +
 					 dev->hard_header_len)) == NULL) {
 			printk(KERN_INFO "%s: no socket buffers available!\n",
 					 card->devname);
@@ -742,6 +776,10 @@
 			return;
 		}
 
+		if (chan->protocol == ETH_P_X25) /* X.25 socket layer control */
+			/* 0 = data packet (dev_alloc_skb zeroed skb->data) */
+			skb_put(skb, 1); 
+
 		skb->dev = dev;
 		skb->protocol = htons(chan->protocol);
 		chan->rx_skb = skb;
@@ -770,12 +808,11 @@
 	dev->last_rx = jiffies;		/* timestamp */
 	chan->rx_skb = NULL;		/* dequeue packet */
 
-	skb->protocol = htons(chan->protocol);
-	skb->dev = dev;
-	skb->mac.raw = skb->data;
-	netif_rx(skb);
 	++chan->ifstats.rx_packets;
 	chan->ifstats.rx_bytes += skb->len;
+
+	skb->mac.raw = skb->data;
+	netif_rx(skb);
 }
 
 /* Connect interrupt handler. */
@@ -1236,7 +1273,7 @@
  * Return:	0	connected
  *		>0	connection in progress
  *		<0	failure */
-int chan_connect (struct net_device *dev)
+static int chan_connect (struct net_device *dev)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
@@ -1307,6 +1344,10 @@
 				*(u16*)dev->dev_addr = htons(chan->lcn);
 				dev->tbusy = 0;
 				reset_timer(dev);
+
+				if (chan->protocol == ETH_P_X25)
+					chan_x25_send_event(dev, 1);
+
 				break;
 
 			case WAN_CONNECTING:
@@ -1329,6 +1370,10 @@
 					*(unsigned short*)dev->dev_addr = 0;
 					chan->lcn = 0;
                                 }
+
+				if (chan->protocol == ETH_P_X25)
+					chan_x25_send_event(dev, 2);
+
 				dev->tbusy = 0;
 				break;
 		}
@@ -1352,7 +1397,7 @@
  *    the packet into 'complete sequence' using M-bit.
  * 2. When transmission is complete, an event notification should be issued
  *    to the router.  */
-int chan_send (struct net_device *dev, struct sk_buff *skb)
+static int chan_send (struct net_device *dev, struct sk_buff *skb)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
@@ -1375,6 +1420,29 @@
 	++chan->ifstats.tx_packets;
 	chan->ifstats.tx_bytes += len;
 	return 0;
+}
+
+/* Send event (connection, disconnection, etc) to X.25 socket layer */
+
+static void chan_x25_send_event(struct net_device *dev, u8 event)
+{
+        struct sk_buff *skb;
+        unsigned char *ptr;
+
+        if ((skb = dev_alloc_skb(1)) == NULL) {
+                printk(KERN_ERR __FUNCTION__ ": out of memory\n");
+                return;
+        }
+
+        ptr  = skb_put(skb, 1);
+        *ptr = event;
+
+        skb->dev = dev;
+        skb->protocol = htons(ETH_P_X25);
+        skb->mac.raw = skb->data;
+        skb->pkt_type = PACKET_HOST;
+
+        netif_rx(skb);
 }
 
 /* Convert line speed in bps to a number used by cyclom 2x code. */
diff -u --recursive --new-file v2.3.24/linux/drivers/net/wd.c linux/drivers/net/wd.c
--- v2.3.24/linux/drivers/net/wd.c	Wed Aug 18 11:36:43 1999
+++ linux/drivers/net/wd.c	Fri Oct 29 13:20:35 1999
@@ -367,9 +367,9 @@
 
 #ifdef notdef
 	/* Officially this is what we are doing, but the readl() is faster */
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 #else
-	((unsigned int*)hdr)[0] = readl(hdr_start);
+	((unsigned int*)hdr)[0] = isa_readl(hdr_start);
 #endif
 }
 
@@ -387,12 +387,12 @@
 	if (xfer_start + count > dev->rmem_end) {
 		/* We must wrap the input move. */
 		int semi_count = dev->rmem_end - xfer_start;
-		memcpy_fromio(skb->data, xfer_start, semi_count);
+		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 
 	/* Turn off 16 bit access so that reboot works.	 ISA brain-damage */
@@ -411,10 +411,10 @@
 	if (ei_status.word16) {
 		/* Turn on and off 16 bit access so that reboot works. */
 		outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
-		memcpy_toio(shmem, buf, count);
+		isa_memcpy_toio(shmem, buf, count);
 		outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
 	} else
-		memcpy_toio(shmem, buf, count);
+		isa_memcpy_toio(shmem, buf, count);
 }
 
 
diff -u --recursive --new-file v2.3.24/linux/drivers/nubus/nubus.c linux/drivers/nubus/nubus.c
--- v2.3.24/linux/drivers/nubus/nubus.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/nubus/nubus.c	Thu Oct 28 14:34:46 1999
@@ -963,37 +963,39 @@
 	return strlen(ptr);
 }
 
-/* We're going to have to be a bit more sophisticated about this, I
-   think, because it doesn't really seem to work right when you do a
-   full listing of boards and devices */
-int get_nubus_list(char *buf)
+static int nubus_read_proc(char *buf, char **start, off_t off,
+				int count, int *eof, void *data)
 {
-	int nprinted, len, size;
-	struct nubus_board* board;
-#define MSG "\nwarning: page-size limit reached!\n"
-
-	/* reserve same for truncation warning message: */
-	size  = PAGE_SIZE - (strlen(MSG) + 1);
-	len   = sprintf(buf, "Nubus boards found:\n");
+	int nprinted, len, begin = 0;
+	int slot;
 
+	len   = sprintf(buf, "Nubus devices found:\n");
 	/* Walk the list of NuBus boards */
 	for (board = nubus_boards; board != NULL; board = board->next)
 	{
 		nprinted = sprint_nubus_board(board, buf + len, size - len);
-		if (nprinted < 0) {
-			return len + sprintf(buf + len, MSG);
-		}
+		if (nprinted < 0)
+			break;
 		len += nprinted;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+		if (len+begin >= off+count)
+			break;
 	}
+	if (slot==16 || len+begin < off)
+		*eof = 1;
+	off -= begin;
+	*strat = buf + off;
+	len -= off;
+	if (len>count)
+		len = count;
+	if (len<0)
+		len = 0;
 	return len;
 }
-
-static struct proc_dir_entry proc_old_nubus = {
-	PROC_NUBUS, 5, "nubus",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-#endif /* CONFIG_PROC_FS */
+#endif
 
 void __init nubus_scan_bus(void)
 {
@@ -1034,7 +1036,7 @@
 	nubus_scan_bus();
 
 #ifdef CONFIG_PROC_FS
-	proc_register(&proc_root, &proc_old_nubus);
+	create_proc_read_entry("nubus", 0, NULL, nubus_read_proc, NULL);
 	nubus_proc_init();
 #endif
 }
diff -u --recursive --new-file v2.3.24/linux/drivers/nubus/proc.c linux/drivers/nubus/proc.c
--- v2.3.24/linux/drivers/nubus/proc.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/nubus/proc.c	Thu Oct 28 14:34:46 1999
@@ -60,13 +60,6 @@
 	return (count > cnt) ? cnt : count;
 }
 
-static struct proc_dir_entry proc_nubus_devices = {
-	PROC_BUS_NUBUS_DEVICES, 7, "devices",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	get_nubus_dev_info
-};
-
 static struct proc_dir_entry *proc_bus_nubus_dir;
 
 static void nubus_proc_subdir(struct nubus_dev* dev,
@@ -178,6 +171,7 @@
 	if (!MACH_IS_MAC)
 		return;
 	proc_bus_nubus_dir = create_proc_entry("nubus", S_IFDIR, proc_bus);
-	proc_register(proc_bus_nubus_dir, &proc_nubus_devices);
+	create_proc_info_entry("devices", 0, proc_bus_nubus_dir,
+				get_nubus_dev_info);
 	proc_bus_nubus_add_devices();
 }
diff -u --recursive --new-file v2.3.24/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.3.24/linux/drivers/parport/parport_pc.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/parport/parport_pc.c	Fri Oct 29 11:05:08 1999
@@ -1782,6 +1782,9 @@
 		{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_B,
 		  PCI_ANY_ID, PCI_ANY_ID,
 		  1, { { 0, -1 }, } },
+		{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_BOCA_IOPPAR,
+		  PCI_ANY_ID, PCI_ANY_ID,
+		  1, { { 0, -1 }, } },
 		{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
 		  PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014,
 		  2, { { 4, -1 }, { 5, -1 }, } },
diff -u --recursive --new-file v2.3.24/linux/drivers/pci/devlist.h linux/drivers/pci/devlist.h
--- v2.3.24/linux/drivers/pci/devlist.h	Fri Oct 15 15:25:14 1999
+++ linux/drivers/pci/devlist.h	Fri Oct 29 11:05:08 1999
@@ -844,6 +844,13 @@
 	DEVICE( MOTOROLA_OOPS,	MOTOROLA_FALCON,"Falcon")
 ENDVENDOR()
 
+VENDOR( LAVA, "Lava Computer MFG" )
+	DEVICE( LAVA,		LAVA_PARALLEL,	"Lava Parallel")
+	DEVICE( LAVA,		LAVA_DUAL_PAR_A,"Lava Dual Parallel (A)")
+	DEVICE( LAVA,		LAVA_DUAL_PAR_B,"Lava Dual Parallel (B)")
+	DEVICE( LAVA,		LAVA_BOCA_IOPPAR,"BOCA Research IOPPAR")
+ENDVENDOR()
+
 VENDOR( SYMPHONY, "Symphony" )
 	DEVICE( SYMPHONY,	SYMPHONY_101,	"82C101")
 ENDVENDOR()
diff -u --recursive --new-file v2.3.24/linux/drivers/pci/helper.c linux/drivers/pci/helper.c
--- v2.3.24/linux/drivers/pci/helper.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/pci/helper.c	Thu Oct 28 17:32:25 1999
@@ -13,11 +13,12 @@
 #include <linux/pci.h>
 
 
-int pci_simple_probe (struct pci_simple_probe_entry *list, size_t match_limit,
-		      pci_simple_probe_callback cb, void *drvr_data)
+int pci_simple_probe (const struct pci_simple_probe_entry *list,
+		      size_t match_limit, pci_simple_probe_callback cb,
+		      void *drvr_data)
 {
 	struct pci_dev *dev;
-	struct pci_simple_probe_entry *ent;
+	const struct pci_simple_probe_entry *ent;
 	size_t matches = 0;
 	unsigned short vendor, device;
 	int rc;
diff -u --recursive --new-file v2.3.24/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c
--- v2.3.24/linux/drivers/pci/pcisyms.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/pci/pcisyms.c	Thu Oct 28 16:18:46 1999
@@ -24,6 +24,7 @@
 EXPORT_SYMBOL(pci_find_device);
 EXPORT_SYMBOL(pci_find_slot);
 EXPORT_SYMBOL(pci_set_master);
+EXPORT_SYMBOL(pci_simple_probe);
 #ifdef	CONFIG_PROC_FS
 EXPORT_SYMBOL(pci_proc_attach_device);
 EXPORT_SYMBOL(pci_proc_detach_device);
diff -u --recursive --new-file v2.3.24/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
--- v2.3.24/linux/drivers/pci/proc.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/pci/proc.c	Thu Oct 28 14:34:46 1999
@@ -271,13 +271,6 @@
 	return (count > cnt) ? cnt : count;
 }
 
-static struct proc_dir_entry proc_pci_devices = {
-	PROC_BUS_PCI_DEVICES, 7, "devices",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	get_pci_dev_info
-};
-
 static struct proc_dir_entry *proc_bus_pci_dir;
 
 int pci_proc_attach_device(struct pci_dev *dev)
@@ -498,37 +491,39 @@
 	return len;
 }
 
-
-static struct proc_dir_entry proc_old_pci = {
-	PROC_PCI, 3, "pci",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-
 /*
  * Return list of PCI devices as a character string for /proc/pci.
  * BUF is a buffer that is PAGE_SIZE bytes long.
  */
-int get_pci_list(char *buf)
+static int pci_read_proc(char *buf, char **start, off_t off,
+				int count, int *eof, void *data)
 {
-	int nprinted, len, size;
+	int nprinted, len, begin = 0;
 	struct pci_dev *dev;
-#	define MSG "\nwarning: page-size limit reached!\n"
 
-	/* reserve same for truncation warning message: */
-	size  = PAGE_SIZE - (strlen(MSG) + 1);
 	len   = sprintf(buf, "PCI devices found:\n");
 
 	for (dev = pci_devices; dev; dev = dev->next) {
-		nprinted = sprint_dev_config(dev, buf + len, size - len);
-		if (nprinted < 0) {
-			len += sprintf(buf + len, MSG);
-			proc_old_pci.size = len;
-			return len;
-		}
+		nprinted = sprint_dev_config(dev, buf + len, count - len);
+		if (nprinted < 0)
+			break;
 		len += nprinted;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+		if (len+begin >= off+count)
+			break;
 	}
-	proc_old_pci.size = len;
+	if (!dev || len+begin < off)
+		*eof = 1;
+	off -= begin;
+	*start = buf + off;
+	len -= off;
+	if (len>count)
+		len = count;
+	if (len<0)
+		len = 0;
 	return len;
 }
 
@@ -536,9 +531,10 @@
 {
 	if (pci_present()) {
 		proc_bus_pci_dir = create_proc_entry("pci", S_IFDIR, proc_bus);
-		proc_register(proc_bus_pci_dir, &proc_pci_devices);
+		create_proc_info_entry("devices",0, proc_bus_pci_dir,
+					get_pci_dev_info);
 		proc_bus_pci_add(pci_root);
-		proc_register(&proc_root, &proc_old_pci);
+		create_proc_read_entry("pci", 0, NULL, pci_read_proc, NULL);
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.3.24/linux/drivers/sbus/audio/Config.in linux/drivers/sbus/audio/Config.in
--- v2.3.24/linux/drivers/sbus/audio/Config.in	Wed Nov 18 09:06:05 1998
+++ linux/drivers/sbus/audio/Config.in	Mon Nov  1 10:31:28 1999
@@ -4,11 +4,11 @@
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
 
-  comment 'Linux/SPARC audio subsystem (EXPERIMENTAL)'
+   comment 'Linux/SPARC audio subsystem (EXPERIMENTAL)'
 
-  tristate 'Audio support (EXPERIMENTAL)' CONFIG_SPARCAUDIO
-  dep_tristate '  AMD7930 Lowlevel Driver' CONFIG_SPARCAUDIO_AMD7930 $CONFIG_SPARCAUDIO
-  dep_tristate '  CS4231 Lowlevel Driver' CONFIG_SPARCAUDIO_CS4231 $CONFIG_SPARCAUDIO
-  dep_tristate '  DBRI Lowlevel Driver' CONFIG_SPARCAUDIO_DBRI $CONFIG_SPARCAUDIO
-  dep_tristate '  Dummy Lowlevel Driver' CONFIG_SPARCAUDIO_DUMMY $CONFIG_SPARCAUDIO
+   tristate 'Audio support (EXPERIMENTAL)' CONFIG_SPARCAUDIO
+   dep_tristate '  AMD7930 Lowlevel Driver' CONFIG_SPARCAUDIO_AMD7930 $CONFIG_SPARCAUDIO
+   dep_tristate '  CS4231 Lowlevel Driver' CONFIG_SPARCAUDIO_CS4231 $CONFIG_SPARCAUDIO
+   dep_tristate '  DBRI Lowlevel Driver' CONFIG_SPARCAUDIO_DBRI $CONFIG_SPARCAUDIO
+   dep_tristate '  Dummy Lowlevel Driver' CONFIG_SPARCAUDIO_DUMMY $CONFIG_SPARCAUDIO
 fi
diff -u --recursive --new-file v2.3.24/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in
--- v2.3.24/linux/drivers/sbus/char/Config.in	Fri Sep 10 23:57:30 1999
+++ linux/drivers/sbus/char/Config.in	Mon Nov  1 10:31:28 1999
@@ -2,21 +2,21 @@
 tristate '/dev/openprom device support' CONFIG_SUN_OPENPROMIO
 tristate 'Mostek real time clock support' CONFIG_SUN_MOSTEK_RTC
 if [ "$ARCH" = "sparc64" ]; then
-	if [ "$CONFIG_PCI" = "y" ]; then
-		tristate 'Siemens SAB82532 serial support' CONFIG_SAB82532
-	fi
-	tristate 'OBP Flash Device support' CONFIG_OBP_FLASH
+   if [ "$CONFIG_PCI" = "y" ]; then
+      tristate 'Siemens SAB82532 serial support' CONFIG_SAB82532
+   fi
+   tristate 'OBP Flash Device support' CONFIG_OBP_FLASH
 fi
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  tristate 'Bidirectional parallel port support (obsolete)' CONFIG_SUN_BPP
-  tristate 'Videopix Frame Grabber (EXPERIMENTAL)' CONFIG_SUN_VIDEOPIX
-  tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA
-  tristate 'Tadpole TS102 Microcontroller support' CONFIG_TADPOLE_TS102_UCTRL
+   tristate 'Bidirectional parallel port support (OBSOLETE)' CONFIG_SUN_BPP
+   tristate 'Videopix Frame Grabber (EXPERIMENTAL)' CONFIG_SUN_VIDEOPIX
+   tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA
+   tristate 'Tadpole TS102 Microcontroller support (EXPERIMENTAL)' CONFIG_TADPOLE_TS102_UCTRL
 
-  # XXX Why don't we do "source drivers/char/Config.in" somewhere?
-  if [ "$CONFIG_PCI" = "y" ]; then
-    define_bool CONFIG_APM_RTC_IS_GMT y		# no shit
-    bool 'PC-style RTC' CONFIG_RTC
-  fi
+   # XXX Why don't we do "source drivers/char/Config.in" somewhere?
+   if [ "$CONFIG_PCI" = "y" ]; then
+      define_bool CONFIG_APM_RTC_IS_GMT y		# no shit
+      bool 'PC-style RTC' CONFIG_RTC
+   fi
 fi
diff -u --recursive --new-file v2.3.24/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c
--- v2.3.24/linux/drivers/sbus/char/flash.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/char/flash.c	Fri Oct 29 11:00:57 1999
@@ -37,9 +37,6 @@
 	unsigned long addr;
 	unsigned long size;
 
-	if (vma->vm_offset & ~(PAGE_MASK))
-		return -ENXIO;
-
 	if (flash.read_base == flash.write_base) {
 		addr = flash.read_base;
 		size = flash.read_size;
diff -u --recursive --new-file v2.3.24/linux/drivers/scsi/53c8xx_d.h linux/drivers/scsi/53c8xx_d.h
--- v2.3.24/linux/drivers/scsi/53c8xx_d.h	Mon May 11 12:49:02 1998
+++ linux/drivers/scsi/53c8xx_d.h	Fri Oct 29 10:53:32 1999
@@ -1,4 +1,4 @@
-u32 SCRIPT[] = {
+static u32 SCRIPT[] = {
 /*
 
 
@@ -2179,40 +2179,40 @@
 };
 
 #define A_NCR53c7xx_msg_abort	0x00000000
-u32 A_NCR53c7xx_msg_abort_used[] = {
+static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = {
 	0x00000249,
 };
 
 #define A_NCR53c7xx_msg_reject	0x00000000
-u32 A_NCR53c7xx_msg_reject_used[] = {
+static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = {
 	0x00000172,
 };
 
 #define A_NCR53c7xx_sink	0x00000000
-u32 A_NCR53c7xx_sink_used[] = {
+static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = {
 	0x00000233,
 	0x00000239,
 	0x0000023f,
 };
 
 #define A_NCR53c7xx_zero	0x00000000
-u32 A_NCR53c7xx_zero_used[] = {
+static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = {
 	0x0000022f,
 	0x00000245,
 };
 
 #define A_NOP_insn	0x00000000
-u32 A_NOP_insn_used[] = {
+static u32 A_NOP_insn_used[] __attribute((unused)) = {
 	0x00000010,
 };
 
 #define A_addr_reconnect_dsa_head	0x00000000
-u32 A_addr_reconnect_dsa_head_used[] = {
+static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = {
 	0x000001a7,
 };
 
 #define A_addr_scratch	0x00000000
-u32 A_addr_scratch_used[] = {
+static u32 A_addr_scratch_used[] __attribute((unused)) = {
 	0x00000004,
 	0x0000001b,
 	0x00000046,
@@ -2227,13 +2227,13 @@
 };
 
 #define A_addr_temp	0x00000000
-u32 A_addr_temp_used[] = {
+static u32 A_addr_temp_used[] __attribute((unused)) = {
 	0x00000025,
 	0x00000034,
 };
 
 #define A_dmode_memory_to_memory	0x00000000
-u32 A_dmode_memory_to_memory_used[] = {
+static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = {
 	0x00000005,
 	0x0000001c,
 	0x00000027,
@@ -2251,7 +2251,7 @@
 };
 
 #define A_dmode_memory_to_ncr	0x00000000
-u32 A_dmode_memory_to_ncr_used[] = {
+static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = {
 	0x00000000,
 	0x00000017,
 	0x00000030,
@@ -2260,7 +2260,7 @@
 };
 
 #define A_dmode_ncr_to_memory	0x00000000
-u32 A_dmode_ncr_to_memory_used[] = {
+static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = {
 	0x00000022,
 	0x00000064,
 	0x00000070,
@@ -2272,161 +2272,161 @@
 };
 
 #define A_dsa_check_reselect	0x00000000
-u32 A_dsa_check_reselect_used[] = {
+static u32 A_dsa_check_reselect_used[] __attribute((unused)) = {
 	0x000001bd,
 };
 
 #define A_dsa_cmdout	0x00000048
-u32 A_dsa_cmdout_used[] = {
+static u32 A_dsa_cmdout_used[] __attribute((unused)) = {
 	0x00000094,
 };
 
 #define A_dsa_cmnd	0x00000038
-u32 A_dsa_cmnd_used[] = {
+static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_datain	0x00000054
-u32 A_dsa_datain_used[] = {
+static u32 A_dsa_datain_used[] __attribute((unused)) = {
 	0x000000bb,
 };
 
 #define A_dsa_dataout	0x00000050
-u32 A_dsa_dataout_used[] = {
+static u32 A_dsa_dataout_used[] __attribute((unused)) = {
 	0x000000a5,
 };
 
 #define A_dsa_end	0x00000070
-u32 A_dsa_end_used[] = {
+static u32 A_dsa_end_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_fields_start	0x00000000
-u32 A_dsa_fields_start_used[] = {
+static u32 A_dsa_fields_start_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_msgin	0x00000058
-u32 A_dsa_msgin_used[] = {
+static u32 A_dsa_msgin_used[] __attribute((unused)) = {
 	0x00000188,
 };
 
 #define A_dsa_msgout	0x00000040
-u32 A_dsa_msgout_used[] = {
+static u32 A_dsa_msgout_used[] __attribute((unused)) = {
 	0x00000086,
 };
 
 #define A_dsa_msgout_other	0x00000068
-u32 A_dsa_msgout_other_used[] = {
+static u32 A_dsa_msgout_other_used[] __attribute((unused)) = {
 	0x00000180,
 };
 
 #define A_dsa_next	0x00000030
-u32 A_dsa_next_used[] = {
+static u32 A_dsa_next_used[] __attribute((unused)) = {
 	0x0000005c,
 };
 
 #define A_dsa_restore_pointers	0x00000000
-u32 A_dsa_restore_pointers_used[] = {
+static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = {
 	0x0000012e,
 };
 
 #define A_dsa_save_data_pointer	0x00000000
-u32 A_dsa_save_data_pointer_used[] = {
+static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = {
 	0x00000115,
 };
 
 #define A_dsa_select	0x0000003c
-u32 A_dsa_select_used[] = {
+static u32 A_dsa_select_used[] __attribute((unused)) = {
 	0x00000081,
 };
 
 #define A_dsa_status	0x00000060
-u32 A_dsa_status_used[] = {
+static u32 A_dsa_status_used[] __attribute((unused)) = {
 	0x00000184,
 };
 
 #define A_dsa_temp_addr_array_value	0x00000000
-u32 A_dsa_temp_addr_array_value_used[] = {
+static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_temp_addr_dsa_value	0x00000000
-u32 A_dsa_temp_addr_dsa_value_used[] = {
+static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = {
 	0x00000003,
 };
 
 #define A_dsa_temp_addr_new_value	0x00000000
-u32 A_dsa_temp_addr_new_value_used[] = {
+static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_temp_addr_next	0x00000000
-u32 A_dsa_temp_addr_next_used[] = {
+static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = {
 	0x00000015,
 	0x0000004e,
 };
 
 #define A_dsa_temp_addr_residual	0x00000000
-u32 A_dsa_temp_addr_residual_used[] = {
+static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = {
 	0x0000002a,
 	0x00000039,
 };
 
 #define A_dsa_temp_addr_saved_pointer	0x00000000
-u32 A_dsa_temp_addr_saved_pointer_used[] = {
+static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = {
 	0x00000026,
 	0x00000033,
 };
 
 #define A_dsa_temp_addr_saved_residual	0x00000000
-u32 A_dsa_temp_addr_saved_residual_used[] = {
+static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = {
 	0x0000002b,
 	0x00000038,
 };
 
 #define A_dsa_temp_lun	0x00000000
-u32 A_dsa_temp_lun_used[] = {
+static u32 A_dsa_temp_lun_used[] __attribute((unused)) = {
 	0x0000004b,
 };
 
 #define A_dsa_temp_next	0x00000000
-u32 A_dsa_temp_next_used[] = {
+static u32 A_dsa_temp_next_used[] __attribute((unused)) = {
 	0x0000001a,
 };
 
 #define A_dsa_temp_sync	0x00000000
-u32 A_dsa_temp_sync_used[] = {
+static u32 A_dsa_temp_sync_used[] __attribute((unused)) = {
 	0x00000053,
 };
 
 #define A_dsa_temp_target	0x00000000
-u32 A_dsa_temp_target_used[] = {
+static u32 A_dsa_temp_target_used[] __attribute((unused)) = {
 	0x00000040,
 };
 
 #define A_int_debug_break	0x03000000
-u32 A_int_debug_break_used[] = {
+static u32 A_int_debug_break_used[] __attribute((unused)) = {
 	0x00000217,
 };
 
 #define A_int_debug_panic	0x030b0000
-u32 A_int_debug_panic_used[] = {
+static u32 A_int_debug_panic_used[] __attribute((unused)) = {
 	0x000001e8,
 	0x000001f8,
 };
 
 #define A_int_err_check_condition	0x00030000
-u32 A_int_err_check_condition_used[] = {
+static u32 A_int_err_check_condition_used[] __attribute((unused)) = {
 	0x00000194,
 };
 
 #define A_int_err_no_phase	0x00040000
-u32 A_int_err_no_phase_used[] = {
+static u32 A_int_err_no_phase_used[] __attribute((unused)) = {
 };
 
 #define A_int_err_selected	0x00010000
-u32 A_int_err_selected_used[] = {
+static u32 A_int_err_selected_used[] __attribute((unused)) = {
 	0x000001da,
 };
 
 #define A_int_err_unexpected_phase	0x00000000
-u32 A_int_err_unexpected_phase_used[] = {
+static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = {
 	0x0000008c,
 	0x00000092,
 	0x0000009a,
@@ -2444,67 +2444,67 @@
 };
 
 #define A_int_err_unexpected_reselect	0x00020000
-u32 A_int_err_unexpected_reselect_used[] = {
+static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = {
 	0x000001ba,
 };
 
 #define A_int_msg_1	0x01020000
-u32 A_int_msg_1_used[] = {
+static u32 A_int_msg_1_used[] __attribute((unused)) = {
 	0x0000010e,
 	0x00000110,
 };
 
 #define A_int_msg_sdtr	0x01010000
-u32 A_int_msg_sdtr_used[] = {
+static u32 A_int_msg_sdtr_used[] __attribute((unused)) = {
 	0x0000016c,
 };
 
 #define A_int_msg_wdtr	0x01000000
-u32 A_int_msg_wdtr_used[] = {
+static u32 A_int_msg_wdtr_used[] __attribute((unused)) = {
 	0x00000160,
 };
 
 #define A_int_norm_aborted	0x02040000
-u32 A_int_norm_aborted_used[] = {
+static u32 A_int_norm_aborted_used[] __attribute((unused)) = {
 	0x0000024d,
 };
 
 #define A_int_norm_command_complete	0x02020000
-u32 A_int_norm_command_complete_used[] = {
+static u32 A_int_norm_command_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_disconnected	0x02030000
-u32 A_int_norm_disconnected_used[] = {
+static u32 A_int_norm_disconnected_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_reselect_complete	0x02010000
-u32 A_int_norm_reselect_complete_used[] = {
+static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_reset	0x02050000
-u32 A_int_norm_reset_used[] = {
+static u32 A_int_norm_reset_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_select_complete	0x02000000
-u32 A_int_norm_select_complete_used[] = {
+static u32 A_int_norm_select_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_test_1	0x04000000
-u32 A_int_test_1_used[] = {
+static u32 A_int_test_1_used[] __attribute((unused)) = {
 	0x000001fd,
 };
 
 #define A_int_test_2	0x04010000
-u32 A_int_test_2_used[] = {
+static u32 A_int_test_2_used[] __attribute((unused)) = {
 	0x00000215,
 };
 
 #define A_int_test_3	0x04020000
-u32 A_int_test_3_used[] = {
+static u32 A_int_test_3_used[] __attribute((unused)) = {
 };
 
 #define A_msg_buf	0x00000000
-u32 A_msg_buf_used[] = {
+static u32 A_msg_buf_used[] __attribute((unused)) = {
 	0x00000102,
 	0x0000014e,
 	0x00000158,
@@ -2514,24 +2514,24 @@
 };
 
 #define A_reconnect_dsa_head	0x00000000
-u32 A_reconnect_dsa_head_used[] = {
+static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = {
 	0x0000006c,
 	0x00000074,
 	0x000001a0,
 };
 
 #define A_reselected_identify	0x00000000
-u32 A_reselected_identify_used[] = {
+static u32 A_reselected_identify_used[] __attribute((unused)) = {
 	0x00000045,
 	0x0000019c,
 };
 
 #define A_reselected_tag	0x00000000
-u32 A_reselected_tag_used[] = {
+static u32 A_reselected_tag_used[] __attribute((unused)) = {
 };
 
 #define A_schedule	0x00000000
-u32 A_schedule_used[] = {
+static u32 A_schedule_used[] __attribute((unused)) = {
 	0x0000007e,
 	0x00000192,
 	0x000001e2,
@@ -2539,12 +2539,12 @@
 };
 
 #define A_test_dest	0x00000000
-u32 A_test_dest_used[] = {
+static u32 A_test_dest_used[] __attribute((unused)) = {
 	0x000001fb,
 };
 
 #define A_test_src	0x00000000
-u32 A_test_src_used[] = {
+static u32 A_test_src_used[] __attribute((unused)) = {
 	0x000001fa,
 };
 
@@ -2582,7 +2582,7 @@
 #define Ent_test_2	0x000007f8
 #define Ent_test_2_msgout	0x00000810
 #define Ent_wait_reselect	0x00000654
-u32 LABELPATCHES[] = {
+static u32 LABELPATCHES[] __attribute((unused)) = {
 	0x00000008,
 	0x0000000a,
 	0x00000013,
@@ -2666,12 +2666,12 @@
 	0x00000243,
 };
 
-struct {
+static struct {
 	u32	offset;
 	void		*address;
-} EXTERNAL_PATCHES[] = {
+} EXTERNAL_PATCHES[] __attribute((unused)) = {
 };
 
-u32 INSTRUCTIONS	= 301;
-u32 PATCHES	= 81;
-u32 EXTERNAL_PATCHES_LEN	= 0;
+static u32 INSTRUCTIONS __attribute((unused))	= 301;
+static u32 PATCHES __attribute((unused))	= 81;
+static u32 EXTERNAL_PATCHES_LEN __attribute((unused))	= 0;
diff -u --recursive --new-file v2.3.24/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.24/linux/drivers/scsi/scsi.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/scsi/scsi.c	Mon Nov  1 11:37:00 1999
@@ -263,6 +263,7 @@
 								 * SCSI code to reset bus.*/
 	{"QUANTUM", "LPS525S", "3110", BLIST_NOLUN},		/* Locks sometimes if polled for lun != 0 */
 	{"QUANTUM", "PD1225S", "3110", BLIST_NOLUN},		/* Locks sometimes if polled for lun != 0 */
+	{"QUANTUM", "FIREBALL ST4.3S", "0F0C", BLIST_NOLUN},	/* Locks up when polled for lun != 0 */
 	{"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN},		/* Locks up if polled for lun != 0 */
 	{"SANKYO", "CP525", "6.64", BLIST_NOLUN},		/* causes failed REQ SENSE, extra reset */
 	{"HP", "C1750A", "3226", BLIST_NOLUN},			/* scanjet iic */
diff -u --recursive --new-file v2.3.24/linux/drivers/scsi/sim710_d.h linux/drivers/scsi/sim710_d.h
--- v2.3.24/linux/drivers/scsi/sim710_d.h	Sat Oct  9 11:47:50 1999
+++ linux/drivers/scsi/sim710_d.h	Fri Oct 29 10:53:32 1999
@@ -1,4 +1,4 @@
-u32 SCRIPT[] = {
+static u32 SCRIPT[] = {
 /*
 
 
@@ -1776,12 +1776,12 @@
 };
 
 #define A_dsa_cmnd	0x00000010
-u32 A_dsa_cmnd_used[] = {
+static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
 	0x0000001d,
 };
 
 #define A_dsa_datain	0x00000028
-u32 A_dsa_datain_used[] = {
+static u32 A_dsa_datain_used[] __attribute((unused)) = {
 	0x0000003d,
 	0x0000003f,
 	0x00000041,
@@ -1913,7 +1913,7 @@
 };
 
 #define A_dsa_dataout	0x00000428
-u32 A_dsa_dataout_used[] = {
+static u32 A_dsa_dataout_used[] __attribute((unused)) = {
 	0x00000143,
 	0x00000145,
 	0x00000147,
@@ -2045,12 +2045,12 @@
 };
 
 #define A_dsa_msgin	0x00000020
-u32 A_dsa_msgin_used[] = {
+static u32 A_dsa_msgin_used[] __attribute((unused)) = {
 	0x0000002f,
 };
 
 #define A_dsa_msgout	0x00000008
-u32 A_dsa_msgout_used[] = {
+static u32 A_dsa_msgout_used[] __attribute((unused)) = {
 	0x00000013,
 	0x00000285,
 	0x000002c5,
@@ -2058,50 +2058,50 @@
 };
 
 #define A_dsa_select	0x00000000
-u32 A_dsa_select_used[] = {
+static u32 A_dsa_select_used[] __attribute((unused)) = {
 	0x00000006,
 };
 
 #define A_dsa_size	0x00000828
-u32 A_dsa_size_used[] = {
+static u32 A_dsa_size_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_status	0x00000018
-u32 A_dsa_status_used[] = {
+static u32 A_dsa_status_used[] __attribute((unused)) = {
 	0x0000002b,
 };
 
 #define A_had_cmdout	0x00000004
-u32 A_had_cmdout_used[] = {
+static u32 A_had_cmdout_used[] __attribute((unused)) = {
 	0x0000001a,
 };
 
 #define A_had_datain	0x00000008
-u32 A_had_datain_used[] = {
+static u32 A_had_datain_used[] __attribute((unused)) = {
 	0x00000038,
 };
 
 #define A_had_dataout	0x00000010
-u32 A_had_dataout_used[] = {
+static u32 A_had_dataout_used[] __attribute((unused)) = {
 	0x0000013e,
 };
 
 #define A_had_extmsg	0x00000080
-u32 A_had_extmsg_used[] = {
+static u32 A_had_extmsg_used[] __attribute((unused)) = {
 	0x0000025a,
 	0x0000029a,
 	0x000002da,
 };
 
 #define A_had_msgin	0x00000040
-u32 A_had_msgin_used[] = {
+static u32 A_had_msgin_used[] __attribute((unused)) = {
 	0x00000248,
 	0x00000288,
 	0x000002c8,
 };
 
 #define A_had_msgout	0x00000002
-u32 A_had_msgout_used[] = {
+static u32 A_had_msgout_used[] __attribute((unused)) = {
 	0x00000010,
 	0x00000282,
 	0x000002c2,
@@ -2109,161 +2109,161 @@
 };
 
 #define A_had_select	0x00000001
-u32 A_had_select_used[] = {
+static u32 A_had_select_used[] __attribute((unused)) = {
 	0x0000000c,
 };
 
 #define A_had_status	0x00000020
-u32 A_had_status_used[] = {
+static u32 A_had_status_used[] __attribute((unused)) = {
 };
 
 #define A_int_bad_extmsg1a	0xab930000
-u32 A_int_bad_extmsg1a_used[] = {
+static u32 A_int_bad_extmsg1a_used[] __attribute((unused)) = {
 	0x00000263,
 };
 
 #define A_int_bad_extmsg1b	0xab930001
-u32 A_int_bad_extmsg1b_used[] = {
+static u32 A_int_bad_extmsg1b_used[] __attribute((unused)) = {
 	0x0000026b,
 };
 
 #define A_int_bad_extmsg2a	0xab930002
-u32 A_int_bad_extmsg2a_used[] = {
+static u32 A_int_bad_extmsg2a_used[] __attribute((unused)) = {
 	0x000002a3,
 };
 
 #define A_int_bad_extmsg2b	0xab930003
-u32 A_int_bad_extmsg2b_used[] = {
+static u32 A_int_bad_extmsg2b_used[] __attribute((unused)) = {
 	0x000002ab,
 };
 
 #define A_int_bad_extmsg3a	0xab930004
-u32 A_int_bad_extmsg3a_used[] = {
+static u32 A_int_bad_extmsg3a_used[] __attribute((unused)) = {
 	0x000002e3,
 };
 
 #define A_int_bad_extmsg3b	0xab930005
-u32 A_int_bad_extmsg3b_used[] = {
+static u32 A_int_bad_extmsg3b_used[] __attribute((unused)) = {
 	0x000002eb,
 };
 
 #define A_int_bad_msg1	0xab930006
-u32 A_int_bad_msg1_used[] = {
+static u32 A_int_bad_msg1_used[] __attribute((unused)) = {
 	0x00000255,
 };
 
 #define A_int_bad_msg2	0xab930007
-u32 A_int_bad_msg2_used[] = {
+static u32 A_int_bad_msg2_used[] __attribute((unused)) = {
 	0x00000295,
 };
 
 #define A_int_bad_msg3	0xab930008
-u32 A_int_bad_msg3_used[] = {
+static u32 A_int_bad_msg3_used[] __attribute((unused)) = {
 	0x000002d5,
 };
 
 #define A_int_cmd_bad_phase	0xab930009
-u32 A_int_cmd_bad_phase_used[] = {
+static u32 A_int_cmd_bad_phase_used[] __attribute((unused)) = {
 	0x00000027,
 };
 
 #define A_int_cmd_complete	0xab93000a
-u32 A_int_cmd_complete_used[] = {
+static u32 A_int_cmd_complete_used[] __attribute((unused)) = {
 	0x00000037,
 };
 
 #define A_int_data_bad_phase	0xab93000b
-u32 A_int_data_bad_phase_used[] = {
+static u32 A_int_data_bad_phase_used[] __attribute((unused)) = {
 	0x00000247,
 };
 
 #define A_int_disc1	0xab930019
-u32 A_int_disc1_used[] = {
+static u32 A_int_disc1_used[] __attribute((unused)) = {
 	0x00000277,
 };
 
 #define A_int_disc2	0xab93001a
-u32 A_int_disc2_used[] = {
+static u32 A_int_disc2_used[] __attribute((unused)) = {
 	0x000002b7,
 };
 
 #define A_int_disc3	0xab93001b
-u32 A_int_disc3_used[] = {
+static u32 A_int_disc3_used[] __attribute((unused)) = {
 	0x000002f7,
 };
 
 #define A_int_msg_sdtr1	0xab93000c
-u32 A_int_msg_sdtr1_used[] = {
+static u32 A_int_msg_sdtr1_used[] __attribute((unused)) = {
 	0x00000271,
 };
 
 #define A_int_msg_sdtr2	0xab93000d
-u32 A_int_msg_sdtr2_used[] = {
+static u32 A_int_msg_sdtr2_used[] __attribute((unused)) = {
 	0x000002b1,
 };
 
 #define A_int_msg_sdtr3	0xab93000e
-u32 A_int_msg_sdtr3_used[] = {
+static u32 A_int_msg_sdtr3_used[] __attribute((unused)) = {
 	0x000002f1,
 };
 
 #define A_int_no_msgout1	0xab93000f
-u32 A_int_no_msgout1_used[] = {
+static u32 A_int_no_msgout1_used[] __attribute((unused)) = {
 	0x00000281,
 };
 
 #define A_int_no_msgout2	0xab930010
-u32 A_int_no_msgout2_used[] = {
+static u32 A_int_no_msgout2_used[] __attribute((unused)) = {
 	0x000002c1,
 };
 
 #define A_int_no_msgout3	0xab930011
-u32 A_int_no_msgout3_used[] = {
+static u32 A_int_no_msgout3_used[] __attribute((unused)) = {
 	0x00000301,
 };
 
 #define A_int_not_cmd_complete	0xab930012
-u32 A_int_not_cmd_complete_used[] = {
+static u32 A_int_not_cmd_complete_used[] __attribute((unused)) = {
 	0x00000031,
 };
 
 #define A_int_not_rej	0xab93001c
-u32 A_int_not_rej_used[] = {
+static u32 A_int_not_rej_used[] __attribute((unused)) = {
 	0x0000030d,
 };
 
 #define A_int_resel_not_msgin	0xab930016
-u32 A_int_resel_not_msgin_used[] = {
+static u32 A_int_resel_not_msgin_used[] __attribute((unused)) = {
 	0x00000317,
 };
 
 #define A_int_reselected	0xab930017
-u32 A_int_reselected_used[] = {
+static u32 A_int_reselected_used[] __attribute((unused)) = {
 	0x0000031b,
 };
 
 #define A_int_sel_no_ident	0xab930013
-u32 A_int_sel_no_ident_used[] = {
+static u32 A_int_sel_no_ident_used[] __attribute((unused)) = {
 	0x0000000f,
 };
 
 #define A_int_sel_not_cmd	0xab930014
-u32 A_int_sel_not_cmd_used[] = {
+static u32 A_int_sel_not_cmd_used[] __attribute((unused)) = {
 	0x00000019,
 };
 
 #define A_int_selected	0xab930018
-u32 A_int_selected_used[] = {
+static u32 A_int_selected_used[] __attribute((unused)) = {
 	0x0000032d,
 };
 
 #define A_int_status_not_msgin	0xab930015
-u32 A_int_status_not_msgin_used[] = {
+static u32 A_int_status_not_msgin_used[] __attribute((unused)) = {
 	0x0000002d,
 };
 
 #define A_msgin_buf	0x00000000
-u32 A_msgin_buf_used[] = {
+static u32 A_msgin_buf_used[] __attribute((unused)) = {
 	0x0000024b,
 	0x0000025f,
 	0x00000267,
@@ -2280,7 +2280,7 @@
 };
 
 #define A_reselected_identify	0x00000000
-u32 A_reselected_identify_used[] = {
+static u32 A_reselected_identify_used[] __attribute((unused)) = {
 	0x00000319,
 };
 
@@ -2304,7 +2304,7 @@
 #define Ent_wait_disc2	0x00000ad0
 #define Ent_wait_disc3	0x00000bd0
 #define Ent_wait_disc_complete	0x000000d0
-u32 LABELPATCHES[] = {
+static u32 LABELPATCHES[] __attribute((unused)) = {
 	0x00000007,
 	0x00000009,
 	0x00000015,
@@ -2349,12 +2349,12 @@
 	0x0000032b,
 };
 
-struct {
+static struct {
 	u32	offset;
 	void		*address;
-} EXTERNAL_PATCHES[] = {
+} EXTERNAL_PATCHES[] __attribute((unused)) = {
 };
 
-u32 INSTRUCTIONS	= 407;
-u32 PATCHES	= 42;
-u32 EXTERNAL_PATCHES_LEN	= 0;
+static u32 INSTRUCTIONS __attribute((unused))	= 407;
+static u32 PATCHES __attribute((unused))	= 42;
+static u32 EXTERNAL_PATCHES_LEN __attribute((unused))	= 0;
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.3.24/linux/drivers/sound/cmpci.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/cmpci.c	Mon Nov  1 10:31:28 1999
@@ -1333,7 +1333,7 @@
 		db = &s->dma_adc;
 	} else 
 		return -EINVAL;
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.3.24/linux/drivers/sound/es1370.c	Fri Sep 10 23:57:35 1999
+++ linux/drivers/sound/es1370.c	Sat Oct 30 09:45:36 1999
@@ -113,6 +113,7 @@
  *                     replaced current->state = x with set_current_state(x)
  *    03.09.99   0.30  change read semantics for MIDI to match
  *                     OSS more closely; remove possible wakeup race
+ *    28.10.99   0.31  More waitqueue races fixed
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -1064,9 +1065,9 @@
 	
 	if (s->dma_dac1.mapped || !s->dma_dac1.ready)
 		return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac1.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac1.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1100,9 +1101,9 @@
 
 	if (s->dma_dac2.mapped || !s->dma_dac2.ready)
 		return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac2.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac2.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1133,6 +1134,7 @@
 static ssize_t es1370_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1148,26 +1150,38 @@
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
 	ret = 0;
+        add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		swptr = s->dma_adc.swptr;
 		cnt = s->dma_adc.dmasize-swptr;
 		if (s->dma_adc.count < cnt)
 			cnt = s->dma_adc.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_adc(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_adc.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_adc.swptr = swptr;
@@ -1178,12 +1192,15 @@
 		ret += cnt;
 		start_adc(s);
 	}
+        remove_wait_queue(&s->dma_adc.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
 static ssize_t es1370_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1199,6 +1216,7 @@
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
 	ret = 0;
+        add_wait_queue(&s->dma_dac2.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac2.count < 0) {
@@ -1209,20 +1227,31 @@
 		cnt = s->dma_dac2.dmasize-swptr;
 		if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
 			cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac2(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac2.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac2.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac2.swptr = swptr;
@@ -1234,6 +1263,8 @@
 		ret += cnt;
 		start_dac2(s);
 	}
+        remove_wait_queue(&s->dma_dac2.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1285,7 +1316,7 @@
 		db = &s->dma_adc;
 	} else 
 		return -EINVAL;
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
@@ -1608,6 +1639,7 @@
 static int es1370_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1370_state *s = devs;
 	unsigned long flags;
 
@@ -1624,8 +1656,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -1676,8 +1712,8 @@
 		dealloc_dmabuf(&s->dma_adc);
 	}
 	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -1705,6 +1741,7 @@
 static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret = 0;
 	unsigned long flags;
 	unsigned swptr;
@@ -1719,6 +1756,7 @@
 		return ret;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
+        add_wait_queue(&s->dma_dac1.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac1.count < 0) {
@@ -1729,20 +1767,31 @@
 		cnt = s->dma_dac1.dmasize-swptr;
 		if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
 			cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac1(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac1.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac1.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac1.swptr = swptr;
@@ -1754,6 +1803,8 @@
 		ret += cnt;
 		start_dac1(s);
 	}
+        remove_wait_queue(&s->dma_dac1.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1789,7 +1840,7 @@
 		return -EINVAL;
 	if ((ret = prog_dmabuf_dac1(s)) != 0)
 		return ret;
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << s->dma_dac1.buforder))
@@ -1991,6 +2042,7 @@
 static int es1370_open_dac(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1370_state *s = devs;
 	unsigned long flags;
 
@@ -2014,8 +2066,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2047,8 +2103,8 @@
 	stop_dac1(s);
 	dealloc_dmabuf(&s->dma_dac1);
 	s->open_mode &= ~FMODE_DAC;
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2097,6 +2153,8 @@
 		cnt = MIDIINBUF - ptr;
 		if (s->midi.icnt < cnt)
 			cnt = s->midi.icnt;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2106,7 +2164,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2159,8 +2216,10 @@
 		cnt = MIDIOUTBUF - ptr;
 		if (s->midi.ocnt + cnt > MIDIOUTBUF)
 			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
+		if (cnt <= 0) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			es1370_handle_midi(s);
+		}
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2170,7 +2229,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2228,6 +2286,7 @@
 static int es1370_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1370_state *s = devs;
 	unsigned long flags;
 
@@ -2244,8 +2303,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2284,9 +2347,9 @@
 	VALIDATE_STATE(s);
 
 	if (file->f_mode & FMODE_WRITE) {
-		__set_current_state(TASK_INTERRUPTIBLE);
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			spin_lock_irqsave(&s->lock, flags);
 			count = s->midi.ocnt;
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -2314,8 +2377,8 @@
 		outl(s->ctrl, s->io+ES1370_REG_CONTROL);
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2389,7 +2452,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.29 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
 		if (!RSRCISIOREGION(pcidev, 0))
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.3.24/linux/drivers/sound/es1371.c	Fri Sep 10 23:57:35 1999
+++ linux/drivers/sound/es1371.c	Sat Oct 30 09:45:36 1999
@@ -86,7 +86,14 @@
  *                     replaced current->state = x with set_current_state(x)
  *    03.09.99   0.18  change read semantics for MIDI to match
  *                     OSS more closely; remove possible wakeup race
- *
+ *    21.10.99   0.19  Round sampling rates, requested by
+ *                     Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp>
+ *    27.10.99   0.20  Added SigmaTel 3D enhancement string
+ *                     Codec ID printing changes
+ *    28.10.99   0.21  More waitqueue races fixed
+ *                     Joe Cotellese <joec@ensoniq.com>
+ *                     Changed PCI detection routine so we can more easily
+ *                     detect ES137x chip and derivatives.
  */
 
 /*****************************************************************************/
@@ -116,16 +123,31 @@
 
 #undef OSS_DOCUMENTED_MIXER_SEMANTICS
 #define ES1371_DEBUG
+#define DBG(x) {}
+/*#define DBG(x) {x}*/
 
 /* --------------------------------------------------------------------- */
 
 #ifndef PCI_VENDOR_ID_ENSONIQ
 #define PCI_VENDOR_ID_ENSONIQ        0x1274    
 #endif
+
+#ifndef PCI_VENDOR_ID_ECTIVA
+#define PCI_VENDOR_ID_ECTIVA         0x1102
+#endif
+
 #ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
 #define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
 #endif
 
+#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
+#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
+#endif
+
+#ifndef PCI_DEVICE_ID_ECTIVA_EV1938
+#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938
+#endif
+
 /* ES1371 chip ID */
 /* This is a little confusing because all ES1371 compatible chips have the
    same DEVICE_ID, the only thing differentiating them is the REV_ID field.
@@ -135,8 +157,9 @@
 #define ES1371REV_ES1373_A  0x04
 #define ES1371REV_ES1373_B  0x06
 #define ES1371REV_CT5880_A  0x07
+#define CT5880REV_CT5880_C  0x02
 #define ES1371REV_ES1371_B  0x09
-
+#define EV1938REV_EV1938_A  0x00
 
 #define ES1371_MAGIC  ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371)
 
@@ -144,7 +167,7 @@
 #define JOY_EXTENT                8
 
 #define ES1371_REG_CONTROL        0x00
-#define ES1371_REG_STATUS         0x04
+#define ES1371_REG_STATUS         0x04 /* on the 5880 it is control/status */
 #define ES1371_REG_UART_DATA      0x08
 #define ES1371_REG_UART_STATUS    0x09
 #define ES1371_REG_UART_CONTROL   0x09
@@ -212,6 +235,7 @@
 
 
 #define STAT_INTR       0x80000000  /* wired or of all interrupt bits */
+#define CSTAT_5880_AC97_RST 0x20000000 /* CT5880 Reset bit */
 #define STAT_EN_SPDIF   0x00040000  /* enable S/PDIF circuitry */
 #define STAT_TS_SPDIF   0x00020000  /* test S/PDIF circuitry */
 #define STAT_TESTMODE   0x00010000  /* test ASIC */
@@ -370,7 +394,13 @@
 	"NVidea 3D Stereo Enhancement",
 	"Philips Incredible Sound",
 	"Texas Instruments 3D Stereo Enhancement",
-	"VLSI Technology 3D Stereo Enhancement"
+	"VLSI Technology 3D Stereo Enhancement",
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"SigmaTel SS3D"
 };
 
 /* --------------------------------------------------------------------- */
@@ -391,8 +421,12 @@
 	/* hardware resources */
 	unsigned long io; /* long for SPARC */
 	unsigned int irq;
+
+	/* PCI ID's */
+	u16 vendor;
+	u16 device;
         u8 rev; /* the chip revision */
-        
+
 #ifdef ES1371_DEBUG
         /* debug /proc entry */
 	struct proc_dir_entry *ps;
@@ -591,8 +625,8 @@
 		rate = 48000;
 	if (rate < 4000)
 		rate = 4000;
-        freq = (rate << 15) / 3000;
-	s->dac1rate = (freq * 3000) >> 15;
+        freq = ((rate << 15) + 1500) / 3000;
+	s->dac1rate = (freq * 3000 + 16384) >> 15;
 	spin_lock_irqsave(&s->lock, flags);
 	r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)) | SRC_DDAC1;
 	outl(r, s->io + ES1371_REG_SRCONV);
@@ -614,9 +648,8 @@
 		rate = 48000;
 	if (rate < 4000)
 		rate = 4000;
-        freq = (rate << 15) / 3000;
-	s->dac2rate = (freq * 3000) >> 15;
-        printk (KERN_DEBUG "dac2 freq: %d\n", freq);
+        freq = ((rate << 15) + 1500) / 3000;
+	s->dac2rate = (freq * 3000 + 16384) >> 15;
 	spin_lock_irqsave(&s->lock, flags);
 	r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)) | SRC_DDAC2;
 	outl(r, s->io + ES1371_REG_SRCONV);
@@ -1612,10 +1645,9 @@
 	
 	if (s->dma_dac1.mapped || !s->dma_dac1.ready)
 		return 0;
-
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac1.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac1.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1631,7 +1663,7 @@
 		tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate;
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
 		if (!schedule_timeout(tmo + 1))
-			printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");
+			DBG(printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac1.wait, &wait);
         set_current_state(TASK_RUNNING);
@@ -1648,10 +1680,9 @@
 
 	if (s->dma_dac2.mapped || !s->dma_dac2.ready)
 		return 0;
-
-        __set_current_state(TASK_UNINTERRUPTIBLE);
         add_wait_queue(&s->dma_dac2.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_UNINTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac2.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1667,7 +1698,7 @@
 		tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate;
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
 		if (!schedule_timeout(tmo + 1))
-			printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");
+			DBG(printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac2.wait, &wait);
         set_current_state(TASK_RUNNING);
@@ -1681,6 +1712,7 @@
 static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1696,26 +1728,38 @@
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
 	ret = 0;
+	add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		swptr = s->dma_adc.swptr;
 		cnt = s->dma_adc.dmasize-swptr;
 		if (s->dma_adc.count < cnt)
 			cnt = s->dma_adc.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_adc(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_adc.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_adc.swptr = swptr;
@@ -1726,12 +1770,15 @@
 		ret += cnt;
 		start_adc(s);
 	}
+	remove_wait_queue(&s->dma_adc.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
 static ssize_t es1371_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1747,6 +1794,7 @@
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
 	ret = 0;
+	add_wait_queue(&s->dma_dac2.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac2.count < 0) {
@@ -1757,20 +1805,31 @@
 		cnt = s->dma_dac2.dmasize-swptr;
 		if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
 			cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac2(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac2.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac2.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac2.swptr = swptr;
@@ -1782,6 +1841,8 @@
 		ret += cnt;
 		start_dac2(s);
 	}
+	remove_wait_queue(&s->dma_dac2.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1833,7 +1894,7 @@
 		db = &s->dma_adc;
 	} else 
 		return -EINVAL;
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
@@ -1894,7 +1955,6 @@
 			if (file->f_mode & FMODE_WRITE) {
 				stop_dac2(s);
 				s->dma_dac2.ready = 0;
-                                printk (KERN_DEBUG "es137x: setting DAC2 rate: %d\n", val);
 				set_dac2_rate(s, val);
 			}
 		}
@@ -2152,6 +2212,7 @@
 static int es1371_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1371_state *s = devs;
 	unsigned long flags;
 
@@ -2168,8 +2229,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2251,6 +2316,7 @@
 static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret = 0;
 	unsigned long flags;
 	unsigned swptr;
@@ -2265,6 +2331,7 @@
 		return ret;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
+	add_wait_queue(&s->dma_dac1.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac1.count < 0) {
@@ -2275,20 +2342,31 @@
 		cnt = s->dma_dac1.dmasize-swptr;
 		if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
 			cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac1(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac1.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac1.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac1.swptr = swptr;
@@ -2300,6 +2378,8 @@
 		ret += cnt;
 		start_dac1(s);
 	}
+	remove_wait_queue(&s->dma_dac1.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -2335,7 +2415,7 @@
 		return -EINVAL;
 	if ((ret = prog_dmabuf_dac1(s)) != 0)
 		return ret;
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << s->dma_dac1.buforder))
@@ -2528,6 +2608,7 @@
 static int es1371_open_dac(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1371_state *s = devs;
 	unsigned long flags;
 
@@ -2551,8 +2632,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2633,6 +2718,8 @@
 		cnt = MIDIINBUF - ptr;
 		if (s->midi.icnt < cnt)
 			cnt = s->midi.icnt;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2642,7 +2729,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2695,8 +2781,10 @@
 		cnt = MIDIOUTBUF - ptr;
 		if (s->midi.ocnt + cnt > MIDIOUTBUF)
 			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
+		if (cnt <= 0) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			es1371_handle_midi(s);
+		}
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2706,7 +2794,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2764,6 +2851,7 @@
 static int es1371_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1371_state *s = devs;
 	unsigned long flags;
 
@@ -2780,8 +2868,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2819,9 +2911,9 @@
 
 	VALIDATE_STATE(s);
 	if (file->f_mode & FMODE_WRITE) {
-		__set_current_state(TASK_INTERRUPTIBLE);
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			spin_lock_irqsave(&s->lock, flags);
 			count = s->midi.ocnt;
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -2952,162 +3044,212 @@
 				 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
 
+static int __init probe_chip(struct pci_dev *pcidev, int index)
+{
+	struct es1371_state *s;
+	mm_segment_t fs;
+	int i, val, val2;
+	unsigned char id[4];
+	unsigned long tmo;
+	signed long tmo2;
+	unsigned int cssr;
+
+	if (!RSRCISIOREGION(pcidev, 0))
+		return -1;
+	if (pcidev->irq == 0) 
+		return -1;
+	if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
+		printk(KERN_WARNING "es1371: out of memory\n");
+		return -1;
+	}
+	memset(s, 0, sizeof(struct es1371_state));
+	init_waitqueue_head(&s->dma_adc.wait);
+	init_waitqueue_head(&s->dma_dac1.wait);
+	init_waitqueue_head(&s->dma_dac2.wait);
+	init_waitqueue_head(&s->open_wait);
+	init_waitqueue_head(&s->midi.iwait);
+	init_waitqueue_head(&s->midi.owait);
+	init_MUTEX(&s->open_sem);
+	spin_lock_init(&s->lock);
+	s->magic = ES1371_MAGIC;
+	s->io = RSRCADDRESS(pcidev, 0);
+	s->irq = pcidev->irq;
+	s->vendor = pcidev->vendor;
+	s->device = pcidev->device;
+	pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+	printk(KERN_INFO "es1371: found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n",
+	       s->vendor, s->device, s->rev);
+	if (check_region(s->io, ES1371_EXTENT)) {
+		printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
+		goto err_region;
+	}
+	request_region(s->io, ES1371_EXTENT, "es1371");
+	if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
+		printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
+		goto err_irq;
+	}
+	printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
+	       KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
+	/* register devices */
+	if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
+		goto err_dev1;
+	if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
+		goto err_dev2;
+	if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
+		goto err_dev3;
+	if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
+		goto err_dev4;
+#ifdef ES1371_DEBUG
+	/* intialize the debug proc device */
+	s->ps = create_proc_entry("es1371", S_IFREG | S_IRUGO, NULL);
+	if (s->ps)
+		s->ps->read_proc = proc_es1371_dump;
+#endif /* ES1371_DEBUG */
+	
+	/* initialize codec registers */
+	s->ctrl = 0;
+	if ((joystick[index] & ~0x18) == 0x200) {
+		if (check_region(joystick[index], JOY_EXTENT))
+			printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
+		else {
+			s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+		}
+	}
+	s->sctrl = 0;
+	cssr = 0;
+	/* check to see if s/pdif mode is being requested */
+	if (spdif[index]) {
+		if (s->rev >= 4) {
+			printk(KERN_INFO "es1371: enabling S/PDIF output\n");
+			cssr |= STAT_EN_SPDIF;
+			s->ctrl |= CTRL_SPDIFEN_B;
+		} else {
+			printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
+		}
+	}
+	/* initialize the chips */
+	outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+	outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
+	outl(0, s->io+ES1371_REG_LEGACY);
+	pci_set_master(pcidev);  /* enable bus mastering */
+	/* if we are a 5880 turn on the AC97 */
+	if (s->vendor == PCI_VENDOR_ID_ENSONIQ &&
+	    s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 &&
+	    s->rev == CT5880REV_CT5880_C) {
+		cssr |= CSTAT_5880_AC97_RST;
+		outl(cssr, s->io+ES1371_REG_STATUS);
+		/* need to delay around 20ms(bleech) to give
+		   some CODECs enough time to wakeup */
+		tmo = jiffies + (HZ / 50) + 1;
+		for (;;) {
+			tmo2 = tmo - jiffies;
+			if (tmo2 <= 0)
+				break;
+			schedule_timeout(tmo2);
+		}
+	}
+	/* AC97 warm reset to start the bitclk */
+	outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
+	udelay(2);
+	outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+	/* init the sample rate converter */
+	src_init(s);
+	/* codec init */
+	wrcodec(s, AC97_RESET, 0); /* reset codec */
+	s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
+	val = rdcodec(s, AC97_VENDOR_ID1);
+	val2 = rdcodec(s, AC97_VENDOR_ID2);
+	id[0] = val >> 8;
+	id[1] = val;
+	id[2] = val2 >> 8;
+	id[3] = 0;
+	if (id[0] <= ' ' || id[0] > 0x7f)
+		id[0] = ' ';
+	if (id[1] <= ' ' || id[1] > 0x7f)
+		id[1] = ' ';
+	if (id[2] <= ' ' || id[2] > 0x7f)
+		id[2] = ' ';
+	printk(KERN_INFO "es1371: codec vendor %s (0x%04x%02x) revision %d (0x%02x)\n", 
+	       id, val & 0xffff, (val2 >> 8) & 0xff, val2 & 0xff, val2 & 0xff);
+	printk(KERN_INFO "es1371: codec features");
+	if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
+		printk(" dedicated MIC PCM in");
+	if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
+		printk(" Modem Line Codec");
+	if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
+		printk(" Bass & Treble");
+	if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
+		printk(" Simulated Stereo");
+	if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
+		printk(" Headphone out");
+	if (s->mix.codec_id & CODEC_ID_LOUDNESS)
+		printk(" Loudness");
+	if (s->mix.codec_id & CODEC_ID_18BITDAC)
+		printk(" 18bit DAC");
+	if (s->mix.codec_id & CODEC_ID_20BITDAC)
+		printk(" 20bit DAC");
+	if (s->mix.codec_id & CODEC_ID_18BITADC)
+		printk(" 18bit ADC");
+	if (s->mix.codec_id & CODEC_ID_20BITADC)
+		printk(" 20bit ADC");
+	printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
+	val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
+	printk(KERN_INFO "es1371: stereo enhancement: %s\n", 
+	       (val <= 26 && stereo_enhancement[val]) ? stereo_enhancement[val] : "unknown");
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	val = SOUND_MASK_LINE;
+	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+		val = initvol[i].vol;
+		mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+	}
+	set_fs(fs);
+	/* turn on S/PDIF output driver if requested */
+	outl(cssr, s->io+ES1371_REG_STATUS);
+	/* queue it for later freeing */
+	s->next = devs;
+	devs = s;
+       	return 0;
+
+ err_dev4:
+	unregister_sound_dsp(s->dev_dac);
+ err_dev3:
+	unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+	unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+	printk(KERN_ERR "es1371: cannot register misc device\n");
+	free_irq(s->irq, s);
+ err_irq:
+	release_region(s->io, ES1371_EXTENT);
+ err_region:
+	kfree_s(s, sizeof(struct es1371_state));
+	return -1;
+}
+
 
 static int __init init_es1371(void)
 {
-	struct es1371_state *s;
 	struct pci_dev *pcidev = NULL;
-	mm_segment_t fs;
-	int i, val, val2, index = 0;
-	unsigned cssr;
+	int index = 0;
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.17 time " __TIME__ " " __DATE__ "\n");
-	while (index < NR_DEVICE && 
-	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
-		if (!RSRCISIOREGION(pcidev, 0))
-			continue;
-		if (pcidev->irq == 0) 
-			continue;
-		if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
-			printk(KERN_WARNING "es1371: out of memory\n");
+	printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n");
+	while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))) {
+		if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
+			if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
+			    pcidev->device != PCI_DEVICE_ID_ENSONIQ_CT5880)
+				continue;
+		} else if (pcidev->vendor == PCI_VENDOR_ID_ECTIVA) {
+			if (pcidev->device != PCI_DEVICE_ID_ECTIVA_EV1938)
+				continue;
+		} else
 			continue;
-		}
-		memset(s, 0, sizeof(struct es1371_state));
-		init_waitqueue_head(&s->dma_adc.wait);
-		init_waitqueue_head(&s->dma_dac1.wait);
-		init_waitqueue_head(&s->dma_dac2.wait);
-		init_waitqueue_head(&s->open_wait);
-		init_waitqueue_head(&s->midi.iwait);
-		init_waitqueue_head(&s->midi.owait);
-		init_MUTEX(&s->open_sem);
-		spin_lock_init(&s->lock);
-		s->magic = ES1371_MAGIC;
-		s->io = RSRCADDRESS(pcidev, 0);
-		s->irq = pcidev->irq;
-		pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
-		if (check_region(s->io, ES1371_EXTENT)) {
-			printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
-			goto err_region;
-		}
-		request_region(s->io, ES1371_EXTENT, "es1371");
-		if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
-			printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
-			goto err_irq;
-		}
-		printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
-		       KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
-		/* register devices */
-		if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
-			goto err_dev1;
-		if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
-			goto err_dev2;
-		if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
-			goto err_dev3;
-		if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
-			goto err_dev4;
-#ifdef ES1371_DEBUG
-                /* intialize the debug proc device */
-                s->ps = create_proc_entry("es1371", S_IFREG | S_IRUGO, NULL);
-                if (s->ps)
-                        s->ps->read_proc = proc_es1371_dump;
-#endif /* ES1371_DEBUG */
-
-		/* initialize codec registers */
-		s->ctrl = 0;
-		if ((joystick[index] & ~0x18) == 0x200) {
-			if (check_region(joystick[index], JOY_EXTENT))
-				printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
-			else {
-				s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
-			}
-		}
-		s->sctrl = 0;
-		cssr = 0;
-		/* check to see if s/pdif mode is being requested */
-		if (spdif[index]) {
-			if (s->rev >= 4) {
-				printk(KERN_INFO "es1371: enabling S/PDIF output\n");
-				cssr |= STAT_EN_SPDIF;
-				s->ctrl |= CTRL_SPDIFEN_B;
-			} else {
-				printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
-			}
-		}
-		/* initialize the chips */
-		outl(s->ctrl, s->io+ES1371_REG_CONTROL);
-		outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
-		outl(0, s->io+ES1371_REG_LEGACY);
-		pci_set_master(pcidev);  /* enable bus mastering */
-		/* AC97 warm reset to start the bitclk */
-		outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
-		udelay(2);
-		outl(s->ctrl, s->io+ES1371_REG_CONTROL);
-		/* init the sample rate converter */
-                src_init(s);
-		/* codec init */
-		wrcodec(s, AC97_RESET, 0); /* reset codec */
-		s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
-		val = rdcodec(s, AC97_VENDOR_ID1);
-		val2 = rdcodec(s, AC97_VENDOR_ID2);
-		printk(KERN_INFO "es1371: codec vendor %c%c%c revision %d\n", 
-		       (val >> 8) & 0xff, val & 0xff, (val2 >> 8) & 0xff, val2 & 0xff);
-		printk(KERN_INFO "es1371: codec features");
-		if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
-			printk(" dedicated MIC PCM in");
-		if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
-			printk(" Modem Line Codec");
-		if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
-			printk(" Bass & Treble");
-		if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
-			printk(" Simulated Stereo");
-		if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
-			printk(" Headphone out");
-		if (s->mix.codec_id & CODEC_ID_LOUDNESS)
-			printk(" Loudness");
-		if (s->mix.codec_id & CODEC_ID_18BITDAC)
-			printk(" 18bit DAC");
-		if (s->mix.codec_id & CODEC_ID_20BITDAC)
-			printk(" 20bit DAC");
-		if (s->mix.codec_id & CODEC_ID_18BITADC)
-			printk(" 18bit ADC");
-		if (s->mix.codec_id & CODEC_ID_20BITADC)
-			printk(" 20bit ADC");
-		printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
-		val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
-		printk(KERN_INFO "es1371: stereo enhancement: %s\n", (val <= 20) ? stereo_enhancement[val] : "unknown");
-
-		fs = get_fs();
-		set_fs(KERNEL_DS);
-		val = SOUND_MASK_LINE;
-		mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-		for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
-			val = initvol[i].vol;
-			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
-		}
-		set_fs(fs);
-		/* turn on S/PDIF output driver if requested */
-		outl(cssr, s->io+ES1371_REG_STATUS);
-		/* queue it for later freeing */
-		s->next = devs;
-		devs = s;
-		index++;
-		continue;
-
-	err_dev4:
-		unregister_sound_dsp(s->dev_dac);
-	err_dev3:
-		unregister_sound_mixer(s->dev_mixer);
-	err_dev2:
-		unregister_sound_dsp(s->dev_audio);
-	err_dev1:
-		printk(KERN_ERR "es1371: cannot register misc device\n");
-		free_irq(s->irq, s);
-	err_irq:
-		release_region(s->io, ES1371_EXTENT);
-	err_region:
-		kfree_s(s, sizeof(struct es1371_state));
+		if (!probe_chip(pcidev, index))
+			index++;
 	}
 	if (!devs)
 		return -ENODEV;
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- v2.3.24/linux/drivers/sound/esssolo1.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/sound/esssolo1.c	Sat Oct 30 09:45:36 1999
@@ -60,6 +60,7 @@
  *                     OSS more closely; remove possible wakeup race
  *    07.10.99   0.9   Fix initialization; complain if sequencer writes time out
  *                     Revised resource grabbing for the FM synthesizer
+ *    28.10.99   0.10  More waitqueue races fixed
  *
  */
 
@@ -101,7 +102,7 @@
 
 #define SOLO1_MAGIC  ((PCI_VENDOR_ID_ESS<<16)|PCI_DEVICE_ID_ESS_SOLO1)
 
-#define DDMABASE_OFFSET           0x10    /* chip bug workaround kludge */
+#define DDMABASE_OFFSET           0    /* chip bug workaround kludge */
 #define DDMABASE_EXTENT           16
 
 #define IOBASE_EXTENT             16
@@ -939,9 +940,9 @@
 	
 	if (s->dma_dac.mapped)
 		return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac.wait, &wait);
         for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -974,6 +975,7 @@
 static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct solo1_state *s = (struct solo1_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -989,12 +991,15 @@
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
 	ret = 0;
+	add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		swptr = s->dma_adc.swptr;
 		cnt = s->dma_adc.dmasize-swptr;
 		if (s->dma_adc.count < cnt)
 			cnt = s->dma_adc.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1015,9 +1020,12 @@
 #endif
 			if (inb(s->ddmabase+15) & 1)
 				printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_adc.wait);
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
 #ifdef DEBUGREC
 			printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"
 			       KERN_DEBUG "solo1_read: regs: B1: 0x%02x  B2: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n"
@@ -1027,12 +1035,18 @@
 			       read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
 			       inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
 #endif
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_adc.swptr = swptr;
@@ -1047,12 +1061,15 @@
 		       read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc));
 #endif
 	}
+	remove_wait_queue(&s->dma_adc.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
 static ssize_t solo1_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct solo1_state *s = (struct solo1_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1076,6 +1093,7 @@
 	       read_mixer(s, 0x78), read_mixer(s, 0x7a), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc));
 #endif
 	ret = 0;
+	add_wait_queue(&s->dma_dac.wait, &wait);	
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac.count < 0) {
@@ -1086,20 +1104,31 @@
 		cnt = s->dma_dac.dmasize-swptr;
 		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
 			cnt = s->dma_dac.dmasize - s->dma_dac.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac.swptr = swptr;
@@ -1111,6 +1140,8 @@
 		ret += cnt;
 		start_dac(s);
 	}
+	remove_wait_queue(&s->dma_dac.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1168,7 +1199,7 @@
 		db = &s->dma_adc;
 	} else 
 		return -EINVAL;
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
@@ -1473,8 +1504,8 @@
 		dealloc_dmabuf(&s->dma_adc);
 	}
 	s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -1482,6 +1513,7 @@
 static int solo1_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct solo1_state *s = devs;
 
 	while (s && ((s->dev_audio ^ minor) & ~0xf))
@@ -1497,8 +1529,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -1630,6 +1666,8 @@
 		cnt = MIDIINBUF - ptr;
 		if (s->midi.icnt < cnt)
 			cnt = s->midi.icnt;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1639,7 +1677,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -1692,8 +1729,10 @@
 		cnt = MIDIOUTBUF - ptr;
 		if (s->midi.ocnt + cnt > MIDIOUTBUF)
 			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
+		if (cnt <= 0) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			solo1_handle_midi(s);
+		}
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1703,7 +1742,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -1761,6 +1799,7 @@
 static int solo1_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct solo1_state *s = devs;
 	unsigned long flags;
 
@@ -1777,8 +1816,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -1822,9 +1865,9 @@
 	VALIDATE_STATE(s);
 
 	if (file->f_mode & FMODE_WRITE) {
-		__set_current_state(TASK_INTERRUPTIBLE);
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			spin_lock_irqsave(&s->lock, flags);
 			count = s->midi.ocnt;
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -1852,8 +1895,8 @@
 		del_timer(&s->midi.timer);		
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -1978,6 +2021,7 @@
 static int solo1_dmfm_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct solo1_state *s = devs;
 
 	while (s && s->dev_dmfm != minor)
@@ -1993,8 +2037,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2033,8 +2081,8 @@
 		outb(0, s->sbbase+3);
 	}
 	release_region(s->sbbase, FMSYNTH_EXTENT);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2094,7 +2142,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "solo1: version v0.7 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "solo1: version v0.10 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
 		if (!RSRCISIOREGION(pcidev, 0) ||
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c
--- v2.3.24/linux/drivers/sound/maestro.c	Fri Oct 22 13:21:50 1999
+++ linux/drivers/sound/maestro.c	Mon Nov  1 10:31:28 1999
@@ -2339,7 +2339,7 @@
 		db = &s->dma_adc;
 	} else 
 		return -EINVAL;
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.3.24/linux/drivers/sound/sonicvibes.c	Fri Sep 10 23:57:35 1999
+++ linux/drivers/sound/sonicvibes.c	Sat Oct 30 09:45:36 1999
@@ -81,6 +81,7 @@
  *                     replaced current->state = x with set_current_state(x)
  *    03.09.99   0.21  change read semantics for MIDI to match
  *                     OSS more closely; remove possible wakeup race
+ *    28.10.99   0.22  More waitqueue races fixed
  *
  */
 
@@ -1267,9 +1268,9 @@
 
 	if (s->dma_dac.mapped || !s->dma_dac.ready)
 		return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1299,6 +1300,7 @@
 static ssize_t sv_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct sv_state *s = (struct sv_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1315,24 +1317,30 @@
 		return -EFAULT;
 	ret = 0;
 #if 0
-   spin_lock_irqsave(&s->lock, flags);
-   sv_update_ptr(s);
-   spin_unlock_irqrestore(&s->lock, flags);
+	spin_lock_irqsave(&s->lock, flags);
+	sv_update_ptr(s);
+	spin_unlock_irqrestore(&s->lock, flags);
 #endif
+        add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		swptr = s->dma_adc.swptr;
 		cnt = s->dma_adc.dmasize-swptr;
 		if (s->dma_adc.count < cnt)
 			cnt = s->dma_adc.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_adc(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			if (!schedule_timeout(HZ)) {
 				printk(KERN_DEBUG "sv: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
 				       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, 
 				       s->dma_adc.hwptr, s->dma_adc.swptr);
@@ -1345,12 +1353,18 @@
 				s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
 				spin_unlock_irqrestore(&s->lock, flags);
 			}
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_adc.swptr = swptr;
@@ -1361,12 +1375,15 @@
 		ret += cnt;
 		start_adc(s);
 	}
+        remove_wait_queue(&s->dma_adc.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
 static ssize_t sv_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct sv_state *s = (struct sv_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1383,10 +1400,11 @@
 		return -EFAULT;
 	ret = 0;
 #if 0
-   spin_lock_irqsave(&s->lock, flags);
-   sv_update_ptr(s);
-   spin_unlock_irqrestore(&s->lock, flags);
+	spin_lock_irqsave(&s->lock, flags);
+	sv_update_ptr(s);
+	spin_unlock_irqrestore(&s->lock, flags);
 #endif
+        add_wait_queue(&s->dma_dac.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac.count < 0) {
@@ -1397,14 +1415,19 @@
 		cnt = s->dma_dac.dmasize-swptr;
 		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
 			cnt = s->dma_dac.dmasize - s->dma_dac.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			if (!schedule_timeout(HZ)) {
 				printk(KERN_DEBUG "sv: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
 				       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, 
 				       s->dma_dac.hwptr, s->dma_dac.swptr);
@@ -1417,12 +1440,18 @@
 				s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
 				spin_unlock_irqrestore(&s->lock, flags);
 			}
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac.swptr = swptr;
@@ -1434,6 +1463,8 @@
 		ret += cnt;
 		start_dac(s);
 	}
+        remove_wait_queue(&s->dma_dac.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1485,7 +1516,7 @@
 		db = &s->dma_adc;
 	} else 
 		return -EINVAL;
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
@@ -1798,6 +1829,7 @@
 static int sv_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct sv_state *s = devs;
 	unsigned char fmtm = ~0, fmts = 0;
 
@@ -1814,8 +1846,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -1858,8 +1894,8 @@
 		dealloc_dmabuf(&s->dma_adc);
 	}
 	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -1908,6 +1944,8 @@
 		cnt = MIDIINBUF - ptr;
 		if (s->midi.icnt < cnt)
 			cnt = s->midi.icnt;
+		if (cnt <= 0)
+                      __set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1917,7 +1955,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                      __set_current_state(TASK_INTERRUPTIBLE);
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -1970,8 +2007,10 @@
 		cnt = MIDIOUTBUF - ptr;
 		if (s->midi.ocnt + cnt > MIDIOUTBUF)
 			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
+		if (cnt <= 0) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			sv_handle_midi(s);
+		}
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1981,7 +2020,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2039,6 +2077,7 @@
 static int sv_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct sv_state *s = devs;
 	unsigned long flags;
 
@@ -2055,8 +2094,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2103,9 +2146,9 @@
 	VALIDATE_STATE(s);
 
 	if (file->f_mode & FMODE_WRITE) {
-		__set_current_state(TASK_INTERRUPTIBLE);
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			spin_lock_irqsave(&s->lock, flags);
 			count = s->midi.ocnt;
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -2133,8 +2176,8 @@
 		del_timer(&s->midi.timer);		
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2259,6 +2302,7 @@
 static int sv_dmfm_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct sv_state *s = devs;
 
 	while (s && s->dev_dmfm != minor)
@@ -2274,8 +2318,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2307,8 +2355,8 @@
 		outb(regb, s->iosynth+2);
 		outb(0, s->iosynth+3);
 	}
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2385,7 +2433,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.20 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.22 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.3.24/linux/drivers/sound/soundcard.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/soundcard.c	Thu Oct 28 14:34:46 1999
@@ -297,14 +297,6 @@
         return len;
 }
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_root_sound = {
-        PROC_SOUND, 5, "sound",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, NULL, sound_proc_get_info
-};
-#endif
-
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
@@ -756,7 +748,7 @@
 /*		printk("Sound: mmap() called twice for the same DMA buffer\n");*/
 		return -EIO;
 	}
-	if (vma->vm_offset != 0)
+	if (vma->vm_pgoff != 0)
 	{
 /*		printk("Sound: mmap() offset must be 0.\n");*/
 		return -EINVAL;
@@ -855,7 +847,7 @@
 	}
 #endif
 #ifdef CONFIG_PROC_FS
-	if (proc_register(&proc_root, &proc_root_sound))
+	if (!create_proc_info_entry("sound", 0, NULL, sound_proc_get_info))
 		printk(KERN_ERR "sound: registering /proc/sound failed\n");
 #endif		
 }
@@ -935,10 +927,7 @@
 	{
 		return;
 	}
-#ifdef CONFIG_PROC_FS	
-        if (proc_unregister(&proc_root, PROC_SOUND))
-		printk(KERN_ERR "sound: unregistering /proc/sound failed\n");
-#endif		
+        remove_proc_entry("sound", NULL);
 	if (chrdev_registered)
 		destroy_special_devices();
 
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.24/linux/drivers/usb/acm.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/usb/acm.c	Thu Oct 28 12:54:35 1999
@@ -73,6 +73,8 @@
 #define CTRL_STAT_DTR	1
 #define CTRL_STAT_RTS	2
 
+static struct usb_driver acm_driver;
+
 static int acm_refcount;
 
 static struct tty_driver acm_tty_driver;
@@ -83,6 +85,7 @@
 
 struct acm_state {
 	struct usb_device *dev;				//the coresponding usb device
+	int cfgnum;					//configuration number on this device
 	struct tty_struct *tty;				//the coresponding tty
 	char present;					//a device for this struct was detected => this tty is used
 	char active;					//someone has this acm's device open 
@@ -194,7 +197,7 @@
 	info("ACM_READ_IRQ: state %d, %d bytes\n", state, count);
 	if (state) {
 		printk( "acm_read_irq: strange state received: %x\n", state );
-		return 1;
+		return 0;
 	}
 	
 	if (!ACM_READY)
@@ -204,7 +207,7 @@
 		tty_insert_flip_char(tty,data[i],0);
   	tty_flip_buffer_push(tty);
 
-	return 1; /* continue transfer */
+	return 0; /* Never return 1 from this routine. It makes uhci do bad things. */
 }
 
 static int acm_write_irq(int state, void *__buffer, int count, void *dev_id)
@@ -382,7 +385,7 @@
 	return -1;
 }
 
-static int acm_probe(struct usb_device *dev)
+static void * acm_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct acm_state *acm;
 	struct usb_interface_descriptor *interface;
@@ -394,7 +397,7 @@
 	
 	if (0>(acmno=get_free_acm())) {
 		info("Too many acm devices connected\n");
-		return -1;
+		return NULL;
 	}
 	acm = &acm_state_table[acmno];
 
@@ -402,10 +405,14 @@
 	if (dev->descriptor.bDeviceClass != 2 ||
 	    dev->descriptor.bDeviceSubClass != 0 ||
             dev->descriptor.bDeviceProtocol != 0)
-		return -1;
+		return NULL;
 
 #define IFCLASS(if) ((if->bInterfaceClass << 24) | (if->bInterfaceSubClass << 16) | (if->bInterfaceProtocol << 8) | (if->bNumEndpoints))
 
+	/* FIXME: should the driver really be doing the configuration
+	 * selecting or should the usbcore?  [different configurations
+	 * can have different bandwidth requirements] -greg */
+
 	/* Now scan all configs for a ACM configuration*/
 	for (cfgnum=0;cfgnum<dev->descriptor.bNumConfigurations;cfgnum++) {
 		/* The first one should be Communications interface? */
@@ -425,7 +432,14 @@
 		    interface->bNumEndpoints != 2)
 			continue;
 
-		/* if ((endpoint->bEndpointAddress & 0x80) == 0x80) */
+		/* make sure both interfaces are available for our use */
+		if (usb_interface_claimed(&dev->config[cfgnum].interface[0]) ||
+		    usb_interface_claimed(&dev->config[cfgnum].interface[1])) {
+			printk("usb-acm: required interface already has a driver\n");
+			continue;
+		}
+
+		endpoint = &interface->endpoint[0];
 		if ((endpoint->bEndpointAddress & 0x80) != 0x80)
 			swapped = 1;
 
@@ -445,7 +459,6 @@
 		usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue);
 
 		acm->dev=dev;
-		dev->private=acm;
 
 		acm->readendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0^swapped].bEndpointAddress;
 		acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp);
@@ -453,7 +466,7 @@
 		acm->reading=0;
 		if (!acm->readbuffer) {
 			printk("ACM: Couldn't allocate readbuffer\n");
-			return -1;
+			return NULL;
 		}
 
 		acm->writeendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1^swapped].bEndpointAddress;
@@ -463,23 +476,29 @@
 		if (!acm->writebuffer) {
 			printk("ACM: Couldn't allocate writebuffer\n");
 			kfree(acm->readbuffer);
-			return -1;
+			return NULL;
 		}
 
 		acm->ctrlendp=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bEndpointAddress;
 		acm->ctrlpipe=usb_rcvctrlpipe(acm->dev,acm->ctrlendp);
 		acm->ctrlinterval=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bInterval;
 
+		acm->cfgnum = cfgnum;
 		acm->present=1;				
 		MOD_INC_USE_COUNT;
-		return 0;
+
+		usb_driver_claim_interface(&acm_driver,
+				&dev->config[cfgnum].interface[0], acm);
+		usb_driver_claim_interface(&acm_driver,
+				&dev->config[cfgnum].interface[1], acm);
+		return acm;
 	}
-	return -1;
+	return NULL;
 }
 
-static void acm_disconnect(struct usb_device *dev)
+static void acm_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct acm_state *acm = (struct acm_state *) dev->private;
+	struct acm_state *acm = ptr;
 
 	info("acm_disconnect\n");
 	
@@ -501,6 +520,12 @@
 	kfree(acm->writebuffer);
 	kfree(acm->readbuffer);
 
+	/* release the interfaces so that other drivers can have at them */
+	usb_driver_release_interface(&acm_driver,
+				&dev->config[acm->cfgnum].interface[0]);
+	usb_driver_release_interface(&acm_driver,
+				&dev->config[acm->cfgnum].interface[1]);
+
 	MOD_DEC_USE_COUNT;
 }
 
@@ -584,7 +609,7 @@
 		acm=&acm_state_table[i];
 		if (acm->present) {
 			printk("disconnecting %d\n",i);
-			acm_disconnect(acm->dev);
+			acm_disconnect(acm->dev, acm);
 		}  
 	}
 	tty_unregister_driver(&acm_tty_driver);
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.3.24/linux/drivers/usb/audio.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/usb/audio.c	Sun Oct 31 15:01:59 1999
@@ -33,6 +33,22 @@
  *              wants to use an Asynch out pipe. usb_audio_state now basically
  *              only contains lists of mixer and wave devices. We can therefore
  *              now have multiple mixer/wave devices per USB device.
+ * 1999-10-31:  Thomas Sailer
+ *              Audio can now be unloaded if it is not in use by any mixer
+ *              or dsp client (formerly you had to disconnect the audio devices
+ *              from the USB port)
+ *              Finally, about three months after ordering, my "Maxxtro SPK222"
+ *              speakers arrived, isn't disdata a great mail order company 8-)
+ *              Parse class specific endpoint descriptor of the audiostreaming
+ *              interfaces and take the endpoint attributes from there.
+ *              Unbelievably, the Philips USB DAC has a sampling rate range
+ *              of over a decade, yet does not support the sampling rate control!
+ *              No wonder it sounds so bad, has very audible sampling rate
+ *              conversion distortion. Don't try to listen to it using
+ *              decent headphones!
+ *              "Let's make things better" -> but please Philips start with your
+ *              own stuff!!!!
+ *
  *
  */
 
@@ -182,6 +198,7 @@
 	unsigned int sratelo;
 	unsigned int sratehi;
 	unsigned char altsetting;
+	unsigned char attributes;
 };
 
 struct dmabuf {
@@ -542,11 +559,24 @@
 	i = u->flags;
         spin_unlock_irqrestore(&as->lock, flags);
 	while (i & (FLG_ID0RUNNING|FLG_ID1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(1);
+		if (signal_pending(current)) {
+			if (i & FLG_ID0RUNNING)
+				usb_kill_isoc(u->dataiso[0]);
+			if (i & FLG_ID1RUNNING)
+				usb_kill_isoc(u->dataiso[1]);
+			if (i & FLG_SYNC0RUNNING)
+				usb_kill_isoc(u->synciso[0]);
+			if (i & FLG_SYNC1RUNNING)
+				usb_kill_isoc(u->synciso[1]);
+			break;
+		}
 		spin_lock_irqsave(&as->lock, flags);
 		i = u->flags;
 		spin_unlock_irqrestore(&as->lock, flags);
 	}
+	set_current_state(TASK_RUNNING);
 	if (u->dataiso[0])
 		usb_free_isoc(u->dataiso[0]);
 	if (u->dataiso[1])
@@ -801,6 +831,7 @@
 		printk(KERN_DEBUG "usbin_completed: killing id\n");
 		usb_kill_isoc(id);
 		printk(KERN_DEBUG "usbin_completed: id killed\n");
+		wake_up(&u->dma.wait);
 	}
 	spin_unlock_irqrestore(&as->lock, flags);
 	return 0;
@@ -873,6 +904,7 @@
 		printk(KERN_DEBUG "usbin_sync_completed: killing id\n");
 		usb_kill_isoc(id);
 		printk(KERN_DEBUG "usbin_sync_completed: id killed\n");
+		wake_up(&u->dma.wait);
 	}
 	spin_unlock_irqrestore(&as->lock, flags);
 	return 0;
@@ -1005,12 +1037,25 @@
         spin_unlock_irqrestore(&as->lock, flags);
 printk(KERN_DEBUG "usb_audio: usbout_stop (2) flags 0x%04x\n", i);
 	while (i & (FLG_ID0RUNNING|FLG_ID1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(1);
+		if (signal_pending(current)) {
+			if (i & FLG_ID0RUNNING)
+				usb_kill_isoc(u->dataiso[0]);
+			if (i & FLG_ID1RUNNING)
+				usb_kill_isoc(u->dataiso[1]);
+			if (i & FLG_SYNC0RUNNING)
+				usb_kill_isoc(u->synciso[0]);
+			if (i & FLG_SYNC1RUNNING)
+				usb_kill_isoc(u->synciso[1]);
+			break;
+		}
 		spin_lock_irqsave(&as->lock, flags);
 		i = u->flags;
 		spin_unlock_irqrestore(&as->lock, flags);
 printk(KERN_DEBUG "usb_audio: usbout_stop (3) flags 0x%04x\n", i);
 	}
+	set_current_state(TASK_RUNNING);
 	if (u->dataiso[0])
 		usb_free_isoc(u->dataiso[0]);
 	if (u->dataiso[1])
@@ -1272,6 +1317,7 @@
 		printk(KERN_DEBUG "usbout_completed: killing id\n");
 		usb_kill_isoc(id);
 		printk(KERN_DEBUG "usbout_completed: id killed\n");
+		wake_up(&u->dma.wait);
 	}
 	spin_unlock_irqrestore(&as->lock, flags);
 	return 0;
@@ -1347,6 +1393,7 @@
 		printk(KERN_DEBUG "usbout_sync_completed: killing id\n");
 		usb_kill_isoc(id);
 		printk(KERN_DEBUG "usbout_sync_completed: id killed\n");
+		wake_up(&u->dma.wait);
 	}
 	spin_unlock_irqrestore(&as->lock, flags);
 	return 0;
@@ -1500,6 +1547,7 @@
 	struct audioformat *fmt;
 	unsigned int fmtnr, ep;
 	unsigned char data[3];
+	int ret;
 
 	if (u->interface < 0 || u->interface >= config->bNumInterfaces)
 		return 0;
@@ -1515,7 +1563,7 @@
 		    alts->endpoint[1].bmAttributes != 0x01 ||
 		    alts->endpoint[1].bSynchAddress != 0 ||
 		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress & 0x7f)) {
-			printk(KERN_ERR "usb_audio: device %d interface %d altsetting %d invalid synch pipe\n",
+			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
 			       dev->devnum, u->interface, fmt->altsetting);
 			return -1;
 		}
@@ -1533,25 +1581,38 @@
 	}
 	if (fmt->sratelo == fmt->sratehi)
 		return 0;
-	data[0] = d->srate;
-	data[1] = d->srate >> 8;
-	data[2] = d->srate >> 16;
 	ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN);
-	if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-			    SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ) < 0) {
-		printk(KERN_ERR "usbaudio: failure to set input sampling frequency device %d endpoint 0x%x to %u\n",
-		       dev->devnum, ep, d->srate);
-		return -1;
+	/* if endpoint has pitch control, enable it */
+	if (fmt->attributes & 0x02) {
+		data[0] = 1;
+		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
+			       ret, dev->devnum, u->interface, ep, d->srate);
+			return -1;
+		}
 	}
-	if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
-			    SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ) < 0) {
-		printk(KERN_ERR "usbaudio: failure to get input sampling frequency device %d endpoint 0x%x\n",
-		       dev->devnum, ep);
-		return -1;
+	/* if endpoint has sampling rate control, set it */
+	if (fmt->attributes & 0x01) {
+		data[0] = d->srate;
+		data[1] = d->srate >> 8;
+		data[2] = d->srate >> 16;
+		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to set input sampling frequency device %d interface %u endpoint 0x%x to %u\n",
+			       ret, dev->devnum, u->interface, ep, d->srate);
+			return -1;
+		}
+		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to get input sampling frequency device %d interface %u endpoint 0x%x\n",
+			       ret, dev->devnum, u->interface, ep);
+			return -1;
+		}
+		printk(KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n",
+		       dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16));
+		d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
 	}
-	printk(KERN_DEBUG "usb_audio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n",
-	       dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16));
-	d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
 	return 0;
 }
 
@@ -1566,6 +1627,7 @@
 	struct audioformat *fmt;
 	unsigned int fmtnr, ep;
 	unsigned char data[3];
+	int ret;
 
 	if (u->interface < 0 || u->interface >= config->bNumInterfaces)
 		return 0;
@@ -1581,7 +1643,7 @@
 		    alts->endpoint[1].bmAttributes != 0x01 ||
 		    alts->endpoint[1].bSynchAddress != 0 ||
 		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress | 0x80)) {
-			printk(KERN_ERR "usb_audio: device %d interface %d altsetting %d invalid synch pipe\n",
+			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
 			       dev->devnum, u->interface, fmt->altsetting);
 			return -1;
 		}
@@ -1599,25 +1661,38 @@
 	}
 	if (fmt->sratelo == fmt->sratehi)
 		return 0;
-	data[0] = d->srate;
-	data[1] = d->srate >> 8;
-	data[2] = d->srate >> 16;
 	ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN);
-	if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-			    SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ) < 0) {
-		printk(KERN_ERR "usbaudio: failure to set output sampling frequency device %d endpoint 0x%x to %u\n",
-		       dev->devnum, ep, d->srate);
-		return -1;
+	/* if endpoint has pitch control, enable it */
+	if (fmt->attributes & 0x02) {
+		data[0] = 1;
+		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
+			       ret, dev->devnum, u->interface, ep, d->srate);
+			return -1;
+		}
 	}
-	if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
-			    SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ) < 0) {
-		printk(KERN_ERR "usbaudio: failure to get output sampling frequency device %d endpoint 0x%x\n",
-		       dev->devnum, ep);
-		return -1;
+	/* if endpoint has sampling rate control, set it */
+	if (fmt->attributes & 0x01) {
+		data[0] = d->srate;
+		data[1] = d->srate >> 8;
+		data[2] = d->srate >> 16;
+		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n",
+			       ret, dev->devnum, u->interface, ep, d->srate);
+			return -1;
+		}
+		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n",
+			       ret, dev->devnum, u->interface, ep);
+			return -1;
+		}
+		printk(KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n",
+		       dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16));
+		d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
 	}
-	printk(KERN_DEBUG "usb_audio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n",
-	       dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16));
-	d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
 	return 0;
 }
 
@@ -1736,7 +1811,7 @@
         return 0;
 
  err:
-        printk(KERN_ERR "usb_audio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
+        printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
                dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector);
 	return -1;
 }
@@ -1775,7 +1850,6 @@
 		kfree(ms);
 	}
 	kfree(s);
-        MOD_DEC_USE_COUNT;
 }
 
 extern inline int prog_dmabuf_in(struct usb_audiodev *as)
@@ -1825,6 +1899,7 @@
 	}
         file->private_data = ms;
 	s->count++;
+	MOD_INC_USE_COUNT;
 	up(&open_sem);
         return 0;
 }
@@ -1836,6 +1911,7 @@
 
 	down(&open_sem);
 	release(s);
+        MOD_DEC_USE_COUNT;
         return 0;
 }
 
@@ -1952,10 +2028,10 @@
         
         if (as->usbout.dma.mapped || !as->usbout.dma.ready)
                 return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&as->usbout.dma.wait, &wait);
         for (;;) {
-                spin_lock_irqsave(&as->lock, flags);
+		__set_current_state(TASK_INTERRUPTIBLE);
+		spin_lock_irqsave(&as->lock, flags);
                 count = as->usbout.dma.count;
                 spin_unlock_irqrestore(&as->lock, flags);
                 if (count <= 0)
@@ -1969,8 +2045,10 @@
                 }
                 tmo = 3 * HZ * count / as->usbout.dma.srate;
 		tmo >>= AFMT_BYTESSHIFT(as->usbout.dma.format);
-                if (!schedule_timeout(tmo + 1))
+                if (!schedule_timeout(tmo + 1)) {
                         printk(KERN_DEBUG "usbaudio: dma timed out??\n");
+			break;
+		}
         }
         remove_wait_queue(&as->usbout.dma.wait, &wait);
         set_current_state(TASK_RUNNING);
@@ -1998,12 +2076,14 @@
                 return ret;
         if (!access_ok(VERIFY_WRITE, buffer, count))
                 return -EFAULT;
-	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue(&as->usbin.dma.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&as->lock, flags);
 		ptr = as->usbin.dma.rdptr;
 		cnt = as->usbin.dma.count;
+		/* set task state early to avoid wakeup races */
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&as->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2060,9 +2140,13 @@
                 return ret;
         if (!access_ok(VERIFY_READ, buffer, count))
                 return -EFAULT;
-	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue(&as->usbout.dma.wait, &wait);
         while (count > 0) {
+#if 0
+		printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%x\n",
+		       count, as->usbout.dma.count, as->usbout.dma.rdptr, as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize,
+		       as->usbout.flags, current->state);
+#endif
                 spin_lock_irqsave(&as->lock, flags);
                 if (as->usbout.dma.count < 0) {
                         as->usbout.dma.count = 0;
@@ -2070,6 +2154,9 @@
                 }
                 ptr = as->usbout.dma.wrptr;
                 cnt = as->usbout.dma.dmasize - as->usbout.dma.count;
+		/* set task state early to avoid wakeup races */
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
                 spin_unlock_irqrestore(&as->lock, flags);
                 if (cnt > count)
                         cnt = count;
@@ -2160,7 +2247,7 @@
                 db = &as->usbin.dma;
         } else
                 return -EINVAL;
-        if (vma->vm_offset != 0)
+        if (vma->vm_pgoff != 0)
                 return -EINVAL;
 	return dmabuf_mmap(db,  vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot);
 }
@@ -2469,6 +2556,7 @@
         file->private_data = as;
         as->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 	s->count++;
+	MOD_INC_USE_COUNT;
         up(&open_sem);
         return 0;
 }
@@ -2498,6 +2586,7 @@
         as->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
 	release(s);
         wake_up(&open_wait);
+        MOD_DEC_USE_COUNT;
         return 0;
 }
 
@@ -2532,14 +2621,16 @@
  *	zero bandwidth (idle) config and one or more live one pers interface.
  */
 
-static int usb_audio_probe(struct usb_device *dev);
-static void usb_audio_disconnect(struct usb_device *dev);
+static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum);
+static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
 
 static struct usb_driver usb_audio_driver = {
 	"audio",
 	usb_audio_probe,
 	usb_audio_disconnect,
-	{ NULL, NULL }
+	/*{ NULL, NULL }, */ LIST_HEAD_INIT(usb_audio_driver.driver_list), 
+	NULL,
+	0
 };
 
 
@@ -2620,7 +2711,7 @@
 	struct usb_interface_descriptor *alts;
 	struct usb_interface *iface;
 	struct audioformat *fp;
-	unsigned char *fmt;
+	unsigned char *fmt, *csep;
 	unsigned int i, j, k, format;
 
 	if (!(as = kmalloc(sizeof(struct usb_audiodev), GFP_KERNEL)))
@@ -2640,44 +2731,50 @@
 			if (alts->bInterfaceClass != USB_CLASS_AUDIO || alts->bInterfaceSubClass != 2)
 				continue;
 			if (alts->bNumEndpoints < 1) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u does not have an endpoint\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", 
 				       dev->devnum, asifin, i);
 				continue;
 			}
 			if ((alts->endpoint[0].bmAttributes & 0x03) != 0x01 ||
 			    !(alts->endpoint[0].bEndpointAddress & 0x80)) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u first endpoint not isochronous in\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous in\n", 
 				       dev->devnum, asifin, i);
 				continue;
 			}
 			fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifin, i);
 			if (!fmt) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
 				       dev->devnum, asifin, i);
 				continue;
 			}
 			if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u format not supported\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", 
 				       dev->devnum, asifin, i);
 				continue;
 			}
 			format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8);
 			fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifin, i);
 			if (!fmt) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
 				       dev->devnum, asifin, i);
 				continue;
 			}
 			if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", 
 				       dev->devnum, asifin, i);
 				continue;
 			}
 			if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", 
 				       dev->devnum, asifin, i, fmt[4], fmt[5]);
 				continue;
 			}
+			csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifin, i);
+			if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", 
+				       dev->devnum, asifin, i);
+				continue;
+			}
 			if (as->numfmtin >= MAXFORMATS)
 				continue;
 			fp = &as->fmtin[as->numfmtin++];
@@ -2697,8 +2794,9 @@
 				if (k < fp->sratelo)
 					fp->sratelo = k;
 			}
-			printk(KERN_INFO "usb_audio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u\n", 
-			       dev->devnum, asifin, i, fp->format, fp->sratelo, fp->sratehi);
+			fp->attributes = csep[3];
+			printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", 
+			       dev->devnum, asifin, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes);
 		}
 	}
 	/* search for output formats */
@@ -2709,44 +2807,50 @@
 			if (alts->bInterfaceClass != USB_CLASS_AUDIO || alts->bInterfaceSubClass != 2)
 				continue;
 			if (alts->bNumEndpoints < 1) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u does not have an endpoint\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", 
 				       dev->devnum, asifout, i);
 				continue;
 			}
 			if ((alts->endpoint[0].bmAttributes & 0x03) != 0x01 ||
 			    (alts->endpoint[0].bEndpointAddress & 0x80)) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u first endpoint not isochronous out\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous out\n", 
 				       dev->devnum, asifout, i);
 				continue;
 			}
 			fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifout, i);
 			if (!fmt) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
 				       dev->devnum, asifout, i);
 				continue;
 			}
 			if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u format not supported\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", 
 				       dev->devnum, asifout, i);
 				continue;
 			}
 			format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8);
 			fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifout, i);
 			if (!fmt) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
 				       dev->devnum, asifout, i);
 				continue;
 			}
 			if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", 
 				       dev->devnum, asifout, i);
 				continue;
 			}
 			if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) {
-				printk(KERN_ERR "usb_audio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", 
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", 
 				       dev->devnum, asifout, i, fmt[4], fmt[5]);
 				continue;
 			}
+			csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifout, i);
+			if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", 
+				       dev->devnum, asifout, i);
+				continue;
+			}
 			if (as->numfmtout >= MAXFORMATS)
 				continue;
 			fp = &as->fmtout[as->numfmtout++];
@@ -2766,8 +2870,9 @@
 				if (k < fp->sratelo)
 					fp->sratelo = k;
 			}
-			printk(KERN_INFO "usb_audio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u\n", 
-			       dev->devnum, asifout, i, fp->format, fp->sratelo, fp->sratehi);
+			fp->attributes = csep[3];
+			printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", 
+			       dev->devnum, asifout, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes);
 		}
 	}
 	if (as->numfmtin == 0 && as->numfmtout == 0) {
@@ -2775,7 +2880,7 @@
 		return;
 	}
 	if ((as->dev_audio = register_sound_dsp(&usb_audio_fops, -1)) < 0) {
-		printk(KERN_ERR "usb_audio: cannot register dsp\n");
+		printk(KERN_ERR "usbaudio: cannot register dsp\n");
 		kfree(as);
 		return;
 	}
@@ -2803,11 +2908,11 @@
 	struct mixerchannel *c;
 
 	if (nr >= SOUND_MIXER_NRDEVICES) {
-		printk(KERN_ERR "usb_audio: invalid OSS mixer channel %u\n", nr);
+		printk(KERN_ERR "usbaudio: invalid OSS mixer channel %u\n", nr);
 		return NULL;
 	}
 	if (!(state->mixchmask & (1 << nr))) {
-		printk(KERN_WARNING "usb_audio: OSS mixer channel %u already in use\n", nr);
+		printk(KERN_WARNING "usbaudio: OSS mixer channel %u already in use\n", nr);
 		return NULL;
 	}
 	c = &state->mixch[state->nrmixch++];
@@ -2973,7 +3078,7 @@
 	return;
 
  err:
-	printk(KERN_ERR "usb_audio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
+	printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
 	       dev->devnum, state->ctrlif, ch->unitid, ch->chnum, ch->selector);
 	if (state->nrmixch)
 		state->nrmixch--;
@@ -3009,11 +3114,11 @@
 	unsigned int i;
 
 	if (!mixer[4]) {
-		printk(KERN_ERR "usb_audio: unit %u invalid MIXER_UNIT descriptor\n", mixer[3]);
+		printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor\n", mixer[3]);
 		return;
 	}
 	if (mixer[4] > SOUND_MIXER_NRDEVICES) {
-		printk(KERN_ERR "usb_audio: mixer unit %u: too many input pins\n", mixer[3]);
+		printk(KERN_ERR "usbaudio: mixer unit %u: too many input pins\n", mixer[3]);
 		return;
 	}
 	chidx[0] = 0;
@@ -3027,7 +3132,7 @@
 	bmapsize = (nroutch * chidx[mixer[4]] + 7) >> 3;
 	bmap += bmapsize - 1;
 	if (mixer[0] < 10+mixer[4]+bmapsize) {
-		printk(KERN_ERR "usb_audio: unit %u invalid MIXER_UNIT descriptor (bitmap too small)\n", mixer[3]);
+		printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor (bitmap too small)\n", mixer[3]);
 		return;
 	}
 	for (i = 0; i < mixer[4]; i++) {
@@ -3066,7 +3171,7 @@
 	unsigned int chnum, i;
 
 	if (!selector[4]) {
-		printk(KERN_ERR "usb_audio: unit %u invalid SELECTOR_UNIT descriptor\n", selector[3]);
+		printk(KERN_ERR "usbaudio: unit %u invalid SELECTOR_UNIT descriptor\n", selector[3]);
 		return;
 	}
 	usb_audio_recurseunit(state, selector[5]);
@@ -3074,7 +3179,7 @@
 	for (i = 1; i < selector[4]; i++) {
 		usb_audio_recurseunit(state, selector[5+i]);
 		if (chnum != state->nrchannels) {
-			printk(KERN_ERR "usb_audio: selector unit %u: input pins with varying channel numbers\n", selector[3]);
+			printk(KERN_ERR "usbaudio: selector unit %u: input pins with varying channel numbers\n", selector[3]);
 			state->termtype = 0;
 			state->chconfig = 0;
 			state->nrchannels = 0;
@@ -3100,18 +3205,20 @@
 
 static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr)
 {
+	struct usb_device *dev = state->s->usbdev;
 	struct mixerchannel *ch;
 	unsigned short chftr, mchftr;
+	unsigned char data[1];
 
 	usb_audio_recurseunit(state, ftr[4]);
 	if (state->nrchannels == 0) {
-		printk(KERN_ERR "usb_audio: feature unit %u source has no channels\n", ftr[3]);
+		printk(KERN_ERR "usbaudio: feature unit %u source has no channels\n", ftr[3]);
 		return;
 	}
 	if (state->nrchannels > 2)
-		printk(KERN_WARNING "usb_audio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
+		printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
 	if (ftr[0] < 7+ftr[5]*(1+state->nrchannels)) {
-		printk(KERN_ERR "usb_audio: unit %u: invalid FEATURE_UNIT descriptor\n", ftr[3]);
+		printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", ftr[3]);
 		return;
 	}
 	mchftr = ftr[6];
@@ -3149,7 +3256,7 @@
 			prepmixch(state);
 		}
 	} else if (mchftr & 4) {
-		ch = getmixchannel(state, getvolchannel(state));
+		ch = getmixchannel(state, SOUND_MIXER_BASS);
 		if (ch) {
 			ch->unitid = ftr[3];
 			ch->selector = BASS_CONTROL;
@@ -3169,7 +3276,7 @@
 			prepmixch(state);
 		}
 	} else if (mchftr & 16) {
-		ch = getmixchannel(state, getvolchannel(state));
+		ch = getmixchannel(state, SOUND_MIXER_TREBLE);
 		if (ch) {
 			ch->unitid = ftr[3];
 			ch->selector = TREBLE_CONTROL;
@@ -3178,6 +3285,14 @@
 			prepmixch(state);
 		}
 	}
+	/* if there are mute controls, unmute them */
+	if ((chftr & 1) || (mchftr & 1)) {
+		printk(KERN_DEBUG "usbaudio: unmuting feature unit %u interface %u\n", ftr[3], state->ctrlif);
+		data[0] = 0;
+		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+                                    (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, HZ) < 0)
+			printk(KERN_WARNING "usbaudio: failure to unmute feature unit %u interface %u\n", ftr[3], state->ctrlif);
+ 	}
 }
 
 static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid)
@@ -3186,12 +3301,12 @@
 	unsigned int i, j;
 
 	if (test_and_set_bit(unitid, &state->unitbitmap)) {
-		printk(KERN_ERR "usb_audio: mixer path recursion detected, unit %d!\n", unitid);
+		printk(KERN_ERR "usbaudio: mixer path recursion detected, unit %d!\n", unitid);
 		return;
 	}
 	p1 = find_audiocontrol_unit(state->buffer, state->buflen, NULL, unitid, state->ctrlif);
 	if (!p1) {
-		printk(KERN_ERR "usb_audio: unit %d not found!\n", unitid);
+		printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid);
 		return;
 	}
 	state->nrchannels = 0;
@@ -3200,7 +3315,7 @@
 	switch (p1[2]) {
 	case INPUT_TERMINAL:
 		if (p1[0] < 12) {
-			printk(KERN_ERR "usb_audio: unit %u: invalid INPUT_TERMINAL descriptor\n", unitid);
+			printk(KERN_ERR "usbaudio: unit %u: invalid INPUT_TERMINAL descriptor\n", unitid);
 			return;
 		}
 		state->nrchannels = p1[7];
@@ -3210,7 +3325,7 @@
 
 	case MIXER_UNIT:
 		if (p1[0] < 10 || p1[0] < 10+p1[4]) {
-			printk(KERN_ERR "usb_audio: unit %u: invalid MIXER_UNIT descriptor\n", unitid);
+			printk(KERN_ERR "usbaudio: unit %u: invalid MIXER_UNIT descriptor\n", unitid);
 			return;
 		}
 		usb_audio_mixerunit(state, p1);
@@ -3218,7 +3333,7 @@
 
 	case SELECTOR_UNIT:
 		if (p1[0] < 6 || p1[0] < 6+p1[4]) {
-			printk(KERN_ERR "usb_audio: unit %u: invalid SELECTOR_UNIT descriptor\n", unitid);
+			printk(KERN_ERR "usbaudio: unit %u: invalid SELECTOR_UNIT descriptor\n", unitid);
 			return;
 		}
 		usb_audio_selectorunit(state, p1);
@@ -3226,7 +3341,7 @@
 
 	case FEATURE_UNIT:
 		if (p1[0] < 7 || p1[0] < 7+p1[5]) {
-			printk(KERN_ERR "usb_audio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid);
+			printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid);
 			return;
 		}
 		usb_audio_featureunit(state, p1);
@@ -3234,7 +3349,7 @@
 
 	case PROCESSING_UNIT:
 		if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]] || p1[0] < 13+p1[6]+p1[11+p1[6]]+p1[13+p1[6]+p1[11+p1[6]]]) {
-			printk(KERN_ERR "usb_audio: unit %u: invalid PROCESSING_UNIT descriptor\n", unitid);
+			printk(KERN_ERR "usbaudio: unit %u: invalid PROCESSING_UNIT descriptor\n", unitid);
 			return;
 		}
 		usb_audio_processingunit(state, p1);
@@ -3242,7 +3357,7 @@
 
 	case EXTENSION_UNIT:
 		if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]]) {
-			printk(KERN_ERR "usb_audio: unit %u: invalid EXTENSION_UNIT descriptor\n", unitid);
+			printk(KERN_ERR "usbaudio: unit %u: invalid EXTENSION_UNIT descriptor\n", unitid);
 			return;
 		}
 		for (j = i = 0; i < p1[6]; i++) {
@@ -3258,7 +3373,7 @@
 		return;
 
 	default:
-		printk(KERN_ERR "usb_audio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
+		printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
 		return;
 	}
 }
@@ -3276,11 +3391,11 @@
 	state.buflen = buflen;
 	state.ctrlif = ctrlif;
 	set_bit(oterm[3], &state.unitbitmap);  /* mark terminal ID as visited */
-	printk(KERN_INFO "usb_audio: constructing mixer for Terminal %u type 0x%04x\n",
+	printk(KERN_INFO "usbaudio: constructing mixer for Terminal %u type 0x%04x\n",
 	       oterm[3], oterm[4] | (oterm[5] << 8));
 	usb_audio_recurseunit(&state, oterm[7]);
 	if (!state.nrmixch) {
-		printk(KERN_INFO "usb_audio: no mixer controls found for Terminal %u\n", oterm[3]);
+		printk(KERN_INFO "usbaudio: no mixer controls found for Terminal %u\n", oterm[3]);
 		return;
 	}
 	if (!(ms = kmalloc(sizeof(struct usb_mixerdev)+state.nrmixch*sizeof(struct mixerchannel), GFP_KERNEL)))
@@ -3291,14 +3406,14 @@
 	ms->iface = ctrlif;
 	ms->numch = state.nrmixch;
 	if ((ms->dev_mixer = register_sound_mixer(&usb_mixer_fops, -1)) < 0) {
-		printk(KERN_ERR "usb_audio: cannot register mixer\n");
+		printk(KERN_ERR "usbaudio: cannot register mixer\n");
 		kfree(ms);
 		return;
 	}
 	list_add_tail(&ms->list, &s->mixerlist);
 }
 
-static int usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
+static void * usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
 {
 	struct usb_audio_state *s;
 	struct usb_config_descriptor *config = dev->actconfig;
@@ -3308,7 +3423,7 @@
 	unsigned int i, j, numifin = 0, numifout = 0;
 
 	if (!(s = kmalloc(sizeof(struct usb_audio_state), GFP_KERNEL)))
-		return -1;
+		return NULL;
 	memset(s, 0, sizeof(struct usb_audio_state));
 	INIT_LIST_HEAD(&s->audiolist);
 	INIT_LIST_HEAD(&s->mixerlist);
@@ -3316,63 +3431,67 @@
 	s->count = 1;
 	/* find audiocontrol interface */
 	if (!(p1 = find_csinterface_descriptor(buffer, buflen, NULL, HEADER, ctrlif, -1))) {
-		printk(KERN_ERR "usb_audio: device %d audiocontrol interface %u no HEADER found\n",
+		printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u no HEADER found\n",
 		       dev->devnum, ctrlif);
 		goto ret;
 	}
 	if (p1[0] < 8 + p1[7]) {
-		printk(KERN_ERR "usb_audio: device %d audiocontrol interface %u HEADER error\n",
+		printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u HEADER error\n",
 		       dev->devnum, ctrlif);
 		goto ret;
 	}
 	if (!p1[7])
-		printk(KERN_INFO "usb_audio: device %d audiocontrol interface %u has no AudioStreaming and MidiStreaming interfaces\n",
+		printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has no AudioStreaming and MidiStreaming interfaces\n",
 		       dev->devnum, ctrlif);
 	for (i = 0; i < p1[7]; i++) {
 		j = p1[8+i];
 		if (j >= config->bNumInterfaces) {
-			printk(KERN_ERR "usb_audio: device %d audiocontrol interface %u interface %u does not exist\n",
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u does not exist\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
 		iface = &config->interface[j];
 		if (iface->altsetting[0].bInterfaceClass != USB_CLASS_AUDIO) {
-			printk(KERN_ERR "usb_audio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n",
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
 		if (iface->altsetting[0].bInterfaceSubClass == 3) {
-			printk(KERN_INFO "usb_audio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n",
+			printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
 		if (iface->altsetting[0].bInterfaceSubClass != 2) {
-			printk(KERN_ERR "usb_audio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n",
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
 		if (iface->num_altsetting < 2 ||
 		    iface->altsetting[0].bNumEndpoints > 0) {
-			printk(KERN_ERR "usb_audio: device %d audiocontrol interface %u altsetting 0 not zero bandwidth\n",
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u altsetting 0 not zero bandwidth\n",
 			       dev->devnum, ctrlif);
 			continue;
 		}
 		if (iface->altsetting[1].bNumEndpoints < 1) {
-			printk(KERN_ERR "usb_audio: device %d audiocontrol interface %u interface %u has no endpoint\n",
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no endpoint\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
 		/* note: this requires the data endpoint to be ep0 and the optional sync
 		   ep to be ep1, which seems to be the case */
 		if (iface->altsetting[1].endpoint[0].bEndpointAddress & USB_DIR_IN) {
-			if (numifin < USB_MAXINTERFACES)
+			if (numifin < USB_MAXINTERFACES) {
 				ifin[numifin++] = j;
+				usb_driver_claim_interface(&usb_audio_driver, iface, s);
+			}
 		} else {
-			if (numifout < USB_MAXINTERFACES)
+			if (numifout < USB_MAXINTERFACES) {
 				ifout[numifout++] = j;
+				usb_driver_claim_interface(&usb_audio_driver, iface, s);
+			}
 		}
 	}
-	printk(KERN_INFO "usb_audio: device %d audiocontrol interface %u has %u input and %u output AudioStreaming interfaces\n",
+	printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has %u input and %u output AudioStreaming interfaces\n",
 	       dev->devnum, ctrlif, numifin, numifout);
 	for (i = 0; i < numifin && i < numifout; i++)
 		usb_audio_parsestreaming(s, buffer, buflen, ifin[i], ifout[i]);
@@ -3391,20 +3510,18 @@
  ret:
 	if (list_empty(&s->audiolist) && list_empty(&s->mixerlist)) {
 		kfree(s);
-		return -1;
+		return NULL;
 	}
 	/* everything successful */
-	dev->private = s;
 	down(&open_sem);
 	list_add_tail(&s->audiodev, &audiodevs);
 	up(&open_sem);
-	MOD_INC_USE_COUNT;
-	return 0;
+	return s;
 }
 
 /* we only care for the currently active configuration */
 
-static int usb_audio_probe(struct usb_device *dev)
+static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_config_descriptor *config = dev->actconfig;	
 	unsigned char *buffer;
@@ -3416,40 +3533,36 @@
 		if (config->interface[i].altsetting[0].bInterfaceClass == USB_CLASS_AUDIO &&
 		    config->interface[i].altsetting[0].bInterfaceSubClass == 1)  /* audiocontrol interface found */
 			goto audioctrlfound;
-	printk(KERN_DEBUG "usb_audio: vendor id 0x%04x, product id 0x%04x contains no AudioControl interface\n",
+	printk(KERN_DEBUG "usbaudio: vendor id 0x%04x, product id 0x%04x contains no AudioControl interface\n",
 	       dev->descriptor.idVendor, dev->descriptor.idProduct);
-	return -1;
+	return NULL;
 
  audioctrlfound:
 	/* find which configuration number is active */
 	for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
 		if (dev->config+i == config)
 			goto configfound;
-	printk(KERN_ERR "usb_audio: cannot find active configuration number of device %d\n", dev->devnum);
-	return -1;
+	printk(KERN_ERR "usbaudio: cannot find active configuration number of device %d\n", dev->devnum);
+	return NULL;
 
  configfound:
-        if (usb_set_configuration(dev, config->bConfigurationValue) < 0) {
-		printk(KERN_ERR "usb_audio: set_configuration failed (ConfigValue 0x%x)\n", config->bConfigurationValue);
-		return -1;
-	}
 	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buf, 8);
 	if (ret) {
-		printk(KERN_ERR "usb_audio: cannot get first 8 bytes of config descriptor %d of device %d\n", i, dev->devnum);
-		return -1;
+		printk(KERN_ERR "usbaudio: cannot get first 8 bytes of config descriptor %d of device %d\n", i, dev->devnum);
+		return NULL;
 	}
 	if (buf[1] != USB_DT_CONFIG || buf[0] < 9) {
-		printk(KERN_ERR "usb_audio: invalid config descriptor %d of device %d\n", i, dev->devnum);
-		return -1;
+		printk(KERN_ERR "usbaudio: invalid config descriptor %d of device %d\n", i, dev->devnum);
+		return NULL;
 	}
 	buflen = buf[2] | (buf[3] << 8);
 	if (!(buffer = kmalloc(buflen, GFP_KERNEL)))
-		return -1;
+		return NULL;
 	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen);
 	if (ret) {
 		kfree(buffer);
-		printk(KERN_ERR "usb_audio: cannot get config descriptor %d of device %d\n", i, dev->devnum);
-		return -1;
+		printk(KERN_ERR "usbaudio: cannot get config descriptor %d of device %d\n", i, dev->devnum);
+		return NULL;
 	}
 	/* find first audio control interface; we currently cannot handle more than one */
 	for (i = 0; i < config->bNumInterfaces; i++) {
@@ -3457,18 +3570,17 @@
 		    config->interface[i].altsetting[0].bInterfaceSubClass != 1)
 			continue;
 		/* audiocontrol interface found */
-		if (!usb_audio_parsecontrol(dev, buffer, buflen, i)) 
-			return 0;
+		return usb_audio_parsecontrol(dev, buffer, buflen, i);
 	}
-	return -1;
+	return NULL;
 }
 
 
 /* a revoke facility would make things simpler */
 
-static void usb_audio_disconnect(struct usb_device *dev)
+static void usb_audio_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct usb_audio_state *s = (struct usb_audio_state *)dev->private;
+	struct usb_audio_state *s = (struct usb_audio_state *)ptr;
 	struct list_head *list;
 	struct usb_audiodev *as;
 	struct usb_mixerdev *ms;
@@ -3496,7 +3608,6 @@
 #endif
 	release(s);
         wake_up(&open_wait);
-	dev->private = NULL;
 }
 
 int usb_audio_init(void)
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c
--- v2.3.24/linux/drivers/usb/cpia.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/usb/cpia.c	Mon Nov  1 11:30:29 1999
@@ -29,6 +29,7 @@
 #define CPIA_DEBUG	/* Gobs of debugging info */
 
 /* Video Size 384 x 288 x 3 bytes for RGB */
+/* 384 because xawtv tries to grab 384 even though we tell it 352 is our max */
 #define MAX_FRAME_SIZE (384 * 288 * 3)
 
 /*******************************/
@@ -37,6 +38,8 @@
 
 #define MDEBUG(x)	do { } while(0)		/* Debug memory management */
 
+static struct usb_driver cpia_driver;
+
 /* Given PGD from the address space's page table, return the kernel
  * virtual mapping of the physical memory mapped at ADR.
  */
@@ -207,8 +210,8 @@
 static int usb_cpia_upload_frame(struct usb_device *dev, int forceupload)
 {
 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_CPIA_UPLOAD_FRAME,
-		USB_TYPE_VENDOR | USB_RECIP_DEVICE, forceupload, 0, NULL, 0, HZ);
+		USB_REQ_CPIA_UPLOAD_FRAME, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		forceupload, 0, NULL, 0, HZ);
 }
 
 static int usb_cpia_set_grab_mode(struct usb_device *dev, int continuousgrab)
@@ -245,6 +248,16 @@
 }
 
 #ifdef NOTUSED
+static int usb_cpia_set_compression_target(struct usb_device *dev, int target, int targetfr, int targetq)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		USB_REQ_CPIA_SET_COMPRESSION_TARGET,
+		USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		(targetfr << 8) + target, targetq, NULL, 0, HZ);
+}
+#endif
+
+#ifdef NOTUSED
 static int usb_cpia_initstreamcap(struct usb_device *dev, int skipframes, int streamstartline)
 {
 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -284,6 +297,7 @@
 	unsigned char *data = cpia->scratch;
 	unsigned long l;
 
+	/* Grab the current frame and the previous frame */
 	frame = &cpia->frame[cpia->curframe];
 	pframe = &cpia->frame[(cpia->curframe - 1 + CPIA_NUMFRAMES) % CPIA_NUMFRAMES];
 
@@ -314,9 +328,9 @@
 			/* See if we found the end of the frame */
 			while (scratch_left(data) >= 4) {
 				if (*((__u32 *)data) == 0xFFFFFFFF) {
-printk("found end of frame\n");
 					data += 4;
-goto error;
+					printk(KERN_INFO "cpia: EOF while scanning for magic\n");
+					goto error;
 				}
 				data++;
 			}
@@ -347,7 +361,6 @@
 
 			frame->scanstate = STATE_LINES;
 			frame->curline = 0;
-
 			break;
 		case STATE_LINES:
 		{
@@ -363,10 +376,9 @@
 			/* Grab the length */
 			len = data[0] + (data[1] << 8);
 
-printk("line %d, %d bytes long\n", frame->curline, len);
 			/* Check to make sure it's nothing outrageous */
 			if (len > (frame->hdrwidth * 2) + 1) {
-				printk(KERN_INFO "cpia: bad length, resynching\n");
+				printk(KERN_INFO "cpia: bad length, resynching (expected %d, got %d)\n", (frame->hdrwidth * 2) + 1, len);
 				goto error;
 			}
 
@@ -380,12 +392,6 @@
 			/* Is the end of the line there */
 			if (data[len - 1] != 0xFD) {
 				printk(KERN_INFO "cpia: lost synch\n");
-end = data + len - 1 - 4;
-printk("%02X %02X %02X %02X %02X %02X %02X %02X\n",
-end[0], end[1],
-end[2], end[3],
-end[4], end[5],
-end[6], end[7]);
 				goto error;
 			}
 
@@ -426,12 +432,6 @@
 *f++ = LIMIT(b + y); *f++ = LIMIT(g + y); *f++ = LIMIT(r + y);
 *f++ = LIMIT(b + y1); *f++ = LIMIT(g + y1); *f++ = LIMIT(r + y1);
 						fp += 6;
-/*
-						f[0] = f[1] = f[2] = *data;
-						f += 3;
-						data += 2;
-						fp += 3;
-*/
 					}
 				}
 			} else {
@@ -469,10 +469,11 @@
 	}
 
 nextframe:
-	if (scratch_left(data) >= 4 && *((__u32 *)data) == 0xFFFFFFFF) {
+#ifdef CPIA_DEBUG
+	printk("cpia: marking as success\n");
+#endif
+	if (scratch_left(data) >= 4 && *((__u32 *)data) == 0xFFFFFFFF)
 		data += 4;
-printk("end of frame found normally\n");
-}
 
 	frame->grabstate = FRAME_DONE;
 	cpia->curframe = -1;
@@ -484,6 +485,9 @@
 	goto out;
 
 error:
+#ifdef CPIA_DEBUG
+	printk("cpia: marking as error\n");
+#endif
 	frame->grabstate = FRAME_ERROR;
 	cpia->curframe = -1;
 	cpia->compress = 0;
@@ -493,7 +497,6 @@
 		wake_up_interruptible(&frame->wq);
 
 out:
-printk("scanned %d bytes, %d left\n", data - cpia->scratch, scratch_left(data));
 	/* Grab the remaining */
 	l = scratch_left(data);
 	memmove(cpia->scratch, data, l);
@@ -544,7 +547,7 @@
 	int i;
 
 	if (!cpia->streaming) {
-		printk("oops, not streaming, but interrupt\n");
+		printk("cpia: oops, not streaming, but interrupt\n");
 		return 0;
 	}
 	
@@ -554,7 +557,6 @@
 	/* Copy the data received into our scratch buffer */
 	len = cpia_compress_isochronous(cpia, sbuf->isodesc);
 
-printk("%d bytes received\n", len);
 	/* If we don't have a frame we're current working on, complain */
 	if (len) {
 		if (cpia->curframe < 0)
@@ -587,7 +589,7 @@
 
 	/* Alternate interface 3 is is the biggest frame size */
 	if (usb_set_interface(cpia->dev, 1, 3) < 0) {
-		printk("usb_set_interface error\n");
+		printk(KERN_ERR "usb_set_interface error\n");
 		return -EBUSY;
 	}
 
@@ -642,21 +644,7 @@
 	if (err)
 		printk(KERN_ERR "CPiA USB driver error (%d) on usb_run_isoc\n", err);
 
-#ifdef CPIA_DEBUG
-	printk("done scheduling\n");
-#endif
-
-#if 0
-	if (usb_cpia_grab_frame(dev, 120) < 0) {
-		printk(KERN_INFO "cpia_grab_frame error\n");
-		return -EBUSY;
-	}
-#endif
-
 	cpia->streaming = 1;
-#ifdef CPIA_DEBUG
-	printk("now streaming\n");
-#endif
 
 	return 0;
 }
@@ -666,21 +654,12 @@
 	if (!cpia->streaming)
 		return;
 
-	cpia->streaming = 0;
-
 	/* Turn off continuous grab */
 	if (usb_cpia_set_grab_mode(cpia->dev, 0) < 0) {
 		printk(KERN_INFO "cpia_set_grab_mode error\n");
 		return /* -EBUSY */;
 	}
 
-#if 0
-	if (usb_cpia_grab_frame(cpia->dev, 0) < 0) {
-		printk(KERN_INFO "cpia_grab_frame error\n");
-		return /* -EBUSY */;
-	}
-#endif
-
 	/* Set packet size to 0 */
 	if (usb_set_interface(cpia->dev, 1, 0) < 0) {
 		printk(KERN_INFO "usb_set_interface error\n");
@@ -691,6 +670,8 @@
 	usb_kill_isoc(cpia->sbuf[1].isodesc);
 	usb_kill_isoc(cpia->sbuf[0].isodesc);
 
+	cpia->streaming = 0;
+
 	/* Delete them all */
 	usb_free_isoc(cpia->sbuf[1].isodesc);
 	usb_free_isoc(cpia->sbuf[0].isodesc);
@@ -701,29 +682,23 @@
 	struct cpia_frame *frame;
 	int width, height;
 
-printk("new frame %d\n", framenum);
-	if (framenum == -1) {
-		int i;
-		for (i = 0; i < CPIA_NUMFRAMES; i++)
-			if (cpia->frame[i].grabstate == FRAME_READY)
-				break;
-
-		if (i >= CPIA_NUMFRAMES) {
-			printk("no frame ready\n");
-			return 0;
-		}
-
-		framenum = i;
-printk("using frame %d\n", framenum);
-	}
-
-	if (cpia->curframe != -1 && cpia->curframe != framenum)
+	/* If we're not grabbing a frame right now and the other frame is */
+	/*  ready to be grabbed into, then use it instead */
+	if (cpia->curframe == -1) {
+		if (cpia->frame[(framenum - 1 + CPIA_NUMFRAMES) % CPIA_NUMFRAMES].grabstate == FRAME_READY)
+			framenum = (framenum - 1 + CPIA_NUMFRAMES) % CPIA_NUMFRAMES;
+	} else
 		return 0;
 
 	frame = &cpia->frame[framenum];
 	width = frame->width;
 	height = frame->height;
 
+	frame->grabstate = FRAME_GRABBING;
+	frame->scanstate = STATE_SCANNING;
+
+	cpia->curframe = framenum;
+
 	/* Make sure it's not too big */
 	if (width > 352)
 		width = 352;
@@ -737,7 +712,8 @@
 	if (usb_cpia_set_roi(cpia->dev, 0, width / 8, 0, height / 4) < 0)
 		return -EBUSY;
 
-	if (usb_cpia_set_compression(cpia->dev, cpia->compress ? 1 : 0, 0) < 0) {
+	if (usb_cpia_set_compression(cpia->dev, cpia->compress ?
+			COMP_AUTO : COMP_DISABLED, DONT_DECIMATE) < 0) {
 		printk(KERN_INFO "cpia_set_compression error\n");
 		return -EBUSY;
 	}
@@ -746,16 +722,11 @@
 	cpia->compress = (cpia->compress + 1) % 30;
 
 	/* Grab the frame */
-	if (usb_cpia_upload_frame(cpia->dev, 1) < 0) {
+	if (usb_cpia_upload_frame(cpia->dev, WAIT_FOR_NEXT_FRAME) < 0) {
 		printk(KERN_INFO "cpia_upload_frame error\n");
 		return -EBUSY;
 	}
 
-	frame->grabstate = FRAME_GRABBING;
-	frame->scanstate = STATE_SCANNING;
-
-	cpia->curframe = framenum;
-
 	return 0;
 }
 
@@ -862,8 +833,8 @@
 			b.audios = 0;
 			b.maxwidth = 352;	/* CIF */
 			b.maxheight = 288;	/*  "  */
-			b.minwidth = 176;	/* QCIF */
-			b.minheight = 144;	/*  "   */
+			b.minwidth = 8;
+			b.minheight = 4;
 
 			if (copy_to_user(arg, &b, sizeof(b)))
 				return -EFAULT;
@@ -1065,11 +1036,11 @@
 				return -EINVAL;
 			case FRAME_READY:
 			case FRAME_GRABBING:
+			case FRAME_ERROR:
 redo:
 				do {
-printk("enter sleeping\n");
+					init_waitqueue_head(&cpia->frame[frame].wq);
 					interruptible_sleep_on(&cpia->frame[frame].wq);
-printk("back from sleeping\n");
 					if (signal_pending(current))
 						return -EINTR;
 				} while (cpia->frame[frame].grabstate ==
@@ -1091,8 +1062,9 @@
 #ifdef CPIA_DEBUG
 			printk("cpia: finished, synced to frame %d\n", frame);
 #endif
+			cpia->frame[frame].grabstate = FRAME_UNUSED;
 
-			return cpia_new_frame(cpia, -1);
+			return 0;
 		}
 		case VIDIOCGFBUF:
 		{
@@ -1195,12 +1167,11 @@
 	struct usb_device *dev = cpia->dev;
 	unsigned char version[4];
 
-	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) < 0) {
-		printk(KERN_INFO "cpia: usb_set_configuration failed\n");
-		return -EBUSY;
-	}
+	/* claim interface 1 */
+	usb_driver_claim_interface(&cpia_driver,
+		&dev->actconfig->interface[1], cpia);
 
-	/* Set packet size to 0 */
+	/* Set altsetting 0 on interface 1 */
 	if (usb_set_interface(dev, 1, 0) < 0) {
 		printk(KERN_INFO "usb_set_interface error\n");
 		return -EBUSY;
@@ -1211,7 +1182,7 @@
 		return -EBUSY;
 	}
 
-	printk("cpia: Firmware v%d.%d, VC Hardware v%d.%d\n",
+	printk(KERN_DEBUG "cpia: Firmware v%d.%d, VC Hardware v%d.%d\n",
 		version[0], version[1], version[2], version[3]);
 
 	memcpy(&cpia->vdev, &cpia_template, sizeof(cpia_template));
@@ -1234,8 +1205,8 @@
 		goto error;
 	}
 
-	printk("cpia: VP v%d rev %d\n", version[0], version[1]);
-	printk("cpia: Camera Head ID %04X\n", (version[3] << 8) + version[2]);
+	printk(KERN_DEBUG "cpia: VP v%d rev %d\n", version[0], version[1]);
+	printk(KERN_DEBUG "cpia: Camera Head ID %04X\n", (version[3] << 8) + version[2]);
 
 	/* Turn on continuous grab */
 	if (usb_cpia_set_grab_mode(dev, 1) < 0) {
@@ -1250,13 +1221,14 @@
 	}
 
 	/* Set video into CIF mode, and order into YUYV mode */
-	if (usb_cpia_set_format(dev, CPIA_CIF, 1, CPIA_YUYV) < 0) {
+	if (usb_cpia_set_format(dev, FORMAT_CIF, FORMAT_422,
+			FORMAT_YUYV) < 0) {
 		printk(KERN_INFO "cpia_set_format error\n");
 		goto error;
 	}
 
 	/* Turn off compression */
-	if (usb_cpia_set_compression(dev, 0, 0) < 0) {
+	if (usb_cpia_set_compression(dev, COMP_DISABLED, DONT_DECIMATE) < 0) {
 		printk(KERN_INFO "cpia_set_compression error\n");
 		goto error;
 	}
@@ -1267,56 +1239,62 @@
 
 error:
 	video_unregister_device(&cpia->vdev);
+	usb_driver_release_interface(&cpia_driver,
+		&dev->actconfig->interface[1]);
 
 	kfree(cpia);
 
 	return -EBUSY;
 }
 
-static int cpia_probe(struct usb_device *dev)
+static void * cpia_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_interface_descriptor *interface;
 	struct usb_cpia *cpia;
 
 	/* We don't handle multi-config cameras */
 	if (dev->descriptor.bNumConfigurations != 1)
-		return -1;
+		return NULL;
 
-	interface = &dev->config[0].interface[0].altsetting[0];
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
 
 	/* Is it a CPiA? */
 	if (dev->descriptor.idVendor != 0x0553)
-		return -1;
+		return NULL;
 	if (dev->descriptor.idProduct != 0x0002)
-		return -1;
+		return NULL;
 
 	/* Checking vendor/product should be enough, but what the hell */
 	if (interface->bInterfaceClass != 0xFF)
-		return -1;
+		return NULL;
 	if (interface->bInterfaceSubClass != 0x00)
-		return -1;
+		return NULL;
 
 	/* We found a CPiA */
-	printk("USB CPiA camera found\n");
+	printk(KERN_INFO "USB CPiA camera found\n");
 
 	if ((cpia = kmalloc(sizeof(*cpia), GFP_KERNEL)) == NULL) {
-		printk("couldn't kmalloc cpia struct\n");
-		return -1;
+		printk(KERN_ERR "couldn't kmalloc cpia struct\n");
+		return NULL;
 	}
 
 	memset(cpia, 0, sizeof(*cpia));
 
-	dev->private = cpia;
 	cpia->dev = dev;
 
-	return usb_cpia_configure(cpia);
+	if (!usb_cpia_configure(cpia)) {
+	    return cpia;
+	} else return NULL;
 }
 
-static void cpia_disconnect(struct usb_device *dev)
+static void cpia_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct usb_cpia *cpia = dev->private;
+	struct usb_cpia *cpia = (struct usb_cpia *) ptr;
 
 	video_unregister_device(&cpia->vdev);
+
+	usb_driver_release_interface(&cpia_driver,
+		&cpia->dev->actconfig->interface[1]);
 
 	/* Free the memory */
 	kfree(cpia);
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/cpia.h linux/drivers/usb/cpia.h
--- v2.3.24/linux/drivers/usb/cpia.h	Sat Oct  9 11:47:50 1999
+++ linux/drivers/usb/cpia.h	Mon Nov  1 11:30:29 1999
@@ -50,15 +50,30 @@
 
 #define USB_REQ_CPIA_GRAB_FRAME			0xC1
 #define USB_REQ_CPIA_UPLOAD_FRAME		0xC2
+#define  WAIT_FOR_NEXT_FRAME			0
+#define  FORCE_FRAME_UPLOAD			1
 #define USB_REQ_CPIA_SET_GRAB_MODE		0xC3
 #define USB_REQ_CPIA_INIT_STREAM_CAP		0xC4
 #define USB_REQ_CPIA_FINI_STREAM_CAP		0xC5
 #define USB_REQ_CPIA_START_STREAM_CAP		0xC6
 #define USB_REQ_CPIA_END_STREAM_CAP		0xC7
 #define USB_REQ_CPIA_SET_FORMAT			0xC8
+#define  FORMAT_QCIF	0
+#define  FORMAT_CIF	1
+#define  FORMAT_YUYV	0
+#define  FORMAT_UYVY	1
+#define  FORMAT_420	0
+#define  FORMAT_422	1
 #define USB_REQ_CPIA_SET_ROI			0xC9
 #define USB_REQ_CPIA_SET_COMPRESSION		0xCA
+#define  COMP_DISABLED	0
+#define  COMP_AUTO	1
+#define  COMP_MANUAL	2
+#define  DONT_DECIMATE	0
+#define  DECIMATE	1
 #define USB_REQ_CPIA_SET_COMPRESSION_TARGET	0xCB
+#define  TARGET_QUALITY		0
+#define  TARGET_FRAMERATE	1
 #define USB_REQ_CPIA_SET_YUV_THRESH		0xCC
 #define USB_REQ_CPIA_SET_COMPRESSION_PARAMS	0xCD
 #define USB_REQ_CPIA_DISCARD_FRAME		0xCE
@@ -71,12 +86,6 @@
 #define USB_REQ_CPIA_ABORT_STREAM		0xE9
 #define USB_REQ_CPIA_DOWNLOAD_DRAM		0xEA
 /* #define USB_REQ_CPIA_NULL_CMD		0x?? */
-
-#define CPIA_QCIF	0
-#define CPIA_CIF	1
-
-#define CPIA_YUYV	0
-#define CPIA_UYVY	1
 
 #define STREAM_BUF_SIZE		(PAGE_SIZE * 4)
 /* #define STREAM_BUF_SIZE	(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC) */
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/ezusb.c linux/drivers/usb/ezusb.c
--- v2.3.24/linux/drivers/usb/ezusb.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/usb/ezusb.c	Thu Oct 28 12:53:26 1999
@@ -968,7 +968,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int ezusb_probe(struct usb_device *usbdev)
+static void * ezusb_probe(struct usb_device *usbdev, unsigned int ifnum)
 {
 	struct ezusb *ez = &ezusb[0];
         struct usb_interface_descriptor *interface;
@@ -982,56 +982,49 @@
 	/* the 1234:5678 is just a self assigned test ID */
         if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) &&
 	    (usbdev->descriptor.idVendor != 0x1234 || usbdev->descriptor.idProduct != 0x5678))
-                return -1;
+                return NULL;
 
         /* We don't handle multiple configurations */
         if (usbdev->descriptor.bNumConfigurations != 1)
-                return -1;
+                return NULL;
 
 #if 0
         /* We don't handle multiple interfaces */
-        if (usbdev->config[0].bNumInterfaces != 1)
-                return -1;
+        if (usbdev->actconfig.bNumInterfaces != 1)
+                return NULL;
 #endif
 
 	down(&ez->mutex);
 	if (ez->usbdev) {
 		up(&ez->mutex);
 		printk(KERN_INFO "ezusb: device already used\n");
-		return -1;
+		return NULL;
 	}
 	ez->usbdev = usbdev;
-	usbdev->private = ez;
-        if (usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue) < 0) {
-		printk(KERN_ERR "ezusb: set_configuration failed\n");
-		goto err;
-	}
-        interface = &usbdev->config[0].interface[0].altsetting[1];
-	if (usb_set_interface(usbdev, 0, 1) < 0) {
+        interface = &usbdev->actconfig->interface[ifnum].altsetting[1];
+	if (usb_set_interface(usbdev, ifnum, 1) < 0) {
 		printk(KERN_ERR "ezusb: set_interface failed\n");
 		goto err;
 	}
 	up(&ez->mutex);
 	MOD_INC_USE_COUNT;
-        return 0;
+        return ez;
 
  err:
 	up(&ez->mutex);
 	ez->usbdev = NULL;
-	usbdev->private = NULL;
-	return -1;
+	return NULL;
 }
 
-static void ezusb_disconnect(struct usb_device *usbdev)
+static void ezusb_disconnect(struct usb_device *usbdev, void *ptr)
 {
-	struct ezusb *ez = (struct ezusb *)usbdev->private;
+	struct ezusb *ez = (struct ezusb *) ptr;
 
 	down(&ez->mutex);
 	destroy_all_async(ez);
 	ez->usbdev = NULL;
 	up(&ez->mutex);
 	wake_up(&ez->wait);
-        usbdev->private = NULL;
 	MOD_DEC_USE_COUNT;
 }
 
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/hp_scanner.c linux/drivers/usb/hp_scanner.c
--- v2.3.24/linux/drivers/usb/hp_scanner.c	Fri Oct 22 13:21:51 1999
+++ linux/drivers/usb/hp_scanner.c	Thu Oct 28 12:53:26 1999
@@ -217,8 +217,8 @@
 	return read_count;
 }
 
-static int
-probe_scanner(struct usb_device *dev)
+static void *
+probe_scanner(struct usb_device *dev, unsigned int ifnum)
 {
 	struct hpscan_usb_data *hps = &hpscan;
 
@@ -228,41 +228,36 @@
 	 * soon.  */
 	if (dev->descriptor.idVendor != 0x3f0 ) {
 		printk(KERN_INFO "Scanner is not an HP Scanner.\n");
-		return -1;
+		return NULL;
 	}
 
 	if (dev->descriptor.idProduct != 0x101 && /* HP 4100C */
 	    dev->descriptor.idProduct != 0x202 && /* HP 5100C */
             dev->descriptor.idProduct != 0x601) { /* HP 6300C */
 		printk(KERN_INFO "Scanner model not supported/tested.\n");
-		return -1;
+		return NULL;
 	}
 	
 	printk(KERN_DEBUG "USB Scanner found at address %d\n", dev->devnum);
 	
-	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-		printk(KERN_DEBUG "Failed to set configuration\n");
-		return -1;
-	}
-
 	hps->present = 1;
 	hps->hpscan_dev = dev;
 
 	if (!(hps->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
-		return -ENOMEM;
+		return NULL;
 	}
 
 	if (!(hps->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
-		return -ENOMEM;
+		return NULL;
 	}
   
-	return 0;
+	return hps;
 }
 
 static void
-disconnect_scanner(struct usb_device *dev)
+disconnect_scanner(struct usb_device *dev, void *ptr)
 {
-	struct hpscan_usb_data *hps = &hpscan;
+	struct hpscan_usb_data *hps = (struct hpscan_usb_data *) ptr;
 
 	if (hps->isopen) {
 		/* better let it finish - the release will do whats needed */
@@ -272,7 +267,6 @@
 	kfree(hps->ibuf);
 	kfree(hps->obuf);
 
-	dev->private = NULL;		/* just in case */
 	hps->present = 0;
 }
 
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.24/linux/drivers/usb/hub.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/usb/hub.c	Thu Oct 28 12:53:26 1999
@@ -22,7 +22,6 @@
 
 /* Wakes up khubd */
 static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t hub_list_lock = SPIN_LOCK_UNLOCKED;
 
 static LIST_HEAD(hub_event_list);	/* List of hubs needing servicing */
 static LIST_HEAD(hub_list);		/* List containing all of the hubs (for cleanup) */
@@ -105,9 +104,6 @@
 	struct usb_hub_status *hubsts;
 	int i;
 
-	/* Set it to the first configuration */
-	usb_set_configuration(dev, dev->config[0].bConfigurationValue);
-
 	/* Get the length first */
 	if (usb_get_hub_descriptor(dev, buffer, 4))
 		return -1;
@@ -188,7 +184,7 @@
 	return 0;
 }
 
-static int hub_probe(struct usb_device *dev)
+static void * hub_probe(struct usb_device *dev, unsigned int i)
 {
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
@@ -196,60 +192,50 @@
 	unsigned long flags;
 	int ret;
 
-	/* We don't handle multi-config hubs */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return -1;
-
-	/* We don't handle multi-interface hubs */
-	if (dev->config[0].bNumInterfaces != 1)
-		return -1;
-
-	interface = &dev->config[0].interface[0].altsetting[0];
+	interface = &dev->actconfig->interface[i].altsetting[0];
 
 	/* Is it a hub? */
 	if (interface->bInterfaceClass != USB_CLASS_HUB)
-		return -1;
+		return NULL;
 
 	/* Some hubs have a subclass of 1, which AFAICT according to the */
 	/*  specs is not defined, but it works */
 	if ((interface->bInterfaceSubClass != 0) &&
 	    (interface->bInterfaceSubClass != 1))
-		return -1;
+		return NULL;
 
 	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
 	if (interface->bNumEndpoints != 1)
-		return -1;
+		return NULL;
 
 	endpoint = &interface->endpoint[0];
 
 	/* Output endpoint? Curiousier and curiousier.. */
 	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-		return -1;
+		return NULL;
 
 	/* If it's not an interrupt endpoint, we'd better punt! */
 	if ((endpoint->bmAttributes & 3) != 3)
-		return -1;
+		return NULL;
 
 	/* We found a hub */
 	printk(KERN_INFO "USB hub found\n");
 
 	if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "couldn't kmalloc hub struct\n");
-		return -1;
+		return NULL;
 	}
 
 	memset(hub, 0, sizeof(*hub));
 
-	dev->private = hub;
-
 	INIT_LIST_HEAD(&hub->event_list);
 	hub->dev = dev;
 
 	/* Record the new hub's existence */
-	spin_lock_irqsave(&hub_list_lock, flags);
+	spin_lock_irqsave(&hub_event_lock, flags);
 	INIT_LIST_HEAD(&hub->hub_list);
 	list_add(&hub->hub_list, &hub_list);
-	spin_unlock_irqrestore(&hub_list_lock, flags);
+	spin_unlock_irqrestore(&hub_event_lock, flags);
 
 	if (usb_hub_configure(hub) >= 0) {
 		hub->irqpipe = usb_rcvctrlpipe(dev, endpoint->bEndpointAddress);
@@ -258,20 +244,32 @@
 			hub, &hub->irq_handle);
 		if (ret) {
 			printk (KERN_WARNING "usb-hub: usb_request_irq failed (0x%x)\n", ret);
-			/* FIXME: need to free <hub> but first clean up its list. */
-			return -1;
+			/* free hub, but first clean up its list. */
+			spin_lock_irqsave(&hub_event_lock, flags);
+
+			/* Delete it and then reset it */
+			list_del(&hub->event_list);
+			INIT_LIST_HEAD(&hub->event_list);
+			list_del(&hub->hub_list);
+			INIT_LIST_HEAD(&hub->hub_list);
+
+			spin_unlock_irqrestore(&hub_event_lock, flags);
+
+			kfree(hub);
+
+			return NULL;
 		}
 
 		/* Wake up khubd */
 		wake_up(&khubd_wait);
 	}
 
-	return 0;
+	return hub;
 }
 
-static void hub_disconnect(struct usb_device *dev)
+static void hub_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct usb_hub *hub = dev->private;
+	struct usb_hub *hub = ptr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hub_event_lock, flags);
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/inits.h linux/drivers/usb/inits.h
--- v2.3.24/linux/drivers/usb/inits.h	Fri Oct 22 13:21:51 1999
+++ linux/drivers/usb/inits.h	Thu Oct 28 10:20:36 1999
@@ -4,6 +4,7 @@
 void usb_hub_cleanup(void);
 int usb_kbd_init(void);
 void usb_major_init(void);
+void usb_major_cleanup(void);
 void usb_mouse_cleanup(void);
 int usb_hp_scanner_init(void);
 void usb_hp_scanner_cleanup(void);
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/keyboard.c linux/drivers/usb/keyboard.c
--- v2.3.24/linux/drivers/usb/keyboard.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/usb/keyboard.c	Thu Oct 28 12:53:26 1999
@@ -45,8 +45,8 @@
 
 extern unsigned char usb_kbd_map[];
 
-static int usb_kbd_probe(struct usb_device *dev);
-static void usb_kbd_disconnect(struct usb_device *dev);
+static void * usb_kbd_probe(struct usb_device *dev, unsigned int i);
+static void usb_kbd_disconnect(struct usb_device *dev, void *ptr);
 static void usb_kbd_repeat(unsigned long dummy);
 
 static LIST_HEAD(usb_kbd_list);
@@ -190,25 +190,22 @@
     return 1;
 }
 
-static int
-usb_kbd_probe(struct usb_device *dev)
+static void *
+usb_kbd_probe(struct usb_device *dev, unsigned int i)
 {
     struct usb_interface_descriptor *interface;
     struct usb_endpoint_descriptor *endpoint;
     struct usb_keyboard *kbd;
     int ret;
     
-    if (dev->descriptor.bNumConfigurations < 1)
-	return -1;
-
-    interface = &dev->config[0].interface[0].altsetting[0];
+    interface = &dev->actconfig->interface[i].altsetting[0];
     endpoint = &interface->endpoint[0];
 
     if(interface->bInterfaceClass != 3
        || interface->bInterfaceSubClass != 1
        || interface->bInterfaceProtocol != 1)
     {
-        return -1;
+        return NULL;
     }
 
     printk(KERN_INFO "USB HID boot protocol keyboard detected.\n");
@@ -218,12 +215,7 @@
     {
         memset(kbd, 0, sizeof(*kbd));
         kbd->dev = dev;
-        dev->private = kbd;
 
-        if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-		printk (KERN_INFO " Failed usb_set_configuration: kbd\n");
-		goto probe_err;
-	}
         usb_set_protocol(dev, 0);
         usb_set_idle(dev, 0, 0);
         
@@ -238,23 +230,22 @@
 
         list_add(&kbd->list, &usb_kbd_list);
 	
-	return 0;
+	return kbd;
     }
 
 probe_err:
     if (kbd)
     	kfree (kbd);
-    return -1;
+    return NULL;
 }
 
 static void
-usb_kbd_disconnect(struct usb_device *dev)
+usb_kbd_disconnect(struct usb_device *dev, void *ptr)
 {
-    struct usb_keyboard *kbd = (struct usb_keyboard*) dev->private;
+    struct usb_keyboard *kbd = (struct usb_keyboard*) ptr;
     if (kbd)
     {
 	usb_release_irq(dev, kbd->irq_handler, kbd->irqpipe);
-	dev->private = NULL;
 	list_del(&kbd->list);
 	del_timer(&kbd->repeat_timer);
 	kfree(kbd);
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c
--- v2.3.24/linux/drivers/usb/mouse.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/usb/mouse.c	Thu Oct 28 12:53:26 1999
@@ -316,51 +316,38 @@
 	fasync_mouse,
 };
 
-static int mouse_probe(struct usb_device *dev)
+static void* mouse_probe(struct usb_device *dev, unsigned int i)
 {
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct mouse_state *mouse = &static_mouse_state;
 	int ret;
 
-	/* We don't handle multi-config mice */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return -1;
-
-	/* We don't handle multi-interface mice */
-	if (dev->config[0].bNumInterfaces != 1)
-		return -1;
-
 	/* Is it a mouse interface? */
-	interface = &dev->config[0].interface[0].altsetting[0];
+	interface = &dev->actconfig->interface[i].altsetting[0];
 	if (interface->bInterfaceClass != 3)
-		return -1;
+		return NULL;
 	if (interface->bInterfaceSubClass != 1)
-		return -1;
+		return NULL;
 	if (interface->bInterfaceProtocol != 2)
-		return -1;
+		return NULL;
 
 	/* Multiple endpoints? What kind of mutant ninja-mouse is this? */
 	if (interface->bNumEndpoints != 1)
-		return -1;
+		return NULL;
 
 	endpoint = &interface->endpoint[0];
 
 	/* Output endpoint? Curiousier and curiousier.. */
 	if (!(endpoint->bEndpointAddress & 0x80))
-		return -1;
+		return NULL;
 
 	/* If it's not an interrupt endpoint, we'd better punt! */
 	if ((endpoint->bmAttributes & 3) != 3)
-		return -1;
+		return NULL;
 
 	printk("USB mouse found\n");
 
-	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-		printk (KERN_INFO " Failed usb_set_configuration: mouse\n");
-		return -1;
-	}
-
 	/* these are used to request the irq when the mouse is opened */
 	mouse->dev = dev;
 	mouse->bEndpointAddress = endpoint->bEndpointAddress;
@@ -379,17 +366,17 @@
 			NULL, &mouse->irq_handle);
 		if (ret) {
 			printk (KERN_WARNING "usb-mouse: usb_request_irq failed (0x%x)\n", ret);
-			return ret;
+			return NULL;
 		}
 		mouse->suspended = 0;
 	}
 
-	return 0;
+	return mouse;
 }
 
-static void mouse_disconnect(struct usb_device *dev)
+static void mouse_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct mouse_state *mouse = &static_mouse_state;
+	struct mouse_state *mouse = ptr;
 
 	/* stop the usb interrupt transfer */
 	if (mouse->present) {
@@ -402,7 +389,7 @@
 
 	/* this might need work */
 	mouse->present = 0;
-	printk("Mouse disconnected\n");
+	printk("USB Mouse disconnected\n");
 }
 
 static struct usb_driver mouse_driver = {
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
--- v2.3.24/linux/drivers/usb/ohci-hcd.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/usb/ohci-hcd.c	Thu Oct 28 10:45:51 1999
@@ -1540,8 +1540,8 @@
 #	endif
 	while(!list_empty(&ohci_hcd_list)) {
 		ohci = list_entry(ohci_hcd_list.next, struct ohci, ohci_hcd_list);
-		list_del(ohci->ohci_hcd_list);
-		INIT_LIST_HEAD(ohci->ohci_hcd_list);
+		list_del(&ohci->ohci_hcd_list);
+		INIT_LIST_HEAD(&ohci->ohci_hcd_list);
 		release_ohci(ohci);
 	}		
 }
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.3.24/linux/drivers/usb/printer.c	Fri Oct 22 13:21:51 1999
+++ linux/drivers/usb/printer.c	Thu Oct 28 12:53:26 1999
@@ -254,9 +254,10 @@
 	return read_count;
 }
 
-static int printer_probe(struct usb_device *dev)
+static void * printer_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_interface_descriptor *interface;
+	struct pp_usb_data *pp;
 	int i;
 
 	/*
@@ -265,29 +266,29 @@
 	if ((dev->descriptor.bDeviceClass != USB_CLASS_PRINTER &&
 	    dev->descriptor.bDeviceClass != 0) ||
 	    dev->descriptor.bNumConfigurations != 1 ||
-	    dev->config[0].bNumInterfaces != 1) {
-		return -1;
+	    dev->actconfig->bNumInterfaces != 1) {
+		return NULL;
 	}
 
-	interface = &dev->config[0].interface[0].altsetting[0];
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
 
 	/* Let's be paranoid (for the moment). */
 	if (interface->bInterfaceClass != USB_CLASS_PRINTER ||
 	    interface->bInterfaceSubClass != 1 ||
 	    (interface->bInterfaceProtocol != 2 && interface->bInterfaceProtocol != 1) ||
 	    interface->bNumEndpoints > 2) {
-		return -1;
+		return NULL;
 	}
 
 	/* Does this (these) interface(s) support bulk transfers? */
 	if ((interface->endpoint[0].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 	      != USB_ENDPOINT_XFER_BULK) {
-		return -1;
+		return NULL;
 	}
 	if ((interface->bNumEndpoints > 1) &&
 	      ((interface->endpoint[1].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 	      != USB_ENDPOINT_XFER_BULK)) {
-		return -1;
+		return NULL;
 	}
 
 	/*
@@ -299,7 +300,7 @@
 	    (interface->bNumEndpoints > 1 &&
 	      (interface->endpoint[1].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
 	      != USB_DIR_OUT)) {
- 		return -1;
+ 		return NULL;
  	}
 
 	for (i=0; i<MAX_PRINTERS; i++) {
@@ -308,18 +309,18 @@
 	}
 	if (i >= MAX_PRINTERS) {
 		printk("No minor table space available for USB Printer\n");
-		return -1;
+		return NULL;
 	}
 
 	printk(KERN_INFO "USB Printer found at address %d\n", dev->devnum);
 
-	if (!(dev->private = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
+	if (!(pp = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
 		printk(KERN_DEBUG "usb_printer: no memory!\n");
-		return -1;
+		return NULL;
 	}
 
-	memset(dev->private, 0, sizeof(struct pp_usb_data));
-	minor_data[i] = PPDATA(dev->private);
+	memset(pp, 0, sizeof(struct pp_usb_data));
+	minor_data[i] = PPDATA(pp);
 	minor_data[i]->minor = i;
 	minor_data[i]->pusb_dev = dev;
 	minor_data[i]->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
@@ -342,11 +343,6 @@
 			interface->endpoint[minor_data[i]->bulk_in_index].wMaxPacketSize;
 	}
 
-        if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-		printk(KERN_INFO "  Failed usb_set_configuration: printer\n");
-		return -1;
-	}
-
 	printk(KERN_INFO "USB Printer Summary:\n");
 	printk(KERN_INFO "index=%d, maxout=%d, noinput=%d\n",
 		i, minor_data[i]->maxout, minor_data[i]->noinput);
@@ -374,19 +370,19 @@
 			printk(KERN_INFO "  USB Printer ID is %s\n",
 				&ieee_id[2]);
 		}
-		status = printer_read_status(PPDATA(dev->private));
+		status = printer_read_status(PPDATA(pp));
 		printk(KERN_INFO "  Status is %s,%s,%s\n",
 		       (status & LP_PSELECD) ? "Selected" : "Not Selected",
 		       (status & LP_POUTPA)  ? "No Paper" : "Paper",
 		       (status & LP_PERRORP) ? "No Error" : "Error");
 	}
 #endif
-	return 0;
+	return pp;
 }
 
-static void printer_disconnect(struct usb_device *dev)
+static void printer_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct pp_usb_data *pp = dev->private;
+	struct pp_usb_data *pp = ptr;
 
 	if (pp->isopen) {
 		/* better let it finish - the release will do whats needed */
@@ -395,7 +391,6 @@
 	}
 	minor_data[pp->minor] = NULL;
 	kfree(pp);
-	dev->private = NULL;		/* just in case */
 }
 
 static struct file_operations usb_printer_fops = {
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
--- v2.3.24/linux/drivers/usb/proc_usb.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/usb/proc_usb.c	Thu Oct 28 14:34:46 1999
@@ -62,8 +62,8 @@
 
 
 static char *format_topo =
-/* T:  Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd If#=ddd MxCh=dd Driver=%s */
-  "T:  Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s If#=%3d MxCh=%2d Driver=%s\n";
+/* T:  Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
+  "T:  Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
 
 static char *format_bandwidth =
 /* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
@@ -83,7 +83,7 @@
   
 static char *format_iface =
 /* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx */
-  "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
+  "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
 
 static char *format_endpt =
 /* E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
@@ -161,9 +161,12 @@
 	return 0;
 }
 
-static int usb_dump_interface_descriptor (const struct usb_interface_descriptor *desc,
-						char *buf, int *len)
+static int usb_dump_interface_descriptor (const struct usb_interface *iface,
+						int setno, char *buf, int *len)
 {
+	struct usb_interface_descriptor *desc =
+	    &iface->altsetting[setno];
+
 	*len += sprintf (buf + *len, format_iface,
 		desc->bInterfaceNumber,
 		desc->bAlternateSetting,
@@ -171,22 +174,25 @@
 		desc->bInterfaceClass,
 		class_decode (desc->bInterfaceClass),
 		desc->bInterfaceSubClass,
-		desc->bInterfaceProtocol
+		desc->bInterfaceProtocol,
+		iface->driver ? iface->driver->name : "(none)"
 		);
 
 	return (*len >= DUMP_LIMIT) ? -1 : 0;
 }
 
-static int usb_dump_interface (const struct usb_interface_descriptor *interface,
-				char *buf, int *len)
+static int usb_dump_interface (const struct usb_interface *iface,
+				int setno, char *buf, int *len)
 {
 	int i;
+	struct usb_interface_descriptor *desc =
+	    &iface->altsetting[setno];
 
-	if (usb_dump_interface_descriptor (interface, buf, len) < 0)
+	if (usb_dump_interface_descriptor (iface, setno, buf, len) < 0)
 		return -1;
 
-	for (i = 0; i < interface->bNumEndpoints; i++) {
-		if (usb_dump_endpoint (interface->endpoint + i, buf, len) < 0)
+	for (i = 0; i < desc->bNumEndpoints; i++) {
+		if (usb_dump_endpoint (desc->endpoint + i, buf, len) < 0)
 			return -1;
 	}
 
@@ -234,7 +240,7 @@
 			break;
 
 		for (j = 0; j < interface->num_altsetting; j++)
-			if (usb_dump_interface (interface->altsetting + j, buf, len) < 0)
+			if (usb_dump_interface (interface, j, buf, len) < 0)
 				return -1;
 	}
 
@@ -349,9 +355,7 @@
 		level, parent_devnum, index, count,
 		usbdev->devnum,
 		usbdev->slow ? "1.5" : "12 ",
-		usbdev->ifnum, usbdev->maxchild,
-		usbdev->driver ? usbdev->driver->name :
-		(level == 0) ? "(root hub)" : "(none)"
+		usbdev->maxchild
 		);
 		/*
 		 * level = topology-tier level;
@@ -1036,21 +1040,21 @@
 		return -1;
 	}
 
-	driversdir = create_proc_entry ("drivers", 0, usbdir);
+	driversdir = create_proc_read_entry("drivers", 0, usbdir,
+					usb_driver_list_dump, NULL);
 	if (!driversdir) {
 		printk ("proc_usb: cannot create /proc/bus/usb/drivers entry\n");
 		proc_usb_cleanup ();
 		return -1;
 	}
-	driversdir->read_proc = usb_driver_list_dump;
 
-	devicesdir = create_proc_entry ("devices", 0, usbdir);
+	devicesdir = create_proc_read_entry ("devices", 0, usbdir,
+					usb_bus_list_dump_devices, NULL);
 	if (!devicesdir) {
 		printk ("proc_usb: cannot create /proc/bus/usb/devices entry\n");
 		proc_usb_cleanup ();
 		return -1;
 	}
-	devicesdir->read_proc = usb_bus_list_dump_devices;
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/usb-core.c linux/drivers/usb/usb-core.c
--- v2.3.24/linux/drivers/usb/usb-core.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/usb/usb-core.c	Thu Oct 28 10:20:36 1999
@@ -83,6 +83,7 @@
  */
 void cleanup_drivers(void)
 {
+	usb_major_cleanup();
 #ifdef CONFIG_USB_PROC
 	proc_usb_cleanup ();
 #endif
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
--- v2.3.24/linux/drivers/usb/usb-serial.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/usb/usb-serial.c	Thu Oct 28 12:53:26 1999
@@ -67,8 +67,8 @@
 				/* into dynamically creating them at insertion time. */
 
 
-static int usb_serial_probe(struct usb_device *dev);
-static void usb_serial_disconnect(struct usb_device *dev);
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
+static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
 
 typedef enum {
 	unknown = 0,
@@ -441,7 +441,7 @@
 }
 
 
-static int usb_serial_probe(struct usb_device *dev)
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_serial_state *serial;
 	struct usb_interface_descriptor *interface;
@@ -466,18 +466,13 @@
 		}
 
 	if (type == unknown)
-		return (-1);	
+		return NULL;	
 
 	printk (KERN_INFO "USB serial converter detected.\n");
 
-	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-		printk (KERN_INFO " Failed usb_set_configuration: serial\n");
-		return (-1);
-	}
-
 	if (0>(serial_num = Get_Free_Serial())) {
 		debug_info("USB Serial: Too many devices connected\n");
-		return (-1);
+		return NULL;
 	}
 	
 	serial = &serial_state_table[serial_num];
@@ -485,10 +480,9 @@
        	memset(serial, 0, sizeof(serial));
        	serial->dev = dev;
 	serial->type = type;
-       	dev->private = serial;
 
 	/* we should have 1 bulk in, 1 bulk out, and 1 interrupt in endpoints */
-	interface = &dev->config[0].interface[0].altsetting[0];
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
 	for (i = 0; i < interface->bNumEndpoints; ++i) {
 		endpoint = &interface->endpoint[i];
 		
@@ -564,7 +558,7 @@
 	serial->present = 1;
 	MOD_INC_USE_COUNT;
 
-	return (0);
+	return serial;
 
 probe_error:
 	if (serial) {
@@ -575,13 +569,13 @@
 		if (serial->interrupt_in_buffer)
 			kfree (serial->interrupt_in_buffer);
 	}
-	return (-1);
+	return NULL;
 }
 
 
-static void usb_serial_disconnect(struct usb_device *dev)
+static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *)dev->private;
+	struct usb_serial_state *serial = (struct usb_serial_state *) ptr;
 
 	if (serial) {
 		if (!serial->present) {
@@ -610,7 +604,6 @@
 		serial->present = 0;
 		serial->active = 0;
 	}
-       	dev->private = NULL;
 	
 	MOD_DEC_USE_COUNT;
 
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.24/linux/drivers/usb/usb.c	Fri Oct 22 13:21:51 1999
+++ linux/drivers/usb/usb.c	Thu Oct 28 12:53:26 1999
@@ -3,6 +3,8 @@
  *
  * (C) Copyright Linus Torvalds 1999
  * (C) Copyright Johannes Erdfelt 1999
+ * (C) Copyright Andreas Gal 1999
+ * (C) Copyright Gregory P. Smith 1999
  *
  * NOTE! This is not actually a driver at all, rather this is
  * just a collection of helper routines that implement the
@@ -27,9 +29,12 @@
 
 #include "usb.h"
 
-static int usb_find_driver(struct usb_device *);
+/*
+ * Prototypes for the device driver probing/loading functions
+ */
+static void usb_find_drivers(struct usb_device *);
+static int  usb_find_interface_driver(struct usb_device *, unsigned int);
 static void usb_check_support(struct usb_device *);
-static void usb_driver_purge(struct usb_driver *, struct usb_device *);
 
 /*
  * We have a per-interface "registered driver" list.
@@ -37,6 +42,8 @@
 static LIST_HEAD(usb_driver_list);
 static LIST_HEAD(usb_bus_list);
 
+static struct usb_busmap busmap;
+
 static struct usb_driver *usb_minors[16];
 
 int usb_register(struct usb_driver *new_driver)
@@ -70,6 +77,44 @@
 	return 0;
 }
 
+/*
+ * This function is part of a depth-first search down the device tree,
+ * removing any instances of a device driver.
+ */
+static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
+{
+	int i;
+
+	if (!dev) {
+		printk(KERN_ERR "usbcore: null device being purged!!!\n");
+		return;
+	}
+
+	for (i=0; i<USB_MAXCHILDREN; i++)
+		if (dev->children[i])
+			usb_drivers_purge(driver, dev->children[i]);
+
+        if (!dev->actconfig)
+                return;
+                        
+        for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+                struct usb_interface *interface = &dev->actconfig->interface[i];
+		
+	        if (interface->driver == driver) {
+                        driver->disconnect(dev, interface->private_data);
+			usb_driver_release_interface(driver, interface);
+		        /*
+		         * This will go through the list looking for another
+		         * driver that can handle the device
+		         */
+                        usb_find_interface_driver(dev, i);
+                }
+	}
+}
+
+/*
+ * Unlink a driver from the driver list when it is unloaded
+ */
 void usb_deregister(struct usb_driver *driver)
 {
 	struct list_head *tmp;
@@ -89,45 +134,10 @@
 		struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);
 
 		tmp = tmp->next;
-		usb_driver_purge(driver, bus->root_hub);
+		usb_drivers_purge(driver, bus->root_hub);
 	}
 }
 
-/*
- * This function is part of a depth-first search down the device tree,
- * removing any instances of a device driver.
- */
-static void usb_driver_purge(struct usb_driver *driver,struct usb_device *dev)
-{
-	int i;
-
-	if (!dev) {
-		printk(KERN_ERR "usbcore: null device being purged!!!\n");
-		return;
-	}
-
-	for (i=0; i<USB_MAXCHILDREN; i++)
-		if (dev->children[i])
-			usb_driver_purge(driver, dev->children[i]);
-
-	/* now we check this device */
-	if (dev->driver == driver) {
-		/*
-		 * Note: this is not the correct way to do this, this
-		 * uninitializes and reinitializes EVERY driver
-		 */
-		printk(KERN_INFO "disconnect driverless device %d\n",
-			dev->devnum);
-		dev->driver->disconnect(dev);
-		dev->driver = NULL;
-
-		/*
-		 * This will go back through the list looking for a driver
-		 * that can handle the device
-		 */
-		usb_find_driver(dev);
-	}
-}
 
 /*
  * calc_bus_time:
@@ -222,6 +232,7 @@
 	bus->op = op;
 	bus->root_hub = NULL;
 	bus->hcpriv = NULL;
+	bus->busnum = -1;
 	bus->bandwidth_allocated = 0;
 	bus->bandwidth_int_reqs  = 0;
 	bus->bandwidth_isoc_reqs = 0;
@@ -241,16 +252,27 @@
 
 void usb_register_bus(struct usb_bus *bus)
 {
+	int busnum;
+
+	busnum = find_next_zero_bit(busmap.busmap, USB_MAXBUS, 1);
+	if (busnum < USB_MAXBUS) {
+		set_bit(busnum, busmap.busmap);
+		bus->busnum = busnum;
+	} else
+		printk(KERN_INFO "usb: too many bus'\n");
+
 	proc_usb_add_bus(bus);
 
 	/* Add it to the list of buses */
 	list_add(&bus->bus_list, &usb_bus_list);
 
-	printk("New USB bus registered\n");
+	printk("New USB bus registered, assigned bus number %d\n", bus->busnum);
 }
 
 void usb_deregister_bus(struct usb_bus *bus)
 {
+	printk("usbcore: USB bus %d deregistered\n", bus->busnum);
+
 	/*
 	 * NOTE: make sure that all the devices are removed by the
 	 * controller code, as well as having it call this when cleaning
@@ -259,6 +281,8 @@
 	list_del(&bus->bus_list);
 
 	proc_usb_remove_bus(bus);
+
+	clear_bit(bus->busnum, busmap.busmap);
 }
 
 /*
@@ -278,37 +302,123 @@
 		if (dev->children[i])
 			usb_check_support(dev->children[i]);
 
+        if (!dev->actconfig)
+                return;
+
 	/* now we check this device */
-	if (!dev->driver && dev->devnum > 0)
-		usb_find_driver(dev);
+        if (dev->devnum > 0)
+                for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+                        usb_find_interface_driver(dev, i);
+}
+
+
+/*
+ * This is intended to be used by usb device drivers that need to
+ * claim more than one interface on a device at once when probing
+ * (audio and acm are good examples).  No device driver should have
+ * to mess with the internal usb_interface or usb_device structure
+ * members.
+ */
+void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv)
+{
+	if (!iface || !driver)
+		return;
+
+	printk(KERN_DEBUG "usbcore: %s driver claimed interface %p\n", driver->name, iface);
+
+	iface->driver = driver;
+	iface->private_data = priv;
+} /* usb_driver_claim_interface() */
+
+/*
+ * This should be used by drivers to check other interfaces to see if
+ * they are available or not.
+ */
+int usb_interface_claimed(struct usb_interface *iface)
+{
+	if (!iface)
+		return 0;
+
+	return (iface->driver != NULL);
+} /* usb_interface_claimed() */
+
+/*
+ * This should be used by drivers to release their claimed interfaces
+ */
+void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
+{
+	/* this should never happen, don't release something that's not ours */
+	if (iface->driver != driver || !iface)
+		return;
+
+	iface->driver = NULL;
+	iface->private_data = NULL;
 }
 
 /*
  * This entrypoint gets called for each new device.
  *
  * We now walk the list of registered USB drivers,
- * looking for one that will accept this device as
- * his..
+ * looking for one that will accept this interface.
+ *
+ * The probe return value is changed to be a private pointer.  This way
+ * the drivers don't have to dig around in our structures to set the
+ * private pointer if they only need one interface. 
+ *
+ * Returns: 0 if a driver accepted the interface, -1 otherwise
  */
-static int usb_find_driver(struct usb_device *dev)
+static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
 {
 	struct list_head *tmp = usb_driver_list.next;
-
-	while (tmp != &usb_driver_list) {
-		struct usb_driver *driver = list_entry(tmp, struct usb_driver,
-						       driver_list);
-		tmp = tmp->next;
-		if (driver->probe(dev))
-			continue;
-		dev->driver = driver;
-		return 1;
+        struct usb_interface *interface;
+	
+	if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {
+		printk(KERN_ERR "usb-core: bad find_interface_driver params\n");
+		return -1;
 	}
 
-	/*
-	 * Ok, no driver accepted the device, so show the info
-	 * for debugging..
-	 */
-	return 0;
+	interface = &dev->actconfig->interface[ifnum];
+
+        if (usb_interface_claimed(interface))
+                return -1;
+
+        while (tmp != &usb_driver_list) {
+		void *private;
+                struct usb_driver *driver = list_entry(tmp, struct usb_driver,
+		  			               driver_list);
+                        
+                tmp = tmp->next;
+                if (!(private = driver->probe(dev, ifnum)))
+                        continue;
+		usb_driver_claim_interface(driver, interface, private);
+
+                return 0;
+        }
+        
+	return -1;
+}
+
+/*
+ * This entrypoint gets called for each new device.
+ *
+ * All interfaces are scanned for matching drivers.
+ */
+static void usb_find_drivers(struct usb_device *dev)
+{
+	unsigned ifnum;
+        unsigned rejected = 0;
+
+	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {
+		/* if this interface hasn't already been claimed */
+		if (!usb_interface_claimed(dev->actconfig->interface)) {
+			if (usb_find_interface_driver(dev, ifnum))
+				rejected++;
+		}
+	}
+ 
+	if (rejected) {
+		printk(KERN_DEBUG "usbcore: unhandled interfaces on device.\n");
+	}
 }
 
 /*
@@ -631,6 +741,7 @@
 {
 	dev->devnum = -1;
 	dev->slow = 0;
+	dev->actconfig = NULL;
 }
 
 /*
@@ -646,10 +757,18 @@
 
 	*pdev = NULL;
 
-	printk("USB disconnect on device %d\n", dev->devnum);
+	printk("usbcore: USB disconnect on device %d\n", dev->devnum);
 
-	if (dev->driver)
-		dev->driver->disconnect(dev);
+        if (dev->actconfig) {
+                for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+                        struct usb_interface *interface = &dev->actconfig->interface[i];
+			struct usb_driver *driver = interface->driver;
+		        if (driver) {
+			        driver->disconnect(dev, interface->private_data);
+				usb_driver_release_interface(driver, interface);
+                        }
+                }
+        }
 
 	/* Free up all the children.. */
 	for (i = 0; i < USB_MAXCHILDREN; i++) {
@@ -894,7 +1013,6 @@
 	if (err)
 		return err;
 
-	dev->ifnum = interface;
 	dev->actconfig->interface[interface].act_altsetting = alternate;
 	usb_set_maxpacket(dev);
 	return 0;
@@ -1113,9 +1231,14 @@
 	}
 
 	dev->actconfig = dev->config;
-	dev->ifnum = 0;
 	usb_set_maxpacket(dev);
 
+	/* we set the default configuration here */
+	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
+		printk(KERN_ERR "usbcore: failed to set default configuration\n");
+		return -1;
+	}
+
 	usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
 	usb_show_string(dev, "Product", dev->descriptor.iProduct);
 	usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
@@ -1123,14 +1246,8 @@
 	/* now that the basic setup is over, add a /proc/bus/usb entry */
 	proc_usb_add_device(dev);
 
-	if (!usb_find_driver(dev)) {
-		/*
-		 * Ok, no driver accepted the device, so show the info for
-		 * debugging
-		 */
-		printk(KERN_DEBUG "Unknown new USB device:\n");
-		usb_show_device(dev);
-	}
+	/* find drivers willing to handle this device */
+        usb_find_drivers(dev);
 
 	return 0;
 }
@@ -1226,12 +1343,12 @@
  * returns the current frame number for the parent USB bus/controller
  * of the given USB device.
  */
-int usb_get_current_frame_number (struct usb_device *usb_dev)
+int usb_get_current_frame_number(struct usb_device *usb_dev)
 {
 	return usb_dev->bus->op->get_frame_number (usb_dev);
 }
 
-int usb_init_isoc (struct usb_device *usb_dev,
+int usb_init_isoc(struct usb_device *usb_dev,
 			unsigned int pipe,
 			int frame_count,
 			void *context,
@@ -1302,7 +1419,7 @@
 	struct usb_driver *c = usb_minors[minor/16];
 	file->f_op = NULL;
 
-	if ((file->f_op = c->fops) && file->f_op->open)
+	if (c && (file->f_op = c->fops) && file->f_op->open)
 		return file->f_op->open(inode,file);
 	else
 		return -ENODEV;
@@ -1323,10 +1440,15 @@
 
 void usb_major_init(void)
 {
-	if (register_chrdev(180,"usb",&usb_fops)) {
+	if (register_chrdev(USB_MAJOR,"usb",&usb_fops)) {
 		printk("unable to get major %d for usb devices\n",
-		       MISC_MAJOR);
+		       USB_MAJOR);
 	}
+}
+
+void usb_major_cleanup(void)
+{
+	unregister_chrdev(USB_MAJOR, "usb");
 }
 
 
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.3.24/linux/drivers/usb/usb.h	Fri Oct 22 13:21:51 1999
+++ linux/drivers/usb/usb.h	Thu Oct 28 12:53:26 1999
@@ -175,6 +175,8 @@
 #include <linux/list.h>
 #include <linux/sched.h>
 
+#define USB_MAJOR 180
+
 extern int usb_hub_init(void);
 extern int usb_kbd_init(void);
 extern int usb_cpia_init(void);
@@ -235,6 +237,12 @@
 	unsigned long devicemap[128 / (8*sizeof(unsigned long))];
 };
 
+#define USB_MAXBUS		64
+
+struct usb_busmap {
+	unsigned long busmap[USB_MAXBUS / (8*sizeof(unsigned long))];
+};
+
 /*
  * This is a USB device descriptor.
  *
@@ -320,6 +328,9 @@
 
 	int act_altsetting;		/* active alternate setting */
 	int num_altsetting;		/* number of alternate settings */
+
+        struct usb_driver *driver;	/* driver */
+	void *private_data;
 };
 
 /* Configuration descriptor information.. */
@@ -348,8 +359,8 @@
 struct usb_driver {
 	const char *name;
 
-	int (*probe)(struct usb_device *);
-	void (*disconnect)(struct usb_device *);
+	void * (*probe)(struct usb_device *, unsigned int);
+	void (*disconnect)(struct usb_device *, void *);
 
 	struct list_head driver_list;
 
@@ -476,6 +487,8 @@
  * Allocated per bus we have
  */
 struct usb_bus {
+	int busnum;			/* Bus number (in order of reg) */
+
 	struct usb_devmap devmap;       /* Device map */
 	struct usb_operations *op;      /* Operations (specific to the HC) */
 	struct usb_device *root_hub;    /* Root hub */
@@ -510,11 +523,9 @@
 	struct usb_config_descriptor *actconfig;/* the active configuration */
 	int epmaxpacketin[16];		/* INput endpoint specific maximums */
 	int epmaxpacketout[16];		/* OUTput endpoint specific maximums */
-	int ifnum;			/* active interface number */
 
 	struct usb_device *parent;
 	struct usb_bus *bus;		/* Bus we're part of */
-	struct usb_driver *driver;	/* Driver */
 
 	struct usb_device_descriptor descriptor;/* Descriptor */
 	struct usb_config_descriptor *config;	/* All of the configs */
@@ -523,7 +534,6 @@
 	int string_langid;		/* language ID for strings */
   
 	void *hcpriv;			/* Host Controller private data */
-	void *private;			/* Upper layer private data */
 	void *audiopriv;		/* May be both audio and HID */
 	/* procfs entry */
 	struct proc_dir_entry *proc_entry;
@@ -543,6 +553,11 @@
 extern int usb_register(struct usb_driver *);
 extern void usb_deregister(struct usb_driver *);
 
+/* used these for multi-interface device registration */
+extern void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv);
+extern int usb_interface_claimed(struct usb_interface *iface);
+extern void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface);
+
 extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
 extern void usb_free_bus(struct usb_bus *);
 extern void usb_register_bus(struct usb_bus *);
@@ -620,6 +635,11 @@
 #define PIPE_INTERRUPT			1
 #define PIPE_CONTROL			2
 #define PIPE_BULK			3
+
+#define USB_ISOCHRONOUS		0
+#define USB_INTERRUPT		1
+#define USB_CONTROL		2
+#define USB_BULK		3
 
 #define usb_maxpacket(dev, pipe, out)	(out \
 				? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c
--- v2.3.24/linux/drivers/usb/usb_scsi.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/usb/usb_scsi.c	Thu Oct 28 12:53:26 1999
@@ -69,6 +69,7 @@
 	struct usb_scsi_filter  *filter;		/* filter driver */
 	void 			*fdata;			/* filter data */
 	unsigned int		flags;			/* from filter initially*/
+	__u8			ifnum;			/* interface number */
 	__u8			ep_in;			/* in endpoint */
 	__u8			ep_out;			/* out ....... */
 	__u8			ep_int;			/* interrupt . */
@@ -118,8 +119,8 @@
 
 static struct usb_scsi_filter *filters;
 
-static int scsi_probe(struct usb_device *dev);
-static void scsi_disconnect(struct usb_device *dev);
+static void * scsi_probe(struct usb_device *dev, unsigned int ifnum);
+static void scsi_disconnect(struct usb_device *dev, void *ptr);
 static struct usb_driver scsi_driver = {
 	"usb_scsi",
 	scsi_probe,
@@ -269,7 +270,7 @@
     cmd[1] = 4;
     result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
 			US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
-			0, us->pusb_dev->ifnum, cmd, sizeof(cmd), HZ*5);
+			0, us->ifnum, cmd, sizeof(cmd), HZ*5);
 
     /* long wait for reset */
 
@@ -324,7 +325,7 @@
 	    }
 	    result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
 				US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
-				0, us->pusb_dev->ifnum,
+				0, us->ifnum,
 				cmd, us->fixedlength, HZ*5);
 	    if (!done_start && (us->subclass == US_SC_UFI /*|| us->subclass == US_SC_8070*/)
 		 && cmd[0] == TEST_UNIT_READY && result) {
@@ -336,7 +337,7 @@
 		cmd[4] = 1;		/* start */
 		result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
 				US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
-				0, us->pusb_dev->ifnum,
+				0, us->ifnum,
 				cmd, us->fixedlength, HZ*5);
 		wait_ms(100);
 		retry++;
@@ -345,7 +346,7 @@
 	} else {
 	    result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
 				US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
-				0, us->pusb_dev->ifnum,
+				0, us->ifnum,
 	    			srb->cmnd, srb->cmd_len, HZ*5);
 	}
 	if (/*result != USB_ST_STALL &&*/ result != USB_ST_TIMEOUT)
@@ -374,7 +375,7 @@
 	while (retry--) {
 	    result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),
 	    			USB_REQ_GET_STATUS, USB_DIR_IN | USB_TYPE_STANDARD | USB_RT_DEVICE,
-				0, 0,
+				0, us->ifnum,
 				status, sizeof(status), HZ*5);
 	    if (result != USB_ST_TIMEOUT)
 		break;
@@ -479,7 +480,7 @@
 
     result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
 			US_BULK_RESET, USB_TYPE_CLASS | USB_RT_INTERFACE,
-			US_BULK_RESET_HARD, 0,
+			US_BULK_RESET_HARD, us->ifnum,
 			NULL, 0, HZ*5);
     if (result)
 	US_DEBUGP("Bulk hard reset failed %d\n", result);
@@ -1052,7 +1053,7 @@
     return 0;
 }	
 
-static int scsi_probe(struct usb_device *dev)
+static void * scsi_probe(struct usb_device *dev, unsigned int ifnum)
 {
     struct usb_interface_descriptor *interface;
     int i;
@@ -1098,11 +1099,11 @@
 	    protocol = US_PR_CB;
 	    subclass = US_SC_8070;	/* an assumption */
 	} else if (dev->descriptor.bDeviceClass != 0 ||
-	    dev->config[0].interface[0].altsetting[0].bInterfaceClass !=
+	    dev->actconfig->interface[ifnum].altsetting[0].bInterfaceClass !=
 		USB_CLASS_MASS_STORAGE ||
-	    dev->config[0].interface[0].altsetting[0].bInterfaceSubClass < US_SC_MIN ||
-	    dev->config[0].interface[0].altsetting[0].bInterfaceSubClass > US_SC_MAX) {
-	    return -1;
+	    dev->actconfig->interface[ifnum].altsetting[0].bInterfaceSubClass < US_SC_MIN ||
+	    dev->actconfig->interface[ifnum].altsetting[0].bInterfaceSubClass > US_SC_MAX) {
+	    return NULL;
 	}
 
 	/* now check if we have seen it before */
@@ -1130,12 +1131,12 @@
 	    printk(KERN_WARNING USB_SCSI "Out of memory\n");
 	    if (filter)
 		    filter->release(fdata);
-	    return -1;
+	    return NULL;
 	}
 	memset(ss, 0, sizeof(struct us_data));
     }
 
-    interface = &dev->config[0].interface[0].altsetting[0];
+    interface = &dev->actconfig->interface[ifnum].altsetting[0];
     ss->filter = filter;
     ss->fdata = fdata;
     ss->flags = flags;
@@ -1195,10 +1196,12 @@
     US_DEBUGP("Endpoints In %d Out %d Int %d\n",
 		ss->ep_in, ss->ep_out, ss->ep_int);
 
+    /* save the interface number */
+    ss->ifnum = ifnum;
+
     /* exit if strange looking */
 
-    if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) ||
-	usb_set_interface(dev, interface->bInterfaceNumber, 0) ||
+    if (usb_set_interface(dev, interface->bInterfaceNumber, 0) ||
 	!ss->ep_in || !ss->ep_out || (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
 	US_DEBUGP("Problems with device\n");
 	if (ss->host) {
@@ -1209,12 +1212,12 @@
 	if (filter)
 		filter->release(fdata);
 	kfree(ss);
-	return -1;			/* no endpoints */
+	return NULL;			/* no endpoints */
     }
 
-    if (dev->config[0].iConfiguration && usb_string(dev, dev->config[0].iConfiguration))
+    if (dev->actconfig->iConfiguration && usb_string(dev, dev->actconfig->iConfiguration))
 	US_DEBUGP("Configuration %s\n",
-		usb_string(dev, dev->config[0].iConfiguration));
+		usb_string(dev, dev->actconfig->iConfiguration));
     if (interface->iInterface && usb_string(dev, interface->iInterface))
 	US_DEBUGP("Interface %s\n",
 		usb_string(dev, interface->iInterface));
@@ -1268,7 +1271,7 @@
 	    if (filter)
 		    filter->release(fdata);
 	    kfree(ss);
-	    return -1;
+	    return NULL;
 	}
 	memcpy(htmplt, &my_host_template, sizeof(my_host_template));
 	ss->host_number = my_host_number++;
@@ -1284,7 +1287,7 @@
 	    /* shuttle E-USB */
 	    result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0),
 			1, 0xC0,
-			0, 0,
+			0, ss->ifnum,
 			qstat, 2, HZ*5);
 	    US_DEBUGP("C0 status %x %x\n", qstat[0], qstat[1]);
 	    init_waitqueue_head(&ss->ip_waitq);
@@ -1292,7 +1295,7 @@
 	    result = usb_request_irq(ss->pusb_dev, ss->irqpipe, pop_CBI_irq,
 				0, (void *)ss, &ss->irq_handle);
 	    if (result)
-	    	return -1;
+	    	return NULL;
 	    interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6);
 
 	} else if (ss->protocol == US_PR_CBI)
@@ -1314,7 +1317,7 @@
 		if (filter)
 			filter->release(fdata);
 		kfree(ss);
-		return -1;
+		return NULL;
 	    }
 
 	    /* wait for it to start */
@@ -1336,20 +1339,18 @@
 
     printk(KERN_INFO "USB SCSI device found at address %d\n", dev->devnum);
 
-    dev->private = ss;
-    return 0;
+    return ss;
 }
 
-static void scsi_disconnect(struct usb_device *dev)
+static void scsi_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct us_data *ss = dev->private;
+	struct us_data *ss = ptr;
 
 	if (!ss)
 	    return;
 	if (ss->filter)
 		ss->filter->release(ss->fdata);
 	ss->pusb_dev = NULL;
-	dev->private = NULL;		/* just in case */
 	MOD_DEC_USE_COUNT;
 }
 
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c
--- v2.3.24/linux/drivers/usb/uss720.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/usb/uss720.c	Thu Oct 28 12:53:26 1999
@@ -538,7 +538,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int uss720_probe(struct usb_device *usbdev)
+static void * uss720_probe(struct usb_device *usbdev, unsigned int ifnum)
 {
         struct usb_interface_descriptor *interface;
         struct usb_endpoint_descriptor *endpoint;
@@ -552,31 +552,16 @@
         if ((usbdev->descriptor.idVendor != 0x047e || usbdev->descriptor.idProduct != 0x1001) &&
 	    (usbdev->descriptor.idVendor != 0x0557 || usbdev->descriptor.idProduct != 0x2001) &&
 	    (usbdev->descriptor.idVendor != 0x0729 || usbdev->descriptor.idProduct != 0x1284))
-                return -1;
+                return NULL;
 
-        /* We don't handle multiple configurations */
-        if (usbdev->descriptor.bNumConfigurations != 1)
-                return -1;
+        /* our known interfaces have 3 alternate settings */
+        if (usbdev->actconfig->interface[ifnum].num_altsetting != 3)
+                return NULL;
 
-        /* We don't handle multiple interfaces */
-        if (usbdev->config[0].bNumInterfaces != 1)
-                return -1;
-
-        /* We don't handle multiple interfaces */
-        if (usbdev->config[0].interface[0].num_altsetting != 3)
-                return -1;
-
-        printk(KERN_DEBUG "uss720: set configuration\n");
-        usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue);
-
-        i = usb_set_interface(usbdev, 0, 2);
+        i = usb_set_interface(usbdev, ifnum, 2);
         printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
 
-        interface = &usbdev->config[0].interface[0].altsetting[2];
-
-        //printk(KERN_DEBUG "uss720: get interface\n");
-        //i = usb_get_interface(usbdev, 0);
-        //printk(KERN_DEBUG "uss720: is in alternate setting %d\n", i);
+        interface = &usbdev->actconfig->interface[ifnum].altsetting[2];
 
 	/*
 	 * Allocate parport interface 
@@ -584,13 +569,13 @@
 	printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
 
 	if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
-		return -1;
+		return NULL;
 	if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
-		kfree(priv);
-		return -1;
+		printk(KERN_WARNING "usb-uss720: could not register parport\n");
+		goto probe_abort;
 	}
+
 	pp->private_data = priv;
-        usbdev->private = pp;
 	priv->usbdev = usbdev;
 	pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
 
@@ -612,26 +597,28 @@
 				  pp, &priv->irqhandle);
 	if (i) {
 		printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
-		/* FIXME: undo some stuff and free some memory. */
-		return -1;
+		goto probe_abort_port;
 	}
 #endif
         parport_proc_register(pp);
         parport_announce_port(pp);
 
 	MOD_INC_USE_COUNT;
-        return 0;
+        return pp;
+
+probe_abort_port:
+	parport_unregister_port(pp);
+probe_abort:
+	kfree(priv);
+	return NULL;
 }
 
-static void uss720_disconnect(struct usb_device *usbdev)
+static void uss720_disconnect(struct usb_device *usbdev, void *ptr)
 {
-	struct parport *pp = (struct parport *)usbdev->private;
+	struct parport *pp = (struct parport *)ptr;
 	struct parport_uss720_private *priv = pp->private_data;
 
-#if 0
 	usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
-#endif
-        usbdev->private = NULL;
         priv->usbdev = NULL;
 	parport_proc_unregister(pp);
 	parport_unregister_port(pp);
diff -u --recursive --new-file v2.3.24/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.3.24/linux/drivers/video/acornfb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/acornfb.c	Thu Oct 28 10:16:02 1999
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/video/acorn.c
+ * linux/drivers/video/acornfb.c
  *
  * Copyright (C) 1998,1999 Russell King
  *
@@ -36,6 +36,8 @@
 #include <video/fbcon-cfb16.h>
 #include <video/fbcon-cfb32.h>
 
+#include "acornfb.h"
+
 /*
  * Default resolution.
  * NOTE that it has to be supported in the table towards
@@ -43,78 +45,40 @@
  */
 #define DEFAULT_XRES	640
 #define DEFAULT_YRES	480
-
 /*
- * define this to debug the video mode selection
+ * The order here defines which BPP we
+ * pick depending on which resolutions
+ * we have configured.
  */
-#undef DEBUG_MODE_SELECTION
-
-#if defined(HAS_VIDC20)
-#define VIDC_PALETTE_SIZE	256
-#define VIDC_NAME		"VIDC20"
-#elif defined(HAS_VIDC)
-#include <asm/memc.h>
-#define VIDC_PALETTE_SIZE	16
-#define VIDC_NAME		"VIDC"
+#if   defined(FBCON_HAS_CFB4)
+# define DEFAULT_BPP	4
+#elif defined(FBCON_HAS_CFB8)
+# define DEFAULT_BPP	8
+#elif defined(FBCON_HAS_CFB16)
+# define DEFAULT_BPP	16
+#elif defined(FBCON_HAS_CFB2)
+# define DEFAULT_BPP	2
+#elif defined(FBCON_HAS_MFB)
+# define DEFAULT_BPP	1
+#else
+#error No suitable framebuffers configured
 #endif
 
-#define EXTEND8(x) ((x)|(x)<<8)
-#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
-
-struct vidc20_palette {
-	u_int red:8;
-	u_int green:8;
-	u_int blue:8;
-	u_int ext:4;
-	u_int unused:4;
-};
-
-struct vidc_palette {
-	u_int red:4;
-	u_int green:4;
-	u_int blue:4;
-	u_int trans:1;
-	u_int sbz1:13;
-	u_int reg:4;
-	u_int sbz2:2;
-};
-
-union palette {
-	struct vidc20_palette	vidc20;
-	struct vidc_palette	vidc;
-	u_int	p;
-};
 
-struct acornfb_par {
-	unsigned long	screen_base;
-	unsigned long	screen_base_p;
-	unsigned long	screen_end;
-	unsigned long	screen_size;
-	unsigned int	dram_size;
-	unsigned int	vram_half_sam;
-	unsigned int	palette_size;
-	  signed int	montype;
-	  signed int	currcon;
-	unsigned int	allow_modeset	: 1;
-	unsigned int	using_vram	: 1;
-	unsigned int	dpms		: 1;
-
-	union palette palette[VIDC_PALETTE_SIZE];
-
-	union {
-		unsigned short cfb16[16];
-		unsigned long  cfb32[16];
-	} cmap;
-};
+/*
+ * define this to debug the video mode selection
+ */
+#undef DEBUG_MODE_SELECTION
 
 /*
  * Translation from RISC OS monitor types to actual
  * HSYNC and VSYNC frequency ranges.  These are
- * probably not right...
+ * probably not right, but they're the best info I
+ * have.  Allow 1% either way on the nominal for TVs.
  */
 #define NR_MONTYPES	6
 static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
-	{ 15625, 15625, 50, 50, 0 },	/* TV		*/
+	{ 15469, 15781, 49, 51, 0 },	/* TV		*/
 	{     0, 99999,  0, 99, 0 },	/* Multi Freq	*/
 	{ 58608, 58608, 64, 64, 0 },	/* Hi-res mono	*/
 	{ 30000, 70000, 60, 60, 0 },	/* VGA		*/
@@ -125,56 +89,14 @@
 static struct display global_disp;
 static struct fb_info fb_info;
 static struct acornfb_par current_par;
+static struct vidc_timing current_vidc;
 static struct fb_var_screeninfo __initdata init_var = {};
 
 extern int acornfb_depth;	/* set by setup.c */
 extern unsigned int vram_size;	/* set by setup.c */
 
-
-static struct vidc_timing {
-	u_int	h_cycle;
-	u_int	h_sync_width;
-	u_int	h_border_start;
-	u_int	h_display_start;
-	u_int	h_display_end;
-	u_int	h_border_end;
-	u_int	h_interlace;
-
-	u_int	v_cycle;
-	u_int	v_sync_width;
-	u_int	v_border_start;
-	u_int	v_display_start;
-	u_int	v_display_end;
-	u_int	v_border_end;
-
-	u_int	control;
-
-	/* VIDC20 only */
-	u_int	pll_ctl;
-} current_vidc;
-
 #ifdef HAS_VIDC
 
-#define VID_CTL_VS_NVSYNC	(1 << 3)
-#define VID_CTL_HS_NHSYNC	(1 << 2)
-#define VID_CTL_24MHz		(0)
-#define VID_CTL_25MHz		(1)
-#define VID_CTL_36MHz		(2)
-
-#define VIDC_CTRL_INTERLACE	(1 << 6)
-#define VIDC_CTRL_FIFO_0_4	(0 << 4)
-#define VIDC_CTRL_FIFO_1_5	(1 << 4)
-#define VIDC_CTRL_FIFO_2_6	(2 << 4)
-#define VIDC_CTRL_FIFO_3_7	(3 << 4)
-#define VIDC_CTRL_1BPP		(0 << 2)
-#define VIDC_CTRL_2BPP		(1 << 2)
-#define VIDC_CTRL_4BPP		(2 << 2)
-#define VIDC_CTRL_8BPP		(3 << 2)
-#define VIDC_CTRL_DIV3		(0 << 0)
-#define VIDC_CTRL_DIV2		(1 << 0)
-#define VIDC_CTRL_DIV1_5	(2 << 0)
-#define VIDC_CTRL_DIV1		(3 << 0)
-
 /* CTL     VIDC	Actual
  * 24.000  0	 8.000
  * 25.175  0	 8.392
@@ -411,162 +333,7 @@
 #endif
 
 #ifdef HAS_VIDC20
-/*
- * VIDC20 registers
- */
-#define VIDC20_CTRL		0xe0000000
-#define VIDC20_CTRL_PIX_VCLK	(0 << 0)
-#define VIDC20_CTRL_PIX_HCLK	(1 << 0)
-#define VIDC20_CTRL_PIX_RCLK	(2 << 0)
-#define VIDC20_CTRL_PIX_CK	(0 << 2)
-#define VIDC20_CTRL_PIX_CK2	(1 << 2)
-#define VIDC20_CTRL_PIX_CK3	(2 << 2)
-#define VIDC20_CTRL_PIX_CK4	(3 << 2)
-#define VIDC20_CTRL_PIX_CK5	(4 << 2)
-#define VIDC20_CTRL_PIX_CK6	(5 << 2)
-#define VIDC20_CTRL_PIX_CK7	(6 << 2)
-#define VIDC20_CTRL_PIX_CK8	(7 << 2)
-#define VIDC20_CTRL_1BPP	(0 << 5)
-#define VIDC20_CTRL_2BPP	(1 << 5)
-#define VIDC20_CTRL_4BPP	(2 << 5)
-#define VIDC20_CTRL_8BPP	(3 << 5)
-#define VIDC20_CTRL_16BPP	(4 << 5)
-#define VIDC20_CTRL_32BPP	(6 << 5)
-#define VIDC20_CTRL_FIFO_NS	(0 << 8)
-#define VIDC20_CTRL_FIFO_4	(1 << 8)
-#define VIDC20_CTRL_FIFO_8	(2 << 8)
-#define VIDC20_CTRL_FIFO_12	(3 << 8)
-#define VIDC20_CTRL_FIFO_16	(4 << 8)
-#define VIDC20_CTRL_FIFO_20	(5 << 8)
-#define VIDC20_CTRL_FIFO_24	(6 << 8)
-#define VIDC20_CTRL_FIFO_28	(7 << 8)
-#define VIDC20_CTRL_INT		(1 << 12)
-#define VIDC20_CTRL_DUP		(1 << 13)
-#define VIDC20_CTRL_PDOWN	(1 << 14)
-
-#define VIDC20_ECTL		0xc0000000
-#define VIDC20_ECTL_REG(x)	((x) & 0xf3)
-#define VIDC20_ECTL_ECK		(1 << 2)
-#define VIDC20_ECTL_REDPED	(1 << 8)
-#define VIDC20_ECTL_GREENPED	(1 << 9)
-#define VIDC20_ECTL_BLUEPED	(1 << 10)
-#define VIDC20_ECTL_DAC		(1 << 12)
-#define VIDC20_ECTL_LCDGS	(1 << 13)
-#define VIDC20_ECTL_HRM		(1 << 14)
-
-#define VIDC20_ECTL_HS_MASK	(3 << 16)
-#define VIDC20_ECTL_HS_HSYNC	(0 << 16)
-#define VIDC20_ECTL_HS_NHSYNC	(1 << 16)
-#define VIDC20_ECTL_HS_CSYNC	(2 << 16)
-#define VIDC20_ECTL_HS_NCSYNC	(3 << 16)
-
-#define VIDC20_ECTL_VS_MASK	(3 << 18)
-#define VIDC20_ECTL_VS_VSYNC	(0 << 18)
-#define VIDC20_ECTL_VS_NVSYNC	(1 << 18)
-#define VIDC20_ECTL_VS_CSYNC	(2 << 18)
-#define VIDC20_ECTL_VS_NCSYNC	(3 << 18)
-
-#define VIDC20_DCTL		0xf0000000
-/* 0-9 = number of words in scanline */
-#define VIDC20_DCTL_SNA		(1 << 12)
-#define VIDC20_DCTL_HDIS	(1 << 13)
-#define VIDC20_DCTL_BUS_NS	(0 << 16)
-#define VIDC20_DCTL_BUS_D31_0	(1 << 16)
-#define VIDC20_DCTL_BUS_D63_32	(2 << 16)
-#define VIDC20_DCTL_BUS_D63_0	(3 << 16)
-#define VIDC20_DCTL_VRAM_DIS	(0 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK	(1 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK2	(2 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK4	(3 << 18)
-
-#define acornfb_valid_pixrate(rate) (1)
-
-/*
- * Try to find the best PLL parameters for the pixel clock.
- * This algorithm seems to give best predictable results,
- * and produces the same values as detailed in the VIDC20
- * data sheet.
- */
-static inline u_int
-acornfb_vidc20_find_pll(u_int pixclk)
-{
-	u_int r, best_r = 2, best_v = 2;
-	int best_d = 0x7fffffff;
-
-	for (r = 2; r <= 32; r++) {
-		u_int rr, v, p;
-		int d;
-
-		rr = 41667 * r;
-
-		v = (rr + pixclk / 2) / pixclk;
-
-		if (v > 32 || v < 2)
-			continue;
-
-		p = (rr + v / 2) / v;
-
-		d = pixclk - p;
-
-		if (d < 0)
-			d = -d;
-
-		if (d < best_d) {
-			best_d = d;
-			best_v = v - 1;
-			best_r = r - 1;
-		}
-
-		if (d == 0)
-			break;
-	}
-
-	return best_v << 8 | best_r;
-}
-
-static inline void
-acornfb_vidc20_find_rates(struct vidc_timing *vidc,
-			  struct fb_var_screeninfo *var)
-{
-	u_int div, bandwidth;
-
-	/* Select pixel-clock divisor to keep PLL in range */
-	div = var->pixclock / 9090; /*9921*/
-
-	/* Limit divisor */
-	if (div == 0)
-		div = 1;
-	if (div > 8)
-		div = 8;
-
-	/* Encode divisor to VIDC20 setting */
-	switch (div) {
-	case 1:	vidc->control |= VIDC20_CTRL_PIX_CK;  break;
-	case 2:	vidc->control |= VIDC20_CTRL_PIX_CK2; break;
-	case 3:	vidc->control |= VIDC20_CTRL_PIX_CK3; break;
-	case 4:	vidc->control |= VIDC20_CTRL_PIX_CK4; break;
-	case 5:	vidc->control |= VIDC20_CTRL_PIX_CK5; break;
-	case 6:	vidc->control |= VIDC20_CTRL_PIX_CK6; break;
-	case 7:	vidc->control |= VIDC20_CTRL_PIX_CK7; break;
-	case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break;
-	}
-
-	/* Calculate bandwidth */
-	bandwidth = var->pixclock * 8 / var->bits_per_pixel;
-
-	/* Encode bandwidth as VIDC20 setting */
-	if (bandwidth > 33334)
-		vidc->control |= VIDC20_CTRL_FIFO_16;	/* < 30.0MB/s */
-	else if (bandwidth > 26666)
-		vidc->control |= VIDC20_CTRL_FIFO_20;	/* < 37.5MB/s */
-	else if (bandwidth > 22222)
-		vidc->control |= VIDC20_CTRL_FIFO_24;	/* < 45.0MB/s */
-	else
-		vidc->control |= VIDC20_CTRL_FIFO_28;	/* > 45.0MB/s */
-
-	/* Find the PLL values */
-	vidc->pll_ctl  = acornfb_vidc20_find_pll(var->pixclock / div);
-}
+#include <asm/arch/acornfb.h>
 
 /* VIDC20 has a different set of rules from the VIDC:
  *  hcr  : must be multiple of 4
@@ -600,7 +367,7 @@
 	vidc.v_display_start	= vidc.v_border_start;
 	vidc.v_display_end	= vidc.v_display_start + var->yres;
 	vidc.v_border_end	= vidc.v_display_end;
-	vidc.control		= VIDC20_CTRL_PIX_VCLK;
+	vidc.control		= acornfb_default_control();
 
 	vcr = var->vsync_len + var->upper_margin + var->yres +
 	      var->lower_margin;
@@ -649,7 +416,7 @@
 
 	outl(fsize, IOMD_FSIZE);
 
-	ext_ctl = VIDC20_ECTL_DAC | VIDC20_ECTL_REG(3);
+	ext_ctl = acornfb_default_econtrol();
 
 	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
 		ext_ctl |= VIDC20_ECTL_HS_HSYNC;
@@ -744,7 +511,7 @@
  * the resolution to fit the rules.
  */
 static int
-acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con)
+acornfb_adjust_timing(struct fb_var_screeninfo *var, int con)
 {
 	u_int font_line_len;
 	u_int fontht;
@@ -828,17 +595,7 @@
 		if (var->yoffset + var->yres > var->yres_virtual)
 			var->yoffset = var->yres_virtual - var->yres;
 	}
-	return 0;
-}
 
-/*
- * After selecting the timing parameters, adjust
- * the timing to suit the chip.
- * NOTE! Only minor adjustments should be made here.
- */
-static void
-acornfb_post_adjust_timing(struct fb_var_screeninfo *var)
-{
 	/* hsync_len must be even */
 	var->hsync_len = (var->hsync_len + 1) & ~1;
 
@@ -865,6 +622,31 @@
 
 	if (var->vsync_len < 1)
 		var->vsync_len = 1;
+
+	return 0;
+}
+
+static int
+acornfb_validate_timing(struct fb_var_screeninfo *var,
+			struct fb_monspecs *monspecs)
+{
+	unsigned long hs, vs;
+
+	/*
+	 * hs(Hz) = 10^12 / (pixclock * xtotal)
+	 * vs(Hz) = hs(Hz) / ytotal
+	 *
+	 * No need to do long long divisions or anything
+	 * like that if you factor it correctly
+	 */
+	hs = 1953125000 / var->pixclock;
+	hs = hs * 512 /
+	     (var->xres + var->left_margin + var->right_margin + var->hsync_len);
+	vs = hs /
+	     (var->yres + var->upper_margin + var->lower_margin + var->vsync_len);
+
+	return (vs >= monspecs->vfmin && vs <= monspecs->vfmax &&
+		hs >= monspecs->hfmin && hs <= monspecs->hfmax) ? 0 : -EINVAL;
 }
 
 static inline void
@@ -1064,10 +846,18 @@
 		return -EINVAL;
 
 	/*
-	 * Validate and adjust the resolution
-	 * before using it.
+	 * Validate and adjust the resolution to
+	 * match the video generator hardware.
+	 */
+	err = acornfb_adjust_timing(var, con);
+	if (err)
+		return err;
+
+	/*
+	 * Validate the timing against the
+	 * monitor hardware.
 	 */
-	err = acornfb_pre_adjust_timing(var, con);
+	err = acornfb_validate_timing(var, &fb_info.monspecs);
 	if (err)
 		return err;
 
@@ -1110,11 +900,6 @@
 	var->blue          = var->red;
 	var->transp.length = 1;
 #endif
-	/*
-	 * Now adjust the timing parameters
-	 */
-	acornfb_post_adjust_timing(var);
-
 	return 0;
 }
 
@@ -1403,7 +1188,9 @@
 
 			acornfb_palette_write(i, p);
 		}
-	} else {
+	}
+#ifdef FBCON_HAS_CFB16
+	else {
 		p.p = 0;
 
 		for (i = 0; i < 256; i++) {
@@ -1417,220 +1204,68 @@
 			acornfb_palette_write(i, current_par.palette[i]);
 		}
 	}
+#endif
 }
 
 /*
  * Everything after here is initialisation!!!
  */
-struct modey_params {
-	u_int	y_res;
-	u_int	u_margin;
-	u_int	b_margin;
-	u_int	vsync_len;
-	u_int	vf;
-};
-
-struct modex_params {
-	u_int	x_res;
-	u_int	l_margin;
-	u_int	r_margin;
-	u_int	hsync_len;
-	u_int	clock;
-	u_int	hf;
-	const struct modey_params *modey;
-};
-
-static const struct modey_params modey_640_15600[] __initdata = {
-	{  250,  38,  21,  3,  50 },	/*  640x 250, 50Hz */
-	{  256,  35,  18,  3,  50 },	/*  640x 256, 50Hz */
-	{    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_640_26800[] __initdata = {
-	{  512,  18,   1,  3,  50 },	/*  640x 512, 50Hz */
-	{    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_640_31500[] __initdata = {
-	{  250, 109,  88,  2,  70 },	/*  640x 250, 70Hz */
-	{  256, 106,  85,  2,  70 },	/*  640x 256, 70Hz */
-	{  352,  58,  37,  2,  70 },	/*  640x 352, 70Hz */
-	{  480,  32,  11,  2,  60 },	/*  640x 480, 60Hz */
-	{    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_800_35200[] __initdata = {
-	{  600,  22,   1,  2,  56 },	/*  800x 600, 56Hz */
-	{    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_896_21800[] __initdata = {
-	{  352,   9,   0,  3,  60 },	/*  896x 352, 60Hz */
-	{    0,   0,   0,  0,   0 }
-};
-
-/* everything after here is not supported */
-static const struct modey_params modey_1024_uk[] __initdata = {
-	{  768,   0,   0,  0,   0 },	/* 1024x 768 */
-	{    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_1056_uk[] __initdata = {
-	{  250,   0,   0,  0,   0 },	/* 1056x 250 */
-	{  256,   0,   0,  0,   0 },	/* 1056x 256 */
-	{    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_1152_uk[] __initdata = {
-	{  896,   0,   0,  0,   0 },	/* 1152x 896 */
-	{    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_1280_63600[] __initdata = {
-	{ 1024,   0,   0,  0,  60 },	/* 1280x1024, 60Hz */
-	{    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_1600_uk[] __initdata = {
-	{ 1280,   0,   0,  0,   0 },	/* 1600x1280 */
-	{    0,   0,   0,  0,   0 }
-};
-
-/*
- * Horizontal video programming requirements.
- * This table is searched for the required horizontal
- * and required frequency, and then the tables above
- * are then searched for the required vertical
- * resolution.
- *
- * NOTE! we can match multiple entries, so we search
- * all horizontal entries for which the hfreq is within
- * the monitor's range.
- */
-static const struct modex_params modex_params[] __initdata = {
-	{						/* X:  640, 15.6kHz */
-		 640,  185, 123,  76, 16000, 15625, modey_640_15600
-	},
-	{						/* X:  640, 26.8kHz */
-		 640,  113,  87,  56, 24000, 26800, modey_640_26800
-	},
-	{						/* X:  640, 31.5kHz */
-		 640,   48,  16,  96, 25175, 31500, modey_640_31500
-	},
-	{						/* X:  800, 35.2kHz */
-		 800,  101,  23, 100, 36000, 35200, modey_800_35200
-	},
-	{						/* X:  896, 21.8kHz */
-		 896,   59,  27, 118, 24000, 21800, modey_896_21800
-	},
-	{						/* X: 1024 */
-		1024,    0,   0,   0,     0,     0, modey_1024_uk
-	},
-	{						/* X: 1056 */
-		1056,    0,   0,   0,     0,     0, modey_1056_uk
-	},
-	{						/* X: 1152 */
-		1152,    0,   0,   0,     0,     0, modey_1152_uk
-	},
-	{						/* X: 1280, 63.6kHz */
-		1280,    0,   0,   0,     0, 63600, modey_1280_63600
-	},
-	{						/* X: 1600 */
-		1600,    0,   0,   0,     0,     0, modey_1600_uk
-	},
-	{
+static struct fb_videomode modedb[] __initdata = {
+	{	/* 640x250 @ 50Hz, 15.6 kHz hsync */
+		NULL, 50, 640, 250, 62500, 185, 123,  38, 21,  76, 3,
 		0,
-	}
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x256 @ 50Hz, 15.6 kHz hsync */
+		NULL, 50, 640, 256, 62500, 185, 123,  35, 18,  76, 3,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x512 @ 50Hz, 26.8 kHz hsync */
+		NULL, 50, 640, 512, 41667, 113,  87,  18,  1,  56, 3,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x250 @ 70Hz, 31.5 kHz hsync */
+		NULL, 70, 640, 250, 39722,  48,  16, 109, 88,  96, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x256 @ 70Hz, 31.5 kHz hsync */
+		NULL, 70, 640, 256, 39722,  48,  16, 106, 85,  96, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x352 @ 70Hz, 31.5 kHz hsync */
+		NULL, 70, 640, 352, 39722,  48,  16,  58, 37,  96, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x480 @ 60Hz, 31.5 kHz hsync */
+		NULL, 60, 640, 480, 39722,  48,  16,  32, 11,  96, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 800x600 @ 56Hz, 35.2 kHz hsync */
+		NULL, 56, 800, 600, 27778, 101,  23,  22,  1, 100, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 896x352 @ 60Hz, 21.8 kHz hsync */
+		NULL, 60, 896, 352, 41667,  59,  27,   9,  0, 118, 3,
+		0,
+		FB_VMODE_NONINTERLACED
+	},
 };
 
-static int __init 
-acornfb_lookup_timing(struct fb_var_screeninfo *var)
-{
-	const struct modex_params *x;
-	const struct modey_params *y;
-
-	/*
-	 * We must adjust the resolution parameters
-	 * before selecting the timing parameters.
-	 */
-	acornfb_pre_adjust_timing(var, -1);
-
-	for (x = modex_params; x->x_res; x++) {
-
-		/*
-		 * Is this resolution one we're looking for?
-		 */
-		if (x->x_res != var->xres)
-			continue;
-
-		/*
-		 * Is the hsync frequency ok for our monitor?
-		 */
-		if (x->hf > fb_info.monspecs.hfmax ||
-		    x->hf < fb_info.monspecs.hfmin)
-			continue;
-
-		/*
-		 * Try to find a vertical resolution
-		 */
-		for (y = x->modey; y->y_res; y++) {
-			/*
-			 * Is this resolution one we're looking for?
-			 */
-			if (y->y_res != var->yres)
-				continue;
-
-			/*
-			 * Is the vsync frequency ok for our monitor?
-			 */
-			if (y->vf > fb_info.monspecs.vfmax ||
-			    y->vf < fb_info.monspecs.vfmin)
-				continue;
-
-			goto found;
-		}
-	}
-
-	var->pixclock = 0;
-
-	return -EINVAL;
-
-found:
-	/*
-	 * Why is pixclock in picoseconds?
-	 */
-	switch (x->clock) {
-	case 36000: var->pixclock =  27778;	break;
-	case 25175: var->pixclock =  39722;	break;
-	case 24000: var->pixclock =  41667;	break;
-	case 16000: var->pixclock =  62500;	break;
-	case 12000: var->pixclock =  83333;	break;
-	case  8000: var->pixclock = 125000;	break;
-	default:    var->pixclock =      0;     break;
-	}
-
-#ifdef DEBUG_MODE_SELECTION
-	printk(KERN_DEBUG "Found %dx%d at %d.%3dkHz, %dHz, pix %d\n",
-		x->x_res, y->y_res,
-		x->hf / 1000, x->hf % 1000,
-		y->vf, var->pixclock);
-#endif
-
-	var->left_margin	= x->l_margin;
-	var->right_margin	= x->r_margin;
-	var->upper_margin	= y->u_margin;
-	var->lower_margin	= y->b_margin;
-	var->hsync_len		= x->hsync_len;
-	var->vsync_len		= y->vsync_len;
-	var->sync		= 0;
-
-	/*
-	 * Now adjust the parameters we found
-	 */
-	acornfb_post_adjust_timing(var);
-
-	return 0;
-}
+static struct fb_videomode __initdata
+acornfb_default_mode = {
+	name:		NULL,
+	refresh:	60,
+	xres:		640,
+	yres:		480,
+	pixclock:	39722,
+	left_margin:	56,
+	right_margin:	16,
+	upper_margin:	34,
+	lower_margin:	9,
+	hsync_len:	88,
+	vsync_len:	2,
+	sync:		0,
+	vmode:		FB_VMODE_NONINTERLACED
+};
 
 static void __init 
 acornfb_init_fbinfo(void)
@@ -1659,20 +1294,6 @@
 	 * setup initial parameters
 	 */
 	memset(&init_var, 0, sizeof(init_var));
-	init_var.xres		   = DEFAULT_XRES;
-	init_var.yres		   = DEFAULT_YRES;
-
-#if   defined(FBCON_HAS_CFB4)
-	init_var.bits_per_pixel	   = 4;
-#elif defined(FBCON_HAS_CFB8)
-	init_var.bits_per_pixel    = 8;
-#elif defined(FBCON_HAS_CFB2)
-	init_var.bits_per_pixel    = 2;
-#elif defined(FBCON_HAS_MFB)
-	init_var.bits_per_pixel    = 1;
-#else
-#error No suitable framebuffers configured
-#endif
 
 #if defined(HAS_VIDC20)
 	init_var.red.length	   = 8;
@@ -1922,6 +1543,7 @@
 {
 	unsigned long size;
 	u_int h_sync, v_sync;
+	int rc, i;
 
 	acornfb_init_fbinfo();
 
@@ -1934,6 +1556,26 @@
 	fb_info.monspecs = monspecs[current_par.montype];
 	fb_info.monspecs.dpms = current_par.dpms;
 
+	/*
+	 * Try to select a suitable default mode
+	 */
+	for (i = 0; i < sizeof(modedb) / sizeof(*modedb); i++) {
+		unsigned long hs;
+
+		hs = modedb[i].refresh *
+		     (modedb[i].yres + modedb[i].upper_margin +
+		      modedb[i].lower_margin + modedb[i].vsync_len);
+		if (modedb[i].xres == DEFAULT_XRES &&
+		    modedb[i].yres == DEFAULT_YRES &&
+		    modedb[i].refresh >= fb_info.monspecs.vfmin &&
+		    modedb[i].refresh <= fb_info.monspecs.vfmax &&
+		    hs                >= fb_info.monspecs.hfmin &&
+		    hs                <= fb_info.monspecs.hfmax) {
+			acornfb_default_mode = modedb[i];
+			break;
+		}
+	}
+
 	current_par.currcon	   = -1;
 	current_par.screen_base	   = SCREEN2_BASE;
 	current_par.screen_base_p  = SCREEN_START;
@@ -1972,7 +1614,7 @@
 		if (current_par.screen_base == 0) {
 			printk(KERN_ERR "acornfb: unable to allocate screen "
 			       "memory\n");
-			return;
+			return -ENOMEM;
 		}
 		top = current_par.screen_base + (PAGE_SIZE * (1 << order));
 		/* Mark the framebuffer pages as reserved so mmap will work. */
@@ -2010,8 +1652,14 @@
 	 * find it, then we can't restore it if we change
 	 * the resolution, so we disable this feature.
 	 */
-	if (acornfb_lookup_timing(&init_var))
-		current_par.allow_modeset = 0;
+	rc = fb_find_mode(&init_var, &fb_info, NULL, modedb,
+			 sizeof(modedb) / sizeof(*modedb),
+			 &acornfb_default_mode, DEFAULT_BPP);
+
+	if (!rc && fb_find_mode(&init_var, &fb_info, NULL, NULL, 0,
+				&acornfb_default_mode, DEFAULT_BPP)) {
+		printk("Acornfb: no valid mode found\n");
+	}
 
 	/*
 	 * Again, if this does not succeed, then we disallow
diff -u --recursive --new-file v2.3.24/linux/drivers/video/acornfb.h linux/drivers/video/acornfb.h
--- v2.3.24/linux/drivers/video/acornfb.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/acornfb.h	Thu Oct 28 10:16:02 1999
@@ -0,0 +1,200 @@
+/*
+ * linux/drivers/video/acornfb.h
+ *
+ * Copyright (C) 1998,1999 Russell King
+ *
+ * Frame buffer code for Acorn platforms
+ */
+#if defined(HAS_VIDC20)
+#include <asm/iomd.h>
+#define VIDC_PALETTE_SIZE	256
+#define VIDC_NAME		"VIDC20"
+#elif defined(HAS_VIDC)
+#include <asm/memc.h>
+#define VIDC_PALETTE_SIZE	16
+#define VIDC_NAME		"VIDC"
+#endif
+
+#define EXTEND8(x) ((x)|(x)<<8)
+#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
+
+struct vidc20_palette {
+	u_int red:8;
+	u_int green:8;
+	u_int blue:8;
+	u_int ext:4;
+	u_int unused:4;
+};
+
+struct vidc_palette {
+	u_int red:4;
+	u_int green:4;
+	u_int blue:4;
+	u_int trans:1;
+	u_int sbz1:13;
+	u_int reg:4;
+	u_int sbz2:2;
+};
+
+union palette {
+	struct vidc20_palette	vidc20;
+	struct vidc_palette	vidc;
+	u_int	p;
+};
+
+struct acornfb_par {
+	unsigned long	screen_base;
+	unsigned long	screen_base_p;
+	unsigned long	screen_end;
+	unsigned long	screen_size;
+	unsigned int	dram_size;
+	unsigned int	vram_half_sam;
+	unsigned int	palette_size;
+	  signed int	montype;
+	  signed int	currcon;
+	unsigned int	allow_modeset	: 1;
+	unsigned int	using_vram	: 1;
+	unsigned int	dpms		: 1;
+
+	union palette palette[VIDC_PALETTE_SIZE];
+
+	union {
+		unsigned short cfb16[16];
+		unsigned long  cfb32[16];
+	} cmap;
+};
+
+struct vidc_timing {
+	u_int	h_cycle;
+	u_int	h_sync_width;
+	u_int	h_border_start;
+	u_int	h_display_start;
+	u_int	h_display_end;
+	u_int	h_border_end;
+	u_int	h_interlace;
+
+	u_int	v_cycle;
+	u_int	v_sync_width;
+	u_int	v_border_start;
+	u_int	v_display_start;
+	u_int	v_display_end;
+	u_int	v_border_end;
+
+	u_int	control;
+
+	/* VIDC20 only */
+	u_int	pll_ctl;
+};
+
+struct modey_params {
+	u_int	y_res;
+	u_int	u_margin;
+	u_int	b_margin;
+	u_int	vsync_len;
+	u_int	vf;
+};
+
+struct modex_params {
+	u_int	x_res;
+	u_int	l_margin;
+	u_int	r_margin;
+	u_int	hsync_len;
+	u_int	clock;
+	u_int	hf;
+	const struct modey_params *modey;
+};
+
+#ifdef HAS_VIDC
+
+#define VID_CTL_VS_NVSYNC	(1 << 3)
+#define VID_CTL_HS_NHSYNC	(1 << 2)
+#define VID_CTL_24MHz		(0)
+#define VID_CTL_25MHz		(1)
+#define VID_CTL_36MHz		(2)
+
+#define VIDC_CTRL_INTERLACE	(1 << 6)
+#define VIDC_CTRL_FIFO_0_4	(0 << 4)
+#define VIDC_CTRL_FIFO_1_5	(1 << 4)
+#define VIDC_CTRL_FIFO_2_6	(2 << 4)
+#define VIDC_CTRL_FIFO_3_7	(3 << 4)
+#define VIDC_CTRL_1BPP		(0 << 2)
+#define VIDC_CTRL_2BPP		(1 << 2)
+#define VIDC_CTRL_4BPP		(2 << 2)
+#define VIDC_CTRL_8BPP		(3 << 2)
+#define VIDC_CTRL_DIV3		(0 << 0)
+#define VIDC_CTRL_DIV2		(1 << 0)
+#define VIDC_CTRL_DIV1_5	(2 << 0)
+#define VIDC_CTRL_DIV1		(3 << 0)
+
+#endif
+
+#ifdef HAS_VIDC20
+/*
+ * VIDC20 registers
+ */
+#define VIDC20_CTRL		0xe0000000
+#define VIDC20_CTRL_PIX_VCLK	(0 << 0)
+#define VIDC20_CTRL_PIX_HCLK	(1 << 0)
+#define VIDC20_CTRL_PIX_RCLK	(2 << 0)
+#define VIDC20_CTRL_PIX_CK	(0 << 2)
+#define VIDC20_CTRL_PIX_CK2	(1 << 2)
+#define VIDC20_CTRL_PIX_CK3	(2 << 2)
+#define VIDC20_CTRL_PIX_CK4	(3 << 2)
+#define VIDC20_CTRL_PIX_CK5	(4 << 2)
+#define VIDC20_CTRL_PIX_CK6	(5 << 2)
+#define VIDC20_CTRL_PIX_CK7	(6 << 2)
+#define VIDC20_CTRL_PIX_CK8	(7 << 2)
+#define VIDC20_CTRL_1BPP	(0 << 5)
+#define VIDC20_CTRL_2BPP	(1 << 5)
+#define VIDC20_CTRL_4BPP	(2 << 5)
+#define VIDC20_CTRL_8BPP	(3 << 5)
+#define VIDC20_CTRL_16BPP	(4 << 5)
+#define VIDC20_CTRL_32BPP	(6 << 5)
+#define VIDC20_CTRL_FIFO_NS	(0 << 8)
+#define VIDC20_CTRL_FIFO_4	(1 << 8)
+#define VIDC20_CTRL_FIFO_8	(2 << 8)
+#define VIDC20_CTRL_FIFO_12	(3 << 8)
+#define VIDC20_CTRL_FIFO_16	(4 << 8)
+#define VIDC20_CTRL_FIFO_20	(5 << 8)
+#define VIDC20_CTRL_FIFO_24	(6 << 8)
+#define VIDC20_CTRL_FIFO_28	(7 << 8)
+#define VIDC20_CTRL_INT		(1 << 12)
+#define VIDC20_CTRL_DUP		(1 << 13)
+#define VIDC20_CTRL_PDOWN	(1 << 14)
+
+#define VIDC20_ECTL		0xc0000000
+#define VIDC20_ECTL_REG(x)	((x) & 0xf3)
+#define VIDC20_ECTL_ECK		(1 << 2)
+#define VIDC20_ECTL_REDPED	(1 << 8)
+#define VIDC20_ECTL_GREENPED	(1 << 9)
+#define VIDC20_ECTL_BLUEPED	(1 << 10)
+#define VIDC20_ECTL_DAC		(1 << 12)
+#define VIDC20_ECTL_LCDGS	(1 << 13)
+#define VIDC20_ECTL_HRM		(1 << 14)
+
+#define VIDC20_ECTL_HS_MASK	(3 << 16)
+#define VIDC20_ECTL_HS_HSYNC	(0 << 16)
+#define VIDC20_ECTL_HS_NHSYNC	(1 << 16)
+#define VIDC20_ECTL_HS_CSYNC	(2 << 16)
+#define VIDC20_ECTL_HS_NCSYNC	(3 << 16)
+
+#define VIDC20_ECTL_VS_MASK	(3 << 18)
+#define VIDC20_ECTL_VS_VSYNC	(0 << 18)
+#define VIDC20_ECTL_VS_NVSYNC	(1 << 18)
+#define VIDC20_ECTL_VS_CSYNC	(2 << 18)
+#define VIDC20_ECTL_VS_NCSYNC	(3 << 18)
+
+#define VIDC20_DCTL		0xf0000000
+/* 0-9 = number of words in scanline */
+#define VIDC20_DCTL_SNA		(1 << 12)
+#define VIDC20_DCTL_HDIS	(1 << 13)
+#define VIDC20_DCTL_BUS_NS	(0 << 16)
+#define VIDC20_DCTL_BUS_D31_0	(1 << 16)
+#define VIDC20_DCTL_BUS_D63_32	(2 << 16)
+#define VIDC20_DCTL_BUS_D63_0	(3 << 16)
+#define VIDC20_DCTL_VRAM_DIS	(0 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK	(1 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK2	(2 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK4	(3 << 18)
+
+#endif
diff -u --recursive --new-file v2.3.24/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- v2.3.24/linux/drivers/video/clgenfb.c	Fri Sep 10 23:57:36 1999
+++ linux/drivers/video/clgenfb.c	Sun Oct 31 15:01:51 1999
@@ -2476,7 +2476,7 @@
 	for (i = 0; i < dp->n_addrs; ++i) {
 		unsigned long addr = dp->addrs[i].address;
 		unsigned long size = dp->addrs[i].size;
-		printk ("dp->addrs[%d].address = $lx, dp->addrs[%d].size = %lx\n",
+		printk ("dp->addrs[%d].address = %lx, dp->addrs[%d].size = %lx\n",
 			i, addr, i, size);
 		if (size >= 0x800000) {
 			*display = addr;
diff -u --recursive --new-file v2.3.24/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- v2.3.24/linux/drivers/video/cyber2000fb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/cyber2000fb.c	Thu Oct 28 10:16:02 1999
@@ -35,7 +35,9 @@
 #define DEFAULT_YRES	480
 #define DEFAULT_BPP	8
 
-static volatile unsigned char	*CyberRegs;
+#define MMIO_SIZE	0x000c0000
+
+static char			*CyberRegs;
 
 #include "cyber2000fb.h"
 
@@ -45,7 +47,7 @@
 static struct display_switch	*dispsw;
 static struct fb_var_screeninfo __initdata init_var = {};
 
-#ifdef DEBUG
+#if defined(DEBUG) && defined(CONFIG_DEBUG_LL)
 static void debug_printf(char *fmt, ...)
 {
 	char buffer[128];
@@ -61,168 +63,6 @@
 #define debug_printf(x...) do { } while (0)
 #endif
 
-/*
- *    Predefined Video Modes
- */
-static const struct res cyber2000_res[] = {
-	{
-		640, 480,
-		{
-			0x5f, 0x4f, 0x50, 0x80, 0x52, 0x9d, 0x0b, 0x3e,
-			0x00, 0x40,
-			0xe9, 0x8b, 0xdf, 0x50, 0x00, 0xe6, 0x04, 0xc3
-		},
-		0x00,
-		{ 0xd2, 0xce, 0xdb, 0x54 }
-	},
-
-	{
-		800, 600,
-		{
-			0x7f, 0x63, 0x64, 0x00, 0x66, 0x10, 0x6f, 0xf0,
-			0x00, 0x60,
-			0x5b, 0x8f, 0x57, 0x64, 0x00, 0x59, 0x6e, 0xe3
-		},
-		0x00,
-		{ 0x52, 0x85, 0xdb, 0x54 }
-	},
-
-	{
-		1024, 768,
-		{
-			0x9f, 0x7f, 0x80, 0x80, 0x8b, 0x94, 0x1e, 0xfd,
-			0x00, 0x60,
-			0x03, 0x86, 0xff, 0x80, 0x0f, 0x00, 0x1e, 0xe3
-		},
-		0x00,
-		{ 0xd0, 0x52, 0xdb, 0x54 }
-	},
-#if 0
-	{
-		1152, 886,
-		{
-		},
-		{
-		}
-	},
-#endif
-	{
-		1280, 1024,
-		{
-			0xce, 0x9f, 0xa0, 0x8f, 0xa2, 0x1f, 0x28, 0x52,
-			0x00, 0x40,
-			0x08, 0x8f, 0xff, 0xa0, 0x00, 0x03, 0x27, 0xe3
-		},
-		0x1d,
-		{ 0xb4, 0x4b, 0xdb, 0x54 }
-	},
-
-	{
-		1600, 1200,
-		{
-			0xff, 0xc7, 0xc9, 0x9f, 0xcf, 0xa0, 0xfe, 0x10,
- 			0x00, 0x40,
-			0xcf, 0x89, 0xaf, 0xc8, 0x00, 0xbc, 0xf1, 0xe3
-		},
-		0x1f,
-		{ 0xbd, 0x10, 0xdb, 0x54 }
-	}
-};
-
-#define NUM_TOTAL_MODES    arraysize(cyber2000_res)
-
-static const char igs_regs[] = {
-	0x10, 0x10,			0x12, 0x00,	0x13, 0x00,
-	0x30, 0x21,	0x31, 0x00,	0x32, 0x00,	0x33, 0x01,
-	0x50, 0x00,	0x51, 0x00,	0x52, 0x00,	0x53, 0x00,
-	0x54, 0x00,	0x55, 0x00,	0x56, 0x00,	0x57, 0x01,
-	0x58, 0x00,	0x59, 0x00,	0x5a, 0x00,
-	0x70, 0x0b,	0x71, 0x10,	0x72, 0x45,	0x73, 0x30,
-	0x74, 0x1b,	0x75, 0x1e,	0x76, 0x00,	0x7a, 0xc8
-};
-
-static const char crtc_idx[] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09,
-	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
-};
-
-static void cyber2000_init_hw(const struct res *res)
-{
-	int i;
-
-	debug_printf("init vga hw for %dx%d\n", res->xres, res->yres);
-
-	cyber2000_outb(0xef, 0x3c2);
-	cyber2000_crtcw(0x11, 0x0b);
-	cyber2000_attrw(0x11, 0x00);
-
-	cyber2000_seqw(0x00, 0x01);
-	cyber2000_seqw(0x01, 0x01);
-	cyber2000_seqw(0x02, 0x0f);
-	cyber2000_seqw(0x03, 0x00);
-	cyber2000_seqw(0x04, 0x0e);
-	cyber2000_seqw(0x00, 0x03);
-
-	for (i = 0; i < sizeof(crtc_idx); i++)
-		cyber2000_crtcw(crtc_idx[i], res->crtc_regs[i]);
-
-	for (i = 0x0a; i < 0x10; i++)
-		cyber2000_crtcw(i, 0);
-
-	cyber2000_crtcw(0x18, 0xff);
-
-	cyber2000_grphw(0x00, 0x00);
-	cyber2000_grphw(0x01, 0x00);
-	cyber2000_grphw(0x02, 0x00);
-	cyber2000_grphw(0x03, 0x00);
-	cyber2000_grphw(0x04, 0x00);
-	cyber2000_grphw(0x05, 0x60);
-	cyber2000_grphw(0x06, 0x05);
-	cyber2000_grphw(0x07, 0x0f);
-	cyber2000_grphw(0x08, 0xff);
-
-	for (i = 0; i < 16; i++)
-		cyber2000_attrw(i, i);
-
-	cyber2000_attrw(0x10, 0x01);
-	cyber2000_attrw(0x11, 0x00);
-	cyber2000_attrw(0x12, 0x0f);
-	cyber2000_attrw(0x13, 0x00);
-	cyber2000_attrw(0x14, 0x00);
-
-	for (i = 0; i < sizeof(igs_regs); i += 2)
-		cyber2000_grphw(igs_regs[i], igs_regs[i+1]);
-
-	cyber2000_grphw(0x11, res->crtc_ofl);
-
-	for (i = 0; i < 4; i += 1)
-		cyber2000_grphw(0xb0 + i, res->clk_regs[i]);
-
-	cyber2000_grphw(0x90, 0x01);
-	cyber2000_grphw(0xb9, 0x80);
-	cyber2000_grphw(0xb9, 0x00);
-
-	cyber2000_outb(0x56, 0x3ce);
-	i = cyber2000_inb(0x3cf);
-	cyber2000_outb(i | 4, 0x3cf);
-	cyber2000_outb(0x04, 0x3c6);
-	cyber2000_outb(i,    0x3cf);
-
-	cyber2000_outb(0x20, 0x3c0);
-	cyber2000_outb(0xff, 0x3c6);
-
-	for (i = 0; i < 256; i++) {
-		cyber2000_outb(i, 0x3c8);
-		cyber2000_outb(0, 0x3c9);
-		cyber2000_outb(0, 0x3c9);
-		cyber2000_outb(0, 0x3c9);
-	}
-}
-
-
-static struct fb_ops cyber2000fb_ops;
-
 /* -------------------- Hardware specific routines ------------------------- */
 
 /*
@@ -232,10 +72,10 @@
 {
 	int count = 10000;
 
-	while (cyber2000_inb(0xbf011) & 0x80) {
+	while (cyber2000_inb(CO_REG_CONTROL) & 0x80) {
 		if (!count--) {
 			debug_printf("accel_wait timed out\n");
-			cyber2000_outb(0, 0xbf011);
+			cyber2000_outb(0, CO_REG_CONTROL);
 			return;
 		}
 		udelay(10);
@@ -252,45 +92,54 @@
 cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
 		int height, int width)
 {
-	unsigned long src, dst, chwidth = p->var.xres_virtual * fontheight(p);
-	int v = 0x8000;
+	unsigned long src, dst;
+	unsigned int fh, fw;
+	int cmd = CO_CMD_L_PATTERN_FGCOL;
+
+	fw    = fontwidth(p);
+	sx    *= fw;
+	dx    *= fw;
+	width *= fw;
+	width -= 1;
 
 	if (sx < dx) {
-		sx += width - 1;
-		dx += width - 1;
-		v |= 4;
+		sx += width;
+		dx += width;
+		cmd |= CO_CMD_L_INC_LEFT;
 	}
 
+	fh     = fontheight(p);
+	sy     *= fh;
+	dy     *= fh;
+	height *= fh;
+	height -= 1;
+
 	if (sy < dy) {
-		sy += height - 1;
-		dy += height - 1;
-		v |= 2;
+		sy += height;
+		dy += height;
+		cmd |= CO_CMD_L_INC_UP;
 	}
 
-	sx *= fontwidth(p);
-	dx *= fontwidth(p);
-	src = sx + sy * chwidth;
-	dst = dx + dy * chwidth;
-	width = width * fontwidth(p) - 1;
-	height = height * fontheight(p) - 1;
+	src    = sx + sy * p->var.xres_virtual;
+	dst    = dx + dy * p->var.xres_virtual;
 
 	cyber2000_accel_wait();
-	cyber2000_outb(0x00,   0xbf011);
-	cyber2000_outb(0x03,   0xbf048);
-	cyber2000_outw(width,  0xbf060);
+	cyber2000_outb(0x00,  CO_REG_CONTROL);
+	cyber2000_outb(0x03,  CO_REG_FORE_MIX);
+	cyber2000_outw(width, CO_REG_WIDTH);
 
 	if (p->var.bits_per_pixel != 24) {
-		cyber2000_outl(dst, 0xbf178);
-		cyber2000_outl(src, 0xbf170);
+		cyber2000_outl(dst, CO_REG_DEST_PTR);
+		cyber2000_outl(src, CO_REG_SRC_PTR);
 	} else {
-		cyber2000_outl(dst * 3, 0xbf178);
-		cyber2000_outb(dst, 0xbf078);
-		cyber2000_outl(src * 3, 0xbf170);
+		cyber2000_outl(dst * 3, CO_REG_DEST_PTR);
+		cyber2000_outb(dst,     CO_REG_X_PHASE);
+		cyber2000_outl(src * 3, CO_REG_SRC_PTR);
 	}
 
-	cyber2000_outw(height, 0xbf062);
-	cyber2000_outw(v,      0xbf07c);
-	cyber2000_outw(0x2800, 0xbf07e);
+	cyber2000_outw(height, CO_REG_HEIGHT);
+	cyber2000_outw(cmd,    CO_REG_CMD_L);
+	cyber2000_outw(0x2800, CO_REG_CMD_H);
 }
 
 static void
@@ -298,36 +147,40 @@
 		int height, int width)
 {
 	unsigned long dst;
+	unsigned int fw, fh;
 	u32 bgx = attr_bgcol_ec(p, conp);
 
-	dst = sx * fontwidth(p) + sy * p->var.xres_virtual * fontheight(p);
-	width = width * fontwidth(p) - 1;
-	height = height * fontheight(p) - 1;
+	fw = fontwidth(p);
+	fh = fontheight(p);
+
+	dst    = sx * fw + sy * p->var.xres_virtual * fh;
+	width  = width * fw - 1;
+	height = height * fh - 1;
 
 	cyber2000_accel_wait();
-	cyber2000_outb(0x00,   0xbf011);
-	cyber2000_outb(0x03,   0xbf048);
-	cyber2000_outw(width,  0xbf060);
-	cyber2000_outw(height, 0xbf062);
+	cyber2000_outb(0x00,   CO_REG_CONTROL);
+	cyber2000_outb(0x03,   CO_REG_FORE_MIX);
+	cyber2000_outw(width,  CO_REG_WIDTH);
+	cyber2000_outw(height, CO_REG_HEIGHT);
 
 	switch (p->var.bits_per_pixel) {
 	case 15:
 	case 16:
 		bgx = ((u16 *)p->dispsw_data)[bgx];
 	case 8:
-		cyber2000_outl(dst, 0xbf178);
+		cyber2000_outl(dst, CO_REG_DEST_PTR);
 		break;
 
 	case 24:
-		cyber2000_outl(dst * 3, 0xbf178);
-		cyber2000_outb(dst, 0xbf078);
+		cyber2000_outl(dst * 3, CO_REG_DEST_PTR);
+		cyber2000_outb(dst, CO_REG_X_PHASE);
 		bgx = ((u32 *)p->dispsw_data)[bgx];
 		break;
 	}
 
-	cyber2000_outl(bgx,    0xbf058);
-	cyber2000_outw(0x8000, 0xbf07c);
-	cyber2000_outw(0x0800, 0xbf07e);
+	cyber2000_outl(bgx, CO_REG_FOREGROUND);
+	cyber2000_outw(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L);
+	cyber2000_outw(0x0800, CO_REG_CMD_H);
 }
 
 static void
@@ -478,183 +331,136 @@
 	return 0;
 }
 
-static void cyber2000fb_calculate_timing(unsigned char *v, struct fb_var_screeninfo *var)
-{
-	int Htotal, Hdispend, Hblankstart, Hblankend, Hsyncstart, Hsyncend;
-	int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
-#define BIT(v,b1,m,b2) (((v >> b1) & m) << b2)
-
-	Hdispend    = var->xres;
-	Hsyncstart  = var->xres + var->right_margin;
-	Hsyncend    = var->xres + var->right_margin + var->hsync_len;
-	Htotal      = var->xres + var->right_margin + var->hsync_len + var->left_margin;
-
-	Hblankstart = var->xres;
-	Hblankend   = Htotal - 4*8;
-
-	Vdispend    = var->yres;
-	Vsyncstart  = var->yres + var->lower_margin;
-	Vsyncend    = var->yres + var->lower_margin + var->vsync_len;
-	Vtotal      = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
-
-	Vblankstart = var->yres + 7;
-	Vblankend   = Vtotal - 11;
+struct par_info {
+	/*
+	 * Hardware
+	 */
+	unsigned char	clock_mult;
+	unsigned char	clock_div;
+	unsigned char	visualid;
+	unsigned char	pixformat;
+	unsigned char	crtc_ofl;
+	unsigned char	crtc[19];
+	unsigned int	width;
+	unsigned int	pitch;
 
-	Hdispend    >>= 3;
-	Hsyncstart  >>= 3;
-	Hsyncend    >>= 3;
-	Htotal      >>= 3;
-	Hblankstart >>= 3;
-	Hblankend   >>= 3;
-
-	Htotal      -= 5;
-	Hdispend    -= 1;
-	Vtotal	    -= 2;
-	Vdispend    -= 1;
-	Vblankstart -= 1;
-	Vblankend   -= 1;
-
-	v[0]  = Htotal;
-	v[1]  = Hdispend;
-	v[2]  = Hblankstart;
-	v[3]  = BIT(Hblankend,  0, 0x1f,  0) |
-		BIT(1,          0, 0x01,  7);
-	v[4]  = Hsyncstart;
-	v[5]  = BIT(Hsyncend,   0, 0x1f,  0) |
-	        BIT(Hblankend,  5, 0x01,  7);
-
-	v[6]  = Vtotal;
-	v[7]  = BIT(Vtotal,     8, 0x01,  0) |
-		BIT(Vdispend,   8, 0x01,  1) |
-		BIT(Vsyncstart, 8, 0x01,  2) |
-		BIT(Vblankstart,8, 0x01,  3) |
-		BIT(1,          0, 0x01,  4) |
-	        BIT(Vtotal,     9, 0x01,  5) |
-		BIT(Vdispend,   9, 0x01,  6) |
-		BIT(Vsyncstart, 9, 0x01,  7);
-	v[8]  = 0;
-	v[9]  = BIT(0,          0, 0x1f,  0) |
-	        BIT(Vblankstart,9, 0x01,  5) |
-		BIT(1,          0, 0x01,  6);
-	v[10] = Vsyncstart;
-	v[11] = BIT(Vsyncend,   0, 0x0f,  0) |
-		BIT(1,          0, 0x01,  7);
-	v[12] = Vdispend;
-	v[14] = 0;
-	v[15] = Vblankstart;
-	v[16] = Vblankend;
-	v[17] = 0xe3;
+	/*
+	 * Other
+	 */
+	unsigned int	visual;
+};
 
-	/* overflow - graphics reg 0x11 */
-	v[18] = BIT(Vtotal,     10, 0x01,  0) | /* guess */
-		BIT(Vdispend,   10, 0x01,  1) |
-		BIT(Vsyncstart, 10, 0x01,  2) | /* guess */
-		BIT(Vblankstart,10, 0x01,  3) | /* guess */
-		BIT(Hblankend,   6, 0x01,  4);  /* guess */
-}
+static const char crtc_idx[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
+};
 
-static void cyber2000fb_set_timing(struct fb_var_screeninfo *var)
+static void cyber2000fb_set_timing(struct par_info *hw)
 {
-	unsigned int width = var->xres_virtual;
-	unsigned int scr_pitch, fetchrow, i;
-	char b, graph_r77, crtc[32];
+	unsigned int fetchrow, i;
 
-	switch (var->bits_per_pixel) {
-	case 8:	/* PSEUDOCOLOUR, 256 */
-		b = 0;
-		graph_r77 = 1;
-		scr_pitch = width;
-		break;
+	/*
+	 * Blank palette
+	 */
+	for (i = 0; i < 256; i++) {
+		cyber2000_outb(i, 0x3c8);
+		cyber2000_outb(0, 0x3c9);
+		cyber2000_outb(0, 0x3c9);
+		cyber2000_outb(0, 0x3c9);
+	}
 
-	case 15:/* DIRECTCOLOUR, 32k */
-		b = 1;
-		graph_r77 = 6;
-		scr_pitch = width * 2;
-		break;
+	cyber2000_outb(0xef, 0x3c2);
+	cyber2000_crtcw(0x11, 0x0b);
+	cyber2000_attrw(0x11, 0x00);
 
-	case 16:/* DIRECTCOLOUR, 64k */
-		b = 1;
-		graph_r77 = 2;
-		scr_pitch = width * 2;
-		break;
+	cyber2000_seqw(0x00, 0x01);
+	cyber2000_seqw(0x01, 0x01);
+	cyber2000_seqw(0x02, 0x0f);
+	cyber2000_seqw(0x03, 0x00);
+	cyber2000_seqw(0x04, 0x0e);
+	cyber2000_seqw(0x00, 0x03);
 
-	case 24:/* TRUECOLOUR, 16m */
-		b = 2;
-		graph_r77 = 4;
-		width *= 3;
-		scr_pitch = width;
-		break;
+	for (i = 0; i < sizeof(crtc_idx); i++)
+		cyber2000_crtcw(crtc_idx[i], hw->crtc[i]);
 
-	default:
-		return;
-	}
+	for (i = 0x0a; i < 0x10; i++)
+		cyber2000_crtcw(i, 0);
 
-	width -= 1;
-	scr_pitch >>= 3;
-	fetchrow = scr_pitch + 1;
+	cyber2000_grphw(0x11, hw->crtc_ofl);
+	cyber2000_grphw(0x00, 0x00);
+	cyber2000_grphw(0x01, 0x00);
+	cyber2000_grphw(0x02, 0x00);
+	cyber2000_grphw(0x03, 0x00);
+	cyber2000_grphw(0x04, 0x00);
+	cyber2000_grphw(0x05, 0x60);
+	cyber2000_grphw(0x06, 0x05);
+	cyber2000_grphw(0x07, 0x0f);
+	cyber2000_grphw(0x08, 0xff);
 
-	cyber2000fb_calculate_timing(crtc, var);
+	/* Attribute controller registers */
+	for (i = 0; i < 16; i++)
+		cyber2000_attrw(i, i);
 
-	for (i = 0; i < NUM_TOTAL_MODES; i++)
-		if (var->xres == cyber2000_res[i].xres &&
-		    var->yres == cyber2000_res[i].yres)
-			break;
+	cyber2000_attrw(0x10, 0x01);
+	cyber2000_attrw(0x11, 0x00);
+	cyber2000_attrw(0x12, 0x0f);
+	cyber2000_attrw(0x13, 0x00);
+	cyber2000_attrw(0x14, 0x00);
 
-	if (i < NUM_TOTAL_MODES)
-		cyber2000_init_hw(cyber2000_res + i);
+	/* PLL registers */
+	cyber2000_grphw(0xb0, hw->clock_mult);
+	cyber2000_grphw(0xb1, hw->clock_div);
+	cyber2000_grphw(0xb2, 0xdb);
+	cyber2000_grphw(0xb3, 0x54);		/* MCLK: 75MHz */
+	cyber2000_grphw(0x90, 0x01);
+	cyber2000_grphw(0xb9, 0x80);
+	cyber2000_grphw(0xb9, 0x00);
 
-	crtc[13] = scr_pitch;
+	cyber2000_outb(0x56, 0x3ce);
+	i = cyber2000_inb(0x3cf);
+	cyber2000_outb(i | 4, 0x3cf);
+	cyber2000_outb(0x04, 0x3c6);
+	cyber2000_outb(i,    0x3cf);
 
-	/*
-	 * reprogram the CRTC with the values we calculated
-	 * above.  This should be cleaned up once we're
-	 * confident that we're generating the correct
-	 * values.  Disable this if you're having problems,
-	 * and report the values obtained from the kernel
-	 * messages.
-	 */
-#if 1
-	cyber2000_crtcw(0x11, 0x0b);
-	for (i = 0; i < sizeof(crtc_idx); i++)
-		cyber2000_crtcw(crtc_idx[i], crtc[i]);
-#else
-	cyber2000_crtcw(0x13, crtc[13]);
-#endif
+	cyber2000_outb(0x20, 0x3c0);
+	cyber2000_outb(0xff, 0x3c6);
 
+	fetchrow = hw->pitch + 1;
 	cyber2000_grphw(0x14, fetchrow);
-					/* FIXME: is this the right way round? */
-	cyber2000_grphw(0x15, ((fetchrow >> 4) & 0xf0) | ((scr_pitch >> 8) & 0x0f));
-	cyber2000_grphw(0x77, graph_r77);
+	/* FIXME: is this the right way round? */
+	cyber2000_grphw(0x15, ((fetchrow >> 4) & 0xf0) | ((hw->pitch >> 8) & 0x0f));
+	cyber2000_grphw(0x77, hw->visualid);
 	cyber2000_grphw(0x33, 0x1c);
 
-	cyber2000_outw(width, 0xbf018);
-	cyber2000_outw(width, 0xbf218);
-	cyber2000_outb(b,     0xbf01c);
-
-#if 0
-{ int j; i = 0;
- printk(KERN_DEBUG);
- for (j = 0; j < 19; j++) printk("%2d ", j); printk("\n"KERN_DEBUG);
- for (j = 0; j < 19; j++) printk("%02X ", crtc[j]); printk("\n"KERN_DEBUG);
- for (j = 0; j < 18; j++) printk("%02X ", cyber2000_res[i].crtc_regs[j]);
- printk("%02X\n", cyber2000_res[i].crtc_ofl);
-}
-#endif
+	/*
+	 * Set up accelerator registers
+	 */
+	cyber2000_outw(hw->width, CO_REG_SRC_WIDTH);
+	cyber2000_outw(hw->width, CO_REG_DEST_WIDTH);
+	cyber2000_outb(hw->pixformat, CO_REG_PIX_FORMAT);
 }
 
-static inline void
+static inline int
 cyber2000fb_update_start(struct fb_var_screeninfo *var)
 {
-#if 0
 	unsigned int base;
 
 	base = var->yoffset * var->xres_virtual + var->xoffset;
 
-	cyber2000_crtcw(0x0c, base);
-	cyber2000_crtcw(0x0d, base >> 8);
-	/* FIXME: need the upper bits of the start offset */
-/*	cyber2000_crtcw(0x??, base >> 16);*/
-#endif
+	base >>= 2;
+
+	if (base >= 1 << 20)
+		return -EINVAL;
+
+	/*
+	 * FIXME: need the upper bits of the start offset
+	 */
+	cyber2000_grphw(0x10, base >> 16 | 0x10);
+	cyber2000_crtcw(0x0c, base >> 8);
+	cyber2000_crtcw(0x0d, base);
+
+	return 0;
 }
 
 /*
@@ -723,30 +529,230 @@
 	return err;
 }
 
+static int cyber2000fb_decode_crtc(struct par_info *hw, struct fb_var_screeninfo *var)
+{
+	unsigned int Htotal, Hblankend, Hsyncend;
+	unsigned int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
+#define BIT(v,b1,m,b2) (((v >> b1) & m) << b2)
+
+	hw->crtc[13] = hw->pitch;
+	hw->crtc[17] = 0xe3;
+	hw->crtc[14] = 0;
+	hw->crtc[8]  = 0;
+
+	Htotal      = var->xres + var->right_margin + var->hsync_len + var->left_margin;
+	if (Htotal > 2080)
+		return -EINVAL;
+
+	hw->crtc[0] = (Htotal >> 3) - 5;			/* Htotal	*/
+	hw->crtc[1] = (var->xres >> 3) - 1;			/* Hdispend	*/
+	hw->crtc[2] = var->xres >> 3;				/* Hblankstart	*/
+	hw->crtc[4] = (var->xres + var->right_margin) >> 3;	/* Hsyncstart	*/
+
+	Hblankend   = (Htotal - 4*8) >> 3;
+
+	hw->crtc[3] = BIT(Hblankend,  0, 0x1f,  0) |		/* Hblankend	*/
+		      BIT(1,          0, 0x01,  7);
+
+	Hsyncend    = (var->xres + var->right_margin + var->hsync_len) >> 3;
+
+	hw->crtc[5] = BIT(Hsyncend,   0, 0x1f,  0) |		/* Hsyncend	*/
+		      BIT(Hblankend,  5, 0x01,  7);
+
+	Vdispend    = var->yres - 1;
+	Vsyncstart  = var->yres + var->lower_margin;
+	Vsyncend    = var->yres + var->lower_margin + var->vsync_len;
+	Vtotal      = var->yres + var->lower_margin + var->vsync_len + var->upper_margin - 2;
+
+	if (Vtotal > 2047)
+		return -EINVAL;
+
+	Vblankstart = var->yres + 6;
+	Vblankend   = Vtotal - 10;
+
+	hw->crtc[6]  = Vtotal;
+	hw->crtc[7]  = BIT(Vtotal,     8, 0x01,  0) |
+			BIT(Vdispend,   8, 0x01,  1) |
+			BIT(Vsyncstart, 8, 0x01,  2) |
+			BIT(Vblankstart,8, 0x01,  3) |
+			BIT(1,          0, 0x01,  4) |
+	        	BIT(Vtotal,     9, 0x01,  5) |
+			BIT(Vdispend,   9, 0x01,  6) |
+			BIT(Vsyncstart, 9, 0x01,  7);
+	hw->crtc[9]  = BIT(0,          0, 0x1f,  0) |
+		        BIT(Vblankstart,9, 0x01,  5) |
+			BIT(1,          0, 0x01,  6);
+	hw->crtc[10] = Vsyncstart;
+	hw->crtc[11] = BIT(Vsyncend,   0, 0x0f,  0) |
+		       BIT(1,          0, 0x01,  7);
+	hw->crtc[12] = Vdispend;
+	hw->crtc[15] = Vblankstart;
+	hw->crtc[16] = Vblankend;
+	hw->crtc[18] = 0xff;
+
+	/* overflow - graphics reg 0x11 */
+/* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10 4=LINECOMP:10 5-IVIDEO 6=FIXCNT */
+	hw->crtc_ofl =
+		BIT(Vtotal,     10, 0x01,  0) |
+		BIT(Vdispend,   10, 0x01,  1) |
+		BIT(Vsyncstart, 10, 0x01,  2) |
+		BIT(Vblankstart,10, 0x01,  3) |
+		1 << 4;
+
+	return 0;
+}
+
+/*
+ * The following was discovered by a good monitor,
+ * bit twiddling, theorising and but mostly luck.
+ * Strangely, it looks like everyone elses' PLL!
+ *
+ * Clock registers:
+ *   fclock = fpll / div2
+ *   fpll   = fref * mult / div1
+ * where:
+ *   fref = 14.318MHz (69842ps)
+ *   mult = reg0xb0.7:0
+ *   div1 = (reg0xb1.5:0 + 1)
+ *   div2 =  2^(reg0xb1.7:6)
+ *   fpll should be between 150 and 220 MHz
+ *  (6667ps and 4545ps)
+ */
 static int
-cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
+cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var)
 {
+	unsigned long pll_ps = var->pixclock;
+	unsigned long ref_ps = 69842;
+	int div2, div1, mult;
+
+	/*
+	 * Step 1:
+	 *   find div2 such that 150MHz < fpll < 220MHz
+	 *   and 0 <= div2 < 4
+	 */
+	for (div2 = 0; div2 < 4; div2++, pll_ps >>= 1)
+		if (6667 > pll_ps && pll_ps > 4545)
+			break;
+
+	if (div2 == 4)
+		return -EINVAL;
+
+#if 0
+	/*
+	 * Step 2:
+	 *  Find fpll
+	 *    fpll = fref * mult / div1
+	 *
+	 * Note!  This just picks any old values at the moment,
+	 * and as such I don't trust it.  It certainly doesn't
+	 * come out with the values below, so the PLL may become
+	 * unstable under some circumstances (you don't want an
+	 * FM dot clock)
+	 */
+	for (div1 = 32; div1 > 1; div1 -= 1) {
+		mult = (ref_ps * div1 + pll_ps / 2) / pll_ps;
+		if (mult < 256)
+			break;
+	}
+#else
+	if (pll_ps == 4630) {		/* 216.0, 108.0, 54.00, 27.000 */
+		mult = 181;		/* 4630   9260   18520  37040  */
+		div1 = 12;
+	} else if (pll_ps == 4965) {	/* 201.0, 100.5, 50.25, 25.125 */
+		mult = 211;		/* 4965   9930   19860  39720  */
+		div1 = 15;
+	} else if (pll_ps == 5050) {	/* 198.0,  99.0, 49.50, 24.750 */
+		mult = 83;		/* 5050   10100  20200  40400  */
+		div1 = 6;
+	} else if (pll_ps == 6349) {	/* 158.0,  79.0, 39.50, 19.750 */
+		mult = 209;		/* 6349   12698  25396  50792  */
+		div1 = 19;
+	} else if (pll_ps == 6422) {	/* 156.0,  78.0, 39.00, 19.500 */
+		mult = 190;		/* 6422   12844  25688  51376  */
+		div1 = 17;
+	} else
+		return -EINVAL;
+#endif
+	/*
+	 * Step 3:
+	 *  combine values
+	 */
+	hw->clock_mult = mult - 1;
+	hw->clock_div  = div2 << 6 | (div1 - 1);
+
+	return 0;
+}
+
+/*
+ * Decode the info required for the hardware.
+ * This involves the PLL parameters for the dot clock,
+ * CRTC registers, and accelerator settings.
+ */
+static int
+cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, struct par_info *hw)
+{
+	int err;
+
+	hw->width = var->xres_virtual;
 	switch (var->bits_per_pixel) {
 #ifdef FBCON_HAS_CFB8
-	case 8:
-		*visual = FB_VISUAL_PSEUDOCOLOR;
+	case 8:	/* PSEUDOCOLOUR, 256 */
+		hw->visual    = FB_VISUAL_PSEUDOCOLOR;
+		hw->pixformat = PIXFORMAT_8BPP;
+		hw->visualid  = VISUALID_256;
+		hw->pitch     = hw->width >> 3;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
-	case 15:
-	case 16:
-		*visual = FB_VISUAL_DIRECTCOLOR;
+	case 15:/* DIRECTCOLOUR, 32k */
+		hw->visual    = FB_VISUAL_DIRECTCOLOR;
+		hw->pixformat = PIXFORMAT_16BPP;
+		hw->visualid  = VISUALID_32K;
+		hw->pitch     = hw->width >> 2;
+		break;
+
+	case 16:/* DIRECTCOLOUR, 64k */
+		hw->visual    = FB_VISUAL_DIRECTCOLOR;
+		hw->pixformat = PIXFORMAT_16BPP;
+		hw->visualid  = VISUALID_64K;
+		hw->pitch     = hw->width >> 2;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB24
-	case 24:
-		*visual = FB_VISUAL_TRUECOLOR;
+	case 24:/* TRUECOLOUR, 16m */
+		hw->visual    = FB_VISUAL_TRUECOLOR;
+		hw->pixformat = PIXFORMAT_24BPP;
+		hw->visualid  = VISUALID_16M;
+		hw->width    *= 3;
+		hw->pitch     = hw->width >> 3;
 		break;
 #endif
 	default:
 		return -EINVAL;
 	}
 
+	err = cyber2000fb_decode_clock(hw, var);
+	if (err)
+		return err;
+
+	err = cyber2000fb_decode_crtc(hw, var);
+	if (err)
+		return err;
+
+	debug_printf("Clock: %02X %02X\n",
+		hw->clock_mult, hw->clock_div);
+	{
+		int i;
+
+		for (i = 0; i < 19; i++)
+			debug_printf("%2d ", i);
+		debug_printf("\n");
+		for (i = 0; i < 18; i++)
+			debug_printf("%02X ", hw->crtc[i]);
+		debug_printf("%02X\n", hw->crtc_ofl);
+	}
+	hw->width     -= 1;
+
 	return 0;
 }
 
@@ -760,7 +766,7 @@
 	struct display *display;
 
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, "Cyber2000");
+	strcpy(fix->id, current_par.dev_name);
 
 	if (con >= 0)
 		display = fb_display + con;
@@ -770,7 +776,7 @@
 	fix->smem_start	 = current_par.screen_base_p;
 	fix->smem_len	 = current_par.screen_size;
 	fix->mmio_start	 = current_par.regs_base_p;
-	fix->mmio_len	 = 0x000c0000;
+	fix->mmio_len	 = MMIO_SIZE;
 	fix->type	 = display->type;
 	fix->type_aux	 = display->type_aux;
 	fix->xpanstep	 = 0;
@@ -806,14 +812,15 @@
 cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
 	struct display *display;
-	int err, chgvar = 0, visual;
+	struct par_info hw;
+	int err, chgvar = 0;
 
 	if (con >= 0)
 		display = fb_display + con;
 	else
 		display = &global_disp;
 
-	err = cyber2000fb_decode_var(var, con, &visual);
+	err = cyber2000fb_decode_var(var, con, &hw);
 	if (err)
 		return err;
 
@@ -854,11 +861,11 @@
 	if (var->activate & FB_ACTIVATE_ALL)
 		global_disp.var = display->var;
 
-	display->screen_base	= (char *)current_par.screen_base;
-	display->visual		= visual;
+	display->screen_base	= current_par.screen_base;
+	display->visual		= hw.visual;
 	display->type		= FB_TYPE_PACKED_PIXELS;
 	display->type_aux	= 0;
-	display->ypanstep	= 0;
+	display->ypanstep	= 1;
 	display->ywrapstep	= 0;
 	display->can_soft_blank = 1;
 	display->inverse	= 0;
@@ -887,8 +894,8 @@
 		break;
 #endif
 	default:
-		printk(KERN_WARNING "cyber2000: no support for %dbpp\n",
-		       display->var.bits_per_pixel);
+		printk(KERN_WARNING "%s: no support for %dbpp\n",
+		       current_par.dev_name, display->var.bits_per_pixel);
 		dispsw = &fbcon_dummy;
 		break;
 	}
@@ -908,7 +915,7 @@
 		struct fb_cmap *cmap;
 
 		cyber2000fb_update_start(var);
-		cyber2000fb_set_timing(var);
+		cyber2000fb_set_timing(&hw);
 
 		if (display->cmap.len)
 			cmap = &display->cmap;
@@ -938,10 +945,9 @@
 		return -EINVAL;
 	if (y_bottom > fb_display[con].var.yres_virtual)
 		return -EINVAL;
-/*disabled until we can update the start address properly */
-return -EINVAL;
 
-	cyber2000fb_update_start(var);
+	if (cyber2000fb_update_start(var))
+		return -EINVAL;
 
 	fb_display[con].var.xoffset = var->xoffset;
 	fb_display[con].var.yoffset = var->yoffset;
@@ -970,9 +976,12 @@
 static int
 cyber2000fb_updatevar(int con, struct fb_info *info)
 {
+	int ret = 0;
+
 	if (con == current_par.currcon)
-		cyber2000fb_update_start(&fb_display[con].var);
-	return 0;
+		ret = cyber2000fb_update_start(&fb_display[con].var);
+
+	return ret;
 }
 
 static int
@@ -1020,11 +1029,6 @@
 	}
 }
 
-int __init cyber2000fb_setup(char *options)
-{
-	return 0;
-}
-
 static struct fb_ops cyber2000fb_ops =
 {
 	cyber2000fb_open,
@@ -1038,6 +1042,27 @@
 	cyber2000fb_ioctl
 };
 
+/*
+ * These parameters give
+ * 640x480, hsync 31.5kHz, vsync 60Hz
+ */
+static struct fb_videomode __initdata
+cyber2000fb_default_mode = {
+	name:		NULL,
+	refresh:	60,
+	xres:		640,
+	yres:		480,
+	pixclock:	39722,
+	left_margin:	56,
+	right_margin:	16,
+	upper_margin:	34,
+	lower_margin:	9,
+	hsync_len:	88,
+	vsync_len:	2,
+	sync:		FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	vmode:		FB_VMODE_NONINTERLACED
+};
+
 static void __init 
 cyber2000fb_init_fbinfo(void)
 {
@@ -1063,23 +1088,6 @@
 	 * setup initial parameters
 	 */
 	memset(&init_var, 0, sizeof(init_var));
-	init_var.xres_virtual		=
-	init_var.xres			= DEFAULT_XRES;
-	init_var.yres_virtual		=
-	init_var.yres			= DEFAULT_YRES;
-	init_var.bits_per_pixel		= DEFAULT_BPP;
-
-	/*
-	 * These parameters give
-	 * 640x480, hsync 31.5kHz, vsync 60Hz
-	 */
-	init_var.left_margin		= 56;
-	init_var.right_margin		= 16;
-	init_var.upper_margin		= 34;
-	init_var.lower_margin		= 9;
-	init_var.hsync_len		= 88;
-	init_var.vsync_len		= 2;
-	init_var.pixclock		= 39722;
 
 	init_var.red.msb_right		= 0;
 	init_var.green.msb_right	= 0;
@@ -1134,8 +1142,81 @@
 	init_var.height			= -1;
 	init_var.width			= -1;
 	init_var.accel_flags		= FB_ACCELF_TEXT;
-	init_var.sync			= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;
-	init_var.vmode			= FB_VMODE_NONINTERLACED;
+}
+
+/*
+ * Cyber2000 options:
+ *
+ *  font:fontname
+ *	Set the fontname
+ *
+ *  res:XxY
+ *	Set the default display resolution
+ */
+static void __init
+cyber2000fb_parse_font(char *opt)
+{
+	strcpy(fb_info.fontname, opt);
+}
+
+static struct options {
+	char *name;
+	void (*parse)(char *opt);
+} opt_table[] __initdata = {
+	{ "font",	cyber2000fb_parse_font		},
+	{ NULL,		NULL				}
+};
+
+int __init
+cyber2000fb_setup(char *options)
+{
+	struct options *optp;
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	cyber2000fb_init_fbinfo();
+
+	for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) {
+		if (!*opt)
+			continue;
+
+		for (optp = opt_table; optp->name; optp++) {
+			int optlen;
+
+			optlen = strlen(optp->name);
+
+			if (strncmp(opt, optp->name, optlen) == 0 &&
+			    opt[optlen] == ':') {
+				optp->parse(opt + optlen + 1);
+				break;
+			}
+		}
+
+		if (!optp->name)
+			printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n",
+				opt);
+	}
+	return 0;
+}
+
+static char igs_regs[] __initdata = {
+	0x10, 0x10,			0x12, 0x00,	0x13, 0x00,
+/*	0x30, 0x21,*/	0x31, 0x00,	0x32, 0x00,	0x33, 0x01,
+	0x50, 0x00,	0x51, 0x00,	0x52, 0x00,	0x53, 0x00,
+	0x54, 0x00,	0x55, 0x00,	0x56, 0x00,	0x57, 0x01,
+	0x58, 0x00,	0x59, 0x00,	0x5a, 0x00,
+	0x70, 0x0b,/*	0x71, 0x10,	0x72, 0x45,*/	0x73, 0x30,
+	0x74, 0x1b,	0x75, 0x1e,	0x76, 0x00,	0x7a, 0xc8
+};
+
+static void __init cyber2000fb_hw_init(void)
+{
+	int i;
+
+	for (i = 0; i < sizeof(igs_regs); i += 2)
+		cyber2000_grphw(igs_regs[i], igs_regs[i+1]);
 }
 
 /*
@@ -1145,37 +1226,96 @@
 {
 	struct pci_dev *dev;
 	u_int h_sync, v_sync;
-	u_long base_p, base_v;
+	u_long mmio_base, smem_base, smem_size;
+	int err = 0;
+
+	dev = pci_find_device(PCI_VENDOR_ID_INTERG,
+			      PCI_DEVICE_ID_INTERG_2000, NULL);
+
+	if (!dev)
+		dev = pci_find_device(PCI_VENDOR_ID_INTERG,
+				      PCI_DEVICE_ID_INTERG_2010, NULL);
 
-	dev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, NULL);
 	if (!dev)
 		return -ENXIO;
 
-	/* this should be done by PCI generic code */
-	base_p = 0x80000000 + dev->resource[0].start;
+	sprintf(current_par.dev_name, "CyberPro%4X", dev->device);
+
+	smem_base = dev->resource[0].start;
+	mmio_base = dev->resource[0].start + 0x00800000;
 
 	/*
-	 * This should be ioremap'd, thus:
-	 *
-	 * base_v = ioremap(dev->resource[0].start, dev->resource[0].end - dev->resource[0].start + 1);
+	 * Map in the registers
 	 */
-	base_v = (u_long)bus_to_virt(dev->resource[0].start);
+	if (!request_mem_region(mmio_base, MMIO_SIZE, "memory mapped I/O")) {
+		printk("%s: memory mapped IO in use\n",
+		       current_par.dev_name);
+		return -EBUSY;
+	}
 
-	/*FIXME*/
-	CyberRegs = base_v + 0x00800000;
+	CyberRegs = ioremap(mmio_base, MMIO_SIZE);
+	if (!CyberRegs) {
+		printk("%s: unable to map memory mapped IO\n",
+		       current_par.dev_name);
+		err = -ENOMEM;
+		goto release_mmio_resource;
+	}
 
 	cyber2000_outb(0x18, 0x46e8);
 	cyber2000_outb(0x01, 0x102);
 	cyber2000_outb(0x08, 0x46e8);
 
+	/*
+	 * get the video RAM size from the VGA register.
+	 * This should have been already initialised by the BIOS,
+	 * but if it's garbage, claim default 1MB VRAM (woody)
+	 */
+	cyber2000_outb(0x72, 0x3ce);
+	switch (cyber2000_inb(0x3cf) & 3) {
+	case 2:	 smem_size = 0x00400000; break;
+	case 1:	 smem_size = 0x00200000; break;
+	default: smem_size = 0x00100000; break;
+	}
+
+	/*
+	 * Map in screen memory
+	 */
+	if (!request_mem_region(smem_base, smem_size, "frame buffer")) {
+		printk("%s: frame buffer in use\n",
+		       current_par.dev_name);
+		err = -EBUSY;
+		goto release_mmio;
+	}
+
+	current_par.screen_base = ioremap(smem_base, smem_size);
+	if (!current_par.screen_base) {
+		printk("%s: unable to map screen memory\n",
+		       current_par.dev_name);
+		err = -ENOMEM;
+		goto release_smem_resource;
+	}
+current_par.screen_base += IO_FUDGE_FACTOR;
+	current_par.screen_size   = smem_size;
+	current_par.screen_base_p = smem_base + 0x80000000;
+	current_par.regs_base_p   = mmio_base + 0x80000000;
+	current_par.currcon	  = -1;
+
 	cyber2000fb_init_fbinfo();
 
-	current_par.currcon		= -1;
-	current_par.screen_base_p	= base_p;
-	current_par.screen_base		= base_v;
-	current_par.screen_size		= 0x00200000;
-	current_par.regs_base_p		= base_p + 0x00800000;
+	if (!fb_find_mode(&init_var, &fb_info, NULL,
+	    NULL, 0, &cyber2000fb_default_mode, 8)) {
+		printk("%s: no valid mode found\n",
+			current_par.dev_name);
+		goto release_smem_resource;
+	}
+
+	init_var.yres_virtual = smem_size * 8 /
+			(init_var.bits_per_pixel * init_var.xres_virtual);
 
+	if (init_var.yres_virtual < init_var.yres)
+		init_var.yres_virtual = init_var.yres;
+    
+	cyber2000fb_hw_init();
 	cyber2000fb_set_var(&init_var, -1, &fb_info);
 
 	h_sync = 1953125000 / init_var.pixclock;
@@ -1184,24 +1324,44 @@
 	v_sync = h_sync / (init_var.yres + init_var.upper_margin +
 		 init_var.lower_margin + init_var.vsync_len);
 
-	printk("Cyber2000: %ldkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+	printk("%s: %ldkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+		current_par.dev_name,
 		current_par.screen_size >> 10,
 		init_var.xres, init_var.yres,
 		h_sync / 1000, h_sync % 1000, v_sync);
 
-	if (register_framebuffer(&fb_info) < 0)
-		return -EINVAL;
+	if (register_framebuffer(&fb_info) < 0) {
+		err = -EINVAL;
+		goto release_smem;
+	}
+
+	current_par.initialised = 1;
 
 	MOD_INC_USE_COUNT;	/* TODO: This driver cannot be unloaded yet */
 	return 0;
-}
 
+release_smem:
+	iounmap(current_par.screen_base);
+release_smem_resource:
+	release_mem_region(smem_base, smem_size);
+release_mmio:
+	iounmap(CyberRegs);
+release_mmio_resource:
+	release_mem_region(mmio_base, MMIO_SIZE);
 
+	return err;
+}
 
 #ifdef MODULE
 int __init init_module(void)
 {
-	return cyber2000fb_init();
+	int ret;
+
+	ret = cyber2000fb_init();
+	if (ret)
+		return ret;
+
+	return 0;
 }
 
 void cleanup_module(void)
@@ -1210,6 +1370,12 @@
 	   decremented to zero */
 	unregister_framebuffer(&fb_info);
 	/* TODO: clean up ... */
+
+	iounmap(current_par.screen_base);
+	iounmap(CyberRegs);
+
+	release_mem_region(smem_base, current_par.screen_size);
+	release_mem_region(mmio_base, MMIO_SIZE);
 }
 
 #endif				/* MODULE */
diff -u --recursive --new-file v2.3.24/linux/drivers/video/cyber2000fb.h linux/drivers/video/cyber2000fb.h
--- v2.3.24/linux/drivers/video/cyber2000fb.h	Thu Jun 17 01:11:35 1999
+++ linux/drivers/video/cyber2000fb.h	Thu Oct 28 10:16:02 1999
@@ -5,13 +5,14 @@
  */
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
-#define cyber2000_outb(dat,reg)	(CyberRegs[reg] = dat)
-#define cyber2000_outw(dat,reg)	(*(unsigned short *)&CyberRegs[reg] = dat)
-#define cyber2000_outl(dat,reg)	(*(unsigned long *)&CyberRegs[reg] = dat)
-
-#define cyber2000_inb(reg)	(CyberRegs[reg])
-#define cyber2000_inw(reg)	(*(unsigned short *)&CyberRegs[reg])
-#define cyber2000_inl(reg)	(*(unsigned long *)&CyberRegs[reg])
+
+#define cyber2000_outb(dat,reg)	writeb(dat, CyberRegs + reg)
+#define cyber2000_outw(dat,reg)	writew(dat, CyberRegs + reg)
+#define cyber2000_outl(dat,reg)	writel(dat, CyberRegs + reg)
+
+#define cyber2000_inb(reg)	readb(CyberRegs + reg)
+#define cyber2000_inw(reg)	readw(CyberRegs + reg)
+#define cyber2000_inl(reg)	readl(CyberRegs + reg)
 
 static inline void cyber2000_crtcw(int reg, int val)
 {
@@ -40,7 +41,7 @@
 }
 
 struct cyber2000fb_par {
-	unsigned long	screen_base;
+	char *		screen_base;
 	unsigned long	screen_base_p;
 	unsigned long	regs_base;
 	unsigned long	regs_base_p;
@@ -48,6 +49,9 @@
 	unsigned long	screen_size;
 	unsigned int	palette_size;
 	  signed int	currcon;
+	char		dev_name[32];
+	unsigned int	initialised;
+
 	/*
 	 * palette
 	 */
@@ -69,10 +73,32 @@
 	} c_table;
 };
 
-struct res {
-	int	xres;
-	int	yres;
-	unsigned char crtc_regs[18];
-	unsigned char crtc_ofl;
-	unsigned char clk_regs[4];
-};
+#define PIXFORMAT_8BPP		0
+#define PIXFORMAT_16BPP		1
+#define PIXFORMAT_24BPP		2
+
+#define VISUALID_256		1
+#define VISUALID_64K		2
+#define VISUALID_16M		4
+#define VISUALID_32K		6
+
+#define CO_CMD_L_PATTERN_FGCOL	0x8000
+#define CO_CMD_L_INC_LEFT	0x0004
+#define CO_CMD_L_INC_UP		0x0002
+
+#define CO_CMD_H_SRC_PIXMAP	0x2000
+#define CO_CMD_H_BLITTER	0x0800
+
+#define CO_REG_CONTROL		0xbf011
+#define CO_REG_SRC_WIDTH	0xbf018
+#define CO_REG_PIX_FORMAT	0xbf01c
+#define CO_REG_FORE_MIX		0xbf048
+#define CO_REG_FOREGROUND	0xbf058
+#define CO_REG_WIDTH		0xbf060
+#define CO_REG_HEIGHT		0xbf062
+#define CO_REG_X_PHASE		0xbf078
+#define CO_REG_CMD_L		0xbf07c
+#define CO_REG_CMD_H		0xbf07e
+#define CO_REG_SRC_PTR		0xbf170
+#define CO_REG_DEST_PTR		0xbf178
+#define CO_REG_DEST_WIDTH	0xbf218
diff -u --recursive --new-file v2.3.24/linux/drivers/video/fbcon-mac.c linux/drivers/video/fbcon-mac.c
--- v2.3.24/linux/drivers/video/fbcon-mac.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/video/fbcon-mac.c	Sun Oct 31 15:01:51 1999
@@ -455,7 +455,7 @@
   u8 *dest, bit;
   u16 *dest16;
   u32 *dest32;
-  u8 pixel;
+  u8 pixel=0;
 
   switch (p->var.bits_per_pixel) {
   case 1:
diff -u --recursive --new-file v2.3.24/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.3.24/linux/drivers/video/fbmem.c	Fri Oct 22 13:21:51 1999
+++ linux/drivers/video/fbmem.c	Thu Oct 28 14:34:46 1999
@@ -646,16 +646,12 @@
 	return 0;
 }
 
-static struct proc_dir_entry *proc_fbmem;
-
 void __init 
 fbmem_init(void)
 {
 	int i;
 
-	proc_fbmem = create_proc_entry("fb", 0, 0);
-	if (proc_fbmem)
-		proc_fbmem->read_proc = fbmem_read_proc;
+	create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL);
 
 	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
 		printk("unable to get major %d for fb devs\n", FB_MAJOR);
diff -u --recursive --new-file v2.3.24/linux/drivers/zorro/proc.c linux/drivers/zorro/proc.c
--- v2.3.24/linux/drivers/zorro/proc.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/zorro/proc.c	Thu Oct 28 14:34:46 1999
@@ -134,13 +134,6 @@
 	return (count > cnt) ? cnt : count;
 }
 
-static struct proc_dir_entry proc_zorro_devices = {
-	PROC_BUS_ZORRO_DEVICES, 7, "devices",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	get_zorro_dev_info
-};
-
 static struct proc_dir_entry *proc_bus_zorro_dir;
 
 static int __init zorro_proc_attach_device(u_int slot)
@@ -165,7 +158,7 @@
 	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
 		return;
 	proc_bus_zorro_dir = create_proc_entry("zorro", S_IFDIR, proc_bus);
-	proc_register(proc_bus_zorro_dir, &proc_zorro_devices);
+	create_proc_info_entry("devices", 0, proc_bus_zorro_dir, get_zorro_dev_info);
 	for (slot = 0; slot < zorro_num_autocon; slot++)
 	    zorro_proc_attach_device(slot);
 }
diff -u --recursive --new-file v2.3.24/linux/fs/Config.in linux/fs/Config.in
--- v2.3.24/linux/fs/Config.in	Wed Oct 27 16:34:12 1999
+++ linux/fs/Config.in	Thu Oct 28 14:45:16 1999
@@ -58,6 +58,12 @@
 fi
 tristate 'ROM filesystem support' CONFIG_ROMFS_FS
 tristate 'Second extended fs support' CONFIG_EXT2_FS
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   tristate 'BFS filesystem (read only) support (EXPERIMENTAL)' CONFIG_BFS_FS
+   if [ "$CONFIG_BFS_FS" != "n" ]; then
+      bool '  BFS filesystem write support (DANGEROUS)' CONFIG_BFS_FS_WRITE
+   fi
+fi
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
 if [ "$CONFIG_SYSV_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  SYSV filesystem write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE
diff -u --recursive --new-file v2.3.24/linux/fs/Makefile linux/fs/Makefile
--- v2.3.24/linux/fs/Makefile	Tue Sep  7 12:14:07 1999
+++ linux/fs/Makefile	Thu Oct 28 14:45:16 1999
@@ -18,7 +18,7 @@
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
 		hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \
-		nfsd nls devpts adfs partitions qnx4 udf
+		nfsd nls devpts adfs partitions qnx4 udf bfs
 
 SUB_DIRS := partitions
 
@@ -84,6 +84,14 @@
 endif
 endif
 
+ifeq ($(CONFIG_BFS_FS),y)
+SUB_DIRS += bfs
+else
+  ifeq ($(CONFIG_BFS_FS),m)
+  MOD_SUB_DIRS += bfs
+  endif
+endif
+ 
 ifeq ($(CONFIG_ISO9660_FS),y)
 SUB_DIRS += isofs
 else
diff -u --recursive --new-file v2.3.24/linux/fs/bfs/Makefile linux/fs/bfs/Makefile
--- v2.3.24/linux/fs/bfs/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/fs/bfs/Makefile	Thu Oct 28 14:45:16 1999
@@ -0,0 +1,14 @@
+#
+# Makefile for BFS filesystem.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main Makefile...
+
+O_TARGET := bfs.o
+O_OBJS   := inode.o file.o dir.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.24/linux/fs/bfs/bfs_defs.h linux/fs/bfs/bfs_defs.h
--- v2.3.24/linux/fs/bfs/bfs_defs.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/bfs/bfs_defs.h	Fri Oct 29 11:05:08 1999
@@ -0,0 +1,14 @@
+#define su_lasti	u.bfs_sb.si_lasti
+#define su_blocks	u.bfs_sb.si_blocks
+#define su_freeb	u.bfs_sb.si_freeb
+#define su_freei	u.bfs_sb.si_freei
+#define su_lf_ioff	u.bfs_sb.si_lf_ioff
+#define su_lf_sblk	u.bfs_sb.si_lf_sblk
+#define su_lf_eblk	u.bfs_sb.si_lf_eblk
+#define su_imap		u.bfs_sb.si_imap
+#define su_sbh		u.bfs_sb.si_sbh
+#define su_bfs_sb	u.bfs_sb.si_bfs_sb
+
+#define iu_dsk_ino	u.bfs_i.i_dsk_ino
+#define iu_sblock	u.bfs_i.i_sblock
+#define iu_eblock	u.bfs_i.i_eblock
diff -u --recursive --new-file v2.3.24/linux/fs/bfs/dir.c linux/fs/bfs/dir.c
--- v2.3.24/linux/fs/bfs/dir.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/bfs/dir.c	Fri Oct 29 11:05:08 1999
@@ -0,0 +1,382 @@
+/*
+ *	fs/bfs/dir.c
+ *	BFS directory operations.
+ *	Copyright (C) 1999  Tigran Aivazian <tigran@ocston.org>
+ */
+
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/bfs_fs.h>
+#include <linux/locks.h>
+
+#include "bfs_defs.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...)	printk(x)
+#else
+#define DBG(x...)
+#endif
+
+static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino);
+static struct buffer_head * bfs_find_entry(struct inode * dir, 
+	const char * name, int namelen, struct bfs_dirent ** res_dir);
+
+static ssize_t bfs_dir_read(struct file * f, char * buf, size_t count, loff_t *ppos)
+{
+	return -EISDIR;
+}
+
+static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
+{
+	struct inode * dir = f->f_dentry->d_inode;
+	struct buffer_head * bh;
+	struct bfs_dirent * de;
+	kdev_t dev = dir->i_dev;
+	unsigned int offset;
+	int block;
+
+	if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) {
+		printk(KERN_ERR "BFS-fs: %s(): Bad inode or not a directory %s:%08lx\n",
+			__FUNCTION__, bdevname(dev), dir->i_ino);
+		return -EBADF;
+	}
+
+	if (f->f_pos & (BFS_DIRENT_SIZE-1)) {
+		printk(KERN_ERR "BFS-fs: %s(): Bad f_pos=%08lx for %s:%08lx\n", 
+			__FUNCTION__, (unsigned long)f->f_pos, bdevname(dev), dir->i_ino);
+		return -EBADF;
+	}
+
+	while (f->f_pos < dir->i_size) {
+		offset = f->f_pos & (BFS_BSIZE-1);
+		block = dir->iu_sblock + f->f_pos/BFS_BSIZE;
+		bh = bread(dev, block, BFS_BSIZE);
+		if (!bh) {
+			f->f_pos += BFS_BSIZE - offset;
+			continue;
+		}
+		do {
+			de = (struct bfs_dirent *)(bh->b_data + offset);
+			if (de->ino) {
+				int size = strnlen(de->name, BFS_NAMELEN);
+				if (filldir(dirent, de->name, size, f->f_pos, de->ino) < 0) {
+					brelse(bh);
+					return 0;
+				}
+			}
+			offset += BFS_DIRENT_SIZE;
+			f->f_pos += BFS_DIRENT_SIZE;
+		} while (offset < BFS_BSIZE && f->f_pos < dir->i_size);
+		brelse(bh);
+	}
+
+	UPDATE_ATIME(dir);
+	return 0;	
+}
+
+static struct file_operations bfs_dir_operations = {
+	llseek:			NULL,
+	read:			bfs_dir_read,
+	write:			NULL,
+	readdir:		bfs_readdir,
+	poll:			NULL,
+	ioctl:			NULL,
+	mmap:			NULL,
+	open:			NULL,
+	flush:			NULL,
+	release:		NULL,
+	fsync:			file_fsync,
+	fasync:			NULL,
+	check_media_change:	NULL,
+	revalidate:		NULL,
+};
+
+extern void dump_imap(const char *, struct super_block *);
+
+static int bfs_create(struct inode * dir, struct dentry * dentry, int mode)
+{
+	int err;
+	struct inode * inode;
+	struct super_block * s = dir->i_sb;
+	unsigned long ino;
+
+	inode = get_empty_inode();
+	if (!inode)
+		return -ENOSPC;
+	inode->i_sb = s;
+	ino = find_first_zero_bit(s->su_imap, s->su_lasti);
+	if (ino > s->su_lasti) {
+		iput(inode);
+		return -ENOSPC;
+	}
+	set_bit(ino, s->su_imap);	
+	s->su_freei--;
+	inode->i_dev = s->s_dev;
+	inode->i_uid = current->fsuid;
+	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	inode->i_blocks = inode->i_blksize = 0;
+	inode->i_op = &bfs_file_inops;
+	inode->i_mode = mode;
+	inode->i_ino = inode->iu_dsk_ino = ino;
+	inode->iu_sblock = inode->iu_eblock = 0;
+	insert_inode_hash(inode);
+        mark_inode_dirty(inode);
+	dump_imap("create",s);
+
+	err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino);
+	if (err) {
+		inode->i_nlink--;
+		mark_inode_dirty(inode);
+		iput(inode);
+		return err;
+	}
+	d_instantiate(dentry, inode);
+	return 0;
+}
+
+static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry)
+{
+	struct inode * inode = NULL;
+	struct buffer_head * bh;
+	struct bfs_dirent * de;
+
+	if (dentry->d_name.len > BFS_NAMELEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+	if (bh) {
+		unsigned long ino = le32_to_cpu(de->ino);
+		brelse(bh);
+		inode = iget(dir->i_sb, ino);
+		if (!inode)
+			return ERR_PTR(-EACCES);
+	}
+	d_add(dentry, inode);
+	return NULL;
+}
+
+static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new)
+{
+	struct inode * inode = old->d_inode;
+	int err;
+
+	if (S_ISDIR(inode->i_mode))
+		return -EPERM;
+
+	err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino);
+	if (err)
+		return err;
+	inode->i_nlink++;
+	inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	inode->i_count++;
+	d_instantiate(new, inode);
+	return 0;
+}
+
+
+static int bfs_unlink(struct inode * dir, struct dentry * dentry)
+{
+	int error = -ENOENT;
+	struct inode * inode;
+	struct buffer_head * bh;
+	struct bfs_dirent * de;
+
+	inode = dentry->d_inode;
+	bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+	if (!bh || de->ino != inode->i_ino) 
+		goto out_brelse;
+
+	if (!inode->i_nlink) {
+		printk(KERN_WARNING 
+		"BFS-fs: %s(): unlinking non-existent file %s:%lu (nlink=%d)\n",
+		__FUNCTION__, bdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
+		inode->i_nlink = 1;
+	}
+	de->ino = 0;
+	dir->i_version = ++event;
+	mark_buffer_dirty(bh, 1);
+	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	mark_inode_dirty(dir);
+	inode->i_nlink--;
+	inode->i_ctime = dir->i_ctime;
+	mark_inode_dirty(inode);
+	d_delete(dentry);
+	error = 0;
+
+out_brelse:
+	brelse(bh);
+	return error;
+}
+
+static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, 
+			struct inode * new_dir, struct dentry * new_dentry)
+{
+	struct inode * old_inode, * new_inode;
+	struct buffer_head * old_bh, * new_bh;
+	struct bfs_dirent * old_de, * new_de;		
+	int error = -ENOENT;
+
+	old_bh = new_bh = NULL;
+	old_inode = old_dentry->d_inode;
+	if (S_ISDIR(old_inode->i_mode))
+		return -EINVAL;
+
+	old_bh = bfs_find_entry(old_dir, 
+				old_dentry->d_name.name, 
+				old_dentry->d_name.len, &old_de);
+
+	if (!old_bh || old_de->ino != old_inode->i_ino)
+		goto end_rename;
+
+	error = -EPERM;
+	new_inode = new_dentry->d_inode;
+	new_bh = bfs_find_entry(new_dir, 
+				new_dentry->d_name.name, 
+				new_dentry->d_name.len, &new_de);
+
+	if (new_bh && !new_inode) {
+		brelse(new_bh);
+		new_bh = NULL;
+	}
+	if (!new_bh) {
+		error = bfs_add_entry(new_dir, 
+					new_dentry->d_name.name,
+			 		new_dentry->d_name.len, old_inode->i_ino);
+		if (error)
+			goto end_rename;
+	}
+	old_de->ino = 0;
+	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+	old_dir->i_version = ++event;
+	mark_inode_dirty(old_dir);
+	if (new_inode) {
+		new_inode->i_nlink--;
+		new_inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(new_inode);
+	}
+	mark_buffer_dirty(old_bh, 1);
+	error = 0;
+
+end_rename:
+	brelse(old_bh);
+	brelse(new_bh);
+	return error;
+}
+
+struct inode_operations bfs_dir_inops = {
+	default_file_ops:	&bfs_dir_operations,
+	create:			bfs_create,
+	lookup:			bfs_lookup,
+	link:			bfs_link,
+	unlink:			bfs_unlink,
+	symlink:		NULL,
+	mkdir:			NULL,
+	rmdir:			NULL,
+	mknod:			NULL,
+	rename:			bfs_rename,
+	readlink:		NULL,
+	follow_link:		NULL,
+	get_block:		NULL,
+	readpage:		NULL,
+	writepage:		NULL,
+	flushpage:		NULL,
+	truncate:		NULL,
+	permission:		NULL,
+	smap:			NULL,
+	revalidate:		NULL
+};
+
+static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino)
+{
+	struct buffer_head * bh;
+	struct bfs_dirent * de;
+	int block, sblock, eblock, off;
+	kdev_t dev;
+	int i;
+
+	DBG(KERN_ERR "BFS-fs: %s(%s,%d)\n", __FUNCTION__, name, namelen);
+
+	if (!namelen)
+		return -ENOENT;
+	if (namelen > BFS_NAMELEN)
+		return -ENAMETOOLONG;
+
+	dev = dir->i_dev;
+	sblock = dir->iu_sblock;
+	eblock = dir->iu_eblock;
+	for (block=sblock; block<=eblock; block++) {
+		bh = bread(dev, block, BFS_BSIZE);
+		if(!bh) 
+			return -ENOSPC;
+		for (off=0; off<BFS_BSIZE; off+=BFS_DIRENT_SIZE) {
+			de = (struct bfs_dirent *)(bh->b_data + off);
+			if (!de->ino) {
+				if ((block-sblock)*BFS_BSIZE + off >= dir->i_size) {
+					dir->i_size += BFS_DIRENT_SIZE;
+					dir->i_ctime = CURRENT_TIME;
+				}
+				dir->i_mtime = CURRENT_TIME;
+				mark_inode_dirty(dir);
+				dir->i_version = ++event;
+				de->ino = ino;
+				for (i=0; i<BFS_NAMELEN; i++)
+					de->name[i] = (i < namelen) ? name[i] : 0;
+				mark_buffer_dirty(bh, 1);
+				brelse(bh);
+				return 0;
+			}
+		}
+		brelse(bh);
+	}
+	return -ENOSPC;
+}
+
+static inline int bfs_namecmp(int len, const char * name, const char * buffer)
+{
+	if (len < BFS_NAMELEN && buffer[len])
+		return 0;
+	return !memcmp(name, buffer, len);
+}
+
+static struct buffer_head * bfs_find_entry(struct inode * dir, 
+	const char * name, int namelen, struct bfs_dirent ** res_dir)
+{
+	unsigned long block, offset;
+	struct buffer_head * bh;
+	struct bfs_sb_info * info;
+	struct bfs_dirent * de;
+
+	*res_dir = NULL;
+	info = &dir->i_sb->u.bfs_sb;
+	if (namelen > BFS_NAMELEN)
+		return NULL;
+	bh = NULL;
+	block = offset = 0;
+	while (block * BFS_BSIZE + offset < dir->i_size) {
+		if (!bh) {
+			bh = bread(dir->i_dev, dir->iu_sblock + block, BFS_BSIZE);
+			if (!bh) {
+				block++;
+				continue;
+			}
+		}
+		de = (struct bfs_dirent *)(bh->b_data + offset);
+		offset += BFS_DIRENT_SIZE;
+		if (de->ino && bfs_namecmp(namelen, name, de->name)) {
+			*res_dir = de;
+			return bh;
+		}
+		if (offset < bh->b_size)
+			continue;
+		brelse(bh);
+		bh = NULL;
+		offset = 0;
+		block++;
+	}
+	brelse(bh);
+	return NULL;
+}
diff -u --recursive --new-file v2.3.24/linux/fs/bfs/file.c linux/fs/bfs/file.c
--- v2.3.24/linux/fs/bfs/file.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/bfs/file.c	Thu Oct 28 14:45:16 1999
@@ -0,0 +1,76 @@
+/*
+ *	fs/bfs/file.c
+ *	BFS file operations.
+ *	Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ */
+
+#include <linux/fs.h>
+#include <linux/bfs_fs.h>
+#include "bfs_defs.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...)	printk(x)
+#else
+#define DBG(x...)
+#endif
+
+static ssize_t bfs_file_write(struct file * f, const char * buf, size_t count, loff_t *ppos)
+{
+	return generic_file_write(f, buf, count, ppos, block_write_partial_page);
+}
+
+static struct file_operations bfs_file_operations = {
+	llseek:			NULL,
+	read:			generic_file_read,
+	write:			bfs_file_write,
+	readdir:		NULL,
+	poll:			NULL,
+	ioctl:			NULL,
+	mmap:			generic_file_mmap,
+	open:			NULL,
+	flush:			NULL,
+	release:		NULL,
+	fsync:			NULL,
+	fasync:			NULL,
+	check_media_change:	NULL,
+	revalidate:		NULL,
+};
+
+static int bfs_get_block(struct inode * inode, long block, 
+	struct buffer_head * bh_result, int create)
+{
+	if (!create) {
+		bh_result->b_dev = inode->i_dev;
+		bh_result->b_blocknr = inode->iu_sblock + block;
+		bh_result->b_state |= (1UL << BH_Mapped);
+		return 0;
+	} else 
+		DBG(KERN_ERR "BFS-fs: %s(create=%d) impossible!\n", 
+			__FUNCTION__, create);
+	return -EIO;
+}
+
+struct inode_operations bfs_file_inops = {
+	default_file_ops:	&bfs_file_operations,
+	create:			NULL,
+	lookup:			NULL,
+	link:			NULL,
+	unlink:			NULL,
+	symlink:		NULL,
+	mkdir:			NULL,
+	rmdir:			NULL,
+	mknod:			NULL,
+	rename:			NULL,
+	readlink:		NULL,
+	follow_link:		NULL,
+	get_block:		bfs_get_block,	
+	readpage:		block_read_full_page,
+	writepage:		block_write_full_page,
+	flushpage:		block_flushpage,
+	truncate:		NULL,
+	permission:		NULL,
+	smap:			NULL,
+	revalidate:		NULL
+};
diff -u --recursive --new-file v2.3.24/linux/fs/bfs/inode.c linux/fs/bfs/inode.c
--- v2.3.24/linux/fs/bfs/inode.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/bfs/inode.c	Fri Oct 29 11:05:08 1999
@@ -0,0 +1,375 @@
+/*
+ *	fs/bfs/inode.c
+ *	BFS superblock and inode operations.
+ *	Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ *	From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/locks.h>
+#include <linux/bfs_fs.h>
+
+#include <asm/uaccess.h>
+
+#include "bfs_defs.h"
+
+MODULE_AUTHOR("Tigran A. Aivazian");
+MODULE_DESCRIPTION("UnixWare BFS filesystem for Linux");
+EXPORT_NO_SYMBOLS;
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...)	printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void dump_imap(const char *prefix, struct super_block * s);
+
+static void bfs_read_inode(struct inode * inode)
+{
+	unsigned long ino = inode->i_ino;
+	kdev_t dev = inode->i_dev;
+	struct bfs_inode * di;
+	struct buffer_head * bh;
+	int block, off;
+
+	if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
+		printk(KERN_ERR "BFS-fs: %s(): Bad inode number %s:%08lx\n", 
+			__FUNCTION__, bdevname(dev), ino);
+		make_bad_inode(inode);
+		return;
+	}
+
+	block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+	bh = bread(dev, block, BFS_BSIZE);
+	if (!bh) {
+		printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+			__FUNCTION__, bdevname(dev), ino);
+		make_bad_inode(inode);
+		return;
+	}
+
+	off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
+	di = (struct bfs_inode *)bh->b_data + off;
+
+	inode->i_mode = 0x0000FFFF & di->i_mode;
+	if (di->i_vtype == BFS_VDIR) {
+		inode->i_mode |= S_IFDIR;
+		inode->i_op = &bfs_dir_inops;
+	} else if (di->i_vtype == BFS_VREG) {
+		inode->i_mode |= S_IFREG;
+		inode->i_op = &bfs_file_inops;
+	} else 
+		inode->i_op = NULL;
+
+	inode->i_uid = di->i_uid;
+	inode->i_gid = di->i_gid;
+	inode->i_nlink = di->i_nlink;
+	inode->i_size = BFS_FILESIZE(di);
+	inode->i_blocks = BFS_FILEBLOCKS(di);
+	inode->i_blksize = PAGE_SIZE;
+	inode->i_atime = di->i_atime;
+	inode->i_mtime = di->i_mtime;
+	inode->i_ctime = di->i_ctime;
+	inode->i_rdev = 0; /* BFS doesn't have special nodes */
+	inode->iu_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
+	inode->iu_sblock = di->i_sblock;
+	inode->iu_eblock = di->i_eblock;
+
+	brelse(bh);
+}
+
+static void bfs_write_inode(struct inode * inode)
+{
+	unsigned long ino = inode->i_ino;
+	kdev_t dev = inode->i_dev;
+	struct bfs_inode * di;
+	struct buffer_head * bh;
+	int block, off;
+
+	if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
+		printk(KERN_ERR "BFS-fs: %s(): Bad inode number %s:%08lx\n", 
+			__FUNCTION__, bdevname(dev), ino);
+		return;
+	}
+
+	block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+	bh = bread(dev, block, BFS_BSIZE);
+	if (!bh) {
+		printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+			__FUNCTION__, bdevname(dev), ino);
+		return;
+	}
+
+	off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
+	di = (struct bfs_inode *)bh->b_data + off;
+
+	if (inode->i_ino == BFS_ROOT_INO)
+		di->i_vtype = BFS_VDIR;
+	else
+		di->i_vtype = BFS_VREG;
+
+	di->i_ino = inode->i_ino;
+	di->i_mode = inode->i_mode;
+	di->i_uid = inode->i_uid;
+	di->i_gid = inode->i_gid;
+	di->i_nlink = inode->i_nlink;
+	di->i_atime = inode->i_atime;
+	di->i_mtime = inode->i_mtime;
+	di->i_ctime = inode->i_ctime;
+	di->i_sblock = inode->iu_sblock;
+	di->i_eblock = inode->iu_eblock;
+	di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
+
+	mark_buffer_dirty(bh, 1);
+	brelse(bh);
+}
+
+static void bfs_delete_inode(struct inode * inode)
+{
+	unsigned long ino = inode->i_ino;
+	kdev_t dev = inode->i_dev;
+	struct bfs_inode * di;
+	struct buffer_head * bh;
+	int block, off;
+	struct super_block * s = inode->i_sb;
+
+	DBG(KERN_ERR "%s(ino=%08lx)\n", __FUNCTION__, inode->i_ino);
+
+	if (!inode)
+		return;
+	if (!inode->i_dev) {
+		printk(KERN_ERR "BFS-fs: free_inode(%08lx) !dev\n", inode->i_ino);
+		return;
+	}
+	if (inode->i_count > 1) {
+		printk(KERN_ERR "BFS-fs: free_inode(%08lx) count=%d\n", 
+			inode->i_ino, inode->i_count);
+		return;
+	}
+	if (inode->i_nlink) {
+		printk(KERN_ERR "BFS-fs: free_inode(%08lx) nlink=%d\n", 
+			inode->i_ino, inode->i_nlink);
+		return;
+	}
+	if (!inode->i_sb) {
+		printk(KERN_ERR "BFS-fs: free_inode(%08lx) !sb\n", inode->i_ino);
+		return;
+	}
+	if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > inode->i_sb->su_lasti) {
+		printk(KERN_ERR "BFS-fs: free_inode(%08lx) invalid ino\n", inode->i_ino);
+		return;
+	}
+	
+	inode->i_size = 0;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+	bh = bread(dev, block, BFS_BSIZE);
+	if (!bh) {
+		printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+			__FUNCTION__, bdevname(dev), ino);
+		return;
+	}
+	off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
+	di = (struct bfs_inode *)bh->b_data + off;
+	if (di->i_ino) {
+		s->su_freeb += BFS_FILEBLOCKS(di);
+		s->su_freei++;
+		clear_bit(di->i_ino, s->su_imap);
+		dump_imap("delete_inode", s);
+	}
+	di->i_ino = 0;
+	di->i_sblock = 0;
+	mark_buffer_dirty(bh, 1);
+	brelse(bh);
+	clear_inode(inode);
+}
+
+static void bfs_put_super(struct super_block *s)
+{
+	brelse(s->su_sbh);
+	kfree(s->su_imap);
+	MOD_DEC_USE_COUNT;
+}
+
+static int bfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz)
+{
+	struct statfs tmp;
+
+	tmp.f_type = BFS_MAGIC;
+	tmp.f_bsize = s->s_blocksize;
+	tmp.f_blocks = s->su_blocks;
+	tmp.f_bfree = tmp.f_bavail = s->su_freeb;
+	tmp.f_files = s->su_lasti + 1 - BFS_ROOT_INO;
+	tmp.f_ffree = s->su_freei;
+	tmp.f_fsid.val[0] = s->s_dev;
+	tmp.f_namelen = BFS_NAMELEN;
+	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static void bfs_write_super(struct super_block *s)
+{
+	if (!(s->s_flags & MS_RDONLY))
+		mark_buffer_dirty(s->su_sbh, 1);
+	s->s_dirt = 0;
+}
+
+static struct super_operations bfs_sops = {
+	read_inode:	bfs_read_inode,
+	write_inode:	bfs_write_inode,
+	put_inode:	NULL,
+	delete_inode:	bfs_delete_inode,
+	notify_change:	NULL,
+	put_super:	bfs_put_super,
+	write_super:	bfs_write_super,
+	statfs:		bfs_statfs,
+	remount_fs:	NULL,
+	clear_inode:	NULL,
+	umount_begin:	NULL
+};
+
+void dump_imap(const char *prefix, struct super_block * s)
+{
+#if 0
+	int i;
+	char *tmpbuf = (char *)get_free_page(GFP_KERNEL);
+
+	if (!tmpbuf)
+		return;
+	memset(tmpbuf, 0, 400);
+	for (i=s->su_lasti; i>=0; i--) {
+		if (i>PAGE_SIZE-100) break;
+		if (test_bit(i, s->su_imap))
+			strcat(tmpbuf, "1");
+		else
+			strcat(tmpbuf, "0");
+	}
+	printk(KERN_ERR "BFS-fs: %s: lasti=%d <%s>\n", prefix, s->su_lasti, tmpbuf);
+	free_page((unsigned long)tmpbuf);
+#endif
+}
+
+static struct super_block * bfs_read_super(struct super_block * s, 
+	void * data, int silent)
+{
+	kdev_t dev;
+	struct buffer_head * bh;
+	struct bfs_super_block * bfs_sb;
+	struct inode * inode;
+	int i, imap_len;
+
+	MOD_INC_USE_COUNT;
+	lock_super(s);
+	dev = s->s_dev;
+	set_blocksize(dev, BFS_BSIZE);
+	s->s_blocksize = BFS_BSIZE;
+	s->s_blocksize_bits = BFS_BSIZE_BITS;
+
+	/* read ahead 8K to get inodes as we'll need them in a tick */
+	bh = breada(dev, 0, BFS_BSIZE, 0, 8192);
+	if(!bh)
+		goto out;
+	bfs_sb = (struct bfs_super_block *)bh->b_data;
+	if (bfs_sb->s_magic != BFS_MAGIC) {
+		if (!silent)
+			printk(KERN_ERR "BFS-fs: No BFS filesystem on %s (magic=%08x)\n", 
+					bdevname(dev), bfs_sb->s_magic);
+		goto out;
+	}
+	if (BFS_UNCLEAN(bfs_sb, s) && !silent)
+		printk(KERN_WARNING "BFS-fs: %s is unclean\n", bdevname(dev));
+
+#ifndef CONFIG_BFS_FS_WRITE
+	s->s_flags |= MS_RDONLY; 
+#endif
+	s->s_magic = BFS_MAGIC;
+	s->su_bfs_sb = bfs_sb;
+	s->su_sbh = bh;
+	s->su_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) 
+			+ BFS_ROOT_INO - 1;
+
+	imap_len = s->su_lasti/8 + 1;
+	s->su_imap = kmalloc(imap_len, GFP_KERNEL);
+	if (!s->su_imap)
+		goto out;
+	memset(s->su_imap, 0, imap_len);
+	for (i=0; i<BFS_ROOT_INO; i++)
+		set_bit(i, s->su_imap);
+
+	s->s_op = &bfs_sops;
+	inode = iget(s, BFS_ROOT_INO);
+	if (!inode) {
+		kfree(s->su_imap);
+		goto out;
+	}
+	s->s_root = d_alloc_root(inode);
+	if (!s->s_root) {
+		iput(inode);
+		kfree(s->su_imap);
+		goto out;
+	}
+
+	s->su_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
+	s->su_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS;
+	s->su_freei = 0;
+	s->su_lf_eblk = 0;
+	s->su_lf_sblk = 0;
+	s->su_lf_ioff = 0;
+	for (i=BFS_ROOT_INO; i<=s->su_lasti; i++) {
+		inode = iget(s,i);
+		if (inode->iu_dsk_ino == 0)
+			s->su_freei++;
+		else {
+			set_bit(i, s->su_imap);
+			s->su_freeb -= inode->i_blocks;
+			if (inode->iu_eblock > s->su_lf_eblk) {
+				s->su_lf_eblk = inode->iu_eblock;
+				s->su_lf_sblk = inode->iu_sblock;
+				s->su_lf_ioff = BFS_INO2OFF(i);
+			}
+		}
+		iput(inode);
+	}
+	if (!(s->s_flags & MS_RDONLY)) {
+		mark_buffer_dirty(bh, 1);
+		s->s_dirt = 1;
+	} 
+	dump_imap("read_super", s);
+	unlock_super(s);
+	return s;
+
+out:
+	brelse(bh);
+	s->s_dev = 0;
+	unlock_super(s);
+	MOD_DEC_USE_COUNT;
+	return NULL;
+}
+
+static struct file_system_type bfs_fs_type = {
+	name:		"bfs",
+	fs_flags:	FS_REQUIRES_DEV,
+	read_super:	bfs_read_super,
+	next:		NULL
+};
+
+#ifdef MODULE
+#define init_bfs_fs init_module
+
+void cleanup_module(void)
+{
+	unregister_filesystem(&bfs_fs_type);
+}
+#endif
+
+int __init init_bfs_fs(void)
+{
+	return register_filesystem(&bfs_fs_type);
+}
diff -u --recursive --new-file v2.3.24/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.3.24/linux/fs/binfmt_elf.c	Tue Aug  3 10:18:39 1999
+++ linux/fs/binfmt_elf.c	Fri Oct 29 11:03:07 1999
@@ -415,8 +415,7 @@
 
 	retval = -ENOEXEC;
 	/* First of all, some simple consistency checks */
-	if (elf_ex.e_ident[0] != 0x7f ||
-	    strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0)
+	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
 		goto out;
 
 	if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN)
@@ -538,8 +537,7 @@
 		    (N_MAGIC(interp_ex) != QMAGIC))
 			interpreter_type = INTERPRETER_ELF;
 
-		if (interp_elf_ex.e_ident[0] != 0x7f ||
-		    strncmp(&interp_elf_ex.e_ident[1], "ELF", 3) != 0)
+		if (memcmp(interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
 			interpreter_type &= ~INTERPRETER_ELF;
 
 		retval = -ELIBBAD;
@@ -823,8 +821,7 @@
 	if (retval != sizeof(elf_ex))
 		goto out_putf;
 
-	if (elf_ex.e_ident[0] != 0x7f ||
-	    strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0)
+	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
 		goto out_putf;
 
 	/* First of all, some simple consistency checks */
diff -u --recursive --new-file v2.3.24/linux/fs/binfmt_em86.c linux/fs/binfmt_em86.c
--- v2.3.24/linux/fs/binfmt_em86.c	Tue Aug  3 10:18:39 1999
+++ linux/fs/binfmt_em86.c	Fri Oct 29 11:03:07 1999
@@ -30,20 +30,17 @@
 	/* Make sure this is a Linux/Intel ELF executable... */
 	elf_ex = *((struct elfhdr *)bprm->buf);
 
-        if (elf_ex.e_ident[0] != 0x7f ||
-            strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
-                return  -ENOEXEC;
-        }
+	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+		return  -ENOEXEC;
 
-
-        /* First of all, some simple consistency checks */
-        if ((elf_ex.e_type != ET_EXEC &&
-            elf_ex.e_type != ET_DYN) ||
-           (!((elf_ex.e_machine == EM_386) || (elf_ex.e_machine == EM_486))) ||
-           (!bprm->dentry->d_inode->i_op || !bprm->dentry->d_inode->i_op->default_file_ops ||
-            !bprm->dentry->d_inode->i_op->default_file_ops->mmap)){
-                return -ENOEXEC;
-        }
+	/* First of all, some simple consistency checks */
+	if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
+		(!((elf_ex.e_machine == EM_386) || (elf_ex.e_machine == EM_486))) ||
+		(!bprm->dentry->d_inode->i_op || 
+		!bprm->dentry->d_inode->i_op->default_file_ops ||
+		!bprm->dentry->d_inode->i_op->default_file_ops->mmap)) {
+			return -ENOEXEC;
+	}
 
 	bprm->sh_bang++;	/* Well, the bang-shell is implicit... */
 	dput(bprm->dentry);
diff -u --recursive --new-file v2.3.24/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.24/linux/fs/buffer.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/buffer.c	Mon Nov  1 11:11:48 1999
@@ -58,7 +58,7 @@
   6};
 
 #define BUFSIZE_INDEX(X) ((int) buffersize_index[(X)>>9])
-#define MAX_BUF_PER_PAGE (PAGE_SIZE / 512)
+#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512)
 #define NR_RESERVED (2*MAX_BUF_PER_PAGE)
 #define MAX_UNUSED_BUFFERS NR_RESERVED+20 /* don't ever have more than this 
 					     number of unused buffer heads */
@@ -823,7 +823,7 @@
 	unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit;
 
 	dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
-	tot = nr_lru_pages + nr_free_pages + nr_free_highpages;
+	tot = nr_lru_pages + nr_free_pages - nr_free_highpages;
 	hard_dirty_limit = tot * bdf_prm.b_un.nfract / 100;
 	soft_dirty_limit = hard_dirty_limit >> 1;
 
@@ -1293,13 +1293,17 @@
 static void unmap_underlying_metadata(struct buffer_head * bh)
 {
 #if 0
-	bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
-	if (bh) {
-		unmap_buffer(bh);
-		/* Here we could run brelse or bforget. We use
-		   bforget because it will try to put the buffer
-		   in the freelist. */
-		__bforget(bh);
+	if (buffer_new(bh)) {
+		struct buffer_head *old_bh;
+
+		old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
+		if (old_bh) {
+			unmap_buffer(old_bh);
+			/* Here we could run brelse or bforget. We use
+			   bforget because it will try to put the buffer
+			   in the freelist. */
+			__bforget(old_bh);
+		}
 	}
 #endif
 }
@@ -1313,7 +1317,7 @@
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
 	int err, i;
-	unsigned long block, offset;
+	unsigned long block;
 	struct buffer_head *bh, *head;
 
 	if (!PageLocked(page))
@@ -1323,12 +1327,10 @@
 		create_empty_buffers(page, inode, inode->i_sb->s_blocksize);
 	head = page->buffers;
 
-	offset = page->offset;
-	block = offset >> inode->i_sb->s_blocksize_bits;
-
-	// FIXME: currently we assume page alignment.
-	if (offset & (PAGE_SIZE-1))
-		BUG();
+	/* The page cache is now PAGE_CACHE_SIZE aligned, period.  We handle old a.out
+	 * and others via unaligned private mappings.
+	 */
+	block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 
 	bh = head;
 	i = 0;
@@ -1389,8 +1391,8 @@
 	head = page->buffers;
 
 	bbits = inode->i_sb->s_blocksize_bits;
-	block = page->offset >> bbits;
-	blocks = PAGE_SIZE >> bbits;
+	block = page->index << (PAGE_CACHE_SHIFT - bbits);
+	blocks = PAGE_CACHE_SIZE >> bbits;
 	start_block = offset >> bbits;
 	end_block = (offset + bytes - 1) >> bbits;
 	start_offset = offset & (blocksize - 1);
@@ -1409,9 +1411,6 @@
 		BUG();
 	if (end_block < 0 || end_block >= blocks)
 		BUG();
-	// FIXME: currently we assume page alignment.
-	if (page->offset & (PAGE_SIZE-1))
-		BUG();
 
 	i = 0;
 	bh = head;
@@ -1537,12 +1536,12 @@
 	unsigned long data_offset = offset;
 	int need_balance_dirty;
 
-	offset = inode->i_size - page->offset;
-	if (page->offset>inode->i_size)
+	offset = inode->i_size - (page->index << PAGE_CACHE_SHIFT);
+	if (page->index > (inode->i_size >> PAGE_CACHE_SHIFT))
 		offset = 0;
 	else if (offset >= data_offset)
 		offset = data_offset;
-	bytes += data_offset-offset;
+	bytes += data_offset - offset;
 
 	target_buf = (char *)page_address(page) + offset;
 	target_data = (char *)page_address(page) + data_offset;
@@ -1556,8 +1555,8 @@
 	head = page->buffers;
 
 	bbits = inode->i_sb->s_blocksize_bits;
-	block = page->offset >> bbits;
-	blocks = PAGE_SIZE >> bbits;
+	block = page->index << (PAGE_CACHE_SHIFT - bbits);
+	blocks = PAGE_CACHE_SIZE >> bbits;
 	start_block = offset >> bbits;
 	end_block = (offset + bytes - 1) >> bbits;
 	start_offset = offset & (blocksize - 1);
@@ -1576,9 +1575,6 @@
 		BUG();
 	if (end_block < 0 || end_block >= blocks)
 		BUG();
-	// FIXME: currently we assume page alignment.
-	if (page->offset & (PAGE_SIZE-1))
-		BUG();
 
 	i = 0;
 	bh = head;
@@ -2015,8 +2011,8 @@
 		create_empty_buffers(page, inode, blocksize);
 	head = page->buffers;
 
-	blocks = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
-	iblock = page->offset >> inode->i_sb->s_blocksize_bits;
+	blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits;
+	iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 	bh = head;
 	nr = 0;
 
diff -u --recursive --new-file v2.3.24/linux/fs/coda/file.c linux/fs/coda/file.c
--- v2.3.24/linux/fs/coda/file.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/coda/file.c	Fri Oct 29 16:45:32 1999
@@ -99,7 +99,7 @@
 			      &cont_file, &cont_dentry);
 
         CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", 
-	       coda_inode->i_ino, cii->c_ovp->i_ino, page->offset);
+	       coda_inode->i_ino, cii->c_ovp->i_ino, page->index);
 
         block_read_full_page(&cont_file, page);
         EXIT;
diff -u --recursive --new-file v2.3.24/linux/fs/coda/sysctl.c linux/fs/coda/sysctl.c
--- v2.3.24/linux/fs/coda/sysctl.c	Tue Jul  6 19:08:33 1999
+++ linux/fs/coda/sysctl.c	Thu Oct 28 14:34:46 1999
@@ -476,43 +476,7 @@
 
 */
 
-struct proc_dir_entry proc_fs_coda = {
-        PROC_FS_CODA, 4, "coda",
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-        0, &proc_dir_inode_operations,
-	NULL, NULL,
-	NULL,
-	NULL, NULL
-};
-
-struct proc_dir_entry proc_coda_vfs =  {
-                PROC_VFS_STATS , 9, "vfs_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_vfs_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_upcall =  {
-                PROC_UPCALL_STATS , 12, "upcall_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_upcall_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_permission =  {
-                PROC_PERMISSION_STATS , 16, "permission_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_permission_stats_get_info
-        };
-
-
-struct proc_dir_entry proc_coda_cache_inv =  {
-                PROC_CACHE_INV_STATS , 15, "cache_inv_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_cache_inv_stats_get_info
-        };
+struct proc_dir_entry* proc_fs_coda;
 
 static void coda_proc_modcount(struct inode *inode, int fill)
 {
@@ -525,6 +489,8 @@
 
 #endif
 
+#define coda_proc_create(name,get_info) \
+	create_proc_info_entry(name, 0, proc_fs_coda, get_info)
 
 void coda_sysctl_init()
 {
@@ -535,12 +501,12 @@
 	reset_coda_cache_inv_stats();
 
 #ifdef CONFIG_PROC_FS
-	proc_register(&proc_root_fs,&proc_fs_coda);
-	proc_fs_coda.fill_inode = &coda_proc_modcount;
-	proc_register(&proc_fs_coda,&proc_coda_vfs);
-	proc_register(&proc_fs_coda,&proc_coda_upcall);
-	proc_register(&proc_fs_coda,&proc_coda_permission);
-	proc_register(&proc_fs_coda,&proc_coda_cache_inv);
+	proc_fs_coda = create_proc_entry("coda", S_IFDIR, proc_root_fs);
+	proc_fs_coda->fill_inode = &coda_proc_modcount;
+	coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
+	coda_proc_create("upcall_stats", coda_upcall_stats_get_info);
+	coda_proc_create("permission_stats", coda_permission_stats_get_info);
+	coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info);
 #endif
 
 #ifdef CONFIG_SYSCTL
@@ -560,10 +526,10 @@
 #endif
 
 #if CONFIG_PROC_FS
-        proc_unregister(&proc_fs_coda, proc_coda_cache_inv.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_permission.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_upcall.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_vfs.low_ino);
-	proc_unregister(&proc_root_fs, proc_fs_coda.low_ino);
+        remove_proc_entry("cache_inv_stats", proc_fs_coda);
+        remove_proc_entry("permission_stats", proc_fs_coda);
+        remove_proc_entry("upcall_stats", proc_fs_coda);
+        remove_proc_entry("vfs_stats", proc_fs_coda);
+	remove_proc_entry("coda", proc_root_fs);
 #endif 
 }
diff -u --recursive --new-file v2.3.24/linux/fs/dcache.c linux/fs/dcache.c
--- v2.3.24/linux/fs/dcache.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/dcache.c	Thu Oct 28 13:12:21 1999
@@ -712,7 +712,7 @@
 
 	*--end = '\0';
 	buflen--;
-	if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
+	if (!IS_ROOT(dentry) && list_empty(&dentry->d_hash)) {
 		buflen -= 10;
 		end -= 10;
 		memcpy(end, " (deleted)", 10);
diff -u --recursive --new-file v2.3.24/linux/fs/exec.c linux/fs/exec.c
--- v2.3.24/linux/fs/exec.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/exec.c	Thu Oct 28 13:03:38 1999
@@ -297,7 +297,7 @@
 		mpnt->vm_page_prot = PAGE_COPY;
 		mpnt->vm_flags = VM_STACK_FLAGS;
 		mpnt->vm_ops = NULL;
-		mpnt->vm_offset = 0;
+		mpnt->vm_pgoff = 0;
 		mpnt->vm_file = NULL;
 		mpnt->vm_private_data = (void *) 0;
 		vmlist_modify_lock(current->mm);
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/acl.c linux/fs/ext2/acl.c
--- v2.3.24/linux/fs/ext2/acl.c	Wed May  6 10:56:08 1998
+++ linux/fs/ext2/acl.c	Thu Oct 28 13:23:10 1999
@@ -7,16 +7,16 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+
+
 /*
  * This file will contain the Access Control Lists management for the
  * second extended file system.
  */
 
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
 
 /*
  * ext2_permission ()
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v2.3.24/linux/fs/ext2/balloc.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/ext2/balloc.c	Thu Oct 28 13:23:10 1999
@@ -11,6 +11,12 @@
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+#include <linux/quotaops.h>
+
+
 /*
  * balloc.c contains the blocks allocation and deallocation routines
  */
@@ -26,16 +32,6 @@
  * when a file system is mounted (see ext2_read_super).
  */
 
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
 
 #define in_range(b, first, len)		((b) >= (first) && (b) <= (first) + (len) - 1)
 
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/bitmap.c linux/fs/ext2/bitmap.c
--- v2.3.24/linux/fs/ext2/bitmap.c	Wed Mar 22 00:33:59 1995
+++ linux/fs/ext2/bitmap.c	Thu Oct 28 13:23:10 1999
@@ -7,8 +7,10 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
+
+
 
 static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
 
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v2.3.24/linux/fs/ext2/dir.c	Sat Jun 26 12:04:39 1999
+++ linux/fs/ext2/dir.c	Thu Oct 28 13:23:10 1999
@@ -18,13 +18,10 @@
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+
+
 
 static ssize_t ext2_dir_read (struct file * filp, char * buf,
 			      size_t count, loff_t *ppos)
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.3.24/linux/fs/ext2/file.c	Sat Jun 26 12:04:39 1999
+++ linux/fs/ext2/file.c	Thu Oct 28 13:23:10 1999
@@ -18,19 +18,11 @@
  * 	(jj@sunsite.ms.mff.cuni.cz)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fcntl.h>
 #include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
+
+
 
 #define	NBUF	32
 
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/fsync.c linux/fs/ext2/fsync.c
--- v2.3.24/linux/fs/ext2/fsync.c	Tue Jun 29 09:22:08 1999
+++ linux/fs/ext2/fsync.c	Thu Oct 28 13:23:10 1999
@@ -22,17 +22,10 @@
  * we can depend on generic_block_fdatasync() to sync the data blocks.
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
+
+
 
 
 #define blocksize	(EXT2_BLOCK_SIZE(inode->i_sb))
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v2.3.24/linux/fs/ext2/ialloc.c	Tue May 11 14:37:47 1999
+++ linux/fs/ext2/ialloc.c	Thu Oct 28 13:23:10 1999
@@ -12,6 +12,12 @@
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+#include <linux/quotaops.h>
+
+
 /*
  * ialloc.c contains the inodes allocation and deallocation routines
  */
@@ -27,16 +33,6 @@
  * when a file system is mounted (see ext2_read_super).
  */
 
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
 
 /*
  * Read the inode allocation bitmap for a given block_group, reading
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.3.24/linux/fs/ext2/inode.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/ext2/inode.c	Thu Oct 28 13:23:10 1999
@@ -20,18 +20,13 @@
  * 	(jj@sunsite.ms.mff.cuni.cz)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/mm.h>
 #include <linux/smp_lock.h>
+#include <linux/sched.h>
+
+
 
 static int ext2_update_inode(struct inode * inode, int do_sync);
 
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c
--- v2.3.24/linux/fs/ext2/ioctl.c	Thu Jul  1 16:04:08 1999
+++ linux/fs/ext2/ioctl.c	Thu Oct 28 13:23:10 1999
@@ -7,14 +7,11 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/ioctl.h>
 #include <linux/sched.h>
-#include <linux/mm.h>
+#include <asm/uaccess.h>
+
 
 int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		unsigned long arg)
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.3.24/linux/fs/ext2/namei.c	Thu Jun 24 11:26:43 1999
+++ linux/fs/ext2/namei.c	Thu Oct 28 13:23:10 1999
@@ -18,17 +18,11 @@
  *  	for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
  */
 
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/quotaops.h>
+
 
 
 /*
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.3.24/linux/fs/ext2/super.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/ext2/super.c	Thu Oct 28 13:23:10 1999
@@ -17,23 +17,14 @@
  */
 
 #include <linux/module.h>
-
-#include <stdarg.h>
-
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/malloc.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/blkdev.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/locks.h>
+#include <asm/uaccess.h>
+
+
 
 static char error_buf[1024];
 
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c
--- v2.3.24/linux/fs/ext2/symlink.c	Sat Jun 26 12:04:39 1999
+++ linux/fs/ext2/symlink.c	Thu Oct 28 13:23:10 1999
@@ -15,14 +15,11 @@
  *  ext2 symlink handling code
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
 #include <asm/uaccess.h>
 
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/stat.h>
+
 
 static int ext2_readlink (struct dentry *, char *, int);
 static struct dentry *ext2_follow_link(struct dentry *, struct dentry *, unsigned int);
diff -u --recursive --new-file v2.3.24/linux/fs/ext2/truncate.c linux/fs/ext2/truncate.c
--- v2.3.24/linux/fs/ext2/truncate.c	Tue Jun 29 09:22:08 1999
+++ linux/fs/ext2/truncate.c	Thu Oct 28 13:23:10 1999
@@ -18,19 +18,15 @@
  *  General cleanup and race fixes, wsh, 1998
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+
+
 /*
  * Real random numbers for secure rm added 94/02/18
  * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr>
  */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/string.h>
 
 #if 0
 
diff -u --recursive --new-file v2.3.24/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.3.24/linux/fs/fat/file.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/fat/file.c	Fri Oct 29 17:04:40 1999
@@ -118,8 +118,8 @@
 	struct page *page_cache = NULL;
 	long status;
 
-	pgpos = MSDOS_I(inode)->i_realsize & PAGE_CACHE_MASK;
-	while (pgpos < page->offset) {
+	pgpos = MSDOS_I(inode)->i_realsize >> PAGE_CACHE_SHIFT;
+	while (pgpos < page->index) {
 		hash = page_hash(&inode->i_data, pgpos);
 repeat_find:	new_page = __find_lock_page(&inode->i_data, pgpos, hash);
 		if (!new_page) {
@@ -140,7 +140,7 @@
 		page_cache_release(new_page);
 		if (status < 0)
 			goto out;
-		pgpos = MSDOS_I(inode)->i_realsize & PAGE_CACHE_MASK;
+		pgpos = MSDOS_I(inode)->i_realsize >> PAGE_CACHE_SHIFT;
 	}
 	status = block_write_cont_page(file, page, offset, bytes, buf);
 out:
diff -u --recursive --new-file v2.3.24/linux/fs/file.c linux/fs/file.c
--- v2.3.24/linux/fs/file.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/file.c	Sat Oct 30 11:10:31 1999
@@ -64,7 +64,7 @@
 
 	
 	error = -EMFILE;
-	if (files->max_fds >= NR_OPEN || nr > NR_OPEN)
+	if (files->max_fds >= NR_OPEN || nr >= NR_OPEN)
 		goto out;
 
 	nfds = files->max_fds;
@@ -88,7 +88,7 @@
 			if (nfds > NR_OPEN)
 				nfds = NR_OPEN;
 		}
-	} while (nfds < nr);
+	} while (nfds <= nr);
 
 	error = -ENOMEM;
 	new_fds = alloc_fd_array(nfds);
diff -u --recursive --new-file v2.3.24/linux/fs/filesystems.c linux/fs/filesystems.c
--- v2.3.24/linux/fs/filesystems.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/filesystems.c	Thu Oct 28 14:45:16 1999
@@ -30,6 +30,7 @@
 #include <linux/ntfs_fs.h>
 #include <linux/hfs_fs.h>
 #include <linux/devpts_fs.h>
+#include <linux/bfs_fs.h>
 #include <linux/major.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -153,6 +154,10 @@
 
 #ifdef CONFIG_UDF_FS
 	init_udf_fs();
+#endif
+
+#ifdef CONFIG_BFS_FS
+	init_bfs_fs();
 #endif
    
 #ifdef CONFIG_NLS
diff -u --recursive --new-file v2.3.24/linux/fs/inode.c linux/fs/inode.c
--- v2.3.24/linux/fs/inode.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/inode.c	Thu Oct 28 17:30:51 1999
@@ -518,8 +518,7 @@
 		spin_lock(&inode_lock);
 		/* We released the lock, so.. */
 		old = find_inode(sb, ino, head, find_actor, opaque);
-		if (!old)
-		{
+		if (!old) {
 			list_add(&inode->i_list, &inode_in_use);
 			list_add(&inode->i_hash, head);
 			inode->i_sb = sb;
@@ -546,7 +545,13 @@
 
 			return inode;
 		}
-		__iget(inode);
+
+		/*
+		 * Uhhuh, somebody else created the same inode under
+		 * us. Use the old inode instead of the one we just
+		 * allocated.
+		 */
+		__iget(old);
 		spin_unlock(&inode_lock);
 		destroy_inode(inode);
 		inode = old;
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.3.24/linux/fs/ncpfs/dir.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/ncpfs/dir.c	Mon Nov  1 10:31:34 1999
@@ -26,8 +26,10 @@
 
 #include "ncplib_kernel.h"
 
-static int ncp_read_volume_list(struct file *, void *, filldir_t);
-static int ncp_do_readdir(struct file *, void *, filldir_t);
+static void ncp_read_volume_list(struct file *, void *, filldir_t,
+				struct ncp_cache_control *);
+static void ncp_do_readdir(struct file *, void *, filldir_t,
+				struct ncp_cache_control *);
 
 static ssize_t ncp_dir_read(struct file *, char *, size_t, loff_t *);
 static int ncp_readdir(struct file *, void *, filldir_t);
@@ -171,10 +173,8 @@
 		 * (Somebody might have used it again ...)
 		 */
 		if (dentry->d_count == 1 && NCP_FINFO(inode)->opened) {
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_delete_dentry: closing file %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
+			PPRINTK("ncp_delete_dentry: closing file %s/%s\n",
+			dentry->d_parent->d_name.name, dentry->d_name.name);
 			ncp_make_closed(inode);
 		}
 	} else
@@ -310,7 +310,7 @@
 
 	if (!dentry->d_inode || !dir)
 		goto finished;
-        
+
 	server = NCP_SERVER(dir);
 
 	if (!ncp_conn_valid(server))
@@ -325,19 +325,18 @@
 	val = NCP_TEST_AGE(server, dentry);
 	if (val)
 		goto finished;
-#ifdef NCPFS_PARANOIA
-	printk(KERN_DEBUG "ncp_lookup_validate: %s/%s not valid, age=%ld\n",
+
+	PPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		NCP_GET_AGE(dentry));
-#endif
 
 	memcpy(__name, dentry->d_name.name, len);
 	__name[len] = '\0';
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_lookup_validate: %s, len %d\n", __name, len);
-printk(KERN_DEBUG "ncp_lookup_validate: server lookup for %s/%s\n",
-dentry->d_parent->d_name.name, __name);
-#endif
+
+	PPRINTK("ncp_lookup_validate: %s, len %d\n", __name, len);
+	PPRINTK("ncp_lookup_validate: server lookup for %s/%s\n",
+			dentry->d_parent->d_name.name, __name);
+
 	if (ncp_is_server_root(dir)) {
 		io2vol(server, __name, 1);
 		res = ncp_lookup_volume(server, __name, &(finfo.i));
@@ -345,10 +344,8 @@
 		io2vol(server, __name, !ncp_preserve_case(dir));
 		res = ncp_obtain_info(server, dir, __name, &(finfo.i));
 	}
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_lookup_validate: looked for %s/%s, res=%d\n",
-dentry->d_parent->d_name.name, __name, res);
-#endif
+	PPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
+		dentry->d_parent->d_name.name, __name, res);
 	/*
 	 * If we didn't find it, or if it has a different dirEntNum to
 	 * what we remember, it's not valid any more.
@@ -356,359 +353,436 @@
 	if (!res) {
 		if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum)
 			val=1;
-#ifdef NCPFS_PARANOIA
 		else
-			printk(KERN_DEBUG "ncp_lookup_validate: found, but dirEntNum changed\n");
-#endif
+			PPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
+
 		vol2io(server, finfo.i.entryName,
 			!ncp_preserve_entry_case(dir, finfo.i.NSCreator));
 		ncp_update_inode2(dentry->d_inode, &finfo);
-		ncp_new_dentry(dentry);
+		if (val)
+			ncp_new_dentry(dentry);
 	}
 
 finished:
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_lookup_validate: result=%d\n", val);
-#endif
-
+	PPRINTK("ncp_lookup_validate: result=%d\n", val);
 	return val;
 }
 
+static struct page *
+ncp_get_cache_page(struct inode *inode, unsigned long offset, int used)
+{
+	struct address_space *i_data = &inode->i_data;
+	struct page *new_page, *page, **hash;
+
+	hash = page_hash(i_data, offset);
+
+	page = __find_lock_page(i_data, offset, hash);
+	if (used || page)
+		return page;
+
+	new_page = page_cache_alloc();
+	if (!new_page)
+		return NULL;
+
+	for (;;) {
+		page = new_page;
+		if (!add_to_page_cache_unique(page, i_data, offset, hash))
+			break;
+		page_cache_release(page);
+		page = __find_lock_page(i_data, offset, hash);
+		if (page) {
+			page_cache_free(new_page);
+			break;
+		}
+	}
+
+	return page;
+}
+
+/* most parts from nfsd_d_validate() */
+static int
+ncp_d_validate(struct dentry *dentry)
+{
+	unsigned long dent_addr = (unsigned long) dentry;
+	unsigned long min_addr = PAGE_OFFSET;
+	unsigned long max_addr = min_addr + (max_mapnr << PAGE_SHIFT);
+	unsigned long align_mask = 0x0F;
+	unsigned int len;
+	int valid = 0;
+
+	if (dent_addr < min_addr)
+		goto bad_addr;
+	if (dent_addr > max_addr - sizeof(struct dentry))
+		goto bad_addr;
+	if ((dent_addr & ~align_mask) != dent_addr)
+		goto bad_align;
+	if (!kern_addr_valid(dent_addr))
+		goto bad_addr;
+	/*
+	 * Looks safe enough to dereference ...
+	 */
+	len = dentry->d_name.len;
+	if (len > NCP_MAXPATHLEN)
+		goto out;
+	/*
+	 * Note: d_validate doesn't dereference the parent pointer ...
+	 * just combines it with the name hash to find the hash chain.
+	 */
+	valid = d_validate(dentry, dentry->d_parent, dentry->d_name.hash, len);
+out:
+	return valid;
+
+bad_addr:
+	PRINTK("ncp_d_validate: invalid address %lx\n", dent_addr);
+	goto out;
+bad_align:
+	PRINTK("ncp_d_validate: unaligned address %lx\n", dent_addr);
+	goto out;
+}
+
+static struct dentry *
+ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
+{
+	struct dentry *dent = dentry;
+	struct list_head *next;
+
+	if (ncp_d_validate(dent))
+		if ((dent->d_parent == parent) &&
+		    ((unsigned long)dent->d_fsdata == fpos))
+			goto out;
+
+	/* If a pointer is invalid, we search the dentry. */
+	next = parent->d_subdirs.next;
+	while (next != &parent->d_subdirs) {
+		dent = list_entry(next, struct dentry, d_child);
+		if ((unsigned long)dent->d_fsdata == fpos)
+			goto out;
+		next = next->next;
+	}
+	dent = NULL;
+out:
+	if (dent)
+		if (dent->d_inode)
+			return dget(dent);
+	return NULL;
+}
+
+static time_t ncp_obtain_mtime(struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+	struct ncp_server *server = NCP_SERVER(inode);
+	struct nw_info_struct i;
+
+	if (!ncp_conn_valid(server) ||
+	    ncp_is_server_root(inode))
+		return 0;
+
+	if (ncp_obtain_info(server, inode, NULL, &i))
+		return 0;
+
+	return ncp_date_dos2unix(le16_to_cpu(i.modifyTime),
+						le16_to_cpu(i.modifyDate));
+}
 
 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
+	struct page *page = NULL;
 	struct ncp_server *server = NCP_SERVER(inode);
-	int entries, result;
+	union  ncp_dir_cache *cache = NULL;
+	struct ncp_cache_control ctl;
+	int result, mtime_valid = 0;
+	time_t mtime = 0;
+
+	ctl.page  = NULL;
+	ctl.cache = NULL;
 
-	DDPRINTK(KERN_DEBUG "ncp_readdir: reading %s/%s, pos=%d\n",
+	DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(int) filp->f_pos);
 
 	result = -EIO;
 	if (!ncp_conn_valid(server))
-		goto finished;
+		goto out;
 
 	result = 0;
 	if (filp->f_pos == 0) {
 		if (filldir(dirent, ".", 1, 0, inode->i_ino))
-			goto finished;
+			goto out;
 		filp->f_pos = 1;
 	}
 	if (filp->f_pos == 1) {
 		if (filldir(dirent, "..", 2, 1,
 				dentry->d_parent->d_inode->i_ino))
-			goto finished;
+			goto out;
 		filp->f_pos = 2;
 	}
 
-	if (ncp_is_server_root(inode)) {
-		entries = ncp_read_volume_list(filp, dirent, filldir);
-		DPRINTK(KERN_DEBUG "ncp_read_volume_list returned %d\n", entries);
-	} else {
-		entries = ncp_do_readdir(filp, dirent, filldir);
-		DPRINTK(KERN_DEBUG "ncp_readdir: returned %d\n", entries);
+	page = ncp_get_cache_page(inode, 0, 0);
+	if (!page)
+		goto read_really;
+
+	ctl.cache = cache = (union ncp_dir_cache *) page_address(page);
+	ctl.head  = cache->head;
+
+	if (!Page_Uptodate(page) || !ctl.head.eof)
+		goto init_cache;
+
+	if (filp->f_pos == 2) {
+		if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
+			goto init_cache;
+
+		mtime = ncp_obtain_mtime(dentry);
+		mtime_valid = 1;
+		if ((!mtime) || (mtime != ctl.head.mtime))
+			goto init_cache;
 	}
 
-	if (entries < 0)
-		result = entries;
+	if (filp->f_pos > ctl.head.end)
+		goto finished;
+
+	ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
+	ctl.ofs  = ctl.fpos / NCP_DIRCACHE_SIZE;
+	ctl.idx  = ctl.fpos % NCP_DIRCACHE_SIZE;
 
+	for (;;) {
+		if (ctl.ofs != 0) {
+			ctl.page = ncp_get_cache_page(inode, ctl.ofs, 1);
+			if (!ctl.page)
+				goto invalid_cache;
+			if (!Page_Uptodate(ctl.page))
+				goto invalid_cache;
+			ctl.cache = (union ncp_dir_cache *)
+					page_address(ctl.page);
+		}
+		while (ctl.idx < NCP_DIRCACHE_SIZE) {
+			struct dentry *dent;
+			int res;
+
+			dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
+						dentry, filp->f_pos);
+			if (!dent)
+				goto invalid_cache;
+			res = filldir(dirent, dent->d_name.name,
+					dent->d_name.len, filp->f_pos,
+					dent->d_inode->i_ino);
+			dput(dent);
+			if (res)
+				goto finished;
+			filp->f_pos += 1;
+			ctl.idx += 1;
+			if (filp->f_pos > ctl.head.end)
+				goto finished;
+		}
+		if (ctl.page) {
+			SetPageUptodate(ctl.page);
+			UnlockPage(ctl.page);
+			page_cache_release(ctl.page);
+			ctl.page = NULL;
+		}
+		ctl.idx  = 0;
+		ctl.ofs += 1;
+	}
+invalid_cache:
+	if (ctl.page) {
+		UnlockPage(ctl.page);
+		page_cache_release(ctl.page);
+		ctl.page = NULL;
+	}
+	ctl.cache = cache;
+init_cache:
+	ncp_invalidate_dircache_entries(dentry);
+	if (!mtime_valid) {
+		mtime = ncp_obtain_mtime(dentry);
+		mtime_valid = 1;
+	}
+	ctl.head.mtime = mtime;
+	ctl.head.time = jiffies;
+	ctl.head.eof = 0;
+	ctl.fpos = 2;
+	ctl.ofs = 0;
+	ctl.idx = NCP_DIRCACHE_START;
+	ctl.filled = 0;
+	ctl.valid  = 1;
+read_really:
+	if (ncp_is_server_root(inode)) {
+		ncp_read_volume_list(filp, dirent, filldir, &ctl);
+	} else {
+		ncp_do_readdir(filp, dirent, filldir, &ctl);
+	}
+	ctl.head.end = ctl.fpos - 1;
+	ctl.head.eof = ctl.valid;
 finished:
+	if (page) {
+		cache->head = ctl.head;
+		SetPageUptodate(page);
+		UnlockPage(page);
+		page_cache_release(page);
+	}
+	if (ctl.page) {
+		SetPageUptodate(ctl.page);
+		UnlockPage(ctl.page);
+		page_cache_release(ctl.page);
+	}
+out:
 	return result;
 }
 
 static int
-ncp_do_simple_filldir(struct file *filp, char* name, int len,
-		void* dirent, filldir_t filldir)
+ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+		struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
 {
-	struct dentry *dentry = filp->f_dentry;
+	struct dentry *newdent, *dentry = filp->f_dentry;
+	struct inode *newino, *inode = dentry->d_inode;
+	struct ncp_server *server = NCP_SERVER(inode);
+	struct ncp_cache_control ctl = *ctrl;
 	struct qstr qname;
 	ino_t ino = 0;
-	int result;
-	
-	qname.name = name;
-	qname.len = len;
-	
-	ino = find_inode_number(dentry, &qname);
-
-	if (!ino)
-		ino = iunique(dentry->d_inode->i_sb, 2);
-
-	result = filldir(dirent, name, len, filp->f_pos, ino);
-	if (!result)
-		filp->f_pos += 1;
+	int valid = 0;
 
-	return result;
-}	
-	
-static int
-ncp_do_filldir(struct file *filp, struct ncp_entry_info *entry, void *dirent,
-			filldir_t filldir)
-{
-	struct dentry *dentry = filp->f_dentry;
-	struct inode *inode = dentry->d_inode;
-	struct qstr qname;
-	ino_t ino = 0;
-	int result;
+	vol2io(server, entry->i.entryName,
+		!ncp_preserve_entry_case(inode, entry->i.NSCreator));
 
-	/* For getwd() we have to return the correct inode in d_ino if the
-	 * inode is currently in use. Otherwise the inode number does not
-	 * matter. (You can argue a lot about this..)
-	 */
 	qname.name = entry->i.entryName;
 	qname.len  = entry->i.nameLen;
+	qname.hash = full_name_hash(qname.name, qname.len);
 
-	{
-		struct dentry *newdent;
-		struct inode *newino;
-
-		qname.hash = full_name_hash(qname.name, qname.len);
-		if (dentry->d_op && dentry->d_op->d_hash)
-			if (dentry->d_op->d_hash(dentry, &qname) != 0)
-				goto end_advance;
-
-		newdent = d_lookup(dentry, &qname);
-
-		if (!newdent) {
-			newdent = d_alloc(dentry, &qname);
-			if (!newdent)
-				goto end_advance;
-		}
+	if (dentry->d_op && dentry->d_op->d_hash)
+		if (dentry->d_op->d_hash(dentry, &qname) != 0)
+			goto end_advance;
+
+	newdent = d_lookup(dentry, &qname);
+
+	if (!newdent) {
+		newdent = d_alloc(dentry, &qname);
+		if (!newdent)
+			goto end_advance;
+	} else
+		memcpy((char *) newdent->d_name.name, qname.name,
+							newdent->d_name.len);
 
-		if (!newdent->d_inode) {
-			entry->opened = 0;
-			entry->ino = iunique(inode->i_sb, 2);
-			newino = ncp_iget(inode->i_sb, entry);
-			if (newino) {
-				newdent->d_op = &ncp_dentry_operations;
-				d_add(newdent, newino);
-				ncp_new_dentry(newdent);
-			}
-		} else {
-			ncp_update_inode2(newdent->d_inode, entry);
-			ncp_new_dentry(newdent);
+	if (!newdent->d_inode) {
+		entry->opened = 0;
+		entry->ino = iunique(inode->i_sb, 2);
+		newino = ncp_iget(inode->i_sb, entry);
+		if (newino) {
+			newdent->d_op = &ncp_dentry_operations;
+			d_add(newdent, newino);
 		}
+	} else
+		ncp_update_inode2(newdent->d_inode, entry);
 
-		if (newdent->d_inode)
-			ino = newdent->d_inode->i_ino;
-
-		dput(newdent);
-
-end_advance:
+	if (newdent->d_inode) {
+		ino = newdent->d_inode->i_ino;
+		newdent->d_fsdata = (void *) ctl.fpos;
+		ncp_new_dentry(newdent);
 	}
-	if (!ino)
-		ino = find_inode_number(dentry, &qname);
-
-	if (!ino)
-		ino = iunique(inode->i_sb, 2);
 
-	result = filldir(dirent, entry->i.entryName, entry->i.nameLen,
-				filp->f_pos, ino);
-	if (!result)
-		filp->f_pos += 1;
-
-	return result;
+	if (ctl.idx >= NCP_DIRCACHE_SIZE) {
+		if (ctl.page) {
+			SetPageUptodate(ctl.page);
+			UnlockPage(ctl.page);
+			page_cache_release(ctl.page);
+		}
+		ctl.cache = NULL;
+		ctl.idx  -= NCP_DIRCACHE_SIZE;
+		ctl.ofs  += 1;
+		ctl.page  = ncp_get_cache_page(inode, ctl.ofs, 0);
+		if (ctl.page)
+			ctl.cache = (union ncp_dir_cache *)
+					page_address(ctl.page);
+	}
+	if (ctl.cache) {
+		ctl.cache->dentry[ctl.idx] = newdent;
+		valid = 1;
+	}
+	dput(newdent);
+end_advance:
+	if (!valid)
+		ctl.valid = 0;
+	if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
+		if (!ino)
+			ino = find_inode_number(dentry, &qname);
+		if (!ino)
+			ino = iunique(inode->i_sb, 2);
+		ctl.filled = filldir(dirent, entry->i.entryName,
+					entry->i.nameLen, filp->f_pos, ino);
+		if (!ctl.filled)
+			filp->f_pos += 1;
+	}
+	ctl.fpos += 1;
+	ctl.idx  += 1;
+	*ctrl = ctl;
+	return (ctl.valid || !ctl.filled);
 }
 
-static int 
-ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir)
+static void
+ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
+			struct ncp_cache_control *ctl)
 {
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
 	struct ncp_server *server = NCP_SERVER(inode);
 	struct ncp_volume_info info;
 	struct ncp_entry_info entry;
-	unsigned long total_count = 2, fpos = filp->f_pos;
 	int i;
 
-	DPRINTK(KERN_DEBUG "ncp_read_volume_list: pos=%ld\n", fpos);
+	DPRINTK("ncp_read_volume_list: pos=%ld\n",
+			(unsigned long) filp->f_pos);
 
 	for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
 
 		if (ncp_get_volume_info_with_number(server, i, &info) != 0)
-			break;
+			return;
 		if (!strlen(info.volume_name))
 			continue;
 
-		if (total_count < fpos) {
-			DPRINTK(KERN_DEBUG "ncp_read_volume_list: skipped vol: %s\n",
-				info.volume_name);
-		} else {
-			DPRINTK(KERN_DEBUG "ncp_read_volume_list: found vol: %s\n",
-				info.volume_name);
+		DPRINTK("ncp_read_volume_list: found vol: %s\n",
+			info.volume_name);
 
-			if (ncp_lookup_volume(server, info.volume_name,
-						&entry.i)) {
-				DPRINTK(KERN_DEBUG "ncpfs: could not lookup vol %s\n",
-					info.volume_name);
-				continue;
-			}
-			vol2io(server, entry.i.entryName,
-				!ncp_preserve_entry_case(inode, entry.i.NSCreator));
-			if (ncp_do_filldir(filp, &entry, dirent, filldir))
-				break;
+		if (ncp_lookup_volume(server, info.volume_name,
+					&entry.i)) {
+			DPRINTK("ncpfs: could not lookup vol %s\n",
+				info.volume_name);
+			continue;
 		}
-		total_count += 1;
+		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
+			return;
 	}
-
-	return (total_count - fpos);
 }
 
-static int ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir)
+static void ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
+				struct ncp_cache_control *ctl)
 {
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *dir = dentry->d_inode;
 	struct ncp_server *server = NCP_SERVER(dir);
-	struct ncp_seq_cache *cache = NULL;
-	struct ncp_cache_control ctl;
+	struct nw_search_sequence seq;
 	struct ncp_entry_info entry;
-	struct page *page, **hash;
-	unsigned long total_count = 0, fpos = filp->f_pos;
 	int err;
 
-	DPRINTK(KERN_DEBUG "ncp_do_readdir: %s/%s, fpos=%ld\n",
-		dentry->d_parent->d_name.name, dentry->d_name.name, fpos);
-
-#ifdef NCPFS_DEBUG_VERBOSE
-printk("ncp_do_readdir: finding cache for %s/%s\n",
-	dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
-
-	/* cache using inspired by smbfs and nfs */
-	hash = page_hash(&dir->i_data, 0);
-
-	page = __find_lock_page(&dir->i_data, 0, hash);
-
-	if (!page) {
-		unsigned long page_cache;
-
-		page_cache = page_cache_alloc();
-		if (page_cache) {
-			page = page_cache_entry(page_cache);
-			if (add_to_page_cache_unique(page, &dir->i_data, 0, hash)) {
-				page_cache_release(page);
-				page = NULL;
-				page_cache_free(page_cache);
-			}
-		}
-	}
-
-	if (!page)
-		goto start_search;
-
-	cache = (struct ncp_seq_cache *) page_address(page);
-	ctl = cache->ctl;
-
-	if (!Page_Uptodate(page))
-		ctl.currentpos = NCP_FPOS_EMPTY;
-
-	if ((fpos == 2) || (fpos < ctl.firstcache))
-		ctl.currentpos = NCP_FPOS_EMPTY;
-
-	if (ctl.currentpos == NCP_FPOS_EMPTY)
-		goto start_search;
-
-	{
-		int fetchpos = ctl.cachehead;
-		int readpos = ctl.firstcache;
-		
-		while (readpos < fpos) {
-			fetchpos += cache->cache[fetchpos] + 1;
-			readpos++;
-		}
-		while (fpos < ctl.currentpos) {
-			err = ncp_do_simple_filldir(filp, 
-				(char*)(cache->cache+fetchpos+1), 
-				cache->cache[fetchpos], 
-				dirent, filldir);
-			if (err)
-				goto out;
-			fetchpos += cache->cache[fetchpos] + 1;
-			fpos++;
-			total_count++;
-		}
+	DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name,
+		(unsigned long) filp->f_pos);
+	PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
+		dentry->d_name.name, NCP_FINFO(dir)->volNumber,
+		NCP_FINFO(dir)->dirEntNum);
+
+	err = ncp_initialize_search(server, dir, &seq);
+	if (err) {
+		DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
+		return;
 	}
-	
-start_search:
-
-	DDPRINTK(KERN_DEBUG "ncp_do_readdir: %s: f_pos=%ld,total_count=%ld\n",
-			dentry->d_name.name, fpos, total_count);
-
-	if (ctl.currentpos == NCP_FPOS_EMPTY) {
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
-dentry->d_name.name, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
-#endif
-		err = ncp_initialize_search(server, dir, &ctl.seq); 
-		if (err) {
-			DPRINTK(KERN_DEBUG "ncp_do_readdir: init failed, err=%d\n", err);
-			goto out;
-		}
-		ctl.eof = 0;
-		ctl.cachehead = ctl.cachetail = 0;
-		ctl.firstcache = ctl.currentpos = 2;
-	} else
-		DDPRINTK(KERN_DEBUG "ncp_do_readdir: reused seq for %s, fpos=%li\n",
-				dentry->d_name.name, total_count);
-
 	for (;;) {
-		err = ncp_search_for_file_or_subdir(server, &ctl.seq,
-						    &entry.i);
+		err = ncp_search_for_file_or_subdir(server, &seq, &entry.i);
 		if (err) {
-			DPRINTK(KERN_DEBUG "ncp_do_readdir: search failed, err=%d\n", err);
-			ctl.eof = 1;
-			break;
-		}
-
-		ctl.currentpos++;
-		
-		vol2io(server, entry.i.entryName,
-			!ncp_preserve_entry_case(dir, entry.i.NSCreator));
-			
-		if (page) {
-			int tlen = ctl.cachetail + entry.i.nameLen + 1;
-			
-			if (tlen > NCP_DIRCACHE_SIZE) {
-				int ofs = ctl.cachehead;
-				
-				while (tlen - ofs > NCP_DIRCACHE_SIZE) {
-					ofs += cache->cache[ofs] + 1;
-					ctl.firstcache++;
-				}
-				ctl.cachetail -= ofs;
-				memmove(cache->cache+0,
-					cache->cache+ofs,
-					ctl.cachetail);
-			}
-			cache->cache[ctl.cachetail++] = entry.i.nameLen;
-			memcpy(cache->cache+ctl.cachetail, 
-			       entry.i.entryName, entry.i.nameLen);
-			ctl.cachetail += entry.i.nameLen;
+			DPRINTK("ncp_do_readdir: search failed, err=%d\n", err);
+			return;
 		}
-		if (ctl.currentpos < fpos) {
-			DPRINTK(KERN_DEBUG "ncp_do_readdir: skipped file: %s/%s\n",
-				dentry->d_name.name, entry.i.entryName);
-		} else {
-			DDPRINTK(KERN_DEBUG "ncp_do_r: file: %s, f_pos=%ld,total_count=%ld",
-				entry.i.entryName, fpos, total_count);
-			if (ncp_do_filldir(filp, &entry, dirent, filldir))
-				break;
-		}
-		total_count++;
-		fpos++;
+		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
+			return;
 	}
-out:
-	if (page) {
-		cache->ctl = ctl;
-		SetPageUptodate(page);
-		UnlockPage(page);
-		page_cache_release(page);
-	}
-
-	DDPRINTK(KERN_DEBUG "ncp_do_readdir: %s: return=%ld\n",
-			dentry->d_name.name, total_count);
-	return total_count;
 }
 
 int ncp_conn_logged_in(struct super_block *sb)
@@ -723,9 +797,8 @@
 		result = -ENOENT;
 		io2vol(server, server->m.mounted_vol, 1);
 		if (ncp_lookup_volume(server, server->m.mounted_vol, &i)) {
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_conn_logged_in: %s not found\n", server->m.mounted_vol);
-#endif
+			PPRINTK("ncp_conn_logged_in: %s not found\n",
+				server->m.mounted_vol);
 			goto out;
 		}
 		vol2io(server, i.entryName, 1);
@@ -737,10 +810,10 @@
 				NCP_FINFO(ino)->dirEntNum = i.dirEntNum;
 				NCP_FINFO(ino)->DosDirNum = i.DosDirNum;
 			} else {
-				DPRINTK(KERN_DEBUG "ncpfs: sb->s_root->d_inode == NULL!\n");
+				DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
 			}
 		} else {
-			DPRINTK(KERN_DEBUG "ncpfs: sb->s_root == NULL!\n");
+			DPRINTK("ncpfs: sb->s_root == NULL!\n");
 		}
 	}
 	result = 0;
@@ -765,11 +838,9 @@
 
 	memcpy(__name, dentry->d_name.name, len);
 	__name[len] = '\0';
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_lookup: %s, len %d\n", __name, len);
-printk(KERN_DEBUG "ncp_lookup: server lookup for %s/%s\n",
-dentry->d_parent->d_name.name, __name);
-#endif
+	PPRINTK("ncp_lookup: %s, len %d\n", __name, len);
+	PPRINTK("ncp_lookup: server lookup for %s/%s\n",
+		dentry->d_parent->d_name.name, __name);
 	if (ncp_is_server_root(dir)) {
 		io2vol(server, __name, 1);
 		res = ncp_lookup_volume(server, __name, &(finfo.i));
@@ -777,10 +848,8 @@
 		io2vol(server, __name, !ncp_preserve_case(dir));
 		res = ncp_obtain_info(server, dir, __name, &(finfo.i));
 	}
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_lookup: looked for %s/%s, res=%d\n",
-dentry->d_parent->d_name.name, __name, res);
-#endif
+	PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
+		dentry->d_parent->d_name.name, __name, res);
 	/*
 	 * If we didn't find an entry, make a negative dentry.
 	 */
@@ -807,9 +876,7 @@
 	}
 
 finished:
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_lookup: result=%d\n", error);
-#endif
+	PPRINTK("ncp_lookup: result=%d\n", error);
 	return ERR_PTR(error);
 }
 
@@ -832,10 +899,8 @@
 	return error;
 
 out_close:
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_instantiate: %s/%s failed, closing file\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
+	PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name);
 	ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
 	goto out;
 }
@@ -848,10 +913,8 @@
 	struct ncp_server *server = NCP_SERVER(dir);
 	__u8 _name[dentry->d_name.len + 1];
 	
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_create_new: creating %s/%s, mode=%x\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, mode);
-#endif
+	PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name, mode);
 	error = -EIO;
 	if (!ncp_conn_valid(server))
 		goto out;
@@ -872,7 +935,7 @@
 		error = ncp_instantiate(dir, dentry, &finfo);
 	} else {
 		if (result == 0x87) error = -ENAMETOOLONG;
-		DPRINTK(KERN_DEBUG "ncp_create: %s/%s failed\n",
+		DPRINTK("ncp_create: %s/%s failed\n",
 			dentry->d_parent->d_name.name, dentry->d_name.name);
 	}
 
@@ -892,7 +955,7 @@
 	struct ncp_server *server = NCP_SERVER(dir);
 	__u8 _name[dentry->d_name.len + 1];
 
-	DPRINTK(KERN_DEBUG "ncp_mkdir: making %s/%s\n",
+	DPRINTK("ncp_mkdir: making %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	error = -EIO;
 	if (!ncp_conn_valid(server))
@@ -921,7 +984,7 @@
 	struct ncp_server *server = NCP_SERVER(dir);
 	__u8 _name[dentry->d_name.len + 1];
 
-	DPRINTK(KERN_DEBUG "ncp_rmdir: removing %s/%s\n",
+	DPRINTK("ncp_rmdir: removing %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
 	error = -EIO;
@@ -972,7 +1035,7 @@
 	struct ncp_server *server = NCP_SERVER(dir);
 	int error;
 
-	DPRINTK(KERN_DEBUG "ncp_unlink: unlinking %s/%s\n",
+	DPRINTK("ncp_unlink: unlinking %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	
 	error = -EIO;
@@ -983,9 +1046,7 @@
 	 * Check whether to close the file ...
 	 */
 	if (inode && NCP_FINFO(inode)->opened) {
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_unlink: closing file\n");
-#endif
+		PPRINTK("ncp_unlink: closing file\n");
 		ncp_make_closed(inode);
 	}
 
@@ -999,7 +1060,7 @@
 #endif
 	switch (error) {
 		case 0x00:
-			DPRINTK(KERN_DEBUG "ncp: removed %s/%s\n",
+			DPRINTK("ncp: removed %s/%s\n",
 				dentry->d_parent->d_name.name, dentry->d_name.name);
 			d_delete(dentry);
 			break;
@@ -1037,7 +1098,7 @@
 	char _old_name[old_dentry->d_name.len + 1];
 	char _new_name[new_dentry->d_name.len + 1];
 
-	DPRINTK(KERN_DEBUG "ncp_rename: %s/%s to %s/%s\n",
+	DPRINTK("ncp_rename: %s/%s to %s/%s\n",
 		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
 		new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
 
@@ -1067,7 +1128,7 @@
 #endif
 	switch (error) {
 		case 0x00:
-               	        DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n",
+               	        DPRINTK("ncp renamed %s -> %s.\n",
                                 old_dentry->d_name.name,new_dentry->d_name.name);
 			/* d_move(old_dentry, new_dentry); */
 			break;
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c
--- v2.3.24/linux/fs/ncpfs/file.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/ncpfs/file.c	Fri Oct 29 10:53:32 1999
@@ -46,7 +46,7 @@
 		goto out;
 	}
 
-	DPRINTK(KERN_DEBUG "ncp_make_open: opened=%d, volume # %u, dir entry # %u\n",
+	DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n",
 		NCP_FINFO(inode)->opened, 
 		NCP_FINFO(inode)->volNumber, 
 		NCP_FINFO(inode)->dirEntNum);
@@ -67,9 +67,7 @@
 					NULL, NULL, OC_MODE_OPEN,
 					0, AR_READ, &finfo);
 		if (result) {
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_make_open: failed, result=%d\n", result);
-#endif
+			PPRINTK("ncp_make_open: failed, result=%d\n", result);
 			goto out_unlock;
 		}
 		/*
@@ -80,9 +78,7 @@
 	}
 
 	access = NCP_FINFO(inode)->access;
-#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_make_open: file open, access=%x\n", access);
-#endif
+	PPRINTK("ncp_make_open: file open, access=%x\n", access);
 	if (access == right || access == O_RDWR)
 		error = 0;
 
@@ -104,12 +100,12 @@
 	void* freepage;
 	size_t freelen;
 
-	DPRINTK(KERN_DEBUG "ncp_file_read: enter %s/%s\n",
+	DPRINTK("ncp_file_read: enter %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
 	error = -EINVAL;
 	if (inode == NULL) {
-		DPRINTK(KERN_DEBUG "ncp_file_read: inode = NULL\n");
+		DPRINTK("ncp_file_read: inode = NULL\n");
 		goto out;
 	}
 	error = -EIO;
@@ -117,7 +113,7 @@
 		goto out;
 	error = -EINVAL;
 	if (!S_ISREG(inode->i_mode)) {
-		DPRINTK(KERN_DEBUG "ncp_file_read: read from non-file, mode %07o\n",
+		DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
 			inode->i_mode);
 		goto out;
 	}
@@ -177,7 +173,7 @@
 		inode->i_atime = CURRENT_TIME;
 	}
 	
-	DPRINTK(KERN_DEBUG "ncp_file_read: exit %s/%s\n",
+	DPRINTK("ncp_file_read: exit %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 out:
 	return already_read ? already_read : error;
@@ -194,17 +190,17 @@
 	int errno;
 	void* bouncebuffer;
 
-	DPRINTK(KERN_DEBUG "ncp_file_write: enter %s/%s\n",
+	DPRINTK("ncp_file_write: enter %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	if (inode == NULL) {
-		DPRINTK(KERN_DEBUG "ncp_file_write: inode = NULL\n");
+		DPRINTK("ncp_file_write: inode = NULL\n");
 		return -EINVAL;
 	}
 	errno = -EIO;
 	if (!ncp_conn_valid(NCP_SERVER(inode)))
 		goto out;
 	if (!S_ISREG(inode->i_mode)) {
-		DPRINTK(KERN_DEBUG "ncp_file_write: write to non-file, mode %07o\n",
+		DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
 			inode->i_mode);
 		return -EINVAL;
 	}
@@ -260,7 +256,7 @@
 	if (pos > inode->i_size) {
 		inode->i_size = pos;
 	}
-	DPRINTK(KERN_DEBUG "ncp_file_write: exit %s/%s\n",
+	DPRINTK("ncp_file_write: exit %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 out:
 	return already_written ? already_written : errno;
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.3.24/linux/fs/ncpfs/inode.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/ncpfs/inode.c	Fri Oct 29 10:53:32 1999
@@ -72,10 +72,9 @@
 	NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
 	memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
 			sizeof(nwinfo->file_handle));
-#ifdef NCPFS_DEBUG_VERBOSE
-printk(KERN_DEBUG "ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
-nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum);
-#endif
+	DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
+		nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
+		NCP_FINFO(inode)->dirEntNum);
 }
 
 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
@@ -163,8 +162,8 @@
 			switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
 				case aHIDDEN:
 					if (server->m.flags & NCP_MOUNT_SYMLINKS) {
-						if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
-						 && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+						if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
+						 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
 							inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
 							break;
 						}
@@ -188,7 +187,7 @@
 	}
 	if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
 
-	DDPRINTK(KERN_DEBUG "ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
+	DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
 
 	inode->i_nlink = 1;
 	inode->i_uid = server->m.uid;
@@ -255,7 +254,7 @@
 ncp_delete_inode(struct inode *inode)
 {
 	if (S_ISDIR(inode->i_mode)) {
-		DDPRINTK(KERN_DEBUG "ncp_delete_inode: put directory %ld\n", inode->i_ino);
+		DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
 	}
 
 	if (NCP_FINFO(inode)->opened && ncp_make_closed(inode) != 0) {
@@ -323,10 +322,11 @@
 	server->m = *data;
 	/* Althought anything producing this is buggy, it happens
 	   now because of PATH_MAX changes.. */
-	if (server->m.time_out < 10) {
+	if (server->m.time_out < 1) {
 		server->m.time_out = 10;
 		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
 	}
+	server->m.time_out = server->m.time_out * HZ / 100;
 	server->m.file_mode = (server->m.file_mode &
 			       (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
 	server->m.dir_mode = (server->m.dir_mode &
@@ -350,7 +350,7 @@
 	ncp_unlock_server(server);
 	if (error < 0)
 		goto out_no_connect;
-	DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
+	DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
 
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
 	if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
@@ -375,7 +375,7 @@
 	if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
   				     &(server->buffer_size)) != 0)
 		goto out_no_bufsize;
-	DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size);
+	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
 
 	memset(&finfo, 0, sizeof(finfo));
 	finfo.i.attributes	= aDIR;
@@ -402,7 +402,7 @@
         root_inode = ncp_iget(sb, &finfo);
         if (!root_inode)
 		goto out_no_root;
-	DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
+	DPRINTK("ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
 	sb->s_root = d_alloc_root(root_inode);
         if (!sb->s_root)
 		goto out_no_root;
@@ -650,7 +650,7 @@
 	if ((attr->ia_valid & ATTR_SIZE) != 0) {
 		int written;
 
-		DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n",
+		DPRINTK("ncpfs: trying to change size to %ld\n",
 			attr->ia_size);
 
 		if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
@@ -689,7 +689,7 @@
 
 int init_module(void)
 {
-	DPRINTK(KERN_DEBUG "ncpfs: init_module called\n");
+	DPRINTK("ncpfs: init_module called\n");
 
 #ifdef DEBUG_NCP_MALLOC
 	ncp_malloced = 0;
@@ -700,11 +700,11 @@
 
 void cleanup_module(void)
 {
-	DPRINTK(KERN_DEBUG "ncpfs: cleanup_module called\n");
+	DPRINTK("ncpfs: cleanup_module called\n");
 	unregister_filesystem(&ncp_fs_type);
 #ifdef DEBUG_NCP_MALLOC
-	printk(KERN_DEBUG "ncp_malloced: %d\n", ncp_malloced);
-	printk(KERN_DEBUG "ncp_current_malloced: %d\n", ncp_current_malloced);
+	PRINTK("ncp_malloced: %d\n", ncp_malloced);
+	PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);
 #endif
 }
 
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c
--- v2.3.24/linux/fs/ncpfs/ioctl.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/ncpfs/ioctl.c	Fri Oct 29 10:53:32 1999
@@ -93,7 +93,7 @@
 		else
 			result = server->reply_size;
 		ncp_unlock_server(server);
-		DPRINTK(KERN_DEBUG "ncp_ioctl: copy %d bytes\n",
+		DPRINTK("ncp_ioctl: copy %d bytes\n",
 			result);
 		if (result >= 0)
 			if (copy_to_user(request.data, bouncebuffer, result))
@@ -124,7 +124,7 @@
 		copy_from_user(&info, (struct ncp_fs_info *) arg, sizeof(info));
 
 		if (info.version != NCP_GET_FS_INFO_VERSION) {
-			DPRINTK(KERN_DEBUG "info.version invalid: %d\n", info.version);
+			DPRINTK("info.version invalid: %d\n", info.version);
 			return -EINVAL;
 		}
 		/* TODO: info.addr = server->m.serv_addr; */
@@ -171,9 +171,9 @@
 						sr.dirEntNum = NCP_FINFO(inode)->dirEntNum;
 						sr.namespace = server->name_space[sr.volNumber];
 					} else
-						DPRINTK(KERN_DEBUG "ncpfs: s_root->d_inode==NULL\n");
+						DPRINTK("ncpfs: s_root->d_inode==NULL\n");
 				} else
-					DPRINTK(KERN_DEBUG "ncpfs: s_root==NULL\n");
+					DPRINTK("ncpfs: s_root==NULL\n");
 			} else {
 				sr.volNumber = -1;
 				sr.namespace = 0;
@@ -221,9 +221,9 @@
 					NCP_FINFO(inode)->dirEntNum = i.dirEntNum;
 					NCP_FINFO(inode)->DosDirNum = i.DosDirNum;
 				} else
-					DPRINTK(KERN_DEBUG "ncpfs: s_root->d_inode==NULL\n");
+					DPRINTK("ncpfs: s_root->d_inode==NULL\n");
 			} else
-				DPRINTK(KERN_DEBUG "ncpfs: s_root==NULL\n");
+				DPRINTK("ncpfs: s_root==NULL\n");
 
 			return 0;
 		}
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c
--- v2.3.24/linux/fs/ncpfs/mmap.c	Fri Jul  2 15:15:51 1999
+++ linux/fs/ncpfs/mmap.c	Fri Oct 29 10:53:32 1999
@@ -30,23 +30,25 @@
 /*
  * Fill in the supplied page for mmap
  */
-static unsigned long ncp_file_mmap_nopage(struct vm_area_struct *area,
-				     unsigned long address, int no_share)
+static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
+				     unsigned long address, int write_access)
 {
 	struct file *file = area->vm_file;
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
-	unsigned long page;
+	struct page* page;
+	unsigned long pg_addr;
 	unsigned int already_read;
 	unsigned int count;
 	int bufsize;
 	int pos;
 
-	page = __get_free_page(GFP_KERNEL);
+	page = __get_pages(GFP_KERNEL, 0);
 	if (!page)
 		return page;
+	pg_addr = page_address(page);
 	address &= PAGE_MASK;
-	pos = address - area->vm_start + area->vm_offset;
+	pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT);
 
 	count = PAGE_SIZE;
 	if (address + PAGE_SIZE > area->vm_end) {
@@ -68,7 +70,7 @@
 			if (ncp_read_kernel(NCP_SERVER(inode),
 				     NCP_FINFO(inode)->file_handle,
 				     pos, to_read,
-				     (char *) (page + already_read),
+				     (char *) (pg_addr + already_read),
 				     &read_this_time) != 0) {
 				read_this_time = 0;
 			}
@@ -83,7 +85,7 @@
 	}
 
 	if (already_read < PAGE_SIZE)
-		memset((char*)(page + already_read), 0, 
+		memset((char*)(pg_addr + already_read), 0, 
 		       PAGE_SIZE - already_read);
 	return page;
 }
@@ -107,7 +109,7 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	
-	DPRINTK(KERN_DEBUG "ncp_mmap: called\n");
+	DPRINTK("ncp_mmap: called\n");
 
 	if (!ncp_conn_valid(NCP_SERVER(inode))) {
 		return -EIO;
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c
--- v2.3.24/linux/fs/ncpfs/ncplib_kernel.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/ncpfs/ncplib_kernel.c	Mon Nov  1 10:31:34 1999
@@ -17,10 +17,10 @@
 	return a < b ? a : b;
 }
 
-static void assert_server_locked(struct ncp_server *server)
+static inline void assert_server_locked(struct ncp_server *server)
 {
 	if (server->lock == 0) {
-		DPRINTK(KERN_DEBUG "ncpfs: server not locked!\n");
+		DPRINTK("ncpfs: server not locked!\n");
 	}
 }
 
@@ -69,7 +69,7 @@
 	int len = strlen(s);
 	assert_server_locked(server);
 	if (len > 255) {
-		DPRINTK(KERN_DEBUG "ncpfs: string too long: %s\n", s);
+		DPRINTK("ncpfs: string too long: %s\n", s);
 		len = 255;
 	}
 	ncp_add_byte(server, len);
@@ -77,7 +77,7 @@
 	return;
 }
 
-static void ncp_init_request(struct ncp_server *server)
+static inline void ncp_init_request(struct ncp_server *server)
 {
 	ncp_lock_server(server);
 
@@ -95,7 +95,7 @@
 	server->has_subfunction = 1;
 }
 
-static char *
+static inline char *
  ncp_reply_data(struct ncp_server *server, int offset)
 {
 	return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
@@ -196,7 +196,7 @@
 	result = -EIO;
 	len = ncp_reply_byte(server, 29);
 	if (len > NCP_VOLNAME_LEN) {
-		DPRINTK(KERN_DEBUG "ncpfs: volume name too long: %d\n", len);
+		DPRINTK("ncpfs: volume name too long: %d\n", len);
 		goto out;
 	}
 	memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
@@ -229,11 +229,11 @@
 	int err;
 	NCP_FINFO(inode)->opened = 0;
 	err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle);
-#ifdef NCPFS_PARANOIA
-if (!err)
-printk(KERN_DEBUG "ncp_make_closed: volnum=%d, dirent=%u, error=%d\n",
-NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum, err);
-#endif
+
+	if (!err)
+		PPRINTK("ncp_make_closed: volnum=%d, dirent=%u, error=%d\n",
+			NCP_FINFO(inode)->volNumber,
+			NCP_FINFO(inode)->dirEntNum, err);
 	return err;
 }
 
@@ -350,7 +350,7 @@
 	namespace = ncp_reply_data(server, 2);
 
 	while (no_namespaces > 0) {
-		DPRINTK(KERN_DEBUG "get_namespaces: found %d on %d\n", *namespace, volume);
+		DPRINTK("get_namespaces: found %d on %d\n", *namespace, volume);
 
 #ifdef CONFIG_NCPFS_NFS_NS
 		if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) 
@@ -387,7 +387,7 @@
 	ncp_add_byte(server, 6); /* subfunction */
 	ncp_add_byte(server, nsSrc);
 	ncp_add_byte(server, nsDst);
-	ncp_add_word(server, 0x8006); /* get all */
+	ncp_add_word(server, htons(0x0680)); /* get all */
 	ncp_add_dword(server, RIM_ALL);
 	ncp_add_handle_path(server, vol_num, dir_base, 1, path);
 
@@ -436,7 +436,7 @@
 	int result;
 	int volnum;
 
-	DPRINTK(KERN_DEBUG "ncp_lookup_volume: looking up vol %s\n", volname);
+	DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
 
 	ncp_init_request(server);
 	ncp_add_byte(server, 22);	/* Subfunction: Generate dir handle */
@@ -462,7 +462,7 @@
 
 	server->name_space[volnum] = ncp_get_known_namespace(server, volnum);
 
-	DPRINTK(KERN_DEBUG "lookup_vol: namespace[%d] = %d\n",
+	DPRINTK("lookup_vol: namespace[%d] = %d\n",
 		volnum, server->name_space[volnum]);
 
 	target->nameLen = strlen(volname);
@@ -537,7 +537,7 @@
 
 	if (!inode) {
 #if CONFIG_NCPFS_DEBUGDENTRY
-		printk(KERN_DEBUG "ncpfs: ncpdel2: dentry->d_inode == NULL\n");
+		PRINTK("ncpfs: ncpdel2: dentry->d_inode == NULL\n");
 #endif
 		return 0xFF;	/* Any error */
 	}
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/ncplib_kernel.h linux/fs/ncpfs/ncplib_kernel.h
--- v2.3.24/linux/fs/ncpfs/ncplib_kernel.h	Sat Oct  9 11:47:50 1999
+++ linux/fs/ncpfs/ncplib_kernel.h	Sun Oct 31 00:19:18 1999
@@ -173,8 +173,8 @@
 #endif /* CONFIG_NCPFS_NLS */
 
 #define NCP_GET_AGE(dentry)	(jiffies - (dentry)->d_time)
-#define NCP_MAX_AGE		(server->dentry_ttl)
-#define NCP_TEST_AGE(server,dentry)	(NCP_GET_AGE(dentry) < NCP_MAX_AGE)
+#define NCP_MAX_AGE(server)	((server)->dentry_ttl)
+#define NCP_TEST_AGE(server,dentry)	(NCP_GET_AGE(dentry) < NCP_MAX_AGE(server))
 
 static inline void
 ncp_age_dentry(struct ncp_server* server, struct dentry* dentry)
@@ -188,21 +188,65 @@
 	dentry->d_time = jiffies;
 }
 
-#define NCP_FPOS_EMPTY	0	/* init value for fpos variables. */
+static inline void
+ncp_renew_dentries(struct dentry *parent)
+{
+	struct ncp_server *server = NCP_SERVER(parent->d_inode);
+	struct list_head *next = parent->d_subdirs.next;
+	struct dentry *dentry;
 
-struct ncp_cache_control {
-	struct nw_search_sequence seq;
-	int		firstcache;
-	int		currentpos;
-	int		cachehead;
-	int		cachetail;
+	while (next != &parent->d_subdirs) {
+		dentry = list_entry(next, struct dentry, d_child);
+
+		if (dentry->d_fsdata == NULL)
+			ncp_age_dentry(server, dentry);
+		else
+			ncp_new_dentry(dentry);
+
+		next = next->next;
+	}
+}
+
+static inline void
+ncp_invalidate_dircache_entries(struct dentry *parent)
+{
+	struct ncp_server *server = NCP_SERVER(parent->d_inode);
+	struct list_head *next = parent->d_subdirs.next;
+	struct dentry *dentry;
+
+	while (next != &parent->d_subdirs) {
+		dentry = list_entry(next, struct dentry, d_child);
+		dentry->d_fsdata = NULL;
+		ncp_age_dentry(server, dentry);
+		next = next->next;
+	}
+}
+
+struct ncp_cache_head {
+	time_t		mtime;
+	unsigned long	time;	/* cache age */
+	unsigned long	end;	/* last valid fpos in cache */
 	int		eof;
 };
 
-#define NCP_DIRCACHE_SIZE	(PAGE_CACHE_SIZE-sizeof(struct ncp_cache_control))
-struct ncp_seq_cache {
-	struct ncp_cache_control ctl;
-	unsigned char cache[NCP_DIRCACHE_SIZE];
+#define NCP_DIRCACHE_SIZE	((int)(PAGE_CACHE_SIZE/sizeof(struct dentry *)))
+union ncp_dir_cache {
+	struct ncp_cache_head	head;
+	struct dentry		*dentry[NCP_DIRCACHE_SIZE];
+};
+
+#define NCP_FIRSTCACHE_SIZE	((int)((NCP_DIRCACHE_SIZE * \
+	sizeof(struct dentry *) - sizeof(struct ncp_cache_head)) / \
+	sizeof(struct dentry *)))
+
+#define NCP_DIRCACHE_START	(NCP_DIRCACHE_SIZE - NCP_FIRSTCACHE_SIZE)
+
+struct ncp_cache_control {
+	struct	ncp_cache_head		head;
+	struct	page			*page;
+	union	ncp_dir_cache		*cache;
+	unsigned long			fpos, ofs;
+	int				filled, valid, idx;
 };
 
 #endif /* _NCPLIB_H */
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c
--- v2.3.24/linux/fs/ncpfs/sock.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/ncpfs/sock.c	Fri Oct 29 10:53:32 1999
@@ -144,7 +144,7 @@
 	set_fs(get_ds());
 	for (n = 0, timeout = init_timeout;; n++, timeout <<= 1) {
 		/*
-		DDPRINTK(KERN_DEBUG "ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
+		DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
 			 htonl(server->m.serv_addr.sipx_network),
 			 server->m.serv_addr.sipx_node[0],
 			 server->m.serv_addr.sipx_node[1],
@@ -154,12 +154,12 @@
 			 server->m.serv_addr.sipx_node[5],
 			 ntohs(server->m.serv_addr.sipx_port));
 		*/
-		DDPRINTK(KERN_DEBUG "ncpfs: req.typ: %04X, con: %d, "
+		DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
 			 "seq: %d",
 			 request.type,
 			 (request.conn_high << 8) + request.conn_low,
 			 request.sequence);
-		DDPRINTK(KERN_DEBUG " func: %d\n",
+		DDPRINTK(" func: %d\n",
 			 request.function);
 
 		result = _send(sock, (void *) start, size);
@@ -223,11 +223,11 @@
 			       MSG_PEEK | MSG_DONTWAIT);
 		if (result < 0) {
 			if (result == -EAGAIN) {
-				DDPRINTK(KERN_DEBUG "ncp_rpc_call: bad select ready\n");
+				DDPRINTK("ncp_rpc_call: bad select ready\n");
 				goto re_select;
 			}
 			if (result == -ECONNREFUSED) {
-				DPRINTK(KERN_WARNING "ncp_rpc_call: server playing coy\n");
+				DPRINTK("ncp_rpc_call: server playing coy\n");
 				goto re_select;
 			}
 			if (result != -ERESTARTSYS) {
@@ -239,7 +239,7 @@
 		if ((result == sizeof(reply))
 		    && (reply.type == NCP_POSITIVE_ACK)) {
 			/* Throw away the packet */
-			DPRINTK(KERN_DEBUG "ncp_rpc_call: got positive acknowledge\n");
+			DPRINTK("ncp_rpc_call: got positive acknowledge\n");
 			_recv(sock, (void *) &reply, sizeof(reply),
 			      MSG_DONTWAIT);
 			n = 0;
@@ -247,7 +247,7 @@
 			acknowledge_seen = 1;
 			goto re_select;
 		}
-		DDPRINTK(KERN_DEBUG "ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
+		DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
 			 "seq: %d\n",
 			 reply.type,
 			 (reply.conn_high << 8) + reply.conn_low,
@@ -271,7 +271,7 @@
 		 * a null buffer yet. */
 		_recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT);
 
-		DPRINTK(KERN_WARNING "ncp_rpc_call: reply mismatch\n");
+		DPRINTK("ncp_rpc_call: reply mismatch\n");
 		goto re_select;
 	}
 	/* 
@@ -321,7 +321,7 @@
 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
 	result = do_ncp_rpc_call(server, size, reply, max_reply_size);
 
-	DDPRINTK(KERN_DEBUG "do_ncp_rpc_call returned %d\n", result);
+	DDPRINTK("do_ncp_rpc_call returned %d\n", result);
 
 	if (result < 0) {
 		/* There was a problem with I/O, so the connections is
@@ -363,7 +363,7 @@
 
 	result = ncp_do_request(server, request_size + sizeof(*h), reply, size);
 	if (result < 0) {
-		DPRINTK(KERN_WARNING "ncp_request_error: %d\n", result);
+		DPRINTK("ncp_request_error: %d\n", result);
 		goto out;
 	}
 	server->completion = reply->completion_code;
@@ -373,10 +373,8 @@
 
 	result = reply->completion_code;
 
-#ifdef NCPFS_PARANOIA
-if (result != 0)
-printk(KERN_DEBUG "ncp_request: completion code=%x\n", result);
-#endif
+	if (result != 0)
+		PPRINTK("ncp_request: completion code=%x\n", result);
 out:
 	return result;
 }
@@ -428,7 +426,7 @@
 #if 0
 	/* For testing, only 1 process */
 	if (server->lock != 0) {
-		DPRINTK(KERN_WARNING "ncpfs: server locked!!!\n");
+		DPRINTK("ncpfs: server locked!!!\n");
 	}
 #endif
 	down(&server->sem);
diff -u --recursive --new-file v2.3.24/linux/fs/ncpfs/symlink.c linux/fs/ncpfs/symlink.c
--- v2.3.24/linux/fs/ncpfs/symlink.c	Sun Jun 27 10:10:41 1999
+++ linux/fs/ncpfs/symlink.c	Fri Oct 29 10:53:32 1999
@@ -80,7 +80,7 @@
 	char *link;
 
 #ifdef DEBUG
-	printk("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
+	PRINTK("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
 #endif
 
 	if(!S_ISLNK(inode->i_mode)) {
@@ -131,7 +131,7 @@
 	int length,error;
 
 #ifdef DEBUG
-	printk("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
+	PRINTK("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
 #endif
 
 	if(!S_ISLNK(inode->i_mode))
@@ -173,7 +173,7 @@
 	char *link;
 
 #ifdef DEBUG
-	printk("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
+	PRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
 #endif
 
 	if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS))
diff -u --recursive --new-file v2.3.24/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.3.24/linux/fs/nfs/dir.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/nfs/dir.c	Sat Oct 30 09:37:26 1999
@@ -1200,12 +1200,12 @@
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	struct dentry *dentry = NULL;
-	int error, rehash = 0, update = 1;
+	int error, rehash = 0;
 
 	dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
-		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
-		new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-		new_dentry->d_count);
+		 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
+		 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
+		 new_dentry->d_count);
 
 	/*
 	 * First check whether the target is busy ... we can't
@@ -1238,21 +1238,16 @@
 		/* dentry still busy? */
 		if (new_dentry->d_count > 1) {
 #ifdef NFS_PARANOIA
-printk("nfs_rename: target %s/%s busy, d_count=%d\n",
-new_dentry->d_parent->d_name.name,new_dentry->d_name.name,new_dentry->d_count);
+			printk("nfs_rename: target %s/%s busy, d_count=%d\n",
+			       new_dentry->d_parent->d_name.name,
+			       new_dentry->d_name.name,
+			       new_dentry->d_count);
 #endif
 			goto out;
 		}
 	}
 
 	/*
-	 * Check for within-directory rename ... no complications.
-	 */
-	if (new_dir == old_dir)
-		goto do_rename;
-	/*
-	 * Cross-directory move ...
-	 *
 	 * ... prune child dentries and writebacks if needed.
 	 */
 	if (old_dentry->d_count > 1) {
@@ -1260,40 +1255,26 @@
 		shrink_dcache_parent(old_dentry);
 	}
 
-	/*
-	 * Now check the use counts ... we can't safely do the
-	 * rename unless we can drop the dentries first.
-	 */
-	if (old_dentry->d_count > 1) {
-#ifdef NFS_PARANOIA
-printk("nfs_rename: old dentry %s/%s busy, d_count=%d\n",
-old_dentry->d_parent->d_name.name,old_dentry->d_name.name,old_dentry->d_count);
-#endif
-		goto out;
-	}
 	if (new_dentry->d_count > 1 && new_inode) {
 #ifdef NFS_PARANOIA
-printk("nfs_rename: new dentry %s/%s busy, d_count=%d\n",
-new_dentry->d_parent->d_name.name,new_dentry->d_name.name,new_dentry->d_count);
+		printk("nfs_rename: new dentry %s/%s busy, d_count=%d\n",
+		       new_dentry->d_parent->d_name.name,
+		       new_dentry->d_name.name,
+		       new_dentry->d_count);
 #endif
 		goto out;
 	}
 
-	d_drop(old_dentry);
-	update = 0;
-
-do_rename:
 	/*
 	 * To prevent any new references to the target during the rename,
 	 * we unhash the dentry and free the inode in advance.
 	 */
 	if (!list_empty(&new_dentry->d_hash)) {
 		d_drop(new_dentry);
-		rehash = update;
+		rehash = 1;
 	}
-	if (new_inode) {
+	if (new_inode)
 		d_delete(new_dentry);
-	}
 
 	invalidate_inode_pages(new_dir);
 	nfs_flush_dircache(new_dir);
@@ -1302,13 +1283,14 @@
 	error = nfs_proc_rename(NFS_DSERVER(old_dentry),
 			NFS_FH(old_dentry->d_parent), old_dentry->d_name.name,
 			NFS_FH(new_dentry->d_parent), new_dentry->d_name.name);
-	if (!error && !S_ISDIR(old_inode->i_mode)) {
-		/* Update the dcache if needed */
-		if (rehash)
-			d_add(new_dentry, NULL);
-		if (update)
-			d_move(old_dentry, new_dentry);
-	}
+
+	NFS_CACHEINV(old_dir);
+	NFS_CACHEINV(new_dir);
+	/* Update the dcache if needed */
+	if (rehash)
+		d_add(new_dentry, NULL);
+	if (!error && !S_ISDIR(old_inode->i_mode))
+		d_move(old_dentry, new_dentry);
 
 out:
 	/* new dentry created? */
diff -u --recursive --new-file v2.3.24/linux/fs/nfs/nfs3xdr.c linux/fs/nfs/nfs3xdr.c
--- v2.3.24/linux/fs/nfs/nfs3xdr.c	Sat Dec 20 21:06:01 1997
+++ linux/fs/nfs/nfs3xdr.c	Thu Oct 28 14:34:46 1999
@@ -679,7 +679,7 @@
 static struct proc_dir_entry	proc_nfsclnt = {
 	0, 3, "nfs",
 	S_IFREG | S_IRUGO, 1, 0, 0,
-	6, &proc_net_inode_operations,
+	6, NULL,
 	nfs_get_info
 };
 
diff -u --recursive --new-file v2.3.24/linux/fs/nfs/read.c linux/fs/nfs/read.c
--- v2.3.24/linux/fs/nfs/read.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/nfs/read.c	Fri Oct 29 16:45:32 1999
@@ -70,7 +70,7 @@
 nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
 {
 	struct nfs_rreq	rqst;
-	unsigned long	offset = page->offset;
+	unsigned long	offset = page->index << PAGE_CACHE_SHIFT;
 	char		*buffer = (char *) page_address(page);
 	int		rsize = NFS_SERVER(inode)->rsize;
 	int		result, refresh = 0;
@@ -179,7 +179,7 @@
 
 	/* Initialize request */
 	/* N.B. Will the dentry remain valid for life of request? */
-	nfs_readreq_setup(req, NFS_FH(dentry), page->offset,
+	nfs_readreq_setup(req, NFS_FH(dentry), page->index << PAGE_CACHE_SHIFT,
 				(void *) address, PAGE_SIZE);
 	req->ra_inode = inode;
 	req->ra_page = page; /* count has been incremented by caller */
@@ -224,8 +224,8 @@
 	int		error;
 
 	lock_kernel();
-	dprintk("NFS: nfs_readpage (%p %ld@%ld)\n",
-		page, PAGE_SIZE, page->offset);
+	dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
+		page, PAGE_SIZE, page->index);
 	get_page(page);
 
 	/*
diff -u --recursive --new-file v2.3.24/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.3.24/linux/fs/nfs/write.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/nfs/write.c	Fri Oct 29 16:45:32 1999
@@ -95,12 +95,12 @@
 	struct nfs_fattr fattr;
 
 	lock_kernel();
-	dprintk("NFS:      nfs_writepage_sync(%s/%s %d@%ld)\n",
+	dprintk("NFS:      nfs_writepage_sync(%s/%s %d@%lu/%ld)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
-		count, page->offset + offset);
+		count, page->index, offset);
 
 	buffer = (u8 *) page_address(page) + offset;
-	offset += page->offset;
+	offset += page->index << PAGE_CACHE_SHIFT;
 
 	do {
 		if (count < wsize && !IS_SWAPFILE(inode))
@@ -287,7 +287,7 @@
 
 	dprintk("NFS:      create_write_request(%s/%s, %ld+%d)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
-		page->offset + offset, bytes);
+		(page->index << PAGE_CACHE_SHIFT) + offset, bytes);
 
 	/* FIXME: Enforce hard limit on number of concurrent writes? */
 	wreq = kmem_cache_alloc(nfs_wreq_cachep, SLAB_KERNEL);
@@ -435,7 +435,7 @@
 
 	dprintk("NFS:      nfs_updatepage(%s/%s %d@%ld)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
-		count, page->offset+offset);
+		count, (page->index << PAGE_CACHE_SHIFT) +offset);
 
 	/*
 	 * Try to find a corresponding request on the writeback queue.
@@ -620,7 +620,7 @@
 	/* Setup the task struct for a writeback call */
 	req->wb_flags |= NFS_WRITE_INPROGRESS;
 	req->wb_args.fh     = NFS_FH(dentry);
-	req->wb_args.offset = page->offset + req->wb_offset;
+	req->wb_args.offset = (page->index << PAGE_CACHE_SHIFT) + req->wb_offset;
 	req->wb_args.count  = req->wb_bytes;
 	req->wb_args.buffer = (void *) (page_address(page) + req->wb_offset);
 
diff -u --recursive --new-file v2.3.24/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.3.24/linux/fs/nfsd/nfsctl.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/nfsd/nfsctl.c	Thu Oct 28 14:34:47 1999
@@ -57,13 +57,9 @@
 
 void proc_export_init(void)
 {
-	struct proc_dir_entry *nfs_export_ent = NULL;
-
-	if (!(nfs_export_ent = create_proc_entry("fs/nfs", S_IFDIR, 0)))
+	if (!create_proc_entry("fs/nfs", S_IFDIR, 0))
 		return;
-	if (!(nfs_export_ent = create_proc_entry("fs/nfs/exports", 0, 0)))
-		return;
-	nfs_export_ent->read_proc = exp_procfs_exports;
+	create_proc_read_entry("fs/nfs/exports", 0, 0, exp_procfs_exports,NULL);
 }
 
 
diff -u --recursive --new-file v2.3.24/linux/fs/open.c linux/fs/open.c
--- v2.3.24/linux/fs/open.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/open.c	Sun Oct 31 09:25:38 1999
@@ -707,7 +707,7 @@
 
 	/* Do we need to expand the fdset array? */
 	if (fd >= current->files->max_fdset) {
-		error = expand_fdset(files, 0);
+		error = expand_fdset(files, fd);
 		if (!error) {
 			error = -EMFILE;
 			goto repeat;
@@ -719,7 +719,7 @@
 	 * Check whether we need to expand the fd array.
 	 */
 	if (fd >= files->max_fds) {
-		error = expand_fd_array(files, 0);
+		error = expand_fd_array(files, fd);
 		if (!error) {
 			error = -EMFILE;
 			goto repeat;
diff -u --recursive --new-file v2.3.24/linux/fs/proc/Makefile linux/fs/proc/Makefile
--- v2.3.24/linux/fs/proc/Makefile	Mon Jun  7 12:20:50 1999
+++ linux/fs/proc/Makefile	Thu Oct 28 14:34:43 1999
@@ -9,7 +9,7 @@
 
 O_TARGET := proc.o
 O_OBJS   := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \
-		kmsg.o scsi.o proc_tty.o sysvipc.o
+		kmsg.o scsi.o proc_tty.o sysvipc.o proc_misc.o
 ifdef CONFIG_OMIRR
 O_OBJS   := $(O_OBJS) omirr.o
 endif
diff -u --recursive --new-file v2.3.24/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.3.24/linux/fs/proc/array.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/proc/array.c	Thu Oct 28 14:34:43 1999
@@ -72,13 +72,6 @@
 #include <asm/pgtable.h>
 #include <asm/io.h>
 
-#define LOAD_INT(x) ((x) >> FSHIFT)
-#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
-
-#ifdef CONFIG_DEBUG_MALLOC
-int get_malloc(char * buffer);
-#endif
-
 
 static int open_kcore(struct inode * inode, struct file * filp)
 {
@@ -229,193 +222,6 @@
 	&proc_profile_operations,
 };
 
-
-static int get_loadavg(char * buffer)
-{
-	int a, b, c;
-
-	a = avenrun[0] + (FIXED_1/200);
-	b = avenrun[1] + (FIXED_1/200);
-	c = avenrun[2] + (FIXED_1/200);
-	return sprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
-		LOAD_INT(a), LOAD_FRAC(a),
-		LOAD_INT(b), LOAD_FRAC(b),
-		LOAD_INT(c), LOAD_FRAC(c),
-		nr_running, nr_threads, last_pid);
-}
-
-static int get_kstat(char * buffer)
-{
-	int i, len;
-	unsigned sum = 0;
-	extern unsigned long total_forks;
-	unsigned long jif = jiffies;
-
-	for (i = 0 ; i < NR_IRQS ; i++)
-		sum += kstat_irqs(i);
-
-#ifdef __SMP__
-	len = sprintf(buffer,
-		"cpu  %u %u %u %lu\n",
-		kstat.cpu_user,
-		kstat.cpu_nice,
-		kstat.cpu_system,
-		jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
-	for (i = 0 ; i < smp_num_cpus; i++)
-		len += sprintf(buffer + len, "cpu%d %u %u %u %lu\n",
-			i,
-			kstat.per_cpu_user[cpu_logical_map(i)],
-			kstat.per_cpu_nice[cpu_logical_map(i)],
-			kstat.per_cpu_system[cpu_logical_map(i)],
-			jif - (  kstat.per_cpu_user[cpu_logical_map(i)] \
-			           + kstat.per_cpu_nice[cpu_logical_map(i)] \
-			           + kstat.per_cpu_system[cpu_logical_map(i)]));
-	len += sprintf(buffer + len,
-		"disk %u %u %u %u\n"
-		"disk_rio %u %u %u %u\n"
-		"disk_wio %u %u %u %u\n"
-		"disk_rblk %u %u %u %u\n"
-		"disk_wblk %u %u %u %u\n"
-		"page %u %u\n"
-		"swap %u %u\n"
-		"intr %u",
-#else
-	len = sprintf(buffer,
-		"cpu  %u %u %u %lu\n"
-		"disk %u %u %u %u\n"
-		"disk_rio %u %u %u %u\n"
-		"disk_wio %u %u %u %u\n"
-		"disk_rblk %u %u %u %u\n"
-		"disk_wblk %u %u %u %u\n"
-		"page %u %u\n"
-		"swap %u %u\n"
-		"intr %u",
-		kstat.cpu_user,
-		kstat.cpu_nice,
-		kstat.cpu_system,
-		jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
-#endif
-		kstat.dk_drive[0], kstat.dk_drive[1],
-		kstat.dk_drive[2], kstat.dk_drive[3],
-		kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
-		kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
-		kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
-		kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
-		kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
-		kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
-		kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
-		kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
-		kstat.pgpgin,
-		kstat.pgpgout,
-		kstat.pswpin,
-		kstat.pswpout,
-		sum);
-	for (i = 0 ; i < NR_IRQS ; i++)
-		len += sprintf(buffer + len, " %u", kstat_irqs(i));
-	len += sprintf(buffer + len,
-		"\nctxt %u\n"
-		"btime %lu\n"
-		"processes %lu\n",
-		kstat.context_swtch,
-		xtime.tv_sec - jif / HZ,
-		total_forks);
-	return len;
-}
-
-
-static int get_uptime(char * buffer)
-{
-	unsigned long uptime;
-	unsigned long idle;
-
-	uptime = jiffies;
-	idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;
-
-	/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
-	   that would overflow about every five days at HZ == 100.
-	   Therefore the identity a = (a / b) * b + a % b is used so that it is
-	   calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
-	   The part in front of the '+' always evaluates as 0 (mod 100). All divisions
-	   in the above formulas are truncating. For HZ being a power of 10, the
-	   calculations simplify to the version in the #else part (if the printf
-	   format is adapted to the same number of digits as zeroes in HZ.
-	 */
-#if HZ!=100
-	return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
-		uptime / HZ,
-		(((uptime % HZ) * 100) / HZ) % 100,
-		idle / HZ,
-		(((idle % HZ) * 100) / HZ) % 100);
-#else
-	return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
-		uptime / HZ,
-		uptime % HZ,
-		idle / HZ,
-		idle % HZ);
-#endif
-}
-
-static int get_meminfo(char * buffer)
-{
-	struct sysinfo i;
-	int len;
-
-/*
- * display in kilobytes.
- */
-#define K(x) ((x) << (PAGE_SHIFT - 10))
-
-	si_meminfo(&i);
-	si_swapinfo(&i);
-	len = sprintf(buffer, "        total:    used:    free:  shared: buffers:  cached:\n"
-		"Mem:  %8lu %8lu %8lu %8lu %8lu %8u\n"
-		"Swap: %8lu %8lu %8lu\n",
-		K(i.totalram), K(i.totalram-i.freeram), K(i.freeram),
-		K(i.sharedram), K(i.bufferram),
-		K(atomic_read(&page_cache_size)), K(i.totalswap),
-		K(i.totalswap-i.freeswap), K(i.freeswap));
-	/*
-	 * Tagged format, for easy grepping and expansion.
-	 * The above will go away eventually, once the tools
-	 * have been updated.
-	 */
-	return len + sprintf(buffer+len,
-		"MemTotal:  %8lu kB\n"
-		"MemFree:   %8lu kB\n"
-		"MemShared: %8lu kB\n"
-		"Buffers:   %8lu kB\n"
-		"Cached:    %8u kB\n"
-		"HighTotal: %8lu kB\n"
-		"HighFree:  %8lu kB\n"
-		"SwapTotal: %8lu kB\n"
-		"SwapFree:  %8lu kB\n",
-		K(i.totalram),
-		K(i.freeram),
-		K(i.sharedram),
-		K(i.bufferram),
-		K(atomic_read(&page_cache_size)),
-		K(i.totalhigh),
-		K(i.freehigh),
-		K(i.totalswap),
-		K(i.freeswap));
-#undef K
-}
-
-static int get_version(char * buffer)
-{
-	extern char *linux_banner;
-
-	strcpy(buffer, linux_banner);
-	return strlen(buffer);
-}
-
-static int get_cmdline(char * buffer)
-{
-	extern char saved_command_line[];
-
-	return sprintf(buffer, "%s\n", saved_command_line);
-}
-
 static struct page * get_phys_addr(struct mm_struct * mm, unsigned long ptr)
 {
 	pgd_t *pgd;
@@ -633,7 +439,7 @@
 		int count = 0;
 
 		stack_page = 4096 + (unsigned long)p;
-		fp = get_css_fp (&p->tss);
+		fp = get_css_fp(&p->thread);
 		do {
 			if (fp < stack_page || fp > 4092+stack_page)
 				return 0;
@@ -684,8 +490,13 @@
     (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk)))
 # define KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
 #elif defined(__arm__)
-# define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-# define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
+# ifdef CONFIG_CPU_26
+#  define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
+#  define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
+# else
+#  define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1021])
+#  define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
+# endif
 #elif defined(__mc68000__)
 #define	KSTK_EIP(tsk)	\
     ({			\
@@ -1250,7 +1061,7 @@
 
 		len = sprintf(line,
 			      sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8,
-			      map->vm_start, map->vm_end, str, map->vm_offset,
+			      map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT,
 			      kdevname(dev), ino);
 
 		if(map->vm_file) {
@@ -1329,131 +1140,6 @@
 }
 #endif
 
-#ifdef CONFIG_MODULES
-extern int get_module_list(char *);
-extern int get_ksyms_list(char *, char **, off_t, int);
-#endif
-extern int get_device_list(char *);
-extern int get_partition_list(char *);
-extern int get_filesystem_list(char *);
-extern int get_filesystem_info( char * );
-extern int get_irq_list(char *);
-extern int get_dma_list(char *);
-extern int get_cpuinfo(char *);
-extern int get_pci_list(char *);
-extern int get_md_status (char *);
-extern int get_rtc_status (char *);
-extern int get_locks_status (char *, char **, off_t, int);
-extern int get_swaparea_info (char *);
-extern int get_hardware_list(char *);
-extern int get_stram_list(char *);
-
-static long get_root_array(char * page, int type, char **start,
-	off_t offset, unsigned long length)
-{
-	switch (type) {
-		case PROC_LOADAVG:
-			return get_loadavg(page);
-
-		case PROC_UPTIME:
-			return get_uptime(page);
-
-		case PROC_MEMINFO:
-			return get_meminfo(page);
-
-#ifdef CONFIG_PCI
-	        case PROC_PCI:
-			return get_pci_list(page);
-#endif
-
-#ifdef CONFIG_NUBUS
-		case PROC_NUBUS:
-			return get_nubus_list(page);
-#endif			
-			
-		case PROC_CPUINFO:
-			return get_cpuinfo(page);
-
-		case PROC_VERSION:
-			return get_version(page);
-
-#ifdef CONFIG_DEBUG_MALLOC
-		case PROC_MALLOC:
-			return get_malloc(page);
-#endif
-
-#ifdef CONFIG_MODULES
-		case PROC_MODULES:
-			return get_module_list(page);
-
-		case PROC_KSYMS:
-			return get_ksyms_list(page, start, offset, length);
-#endif
-
-		case PROC_STAT:
-			return get_kstat(page);
-
-		case PROC_SLABINFO:
-			return get_slabinfo(page);
-
-		case PROC_DEVICES:
-			return get_device_list(page);
-
-		case PROC_PARTITIONS:
-			return get_partition_list(page);
-
-		case PROC_INTERRUPTS:
-			return get_irq_list(page);
-
-		case PROC_FILESYSTEMS:
-			return get_filesystem_list(page);
-
-		case PROC_DMA:
-			return get_dma_list(page);
-
-		case PROC_IOPORTS:
-			return get_ioport_list(page);
-
-		case PROC_MEMORY:
-			return get_mem_list(page);
-#ifdef CONFIG_BLK_DEV_MD
-	        case PROC_MD:
-			return get_md_status(page);
-#endif
-		case PROC_CMDLINE:
-			return get_cmdline(page);
-
-		case PROC_MTAB:
-			return get_filesystem_info( page );
-
-		case PROC_SWAP:
-			return get_swaparea_info(page);
-#ifdef CONFIG_RTC
-		case PROC_RTC:
-			return get_rtc_status(page);
-#endif
-#ifdef CONFIG_SGI_DS1286
-		case PROC_RTC:
-			return get_ds1286_status(page);
-#endif
-#ifdef CONFIG_SGI_DS1286
-		case PROC_RTC:
-			return get_ds1286_status(page);
-#endif
-		case PROC_LOCKS:
-			return get_locks_status(page, start, offset, length);
-#ifdef CONFIG_PROC_HARDWARE
-		case PROC_HARDWARE:
-			return get_hardware_list(page);
-#endif
-#ifdef CONFIG_STRAM_PROC
-		case PROC_STRAM:
-			return get_stram_list(page);
-#endif
-	}
-	return -EBADF;
-}
-
 static int process_unauthorized(int type, int pid)
 {
 	struct task_struct *p;
@@ -1495,7 +1181,7 @@
 }
 
 
-static int get_process_array(char * page, int pid, int type)
+static inline int get_process_array(char * page, int pid, int type)
 {
 	switch (type) {
 		case PROC_PID_STATUS:
@@ -1516,14 +1202,6 @@
 	return -EBADF;
 }
 
-
-static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
-{
-	if (pid)
-		return get_process_array(page, pid, type);
-	return get_root_array(page, type, start, offset, length);
-}
-
 #define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
 
 static ssize_t array_read(struct file * file, char * buf,
@@ -1546,39 +1224,32 @@
 	type &= 0x0000ffff;
 	start = NULL;
 	dp = (struct proc_dir_entry *) inode->u.generic_ip;
+
+	if (!pid) {	/* can't happen */
+		free_page(page);
+		return -EBADF;
+	}
 	
-	if (pid && process_unauthorized(type, pid)) {
+	if (process_unauthorized(type, pid)) {
 		free_page(page);
 		return -EIO;
 	}
 	
-	if (dp->get_info)
-		length = dp->get_info((char *)page, &start, *ppos,
-				      count, 0);
-	else
-		length = fill_array((char *) page, pid, type,
-				    &start, *ppos, count);
+	length = get_process_array((char *) page, pid, type);
 	if (length < 0) {
 		free_page(page);
 		return length;
 	}
-	if (start != NULL) {
-		/* We have had block-adjusting processing! */
-		copy_to_user(buf, start, length);
-		*ppos += length;
-		count = length;
-	} else {
-		/* Static 4kB (or whatever) block capacity */
-		if (*ppos >= length) {
-			free_page(page);
-			return 0;
-		}
-		if (count + *ppos > length)
-			count = length - *ppos;
-		end = count + *ppos;
-		copy_to_user(buf, (char *) page + *ppos, count);
-		*ppos = end;
+	/* Static 4kB (or whatever) block capacity */
+	if (*ppos >= length) {
+		free_page(page);
+		return 0;
 	}
+	if (count + *ppos > length)
+		count = length - *ppos;
+	end = count + *ppos;
+	copy_to_user(buf, (char *) page + *ppos, count);
+	*ppos = end;
 	free_page(page);
 	return count;
 }
diff -u --recursive --new-file v2.3.24/linux/fs/proc/generic.c linux/fs/proc/generic.c
--- v2.3.24/linux/fs/proc/generic.c	Sat Jun 26 12:04:40 1999
+++ linux/fs/proc/generic.c	Thu Oct 28 14:34:43 1999
@@ -70,33 +70,6 @@
 	NULL		/* revalidate 	*/
 };
 
-/*
- * compatibility to replace fs/proc/net.c
- */
-struct inode_operations proc_net_inode_operations = {
-	&proc_file_operations,	/* default net file-ops */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* flushpage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL,			/* smap */
-	NULL			/* revalidate */
-};
-
-
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
diff -u --recursive --new-file v2.3.24/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v2.3.24/linux/fs/proc/mem.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/proc/mem.c	Thu Oct 28 13:03:38 1999
@@ -222,7 +222,7 @@
 	pgd_t *src_dir, *dest_dir;
 	pmd_t *src_middle, *dest_middle;
 	pte_t *src_table, *dest_table;
-	unsigned long stmp, dtmp, mapnr;
+	unsigned long stmp, etmp, dtmp, mapnr;
 	struct vm_area_struct *src_vma = NULL;
 	struct inode *inode = file->f_dentry->d_inode;
 	
@@ -239,8 +239,9 @@
 	 worth it. */
 
 	src_vma = tsk->mm->mmap;
-	stmp = vma->vm_offset;
-	while (stmp < vma->vm_offset + (vma->vm_end - vma->vm_start)) {
+	stmp = vma->vm_pgoff << PAGE_SHIFT;
+	etmp = stmp + vma->vm_end - vma->vm_start;
+	while (stmp < etmp) {
 		while (src_vma && stmp > src_vma->vm_end)
 			src_vma = src_vma->vm_next;
 		if (!src_vma || (src_vma->vm_flags & VM_SHM))
@@ -274,7 +275,7 @@
 	}
 
 	src_vma = tsk->mm->mmap;
-	stmp    = vma->vm_offset;
+	stmp    = vma->vm_pgoff << PAGE_SHIFT;
 	dtmp    = vma->vm_start;
 
 	flush_cache_range(vma->vm_mm, vma->vm_start, vma->vm_end);
diff -u --recursive --new-file v2.3.24/linux/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c
--- v2.3.24/linux/fs/proc/proc_misc.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/proc/proc_misc.c	Mon Nov  1 11:37:00 1999
@@ -0,0 +1,621 @@
+/*
+ *  linux/fs/proc/proc_misc.c
+ *
+ *  linux/fs/proc/array.c
+ *  Copyright (C) 1992  by Linus Torvalds
+ *  based on ideas by Darren Senn
+ *
+ *  This used to be the part of array.c. See the rest of history and credits
+ *  there. I took this into a separate file and switched the thing to generic
+ *  proc_file_inode_operations, leaving in array.c only per-process stuff.
+ *  Inumbers allocation made dynamic (via create_proc_entry()).  AV, May 1999.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/tty.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/string.h>
+#include <linux/mman.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/signal.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+/*
+ * Warning: stuff below (imported functions) assumes that its output will fit
+ * into one page. For some of those functions it may be wrong. Moreover, we
+ * have a way to deal with that gracefully. Right now I used straightforward
+ * wrappers, but this needs further analysis wrt potential overflows.
+ */
+extern int get_cpuinfo(char *);
+extern int get_hardware_list(char *);
+extern int get_stram_list(char *);
+#ifdef CONFIG_DEBUG_MALLOC
+extern int get_malloc(char * buffer);
+#endif
+#ifdef CONFIG_MODULES
+extern int get_module_list(char *);
+extern int get_ksyms_list(char *, char **, off_t, int);
+#endif
+extern int get_device_list(char *);
+extern int get_partition_list(char *);
+extern int get_filesystem_list(char *);
+extern int get_filesystem_info(char *);
+extern int get_exec_domain_list(char *);
+extern int get_irq_list(char *);
+extern int get_dma_list(char *);
+extern int get_rtc_status (char *);
+extern int get_locks_status (char *, char **, off_t, int);
+extern int get_swaparea_info (char *);
+#ifdef CONFIG_SGI_DS1286
+extern int get_ds1286_status(char *);
+#endif
+
+static int loadavg_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int a, b, c;
+	int len;
+
+	a = avenrun[0] + (FIXED_1/200);
+	b = avenrun[1] + (FIXED_1/200);
+	c = avenrun[2] + (FIXED_1/200);
+	len = sprintf(page,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
+		LOAD_INT(a), LOAD_FRAC(a),
+		LOAD_INT(b), LOAD_FRAC(b),
+		LOAD_INT(c), LOAD_FRAC(c),
+		nr_running, nr_threads, last_pid);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int uptime_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	unsigned long uptime;
+	unsigned long idle;
+	int len;
+
+	uptime = jiffies;
+	idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;
+
+	/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
+	   that would overflow about every five days at HZ == 100.
+	   Therefore the identity a = (a / b) * b + a % b is used so that it is
+	   calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
+	   The part in front of the '+' always evaluates as 0 (mod 100). All divisions
+	   in the above formulas are truncating. For HZ being a power of 10, the
+	   calculations simplify to the version in the #else part (if the printf
+	   format is adapted to the same number of digits as zeroes in HZ.
+	 */
+#if HZ!=100
+	len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
+		uptime / HZ,
+		(((uptime % HZ) * 100) / HZ) % 100,
+		idle / HZ,
+		(((idle % HZ) * 100) / HZ) % 100);
+#else
+	len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
+		uptime / HZ,
+		uptime % HZ,
+		idle / HZ,
+		idle % HZ);
+#endif
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int meminfo_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	struct sysinfo i;
+	int len;
+
+/*
+ * display in kilobytes.
+ */
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+#define B(x) ((x) << PAGE_SHIFT)
+        si_meminfo(&i);
+        si_swapinfo(&i);
+        len = sprintf(page, "        total:    used:    free:  shared: buffers:  cached:\n"
+                "Mem:  %8lu %8lu %8lu %8lu %8lu %8u\n"
+                "Swap: %8lu %8lu %8lu\n",
+                B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
+                B(i.sharedram), B(i.bufferram),
+                B(atomic_read(&page_cache_size)), B(i.totalswap),
+                B(i.totalswap-i.freeswap), B(i.freeswap));
+        /*
+         * Tagged format, for easy grepping and expansion.
+         * The above will go away eventually, once the tools
+         * have been updated.
+         */
+        len += sprintf(page+len,
+                "MemTotal:  %8lu kB\n"
+                "MemFree:   %8lu kB\n"
+                "MemShared: %8lu kB\n"
+                "Buffers:   %8lu kB\n"
+                "Cached:    %8u kB\n"
+                "HighTotal: %8lu kB\n"
+                "HighFree:  %8lu kB\n"
+                "SwapTotal: %8lu kB\n"
+                "SwapFree:  %8lu kB\n",
+                K(i.totalram),
+                K(i.freeram),
+                K(i.sharedram),
+                K(i.bufferram),
+                K(atomic_read(&page_cache_size)),
+                K(i.totalhigh),
+                K(i.freehigh),
+                K(i.totalswap),
+                K(i.freeswap));
+
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+#undef B
+#undef K
+}
+
+static int version_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	extern char *linux_banner;
+	int len;
+
+	strcpy(page, linux_banner);
+	len = strlen(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int cpuinfo_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_cpuinfo(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+#ifdef CONFIG_PROC_HARDWARE
+static int hardware_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_hardware_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+#endif
+
+#ifdef CONFIG_STRAM_PROC
+static int stram_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_stram_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+#endif
+
+#ifdef CONFIG_DEBUG_MALLOC
+static int malloc_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_malloc(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+#endif
+
+#ifdef CONFIG_MODULES
+static int modules_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_module_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int ksyms_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_ksyms_list(page, start, off, count);
+	if (len < count) *eof = 1;
+	return len;
+}
+#endif
+
+static int kstat_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int i, len;
+	unsigned sum = 0;
+	extern unsigned long total_forks;
+	unsigned long jif = jiffies;
+
+	for (i = 0 ; i < NR_IRQS ; i++)
+		sum += kstat_irqs(i);
+
+#ifdef __SMP__
+	len = sprintf(page,
+		"cpu  %u %u %u %lu\n",
+		kstat.cpu_user,
+		kstat.cpu_nice,
+		kstat.cpu_system,
+		jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
+	for (i = 0 ; i < smp_num_cpus; i++)
+		len += sprintf(page + len, "cpu%d %u %u %u %lu\n",
+			i,
+			kstat.per_cpu_user[cpu_logical_map(i)],
+			kstat.per_cpu_nice[cpu_logical_map(i)],
+			kstat.per_cpu_system[cpu_logical_map(i)],
+			jif - (  kstat.per_cpu_user[cpu_logical_map(i)] \
+			           + kstat.per_cpu_nice[cpu_logical_map(i)] \
+			           + kstat.per_cpu_system[cpu_logical_map(i)]));
+	len += sprintf(page + len,
+		"disk %u %u %u %u\n"
+		"disk_rio %u %u %u %u\n"
+		"disk_wio %u %u %u %u\n"
+		"disk_rblk %u %u %u %u\n"
+		"disk_wblk %u %u %u %u\n"
+		"page %u %u\n"
+		"swap %u %u\n"
+		"intr %u",
+#else
+	len = sprintf(page,
+		"cpu  %u %u %u %lu\n"
+		"disk %u %u %u %u\n"
+		"disk_rio %u %u %u %u\n"
+		"disk_wio %u %u %u %u\n"
+		"disk_rblk %u %u %u %u\n"
+		"disk_wblk %u %u %u %u\n"
+		"page %u %u\n"
+		"swap %u %u\n"
+		"intr %u",
+		kstat.cpu_user,
+		kstat.cpu_nice,
+		kstat.cpu_system,
+		jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
+#endif
+		kstat.dk_drive[0], kstat.dk_drive[1],
+		kstat.dk_drive[2], kstat.dk_drive[3],
+		kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
+		kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
+		kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
+		kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
+		kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
+		kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
+		kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
+		kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
+		kstat.pgpgin,
+		kstat.pgpgout,
+		kstat.pswpin,
+		kstat.pswpout,
+		sum);
+	for (i = 0 ; i < NR_IRQS ; i++)
+		len += sprintf(page + len, " %u", kstat_irqs(i));
+	len += sprintf(page + len,
+		"\nctxt %u\n"
+		"btime %lu\n"
+		"processes %lu\n",
+		kstat.context_swtch,
+		xtime.tv_sec - jif / HZ,
+		total_forks);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int devices_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_device_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int partitions_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_partition_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int interrupts_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_irq_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int filesystems_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_filesystem_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int dma_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_dma_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int ioports_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_ioport_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int cmdline_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	extern char saved_command_line[];
+	int len;
+
+	len = sprintf(page, "%s\n", saved_command_line);
+	len = strlen(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+#ifdef CONFIG_RTC
+static int rtc_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_rtc_status(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+#endif
+
+#ifdef CONFIG_SGI_DS1286
+static int ds1286_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_ds1286_status(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+#endif
+
+static int locks_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_locks_status(page, start, off, count);
+	if (len < count) *eof = 1;
+	return len;
+}
+
+static int mounts_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_filesystem_info(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int execdomains_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_exec_domain_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int swaps_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_swaparea_info(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int slabinfo_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_slabinfo(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static int memory_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len = get_mem_list(page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+static struct proc_dir_entry proc_root_kmsg = {
+	0, 4, "kmsg",
+	S_IFREG | S_IRUSR, 1, 0, 0,
+	0, &proc_kmsg_inode_operations
+};
+static struct proc_dir_entry proc_root_kcore = {
+	0, 5, "kcore",
+	S_IFREG | S_IRUSR, 1, 0, 0,
+	0, &proc_kcore_inode_operations
+};
+static struct proc_dir_entry proc_root_profile = {
+	0, 7, "profile",
+	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+	0, &proc_profile_inode_operations
+};
+
+void proc_misc_init(void)
+{
+	static struct {
+		char *name;
+		int (*read_proc)(char*,char**,off_t,int,int*,void*);
+	} *p, simple_ones[] = {
+		{"loadavg",     loadavg_read_proc},
+		{"uptime",	uptime_read_proc},
+		{"meminfo",	meminfo_read_proc},
+		{"version",	version_read_proc},
+		{"cpuinfo",	cpuinfo_read_proc},
+#ifdef CONFIG_PROC_HARDWARE
+		{"hardware",	hardware_read_proc},
+#endif
+#ifdef CONFIG_STRAM_PROC
+		{"stram",	stram_read_proc},
+#endif
+#ifdef CONFIG_DEBUG_MALLOC
+		{"malloc",	malloc_read_proc},
+#endif
+#ifdef CONFIG_MODULES
+		{"modules",	modules_read_proc},
+		{"ksyms",	ksyms_read_proc},
+#endif
+		{"stat",	kstat_read_proc},
+		{"devices",	devices_read_proc},
+		{"partitions",	partitions_read_proc},
+		{"interrupts",	interrupts_read_proc},
+		{"filesystems",	filesystems_read_proc},
+		{"dma",		dma_read_proc},
+		{"ioports",	ioports_read_proc},
+		{"cmdline",	cmdline_read_proc},
+#ifdef CONFIG_RTC
+		{"rtc",		rtc_read_proc},
+#endif
+#ifdef CONFIG_SGI_DS1286
+		{"rtc",		ds1286_read_proc},
+#endif
+		{"locks",	locks_read_proc},
+		{"mounts",	mounts_read_proc},
+		{"swaps",	swaps_read_proc},
+		{"slabinfo",	slabinfo_read_proc},
+		{"iomem",	memory_read_proc},
+		{"execdomains",	execdomains_read_proc},
+		{NULL,NULL}
+	};
+	for(p=simple_ones;p->name;p++)
+		create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
+
+	/* And now for trickier ones */
+	proc_register(&proc_root, &proc_root_kmsg);
+	proc_register(&proc_root, &proc_root_kcore);
+	proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
+	if (prof_shift) {
+		proc_register(&proc_root, &proc_root_profile);
+		proc_root_profile.size = (1+prof_len) * sizeof(unsigned int);
+	}
+}
diff -u --recursive --new-file v2.3.24/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.3.24/linux/fs/proc/procfs_syms.c	Sat Jan  2 17:55:06 1999
+++ linux/fs/proc/procfs_syms.c	Thu Oct 28 14:34:43 1999
@@ -11,7 +11,7 @@
 extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
 				       off_t offset, int length, int inout);
 extern struct inode_operations proc_scsi_inode_operations;
-extern struct proc_dir_entry proc_sys_root;
+extern struct proc_dir_entry *proc_sys_root;
 
 #ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(proc_sys_root);
@@ -24,7 +24,6 @@
 EXPORT_SYMBOL(proc_root_fs);
 EXPORT_SYMBOL(proc_get_inode);
 EXPORT_SYMBOL(proc_dir_inode_operations);
-EXPORT_SYMBOL(proc_net_inode_operations);
 EXPORT_SYMBOL(proc_net);
 EXPORT_SYMBOL(proc_bus);
 
diff -u --recursive --new-file v2.3.24/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.3.24/linux/fs/proc/root.c	Fri Oct 15 15:25:14 1999
+++ linux/fs/proc/root.c	Thu Oct 28 14:34:43 1999
@@ -164,27 +164,15 @@
 	&proc_root, NULL
 };
 
-struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus, *proc_sysvipc;
+struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus, *proc_sysvipc,
+		      *proc_root_fs, *proc_root_driver;
 
 #ifdef CONFIG_MCA
-struct proc_dir_entry proc_mca = {
-	PROC_MCA, 3, "mca",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-	0, &proc_dir_inode_operations,
-	NULL, NULL,
-	NULL, &proc_root, NULL
-};
+struct proc_dir_entry *proc_mca;
 #endif
 
 #ifdef CONFIG_SYSCTL
-struct proc_dir_entry proc_sys_root = {
-	PROC_SYS, 3, "sys",			/* inode, name */
-	S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,	/* mode, nlink, uid, gid */
-	0, &proc_dir_inode_operations,		/* size, ops */
-	NULL, NULL,				/* get_info, fill_inode */
-	NULL,					/* next */
-	NULL, NULL				/* parent, subdir */
-};
+struct proc_dir_entry *proc_sys_root;
 #endif
 
 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
@@ -535,175 +523,14 @@
 	NULL			/* revalidate */
 };
 
-static struct proc_dir_entry proc_root_loadavg = {
-	PROC_LOADAVG, 7, "loadavg",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_uptime = {
-	PROC_UPTIME, 6, "uptime",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_meminfo = {
-	PROC_MEMINFO, 7, "meminfo",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_kmsg = {
-	PROC_KMSG, 4, "kmsg",
-	S_IFREG | S_IRUSR, 1, 0, 0,
-	0, &proc_kmsg_inode_operations
-};
-static struct proc_dir_entry proc_root_version = {
-	PROC_VERSION, 7, "version",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_cpuinfo = {
-	PROC_CPUINFO, 7, "cpuinfo",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-#if defined (CONFIG_PROC_HARDWARE)
-static struct proc_dir_entry proc_root_hardware = {
-	PROC_HARDWARE, 8, "hardware",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-#endif
-#ifdef CONFIG_STRAM_PROC
-static struct proc_dir_entry proc_root_stram = {
-	PROC_STRAM, 5, "stram",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-#endif
 static struct proc_dir_entry proc_root_self = {
-	PROC_SELF, 4, "self",
+	0, 4, "self",
 	S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
 	64, &proc_self_inode_operations,
 };
-#ifdef CONFIG_DEBUG_MALLOC
-static struct proc_dir_entry proc_root_malloc = {
-	PROC_MALLOC, 6, "malloc",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-#endif
-static struct proc_dir_entry proc_root_kcore = {
-	PROC_KCORE, 5, "kcore",
-	S_IFREG | S_IRUSR, 1, 0, 0,
-	0, &proc_kcore_inode_operations
-};
-#ifdef CONFIG_MODULES
-static struct proc_dir_entry proc_root_modules = {
-	PROC_MODULES, 7, "modules",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_ksyms = {
-	PROC_KSYMS, 5, "ksyms",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-#endif
-static struct proc_dir_entry proc_root_stat = {
-	PROC_STAT, 4, "stat",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_devices = {
-	PROC_DEVICES, 7, "devices",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_partitions = {
-	PROC_PARTITIONS, 10, "partitions",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_interrupts = {
-	PROC_INTERRUPTS, 10,"interrupts",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_filesystems = {
-	PROC_FILESYSTEMS, 11,"filesystems",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-struct proc_dir_entry proc_root_fs = {
-        PROC_FS, 2, "fs",
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-        0, &proc_dir_inode_operations,
-	NULL, NULL,
-	NULL,
-	NULL, NULL
-};
-struct proc_dir_entry proc_root_driver = {
-        PROC_DRIVER, 6, "driver",
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-        0, &proc_dir_inode_operations,
-	NULL, NULL,
-	NULL,
-	NULL, NULL
-};
-static struct proc_dir_entry proc_root_dma = {
-	PROC_DMA, 3, "dma",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_ioports = {
-	PROC_IOPORTS, 7, "ioports",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_iomem = {
-	PROC_MEMORY, 5, "iomem",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_cmdline = {
-	PROC_CMDLINE, 7, "cmdline",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-#ifdef CONFIG_RTC
-static struct proc_dir_entry proc_root_rtc = {
-	PROC_RTC, 3, "rtc",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-#endif
-static struct proc_dir_entry proc_root_locks = {
-	PROC_LOCKS, 5, "locks",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_mounts = {
-	PROC_MTAB, 6, "mounts",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_swaps = {
-	PROC_SWAP, 5, "swaps",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_profile = {
-	PROC_PROFILE, 7, "profile",
-	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
-	0, &proc_profile_inode_operations
-};
-static struct proc_dir_entry proc_root_slab = {
-	PROC_SLABINFO, 8, "slabinfo",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
 #ifdef __powerpc__
 static struct proc_dir_entry proc_root_ppc_htab = {
-	PROC_PPC_HTAB, 8, "ppc_htab",
+	0, 8, "ppc_htab",
 	S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0,
 	0, &proc_ppc_htab_inode_operations,
 	NULL, NULL,                		/* get_info, fill_inode */
@@ -715,12 +542,7 @@
 void __init proc_root_init(void)
 {
 	proc_base_init();
-	proc_register(&proc_root, &proc_root_loadavg);
-	proc_register(&proc_root, &proc_root_uptime);
-	proc_register(&proc_root, &proc_root_meminfo);
-	proc_register(&proc_root, &proc_root_kmsg);
-	proc_register(&proc_root, &proc_root_version);
-	proc_register(&proc_root, &proc_root_cpuinfo);
+	proc_misc_init();
 	proc_register(&proc_root, &proc_root_self);
 	proc_net = create_proc_entry("net", S_IFDIR, 0);
 	proc_scsi = create_proc_entry("scsi", S_IFDIR, 0);
@@ -728,60 +550,19 @@
 	proc_sysvipc = create_proc_entry("sysvipc", S_IFDIR, 0);
 #endif
 #ifdef CONFIG_SYSCTL
-	proc_register(&proc_root, &proc_sys_root);
+	proc_sys_root = create_proc_entry("sys", S_IFDIR, 0);
 #endif
 #ifdef CONFIG_MCA
-	proc_register(&proc_root, &proc_mca);
-#endif
-
-#ifdef CONFIG_DEBUG_MALLOC
-	proc_register(&proc_root, &proc_root_malloc);
+	proc_mca = create_proc_entry("mca", S_IFDIR, 0);
 #endif
-	proc_register(&proc_root, &proc_root_kcore);
-	proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
-
-#ifdef CONFIG_MODULES
-	proc_register(&proc_root, &proc_root_modules);
-	proc_register(&proc_root, &proc_root_ksyms);
-#endif
-	proc_register(&proc_root, &proc_root_stat);
-	proc_register(&proc_root, &proc_root_devices);
-	proc_register(&proc_root, &proc_root_driver);
-	proc_register(&proc_root, &proc_root_partitions);
-	proc_register(&proc_root, &proc_root_interrupts);
-	proc_register(&proc_root, &proc_root_filesystems);
-	proc_register(&proc_root, &proc_root_fs);
-	proc_register(&proc_root, &proc_root_dma);
-	proc_register(&proc_root, &proc_root_ioports);
-	proc_register(&proc_root, &proc_root_iomem);
-	proc_register(&proc_root, &proc_root_cmdline);
-#ifdef CONFIG_RTC
-	proc_register(&proc_root, &proc_root_rtc);
-#endif
-	proc_register(&proc_root, &proc_root_locks);
-
-	proc_register(&proc_root, &proc_root_mounts);
-	proc_register(&proc_root, &proc_root_swaps);
-
+	proc_root_fs = create_proc_entry("fs", S_IFDIR, 0);
+	proc_root_driver = create_proc_entry("driver", S_IFDIR, 0);
 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
 #ifdef CONFIG_SUN_OPENPROMFS
 	openpromfs_init ();
 #endif
 	proc_register(&proc_root, &proc_openprom);
 #endif
-#ifdef CONFIG_PROC_HARDWARE
-	proc_register(&proc_root, &proc_root_hardware);
-#endif
-#ifdef CONFIG_STRAM_PROC
-	proc_register(&proc_root, &proc_root_stram);
-#endif
-	proc_register(&proc_root, &proc_root_slab);
-
-	if (prof_shift) {
-		proc_register(&proc_root, &proc_root_profile);
-		proc_root_profile.size = (1+prof_len) * sizeof(unsigned int);
-	}
-
 	proc_tty_init();
 #ifdef __powerpc__
 	proc_register(&proc_root, &proc_root_ppc_htab);
@@ -789,7 +570,6 @@
 #ifdef CONFIG_PROC_DEVICETREE
 	proc_device_tree_init();
 #endif
-
 	proc_bus = create_proc_entry("bus", S_IFDIR, 0);
 }
 
diff -u --recursive --new-file v2.3.24/linux/fs/smbfs/cache.c linux/fs/smbfs/cache.c
--- v2.3.24/linux/fs/smbfs/cache.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/smbfs/cache.c	Thu Oct 28 10:53:51 1999
@@ -48,30 +48,39 @@
 {
 	struct page * page;
 	struct page ** hash;
-	unsigned long new_page;
+	struct page *cached_page = NULL;
 
  again:
 	hash = page_hash(mapping, offset);
 	page = __find_lock_page(mapping, offset, hash);
 	if(!page && new) {
-		/* not in cache, alloc a new page */
-		new_page = page_cache_alloc();
-		if (!new_page)
-			return 0;
-		clear_page(new_page);	/* smb code assumes pages are zeroed */
-		page = page_cache_entry(new_page);
-		if (add_to_page_cache_unique(page, mapping, offset, hash)) {
+		/* not in cache, alloc a new page if we didn't do it yet */
+		if (!cached_page) {
+			cached_page = page_cache_alloc();
+			if (!cached_page)
+				return 0;
+			/* smb code assumes pages are zeroed */
+			clear_page(page_address(cached_page));
+			goto again;
+		}
+		page = cached_page;
+		if (page->buffers)
+			BUG();
+		printk(KERN_DEBUG "smbfs: get_cached_page\n");
+		if (add_to_page_cache_unique(page, mapping, offset, hash))
 			/* Hmm, a page has materialized in the
                            cache. Fine. Go back and get that page
-                           instead ... throwing away this one first. */
-			put_cached_page((unsigned long) page);
+                          instead... */
 			goto again;
-		}
+		cached_page = NULL;
 	}
+	printk(KERN_DEBUG "smbfs: get_cached_page done\n");
+	if (cached_page)
+		page_cache_free(cached_page);
 	if(!page)
 		return 0;
 	if(!PageLocked(page))
-		printk(KERN_ERR "smbfs/cache.c: page isn't locked! This could be fun ...\n");
+		BUG();
 	return page_address(page);
 }
 
diff -u --recursive --new-file v2.3.24/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v2.3.24/linux/fs/smbfs/file.c	Mon Oct 11 15:38:15 1999
+++ linux/fs/smbfs/file.c	Fri Oct 29 16:45:32 1999
@@ -49,7 +49,7 @@
 smb_readpage_sync(struct dentry *dentry, struct page *page)
 {
 	char *buffer = (char *) page_address(page);
-	unsigned long offset = page->offset;
+	unsigned long offset = page->index << PAGE_CACHE_SHIFT;
 	int rsize = smb_get_rsize(server_from_dentry(dentry));
 	int count = PAGE_SIZE;
 	int result;
@@ -128,7 +128,7 @@
 	int wsize = smb_get_wsize(server_from_dentry(dentry));
 	int result, written = 0;
 
-	offset += page->offset;
+	offset += page->index << PAGE_CACHE_SHIFT;
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize);
@@ -191,7 +191,7 @@
 
 	pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
-	 	count, page->offset+offset);
+	 	count, (page->index << PAGE_CACHE_SHIFT)+offset);
 
 	return smb_writepage_sync(dentry, page, offset, count);
 }
diff -u --recursive --new-file v2.3.24/linux/fs/super.c linux/fs/super.c
--- v2.3.24/linux/fs/super.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/super.c	Sun Oct 31 00:19:22 1999
@@ -1025,14 +1025,14 @@
 	struct dentry * dentry = NULL;
 	struct inode * inode = NULL;
 	kdev_t dev;
-	int retval = -EPERM;
+	int retval;
 	unsigned long flags = 0;
 	unsigned long page = 0;
 	struct file dummy;	/* allows read-write or read-only flag */
 
-	lock_kernel();
 	if (!capable(CAP_SYS_ADMIN))
-		goto out;
+		return -EPERM;
+	lock_kernel();
 	if ((new_flags &
 	     (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) {
 		retval = copy_mount_options (data, &page);
diff -u --recursive --new-file v2.3.24/linux/fs/udf/balloc.c linux/fs/udf/balloc.c
--- v2.3.24/linux/fs/udf/balloc.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/udf/balloc.c	Sat Oct 30 09:42:30 1999
@@ -402,7 +402,7 @@
 
 got_block:
 	newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) -
-		(group_start << 3);
+		(sizeof(struct SpaceBitmapDesc) << 3);
 
 	tmp = udf_get_pblock(sb, newblock, partition, 0);
 	if (!udf_clear_bit(bit, bh->b_data))
@@ -412,16 +412,6 @@
 	}
 
 	mark_buffer_dirty(bh, 1);
-	if (!(bh = getblk(sb->s_dev, tmp, sb->s_blocksize)))
-	{
-		udf_debug("cannot get block %d\n", tmp);
-		unlock_super(sb);
-		return 0;
-	}
-	memset(bh->b_data, 0, sb->s_blocksize);
-	mark_buffer_uptodate(bh, 1);
-	mark_buffer_dirty(bh, 1);
-	udf_release_data(bh);
 
 	if (UDF_SB_LVIDBH(sb))
 	{
diff -u --recursive --new-file v2.3.24/linux/fs/udf/dir.c linux/fs/udf/dir.c
--- v2.3.24/linux/fs/udf/dir.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/udf/dir.c	Sat Oct 30 09:42:30 1999
@@ -180,7 +180,7 @@
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
 	{
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
-		if (++offset < (elen >> dir->i_sb->s_blocksize_bits))
+		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
 			if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
 				extoffset -= sizeof(short_ad);
@@ -207,8 +207,6 @@
 		filp->f_pos = nf_pos;
 
 		fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &offset, &bh);
-		liu = le16_to_cpu(cfi.lengthOfImpUse);
-		lfi = cfi.lengthFileIdent;
 
 		if (!fi)
 		{
@@ -218,6 +216,9 @@
 			udf_release_data(bh);
 			return 1;
 		}
+
+		liu = le16_to_cpu(cfi.lengthOfImpUse);
+		lfi = cfi.lengthFileIdent;
 
 		if (fibh.sbh == fibh.ebh)
 			nameptr = fi->fileIdent + liu;
diff -u --recursive --new-file v2.3.24/linux/fs/udf/directory.c linux/fs/udf/directory.c
--- v2.3.24/linux/fs/udf/directory.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/udf/directory.c	Sat Oct 30 09:42:30 1999
@@ -112,7 +112,7 @@
 
 		(*offset) ++;
 
-		if (*offset >= (elen >> dir->i_sb->s_blocksize_bits))
+		if ((*offset << dir->i_sb->s_blocksize_bits) >= elen)
 			*offset = 0;
 		else
 			*extoffset = lextoffset;
@@ -154,7 +154,7 @@
 
 		(*offset) ++;
 
-		if (*offset >= (elen >> dir->i_sb->s_blocksize_bits))
+		if ((*offset << dir->i_sb->s_blocksize_bits) >= elen)
 			*offset = 0;
 		else
 			*extoffset = lextoffset;
diff -u --recursive --new-file v2.3.24/linux/fs/udf/file.c linux/fs/udf/file.c
--- v2.3.24/linux/fs/udf/file.c	Fri Sep 10 23:57:36 1999
+++ linux/fs/udf/file.c	Sat Oct 30 09:42:30 1999
@@ -213,6 +213,8 @@
 
 		if ((bh = udf_expand_adinicb(inode, &i, 0, &err)))
 			udf_release_data(bh);
+		else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+			return err;
 	}
 
 	retval = generic_file_write(file, buf, count, ppos, block_write_partial_page);
@@ -294,7 +296,9 @@
 	if (!copy_to_user(buf, bh->b_data + pos, left))
 		*loff += left;
 	else
-		return -EFAULT;
+		left = -EFAULT;
+
+	udf_release_data(bh);
 
 	return left;
 }
@@ -336,11 +340,11 @@
 int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 	unsigned long arg)
 {
-	int result=-1;
-	int size;
+	int result = -1;
 	struct buffer_head *bh = NULL;
-	struct FileEntry *fe;
 	Uint16 ident;
+	long_ad eaicb;
+	Uint8 *ea = NULL;
 
 	if ( permission(inode, MAY_READ) != 0 )
 	{
@@ -368,26 +372,42 @@
 	/* ok, we need to read the inode */
 	bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
 
-	if (!bh || ident != TID_FILE_ENTRY)
+	if (!bh || (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY))
 	{
-		udf_debug("bread failed (ino=%ld) or ident (%d) != TID_FILE_ENTRY",
+		udf_debug("bread failed (ino=%ld) or ident (%d) != TID_(EXTENDED_)FILE_ENTRY",
 			inode->i_ino, ident);
 		return -EFAULT;
 	}
 
-	fe = (struct FileEntry *)bh->b_data;
-	size = le32_to_cpu(fe->lengthExtendedAttr);
+	if (UDF_I_EXTENDED_FE(inode) == 0)
+	{
+		struct FileEntry *fe;
+
+		fe = (struct FileEntry *)bh->b_data;
+		eaicb = fe->extendedAttrICB;
+		if (UDF_I_LENEATTR(inode))
+			ea = fe->extendedAttr;
+	}
+	else
+	{
+		struct ExtendedFileEntry *efe;
+
+		efe = (struct ExtendedFileEntry *)bh->b_data;
+		eaicb = efe->extendedAttrICB;
+		if (UDF_I_LENEATTR(inode))
+			ea = efe->extendedAttr;
+	}
 
 	switch (cmd) 
 	{
 		case UDF_GETEASIZE:
 			if ( (result = verify_area(VERIFY_WRITE, (char *)arg, 4)) == 0) 
-				result= put_user(size, (int *)arg);
+				result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
 			break;
 
 		case UDF_GETEABLOCK:
-			if ( (result = verify_area(VERIFY_WRITE, (char *)arg, size)) == 0) 
-				result= copy_to_user((char *)arg, fe->extendedAttr, size);
+			if ( (result = verify_area(VERIFY_WRITE, (char *)arg, UDF_I_LENEATTR(inode))) == 0) 
+				result = copy_to_user((char *)arg, ea, UDF_I_LENEATTR(inode));
 			break;
 
 		default:
diff -u --recursive --new-file v2.3.24/linux/fs/udf/inode.c linux/fs/udf/inode.c
--- v2.3.24/linux/fs/udf/inode.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/udf/inode.c	Sat Oct 30 09:42:30 1999
@@ -106,18 +106,48 @@
 void udf_discard_prealloc(struct inode * inode)
 {
 #ifdef UDF_PREALLOCATE
-#if 0
-	unsigned short total;
-	lb_addr loc = UDF_I_LOCATION(inode);
+	lb_addr bloc, eloc;
+	Uint32 extoffset, elen, nelen, offset, adsize = 0;
+	struct buffer_head *bh = NULL;
 
-	if (UDF_I_PREALLOC_COUNT(inode))
-	{
-		total = UDF_I_PREALLOC_COUNT(inode);
-		UDF_I_PREALLOC_COUNT(inode) = 0;
-		loc.logicalBlockNum = UDF_I_PREALLOC_BLOCK(inode);
-		udf_free_blocks(inode, loc, 0, total);
+	if ((inode->i_size > 0) &&
+		(inode_bmap(inode, (inode->i_size-1) >> inode->i_sb->s_blocksize_bits,
+			&bloc, &extoffset, &eloc, &elen, &offset, &bh) ==
+				EXTENT_RECORDED_ALLOCATED))
+	{
+		if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
+			adsize = sizeof(short_ad);
+		else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
+			adsize = sizeof(long_ad);
+		else
+		{
+			udf_release_data(bh);
+			return;
+		}
+
+		nelen = (EXTENT_RECORDED_ALLOCATED << 30) |
+			((((elen - 1) & ~(inode->i_sb->s_blocksize - 1)) |
+			((inode->i_size - 1) & (inode->i_sb->s_blocksize - 1))) + 1);
+
+		if (nelen != ((EXTENT_RECORDED_ALLOCATED << 30) | elen))
+		{
+			extoffset -= adsize;
+			udf_write_aext(inode, bloc, &extoffset, eloc, nelen, &bh, 1);
+		}
+
+		if (udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0) ==
+			EXTENT_NOT_RECORDED_ALLOCATED)
+		{
+			udf_free_blocks(inode, eloc, 0, elen >> inode->i_sb->s_blocksize_bits);
+			memset(&eloc, 0x00, sizeof(lb_addr));
+			udf_write_aext(inode, bloc, &extoffset, eloc, 0, &bh, 1);
+			UDF_I_LENALLOC(inode) -= adsize;
+			udf_write_inode(inode);
+		}
+		udf_release_data(bh);
 	}
-#endif
+	else if (bh)
+		udf_release_data(bh);
 #endif
 }
 
@@ -144,6 +174,9 @@
 		{
 			UDF_I_EXT0OFFS(inode) = 0;
 			UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+			mark_inode_dirty(inode);
+			if (inode->i_op == &udf_file_inode_operations_adinicb)
+				inode->i_op = &udf_file_inode_operations;
 			return NULL;
 		}
 
@@ -208,6 +241,7 @@
 		memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
 			0, UDF_I_LENALLOC(inode));
 
+		memset(&newad, 0x00, sizeof(long_ad));
 		newad.extLength = UDF_I_EXT0LEN(inode) = inode->i_size;
 		newad.extLocation.logicalBlockNum = *block;
 		newad.extLocation.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
@@ -248,7 +282,7 @@
 		bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
 		if (buffer_new(&dummy))
 		{
-			memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+			memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
 			mark_buffer_uptodate(bh, 1);
 			mark_buffer_dirty(bh, 1);
 		}
@@ -340,6 +374,7 @@
 		if (pbh != cbh)
 		{
 			udf_release_data(pbh);
+			pbh = cbh;
 			atomic_inc(&cbh->b_count);
 			pbloc = cbloc;
 		}
@@ -462,7 +497,6 @@
 			UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
 		{
 			udf_release_data(pbh);
-			udf_release_data(cbh);
 			*err = -ENOSPC;
 			return NULL;
 		}
@@ -488,7 +522,7 @@
 
 	udf_release_data(pbh);
 
-	if (c == 0 || c == 1)
+	if (pextoffset == udf_file_entry_alloc_offset(inode))
 	{
 		UDF_I_EXT0LEN(inode) = laarr[0].extLength;
 		UDF_I_EXT0LOC(inode) = laarr[0].extLocation;
@@ -889,7 +923,8 @@
 {
 	struct FileEntry *fe;
 	struct ExtendedFileEntry *efe;
-    time_t convtime;
+	time_t convtime;
+	long convtime_usec;
 	int offset, alen;
 
 	fe = (struct FileEntry *)bh->b_data;
@@ -940,21 +975,33 @@
 		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
 			(inode->i_sb->s_blocksize_bits - 9);
 
-		if ( udf_stamp_to_time(&convtime, lets_to_cpu(fe->modificationTime)) )
+		if ( udf_stamp_to_time(&convtime, &convtime_usec,
+			lets_to_cpu(fe->modificationTime)) )
 		{
 			inode->i_mtime = convtime;
+			UDF_I_UMTIME(inode) = convtime_usec;
 			inode->i_ctime = convtime;
+			UDF_I_UCTIME(inode) = convtime_usec;
 		}
 		else
 		{
 			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
+			UDF_I_UMTIME(inode) = 0;
 			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
+			UDF_I_UCTIME(inode) = 0;
 		}
 
-		if ( udf_stamp_to_time(&convtime, lets_to_cpu(fe->accessTime)) ) 
+		if ( udf_stamp_to_time(&convtime, &convtime_usec,
+			lets_to_cpu(fe->accessTime)) ) 
+		{
 			inode->i_atime = convtime;
+			UDF_I_UATIME(inode) = convtime_usec;
+		}
 		else
+		{
 			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
+			UDF_I_UATIME(inode) = convtime_usec;
+		}
 
 		UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID);
 		UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);
@@ -967,20 +1014,41 @@
 		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << 
 			(inode->i_sb->s_blocksize_bits - 9);
 
-		if ( udf_stamp_to_time(&convtime, lets_to_cpu(efe->modificationTime)) )
+		if ( udf_stamp_to_time(&convtime, &convtime_usec,
+			lets_to_cpu(efe->modificationTime)) )
+		{
 			inode->i_mtime = convtime;
+			UDF_I_UMTIME(inode) = convtime_usec;
+		}
 		else
+		{
 			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
+			UDF_I_UMTIME(inode) = 0;
+		}
 
-		if ( udf_stamp_to_time(&convtime, lets_to_cpu(efe->accessTime)) )
+		if ( udf_stamp_to_time(&convtime, &convtime_usec,
+			lets_to_cpu(efe->accessTime)) )
+		{
 			inode->i_atime = convtime;
+			UDF_I_UATIME(inode) = convtime_usec;
+		}
 		else
+		{
 			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
+			UDF_I_UATIME(inode) = 0;
+		}
 
-		if ( udf_stamp_to_time(&convtime, lets_to_cpu(efe->createTime)) )
+		if ( udf_stamp_to_time(&convtime, &convtime_usec,
+			lets_to_cpu(efe->createTime)) )
+		{
 			inode->i_ctime = convtime;
+			UDF_I_UCTIME(inode) = convtime_usec;
+		}
 		else
+		{
 			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
+			UDF_I_UCTIME(inode) = 0;
+		}
 
 		UDF_I_UNIQUE(inode) = le64_to_cpu(efe->uniqueID);
 		UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);
@@ -1274,8 +1342,8 @@
 		efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
 		efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
 		efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
-        efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
-        efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
+		efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
+		efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
 		efe->descTag.tagIdent = le16_to_cpu(TID_EXTENDED_FILE_ENTRY);
 		crclen = sizeof(struct ExtendedFileEntry);
 	}
@@ -1764,6 +1832,8 @@
 			return -1;
 		}
 	}
+	else
+		atomic_inc(&bh->b_count);
 
 	while ((type = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
 	{
@@ -1773,6 +1843,7 @@
 		nelen = (type << 30) | oelen;
 	}
 	udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);
+	udf_release_data(bh);
 	return (nelen >> 30);
 }
 
@@ -1879,12 +1950,12 @@
 	if (block < 0)
 	{
 		printk(KERN_ERR "udf: inode_bmap: block < 0\n");
-		return 0;
+		return -1;
 	}
 	if (!inode)
 	{
 		printk(KERN_ERR "udf: inode_bmap: NULL inode\n");
-		return 0;
+		return -1;
 	}
 
 	b_off = block << inode->i_sb->s_blocksize_bits;
diff -u --recursive --new-file v2.3.24/linux/fs/udf/lowlevel.c linux/fs/udf/lowlevel.c
--- v2.3.24/linux/fs/udf/lowlevel.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/udf/lowlevel.c	Sat Oct 30 09:42:30 1999
@@ -95,16 +95,17 @@
 	int ret;
 	unsigned long lblock;
 	unsigned int hbsize = get_hardblocksize(dev);
+	unsigned int secsize = 512;
 	unsigned int mult = 0;
 	unsigned int div = 0;
 
 	if (!hbsize)
-		hbsize = 512;
+		hbsize = blksize_size[MAJOR(dev)][MINOR(dev)];
 
-	if (hbsize > blksize_size[MAJOR(dev)][MINOR(dev)])
-		mult = hbsize / blksize_size[MAJOR(dev)][MINOR(dev)];
-	else if (blksize_size[MAJOR(dev)][MINOR(dev)] > hbsize)
-		div = blksize_size[MAJOR(dev)][MINOR(dev)] / hbsize;
+	if (secsize > hbsize)
+		mult = secsize / hbsize;
+	else if (hbsize > secsize)
+		div = hbsize / secsize;
 
 	if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
 	{
@@ -138,7 +139,7 @@
 		}
 
 		set_fs(old_fs);
-		if (!ret)
+		if (!ret && lblock)
 			return lblock - 1;
 	}
 	else
diff -u --recursive --new-file v2.3.24/linux/fs/udf/misc.c linux/fs/udf/misc.c
--- v2.3.24/linux/fs/udf/misc.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/udf/misc.c	Sat Oct 30 09:42:30 1999
@@ -66,28 +66,6 @@
 	return indat >> 32;
 }
 
-/*
- * udf_stamp_to_time
- */
-time_t * 
-udf_stamp_to_time(time_t *dest, timestamp src)
-{
-	struct ktm tm;
-
-	if ((!dest))
-		return NULL;
-
-	/* this is very rough. need to find source to mktime() */
-	tm.tm_year=(src.year) - 1900;	
-	tm.tm_mon=(src.month);
-	tm.tm_mday=(src.day);
-	tm.tm_hour=src.hour;
-	tm.tm_min=src.minute;
-	tm.tm_sec=src.second;
-	*dest = udf_converttime(&tm);
-	return dest;
-}
-
 uid_t udf_convert_uid(int uidin)
 {
 	if ( uidin == -1 )
diff -u --recursive --new-file v2.3.24/linux/fs/udf/namei.c linux/fs/udf/namei.c
--- v2.3.24/linux/fs/udf/namei.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/udf/namei.c	Sat Oct 30 09:42:30 1999
@@ -49,141 +49,95 @@
 	struct udf_fileident_bh *fibh,
 	Uint8 *impuse, Uint8 *fileident)
 {
-	struct FileIdentDesc *efi;
 	Uint16 crclen = fibh->eoffset - fibh->soffset - sizeof(tag);
 	Uint16 crc;
 	Uint8 checksum = 0;
 	int i;
-	int offset, len;
-	int padlen = fibh->eoffset - fibh->soffset - cfi->lengthOfImpUse - cfi->lengthFileIdent -
+	int offset;
+	Uint16 liu = le16_to_cpu(cfi->lengthOfImpUse);
+	Uint8 lfi = cfi->lengthFileIdent;
+	int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
 		sizeof(struct FileIdentDesc);
 
-	crc = udf_crc((Uint8 *)cfi + sizeof(tag), sizeof(struct FileIdentDesc) -
-		sizeof(tag), 0);
-	efi = (struct FileIdentDesc *)(fibh->ebh->b_data + fibh->soffset);
-	if (fibh->sbh == fibh->ebh ||
-		(!fileident &&
-			(sizeof(struct FileIdentDesc) + (impuse ? cfi->lengthOfImpUse : 0))
-			<= -fibh->soffset))
-	{
-		memcpy((Uint8 *)sfi, (Uint8 *)cfi, sizeof(struct FileIdentDesc));
-
-		if (impuse)
-			memcpy(sfi->impUse, impuse, cfi->lengthOfImpUse);
 
-		if (fileident)
-			memcpy(sfi->fileIdent + cfi->lengthOfImpUse, fileident,
-				cfi->lengthFileIdent);
-
-        /* Zero padding */
-		memset(sfi->fileIdent + cfi->lengthOfImpUse + cfi->lengthFileIdent, 0,
-			padlen);
+	offset = fibh->soffset + sizeof(struct FileIdentDesc);
 
-		if (fibh->sbh == fibh->ebh)
-			crc = udf_crc((Uint8 *)sfi + sizeof(tag), crclen, 0);
+	if (impuse)
+	{
+		if (offset + liu < 0)
+			memcpy((Uint8 *)sfi->impUse, impuse, liu);
+		else if (offset >= 0)
+			memcpy(fibh->ebh->b_data + offset, impuse, liu);
 		else
 		{
-			crc = udf_crc((Uint8 *)sfi + sizeof(tag), crclen - fibh->eoffset, 0);
-			crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
+			memcpy((Uint8 *)sfi->impUse, impuse, -offset);
+			memcpy(fibh->ebh->b_data, impuse - offset, liu + offset);
 		}
+	}
 
-		sfi->descTag.descCRC = cpu_to_le32(crc);
-		sfi->descTag.descCRCLength = cpu_to_le16(crclen);
-
-		for (i=0; i<16; i++)
-			if (i != 4)
-				checksum += ((Uint8 *)&sfi->descTag)[i];
-
-		sfi->descTag.tagChecksum = checksum;
+	offset += liu;
 
-		mark_buffer_dirty(fibh->sbh, 1);
-	}
-	else
+	if (fileident)
 	{
-		offset = -fibh->soffset;
-		len = sizeof(struct FileIdentDesc);
-
-		if (len <= offset)
-			memcpy((Uint8 *)sfi, (Uint8 *)cfi, len);
+		if (offset + lfi < 0)
+			memcpy((Uint8 *)sfi->fileIdent + liu, fileident, lfi);
+		else if (offset >= 0)
+			memcpy(fibh->ebh->b_data + offset, fileident, lfi);
 		else
 		{
-			memcpy((Uint8 *)sfi, (Uint8 *)cfi, offset);
-			memcpy(fibh->ebh->b_data, (Uint8 *)cfi + offset, len - offset);
-		}
-
-		offset -= len;
-		len = cfi->lengthOfImpUse;
-
-		if (impuse)
-		{
-			if (offset <= 0)
-				memcpy(efi->impUse, impuse, len);
-			else if (sizeof(struct FileIdentDesc) + len <= -fibh->soffset)
-				memcpy(sfi->impUse, impuse, len);
-			else
-			{
-				memcpy(sfi->impUse, impuse, offset);
-				memcpy(efi->impUse + offset, impuse + offset, len - offset);
-			}
+			memcpy((Uint8 *)sfi->fileIdent + liu, fileident, -offset);
+			memcpy(fibh->ebh->b_data, fileident - offset, lfi + offset);
 		}
+	}
 
-		offset -= len;
-		len = cfi->lengthFileIdent;
+	offset += lfi;
 
-		if (fileident)
-		{
-			if (offset <= 0)
-				memcpy(efi->fileIdent + cfi->lengthOfImpUse, fileident, len);
-			else
-			{
-				memcpy(sfi->fileIdent + cfi->lengthOfImpUse, fileident, offset);
-				memcpy(efi->fileIdent + cfi->lengthOfImpUse + offset,
-					fileident + offset, len - offset);
-			}
-		}
+	if (offset + padlen < 0)
+		memset((Uint8 *)sfi->padding + liu + lfi, 0x00, padlen);
+	else if (offset >= 0)
+		memset(fibh->ebh->b_data + offset, 0x00, padlen);
+	else
+	{
+		memset((Uint8 *)sfi->padding + liu + lfi, 0x00, -offset);
+		memset(fibh->ebh->b_data, 0x00, padlen + offset);
+	}
 
-        /* Zero padding */
-        memset(efi->fileIdent + cfi->lengthOfImpUse + cfi->lengthFileIdent, 0x00,
-			padlen);
+	crc = udf_crc((Uint8 *)cfi + sizeof(tag), sizeof(struct FileIdentDesc) -
+		sizeof(tag), 0);
 
-		if (sizeof(tag) < -fibh->soffset)
-		{
-			crc = udf_crc((Uint8 *)sfi + sizeof(tag), crclen - fibh->eoffset, 0);
-			crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
-		}
-		else
-			crc = udf_crc((Uint8 *)fibh->ebh->b_data + fibh->eoffset - crclen, crclen, 0);
+	if (fibh->sbh == fibh->ebh)
+		crc = udf_crc((Uint8 *)sfi->impUse,
+			crclen + sizeof(tag) - sizeof(struct FileIdentDesc), crc);
+	else if (sizeof(struct FileIdentDesc) >= -fibh->soffset)
+		crc = udf_crc(fibh->ebh->b_data + sizeof(struct FileIdentDesc) + fibh->soffset,
+			crclen + sizeof(tag) - sizeof(struct FileIdentDesc), crc);
+	else
+	{
+		crc = udf_crc((Uint8 *)sfi->impUse,
+			-fibh->soffset - sizeof(struct FileIdentDesc), crc);
+		crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
+	}
 
-		if (&(efi->descTag.descCRC) < (Uint16 *)fibh->ebh->b_data)
-		{
-			sfi->descTag.descCRC = cpu_to_le16(crc);
-			sfi->descTag.descCRCLength = cpu_to_le16(crclen);
-		}
-		else
-		{
-			efi->descTag.descCRC = cpu_to_le16(crc);
-			efi->descTag.descCRCLength = cpu_to_le16(crclen);
-		}
+	cfi->descTag.descCRC = cpu_to_le32(crc);
+	cfi->descTag.descCRCLength = cpu_to_le16(crclen);
 
-		for (i=0; i<16; i++)
-		{
-			if (i != 4)
-			{
-				if (&(((Uint8 *)&efi->descTag)[i]) < (Uint8 *)fibh->ebh->b_data)
-					checksum += ((Uint8 *)&sfi->descTag)[i];
-				else
-					checksum += ((Uint8 *)&efi->descTag)[i];
-			}
-		}
+	for (i=0; i<16; i++)
+		if (i != 4)
+			checksum += ((Uint8 *)&cfi->descTag)[i];
 
-		if (&(cfi->descTag.tagChecksum) < (Uint8 *)fibh->ebh->b_data)
-			sfi->descTag.tagChecksum = checksum;
-		else
-			efi->descTag.tagChecksum = checksum;
+	cfi->descTag.tagChecksum = checksum;
+	if (sizeof(struct FileIdentDesc) <= -fibh->soffset)
+		memcpy((Uint8 *)sfi, (Uint8 *)cfi, sizeof(struct FileIdentDesc));
+	else
+	{
+		memcpy((Uint8 *)sfi, (Uint8 *)cfi, -fibh->soffset);
+		memcpy(fibh->ebh->b_data, (Uint8 *)cfi - fibh->soffset,
+			sizeof(struct FileIdentDesc) + fibh->soffset);
+	}
 
-		mark_buffer_dirty(fibh->sbh, 1);
+	if (fibh->sbh != fibh->ebh)
 		mark_buffer_dirty(fibh->ebh, 1);
-	}
+	mark_buffer_dirty(fibh->sbh, 1);
 	return 0;
 }
 
@@ -214,7 +168,7 @@
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
 	{
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
-		if (++offset < (elen >> dir->i_sb->s_blocksize_bits))
+		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
 			if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
 				extoffset -= sizeof(short_ad);
@@ -240,8 +194,6 @@
 	while ( (f_pos < size) )
 	{
 		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &offset, &bh);
-		liu = le16_to_cpu(cfi->lengthOfImpUse);
-		lfi = cfi->lengthFileIdent;
 
 		if (!fi)
 		{
@@ -252,6 +204,9 @@
 			return NULL;
 		}
 
+		liu = le16_to_cpu(cfi->lengthOfImpUse);
+		lfi = cfi->lengthFileIdent;
+
 		if (fibh->sbh == fibh->ebh)
 		{
 			nameptr = fi->fileIdent + liu;
@@ -422,7 +377,7 @@
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
 	{
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
-		if (++offset < (elen >> dir->i_sb->s_blocksize_bits))
+		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
 			if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
 				extoffset -= sizeof(short_ad);
@@ -446,8 +401,6 @@
 	while ( (f_pos < size) )
 	{
 		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &offset, &bh);
-		liu = le16_to_cpu(cfi->lengthOfImpUse);
-		lfi = cfi->lengthFileIdent;
 
 		if (!fi)
 		{
@@ -458,6 +411,9 @@
 			return NULL;
 		}
 
+		liu = le16_to_cpu(cfi->lengthOfImpUse);
+		lfi = cfi->lengthFileIdent;
+
 		if (fibh->sbh == fibh->ebh)
 			nameptr = fi->fileIdent + liu;
 		else
@@ -520,6 +476,8 @@
 		fibh->soffset -= UDF_I_EXT0OFFS(dir);
 		fibh->eoffset -= UDF_I_EXT0OFFS(dir);
 		f_pos -= (UDF_I_EXT0OFFS(dir) >> 2);
+		if (fibh->sbh != fibh->ebh)
+			udf_release_data(fibh->ebh);
 		udf_release_data(fibh->sbh);
 		if (!(fibh->sbh = fibh->ebh = udf_expand_adinicb(dir, &block, 1, err)))
 			return NULL;
@@ -557,10 +515,12 @@
 			}
 			else
 			{
-				elen += nfidlen;
+				if (elen & (sb->s_blocksize - 1))
+					elen += nfidlen;
+				block = eloc.logicalBlockNum + ((elen - 1) >>
+					dir->i_sb->s_blocksize_bits);
 				elen = (EXTENT_RECORDED_ALLOCATED << 30) | elen;
 				udf_write_aext(dir, bloc, &lextoffset, eloc, elen, &bh, 1);
-				block = eloc.logicalBlockNum + (elen >> dir->i_sb->s_blocksize_bits);
 			}
 		}
 		else
@@ -588,10 +548,16 @@
 			return NULL;
 		}
 		else
-			block = eloc.logicalBlockNum + (elen >> dir->i_sb->s_blocksize_bits);
+		{
+			elen = ((elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
+			block = eloc.logicalBlockNum + ((elen - 1) >>
+				dir->i_sb->s_blocksize_bits);
+			elen = (EXTENT_RECORDED_ALLOCATED << 30) | elen;
+			udf_write_aext(dir, bloc, &lextoffset, eloc, elen, &bh, 0);
+		}
 
 		*err = -ENOSPC;
-		if (!(fibh->ebh = udf_getblk(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
+		if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
 		{
 			udf_release_data(bh);
 			udf_release_data(fibh->sbh);
@@ -602,7 +568,8 @@
 			if (udf_next_aext(dir, &bloc, &lextoffset, &eloc, &elen, &bh, 1) ==
 				EXTENT_RECORDED_ALLOCATED)
 			{
-				block = eloc.logicalBlockNum + (elen >> dir->i_sb->s_blocksize_bits);
+				block = eloc.logicalBlockNum + ((elen - 1) >>
+					dir->i_sb->s_blocksize_bits);
 			}
 			else
 				block ++;
@@ -854,7 +821,7 @@
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
 	{
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
-		if (++offset < (elen >> dir->i_sb->s_blocksize_bits))
+		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
 			if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
 				extoffset -= sizeof(short_ad);
diff -u --recursive --new-file v2.3.24/linux/fs/udf/super.c linux/fs/udf/super.c
--- v2.3.24/linux/fs/udf/super.c	Fri Sep 10 23:57:36 1999
+++ linux/fs/udf/super.c	Sat Oct 30 09:42:30 1999
@@ -768,18 +768,20 @@
 {
 	struct PrimaryVolDesc *pvoldesc;
 	time_t recording;
+	long recording_usec;
 	struct ustr instr;
 	struct ustr outstr;
 
 	pvoldesc = (struct PrimaryVolDesc *)bh->b_data;
 
-	if ( udf_stamp_to_time(&recording, lets_to_cpu(pvoldesc->recordingDateAndTime)) )
+	if ( udf_stamp_to_time(&recording, &recording_usec,
+		lets_to_cpu(pvoldesc->recordingDateAndTime)) )
 	{
 	    timestamp ts;
 	    ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
-		udf_debug("recording time %ld, %u/%u/%u %u:%u (%x)\n",
-			recording, ts.year, ts.month, ts.day, ts.hour, ts.minute,
-			ts.typeAndTimezone);
+		udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n",
+			recording, recording_usec,
+			ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.typeAndTimezone);
 	    UDF_SB_RECORDTIME(sb) = recording;
 	}
 
@@ -1397,8 +1399,9 @@
 	{
 		timestamp ts;
 		udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0);
-		udf_info("Mounting volume '%s', timestamp %u/%02u/%u %02u:%02u\n",
-			UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute);
+		udf_info("Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
+			UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
+			ts.typeAndTimezone);
 	}
 	if (!(sb->s_flags & MS_RDONLY))
 		udf_open_lvid(sb);
diff -u --recursive --new-file v2.3.24/linux/fs/udf/udfdecl.h linux/fs/udf/udfdecl.h
--- v2.3.24/linux/fs/udf/udfdecl.h	Tue Sep  7 12:14:07 1999
+++ linux/fs/udf/udfdecl.h	Sat Oct 30 09:42:30 1999
@@ -1,7 +1,7 @@
 #ifndef __UDF_DECL_H
 #define __UDF_DECL_H
 
-#define UDF_VERSION_NOTICE "v0.8.9"
+#define UDF_VERSION_NOTICE "v0.8.9.3"
 
 #ifdef __KERNEL__
 
@@ -249,7 +249,7 @@
 extern Uint32 udf64_high32(Uint64);
 
 
-extern time_t *udf_stamp_to_time(time_t *, timestamp);
+extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
 extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
 extern time_t udf_converttime (struct ktm *);
 
diff -u --recursive --new-file v2.3.24/linux/fs/udf/udfend.h linux/fs/udf/udfend.h
--- v2.3.24/linux/fs/udf/udfend.h	Fri Sep 10 23:57:36 1999
+++ linux/fs/udf/udfend.h	Sat Oct 30 09:42:30 1999
@@ -42,13 +42,13 @@
 #define cpu_to_le32(x) (x)
 #define cpu_to_le64(x) (x)
 
-#endif
+#endif /* __BYTE_ORDER == 0 */
 
-#endif
+#else /* __KERNEL__ */
 
-#ifdef __KERNEL__
 #include <linux/string.h>
-#endif
+
+#endif /* ! __KERNEL__ */
 
 static inline lb_addr lelb_to_cpu(lb_addr in)
 {
diff -u --recursive --new-file v2.3.24/linux/fs/udf/udftime.c linux/fs/udf/udftime.c
--- v2.3.24/linux/fs/udf/udftime.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/udf/udftime.c	Sat Oct 30 09:42:30 1999
@@ -18,16 +18,19 @@
    Boston, MA 02111-1307, USA.  */
 
 /*
- * dgb 10/2/98: ripped this from glibc source to help convert timestamps to unix time 
- *     10/4/98: added new table-based lookup after seeing how ugly the gnu code is
+ * dgb 10/02/98: ripped this from glibc source to help convert timestamps to unix time 
+ *     10/04/98: added new table-based lookup after seeing how ugly the gnu code is
+ * blf 09/27/99: ripped out all the old code and inserted new table from
+ *					John Brockmeyer (without leap second corrections)
+ *				 rewrote udf_stamp_to_time and fixed timezone accounting in
+					udf_time_to_stamp.
  */
 
-/* Assume that leap seconds are possible, unless told otherwise.
-   If the host has a `zic' command with a `-L leapsecondfilename' option,
-   then it supports leap seconds; otherwise it probably doesn't.  */
-#ifndef LEAP_SECONDS_POSSIBLE
-#define LEAP_SECONDS_POSSIBLE 1
-#endif
+/*
+ * We don't take into account leap seconds. This may be correct or incorrect.
+ * For more NIST information (especially dealing with leap seconds), see:
+ *  http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm
+ */
 
 #if defined(__linux__) && defined(__KERNEL__)
 #include <linux/types.h>
@@ -35,30 +38,11 @@
 #else
 #include <stdio.h>
 #include <sys/types.h>
+#include <sys/time.h>
 #endif
 
 #include "udfdecl.h"
 
-#ifndef CHAR_BIT
-#define CHAR_BIT 8
-#endif
-
-#ifndef INT_MIN
-#define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
-#endif
-#ifndef INT_MAX
-#define INT_MAX (~0 - INT_MIN)
-#endif
-
-#ifndef TIME_T_MIN
-#define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
-		    : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
-#endif
-#ifndef TIME_T_MAX
-#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
-#endif
-
-#define TM_YEAR_BASE 1900
 #define EPOCH_YEAR 1970
 
 #ifndef __isleap
@@ -77,70 +61,85 @@
     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
   };
 
-time_t udf_converttime (struct ktm *);
-#ifndef USE_GNU_MKTIME_METHOD
-
-#define MAX_YEAR_SECONDS	68
+#define MAX_YEAR_SECONDS	69
+#define SPD 0x15180 /*3600*24*/
+#define SPY(y,l,s) (SPD * (365*y+l)+s)
 
 time_t year_seconds[MAX_YEAR_SECONDS]= {
-	0, 
-	/*1971:*/ 31554000, /*1972:*/ 63090000, /*1973:*/ 94712400,
- 	/*1974:*/ 126248400, /*1975:*/ 157784400, /*1976:*/ 189320400,
- 	/*1977:*/ 220942800, /*1978:*/ 252478800, /*1979:*/ 284014800,
- 	/*1980:*/ 315550800, /*1981:*/ 347173200, /*1982:*/ 378709200,
- 	/*1983:*/ 410245200, /*1984:*/ 441781200, /*1985:*/ 473403600,
- 	/*1986:*/ 504939600, /*1987:*/ 536475600, /*1988:*/ 568011600,
- 	/*1989:*/ 599634000, /*1990:*/ 631170000, /*1991:*/ 662706000,
- 	/*1992:*/ 694242000, /*1993:*/ 725864400, /*1994:*/ 757400400,
- 	/*1995:*/ 788936400, /*1996:*/ 820472400, /*1997:*/ 852094800,
- 	/*1998:*/ 883630800, /*1999:*/ 915166800, /*2000:*/ 946702800,
- 	/*2001:*/ 978325200, /*2002:*/ 1009861200, /*2003:*/ 1041397200,
- 	/*2004:*/ 1072933200, /*2005:*/ 1104555600, /*2006:*/ 1136091600,
- 	/*2007:*/ 1167627600, /*2008:*/ 1199163600, /*2009:*/ 1230786000,
- 	/*2010:*/ 1262322000, /*2011:*/ 1293858000, /*2012:*/ 1325394000,
- 	/*2013:*/ 1357016400, /*2014:*/ 1388552400, /*2015:*/ 1420088400,
- 	/*2016:*/ 1451624400, /*2017:*/ 1483246800, /*2018:*/ 1514782800,
- 	/*2019:*/ 1546318800, /*2020:*/ 1577854800, /*2021:*/ 1609477200,
- 	/*2022:*/ 1641013200, /*2023:*/ 1672549200, /*2024:*/ 1704085200,
- 	/*2025:*/ 1735707600, /*2026:*/ 1767243600, /*2027:*/ 1798779600,
- 	/*2028:*/ 1830315600, /*2029:*/ 1861938000, /*2030:*/ 1893474000,
- 	/*2031:*/ 1925010000, /*2032:*/ 1956546000, /*2033:*/ 1988168400,
- 	/*2034:*/ 2019704400, /*2035:*/ 2051240400, /*2036:*/ 2082776400,
- 	/*2037:*/ 2114398800
+/*1970*/ SPY( 0, 0,0), SPY( 1, 0,0), SPY( 2, 0,0), SPY( 3, 1,0), 
+/*1974*/ SPY( 4, 1,0), SPY( 5, 1,0), SPY( 6, 1,0), SPY( 7, 2,0), 
+/*1978*/ SPY( 8, 2,0), SPY( 9, 2,0), SPY(10, 2,0), SPY(11, 3,0), 
+/*1982*/ SPY(12, 3,0), SPY(13, 3,0), SPY(14, 3,0), SPY(15, 4,0), 
+/*1986*/ SPY(16, 4,0), SPY(17, 4,0), SPY(18, 4,0), SPY(19, 5,0), 
+/*1990*/ SPY(20, 5,0), SPY(21, 5,0), SPY(22, 5,0), SPY(23, 6,0), 
+/*1994*/ SPY(24, 6,0), SPY(25, 6,0), SPY(26, 6,0), SPY(27, 7,0), 
+/*1998*/ SPY(28, 7,0), SPY(29, 7,0), SPY(30, 7,0), SPY(31, 8,0), 
+/*2002*/ SPY(32, 8,0), SPY(33, 8,0), SPY(34, 8,0), SPY(35, 9,0), 
+/*2006*/ SPY(36, 9,0), SPY(37, 9,0), SPY(38, 9,0), SPY(39,10,0), 
+/*2010*/ SPY(40,10,0), SPY(41,10,0), SPY(42,10,0), SPY(43,11,0), 
+/*2014*/ SPY(44,11,0), SPY(45,11,0), SPY(46,11,0), SPY(47,12,0), 
+/*2018*/ SPY(48,12,0), SPY(49,12,0), SPY(50,12,0), SPY(51,13,0), 
+/*2022*/ SPY(52,13,0), SPY(53,13,0), SPY(54,13,0), SPY(55,14,0), 
+/*2026*/ SPY(56,14,0), SPY(57,14,0), SPY(58,14,0), SPY(59,15,0), 
+/*2030*/ SPY(60,15,0), SPY(61,15,0), SPY(62,15,0), SPY(63,16,0), 
+/*2034*/ SPY(64,16,0), SPY(65,16,0), SPY(66,16,0), SPY(67,17,0), 
+/*2038*/ SPY(68,17,0)
 };
 
-time_t udf_converttime (struct ktm *tm)
-{
-    time_t r;
-    int yday;
-
-	if ( !tm )
-		return -1;
-	if ( (tm->tm_year+TM_YEAR_BASE < EPOCH_YEAR) || 
-		 (tm->tm_year+TM_YEAR_BASE > EPOCH_YEAR+MAX_YEAR_SECONDS) )
-		return -1;
-	r = year_seconds[tm->tm_year-70];
-
-	yday = ((__mon_yday[__isleap (tm->tm_year + TM_YEAR_BASE)]
-	       [tm->tm_mon-1])
-	      + tm->tm_mday - 1);
-	r += ( ( (yday* 24) + (tm->tm_hour-1) ) * 60 + tm->tm_min ) * 60 + tm->tm_sec;
-	return r;
-}
-
 #ifdef __KERNEL__
-
 extern struct timezone sys_tz;
+#endif
 
 #define SECS_PER_HOUR   (60 * 60)
 #define SECS_PER_DAY    (SECS_PER_HOUR * 24)
 
+time_t *
+udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
+{
+	int yday;
+	Uint8 type = src.typeAndTimezone >> 12;
+	Sint16 offset;
+
+	if (type == 1)
+	{
+		offset = src.typeAndTimezone << 4;
+		/* sign extent offset */
+		offset = (offset >> 4);
+	}
+	else
+		offset = 0;
+
+	if ((src.year < EPOCH_YEAR) ||
+		(src.year > EPOCH_YEAR+MAX_YEAR_SECONDS))
+	{
+		*dest = -1;
+		*dest_usec = -1;
+		return NULL;
+	}
+	*dest = year_seconds[src.year - EPOCH_YEAR];
+	*dest -= offset * 60;
+
+	yday = ((__mon_yday[__isleap (src.year)]
+		[src.month-1]) + (src.day-1));
+	*dest += ( ( (yday* 24) + src.hour ) * 60 + src.minute ) * 60 + src.second;
+	*dest_usec = src.centiseconds * 10000 + src.hundredsOfMicroseconds * 100 + src.microseconds;
+	return dest;
+}
+
+
 timestamp *
 udf_time_to_stamp(timestamp *dest, time_t tv_sec, long tv_usec)
 {
 	long int days, rem, y;
 	const unsigned short int *ip;
-	int offset = (-sys_tz.tz_minuteswest + (sys_tz.tz_dsttime ? 60 : 0));
+	Sint16 offset;
+#ifndef __KERNEL__
+	struct timeval tv;
+	struct timezone sys_tz;
+
+	gettimeofday(&tv, &sys_tz);
+#endif
+	offset = (-sys_tz.tz_minuteswest + (sys_tz.tz_dsttime ? 60 : 0));
 
     if (!dest)
         return NULL;
@@ -183,191 +182,5 @@
 		dest->hundredsOfMicroseconds * 100);
     return dest;
 }
-#endif
-
-#else
-
-static time_t ydhms_tm_diff (int, int, int, int, int, const struct ktm *);
-
-
-/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
-   measured in seconds, ignoring leap seconds.
-   YEAR uses the same numbering as TM->tm_year.
-   All values are in range, except possibly YEAR.
-   If overflow occurs, yield the low order bits of the correct answer.  */
-static time_t
-ydhms_tm_diff (int year, int yday, int hour, int min, int sec, const struct ktm *tp)
-{
-  time_t result;
-
-  /* Compute intervening leap days correctly even if year is negative.
-     Take care to avoid int overflow.  time_t overflow is OK, since
-     only the low order bits of the correct time_t answer are needed.
-     Don't convert to time_t until after all divisions are done, since
-     time_t might be unsigned.  */
-  int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
-  int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
-  int a100 = a4 / 25 - (a4 % 25 < 0);
-  int b100 = b4 / 25 - (b4 % 25 < 0);
-  int a400 = a100 >> 2;
-  int b400 = b100 >> 2;
-  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
-  time_t years = year - (time_t) tp->tm_year;
-  time_t days = (365 * years + intervening_leap_days);
-  result= (60 * (60 * (24 * days + (hour - tp->tm_hour))
-		+ (min - tp->tm_min))
-	  + (sec - tp->tm_sec));
-#ifdef __KERNEL__
-  printk(KERN_ERR "udf: ydhms_tm_diff(%d,%d,%d,%d,%d,) returning %ld\n",
-	year, yday, hour, min, sec, result);
-#endif
-  return result;
-}
-
-
-/* Convert *TP to a time_t value, inverting
-   the monotonic and mostly-unit-linear conversion function CONVERT.
-   Use *OFFSET to keep track of a guess at the offset of the result,
-   compared to what the result would be for UTC without leap seconds.
-   If *OFFSET's guess is correct, only one CONVERT call is needed.  */
-time_t
-udf_converttime (struct ktm *tp)
-{
-  time_t t, dt, t0;
-  struct ktm tm;
-
-  /* The maximum number of probes (calls to CONVERT) should be enough
-     to handle any combinations of time zone rule changes, solar time,
-     and leap seconds.  Posix.1 prohibits leap seconds, but some hosts
-     have them anyway.  */
-  int remaining_probes = 4;
-
-  /* Time requested.  Copy it in case CONVERT modifies *TP; this can
-     occur if TP is localtime's returned value and CONVERT is localtime.  */
-  int sec = tp->tm_sec;
-  int min = tp->tm_min;
-  int hour = tp->tm_hour;
-  int mday = tp->tm_mday;
-  int mon = tp->tm_mon;
-  int year_requested = tp->tm_year;
-  int isdst = tp->tm_isdst;
-
-  /* Ensure that mon is in range, and set year accordingly.  */
-  int mon_remainder = mon % 12;
-  int negative_mon_remainder = mon_remainder < 0;
-  int mon_years = mon / 12 - negative_mon_remainder;
-  int year = year_requested + mon_years;
-
-  /* The other values need not be in range:
-     the remaining code handles minor overflows correctly,
-     assuming int and time_t arithmetic wraps around.
-     Major overflows are caught at the end.  */
-
-  /* Calculate day of year from year, month, and day of month.
-     The result need not be in range.  */
-  int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
-	       [mon_remainder + 12 * negative_mon_remainder])
-	      + mday - 1);
-
-#if LEAP_SECONDS_POSSIBLE
-  /* Handle out-of-range seconds specially,
-     since ydhms_tm_diff assumes every minute has 60 seconds.  */
-  int sec_requested = sec;
-  if (sec < 0)
-    sec = 0;
-  if (59 < sec)
-    sec = 59;
-#endif
-
-  /* Invert CONVERT by probing.  First assume the same offset as last time.
-     Then repeatedly use the error to improve the guess.  */
-
-  tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
-  tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
-  /*
-  t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
-
-  for (t = t0; 
-       (dt = ydhms_tm_diff (year, yday, hour, min, sec, &tm));
-       t += dt)
-    if (--remaining_probes == 0)
-      return -1;
-  */
-
-  /* Check whether tm.tm_isdst has the requested value, if any.  */
-  if (0 <= isdst && 0 <= tm.tm_isdst)
-    {
-      int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
-      if (dst_diff)
-	{
-	  /* Move two hours in the direction indicated by the disagreement,
-	     probe some more, and switch to a new time if found.
-	     The largest known fallback due to daylight savings is two hours:
-	     once, in Newfoundland, 1988-10-30 02:00 -> 00:00.  */
-	  time_t ot = t - 2 * 60 * 60 * dst_diff;
-	  while (--remaining_probes != 0)
-	    {
-	      struct ktm otm;
-	      if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
-					 &otm)))
-		{
-		  t = ot;
-		  tm = otm;
-		  break;
-		}
-	      if ((ot += dt) == t)
-		break;  /* Avoid a redundant probe.  */
-	    }
-	}
-    }
-
-
-#if LEAP_SECONDS_POSSIBLE
-  if (sec_requested != tm.tm_sec)
-    {
-      /* Adjust time to reflect the tm_sec requested, not the normalized value.
-	 Also, repair any damage from a false match due to a leap second.  */
-      t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
-    }
-#endif
-
-  if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
-    {
-      /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
-	 so check for major overflows.  A gross check suffices,
-	 since if t has overflowed, it is off by a multiple of
-	 TIME_T_MAX - TIME_T_MIN + 1.  So ignore any component of
-	 the difference that is bounded by a small value.  */
-
-      double dyear = (double) year_requested + mon_years - tm.tm_year;
-      double dday = 366 * dyear + mday;
-      double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
-
-      if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
-	return -1;
-    }
-
-  *tp = tm;
-#ifdef __KERNEL__
-  udf_debug("returning %ld\n", t);
-#endif
-  return t;
-}
-#endif
-
-#ifdef INCLUDE_PRINT_KTM
-static void
-print_ktm (struct ktm *tp)
-{
-#ifdef __KERNEL__
-  udf_debug(
-#else
-  printf(
-#endif
-	"%04d-%02d-%02d %02d:%02d:%02d isdst %d",
-	  tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
-	  tp->tm_hour, tp->tm_min, tp->tm_sec, tp->tm_isdst);
-}
-#endif
 
 /* EOF */
diff -u --recursive --new-file v2.3.24/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h
--- v2.3.24/linux/include/asm-alpha/termios.h	Wed Mar 24 11:46:00 1999
+++ linux/include/asm-alpha/termios.h	Wed Oct 27 17:04:51 1999
@@ -80,6 +80,7 @@
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
 
 #ifdef __KERNEL__
 /*	eof=^D		eol=\0		eol2=\0		erase=del
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/arch-arc/memory.h linux/include/asm-arm/arch-arc/memory.h
--- v2.3.24/linux/include/asm-arm/arch-arc/memory.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-arc/memory.h	Thu Oct 28 10:16:02 1999
@@ -21,6 +21,7 @@
  * Page offset: 32MB
  */
 #define PAGE_OFFSET	(0x02000000UL)
+#define PHYS_OFFSET	(0x02000000UL)
 
 #define __virt_to_phys__is_a_macro
 #define __virt_to_phys(vpage) vpage
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/arch-ebsa110/memory.h linux/include/asm-arm/arch-ebsa110/memory.h
--- v2.3.24/linux/include/asm-arm/arch-ebsa110/memory.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-ebsa110/memory.h	Thu Oct 28 10:16:02 1999
@@ -22,6 +22,7 @@
  * Page offset: 3GB
  */
 #define PAGE_OFFSET	(0xc0000000UL)
+#define PHYS_OFFSET	(0x00000000UL)
 
 #define __virt_to_phys__is_a_macro
 #define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/arch-ebsa285/memory.h linux/include/asm-arm/arch-ebsa285/memory.h
--- v2.3.24/linux/include/asm-arm/arch-ebsa285/memory.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-ebsa285/memory.h	Thu Oct 28 10:16:02 1999
@@ -29,6 +29,7 @@
  * Page offset: 3GB
  */
 #define PAGE_OFFSET		(0xc0000000UL)
+#define PHYS_OFFSET		(0x00000000UL)
 
 #define __virt_to_bus__is_a_macro
 #define __virt_to_bus(x)	((x) - 0xe0000000)
@@ -49,6 +50,7 @@
  * Page offset: 1.5GB
  */
 #define PAGE_OFFSET		(0x60000000UL)
+#define PHYS_OFFSET		(0x00000000UL)
 
 #else
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/arch-nexuspci/memory.h linux/include/asm-arm/arch-nexuspci/memory.h
--- v2.3.24/linux/include/asm-arm/arch-nexuspci/memory.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-nexuspci/memory.h	Thu Oct 28 10:16:02 1999
@@ -18,12 +18,13 @@
  * Page offset: 3GB
  */
 #define PAGE_OFFSET	(0xc0000000UL)
+#define PHYS_OFFSET	(0x40000000UL)
 
 /*
  * On NexusPCI, the DRAM is contiguous
  */
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000)
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000)
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET)
 #define __virt_to_phys__is_a_macro
 #define __phys_to_virt__is_a_macro
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/arch-rpc/memory.h linux/include/asm-arm/arch-rpc/memory.h
--- v2.3.24/linux/include/asm-arm/arch-rpc/memory.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-rpc/memory.h	Thu Oct 28 10:16:02 1999
@@ -24,11 +24,12 @@
  * Page offset: 3GB
  */
 #define PAGE_OFFSET	(0xc0000000UL)
+#define PHYS_OFFSET	(0x10000000UL)
 
 #define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x10000000)
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
 #define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x10000000)
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET)
 
 /*
  * These are exactly the same on the RiscPC as the
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/arch-rpc/system.h linux/include/asm-arm/arch-rpc/system.h
--- v2.3.24/linux/include/asm-arm/arch-rpc/system.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-rpc/system.h	Thu Oct 28 10:16:02 1999
@@ -18,7 +18,7 @@
 	outb(0, IOMD_ROMCR0);
 
 	__asm__ __volatile__(
-		"mcr  p15, 0, %0, c1, c0, 0\n\t"
-		"movs pc, #0"
+		"mcr p15, 0, %0, c1, c0, 0\n\t"
+		"mov pc, #0"
 		 : : "r" (cpu_reset()));
 }
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/arch-sa1100/memory.h linux/include/asm-arm/arch-sa1100/memory.h
--- v2.3.24/linux/include/asm-arm/arch-sa1100/memory.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-sa1100/memory.h	Thu Oct 28 10:16:02 1999
@@ -11,12 +11,13 @@
 /*
  * Task size: 3GB
  */
-#define TASK_SIZE	 (0xc0000000UL)
+#define TASK_SIZE	(0xc0000000UL)
 
 /*
  * Page offset: 3GB
  */
-#define PAGE_OFFSET	 (0xc0000000UL)
+#define PAGE_OFFSET	(0xc0000000UL)
+#define PHYS_OFFSET	(0x00000000UL)
 
 #define __virt_to_phys__is_a_macro
 #define __phys_to_virt__is_a_macro
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/io.h linux/include/asm-arm/io.h
--- v2.3.24/linux/include/asm-arm/io.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/io.h	Thu Oct 28 10:16:02 1999
@@ -185,17 +185,16 @@
 
 #endif
 
-#ifndef ARCH_READWRITE
+extern void __readwrite_bug(const char *fn);
 
-/* for panic */
-#include <linux/kernel.h>
+#ifndef ARCH_READWRITE
 
-#define readb(p)	(panic("readb called, but not implemented"),0)
-#define readw(p)	(panic("readw called, but not implemented"),0)
-#define readl(p)	(panic("readl called, but not implemented"),0)
-#define writeb(v,p)	panic("writeb called, but not implemented")
-#define writew(v,p)	panic("writew called, but not implemented")
-#define writel(v,p)	panic("writel called, but not implemented")
+#define readb(p)	(__readwrite_bug("readb"),0)
+#define readw(p)	(__readwrite_bug("readw"),0)
+#define readl(p)	(__readwrite_bug("readl"),0)
+#define writeb(v,p)	__readwrite_bug("writeb")
+#define writew(v,p)	__readwrite_bug("writew")
+#define writel(v,p)	__readwrite_bug("writel")
 
 #endif
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/page.h linux/include/asm-arm/page.h
--- v2.3.24/linux/include/asm-arm/page.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/page.h	Thu Oct 28 10:16:02 1999
@@ -12,7 +12,7 @@
 #define STRICT_MM_TYPECHECKS
 
 #define clear_page(page)	memzero((void *)(page), PAGE_SIZE)
-extern void copy_page(unsigned long to, unsigned long from);
+extern void copy_page(void *to, void *from);
 
 #ifdef STRICT_MM_TYPECHECKS
 /*
@@ -60,22 +60,18 @@
 
 #ifndef __ASSEMBLY__
 
-#define BUG() do { \
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	*(int *)0 = 0; \
-} while (0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
+extern void __bug(const char *file, int line, void *data);
+
+#define BUG()		__bug(__FILE__, __LINE__, NULL)
+#define PAGE_BUG(page)	__bug(__FILE__, __LINE__, page)
 
 #endif /* !__ASSEMBLY__ */
 
 #include <asm/arch/memory.h>
 
-#define __pa(x)			__virt_to_phys((unsigned long)(x))
-#define __va(x)			((void *)(__phys_to_virt((unsigned long)(x))))
-#define MAP_NR(addr)		(((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
+#define __pa(x)			((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x)			((void *)((unsigned long)(x) + PAGE_OFFSET))
+#define MAP_NR(addr)		(__pa(addr) >> PAGE_SHIFT)
 
 #endif
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/pgtable.h linux/include/asm-arm/pgtable.h
--- v2.3.24/linux/include/asm-arm/pgtable.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/pgtable.h	Thu Oct 28 10:16:02 1999
@@ -1,55 +1,155 @@
+/*
+ * linux/include/asm-arm/pgtable.h
+ */
 #ifndef _ASMARM_PGTABLE_H
 #define _ASMARM_PGTABLE_H
 
 #include <linux/config.h>
 
-#include <asm/arch/memory.h>		/* For TASK_SIZE */
+#include <asm/arch/memory.h>
 #include <asm/proc-fns.h>
 #include <asm/system.h>
-#include <asm/proc/cache.h>
+
+/*
+ * PMD_SHIFT determines the size of the area a second-level page table can map
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PMD_SHIFT		20
+#define PGDIR_SHIFT		20
 
 #define LIBRARY_TEXT_START	0x0c000000
 
-#undef TEST_VERIFY_AREA
+#ifndef __ASSEMBLY__
+extern void __pte_error(const char *file, int line, unsigned long val);
+extern void __pmd_error(const char *file, int line, unsigned long val);
+extern void __pgd_error(const char *file, int line, unsigned long val);
+
+#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
+#define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
+#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+#endif /* !__ASSEMBLY__ */
+
+#define PMD_SIZE		(1UL << PMD_SHIFT)
+#define PMD_MASK		(~(PMD_SIZE-1))
+#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
 
 /*
- * BAD_PAGETABLE is used when we need a bogus page-table, while
- * BAD_PAGE is used for a bogus page.
- *
+ * The table below defines the page protection levels that we insert into our
+ * Linux page table version.  These get translated into the best that the
+ * architecture can perform.  Note that on most ARM hardware:
+ *  1) We cannot do execute protection
+ *  2) If we could do execute protection, then read is implied
+ *  3) write implies read permissions
+ */
+#define __P000  PAGE_NONE
+#define __P001  PAGE_READONLY
+#define __P010  PAGE_COPY
+#define __P011  PAGE_COPY
+#define __P100  PAGE_READONLY
+#define __P101  PAGE_READONLY
+#define __P110  PAGE_COPY
+#define __P111  PAGE_COPY
+
+#define __S000  PAGE_NONE
+#define __S001  PAGE_READONLY
+#define __S010  PAGE_SHARED
+#define __S011  PAGE_SHARED
+#define __S100  PAGE_READONLY
+#define __S101  PAGE_READONLY
+#define __S110  PAGE_SHARED
+#define __S111  PAGE_SHARED
+
+#ifndef __ASSEMBLY__
+/*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
-extern unsigned long *empty_zero_page;
-
-#define BAD_PAGETABLE		__bad_pagetable()
-#define BAD_PAGE		__bad_page()
-#define ZERO_PAGE(vaddr)	((unsigned long) empty_zero_page)
-
-/* number of bits that fit into a memory pointer */
-#define BYTES_PER_PTR		(sizeof(unsigned long))
-#define BITS_PER_PTR		(8*BYTES_PER_PTR)
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK		(~(sizeof(void*)-1))
-
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-#define SIZEOF_PTR_LOG2		2
-
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-	((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+struct page *empty_zero_page;
+#define ZERO_PAGE(vaddr)	(empty_zero_page)
+
+/*
+ * Handling allocation failures during page table setup.
+ */
+extern void __handle_bad_pmd(pmd_t *pmd);
+extern void __handle_bad_pmd_kernel(pmd_t *pmd);
+
+#define pte_none(pte)		(!pte_val(pte))
+#define pte_clear(ptep)		set_pte((ptep), __pte(0))
+#define pte_pagenr(pte)		((unsigned long)(((pte_val(pte) - PHYS_OFFSET) >> PAGE_SHIFT)))
+
+#define pmd_none(pmd)		(!pmd_val(pmd))
+#define pmd_clear(pmdp)		set_pmd(pmdp, __pmd(0))
+
+/*
+ * Permanent address of a page.
+ */
+#define page_address(page)	(PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define pages_to_mb(x)		((x) >> (20 - PAGE_SHIFT))
+#define pte_page(x)		(mem_map + pte_pagenr(x))
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+#define pgd_none(pgd)		(0)
+#define pgd_bad(pgd)		(0)
+#define pgd_present(pgd)	(1)
+#define pgd_clear(pgdp)
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+{
+	pte_t pte;
+	pte_val(pte) = physpage | pgprot_val(pgprot);
+	return pte;
+}
 
-extern void __bad_pmd(pmd_t *pmd);
-extern void __bad_pmd_kernel(pmd_t *pmd);
+extern __inline__ pte_t mk_pte(struct page *page, pgprot_t pgprot)
+{
+	pte_t pte;
+	pte_val(pte) = (PHYS_OFFSET + ((page - mem_map) << PAGE_SHIFT)) | pgprot_val(pgprot);
+	return pte;
+}
+
+#define page_pte_prot(page,prot)	mk_pte(page, prot)
+#define page_pte(page)		mk_pte(page, __pgprot(0))
+
+/* to find an entry in a page-table-directory */
+#define __pgd_offset(addr)	((addr) >> PGDIR_SHIFT)
+
+#define pgd_offset(mm, addr)	((mm)->pgd+__pgd_offset(addr))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir, addr)	((pmd_t *)(dir))
+
+/* Find an entry in the third-level page table.. */
+#define __pte_offset(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset(dir, addr)	((pte_t *)pmd_page(*(dir)) + __pte_offset(addr))
+
+/*
+ * Get the cache handling stuff now.
+ */
+#include <asm/proc/cache.h>
 
 /*
  * Page table cache stuff
  */
 #ifndef CONFIG_NO_PGT_CACHE
 
-#ifndef __SMP__
+#ifdef __SMP__
+#error Pgtable caches have to be per-CPU, so that no locking is needed.
+#endif	/* __SMP__ */
+
 extern struct pgtable_cache_struct {
 	unsigned long *pgd_cache;
 	unsigned long *pte_cache;
@@ -61,10 +161,6 @@
 #define pte_quicklist		(quicklists.pte_cache)
 #define pgtable_cache_size	(quicklists.pgtable_cache_sz)
 
-#else	/* __SMP__ */
-#error Pgtable caches have to be per-CPU, so that no locking is needed.
-#endif	/* __SMP__ */
-
 /* used for quicklists */
 #define __pgd_next(pgd) (((unsigned long *)pgd)[1])
 #define __pte_next(pte)	(((unsigned long *)pte)[0])
@@ -73,7 +169,7 @@
 {
 	unsigned long *ret;
 
-	if((ret = pgd_quicklist) != NULL) {
+	if ((ret = pgd_quicklist) != NULL) {
 		pgd_quicklist = (unsigned long *)__pgd_next(ret);
 		ret[1] = ret[2];
 		clean_cache_area(ret + 1, 4);
@@ -82,10 +178,18 @@
 	return (pgd_t *)ret;
 }
 
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+	__pgd_next(pgd) = (unsigned long) pgd_quicklist;
+	pgd_quicklist = (unsigned long *) pgd;
+	pgtable_cache_size++;
+}
+
 /* We don't use pmd cache, so this is a dummy routine */
-extern __inline__ pmd_t *get_pmd_fast(void)
+#define get_pmd_fast()		((pmd_t *)0)
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
 {
-	return (pmd_t *)0;
 }
 
 extern __inline__ pte_t *get_pte_fast(void)
@@ -101,17 +205,6 @@
 	return (pte_t *)ret;
 }
 
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
-{
-	__pgd_next(pgd) = (unsigned long) pgd_quicklist;
-	pgd_quicklist = (unsigned long *) pgd;
-	pgtable_cache_size++;
-}
-
-extern __inline__ void free_pmd_fast(pmd_t *pmd)
-{
-}
-
 extern __inline__ void free_pte_fast(pte_t *pte)
 {
 	__pte_next(pte) = (unsigned long) pte_quicklist;
@@ -121,9 +214,13 @@
 
 #else	/* CONFIG_NO_PGT_CACHE */
 
-#define get_pgd_fast()		(NULL)
-#define get_pmd_fast()		(NULL)
-#define get_pte_fast()		(NULL)
+#define pgd_quicklist		((unsigned long *)0)
+#define pmd_quicklist		((unsigned long *)0)
+#define pte_quicklist		((unsigned long *)0)
+
+#define get_pgd_fast()		((pgd_t *)0)
+#define get_pmd_fast()		((pmd_t *)0)
+#define get_pte_fast()		((pte_t *)0)
 
 #define free_pgd_fast(pgd)	free_pgd_slow(pgd)
 #define free_pmd_fast(pmd)	free_pmd_slow(pmd)
@@ -131,8 +228,93 @@
 
 #endif	/* CONFIG_NO_PGT_CACHE */
 
+extern pgd_t *get_pgd_slow(void);
+extern void free_pgd_slow(pgd_t *pgd);
+
+#define free_pmd_slow(pmd)	do { } while (0)
+
+extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long addr_preadjusted);
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long addr_preadjusted);
+extern void free_pte_slow(pte_t *pte);
+
 #include <asm/proc/pgtable.h>
 
+extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+	return pte;
+}
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any.
+ */
+#define pte_free_kernel(pte)	free_pte_fast(pte)
+#define pte_free(pte)		free_pte_fast(pte)
+
+#ifndef pte_alloc_kernel
+extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+{
+	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	if (pmd_none(*pmd)) {
+		pte_t *page = (pte_t *) get_pte_fast();
+
+		if (!page)
+			return get_pte_kernel_slow(pmd, address);
+		set_pmd(pmd, mk_kernel_pmd(page));
+		return page + address;
+	}
+	if (pmd_bad(*pmd)) {
+		__handle_bad_pmd_kernel(pmd);
+		return NULL;
+	}
+	return (pte_t *) pmd_page(*pmd) + address;
+}
+#endif
+
+extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
+{
+	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	if (pmd_none(*pmd)) {
+		pte_t *page = (pte_t *) get_pte_fast();
+
+		if (!page)
+			return get_pte_slow(pmd, address);
+		set_pmd(pmd, mk_user_pmd(page));
+		return page + address;
+	}
+	if (pmd_bad(*pmd)) {
+		__handle_bad_pmd(pmd);
+		return NULL;
+	}
+	return (pte_t *) pmd_page(*pmd) + address;
+}
+
+#define pmd_free_kernel		pmd_free
+#define pmd_free(pmd)		do { } while (0)
+
+#define pmd_alloc_kernel	pmd_alloc
+extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
+{
+	return (pmd_t *) pgd;
+}
+
+#define pgd_free(pgd)		free_pgd_fast(pgd)
+
+extern __inline__ pgd_t *pgd_alloc(void)
+{
+	pgd_t *pgd;
+
+	pgd = get_pgd_fast();
+	if (!pgd)
+		pgd = get_pgd_slow();
+
+	return pgd;
+}
+
+extern int do_check_pgt_cache(int, int);
+
 extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
 {
 	struct task_struct * p;
@@ -159,15 +341,16 @@
 
 #define update_mmu_cache(vma,address,pte)
 
-#define SWP_TYPE(entry)		(((entry) >> 2) & 0x7f)
-#define SWP_OFFSET(entry)	((entry) >> 9)
-#define SWP_ENTRY(type,offset)	(((type) << 2) | ((offset) << 9))
+/*
+ * We support up to 32GB of swap on 4k machines
+ */
+#define SWP_TYPE(entry)		(((pte_val(entry)) >> 2) & 0x7f)
+#define SWP_OFFSET(entry)	((pte_val(entry)) >> 9)
+#define SWP_ENTRY(type,offset)	__pte((((type) << 2) | ((offset) << 9)))
 
 #define module_map		vmalloc
 #define module_unmap		vfree
 
-extern int do_check_pgt_cache(int, int);
-
 /*
  * We rely on GCC optimising this code away for
  * architectures which it doesn't apply to.  Note
@@ -189,5 +372,7 @@
 #define kern_addr_valid(addr)	(!machine_is_riscpc() || __kern_valid_addr(addr))
 
 #define io_remap_page_range	remap_page_range
+
+#endif /* !__ASSEMBLY__ */
 
 #endif /* _ASMARM_PGTABLE_H */
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/proc-armo/cache.h linux/include/asm-arm/proc-armo/cache.h
--- v2.3.24/linux/include/asm-arm/proc-armo/cache.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/proc-armo/cache.h	Thu Oct 28 10:16:02 1999
@@ -46,18 +46,18 @@
 }
 
 extern __inline__ void
-memc_update_addr(struct mm_struct *mm, pte_t pte, unsigned long addr)
+memc_update_addr(struct mm_struct *mm, pte_t pte, unsigned long vaddr)
 {
-	cpu_memc_update_entry(mm->pgd, pte_val(pte), addr);
+	cpu_memc_update_entry(mm->pgd, pte_val(pte), vaddr);
 
 	if (mm == current->active_mm)
 		processor._set_pgd(mm->pgd);
 }
 
 extern __inline__ void
-memc_clear(struct mm_struct *mm, unsigned long phys_addr)
+memc_clear(struct mm_struct *mm, struct page *page)
 {
-	cpu_memc_update_entry(mm->pgd, phys_addr, 0);
+	cpu_memc_update_entry(mm->pgd, page_address(page), 0);
 
 	if (mm == current->active_mm)
 		processor._set_pgd(mm->pgd);
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h
--- v2.3.24/linux/include/asm-arm/proc-armo/pgtable.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/proc-armo/pgtable.h	Thu Oct 28 10:16:02 1999
@@ -9,31 +9,46 @@
 #define __ASM_PROC_PGTABLE_H
 
 /*
- * PMD_SHIFT determines the size of the area a second-level page table can map
+ * entries per page directory level: they are two-level, so
+ * we don't really have any PMD directory.
  */
-#define PMD_SHIFT       20
-#define PMD_SIZE        (1UL << PMD_SHIFT)
-#define PMD_MASK        (~(PMD_SIZE-1))
+#define PTRS_PER_PTE		32
+#define PTRS_PER_PMD		1
+#define PTRS_PER_PGD		32
 
 /*
- * PGDIR_SHIFT determines what a third-level page table entry can map
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
  */
-#define PGDIR_SHIFT     20
-#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK      (~(PGDIR_SIZE-1))
+#define VMALLOC_START	  0x01a00000
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END	  0x01c00000
 
-/*
- * entries per page directory level: the arm3 is one-level, so
- * we don't really have any PMD or PTE directory physically.
- */
-#define PTRS_PER_PTE    32
-#define PTRS_PER_PMD    1
-#define PTRS_PER_PGD    32
-#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
+#define _PAGE_TABLE     (0x01)
 
-#define VMALLOC_START	0x01a00000
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END	0x01c00000
+#define pmd_bad(pmd)		((pmd_val(pmd) & 0xfc000002))
+#define set_pmd(pmdp,pmd)	((*(pmdp)) = (pmd))
+
+extern __inline__ pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
+{
+	unsigned long pte_ptr = (unsigned long)ptep;
+	pmd_t pmd;
+
+	pmd_val(pmd) = __virt_to_phys(pte_ptr) | prot;
+
+	return pmd;
+}
+
+/* these are aliases for the above function */
+#define mk_user_pmd(ptep)	__mk_pmd(ptep, _PAGE_TABLE)
+#define mk_kernel_pmd(ptep)	__mk_pmd(ptep, _PAGE_TABLE)
+
+extern __inline__ unsigned long pmd_page(pmd_t pmd)
+{
+	return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE);
+}
+
+#define set_pte(pteptr, pteval)	((*(pteptr)) = (pteval))
 
 #define _PAGE_PRESENT	0x01
 #define _PAGE_READONLY	0x02
@@ -41,9 +56,6 @@
 #define _PAGE_OLD	0x08
 #define _PAGE_CLEAN	0x10
 
-#define _PAGE_TABLE     (_PAGE_PRESENT)
-#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_OLD | _PAGE_CLEAN)
-
 /*                               -- present --   -- !dirty --  --- !write ---   ---- !user --- */
 #define PAGE_NONE       __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY | _PAGE_NOT_USER)
 #define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_CLEAN                                  )
@@ -51,59 +63,19 @@
 #define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY                 )
 #define PAGE_KERNEL     __pgprot(_PAGE_PRESENT                                | _PAGE_NOT_USER)
 
-/*
- * The arm can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
- */
-#define __P000  PAGE_NONE
-#define __P001  PAGE_READONLY
-#define __P010  PAGE_COPY
-#define __P011  PAGE_COPY
-#define __P100  PAGE_READONLY
-#define __P101  PAGE_READONLY
-#define __P110  PAGE_COPY
-#define __P111  PAGE_COPY
-
-#define __S000  PAGE_NONE
-#define __S001  PAGE_READONLY
-#define __S010  PAGE_SHARED
-#define __S011  PAGE_SHARED
-#define __S100  PAGE_READONLY
-#define __S101  PAGE_READONLY
-#define __S110  PAGE_SHARED
-#define __S111  PAGE_SHARED
-
-extern unsigned long physical_start;
-extern unsigned long physical_end;
-
-#define pte_none(pte)		(!pte_val(pte))
-#define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
-#define pte_clear(ptep)		set_pte((ptep), __pte(0))
+#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_OLD | _PAGE_CLEAN)
 
-#define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_bad(pmd)		((pmd_val(pmd) & 0xfc000002))
-#define pmd_present(pmd)	(pmd_val(pmd) & _PAGE_PRESENT)
-#define pmd_clear(pmdp)		set_pmd(pmdp, __pmd(0))
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-#define pgd_none(pgd)		(0)
-#define pgd_bad(pgd)		(0)
-#define pgd_present(pgd)	(1)
-#define pgd_clear(pgdp)
 
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-extern inline int pte_read(pte_t pte)           { return !(pte_val(pte) & _PAGE_NOT_USER);     }
-extern inline int pte_write(pte_t pte)          { return !(pte_val(pte) & _PAGE_READONLY);     }
-extern inline int pte_exec(pte_t pte)           { return !(pte_val(pte) & _PAGE_NOT_USER);     }
-extern inline int pte_dirty(pte_t pte)          { return !(pte_val(pte) & _PAGE_CLEAN);        }
-extern inline int pte_young(pte_t pte)          { return !(pte_val(pte) & _PAGE_OLD);          }
+#define pte_present(pte)		(pte_val(pte) & _PAGE_PRESENT)
+#define pte_read(pte)			(!(pte_val(pte) & _PAGE_NOT_USER))
+#define pte_write(pte)			(!(pte_val(pte) & _PAGE_READONLY))
+#define pte_exec(pte)			(!(pte_val(pte) & _PAGE_NOT_USER))
+#define pte_dirty(pte)			(!(pte_val(pte) & _PAGE_CLEAN))
+#define pte_young(pte)			(!(pte_val(pte) & _PAGE_OLD))
 
 extern inline pte_t pte_nocache(pte_t pte)	{ return pte; }
 extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) |= _PAGE_READONLY;  return pte; }
@@ -118,155 +90,6 @@
 extern inline pte_t pte_mkdirty(pte_t pte)      { pte_val(pte) &= ~_PAGE_CLEAN;    return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)      { pte_val(pte) &= ~_PAGE_OLD;      return pte; }
 
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{
-	pte_t pte;
-	pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
-	return pte;
-}
-
-/* This takes a physical page address that is used by the remapping functions */
-extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{
-	pte_t pte;
-	pte_val(pte) = physpage + pgprot_val(pgprot);
-	return pte;
-}
-
-extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
-	pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
-	return pte;
-}
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-
-extern __inline__ unsigned long pte_page(pte_t pte)
-{
-	return __phys_to_virt(pte_val(pte) & PAGE_MASK);
-}
-
-extern __inline__ pmd_t mk_pmd(pte_t *ptep)
-{
-	pmd_t pmd;
-	pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_TABLE;
-	return pmd;
-}
-
-/* these are aliases for the above function */
-#define mk_user_pmd(ptep)   mk_pmd(ptep)
-#define mk_kernel_pmd(ptep) mk_pmd(ptep)
-
-#define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd))
-
-extern __inline__ unsigned long pmd_page(pmd_t pmd)
-{
-	return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE);
-}
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
-/* to find an entry in a page-table-directory */
-extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
-        return mm->pgd + (address >> PGDIR_SHIFT);
-}
-
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, address) ((pmd_t *)(dir))
-
-/* Find an entry in the third-level page table.. */
-extern __inline__ pte_t * pte_offset(pmd_t *dir, unsigned long address)
-{
-	return (pte_t *)pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
-}
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-
-extern void free_table(void *table);
-
-/* keep this as an inline so we get type checking */
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
-{
-	free_table(pgd);
-}
-
-/* keep this as an inline so we get type checking */
-extern __inline__ void free_pte_slow(pte_t *pte)
-{
-	free_table(pte);
-}
-
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
-{
-}
-
-#define pgd_free(pgd)           free_pgd_fast(pgd)
-
-extern __inline__ pgd_t *pgd_alloc(void)
-{
-	extern pgd_t *get_pgd_slow(void);
-	pgd_t *pgd;
-
-	pgd = get_pgd_fast();
-	if (!pgd)
-		pgd = get_pgd_slow();
-
-	return pgd;
-}
-
-#define pte_free_kernel(pte)    free_pte_fast(pte)
-#define pte_free(pte)           free_pte_fast(pte)
-
-extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
-{
-	extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
-
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-
-	if (pmd_none (*pmd)) {
-		pte_t *page = (pte_t *) get_pte_fast();
-
-		if (!page)
-			return get_pte_slow(pmd, address);
-		set_pmd(pmd, mk_pmd(page));
-		return page + address;
-	}
-	if (pmd_bad (*pmd)) {
-		__bad_pmd(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + address;
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern __inline__ void pmd_free(pmd_t *pmd)
-{
-}
-
-extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
-{
-	return (pmd_t *) pgd;
-}
-
-#define pmd_free_kernel         pmd_free
-#define pmd_alloc_kernel        pmd_alloc
 #define pte_alloc_kernel        pte_alloc
 
 #endif /* __ASM_PROC_PGTABLE_H */
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/proc-armv/cache.h linux/include/asm-arm/proc-armv/cache.h
--- v2.3.24/linux/include/asm-arm/proc-armv/cache.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/proc-armv/cache.h	Thu Oct 28 10:16:02 1999
@@ -54,8 +54,11 @@
  * This flushes back any buffered write data.  We have to clean the entries
  * in the cache for this page.  This does not invalidate either I or D caches.
  */
-#define flush_page_to_ram(_page)					\
-	cpu_flush_ram_page((_page) & PAGE_MASK);
+static __inline__ void flush_page_to_ram(struct page *page)
+{
+	unsigned long virt = page_address(page);
+	cpu_flush_ram_page(virt);
+}
 
 /*
  * TLB flushing:
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/proc-armv/pgtable.h linux/include/asm-arm/proc-armv/pgtable.h
--- v2.3.24/linux/include/asm-arm/proc-armv/pgtable.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/proc-armv/pgtable.h	Thu Oct 28 10:16:02 1999
@@ -14,27 +14,12 @@
 #include <asm/proc/domain.h>
 
 /*
- * PMD_SHIFT determines the size of the area a second-level page table can map
+ * entries per page directory level: they are two-level, so
+ * we don't really have any PMD directory.
  */
-#define PMD_SHIFT       20
-#define PMD_SIZE        (1UL << PMD_SHIFT)
-#define PMD_MASK        (~(PMD_SIZE-1))
-
-/*
- * PGDIR_SHIFT determines what a third-level page table entry can map
- */
-#define PGDIR_SHIFT     20
-#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK      (~(PGDIR_SIZE-1))
-
-/*
- * entries per page directory level: the sa110 is two-level, so
- * we don't really have any PMD directory physically.
- */
-#define PTRS_PER_PTE    256
-#define PTRS_PER_PMD    1
-#define PTRS_PER_PGD    4096
-#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
+#define PTRS_PER_PTE		256
+#define PTRS_PER_PMD		1
+#define PTRS_PER_PGD		4096
 
 /*
  * Just any arbitrary offset to the start of the vmalloc VM area: the
@@ -49,15 +34,6 @@
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
 
-extern unsigned long get_page_2k(int priority);
-extern void free_page_2k(unsigned long page);
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-
 /****************
 * PMD functions *
 ****************/
@@ -77,47 +53,15 @@
 #define _PAGE_USER_TABLE	(PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
 #define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
 
-#define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_clear(pmdp)		set_pmd(pmdp, __pmd(0))
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
-#define mk_user_pmd(ptep)	__mk_pmd(ptep, _PAGE_USER_TABLE)
-#define mk_kernel_pmd(ptep)	__mk_pmd(ptep, _PAGE_KERNEL_TABLE)
 #define set_pmd(pmdp,pmd)	cpu_set_pmd(pmdp,pmd)
 
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, address) ((pmd_t *)(dir))
-
-extern __inline__ int pmd_present(pmd_t pmd)
-{
-	return ((pmd_val(pmd) + 1) & 2);
-}
-
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
-{
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern __inline__ void pmd_free(pmd_t *pmd)
-{
-}
-
-extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
-{
-	return (pmd_t *) pgd;
-}
-
-#define pmd_free_kernel		pmd_free
-#define pmd_alloc_kernel	pmd_alloc
-
 extern __inline__ pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
 {
 	unsigned long pte_ptr = (unsigned long)ptep;
 	pmd_t pmd;
 
-	pte_ptr -= PTRS_PER_PTE * BYTES_PER_PTR;
+	pte_ptr -= PTRS_PER_PTE * sizeof(void *);
 
 	/*
 	 * The pmd must be loaded with the physical
@@ -128,13 +72,17 @@
 	return pmd;
 }
 
+/* these are aliases for the above function */
+#define mk_user_pmd(ptep)	__mk_pmd(ptep, _PAGE_USER_TABLE)
+#define mk_kernel_pmd(ptep)	__mk_pmd(ptep, _PAGE_KERNEL_TABLE)
+
 extern __inline__ unsigned long pmd_page(pmd_t pmd)
 {
 	unsigned long ptr;
 
-	ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * BYTES_PER_PTR - 1);
+	ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1);
 
-	ptr += PTRS_PER_PTE * BYTES_PER_PTR;
+	ptr += PTRS_PER_PTE * sizeof(void *);
 
 	return __phys_to_virt(ptr);
 }
@@ -153,48 +101,8 @@
 #define PTE_CACHEABLE		0x0008
 #define PTE_BUFFERABLE		0x0004
 
-#define pte_none(pte)		(!pte_val(pte))
-#define pte_clear(ptep)		set_pte(ptep, __pte(0))
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{
-	pte_t pte;
-	pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
-	return pte;
-}
-
-/* This takes a physical page address that is used by the remapping functions */
-extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{
-	pte_t pte;
-	pte_val(pte) = physpage + pgprot_val(pgprot);
-	return pte;
-}
-
 #define set_pte(ptep, pte)	cpu_set_pte(ptep,pte)
 
-extern __inline__ unsigned long pte_page(pte_t pte)
-{
-	return __phys_to_virt(pte_val(pte) & PAGE_MASK);
-}
-
-extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
-
-extern __inline__ void free_pte_slow(pte_t *pte)
-{
-	free_page_2k((unsigned long)(pte - PTRS_PER_PTE));
-}
-
-#define pte_free_kernel(pte)	free_pte_fast(pte)
-#define pte_free(pte)		free_pte_fast(pte)
-
-/*###############################################################################
- * New PageTableEntry stuff...
- */
 /* We now keep two sets of ptes - the physical and the linux version.
  * This gives us many advantages, and allows us greater flexibility.
  *
@@ -227,7 +135,6 @@
  */
 #define _L_PTE_DEFAULT	L_PTE_PRESENT | L_PTE_YOUNG
 #define _L_PTE_READ	L_PTE_USER | L_PTE_CACHEABLE
-#define _L_PTE_EXEC	_L_PTE_READ | L_PTE_EXEC
 
 #define PAGE_NONE       __pgprot(_L_PTE_DEFAULT)
 #define PAGE_COPY       __pgprot(_L_PTE_DEFAULT | _L_PTE_READ  | L_PTE_BUFFERABLE)
@@ -235,40 +142,14 @@
 #define PAGE_READONLY   __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
 #define PAGE_KERNEL     __pgprot(_L_PTE_DEFAULT | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_DIRTY | L_PTE_WRITE)
 
-#define _PAGE_CHG_MASK		(PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG)
+#define _PAGE_CHG_MASK	(PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG)
 
-/*
- * The table below defines the page protection levels that we insert into our
- * Linux page table version.  These get translated into the best that the
- * architecture can perform.  Note that on most ARM hardware:
- *  1) We cannot do execute protection
- *  2) If we could do execute protection, then read is implied
- *  3) write implies read permissions
- */
-#define __P000  PAGE_NONE
-#define __P001  PAGE_READONLY
-#define __P010  PAGE_COPY
-#define __P011  PAGE_COPY
-#define __P100  PAGE_READONLY
-#define __P101  PAGE_READONLY
-#define __P110  PAGE_COPY
-#define __P111  PAGE_COPY
-
-#define __S000  PAGE_NONE
-#define __S001  PAGE_READONLY
-#define __S010  PAGE_SHARED
-#define __S011  PAGE_SHARED
-#define __S100  PAGE_READONLY
-#define __S101  PAGE_READONLY
-#define __S110  PAGE_SHARED
-#define __S111  PAGE_SHARED
-
-#define pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT)
 
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
+#define pte_present(pte)		(pte_val(pte) & L_PTE_PRESENT)
 #define pte_read(pte)			(pte_val(pte) & L_PTE_USER)
 #define pte_write(pte)			(pte_val(pte) & L_PTE_WRITE)
 #define pte_exec(pte)			(pte_val(pte) & L_PTE_EXEC)
@@ -276,130 +157,18 @@
 #define pte_young(pte)			(pte_val(pte) & L_PTE_YOUNG)
 
 #define PTE_BIT_FUNC(fn,op)			\
-extern inline pte_t fn##(pte_t pte) { pte_val(pte) op##; return pte; }
-
-/*PTE_BIT_FUNC(pte_rdprotect, &= ~L_PTE_USER);*/
-PTE_BIT_FUNC(pte_wrprotect, &= ~L_PTE_WRITE);
-PTE_BIT_FUNC(pte_exprotect, &= ~L_PTE_EXEC);
-PTE_BIT_FUNC(pte_mkclean,   &= ~L_PTE_DIRTY);
-PTE_BIT_FUNC(pte_mkold,     &= ~L_PTE_YOUNG);
-/*PTE_BIT_FUNC(pte_mkread,    |= L_PTE_USER);*/
-PTE_BIT_FUNC(pte_mkwrite,   |= L_PTE_WRITE);
-PTE_BIT_FUNC(pte_mkexec,    |= L_PTE_EXEC);
-PTE_BIT_FUNC(pte_mkdirty,   |= L_PTE_DIRTY);
-PTE_BIT_FUNC(pte_mkyoung,   |= L_PTE_YOUNG);
-PTE_BIT_FUNC(pte_nocache,   &= ~L_PTE_CACHEABLE);
+extern inline pte_t pte_##fn##(pte_t pte) { pte_val(pte) op##; return pte; }
 
-extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
-	pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
-	return pte;
-}
-
-/* Find an entry in the third-level page table.. */
-extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
-{
-	return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
-}
-
-extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
-{
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-	if (pmd_none(*pmd)) {
-		pte_t *page = (pte_t *) get_pte_fast();
-
-		if (!page)
-			return get_pte_kernel_slow(pmd, address);
-		set_pmd(pmd, mk_kernel_pmd(page));
-		return page + address;
-	}
-	if (pmd_bad(*pmd)) {
-		__bad_pmd_kernel(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + address;
-}
-
-extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
-{
-	extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
-
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-
-	if (pmd_none(*pmd)) {
-		pte_t *page = (pte_t *) get_pte_fast();
-
-		if (!page)
-			return get_pte_slow(pmd, address);
-		set_pmd(pmd, mk_user_pmd(page));
-		return page + address;
-	}
-	if (pmd_bad(*pmd)) {
-		__bad_pmd(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + address;
-}
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-#define pgd_none(pgd)		(0)
-#define pgd_bad(pgd)		(0)
-#define pgd_present(pgd)	(1)
-#define pgd_clear(pgdp)
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
-/* to find an entry in a page-table-directory */
-extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
-	return mm->pgd + (address >> PGDIR_SHIFT);
-}
-
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
-{
-	do {
-		if (pgd) { /* can pgd be NULL? */
-			pmd_t *pmd;
-			pte_t *pte;
-
-			/* pgd is never none and bad - it is
-			 * detected in the pmd macros.
-			 */
-			pmd = pmd_offset(pgd, 0);
-			if (pmd_none(*pmd))
-				break;
-			if (pmd_bad(*pmd)) {
-				printk("free_pgd_slow: bad directory entry %08lx\n", pmd_val(*pmd));
-				pmd_clear(pmd);
-				break;
-			}
-
-			pte = pte_offset(pmd, 0);
-			pmd_clear(pmd);
-			pte_free(pte);
-			pmd_free(pmd);
-		}
-	} while (0);
-	free_pages((unsigned long) pgd, 2);
-}
-
-#define pgd_free(pgd)		free_pgd_fast(pgd)
-
-extern __inline__ pgd_t *pgd_alloc(void)
-{
-	extern pgd_t *get_pgd_slow(void);
-	pgd_t *pgd;
-
-	pgd = get_pgd_fast();
-	if (!pgd)
-		pgd = get_pgd_slow();
-
-	return pgd;
-}
+/*PTE_BIT_FUNC(rdprotect, &= ~L_PTE_USER);*/
+/*PTE_BIT_FUNC(mkread,    |= L_PTE_USER);*/
+PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE);
+PTE_BIT_FUNC(mkwrite,   |= L_PTE_WRITE);
+PTE_BIT_FUNC(exprotect, &= ~L_PTE_EXEC);
+PTE_BIT_FUNC(mkexec,    |= L_PTE_EXEC);
+PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
+PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
+PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
+PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
+PTE_BIT_FUNC(nocache,   &= ~L_PTE_CACHEABLE);
 
 #endif /* __ASM_PROC_PGTABLE_H */
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/setup.h linux/include/asm-arm/setup.h
--- v2.3.24/linux/include/asm-arm/setup.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/setup.h	Thu Oct 28 10:16:02 1999
@@ -16,6 +16,8 @@
  *  - when adding fields, don't rely on the address until
  *    a patch from me has been released
  *  - unused fields should be zero (for future expansion)
+ *  - this structure is relatively short-lived - only
+ *    guaranteed to contain useful data in setup_arch()
  */
 #define COMMAND_LINE_SIZE 1024
 
@@ -59,5 +61,21 @@
     } u2;
     char commandline[COMMAND_LINE_SIZE];
 };
+
+/*
+ * Memory map description
+ */
+#define NR_BANKS 4
+
+struct meminfo {
+	int nr_banks;
+	unsigned long end;
+	struct {
+		unsigned long start;
+		unsigned long size;
+	} bank[NR_BANKS];
+};
+
+extern struct meminfo meminfo;
 
 #endif
diff -u --recursive --new-file v2.3.24/linux/include/asm-arm/termios.h linux/include/asm-arm/termios.h
--- v2.3.24/linux/include/asm-arm/termios.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-arm/termios.h	Wed Oct 27 17:04:51 1999
@@ -63,6 +63,7 @@
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v2.3.24/linux/include/asm-i386/io.h	Wed Oct 27 16:34:12 1999
+++ linux/include/asm-i386/io.h	Mon Nov  1 13:38:39 1999
@@ -205,11 +205,13 @@
 #define isa_memcpy_fromio(a,b,c)	memcpy_fromio((a),__ISA_IO_base + (b),(c))
 #define isa_memcpy_toio(a,b,c)		memcpy_toio(__ISA_IO_base + (a),(b),(c))
 
+
 /*
  * Again, i386 does not require mem IO specific function.
  */
 
-#define eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),__io_virt(b),(c),(d))
+#define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),__io_virt(b),(c),(d))
+#define isa_eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d))
 
 static inline int check_signature(unsigned long io_addr,
 	const unsigned char *signature, int length)
diff -u --recursive --new-file v2.3.24/linux/include/asm-i386/mmx.h linux/include/asm-i386/mmx.h
--- v2.3.24/linux/include/asm-i386/mmx.h	Mon Oct 11 15:38:15 1999
+++ linux/include/asm-i386/mmx.h	Fri Oct 29 10:53:32 1999
@@ -8,7 +8,7 @@
 #include <linux/types.h>
  
 extern void *_mmx_memcpy(void *to, const void *from, size_t size);
-extern void mmx_clear_page(long page);
-extern void mmx_copy_page(long to, long from);
+extern void mmx_clear_page(void *page);
+extern void mmx_copy_page(void *to, void *from);
 
 #endif
diff -u --recursive --new-file v2.3.24/linux/include/asm-i386/page.h linux/include/asm-i386/page.h
--- v2.3.24/linux/include/asm-i386/page.h	Wed Oct 27 16:34:12 1999
+++ linux/include/asm-i386/page.h	Fri Oct 29 13:41:57 1999
@@ -50,9 +50,6 @@
 #define pgd_val(x)	((x).pgd)
 #define pgprot_val(x)	((x).pgprot)
 
-#define __pte(x)	((pte_t) { (x) } )
-#define __pmd(x)	((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
 #endif /* !__ASSEMBLY__ */
diff -u --recursive --new-file v2.3.24/linux/include/asm-i386/pgtable-2level.h linux/include/asm-i386/pgtable-2level.h
--- v2.3.24/linux/include/asm-i386/pgtable-2level.h	Wed Oct 27 16:34:12 1999
+++ linux/include/asm-i386/pgtable-2level.h	Thu Oct 28 15:35:00 1999
@@ -57,6 +57,4 @@
 	return (pmd_t *) pgd;
 }
 
-#define SWP_ENTRY(type,offset) __pte((((type) << 1) | ((offset) << 8)))
-
 #endif /* _I386_PGTABLE_2LEVEL_H */
diff -u --recursive --new-file v2.3.24/linux/include/asm-i386/pgtable-3level.h linux/include/asm-i386/pgtable-3level.h
--- v2.3.24/linux/include/asm-i386/pgtable-3level.h	Fri Oct 22 13:21:54 1999
+++ linux/include/asm-i386/pgtable-3level.h	Thu Oct 28 15:35:00 1999
@@ -121,11 +121,4 @@
 	return (pmd_t *)pgd_page(*pgd) + address;
 }
 
-/*
- * Subtle. offset can overflow 32 bits and that's a feature - we can do
- * up to 16 TB swap on PAE. (Not that anyone should need that much
- * swapspace, but who knows?)
- */
-#define SWP_ENTRY(type,offset) __pte((((type) << 1) | ((offset) << 8ULL)))
-
 #endif /* _I386_PGTABLE_3LEVEL_H */
diff -u --recursive --new-file v2.3.24/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v2.3.24/linux/include/asm-i386/pgtable.h	Fri Oct 22 13:21:54 1999
+++ linux/include/asm-i386/pgtable.h	Mon Nov  1 13:38:16 1999
@@ -495,8 +495,12 @@
 {
 }
 
-#define SWP_TYPE(entry) (((pte_val(entry)) >> 1) & 0x3f)
-#define SWP_OFFSET(entry) ((pte_val(entry)) >> 8)
+/* Encode and de-code a swap entry */
+#define SWP_TYPE(x)			(((x).val >> 1) & 0x3f)
+#define SWP_OFFSET(x)			((x).val >> 8)
+#define SWP_ENTRY(type, offset)		((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+#define pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x)		((pte_t) { (x).val })
 
 #define module_map      vmalloc
 #define module_unmap    vfree
diff -u --recursive --new-file v2.3.24/linux/include/asm-i386/string.h linux/include/asm-i386/string.h
--- v2.3.24/linux/include/asm-i386/string.h	Mon Oct 11 15:38:15 1999
+++ linux/include/asm-i386/string.h	Mon Nov  1 13:38:19 1999
@@ -303,6 +303,7 @@
 #include <asm/system.h>
 #include <asm/ptrace.h>
 #include <linux/smp.h>
+#include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <asm/mmx.h>
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v2.3.24/linux/include/asm-i386/unistd.h	Mon Oct  4 15:49:30 1999
+++ linux/include/asm-i386/unistd.h	Fri Oct 29 13:19:49 1999
@@ -80,7 +80,7 @@
 #define __NR_sigpending		 73
 #define __NR_sethostname	 74
 #define __NR_setrlimit		 75
-#define __NR_getrlimit		 76
+#define __NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
 #define __NR_getrusage		 77
 #define __NR_gettimeofday	 78
 #define __NR_settimeofday	 79
@@ -195,6 +195,7 @@
 #define __NR_getpmsg		188	/* some people actually want streams */
 #define __NR_putpmsg		189	/* some people actually want streams */
 #define __NR_vfork		190
+#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-m68k/termios.h linux/include/asm-m68k/termios.h
--- v2.3.24/linux/include/asm-m68k/termios.h	Wed Mar 24 11:46:00 1999
+++ linux/include/asm-m68k/termios.h	Wed Oct 27 17:04:51 1999
@@ -61,6 +61,7 @@
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v2.3.24/linux/include/asm-mips/termios.h	Wed Mar 24 11:45:59 1999
+++ linux/include/asm-mips/termios.h	Wed Oct 27 17:04:51 1999
@@ -99,6 +99,7 @@
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-ppc/termios.h linux/include/asm-ppc/termios.h
--- v2.3.24/linux/include/asm-ppc/termios.h	Wed Mar 24 11:46:00 1999
+++ linux/include/asm-ppc/termios.h	Wed Oct 27 17:04:51 1999
@@ -185,6 +185,7 @@
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-sh/termios.h linux/include/asm-sh/termios.h
--- v2.3.24/linux/include/asm-sh/termios.h	Fri Oct 22 13:21:55 1999
+++ linux/include/asm-sh/termios.h	Wed Oct 27 17:04:51 1999
@@ -53,6 +53,7 @@
 #define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h
--- v2.3.24/linux/include/asm-sparc/termios.h	Thu Mar 25 09:23:34 1999
+++ linux/include/asm-sparc/termios.h	Wed Oct 27 17:04:51 1999
@@ -69,6 +69,7 @@
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.24/linux/include/asm-sparc64/termios.h linux/include/asm-sparc64/termios.h
--- v2.3.24/linux/include/asm-sparc64/termios.h	Thu Mar 25 09:23:34 1999
+++ linux/include/asm-sparc64/termios.h	Wed Oct 27 17:04:51 1999
@@ -69,6 +69,7 @@
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.24/linux/include/linux/acpi.h linux/include/linux/acpi.h
--- v2.3.24/linux/include/linux/acpi.h	Wed Oct 27 16:34:12 1999
+++ linux/include/linux/acpi.h	Mon Nov  1 13:28:43 1999
@@ -53,6 +53,9 @@
 #define ACPI_SLP_TYP2 0x1000
 #define ACPI_SLP_EN   0x2000
 
+#define ACPI_SLP_TYP_MASK  0x1c00
+#define ACPI_SLP_TYP_SHIFT 10
+
 /* PM_TMR masks */
 #define ACPI_TMR_MASK	0x00ffffff
 #define ACPI_TMR_HZ	3580000 /* 3.58 MHz */
@@ -82,6 +85,9 @@
 #define ACPI_TMR_VAL_EXT  0x00000100
 #define ACPI_DCK_CAP	  0x00000200
 
+/* FACS flags */
+#define ACPI_S4BIOS	  0x00000001
+
 struct acpi_rsdp {
 	__u32 signature[2];
 	__u8 checksum;
@@ -145,6 +151,15 @@
 	__u32 flags;
 };
 
+struct acpi_facs {
+	__u32 signature;
+	__u32 length;
+	__u32 hw_signature;
+	__u32 fw_wake_vector;
+	__u32 global_lock;
+	__u32 flags;
+};
+
 /*
  * Sysctl declarations
  */
@@ -166,8 +181,12 @@
 	ACPI_P_LVL3,
 	ACPI_P_LVL2_LAT,
 	ACPI_P_LVL3_LAT,
+	ACPI_S5_SLP_TYP
 };
 
+#define ACPI_P_LVL_DISABLED	0x80
+#define ACPI_SLP_TYP_DISABLED	(~0UL)
+
 /*
  * PIIX4-specific ACPI info (for systems with PIIX4 but no ACPI tables)
  */
@@ -208,6 +227,7 @@
 #ifdef __KERNEL__
 
 extern void (*acpi_idle)(void);
+extern void (*acpi_power_off)(void);
 
 #endif
 
diff -u --recursive --new-file v2.3.24/linux/include/linux/apm_bios.h linux/include/linux/apm_bios.h
--- v2.3.24/linux/include/linux/apm_bios.h	Fri Aug  6 11:09:40 1999
+++ linux/include/linux/apm_bios.h	Thu Oct 28 10:16:02 1999
@@ -3,7 +3,7 @@
 
 /*
  * Include file for the interface to an APM BIOS
- * Copyright 1994-1998 Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
+ * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
  *
  * 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
diff -u --recursive --new-file v2.3.24/linux/include/linux/bfs_fs.h linux/include/linux/bfs_fs.h
--- v2.3.24/linux/include/linux/bfs_fs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/bfs_fs.h	Thu Oct 28 14:45:16 1999
@@ -0,0 +1,91 @@
+/*
+ *	include/linux/bfs_fs.h - BFS data structures on disk.
+ *	Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ */
+
+#ifndef _LINUX_BFS_FS_H
+#define _LINUX_BFS_FS_H
+
+#define BFS_BSIZE_BITS		9
+#define BFS_BSIZE		(1<<BFS_BSIZE_BITS)
+
+#define BFS_MAGIC		0x1BADFACE
+#define BFS_ROOT_INO		2
+#define BFS_INODES_PER_BLOCK	8
+
+/* SVR4 vnode type values (bfs_inode->i_vtype) */
+#define BFS_VDIR		2
+#define BFS_VREG		1
+
+/* BFS inode layout on disk */
+struct bfs_inode {
+	__u16 i_ino;
+	__u16 i_unused;
+	__u32 i_sblock;
+	__u32 i_eblock;
+	__u32 i_eoffset;
+	__u32 i_vtype;
+	__u32 i_mode;
+	__s32 i_uid;
+	__s32 i_gid;
+	__u32 i_nlink;
+	__u32 i_atime;
+	__u32 i_mtime;
+	__u32 i_ctime;
+	__u8  i_padding[16];
+};
+
+#define BFS_NAMELEN		14	
+#define BFS_DIRENT_SIZE		16
+#define BFS_DIRS_PER_BLOCK	32
+
+struct bfs_dirent {
+	__u16 ino;
+	char name[BFS_NAMELEN];
+};
+
+/* BFS superblock layout on disk */
+struct bfs_super_block {
+	__u32 s_magic;
+	__u32 s_start;
+	__u32 s_end;
+	__s32 s_from;
+	__s32 s_to;
+	__s32 s_bfrom;
+	__s32 s_bto;
+	char  s_fsname[6];
+	char  s_volume[6];
+	__u8  s_padding[472];
+};
+
+#define BFS_NZFILESIZE(ip) \
+        (((ip)->i_eoffset + 1) - (ip)->i_sblock * BFS_BSIZE)
+
+#define BFS_FILESIZE(ip) \
+        ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip))
+
+#define BFS_FILEBLOCKS(ip) \
+        ((ip)->i_sblock == 0 ? 0 : ((ip)->i_eblock + 1) - (ip)->i_sblock)
+
+#define BFS_OFF2INO(offset) \
+        ((((offset) - BFS_BSIZE) / sizeof(struct bfs_inode)) + BFS_ROOT_INO)
+
+#define BFS_INO2OFF(ino) \
+	((__u32)(((ino) - BFS_ROOT_INO) * sizeof(struct bfs_inode)) + BFS_BSIZE)
+
+#define BFS_UNCLEAN(bfs_sb, sb)	\
+	((bfs_sb->s_from != -1) && (bfs_sb->s_to != -1) && !(sb->s_flags & MS_RDONLY))
+
+#ifdef __KERNEL__
+
+/* inode.c */
+extern int init_bfs_fs(void);
+
+/* file.c */
+extern struct inode_operations bfs_file_inops;
+
+/* dir.c */
+extern struct inode_operations bfs_dir_inops;
+
+#endif /* __KERNEL__ */
+#endif	/* _LINUX_BFS_FS_H */
diff -u --recursive --new-file v2.3.24/linux/include/linux/bfs_fs_i.h linux/include/linux/bfs_fs_i.h
--- v2.3.24/linux/include/linux/bfs_fs_i.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/bfs_fs_i.h	Thu Oct 28 14:45:16 1999
@@ -0,0 +1,18 @@
+/*
+ *	include/linux/bfs_fs_i.h
+ *	Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ */
+
+#ifndef _LINUX_BFS_FS_I
+#define _LINUX_BFS_FS_I
+
+/*
+ * BFS file system in-core inode info
+ */
+struct bfs_inode_info {
+	__u32	i_dsk_ino;	/* inode number from the disk, can be 0 */
+	__u32	i_sblock;
+	__u32	i_eblock;
+};
+
+#endif	/* _LINUX_BFS_FS_I */
diff -u --recursive --new-file v2.3.24/linux/include/linux/bfs_fs_sb.h linux/include/linux/bfs_fs_sb.h
--- v2.3.24/linux/include/linux/bfs_fs_sb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/bfs_fs_sb.h	Fri Oct 29 11:05:08 1999
@@ -0,0 +1,25 @@
+/*
+ *	include/linux/bfs_fs_sb.h
+ *	Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ */
+
+#ifndef _LINUX_BFS_FS_SB
+#define _LINUX_BFS_FS_SB
+
+/*
+ * BFS file system in-core superblock info
+ */
+struct bfs_sb_info {
+	__u32 si_blocks;
+	__u32 si_freeb;
+	__u32 si_freei;
+	__u32 si_lf_ioff;
+	__u32 si_lf_sblk;
+	__u32 si_lf_eblk;
+	__u32 si_lasti;
+	__u8 *si_imap;
+	struct buffer_head * si_sbh;		/* buffer header w/superblock */
+	struct bfs_super_block * si_bfs_sb;	/* superblock in si_sbh->b_data */
+};
+
+#endif	/* _LINUX_BFS_FS_SB */
diff -u --recursive --new-file v2.3.24/linux/include/linux/cycx_drv.h linux/include/linux/cycx_drv.h
--- v2.3.24/linux/include/linux/cycx_drv.h	Thu Aug 12 09:46:13 1999
+++ linux/include/linux/cycx_drv.h	Sun Oct 31 00:19:22 1999
@@ -11,13 +11,14 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
+* 1999/10/23	acme		cycxhw_t cleanup
 * 1999/01/03	acme		more judicious use of data types...
 *				uclong, ucchar, etc deleted, the u8, u16, u32
 *				types are the portable way to go.
 * 1999/01/03	acme		judicious use of data types... u16, u32, etc
-* Dec 26, 1998	Arnaldo 	FIXED_BUFFERS, CONF_OFFSET,
+* 1998/12/26	acme	 	FIXED_BUFFERS, CONF_OFFSET,
 *                               removal of cy_read{bwl}
-* Aug 08, 1998	Arnaldo 	Initial version.
+* 1998/08/08	acme	 	Initial version.
 */
 #ifndef	_CYCX_DRV_H
 #define	_CYCX_DRV_H
@@ -43,22 +44,19 @@
 /* Adapter hardware configuration. Pointer to this structure is passed to all
  * APIs.  */
 typedef struct cycxhw {
-	u32 type;		/* adapter type */
 	u32 fwid;		/* firmware ID */
 	int irq;		/* interrupt request level */
 	u32 dpmbase;		/* dual-port memory base */
 	u32 dpmsize;		/* dual-port memory size */
-	u32 pclk;		/* CPU clock rate, kHz */
-	u32 memory;		/* memory size */
 	u32 reserved[5];
 } cycxhw_t;
 
 /* Function Prototypes */
 extern int cycx_setup (cycxhw_t *hw, void *sfm, u32 len);
-extern int cycx_down (cycxhw_t *hw);
-extern int cycx_inten (cycxhw_t *hw);
-extern int cycx_intr (cycxhw_t *hw);
 extern int cycx_peek (cycxhw_t *hw, u32 addr, void *buf, u32 len);
 extern int cycx_poke (cycxhw_t *hw, u32 addr, void *buf, u32 len);
 extern int cycx_exec (u32 addr);
+
+extern void cycx_inten (cycxhw_t *hw);
+extern void cycx_intr (cycxhw_t *hw);
 #endif	/* _CYCX_DRV_H */
diff -u --recursive --new-file v2.3.24/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.3.24/linux/include/linux/fb.h	Mon Oct 11 15:38:15 1999
+++ linux/include/linux/fb.h	Sun Oct 31 15:01:51 1999
@@ -83,6 +83,7 @@
 #define FB_ACCEL_NV5		29	/* nVidia RIVA TNT2		*/
 #define FB_ACCEL_CT_6555x	30	/* C&T 6555x			*/
 #define FB_ACCEL_3DFX_BANSHEE	31	/* 3Dfx Banshee			*/
+#define FB_ACCEL_ATI_RAGE128	32	/* ATI Rage128 family		*/
 
 struct fb_fix_screeninfo {
 	char id[16];			/* identification string eg "TT Builtin" */
diff -u --recursive --new-file v2.3.24/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.24/linux/include/linux/fs.h	Wed Oct 27 16:34:12 1999
+++ linux/include/linux/fs.h	Mon Nov  1 13:38:15 1999
@@ -268,6 +268,7 @@
 #include <linux/hfs_fs_i.h>
 #include <linux/adfs_fs_i.h>
 #include <linux/qnx4_fs_i.h>
+#include <linux/bfs_fs_i.h>
 #include <linux/udf_fs_i.h>
 #include <linux/ncp_fs_i.h>
 
@@ -391,6 +392,7 @@
 		struct hfs_inode_info		hfs_i;
 		struct adfs_inode_info		adfs_i;
 		struct qnx4_inode_info		qnx4_i;
+		struct bfs_inode_info		bfs_i;
 		struct udf_inode_info		udf_i;
 		struct ncp_inode_info		ncpfs_i;
 		struct socket			socket_i;
@@ -522,6 +524,7 @@
 #include <linux/hfs_fs_sb.h>
 #include <linux/adfs_fs_sb.h>
 #include <linux/qnx4_fs_sb.h>
+#include <linux/bfs_fs_sb.h>
 #include <linux/udf_fs_sb.h>
 #include <linux/ncp_fs_sb.h>
 
@@ -568,6 +571,7 @@
 		struct hfs_sb_info	hfs_sb;
 		struct adfs_sb_info	adfs_sb;
 		struct qnx4_sb_info	qnx4_sb;
+		struct bfs_sb_info	bfs_sb;
 		struct udf_sb_info	udf_sb;
 		struct ncp_sb_info	ncpfs_sb;
 		void			*generic_sbp;
diff -u --recursive --new-file v2.3.24/linux/include/linux/if_arp.h linux/include/linux/if_arp.h
--- v2.3.24/linux/include/linux/if_arp.h	Tue Sep  7 12:14:07 1999
+++ linux/include/linux/if_arp.h	Mon Nov  1 13:39:28 1999
@@ -13,6 +13,7 @@
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Florian La Roche,
  *		Jonathan Layes <layes@loran.com>
+ *		Arnaldo Carvalho de Melo <acme@conectiva.com.br> ARPHRD_HWX25
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -47,6 +48,7 @@
 #define ARPHRD_ADAPT	264
 #define ARPHRD_ROSE	270
 #define ARPHRD_X25	271		/* CCITT X.25			*/
+#define ARPHRD_HWX25	272		/* Boards with X.25 in firmware	*/
 #define ARPHRD_PPP	512
 #define ARPHRD_HDLC	513		/* (Cisco) HDLC 		*/
 #define ARPHRD_LAPB	516		/* LAPB				*/
diff -u --recursive --new-file v2.3.24/linux/include/linux/ipc.h linux/include/linux/ipc.h
--- v2.3.24/linux/include/linux/ipc.h	Sun Dec 27 22:18:28 1998
+++ linux/include/linux/ipc.h	Thu Oct 28 10:43:26 1999
@@ -38,7 +38,7 @@
 
 #ifdef __KERNEL__
 
-/* special shmsegs[id], msgque[id] or semary[id]  values */
+/* special shmsegs[id]  values */
 #define IPC_UNUSED	((void *) -1)
 #define IPC_NOID	((void *) -2)		/* being allocated/destroyed */
 
diff -u --recursive --new-file v2.3.24/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.24/linux/include/linux/mm.h	Wed Oct 27 16:34:12 1999
+++ linux/include/linux/mm.h	Mon Nov  1 13:38:21 1999
@@ -56,7 +56,7 @@
 	struct vm_area_struct **vm_pprev_share;
 
 	struct vm_operations_struct * vm_ops;
-	unsigned long vm_offset;
+	unsigned long vm_pgoff;		/* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */
 	struct file * vm_file;
 	void * vm_private_data;		/* was vm_pte (shared mem) */
 };
@@ -110,6 +110,15 @@
 };
 
 /*
+ * A swap entry has to fit into a "unsigned long", as
+ * the entry is hidden in the "index" field of the
+ * swapper address space.
+ */
+typedef struct {
+	unsigned long val;
+} swp_entry_t;
+
+/*
  * Try to keep the most commonly accessed fields in single cache lines
  * here (16 bytes or greater).  This ordering should be particularly
  * beneficial on 32-bit processors.
@@ -121,7 +130,7 @@
 	/* these must be first (free area handling) */
 	struct list_head list;
 	struct address_space *mapping;
-	unsigned long offset;
+	unsigned long index;
 	struct page *next_hash;
 	atomic_t count;
 	unsigned long flags;	/* atomic flags, some possibly updated asynchronously */
@@ -325,7 +334,7 @@
 extern void show_mem(void);
 extern void oom(struct task_struct * tsk);
 extern void si_meminfo(struct sysinfo * val);
-extern void swapin_readahead(pte_t);
+extern void swapin_readahead(swp_entry_t);
 
 /* mmap.c */
 extern void vma_init(void);
@@ -389,15 +398,15 @@
 	unsigned long grow;
 
 	address &= PAGE_MASK;
-	grow = vma->vm_start - address;
+	grow = (vma->vm_start - address) >> PAGE_SHIFT;
 	if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
-	    (vma->vm_mm->total_vm << PAGE_SHIFT) + grow > current->rlim[RLIMIT_AS].rlim_cur)
+	    ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)
 		return -ENOMEM;
 	vma->vm_start = address;
-	vma->vm_offset -= grow;
-	vma->vm_mm->total_vm += grow >> PAGE_SHIFT;
+	vma->vm_pgoff -= grow;
+	vma->vm_mm->total_vm += grow;
 	if (vma->vm_flags & VM_LOCKED)
-		vma->vm_mm->locked_vm += grow >> PAGE_SHIFT;
+		vma->vm_mm->locked_vm += grow;
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.24/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h
--- v2.3.24/linux/include/linux/ncp_fs.h	Sat Oct  9 11:47:50 1999
+++ linux/include/linux/ncp_fs.h	Mon Nov  1 13:40:19 1999
@@ -136,18 +136,28 @@
 
 #include <linux/config.h>
 
+/* undef because public define in umsdos_fs.h (ncp_fs.h isn't public) */
+#undef PRINTK
+/* define because it is easy to change PRINTK to {*}PRINTK */
+#define PRINTK(format, args...) printk(KERN_DEBUG format , ## args)
+
 #undef NCPFS_PARANOIA
+#ifdef NCPFS_PARANOIA
+#define PPRINTK(format, args...) PRINTK(format , ## args)
+#else
+#define PPRINTK(format, args...)
+#endif
+
 #ifndef DEBUG_NCP
 #define DEBUG_NCP 0
 #endif
 #if DEBUG_NCP > 0
-#define DPRINTK(format, args...) printk(format , ## args)
+#define DPRINTK(format, args...) PRINTK(format , ## args)
 #else
 #define DPRINTK(format, args...)
 #endif
-
 #if DEBUG_NCP > 1
-#define DDPRINTK(format, args...) printk(format , ## args)
+#define DDPRINTK(format, args...) PRINTK(format , ## args)
 #else
 #define DDPRINTK(format, args...)
 #endif
diff -u --recursive --new-file v2.3.24/linux/include/linux/nvram.h linux/include/linux/nvram.h
--- v2.3.24/linux/include/linux/nvram.h	Thu Jul 31 13:09:18 1997
+++ linux/include/linux/nvram.h	Fri Oct 29 10:58:00 1999
@@ -12,7 +12,6 @@
 extern void nvram_write_byte( unsigned char c, int i );
 extern int nvram_check_checksum( void );
 extern void nvram_set_checksum( void );
-extern int nvram_init( void );
 #endif
 
 #endif  /* _LINUX_NVRAM_H */
diff -u --recursive --new-file v2.3.24/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.3.24/linux/include/linux/pagemap.h	Wed Oct 27 16:34:12 1999
+++ linux/include/linux/pagemap.h	Mon Nov  1 13:38:29 1999
@@ -14,15 +14,6 @@
 #include <linux/highmem.h>
 #include <linux/list.h>
 
-extern inline pte_t get_pagecache_pte(struct page *page)
-{
-	/*
-	 * the pagecache is still machineword sized. The rest of the VM
-	 * can deal with arbitrary sized ptes.
-	 */
-        return __pte(page->offset);
-}
-
 /*
  * The page cache can done in larger chunks than
  * one page, because it allows for more efficient
@@ -57,43 +48,42 @@
 /*
  * We use a power-of-two hash table to avoid a modulus,
  * and get a reasonable hash by knowing roughly how the
- * inode pointer and offsets are distributed (ie, we
+ * inode pointer and indexes are distributed (ie, we
  * roughly know which bits are "significant")
  *
  * For the time being it will work for struct address_space too (most of
  * them sitting inside the inodes). We might want to change it later.
  */
-extern inline unsigned long _page_hashfn(struct address_space * mapping, unsigned long offset)
+extern inline unsigned long _page_hashfn(struct address_space * mapping, unsigned long index)
 {
 #define i (((unsigned long) mapping)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))
-#define o (offset >> PAGE_SHIFT)
 #define s(x) ((x)+((x)>>PAGE_HASH_BITS))
-	return s(i+o) & (PAGE_HASH_SIZE-1);
+	return s(i+index) & (PAGE_HASH_SIZE-1);
 #undef i
 #undef o
 #undef s
 }
 
-#define page_hash(mapping,offset) (page_hash_table+_page_hashfn(mapping,offset))
+#define page_hash(mapping,index) (page_hash_table+_page_hashfn(mapping,index))
 
 extern struct page * __find_get_page (struct address_space *mapping,
-				unsigned long offset, struct page **hash);
-#define find_get_page(mapping, offset) \
-		__find_get_page(mapping, offset, page_hash(mapping, offset))
+				unsigned long index, struct page **hash);
+#define find_get_page(mapping, index) \
+		__find_get_page(mapping, index, page_hash(mapping, index))
 extern struct page * __find_lock_page (struct address_space * mapping,
-				unsigned long offset, struct page **hash);
+				unsigned long index, struct page **hash);
 extern void lock_page(struct page *page);
-#define find_lock_page(mapping, offset) \
-		__find_lock_page(mapping, offset, page_hash(mapping, offset))
+#define find_lock_page(mapping, index) \
+		__find_lock_page(mapping, index, page_hash(mapping, index))
 
 extern void __add_page_to_hash_queue(struct page * page, struct page **p);
 
-extern void add_to_page_cache(struct page * page, struct address_space *mapping, unsigned long offset);
-extern int add_to_page_cache_unique(struct page * page, struct address_space *mapping, unsigned long offset, struct page **hash);
+extern void add_to_page_cache(struct page * page, struct address_space *mapping, unsigned long index);
+extern int add_to_page_cache_unique(struct page * page, struct address_space *mapping, unsigned long index, struct page **hash);
 
-extern inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long offset)
+extern inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long index)
 {
-	__add_page_to_hash_queue(page, page_hash(&inode->i_data,offset));
+	__add_page_to_hash_queue(page, page_hash(&inode->i_data,index));
 }
 
 extern inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
diff -u --recursive --new-file v2.3.24/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.24/linux/include/linux/pci.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/pci.h	Mon Nov  1 13:38:16 1999
@@ -438,7 +438,6 @@
 
 void pci_init(void);
 struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
-int get_pci_list(char *buf);
 int pci_proc_attach_device(struct pci_dev *dev);
 int pci_proc_detach_device(struct pci_dev *dev);
 void pci_name_device(struct pci_dev *dev);
@@ -490,8 +489,9 @@
 	void *dev_data;		/* driver-private, entry-specific data */
 };
 
-int pci_simple_probe (struct pci_simple_probe_entry *list, size_t match_limit,
-		      pci_simple_probe_callback cb, void *drvr_data);
+int pci_simple_probe (const struct pci_simple_probe_entry *list,
+		      size_t match_limit, pci_simple_probe_callback cb,
+		      void *drvr_data);
 
 
 
diff -u --recursive --new-file v2.3.24/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.3.24/linux/include/linux/pci_ids.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/pci_ids.h	Fri Oct 29 11:05:08 1999
@@ -597,6 +597,7 @@
 #define PCI_DEVICE_ID_INTERG_1680	0x1680
 #define PCI_DEVICE_ID_INTERG_1682	0x1682
 #define PCI_DEVICE_ID_INTERG_2000	0x2000
+#define PCI_DEVICE_ID_INTERG_2010	0x2010
 
 #define PCI_VENDOR_ID_REALTEK		0x10ec
 #define PCI_DEVICE_ID_REALTEK_8029	0x8029
@@ -929,6 +930,7 @@
 #define PCI_DEVICE_ID_LAVA_PARALLEL	0x8000
 #define PCI_DEVICE_ID_LAVA_DUAL_PAR_A	0x8002 /* The Lava Dual Parallel is */
 #define PCI_DEVICE_ID_LAVA_DUAL_PAR_B	0x8003 /* two PCI devices on a card */
+#define PCI_DEVICE_ID_LAVA_BOCA_IOPPAR	0x8800
 
 #define PCI_VENDOR_ID_PANACOM		0x14d4
 #define PCI_DEVICE_ID_PANACOM_QUADMODEM	0x0400
diff -u --recursive --new-file v2.3.24/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.3.24/linux/include/linux/proc_fs.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/proc_fs.h	Mon Nov  1 13:38:26 1999
@@ -12,51 +12,8 @@
  * We always define these enumerators
  */
 
-enum root_directory_inos {
+enum {
 	PROC_ROOT_INO = 1,
-	PROC_LOADAVG,
-	PROC_UPTIME,
-	PROC_MEMINFO,
-	PROC_KMSG,
-	PROC_VERSION,
-	PROC_CPUINFO,
-	PROC_PCI,
-	PROC_MCA,
-	PROC_NUBUS,
-	PROC_MAC_VIA,
-	PROC_SELF,	/* will change inode # */
-	PROC_NET,
-        PROC_SCSI,
-	PROC_MALLOC,
-	PROC_KCORE,
-	PROC_MODULES,
-	PROC_STAT,
-	PROC_DEVICES,
-	PROC_PARTITIONS,
-	PROC_INTERRUPTS,
-	PROC_FILESYSTEMS,
-	PROC_KSYMS,
-	PROC_DMA,	
-	PROC_IOPORTS,
-	PROC_MEMORY,
-	PROC_PROFILE, /* whether enabled or not */
-	PROC_CMDLINE,
-	PROC_SYS,
-	PROC_MTAB,
-	PROC_SWAP,
-	PROC_MD,
-	PROC_RTC,
-	PROC_LOCKS,
-	PROC_HARDWARE,
-	PROC_SLABINFO,
-	PROC_PARPORT,
-	PROC_PPC_HTAB,
-	PROC_STRAM,
-	PROC_SOUND,
-	PROC_MTRR, /* whether enabled or not */
-	PROC_FS,
-	PROC_SYSVIPC,
-	PROC_DRIVER,
 };
 
 enum pid_directory_inos {
@@ -83,73 +40,6 @@
 };
 
 enum net_directory_inos {
-	PROC_NET_UNIX = 128,
-	PROC_NET_ARP,
-	PROC_NET_ROUTE,
-	PROC_NET_DEV,
-	PROC_NET_RAW,
-	PROC_NET_RAW6,
-	PROC_NET_TCP,
-	PROC_NET_TCP6,
-	PROC_NET_UDP,
-	PROC_NET_UDP6,
-	PROC_NET_SNMP,
-	PROC_NET_RARP,
-	PROC_NET_IGMP,
-	PROC_NET_IPMR_VIF,
-	PROC_NET_IPMR_MFC,
-	PROC_NET_IPFWFWD,
-	PROC_NET_IPFWIN,
-	PROC_NET_IPFWOUT,
-	PROC_NET_IPACCT,
-	PROC_NET_IPMSQHST,
-	PROC_NET_WIRELESS,
-	PROC_NET_IPX_INTERFACE,
-	PROC_NET_IPX_ROUTE,
-	PROC_NET_IPX,
-	PROC_NET_ATALK,
-	PROC_NET_AT_ROUTE,
-	PROC_NET_ATIF,
-	PROC_NET_AX25_ROUTE,
-	PROC_NET_AX25,
-	PROC_NET_AX25_CALLS,
-	PROC_NET_BMAC,
-	PROC_NET_NR_NODES,
-	PROC_NET_NR_NEIGH,
-	PROC_NET_NR,
-	PROC_NET_SOCKSTAT,
-	PROC_NET_SOCKSTAT6,
-	PROC_NET_RTCACHE,
-	PROC_NET_AX25_BPQETHER,
-	PROC_NET_IP_MASQ_APP,
-	PROC_NET_RT6,
-	PROC_NET_SNMP6,
-	PROC_NET_RT6_STATS,
-	PROC_NET_NDISC,
-	PROC_NET_STRIP_STATUS,
-	PROC_NET_STRIP_TRACE,
-	PROC_NET_Z8530,
-	PROC_NET_RS_NODES,
-	PROC_NET_RS_NEIGH,
-	PROC_NET_RS_ROUTES,
-	PROC_NET_RS,
-	PROC_NET_CL2LLC,
-	PROC_NET_X25_ROUTES,
-	PROC_NET_X25,
-	PROC_NET_TR_RIF,
-	PROC_NET_DN_DEV,
-	PROC_NET_DN_ADJ,
-	PROC_NET_DN_ROUTE,
-	PROC_NET_DN_CACHE,
-	PROC_NET_DN_SKT,
-	PROC_NET_DN_FW_CHAINS,
-	PROC_NET_DN_FW_CHAIN_NAMES,
-	PROC_NET_DN_RAW,
-	PROC_NET_NETSTAT,
-	PROC_NET_IPFW_CHAINS,
-	PROC_NET_IPFW_CHAIN_NAMES,
-	PROC_NET_AT_AARP,
-	PROC_NET_BRIDGE,
 	PROC_NET_LAST
 };
 
@@ -231,36 +121,6 @@
 	PROC_MCA_LAST = (PROC_MCA_SLOT + 8)
 };
 
-enum bus_directory_inos {
-	PROC_BUS_PCI = PROC_MCA_LAST,
-	PROC_BUS_PCI_DEVICES,
-	PROC_BUS_ZORRO,
-	PROC_BUS_ZORRO_DEVICES,
-	PROC_BUS_ECARD_DEVICES,
-	PROC_BUS_NUBUS,
-	PROC_BUS_NUBUS_DEVICES,
-	PROC_BUS_LAST
-};
-
-enum fs_directory_inos {
-	PROC_FS_CODA = PROC_BUS_LAST,
-	PROC_FS_LAST
-};
-
-enum fs_coda_directory_inos {
-	PROC_VFS_STATS = PROC_FS_LAST,
-	PROC_UPCALL_STATS,
-	PROC_PERMISSION_STATS,
-	PROC_CACHE_INV_STATS,
-	PROC_CODA_FS_LAST
-};
-
-enum sysvipc_directory_inos {
-	PROC_SYSVIPC_SHM = PROC_CODA_FS_LAST,
-	PROC_SYSVIPC_SEM,
-	PROC_SYSVIPC_MSG
-};
-
 /* Finally, the dynamically allocatable proc entries are reserved: */
 
 #define PROC_DYNAMIC_FIRST 4096
@@ -288,6 +148,13 @@
  * fill in file type/protection/owner information specific to the
  * particular /proc file.
  */
+
+typedef	int (read_proc_t)(char *page, char **start, off_t off,
+			  int count, int *eof, void *data);
+typedef	int (write_proc_t)(struct file *file, const char *buffer,
+			   unsigned long count, void *data);
+typedef int (get_info_t)(char *, char **, off_t, int, int);
+
 struct proc_dir_entry {
 	unsigned short low_ino;
 	unsigned short namelen;
@@ -298,74 +165,50 @@
 	gid_t gid;
 	unsigned long size;
 	struct inode_operations * ops;
-	int (*get_info)(char *, char **, off_t, int, int);
+	get_info_t *get_info;
 	void (*fill_inode)(struct inode *, int);
 	struct proc_dir_entry *next, *parent, *subdir;
 	void *data;
-	int (*read_proc)(char *page, char **start, off_t off,
-			 int count, int *eof, void *data);
-	int (*write_proc)(struct file *file, const char *buffer,
-			  unsigned long count, void *data);
+	read_proc_t *read_proc;
+	write_proc_t *write_proc;
 	int (*readlink_proc)(struct proc_dir_entry *de, char *page);
 	unsigned int count;	/* use count */
 	int deleted;		/* delete flag */
 };
 
-typedef	int (read_proc_t)(char *page, char **start, off_t off,
-			  int count, int *eof, void *data);
-typedef	int (write_proc_t)(struct file *file, const char *buffer,
-			   unsigned long count, void *data);
-
 extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
 				off_t offset, int length, int inout);
 
 #ifdef CONFIG_PROC_FS
 
 extern struct proc_dir_entry proc_root;
-extern struct proc_dir_entry proc_root_fs;
+extern struct proc_dir_entry *proc_root_fs;
 extern struct proc_dir_entry *proc_net;
 extern struct proc_dir_entry *proc_scsi;
 extern struct proc_dir_entry proc_sys;
 extern struct proc_dir_entry proc_openprom;
 extern struct proc_dir_entry proc_pid;
 extern struct proc_dir_entry proc_pid_fd;
-extern struct proc_dir_entry proc_mca;
+extern struct proc_dir_entry *proc_mca;
 extern struct proc_dir_entry *proc_bus;
 extern struct proc_dir_entry *proc_sysvipc;
-extern struct proc_dir_entry proc_root_driver;
+extern struct proc_dir_entry *proc_root_driver;
 
 extern struct inode_operations proc_scsi_inode_operations;
 
 extern void proc_root_init(void);
 extern void proc_base_init(void);
+extern void proc_misc_init(void);
 
 extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
 extern int proc_unregister(struct proc_dir_entry *, int);
 
-/*
- * generic.c
- */
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
-					        struct proc_dir_entry *parent);
+						struct proc_dir_entry *parent);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
 
 
-
-/*
- * inlined /proc helper functions
- */
-
-static inline int proc_net_register(struct proc_dir_entry * x)
-{
-	return proc_register(proc_net, x);
-}
-
-static inline int proc_net_unregister(int x)
-{
-	return proc_unregister(proc_net, x);
-}
-
-static inline int proc_scsi_register(struct proc_dir_entry *driver, 
+extern inline int proc_scsi_register(struct proc_dir_entry *driver, 
 				     struct proc_dir_entry *x)
 {
     x->ops = &proc_scsi_inode_operations;
@@ -376,7 +219,7 @@
     }
 }
 
-static inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
+extern inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
 {
     extern void scsi_init_free(char *ptr, unsigned int size);
 
@@ -406,7 +249,7 @@
 {
         struct proc_dir_entry *p;
         
-        p = proc_root_driver.subdir;
+        p = proc_root_driver->subdir;
         while (p != NULL) {
                 if (strcmp (p->name, module_name) == 0)
                         return p;
@@ -422,7 +265,7 @@
  */
 extern inline int proc_driver_unregister(const char *module_name)
 {
-        remove_proc_entry (module_name, &proc_root_driver);
+        remove_proc_entry (module_name, proc_root_driver);
         return 0;
 }
 
@@ -434,7 +277,7 @@
 {
         struct proc_dir_entry *p;
 
-        p = create_proc_entry (module_name, S_IFDIR, &proc_root_driver);
+        p = create_proc_entry (module_name, S_IFDIR, proc_root_driver);
 
         return (p == NULL) ? -1 : 0;
 }
@@ -483,7 +326,6 @@
   
 extern struct inode_operations proc_dir_inode_operations;
 extern struct inode_operations proc_file_inode_operations;
-extern struct inode_operations proc_net_inode_operations;
 extern struct inode_operations proc_netdir_inode_operations;
 extern struct inode_operations proc_openprom_inode_operations;
 extern struct inode_operations proc_mem_inode_operations;
@@ -514,22 +356,71 @@
  */
 extern void proc_device_tree_init(void);
 
+extern inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+	mode_t mode, struct proc_dir_entry *base, 
+	read_proc_t *read_proc, void * data)
+{
+	struct proc_dir_entry *res=create_proc_entry(name,mode,base);
+	if (res) {
+		res->read_proc=read_proc;
+		res->data=data;
+	}
+	return res;
+}
+ 
+extern inline struct proc_dir_entry *create_proc_info_entry(const char *name,
+	mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
+{
+	struct proc_dir_entry *res=create_proc_entry(name,mode,base);
+	if (res) res->get_info=get_info;
+	return res;
+}
+ 
+extern inline struct proc_dir_entry *proc_net_create(const char *name,
+	mode_t mode, get_info_t *get_info)
+{
+	return create_proc_info_entry(name,mode,proc_net,get_info);
+}
+
+extern inline void proc_net_remove(const char *name)
+{
+	remove_proc_entry(name,proc_net);
+}
+
+extern inline int proc_net_register(struct proc_dir_entry * x)
+{
+	return proc_register(proc_net, x);
+}
+
+extern inline int proc_net_unregister(int x)
+{
+	return proc_unregister(proc_net, x);
+}
+
 #else
 
 extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) { return 0; }
 extern inline int proc_unregister(struct proc_dir_entry *a, int b) { return 0; }
-extern inline int proc_net_register(struct proc_dir_entry *a) { return 0; }
+extern inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, 
+	get_info_t *get_info) {return NULL;}
+extern inline void proc_net_remove(const char *name) {}
+extern inline int proc_net_register(struct proc_dir_entry * x) { return 0; }
 extern inline int proc_net_unregister(int x) { return 0; }
 extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; }
 extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; }
 
-extern inline struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
-					 struct proc_dir_entry *parent)
-{
-	return NULL;
-}
+extern inline struct proc_dir_entry *create_proc_entry(const char *name,
+	mode_t mode, struct proc_dir_entry *parent) { return NULL; }
 
 extern inline void remove_proc_entry(const char *name, struct proc_dir_entry *parent) {};
+
+extern inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+	mode_t mode, struct proc_dir_entry *base, 
+	int (*read_proc)(char *, char **, off_t, int, int *, void *),
+	void * data) { return NULL; }
+extern inline struct proc_dir_entry *create_proc_info_entry(const char *name,
+	mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
+	{ return NULL; }
 
 extern inline void proc_tty_register_driver(struct tty_driver *driver) {};
 extern inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
diff -u --recursive --new-file v2.3.24/linux/include/linux/sem.h linux/include/linux/sem.h
--- v2.3.24/linux/include/linux/sem.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/sem.h	Thu Oct 28 10:43:26 1999
@@ -60,11 +60,11 @@
 	int semaem;
 };
 
-#define SEMMNI  128             /* ?  max # of semaphore identifiers */
-#define SEMMSL  32              /* <= 512 max num of semaphores per id */
-#define SEMMNS  (SEMMNI*SEMMSL) /* ? max # of semaphores in system */
-#define SEMOPM  32	        /* ~ 100 max num of ops per semop call */
-#define SEMVMX  32767           /* semaphore maximum value */
+#define SEMMNI  128             /* <= 32767  max # of semaphore identifiers */
+#define SEMMSL  250             /* <= 512 max num of semaphores per id */
+#define SEMMNS  (SEMMNI*SEMMSL) /* <= MAX_INT max # of semaphores in system */
+#define SEMOPM  32	        /* <= 160 max num of ops per semop call */
+#define SEMVMX  32767           /* <= 32767 semaphore maximum value */
 
 /* unused */
 #define SEMUME  SEMOPM          /* max num of undo entries per process */
@@ -81,15 +81,16 @@
 	int	sempid;		/* pid of last operation */
 };
 
-/* One queue for each semaphore set in the system. */
+/* One queue for each sleeping process in the system. */
 struct sem_queue {
 	struct sem_queue *	next;	 /* next entry in the queue */
 	struct sem_queue **	prev;	 /* previous entry in the queue, *(q->prev) == q */
-	wait_queue_head_t	sleeper; /* sleeping process */
+	struct task_struct*	sleeper; /* this process */
 	struct sem_undo *	undo;	 /* undo structure */
 	int    			pid;	 /* process id of requesting process */
 	int    			status;	 /* completion status of operation */
 	struct semid_ds *	sma;	 /* semaphore array for operations */
+	int			id;	 /* internal sem id */
 	struct sembuf *		sops;	 /* array of pending operations */
 	int			nsops;	 /* number of operations */
 	int			alter;	 /* operation will alter semaphore */
diff -u --recursive --new-file v2.3.24/linux/include/linux/serial.h linux/include/linux/serial.h
--- v2.3.24/linux/include/linux/serial.h	Tue Aug 31 17:29:14 1999
+++ linux/include/linux/serial.h	Thu Oct 28 10:45:51 1999
@@ -37,6 +37,20 @@
 #define ASYNC_CLOSING_WAIT_NONE	65535
 
 /*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
+/*
+ * Counters of the input lines (CTS, DSR, RI, CD) interrupts
+ */
+struct async_icount {
+	__u32	cts, dsr, rng, dcd, tx, rx;
+	__u32	frame, parity, overrun, brk;
+	__u32	buf_overrun;
+};
+
+/*
  * These are the supported serial types.
  */
 #define PORT_UNKNOWN	0
diff -u --recursive --new-file v2.3.24/linux/include/linux/serialP.h linux/include/linux/serialP.h
--- v2.3.24/linux/include/linux/serialP.h	Wed Oct 27 16:34:12 1999
+++ linux/include/linux/serialP.h	Mon Nov  1 13:38:16 1999
@@ -24,14 +24,6 @@
 #include <linux/tqueue.h>
 #include <linux/wait.h>
 
-/*
- * Counters of the input lines (CTS, DSR, RI, CD) interrupts
- */
-struct async_icount {
-	__u32	cts, dsr, rng, dcd, tx, rx;
-	__u32	frame, parity, overrun, brk;
-	__u32	buf_overrun;
-};
 
 struct serial_state {
 	int	magic;
@@ -107,10 +99,6 @@
 #define SERIAL_MAGIC 0x5301
 #define SSTATE_MAGIC 0x5302
 
-/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#define SERIAL_XMIT_SIZE 4096
 
 /*
  * Events are used to schedule things to happen at timer-interrupt
diff -u --recursive --new-file v2.3.24/linux/include/linux/shm.h linux/include/linux/shm.h
--- v2.3.24/linux/include/linux/shm.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/shm.h	Fri Oct 29 15:07:16 1999
@@ -7,7 +7,7 @@
 
 struct shmid_ds {
 	struct ipc_perm		shm_perm;	/* operation perms */
-	int			shm_segsz;	/* size of segment (bytes) */
+	size_t			shm_segsz;	/* size of segment (bytes) */
 	__kernel_time_t		shm_atime;	/* last attach time */
 	__kernel_time_t		shm_dtime;	/* last detach time */
 	__kernel_time_t		shm_ctime;	/* last change time */
@@ -46,7 +46,7 @@
 #define SHM_INFO 	14
 
 struct	shminfo {
-	int shmmax;
+	size_t shmmax;
 	int shmmin;
 	int shmmni;
 	int shmseg;
@@ -68,11 +68,11 @@
 #define	SHM_DEST	01000	/* segment will be destroyed on last detach */
 #define SHM_LOCKED      02000   /* segment will not be swapped */
 
-asmlinkage long sys_shmget (key_t key, int size, int flag);
+asmlinkage long sys_shmget (key_t key, size_t size, int flag);
 asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, unsigned long *addr);
 asmlinkage long sys_shmdt (char *shmaddr);
 asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
-extern void shm_unuse(pte_t entry, struct page *page);
+extern void shm_unuse(swp_entry_t entry, struct page *page);
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.24/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.3.24/linux/include/linux/swap.h	Wed Oct 27 16:34:12 1999
+++ linux/include/linux/swap.h	Mon Nov  1 13:38:15 1999
@@ -85,20 +85,20 @@
 
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, struct page *, int);
-extern void rw_swap_page_nolock(int, pte_t, char *, int);
+extern void rw_swap_page_nolock(int, swp_entry_t, char *, int);
 
 /* linux/mm/page_alloc.c */
 
 /* linux/mm/swap_state.c */
 extern void show_swap_cache_info(void);
-extern void add_to_swap_cache(struct page *, pte_t);
-extern int swap_duplicate(pte_t);
+extern void add_to_swap_cache(struct page *, swp_entry_t);
+extern int swap_duplicate(swp_entry_t);
 extern int swap_check_entry(unsigned long);
-struct page * lookup_swap_cache(pte_t);
-extern struct page * read_swap_cache_async(pte_t, int);
+extern struct page * lookup_swap_cache(swp_entry_t);
+extern struct page * read_swap_cache_async(swp_entry_t, int);
 #define read_swap_cache(entry) read_swap_cache_async(entry, 1);
 extern int swap_count(struct page *);
-extern pte_t acquire_swap_entry(struct page *page);
+extern swp_entry_t acquire_swap_entry(struct page *page);
 
 /*
  * Make these inline later once they are working properly.
@@ -111,9 +111,9 @@
 extern unsigned int nr_swapfiles;
 extern struct swap_info_struct swap_info[];
 extern int is_swap_partition(kdev_t);
-void si_swapinfo(struct sysinfo *);
-pte_t get_swap_page(void);
-extern void swap_free(pte_t);
+extern void si_swapinfo(struct sysinfo *);
+extern swp_entry_t get_swap_page(void);
+extern void swap_free(swp_entry_t);
 struct swap_list_t {
 	int head;	/* head of priority-ordered swapfile list */
 	int next;	/* swapfile to be used next */
diff -u --recursive --new-file v2.3.24/linux/include/linux/udf_167.h linux/include/linux/udf_167.h
--- v2.3.24/linux/include/linux/udf_167.h	Tue Sep  7 12:14:07 1999
+++ linux/include/linux/udf_167.h	Sat Oct 30 09:42:30 1999
@@ -54,15 +54,23 @@
 #ifdef __KERNEL__
 #include <linux/types.h>
 #define Uint8	__u8
+#define Sint8	__s8
 #define Uint16	__u16
+#define Sint16	__s16
 #define Uint32	__u32
+#define Sint32	__s32
 #define Uint64	__u64
+#define Sint64	__s64
 typedef Uint8	dstring;
 #else
 #define Uint8	unsigned char
+#define Sint8	char
 #define Uint16	unsigned short
+#define Sint16	short
 #define Uint32	unsigned int
+#define Sint32	int
 #define Uint64	unsigned long long
+#define Sint64	long long
 typedef Uint8	dstring;
 #endif
 
diff -u --recursive --new-file v2.3.24/linux/include/linux/udf_fs.h linux/include/linux/udf_fs.h
--- v2.3.24/linux/include/linux/udf_fs.h	Tue Sep  7 12:14:07 1999
+++ linux/include/linux/udf_fs.h	Sat Oct 30 09:42:30 1999
@@ -30,8 +30,8 @@
 #define UDF_DEFAULT_PREALLOC_BLOCKS		8
 #define UDF_DEFAULT_PREALLOC_DIR_BLOCKS	0
 
-#define UDFFS_DATE		"99/09/02"
-#define UDFFS_VERSION	"0.8.9"
+#define UDFFS_DATE		"99/10/29"
+#define UDFFS_VERSION	"0.8.9.3"
 #define UDFFS_DEBUG
 
 #ifdef UDFFS_DEBUG
diff -u --recursive --new-file v2.3.24/linux/include/linux/wrapper.h linux/include/linux/wrapper.h
--- v2.3.24/linux/include/linux/wrapper.h	Sat Sep 20 14:51:55 1997
+++ linux/include/linux/wrapper.h	Thu Oct 28 13:03:38 1999
@@ -28,7 +28,7 @@
 
 #define vma_set_inode(v,i) v->vm_inode = i
 #define vma_get_flags(v) v->vm_flags
-#define vma_get_offset(v) v->vm_offset
+#define vma_get_pgoff(v) v->vm_pgoff
 #define vma_get_start(v) v->vm_start
 #define vma_get_end(v) v->vm_end
 #define vma_get_page_prot(v) v->vm_page_prot
diff -u --recursive --new-file v2.3.24/linux/ipc/msg.c linux/ipc/msg.c
--- v2.3.24/linux/ipc/msg.c	Sat Oct  9 11:47:50 1999
+++ linux/ipc/msg.c	Thu Oct 28 14:34:47 1999
@@ -97,17 +97,13 @@
 void __init msg_init (void)
 {
 	int id;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-#endif
 
 	for (id = 0; id < MSGMNI; id++) {
 		msg_que[id].lock = SPIN_LOCK_UNLOCKED;
 		msg_que[id].q = NULL;
 	}
 #ifdef CONFIG_PROC_FS
-	ent = create_proc_entry("sysvipc/msg", 0, 0);
-	ent->read_proc = sysvipc_msg_read_proc;
+	create_proc_read_entry("sysvipc/msg", 0, 0, sysvipc_msg_read_proc, NULL);
 #endif
 }
 
diff -u --recursive --new-file v2.3.24/linux/ipc/sem.c linux/ipc/sem.c
--- v2.3.24/linux/ipc/sem.c	Thu Aug 26 13:05:41 1999
+++ linux/ipc/sem.c	Thu Oct 28 14:35:57 1999
@@ -50,11 +50,13 @@
  *      array we do the same as before.
  *
  * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
+ *
+ * SMP-threaded (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  */
 
 #include <linux/config.h>
 #include <linux/malloc.h>
-#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 
@@ -68,27 +70,42 @@
 static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
 
-static struct semid_ds *semary[SEMMNI];
-static int used_sems = 0, used_semids = 0;
-static DECLARE_WAIT_QUEUE_HEAD(sem_lock);
+struct semid_ary
+{
+	spinlock_t lock;
+	struct semid_ds* s;
+};
+
+static struct semid_ary semary[SEMMNI];
+
+static DECLARE_MUTEX(sem_lock);
 static int max_semid = 0;
+static int used_sems = 0;
+static int used_semids = 0;
 
 static unsigned short sem_seq = 0;
 
+/* anti-deadlock ordering:
+ *	sem_lock < semary[].lock
+ * linked list protection:
+ *	sem_undo.id_next,
+ *	semid_ds.sem_pending{,last},
+ *	semid_ds.sem_undo: semary[].lock for read/write
+ *	sem_undo.proc_next: only "current" is allowed to read/write that field.
+ *	
+ */
+
 void __init sem_init (void)
 {
 	int i;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-#endif
 
-	init_waitqueue_head(&sem_lock);
 	used_sems = used_semids = max_semid = sem_seq = 0;
-	for (i = 0; i < SEMMNI; i++)
-		semary[i] = (struct semid_ds *) IPC_UNUSED;
+	for (i = 0; i < SEMMNI; i++) {
+		semary[i].lock = SPIN_LOCK_UNLOCKED;
+		semary[i].s = NULL;
+	}
 #ifdef CONFIG_PROC_FS
-	ent = create_proc_entry("sysvipc/sem", 0, 0);
-	ent->read_proc = sysvipc_sem_read_proc;
+	create_proc_read_entry("sysvipc/sem", 0, 0, sysvipc_sem_read_proc, NULL);
 #endif
 	return;
 }
@@ -99,10 +116,10 @@
 	struct semid_ds *sma;
 
 	for (id = 0; id <= max_semid; id++) {
-		while ((sma = semary[id]) == IPC_NOID)
-			interruptible_sleep_on (&sem_lock);
-		if (sma == IPC_UNUSED)
+		sma = semary[id].s;
+		if(sma==NULL)
 			continue;
+
 		if (key == sma->sem_perm.key)
 			return id;
 	}
@@ -120,20 +137,17 @@
 		return -EINVAL;
 	if (used_sems + nsems > SEMMNS)
 		return -ENOSPC;
-	for (id = 0; id < SEMMNI; id++)
-		if (semary[id] == IPC_UNUSED) {
-			semary[id] = (struct semid_ds *) IPC_NOID;
+	for (id = 0; id < SEMMNI; id++) {
+		if(semary[id].s == NULL)
 			goto found;
-		}
+	}
 	return -ENOSPC;
 found:
 	size = sizeof (*sma) + nsems * sizeof (struct sem);
 	used_sems += nsems;
 	sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);
 	if (!sma) {
-		semary[id] = (struct semid_ds *) IPC_UNUSED;
 		used_sems -= nsems;
-		wake_up (&sem_lock);
 		return -ENOMEM;
 	}
 	memset (sma, 0, size);
@@ -143,7 +157,10 @@
 	ipcp->key = key;
 	ipcp->cuid = ipcp->uid = current->euid;
 	ipcp->gid = ipcp->cgid = current->egid;
-	sma->sem_perm.seq = sem_seq;
+	/* sma->sem_perm.seq*MSGMNI must be a positive integer.
+	 * this limits MSGMNI to 32768
+	 */
+	sma->sem_perm.seq = sem_seq++;
 	/* sma->sem_pending = NULL; */
 	sma->sem_pending_last = &sma->sem_pending;
 	/* sma->undo = NULL; */
@@ -152,8 +169,9 @@
 	if (id > max_semid)
 		max_semid = id;
 	used_semids++;
-	semary[id] = sma;
-	wake_up (&sem_lock);
+	spin_lock(&semary[id].lock);
+	semary[id].s = sma;
+	spin_unlock(&semary[id].lock);
 	return (unsigned int) sma->sem_perm.seq * SEMMNI + id;
 }
 
@@ -162,9 +180,10 @@
 	int id, err = -EINVAL;
 	struct semid_ds *sma;
 
-	lock_kernel();
 	if (nsems < 0 || nsems > SEMMSL)
-		goto out;
+		return -EINVAL;
+	down(&sem_lock);
+	
 	if (key == IPC_PRIVATE) {
 		err = newary(key, nsems, semflg);
 	} else if ((id = findkey (key)) == -1) {  /* key not used */
@@ -175,7 +194,7 @@
 	} else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {
 		err = -EEXIST;
 	} else {
-		sma = semary[id];
+		sma = semary[id].s;
 		if (nsems > sma->sem_nsems)
 			err = -EINVAL;
 		else if (ipcperms(&sma->sem_perm, semflg))
@@ -183,8 +202,8 @@
 		else
 			err = (int) sma->sem_perm.seq * SEMMNI + id;
 	}
-out:
-	unlock_kernel();
+
+	up(&sem_lock);
 	return err;
 }
 
@@ -192,25 +211,25 @@
  * insert new queue elements at the tail sma->sem_pending_last.
  */
 static inline void append_to_queue (struct semid_ds * sma,
-                                    struct sem_queue * q)
+				    struct sem_queue * q)
 {
 	*(q->prev = sma->sem_pending_last) = q;
 	*(sma->sem_pending_last = &q->next) = NULL;
 }
 
 static inline void prepend_to_queue (struct semid_ds * sma,
-                                     struct sem_queue * q)
+				     struct sem_queue * q)
 {
-        q->next = sma->sem_pending;
-        *(q->prev = &sma->sem_pending) = q;
-        if (q->next)
-                q->next->prev = &q->next;
-        else /* sma->sem_pending_last == &sma->sem_pending */
-                sma->sem_pending_last = &q->next;
+	q->next = sma->sem_pending;
+	*(q->prev = &sma->sem_pending) = q;
+	if (q->next)
+		q->next->prev = &q->next;
+	else /* sma->sem_pending_last == &sma->sem_pending */
+		sma->sem_pending_last = &q->next;
 }
 
 static inline void remove_from_queue (struct semid_ds * sma,
-                                      struct sem_queue * q)
+				      struct sem_queue * q)
 {
 	*(q->prev) = q->next;
 	if (q->next)
@@ -226,8 +245,8 @@
  */
 
 static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,
-                             int nsops, struct sem_undo *un, int pid,
-                             int do_undo)
+			     int nsops, struct sem_undo *un, int pid,
+			     int do_undo)
 {
 	int result, sem_op;
 	struct sembuf *sop;
@@ -251,12 +270,12 @@
 			goto out_of_range;
 	}
 
-        if (do_undo)
-        {
-                sop--;
-                result = 0;
-                goto undo;
-        }
+	if (do_undo)
+	{
+		sop--;
+		result = 0;
+		goto undo;
+	}
 
 	sma->sem_otime = CURRENT_TIME;
 	return 0;
@@ -272,7 +291,7 @@
 		result = 1;
 
 undo:
-        while (sop >= sops) {
+	while (sop >= sops) {
 		curr = sma->sem_base + sop->sem_num;
 		curr->semval -= sop->sem_op;
 		curr->sempid >>= 16;
@@ -293,27 +312,27 @@
 	int error;
 	struct sem_queue * q;
 
-        for (q = sma->sem_pending; q; q = q->next) {
-                        
-                if (q->status == 1)
-                        return; /* wait for other process */
-
-                error = try_atomic_semop(sma, q->sops, q->nsops,
-                                         q->undo, q->pid, q->alter);
-
-                /* Does q->sleeper still need to sleep? */
-                if (error <= 0) {
-                                /* Found one, wake it up */
-                        wake_up_interruptible(&q->sleeper);
-                        if (error == 0 && q->alter) {
-                                /* if q-> alter let it self try */
-                                q->status = 1;
-                                return;
-                        }
-                        q->status = error;
-                        remove_from_queue(sma,q);
-                }
-        }
+	for (q = sma->sem_pending; q; q = q->next) {
+			
+		if (q->status == 1)
+			return; /* wait for other process */
+
+		error = try_atomic_semop(sma, q->sops, q->nsops,
+					 q->undo, q->pid, q->alter);
+
+		/* Does q->sleeper still need to sleep? */
+		if (error <= 0) {
+				/* Found one, wake it up */
+			wake_up_process(q->sleeper);
+			if (error == 0 && q->alter) {
+				/* if q-> alter let it self try */
+				q->status = 1;
+				return;
+			}
+			q->status = error;
+			remove_from_queue(sma,q);
+		}
+	}
 }
 
 /* The following counts are associated to each semaphore:
@@ -365,21 +384,22 @@
 /* Free a semaphore set. */
 static void freeary (int id)
 {
-	struct semid_ds *sma = semary[id];
+	struct semid_ds *sma;
 	struct sem_undo *un;
 	struct sem_queue *q;
 
-	/* Invalidate this semaphore set */
-	sma->sem_perm.seq++;
-	sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI); /* increment, but avoid overflow */
+	/* we own both locks, noone can get in */
+	sma = semary[id].s;
+	semary[id].s = NULL;
+
 	used_sems -= sma->sem_nsems;
 	if (id == max_semid)
-		while (max_semid && (semary[--max_semid] == IPC_UNUSED));
-	semary[id] = (struct semid_ds *) IPC_UNUSED;
+		while (max_semid && (semary[--max_semid].s == NULL));
 	used_semids--;
 
 	/* Invalidate the existing undo structures for this semaphore set.
-	 * (They will be freed without any further action in sem_exit().)
+	 * (They will be freed without any further action in sem_exit()
+	 * or during the next semop.)
 	 */
 	for (un = sma->undo; un; un = un->id_next)
 		un->semid = -1;
@@ -388,35 +408,23 @@
 	for (q = sma->sem_pending; q; q = q->next) {
 		q->status = -EIDRM;
 		q->prev = NULL;
-		wake_up_interruptible(&q->sleeper); /* doesn't sleep! */
+		wake_up_process(q->sleeper); /* doesn't sleep */
 	}
 
 	kfree(sma);
 }
 
-asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
+int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
 {
-	struct semid_ds *buf = NULL;
-	struct semid_ds tbuf;
-	int i, id, val = 0;
-	struct semid_ds *sma;
-	struct ipc_perm *ipcp;
-	struct sem *curr = NULL;
-	struct sem_undo *un;
-	unsigned int nsems;
-	ushort *array = NULL;
-	ushort sem_io[SEMMSL];
 	int err = -EINVAL;
+	int lid = semid % SEMMNI;
 
-	lock_kernel();
-	if (semid < 0 || semnum < 0 || cmd < 0)
-		goto out;
-
-	switch (cmd) {
+	switch(cmd) {
 	case IPC_INFO:
 	case SEM_INFO:
 	{
-		struct seminfo seminfo, *tmp = arg.__buf;
+		struct seminfo seminfo;
+
 		seminfo.semmni = SEMMNI;
 		seminfo.semmns = SEMMNS;
 		seminfo.semmsl = SEMMSL;
@@ -428,174 +436,201 @@
 		seminfo.semusz = SEMUSZ;
 		seminfo.semaem = SEMAEM;
 		if (cmd == SEM_INFO) {
+			down(&sem_lock);
 			seminfo.semusz = used_semids;
 			seminfo.semaem = used_sems;
+			up(&sem_lock);
 		}
-		err = -EFAULT;
-		if (copy_to_user (tmp, &seminfo, sizeof(struct seminfo))) 
-			goto out;
-		err = max_semid;
-		goto out;
+		if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo))) 
+			return -EFAULT;
+		return max_semid;
 	}
-
 	case SEM_STAT:
-		buf = arg.buf;
-		err = -EINVAL;
+	{
+		struct semid_ds *sma;
+		struct semid_ds tbuf;
+		int id;
+
 		if (semid > max_semid)
-			goto out;
-		sma = semary[semid];
-		if (sma == IPC_UNUSED || sma == IPC_NOID)
-			goto out;
+			return -EINVAL;
+
+		spin_lock(&semary[lid].lock);
+		err = -EINVAL;
+		sma = semary[semid].s;
+		if (sma ==  NULL)
+			goto out_unlock;
 		err = -EACCES;
 		if (ipcperms (&sma->sem_perm, S_IRUGO))
-			goto out;
+			goto out_unlock;
 		id = (unsigned int) sma->sem_perm.seq * SEMMNI + semid;
+		memset(&tbuf,0,sizeof(tbuf));
 		tbuf.sem_perm   = sma->sem_perm;
 		tbuf.sem_otime  = sma->sem_otime;
 		tbuf.sem_ctime  = sma->sem_ctime;
 		tbuf.sem_nsems  = sma->sem_nsems;
-		err = -EFAULT;
-		if (copy_to_user (buf, &tbuf, sizeof(*buf)) == 0)
-			err = id;
-		goto out;
+		spin_unlock(&semary[lid].lock);
+		if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
+			return -EFAULT;
+		return id;
+	}
+	default:
+		return -EINVAL;
 	}
+	return err;
+out_unlock:
+	spin_unlock(&semary[lid].lock);
+	return err;
+}
 
-	id = (unsigned int) semid % SEMMNI;
-	sma = semary [id];
-	err = -EINVAL;
-	if (sma == IPC_UNUSED || sma == IPC_NOID)
-		goto out;
-	ipcp = &sma->sem_perm;
-	nsems = sma->sem_nsems;
-	err = -EIDRM;
+int semctl_locked_unlock(int semid, int semnum, int cmd, union semun arg)
+{
+	struct semid_ds *sma;
+	struct semid_ds tbuf;
+	int err;
+	int lid = semid % SEMMNI;
+
+	sma = semary[lid].s;
+	err=-EINVAL;
+	if (sma == NULL)
+		goto out_unlock;
+	err=-EIDRM;
 	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-		goto out;
+		goto out_unlock;
 
+	err = -EACCES;
+	if (ipcperms(&sma->sem_perm, S_IRUGO))
+			goto out_unlock;	
+	
 	switch (cmd) {
-	case GETVAL:
-	case GETPID:
-	case GETNCNT:
-	case GETZCNT:
-	case SETVAL:
+	case GETALL:
+	{
+		ushort *array = arg.array;
+		ushort sem_io[SEMMSL];
+		int i;
+		int nsems = sma->sem_nsems;
+
+		for (i = 0; i < sma->sem_nsems; i++)
+			sem_io[i] = sma->sem_base[i].semval;
+		spin_unlock(&semary[lid].lock);
+		if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
+			return -EFAULT;
+		return 0;
+	}
+	case IPC_STAT:
+		memset(&tbuf,0,sizeof(tbuf));
+		tbuf.sem_perm   = sma->sem_perm;
+		tbuf.sem_otime  = sma->sem_otime;
+		tbuf.sem_ctime  = sma->sem_ctime;
+		tbuf.sem_nsems  = sma->sem_nsems;
+		spin_unlock(&semary[lid].lock);
+		if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
+			return -EFAULT;
+		return 0;
+default:
 		err = -EINVAL;
-		if (semnum >= nsems)
-			goto out;
-		curr = &sma->sem_base[semnum];
-		break;
 	}
+out_unlock:
+	spin_unlock(&semary[lid].lock);
+	return err;
+
+}
+
+int semctl_locked(int semid, int semnum, int cmd, union semun arg)
+{
+	struct semid_ds *sma;
+	int lid = semid % SEMMNI;
+	struct sem *curr;
+
+	sma = semary[lid].s;
+	if (sma == NULL)
+		return -EINVAL;
+
+	if (ipcperms (&sma->sem_perm, (cmd==SETVAL)?S_IWUGO:S_IRUGO))
+		return -EACCES;
+
+	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+		return -EIDRM;
+
+	if (semnum >= sma->sem_nsems)
+		return -EINVAL;
+
+	curr = &sma->sem_base[semnum];
 
 	switch (cmd) {
 	case GETVAL:
+		return curr->semval;
 	case GETPID:
+		return curr->sempid & 0xffff;
 	case GETNCNT:
+		return count_semncnt(sma,semnum);
 	case GETZCNT:
-	case GETALL:
-		err = -EACCES;
-		if (ipcperms (ipcp, S_IRUGO))
-			goto out;
-		switch (cmd) {
-		case GETVAL : err = curr->semval; goto out;
-		case GETPID : err = curr->sempid & 0xffff; goto out;
-		case GETNCNT: err = count_semncnt(sma,semnum); goto out;
-		case GETZCNT: err = count_semzcnt(sma,semnum); goto out;
-		case GETALL:
-			array = arg.array;
-			break;
-		}
-		break;
+		return count_semzcnt(sma,semnum);
 	case SETVAL:
-		val = arg.val;
-		err = -ERANGE;
+	{
+		int val = arg.val;
+		struct sem_undo *un;
 		if (val > SEMVMX || val < 0)
-			goto out;
-		break;
-	case IPC_RMID:
-		if (current->euid == ipcp->cuid || 
-		    current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {
-			freeary (id);
-			err = 0;
-			goto out;
-		}
-		err = -EPERM;
-		goto out;
-	case SETALL: /* arg is a pointer to an array of ushort */
-		array = arg.array;
-		err = -EFAULT;
-		if (copy_from_user (sem_io, array, nsems*sizeof(ushort)))
-		       goto out;
-		err = 0;
-		for (i = 0; i < nsems; i++)
-			if (sem_io[i] > SEMVMX) {
-				err = -ERANGE;
-				goto out;
-			}
-		break;
-	case IPC_STAT:
-		buf = arg.buf;
-		break;
-	case IPC_SET:
-		buf = arg.buf;
-		err = copy_from_user (&tbuf, buf, sizeof (*buf));
-		if (err)
-			err = -EFAULT;
-		break;
-	}
-
-	err = -EIDRM;
-	if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
-		goto out;
-	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-		goto out;
+			return -ERANGE;
 
-	switch (cmd) {
-	case GETALL:
-		err = -EACCES;
-		if (ipcperms (ipcp, S_IRUGO))
-			goto out;
-		for (i = 0; i < sma->sem_nsems; i++)
-			sem_io[i] = sma->sem_base[i].semval;
-		if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
-			err = -EFAULT;
-		break;
-	case SETVAL:
-		err = -EACCES;
-		if (ipcperms (ipcp, S_IWUGO))
-			goto out;
 		for (un = sma->undo; un; un = un->id_next)
 			un->semadj[semnum] = 0;
 		curr->semval = val;
 		sma->sem_ctime = CURRENT_TIME;
 		/* maybe some queued-up processes were waiting for this */
 		update_queue(sma);
-		break;
-	case IPC_SET:
-		if (current->euid == ipcp->cuid || 
-		    current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {
-			ipcp->uid = tbuf.sem_perm.uid;
-			ipcp->gid = tbuf.sem_perm.gid;
-			ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
-				| (tbuf.sem_perm.mode & S_IRWXUGO);
-			sma->sem_ctime = CURRENT_TIME;
-			err = 0;
-			goto out;
-		}
-		err = -EPERM;
-		goto out;
-	case IPC_STAT:
-		err = -EACCES;
-		if (ipcperms (ipcp, S_IRUGO))
-			goto out;
-		tbuf.sem_perm   = sma->sem_perm;
-		tbuf.sem_otime  = sma->sem_otime;
-		tbuf.sem_ctime  = sma->sem_ctime;
-		tbuf.sem_nsems  = sma->sem_nsems;
-		if (copy_to_user (buf, &tbuf, sizeof(*buf)))
-			err = -EFAULT;
-		break;
-	case SETALL:
-		err = -EACCES;
+		return 0;
+	}
+	}
+	return -EINVAL;
+}
+
+int semctl_down(int semid, int semnum, int cmd, union semun arg)
+{
+	struct semid_ds *sma;
+	int err;
+	int lid = semid % SEMMNI;
+	struct semid_ds tbuf;
+	struct ipc_perm *ipcp;
+
+	if(cmd == IPC_SET) {
+		if(copy_from_user (&tbuf, arg.buf, sizeof (tbuf)))
+			return -EFAULT;
+	}
+	spin_lock(&semary[lid].lock);
+	sma = semary[lid].s;
+	err=-EINVAL;
+	if (sma == NULL)
+		goto out_unlock;
+	ipcp = &sma->sem_perm;
+	
+	if(cmd == SETALL) {
+		int i;
+		struct sem_undo *un;
+		unsigned int nsems;
+		ushort sem_io[SEMMSL];
+		/* SETALL doesn't belong into this
+		 * group, but I need the semaphore
+		 * for atomically reading nsems
+		 * and changing the semaphore values
+		 */
+		err=-EACCES;
 		if (ipcperms (ipcp, S_IWUGO))
-			goto out;
+			goto out_unlock;
+		nsems=sma->sem_nsems;
+		spin_unlock(&semary[lid].lock);
+
+		if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort)))
+			return -EFAULT;
+		for (i = 0; i < nsems; i++) {
+			if (sem_io[i] > SEMVMX) {
+				return -ERANGE;
+			}
+		}
+		/* we still own sem_lock, ie neither ownership
+		 * nor permissions of the sem array could
+		 * have changed. Just continue.
+		 */
+		spin_lock(&semary[lid].lock);
 		for (i = 0; i < nsems; i++)
 			sma->sem_base[i].semval = sem_io[i];
 		for (un = sma->undo; un; un = un->id_next)
@@ -604,44 +639,169 @@
 		sma->sem_ctime = CURRENT_TIME;
 		/* maybe some queued-up processes were waiting for this */
 		update_queue(sma);
+		err = 0;
+		goto out_unlock;
+	}
+
+	if (current->euid != ipcp->cuid && 
+	    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
+	    	err=-EPERM;
+		goto out_unlock;
+	}
+		
+	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI) {
+		err=-EIDRM;
+		goto out_unlock;
+	}	
+	switch(cmd){
+	case IPC_RMID:
+		freeary(lid);
+		err = 0;
+		break;
+	case IPC_SET:
+		ipcp->uid = tbuf.sem_perm.uid;
+		ipcp->gid = tbuf.sem_perm.gid;
+		ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
+				| (tbuf.sem_perm.mode & S_IRWXUGO);
+		sma->sem_ctime = CURRENT_TIME;
+		err = 0;
 		break;
 	default:
 		err = -EINVAL;
-		goto out;
 	}
-	err = 0;
-out:
-	unlock_kernel();
+
+out_unlock:
+	spin_unlock(&semary[lid].lock);
 	return err;
 }
 
+asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
+{
+	int lid; /* lock id */
+	int err = -EINVAL;
+
+	if (semid < 0 || semnum < 0 || cmd < 0)
+		return -EINVAL;
+
+	lid = semid % SEMMNI;
+
+	switch(cmd) {
+	case IPC_INFO:
+	case SEM_INFO:
+	case SEM_STAT:
+		err = semctl_nolock(semid,semnum,cmd,arg);
+		return err;
+	case GETALL:
+	case IPC_STAT:
+		spin_lock(&semary[lid].lock);
+		err = semctl_locked_unlock(semid,semnum,cmd,arg);
+		return err;
+	case GETVAL:
+	case GETPID:
+	case GETNCNT:
+	case GETZCNT:
+	case SETVAL:
+		spin_lock(&semary[lid].lock);
+		err= semctl_locked(semid,semnum,cmd,arg);
+		spin_unlock(&semary[lid].lock);
+		return err;
+	case SETALL:
+	case IPC_RMID:
+	case IPC_SET:
+		down(&sem_lock);
+		err= semctl_down(semid,semnum,cmd,arg);
+		up(&sem_lock);
+		return err;
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct sem_undo* freeundos(struct semid_ds *sma, struct sem_undo* un)
+{
+	struct sem_undo* u;
+	struct sem_undo** up;
+
+	for(up = &current->semundo;(u=*up);up=&u->proc_next) {
+		if(un==u) {
+			un=u->proc_next;
+			*up=un;
+			kfree(u);
+			return un;
+		}
+	}
+	printk ("freeundos undo list error id=%d\n", un->semid);
+	return un->proc_next;
+}
+
+static int alloc_undo(struct semid_ds *sma, struct sem_undo** unp, int semid, int alter)
+{
+	int size;
+	struct sem_undo *un;
+	int error,id;
+	id = (unsigned int) semid % SEMMNI;
+	size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
+	spin_unlock(&semary[id].lock);
+
+	un = (struct sem_undo *) kmalloc(size, GFP_KERNEL);
+	spin_lock(&semary[id].lock);
+	if (!un) {
+		return -ENOMEM;
+	}
+	sma = semary[id].s;
+	error = -EIDRM;
+	if (sma == NULL)
+		goto out;
+	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+		goto out;
+	if (size != sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems)
+		goto out;
+
+	error = -EACCES;
+	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
+		goto out;
+	memset(un, 0, size);
+	un->semadj = (short *) &un[1];
+	un->semid = semid;
+	un->proc_next = current->semundo;
+	current->semundo = un;
+	un->id_next = sma->undo;
+	sma->undo = un;
+	*unp = un;
+	return 0;
+out:
+	kfree(un);
+	return error;
+}
+
 asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 {
-	int id, size, error = -EINVAL;
+	int id, error = -EINVAL;
 	struct semid_ds *sma;
 	struct sembuf sops[SEMOPM], *sop;
 	struct sem_undo *un;
 	int undos = 0, decrease = 0, alter = 0;
 	struct sem_queue queue;
 
-	lock_kernel();
 	if (nsops < 1 || semid < 0)
-		goto out;
-	error = -E2BIG;
+		return -EINVAL;
+
 	if (nsops > SEMOPM)
-		goto out;
-	error = -EFAULT;
+		return -E2BIG;
 	if (copy_from_user (sops, tsops, nsops * sizeof(*tsops)))
-		goto out;
+		return -EFAULT;
+
 	id = (unsigned int) semid % SEMMNI;
+	spin_lock(&semary[id].lock);
+	sma = semary[id].s;
 	error = -EINVAL;
-	if ((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)
+	if (sma == NULL)
 		goto out;
 	error = -EIDRM;
 	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
 		goto out;
 
-		error = -EFBIG;
+	error = -EFBIG;
 	for (sop = sops; sop < sops + nsops; sop++) {
 		if (sop->sem_num >= sma->sem_nsems)
 			goto out;
@@ -649,10 +809,10 @@
 			undos++;
 		if (sop->sem_op < 0)
 			decrease = 1;
-                if (sop->sem_op > 0)
-                        alter = 1;
+		if (sop->sem_op > 0)
+			alter = 1;
 	}
-        alter |= decrease;
+	alter |= decrease;
 
 	error = -EACCES;
 	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
@@ -661,81 +821,85 @@
 		/* Make sure we have an undo structure
 		 * for this process and this semaphore set.
 		 */
-		for (un = current->semundo; un; un = un->proc_next)
-			if (un->semid == semid)
+		un=current->semundo;
+		while(un != NULL) {
+			if(un->semid==semid)
 				break;
+			if(un->semid==-1)
+				un=freeundos(sma,un);
+			 else
+				un=un->proc_next;
+		}
 		if (!un) {
-			size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
-			un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
-			if (!un) {
-				error = -ENOMEM;
+			error = alloc_undo(sma,&un,semid,alter);
+			if(error<0)
 				goto out;
-			}
-			memset(un, 0, size);
-			un->semadj = (short *) &un[1];
-			un->semid = semid;
-			un->proc_next = current->semundo;
-			current->semundo = un;
-			un->id_next = sma->undo;
-			sma->undo = un;
 		}
 	} else
 		un = NULL;
 
 	error = try_atomic_semop (sma, sops, nsops, un, current->pid, 0);
 	if (error <= 0)
-                goto update;
+		goto update;
+
+	/* We need to sleep on this operation, so we put the current
+	 * task into the pending queue and go to sleep.
+	 */
+		
+	queue.sma = sma;
+	queue.sops = sops;
+	queue.nsops = nsops;
+	queue.undo = un;
+	queue.pid = current->pid;
+	queue.alter = decrease;
+	queue.id = id;
+	current->semsleeping = &queue;
+	if (alter)
+		append_to_queue(sma ,&queue);
+	else
+		prepend_to_queue(sma ,&queue);
+
+	for (;;) {
+		queue.status = -EINTR;
+		queue.sleeper = current;
+		current->state = TASK_INTERRUPTIBLE;
+		spin_unlock(&semary[id].lock);
 
-        /* We need to sleep on this operation, so we put the current
-         * task into the pending queue and go to sleep.
-         */
-                
-        queue.sma = sma;
-        queue.sops = sops;
-        queue.nsops = nsops;
-        queue.undo = un;
-        queue.pid = current->pid;
-        queue.alter = decrease;
-        current->semsleeping = &queue;
-        if (alter)
-                append_to_queue(sma ,&queue);
-        else
-                prepend_to_queue(sma ,&queue);
-
-        for (;;) {
-                queue.status = -EINTR;
-                init_waitqueue_head(&queue.sleeper);
-                interruptible_sleep_on(&queue.sleeper);
-
-                /*
-                 * If queue.status == 1 we where woken up and
-                 * have to retry else we simply return.
-                 * If an interrupt occurred we have to clean up the
-                 * queue
-                 *
-                 */
-                if (queue.status == 1)
-                {
-                        error = try_atomic_semop (sma, sops, nsops, un,
-                                                  current->pid,0);
-                        if (error <= 0) 
-                                break;
-                } else {
-                        error = queue.status;;
-                        if (queue.prev) /* got Interrupt */
-                                break;
-                        /* Everything done by update_queue */
-                        current->semsleeping = NULL;
-                        goto out;
-                }
-        }
-        current->semsleeping = NULL;
-        remove_from_queue(sma,&queue);
+		schedule();
+
+		/* we can lock the semary even if it was
+		 * deleted.
+		 */
+		spin_lock(&semary[id].lock);
+		/*
+		 * If queue.status == 1 we where woken up and
+		 * have to retry else we simply return.
+		 * If an interrupt occurred we have to clean up the
+		 * queue
+		 *
+		 */
+		if (queue.status == 1)
+		{
+			error = try_atomic_semop (sma, sops, nsops, un,
+						  current->pid,0);
+			if (error <= 0) 
+				break;
+		} else {
+			error = queue.status;
+			if (queue.prev) /* got Interrupt */
+				break;
+			/* Everything done by update_queue */
+			current->semsleeping = NULL;
+			goto out;
+		}
+	}
+	current->semsleeping = NULL;
+	remove_from_queue(sma,&queue);
 update:
-        if (alter)
-                update_queue (sma);
+	if (alter)
+		update_queue (sma);
 out:
-	unlock_kernel();
+	spin_unlock(&semary[id].lock);
 	return error;
 }
 
@@ -761,27 +925,43 @@
 	/* If the current process was sleeping for a semaphore,
 	 * remove it from the queue.
 	 */
+	/* semsleeping is part of "current", and it
+	 * is never modified by another thread.
+	 * No synchronization required.
+	 */
 	if ((q = current->semsleeping)) {
+		spin_lock(&semary[current->semsleeping->id].lock);
+
 		if (q->prev)
 			remove_from_queue(q->sma,q);
 		current->semsleeping = NULL;
+		spin_unlock(&semary[current->semsleeping->id].lock);
 	}
 
 	for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
-		if (u->semid == -1)
-			continue;
-		sma = semary[(unsigned int) u->semid % SEMMNI];
-		if (sma == IPC_UNUSED || sma == IPC_NOID)
+		int semid = u->semid;
+		int lid;
+		if(semid == -1)
 			continue;
+		lid = semid % SEMMNI;
+		spin_lock(&semary[lid].lock);
+
+		if (u->semid == -1)
+			goto next_entry;
+
+		sma = semary[lid].s;
+		if (sma == NULL)
+			goto next_entry;
 		if (sma->sem_perm.seq != (unsigned int) u->semid / SEMMNI)
-			continue;
+			goto next_entry;
+
 		/* remove u from the sma->undo list */
 		for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
 			if (u == un)
 				goto found;
 		}
 		printk ("sem_exit undo list error id=%d\n", u->semid);
-		break;
+		goto next_entry;
 found:
 		*unp = un->id_next;
 		/* perform adjustments registered in u */
@@ -796,6 +976,8 @@
 		sma->sem_otime = CURRENT_TIME;
 		/* maybe some queued-up processes were waiting for this */
 		update_queue(sma);
+next_entry:
+		spin_unlock(&semary[lid].lock);
 	}
 	current->semundo = NULL;
 }
@@ -808,20 +990,23 @@
 	int i, len = 0;
 
 	len += sprintf(buffer, "       key      semid perms nsems   uid   gid  cuid  cgid      otime      ctime\n");
+	down(&sem_lock);
 
 	for(i = 0; i < SEMMNI; i++)
-		if(semary[i] != IPC_UNUSED) {
+		if(semary[i].s != NULL) {
+			spin_lock(&semary[i].lock);
 			len += sprintf(buffer + len, "%10d %10d  %4o %5u %5u %5u %5u %5u %10lu %10lu\n",
-				semary[i]->sem_perm.key,
-				semary[i]->sem_perm.seq * SEMMNI + i,
-				semary[i]->sem_perm.mode,
-				semary[i]->sem_nsems,
-				semary[i]->sem_perm.uid,
-				semary[i]->sem_perm.gid,
-				semary[i]->sem_perm.cuid,
-				semary[i]->sem_perm.cgid,
-				semary[i]->sem_otime,
-				semary[i]->sem_ctime);
+				semary[i].s->sem_perm.key,
+				semary[i].s->sem_perm.seq * SEMMNI + i,
+				semary[i].s->sem_perm.mode,
+				semary[i].s->sem_nsems,
+				semary[i].s->sem_perm.uid,
+				semary[i].s->sem_perm.gid,
+				semary[i].s->sem_perm.cuid,
+				semary[i].s->sem_perm.cgid,
+				semary[i].s->sem_otime,
+				semary[i].s->sem_ctime);
+			spin_unlock(&semary[i].lock);
 
 			pos += len;
 			if(pos < offset) {
@@ -833,6 +1018,7 @@
 		}
 	*eof = 1;
 done:
+	up(&sem_lock);
 	*start = buffer + (offset - begin);
 	len -= (offset - begin);
 	if(len > length)
diff -u --recursive --new-file v2.3.24/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.24/linux/ipc/shm.c	Wed Oct 27 16:34:12 1999
+++ linux/ipc/shm.c	Fri Oct 29 15:07:16 1999
@@ -27,7 +27,7 @@
 
 extern int ipcperms (struct ipc_perm *ipcp, short shmflg);
 static int findkey (key_t key);
-static int newseg (key_t key, int shmflg, int size);
+static int newseg (key_t key, int shmflg, size_t size);
 static int shm_map (struct vm_area_struct *shmd);
 static void killseg (int id);
 static void shm_open (struct vm_area_struct *shmd);
@@ -57,17 +57,13 @@
 void __init shm_init (void)
 {
 	int id;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-#endif
 
 	for (id = 0; id < SHMMNI; id++)
 		shm_segs[id] = (struct shmid_kernel *) IPC_UNUSED;
 	shm_tot = shm_rss = shm_seq = max_shmid = used_segs = 0;
 	init_waitqueue_head(&shm_wait);
 #ifdef CONFIG_PROC_FS
-	ent = create_proc_entry("sysvipc/shm", 0, 0);
-	ent->read_proc = sysvipc_shm_read_proc;
+	create_proc_read_entry("sysvipc/shm", 0, 0, sysvipc_shm_read_proc, NULL);
 #endif
 	return;
 }
@@ -104,7 +100,7 @@
 /*
  * allocate new shmid_kernel and pgtable. protected by shm_segs[id] = NOID.
  */
-static int newseg (key_t key, int shmflg, int size)
+static int newseg (key_t key, int shmflg, size_t size)
 {
 	struct shmid_kernel *shp;
 	int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;
@@ -168,16 +164,16 @@
 	return (unsigned int) shp->u.shm_perm.seq * SHMMNI + id;
 }
 
-int shmmax = SHMMAX;
+size_t shmmax = SHMMAX;
 
-asmlinkage long sys_shmget (key_t key, int size, int shmflg)
+asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
 {
 	struct shmid_kernel *shp;
 	int err, id = 0;
 
 	down(&current->mm->mmap_sem);
 	spin_lock(&shm_lock);
-	if (size < 0 || size > shmmax) {
+	if (size > shmmax) {
 		err = -EINVAL;
 	} else if (key == IPC_PRIVATE) {
 		err = newseg(key, shmflg, size);
@@ -237,7 +233,7 @@
 			rss++;
 		} else {
 			lock_kernel();
-			swap_free(pte);
+			swap_free(pte_to_swp_entry(pte));
 			unlock_kernel();
 			swp++;
 		}
@@ -409,7 +405,7 @@
  * shmd->vm_end		multiple of SHMLBA
  * shmd->vm_next	next attach for task
  * shmd->vm_next_share	next attach for segment
- * shmd->vm_offset	offset into segment
+ * shmd->vm_pgoff	offset into segment (in pages)
  * shmd->vm_private_data		signature for this attach
  */
 
@@ -494,7 +490,7 @@
 		err = -ENOMEM;
 		addr = 0;
 	again:
-		if (!(addr = get_unmapped_area(addr, shp->u.shm_segsz)))
+		if (!(addr = get_unmapped_area(addr, (unsigned long)shp->u.shm_segsz)))
 			goto out;
 		if(addr & (SHMLBA - 1)) {
 			addr = (addr + (SHMLBA - 1)) & ~(SHMLBA - 1);
@@ -520,7 +516,7 @@
 	if (addr < current->mm->start_stack &&
 	    addr > current->mm->start_stack - PAGE_SIZE*(shp->shm_npages + 4))
 		goto out;
-	if (!(shmflg & SHM_REMAP) && find_vma_intersection(current->mm, addr, addr + shp->u.shm_segsz))
+	if (!(shmflg & SHM_REMAP) && find_vma_intersection(current->mm, addr, addr + (unsigned long)shp->u.shm_segsz))
 		goto out;
 
 	err = -EACCES;
@@ -551,7 +547,7 @@
 			 | VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC
 			 | ((shmflg & SHM_RDONLY) ? 0 : VM_MAYWRITE | VM_WRITE);
 	shmd->vm_file = NULL;
-	shmd->vm_offset = 0;
+	shmd->vm_pgoff = 0;
 	shmd->vm_ops = &shm_vm_ops;
 
 	shp->u.shm_nattch++;	    /* prevent destruction */
@@ -631,7 +627,7 @@
 	for (shmd = current->mm->mmap; shmd; shmd = shmdnext) {
 		shmdnext = shmd->vm_next;
 		if (shmd->vm_ops == &shm_vm_ops
-		    && shmd->vm_start - shmd->vm_offset == (ulong) shmaddr)
+		    && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr)
 			do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start);
 	}
 	up(&current->mm->mmap_sem);
@@ -662,7 +658,8 @@
 	struct page * page;
 
 	shp = *(struct shmid_kernel **) shmd->vm_private_data;
-	idx = (address - shmd->vm_start + shmd->vm_offset) >> PAGE_SHIFT;
+	idx = (address - shmd->vm_start) >> PAGE_SHIFT;
+	idx += shmd->vm_pgoff;
 
 	spin_lock(&shm_lock);
 again:
@@ -678,7 +675,7 @@
 			if (pte_val(pte) != pte_val(shp->shm_pages[idx]))
 				goto changed;
 		} else {
-			pte_t entry = pte;
+			swp_entry_t entry = pte_to_swp_entry(pte);
 
 			spin_unlock(&shm_lock);
 			page = lookup_swap_cache(entry);
@@ -735,15 +732,18 @@
 {
 	pte_t page;
 	struct shmid_kernel *shp;
-	pte_t swap_entry;
+	swp_entry_t swap_entry;
 	unsigned long id, idx;
 	int loop = 0;
 	int counter;
 	struct page * page_map;
 	
 	counter = shm_rss >> prio;
+	if (!counter)
+		return 0;
 	lock_kernel();
-	if (!counter || !pte_val(swap_entry = get_swap_page())) {
+	swap_entry = get_swap_page();
+	if (!swap_entry.val) {
 		unlock_kernel();
 		return 0;
 	}
@@ -792,7 +792,7 @@
 		goto check_table;
 	if (!(page_map = prepare_highmem_swapout(page_map)))
 		goto check_table;
-	shp->shm_pages[idx] = swap_entry;
+	shp->shm_pages[idx] = swp_entry_to_pte(swap_entry);
 	swap_successes++;
 	shm_swp++;
 	shm_rss--;
@@ -812,7 +812,7 @@
  * Free the swap entry and set the new pte for the shm page.
  */
 static void shm_unuse_page(struct shmid_kernel *shp, unsigned long idx,
-			pte_t entry, struct page *page)
+			swp_entry_t entry, struct page *page)
 {
 	pte_t pte;
 
@@ -832,7 +832,7 @@
 /*
  * unuse_shm() search for an eventually swapped out shm page.
  */
-void shm_unuse(pte_t entry, struct page *page)
+void shm_unuse(swp_entry_t entry, struct page *page)
 {
 	int i, n;
 
@@ -841,11 +841,16 @@
 		struct shmid_kernel *seg = shm_segs[i];
 		if ((seg == IPC_UNUSED) || (seg == IPC_NOID))
 			continue;
-		for (n = 0; n < seg->shm_npages; n++)
-			if (pte_val(seg->shm_pages[n]) == pte_val(entry)) {
+		for (n = 0; n < seg->shm_npages; n++) {
+			if (pte_none(seg->shm_pages[n]))
+				continue;
+			if (pte_present(seg->shm_pages[n]))
+				continue;
+			if (pte_to_swp_entry(seg->shm_pages[n]).val == entry.val) {
 				shm_unuse_page(seg, n, entry, page);
 				return;
 			}
+		}
 	}
 	spin_unlock(&shm_lock);
 }
@@ -862,7 +867,15 @@
 	spin_lock(&shm_lock);
     	for(i = 0; i < SHMMNI; i++)
 		if(shm_segs[i] != IPC_UNUSED) {
-	    		len += sprintf(buffer + len, "%10d %10d  %4o %10d %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n",
+#define SMALL_STRING "%10d %10d  %4o %10u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
+#define BIG_STRING   "%10d %10d  %4o %21u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
+			char *format;
+
+			if (sizeof(size_t) <= sizeof(int))
+				format = SMALL_STRING;
+			else
+				format = BIG_STRING;
+	    		len += sprintf(buffer + len, format,
 			shm_segs[i]->u.shm_perm.key,
 			shm_segs[i]->u.shm_perm.seq * SHMMNI + i,
 			shm_segs[i]->u.shm_perm.mode,
diff -u --recursive --new-file v2.3.24/linux/ipc/util.c linux/ipc/util.c
--- v2.3.24/linux/ipc/util.c	Wed Oct 27 16:34:12 1999
+++ linux/ipc/util.c	Fri Oct 29 11:19:10 1999
@@ -119,7 +119,7 @@
 	return -ENOSYS;
 }
 
-void shm_unuse(pte_t entry, struct page *page)
+void shm_unuse(swp_entry_t entry, struct page *page)
 {
 }
 
diff -u --recursive --new-file v2.3.24/linux/kernel/exec_domain.c linux/kernel/exec_domain.c
--- v2.3.24/linux/kernel/exec_domain.c	Tue Sep  7 12:14:07 1999
+++ linux/kernel/exec_domain.c	Fri Oct 29 11:04:06 1999
@@ -125,3 +125,15 @@
 	unlock_kernel();
 	return ret;
 }
+
+int get_exec_domain_list(char * page)
+{
+	int len = 0;
+	struct exec_domain * e;
+
+	for (e=exec_domains; e && len < PAGE_SIZE - 80; e=e->next)
+		len += sprintf(page+len, "%d-%d\t%-16s\t[%s]\n",
+			e->pers_low, e->pers_high, e->name,
+			e->module ? e->module->name : "kernel");
+	return len;
+}
diff -u --recursive --new-file v2.3.24/linux/kernel/exit.c linux/kernel/exit.c
--- v2.3.24/linux/kernel/exit.c	Fri Oct 22 13:21:55 1999
+++ linux/kernel/exit.c	Mon Nov  1 13:18:00 1999
@@ -455,6 +455,7 @@
 	add_wait_queue(&current->wait_chldexit,&wait);
 repeat:
 	flag = 0;
+	current->state = TASK_INTERRUPTIBLE;
 	read_lock(&tasklist_lock);
  	for (p = current->p_cptr ; p ; p = p->p_osptr) {
 		if (pid>0) {
@@ -521,12 +522,12 @@
 		retval = -ERESTARTSYS;
 		if (signal_pending(current))
 			goto end_wait4;
-		current->state=TASK_INTERRUPTIBLE;
 		schedule();
 		goto repeat;
 	}
 	retval = -ECHILD;
 end_wait4:
+	current->state = TASK_RUNNING;
 	remove_wait_queue(&current->wait_chldexit,&wait);
 	return retval;
 }
diff -u --recursive --new-file v2.3.24/linux/kernel/sys.c linux/kernel/sys.c
--- v2.3.24/linux/kernel/sys.c	Sat Oct  9 11:47:50 1999
+++ linux/kernel/sys.c	Fri Oct 29 13:19:49 1999
@@ -889,6 +889,25 @@
 			? -EFAULT : 0;
 }
 
+/*
+ *	Back compatibility for getrlimit. Needed for some apps.
+ */
+ 
+asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim)
+{
+	struct rlimit x;
+	if (resource >= RLIM_NLIMITS)
+		return -EINVAL;
+
+	memcpy(&x, current->rlim + resource, sizeof(*rlim));
+	if(x.rlim_cur > 0x7FFFFFFF)
+		x.rlim_cur = 0x7FFFFFFF;
+	if(x.rlim_max > 0x7FFFFFFF)
+		x.rlim_max = 0x7FFFFFFF;
+	return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0;
+}
+
+
 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
 	struct rlimit new_rlim, *old_rlim;
diff -u --recursive --new-file v2.3.24/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.3.24/linux/kernel/sysctl.c	Sat Oct  9 11:47:50 1999
+++ linux/kernel/sysctl.c	Fri Oct 29 15:07:16 1999
@@ -49,7 +49,7 @@
 extern int sg_big_buff;
 #endif
 #ifdef CONFIG_SYSVIPC
-extern int shmmax;
+extern size_t shmmax;
 #endif
 
 #ifdef __sparc__
@@ -136,7 +136,7 @@
 	NULL		/* revalidate */
 };
 
-extern struct proc_dir_entry proc_sys_root;
+extern struct proc_dir_entry *proc_sys_root;
 
 static void register_proc_table(ctl_table *, struct proc_dir_entry *);
 static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
@@ -213,8 +213,8 @@
 	{KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int),
 	 0644, NULL, &proc_dointvec},
 #ifdef CONFIG_SYSVIPC
-	{KERN_SHMMAX, "shmmax", &shmmax, sizeof (int),
-	 0644, NULL, &proc_dointvec},
+	{KERN_SHMMAX, "shmmax", &shmmax, sizeof (size_t),
+	 0644, NULL, &proc_doulongvec_minmax},
 #endif
 #ifdef CONFIG_MAGIC_SYSRQ
 	{KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
@@ -285,7 +285,7 @@
 void __init sysctl_init(void)
 {
 #ifdef CONFIG_PROC_FS
-	register_proc_table(root_table, &proc_sys_root);
+	register_proc_table(root_table, proc_sys_root);
 #endif
 }
 
@@ -480,7 +480,7 @@
 	else
 		DLIST_INSERT_BEFORE(&root_table_header, tmp, ctl_entry);
 #ifdef CONFIG_PROC_FS
-	register_proc_table(table, &proc_sys_root);
+	register_proc_table(table, proc_sys_root);
 #endif
 	return tmp;
 }
@@ -492,7 +492,7 @@
 {
 	DLIST_DELETE(header, ctl_entry);
 #ifdef CONFIG_PROC_FS
-	unregister_proc_table(header->ctl_table, &proc_sys_root);
+	unregister_proc_table(header->ctl_table, proc_sys_root);
 #endif
 	kfree(header);
 }
@@ -1067,6 +1067,12 @@
 	return -ENOSYS;
 }
 
+int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
+			void *buffer, size_t *lenp)
+{
+	return -ENOSYS;
+}
+
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
 		    void *buffer, size_t *lenp)
 {
@@ -1308,6 +1314,12 @@
 
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp)
+{
+	return -ENOSYS;
+}
+
+int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
+			void *buffer, size_t *lenp)
 {
 	return -ENOSYS;
 }
diff -u --recursive --new-file v2.3.24/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.24/linux/mm/filemap.c	Wed Oct 27 16:34:12 1999
+++ linux/mm/filemap.c	Fri Oct 29 16:45:32 1999
@@ -50,9 +50,7 @@
 spinlock_t pagemap_lru_lock = SPIN_LOCK_UNLOCKED;
 
 #define CLUSTER_PAGES		(1 << page_cluster)
-#define CLUSTER_SHIFT		(PAGE_CACHE_SHIFT + page_cluster)
-#define CLUSTER_BYTES		(1 << CLUSTER_SHIFT)
-#define CLUSTER_OFFSET(x)	(((x) >> CLUSTER_SHIFT) << CLUSTER_SHIFT)
+#define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
 
 void __add_page_to_hash_queue(struct page * page, struct page **p)
 {
@@ -127,20 +125,22 @@
 void truncate_inode_pages(struct inode * inode, unsigned long start)
 {
 	struct list_head *head, *curr;
-	unsigned long offset;
 	struct page * page;
-	int partial = 0;
+	unsigned partial = start & (PAGE_CACHE_SIZE - 1);
+
+	start = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 repeat:
 	head = &inode->i_data.pages;
 	spin_lock(&pagecache_lock);
 	curr = head->next;
 	while (curr != head) {
+		unsigned long offset;
 
 		page = list_entry(curr, struct page, list);
 		curr = curr->next;
 
-		offset = page->offset;
+		offset = page->index;
 
 		/* page wholly truncated - free it */
 		if (offset >= start) {
@@ -179,30 +179,32 @@
 		/*
 		 * there is only one partial page possible.
 		 */
-		if (partial)
+		if (!partial)
+			continue;
+
+		/* and it's the one preceeding the first wholly truncated page */
+		if ((offset + 1) != start)
 			continue;
 
-		offset = start - offset;
 		/* partial truncate, clear end of page */
-		if (offset < PAGE_CACHE_SIZE) {
-			get_page(page);
-			spin_unlock(&pagecache_lock);
+		get_page(page);
+		spin_unlock(&pagecache_lock);
 
-			lock_page(page);
-			partial = 1;
+		lock_page(page);
 
-			memclear_highpage_flush(page, offset,
-						PAGE_CACHE_SIZE-offset);
-			if (inode->i_op->flushpage)
-				inode->i_op->flushpage(inode, page, offset);
-			/*
-			 * we have dropped the spinlock so we have to
-			 * restart.
-			 */
-			UnlockPage(page);
-			page_cache_release(page);
-			goto repeat;
-		}
+		memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
+		if (inode->i_op->flushpage)
+			inode->i_op->flushpage(inode, page, partial);
+
+		partial = 0;
+
+		/*
+		 * we have dropped the spinlock so we have to
+		 * restart.
+		 */
+		UnlockPage(page);
+		page_cache_release(page);
+		goto repeat;
 	}
 	spin_unlock(&pagecache_lock);
 }
@@ -367,7 +369,7 @@
 			goto not_found;
 		if (page->mapping != mapping)
 			continue;
-		if (page->offset == offset)
+		if (page->index == offset)
 			break;
 	}
 	set_bit(PG_referenced, &page->flags);
@@ -417,7 +419,6 @@
 	int retval = 0;
 
 	head = &inode->i_data.pages;
-	start &= PAGE_MASK;
 
 	spin_lock(&pagecache_lock);
 	curr = head->next;
@@ -426,9 +427,9 @@
 		curr = curr->next;
 		if (!page->buffers)
 			continue;
-		if (page->offset >= end)
+		if (page->index >= end)
 			continue;
-		if (page->offset < start)
+		if (page->index < start)
 			continue;
 
 		get_page(page);
@@ -455,10 +456,12 @@
  */
 int generic_buffer_fdatasync(struct inode *inode, unsigned long start, unsigned long end)
 {
+	unsigned long start_idx = start >> PAGE_CACHE_SHIFT;
+	unsigned long end_idx = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	int retval;
 
-	retval = do_buffer_fdatasync(inode, start, end, writeout_one_page);
-	retval |= do_buffer_fdatasync(inode, start, end, waitfor_one_page);
+	retval = do_buffer_fdatasync(inode, start_idx, end_idx, writeout_one_page);
+	retval |= do_buffer_fdatasync(inode, start_idx, end_idx, waitfor_one_page);
 	return retval;
 }
 
@@ -476,7 +479,7 @@
 	flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced));
 	page->flags = flags | (1 << PG_locked);
 	get_page(page);
-	page->offset = offset;
+	page->index = offset;
 	add_page_to_inode_queue(mapping, page);
 	__add_page_to_hash_queue(page, hash);
 	lru_cache_add(page);
@@ -549,16 +552,15 @@
  * Read in an entire cluster at once.  A cluster is usually a 64k-
  * aligned block that includes the address requested in "offset."
  */
-static void read_cluster_nonblocking(struct file * file,
-	unsigned long offset)
+static void read_cluster_nonblocking(struct file * file, unsigned long offset)
 {
-	off_t filesize = file->f_dentry->d_inode->i_size;
+	unsigned long filesize = (file->f_dentry->d_inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	unsigned long pages = CLUSTER_PAGES;
 
 	offset = CLUSTER_OFFSET(offset);
 	while ((pages-- > 0) && (offset < filesize)) {
 		page_cache_read(file, offset);
-		offset += PAGE_CACHE_SIZE;
+		offset ++;
 	}
 
 	return;
@@ -751,7 +753,7 @@
 			total_rawin/total_reada,
 			(total_async*100)/total_reada);
 #ifdef DEBUG_READAHEAD
-		printk("Readahead snapshot: max=%ld, len=%ld, win=%ld, raend=%ld\n",
+		printk("Readahead snapshot: max=%ld, len=%ld, win=%ld, raend=%Ld\n",
 			filp->f_ramax, filp->f_ralen, filp->f_rawin, filp->f_raend);
 #endif
 
@@ -897,7 +899,7 @@
 		ahead += PAGE_CACHE_SIZE;
 		if ((raend + ahead) >= inode->i_size)
 			break;
-		page_cache_read(filp, raend + ahead);
+		page_cache_read(filp, (raend + ahead) >> PAGE_CACHE_SHIFT);
 	}
 /*
  * If we tried to read ahead some pages,
@@ -945,15 +947,17 @@
 {
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
-	size_t pos, pgpos;
+	unsigned long pos, pgpos;
 	struct page *cached_page;
 	int reada_ok;
 	int error;
 	int max_readahead = get_max_readahead(inode);
+	unsigned long pgoff;
 
 	cached_page = NULL;
 	pos = *ppos;
 	pgpos = pos & PAGE_CACHE_MASK;
+	pgoff = pos >> PAGE_CACHE_SHIFT;
 /*
  * If the current position is outside the previous read-ahead window, 
  * we reset the current read-ahead context and set read ahead max to zero
@@ -1002,10 +1006,10 @@
 		/*
 		 * Try to find the data in the page cache..
 		 */
-		hash = page_hash(&inode->i_data, pos & PAGE_CACHE_MASK);
+		hash = page_hash(&inode->i_data, pgoff);
 
 		spin_lock(&pagecache_lock);
-		page = __find_page_nolock(&inode->i_data, pos & PAGE_CACHE_MASK, *hash);
+		page = __find_page_nolock(&inode->i_data, pgoff, *hash);
 		if (!page)
 			goto no_cached_page;
 found_page:
@@ -1036,6 +1040,7 @@
 		 */
 		nr = actor(desc, page, offset, nr);
 		pos += nr;
+		pgoff = pos >> PAGE_CACHE_SHIFT;
 		page_cache_release(page);
 		if (nr && desc->count)
 			continue;
@@ -1047,7 +1052,7 @@
  */
 page_not_up_to_date:
 		generic_file_readahead(reada_ok, filp, inode,
-						pos & PAGE_CACHE_MASK, page);
+					pos & PAGE_CACHE_MASK, page);
 
 		if (Page_Uptodate(page))
 			goto page_ok;
@@ -1101,7 +1106,7 @@
 			 * dropped the page cache lock. Check for that.
 			 */
 			spin_lock(&pagecache_lock);
-			page = __find_page_nolock(&inode->i_data, pos & PAGE_CACHE_MASK, *hash);
+			page = __find_page_nolock(&inode->i_data, pgoff, *hash);
 			if (page)
 				goto found_page;
 		}
@@ -1110,7 +1115,7 @@
 		 * Ok, add the new page to the hash-queues...
 		 */
 		page = cached_page;
-		__add_to_page_cache(page, &inode->i_data, pos & PAGE_CACHE_MASK, hash);
+		__add_to_page_cache(page, &inode->i_data, pgoff, hash);
 		spin_unlock(&pagecache_lock);
 		cached_page = NULL;
 
@@ -1159,6 +1164,7 @@
 	retval = -EFAULT;
 	if (access_ok(VERIFY_WRITE, buf, count)) {
 		retval = 0;
+
 		if (count) {
 			read_descriptor_t desc;
 
@@ -1297,8 +1303,9 @@
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
 	struct page *page, **hash, *old_page;
+	unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
-	unsigned long offset = address - area->vm_start + area->vm_offset;
+	unsigned long pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
 
 	/*
 	 * Semantics for shared and private memory areas are different
@@ -1306,16 +1313,16 @@
 	 * of the file is an error and results in a SIGBUS, while a
 	 * private mapping just maps in a zero page.
 	 */
-	if ((offset >= inode->i_size) &&
+	if ((pgoff >= size) &&
 		(area->vm_flags & VM_SHARED) && (area->vm_mm == current->mm))
 		return NULL;
 
 	/*
 	 * Do we have something in the page cache already?
 	 */
-	hash = page_hash(&inode->i_data, offset);
+	hash = page_hash(&inode->i_data, pgoff);
 retry_find:
-	page = __find_get_page(&inode->i_data, offset, hash);
+	page = __find_get_page(&inode->i_data, pgoff, hash);
 	if (!page)
 		goto no_cached_page;
 
@@ -1356,10 +1363,10 @@
 	 * Otherwise, we're off the end of a privately mapped file,
 	 * so we need to map a zero page.
 	 */
-	if (offset < inode->i_size)
-		read_cluster_nonblocking(file, offset);
+	if (pgoff < size)
+		read_cluster_nonblocking(file, pgoff);
 	else
-		page_cache_read(file, offset);
+		page_cache_read(file, pgoff);
 
 	/*
 	 * The page we want has now been added to the page cache.
@@ -1418,7 +1425,7 @@
 	unsigned long size;
 	int (*writepage) (struct file *, struct page *);
 
-	size = offset + PAGE_SIZE;
+	size = (offset << PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE;
 	/* refuse to extend file size.. */
 	if (S_ISREG(inode->i_mode)) {
 		if (size > inode->i_size)
@@ -1427,7 +1434,6 @@
 		if (size < offset)
 			return -EIO;
 	}
-	size -= offset;
 	retval = -EIO;
 	writepage = inode->i_op->writepage;
 	lock_page(page);
@@ -1469,7 +1475,7 @@
 extern void wakeup_bdflush(int);
 int filemap_swapout(struct page * page, struct file * file)
 {
-	int retval = filemap_write_page(file, page->offset, page, 0);
+	int retval = filemap_write_page(file, page->index, page, 0);
 	wakeup_bdflush(0);
 	return retval;
 }
@@ -1477,6 +1483,7 @@
 static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
 	unsigned long address, unsigned int flags)
 {
+	unsigned long pgoff;
 	pte_t pte = *ptep;
 	struct page *page;
 	int error;
@@ -1499,7 +1506,7 @@
 		pte_clear(ptep);
 		flush_tlb_page(vma, address);
 		if (!pte_present(pte)) {
-			swap_free(pte);
+			swap_free(pte_to_swp_entry(pte));
 			return 0;
 		}
 		page = pte_page(pte);
@@ -1510,7 +1517,13 @@
 	}
 	if (PageHighMem(page))
 		BUG();
-	error = filemap_write_page(vma->vm_file, address - vma->vm_start + vma->vm_offset, page, 1);
+	pgoff = (address - vma->vm_start) >> PAGE_CACHE_SHIFT;
+	pgoff += vma->vm_pgoff;
+	if (page->index != pgoff) {
+		printk("weirdness: pgoff=%lu index=%lu address=%lu vm_start=%lu vm_pgoff=%lu\n",
+			pgoff, page->index, address, vma->vm_start, vma->vm_pgoff);
+	}
+	error = filemap_write_page(vma->vm_file, pgoff, page, 1);
 	page_cache_free(page);
 	return error;
 }
@@ -1805,20 +1818,21 @@
 	}
 
 	while (count) {
-		unsigned long bytes, pgpos, offset;
+		unsigned long bytes, pgoff, offset;
+
 		/*
 		 * Try to find the page in the cache. If it isn't there,
 		 * allocate a free page.
 		 */
-		offset = (pos & ~PAGE_CACHE_MASK);
-		pgpos = pos & PAGE_CACHE_MASK;
+		offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
+		pgoff = pos >> PAGE_CACHE_SHIFT;
 		bytes = PAGE_CACHE_SIZE - offset;
 		if (bytes > count)
 			bytes = count;
 
-		hash = page_hash(&inode->i_data, pgpos);
+		hash = page_hash(&inode->i_data, pgoff);
 repeat_find:
-		page = __find_lock_page(&inode->i_data, pgpos, hash);
+		page = __find_lock_page(&inode->i_data, pgoff, hash);
 		if (!page) {
 			if (!cached_page) {
 				cached_page = page_cache_alloc();
@@ -1828,7 +1842,7 @@
 				break;
 			}
 			page = cached_page;
-			if (add_to_page_cache_unique(page,&inode->i_data,pgpos,hash))
+			if (add_to_page_cache_unique(page,&inode->i_data,pgoff,hash))
 				goto repeat_find;
 
 			cached_page = NULL;
diff -u --recursive --new-file v2.3.24/linux/mm/highmem.c linux/mm/highmem.c
--- v2.3.24/linux/mm/highmem.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/highmem.c	Fri Oct 29 16:45:32 1999
@@ -68,8 +68,8 @@
 	kunmap(vaddr, KM_WRITE);
 
 	/* Preserve the caching of the swap_entry. */
-	highpage->offset = page->offset;
-	highpage->inode = page->inode;
+	highpage->index = page->index;
+	highpage->mapping = page->mapping;
 
 	/*
 	 * We can just forget the old page since 
diff -u --recursive --new-file v2.3.24/linux/mm/memory.c linux/mm/memory.c
--- v2.3.24/linux/mm/memory.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/memory.c	Thu Oct 28 16:08:20 1999
@@ -227,7 +227,7 @@
 				if (pte_none(pte))
 					goto cont_copy_pte_range;
 				if (!pte_present(pte)) {
-					swap_duplicate(pte);
+					swap_duplicate(pte_to_swp_entry(pte));
 					set_pte(dst_pte, pte);
 					goto cont_copy_pte_range;
 				}
@@ -282,7 +282,7 @@
 		free_page_and_swap_cache(mem_map+nr);
 		return 1;
 	}
-	swap_free(page);
+	swap_free(pte_to_swp_entry(page));
 	return 0;
 }
 
@@ -887,12 +887,19 @@
  */
 void vmtruncate(struct inode * inode, unsigned long offset)
 {
+	unsigned long partial, pgoff;
 	struct vm_area_struct * mpnt;
 
 	truncate_inode_pages(inode, offset);
 	spin_lock(&inode->i_shared_lock);
 	if (!inode->i_mmap)
 		goto out_unlock;
+
+	partial = offset & (PAGE_CACHE_SIZE - 1);
+	pgoff = offset >> PAGE_CACHE_SHIFT;
+	if (partial)
+		pgoff ++;
+
 	mpnt = inode->i_mmap;
 	do {
 		struct mm_struct *mm = mpnt->vm_mm;
@@ -902,19 +909,22 @@
 		unsigned long diff;
 
 		/* mapping wholly truncated? */
-		if (mpnt->vm_offset >= offset) {
+		if (mpnt->vm_pgoff >= pgoff) {
 			flush_cache_range(mm, start, end);
 			zap_page_range(mm, start, len);
 			flush_tlb_range(mm, start, end);
 			continue;
 		}
+
 		/* mapping wholly unaffected? */
-		diff = offset - mpnt->vm_offset;
+		len = len >> PAGE_SHIFT;
+		diff = pgoff - mpnt->vm_pgoff;
 		if (diff >= len)
 			continue;
+
 		/* Ok, partially affected.. */
-		start += diff;
-		len = (len - diff) & PAGE_MASK;
+		start += diff << PAGE_SHIFT;
+		len = (len - diff) << PAGE_SHIFT;
 		if (start & ~PAGE_MASK) {
 			partial_clear(mpnt, start);
 			start = (start + ~PAGE_MASK) & PAGE_MASK;
@@ -935,7 +945,7 @@
  * because it doesn't cost us any seek time.  We also make sure to queue
  * the 'original' request together with the readahead ones...  
  */
-void swapin_readahead(pte_t entry)
+void swapin_readahead(swp_entry_t entry)
 {
 	int i;
 	struct page *new_page;
@@ -969,7 +979,7 @@
 
 static int do_swap_page(struct task_struct * tsk,
 	struct vm_area_struct * vma, unsigned long address,
-	pte_t * page_table, pte_t entry, int write_access)
+	pte_t * page_table, swp_entry_t entry, int write_access)
 {
 	struct page *page = lookup_swap_cache(entry);
 	pte_t pte;
@@ -1116,7 +1126,7 @@
 	if (!pte_present(entry)) {
 		if (pte_none(entry))
 			return do_no_page(tsk, vma, address, write_access, pte);
-		return do_swap_page(tsk, vma, address, pte, entry, write_access);
+		return do_swap_page(tsk, vma, address, pte, pte_to_swp_entry(entry), write_access);
 	}
 
 	/*
diff -u --recursive --new-file v2.3.24/linux/mm/mlock.c linux/mm/mlock.c
--- v2.3.24/linux/mm/mlock.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/mlock.c	Thu Oct 28 13:03:38 1999
@@ -7,6 +7,7 @@
 #include <linux/shm.h>
 #include <linux/mman.h>
 #include <linux/smp_lock.h>
+#include <linux/pagemap.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -35,7 +36,7 @@
 	if (n->vm_ops && n->vm_ops->open)
 		n->vm_ops->open(n);
 	vmlist_modify_lock(vma->vm_mm);
-	vma->vm_offset += end - vma->vm_start;
+	vma->vm_pgoff += (end - vma->vm_start) >> PAGE_SHIFT;
 	vma->vm_start = end;
 	insert_vm_struct(current->mm, n);
 	vmlist_modify_unlock(vma->vm_mm);
@@ -52,7 +53,7 @@
 		return -EAGAIN;
 	*n = *vma;
 	n->vm_start = start;
-	n->vm_offset += n->vm_start - vma->vm_start;
+	n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT;
 	n->vm_flags = newflags;
 	if (n->vm_file)
 		get_file(n->vm_file);
@@ -82,7 +83,7 @@
 	*right = *vma;
 	left->vm_end = start;
 	right->vm_start = end;
-	right->vm_offset += right->vm_start - left->vm_start;
+	right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT;
 	vma->vm_flags = newflags;
 	if (vma->vm_file)
 		atomic_add(2, &vma->vm_file->f_count);
@@ -92,7 +93,7 @@
 		vma->vm_ops->open(right);
 	}
 	vmlist_modify_lock(vma->vm_mm);
-	vma->vm_offset += start - vma->vm_start;
+	vma->vm_pgoff += (start - vma->vm_start) >> PAGE_SHIFT;
 	vma->vm_start = start;
 	vma->vm_end = end;
 	vma->vm_flags = newflags;
diff -u --recursive --new-file v2.3.24/linux/mm/mmap.c linux/mm/mmap.c
--- v2.3.24/linux/mm/mmap.c	Wed Oct 27 16:34:12 1999
+++ linux/mm/mmap.c	Thu Oct 28 13:03:38 1999
@@ -183,6 +183,8 @@
 	if (off + len < off)
 		return -EINVAL;
 
+	off = off >> PAGE_SHIFT;
+
 	/* Too many mappings? */
 	if (mm->map_count > MAX_MAP_COUNT)
 		return -ENOMEM;
@@ -272,7 +274,7 @@
 		vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
 	vma->vm_ops = NULL;
-	vma->vm_offset = off;
+	vma->vm_pgoff = off;
 	vma->vm_file = NULL;
 	vma->vm_private_data = NULL;
 
@@ -533,7 +535,7 @@
 		area->vm_end = addr;
 		vmlist_modify_lock(current->mm);
 	} else if (addr == area->vm_start) {
-		area->vm_offset += (end - area->vm_start);
+		area->vm_pgoff += (end - area->vm_start) >> PAGE_SHIFT;
 		area->vm_start = end;
 		vmlist_modify_lock(current->mm);
 	} else {
@@ -548,7 +550,8 @@
 		mpnt->vm_page_prot = area->vm_page_prot;
 		mpnt->vm_flags = area->vm_flags;
 		mpnt->vm_ops = area->vm_ops;
-		mpnt->vm_offset = area->vm_offset + (end - area->vm_start);
+		mpnt->vm_pgoff = area->vm_pgoff;
+		area->vm_pgoff += (end - area->vm_start) >> PAGE_SHIFT;
 		mpnt->vm_file = area->vm_file;
 		mpnt->vm_private_data = area->vm_private_data;
 		if (mpnt->vm_file)
@@ -783,7 +786,7 @@
 	vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
 	vma->vm_ops = NULL;
-	vma->vm_offset = 0;
+	vma->vm_pgoff = 0;
 	vma->vm_file = NULL;
 	vma->vm_private_data = NULL;
 
@@ -943,8 +946,9 @@
 		 * the offsets must be contiguous..
 		 */
 		if ((mpnt->vm_file != NULL) || (mpnt->vm_flags & VM_SHM)) {
-			unsigned long off = prev->vm_offset+prev->vm_end-prev->vm_start;
-			if (off != mpnt->vm_offset)
+			unsigned long off = prev->vm_pgoff;
+			off += (prev->vm_end - prev->vm_start) >> PAGE_SHIFT;
+			if (off != mpnt->vm_pgoff)
 				continue;
 		}
 
@@ -957,7 +961,7 @@
 		prev->vm_end = mpnt->vm_end;
 		prev->vm_next = mpnt->vm_next;
 		if (mpnt->vm_ops && mpnt->vm_ops->close) {
-			mpnt->vm_offset += mpnt->vm_end - mpnt->vm_start;
+			mpnt->vm_pgoff += (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
 			mpnt->vm_start = mpnt->vm_end;
 			vmlist_modify_unlock(mm);
 			mpnt->vm_ops->close(mpnt);
diff -u --recursive --new-file v2.3.24/linux/mm/mprotect.c linux/mm/mprotect.c
--- v2.3.24/linux/mm/mprotect.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/mprotect.c	Thu Oct 28 16:50:03 1999
@@ -72,11 +72,13 @@
 	flush_cache_range(current->mm, beg, end);
 	if (start >= end)
 		BUG();
+	spin_lock(&current->mm->page_table_lock);
 	do {
 		change_pmd_range(dir, start, end - start, newprot);
 		start = (start + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (start && (start < end));
+	spin_unlock(&current->mm->page_table_lock);
 	flush_tlb_range(current->mm, beg, end);
 	return;
 }
@@ -109,7 +111,7 @@
 	if (n->vm_ops && n->vm_ops->open)
 		n->vm_ops->open(n);
 	vmlist_modify_lock(vma->vm_mm);
-	vma->vm_offset += end - vma->vm_start;
+	vma->vm_pgoff += (end - vma->vm_start) >> PAGE_SHIFT;
 	vma->vm_start = end;
 	insert_vm_struct(current->mm, n);
 	vmlist_modify_unlock(vma->vm_mm);
@@ -127,7 +129,7 @@
 		return -ENOMEM;
 	*n = *vma;
 	n->vm_start = start;
-	n->vm_offset += n->vm_start - vma->vm_start;
+	n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT;
 	n->vm_flags = newflags;
 	n->vm_page_prot = prot;
 	if (n->vm_file)
@@ -159,7 +161,7 @@
 	*right = *vma;
 	left->vm_end = start;
 	right->vm_start = end;
-	right->vm_offset += right->vm_start - left->vm_start;
+	right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT;
 	if (vma->vm_file)
 		atomic_add(2,&vma->vm_file->f_count);
 	if (vma->vm_ops && vma->vm_ops->open) {
@@ -167,7 +169,7 @@
 		vma->vm_ops->open(right);
 	}
 	vmlist_modify_lock(vma->vm_mm);
-	vma->vm_offset += start - vma->vm_start;
+	vma->vm_pgoff += (start - vma->vm_start) >> PAGE_SHIFT;
 	vma->vm_start = start;
 	vma->vm_end = end;
 	vma->vm_flags = newflags;
diff -u --recursive --new-file v2.3.24/linux/mm/mremap.c linux/mm/mremap.c
--- v2.3.24/linux/mm/mremap.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/mremap.c	Thu Oct 28 16:50:03 1999
@@ -93,7 +93,6 @@
 	unsigned long offset = len;
 
 	flush_cache_range(mm, old_addr, old_addr + len);
-	flush_tlb_range(mm, old_addr, old_addr + len);
 
 	/*
 	 * This is not the clever way to do this, but we're taking the
@@ -105,6 +104,7 @@
 		if (move_one_page(mm, old_addr + offset, new_addr + offset))
 			goto oops_we_failed;
 	}
+	flush_tlb_range(mm, old_addr, old_addr + len);
 	return 0;
 
 	/*
@@ -136,7 +136,8 @@
 			*new_vma = *vma;
 			new_vma->vm_start = new_addr;
 			new_vma->vm_end = new_addr+new_len;
-			new_vma->vm_offset = vma->vm_offset + (addr - vma->vm_start);
+			new_vma->vm_pgoff = vma->vm_pgoff;
+			new_vma->vm_pgoff += (addr - vma->vm_start) >> PAGE_SHIFT;
 			if (new_vma->vm_file)
 				get_file(new_vma->vm_file);
 			if (new_vma->vm_ops && new_vma->vm_ops->open)
diff -u --recursive --new-file v2.3.24/linux/mm/page_io.c linux/mm/page_io.c
--- v2.3.24/linux/mm/page_io.c	Wed Oct 27 16:34:12 1999
+++ linux/mm/page_io.c	Fri Oct 29 16:45:32 1999
@@ -33,7 +33,7 @@
  * that shared pages stay shared while being swapped.
  */
 
-static int rw_swap_page_base(int rw, pte_t entry, struct page *page, int wait)
+static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page, int wait)
 {
 	unsigned long type, offset;
 	struct swap_info_struct * p;
@@ -59,7 +59,7 @@
 		return 0;
 	}
 	if (p->swap_map && !p->swap_map[offset]) {
-		pte_ERROR(entry);
+		printk("VM: Bad swap entry %08lx\n", entry.val);
 		return 0;
 	}
 	if (!(p->flags & SWP_USED)) {
@@ -130,7 +130,9 @@
  */
 void rw_swap_page(int rw, struct page *page, int wait)
 {
-	pte_t entry = get_pagecache_pte(page);
+	swp_entry_t entry;
+
+	entry.val = page->index;
 
 	if (!PageLocked(page))
 		PAGE_BUG(page);
@@ -147,7 +149,7 @@
  * Therefore we can't use it.  Later when we can remove the need for the
  * lock map and we can reduce the number of functions exported.
  */
-void rw_swap_page_nolock(int rw, pte_t entry, char *buf, int wait)
+void rw_swap_page_nolock(int rw, swp_entry_t entry, char *buf, int wait)
 {
 	struct page *page = mem_map + MAP_NR(buf);
 	
diff -u --recursive --new-file v2.3.24/linux/mm/slab.c linux/mm/slab.c
--- v2.3.24/linux/mm/slab.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/slab.c	Thu Oct 28 10:16:02 1999
@@ -110,7 +110,7 @@
 /* If there is a different PAGE_SIZE around, and it works with this allocator,
  * then change the following.
  */
-#if	(PAGE_SIZE != 8192 && PAGE_SIZE != 4096)
+#if	(PAGE_SIZE != 8192 && PAGE_SIZE != 4096 && PAGE_SIZE != 32768)
 #error	Your page size is probably not correctly supported - please check
 #endif
 
diff -u --recursive --new-file v2.3.24/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.3.24/linux/mm/swap_state.c	Wed Oct 27 16:34:12 1999
+++ linux/mm/swap_state.c	Fri Oct 29 16:45:32 1999
@@ -40,7 +40,7 @@
 }
 #endif
 
-void add_to_swap_cache(struct page *page, pte_t entry)
+void add_to_swap_cache(struct page *page, swp_entry_t entry)
 {
 #ifdef SWAP_CACHE_INFO
 	swap_cache_add_total++;
@@ -49,7 +49,7 @@
 		BUG();
 	if (page->mapping)
 		BUG();
-	add_to_page_cache(page, &swapper_space, pte_val(entry));
+	add_to_page_cache(page, &swapper_space, entry.val);
 }
 
 /*
@@ -58,13 +58,14 @@
  * Note: if swap_map[] reaches SWAP_MAP_MAX the entries are treated as
  * "permanent", but will be reclaimed by the next swapoff.
  */
-int swap_duplicate(pte_t entry)
+int swap_duplicate(swp_entry_t entry)
 {
 	struct swap_info_struct * p;
 	unsigned long offset, type;
 	int result = 0;
 
-	if (!pte_val(entry))
+	/* Swap entry 0 is illegal */
+	if (!entry.val)
 		goto out;
 	type = SWP_TYPE(entry);
 	if (type & SHM_SWP_TYPE)
@@ -85,7 +86,7 @@
 	else {
 		static int overflow = 0;
 		if (overflow++ < 5)
-			pte_ERROR(entry);
+			printk("VM: swap entry overflow\n");
 		p->swap_map[offset] = SWAP_MAP_MAX;
 	}
 	result = 1;
@@ -93,13 +94,13 @@
 	return result;
 
 bad_file:
-	pte_ERROR(entry);
+	printk("Bad swap file entry %08lx\n", entry.val);
 	goto out;
 bad_offset:
-	pte_ERROR(entry);
+	printk("Bad swap offset entry %08lx\n", entry.val);
 	goto out;
 bad_unused:
-	pte_ERROR(entry);
+	printk("Unused swap offset entry %08lx\n", entry.val);
 	goto out;
 }
 
@@ -107,10 +108,11 @@
 {
 	struct swap_info_struct * p;
 	unsigned long offset, type;
-	pte_t entry = get_pagecache_pte(page);
+	swp_entry_t entry;
 	int retval = 0;
 
-	if (!pte_val(entry))
+	entry.val = page->index;
+	if (!entry.val)
 		goto bad_entry;
 	type = SWP_TYPE(entry);
 	if (type & SHM_SWP_TYPE)
@@ -131,13 +133,13 @@
 	printk(KERN_ERR "swap_count: null entry!\n");
 	goto out;
 bad_file:
-	pte_ERROR(entry);
+	printk("Bad swap file entry %08lx\n", entry.val);
 	goto out;
 bad_offset:
-	pte_ERROR(entry);
+	printk("Bad swap offset entry %08lx\n", entry.val);
 	goto out;
 bad_unused:
-	pte_ERROR(entry);
+	printk("Unused swap offset entry %08lx\n", entry.val);
 	goto out;
 }
 
@@ -160,7 +162,9 @@
  */
 void __delete_from_swap_cache(struct page *page)
 {
-	pte_t entry = get_pagecache_pte(page);
+	swp_entry_t entry;
+
+	entry.val = page->index;
 
 #ifdef SWAP_CACHE_INFO
 	swap_cache_del_total++;
@@ -223,7 +227,7 @@
  * lock before returning.
  */
 
-struct page * lookup_swap_cache(pte_t entry)
+struct page * lookup_swap_cache(swp_entry_t entry)
 {
 	struct page *found;
 
@@ -232,9 +236,9 @@
 #endif
 	while (1) {
 		/*
-		 * Right now the pagecache is 32-bit only.
+		 * Right now the pagecache is 32-bit only.  But it's a 32 bit index. =)
 		 */
-		found = find_lock_page(&swapper_space, pte_val(entry));
+		found = find_lock_page(&swapper_space, entry.val);
 		if (!found)
 			return 0;
 		if (found->mapping != &swapper_space || !PageSwapCache(found))
@@ -262,7 +266,7 @@
  * the swap entry is no longer in use.
  */
 
-struct page * read_swap_cache_async(pte_t entry, int wait)
+struct page * read_swap_cache_async(swp_entry_t entry, int wait)
 {
 	struct page *found_page = 0, *new_page;
 	unsigned long new_page_addr;
diff -u --recursive --new-file v2.3.24/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.3.24/linux/mm/swapfile.c	Wed Oct 27 16:34:12 1999
+++ linux/mm/swapfile.c	Mon Nov  1 10:19:46 1999
@@ -81,13 +81,14 @@
 	return 0;
 }
 
-pte_t get_swap_page(void)
+swp_entry_t get_swap_page(void)
 {
 	struct swap_info_struct * p;
 	unsigned long offset;
-	pte_t entry = __pte(0);
+	swp_entry_t entry;
 	int type, wrapped = 0;
 
+	entry.val = 0;	/* Out of memory */
 	type = swap_list.next;
 	if (type < 0)
 		goto out;
@@ -125,12 +126,12 @@
 }
 
 
-void swap_free(pte_t entry)
+void swap_free(swp_entry_t entry)
 {
 	struct swap_info_struct * p;
 	unsigned long offset, type;
 
-	if (!pte_val(entry))
+	if (!entry.val)
 		goto out;
 
 	type = SWP_TYPE(entry);
@@ -170,24 +171,24 @@
 	printk("swap_free: offset exceeds max\n");
 	goto out;
 bad_free:
-	pte_ERROR(entry);
+	printk("VM: Bad swap entry %08lx\n", entry.val);
 	goto out;
 }
 
 /* needs the big kernel lock */
-pte_t acquire_swap_entry(struct page *page)
+swp_entry_t acquire_swap_entry(struct page *page)
 {
 	struct swap_info_struct * p;
 	unsigned long offset, type;
-	pte_t entry;
+	swp_entry_t entry;
 
 	if (!test_bit(PG_swap_entry, &page->flags))
 		goto new_swap_entry;
 
 	/* We have the old entry in the page offset still */
-	if (!page->offset)
+	if (!page->index)
 		goto new_swap_entry;
-	entry = get_pagecache_pte(page);
+	entry.val = page->index;
 	type = SWP_TYPE(entry);
 	if (type & SHM_SWP_TYPE)
 		goto new_swap_entry;
@@ -222,7 +223,7 @@
  * what to do if a write is requested later.
  */
 static inline void unuse_pte(struct vm_area_struct * vma, unsigned long address,
-	pte_t *dir, pte_t entry, struct page* page)
+	pte_t *dir, swp_entry_t entry, struct page* page)
 {
 	pte_t pte = *dir;
 
@@ -238,17 +239,17 @@
 		set_pte(dir, pte_mkdirty(pte));
 		return;
 	}
-	if (pte_val(pte) != pte_val(entry))
+	if (pte_val(pte) != entry.val)
 		return;
 	set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 	swap_free(entry);
-	get_page(mem_map + MAP_NR(page));
+	get_page(page);
 	++vma->vm_mm->rss;
 }
 
 static inline void unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
 	unsigned long address, unsigned long size, unsigned long offset,
-	pte_t entry, struct page* page)
+	swp_entry_t entry, struct page* page)
 {
 	pte_t * pte;
 	unsigned long end;
@@ -275,7 +276,7 @@
 
 static inline void unuse_pgd(struct vm_area_struct * vma, pgd_t *dir,
 	unsigned long address, unsigned long size,
-	pte_t entry, struct page* page)
+	swp_entry_t entry, struct page* page)
 {
 	pmd_t * pmd;
 	unsigned long offset, end;
@@ -304,7 +305,7 @@
 }
 
 static void unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir,
-			pte_t entry, struct page* page)
+			swp_entry_t entry, struct page* page)
 {
 	unsigned long start = vma->vm_start, end = vma->vm_end;
 
@@ -318,7 +319,7 @@
 }
 
 static void unuse_process(struct mm_struct * mm,
-			pte_t entry, struct page* page)
+			swp_entry_t entry, struct page* page)
 {
 	struct vm_area_struct* vma;
 
@@ -344,7 +345,7 @@
 	struct swap_info_struct * si = &swap_info[type];
 	struct task_struct *p;
 	struct page *page;
-	pte_t entry;
+	swp_entry_t entry;
 	int i;
 
 	while (1) {
@@ -388,7 +389,7 @@
 		 */
 		if (si->swap_map[i] != 0) {
 			if (si->swap_map[i] != SWAP_MAP_MAX)
-				pte_ERROR(entry);
+				printk("VM: Undead swap entry %08lx\n", entry.val);
 			si->swap_map[i] = 0;
 			nr_swap_pages++;
 		}
diff -u --recursive --new-file v2.3.24/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.24/linux/mm/vmscan.c	Wed Oct 27 16:34:12 1999
+++ linux/mm/vmscan.c	Fri Oct 29 16:45:32 1999
@@ -35,7 +35,8 @@
  */
 static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table, int gfp_mask)
 {
-	pte_t pte, entry;
+	pte_t pte;
+	swp_entry_t entry;
 	struct page * page;
 	int (*swapout)(struct page *, struct file *);
 
@@ -72,9 +73,9 @@
 	 * memory, and we should just continue our scan.
 	 */
 	if (PageSwapCache(page)) {
-		entry = get_pagecache_pte(page);
+		entry.val = page->index;
 		swap_duplicate(entry);
-		set_pte(page_table, entry);
+		set_pte(page_table, swp_entry_to_pte(entry));
 drop_pte:
 		vma->vm_mm->rss--;
 		flush_tlb_page(vma, address);
@@ -151,14 +152,14 @@
 	 * page with that swap entry.
 	 */
 	entry = acquire_swap_entry(page);
-	if (!pte_val(entry))
+	if (!entry.val)
 		goto out_failed; /* No swap space left */
 		
 	if (!(page = prepare_highmem_swapout(page)))
 		goto out_swap_free;
 
 	vma->vm_mm->rss--;
-	set_pte(page_table, entry);
+	set_pte(page_table, swp_entry_to_pte(entry));
 	vmlist_access_unlock(vma->vm_mm);
 
 	flush_tlb_page(vma, address);
diff -u --recursive --new-file v2.3.24/linux/net/802/tr.c linux/net/802/tr.c
--- v2.3.24/linux/net/802/tr.c	Thu Aug 26 13:05:42 1999
+++ linux/net/802/tr.c	Thu Oct 28 14:34:44 1999
@@ -447,7 +447,9 @@
  *	routing.
  */
  
-#ifdef CONFIG_PROC_FS
+#ifndef CONFIG_PROC_FS
+int rif_get_info(char *buffer,char **start, off_t offset, int length, int dummy)  {}
+#else
 int rif_get_info(char *buffer,char **start, off_t offset, int length, int dummy) 
 {
 	int len=0;
@@ -529,15 +531,6 @@
  *	too much for this.
  */
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry tr_rif_proc = {
-	PROC_NET_TR_RIF, 6, "tr_rif",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	rif_get_info
-};
-#endif
-
 void __init rif_init(struct net_proto *unused)
 {
 	rif_timer.expires  = RIF_TIMEOUT;
@@ -546,7 +539,5 @@
 	init_timer(&rif_timer);
 	add_timer(&rif_timer);
 
-#ifdef CONFIG_PROC_FS
-	proc_net_register(&tr_rif_proc);
-#endif
+	proc_net_create("tr_rif",0,rif_get_info);
 }
diff -u --recursive --new-file v2.3.24/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c
--- v2.3.24/linux/net/appletalk/aarp.c	Thu Aug 26 13:05:42 1999
+++ linux/net/appletalk/aarp.c	Thu Oct 28 14:34:44 1999
@@ -1159,22 +1159,14 @@
 
 #ifdef CONFIG_PROC_FS
 
-static struct proc_dir_entry proc_aarp_entries=
-{
-	PROC_NET_AT_AARP, 4, "aarp",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	aarp_get_info
-};
-
 void aarp_register_proc_fs(void)
 {
-	proc_net_register(&proc_aarp_entries);
+	proc_net_create("aarp", 0, aarp_get_info);
 }
 
 void aarp_unregister_proc_fs(void)
 {
-	proc_net_unregister(PROC_NET_AT_AARP);
+	proc_net_remove("aarp");
 }
 
 #endif
diff -u --recursive --new-file v2.3.24/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.3.24/linux/net/appletalk/ddp.c	Tue Sep  7 12:14:07 1999
+++ linux/net/appletalk/ddp.c	Thu Oct 28 14:34:44 1999
@@ -2069,32 +2069,6 @@
 EXPORT_SYMBOL(atrtr_get_dev);
 EXPORT_SYMBOL(atalk_find_dev_addr);
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_appletalk=
-{
-	PROC_NET_ATALK, 9, "appletalk",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	atalk_get_info
-};
-
-static struct proc_dir_entry proc_atalk_route=
-{
-	PROC_NET_AT_ROUTE, 11,"atalk_route",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	atalk_rt_get_info
-};
-
-static struct proc_dir_entry proc_atalk_iface=
-{
-	PROC_NET_ATIF, 11,"atalk_iface",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	atalk_if_get_info
-};
-#endif /* CONFIG_PROC_FS */
-
 /* Called by proto.c on kernel start up */
 
 void __init atalk_proto_init(struct net_proto *pro)
@@ -2113,9 +2087,9 @@
 	aarp_proto_init();
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_appletalk);
-	proc_net_register(&proc_atalk_route);
-	proc_net_register(&proc_atalk_iface);
+	proc_net_create("appletalk", 0, atalk_get_info);
+	proc_net_create("atalk_route", 0, atalk_rt_get_info);
+	proc_net_create("atalk_iface", 0, atalk_if_get_info);
 
 	aarp_register_proc_fs();
 #endif /* CONFIG_PROC_FS */
@@ -2155,9 +2129,9 @@
 #endif /* CONFIG_SYSCTL */
 
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_ATALK);
-	proc_net_unregister(PROC_NET_AT_ROUTE);
-	proc_net_unregister(PROC_NET_ATIF);
+	proc_net_remove("appletalk");
+	proc_net_remove("atalk_route");
+	proc_net_remove("atalk_iface");
 
 	aarp_unregister_proc_fs();
 #endif /* CONFIG_PROC_FS */
diff -u --recursive --new-file v2.3.24/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.3.24/linux/net/ax25/af_ax25.c	Thu Aug 26 13:05:43 1999
+++ linux/net/ax25/af_ax25.c	Thu Oct 28 14:34:44 1999
@@ -1766,27 +1766,6 @@
 EXPORT_SYMBOL(null_ax25_address);
 EXPORT_SYMBOL(ax25_display_timer);
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_ax25_route = {
-	PROC_NET_AX25_ROUTE, 10, "ax25_route",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	ax25_rt_get_info
-};
-static struct proc_dir_entry proc_ax25 = {
-	PROC_NET_AX25, 4, "ax25",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	ax25_get_info
-};
-static struct proc_dir_entry proc_ax25_calls = {
-	PROC_NET_AX25_CALLS, 10, "ax25_calls",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	ax25_uid_get_info
-};
-#endif
-
 void __init ax25_proto_init(struct net_proto *pro)
 {
 	sock_register(&ax25_family_ops);
@@ -1798,9 +1777,9 @@
 #endif
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_ax25_route);
-	proc_net_register(&proc_ax25);
-	proc_net_register(&proc_ax25_calls);
+	proc_net_create("ax25_route", 0, ax25_rt_get_info);
+	proc_net_create("ax25", 0, ax25_get_info);
+	proc_net_create("ax25_calls", 0, ax25_uid_get_info);
 #endif
 
 	printk(KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n");
@@ -1820,10 +1799,9 @@
 void cleanup_module(void)
 {
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_AX25_ROUTE);
-	proc_net_unregister(PROC_NET_AX25);
-	proc_net_unregister(PROC_NET_AX25_CALLS);
-	proc_net_unregister(PROC_NET_AX25_ROUTE);
+	proc_net_remove("ax25_route");
+	proc_net_remove("ax25");
+	proc_net_remove("ax25_calls");
 #endif
 	ax25_rt_free();
 	ax25_uid_free();
diff -u --recursive --new-file v2.3.24/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.3.24/linux/net/bridge/br.c	Tue Aug 31 17:29:15 1999
+++ linux/net/bridge/br.c	Thu Oct 28 14:34:44 1999
@@ -831,14 +831,6 @@
 
 	return len;
 }
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry proc_net_bridge= {
-	PROC_NET_BRIDGE, 6, "bridge",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	br_tree_get_info
-};
-#endif
 void __init br_init(void)
 {						  /* (4.8.1)	 */
 	int port_no;
@@ -895,9 +887,7 @@
 	br_stats.exempt_protocols = 0;
 	/*start_hello_timer();*/
 	/* Vova Oksman: register the function for the PROCfs "bridge" file */
-#ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_bridge);
-#endif
+	proc_net_create("bridge", 0, br_tree_get_info);
 }
 
 static inline unsigned short make_port_id(int port_no)
diff -u --recursive --new-file v2.3.24/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.24/linux/net/core/dev.c	Wed Oct 27 16:34:12 1999
+++ linux/net/core/dev.c	Thu Oct 28 14:34:44 1999
@@ -2008,26 +2008,6 @@
 extern int cpm_enet_init(void);
 #endif /* CONFIG_8xx */
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_dev = {
-	PROC_NET_DEV, 3, "dev",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	dev_get_info
-};
-#endif
-
-#ifdef CONFIG_NET_RADIO
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_wireless = {
-	PROC_NET_WIRELESS, 8, "wireless",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	dev_get_wireless_info
-};
-#endif	/* CONFIG_PROC_FS */
-#endif	/* CONFIG_NET_RADIO */
-
 int __init net_dev_init(void)
 {
 	struct net_device *dev, **dp;
@@ -2142,18 +2122,12 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_dev);
-	{
-		struct proc_dir_entry *ent = create_proc_entry("net/dev_stat", 0, 0);
-		ent->read_proc = dev_proc_stats;
-	}
-#endif
-
+	proc_net_create("dev", 0, dev_get_info);
+	create_proc_read_entry("net/dev_stat", 0, 0, dev_proc_stats, NULL);
 #ifdef CONFIG_NET_RADIO
-#ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_wireless);
-#endif	/* CONFIG_PROC_FS */
+	proc_net_create("wireless", 0, dev_get_wireless_info);
 #endif	/* CONFIG_NET_RADIO */
+#endif	/* CONFIG_PROC_FS */
 
 	init_bh(NET_BH, net_bh);
 
diff -u --recursive --new-file v2.3.24/linux/net/core/dev_mcast.c linux/net/core/dev_mcast.c
--- v2.3.24/linux/net/core/dev_mcast.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/dev_mcast.c	Thu Oct 28 14:34:44 1999
@@ -258,10 +258,7 @@
 void __init dev_mcast_init(void)
 {
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-
-	ent = create_proc_entry("net/dev_mcast", 0, 0);
-	ent->read_proc = dev_mc_read_proc;
+	create_proc_read_entry("net/dev_mcast", 0, 0, dev_mc_read_proc, NULL);
 #endif
 }
 
diff -u --recursive --new-file v2.3.24/linux/net/core/profile.c linux/net/core/profile.c
--- v2.3.24/linux/net/core/profile.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/profile.c	Thu Oct 28 14:34:44 1999
@@ -265,10 +265,7 @@
 	int i;
 
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-
-	ent = create_proc_entry("net/profile", 0, 0);
-	ent->read_proc = profile_read_proc;
+	create_proc_read_entry("net/profile", 0, 0, profile_read_proc, NULL);
 #endif
 
 	register_netdevice(&whitehole_dev);
diff -u --recursive --new-file v2.3.24/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- v2.3.24/linux/net/decnet/af_decnet.c	Tue Sep  7 12:14:07 1999
+++ linux/net/decnet/af_decnet.c	Thu Oct 28 14:34:44 1999
@@ -1980,8 +1980,6 @@
 	NULL,
 };
 
-#ifdef CONFIG_PROC_FS
-
 static int dn_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct sock *sk;
@@ -2036,22 +2034,11 @@
 	return len;
 }
 
-struct proc_dir_entry decnet_linkinfo = {
-	PROC_NET_DN_SKT, 6, "decnet", S_IFREG | S_IRUGO,
-	1, 0, 0, 0, &proc_net_inode_operations, dn_get_info
-};
-
 #ifdef CONFIG_DECNET_RAW
 
 extern int dn_raw_get_info(char *, char **, off_t, int, int);
 
-struct proc_dir_entry decnet_rawinfo = {
-	PROC_NET_DN_RAW, 10, "decnet_raw", S_IFREG | S_IRUGO,
-	1, 0, 0, 0, &proc_net_inode_operations, dn_raw_get_info
-};
-
 #endif /* CONFIG_DECNET_RAW */
-#endif /* CONFIG_PROC_FS */
 static struct net_proto_family	dn_family_ops = {
 	AF_DECnet,
 	dn_create
@@ -2089,11 +2076,9 @@
 	dev_add_pack(&dn_dix_packet_type);
 	register_netdevice_notifier(&dn_dev_notifier);
 
-#ifdef CONFIG_PROC_FS
-	proc_net_register(&decnet_linkinfo);
+	proc_net_create("decnet", 0, dn_get_info);
 #ifdef CONFIG_DECNET_RAW
-	proc_net_register(&decnet_rawinfo);
-#endif
+	proc_net_create("decnet_raw", 0, dn_raw_get_info);
 #endif
 	dn_dev_init();
 	dn_neigh_init();
@@ -2222,11 +2207,9 @@
 	dn_fib_cleanup();
 #endif /* CONFIG_DECNET_ROUTER */
 
-#ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_DN_SKT);
+	proc_net_remove("decnet");
 #ifdef CONFIG_DECNET_RAW
-	proc_net_unregister(PROC_NET_DN_RAW);
-#endif
+	proc_net_remove("decnet_raw");
 #endif
 
 	dev_remove_pack(&dn_dix_packet_type);
diff -u --recursive --new-file v2.3.24/linux/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c
--- v2.3.24/linux/net/decnet/dn_dev.c	Thu Aug 26 13:05:45 1999
+++ linux/net/decnet/dn_dev.c	Thu Oct 28 14:34:44 1999
@@ -1214,13 +1214,6 @@
         return(len);
 }
 
-static struct proc_dir_entry proc_net_decnet_dev = {
-        PROC_NET_DN_DEV, 10, "decnet_dev",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, &proc_net_inode_operations,
-        decnet_dev_get_info
-};
-
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_RTNETLINK
@@ -1271,7 +1264,7 @@
 #endif /* CONFIG_RTNETLINK */
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_decnet_dev);
+	proc_net_create("decnet_dev", 0, decnet_dev_get_info);
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SYSCTL
@@ -1303,7 +1296,7 @@
 #endif /* CONFIG_SYSCTL */
 
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_DN_DEV);
+	proc_net_remove("decnet_dev");
 #endif /* CONFIG_PROC_FS */
 
 	dn_dev_devices_off();
diff -u --recursive --new-file v2.3.24/linux/net/decnet/dn_fib.c linux/net/decnet/dn_fib.c
--- v2.3.24/linux/net/decnet/dn_fib.c	Fri Sep 10 23:57:38 1999
+++ linux/net/decnet/dn_fib.c	Thu Oct 28 14:34:44 1999
@@ -798,20 +798,13 @@
 	return pinfo.len;
 }
 
-static struct proc_dir_entry proc_net_decnet_route = {
-	PROC_NET_DN_ROUTE, 12, "decnet_route",
-	 S_IFREG | S_IRUGO, 1, 0, 0,
-        0, &proc_net_inode_operations,
-	decnet_rt_get_info
-};
-
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_DECNET_MODULE
 void dn_fib_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_DN_ROUTE);
+	proc_net_create("decnet_route",0,decnet_rt_get_info);
 #endif /* CONFIG_PROC_FS */
 }
 #endif /* CONFIG_DECNET_MODULE */
@@ -822,7 +815,7 @@
 	memset(dn_fib_tables, 0, DN_NUM_TABLES * sizeof(struct dn_fib_table *));
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_decnet_route);
+	proc_net_remove("decnet_route");
 #endif
 
 }
diff -u --recursive --new-file v2.3.24/linux/net/decnet/dn_neigh.c linux/net/decnet/dn_neigh.c
--- v2.3.24/linux/net/decnet/dn_neigh.c	Fri Sep 10 23:57:38 1999
+++ linux/net/decnet/dn_neigh.c	Thu Oct 28 14:34:44 1999
@@ -643,13 +643,6 @@
         return len;
 }
 
-static struct proc_dir_entry proc_net_dn_neigh = {
-        PROC_NET_DN_ADJ, 12, "decnet_neigh",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, &proc_net_inode_operations,
-        dn_neigh_get_info
-};
-
 #endif
 
 void __init dn_neigh_init(void)
@@ -657,7 +650,7 @@
 	neigh_table_init(&dn_neigh_table);
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_dn_neigh);
+	proc_net_create("decnet_neigh",0,dn_neigh_get_info);
 #endif /* CONFIG_PROC_FS */
 }
 
@@ -665,7 +658,7 @@
 void dn_neigh_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_DN_ADJ);
+	proc_net_remove("decnet_neigh");
 #endif /* CONFIG_PROC_FS */
 	neigh_table_clear(&dn_neigh_table);
 }
diff -u --recursive --new-file v2.3.24/linux/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- v2.3.24/linux/net/decnet/dn_route.c	Tue Aug 31 17:29:15 1999
+++ linux/net/decnet/dn_route.c	Thu Oct 28 14:34:44 1999
@@ -959,13 +959,6 @@
         return(len);
 } 
 
-static struct proc_dir_entry proc_net_decnet_cache = {
-        PROC_NET_DN_CACHE, 12, "decnet_cache",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, &proc_net_inode_operations,
-        decnet_cache_get_info
-};
-
 #endif /* CONFIG_PROC_FS */
 
 void __init dn_route_init(void)
@@ -982,7 +975,7 @@
 	add_timer(&dn_route_timer);
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_decnet_cache);
+	proc_net_create("decnet_cache",0,decnet_cache_get_info);
 #endif /* CONFIG_PROC_FS */
 }
 
@@ -992,7 +985,7 @@
 	del_timer(&dn_route_timer);
 	dn_run_flush(0);
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_DN_CACHE);
+	proc_net_remove("decnet_cache");
 #endif /* CONFIG_PROC_FS */
 }
 #endif /* CONFIG_DECNET_MODULE */
diff -u --recursive --new-file v2.3.24/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.3.24/linux/net/ipv4/af_inet.c	Fri Sep 10 23:57:38 1999
+++ linux/net/ipv4/af_inet.c	Thu Oct 28 14:34:44 1999
@@ -948,45 +948,6 @@
 };
 
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_raw = {
-	PROC_NET_RAW, 3, "raw",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	raw_get_info
-};
-static struct proc_dir_entry proc_net_netstat = {
-	PROC_NET_NETSTAT, 7, "netstat",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	netstat_get_info
-};
-static struct proc_dir_entry proc_net_snmp = {
-	PROC_NET_SNMP, 4, "snmp",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	snmp_get_info
-};
-static struct proc_dir_entry proc_net_sockstat = {
-	PROC_NET_SOCKSTAT, 8, "sockstat",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	afinet_get_info
-};
-static struct proc_dir_entry proc_net_tcp = {
-	PROC_NET_TCP, 3, "tcp",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	tcp_get_info
-};
-static struct proc_dir_entry proc_net_udp = {
-	PROC_NET_UDP, 3, "udp",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	udp_get_info
-};
-#endif		/* CONFIG_PROC_FS */
-
 extern void tcp_init(void);
 extern void tcp_v4_init(struct net_proto_family *);
 
@@ -1071,13 +1032,12 @@
 	/*
 	 *	Create all the /proc entries.
 	 */
-
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_raw);
-	proc_net_register(&proc_net_snmp);
-	proc_net_register(&proc_net_netstat);
-	proc_net_register(&proc_net_sockstat);
-	proc_net_register(&proc_net_tcp);
-	proc_net_register(&proc_net_udp);
+	proc_net_create ("raw", 0, raw_get_info);
+	proc_net_create ("netstat", 0, netstat_get_info);
+	proc_net_create ("snmp", 0, snmp_get_info);
+	proc_net_create ("sockstat", 0, afinet_get_info);
+	proc_net_create ("tcp", 0, tcp_get_info);
+	proc_net_create ("udp", 0, udp_get_info);
 #endif		/* CONFIG_PROC_FS */
 }
diff -u --recursive --new-file v2.3.24/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.3.24/linux/net/ipv4/arp.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv4/arp.c	Thu Oct 28 14:34:44 1999
@@ -980,11 +980,12 @@
 /*
  *	Write the contents of the ARP cache to a PROCfs file.
  */
-#ifdef CONFIG_PROC_FS
-
+#ifndef CONFIG_PROC_FS
+static int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy) { return 0; }
+#else
 #define HBUFFERLEN 30
 
-int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+static int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	int len=0;
 	off_t pos=0;
@@ -1116,24 +1117,14 @@
 	NULL
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_arp = {
-	PROC_NET_ARP, 3, "arp",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	arp_get_info
-};
-#endif
-
 void __init arp_init (void)
 {
 	neigh_table_init(&arp_tbl);
 
 	dev_add_pack(&arp_packet_type);
 
-#ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_arp);
-#endif
+	proc_net_create ("arp", 0, arp_get_info);
+
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
 #endif
diff -u --recursive --new-file v2.3.24/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.3.24/linux/net/ipv4/fib_frontend.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv4/fib_frontend.c	Thu Oct 28 14:34:44 1999
@@ -648,12 +648,7 @@
 void __init ip_fib_init(void)
 {
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_ROUTE, 5, "route",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		fib_get_procinfo
-	});
+	proc_net_create("route",0,fib_get_procinfo);
 #endif		/* CONFIG_PROC_FS */
 
 #ifndef CONFIG_IP_MULTIPLE_TABLES
diff -u --recursive --new-file v2.3.24/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.3.24/linux/net/ipv4/ip_output.c	Fri Sep 10 23:57:38 1999
+++ linux/net/ipv4/ip_output.c	Thu Oct 28 14:34:44 1999
@@ -1006,18 +1006,6 @@
 };
 
 
-
-#ifdef CONFIG_PROC_FS
-#ifdef CONFIG_IP_MULTICAST
-static struct proc_dir_entry proc_net_igmp = {
-	PROC_NET_IGMP, 4, "igmp",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	ip_mc_procinfo
-};
-#endif
-#endif	
-
 /*
  *	IP registers the packet type and then calls the subprotocol initialisers
  */
@@ -1028,10 +1016,8 @@
 
 	ip_rt_init();
 
-#ifdef CONFIG_PROC_FS
 #ifdef CONFIG_IP_MULTICAST
-	proc_net_register(&proc_net_igmp);
+	proc_net_create("igmp", S_IFREG | S_IRUGO, ip_mc_procinfo);
 #endif
-#endif	
 }
 
diff -u --recursive --new-file v2.3.24/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.3.24/linux/net/ipv4/ipmr.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv4/ipmr.c	Thu Oct 28 14:34:44 1999
@@ -1703,18 +1703,6 @@
 }
 
 #ifdef CONFIG_PROC_FS	
-static struct proc_dir_entry proc_net_ipmr_vif = {
-	PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	ipmr_vif_info
-};
-static struct proc_dir_entry proc_net_ipmr_mfc = {
-	PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	ipmr_mfc_info
-};
 #endif	
 
 #ifdef CONFIG_IP_PIMSM_V2
@@ -1746,7 +1734,7 @@
 	ipmr_expire_timer.function=ipmr_expire_process;
 	register_netdevice_notifier(&ip_mr_notifier);
 #ifdef CONFIG_PROC_FS	
-	proc_net_register(&proc_net_ipmr_vif);
-	proc_net_register(&proc_net_ipmr_mfc);
+	proc_net_create("ip_mr_vif",0,ipmr_vif_info);
+	proc_net_create("ip_mr_cache",0,ipmr_mfc_info);
 #endif	
 }
diff -u --recursive --new-file v2.3.24/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.3.24/linux/net/ipv4/route.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv4/route.c	Fri Oct 29 13:21:52 1999
@@ -201,8 +201,9 @@
 	return (hash^(hash>>8)) & 0xFF;
 }
 
-#ifdef CONFIG_PROC_FS
-
+#ifndef CONFIG_PROC_FS
+static int rt_cache_get_info(char *buffer, char **start, off_t offset, int length, int dummy) { return 0; }
+#else
 static int rt_cache_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	int len=0;
@@ -2147,11 +2148,6 @@
 
 void __init ip_rt_init(void)
 {
-#ifdef CONFIG_PROC_FS
-#ifdef CONFIG_NET_CLS_ROUTE
-	struct proc_dir_entry *ent;
-#endif
-#endif
 	ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",
 						     sizeof(struct rtable),
 						     0, SLAB_HWCACHE_ALIGN,
@@ -2167,16 +2163,8 @@
 		+ ip_rt_gc_interval;
 	add_timer(&rt_periodic_timer);
 
-#ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RTCACHE, 8, "rt_cache",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		rt_cache_get_info
-	});
+	proc_net_create ("rt_cache", 0, rt_cache_get_info);
 #ifdef CONFIG_NET_CLS_ROUTE
-	ent = create_proc_entry("net/rt_acct", 0, 0);
-	ent->read_proc = ip_rt_acct_read;
-#endif
+	create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL);
 #endif
 }
diff -u --recursive --new-file v2.3.24/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.3.24/linux/net/ipv6/addrconf.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv6/addrconf.c	Thu Oct 28 14:34:44 1999
@@ -1590,13 +1590,6 @@
 	return len;
 }
 
-struct proc_dir_entry iface_proc_entry =
-{
-        0, 8, "if_inet6",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, NULL,
-        &iface_proc_info
-};
 #endif	/* CONFIG_PROC_FS */
 
 /*
@@ -2008,7 +2001,7 @@
 #endif
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&iface_proc_entry);
+	proc_net_create("if_inet6", 0, iface_proc_info);
 #endif
 	
 	addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY;
@@ -2075,7 +2068,7 @@
 	rtnl_unlock();
 
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(iface_proc_entry.low_ino);
+	proc_net_remove("if_inet6");
 #endif
 }
 #endif	/* MODULE */
diff -u --recursive --new-file v2.3.24/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.3.24/linux/net/ipv6/af_inet6.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv6/af_inet6.c	Thu Oct 28 14:34:44 1999
@@ -459,39 +459,6 @@
 	inet6_create
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_raw6 = {
-	PROC_NET_RAW6, 4, "raw6",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	raw6_get_info
-};
-static struct proc_dir_entry proc_net_tcp6 = {
-	PROC_NET_TCP6, 4, "tcp6",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	tcp6_get_info
-};
-static struct proc_dir_entry proc_net_udp6 = {
-	PROC_NET_RAW6, 4, "udp6",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	udp6_get_info
-};
-static struct proc_dir_entry proc_net_sockstat6 = {
-	PROC_NET_SOCKSTAT6, 9, "sockstat6",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	afinet6_get_info
-};
-static struct proc_dir_entry proc_net_snmp6 = {
-	PROC_NET_SNMP6, 5, "snmp6",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	afinet6_get_snmp
-};
-#endif	/* CONFIG_PROC_FS */
-
 #ifdef MODULE
 int ipv6_unload(void)
 {
@@ -566,11 +533,11 @@
 
 	/* Create /proc/foo6 entries. */
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_raw6);
-	proc_net_register(&proc_net_tcp6);
-	proc_net_register(&proc_net_udp6);
-	proc_net_register(&proc_net_sockstat6);
-	proc_net_register(&proc_net_snmp6);
+	proc_net_create("raw6", 0, raw6_get_info);
+	proc_net_create("tcp6", 0, tcp6_get_info);
+	proc_net_create("udp6", 0, udp6_get_info);
+	proc_net_create("sockstat6", 0, afinet6_get_info);
+	proc_net_create("snmp6", 0, afinet6_get_snmp);
 #endif
 
 	/* Now the userspace is allowed to create INET6 sockets. */
@@ -603,11 +570,11 @@
 	/* First of all disallow new sockets creation. */
 	sock_unregister(PF_INET6);
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(proc_net_raw6.low_ino);
-	proc_net_unregister(proc_net_tcp6.low_ino);
-	proc_net_unregister(proc_net_udp6.low_ino);
-	proc_net_unregister(proc_net_sockstat6.low_ino);
-	proc_net_unregister(proc_net_snmp6.low_ino);
+	proc_net_remove("raw6");
+	proc_net_remove("tcp6");
+	proc_net_remove("udp6");
+	proc_net_remove("sockstat6");
+	proc_net_remove("snmp6");
 #endif
 	/* Cleanup code parts. */
 	sit_cleanup();
diff -u --recursive --new-file v2.3.24/linux/net/ipv6/ip6_flowlabel.c linux/net/ipv6/ip6_flowlabel.c
--- v2.3.24/linux/net/ipv6/ip6_flowlabel.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/ip6_flowlabel.c	Thu Oct 28 14:34:44 1999
@@ -606,15 +606,10 @@
 
 void ip6_flowlabel_init()
 {
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-#endif
-
 	init_timer(&ip6_fl_gc_timer);
 	ip6_fl_gc_timer.function = ip6_fl_gc;
 #ifdef CONFIG_PROC_FS
-	ent = create_proc_entry("net/ip6_flowlabel", 0, 0);
-	ent->read_proc = ip6_fl_read_proc;
+	create_proc_read_entry("net/ip6_flowlabel", 0, 0, ip6_fl_read_proc, NULL);
 #endif
 }
 
diff -u --recursive --new-file v2.3.24/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c
--- v2.3.24/linux/net/ipv6/mcast.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv6/mcast.c	Thu Oct 28 14:34:44 1999
@@ -707,9 +707,6 @@
 
 int __init igmp6_init(struct net_proto_family *ops)
 {
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-#endif
 	struct sock *sk;
 	int err;
 
@@ -738,8 +735,7 @@
 
 	sk->net_pinfo.af_inet6.hop_limit = 1;
 #ifdef CONFIG_PROC_FS
-	ent = create_proc_entry("net/igmp6", 0, 0);
-	ent->read_proc = igmp6_read_proc;
+	create_proc_read_entry("net/igmp6", 0, 0, igmp6_read_proc, NULL);
 #endif
 
 	return 0;
diff -u --recursive --new-file v2.3.24/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
--- v2.3.24/linux/net/ipv6/ndisc.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv6/ndisc.c	Thu Oct 28 14:34:44 1999
@@ -1179,18 +1179,10 @@
 	return len;
 }
 
-struct proc_dir_entry ndisc_proc_entry =
-{
-        PROC_NET_NDISC, 5, "ndisc",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, NULL,
-        &ndisc_get_info
-};
 #endif
 #endif	/* CONFIG_PROC_FS */
 
 
-
 int __init ndisc_init(struct net_proto_family *ops)
 {
 	struct sock *sk;
@@ -1230,7 +1222,7 @@
 
 #ifdef CONFIG_PROC_FS
 #ifndef CONFIG_RTNETLINK
-	proc_net_register(&ndisc_proc_entry);
+	proc_net_create("ndisc", 0, ndisc_get_info);
 #endif
 #endif
 #ifdef CONFIG_SYSCTL
@@ -1244,7 +1236,7 @@
 {
 #ifdef CONFIG_PROC_FS
 #ifndef CONFIG_RTNETLINK
-        proc_net_unregister(ndisc_proc_entry.low_ino);
+        proc_net_remove("ndisc");
 #endif
 #endif
 	neigh_table_clear(&nd_tbl);
diff -u --recursive --new-file v2.3.24/linux/net/ipv6/route.c linux/net/ipv6/route.c
--- v2.3.24/linux/net/ipv6/route.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv6/route.c	Thu Oct 28 14:34:44 1999
@@ -1861,19 +1861,6 @@
 
 	return len;
 }
-
-static struct proc_dir_entry proc_rt6_info = {
-	PROC_NET_RT6, 10, "ipv6_route",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	rt6_proc_info
-};
-static struct proc_dir_entry proc_rt6_stats = {
-	PROC_NET_RT6_STATS, 9, "rt6_stats",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations,
-	rt6_proc_stats
-};
 #endif	/* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SYSCTL
@@ -1936,8 +1923,8 @@
 						     NULL, NULL);
 	fib6_init();
 #ifdef 	CONFIG_PROC_FS
-	proc_net_register(&proc_rt6_info);
-	proc_net_register(&proc_rt6_stats);
+	proc_net_create("ipv6_route", 0, rt6_proc_info);
+	proc_net_create("rt6_stats", 0, rt6_proc_stats);
 #endif
 }
 
@@ -1945,8 +1932,8 @@
 void ip6_route_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_RT6);
-	proc_net_unregister(PROC_NET_RT6_STATS);
+	proc_net_remove("ipv6_route");
+	proc_net_remove("rt6_stats");
 #endif
 
 	rt6_ifdown(NULL);
diff -u --recursive --new-file v2.3.24/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.3.24/linux/net/ipx/af_ipx.c	Mon Oct  4 15:49:30 1999
+++ linux/net/ipx/af_ipx.c	Thu Oct 28 14:34:44 1999
@@ -2388,23 +2388,6 @@
 extern void destroy_EII_client(struct datalink_proto *);
 extern void destroy_8023_client(struct datalink_proto *);
 
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry ipx_procinfo = {
-	PROC_NET_IPX, 3, "ipx", S_IFREG | S_IRUGO,
-	1, 0, 0, 0, &proc_net_inode_operations, ipx_get_info
-};
-
-struct proc_dir_entry ipx_if_procinfo = {
-	PROC_NET_IPX_INTERFACE, 13, "ipx_interface", S_IFREG | S_IRUGO,
-	1, 0, 0, 0, &proc_net_inode_operations, ipx_interface_get_info
-};
-
-struct proc_dir_entry ipx_rt_procinfo = {
-	PROC_NET_IPX_ROUTE, 9, "ipx_route", S_IFREG | S_IRUGO,
-	1, 0, 0, 0, &proc_net_inode_operations, ipx_rt_get_info
-};
-#endif
-
 static unsigned char ipx_8022_type = 0xE0;
 static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
 
@@ -2429,9 +2412,9 @@
 	register_netdevice_notifier(&ipx_dev_notifier);
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&ipx_procinfo);
-	proc_net_register(&ipx_if_procinfo);
-	proc_net_register(&ipx_rt_procinfo);
+	proc_net_create("ipx", 0, ipx_get_info);
+	proc_net_create("ipx_interface", 0, ipx_interface_get_info);
+	proc_net_create("ipx_route", 0, ipx_rt_get_info);
 #endif
 
 	printk(KERN_INFO "NET4: Linux IPX 0.38 for NET4.0\n");
@@ -2482,9 +2465,9 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_IPX_ROUTE);
-	proc_net_unregister(PROC_NET_IPX_INTERFACE);
-	proc_net_unregister(PROC_NET_IPX);
+	proc_net_remove("ipx_route");
+	proc_net_remove("ipx_interface");
+	proc_net_remove("ipx");
 #endif
 
 	unregister_netdevice_notifier(&ipx_dev_notifier);
diff -u --recursive --new-file v2.3.24/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.3.24/linux/net/irda/irlan/irlan_common.c	Wed Oct 27 16:34:12 1999
+++ linux/net/irda/irlan/irlan_common.c	Thu Oct 28 14:34:44 1999
@@ -176,7 +176,7 @@
 		return -ENOMEM;
 	}
 #ifdef CONFIG_PROC_FS
-	create_proc_entry("irlan", 0, proc_irda)->get_info = irlan_proc_read;
+	create_proc_info_entry("irlan", 0, proc_irda, irlan_proc_read);
 #endif /* CONFIG_PROC_FS */
 
 	DEBUG(4, __FUNCTION__ "()\n");
diff -u --recursive --new-file v2.3.24/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.3.24/linux/net/irda/irproc.c	Wed Oct 27 16:34:13 1999
+++ linux/net/irda/irproc.c	Thu Oct 28 14:34:44 1999
@@ -75,7 +75,7 @@
 #endif /* MODULE */
 
 	for (i=0;i<IRDA_ENTRIES_NUM;i++)
-		create_proc_entry(dir[i].name,0,proc_irda)->get_info=dir[i].fn;
+		create_proc_info_entry(dir[i].name,0,proc_irda,dir[i].fn);
 }
 
 /*
diff -u --recursive --new-file v2.3.24/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.3.24/linux/net/netlink/af_netlink.c	Tue Aug 31 17:29:15 1999
+++ linux/net/netlink/af_netlink.c	Thu Oct 28 14:34:44 1999
@@ -967,9 +967,6 @@
 
 void netlink_proto_init(struct net_proto *pro)
 {
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-#endif
 	struct sk_buff *dummy_skb;
 
 	if (sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb)) {
@@ -978,7 +975,6 @@
 	}
 	sock_register(&netlink_family_ops);
 #ifdef CONFIG_PROC_FS
-	ent = create_proc_entry("net/netlink", 0, 0);
-	ent->read_proc = netlink_read_proc;
+	create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL);
 #endif
 }
diff -u --recursive --new-file v2.3.24/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.3.24/linux/net/netrom/af_netrom.c	Tue Sep  7 12:14:07 1999
+++ linux/net/netrom/af_netrom.c	Thu Oct 28 14:34:44 1999
@@ -1268,27 +1268,6 @@
 	0
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_nr = {
-	PROC_NET_NR, 2, "nr",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	nr_get_info
-};
-static struct proc_dir_entry proc_net_nr_neigh = {
-	PROC_NET_NR_NEIGH, 8, "nr_neigh",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	nr_neigh_get_info
-};
-static struct proc_dir_entry proc_net_nr_nodes = {
-	PROC_NET_NR_NODES, 8, "nr_nodes",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	nr_nodes_get_info
-};
-#endif	
-
 static struct net_device *dev_nr;
 
 void __init nr_proto_init(struct net_proto *pro)
@@ -1328,9 +1307,9 @@
 	nr_loopback_init();
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_nr);
-	proc_net_register(&proc_net_nr_neigh);
-	proc_net_register(&proc_net_nr_nodes);
+	proc_net_create("nr", 0, nr_get_info);
+	proc_net_create("nr_neigh", 0, nr_neigh_get_info);
+	proc_net_create("nr_nodes", 0, nr_nodes_get_info);
 #endif	
 }
 
@@ -1355,9 +1334,9 @@
 	int i;
 
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_NR);
-	proc_net_unregister(PROC_NET_NR_NEIGH);
-	proc_net_unregister(PROC_NET_NR_NODES);
+	proc_net_remove("nr");
+	proc_net_remove("nr_neigh");
+	proc_net_remove("nr_nodes");
 #endif
 	nr_loopback_clear();
 
diff -u --recursive --new-file v2.3.24/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.3.24/linux/net/packet/af_packet.c	Tue Aug 31 17:29:15 1999
+++ linux/net/packet/af_packet.c	Fri Oct 29 10:59:17 1999
@@ -1698,7 +1698,7 @@
 	int err = -EINVAL;
 	int i;
 
-	if (vma->vm_offset)
+	if (vma->vm_pgoff)
 		return -EINVAL;
 
 	size = vma->vm_end - vma->vm_start;
diff -u --recursive --new-file v2.3.24/linux/net/rose/af_rose.c linux/net/rose/af_rose.c
--- v2.3.24/linux/net/rose/af_rose.c	Tue Sep  7 12:14:07 1999
+++ linux/net/rose/af_rose.c	Thu Oct 28 14:34:44 1999
@@ -1458,33 +1458,6 @@
 	0
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_rose = {
-	PROC_NET_RS, 4, "rose",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	rose_get_info
-};
-static struct proc_dir_entry proc_net_rose_neigh = {
-	PROC_NET_RS_NEIGH, 10, "rose_neigh",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	rose_neigh_get_info
-};
-static struct proc_dir_entry proc_net_rose_nodes = {
-	PROC_NET_RS_NODES, 10, "rose_nodes",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	rose_nodes_get_info
-};
-static struct proc_dir_entry proc_net_rose_routes = {
-	PROC_NET_RS_ROUTES, 11, "rose_routes",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	rose_routes_get_info
-};
-#endif	
-
 static struct net_device *dev_rose;
 
 void __init rose_proto_init(struct net_proto *pro)
@@ -1527,10 +1500,10 @@
 	rose_add_loopback_neigh();
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_rose);
-	proc_net_register(&proc_net_rose_neigh);
-	proc_net_register(&proc_net_rose_nodes);
-	proc_net_register(&proc_net_rose_routes);
+	proc_net_create("rose", 0, rose_get_info);
+	proc_net_create("rose_neigh", 0, rose_neigh_get_info);
+	proc_net_create("rose_nodes", 0, rose_nodes_get_info);
+	proc_net_create("rose_routes", 0, rose_routes_get_info);
 #endif
 }
 
@@ -1555,10 +1528,10 @@
 	int i;
 
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_RS);
-	proc_net_unregister(PROC_NET_RS_NEIGH);
-	proc_net_unregister(PROC_NET_RS_NODES);
-	proc_net_unregister(PROC_NET_RS_ROUTES);
+	proc_net_remove("rose");
+	proc_net_remove("rose_neigh");
+	proc_net_remove("rose_nodes");
+	proc_net_remove("rose_routes");
 #endif
 	rose_loopback_clear();
 
diff -u --recursive --new-file v2.3.24/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.3.24/linux/net/sched/sch_api.c	Tue Aug 31 17:29:15 1999
+++ linux/net/sched/sch_api.c	Thu Oct 28 14:34:44 1999
@@ -1133,9 +1133,6 @@
 #ifdef CONFIG_RTNETLINK
 	struct rtnetlink_link *link_p;
 #endif
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-#endif
 
 #if PSCHED_CLOCK_SOURCE == PSCHED_CPU
 	if (psched_calibrate_clock() < 0)
@@ -1216,8 +1213,7 @@
 #endif
 
 #ifdef CONFIG_PROC_FS
-	ent = create_proc_entry("net/psched", 0, 0);
-	ent->read_proc = psched_read_proc;
+	create_proc_read_entry("net/psched", 0, 0, psched_read_proc, NULL);
 #endif
 
 	return 0;
diff -u --recursive --new-file v2.3.24/linux/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
--- v2.3.24/linux/net/sunrpc/clnt.c	Fri Oct 22 13:21:56 1999
+++ linux/net/sunrpc/clnt.c	Sun Oct 31 14:48:46 1999
@@ -294,7 +294,8 @@
 	task->tk_flags |= flags;
 
 	/* Increment call count */
-	rpcproc_count(task->tk_client, proc)++;
+	if (task->tk_proc < task->tk_client->cl_maxproc)
+		rpcproc_count(task->tk_client, proc)++;
 }
 
 /*
@@ -319,9 +320,14 @@
 call_bind(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
+	struct rpc_xprt *xprt = clnt->cl_xprt;
 
-	task->tk_action = call_reserve;
+	if (xprt->stream && !xprt->connected)
+		task->tk_action = call_reconnect;
+	else
+		task->tk_action = call_reserve;
 	task->tk_status = 0;
+
 	if (!clnt->cl_port)
 		rpc_getport(task, clnt);
 }
@@ -340,6 +346,7 @@
 			clnt->cl_protname, clnt->cl_server,
 			clnt->cl_softrtry? "giving up" : "retrying");
 		if (!clnt->cl_softrtry) {
+			task->tk_action = call_bind;
 			rpc_delay(task, 5*HZ);
 			return;
 		}
@@ -376,25 +383,27 @@
 
 	if (task->tk_status >= 0) {
 		task->tk_action = call_allocate;
-		goto out;
-	} else if (task->tk_status == -EAGAIN) {
+		return;
+	}
+
+	switch (task->tk_status) {
+	case -EAGAIN:
+	case -ENOBUFS:
 		task->tk_timeout = task->tk_client->cl_timeout.to_resrvval;
 		task->tk_status = 0;
-		xprt_reserve(task);
-		goto out;
-	} else if (task->tk_status == -ETIMEDOUT) {
+		task->tk_action = call_reserve;
+		break;
+	case -ETIMEDOUT:
 		dprintk("RPC: task timed out\n");
 		task->tk_action = call_timeout;
-		goto out;
-	} else {
+		break;
+	default:
 		task->tk_action = NULL;
+		if (!task->tk_rqstp) {
+			printk("RPC: task has no request, exit EIO\n");
+			rpc_exit(task, -EIO);
+		}
 	}
-	if (!task->tk_rqstp) {
-		printk("RPC: task has no request, exit EIO\n");
-		rpc_exit(task, -EIO);
-	}
-out:
-	return;
 }
 
 /*
@@ -424,7 +433,7 @@
 	if (!signalled()) {
 		xprt_release(task);
 		task->tk_action = call_reserve;
-		rpc_delay(task, HZ);
+		rpc_delay(task, HZ>>4);
 		return;
 	}
 
@@ -477,7 +486,7 @@
 		printk("RPC: call_header failed, exit EIO\n");
 		rpc_exit(task, -EIO);
 	} else
-	if ((status = encode(req, p, task->tk_argp)) < 0) {
+	if (encode && (status = encode(req, p, task->tk_argp)) < 0) {
 		printk(KERN_WARNING "%s: can't encode arguments: %d\n",
 				clnt->cl_protname, -status);
 		rpc_exit(task, status);
@@ -508,19 +517,16 @@
 		task->tk_pid, task->tk_status);
 
 	task->tk_action = call_status;
-	/* In case of error, evaluate status */
-	if (task->tk_status < 0)
-		return;
+
+	/* Need to ensure cleanups are performed by xprt_receive_status() */
+	xprt_receive(task);
 
 	/* If we have no decode function, this means we're performing
 	 * a void call (a la lockd message passing). */
 	if (!rpcproc_decode(task->tk_client, task->tk_proc)) {
-		rpc_remove_wait_queue(task); /* remove from xprt_pending */
 		task->tk_action = NULL;
 		return;
 	}
-
-	xprt_receive(task);
 }
 
 /*
@@ -530,6 +536,7 @@
 call_status(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
+	struct rpc_xprt *xprt = clnt->cl_xprt;
 	struct rpc_rqst	*req;
 	int		status = task->tk_status;
 
@@ -538,28 +545,49 @@
 
 	if (status >= 0) {
 		task->tk_action = call_decode;
-	} else if (status == -ETIMEDOUT) {
+		return;
+	}
+
+	task->tk_status = 0;
+	req = task->tk_rqstp;
+	switch(status) {
+	case -ETIMEDOUT:
 		task->tk_action = call_timeout;
-	} else if (status == -EAGAIN) {
-		if (!(req = task->tk_rqstp))
+		break;
+	case -EAGAIN:
+		if (!req)
 			task->tk_action = call_reserve;
 		else if (!task->tk_buffer)
 			task->tk_action = call_allocate;
-		else if (req->rq_damaged)
+		else if (req->rq_damaged) {
 			task->tk_action = call_encode;
-		else
+			clnt->cl_stats->rpcretrans++;
+		} else {
 			task->tk_action = call_transmit;
-	} else if (status == -ENOTCONN) {
-		task->tk_action = call_reconnect;
-	} else if (status == -ECONNREFUSED && clnt->cl_autobind) {
-		task->tk_action = call_bind;
-		clnt->cl_port = 0;
-	} else {
+			clnt->cl_stats->rpcretrans++;
+		}
+		break;
+	case -ECONNREFUSED:
+	case -ENOTCONN:
+		if (clnt->cl_autobind || !clnt->cl_port) {
+			clnt->cl_port = 0;
+			task->tk_action = call_bind;
+		} else if (xprt->stream)
+			task->tk_action = call_reconnect;
+		else {
+			rpc_delay(task, 5*HZ); /* Hope it all wears off */
+			if (req->rq_damaged)
+				task->tk_action = call_encode;
+			else
+				task->tk_action = call_transmit;
+			clnt->cl_stats->rpcretrans++;
+		}
+		break;
+	default:
 		if (clnt->cl_chatty)
 			printk("%s: RPC call returned error %d\n",
-				clnt->cl_protname, -status);
-		task->tk_action = NULL;
-		return;
+			       clnt->cl_protname, -status);
+		rpc_exit(task, status);
 	}
 }
 
@@ -600,7 +628,7 @@
 		if (req)
 			printk("%s: server %s not responding, still trying\n",
 				clnt->cl_protname, clnt->cl_server);
-		else 
+		else
 			printk("%s: task %d can't get a request slot\n",
 				clnt->cl_protname, task->tk_pid);
 	}
@@ -610,6 +638,8 @@
 minor_timeout:
 	if (!clnt->cl_port) {
 		task->tk_action = call_bind;
+	} else if (clnt->cl_xprt->stream && !clnt->cl_xprt->connected) {
+		task->tk_action = call_reconnect;
 	} else if (!req) {
 		task->tk_action = call_reserve;
 	} else if (req->rq_damaged) {
@@ -628,14 +658,12 @@
 static void
 call_reconnect(struct rpc_task *task)
 {
+	struct rpc_clnt *clnt = task->tk_client;
 	dprintk("RPC: %4d call_reconnect status %d\n",
 				task->tk_pid, task->tk_status);
-	if (task->tk_status == 0) {
-		task->tk_action = call_status;
-		task->tk_status = -EAGAIN;
-		return;
-	}
-	task->tk_client->cl_stats->netreconn++;
+	task->tk_action = call_reserve;
+	task->tk_status = 0;
+	clnt->cl_stats->netreconn++;
 	xprt_reconnect(task);
 }
 
@@ -685,7 +713,9 @@
 	}
 
 	task->tk_action = NULL;
-	task->tk_status = decode(req, p, task->tk_resp);
+
+	if (decode)
+		task->tk_status = decode(req, p, task->tk_resp);
 	dprintk("RPC: %4d call_decode result %d\n", task->tk_pid,
 					task->tk_status);
 }
@@ -714,11 +744,10 @@
 	dprintk("RPC: %4d call_refreshresult (status %d)\n", 
 				task->tk_pid, task->tk_status);
 
-	if (task->tk_status < 0) {
-		task->tk_status = -EACCES;
-		task->tk_action = NULL;
-	} else
-		task->tk_action = call_reserve;
+	if (task->tk_status < 0)
+		rpc_exit(task, -EACCES);
+	else
+		task->tk_action = call_bind;
 }
 
 /*
diff -u --recursive --new-file v2.3.24/linux/net/sunrpc/stats.c linux/net/sunrpc/stats.c
--- v2.3.24/linux/net/sunrpc/stats.c	Sat Jan  2 17:55:06 1999
+++ linux/net/sunrpc/stats.c	Thu Oct 28 14:34:44 1999
@@ -126,14 +126,10 @@
 static inline struct proc_dir_entry *
 do_register(const char *name, void *data, int issvc)
 {
-	struct proc_dir_entry	*ent;
-
 	dprintk("RPC: registering /proc/net/rpc/%s\n", name);
-	ent = create_proc_entry(name, 0, proc_net_rpc);
-	ent->read_proc = issvc? svc_proc_read : rpc_proc_read;
-	ent->data = data;
-
-	return ent;
+	return create_proc_read_entry(name, 0, proc_net_rpc, 
+				      issvc? svc_proc_read : rpc_proc_read,
+				      data);
 }
 
 struct proc_dir_entry *
diff -u --recursive --new-file v2.3.24/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.3.24/linux/net/unix/af_unix.c	Fri Oct 15 15:25:14 1999
+++ linux/net/unix/af_unix.c	Thu Oct 28 14:34:44 1999
@@ -1777,7 +1777,6 @@
 #endif
 {
 	struct sk_buff *dummy_skb;
-	struct proc_dir_entry *ent;
 	
 	printk(KERN_INFO "NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.\n");
 	if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb))
@@ -1791,8 +1790,7 @@
 	}
 	sock_register(&unix_family_ops);
 #ifdef CONFIG_PROC_FS
-	ent = create_proc_entry("net/unix", 0, 0);
-	ent->read_proc = unix_read_proc;
+	create_proc_read_entry("net/unix", 0, 0, unix_read_proc, NULL);
 #endif
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.24/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c
--- v2.3.24/linux/net/wanrouter/wanproc.c	Tue Aug 31 17:29:15 1999
+++ linux/net/wanrouter/wanproc.c	Thu Oct 28 14:34:44 1999
@@ -193,16 +193,6 @@
 	name_root,		/* .name */
 	0555 | S_IFDIR,		/* .mode */
 	2,			/* .nlink */
-	0,			/* .uid */
-	0,			/* .gid */
-	0,			/* .size */
-	&proc_dir_inode_operations, /* .ops */
-	NULL,			/* .get_info */
-	NULL,			/* .fill_node */
-	NULL,			/* .next */
-	NULL,			/* .parent */
-	NULL,			/* .subdir */
-	NULL,			/* .data */
 };
 
 /*
diff -u --recursive --new-file v2.3.24/linux/net/x25/af_x25.c linux/net/x25/af_x25.c
--- v2.3.24/linux/net/x25/af_x25.c	Fri Oct 15 15:25:14 1999
+++ linux/net/x25/af_x25.c	Thu Oct 28 14:34:45 1999
@@ -1283,21 +1283,6 @@
 	} 
 }
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_x25 = {
-	PROC_NET_X25, 3, "x25",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	x25_get_info
-};
-static struct proc_dir_entry proc_net_x25_routes = {
-	PROC_NET_X25_ROUTES, 10, "x25_routes",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_net_inode_operations, 
-	x25_routes_get_info
-};
-#endif	
-
 void __init x25_proto_init(struct net_proto *pro)
 {
 	sock_register(&x25_family_ops);
@@ -1314,8 +1299,8 @@
 #endif
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_x25);
-	proc_net_register(&proc_net_x25_routes);
+	proc_net_create("x25", 0, x25_get_info);
+	proc_net_create("x25_routes", 0, x25_routes_get_info);
 #endif	
 }
 
@@ -1352,8 +1337,8 @@
 {
 
 #ifdef CONFIG_PROC_FS
-	proc_net_unregister(PROC_NET_X25);
-	proc_net_unregister(PROC_NET_X25_ROUTES);
+	proc_net_remove("x25");
+	proc_net_remove("x25_routes");
 #endif
 
 	x25_link_free();
diff -u --recursive --new-file v2.3.24/linux/scripts/Configure linux/scripts/Configure
--- v2.3.24/linux/scripts/Configure	Mon Oct  4 15:49:30 1999
+++ linux/scripts/Configure	Thu Oct 28 10:16:02 1999
@@ -389,9 +389,9 @@
 #	define_string define value
 #
 function define_string () {
-	echo "$1="'"'$2'"' >>$CONFIG
-	echo "#define $1 "'"'$2'"' >>$CONFIG_H
-	eval "$1=$2"
+	echo "$1=\"$2\"" >>$CONFIG
+	echo "#define $1 \"$2\"" >>$CONFIG_H
+	eval "$1=\"$2\""
 }
 
 #
