## Automatically generated incremental diff
## From:   linux-2.5.65-bk2
## To:     linux-2.5.65-bk3
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.65-bk2/Documentation/filesystems/sysfs.txt linux-2.5.65-bk3/Documentation/filesystems/sysfs.txt
--- linux-2.5.65-bk2/Documentation/filesystems/sysfs.txt	Mon Mar 17 13:43:42 2003
+++ linux-2.5.65-bk3/Documentation/filesystems/sysfs.txt	Mon Mar 31 12:41:39 2003
@@ -60,7 +60,7 @@
 you publically humiliated and your code rewritten without notice. 
 
 
-An attriubte definition is simply:
+An attribute definition is simply:
 
 struct attribute {
         char                    * name;
@@ -261,7 +261,7 @@
 that point to the device's directory under root/.
 
 drivers/ contains a directory for each device driver that is loaded
-for devices on that particular bus (this assmumes that drivers do not
+for devices on that particular bus (this assumes that drivers do not
 span multiple bus types).
 
 
diff -urN linux-2.5.65-bk2/Documentation/kernel-parameters.txt linux-2.5.65-bk3/Documentation/kernel-parameters.txt
--- linux-2.5.65-bk2/Documentation/kernel-parameters.txt	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/Documentation/kernel-parameters.txt	Mon Mar 31 12:41:39 2003
@@ -713,7 +713,6 @@
 					numbers ourselves, overriding
 					whatever the firmware may have
 					done.
-
 		usepirqmask		[IA-32] Honor the possible IRQ mask
 					stored in the BIOS $PIR table. This is
 					needed on some systems with broken
@@ -721,6 +720,7 @@
 					and Omnibook XE3 notebooks. This will
 					have no effect if ACPI IRQ routing is
 					enabled.
+		noacpi			[IA-32] Do not use ACPI for IRQ routing.
 
 	pcmv=		[HW,PCMCIA] BadgePAD 4
 
diff -urN linux-2.5.65-bk2/MAINTAINERS linux-2.5.65-bk3/MAINTAINERS
--- linux-2.5.65-bk2/MAINTAINERS	Mon Mar 31 12:41:36 2003
+++ linux-2.5.65-bk3/MAINTAINERS	Mon Mar 31 12:41:39 2003
@@ -728,7 +728,7 @@
 
 GDT SCSI DISK ARRAY CONTROLLER DRIVER
 P:	Achim Leubner
-M:	achim@vortex.de
+M:	achim.leubner@intel.com
 L:	linux-scsi@vger.kernel.org
 W:	http://www.icp-vortex.com/
 S:	Supported
diff -urN linux-2.5.65-bk2/Makefile linux-2.5.65-bk3/Makefile
--- linux-2.5.65-bk2/Makefile	Mon Mar 31 12:41:36 2003
+++ linux-2.5.65-bk3/Makefile	Mon Mar 31 12:41:39 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 65
-EXTRAVERSION = -bk2
+EXTRAVERSION = -bk3
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -164,6 +164,8 @@
 OBJCOPY		= $(CROSS_COMPILE)objcopy
 OBJDUMP		= $(CROSS_COMPILE)objdump
 AWK		= awk
+RPM 		:= $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \
+		    	else echo rpm; fi)
 GENKSYMS	= scripts/genksyms/genksyms
 DEPMOD		= /sbin/depmod
 KALLSYMS	= scripts/kallsyms
@@ -768,9 +770,7 @@
 	rm $(KERNELPATH) ; \
 	cd $(TOPDIR) ; \
 	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > .version ; \
-	RPM=`which rpmbuild`; \
-	if [ -z "$$RPM" ]; then RPM=rpm; fi; \
-	$$RPM -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \
+	$(RPM) -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \
 	rm $(TOPDIR)/../$(KERNELPATH).tar.gz
 
 # Brief documentation of the typical targets used
diff -urN linux-2.5.65-bk2/arch/i386/boot98/Makefile linux-2.5.65-bk3/arch/i386/boot98/Makefile
--- linux-2.5.65-bk2/arch/i386/boot98/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/Makefile	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,76 @@
+#
+# arch/i386/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+#
+
+# ROOT_DEV specifies the default root-device when making the image.
+# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
+# the default of FLOPPY is used by 'build'.
+
+ROOT_DEV := CURRENT
+
+# If you want to preset the SVGA mode, uncomment the next line and
+# set SVGA_MODE to whatever number you want.
+# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
+# The number is the same as you would ordinarily press at bootup.
+
+SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
+
+# If you want the RAM disk device, define this to be the size in blocks.
+
+#RAMDISK := -DRAMDISK=512
+
+EXTRA_TARGETS	:= vmlinux.bin bootsect bootsect.o \
+		   setup setup.o zImage bzImage
+
+subdir- 	:= compressed
+
+host-progs	:= tools/build
+
+# ---------------------------------------------------------------------------
+
+$(obj)/zImage:  IMAGE_OFFSET := 0x1000
+$(obj)/zImage:  EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK)
+$(obj)/bzImage: IMAGE_OFFSET := 0x100000
+$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
+$(obj)/bzImage: BUILDFLAGS   := -b
+
+quiet_cmd_image = BUILD   $@
+cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
+	    $(obj)/vmlinux.bin $(ROOT_DEV) > $@
+
+$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
+			      $(obj)/vmlinux.bin $(obj)/tools/build FORCE
+	$(call if_changed,image)
+	@echo 'Kernel: $@ is ready'
+
+$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
+	$(call if_changed,objcopy)
+
+LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
+LDFLAGS_setup	 := -Ttext 0x0 -s --oformat binary -e begtext
+
+$(obj)/setup $(obj)/bootsect: %: %.o FORCE
+	$(call if_changed,ld)
+
+$(obj)/compressed/vmlinux: FORCE
+	$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
+					IMAGE_OFFSET=$(IMAGE_OFFSET) $@
+
+zdisk: $(BOOTIMAGE)
+	dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
+
+zlilo: $(BOOTIMAGE)
+	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
+	if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
+	cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
+	cp System.map $(INSTALL_PATH)/
+	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+
+install: $(BOOTIMAGE)
+	sh $(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff -urN linux-2.5.65-bk2/arch/i386/boot98/bootsect.S linux-2.5.65-bk3/arch/i386/boot98/bootsect.S
--- linux-2.5.65-bk2/arch/i386/boot98/bootsect.S	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/bootsect.S	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,397 @@
+/*	
+ *	bootsect.S - boot sector for NEC PC-9800 series
+ *
+ *	Linux/98 project at Kyoto University Microcomputer Club (KMC)
+ *		    FUJITA Norimasa, TAKAI Kousuke  1997-1998
+ *	rewritten by TAKAI Kousuke (as86 -> gas), Nov 1999
+ *
+ * Based on:
+ *	bootsect.S		Copyright (C) 1991, 1992 Linus Torvalds
+ *	modified by Drew Eckhardt
+ *	modified by Bruce Evans (bde)
+ *
+ * bootsect.S is loaded at 0x1FC00 or 0x1FE00 by the bios-startup routines,
+ * and moves itself out of the way to address 0x90000, and jumps there.
+ *
+ * It then loads 'setup' directly after itself (0x90200), and the system
+ * at 0x10000, using BIOS interrupts. 
+ *
+ * NOTE! currently system is at most (8*65536-4096) bytes long. This should 
+ * be no problem, even in the future. I want to keep it simple. This 508 kB
+ * kernel size should be enough, especially as this doesn't contain the
+ * buffer cache as in minix (and especially now that the kernel is 
+ * compressed :-)
+ *
+ * The loader has been made as simple as possible, and continuous
+ * read errors will result in a unbreakable loop. Reboot by hand. It
+ * loads pretty fast by getting whole tracks at a time whenever possible.
+ */
+
+#include <linux/config.h>		/* for CONFIG_ROOT_RDONLY */
+#include <asm/boot.h>
+
+SETUPSECTS	= 4			/* default nr of setup-sectors */
+BOOTSEG		= 0x1FC0		/* original address of boot-sector */
+INITSEG		= DEF_INITSEG		/* we move boot here - out of the way */
+SETUPSEG	= DEF_SETUPSEG		/* setup starts here */
+SYSSEG		= DEF_SYSSEG		/* system loaded at 0x10000 (65536) */
+SYSSIZE		= DEF_SYSSIZE		/* system size: # of 16-byte clicks */
+					/* to be loaded */
+ROOT_DEV	= 0 			/* ROOT_DEV is now written by "build" */
+SWAP_DEV	= 0			/* SWAP_DEV is now written by "build" */
+
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
+
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif 
+
+#ifndef ROOT_RDONLY
+#define ROOT_RDONLY 1
+#endif
+
+/* normal/hireso text VRAM segments */
+#define NORMAL_TEXT	0xa000
+#define HIRESO_TEXT	0xe000
+
+/* bios work area addresses */
+#define EXPMMSZ		0x0401
+#define BIOS_FLAG	0x0501
+#define	DISK_BOOT	0x0584
+
+.code16
+.text
+
+.global _start
+_start:
+
+#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
+	int	$0x3
+#endif
+	jmp	real_start
+	.ascii	"Linux 98"
+	.word	0
+real_start:
+	xorw	%di, %di		/* %di = 0 */
+	movw	%di, %ss		/* %ss = 0 */
+	movw	$0x03F0, %sp
+	pushw	%cx			/* for hint */
+
+	movw	$0x0A00, %ax		/* normal mode defaults (80x25) */
+
+	testb	$0x08, %ss:BIOS_FLAG	/* check hi-reso bit */
+	jnz	set_crt_mode
+/*
+ * Hi-Reso (high-resolution) machine.
+ *
+ * Some hi-reso machines have no RAMs on bank 8/A (0x080000 - 0x0BFFFF).
+ * On such machines we get two RAM banks from top of protect menory and
+ * map them on bank 8/A.
+ * These work-around must be done before moving myself on INITSEG (0x090000-).
+ */
+	movw	$(HIRESO_TEXT >> 8), %cs:(vram + 1)	/* text VRAM segment */
+
+	/* set memory window */
+	movb	$0x08, %al
+	outb	%al, $0x91		/* map native RAM (if any) */
+	movb	$0x0A, %al
+	outb	%al, $0x93
+
+	/* check bank ram A */
+	pushw	$0xA500
+	popw	%ds
+	movw	(%di), %cx		/* %si == 0 from entry */
+	notw	%cx
+	movw	%cx, (%di)
+
+	movw	$0x43F, %dx		/* cache flush for 486 and up. */
+	movb	$0xA0, %al
+	outb	%al, %dx
+	
+	cmpw	%cx, (%di)
+	je	hireso_done
+
+	/* 
+	 * Write test failed; we have no native RAM on 080000h - 0BFFFFh.
+	 * Take 256KB of RAM from top of protected memory.
+	 */
+	movb	%ss:EXPMMSZ, %al
+	subb	$2, %al			/* reduce 2 x 128KB */
+	movb	%al, %ss:EXPMMSZ
+	addb	%al, %al
+	addb	$0x10, %al
+	outb	%al, $0x91
+	addb	$2, %al
+	outb	%al, $0x93
+
+hireso_done:
+	movb	$0x10, %al		/* CRT mode 80x31, %ah still 0Ah */
+
+set_crt_mode:
+	int	$0x18			/* set CRT mode */
+
+	movb	$0x0C, %ah		/* turn on text displaying */
+	int	$0x18
+
+	xorw	%dx, %dx		/* position cursor to home */
+	movb	$0x13, %ah
+	int	$0x18
+
+	movb	$0x11, %ah		/* turn cursor displaying on */
+	int	$0x18
+
+	/* move 1 kilobytes from [BOOTSEG:0000h] to [INITSEG:0000h] */
+	cld
+	xorw	%si, %si
+	pushw	$INITSEG
+	popw	%es
+	movw	$512, %cx		/* %di == 0 from entry */
+	rep
+	cs
+	movsw
+
+	ljmp	$INITSEG, $go
+
+go:
+	pushw	%cs
+	popw	%ds		/* %ds = %cs */
+
+	popw	%dx		/* %dh = saved %ch passed from BIOS */
+	movb	%ss:DISK_BOOT, %al
+	andb	$0xf0, %al	/* %al = Device Address */
+	movb	$18, %ch	/* 18 secs/track,  512 b/sec (1440 KB) */
+	cmpb	$0x30, %al
+	je	try512
+	cmpb	$0x90, %al	/* 1 MB I/F, 1 MB floppy */
+	je	try1.2M
+	cmpb	$0xf0, %al	/* 640 KB I/F, 1 MB floppy */
+	je	try1.2M
+	movb	$9, %ch		/*  9 secs/track,  512 b/sec ( 720 KB) */
+	cmpb	$0x10, %al	/* 1 MB I/F, 640 KB floppy */
+	je	try512
+	cmpb	$0x70, %al	/* 640 KB I/F, 640 KB floppy */
+	jne	error		/* unknown device? */
+
+	/* XXX: Does it make sense to support 8 secs/track, 512 b/sec 
+		(640 KB) floppy? */
+
+try512:	movb	$2, %cl		/* 512 b/sec */
+lasttry:call	tryload
+/*
+ * Display error message and halt
+ */
+error:	movw	$error_msg, %si
+	call	print
+wait_reboot:
+	movb	$0x0, %ah
+	int	$0x18			/* wait keyboard input */
+1:	movb	$0, %al
+	outb	%al, $0xF0		/* reset CPU */
+	jmp	1b			/* just in case... */
+
+try1.2M:cmpb	$2, %dh
+	je	try2HC
+	movw	$0x0803, %cx	/*  8 secs/track, 1024 b/sec (1232 KB) */
+	call	tryload
+	movb	$15, %ch	/* 15 secs/track,  512 b/sec (1200 KB) */
+	jmp	try512
+try2HC:	movw	$0x0F02, %cx	/* 15 secs/track,  512 b/sec (1200 KB) */
+	call	tryload
+	movw	$0x0803, %cx	/*  8 secs/track, 1024 b/sec (1232 KB) */
+	jmp	lasttry
+
+/*
+ * Try to load SETUP and SYSTEM provided geometry information in %cx.
+ * This routine *will not* return on successful load...
+ */
+tryload:
+	movw	%cx, sectlen
+	movb	%ss:DISK_BOOT, %al
+	movb	$0x7, %ah		/* recalibrate the drive */
+	int	$0x1b
+	jc	error			/* recalibration should succeed */
+
+	/*
+	 * Load SETUP into memory. It is assumed that SETUP fits into
+	 * first cylinder (2 tracks, 9KB on 2DD, 15-18KB on 2HD).
+	 */
+	movb	$0, %bl
+	movb	setup_sects, %bh
+	incb	%bh
+	shlw	%bx			/* %bx = (setup_sects + 1) * 512 */
+	movw	$128, %bp
+	shlw	%cl, %bp		/* %bp = <sector size> */
+	subw	%bp, %bx		/* length to load */
+	movw	$0x0002, %dx		/* head 0, sector 2 */
+	movb	%cl, %ch		/* `N' for sector address */
+	movb	$0, %cl			/* cylinder 0 */
+	pushw	%cs
+	popw	%es			/* %es = %cs (= INITSEG) */
+	movb	$0xd6, %ah		/* read, multi-track, MFM */
+	int	$0x1b			/* load it! */
+	jc	read_error
+
+	movw	$loading_msg, %si
+	call	print
+
+	movw	$SYSSEG, %ax
+	movw	%ax, %es		/* %es = SYSSEG */
+
+/*
+ * This routine loads the system at address 0x10000, making sure
+ * no 64kB boundaries are crossed. We try to load it as fast as
+ * possible, loading whole tracks whenever we can.
+ *
+ * in:	es - starting address segment (normally 0x1000)
+ */
+	movb	%ch, %cl
+	addb	$7, %cl			/* %cl = log2 <sector_size> */
+	shrw	%cl, %bx		/* %bx = # of phys. sectors in SETUP */
+	addb	%bl, %dl		/* %dl = start sector # of SYSTEM */
+	decb	%dl			/* %dl is 0-based in below loop */
+
+rp_read_newseg:
+	xorw	%bp, %bp		/* = starting address within segment */
+#ifdef __BIG_KERNEL__
+	bootsect_kludge = 0x220		/* 0x200 (size of bootsector) + 0x20 (offset */
+	lcall	*bootsect_kludge	/* of bootsect_kludge in setup.S */
+#else
+	movw	%es, %ax
+	subw	$SYSSEG, %ax
+#endif
+	cmpw	syssize, %ax
+	ja	boot			/* done! */
+
+rp_read:
+	movb	sectors, %al
+	addb	%al, %al
+	movb	%al, %ch		/* # of sectors on both surface */
+	subb	%dl, %al		/* # of sectors left on this track */
+	movb	$0, %ah
+	shlw	%cl, %ax		/* # of bytes left on this track */
+	movw	%ax, %bx		/* transfer length */
+	addw	%bp, %ax		/* cross 64K boundary? */
+	jnc	1f			/* ok. */
+	jz	1f			/* also ok. */
+	/*
+	 * Oops, we are crossing 64K boundary...
+	 * Adjust transfer length to make transfer fit in the boundary.
+	 *
+	 * Note: sector size is assumed to be a measure of 65536.
+	 */
+	xorw	%bx, %bx
+	subw	%bp, %bx
+1:	pushw	%dx
+	movw	$dot_msg, %si		/* give progress message */
+	call	print
+	xchgw	%ax, %dx
+	movb	$0, %ah
+	divb	sectors
+	xchgb	%al, %ah
+	xchgw	%ax, %dx		/* %dh = head # / %dl = sector # */
+	incb	%dl			/* fix %dl to 1-based */
+	pushw	%cx
+	movw	cylinder, %cx
+	movb	$0xd6, %ah		/* read, multi-track, seek, MFM */
+	movb	%ss:DISK_BOOT, %al
+	int	$0x1b
+	popw	%cx
+	popw	%dx
+	jc	read_error
+	movw	%bx, %ax		/* # of bytes just read */
+	shrw	%cl, %ax		/* %ax = # of sectors just read */
+	addb	%al, %dl		/* advance sector # */
+	cmpb	%ch, %dl		/* %ch = # of sectors/cylinder */
+	jb	2f
+	incb	cylinder		/* next cylinder */
+	xorb	%dl, %dl		/* sector 0 */
+2:	addw	%bx, %bp		/* advance offset pointer */
+	jnc	rp_read
+	/* offset pointer wrapped; advance segment pointer. */
+	movw	%es, %ax
+	addw	$0x1000, %ax
+	movw	%ax, %es
+	jmp	rp_read_newseg
+
+read_error:
+	ret
+
+boot:	movw	%cs, %ax		/* = INITSEG */
+	/* movw	%ax, %ds */
+	movw	%ax, %ss
+	movw	$0x4000, %sp		/* 0x4000 is arbitrary value >=
+					 * length of bootsect + length of
+					 * setup + room for stack;
+					 * PC-9800 never have BIOS workareas
+					 * on high memory.
+					 */
+/*
+ * After that we check which root-device to use. If the device is
+ * not defined, /dev/fd0 (2, 0) will be used.
+ */
+	cmpw	$0, root_dev
+	jne	3f
+	movb	$2, root_dev+1
+3:
+
+/*
+ * After that (everything loaded), we jump to the setup-routine
+ * loaded directly after the bootblock:
+ */
+	ljmp	$SETUPSEG, $0
+
+/*
+ * Subroutine for print string on console.
+ *	%cs:%si	- pointer to message
+ */
+print:
+	pushaw
+	pushw	%ds
+	pushw	%es
+	pushw	%cs
+	popw	%ds
+	lesw	curpos, %di		/* %es:%di = current text VRAM addr. */
+1:	xorw	%ax, %ax
+	lodsb
+	testb	%al, %al
+	jz	2f			/* end of string */
+	stosw					/* character code */
+	movb	$0xE1, %es:0x2000-2(%di)	/* character attribute */
+	jmp	1b
+2:	movw	%di, %dx
+	movb	$0x13, %ah
+	int	$0x18			/* move cursor to current point */
+	popw	%es
+	popw	%ds
+	popaw
+	ret
+
+loading_msg:
+	.string	"Loading"
+dot_msg:
+	.string	"."
+error_msg:
+	.string	"Read Error!"
+
+	.org	490
+
+curpos:	.word	160		/* current cursor position */
+vram:	.word	NORMAL_TEXT	/* text VRAM segment */
+
+cylinder:	.byte	0	/* current cylinder (lower byte)	*/
+sectlen:	.byte	0	/* (log2 of <sector size>) - 7		*/
+sectors:	.byte	0x0F	/* default is 2HD (15 sector/track)	*/
+
+# XXX: This is a fairly snug fit.
+
+.org 497
+setup_sects:	.byte SETUPSECTS
+root_flags:	.word ROOT_RDONLY
+syssize:	.word SYSSIZE
+swap_dev:	.word SWAP_DEV
+ram_size:	.word RAMDISK
+vid_mode:	.word SVGA_MODE
+root_dev:	.word ROOT_DEV
+boot_flag:	.word 0xAA55
diff -urN linux-2.5.65-bk2/arch/i386/boot98/compressed/Makefile linux-2.5.65-bk3/arch/i386/boot98/compressed/Makefile
--- linux-2.5.65-bk2/arch/i386/boot98/compressed/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/compressed/Makefile	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,25 @@
+#
+# linux/arch/i386/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+EXTRA_TARGETS	:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+EXTRA_AFLAGS	:= -traditional
+
+LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
+
+$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
+	$(call if_changed,ld)
+	@:
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,gzip)
+
+LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
+	$(call if_changed,ld)
diff -urN linux-2.5.65-bk2/arch/i386/boot98/compressed/head.S linux-2.5.65-bk3/arch/i386/boot98/compressed/head.S
--- linux-2.5.65-bk2/arch/i386/boot98/compressed/head.S	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/compressed/head.S	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,128 @@
+/*
+ *  linux/boot/head.S
+ *
+ *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
+ */
+
+/*
+ *  head.S contains the 32-bit startup code.
+ *
+ * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
+ * the page directory will exist. The startup code will be overwritten by
+ * the page directory. [According to comments etc elsewhere on a compressed
+ * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
+ *
+ * Page 0 is deliberately kept safe, since System Management Mode code in 
+ * laptops may need to access the BIOS data stored there.  This is also
+ * useful for future device drivers that either access the BIOS via VM86 
+ * mode.
+ */
+
+/*
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ */
+.text
+
+#include <linux/linkage.h>
+#include <asm/segment.h>
+
+	.globl startup_32
+	
+startup_32:
+	cld
+	cli
+	movl $(__BOOT_DS),%eax
+	movl %eax,%ds
+	movl %eax,%es
+	movl %eax,%fs
+	movl %eax,%gs
+
+	lss stack_start,%esp
+	xorl %eax,%eax
+1:	incl %eax		# check that A20 really IS enabled
+	movl %eax,0x000000	# loop forever if it isn't
+	cmpl %eax,0x100000
+	je 1b
+
+/*
+ * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
+ * confuse the debugger if this code is traced.
+ * XXX - best to initialize before switching to protected mode.
+ */
+	pushl $0
+	popfl
+/*
+ * Clear BSS
+ */
+	xorl %eax,%eax
+	movl $_edata,%edi
+	movl $_end,%ecx
+	subl %edi,%ecx
+	cld
+	rep
+	stosb
+/*
+ * Do the decompression, and jump to the new kernel..
+ */
+	subl $16,%esp	# place for structure on the stack
+	movl %esp,%eax
+	pushl %esi	# real mode pointer as second arg
+	pushl %eax	# address of structure as first arg
+	call decompress_kernel
+	orl  %eax,%eax 
+	jnz  3f
+	popl %esi	# discard address
+	popl %esi	# real mode pointer
+	xorl %ebx,%ebx
+	ljmp $(__BOOT_CS), $0x100000
+
+/*
+ * We come here, if we were loaded high.
+ * We need to move the move-in-place routine down to 0x1000
+ * and then start it with the buffer addresses in registers,
+ * which we got from the stack.
+ */
+3:
+	movl $move_routine_start,%esi
+	movl $0x1000,%edi
+	movl $move_routine_end,%ecx
+	subl %esi,%ecx
+	addl $3,%ecx
+	shrl $2,%ecx
+	cld
+	rep
+	movsl
+
+	popl %esi	# discard the address
+	popl %ebx	# real mode pointer
+	popl %esi	# low_buffer_start
+	popl %ecx	# lcount
+	popl %edx	# high_buffer_start
+	popl %eax	# hcount
+	movl $0x100000,%edi
+	cli		# make sure we don't get interrupted
+	ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine
+
+/*
+ * Routine (template) for moving the decompressed kernel in place,
+ * if we were high loaded. This _must_ PIC-code !
+ */
+move_routine_start:
+	movl %ecx,%ebp
+	shrl $2,%ecx
+	rep
+	movsl
+	movl %ebp,%ecx
+	andl $3,%ecx
+	rep
+	movsb
+	movl %edx,%esi
+	movl %eax,%ecx	# NOTE: rep movsb won't move if %ecx == 0
+	addl $3,%ecx
+	shrl $2,%ecx
+	rep
+	movsl
+	movl %ebx,%esi	# Restore setup pointer
+	xorl %ebx,%ebx
+	ljmp $(__BOOT_CS), $0x100000
+move_routine_end:
diff -urN linux-2.5.65-bk2/arch/i386/boot98/compressed/misc.c linux-2.5.65-bk3/arch/i386/boot98/compressed/misc.c
--- linux-2.5.65-bk2/arch/i386/boot98/compressed/misc.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/compressed/misc.c	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,379 @@
+/*
+ * misc.c
+ * 
+ * This is a collection of several routines from gzip-1.0.3 
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ * puts by Nick Holloway 1993, better puts by Martin Mares 1995
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ */
+
+#include <linux/linkage.h>
+#include <linux/vmalloc.h>
+#include <linux/tty.h>
+#include <asm/io.h>
+#ifdef STANDARD_MEMORY_BIOS_CALL
+#undef STANDARD_MEMORY_BIOS_CALL
+#endif
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+#undef memset
+#undef memcpy
+
+/*
+ * Why do we do this? Don't ask me..
+ *
+ * Incomprehensible are the ways of bootloaders.
+ */
+static void* memset(void *, int, size_t);
+static void* memcpy(void *, __const void *, size_t);
+#define memzero(s, n)     memset ((s), 0, (n))
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define WSIZE 0x8000		/* Window size must be at least 32k, */
+				/* and a power of two */
+
+static uch *inbuf;	     /* input buffer */
+static uch window[WSIZE];    /* Sliding window buffer */
+
+static unsigned insize = 0;  /* valid bytes in inbuf */
+static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0;  /* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+		
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+  
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+static unsigned char *real_mode; /* Pointer to real-mode data */
+
+#define EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
+#ifndef STANDARD_MEMORY_BIOS_CALL
+#define ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
+#endif
+#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+
+extern char input_data[];
+extern int input_len;
+
+static long bytes_out = 0;
+static uch *output_data;
+static unsigned long output_ptr = 0;
+
+static void *malloc(int size);
+static void free(void *where);
+
+static void puts(const char *);
+
+extern int end;
+static long free_mem_ptr = (long)&end;
+static long free_mem_end_ptr;
+
+#define INPLACE_MOVE_ROUTINE  0x1000
+#define LOW_BUFFER_START      0x2000
+#define LOW_BUFFER_MAX       0x90000
+#define HEAP_SIZE             0x3000
+static unsigned int low_buffer_end, low_buffer_size;
+static int high_loaded =0;
+static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
+
+static char *vidmem = (char *)0xa0000;
+static int lines, cols;
+
+#ifdef CONFIG_X86_NUMAQ
+static void * xquad_portio = NULL;
+#endif
+
+#include "../../../../lib/inflate.c"
+
+static void *malloc(int size)
+{
+	void *p;
+
+	if (size <0) error("Malloc error\n");
+	if (free_mem_ptr <= 0) error("Memory error\n");
+
+	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+
+	p = (void *)free_mem_ptr;
+	free_mem_ptr += size;
+
+	if (free_mem_ptr >= free_mem_end_ptr)
+		error("\nOut of memory\n");
+
+	return p;
+}
+
+static void free(void *where)
+{	/* Don't care */
+}
+
+static void gzip_mark(void **ptr)
+{
+	*ptr = (void *) free_mem_ptr;
+}
+
+static void gzip_release(void **ptr)
+{
+	free_mem_ptr = (long) *ptr;
+}
+ 
+static void scroll(void)
+{
+	int i;
+
+	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+		vidmem[i] = ' ';
+}
+
+static void puts(const char *s)
+{
+	int x,y,pos;
+	char c;
+
+	x = SCREEN_INFO.orig_x;
+	y = SCREEN_INFO.orig_y;
+
+	while ( ( c = *s++ ) != '\0' ) {
+		if ( c == '\n' ) {
+			x = 0;
+			if ( ++y >= lines ) {
+				scroll();
+				y--;
+			}
+		} else {
+			vidmem [ ( x + cols * y ) * 2 ] = c; 
+			if ( ++x >= cols ) {
+				x = 0;
+				if ( ++y >= lines ) {
+					scroll();
+					y--;
+				}
+			}
+		}
+	}
+
+	SCREEN_INFO.orig_x = x;
+	SCREEN_INFO.orig_y = y;
+
+	pos = x + cols * y;	/* Update cursor position */
+	while (!(inb_p(0x60) & 4));
+	outb_p(0x49, 0x62);
+	outb_p(pos & 0xff, 0x60);
+	outb_p((pos >> 8) & 0xff, 0x60);
+}
+
+static void* memset(void* s, int c, size_t n)
+{
+	int i;
+	char *ss = (char*)s;
+
+	for (i=0;i<n;i++) ss[i] = c;
+	return s;
+}
+
+static void* memcpy(void* __dest, __const void* __src,
+			    size_t __n)
+{
+	int i;
+	char *d = (char *)__dest, *s = (char *)__src;
+
+	for (i=0;i<__n;i++) d[i] = s[i];
+	return __dest;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf(void)
+{
+	if (insize != 0) {
+		error("ran out of input data\n");
+	}
+
+	inbuf = input_data;
+	insize = input_len;
+	inptr = 1;
+	return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window_low(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, *out, ch;
+    
+    in = window;
+    out = &output_data[output_ptr]; 
+    for (n = 0; n < outcnt; n++) {
+	    ch = *out++ = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    output_ptr += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void flush_window_high(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in,  ch;
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+	ch = *output_data++ = *in++;
+	if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start;
+	c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void flush_window(void)
+{
+	if (high_loaded) flush_window_high();
+	else flush_window_low();
+}
+
+static void error(char *x)
+{
+	puts("\n\n");
+	puts(x);
+	puts("\n\n -- System halted");
+
+	while(1);	/* Halt */
+}
+
+#define STACK_SIZE (4096)
+
+long user_stack [STACK_SIZE];
+
+struct {
+	long * a;
+	short b;
+	} stack_start = { & user_stack [STACK_SIZE] , __BOOT_DS };
+
+static void setup_normal_output_buffer(void)
+{
+#ifdef STANDARD_MEMORY_BIOS_CALL
+	if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n");
+#else
+	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n");
+#endif
+	output_data = (char *)0x100000; /* Points to 1M */
+	free_mem_end_ptr = (long)real_mode;
+}
+
+struct moveparams {
+	uch *low_buffer_start;  int lcount;
+	uch *high_buffer_start; int hcount;
+};
+
+static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+	high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
+#ifdef STANDARD_MEMORY_BIOS_CALL
+	if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n");
+#else
+	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n");
+#endif	
+	mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
+	low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
+	  ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
+	low_buffer_size = low_buffer_end - LOW_BUFFER_START;
+	high_loaded = 1;
+	free_mem_end_ptr = (long)high_buffer_start;
+	if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) {
+		high_buffer_start = (uch *)(0x100000 + low_buffer_size);
+		mv->hcount = 0; /* say: we need not to move high_buffer */
+	}
+	else mv->hcount = -1;
+	mv->high_buffer_start = high_buffer_start;
+}
+
+static void close_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+	if (bytes_out > low_buffer_size) {
+		mv->lcount = low_buffer_size;
+		if (mv->hcount)
+			mv->hcount = bytes_out - low_buffer_size;
+	} else {
+		mv->lcount = bytes_out;
+		mv->hcount = 0;
+	}
+}
+
+
+asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
+{
+	real_mode = rmode;
+
+	vidmem = (char *)(((unsigned int)SCREEN_INFO.orig_video_page) << 4);
+
+	lines = SCREEN_INFO.orig_video_lines;
+	cols = SCREEN_INFO.orig_video_cols;
+
+	if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
+	else setup_output_buffer_if_we_run_high(mv);
+
+	makecrc();
+	puts("Uncompressing Linux... ");
+	gunzip();
+	puts("Ok, booting the kernel.\n");
+	if (high_loaded) close_output_buffer_if_we_run_high(mv);
+	return high_loaded;
+}
+
+/* We don't actually check for stack overflows this early. */
+__asm__(".globl mcount ; mcount: ret\n");
+
diff -urN linux-2.5.65-bk2/arch/i386/boot98/compressed/vmlinux.scr linux-2.5.65-bk3/arch/i386/boot98/compressed/vmlinux.scr
--- linux-2.5.65-bk2/arch/i386/boot98/compressed/vmlinux.scr	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/compressed/vmlinux.scr	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  .data : { 
+	input_len = .;
+	LONG(input_data_end - input_data) input_data = .; 
+	*(.data) 
+	input_data_end = .; 
+	}
+}
diff -urN linux-2.5.65-bk2/arch/i386/boot98/install.sh linux-2.5.65-bk3/arch/i386/boot98/install.sh
--- linux-2.5.65-bk2/arch/i386/boot98/install.sh	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/install.sh	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# arch/i386/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+#
+# "make install" script for i386 architecture
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+# User may have a custom install script
+
+if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
+if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+
+# Default install - same as make zlilo
+
+if [ -f $4/vmlinuz ]; then
+	mv $4/vmlinuz $4/vmlinuz.old
+fi
+
+if [ -f $4/System.map ]; then
+	mv $4/System.map $4/System.old
+fi
+
+cat $2 > $4/vmlinuz
+cp $3 $4/System.map
+
+if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
diff -urN linux-2.5.65-bk2/arch/i386/boot98/setup.S linux-2.5.65-bk3/arch/i386/boot98/setup.S
--- linux-2.5.65-bk2/arch/i386/boot98/setup.S	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/setup.S	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,961 @@
+/*
+ *	setup.S		Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * setup.s is responsible for getting the system data from the BIOS,
+ * and putting them into the appropriate places in system memory.
+ * both setup.s and system has been loaded by the bootblock.
+ *
+ * This code asks the bios for memory/disk/other parameters, and
+ * puts them in a "safe" place: 0x90000-0x901FF, ie where the
+ * boot-block used to be. It is then up to the protected mode
+ * system to read them from there before the area is overwritten
+ * for buffer-blocks.
+ *
+ * Move PS/2 aux init code to psaux.c
+ * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
+ *
+ * some changes and additional features by Christoph Niemann,
+ * March 1993/June 1994 (Christoph.Niemann@linux.org)
+ *
+ * add APM BIOS checking by Stephen Rothwell, May 1994
+ * (sfr@canb.auug.org.au)
+ *
+ * High load stuff, initrd support and position independency
+ * by Hans Lermen & Werner Almesberger, February 1996
+ * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
+ *
+ * Video handling moved to video.S by Martin Mares, March 1996
+ * <mj@k332.feld.cvut.cz>
+ *
+ * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
+ * parsons) to avoid loadlin confusion, July 1997
+ *
+ * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
+ * <stiker@northlink.com>
+ *
+ * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * and/or report extended memory in CX/DX for e801h memory size detection 
+ * call.  As a result the kernel got wrong figures.  The int15/e801h docs
+ * from Ralf Brown interrupt list seem to indicate AX/BX should be used
+ * anyway.  So to avoid breaking many machines (presumably there was a reason
+ * to orginally use CX/DX instead of AX/BX), we do a kludge to see
+ * if CX/DX have been changed in the e801 call and if so use AX/BX .
+ * Michael Miller, April 2001 <michaelm@mjmm.org>
+ *
+ * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
+ * by Robert Schwebel, December 2001 <robert@schwebel.de>
+ *
+ * Heavily modified for NEC PC-9800 series by Kyoto University Microcomputer
+ * Club (KMC) Linux/98 project <seraphim@kmc.kyoto-u.ac.jp>, 1997-1999
+ */
+
+#include <linux/config.h>
+#include <asm/segment.h>
+#include <linux/version.h>
+#include <linux/compile.h>
+#include <asm/boot.h>
+#include <asm/e820.h>
+#include <asm/page.h>
+	
+/* Signature words to ensure LILO loaded us right */
+#define SIG1	0xAA55
+#define SIG2	0x5A5A
+
+#define HIRESO_TEXT	0xe000
+#define NORMAL_TEXT	0xa000
+
+#define BIOS_FLAG2	0x0400
+#define BIOS_FLAG5	0x0458
+#define RDISK_EQUIP	0x0488
+#define BIOS_FLAG	0x0501
+#define KB_SHFT_STS	0x053a
+#define DISK_EQUIP	0x055c
+
+INITSEG  = DEF_INITSEG		# 0x9000, we move boot here, out of the way
+SYSSEG   = DEF_SYSSEG		# 0x1000, system loaded at 0x10000 (65536).
+SETUPSEG = DEF_SETUPSEG		# 0x9020, this is the current segment
+				# ... and the former contents of CS
+
+DELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020
+
+.code16
+.globl begtext, begdata, begbss, endtext, enddata, endbss
+
+.text
+begtext:
+.data
+begdata:
+.bss
+begbss:
+.text
+
+start:
+	jmp	trampoline
+
+# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
+
+		.ascii	"HdrS"		# header signature
+		.word	0x0203		# header version number (>= 0x0105)
+					# or else old loadlin-1.5 will fail)
+realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
+start_sys_seg:	.word	SYSSEG
+		.word	kernel_version	# pointing to kernel version string
+					# above section of header is compatible
+					# with loadlin-1.5 (header v1.5). Don't
+					# change it.
+
+type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
+					#      Bootlin, SYSLX, bootsect...)
+					# See Documentation/i386/boot.txt for
+					# assigned ids
+	
+# flags, unused bits must be zero (RFU) bit within loadflags
+loadflags:
+LOADED_HIGH	= 1			# If set, the kernel is loaded high
+CAN_USE_HEAP	= 0x80			# If set, the loader also has set
+					# heap_end_ptr to tell how much
+					# space behind setup.S can be used for
+					# heap purposes.
+					# Only the loader knows what is free
+#ifndef __BIG_KERNEL__
+		.byte	0
+#else
+		.byte	LOADED_HIGH
+#endif
+
+setup_move_size: .word  0x8000		# size to move, when setup is not
+					# loaded at 0x90000. We will move setup 
+					# to 0x90000 then just before jumping
+					# into the kernel. However, only the
+					# loader knows how much data behind
+					# us also needs to be loaded.
+
+code32_start:				# here loaders can put a different
+					# start address for 32-bit code.
+#ifndef __BIG_KERNEL__
+		.long	0x1000		#   0x1000 = default for zImage
+#else
+		.long	0x100000	# 0x100000 = default for big kernel
+#endif
+
+ramdisk_image:	.long	0		# address of loaded ramdisk image
+					# Here the loader puts the 32-bit
+					# address where it loaded the image.
+					# This only will be read by the kernel.
+
+ramdisk_size:	.long	0		# its size in bytes
+
+bootsect_kludge:
+		.word  bootsect_helper, SETUPSEG
+
+heap_end_ptr:	.word	modelist+1024	# (Header version 0x0201 or later)
+					# space from here (exclusive) down to
+					# end of setup code can be used by setup
+					# for local heap purposes.
+
+pad1:		.word	0
+cmd_line_ptr:	.long 0			# (Header version 0x0202 or later)
+					# If nonzero, a 32-bit pointer
+					# to the kernel command line.
+					# The command line should be
+					# located between the start of
+					# setup and the end of low
+					# memory (0xa0000), or it may
+					# get overwritten before it
+					# gets read.  If this field is
+					# used, there is no longer
+					# anything magical about the
+					# 0x90000 segment; the setup
+					# can be located anywhere in
+					# low memory 0x10000 or higher.
+
+ramdisk_max:	.long __MAXMEM-1	# (Header version 0x0203 or later)
+					# The highest safe address for
+					# the contents of an initrd
+
+trampoline:	call	start_of_setup
+		.space	1024
+# End of setup header #####################################################
+
+start_of_setup:
+# Set %ds = %cs, we know that SETUPSEG = %cs at this point
+	movw	%cs, %ax		# aka SETUPSEG
+	movw	%ax, %ds
+# Check signature at end of setup
+	cmpw	$SIG1, setup_sig1
+	jne	bad_sig
+
+	cmpw	$SIG2, setup_sig2
+	jne	bad_sig
+
+	jmp	good_sig1
+
+# Routine to print asciiz string at ds:si
+prtstr:
+	lodsb
+	andb	%al, %al
+	jz	fin
+
+	call	prtchr
+	jmp	prtstr
+
+fin:	ret
+
+no_sig_mess: .string	"No setup signature found ..."
+
+good_sig1:
+	jmp	good_sig
+
+# We now have to find the rest of the setup code/data
+bad_sig:
+	movw	%cs, %ax			# SETUPSEG
+	subw	$DELTA_INITSEG, %ax		# INITSEG
+	movw	%ax, %ds
+	xorb	%bh, %bh
+	movb	(497), %bl			# get setup sect from bootsect
+	subw	$4, %bx				# LILO loads 4 sectors of setup
+	shlw	$8, %bx				# convert to words (1sect=2^8 words)
+	movw	%bx, %cx
+	shrw	$3, %bx				# convert to segment
+	addw	$SYSSEG, %bx
+	movw	%bx, %cs:start_sys_seg
+# Move rest of setup code/data to here
+	movw	$2048, %di			# four sectors loaded by LILO
+	subw	%si, %si
+	pushw	%cs
+	popw	%es
+	movw	$SYSSEG, %ax
+	movw	%ax, %ds
+	rep
+	movsw
+	movw	%cs, %ax			# aka SETUPSEG
+	movw	%ax, %ds
+	cmpw	$SIG1, setup_sig1
+	jne	no_sig
+
+	cmpw	$SIG2, setup_sig2
+	jne	no_sig
+
+	jmp	good_sig
+
+no_sig:
+	lea	no_sig_mess, %si
+	call	prtstr
+
+no_sig_loop:
+	hlt
+	jmp	no_sig_loop
+
+good_sig:
+	movw	%cs, %ax			# aka SETUPSEG
+	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
+	movw	%ax, %ds
+# Check if an old loader tries to load a big-kernel
+	testb	$LOADED_HIGH, %cs:loadflags	# Do we have a big kernel?
+	jz	loader_ok			# No, no danger for old loaders.
+
+	cmpb	$0, %cs:type_of_loader 		# Do we have a loader that
+						# can deal with us?
+	jnz	loader_ok			# Yes, continue.
+
+	pushw	%cs				# No, we have an old loader,
+	popw	%ds				# die. 
+	lea	loader_panic_mess, %si
+	call	prtstr
+
+	jmp	no_sig_loop
+
+loader_panic_mess: .string "Wrong loader, giving up..."
+
+loader_ok:
+# Get memory size (extended mem, kB)
+
+# On PC-9800, memory size detection is done completely in 32-bit
+# kernel initialize code (kernel/setup.c).
+	pushw	%es
+	xorl	%eax, %eax
+	movw	%ax, %es
+	movb	%al, (E820NR)		# PC-9800 has no E820
+	movb	%es:(0x401), %al
+	shll	$7, %eax
+	addw	$1024, %ax
+	movw	%ax, (2)
+	movl	%eax, (0x1e0)
+	movw	%es:(0x594), %ax
+	shll	$10, %eax
+	addl	%eax, (0x1e0)
+	popw	%es
+
+# Check for video adapter and its parameters and allow the
+# user to browse video modes.
+	call	video				# NOTE: we need %ds pointing
+						# to bootsector
+
+# Get text video mode
+	movb	$0x0B, %ah
+	int	$0x18		# CRT mode sense
+	movw	$(20 << 8) + 40, %cx
+	testb	$0x10, %al
+	jnz	3f
+	movb	$20, %ch
+	testb	$0x01, %al
+	jnz	1f
+	movb	$25, %ch
+	jmp	1f
+3:	# If bit 4 was 1, it means either 1) 31 lines for hi-reso mode,
+	# or 2) 30 lines for PC-9821.
+	movb	$31, %ch	# hireso mode value
+	pushw	$0
+	popw	%es
+	testb	$0x08, %es:BIOS_FLAG
+	jnz	1f
+	movb	$30, %ch
+1:	# Now we got # of rows in %ch
+	movb	%ch, (14)
+
+	testb	$0x02, %al
+	jnz	2f
+	movb	$80, %cl
+2:	# Now we got # of columns in %cl
+	movb	%cl, (7)
+
+	# Next, get horizontal frequency if supported
+	movw	$0x3100, %ax
+	int	$0x18		# Call CRT bios
+	movb	%al, (6)	# If 31h is unsupported, %al remains 0
+
+# Get hd0-3 data...
+	pushw	%ds				# aka INITSEG
+	popw	%es
+	xorw	%ax, %ax
+	movw	%ax, %ds
+	cld
+	movw	$0x0080, %di
+	movb	DISK_EQUIP+1, %ah
+	movb	$0x80, %al
+
+get_hd_info:
+	shrb	%ah
+	pushw	%ax
+	jnc	1f
+	movb	$0x84, %ah
+	int	$0x1b
+	jnc	2f				# Success
+1:	xorw	%cx, %cx			# `0 cylinders' means no drive
+2:	# Attention! Work area (drive_info) is arranged for PC-9800.
+	movw	%cx, %ax			# # of cylinders
+	stosw
+	movw	%dx, %ax			# # of sectors / # of heads
+	stosw
+	movw	%bx, %ax			# sector size in bytes
+	stosw
+	popw	%ax
+	incb	%al
+	cmpb	$0x84, %al
+	jb	get_hd_info
+
+# Get fd data...
+	movw	DISK_EQUIP, %ax
+	andw	$0xf00f, %ax
+	orb	%al, %ah
+	movb	RDISK_EQUIP, %al
+	notb	%al
+	andb	%al, %ah			# ignore all `RAM drive'
+
+	movb	$0x30, %al
+
+get_fd_info:
+	shrb	%ah
+	pushw	%ax
+	jnc	1f
+	movb	$0xc4, %ah
+	int	$0x1b
+	movb	%ah, %al
+	andb	$4, %al				# 1.44MB support flag
+	shrb	%al
+	addb	$2, %al				# %al = 2 (1.2MB) or 4 (1.44MB)
+	jmp	2f
+1:	movb	$0, %al				# no drive
+2:	stosb
+	popw	%ax
+	incb	%al
+	testb	$0x04, %al
+	jz	get_fd_info
+
+	addb	$(0xb0 - 0x34), %al
+	jnc	get_fd_info			# check FDs on 640KB I/F
+
+	pushw	%es
+	popw	%ds				# %ds got bootsector again
+#if 0
+	mov	$0, (0x1ff)			# default is no pointing device
+#endif
+
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+# Then check for an APM BIOS...
+						# %ds points to the bootsector
+	movw	$0, 0x40			# version = 0 means no APM BIOS
+	movw	$0x09a00, %ax			# APM BIOS installation check
+	xorw	%bx, %bx
+	int	$0x1f
+	jc	done_apm_bios			# Nope, no APM BIOS
+
+	cmpw	$0x0504d, %bx			# Check for "PM" signature
+	jne	done_apm_bios			# No signature, no APM BIOS
+
+	testb	$0x02, %cl			# Is 32 bit supported?
+	je	done_apm_bios			# No 32-bit, no (good) APM BIOS
+
+	movw	$0x09a04, %ax			# Disconnect first just in case
+	xorw	%bx, %bx
+	int	$0x1f				# ignore return code
+	movw	$0x09a03, %ax			# 32 bit connect
+	xorl	%ebx, %ebx
+	int	$0x1f
+	jc	no_32_apm_bios			# Ack, error.
+
+	movw	%ax,  (66)			# BIOS code segment
+	movl	%ebx, (68)			# BIOS entry point offset
+	movw	%cx,  (72)			# BIOS 16 bit code segment
+	movw	%dx,  (74)			# BIOS data segment
+	movl	%esi, (78)			# BIOS code segment length
+	movw	%di,  (82)			# BIOS data segment length
+# Redo the installation check as the 32 bit connect
+# modifies the flags returned on some BIOSs
+	movw	$0x09a00, %ax			# APM BIOS installation check
+	xorw	%bx, %bx
+	int	$0x1f
+	jc	apm_disconnect			# error -> shouldn't happen
+
+	cmpw	$0x0504d, %bx			# check for "PM" signature
+	jne	apm_disconnect			# no sig -> shouldn't happen
+
+	movw	%ax, (64)			# record the APM BIOS version
+	movw	%cx, (76)			# and flags
+	jmp	done_apm_bios
+
+apm_disconnect:					# Tidy up
+	movw	$0x09a04, %ax			# Disconnect
+	xorw	%bx, %bx
+	int	$0x1f				# ignore return code
+
+	jmp	done_apm_bios
+
+no_32_apm_bios:
+	andw	$0xfffd, (76)			# remove 32 bit support bit
+done_apm_bios:
+#endif
+
+# Pass cursor position to kernel...
+	movw	%cs:cursor_address, %ax
+	shrw	%ax		# cursor_address is 2 bytes unit
+	movb	$80, %cl
+	divb	%cl
+	xchgb	%al, %ah	# (0) = %al = X, (1) = %ah = Y
+	movw	%ax, (0)
+
+#if 0
+	movw	$msg_cpos, %si
+	call	prtstr_cs
+	call	prthex
+	call	prtstr_cs
+	movw	%ds, %ax
+	call	prthex
+	call	prtstr_cs
+	movb	$0x11, %ah
+	int	$0x18
+	movb	$0, %ah
+	int	$0x18
+	.section .rodata, "a"
+msg_cpos:	.string	"Cursor position: 0x"
+		.string	", %ds:0x"
+		.string	"\r\n"
+	.previous
+#endif
+
+# Now we want to move to protected mode ...
+	cmpw	$0, %cs:realmode_swtch
+	jz	rmodeswtch_normal
+
+	lcall	*%cs:realmode_swtch
+
+	jmp	rmodeswtch_end
+
+rmodeswtch_normal:
+        pushw	%cs
+	call	default_switch
+
+rmodeswtch_end:
+# we get the code32 start address and modify the below 'jmpi'
+# (loader may have changed it)
+	movl	%cs:code32_start, %eax
+	movl	%eax, %cs:code32
+
+# Now we move the system to its rightful place ... but we check if we have a
+# big-kernel. In that case we *must* not move it ...
+	testb	$LOADED_HIGH, %cs:loadflags
+	jz	do_move0			# .. then we have a normal low
+						# loaded zImage
+						# .. or else we have a high
+						# loaded bzImage
+	jmp	end_move			# ... and we skip moving
+
+do_move0:
+	movw	$0x100, %ax			# start of destination segment
+	movw	%cs, %bp			# aka SETUPSEG
+	subw	$DELTA_INITSEG, %bp		# aka INITSEG
+	movw	%cs:start_sys_seg, %bx		# start of source segment
+	cld
+do_move:
+	movw	%ax, %es			# destination segment
+	incb	%ah				# instead of add ax,#0x100
+	movw	%bx, %ds			# source segment
+	addw	$0x100, %bx
+	subw	%di, %di
+	subw	%si, %si
+	movw 	$0x800, %cx
+	rep
+	movsw
+	cmpw	%bp, %bx			# assume start_sys_seg > 0x200,
+						# so we will perhaps read one
+						# page more than needed, but
+						# never overwrite INITSEG
+						# because destination is a
+						# minimum one page below source
+	jb	do_move
+
+end_move:
+# then we load the segment descriptors
+	movw	%cs, %ax			# aka SETUPSEG
+	movw	%ax, %ds
+               
+# Check whether we need to be downward compatible with version <=201
+	cmpl	$0, cmd_line_ptr
+	jne	end_move_self		# loader uses version >=202 features
+	cmpb	$0x20, type_of_loader
+	je	end_move_self		# bootsect loader, we know of it
+ 
+# Boot loader does not support boot protocol version 2.02.
+# If we have our code not at 0x90000, we need to move it there now.
+# We also then need to move the params behind it (commandline)
+# Because we would overwrite the code on the current IP, we move
+# it in two steps, jumping high after the first one.
+	movw	%cs, %ax
+	cmpw	$SETUPSEG, %ax
+	je	end_move_self
+
+	cli					# make sure we really have
+						# interrupts disabled !
+						# because after this the stack
+						# should not be used
+	subw	$DELTA_INITSEG, %ax		# aka INITSEG
+	movw	%ss, %dx
+	cmpw	%ax, %dx
+	jb	move_self_1
+
+	addw	$INITSEG, %dx
+	subw	%ax, %dx			# this will go into %ss after
+						# the move
+move_self_1:
+	movw	%ax, %ds
+	movw	$INITSEG, %ax			# real INITSEG
+	movw	%ax, %es
+	movw	%cs:setup_move_size, %cx
+	std					# we have to move up, so we use
+						# direction down because the
+						# areas may overlap
+	movw	%cx, %di
+	decw	%di
+	movw	%di, %si
+	subw	$move_self_here+0x200, %cx
+	rep
+	movsb
+	ljmp	$SETUPSEG, $move_self_here
+
+move_self_here:
+	movw	$move_self_here+0x200, %cx
+	rep
+	movsb
+	movw	$SETUPSEG, %ax
+	movw	%ax, %ds
+	movw	%dx, %ss
+
+end_move_self:					# now we are at the right place
+	lidt	idt_48				# load idt with 0,0
+	xorl	%eax, %eax			# Compute gdt_base
+	movw	%ds, %ax			# (Convert %ds:gdt to a linear ptr)
+	shll	$4, %eax
+	addl	$gdt, %eax
+	movl	%eax, (gdt_48+2)
+	lgdt	gdt_48				# load gdt with whatever is
+						# appropriate
+
+# that was painless, now we enable A20
+
+	outb	%al, $0xf2			# A20 on
+	movb	$0x02, %al
+	outb	%al, $0xf6			# also A20 on; making ITF's
+						# way our model
+
+	# PC-9800 seems to enable A20 at the moment of `outb';
+	# so we don't wait unlike IBM PCs (see ../setup.S).
+
+# enable DMA to access memory over 0x100000 (1MB).
+
+	movw	$0x439, %dx
+	inb	%dx, %al
+	andb	$(~4), %al
+	outb	%al, %dx
+
+# Set DMA to increment its bank address automatically at 16MB boundary.
+# Initial setting is 64KB boundary mode so that we can't run DMA crossing
+# physical address 0xXXXXFFFF.
+
+	movb	$0x0c, %al
+	outb	%al, $0x29			# ch. 0
+	movb	$0x0d, %al
+	outb	%al, $0x29			# ch. 1
+	movb	$0x0e, %al
+	outb	%al, $0x29			# ch. 2
+	movb	$0x0f, %al
+	outb	%al, $0x29			# ch. 3
+	movb	$0x50, %al
+	outb	%al, $0x11			# reinitialize DMAC
+
+# make sure any possible coprocessor is properly reset..
+	movb	$0, %al
+	outb	%al, $0xf8
+	outb	%al, $0x5f			# delay
+
+# well, that went ok, I hope. Now we mask all interrupts - the rest
+# is done in init_IRQ().
+	movb	$0xFF, %al			# mask all interrupts for now
+	outb	%al, $0x0A
+	outb	%al, $0x5f			# delay
+	
+	movb	$0x7F, %al			# mask all irq's but irq7 which
+	outb	%al, $0x02			# is cascaded
+
+# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
+# need no steenking BIOS anyway (except for the initial loading :-).
+# The BIOS-routine wants lots of unnecessary data, and it's less
+# "interesting" anyway. This is how REAL programmers do it.
+#
+# Well, now's the time to actually move into protected mode. To make
+# things as simple as possible, we do no register set-up or anything,
+# we let the gnu-compiled 32-bit programs do that. We just jump to
+# absolute address 0x1000 (or the loader supplied one),
+# in 32-bit protected mode.
+#
+# Note that the short jump isn't strictly needed, although there are
+# reasons why it might be a good idea. It won't hurt in any case.
+	movw	$1, %ax				# protected mode (PE) bit
+	lmsw	%ax				# This is it!
+	jmp	flush_instr
+
+flush_instr:
+	xorw	%bx, %bx			# Flag to indicate a boot
+	xorl	%esi, %esi			# Pointer to real-mode code
+	movw	%cs, %si
+	subw	$DELTA_INITSEG, %si
+	shll	$4, %esi			# Convert to 32-bit pointer
+# NOTE: For high loaded big kernels we need a
+#	jmpi    0x100000,__BOOT_CS
+#
+#	but we yet haven't reloaded the CS register, so the default size 
+#	of the target offset still is 16 bit.
+#       However, using an operand prefix (0x66), the CPU will properly
+#	take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
+#	Manual, Mixing 16-bit and 32-bit code, page 16-6)
+
+	.byte 0x66, 0xea			# prefix + jmpi-opcode
+code32:	.long	0x1000				# will be set to 0x100000
+						# for big kernels
+	.word	__BOOT_CS
+
+# Here's a bunch of information about your current kernel..
+kernel_version:	.ascii	UTS_RELEASE
+		.ascii	" ("
+		.ascii	LINUX_COMPILE_BY
+		.ascii	"@"
+		.ascii	LINUX_COMPILE_HOST
+		.ascii	") "
+		.ascii	UTS_VERSION
+		.byte	0
+
+# This is the default real mode switch routine.
+# to be called just before protected mode transition
+default_switch:
+	cli					# no interrupts allowed !
+	outb	%al, $0x50			# disable NMI for bootup
+						# sequence
+	lret
+
+# This routine only gets called, if we get loaded by the simple
+# bootsect loader _and_ have a bzImage to load.
+# Because there is no place left in the 512 bytes of the boot sector,
+# we must emigrate to code space here.
+bootsect_helper:
+	cmpw	$0, %cs:bootsect_es
+	jnz	bootsect_second
+
+	movb	$0x20, %cs:type_of_loader
+	movw	%es, %ax
+	shrw	$4, %ax
+	movb	%ah, %cs:bootsect_src_base+2
+	movw	%es, %ax
+	movw	%ax, %cs:bootsect_es
+	subw	$SYSSEG, %ax
+	lret					# nothing else to do for now
+
+bootsect_second:
+	pushw	%bx
+	pushw	%cx
+	pushw	%si
+	pushw	%di
+	testw	%bp, %bp			# 64K full ?
+	jne	bootsect_ex
+
+	xorw	%cx, %cx			# zero means full 64K
+	pushw	%cs
+	popw	%es
+	movw	$bootsect_gdt, %bx
+	xorw	%si, %si			# source address
+	xorw	%di, %di			# destination address
+	movb	$0x90, %ah
+	int	$0x1f
+	jc	bootsect_panic			# this, if INT1F fails
+
+	movw	%cs:bootsect_es, %es		# we reset %es to always point
+	incb	%cs:bootsect_dst_base+2		# to 0x10000
+bootsect_ex:
+	movb	%cs:bootsect_dst_base+2, %ah
+	shlb	$4, %ah				# we now have the number of
+						# moved frames in %ax
+	xorb	%al, %al
+	popw	%di
+	popw	%si
+	popw	%cx
+	popw	%bx
+	lret
+
+bootsect_gdt:
+	.word	0, 0, 0, 0
+	.word	0, 0, 0, 0
+
+bootsect_src:
+	.word	0xffff
+
+bootsect_src_base:
+	.byte	0x00, 0x00, 0x01		# base = 0x010000
+	.byte	0x93				# typbyte
+	.word	0				# limit16,base24 =0
+
+bootsect_dst:
+	.word	0xffff
+
+bootsect_dst_base:
+	.byte	0x00, 0x00, 0x10		# base = 0x100000
+	.byte	0x93				# typbyte
+	.word	0				# limit16,base24 =0
+	.word	0, 0, 0, 0			# BIOS CS
+	.word	0, 0, 0, 0			# BIOS DS
+
+bootsect_es:
+	.word	0
+
+bootsect_panic:
+	pushw	%cs
+	popw	%ds
+	cld
+	leaw	bootsect_panic_mess, %si
+	call	prtstr
+
+bootsect_panic_loop:
+	jmp	bootsect_panic_loop
+
+bootsect_panic_mess:
+	.string	"INT1F refuses to access high mem, giving up."
+
+# This routine prints one character (in %al) on console.
+# PC-9800 doesn't have BIOS-function to do it like IBM PC's INT 10h - 0Eh,
+# so we hardcode `prtchr' subroutine here.
+prtchr:
+	pushaw
+	pushw	%es
+	cmpb	$0, %cs:prtchr_initialized
+	jnz	prtchr_ok
+	xorw	%cx, %cx
+	movw	%cx, %es
+	testb	$0x8, %es:BIOS_FLAG
+	jz	1f
+	movb	$(HIRESO_TEXT >> 8), %cs:cursor_address+3
+	movw	$(80 * 31 * 2), %cs:max_cursor_offset
+1:	pushw	%ax
+	call	get_cursor_position
+	movw	%ax, %cs:cursor_address
+	popw	%ax
+	movb	$1, %cs:prtchr_initialized
+prtchr_ok:
+	lesw	%cs:cursor_address, %di
+	movw	$160, %bx
+	movb	$0, %ah
+	cmpb	$13, %al
+	je	do_cr
+	cmpb	$10, %al
+	je	do_lf
+
+	# normal (printable) character
+	stosw
+	movb	$0xe1, %es:0x2000-2(%di)
+	jmp	1f
+
+do_cr:	movw	%di, %ax
+	divb	%bl				# %al = Y, %ah = X * 2
+	mulb	%bl
+	movw	%ax, %dx
+	jmp	2f
+
+do_lf:	addw	%bx, %di
+1:	movw	%cs:max_cursor_offset, %cx
+	cmpw	%cx, %di
+	movw	%di, %dx
+	jb	2f
+	# cursor reaches bottom of screen; scroll it
+	subw	%bx, %dx
+	xorw	%di, %di
+	movw	%bx, %si
+	cld
+	subw	%bx, %cx
+	shrw	%cx
+	pushw	%cx
+	rep; es; movsw
+	movb	$32, %al			# clear bottom line characters
+	movb	$80, %cl
+	rep; stosw
+	movw	$0x2000, %di
+	popw	%cx
+	leaw	(%bx,%di), %si
+	rep; es; movsw
+	movb	$0xe1, %al			# clear bottom line attributes
+	movb	$80, %cl
+	rep; stosw
+2:	movw	%dx, %cs:cursor_address
+	movb	$0x13, %ah			# move cursor to right position
+	int	$0x18
+	popw	%es
+	popaw
+	ret
+
+cursor_address:
+	.word	0
+	.word	NORMAL_TEXT
+max_cursor_offset:
+	.word	80 * 25 * 2			# for normal 80x25 mode
+
+# putstr may called without running through start_of_setup (via bootsect_panic)
+# so we should initialize ourselves on demand.
+prtchr_initialized:
+	.byte	0
+
+# This routine queries GDC (graphic display controller) for current cursor
+# position. Cursor position is returned in %ax (CPU offset address).
+get_cursor_position:
+1:	inb	$0x60, %al
+	outb	%al, $0x5f			# delay
+	outb	%al, $0x5f			# delay
+	testb	$0x04, %al			# Is FIFO empty?
+	jz	1b				# no -> wait until empty
+
+	movb	$0xe0, %al			# CSRR command
+	outb	%al, $0x62			# command write
+	outb	%al, $0x5f			# delay
+	outb	%al, $0x5f			# delay
+
+2:	inb	$0x60, %al
+	outb	%al, $0x5f			# delay
+	outb	%al, $0x5f			# delay
+	testb	$0x01, %al			# Is DATA READY?
+	jz	2b				# no -> wait until ready
+
+	inb	$0x62, %al			# read xAD (L)
+	outb	%al, $0x5f			# delay
+	outb	%al, $0x5f			# delay
+	movb	%al, %ah
+	inb	$0x62, %al			# read xAD (H)
+	outb	%al, $0x5f			# delay
+	outb	%al, $0x5f			# delay
+	xchgb	%al, %ah			# correct byte order
+	pushw	%ax
+	inb	$0x62, %al			# read yAD (L)
+	outb	%al, $0x5f			# delay
+	outb	%al, $0x5f			# delay
+	inb	$0x62, %al			# read yAD (M)
+	outb	%al, $0x5f			# delay
+	outb	%al, $0x5f			# delay
+	inb	$0x62, %al			# read yAD (H)
+						# yAD is not our interest,
+						# so discard it.
+	popw	%ax
+	addw	%ax, %ax			# convert to CPU address
+	ret
+
+# Descriptor tables
+#
+# NOTE: The intel manual says gdt should be sixteen bytes aligned for
+# efficiency reasons.  However, there are machines which are known not
+# to boot with misaligned GDTs, so alter this at your peril!  If you alter
+# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
+# empty GDT entries (one for NULL and one reserved).
+#
+# NOTE:	On some CPUs, the GDT must be 8 byte aligned.  This is
+# true for the Voyager Quad CPU card which will not boot without
+# This directive.  16 byte aligment is recommended by intel.
+#
+	.align 16
+gdt:
+	.fill GDT_ENTRY_BOOT_CS,8,0
+
+	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
+	.word	0				# base address = 0
+	.word	0x9A00				# code read/exec
+	.word	0x00CF				# granularity = 4096, 386
+						#  (+5th nibble of limit)
+
+	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
+	.word	0				# base address = 0
+	.word	0x9200				# data read/write
+	.word	0x00CF				# granularity = 4096, 386
+						#  (+5th nibble of limit)
+gdt_end:
+	.align	4
+	
+	.word	0				# alignment byte
+idt_48:
+	.word	0				# idt limit = 0
+	.word	0, 0				# idt base = 0L
+
+	.word	0				# alignment byte
+gdt_48:
+	.word	gdt_end - gdt - 1		# gdt limit
+	.word	0, 0				# gdt base (filled in later)
+
+# Include video setup & detection code
+
+#include "video.S"
+
+# Setup signature -- must be last
+setup_sig1:	.word	SIG1
+setup_sig2:	.word	SIG2
+
+# After this point, there is some free space which is used by the video mode
+# handling code to store the temporary mode table (not used by the kernel).
+
+modelist:
+
+.text
+endtext:
+.data
+enddata:
+.bss
+endbss:
diff -urN linux-2.5.65-bk2/arch/i386/boot98/tools/build.c linux-2.5.65-bk3/arch/i386/boot98/tools/build.c
--- linux-2.5.65-bk2/arch/i386/boot98/tools/build.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/tools/build.c	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,188 @@
+/*
+ *  $Id: build.c,v 1.5 1997/05/19 12:29:58 mj Exp $
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1997 Martin Mares
+ */
+
+/*
+ * This file builds a disk-image from three different files:
+ *
+ * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - setup: 8086 machine code, sets up system parm
+ * - system: 80386 code for actual system
+ *
+ * It does some checking that all files are of the correct type, and
+ * just writes the result to stdout, removing headers and padding to
+ * the right amount. It also writes some system data to stderr.
+ */
+
+/*
+ * Changes by tytso to allow root device specification
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ * Cross compiling fixes by Gertjan van Wingerde, July 1996
+ * Rewritten by Martin Mares, April 1997
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <asm/boot.h>
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long u32;
+
+#define DEFAULT_MAJOR_ROOT 0
+#define DEFAULT_MINOR_ROOT 0
+
+/* Minimal number of setup sectors (see also bootsect.S) */
+#define SETUP_SECTS 4
+
+byte buf[1024];
+int fd;
+int is_big_kernel;
+
+void die(const char * str, ...)
+{
+	va_list args;
+	va_start(args, str);
+	vfprintf(stderr, str, args);
+	fputc('\n', stderr);
+	exit(1);
+}
+
+void file_open(const char *name)
+{
+	if ((fd = open(name, O_RDONLY, 0)) < 0)
+		die("Unable to open `%s': %m", name);
+}
+
+void usage(void)
+{
+	die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
+}
+
+int main(int argc, char ** argv)
+{
+	unsigned int i, c, sz, setup_sectors;
+	u32 sys_size;
+	byte major_root, minor_root;
+	struct stat sb;
+
+	if (argc > 2 && !strcmp(argv[1], "-b"))
+	  {
+	    is_big_kernel = 1;
+	    argc--, argv++;
+	  }
+	if ((argc < 4) || (argc > 5))
+		usage();
+	if (argc > 4) {
+		if (!strcmp(argv[4], "CURRENT")) {
+			if (stat("/", &sb)) {
+				perror("/");
+				die("Couldn't stat /");
+			}
+			major_root = major(sb.st_dev);
+			minor_root = minor(sb.st_dev);
+		} else if (strcmp(argv[4], "FLOPPY")) {
+			if (stat(argv[4], &sb)) {
+				perror(argv[4]);
+				die("Couldn't stat root device.");
+			}
+			major_root = major(sb.st_rdev);
+			minor_root = minor(sb.st_rdev);
+		} else {
+			major_root = 0;
+			minor_root = 0;
+		}
+	} else {
+		major_root = DEFAULT_MAJOR_ROOT;
+		minor_root = DEFAULT_MINOR_ROOT;
+	}
+	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
+
+	file_open(argv[1]);
+	i = read(fd, buf, sizeof(buf));
+	fprintf(stderr,"Boot sector %d bytes.\n",i);
+	if (i != 512)
+		die("Boot block must be exactly 512 bytes");
+	if (buf[510] != 0x55 || buf[511] != 0xaa)
+		die("Boot block hasn't got boot flag (0xAA55)");
+	buf[508] = minor_root;
+	buf[509] = major_root;
+	if (write(1, buf, 512) != 512)
+		die("Write call failed");
+	close (fd);
+
+	file_open(argv[2]);				    /* Copy the setup code */
+	for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
+		if (write(1, buf, c) != c)
+			die("Write call failed");
+	if (c != 0)
+		die("read-error on `setup'");
+	close (fd);
+
+	setup_sectors = (i + 511) / 512;	/* Pad unused space with zeros */
+	if (!(setup_sectors & 1))
+		setup_sectors++;    /* setup_sectors must be odd on NEC PC-9800 */
+	fprintf(stderr, "Setup is %d bytes.\n", i);
+	memset(buf, 0, sizeof(buf));
+	while (i < setup_sectors * 512) {
+		c = setup_sectors * 512 - i;
+		if (c > sizeof(buf))
+			c = sizeof(buf);
+		if (write(1, buf, c) != c)
+			die("Write call failed");
+		i += c;
+	}
+
+	file_open(argv[3]);
+	if (fstat (fd, &sb))
+		die("Unable to stat `%s': %m", argv[3]);
+	sz = sb.st_size;
+	fprintf (stderr, "System is %d kB\n", sz/1024);
+	sys_size = (sz + 15) / 16;
+	/* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
+	if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
+		die("System is too big. Try using %smodules.",
+			is_big_kernel ? "" : "bzImage or ");
+	if (sys_size > 0xefff)
+		fprintf(stderr,"warning: kernel is too big for standalone boot "
+		    "from floppy\n");
+	while (sz > 0) {
+		int l, n;
+
+		l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
+		if ((n=read(fd, buf, l)) != l) {
+			if (n < 0)
+				die("Error reading %s: %m", argv[3]);
+			else
+				die("%s: Unexpected EOF", argv[3]);
+		}
+		if (write(1, buf, l) != l)
+			die("Write failed");
+		sz -= l;
+	}
+	close(fd);
+
+	if (lseek(1, 497, SEEK_SET) != 497)		    /* Write sizes to the bootsector */
+		die("Output: seek failed");
+	buf[0] = setup_sectors;
+	if (write(1, buf, 1) != 1)
+		die("Write of setup sector count failed");
+	if (lseek(1, 500, SEEK_SET) != 500)
+		die("Output: seek failed");
+	buf[0] = (sys_size & 0xff);
+	buf[1] = ((sys_size >> 8) & 0xff);
+	if (write(1, buf, 2) != 2)
+		die("Write of image length failed");
+
+	return 0;					    /* Everything is OK */
+}
diff -urN linux-2.5.65-bk2/arch/i386/boot98/video.S linux-2.5.65-bk3/arch/i386/boot98/video.S
--- linux-2.5.65-bk2/arch/i386/boot98/video.S	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/boot98/video.S	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,262 @@
+/*	video.S
+ *
+ *  Video mode setup, etc. for NEC PC-9800 series.
+ *
+ *  Copyright (C) 1997,98,99  Linux/98 project  <seraphim@kmc.kyoto-u.ac.jp>
+ *
+ *  Based on the video.S for IBM PC:
+ *	copyright (C) Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+/* Positions of various video parameters passed to the kernel */
+/* (see also include/linux/tty.h) */
+#define PARAM_CURSOR_POS	0x00
+#define PARAM_VIDEO_PAGE	0x04
+#define PARAM_VIDEO_MODE	0x06
+#define PARAM_VIDEO_COLS	0x07
+#define PARAM_VIDEO_EGA_BX	0x0a
+#define PARAM_VIDEO_LINES	0x0e
+#define PARAM_HAVE_VGA		0x0f
+#define PARAM_FONT_POINTS	0x10
+
+#define PARAM_VIDEO98_COMPAT	0x0a
+#define PARAM_VIDEO98_HIRESO	0x0b
+#define PARAM_VIDEO98_MACHTYPE	0x0c
+#define PARAM_VIDEO98_LINES	0x0e
+#define PARAM_VIDEO98_COLS	0x0f
+
+# PARAM_LFB_* and PARAM_VESAPM_* are unused on PC-9800.
+
+# This is the main entry point called by setup.S
+# %ds *must* be pointing to the bootsector
+video:	xorw	%ax, %ax
+	movw	%ax, %es			# %es = 0
+
+	movb	%es:BIOS_FLAG, %al
+	movb	%al, PARAM_VIDEO_MODE
+
+	movb	$0, PARAM_VIDEO98_HIRESO	# 0 = normal
+	movw	$NORMAL_TEXT, PARAM_VIDEO_PAGE
+	testb	$0x8, %al
+	movw	$(80 * 256 + 25), %ax
+	jz	1f
+	# hireso machine.
+	movb	$1, PARAM_VIDEO98_HIRESO	# !0 = hi-reso
+	movb	$(HIRESO_TEXT >> 8), PARAM_VIDEO_PAGE + 1
+	movw	$(80 * 256 + 31), %ax
+1:	movw	%ax, PARAM_VIDEO98_LINES	# also sets VIDEO98_COLS
+
+	movb	$0xc0, %ch			# 400-line graphic mode
+	movb	$0x42, %ah
+	int	$0x18
+
+	movw	$80, PARAM_VIDEO_COLS
+
+	movw	$msg_probing, %si
+	call	prtstr_cs
+
+# Check vendor from font pattern of `A'...
+
+1:	inb	$0x60, %al			# wait V-sync
+	testb	$0x20, %al
+	jnz	1b
+2:	inb	$0x60, %al
+	testb	$0x20, %al
+	jz	2b
+
+	movb	$0x00, %al			# select font of `A'
+	outb	%al, $0xa1
+	movb	$0x41, %al
+	outb	%al, $0xa3
+
+	movw	$8, %cx
+	movw	PARAM_VIDEO_PAGE, %ax
+	cmpw	$NORMAL_TEXT, %ax
+	je	3f
+	movb	$24, %cl			# for hi-reso machine
+3:	addw	$0x400, %ax			# %ax = CG window segment
+	pushw	%ds
+	movw	%ax, %ds
+	xorw	%dx, %dx			# get sum of `A' pattern...
+	xorw	%si, %si
+4:	lodsw
+	addw	%ax, %dx
+	loop	4b
+	popw	%ds
+
+	movw	%dx, %ax
+	movw	$msg_nec, %si
+	xorw	%bx, %bx			# vendor info will go into %bx
+	testb	$8, %es:BIOS_FLAG
+	jnz	check_hireso_vendor
+	cmpw	$0xc7f8, %ax
+	je	5f
+	jmp	6f
+check_hireso_vendor:
+	cmpw	$0x9639, %ax			# XXX: NOT VERIFIED!!!
+	je	5f
+6:	incw	%bx				# compatible machine
+	movw	$msg_compat, %si
+5:	movb	%bl, PARAM_VIDEO98_COMPAT
+	call	prtstr_cs
+
+	movw	$msg_fontdata, %si
+	call	prtstr_cs			# " (CG sum of A = 0x"
+	movw	%dx, %ax
+	call	prthex
+	call	prtstr_cs			# ") PC-98"
+
+	movb	$'0', %al
+	pushw	%ds
+	pushw	$0xf8e8
+	popw	%ds
+	cmpw	$0x2198, (0)
+	popw	%ds
+	jne	7f
+	movb	$'2', %al
+7:	call	prtchr
+	call	prtstr_cs			# "1 "
+
+	movb	$0, PARAM_VIDEO98_MACHTYPE
+#if 0	/* XXX - This check is bogus? [0000:BIOS_FLAG2]-bit7 does NOT
+		 indicate whether it is a note machine, but merely indicates
+		 whether it has ``RAM drive''. */
+# check note machine
+	testb	$0x80, %es:BIOS_FLAG2
+	jnz	is_note
+	pushw	%ds
+	pushw	$0xfd80
+	popw	%ds
+	movb	(4), %al
+	popw	%ds
+	cmpb	$0x20, %al			# EPSON note A
+	je	epson_note
+	cmpb	$0x22, %al			# EPSON note W
+	je	epson_note
+	cmpb	$0x27, %al			# EPSON note AE
+	je	epson_note
+	cmpb	$0x2a, %al			# EPSON note WR
+	jne	note_done
+epson_note:
+	movb	$1, PARAM_VIDEO98_MACHTYPE
+	movw	$msg_note, %si
+	call	prtstr_cs
+note_done:
+#endif
+	
+# print h98 ? (only NEC)
+	cmpb	$0, PARAM_VIDEO98_COMPAT
+	jnz	8f				# not NEC -> not H98
+
+	testb	$0x80, %es:BIOS_FLAG5
+	jz	8f				# have NESA bus -> H98
+	movw	$msg_h98, %si
+	call	prtstr_cs
+	orb	$2, PARAM_VIDEO98_MACHTYPE
+8:	testb	$0x40, %es:BIOS_FLAG5
+	jz	9f
+	movw	$msg_gs, %si
+	call	prtstr_cs			# only prints it :-)
+9:
+	movw	$msg_normal, %si		# "normal"
+	testb	$0x8, %es:BIOS_FLAG
+	jz	1f
+	movw	$msg_hireso, %si
+1:	call	prtstr_cs
+
+	movw	$msg_sysclk, %si
+	call	prtstr_cs
+	movb	$'5', %al
+	testb	$0x80, %es:BIOS_FLAG
+	jz	2f
+	movb	$'8', %al
+2:	call	prtchr
+	call	prtstr_cs
+
+#if 0
+	testb	$0x40, %es:(0x45c)
+	jz	no_30line			# no 30-line support
+
+	movb	%es:KB_SHFT_STS, %al
+	testb	$0x01, %al			# is SHIFT key pressed?
+	jz	no_30line
+
+	testb	$0x10, %al			# is CTRL key pressed?
+	jnz	line40
+
+	# switch to 30-line mode
+	movb	$30, PARAM_VIDEO98_LINES
+	movw	$msg_30line, %si
+	jmp	3f
+
+line40:
+	movb	$37, PARAM_VIDEO98_LINES
+	movw	$40, PARAM_VIDEO_LINES
+	movw	$msg_40line, %si
+3:	call	prtstr_cs
+
+	movb	$0x32, %bh
+	movw	$0x300c, %ax
+	int	$0x18				# switch video mode
+	movb	$0x0c, %ah
+	int	$0x18				# turn on text plane
+	movw	%cs:cursor_address, %dx
+	movb	$0x13, %ah
+	int	$0x18				# move cursor to correct place
+	mov	$0x11, %ah
+	int	$0x18				# turn on text plane
+
+	call	prtstr_cs			# "Ok.\r\n"
+no_30line:
+#endif
+	ret
+
+prtstr_cs:
+	pushw	%ds
+	pushw	%cs
+	popw	%ds
+	call	prtstr
+	popw	%ds
+	ret
+
+# prthex is for debugging purposes, and prints %ax in hexadecimal.
+prthex:	pushw	%cx
+	movw	$4, %cx
+1:	rolw	$4, %ax
+	pushw	%ax
+	andb	$0xf, %al
+	cmpb	$10, %al
+	sbbb	$0x69, %al
+	das
+	call	prtchr
+	popw	%ax
+	loop	1b
+	popw	%cx
+	ret
+
+msg_probing:	.string	"Probing machine: "
+
+msg_nec:	.string	"NEC"
+msg_compat:	.string	"compatible"
+
+msg_fontdata:	.string	" (CG sum of A = 0x"
+		.string	") PC-98"
+		.string	"1 "
+
+msg_gs:		.string	"(GS) "
+msg_h98:	.string	"(H98) "
+
+msg_normal:	.string	"normal"
+msg_hireso:	.string	"Hi-reso"
+
+msg_sysclk:	.string	" mode, system clock "
+		.string	"MHz\r\n"
+
+#if 0
+msg_40line:	# cpp will concat following lines, so the assembler can deal.
+		.ascii	"\
+Video mode will be adjusted to 37-line (so-called ``40-line'') mode later.\r\n\
+THIS MODE MAY DAMAGE YOUR MONITOR PHYSICALLY. USE AT YOUR OWN RISK.\r\n"
+msg_30line:	.string	"Switching video mode to 30-line (640x480) mode... "
+		.string	"Ok.\r\n"
+#endif
diff -urN linux-2.5.65-bk2/arch/i386/kernel/dmi_scan.c linux-2.5.65-bk3/arch/i386/kernel/dmi_scan.c
--- linux-2.5.65-bk2/arch/i386/kernel/dmi_scan.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk3/arch/i386/kernel/dmi_scan.c	Mon Mar 31 12:41:39 2003
@@ -499,6 +499,19 @@
 	return 0;
 }
 
+/*
+ *	Exploding PnPBIOS. Don't yet know if its the BIOS or us for
+ *	some entries
+ */
+
+static __init int exploding_pnp_bios(struct dmi_blacklist *d)
+{
+	printk(KERN_WARNING "%s detected. Disabling PnPBIOS\n", d->ident);
+	dmi_broken |= BROKEN_PNP_BIOS;
+	return 0;
+}
+
+
 
 /*
  *	Simple "print if true" callback
@@ -687,6 +700,13 @@
 			MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
 			MATCH(DMI_BIOS_DATE, "10/26/01"), NO_MATCH
 			} },
+			
+	{ exploding_pnp_bios, "Higraded P14H", {	/* BIOSPnP problem */
+			MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
+			MATCH(DMI_BIOS_VERSION, "07.00T"),
+			MATCH(DMI_SYS_VENDOR, "Higraded"),
+			MATCH(DMI_PRODUCT_NAME, "P14H")
+			} },
 
 	/* Machines which have problems handling enabled local APICs */
 
diff -urN linux-2.5.65-bk2/arch/i386/mach-pc9800/Makefile linux-2.5.65-bk3/arch/i386/mach-pc9800/Makefile
--- linux-2.5.65-bk2/arch/i386/mach-pc9800/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/mach-pc9800/Makefile	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
+
+EXTRA_CFLAGS	+= -I../kernel
+
+obj-y				:= setup.o topology.o
diff -urN linux-2.5.65-bk2/arch/i386/mach-pc9800/setup.c linux-2.5.65-bk3/arch/i386/mach-pc9800/setup.c
--- linux-2.5.65-bk2/arch/i386/mach-pc9800/setup.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/mach-pc9800/setup.c	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,117 @@
+/*
+ *	Machine specific setup for pc9800
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/apm_bios.h>
+#include <asm/setup.h>
+#include <asm/arch_hooks.h>
+
+struct sys_desc_table_struct {
+	unsigned short length;
+	unsigned char table[0];
+};
+
+/**
+ * pre_intr_init_hook - initialisation prior to setting up interrupt vectors
+ *
+ * Description:
+ *	Perform any necessary interrupt initialisation prior to setting up
+ *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA
+ *	interrupts should be initialised here if the machine emulates a PC
+ *	in any way.
+ **/
+void __init pre_intr_init_hook(void)
+{
+	init_ISA_irqs();
+}
+
+/*
+ * IRQ7 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq7 = { no_action, 0, 0, "cascade", NULL, NULL};
+
+/**
+ * intr_init_hook - post gate setup interrupt initialisation
+ *
+ * Description:
+ *	Fill in any interrupts that may have been left out by the general
+ *	init_IRQ() routine.  interrupts having to do with the machine rather
+ *	than the devices on the I/O bus (like APIC interrupts in intel MP
+ *	systems) are started here.
+ **/
+void __init intr_init_hook(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	apic_intr_init();
+#endif
+
+	setup_irq(7, &irq7);
+}
+
+/**
+ * pre_setup_arch_hook - hook called prior to any setup_arch() execution
+ *
+ * Description:
+ *	generally used to activate any machine specific identification
+ *	routines that may be needed before setup_arch() runs.  On VISWS
+ *	this is used to get the board revision and type.
+ **/
+void __init pre_setup_arch_hook(void)
+{
+	SYS_DESC_TABLE.length = 0;
+	MCA_bus = 0;
+	/* In PC-9800, APM BIOS version is written in BCD...?? */
+	APM_BIOS_INFO.version = (APM_BIOS_INFO.version & 0xff00)
+				| ((APM_BIOS_INFO.version & 0x00f0) >> 4);
+}
+
+/**
+ * trap_init_hook - initialise system specific traps
+ *
+ * Description:
+ *	Called as the final act of trap_init().  Used in VISWS to initialise
+ *	the various board specific APIC traps.
+ **/
+void __init trap_init_hook(void)
+{
+}
+
+static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
+
+/**
+ * time_init_hook - do any specific initialisations for the system timer.
+ *
+ * Description:
+ *	Must plug the system timer interrupt source at HZ into the IRQ listed
+ *	in irq_vectors.h:TIMER_IRQ
+ **/
+void __init time_init_hook(void)
+{
+	setup_irq(0, &irq0);
+}
+
+#ifdef CONFIG_MCA
+/**
+ * mca_nmi_hook - hook into MCA specific NMI chain
+ *
+ * Description:
+ *	The MCA (Microchannel Architecture) has an NMI chain for NMI sources
+ *	along the MCA bus.  Use this to hook into that chain if you will need
+ *	it.
+ **/
+void __init mca_nmi_hook(void)
+{
+	/* If I recall correctly, there's a whole bunch of other things that
+	 * we can do to check for NMI problems, but that's all I know about
+	 * at the moment.
+	 */
+
+	printk("NMI generated from unknown source!\n");
+}
+#endif
diff -urN linux-2.5.65-bk2/arch/i386/mach-pc9800/topology.c linux-2.5.65-bk3/arch/i386/mach-pc9800/topology.c
--- linux-2.5.65-bk2/arch/i386/mach-pc9800/topology.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/arch/i386/mach-pc9800/topology.c	Mon Mar 31 12:41:39 2003
@@ -0,0 +1,44 @@
+/*
+ * arch/i386/mach-pc9800/topology.c - Populate driverfs with topology information
+ *
+ * Written by: Matthew Dobson, IBM Corporation
+ * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
+ *
+ * Copyright (C) 2002, IBM Corp.
+ *
+ * All rights reserved.          
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Modify for PC-9800 by Osamu Tomita <tomita@cinet.co.jp>
+ *
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/cpu.h>
+
+struct i386_cpu cpu_devices[NR_CPUS];
+
+static int __init topology_init(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++)
+		if (cpu_possible(i)) arch_register_cpu(i);
+	return 0;
+}
+
+subsys_initcall(topology_init);
diff -urN linux-2.5.65-bk2/arch/i386/pci/pcbios.c linux-2.5.65-bk3/arch/i386/pci/pcbios.c
--- linux-2.5.65-bk2/arch/i386/pci/pcbios.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/arch/i386/pci/pcbios.c	Mon Mar 31 12:41:39 2003
@@ -5,22 +5,9 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include "pci.h"
+#include "pci-functions.h"
 
 
-#define PCIBIOS_PCI_FUNCTION_ID 	0xb1XX
-#define PCIBIOS_PCI_BIOS_PRESENT 	0xb101
-#define PCIBIOS_FIND_PCI_DEVICE		0xb102
-#define PCIBIOS_FIND_PCI_CLASS_CODE	0xb103
-#define PCIBIOS_GENERATE_SPECIAL_CYCLE	0xb106
-#define PCIBIOS_READ_CONFIG_BYTE	0xb108
-#define PCIBIOS_READ_CONFIG_WORD	0xb109
-#define PCIBIOS_READ_CONFIG_DWORD	0xb10a
-#define PCIBIOS_WRITE_CONFIG_BYTE	0xb10b
-#define PCIBIOS_WRITE_CONFIG_WORD	0xb10c
-#define PCIBIOS_WRITE_CONFIG_DWORD	0xb10d
-#define PCIBIOS_GET_ROUTING_OPTIONS	0xb10e
-#define PCIBIOS_SET_PCI_HW_INT		0xb10f
-
 /* BIOS32 signature: "_32_" */
 #define BIOS32_SIGNATURE	(('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
 
diff -urN linux-2.5.65-bk2/arch/s390x/kernel/exec32.c linux-2.5.65-bk3/arch/s390x/kernel/exec32.c
--- linux-2.5.65-bk2/arch/s390x/kernel/exec32.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/arch/s390x/kernel/exec32.c	Mon Mar 31 12:41:39 2003
@@ -21,7 +21,6 @@
 #include <linux/highmem.h>
 #include <linux/spinlock.h>
 #include <linux/binfmts.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <asm/uaccess.h>
diff -urN linux-2.5.65-bk2/arch/um/drivers/ubd_kern.c linux-2.5.65-bk3/arch/um/drivers/ubd_kern.c
--- linux-2.5.65-bk2/arch/um/drivers/ubd_kern.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/arch/um/drivers/ubd_kern.c	Mon Mar 31 12:41:39 2003
@@ -507,7 +507,7 @@
 	/* /dev/ubd/N style names */
 	sprintf(devfs_name, "%d", unit);
 	*handle_out = devfs_register(dir_handle, devfs_name,
-				     DEVFS_FL_REMOVABLE, major, minor,
+				     0, major, minor,
 				     S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
 				     S_IWGRP, &ubd_blops, NULL);
 	disk->private_data = &ubd_dev[unit];
diff -urN linux-2.5.65-bk2/drivers/char/Makefile linux-2.5.65-bk3/drivers/char/Makefile
--- linux-2.5.65-bk2/drivers/char/Makefile	Mon Mar 17 13:44:45 2003
+++ linux-2.5.65-bk3/drivers/char/Makefile	Mon Mar 31 12:41:40 2003
@@ -44,6 +44,7 @@
 
 obj-$(CONFIG_PRINTER) += lp.o
 obj-$(CONFIG_TIPAR) += tipar.o
+obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o
 
 obj-$(CONFIG_BUSMOUSE) += busmouse.o
 obj-$(CONFIG_DTLK) += dtlk.o
diff -urN linux-2.5.65-bk2/drivers/char/drm/ati_pcigart.h linux-2.5.65-bk3/drivers/char/drm/ati_pcigart.h
--- linux-2.5.65-bk2/drivers/char/drm/ati_pcigart.h	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/drivers/char/drm/ati_pcigart.h	Mon Mar 31 12:41:40 2003
@@ -27,7 +27,6 @@
  *   Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 #if PAGE_SIZE == 65536
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_agpsupport.h linux-2.5.65-bk3/drivers/char/drm/drm_agpsupport.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_agpsupport.h	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_agpsupport.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 #include <linux/module.h>
 
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_auth.h linux-2.5.65-bk3/drivers/char/drm/drm_auth.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_auth.h	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_auth.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 static int DRM(hash_magic)(drm_magic_t magic)
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_bufs.h linux-2.5.65-bk3/drivers/char/drm/drm_bufs.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_bufs.h	Mon Mar 17 13:43:47 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_bufs.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include <linux/vmalloc.h>
 #include "drmP.h"
 
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_context.h linux-2.5.65-bk3/drivers/char/drm/drm_context.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_context.h	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_context.h	Mon Mar 31 12:41:40 2003
@@ -33,7 +33,6 @@
  *		needed by SiS driver's memory management.
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 #if __HAVE_CTX_BITMAP
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_dma.h linux-2.5.65-bk3/drivers/char/drm/drm_dma.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_dma.h	Mon Mar 17 13:44:15 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_dma.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 #include <linux/interrupt.h>	/* For task queue support */
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_drawable.h linux-2.5.65-bk3/drivers/char/drm/drm_drawable.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_drawable.h	Mon Mar 17 13:44:39 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_drawable.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 int DRM(adddraw)(struct inode *inode, struct file *filp,
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_fops.h linux-2.5.65-bk3/drivers/char/drm/drm_fops.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_fops.h	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_fops.h	Mon Mar 31 12:41:40 2003
@@ -30,7 +30,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 #include <linux/poll.h>
 
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_init.h linux-2.5.65-bk3/drivers/char/drm/drm_init.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_init.h	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_init.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 #if 0
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_ioctl.h linux-2.5.65-bk3/drivers/char/drm/drm_ioctl.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_ioctl.h	Mon Mar 17 13:43:48 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_ioctl.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_lists.h linux-2.5.65-bk3/drivers/char/drm/drm_lists.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_lists.h	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_lists.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 #if __HAVE_DMA_WAITLIST
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_lock.h linux-2.5.65-bk3/drivers/char/drm/drm_lock.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_lock.h	Mon Mar 17 13:44:18 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_lock.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 int DRM(block)(struct inode *inode, struct file *filp, unsigned int cmd,
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_memory.h linux-2.5.65-bk3/drivers/char/drm/drm_memory.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_memory.h	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_memory.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include "drmP.h"
 #include <linux/wrapper.h>
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_os_linux.h linux-2.5.65-bk3/drivers/char/drm/drm_os_linux.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_os_linux.h	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_os_linux.h	Mon Mar 31 12:41:40 2003
@@ -1,4 +1,3 @@
-#define __NO_VERSION__
 
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/delay.h>
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_proc.h linux-2.5.65-bk3/drivers/char/drm/drm_proc.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_proc.h	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_proc.h	Mon Mar 31 12:41:40 2003
@@ -33,7 +33,6 @@
  *    the problem with the proc files not outputting all their information.
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 static int	   DRM(name_info)(char *buf, char **start, off_t offset,
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_scatter.h linux-2.5.65-bk3/drivers/char/drm/drm_scatter.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_scatter.h	Mon Mar 17 13:44:11 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_scatter.h	Mon Mar 31 12:41:40 2003
@@ -27,7 +27,6 @@
  *   Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/vmalloc.h>
 #include "drmP.h"
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_stub.h linux-2.5.65-bk3/drivers/char/drm/drm_stub.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_stub.h	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_stub.h	Mon Mar 31 12:41:40 2003
@@ -28,7 +28,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 #define DRM_STUB_MAXCARDS 16	/* Enough for one machine */
diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_vm.h linux-2.5.65-bk3/drivers/char/drm/drm_vm.h
--- linux-2.5.65-bk2/drivers/char/drm/drm_vm.h	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/drivers/char/drm/drm_vm.h	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "drmP.h"
 
 struct vm_operations_struct   DRM(vm_ops) = {
diff -urN linux-2.5.65-bk2/drivers/char/drm/gamma_dma.c linux-2.5.65-bk3/drivers/char/drm/gamma_dma.c
--- linux-2.5.65-bk2/drivers/char/drm/gamma_dma.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/drivers/char/drm/gamma_dma.c	Mon Mar 31 12:41:40 2003
@@ -29,7 +29,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "gamma.h"
 #include "drmP.h"
 #include "drm.h"
diff -urN linux-2.5.65-bk2/drivers/char/drm/i810_dma.c linux-2.5.65-bk3/drivers/char/drm/i810_dma.c
--- linux-2.5.65-bk2/drivers/char/drm/i810_dma.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk3/drivers/char/drm/i810_dma.c	Mon Mar 31 12:41:40 2003
@@ -30,7 +30,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "i810.h"
 #include "drmP.h"
 #include "drm.h"
diff -urN linux-2.5.65-bk2/drivers/char/drm/i830_dma.c linux-2.5.65-bk3/drivers/char/drm/i830_dma.c
--- linux-2.5.65-bk2/drivers/char/drm/i830_dma.c	Mon Mar 31 12:41:36 2003
+++ linux-2.5.65-bk3/drivers/char/drm/i830_dma.c	Mon Mar 31 12:41:40 2003
@@ -31,7 +31,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "i830.h"
 #include "drmP.h"
 #include "drm.h"
diff -urN linux-2.5.65-bk2/drivers/char/drm/mga_warp.c linux-2.5.65-bk3/drivers/char/drm/mga_warp.c
--- linux-2.5.65-bk2/drivers/char/drm/mga_warp.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/drivers/char/drm/mga_warp.c	Mon Mar 31 12:41:40 2003
@@ -27,7 +27,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#define __NO_VERSION__
 #include "mga.h"
 #include "drmP.h"
 #include "drm.h"
diff -urN linux-2.5.65-bk2/drivers/char/drm/sis_ds.c linux-2.5.65-bk3/drivers/char/drm/sis_ds.c
--- linux-2.5.65-bk2/drivers/char/drm/sis_ds.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/drivers/char/drm/sis_ds.c	Mon Mar 31 12:41:40 2003
@@ -28,7 +28,6 @@
  * 
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/drm/sis_mm.c linux-2.5.65-bk3/drivers/char/drm/sis_mm.c
--- linux-2.5.65-bk2/drivers/char/drm/sis_mm.c	Mon Mar 17 13:44:19 2003
+++ linux-2.5.65-bk3/drivers/char/drm/sis_mm.c	Mon Mar 31 12:41:40 2003
@@ -28,7 +28,6 @@
  * 
  */
 
-#define __NO_VERSION__
 #include "sis.h"
 #include <linux/sisfb.h>
 #include "drmP.h"
diff -urN linux-2.5.65-bk2/drivers/char/ftape/lowlevel/ftape_syms.c linux-2.5.65-bk3/drivers/char/ftape/lowlevel/ftape_syms.c
--- linux-2.5.65-bk2/drivers/char/ftape/lowlevel/ftape_syms.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk3/drivers/char/ftape/lowlevel/ftape_syms.c	Mon Mar 31 12:41:40 2003
@@ -26,7 +26,6 @@
  */
 
 #include <linux/config.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/ftape.h>
diff -urN linux-2.5.65-bk2/drivers/char/ftape/zftape/zftape-ctl.c linux-2.5.65-bk3/drivers/char/ftape/zftape/zftape-ctl.c
--- linux-2.5.65-bk2/drivers/char/ftape/zftape/zftape-ctl.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk3/drivers/char/ftape/zftape/zftape-ctl.c	Mon Mar 31 12:41:40 2003
@@ -27,7 +27,6 @@
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/fcntl.h>
 
diff -urN linux-2.5.65-bk2/drivers/char/ftape/zftape/zftape_syms.c linux-2.5.65-bk3/drivers/char/ftape/zftape/zftape_syms.c
--- linux-2.5.65-bk2/drivers/char/ftape/zftape/zftape_syms.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/drivers/char/ftape/zftape/zftape_syms.c	Mon Mar 31 12:41:40 2003
@@ -24,7 +24,6 @@
  *      the ftape floppy tape driver exports 
  */		 
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/zftape.h>
diff -urN linux-2.5.65-bk2/drivers/char/ipmi/ipmi_devintf.c linux-2.5.65-bk3/drivers/char/ipmi/ipmi_devintf.c
--- linux-2.5.65-bk2/drivers/char/ipmi/ipmi_devintf.c	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk3/drivers/char/ipmi/ipmi_devintf.c	Mon Mar 31 12:41:40 2003
@@ -105,7 +105,7 @@
 
 static struct ipmi_user_hndl ipmi_hndlrs =
 {
-	ipmi_recv_hndl : file_receive_handler
+	.ipmi_recv_hndl	= file_receive_handler,
 };
 
 static int ipmi_open(struct inode *inode, struct file *file)
@@ -424,12 +424,12 @@
 
 
 static struct file_operations ipmi_fops = {
-	owner:   THIS_MODULE,
-	ioctl:   ipmi_ioctl,
-	open:    ipmi_open,
-	release: ipmi_release,
-	fasync:  ipmi_fasync,
-	poll:    ipmi_poll
+	.owner		= THIS_MODULE,
+	.ioctl		= ipmi_ioctl,
+	.open		= ipmi_open,
+	.release	= ipmi_release,
+	.fasync		= ipmi_fasync,
+	.poll		= ipmi_poll,
 };
 
 #define DEVICE_NAME     "ipmidev"
@@ -468,8 +468,8 @@
 
 static struct ipmi_smi_watcher smi_watcher =
 {
-	new_smi  : ipmi_new_smi,
-	smi_gone : ipmi_smi_gone
+	.new_smi	= ipmi_new_smi,
+	.smi_gone	= ipmi_smi_gone,
 };
 
 static __init int init_ipmi_devintf(void)
diff -urN linux-2.5.65-bk2/drivers/char/ite_gpio.c linux-2.5.65-bk3/drivers/char/ite_gpio.c
--- linux-2.5.65-bk2/drivers/char/ite_gpio.c	Mon Mar 17 13:44:20 2003
+++ linux-2.5.65-bk3/drivers/char/ite_gpio.c	Mon Mar 31 12:41:40 2003
@@ -140,7 +140,7 @@
 {
 	int ret=-1;
 
-	if (MAX_GPIO_LINE > *data >= 0) 
+	if ((MAX_GPIO_LINE > *data) && (*data >= 0)) 
 		ret=ite_gpio_irq_pending[*data];
  
 	DEB(printk("ite_gpio_in_status %d ret=%d\n",*data, ret));
diff -urN linux-2.5.65-bk2/drivers/char/lp_old98.c linux-2.5.65-bk3/drivers/char/lp_old98.c
--- linux-2.5.65-bk2/drivers/char/lp_old98.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/drivers/char/lp_old98.c	Mon Mar 31 12:41:40 2003
@@ -0,0 +1,544 @@
+/*
+ *	linux/drivers/char/lp_old98.c
+ *
+ * printer port driver for ancient PC-9800s with no bidirectional port support
+ *
+ * Copyright (C)  1998,99  Kousuke Takai <tak@kmc.kyoto-u.ac.jp>,
+ *			   Kyoto University Microcomputer Club
+ *
+ * This driver is based on and has compatibility with `lp.c',
+ * generic PC printer port driver.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/lp.h>
+
+/*
+ *  I/O port numbers
+ */
+#define	LP_PORT_DATA	0x40
+#define	LP_PORT_STATUS	(LP_PORT_DATA + 2)
+#define	LP_PORT_STROBE	(LP_PORT_DATA + 4)
+#define LP_PORT_CONTROL	(LP_PORT_DATA + 6)
+
+#define	LP_PORT_H98MODE	0x0448
+#define	LP_PORT_EXTMODE	0x0149
+
+/*
+ *  bit mask for I/O
+ */
+#define	LP_MASK_nBUSY	(1 << 2)
+#define	LP_MASK_nSTROBE	(1 << 7)
+
+#define LP_CONTROL_ASSERT_STROBE	(0x0e)
+#define LP_CONTROL_NEGATE_STROBE	(0x0f)
+
+/*
+ *  Acceptable maximum value for non-privileged user for LPCHARS ioctl.
+ */
+#define LP_CHARS_NOPRIV_MAX	65535
+
+#define	DC1	'\x11'
+#define	DC3	'\x13'
+
+/* PC-9800s have at least and at most one old-style printer port. */
+static struct lp_struct lp = {
+	.flags	= LP_EXIST | LP_ABORTOPEN,
+	.chars	= LP_INIT_CHAR,
+	.time	= LP_INIT_TIME,
+	.wait	= LP_INIT_WAIT,
+};
+
+static	int	dc1_check;
+static spinlock_t lp_old98_lock = SPIN_LOCK_UNLOCKED;
+
+
+#undef LP_OLD98_DEBUG
+
+#ifdef CONFIG_PC9800_OLDLP_CONSOLE
+static struct console lp_old98_console;		/* defined later */
+static short saved_console_flags;
+#endif
+
+static DECLARE_WAIT_QUEUE_HEAD (lp_old98_waitq);
+
+static void lp_old98_timer_function(unsigned long data)
+{
+	if (inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
+		wake_up_interruptible(&lp_old98_waitq);
+	else {
+		struct timer_list *t = (struct timer_list *) data;
+
+		t->expires = jiffies + 1;
+		add_timer(t);
+	}
+}
+
+static inline int lp_old98_wait_ready(void)
+{
+	struct timer_list timer;
+
+	init_timer(&timer);
+	timer.function = lp_old98_timer_function;
+	timer.expires = jiffies + 1;
+	timer.data = (unsigned long)&timer;
+	add_timer(&timer);
+	interruptible_sleep_on(&lp_old98_waitq);
+	del_timer(&timer);
+	return signal_pending(current);
+}
+
+static inline int lp_old98_char(char lpchar)
+{
+	unsigned long count = 0;
+#ifdef LP_STATS
+	int tmp;
+#endif
+
+	while (!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY)) {
+		count++;
+		if (count >= lp.chars)
+			return 0;
+	}
+
+	outb(lpchar, LP_PORT_DATA);
+
+#ifdef LP_STATS
+	/*
+	 *  Update lp statsistics here (and between next two outb()'s).
+	 *  Time to compute it is part of storobe delay.
+	 */
+	if (count > lp.stats.maxwait) {
+#ifdef LP_OLD98_DEBUG
+		printk(KERN_DEBUG "lp_old98: success after %d counts.\n",
+		       count);
+#endif
+		lp.stats.maxwait = count;
+	}
+	count *= 256;
+	tmp = count - lp.stats.meanwait;
+	if (tmp < 0)
+		tmp = -tmp;
+#endif
+	ndelay(lp.wait);
+    
+	/* negate PSTB# (activate strobe)	*/
+	outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
+
+#ifdef LP_STATS
+	lp.stats.meanwait = (255 * lp.stats.meanwait + count + 128) / 256;
+	lp.stats.mdev = (127 * lp.stats.mdev + tmp + 64) / 128;
+	lp.stats.chars ++;
+#endif
+
+	ndelay(lp.wait);
+
+	/* assert PSTB# (deactivate strobe)	*/
+	outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
+
+	return 1;
+}
+
+static ssize_t lp_old98_write(struct file * file,
+			      const char * buf, size_t count,
+			      loff_t *dummy)
+{
+	unsigned long total_bytes_written = 0;
+
+	if (!access_ok(VERIFY_READ, buf, count))
+		return -EFAULT;
+
+#ifdef LP_STATS
+	if (jiffies - lp.lastcall > lp.time)
+		lp.runchars = 0;
+	lp.lastcall = jiffies;
+#endif
+
+	do {
+		unsigned long bytes_written = 0;
+		unsigned long copy_size
+			= (count < LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
+
+		if (__copy_from_user(lp.lp_buffer, buf, copy_size))
+			return -EFAULT;
+
+		while (bytes_written < copy_size) {
+			if (lp_old98_char(lp.lp_buffer[bytes_written]))
+				bytes_written ++;
+			else {
+#ifdef LP_STATS
+				int rc = lp.runchars + bytes_written;
+
+				if (rc > lp.stats.maxrun)
+					lp.stats.maxrun = rc;
+
+				lp.stats.sleeps ++;
+#endif
+#ifdef LP_OLD98_DEBUG
+				printk(KERN_DEBUG
+				       "lp_old98: sleeping at %d characters"
+				       " for %d jiffies\n",
+				       lp.runchars, lp.time);
+				lp.runchars = 0;
+#endif
+				if (lp_old98_wait_ready())
+					return ((total_bytes_written
+						 + bytes_written)
+						? : -EINTR);
+			}
+		}
+		total_bytes_written += bytes_written;
+		buf += bytes_written;
+#ifdef LP_STATS
+		lp.runchars += bytes_written;
+#endif
+		count -= bytes_written;
+	} while (count > 0);
+
+	return total_bytes_written;
+}
+
+static int lp_old98_open(struct inode * inode, struct file * file)
+{
+	if (minor(inode->i_rdev) != 0)
+		return -ENXIO;
+
+	if (lp.flags & LP_BUSY)
+		return -EBUSY;
+
+	if (dc1_check && (lp.flags & LP_ABORTOPEN)
+	    && !(file->f_flags & O_NONBLOCK)) {
+		/*
+		 *  Check whether printer is on-line.
+		 *  PC-9800's old style port have only BUSY# as status input,
+		 *  so that it is impossible to distinguish that the printer is
+		 *  ready and that the printer is off-line or not connected
+		 *  (in both case BUSY# is in the same state). So:
+		 *
+		 *    (1) output DC1 (0x11) to printer port and do strobe.
+		 *    (2) watch BUSY# line for a while. If BUSY# is pulled
+		 *	  down, the printer will be ready. Otherwise,
+		 *	  it will be off-line (or not connected, or power-off,
+		 *	   ...).
+		 *
+		 *  The source of this procedure:
+		 *	Terumasa KODAKA, Kazufumi SHIMIZU, Yu HAYAMI:
+		 *		`PC-9801 Super Technique', Ascii, 1992.
+		 */
+		int count;
+		unsigned long flags;
+
+		/* interrupts while check is fairly bad */
+		spin_lock_irqsave(&lp_old98_lock, flags);
+
+		if (!lp_old98_char(DC1)) {
+			spin_unlock_irqrestore(&lp_old98_lock, flags);
+			return -EBUSY;
+		}
+		count = (unsigned int)dc1_check > 10000 ? 10000 : dc1_check;
+		while (inb(LP_PORT_STATUS) & LP_MASK_nBUSY) {
+			if (--count == 0) {
+				spin_unlock_irqrestore(&lp_old98_lock, flags);
+				return -ENODEV;
+			}
+		}
+		spin_unlock_irqrestore(&lp_old98_lock, flags);
+	}
+
+	if ((lp.lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	lp.flags |= LP_BUSY;
+
+#ifdef CONFIG_PC9800_OLDLP_CONSOLE
+	saved_console_flags = lp_old98_console.flags;
+	lp_old98_console.flags &= ~CON_ENABLED;
+#endif
+	return 0;
+}
+
+static int lp_old98_release(struct inode * inode, struct file * file)
+{
+	kfree(lp.lp_buffer);
+	lp.lp_buffer = NULL;
+	lp.flags &= ~LP_BUSY;
+#ifdef CONFIG_PC9800_OLDLP_CONSOLE
+	lp_old98_console.flags = saved_console_flags;
+#endif
+	return 0;
+}
+
+static int lp_old98_init_device(void)
+{
+	unsigned char data;
+
+	if ((data = inb(LP_PORT_EXTMODE)) != 0xFF && (data & 0x10)) {
+		printk(KERN_INFO
+		       "lp_old98: shutting down extended parallel port mode...\n");
+		outb(data & ~0x10, LP_PORT_EXTMODE);
+	}
+#ifdef	PC98_HW_H98
+	if ((pc98_hw_flags & PC98_HW_H98)
+	    && ((data = inb(LP_PORT_H98MODE)) & 0x01)) {
+		printk(KERN_INFO
+		       "lp_old98: shutting down H98 full centronics mode...\n");
+		outb(data & ~0x01, LP_PORT_H98MODE);
+	}
+#endif
+	return 0;
+}
+
+static int lp_old98_ioctl(struct inode *inode, struct file *file,
+			  unsigned int command, unsigned long arg)
+{
+	int retval = 0;
+
+	switch (command) {
+	case LPTIME:
+		lp.time = arg * HZ/100;
+		break;
+	case LPCHAR:
+		lp.chars = arg;
+		break;
+	case LPABORT:
+		if (arg)
+			lp.flags |= LP_ABORT;
+		else
+			lp.flags &= ~LP_ABORT;
+		break;
+	case LPABORTOPEN:
+		if (arg)
+			lp.flags |= LP_ABORTOPEN;
+		else
+			lp.flags &= ~LP_ABORTOPEN;
+		break;
+	case LPCAREFUL:
+		/* do nothing */
+		break;
+	case LPWAIT:
+		lp.wait = arg;
+		break;
+	case LPGETIRQ:
+		retval = put_user(0, (int *)arg);
+		break;
+	case LPGETSTATUS:
+		/*
+		 * convert PC-9800's status to IBM PC's one, so that tunelp(8)
+		 * works in the same way on this driver.
+		 */
+		retval = put_user((inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
+					? (LP_PBUSY | LP_PERRORP) : LP_PERRORP,
+					(int *)arg);
+		break;
+	case LPRESET:
+		retval = lp_old98_init_device();
+		break;
+#ifdef LP_STATS
+	case LPGETSTATS:
+		if (copy_to_user((struct lp_stats *)arg, &lp.stats,
+				 sizeof(struct lp_stats)))
+			retval = -EFAULT;
+		else if (suser())
+			memset(&lp.stats, 0, sizeof(struct lp_stats));
+		break;
+#endif
+	case LPGETFLAGS:
+		retval = put_user(lp.flags, (int *)arg);
+		break;
+	case LPSETIRQ: 
+	default:
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+static struct file_operations lp_old98_fops = {
+	.owner		= THIS_MODULE,
+	.write		= lp_old98_write,
+	.ioctl		= lp_old98_ioctl,
+	.open		= lp_old98_open,
+	.release	= lp_old98_release,
+};
+
+/*
+ *  Support for console on lp_old98
+ */
+#ifdef CONFIG_PC9800_OLDLP_CONSOLE
+
+static inline void io_delay(void)
+{
+	unsigned char dummy;	/* actually not output */
+
+	asm volatile ("out%B0 %0,%1" : "=a"(dummy) : "N"(0x5f));
+}
+
+static void lp_old98_console_write(struct console *console,
+				    const char *s, unsigned int count)
+{
+	int i;
+	static unsigned int timeout_run = 0;
+
+	while (count) {
+		/* wait approx 1.2 seconds */
+		for (i = 2000000; !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY);
+								io_delay())
+			if (!--i) {
+				if (++timeout_run >= 10)
+					/* disable forever... */
+					console->flags &= ~CON_ENABLED;
+				return;
+			}
+
+		timeout_run = 0;
+
+		if (*s == '\n') {
+			outb('\r', LP_PORT_DATA);
+			io_delay();
+			io_delay();
+			outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
+			io_delay();
+			io_delay();
+			outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
+			io_delay();
+			io_delay();
+			for (i = 1000000;
+					!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY);
+					io_delay())
+				if (!--i)
+					return;
+		}
+
+		outb(*s++, LP_PORT_DATA);
+		io_delay();
+		io_delay();
+		outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
+		io_delay();
+		io_delay();
+		outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
+		io_delay();
+		io_delay();
+
+		--count;
+	}
+}
+
+static kdev_t lp_old98_console_device(struct console *console)
+{
+	return mk_kdev(LP_MAJOR, 0);
+}
+
+static struct console lp_old98_console = {
+	.name	= "lp_old98",
+	.write	= lp_old98_console_write,
+	.device	= lp_old98_console_device,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+#endif	/* console on lp_old98 */
+
+static int __init lp_old98_init(void)
+{
+	char *errmsg = "I/O ports already occupied, giving up.";
+
+#ifdef	PC98_HW_H98
+	if (pc98_hw_flags & PC98_HW_H98)
+	    if (!request_region(LP_PORT_H98MODE, 1, "lp_old98")
+		goto err1;
+#endif
+	if (!request_region(LP_PORT_DATA,   1, "lp_old98"))
+		goto err2;
+	if (!request_region(LP_PORT_STATUS, 1, "lp_old98"))
+		goto err3;
+	if (!request_region(LP_PORT_STROBE, 1, "lp_old98"))
+		goto err4;
+	if (!request_region(LP_PORT_EXTMODE, 1, "lp_old98"))
+		goto err5;
+	if (!register_chrdev(LP_MAJOR, "lp", &lp_old98_fops)) {
+#ifdef CONFIG_PC9800_OLDLP_CONSOLE
+		register_console(&lp_old98_console);
+		printk(KERN_INFO "lp_old98: console ready\n");
+#endif
+		/*
+		 * rest are not needed by this driver,
+		 * but for locking out other printer drivers...
+		 */
+		lp_old98_init_device();
+		return 0;
+	} else
+		errmsg = "unable to register device";
+
+	release_region(LP_PORT_EXTMODE, 1);
+err5:
+	release_region(LP_PORT_STROBE, 1);
+err4:
+	release_region(LP_PORT_STATUS, 1);
+err3:
+	release_region(LP_PORT_DATA, 1);
+err2:
+#ifdef	PC98_HW_H98
+	if (pc98_hw_flags & PC98_HW_H98)
+	    release_region(LP_PORT_H98MODE, 1);
+
+err1:
+#endif
+	printk(KERN_ERR "lp_old98: %s\n", errmsg);
+	return -EBUSY;
+}
+
+static void __exit lp_old98_exit(void)
+{
+#ifdef CONFIG_PC9800_OLDLP_CONSOLE
+	unregister_console(&lp_old98_console);
+#endif
+	unregister_chrdev(LP_MAJOR, "lp");
+
+	release_region(LP_PORT_DATA,   1);
+	release_region(LP_PORT_STATUS, 1);
+	release_region(LP_PORT_STROBE, 1);
+#ifdef	PC98_HW_H98
+	if (pc98_hw_flags & PC98_HW_H98)
+		release_region(LP_PORT_H98MODE, 1);
+#endif
+	release_region(LP_PORT_EXTMODE, 1);
+}
+
+#ifndef MODULE
+static int __init lp_old98_setup(char *str)
+{
+        int ints[4];
+
+        str = get_options(str, ARRAY_SIZE(ints), ints);
+        if (ints[0] > 0)
+		dc1_check = ints[1];
+        return 1;
+}
+__setup("lp_old98_dc1_check=", lp_old98_setup);
+#endif
+
+MODULE_PARM(dc1_check, "i");
+MODULE_AUTHOR("Kousuke Takai <tak@kmc.kyoto-u.ac.jp>");
+MODULE_DESCRIPTION("PC-9800 old printer port driver");
+MODULE_LICENSE("GPL");
+
+module_init(lp_old98_init);
+module_exit(lp_old98_exit);
diff -urN linux-2.5.65-bk2/drivers/char/mwave/mwavedd.c linux-2.5.65-bk3/drivers/char/mwave/mwavedd.c
--- linux-2.5.65-bk2/drivers/char/mwave/mwavedd.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/char/mwave/mwavedd.c	Mon Mar 31 12:41:40 2003
@@ -53,46 +53,20 @@
 #include <linux/init.h>
 #include <linux/major.h>
 #include <linux/miscdevice.h>
-#include <linux/proc_fs.h>
+#include <linux/device.h>
 #include <linux/serial.h>
 #include <linux/sched.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 #include <linux/spinlock.h>
-#else
-#include <asm/spinlock.h>
-#endif
 #include <linux/delay.h>
 #include "smapi.h"
 #include "mwavedd.h"
 #include "3780i.h"
 #include "tp3780i.h"
 
-#ifndef __exit
-#define __exit
-#endif
-
 MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver");
 MODULE_AUTHOR("Mike Sullivan and Paul Schroeder");
 MODULE_LICENSE("GPL");
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-static int mwave_get_info(char *buf, char **start, off_t offset, int len);
-#else
-static int mwave_read_proc(char *buf, char **start, off_t offset, int xlen, int unused);
-static struct proc_dir_entry mwave_proc = {
-	0,                      /* unsigned short low_ino */
-	5,                      /* unsigned short namelen */
-	"mwave",                /* const char *name */
-	S_IFREG | S_IRUGO,      /* mode_t mode */
-	1,                      /* nlink_t nlink */
-	0,                      /* uid_t uid */
-	0,                      /* gid_t gid */
-	0,                      /* unsigned long size */
-	NULL,                   /* struct inode_operations *ops */
-	&mwave_read_proc        /* int (*get_info) (...) */
-};
-#endif
-
 /*
 * These parameters support the setting of MWave resources. Note that no
 * checks are made against other devices (ie. superio) for conflicts.
@@ -157,19 +131,23 @@
 
 		case IOCTL_MW_RESET:
 			PRINTK_1(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl, IOCTL_MW_RESET calling tp3780I_ResetDSP\n");
+				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
+				" calling tp3780I_ResetDSP\n");
 			retval = tp3780I_ResetDSP(&pDrvData->rBDData);
 			PRINTK_2(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl, IOCTL_MW_RESET retval %x from tp3780I_ResetDSP\n",
+				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
+				" retval %x from tp3780I_ResetDSP\n",
 				retval);
 			break;
 	
 		case IOCTL_MW_RUN:
 			PRINTK_1(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl, IOCTL_MW_RUN calling tp3780I_StartDSP\n");
+				"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
+				" calling tp3780I_StartDSP\n");
 			retval = tp3780I_StartDSP(&pDrvData->rBDData);
 			PRINTK_2(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl, IOCTL_MW_RUN retval %x from tp3780I_StartDSP\n",
+				"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
+				" retval %x from tp3780I_StartDSP\n",
 				retval);
 			break;
 	
@@ -177,17 +155,24 @@
 			MW_ABILITIES rAbilities;
 	
 			PRINTK_1(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES calling tp3780I_QueryAbilities\n");
-			retval = tp3780I_QueryAbilities(&pDrvData->rBDData, &rAbilities);
+				"mwavedd::mwave_ioctl,"
+				" IOCTL_MW_DSP_ABILITIES calling"
+				" tp3780I_QueryAbilities\n");
+			retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
+					&rAbilities);
 			PRINTK_2(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES retval %x from tp3780I_QueryAbilities\n",
+				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
+				" retval %x from tp3780I_QueryAbilities\n",
 				retval);
 			if (retval == 0) {
-				if( copy_to_user((char *) ioarg, (char *) &rAbilities, sizeof(MW_ABILITIES)) )
+				if( copy_to_user((char *) ioarg,
+							(char *) &rAbilities,
+							sizeof(MW_ABILITIES)) )
 					return -EFAULT;
 			}
 			PRINTK_2(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES exit retval %x\n",
+				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
+				" exit retval %x\n",
 				retval);
 		}
 			break;
@@ -197,15 +182,21 @@
 			MW_READWRITE rReadData;
 			unsigned short *pusBuffer = 0;
 	
-			if( copy_from_user((char *) &rReadData, (char *) ioarg, sizeof(MW_READWRITE)) )
+			if( copy_from_user((char *) &rReadData,
+						(char *) ioarg,
+						sizeof(MW_READWRITE)) )
 				return -EFAULT;
 			pusBuffer = (unsigned short *) (rReadData.pBuf);
 	
 			PRINTK_4(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA, size %lx, ioarg %lx pusBuffer %p\n",
+				"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
+				" size %lx, ioarg %lx pusBuffer %p\n",
 				rReadData.ulDataLength, ioarg, pusBuffer);
-			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd,
-				(void *) pusBuffer, rReadData.ulDataLength, rReadData.usDspAddress);
+			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
+					iocmd,
+					(void *) pusBuffer,
+					rReadData.ulDataLength,
+					rReadData.usDspAddress);
 		}
 			break;
 	
@@ -213,12 +204,14 @@
 			MW_READWRITE rReadData;
 			unsigned short *pusBuffer = 0;
 	
-			if( copy_from_user((char *) &rReadData, (char *) ioarg, sizeof(MW_READWRITE)) )
+			if( copy_from_user((char *) &rReadData, (char *) ioarg,
+						sizeof(MW_READWRITE)) )
 				return -EFAULT;
 			pusBuffer = (unsigned short *) (rReadData.pBuf);
 	
 			PRINTK_4(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl IOCTL_MW_READ_INST, size %lx, ioarg %lx pusBuffer %p\n",
+				"mwavedd::mwave_ioctl IOCTL_MW_READ_INST,"
+				" size %lx, ioarg %lx pusBuffer %p\n",
 				rReadData.ulDataLength / 2, ioarg,
 				pusBuffer);
 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
@@ -232,16 +225,21 @@
 			MW_READWRITE rWriteData;
 			unsigned short *pusBuffer = 0;
 	
-			if( copy_from_user((char *) &rWriteData, (char *) ioarg, sizeof(MW_READWRITE)) )
+			if( copy_from_user((char *) &rWriteData,
+						(char *) ioarg,
+						sizeof(MW_READWRITE)) )
 				return -EFAULT;
 			pusBuffer = (unsigned short *) (rWriteData.pBuf);
 	
 			PRINTK_4(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA, size %lx, ioarg %lx pusBuffer %p\n",
+				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA,"
+				" size %lx, ioarg %lx pusBuffer %p\n",
 				rWriteData.ulDataLength, ioarg,
 				pusBuffer);
-			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd,
-				pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress);
+			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
+					iocmd, pusBuffer,
+					rWriteData.ulDataLength,
+					rWriteData.usDspAddress);
 		}
 			break;
 	
@@ -249,16 +247,21 @@
 			MW_READWRITE rWriteData;
 			unsigned short *pusBuffer = 0;
 	
-			if( copy_from_user((char *) &rWriteData, (char *) ioarg, sizeof(MW_READWRITE)) )
+			if( copy_from_user((char *) &rWriteData,
+						(char *) ioarg,
+						sizeof(MW_READWRITE)) )
 				return -EFAULT;
 			pusBuffer = (unsigned short *) (rWriteData.pBuf);
 	
 			PRINTK_4(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST, size %lx, ioarg %lx pusBuffer %p\n",
+				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST,"
+				" size %lx, ioarg %lx pusBuffer %p\n",
 				rWriteData.ulDataLength, ioarg,
 				pusBuffer);
-			retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, iocmd,
-					pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress);
+			retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
+					iocmd, pusBuffer,
+					rWriteData.ulDataLength,
+					rWriteData.usDspAddress);
 		}
 			break;
 	
@@ -266,23 +269,25 @@
 			unsigned int ipcnum = (unsigned int) ioarg;
 	
 			PRINTK_3(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC ipcnum %x entry usIntCount %x\n",
+				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
+				" ipcnum %x entry usIntCount %x\n",
 				ipcnum,
 				pDrvData->IPCs[ipcnum].usIntCount);
 	
-			if (ipcnum > 16) {
-				PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_REGISTER_IPC: Error: Invalid ipcnum %x\n", ipcnum);
+			if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) {
+				PRINTK_ERROR(KERN_ERR_MWAVE
+						"mwavedd::mwave_ioctl:"
+						" IOCTL_MW_REGISTER_IPC:"
+						" Error: Invalid ipcnum %x\n",
+						ipcnum);
 				return -EINVAL;
 			}
 			pDrvData->IPCs[ipcnum].bIsHere = FALSE;
 			pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
-	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	#else
-			current->priority = 0x28;	/* boost to provide priority timing */
-	#endif
 	
 			PRINTK_2(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC ipcnum %x exit\n",
+				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
+				" ipcnum %x exit\n",
 				ipcnum);
 		}
 			break;
@@ -293,17 +298,22 @@
 			unsigned long flags;
 	
 			PRINTK_3(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x, usIntCount %x\n",
+				"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
+				" ipcnum %x, usIntCount %x\n",
 				ipcnum,
 				pDrvData->IPCs[ipcnum].usIntCount);
-			if (ipcnum > 16) {
-				PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_GET_IPC: Error: Invalid ipcnum %x\n", ipcnum);
+			if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) {
+				PRINTK_ERROR(KERN_ERR_MWAVE
+						"mwavedd::mwave_ioctl:"
+						" IOCTL_MW_GET_IPC: Error:"
+						" Invalid ipcnum %x\n", ipcnum);
 				return -EINVAL;
 			}
 	
 			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
 				PRINTK_2(TRACE_MWAVE,
-					"mwavedd::mwave_ioctl, thread for ipc %x going to sleep\n",
+					"mwavedd::mwave_ioctl, thread for"
+					" ipc %x going to sleep\n",
 					ipcnum);
 	
 				spin_lock_irqsave(&ipc_lock, flags);
@@ -313,10 +323,13 @@
 					pDrvData->IPCs[ipcnum].usIntCount = 2;	/* first int has been handled */
 					spin_unlock_irqrestore(&ipc_lock, flags);
 					PRINTK_2(TRACE_MWAVE,
-						"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x handling first int\n",
+						"mwavedd::mwave_ioctl"
+						" IOCTL_MW_GET_IPC ipcnum %x"
+						" handling first int\n",
 						ipcnum);
 				} else {	/* either 1st int has not yet occurred, or we have already handled the first int */
 					pDrvData->IPCs[ipcnum].bIsHere = TRUE;
+#warning "Sleeping on spinlock"
 					interruptible_sleep_on(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
 					pDrvData->IPCs[ipcnum].bIsHere = FALSE;
 					if (pDrvData->IPCs[ipcnum].usIntCount == 1) {
@@ -325,11 +338,16 @@
 					}
 					spin_unlock_irqrestore(&ipc_lock, flags);
 					PRINTK_2(TRACE_MWAVE,
-						"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x woke up and returning to application\n",
+						"mwavedd::mwave_ioctl"
+						" IOCTL_MW_GET_IPC ipcnum %x"
+						" woke up and returning to"
+						" application\n",
 						ipcnum);
 				}
 				PRINTK_2(TRACE_MWAVE,
-					"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC, returning thread for ipc %x processing\n",
+					"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC,"
+					" returning thread for ipc %x"
+					" processing\n",
 					ipcnum);
 			}
 		}
@@ -339,10 +357,15 @@
 			unsigned int ipcnum = (unsigned int) ioarg;
 	
 			PRINTK_2(TRACE_MWAVE,
-				"mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC ipcnum %x\n",
+				"mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC"
+				" ipcnum %x\n",
 				ipcnum);
-			if (ipcnum > 16) {
-				PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_UNREGISTER_IPC: Error: Invalid ipcnum %x\n", ipcnum);
+			if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) {
+				PRINTK_ERROR(KERN_ERR_MWAVE
+						"mwavedd::mwave_ioctl:"
+						" IOCTL_MW_UNREGISTER_IPC:"
+						" Error: Invalid ipcnum %x\n",
+						ipcnum);
 				return -EINVAL;
 			}
 			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
@@ -355,7 +378,9 @@
 			break;
 	
 		default:
-			PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: Error: Unrecognized iocmd %x\n", iocmd);
+			PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:"
+					" Error: Unrecognized iocmd %x\n",
+					iocmd);
 			return -ENOTTY;
 			break;
 	} /* switch */
@@ -381,7 +406,8 @@
                            size_t count, loff_t * ppos)
 {
 	PRINTK_5(TRACE_MWAVE,
-		"mwavedd::mwave_write entry file %p, buf %p, count %x ppos %p\n",
+		"mwavedd::mwave_write entry file %p, buf %p,"
+		" count %x ppos %p\n",
 		file, buf, count, ppos);
 
 	return -EINVAL;
@@ -400,7 +426,9 @@
 			/* OK */
 			break;
 		default:
-			PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::register_serial_portandirq: Error: Illegal port %x\n", port );
+			PRINTK_ERROR(KERN_ERR_MWAVE
+					"mwavedd::register_serial_portandirq:"
+					" Error: Illegal port %x\n", port );
 			return -1;
 	} /* switch */
 	/* port is okay */
@@ -413,7 +441,9 @@
 			/* OK */
 			break;
 		default:
-			PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::register_serial_portandirq: Error: Illegal irq %x\n", irq );
+			PRINTK_ERROR(KERN_ERR_MWAVE
+					"mwavedd::register_serial_portandirq:"
+					" Error: Illegal irq %x\n", irq );
 			return -1;
 	} /* switch */
 	/* irq is okay */
@@ -427,7 +457,6 @@
 }
 
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 static struct file_operations mwave_fops = {
 	.owner		= THIS_MODULE,
 	.read		= mwave_read,
@@ -436,24 +465,46 @@
 	.open		= mwave_open,
 	.release	= mwave_close
 };
-#else
-static struct file_operations mwave_fops = {
-	NULL,			/* lseek */
-	mwave_read,		/* read */
-	mwave_write,		/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	mwave_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	mwave_open,		/* open */
-	NULL,			/* flush */
-	mwave_close		/* release */
-};
-#endif
+
 
 static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops };
 
 /*
+ * sysfs support <paulsch@us.ibm.com>
+ */
+
+struct device mwave_device;
+
+/* Prevent code redundancy, create a macro for mwave_show_* functions. */
+#define mwave_show_function(attr_name, format_string, field)		\
+static ssize_t mwave_show_##attr_name(struct device *dev, char *buf)	\
+{									\
+	DSP_3780I_CONFIG_SETTINGS *pSettings =				\
+		&mwave_s_mdd.rBDData.rDspSettings;			\
+        return sprintf(buf, format_string, pSettings->field);		\
+}
+
+/* All of our attributes are read attributes. */
+#define mwave_dev_rd_attr(attr_name, format_string, field)		\
+	mwave_show_function(attr_name, format_string, field)		\
+static DEVICE_ATTR(attr_name, S_IRUGO, mwave_show_##attr_name, NULL)
+
+mwave_dev_rd_attr (3780i_dma, "%i\n", usDspDma);
+mwave_dev_rd_attr (3780i_irq, "%i\n", usDspIrq);
+mwave_dev_rd_attr (3780i_io, "%#.4x\n", usDspBaseIO);
+mwave_dev_rd_attr (uart_irq, "%i\n", usUartIrq);
+mwave_dev_rd_attr (uart_io, "%#.4x\n", usUartBaseIO);
+
+static struct device_attribute * const mwave_dev_attrs[] = {
+	&dev_attr_3780i_dma,
+	&dev_attr_3780i_irq,
+	&dev_attr_3780i_io,
+	&dev_attr_uart_irq,
+	&dev_attr_uart_io,
+};
+
+
+/*
 * mwave_init is called on module load
 *
 * mwave_exit is called on module unload
@@ -461,17 +512,16 @@
 */
 static void mwave_exit(void)
 {
+	int i;
 	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
 
 	PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit entry\n");
 
-	if (pDrvData->bProcEntryCreated) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-		remove_proc_entry("mwave", NULL);
-#else
-		proc_unregister(&proc_root, mwave_proc.low_ino);
-#endif
+	for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) {
+		device_remove_file(&mwave_device, mwave_dev_attrs[i]);
 	}
+	device_unregister(&mwave_device);
+
 	if ( pDrvData->sLine >= 0 ) {
 		unregister_serial(pDrvData->sLine);
 	}
@@ -497,72 +547,81 @@
 {
 	int i;
 	int retval = 0;
-	unsigned int resultMiscRegister;
 	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
 
-	memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA));
-
 	PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entry\n");
 
+	memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA));
+
 	pDrvData->bBDInitialized = FALSE;
 	pDrvData->bResourcesClaimed = FALSE;
 	pDrvData->bDSPEnabled = FALSE;
 	pDrvData->bDSPReset = FALSE;
 	pDrvData->bMwaveDevRegistered = FALSE;
 	pDrvData->sLine = -1;
-	pDrvData->bProcEntryCreated = FALSE;
 
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < ARRAY_SIZE(pDrvData->IPCs); i++) {
 		pDrvData->IPCs[i].bIsEnabled = FALSE;
 		pDrvData->IPCs[i].bIsHere = FALSE;
 		pDrvData->IPCs[i].usIntCount = 0;	/* no ints received yet */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 		init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue);
-#endif
 	}
 
 	retval = tp3780I_InitializeBoardData(&pDrvData->rBDData);
 	PRINTK_2(TRACE_MWAVE,
-		"mwavedd::mwave_init, return from tp3780I_InitializeBoardData retval %x\n",
+		"mwavedd::mwave_init, return from tp3780I_InitializeBoardData"
+		" retval %x\n",
 		retval);
 	if (retval) {
-		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to initialize board data\n");
+		PRINTK_ERROR(KERN_ERR_MWAVE
+				"mwavedd::mwave_init: Error:"
+				" Failed to initialize board data\n");
 		goto cleanup_error;
 	}
 	pDrvData->bBDInitialized = TRUE;
 
 	retval = tp3780I_CalcResources(&pDrvData->rBDData);
 	PRINTK_2(TRACE_MWAVE,
-		"mwavedd::mwave_init, return from tp3780I_CalcResources retval %x\n",
+		"mwavedd::mwave_init, return from tp3780I_CalcResources"
+		" retval %x\n",
 		retval);
 	if (retval) {
-		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to calculate resources\n");
+		PRINTK_ERROR(KERN_ERR_MWAVE
+				"mwavedd:mwave_init: Error:"
+				" Failed to calculate resources\n");
 		goto cleanup_error;
 	}
 
 	retval = tp3780I_ClaimResources(&pDrvData->rBDData);
 	PRINTK_2(TRACE_MWAVE,
-		"mwavedd::mwave_init, return from tp3780I_ClaimResources retval %x\n",
+		"mwavedd::mwave_init, return from tp3780I_ClaimResources"
+		" retval %x\n",
 		retval);
 	if (retval) {
-		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to claim resources\n");
+		PRINTK_ERROR(KERN_ERR_MWAVE
+				"mwavedd:mwave_init: Error:"
+				" Failed to claim resources\n");
 		goto cleanup_error;
 	}
 	pDrvData->bResourcesClaimed = TRUE;
 
 	retval = tp3780I_EnableDSP(&pDrvData->rBDData);
 	PRINTK_2(TRACE_MWAVE,
-		"mwavedd::mwave_init, return from tp3780I_EnableDSP retval %x\n",
+		"mwavedd::mwave_init, return from tp3780I_EnableDSP"
+		" retval %x\n",
 		retval);
 	if (retval) {
-		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to enable DSP\n");
+		PRINTK_ERROR(KERN_ERR_MWAVE
+				"mwavedd:mwave_init: Error:"
+				" Failed to enable DSP\n");
 		goto cleanup_error;
 	}
 	pDrvData->bDSPEnabled = TRUE;
 
-	resultMiscRegister = misc_register(&mwave_misc_dev);
-	if (resultMiscRegister < 0) {
-		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to register misc device\n");
+	if (misc_register(&mwave_misc_dev) < 0) {
+		PRINTK_ERROR(KERN_ERR_MWAVE
+				"mwavedd:mwave_init: Error:"
+				" Failed to register misc device\n");
 		goto cleanup_error;
 	}
 	pDrvData->bMwaveDevRegistered = TRUE;
@@ -572,28 +631,36 @@
 		pDrvData->rBDData.rDspSettings.usUartIrq
 	);
 	if (pDrvData->sLine < 0) {
-		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to register serial driver\n");
+		PRINTK_ERROR(KERN_ERR_MWAVE
+				"mwavedd:mwave_init: Error:"
+				" Failed to register serial driver\n");
 		goto cleanup_error;
 	}
 	/* uart is registered */
 
-	if (
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-		!create_proc_info_entry("mwave", 0, NULL, mwave_get_info)
-#else
-		proc_register(&proc_root, &mwave_proc)
-#endif
-	) {
-		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to register /proc/mwave\n");
-		goto cleanup_error;
+	/* sysfs */
+	memset(&mwave_device, 0, sizeof (struct device));
+	snprintf(mwave_device.name, DEVICE_NAME_SIZE, "mwave");
+	snprintf(mwave_device.bus_id, BUS_ID_SIZE, "mwave");
+
+	device_register(&mwave_device);
+	for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) {
+		if(device_create_file(&mwave_device, mwave_dev_attrs[i])) {
+			PRINTK_ERROR(KERN_ERR_MWAVE
+					"mwavedd:mwave_init: Error:"
+					" Failed to create sysfs file %s\n",
+					mwave_dev_attrs[i]->attr.name);
+			goto cleanup_error;
+		}
 	}
-	pDrvData->bProcEntryCreated = TRUE;
 
 	/* SUCCESS! */
 	return 0;
 
 	cleanup_error:
-	PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to initialize\n");
+	PRINTK_ERROR(KERN_ERR_MWAVE
+			"mwavedd::mwave_init: Error:"
+			" Failed to initialize\n");
 	mwave_exit(); /* clean up */
 
 	return -EIO;
@@ -601,39 +668,3 @@
 
 module_init(mwave_init);
 
-
-/*
-* proc entry stuff added by Ian Pilcher <pilcher@us.ibm.com>
-*/
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-static int mwave_get_info(char *buf, char **start, off_t offset, int len)
-{
-	DSP_3780I_CONFIG_SETTINGS *pSettings = &mwave_s_mdd.rBDData.rDspSettings;
-
-	char *out = buf;
-
-	out += sprintf(out, "3780i_IRQ %i\n", pSettings->usDspIrq);
-	out += sprintf(out, "3780i_DMA %i\n", pSettings->usDspDma);
-	out += sprintf(out, "3780i_IO  %#.4x\n", pSettings->usDspBaseIO);
-	out += sprintf(out, "UART_IRQ  %i\n", pSettings->usUartIrq);
-	out += sprintf(out, "UART_IO   %#.4x\n", pSettings->usUartBaseIO);
-
-	return out - buf;
-}
-#else /* kernel version < 2.4.0 */
-static int mwave_read_proc(char *buf, char **start, off_t offset,
-                           int xlen, int unused)
-{
-	DSP_3780I_CONFIG_SETTINGS *pSettings = &mwave_s_mdd.rBDData.rDspSettings;
-	int len;
-
-	len = sprintf(buf,        "3780i_IRQ %i\n", pSettings->usDspIrq);
-	len += sprintf(&buf[len], "3780i_DMA %i\n", pSettings->usDspDma);
-	len += sprintf(&buf[len], "3780i_IO  %#.4x\n", pSettings->usDspBaseIO);
-	len += sprintf(&buf[len], "UART_IRQ  %i\n", pSettings->usUartIrq);
-	len += sprintf(&buf[len], "UART_IO   %#.4x\n", pSettings->usUartBaseIO);
-
-	return len;
-}
-#endif
diff -urN linux-2.5.65-bk2/drivers/char/mwave/mwavedd.h linux-2.5.65-bk3/drivers/char/mwave/mwavedd.h
--- linux-2.5.65-bk2/drivers/char/mwave/mwavedd.h	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/drivers/char/mwave/mwavedd.h	Mon Mar 31 12:41:40 2003
@@ -126,11 +126,7 @@
 	BOOLEAN bIsEnabled;
 	BOOLEAN bIsHere;
 	/* entry spin lock */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	wait_queue_head_t ipc_wait_queue;
-#else
-	struct wait_queue *ipc_wait_queue;
-#endif
 } MWAVE_IPC;
 
 typedef struct _MWAVE_DEVICE_DATA {
@@ -143,7 +139,6 @@
 	BOOLEAN bDSPReset;
 	MWAVE_IPC IPCs[16];
 	BOOLEAN bMwaveDevRegistered;
-	BOOLEAN bProcEntryCreated;
 	short sLine;
 
 } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA;
diff -urN linux-2.5.65-bk2/drivers/char/mwave/mwavepub.h linux-2.5.65-bk3/drivers/char/mwave/mwavepub.h
--- linux-2.5.65-bk2/drivers/char/mwave/mwavepub.h	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/drivers/char/mwave/mwavepub.h	Mon Mar 31 12:41:40 2003
@@ -50,13 +50,8 @@
 #ifndef _LINUX_MWAVEPUB_H
 #define _LINUX_MWAVEPUB_H
 
-#ifndef MWAVEM_APP_DIST
 #include <linux/miscdevice.h>
-#endif
 
-#ifdef MWAVEM_APP_DIST
-#define MWAVE_MINOR      219
-#endif
 
 typedef struct _MW_ABILITIES {
 	unsigned long instr_per_sec;
diff -urN linux-2.5.65-bk2/drivers/char/mwave/smapi.c linux-2.5.65-bk3/drivers/char/mwave/smapi.c
--- linux-2.5.65-bk2/drivers/char/mwave/smapi.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/drivers/char/mwave/smapi.c	Mon Mar 31 12:41:40 2003
@@ -280,10 +280,11 @@
 				if ((usSI & 0xFF) == mwave_uart_irq) {
 #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
 					PRINTK_ERROR(KERN_ERR_MWAVE
+						"smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
 #else
 					PRINTK_3(TRACE_SMAPI,
+						"smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
 #endif
-						"smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI, mwave_uart_irq);
 #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
 					PRINTK_1(TRACE_SMAPI,
 						"smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n");
@@ -300,13 +301,14 @@
 					if ((usSI >> 8) == uartio_index) {
 #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
 						PRINTK_ERROR(KERN_ERR_MWAVE
+							"smapi::smapi_set_DSP_cfg: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
 #else
 						PRINTK_3(TRACE_SMAPI,
+							"smapi::smapi_set_DSP_cfg: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
 #endif
-							"smapi::smapi_set_DSP_cfg: Serial port A base I/O address index %x conflicts with uartio_index %x\n", usSI >> 8, uartio_index);
 #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
 						PRINTK_1(TRACE_SMAPI,
-							"smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n");
+							"smapi::smapi_set_DSP_cfg Disabling conflicting serial port A\n");
 						bRC = smapi_request (0x1403, 0x0100, 0, usSI,
 							&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
 						if (bRC) goto exit_smapi_request_error;
@@ -331,13 +333,14 @@
 				if ((usSI & 0xFF) == mwave_uart_irq) {
 #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
 					PRINTK_ERROR(KERN_ERR_MWAVE
+						"smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
 #else
 					PRINTK_3(TRACE_SMAPI,
+						"smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
 #endif
-						"smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI, mwave_uart_irq);
 #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
 					PRINTK_1(TRACE_SMAPI,
-						"smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n");
+						"smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n");
 					bRC = smapi_request(0x1405, 0x0100, 0, usSI,
 						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
 					if (bRC) goto exit_smapi_request_error;
@@ -351,13 +354,14 @@
 					if ((usSI >> 8) == uartio_index) {
 #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
 						PRINTK_ERROR(KERN_ERR_MWAVE
+							"smapi::smapi_set_DSP_cfg: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
 #else
 						PRINTK_3(TRACE_SMAPI,
+							"smapi::smapi_set_DSP_cfg: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
 #endif
-							"smapi::smapi_set_DSP_cfg: Serial port B base I/O address index %x conflicts with uartio_index %x\n", usSI >> 8, uartio_index);
 #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
 						PRINTK_1 (TRACE_SMAPI,
-						    "smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n");
+						    "smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n");
 						bRC = smapi_request (0x1405, 0x0100, 0, usSI,
 							&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
 						if (bRC) goto exit_smapi_request_error;
@@ -380,39 +384,15 @@
 			&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
 		if (bRC) goto exit_smapi_request_error;
 		/* bRC == 0 */
-		if ((usCX & 0xff) == mwave_uart_irq) {	/* serial port is enabled */
-#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
-			PRINTK_ERROR(KERN_ERR_MWAVE
-#else
-			PRINTK_3(TRACE_SMAPI,
-#endif
-				"smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usSI, mwave_uart_irq);
-#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
-			PRINTK_1(TRACE_SMAPI,
-				"smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
-			bRC = smapi_request(0x1701, 0x0100, 0, 0,
-				&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
-			if (bRC) goto exit_smapi_request_error;
-			bRC = smapi_request(0x1700, 0, 0, 0,
-				&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
-			if (bRC) goto exit_smapi_request_error;
-			bRC = smapi_request(0x1705, 0x01ff, 0, usSI,
-				&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
-			if (bRC) goto exit_smapi_request_error;
-			bRC = smapi_request(0x1704, 0x0000, 0, 0,
-				&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
-			if (bRC) goto exit_smapi_request_error;
-#else
-			goto exit_conflict;
-#endif
-		} else {
-			if ((usSI & 0xff) == uartio_index) {
+		if ((usCX & 0xff) != 0xff) { /* IR port not disabled */
+			if ((usCX & 0xff) == mwave_uart_irq) {
 #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
 				PRINTK_ERROR(KERN_ERR_MWAVE
+					"smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq);
 #else
 				PRINTK_3(TRACE_SMAPI,
+					"smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq);
 #endif
-					"smapi::smapi_set_DSP_cfg: IR port base I/O address index %x conflicts with uartio_index %x\n", usSI & 0xff, uartio_index);
 #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
 				PRINTK_1(TRACE_SMAPI,
 					"smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
@@ -431,6 +411,34 @@
 #else
 				goto exit_conflict;
 #endif
+			} else {
+				if ((usSI & 0xff) == uartio_index) {
+#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
+					PRINTK_ERROR(KERN_ERR_MWAVE
+						"smapi::smapi_set_DSP_cfg: IR port base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI & 0xff], ausUartBases[uartio_index]);
+#else
+					PRINTK_3(TRACE_SMAPI,
+						"smapi::smapi_set_DSP_cfg: IR port base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI & 0xff], ausUartBases[uartio_index]);
+#endif
+#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
+					PRINTK_1(TRACE_SMAPI,
+						"smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
+					bRC = smapi_request(0x1701, 0x0100, 0, 0,
+						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
+					if (bRC) goto exit_smapi_request_error;
+					bRC = smapi_request(0x1700, 0, 0, 0,
+						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
+					if (bRC) goto exit_smapi_request_error;
+					bRC = smapi_request(0x1705, 0x01ff, 0, usSI,
+						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
+					if (bRC) goto exit_smapi_request_error;
+					bRC = smapi_request(0x1704, 0x0000, 0, 0,
+						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
+					if (bRC) goto exit_smapi_request_error;
+#else
+					goto exit_conflict;
+#endif
+				}
 			}
 		}
 	}
diff -urN linux-2.5.65-bk2/drivers/char/rio/rioboot.c linux-2.5.65-bk3/drivers/char/rio/rioboot.c
--- linux-2.5.65-bk2/drivers/char/rio/rioboot.c	Mon Mar 17 13:43:49 2003
+++ linux-2.5.65-bk3/drivers/char/rio/rioboot.c	Mon Mar 31 12:41:40 2003
@@ -34,7 +34,6 @@
 static char *_rioboot_c_sccs_ = "@(#)rioboot.c	1.3";
 #endif
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/rio/riocmd.c linux-2.5.65-bk3/drivers/char/rio/riocmd.c
--- linux-2.5.65-bk2/drivers/char/rio/riocmd.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/char/rio/riocmd.c	Mon Mar 31 12:41:40 2003
@@ -34,7 +34,6 @@
 static char *_riocmd_c_sccs_ = "@(#)riocmd.c	1.2";
 #endif
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/rio/rioctrl.c linux-2.5.65-bk3/drivers/char/rio/rioctrl.c
--- linux-2.5.65-bk2/drivers/char/rio/rioctrl.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/drivers/char/rio/rioctrl.c	Mon Mar 31 12:41:40 2003
@@ -34,7 +34,6 @@
 #endif
 
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/rio/rioinit.c linux-2.5.65-bk3/drivers/char/rio/rioinit.c
--- linux-2.5.65-bk2/drivers/char/rio/rioinit.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/char/rio/rioinit.c	Mon Mar 31 12:41:40 2003
@@ -33,7 +33,6 @@
 static char *_rioinit_c_sccs_ = "@(#)rioinit.c	1.3";
 #endif
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
diff -urN linux-2.5.65-bk2/drivers/char/rio/riointr.c linux-2.5.65-bk3/drivers/char/rio/riointr.c
--- linux-2.5.65-bk2/drivers/char/rio/riointr.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/drivers/char/rio/riointr.c	Mon Mar 31 12:41:40 2003
@@ -34,7 +34,6 @@
 #endif
 
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/rio/rioparam.c linux-2.5.65-bk3/drivers/char/rio/rioparam.c
--- linux-2.5.65-bk2/drivers/char/rio/rioparam.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/drivers/char/rio/rioparam.c	Mon Mar 31 12:41:40 2003
@@ -34,7 +34,6 @@
 static char *_rioparam_c_sccs_ = "@(#)rioparam.c	1.3";
 #endif
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/rio/rioroute.c linux-2.5.65-bk3/drivers/char/rio/rioroute.c
--- linux-2.5.65-bk2/drivers/char/rio/rioroute.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/drivers/char/rio/rioroute.c	Mon Mar 31 12:41:40 2003
@@ -33,7 +33,6 @@
 static char *_rioroute_c_sccs_ = "@(#)rioroute.c	1.3";
 #endif
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/rio/riotable.c linux-2.5.65-bk3/drivers/char/rio/riotable.c
--- linux-2.5.65-bk2/drivers/char/rio/riotable.c	Mon Mar 17 13:44:45 2003
+++ linux-2.5.65-bk3/drivers/char/rio/riotable.c	Mon Mar 31 12:41:40 2003
@@ -33,7 +33,6 @@
 static char *_riotable_c_sccs_ = "@(#)riotable.c	1.2";
 #endif
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/rio/riotty.c linux-2.5.65-bk3/drivers/char/rio/riotty.c
--- linux-2.5.65-bk2/drivers/char/rio/riotty.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk3/drivers/char/rio/riotty.c	Mon Mar 31 12:41:40 2003
@@ -36,7 +36,6 @@
 
 #define __EXPLICIT_DEF_H__
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -urN linux-2.5.65-bk2/drivers/char/rtc.c linux-2.5.65-bk3/drivers/char/rtc.c
--- linux-2.5.65-bk2/drivers/char/rtc.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/drivers/char/rtc.c	Mon Mar 31 12:41:40 2003
@@ -47,7 +47,7 @@
 
 #define RTC_VERSION		"1.11"
 
-#define RTC_IO_EXTENT	0x10	/* Only really two ports, but...	*/
+#define RTC_IO_EXTENT	0x8
 
 /*
  *	Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
diff -urN linux-2.5.65-bk2/drivers/char/upd4990a.c linux-2.5.65-bk3/drivers/char/upd4990a.c
--- linux-2.5.65-bk2/drivers/char/upd4990a.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/drivers/char/upd4990a.c	Mon Mar 31 12:41:40 2003
@@ -0,0 +1,423 @@
+/*
+ * NEC PC-9800 Real Time Clock interface for Linux	
+ *
+ * Copyright (C) 1997-2001  Linux/98 project,
+ *			    Kyoto University Microcomputer Club.
+ *
+ * Based on:
+ *	drivers/char/rtc.c by Paul Gortmaker
+ *
+ * Changes:
+ *  2001-02-09	Call check_region on rtc_init and do not request I/O 0033h.
+ *		Call del_timer and release_region on rtc_exit. -- tak
+ *  2001-07-14	Rewrite <linux/upd4990a.h> and split to <linux/upd4990a.h>
+ *		and <asm-i386/upd4990a.h>.
+ *		Introduce a lot of spin_lock/unlock (&rtc_lock).
+ */
+
+#define RTC98_VERSION	"1.2"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/upd4990a.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/*
+ *	We sponge a minor off of the misc major. No need slurping
+ *	up another valuable major dev number for this. If you add
+ *	an ioctl, make sure you don't conflict with SPARC's RTC
+ *	ioctls.
+ */
+
+static struct fasync_struct *rtc_async_queue;
+
+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
+
+static struct timer_list rtc_uie_timer;
+static u8 old_refclk;
+
+static int rtc_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg);
+
+static int rtc_read_proc(char *page, char **start, off_t off,
+			  int count, int *eof, void *data);
+
+/*
+ *	Bits in rtc_status. (5 bits of room for future expansion)
+ */
+
+#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
+#define RTC_TIMER_ON            0x02    /* not used */
+#define RTC_UIE_TIMER_ON        0x04	/* UIE emulation timer is active */
+
+/*
+ * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is
+ * protected by the big kernel lock. However, ioctl can still disable the timer
+ * in rtc_status and then with del_timer after the interrupt has read
+ * rtc_status but before mod_timer is called, which would then reenable the
+ * timer (but you would need to have an awful timing before you'd trip on it)
+ */
+static unsigned char rtc_status;	/* bitmapped status byte.	*/
+static unsigned long rtc_irq_data;	/* our output to the world	*/
+
+static const unsigned char days_in_mo[] = 
+{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+extern spinlock_t rtc_lock;	/* defined in arch/i386/kernel/time.c */
+
+static void rtc_uie_intr(unsigned long data)
+{
+	u8 refclk, tmp;
+
+	/* Kernel timer does del_timer internally before calling
+	   each timer entry, so this is unnecessary.
+	   del_timer(&rtc_uie_timer);  */
+	spin_lock(&rtc_lock);
+
+	/* Detect rising edge of 1Hz reference clock.  */
+	refclk = UPD4990A_READ_DATA();
+	tmp = old_refclk & refclk;
+	old_refclk = ~refclk;
+	if (!(tmp & 1))
+		rtc_irq_data += 0x100;
+
+	spin_unlock(&rtc_lock);
+
+	if (!(tmp & 1)) {
+		/* Now do the rest of the actions */
+		wake_up_interruptible(&rtc_wait);
+		kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+	}
+
+	rtc_uie_timer.expires = jiffies + 1;
+	add_timer(&rtc_uie_timer);
+}
+
+/*
+ *	Now all the various file operations that we export.
+ */
+
+static ssize_t rtc_read(struct file *file, char *buf,
+			size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long data;
+	ssize_t retval = 0;
+	
+	if (count < sizeof(unsigned long))
+		return -EINVAL;
+
+	add_wait_queue(&rtc_wait, &wait);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	do {
+		/* First make it right. Then make it fast. Putting this whole
+		 * block within the parentheses of a while would be too
+		 * confusing. And no, xchg() is not the answer. */
+		spin_lock_irq(&rtc_lock);
+		data = rtc_irq_data;
+		rtc_irq_data = 0;
+		spin_unlock_irq(&rtc_lock);
+
+		if (data != 0)
+			break;
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto out;
+		}
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+		schedule();
+	} while (1);
+
+	retval = put_user(data, (unsigned long *)buf);
+	if (!retval)
+		retval = sizeof(unsigned long); 
+ out:
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&rtc_wait, &wait);
+
+	return retval;
+}
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg)
+{
+	struct rtc_time wtime; 
+	struct upd4990a_raw_data raw;
+
+	switch (cmd) {
+	case RTC_UIE_OFF:	/* Mask ints from RTC updates.	*/
+		spin_lock_irq(&rtc_lock);
+		if (rtc_status & RTC_UIE_TIMER_ON) {
+			rtc_status &= ~RTC_UIE_TIMER_ON;
+			del_timer(&rtc_uie_timer);
+		}
+		spin_unlock_irq(&rtc_lock);
+		return 0;
+
+	case RTC_UIE_ON:	/* Allow ints for RTC updates.	*/
+		spin_lock_irq(&rtc_lock);
+		rtc_irq_data = 0;
+		if (!(rtc_status & RTC_UIE_TIMER_ON)) {
+			rtc_status |= RTC_UIE_TIMER_ON;
+			rtc_uie_timer.expires = jiffies + 1;
+			add_timer(&rtc_uie_timer);
+		}
+		/* Just in case... */
+		upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
+		old_refclk = ~UPD4990A_READ_DATA();
+		spin_unlock_irq(&rtc_lock);
+		return 0;
+
+	case RTC_RD_TIME:	/* Read the time/date from RTC	*/
+		spin_lock_irq(&rtc_lock);
+		upd4990a_get_time(&raw, 0);
+		spin_unlock_irq(&rtc_lock);
+
+		wtime.tm_sec	= BCD2BIN(raw.sec);
+		wtime.tm_min	= BCD2BIN(raw.min);
+		wtime.tm_hour	= BCD2BIN(raw.hour);
+		wtime.tm_mday	= BCD2BIN(raw.mday);
+		wtime.tm_mon	= raw.mon - 1; /* convert to 0-base */
+		wtime.tm_wday	= raw.wday;
+
+		/*
+		 * Account for differences between how the RTC uses the values
+		 * and how they are defined in a struct rtc_time;
+		 */
+		if ((wtime.tm_year = BCD2BIN(raw.year)) < 95)
+			wtime.tm_year += 100;
+
+		wtime.tm_isdst = 0;
+		break;
+
+	case RTC_SET_TIME:	/* Set the RTC */
+	{
+		int leap_yr;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		if (copy_from_user(&wtime, (struct rtc_time *) arg,
+				    sizeof (struct rtc_time)))
+			return -EFAULT;
+
+		/* Valid year is 1995 - 2094, inclusive.  */
+		if (wtime.tm_year < 95 || wtime.tm_year > 194)
+			return -EINVAL;
+
+		if (wtime.tm_mon > 11 || wtime.tm_mday == 0)
+			return -EINVAL;
+
+		/* For acceptable year domain (1995 - 2094),
+		   this IS sufficient.  */
+		leap_yr = !(wtime.tm_year % 4);
+
+		if (wtime.tm_mday > (days_in_mo[wtime.tm_mon]
+				     + (wtime.tm_mon == 2 && leap_yr)))
+			return -EINVAL;
+			
+		if (wtime.tm_hour >= 24
+		    || wtime.tm_min >= 60 || wtime.tm_sec >= 60)
+			return -EINVAL;
+
+		if (wtime.tm_wday > 6)
+			return -EINVAL;
+
+		raw.sec  = BIN2BCD(wtime.tm_sec);
+		raw.min  = BIN2BCD(wtime.tm_min);
+		raw.hour = BIN2BCD(wtime.tm_hour);
+		raw.mday = BIN2BCD(wtime.tm_mday);
+		raw.mon  = wtime.tm_mon + 1;
+		raw.wday = wtime.tm_wday;
+		raw.year = BIN2BCD(wtime.tm_year % 100);
+
+		spin_lock_irq(&rtc_lock);
+		upd4990a_set_time(&raw, 0);
+		spin_unlock_irq(&rtc_lock);
+
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	}
+	return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
+}
+
+/*
+ *	We enforce only one user at a time here with the open/close.
+ *	Also clear the previous interrupt data on an open, and clean
+ *	up things on a close.
+ */
+
+static int rtc_open(struct inode *inode, struct file *file)
+{
+	spin_lock_irq(&rtc_lock);
+
+	if(rtc_status & RTC_IS_OPEN)
+		goto out_busy;
+
+	rtc_status |= RTC_IS_OPEN;
+
+	rtc_irq_data = 0;
+	spin_unlock_irq(&rtc_lock);
+	return 0;
+
+ out_busy:
+	spin_unlock_irq(&rtc_lock);
+	return -EBUSY;
+}
+
+static int rtc_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &rtc_async_queue);
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+	del_timer(&rtc_uie_timer);
+
+	if (file->f_flags & FASYNC)
+		rtc_fasync(-1, file, 0);
+
+	rtc_irq_data = 0;
+
+	/* No need for locking -- nobody else can do anything until this rmw is
+	 * committed, and no timer is running. */
+	rtc_status &= ~(RTC_IS_OPEN | RTC_UIE_TIMER_ON);
+	return 0;
+}
+
+static unsigned int rtc_poll(struct file *file, poll_table *wait)
+{
+	unsigned long l;
+
+	poll_wait(file, &rtc_wait, wait);
+
+	spin_lock_irq(&rtc_lock);
+	l = rtc_irq_data;
+	spin_unlock_irq(&rtc_lock);
+
+	if (l != 0)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+/*
+ *	The various file operations we support.
+ */
+
+static struct file_operations rtc_fops = {
+	.owner		= THIS_MODULE,
+	.read		= rtc_read,
+	.poll		= rtc_poll,
+	.ioctl		= rtc_ioctl,
+	.open		= rtc_open,
+	.release	= rtc_release,
+	.fasync		= rtc_fasync,
+};
+
+static struct miscdevice rtc_dev=
+{
+	.minor	= RTC_MINOR,
+	.name	= "rtc",
+	.fops	= &rtc_fops,
+};
+
+static int __init rtc_init(void)
+{
+	if (!request_region(UPD4990A_IO, 1, "rtc")) {
+		printk(KERN_ERR "upd4990a: could not acquire I/O port %#x\n",
+			UPD4990A_IO);
+		return -EBUSY;
+	}
+
+#if 0
+	printk(KERN_INFO "\xB6\xDA\xDD\xC0\xDE \xC4\xDE\xB9\xB2 Driver\n");  /* Calender Clock Driver */
+#else
+	printk(KERN_INFO
+	       "Real Time Clock driver for NEC PC-9800 v" RTC98_VERSION "\n");
+#endif
+	misc_register(&rtc_dev);
+	create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL);
+
+	init_timer(&rtc_uie_timer);
+	rtc_uie_timer.function = rtc_uie_intr;
+
+	return 0;
+}
+
+module_init (rtc_init);
+
+static void __exit rtc_exit(void)
+{
+	del_timer(&rtc_uie_timer);
+	release_region(UPD4990A_IO, 1);
+	remove_proc_entry("driver/rtc", NULL);
+	misc_deregister(&rtc_dev);
+}
+
+module_exit (rtc_exit);
+
+/*
+ *	Info exported via "/proc/driver/rtc".
+ */
+
+static inline int rtc_get_status(char *buf)
+{
+	char *p;
+	unsigned int year;
+	struct upd4990a_raw_data data;
+
+	p = buf;
+
+	upd4990a_get_time(&data, 0);
+
+	/*
+	 * There is no way to tell if the luser has the RTC set for local
+	 * time or for Universal Standard Time (GMT). Probably local though.
+	 */
+	if ((year = BCD2BIN(data.year) + 1900) < 1995)
+		year += 100;
+	p += sprintf(p,
+		     "rtc_time\t: %02d:%02d:%02d\n"
+		     "rtc_date\t: %04d-%02d-%02d\n",
+		     BCD2BIN(data.hour), BCD2BIN(data.min),
+		     BCD2BIN(data.sec),
+		     year, data.mon, BCD2BIN(data.mday));
+
+	return  p - buf;
+}
+
+static int rtc_read_proc(char *page, char **start, off_t off,
+			 int count, int *eof, void *data)
+{
+	int len = rtc_get_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;
+}
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/acquirewdt.c linux-2.5.65-bk3/drivers/char/watchdog/acquirewdt.c
--- linux-2.5.65-bk2/drivers/char/watchdog/acquirewdt.c	Mon Mar 17 13:44:14 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/acquirewdt.c	Mon Mar 31 12:41:40 2003
@@ -141,6 +141,8 @@
 			spin_unlock(&acq_lock);
 			return -EBUSY;
 		}
+		if (nowayout)
+			MOD_INC_USE_COUNT;
 
 		/* Activate */
 		acq_is_open=1;
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/ib700wdt.c linux-2.5.65-bk3/drivers/char/watchdog/ib700wdt.c
--- linux-2.5.65-bk2/drivers/char/watchdog/ib700wdt.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/ib700wdt.c	Mon Mar 31 12:41:40 2003
@@ -228,6 +228,8 @@
 			spin_unlock(&ibwdt_lock);
 			return -EBUSY;
 		}
+		if (nowayout)
+			MOD_INC_USE_COUNT;
 
 		/* Activate */
 		ibwdt_is_open = 1;
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/indydog.c linux-2.5.65-bk3/drivers/char/watchdog/indydog.c
--- linux-2.5.65-bk2/drivers/char/watchdog/indydog.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/indydog.c	Mon Mar 31 12:41:40 2003
@@ -53,6 +53,9 @@
 	if( test_and_set_bit(0,&indydog_alive) )
 		return -EBUSY;
 
+	if (nowayout)
+		MOD_INC_USE_COUNT;
+
 	/*
 	 *	Activate timer
 	 */
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/machzwd.c linux-2.5.65-bk3/drivers/char/watchdog/machzwd.c
--- linux-2.5.65-bk2/drivers/char/watchdog/machzwd.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/machzwd.c	Mon Mar 31 12:41:40 2003
@@ -390,6 +390,9 @@
 				return -EBUSY;
 			}
 
+			if (nowayout)
+				MOD_INC_USE_COUNT;
+
 			zf_is_open = 1;
 
 			spin_unlock(&zf_lock);
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/mixcomwd.c linux-2.5.65-bk3/drivers/char/watchdog/mixcomwd.c
--- linux-2.5.65-bk2/drivers/char/watchdog/mixcomwd.c	Mon Mar 17 13:43:49 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/mixcomwd.c	Mon Mar 31 12:41:40 2003
@@ -93,7 +93,9 @@
 	}
 	mixcomwd_ping();
 	
-	if (!nowayout) {
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	} else {
 		if(mixcomwd_timer_alive) {
 			del_timer(&mixcomwd_timer);
 			mixcomwd_timer_alive=0;
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/pcwd.c linux-2.5.65-bk3/drivers/char/watchdog/pcwd.c
--- linux-2.5.65-bk2/drivers/char/watchdog/pcwd.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/pcwd.c	Mon Mar 31 12:41:40 2003
@@ -430,7 +430,7 @@
 			atomic_inc( &open_allowed );
 			return -EBUSY;
 		}
-
+		MOD_INC_USE_COUNT;
 		/*  Enable the port  */
 		if (revision == PCWD_REVISION_C) {
 			spin_lock(&io_lock);
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/sbc60xxwdt.c linux-2.5.65-bk3/drivers/char/watchdog/sbc60xxwdt.c
--- linux-2.5.65-bk2/drivers/char/watchdog/sbc60xxwdt.c	Mon Mar 17 13:44:20 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/sbc60xxwdt.c	Mon Mar 31 12:41:40 2003
@@ -206,7 +206,9 @@
 			/* Just in case we're already talking to someone... */
 			if(wdt_is_open)
 				return -EBUSY;
-
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/* Good, fire up the show */
 			wdt_is_open = 1;
 			wdt_startup();
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/sc520_wdt.c linux-2.5.65-bk3/drivers/char/watchdog/sc520_wdt.c
--- linux-2.5.65-bk2/drivers/char/watchdog/sc520_wdt.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/sc520_wdt.c	Mon Mar 31 12:41:40 2003
@@ -229,6 +229,8 @@
 				return -EBUSY;
 			/* Good, fire up the show */
 			wdt_startup();
+			if (nowayout)
+				MOD_INC_USE_COUNT;
 
 			return 0;
 		default:
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/shwdt.c linux-2.5.65-bk3/drivers/char/watchdog/shwdt.c
--- linux-2.5.65-bk2/drivers/char/watchdog/shwdt.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/shwdt.c	Mon Mar 31 12:41:40 2003
@@ -189,6 +189,10 @@
 			if (test_and_set_bit(0, &sh_is_open))
 				return -EBUSY;
 
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
+
 			sh_wdt_start();
 
 			break;
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/softdog.c linux-2.5.65-bk3/drivers/char/watchdog/softdog.c
--- linux-2.5.65-bk2/drivers/char/watchdog/softdog.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/softdog.c	Mon Mar 31 12:41:40 2003
@@ -103,7 +103,9 @@
 {
 	if(test_and_set_bit(0, &timer_alive))
 		return -EBUSY;
-
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	}
 	/*
 	 *	Activate timer
 	 */
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/wdt977.c linux-2.5.65-bk3/drivers/char/watchdog/wdt977.c
--- linux-2.5.65-bk2/drivers/char/watchdog/wdt977.c	Mon Mar 17 13:44:40 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/wdt977.c	Mon Mar 31 12:41:40 2003
@@ -99,6 +99,8 @@
 
 	if (nowayout)
 	{
+		MOD_INC_USE_COUNT;
+
 		/* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */
 		if (!timeoutM) timeoutM = DEFAULT_TIMEOUT;
 	}
diff -urN linux-2.5.65-bk2/drivers/char/watchdog/wdt_pci.c linux-2.5.65-bk3/drivers/char/watchdog/wdt_pci.c
--- linux-2.5.65-bk2/drivers/char/watchdog/wdt_pci.c	Mon Mar 17 13:44:15 2003
+++ linux-2.5.65-bk3/drivers/char/watchdog/wdt_pci.c	Mon Mar 31 12:41:40 2003
@@ -365,6 +365,9 @@
 			if (down_trylock(&open_sem))
 				return -EBUSY;
 
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
diff -urN linux-2.5.65-bk2/drivers/fc4/fc_syms.c linux-2.5.65-bk3/drivers/fc4/fc_syms.c
--- linux-2.5.65-bk2/drivers/fc4/fc_syms.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/drivers/fc4/fc_syms.c	Mon Mar 31 12:41:40 2003
@@ -2,7 +2,6 @@
  * We should not even be trying to compile this if we are not doing
  * a module.
  */
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
 
diff -urN linux-2.5.65-bk2/drivers/ide/Makefile linux-2.5.65-bk3/drivers/ide/Makefile
--- linux-2.5.65-bk2/drivers/ide/Makefile	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/drivers/ide/Makefile	Mon Mar 31 12:41:40 2003
@@ -12,7 +12,7 @@
 
 # Core IDE code - must come before legacy
 
-obj-$(CONFIG_BLK_DEV_IDE)		+= ide-io.o ide-probe.o ide-geometry.o ide-iops.o ide-taskfile.o ide.o ide-lib.o
+obj-$(CONFIG_BLK_DEV_IDE)		+= ide-io.o ide-probe.o ide-geometry.o ide-iops.o ide-taskfile.o ide.o ide-lib.o ide-default.o
 obj-$(CONFIG_BLK_DEV_IDEDISK)		+= ide-disk.o
 obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd.o
 obj-$(CONFIG_BLK_DEV_IDETAPE)		+= ide-tape.o
diff -urN linux-2.5.65-bk2/drivers/ide/ide-cd.c linux-2.5.65-bk3/drivers/ide/ide-cd.c
--- linux-2.5.65-bk2/drivers/ide/ide-cd.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-cd.c	Mon Mar 31 12:41:40 2003
@@ -294,7 +294,7 @@
  *
  *************************************************************************/
  
-#define IDECD_VERSION "4.59"
+#define IDECD_VERSION "4.59-ac1"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -635,6 +635,23 @@
 	return ide_stopped;
 }
 
+ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg)
+{
+	struct request *rq;
+
+	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+		return ide_stopped;
+	/* retry only "normal" I/O: */
+	if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+		rq->errors = 1;
+		ide_end_drive_cmd(drive, BUSY_STAT, 0);
+		return ide_stopped;
+	}
+	rq->errors |= ERROR_RESET;
+	DRIVER(drive)->end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
 static void cdrom_end_request (ide_drive_t *drive, int uptodate)
 {
 	struct request *rq = HWGROUP(drive)->rq;
@@ -899,9 +916,6 @@
 			return startstop;
 	}
 
-	if (HWGROUP(drive)->handler != NULL)	/* paranoia check */
-		BUG();
-
 	/* Arm the interrupt handler. */
 	ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
 
@@ -1133,9 +1147,6 @@
 		}
 	}
 
-	if (HWGROUP(drive)->handler != NULL)    /* paranoia check */
-		BUG();
-
 	/* Done moving data!  Wait for another interrupt. */
 	ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL);
 	return ide_started;
@@ -1470,9 +1481,6 @@
 		rq->flags |= REQ_FAILED;
 	}
 
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-
 	/* Now we wait for another interrupt. */
 	ide_set_handler(drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
 	return ide_started;
@@ -1863,9 +1871,6 @@
 			cdrom_end_request(drive, 1);
 	}
 
-	if (HWGROUP(drive)->handler != NULL)	/* paranoia check */
-		BUG();
-
 	/* re-arm handler */
 	ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
 	return ide_started;
@@ -2837,11 +2842,9 @@
 	 * ACER50 (and others?) require the full spec length mode sense
 	 * page capabilities size, but older drives break.
 	 */
-	if (drive->id) {
-		if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
-		    !strcmp(drive->id->model, "WPI CDS-32X")))
-			size -= sizeof(cap->pad);
-	}
+	if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
+	    !strcmp(drive->id->model, "WPI CDS-32X")))
+		size -= sizeof(cap->pad);
 
 	/* we have to cheat a little here. the packet will eventually
 	 * be queued with ide_cdrom_packet(), which extracts the
@@ -2924,7 +2927,7 @@
 	}
 
 	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
-	if (drive->id && !drive->id->model[0] &&
+	if (!drive->id->model[0] &&
 	    !strncmp(drive->id->fw_rev, "241N", 4)) {
 		CDROM_STATE_FLAGS(drive)->current_speed  = 
 			(((unsigned int)cap.curspeed) + (176/2)) / 176;
@@ -3089,12 +3092,7 @@
 	CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0;
 #endif
 
-	if (drive->id != NULL)
-		CDROM_CONFIG_FLAGS(drive)->drq_interrupt =
-			((drive->id->config & 0x0060) == 0x20);
-	else
-		CDROM_CONFIG_FLAGS(drive)->drq_interrupt = 0;
-
+	CDROM_CONFIG_FLAGS(drive)->drq_interrupt = ((drive->id->config & 0x0060) == 0x20);
 	CDROM_CONFIG_FLAGS(drive)->is_changer = 0;
 	CDROM_CONFIG_FLAGS(drive)->cd_r = 0;
 	CDROM_CONFIG_FLAGS(drive)->cd_rw = 0;
@@ -3109,16 +3107,14 @@
 	
 	/* limit transfer size per interrupt. */
 	CDROM_CONFIG_FLAGS(drive)->limit_nframes = 0;
-	if (drive->id != NULL) {
-		/* a testament to the nice quality of Samsung drives... */
-		if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
-			CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
-		else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
-			CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
-		/* the 3231 model does not support the SET_CD_SPEED command */
-		else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231"))
-			cdi->mask |= CDC_SELECT_SPEED;
-	}
+	/* a testament to the nice quality of Samsung drives... */
+	if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
+		CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
+	else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
+		CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
+	/* the 3231 model does not support the SET_CD_SPEED command */
+	else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231"))
+		cdi->mask |= CDC_SELECT_SPEED;
 
 #if ! STANDARD_ATAPI
 	/* by default Sanyo 3 CD changer support is turned off and
@@ -3131,55 +3127,47 @@
 	CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 0;
 	CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 0;
 
-	if (drive->id != NULL) {
-		if (strcmp (drive->id->model, "V003S0DS") == 0 &&
-		    drive->id->fw_rev[4] == '1' &&
-		    drive->id->fw_rev[6] <= '2') {
-			/* Vertos 300.
-			   Some versions of this drive like to talk BCD. */
-			CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
-			CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
-			CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
-			CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
-		}
-
-		else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
-		    drive->id->fw_rev[4] == '1' &&
-		    drive->id->fw_rev[6] <= '2') {
-			/* Vertos 600 ESD. */
-			CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
-		}
-
-		else if (strcmp(drive->id->model,
-				 "NEC CD-ROM DRIVE:260") == 0 &&
-			 strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
-			/* Old NEC260 (not R).
-			   This drive was released before the 1.2 version
-			   of the spec. */
-			CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
-			CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
-			CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
-			CDROM_CONFIG_FLAGS(drive)->nec260         = 1;
-		}
-
-		else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 &&
-			 strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
-			/* Wearnes */
-			CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
-			CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
-		}
-
-                /* Sanyo 3 CD changer uses a non-standard command
-                    for CD changing */
-                 else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
-                         (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
-                         (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
-                        /* uses CD in slot 0 when value is set to 3 */
-                        cdi->sanyo_slot = 3;
-                }
-
-
-	}
+	if (strcmp (drive->id->model, "V003S0DS") == 0 &&
+	    drive->id->fw_rev[4] == '1' &&
+	    drive->id->fw_rev[6] <= '2') {
+		/* Vertos 300.
+		   Some versions of this drive like to talk BCD. */
+		CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
+		CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
+		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
+		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
+	}
+
+	else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
+	    drive->id->fw_rev[4] == '1' &&
+	    drive->id->fw_rev[6] <= '2') {
+		/* Vertos 600 ESD. */
+		CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
+	}
+	else if (strcmp(drive->id->model, "NEC CD-ROM DRIVE:260") == 0 &&
+		 strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
+		/* Old NEC260 (not R).
+		   This drive was released before the 1.2 version
+		   of the spec. */
+		CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
+		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
+		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
+		CDROM_CONFIG_FLAGS(drive)->nec260         = 1;
+	}
+	else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 &&
+		 strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
+		/* Wearnes */
+		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
+		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
+	}
+        /* Sanyo 3 CD changer uses a non-standard command
+           for CD changing */
+        else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
+                 (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
+                 (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
+                 /* uses CD in slot 0 when value is set to 3 */
+                 cdi->sanyo_slot = 3;
+        }
 #endif /* not STANDARD_ATAPI */
 
 	info->toc		= NULL;
@@ -3246,6 +3234,7 @@
 		printk("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
 	kfree(info);
 	drive->driver_data = NULL;
+	blk_queue_prep_rq(&drive->queue, NULL);
 	del_gendisk(g);
 	g->fops = ide_fops;
 	return 0;
@@ -3265,6 +3254,7 @@
 	.do_request		= ide_do_rw_cdrom,
 	.sense			= ide_cdrom_dump_status,
 	.error			= ide_cdrom_error,
+	.abort			= ide_cdrom_abort,
 	.capacity		= ide_cdrom_capacity,
 	.attach			= ide_cdrom_attach,
 	.drives			= LIST_HEAD_INIT(ide_cdrom_driver.drives),
diff -urN linux-2.5.65-bk2/drivers/ide/ide-default.c linux-2.5.65-bk3/drivers/ide/ide-default.c
--- linux-2.5.65-bk2/drivers/ide/ide-default.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/drivers/ide/ide-default.c	Mon Mar 31 12:41:40 2003
@@ -0,0 +1,71 @@
+/*
+ *	ide-default		-	Driver for unbound ide devices
+ *
+ *	This provides a clean way to bind a device to default operations
+ *	by having an actual driver class that rather than special casing
+ *	"no driver" all over the IDE code
+ *
+ *	Copyright (C) 2003, Red Hat <alan@redhat.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/cdrom.h>
+#include <linux/ide.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <asm/bitops.h>
+
+#define IDEDEFAULT_VERSION	"0.9.newide"
+/*
+ *	Driver initialization.
+ */
+
+static int idedefault_attach(ide_drive_t *drive);
+
+/*
+ *	IDE subdriver functions, registered with ide.c
+ *
+ *	idedefault *must* support DMA because it will be
+ *	attached before the other drivers are loaded and
+ *	we don't want to lose the DMA status at probe
+ *	time.
+ */
+
+ide_driver_t idedefault_driver = {
+	.name		=	"ide-default",
+	.version	=	IDEDEFAULT_VERSION,
+	.attach		=	idedefault_attach,
+	.supports_dma	=	1,
+	.drives		=	LIST_HEAD_INIT(idedefault_driver.drives)
+};
+
+static int idedefault_attach (ide_drive_t *drive)
+{
+	if (ide_register_subdriver(drive,
+			&idedefault_driver, IDE_SUBDRIVER_VERSION)) {
+		printk(KERN_ERR "ide-default: %s: Failed to register the "
+			"driver with ide.c\n", drive->name);
+		return 1;
+	}
+	return 0;
+}
+
+MODULE_DESCRIPTION("IDE Default Driver");
+
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.65-bk2/drivers/ide/ide-disk.c linux-2.5.65-bk3/drivers/ide/ide-disk.c
--- linux-2.5.65-bk2/drivers/ide/ide-disk.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-disk.c	Mon Mar 31 12:41:40 2003
@@ -1,11 +1,10 @@
 /*
- *  linux/drivers/ide/ide-disk.c	Version 1.16	April 7, 2002
+ *  linux/drivers/ide/ide-disk.c	Version 1.18	Mar 05, 2003
  *
+ *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  *  Copyright (C) 1998-2002  Linux ATA Developemt
  *				Andre Hedrick <andre@linux-ide.org>
- *
- *
- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
+ *  Copyright (C) 2003	     Red Hat <alan@redhat.com>
  */
 
 /*
@@ -42,7 +41,7 @@
  *			fix wcache setup.
  */
 
-#define IDEDISK_VERSION	"1.17"
+#define IDEDISK_VERSION	"1.18"
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
@@ -154,8 +153,6 @@
 			return DRIVER(drive)->error(drive, "read_intr", stat);
 		}
 		/* no data yet, so wait for another interrupt */
-		if (HWGROUP(drive)->handler != NULL)
-			BUG();
 		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
 		return ide_started;
 	}
@@ -189,8 +186,6 @@
 	if (i > 0) {
 		if (msect)
 			goto read_next;
-		if (HWGROUP(drive)->handler != NULL)
-			BUG();
 		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
                 return ide_started;
 	}
@@ -230,8 +225,6 @@
 				char *to = ide_map_buffer(rq, &flags);
 				taskfile_output_data(drive, to, SECTOR_WORDS);
 				ide_unmap_buffer(rq, to, &flags);
-				if (HWGROUP(drive)->handler != NULL)
-					BUG();
 				ide_set_handler(drive, &write_intr, WAIT_CMD, NULL);
                                 return ide_started;
 			}
@@ -332,8 +325,6 @@
 			if (rq->nr_sectors) {
 				if (ide_multwrite(drive, drive->mult_count))
 					return ide_stopped;
-				if (HWGROUP(drive)->handler != NULL)
-					BUG();
 				ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL);
 				return ide_started;
 			}
@@ -550,8 +541,6 @@
 	 * MAJOR DATA INTEGRITY BUG !!! only if we error 
 	 */
 			hwgroup->wrq = *rq; /* scratchpad */
-			if (HWGROUP(drive)->handler != NULL)
-				BUG();
 			ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL);
 			if (ide_multwrite(drive, drive->mult_count)) {
 				unsigned long flags;
@@ -564,8 +553,6 @@
 		} else {
 			unsigned long flags;
 			char *to = ide_map_buffer(rq, &flags);
-			if (HWGROUP(drive)->handler != NULL)
-				BUG();
 			ide_set_handler(drive, &write_intr, WAIT_CMD, NULL);
 			taskfile_output_data(drive, to, SECTOR_WORDS);
 			ide_unmap_buffer(rq, to, &flags);
@@ -941,6 +928,26 @@
 	return ide_stopped;
 }
 
+ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg)
+{
+	ide_hwif_t *hwif;
+	struct request *rq;
+
+	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+		return ide_stopped;
+
+	hwif = HWIF(drive);
+
+	if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
+		rq->errors = 1;
+		ide_end_drive_cmd(drive, BUSY_STAT, 0);
+		return ide_stopped;
+	}
+
+	DRIVER(drive)->end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
 /*
  * Queries for true maximum capacity of the drive.
  * Returns maximum LBA address (> 0) of the drive, 0 if failed.
@@ -1073,7 +1080,7 @@
 {
 	int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0;
 	if (flag)
-		printk("%s: host protected area => %d\n", drive->name, flag);
+		printk(KERN_INFO "%s: host protected area => %d\n", drive->name, flag);
 	return flag;
 }
 
@@ -1201,7 +1208,7 @@
 		}
 	} else if (s->b.set_multmode) {
 		s->b.set_multmode = 0;
-		if (drive->id && drive->mult_req > drive->id->max_multsect)
+		if (drive->mult_req > drive->id->max_multsect)
 			drive->mult_req = drive->id->max_multsect;
 		if (!IS_PDC4030_DRIVE) {
 			ide_task_t args;
@@ -1286,7 +1293,7 @@
 	char		*out = page;
 	int		len;
 
-	if (drive->id)
+	if (drive->id_read)
 		len = sprintf(out,"%i\n", drive->id->buf_size / 2);
 	else
 		len = sprintf(out,"(none)\n");
@@ -1549,7 +1556,7 @@
 	
 	idedisk_add_settings(drive);
 
-	if (id == NULL)
+	if (drive->id_read == 0)
 		return;
 
 	/*
@@ -1666,6 +1673,7 @@
 	.do_request		= do_rw_disk,
 	.sense			= idedisk_dump_status,
 	.error			= idedisk_error,
+	.abort			= idedisk_abort,
 	.pre_reset		= idedisk_pre_reset,
 	.capacity		= idedisk_capacity,
 	.special		= idedisk_special,
diff -urN linux-2.5.65-bk2/drivers/ide/ide-dma.c linux-2.5.65-bk3/drivers/ide/ide-dma.c
--- linux-2.5.65-bk2/drivers/ide/ide-dma.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-dma.c	Mon Mar 31 12:41:40 2003
@@ -75,7 +75,6 @@
  */
 
 #include <linux/config.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -419,7 +418,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_hwif_t *hwif = HWIF(drive);
 
-	if (id && (id->capability & 1) && hwif->autodma) {
+	if ((id->capability & 1) && hwif->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (hwif->ide_dma_bad_drive(drive))
 			return hwif->ide_dma_off(drive);
@@ -977,14 +976,12 @@
 {
 	printk(KERN_INFO "    %s: MMIO-DMA at 0x%08lx-0x%08lx",
 		hwif->name, base, base + ports - 1);
-	if (check_mem_region(base, ports)) {
-		printk(" -- Error, MMIO ports already in use.\n");
-		return 1;
-	}
-	request_mem_region(base, ports, hwif->name);
+	if (!request_mem_region(base, ports, hwif->name))
+		goto fail;
 	hwif->dma_base = base;
 	if ((hwif->cds->extra) && (hwif->channel == 0)) {
-		request_region(base+16, hwif->cds->extra, hwif->cds->name);
+		if (!request_region(base+16, hwif->cds->extra, hwif->cds->name))
+			goto release_mem;
 		hwif->dma_extra = hwif->cds->extra;
 	}
 	
@@ -993,10 +990,18 @@
 	else
 		hwif->dma_master = base;
 	if (hwif->dma_base2) {
-		if (!check_mem_region(hwif->dma_base2, ports))
-			request_mem_region(hwif->dma_base2, ports, hwif->name);
+		if (!request_mem_region(hwif->dma_base2, ports, hwif->name))
+			goto release_io;
 	}
 	return 0;
+
+release_mem:
+	release_mem_region(base, ports);
+release_io:
+	release_region(base+16, hwif->cds->extra);
+fail:
+	printk(" -- Error, MMIO ports already in use.\n");
+	return 1;
 }
 
 int ide_iomio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports)
diff -urN linux-2.5.65-bk2/drivers/ide/ide-geometry.c linux-2.5.65-bk3/drivers/ide/ide-geometry.c
--- linux-2.5.65-bk2/drivers/ide/ide-geometry.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-geometry.c	Mon Mar 31 12:41:40 2003
@@ -129,7 +129,7 @@
 	set_capacity(drive->disk, current_capacity(drive));
 
 	if (ret)
-		printk(KERN_INFO "%s%s [%d/%d/%d]", msg, msg1,
+		printk("%s%s [%d/%d/%d]", msg, msg1,
 		       drive->bios_cyl, drive->bios_head, drive->bios_sect);
 	return ret;
 }
diff -urN linux-2.5.65-bk2/drivers/ide/ide-io.c linux-2.5.65-bk3/drivers/ide/ide-io.c
--- linux-2.5.65-bk2/drivers/ide/ide-io.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-io.c	Mon Mar 31 12:41:40 2003
@@ -330,10 +330,7 @@
 		hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
 	}
 	if (rq->errors >= ERROR_MAX) {
-		if (drive->driver != NULL)
-			DRIVER(drive)->end_request(drive, 0, 0);
-		else
-	 		ide_end_request(drive, 0, 0);
+		DRIVER(drive)->end_request(drive, 0, 0);
 	} else {
 		if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
 			++rq->errors;
@@ -349,6 +346,49 @@
 EXPORT_SYMBOL(ide_error);
 
 /**
+ *	ide_abort	-	abort pending IDE operatins
+ *	@drive: drive the error occurred on
+ *	@msg: message to report
+ *
+ *	ide_abort kills and cleans up when we are about to do a 
+ *	host initiated reset on active commands. Longer term we
+ *	want handlers to have sensible abort handling themselves
+ *
+ *	This differs fundamentally from ide_error because in 
+ *	this case the command is doing just fine when we
+ *	blow it away.
+ */
+ 
+ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
+{
+	ide_hwif_t *hwif;
+	struct request *rq;
+
+	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+		return ide_stopped;
+
+	hwif = HWIF(drive);
+	/* retry only "normal" I/O: */
+	if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+		rq->errors = 1;
+		ide_end_drive_cmd(drive, BUSY_STAT, 0);
+		return ide_stopped;
+	}
+	if (rq->flags & REQ_DRIVE_TASKFILE) {
+		rq->errors = 1;
+		ide_end_drive_cmd(drive, BUSY_STAT, 0);
+//		ide_end_taskfile(drive, BUSY_STAT, 0);
+		return ide_stopped;
+	}
+
+	rq->errors |= ERROR_RESET;
+	DRIVER(drive)->end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
+EXPORT_SYMBOL(ide_abort);
+
+/**
  *	ide_cmd		-	issue a simple drive command
  *	@drive: drive the command is for
  *	@cmd: command byte
@@ -399,7 +439,7 @@
 			udelay(100);
 	}
 
-	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+	if (!OK_STAT(stat, READY_STAT, BAD_STAT) && DRIVER(drive) != NULL)
 		return DRIVER(drive)->error(drive, "drive_cmd", stat);
 		/* calls ide_end_drive_cmd */
 	ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
@@ -428,13 +468,10 @@
 		s->b.set_tune = 0;
 		if (HWIF(drive)->tuneproc != NULL)
 			HWIF(drive)->tuneproc(drive, drive->tune_req);
-	} else if (drive->driver != NULL) {
-		return DRIVER(drive)->special(drive);
-	} else if (s->all) {
-		printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, s->all);
-		s->all = 0;
+		return ide_stopped;
 	}
-	return ide_stopped;
+	else
+		return DRIVER(drive)->special(drive);
 }
 
 EXPORT_SYMBOL(do_special);
@@ -589,42 +626,17 @@
 			return execute_drive_cmd(drive, rq);
 		else if (rq->flags & REQ_DRIVE_TASKFILE)
 			return execute_drive_cmd(drive, rq);
-
-		if (drive->driver != NULL) {
-			return (DRIVER(drive)->do_request(drive, rq, block));
-		}
-		printk(KERN_ERR "%s: media type %d not supported\n", drive->name, drive->media);
-		goto kill_rq;
+		return (DRIVER(drive)->do_request(drive, rq, block));
 	}
 	return do_special(drive);
 kill_rq:
-	if (drive->driver != NULL)
-		DRIVER(drive)->end_request(drive, 0, 0);
-	else
-		ide_end_request(drive, 0, 0);
+	DRIVER(drive)->end_request(drive, 0, 0);
 	return ide_stopped;
 }
 
 EXPORT_SYMBOL(start_request);
 
 /**
- *	restart_request		-	reissue an IDE request
- *	@drive: drive for request
- *	@rq: request to reissue
- *
- *	Reissue a request. See start_request for details and for
- *	FIXME
- */
- 
-int restart_request (ide_drive_t *drive, struct request *rq)
-{
-	(void) start_request(drive, rq);
-	return 0;
-}
-
-EXPORT_SYMBOL(restart_request);
-
-/**
  *	ide_stall_queue		-	pause an IDE device
  *	@drive: drive to stall
  *	@timeout: time to stall for (jiffies)
@@ -742,8 +754,8 @@
 	/* for atari only: POSSIBLY BROKEN HERE(?) */
 	ide_get_lock(ide_intr, hwgroup);
 
-	/* necessary paranoia: ensure IRQs are masked on local CPU */
-	local_irq_disable();
+	/* caller must own ide_lock */
+	BUG_ON(!irqs_disabled());
 
 	while (!hwgroup->busy) {
 		hwgroup->busy = 1;
diff -urN linux-2.5.65-bk2/drivers/ide/ide-iops.c linux-2.5.65-bk3/drivers/ide/ide-iops.c
--- linux-2.5.65-bk2/drivers/ide/ide-iops.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-iops.c	Mon Mar 31 12:41:40 2003
@@ -1,13 +1,12 @@
 /*
- * linux/drivers/ide/ide-iops.c	Version 0.33	April 11, 2002
+ * linux/drivers/ide/ide-iops.c	Version 0.37	Mar 05, 2003
  *
  *  Copyright (C) 2000-2002	Andre Hedrick <andre@linux-ide.org>
- *
+ *  Copyright (C) 2003		Red Hat <alan@redhat.com>
  *
  */
 
 #include <linux/config.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -63,6 +62,10 @@
 {
 }
 
+static void ide_unplugged_outbsync (ide_drive_t *drive, u8 addr, unsigned long port)
+{
+}
+
 static void ide_unplugged_outw (u16 val, unsigned long port)
 {
 }
@@ -82,7 +85,7 @@
 void unplugged_hwif_iops (ide_hwif_t *hwif)
 {
 	hwif->OUTB	= ide_unplugged_outb;
-	hwif->OUTBSYNC	= ide_unplugged_outb;
+	hwif->OUTBSYNC	= ide_unplugged_outbsync;
 	hwif->OUTW	= ide_unplugged_outw;
 	hwif->OUTL	= ide_unplugged_outl;
 	hwif->OUTSW	= ide_unplugged_outsw;
@@ -130,6 +133,11 @@
 	outb(val, port);
 }
 
+static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port)
+{
+	outb(addr, port);
+}
+
 static void ide_outw (u16 val, unsigned long port)
 {
 	outw(val, port);
@@ -153,7 +161,7 @@
 void default_hwif_iops (ide_hwif_t *hwif)
 {
 	hwif->OUTB	= ide_outb;
-	hwif->OUTBSYNC	= ide_outb;
+	hwif->OUTBSYNC	= ide_outbsync;
 	hwif->OUTW	= ide_outw;
 	hwif->OUTL	= ide_outl;
 	hwif->OUTSW	= ide_outsw;
@@ -201,6 +209,11 @@
 	writeb(value, port);
 }
 
+static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port)
+{
+	writeb(value, port);	
+}
+
 static void ide_mm_outw (u16 value, unsigned long port)
 {
 	writew(value, port);
@@ -226,7 +239,7 @@
 	hwif->OUTB	= ide_mm_outb;
 	/* Most systems will need to override OUTBSYNC, alas however
 	   this one is controller specific! */
-	hwif->OUTBSYNC	= ide_mm_outb;
+	hwif->OUTBSYNC	= ide_mm_outbsync;
 	hwif->OUTW	= ide_mm_outw;
 	hwif->OUTL	= ide_mm_outl;
 	hwif->OUTSW	= ide_mm_outsw;
@@ -986,13 +999,11 @@
  *
  * See also ide_execute_command
  */
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
+void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
 		      unsigned int timeout, ide_expiry_t *expiry)
 {
-	unsigned long flags;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 
-	spin_lock_irqsave(&ide_lock, flags);
 	if (hwgroup->handler != NULL) {
 		printk(KERN_CRIT "%s: ide_set_handler: handler not null; "
 			"old=%p, new=%p\n",
@@ -1002,11 +1013,21 @@
 	hwgroup->expiry		= expiry;
 	hwgroup->timer.expires	= jiffies + timeout;
 	add_timer(&hwgroup->timer);
+}
+
+EXPORT_SYMBOL(__ide_set_handler);
+
+void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
+		      unsigned int timeout, ide_expiry_t *expiry)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&ide_lock, flags);
+	__ide_set_handler(drive, handler, timeout, expiry);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
 EXPORT_SYMBOL(ide_set_handler);
-
+ 
 /**
  *	ide_execute_command	-	execute an IDE command
  *	@drive: IDE drive to issue the command against
@@ -1035,7 +1056,7 @@
 	hwgroup->expiry		= expiry;
 	hwgroup->timer.expires	= jiffies + timeout;
 	add_timer(&hwgroup->timer);
-	hwif->OUTBSYNC(cmd, IDE_COMMAND_REG);
+	hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);
 	/* Drive takes 400nS to respond, we must avoid the IRQ being
 	   serviced before that. 
 	   
@@ -1050,7 +1071,7 @@
 
 
 /* needed below */
-ide_startstop_t do_reset1 (ide_drive_t *, int);
+static ide_startstop_t do_reset1 (ide_drive_t *, int);
 
 /*
  * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
@@ -1167,8 +1188,7 @@
 
 void pre_reset (ide_drive_t *drive)
 {
-	if (drive->driver != NULL)
-		DRIVER(drive)->pre_reset(drive);
+	DRIVER(drive)->pre_reset(drive);
 
 	if (!drive->keep_settings) {
 		if (drive->using_dma) {
@@ -1202,14 +1222,20 @@
  * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it,
  * we set a timer to poll at 50ms intervals.
  */
-ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
 {
 	unsigned int unit;
 	unsigned long flags;
-	ide_hwif_t *hwif = HWIF(drive);
-	ide_hwgroup_t *hwgroup = HWGROUP(drive);
+	ide_hwif_t *hwif;
+	ide_hwgroup_t *hwgroup;
+	
+	spin_lock_irqsave(&ide_lock, flags);
+	hwif = HWIF(drive);
+	hwgroup = HWGROUP(drive);
 
-	local_irq_save(flags);
+	/* We must not reset with running handlers */
+	if(hwgroup->handler != NULL)
+		BUG();
 
 	/* For an ATAPI device, first try an ATAPI SRST. */
 	if (drive->media != ide_disk && !do_not_try_atapi) {
@@ -1218,10 +1244,8 @@
 		udelay (20);
 		hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-		if (HWGROUP(drive)->handler != NULL)
-			BUG();
-		ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
-		local_irq_restore(flags);
+		__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
+		spin_unlock_irqrestore(&ide_lock, flags);
 		return ide_started;
 	}
 
@@ -1234,20 +1258,10 @@
 
 #if OK_TO_RESET_CONTROLLER
 	if (!IDE_CONTROL_REG) {
-		local_irq_restore(flags);
+		spin_unlock_irqrestore(&ide_lock, flags);
 		return ide_stopped;
 	}
 
-# if 0
-        {
-		u8 control = hwif->INB(IDE_CONTROL_REG);
-		control |= 0x04;
-		hwif->OUTB(control,IDE_CONTROL_REG);
-		udelay(30);
-		control &= 0xFB;
-		hwif->OUTB(control, IDE_CONTROL_REG);
-	}
-# else
 	/*
 	 * Note that we also set nIEN while resetting the device,
 	 * to mask unwanted interrupts from the interface during the reset.
@@ -1257,23 +1271,21 @@
 	 * recover from reset very quickly, saving us the first 50ms wait time.
 	 */
 	/* set SRST and nIEN */
-	hwif->OUTB(drive->ctl|6,IDE_CONTROL_REG);
+	hwif->OUTBSYNC(drive, drive->ctl|6,IDE_CONTROL_REG);
 	/* more than enough time */
 	udelay(10);
 	if (drive->quirk_list == 2) {
 		/* clear SRST and nIEN */
-		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+		hwif->OUTBSYNC(drive, drive->ctl, IDE_CONTROL_REG);
 	} else {
 		/* clear SRST, leave nIEN */
-		hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);
+		hwif->OUTBSYNC(drive, drive->ctl|2, IDE_CONTROL_REG);
 	}
 	/* more than enough time */
 	udelay(10);
 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-	ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
-# endif
+	__ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
+
 	/*
 	 * Some weird controller like resetting themselves to a strange
 	 * state when the disks are reset this way. At least, the Winbond
@@ -1281,71 +1293,22 @@
 	 */
 	if (hwif->resetproc != NULL) {
 		hwif->resetproc(drive);
-
-# if 0
-		if (drive->failures) {
-			local_irq_restore(flags);
-			return ide_stopped;
-		}
-# endif
 	}
-
+	
 #endif	/* OK_TO_RESET_CONTROLLER */
 
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&ide_lock, flags);
 	return ide_started;
 }
 
-#if 0
 /*
  * ide_do_reset() is the entry point to the drive/interface reset code.
  */
+
 ide_startstop_t ide_do_reset (ide_drive_t *drive)
 {
 	return do_reset1(drive, 0);
 }
-#else
-/*
- * ide_do_reset() is the entry point to the drive/interface reset code.
- */
-ide_startstop_t ide_do_reset (ide_drive_t *drive)
-{
-	ide_startstop_t start_stop = ide_started;
-# if 0
-        u8 tmp_dma	= drive->using_dma;
-        u8 cspeed	= drive->current_speed;
-	u8 unmask	= drive->unmask;
-# endif
-
-	if (HWGROUP(drive)->handler != NULL) {
-		unsigned long flags;
-		spin_lock_irqsave(&ide_lock, flags);
-		HWGROUP(drive)->handler = NULL;
-		del_timer(&HWGROUP(drive)->timer);
-		spin_unlock_irqrestore(&ide_lock, flags);
-	}
-
-	start_stop = do_reset1(drive, 0);
-# if 0
-	/*
-	 * check for suspend-spindown flag,
-	 * to attempt a restart or spinup of device.
-	 */
-	if (drive->suspend_reset) {
-		/*
-		 * APM WAKE UP todo !!
-		 * int nogoodpower = 1;
-		 * while(nogoodpower) {
-		 * 	check_power1() or check_power2()
-		 * 	nogoodpower = 0;
-		 * }
-		 * HWIF(drive)->multiproc(drive);
-		 */
-# endif
-
-	return start_stop;
-}
-#endif
 
 EXPORT_SYMBOL(ide_do_reset);
 
diff -urN linux-2.5.65-bk2/drivers/ide/ide-lib.c linux-2.5.65-bk3/drivers/ide/ide-lib.c
--- linux-2.5.65-bk2/drivers/ide/ide-lib.c	Mon Mar 17 13:44:46 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-lib.c	Mon Mar 31 12:41:40 2003
@@ -1,5 +1,4 @@
 #include <linux/config.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
diff -urN linux-2.5.65-bk2/drivers/ide/ide-probe.c linux-2.5.65-bk3/drivers/ide/ide-probe.c
--- linux-2.5.65-bk2/drivers/ide/ide-probe.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-probe.c	Mon Mar 31 12:41:40 2003
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/ide-probe.c	Version 1.10	Feb 11, 2003
+ *  linux/drivers/ide/ide-probe.c	Version 1.11	Mar 05, 2003
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -65,23 +65,14 @@
  *	and make drive properties unconditional outside of this file
  */
  
-static int generic_id(ide_drive_t *drive)
+static void generic_id(ide_drive_t *drive)
 {
-	drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL);
-	if(drive->id == NULL)
-	{
-		printk(KERN_ERR "ide: out of memory for id data.\n");
-		return -ENOMEM;
-	}
-	memset(drive->id, 0, SECTOR_WORDS * 4);
 	drive->id->cyls = drive->cyl;
 	drive->id->heads = drive->head;
 	drive->id->sectors = drive->sect;
 	drive->id->cur_cyls = drive->cyl;
 	drive->id->cur_heads = drive->head;
 	drive->id->cur_sectors = drive->sect;
-	strcpy(drive->id->model, "UNKNOWN");
-	return 0;
 }
 		
 /**
@@ -107,7 +98,7 @@
 {
 	struct hd_driveid *id = drive->id;
 
-	if (drive->removable && id != NULL) {
+	if (drive->removable) {
 		if (id->config == 0x848a) return 1;	/* CompactFlash */
 		if (!strncmp(id->model, "KODAK ATA_FLASH", 15)	/* Kodak */
 		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */
@@ -138,16 +129,11 @@
 	int bswap = 1;
 	struct hd_driveid *id;
 
-	/* called with interrupts disabled! */
-	id = drive->id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
-	if (!id) {
-		printk(KERN_WARNING "(ide-probe::do_identify) "
-			"Out of memory.\n");
-		goto err_kmalloc;
-	}
+	id = drive->id;
 	/* read 512 bytes of id info */
 	hwif->ata_input_data(drive, id, SECTOR_WORDS);
 
+	drive->id_read = 1;
 	local_irq_enable();
 	ide_fix_driveid(id);
 
@@ -290,7 +276,6 @@
 
 err_misc:
 	kfree(id);
-err_kmalloc:
 	drive->present = 0;
 	return;
 }
@@ -592,6 +577,25 @@
  
 static inline u8 probe_for_drive (ide_drive_t *drive)
 {
+	/*
+	 *	In order to keep things simple we have an id
+	 *	block for all drives at all times. If the device
+	 *	is pre ATA or refuses ATA/ATAPI identify we
+	 *	will add faked data to this.
+	 *
+	 *	Also note that 0 everywhere means "can't do X"
+	 */
+ 
+	drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL);
+	drive->id_read = 0;
+	if(drive->id == NULL)
+	{
+		printk(KERN_ERR "ide: out of memory for id data.\n");
+		return 0;
+	}
+	memset(drive->id, 0, SECTOR_WORDS * 4);
+	strcpy(drive->id->model, "UNKNOWN");
+	
 	/* skip probing? */
 	if (!drive->noprobe)
 	{
@@ -600,14 +604,14 @@
 			/* look for ATAPI device */
 			(void) do_probe(drive, WIN_PIDENTIFY);
 		}
-		if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T"))
+		if (strstr(drive->id->model, "E X A B Y T E N E S T"))
 			enable_nest(drive);
 		if (!drive->present)
 			/* drive not found */
 			return 0;
 	
 		/* identification failed? */
-		if (drive->id == NULL) {
+		if (!drive->id_read) {
 			if (drive->media == ide_disk) {
 				printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n",
 					drive->name, drive->cyl,
@@ -616,6 +620,7 @@
 				printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name);
 			} else {
 				/* nuke it */
+				printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
 				drive->present = 0;
 			}
 		}
@@ -623,9 +628,9 @@
 	}
 	if(!drive->present)
 		return 0;
-	if(drive->id == NULL)
-		if(generic_id(drive) < 0)
-			drive->present = 0;
+	/* The drive wasn't being helpful. Add generic info only */
+	if(!drive->id_read)
+		generic_id(drive);
 	return drive->present;
 }
 
@@ -945,6 +950,9 @@
 		u16 unit = 0;
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
 			ide_drive_t *drive = &hwif->drives[unit];
+			/* For now don't attach absent drives, we may
+			   want them on default or a new "empty" class
+			   for hotplug reprobing ? */
 			if (drive->present) {
 				ata_attach(drive);
 			}
@@ -990,18 +998,23 @@
 static void ide_init_queue(ide_drive_t *drive)
 {
 	request_queue_t *q = &drive->queue;
-	int max_sectors;
+	int max_sectors = 256;
 
+	/*
+	 *	Our default set up assumes the normal IDE case,
+	 *	that is 64K segmenting, standard PRD setup
+	 *	and LBA28. Some drivers then impose their own
+	 *	limits and LBA48 we could raise it but as yet
+	 *	do not.
+	 */
+	 
 	q->queuedata = HWGROUP(drive);
 	blk_init_queue(q, do_ide_request, &ide_lock);
 	drive->queue_setup = 1;
 	blk_queue_segment_boundary(q, 0xffff);
 
-#ifdef CONFIG_BLK_DEV_PDC4030
-	max_sectors = 127;
-#else
-	max_sectors = 255;
-#endif
+	if (HWIF(drive)->rqsize)
+		max_sectors = HWIF(drive)->rqsize;
 	blk_queue_max_sectors(q, max_sectors);
 
 	/* IDE DMA can do PRD_ENTRIES number of segments. */
@@ -1009,7 +1022,13 @@
 
 	/* This is a driver limit and could be eliminated. */
 	blk_queue_max_phys_segments(q, PRD_ENTRIES);
+}
 
+/*
+ * Setup the drive for request handling.
+ */
+static void ide_init_drive(ide_drive_t *drive)
+{
 	ide_toggle_bounce(drive, 1);
 
 #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
@@ -1032,16 +1051,14 @@
  */
 static int init_irq (ide_hwif_t *hwif)
 {
-	unsigned long flags;
 	unsigned int index;
-	ide_hwgroup_t *hwgroup, *new_hwgroup;
+	ide_hwgroup_t *hwgroup;
 	ide_hwif_t *match = NULL;
 
-	/* Allocate the buffer and potentially sleep first */
-	new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
-	
-	spin_lock_irqsave(&ide_lock, flags);
 
+	BUG_ON(in_interrupt());
+	BUG_ON(irqs_disabled());	
+	down(&ide_cfg_sem);
 	hwif->hwgroup = NULL;
 #if MAX_HWIFS > 1
 	/*
@@ -1073,14 +1090,28 @@
 	 */
 	if (match) {
 		hwgroup = match->hwgroup;
-		if(new_hwgroup)
-			kfree(new_hwgroup);
+		hwif->hwgroup = hwgroup;
+		/*
+		 * Link us into the hwgroup.
+		 * This must be done early, do ensure that unexpected_intr
+		 * can find the hwif and prevent irq storms.
+		 * No drives are attached to the new hwif, choose_drive
+		 * can't do anything stupid (yet).
+		 * Add ourself as the 2nd entry to the hwgroup->hwif
+		 * linked list, the first entry is the hwif that owns
+		 * hwgroup->handler - do not change that.
+		 */
+		spin_lock_irq(&ide_lock);
+		hwif->next = hwgroup->hwif->next;
+		hwgroup->hwif->next = hwif;
+		spin_unlock_irq(&ide_lock);
 	} else {
-		hwgroup = new_hwgroup;
-		if (!hwgroup) {
-			spin_unlock_irqrestore(&ide_lock, flags);
-			return 1;
-		}
+		hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
+		if (!hwgroup)
+	       		goto out_up;
+
+		hwif->hwgroup = hwgroup;
+
 		memset(hwgroup, 0, sizeof(ide_hwgroup_t));
 		hwgroup->hwif     = hwif->next = hwif;
 		hwgroup->rq       = NULL;
@@ -1112,44 +1143,35 @@
 			/* clear nIEN */
 			hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]);
 
-		if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) {
-			if (!match)
-				kfree(hwgroup);
-			spin_unlock_irqrestore(&ide_lock, flags);
-			return 1;
-		}
+		if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
+	       		goto out_unlink;
 	}
 
 	/*
-	 * Everything is okay, so link us into the hwgroup
+	 * Link any new drives into the hwgroup, allocate
+	 * the block device queue and initialize the drive.
+	 * Note that ide_init_drive sends commands to the new
+	 * drive.
 	 */
-	hwif->hwgroup = hwgroup;
-	hwif->next = hwgroup->hwif->next;
-	hwgroup->hwif->next = hwif;
-
 	for (index = 0; index < MAX_DRIVES; ++index) {
 		ide_drive_t *drive = &hwif->drives[index];
 		if (!drive->present)
 			continue;
-		if (!hwgroup->drive)
-			hwgroup->drive = drive;
-		drive->next = hwgroup->drive->next;
-		hwgroup->drive->next = drive;
-		spin_unlock_irqrestore(&ide_lock, flags);
 		ide_init_queue(drive);
-		spin_lock_irqsave(&ide_lock, flags);
-	}
-
-	if (!hwgroup->hwif) {
-		hwgroup->hwif = HWIF(hwgroup->drive);
-#ifdef DEBUG
-		printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
-#endif
+		spin_lock_irq(&ide_lock);
+		if (!hwgroup->drive) {
+			/* first drive for hwgroup. */
+			drive->next = drive;
+			hwgroup->drive = drive;
+			hwgroup->hwif = HWIF(hwgroup->drive);
+		} else {
+			drive->next = hwgroup->drive->next;
+			hwgroup->drive->next = drive;
+		}
+		spin_unlock_irq(&ide_lock);
+		ide_init_drive(drive);
 	}
 
-	/* all CPUs; safe now that hwif->hwgroup is set up */
-	spin_unlock_irqrestore(&ide_lock, flags);
-
 #if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
 	printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
 		hwif->io_ports[IDE_DATA_OFFSET],
@@ -1168,6 +1190,30 @@
 		printk(" (%sed with %s)",
 			hwif->sharing_irq ? "shar" : "serializ", match->name);
 	printk("\n");
+	up(&ide_cfg_sem);
+	return 0;
+out_unlink:
+	spin_lock_irq(&ide_lock);
+	if (hwif->next == hwif) {
+		BUG_ON(match);
+		BUG_ON(hwgroup->hwif != hwif);
+		kfree(hwgroup);
+	} else {
+		ide_hwif_t *g;
+		g = hwgroup->hwif;
+		while (g->next != hwif)
+			g = g->next;
+		g->next = hwif->next;
+		if (hwgroup->hwif == hwif) {
+			/* Impossible. */
+			printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n");
+			hwgroup->hwif = g;
+		}
+		BUG_ON(hwgroup->hwif == hwif);
+	}
+	spin_unlock_irq(&ide_lock);
+out_up:
+	up(&ide_cfg_sem);
 	return 0;
 }
 
@@ -1340,6 +1386,7 @@
 void export_ide_init_queue (ide_drive_t *drive)
 {
 	ide_init_queue(drive);
+	ide_init_drive(drive);
 }
 
 EXPORT_SYMBOL(export_ide_init_queue);
@@ -1384,7 +1431,8 @@
 			if (!hwif->present)
 				continue;
 			for (unit = 0; unit < MAX_DRIVES; ++unit)
-				ata_attach(&hwif->drives[unit]);
+				if (hwif->drives[unit].present)
+					ata_attach(&hwif->drives[unit]);
 		}
 	}
 	if (!ide_probe)
diff -urN linux-2.5.65-bk2/drivers/ide/ide-proc.c linux-2.5.65-bk3/drivers/ide/ide-proc.c
--- linux-2.5.65-bk2/drivers/ide/ide-proc.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-proc.c	Mon Mar 31 12:41:40 2003
@@ -1,7 +1,8 @@
 /*
- *  linux/drivers/ide/ide-proc.c	Version 1.03	January  2, 1998
+ *  linux/drivers/ide/ide-proc.c	Version 1.05	Mar 05, 2003
  *
  *  Copyright (C) 1997-1998	Mark Lord
+ *  Copyright (C) 2003		Red Hat <alan@redhat.com>
  */
 
 /*
@@ -57,7 +58,6 @@
  */
 
 #include <linux/config.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <asm/uaccess.h>
@@ -365,6 +365,7 @@
 		case ide_cy82c693:	name = "cy82c693";	break;
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
+		case ide_pc9800:	name = "pc9800";	break;
 		default:		name = "(unknown)";	break;
 	}
 	len = sprintf(page, "%s\n", name);
@@ -568,14 +569,10 @@
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
 	ide_drive_t	*drive = (ide_drive_t *) data;
-	ide_driver_t    *driver = (ide_driver_t *) drive->driver;
 	int		len;
 
-	if (!driver)
-		len = sprintf(page, "(none)\n");
-        else
-		len = sprintf(page,"%llu\n",
-			      (long long) ((ide_driver_t *)drive->driver)->capacity(drive));
+	len = sprintf(page,"%llu\n",
+		      (long long) (DRIVER(drive)->capacity(drive)));
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
@@ -620,10 +617,7 @@
 	ide_driver_t	*driver = drive->driver;
 	int		len;
 
-	if (!driver)
-		len = sprintf(page, "(none)\n");
-	else
-		len = sprintf(page, "%s version %s\n",
+	len = sprintf(page, "%s version %s\n",
 			driver->name, driver->version);
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
@@ -775,8 +769,7 @@
 	ide_driver_t *driver = drive->driver;
 
 	if (drive->proc) {
-		if (driver)
-			ide_remove_proc_entries(drive->proc, driver->proc);
+		ide_remove_proc_entries(drive->proc, driver->proc);
 		ide_remove_proc_entries(drive->proc, generic_drive_entries);
 		remove_proc_entry(drive->name, proc_ide_root);
 		remove_proc_entry(drive->name, hwif->proc);
diff -urN linux-2.5.65-bk2/drivers/ide/ide-tape.c linux-2.5.65-bk3/drivers/ide/ide-tape.c
--- linux-2.5.65-bk2/drivers/ide/ide-tape.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-tape.c	Mon Mar 31 12:41:40 2003
@@ -422,7 +422,7 @@
  *		sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
  */
 
-#define IDETAPE_VERSION "1.17b"
+#define IDETAPE_VERSION "1.17b-ac1"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -2128,8 +2128,6 @@
 			if (temp > pc->buffer_size) {
 				printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
 				idetape_discard_data(drive, bcount.all);
-				if (HWGROUP(drive)->handler != NULL)	/* paranoia check */
-					BUG();
 				ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
 				return ide_started;
 			}
@@ -2156,8 +2154,6 @@
 	if (tape->debug_level >= 2)
 		printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
 #endif
-	if (HWGROUP(drive)->handler != NULL)	/* paranoia check */
-		BUG();
 	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);	/* And set the interrupt handler again */
 	return ide_started;
 }
@@ -2235,8 +2231,6 @@
 		return ide_do_reset(drive);
 	}
 	tape->cmd_start_time = jiffies;
-	if (HWGROUP(drive)->handler != NULL)	/* paranoia check */
-		BUG();
 	/* Set the interrupt routine */
 	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -2325,8 +2319,6 @@
 	if (dma_ok)			/* Will begin DMA later */
 		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
 	if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
-		if (HWGROUP(drive)->handler != NULL)	/* paranoia check */
-			BUG();
 		ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
 		OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
@@ -5605,15 +5597,16 @@
  *
  *	0 	If this tape driver is not currently supported by us.
  */
-static int idetape_identify_device (ide_drive_t *drive,struct hd_driveid *id)
+static int idetape_identify_device (ide_drive_t *drive)
 {
 	struct idetape_id_gcw gcw;
+	struct hd_driveid *id = drive->id;
 #if IDETAPE_DEBUG_INFO
 	unsigned short mask,i;
 #endif /* IDETAPE_DEBUG_INFO */
 
-	if (!id)
-		return 0;
+	if (drive->id_read == 0)
+		return 1;
 
 	*((unsigned short *) &gcw) = id->config;
 
@@ -6287,7 +6280,7 @@
 		goto failed;
 	if (drive->media != ide_tape)
 		goto failed;
-	if (!idetape_identify_device (drive, drive->id)) {
+	if (!idetape_identify_device (drive)) {
 		printk(KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name);
 		goto failed;
 	}
diff -urN linux-2.5.65-bk2/drivers/ide/ide-taskfile.c linux-2.5.65-bk3/drivers/ide/ide-taskfile.c
--- linux-2.5.65-bk2/drivers/ide/ide-taskfile.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/drivers/ide/ide-taskfile.c	Mon Mar 31 12:41:40 2003
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/ide-taskfile.c	Version 0.33	April 11, 2002
+ * linux/drivers/ide/ide-taskfile.c	Version 0.38	March 05, 2003
  *
  *  Copyright (C) 2000-2002	Michael Cornwell <cornwell@acm.org>
  *  Copyright (C) 2000-2002	Andre Hedrick <andre@linux-ide.org>
@@ -27,7 +27,6 @@
  */
 
 #include <linux/config.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -642,7 +641,7 @@
 				 * NOTE: could rewind beyond beginning :-/
 				 */
 			} else {
-				printk("%s: MULTI-READ assume all data " \
+				printk(KERN_ERR "%s: MULTI-READ assume all data " \
 					"transfered is bad status=0x%02x\n",
 					drive->name, stat);
 			}
@@ -810,11 +809,6 @@
 	rq->errors = 0;
 	return ide_started;
 #else /* ! ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
-
-#if 0
-	if (wait_for_ready(drive, 100))
-		IDE_DEBUG(__LINE__);		//BUG();
-#else
 	if (!(drive_is_ready(drive))) {
 		int i;
 		for (i=0; i<100; i++) {
@@ -822,7 +816,7 @@
 				break;
 		}
 	}
-#endif
+
 	/*
 	 * WARNING :: if the drive as not acked good status we may not
 	 * move the DATA-TRANSFER T-Bar as BSY != 0. <andre@linux-ide.org>
@@ -864,7 +858,7 @@
 				 * NOTE: could rewind beyond beginning :-/
 				 */
 			} else {
-				printk("%s: MULTI-WRITE assume all data " \
+				printk(KERN_ERR "%s: MULTI-WRITE assume all data " \
 					"transfered is bad status=0x%02x\n",
 					drive->name, stat);
 			}
@@ -1497,7 +1491,7 @@
 		case TASKFILE_MULTI_OUT:
 			if (!drive->mult_count) {
 				/* (hs): give up if multcount is not set */
-				printk("%s: %s Multimode Write " \
+				printk(KERN_ERR "%s: %s Multimode Write " \
 					"multcount is not set\n",
 					drive->name, __FUNCTION__);
 				err = -EPERM;
@@ -1525,7 +1519,7 @@
 		case TASKFILE_MULTI_IN:
 			if (!drive->mult_count) {
 				/* (hs): give up if multcount is not set */
-				printk("%s: %s Multimode Read failure " \
+				printk(KERN_ERR "%s: %s Multimode Read failure " \
 					"multcount is not set\n",
 					drive->name, __FUNCTION__);
 				err = -EPERM;
diff -urN linux-2.5.65-bk2/drivers/ide/ide.c linux-2.5.65-bk3/drivers/ide/ide.c
--- linux-2.5.65-bk2/drivers/ide/ide.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/ide/ide.c	Mon Mar 31 12:41:40 2003
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/ide.c		Version 7.00alpha1	August 19 2002
+ *  linux/drivers/ide/ide.c		Version 7.00beta2	Mar 05 2003
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -177,6 +177,7 @@
 static int system_bus_speed;	/* holds what we think is VESA/PCI bus speed */
 static int initializing;	/* set while initializing built-in drivers */
 
+DECLARE_MUTEX(ide_cfg_sem);
 spinlock_t ide_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
@@ -214,6 +215,8 @@
 EXPORT_SYMBOL(idetape);
 EXPORT_SYMBOL(idescsi);
 
+extern ide_driver_t idedefault_driver;
+static void setup_driver_defaults (ide_drive_t *drive);
 
 /*
  * Do not even *think* about calling this!
@@ -271,6 +274,8 @@
 		drive->max_failures		= IDE_DEFAULT_MAX_FAILURES;
 		drive->using_dma		= 0;
 		drive->is_flash			= 0;
+		drive->driver			= &idedefault_driver;
+		setup_driver_defaults(drive);
 		drive->vdma			= 0;
 		INIT_LIST_HEAD(&drive->list);
 	}
@@ -349,9 +354,7 @@
 {
 	if (!drive->present)
 		return 0;
-	if (drive->driver != NULL)
-		return DRIVER(drive)->capacity(drive);
-	return 0;
+	return DRIVER(drive)->capacity(drive);
 }
 
 EXPORT_SYMBOL(current_capacity);
@@ -580,17 +583,19 @@
  
 void ide_unregister (unsigned int index)
 {
-	ide_drive_t *drive, *d;
+	ide_drive_t *drive;
 	ide_hwif_t *hwif, *g;
 	ide_hwgroup_t *hwgroup;
 	int irq_count = 0, unit, i;
-	unsigned long flags;
 	ide_hwif_t old_hwif;
 
 	if (index >= MAX_HWIFS)
 		BUG();
 		
-	spin_lock_irqsave(&ide_lock, flags);
+	BUG_ON(in_interrupt());
+	BUG_ON(irqs_disabled());
+	down(&ide_cfg_sem);
+	spin_lock_irq(&ide_lock);
 	hwif = &ide_hwifs[index];
 	if (!hwif->present)
 		goto abort;
@@ -600,25 +605,23 @@
 			continue;
 		if (drive->usage)
 			goto abort;
-		if (drive->driver != NULL && DRIVER(drive)->shutdown(drive))
+		if (DRIVER(drive)->shutdown(drive))
 			goto abort;
 	}
 	hwif->present = 0;
 	
-	spin_unlock_irqrestore(&ide_lock, flags);
+	spin_unlock_irq(&ide_lock);
 
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		drive = &hwif->drives[unit];
 		if (!drive->present)
 			continue;
-		if (drive->driver != NULL)
-			DRIVER(drive)->cleanup(drive);
+		DRIVER(drive)->cleanup(drive);
 	}
 	
 #ifdef CONFIG_PROC_FS
 	destroy_proc_ide_drives(hwif);
 #endif
-	spin_lock_irqsave(&ide_lock, flags);
 	hwgroup = hwif->hwgroup;
 
 	/*
@@ -633,6 +636,7 @@
 	if (irq_count == 1)
 		free_irq(hwif->irq, hwgroup);
 
+	spin_lock_irq(&ide_lock);
 	/*
 	 * Note that we only release the standard ports,
 	 * and do not even try to handle any extra ports
@@ -644,7 +648,6 @@
 	 * Remove us from the hwgroup, and free
 	 * the hwgroup if we were the only member
 	 */
-	d = hwgroup->drive;
 	for (i = 0; i < MAX_DRIVES; ++i) {
 		drive = &hwif->drives[i];
 		if (drive->de) {
@@ -653,11 +656,23 @@
 		}
 		if (!drive->present)
 			continue;
-		while (hwgroup->drive->next != drive)
-			hwgroup->drive = hwgroup->drive->next;
-		hwgroup->drive->next = drive->next;
-		if (hwgroup->drive == drive)
+		if (drive == drive->next) {
+			/* special case: last drive from hwgroup. */
+			BUG_ON(hwgroup->drive != drive);
 			hwgroup->drive = NULL;
+		} else {
+			ide_drive_t *walk;
+
+			walk = hwgroup->drive;
+			while (walk->next != drive)
+				walk = walk->next;
+			walk->next = drive->next;
+			if (hwgroup->drive == drive) {
+				hwgroup->drive = drive->next;
+				hwgroup->hwif = HWIF(hwgroup->drive);
+			}
+		}
+		BUG_ON(hwgroup->drive == drive);
 		if (drive->id != NULL) {
 			kfree(drive->id);
 			drive->id = NULL;
@@ -665,15 +680,28 @@
 		drive->present = 0;
 		blk_cleanup_queue(&drive->queue);
 	}
-	if (d->present)
-		hwgroup->drive = d;
-	while (hwgroup->hwif->next != hwif)
-		hwgroup->hwif = hwgroup->hwif->next;
-	hwgroup->hwif->next = hwif->next;
-	if (hwgroup->hwif == hwif)
+	if (hwif->next == hwif) {
 		kfree(hwgroup);
-	else
-		hwgroup->hwif = HWIF(hwgroup->drive);
+		BUG_ON(hwgroup->hwif != hwif);
+	} else {
+		/* There is another interface in hwgroup.
+		 * Unlink us, and set hwgroup->drive and ->hwif to
+		 * something sane.
+		 */
+		g = hwgroup->hwif;
+		while (g->next != hwif)
+			g = g->next;
+		g->next = hwif->next;
+		if (hwgroup->hwif == hwif) {
+			/* Chose a random hwif for hwgroup->hwif.
+			 * It's guaranteed that there are no drives
+			 * left in the hwgroup.
+			 */
+			BUG_ON(hwgroup->drive != NULL);
+			hwgroup->hwif = g;
+		}
+		BUG_ON(hwgroup->hwif == hwif);
+	}
 
 #if !defined(CONFIG_DMA_NONPCI)
 	if (hwif->dma_base) {
@@ -813,7 +841,8 @@
 
 	hwif->hwif_data			= old_hwif.hwif_data;
 abort:
-	spin_unlock_irqrestore(&ide_lock, flags);
+	spin_unlock_irq(&ide_lock);
+	up(&ide_cfg_sem);
 }
 
 EXPORT_SYMBOL(ide_unregister);
@@ -998,7 +1027,7 @@
 	setting->set = set;
 	
 	setting->next = *p;
-	if (drive->driver)
+	if (drive->driver != &idedefault_driver)
 		setting->auto_remove = 1;
 	*p = setting;
 	up(&ide_setting_sem);
@@ -1255,13 +1284,14 @@
 
 static int set_using_dma (ide_drive_t *drive, int arg)
 {
-	if (!drive->driver || !DRIVER(drive)->supports_dma)
+	if (!DRIVER(drive)->supports_dma)
 		return -EPERM;
 	if (!drive->id || !(drive->id->capability & 1))
 		return -EPERM;
 	if (HWIF(drive)->ide_dma_check == NULL)
 		return -EPERM;
 	if (arg) {
+		if (HWIF(drive)->ide_dma_check(drive)) return -EIO;
 		if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
 	} else {
 		if (HWIF(drive)->ide_dma_off(drive)) return -EIO;
@@ -1304,15 +1334,9 @@
 		return 0;
 	}
 
-	if (drive->driver != NULL) {
-#if 0
-		ide_unregister_subdriver(drive);
-#else
-		if (DRIVER(drive)->cleanup(drive)) {
-			drive->scsi = 0;
-			return 0;
-		}
-#endif
+	if (DRIVER(drive)->cleanup(drive)) {
+		drive->scsi = 0;
+		return 0;
 	}
 
 	drive->scsi = (u8) arg;
@@ -1353,7 +1377,7 @@
 	mdelay(50);
 #else
 	__set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/20);
+	schedule_timeout(1+HZ/20);
 #endif /* CONFIG_BLK_DEV_IDECS */
 }
 
@@ -1375,7 +1399,7 @@
 {
 	if (!drive->present || drive->usage || drive->dead)
 		goto abort;
-	if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
+	if (DRIVER(drive)->cleanup(drive))
 		goto abort;
 	strncpy(drive->driver_req, driver, 9);
 	if (ata_attach(drive)) {
@@ -1387,7 +1411,7 @@
 	} else {
 		drive->driver_req[0] = 0;
 	}
-	if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver))
+	if (DRIVER(drive)!= &idedefault_driver && !strcmp(DRIVER(drive)->name, driver))
 		return 0;
 abort:
 	return 1;
@@ -1412,10 +1436,12 @@
 		spin_lock(&drivers_lock);
 		module_put(driver->owner);
 	}
+	drive->gendev.driver = &idedefault_driver.gen_driver;
 	spin_unlock(&drivers_lock);
+	if(idedefault_driver.attach(drive) != 0)
+		panic("ide: default attach failed");
 	spin_lock(&drives_lock);
 	list_add_tail(&drive->list, &ata_unused);
-	drive->gendev.driver = NULL;
 	spin_unlock(&drives_lock);
 	return 1;
 }
@@ -1476,7 +1502,7 @@
 		case HDIO_GET_IDENTITY:
 			if (bdev != bdev->bd_contains)
 				return -EINVAL;
-			if (drive->id == NULL)
+			if (drive->id_read == 0)
 				return -ENOMSG;
 			if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
 				return -EFAULT;
@@ -1521,7 +1547,7 @@
 		case HDIO_SCAN_HWIF:
 		{
 			int args[3];
-			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+			if (!capable(CAP_SYS_RAWIO)) return -EACCES;
 			if (copy_from_user(args, (void *)arg, 3 * sizeof(int)))
 				return -EFAULT;
 			if (ide_register(args[0], args[1], args[2]) == -1)
@@ -1529,14 +1555,12 @@
 			return 0;
 		}
 	        case HDIO_UNREGISTER_HWIF:
-			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+			if (!capable(CAP_SYS_RAWIO)) return -EACCES;
 			/* (arg > MAX_HWIFS) checked in function */
 			ide_unregister(arg);
 			return 0;
 		case HDIO_SET_NICE:
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-			if (drive->driver == NULL)
-				return -EPERM;
 			if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
 				return -EPERM;
 			drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
@@ -1550,18 +1574,26 @@
 		{
 			unsigned long flags;
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-#if 1
+			
+			/*
+			 *	Abort the current command on the
+			 *	group if there is one, taking
+			 *	care not to allow anything else
+			 *	to be queued and to die on the
+			 *	spot if we miss one somehow
+			 */
+
 			spin_lock_irqsave(&ide_lock, flags);
-			if ( HWGROUP(drive)->handler != NULL) {
-				printk(KERN_ERR "%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler);
-				(void) HWGROUP(drive)->handler(drive);
-//				HWGROUP(drive)->handler = NULL;
-				HWGROUP(drive)->expiry	= NULL;
-				del_timer(&HWGROUP(drive)->timer);
-			}
+			
+			DRIVER(drive)->abort(drive, "drive reset");
+			if(HWGROUP(drive)->handler)
+				BUG();
+				
+			/* Ensure nothing gets queued after we
+			   drop the lock. Reset will clear the busy */
+		   
+			HWGROUP(drive)->busy = 1;
 			spin_unlock_irqrestore(&ide_lock, flags);
-
-#endif
 			(void) ide_do_reset(drive);
 			if (drive->suspend_reset) {
 /*
@@ -1593,9 +1625,8 @@
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
 			if (HWIF(drive)->busproc)
-				HWIF(drive)->busproc(drive, (int)arg);
-			return 0;
-
+				return HWIF(drive)->busproc(drive, (int)arg);
+			return -EOPNOTSUPP;
 		default:
 			return -EINVAL;
 	}
@@ -2193,7 +2224,7 @@
  
 static int default_shutdown(ide_drive_t *drive)
 {
-	if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
+	if (drive->usage || DRIVER(drive)->busy) {
 		return 1;
 	}
 	drive->dead = 1;
@@ -2261,6 +2292,11 @@
 	return 0;
 }
 
+static ide_startstop_t default_abort (ide_drive_t *drive, const char *msg)
+{
+	return ide_abort(drive, msg);
+}
+
 static void setup_driver_defaults (ide_drive_t *drive)
 {
 	ide_driver_t *d = drive->driver;
@@ -2272,6 +2308,7 @@
 	if (d->end_request == NULL)	d->end_request = default_end_request;
 	if (d->sense == NULL)		d->sense = default_sense;
 	if (d->error == NULL)		d->error = default_error;
+	if (d->abort == NULL)		d->abort = default_abort;
 	if (d->pre_reset == NULL)	d->pre_reset = default_pre_reset;
 	if (d->capacity == NULL)	d->capacity = default_capacity;
 	if (d->special == NULL)		d->special = default_special;
@@ -2282,9 +2319,11 @@
 {
 	unsigned long flags;
 	
+	BUG_ON(drive->driver == NULL);
+	
 	spin_lock_irqsave(&ide_lock, flags);
 	if (version != IDE_SUBDRIVER_VERSION || !drive->present ||
-	    drive->driver != NULL || drive->usage || drive->dead) {
+	    drive->driver != &idedefault_driver || drive->usage || drive->dead) {
 		spin_unlock_irqrestore(&ide_lock, flags);
 		return 1;
 	}
@@ -2294,6 +2333,7 @@
 	spin_lock(&drives_lock);
 	list_add(&drive->list, &driver->drives);
 	spin_unlock(&drives_lock);
+//	printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name);
 	if ((drive->autotune == IDE_TUNE_DEFAULT) ||
 		(drive->autotune == IDE_TUNE_AUTO)) {
 		/* DMA timings and setup moved to ide-probe.c */
@@ -2318,7 +2358,7 @@
 	unsigned long flags;
 	
 	spin_lock_irqsave(&ide_lock, flags);
-	if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
+	if (drive->usage || drive->driver == &idedefault_driver || DRIVER(drive)->busy) {
 		spin_unlock_irqrestore(&ide_lock, flags);
 		return 1;
 	}
@@ -2330,10 +2370,12 @@
 	ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
 #endif
 	auto_remove_settings(drive);
-	drive->driver = NULL;
+	drive->driver = &idedefault_driver;
+	setup_driver_defaults(drive);
 	spin_unlock_irqrestore(&ide_lock, flags);
 	spin_lock(&drives_lock);
 	list_del_init(&drive->list);
+	list_add(&drive->list, &drive->driver->drives);
 	spin_unlock(&drives_lock);
 	return 0;
 }
@@ -2343,10 +2385,7 @@
 static int ide_drive_remove(struct device * dev)
 {
 	ide_drive_t * drive = container_of(dev,ide_drive_t,gendev);
-	ide_driver_t * driver = drive->driver;
-
-	if (driver && driver->cleanup)
-		driver->cleanup(drive);
+	DRIVER(drive)->cleanup(drive);
 	return 0;
 }
 
@@ -2366,7 +2405,8 @@
 	while (!list_empty(&list)) {
 		ide_drive_t *drive = list_entry(list.next, ide_drive_t, list);
 		list_del_init(&drive->list);
-		ata_attach(drive);
+		if (drive->present)
+			ata_attach(drive);
 	}
 	driver->gen_driver.name = (char *) driver->name;
 	driver->gen_driver.bus = &ide_bus_type;
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/Makefile linux-2.5.65-bk3/drivers/ide/legacy/Makefile
--- linux-2.5.65-bk2/drivers/ide/legacy/Makefile	Mon Mar 17 13:43:43 2003
+++ linux-2.5.65-bk3/drivers/ide/legacy/Makefile	Mon Mar 31 12:41:40 2003
@@ -2,6 +2,7 @@
 obj-$(CONFIG_BLK_DEV_ALI14XX)		+= ali14xx.o
 obj-$(CONFIG_BLK_DEV_DTC2278)		+= dtc2278.o
 obj-$(CONFIG_BLK_DEV_HT6560B)		+= ht6560b.o
+obj-$(CONFIG_BLK_DEV_IDE_PC9800)	+= pc9800.o
 obj-$(CONFIG_BLK_DEV_PDC4030)		+= pdc4030.o
 obj-$(CONFIG_BLK_DEV_QD65XX)		+= qd65xx.o
 obj-$(CONFIG_BLK_DEV_UMC8672)		+= umc8672.o
@@ -15,6 +16,10 @@
 obj-$(CONFIG_BLK_DEV_IDECS)		+= ide-cs.o
 
 # Last of all
+ifneq ($(CONFIG_X86_PC9800),y)
 obj-$(CONFIG_BLK_DEV_HD)		+= hd.o
+else
+obj-$(CONFIG_BLK_DEV_HD)		+= hd98.o
+endif
 
 EXTRA_CFLAGS	:= -Idrivers/ide
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/ali14xx.c linux-2.5.65-bk3/drivers/ide/legacy/ali14xx.c
--- linux-2.5.65-bk2/drivers/ide/legacy/ali14xx.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/drivers/ide/legacy/ali14xx.c	Mon Mar 31 12:41:40 2003
@@ -229,10 +229,8 @@
 		return 1;
 	}
 
-#ifndef HWIF_PROBE_CLASSIC_METHOD
 	probe_hwif_init(&ide_hwifs[0]);
 	probe_hwif_init(&ide_hwifs[1]);
-#endif /* HWIF_PROBE_CLASSIC_METHOD */
 
 	return 0;
 }
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/dtc2278.c linux-2.5.65-bk3/drivers/ide/legacy/dtc2278.c
--- linux-2.5.65-bk2/drivers/ide/legacy/dtc2278.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/ide/legacy/dtc2278.c	Mon Mar 31 12:41:40 2003
@@ -138,11 +138,8 @@
 	ide_hwifs[1].mate = &ide_hwifs[0];
 	ide_hwifs[1].channel = 1;
 
-#ifndef HWIF_PROBE_CLASSIC_METHOD
 	probe_hwif_init(&ide_hwifs[0]);
 	probe_hwif_init(&ide_hwifs[1]);
-#endif /* HWIF_PROBE_CLASSIC_METHOD */
-
 }
 
 void __init dtc2278_release (void)
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/hd98.c linux-2.5.65-bk3/drivers/ide/legacy/hd98.c
--- linux-2.5.65-bk2/drivers/ide/legacy/hd98.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/drivers/ide/legacy/hd98.c	Mon Mar 31 12:41:40 2003
@@ -0,0 +1,904 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * This is the low-level hd interrupt support. It traverses the
+ * request-list, using interrupts to jump between functions. As
+ * all the functions are called within interrupts, we may not
+ * sleep. Special care is recommended.
+ *
+ *  modified by Drew Eckhardt to check nr of hd's from the CMOS.
+ *
+ *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ *  in the early extended-partition checks and added DM partitions
+ *
+ *  IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
+ *  and general streamlining by Mark Lord.
+ *
+ *  Removed 99% of above. Use Mark's ide driver for those options.
+ *  This is now a lightweight ST-506 driver. (Paul Gortmaker)
+ *
+ *  Modified 1995 Russell King for ARM processor.
+ *
+ *  Bugfix: max_sectors must be <= 255 or the wheels tend to come
+ *  off in a hurry once you queue things up - Paul G. 02/2001
+ */
+
+/* Uncomment the following if you want verbose error reports. */
+/* #define VERBOSE_ERRORS */
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/mc146818rtc.h> /* CMOS defines */
+#include <linux/init.h>
+#include <linux/blkpg.h>
+#include <linux/hdreg.h>
+
+#define REALLY_SLOW_IO
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#define MAJOR_NR HD_MAJOR
+#define DEVICE_NR(device) (minor(device)>>6)
+#include <linux/blk.h>
+
+#include "io_ports.h"
+
+#ifdef __arm__
+#undef  HD_IRQ
+#endif
+#include <asm/irq.h>
+#ifdef __arm__
+#define HD_IRQ IRQ_HARDDISK
+#endif
+
+/* Hd controller regster ports */
+
+#define HD_DATA		0x640	/* _CTL when writing */
+#define HD_ERROR	0x642	/* see err-bits */
+#define HD_NSECTOR	0x644	/* nr of sectors to read/write */
+#define HD_SECTOR	0x646	/* starting sector */
+#define HD_LCYL		0x648	/* starting cylinder */
+#define HD_HCYL		0x64a	/* high byte of starting cyl */
+#define HD_CURRENT	0x64c	/* 101dhhhh , d=drive, hhhh=head */
+#define HD_STATUS	0x64e	/* see status-bits */
+#define HD_FEATURE	HD_ERROR	/* same io address, read=error, write=feature */
+#define HD_PRECOMP	HD_FEATURE	/* obsolete use of this port - predates IDE */
+#define HD_COMMAND	HD_STATUS	/* same io address, read=status, write=cmd */
+
+#define HD_CMD		0x74c	/* used for resets */
+#define HD_ALTSTATUS	0x74c	/* same as HD_STATUS but doesn't clear irq */
+
+/* Bits of HD_STATUS */
+#define ERR_STAT		0x01
+#define INDEX_STAT		0x02
+#define ECC_STAT		0x04	/* Corrected error */
+#define DRQ_STAT		0x08
+#define SEEK_STAT		0x10
+#define SERVICE_STAT		SEEK_STAT
+#define WRERR_STAT		0x20
+#define READY_STAT		0x40
+#define BUSY_STAT		0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR		0x01	/* Bad address mark */
+#define TRK0_ERR		0x02	/* couldn't find track 0 */
+#define ABRT_ERR		0x04	/* Command aborted */
+#define MCR_ERR			0x08	/* media change request */
+#define ID_ERR			0x10	/* ID field not found */
+#define MC_ERR			0x20	/* media changed */
+#define ECC_ERR			0x40	/* Uncorrectable ECC error */
+#define BBD_ERR			0x80	/* pre-EIDE meaning:  block marked bad */
+#define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */
+
+static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED;
+
+#define TIMEOUT_VALUE	(6*HZ)
+#define	HD_DELAY	0
+
+#define MAX_ERRORS     16	/* Max read/write errors/sector */
+#define RESET_FREQ      8	/* Reset controller every 8th retry */
+#define RECAL_FREQ      4	/* Recalibrate every 4th retry */
+#define MAX_HD		2
+
+#define STAT_OK		(READY_STAT|SEEK_STAT)
+#define OK_STATUS(s)	(((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
+
+static void recal_intr(void);
+static void bad_rw_intr(void);
+
+static char recalibrate[MAX_HD];
+static char special_op[MAX_HD];
+
+static int reset;
+static int hd_error;
+
+#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
+
+/*
+ *  This struct defines the HD's and their types.
+ */
+struct hd_i_struct {
+	unsigned int head,sect,cyl,wpcom,lzone,ctl;
+};
+	
+#ifdef HD_TYPE
+struct hd_i_struct hd_info[] = { HD_TYPE };
+static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
+#else
+struct hd_i_struct hd_info[MAX_HD];
+static int NR_HD;
+#endif
+
+static struct gendisk *hd_gendisk[MAX_HD];
+
+static struct timer_list device_timer;
+
+#define TIMEOUT_VALUE (6*HZ)
+
+#define SET_TIMER							\
+	do {								\
+		mod_timer(&device_timer, jiffies + TIMEOUT_VALUE);	\
+	} while (0)
+
+static void (*do_hd)(void) = NULL;
+#define SET_HANDLER(x) \
+if ((do_hd = (x)) != NULL) \
+	SET_TIMER; \
+else \
+	del_timer(&device_timer);
+
+
+#if (HD_DELAY > 0)
+unsigned long last_req;
+
+unsigned long read_timer(void)
+{
+        extern spinlock_t i8253_lock;
+	unsigned long t, flags;
+	int i;
+
+	spin_lock_irqsave(&i8253_lock, flags);
+	t = jiffies * 11932;
+    	outb_p(0, PIT_MODE);
+	i = inb_p(PIT_CH0);
+	i |= inb(PIT_CH0) << 8;
+	spin_unlock_irqrestore(&i8253_lock, flags);
+	return(t - i);
+}
+#endif
+
+void __init hd_setup(char *str, int *ints)
+{
+	int hdind = 0;
+
+	if (ints[0] != 3)
+		return;
+	if (hd_info[0].head != 0)
+		hdind=1;
+	hd_info[hdind].head = ints[2];
+	hd_info[hdind].sect = ints[3];
+	hd_info[hdind].cyl = ints[1];
+	hd_info[hdind].wpcom = 0;
+	hd_info[hdind].lzone = ints[1];
+	hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
+	NR_HD = hdind+1;
+}
+
+static void dump_status (const char *msg, unsigned int stat)
+{
+	char devc;
+
+	devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
+#ifdef VERBOSE_ERRORS
+	printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
+	if (stat & BUSY_STAT)	printk("Busy ");
+	if (stat & READY_STAT)	printk("DriveReady ");
+	if (stat & WRERR_STAT)	printk("WriteFault ");
+	if (stat & SEEK_STAT)	printk("SeekComplete ");
+	if (stat & DRQ_STAT)	printk("DataRequest ");
+	if (stat & ECC_STAT)	printk("CorrectedError ");
+	if (stat & INDEX_STAT)	printk("Index ");
+	if (stat & ERR_STAT)	printk("Error ");
+	printk("}\n");
+	if ((stat & ERR_STAT) == 0) {
+		hd_error = 0;
+	} else {
+		hd_error = inb(HD_ERROR);
+		printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff);
+		if (hd_error & BBD_ERR)		printk("BadSector ");
+		if (hd_error & ECC_ERR)		printk("UncorrectableError ");
+		if (hd_error & ID_ERR)		printk("SectorIdNotFound ");
+		if (hd_error & ABRT_ERR)	printk("DriveStatusError ");
+		if (hd_error & TRK0_ERR)	printk("TrackZeroNotFound ");
+		if (hd_error & MARK_ERR)	printk("AddrMarkNotFound ");
+		printk("}");
+		if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
+			printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
+				inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
+			if (!blk_queue_empty(QUEUE))
+				printk(", sector=%ld", CURRENT->sector);
+		}
+		printk("\n");
+	}
+#else
+	printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff);
+	if ((stat & ERR_STAT) == 0) {
+		hd_error = 0;
+	} else {
+		hd_error = inb(HD_ERROR);
+		printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff);
+	}
+#endif
+}
+
+void check_status(void)
+{
+	int i = inb(HD_STATUS);
+
+	if (!OK_STATUS(i)) {
+		dump_status("check_status", i);
+		bad_rw_intr();
+	}
+}
+
+static int controller_busy(void)
+{
+	int retries = 100000;
+	unsigned char status;
+
+	do {
+		status = inb(HD_STATUS);
+	} while ((status & BUSY_STAT) && --retries);
+	return status;
+}
+
+static int status_ok(void)
+{
+	unsigned char status = inb(HD_STATUS);
+
+	if (status & BUSY_STAT)
+		return 1;	/* Ancient, but does it make sense??? */
+	if (status & WRERR_STAT)
+		return 0;
+	if (!(status & READY_STAT))
+		return 0;
+	if (!(status & SEEK_STAT))
+		return 0;
+	return 1;
+}
+
+static int controller_ready(unsigned int drive, unsigned int head)
+{
+	int retry = 100;
+
+	do {
+		if (controller_busy() & BUSY_STAT)
+			return 0;
+		outb(0xA0 | (drive<<4) | head, HD_CURRENT);
+		if (status_ok())
+			return 1;
+	} while (--retry);
+	return 0;
+}
+
+static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
+		unsigned int head,unsigned int cyl,unsigned int cmd,
+		void (*intr_addr)(void))
+{
+	unsigned short port;
+
+#if (HD_DELAY > 0)
+	while (read_timer() - last_req < HD_DELAY)
+		/* nothing */;
+#endif
+	if (reset)
+		return;
+	if (!controller_ready(drive, head)) {
+		reset = 1;
+		return;
+	}
+	SET_HANDLER(intr_addr);
+	outb(hd_info[drive].ctl,HD_CMD);
+	port=HD_DATA + 2;
+	outb(hd_info[drive].wpcom>>2, port); port += 2;
+	outb(nsect, port); port += 2;
+	outb(sect, port); port += 2;
+	outb(cyl, port); port += 2;
+	outb(cyl>>8, port); port += 2;
+	outb(0xA0|(drive<<4)|head, port); port += 2;
+	outb(cmd, port);
+}
+
+static void hd_request (void);
+
+static int drive_busy(void)
+{
+	unsigned int i;
+	unsigned char c;
+
+	for (i = 0; i < 500000 ; i++) {
+		c = inb(HD_STATUS);
+		if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
+			return 0;
+	}
+	dump_status("reset timed out", c);
+	return 1;
+}
+
+static void reset_controller(void)
+{
+	int	i;
+
+	outb(4,HD_CMD);
+	for(i = 0; i < 1000; i++) barrier();
+	outb(hd_info[0].ctl & 0x0f,HD_CMD);
+	for(i = 0; i < 1000; i++) barrier();
+	if (drive_busy())
+		printk("hd: controller still busy\n");
+	else if ((hd_error = inb(HD_ERROR)) != 1)
+		printk("hd: controller reset failed: %02x\n",hd_error);
+}
+
+static void reset_hd(void)
+{
+	static int i;
+
+repeat:
+	if (reset) {
+		reset = 0;
+		i = -1;
+		reset_controller();
+	} else {
+		check_status();
+		if (reset)
+			goto repeat;
+	}
+	if (++i < NR_HD) {
+		special_op[i] = recalibrate[i] = 1;
+		hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
+			hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
+		if (reset)
+			goto repeat;
+	} else
+		hd_request();
+}
+
+/*
+ * Ok, don't know what to do with the unexpected interrupts: on some machines
+ * doing a reset and a retry seems to result in an eternal loop. Right now I
+ * ignore it, and just set the timeout.
+ *
+ * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
+ * drive enters "idle", "standby", or "sleep" mode, so if the status looks
+ * "good", we just ignore the interrupt completely.
+ */
+void unexpected_hd_interrupt(void)
+{
+	unsigned int stat = inb(HD_STATUS);
+
+	if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
+		dump_status ("unexpected interrupt", stat);
+		SET_TIMER;
+	}
+}
+
+/*
+ * bad_rw_intr() now tries to be a bit smarter and does things
+ * according to the error returned by the controller.
+ * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
+ */
+static void bad_rw_intr(void)
+{
+	int dev;
+
+	if (blk_queue_empty(QUEUE))
+		return;
+	dev = DEVICE_NR(CURRENT->rq_dev);
+	if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
+		end_request(CURRENT, 0);
+		special_op[dev] = recalibrate[dev] = 1;
+	} else if (CURRENT->errors % RESET_FREQ == 0)
+		reset = 1;
+	else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
+		special_op[dev] = recalibrate[dev] = 1;
+	/* Otherwise just retry */
+}
+
+static inline int wait_DRQ(void)
+{
+	int retries = 100000, stat;
+
+	while (--retries > 0)
+		if ((stat = inb(HD_STATUS)) & DRQ_STAT)
+			return 0;
+	dump_status("wait_DRQ", stat);
+	return -1;
+}
+
+static void read_intr(void)
+{
+	int i, retries = 100000;
+
+	do {
+		i = (unsigned) inb(HD_STATUS);
+		if (i & BUSY_STAT)
+			continue;
+		if (!OK_STATUS(i))
+			break;
+		if (i & DRQ_STAT)
+			goto ok_to_read;
+	} while (--retries > 0);
+	dump_status("read_intr", i);
+	bad_rw_intr();
+	hd_request();
+	return;
+ok_to_read:
+	insw(HD_DATA,CURRENT->buffer,256);
+	CURRENT->sector++;
+	CURRENT->buffer += 512;
+	CURRENT->errors = 0;
+	i = --CURRENT->nr_sectors;
+	--CURRENT->current_nr_sectors;
+#ifdef DEBUG
+	printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n",
+		dev+'a', CURRENT->sector, CURRENT->nr_sectors,
+		(unsigned long) CURRENT->buffer+512);
+#endif
+	if (CURRENT->current_nr_sectors <= 0)
+		end_request(CURRENT, 1);
+	if (i > 0) {
+		SET_HANDLER(&read_intr);
+		return;
+	}
+	(void) inb(HD_STATUS);
+#if (HD_DELAY > 0)
+	last_req = read_timer();
+#endif
+	if (!blk_queue_empty(QUEUE))
+		hd_request();
+	return;
+}
+
+static void write_intr(void)
+{
+	int i;
+	int retries = 100000;
+
+	do {
+		i = (unsigned) inb(HD_STATUS);
+		if (i & BUSY_STAT)
+			continue;
+		if (!OK_STATUS(i))
+			break;
+		if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
+			goto ok_to_write;
+	} while (--retries > 0);
+	dump_status("write_intr", i);
+	bad_rw_intr();
+	hd_request();
+	return;
+ok_to_write:
+	CURRENT->sector++;
+	i = --CURRENT->nr_sectors;
+	--CURRENT->current_nr_sectors;
+	CURRENT->buffer += 512;
+	if (!i || (CURRENT->bio && !SUBSECTOR(i)))
+		end_request(CURRENT, 1);
+	if (i > 0) {
+		SET_HANDLER(&write_intr);
+		outsw(HD_DATA,CURRENT->buffer,256);
+		local_irq_enable();
+	} else {
+#if (HD_DELAY > 0)
+		last_req = read_timer();
+#endif
+		hd_request();
+	}
+	return;
+}
+
+static void recal_intr(void)
+{
+	check_status();
+#if (HD_DELAY > 0)
+	last_req = read_timer();
+#endif
+	hd_request();
+}
+
+/*
+ * This is another of the error-routines I don't know what to do with. The
+ * best idea seems to just set reset, and start all over again.
+ */
+static void hd_times_out(unsigned long dummy)
+{
+	unsigned int dev;
+
+	do_hd = NULL;
+
+	if (blk_queue_empty(QUEUE))
+		return;
+
+	disable_irq(HD_IRQ);
+	local_irq_enable();
+	reset = 1;
+	dev = DEVICE_NR(CURRENT->rq_dev);
+	printk("hd%c: timeout\n", dev+'a');
+	if (++CURRENT->errors >= MAX_ERRORS) {
+#ifdef DEBUG
+		printk("hd%c: too many errors\n", dev+'a');
+#endif
+		end_request(CURRENT, 0);
+	}
+	local_irq_disable();
+	hd_request();
+	enable_irq(HD_IRQ);
+}
+
+int do_special_op (unsigned int dev)
+{
+	if (recalibrate[dev]) {
+		recalibrate[dev] = 0;
+		hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
+		return reset;
+	}
+	if (hd_info[dev].head > 16) {
+		printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
+		end_request(CURRENT, 0);
+	}
+	special_op[dev] = 0;
+	return 1;
+}
+
+/*
+ * The driver enables interrupts as much as possible.  In order to do this,
+ * (a) the device-interrupt is disabled before entering hd_request(),
+ * and (b) the timeout-interrupt is disabled before the sti().
+ *
+ * Interrupts are still masked (by default) whenever we are exchanging
+ * data/cmds with a drive, because some drives seem to have very poor
+ * tolerance for latency during I/O. The IDE driver has support to unmask
+ * interrupts for non-broken hardware, so use that driver if required.
+ */
+static void hd_request(void)
+{
+	unsigned int dev, block, nsect, sec, track, head, cyl;
+
+	if (do_hd)
+		return;
+repeat:
+	del_timer(&device_timer);
+	local_irq_enable();
+
+	if (blk_queue_empty(QUEUE)) {
+		do_hd = NULL;
+		return;
+	}
+
+	if (reset) {
+		local_irq_disable();
+		reset_hd();
+		return;
+	}
+	dev = DEVICE_NR(CURRENT->rq_dev);
+	block = CURRENT->sector;
+	nsect = CURRENT->nr_sectors;
+	if (dev >= NR_HD) {
+		printk("hd: bad disk number: %d\n", dev);
+		end_request(CURRENT, 0);
+		goto repeat;
+	}
+	if (block >= get_capacity(hd_gendisk[dev]) ||
+	    ((block+nsect) > get_capacity(hd_gendisk[dev]))) {
+		printk("%s: bad access: block=%d, count=%d\n",
+			hd_gendisk[dev]->disk_name, block, nsect);
+		end_request(CURRENT, 0);
+		goto repeat;
+	}
+
+	if (special_op[dev]) {
+		if (do_special_op(dev))
+			goto repeat;
+		return;
+	}
+	sec   = block % hd_info[dev].sect + 1;
+	track = block / hd_info[dev].sect;
+	head  = track % hd_info[dev].head;
+	cyl   = track / hd_info[dev].head;
+#ifdef DEBUG
+	printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n",
+		dev+'a', (CURRENT->cmd == READ)?"read":"writ",
+		cyl, head, sec, nsect, (unsigned long) CURRENT->buffer);
+#endif
+	if(CURRENT->flags & REQ_CMD) {
+		switch (rq_data_dir(CURRENT)) {
+		case READ:
+			hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
+			if (reset)
+				goto repeat;
+			break;
+		case WRITE:
+			hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
+			if (reset)
+				goto repeat;
+			if (wait_DRQ()) {
+				bad_rw_intr();
+				goto repeat;
+			}
+			outsw(HD_DATA,CURRENT->buffer,256);
+			break;
+		default:
+			printk("unknown hd-command\n");
+			end_request(CURRENT, 0);
+			break;
+		}
+	}
+}
+
+static void do_hd_request (request_queue_t * q)
+{
+	disable_irq(HD_IRQ);
+	hd_request();
+	enable_irq(HD_IRQ);
+}
+
+static int hd_ioctl(struct inode * inode, struct file * file,
+	unsigned int cmd, unsigned long arg)
+{
+	struct hd_geometry *loc = (struct hd_geometry *) arg;
+	int dev;
+
+	if ((!inode) || kdev_none(inode->i_rdev))
+		return -EINVAL;
+	dev = DEVICE_NR(inode->i_rdev);
+	if (dev >= NR_HD)
+		return -EINVAL;
+	switch (cmd) {
+		case HDIO_GETGEO:
+		{
+			struct hd_geometry g; 
+			if (!loc)  return -EINVAL;
+			g.heads = hd_info[dev].head;
+			g.sectors = hd_info[dev].sect;
+			g.cylinders = hd_info[dev].cyl;
+			g.start = get_start_sect(inode->i_bdev);
+			return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
+		}
+
+		default:
+			return -EINVAL;
+	}
+}
+
+static int hd_open(struct inode * inode, struct file * filp)
+{
+	int target =  DEVICE_NR(inode->i_rdev);
+	if (target >= NR_HD)
+		return -ENODEV;
+	return 0;
+}
+
+/*
+ * Releasing a block device means we sync() it, so that it can safely
+ * be forgotten about...
+ */
+
+extern struct block_device_operations hd_fops;
+
+static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	void (*handler)(void) = do_hd;
+
+	do_hd = NULL;
+	del_timer(&device_timer);
+	if (!handler)
+		handler = unexpected_hd_interrupt;
+	handler();
+	local_irq_enable();
+}
+
+static struct block_device_operations hd_fops = {
+	.open =		hd_open,
+	.ioctl =	hd_ioctl,
+};
+
+/*
+ * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
+ * means we run the IRQ-handler with interrupts disabled:  this is bad for
+ * interrupt latency, but anything else has led to problems on some
+ * machines.
+ *
+ * We enable interrupts in some of the routines after making sure it's
+ * safe.
+ */
+
+static int __init hd_init(void)
+{
+	int drive;
+	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
+		printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
+		return -1;
+	}
+	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
+	blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
+	init_timer(&device_timer);
+	device_timer.function = hd_times_out;
+	blk_queue_hardsect_size(QUEUE, 512);
+
+#ifdef __i386__
+	if (!NR_HD) {
+		extern struct drive_info drive_info;
+		unsigned char *BIOS = (unsigned char *) &drive_info;
+		unsigned long flags;
+#ifndef CONFIG_X86_PC9800
+		int cmos_disks;
+#endif
+
+		for (drive=0 ; drive<2 ; drive++) {
+			hd_info[drive].cyl = *(unsigned short *) BIOS;
+			hd_info[drive].head = *(3+BIOS);
+			hd_info[drive].sect = *(2+BIOS);
+			hd_info[drive].wpcom = 0;
+			hd_info[drive].ctl = *(3+BIOS) > 8 ? 8 : 0;
+			hd_info[drive].lzone = *(unsigned short *) BIOS;
+			if (hd_info[drive].cyl && NR_HD == drive)
+				NR_HD++;
+			BIOS += 6;
+		}
+
+	}
+#endif /* __i386__ */
+#ifdef __arm__
+	if (!NR_HD) {
+		/* We don't know anything about the drive.  This means
+		 * that you *MUST* specify the drive parameters to the
+		 * kernel yourself.
+		 */
+		printk("hd: no drives specified - use hd=cyl,head,sectors"
+			" on kernel command line\n");
+	}
+#endif
+	if (!NR_HD)
+		goto out;
+
+	for (drive=0 ; drive < NR_HD ; drive++) {
+		struct gendisk *disk = alloc_disk();
+		if (!disk)
+			goto Enomem;
+		disk->major = MAJOR_NR;
+		disk->first_minor = drive << 6;
+		disk->minor_shift = 6;
+		disk->fops = &hd_fops;
+		sprintf(disk->disk_name, "hd%c", 'a'+drive);
+		hd_gendisk[drive] = disk;
+	}
+	for (drive=0 ; drive < NR_HD ; drive++) {
+		sector_t size = hd_info[drive].head *
+			hd_info[drive].sect * hd_info[drive].cyl;
+		set_capacity(hd_gendisk[drive], size);
+		printk ("%s: %ldMB, CHS=%d/%d/%d\n",
+			hd_gendisk[drive]->disk_name,
+			size / 2048, hd_info[drive].cyl,
+			hd_info[drive].head, hd_info[drive].sect);
+	}
+
+	if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
+		printk("hd: unable to get IRQ%d for the hard disk driver\n",
+			HD_IRQ);
+		goto out1;
+	}
+
+	if (!request_region(HD_DATA, 2, "hd(data)")) {
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		NR_HD = 0;
+		free_irq(HD_IRQ, NULL);
+		return;
+	}
+
+	if (!request_region(HD_DATA + 2, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out2;
+	}
+
+	if (!request_region(HD_DATA + 4, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out3;
+	}
+
+	if (!request_region(HD_DATA + 6, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out4;
+	}
+
+	if (!request_region(HD_DATA + 8, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out5;
+	}
+
+	if (!request_region(HD_DATA + 10, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out6;
+	}
+
+	if (!request_region(HD_DATA + 12, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out7;
+	}
+
+	if (!request_region(HD_CMD, 1, "hd(cmd)"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
+		goto out8;
+	}
+
+	if (!request_region(HD_CMD + 2, 1, "hd(cmd)"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
+		goto out9;
+	}
+
+	for(drive=0; drive < NR_HD; drive++) {
+		struct hd_i_struct *p = hd_info + drive;
+		set_capacity(hd_gendisk[drive], p->head * p->sect * p->cyl);
+		add_disk(hd_gendisk[drive]);
+	}
+	return 0;
+
+out9:
+	release_region(HD_CMD, 1);
+out8:
+	release_region(HD_DATA + 12, 1);
+out7:
+	release_region(HD_DATA + 10, 1);
+out6:
+	release_region(HD_DATA + 8, 1);
+out5:
+	release_region(HD_DATA + 6, 1);
+out4:
+	release_region(HD_DATA + 4, 1);
+out3:
+	release_region(HD_DATA + 2, 1);
+out2:
+	release_region(HD_DATA, 2);
+	free_irq(HD_IRQ, NULL);
+out1:
+	for (drive = 0; drive < NR_HD; drive++)
+		put_disk(hd_gendisk[drive]);
+	NR_HD = 0;
+out:
+	del_timer(&device_timer);
+	unregister_blkdev(MAJOR_NR,"hd");
+	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	return -1;
+Enomem:
+	while (drive--)
+		put_disk(hd_gendisk[drive]);
+	goto out;
+}
+
+static int parse_hd_setup (char *line) {
+	int ints[6];
+
+	(void) get_options(line, ARRAY_SIZE(ints), ints);
+	hd_setup(NULL, ints);
+
+	return 1;
+}
+__setup("hd=", parse_hd_setup);
+
+module_init(hd_init);
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/ht6560b.c linux-2.5.65-bk3/drivers/ide/legacy/ht6560b.c
--- linux-2.5.65-bk2/drivers/ide/legacy/ht6560b.c	Mon Mar 17 13:44:40 2003
+++ linux-2.5.65-bk3/drivers/ide/legacy/ht6560b.c	Mon Mar 31 12:41:40 2003
@@ -312,42 +312,7 @@
 #endif
 }
 
-void __init probe_ht6560b (void)
-{
-	int t;
-	
-	request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name);
-	ide_hwifs[0].chipset = ide_ht6560b;
-	ide_hwifs[1].chipset = ide_ht6560b;
-	ide_hwifs[0].selectproc = &ht6560b_selectproc;
-	ide_hwifs[1].selectproc = &ht6560b_selectproc;
-	ide_hwifs[0].tuneproc = &tune_ht6560b;
-	ide_hwifs[1].tuneproc = &tune_ht6560b;
-	ide_hwifs[0].serialized = 1;  /* is this needed? */
-	ide_hwifs[1].serialized = 1;  /* is this needed? */
-	ide_hwifs[0].mate = &ide_hwifs[1];
-	ide_hwifs[1].mate = &ide_hwifs[0];
-	ide_hwifs[1].channel = 1;
-			
-	/*
-	 * Setting default configurations for drives
-	 */
-	t = (HT_CONFIG_DEFAULT << 8);
-	t |= HT_TIMING_DEFAULT;
-	ide_hwifs[0].drives[0].drive_data = t;
-	ide_hwifs[0].drives[1].drive_data = t;
-	t |= (HT_SECONDARY_IF << 8);
-	ide_hwifs[1].drives[0].drive_data = t;
-	ide_hwifs[1].drives[1].drive_data = t;
-
-#ifndef HWIF_PROBE_CLASSIC_METHOD
-	probe_hwif_init(&ide_hwifs[0]);
-	probe_hwif_init(&ide_hwifs[1]);
-#endif /* HWIF_PROBE_CLASSIC_METHOD */
-
-}
-
-void __init ht6560b_release (void)
+void ht6560b_release (void)
 {
 	if (ide_hwifs[0].chipset != ide_ht6560b &&
 	    ide_hwifs[1].chipset != ide_ht6560b)
@@ -371,60 +336,80 @@
 	release_region(HT_CONFIG_PORT, 1);
 }
 
-#ifndef MODULE
-/*
- * init_ht6560b:
- *
- * called by ide.c when parsing command line
- */
-
-void __init init_ht6560b (void)
+int __init ht6560b_mod_init(void)
 {
-	if (check_region(HT_CONFIG_PORT,1)) {
+	int t;
+
+	if (!request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name)) {
 		printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
 			__FUNCTION__);
-		return;
+		return -ENODEV;
 	}
+
 	if (!try_to_init_ht6560b()) {
-                printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
-		return;
+		printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
+		goto release_region;
 	}
-	probe_ht6560b();
-}
 
-#else
+	ide_hwifs[0].chipset = ide_ht6560b;
+	ide_hwifs[1].chipset = ide_ht6560b;
+	ide_hwifs[0].selectproc = &ht6560b_selectproc;
+	ide_hwifs[1].selectproc = &ht6560b_selectproc;
+	ide_hwifs[0].tuneproc = &tune_ht6560b;
+	ide_hwifs[1].tuneproc = &tune_ht6560b;
+	ide_hwifs[0].serialized = 1;  /* is this needed? */
+	ide_hwifs[1].serialized = 1;  /* is this needed? */
+	ide_hwifs[0].mate = &ide_hwifs[1];
+	ide_hwifs[1].mate = &ide_hwifs[0];
+	ide_hwifs[1].channel = 1;
 
-MODULE_AUTHOR("See Local File");
-MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
-MODULE_LICENSE("GPL");
+	/*
+	 * Setting default configurations for drives
+	 */
+	t = (HT_CONFIG_DEFAULT << 8);
+	t |= HT_TIMING_DEFAULT;
+	ide_hwifs[0].drives[0].drive_data = t;
+	ide_hwifs[0].drives[1].drive_data = t;
+	t |= (HT_SECONDARY_IF << 8);
+	ide_hwifs[1].drives[0].drive_data = t;
+	ide_hwifs[1].drives[1].drive_data = t;
 
-int __init ht6560b_mod_init(void)
-{
-	if (check_region(HT_CONFIG_PORT,1)) {
-		printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
-			__FUNCTION__);
-		return -ENODEV;
-	}
+	probe_hwif_init(&ide_hwifs[0]);
+	probe_hwif_init(&ide_hwifs[1]);
 
-	if (!try_to_init_ht6560b()) {
-		printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
+#ifdef MODULE
+	if (ide_hwifs[0].chipset != ide_ht6560b &&
+	    ide_hwifs[1].chipset != ide_ht6560b) {
+		ht6560b_release();
 		return -ENODEV;
 	}
+#endif
 
-	probe_ht6560b();
-        if (ide_hwifs[0].chipset != ide_ht6560b &&
-            ide_hwifs[1].chipset != ide_ht6560b) {
-                ht6560b_release();
-                return -ENODEV;
-        }
-        return 0;
+	return 0;
+
+release_region:
+	release_region(HT_CONFIG_PORT, 1);
+	return -ENODEV;
 }
-module_init(ht6560b_mod_init);
 
+MODULE_AUTHOR("See Local File");
+MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
+MODULE_LICENSE("GPL");
+
+#ifdef MODULE
 void __init ht6560b_mod_exit(void)
 {
         ht6560b_release();
 }
+
+module_init(ht6560b_mod_init);
 module_exit(ht6560b_mod_exit);
+#else
+/*
+ * called by ide.c when parsing command line
+ */
+void __init init_ht6560b (void)
+{
+	ht6560b_mod_init();	/* ignore return value */
+}
 #endif
-
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/pc9800.c linux-2.5.65-bk3/drivers/ide/legacy/pc9800.c
--- linux-2.5.65-bk2/drivers/ide/legacy/pc9800.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/drivers/ide/legacy/pc9800.c	Mon Mar 31 12:41:40 2003
@@ -0,0 +1,80 @@
+/*
+ *  ide_pc9800.c
+ *
+ *  Copyright (C) 1997-2000  Linux/98 project,
+ *			     Kyoto University Microcomputer Club.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pc9800.h>
+
+#define PC9800_IDE_BANKSELECT	0x432
+
+#undef PC9800_IDE_DEBUG
+
+static void pc9800_select(ide_drive_t *drive)
+{
+#ifdef PC9800_IDE_DEBUG
+	byte old;
+
+	/* Too noisy: */
+	/* printk(KERN_DEBUG "pc9800_select(%s)\n", drive->name); */
+
+	outb(0x80, PC9800_IDE_BANKSELECT);
+	old = inb(PC9800_IDE_BANKSELECT);
+	if (old != HWIF(drive)->index)
+		printk(KERN_DEBUG "ide-pc9800: switching bank #%d -> #%d\n",
+			old, HWIF(drive)->index);
+#endif
+	outb(HWIF(drive)->index, PC9800_IDE_BANKSELECT);
+}
+
+void __init ide_probe_for_pc9800(void)
+{
+	u8 saved_bank;
+
+	if (!PC9800_9821_P() /* || !PC9821_IDEIF_DOUBLE_P() */)
+		return;
+
+	if (!request_region(PC9800_IDE_BANKSELECT, 1, "ide0/1 bank")) {
+		printk(KERN_ERR
+			"ide: bank select port (%#x) is already occupied!\n",
+			PC9800_IDE_BANKSELECT);
+		return;
+	}
+
+	/* Do actual probing. */
+	if ((saved_bank = inb(PC9800_IDE_BANKSELECT)) == (u8) ~0
+	    || (outb(saved_bank ^ 1, PC9800_IDE_BANKSELECT),
+		/* Next outb is dummy for reading status. */
+		outb(0x80, PC9800_IDE_BANKSELECT),
+		inb(PC9800_IDE_BANKSELECT) != (saved_bank ^ 1))) {
+		printk(KERN_INFO
+			"ide: pc9800 type bank selecting port not found\n");
+		release_region(PC9800_IDE_BANKSELECT, 1);
+		return;
+	}
+
+	/* Restore original value, just in case. */
+	outb(saved_bank, PC9800_IDE_BANKSELECT);
+
+	/* These ports are probably used by IDE I/F.  */
+	request_region(0x430, 1, "ide");
+	request_region(0x435, 1, "ide");
+
+	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET] == HD_DATA &&
+	    ide_hwifs[1].io_ports[IDE_DATA_OFFSET] == HD_DATA) {
+		ide_hwifs[0].chipset = ide_pc9800;
+		ide_hwifs[0].mate = &ide_hwifs[1];
+		ide_hwifs[0].selectproc = pc9800_select;
+		ide_hwifs[1].chipset = ide_pc9800;
+		ide_hwifs[1].mate = &ide_hwifs[0];
+		ide_hwifs[1].selectproc = pc9800_select;
+	}
+}
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/pdc4030.c linux-2.5.65-bk3/drivers/ide/legacy/pdc4030.c
--- linux-2.5.65-bk2/drivers/ide/legacy/pdc4030.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/drivers/ide/legacy/pdc4030.c	Mon Mar 31 12:41:40 2003
@@ -256,12 +256,11 @@
 		if (!ident.current_tm[i+2].cyl)
 			hwif2->drives[i].noprobe = 1;
 	}
-#ifndef HWIF_PROBE_CLASSIC_METHOD
+
 	probe_hwif_init(&ide_hwifs[hwif->index]);
 	probe_hwif_init(&ide_hwifs[hwif2->index]);
-#endif /* HWIF_PROBE_CLASSIC_METHOD */
 
-        return 1;
+	return 1;
 }
 
 /*
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/qd65xx.c linux-2.5.65-bk3/drivers/ide/legacy/qd65xx.c
--- linux-2.5.65-bk2/drivers/ide/legacy/qd65xx.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/drivers/ide/legacy/qd65xx.c	Mon Mar 31 12:41:40 2003
@@ -359,9 +359,7 @@
 	hwif->drives[0].io_32bit =
 	hwif->drives[1].io_32bit = 1;
 	hwif->tuneproc = tuneproc;
-#ifndef HWIF_PROBE_CLASSIC_METHOD
 	probe_hwif_init(hwif);
-#endif /* HWIF_PROBE_CLASSIC_METHOD */
 }
 
 /*
diff -urN linux-2.5.65-bk2/drivers/ide/legacy/umc8672.c linux-2.5.65-bk3/drivers/ide/legacy/umc8672.c
--- linux-2.5.65-bk2/drivers/ide/legacy/umc8672.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/drivers/ide/legacy/umc8672.c	Mon Mar 31 12:41:40 2003
@@ -162,10 +162,8 @@
 	ide_hwifs[1].mate = &ide_hwifs[0];
 	ide_hwifs[1].channel = 1;
 
-#ifndef HWIF_PROBE_CLASSIC_METHOD
 	probe_hwif_init(&ide_hwifs[0]);
 	probe_hwif_init(&ide_hwifs[1]);
-#endif /* HWIF_PROBE_CLASSIC_METHOD */
 
 	return 0;
 }
diff -urN linux-2.5.65-bk2/drivers/ide/pci/aec62xx.c linux-2.5.65-bk3/drivers/ide/pci/aec62xx.c
--- linux-2.5.65-bk2/drivers/ide/pci/aec62xx.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/aec62xx.c	Mon Mar 31 12:41:40 2003
@@ -38,6 +38,7 @@
 	char *chipset_nums[] = {"error", "error", "error", "error",
 				"error", "error", "850UF",   "860",
 				 "860R",   "865",  "865R", "error"  };
+	int len;
 	int i;
 
 	for (i = 0; i < n_aec_devs; i++) {
@@ -170,7 +171,11 @@
 #endif /* DEBUG_AEC_REGS */
 		}
 	}
-	return p-buffer;/* => must be less than 4k! */
+	/* p - buffer must be less than 4k! */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 #endif	/* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */
 
@@ -324,7 +329,7 @@
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct hd_driveid *id	= drive->id;
 
-	if (id && (id->capability & 1) && drive->autodma) {
+	if ((id->capability & 1) && drive->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (hwif->ide_dma_bad_drive(drive))
 			goto fast_ata_pio;
diff -urN linux-2.5.65-bk2/drivers/ide/pci/alim15x3.c linux-2.5.65-bk3/drivers/ide/pci/alim15x3.c
--- linux-2.5.65-bk2/drivers/ide/pci/alim15x3.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/alim15x3.c	Mon Mar 31 12:41:40 2003
@@ -518,7 +518,7 @@
 	if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (hwif->ide_dma_bad_drive(drive))
-			goto fast_ata_pio;
+			goto ata_pio;
 		if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) {
 			if (id->dma_ultra & hwif->ultra_mask) {
 				/* Force if Capable UltraDMA */
@@ -540,12 +540,12 @@
 			if (!config_chipset_for_dma(drive))
 				goto no_dma_set;
 		} else {
-			goto fast_ata_pio;
+			goto ata_pio;
 		}
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	} else {
+ata_pio:
+		hwif->tuneproc(drive, 255);
 no_dma_set:
-		hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
 	return hwif->ide_dma_on(drive);
@@ -753,6 +753,8 @@
 		return;
 	}
 
+	hwif->atapi_dma = 1;
+
 	if (m5229_revision > 0x20)
 		hwif->ultra_mask = 0x3f;
 	hwif->mwdma_mask = 0x07;
diff -urN linux-2.5.65-bk2/drivers/ide/pci/amd74xx.c linux-2.5.65-bk3/drivers/ide/pci/amd74xx.c
--- linux-2.5.65-bk2/drivers/ide/pci/amd74xx.c	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/amd74xx.c	Mon Mar 31 12:41:40 2003
@@ -98,6 +98,7 @@
 	unsigned int v, u, i;
 	unsigned short c, w;
 	unsigned char t;
+	int len;
 	char *p = buffer;
 
 	amd_print("----------AMD BusMastering IDE Configuration----------------");
@@ -167,7 +168,11 @@
 	amd_print_drive("Cycle Time:    ", "%8dns", cycle[i]);
 	amd_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10);
 
-	return p - buffer;	/* hoping it is less than 4K... */
+	/* hoping p - buffer is less than 4K... */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 
 #endif
diff -urN linux-2.5.65-bk2/drivers/ide/pci/cmd640.c linux-2.5.65-bk3/drivers/ide/pci/cmd640.c
--- linux-2.5.65-bk2/drivers/ide/pci/cmd640.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/cmd640.c	Mon Mar 31 12:41:40 2003
@@ -197,8 +197,8 @@
  * Interface to access cmd640x registers
  */
 static unsigned int cmd640_key;
-static void (*put_cmd640_reg)(u16 reg, u8 val);
-static u8 (*get_cmd640_reg)(u16 reg);
+static void (*__put_cmd640_reg)(u16 reg, u8 val);
+static u8 (*__get_cmd640_reg)(u16 reg);
 
 /*
  * This is read from the CFR reg, and is used in several places.
@@ -215,49 +215,32 @@
 
 static void put_cmd640_reg_pci1 (u16 reg, u8 val)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&ide_lock, flags);
 	outb_p((reg & 0xfc) | cmd640_key, 0xcf8);
 	outb_p(val, (reg & 3) | 0xcfc);
-	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
 static u8 get_cmd640_reg_pci1 (u16 reg)
 {
-	u8 b;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ide_lock, flags);
 	outb_p((reg & 0xfc) | cmd640_key, 0xcf8);
-	b = inb_p((reg & 3) | 0xcfc);
-	spin_unlock_irqrestore(&ide_lock, flags);
-	return b;
+	return inb_p((reg & 3) | 0xcfc);
 }
 
 /* PCI method 2 access (from CMD datasheet) */
 
 static void put_cmd640_reg_pci2 (u16 reg, u8 val)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&ide_lock, flags);
 	outb_p(0x10, 0xcf8);
 	outb_p(val, cmd640_key + reg);
 	outb_p(0, 0xcf8);
-	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
 static u8 get_cmd640_reg_pci2 (u16 reg)
 {
 	u8 b;
-	unsigned long flags;
 
-	spin_lock_irqsave(&ide_lock, flags);
 	outb_p(0x10, 0xcf8);
 	b = inb_p(cmd640_key + reg);
 	outb_p(0, 0xcf8);
-	spin_unlock_irqrestore(&ide_lock, flags);
 	return b;
 }
 
@@ -265,26 +248,36 @@
 
 static void put_cmd640_reg_vlb (u16 reg, u8 val)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&ide_lock, flags);
 	outb_p(reg, cmd640_key);
 	outb_p(val, cmd640_key + 4);
-	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
 static u8 get_cmd640_reg_vlb (u16 reg)
 {
+	outb_p(reg, cmd640_key);
+	return inb_p(cmd640_key + 4);
+}
+
+static u8 get_cmd640_reg(u16 reg)
+{
 	u8 b;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ide_lock, flags);
-	outb_p(reg, cmd640_key);
-	b = inb_p(cmd640_key + 4);
+	b = __get_cmd640_reg(reg);
 	spin_unlock_irqrestore(&ide_lock, flags);
 	return b;
 }
 
+static void put_cmd640_reg(u16 reg, u8 val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ide_lock, flags);
+	__put_cmd640_reg(reg,val);
+	spin_unlock_irqrestore(&ide_lock, flags);
+}
+
 static int __init match_pci_cmd640_device (void)
 {
 	const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
@@ -307,8 +300,8 @@
  */
 static int __init probe_for_cmd640_pci1 (void)
 {
-	get_cmd640_reg = get_cmd640_reg_pci1;
-	put_cmd640_reg = put_cmd640_reg_pci1;
+	__get_cmd640_reg = get_cmd640_reg_pci1;
+	__put_cmd640_reg = put_cmd640_reg_pci1;
 	for (cmd640_key = 0x80000000;
 	     cmd640_key <= 0x8000f800;
 	     cmd640_key += 0x800) {
@@ -323,8 +316,8 @@
  */
 static int __init probe_for_cmd640_pci2 (void)
 {
-	get_cmd640_reg = get_cmd640_reg_pci2;
-	put_cmd640_reg = put_cmd640_reg_pci2;
+	__get_cmd640_reg = get_cmd640_reg_pci2;
+	__put_cmd640_reg = put_cmd640_reg_pci2;
 	for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) {
 		if (match_pci_cmd640_device())
 			return 1; /* success */
@@ -339,8 +332,8 @@
 {
 	u8 b;
 
-	get_cmd640_reg = get_cmd640_reg_vlb;
-	put_cmd640_reg = put_cmd640_reg_vlb;
+	__get_cmd640_reg = get_cmd640_reg_vlb;
+	__put_cmd640_reg = put_cmd640_reg_vlb;
 	cmd640_key = 0x178;
 	b = get_cmd640_reg(CFR);
 	if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) {
@@ -454,7 +447,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&ide_lock, flags);
-	b = get_cmd640_reg(reg);
+	b = __get_cmd640_reg(reg);
 	if (mode) {	/* want prefetch on? */
 #if CMD640_PREFETCH_MASKS
 		drive->no_unmask = 1;
@@ -468,7 +461,7 @@
 		drive->io_32bit = 0;
 		b |= prefetch_masks[index];	/* disable prefetch */
 	}
-	put_cmd640_reg(reg, b);
+	__put_cmd640_reg(reg, b);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
@@ -576,9 +569,9 @@
 	 * and then the active/recovery counts into the DRWTIM reg
 	 * (this converts counts of 16 into counts of zero -- okay).
 	 */
-	setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f;
-	put_cmd640_reg(arttim_regs[index], setup_count);
-	put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
+	setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
+	__put_cmd640_reg(arttim_regs[index], setup_count);
+	__put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/cs5520.c linux-2.5.65-bk3/drivers/ide/pci/cs5520.c
--- linux-2.5.65-bk2/drivers/ide/pci/cs5520.c	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/cs5520.c	Mon Mar 31 12:41:40 2003
@@ -65,6 +65,7 @@
 {
 	char *p = buffer;
 	unsigned long bmiba = pci_resource_start(bmide_dev, 2);
+	int len;
 	u8 c0 = 0, c1 = 0;
 	u16 reg16;
 	u32 reg32;
@@ -94,7 +95,10 @@
 	pci_read_config_dword(bmide_dev, 0x68, &reg32);
 	p += sprintf(p, "16bit Secondary: %08x\n", reg32);
 	
-	return p-buffer;
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 
 #endif
@@ -259,9 +263,9 @@
 {
 	ata_index_t index;
 	ide_pci_device_t *d = &cyrix_chipsets[id->driver_data];
-	
-	ide_setup_pci_noise(dev, d);	
-	
+
+	ide_setup_pci_noise(dev, d);
+
 	/* We must not grab the entire device, it has 'ISA' space in its
 	   BARS too and we will freak out other bits of the kernel */
 	if(pci_enable_device_bars(dev, 1<<2))
@@ -271,15 +275,15 @@
 	}
 	pci_set_master(dev);
 	pci_set_dma_mask(dev, 0xFFFFFFFF);
-	init_chipset_cs5520(dev, d->name);	
-	
+	init_chipset_cs5520(dev, d->name);
+
 	index.all = 0xf0f0;
 
 	/*
 	 *	Now the chipset is configured we can let the core
 	 *	do all the device setup for us
 	 */
-	 	
+
 	ide_pci_setup_ports(dev, d, 1, 14, &index);
 
 	printk("Index.b %d %d\n", index.b.low, index.b.high);
@@ -288,7 +292,7 @@
 		probe_hwif_init(&ide_hwifs[index.b.low]);
 	if((index.b.high & 0xf0) != 0xf0)
 		probe_hwif_init(&ide_hwifs[index.b.high]);
-		
+	MOD_INC_USE_COUNT;
 	return 0;
 }
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/hpt34x.c linux-2.5.65-bk3/drivers/ide/pci/hpt34x.c
--- linux-2.5.65-bk2/drivers/ide/pci/hpt34x.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/hpt34x.c	Mon Mar 31 12:41:40 2003
@@ -58,7 +58,7 @@
 static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	int i;
+	int i, len;
 
 	p += sprintf(p, "\n                             "
 			"HPT34X Chipset.\n");
@@ -96,7 +96,11 @@
 	}
 	p += sprintf(p, "\n");
 
-	return p-buffer;	/* => must be less than 4k! */
+	/* p - buffer must be less than 4k! */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 #endif  /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/hpt366.c linux-2.5.65-bk3/drivers/ide/pci/hpt366.c
--- linux-2.5.65-bk2/drivers/ide/pci/hpt366.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/hpt366.c	Mon Mar 31 12:41:40 2003
@@ -85,7 +85,7 @@
 	char *chipset_nums[] = {"366", "366",  "368",
 				"370", "370A", "372",
 				"302", "371",  "374" };
-	int i;
+	int i, len;
 
 	p += sprintf(p, "\n                             "
 		"HighPoint HPT366/368/370/372/374\n");
@@ -153,8 +153,12 @@
 		}
 	}
 	p += sprintf(p, "\n");
+
+	/* p - buffer must be less than 4k! */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
 	
-	return p-buffer;/* => must be less than 4k! */
+	return len > count ? count : len;
 }
 #endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/pdc202xx_new.c linux-2.5.65-bk3/drivers/ide/pci/pdc202xx_new.c
--- linux-2.5.65-bk2/drivers/ide/pci/pdc202xx_new.c	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/pdc202xx_new.c	Mon Mar 31 12:41:40 2003
@@ -77,13 +77,17 @@
 static int pdcnew_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	int i;
+	int i, len;
 
 	for (i = 0; i < n_pdc202_devs; i++) {
 		struct pci_dev *dev	= pdc202_devs[i];
 		p = pdcnew_info(buffer, dev);
 	}
-	return p-buffer;	/* => must be less than 4k! */
+	/* p - buffer must be less than 4k! */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 #endif  /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/pdc202xx_old.c linux-2.5.65-bk3/drivers/ide/pci/pdc202xx_old.c
--- linux-2.5.65-bk2/drivers/ide/pci/pdc202xx_old.c	Mon Mar 17 13:44:49 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/pdc202xx_old.c	Mon Mar 31 12:41:40 2003
@@ -177,13 +177,17 @@
 static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	int i;
+	int i, len;
 
 	for (i = 0; i < n_pdc202_devs; i++) {
 		struct pci_dev *dev	= pdc202_devs[i];
 		p = pdc202xx_info(buffer, dev);
 	}
-	return p-buffer;	/* => must be less than 4k! */
+	/* p - buffer must be less than 4k! */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 #endif  /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/piix.c linux-2.5.65-bk3/drivers/ide/pci/piix.c
--- linux-2.5.65-bk2/drivers/ide/pci/piix.c	Mon Mar 31 12:41:36 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/piix.c	Mon Mar 31 12:41:40 2003
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/pci/piix.c	Version 0.42	January 11, 2003
+ *  linux/drivers/ide/pci/piix.c	Version 0.44	March 20, 2003
  *
  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -146,7 +146,9 @@
 			case PCI_DEVICE_ID_INTEL_82801BA_9:
 			case PCI_DEVICE_ID_INTEL_82801CA_10:
 			case PCI_DEVICE_ID_INTEL_82801CA_11:
+			case PCI_DEVICE_ID_INTEL_82801DB_10:
 			case PCI_DEVICE_ID_INTEL_82801DB_11:
+			case PCI_DEVICE_ID_INTEL_82801EB_11:
 			case PCI_DEVICE_ID_INTEL_82801E_11:
 				p += sprintf(p, "PIIX4 Ultra 100 ");
 				break;
@@ -279,7 +281,9 @@
 		case PCI_DEVICE_ID_INTEL_82801CA_10:
 		case PCI_DEVICE_ID_INTEL_82801CA_11:
 		case PCI_DEVICE_ID_INTEL_82801E_11:
+		case PCI_DEVICE_ID_INTEL_82801DB_10:
 		case PCI_DEVICE_ID_INTEL_82801DB_11:
+		case PCI_DEVICE_ID_INTEL_82801EB_11:
 			mode = 3;
 			break;
 		/* UDMA 66 capable */
@@ -551,7 +555,7 @@
 
 	drive->init_speed = 0;
 
-	if (id && (id->capability & 1) && drive->autodma) {
+	if ((id->capability & 1) && drive->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (hwif->ide_dma_bad_drive(drive))
 			goto fast_ata_pio;
@@ -605,7 +609,9 @@
 		case PCI_DEVICE_ID_INTEL_82801BA_9:
 		case PCI_DEVICE_ID_INTEL_82801CA_10:
 		case PCI_DEVICE_ID_INTEL_82801CA_11:
+		case PCI_DEVICE_ID_INTEL_82801DB_10:
 		case PCI_DEVICE_ID_INTEL_82801DB_11:
+		case PCI_DEVICE_ID_INTEL_82801EB_11:
 		case PCI_DEVICE_ID_INTEL_82801E_11:
 		{
 			unsigned int extra = 0;
@@ -794,7 +800,9 @@
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
 	{ 0, },
 };
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/piix.h linux-2.5.65-bk3/drivers/ide/pci/piix.h
--- linux-2.5.65-bk2/drivers/ide/pci/piix.h	Mon Mar 17 13:43:46 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/piix.h	Mon Mar 31 12:41:40 2003
@@ -251,11 +251,53 @@
 		.extra		= 0,
 	},{	/* 15 */
 		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801EB_11,
+		.name		= "ICH5",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
+	},{	/* 16 */
+		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_82801E_11,
 		.name		= "C-ICH",
 		.init_setup	= init_setup_piix,
 		.init_chipset	= init_chipset_piix,
 		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
+	},{	/* 17 */
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801DB_10,
+		.name		= "ICH4",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
+	},{	/* 17 */
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801DB_10,
+		.name		= "ICH4",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
 		.init_hwif	= init_hwif_piix,
 		.init_dma	= init_dma_piix,
 		.channels	= 2,
diff -urN linux-2.5.65-bk2/drivers/ide/pci/sc1200.c linux-2.5.65-bk3/drivers/ide/pci/sc1200.c
--- linux-2.5.65-bk2/drivers/ide/pci/sc1200.c	Mon Mar 17 13:44:09 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/sc1200.c	Mon Mar 31 12:41:40 2003
@@ -87,6 +87,7 @@
 {
 	char *p = buffer;
 	unsigned long bibma = pci_resource_start(bmide_dev, 4);
+	int len;
 	u8  c0 = 0, c1 = 0;
 
 	/*
@@ -111,7 +112,10 @@
 	p += sprintf(p, "DMA\n");
 	p += sprintf(p, "PIO\n");
 
-	return p-buffer;
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 #endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/serverworks.c linux-2.5.65-bk3/drivers/ide/pci/serverworks.c
--- linux-2.5.65-bk2/drivers/ide/pci/serverworks.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/serverworks.c	Mon Mar 31 12:41:40 2003
@@ -57,7 +57,7 @@
 static int svwks_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	int i;
+	int i, len;
 
 	p += sprintf(p, "\n                             "
 			"ServerWorks OSB4/CSB5/CSB6\n");
@@ -195,7 +195,11 @@
 	}
 	p += sprintf(p, "\n");
 
-	return p-buffer;	 /* => must be less than 4k! */
+	/* p - buffer must be less than 4k! */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 #endif  /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/siimage.c linux-2.5.65-bk3/drivers/ide/pci/siimage.c
--- linux-2.5.65-bk2/drivers/ide/pci/siimage.c	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/siimage.c	Mon Mar 31 12:41:40 2003
@@ -55,6 +55,7 @@
 static int siimage_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
+	int len;
 	u16 i;
 
 	p += sprintf(p, "\n");
@@ -62,7 +63,11 @@
 		struct pci_dev *dev	= siimage_devs[i];
 		p = print_siimage_get_info(p, dev, i);
 	}
-	return p-buffer;	/* => must be less than 4k! */
+	/* p - buffer must be less than 4k! */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 
 #endif	/* defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) */
diff -urN linux-2.5.65-bk2/drivers/ide/pci/sis5513.c linux-2.5.65-bk3/drivers/ide/pci/sis5513.c
--- linux-2.5.65-bk2/drivers/ide/pci/sis5513.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/sis5513.c	Mon Mar 31 12:41:40 2003
@@ -424,6 +424,7 @@
 static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
+	int len;
 	u8 reg;
 	u16 reg2, reg3;
 
@@ -494,7 +495,10 @@
 	p = get_masters_info(p);
 	p = get_slaves_info(p);
 
-	return p-buffer;
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 #endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/slc90e66.c linux-2.5.65-bk3/drivers/ide/pci/slc90e66.c
--- linux-2.5.65-bk2/drivers/ide/pci/slc90e66.c	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/slc90e66.c	Mon Mar 31 12:41:40 2003
@@ -34,8 +34,9 @@
 static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
+	int len;
 	unsigned long bibma = pci_resource_start(bmide_dev, 4);
-        u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
+	u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
 	u8  c0 = 0, c1 = 0;
 	u8  reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0;
 
@@ -110,7 +111,11 @@
  *	FIXME.... Add configuration junk data....blah blah......
  */
 
-	return p-buffer;	 /* => must be less than 4k! */
+	/* p - buffer must be less than 4k! */
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+	
+	return len > count ? count : len;
 }
 #endif  /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */
 
diff -urN linux-2.5.65-bk2/drivers/ide/pci/via82cxxx.c linux-2.5.65-bk3/drivers/ide/pci/via82cxxx.c
--- linux-2.5.65-bk2/drivers/ide/pci/via82cxxx.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/drivers/ide/pci/via82cxxx.c	Mon Mar 31 12:41:40 2003
@@ -140,6 +140,7 @@
 		 uen[4], udma[4], umul[4], active8b[4], recover8b[4];
 	struct pci_dev *dev = bmide_dev;
 	unsigned int v, u, i;
+	int len;
 	u16 c, w;
 	u8 t, x;
 	char *p = buffer;
@@ -269,7 +270,10 @@
 		speed[i] / 1000, speed[i] / 100 % 10);
 
 	/* hoping it is less than 4K... */
-	return p - buffer;
+	len = (p - buffer) - offset;
+	*addr = buffer + offset;
+
+	return len > count ? count : len;
 }
 
 #endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */
diff -urN linux-2.5.65-bk2/drivers/macintosh/mac_hid.c linux-2.5.65-bk3/drivers/macintosh/mac_hid.c
--- linux-2.5.65-bk2/drivers/macintosh/mac_hid.c	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk3/drivers/macintosh/mac_hid.c	Mon Mar 31 12:41:40 2003
@@ -25,38 +25,56 @@
 
 #if defined(CONFIG_SYSCTL)
 /* file(s) in /proc/sys/dev/mac_hid */
-ctl_table mac_hid_files[] =
-{
-  {
-    DEV_MAC_HID_MOUSE_BUTTON_EMULATION,
-    "mouse_button_emulation", &mouse_emulate_buttons, sizeof(int),
-    0644, NULL, &proc_dointvec
-  },
-  {
-    DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE,
-    "mouse_button2_keycode", &mouse_button2_keycode, sizeof(int),
-    0644, NULL, &proc_dointvec
-  },
-  {
-    DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE,
-    "mouse_button3_keycode", &mouse_button3_keycode, sizeof(int),
-    0644, NULL, &proc_dointvec
-  },
-  { 0 }
+ctl_table mac_hid_files[] = {
+	{
+		.ctl_name	= DEV_MAC_HID_MOUSE_BUTTON_EMULATION,
+		.procname	= "mouse_button_emulation",
+		.data		= &mouse_emulate_buttons,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE,
+		.procname	= "mouse_button2_keycode",
+		.data		= &mouse_button2_keycode,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE,
+		.procname	= "mouse_button3_keycode",
+		.data		= &mouse_button3_keycode,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{ .ctl_name = 0 }
 };
 
 /* dir in /proc/sys/dev */
-ctl_table mac_hid_dir[] =
-{
-  { DEV_MAC_HID, "mac_hid", NULL, 0, 0555, mac_hid_files },
-  { 0 }
+ctl_table mac_hid_dir[] = {
+	{
+		.ctl_name	= DEV_MAC_HID,
+		.procname	= "mac_hid",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= mac_hid_files,
+	},
+	{ .ctl_name = 0 }
 };
 
 /* /proc/sys/dev itself, in case that is not there yet */
-ctl_table mac_hid_root_dir[] =
-{
-  { CTL_DEV, "dev", NULL, 0, 0555, mac_hid_dir },
-  { 0 }
+ctl_table mac_hid_root_dir[] = {
+	{
+		.ctl_name	= CTL_DEV,
+		.procname	= "dev",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= mac_hid_dir,
+	},
+	{ .ctl_name = 0 }
 };
 
 static struct ctl_table_header *mac_hid_sysctl_header;
diff -urN linux-2.5.65-bk2/drivers/media/dvb/dvb-core/Kconfig linux-2.5.65-bk3/drivers/media/dvb/dvb-core/Kconfig
--- linux-2.5.65-bk2/drivers/media/dvb/dvb-core/Kconfig	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/drivers/media/dvb/dvb-core/Kconfig	Mon Mar 31 12:41:40 2003
@@ -5,13 +5,3 @@
 	  DVB core utility functions for device handling, software fallbacks etc.
 
 	  Say Y when you have a DVB card and want to use it. If unsure say N.
-
-config DVB_DEVFS_ONLY
-	bool "devfs only"
-	depends on DVB_CORE=y && DEVFS_FS
-	help
-	  Drop support for old major/minor device scheme and support only devfs 
-	  systems. This saves some code.
-
-	  If unsure say N.
-
diff -urN linux-2.5.65-bk2/drivers/media/dvb/dvb-core/dvbdev.c linux-2.5.65-bk3/drivers/media/dvb/dvb-core/dvbdev.c
--- linux-2.5.65-bk2/drivers/media/dvb/dvb-core/dvbdev.c	Mon Mar 17 13:43:46 2003
+++ linux-2.5.65-bk3/drivers/media/dvb/dvb-core/dvbdev.c	Mon Mar 31 12:41:40 2003
@@ -21,8 +21,6 @@
  *
  */
 
-/*#define CONFIG_DVB_DEVFS_ONLY 1*/
-
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
@@ -56,17 +54,8 @@
 };
 
 
-#ifdef CONFIG_DVB_DEVFS_ONLY
-
-	#define DVB_MAX_IDS              ~0
-	#define nums2minor(num,type,id)  0
-	#define DVB_DEVFS_FLAGS          (DEVFS_FL_DEFAULT|DEVFS_FL_AUTO_DEVNUM)
-
-#else
-
-	#define DVB_MAX_IDS              4
-	#define nums2minor(num,type,id)  ((num << 6) | (id << 4) | type)
-	#define DVB_DEVFS_FLAGS          (DEVFS_FL_DEFAULT)
+#define DVB_MAX_IDS              4
+#define nums2minor(num,type,id)  ((num << 6) | (id << 4) | type)
 
 
 static
@@ -234,8 +223,7 @@
 
 	sprintf(name, "%s%d", dnames[type], id);
 	dvbdev->devfs_handle = devfs_register(adap->devfs_handle, name,
-					      DVB_DEVFS_FLAGS,
-					      DVB_MAJOR,
+					      0, DVB_MAJOR,
 					      nums2minor(adap->num, type, id),
 					      S_IFCHR | S_IRUSR | S_IWUSR,
 					      dvbdev->fops, dvbdev);
diff -urN linux-2.5.65-bk2/drivers/media/radio/miropcm20-rds-core.c linux-2.5.65-bk3/drivers/media/radio/miropcm20-rds-core.c
--- linux-2.5.65-bk2/drivers/media/radio/miropcm20-rds-core.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/drivers/media/radio/miropcm20-rds-core.c	Mon Mar 31 12:41:40 2003
@@ -13,8 +13,6 @@
  *        RDS support for MiroSound PCM20 radio
  */
 
-#define _NO_VERSION_
-
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/string.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/bttv-cards.c linux-2.5.65-bk3/drivers/media/video/bttv-cards.c
--- linux-2.5.65-bk2/drivers/media/video/bttv-cards.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/drivers/media/video/bttv-cards.c	Mon Mar 31 12:41:40 2003
@@ -24,8 +24,6 @@
     
 */
 
-#define __NO_VERSION__ 1
-
 #include <linux/version.h>
 #include <linux/delay.h>
 #include <linux/module.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/bttv-if.c linux-2.5.65-bk3/drivers/media/video/bttv-if.c
--- linux-2.5.65-bk2/drivers/media/video/bttv-if.c	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk3/drivers/media/video/bttv-if.c	Mon Mar 31 12:41:40 2003
@@ -25,8 +25,6 @@
     
 */
 
-#define __NO_VERSION__ 1
-
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/bttv-risc.c linux-2.5.65-bk3/drivers/media/video/bttv-risc.c
--- linux-2.5.65-bk2/drivers/media/video/bttv-risc.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/drivers/media/video/bttv-risc.c	Mon Mar 31 12:41:40 2003
@@ -23,8 +23,6 @@
 
 */
 
-#define __NO_VERSION__ 1
-
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/cpia.c linux-2.5.65-bk3/drivers/media/video/cpia.c
--- linux-2.5.65-bk2/drivers/media/video/cpia.c	Mon Mar 17 13:44:20 2003
+++ linux-2.5.65-bk3/drivers/media/video/cpia.c	Mon Mar 31 12:41:40 2003
@@ -23,7 +23,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* #define _CPIA_DEBUG_		define for verbose debug output */
+/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
+/* #define _CPIA_DEBUG_  1 */  
+
 #include <linux/config.h>
 
 #include <linux/module.h>
@@ -1796,7 +1798,7 @@
 
 	retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
 	if (retval)
-		LOG("%x - failed\n", command);
+		DBG("%x - failed\n", command);
 
 	return retval;
 }
@@ -2174,7 +2176,7 @@
 		}
 		if (ll == 1) {
 			if (*ibuf != EOL) {
-				LOG("EOL not found giving up after %d/%d"
+				DBG("EOL not found giving up after %d/%d"
 				    " bytes\n", origsize-size, origsize);
 				return -1;
 			}
@@ -3158,7 +3160,8 @@
 
 static void put_cam(struct cpia_camera_ops* ops)
 {
-	module_put(ops->owner);
+	if (ops->owner)
+		module_put(ops->owner);
 }
 
 /* ------------------------- V4L interface --------------------- */
@@ -3173,16 +3176,15 @@
 		return -ENODEV;
 	}
 
+	if (cam->open_count > 0) {
+		DBG("Camera already open\n");
+		return -EBUSY;
+	}
+
 	if (!try_module_get(cam->ops->owner))
 		return -ENODEV;
 
 	down(&cam->busy_lock);
-	err = -EBUSY;
-	if (cam->open_count > 0) {
-		DBG("Camera already open\n");
-		goto oops;
-	}
-	
 	err = -ENOMEM;
 	if (!cam->raw_image) {
 		cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE);
@@ -3206,10 +3208,11 @@
 		cam->ops->close(cam->lowlevel_data);
 		goto oops;
 	}
-
-	if(signal_pending(current))
-		return -EINTR;
 	
+	err = -EINTR;
+	if(signal_pending(current))
+		goto oops;
+
 	/* Set ownership of /proc/cpia/videoX to current user */
 	if(cam->proc_entry)
 		cam->proc_entry->uid = current->uid;
@@ -3451,6 +3454,14 @@
 			cam->params.colourParams.contrast = 80;
 		}
 
+		/* Adjust flicker control if necessary */
+		if(cam->params.flickerControl.allowableOverExposure < 0)
+			cam->params.flickerControl.allowableOverExposure = 
+				-find_over_exposure(cam->params.colourParams.brightness);
+		if(cam->params.flickerControl.flickerMode != 0)
+			cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
+		
+
 		/* queue command to update camera */
 		cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
 		up(&cam->param_lock);
@@ -3600,7 +3611,7 @@
 	{
 		int *frame = arg;
 
-		//DBG("VIDIOCSYNC: %d\n", frame);
+		//DBG("VIDIOCSYNC: %d\n", *frame);
 
 		if (*frame<0 || *frame >= FRAME_NUM) {
 			retval = -EINVAL;
@@ -3628,52 +3639,53 @@
 	}
 
 	case VIDIOCGCAPTURE:
+	{
+		struct video_capture *vc = arg;
+
 		DBG("VIDIOCGCAPTURE\n");
-		if (copy_to_user(arg, &cam->vc, sizeof(struct video_capture)))
-			retval = -EFAULT;
+
+		*vc = cam->vc;
+
 		break;
+	}	
 
 	case VIDIOCSCAPTURE:
 	{
-		struct video_capture vc;
+		struct video_capture *vc = arg;
 
 		DBG("VIDIOCSCAPTURE\n");
-		if (copy_from_user(&vc, arg, sizeof(vc))) {
-			retval = -EFAULT;
-			break;
-		}
 
-		if (vc.decimation != 0) {    /* How should this be used? */
+		if (vc->decimation != 0) {    /* How should this be used? */
 			retval = -EINVAL;
 			break;
 		}
-		if (vc.flags != 0) {     /* Even/odd grab not supported */
+		if (vc->flags != 0) {     /* Even/odd grab not supported */
 			retval = -EINVAL;
 			break;
 		}
 		
 		/* Clip to the resolution we can set for the ROI
 		   (every 8 columns and 4 rows) */
-		vc.x      = vc.x      & ~(__u32)7;
-		vc.y      = vc.y      & ~(__u32)3;
-		vc.width  = vc.width  & ~(__u32)7;
-		vc.height = vc.height & ~(__u32)3;
-
-		if(vc.width == 0 || vc.height == 0 ||
-		   vc.x + vc.width  > cam->vw.width ||
-		   vc.y + vc.height > cam->vw.height) {
+		vc->x      = vc->x      & ~(__u32)7;
+		vc->y      = vc->y      & ~(__u32)3;
+		vc->width  = vc->width  & ~(__u32)7;
+		vc->height = vc->height & ~(__u32)3;
+
+		if(vc->width == 0 || vc->height == 0 ||
+		   vc->x + vc->width  > cam->vw.width ||
+		   vc->y + vc->height > cam->vw.height) {
 			retval = -EINVAL;
 			break;
 		}
 
-		DBG("%d,%d/%dx%d\n", vc.x,vc.y,vc.width, vc.height);
+		DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height);
 		
 		down(&cam->param_lock);
 		
-		cam->vc.x      = vc.x;
-		cam->vc.y      = vc.y;
-		cam->vc.width  = vc.width;
-		cam->vc.height = vc.height;
+		cam->vc.x      = vc->x;
+		cam->vc.y      = vc->y;
+		cam->vc.width  = vc->width;
+		cam->vc.height = vc->height;
 		
 		set_vw_size(cam);
 		cam->cmd_queue |= COMMAND_SETFORMAT;
@@ -3688,16 +3700,20 @@
 	
 	case VIDIOCGUNIT:
 	{
-		struct video_unit vu;
-		vu.video    = cam->vdev.minor;
-		vu.vbi      = VIDEO_NO_UNIT;
-		vu.radio    = VIDEO_NO_UNIT;
-		vu.audio    = VIDEO_NO_UNIT;
-		vu.teletext = VIDEO_NO_UNIT;
+		struct video_unit *vu = arg;
+
+		DBG("VIDIOCGUNIT\n");
+
+		vu->video    = cam->vdev.minor;
+		vu->vbi      = VIDEO_NO_UNIT;
+		vu->radio    = VIDEO_NO_UNIT;
+		vu->audio    = VIDEO_NO_UNIT;
+		vu->teletext = VIDEO_NO_UNIT;
+
 		break;
 	}
-		
 
+		
 	/* pointless to implement overlay with this camera */
 	case VIDIOCCAPTURE:
 	case VIDIOCGFBUF:
@@ -3728,12 +3744,13 @@
 	return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl);
 }
 
+
 /* FIXME */
 static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct video_device *dev = file->private_data;
 	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
+	unsigned long size  = vma->vm_end - vma->vm_start;
 	unsigned long page, pos;
 	struct cam_data *cam = dev->priv;
 	int retval;
@@ -3956,9 +3973,6 @@
 		printk(KERN_DEBUG "video_register_device failed\n");
 		return NULL;
 	}
-#ifdef CONFIG_PROC_FS
-	create_proc_cpia_cam(camera);
-#endif
 
 	/* get version information from camera: open/reset/close */
 
@@ -3975,6 +3989,10 @@
 	/* close cpia */
 	camera->ops->close(camera->lowlevel_data);
 
+#ifdef CONFIG_PROC_FS
+	create_proc_cpia_cam(camera);
+#endif
+
 	printk(KERN_INFO "  CPiA Version: %d.%02d (%d.%d)\n",
 	       camera->params.version.firmwareVersion,
 	       camera->params.version.firmwareRevision,
@@ -3997,6 +4015,7 @@
 	DBG("unregistering video\n");
 	video_unregister_device(&cam->vdev);
 	if (cam->open_count) {
+		put_cam(cam->ops);
 		DBG("camera open -- setting ops to NULL\n");
 		cam->ops = NULL;
 	}
@@ -4019,9 +4038,6 @@
 	proc_cpia_create();
 #endif
 
-#ifdef CONFIG_VIDEO_CPIA_PP
-	cpia_pp_init();
-#endif
 #ifdef CONFIG_KMOD
 #ifdef CONFIG_VIDEO_CPIA_PP_MODULE
 	request_module("cpia_pp");
@@ -4031,6 +4047,10 @@
 	request_module("cpia_usb");
 #endif
 #endif	/* CONFIG_KMOD */
+
+#ifdef CONFIG_VIDEO_CPIA_PP
+	cpia_pp_init();
+#endif
 #ifdef CONFIG_VIDEO_CPIA_USB
 	cpia_usb_init();
 #endif
diff -urN linux-2.5.65-bk2/drivers/media/video/cpia.h linux-2.5.65-bk3/drivers/media/video/cpia.h
--- linux-2.5.65-bk2/drivers/media/video/cpia.h	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/drivers/media/video/cpia.h	Mon Mar 31 12:41:40 2003
@@ -27,12 +27,16 @@
  */
 
 #define CPIA_MAJ_VER	1
-#define CPIA_MIN_VER    2
-#define CPIA_PATCH_VER	2
+#define CPIA_MIN_VER   2
+#define CPIA_PATCH_VER	3
 
-#define CPIA_PP_MAJ_VER       1
-#define CPIA_PP_MIN_VER       2
-#define CPIA_PP_PATCH_VER     2
+#define CPIA_PP_MAJ_VER       CPIA_MAJ_VER
+#define CPIA_PP_MIN_VER       CPIA_MIN_VER
+#define CPIA_PP_PATCH_VER     CPIA_PATCH_VER
+
+#define CPIA_USB_MAJ_VER      CPIA_MAJ_VER
+#define CPIA_USB_MIN_VER      CPIA_MIN_VER
+#define CPIA_USB_PATCH_VER    CPIA_PATCH_VER
 
 #define CPIA_MAX_FRAME_SIZE_UNALIGNED	(352 * 288 * 4)   /* CIF at RGB32 */
 #define CPIA_MAX_FRAME_SIZE	((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */
diff -urN linux-2.5.65-bk2/drivers/media/video/cpia_pp.c linux-2.5.65-bk3/drivers/media/video/cpia_pp.c
--- linux-2.5.65-bk2/drivers/media/video/cpia_pp.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/drivers/media/video/cpia_pp.c	Mon Mar 31 12:41:40 2003
@@ -22,6 +22,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
+/* #define _CPIA_DEBUG_  1 */  
+
 #include <linux/config.h>
 #include <linux/version.h>
 
@@ -34,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/smp_lock.h>
+#include <linux/sched.h>
 
 #include <linux/kmod.h>
 
@@ -49,68 +53,10 @@
 static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);
 static int cpia_pp_close(void *privdata);
 
-#define ABOUT "Parallel port driver for Vision CPiA based cameras"
 
-/* IEEE 1284 Compatiblity Mode signal names 	*/
-#define nStrobe		PARPORT_CONTROL_STROBE	  /* inverted */
-#define nAutoFd		PARPORT_CONTROL_AUTOFD	  /* inverted */
-#define nInit		PARPORT_CONTROL_INIT
-#define nSelectIn	PARPORT_CONTROL_SELECT
-#define IntrEnable	PARPORT_CONTROL_INTEN	  /* normally zero for no IRQ */
-#define DirBit		PARPORT_CONTROL_DIRECTION /* 0 = Forward, 1 = Reverse	*/
-
-#define nFault		PARPORT_STATUS_ERROR
-#define Select		PARPORT_STATUS_SELECT
-#define PError		PARPORT_STATUS_PAPEROUT
-#define nAck		PARPORT_STATUS_ACK
-#define Busy		PARPORT_STATUS_BUSY	  /* inverted */	
-
-/* some more */
-#define HostClk		nStrobe
-#define HostAck		nAutoFd
-#define nReverseRequest	nInit
-#define Active_1284	nSelectIn
-#define nPeriphRequest	nFault
-#define XFlag		Select
-#define nAckReverse	PError
-#define PeriphClk	nAck
-#define PeriphAck	Busy
-
-/* these can be used to correct for the inversion on some bits */
-#define STATUS_INVERSION_MASK	(Busy)
-#define CONTROL_INVERSION_MASK	(nStrobe|nAutoFd|nSelectIn)
-
-#define ECR_empty	0x01
-#define ECR_full	0x02
-#define ECR_serviceIntr 0x04
-#define ECR_dmaEn	0x08
-#define ECR_nErrIntrEn	0x10
-
-#define ECR_mode_mask	0xE0
-#define ECR_SPP_mode	0x00
-#define ECR_PS2_mode	0x20
-#define ECR_FIFO_mode	0x40
-#define ECR_ECP_mode	0x60
-
-#define ECP_FIFO_SIZE	16
-#define DMA_BUFFER_SIZE               PAGE_SIZE
-	/* for 16bit DMA make sure DMA_BUFFER_SIZE is 16 bit aligned */
-#define PARPORT_CHUNK_SIZE	PAGE_SIZE/* >=2.3.x */
-				/* we read this many bytes at once */
-
-#define GetECRMasked(port,mask)	(parport_read_econtrol(port) & (mask))
-#define GetStatus(port)		((parport_read_status(port)^STATUS_INVERSION_MASK)&(0xf8))
-#define SetStatus(port,val)	parport_write_status(port,(val)^STATUS_INVERSION_MASK)
-#define GetControl(port)	((parport_read_control(port)^CONTROL_INVERSION_MASK)&(0x3f))
-#define SetControl(port,val)	parport_write_control(port,(val)^CONTROL_INVERSION_MASK)
-
-#define GetStatusMasked(port,mask)	(GetStatus(port) & (mask))
-#define GetControlMasked(port,mask)	(GetControl(port) & (mask))
-#define SetControlMasked(port,mask)	SetControl(port,GetControl(port) | (mask));
-#define ClearControlMasked(port,mask)	SetControl(port,GetControl(port)&~(mask));
-#define FrobControlBit(port,mask,value)	SetControl(port,(GetControl(port)&~(mask))|((value)&(mask)));
+#define ABOUT "Parallel port driver for Vision CPiA based cameras"
 
-#define PACKET_LENGTH 	8
+#define PACKET_LENGTH  8
 
 /* Magic numbers for defining port-device mappings */
 #define PPCPIA_PARPORT_UNSPEC -4
@@ -162,30 +108,7 @@
 };
 
 static LIST_HEAD(cam_list);
-static spinlock_t cam_list_lock_pp = SPIN_LOCK_UNLOCKED;
-
-#ifdef _CPIA_DEBUG_
-#define DEB_PORT(port) { \
-u8 controll = GetControl(port); \
-u8 statusss = GetStatus(port); \
-DBG("nsel %c per %c naut %c nstrob %c nak %c busy %c nfaul %c sel %c init %c dir %c\n",\
-((controll & nSelectIn)	? 'U' : 'D'), \
-((statusss & PError)	? 'U' : 'D'), \
-((controll & nAutoFd)	? 'U' : 'D'), \
-((controll & nStrobe)	? 'U' : 'D'), \
-((statusss & nAck)	? 'U' : 'D'), \
-((statusss & Busy)	? 'U' : 'D'), \
-((statusss & nFault)	? 'U' : 'D'), \
-((statusss & Select)	? 'U' : 'D'), \
-((controll & nInit)	? 'U' : 'D'), \
-((controll & DirBit)	? 'R' : 'F')  \
-); }
-#else
-#define DEB_PORT(port) {}
-#endif
-
-#define WHILE_OUT_TIMEOUT (HZ/10)
-#define DMA_TIMEOUT 10*HZ
+static spinlock_t cam_list_lock_pp;
 
 /* FIXME */
 static void cpia_parport_enable_irq( struct parport *port ) {
@@ -200,6 +123,205 @@
 	return;
 }
 
+/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility
+ * Link Flag during negotiation */  
+#define UPLOAD_FLAG  0x08
+#define NIBBLE_TRANSFER 0x01
+#define ECP_TRANSFER 0x03
+
+#define PARPORT_CHUNK_SIZE	PAGE_SIZE
+
+
+/****************************************************************************
+ *
+ *  CPiA-specific  low-level parport functions for nibble uploads
+ *
+ ***************************************************************************/
+/*  CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */
+/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */
+
+static size_t cpia_read_nibble (struct parport *port, 
+			 void *buffer, size_t len, 
+			 int flags)
+{
+	/* adapted verbatim, with one change, from 
+	   parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */
+
+	unsigned char *buf = buffer;
+	int i;
+	unsigned char byte = 0;
+	
+	len *= 2; /* in nibbles */
+	for (i=0; i < len; i++) {
+		unsigned char nibble;
+
+		/* The CPiA firmware suppresses the use of nDataAvail (nFault LO)
+		 * after every second nibble to signal that more
+		 * data is available.  (the total number of Bytes that
+		 * should be sent is known; if too few are received, an error
+		 * will be recorded after a timeout).  
+		 * This is incompatible with parport_ieee1284_read_nibble(),
+		 * which expects to find nFault LO after every second nibble.
+		 */
+
+		/* Solution: modify cpia_read_nibble to only check for 
+		 * nDataAvail before the first nibble is sent.
+		 */
+
+		/* Does the error line indicate end of data? */
+		if (((i /*& 1*/) == 0) &&
+		    (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
+			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+				DBG("%s: No more nibble data (%d bytes)\n",
+				port->name, i/2);
+
+			/* Go to reverse idle phase. */
+			parport_frob_control (port,
+					      PARPORT_CONTROL_AUTOFD,
+					      PARPORT_CONTROL_AUTOFD);
+			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+			break;
+		}
+
+		/* Event 7: Set nAutoFd low. */
+		parport_frob_control (port,
+				      PARPORT_CONTROL_AUTOFD,
+				      PARPORT_CONTROL_AUTOFD);
+
+		/* Event 9: nAck goes low. */
+		port->ieee1284.phase = IEEE1284_PH_REV_DATA;
+		if (parport_wait_peripheral (port,
+					     PARPORT_STATUS_ACK, 0)) {
+			/* Timeout -- no more data? */
+				 DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
+				 port->name, i/2);
+			parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+			break;
+		}
+
+
+		/* Read a nibble. */
+		nibble = parport_read_status (port) >> 3;
+		nibble &= ~8;
+		if ((nibble & 0x10) == 0)
+			nibble |= 8;
+		nibble &= 0xf;
+
+		/* Event 10: Set nAutoFd high. */
+		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+
+		/* Event 11: nAck goes high. */
+		if (parport_wait_peripheral (port,
+					     PARPORT_STATUS_ACK,
+					     PARPORT_STATUS_ACK)) {
+			/* Timeout -- no more data? */
+			DBG("%s: Nibble timeout at event 11\n",
+				 port->name);
+			break;
+		}
+
+		if (i & 1) {
+			/* Second nibble */
+			byte |= nibble << 4;
+			*buf++ = byte;
+		} else 
+			byte = nibble;
+	}
+
+	i /= 2; /* i is now in bytes */
+
+	if (i == len) {
+		/* Read the last nibble without checking data avail. */
+		port = port->physport;
+		if (parport_read_status (port) & PARPORT_STATUS_ERROR)
+			port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+		else
+			port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+	}
+
+	return i;
+}
+
+/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
+ * (See CPiA Data sheet p. 31) 
+ * 
+ * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a 
+ * nonstandard variant of nibble mode which allows the same (mediocre) 
+ * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable 
+ * parallel ports, but works also for  non-TRISTATE-capable ports.
+ * (Standard nibble mode only send 4 bits per cycle)
+ *
+ */
+
+static size_t cpia_read_nibble_stream(struct parport *port, 
+			       void *buffer, size_t len, 
+			       int flags)
+{
+	int i;
+	unsigned char *buf = buffer;
+	int endseen = 0;
+
+	for (i=0; i < len; i++) {
+		unsigned char nibble[2], byte = 0;
+		int j;
+
+		/* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */ 
+		if (endseen > 3 )
+			break;
+
+		/* Event 7: Set nAutoFd low. */
+		parport_frob_control (port,
+				      PARPORT_CONTROL_AUTOFD,
+				      PARPORT_CONTROL_AUTOFD);
+		
+		/* Event 9: nAck goes low. */
+		port->ieee1284.phase = IEEE1284_PH_REV_DATA;
+		if (parport_wait_peripheral (port,
+					     PARPORT_STATUS_ACK, 0)) {
+			/* Timeout -- no more data? */
+				 DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
+				 port->name, i/2);
+			parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+			break;
+		}
+
+		/* Read lower nibble */
+		nibble[0] = parport_read_status (port) >>3;
+		
+		/* Event 10: Set nAutoFd high. */
+		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+
+		/* Event 11: nAck goes high. */
+		if (parport_wait_peripheral (port,
+					     PARPORT_STATUS_ACK,
+					     PARPORT_STATUS_ACK)) {
+			/* Timeout -- no more data? */
+			DBG("%s: Nibble timeout at event 11\n",
+				 port->name);
+			break;
+		}
+		
+		/* Read upper nibble */
+		nibble[1] = parport_read_status (port) >>3;
+		
+		/* reassemble the byte */
+		for (j = 0; j < 2 ; j++ ) {
+			nibble[j] &= ~8;
+			if ((nibble[j] & 0x10) == 0)
+				nibble[j] |= 8;
+			nibble[j] &= 0xf;
+		}
+		byte = (nibble[0] |(nibble[1] << 4));
+		*buf++ = byte;
+
+		if(byte == EOI)
+		  endseen++;
+		else
+		  endseen = 0;
+	}
+	return i;
+}
+
 /****************************************************************************
  *
  *  EndTransferMode
@@ -219,20 +341,25 @@
 {
 	int retry;
 	
-	/* After some commands the camera needs extra time before
-	 * it will respond again, so we try up to 3 times */
-	for(retry=0; retry<3; ++retry) {
+	/* The CPiA uses ECP protocol for Downloads from the Host to the camera. 
+	 * This will be software-emulated if ECP hardware is not present
+	 */
+
+	/* the usual camera maximum response time is 10ms, but after receiving
+	 * some commands, it needs up to 40ms. (Data Sheet p. 32)*/
+
+	for(retry = 0; retry < 4; ++retry) {
 		if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) {
 			break;
 		}
+		mdelay(10);
 	}
-	if(retry == 3) {
-		DBG("Unable to negotiate ECP mode\n");
+	if(retry == 4) {
+		DBG("Unable to negotiate IEEE1284 ECP Download mode\n");
 		return -1;
 	}
 	return 0;
 }
-
 /****************************************************************************
  *
  *  ReverseSetup
@@ -241,24 +368,35 @@
 static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
 {
 	int retry;
-	int mode = IEEE1284_MODE_ECP;
-	if(extensibility) mode = 8|3|IEEE1284_EXT_LINK;
+	int upload_mode, mode = IEEE1284_MODE_ECP;
+	int transfer_mode = ECP_TRANSFER;
 
-	/* After some commands the camera needs extra time before
-	 * it will respond again, so we try up to 3 times */
-	for(retry=0; retry<3; ++retry) {
+	if (!(cam->port->modes & PARPORT_MODE_ECP) &&
+	     !(cam->port->modes & PARPORT_MODE_TRISTATE)) {
+		mode = IEEE1284_MODE_NIBBLE;
+		transfer_mode = NIBBLE_TRANSFER;
+	}
+
+	upload_mode = mode;
+	if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK;
+
+	/* the usual camera maximum response time is 10ms, but after 
+	 * receiving some commands, it needs up to 40ms. */
+		
+	for(retry = 0; retry < 4; ++retry) {
 		if(!parport_negotiate(cam->port, mode)) {
 			break;
 		}
+		mdelay(10);
 	}
-	if(retry == 3) {
+	if(retry == 4) {
 		if(extensibility)
-			DBG("Unable to negotiate extensibility mode\n");
+			DBG("Unable to negotiate upload extensibility mode\n");
 		else
-			DBG("Unable to negotiate ECP mode\n");
+			DBG("Unable to negotiate upload mode\n");
 		return -1;
 	}
-	if(extensibility) cam->port->ieee1284.mode = IEEE1284_MODE_ECP;
+	if(extensibility) cam->port->ieee1284.mode = upload_mode;
 	return 0;
 }
 
@@ -296,14 +434,21 @@
 static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
 {
 	int retval=0;
+
 	if (packet == NULL) {
 		return -EINVAL;
 	}
 	if (ReverseSetup(cam, 0)) {
 		return -EIO;
 	}
-	if(parport_read(cam->port, packet, size) != size) {
-		retval = -EIO;
+
+	/* support for CPiA variant nibble reads */
+	if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) {
+		if(cpia_read_nibble(cam->port, packet, size, 0) != size) 
+			retval = -EIO;			
+	} else {
+		if(parport_read(cam->port, packet, size) != size) 
+			retval = -EIO;
 	}
 	EndTransferMode(cam);
 	return retval;
@@ -347,11 +492,29 @@
  *  cpia_pp_streamRead
  *
  ***************************************************************************/
+static int cpia_pp_read(struct parport *port, u8 *buffer, int len)
+{
+	int bytes_read;
+
+	/* support for CPiA variant "nibble stream" reads */
+	if(port->ieee1284.mode == IEEE1284_MODE_NIBBLE)
+		bytes_read = cpia_read_nibble_stream(port,buffer,len,0);
+	else {
+		int new_bytes;
+		for(bytes_read=0; bytes_read<len; bytes_read += new_bytes) {
+			new_bytes = parport_read(port, buffer+bytes_read,
+						 len-bytes_read);
+			if(new_bytes < 0) break;
+		}
+	}
+	return bytes_read;
+}
+
 static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
 {
 	struct pp_cam_entry *cam = privdata;
 	int read_bytes = 0;
-	int i, endseen;
+	int i, endseen, block_size, new_bytes;
 
 	if(cam == NULL) {
 		DBG("Internal driver error: cam is NULL\n");
@@ -380,27 +543,36 @@
 			return -EIO;
 		}
 	}
-	read_bytes = parport_read(cam->port, buffer, CPIA_MAX_IMAGE_SIZE );
-
-	EndTransferMode(cam);
-	DBG("read %d bytes\n", read_bytes);
-	if( read_bytes<0) return -EIO;
 	endseen = 0;
-	for( i=0; i<read_bytes && endseen<4; i++ ) {
-	  if( *buffer==EOI ) {
-	    endseen++;
-	  } else {
-	    endseen=0;
-	  }
-	  buffer++;
-	}
-	if( endseen>3 ) {
-	  cam->image_complete=1;
-	  DBG("endseen at %d bytes\n", i);
- 	}
+	block_size = PARPORT_CHUNK_SIZE;
+	while( !cam->image_complete ) {
+		cond_resched();
+		
+		new_bytes = cpia_pp_read(cam->port, buffer, block_size );
+		if( new_bytes <= 0 ) {
+			break;
+		}
+		i=-1;
+		while(++i<new_bytes && endseen<4) {
+	        	if(*buffer==EOI) {
+	                	endseen++;
+	                } else {
+	                	endseen=0;
+	                }
+			buffer++;
+		}
+		read_bytes += i;
+		if( endseen==4 ) {
+			cam->image_complete=1;
+			break;
+		}
+		if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) {
+			block_size=CPIA_MAX_IMAGE_SIZE-read_bytes;
+		}
+	}
+	EndTransferMode(cam);
 	return cam->image_complete ? read_bytes : -EIO;
 }
-
 /****************************************************************************
  *
  *  cpia_pp_transferCmd
@@ -530,9 +702,8 @@
 	struct pp_cam_entry *cam;
 	struct cam_data *cpia;
 
-	if (!(port->modes & PARPORT_MODE_ECP) &&
-	    !(port->modes & PARPORT_MODE_TRISTATE)) {
-		LOG("port is not ECP capable\n");
+	if (!(port->modes & PARPORT_MODE_PCSPP)) {
+		LOG("port is not supported by CPiA driver\n");
 		return -ENXIO;
 	}
 
@@ -575,29 +746,33 @@
 static void cpia_pp_detach (struct parport *port)
 {
 	struct list_head *tmp;
-	struct cam_data *cpia;
+	struct cam_data *cpia = NULL;
 	struct pp_cam_entry *cam;
 
 	spin_lock( &cam_list_lock_pp );
 	list_for_each (tmp, &cam_list) {
 		cpia = list_entry(tmp, struct cam_data, cam_data_list);
-		cam = cpia->lowlevel_data;
+		cam = (struct pp_cam_entry *) cpia->lowlevel_data;
 		if (cam && cam->port->number == port->number) {
 			list_del(&cpia->cam_data_list);
-			cpia_unregister_camera(cpia);
-			
-			if(cam->open_count > 0) {
-				cpia_pp_close(cam);
-			}
-
-			parport_unregister_device(cam->pdev);
-		
-			kfree(cam);
-			cpia->lowlevel_data = NULL;
 			break;
 		}
+		cpia = NULL;
 	}
 	spin_unlock( &cam_list_lock_pp );			
+
+	if (!cpia) {
+		DBG("cpia_pp_detach failed to find cam_data in cam_list\n");
+		return;
+	}
+	
+	cam = (struct pp_cam_entry *) cpia->lowlevel_data;	
+	cpia_unregister_camera(cpia);
+	if(cam->open_count > 0) 
+		cpia_pp_close(cam);
+	parport_unregister_device(cam->pdev);
+	cpia->lowlevel_data = NULL;	
+	kfree(cam);
 }
 
 static void cpia_pp_attach (struct parport *port)
@@ -645,11 +820,12 @@
 		return 0;
 	}
 	
+	spin_lock_init( &cam_list_lock_pp );
+
 	if (parport_register_driver (&cpia_pp_driver)) {
 		LOG ("unable to register with parport\n");
 		return -EIO;
 	}
-	
 	return 0;
 }
 
diff -urN linux-2.5.65-bk2/drivers/media/video/cpia_usb.c linux-2.5.65-bk3/drivers/media/video/cpia_usb.c
--- linux-2.5.65-bk2/drivers/media/video/cpia_usb.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/drivers/media/video/cpia_usb.c	Mon Mar 31 12:41:40 2003
@@ -21,11 +21,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
+/* #define _CPIA_DEBUG_  1 */  
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
@@ -105,7 +107,7 @@
 };
 
 static LIST_HEAD(cam_list);
-static spinlock_t cam_list_lock_usb = SPIN_LOCK_UNLOCKED;
+static spinlock_t cam_list_lock_usb;
 
 static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
 {
@@ -464,12 +466,14 @@
 {
 	struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
 
-	ucpia->open = 0;
+	if(!ucpia)
+		return -ENODEV;
 
-	cpia_usb_free_resources(ucpia, 1);
+	ucpia->open = 0;
 
-	if (!ucpia->present)
-		kfree(ucpia);
+	/* ucpia->present = 0 protects against trying to reset the
+	 * alt setting if camera is physically disconnected while open */
+	cpia_usb_free_resources(ucpia, ucpia->present);
 
 	return 0;
 }
@@ -565,7 +569,7 @@
 	vfree(ucpia->buffers[0]);
 	ucpia->buffers[0] = NULL;
 fail_alloc_0:
-
+	kfree(ucpia);
 	return -EIO;
 }
 
@@ -588,9 +592,6 @@
 	.id_table	= cpia_id_table,
 };
 
-/* don't use dev, it may be NULL! (see usb_cpia_cleanup) */
-/* _disconnect from usb_cpia_cleanup is not necessary since usb_deregister */
-/* will do it for us as well as passing a udev structure - jerdfelt */
 static void cpia_disconnect(struct usb_interface *intf)
 {
 	struct cam_data *cam = usb_get_intfdata(intf);
@@ -606,12 +607,11 @@
 	list_del(&cam->cam_data_list);
 	spin_unlock( &cam_list_lock_usb );
 	
-	/* Don't even try to reset the altsetting if we're disconnected */
-	cpia_usb_free_resources(ucpia, 0);
-
 	ucpia->present = 0;
 
 	cpia_unregister_camera(cam);
+	if(ucpia->open)
+		cpia_usb_close(cam->lowlevel_data);
 
 	ucpia->curbuff->status = FRAME_ERROR;
 
@@ -639,29 +639,25 @@
 		ucpia->buffers[0] = NULL;
 	}
 
-	if (!ucpia->open) {
- 		kfree(ucpia);
-		cam->lowlevel_data = NULL;
-	}
+	cam->lowlevel_data = NULL;
+	kfree(ucpia);
 }
 
 static int __init usb_cpia_init(void)
 {
+	printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, 
+	       CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER);
+
+	spin_lock_init(&cam_list_lock_usb);
 	return usb_register(&cpia_driver);
 }
 
 static void __exit usb_cpia_cleanup(void)
 {
-/*
-	struct cam_data *cam;
-
-	while ((cam = cam_list) != NULL)
-		cpia_disconnect(NULL, cam);
-*/
-
 	usb_deregister(&cpia_driver);
 }
 
 
 module_init (usb_cpia_init);
 module_exit (usb_cpia_cleanup);
+
diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-i2c.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-i2c.c
--- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-i2c.c	Mon Mar 17 13:43:43 2003
+++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-i2c.c	Mon Mar 31 12:41:40 2003
@@ -19,8 +19,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define __NO_VERSION__ 1
-
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-oss.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-oss.c
--- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-oss.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-oss.c	Mon Mar 31 12:41:40 2003
@@ -19,8 +19,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define __NO_VERSION__ 1
-
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-ts.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-ts.c
--- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-ts.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-ts.c	Mon Mar 31 12:41:40 2003
@@ -19,8 +19,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define __NO_VERSION__ 1
-
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-tvaudio.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-tvaudio.c
--- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-tvaudio.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-tvaudio.c	Mon Mar 31 12:41:40 2003
@@ -19,8 +19,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define __NO_VERSION__ 1
-
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-vbi.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-vbi.c
--- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-vbi.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-vbi.c	Mon Mar 31 12:41:40 2003
@@ -19,8 +19,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define __NO_VERSION__ 1
-
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-video.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-video.c
--- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-video.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-video.c	Mon Mar 31 12:41:40 2003
@@ -19,8 +19,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define __NO_VERSION__ 1
-
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
diff -urN linux-2.5.65-bk2/drivers/media/video/w9966.c linux-2.5.65-bk3/drivers/media/video/w9966.c
--- linux-2.5.65-bk2/drivers/media/video/w9966.c	Mon Mar 17 13:43:48 2003
+++ linux-2.5.65-bk3/drivers/media/video/w9966.c	Mon Mar 31 12:41:40 2003
@@ -742,7 +742,7 @@
 	case VIDIOCGTUNER:
 	{
 		struct video_tuner *vtune = arg;
-		if(vtune->tuner != 0);
+		if(vtune->tuner != 0)
 			return -EINVAL;
 		strcpy(vtune->name, "no tuner");
 		vtune->rangelow = 0;
diff -urN linux-2.5.65-bk2/drivers/message/i2o/Kconfig linux-2.5.65-bk3/drivers/message/i2o/Kconfig
--- linux-2.5.65-bk2/drivers/message/i2o/Kconfig	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/drivers/message/i2o/Kconfig	Mon Mar 31 12:41:40 2003
@@ -3,6 +3,7 @@
 
 config I2O
 	tristate "I2O support"
+	depends on PCI
 	---help---
 	  The Intelligent Input/Output (I2O) architecture allows hardware
 	  drivers to be split into two parts: an operating system specific
diff -urN linux-2.5.65-bk2/drivers/message/i2o/Makefile linux-2.5.65-bk3/drivers/message/i2o/Makefile
--- linux-2.5.65-bk2/drivers/message/i2o/Makefile	Mon Mar 17 13:44:20 2003
+++ linux-2.5.65-bk3/drivers/message/i2o/Makefile	Mon Mar 31 12:41:40 2003
@@ -5,7 +5,6 @@
 # In the future, some of these should be built conditionally.
 #
 
-obj-$(CONFIG_I2O_PCI)	+= i2o_pci.o
 obj-$(CONFIG_I2O)	+= i2o_core.o i2o_config.o
 obj-$(CONFIG_I2O_BLOCK)	+= i2o_block.o
 obj-$(CONFIG_I2O_SCSI)	+= i2o_scsi.o
diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_block.c linux-2.5.65-bk3/drivers/message/i2o/i2o_block.c
--- linux-2.5.65-bk2/drivers/message/i2o/i2o_block.c	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk3/drivers/message/i2o/i2o_block.c	Mon Mar 31 12:41:41 2003
@@ -754,7 +754,7 @@
 				 * hit the fan big time. The card seems to recover but loses
 				 * the pending writes. Deeply ungood except for testing fsck
 				 */
-				if(i2ob_dev[unit].i2odev->controller->bus.pci.promise)
+				if(i2ob_dev[unit].i2odev->controller->promise)
 					panic("I2O controller firmware failed. Reboot and force a filesystem check.\n");
 			default:
 				printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n"
@@ -1140,10 +1140,10 @@
 		if(d->controller->battery == 0)
 			i2ob_dev[i].wcache = CACHE_WRITETHROUGH;
 
-		if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.promise)
+		if(d->controller->promise)
 			i2ob_dev[i].wcache = CACHE_WRITETHROUGH;
 
-		if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.short_req)
+		if(d->controller->short_req)
 		{
 			blk_queue_max_sectors(q, 8);
 			blk_queue_max_phys_segments(q, 8);
diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_core.c linux-2.5.65-bk3/drivers/message/i2o/i2o_core.c
--- linux-2.5.65-bk2/drivers/message/i2o/i2o_core.c	Mon Mar 17 13:44:14 2003
+++ linux-2.5.65-bk3/drivers/message/i2o/i2o_core.c	Mon Mar 31 12:41:41 2003
@@ -50,6 +50,9 @@
 
 #include <asm/io.h>
 #include <linux/reboot.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif // CONFIG_MTRR
 
 #include "i2o_lan.h"
 
@@ -103,6 +106,8 @@
 
 void i2o_report_controller_unit(struct i2o_controller *, struct i2o_device *);
 
+static void i2o_pci_dispose(struct i2o_controller *c);
+
 /*
  * I2O System Table.  Contains information about
  * all the IOPs in the system.  Used to inform IOPs
@@ -206,7 +211,6 @@
  */
 
 static int verbose;
-MODULE_PARM(verbose, "i");
 
 /*
  * I2O Core reply handler
@@ -549,7 +553,8 @@
 		if(__i2o_delete_device(c->devices)<0)
 		{
 			/* Shouldnt happen */
-			c->bus_disable(c);
+			I2O_IRQ_WRITE32(c, 0xFFFFFFFF);
+			c->enabled = 0;
 			up(&i2o_configuration_lock);
 			return -EBUSY;
 		}
@@ -584,7 +589,7 @@
 			i2o_reset_controller(c);
 
 			/* Release IRQ */
-			c->destructor(c);
+			i2o_pci_dispose(c);
 
 			*p=c->next;
 			up(&i2o_configuration_lock);
@@ -1651,7 +1656,7 @@
 
 	for (iop = i2o_controller_chain; iop; iop = iop->next)
 	{
-		if(iop->type != I2O_TYPE_PCI || !iop->bus.pci.dpt)
+		if(!iop->dpt)
 			i2o_quiesce_controller(iop);
 	}
 
@@ -1911,65 +1916,62 @@
 	u32 msg[12];
 	dma_addr_t sys_tbl_phys;
 	int ret;
+	struct resource *root;
 	u32 *privbuf = kmalloc(16, GFP_KERNEL);
 	if(privbuf == NULL)
 		return -ENOMEM;
 	
-	if(iop->type == I2O_TYPE_PCI)
-	{
-		struct resource *root;
 		
-		if(iop->status_block->current_mem_size < iop->status_block->desired_mem_size)
-		{
-			struct resource *res = &iop->mem_resource;
-			res->name = iop->pdev->bus->name;
-			res->flags = IORESOURCE_MEM;
-			res->start = 0;
-			res->end = 0;
-			printk("%s: requires private memory resources.\n", iop->name);
-			root = pci_find_parent_resource(iop->pdev, res);
-			if(root==NULL)
-				printk("Can't find parent resource!\n");
-			if(root && allocate_resource(root, res, 
-					iop->status_block->desired_mem_size,
-					iop->status_block->desired_mem_size,
-					iop->status_block->desired_mem_size,
-					1<<20,	/* Unspecified, so use 1Mb and play safe */
-					NULL,
-					NULL)>=0)
-			{
-				iop->mem_alloc = 1;
-				iop->status_block->current_mem_size = 1 + res->end - res->start;
-				iop->status_block->current_mem_base = res->start;
-				printk(KERN_INFO "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n", 
-					iop->name, 1+res->end-res->start, res->start);
-			}
-		}
-		if(iop->status_block->current_io_size < iop->status_block->desired_io_size)
-		{
-			struct resource *res = &iop->io_resource;
-			res->name = iop->pdev->bus->name;
-			res->flags = IORESOURCE_IO;
-			res->start = 0;
-			res->end = 0;
-			printk("%s: requires private memory resources.\n", iop->name);
-			root = pci_find_parent_resource(iop->pdev, res);
-			if(root==NULL)
-				printk("Can't find parent resource!\n");
-			if(root &&  allocate_resource(root, res, 
-					iop->status_block->desired_io_size,
-					iop->status_block->desired_io_size,
-					iop->status_block->desired_io_size,
-					1<<20,	/* Unspecified, so use 1Mb and play safe */
-					NULL,
-					NULL)>=0)
-			{
-				iop->io_alloc = 1;
-				iop->status_block->current_io_size = 1 + res->end - res->start;
-				iop->status_block->current_mem_base = res->start;
-				printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n", 
-					iop->name, 1+res->end-res->start, res->start);
-			}
+	if(iop->status_block->current_mem_size < iop->status_block->desired_mem_size)
+	{
+		struct resource *res = &iop->mem_resource;
+		res->name = iop->pdev->bus->name;
+		res->flags = IORESOURCE_MEM;
+		res->start = 0;
+		res->end = 0;
+		printk("%s: requires private memory resources.\n", iop->name);
+		root = pci_find_parent_resource(iop->pdev, res);
+		if(root==NULL)
+			printk("Can't find parent resource!\n");
+		if(root && allocate_resource(root, res, 
+				iop->status_block->desired_mem_size,
+				iop->status_block->desired_mem_size,
+				iop->status_block->desired_mem_size,
+				1<<20,	/* Unspecified, so use 1Mb and play safe */
+				NULL,
+				NULL)>=0)
+		{
+			iop->mem_alloc = 1;
+			iop->status_block->current_mem_size = 1 + res->end - res->start;
+			iop->status_block->current_mem_base = res->start;
+			printk(KERN_INFO "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n", 
+				iop->name, 1+res->end-res->start, res->start);
+		}
+	}
+	if(iop->status_block->current_io_size < iop->status_block->desired_io_size)
+	{
+		struct resource *res = &iop->io_resource;
+		res->name = iop->pdev->bus->name;
+		res->flags = IORESOURCE_IO;
+		res->start = 0;
+		res->end = 0;
+		printk("%s: requires private memory resources.\n", iop->name);
+		root = pci_find_parent_resource(iop->pdev, res);
+		if(root==NULL)
+			printk("Can't find parent resource!\n");
+		if(root &&  allocate_resource(root, res, 
+				iop->status_block->desired_io_size,
+				iop->status_block->desired_io_size,
+				iop->status_block->desired_io_size,
+				1<<20,	/* Unspecified, so use 1Mb and play safe */
+				NULL,
+				NULL)>=0)
+		{
+			iop->io_alloc = 1;
+			iop->status_block->current_io_size = 1 + res->end - res->start;
+			iop->status_block->current_mem_base = res->start;
+			printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n", 
+				iop->name, 1+res->end-res->start, res->start);
 		}
 	}
 	else
@@ -3427,48 +3429,256 @@
 }
 
 
-EXPORT_SYMBOL(i2o_controller_chain);
-EXPORT_SYMBOL(i2o_num_controllers);
-EXPORT_SYMBOL(i2o_find_controller);
-EXPORT_SYMBOL(i2o_unlock_controller);
-EXPORT_SYMBOL(i2o_status_get);
 
-EXPORT_SYMBOL(i2o_install_handler);
-EXPORT_SYMBOL(i2o_remove_handler);
 
-EXPORT_SYMBOL(i2o_install_controller);
-EXPORT_SYMBOL(i2o_delete_controller);
-EXPORT_SYMBOL(i2o_run_queue);
+/**
+ *	i2o_pci_dispose		-	Free bus specific resources
+ *	@c: I2O controller
+ *
+ *	Disable interrupts and then free interrupt, I/O and mtrr resources 
+ *	used by this controller. Called by the I2O core on unload.
+ */
+ 
+static void i2o_pci_dispose(struct i2o_controller *c)
+{
+	I2O_IRQ_WRITE32(c,0xFFFFFFFF);
+	if(c->irq > 0)
+		free_irq(c->irq, c);
+	iounmap(((u8 *)c->post_port)-0x40);
 
-EXPORT_SYMBOL(i2o_claim_device);
-EXPORT_SYMBOL(i2o_release_device);
-EXPORT_SYMBOL(i2o_device_notify_on);
-EXPORT_SYMBOL(i2o_device_notify_off);
+#ifdef CONFIG_MTRR
+	if(c->mtrr_reg0 > 0)
+		mtrr_del(c->mtrr_reg0, 0, 0);
+	if(c->mtrr_reg1 > 0)
+		mtrr_del(c->mtrr_reg1, 0, 0);
+#endif
+}
 
-EXPORT_SYMBOL(i2o_post_this);
-EXPORT_SYMBOL(i2o_post_wait);
-EXPORT_SYMBOL(i2o_post_wait_mem);
+/**
+ *	i2o_pci_interrupt	-	Bus specific interrupt handler
+ *	@irq: interrupt line
+ *	@dev_id: cookie
+ *
+ *	Handle an interrupt from a PCI based I2O controller. This turns out
+ *	to be rather simple. We keep the controller pointer in the cookie.
+ */
+ 
+static void i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
+{
+	struct i2o_controller *c = dev_id;
+	i2o_run_queue(c);
+}	
 
-EXPORT_SYMBOL(i2o_query_scalar);
-EXPORT_SYMBOL(i2o_set_scalar);
-EXPORT_SYMBOL(i2o_query_table);
-EXPORT_SYMBOL(i2o_clear_table);
-EXPORT_SYMBOL(i2o_row_add_table);
-EXPORT_SYMBOL(i2o_issue_params);
+/**
+ *	i2o_pci_install		-	Install a PCI i2o controller
+ *	@dev: PCI device of the I2O controller
+ *
+ *	Install a PCI (or in theory AGP) i2o controller. Devices are
+ *	initialized, configured and registered with the i2o core subsystem. Be
+ *	very careful with ordering. There may be pending interrupts.
+ *
+ *	To Do: Add support for polled controllers
+ */
 
-EXPORT_SYMBOL(i2o_event_register);
-EXPORT_SYMBOL(i2o_event_ack);
+int __init i2o_pci_install(struct pci_dev *dev)
+{
+	struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller),
+						GFP_KERNEL);
+	unsigned long mem;
+	u32 memptr = 0;
+	u32 size;
+	
+	int i;
 
-EXPORT_SYMBOL(i2o_report_status);
-EXPORT_SYMBOL(i2o_dump_message);
+	if(c==NULL)
+	{
+		printk(KERN_ERR "i2o: Insufficient memory to add controller.\n");
+		return -ENOMEM;
+	}
+	memset(c, 0, sizeof(*c));
 
-EXPORT_SYMBOL(i2o_get_class_name);
+	for(i=0; i<6; i++)
+	{
+		/* Skip I/O spaces */
+		if(!(pci_resource_flags(dev, i) & IORESOURCE_IO))
+		{
+			memptr = pci_resource_start(dev, i);
+			break;
+		}
+	}
+	
+	if(i==6)
+	{
+		printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n");
+		kfree(c);
+		return -EINVAL;
+	}
+	
+	size = dev->resource[i].end-dev->resource[i].start+1;	
+	/* Map the I2O controller */
+	
+	printk(KERN_INFO "i2o: PCI I2O controller at 0x%08X size=%d\n", memptr, size);
+	mem = (unsigned long)ioremap(memptr, size);
+	if(mem==0)
+	{
+		printk(KERN_ERR "i2o: Unable to map controller.\n");
+		kfree(c);
+		return -EINVAL;
+	}
 
-EXPORT_SYMBOL_GPL(i2o_sys_init);
+	c->irq = -1;
+	c->dpt = 0;
+	c->short_req = 0;
+	c->pdev = dev;
+
+	c->irq_mask = mem+0x34;
+	c->post_port = mem+0x40;
+	c->reply_port = mem+0x44;
 
-MODULE_AUTHOR("Red Hat Software");
-MODULE_DESCRIPTION("I2O Core");
-MODULE_LICENSE("GPL");
+	c->mem_phys = memptr;
+	c->mem_offset = mem;
+	
+	/*
+	 *	Cards that fall apart if you hit them with large I/O
+	 *	loads...
+	 */
+	 
+	if(dev->vendor == PCI_VENDOR_ID_NCR && dev->device == 0x0630)
+	{
+		c->short_req = 1;
+		printk(KERN_INFO "I2O: Symbios FC920 workarounds activated.\n");
+	}
+	if(dev->subsystem_vendor == PCI_VENDOR_ID_PROMISE)
+	{
+		c->promise = 1;
+		printk(KERN_INFO "I2O: Promise workarounds activated.\n");
+	}
+
+	/*
+	 *	Cards that go bananas if you quiesce them before you reset
+	 *	them
+	 */
+	 
+	if(dev->vendor == PCI_VENDOR_ID_DPT)
+		c->dpt=1;
+	
+	/* 
+	 * Enable Write Combining MTRR for IOP's memory region
+	 */
+#ifdef CONFIG_MTRR
+	c->mtrr_reg0 =
+		mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1);
+	/*
+	 * If it is an INTEL i960 I/O processor then set the first 64K to
+	 * Uncacheable since the region contains the Messaging unit which
+	 * shouldn't be cached.
+	 */
+	c->mtrr_reg1 = -1;
+	if(dev->vendor == PCI_VENDOR_ID_INTEL || dev->vendor == PCI_VENDOR_ID_DPT)
+	{
+		printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n"); 
+		c->mtrr_reg1 =	mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
+		if(c->mtrr_reg1< 0)
+		{
+			printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n");
+			mtrr_del(c->mtrr_reg0, c->mem_phys, size);
+			c->mtrr_reg0 = -1;
+		}
+	}
+
+#endif
+
+	I2O_IRQ_WRITE32(c,0xFFFFFFFF);
+
+	i = i2o_install_controller(c);
+	
+	if(i<0)
+	{
+		printk(KERN_ERR "i2o: Unable to install controller.\n");
+		kfree(c);
+		iounmap((void *)mem);
+		return i;
+	}
+
+	c->irq = dev->irq;
+	if(c->irq)
+	{
+		i=request_irq(dev->irq, i2o_pci_interrupt, SA_SHIRQ,
+			c->name, c);
+		if(i<0)
+		{
+			printk(KERN_ERR "%s: unable to allocate interrupt %d.\n",
+				c->name, dev->irq);
+			c->irq = -1;
+			i2o_delete_controller(c);
+			iounmap((void *)mem);
+			return -EBUSY;
+		}
+	}
+
+	printk(KERN_INFO "%s: Installed at IRQ%d\n", c->name, dev->irq);
+	I2O_IRQ_WRITE32(c,0x0);
+	c->enabled = 1;
+	return 0;	
+}
+
+static int dpt;
+
+/**
+ *	i2o_pci_scan	-	Scan the pci bus for controllers
+ *	
+ *	Scan the PCI devices on the system looking for any device which is a 
+ *	memory of the Intelligent, I2O class. We attempt to set up each such device
+ *	and register it with the core.
+ *
+ *	Returns the number of controllers registered
+ *
+ *	Note; Do not change this to a hot plug interface. I2O 1.5 itself
+ *	does not support hot plugging.
+ */
+ 
+int __init i2o_pci_scan(void)
+{
+	struct pci_dev *dev;
+	int count=0;
+	
+	printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
+
+	pci_for_each_dev(dev)	
+	{
+		if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O)
+			continue;
+		if(dev->vendor == PCI_VENDOR_ID_DPT && !dpt)
+		{
+			if(dev->device == 0xA501 || dev->device == 0xA511)
+			{
+				printk(KERN_INFO "i2o: Skipping Adaptec/DPT I2O raid with preferred native driver.\n");
+				continue;
+			}
+		}
+		if((dev->class&0xFF)>1)
+		{
+			printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n");
+			continue;
+		}
+		if (pci_enable_device(dev))
+			continue;
+		printk(KERN_INFO "i2o: I2O controller on bus %d at %d.\n",
+			dev->bus->number, dev->devfn);
+		if(pci_set_dma_mask(dev, 0xffffffff))
+		{
+			printk(KERN_WARNING "I2O controller on bus %d at %d : No suitable DMA available\n", dev->bus->number, dev->devfn);
+		 	continue;
+		}
+		pci_set_master(dev);
+		if(i2o_pci_install(dev)==0)
+			count++;
+	}
+	if(count)
+		printk(KERN_INFO "i2o: %d I2O controller%s found and installed.\n", count,
+			count==1?"":"s");
+	return count?count:-ENODEV;
+}
 
 static int i2o_core_init(void)
 {
@@ -3496,6 +3706,7 @@
 	else
 		printk(KERN_INFO "I2O: Event thread created as pid %d\n", evt_pid);
 
+	i2o_pci_scan();
 	if(i2o_num_controllers)
 		i2o_sys_init();
 
@@ -3532,3 +3743,40 @@
 module_init(i2o_core_init);
 module_exit(i2o_core_exit);
 
+MODULE_PARM(dpt, "i");
+MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o");
+MODULE_PARM(verbose, "i");
+MODULE_PARM_DESC(verbose, "Verbose diagnostics");
+
+MODULE_AUTHOR("Red Hat Software");
+MODULE_DESCRIPTION("I2O Core");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(i2o_controller_chain);
+EXPORT_SYMBOL(i2o_num_controllers);
+EXPORT_SYMBOL(i2o_find_controller);
+EXPORT_SYMBOL(i2o_unlock_controller);
+EXPORT_SYMBOL(i2o_status_get);
+EXPORT_SYMBOL(i2o_install_handler);
+EXPORT_SYMBOL(i2o_remove_handler);
+EXPORT_SYMBOL(i2o_install_controller);
+EXPORT_SYMBOL(i2o_delete_controller);
+EXPORT_SYMBOL(i2o_run_queue);
+EXPORT_SYMBOL(i2o_claim_device);
+EXPORT_SYMBOL(i2o_release_device);
+EXPORT_SYMBOL(i2o_device_notify_on);
+EXPORT_SYMBOL(i2o_device_notify_off);
+EXPORT_SYMBOL(i2o_post_this);
+EXPORT_SYMBOL(i2o_post_wait);
+EXPORT_SYMBOL(i2o_post_wait_mem);
+EXPORT_SYMBOL(i2o_query_scalar);
+EXPORT_SYMBOL(i2o_set_scalar);
+EXPORT_SYMBOL(i2o_query_table);
+EXPORT_SYMBOL(i2o_clear_table);
+EXPORT_SYMBOL(i2o_row_add_table);
+EXPORT_SYMBOL(i2o_issue_params);
+EXPORT_SYMBOL(i2o_event_register);
+EXPORT_SYMBOL(i2o_event_ack);
+EXPORT_SYMBOL(i2o_report_status);
+EXPORT_SYMBOL(i2o_dump_message);
+EXPORT_SYMBOL(i2o_get_class_name);
diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_pci.c linux-2.5.65-bk3/drivers/message/i2o/i2o_pci.c
--- linux-2.5.65-bk2/drivers/message/i2o/i2o_pci.c	Mon Mar 17 13:43:43 2003
+++ linux-2.5.65-bk3/drivers/message/i2o/i2o_pci.c	Mon Mar 31 12:41:41 2003
@@ -32,9 +32,6 @@
 
 #include <asm/io.h>
 
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif // CONFIG_MTRR
 
 static int dpt;
 
diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_proc.c linux-2.5.65-bk3/drivers/message/i2o/i2o_proc.c
--- linux-2.5.65-bk2/drivers/message/i2o/i2o_proc.c	Mon Mar 17 13:44:12 2003
+++ linux-2.5.65-bk3/drivers/message/i2o/i2o_proc.c	Mon Mar 31 12:41:41 2003
@@ -836,10 +836,14 @@
 		u16 row_count;
 		u16 more_flag;
 		i2o_exec_execute_ddm_table ddm_table[MAX_I2O_MODULES];
-	} result;
+	} *result;
 
 	i2o_exec_execute_ddm_table ddm_table;
 
+	result = kmalloc(sizeof(*result), GFP_KERNEL);
+	if(!result)
+		return -ENOMEM;
+
 	spin_lock(&i2o_proc_lock);
 	len = 0;
 
@@ -847,18 +851,17 @@
 				c, ADAPTER_TID, 
 				0x0003, -1,
 				NULL, 0,
-				&result, sizeof(result));
+				result, sizeof(*result));
 
 	if (token < 0) {
 		len += i2o_report_query_status(buf+len, token,"0x0003 Executing DDM List");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		goto out;
 	}
 
 	len += sprintf(buf+len, "Tid   Module_type     Vendor Mod_id  Module_name             Vrs  Data_size Code_size\n");
-	ddm_table=result.ddm_table[0];
+	ddm_table=result->ddm_table[0];
 
-	for(i=0; i < result.row_count; ddm_table=result.ddm_table[++i])
+	for(i=0; i < result->row_count; ddm_table=result->ddm_table[++i])
 	{
 		len += sprintf(buf+len, "0x%03x ", ddm_table.ddm_tid & 0xFFF);
 
@@ -882,9 +885,9 @@
 
 		len += sprintf(buf+len, "\n");
 	}
-
+out:
 	spin_unlock(&i2o_proc_lock);
-
+	kfree(result);
 	return len;
 }
 
@@ -1047,7 +1050,11 @@
 		u16 row_count;
 		u16 more_flag;
 		i2o_group_info group[256];
-	} result;
+	} *result;
+
+	result = kmalloc(sizeof(*result), GFP_KERNEL);
+	if(!result)
+		return -ENOMEM;
 
 	spin_lock(&i2o_proc_lock);
 
@@ -1055,24 +1062,23 @@
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
 				d->controller, d->lct_data.tid, 0xF000, -1, NULL, 0,
-				&result, sizeof(result));
+				result, sizeof(*result));
 
 	if (token < 0) {
 		len = i2o_report_query_status(buf+len, token, "0xF000 Params Descriptor");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		goto out;
 	}
 
 	len += sprintf(buf+len, "#  Group   FieldCount RowCount Type   Add Del Clear\n");
 
-	for (i=0; i < result.row_count; i++)
+	for (i=0; i < result->row_count; i++)
 	{
 		len += sprintf(buf+len, "%-3d", i);
-		len += sprintf(buf+len, "0x%04X ", result.group[i].group_number);
-		len += sprintf(buf+len, "%10d ", result.group[i].field_count);
-		len += sprintf(buf+len, "%8d ",  result.group[i].row_count);
+		len += sprintf(buf+len, "0x%04X ", result->group[i].group_number);
+		len += sprintf(buf+len, "%10d ", result->group[i].field_count);
+		len += sprintf(buf+len, "%8d ",  result->group[i].row_count);
 
-		properties = result.group[i].properties;
+		properties = result->group[i].properties;
 		if (properties & 0x1)	len += sprintf(buf+len, "Table  ");
 				else	len += sprintf(buf+len, "Scalar ");
 		if (properties & 0x2)	len += sprintf(buf+len, " + ");
@@ -1085,11 +1091,11 @@
 		len += sprintf(buf+len, "\n");
 	}
 
-	if (result.more_flag)
+	if (result->more_flag)
 		len += sprintf(buf+len, "There is more...\n");
-
+out:
 	spin_unlock(&i2o_proc_lock);
-
+	kfree(result);
 	return len;
 }
 
@@ -1220,7 +1226,11 @@
 		u16 row_count;
 		u16 more_flag;
 		i2o_user_table user[64];
-	} result;
+	} *result;
+
+	result = kmalloc(sizeof(*result), GFP_KERNEL);
+	if(!result)
+		return -ENOMEM;
 
 	spin_lock(&i2o_proc_lock);
 	len = 0;
@@ -1228,28 +1238,28 @@
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
 				d->controller, d->lct_data.tid,
 				0xF003, -1, NULL, 0,
-				&result, sizeof(result));
+				result, sizeof(*result));
 
 	if (token < 0) {
 		len += i2o_report_query_status(buf+len, token,"0xF003 User Table");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		goto out;
 	}
 
 	len += sprintf(buf+len, "#  Instance UserTid ClaimType\n");
 
-	for(i=0; i < result.row_count; i++)
+	for(i=0; i < result->row_count; i++)
 	{
 		len += sprintf(buf+len, "%-3d", i);
-		len += sprintf(buf+len, "%#8x ", result.user[i].instance);
-		len += sprintf(buf+len, "%#7x ", result.user[i].user_tid);
-		len += sprintf(buf+len, "%#9x\n", result.user[i].claim_type);
+		len += sprintf(buf+len, "%#8x ", result->user[i].instance);
+		len += sprintf(buf+len, "%#7x ", result->user[i].user_tid);
+		len += sprintf(buf+len, "%#9x\n", result->user[i].claim_type);
 	}
 
-	if (result.more_flag)
+	if (result->more_flag)
 		len += sprintf(buf+len, "There is more...\n");
-
+out:
 	spin_unlock(&i2o_proc_lock);
+	kfree(result);
 	return len;
 }
 
@@ -2264,24 +2274,27 @@
 		u16 row_count;
 		u16 more_flag;
 		u8  mc_addr[256][8];
-	} result;	
+	} *result;	
+
+	result = kmalloc(sizeof(*result), GFP_KERNEL);
+	if(!result)
+		return -ENOMEM;
 
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
 				d->controller, d->lct_data.tid, 0x0002, -1, 
-				NULL, 0, &result, sizeof(result));
+				NULL, 0, result, sizeof(*result));
 
 	if (token < 0) {
 		len += i2o_report_query_status(buf+len, token,"0x002 LAN Multicast MAC Address");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		goto out;
 	}
 
-	for (i = 0; i < result.row_count; i++)
+	for (i = 0; i < result->row_count; i++)
 	{
-		memcpy(mc_addr, result.mc_addr[i], 8);
+		memcpy(mc_addr, result->mc_addr[i], 8);
 
 		len += sprintf(buf+len, "MC MAC address[%d]: "
 			       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -2289,8 +2302,9 @@
 			       mc_addr[3], mc_addr[4], mc_addr[5],
 			       mc_addr[6], mc_addr[7]);
 	}
-
+out:
 	spin_unlock(&i2o_proc_lock);
+	kfree(result);
 	return len;
 }
 
@@ -2495,32 +2509,36 @@
 		u16 row_count;
 		u16 more_flag;
 		u8  alt_addr[256][8];
-	} result;	
+	} *result;	
+
+	result = kmalloc(sizeof(*result), GFP_KERNEL);
+	if(!result)
+		return -ENOMEM;
 
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
 				d->controller, d->lct_data.tid,
-				0x0006, -1, NULL, 0, &result, sizeof(result));
+				0x0006, -1, NULL, 0, result, sizeof(*result));
 
 	if (token < 0) {
 		len += i2o_report_query_status(buf+len, token, "0x0006 LAN Alternate Address (optional)");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		goto out;
 	}
 
-	for (i=0; i < result.row_count; i++)
+	for (i=0; i < result->row_count; i++)
 	{
-		memcpy(alt_addr,result.alt_addr[i],8);
+		memcpy(alt_addr,result->alt_addr[i],8);
 		len += sprintf(buf+len, "Alternate address[%d]: "
 			       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
 			       i, alt_addr[0], alt_addr[1], alt_addr[2],
 			       alt_addr[3], alt_addr[4], alt_addr[5],
 			       alt_addr[6], alt_addr[7]);
 	}
-
+out:
 	spin_unlock(&i2o_proc_lock);
+	kfree(result);
 	return len;
 }
 
diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_scsi.c linux-2.5.65-bk3/drivers/message/i2o/i2o_scsi.c
--- linux-2.5.65-bk2/drivers/message/i2o/i2o_scsi.c	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk3/drivers/message/i2o/i2o_scsi.c	Mon Mar 31 12:41:41 2003
@@ -85,7 +85,7 @@
 static u32 *retry[32];
 static struct i2o_controller *retry_ctrl[32];
 static struct timer_list retry_timer;
-static spinlock_t retry_lock;
+static spinlock_t retry_lock = SPIN_LOCK_UNLOCKED;
 static int retry_ct = 0;
 
 static atomic_t queue_depth;
diff -urN linux-2.5.65-bk2/drivers/mtd/nftlmount.c linux-2.5.65-bk3/drivers/mtd/nftlmount.c
--- linux-2.5.65-bk2/drivers/mtd/nftlmount.c	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk3/drivers/mtd/nftlmount.c	Mon Mar 31 12:41:41 2003
@@ -21,7 +21,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define __NO_VERSION__
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <asm/errno.h>
diff -urN linux-2.5.65-bk2/drivers/net/3c501.c linux-2.5.65-bk3/drivers/net/3c501.c
--- linux-2.5.65-bk2/drivers/net/3c501.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/drivers/net/3c501.c	Mon Mar 31 12:41:41 2003
@@ -955,7 +955,7 @@
  * init_module:
  *
  * When the driver is loaded as a module this function is called. We fake up
- * a device structure with the base I/O and interrupt set as if it was being
+ * a device structure with the base I/O and interrupt set as if it were being
  * called from Space.c. This minimises the extra code that would otherwise
  * be required.
  *
diff -urN linux-2.5.65-bk2/drivers/net/irda/ali-ircc.c linux-2.5.65-bk3/drivers/net/irda/ali-ircc.c
--- linux-2.5.65-bk2/drivers/net/irda/ali-ircc.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/drivers/net/irda/ali-ircc.c	Mon Mar 31 12:41:41 2003
@@ -248,7 +248,6 @@
 	struct ali_ircc_cb *self;
 	struct pm_dev *pmdev;
 	int dongle_id;
-	int ret;
 	int err;
 			
 	IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);	
diff -urN linux-2.5.65-bk2/drivers/net/sk98lin/skvpd.c linux-2.5.65-bk3/drivers/net/sk98lin/skvpd.c
--- linux-2.5.65-bk2/drivers/net/sk98lin/skvpd.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/drivers/net/sk98lin/skvpd.c	Mon Mar 31 12:41:41 2003
@@ -121,7 +121,7 @@
  ******************************************************************************/
 
 /*
-	Please refer skvpd.txt for infomation how to include this module
+	Please refer skvpd.txt for information how to include this module
  */
 static const char SysKonnectFileId[] =
 	"@(#)$Id: skvpd.c,v 1.26 2000/06/13 08:00:01 mkarl Exp $ (C) SK" ;
diff -urN linux-2.5.65-bk2/drivers/net/tulip/winbond-840.c linux-2.5.65-bk3/drivers/net/tulip/winbond-840.c
--- linux-2.5.65-bk2/drivers/net/tulip/winbond-840.c	Mon Mar 17 13:43:46 2003
+++ linux-2.5.65-bk3/drivers/net/tulip/winbond-840.c	Mon Mar 31 12:41:41 2003
@@ -17,7 +17,7 @@
 	Support and updates available at
 	http://www.scyld.com/network/drivers.html
 
-	Do not remove the copyright infomation.
+	Do not remove the copyright information.
 	Do not change the version information unless an improvement has been made.
 	Merely removing my name, as Compex has done in the past, does not count
 	as an improvement.
diff -urN linux-2.5.65-bk2/drivers/pcmcia/bulkmem.c linux-2.5.65-bk3/drivers/pcmcia/bulkmem.c
--- linux-2.5.65-bk2/drivers/pcmcia/bulkmem.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/drivers/pcmcia/bulkmem.c	Mon Mar 31 12:41:41 2003
@@ -31,8 +31,6 @@
     
 ======================================================================*/
 
-#define __NO_VERSION__
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff -urN linux-2.5.65-bk2/drivers/pcmcia/cardbus.c linux-2.5.65-bk3/drivers/pcmcia/cardbus.c
--- linux-2.5.65-bk2/drivers/pcmcia/cardbus.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/pcmcia/cardbus.c	Mon Mar 31 12:41:41 2003
@@ -46,8 +46,6 @@
  */
 
 
-#define __NO_VERSION__
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff -urN linux-2.5.65-bk2/drivers/pcmcia/cistpl.c linux-2.5.65-bk3/drivers/pcmcia/cistpl.c
--- linux-2.5.65-bk2/drivers/pcmcia/cistpl.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/pcmcia/cistpl.c	Mon Mar 31 12:41:41 2003
@@ -31,8 +31,6 @@
     
 ======================================================================*/
 
-#define __NO_VERSION__
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff -urN linux-2.5.65-bk2/drivers/pcmcia/cs.c linux-2.5.65-bk3/drivers/pcmcia/cs.c
--- linux-2.5.65-bk2/drivers/pcmcia/cs.c	Mon Mar 17 13:43:49 2003
+++ linux-2.5.65-bk3/drivers/pcmcia/cs.c	Mon Mar 31 12:41:41 2003
@@ -895,6 +895,10 @@
 	c = &s->config[reg->Function];
     } else
 	c = CONFIG(handle);
+
+    if (c == NULL)
+	return CS_NO_CARD;
+
     if (!(c->state & CONFIG_LOCKED))
 	return CS_CONFIGURATION_LOCKED;
 
diff -urN linux-2.5.65-bk2/drivers/pcmcia/rsrc_mgr.c linux-2.5.65-bk3/drivers/pcmcia/rsrc_mgr.c
--- linux-2.5.65-bk2/drivers/pcmcia/rsrc_mgr.c	Mon Mar 17 13:44:10 2003
+++ linux-2.5.65-bk3/drivers/pcmcia/rsrc_mgr.c	Mon Mar 31 12:41:41 2003
@@ -31,8 +31,6 @@
     
 ======================================================================*/
 
-#define __NO_VERSION__
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff -urN linux-2.5.65-bk2/drivers/pnp/pnpbios/core.c linux-2.5.65-bk3/drivers/pnp/pnpbios/core.c
--- linux-2.5.65-bk2/drivers/pnp/pnpbios/core.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/drivers/pnp/pnpbios/core.c	Mon Mar 31 12:41:41 2003
@@ -969,7 +969,7 @@
 
 	spin_lock_init(&pnp_bios_lock);
 
-	if(pnpbios_disabled) {
+	if(pnpbios_disabled || (dmi_broken & BROKEN_PNP_BIOS)) {
 		printk(KERN_INFO "PnPBIOS: Disabled\n");
 		return -ENODEV;
 	}
diff -urN linux-2.5.65-bk2/drivers/pnp/pnpbios/proc.c linux-2.5.65-bk3/drivers/pnp/pnpbios/proc.c
--- linux-2.5.65-bk2/drivers/pnp/pnpbios/proc.c	Mon Mar 17 13:44:45 2003
+++ linux-2.5.65-bk3/drivers/pnp/pnpbios/proc.c	Mon Mar 31 12:41:41 2003
@@ -19,7 +19,6 @@
  */
 
 //#include <pcmcia/config.h>
-#define __NO_VERSION__
 //#include <pcmcia/k_compat.h>
 
 #include <linux/module.h>
diff -urN linux-2.5.65-bk2/drivers/scsi/advansys.c linux-2.5.65-bk3/drivers/scsi/advansys.c
--- linux-2.5.65-bk2/drivers/scsi/advansys.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/drivers/scsi/advansys.c	Mon Mar 31 12:41:41 2003
@@ -7099,7 +7099,7 @@
          * then return the number of underrun bytes.
          */
         if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
-            qdonep->remain_bytes <= scp->request_bufflen != 0) {
+            qdonep->remain_bytes <= scp->request_bufflen) {
             ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n",
             (unsigned) qdonep->remain_bytes);
             scp->resid = qdonep->remain_bytes;
diff -urN linux-2.5.65-bk2/drivers/scsi/aha152x.c linux-2.5.65-bk3/drivers/scsi/aha152x.c
--- linux-2.5.65-bk2/drivers/scsi/aha152x.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/drivers/scsi/aha152x.c	Mon Mar 31 12:41:42 2003
@@ -2651,7 +2651,7 @@
 
 static void datai_run(struct Scsi_Host *shpnt)
 {
-	unsigned int the_time;
+	unsigned long the_time;
 	int fifodata, data_count;
 
 	/*
@@ -2793,7 +2793,7 @@
 
 static void datao_run(struct Scsi_Host *shpnt)
 {
-	unsigned int the_time;
+	unsigned long the_time;
 	int data_count;
 
 	/* until phase changes or all data sent */
diff -urN linux-2.5.65-bk2/drivers/scsi/aha1542.c linux-2.5.65-bk3/drivers/scsi/aha1542.c
--- linux-2.5.65-bk2/drivers/scsi/aha1542.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/drivers/scsi/aha1542.c	Mon Mar 31 12:41:42 2003
@@ -1020,7 +1020,7 @@
 
 static int __init do_setup(char *str)
 {
-	int ints[4];
+	int ints[5];
 
 	int count=setup_idx;
 
diff -urN linux-2.5.65-bk2/drivers/scsi/cpqfcTSinit.c linux-2.5.65-bk3/drivers/scsi/cpqfcTSinit.c
--- linux-2.5.65-bk2/drivers/scsi/cpqfcTSinit.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/drivers/scsi/cpqfcTSinit.c	Mon Mar 31 12:41:42 2003
@@ -686,7 +686,7 @@
 	if( (vendor_cmd->rw_flag == VENDOR_READ_OPCODE) &&
 	     vendor_cmd->len )
         if(  copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len))
-		return( -EFAULT);
+		result = -EFAULT;
 
         if( buf) 
 	  kfree( buf);
diff -urN linux-2.5.65-bk2/drivers/scsi/gdth.c linux-2.5.65-bk3/drivers/scsi/gdth.c
--- linux-2.5.65-bk2/drivers/scsi/gdth.c	Mon Mar 17 13:44:14 2003
+++ linux-2.5.65-bk3/drivers/scsi/gdth.c	Mon Mar 31 12:41:42 2003
@@ -4,7 +4,7 @@
  * Intel Corporation:  Storage RAID Controllers                         *
  *                                                                      *
  * gdth.c                                                               *
- * Copyright (C) 1995-02 ICP vortex, an Intel company,  Achim Leubner   *
+ * Copyright (C) 1995-03 ICP vortex, an Intel company,  Achim Leubner   *
  * <achim.leubner@intel.com>                                            *
  *                                                                      *
  * Additions/Fixes: Boji Tony Kannanthanam                              *
@@ -24,11 +24,17 @@
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.18                   *
+ * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.20                   *
  *                                                                      *
  * $Log: gdth.c,v $
- * Revision 1.61  2002/10/03 09:35:22  boji
- * Fixed SCREENSERVICE initialisation in SMP cases.
+ * Revision 1.62  2003/02/27 15:01:59  achim
+ * Dynamic DMA mapping implemented
+ * New (character device) IOCTL interface added
+ * Other controller related changes made
+ *
+ * Revision 1.61  2002/11/08 13:09:52  boji
+ * Added support for XSCALE based RAID Controllers
+ * Fixed SCREENSERVICE initialization in SMP cases
  * Added checks for gdth_polling before GDTH_HA_LOCK
  *
  * Revision 1.60  2002/02/05 09:35:22  achim
@@ -216,7 +222,7 @@
  *
  * Revision 1.9  1997/09/04 10:07:25  achim
  * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ...
- * register_reboot_notifier() to get a notify on shutdown used
+ * register_reboot_notifier() to get a notify on shutown used
  *
  * Revision 1.8  1997/04/02 12:14:30  achim
  * Version 1.00 (see gdth.h), tested with kernel 2.0.29
@@ -248,7 +254,7 @@
  * Initial revision
  *
  ************************************************************************/
-#ident "$Id: gdth.c,v 1.60 2002/02/05 09:35:22 achim Exp $" 
+#ident "$Id: gdth.c,v 1.62 2003/02/27 15:01:59 achim Exp $" 
 
 /* All GDT Disk Array Controllers are fully supported by this driver.
  * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
@@ -300,18 +306,21 @@
  */
 
 /* The meaning of the Scsi_Pointer members in this driver is as follows:
- * ptr:                         Chaining
- * this_residual:               Command priority
- * buffer:                      Unused
- * buffers_residual:            Timeout value
- * Status:                      Command status (gdth_do_cmd())
- * Message:                     Additional info (gdth_do_cmd())
- * have_data_in:                Flag for gdth_wait_completion()
- * sent_command:                Opcode special command
- * phase:                       Service/parameter/return code special command
+ * ptr:                     Chaining
+ * this_residual:           Command priority
+ * buffer:                  phys. DMA sense buffer 
+ * dma_handle:              phys. DMA buffer (kernel >= 2.4.0)
+ * buffers_residual:        Timeout value
+ * Status:                  Command status (gdth_do_cmd()), DMA mem. mappings
+ * Message:                 Additional info (gdth_do_cmd()), DMA direction
+ * have_data_in:            Flag for gdth_wait_completion()
+ * sent_command:            Opcode special command
+ * phase:                   Service/parameter/return code special command
  */
 
-#error Please convert me to Documentation/DMA-mapping.txt
+/* default: activate /proc and character device IOCTL interface */
+#define GDTH_IOCTL_PROC
+#define GDTH_IOCTL_CHRDEV
 
 #include <linux/module.h>
 
@@ -324,6 +333,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/proc_fs.h>
 #include <linux/time.h>
@@ -340,6 +350,7 @@
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 #if LINUX_VERSION_CODE >= 0x020322
 #include <linux/spinlock.h>
 #elif LINUX_VERSION_CODE >= 0x02015F
@@ -353,6 +364,9 @@
 #endif
 #include "scsi.h"
 #include "hosts.h"
+#if LINUX_VERSION_CODE < 0x020503
+#include "sd.h"
+#endif
 
 #include "gdth.h"
 
@@ -378,7 +392,8 @@
                                gdth_evt_str *estr);
 static void gdth_clear_events(void);
 
-static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count);
+static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
+                                    char *buffer,ushort count);
 static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp);
 static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
 
@@ -408,6 +423,13 @@
 
 static const char *gdth_ctr_name(int hanum);
 
+#ifdef GDTH_IOCTL_CHRDEV
+static int gdth_open(struct inode *inode, struct file *filep);
+static int gdth_close(struct inode *inode, struct file *filep);
+static int gdth_ioctl(struct inode *inode, struct file *filep,
+                      unsigned int cmd, unsigned long arg);
+#endif
+
 #if LINUX_VERSION_CODE >= 0x010300
 static void gdth_flush(int hanum);
 #if LINUX_VERSION_CODE >= 0x020100
@@ -604,6 +626,9 @@
 static gdth_evt_str ebuffer[MAX_EVENTS];                /* event buffer */
 static int elastidx;
 static int eoldidx;
+#ifdef GDTH_IOCTL_CHRDEV
+static int major;
+#endif
 
 #define DIN     1                               /* IN data direction */
 #define DOU     2                               /* OUT data direction */
@@ -641,24 +666,35 @@
 #define __init
 #endif
 
-#if LINUX_VERSION_CODE >= 0x02015F
+#if LINUX_VERSION_CODE >= 0x020503
+#define GDTH_INIT_LOCK_HA(ha)           spin_lock_init(&(ha)->smp_lock)
+#define GDTH_LOCK_HA(ha,flags)          spin_lock_irqsave(&(ha)->smp_lock,flags)
+#define GDTH_UNLOCK_HA(ha,flags)        spin_unlock_irqrestore(&(ha)->smp_lock,flags)
+
+#define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags)
+#define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags)
+#define GDTH_LOCK_SCSI_DOCMD(dev)       spin_lock_irq(dev->host_lock)
+#define GDTH_UNLOCK_SCSI_DOCMD(dev)     spin_unlock_irq(dev->host_lock)
+
+#elif LINUX_VERSION_CODE >= 0x02015F
 #define GDTH_INIT_LOCK_HA(ha)           spin_lock_init(&(ha)->smp_lock)
 #define GDTH_LOCK_HA(ha,flags)          spin_lock_irqsave(&(ha)->smp_lock,flags)
 #define GDTH_UNLOCK_HA(ha,flags)        spin_unlock_irqrestore(&(ha)->smp_lock,flags)
 
-#define GDTH_LOCK_SCSI_DONE(dev, flags)      spin_lock_irqsave(dev->host_lock,flags)
-#define GDTH_UNLOCK_SCSI_DONE(flags)    spin_unlock_irqrestore(dev->host_lock,flags)
-#define GDTH_LOCK_SCSI_DOCMD(dev)          spin_lock_irq(dev->host_lock)
-#define GDTH_UNLOCK_SCSI_DOCMD(dev)        spin_unlock_irq(dev->host_lock)
+#define GDTH_LOCK_SCSI_DONE(flags)      spin_lock_irqsave(&io_request_lock,flags)
+#define GDTH_UNLOCK_SCSI_DONE(flags)    spin_unlock_irqrestore(&io_request_lock,flags)
+#define GDTH_LOCK_SCSI_DOCMD()          spin_lock_irq(&io_request_lock)
+#define GDTH_UNLOCK_SCSI_DOCMD()        spin_unlock_irq(&io_request_lock)
+
 #else
 #define GDTH_INIT_LOCK_HA(ha)           do {} while (0)
 #define GDTH_LOCK_HA(ha,flags)          do {save_flags(flags); cli();} while (0)
 #define GDTH_UNLOCK_HA(ha,flags)        do {restore_flags(flags);} while (0)
 
-#define GDTH_LOCK_SCSI_DONE(dev, flags)      do {} while (0)
-#define GDTH_UNLOCK_SCSI_DONE(dev, flags)    do {} while (0)
-#define GDTH_LOCK_SCSI_DOCMD(dev)          do {} while (0)
-#define GDTH_UNLOCK_SCSI_DOCMD(dev)        do {} while (0)
+#define GDTH_LOCK_SCSI_DONE(flags)      do {} while (0)
+#define GDTH_UNLOCK_SCSI_DONE(flags)    do {} while (0)
+#define GDTH_LOCK_SCSI_DOCMD()          do {} while (0)
+#define GDTH_UNLOCK_SCSI_DOCMD()        do {} while (0)
 #endif
 
 /* LILO and modprobe/insmod parameters */
@@ -702,10 +738,21 @@
 MODULE_PARM(virt_ctr, "i");
 MODULE_PARM(shared_access, "i");
 MODULE_AUTHOR("Achim Leubner");
+#endif
+#if LINUX_VERSION_CODE >= 0x02040B
 MODULE_LICENSE("GPL");
 #endif
 #endif
 
+#ifdef GDTH_IOCTL_CHRDEV
+/* ioctl interface */
+static struct file_operations gdth_fops = {
+    ioctl:gdth_ioctl,
+    open:gdth_open,
+    release:gdth_close,
+};
+#endif
+
 /* /proc support */
 #if LINUX_VERSION_CODE >= 0x010300
 #include <linux/stat.h> 
@@ -813,6 +860,8 @@
                     PCI_DEVICE_ID_VORTEX_GDTNEWRX);
     gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
                     PCI_DEVICE_ID_INTEL_SRC);
+    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
+                    PCI_DEVICE_ID_INTEL_SRC_XSCALE);
     return cnt;
 }
 
@@ -820,10 +869,11 @@
 /* Vortex only makes RAID controllers.
  * We do not really want to specify all 550 ids here, so wildcard match.
  */
-static struct pci_device_id gdthtable[] = {
-	{PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID },
-	{PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID }, 
-	{0}
+static struct pci_device_id gdthtable[] __devinitdata = {
+    {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
+    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
+    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
+    {0}
 };
 MODULE_DEVICE_TABLE(pci,gdthtable);
 #endif
@@ -1235,6 +1285,9 @@
     ha->stype = (ulong32)pcistr->device_id;
     ha->subdevice_id = pcistr->subdevice_id;
     ha->irq = pcistr->irq;
+#if LINUX_VERSION_CODE >= 0x20400
+    ha->pdev = pcistr->pdev;
+#endif
     
     if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) {  /* GDT6000/B */
         TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
@@ -1511,6 +1564,11 @@
                                    PCI_ROM_ADDRESS, rom_addr);
 #endif
         
+        /* Ensure that it is safe to access the non HW portions of DPMEM.
+         * Aditional check needed for Xscale based RAID controllers */
+        while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 )
+            gdth_delay(1);
+        
         /* check and reset interface area */
         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
@@ -1840,7 +1898,7 @@
 
     if (ha->type == GDT_EISA) {
         if (ha->pccb->OpCode == GDT_INIT)               /* store DMA buffer */
-            outl(virt_to_bus(ha->pccb), ha->bmic + MAILBOXREG);
+            outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
         outb(ha->pccb->Service, ha->bmic + LDOORREG);
     } else if (ha->type == GDT_ISA) {
         gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
@@ -1916,7 +1974,7 @@
                 cmd_ptr->u.ioctl.subfunc = p1;
                 cmd_ptr->u.ioctl.channel = p2;
                 cmd_ptr->u.ioctl.param_size = (ushort)p3;
-                cmd_ptr->u.ioctl.p_param = virt_to_bus(ha->pscratch);
+                cmd_ptr->u.ioctl.p_param = ha->scratch_phys;
             } else {
                 cmd_ptr->u.cache.DeviceNo = (ushort)p1;
                 cmd_ptr->u.cache.BlockNo  = p2;
@@ -1965,6 +2023,8 @@
     gdth_raw_iochan_str *iocr;
     gdth_arcdl_str *alst;
     gdth_alist_str *alst2;
+    gdth_oem_str_ioctl *oemstr;
+
 #ifdef GDTH_RTC
     unchar rtc[12];
     ulong flags;
@@ -2233,6 +2293,27 @@
         }
     }
 
+    /* Determine OEM string using IOCTL */
+    oemstr = (gdth_oem_str_ioctl *)ha->pscratch;
+    oemstr->params.ctl_version = 0x01;
+    oemstr->params.buffer_size = sizeof(oemstr->text);
+    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+                          CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL,
+                          sizeof(gdth_oem_str_ioctl))) {
+        TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n"));
+        printk("GDT CTR%d Vendor: %s\n",hanum,oemstr->text.oem_company_name);
+        /* Save the Host Drive inquiry data */
+        strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7);
+        ha->oem_name[7] = '\0';
+    } else {
+        /* Old method, based on PCI ID */
+        TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
+        if (ha->oem_id == OEM_ID_INTEL)
+            strcpy(ha->oem_name,"Intel  ");
+        else
+            strcpy(ha->oem_name,"ICP    ");
+    }
+
     /* scanning for host drives */
     for (i = 0; i < cdev_cnt; ++i) 
         gdth_analyse_hdrive(hanum,i);
@@ -2313,8 +2394,13 @@
     GDTH_LOCK_HA(ha, flags);
 
     scp->SCp.this_residual = (int)priority;
+#if LINUX_VERSION_CODE >= 0x02053C
     b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
     t = scp->device->id;
+#else
+    b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+    t = scp->target;
+#endif
 #if LINUX_VERSION_CODE >= 0x010300
     if (priority >= DEFAULT_PRI) {
         if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
@@ -2357,7 +2443,7 @@
     register gdth_ha_str *ha;
     register Scsi_Cmnd *pscp;
     register Scsi_Cmnd *nscp;
-    unchar b, t, firsttime;
+    unchar b, t, l, firsttime;
     unchar this_cmd, next_cmd;
     ulong flags = 0;
     int cmd_index;
@@ -2365,7 +2451,7 @@
     TRACE(("gdth_next() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
     if (!gdth_polling) 
-    	GDTH_LOCK_HA(ha, flags);
+        GDTH_LOCK_HA(ha, flags);
 
     ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
     this_cmd = firsttime = TRUE;
@@ -2375,8 +2461,15 @@
     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
         if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
             pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
+#if LINUX_VERSION_CODE >= 0x02053C
         b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
         t = nscp->device->id;
+        l = nscp->device->lun;
+#else
+        b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel;
+        t = nscp->target;
+        l = nscp->lun;
+#endif
         if (nscp->SCp.this_residual >= DEFAULT_PRI) {
             if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
                 (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) 
@@ -2404,16 +2497,16 @@
             nscp->SCp.phase = CACHESERVICE;           /* default: cache svc. */ 
             if (nscp->cmnd[0] == TEST_UNIT_READY) {
                 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", 
-                        b, t, nscp->lun));
+                        b, t, l));
                 /* TEST_UNIT_READY -> set scan mode */
                 if ((ha->scan_mode & 0x0f) == 0) {
-                    if (b == 0 && t == 0 && nscp->device->lun == 0) {
+                    if (b == 0 && t == 0 && l == 0) {
                         ha->scan_mode |= 1;
                         TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
                     }
                 } else if ((ha->scan_mode & 0x0f) == 1) {
-                    if (b == 0 && ((t == 0 && nscp->device->lun == 1) ||
-                         (t == 1 && nscp->device->lun == 0))) {
+                    if (b == 0 && ((t == 0 && l == 1) ||
+                         (t == 1 && l == 0))) {
                         nscp->SCp.sent_command = GDT_SCAN_START;
                         nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) 
                             | SCSIRAWSERVICE;
@@ -2465,7 +2558,7 @@
                     /* io_request_lock already active ! */
                     nscp->scsi_done(nscp);
                     if (!gdth_polling) 
-                    	GDTH_LOCK_HA(ha,flags);
+                        GDTH_LOCK_HA(ha,flags);
                 }
             }
         } else
@@ -2483,19 +2576,19 @@
                 this_cmd = FALSE;
             else 
                 ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
-        } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || nscp->device->lun != 0) {
+        } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || l != 0) {
             TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
-                    nscp->cmnd[0], b, t, nscp->lun));
+                    nscp->cmnd[0], b, t, l));
             nscp->result = DID_BAD_TARGET << 16;
             if (!nscp->SCp.have_data_in)
                 nscp->SCp.have_data_in++;
             else {
                 if (!gdth_polling) 
-                	GDTH_UNLOCK_HA(ha,flags);
+                    GDTH_UNLOCK_HA(ha,flags);
                 /* io_request_lock already active ! */      
                 nscp->scsi_done(nscp);
                 if (!gdth_polling) 
-                	GDTH_LOCK_HA(ha,flags);
+                    GDTH_LOCK_HA(ha,flags);
             }
         } else {
             switch (nscp->cmnd[0]) {
@@ -2521,20 +2614,20 @@
                     if (!nscp->SCp.have_data_in)
                         nscp->SCp.have_data_in++;
                     else {
-                	if (!gdth_polling) 
-                        	GDTH_UNLOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_UNLOCK_HA(ha,flags);
                         /* io_request_lock already active ! */      
                         nscp->scsi_done(nscp);
-                	if (!gdth_polling) 
-                        	GDTH_LOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_LOCK_HA(ha,flags);
                     }
                 } else if (gdth_internal_cache_cmd(hanum,nscp)) {
                     if (!gdth_polling) 
-                    	GDTH_UNLOCK_HA(ha,flags);
+                        GDTH_UNLOCK_HA(ha,flags);
                     /* io_request_lock already active ! */      
                     nscp->scsi_done(nscp);
                     if (!gdth_polling) 
-                    	GDTH_LOCK_HA(ha,flags);
+                        GDTH_LOCK_HA(ha,flags);
                 }
                 break;
 
@@ -2549,12 +2642,12 @@
                     if (!nscp->SCp.have_data_in)
                         nscp->SCp.have_data_in++;
                     else {
-                    	if (!gdth_polling) 
-                        	GDTH_UNLOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_UNLOCK_HA(ha,flags);
                         /* io_request_lock already active ! */      
                         nscp->scsi_done(nscp);
-                    	if (!gdth_polling) 
-                        	GDTH_LOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_LOCK_HA(ha,flags);
                     }
                 } else {
                     nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
@@ -2589,12 +2682,12 @@
                     if (!nscp->SCp.have_data_in)
                         nscp->SCp.have_data_in++;
                     else {
-                    	if (!gdth_polling) 
-                        	GDTH_UNLOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_UNLOCK_HA(ha,flags);
                         /* io_request_lock already active ! */      
                         nscp->scsi_done(nscp);
-                    	if (!gdth_polling) 
-                        	GDTH_LOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_LOCK_HA(ha,flags);
                     }
                 } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
                     this_cmd = FALSE;
@@ -2611,11 +2704,11 @@
                     nscp->SCp.have_data_in++;
                 else {
                     if (!gdth_polling) 
-                    	GDTH_UNLOCK_HA(ha,flags);
+                        GDTH_UNLOCK_HA(ha,flags);
                     /* io_request_lock already active ! */  
                     nscp->scsi_done(nscp);
                     if (!gdth_polling) 
-                    	GDTH_LOCK_HA(ha,flags);
+                        GDTH_LOCK_HA(ha,flags);
                 }
                 break;
             }
@@ -2636,7 +2729,7 @@
     }
 
     if (!gdth_polling) 
-    	GDTH_UNLOCK_HA(ha, flags);
+        GDTH_UNLOCK_HA(ha, flags);
 
     if (gdth_polling && ha->cmd_cnt > 0) {
         if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
@@ -2645,27 +2738,54 @@
     }
 }
     
-static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count)
+static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
+                                    char *buffer,ushort count)
 {
     ushort cpcount,i;
     ushort cpsum,cpnow;
     struct scatterlist *sl;
+    gdth_ha_str *ha;
+    int sgcnt;
+    char *address;
 
     cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
+    ha = HADATA(gdth_ctr_tab[hanum]);
+
     if (scp->use_sg) {
         sl = (struct scatterlist *)scp->request_buffer;
-        for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
-            cpnow = (ushort)sl->length;
+#if LINUX_VERSION_CODE >= 0x020400
+        sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE);
+        for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
+            cpnow = (ushort)sg_dma_len(sl);
             TRACE(("copy_internal() now %d sum %d count %d %d\n",
                           cpnow,cpsum,cpcount,(ushort)scp->bufflen));
             if (cpsum+cpnow > cpcount) 
                 cpnow = cpcount - cpsum;
             cpsum += cpnow;
-            memcpy((char*)sl->address,buffer,cpnow);
+            address = (char *)phys_to_virt(sg_dma_address(sl));
+            memcpy(address,buffer,cpnow);
+            if (cpsum == cpcount)
+                break;
+            buffer += cpnow;
+        }
+        pci_unmap_sg(ha->pdev,scp->request_buffer,
+                     scp->use_sg,PCI_DMA_FROMDEVICE);
+#else
+        sgcnt = scp->use_sg;
+        for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
+            cpnow = (ushort)sl->length;
+            TRACE(("copy_internal() now %d sum %d count %d %d\n",
+                          cpnow,cpsum,cpcount,(ushort)scp->bufflen));
+            if (cpsum+cpnow > cpcount) 
+               cpnow = cpcount - cpsum;
+            cpsum += cpnow;
+            address = (char *)sl->address;
+            memcpy(address,buffer,cpnow);
             if (cpsum == cpcount)
                 break;
             buffer += cpnow;
         }
+#endif
     } else {
         TRACE(("copy_internal() count %d\n",cpcount));
         memcpy((char*)scp->request_buffer,buffer,cpcount);
@@ -2682,7 +2802,11 @@
     gdth_modep_data mpd;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
+#if LINUX_VERSION_CODE >= 0x02053C
     t  = scp->device->id;
+#else
+    t  = scp->target;
+#endif
     TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
            scp->cmnd[0],t));
 
@@ -2706,13 +2830,10 @@
         inq.version   = 2;
         inq.resp_aenc = 2;
         inq.add_length= 32;
-        if (ha->oem_id == OEM_ID_INTEL)
-            strcpy(inq.vendor,"Intel  ");
-        else 
-            strcpy(inq.vendor,"ICP    ");
+        strcpy(inq.vendor,ha->oem_name);
         sprintf(inq.product,"Host Drive  #%02d",t);
         strcpy(inq.revision,"   ");
-        gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
+        gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data));
         break;
 
       case REQUEST_SENSE:
@@ -2722,7 +2843,7 @@
         sd.key       = NO_SENSE;
         sd.info      = 0;
         sd.add_length= 0;
-        gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
+        gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data));
         break;
 
       case MODE_SENSE:
@@ -2734,14 +2855,14 @@
         mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
         mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
         mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
-        gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
+        gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data));
         break;
 
       case READ_CAPACITY:
         TRACE2(("Read capacity hdrive %d\n",t));
         rdc.last_block_no = ntohl(ha->hdr[t].size-1);
         rdc.block_length  = ntohl(SECTOR_SIZE);
-        gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
+        gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data));
         break;
 
       default:
@@ -2766,8 +2887,8 @@
     register gdth_cmd_str *cmdp;
     struct scatterlist *sl;
     ushort i, cnt;
-    ulong32 no;
-    int cmd_index, read_write;
+    ulong32 no, phys_addr;
+    int cmd_index, read_write, sgcnt;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
@@ -2789,7 +2910,7 @@
         gdth_set_sema0(hanum);
 
     /* fill command */
-    read_write = FALSE;
+    read_write = 0;
     if (scp->SCp.sent_command != -1) 
         cmdp->OpCode = scp->SCp.sent_command;   /* special cache cmd. */
     else if (scp->cmnd[0] == RESERVE) 
@@ -2803,15 +2924,16 @@
             cmdp->OpCode = GDT_UNMOUNT;
         else
             cmdp->OpCode = GDT_FLUSH;
-    } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10) {
-        read_write = TRUE;
+    } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 ||
+               scp->cmnd[0] == WRITE_12) {
+        read_write = 1;
         if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) && 
                                    (ha->cache_feat & GDT_WR_THROUGH)))
             cmdp->OpCode = GDT_WRITE_THR;
         else
             cmdp->OpCode = GDT_WRITE;
     } else {
-        read_write = TRUE;
+        read_write = 2;
         cmdp->OpCode = GDT_READ;
     }
     
@@ -2835,10 +2957,22 @@
         if (scp->use_sg) {
             cmdp->u.cache.DestAddr= 0xffffffff;
             sl = (struct scatterlist *)scp->request_buffer;
-            for (i=0; i<scp->use_sg; ++i,++sl) {
+            sgcnt = scp->use_sg;
+#if LINUX_VERSION_CODE >= 0x020400
+            scp->SCp.Status = GDTH_MAP_SG;
+            scp->SCp.Message = (read_write == 1 ? 
+                PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);   
+            sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
+            for (i=0; i<sgcnt; ++i,++sl) {
+                cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl);
+                cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl);
+            }
+#else
+            for (i=0; i<sgcnt; ++i,++sl) {
                 cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
                 cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
             }
+#endif
             cmdp->u.cache.sg_canz = (ulong32)i;
 
 #ifdef GDTH_STATISTICS
@@ -2850,15 +2984,24 @@
             if (i<GDTH_MAXSG)
                 cmdp->u.cache.sg_lst[i].sg_len = 0;
         } else {
+#if LINUX_VERSION_CODE >= 0x020400
+            scp->SCp.Status = GDTH_MAP_SINGLE;
+            scp->SCp.Message = (read_write == 1 ? 
+                PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);   
+            phys_addr = pci_map_single(ha->pdev,scp->request_buffer,
+                                       scp->request_bufflen,scp->SCp.Message);
+            scp->SCp.dma_handle = phys_addr;
+#else
+            phys_addr = virt_to_bus(scp->request_buffer);
+#endif
             if (ha->cache_feat & SCATTER_GATHER) {
                 cmdp->u.cache.DestAddr = 0xffffffff;
                 cmdp->u.cache.sg_canz = 1;
-                cmdp->u.cache.sg_lst[0].sg_ptr = 
-                    virt_to_bus(scp->request_buffer);
+                cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr;
                 cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
                 cmdp->u.cache.sg_lst[1].sg_len = 0;
             } else {
-                cmdp->u.cache.DestAddr  = virt_to_bus(scp->request_buffer);
+                cmdp->u.cache.DestAddr  = phys_addr;
                 cmdp->u.cache.sg_canz= 0;
             }
         }
@@ -2896,12 +3039,18 @@
     register gdth_cmd_str *cmdp;
     struct scatterlist *sl;
     ushort i;
-    int cmd_index;
+    ulong32 phys_addr, sense_paddr;
+    int cmd_index, sgcnt;
     unchar t,l;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
+#if LINUX_VERSION_CODE >= 0x02053C
     t = scp->device->id;
     l = scp->device->lun;
+#else
+    t = scp->target;
+    l = scp->lun;
+#endif
     cmdp = ha->pccb;
     TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
            scp->cmnd[0],b,t,l));
@@ -2931,6 +3080,13 @@
         /* evaluate command size */
         ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst);
     } else {
+#if LINUX_VERSION_CODE >= 0x020400
+        sense_paddr = pci_map_single(ha->pdev,scp->sense_buffer,
+                                     16,PCI_DMA_FROMDEVICE);
+        scp->SCp.buffer = (struct scatterlist *)sense_paddr;
+#else
+        sense_paddr = virt_to_bus(scp->sense_buffer);
+#endif
         cmdp->OpCode           = GDT_WRITE;             /* always */
         cmdp->BoardNode        = LOCALBOARD;
         cmdp->u.raw.reserved   = 0;
@@ -2944,7 +3100,7 @@
         cmdp->u.raw.link_p     = 0;
         cmdp->u.raw.sdlen      = scp->request_bufflen;
         cmdp->u.raw.sense_len  = 16;
-        cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
+        cmdp->u.raw.sense_data = sense_paddr;
         cmdp->u.raw.direction  = 
             gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
         memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
@@ -2952,10 +3108,21 @@
         if (scp->use_sg) {
             cmdp->u.raw.sdata  = 0xffffffff;
             sl = (struct scatterlist *)scp->request_buffer;
-            for (i=0; i<scp->use_sg; ++i,++sl) {
+            sgcnt = scp->use_sg;
+#if LINUX_VERSION_CODE >= 0x020400
+            scp->SCp.Status = GDTH_MAP_SG;
+            scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; 
+            sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
+            for (i=0; i<sgcnt; ++i,++sl) {
+                cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl);
+                cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl);
+            }
+#else
+            for (i=0; i<sgcnt; ++i,++sl) {
                 cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
                 cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
             }
+#endif
             cmdp->u.raw.sg_ranz = (ulong32)i;
 
 #ifdef GDTH_STATISTICS
@@ -2967,14 +3134,23 @@
             if (i<GDTH_MAXSG)
                 cmdp->u.raw.sg_lst[i].sg_len = 0;
         } else {
+#if LINUX_VERSION_CODE >= 0x020400
+            scp->SCp.Status = GDTH_MAP_SINGLE;
+            scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; 
+            phys_addr = pci_map_single(ha->pdev,scp->request_buffer,
+                                       scp->request_bufflen,scp->SCp.Message);
+            scp->SCp.dma_handle = phys_addr;
+#else
+            phys_addr = virt_to_bus(scp->request_buffer);
+#endif
             if (ha->raw_feat & SCATTER_GATHER) {
                 cmdp->u.raw.sdata  = 0xffffffff;
                 cmdp->u.raw.sg_ranz= 1;
-                cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
+                cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr;
                 cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
                 cmdp->u.raw.sg_lst[1].sg_len = 0;
             } else {
-                cmdp->u.raw.sdata  = virt_to_bus(scp->request_buffer);
+                cmdp->u.raw.sdata  = phys_addr;
                 cmdp->u.raw.sg_ranz= 0;
             }
         }
@@ -3372,9 +3548,19 @@
     if (rval == 2) {
         gdth_putq(hanum,scp,scp->SCp.this_residual);
     } else if (rval == 1) {
+#if LINUX_VERSION_CODE >= 0x02053C
         GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
         scp->scsi_done(scp);
-        GDTH_UNLOCK_SCSI_DONE(scp->host,flags);
+        GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
+#elif LINUX_VERSION_CODE >= 0x020503
+        GDTH_LOCK_SCSI_DONE(scp->host, flags);
+        scp->scsi_done(scp);
+        GDTH_UNLOCK_SCSI_DONE(scp->host, flags);
+#else
+        GDTH_LOCK_SCSI_DONE(flags);
+        scp->scsi_done(scp);
+        GDTH_UNLOCK_SCSI_DONE(flags);
+#endif
     }
     gdth_next(hanum);
 }
@@ -3384,7 +3570,7 @@
     register gdth_ha_str *ha;
     gdth_msg_str *msg;
     gdth_cmd_str *cmdp;
-    unchar b;
+    unchar b, t;
 
     ha   = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
@@ -3413,7 +3599,7 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
-            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
+            cmdp->u.screen.su.msg.msg_addr  = ha->scratch_phys;
             ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
@@ -3448,7 +3634,7 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
-            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
+            cmdp->u.screen.su.msg.msg_addr  = ha->scratch_phys;
             ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
@@ -3461,11 +3647,35 @@
         printk("\n");
 
     } else {
+#if LINUX_VERSION_CODE >= 0x02053C
         b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        t = scp->device->id;
+#else
+        b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        t = scp->target;
+#endif
         if (scp->SCp.sent_command == -1 && b != ha->virt_bus) {
-            ha->raw[BUS_L2P(ha,b)].io_cnt[scp->device->id]--;
+            ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
         }
         /* cache or raw service */
+        if (ha->status == S_BSY) {
+            TRACE2(("Controller busy -> retry !\n"));
+            if (scp->SCp.sent_command == GDT_MOUNT)
+                scp->SCp.sent_command = GDT_CLUST_INFO;
+            /* retry */
+            return 2;
+        }
+#if LINUX_VERSION_CODE >= 0x020400
+        if (scp->SCp.Status == GDTH_MAP_SG) 
+            pci_unmap_sg(ha->pdev,scp->request_buffer,
+                         scp->use_sg,scp->SCp.Message);
+        else if (scp->SCp.Status == GDTH_MAP_SINGLE) 
+            pci_unmap_single(ha->pdev,scp->SCp.dma_handle,
+                         scp->request_bufflen,scp->SCp.Message);
+        if (scp->SCp.buffer)
+            pci_unmap_single(ha->pdev,(dma_addr_t)scp->SCp.buffer,
+                             16,PCI_DMA_FROMDEVICE);
+#endif
         if (ha->status == S_OK) {
             scp->SCp.Status = S_OK;
             scp->SCp.Message = ha->info;
@@ -3474,12 +3684,12 @@
                         scp->SCp.sent_command));
                 /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */
                 if (scp->SCp.sent_command == GDT_CLUST_INFO) {
-                    ha->hdr[scp->device->id].cluster_type = (unchar)ha->info;
-                    if (!(ha->hdr[scp->device->id].cluster_type & 
+                    ha->hdr[t].cluster_type = (unchar)ha->info;
+                    if (!(ha->hdr[t].cluster_type & 
                         CLUSTER_MOUNTED)) {
                         /* NOT MOUNTED -> MOUNT */
                         scp->SCp.sent_command = GDT_MOUNT;
-                        if (ha->hdr[scp->device->id].cluster_type & 
+                        if (ha->hdr[t].cluster_type & 
                             CLUSTER_RESERVED) {
                             /* cluster drive RESERVED (on the other node) */
                             scp->SCp.phase = -2;      /* reservation conflict */
@@ -3489,11 +3699,11 @@
                     }
                 } else {
                     if (scp->SCp.sent_command == GDT_MOUNT) {
-                        ha->hdr[scp->device->id].cluster_type |= CLUSTER_MOUNTED;
-                        ha->hdr[scp->device->id].media_changed = TRUE;
+                        ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
+                        ha->hdr[t].media_changed = TRUE;
                     } else if (scp->SCp.sent_command == GDT_UNMOUNT) {
-                        ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_MOUNTED;
-                        ha->hdr[scp->device->id].media_changed = TRUE;
+                        ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED;
+                        ha->hdr[t].media_changed = TRUE;
                     } 
                     scp->SCp.sent_command = -1;
                 }
@@ -3503,21 +3713,13 @@
             } else {
                 /* RESERVE/RELEASE ? */
                 if (scp->cmnd[0] == RESERVE) {
-                    ha->hdr[scp->device->id].cluster_type |= CLUSTER_RESERVED;
+                    ha->hdr[t].cluster_type |= CLUSTER_RESERVED;
                 } else if (scp->cmnd[0] == RELEASE) {
-                    ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_RESERVED;
+                    ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
                 }           
                 scp->result = DID_OK << 16;
                 scp->sense_buffer[0] = 0;
             }
-        } else if (ha->status == S_BSY) {
-            TRACE2(("Controller busy -> retry !\n"));
-            scp->SCp.Status = S_BSY;
-            scp->SCp.Message = ha->info;
-            if (scp->SCp.sent_command == GDT_MOUNT)
-                scp->SCp.sent_command = GDT_CLUST_INFO;
-            /* retry */
-            return 2;
         } else {
             scp->SCp.Status = ha->status;
             scp->SCp.Message = ha->info;
@@ -3538,10 +3740,10 @@
                 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
             } else if (service == CACHESERVICE) {
                 if (ha->status == S_CACHE_UNKNOWN &&
-                    (ha->hdr[scp->device->id].cluster_type & 
+                    (ha->hdr[t].cluster_type & 
                      CLUSTER_RESERVE_STATE) == CLUSTER_RESERVE_STATE) {
                     /* bus reset -> force GDT_CLUST_INFO */
-                    ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_RESERVED;
+                    ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
                 }
                 memset((char*)scp->sense_buffer,0,16);
                 if (ha->status == (ushort)S_CACHE_RESERV) {
@@ -3560,7 +3762,7 @@
                     ha->dvr.eu.sync.service = service;
                     ha->dvr.eu.sync.status  = ha->status;
                     ha->dvr.eu.sync.info    = ha->info;
-                    ha->dvr.eu.sync.hostdrive = scp->device->id;
+                    ha->dvr.eu.sync.hostdrive = t;
                     if (ha->status >= 0x8000)
                         gdth_store_event(ha, ES_SYNC, 0, &ha->dvr);
                     else
@@ -3765,7 +3967,7 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE;
-            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
+            cmdp->u.screen.su.msg.msg_addr  = ha->scratch_phys;
             ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
@@ -4028,8 +4230,8 @@
             break;
         if (gdth_search_isa(isa_bios)) {        /* controller found */
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
-	    if(shp == NULL)
-		    continue;
+            if (shp == NULL)
+                continue;  
 
             ha = HADATA(shp);
             if (!gdth_init_isa(isa_bios,ha)) {
@@ -4076,11 +4278,15 @@
             NUMDATA(shp)->busnum= 0;
 
             ha->pccb = CMDDATA(shp);
-#if LINUX_VERSION_CODE >= 0x020322
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
-                                                     GDTH_SCRATCH_ORD);
+            ha->ccb_phys = 0L;
+#if LINUX_VERSION_CODE >= 0x020400
+            ha->pdev = NULL;
+            ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
+                                                &ha->scratch_phys); 
 #else
             ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+            if (ha->pscratch)
+                ha->scratch_phys = virt_to_bus(ha->pscratch);
 #endif
             ha->scratch_busy = FALSE;
             ha->req_first = NULL;
@@ -4095,12 +4301,14 @@
                 printk("GDT-ISA: Error during device scan\n");
                 --gdth_ctr_count;
                 --gdth_ctr_vcount;
-                if (ha->pscratch != NULL)
-#if LINUX_VERSION_CODE >= 0x020322
-                    free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
+                if (ha->pscratch != NULL) {
+#if LINUX_VERSION_CODE >= 0x020400
+                    pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
+                                        ha->pscratch, ha->scratch_phys);
 #else
                     scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
 #endif
+                }
 #if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,ha);
 #else
@@ -4145,8 +4353,8 @@
             break;
         if (gdth_search_eisa(eisa_slot)) {      /* controller found */
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
-	    if(shp == NULL)
-		    continue;
+            if (shp == NULL)
+                continue;  
 
             ha = HADATA(shp);
             if (!gdth_init_eisa(eisa_slot,ha)) {
@@ -4180,11 +4388,19 @@
                     NUMDATA(shp)->hanum));
 
             ha->pccb = CMDDATA(shp);
-#if LINUX_VERSION_CODE >= 0x020322
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
-                                                     GDTH_SCRATCH_ORD);
+            ha->ccb_phys = 0L; 
+#if LINUX_VERSION_CODE >= 0x020400
+            ha->pdev = NULL;
+            ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
+                                                &ha->scratch_phys); 
+            ha->ccb_phys = 
+                pci_map_single(ha->pdev,ha->pccb,
+                               sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
 #else
             ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+            if (ha->pscratch)
+                ha->scratch_phys = virt_to_bus(ha->pscratch);
+            ha->ccb_phys = virt_to_bus(ha->pccb);
 #endif
             ha->scratch_busy = FALSE;
             ha->req_first = NULL;
@@ -4199,12 +4415,16 @@
                 printk("GDT-EISA: Error during device scan\n");
                 --gdth_ctr_count;
                 --gdth_ctr_vcount;
-                if (ha->pscratch != NULL)
-#if LINUX_VERSION_CODE >= 0x020322
-                    free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
+                if (ha->pscratch != NULL) {
+#if LINUX_VERSION_CODE >= 0x020400
+                    pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
+                                        ha->pscratch, ha->scratch_phys);
+                    pci_unmap_single(ha->pdev,ha->ccb_phys,
+                                    sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
 #else
                     scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
 #endif
+                }
 #if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,ha);
 #else
@@ -4252,14 +4472,14 @@
         gdth_pci_str pcistr[MAXHA];
 
         cnt = gdth_search_pci(pcistr);
-	printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt);
+        printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt);
         gdth_sort_pci(pcistr,cnt);
         for (ctr = 0; ctr < cnt; ++ctr) {
             if (gdth_ctr_count >= MAXHA)
                 break;
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
-	    if(shp == NULL)
-		    continue;
+            if (shp == NULL)
+                continue;  
 
             ha = HADATA(shp);
             if (!gdth_init_pci(&pcistr[ctr],ha)) {
@@ -4293,11 +4513,14 @@
             NUMDATA(shp)->busnum= 0;
 
             ha->pccb = CMDDATA(shp);
-#if LINUX_VERSION_CODE >= 0x020322
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
-                                                     GDTH_SCRATCH_ORD);
+            ha->ccb_phys = 0L;
+#if LINUX_VERSION_CODE >= 0x020400
+            ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
+                                                &ha->scratch_phys); 
 #else
             ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+            if (ha->pscratch)
+                ha->scratch_phys = virt_to_bus(ha->pscratch);
 #endif
             ha->scratch_busy = FALSE;
             ha->req_first = NULL;
@@ -4312,12 +4535,14 @@
                 printk("GDT-PCI: Error during device scan\n");
                 --gdth_ctr_count;
                 --gdth_ctr_vcount;
-                if (ha->pscratch != NULL)
-#if LINUX_VERSION_CODE >= 0x020322
-                    free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
+                if (ha->pscratch != NULL) {
+#if LINUX_VERSION_CODE >= 0x020400
+                    pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
+                                        ha->pscratch, ha->scratch_phys);
 #else
                     scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
 #endif
+                }
 #if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,ha);
 #else
@@ -4365,6 +4590,9 @@
         gdth_timer.function = gdth_timeout;
         add_timer(&gdth_timer);
 #endif
+#ifdef GDTH_IOCTL_CHRDEV
+        major = register_chrdev(0,"gdth",&gdth_fops);
+#endif
 #if LINUX_VERSION_CODE >= 0x020100
         register_reboot_notifier(&gdth_notifier);
 #endif
@@ -4399,8 +4627,12 @@
             free_dma(shp->dma_channel);
         }
 #endif
-#if LINUX_VERSION_CODE >= 0x020322
-        free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
+#if LINUX_VERSION_CODE >= 0x020400
+        pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
+            ha->pscratch, ha->scratch_phys);
+        if (ha->ccb_phys)
+            pci_unmap_single(ha->pdev,ha->ccb_phys,
+                             sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
 #else
         scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
 #endif
@@ -4412,6 +4644,9 @@
 #ifdef GDTH_STATISTICS
             del_timer(&gdth_timer);
 #endif
+#ifdef GDTH_IOCTL_CHRDEV
+            unregister_chrdev(major,"gdth");
+#endif
 #if LINUX_VERSION_CODE >= 0x020100
             unregister_reboot_notifier(&gdth_notifier);
 #endif
@@ -4507,15 +4742,24 @@
     unchar b;
 
     TRACE2(("gdth_eh_bus_reset()\n"));
+#if LINUX_VERSION_CODE >= 0x02053C
     hanum = NUMDATA(scp->device->host)->hanum;
     b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+#else
+    hanum = NUMDATA(scp->host)->hanum;
+    b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+#endif
     ha    = HADATA(gdth_ctr_tab[hanum]);
 
     /* clear command tab */
     GDTH_LOCK_HA(ha, flags);
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
         cmnd = ha->cmd_tab[i].cmnd;
+#if LINUX_VERSION_CODE >= 0x02053C
         if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b)
+#else
+        if (!SPECIAL_SCP(cmnd) && cmnd->channel == b)
+#endif
             ha->cmd_tab[i].cmnd = UNUSED_CMND;
     }
     GDTH_UNLOCK_HA(ha, flags);
@@ -4558,16 +4802,31 @@
 }
 #endif
 
-int gdth_bios_param(struct scsi_device *sdev, struct block_device *bdev,
-		sector_t capacity, int *ip)
+
+#if LINUX_VERSION_CODE >= 0x020503
+int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip)
+#elif LINUX_VERSION_CODE >= 0x010300
+int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
+#else
+int gdth_bios_param(Disk *disk,int dev,int *ip)
+#endif
 {
     unchar b, t;
     int hanum;
     gdth_ha_str *ha;
+    struct scsi_device *sd;
+    unsigned capacity;
 
-    hanum = NUMDATA(sdev->host)->hanum;
-    b = virt_ctr ? NUMDATA(sdev->host)->busnum : sdev->channel;
-    t = sdev->id;
+#if LINUX_VERSION_CODE >= 0x020503
+    sd = sdev;
+    capacity = cap;
+#else
+    sd = disk->device;
+    capacity = disk->capacity;
+#endif
+    hanum = NUMDATA(sd->host)->hanum;
+    b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel;
+    t = sd->id;
     TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t)); 
     ha = HADATA(gdth_ctr_tab[hanum]);
 
@@ -4592,14 +4851,19 @@
     int hanum;
     int priority;
 
-    TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n",
-           scp->cmnd[0],scp->device->id,scp->lun));
+    TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
     
     scp->scsi_done = (void *)done;
     scp->SCp.have_data_in = 1;
     scp->SCp.phase = -1;
     scp->SCp.sent_command = -1;
+    scp->SCp.Status = GDTH_MAP_NONE;
+    scp->SCp.buffer = (struct scatterlist *)NULL;
+#if LINUX_VERSION_CODE >= 0x02053C
     hanum = NUMDATA(scp->device->host)->hanum;
+#else
+    hanum = NUMDATA(scp->host)->hanum;
+#endif
 #ifdef GDTH_STATISTICS
     ++act_ios;
 #endif
@@ -4615,6 +4879,667 @@
     return 0;
 }
 
+#ifdef GDTH_IOCTL_CHRDEV
+static int gdth_open(struct inode *inode, struct file *filep)
+{
+    TRACE(("gdth_open()\n"));
+    return 0;
+}
+
+static int gdth_close(struct inode *inode, struct file *filep)
+{
+    TRACE(("gdth_close()\n"));
+    return 0;
+}
+
+static int gdth_ioctl(struct inode *inode, struct file *filep,
+                      unsigned int cmd, unsigned long arg)
+{
+    gdth_ha_str *ha; 
+#if LINUX_VERSION_CODE >= 0x020503
+    Scsi_Request *srp;
+    Scsi_Cmnd *scp;
+    Scsi_Device *sdev;
+#elif LINUX_VERSION_CODE >= 0x020322
+    Scsi_Cmnd *scp;
+    Scsi_Device *sdev;
+#else
+    Scsi_Cmnd scp;
+    Scsi_Device sdev;
+#endif
+    ulong flags;
+    char cmnd[MAX_COMMAND_SIZE];   
+    memset(cmnd, 0xff, 12);
+    
+    TRACE(("gdth_ioctl() cmd 0x%x\n", cmd));
+ 
+    switch (cmd) {
+      case GDTIOCTL_CTRCNT:
+      { 
+        int cnt = gdth_ctr_count;
+        put_user(cnt, (int *)arg);
+        break;
+      }
+
+      case GDTIOCTL_DRVERS:
+      { 
+        int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
+        put_user(ver, (int *)arg);
+        break;
+      }
+      
+      case GDTIOCTL_OSVERS:
+      { 
+        gdth_ioctl_osvers osv; 
+
+        osv.version = (unchar)(LINUX_VERSION_CODE >> 16);
+        osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8);
+        osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff);
+        copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers));
+        break;
+      }
+
+      case GDTIOCTL_CTRTYPE:
+      { 
+        gdth_ioctl_ctrtype ctrt;
+        
+        if (copy_from_user(&ctrt, (char *)arg, sizeof(gdth_ioctl_ctrtype)) ||
+            ctrt.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        ha = HADATA(gdth_ctr_tab[ctrt.ionode]);
+        if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
+            ctrt.type = (unchar)((ha->stype>>20) - 0x10);
+        } else {
+            if (ha->type != GDT_PCIMPR) {
+                ctrt.type = (unchar)((ha->stype<<4) + 6);
+            } else {
+                ctrt.type = 
+                    (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe);
+                if (ha->stype >= 0x300)
+                    ctrt.ext_type = 0x6000 | ha->subdevice_id;
+                else 
+                    ctrt.ext_type = 0x6000 | ha->stype;
+            }
+            ctrt.device_id = ha->stype;
+            ctrt.sub_device_id = ha->subdevice_id;
+        }
+        ctrt.info = ha->brd_phys;
+        ctrt.oem_id = ha->oem_id;
+        if (copy_to_user((char *)arg, &ctrt, sizeof(gdth_ioctl_ctrtype)))
+            return -EFAULT;
+        break;
+      }
+        
+      case GDTIOCTL_GENERAL:
+      {
+        gdth_ioctl_general gen;
+        char *buf = NULL;
+        ulong32 paddr; 
+        int hanum;
+        
+        if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) ||
+            gen.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        hanum = gen.ionode; 
+        ha = HADATA(gdth_ctr_tab[hanum]);
+        if (gen.data_len + gen.sense_len != 0) {
+            if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, 
+                                         FALSE, &paddr)))
+                return -EFAULT;
+            if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general),  
+                               gen.data_len + gen.sense_len)) {
+                gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+                return -EFAULT;
+            }
+
+            if (gen.command.OpCode == GDT_IOCTL) {
+                gen.command.u.ioctl.p_param = paddr;
+            } else if (gen.command.Service == CACHESERVICE) {
+                if (ha->cache_feat & SCATTER_GATHER) {
+                    gen.command.u.cache.DestAddr = 0xffffffff;
+                    gen.command.u.cache.sg_canz = 1;
+                    gen.command.u.cache.sg_lst[0].sg_ptr = paddr;
+                    gen.command.u.cache.sg_lst[0].sg_len = gen.data_len;
+                    gen.command.u.cache.sg_lst[1].sg_len = 0;
+                } else {
+                    gen.command.u.cache.DestAddr = paddr;
+                    gen.command.u.cache.sg_canz = 0;
+                }
+            } else if (gen.command.Service == SCSIRAWSERVICE) {
+                if (ha->raw_feat & SCATTER_GATHER) {
+                    gen.command.u.raw.sdata = 0xffffffff;
+                    gen.command.u.raw.sg_ranz = 1;
+                    gen.command.u.raw.sg_lst[0].sg_ptr = paddr;
+                    gen.command.u.raw.sg_lst[0].sg_len = gen.data_len;
+                    gen.command.u.raw.sg_lst[1].sg_len = 0;
+                } else {
+                    gen.command.u.raw.sdata = paddr;
+                    gen.command.u.raw.sg_ranz = 0;
+                }
+                gen.command.u.raw.sense_data = paddr + gen.data_len;
+
+            } else {
+                gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+                return -EFAULT;
+            }
+        }
+
+#if LINUX_VERSION_CODE >= 0x020503
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        srp  = scsi_allocate_request(sdev);
+        if (!srp)
+            return -ENOMEM;
+        srp->sr_cmd_len = 12;
+        srp->sr_use_sg = 0;
+        gdth_do_req(srp, &gen.command, cmnd, gen.timeout);
+        gen.status = srp->sr_command->SCp.Status;
+        gen.info = srp->sr_command->SCp.Message;
+        scsi_release_request(srp);
+        scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
+        if (!scp)
+            return -ENOMEM;
+        scp->cmd_len = 12;
+        scp->use_sg = 0;
+        gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout);
+        gen.status = scp->SCp.Status;
+        gen.info = scp->SCp.Message;
+        scsi_release_command(scp);
+        scsi_free_host_dev(sdev);
+#else
+        memset(&sdev,0,sizeof(Scsi_Device));
+        memset(&scp, 0,sizeof(Scsi_Cmnd));
+        sdev.host = scp.host = gdth_ctr_tab[hanum];
+        sdev.id = scp.target = sdev.host->this_id;
+        scp.device = &sdev;
+        gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout);
+        gen.status = scp.SCp.Status;
+        gen.info = scp.SCp.Message;
+#endif
+
+        if (copy_to_user((char *)arg + sizeof(gdth_ioctl_general), buf, 
+                         gen.data_len + gen.sense_len)) {
+            gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+            return -EFAULT; 
+        } 
+        if (copy_to_user((char *)arg, &gen, 
+            sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) {
+            gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+            return -EFAULT;
+        }
+        gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+        break;
+      }
+ 
+      case GDTIOCTL_EVENT:
+      {
+        gdth_ioctl_event evt;
+        gdth_ha_str *ha;
+        ulong flags;
+
+        if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) ||
+            evt.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        ha = HADATA(gdth_ctr_tab[evt.ionode]);
+
+        if (evt.erase == 0xff) {
+            if (evt.event.event_source == ES_TEST)
+                evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); 
+            else if (evt.event.event_source == ES_DRIVER)
+                evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); 
+            else if (evt.event.event_source == ES_SYNC)
+                evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); 
+            else
+                evt.event.event_data.size=sizeof(evt.event.event_data.eu.async);
+            GDTH_LOCK_HA(ha, flags);
+            gdth_store_event(ha, evt.event.event_source, evt.event.event_idx,
+                             &evt.event.event_data);
+            GDTH_UNLOCK_HA(ha, flags);
+        } else if (evt.erase == 0xfe) {
+            gdth_clear_events();
+        } else if (evt.erase == 0) {
+            evt.handle = gdth_read_event(ha, evt.handle, &evt.event);
+        } else {
+            gdth_readapp_event(ha, evt.erase, &evt.event);
+        }     
+        if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event)))
+            return -EFAULT;
+        break;
+      }
+
+      case GDTIOCTL_LOCKDRV:
+      {
+        gdth_ioctl_lockdrv ldrv;
+        unchar i, j;
+
+        if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) ||
+            ldrv.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        ha = HADATA(gdth_ctr_tab[ldrv.ionode]);
+ 
+        for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) {
+            j = ldrv.drives[i];
+            if (j >= MAX_HDRIVES || !ha->hdr[j].present)
+                continue;
+            if (ldrv.lock) {
+                GDTH_LOCK_HA(ha, flags);
+                ha->hdr[j].lock = 1;
+                GDTH_UNLOCK_HA(ha, flags);
+                gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); 
+                gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); 
+            } else {
+                GDTH_LOCK_HA(ha, flags);
+                ha->hdr[j].lock = 0;
+                GDTH_UNLOCK_HA(ha, flags);
+                gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); 
+                gdth_next(ldrv.ionode); 
+            }
+        } 
+        break;
+      }
+
+      case GDTIOCTL_LOCKCHN:
+      {
+        gdth_ioctl_lockchn lchn;
+        unchar i, j;
+
+        if (copy_from_user(&lchn, (char *)arg, sizeof(gdth_ioctl_lockchn)) ||
+            lchn.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        ha = HADATA(gdth_ctr_tab[lchn.ionode]);
+        
+        i = lchn.channel;
+        if (i < ha->bus_cnt) {
+            if (lchn.lock) {
+                GDTH_LOCK_HA(ha, flags);
+                ha->raw[i].lock = 1;
+                GDTH_UNLOCK_HA(ha, flags);
+                for (j = 0; j < ha->tid_cnt; ++j) {
+                    gdth_wait_completion(lchn.ionode, i, j); 
+                    gdth_stop_timeout(lchn.ionode, i, j); 
+                }
+            } else {
+                GDTH_LOCK_HA(ha, flags);
+                ha->raw[i].lock = 0;
+                GDTH_UNLOCK_HA(ha, flags);
+                for (j = 0; j < ha->tid_cnt; ++j) {
+                    gdth_start_timeout(lchn.ionode, i, j); 
+                    gdth_next(lchn.ionode); 
+                }
+            }
+        } 
+        break;
+      }
+
+      case GDTIOCTL_RESCAN:
+      {
+        gdth_ioctl_rescan rsc;
+        gdth_cmd_str cmd;
+        ushort i, status, hdr_cnt;
+        ulong32 info;
+        int hanum, cyls, hds, secs;
+        
+        if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) ||
+            rsc.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        hanum = rsc.ionode;
+        ha = HADATA(gdth_ctr_tab[hanum]);
+
+#if LINUX_VERSION_CODE >= 0x020503
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        srp  = scsi_allocate_request(sdev);
+        if (!srp)
+            return -ENOMEM;
+        srp->sr_cmd_len = 12;
+        srp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= 0x020322
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
+        if (!scp)
+            return -ENOMEM;
+        scp->cmd_len = 12;
+        scp->use_sg = 0;
+#else
+        memset(&sdev,0,sizeof(Scsi_Device));
+        memset(&scp, 0,sizeof(Scsi_Cmnd));
+        sdev.host = scp.host = gdth_ctr_tab[hanum];
+        sdev.id = scp.target = sdev.host->this_id;
+        scp.device = &sdev;
+#endif
+     
+        if (rsc.flag == 0) {
+            /* old method: re-init. cache service */
+            cmd.Service = CACHESERVICE;
+            cmd.OpCode = GDT_INIT;
+            cmd.u.cache.DeviceNo = LINUX_OS;
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(srp, &cmd, cmnd, 30);
+            status = (ushort)srp->sr_command->SCp.Status;
+            info = (ulong32)srp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &cmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status;
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &cmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            i = 0;
+            hdr_cnt = (status == S_OK ? (ushort)info : 0);
+        } else {
+            i = rsc.hdr_no;
+            hdr_cnt = i + 1;
+        }
+        for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) {
+            cmd.Service = CACHESERVICE;
+            cmd.OpCode = GDT_INFO;
+            cmd.u.cache.DeviceNo = i;
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(srp, &cmd, cmnd, 30);
+            status = (ushort)srp->sr_command->SCp.Status;
+            info = (ulong32)srp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &cmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status;
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &cmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            GDTH_LOCK_HA(ha, flags);
+            rsc.hdr_list[i].bus = ha->virt_bus;
+            rsc.hdr_list[i].target = i;
+            rsc.hdr_list[i].lun = 0;
+            if (status != S_OK) {
+                ha->hdr[i].present = FALSE;
+            } else {
+                ha->hdr[i].present = TRUE;
+                ha->hdr[i].size = info;
+                /* evaluate mapping */
+                ha->hdr[i].size &= ~SECS32;
+                gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs); 
+                ha->hdr[i].heads = hds;
+                ha->hdr[i].secs = secs;
+                /* round size */
+                ha->hdr[i].size = cyls * hds * secs;
+            }
+            GDTH_UNLOCK_HA(ha, flags);
+            if (status != S_OK)
+                continue; 
+
+            /* devtype, cluster info, R/W attribs */
+            cmd.Service = CACHESERVICE;
+            cmd.OpCode = GDT_DEVTYPE;
+            cmd.u.cache.DeviceNo = i;
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(srp, &cmd, cmnd, 30);
+            status = (ushort)srp->sr_command->SCp.Status;
+            info = (ulong32)srp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &cmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status;
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &cmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            GDTH_LOCK_HA(ha, flags);
+            ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0);
+            GDTH_UNLOCK_HA(ha, flags);
+
+            cmd.Service = CACHESERVICE;
+            cmd.OpCode = GDT_CLUST_INFO;
+            cmd.u.cache.DeviceNo = i;
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(srp, &cmd, cmnd, 30);
+            status = (ushort)srp->sr_command->SCp.Status;
+            info = (ulong32)srp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &cmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status;
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &cmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            GDTH_LOCK_HA(ha, flags);
+            ha->hdr[i].cluster_type = 
+                ((status == S_OK && !shared_access) ? (ushort)info : 0);
+            GDTH_UNLOCK_HA(ha, flags);
+            rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+
+            cmd.Service = CACHESERVICE;
+            cmd.OpCode = GDT_RW_ATTRIBS;
+            cmd.u.cache.DeviceNo = i;
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(srp, &cmd, cmnd, 30);
+            status = (ushort)srp->sr_command->SCp.Status;
+            info = (ulong32)srp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &cmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status;
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &cmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            GDTH_LOCK_HA(ha, flags);
+            ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0);
+            GDTH_UNLOCK_HA(ha, flags);
+        }
+#if LINUX_VERSION_CODE >= 0x020503
+        scsi_release_request(srp);
+        scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+        scsi_release_command(scp);
+        scsi_free_host_dev(sdev);
+#endif       
+ 
+        if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan)))
+            return -EFAULT;
+        break;
+      }
+  
+      case GDTIOCTL_HDRLIST:
+      {
+        gdth_ioctl_rescan rsc;
+        gdth_cmd_str cmd;
+        gdth_ha_str *ha;
+        unchar i;
+        int hanum;
+        
+        if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) ||
+            rsc.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        hanum = rsc.ionode;
+        ha = HADATA(gdth_ctr_tab[hanum]);
+   
+#if LINUX_VERSION_CODE >= 0x020503
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        srp  = scsi_allocate_request(sdev);
+        if (!srp)
+            return -ENOMEM;
+        srp->sr_cmd_len = 12;
+        srp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= 0x020322
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
+        if (!scp)
+            return -ENOMEM;
+        scp->cmd_len = 12;
+        scp->use_sg = 0;
+#else
+        memset(&sdev,0,sizeof(Scsi_Device));
+        memset(&scp, 0,sizeof(Scsi_Cmnd));
+        sdev.host = scp.host = gdth_ctr_tab[hanum];
+        sdev.id = scp.target = sdev.host->this_id;
+        scp.device = &sdev;
+#endif
+
+        for (i = 0; i < MAX_HDRIVES; ++i) { 
+            if (!ha->hdr[i].present) {
+                rsc.hdr_list[i].bus = 0xff; 
+                continue;
+            } 
+            rsc.hdr_list[i].bus = ha->virt_bus;
+            rsc.hdr_list[i].target = i;
+            rsc.hdr_list[i].lun = 0;
+            rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+            if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { 
+                cmd.Service = CACHESERVICE;
+                cmd.OpCode = GDT_CLUST_INFO;
+                cmd.u.cache.DeviceNo = i;
+#if LINUX_VERSION_CODE >= 0x020503
+                gdth_do_req(srp, &cmd, cmnd, 30);
+                if (srp->sr_command->SCp.Status == S_OK)
+                    rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
+                gdth_do_cmd(scp, &cmd, cmnd, 30);
+                if (scp->SCp.Status == S_OK)
+                    rsc.hdr_list[i].cluster_type = scp->SCp.Message;
+#else
+                gdth_do_cmd(&scp, &cmd, cmnd, 30);
+                if (scp.SCp.Status == S_OK)
+                    rsc.hdr_list[i].cluster_type = scp.SCp.Message;
+#endif
+            }
+        } 
+#if LINUX_VERSION_CODE >= 0x020503
+        scsi_release_request(srp);
+        scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+        scsi_release_command(scp);
+        scsi_free_host_dev(sdev);
+#endif       
+ 
+        if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan)))
+            return -EFAULT;
+        break;
+      }
+
+      case GDTIOCTL_RESET_BUS:
+      {
+        gdth_ioctl_reset res;
+        int hanum, rval;
+
+        if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
+            res.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        hanum = res.ionode; 
+
+        /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.5.x */        
+#if LINUX_VERSION_CODE >= 0x02053C
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        scp  = scsi_get_command(sdev, GFP_KERNEL);
+        if (!scp)
+            return -ENOMEM;
+        scp->cmd_len = 12;
+        scp->use_sg = 0;
+        scp->device->channel = virt_ctr ? 0 : res.number;
+        rval = gdth_eh_bus_reset(scp);
+        res.status = (rval == SUCCESS ? S_OK : S_GENERR);
+        scsi_put_command(scp);
+        scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+#if LINUX_VERSION_CODE >= 0x020503
+        scp  = scsi_allocate_device(sdev, 1);
+#else
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
+#endif
+        if (!scp)
+            return -ENOMEM;
+        scp->cmd_len = 12;
+        scp->use_sg = 0;
+        scp->channel = virt_ctr ? 0 : res.number;
+        rval = gdth_eh_bus_reset(scp);
+        res.status = (rval == SUCCESS ? S_OK : S_GENERR);
+        scsi_release_command(scp);
+        scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x02015F
+        memset(&sdev,0,sizeof(Scsi_Device));
+        memset(&scp, 0,sizeof(Scsi_Cmnd));
+        sdev.host = scp.host = gdth_ctr_tab[hanum];
+        sdev.id = scp.target = sdev.host->this_id;
+        scp.device = &sdev;
+        scp.channel = virt_ctr ? 0 : res.number;
+        rval = gdth_eh_bus_reset(&scp);
+        res.status = (rval == SUCCESS ? S_OK : S_GENERR);
+#else
+        res.status = S_OK;
+#endif
+        if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset)))
+            return -EFAULT;
+        break;
+      }
+
+      case GDTIOCTL_RESET_DRV:
+      {
+        gdth_ioctl_reset res;
+        gdth_cmd_str cmd;
+        int hanum;
+
+        if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
+            res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES)
+            return -EFAULT;
+        hanum = res.ionode;
+        ha = HADATA(gdth_ctr_tab[hanum]);
+ 
+        if (!ha->hdr[res.number].present)
+            return 0;
+        cmd.Service = CACHESERVICE;
+        cmd.OpCode = GDT_CLUST_RESET;
+        cmd.u.cache.DeviceNo = res.number;
+#if LINUX_VERSION_CODE >= 0x020503
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        srp  = scsi_allocate_request(sdev);
+        if (!srp)
+            return -ENOMEM;
+        srp->sr_cmd_len = 12;
+        srp->sr_use_sg = 0;
+        gdth_do_req(srp, &cmd, cmnd, 30);
+        res.status = (ushort)srp->sr_command->SCp.Status;
+        scsi_release_request(srp);
+        scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
+        if (!scp)
+            return -ENOMEM;
+        scp->cmd_len = 12;
+        scp->use_sg = 0;
+        gdth_do_cmd(scp, &cmd, cmnd, 30);
+        res.status = (ushort)scp->SCp.Status;
+        scsi_release_command(scp);
+        scsi_free_host_dev(sdev);
+#else
+        memset(&sdev,0,sizeof(Scsi_Device));
+        memset(&scp, 0,sizeof(Scsi_Cmnd));
+        sdev.host = scp.host = gdth_ctr_tab[hanum];
+        sdev.id = scp.target = sdev.host->this_id;
+        scp.device = &sdev;
+        gdth_do_cmd(&scp, &cmd, cmnd, 30);
+        res.status = (ushort)scp.SCp.Status;
+#endif
+        if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset)))
+            return -EFAULT;
+        break;
+      }
+
+      default:
+        break; 
+    }
+    return 0;
+}
+#endif
+
 #if LINUX_VERSION_CODE >= 0x010300
 /* flush routine */
 static void gdth_flush(int hanum)
@@ -4622,7 +5547,10 @@
     int             i;
     gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+    Scsi_Request    *srp;
+    Scsi_Device     *sdev;
+#elif LINUX_VERSION_CODE >= 0x020322
     Scsi_Cmnd       *scp;
     Scsi_Device     *sdev;
 #else
@@ -4635,9 +5563,18 @@
     TRACE2(("gdth_flush() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
     sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-    scp  = scsi_get_command(sdev, GFP_KERNEL);
+    srp  = scsi_allocate_request(sdev);
+    if (!srp)
+        return;
+    srp->sr_cmd_len = 12;
+    srp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= 0x020322
+    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+    scp  = scsi_allocate_device(sdev, 1, FALSE);
+    if (!scp)
+        return;
     scp->cmd_len = 12;
     scp->use_sg = 0;
 #else
@@ -4657,15 +5594,20 @@
             gdtcmd.u.cache.BlockNo = 1;
             gdtcmd.u.cache.sg_canz = 0;
             TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(srp, &gdtcmd, cmnd, 30);
+#elif LINUX_VERSION_CODE >= 0x020322
             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
 #else
             gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
 #endif
         }
     }
-#if LINUX_VERSION_CODE >= 0x020322
-    scsi_put_command(scp);
+#if LINUX_VERSION_CODE >= 0x020503
+    scsi_release_request(srp);
+    scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+    scsi_release_command(scp);
     scsi_free_host_dev(sdev);
 #endif
 }
@@ -4680,7 +5622,10 @@
     int             hanum;
 #ifndef __alpha__
     gdth_cmd_str    gdtcmd;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+    Scsi_Request    *srp;
+    Scsi_Device     *sdev;
+#elif LINUX_VERSION_CODE >= 0x020322
     Scsi_Cmnd       *scp;
     Scsi_Device     *sdev;
 #else
@@ -4702,6 +5647,7 @@
     }
     halt_called = TRUE;
 #endif
+
     printk("GDT: Flushing all host drives .. ");
     for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
         gdth_flush(hanum);
@@ -4709,28 +5655,48 @@
 #ifndef __alpha__
         /* controller reset */
         memset(cmnd, 0xff, MAX_COMMAND_SIZE);
-#if LINUX_VERSION_CODE >= 0x020322
+        gdtcmd.BoardNode = LOCALBOARD;
+        gdtcmd.Service = CACHESERVICE;
+        gdtcmd.OpCode = GDT_RESET;
+        TRACE2(("gdth_halt(): reset controller %d\n", hanum));
+#if LINUX_VERSION_CODE >= 0x020503
         sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-        scp  = scsi_get_command(sdev, GFP_KERNEL);
+        srp  = scsi_allocate_request(sdev);
+        if (!srp) {
+#if LINUX_VERSION_CODE >= 0x020100
+            unregister_reboot_notifier(&gdth_notifier);
+            return NOTIFY_OK;
+#else
+            return;
+#endif
+        }
+        srp->sr_cmd_len = 12;
+        srp->sr_use_sg = 0;
+        gdth_do_req(srp, &gdtcmd, cmnd, 10);
+        scsi_release_request(srp);
+        scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
+        if (!scp) {
+#if LINUX_VERSION_CODE >= 0x020100
+            unregister_reboot_notifier(&gdth_notifier);
+            return NOTIFY_OK;
+#else
+            return;
+#endif
+        }
         scp->cmd_len = 12;
         scp->use_sg = 0;
+        gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
+        scsi_release_command(scp);
+        scsi_free_host_dev(sdev);
 #else
         memset(&sdev,0,sizeof(Scsi_Device));
         memset(&scp, 0,sizeof(Scsi_Cmnd));
         sdev.host = scp.host = gdth_ctr_tab[hanum];
         sdev.id = scp.target = sdev.host->this_id;
         scp.device = &sdev;
-#endif
-
-        gdtcmd.BoardNode = LOCALBOARD;
-        gdtcmd.Service = CACHESERVICE;
-        gdtcmd.OpCode = GDT_RESET;
-        TRACE2(("gdth_halt(): reset controller %d\n", hanum));
-#if LINUX_VERSION_CODE >= 0x020322
-        gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
-        scsi_put_command(scp);
-        scsi_free_host_dev(sdev);
-#else
         gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
 #endif
 #endif
diff -urN linux-2.5.65-bk2/drivers/scsi/gdth.h linux-2.5.65-bk3/drivers/scsi/gdth.h
--- linux-2.5.65-bk2/drivers/scsi/gdth.h	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk3/drivers/scsi/gdth.h	Mon Mar 31 12:41:42 2003
@@ -10,7 +10,7 @@
  *
  * <achim.leubner@intel.com>
  *
- * $Id: gdth.h,v 1.46 2002/02/05 09:39:53 achim Exp $
+ * $Id: gdth.h,v 1.48 2003/02/27 14:58:22 achim Exp $
  */
 
 #include <linux/version.h>
@@ -29,16 +29,16 @@
 /* defines, macros */
 
 /* driver version */
-#define GDTH_VERSION_STR        "2.05"
+#define GDTH_VERSION_STR        "2.07"
 #define GDTH_VERSION            2
-#define GDTH_SUBVERSION         5
+#define GDTH_SUBVERSION         7
 
 /* protocol version */
 #define PROTOCOL_VERSION        1
 
 /* OEM IDs */
-#define OEM_ID_ICP	0x941c
-#define OEM_ID_INTEL	0x8000
+#define OEM_ID_ICP      0x941c
+#define OEM_ID_INTEL    0x8000
 
 /* controller classes */
 #define GDT_ISA         0x01                    /* ISA controller */
@@ -134,12 +134,17 @@
 
 #ifndef PCI_DEVICE_ID_VORTEX_GDTNEWRX
 /* new GDT Rx Controller */
-#define PCI_DEVICE_ID_VORTEX_GDTNEWRX	0x300
+#define PCI_DEVICE_ID_VORTEX_GDTNEWRX   0x300
 #endif
-	
+        
 #ifndef PCI_DEVICE_ID_INTEL_SRC
 /* Intel Storage RAID Controller */
-#define PCI_DEVICE_ID_INTEL_SRC		0x600
+#define PCI_DEVICE_ID_INTEL_SRC         0x600
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_SRC_XSCALE
+/* Intel Storage RAID Controller */
+#define PCI_DEVICE_ID_INTEL_SRC_XSCALE  0x601
 #endif
 
 /* limits */
@@ -153,8 +158,6 @@
 #define MAXID           127
 #define MAXLUN          8
 #define MAXBUS          6
-#define MAX_HDRIVES     100                     /* max. host drive count */
-#define MAX_LDRIVES     255                     /* max. log. drive count */
 #define MAX_EVENTS      100                     /* event buffer count */
 #define MAX_RES_ARGS    40                      /* device reservation, 
                                                    must be a multiple of 4 */
@@ -254,6 +257,7 @@
 #define CACHE_DRV_INFO  0x07                    /* cache drive info */
 #define BOARD_FEATURES  0x15                    /* controller features */
 #define BOARD_INFO      0x28                    /* controller info */
+#define CACHE_READ_OEM_STRING_RECORD 0x84       /* read OEM string record */ 
 #define HOST_GET        0x10001L                /* get host drive list */
 #define IO_CHANNEL      0x00020000L             /* default IO channel */
 #define INVALID_CHANNEL 0x0000ffffL             /* invalid channel */
@@ -265,7 +269,7 @@
 #define S_CACHE_UNKNOWN 12                      /* cache serv.: drive unknown */
 #define S_RAW_SCSI      12                      /* raw serv.: target error */
 #define S_RAW_ILL       0xff                    /* raw serv.: illegal */
-#define S_CACHE_RESERV	-24			/* cache: reserv. conflict */	
+#define S_CACHE_RESERV  -24                     /* cache: reserv. conflict */   
 
 /* timeout values */
 #define INIT_RETRIES    100000                  /* 100000 * 1ms = 100s */
@@ -292,10 +296,15 @@
 #define MAILBOXREG      0x0c90                  /* mailbox reg. (16 bytes) */
 #define EISAREG         0x0cc0                  /* EISA configuration */
 
+/* DMA memory mappings */
+#define GDTH_MAP_NONE   0
+#define GDTH_MAP_SINGLE 1
+#define GDTH_MAP_SG     2
+#define GDTH_MAP_IOCTL  3 
+
 /* other defines */
 #define LINUX_OS        8                       /* used for cache optim. */
 #define SCATTER_GATHER  1                       /* s/g feature */
-#define GDTH_MAXSG      32                      /* max. s/g elements */
 #define SECS32          0x1f                    /* round capacity */
 #define BIOS_ID_OFFS    0x10                    /* offset contr-ID in ISABIOS */
 #define LOCALBOARD      0                       /* board node always 0 */
@@ -303,10 +312,7 @@
 #define SPEZINDEX       1                       /* cmd index unknown service */
 #define GDT_WR_THROUGH  0x100                   /* WRITE_THROUGH supported */
 
-
-/* typedefs */
-typedef u32     ulong32;
-#define PACKED  __attribute__((packed))
+#include "gdth_ioctl.h"
 
 /* screenservice message */
 typedef struct {                               
@@ -535,6 +541,50 @@
     unchar      ld_error;                       /* error */
 } PACKED gdth_cdrinfo_str;
 
+/* OEM string */
+typedef struct {
+    ulong32     ctl_version;
+    ulong32     file_major_version;
+    ulong32     file_minor_version;
+    ulong32     buffer_size;
+    ulong32     cpy_count;
+    ulong32     ext_error;
+    ulong32     oem_id;
+    ulong32     board_id;
+} PACKED gdth_oem_str_params;
+
+typedef struct {
+    unchar      product_0_1_name[16];
+    unchar      product_4_5_name[16];
+    unchar      product_cluster_name[16];
+    unchar      product_reserved[16];
+    unchar      scsi_cluster_target_vendor_id[16];
+    unchar      cluster_raid_fw_name[16];
+    unchar      oem_brand_name[16];
+    unchar      oem_raid_type[16];
+    unchar      bios_type[13];
+    unchar      bios_title[50];
+    unchar      oem_company_name[37];
+    ulong32     pci_id_1;
+    ulong32     pci_id_2;
+    unchar      validation_status[80];
+    unchar      reserved_1[4];
+    unchar      scsi_host_drive_inquiry_vendor_id[16];
+    unchar      library_file_template[16];
+    unchar      reserved_2[16];
+    unchar      tool_name_1[32];
+    unchar      tool_name_2[32];
+    unchar      tool_name_3[32];
+    unchar      oem_contact_1[84];
+    unchar      oem_contact_2[84];
+    unchar      oem_contact_3[84];
+} PACKED gdth_oem_str;
+
+typedef struct {
+    gdth_oem_str_params params;
+    gdth_oem_str        text;
+} PACKED gdth_oem_str_ioctl;
+
 /* board features */
 typedef struct {
     unchar      chaining;                       /* Chaining supported */
@@ -594,118 +644,6 @@
     gdth_hentry_str entry[MAX_HDRIVES];         /* entries */
 } PACKED gdth_hget_str;    
 
-/* scatter/gather element */
-typedef struct {
-    ulong32     sg_ptr;                         /* address */
-    ulong32     sg_len;                         /* length */
-} PACKED gdth_sg_str;
-
-/* command structure */
-typedef struct {
-    ulong32     BoardNode;                      /* board node (always 0) */
-    ulong32     CommandIndex;                   /* command number */
-    ushort      OpCode;                         /* the command (READ,..) */
-    union {
-        struct {
-            ushort      DeviceNo;               /* number of cache drive */
-            ulong32     BlockNo;                /* block number */
-            ulong32     BlockCnt;               /* block count */
-            ulong32     DestAddr;               /* dest. addr. (if s/g: -1) */
-            ulong32     sg_canz;                /* s/g element count */
-            gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
-        } PACKED cache;                         /* cache service cmd. str. */
-        struct {
-            ushort      param_size;             /* size of p_param buffer */
-            ulong32     subfunc;                /* IOCTL function */
-            ulong32     channel;                /* device */
-            ulong32     p_param;                /* buffer */
-        } PACKED ioctl;                         /* IOCTL command structure */
-        struct {
-            ushort      reserved;
-            union {
-                struct {
-                    ulong32  msg_handle;        /* message handle */
-                    ulong32  msg_addr;          /* message buffer address */
-                } PACKED msg;
-                unchar       data[12];          /* buffer for rtc data, ... */
-            } su;
-        } PACKED screen;                        /* screen service cmd. str. */
-        struct {
-            ushort      reserved;
-            ulong32     direction;              /* data direction */
-            ulong32     mdisc_time;             /* disc. time (0: no timeout)*/
-            ulong32     mcon_time;              /* connect time(0: no to.) */
-            ulong32     sdata;                  /* dest. addr. (if s/g: -1) */
-            ulong32     sdlen;                  /* data length (bytes) */
-            ulong32     clen;                   /* SCSI cmd. length(6,10,12) */
-            unchar      cmd[12];                /* SCSI command */
-            unchar      target;                 /* target ID */
-            unchar      lun;                    /* LUN */
-            unchar      bus;                    /* SCSI bus number */
-            unchar      priority;               /* only 0 used */
-            ulong32     sense_len;              /* sense data length */
-            ulong32     sense_data;             /* sense data addr. */
-            ulong32     link_p;                 /* linked cmds (not supp.) */
-            ulong32     sg_ranz;                /* s/g element count */
-            gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
-        } PACKED raw;                           /* raw service cmd. struct. */
-    } u;
-    /* additional variables */
-    unchar      Service;                        /* controller service */
-    ushort      Status;                         /* command result */
-    ulong32     Info;                           /* additional information */
-    Scsi_Cmnd   *RequestBuffer;                 /* request buffer */
-} PACKED gdth_cmd_str;
-
-/* controller event structure */
-#define ES_ASYNC    1
-#define ES_DRIVER   2
-#define ES_TEST     3
-#define ES_SYNC     4
-typedef struct {
-    ushort                  size;               /* size of structure */
-    union {
-        char                stream[16];
-        struct {
-            ushort          ionode;
-            ushort          service;
-            ulong32         index;
-        } PACKED driver;
-        struct {
-            ushort          ionode;
-            ushort          service;
-            ushort          status;
-            ulong32         info;
-            unchar          scsi_coord[3];
-        } PACKED async;
-        struct {
-            ushort          ionode;
-            ushort          service;
-            ushort          status;
-            ulong32         info;
-            ushort          hostdrive;
-            unchar          scsi_coord[3];
-            unchar          sense_key;
-        } PACKED sync;
-        struct {
-            ulong32         l1, l2, l3, l4;
-        } PACKED test;
-    } eu;
-    ulong32                 severity;
-    unchar                  event_string[256];          
-} PACKED gdth_evt_data;
-
-typedef struct {
-    ulong32         first_stamp;
-    ulong32         last_stamp;
-    ushort          same_count;
-    ushort          event_source;
-    ushort          event_idx;
-    unchar          application;
-    unchar          reserved;
-    gdth_evt_data   event_data;
-} PACKED gdth_evt_str;
-
 
 /* DPRAM structures */
 
@@ -889,7 +827,9 @@
     ulong32             brd_phys;               /* slot number/BIOS address */
     gdt6c_plx_regs      *plx;                   /* PLX regs (new PCI contr.) */
     gdth_cmd_str        *pccb;                  /* address command structure */
+    ulong32             ccb_phys;               /* phys. address */
     char                *pscratch;              /* scratch (DMA) buffer */
+    ulong32             scratch_phys;           /* phys. address */
     unchar              scratch_busy;           /* in use? */
     unchar              scan_mode;              /* current scan mode */
     unchar              irq;                    /* IRQ */
@@ -946,6 +886,10 @@
 #if LINUX_VERSION_CODE >= 0x02015F
     spinlock_t          smp_lock;
 #endif
+#if LINUX_VERSION_CODE >= 0x020400
+    struct pci_dev      *pdev;
+#endif
+    char                oem_name[8];
 } gdth_ha_str;
 
 /* structure for scsi_register(), SCSI bus != 0 */
@@ -1032,34 +976,145 @@
 #endif
 const char *gdth_info(struct Scsi_Host *);
 
+#if LINUX_VERSION_CODE >= 0x020501
 int gdth_bios_param(struct scsi_device *,struct block_device *,sector_t,int *);
 int gdth_proc_info(char *,char **,off_t,int,int,int);
 int gdth_eh_abort(Scsi_Cmnd *scp);
 int gdth_eh_device_reset(Scsi_Cmnd *scp);
 int gdth_eh_bus_reset(Scsi_Cmnd *scp);
 int gdth_eh_host_reset(Scsi_Cmnd *scp);
-#define GDTH { .proc_name       = "gdth",                          \
-               .proc_info       = gdth_proc_info,                  \
-               .name            = "GDT SCSI Disk Array Controller",\
-               .detect          = gdth_detect,                     \
-               .release         = gdth_release,                    \
-               .info            = gdth_info,                       \
-               .command         = NULL,                            \
-               .queuecommand    = gdth_queuecommand,               \
-               .eh_abort_handler = gdth_eh_abort,                  \
-               .eh_device_reset_handler = gdth_eh_device_reset,    \
-               .eh_bus_reset_handler = gdth_eh_bus_reset,          \
-               .eh_host_reset_handler = gdth_eh_host_reset,        \
-               .abort           = gdth_abort,                      \
-               .reset           = gdth_reset,                      \
-               .bios_param      = gdth_bios_param,                 \
-               .can_queue       = GDTH_MAXCMDS,                    \
-               .this_id         = -1,                              \
-               .sg_tablesize    = GDTH_MAXSG,                      \
-               .cmd_per_lun     = GDTH_MAXC_P_L,                   \
-               .present         = 0,                               \
-               .unchecked_isa_dma = 1,                             \
-               .use_clustering  = ENABLE_CLUSTERING }
+#define GDTH { .proc_name =      "gdth",                          \
+               .proc_info =      gdth_proc_info,                  \
+               .name =           "GDT SCSI Disk Array Controller",\
+               .detect =         gdth_detect,                     \
+               .release =        gdth_release,                    \
+               .info =           gdth_info,                       \
+               .command =        NULL,                            \
+               .queuecommand =   gdth_queuecommand,               \
+               .eh_abort_handler = gdth_eh_abort,                 \
+               .eh_device_reset_handler = gdth_eh_device_reset,   \
+               .eh_bus_reset_handler = gdth_eh_bus_reset,         \
+               .eh_host_reset_handler = gdth_eh_host_reset,       \
+               .abort =          NULL,                            \
+               .reset =          NULL,                            \
+               .bios_param =     gdth_bios_param,                 \
+               .can_queue =      GDTH_MAXCMDS,                    \
+               .this_id =        -1,                              \
+               .sg_tablesize =   GDTH_MAXSG,                      \
+               .cmd_per_lun =    GDTH_MAXC_P_L,                   \
+               .present =        0,                               \
+               .unchecked_isa_dma = 1,                            \
+               .use_clustering = ENABLE_CLUSTERING}
+
+#elif LINUX_VERSION_CODE >= 0x020322
+int gdth_bios_param(Disk *,kdev_t,int *);
+int gdth_proc_info(char *,char **,off_t,int,int,int);
+int gdth_eh_abort(Scsi_Cmnd *scp);
+int gdth_eh_device_reset(Scsi_Cmnd *scp);
+int gdth_eh_bus_reset(Scsi_Cmnd *scp);
+int gdth_eh_host_reset(Scsi_Cmnd *scp);
+#define GDTH { proc_name:       "gdth",                          \
+               proc_info:       gdth_proc_info,                  \
+               name:            "GDT SCSI Disk Array Controller",\
+               detect:          gdth_detect,                     \
+               release:         gdth_release,                    \
+               info:            gdth_info,                       \
+               command:         NULL,                            \
+               queuecommand:    gdth_queuecommand,               \
+               eh_abort_handler: gdth_eh_abort,                  \
+               eh_device_reset_handler: gdth_eh_device_reset,    \
+               eh_bus_reset_handler: gdth_eh_bus_reset,          \
+               eh_host_reset_handler: gdth_eh_host_reset,        \
+               abort:           gdth_abort,                      \
+               reset:           gdth_reset,                      \
+               bios_param:      gdth_bios_param,                 \
+               can_queue:       GDTH_MAXCMDS,                    \
+               this_id:         -1,                              \
+               sg_tablesize:    GDTH_MAXSG,                      \
+               cmd_per_lun:     GDTH_MAXC_P_L,                   \
+               present:         0,                               \
+               unchecked_isa_dma: 1,                             \
+               use_clustering:  ENABLE_CLUSTERING,               \
+               use_new_eh_code: 1       /* use new error code */ }    
+
+#elif LINUX_VERSION_CODE >= 0x02015F
+int gdth_bios_param(Disk *,kdev_t,int *);
+extern struct proc_dir_entry proc_scsi_gdth;
+int gdth_proc_info(char *,char **,off_t,int,int,int);
+int gdth_eh_abort(Scsi_Cmnd *scp);
+int gdth_eh_device_reset(Scsi_Cmnd *scp);
+int gdth_eh_bus_reset(Scsi_Cmnd *scp);
+int gdth_eh_host_reset(Scsi_Cmnd *scp);
+#define GDTH { proc_dir:        &proc_scsi_gdth,                 \
+               proc_info:       gdth_proc_info,                  \
+               name:            "GDT SCSI Disk Array Controller",\
+               detect:          gdth_detect,                     \
+               release:         gdth_release,                    \
+               info:            gdth_info,                       \
+               command:         NULL,                            \
+               queuecommand:    gdth_queuecommand,               \
+               eh_abort_handler: gdth_eh_abort,                  \
+               eh_device_reset_handler: gdth_eh_device_reset,    \
+               eh_bus_reset_handler: gdth_eh_bus_reset,          \
+               eh_host_reset_handler: gdth_eh_host_reset,        \
+               abort:           gdth_abort,                      \
+               reset:           gdth_reset,                      \
+               bios_param:      gdth_bios_param,                 \
+               can_queue:       GDTH_MAXCMDS,                    \
+               this_id:         -1,                              \
+               sg_tablesize:    GDTH_MAXSG,                      \
+               cmd_per_lun:     GDTH_MAXC_P_L,                   \
+               present:         0,                               \
+               unchecked_isa_dma: 1,                             \
+               use_clustering:  ENABLE_CLUSTERING,               \
+               use_new_eh_code: 1       /* use new error code */ }    
+
+#elif LINUX_VERSION_CODE >= 0x010300
+int gdth_bios_param(Disk *,kdev_t,int *);
+extern struct proc_dir_entry proc_scsi_gdth;
+int gdth_proc_info(char *,char **,off_t,int,int,int);
+#define GDTH { NULL, NULL,                              \
+                   &proc_scsi_gdth,                     \
+                   gdth_proc_info,                      \
+                   "GDT SCSI Disk Array Controller",    \
+                   gdth_detect,                         \
+                   gdth_release,                        \
+                   gdth_info,                           \
+                   NULL,                                \
+                   gdth_queuecommand,                   \
+                   gdth_abort,                          \
+                   gdth_reset,                          \
+                   NULL,                                \
+                   gdth_bios_param,                     \
+                   GDTH_MAXCMDS,                        \
+                   -1,                                  \
+                   GDTH_MAXSG,                          \
+                   GDTH_MAXC_P_L,                       \
+                   0,                                   \
+                   1,                                   \
+                   ENABLE_CLUSTERING}
+
+#else
+int gdth_bios_param(Disk *,int,int *);
+#define GDTH { NULL, NULL,                              \
+                   "GDT SCSI Disk Array Controller",    \
+                   gdth_detect,                         \
+                   gdth_release,                        \
+                   gdth_info,                           \
+                   NULL,                                \
+                   gdth_queuecommand,                   \
+                   gdth_abort,                          \
+                   gdth_reset,                          \
+                   NULL,                                \
+                   gdth_bios_param,                     \
+                   GDTH_MAXCMDS,                        \
+                   -1,                                  \
+                   GDTH_MAXSG,                          \
+                   GDTH_MAXC_P_L,                       \
+                   0,                                   \
+                   1,                                   \
+                   ENABLE_CLUSTERING}
+#endif
 
 #endif
 
diff -urN linux-2.5.65-bk2/drivers/scsi/gdth_ioctl.h linux-2.5.65-bk3/drivers/scsi/gdth_ioctl.h
--- linux-2.5.65-bk2/drivers/scsi/gdth_ioctl.h	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/drivers/scsi/gdth_ioctl.h	Mon Mar 31 12:41:42 2003
@@ -2,7 +2,7 @@
 #define _GDTH_IOCTL_H
 
 /* gdth_ioctl.h
- * $Id: gdth_ioctl.h,v 1.10 2001/05/22 06:28:59 achim Exp $
+ * $Id: gdth_ioctl.h,v 1.11 2003/02/27 14:59:03 achim Exp $
  */
 
 /* IOCTLs */
@@ -23,8 +23,136 @@
 
 #define GDTIOCTL_MAGIC      0xaffe0004
 #define EVENT_SIZE          294 
-#define MAX_HDRIVES         100                     
+#define GDTH_MAXSG      32                      /* max. s/g elements */
 
+#define MAX_LDRIVES     255                     /* max. log. drive count */
+#ifdef GDTH_IOCTL_PROC
+#define MAX_HDRIVES     100                     /* max. host drive count */
+#else
+#define MAX_HDRIVES     MAX_LDRIVES             /* max. host drive count */
+#endif
+
+/* typedefs */
+#ifdef __KERNEL__
+typedef u32     ulong32;
+#endif
+#define PACKED  __attribute__((packed))
+
+/* scatter/gather element */
+typedef struct {
+    ulong32     sg_ptr;                         /* address */
+    ulong32     sg_len;                         /* length */
+} PACKED gdth_sg_str;
+
+/* command structure */
+typedef struct {
+    ulong32     BoardNode;                      /* board node (always 0) */
+    ulong32     CommandIndex;                   /* command number */
+    ushort      OpCode;                         /* the command (READ,..) */
+    union {
+        struct {
+            ushort      DeviceNo;               /* number of cache drive */
+            ulong32     BlockNo;                /* block number */
+            ulong32     BlockCnt;               /* block count */
+            ulong32     DestAddr;               /* dest. addr. (if s/g: -1) */
+            ulong32     sg_canz;                /* s/g element count */
+            gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
+        } PACKED cache;                         /* cache service cmd. str. */
+        struct {
+            ushort      param_size;             /* size of p_param buffer */
+            ulong32     subfunc;                /* IOCTL function */
+            ulong32     channel;                /* device */
+            ulong32     p_param;                /* buffer */
+        } PACKED ioctl;                         /* IOCTL command structure */
+        struct {
+            ushort      reserved;
+            union {
+                struct {
+                    ulong32  msg_handle;        /* message handle */
+                    ulong32  msg_addr;          /* message buffer address */
+                } PACKED msg;
+                unchar       data[12];          /* buffer for rtc data, ... */
+            } su;
+        } PACKED screen;                        /* screen service cmd. str. */
+        struct {
+            ushort      reserved;
+            ulong32     direction;              /* data direction */
+            ulong32     mdisc_time;             /* disc. time (0: no timeout)*/
+            ulong32     mcon_time;              /* connect time(0: no to.) */
+            ulong32     sdata;                  /* dest. addr. (if s/g: -1) */
+            ulong32     sdlen;                  /* data length (bytes) */
+            ulong32     clen;                   /* SCSI cmd. length(6,10,12) */
+            unchar      cmd[12];                /* SCSI command */
+            unchar      target;                 /* target ID */
+            unchar      lun;                    /* LUN */
+            unchar      bus;                    /* SCSI bus number */
+            unchar      priority;               /* only 0 used */
+            ulong32     sense_len;              /* sense data length */
+            ulong32     sense_data;             /* sense data addr. */
+            ulong32     link_p;                 /* linked cmds (not supp.) */
+            ulong32     sg_ranz;                /* s/g element count */
+            gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
+        } PACKED raw;                           /* raw service cmd. struct. */
+    } u;
+    /* additional variables */
+    unchar      Service;                        /* controller service */
+    unchar      reserved;
+    ushort      Status;                         /* command result */
+    ulong32     Info;                           /* additional information */
+    void        *RequestBuffer;                 /* request buffer */
+} PACKED gdth_cmd_str;
+
+/* controller event structure */
+#define ES_ASYNC    1
+#define ES_DRIVER   2
+#define ES_TEST     3
+#define ES_SYNC     4
+typedef struct {
+    ushort                  size;               /* size of structure */
+    union {
+        char                stream[16];
+        struct {
+            ushort          ionode;
+            ushort          service;
+            ulong32         index;
+        } PACKED driver;
+        struct {
+            ushort          ionode;
+            ushort          service;
+            ushort          status;
+            ulong32         info;
+            unchar          scsi_coord[3];
+        } PACKED async;
+        struct {
+            ushort          ionode;
+            ushort          service;
+            ushort          status;
+            ulong32         info;
+            ushort          hostdrive;
+            unchar          scsi_coord[3];
+            unchar          sense_key;
+        } PACKED sync;
+        struct {
+            ulong32         l1, l2, l3, l4;
+        } PACKED test;
+    } eu;
+    ulong32                 severity;
+    unchar                  event_string[256];          
+} PACKED gdth_evt_data;
+
+typedef struct {
+    ulong32         first_stamp;
+    ulong32         last_stamp;
+    ushort          same_count;
+    ushort          event_source;
+    ushort          event_idx;
+    unchar          application;
+    unchar          reserved;
+    gdth_evt_data   event_data;
+} PACKED gdth_evt_str;
+
+
+#ifdef GDTH_IOCTL_PROC
 /* IOCTL structure (write) */
 typedef struct {
     ulong32                 magic;              /* IOCTL magic */
@@ -106,7 +234,82 @@
         } hdr_list[MAX_HDRIVES];                /* index is host drive number */
     } iu;
 } gdth_iord_str;
+#endif
+
+#ifdef GDTH_IOCTL_CHRDEV
+/* GDTIOCTL_GENERAL */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    ushort timeout;                             /* timeout */
+    ulong32 info;                               /* error info */ 
+    ushort status;                              /* status */
+    ulong data_len;                             /* data buffer size */
+    ulong sense_len;	                        /* sense buffer size */
+    gdth_cmd_str command;                       /* command */			
+} gdth_ioctl_general;
+
+/* GDTIOCTL_LOCKDRV */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    unchar lock;                                /* lock/unlock */
+    unchar drive_cnt;                           /* drive count */
+    ushort drives[MAX_HDRIVES];                 /* drives */
+} gdth_ioctl_lockdrv;
+
+/* GDTIOCTL_LOCKCHN */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    unchar lock;                                /* lock/unlock */
+    unchar channel;                             /* channel */
+} gdth_ioctl_lockchn;
+
+/* GDTIOCTL_OSVERS */
+typedef struct {
+    unchar version;                             /* OS version */
+    unchar subversion;                          /* OS subversion */
+    ushort revision;                            /* revision */
+} gdth_ioctl_osvers;
+
+/* GDTIOCTL_CTRTYPE */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    unchar type;                                /* controller type */
+    ushort info;                                /* slot etc. */
+    ushort oem_id;                              /* OEM ID */
+    ushort bios_ver;                            /* not used */
+    ushort access;                              /* not used */
+    ushort ext_type;                            /* extended type */
+    ushort device_id;                           /* device ID */
+    ushort sub_device_id;                       /* sub device ID */
+} gdth_ioctl_ctrtype;
+
+/* GDTIOCTL_EVENT */
+typedef struct {
+    ushort ionode;
+    int erase;                                  /* erase event? */
+    int handle;                                 /* event handle */
+    gdth_evt_str event;
+} gdth_ioctl_event;
 
+/* GDTIOCTL_RESCAN/GDTIOCTL_HDRLIST */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    unchar flag;                                /* add/remove */
+    ushort hdr_no;                              /* drive no. */
+    struct {
+        unchar bus;                             /* SCSI bus */
+        unchar target;                          /* target ID */
+        unchar lun;                             /* LUN */
+        unchar cluster_type;                    /* cluster properties */
+    } hdr_list[MAX_HDRIVES];                    /* index is host drive number */
+} gdth_ioctl_rescan;
 
+/* GDTIOCTL_RESET_BUS/GDTIOCTL_RESET_DRV */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    ushort number;                              /* bus/host drive number */
+    ushort status;                              /* status */
+} gdth_ioctl_reset;
 #endif
 
+#endif
diff -urN linux-2.5.65-bk2/drivers/scsi/gdth_proc.c linux-2.5.65-bk3/drivers/scsi/gdth_proc.c
--- linux-2.5.65-bk2/drivers/scsi/gdth_proc.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/drivers/scsi/gdth_proc.c	Mon Mar 31 12:41:42 2003
@@ -1,8 +1,7 @@
 /* gdth_proc.c 
- * $Id: gdth_proc.c,v 1.33 2001/08/10 07:54:39 achim Exp $
+ * $Id: gdth_proc.c,v 1.35 2003/02/27 15:00:44 achim Exp $
  */
 
-#include "gdth_ioctl.h"
 #if LINUX_VERSION_CODE >= 0x020407
 #include <linux/completion.h>
 #endif
@@ -33,22 +32,33 @@
 
 static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
 {
-    int             ret_val;
-#if LINUX_VERSION_CODE >= 0x020322
+    int             ret_val = -EINVAL;
+#if LINUX_VERSION_CODE >= 0x020503
+    Scsi_Request    *scp;
+    Scsi_Device     *sdev;
+#elif LINUX_VERSION_CODE >= 0x020322
     Scsi_Cmnd       *scp;
     Scsi_Device     *sdev;
 #else
     Scsi_Cmnd       scp;
     Scsi_Device     sdev;
 #endif
+#ifdef GDTH_IOCTL_PROC
     gdth_iowr_str   *piowr;
-
-    TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
     piowr = (gdth_iowr_str *)buffer;
+#endif
+    TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
 
-#if LINUX_VERSION_CODE >= 0x020322
-    sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
-    scp  = scsi_get_command(sdev, GFP_KERNEL);
+#if LINUX_VERSION_CODE >= 0x020503
+    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+    scp  = scsi_allocate_request(sdev);
+    if (!scp)
+        return -ENOMEM;
+    scp->sr_cmd_len = 12;
+    scp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= 0x020322
+    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+    scp  = scsi_allocate_device(sdev, 1, FALSE);
     if (!scp)
         return -ENOMEM;
     scp->cmd_len = 12;
@@ -56,7 +66,7 @@
 #else
     memset(&sdev,0,sizeof(Scsi_Device));
     memset(&scp, 0,sizeof(Scsi_Cmnd));
-    sdev.host = scp.host = gdth_ctr_vtab[vh];
+    sdev.host = scp.host = gdth_ctr_tab[hanum];
     sdev.id = scp.target = sdev.host->this_id;
     scp.device = &sdev;
 #endif
@@ -66,6 +76,7 @@
             buffer += 5;
             length -= 5;
             ret_val = gdth_set_asc_info( buffer, length, hanum, scp );
+#ifdef GDTH_IOCTL_PROC
         } else if (piowr->magic == GDTIOCTL_MAGIC) {
             ret_val = gdth_set_bin_info( buffer, length, hanum, scp );
         } else {
@@ -75,19 +86,22 @@
                 printk("GDT: Please update your driver.\n");
             else
                 printk("GDT: Please update your tool.\n");
-            ret_val = -EINVAL;
+#endif
         }
-    } else {
-        ret_val = -EINVAL;
     }
-#if LINUX_VERSION_CODE >= 0x020322
-    scsi_put_command(scp);
+#if LINUX_VERSION_CODE >= 0x020503
+    scsi_release_request(scp);
+    scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+    scsi_release_command(scp);
     scsi_free_host_dev(sdev);
 #endif
     return ret_val;
 }
          
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp)
+#elif LINUX_VERSION_CODE >= 0x020322
 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
 #else
 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
@@ -98,6 +112,7 @@
     gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
     gdth_cpar_str   *pcpar;
+    ulong32         paddr;
 
     char            cmnd[MAX_COMMAND_SIZE];
     memset(cmnd, 0xff, 12);
@@ -133,7 +148,9 @@
                 gdtcmd.OpCode = GDT_FLUSH;
                 gdtcmd.u.cache.DeviceNo = i;
                 gdtcmd.u.cache.BlockNo = 1;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+                gdth_do_req(scp, &gdtcmd, cmnd, 30);
+#elif LINUX_VERSION_CODE >= 0x020322
                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
 #else
                 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
@@ -178,23 +195,25 @@
     }
 
     if (wb_mode) {
-        if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE))
+        if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr))
             return(-EBUSY);
         pcpar = (gdth_cpar_str *)ha->pscratch;
         memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_IOCTL;
-        gdtcmd.u.ioctl.p_param = virt_to_bus(pcpar);
+        gdtcmd.u.ioctl.p_param = paddr;
         gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str);
         gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
         gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
         pcpar->write_back = wb_mode==1 ? 0:1;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+        gdth_do_req(scp, &gdtcmd, cmnd, 30);
+#elif LINUX_VERSION_CODE >= 0x020322
         gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
 #else
         gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
 #endif
-        gdth_ioctl_free(hanum, ha->pscratch);
+        gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
         printk("Done.\n");
         return(orig_length);
     }
@@ -203,7 +222,10 @@
     return(-EINVAL);
 }
 
-#if LINUX_VERSION_CODE >= 0x020322
+#ifdef GDTH_IOCTL_PROC
+#if LINUX_VERSION_CODE >= 0x020503
+static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Request *scp)
+#elif LINUX_VERSION_CODE >= 0x020322
 static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
 #else
 static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
@@ -216,7 +238,7 @@
     gdth_iord_str   *piord;
     gdth_cmd_str    *pcmd;
     gdth_evt_str    *pevt;
-    ulong32         *ppadd, add_size, *ppadd2, add_size2, info;
+    ulong32         *ppadd, add_size, *ppadd2, add_size2, info, paddr;
     ulong           flags;
     gdth_cmd_str    gdtcmd;
     int             drv_cyls, drv_hds, drv_secs;
@@ -273,21 +295,25 @@
             return(-EINVAL);
         }
         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2,
-                               TRUE ))
+                               TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
-
         piord->size = sizeof(gdth_iord_str) + add_size + add_size2;
         if (add_size > 0) {
             memcpy(piord->iu.general.data, piowr->iu.general.data, add_size);
-            *ppadd = virt_to_bus(piord->iu.general.data);
+            *ppadd = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]);
         }
         if (add_size2 > 0) {
             memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2);
-            *ppadd2 = virt_to_bus(piord->iu.general.data+add_size);
+            *ppadd2 = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]) + add_size2;
         }
+        
         /* do IOCTL */
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+        gdth_do_req(scp, pcmd, cmnd, piowr->timeout);
+        piord->status = (scp->sr_command->SCp.Message << 16) |
+            scp->sr_command->SCp.Status;
+#elif LINUX_VERSION_CODE >= 0x020322
         gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
         piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
 #else
@@ -297,7 +323,7 @@
         break;
 
       case GDTIOCTL_DRVERS:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
@@ -306,7 +332,7 @@
         break;
 
       case GDTIOCTL_CTRTYPE:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
@@ -332,7 +358,7 @@
         break;
 
       case GDTIOCTL_CTRCNT:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
@@ -341,7 +367,7 @@
         break;
 
       case GDTIOCTL_OSVERS:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
@@ -352,7 +378,7 @@
         break;
 
       case GDTIOCTL_LOCKDRV:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) {
@@ -378,7 +404,7 @@
         break;
 
       case GDTIOCTL_LOCKCHN:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         i = piowr->iu.lockchn.channel;
         if (i < ha->bus_cnt) {
@@ -406,7 +432,7 @@
         break;
 
       case GDTIOCTL_EVENT:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         if (piowr->iu.event.erase == 0xff) {
@@ -439,16 +465,19 @@
         piord->size = sizeof(gdth_iord_str);
         piord->status = S_OK;
         break;
-
+      
       case GDTIOCTL_SCSI:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+#if LINUX_VERSION_CODE >= 0x020503
+        return(-EINVAL);
+#else
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
         memcpy(cmnd, piowr->iu.scsi.cmd, 12);
 #if LINUX_VERSION_CODE >= 0x020322
-        scp->device->id = piowr->iu.scsi.target;
-        scp->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
+        scp->target = piowr->iu.scsi.target;
+        scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
         scp->cmd_len = piowr->iu.scsi.cmd_len;
         gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
         piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
@@ -459,15 +488,47 @@
         gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout);
         piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
 #endif
+#endif
         break;
 
       case GDTIOCTL_RESET_BUS:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
-#if LINUX_VERSION_CODE >= 0x020322
-        scp->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
+#if LINUX_VERSION_CODE >= 0x02053C
+        {
+            Scsi_Device     *sdev;
+            Scsi_Cmnd       *scmnd;
+
+            sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+            scmnd= scsi_get_command(sdev, GFP_KERNEL);
+            if (!scmnd)
+                return(-ENOMEM);
+            scmnd->device->host = scp->sr_host; 
+            scmnd->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
+            piord->status = (ulong32)gdth_eh_bus_reset( scmnd );
+            if (piord->status == SUCCESS)
+                piord->status = S_OK;
+            else
+                piord->status = S_GENERR;
+            scsi_put_command(scmnd);
+            scsi_free_host_dev(sdev);
+        }
+#elif LINUX_VERSION_CODE >= 0x020503
+        {
+            Scsi_Cmnd scmnd;
+             
+            scmnd.host = scp->sr_host; 
+            scmnd.channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
+            piord->status = (ulong32)gdth_eh_bus_reset( &scmnd );
+            if (piord->status == SUCCESS)
+                piord->status = S_OK;
+            else
+                piord->status = S_GENERR;
+        }
+#elif LINUX_VERSION_CODE >= 0x020322
+        scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
         piord->status = (ulong32)gdth_eh_bus_reset( scp );
         if (piord->status == SUCCESS)
             piord->status = S_OK;
@@ -486,7 +547,7 @@
         break;
 
       case GDTIOCTL_HDRLIST:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
@@ -501,7 +562,12 @@
                     gdtcmd.Service = CACHESERVICE;
                     gdtcmd.OpCode = GDT_CLUST_INFO;
                     gdtcmd.u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+                    gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                    if (scp->sr_command->SCp.Status == S_OK)
+                        piord->iu.hdr_list[i].cluster_type = 
+                            (unchar)scp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
                     gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
                     if (scp->SCp.Status == S_OK)
                         piord->iu.hdr_list[i].cluster_type = 
@@ -520,7 +586,7 @@
         break;
 
       case GDTIOCTL_RESCAN:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
@@ -532,7 +598,11 @@
             gdtcmd.Service = CACHESERVICE;
             gdtcmd.OpCode = GDT_INIT;
             gdtcmd.u.cache.DeviceNo = LINUX_OS;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->sr_command->SCp.Status; 
+            info = (ulong32)scp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
             status = (ushort)scp->SCp.Status; 
             info = (ulong32)scp->SCp.Message;
@@ -557,7 +627,11 @@
             gdtcmd.Service = CACHESERVICE;
             gdtcmd.OpCode = GDT_INFO;
             gdtcmd.u.cache.DeviceNo = k;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->sr_command->SCp.Status; 
+            info = (ulong32)scp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
             status = (ushort)scp->SCp.Status; 
             info = (ulong32)scp->SCp.Message;
@@ -591,7 +665,11 @@
             gdtcmd.Service = CACHESERVICE;
             gdtcmd.OpCode = GDT_DEVTYPE;
             gdtcmd.u.cache.DeviceNo = k;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->sr_command->SCp.Status; 
+            info = (ulong32)scp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
             status = (ushort)scp->SCp.Status; 
             info = (ulong32)scp->SCp.Message;
@@ -609,7 +687,11 @@
             gdtcmd.Service = CACHESERVICE;
             gdtcmd.OpCode = GDT_CLUST_INFO;
             gdtcmd.u.cache.DeviceNo = k;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->sr_command->SCp.Status; 
+            info = (ulong32)scp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
             status = (ushort)scp->SCp.Status; 
             info = (ulong32)scp->SCp.Message;
@@ -628,7 +710,11 @@
             gdtcmd.Service = CACHESERVICE;
             gdtcmd.OpCode = GDT_RW_ATTRIBS;
             gdtcmd.u.cache.DeviceNo = k;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->sr_command->SCp.Status; 
+            info = (ulong32)scp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= 0x020322
             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
             status = (ushort)scp->SCp.Status; 
             info = (ulong32)scp->SCp.Message;
@@ -646,7 +732,7 @@
         break;
 
       case GDTIOCTL_RESET_DRV:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
             return(-EBUSY);
         piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
@@ -656,7 +742,10 @@
             gdtcmd.Service = CACHESERVICE;
             gdtcmd.OpCode = GDT_CLUST_RESET;
             gdtcmd.u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            piord->status = (ushort)scp->sr_command->SCp.Status; 
+#elif LINUX_VERSION_CODE >= 0x020322
             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
             piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
 #else
@@ -671,6 +760,7 @@
     }
     return length;
 }
+#endif
 
 static int gdth_get_info(char *buffer,char **start,off_t offset,
                          int length,int vh,int hanum,int busnum)
@@ -678,14 +768,16 @@
     int size = 0,len = 0;
     off_t begin = 0,pos = 0;
     gdth_ha_str *ha;
-    gdth_iord_str *piord;
     int id, i, j, k, sec, flag;
     int no_mdrv = 0, drv_no, is_mirr;
-    ulong32 cnt;
+    ulong32 cnt, paddr;
 
     gdth_cmd_str gdtcmd;
     gdth_evt_str estr;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+    Scsi_Request *scp;
+    Scsi_Device *sdev; 
+#elif LINUX_VERSION_CODE >= 0x020322
     Scsi_Cmnd *scp;
     Scsi_Device *sdev;
 #else
@@ -710,9 +802,16 @@
     TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
-#if LINUX_VERSION_CODE >= 0x020322
-    sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
-    scp  = scsi_get_command(sdev, GFP_KERNEL);
+#if LINUX_VERSION_CODE >= 0x020503
+    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+    scp  = scsi_allocate_request(sdev);
+    if (!scp)
+        return -ENOMEM;
+    scp->sr_cmd_len = 12;
+    scp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= 0x020322
+    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+    scp  = scsi_allocate_device(sdev, 1, FALSE);
     if (!scp)
         return -ENOMEM;
     scp->cmd_len = 12;
@@ -720,13 +819,15 @@
 #else
     memset(&sdev,0,sizeof(Scsi_Device));
     memset(&scp, 0,sizeof(Scsi_Cmnd));
-    sdev.host = scp.host = gdth_ctr_vtab[vh];
+    sdev.host = scp.host = gdth_ctr_tab[hanum];
     sdev.id = scp.target = sdev.host->this_id;
     scp.device = &sdev;
 #endif
 
+#ifdef GDTH_IOCTL_PROC
     /* ioctl from tool? */
     if (!gdth_ioctl_check_bin(hanum, (ushort)length)) {
+#endif
         /* request is i.e. "cat /proc/scsi/gdth/0" */ 
         /* format: %-15s\t%-10s\t%-15s\t%s */
         /* driver parameters */
@@ -798,7 +899,7 @@
             len += size;  pos = begin + len;
             flag = FALSE;
             
-            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
+            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
             if (!buf) 
                 goto stop_output;
             for (i = 0; i < ha->bus_cnt; ++i) {
@@ -807,7 +908,7 @@
                 pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_IOCTL;
-                gdtcmd.u.ioctl.p_param = virt_to_bus(pds);
+                gdtcmd.u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
                 gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
                 gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
                 gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
@@ -818,7 +919,10 @@
                     sizeof(pds->list[0]);
                 if (pds->entries > cnt)
                     pds->entries = cnt;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+                gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                if (scp->sr_command->SCp.Status != S_OK) 
+#elif LINUX_VERSION_CODE >= 0x020322
                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
                 if (scp->SCp.Status != S_OK) 
 #else
@@ -837,12 +941,15 @@
                     pdi = (gdth_diskinfo_str *)buf;
                     gdtcmd.Service = CACHESERVICE;
                     gdtcmd.OpCode = GDT_IOCTL;
-                    gdtcmd.u.ioctl.p_param = virt_to_bus(pdi);
+                    gdtcmd.u.ioctl.p_param = paddr;
                     gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
                     gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
                     gdtcmd.u.ioctl.channel = 
                         ha->raw[i].address | ha->raw[i].id_list[j];
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+                    gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                    if (scp->sr_command->SCp.Status == S_OK) 
+#elif LINUX_VERSION_CODE >= 0x020322
                     gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
                     if (scp->SCp.Status == S_OK) 
 #else
@@ -892,13 +999,16 @@
                         pdef = (gdth_defcnt_str *)buf;
                         gdtcmd.Service = CACHESERVICE;
                         gdtcmd.OpCode = GDT_IOCTL;
-                        gdtcmd.u.ioctl.p_param = virt_to_bus(pdef);
+                        gdtcmd.u.ioctl.p_param = paddr;
                         gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
                         gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
                         gdtcmd.u.ioctl.channel = 
                             ha->raw[i].address | ha->raw[i].id_list[j];
                         pdef->sddc_type = 0x08;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+                        gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                        if (scp->sr_command->SCp.Status == S_OK) 
+#elif LINUX_VERSION_CODE >= 0x020322
                         gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
                         if (scp->SCp.Status == S_OK) 
 #else
@@ -920,7 +1030,7 @@
                         goto stop_output;
                 }
             }
-            gdth_ioctl_free(hanum, buf);
+            gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
 
             if (!flag) {
                 size = sprintf(buffer+len, "\n --\n");
@@ -932,7 +1042,7 @@
             len += size;  pos = begin + len;
             flag = FALSE;
 
-            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
+            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
             if (!buf) 
                 goto stop_output;
             for (i = 0; i < MAX_LDRIVES; ++i) {
@@ -947,11 +1057,14 @@
                     pcdi = (gdth_cdrinfo_str *)buf;
                     gdtcmd.Service = CACHESERVICE;
                     gdtcmd.OpCode = GDT_IOCTL;
-                    gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi);
+                    gdtcmd.u.ioctl.p_param = paddr;
                     gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
                     gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
                     gdtcmd.u.ioctl.channel = drv_no;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+                    gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                    if (scp->sr_command->SCp.Status != S_OK) 
+#elif LINUX_VERSION_CODE >= 0x020322
                     gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
                     if (scp->SCp.Status != S_OK)
 #else
@@ -1034,7 +1147,7 @@
                 if (pos > offset + length)
                     goto stop_output;
             }       
-            gdth_ioctl_free(hanum, buf);
+            gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
         
             if (!flag) {
                 size = sprintf(buffer+len, "\n --\n");
@@ -1046,7 +1159,7 @@
             len += size;  pos = begin + len;
             flag = FALSE;
 
-            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
+            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
             if (!buf) 
                 goto stop_output;
             for (i = 0; i < MAX_LDRIVES; ++i) {
@@ -1057,11 +1170,14 @@
                 pai = (gdth_arrayinf_str *)buf;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_IOCTL;
-                gdtcmd.u.ioctl.p_param = virt_to_bus(pai);
+                gdtcmd.u.ioctl.p_param = paddr;
                 gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
                 gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
                 gdtcmd.u.ioctl.channel = i;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+                gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                if (scp->sr_command->SCp.Status == S_OK) 
+#elif LINUX_VERSION_CODE >= 0x020322
                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
                 if (scp->SCp.Status == S_OK) 
 #else
@@ -1112,7 +1228,7 @@
                         goto stop_output;
                 }
             }
-            gdth_ioctl_free(hanum, buf);
+            gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
         
             if (!flag) {
                 size = sprintf(buffer+len, "\n --\n");
@@ -1124,7 +1240,7 @@
             len += size;  pos = begin + len;
             flag = FALSE;
 
-            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
+            buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr);
             if (!buf) 
                 goto stop_output;
             for (i = 0; i < MAX_LDRIVES; ++i) {
@@ -1136,13 +1252,16 @@
                 phg = (gdth_hget_str *)buf;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_IOCTL;
-                gdtcmd.u.ioctl.p_param = virt_to_bus(phg);
+                gdtcmd.u.ioctl.p_param = paddr;
                 gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
                 gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
                 gdtcmd.u.ioctl.channel = i;
                 phg->entries = MAX_HDRIVES;
                 phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+                gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                if (scp->sr_command->SCp.Status != S_OK) 
+#elif LINUX_VERSION_CODE >= 0x020322
                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
                 if (scp->SCp.Status != S_OK) 
 #else
@@ -1164,7 +1283,7 @@
                     }
                 }
             }
-            gdth_ioctl_free(hanum, buf);
+            gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr);
 
             for (i = 0; i < MAX_HDRIVES; ++i) {
                 if (!(ha->hdr[i].present))
@@ -1221,20 +1340,27 @@
             if (id == -1)
                 break;
         }
+#ifdef GDTH_IOCTL_PROC
     } else {
+        gdth_iord_str *piord;
+
         /* request from tool (GDTMON,..) */
         piord = (gdth_iord_str *)ha->pscratch;
         if (piord == NULL)
             goto stop_output;
         length = piord->size;
         memcpy(buffer+len, (char *)piord, length);
-        gdth_ioctl_free(hanum, ha->pscratch);
+        gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
         len = length; 
     }
+#endif
 
 stop_output:
-#if LINUX_VERSION_CODE >= 0x020322
-    scsi_put_command(scp);
+#if LINUX_VERSION_CODE >= 0x020503
+    scsi_release_request(scp);
+    scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= 0x020322
+    scsi_release_command(scp);
     scsi_free_host_dev(sdev);
 #endif
     *start = buffer +(offset-begin);
@@ -1246,6 +1372,26 @@
     return(len);
 }
 
+#if LINUX_VERSION_CODE >= 0x020503
+static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd, 
+                        char *cmnd, int timeout)
+{
+    unsigned bufflen;
+    DECLARE_COMPLETION(wait);
+
+    TRACE2(("gdth_do_req()\n"));
+    if (gdtcmd != NULL) { 
+        bufflen = sizeof(gdth_cmd_str);
+    } else {
+        bufflen = 0;
+    }
+    scp->sr_request->rq_status = RQ_SCSI_BUSY;
+    scp->sr_request->waiting = &wait;
+    scsi_do_req(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
+    wait_for_completion(&wait);
+}
+
+#else
 static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd, 
                         char *cmnd, int timeout)
 {
@@ -1266,8 +1412,8 @@
         scp->SCp.this_residual = DEFAULT_PRI;
         bufflen = 0;
     }
-    scp->request.rq_status = RQ_SCSI_BUSY;
 #if LINUX_VERSION_CODE >= 0x020407
+    scp->request.rq_status = RQ_SCSI_BUSY;
     scp->request.waiting = &wait;
     scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
     wait_for_completion(&wait);
@@ -1283,46 +1429,53 @@
     down(&sem);
 #endif
 }
+#endif
 
 void gdth_scsi_done(Scsi_Cmnd *scp)
 {
     TRACE2(("gdth_scsi_done()\n"));
 
+#if LINUX_VERSION_CODE >= 0x020503
+    scp->request->rq_status = RQ_SCSI_DONE;
+    if (scp->request->waiting != NULL)
+        complete(scp->request->waiting);
+#elif LINUX_VERSION_CODE >= 0x020407
     scp->request.rq_status = RQ_SCSI_DONE;
-
-#if LINUX_VERSION_CODE >= 0x020407
     if (scp->request.waiting != NULL)
         complete(scp->request.waiting);
 #else
+    scp->request.rq_status = RQ_SCSI_DONE;
     if (scp->request.sem != NULL)
         up(scp->request.sem);
 #endif
 }
 
-static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch)
+static char *gdth_ioctl_alloc(int hanum, int size, int scratch, 
+                              ulong32 *paddr)
 {
     gdth_ha_str *ha;
     ulong flags;
     char *ret_val;
 
-    if (size == 0 || size > GDTH_SCRATCH)
-        return FALSE;
+    if (size == 0)
+        return NULL;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
-    if (scratch) { 
-        if (!ha->scratch_busy) {
-            ha->scratch_busy = TRUE;
-            ret_val = ha->pscratch;
-        } else
-            ret_val = NULL;
+    if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
+        ha->scratch_busy = TRUE;
+        ret_val = ha->pscratch;
+        *paddr = ha->scratch_phys;
+    } else if (scratch) {
+        ret_val = NULL;
     } else {
-#if LINUX_VERSION_CODE >= 0x020322
-        ret_val = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
-                                            GDTH_SCRATCH_ORD);
+#if LINUX_VERSION_CODE >= 0x020400
+        ret_val = pci_alloc_consistent(ha->pdev, size, paddr);
 #else
-        ret_val = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+        ret_val = scsi_init_malloc(size, GFP_ATOMIC | GFP_DMA);
+        if (ret_val)
+            *paddr = virt_to_bus(ret_val);
 #endif
     }
 
@@ -1330,7 +1483,7 @@
     return ret_val;
 }
 
-static void gdth_ioctl_free(int hanum, char *buf)
+static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr)
 {
     gdth_ha_str *ha;
     ulong flags;
@@ -1341,16 +1494,17 @@
     if (buf == ha->pscratch) {
         ha->scratch_busy = FALSE;
     } else {
-#if LINUX_VERSION_CODE >= 0x020322
-        free_pages((unsigned long)buf, GDTH_SCRATCH_ORD);
+#if LINUX_VERSION_CODE >= 0x020400
+        pci_free_consistent(ha->pdev, size, buf, paddr);
 #else
-        scsi_init_free((void *)buf, GDTH_SCRATCH);
+        scsi_init_free((void *)buf, size);
 #endif
     }
 
     GDTH_UNLOCK_HA(ha, flags);
 }
 
+#ifdef GDTH_IOCTL_PROC
 static int gdth_ioctl_check_bin(int hanum, ushort size)
 {
     gdth_ha_str *ha;
@@ -1368,7 +1522,7 @@
     GDTH_UNLOCK_HA(ha, flags);
     return ret_val;
 }
-
+#endif
 
 static void gdth_wait_completion(int hanum, int busnum, int id)
 {
@@ -1376,23 +1530,39 @@
     ulong flags;
     int i;
     Scsi_Cmnd *scp;
-    unchar b;
+    unchar b, t;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
         scp = ha->cmd_tab[i].cmnd;
+#if LINUX_VERSION_CODE >= 0x02053C
         b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-        if (!SPECIAL_SCP(scp) && scp->device->id == (unchar)id && 
+        t = scp->device->id;
+#else
+        b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        t = scp->target;
+#endif
+        if (!SPECIAL_SCP(scp) && t == (unchar)id && 
             b == (unchar)busnum) {
             scp->SCp.have_data_in = 0;
             GDTH_UNLOCK_HA(ha, flags);
             while (!scp->SCp.have_data_in)
                 barrier();
+#if LINUX_VERSION_CODE >= 0x02053C
+            GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
+            scp->scsi_done(scp);
+            GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
+#elif LINUX_VERSION_CODE >= 0x020503
+            GDTH_LOCK_SCSI_DONE(scp->host, flags);
+            scp->scsi_done(scp);
+            GDTH_UNLOCK_SCSI_DONE(scp->host, flags);
+#else
             GDTH_LOCK_SCSI_DONE(flags);
             scp->scsi_done(scp);
             GDTH_UNLOCK_SCSI_DONE(flags);
+#endif
         GDTH_LOCK_HA(ha, flags);
         }
     }
@@ -1404,14 +1574,20 @@
     gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
-    unchar b;
+    unchar b, t;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
+#if LINUX_VERSION_CODE >= 0x02053C
         b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-        if (scp->device->id == (unchar)id && b == (unchar)busnum) {
+        t = scp->device->id;
+#else
+        b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        t = scp->target;
+#endif
+        if (t == (unchar)id && b == (unchar)busnum) {
             TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
             scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
         }
@@ -1424,14 +1600,20 @@
     gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
-    unchar b;
+    unchar b, t;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
+#if LINUX_VERSION_CODE >= 0x02053C
         b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-        if (scp->device->id == (unchar)id && b == (unchar)busnum) {
+        t = scp->device->id;
+#else
+        b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        t = scp->target;
+#endif
+        if (t == (unchar)id && b == (unchar)busnum) {
             TRACE2(("gdth_start_timeout(): update_timeout()\n"));
             gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
         }
@@ -1464,7 +1646,7 @@
             timer_table[SCSI_TIMER].expires = jiffies + timeout;
             timer_active |= 1 << SCSI_TIMER;
         } else {
-            if (time_before(jiffies + timeout, timer_table[SCSI_TIMER].expires))
+            if (jiffies + timeout < timer_table[SCSI_TIMER].expires)
                 timer_table[SCSI_TIMER].expires = jiffies + timeout;
         }
     }
diff -urN linux-2.5.65-bk2/drivers/scsi/gdth_proc.h linux-2.5.65-bk3/drivers/scsi/gdth_proc.h
--- linux-2.5.65-bk2/drivers/scsi/gdth_proc.h	Mon Mar 17 13:44:20 2003
+++ linux-2.5.65-bk3/drivers/scsi/gdth_proc.h	Mon Mar 31 12:41:42 2003
@@ -2,26 +2,42 @@
 #define _GDTH_PROC_H
 
 /* gdth_proc.h 
- * $Id: gdth_proc.h,v 1.11 2001/07/25 15:37:40 achim Exp $
+ * $Id: gdth_proc.h,v 1.13 2003/02/27 14:59:25 achim Exp $
  */
 
 static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum);
 static int gdth_get_info(char *buffer,char **start,off_t offset,
                          int length,int vh,int hanum,int busnum);
 
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= 0x020503
+static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd, 
+                        char *cmnd, int timeout);
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp);
+#ifdef GDTH_IOCTL_PROC
+static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Request *scp);
+#endif
+#elif LINUX_VERSION_CODE >= 0x020322
+static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, 
+                        char *cmnd, int timeout);
 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
+#ifdef GDTH_IOCTL_PROC
 static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
+#endif
 #else 
+static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, 
+                        char *cmnd, int timeout);
 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
+#ifdef GDTH_IOCTL_PROC
 static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
 #endif
-static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, 
-                        char *cmnd, int timeout);
+#endif
 
-static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch);
-static void gdth_ioctl_free(int hanum, char *buf);
+static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
+                              ulong32 *paddr);  
+static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr);
+#ifdef GDTH_IOCTL_PROC
 static int gdth_ioctl_check_bin(int hanum, ushort size);
+#endif
 static void gdth_wait_completion(int hanum, int busnum, int id);
 static void gdth_stop_timeout(int hanum, int busnum, int id);
 static void gdth_start_timeout(int hanum, int busnum, int id);
diff -urN linux-2.5.65-bk2/drivers/scsi/sym53c416.h linux-2.5.65-bk3/drivers/scsi/sym53c416.h
--- linux-2.5.65-bk2/drivers/scsi/sym53c416.h	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk3/drivers/scsi/sym53c416.h	Mon Mar 31 12:41:42 2003
@@ -18,14 +18,6 @@
 #ifndef _SYM53C416_H
 #define _SYM53C416_H
 
-#if !defined(LINUX_VERSION_CODE)
-#include <linux/version.h>
-#endif
-
-#ifndef LinuxVersionCode
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-#endif
-
 #include <linux/types.h>
 
 #define SYM53C416_SCSI_ID 7
diff -urN linux-2.5.65-bk2/drivers/serial/8250_pnp.c linux-2.5.65-bk3/drivers/serial/8250_pnp.c
--- linux-2.5.65-bk2/drivers/serial/8250_pnp.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/drivers/serial/8250_pnp.c	Mon Mar 31 12:41:42 2003
@@ -188,6 +188,8 @@
 	{	"MVX00A1",		0	},
 	/* PC Rider K56 Phone System PnP */
 	{	"MVX00F2",		0	},
+	/* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
+	{	"nEC8241",		0	},
 	/* Pace 56 Voice Internal Plug & Play Modem */
 	{	"PMC2430",		0	},
 	/* Generic */
@@ -373,6 +375,9 @@
 			    ((port->min == 0x2f8) ||
 			     (port->min == 0x3f8) ||
 			     (port->min == 0x2e8) ||
+#ifdef CONFIG_X86_PC9800
+			     (port->min == 0x8b0) ||
+#endif
 			     (port->min == 0x3e8)))
 				return 0;
 	}
diff -urN linux-2.5.65-bk2/drivers/serial/serial98.c linux-2.5.65-bk3/drivers/serial/serial98.c
--- linux-2.5.65-bk2/drivers/serial/serial98.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/drivers/serial/serial98.c	Mon Mar 31 12:41:42 2003
@@ -0,0 +1,1124 @@
+/*
+ *  linux/drivers/serial/serial98.c
+ *
+ *  Driver for NEC PC-9801/PC-9821 standard serial ports
+ *
+ *  Based on drivers/serial/8250.c, by Russell King.
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ *  Copyright (C) 2002 Osamu Tomita <tomita@cinet.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pc9800.h>
+#include <asm/pc9800_sca.h>
+
+#if defined(CONFIG_SERIAL98_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#define SERIAL98_NR		1
+#define SERIAL98_ISR_PASS_LIMIT	256
+#define SERIAL98_EXT		0x434
+
+//#define RX_8251F		0x130	/* In: Receive buffer */
+//#define TX_8251F		0x130	/* Out: Transmit buffer */
+//#define LSR_8251F		0x132	/* In: Line Status Register */
+//#define MSR_8251F		0x134	/* In: Modem Status Register */
+#define IIR_8251F		0x136	/* In: Interrupt ID Register */
+#define FCR_8251F		0x138	/* I/O: FIFO Control Register */
+#define VFAST_8251F		0x13a	/* I/O: VFAST mode Register */
+
+#define CMD_8251F		0x32	/* Out: 8251 Command Resister */
+#define IER2_8251F		0x34	/* I/O: Interrupt Enable Register */
+#define IER1_8251F		0x35	/* I/O: Interrupt Enable Register */
+#define IER1_CTL		0x37	/* Out: Interrupt Enable Register */
+#define DIS_RXR_INT		0x00	/* disable RxRDY Interrupt */
+#define ENA_RXR_INT		0x01	/* enable RxRDY Interrupt */
+#define DIS_TXE_INT		0x02	/* disable TxEMPTY Interrupt */
+#define ENA_TXE_INT		0x03	/* enable TxEMPTY Interrupt */
+#define DIS_TXR_INT		0x04	/* disable TxRDY Interrupt */
+#define ENA_TXR_INT		0x05	/* enable TxRDY Interrupt */
+
+#define CMD_RESET		0x40	/* Reset Command */
+#define CMD_RTS			0x20	/* Set RTS line */
+#define CMD_CLR_ERR		0x10	/* Clear error flag */
+#define CMD_BREAK		0x08	/* Send Break */
+#define CMD_RXE			0x04	/* Enable receive */
+#define CMD_DTR			0x02	/* Set DTR line */
+#define CMD_TXE			0x01	/* Enable send */
+#define CMD_DUMMY		0x00	/* Dummy Command */
+
+#define VFAST_ENABLE		0x80	/* V.Fast mode Enable */
+
+/* Interrupt masks */
+#define INTR_8251_TXRE		0x04
+#define INTR_8251_TXEE		0x02
+#define INTR_8251_RXRE		0x01
+/* I/O Port */
+//#define PORT_8251_DATA	0
+//#define PORT_8251_CMD		2
+//#define PORT_8251_MOD		2
+//#define PORT_8251_STS		2
+/* status read */
+#define STAT_8251_TXRDY		0x01
+#define STAT_8251_RXRDY		0x02
+#define STAT_8251_TXEMP		0x04
+#define STAT_8251_PER		0x08
+#define STAT_8251_OER		0x10
+#define STAT_8251_FER		0x20
+#define STAT_8251_BRK		0x40
+#define STAT_8251_DSR		0x80
+#if 1
+#define STAT_8251F_TXEMP	0x01
+#define STAT_8251F_TXRDY	0x02
+#define STAT_8251F_RXRDY	0x04
+#define STAT_8251F_DSR		0x08
+#define STAT_8251F_OER		0x10
+#define STAT_8251F_PER		0x20
+#define STAT_8251F_FER		0x40
+#define STAT_8251F_BRK		0x80
+#else
+#define STAT_8251F_TXEMP	0x01
+#define STAT_8251F_TEMT		0x01
+#define STAT_8251F_TXRDY	0x02
+#define STAT_8251F_THRE		0x02
+#define STAT_8251F_RXRDY	0x04
+#define STAT_8251F_DSR		0x04
+#define STAT_8251F_PER		0x08
+#define STAT_8251F_OER		0x10
+#define STAT_8251F_FER		0x20
+#define STAT_8251F_BRK		0x40
+#endif
+
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+struct serial98_port {
+	struct uart_port	port;
+	unsigned int		type;
+	unsigned int		ext;
+	unsigned int		lsr_break_flag;
+	unsigned char		cmd;
+	unsigned char		mode;
+	unsigned char		msr;
+	unsigned char		ier;
+	unsigned char		rxchk;
+	unsigned char		txemp;
+	unsigned char		txrdy;
+	unsigned char		rxrdy;
+	unsigned char		brk;
+	unsigned char		fe;
+	unsigned char		oe;
+	unsigned char		pe;
+	unsigned char		dr;
+};
+
+#ifdef CONFIG_SERIAL98_CONSOLE
+static void
+serial98_console_write(struct console *co, const char *s, unsigned int count);
+static kdev_t serial98_console_device(struct console *co);
+static int __init serial98_console_setup(struct console *co, char *options);
+
+static struct console serial98_console = {
+	.name		= "ttyS",
+	.write		= serial98_console_write,
+	.device		= serial98_console_device,
+	.setup		= serial98_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+};
+
+#define SERIAL98_CONSOLE	&serial98_console
+#else
+#define SERIAL98_CONSOLE	NULL
+#endif
+
+static struct uart_driver serial98_reg = {
+	.owner			= THIS_MODULE,
+	.driver_name		= "serial98",
+	.dev_name		= "ttyS%d",
+	.major			= TTY_MAJOR,
+	.minor			= 64,
+	.nr			= SERIAL98_NR,
+	.cons			= SERIAL98_CONSOLE,
+};
+
+static int serial98_clk;
+static char type_str[48];
+
+#define PORT98 ((struct serial98_port *)port)
+#define PORT (PORT98->port)
+
+static void serial98_fifo_enable(struct uart_port *port, int enable)
+{
+	unsigned char fcr;
+
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		fcr = inb(FCR_8251F);
+		if (enable)
+			fcr |= UART_FCR_ENABLE_FIFO;
+		else
+			fcr &= ~UART_FCR_ENABLE_FIFO;
+		outb(fcr, FCR_8251F);
+	}
+
+	if (!enable)
+		return;
+
+	outb(0, 0x5f);	/* wait */
+	outb(0, 0x5f);
+	outb(0, 0x5f);
+	outb(0, 0x5f);
+}
+
+static void serial98_cmd_out(struct uart_port *port, unsigned char cmd)
+{
+	serial98_fifo_enable(port, 0);
+	outb(cmd, CMD_8251F);
+	serial98_fifo_enable(port, 1);
+}
+
+static void serial98_mode_set(struct uart_port *port)
+{
+	serial98_cmd_out(port, CMD_DUMMY);
+	serial98_cmd_out(port, CMD_DUMMY);
+	serial98_cmd_out(port, CMD_DUMMY);
+	serial98_cmd_out(port, CMD_RESET);
+	serial98_cmd_out(port, PORT98->mode);
+}
+
+static unsigned char serial98_msr_in(struct uart_port *port)
+{
+	unsigned long flags;
+	unsigned int ms, st;
+	unsigned int tmp;
+
+	spin_lock_irqsave(&PORT.lock, flags);
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		PORT98->msr = inb(PORT.iobase + 4);
+	} else {
+		ms = inb(0x33);
+		st = inb(0x32);
+		tmp = 0;
+		if(!(ms & 0x20))
+			tmp |= UART_MSR_DCD;
+		if(!(ms & 0x80)) {
+			tmp |= UART_MSR_RI;
+			PORT98->msr |= UART_MSR_RI;
+		}
+		if(!(ms & 0x40))
+			tmp |= UART_MSR_CTS;
+		if(st & 0x80)
+			tmp |= UART_MSR_DSR;
+		PORT98->msr = ((PORT98->msr ^ tmp) >> 4) | tmp;
+	}
+
+	spin_unlock_irqrestore(&PORT.lock, flags);
+	return PORT98->msr;
+}
+
+static void serial98_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	unsigned int ier = inb(IER1_8251F);
+
+	ier &= ~(INTR_8251_TXRE | INTR_8251_TXEE);
+	outb(ier, IER1_8251F);
+}
+
+static void serial98_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	unsigned int ier = inb(IER1_8251F);
+
+	ier |= INTR_8251_TXRE | INTR_8251_TXEE;
+	outb(ier, IER1_8251F);
+}
+
+static void serial98_stop_rx(struct uart_port *port)
+{
+	PORT.read_status_mask &= ~PORT98->dr;
+	outb(DIS_RXR_INT, IER1_CTL);
+}
+
+static void serial98_enable_ms(struct uart_port *port)
+{
+	outb(PORT98->ier | 0x80, IER2_8251F);
+}
+
+static void serial98_rx_chars(struct uart_port *port, int *status,
+				struct pt_regs *regs)
+{
+	struct tty_struct *tty = PORT.info->tty;
+	unsigned char ch;
+	int max_count = 256;
+
+	do {
+		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+			tty->flip.work.func((void *)tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				return; // if TTY_DONT_FLIP is set
+		}
+		ch = inb(PORT.iobase);
+		*tty->flip.char_buf_ptr = ch;
+		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		PORT.icount.rx++;
+
+		if (unlikely(*status & (PORT98->brk | PORT98->pe |
+				       PORT98->fe | PORT98->oe))) {
+			/*
+			 * For statistics only
+			 */
+			if (*status & PORT98->brk) {
+				*status &= ~(PORT98->fe | PORT98->pe);
+				PORT.icount.brk++;
+				/*
+				 * We do the SysRQ and SAK checking
+				 * here because otherwise the break
+				 * may get masked by ignore_status_mask
+				 * or read_status_mask.
+				 */
+				if (uart_handle_break(&PORT))
+					goto ignore_char;
+			} else if (*status & PORT98->pe)
+				PORT.icount.parity++;
+			else if (*status & PORT98->fe)
+				PORT.icount.frame++;
+			if (*status & PORT98->oe)
+				PORT.icount.overrun++;
+
+			/*
+			 * Mask off conditions which should be ingored.
+			 */
+			*status &= PORT.read_status_mask;
+
+#ifdef CONFIG_SERIAL98_CONSOLE
+			if (PORT.line == PORT.cons->index) {
+				/* Recover the break flag from console xmit */
+				*status |= PORT98->lsr_break_flag;
+				PORT98->lsr_break_flag = 0;
+			}
+#endif
+			if (*status & PORT98->brk) {
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+			} else if (*status & PORT98->pe)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (*status & PORT98->fe)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+		}
+		if (uart_handle_sysrq_char(&PORT, ch, regs))
+			goto ignore_char;
+		if ((*status & PORT.ignore_status_mask) == 0) {
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+		if ((*status & PORT98->oe) &&
+		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+			/*
+			 * Overrun is special, since it's reported
+			 * immediately, and doesn't affect the current
+			 * character.
+			 */
+			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+	ignore_char:
+		*status = inb(PORT.iobase + 2);
+	} while ((*status & PORT98->rxchk) && (max_count-- > 0));
+	tty_flip_buffer_push(tty);
+}
+
+static void serial98_tx_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit = &PORT.info->xmit;
+	int count;
+
+	if (PORT.x_char) {
+		outb(PORT.x_char, PORT.iobase);
+		PORT.icount.tx++;
+		PORT.x_char = 0;
+		return;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&PORT)) {
+		serial98_stop_tx(port, 0);
+		return;
+	}
+
+	count = PORT.fifosize;
+	do {
+		outb(xmit->buf[xmit->tail], PORT.iobase);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		PORT.icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (--count > 0);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&PORT);
+
+	if (uart_circ_empty(xmit))
+		serial98_stop_tx(&PORT, 0);
+}
+
+static void serial98_modem_status(struct uart_port *port)
+{
+	int status;
+
+	status = serial98_msr_in(port);
+
+	if ((status & UART_MSR_ANY_DELTA) == 0)
+		return;
+
+	if (status & UART_MSR_TERI)
+		PORT.icount.rng++;
+	if (status & UART_MSR_DDSR)
+		PORT.icount.dsr++;
+	if (status & UART_MSR_DDCD)
+		uart_handle_dcd_change(&PORT, status & UART_MSR_DCD);
+	if (status & UART_MSR_DCTS)
+		uart_handle_cts_change(&PORT, status & UART_MSR_CTS);
+
+	wake_up_interruptible(&PORT.info->delta_msr_wait);
+}
+
+static void serial98_int(int irq, void *port, struct pt_regs *regs)
+{
+	unsigned int status;
+
+	spin_lock(&PORT.lock);
+	status = inb(PORT.iobase + 2);
+	if (status & PORT98->rxrdy) {
+		serial98_rx_chars(port, &status, regs);
+	}
+	serial98_modem_status(port);
+	if (status & PORT98->txrdy) {
+		serial98_tx_chars(port);
+	}
+	spin_unlock(&PORT.lock);
+}
+
+static unsigned int serial98_tx_empty(struct uart_port *port)
+{
+	unsigned long flags;
+	unsigned int ret = 0;
+
+	spin_lock_irqsave(&PORT.lock, flags);
+	if (inb(PORT.iobase + 2) & PORT98->txemp)
+			ret = TIOCSER_TEMT;
+
+	spin_unlock_irqrestore(&PORT.lock, flags);
+	return ret;
+}
+
+static unsigned int serial98_get_mctrl(struct uart_port *port)
+{
+	unsigned char status;
+	unsigned int ret = 0;
+
+	status = serial98_msr_in(port);
+	if (status & UART_MSR_DCD)
+		ret |= TIOCM_CAR;
+	if (status & UART_MSR_RI)
+		ret |= TIOCM_RNG;
+	if (status & UART_MSR_DSR)
+		ret |= TIOCM_DSR;
+	if (status & UART_MSR_CTS)
+		ret |= TIOCM_CTS;
+	return ret;
+}
+
+static void serial98_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	PORT98->cmd &= 0xdd;
+	if (mctrl & TIOCM_RTS)
+		PORT98->cmd |= CMD_RTS;
+
+	if (mctrl & TIOCM_DTR)
+		PORT98->cmd |= CMD_DTR;
+
+	serial98_cmd_out(port, PORT98->cmd);
+}
+
+static void serial98_break_ctl(struct uart_port *port, int break_state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&PORT.lock, flags);
+	if (break_state == -1)
+		PORT98->cmd |= CMD_BREAK;
+	else
+		PORT98->cmd &= ~CMD_BREAK;
+
+	serial98_cmd_out(port, PORT98->cmd);
+	spin_unlock_irqrestore(&PORT.lock, flags);
+}
+
+static int serial98_startup(struct uart_port *port)
+{
+	int retval;
+
+	if (PORT.type == PORT_8251_PC98) {
+		/* Wake up UART */
+		PORT98->mode = 0xfc;
+		serial98_mode_set(port);
+		outb(DIS_RXR_INT, IER1_CTL);
+		outb(DIS_TXE_INT, IER1_CTL);
+		outb(DIS_TXR_INT, IER1_CTL);
+		PORT98->mode = 0;
+		serial98_mode_set(port);
+	}
+
+	/*
+	 * Clear the FIFO buffers and disable them.
+	 * (they will be reeanbled in set_termios())
+	 */
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		outb(UART_FCR_ENABLE_FIFO, FCR_8251F);
+		outb((UART_FCR_ENABLE_FIFO
+			| UART_FCR_CLEAR_RCVR
+			| UART_FCR_CLEAR_XMIT), FCR_8251F);
+		outb(0, FCR_8251F);
+	}
+
+	/* Clear the interrupt registers. */
+	inb(0x30);
+	inb(0x32);
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		inb(PORT.iobase);
+		inb(PORT.iobase + 2);
+		inb(PORT.iobase + 4);
+		inb(PORT.iobase + 6);
+	}
+
+	/* Allocate the IRQ */
+	retval = request_irq(PORT.irq, serial98_int, 0,
+				serial98_reg.driver_name, port);
+	if (retval)
+		return retval;
+
+	/*
+	 * Now, initialize the UART
+	 */
+	PORT98->mode = 0x4e;
+	serial98_mode_set(port);
+	PORT98->cmd = 0x15;
+	serial98_cmd_out(port, PORT98->cmd);
+	PORT98->cmd = 0x05;
+
+	/*
+	 * Finally, enable interrupts
+	 */
+	outb(0x00, IER2_8251F);
+	outb(ENA_RXR_INT, IER1_CTL);
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	inb(0x30);
+	inb(0x32);
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		inb(PORT.iobase);
+		inb(PORT.iobase + 2);
+		inb(PORT.iobase + 4);
+		inb(PORT.iobase + 6);
+	}
+
+	return 0;
+}
+
+static void serial98_shutdown(struct uart_port *port)
+{
+	unsigned long flags;
+
+	/*
+	 * disable all interrupts
+	 */
+	spin_lock_irqsave(&PORT.lock, flags);
+	if (PORT.type == PORT_VFAST_PC98)
+		outb(0, VFAST_8251F);		/* V.FAST mode off */
+
+	/* disnable all modem status interrupt */
+	outb(0x80, IER2_8251F);
+
+	/* disnable TX/RX interrupt */
+	outb(0x00, IER2_8251F);
+	outb(DIS_RXR_INT, IER1_CTL);
+	outb(DIS_TXE_INT, IER1_CTL);
+	outb(DIS_TXR_INT, IER1_CTL);
+	PORT98->ier = 0;
+
+	spin_unlock_irqrestore(&PORT.lock, flags);
+
+	/*
+	 * Free the interrupt
+	 */
+	free_irq(PORT.irq, port);
+
+	/* disable break condition and disable the port */
+	serial98_mode_set(port);
+
+	/* disable FIFO's */	
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		outb((UART_FCR_ENABLE_FIFO
+			| UART_FCR_CLEAR_RCVR
+			| UART_FCR_CLEAR_XMIT), FCR_8251F);
+		outb(0, FCR_8251F);
+	}
+
+	inb(PORT.iobase);
+}
+
+static void
+serial98_set_termios(struct uart_port *port, struct termios *termios,
+		       struct termios *old)
+{
+	unsigned char stopbit, cval, fcr = 0, ier = 0;
+	unsigned long flags;
+	unsigned int baud, quot;
+
+	stopbit = 0x80;
+	switch (termios->c_cflag & CSIZE) {
+		case CS5:
+			cval = 0x42;
+			stopbit = 0xc0;
+			break;
+		case CS6:
+			cval = 0x46;
+			break;
+		case CS7:
+			cval = 0x4a;
+			break;
+		default:
+		case CS8:
+			cval = 0x4e;
+			break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cval ^= stopbit;
+	if (termios->c_cflag & PARENB)
+		cval |= 0x10;
+	if (!(termios->c_cflag & PARODD))
+		cval |= 0x20;
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+	quot = uart_get_divisor(port, baud);
+
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		if ((PORT.uartclk / quot) < (2400 * 16))
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+		else
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
+	}
+
+	/*
+	 * Ok, we're now changing the port state.  Do it with
+	 * interrupts disabled.
+	 */
+	spin_lock_irqsave(&PORT.lock, flags);
+
+	/*
+	 * Update the per-port timeout.
+	 */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	PORT.read_status_mask = PORT98->oe | PORT98->txemp | PORT98->dr;
+	if (termios->c_iflag & INPCK)
+		PORT.read_status_mask |= PORT98->fe | PORT98->pe;
+
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		PORT.read_status_mask |= PORT98->brk;
+	/*
+	 * Characters to ignore
+	 */
+	PORT.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		PORT.ignore_status_mask |= PORT98->fe | PORT98->pe;
+
+	if (termios->c_iflag & IGNBRK) {
+		PORT.ignore_status_mask |= PORT98->brk;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			PORT.ignore_status_mask |= PORT98->oe;
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		PORT.ignore_status_mask |= PORT98->dr;
+
+	/*
+	 * CTS flow control flag and modem status interrupts
+	 */
+	if (PORT.flags & UPF_HARDPPS_CD)
+		ier |= 0x80;	/* enable modem status interrupt */
+	if (termios->c_cflag & CRTSCTS) {
+		ier |= 0x08;	/* enable CTS interrupt */
+		ier |= 0x80;	/* enable modem status interrupt */
+	}
+	if (!(termios->c_cflag & CLOCAL)) {
+		ier |= 0x20;	/* enable CD interrupt */
+		ier |= 0x80;	/* enable modem status interrupt */
+	}
+	PORT98->ier = ier;
+
+	PORT98->mode = cval;
+	serial98_mode_set(port);
+	if (PORT.type == PORT_VFAST_PC98 && quot <= 48) {
+		quot /= 4;
+		if (quot < 1)
+			quot = 1;
+		outb(quot | VFAST_ENABLE, VFAST_8251F);
+	} else {
+		quot /= 3;
+		if (quot < 1)
+			quot = 1;
+		if (PORT.type == PORT_VFAST_PC98)
+			outb(0, VFAST_8251F);		/* V.FAST mode off */
+		outb(0xb6, 0x77);
+		outb(quot & 0xff, 0x75);		/* LS of divisor */
+		outb(quot >> 8, 0x75);			/* MS of divisor */
+	}
+
+	if (fcr & UART_FCR_ENABLE_FIFO) {
+		outb(UART_FCR_ENABLE_FIFO, FCR_8251F);
+		outb(fcr, FCR_8251F);
+	}
+
+	/* enable RX/TX */
+	PORT98->cmd = 0x15;
+	serial98_cmd_out(port, PORT98->cmd);
+	PORT98->cmd = 0x05;
+	/* enable interrupts */
+	outb(0x00, IER2_8251F);
+	outb(ENA_RXR_INT, IER1_CTL);
+	spin_unlock_irqrestore(&PORT.lock, flags);
+}
+
+static const char *serial98_type(struct uart_port *port)
+{
+	char *p;
+
+	switch (PORT.type) {
+		case PORT_8251_PC98:
+			p = "PC98 onboard legacy 8251";
+			break;
+		case PORT_19K_PC98:
+			p =  "PC98 onboard max 19200bps";
+			break;
+		case PORT_FIFO_PC98:
+			p = "PC98 onboard with FIFO";
+			break;
+		case PORT_VFAST_PC98:
+			p = "PC98 onboard V.FAST";
+			break;
+		case PORT_PC9861:
+			p = "PC-9861K RS-232C ext. board";
+			break;
+		case PORT_PC9801_101:
+			p = "PC-9801-101 RS-232C ext. board";
+			break;
+		default:
+			return NULL;
+	}
+
+	sprintf(type_str, "%s  Clock %dMHz", p, serial98_clk);
+	return type_str;
+}
+
+/* Release the region(s) being used by 'port' */
+static void serial98_release_port(struct uart_port *port)
+{
+	switch (PORT.type) {
+		case PORT_VFAST_PC98:
+			release_region(PORT.iobase + 0xa, 1);
+		case PORT_FIFO_PC98:
+			release_region(PORT.iobase + 8, 1);
+			release_region(PORT.iobase + 6, 1);
+			release_region(PORT.iobase + 4, 1);
+			release_region(PORT.iobase + 2, 1);
+			release_region(PORT.iobase, 1);
+		case PORT_19K_PC98:
+			release_region(SERIAL98_EXT, 1);
+			release_region(0x34, 1);
+		case PORT_8251_PC98:
+			release_region(0x32, 1);
+			release_region(0x30, 1);
+	}
+}
+
+/* Request the region(s) being used by 'port' */
+#define REQ_REGION98(base) (request_region((base), 1, serial98_reg.driver_name))
+static int serial98_request_region(unsigned int type)
+{
+	if (!REQ_REGION98(0x30))
+		return -EBUSY;
+	if (REQ_REGION98(0x32)) {
+		if (type == PORT_8251_PC98)
+			return 0;
+		if (REQ_REGION98(0x34)) {
+			if (REQ_REGION98(SERIAL98_EXT)) {
+				unsigned long base;
+
+				if (type == PORT_19K_PC98)
+					return 0;
+				for (base = 0x130; base <= 0x138; base += 2) {
+					if (!REQ_REGION98(base)) {
+						base -= 2;
+						goto err;
+					}
+				}
+				if (type == PORT_FIFO_PC98)
+					return 0;
+				if (type == PORT_VFAST_PC98) {
+					if (REQ_REGION98(0x13a))
+						return 0;
+				}
+				err:
+				while (base >= 0x130) {
+					release_region(base, 1);
+					base -= 2;
+				}
+				release_region(SERIAL98_EXT, 1);
+			}
+			release_region(0x34, 1);
+		}
+		release_region(0x32, 1);
+	}
+	release_region(0x30, 1);
+	return -EBUSY;
+}
+
+static int serial98_request_port(struct uart_port *port)
+{
+	return serial98_request_region(PORT.type);
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void serial98_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		PORT.type = PORT98->type;
+}
+
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int serial98_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	switch (ser->type) {
+		case PORT_VFAST_PC98:
+		case PORT_FIFO_PC98:
+		case PORT_19K_PC98:
+		case PORT_8251_PC98:
+		/* not implemented yet
+		case PORT_PC9861:
+		case PORT_PC9801_101:
+		*/
+		case PORT_UNKNOWN:
+			break;
+		default:
+			return -EINVAL;
+	}
+	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+		return -EINVAL;
+	if (ser->baud_base < 9600)
+		return -EINVAL;
+	return 0;
+}
+
+static struct uart_ops serial98_ops = {
+	.tx_empty	= serial98_tx_empty,
+	.set_mctrl	= serial98_set_mctrl,
+	.get_mctrl	= serial98_get_mctrl,
+	.stop_tx	= serial98_stop_tx,
+	.start_tx	= serial98_start_tx,
+	.stop_rx	= serial98_stop_rx,
+	.enable_ms	= serial98_enable_ms,
+	.break_ctl	= serial98_break_ctl,
+	.startup	= serial98_startup,
+	.shutdown	= serial98_shutdown,
+	.set_termios	= serial98_set_termios,
+	.type		= serial98_type,
+	.release_port	= serial98_release_port,
+	.request_port	= serial98_request_port,
+	.config_port	= serial98_config_port,
+	.verify_port	= serial98_verify_port,
+};
+
+static struct serial98_port serial98_ports[SERIAL98_NR] = {
+	{
+		.port =	{
+				.iobase		= 0x30,
+				.iotype		= SERIAL_IO_PORT,
+				.irq		= 4,
+				.fifosize	= 1,
+				.ops		= &serial98_ops,
+				.flags		= ASYNC_BOOT_AUTOCONF,
+				.line		= 0,
+			},
+		.rxchk = STAT_8251_RXRDY,
+		.txemp = STAT_8251_TXEMP,
+		.txrdy = STAT_8251_TXRDY,
+		.rxrdy = STAT_8251_RXRDY,
+		.brk = STAT_8251_BRK,
+		.fe = STAT_8251_FER,
+		.oe = STAT_8251_OER,
+		.pe = STAT_8251_PER,
+		.dr = STAT_8251_DSR,
+	},
+};
+
+#ifdef CONFIG_SERIAL98_CONSOLE
+
+#define BOTH_EMPTY (PORT98->txemp | PORT98->txrdy)
+
+/*
+ *	Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_port *port)
+{
+	unsigned int status, tmout = 10000;
+
+	/* Wait up to 10ms for the character(s) to be sent. */
+	do {
+		status = inb(PORT.iobase + 2);
+
+		if (status & PORT98->brk)
+			PORT98->lsr_break_flag = PORT98->brk;
+
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+
+	/* Wait up to 1s for flow control if necessary */
+	if (PORT.flags & UPF_CONS_FLOW) {
+		tmout = 1000000;
+		while (--tmout &&
+		       ((serial98_msr_in(port) & UART_MSR_CTS) == 0))
+			udelay(1);
+	}
+}
+
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ *
+ *	The console_lock must be held when we get here.
+ */
+static void
+serial98_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct uart_port *port = (struct uart_port *)&serial98_ports[co->index];
+	unsigned int ier1, ier2;
+	int i;
+
+	/*
+	 *	First save the UER then disable the interrupts
+	 */
+	ier1 = inb(IER1_8251F);
+	ier2 = inb(IER2_8251F);
+	/* disnable all modem status interrupt */
+	outb(0x80, IER2_8251F);
+
+	/* disnable TX/RX interrupt */
+	outb(0x00, IER2_8251F);
+	outb(DIS_RXR_INT, IER1_CTL);
+	outb(DIS_TXE_INT, IER1_CTL);
+	outb(DIS_TXR_INT, IER1_CTL);
+
+	/*
+	 *	Now, do each character
+	 */
+	for (i = 0; i < count; i++, s++) {
+		wait_for_xmitr(port);
+
+		/*
+		 *	Send the character out.
+		 *	If a LF, also do CR...
+		 */
+		outb(*s, PORT.iobase);
+		if (*s == 10) {
+			wait_for_xmitr(port);
+			outb(13, PORT.iobase);
+		}
+	}
+
+	/*
+	 *	Finally, wait for transmitter to become empty
+	 *	and restore the IER
+	 */
+	wait_for_xmitr(port);
+
+	/* restore TX/RX interrupt */
+	outb(0x00, IER2_8251F);
+	if (ier1 & 0x01)
+		outb(ENA_RXR_INT, IER1_CTL);
+	if (ier1 & 0x02)
+		outb(ENA_TXE_INT, IER1_CTL);
+	if (ier1 & 0x04)
+		outb(ENA_TXR_INT, IER1_CTL);
+
+	/* restore modem status interrupt */
+	outb(ier2, IER2_8251F);
+}
+
+static kdev_t serial98_console_device(struct console *co)
+{
+	return mk_kdev(TTY_MAJOR, 64 + co->index);
+}
+
+static int __init serial98_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	/*
+	 * Check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	if (co->index >= SERIAL98_NR)
+		co->index = 0;
+	port = &serial98_ports[co->index].port;
+
+	/*
+	 * Temporary fix.
+	 */
+	spin_lock_init(&port->lock);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+void __init serial98_console_init(void)
+{
+	register_console(&serial98_console);
+}
+
+#endif /* CONFIG_SERIAL98_CONSOLE */
+
+
+static int __init serial98_init(void)
+{
+	int ret;
+	unsigned char iir1, iir2;
+
+	if (PC9800_8MHz_P()) {
+		serial98_clk = 8;
+		serial98_ports[0].port.uartclk = 374400 * 16;
+	} else {
+		serial98_clk = 5;
+		serial98_ports[0].port.uartclk = 460800 * 16;
+	}
+
+	printk(KERN_INFO "serial98: PC-9801 standard serial port driver Version 0.1alpha\n");
+	serial98_ports[0].type = PORT_8251_PC98;
+	/* Check FIFO exist */
+	iir1 = inb(IIR_8251F);
+	iir2 = inb(IIR_8251F);
+	if ((iir1 & 0x40) != (iir2 & 0x40) && (iir1 & 0x20) == (iir2 & 0x20)) {
+		serial98_ports[0].port.iobase = 0x130;
+		serial98_ports[0].port.fifosize = 16;
+		serial98_ports[0].rxchk = STAT_8251F_DSR;
+		serial98_ports[0].txemp = STAT_8251F_TXEMP;
+		serial98_ports[0].txrdy = STAT_8251F_TXRDY;
+		serial98_ports[0].rxrdy = STAT_8251F_RXRDY;
+		serial98_ports[0].brk = STAT_8251F_BRK;
+		serial98_ports[0].fe = STAT_8251F_FER;
+		serial98_ports[0].oe = STAT_8251F_OER;
+		serial98_ports[0].pe = STAT_8251F_PER;
+		serial98_ports[0].dr = STAT_8251F_DSR;
+
+		if (*(unsigned char*)__va(PC9821SCA_RSFLAGS) & 0x10)
+			serial98_ports[0].type = PORT_VFAST_PC98;
+		else {
+			outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT);
+			serial98_ports[0].port.uartclk *= 4;
+			serial98_ports[0].type = PORT_FIFO_PC98;
+		}
+	} else if ((serial98_ports[0].ext = inb(SERIAL98_EXT)) != 0xff) {
+		outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT);
+		if (inb(SERIAL98_EXT) == (serial98_ports[0].ext | 0x40)) {
+			serial98_ports[0].port.uartclk *= 4;
+			serial98_ports[0].type = PORT_19K_PC98;
+		} else {
+			serial98_ops.enable_ms = NULL;
+			outb(serial98_ports[0].ext, SERIAL98_EXT);
+		}
+	}
+
+	if (serial98_request_region(serial98_ports[0].type))
+		return -EBUSY;
+
+	ret = uart_register_driver(&serial98_reg);
+	if (ret == 0) {
+		int i;
+
+		for (i = 0; i < SERIAL98_NR; i++) {
+			uart_add_one_port(&serial98_reg,
+					(struct uart_port *)&serial98_ports[i]);
+		}
+	}
+
+	return ret;
+}
+
+static void __exit serial98_exit(void)
+{
+	int i;
+
+	if (serial98_ports[0].type == PORT_19K_PC98
+			|| serial98_ports[0].type == PORT_FIFO_PC98)
+		outb(serial98_ports[0].ext, SERIAL98_EXT);
+
+	for (i = 0; i < SERIAL98_NR; i++) {
+		uart_remove_one_port(&serial98_reg,
+					(struct uart_port *)&serial98_ports[i]);
+	}
+
+	uart_unregister_driver(&serial98_reg);
+}
+
+module_init(serial98_init);
+module_exit(serial98_exit);
+
+MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
+MODULE_DESCRIPTION("PC-9801 standard serial port driver Version 0.1alpha");
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.65-bk2/drivers/telephony/ixj.c linux-2.5.65-bk3/drivers/telephony/ixj.c
--- linux-2.5.65-bk2/drivers/telephony/ixj.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/drivers/telephony/ixj.c	Mon Mar 31 12:41:43 2003
@@ -5999,12 +5999,14 @@
 		if(ixjdebug & 0x0001) {
 			printk(KERN_INFO "Could not copy cadence to kernel\n");
 		}
+		kfree(lcp);
 		return -EFAULT;
 	}
 	if (lcp->filter > 5) {
 		if(ixjdebug & 0x0001) {
 			printk(KERN_INFO "Cadence out of range\n");
 		}
+		kfree(lcp);
 		return -1;
 	}
 	j->cadence_f[lcp->filter].state = 0;
diff -urN linux-2.5.65-bk2/fs/Kconfig linux-2.5.65-bk3/fs/Kconfig
--- linux-2.5.65-bk2/fs/Kconfig	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/fs/Kconfig	Mon Mar 31 12:41:43 2003
@@ -1357,6 +1357,35 @@
 	tristate
 	default NFSD
 
+config SUNRPC
+	tristate
+	default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m)
+	default y if NFS_FS=y || NFSD=y
+
+config SUNRPC_GSS
+	tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)"
+	depends on SUNRPC && EXPERIMENTAL
+	default SUNRPC if NFS_V4=y
+	help
+	  Provides cryptographic authentication for NFS rpc requests.  To
+	  make this useful, you must also select at least one rpcsec_gss
+	  mechanism.
+	  Note: You should always select this option if you wish to use
+	  NFSv4.
+
+config RPCSEC_GSS_KRB5
+	tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)"
+	depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5
+	default SUNRPC_GSS if NFS_V4=y
+	help
+	  Provides a gss-api mechanism based on Kerberos V5 (this is
+	  mandatory for RFC3010-compliant NFSv4 implementations).
+	  Requires a userspace daemon;
+		see http://www.citi.umich.edu/projects/nfsv4/.
+
+	  Note: If you select this option, please ensure that you also
+	  enable the MD5 and DES crypto ciphers.
+
 config SMB_FS
 	tristate "SMB file system support (to mount Windows shares etc.)"
 	depends on INET
@@ -1460,6 +1489,8 @@
 	  will be called ncpfs.  Say N unless you are connected to a Novell
 	  network.
 
+source "fs/ncpfs/Kconfig"
+
 config CODA_FS
 	tristate "Coda file system support (advanced network fs)"
 	depends on INET
@@ -1497,37 +1528,6 @@
 	  support.  You will also need a file server daemon, which you can get
 	  from <http://www.inter-mezzo.org/>.
 
-config SUNRPC
-	tristate
-	default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m)
-	default y if NFS_FS=y || NFSD=y
-
-config SUNRPC_GSS
-	tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)"
-	depends on SUNRPC && EXPERIMENTAL
-	default SUNRPC if NFS_V4=y
-	help
-	  Provides cryptographic authentication for NFS rpc requests.  To
-	  make this useful, you must also select at least one rpcsec_gss
-	  mechanism.
-	  Note: You should always select this option if you wish to use
-	  NFSv4.
-
-config RPCSEC_GSS_KRB5
-	tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)"
-	depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5
-	default SUNRPC_GSS if NFS_V4=y
-	help
-	  Provides a gss-api mechanism based on Kerberos V5 (this is
-	  mandatory for RFC3010-compliant NFSv4 implementations).
-	  Requires a userspace daemon;
-		see http://www.citi.umich.edu/projects/nfsv4/.
-
-	  Note: If you select this option, please ensure that you also
-	  enable the MD5 and DES crypto ciphers.
-
-source "fs/ncpfs/Kconfig"
-
 config AFS_FS
 # for fs/nls/Config.in
 	tristate "Andrew File System support (AFS) (Experimental)"
diff -urN linux-2.5.65-bk2/fs/autofs/inode.c linux-2.5.65-bk3/fs/autofs/inode.c
--- linux-2.5.65-bk2/fs/autofs/inode.c	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk3/fs/autofs/inode.c	Mon Mar 31 12:41:43 2003
@@ -16,7 +16,6 @@
 #include <linux/file.h>
 #include <asm/bitops.h>
 #include "autofs_i.h"
-#define __NO_VERSION__
 #include <linux/module.h>
 
 static void autofs_put_super(struct super_block *sb)
diff -urN linux-2.5.65-bk2/fs/autofs4/inode.c linux-2.5.65-bk3/fs/autofs4/inode.c
--- linux-2.5.65-bk2/fs/autofs4/inode.c	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk3/fs/autofs4/inode.c	Mon Mar 31 12:41:43 2003
@@ -16,7 +16,6 @@
 #include <linux/pagemap.h>
 #include <asm/bitops.h>
 #include "autofs_i.h"
-#define __NO_VERSION__
 #include <linux/module.h>
 
 static void ino_lnkfree(struct autofs_info *ino)
diff -urN linux-2.5.65-bk2/fs/befs/debug.c linux-2.5.65-bk3/fs/befs/debug.c
--- linux-2.5.65-bk2/fs/befs/debug.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/fs/befs/debug.c	Mon Mar 31 12:41:43 2003
@@ -80,7 +80,7 @@
 
 	befs_block_run tmp_run;
 
-	befs_debug(sb, "befs_inode infomation");
+	befs_debug(sb, "befs_inode information");
 
 	befs_debug(sb, "  magic1 %08x", fs32_to_cpu(sb, inode->magic1));
 
diff -urN linux-2.5.65-bk2/fs/buffer.c linux-2.5.65-bk3/fs/buffer.c
--- linux-2.5.65-bk2/fs/buffer.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/fs/buffer.c	Mon Mar 31 12:41:44 2003
@@ -532,7 +532,7 @@
  * Completion handler for block_write_full_page() - pages which are unlocked
  * during I/O, and which have PageWriteback cleared upon I/O completion.
  */
-static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
+void end_buffer_async_write(struct buffer_head *bh, int uptodate)
 {
 	static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
 	unsigned long flags;
diff -urN linux-2.5.65-bk2/fs/cifs/cifs_debug.c linux-2.5.65-bk3/fs/cifs/cifs_debug.c
--- linux-2.5.65-bk2/fs/cifs/cifs_debug.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/fs/cifs/cifs_debug.c	Mon Mar 31 12:41:44 2003
@@ -22,7 +22,6 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
diff -urN linux-2.5.65-bk2/fs/devfs/base.c linux-2.5.65-bk3/fs/devfs/base.c
--- linux-2.5.65-bk2/fs/devfs/base.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/fs/devfs/base.c	Mon Mar 31 12:41:44 2003
@@ -758,7 +758,6 @@
     rwlock_t lock;                   /*  Lock for searching(R)/updating(W)   */
     struct devfs_entry *first;
     struct devfs_entry *last;
-    unsigned short num_removable;    /*  Lock for writing but not reading    */
     unsigned char no_more_additions:1;
 };
 
@@ -766,7 +765,6 @@
 {
     struct block_device_operations *ops;
     dev_t dev;
-    unsigned char removable:1;
 };
 
 struct cdev_type
@@ -916,7 +914,7 @@
  *	@de:  The handle to the devfs entry.
  */
 
-void devfs_put (devfs_handle_t de)
+static void devfs_put (devfs_handle_t de)
 {
     if (!de) return;
     VERIFY_ENTRY (de);
@@ -1017,7 +1015,6 @@
  *	_devfs_append_entry - Append a devfs entry to a directory's child list.
  *	@dir:  The directory to add to.
  *	@de:  The devfs entry to append.
- *	@removable: If TRUE, increment the count of removable devices for %dir.
  *	@old_de: If an existing entry exists, it will be written here. This may
  *		 be %NULL. An implicit devfs_get() is performed on this entry.
  *
@@ -1028,7 +1025,7 @@
  */
 
 static int _devfs_append_entry (devfs_handle_t dir, devfs_handle_t de,
-				int removable, devfs_handle_t *old_de)
+				devfs_handle_t *old_de)
 {
     int retval;
 
@@ -1056,7 +1053,6 @@
 	    if (dir->u.dir.first == NULL) dir->u.dir.first = de;
 	    else dir->u.dir.last->next = de;
 	    dir->u.dir.last = de;
-	    if (removable) ++dir->u.dir.num_removable;
 	    retval = 0;
 	}
 	else retval = -EEXIST;
@@ -1095,13 +1091,13 @@
 	 == NULL ) return NULL;
     new->u.cdev.dev = devfs_alloc_devnum (S_IFCHR |S_IRUSR |S_IWUSR);
     new->u.cdev.ops = &devfsd_fops;
-    _devfs_append_entry (root_entry, new, FALSE, NULL);
+    _devfs_append_entry (root_entry, new, NULL);
 #ifdef CONFIG_DEVFS_DEBUG
     if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) )
 	 == NULL ) return NULL;
     new->u.cdev.dev = devfs_alloc_devnum (S_IFCHR | S_IRUGO | S_IWUGO);
     new->u.cdev.ops = &stat_fops;
-    _devfs_append_entry (root_entry, new, FALSE, NULL);
+    _devfs_append_entry (root_entry, new, NULL);
 #endif
     return root_entry;
 }   /*  End Function _devfs_get_root_entry  */
@@ -1164,7 +1160,7 @@
 	{
 	    de = _devfs_alloc_entry (name, next_pos, MODE_DIR);
 	    devfs_get (de);
-	    if ( !de || _devfs_append_entry (dir, de, FALSE, &old) )
+	    if ( !de || _devfs_append_entry (dir, de, &old) )
 	    {
 		devfs_put (de);
 		if ( !old || !S_ISDIR (old->mode) )
@@ -1498,7 +1494,6 @@
 	de->u.bdev.dev = dev;
 	de->u.cdev.autogen = devnum != 0;
 	de->u.bdev.ops = ops;
-	if (flags & DEVFS_FL_REMOVABLE) de->u.bdev.removable = TRUE;
     } else {
 	PRINTK ("(%s): illegal mode: %x\n", name, mode);
 	devfs_put (de);
@@ -1516,7 +1511,7 @@
 	de->inode.uid = 0;
 	de->inode.gid = 0;
     }
-    err = _devfs_append_entry(dir, de, flags & DEVFS_FL_REMOVABLE, NULL);
+    err = _devfs_append_entry(dir, de, NULL);
     if (err)
     {
 	PRINTK ("(%s): could not append to parent, err: %d\n", name, err);
@@ -1553,8 +1548,6 @@
     else de->next->prev = de->prev;
     de->prev = de;          /*  Indicate we're unhooked                      */
     de->next = NULL;        /*  Force early termination for <devfs_readdir>  */
-    if (S_ISBLK (de->mode) && de->u.bdev.removable )
-	--parent->u.dir.num_removable;
     return TRUE;
 }   /*  End Function _devfs_unhook  */
 
@@ -1648,7 +1641,7 @@
     de->info = info;
     de->u.symlink.linkname = newlink;
     de->u.symlink.length = linklength;
-    if ( ( err = _devfs_append_entry (dir, de, FALSE, NULL) ) != 0 )
+    if ( ( err = _devfs_append_entry (dir, de, NULL) ) != 0 )
     {
 	PRINTK ("(%s): could not append to parent, err: %d\n", name, err);
 	devfs_put (dir);
@@ -1725,7 +1718,7 @@
 	return NULL;
     }
     de->info = info;
-    if ( ( err = _devfs_append_entry (dir, de, FALSE, &old) ) != 0 )
+    if ( ( err = _devfs_append_entry (dir, de, &old) ) != 0 )
     {
 	PRINTK ("(%s): could not append to dir: %p \"%s\", err: %d\n",
 		name, dir, dir->name, err);
@@ -1924,102 +1917,6 @@
 }   /*  End Function try_modload  */
 
 
-/**
- *	check_disc_changed - Check if a removable disc was changed.
- *	@de: The device.
- *
- *	Returns 1 if the media was changed, else 0.
- *
- *	This function may block, and may indirectly cause the parent directory
- *	contents to be changed due to partition re-reading.
- */
-
-static int check_disc_changed (struct devfs_entry *de)
-{
-	int tmp;
-	int retval = 0;
-	dev_t dev = de->u.bdev.dev;
-	extern int warn_no_part;
-
-	if (!S_ISBLK(de->mode))
-		return 0;
-	/* Ugly hack to disable messages about unable to read partition table */
-	tmp = warn_no_part;
-	warn_no_part = 0;
-	retval = __check_disk_change(dev);
-	warn_no_part = tmp;
-	return retval;
-}   /*  End Function check_disc_changed  */
-
-/**
- *	scan_dir_for_removable - Scan a directory for removable media devices and check media.
- *	@dir: The directory.
- *
- *	This function may block, and may indirectly cause the directory
- *	contents to be changed due to partition re-reading. The directory will
- *	be locked for reading.
- */
-
-static void scan_dir_for_removable (struct devfs_entry *dir)
-{
-    struct devfs_entry *de;
-
-    read_lock (&dir->u.dir.lock);
-    if (dir->u.dir.num_removable < 1) de = NULL;
-    else
-    {
-	for (de = dir->u.dir.first; de != NULL; de = de->next)
-	{
-	    if (S_ISBLK (de->mode) && de->u.bdev.removable) break;
-	}
-	devfs_get (de);
-    }
-    read_unlock (&dir->u.dir.lock);
-    if (de) check_disc_changed (de);
-    devfs_put (de);
-}   /*  End Function scan_dir_for_removable  */
-
-/**
- *	get_removable_partition - Get removable media partition.
- *	@dir: The parent directory.
- *	@name: The name of the entry.
- *	@namelen: The number of characters in <<name>>.
- *
- *	Returns 1 if the media was changed, else 0.
- *
- *	This function may block, and may indirectly cause the directory
- *	contents to be changed due to partition re-reading. The directory must
- *	be locked for reading upon entry, and will be unlocked upon exit.
- */
-
-static int get_removable_partition (struct devfs_entry *dir, const char *name,
-				    unsigned int namelen)
-{
-    int retval;
-    struct devfs_entry *de;
-
-    if (dir->u.dir.num_removable < 1)
-    {
-	read_unlock (&dir->u.dir.lock);
-	return 0;
-    }
-    for (de = dir->u.dir.first; de != NULL; de = de->next)
-    {
-	if (!S_ISBLK (de->mode) || !de->u.bdev.removable) continue;
-	if (strcmp (de->name, "disc") == 0) break;
-	/*  Support for names where the partition is appended to the disc name
-	 */
-	if (de->namelen >= namelen) continue;
-	if (strncmp (de->name, name, de->namelen) == 0) break;
-    }
-    devfs_get (de);
-    read_unlock (&dir->u.dir.lock);
-    retval = de ? check_disc_changed (de) : 0;
-    devfs_put (de);
-    return retval;
-}   /*  End Function get_removable_partition  */
-
-
 /*  Superblock operations follow  */
 
 static struct inode_operations devfs_iops;
@@ -2169,7 +2066,6 @@
     switch ( (long) file->f_pos )
     {
       case 0:
-	scan_dir_for_removable (parent);
 	err = (*filldir) (dirent, "..", 2, file->f_pos,
 			  parent_ino (file->f_dentry), DT_DIR);
 	if (err == -EINVAL) break;
@@ -2336,6 +2232,8 @@
     wait_queue_head_t wait_queue;
 };
 
+/* XXX: this doesn't handle the case where we got a negative dentry
+        but a devfs entry has been registered in the meanwhile */
 static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
 {
     struct inode *dir = dentry->d_parent->d_inode;
@@ -2380,6 +2278,7 @@
 	add_wait_queue (&lookup_info->wait_queue, &wait);
 	read_unlock (&parent->u.dir.lock);
 	schedule ();
+	remove_wait_queue (&lookup_info->wait_queue, &wait);
     }
     else read_unlock (&parent->u.dir.lock);
     return 1;
@@ -2407,18 +2306,7 @@
     if (parent == NULL) return ERR_PTR (-ENOENT);
     read_lock (&parent->u.dir.lock);
     de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len);
-    if (de) read_unlock (&parent->u.dir.lock);
-    else
-    {   /*  Try re-reading the partition (media may have changed)  */
-	if ( get_removable_partition (parent, dentry->d_name.name,
-				      dentry->d_name.len) )  /*  Unlocks  */
-	{   /*  Media did change  */
-	    read_lock (&parent->u.dir.lock);
-	    de = _devfs_search_dir (parent, dentry->d_name.name,
-				    dentry->d_name.len);
-	    read_unlock (&parent->u.dir.lock);
-	}
-    }
+    read_unlock (&parent->u.dir.lock);
     lookup_info.de = de;
     init_waitqueue_head (&lookup_info.wait_queue);
     dentry->d_fsdata = &lookup_info;
@@ -2545,7 +2433,7 @@
     de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
     if (!de) return -ENOMEM;
     de->vfs_deletable = TRUE;
-    if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 )
+    if ( ( err = _devfs_append_entry (parent, de, NULL) ) != 0 )
 	return err;
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
@@ -2613,7 +2501,7 @@
 	de->u.cdev.dev = rdev;
     else if (S_ISBLK (mode))
 	de->u.bdev.dev = rdev;
-    if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 )
+    if ( ( err = _devfs_append_entry (parent, de, NULL) ) != 0 )
 	return err;
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
diff -urN linux-2.5.65-bk2/fs/exportfs/expfs.c linux-2.5.65-bk3/fs/exportfs/expfs.c
--- linux-2.5.65-bk2/fs/exportfs/expfs.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/fs/exportfs/expfs.c	Mon Mar 31 12:41:44 2003
@@ -447,7 +447,7 @@
  * @dentry:  the dentry to encode
  * @fh:      where to store the file handle fragment
  * @max_len: maximum length to store there
- * @connectable: whether to store parent infomation
+ * @connectable: whether to store parent information
  *
  * This default encode_fh function assumes that the 32 inode number
  * is suitable for locating an inode, and that the generation number
diff -urN linux-2.5.65-bk2/fs/fat/inode.c linux-2.5.65-bk3/fs/fat/inode.c
--- linux-2.5.65-bk2/fs/fat/inode.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/fs/fat/inode.c	Mon Mar 31 12:41:44 2003
@@ -939,7 +939,8 @@
 		error = first;
 		goto out_fail;
 	}
-	if (FAT_FIRST_ENT(sb, media) != first) {
+	if (FAT_FIRST_ENT(sb, media) != first
+	    && (media != 0xf8 || FAT_FIRST_ENT(sb, 0xfe) != first)) {
 		if (!silent) {
 			printk(KERN_ERR "FAT: invalid first entry of FAT "
 			       "(0x%x != 0x%x)\n",
diff -urN linux-2.5.65-bk2/fs/intermezzo/cache.c linux-2.5.65-bk3/fs/intermezzo/cache.c
--- linux-2.5.65-bk2/fs/intermezzo/cache.c	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/fs/intermezzo/cache.c	Mon Mar 31 12:41:44 2003
@@ -20,7 +20,6 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
diff -urN linux-2.5.65-bk2/fs/intermezzo/dcache.c linux-2.5.65-bk3/fs/intermezzo/dcache.c
--- linux-2.5.65-bk2/fs/intermezzo/dcache.c	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk3/fs/intermezzo/dcache.c	Mon Mar 31 12:41:44 2003
@@ -31,7 +31,6 @@
  * with heavy changes by Linus Torvalds
  */
 
-#define __NO_VERSION__
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -urN linux-2.5.65-bk2/fs/intermezzo/dir.c linux-2.5.65-bk3/fs/intermezzo/dir.c
--- linux-2.5.65-bk2/fs/intermezzo/dir.c	Mon Mar 17 13:43:49 2003
+++ linux-2.5.65-bk3/fs/intermezzo/dir.c	Mon Mar 31 12:41:44 2003
@@ -40,7 +40,6 @@
 #include <linux/smp_lock.h>
 #include <linux/blkdev.h>
 #include <linux/init.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include "intermezzo_fs.h"
diff -urN linux-2.5.65-bk2/fs/intermezzo/ext_attr.c linux-2.5.65-bk3/fs/intermezzo/ext_attr.c
--- linux-2.5.65-bk2/fs/intermezzo/ext_attr.c	Mon Mar 17 13:44:12 2003
+++ linux-2.5.65-bk3/fs/intermezzo/ext_attr.c	Mon Mar 31 12:41:44 2003
@@ -22,7 +22,6 @@
  * Extended attribute handling for presto.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff -urN linux-2.5.65-bk2/fs/intermezzo/file.c linux-2.5.65-bk3/fs/intermezzo/file.c
--- linux-2.5.65-bk2/fs/intermezzo/file.c	Mon Mar 17 13:44:16 2003
+++ linux-2.5.65-bk3/fs/intermezzo/file.c	Mon Mar 31 12:41:44 2003
@@ -45,7 +45,6 @@
 #include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/fsfilter.h>
diff -urN linux-2.5.65-bk2/fs/intermezzo/inode.c linux-2.5.65-bk3/fs/intermezzo/inode.c
--- linux-2.5.65-bk2/fs/intermezzo/inode.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/fs/intermezzo/inode.c	Mon Mar 31 12:41:44 2003
@@ -24,7 +24,6 @@
  * Super block/filesystem wide operations
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff -urN linux-2.5.65-bk2/fs/intermezzo/kml.c linux-2.5.65-bk3/fs/intermezzo/kml.c
--- linux-2.5.65-bk2/fs/intermezzo/kml.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/fs/intermezzo/kml.c	Mon Mar 31 12:41:44 2003
@@ -1,7 +1,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
diff -urN linux-2.5.65-bk2/fs/intermezzo/kml_decode.c linux-2.5.65-bk3/fs/intermezzo/kml_decode.c
--- linux-2.5.65-bk2/fs/intermezzo/kml_decode.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/fs/intermezzo/kml_decode.c	Mon Mar 31 12:41:44 2003
@@ -5,7 +5,6 @@
  *
  * Copyright (C) 2001 Mountainview Data, Inc.
  */
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
diff -urN linux-2.5.65-bk2/fs/intermezzo/kml_reint.c linux-2.5.65-bk3/fs/intermezzo/kml_reint.c
--- linux-2.5.65-bk2/fs/intermezzo/kml_reint.c	Mon Mar 17 13:44:42 2003
+++ linux-2.5.65-bk3/fs/intermezzo/kml_reint.c	Mon Mar 31 12:41:44 2003
@@ -22,7 +22,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
diff -urN linux-2.5.65-bk2/fs/intermezzo/kml_setup.c linux-2.5.65-bk3/fs/intermezzo/kml_setup.c
--- linux-2.5.65-bk2/fs/intermezzo/kml_setup.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/fs/intermezzo/kml_setup.c	Mon Mar 31 12:41:44 2003
@@ -1,7 +1,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
diff -urN linux-2.5.65-bk2/fs/intermezzo/methods.c linux-2.5.65-bk3/fs/intermezzo/methods.c
--- linux-2.5.65-bk2/fs/intermezzo/methods.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/fs/intermezzo/methods.c	Mon Mar 31 12:41:44 2003
@@ -40,7 +40,6 @@
 #include <linux/smp_lock.h>
 #include <linux/blkdev.h>
 #include <linux/init.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/fsfilter.h>
diff -urN linux-2.5.65-bk2/fs/intermezzo/replicator.c linux-2.5.65-bk3/fs/intermezzo/replicator.c
--- linux-2.5.65-bk2/fs/intermezzo/replicator.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/fs/intermezzo/replicator.c	Mon Mar 31 12:41:44 2003
@@ -23,7 +23,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
diff -urN linux-2.5.65-bk2/fs/intermezzo/super.c linux-2.5.65-bk3/fs/intermezzo/super.c
--- linux-2.5.65-bk2/fs/intermezzo/super.c	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk3/fs/intermezzo/super.c	Mon Mar 31 12:41:44 2003
@@ -42,7 +42,6 @@
 #include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include "intermezzo_fs.h"
diff -urN linux-2.5.65-bk2/fs/intermezzo/sysctl.c linux-2.5.65-bk3/fs/intermezzo/sysctl.c
--- linux-2.5.65-bk2/fs/intermezzo/sysctl.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/fs/intermezzo/sysctl.c	Mon Mar 31 12:41:44 2003
@@ -21,7 +21,6 @@
  *  Sysctrl entries for Intermezzo!
  */
 
-#define __NO_VERSION__
 #include <linux/config.h> /* for CONFIG_PROC_FS */
 #include <linux/module.h>
 #include <linux/sched.h>
diff -urN linux-2.5.65-bk2/fs/jffs/intrep.c linux-2.5.65-bk3/fs/jffs/intrep.c
--- linux-2.5.65-bk2/fs/jffs/intrep.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/fs/jffs/intrep.c	Mon Mar 31 12:41:44 2003
@@ -55,7 +55,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/slab.h>
diff -urN linux-2.5.65-bk2/fs/jffs/jffs_fm.c linux-2.5.65-bk3/fs/jffs/jffs_fm.c
--- linux-2.5.65-bk2/fs/jffs/jffs_fm.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/fs/jffs/jffs_fm.c	Mon Mar 31 12:41:44 2003
@@ -16,7 +16,6 @@
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
  *
  */
-#define __NO_VERSION__
 #include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/jffs.h>
diff -urN linux-2.5.65-bk2/fs/lockd/lockd_syms.c linux-2.5.65-bk3/fs/lockd/lockd_syms.c
--- linux-2.5.65-bk2/fs/lockd/lockd_syms.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/fs/lockd/lockd_syms.c	Mon Mar 31 12:41:44 2003
@@ -8,7 +8,6 @@
  * Copyright (C) 1997 Olaf Kirch <okir@monad.swb.de>
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
 
diff -urN linux-2.5.65-bk2/fs/partitions/Kconfig linux-2.5.65-bk3/fs/partitions/Kconfig
--- linux-2.5.65-bk2/fs/partitions/Kconfig	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/fs/partitions/Kconfig	Mon Mar 31 12:41:44 2003
@@ -177,6 +177,13 @@
 
 	  If unsure, say N.
 
+config NEC98_PARTITION
+	bool "NEC PC-9800 partition table support" if PARTITION_ADVANCED
+	default y if !PARTITION_ADVANCED && X86_PC9800
+	help
+	  Say Y here if you would like to be able to read the hard disk
+	  partition table format used by NEC PC-9800 machines.
+
 config SGI_PARTITION
 	bool "SGI partition support" if PARTITION_ADVANCED
 	default y if !PARTITION_ADVANCED && (SGI_IP22 || SGI_IP27)
diff -urN linux-2.5.65-bk2/fs/partitions/Makefile linux-2.5.65-bk3/fs/partitions/Makefile
--- linux-2.5.65-bk2/fs/partitions/Makefile	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/fs/partitions/Makefile	Mon Mar 31 12:41:44 2003
@@ -16,3 +16,4 @@
 obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
 obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
+obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o
diff -urN linux-2.5.65-bk2/fs/partitions/check.c linux-2.5.65-bk3/fs/partitions/check.c
--- linux-2.5.65-bk2/fs/partitions/check.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/fs/partitions/check.c	Mon Mar 31 12:41:44 2003
@@ -28,6 +28,7 @@
 #include "ldm.h"
 #include "mac.h"
 #include "msdos.h"
+#include "nec98.h"
 #include "osf.h"
 #include "sgi.h"
 #include "sun.h"
@@ -51,6 +52,9 @@
 #ifdef CONFIG_LDM_PARTITION
 	ldm_partition,		/* this must come before msdos */
 #endif
+#ifdef CONFIG_NEC98_PARTITION
+	nec98_partition,	/* must be come before `msdos_partition' */
+#endif
 #ifdef CONFIG_MSDOS_PARTITION
 	msdos_partition,
 #endif
@@ -156,7 +160,6 @@
 {
 #ifdef CONFIG_DEVFS_FS
 	devfs_handle_t dir;
-	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
 	struct hd_struct *p = dev->part;
 	char devname[16];
 
@@ -165,10 +168,8 @@
 	dir = dev->de;
 	if (!dir)
 		return;
-	if (dev->flags & GENHD_FL_REMOVABLE)
-		devfs_flags |= DEVFS_FL_REMOVABLE;
 	sprintf(devname, "part%d", part);
-	p[part-1].de = devfs_register (dir, devname, devfs_flags,
+	p[part-1].de = devfs_register (dir, devname, 0,
 				    dev->major, dev->first_minor + part,
 				    S_IFBLK | S_IRUSR | S_IWUSR,
 				    dev->fops, NULL);
@@ -185,11 +186,8 @@
 #ifdef CONFIG_DEVFS_FS
 	int pos = 0;
 	devfs_handle_t dir, slave;
-	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
 	char dirname[64], symlink[16];
 
-	if (dev->flags & GENHD_FL_REMOVABLE)
-		devfs_flags |= DEVFS_FL_REMOVABLE;
 	if (dev->flags & GENHD_FL_DEVFS) {
 		dir = dev->de;
 		if (!dir)  /*  Aware driver wants to block disc management  */
@@ -209,7 +207,7 @@
 	sprintf(symlink, "discs/disc%d", dev->number);
 	devfs_mk_symlink(NULL, symlink, DEVFS_FL_DEFAULT,
 			  dirname + pos, &slave, NULL);
-	dev->disk_de = devfs_register(dir, "disc", devfs_flags,
+	dev->disk_de = devfs_register(dir, "disc", 0,
 			    dev->major, dev->first_minor,
 			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
 #endif
diff -urN linux-2.5.65-bk2/fs/partitions/nec98.c linux-2.5.65-bk3/fs/partitions/nec98.c
--- linux-2.5.65-bk2/fs/partitions/nec98.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/fs/partitions/nec98.c	Mon Mar 31 12:41:44 2003
@@ -0,0 +1,197 @@
+/*
+ *  NEC PC-9800 series partition supports
+ *
+ *  Copyright (C) 1999	Kyoto University Microcomputer Club
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/blk.h>
+#include <linux/hdreg.h>
+
+#include "check.h"
+#include "nec98.h"
+
+struct nec98_partition {
+	__u8	mid;		/* 0x80 - active */
+	__u8	sid;		/* 0x80 - bootable */
+	__u16	pad1;		/* dummy for padding */
+	__u8	ipl_sector;	/* IPL sector	*/
+	__u8	ipl_head;	/* IPL head	*/
+	__u16	ipl_cyl;	/* IPL cylinder	*/
+	__u8	sector;		/* starting sector	*/
+	__u8	head;		/* starting head	*/
+	__u16	cyl;		/* starting cylinder	*/
+	__u8	end_sector;	/* end sector	*/
+	__u8	end_head;	/* end head	*/
+	__u16	end_cyl;	/* end cylinder	*/
+	unsigned char name[16];
+} __attribute__((__packed__));
+
+#define NEC98_BSD_PARTITION_MID 0x14
+#define NEC98_BSD_PARTITION_SID 0x44
+#define MID_SID_16(mid, sid)	(((mid) & 0xFF) | (((sid) & 0xFF) << 8))
+#define NEC98_BSD_PARTITION_MID_SID	\
+	MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID)
+#define NEC98_VALID_PTABLE_ENTRY(P) \
+	(!(P)->pad1 && (P)->cyl <= (P)->end_cyl)
+
+extern int pc98_bios_param(struct block_device *bdev, int *ip);
+
+static inline int
+is_valid_nec98_partition_table(const struct nec98_partition *ptable,
+				__u8 nsectors, __u8 nheads)
+{
+	int i;
+	int valid = 0;
+
+	for (i = 0; i < 16; i++) {
+		if (!*(__u16 *)&ptable[i])
+			continue;	/* empty slot */
+		if (ptable[i].pad1	/* `pad1' contains junk */
+		    || ptable[i].ipl_sector	>= nsectors
+		    || ptable[i].sector		>= nsectors
+		    || ptable[i].end_sector	>= nsectors
+		    || ptable[i].ipl_head	>= nheads
+		    || ptable[i].head		>= nheads
+		    || ptable[i].end_head	>= nheads
+		    || ptable[i].cyl > ptable[i].end_cyl)
+			return 0;
+		valid = 1;	/* We have a valid partition.  */
+	}
+	/* If no valid PC-9800-style partitions found,
+	   the disk may have other type of partition table.  */
+	return valid;
+}
+
+#ifdef CONFIG_BSD_DISKLABEL
+extern void parse_bsd(struct parsed_partitions *state,
+			struct block_device *bdev,
+			u32 offset, u32 size, int origin, char *flavour,
+			int max_partitions);
+#endif
+
+int nec98_partition(struct parsed_partitions *state, struct block_device *bdev)
+{
+	unsigned int nr;
+	struct hd_geometry geo;
+	Sector sect;
+	const struct nec98_partition *part;
+	unsigned char *data;
+	int sector_size = bdev_hardsect_size(bdev);
+	int major = MAJOR(bdev->bd_dev);
+
+	if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)&geo) != 0) {
+		printk(" unsupported disk (major = %u)\n", major);
+		return 0;
+	}
+
+#ifdef NEC98_PARTITION_DEBUG
+	printk("ioctl_by_bdev head=%d sect=%d\n", geo.heads, geo.sectors);
+#endif
+	data = read_dev_sector(bdev, 0, &sect);
+	if (!data) {
+		if (warn_no_part)
+			printk(" unable to read partition table\n");
+		return -1;
+	}
+
+	/* magic(?) check */
+	if (*(__u16 *)(data + sector_size - 2) != NEC98_PTABLE_MAGIC) {
+		put_dev_sector(sect);
+		return 0;
+	}
+
+	put_dev_sector(sect);
+	data = read_dev_sector(bdev, 1, &sect);
+	if (!data) {
+		if (warn_no_part)
+			printk(" unable to read partition table\n");
+		return -1;
+	}
+
+	if (!is_valid_nec98_partition_table((struct nec98_partition *)data,
+					     geo.sectors, geo.heads)) {
+#ifdef NEC98_PARTITION_DEBUG
+		if (warn_no_part)
+			printk(" partition table consistency check failed"
+				" (not PC-9800 disk?)\n");
+#endif
+		put_dev_sector(sect);
+		return 0;
+	}
+
+	part = (const struct nec98_partition *)data;
+	for (nr = 0; nr < 16; nr++, part++) {
+		unsigned int start_sect, end_sect;
+
+		if (part->mid == 0 || part->sid == 0)
+			continue;
+
+		if (nr)
+			printk("     ");
+
+		{	/* Print partition name. Fdisk98 might put NUL
+			   characters in partition name... */
+
+			int j;
+			unsigned char *p;
+			unsigned char buf[sizeof (part->name) * 2 + 1];
+
+			for (p = buf, j = 0; j < sizeof (part->name); j++, p++)
+				if ((*p = part->name[j]) < ' ') {
+					*p++ = '^';
+					*p = part->name[j] + '@';
+				}
+
+			*p = 0;
+			printk(" <%s>", buf);
+		}
+		start_sect = (part->cyl * geo.heads + part->head) * geo.sectors
+			+ part->sector;
+		end_sect = (part->end_cyl + 1) * geo.heads * geo.sectors;
+		if (end_sect <= start_sect) {
+			printk(" (invalid partition info)\n");
+			continue;
+		}
+
+		put_partition(state, nr + 1, start_sect, end_sect - start_sect);
+#ifdef CONFIG_BSD_DISKLABEL
+		if ((*(__u16 *)&part->mid & 0x7F7F)
+		    == NEC98_BSD_PARTITION_MID_SID) {
+			printk("!");
+			/* NEC98_BSD_PARTITION_MID_SID is not valid SYSIND for
+			   IBM PC's MS-DOS partition table, so we simply pass
+			   it to bsd_disklabel_partition;
+			   it will just print `<bsd: ... >'. */
+			parse_bsd(state, bdev, start_sect,
+					end_sect - start_sect, nr + 1,
+					"bsd98", BSD_MAXPARTITIONS);
+		}
+#endif
+		{	/* Pretty size printing. */
+			/* XXX sector size? */
+			unsigned int psize = (end_sect - start_sect) / 2;
+			int unit_char = 'K';
+
+			if (psize > 99999) {
+				psize >>= 10;
+				unit_char = 'M';
+			}
+			printk(" %5d%cB (%5d-%5d)\n", 
+			       psize, unit_char, part->cyl, part->end_cyl);
+		}
+	}
+
+	put_dev_sector(sect);
+
+	return nr ? 1 : 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -urN linux-2.5.65-bk2/fs/partitions/nec98.h linux-2.5.65-bk3/fs/partitions/nec98.h
--- linux-2.5.65-bk2/fs/partitions/nec98.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/fs/partitions/nec98.h	Mon Mar 31 12:41:44 2003
@@ -0,0 +1,10 @@
+/*
+ *  NEC PC-9800 series partition supports
+ *
+ *  Copyright (C) 1998-2000	Kyoto University Microcomputer Club
+ */
+
+#define NEC98_PTABLE_MAGIC	0xAA55
+
+extern int nec98_partition(struct parsed_partitions *state,
+				struct block_device *bdev);
diff -urN linux-2.5.65-bk2/fs/proc/inode.c linux-2.5.65-bk3/fs/proc/inode.c
--- linux-2.5.65-bk2/fs/proc/inode.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/fs/proc/inode.c	Mon Mar 31 12:41:44 2003
@@ -13,7 +13,6 @@
 #include <linux/file.h>
 #include <linux/limits.h>
 #include <linux/init.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_aops.c linux-2.5.65-bk3/fs/xfs/linux/xfs_aops.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_aops.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_aops.c	Mon Mar 31 12:41:44 2003
@@ -31,11 +31,55 @@
  */
 
 #include <xfs.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
 #include <linux/mpage.h>
 
+STATIC void convert_page(struct inode *, struct page *,
+			page_buf_bmap_t *, void *, int, int);
 
+void
+linvfs_unwritten_done(
+	struct buffer_head	*bh,
+	int			uptodate)
+{
+	page_buf_t		*pb = (page_buf_t *)bh->b_private;
+
+	ASSERT(buffer_unwritten(bh));
+	bh->b_end_io = NULL;
+	clear_buffer_unwritten(bh);
+	if (!uptodate)
+		pagebuf_ioerror(pb, -EIO);
+	if (atomic_dec_and_test(&pb->pb_io_remaining) == 1)
+		pagebuf_iodone(pb, 1, 1);
+	end_buffer_async_write(bh, uptodate);
+}
+
+/*
+ * Issue transactions to convert a buffer range from unwritten
+ * to written extents.
+ */
+STATIC void
+xfs_unwritten_conv(
+	xfs_buf_t		*bp)
+{
+	bhv_desc_t		*bdp = XFS_BUF_FSPRIVATE(bp, bhv_desc_t *);
+	xfs_mount_t		*mp;
+	xfs_inode_t		*ip;
+
+	ip = XFS_BHVTOI(bdp);
+	mp = ip->i_mount;
+
+	if (XFS_TEST_ERROR(XFS_BUF_GETERROR(bp), mp,
+			   XFS_ERRTAG_STRATCMPL_IOERR,
+			   XFS_RANDOM_STRATCMPL_IOERR)) {
+		xfs_ioerror_alert(__FUNCTION__, mp, bp, XFS_BUF_ADDR(bp));
+	}
+
+	XFS_IOMAP_WRITE_UNWRITTEN(mp, &ip->i_iocore,
+				  XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp));
+	XFS_BUF_SET_FSPRIVATE(bp, NULL);
+	XFS_BUF_CLR_IODONE_FUNC(bp);
+	xfs_biodone(bp);
+}
 
 STATIC int
 map_blocks(
@@ -128,6 +172,58 @@
 }
 
 /*
+ * Look for a page at index which is unlocked and contains our
+ * unwritten extent flagged buffers at its head.  Returns page
+ * locked and with an extra reference count, and length of the
+ * unwritten extent component on this page that we can write,
+ * in units of filesystem blocks.
+ */
+STATIC struct page *
+probe_unwritten_page(
+	struct address_space	*mapping,
+	unsigned long		index,
+	page_buf_bmap_t		*mp,
+	page_buf_t		*pb,
+	unsigned long		max_offset,
+	unsigned long		*fsbs)
+{
+	struct page		*page;
+
+	page = find_trylock_page(mapping, index);
+	if (!page)
+		return 0;
+	if (PageWriteback(page))
+		goto out;
+
+	if (page->mapping && page_has_buffers(page)) {
+		struct buffer_head	*bh, *head;
+		unsigned long		p_offset = 0;
+
+		*fsbs = 0;
+		bh = head = page_buffers(page);
+		do {
+			if (!buffer_unwritten(bh))
+				break;
+			if (!match_offset_to_mapping(page, mp, p_offset))
+				break;
+			if (p_offset >= max_offset)
+				break;
+			set_buffer_unwritten_io(bh);
+			bh->b_private = pb;
+			p_offset += bh->b_size;
+			(*fsbs)++;
+		} while ((bh = bh->b_this_page) != head);
+
+		if (p_offset)
+			return page;
+	}
+
+out:
+	unlock_page(page);
+	return NULL;
+}
+
+/*
  * Look for a page at index which is unlocked and not mapped
  * yet - clustering for mmap write case.
  */
@@ -149,6 +245,7 @@
 	if (page->mapping && PageDirty(page)) {
 		if (page_has_buffers(page)) {
 			struct buffer_head	*bh, *head;
+
 			bh = head = page_buffers(page);
 			do {
 				if (buffer_mapped(bh) || !buffer_uptodate(bh))
@@ -189,6 +286,8 @@
 	 */
 	if (bh == head) {
 		tlast = inode->i_size >> PAGE_CACHE_SHIFT;
+		/* Prune this back to avoid pathological behavior */
+		tlast = min(tlast, startpage->index + 64);
 		for (tindex = startpage->index + 1; tindex < tlast; tindex++) {
 			len = probe_unmapped_page(mapping, tindex,
 							PAGE_CACHE_SIZE);
@@ -206,11 +305,12 @@
 }
 
 /*
- * Probe for a given page (index) in the inode & test if it is delayed.
- * Returns page locked and with an extra reference count.
+ * Probe for a given page (index) in the inode and test if it is delayed
+ * and without unwritten buffers.  Returns page locked and with an extra
+ * reference count.
  */
 STATIC struct page *
-probe_page(
+probe_delalloc_page(
 	struct inode		*inode,
 	unsigned long		index)
 {
@@ -224,12 +324,20 @@
 
 	if (page->mapping && page_has_buffers(page)) {
 		struct buffer_head	*bh, *head;
+		int			acceptable = 0;
 
 		bh = head = page_buffers(page);
 		do {
-			if (buffer_delay(bh))
-				return page;
+			if (buffer_unwritten(bh)) {
+				acceptable = 0;
+				break;
+			} else if (buffer_delay(bh)) {
+				acceptable = 1;
+			}
 		} while ((bh = bh->b_this_page) != head);
+
+		if (acceptable)
+			return page;
 	}
 
 out:
@@ -237,6 +345,103 @@
 	return NULL;
 }
 
+STATIC int
+map_unwritten(
+	struct inode		*inode,
+	struct page		*start_page,
+	struct buffer_head	*head,
+	struct buffer_head	*curr,
+	unsigned long		p_offset,
+	int			block_bits,
+	page_buf_bmap_t		*mp,
+	int			all_bh)
+{
+	struct buffer_head	*bh = curr;
+	page_buf_bmap_t		*tmp;
+	page_buf_t		*pb;
+	loff_t			offset, size;
+	unsigned long		nblocks = 0;
+
+	offset = start_page->index;
+	offset <<= PAGE_CACHE_SHIFT;
+	offset += p_offset;
+
+	pb = pagebuf_lookup(mp->pbm_target,
+			    mp->pbm_offset, mp->pbm_bsize, _PBF_LOCKABLE);
+	if (!pb)
+		return -ENOMEM;
+
+	/* Set the count to 1 initially, this will stop an I/O
+	 * completion callout which happens before we have started
+	 * all the I/O from calling pagebuf_iodone too early.
+	 */
+	atomic_set(&pb->pb_io_remaining, 1);
+
+	/* First map forwards in the page consecutive buffers
+	 * covering this unwritten extent
+	 */
+	do {
+		if (!buffer_unwritten(bh))
+			break;
+		tmp = match_offset_to_mapping(start_page, mp, p_offset);
+		if (!tmp)
+			break;
+		BUG_ON(!(tmp->pbm_flags & PBMF_UNWRITTEN));
+		map_buffer_at_offset(start_page, bh, p_offset, block_bits, mp);
+		set_buffer_unwritten_io(bh);
+		bh->b_private = pb;
+		p_offset += bh->b_size;
+		nblocks++;
+	} while ((bh = bh->b_this_page) != head);
+
+	atomic_add(nblocks, &pb->pb_io_remaining);
+
+	/* If we reached the end of the page, map forwards in any
+	 * following pages which are also covered by this extent.
+	 */
+	if (bh == head) {
+		struct address_space	*mapping = inode->i_mapping;
+		unsigned long		tindex, tlast, bs;
+		struct page		*page;
+
+		tlast = inode->i_size >> PAGE_CACHE_SHIFT;
+		tlast = min(tlast, start_page->index + pb->pb_page_count - 1);
+		for (tindex = start_page->index + 1; tindex < tlast; tindex++) {
+			page = probe_unwritten_page(mapping, tindex, mp, pb,
+					PAGE_CACHE_SIZE, &bs);
+			if (!page)
+				break;
+			nblocks += bs;
+			atomic_add(bs, &pb->pb_io_remaining);
+			convert_page(inode, page, mp, pb, 1, all_bh);
+		}
+
+		if ((tindex == tlast) && (inode->i_size & ~PAGE_CACHE_MASK)) {
+			page = probe_unwritten_page(mapping, tindex, mp, pb,
+					inode->i_size & ~PAGE_CACHE_MASK, &bs);
+			if (page) {
+				nblocks += bs;
+				atomic_add(bs, &pb->pb_io_remaining);
+				convert_page(inode, page,
+							mp, pb, 1, all_bh);
+			}
+		}
+	}
+
+	size = nblocks;		/* NB: using 64bit number here */
+	size <<= block_bits;	/* convert fsb's to byte range */
+
+	XFS_BUF_SET_SIZE(pb, size);
+	XFS_BUF_SET_OFFSET(pb, offset);
+	XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode)->v_fbhv);
+	XFS_BUF_SET_IODONE_FUNC(pb, xfs_unwritten_conv);
+
+	if (atomic_dec_and_test(&pb->pb_io_remaining) == 1)
+		pagebuf_iodone(pb, 1, 1);
+
+	return 0;
+}
+
 STATIC void
 submit_page(
 	struct page		*page,
@@ -255,6 +460,8 @@
 		for (i = 0; i < cnt; i++) {
 			bh = bh_arr[i];
 			mark_buffer_async_write(bh);
+			if (buffer_unwritten(bh))
+				set_buffer_unwritten_io(bh);
 			set_buffer_uptodate(bh);
 			clear_buffer_dirty(bh);
 		}
@@ -268,14 +475,15 @@
 /*
  * Allocate & map buffers for page given the extent map. Write it out.
  * except for the original page of a writepage, this is called on
- * delalloc pages only, for the original page it is possible that
- * the page has no mapping at all.
+ * delalloc/unwritten pages only, for the original page it is possible
+ * that the page has no mapping at all.
  */
 STATIC void
 convert_page(
 	struct inode		*inode,
 	struct page		*page,
 	page_buf_bmap_t		*maps,
+	void			*private,
 	int			startio,
 	int			all_bh)
 {
@@ -308,7 +516,23 @@
 			continue;
 		ASSERT(!(tmp->pbm_flags & PBMF_HOLE));
 		ASSERT(!(tmp->pbm_flags & PBMF_DELAY));
-		map_buffer_at_offset(page, bh, offset, bbits, tmp);
+
+		/* If this is a new unwritten extent buffer (i.e. one
+		 * that we haven't passed in private data for, we must
+		 * now map this buffer too.
+		 */
+		if (buffer_unwritten(bh) && !bh->b_end_io) {
+			ASSERT(tmp->pbm_flags & PBMF_UNWRITTEN);
+			map_unwritten(inode, page, head, bh,
+						offset, bbits, tmp, all_bh);
+		} else {
+			map_buffer_at_offset(page, bh, offset, bbits, tmp);
+			if (buffer_unwritten(bh)) {
+				set_buffer_unwritten_io(bh);
+				bh->b_private = private;
+				ASSERT(private);
+			}
+		}
 		if (startio && (offset < end)) {
 			bh_arr[index++] = bh;
 		} else {
@@ -341,10 +565,10 @@
 
 	tlast = (mp->pbm_offset + mp->pbm_bsize) >> PAGE_CACHE_SHIFT;
 	for (; tindex < tlast; tindex++) {
-		page = probe_page(inode, tindex);
+		page = probe_delalloc_page(inode, tindex);
 		if (!page)
 			break;
-		convert_page(inode, page, mp, startio, all_bh);
+		convert_page(inode, page, mp, NULL, startio, all_bh);
 	}
 }
 
@@ -368,7 +592,7 @@
  */
 
 STATIC int
-delalloc_convert(
+page_state_convert(
 	struct page	*page,
 	int		startio,
 	int		unmapped) /* also implies page uptodate */
@@ -411,10 +635,42 @@
 		}
 
 		/*
-		 * First case, allocate space for delalloc buffer head
-		 * we can return EAGAIN here in the release page case.
+		 * First case, map an unwritten extent and prepare for
+		 * extent state conversion transaction on completion.
 		 */
-		if (buffer_delay(bh)) {
+		if (buffer_unwritten(bh)) {
+			if (!mp) {
+				err = map_blocks(inode, offset, len, &map,
+						PBF_FILE_UNWRITTEN);
+				if (err) {
+					goto error;
+				}
+				mp = match_offset_to_mapping(page, &map,
+								p_offset);
+			}
+			if (mp) {
+				if (!bh->b_end_io) {
+					err = map_unwritten(inode, page,
+							head, bh, p_offset,
+							inode->i_blkbits,
+							mp, unmapped);
+					if (err) {
+						goto error;
+					}
+				}
+				if (startio) {
+					bh_arr[cnt++] = bh;
+				} else {
+					set_buffer_dirty(bh);
+					unlock_buffer(bh);
+				}
+				page_dirty = 0;
+			}
+		/*
+		 * Second case, allocate space for a delalloc buffer.
+		 * We can return EAGAIN here in the release page case.
+		 */
+		} else if (buffer_delay(bh)) {
 			if (!mp) {
 				err = map_blocks(inode, offset, len, &map,
 					PBF_FILE_ALLOCATE | flags);
@@ -574,6 +830,12 @@
 			bh_result->b_bdev = pbmap.pbm_target->pbr_bdev;
 			set_buffer_mapped(bh_result);
 		}
+		if (pbmap.pbm_flags & PBMF_UNWRITTEN) {
+			if (create)
+				set_buffer_mapped(bh_result);
+			set_buffer_unwritten(bh_result);
+			set_buffer_delay(bh_result);
+		}
 	}
 
 	/* If we previously allocated a block out beyond eof and
@@ -695,21 +957,23 @@
 	return mpage_readpages(mapping, pages, nr_pages, linvfs_get_block);
 }
 
-
 STATIC void
 count_page_state(
 	struct page		*page,
 	int			*delalloc,
-	int			*unmapped)
+	int			*unmapped,
+	int			*unwritten)
 {
 	struct buffer_head	*bh, *head;
 
-	*delalloc = *unmapped = 0;
+	*delalloc = *unmapped = *unwritten = 0;
 
 	bh = head = page_buffers(page);
 	do {
 		if (buffer_uptodate(bh) && !buffer_mapped(bh))
 			(*unmapped) = 1;
+		else if (buffer_unwritten(bh))
+			(*unwritten) = 1;
 		else if (buffer_delay(bh))
 			(*delalloc) = 1;
 	} while ((bh = bh->b_this_page) != head);
@@ -736,6 +1000,7 @@
  * is off, we need to fail the writepage and redirty the page.
  * We also need to set PF_NOIO ourselves.
  */
+
 STATIC int
 linvfs_writepage(
 	struct page		*page,
@@ -743,7 +1008,7 @@
 {
 	int			error;
 	int			need_trans;
-	int			delalloc, unmapped;
+	int			delalloc, unmapped, unwritten;
 	struct inode		*inode = page->mapping->host;
 
 	/*
@@ -751,15 +1016,16 @@
 	 *  1. There are delalloc buffers on the page
 	 *  2. The page is upto date and we have unmapped buffers
 	 *  3. The page is upto date and we have no buffers
+	 *  4. There are unwritten buffers on the page
 	 */
 	if (!page_has_buffers(page)) {
 		unmapped = 1;
 		need_trans = 1;
 	} else {
-		count_page_state(page, &delalloc, &unmapped);
+		count_page_state(page, &delalloc, &unmapped, &unwritten);
 		if (!PageUptodate(page))
 			unmapped = 0;
-		need_trans = delalloc + unmapped;
+		need_trans = delalloc + unmapped + unwritten;
 	}
 
 	/*
@@ -775,15 +1041,14 @@
 	 * Delay hooking up buffer heads until we have
 	 * made our go/no-go decision.
 	 */
-	if (!page_has_buffers(page)) {
+	if (!page_has_buffers(page))
 		create_empty_buffers(page, 1 << inode->i_blkbits, 0);
-	}
 
 	/*
-	 * Convert delalloc or unmapped space to real space and flush out
-	 * to disk.
+	 * Convert delayed allocate, unwritten or unmapped space
+	 * to real space and flush out to disk.
 	 */
-	error = delalloc_convert(page, 1, unmapped);
+	error = page_state_convert(page, 1, unmapped);
 	if (error == -EAGAIN)
 		goto out_fail;
 	if (unlikely(error < 0))
@@ -824,10 +1089,10 @@
 	struct page		*page,
 	int			gfp_mask)
 {
-	int			delalloc, unmapped;
+	int			delalloc, unmapped, unwritten;
 
-	count_page_state(page, &delalloc, &unmapped);
-	if (!delalloc)
+	count_page_state(page, &delalloc, &unmapped, &unwritten);
+	if (!delalloc && !unwritten)
 		goto free_buffers;
 
 	if (!(gfp_mask & __GFP_FS))
@@ -839,7 +1104,7 @@
 	 * Never need to allocate space here - we will always
 	 * come back to writepage in that case.
 	 */
-	if (delalloc_convert(page, 0, 0) == 0)
+	if (page_state_convert(page, 0, 0) == 0)
 		goto free_buffers;
 	return 0;
 
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_behavior.c linux-2.5.65-bk3/fs/xfs/linux/xfs_behavior.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_behavior.c	Mon Mar 17 13:44:46 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_behavior.c	Mon Mar 31 12:41:44 2003
@@ -121,9 +121,7 @@
 {
 	bhv_desc_t	*bdp;
 
-	BHV_READ_LOCK(bhp);
 	bdp = bhv_lookup(bhp, ops);
-	BHV_READ_UNLOCK(bhp);
 
 	return bdp;
 }
@@ -140,18 +138,12 @@
 {
 	bhv_desc_t	*curdesc;
 
-	BHV_READ_LOCK(bhp);
 	for (curdesc = bhp->bh_first;
 	     curdesc != NULL;
 	     curdesc = curdesc->bd_next) {
-
-		if (curdesc->bd_next == NULL) {
-			BHV_READ_UNLOCK(bhp);
+		if (curdesc->bd_next == NULL)
 			return curdesc;
-		}
 	}
-
-	BHV_READ_UNLOCK(bhp);
 	return NULL;
 }
 
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_behavior.h linux-2.5.65-bk3/fs/xfs/linux/xfs_behavior.h
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_behavior.h	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_behavior.h	Mon Mar 31 12:41:44 2003
@@ -152,13 +152,6 @@
 #define BHV_IDENTITY(bdp)	((bhv_identity_t *)(bdp)->bd_ops)
 #define BHV_POSITION(bdp)	(BHV_IDENTITY(bdp)->bi_position)
 
-
-#define BHV_READ_LOCK(bhp)
-#define BHV_READ_UNLOCK(bhp)
-#define BHV_NOT_READ_LOCKED(bhp)	1
-#define BHV_IS_WRITE_LOCKED(bhp)	1
-#define BHV_NOT_WRITE_LOCKED(bhp)	1
-
 extern void bhv_head_init(bhv_head_t *, char *);
 extern void bhv_head_destroy(bhv_head_t *);
 extern void bhv_head_reinit(bhv_head_t *);
@@ -180,8 +173,6 @@
 	(bdp)->bd_next = NULL;				\
  }
 
-#define BHV_DESC_INIT(so,A,B)	bhv_desc_init(&(so->so_bhv),so,A,B)
-
 /*
  * Remove a behavior descriptor from a behavior chain.
  */
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_file.c linux-2.5.65-bk3/fs/xfs/linux/xfs_file.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_file.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_file.c	Mon Mar 31 12:41:44 2003
@@ -32,8 +32,6 @@
 
 #include <xfs.h>
 #include <linux/dcache.h>
-#include <linux/pagemap.h>
-#include <linux/slab.h>
 #include <linux/mman.h> /* for PROT_WRITE */
 
 static struct vm_operations_struct linvfs_file_vm_ops;
@@ -227,8 +225,8 @@
 	int		eof = 0;
 	caddr_t		read_buf;
 	int		namelen, size = 0;
-	size_t		rlen = PAGE_CACHE_SIZE << 2;
-	xfs_off_t	start_offset;
+	size_t		rlen = PAGE_CACHE_SIZE;
+	xfs_off_t	start_offset, curr_offset;
 	xfs_dirent_t	*dbp = NULL;
 
 	vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
@@ -247,7 +245,7 @@
 	uio.uio_iov = &iov;
 	uio.uio_fmode = filp->f_mode;
 	uio.uio_segflg = UIO_SYSSPACE;
-	uio.uio_offset = filp->f_pos;
+	curr_offset = uio.uio_offset = filp->f_pos;
 
 	while (!eof) {
 		uio.uio_resid = iov.iov_len = rlen;
@@ -268,21 +266,22 @@
 			namelen = strlen(dbp->d_name);
 
 			if (filldir(dirent, dbp->d_name, namelen,
-					(loff_t) dbp->d_off,
+					(loff_t) curr_offset,
 					(ino_t) dbp->d_ino,
 					DT_UNKNOWN)) {
 				goto done;
 			}
 			size -= dbp->d_reclen;
+			curr_offset = (loff_t)dbp->d_off & 0x7fffffff;
 			dbp = nextdp(dbp);
 		}
 	}
 done:
 	if (!error) {
 		if (size == 0)
-			filp->f_pos = uio.uio_offset;
+			filp->f_pos = uio.uio_offset & 0x7fffffff;
 		else if (dbp)
-			filp->f_pos = dbp->d_off;
+			filp->f_pos = curr_offset;
 	}
 
 	kfree(read_buf);
@@ -308,7 +307,6 @@
 	vma->vm_ops = &linvfs_file_vm_ops;
 
 	VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
-	UPDATE_ATIME(ip);
 	return 0;
 }
 
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_fs_subr.c linux-2.5.65-bk3/fs/xfs/linux/xfs_fs_subr.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_fs_subr.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_fs_subr.c	Mon Mar 31 12:41:44 2003
@@ -33,48 +33,6 @@
 #include <xfs.h>
 
 /*
- * Implementation for VFS_DOUNMOUNT.
- */
-int
-fs_dounmount(
-	bhv_desc_t	*bdp,
-	int		flags,
-	vnode_t		*rootvp,
-	cred_t		*cr)
-{
-	struct vfs	*vfsp = bhvtovfs(bdp);
-	bhv_desc_t	*fbdp = vfsp->vfs_fbhv;
-	int		error;
-
-	/*
-	 * Wait for sync to finish and lock vfsp.  This also sets the
-	 * VFS_OFFLINE flag.  Once we do this we can give up reference
-	 * the root vnode which we hold to avoid the another unmount
-	 * ripping the vfs out from under us before we get to lock it.
-	 * The VFS_DOUNMOUNT calling convention is that the reference
-	 * on the rot vnode is released whether the call succeeds or
-	 * fails.
-	 */
-	if (rootvp)
-		VN_RELE(rootvp);
-
-	/*
-	 * Now invoke SYNC and UNMOUNT ops, using the PVFS versions is
-	 * OK since we already have a behavior lock as a result of
-	 * being in VFS_DOUNMOUNT.  It is necessary to do things this
-	 * way since using the VFS versions would cause us to get the
-	 * behavior lock twice which can cause deadlock as well as
-	 * making the coding of vfs relocation unnecessarilty difficult
-	 * by making relocations invoked by unmount occur in a different
-	 * environment than those invoked by mount-update.
-	 */
-	PVFS_SYNC(fbdp, SYNC_ATTR|SYNC_DELWRI, cr, error);
-	if (error == 0)
-		PVFS_UNMOUNT(fbdp, flags, cr, error);
-	return error;
-}
-
-/*
  * Stub for no-op vnode operations that return error status.
  */
 int
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_fs_subr.h linux-2.5.65-bk3/fs/xfs/linux/xfs_fs_subr.h
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_fs_subr.h	Mon Mar 17 13:44:19 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_fs_subr.h	Mon Mar 31 12:41:44 2003
@@ -42,7 +42,6 @@
 extern int	fs_nosys(void);
 extern int	fs_nodev(void);
 extern void	fs_noval(void);
-extern int	fs_dounmount(bhv_desc_t *, int, vnode_t *, struct cred *);
 extern void	fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
 extern void	fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
 extern int	fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int);
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_globals.c linux-2.5.65-bk3/fs/xfs/linux/xfs_globals.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_globals.c	Mon Mar 17 13:44:14 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_globals.c	Mon Mar 31 12:41:44 2003
@@ -46,7 +46,7 @@
  * Tunable XFS parameters.  xfs_params is required even when CONFIG_SYSCTL=n,
  * other XFS code uses these values.
  */
-xfs_param_t xfs_params = { 0, 1, 0, 0, 0 };
+xfs_param_t xfs_params = { 0, 1, 0, 0, 0, 3 };
 
 /*
  * Used to serialize atomicIncWithWrap.
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_ioctl.c linux-2.5.65-bk3/fs/xfs/linux/xfs_ioctl.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_ioctl.c	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_ioctl.c	Mon Mar 31 12:41:44 2003
@@ -130,7 +130,6 @@
 		int		lock_mode;
 
 		/* need to get access to the xfs_inode to read the generation */
-		VN_BHV_READ_LOCK(&(vp)->v_bh);
 		bhv = VNODE_TO_FIRST_BHV(vp);
 		ASSERT(bhv);
 		ip = XFS_BHVTOI(bhv);
@@ -145,7 +144,6 @@
 		handle.ha_fid.xfs_fid_ino = ip->i_ino;
 
 		xfs_iunlock_map_shared(ip, lock_mode);
-		VN_BHV_READ_UNLOCK(&(vp)->v_bh);
 
 		hsize = XFS_HSIZE(handle);
 	}
@@ -585,6 +583,14 @@
 	case XFS_IOC_FREESP64:
 	case XFS_IOC_RESVSP64:
 	case XFS_IOC_UNRESVSP64:
+		/* 
+		 * Only allow the sys admin to reserve space unless
+		 * unwritten extents are enabled.
+		 */
+		if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) &&
+		    !capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
 		return xfs_ioc_space(bdp, vp, filp, cmd, arg);
 
 	case XFS_IOC_DIOINFO: {
@@ -685,11 +691,7 @@
 		xfs_fsop_resblks_t inout;
 		__uint64_t	   in;
 
-		/* Only allow the sys admin to reserve space unless
-		 * unwritten extents are enabled.
-		 */
-		if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) &&
-		    !capable(CAP_SYS_ADMIN))
+		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
 		if (copy_from_user(&inout, (char *)arg, sizeof(inout)))
@@ -810,9 +812,6 @@
 	int			attr_flags = 0;
 	int			error;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -XFS_ERROR(EPERM);
-
 	if (filp->f_flags & O_RDONLY)
 		return -XFS_ERROR(EBADF);
 
@@ -847,10 +846,7 @@
 	/* done = 1 if there are more stats to get and if bulkstat */
 	/* should be called again (unused here, but used in dmapi) */
 
-	/* Do not allow space reservation if this is not the admin and
-	 * unwritten extents are turned off.
-	 */
-	if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) && !capable(CAP_SYS_ADMIN))
+	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
 	if (XFS_FORCED_SHUTDOWN(mp))
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_iomap.c linux-2.5.65-bk3/fs/xfs/linux/xfs_iomap.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_iomap.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_iomap.c	Mon Mar 31 12:41:45 2003
@@ -530,6 +530,7 @@
 	xfs_trans_t	*tp;
 	int		i, nimaps, committed;
 	int		error = 0;
+	int		nres;
 
 	*retmap = 0;
 
@@ -562,9 +563,19 @@
 		nimaps = 0;
 		while (nimaps == 0) {
 			tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
-			error = xfs_trans_reserve(tp, 0, XFS_WRITE_LOG_RES(mp),
+			nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
+			error = xfs_trans_reserve(tp, nres,
+					XFS_WRITE_LOG_RES(mp),
 					0, XFS_TRANS_PERM_LOG_RES,
 					XFS_WRITE_LOG_COUNT);
+
+			if (error == ENOSPC) {
+				error = xfs_trans_reserve(tp, 0,
+						XFS_WRITE_LOG_RES(mp),
+						0,
+						XFS_TRANS_PERM_LOG_RES,
+						XFS_WRITE_LOG_COUNT);
+			}
 			if (error) {
 				xfs_trans_cancel(tp, 0);
 				return XFS_ERROR(error);
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_iops.c linux-2.5.65-bk3/fs/xfs/linux/xfs_iops.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_iops.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_iops.c	Mon Mar 31 12:41:45 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -45,7 +45,7 @@
 	vattr_t		va;
 	int		error;
 
-	va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE;
+	va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
 	VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error);
 	ip->i_nlink = va.va_nlink;
 	ip->i_size = va.va_size;
@@ -154,20 +154,18 @@
 	return linvfs_mknod(dir, dentry, mode|S_IFDIR, 0);
 }
 
-
 STATIC struct dentry *
 linvfs_lookup(
 	struct inode	*dir,
 	struct dentry	*dentry)
 {
-	int		error;
-	vnode_t		*vp, *cvp;
 	struct inode	*ip = NULL;
+	vnode_t		*vp, *cvp = NULL;
+	int		error;
 
 	if (dentry->d_name.len >= MAXNAMELEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	cvp = NULL;
 	vp = LINVFS_GET_VP(dir);
 	VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error);
 	if (!error) {
@@ -189,10 +187,10 @@
 	struct inode	*dir,
 	struct dentry	*dentry)
 {
-	int		error;
-	vnode_t		*tdvp;	/* Target directory for new name/link */
-	vnode_t		*vp;	/* vp of name being linked */
 	struct inode	*ip;	/* inode of guy being linked to */
+	vnode_t		*tdvp;	/* target directory for new name/link */
+	vnode_t		*vp;	/* vp of name being linked */
+	int		error;
 
 	ip = old_dentry->d_inode;	/* inode being linked to */
 	if (S_ISDIR(ip->i_mode))
@@ -201,7 +199,6 @@
 	tdvp = LINVFS_GET_VP(dir);
 	vp = LINVFS_GET_VP(ip);
 
-	error = 0;
 	VOP_LINK(tdvp, vp, dentry, NULL, error);
 	if (!error) {
 		VMODIFY(tdvp);
@@ -218,16 +215,14 @@
 	struct inode	*dir,
 	struct dentry	*dentry)
 {
-	int		error = 0;
 	struct inode	*inode;
 	vnode_t		*dvp;	/* directory containing name to remove */
+	int		error;
 
 	inode = dentry->d_inode;
-
 	dvp = LINVFS_GET_VP(dir);
 
 	VOP_REMOVE(dvp, dentry, NULL, error);
-
 	if (!error) {
 		validate_fields(dir);	/* For size only */
 		validate_fields(inode);
@@ -244,13 +239,14 @@
 	struct dentry	*dentry,
 	const char	*symname)
 {
-	int		error;
+	struct inode	*ip;
+	vattr_t		va;
 	vnode_t		*dvp;	/* directory containing name to remove */
 	vnode_t		*cvp;	/* used to lookup symlink to put in dentry */
-	vattr_t		va;
-	struct inode	*ip = NULL;
+	int		error;
 
 	dvp = LINVFS_GET_VP(dir);
+	cvp = NULL;
 
 	memset(&va, 0, sizeof(va));
 	va.va_type = VLNK;
@@ -259,20 +255,14 @@
 
 	error = 0;
 	VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error);
-	if (!error) {
-		ASSERT(cvp);
+	if (!error && cvp) {
 		ASSERT(cvp->v_type == VLNK);
 		ip = LINVFS_GET_IP(cvp);
-		if (!ip) {
-			error = ENOMEM;
-			VN_RELE(cvp);
-		} else {
-			d_instantiate(dentry, ip);
-			validate_fields(dir);
-			validate_fields(ip); /* size needs update */
-			mark_inode_dirty_sync(ip);
-			mark_inode_dirty_sync(dir);
-		}
+		d_instantiate(dentry, ip);
+		validate_fields(dir);
+		validate_fields(ip); /* size needs update */
+		mark_inode_dirty_sync(ip);
+		mark_inode_dirty_sync(dir);
 	}
 	return -error;
 }
@@ -303,23 +293,20 @@
 	struct inode	*ndir,
 	struct dentry	*ndentry)
 {
-	int		error;
+	struct inode	*new_inode = ndentry->d_inode;
 	vnode_t		*fvp;	/* from directory */
 	vnode_t		*tvp;	/* target directory */
-	struct inode	*new_inode = NULL;
+	int		error;
 
 	fvp = LINVFS_GET_VP(odir);
 	tvp = LINVFS_GET_VP(ndir);
 
-	new_inode = ndentry->d_inode;
-
 	VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error);
 	if (error)
 		return -error;
 
-	if (new_inode) {
+	if (new_inode)
 		validate_fields(new_inode);
-	}
 
 	validate_fields(odir);
 	if (ndir != odir)
@@ -334,13 +321,11 @@
 	char		*buf,
 	int		size)
 {
-	vnode_t		*vp;
+	vnode_t		*vp = LINVFS_GET_VP(dentry->d_inode);
 	uio_t		uio;
 	iovec_t		iov;
 	int		error;
 
-	vp = LINVFS_GET_VP(dentry->d_inode);
-
 	iov.iov_base = buf;
 	iov.iov_len = size;
 
@@ -348,6 +333,7 @@
 	uio.uio_offset = 0;
 	uio.uio_segflg = UIO_USERSPACE;
 	uio.uio_resid = size;
+	uio.uio_iovcnt = 1;
 
 	VOP_READLINK(vp, &uio, NULL, error);
 	if (error)
@@ -395,6 +381,7 @@
 	uio->uio_segflg = UIO_SYSSPACE;
 	uio->uio_resid = MAXNAMELEN;
 	uio->uio_fmode = 0;
+	uio->uio_iovcnt = 1;
 
 	VOP_READLINK(vp, uio, NULL, error);
 	if (error) {
@@ -425,11 +412,6 @@
 	return -error;
 }
 
-/* Brute force approach for now - copy data into linux inode
- * from the results of a getattr. This gets called out of things
- * like stat.
- */
-
 STATIC int
 linvfs_getattr(
 	struct vfsmount	*mnt,
@@ -440,9 +422,8 @@
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 	int		error = 0;
 
-	if (unlikely(vp->v_flag & VMODIFIED)) {
+	if (unlikely(vp->v_flag & VMODIFIED))
 		error = vn_revalidate(vp);
-	}
 	if (!error)
 		generic_fillattr(inode, stat);
 	return 0;
@@ -454,11 +435,11 @@
 	struct iattr	*attr)
 {
 	struct inode	*inode = dentry->d_inode;
+	unsigned int	ia_valid = attr->ia_valid;
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 	vattr_t		vattr;
-	unsigned int	ia_valid = attr->ia_valid;
-	int		error;
 	int		flags = 0;
+	int		error;
 
 	memset(&vattr, 0, sizeof(vattr_t));
 	if (ia_valid & ATTR_UID) {
@@ -511,7 +492,7 @@
 
 STATIC void
 linvfs_truncate(
-	struct inode		*inode)
+	struct inode	*inode)
 {
 	block_truncate_page(inode->i_mapping, inode->i_size, linvfs_get_block);
 }
@@ -579,11 +560,11 @@
 	size_t		size,
 	int		flags)
 {
-	int		error;
-	int		xflags = 0;
-	char		*p = (char *)name;
 	struct inode	*inode = dentry->d_inode;
 	vnode_t		*vp = LINVFS_GET_VP(inode);
+	char		*p = (char *)name;
+	int		xflags = 0;
+	int		error;
 
 	if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
 			xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
@@ -592,20 +573,16 @@
 			 return error;
 		error = -EOPNOTSUPP;
 		p += xfs_namespaces[SYSTEM_NAMES].namelen;
-		if (strcmp(p, POSIXACL_ACCESS) == 0) {
+		if (strcmp(p, POSIXACL_ACCESS) == 0)
 			error = xfs_acl_vset(vp, (void *) data, size,
 						_ACL_TYPE_ACCESS);
-		}
-		else if (strcmp(p, POSIXACL_DEFAULT) == 0) {
+		else if (strcmp(p, POSIXACL_DEFAULT) == 0)
 			error = xfs_acl_vset(vp, (void *) data, size,
 						_ACL_TYPE_DEFAULT);
-		}
-		else if (strcmp(p, POSIXCAP) == 0) {
+		else if (strcmp(p, POSIXCAP) == 0)
 			error = xfs_cap_vset(vp, (void *) data, size);
-		}
-		if (!error) {
+		if (!error)
 			error = vn_revalidate(vp);
-		}
 		return error;
 	}
 
@@ -642,25 +619,22 @@
 	void		*data,
 	size_t		size)
 {
-	ssize_t		error;
-	int		xflags = 0;
-	char		*p = (char *)name;
 	struct inode	*inode = dentry->d_inode;
 	vnode_t		*vp = LINVFS_GET_VP(inode);
+	char		*p = (char *)name;
+	int		xflags = 0;
+	ssize_t		error;
 
 	if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
 			xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
 		error = -EOPNOTSUPP;
 		p += xfs_namespaces[SYSTEM_NAMES].namelen;
-		if (strcmp(p, POSIXACL_ACCESS) == 0) {
+		if (strcmp(p, POSIXACL_ACCESS) == 0)
 			error = xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
-		}
-		else if (strcmp(p, POSIXACL_DEFAULT) == 0) {
+		else if (strcmp(p, POSIXACL_DEFAULT) == 0)
 			error = xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
-		}
-		else if (strcmp(p, POSIXCAP) == 0) {
+		else if (strcmp(p, POSIXCAP) == 0)
 			error = xfs_cap_vget(vp, data, size);
-		}
 		return error;
 	}
 
@@ -699,15 +673,13 @@
 	char			*data,
 	size_t			size)
 {
-	ssize_t			error;
-	int			result = 0;
-	int			xflags = ATTR_KERNAMELS;
-	char			*k = data;
 	attrlist_cursor_kern_t	cursor;
 	xattr_namespace_t	*sys;
-	vnode_t			*vp;
-
-	vp = LINVFS_GET_VP(dentry->d_inode);
+	vnode_t			*vp = LINVFS_GET_VP(dentry->d_inode);
+	char			*k = data;
+	int			xflags = ATTR_KERNAMELS;
+	int			result = 0;
+	ssize_t			error;
 
 	if (!size)
 		xflags |= ATTR_KERNOVAL;
@@ -743,11 +715,11 @@
 	struct dentry	*dentry,
 	const char	*name)
 {
-	int		error;
-	int		xflags = 0;
-	char		*p = (char *)name;
 	struct inode	*inode = dentry->d_inode;
 	vnode_t		*vp = LINVFS_GET_VP(inode);
+	char		*p = (char *)name;
+	int		xflags = 0;
+	int		error;
 
 	if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
 			xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
@@ -786,8 +758,8 @@
 struct inode_operations linvfs_file_inode_operations =
 {
 	.permission		= linvfs_permission,
-	.getattr		= linvfs_getattr,
 	.truncate		= linvfs_truncate,
+	.getattr		= linvfs_getattr,
 	.setattr		= linvfs_setattr,
 	.setxattr		= linvfs_setxattr,
 	.getxattr		= linvfs_getxattr,
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_iops.h linux-2.5.65-bk3/fs/xfs/linux/xfs_iops.h
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_iops.h	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_iops.h	Mon Mar 31 12:41:45 2003
@@ -66,5 +66,6 @@
 extern struct address_space_operations linvfs_aops;
 
 extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
+extern void linvfs_unwritten_done(struct buffer_head *, int);
 
 #endif /* __XFS_IOPS_H__ */
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_linux.h linux-2.5.65-bk3/fs/xfs/linux/xfs_linux.h
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_linux.h	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_linux.h	Mon Mar 31 12:41:45 2003
@@ -69,22 +69,25 @@
 #define STATIC static
 #endif
 
+/*
+ * State flag for unwritten extent buffers.
+ *
+ * We need to be able to distinguish between these and delayed
+ * allocate buffers within XFS.  The generic IO path code does
+ * not need to distinguish - we use the BH_Delay flag for both
+ * delalloc and these ondisk-uninitialised buffers.
+ */
+BUFFER_FNS(PrivateStart, unwritten);
+static inline void set_buffer_unwritten_io(struct buffer_head *bh)
+{
+	bh->b_end_io = linvfs_unwritten_done;
+}
+
 #define restricted_chown	xfs_params.restrict_chown
 #define irix_sgid_inherit	xfs_params.sgid_inherit
 #define irix_symlink_mode	xfs_params.symlink_mode
 #define xfs_panic_mask		xfs_params.panic_mask
-
-typedef struct xfs_dirent {		/* data from readdir() */
-	xfs_ino_t	d_ino;		/* inode number of entry */
-	xfs_off_t	d_off;		/* offset of disk directory entry */
-	unsigned short	d_reclen;	/* length of this record */
-	char		d_name[1];	/* name of file */
-} xfs_dirent_t;
-
-#define DIRENTBASESIZE		(((xfs_dirent_t *)0)->d_name - (char *)0)
-#define DIRENTSIZE(namelen)	\
-	((DIRENTBASESIZE + (namelen) + \
-		sizeof(xfs_off_t)) & ~(sizeof(xfs_off_t) - 1))
+#define xfs_error_level		xfs_params.error_level
 
 #define NBPP		PAGE_SIZE
 #define DPPSHFT		(PAGE_SHIFT - 9)
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_lrw.c linux-2.5.65-bk3/fs/xfs/linux/xfs_lrw.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_lrw.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_lrw.c	Mon Mar 31 12:41:45 2003
@@ -35,7 +35,6 @@
  */
 
 #include <xfs.h>
-#include <linux/pagemap.h>
 #include <linux/capability.h>
 
 
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_lrw.h linux-2.5.65-bk3/fs/xfs/linux/xfs_lrw.h
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_lrw.h	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_lrw.h	Mon Mar 31 12:41:45 2003
@@ -47,36 +47,36 @@
  */
 #define XFS_MAX_RW_NBMAPS	4
 
-extern int xfs_bmap (struct bhv_desc *, xfs_off_t, ssize_t, int,
+extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
 			struct page_buf_bmap_s *, int *);
-extern int xfsbdstrat (struct xfs_mount *, struct page_buf_s *);
-extern int xfs_bdstrat_cb (struct page_buf_s *);
+extern int xfsbdstrat(struct xfs_mount *, struct page_buf_s *);
+extern int xfs_bdstrat_cb(struct page_buf_s *);
 
-extern int xfs_zero_eof (struct vnode *, struct xfs_iocore *, xfs_off_t,
+extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
 				xfs_fsize_t, xfs_fsize_t);
-extern ssize_t xfs_read (struct bhv_desc *, struct file *,
+extern ssize_t xfs_read(struct bhv_desc *, struct file *,
 				const struct iovec *, unsigned long,
 				loff_t *, struct cred *);
-extern ssize_t xfs_write (struct bhv_desc *, struct file *,
+extern ssize_t xfs_write(struct bhv_desc *, struct file *,
 				const struct iovec *, unsigned long,
 				loff_t *, struct cred *);
-extern ssize_t xfs_sendfile (struct bhv_desc *, struct file *,
+extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
 				loff_t *, size_t, read_actor_t,
 				void *, struct cred *);
 
-extern int xfs_iomap (struct xfs_iocore *, xfs_off_t, ssize_t, int,
+extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
 				struct page_buf_bmap_s *, int *);
-extern int xfs_iomap_write_direct (struct xfs_inode *, loff_t, size_t,
+extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t,
 				int, struct xfs_bmbt_irec *, int *, int);
-extern int xfs_iomap_write_delay (struct xfs_inode *, loff_t, size_t,
+extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t,
 				int, struct xfs_bmbt_irec *, int *);
-extern int xfs_iomap_write_allocate (struct xfs_inode *,
+extern int xfs_iomap_write_allocate(struct xfs_inode *,
 				struct xfs_bmbt_irec *, int *);
-extern int xfs_iomap_write_unwritten (struct xfs_inode *, loff_t, size_t);
+extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t);
 
-extern int xfs_dev_is_read_only (struct xfs_mount *, char *);
+extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
 
-extern void XFS_log_write_unmount_ro (struct bhv_desc *);
+extern void XFS_log_write_unmount_ro(struct bhv_desc *);
 
 #define XFS_FSB_TO_DB_IO(io,fsb) \
 		(((io)->io_flags & XFS_IOCORE_RT) ? \
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_super.c linux-2.5.65-bk3/fs/xfs/linux/xfs_super.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_super.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_super.c	Mon Mar 31 12:41:45 2003
@@ -766,7 +766,9 @@
 	vfs_t			*vfsp = LINVFS_GET_VFS(sb);
 	int			error;
 
-	VFS_DOUNMOUNT(vfsp, 0, NULL, NULL, error);
+	VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error);
+	if (error == 0)
+		VFS_UNMOUNT(vfsp, 0, NULL, error);
 	if (error) {
 		printk("XFS unmount got error %d\n", error);
 		printk("%s: vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp);
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_sysctl.c linux-2.5.65-bk3/fs/xfs/linux/xfs_sysctl.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_sysctl.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_sysctl.c	Mon Mar 31 12:41:45 2003
@@ -35,8 +35,8 @@
 #include <linux/proc_fs.h>
 
 
-STATIC ulong xfs_min[XFS_PARAM] = { 0, 0, 0, 0, 0 };
-STATIC ulong xfs_max[XFS_PARAM] = { 1, 1, 1, 1, 127 };
+STATIC ulong xfs_min[XFS_PARAM] = { 0, 0, 0, 0, 0,   0 };
+STATIC ulong xfs_max[XFS_PARAM] = { 1, 1, 1, 1, 127, 3 };
 
 static struct ctl_table_header *xfs_table_header;
 
@@ -69,23 +69,27 @@
 STATIC ctl_table xfs_table[] = {
 	{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear,
 	sizeof(ulong), 0644, NULL, &xfs_stats_clear_proc_handler,
-	&sysctl_intvec, NULL, &xfs_min[2], &xfs_max[2]},
+	&sysctl_intvec, NULL, &xfs_min[0], &xfs_max[0]},
 
 	{XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[3], &xfs_max[3]},
+	&sysctl_intvec, NULL, &xfs_min[1], &xfs_max[1]},
 
 	{XFS_SGID_INHERIT, "irix_sgid_inherit", &xfs_params.sgid_inherit,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[4], &xfs_max[4]},
+	&sysctl_intvec, NULL, &xfs_min[2], &xfs_max[2]},
 
 	{XFS_SYMLINK_MODE, "irix_symlink_mode", &xfs_params.symlink_mode,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[5], &xfs_max[5]},
+	&sysctl_intvec, NULL, &xfs_min[3], &xfs_max[3]},
 
 	{XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[6], &xfs_max[6]},
+	&sysctl_intvec, NULL, &xfs_min[4], &xfs_max[4]},
+
+	{XFS_ERRLEVEL, "error_level", &xfs_params.error_level,
+	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
+	&sysctl_intvec, NULL, &xfs_min[5], &xfs_max[5]},
 
 	{0}
 };
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_sysctl.h linux-2.5.65-bk3/fs/xfs/linux/xfs_sysctl.h
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_sysctl.h	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_sysctl.h	Mon Mar 31 12:41:45 2003
@@ -48,14 +48,31 @@
 				/*  not a member of the parent dir GID.  */
 	ulong	symlink_mode;	/* Symlink creat mode affected by umask. */
 	ulong	panic_mask;	/* bitmask to specify panics on errors.  */
+	ulong	error_level;	/* Degree of reporting for internal probs*/
 } xfs_param_t;
 
+/*
+ * xfs_error_level:
+ *
+ * How much error reporting will be done when internal problems are
+ * encountered.  These problems normally return an EFSCORRUPTED to their
+ * caller, with no other information reported.
+ *
+ * 0	No error reports
+ * 1	Report EFSCORRUPTED errors that will cause a filesystem shutdown
+ * 5	Report all EFSCORRUPTED errors (all of the above errors, plus any
+ *	additional errors that are known to not cause shutdowns)
+ *
+ * xfs_panic_mask bit 0x8 turns the error reports into panics
+ */
+
 enum {
 	XFS_STATS_CLEAR = 1,
 	XFS_RESTRICT_CHOWN = 2,
 	XFS_SGID_INHERIT = 3,
 	XFS_SYMLINK_MODE = 4,
 	XFS_PANIC_MASK = 5,
+	XFS_ERRLEVEL = 6,
 };
 
 extern xfs_param_t	xfs_params;
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_vfs.h linux-2.5.65-bk3/fs/xfs/linux/xfs_vfs.h
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_vfs.h	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_vfs.h	Mon Mar 31 12:41:45 2003
@@ -75,9 +75,6 @@
 	int	(*vfs_mount)(struct vfs *, struct xfs_mount_args *,
 					struct cred *);
 					/* mount file system */
-	int	(*vfs_dounmount)(bhv_desc_t *, int, struct vnode *,
-				 struct cred *);
-					/* preparation and unmount */
 	int	(*vfs_unmount)(bhv_desc_t *, int, struct cred *);
 					/* unmount file system */
 	int	(*vfs_root)(bhv_desc_t *, struct vnode **);
@@ -98,48 +95,30 @@
 					int, char *, int);
 } vfsops_t;
 
-#define VFS_DOUNMOUNT(vfsp,f,vp,cr, rv) \
-{	\
-	BHV_READ_LOCK(&(vfsp)->vfs_bh); \
-	rv = (*(VFS_FOPS(vfsp)->vfs_dounmount))((vfsp)->vfs_fbhv, f, vp, cr);	\
-	BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \
-}
 #define VFS_UNMOUNT(vfsp,f,cr, rv)	\
 {	\
-	BHV_READ_LOCK(&(vfsp)->vfs_bh); \
-	rv = (*(VFS_FOPS(vfsp)->vfs_unmount))((vfsp)->vfs_fbhv, f, cr);		\
-	BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \
+	rv = (*(VFS_FOPS(vfsp)->vfs_unmount))((vfsp)->vfs_fbhv, f, cr);	\
 }
 #define VFS_ROOT(vfsp, vpp, rv)		\
 {	\
-	BHV_READ_LOCK(&(vfsp)->vfs_bh); \
 	rv = (*(VFS_FOPS(vfsp)->vfs_root))((vfsp)->vfs_fbhv, vpp);	\
-	BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \
 }
 #define VFS_STATVFS(vfsp, sp, vp, rv)	\
 {	\
-	BHV_READ_LOCK(&(vfsp)->vfs_bh); \
-	rv = (*(VFS_FOPS(vfsp)->vfs_statvfs))((vfsp)->vfs_fbhv, sp, vp);	\
-	BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \
+	rv = (*(VFS_FOPS(vfsp)->vfs_statvfs))((vfsp)->vfs_fbhv, sp, vp);\
 }
 #define VFS_SYNC(vfsp, flag, cr, rv) \
 {	\
-	BHV_READ_LOCK(&(vfsp)->vfs_bh); \
 	rv = (*(VFS_FOPS(vfsp)->vfs_sync))((vfsp)->vfs_fbhv, flag, cr); \
-	BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \
 }
 #define VFS_VGET(vfsp, vpp, fidp, rv) \
 {	\
-	BHV_READ_LOCK(&(vfsp)->vfs_bh); \
 	rv = (*(VFS_FOPS(vfsp)->vfs_vget))((vfsp)->vfs_fbhv, vpp, fidp);  \
-	BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \
 }
 
 #define VFS_INIT_VNODE(vfsp, vp, bhv, unlock) \
 {	\
-	BHV_READ_LOCK(&(vfsp)->vfs_bh); \
 	(*(VFS_FOPS(vfsp)->vfs_init_vnode))((vfsp)->vfs_fbhv, vp, bhv, unlock);\
-	BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \
 }
 
 /* No behavior lock here */
@@ -148,9 +127,7 @@
 
 #define VFS_DMAPI_FSYS_VECTOR(vfsp, df, rv) \
 {	\
-	BHV_READ_LOCK(&(vfsp)->vfs_bh); \
 	rv = (*(VFS_FOPS(vfsp)->vfs_dmapi_fsys_vector))((vfsp)->vfs_fbhv, df);	      \
-	BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \
 }
 
 
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_vnode.c linux-2.5.65-bk3/fs/xfs/linux/xfs_vnode.c
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_vnode.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_vnode.c	Mon Mar 31 12:41:45 2003
@@ -137,6 +137,7 @@
 	struct vnode	*vp = LINVFS_GET_VP(inode);
 
 	XFS_STATS_INC(xfsstats.vn_active);
+	XFS_STATS_INC(xfsstats.vn_alloc);
 
 	vp->v_flag = VMODIFIED;
 	spinlock_init(&vp->v_lock, "v_lock");
diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_vnode.h linux-2.5.65-bk3/fs/xfs/linux/xfs_vnode.h
--- linux-2.5.65-bk2/fs/xfs/linux/xfs_vnode.h	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/fs/xfs/linux/xfs_vnode.h	Mon Mar 31 12:41:45 2003
@@ -98,11 +98,6 @@
 
 #define VNODE_TO_FIRST_BHV(vp)		(BHV_HEAD_FIRST(&(vp)->v_bh))
 #define VN_BHV_HEAD(vp)			((bhv_head_t *)(&((vp)->v_bh)))
-#define VN_BHV_READ_LOCK(bhp)		BHV_READ_LOCK(bhp)
-#define VN_BHV_READ_UNLOCK(bhp)		BHV_READ_UNLOCK(bhp)
-#define VN_BHV_WRITE_LOCK(bhp)		BHV_WRITE_LOCK(bhp)
-#define VN_BHV_NOT_READ_LOCKED(bhp)	BHV_NOT_READ_LOCKED(bhp)
-#define VN_BHV_NOT_WRITE_LOCKED(bhp)	BHV_NOT_WRITE_LOCKED(bhp)
 #define vn_bhv_head_init(bhp,name)	bhv_head_init(bhp,name)
 #define vn_bhv_remove(bhp,bdp)		bhv_remove(bhp,bdp)
 #define vn_bhv_lookup(bhp,ops)		bhv_lookup(bhp,ops)
@@ -274,187 +269,130 @@
 
 #define VOP_READ(vp,file,iov,segs,offset,cr,rv)				\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,cr); \
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_WRITE(vp,file,iov,segs,offset,cr,rv)			\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,cr);\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_SENDFILE(vp,f,of,cnt,act,targ,cr,rv)			\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,of,cnt,act,targ,cr);\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_BMAP(vp,of,sz,rw,b,n,rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n);		\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_OPEN(vp, cr, rv)						\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr);			\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_GETATTR(vp, vap, f, cr, rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr);		\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_SETATTR(vp, vap, f, cr, rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr);		\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_ACCESS(vp, mode, cr, rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr);		\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv)				\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr);	\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_CREATE(dvp,d,vap,vpp,cr,rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(dvp)->v_bh);					\
 	rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr);	\
-	VN_BHV_READ_UNLOCK(&(dvp)->v_bh);				\
 }
 #define VOP_REMOVE(dvp,d,cr,rv)						\
 {									\
-	VN_BHV_READ_LOCK(&(dvp)->v_bh);					\
 	rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr);		\
-	VN_BHV_READ_UNLOCK(&(dvp)->v_bh);				\
 }
 #define VOP_LINK(tdvp,fvp,d,cr,rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(tdvp)->v_bh);				\
 	rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr);		\
-	VN_BHV_READ_UNLOCK(&(tdvp)->v_bh);				\
 }
 #define VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv)				\
 {									\
-	VN_BHV_READ_LOCK(&(fvp)->v_bh);					\
 	rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr);	\
-	VN_BHV_READ_UNLOCK(&(fvp)->v_bh);				\
 }
 #define VOP_MKDIR(dp,d,vap,vpp,cr,rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(dp)->v_bh);					\
 	rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr);		\
-	VN_BHV_READ_UNLOCK(&(dp)->v_bh);				\
 }
 #define	VOP_RMDIR(dp,d,cr,rv)	 					\
 {									\
-	VN_BHV_READ_LOCK(&(dp)->v_bh);					\
 	rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr);			\
-	VN_BHV_READ_UNLOCK(&(dp)->v_bh);				\
 }
 #define VOP_READDIR(vp,uiop,cr,eofp,rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp);		\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv)				\
 {									\
-	VN_BHV_READ_LOCK(&(dvp)->v_bh);					\
-	rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr); \
-	VN_BHV_READ_UNLOCK(&(dvp)->v_bh);				\
+	rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr);	\
 }
 #define VOP_READLINK(vp,uiop,cr,rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,cr);		\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_FSYNC(vp,f,cr,b,e,rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e);		\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_INACTIVE(vp, cr, rv)					\
-{	/* vnode not reference-able, so no need to lock chain */	\
+{									\
 	rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr);			\
 }
 #define VOP_RELEASE(vp, rv)						\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_release, vp)((vp)->v_fbhv);			\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_FID2(vp, fidp, rv)						\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp);			\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_RWLOCK(vp,i)						\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	(void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i);			\
-	/* "allow" is done by rwunlock */				\
 }
 #define VOP_RWLOCK_TRY(vp,i)						\
 	_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
 
 #define VOP_RWUNLOCK(vp,i)						\
-{	/* "prevent" was done by rwlock */				\
+{									\
 	(void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i);			\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_RECLAIM(vp, rv)						\
-{	/* vnode not reference-able, so no need to lock chain */	\
+{									\
 	rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv);			\
 }
 #define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv)		\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred); \
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv)		\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred); \
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_ATTR_REMOVE(vp, name, flags, cred, rv)			\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred);	\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv)		\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred);\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_LINK_REMOVED(vp, dvp, linkzero)				\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	(void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero); \
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_VNODE_CHANGE(vp, cmd, val)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	(void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val);	\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 /*
  * These are page cache functions that now go thru VOPs.
@@ -462,39 +400,29 @@
  */
 #define VOP_TOSS_PAGES(vp, first, last, fiopt)				\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	_VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt);	\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 /*
  * 'last' parameter is unused and left in for IRIX compatibility
  */
 #define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt)			\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	_VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt); \
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 /*
  * 'last' parameter is unused and left in for IRIX compatibility
  */
 #define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv)		\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt);\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_IOCTL(vp, inode, filp, cmd, arg, rv)			\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,cmd,arg);	\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 #define VOP_IFLUSH(vp, flags, rv)					\
 {									\
-	VN_BHV_READ_LOCK(&(vp)->v_bh);					\
 	rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags);		\
-	VN_BHV_READ_UNLOCK(&(vp)->v_bh);				\
 }
 
 /*
diff -urN linux-2.5.65-bk2/fs/xfs/pagebuf/page_buf.c linux-2.5.65-bk3/fs/xfs/pagebuf/page_buf.c
--- linux-2.5.65-bk2/fs/xfs/pagebuf/page_buf.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/fs/xfs/pagebuf/page_buf.c	Mon Mar 31 12:41:45 2003
@@ -121,7 +121,8 @@
 STATIC kmem_cache_t *pagebuf_cache;
 STATIC void pagebuf_daemon_wakeup(int);
 STATIC void pagebuf_delwri_queue(page_buf_t *, int);
-STATIC struct workqueue_struct *pagebuf_workqueue;
+STATIC struct workqueue_struct *pagebuf_logio_workqueue;
+STATIC struct workqueue_struct *pagebuf_dataio_workqueue;
 
 /*
  * Pagebuf module configuration parameters, exported via
@@ -786,6 +787,25 @@
 }
 
 /*
+ * Create a skeletal pagebuf (no pages associated with it).
+ */
+page_buf_t *
+pagebuf_lookup(
+	struct pb_target	*target,
+	loff_t			ioff,
+	size_t			isize,
+	page_buf_flags_t	flags)
+{
+	page_buf_t		*pb;
+
+	pb = pagebuf_allocate(flags);
+	if (pb) {
+		_pagebuf_initialize(pb, target, ioff, isize, flags);
+	}
+	return pb;
+}
+
+/*
  * If we are not low on memory then do the readahead in a deadlock
  * safe manner.
  */
@@ -1131,6 +1151,7 @@
 void
 pagebuf_iodone(
 	page_buf_t		*pb,
+	int			dataio,
 	int			schedule)
 {
 	pb->pb_flags &= ~(PBF_READ | PBF_WRITE);
@@ -1143,7 +1164,8 @@
 	if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
 		if (schedule) {
 			INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb);
-			queue_work(pagebuf_workqueue, &pb->pb_iodone_work);
+			queue_work(dataio ? pagebuf_dataio_workqueue :
+				pagebuf_logio_workqueue, &pb->pb_iodone_work);
 		} else {
 			pagebuf_iodone_work(pb);
 		}
@@ -1268,7 +1290,7 @@
 
 	if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
 		pb->pb_locked = 0;
-		pagebuf_iodone(pb, 1);
+		pagebuf_iodone(pb, 0, 1);
 	}
 
 	bio_put(bio);
@@ -1412,7 +1434,7 @@
 
 	if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
 		pb->pb_locked = 0;
-		pagebuf_iodone(pb, 0);
+		pagebuf_iodone(pb, 0, 0);
 	}
 
 	return 0;
@@ -1734,13 +1756,21 @@
 {
 	int		rval;
 
-	pagebuf_workqueue = create_workqueue("pagebuf");
-	if (!pagebuf_workqueue)
+	pagebuf_logio_workqueue = create_workqueue("xfslogd");
+	if (!pagebuf_logio_workqueue)
 		return -ENOMEM;
 
+	pagebuf_dataio_workqueue = create_workqueue("xfsdatad");
+	if (!pagebuf_dataio_workqueue) {
+		destroy_workqueue(pagebuf_logio_workqueue);
+		return -ENOMEM;
+	}
+
 	rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES);
-	if (rval < 0)
-		destroy_workqueue(pagebuf_workqueue);
+	if (rval < 0) {
+		destroy_workqueue(pagebuf_logio_workqueue);
+		destroy_workqueue(pagebuf_dataio_workqueue);
+	}
 
 	return rval;
 }
@@ -1756,7 +1786,8 @@
 	pbd_active = 0;
 	wake_up_interruptible(&pbd_waitq);
 	wait_event_interruptible(pbd_waitq, pbd_active);
-	destroy_workqueue(pagebuf_workqueue);
+	destroy_workqueue(pagebuf_logio_workqueue);
+	destroy_workqueue(pagebuf_dataio_workqueue);
 }
 
 
diff -urN linux-2.5.65-bk2/fs/xfs/pagebuf/page_buf.h linux-2.5.65-bk3/fs/xfs/pagebuf/page_buf.h
--- linux-2.5.65-bk2/fs/xfs/pagebuf/page_buf.h	Mon Mar 17 13:44:09 2003
+++ linux-2.5.65-bk3/fs/xfs/pagebuf/page_buf.h	Mon Mar 31 12:41:45 2003
@@ -169,8 +169,8 @@
  * This buffer structure is used by the page cache buffer management routines
  * to refer to an assembly of pages forming a logical buffer.  The actual
  * I/O is performed with buffer_head or bio structures, as required by drivers,
- * for drivers which do not understand this structure. The buffer structure is
- * used on temporary basis only, and discarded when released.  
+ * for drivers which do not understand this structure.	The buffer structure is
+ * used on temporary basis only, and discarded when released.
  *
  * The real data storage is recorded in the page cache.	 Metadata is
  * hashed to the inode for the block device on which the file system resides.
@@ -245,6 +245,13 @@
 		page_buf_flags_t);	/* PBF_LOCK, PBF_READ,		*/
 					/* PBF_ASYNC			*/	
 
+extern page_buf_t *pagebuf_lookup(
+		struct pb_target *,
+		loff_t,			/* starting offset of range	*/
+		size_t,			/* length of range		*/
+		page_buf_flags_t);	/* PBF_READ, PBF_WRITE,		*/
+					/* PBF_FORCEIO, _PBF_LOCKABLE	*/
+
 extern page_buf_t *pagebuf_get_empty(	/* allocate pagebuf struct with */
 					/*  no memory or disk address	*/
 		struct pb_target *);	/* mount point "fake" inode	*/
@@ -300,6 +307,7 @@
 
 extern void pagebuf_iodone(		/* mark buffer I/O complete	*/
 		page_buf_t *,		/* buffer to mark		*/
+		int,			/* use data/log helper thread.	*/
 		int);			/* run completion locally, or in
 					 * a helper thread. 		*/
 
diff -urN linux-2.5.65-bk2/fs/xfs/support/debug.c linux-2.5.65-bk3/fs/xfs/support/debug.c
--- linux-2.5.65-bk2/fs/xfs/support/debug.c	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk3/fs/xfs/support/debug.c	Mon Mar 31 12:41:45 2003
@@ -55,7 +55,7 @@
     BUG();
 }
 
-#ifdef DEBUG
+#if (defined(DEBUG) || defined(INDUCE_IO_ERRROR))
 
 unsigned long
 random(void)
@@ -85,8 +85,8 @@
 cmn_err(register int level, char *fmt, ...)
 {
 	char	*fp = fmt;
-	ulong	flags;
 	int	len;
+	ulong	flags;
 	va_list	ap;
 
 	level &= XFS_ERR_MASK;
diff -urN linux-2.5.65-bk2/fs/xfs/support/kmem.c linux-2.5.65-bk3/fs/xfs/support/kmem.c
--- linux-2.5.65-bk2/fs/xfs/support/kmem.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/fs/xfs/support/kmem.c	Mon Mar 31 12:41:45 2003
@@ -139,7 +139,7 @@
 	}
 
 	rval = __vmalloc(size, flag_convert(flags), PAGE_KERNEL);
-	if (!rval && !(flags & KM_SLEEP))
+	if (!rval && (flags & KM_SLEEP))
 		panic("kmem_alloc: NULL memory on KM_SLEEP request!");
 
 	return rval;
@@ -176,7 +176,9 @@
 
 	new = kmem_alloc(newsize, flags);
 	if (ptr) {
-		memcpy(new, ptr, ((oldsize < newsize) ? oldsize : newsize));
+		if (new)
+			memcpy(new, ptr,
+				((oldsize < newsize) ? oldsize : newsize));
 		kmem_free(ptr, oldsize);
 	}
 
diff -urN linux-2.5.65-bk2/fs/xfs/support/time.h linux-2.5.65-bk3/fs/xfs/support/time.h
--- linux-2.5.65-bk2/fs/xfs/support/time.h	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk3/fs/xfs/support/time.h	Mon Mar 31 12:41:45 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -35,6 +35,8 @@
 #include <linux/sched.h>
 #include <linux/time.h>
 
+typedef struct timespec timespec_t;
+
 static inline void delay(long ticks)
 {
 	current->state = TASK_UNINTERRUPTIBLE;
diff -urN linux-2.5.65-bk2/fs/xfs/support/uuid.h linux-2.5.65-bk3/fs/xfs/support/uuid.h
--- linux-2.5.65-bk2/fs/xfs/support/uuid.h	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk3/fs/xfs/support/uuid.h	Mon Mar 31 12:41:45 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -32,6 +32,10 @@
 #ifndef __XFS_SUPPORT_UUID_H__
 #define __XFS_SUPPORT_UUID_H__
 
+typedef struct {
+	unsigned char	__u_bits[16];
+} uuid_t;
+
 void uuid_create_nil(uuid_t *uuid);
 int uuid_is_nil(uuid_t *uuid);
 int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_alloc.c linux-2.5.65-bk3/fs/xfs/xfs_alloc.c
--- linux-2.5.65-bk2/fs/xfs/xfs_alloc.c	Mon Mar 17 13:43:49 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_alloc.c	Mon Mar 31 12:41:45 2003
@@ -2183,34 +2183,11 @@
 		INT_GET(agf->agf_flfirst, ARCH_CONVERT) < XFS_AGFL_SIZE(mp) &&
 		INT_GET(agf->agf_fllast,  ARCH_CONVERT) < XFS_AGFL_SIZE(mp) &&
 		INT_GET(agf->agf_flcount, ARCH_CONVERT) <= XFS_AGFL_SIZE(mp);
-	if (XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF,
-			XFS_RANDOM_ALLOC_READ_AGF)) {
+	if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF,
+			XFS_RANDOM_ALLOC_READ_AGF))) {
+		XFS_CORRUPTION_ERROR("xfs_alloc_read_agf",
+				     XFS_ERRLEVEL_LOW, mp, agf);
 		xfs_trans_brelse(tp, bp);
-#ifdef __KERNEL__	/* additional, temporary, debugging code */
-		cmn_err(CE_NOTE,
-			"xfs_alloc_read_agf: error in <%s> AG %d",
-			mp->m_fsname, agno);
-		if (INT_GET(agf->agf_magicnum, ARCH_CONVERT) != XFS_AGF_MAGIC)
-			cmn_err(CE_NOTE, "bad agf_magicnum 0x%x",
-				INT_GET(agf->agf_magicnum, ARCH_CONVERT));
-		if (!XFS_AGF_GOOD_VERSION(INT_GET(agf->agf_versionnum, ARCH_CONVERT)))
-			cmn_err(CE_NOTE, "Bad version number 0x%x",
-				INT_GET(agf->agf_versionnum, ARCH_CONVERT));
-		if (!(INT_GET(agf->agf_freeblks, ARCH_CONVERT) <=
-				INT_GET(agf->agf_length, ARCH_CONVERT)))
-			cmn_err(CE_NOTE, "Bad freeblks %d %d",
-				INT_GET(agf->agf_freeblks, ARCH_CONVERT),
-				INT_GET(agf->agf_length, ARCH_CONVERT));
-		if (!(INT_GET(agf->agf_flfirst, ARCH_CONVERT) < XFS_AGFL_SIZE(mp)))
-			cmn_err(CE_NOTE, "Bad flfirst %d",
-				INT_GET(agf->agf_flfirst, ARCH_CONVERT));
-		if (!(INT_GET(agf->agf_fllast, ARCH_CONVERT) < XFS_AGFL_SIZE(mp)))
-			cmn_err(CE_NOTE, "Bad fllast %d",
-				INT_GET(agf->agf_fllast, ARCH_CONVERT));
-		if (!(INT_GET(agf->agf_flcount, ARCH_CONVERT) <= XFS_AGFL_SIZE(mp)))
-			cmn_err(CE_NOTE, "Bad flcount %d",
-				INT_GET(agf->agf_flcount, ARCH_CONVERT));
-#endif
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	pag = &mp->m_perag[agno];
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_attr.c linux-2.5.65-bk3/fs/xfs/xfs_attr.c
--- linux-2.5.65-bk2/fs/xfs/xfs_attr.c	Mon Mar 17 13:44:09 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_attr.c	Mon Mar 31 12:41:45 2003
@@ -1125,8 +1125,10 @@
 		return(error);
 	ASSERT(bp != NULL);
 	leaf = bp->data;
-	if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT)
-						!= XFS_ATTR_LEAF_MAGIC) {
+	if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT)
+						!= XFS_ATTR_LEAF_MAGIC)) {
+		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
+				     context->dp->i_mount, leaf);
 		xfs_da_brelse(NULL, bp);
 		return(XFS_ERROR(EFSCORRUPTED));
 	}
@@ -1806,14 +1808,22 @@
 						      XFS_ATTR_FORK);
 			if (error)
 				return(error);
-			if (bp == NULL)
+			if (unlikely(bp == NULL)) {
+				XFS_ERROR_REPORT("xfs_attr_node_list(2)",
+						 XFS_ERRLEVEL_LOW,
+						 context->dp->i_mount);
 				return(XFS_ERROR(EFSCORRUPTED));
+			}
 			node = bp->data;
 			if (INT_GET(node->hdr.info.magic, ARCH_CONVERT)
 							== XFS_ATTR_LEAF_MAGIC)
 				break;
-			if (INT_GET(node->hdr.info.magic, ARCH_CONVERT)
-							!= XFS_DA_NODE_MAGIC) {
+			if (unlikely(INT_GET(node->hdr.info.magic, ARCH_CONVERT)
+							!= XFS_DA_NODE_MAGIC)) {
+				XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
+						     XFS_ERRLEVEL_LOW,
+						     context->dp->i_mount,
+						     node);
 				xfs_da_brelse(NULL, bp);
 				return(XFS_ERROR(EFSCORRUPTED));
 			}
@@ -1846,8 +1856,11 @@
 	 */
 	for (;;) {
 		leaf = bp->data;
-		if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT)
-						!= XFS_ATTR_LEAF_MAGIC) {
+		if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT)
+						!= XFS_ATTR_LEAF_MAGIC)) {
+			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
+					     XFS_ERRLEVEL_LOW,
+					     context->dp->i_mount, leaf);
 			xfs_da_brelse(NULL, bp);
 			return(XFS_ERROR(EFSCORRUPTED));
 		}
@@ -1860,8 +1873,12 @@
 					      &bp, XFS_ATTR_FORK);
 		if (error)
 			return(error);
-		if (bp == NULL)
+		if (unlikely((bp == NULL))) {
+			XFS_ERROR_REPORT("xfs_attr_node_list(5)",
+					 XFS_ERRLEVEL_LOW,
+					 context->dp->i_mount);
 			return(XFS_ERROR(EFSCORRUPTED));
+		}
 	}
 	xfs_da_brelse(NULL, bp);
 	return(0);
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_attr_leaf.c linux-2.5.65-bk3/fs/xfs/xfs_attr_leaf.c
--- linux-2.5.65-bk2/fs/xfs/xfs_attr_leaf.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_attr_leaf.c	Mon Mar 31 12:41:45 2003
@@ -455,9 +455,13 @@
 	nsbuf = 0;
 	for (i = 0, sfe = &sf->list[0];
 			i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
-		if (((char *)sfe < (char *)sf) ||
+		if (unlikely(
+		    ((char *)sfe < (char *)sf) ||
 		    ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)) ||
-		    (sfe->namelen >= MAXNAMELEN)) {
+		    (sfe->namelen >= MAXNAMELEN))) {
+			XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
+					     XFS_ERRLEVEL_LOW,
+					     context->dp->i_mount, sfe);
 			xfs_attr_trace_l_c("sf corrupted", context);
 			kmem_free(sbuf, sbsize);
 			return XFS_ERROR(EFSCORRUPTED);
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_bmap.c linux-2.5.65-bk3/fs/xfs/xfs_bmap.c
--- linux-2.5.65-bk2/fs/xfs/xfs_bmap.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_bmap.c	Mon Mar 31 12:41:45 2003
@@ -160,8 +160,7 @@
 	xfs_inode_t		*ip,	/* incore inode pointer */
 	xfs_btree_cur_t		*cur,	/* btree cursor */
 	int			*logflagsp, /* inode logging flags */
-	int			whichfork,  /* data or attr fork */
-	int			async);	    /* xaction can be async */
+	int			whichfork); /* data or attr fork */
 
 #ifdef XFSDEBUG
 /*
@@ -187,7 +186,6 @@
 	xfs_bmap_free_t		*flist, /* list of extents to be freed */
 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
 	xfs_bmbt_irec_t		*new,	/* new data to put in extent list */
-	int			iflags, /* input flags (meta-data or not) */
 	int			*logflagsp,/* inode logging flags */
 	int			whichfork, /* data or attr fork */
 	int			rsvd);	 /* OK to allocate reserved blocks */
@@ -811,7 +809,7 @@
 					RIGHT.br_blockcount, &i)))
 				goto done;
 			ASSERT(i == 1);
-			if ((error = xfs_bmbt_delete(cur, 0, &i)))
+			if ((error = xfs_bmbt_delete(cur, &i)))
 				goto done;
 			ASSERT(i == 1);
 			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
@@ -1349,13 +1347,13 @@
 					RIGHT.br_blockcount, &i)))
 				goto done;
 			ASSERT(i == 1);
-			if ((error = xfs_bmbt_delete(cur, 0, &i)))
+			if ((error = xfs_bmbt_delete(cur, &i)))
 				goto done;
 			ASSERT(i == 1);
 			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
 				goto done;
 			ASSERT(i == 1);
-			if ((error = xfs_bmbt_delete(cur, 0, &i)))
+			if ((error = xfs_bmbt_delete(cur, &i)))
 				goto done;
 			ASSERT(i == 1);
 			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
@@ -1394,7 +1392,7 @@
 					&i)))
 				goto done;
 			ASSERT(i == 1);
-			if ((error = xfs_bmbt_delete(cur, 0, &i)))
+			if ((error = xfs_bmbt_delete(cur, &i)))
 				goto done;
 			ASSERT(i == 1);
 			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
@@ -1434,7 +1432,7 @@
 					RIGHT.br_blockcount, &i)))
 				goto done;
 			ASSERT(i == 1);
-			if ((error = xfs_bmbt_delete(cur, 0, &i)))
+			if ((error = xfs_bmbt_delete(cur, &i)))
 				goto done;
 			ASSERT(i == 1);
 			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
@@ -2010,7 +2008,7 @@
 				right.br_startblock, right.br_blockcount, &i)))
 			return error;
 		ASSERT(i == 1);
-		if ((error = xfs_bmbt_delete(cur, 0, &i)))
+		if ((error = xfs_bmbt_delete(cur, &i)))
 			return error;
 		ASSERT(i == 1);
 		if ((error = xfs_bmbt_decrement(cur, 0, &i)))
@@ -2722,8 +2720,7 @@
 	xfs_inode_t		*ip,	/* incore inode pointer */
 	xfs_btree_cur_t		*cur,	/* btree cursor */
 	int			*logflagsp, /* inode logging flags */
-	int			whichfork,  /* data or attr fork */
-	int			async)	    /* xaction can be async */
+	int			whichfork)  /* data or attr fork */
 {
 	/* REFERENCED */
 	xfs_bmbt_block_t	*cblock;/* child btree block */
@@ -2757,8 +2754,6 @@
 	if ((error = xfs_btree_check_lblock(cur, cblock, 0, cbp)))
 		return error;
 	xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
-	if (!async)
-		xfs_trans_set_sync(tp);
 	ip->i_d.di_nblocks--;
 	if (XFS_IS_QUOTA_ON(mp) &&
 	    ip->i_ino != mp->m_sb.sb_uquotino &&
@@ -2787,7 +2782,6 @@
 	xfs_bmap_free_t		*flist, /* list of extents to be freed */
 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
 	xfs_bmbt_irec_t		*del,	/* data to remove from extent list */
-	int			iflags, /* input flags */
 	int			*logflagsp, /* inode logging flags */
 	int			whichfork, /* data or attr fork */
 	int			rsvd)	/* OK to allocate reserved blocks */
@@ -2916,7 +2910,7 @@
 			flags |= XFS_ILOG_FEXT(whichfork);
 			break;
 		}
-		if ((error = xfs_bmbt_delete(cur, iflags & XFS_BMAPI_ASYNC, &i)))
+		if ((error = xfs_bmbt_delete(cur, &i)))
 			goto done;
 		ASSERT(i == 1);
 		break;
@@ -4396,12 +4390,14 @@
 
 
 		num_recs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
-		if (i + num_recs > room) {
+		if (unlikely(i + num_recs > room)) {
 			ASSERT(i + num_recs <= room);
 			xfs_fs_cmn_err(CE_WARN, ip->i_mount,
-				"corrupt dinode %Lu, (btree extents).  "
-				"Unmount and run xfs_repair.",
+				"corrupt dinode %Lu, (btree extents).  Unmount and run xfs_repair.",
 				(unsigned long long) ip->i_ino);
+			XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
+					 XFS_ERRLEVEL_LOW,
+					ip->i_mount);
 			goto error0;
 		}
 		XFS_WANT_CORRUPTED_GOTO(
@@ -4429,7 +4425,10 @@
 			 * any "older" data bmap btree records for a
 			 * set bit in the "extent flag" position.
 			 */
-			if (xfs_check_nostate_extents(temp, num_recs)) {
+			if (unlikely(xfs_check_nostate_extents(temp, num_recs))) {
+				XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
+						 XFS_ERRLEVEL_LOW,
+						 ip->i_mount);
 				goto error0;
 			}
 		}
@@ -4606,12 +4605,15 @@
 	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE));
 	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
 		XFS_ATTR_FORK : XFS_DATA_FORK;
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL) {
+	mp = ip->i_mount;
+	if (unlikely(XFS_TEST_ERROR(
+	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
+	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
+	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
+		XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
-	mp = ip->i_mount;
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
 	ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -5027,7 +5029,7 @@
 	    XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
 		ASSERT(wr && cur);
 		error = xfs_bmap_btree_to_extents(tp, ip, cur,
-			&tmp_logflags, whichfork, 0);
+			&tmp_logflags, whichfork);
 		logflags |= tmp_logflags;
 		if (error)
 			goto error0;
@@ -5102,8 +5104,11 @@
 	xfs_bmbt_irec_t prev;		/* previous extent list record */
 
 	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) {
+	if (unlikely(
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) {
+	       XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW,
+				ip->i_mount);
 	       return XFS_ERROR(EFSCORRUPTED);
 	}
 	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
@@ -5148,7 +5153,6 @@
 	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
 	int			*done)		/* set if not done yet */
 {
-	int			async;		/* xactions can be async */
 	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
 	xfs_bmbt_irec_t		del;		/* extent being deleted */
 	int			eof;		/* is deleting at eof */
@@ -5175,14 +5179,16 @@
 	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
 		XFS_ATTR_FORK : XFS_DATA_FORK;
 	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
+	if (unlikely(
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
+		XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
+				 ip->i_mount);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	mp = ip->i_mount;
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
-	async = flags & XFS_BMAPI_ASYNC;
 	rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
 	ASSERT(len > 0);
 	ASSERT(nexts >= 0);
@@ -5409,7 +5415,7 @@
 			goto error0;
 		}
 		error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
-			flags, &tmp_logflags, whichfork, rsvd);
+			&tmp_logflags, whichfork, rsvd);
 		logflags |= tmp_logflags;
 		if (error)
 			goto error0;
@@ -5455,7 +5461,7 @@
 		 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
 		ASSERT(cur != NULL);
 		error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
-			whichfork, async);
+			whichfork);
 		logflags |= tmp_logflags;
 		if (error)
 			goto error0;
@@ -5562,11 +5568,11 @@
 			    ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE &&
 			    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
 				return XFS_ERROR(EINVAL);
-		} else if (ip->i_d.di_aformat != 0 &&
-			   ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
-			cmn_err(CE_NOTE,
-				"EFSCORRUPTED returned from file %s line %d",
-				__FILE__, __LINE__);
+		} else if (unlikely(
+		           ip->i_d.di_aformat != 0 &&
+			   ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) {
+			XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW,
+					 ip->i_mount);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
 	} else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
@@ -6114,12 +6120,11 @@
 	mp = ip->i_mount;
 	ifp = XFS_IFORK_PTR(ip, whichfork);
 	if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
-		if (xfs_bmap_count_leaves(ifp->if_u1.if_extents,
+		if (unlikely(xfs_bmap_count_leaves(ifp->if_u1.if_extents,
 			ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t),
-			count) < 0) {
-				cmn_err(CE_NOTE,
-					"EFSCORRUPTED returned from file %s line %d",
-					__FILE__, __LINE__);
+			count) < 0)) {
+			XFS_ERROR_REPORT("xfs_bmap_count_blocks(1)",
+					 XFS_ERRLEVEL_LOW, mp);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
 		return 0;
@@ -6137,10 +6142,9 @@
 	ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
 	bno = INT_GET(*pp, ARCH_CONVERT);
 
-	if (xfs_bmap_count_tree(mp, tp, bno, level, count) < 0) {
-		cmn_err(CE_NOTE,
-			"EFSCORRUPTED returned from file %s line %d",
-			__FILE__, __LINE__);
+	if (unlikely(xfs_bmap_count_tree(mp, tp, bno, level, count) < 0)) {
+		XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
+				 mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -6191,12 +6195,11 @@
 		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
 			xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
 		bno = INT_GET(*pp, ARCH_CONVERT);
-		if ((error =
-		     xfs_bmap_count_tree(mp, tp, bno, level, count)) < 0) {
+		if (unlikely((error =
+		     xfs_bmap_count_tree(mp, tp, bno, level, count)) < 0)) {
 			xfs_trans_brelse(tp, bp);
-			cmn_err(CE_NOTE,
-				"EFSCORRUPTED returned from file %s line %d",
-				__FILE__, __LINE__);
+			XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
+					 XFS_ERRLEVEL_LOW, mp);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
 		xfs_trans_brelse(tp, bp);
@@ -6207,11 +6210,10 @@
 			numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
 			frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize,
 				xfs_bmbt, block, 1, mp->m_bmap_dmxr[0]);
-			if (xfs_bmap_count_leaves(frp, numrecs, count) < 0) {
+			if (unlikely(xfs_bmap_count_leaves(frp, numrecs, count) < 0)) {
 				xfs_trans_brelse(tp, bp);
-				cmn_err(CE_NOTE,
-					"EFSCORRUPTED returned from file %s line %d",
-					__FILE__, __LINE__);
+				XFS_ERROR_REPORT("xfs_bmap_count_tree(2)",
+						 XFS_ERRLEVEL_LOW, mp);
 				return XFS_ERROR(EFSCORRUPTED);
 			}
 			xfs_trans_brelse(tp, bp);
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_bmap_btree.c linux-2.5.65-bk3/fs/xfs/xfs_bmap_btree.c
--- linux-2.5.65-bk2/fs/xfs/xfs_bmap_btree.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_bmap_btree.c	Mon Mar 31 12:41:45 2003
@@ -41,7 +41,7 @@
  */
 
 
-STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *, int);
+STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *);
 STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
 STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
 STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *);
@@ -304,7 +304,6 @@
 xfs_bmbt_delrec(
 	xfs_btree_cur_t		*cur,
 	int			level,
-	int			async,		/* deletion can be async */
 	int			*stat)		/* success/failure */
 {
 	xfs_bmbt_block_t	*block;		/* bmap btree block */
@@ -408,7 +407,7 @@
 	if (level == cur->bc_nlevels - 1) {
 		xfs_iroot_realloc(cur->bc_private.b.ip, -1,
 			cur->bc_private.b.whichfork);
-		if ((error = xfs_bmbt_killroot(cur, async))) {
+		if ((error = xfs_bmbt_killroot(cur))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			goto error0;
 		}
@@ -442,7 +441,7 @@
 	 */
 	if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK &&
 	    level == cur->bc_nlevels - 2) {
-		if ((error = xfs_bmbt_killroot(cur, async))) {
+		if ((error = xfs_bmbt_killroot(cur))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			goto error0;
 		}
@@ -645,8 +644,6 @@
 	}
 	xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1,
 		cur->bc_private.b.flist, mp);
-	if (!async)
-		xfs_trans_set_sync(cur->bc_tp);
 	cur->bc_private.b.ip->i_d.di_nblocks--;
 	xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
 	if (XFS_IS_QUOTA_ON(mp) &&
@@ -911,8 +908,7 @@
 
 STATIC int
 xfs_bmbt_killroot(
-	xfs_btree_cur_t		*cur,
-	int			async)
+	xfs_btree_cur_t		*cur)
 {
 	xfs_bmbt_block_t	*block;
 	xfs_bmbt_block_t	*cblock;
@@ -991,8 +987,6 @@
 	memcpy(pp, cpp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*pp));
 	xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1,
 		cur->bc_private.b.flist, cur->bc_mp);
-	if (!async)
-		xfs_trans_set_sync(cur->bc_tp);
 	ip->i_d.di_nblocks--;
 	if (XFS_IS_QUOTA_ON(cur->bc_mp) &&
 	    ip->i_ino != cur->bc_mp->m_sb.sb_uquotino &&
@@ -1834,7 +1828,6 @@
 int					/* error */
 xfs_bmbt_delete(
 	xfs_btree_cur_t *cur,
-	int		async,		/* deletion can be async */
 	int		*stat)		/* success/failure */
 {
 	int		error;		/* error return value */
@@ -1846,7 +1839,7 @@
 
 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
 	for (level = 0, i = 2; i == 2; level++) {
-		if ((error = xfs_bmbt_delrec(cur, level, async, &i))) {
+		if ((error = xfs_bmbt_delrec(cur, level, &i))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			return error;
 		}
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_bmap_btree.h linux-2.5.65-bk3/fs/xfs/xfs_bmap_btree.h
--- linux-2.5.65-bk2/fs/xfs/xfs_bmap_btree.h	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_bmap_btree.h	Mon Mar 31 12:41:45 2003
@@ -479,7 +479,6 @@
 int
 xfs_bmbt_delete(
 	struct xfs_btree_cur *,
-	int,
 	int *);
 
 void
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_btree.c linux-2.5.65-bk3/fs/xfs/xfs_btree.c
--- linux-2.5.65-bk2/fs/xfs/xfs_btree.c	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_btree.c	Mon Mar 31 12:41:45 2003
@@ -190,15 +190,12 @@
 		!INT_ISZERO(block->bb_rightsib, ARCH_CONVERT) &&
 		(INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO ||
 		 XFS_FSB_SANITY_CHECK(mp, INT_GET(block->bb_rightsib, ARCH_CONVERT)));
-	if (XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK,
-			XFS_RANDOM_BTREE_CHECK_LBLOCK)) {
+	if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK,
+			XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
 		if (bp)
 			xfs_buftrace("LBTREE ERROR", bp);
-#ifdef __KERNEL__	/* additional, temporary, debugging code */
-		cmn_err(CE_NOTE,
-			"EFSCORRUPTED returned from file %s line %d",
-			__FILE__, __LINE__);
-#endif
+		XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW,
+				 mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	return 0;
@@ -312,22 +309,13 @@
 		(INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK ||
 		 INT_GET(block->bb_rightsib, ARCH_CONVERT) < agflen) &&
 		!INT_ISZERO(block->bb_rightsib, ARCH_CONVERT);
-	if (XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
+	if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
 			XFS_ERRTAG_BTREE_CHECK_SBLOCK,
-			XFS_RANDOM_BTREE_CHECK_SBLOCK)) {
+			XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
 		if (bp)
 			xfs_buftrace("SBTREE ERROR", bp);
-#ifdef __KERNEL__	/* additional, temporary, debugging code */
-		cmn_err(CE_NOTE,
-			"xfs_btree_check_sblock: Not OK:");
-		cmn_err(CE_NOTE,
-			"magic 0x%x level %d numrecs %d leftsib %d rightsib %d",
-			INT_GET(block->bb_magic, ARCH_CONVERT),
-			INT_GET(block->bb_level, ARCH_CONVERT),
-			INT_GET(block->bb_numrecs, ARCH_CONVERT),
-			INT_GET(block->bb_leftsib, ARCH_CONVERT),
-			INT_GET(block->bb_rightsib, ARCH_CONVERT));
-#endif
+		XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW,
+				 cur->bc_mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	return 0;
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_btree.h linux-2.5.65-bk3/fs/xfs/xfs_btree.h
--- linux-2.5.65-bk2/fs/xfs/xfs_btree.h	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_btree.h	Mon Mar 31 12:41:45 2003
@@ -570,7 +570,9 @@
 	{ \
 		int fs_is_ok = (x); \
 		ASSERT(fs_is_ok); \
-		if (!fs_is_ok) { \
+		if (unlikely(!fs_is_ok)) { \
+			XFS_ERROR_REPORT("XFS_WANT_CORRUPTED_GOTO", \
+					 XFS_ERRLEVEL_LOW, NULL); \
 			error = XFS_ERROR(EFSCORRUPTED); \
 			goto l; \
 		} \
@@ -580,8 +582,11 @@
 	{ \
 		int fs_is_ok = (x); \
 		ASSERT(fs_is_ok); \
-		if (!fs_is_ok) \
+		if (unlikely(!fs_is_ok)) { \
+			XFS_ERROR_REPORT("XFS_WANT_CORRUPTED_RETURN", \
+					 XFS_ERRLEVEL_LOW, NULL); \
 			return XFS_ERROR(EFSCORRUPTED); \
+		} \
 	}
 
 #endif	/* __XFS_BTREE_H__ */
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_buf.h linux-2.5.65-bk3/fs/xfs/xfs_buf.h
--- linux-2.5.65-bk2/fs/xfs/xfs_buf.h	Mon Mar 17 13:44:47 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_buf.h	Mon Mar 31 12:41:45 2003
@@ -163,15 +163,17 @@
 #define XFS_BUF_SET_PTR(bp, val, count)		\
 				pagebuf_associate_memory(bp, val, count)
 #define XFS_BUF_ADDR(bp)	((bp)->pb_bn)
-#define XFS_BUF_OFFSET(bp)	((bp)->pb_file_offset >> 9)
 #define XFS_BUF_SET_ADDR(bp, blk)		\
 			((bp)->pb_bn = (page_buf_daddr_t)(blk))
+#define XFS_BUF_OFFSET(bp)	((bp)->pb_file_offset)
+#define XFS_BUF_SET_OFFSET(bp, off)		\
+			((bp)->pb_file_offset = (off))
 #define XFS_BUF_COUNT(bp)	((bp)->pb_count_desired)
 #define XFS_BUF_SET_COUNT(bp, cnt)		\
-			((bp)->pb_count_desired = cnt)
+			((bp)->pb_count_desired = (cnt))
 #define XFS_BUF_SIZE(bp)	((bp)->pb_buffer_length)
 #define XFS_BUF_SET_SIZE(bp, cnt)		\
-			((bp)->pb_buffer_length = cnt)
+			((bp)->pb_buffer_length = (cnt))
 #define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
 #define XFS_BUF_SET_VTYPE(bp, type)
 #define XFS_BUF_SET_REF(bp, ref)
@@ -242,7 +244,7 @@
 
 
 #define xfs_biodone(pb)		    \
-	    pagebuf_iodone(pb, 0)
+	    pagebuf_iodone(pb, 0, 0)
 
 #define xfs_incore(buftarg,blkno,len,lockit) \
 	    pagebuf_find(buftarg, blkno ,len, lockit)
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_buf_item.c linux-2.5.65-bk3/fs/xfs/xfs_buf_item.c
--- linux-2.5.65-bk2/fs/xfs/xfs_buf_item.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_buf_item.c	Mon Mar 31 12:41:45 2003
@@ -991,7 +991,7 @@
 	xfs_buf_t	*bp)
 {
 	xfs_log_item_t	*lip;
-	static time_t	lasttime;
+	static ulong	lasttime;
 	static dev_t	lastdev;
 	xfs_mount_t	*mp;
 
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_da_btree.c linux-2.5.65-bk3/fs/xfs/xfs_da_btree.c
--- linux-2.5.65-bk2/fs/xfs/xfs_da_btree.c	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_da_btree.c	Mon Mar 31 12:41:45 2003
@@ -1791,8 +1791,11 @@
 		error = xfs_bmap_last_offset(tp, ip, &lastoff, w);
 	if (error)
 		return error;
-	if (lastoff == 0)
+	if (unlikely(lastoff == 0)) {
+		XFS_ERROR_REPORT("xfs_da_swap_lastblock(1)", XFS_ERRLEVEL_LOW,
+				 mp);
 		return XFS_ERROR(EFSCORRUPTED);
+	}
 	/*
 	 * Read the last block in the btree space.
 	 */
@@ -1833,8 +1836,11 @@
 		if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w)))
 			goto done;
 		sib_info = sib_buf->data;
-		if (INT_GET(sib_info->forw, ARCH_CONVERT) != last_blkno ||
-		    INT_GET(sib_info->magic, ARCH_CONVERT) != INT_GET(dead_info->magic, ARCH_CONVERT)) {
+		if (unlikely(
+		    INT_GET(sib_info->forw, ARCH_CONVERT) != last_blkno ||
+		    INT_GET(sib_info->magic, ARCH_CONVERT) != INT_GET(dead_info->magic, ARCH_CONVERT))) {
+			XFS_ERROR_REPORT("xfs_da_swap_lastblock(2)",
+					 XFS_ERRLEVEL_LOW, mp);
 			error = XFS_ERROR(EFSCORRUPTED);
 			goto done;
 		}
@@ -1852,9 +1858,12 @@
 		if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w)))
 			goto done;
 		sib_info = sib_buf->data;
-		if (   INT_GET(sib_info->back, ARCH_CONVERT) != last_blkno
+		if (unlikely(
+		       INT_GET(sib_info->back, ARCH_CONVERT) != last_blkno
 		    || INT_GET(sib_info->magic, ARCH_CONVERT)
-				!= INT_GET(dead_info->magic, ARCH_CONVERT)) {
+				!= INT_GET(dead_info->magic, ARCH_CONVERT))) {
+			XFS_ERROR_REPORT("xfs_da_swap_lastblock(3)",
+					 XFS_ERRLEVEL_LOW, mp);
 			error = XFS_ERROR(EFSCORRUPTED);
 			goto done;
 		}
@@ -1874,8 +1883,11 @@
 		if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
 			goto done;
 		par_node = par_buf->data;
-		if (INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC ||
-		    (level >= 0 && level != INT_GET(par_node->hdr.level, ARCH_CONVERT) + 1)) {
+		if (unlikely(
+		    INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC ||
+		    (level >= 0 && level != INT_GET(par_node->hdr.level, ARCH_CONVERT) + 1))) {
+			XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)",
+					 XFS_ERRLEVEL_LOW, mp);
 			error = XFS_ERROR(EFSCORRUPTED);
 			goto done;
 		}
@@ -1885,7 +1897,9 @@
 		     INT_GET(par_node->btree[entno].hashval, ARCH_CONVERT) < dead_hash;
 		     entno++)
 			continue;
-		if (entno == INT_GET(par_node->hdr.count, ARCH_CONVERT)) {
+		if (unlikely(entno == INT_GET(par_node->hdr.count, ARCH_CONVERT))) {
+			XFS_ERROR_REPORT("xfs_da_swap_lastblock(5)",
+					 XFS_ERRLEVEL_LOW, mp);
 			error = XFS_ERROR(EFSCORRUPTED);
 			goto done;
 		}
@@ -1910,15 +1924,20 @@
 		par_blkno = INT_GET(par_node->hdr.info.forw, ARCH_CONVERT);
 		xfs_da_brelse(tp, par_buf);
 		par_buf = NULL;
-		if (par_blkno == 0) {
+		if (unlikely(par_blkno == 0)) {
+			XFS_ERROR_REPORT("xfs_da_swap_lastblock(6)",
+					 XFS_ERRLEVEL_LOW, mp);
 			error = XFS_ERROR(EFSCORRUPTED);
 			goto done;
 		}
 		if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
 			goto done;
 		par_node = par_buf->data;
-		if (INT_GET(par_node->hdr.level, ARCH_CONVERT) != level ||
-		    INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) {
+		if (unlikely(
+		    INT_GET(par_node->hdr.level, ARCH_CONVERT) != level ||
+		    INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC)) {
+			XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)",
+					 XFS_ERRLEVEL_LOW, mp);
 			error = XFS_ERROR(EFSCORRUPTED);
 			goto done;
 		}
@@ -2111,6 +2130,26 @@
 	}
 	if (!xfs_da_map_covers_blocks(nmap, mapp, bno, nfsb)) {
 		error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED);
+		if (unlikely(error == EFSCORRUPTED)) {
+			if (xfs_error_level >= XFS_ERRLEVEL_LOW) {
+				int	i;
+				cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n",
+					bno);
+				cmn_err(CE_ALERT, "dir: inode %lld\n",
+					dp->i_ino);
+				for (i = 0; i < nmap; i++) {
+					cmn_err(CE_ALERT,
+						"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n",
+						i,
+						mapp[i].br_startoff,
+						mapp[i].br_startblock,
+						mapp[i].br_blockcount,
+						mapp[i].br_state);
+				}
+			}
+			XFS_ERROR_REPORT("xfs_da_do_buf(1)",
+					 XFS_ERRLEVEL_LOW, mp);
+		}
 		goto exit0;
 	}
 	if (caller != 3 && nmap > 1) {
@@ -2193,7 +2232,8 @@
 		free = rbp->data;
 		magic = INT_GET(info->magic, ARCH_CONVERT);
 		magic1 = INT_GET(data->hdr.magic, ARCH_CONVERT);
-		if (XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
+		if (unlikely(
+		    XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
 				   (magic != XFS_DIR_LEAF_MAGIC) &&
 				   (magic != XFS_ATTR_LEAF_MAGIC) &&
 				   (magic != XFS_DIR2_LEAF1_MAGIC) &&
@@ -2202,8 +2242,10 @@
 				   (magic1 != XFS_DIR2_DATA_MAGIC) &&
 				   (INT_GET(free->hdr.magic, ARCH_CONVERT) != XFS_DIR2_FREE_MAGIC),
 				mp, XFS_ERRTAG_DA_READ_BUF,
-				XFS_RANDOM_DA_READ_BUF)) {
+				XFS_RANDOM_DA_READ_BUF))) {
 			xfs_buftrace("DA READ ERROR", rbp->bps[0]);
+			XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)",
+					     XFS_ERRLEVEL_LOW, mp, info);
 			error = XFS_ERROR(EFSCORRUPTED);
 			xfs_da_brelse(trans, rbp);
 			nbplist = 0;
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dfrag.c linux-2.5.65-bk3/fs/xfs/xfs_dfrag.c
--- linux-2.5.65-bk2/fs/xfs/xfs_dfrag.c	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_dfrag.c	Mon Mar 31 12:41:45 2003
@@ -69,15 +69,12 @@
 	}
 
 	bhp = VN_BHV_HEAD(vp);
-	VN_BHV_READ_LOCK(bhp);
 	bdp = vn_bhv_lookup(bhp, &xfs_vnodeops);
 	if (bdp == NULL) {
-		VN_BHV_READ_UNLOCK(bhp);
 		error = XFS_ERROR(EBADF);
 		goto error0;
 	} else {
 		ip = XFS_BHVTOI(bdp);
-		VN_BHV_READ_UNLOCK(bhp);
 	}
 
 	if (((tfp = fget((int)sx.sx_fdtmp)) == NULL) ||
@@ -87,15 +84,12 @@
 	}
 
 	tbhp = VN_BHV_HEAD(tvp);
-	VN_BHV_READ_LOCK(tbhp);
 	tbdp = vn_bhv_lookup(tbhp, &xfs_vnodeops);
 	if (tbdp == NULL) {
-		VN_BHV_READ_UNLOCK(tbhp);
 		error = XFS_ERROR(EBADF);
 		goto error0;
 	} else {
 		tip = XFS_BHVTOI(tbdp);
-		VN_BHV_READ_UNLOCK(tbhp);
 	}
 
 	if (ip->i_ino == tip->i_ino) {
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir.c linux-2.5.65-bk3/fs/xfs/xfs_dir.c
--- linux-2.5.65-bk2/fs/xfs/xfs_dir.c	Mon Mar 17 13:43:48 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_dir.c	Mon Mar 31 12:41:45 2003
@@ -887,7 +887,7 @@
 	 * hashval, then we run with it.
 	 */
 	if (bno > 0) {
-		error = xfs_da_read_buf(trans, dp, bno, -1, &bp, XFS_DATA_FORK);
+		error = xfs_da_read_buf(trans, dp, bno, -2, &bp, XFS_DATA_FORK);
 		if ((error != 0) && (error != EFSCORRUPTED))
 			return(error);
 		if (bp)
@@ -962,9 +962,11 @@
 	 */
 	for (;;) {
 		leaf = bp->data;
-		if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) {
+		if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC)) {
 			xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf);
 			xfs_da_brelse(trans, bp);
+			XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)",
+					     XFS_ERRLEVEL_LOW, mp, leaf);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
 		xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf);
@@ -988,8 +990,11 @@
 					XFS_DATA_FORK);
 		if (error)
 			return(error);
-		if (bp == NULL)
+		if (unlikely(bp == NULL)) {
+			XFS_ERROR_REPORT("xfs_dir_node_getdents(2)",
+					 XFS_ERRLEVEL_LOW, mp);
 			return(XFS_ERROR(EFSCORRUPTED));
+		}
 	}
 	*eofp = 1;
 	xfs_dir_trace_g_du("node: E-O-F", dp, uio);
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir2_block.c linux-2.5.65-bk3/fs/xfs/xfs_dir2_block.c
--- linux-2.5.65-bk2/fs/xfs/xfs_dir2_block.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_dir2_block.c	Mon Mar 31 12:41:45 2003
@@ -98,7 +98,10 @@
 	/*
 	 * Check the magic number, corrupted if wrong.
 	 */
-	if (INT_GET(block->hdr.magic, ARCH_CONVERT) != XFS_DIR2_BLOCK_MAGIC) {
+	if (unlikely(INT_GET(block->hdr.magic, ARCH_CONVERT)
+						!= XFS_DIR2_BLOCK_MAGIC)) {
+		XFS_CORRUPTION_ERROR("xfs_dir2_block_addname",
+				     XFS_ERRLEVEL_LOW, mp, block);
 		xfs_da_brelse(tp, bp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
@@ -437,7 +440,6 @@
 	xfs_mount_t		*mp;		/* filesystem mount point */
 	xfs_dir2_put_args_t	p;		/* arg package for put rtn */
 	char			*ptr;		/* current data entry */
-	char			*savptr;	/* saved data entry */
 	int			wantoff;	/* starting block offset */
 
 	mp = dp->i_mount;
@@ -488,8 +490,6 @@
 
 		dep = (xfs_dir2_data_entry_t *)ptr;
 
-		savptr = ptr;		/* In case we need it.. */
-
 		/*
 		 * Bump pointer for the next iteration.
 		 */
@@ -504,14 +504,8 @@
 		 */
 		p.namelen = dep->namelen;
 
-		/*
-		 * NOTE! Linux "filldir" semantics require that the
-		 *	 offset "cookie" be for this entry, not the
-		 *	 next; all the actual shuffling to make it
-		 *	 "look right" to the user is done in filldir.
-		 */
 		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-						    savptr - (char *)block);
+						    ptr - (char *)block);
 #if XFS_BIG_FILESYSTEMS
 		p.ino = INT_GET(dep->inumber, ARCH_CONVERT) + mp->m_inoadd;
 #else
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir2_leaf.c linux-2.5.65-bk3/fs/xfs/xfs_dir2_leaf.c
--- linux-2.5.65-bk2/fs/xfs/xfs_dir2_leaf.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_dir2_leaf.c	Mon Mar 31 12:41:45 2003
@@ -1059,6 +1059,9 @@
 					XFS_DIR2_DB_OFF_TO_BYTE(mp,
 					    XFS_DIR2_BYTE_TO_DB(mp, curoff),
 					    (char *)ptr - (char *)data);
+				if (ptr >= (char *)data + mp->m_dirblksize) {
+					continue;
+				}
 			}
 		}
 		/*
@@ -1086,13 +1089,7 @@
 
 		length = XFS_DIR2_DATA_ENTSIZE(p.namelen);
 
-		/*
-		 * NOTE! Linux "filldir" semantics require that the
-		 *	 offset "cookie" be for this entry, not the
-		 *	 next; all the actual shuffling to make it
-		 *	 "look right" to the user is done in filldir.
-		 */
-		p.cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff);
+		p.cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length);
 
 #if XFS_BIG_FILESYSTEMS
 		p.ino = INT_GET(dep->inumber, ARCH_CONVERT) + mp->m_inoadd;
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir2_node.c linux-2.5.65-bk3/fs/xfs/xfs_dir2_node.c
--- linux-2.5.65-bk2/fs/xfs/xfs_dir2_node.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_dir2_node.c	Mon Mar 31 12:41:45 2003
@@ -511,7 +511,9 @@
 				/*
 				 * If it has room, return it.
 				 */
-				if (INT_GET(free->bests[fi], ARCH_CONVERT) == NULLDATAOFF) {
+				if (unlikely(INT_GET(free->bests[fi], ARCH_CONVERT) == NULLDATAOFF)) {
+					XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
+							 XFS_ERRLEVEL_LOW, mp);
 					return XFS_ERROR(EFSCORRUPTED);
 				}
 				if (INT_GET(free->bests[fi], ARCH_CONVERT) >= length) {
@@ -1346,6 +1348,7 @@
 	int			findex;		/* freespace entry index */
 	xfs_dir2_db_t		foundbno=0;	/* found freespace block no */
 	int			foundindex=0;	/* found freespace entry idx */
+	int			foundhole;	/* found hole in freespace */
 	xfs_dir2_free_t		*free=NULL;	/* freespace block structure */
 	xfs_dir2_db_t		ifbno;		/* initial freespace block no */
 	xfs_dir2_db_t		lastfbno=0;	/* highest freespace block no */
@@ -1354,6 +1357,7 @@
 	xfs_mount_t		*mp;		/* filesystem mount point */
 	int			needlog;	/* need to log data header */
 	int			needscan;	/* need to rescan data frees */
+	int			needfreesp;	/* need to allocate freesp blk */
 	xfs_dir2_data_off_t	*tagp;		/* data entry tag pointer */
 	xfs_trans_t		*tp;		/* transaction pointer */
 
@@ -1361,6 +1365,7 @@
 	mp = dp->i_mount;
 	tp = args->trans;
 	length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+	foundhole = 0;
 	/*
 	 * If we came in with a freespace block that means that lookup
 	 * found an entry with our hash value.	This is the freespace
@@ -1450,11 +1455,12 @@
 			 * to avoid it.
 			 */
 			if ((error = xfs_da_read_buf(tp, dp,
-					XFS_DIR2_DB_TO_DA(mp, fbno), -1, &fbp,
+					XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
 					XFS_DATA_FORK))) {
 				return error;
 			}
-			if (fbp == NULL) {
+			if (unlikely(fbp == NULL)) {
+				foundhole = 1;
 				continue;
 			}
 			free = fbp->data;
@@ -1473,7 +1479,7 @@
 			 * one is empty, remember this slot.
 			 */
 			if (foundindex == -1 &&
-			    INT_GET(free->bests[findex], ARCH_CONVERT) == NULLDATAOFF) {
+			    INT_GET(free->bests[findex], ARCH_CONVERT) == NULLDATAOFF && !foundhole) {
 				foundindex = findex;
 				foundbno = fbno;
 			}
@@ -1487,7 +1493,8 @@
 				 * remember this slot.
 				 */
 				if (foundindex == -1 &&
-				    findex < XFS_DIR2_MAX_FREE_BESTS(mp)) {
+				    findex < XFS_DIR2_MAX_FREE_BESTS(mp) &&
+				    !foundhole) {
 					foundindex = findex;
 					foundbno = fbno;
 				}
@@ -1502,68 +1509,10 @@
 		}
 	}
 	/*
-	 * If we don't have a data block, and there's no free slot in a
-	 * freeblock, we need to add a new freeblock.
-	 */
-	if (dbno == -1 && foundindex == -1) {
-		/*
-		 * Not allowed to allocate, so return failure.
-		 */
-		if (args->justcheck || args->total == 0) {
-			return XFS_ERROR(ENOSPC);
-		}
-		/*
-		 * Add the new freeblock.
-		 */
-		if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE,
-				&fbno))) {
-			return error;
-		}
-		/*
-		 * Get a buffer for the new block.
-		 */
-		if ((error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fbno),
-				-1, &fbp, XFS_DATA_FORK))) {
-			return error;
-		}
-		ASSERT(fbp != NULL);
-		/*
-		 * Initialize the new block to be empty, and remember
-		 * its first slot as our empty slot.
-		 */
-		free = fbp->data;
-		INT_SET(free->hdr.magic, ARCH_CONVERT, XFS_DIR2_FREE_MAGIC);
-		INT_SET(free->hdr.firstdb, ARCH_CONVERT, (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
-			XFS_DIR2_MAX_FREE_BESTS(mp));
-		INT_ZERO(free->hdr.nused, ARCH_CONVERT);
-		INT_ZERO(free->hdr.nvalid, ARCH_CONVERT);
-		foundindex = 0;
-		foundbno = fbno;
-	}
-	/*
-	 * If we don't have a data block, and we don't have a freeblock buffer
-	 * in hand (we dropped the one with the free slot in it),
-	 * go read the freeblock again.
-	 */
-	if (dbno == -1 && fbp == NULL) {
-		/*
-		 * We're going to use the empty slot we found before.
-		 */
-		findex = foundindex;
-		fbno = foundbno;
-		if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fbno),
-				-1, &fbp, XFS_DATA_FORK))) {
-			return error;
-		}
-		ASSERT(fbp != NULL);
-		free = fbp->data;
-		ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC);
-	}
-	/*
 	 * If we don't have a data block, we need to allocate one and make
 	 * the freespace entries refer to it.
 	 */
-	if (dbno == -1) {
+	if (unlikely(dbno == -1)) {
 		/*
 		 * Not allowed to allocate, return failure.
 		 */
@@ -1572,7 +1521,7 @@
 			 * Drop the freespace buffer unless it came from our
 			 * caller.
 			 */
-			if (fblk == NULL || fblk->bp == NULL)
+			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
 				xfs_da_buf_done(fbp);
 			return XFS_ERROR(ENOSPC);
 		}
@@ -1586,7 +1535,7 @@
 			 * Drop the freespace buffer unless it came from our
 			 * caller.
 			 */
-			if (fblk == NULL || fblk->bp == NULL)
+			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
 				xfs_da_buf_done(fbp);
 			return error;
 		}
@@ -1595,21 +1544,80 @@
 		 * freespace block we have in hand, drop the one we have
 		 * and get the right one.
 		 */
-		if (XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno) {
-			xfs_da_brelse(tp, fbp);
+		needfreesp = 0;
+		if (XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno || fbp == NULL) {
+			if (fbp)
+				xfs_da_brelse(tp, fbp);
 			if (fblk && fblk->bp)
 				fblk->bp = NULL;
 			fbno = XFS_DIR2_DB_TO_FDB(mp, dbno);
 			if ((error = xfs_da_read_buf(tp, dp,
-					XFS_DIR2_DB_TO_DA(mp, fbno), -1, &fbp,
+					XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
 					XFS_DATA_FORK))) {
 				xfs_da_buf_done(dbp);
 				return error;
 			}
+
+			/*
+			 * If there wasn't a freespace block, the read will
+			 * return a NULL fbp.  Allocate one later.
+			 */
+
+			if(unlikely( fbp == NULL )) {
+				needfreesp = 1;
+			} else {
+				free = fbp->data;
+				ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC);
+			}
+		}
+
+		/*
+		 * If we don't have a data block, and there's no free slot in a
+		 * freeblock, we need to add a new freeblock.
+		 */
+		if (unlikely(needfreesp || foundindex == -1)) {
+			/*
+			 * Add the new freeblock.
+			 */
+			if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE,
+							&fbno))) {
+				return error;
+			}
+
+			if (XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno) {
+				cmn_err(CE_ALERT,
+		"xfs_dir2_node_addname_int: needed block %lld, got %lld\n",
+					XFS_DIR2_DB_TO_FDB(mp, dbno), fbno);
+				XFS_ERROR_REPORT("xfs_dir2_node_addname_int",
+						 XFS_ERRLEVEL_LOW, mp);
+				return XFS_ERROR(EFSCORRUPTED);
+			}
+
+			/*
+			 * Get a buffer for the new block.
+			 */
+			if ((error = xfs_da_get_buf(tp, dp,
+						   XFS_DIR2_DB_TO_DA(mp, fbno),
+						   -1, &fbp, XFS_DATA_FORK))) {
+				return error;
+			}
 			ASSERT(fbp != NULL);
+
+			/*
+			 * Initialize the new block to be empty, and remember
+			 * its first slot as our empty slot.
+			 */
 			free = fbp->data;
-			ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC);
+			INT_SET(free->hdr.magic, ARCH_CONVERT, XFS_DIR2_FREE_MAGIC);
+			INT_SET(free->hdr.firstdb, ARCH_CONVERT,
+				(fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
+				XFS_DIR2_MAX_FREE_BESTS(mp));
+			INT_ZERO(free->hdr.nvalid, ARCH_CONVERT);
+			INT_ZERO(free->hdr.nused, ARCH_CONVERT);
+			foundindex = 0;
+			foundbno = fbno;
 		}
+
 		/*
 		 * Set the freespace block index from the data block number.
 		 */
@@ -1651,16 +1659,17 @@
 		 * If just checking, we succeeded.
 		 */
 		if (args->justcheck) {
-			if (fblk == NULL || fblk->bp == NULL)
+			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
 				xfs_da_buf_done(fbp);
 			return 0;
 		}
 		/*
 		 * Read the data block in.
 		 */
-		if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, dbno),
+		if (unlikely(
+		    error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, dbno),
 				-1, &dbp, XFS_DATA_FORK))) {
-			if (fblk == NULL || fblk->bp == NULL)
+			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
 				xfs_da_buf_done(fbp);
 			return error;
 		}
@@ -1715,7 +1724,7 @@
 	/*
 	 * If the caller didn't hand us the freespace block, drop it.
 	 */
-	if (fblk == NULL || fblk->bp == NULL)
+	if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
 		xfs_da_buf_done(fbp);
 	/*
 	 * Return the data block and offset in args, then drop the data block.
@@ -1943,10 +1952,18 @@
 	/*
 	 * Read the freespace block.
 	 */
-	if ((error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -1, &bp,
+	if (unlikely(error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -2, &bp,
 			XFS_DATA_FORK))) {
 		return error;
 	}
+
+	/*
+	 * There can be holes in freespace.  If fo is a hole, there's
+	 * nothing to do.
+	 */
+	if (bp == NULL) {
+		return 0;
+	}
 	free = bp->data;
 	ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC);
 	/*
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir2_sf.c linux-2.5.65-bk3/fs/xfs/xfs_dir2_sf.c
--- linux-2.5.65-bk2/fs/xfs/xfs_dir2_sf.c	Mon Mar 17 13:44:17 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_dir2_sf.c	Mon Mar 31 12:41:45 2003
@@ -752,14 +752,8 @@
 	if (dir_offset <=
 		    XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
 					       XFS_DIR2_DATA_DOT_OFFSET)) {
-		/*
-		 * NOTE! Linux "filldir" semantics require that the
-		 *	 offset "cookie" be for this entry, not the
-		 *	 next; all the actual shuffling to make it
-		 *	 "look right" to the user is done in filldir.
-		 */
 		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, 0,
-						XFS_DIR2_DATA_DOT_OFFSET);
+						XFS_DIR2_DATA_DOTDOT_OFFSET);
 #if XFS_BIG_FILESYSTEMS
 		p.ino = dp->i_ino + mp->m_inoadd;
 #else
@@ -784,14 +778,8 @@
 	if (dir_offset <=
 		    XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
 					       XFS_DIR2_DATA_DOTDOT_OFFSET)) {
-		/*
-		 * NOTE! Linux "filldir" semantics require that the
-		 *	 offset "cookie" be for this entry, not the
-		 *	 next; all the actual shuffling to make it
-		 *	 "look right" to the user is done in filldir.
-		 */
 		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-						XFS_DIR2_DATA_DOTDOT_OFFSET);
+						XFS_DIR2_DATA_FIRST_OFFSET);
 #if XFS_BIG_FILESYSTEMS
 		p.ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent, ARCH_CONVERT) +
 			mp->m_inoadd;
@@ -826,14 +814,9 @@
 
 		p.namelen = sfep->namelen;
 
-		/*
-		 * NOTE! Linux "filldir" semantics require that the
-		 *	 offset "cookie" be for this entry, not the
-		 *	 next; all the actual shuffling to make it
-		 *	 "look right" to the user is done in filldir.
-		 */
 		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-				XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT));
+			XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT) +
+			XFS_DIR2_DATA_ENTSIZE(p.namelen));
 
 #if XFS_BIG_FILESYSTEMS
 		p.ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp,
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir_leaf.c linux-2.5.65-bk3/fs/xfs/xfs_dir_leaf.c
--- linux-2.5.65-bk2/fs/xfs/xfs_dir_leaf.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_dir_leaf.c	Mon Mar 31 12:41:45 2003
@@ -103,10 +103,11 @@
 		agblkno != 0 &&
 		ioff < (1 << mp->m_sb.sb_inopblog) &&
 		XFS_AGINO_TO_INO(mp, agno, agino) == ino;
-	if (XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
-			XFS_RANDOM_DIR_INO_VALIDATE)) {
+	if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
+			XFS_RANDOM_DIR_INO_VALIDATE))) {
 		xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
 				(unsigned long long) ino);
+		XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	return 0;
@@ -455,10 +456,13 @@
 	for (i = 0, sfe = &sf->list[0];
 			i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
 
-		if (((char *)sfe < (char *)sf) ||
+		if (unlikely(
+		    ((char *)sfe < (char *)sf) ||
 		    ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)) ||
-		    (sfe->namelen >= MAXNAMELEN)) {
+		    (sfe->namelen >= MAXNAMELEN))) {
 			xfs_dir_trace_g_du("sf: corrupted", dp, uio);
+			XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents", 
+					     XFS_ERRLEVEL_LOW, mp, sfe);
 			kmem_free(sbuf, sbsize);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
@@ -1970,9 +1974,12 @@
 		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
 				    INT_GET(entry->nameidx, ARCH_CONVERT));
 
-		if (((char *)namest < (char *)leaf) ||
+		if (unlikely(
+		    ((char *)namest < (char *)leaf) ||
 		    ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)) ||
-		    (entry->namelen >= MAXNAMELEN)) {
+		    (entry->namelen >= MAXNAMELEN))) {
+			XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)", 
+					     XFS_ERRLEVEL_LOW, mp, leaf);
 			xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
@@ -2031,9 +2038,12 @@
 		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
 				    INT_GET(entry->nameidx, ARCH_CONVERT));
 
-		if (((char *)namest < (char *)leaf) ||
+		if (unlikely(
+		    ((char *)namest < (char *)leaf) ||
 		    ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)) ||
-		    (entry->namelen >= MAXNAMELEN)) {
+		    (entry->namelen >= MAXNAMELEN))) {
+			XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)",
+					     XFS_ERRLEVEL_LOW, mp, leaf);
 			xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
@@ -2076,11 +2086,14 @@
 
 			leaf2 = bp2->data;
 
-			if (   (INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT)
+			if (unlikely(
+			       (INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT)
 						!= XFS_DIR_LEAF_MAGIC)
 			    || (INT_GET(leaf2->hdr.info.back, ARCH_CONVERT)
-						!= bno)) {	/* GROT */
-
+						!= bno))) {	/* GROT */
+				XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)",
+						     XFS_ERRLEVEL_LOW, mp,
+						     leaf2);
 				xfs_da_brelse(dp->i_transp, bp2);
 
 				return(XFS_ERROR(EFSCORRUPTED));
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_error.c linux-2.5.65-bk3/fs/xfs/xfs_error.c
--- linux-2.5.65-bk2/fs/xfs/xfs_error.c	Mon Mar 17 13:44:45 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_error.c	Mon Mar 31 12:41:45 2003
@@ -238,3 +238,79 @@
 	xfs_fs_vcmn_err(level, mp, fmt, ap);
 	va_end(ap);
 }
+
+void
+xfs_stack_trace(void)
+{
+	dump_stack();
+}
+
+void
+xfs_error_report(
+	char		*tag,
+	int		level,
+	xfs_mount_t	*mp,
+	char		*fname,
+	int		linenum,
+	inst_t		*ra)
+{
+	if (level <= xfs_error_level) {
+		if (mp != NULL) {
+			xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
+				    CE_ALERT, mp,
+		"XFS internal error %s at line %d of file %s.  Caller 0x%x\n",
+				    tag, linenum, fname, ra);
+		} else {
+			cmn_err(CE_ALERT,
+		"XFS internal error %s at line %d of file %s.  Caller 0x%x\n",
+				tag, linenum, fname, ra);
+		}
+
+		xfs_stack_trace();
+	}
+}
+
+void
+xfs_hex_dump(void *p, int length)
+{
+	__uint8_t *uip = (__uint8_t*)p;
+	int	i;
+	char	sbuf[128], *s;
+	
+	s = sbuf;
+	*s = '\0';
+	for (i=0; i<length; i++, uip++) {
+		if ((i % 16) == 0) {
+			if (*s != '\0')
+				cmn_err(CE_ALERT, "%s\n", sbuf);
+			s = sbuf;
+			sprintf(s, "0x%x: ", i);
+			while( *s != '\0')
+				s++;
+		}
+		sprintf(s, "%02x ", *uip);
+
+		/*
+		 * the kernel sprintf is a void; user sprintf returns
+		 * the sprintf'ed string's length.  Find the new end-
+		 * of-string
+		 */
+		while( *s != '\0')
+			s++;
+	}
+	cmn_err(CE_ALERT, "%s\n", sbuf);
+}
+
+void
+xfs_corruption_error(
+	char		*tag,
+	int		level,
+	xfs_mount_t	*mp,
+	void		*p,
+	char		*fname,
+	int		linenum,
+	inst_t		*ra)
+{
+	xfs_hex_dump(p, 16);
+	xfs_error_report(tag, level, mp, fname, linenum, ra);
+}
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_error.h linux-2.5.65-bk3/fs/xfs/xfs_error.h
--- linux-2.5.65-bk2/fs/xfs/xfs_error.h	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_error.h	Mon Mar 31 12:41:45 2003
@@ -52,6 +52,39 @@
 #define XFS_ERROR(e)	(e)
 #endif
 
+struct xfs_mount;
+
+extern void
+xfs_error_report(
+	char		*tag,
+	int		level,
+	struct xfs_mount *mp,
+	char		*fname,
+	int		linenum,
+	inst_t		*ra);
+
+extern void
+xfs_corruption_error(
+	char		*tag,
+	int		level,
+	struct xfs_mount *mp,
+	void		*p,
+	char		*fname,
+	int		linenum,
+	inst_t		*ra);
+
+extern void
+xfs_hex_dump(void *p, int length);
+
+#define	XFS_ERROR_REPORT(e, lvl, mp)	\
+	xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
+#define	XFS_CORRUPTION_ERROR(e, lvl, mp, mem)	\
+	xfs_corruption_error(e, lvl, mp, mem, \
+			     __FILE__, __LINE__, __return_address)
+
+#define XFS_ERRLEVEL_OFF	0
+#define XFS_ERRLEVEL_LOW	1
+#define XFS_ERRLEVEL_HIGH	5
 
 /*
  * error injection tags - the labels can be anything you want
@@ -79,7 +112,8 @@
 #define XFS_ERRTAG_STRATREAD_IOERR			18
 #define XFS_ERRTAG_STRATCMPL_IOERR			19
 #define XFS_ERRTAG_DIOWRITE_IOERR			20
-#define XFS_ERRTAG_MAX					21
+#define XFS_ERRTAG_BMAPIFORMAT				21
+#define XFS_ERRTAG_MAX					22
 
 /*
  * Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
@@ -105,6 +139,7 @@
 #define XFS_RANDOM_STRATREAD_IOERR			(XFS_RANDOM_DEFAULT/10)
 #define XFS_RANDOM_STRATCMPL_IOERR			(XFS_RANDOM_DEFAULT/10)
 #define XFS_RANDOM_DIOWRITE_IOERR			(XFS_RANDOM_DEFAULT/10)
+#define	XFS_RANDOM_BMAPIFORMAT				XFS_RANDOM_DEFAULT
 
 #if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
 extern int	xfs_error_test(int, int *, char *, int, char *, unsigned long);
@@ -146,7 +181,7 @@
 #define		XFS_PTAG_IFLUSH			0x0000000000000001LL
 #define		XFS_PTAG_LOGRES			0x0000000000000002LL
 #define		XFS_PTAG_AILDELETE		0x0000000000000004LL
-#define		XFS_PTAG_AVAILABLE		0x0000000000000008LL
+#define		XFS_PTAG_ERROR_REPORT		0x0000000000000008LL
 #define		XFS_PTAG_SHUTDOWN_CORRUPT	0x0000000000000010LL
 #define		XFS_PTAG_SHUTDOWN_IOERROR	0x0000000000000020LL
 #define		XFS_PTAG_SHUTDOWN_LOGERROR	0x0000000000000040LL
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_ialloc.c linux-2.5.65-bk3/fs/xfs/xfs_ialloc.c
--- linux-2.5.65-bk2/fs/xfs/xfs_ialloc.c	Mon Mar 17 13:44:08 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_ialloc.c	Mon Mar 31 12:41:45 2003
@@ -1303,14 +1303,11 @@
 		INT_GET(agi->agi_magicnum, ARCH_CONVERT) == XFS_AGI_MAGIC &&
 		XFS_AGI_GOOD_VERSION(
 			INT_GET(agi->agi_versionnum, ARCH_CONVERT));
-	if (XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
-			XFS_RANDOM_IALLOC_READ_AGI)) {
+	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
+			XFS_RANDOM_IALLOC_READ_AGI))) {
+		XFS_CORRUPTION_ERROR("xfs_ialloc_read_agi", XFS_ERRLEVEL_LOW,
+				     mp, agi);
 		xfs_trans_brelse(tp, bp);
-#ifdef __KERNEL__	/* additional, temporary, debugging code */
-		cmn_err(CE_NOTE,
-			"EFSCORRUPTED returned from file %s line %d",
-			__FILE__, __LINE__);
-#endif
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	pag = &mp->m_perag[agno];
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_iget.c linux-2.5.65-bk3/fs/xfs/xfs_iget.c
--- linux-2.5.65-bk2/fs/xfs/xfs_iget.c	Mon Mar 17 13:44:48 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_iget.c	Mon Mar 31 12:41:45 2003
@@ -422,7 +422,6 @@
 		vp = LINVFS_GET_VP(inode);
 		if (inode->i_state & I_NEW) {
 inode_allocate:
-			XFS_STATS_INC(xfsstats.vn_alloc);
 			vn_initialize(inode);
 			error = xfs_iget_core(vp, mp, tp, ino,
 							lock_flags, ipp, bno);
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_inode.c linux-2.5.65-bk3/fs/xfs/xfs_inode.c
--- linux-2.5.65-bk2/fs/xfs/xfs_inode.c	Mon Mar 17 13:44:48 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_inode.c	Mon Mar 31 12:41:45 2003
@@ -31,6 +31,7 @@
  */
 
 #include <xfs.h>
+#include <asm/unaligned.h>	/* for get_unaligned, put_unaligned */
 
 
 kmem_zone_t *xfs_ifork_zone;
@@ -226,8 +227,9 @@
 	di_ok =
 		INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
 		XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
-	if (XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
-			XFS_RANDOM_ITOBP_INOTOBP)) {
+	if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
+			XFS_RANDOM_ITOBP_INOTOBP))) {
+		XFS_CORRUPTION_ERROR("xfs_inotobp", XFS_ERRLEVEL_LOW, mp, dip);
 		xfs_trans_brelse(tp, bp);
 		cmn_err(CE_WARN,
 	"xfs_inotobp: XFS_TEST_ERROR()	returned an "
@@ -369,13 +371,15 @@
 					(i << mp->m_sb.sb_inodelog));
 		di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
 			    XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
-		if (XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
-				 XFS_RANDOM_ITOBP_INOTOBP)) {
+		if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
+				 XFS_RANDOM_ITOBP_INOTOBP))) {
 #ifdef DEBUG
 			prdev("bad inode magic/vsn daddr 0x%llx #%d (magic=%x)",
 				mp->m_dev, (unsigned long long)imap.im_blkno, i,
 				INT_GET(dip->di_core.di_magic, ARCH_CONVERT));
 #endif
+			XFS_CORRUPTION_ERROR("xfs_itobp", XFS_ERRLEVEL_LOW,
+					     mp, dip);
 			xfs_trans_brelse(tp, bp);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
@@ -419,9 +423,10 @@
 		XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
 	error = 0;
 
-	if (INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) +
+	if (unlikely(
+	    INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) +
 		INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) >
-	    INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT)) {
+	    INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT))) {
 		xfs_fs_cmn_err(CE_WARN, ip->i_mount,
 			"corrupt dinode %Lu, extent total = %d, nblocks = %Lu."
 			"  Unmount and run xfs_repair.",
@@ -430,15 +435,19 @@
 			    + INT_GET(dip->di_core.di_anextents, ARCH_CONVERT)),
 			(unsigned long long)
 			INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT));
+		XFS_CORRUPTION_ERROR("xfs_iformat(1)", XFS_ERRLEVEL_LOW,
+				     ip->i_mount, dip);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
-	if (INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize) {
+	if (unlikely(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize)) {
 		xfs_fs_cmn_err(CE_WARN, ip->i_mount,
 			"corrupt dinode %Lu, forkoff = 0x%x."
 			"  Unmount and run xfs_repair.",
 			(unsigned long long)ip->i_ino,
 			(int)(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT)));
+		XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW,
+				     ip->i_mount, dip);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -447,8 +456,11 @@
 	case IFCHR:
 	case IFBLK:
 	case IFSOCK:
-		if (INT_GET(dip->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_DEV)
+		if (unlikely(INT_GET(dip->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_DEV)) {
+			XFS_CORRUPTION_ERROR("xfs_iformat(3)", XFS_ERRLEVEL_LOW,
+					      ip->i_mount, dip);
 			return XFS_ERROR(EFSCORRUPTED);
+		}
 		ip->i_d.di_size = 0;
 		ip->i_df.if_u2.if_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
 		break;
@@ -461,24 +473,26 @@
 			/*
 			 * no local regular files yet
 			 */
-			if ((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFREG) {
+			if (unlikely((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFREG)) {
 				xfs_fs_cmn_err(CE_WARN, ip->i_mount,
-					"corrupt inode "
-					"(local format for regular file) %Lu.  "
-					"Unmount and run xfs_repair.",
+					"corrupt inode (local format for regular file) %Lu.  Unmount and run xfs_repair.",
 					(unsigned long long) ip->i_ino);
+				XFS_CORRUPTION_ERROR("xfs_iformat(4)",
+						     XFS_ERRLEVEL_LOW,
+						     ip->i_mount, dip);
 				return XFS_ERROR(EFSCORRUPTED);
 			}
 
 			di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
-			if (di_size >
-			    XFS_DFORK_DSIZE_ARCH(dip, ip->i_mount, ARCH_CONVERT)) {
+			if (unlikely(di_size >
+			    XFS_DFORK_DSIZE_ARCH(dip, ip->i_mount, ARCH_CONVERT))) {
 				xfs_fs_cmn_err(CE_WARN, ip->i_mount,
-					"corrupt inode %Lu "
-					"(bad size %Ld for local inode).  "
-					"Unmount and run xfs_repair.",
+					"corrupt inode %Lu (bad size %Ld for local inode).  Unmount and run xfs_repair.",
 					(unsigned long long) ip->i_ino,
 					(long long) di_size);
+				XFS_CORRUPTION_ERROR("xfs_iformat(5)",
+						     XFS_ERRLEVEL_LOW,
+						     ip->i_mount, dip);
 				return XFS_ERROR(EFSCORRUPTED);
 			}
 
@@ -492,11 +506,14 @@
 			error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
 			break;
 		default:
+			XFS_ERROR_REPORT("xfs_iformat(6)", XFS_ERRLEVEL_LOW,
+					 ip->i_mount);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
 		break;
 
 	default:
+		XFS_ERROR_REPORT("xfs_iformat(7)", XFS_ERRLEVEL_LOW, ip->i_mount);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	if (error) {
@@ -557,13 +574,13 @@
 	 * is wrong and we just bail out rather than crash in
 	 * kmem_alloc() or memcpy() below.
 	 */
-	if (size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)) {
+	if (unlikely(size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT))) {
 		xfs_fs_cmn_err(CE_WARN, ip->i_mount,
-			"corrupt inode %Lu "
-			"(bad size %d for local fork, size = %d).  "
-			"Unmount and run xfs_repair.",
+			"corrupt inode %Lu (bad size %d for local fork, size = %d).  Unmount and run xfs_repair.",
 			(unsigned long long) ip->i_ino, size,
 			XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT));
+		XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW,
+				     ip->i_mount, dip);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -619,11 +636,12 @@
 	 * is wrong and we just bail out rather than crash in
 	 * kmem_alloc() or memcpy() below.
 	 */
-	if (size < 0 || size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)) {
+	if (unlikely(size < 0 || size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT))) {
 		xfs_fs_cmn_err(CE_WARN, ip->i_mount,
-			"corrupt inode %Lu ((a)extents = %d).  "
-			"Unmount and run xfs_repair.",
+			"corrupt inode %Lu ((a)extents = %d).  Unmount and run xfs_repair.",
 			(unsigned long long) ip->i_ino, nex);
+		XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW,
+				     ip->i_mount, dip);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -647,8 +665,10 @@
 		ep = ifp->if_u1.if_extents;
 #if ARCH_CONVERT != ARCH_NOCONVERT
 		for (i = 0; i < nex; i++, ep++, dp++) {
-			ep->l0 = INT_GET(dp->l0, ARCH_CONVERT);
-			ep->l1 = INT_GET(dp->l1, ARCH_CONVERT);
+			ep->l0 = INT_GET(get_unaligned((u64*)&dp->l0),
+								ARCH_CONVERT);
+			ep->l1 = INT_GET(get_unaligned((u64*)&dp->l1),
+								ARCH_CONVERT);
 		}
 #else
 		memcpy(ep, dp, size);
@@ -657,9 +677,13 @@
 			whichfork);
 		if (whichfork != XFS_DATA_FORK ||
 			XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
-				if (xfs_check_nostate_extents(
-				    ifp->if_u1.if_extents, nex))
+				if (unlikely(xfs_check_nostate_extents(
+				    ifp->if_u1.if_extents, nex))) {
+					XFS_ERROR_REPORT("xfs_iformat_extents(2)",
+							 XFS_ERRLEVEL_LOW,
+							 ip->i_mount);
 					return XFS_ERROR(EFSCORRUPTED);
+				}
 	}
 	ifp->if_flags |= XFS_IFEXTENTS;
 	return 0;
@@ -697,14 +721,15 @@
 	 * or the number of extents is greater than the number of
 	 * blocks.
 	 */
-	if (XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
+	if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
 	    || XFS_BMDR_SPACE_CALC(nrecs) >
 			XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)
-	    || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) {
+	    || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
 		xfs_fs_cmn_err(CE_WARN, ip->i_mount,
-			"corrupt inode %Lu (btree).  "
-			"Unmount and run xfs_repair.",
+			"corrupt inode %Lu (btree).  Unmount and run xfs_repair.",
 			(unsigned long long) ip->i_ino);
+		XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
+				 ip->i_mount);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -975,8 +1000,11 @@
 	xfs_ifork_t	*ifp;
 	size_t		size;
 
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
+	if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
+		XFS_ERROR_REPORT("xfs_iread_extents", XFS_ERRLEVEL_LOW,
+				 ip->i_mount);
 		return XFS_ERROR(EFSCORRUPTED);
+	}
 	size = XFS_IFORK_NEXTENTS(ip, whichfork) * (uint)sizeof(xfs_bmbt_rec_t);
 	ifp = XFS_IFORK_PTR(ip, whichfork);
 	/*
@@ -1817,8 +1845,9 @@
 	agi_ok =
 		INT_GET(agi->agi_magicnum, ARCH_CONVERT) == XFS_AGI_MAGIC &&
 		XFS_AGI_GOOD_VERSION(INT_GET(agi->agi_versionnum, ARCH_CONVERT));
-	if (XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK,
-			XFS_RANDOM_IUNLINK)) {
+	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK,
+			XFS_RANDOM_IUNLINK))) {
+		XFS_CORRUPTION_ERROR("xfs_iunlink", XFS_ERRLEVEL_LOW, mp, agi);
 		xfs_trans_brelse(tp, agibp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
@@ -1919,8 +1948,10 @@
 	agi_ok =
 		INT_GET(agi->agi_magicnum, ARCH_CONVERT) == XFS_AGI_MAGIC &&
 		XFS_AGI_GOOD_VERSION(INT_GET(agi->agi_versionnum, ARCH_CONVERT));
-	if (XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK_REMOVE,
-			XFS_RANDOM_IUNLINK_REMOVE)) {
+	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK_REMOVE,
+			XFS_RANDOM_IUNLINK_REMOVE))) {
+		XFS_CORRUPTION_ERROR("xfs_iunlink_remove", XFS_ERRLEVEL_LOW,
+				     mp, agi);
 		xfs_trans_brelse(tp, agibp);
 		cmn_err(CE_WARN,
 			"xfs_iunlink_remove: XFS_TEST_ERROR()  returned an error on %s.	 Returning EFSCORRUPTED.",
@@ -2676,8 +2707,10 @@
 
 #if ARCH_CONVERT != ARCH_NOCONVERT
 		/* Translate to on disk format */
-		dest_ep->l0 = INT_GET(ep->l0, ARCH_CONVERT);
-		dest_ep->l1 = INT_GET(ep->l1, ARCH_CONVERT);
+		put_unaligned(INT_GET(ep->l0, ARCH_CONVERT),
+			      (u64*)&dest_ep->l0);
+		put_unaligned(INT_GET(ep->l1, ARCH_CONVERT),
+			      (u64*)&dest_ep->l1);
 #else
 		*dest_ep = *ep;
 #endif
@@ -2745,7 +2778,9 @@
 			memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
 		}
 		if (whichfork == XFS_DATA_FORK) {
-			if (XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip)) {
+			if (unlikely(XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip))) {
+				XFS_ERROR_REPORT("xfs_iflush_fork",
+						 XFS_ERRLEVEL_LOW, mp);
 				return XFS_ERROR(EFSCORRUPTED);
 			}
 		}
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_log.c linux-2.5.65-bk3/fs/xfs/xfs_log.c
--- linux-2.5.65-bk2/fs/xfs/xfs_log.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_log.c	Mon Mar 31 12:41:45 2003
@@ -62,10 +62,6 @@
 /* local state machine functions */
 STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int);
 STATIC void xlog_state_do_callback(xlog_t *log,int aborted, xlog_in_core_t *iclog);
-static inline void xlog_state_finish_copy(xlog_t	*log,
-					xlog_in_core_t	*iclog,
-					int		first_write,
-					int		bytes);
 STATIC int  xlog_state_get_iclog_space(xlog_t		*log,
 				       int		len,
 				       xlog_in_core_t	**iclog,
@@ -876,7 +872,7 @@
  * We may be holding the log iclog lock upon entering this routine.
  */
 xfs_lsn_t
-xlog_assign_tail_lsn(xfs_mount_t *mp, xlog_in_core_t *iclog)
+xlog_assign_tail_lsn(xfs_mount_t *mp)
 {
 	xfs_lsn_t tail_lsn;
 	SPLDECL(s);
@@ -888,8 +884,6 @@
 		log->l_tail_lsn = tail_lsn;
 	else
 		tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn;
-	if (iclog)
-		INT_SET(iclog->ic_header.h_tail_lsn, ARCH_CONVERT, tail_lsn);
 	GRANT_UNLOCK(log, s);
 
 	return tail_lsn;
@@ -1402,7 +1396,7 @@
 {
 	xfs_caddr_t	dptr;		/* pointer to byte sized element */
 	xfs_buf_t	*bp;
-	int		i;
+	int		i, ops;
 	uint		roundup;
 	uint		count;		/* byte count of bwrite */
 	int		split = 0;	/* split write into two regions */
@@ -1439,7 +1433,12 @@
 	log->l_roundoff += iclog->ic_roundoff;
 
 	xlog_pack_data(log, iclog);	  /* put cycle number in every block */
-	INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);	/* real byte length */
+
+	/* real byte length */
+	INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
+	/* put ops count in correct order */
+	ops = iclog->ic_header.h_num_logops;
+	INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops);
 
 	bp	    = iclog->ic_bp;
 	ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
@@ -1596,6 +1595,28 @@
 	kmem_free(log, sizeof(xlog_t));
 }	/* xlog_unalloc_log */
 
+/*
+ * Update counters atomically now that memcpy is done.
+ */
+/* ARGSUSED */
+static inline void
+xlog_state_finish_copy(xlog_t		*log,
+		       xlog_in_core_t	*iclog,
+		       int		record_cnt,
+		       int		copy_bytes)
+{
+	SPLDECL(s);
+
+	s = LOG_LOCK(log);
+
+	iclog->ic_header.h_num_logops += record_cnt;
+	iclog->ic_offset += copy_bytes;
+
+	LOG_UNLOCK(log, s);
+}	/* xlog_state_finish_copy */
+
+
+
 
 /*
  * Write some region out to in-core log
@@ -1663,6 +1684,7 @@
     int		     contwr;	     /* continued write of in-core log? */
     int		     firstwr = 0;    /* first write of transaction */
     int		     error;
+    int		     record_cnt = 0, data_cnt = 0;
 
     partial_copy_len = partial_copy = 0;
 
@@ -1725,7 +1747,8 @@
 		logop_head->oh_flags	= XLOG_START_TRANS;
 		INT_ZERO(logop_head->oh_res2, ARCH_CONVERT);
 		ticket->t_flags		&= ~XLOG_TIC_INITED;	/* clear bit */
-		firstwr++;			  /* increment log ops below */
+		firstwr = 1;			  /* increment log ops below */
+		record_cnt++;
 
 		start_rec_copy = sizeof(xlog_op_header_t);
 		xlog_write_adv_cnt(ptr, len, log_offset, start_rec_copy);
@@ -1793,10 +1816,13 @@
 
 	    /* make copy_len total bytes copied, including headers */
 	    copy_len += start_rec_copy + sizeof(xlog_op_header_t);
-	    xlog_state_finish_copy(log, iclog, firstwr, (contwr? copy_len : 0));
+	    record_cnt++;
+	    data_cnt += contwr ? copy_len : 0;
 	    firstwr = 0;
 	    if (partial_copy) {			/* copied partial region */
 		    /* already marked WANT_SYNC by xlog_state_get_iclog_space */
+		    xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
+		    record_cnt = data_cnt = 0;
 		    if ((error = xlog_state_release_iclog(log, iclog)))
 			    return (error);
 		    break;			/* don't increment index */
@@ -1805,6 +1831,8 @@
 		partial_copy_len = partial_copy = 0;
 
 		if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) {
+		    xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
+		    record_cnt = data_cnt = 0;
 		    xlog_state_want_sync(log, iclog);
 		    if (commit_iclog) {
 			ASSERT(flags & XLOG_COMMIT_TRANS);
@@ -1821,6 +1849,7 @@
     } /* for (index = 0; index < nentries; ) */
     ASSERT(len == 0);
 
+    xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
     if (commit_iclog) {
 	ASSERT(flags & XLOG_COMMIT_TRANS);
 	*commit_iclog = iclog;
@@ -2208,30 +2237,6 @@
 
 
 /*
- * Update counters atomically now that memcpy is done.
- */
-/* ARGSUSED */
-static inline void
-xlog_state_finish_copy(xlog_t		*log,
-		       xlog_in_core_t	*iclog,
-		       int		first_write,
-		       int		copy_bytes)
-{
-	SPLDECL(s);
-
-	s = LOG_LOCK(log);
-
-	if (first_write)
-		INT_MOD(iclog->ic_header.h_num_logops, ARCH_CONVERT, +1);
-	INT_MOD(iclog->ic_header.h_num_logops, ARCH_CONVERT, +1);
-	iclog->ic_offset += copy_bytes;
-
-	LOG_UNLOCK(log, s);
-}	/* xlog_state_finish_copy */
-
-
-
-/*
  * If the head of the in-core log ring is not (ACTIVE or DIRTY), then we must
  * sleep.  The flush semaphore is set to the number of in-core buffers and
  * decremented around disk syncing.  Therefore, if all buffers are syncing,
@@ -2722,7 +2727,7 @@
 	SPLDECL(s);
 	int		sync = 0;	/* do we sync? */
 
-	xlog_assign_tail_lsn(log->l_mp, 0);
+	xlog_assign_tail_lsn(log->l_mp);
 
 	s = LOG_LOCK(log);
 
@@ -3594,7 +3599,10 @@
 
 	iclog = log->l_iclog;
 	do {
-		if (INT_GET(iclog->ic_header.h_num_logops, ARCH_CONVERT))
+		/* endianness does not matter here, zero is zero in
+		 * any language.
+		 */
+		if (iclog->ic_header.h_num_logops)
 			return(0);
 		iclog = iclog->ic_next;
 	} while (iclog != log->l_iclog);
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_log_priv.h linux-2.5.65-bk3/fs/xfs/xfs_log_priv.h
--- linux-2.5.65-bk2/fs/xfs/xfs_log_priv.h	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_log_priv.h	Mon Mar 31 12:41:45 2003
@@ -536,8 +536,7 @@
 
 
 /* common routines */
-extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp,
-				      xlog_in_core_t *iclog);
+extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
 extern int	 xlog_find_head(xlog_t *log, xfs_daddr_t *head_blk);
 extern int	 xlog_find_tail(xlog_t	*log,
 				xfs_daddr_t *head_blk,
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_log_recover.c linux-2.5.65-bk3/fs/xfs/xfs_log_recover.c
--- linux-2.5.65-bk2/fs/xfs/xfs_log_recover.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_log_recover.c	Mon Mar 31 12:41:45 2003
@@ -166,17 +166,21 @@
      * a dirty log created in IRIX.
      */
 
-    if (INT_GET(head->h_fmt, ARCH_CONVERT) != XLOG_FMT) {
+    if (unlikely(INT_GET(head->h_fmt, ARCH_CONVERT) != XLOG_FMT)) {
 	xlog_warn("XFS: dirty log written in incompatible format - can't recover");
 #ifdef DEBUG
 	xlog_header_check_dump(mp, head);
 #endif
+	XFS_ERROR_REPORT("xlog_header_check_recover(1)",
+			 XFS_ERRLEVEL_HIGH, mp);
 	return XFS_ERROR(EFSCORRUPTED);
-    } else if (!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid)) {
+    } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) {
 	xlog_warn("XFS: dirty log entry has mismatched uuid - can't recover");
 #ifdef DEBUG
 	xlog_header_check_dump(mp, head);
 #endif
+	XFS_ERROR_REPORT("xlog_header_check_recover(2)",
+			 XFS_ERRLEVEL_HIGH, mp);
 	return XFS_ERROR(EFSCORRUPTED);
     }
 
@@ -202,11 +206,13 @@
 
 	xlog_warn("XFS: nil uuid in log - IRIX style log");
 
-    } else if (!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid)) {
+    } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) {
 	xlog_warn("XFS: log has mismatched uuid - can't recover");
 #ifdef DEBUG
 	xlog_header_check_dump(mp, head);
 #endif
+	XFS_ERROR_REPORT("xlog_header_check_mount",
+			 XFS_ERRLEVEL_HIGH, mp);
 	return XFS_ERROR(EFSCORRUPTED);
     }
 
@@ -1113,8 +1119,11 @@
 		 * the distance from the beginning of the log to the
 		 * tail.
 		 */
-		if (head_block < tail_block || head_block >= log->l_logBBsize)
+		if (unlikely(head_block < tail_block || head_block >= log->l_logBBsize)) {
+			XFS_ERROR_REPORT("xlog_clear_stale_blocks(1)",
+					 XFS_ERRLEVEL_LOW, log->l_mp);
 			return XFS_ERROR(EFSCORRUPTED);
+		}
 		tail_distance = tail_block + (log->l_logBBsize - head_block);
 	} else {
 		/*
@@ -1122,8 +1131,11 @@
 		 * so the distance from the head to the tail is just
 		 * the tail block minus the head block.
 		 */
-		if (head_block >= tail_block || head_cycle != (tail_cycle + 1))
+		if (unlikely(head_block >= tail_block || head_cycle != (tail_cycle + 1))){
+			XFS_ERROR_REPORT("xlog_clear_stale_blocks(2)",
+					 XFS_ERRLEVEL_LOW, log->l_mp);
 			return XFS_ERROR(EFSCORRUPTED);
+		}
 		tail_distance = tail_block - head_block;
 	}
 
@@ -1732,10 +1744,12 @@
 		logged_nextp = (xfs_agino_t *)
 			       ((char *)(item->ri_buf[item_index].i_addr) +
 				(next_unlinked_offset - reg_buf_offset));
-		if (*logged_nextp == 0)	 {
+		if (unlikely(*logged_nextp == 0)) {
 			xfs_fs_cmn_err(CE_ALERT, mp,
 				"bad inode buffer log record (ptr = 0x%p, bp = 0x%p).  XFS trying to replay bad (0) inode di_next_unlinked field",
 				item, bp);
+			XFS_ERROR_REPORT("xlog_recover_do_inode_buf",
+					 XFS_ERRLEVEL_LOW, mp);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
 
@@ -1933,6 +1947,8 @@
 		xfs_fs_cmn_err(CE_ALERT, log->l_mp,
 			"xfs_log_recover: unknown buffer type 0x%x, dev 0x%x",
 			buf_f->blf_type, log->l_dev);
+		XFS_ERROR_REPORT("xlog_recover_do_buffer_trans",
+				 XFS_ERRLEVEL_LOW, log->l_mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -2038,7 +2054,6 @@
 		imap.im_blkno = 0;
 		xfs_imap(log->l_mp, 0, ino, &imap, 0);
 	}
-
 	bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len,
 								XFS_BUF_LOCK);
 	if (XFS_BUF_ISERROR(bp)) {
@@ -2049,7 +2064,6 @@
 		return error;
 	}
 	error = 0;
-	xfs_inobp_check(mp, bp);
 	ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
 	dip = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
 
@@ -2057,34 +2071,42 @@
 	 * Make sure the place we're flushing out to really looks
 	 * like an inode!
 	 */
-	if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
+	if (unlikely(INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC)) {
 		xfs_buf_relse(bp);
 		xfs_fs_cmn_err(CE_ALERT, mp,
 			"xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld",
 			dip, bp, ino);
+		XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)",
+				 XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
-	if (dicp->di_magic != XFS_DINODE_MAGIC) {
+	if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
 		xfs_buf_relse(bp);
 		xfs_fs_cmn_err(CE_ALERT, mp,
 			"xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld",
 			item, ino);
+		XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)",
+				 XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
-	if ((dicp->di_mode & IFMT) == IFREG) {
+	if (unlikely((dicp->di_mode & IFMT) == IFREG)) {
 		if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
 		    (dicp->di_format != XFS_DINODE_FMT_BTREE)) {
+			XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(3)",
+					 XFS_ERRLEVEL_LOW, mp, dicp);
 			xfs_buf_relse(bp);
 			xfs_fs_cmn_err(CE_ALERT, mp,
 				"xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
 				item, dip, bp, ino);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
-	} else if ((dicp->di_mode & IFMT) == IFDIR) {
+	} else if (unlikely((dicp->di_mode & IFMT) == IFDIR)) {
 		if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
 		    (dicp->di_format != XFS_DINODE_FMT_BTREE) &&
 		    (dicp->di_format != XFS_DINODE_FMT_LOCAL)) {
+			XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(4)",
+					     XFS_ERRLEVEL_LOW, mp, dicp);
 			xfs_buf_relse(bp);
 			xfs_fs_cmn_err(CE_ALERT, mp,
 				"xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
@@ -2092,7 +2114,9 @@
 			return XFS_ERROR(EFSCORRUPTED);
 		}
 	}
-	if (dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks) {
+	if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){
+		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(5)",
+				     XFS_ERRLEVEL_LOW, mp, dicp);
 		xfs_buf_relse(bp);
 		xfs_fs_cmn_err(CE_ALERT, mp,
 			"xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
@@ -2101,14 +2125,18 @@
 			dicp->di_nblocks);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
-	if (dicp->di_forkoff > mp->m_sb.sb_inodesize) {
+	if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) {
+		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)",
+				     XFS_ERRLEVEL_LOW, mp, dicp);
 		xfs_buf_relse(bp);
 		xfs_fs_cmn_err(CE_ALERT, mp,
 			"xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
 			item, dip, bp, ino, dicp->di_forkoff);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
-	if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) {
+	if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) {
+		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
+				     XFS_ERRLEVEL_LOW, mp, dicp);
 		xfs_buf_relse(bp);
 		xfs_fs_cmn_err(CE_ALERT, mp,
 			"xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
@@ -2207,14 +2235,6 @@
 
 
 write_inode_buffer:
-#if 0
-	/*
-	 * Can't do this if the transaction didn't log the current
-	 * contents, e.g. rmdir.
-	 */
-	XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip);
-#endif
-	xfs_inobp_check(mp, bp);
 	if (ITEM_TYPE(item) == XFS_LI_INODE) {
 		ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
 		       XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
@@ -3238,10 +3258,12 @@
 	    ASSERT(BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) <= INT_MAX));
 	    bblks = (int) BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));	/* blocks in data section */
 
-	    if ((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) ||
+	    if (unlikely((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) ||
 		(BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) > INT_MAX)) ||
 		(bblks <= 0) ||
-		(blk_no > log->l_logBBsize)) {
+		(blk_no > log->l_logBBsize))) {
+		    XFS_ERROR_REPORT("xlog_do_recovery_pass(1)",
+				     XFS_ERRLEVEL_LOW, log->l_mp);
 		    error = EFSCORRUPTED;
 		    goto bread_err2;
 	    }
@@ -3307,9 +3329,11 @@
 	    ASSERT(bblks > 0);
 	    blk_no += hblks;			/* successfully read header */
 
-	    if ((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) ||
+	    if (unlikely((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) ||
 		(BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) > INT_MAX)) ||
-		(bblks <= 0)) {
+		(bblks <= 0))) {
+		    XFS_ERROR_REPORT("xlog_do_recovery_pass(2)",
+				     XFS_ERRLEVEL_LOW, log->l_mp);
 		    error = EFSCORRUPTED;
 		    goto bread_err2;
 	    }
@@ -3472,7 +3496,7 @@
 	 * or iunlinks they will have some entries in the AIL; so we look at
 	 * the AIL to determine how to set the tail_lsn.
 	 */
-	xlog_assign_tail_lsn(log->l_mp, NULL);
+	xlog_assign_tail_lsn(log->l_mp);
 
 	/*
 	 * Now that we've finished replaying all buffer and inode
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_macros.h linux-2.5.65-bk3/fs/xfs/xfs_macros.h
--- linux-2.5.65-bk2/fs/xfs/xfs_macros.h	Mon Mar 17 13:43:42 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_macros.h	Mon Mar 31 12:41:45 2003
@@ -33,13 +33,12 @@
 #define __XFS_MACROS_H__
 
 /*
- * Set for debug kernels and simulation, and 32-bit kernels,
- * but not for standalone.  These replacements save space.
+ * Set for debug kernels and simulation
+ * These replacements save space.
  * Used in xfs_macros.c.
  */
 #define XFS_WANT_SPACE_C	\
-	(!defined(_STANDALONE) && \
-	 (defined(DEBUG) || (defined(_KERNEL))))
+	(!defined(_STANDALONE) && defined(DEBUG))
 
 /*
  * Set for debug simulation and kernel builds, but not for standalone.
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_mount.c linux-2.5.65-bk3/fs/xfs/xfs_mount.c
--- linux-2.5.65-bk2/fs/xfs/xfs_mount.c	Mon Mar 17 13:44:02 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_mount.c	Mon Mar 31 12:41:45 2003
@@ -205,13 +205,17 @@
 		return XFS_ERROR(EWRONGFS);
 	}
 
-	if (sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp) {
+	if (unlikely(sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
 		cmn_err(CE_WARN, "XFS: filesystem is marked as having an external log; specify logdev on the\nmount command line.");
+		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(1)",
+				     XFS_ERRLEVEL_HIGH, mp, sbp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
-	if (sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp) {
+	if (unlikely(sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
 		cmn_err(CE_WARN, "XFS: filesystem is marked as having an internal log; don't specify logdev on\nthe mount command line.");
+		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(2)",
+				     XFS_ERRLEVEL_HIGH, mp, sbp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -219,7 +223,8 @@
 	 * More sanity checking. These were stolen directly from
 	 * xfs_repair.
 	 */
-	if (sbp->sb_agcount <= 0					||
+	if (unlikely(
+	    sbp->sb_agcount <= 0					||
 	    sbp->sb_sectsize < XFS_MIN_SECTORSIZE			||
 	    sbp->sb_sectsize > XFS_MAX_SECTORSIZE			||
 	    sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG			||
@@ -232,20 +237,25 @@
 	    sbp->sb_inodesize > XFS_DINODE_MAX_SIZE			||
 	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
-	    sbp->sb_imax_pct > 100) {
+	    sbp->sb_imax_pct > 100)) {
 		cmn_err(CE_WARN, "XFS: SB sanity check 1 failed");
+		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)",
+				     XFS_ERRLEVEL_LOW, mp, sbp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
 	/*
 	 * Sanity check AG count, size fields against data size field
 	 */
-	if (sbp->sb_dblocks == 0 ||
+	if (unlikely(
+	    sbp->sb_dblocks == 0 ||
 	    sbp->sb_dblocks >
 	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
 	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
-			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS) {
+			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
 		cmn_err(CE_WARN, "XFS: SB sanity check 2 failed");
+		XFS_ERROR_REPORT("xfs_mount_validate_sb(4)",
+				 XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -257,8 +267,10 @@
 	}
 #endif
 
-	if (sbp->sb_inprogress) {
+	if (unlikely(sbp->sb_inprogress)) {
 		cmn_err(CE_WARN, "XFS: file system busy");
+		XFS_ERROR_REPORT("xfs_mount_validate_sb(5)",
+				 XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -636,7 +648,6 @@
 				error = XFS_ERROR(EINVAL);
 				goto error1;
 			}
-			mp->m_dalign = mp->m_swidth = 0;
 		} else {
 			/*
 			 * Convert the stripe unit and width to FSBs.
@@ -915,7 +926,7 @@
 	/*
 	 * log's mount-time initialization. Perform 1st part recovery if needed
 	 */
-	if (sbp->sb_logblocks > 0) {		/* check for volume case */
+	if (likely(sbp->sb_logblocks > 0)) {	/* check for volume case */
 		error = xfs_log_mount(mp, mp->m_logdev_targp->pbr_dev,
 				      XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
 				      XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
@@ -925,6 +936,7 @@
 		}
 	} else {	/* No log has been defined */
 		cmn_err(CE_WARN, "XFS: no log defined");
+		XFS_ERROR_REPORT("xfs_mountfs_int(1)", XFS_ERRLEVEL_LOW, mp);
 		error = XFS_ERROR(EFSCORRUPTED);
 		goto error2;
 	}
@@ -941,7 +953,7 @@
 
 	ASSERT(rip != NULL);
 	rvp = XFS_ITOV(rip);
-	if ((rip->i_d.di_mode & IFMT) != IFDIR) {
+	if (unlikely((rip->i_d.di_mode & IFMT) != IFDIR)) {
 		cmn_err(CE_WARN, "XFS: corrupted root inode");
 		VMAP(rvp, vmap);
 		prdev("Root inode %llu is not a directory",
@@ -949,6 +961,8 @@
 		xfs_iunlock(rip, XFS_ILOCK_EXCL);
 		VN_RELE(rvp);
 		vn_purge(rvp, &vmap);
+		XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
+				 mp);
 		error = XFS_ERROR(EFSCORRUPTED);
 		goto error3;
 	}
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_qm.c linux-2.5.65-bk3/fs/xfs/xfs_qm.c
--- linux-2.5.65-bk2/fs/xfs/xfs_qm.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_qm.c	Mon Mar 31 12:41:45 2003
@@ -444,16 +444,22 @@
 			xfs_iflock(uqp);
 			error = xfs_iflush(uqp, XFS_IFLUSH_SYNC);
 			xfs_iunlock(uqp, XFS_ILOCK_EXCL);
-			if (error == EFSCORRUPTED)
+			if (unlikely(error == EFSCORRUPTED)) {
+				XFS_ERROR_REPORT("xfs_qm_unmount_quotas(1)",
+						 XFS_ERRLEVEL_LOW, mp);
 				goto out;
+			}
 		}
 		if ((gqp = mp->m_quotainfo->qi_gquotaip) != NULL) {
 			xfs_ilock(gqp, XFS_ILOCK_EXCL);
 			xfs_iflock(gqp);
 			error = xfs_iflush(gqp, XFS_IFLUSH_SYNC);
 			xfs_iunlock(gqp, XFS_ILOCK_EXCL);
-			if (error == EFSCORRUPTED)
+			if (unlikely(error == EFSCORRUPTED)) {
+				XFS_ERROR_REPORT("xfs_qm_unmount_quotas(2)",
+						 XFS_ERRLEVEL_LOW, mp);
 				goto out;
+			}
 		}
 	}
 	if (uqp) {
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_rename.c linux-2.5.65-bk3/fs/xfs/xfs_rename.c
--- linux-2.5.65-bk2/fs/xfs/xfs_rename.c	Mon Mar 17 13:44:06 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_rename.c	Mon Mar 31 12:41:45 2003
@@ -467,9 +467,6 @@
 		}
 		target_ip_dropped = 1;
 
-		/* Do this test while we still hold the locks */
-		target_link_zero = (target_ip)->i_d.di_nlink==0;
-
 		if (src_is_directory) {
 			/*
 			 * Drop the link from the old "." entry.
@@ -481,6 +478,9 @@
 			}
 		}
 
+		/* Do this test while we still hold the locks */
+		target_link_zero = (target_ip)->i_d.di_nlink==0;
+
 	} /* target_ip != NULL */
 
 	/*
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_types.h linux-2.5.65-bk3/fs/xfs/xfs_types.h
--- linux-2.5.65-bk2/fs/xfs/xfs_types.h	Mon Mar 17 13:43:49 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_types.h	Mon Mar 31 12:41:45 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -34,8 +34,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/types.h>
-
 /*
  * POSIX Extensions
  */
@@ -56,9 +54,7 @@
 typedef signed long long int	__int64_t;
 typedef unsigned long long int	__uint64_t;
 
-typedef enum { B_FALSE, B_TRUE } boolean_t;
-
-
+typedef enum { B_FALSE,B_TRUE }	boolean_t;
 typedef __int64_t		prid_t;		/* project ID */
 typedef __uint32_t		inst_t;		/* an instruction */
 
@@ -68,12 +64,6 @@
 typedef char *			xfs_caddr_t;	/* <core address> type */
 typedef __u32			xfs_dev_t;
 
-typedef struct timespec		timespec_t;
-
-typedef struct {
-	unsigned char	__u_bits[16];
-} uuid_t;
-
 /* __psint_t is the same size as a pointer */
 #if (BITS_PER_LONG == 32)
 typedef __int32_t __psint_t;
@@ -185,6 +175,18 @@
  */
 #define MAXNAMELEN	256
 
+typedef struct xfs_dirent {		/* data from readdir() */
+	xfs_ino_t	d_ino;		/* inode number of entry */
+	xfs_off_t	d_off;		/* offset of disk directory entry */
+	unsigned short	d_reclen;	/* length of this record */
+	char		d_name[1];	/* name of file */
+} xfs_dirent_t;
+
+#define DIRENTBASESIZE		(((xfs_dirent_t *)0)->d_name - (char *)0)
+#define DIRENTSIZE(namelen)	\
+	((DIRENTBASESIZE + (namelen) + \
+		sizeof(xfs_off_t)) & ~(sizeof(xfs_off_t) - 1))
+
 typedef enum {
 	XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi
 } xfs_lookup_t;
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_vfsops.c linux-2.5.65-bk3/fs/xfs/xfs_vfsops.c
--- linux-2.5.65-bk2/fs/xfs/xfs_vfsops.c	Mon Mar 17 13:43:45 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_vfsops.c	Mon Mar 31 12:41:45 2003
@@ -1582,7 +1582,6 @@
 
 vfsops_t xfs_vfsops = {
 	.vfs_mount		= xfs_mount,
-	.vfs_dounmount		= fs_dounmount,
 	.vfs_unmount		= xfs_unmount,
 	.vfs_root		= xfs_root,
 	.vfs_statvfs		= xfs_statvfs,
diff -urN linux-2.5.65-bk2/fs/xfs/xfs_vnodeops.c linux-2.5.65-bk3/fs/xfs/xfs_vnodeops.c
--- linux-2.5.65-bk2/fs/xfs/xfs_vnodeops.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/fs/xfs/xfs_vnodeops.c	Mon Mar 31 12:41:45 2003
@@ -72,7 +72,8 @@
 	 */
 	if (vp->v_type == VDIR && ip->i_d.di_nextents > 0) {
 		mode = xfs_ilock_map_shared(ip);
-		(void)xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK);
+		if (ip->i_d.di_nextents > 0)
+			(void)xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK);
 		xfs_iunlock(ip, mode);
 	}
 	return 0;
@@ -125,7 +126,8 @@
 	 * Quick exit for non-stat callers
 	 */
 	if ((vap->va_mask &
-	    ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK)) == 0) {
+	    ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID|
+	      XFS_AT_NLINK|XFS_AT_BLKSIZE)) == 0) {
 		if (!(flags & ATTR_LAZY))
 			xfs_iunlock(ip, XFS_ILOCK_SHARED);
 		return 0;
@@ -1919,6 +1921,7 @@
 	xfs_bmap_free_t		free_list;
 	xfs_fsblock_t		first_block;
 	boolean_t		dp_joined_to_trans;
+	int			dm_event_sent = 0;
 	uint			cancel_flags;
 	int			committed;
 	xfs_prid_t		prid;
@@ -1943,15 +1946,16 @@
 				dm_di_mode, 0, 0);
 		if (error)
 			return error;
+		dm_event_sent = 1;
 	}
 
-	/* Return through std_return after this point. */
-
 	mp = dp->i_mount;
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
 
+	/* Return through std_return after this point. */
+
 	udqp = gdqp = NULL;
 	if (vap->va_mask & XFS_AT_PROJID)
 		prid = (xfs_prid_t)vap->va_projid;
@@ -2111,12 +2115,12 @@
 	/* Fallthrough to std_return with error = 0  */
 
 std_return:
-	if ((error != 0) &&
+	if ( (*vpp || (error != 0 && dm_event_sent != 0)) &&
 			DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp),
 							DM_EVENT_POSTCREATE)) {
 		(void) dm_send_namesp_event(DM_EVENT_POSTCREATE,
 			dir_bdp, DM_RIGHT_NULL,
-			vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops),
+			*vpp ? vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops):NULL,
 			DM_RIGHT_NULL, name, NULL,
 			dm_di_mode, error, 0);
 	}
@@ -2838,6 +2842,7 @@
 	vnode_t			*dir_vp;
 	boolean_t		dp_joined_to_trans;
 	boolean_t		created = B_FALSE;
+	int			dm_event_sent = 0;
 	xfs_prid_t		prid;
 	xfs_dquot_t		*udqp, *gdqp;
 	uint			resblks;
@@ -2864,6 +2869,7 @@
 					dm_di_mode, 0, 0);
 		if (error)
 			return error;
+		dm_event_sent = 1;
 	}
 
 	/* Return through std_return after this point. */
@@ -3026,7 +3032,7 @@
 	 * xfs_trans_commit. */
 
 std_return:
-	if ( (created || (error != 0)) &&
+	if ( (created || (error != 0 && dm_event_sent != 0)) &&
 			DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp),
 						DM_EVENT_POSTCREATE)) {
 		(void) dm_send_namesp_event(DM_EVENT_POSTCREATE,
diff -urN linux-2.5.65-bk2/fs/xfs/xfsidbg.c linux-2.5.65-bk3/fs/xfs/xfsidbg.c
--- linux-2.5.65-bk2/fs/xfs/xfsidbg.c	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk3/fs/xfs/xfsidbg.c	Mon Mar 31 12:41:45 2003
@@ -4162,8 +4162,6 @@
 			}
 			if (!(ip->i_flags & XFS_IQUIESCE)) {
 				kdb_printf("ip 0x%p not quiesced\n", ip);
-			} else if (!BHV_IS_WRITE_LOCKED(VN_BHV_HEAD(XFS_ITOV(ip)))) {
-				kdb_printf("ip 0x%p not write locked\n", ip);
 			}
 			ip = ip->i_mnext;
 		} while (ip != mp->m_inodes);
diff -urN linux-2.5.65-bk2/include/asm-alpha/core_cia.h linux-2.5.65-bk3/include/asm-alpha/core_cia.h
--- linux-2.5.65-bk2/include/asm-alpha/core_cia.h	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/include/asm-alpha/core_cia.h	Mon Mar 31 12:41:45 2003
@@ -293,7 +293,8 @@
 #ifdef __KERNEL__
 
 #ifndef __EXTERN_INLINE
-#define __EXTERN_INLINE static inline
+/* Do not touch, this should *NOT* be static inline */
+#define __EXTERN_INLINE extern inline
 #define __IO_EXTERN_INLINE
 #endif
 
diff -urN linux-2.5.65-bk2/include/asm-i386/mach-default/pci-functions.h linux-2.5.65-bk3/include/asm-i386/mach-default/pci-functions.h
--- linux-2.5.65-bk2/include/asm-i386/mach-default/pci-functions.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/include/asm-i386/mach-default/pci-functions.h	Mon Mar 31 12:41:45 2003
@@ -0,0 +1,19 @@
+/*
+ *	PCI BIOS function numbering for conventional PCI BIOS 
+ *	systems
+ */
+
+#define PCIBIOS_PCI_FUNCTION_ID 	0xb1XX
+#define PCIBIOS_PCI_BIOS_PRESENT 	0xb101
+#define PCIBIOS_FIND_PCI_DEVICE		0xb102
+#define PCIBIOS_FIND_PCI_CLASS_CODE	0xb103
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE	0xb106
+#define PCIBIOS_READ_CONFIG_BYTE	0xb108
+#define PCIBIOS_READ_CONFIG_WORD	0xb109
+#define PCIBIOS_READ_CONFIG_DWORD	0xb10a
+#define PCIBIOS_WRITE_CONFIG_BYTE	0xb10b
+#define PCIBIOS_WRITE_CONFIG_WORD	0xb10c
+#define PCIBIOS_WRITE_CONFIG_DWORD	0xb10d
+#define PCIBIOS_GET_ROUTING_OPTIONS	0xb10e
+#define PCIBIOS_SET_PCI_HW_INT		0xb10f
+
diff -urN linux-2.5.65-bk2/include/asm-i386/mach-pc9800/pci-functions.h linux-2.5.65-bk3/include/asm-i386/mach-pc9800/pci-functions.h
--- linux-2.5.65-bk2/include/asm-i386/mach-pc9800/pci-functions.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/include/asm-i386/mach-pc9800/pci-functions.h	Mon Mar 31 12:41:45 2003
@@ -0,0 +1,20 @@
+/*
+ *	PCI BIOS function codes for the PC9800. Different to
+ *	standard PC systems
+ */
+
+/* Note: PC-9800 confirms PCI 2.1 on only few models */
+
+#define PCIBIOS_PCI_FUNCTION_ID 	0xccXX
+#define PCIBIOS_PCI_BIOS_PRESENT 	0xcc81
+#define PCIBIOS_FIND_PCI_DEVICE		0xcc82
+#define PCIBIOS_FIND_PCI_CLASS_CODE	0xcc83
+/*      PCIBIOS_GENERATE_SPECIAL_CYCLE	0xcc86	(not supported by bios) */
+#define PCIBIOS_READ_CONFIG_BYTE	0xcc88
+#define PCIBIOS_READ_CONFIG_WORD	0xcc89
+#define PCIBIOS_READ_CONFIG_DWORD	0xcc8a
+#define PCIBIOS_WRITE_CONFIG_BYTE	0xcc8b
+#define PCIBIOS_WRITE_CONFIG_WORD	0xcc8c
+#define PCIBIOS_WRITE_CONFIG_DWORD	0xcc8d
+#define PCIBIOS_GET_ROUTING_OPTIONS	0xcc8e	/* PCI 2.1 only */
+#define PCIBIOS_SET_PCI_HW_INT		0xcc8f	/* PCI 2.1 only */
diff -urN linux-2.5.65-bk2/include/asm-i386/mach-pc9800/setup_arch_post.h linux-2.5.65-bk3/include/asm-i386/mach-pc9800/setup_arch_post.h
--- linux-2.5.65-bk2/include/asm-i386/mach-pc9800/setup_arch_post.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/include/asm-i386/mach-pc9800/setup_arch_post.h	Mon Mar 31 12:41:45 2003
@@ -0,0 +1,29 @@
+/**
+ * machine_specific_memory_setup - Hook for machine specific memory setup.
+ *
+ * Description:
+ *	This is included late in kernel/setup.c so that it can make
+ *	use of all of the static functions.
+ **/
+
+static inline char * __init machine_specific_memory_setup(void)
+{
+	char *who;
+	unsigned long low_mem_size, lower_high, higher_high;
+
+
+	who = "BIOS (common area)";
+
+	low_mem_size = ((*(unsigned char *)__va(PC9800SCA_BIOS_FLAG) & 7) + 1) << 17;
+	add_memory_region(0, low_mem_size, 1);
+	lower_high = (__u32) *(__u8 *) bus_to_virt(PC9800SCA_EXPMMSZ) << 17;
+	higher_high = (__u32) *(__u16 *) bus_to_virt(PC9800SCA_MMSZ16M) << 20;
+	if (lower_high != 0x00f00000UL) {
+		add_memory_region(HIGH_MEMORY, lower_high, 1);
+		add_memory_region(0x01000000UL, higher_high, 1);
+	}
+	else
+		add_memory_region(HIGH_MEMORY, lower_high + higher_high, 1);
+
+	return who;
+}
diff -urN linux-2.5.65-bk2/include/asm-i386/mach-pc9800/setup_arch_pre.h linux-2.5.65-bk3/include/asm-i386/mach-pc9800/setup_arch_pre.h
--- linux-2.5.65-bk2/include/asm-i386/mach-pc9800/setup_arch_pre.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/include/asm-i386/mach-pc9800/setup_arch_pre.h	Mon Mar 31 12:41:45 2003
@@ -0,0 +1,36 @@
+/* Hook to call BIOS initialisation function */
+
+/* no action for generic */
+
+#define ARCH_SETUP arch_setup_pc9800();
+
+#include <linux/timex.h>
+#include <asm/io.h>
+#include <asm/pc9800.h>
+#include <asm/pc9800_sca.h>
+
+int CLOCK_TICK_RATE;
+extern unsigned long tick_usec;	/* ACTHZ          period (usec) */
+extern unsigned long tick_nsec;	/* USER_HZ period (nsec) */
+unsigned char pc9800_misc_flags;
+/* (bit 0) 1:High Address Video ram exists 0:otherwise */
+
+#ifdef CONFIG_SMP
+#define MPC_TABLE_SIZE 512
+#define MPC_TABLE ((char *) (PARAM+0x400))
+char mpc_table[MPC_TABLE_SIZE];
+#endif
+
+static  inline void arch_setup_pc9800(void)
+{
+	CLOCK_TICK_RATE = PC9800_8MHz_P() ? 1996800 : 2457600;
+	printk(KERN_DEBUG "CLOCK_TICK_RATE = %d\n", CLOCK_TICK_RATE);
+	tick_usec = TICK_USEC; 		/* ACTHZ          period (usec) */
+	tick_nsec = TICK_NSEC(TICK_USEC);	/* USER_HZ period (nsec) */
+
+	pc9800_misc_flags = PC9800_MISC_FLAGS;
+#ifdef CONFIG_SMP
+	if ((*(u32 *)(MPC_TABLE)) == 0x504d4350)
+		memcpy(mpc_table, MPC_TABLE, *(u16 *)(MPC_TABLE + 4));
+#endif /* CONFIG_SMP */
+}
diff -urN linux-2.5.65-bk2/include/asm-i386/pc9800_sca.h linux-2.5.65-bk3/include/asm-i386/pc9800_sca.h
--- linux-2.5.65-bk2/include/asm-i386/pc9800_sca.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/include/asm-i386/pc9800_sca.h	Mon Mar 31 12:41:45 2003
@@ -0,0 +1,25 @@
+/*
+ *  System-common area definitions for NEC PC-9800 series
+ *
+ *  Copyright (C) 1999	TAKAI Kousuke <tak@kmc.kyoto-u.ac.jp>,
+ *			Kyoto University Microcomputer Club.
+ */
+
+#ifndef _ASM_I386_PC9800SCA_H_
+#define _ASM_I386_PC9800SCA_H_
+
+#define PC9800SCA_EXPMMSZ		(0x0401)	/* B */
+#define PC9800SCA_SCSI_PARAMS		(0x0460)	/* 8 * 4B */
+#define PC9800SCA_DISK_EQUIPS		(0x0482)	/* B */
+#define PC9800SCA_XROM_ID		(0x04C0)	/* 52B */
+#define PC9800SCA_BIOS_FLAG		(0x0501)	/* B */
+#define PC9800SCA_MMSZ16M		(0x0594)	/* W */
+
+/* PC-9821 have additional system common area in their BIOS-ROM segment. */
+
+#define PC9821SCA__BASE			(0xF8E8 << 4)
+#define PC9821SCA_ROM_ID		(PC9821SCA__BASE + 0x00)
+#define PC9821SCA_ROM_FLAG4		(PC9821SCA__BASE + 0x05)
+#define PC9821SCA_RSFLAGS		(PC9821SCA__BASE + 0x11)	/* B */
+
+#endif /* !_ASM_I386_PC9800SCA_H_ */
diff -urN linux-2.5.65-bk2/include/asm-i386/system.h linux-2.5.65-bk3/include/asm-i386/system.h
--- linux-2.5.65-bk2/include/asm-i386/system.h	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/include/asm-i386/system.h	Mon Mar 31 12:41:45 2003
@@ -407,5 +407,6 @@
 
 #define BROKEN_ACPI_Sx		0x0001
 #define BROKEN_INIT_AFTER_S1	0x0002
+#define BROKEN_PNP_BIOS		0x0004
 
 #endif
diff -urN linux-2.5.65-bk2/include/asm-i386/timex.h linux-2.5.65-bk3/include/asm-i386/timex.h
--- linux-2.5.65-bk2/include/asm-i386/timex.h	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/include/asm-i386/timex.h	Mon Mar 31 12:41:45 2003
@@ -9,11 +9,15 @@
 #include <linux/config.h>
 #include <asm/msr.h>
 
+#ifdef CONFIG_X86_PC9800
+   extern int CLOCK_TICK_RATE;
+#else
 #ifdef CONFIG_MELAN
 #  define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
 #else
 #  define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
 #endif
+#endif
 
 #define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
 #define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
diff -urN linux-2.5.65-bk2/include/asm-i386/upd4990a.h linux-2.5.65-bk3/include/asm-i386/upd4990a.h
--- linux-2.5.65-bk2/include/asm-i386/upd4990a.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/include/asm-i386/upd4990a.h	Mon Mar 31 12:41:45 2003
@@ -0,0 +1,52 @@
+/*
+ *  Architecture dependent definitions
+ *  for NEC uPD4990A serial I/O real-time clock.
+ *
+ *  Copyright 2001  TAKAI Kousuke <tak@kmc.kyoto-u.ac.jp>
+ *		    Kyoto University Microcomputer Club (KMC).
+ *
+ *  References:
+ *	uPD4990A serial I/O real-time clock users' manual (Japanese)
+ *	No. S12828JJ4V0UM00 (4th revision), NEC Corporation, 1999.
+ */
+
+#ifndef _ASM_I386_uPD4990A_H
+#define _ASM_I386_uPD4990A_H
+
+#include <asm/io.h>
+
+#define UPD4990A_IO		(0x0020)
+#define UPD4990A_IO_DATAOUT	(0x0033)
+
+#define UPD4990A_OUTPUT_DATA_CLK(data, clk)		\
+	outb((((data) & 1) << 5) | (((clk) & 1) << 4)	\
+	      | UPD4990A_PAR_SERIAL_MODE, UPD4990A_IO)
+
+#define UPD4990A_OUTPUT_CLK(clk)	UPD4990A_OUTPUT_DATA_CLK(0, (clk))
+
+#define UPD4990A_OUTPUT_STROBE(stb) \
+	outb(((stb) << 3) | UPD4990A_PAR_SERIAL_MODE, UPD4990A_IO)
+
+/*
+ * Note: udelay() is *not* usable for UPD4990A_DELAY because
+ *	 the Linux kernel reads uPD4990A to set up system clock
+ *	 before calibrating delay...
+ */
+#define UPD4990A_DELAY(usec)						\
+	do {								\
+		if (__builtin_constant_p((usec)) && (usec) < 5)	\
+			__asm__ (".rept %c1\n\toutb %%al,%0\n\t.endr"	\
+				 : : "N" (0x5F),			\
+				     "i" (((usec) * 10 + 5) / 6));	\
+		else {							\
+			int _count = ((usec) * 10 + 5) / 6;		\
+			__asm__ volatile ("1: outb %%al,%1\n\tloop 1b"	\
+					  : "=c" (_count)		\
+					  : "N" (0x5F), "0" (_count));	\
+		}							\
+	} while (0)
+
+/* Caller should ignore all bits except bit0 */
+#define UPD4990A_READ_DATA()	inb(UPD4990A_IO_DATAOUT)
+
+#endif
diff -urN linux-2.5.65-bk2/include/asm-s390x/bitops.h linux-2.5.65-bk3/include/asm-s390x/bitops.h
--- linux-2.5.65-bk2/include/asm-s390x/bitops.h	Mon Mar 17 13:44:45 2003
+++ linux-2.5.65-bk3/include/asm-s390x/bitops.h	Mon Mar 31 12:41:46 2003
@@ -55,7 +55,7 @@
 
 #ifdef CONFIG_SMP
 /*
- * SMP save set_bit routine based on compare and swap (CS)
+ * SMP safe set_bit routine based on compare and swap (CS)
  */
 static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 {
@@ -80,7 +80,7 @@
 }
 
 /*
- * SMP save clear_bit routine based on compare and swap (CS)
+ * SMP safe clear_bit routine based on compare and swap (CS)
  */
 static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 {
@@ -105,7 +105,7 @@
 }
 
 /*
- * SMP save change_bit routine based on compare and swap (CS)
+ * SMP safe change_bit routine based on compare and swap (CS)
  */
 static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 {
@@ -130,7 +130,7 @@
 }
 
 /*
- * SMP save test_and_set_bit routine based on compare and swap (CS)
+ * SMP safe test_and_set_bit routine based on compare and swap (CS)
  */
 static inline int
 test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
@@ -157,7 +157,7 @@
 }
 
 /*
- * SMP save test_and_clear_bit routine based on compare and swap (CS)
+ * SMP safe test_and_clear_bit routine based on compare and swap (CS)
  */
 static inline int
 test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
@@ -184,7 +184,7 @@
 }
 
 /*
- * SMP save test_and_change_bit routine based on compare and swap (CS) 
+ * SMP safe test_and_change_bit routine based on compare and swap (CS) 
  */
 static inline int
 test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
diff -urN linux-2.5.65-bk2/include/linux/buffer_head.h linux-2.5.65-bk3/include/linux/buffer_head.h
--- linux-2.5.65-bk2/include/linux/buffer_head.h	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/include/linux/buffer_head.h	Mon Mar 31 12:41:46 2003
@@ -137,6 +137,7 @@
 void create_empty_buffers(struct page *, unsigned long,
 			unsigned long b_state);
 void end_buffer_io_sync(struct buffer_head *bh, int uptodate);
+void end_buffer_async_write(struct buffer_head *bh, int uptodate);
 
 /* Things to do with buffers at mapping->private_list */
 void buffer_insert_list(spinlock_t *lock,
diff -urN linux-2.5.65-bk2/include/linux/devfs_fs_kernel.h linux-2.5.65-bk3/include/linux/devfs_fs_kernel.h
--- linux-2.5.65-bk2/include/linux/devfs_fs_kernel.h	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk3/include/linux/devfs_fs_kernel.h	Mon Mar 31 12:41:46 2003
@@ -13,7 +13,6 @@
 
 #define DEVFS_FL_NONE           0x000 /* This helps to make code more readable
 				       */
-#define DEVFS_FL_REMOVABLE      0x008 /* This is a removable media device    */
 #define DEVFS_FL_WAIT           0x010 /* Wait for devfsd to finish           */
 #define DEVFS_FL_CURRENT_OWNER  0x020 /* Set initial ownership to current    */
 #define DEVFS_FL_DEFAULT        DEVFS_FL_NONE
@@ -37,7 +36,6 @@
 
 #define UNIQUE_NUMBERSPACE_INITIALISER {SPIN_LOCK_UNLOCKED, 0, 0, 0, NULL}
 
-extern void devfs_put (devfs_handle_t de);
 extern devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
 				      unsigned int flags,
 				      unsigned int major, unsigned int minor,
@@ -66,10 +64,6 @@
 
 #define UNIQUE_NUMBERSPACE_INITIALISER {0}
 
-static inline void devfs_put (devfs_handle_t de)
-{
-    return;
-}
 static inline devfs_handle_t devfs_register (devfs_handle_t dir,
 					     const char *name,
 					     unsigned int flags,
diff -urN linux-2.5.65-bk2/include/linux/i2o.h linux-2.5.65-bk3/include/linux/i2o.h
--- linux-2.5.65-bk2/include/linux/i2o.h	Mon Mar 17 13:43:47 2003
+++ linux-2.5.65-bk3/include/linux/i2o.h	Mon Mar 31 12:41:46 2003
@@ -23,7 +23,7 @@
 #include <linux/i2o-dev.h>
 
 /* How many different OSM's are we allowing */
-#define MAX_I2O_MODULES		64
+#define MAX_I2O_MODULES		4
 
 /* How many OSMs can register themselves for device status updates? */
 #define I2O_MAX_MANAGERS	4
@@ -76,10 +76,16 @@
 };
 
 /*
- *	Resource data for each PCI I2O controller
+ * Each I2O controller has one of these objects
  */
-struct i2o_pci
+struct i2o_controller
 {
+	char name[16];
+	int unit;
+	int type;
+	int enabled;
+	
+	struct pci_dev *pdev;		/* PCI device */
 	int		irq;
 	int		short_req:1;	/* Use small block sizes        */
 	int		dpt:1;		/* Don't quiesce                */
@@ -88,25 +94,6 @@
 	int		mtrr_reg0;
 	int		mtrr_reg1;
 #endif
-};
-
-/*
- * Transport types supported by I2O stack
- */
-#define I2O_TYPE_PCI		0x01		/* PCI I2O controller */
-
-
-/*
- * Each I2O controller has one of these objects
- */
-struct i2o_controller
-{
-	struct pci_dev *pdev;		/* PCI device */
-
-	char name[16];
-	int unit;
-	int type;
-	int enabled;
 
 	struct notifier_block *event_notifer;	/* Events */
 	atomic_t users;
@@ -143,22 +130,6 @@
 
 	struct proc_dir_entry *proc_entry;	/* /proc dir */
 
-	union {					/* Bus information */
-		struct i2o_pci pci;
-	} bus;
-
-	/* Bus specific destructor */
-	void (*destructor)(struct i2o_controller *);
-
-	/* Bus specific attach/detach */
-	int (*bind)(struct i2o_controller *, struct i2o_device *);
-
-	/* Bus specific initiator */
-	int (*unbind)(struct i2o_controller *, struct i2o_device *);
-
-	/* Bus specific enable/disable */
-	void (*bus_enable)(struct i2o_controller *);
-	void (*bus_disable)(struct i2o_controller *);
 
 	void *page_frame;			/* Message buffers */
 	dma_addr_t page_frame_map;		/* Cache map */
diff -urN linux-2.5.65-bk2/include/linux/ide.h linux-2.5.65-bk3/include/linux/ide.h
--- linux-2.5.65-bk2/include/linux/ide.h	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/include/linux/ide.h	Mon Mar 31 12:41:46 2003
@@ -280,9 +280,6 @@
 	return ((hwif)->chipset == chipset) ? 1 : 0;		\
 }
 
-#define IDE_DEBUG(lineno) \
-	printk("%s,%s,line=%d\n", __FILE__, __FUNCTION__, (lineno))
-
 /*
  * Check for an interrupt and acknowledge the interrupt status
  */
@@ -302,7 +299,8 @@
 		ide_qd65xx,	ide_umc8672,	ide_ht6560b,
 		ide_pdc4030,	ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
-		ide_pmac,	ide_etrax100,	ide_acorn
+		ide_pmac,	ide_etrax100,	ide_acorn,
+		ide_pc9800
 } hwif_chipset_t;
 
 /*
@@ -728,6 +726,7 @@
 
 	unsigned present	: 1;	/* drive is physically present */
 	unsigned dead		: 1;	/* device ejected hint */
+	unsigned id_read	: 1;	/* 1=id read from disk 0 = synthetic */
 	unsigned noprobe 	: 1;	/* from:  hdx=noprobe */
 	unsigned removable	: 1;	/* 1 if need to do check_media_change */
 	unsigned is_flash	: 1;	/* 1 if probed as flash */
@@ -847,7 +846,7 @@
 #define task_rq_offset(rq) \
 	(((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE)
 
-extern inline void *ide_map_buffer(struct request *rq, unsigned long *flags)
+static inline void *ide_map_buffer(struct request *rq, unsigned long *flags)
 {
 	/*
 	 * fs request
@@ -861,7 +860,7 @@
 	return rq->buffer + task_rq_offset(rq);
 }
 
-extern inline void ide_unmap_buffer(struct request *rq, char *buffer, unsigned long *flags)
+static inline void ide_unmap_buffer(struct request *rq, char *buffer, unsigned long *flags)
 {
 	if (rq->bio)
 		bio_kunmap_irq(buffer, flags);
@@ -975,7 +974,7 @@
 	ide_startstop_t (*ide_dma_queued_start)(ide_drive_t *drive);
 
 	void (*OUTB)(u8 addr, unsigned long port);
-	void (*OUTBSYNC)(u8 addr, unsigned long port);
+	void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
 	void (*OUTW)(u16 addr, unsigned long port);
 	void (*OUTL)(u32 addr, unsigned long port);
 	void (*OUTSW)(unsigned long port, void *addr, u32 count);
@@ -1181,6 +1180,7 @@
 	int		(*end_request)(ide_drive_t *, int, int);
 	u8		(*sense)(ide_drive_t *, const char *, u8);
 	ide_startstop_t	(*error)(ide_drive_t *, const char *, u8);
+	ide_startstop_t	(*abort)(ide_drive_t *, const char *);
 	int		(*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
 	void		(*pre_reset)(ide_drive_t *);
 	unsigned long	(*capacity)(ide_drive_t *);
@@ -1280,6 +1280,13 @@
 ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat);
 
 /*
+ * Abort a running command on the controller triggering the abort
+ * from a host side, non error situation
+ * (drive, msg)
+ */
+extern ide_startstop_t ide_abort(ide_drive_t *, const char *);
+
+/*
  * Issue a simple drive command
  * The drive must be selected beforehand.
  *
@@ -1327,12 +1334,6 @@
 extern ide_startstop_t ide_do_reset (ide_drive_t *);
 
 /*
- * Re-Start an operation for an IDE interface.
- * The caller should return immediately after invoking this.
- */
-extern int restart_request (ide_drive_t *, struct request *);
-
-/*
  * This function is intended to be used prior to invoking ide_do_drive_cmd().
  */
 extern void ide_init_drive_cmd (struct request *rq);
@@ -1727,6 +1728,19 @@
 extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
 
 extern spinlock_t ide_lock;
+extern struct semaphore ide_cfg_sem;
+/*
+ * Structure locking:
+ *
+ * ide_cfg_sem and ide_lock together protect changes to
+ * ide_hwif_t->{next,hwgroup}
+ * ide_drive_t->next
+ *
+ * ide_hwgroup_t->busy: ide_lock
+ * ide_hwgroup_t->hwif: ide_lock
+ * ide_hwif_t->mate: constant, no locking
+ * ide_drive_t->hwif: constant, no locking
+ */
 
 #define local_irq_set(flags)	do { local_save_flags((flags)); local_irq_enable(); } while (0)
 
diff -urN linux-2.5.65-bk2/include/linux/module.h linux-2.5.65-bk3/include/linux/module.h
--- linux-2.5.65-bk2/include/linux/module.h	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk3/include/linux/module.h	Mon Mar 31 12:41:46 2003
@@ -69,8 +69,6 @@
   __attribute__ ((unused, alias(__stringify(name))))
 
 #define THIS_MODULE (&__this_module)
-#define MOD_INC_USE_COUNT _MOD_INC_USE_COUNT(THIS_MODULE)
-#define MOD_DEC_USE_COUNT __MOD_DEC_USE_COUNT(THIS_MODULE)
 
 /*
  * The following license idents are currently accepted as indicating free
@@ -107,8 +105,6 @@
 #define MODULE_ALIAS(alias)
 #define MODULE_GENERIC_TABLE(gtype,name)
 #define THIS_MODULE ((struct module *)0)
-#define MOD_INC_USE_COUNT	do { } while (0)
-#define MOD_DEC_USE_COUNT	do { } while (0)
 #define MODULE_LICENSE(license)
 #endif
 
@@ -418,20 +414,6 @@
 #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
 
 /* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */
-static inline void __deprecated __MOD_INC_USE_COUNT(struct module *module)
-{
-	__unsafe(module);
-	/*
-	 * Yes, we ignore the retval here, that's why it's deprecated.
-	 */
-	try_module_get(module);
-}
-
-static inline void __deprecated __MOD_DEC_USE_COUNT(struct module *module)
-{
-	module_put(module);
-}
-
 #define SET_MODULE_OWNER(dev) ((dev)->owner = THIS_MODULE)
 
 struct obsolete_modparm {
@@ -445,14 +427,7 @@
 struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \
 { __stringify(var), type };
 
-#else
-#define MODULE_PARM(var,type)
-#endif
-
-/* People do this inside their init routines, when the module isn't
-   "live" yet.  They should no longer be doing that, but
-   meanwhile... */
-static inline void __deprecated _MOD_INC_USE_COUNT(struct module *module)
+static inline void __deprecated MOD_INC_USE_COUNT(struct module *module)
 {
 	__unsafe(module);
 
@@ -460,9 +435,23 @@
 	local_inc(&module->ref[get_cpu()].count);
 	put_cpu();
 #else
-	try_module_get(module);
+	(void)try_module_get(module);
 #endif
 }
+
+static inline void __deprecated MOD_DEC_USE_COUNT(struct module *module)
+{
+	module_put(module);
+}
+
+#define MOD_INC_USE_COUNT	MOD_INC_USE_COUNT(THIS_MODULE)
+#define MOD_DEC_USE_COUNT	MOD_DEC_USE_COUNT(THIS_MODULE)
+#else
+#define MODULE_PARM(var,type)
+#define MOD_INC_USE_COUNT	do { } while (0)
+#define MOD_DEC_USE_COUNT	do { } while (0)
+#endif
+
 #define __MODULE_STRING(x) __stringify(x)
 
 /*
diff -urN linux-2.5.65-bk2/include/linux/pci_ids.h linux-2.5.65-bk3/include/linux/pci_ids.h
--- linux-2.5.65-bk2/include/linux/pci_ids.h	Mon Mar 17 13:44:04 2003
+++ linux-2.5.65-bk3/include/linux/pci_ids.h	Mon Mar 31 12:41:46 2003
@@ -144,6 +144,7 @@
 #define PCI_DEVICE_ID_COMPAQ_NETEL100I	0xb011
 #define PCI_DEVICE_ID_COMPAQ_CISS	0xb060
 #define PCI_DEVICE_ID_COMPAQ_CISSB	0xb178
+#define PCI_DEVICE_ID_COMPAQ_CISSC	0x46
 #define PCI_DEVICE_ID_COMPAQ_THUNDER	0xf130
 #define PCI_DEVICE_ID_COMPAQ_NETFLEX3B	0xf150
 
@@ -1832,8 +1833,8 @@
 #define PCI_DEVICE_ID_INTEL_82801E_0	0x2450
 #define PCI_DEVICE_ID_INTEL_82801E_2	0x2452
 #define PCI_DEVICE_ID_INTEL_82801E_3	0x2453
-#define PCI_DEVICE_ID_INTEL_82801E_9	0x245b
-#define PCI_DEVICE_ID_INTEL_82801E_11	PCI_DEVICE_ID_INTEL_82801E_9
+#define PCI_DEVICE_ID_INTEL_82801E_9	0x2459
+#define PCI_DEVICE_ID_INTEL_82801E_11	0x245b
 #define PCI_DEVICE_ID_INTEL_82801E_13	0x245d
 #define PCI_DEVICE_ID_INTEL_82801E_14	0x245e
 #define PCI_DEVICE_ID_INTEL_82801CA_0	0x2480
@@ -1853,10 +1854,20 @@
 #define PCI_DEVICE_ID_INTEL_82801DB_5	0x24c5
 #define PCI_DEVICE_ID_INTEL_82801DB_6	0x24c6
 #define PCI_DEVICE_ID_INTEL_82801DB_7	0x24c7
-#define PCI_DEVICE_ID_INTEL_82801DB_9	0x24cb
-#define PCI_DEVICE_ID_INTEL_82801DB_11	PCI_DEVICE_ID_INTEL_82801DB_9
+#define PCI_DEVICE_ID_INTEL_82801DB_9	0x24c9
+#define PCI_DEVICE_ID_INTEL_82801DB_10	0x24ca
+#define PCI_DEVICE_ID_INTEL_82801DB_11	0x24cb
 #define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
 #define PCI_DEVICE_ID_INTEL_82801DB_13	0x24cd
+#define PCI_DEVICE_ID_INTEL_82801EB_0	0x24d0
+#define PCI_DEVICE_ID_INTEL_82801EB_2	0x24d2
+#define PCI_DEVICE_ID_INTEL_82801EB_3	0x24d3
+#define PCI_DEVICE_ID_INTEL_82801EB_4	0x24d4
+#define PCI_DEVICE_ID_INTEL_82801EB_5	0x24d5
+#define PCI_DEVICE_ID_INTEL_82801EB_6	0x24d6
+#define PCI_DEVICE_ID_INTEL_82801EB_7	0x24d7
+#define PCI_DEVICE_ID_INTEL_82801EB_11	0x24db
+#define PCI_DEVICE_ID_INTEL_82801EB_13	0x24dd
 #define PCI_DEVICE_ID_INTEL_82820_HB	0x2500
 #define PCI_DEVICE_ID_INTEL_82820_UP_HB	0x2501
 #define PCI_DEVICE_ID_INTEL_82850_HB	0x2530
diff -urN linux-2.5.65-bk2/include/linux/serial_core.h linux-2.5.65-bk3/include/linux/serial_core.h
--- linux-2.5.65-bk2/include/linux/serial_core.h	Mon Mar 17 13:43:41 2003
+++ linux-2.5.65-bk3/include/linux/serial_core.h	Mon Mar 31 12:41:47 2003
@@ -59,6 +59,14 @@
 /* NEC v850.  */
 #define PORT_NB85E_UART	40
 
+/* NEC PC-9800 */
+#define PORT_8251_PC98	41
+#define PORT_19K_PC98	42
+#define PORT_FIFO_PC98	43
+#define PORT_VFAST_PC98	44
+#define PORT_PC9861	45
+#define PORT_PC9801_101	46
+
 
 #ifdef __KERNEL__
 
diff -urN linux-2.5.65-bk2/include/linux/upd4990a.h linux-2.5.65-bk3/include/linux/upd4990a.h
--- linux-2.5.65-bk2/include/linux/upd4990a.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/include/linux/upd4990a.h	Mon Mar 31 12:41:47 2003
@@ -0,0 +1,140 @@
+/*
+ *  Constant and architecture independent procedures
+ *  for NEC uPD4990A serial I/O real-time clock.
+ *
+ *  Copyright 2001  TAKAI Kousuke <tak@kmc.kyoto-u.ac.jp>
+ *		    Kyoto University Microcomputer Club (KMC).
+ *
+ *  References:
+ *	uPD4990A serial I/O real-time clock users' manual (Japanese)
+ *	No. S12828JJ4V0UM00 (4th revision), NEC Corporation, 1999.
+ */
+
+#ifndef _LINUX_uPD4990A_H
+#define _LINUX_uPD4990A_H
+
+#include <asm/byteorder.h>
+
+#include <asm/upd4990a.h>
+
+/* Serial commands (4 bits) */
+#define UPD4990A_REGISTER_HOLD			(0x0)
+#define UPD4990A_REGISTER_SHIFT			(0x1)
+#define UPD4990A_TIME_SET_AND_COUNTER_HOLD	(0x2)
+#define UPD4990A_TIME_READ			(0x3)
+#define UPD4990A_TP_64HZ			(0x4)
+#define UPD4990A_TP_256HZ			(0x5)
+#define UPD4990A_TP_2048HZ			(0x6)
+#define UPD4990A_TP_4096HZ			(0x7)
+#define UPD4990A_TP_1S				(0x8)
+#define UPD4990A_TP_10S				(0x9)
+#define UPD4990A_TP_30S				(0xA)
+#define UPD4990A_TP_60S				(0xB)
+#define UPD4990A_INTERRUPT_RESET		(0xC)
+#define UPD4990A_INTERRUPT_TIMER_START		(0xD)
+#define UPD4990A_INTERRUPT_TIMER_STOP		(0xE)
+#define UPD4990A_TEST_MODE_SET			(0xF)
+
+/* Parallel commands (3 bits)
+   0-6 are same with serial commands.  */
+#define UPD4990A_PAR_SERIAL_MODE		7
+
+#ifndef UPD4990A_DELAY
+# include <linux/delay.h>
+# define UPD4990A_DELAY(usec)	udelay((usec))
+#endif
+#ifndef UPD4990A_OUTPUT_DATA
+# define UPD4990A_OUTPUT_DATA(bit)			\
+	do {						\
+		UPD4990A_OUTPUT_DATA_CLK((bit), 0);	\
+		UPD4990A_DELAY(1); /* t-DSU */		\
+		UPD4990A_OUTPUT_DATA_CLK((bit), 1);	\
+		UPD4990A_DELAY(1); /* t-DHLD */	\
+	} while (0)
+#endif
+
+static __inline__ void upd4990a_serial_command(int command)
+{
+	UPD4990A_OUTPUT_DATA(command >> 0);
+	UPD4990A_OUTPUT_DATA(command >> 1);
+	UPD4990A_OUTPUT_DATA(command >> 2);
+	UPD4990A_OUTPUT_DATA(command >> 3);
+	UPD4990A_DELAY(1);	/* t-HLD */
+	UPD4990A_OUTPUT_STROBE(1);
+	UPD4990A_DELAY(1);	/* t-STB & t-d1 */
+	UPD4990A_OUTPUT_STROBE(0);
+	/* 19 microseconds extra delay is needed
+	   iff previous mode is TIME READ command  */
+}
+
+struct upd4990a_raw_data {
+	u8	sec;		/* BCD */
+	u8	min;		/* BCD */
+	u8	hour;		/* BCD */
+	u8	mday;		/* BCD */
+#if   defined __LITTLE_ENDIAN_BITFIELD
+	unsigned wday :4;	/* 0-6 */
+	unsigned mon :4;	/* 1-based */
+#elif defined __BIG_ENDIAN_BITFIELD
+	unsigned mon :4;	/* 1-based */
+	unsigned wday :4;	/* 0-6 */
+#else
+# error Unknown bitfield endian!
+#endif
+	u8	year;		/* BCD */
+};
+
+static __inline__ void upd4990a_get_time(struct upd4990a_raw_data *buf,
+					  int leave_register_hold)
+{
+	int byte;
+
+	upd4990a_serial_command(UPD4990A_TIME_READ);
+	upd4990a_serial_command(UPD4990A_REGISTER_SHIFT);
+	UPD4990A_DELAY(19);	/* t-d2 - t-d1 */
+
+	for (byte = 0; byte < 6; byte++) {
+		u8 tmp;
+		int bit;
+
+		for (tmp = 0, bit = 0; bit < 8; bit++) {
+			tmp = (tmp | (UPD4990A_READ_DATA() << 8)) >> 1;
+			UPD4990A_OUTPUT_CLK(1);
+			UPD4990A_DELAY(1);
+			UPD4990A_OUTPUT_CLK(0);
+			UPD4990A_DELAY(1);
+		}
+		((u8 *) buf)[byte] = tmp;
+	}
+
+	/* The uPD4990A users' manual says that we should issue `Register
+	   Hold' command after each data retrieval, or next `Time Read'
+	   command may not work correctly.  */
+	if (!leave_register_hold)
+		upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
+}
+
+static __inline__ void upd4990a_set_time(const struct upd4990a_raw_data *data,
+					  int time_set_only)
+{
+	int byte;
+
+	if (!time_set_only)
+		upd4990a_serial_command(UPD4990A_REGISTER_SHIFT);
+
+	for (byte = 0; byte < 6; byte++) {
+		int bit;
+		u8 tmp = ((const u8 *) data)[byte];
+
+		for (bit = 0; bit < 8; bit++, tmp >>= 1)
+			UPD4990A_OUTPUT_DATA(tmp);
+	}
+
+	upd4990a_serial_command(UPD4990A_TIME_SET_AND_COUNTER_HOLD);
+
+	/* Release counter hold and start the clock.  */
+	if (!time_set_only)
+		upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
+}
+
+#endif /* _LINUX_uPD4990A_H */
diff -urN linux-2.5.65-bk2/kernel/ksyms.c linux-2.5.65-bk3/kernel/ksyms.c
--- linux-2.5.65-bk2/kernel/ksyms.c	Mon Mar 17 13:43:38 2003
+++ linux-2.5.65-bk3/kernel/ksyms.c	Mon Mar 31 12:41:47 2003
@@ -175,6 +175,7 @@
 EXPORT_SYMBOL(d_path);
 EXPORT_SYMBOL(mark_buffer_dirty);
 EXPORT_SYMBOL(end_buffer_io_sync);
+EXPORT_SYMBOL(end_buffer_async_write);
 EXPORT_SYMBOL(__mark_inode_dirty);
 EXPORT_SYMBOL(get_empty_filp);
 EXPORT_SYMBOL(open_private_file);
diff -urN linux-2.5.65-bk2/mm/oom_kill.c linux-2.5.65-bk3/mm/oom_kill.c
--- linux-2.5.65-bk2/mm/oom_kill.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/mm/oom_kill.c	Mon Mar 31 12:41:47 2003
@@ -51,7 +51,7 @@
  * 3) we don't kill anything innocent of eating tons of memory
  * 4) we want to kill the minimum amount of processes (one)
  * 5) we try to kill the process the user expects us to kill, this
- *    algorithm has been meticulously tuned to meet the priniciple
+ *    algorithm has been meticulously tuned to meet the principle
  *    of least surprise ... (be careful when you change it)
  */
 
diff -urN linux-2.5.65-bk2/mm/swapfile.c linux-2.5.65-bk3/mm/swapfile.c
--- linux-2.5.65-bk2/mm/swapfile.c	Mon Mar 17 13:43:46 2003
+++ linux-2.5.65-bk3/mm/swapfile.c	Mon Mar 31 12:41:47 2003
@@ -736,8 +736,7 @@
 		 * interactive performance.  Interruptible check on
 		 * signal_pending() would be nice, but changes the spec?
 		 */
-		if (need_resched())
-			schedule();
+		cond_resched();
 	}
 
 	mmput(start_mm);
diff -urN linux-2.5.65-bk2/net/core/neighbour.c linux-2.5.65-bk3/net/core/neighbour.c
--- linux-2.5.65-bk2/net/core/neighbour.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/net/core/neighbour.c	Mon Mar 31 12:41:47 2003
@@ -550,7 +550,7 @@
 	write_lock(&tbl->lock);
 
 	/*
-	 *	periodicly recompute ReachableTime from random function
+	 *	periodically recompute ReachableTime from random function
 	 */
 
 	if (now - tbl->last_rand > 300 * HZ) {
diff -urN linux-2.5.65-bk2/net/ipv4/netfilter/arp_tables.c linux-2.5.65-bk3/net/ipv4/netfilter/arp_tables.c
--- linux-2.5.65-bk2/net/ipv4/netfilter/arp_tables.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/net/ipv4/netfilter/arp_tables.c	Mon Mar 31 12:41:47 2003
@@ -912,19 +912,25 @@
 		goto free_newinfo_counters_untrans_unlock;
 	}
 
+	/* Get a reference in advance, we're not allowed fail later */
+	if (!try_module_get(t->me)) {
+		ret = -EBUSY;
+		goto free_newinfo_counters_untrans_unlock;
+	}
+
 	oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
 	if (!oldinfo)
-		goto free_newinfo_counters_untrans_unlock;
+		goto put_module;
 
 	/* Update module usage count based on number of rules */
 	duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
 		oldinfo->number, oldinfo->initial_entries, newinfo->number);
-	if (t->me && (oldinfo->number <= oldinfo->initial_entries) &&
- 	    (newinfo->number > oldinfo->initial_entries))
-		__MOD_INC_USE_COUNT(t->me);
-	else if (t->me && (oldinfo->number > oldinfo->initial_entries) &&
-	 	 (newinfo->number <= oldinfo->initial_entries))
-		__MOD_DEC_USE_COUNT(t->me);
+	if ((oldinfo->number > oldinfo->initial_entries) || 
+	    (newinfo->number <= oldinfo->initial_entries)) 
+		module_put(t->me);
+	if ((oldinfo->number > oldinfo->initial_entries) &&
+	    (newinfo->number <= oldinfo->initial_entries))
+		module_put(t->me);
 
 	/* Get the old counters. */
 	get_counters(oldinfo, counters);
@@ -938,6 +944,8 @@
 	up(&arpt_mutex);
 	return 0;
 
+ put_module:
+	module_put(t->me);
  free_newinfo_counters_untrans_unlock:
 	up(&arpt_mutex);
  free_newinfo_counters_untrans:
diff -urN linux-2.5.65-bk2/net/ipv4/netfilter/ip_tables.c linux-2.5.65-bk3/net/ipv4/netfilter/ip_tables.c
--- linux-2.5.65-bk2/net/ipv4/netfilter/ip_tables.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/net/ipv4/netfilter/ip_tables.c	Mon Mar 31 12:41:47 2003
@@ -1106,19 +1106,26 @@
 		goto free_newinfo_counters_untrans_unlock;
 	}
 
+	/* Get a reference in advance, we're not allowed fail later */
+	if (!try_module_get(t->me)) {
+		ret = -EBUSY;
+		goto free_newinfo_counters_untrans_unlock;
+	}
+
+
 	oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
 	if (!oldinfo)
-		goto free_newinfo_counters_untrans_unlock;
+		goto put_module;
 
 	/* Update module usage count based on number of rules */
 	duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
 		oldinfo->number, oldinfo->initial_entries, newinfo->number);
-	if (t->me && (oldinfo->number <= oldinfo->initial_entries) &&
- 	    (newinfo->number > oldinfo->initial_entries))
-		__MOD_INC_USE_COUNT(t->me);
-	else if (t->me && (oldinfo->number > oldinfo->initial_entries) &&
-	 	 (newinfo->number <= oldinfo->initial_entries))
-		__MOD_DEC_USE_COUNT(t->me);
+	if ((oldinfo->number > oldinfo->initial_entries) || 
+	    (newinfo->number <= oldinfo->initial_entries)) 
+		module_put(t->me);
+	if ((oldinfo->number > oldinfo->initial_entries) &&
+	    (newinfo->number <= oldinfo->initial_entries))
+		module_put(t->me);
 
 	/* Get the old counters. */
 	get_counters(oldinfo, counters);
@@ -1132,6 +1139,8 @@
 	up(&ipt_mutex);
 	return 0;
 
+ put_module:
+	module_put(t->me);
  free_newinfo_counters_untrans_unlock:
 	up(&ipt_mutex);
  free_newinfo_counters_untrans:
diff -urN linux-2.5.65-bk2/net/ipv4/route.c linux-2.5.65-bk3/net/ipv4/route.c
--- linux-2.5.65-bk2/net/ipv4/route.c	Mon Mar 17 13:44:50 2003
+++ linux-2.5.65-bk3/net/ipv4/route.c	Mon Mar 31 12:41:48 2003
@@ -1854,7 +1854,7 @@
 			goto out;
 
 		/* I removed check for oif == dev_out->oif here.
-		   It was wrong by three reasons:
+		   It was wrong for two reasons:
 		   1. ip_dev_find(saddr) can return wrong iface, if saddr is
 		      assigned to multiple interfaces.
 		   2. Moreover, we are allowed to send packets with saddr
diff -urN linux-2.5.65-bk2/net/ipv4/xfrm_policy.c linux-2.5.65-bk3/net/ipv4/xfrm_policy.c
--- linux-2.5.65-bk2/net/ipv4/xfrm_policy.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/net/ipv4/xfrm_policy.c	Mon Mar 31 12:41:48 2003
@@ -1101,6 +1101,7 @@
 	case AF_INET6:
 		/* Still not clear... */
 	default:
+		/* nothing */;
 	}
 
 restart:
diff -urN linux-2.5.65-bk2/net/ipv6/netfilter/ip6_tables.c linux-2.5.65-bk3/net/ipv6/netfilter/ip6_tables.c
--- linux-2.5.65-bk2/net/ipv6/netfilter/ip6_tables.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/net/ipv6/netfilter/ip6_tables.c	Mon Mar 31 12:41:48 2003
@@ -1178,19 +1178,25 @@
 		goto free_newinfo_counters_untrans_unlock;
 	}
 
+	/* Get a reference in advance, we're not allowed fail later */
+	if (!try_module_get(t->me)) {
+		ret = -EBUSY;
+		goto free_newinfo_counters_untrans_unlock;
+	}
+
 	oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
 	if (!oldinfo)
-		goto free_newinfo_counters_untrans_unlock;
+		goto put_module;
 
 	/* Update module usage count based on number of rules */
 	duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
 		oldinfo->number, oldinfo->initial_entries, newinfo->number);
-	if (t->me && (oldinfo->number <= oldinfo->initial_entries) &&
- 	    (newinfo->number > oldinfo->initial_entries))
-		__MOD_INC_USE_COUNT(t->me);
-	else if (t->me && (oldinfo->number > oldinfo->initial_entries) &&
-	 	 (newinfo->number <= oldinfo->initial_entries))
-		__MOD_DEC_USE_COUNT(t->me);
+	if ((oldinfo->number > oldinfo->initial_entries) || 
+	    (newinfo->number <= oldinfo->initial_entries)) 
+		module_put(t->me);
+	if ((oldinfo->number > oldinfo->initial_entries) &&
+	    (newinfo->number <= oldinfo->initial_entries))
+		module_put(t->me);
 
 	/* Get the old counters. */
 	get_counters(oldinfo, counters);
@@ -1204,6 +1210,8 @@
 	up(&ip6t_mutex);
 	return 0;
 
+ put_module:
+	module_put(t->me);
  free_newinfo_counters_untrans_unlock:
 	up(&ip6t_mutex);
  free_newinfo_counters_untrans:
diff -urN linux-2.5.65-bk2/sound/isa/cs423x/pc98.c linux-2.5.65-bk3/sound/isa/cs423x/pc98.c
--- linux-2.5.65-bk2/sound/isa/cs423x/pc98.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/sound/isa/cs423x/pc98.c	Mon Mar 31 12:41:50 2003
@@ -0,0 +1,466 @@
+/*
+ *  Driver for CS4232 on NEC PC9800 series
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *                   Osamu Tomita <tomita@cinet.co.jp>
+ *                   Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/cs4231.h>
+#include <sound/mpu401.h>
+#include <sound/opl3.h>
+#define SNDRV_GET_ID
+#include <sound/initval.h>
+#include "sound_pc9800.h"
+
+#define chip_t cs4231_t
+
+MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
+MODULE_LICENSE("GPL");
+MODULE_CLASSES("{sound}");
+MODULE_DESCRIPTION("NEC PC9800 CS4232");
+MODULE_DEVICES("{{NEC,PC9800}}");
+
+#define IDENT "PC98-CS4232"
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
+#if 0 /* NOT USED */
+static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
+#endif
+static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */
+static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
+static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 5,7,9,11,12,15 */
+static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 9,11,12,15 */
+static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
+static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
+static int pc98ii[SNDRV_CARDS];				/* PC98II */
+
+MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard.");
+MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
+MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
+MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard.");
+MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
+MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard.");
+MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
+MODULE_PARM(port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+MODULE_PARM_DESC(port, "Port # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
+#if 0 /* NOT USED */
+MODULE_PARM(cport, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(cport, SNDRV_PORT12_DESC);
+#endif
+MODULE_PARM(mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
+MODULE_PARM(fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
+MODULE_PARM(irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
+MODULE_PARM(mpu_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
+MODULE_PARM(dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
+MODULE_PARM(dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
+MODULE_PARM(pc98ii, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(pc98ii, "Roland MPU-PC98II support.");
+MODULE_PARM_SYNTAX(pc98ii, SNDRV_BOOLEAN_FALSE_DESC);
+
+
+static snd_card_t *snd_pc98_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+
+/*
+ * initialize MPU401-UART
+ */
+
+static int __init pc98_mpu401_init(int irq)
+{
+#include "pc9801_118_magic.h"
+#define outp118(reg,data) outb((reg),0x148e);outb((data),0x148f)
+#define WAIT118 outb(0x00,0x5f)
+	int	mpu_intr, count;
+#ifdef OOKUBO_ORIGINAL
+	int	err = 0;
+#endif /* OOKUBO_ORIGINAL */
+
+	switch (irq) {
+	case 3:
+		mpu_intr = 3;
+		break;
+	case 5:
+		mpu_intr = 2;
+		break;
+	case 6:
+		mpu_intr = 1;
+		break;
+	case 10:
+		mpu_intr = 0;
+		break;
+	default:
+		snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq);
+		return -EINVAL;
+	}
+
+	outp118(0x21, mpu_intr);
+	WAIT118;
+	outb(0x00, 0x148e);
+	if (inb(0x148f) & 0x08) {
+		snd_printk(KERN_INFO IDENT ": No MIDI daughter board found\n");
+		return 0;
+	}
+
+	outp118(0x20, 0x00);
+	outp118(0x05, 0x04);
+	for (count = 0; count < 35000; count ++)
+		WAIT118;
+	outb(0x05, 0x148e);
+	for (count = 0; count < 65000; count ++)
+		if (inb(0x148f) == 0x04)
+			goto set_mode_118;
+	snd_printk(KERN_ERR IDENT ": MIDI daughter board initialize failed at stage1\n\n");
+	return -EINVAL;
+
+ set_mode_118:
+	outp118(0x05, 0x0c);
+	outb(0xaa, 0x485);
+	outb(0x99, 0x485);
+	outb(0x2a, 0x485);
+	for (count = 0; count < sizeof(Data0485_99); count ++) {
+		outb(Data0485_99[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outb(0xaa, 0x485);
+	outb(0x9e, 0x485);
+	outb(0x2a, 0x485);
+	for (count = 0; count < sizeof(Data0485_9E); count ++)
+		if (inb(0x485) != Data0485_9E[count]) {
+#ifdef OOKUBO_ORIGINAL
+			err = 1;
+#endif /* OOKUBO_ORIGINAL */
+			break;
+		}
+	outb(0x00, 0x486);
+	for (count = 0; count < 2000; count ++)
+		WAIT118;
+#ifdef OOKUBO_ORIGINAL
+	if (!err) {
+		outb(0xaa, 0x485);
+		outb(0x36, 0x485);
+		outb(0x28, 0x485);
+		for (count = 0; count < sizeof(Data0485_36); count ++)
+			outb(Data0485_36[count], 0x485);
+		outb(0x00, 0x486);
+		for (count = 0; count < 1500; count ++)
+			WAIT118;
+		outp118(0x05, inb(0x148f) | 0x08);
+		outb(0xff, 0x148c);
+		outp118(0x05, inb(0x148f) & 0xf7);
+		for (count = 0; count < 1500; count ++)
+			WAIT118;
+	}
+#endif /* OOKUBO_ORIGINAL */
+
+	outb(0xaa, 0x485);
+	outb(0xa9, 0x485);
+	outb(0x21, 0x485);
+	for (count = 0; count < sizeof(Data0485_A9); count ++) {
+		outb(Data0485_A9[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outb(0xaa, 0x485);
+	outb(0x0c, 0x485);
+	outb(0x20, 0x485);
+	for (count = 0; count < sizeof(Data0485_0C); count ++) {
+		outb(Data0485_0C[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outb(0xaa, 0x485);
+	outb(0x66, 0x485);
+	outb(0x20, 0x485);
+	for (count = 0; count < sizeof(Data0485_66); count ++) {
+		outb(Data0485_66[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outb(0xaa, 0x485);
+	outb(0x60, 0x485);
+	outb(0x20, 0x485);
+	for (count = 0; count < sizeof(Data0485_60); count ++) {
+		outb(Data0485_60[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outp118(0x05, 0x04);
+	outp118(0x05, 0x00);
+	for (count = 0; count < 35000; count ++)
+		WAIT118;
+	outb(0x05, 0x148e);
+	for (count = 0; count < 65000; count ++)
+		if (inb(0x148f) == 0x00)
+			goto end_mode_118;
+	snd_printk(KERN_ERR IDENT ": MIDI daughter board initialize failed at stage2\n");
+	return -EINVAL;
+
+ end_mode_118:
+	outb(0x3f, 0x148d);
+	snd_printk(KERN_INFO IDENT ": MIDI daughter board initialized\n");
+	return 0;
+}
+
+static int __init pc98_cs4231_chip_init(int dev)
+{
+	int intr_bits, intr_bits2, dma_bits;
+
+	switch (irq[dev]) {
+	case 3:
+		intr_bits = 0x08;
+		intr_bits2 = 0x03;
+		break;
+	case 5:
+		intr_bits = 0x10;
+		intr_bits2 = 0x08;
+		break;
+	case 10:
+		intr_bits = 0x18;
+		intr_bits2 = 0x02;
+		break;
+	case 12:
+		intr_bits = 0x20;
+		intr_bits2 = 0x00;
+		break;
+	default:
+		snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq[dev]);
+		return -EINVAL;
+	}
+
+	switch (dma1[dev]) {
+	case 0:
+		dma_bits = 0x01;
+		break;
+	case 1:
+		dma_bits = 0x02;
+		break;
+	case 3:
+		dma_bits = 0x03;
+		break;
+	default:
+		snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma1[dev]);
+		return -EINVAL;
+	}
+
+	if (dma2[dev] >= 2) {
+		snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma2[dev]);
+		return -EINVAL;
+	}
+	if (dma1[dev] != dma2[dev] && dma2[dev] >= 0)
+		intr_bits |= 0x04;
+
+	if (PC9800_SOUND_ID() == PC9800_SOUND_ID_118) {
+		/* Set up CanBe control registers. */
+		snd_printd(KERN_INFO "Setting up CanBe Sound System\n");
+		outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID);
+		outb(0x01, 0x0f4a);
+		outb(intr_bits2, 0x0f4b);
+	}
+
+	outb(intr_bits | dma_bits, 0xf40);
+	return 0;
+}
+
+
+static int __init snd_card_pc98_probe(int dev)
+{
+	snd_card_t *card;
+	snd_pcm_t *pcm = NULL;
+	cs4231_t *chip;
+	opl3_t *opl3;
+	int err;
+
+	if (port[dev] == SNDRV_AUTO_PORT) {
+		snd_printk(KERN_ERR IDENT ": specify port\n");
+		return -EINVAL;
+	}
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	if (card == NULL)
+		return -ENOMEM;
+	if (mpu_port[dev] < 0 || mpu_irq[dev] < 0)
+		mpu_port[dev] = SNDRV_AUTO_PORT;
+	if (fm_port[dev] < 0)
+		fm_port[dev] = SNDRV_AUTO_PORT;
+
+	if ((err = pc98_cs4231_chip_init(dev)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	if ((err = snd_cs4231_create(card,
+				     port[dev],
+				     -1,
+				     irq[dev],
+				     dma1[dev],
+				     dma2[dev],
+				     CS4231_HW_DETECT,
+				     0,
+				     &chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	if ((err = snd_cs4231_mixer(chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	if (fm_port[dev] != SNDRV_AUTO_PORT) {
+		/* ??? */
+		outb(0x00, fm_port[dev] + 6);
+		inb(fm_port[dev] + 7);
+		/* Enable OPL-3 Function */
+		outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID);
+		if (snd_opl3_create(card,
+				    fm_port[dev], fm_port[dev] + 2,
+				    OPL3_HW_OPL3_PC98, 0, &opl3) < 0) {
+			printk(KERN_ERR IDENT ": OPL3 not detected\n");
+		} else {
+			if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
+				snd_card_free(card);
+				return err;
+			}
+		}
+	}
+
+	if (mpu_port[dev] != SNDRV_AUTO_PORT) {
+		err = pc98_mpu401_init(mpu_irq[dev]);
+		if (! err) {
+			err = snd_mpu401_uart_new(card, 0,
+						  pc98ii[dev] ? MPU401_HW_PC98II : MPU401_HW_MPU401,
+						  mpu_port[dev], 0,
+						  mpu_irq[dev], SA_INTERRUPT, NULL);
+			if (err < 0)
+				snd_printk(KERN_INFO IDENT ": MPU401 not detected\n");
+		}
+	}
+
+	strcpy(card->driver, pcm->name);
+	strcpy(card->shortname, pcm->name);
+	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i",
+		pcm->name,
+		chip->port,
+		irq[dev],
+		dma1[dev]);
+	if (dma1[dev] >= 0)
+		sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
+	if ((err = snd_card_register(card)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	snd_pc98_cards[dev] = card;
+	return 0;
+}
+
+static int __init alsa_card_pc98_init(void)
+{
+	int dev, cards = 0;
+
+	for (dev = 0; dev < SNDRV_CARDS; dev++) {
+		if (!enable[dev])
+			continue;
+		if (snd_card_pc98_probe(dev) >= 0)
+			cards++;
+	}
+	if (!cards) {
+#ifdef MODULE
+		printk(KERN_ERR IDENT " soundcard not found or device busy\n");
+#endif
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void __exit alsa_card_pc98_exit(void)
+{
+	int idx;
+
+	for (idx = 0; idx < SNDRV_CARDS; idx++)
+		snd_card_free(snd_pc98_cards[idx]);
+}
+
+module_init(alsa_card_pc98_init)
+module_exit(alsa_card_pc98_exit)
+
+#ifndef MODULE
+
+/* format is: snd-pc98-cs4232=enable,index,id,port,
+			 mpu_port,fm_port,
+			 irq,mpu_irq,dma1,dma2,pc98ii */
+
+static int __init alsa_card_pc98_setup(char *str)
+{
+	static unsigned __initdata nr_dev = 0;
+
+	if (nr_dev >= SNDRV_CARDS)
+		return 0;
+	(void)(get_option(&str,&enable[nr_dev]) == 2 &&
+	       get_option(&str,&index[nr_dev]) == 2 &&
+	       get_id(&str,&id[nr_dev]) == 2 &&
+	       get_option(&str,(int *)&port[nr_dev]) == 2 &&
+	       get_option(&str,(int *)&mpu_port[nr_dev]) == 2 &&
+	       get_option(&str,(int *)&fm_port[nr_dev]) == 2 &&
+	       get_option(&str,&irq[nr_dev]) == 2 &&
+	       get_option(&str,&mpu_irq[nr_dev]) == 2 &&
+	       get_option(&str,&dma1[nr_dev]) == 2 &&
+	       get_option(&str,&dma2[nr_dev]) == 2 &&
+	       get_option(&str,&pc98ii[nr_dev]) == 2);
+	nr_dev++;
+	return 1;
+}
+
+__setup("snd-pc98-cs4232=", alsa_card_pc98_setup);
+
+#endif /* ifndef MODULE */
diff -urN linux-2.5.65-bk2/sound/isa/cs423x/pc9801_118_magic.h linux-2.5.65-bk3/sound/isa/cs423x/pc9801_118_magic.h
--- linux-2.5.65-bk2/sound/isa/cs423x/pc9801_118_magic.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/sound/isa/cs423x/pc9801_118_magic.h	Mon Mar 31 12:41:50 2003
@@ -0,0 +1,411 @@
+		static unsigned char	Data0485_A9[] = {
+		0x12, 0x03, 0x90, 0xc2, 0x2a, 0x75, 0x1e, 0x20,
+		0xe4, 0x12, 0x2b, 0x9b, 0x22, 0xa9, 0x16, 0x77,
+		0x33, 0xe9, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf5,
+		0x16, 0xc2, 0x2f, 0x22, 0xa9, 0x16, 0x77, 0x42,
+		0xe9, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf9, 0x77,
+		0xf8, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf5, 0x16,
+		0xc2, 0x2f, 0x22, 0x90, 0x25, 0x9f, 0x30, 0x04,
+		0x05, 0xc2, 0x04, 0x12, 0x1f, 0x62, 0x30, 0x00,
+		0x05, 0xc2, 0x00, 0x12, 0x15, 0xe6, 0x30, 0x01,
+		0x05, 0xc2, 0x01, 0x12, 0x29, 0xaf, 0x30, 0x02,
+		0x05, 0xc2, 0x02, 0x12, 0x29, 0xaf, 0x30, 0x05,
+		0x05, 0xc2, 0x05, 0x12, 0x16, 0x65, 0x30, 0x06,
+		0x08, 0xc2, 0x06, 0x12, 0x16, 0xb1, 0x12, 0x29,
+		0xaf, 0x30, 0x07, 0x08, 0xc2, 0x07, 0x12, 0x16,
+		0xe9, 0x12, 0x29, 0xaf, 0x22, 0x20, 0x97, 0x09,
+		0x53, 0xa8, 0xfb, 0x12, 0x04, 0x2c, 0x43, 0xa8,
+		0x04, 0x22, 0x71, 0xb8, 0x71, 0xb8, 0x71, 0xb8,
+		0x22, 0x20, 0x4b, 0x04, 0x75, 0x4e, 0x02, 0x22,
+		0xe5, 0x35, 0x24, 0xff, 0xf5, 0x35, 0xe5, 0x36,
+		0x34, 0xff, 0xf5, 0x36, 0x75, 0x4e, 0x02, 0x22,
+		0x10, 0x19, 0x02, 0x80, 0x08, 0x78, 0x00, 0xe2,
+		0x78, 0x07, 0xf2, 0x61, 0x9b, 0x78, 0x11, 0xe2,
+		0xc0, 0x01, 0xc0, 0xf0, 0xc0, 0xd0, 0xc0, 0x02,
+		0x71, 0x14, 0xe5, 0x30, 0xb4, 0x01, 0x02, 0x61,
+		0x93, 0x43, 0x08, 0x40, 0x12, 0x2a, 0x53, 0x61,
+		0x93, 0x79, 0x03, 0xe3, 0xa2, 0xe2, 0x92, 0x26,
+		0xa2, 0xe3, 0x92, 0x27, 0x22, 0xad, 0x2b, 0xbd,
+		0x04, 0x07, 0xf5, 0x72, 0x78, 0x27, 0x02, 0x11,
+		0x76, 0x02, 0x11, 0x30, 0x00, 0x00, 0x00, 0x12,
+		0x28, 0xba, 0x79, 0x01, 0xe3, 0x75, 0x21, 0x3f,
+		0x75, 0x49, 0x11, 0x75, 0x4c, 0x11, 0x31, 0xdc,
+		0x75, 0x1a, 0x80, 0x51, 0x72, 0x75, 0x81, 0xe3,
+		0x12, 0x25, 0xc9, 0x43, 0xa8, 0x01, 0x00, 0x53,
+		0xa8, 0xfe, 0x10, 0x50, 0x02, 0x80, 0x03, 0x12,
+		0x1a, 0x8d, 0xd1, 0x28, 0x12, 0x03, 0xd9, 0xd1,
+		0xf2, 0x12, 0x2d, 0xf0, 0xb0, 0x11, 0x92, 0xe0,
+		0xa2, 0x2a, 0xa0, 0xb5, 0x82, 0xe0, 0x50, 0x03,
+		0x79, 0x0f, 0xe3, 0x71, 0xca, 0x51, 0x1e, 0x91,
+		0xe4, 0x53, 0xa8, 0xfb, 0x10, 0x10, 0x02, 0x80,
+		0x26, 0xc2, 0x8e, 0xd2, 0xab, 0xa2, 0x1c, 0x40,
+		0x13, 0xa2, 0x1d, 0x50, 0x0a, 0x43, 0x08, 0x40,
+		0x12, 0x1a, 0x01, 0xd1, 0xd7, 0x80, 0x0b, 0x12,
+		0x26, 0x04, 0x61, 0x08, 0x43, 0x08, 0x40, 0x12,
+		0x1a, 0x01, 0xd2, 0x1f, 0x12, 0x17, 0x7f, 0x43,
+		0xa8, 0x04, 0x51, 0x1e, 0x91, 0xe4, 0x12, 0x13,
+		0x34, 0x80, 0x98, 0xa2, 0x17, 0x72, 0x16, 0x72,
+		0x15, 0x72, 0x2d, 0x50, 0x06, 0xfa, 0x12, 0x13,
+		0x66, 0x80, 0x25, 0xc2, 0x13, 0x30, 0x28, 0x05,
+		0x12, 0x02, 0xbe, 0x80, 0x1b, 0xb4, 0x10, 0x12,
+		0x78, 0x00, 0xf2, 0xe5, 0x30, 0xb4, 0x01, 0x06,
+		0x12, 0x03, 0x90, 0xd2, 0x19, 0x22, 0x12, 0x00,
+		0xdd, 0x22, 0x75, 0x30, 0x00, 0x12, 0x00, 0xa1,
+		0x22, 0x00, 0x00, 0x75, 0x1e, 0x00, 0x74, 0x0c,
+		0x12, 0x2b, 0x9b, 0x74, 0x40, 0x79, 0x05, 0xf3,
+		0x74, 0x49, 0x12, 0x2b, 0x9b, 0x74, 0x04, 0x79,
+		0x05, 0xf3, 0x75, 0x15, 0x04, 0x74, 0x10, 0x12,
+		0x2b, 0x9b, 0x74, 0x00, 0x79, 0x05, 0xf3, 0x74,
+		0x17, 0x12, 0x2b, 0x9b, 0x74, 0x00, 0x79, 0x05,
+		0xf3, 0x74, 0x1a, 0x12, 0x2b, 0x9b, 0x74, 0x00,
+		0x79, 0x05, 0xf3, 0x74, 0x0a, 0x12, 0x2b, 0x9b,
+		0x74, 0x20, 0x79, 0x05, 0xf3, 0x79, 0xe0, 0x77,
+		0x20, 0x22, 0xd0, 0x02, 0xd0, 0xd0, 0xd0, 0xf0,
+		0xd0, 0x01, 0xe5, 0x5f, 0xd0, 0xa8, 0x22, 0x00,
+		0x00, 0x90, 0x25, 0x9f, 0x75, 0x26, 0xff, 0x75,
+		0x27, 0xff, 0x75, 0x28, 0x03, 0x75, 0x13, 0xff,
+		0x75, 0x1f, 0x00, 0x75, 0x14, 0xff, 0x22, 0x79,
+		0x06, 0xe5, 0x29, 0x60, 0x0b, 0xe3, 0x30, 0xe1,
+		0xf8, 0xe5, 0x4f, 0x64, 0x80, 0x79, 0x07, 0xf3,
+		0x22, 0x10, 0x4c, 0x01, 0x22, 0x30, 0x4b, 0x0a,
+		0xc2, 0x4b, 0xe5, 0x4d, 0x64, 0x80, 0xf5, 0x4f,
+		0x80, 0x1d, 0xe5, 0x15, 0xa2, 0xe0, 0x82, 0xe6,
+		0x40, 0x02, 0x80, 0x35, 0x30, 0x4a, 0x04, 0xb1,
+		0xe6, 0x80, 0x0c, 0x30, 0x49, 0x04, 0x51, 0x2b,
+		0x80, 0x05, 0x30, 0x48, 0x24, 0x91, 0x7e, 0x79,
+		0x06, 0xe3, 0x30, 0xe0, 0x1a, 0x79, 0x06, 0xf3,
+		0xe5, 0x4e, 0x24, 0xff, 0x50, 0x04, 0xf5, 0x4e,
+		0x80, 0x0d, 0x79, 0x0f, 0xf3, 0x20, 0x2a, 0x07,
+		0x12, 0x2b, 0x32, 0x75, 0x29, 0x00, 0x22, 0x91,
+		0x1b, 0x22, 0x79, 0x0f, 0xe3, 0xc0, 0xa8, 0x75,
+		0xa8, 0x00, 0x30, 0x2b, 0x03, 0xd0, 0xa8, 0x22,
+		0x79, 0x0e, 0xf3, 0xd0, 0xa8, 0x22, 0x8a, 0xf0,
+		0xe5, 0x50, 0x10, 0xf3, 0x10, 0x23, 0x23, 0x23,
+		0x25, 0xf0, 0x12, 0x2c, 0xb8, 0xa2, 0xe7, 0x92,
+		0xe4, 0xc2, 0xe7, 0x80, 0x08, 0x23, 0x23, 0x23,
+		0x25, 0xf0, 0x12, 0x2c, 0x19, 0x25, 0x4f, 0x20,
+		0xd2, 0x04, 0xf5, 0x4f, 0x80, 0x0a, 0x40, 0x05,
+		0x75, 0x4f, 0x7f, 0x80, 0x03, 0x75, 0x4f, 0xff,
+		0xea, 0x12, 0x2c, 0x3c, 0x25, 0x50, 0x20, 0xe7,
+		0x05, 0xb4, 0x03, 0x07, 0x80, 0x0c, 0x75, 0x50,
+		0x00, 0x80, 0x09, 0x40, 0x05, 0x75, 0x50, 0x03,
+		0x80, 0x02, 0xf5, 0x50, 0x22, 0xe5, 0x4d, 0xc4,
+		0x54, 0x0c, 0x03, 0x03, 0xfa, 0x91, 0xa9, 0x71,
+		0xb8, 0xe5, 0x4d, 0xc4, 0x54, 0x03, 0xfa, 0x91,
+		0xa9, 0x71, 0xb8, 0xe5, 0x4d, 0x54, 0x0c, 0x03,
+		0x03, 0xfa, 0x91, 0xa9, 0x71, 0xb8, 0xe5, 0x4d,
+		0x54, 0x03, 0xfa, 0x91, 0xa9, 0x71, 0xb8, 0x22,
+		0x8a, 0xf0, 0xe5, 0x50, 0x23, 0x23, 0x25, 0xf0,
+		0x12, 0x2b, 0xf6, 0x25, 0x4f, 0x20, 0xd2, 0x04,
+		0xf5, 0x4f, 0x80, 0x0a, 0x40, 0x05, 0x75, 0x4f,
+		0x7f, 0x80, 0x03, 0x75, 0x4f, 0xff, 0xea, 0x12,
+		0x2c, 0x40, 0x25, 0x50, 0x20, 0xe7, 0x05, 0xb4,
+		0x05, 0x07, 0x80, 0x0c, 0x75, 0x50, 0x00, 0x80,
+		0x09, 0x40, 0x05, 0x75, 0x50, 0x05, 0x80, 0x02,
+		0xf5, 0x50, 0x22, 0x30, 0x26, 0x03, 0x12, 0x1e,
+		0xf5, 0x30, 0x27, 0x03, 0x12, 0x1f, 0x37, 0x30,
+		0x25, 0x09, 0x12, 0x1f, 0x4e, 0x30, 0x23, 0x03,
+		0x12, 0x1f, 0x1e, 0x10, 0x22, 0x02, 0x80, 0x0a,
+		0xe5, 0x3b, 0xb4, 0xff, 0x02, 0xc2, 0x20, 0x12,
+		0x1e, 0x79, 0x22, 0x78, 0x11, 0xe2, 0x20, 0xe0,
+		0x07, 0xc0, 0x01, 0x12, 0x28, 0xba, 0xd0, 0x01,
+		0x78, 0x00, 0xf2, 0x61, 0x9b, 0x12, 0x2b, 0x32,
+		0x12, 0x17, 0x7f, 0x78, 0x00, 0xf2, 0xaa, 0x35,
+		0xab, 0x36, 0xea, 0x24, 0xff, 0xfa, 0xeb, 0x34,
+		0xff, 0xfb, 0x50, 0x03, 0xd2, 0x10, 0x22, 0x75,
+		0x37, 0x01, 0x75, 0x38, 0x00, 0x75, 0x39, 0x00,
+		0x12, 0x04, 0x04, 0xd2, 0x8e, 0x22, 0xa8, 0x2b,
+		0xb8, 0x00, 0x02, 0x80, 0x03, 0x02, 0x11, 0xbd,
+		0xf5, 0x74, 0x78, 0x2a, 0x12, 0x11, 0xec, 0xe5,
+		0x74, 0x78, 0x29, 0x12, 0x11, 0xec, 0x22, 0xfa,
+		0xe5, 0x2b, 0x60, 0x01, 0x22, 0xea, 0x78, 0x2b,
+		0xf5, 0x75, 0x12, 0x11, 0xec, 0x22, 0x74, 0x10,
+		0x12, 0x2b, 0x9b, 0x74, 0x20, 0x78, 0x05, 0xf2,
+		0x74, 0x09, 0x12, 0x17, 0x75, 0xe5, 0x15, 0x44,
+		0x80, 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x12, 0x17,
+		0x7f, 0x22, 0x12, 0x03, 0x84, 0x79, 0x0f, 0xe3,
+		0x78, 0x00, 0xf2, 0x12, 0x2b, 0x28, 0xe5, 0x81,
+		0x24, 0xfc, 0xf5, 0x81, 0x61, 0x93, 0xd2, 0x07,
+		0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x4c, 0xc2,
+		0x0f, 0x12, 0x29, 0xa3, 0x61, 0x93, 0x02, 0x1b,
+		0x77, 0x00, 0xe1, 0x81, 0xe1, 0x9a, 0xd2, 0x2c,
+		0xa1, 0x0c, 0x20, 0x20, 0x02, 0xd2, 0x26, 0x02,
+		0x1e, 0x35, 0x02, 0x1e, 0x61, 0x02, 0x1d, 0x8f,
+		0xc2, 0x8e, 0x75, 0xa8, 0x9e, 0x22, 0x41, 0x49,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x02, 0x29, 0x91, 0x00, 0x00, 0x00, 0xa1, 0xbb,
+		0xa1, 0xc3, 0x02, 0x1e, 0x6b, 0xe5, 0x4d, 0xc4,
+		0x54, 0x0f, 0xfa, 0x91, 0x2f, 0x71, 0xb8, 0xe5,
+		0x4d, 0x54, 0x0f, 0xfa, 0x91, 0x2f, 0x71, 0xb8,
+		0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xc6,
+		0x02, 0x1d, 0x8f, 0xc2, 0x8e, 0xd2, 0xab, 0xc2,
+		0x10, 0x79, 0x0f, 0xf3, 0x22, 0x00, 0x02, 0x2a,
+		0x84, 0x00, 0xe1, 0xbc, 0xe1, 0xc8, 0x02, 0x1e,
+		0x27, 0x00, 0x78, 0x00, 0xf2, 0x78, 0x0b, 0xe2,
+		0xf4, 0xf5, 0x4d, 0xd2, 0x4c, 0x61, 0x9b, 0x30,
+		0xb5, 0x02, 0xc2, 0x11, 0x22, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x79, 0xbd, 0xf1, 0x3d, 0x83,
+		0x22, 0xdd, 0xbd, 0xbd, 0xbd, 0x61, 0xbd, 0x8d,
+		0x7a, 0xbd, 0xbd, 0xbd, 0xbd, 0x30, 0xbd, 0xbd,
+		0xbd, 0x55, 0xbd, 0xbd, 0xbd, 0x52, 0xbd, 0xb6,
+		0xb6, 0xbd, 0xbd, 0xbd, 0xbd, 0x00, 0xbd, 0xbd,
+		0xbd, 0xe8, 0xda, 0xbd, 0xbd, 0xcf, 0xb9, 0xbd,
+		0xc4, 0xf1, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		0xbd, 0x7b, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		0xbd, 0x70, 0x6a, 0x57, 0x47, 0x34, 0xbd, 0xbd,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x29, 0xbd,
+		0xbd, 0xbd, 0xb6, 0xb6, 0xbd, 0xbd, 0xbd, 0xbd,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x2e, 0x25,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xfe, 0xf5,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x19, 0xbd,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x21, 0x8f,
+		0x09, 0xbd, 0xf9, 0x86, 0xbd, 0xbd, 0xbd, 0xd7,
+		0xbd, 0xa9, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x9b,
+		0xd1, 0x9d, 0xbd, 0xae, 0xbd, 0xbd, 0xbd, 0xcb,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		0xb6, 0xa5, 0xbd, 0xc5, 0xbd, 0xbd, 0xbd, 0xc3,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x74, 0x10,
+		0x12, 0x2b, 0x9b, 0xe4, 0x78, 0x05, 0xf2, 0x74,
+		0x09, 0x12, 0x17, 0x75, 0xe5, 0x15, 0x54, 0x7f,
+		0x79, 0x05, 0xf3, 0xf5, 0x15, 0x12, 0x17, 0x7f,
+		0x22, 0x30, 0x51, 0x01, 0x22, 0x53, 0xa8, 0xfb,
+		0x12, 0x2d, 0xf0, 0x50, 0x22, 0x79, 0x03, 0xe3,
+		0x20, 0xe4, 0x1c, 0xaa, 0x35, 0xab, 0x36, 0xea,
+		0x24, 0xf0, 0xfa, 0xeb, 0x34, 0xff, 0xfb, 0x50,
+		0x0e, 0x10, 0x1f, 0x02, 0x80, 0x09, 0x20, 0x2a,
+		0x03, 0x12, 0x2b, 0x32, 0x12, 0x2d, 0xd6, 0x43,
+		0xa8, 0x04, 0x22, 0xa2, 0x1c, 0x72, 0x1d, 0x40,
+		0x07, 0x53, 0x08, 0xbf, 0x78, 0x00, 0xf2, 0x22,
+		0xb1, 0x1e, 0x22, 0x00, 0x79, 0x02, 0x12, 0x27,
+		0x3d, 0x02, 0x2d, 0x37, 0x14, 0x54, 0xf0, 0x60,
+		0x21, 0xe5, 0xf0, 0x24, 0xb6, 0xe5, 0xf0, 0x50,
+		0x16, 0x24, 0x8b, 0x50, 0x15, 0xe5, 0xf0, 0x24,
+		0x56, 0xe5, 0xf0, 0x50, 0x08, 0x24, 0x2f, 0x50,
+		0x09, 0xe5, 0xf0, 0x24, 0xd9, 0x24, 0xd5, 0x24,
+		0xf0, 0x22, 0x15, 0x81, 0x15, 0x81, 0xe9, 0x22,
+		0x78, 0x13, 0x74, 0x00, 0xf2, 0x75, 0x2e, 0x01,
+		0xd2, 0x6a, 0xc2, 0x69, 0xc2, 0x68, 0xc2, 0x6c,
+		0x90, 0x25, 0x9f, 0x75, 0xb8, 0x07, 0x41, 0xa4,
+		0xc0, 0x01, 0xc0, 0xf0, 0xc0, 0xd0, 0xc0, 0x02,
+		0xe5, 0x3d, 0x54, 0x7d, 0x03, 0x10, 0xe5, 0x05,
+		0x90, 0x28, 0x4b, 0x80, 0x03, 0x90, 0x2b, 0x7c,
+		0x73, 0xe5, 0x3d, 0x30, 0xe5, 0x07, 0x74, 0xfd,
+		0x78, 0x00, 0xf2, 0x61, 0x9b, 0x90, 0x1a, 0x97,
+		0x74, 0xb6, 0xc0, 0xe0, 0x74, 0x27, 0xc0, 0xe0,
+		0xc0, 0xa8, 0x02, 0x1b, 0xab, 0x90, 0x25, 0x9f,
+		0xd0, 0xa8, 0x22, 0x90, 0x27, 0xb6, 0xc0, 0x82,
+		0xc0, 0x83, 0xc0, 0xa8, 0x02, 0x1d, 0xa6, 0x90,
+		0x27, 0xb6, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0xa8,
+		0x02, 0x1e, 0x0a, 0xea, 0x24, 0xf0, 0xfa, 0xeb,
+		0x34, 0xff, 0xfb, 0x50, 0x2e, 0x20, 0x0b, 0x05,
+		0x85, 0x44, 0xe0, 0x80, 0x03, 0x75, 0xe0, 0x00,
+		0x30, 0xe1, 0x20, 0xe5, 0x35, 0x24, 0xff, 0xf5,
+		0x35, 0xe5, 0x36, 0x34, 0xff, 0xf5, 0x36, 0xc3,
+		0xe5, 0x36, 0x13, 0xf5, 0x36, 0xe5, 0x35, 0x13,
+		0xf5, 0x35, 0x75, 0x3a, 0x10, 0x12, 0x1a, 0x77,
+		0x02, 0x18, 0x77, 0x75, 0x3a, 0x00, 0x12, 0x1a,
+		0x77, 0x02, 0x18, 0x1b, 0x20, 0x4b, 0x04, 0x75,
+		0x4e, 0x03, 0x22, 0xe5, 0x35, 0x24, 0xff, 0xf5,
+		0x35, 0xe5, 0x36, 0x34, 0xff, 0xf5, 0x36, 0x75,
+		0x4e, 0x03, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x2c,
+		0x70, 0xd2, 0x00, 0x78, 0x11, 0xe2, 0x44, 0x11,
+		0xf5, 0x3f, 0xc2, 0x08, 0x12, 0x29, 0xa3, 0x02,
+		0x23, 0x93, 0x21, 0x62, 0x61, 0x40, 0x01, 0x3a,
+		0x01, 0x73, 0x21, 0x76, 0x61, 0xa8, 0x21, 0x39,
+		0x21, 0x4a, 0x02, 0x2a, 0x7b, 0x79, 0x06, 0xf3,
+		0xc0, 0xd0, 0x12, 0x03, 0xd9, 0x78, 0x00, 0xf2,
+		0xd0, 0xd0, 0x22, 0x00, 0x00, 0x00, 0x00, 0x02,
+		0x2c, 0xb4, 0x78, 0x11, 0xe2, 0x44, 0x11, 0x54,
+		0x0f, 0xf8, 0xc4, 0x48, 0xd2, 0x05, 0xf5, 0x48,
+		0xc2, 0x0d, 0x31, 0xa3, 0x02, 0x23, 0x93, 0x20,
+		0x4b, 0x04, 0x75, 0x4e, 0x01, 0x22, 0xe5, 0x35,
+		0x24, 0xff, 0xf5, 0x35, 0xe5, 0x36, 0x34, 0xff,
+		0xf5, 0x36, 0x75, 0x4e, 0x01, 0x22, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x79, 0xd0, 0x77, 0x1b, 0x79, 0xd1, 0x77, 0x18,
+		0x79, 0xd2, 0x77, 0x77, 0x79, 0xd3, 0x77, 0x18,
+		0x22, 0x75, 0x29, 0x00, 0x75, 0x25, 0x00, 0x75,
+		0x34, 0x03, 0x75, 0x22, 0x00, 0x75, 0x23, 0x05,
+		0x75, 0x4f, 0x00, 0x75, 0x50, 0x00, 0x75, 0x30,
+		0x00, 0x79, 0xdc, 0x77, 0x03, 0xc2, 0x8e, 0x75,
+		0x17, 0xa8, 0x75, 0x16, 0xa8, 0x74, 0xaa, 0x79,
+		0x01, 0xf3, 0x79, 0xd7, 0x77, 0x74, 0x79, 0xd8,
+		0x77, 0xff, 0x79, 0xd9, 0x77, 0x07, 0x79, 0xda,
+		0x77, 0x00, 0x12, 0x25, 0x6f, 0x43, 0x08, 0x40,
+		0x71, 0x32, 0x79, 0x0e, 0xe3, 0x10, 0x51, 0x1c,
+		0x74, 0x06, 0x71, 0x9b, 0xe5, 0x11, 0x44, 0x80,
+		0x79, 0x05, 0xf3, 0xf5, 0x11, 0x74, 0x07, 0x71,
+		0x9b, 0xe5, 0x12, 0x44, 0x80, 0x79, 0x05, 0xf3,
+		0xf5, 0x12, 0x80, 0x18, 0x53, 0x27, 0xa0, 0x53,
+		0x28, 0x01, 0x75, 0x20, 0xf7, 0x12, 0x23, 0x4c,
+		0x75, 0x11, 0x80, 0x75, 0x12, 0x80, 0x12, 0x1f,
+		0xc0, 0x12, 0x21, 0xdc, 0x79, 0x06, 0xf3, 0x22,
+		0xd2, 0x02, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5,
+		0x43, 0xc2, 0x0a, 0x12, 0x29, 0xa3, 0x02, 0x23,
+		0x93, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x44,
+		0xc2, 0x0b, 0x12, 0x29, 0xa3, 0x02, 0x23, 0x93,
+		0x78, 0x00, 0xe2, 0x90, 0x25, 0x9f, 0x02, 0x23,
+		0x93, 0x78, 0x11, 0xe2, 0x75, 0x20, 0xf7, 0x75,
+		0x21, 0x3f, 0x75, 0x49, 0x11, 0x75, 0x4c, 0x11,
+		0x31, 0xa3, 0x02, 0x23, 0x93, 0x78, 0x11, 0xe2,
+		0x44, 0x11, 0x54, 0x0f, 0xf8, 0xc4, 0x48, 0xf8,
+		0xe5, 0x49, 0x45, 0x3f, 0x58, 0xf5, 0x49, 0xd2,
+		0x06, 0xc2, 0x0e, 0x31, 0xa3, 0x02, 0x23, 0x93,
+		0xc0, 0x01, 0x20, 0x2a, 0x04, 0x71, 0x32, 0xc2,
+		0x11, 0x11, 0x5e, 0xc2, 0x1f, 0xd0, 0x01, 0x02,
+		0x23, 0x9b, 0x12, 0x21, 0xdc, 0x78, 0x00, 0xf2,
+		0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xda,
+		0xe7, 0x70, 0x2b, 0x20, 0x0a, 0x05, 0x85, 0x43,
+		0xe0, 0x80, 0x03, 0x75, 0xe0, 0x00, 0x30, 0xe1,
+		0x1d, 0x20, 0xe2, 0x1f, 0x74, 0xe0, 0xca, 0x74,
+		0x00, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, 0xf5,
+		0x09, 0xca, 0x74, 0x01, 0x71, 0x9b, 0xca, 0x79,
+		0x05, 0xf3, 0xf5, 0x0a, 0x80, 0x43, 0x12, 0x15,
+		0x3e, 0x80, 0x3e, 0xe5, 0x0b, 0xb4, 0x17, 0x02,
+		0x80, 0x0b, 0x50, 0x09, 0x74, 0x17, 0xc3, 0x95,
+		0x0b, 0x44, 0x60, 0x80, 0x02, 0x74, 0x60, 0xca,
+		0x74, 0x00, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3,
+		0xf5, 0x09, 0xe5, 0x0c, 0xb4, 0x17, 0x02, 0x80,
+		0x0b, 0x50, 0x09, 0x74, 0x17, 0xc3, 0x95, 0x0c,
+		0x44, 0x60, 0x80, 0x02, 0x74, 0x60, 0xca, 0x74,
+		0x01, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, 0xf5,
+		0x0a, 0x22, 0xd2, 0x04, 0x78, 0x11, 0xe2, 0x44,
+		0x11, 0xf5, 0x46, 0xc2, 0x0c, 0x31, 0xa3, 0x02,
+		0x23, 0x93, 0xd2, 0x05, 0x78, 0x11, 0xe2, 0x44,
+		0x11, 0xf5, 0x48, 0xc2, 0x0d, 0x31, 0xa3, 0x02,
+		0x23, 0x93, 0xd2, 0x06, 0x78, 0x11, 0xe2, 0x44,
+		0x11, 0xf5, 0x49, 0xc2, 0x0e, 0x31, 0xa3, 0x02,
+		0x23, 0x93, 0x30, 0x1c, 0x21, 0x20, 0x4d, 0x1e,
+		0xe5, 0x29, 0x60, 0x1a, 0xc2, 0x1c, 0x12, 0x19,
+		0xec, 0x12, 0x13, 0xcf, 0xd2, 0x4d, 0x12, 0x17,
+		0x7f, 0x78, 0x00, 0xf2, 0x79, 0x06, 0xf3, 0x43,
+		0xa8, 0x04, 0x12, 0x24, 0x1b, 0x22, 0x12, 0x27,
+		0x24, 0x22, 0x78, 0x00, 0xe2, 0x90, 0x25, 0x9f,
+		0x02, 0x23, 0x93, 0x78, 0x00, 0xe2, 0xa2, 0xe7,
+		0x72, 0xe3, 0x92, 0xe7, 0x02, 0x1d, 0x85, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x79, 0x04, 0xe3, 0x54, 0x80, 0x70, 0xf9, 0x22,
+		0xe5, 0x29, 0x79, 0xde, 0xf7, 0x75, 0x29, 0x00,
+		0x70, 0x12, 0xe5, 0x15, 0x79, 0xdd, 0xf7, 0x12,
+		0x2d, 0xf0, 0x40, 0x08, 0x20, 0x1c, 0x07, 0x20,
+		0x1d, 0x04, 0x80, 0x02, 0x71, 0x32, 0x30, 0xb5,
+		0x0c, 0x79, 0x06, 0xf3, 0x20, 0x2a, 0x06, 0x79,
+		0xdd, 0xe7, 0x54, 0xfc, 0xf7, 0xd2, 0x2b, 0x12,
+		0x25, 0x6f, 0x22, 0x00, 0x00, 0x00, 0x00, 0xe5,
+		0x15, 0xa2, 0xe0, 0xb0, 0xe6, 0x40, 0x31, 0xa2,
+		0xe1, 0xb0, 0xe7, 0x40, 0x38, 0x10, 0x2b, 0x02,
+		0x80, 0x26, 0x79, 0xde, 0xe7, 0x70, 0x0b, 0x79,
+		0xdd, 0xe7, 0x20, 0xe0, 0x12, 0x20, 0xe1, 0x28,
+		0x80, 0x16, 0xf5, 0x29, 0x30, 0x4d, 0x11, 0x20,
+		0x4c, 0x0e, 0x12, 0x24, 0x1b, 0x80, 0x09, 0x43,
+		0x08, 0x40, 0x12, 0x13, 0xcf, 0x12, 0x17, 0x7f,
+		0xe5, 0x13, 0x20, 0xe4, 0x05, 0x12, 0x18, 0x1b,
+		0x80, 0x03, 0x12, 0x18, 0x77, 0xc2, 0x2b, 0x22,
+		0x12, 0x26, 0xd7, 0x12, 0x13, 0xb7, 0x22, 0x78,
+		0x04, 0x79, 0x00, 0xd9, 0xfe, 0xd8, 0xfa, 0x22,
+		0x00, 0x74, 0x09, 0x71, 0x9b, 0xe5, 0x15, 0x54,
+		0xfc, 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x22, 0x78,
+		0x11, 0xe2, 0x44, 0x11, 0x54, 0x0f, 0xf8, 0xc4,
+		0x48, 0xf5, 0x46, 0xc2, 0x0c, 0xd2, 0x04, 0x31,
+		0xa3, 0x02, 0x23, 0x93, 0x12, 0x26, 0xd7, 0x12,
+		0x00, 0xb7, 0x22, 0x00, 0x79, 0x06, 0xf3, 0x74,
+		0x0a, 0x71, 0x9b, 0x79, 0xe0, 0xe7, 0x44, 0x02,
+		0xf7, 0x79, 0x05, 0xf3, 0x22, 0x74, 0x0a, 0x71,
+		0x9b, 0x79, 0xe0, 0xe7, 0x54, 0xfd, 0xf7, 0x79,
+		0x05, 0xf3, 0x22, 0x21, 0x59, 0x41, 0x23, 0x21,
+		0x59, 0x41, 0x33, 0x41, 0x43, 0x21, 0x59, 0x21,
+		0x59, 0x02, 0x25, 0x9f, 0x00, 0x74, 0x0d, 0x71,
+		0x9b, 0x74, 0x4d, 0x79, 0x05, 0xf3, 0xd2, 0x52,
+		0x22, 0x00, 0x53, 0x08, 0x40, 0x45, 0x08, 0x45,
+		0x1e, 0x79, 0x04, 0xf3, 0xf5, 0x08, 0x22, 0xd2,
+		0x01, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x42,
+		0xc2, 0x09, 0x31, 0xa3, 0x02, 0x23, 0x93, 0x00,
+		0x00, 0x00, 0x00, 0x71, 0x6e, 0x74, 0x09, 0x12,
+		0x17, 0x75, 0xe5, 0x15, 0x44, 0x40, 0x79, 0x05,
+		0xf3, 0xf5, 0x15, 0x75, 0x3a, 0x00, 0x12, 0x1a,
+		0x77, 0x02, 0x18, 0x1b, 0xf5, 0x38, 0xe5, 0x37,
+		0x24, 0x01, 0xf5, 0x37, 0xe5, 0x38, 0x34, 0x00,
+		0xf5, 0x38, 0x40, 0x05, 0x75, 0x39, 0x00, 0x80,
+		0x03, 0x75, 0x39, 0x01, 0x12, 0x04, 0x04, 0xd2,
+		0x8e, 0x02, 0x03, 0x8d, 0x00, 0xb4, 0x0d, 0x03,
+		0x74, 0x14, 0x22, 0x04, 0x83, 0x22, 0x00, 0x02,
+		0xff, 0x01, 0x00, 0x05, 0xfe, 0xff, 0x00, 0x0a,
+		0xfc, 0xfe, 0x00, 0xc0, 0xf8, 0xfc, 0x00, 0x28,
+		0xf0, 0xf8, 0x00, 0x30, 0xe0, 0xd0, 0x01, 0x88,
+		0x04, 0x83, 0x22, 0x00, 0xff, 0xfe, 0xfd, 0xfc,
+		0xfc, 0xfb, 0xfa, 0xfe, 0xfd, 0xfb, 0xf9, 0xf7,
+		0xf7, 0xf5, 0xf3, 0xfc, 0xfa, 0xf6, 0xf2, 0xee,
+		0xee, 0xea, 0xe6, 0xf8, 0xf4, 0xec, 0xe4, 0xdc,
+		0xd4, 0xcc, 0xc4, 0x24, 0x21, 0x83, 0x22, 0x04,
+		0x83, 0x22, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00,
+		0x00, 0x02, 0x22, 0x32, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xff,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x83,
+		0x22, 0x8a, 0x01, 0x20, 0x01, 0x0b, 0xea, 0xf3,
+		0xf9, 0x8b, 0x7e, 0x6b, 0xd5, 0x01, 0x00, 0x01,
+		0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x01, 0x3a, 0x01, 0x38, 0x01, 0x4b, 0x01,
+		0x49, 0x01, 0x5c, 0x01, 0x5a, 0x01, 0x08, 0x08,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x01, 0x15, 0x24, 0x48, 0x83, 0x22, 0x04,
+		0x83, 0x22, 0x00, 0x01, 0x02, 0x03, 0x04, 0x06,
+		0x07, 0x08, 0x00, 0x03, 0x05, 0x07, 0x09, 0x0d,
+		0x0f, 0x81, 0x00, 0x06, 0x0a, 0x0e, 0x82, 0x8a,
+		0x8e, 0x22, 0x00, 0x0c, 0x84, 0x8c, 0x24, 0x2c,
+		0xa4, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xaa, 0x35, 0xab, 0x36,
+		0x02, 0x27, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+		0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x25,
+		0x03, 0x03, 0x2b, 0x03, 0x00, 0x03, 0x00, 0x03,
+		0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x22,
+		0x00, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
+		0x2b, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
+		0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01,
+		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
+		0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02,
+		0x21, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00,
+		0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x21,
+		0x01, 0x02, 0x21, 0x02, 0x02, 0x02, 0x00, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x20, 0xb5, 0x05,
+		0x79, 0x0f, 0xf3, 0xc2, 0x11, 0x22, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5,
+		0x15, 0xa2, 0xe0, 0xb0, 0xe6, 0x50, 0x01, 0x22,
+		0xa2, 0xe1, 0xb0, 0xe7, 0x22, 0x02, 0x00};
+		static unsigned char	Data0485_0C[] = {
+		0x02, 0x27, 0x69};
+		static unsigned char	Data0485_66[] = {
+		0x02, 0x25, 0x47, 0x02, 0x25, 0x60};
+		static unsigned char	Data0485_60[] = {
+		0x02, 0x22, 0x7e};
+		static unsigned char	Data0485_99[] = {
+		0xc2, 0x53, 0x02, 0x12, 0x86};
+		static unsigned char	Data0485_9E[] = {
+		0x70, 0xf9, 0x22};
+#ifdef OOKUBO_ORIGINAL
+		static unsigned char	Data0485_36[] = {
+		0x78, 0x00, 0xf2, 0xc2, 0x53, 0x74, 0x86, 0xc0,
+		0xe0, 0x74, 0x12, 0xc0,	0xe0, 0x32};
+#endif /* OOKUBO_ORIGINAL */
diff -urN linux-2.5.65-bk2/sound/isa/cs423x/sound_pc9800.h linux-2.5.65-bk3/sound/isa/cs423x/sound_pc9800.h
--- linux-2.5.65-bk2/sound/isa/cs423x/sound_pc9800.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.65-bk3/sound/isa/cs423x/sound_pc9800.h	Mon Mar 31 12:41:50 2003
@@ -0,0 +1,23 @@
+#ifndef _SOUND_PC9800_H_
+#define _SOUND_PC9800_H_
+
+#include <asm/io.h>
+
+#define PC9800_SOUND_IO_ID	0xa460
+
+/* Sound Functions ID. */
+#define PC9800_SOUND_ID()	((inb(PC9800_SOUND_IO_ID) >> 4) & 0x0f)
+
+#define PC9800_SOUND_ID_DO	0x0	/* PC-98DO+ Internal */
+#define PC9800_SOUND_ID_GS	0x1	/* PC-98GS Internal */
+#define PC9800_SOUND_ID_73	0x2	/* PC-9801-73 (base 0x18x) */
+#define PC9800_SOUND_ID_73A	0x3	/* PC-9801-73/76 (base 0x28x) */
+#define PC9800_SOUND_ID_86	0x4	/* PC-9801-86 and compatible (base 0x18x) */
+#define PC9800_SOUND_ID_86A	0x5	/* PC-9801-86 (base 0x28x) */
+#define PC9800_SOUND_ID_NF	0x6	/* PC-9821Nf/Np Internal */
+#define PC9800_SOUND_ID_XMATE	0x7	/* X-Mate Internal and compatible */
+#define PC9800_SOUND_ID_118	0x8	/* PC-9801-118 and compatible(CanBe Internal, etc.) */
+
+#define PC9800_SOUND_ID_UNKNOWN	0xf	/* Unknown (No Sound System or PC-9801-26) */
+
+#endif
diff -urN linux-2.5.65-bk2/sound/isa/opti9xx/opti92x-ad1848.c linux-2.5.65-bk3/sound/isa/opti9xx/opti92x-ad1848.c
--- linux-2.5.65-bk2/sound/isa/opti9xx/opti92x-ad1848.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/sound/isa/opti9xx/opti92x-ad1848.c	Mon Mar 31 12:41:50 2003
@@ -326,11 +326,11 @@
 static long snd_legacy_find_free_ioport(long *port_table, long size)
 {
 	while (*port_table != -1) {
-		if (!check_region(*port_table, size))
+		if (request_region(*port_table, size, "opti92x-ad1848"))
 			return *port_table;
 		port_table++;
 	}
-	return -1;
+	return SNDRV_AUTO_PORT;
 }
 
 static int __init snd_opti9xx_init(opti9xx_t *chip, unsigned short hardware)
@@ -1917,6 +1917,10 @@
 #ifdef __ISAPNP__
 		snd_card_opti9xx_deactivate(chip);
 #endif	/* __ISAPNP__ */
+		if (chip->wss_base != SNDRV_AUTO_PORT)
+			release_region(chip->wss_base, 4);
+		if (chip->mpu_port != SNDRV_AUTO_PORT)
+			release_region(chip->mpu_port, 2);
 		if (chip->res_mc_base) {
 			release_resource(chip->res_mc_base);
 			kfree_nocheck(chip->res_mc_base);
@@ -1962,6 +1966,16 @@
 	card->private_free = snd_card_opti9xx_free;
 	chip = (opti9xx_t *)card->private_data;
 
+	chip->wss_base = port;
+	chip->fm_port = fm_port;
+	chip->mpu_port = mpu_port;
+	chip->irq = irq;
+	chip->mpu_irq = mpu_irq;
+	chip->dma1 = dma1;
+#if defined(CS4231) || defined(OPTi93X)
+	chip->dma2 = dma2;
+#endif
+
 #ifdef __ISAPNP__
 	if (isapnp && (hw = snd_card_opti9xx_isapnp(chip)) > 0) {
 		switch (hw) {
@@ -2000,28 +2014,18 @@
 		return -ENOMEM;
 	}
 
-	chip->wss_base = port;
-	chip->fm_port = fm_port;
-	chip->mpu_port = mpu_port;
-	chip->irq = irq;
-	chip->mpu_irq = mpu_irq;
-	chip->dma1 = dma1;
-#if defined(CS4231) || defined(OPTi93X)
-	chip->dma2 = dma2;
-#endif
-
 #ifdef __ISAPNP__
 	if (!isapnp) {
 #endif
 	if (chip->wss_base == SNDRV_AUTO_PORT) {
-		if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
+		if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) == SNDRV_AUTO_PORT) {
 			snd_card_free(card);
 			snd_printk("unable to find a free WSS port\n");
 			return -EBUSY;
 		}
 	}
 	if (chip->mpu_port == SNDRV_AUTO_PORT) {
-		if ((chip->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
+		if ((chip->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) == SNDRV_AUTO_PORT) {
 			snd_card_free(card);
 			snd_printk("unable to find a free MPU401 port\n");
 			return -EBUSY;
diff -urN linux-2.5.65-bk2/sound/isa/sb/es968.c linux-2.5.65-bk3/sound/isa/sb/es968.c
--- linux-2.5.65-bk2/sound/isa/sb/es968.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/sound/isa/sb/es968.c	Mon Mar 31 12:41:50 2003
@@ -23,11 +23,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/time.h>
-#ifndef LINUX_ISAPNP_H
-#include <linux/isapnp.h>
-#define isapnp_card pci_bus
-#define isapnp_dev pci_dev
-#endif
+#include <linux/pnp.h>
 #include <sound/core.h>
 #define SNDRV_GET_ID
 #include <sound/initval.h>
@@ -35,6 +31,8 @@
 
 #define chip_t sb_t
 
+#define PFX "es968: "
+
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("ESS AudioDrive ES968");
 MODULE_LICENSE("GPL");
@@ -68,32 +66,18 @@
 MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 struct snd_card_es968 {
-#ifdef __ISAPNP__
-	struct isapnp_dev *dev;
-#endif	/* __ISAPNP__ */
+	struct pnp_dev *dev;
 };
 
-static snd_card_t *snd_es968_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
-#ifdef __ISAPNP__
-static struct isapnp_card *snd_es968_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
-static const struct isapnp_card_id *snd_es968_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
-
-static struct isapnp_card_id snd_es968_pnpids[] __devinitdata = {
-        {
-                ISAPNP_CARD_ID('E','S','S',0x0968),
-                .devs = { ISAPNP_DEVICE_ID('E','S','S',0x0968), }
-        },
-        { ISAPNP_CARD_END, }
+static struct pnp_card_id snd_es968_pnpids[] __devinitdata = {
+	{ .id = "ESS0968", .devs = { { "@@@0968" }, } },
+	{ .id = "", } /* end */
 };
 
-ISAPNP_CARD_TABLE(snd_es968_pnpids);
-
-#endif	/* __ISAPNP__ */
+MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids);
 
 #define	DRIVER_NAME	"snd-card-es968"
 
-
 static void snd_card_es968_interrupt(int irq, void *dev_id,
 				     struct pt_regs *regs)
 {
@@ -106,64 +90,50 @@
 	}
 }
 
-#ifdef __ISAPNP__
-static int __init snd_card_es968_isapnp(int dev, struct snd_card_es968 *acard)
-{
-	const struct isapnp_card_id *id = snd_es968_isapnp_id[dev];
-	struct isapnp_card *card = snd_es968_isapnp_cards[dev];
-	struct isapnp_dev *pdev;
-
-	acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
-	if (acard->dev->active) {
-		acard->dev = NULL;
-		return -EBUSY;
+static int __devinit snd_card_es968_isapnp(int dev, struct snd_card_es968 *acard,
+					struct pnp_card_link *card,
+					const struct pnp_card_id *id)
+{
+	struct pnp_dev *pdev;
+	struct pnp_resource_table * cfg = kmalloc(GFP_ATOMIC, sizeof(struct pnp_resource_table));
+	int err;
+	if (!cfg)
+		return -ENOMEM;
+	acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
+	if (acard->dev == NULL) {
+		kfree(cfg);
+		return -ENODEV;
 	}
 
 	pdev = acard->dev;
-	if (pdev->prepare(pdev)<0)
-		return -EAGAIN;
 
+	pnp_init_resource_table(cfg);
+
+	/* override resources */
 	if (port[dev] != SNDRV_AUTO_PORT)
-		isapnp_resource_change(&pdev->resource[0], port[dev], 16);
+		pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
 	if (dma8[dev] != SNDRV_AUTO_DMA)
-		isapnp_resource_change(&pdev->dma_resource[0], dma8[dev],
-			1);
+		pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
 	if (irq[dev] != SNDRV_AUTO_IRQ)
-		isapnp_resource_change(&pdev->irq_resource[0], irq[dev], 1);
-
-	if (pdev->activate(pdev)<0) {
-		snd_printk("AUDIO isapnp configure failure\n");
-		return -EBUSY;
-	}
-
-	port[dev] = pdev->resource[0].start;
-	dma8[dev] = pdev->dma_resource[0].start;
-	irq[dev] = pdev->irq_resource[0].start;
+		pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
+	if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
+		printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
+	err = pnp_activate_dev(pdev);
+	if (err < 0) {
+		printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
+		return err;
+	}
+	port[dev] = pnp_port_start(pdev, 0);
+	dma8[dev] = pnp_dma(pdev, 1);
+	irq[dev] = pnp_irq(pdev, 0);
 
+	kfree(cfg);
 	return 0;
 }
 
-static void snd_card_es968_deactivate(struct snd_card_es968 *acard)
-{
-	if (acard->dev) {
-		acard->dev->deactivate(acard->dev);
-		acard->dev = NULL;
-	}
-}
-#endif	/* __ISAPNP__ */
-
-static void snd_card_es968_free(snd_card_t *card)
-{
-	struct snd_card_es968 *acard = (struct snd_card_es968 *)card->private_data;
-
-	if (acard) {
-#ifdef __ISAPNP__
-		snd_card_es968_deactivate(acard);
-#endif	/* __ISAPNP__ */
-	}
-}
-
-static int __init snd_card_es968_probe(int dev)
+static int __init snd_card_es968_probe(int dev,
+					struct pnp_card_link *pcard,
+					const struct pnp_card_id *pid)
 {
 	int error;
 	sb_t *chip;
@@ -174,18 +144,10 @@
 				 sizeof(struct snd_card_es968))) == NULL)
 		return -ENOMEM;
 	acard = (struct snd_card_es968 *)card->private_data;
-	card->private_free = snd_card_es968_free;
-
-#ifdef __ISAPNP__
-	if ((error = snd_card_es968_isapnp(dev, acard))) {
+	if ((error = snd_card_es968_isapnp(dev, acard, pcard, pid))) {
 		snd_card_free(card);
 		return error;
 	}
-#else
-	snd_printk("you have to enable PnP support ...\n");
-	snd_card_free(card);
-	return -ENOSYS;
-#endif	/* __ISAPNP__ */
 
 	if ((error = snd_sbdsp_create(card, port[dev],
 				      irq[dev],
@@ -221,13 +183,12 @@
 		snd_card_free(card);
 		return error;
 	}
-	snd_es968_cards[dev] = card;
+	pnp_set_card_drvdata(pcard, card);
 	return 0;
 }
 
-#ifdef __ISAPNP__
-static int __init snd_es968_isapnp_detect(struct isapnp_card *card,
-                                          const struct isapnp_card_id *id)
+static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card,
+                                          const struct pnp_card_id *id)
 {
 	static int dev;
 	int res;
@@ -235,9 +196,7 @@
 	for ( ; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev])
 			continue;
-		snd_es968_isapnp_cards[dev] = card;
-		snd_es968_isapnp_id[dev] = id;
-		res = snd_card_es968_probe(dev);
+		res = snd_card_es968_probe(dev, card, id);
 		if (res < 0)
 			return res;
 		dev++;
@@ -245,30 +204,31 @@
         }
         return -ENODEV;
 }
-#endif /* __ISAPNP__ */
 
-static int __init alsa_card_es968_init(void)
+static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard)
 {
-	int cards = 0;
+	snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
 
-#ifdef __ISAPNP__
-	cards += isapnp_probe_cards(snd_es968_pnpids, snd_es968_isapnp_detect);
-#else
-	snd_printk("you have to enable ISA PnP support.\n");
-#endif
-#ifdef MODULE
-	if (!cards)
-		snd_printk("no ES968 based soundcards found\n");
-#endif
-	return cards ? 0 : -ENODEV;
+	snd_card_disconnect(card);
+	snd_card_free_in_thread(card);
 }
 
-static void __exit alsa_card_es968_exit(void)
+static struct pnp_card_driver es968_pnpc_driver = {
+	.flags		= PNP_DRIVER_RES_DISABLE,
+	.name		= "es968",
+	.id_table	= snd_es968_pnpids,
+	.probe		= snd_es968_pnp_detect,
+	.remove		= __devexit_p(snd_es968_pnp_remove),
+};
+
+static int __init alsa_card_es968_init(void)
 {
-	int dev;
+	return (pnp_register_card_driver(&es968_pnpc_driver) ? 0 : -ENODEV);
+}
 
-	for (dev = 0; dev < SNDRV_CARDS; dev++)
-		snd_card_free(snd_es968_cards[dev]);
+static void __exit alsa_card_es968_exit(void)
+{
+	pnp_unregister_card_driver(&es968_pnpc_driver);
 }
 
 module_init(alsa_card_es968_init)
diff -urN linux-2.5.65-bk2/sound/oss/Kconfig linux-2.5.65-bk3/sound/oss/Kconfig
--- linux-2.5.65-bk2/sound/oss/Kconfig	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/sound/oss/Kconfig	Mon Mar 31 12:41:50 2003
@@ -113,15 +113,17 @@
 	  Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
 	  such as the Creative SBLive!, SB PCI512 or Emu-APS.
 
-	  For more information on this driver and the degree of support for the
-	  different card models please check <http://opensource.creative.com/>.
+	  For more information on this driver and the degree of support for
+	  the different card models please check:
+
+	        <http://sourceforge.net/projects/emu10k1/>
 
 	  It is now possible to load dsp microcode patches into the EMU10K1
 	  chip.  These patches are used to implement real time sound
 	  processing effects which include for example: signal routing,
 	  bass/treble control, AC3 passthrough, ...
 	  Userspace tools to create new patches and load/unload them can be
-	  found at <http://opensource.creative.com/dist.html>.
+	  found in the emu-tools package at the above URL.
 
 config MIDI_EMU10K1
 	bool "Creative SBLive! MIDI (EXPERIMENTAL)"
diff -urN linux-2.5.65-bk2/sound/oss/audio_syms.c linux-2.5.65-bk3/sound/oss/audio_syms.c
--- linux-2.5.65-bk2/sound/oss/audio_syms.c	Mon Mar 17 13:43:44 2003
+++ linux-2.5.65-bk3/sound/oss/audio_syms.c	Mon Mar 31 12:41:50 2003
@@ -1,9 +1,7 @@
 /*
  * Exported symbols for audio driver.
- * __NO_VERSION__ because this is still part of sound.o.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 char audio_syms_symbol;
diff -urN linux-2.5.65-bk2/sound/oss/cs46xx.c linux-2.5.65-bk3/sound/oss/cs46xx.c
--- linux-2.5.65-bk2/sound/oss/cs46xx.c	Mon Mar 17 13:43:37 2003
+++ linux-2.5.65-bk3/sound/oss/cs46xx.c	Mon Mar 31 12:41:50 2003
@@ -4314,7 +4314,7 @@
     {
         offset = ClrStat[i].BA1__DestByteOffset;
         count  = ClrStat[i].BA1__SourceSize;
-        for(  temp1 = offset; temp1<(offset+count); temp1+=4 );
+        for(  temp1 = offset; temp1<(offset+count); temp1+=4 )
               writel(0, pBA1+temp1);
     }
 
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/audio.c linux-2.5.65-bk3/sound/oss/emu10k1/audio.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/audio.c	Mon Mar 17 13:43:40 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/audio.c	Mon Mar 31 12:41:50 2003
@@ -30,7 +30,6 @@
  **********************************************************************
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
@@ -983,11 +982,11 @@
 	unsigned long pgoff;
 	int rd, wr;
 
-	DPF(4, "emu10k1_mm_nopage()\n");
-	DPD(4, "addr: %#lx\n", address);
+	DPF(3, "emu10k1_mm_nopage()\n");
+	DPD(3, "addr: %#lx\n", address);
 
 	if (address > vma->vm_end) {
-		DPF(2, "EXIT, returning NOPAGE_SIGBUS\n");
+		DPF(1, "EXIT, returning NOPAGE_SIGBUS\n");
 		return NOPAGE_SIGBUS; /* Disallow mremap */
 	}
 
@@ -1009,14 +1008,14 @@
 			pgoff -= woinst->buffer.pages;
 			dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
 		} else
-			dmapage = virt_to_page (woinst->buffer.mem[0].addr[pgoff]);
+			dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]);
 	} else {
 		dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
 	}
 
 	get_page (dmapage);
 
-	DPD(4, "page: %#lx\n", dmapage);
+	DPD(3, "page: %#lx\n", (unsigned long) dmapage);
 	return dmapage;
 }
 
@@ -1083,8 +1082,8 @@
 	n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	pgoffset = vma->vm_pgoff;
 
-	DPD(3, "vma_start: %#lx, vma_end: %#lx, vma_offset: %d\n", vma->vm_start, vma->vm_end, pgoffset);
-	DPD(3, "n_pages: %d, max_pages: %d\n", n_pages, max_pages);
+	DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset);
+	DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages);
 
 	if (pgoffset + n_pages > max_pages)
 		return -EINVAL;
@@ -1092,7 +1091,6 @@
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_ops = &emu10k1_mm_ops;
 	vma->vm_private_data = wave_dev;
-
 	return 0;
 }
 
@@ -1136,7 +1134,8 @@
 
 		if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
 			ERROR();
-			return -ENODEV;
+			kfree(wave_dev);
+			return -ENOMEM;
 		}
 
 		wiinst->recsrc = card->wavein.recsrc;
@@ -1162,6 +1161,8 @@
 			wiinst->format.channels = hweight32(wiinst->fxwc);
 			break;
 		default:
+			kfree(wave_dev);
+			kfree(wiinst);
 			BUG();
 			break;
 		}
@@ -1211,7 +1212,7 @@
 		woinst->num_voices = 1;
 		for (i = 0; i < WAVEOUT_MAXVOICES; i++) {
 			woinst->voice[i].usage = VOICE_USAGE_FREE;
-			woinst->buffer.mem[i].emupageindex = -1;
+			woinst->voice[i].mem.emupageindex = -1;
 		}
 
 		init_waitqueue_head(&woinst->wait_queue);
@@ -1330,23 +1331,13 @@
 	if (file->f_mode & FMODE_READ) {
 		spin_lock_irqsave(&wiinst->lock, flags);
 
-		if (wiinst->state == WAVE_STATE_CLOSED) {
-			calculate_ifrag(wiinst);
-			if (emu10k1_wavein_open(wave_dev) < 0) {
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				return (mask |= POLLERR);
-			}
-		}
+		if (wiinst->state & WAVE_STATE_OPEN) {
+			emu10k1_wavein_update(wave_dev->card, wiinst);
+			emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
 
-		if (!(wiinst->state & WAVE_STATE_STARTED)) {
-			wave_dev->enablebits |= PCM_ENABLE_INPUT;
-			emu10k1_wavein_start(wave_dev);
+			if (bytestocopy >= wiinst->buffer.fragment_size)
+				mask |= POLLIN | POLLRDNORM;
 		}
-		emu10k1_wavein_update(wave_dev->card, wiinst);
-		emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-		if (bytestocopy >= wiinst->buffer.fragment_size)
-			mask |= POLLIN | POLLRDNORM;
 
 		spin_unlock_irqrestore(&wiinst->lock, flags);
 	}
@@ -1376,6 +1367,13 @@
 
 	buffer->fragment_size = 1 << buffer->ossfragshift;
 
+	while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE)
+		buffer->fragment_size >>= 1;
+
+	/* now we are sure that:
+	 (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS)
+	*/
+
 	if (!buffer->numfrags) {
 		u32 numfrags;
 
@@ -1390,19 +1388,14 @@
 		}
 	}
 
-	if (buffer->numfrags < MINFRAGS)
-		buffer->numfrags = MINFRAGS;
+	if (buffer->numfrags < WAVEOUT_MINFRAGS)
+		buffer->numfrags = WAVEOUT_MINFRAGS;
 
-	if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE) {
+	if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE)
 		buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size;
 
-		if (buffer->numfrags < MINFRAGS) {
-			buffer->numfrags = MINFRAGS;
-			buffer->fragment_size = WAVEOUT_MAXBUFSIZE / MINFRAGS;
-		}
-
-	} else if (buffer->numfrags * buffer->fragment_size < WAVEOUT_MINBUFSIZE)
-		buffer->numfrags = WAVEOUT_MINBUFSIZE / buffer->fragment_size;
+	if (buffer->numfrags < WAVEOUT_MINFRAGS)
+		BUG();
 
 	buffer->size = buffer->fragment_size * buffer->numfrags;
 	buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
@@ -1436,24 +1429,29 @@
 
 	buffer->fragment_size = 1 << buffer->ossfragshift;
 
+	while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE)
+		buffer->fragment_size >>= 1;
+
+	/* now we are sure that:
+	   (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS)
+        */
+
+
 	if (!buffer->numfrags)
 		buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1;
 
-	if (buffer->numfrags < MINFRAGS)
-		buffer->numfrags = MINFRAGS;
+	if (buffer->numfrags < WAVEIN_MINFRAGS)
+		buffer->numfrags = WAVEIN_MINFRAGS;
 
-	if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE) {
+	if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE)
 		buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size;
 
-		if (buffer->numfrags < MINFRAGS) {
-			buffer->numfrags = MINFRAGS;
-			buffer->fragment_size = WAVEIN_MAXBUFSIZE / MINFRAGS;
-		}
-	} else if (buffer->numfrags * buffer->fragment_size < WAVEIN_MINBUFSIZE)
-		buffer->numfrags = WAVEIN_MINBUFSIZE / buffer->fragment_size;
+	if (buffer->numfrags < WAVEIN_MINFRAGS)
+		BUG();
 
 	bufsize = buffer->fragment_size * buffer->numfrags;
 
+	/* the buffer size for recording is restricted to certain values, adjust it now */
 	if (bufsize >= 0x10000) {
 		buffer->size = 0x10000;
 		buffer->sizeregval = 0x1f;
@@ -1479,10 +1477,12 @@
 		}
 	}
 
+	/* adjust the fragment size so that buffer size is an integer multiple */
+	while (buffer->size % buffer->fragment_size)
+		buffer->fragment_size >>= 1;
+
 	buffer->numfrags = buffer->size / buffer->fragment_size;
 	buffer->pages =  buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
-	if (buffer->size % buffer->fragment_size)
-		BUG();
 
 	DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size);
 	DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags);
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/audio.h linux-2.5.65-bk3/sound/oss/emu10k1/audio.h
--- linux-2.5.65-bk2/sound/oss/emu10k1/audio.h	Mon Mar 17 13:44:46 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/audio.h	Mon Mar 31 12:41:50 2003
@@ -33,8 +33,6 @@
 #ifndef _AUDIO_H
 #define _AUDIO_H
 
-#define MINFRAGS	2	/* _don't_ got bellow 2 */
-
 struct emu10k1_wavedevice
 {
         struct emu10k1_card *card;
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/cardwi.c linux-2.5.65-bk3/sound/oss/emu10k1/cardwi.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/cardwi.c	Mon Mar 17 13:44:17 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/cardwi.c	Mon Mar 31 12:41:50 2003
@@ -96,6 +96,7 @@
 	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
 	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
 	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
+	wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
 }
 
 static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
@@ -120,7 +121,7 @@
 	struct emu10k1_card *card = wave_dev->card;
 	struct wiinst *wiinst = wave_dev->wiinst;
 	struct wiinst **wiinst_tmp = NULL;
-	u32 delay;
+	u16 delay;
 	unsigned long flags;
 
 	DPF(2, "emu10k1_wavein_open()\n");
@@ -169,6 +170,12 @@
 
 	emu10k1_set_record_src(card, wiinst);
 
+	emu10k1_reset_record(card, &wiinst->buffer);
+
+	wiinst->buffer.hw_pos = 0;
+	wiinst->buffer.pos = 0;
+	wiinst->buffer.bytestocopy = 0;
+
 	delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
 
 	emu10k1_timer_install(card, &wiinst->timer, delay / 2);
@@ -222,10 +229,6 @@
 	emu10k1_start_record(card, &wiinst->buffer);
 	emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
 
-	wiinst->buffer.hw_pos = 0;
-	wiinst->buffer.pos = 0;
-	wiinst->buffer.bytestocopy = 0;
-
 	wiinst->state |= WAVE_STATE_STARTED;
 }
 
@@ -249,7 +252,7 @@
 {
 	struct emu10k1_card *card = wave_dev->card;
 	struct wiinst *wiinst = wave_dev->wiinst;
-	u32 delay;
+	u16 delay;
 
 	DPF(2, "emu10k1_wavein_setformat()\n");
 
@@ -304,10 +307,9 @@
 
 static void copy_block(u8 *dst, u8 * src, u32 str, u32 len, u8 cov)
 {
-	if (cov == 1) {
-		if (__copy_to_user(dst, src + str, len))
-			return;
-	} else {
+	if (cov == 1)
+		__copy_to_user(dst, src + str, len);
+	else {
 		u8 byte;
 		u32 i;
 
@@ -315,8 +317,7 @@
 
 		for (i = 0; i < len; i++) {
 			byte = src[2 * i] ^ 0x80;
-			if (__copy_to_user(dst + i, &byte, 1))
-				return;
+			__copy_to_user(dst + i, &byte, 1);
 		}
 	}
 }
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/cardwi.h linux-2.5.65-bk3/sound/oss/emu10k1/cardwi.h
--- linux-2.5.65-bk2/sound/oss/emu10k1/cardwi.h	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/cardwi.h	Mon Mar 31 12:41:50 2003
@@ -69,13 +69,14 @@
 	u16 fxwc;
 };
 
-#define WAVEIN_MAXBUFSIZE         65536
-#define WAVEIN_MINBUFSIZE	  368
+#define WAVEIN_MAXBUFSIZE	65536
+#define WAVEIN_MINBUFSIZE	368
 
-#define WAVEIN_DEFAULTFRAGLEN     100 
-#define WAVEIN_DEFAULTBUFLEN      1000
+#define WAVEIN_DEFAULTFRAGLEN	100 
+#define WAVEIN_DEFAULTBUFLEN	1000
 
-#define WAVEIN_MINFRAGSHIFT   	  8 
+#define WAVEIN_MINFRAGSHIFT	8 
+#define WAVEIN_MINFRAGS		2
 
 int emu10k1_wavein_open(struct emu10k1_wavedevice *);
 void emu10k1_wavein_close(struct emu10k1_wavedevice *);
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/cardwo.c linux-2.5.65-bk3/sound/oss/emu10k1/cardwo.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/cardwo.c	Mon Mar 17 13:44:41 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/cardwo.c	Mon Mar 31 12:41:50 2003
@@ -108,95 +108,20 @@
 	}
 
 	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
+	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
+	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
 
 	if (wave_fmt->channels == 2)
 		wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel;
 	else
 		wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel;
-
-	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
-	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
-}
-
-/**
- * alloc_buffer -
- *
- * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
- * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
- * is passed to the device so that it can do DMA to host memory. 
- *
- */
-static int alloc_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum)
-{
-	u32 pageindex, pagecount;
-	unsigned long busaddx;
-	int i;
-
-	DPD(2, "requested pages is: %d\n", buffer->pages);
-
-	if ((buffer->mem[voicenum].emupageindex =
-	 emu10k1_addxmgr_alloc(buffer->pages * PAGE_SIZE, card)) < 0)
-		return -1;
-
-	/* Fill in virtual memory table */
-	for (pagecount = 0; pagecount < buffer->pages; pagecount++) {
-		if ((buffer->mem[voicenum].addr[pagecount] =
-		 pci_alloc_consistent(card->pci_dev, PAGE_SIZE,
-		 &buffer->mem[voicenum].dma_handle[pagecount])) == NULL) {
-			buffer->pages = pagecount;
-			return -1;
-		}
-
-		DPD(2, "Virtual Addx: %p\n", buffer->mem[voicenum].addr[pagecount]);
-
-		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-			busaddx = buffer->mem[voicenum].dma_handle[pagecount] + i * EMUPAGESIZE;
-
-			DPD(3, "Bus Addx: %#lx\n", busaddx);
-
-			pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-
-			((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
-		}
-	}
-
-	return 0;
-}
-
-/**
- * free_buffer -
- *
- * frees the memory buffer for a voice.
- */
-static void free_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum)
-{
-	u32 pagecount, pageindex;
-	int i;
-
-	if (buffer->mem[voicenum].emupageindex < 0)
-		return;
-
-	for (pagecount = 0; pagecount < buffer->pages; pagecount++) {
-		pci_free_consistent(card->pci_dev, PAGE_SIZE,
-		 buffer->mem[voicenum].addr[pagecount],
-		 buffer->mem[voicenum].dma_handle[pagecount]);
-
-		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-			pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-			((u32 *) card->virtualpagetable.addr)[pageindex] =
-			 cpu_to_le32((card->silentpage.dma_handle * 2) | pageindex);
-		}
-	}
-
-	emu10k1_addxmgr_free(card, buffer->mem[voicenum].emupageindex);
-	buffer->mem[voicenum].emupageindex = -1;
 }
 
 static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned int voicenum)
 {
 	struct emu_voice *voice = &woinst->voice[voicenum];
-	/* Allocate voices here, if no voices available, return error.
-	 * Init voice_allocdesc first.*/
+
+	/* Allocate voices here, if no voices available, return error. */
 
 	voice->usage = VOICE_USAGE_PLAYBACK;
 
@@ -219,7 +144,7 @@
 
 	DPD(2, "Initial pitch --> %#x\n", voice->initial_pitch);
 
-	voice->startloop = (woinst->buffer.mem[voicenum].emupageindex << 12) /
+	voice->startloop = (voice->mem.emupageindex << 12) /
 	 woinst->format.bytespervoicesample;
 	voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;
 	voice->start = voice->startloop;
@@ -297,12 +222,12 @@
 	struct woinst *woinst = wave_dev->woinst;
 	struct waveout_buffer *buffer = &woinst->buffer;
 	unsigned int voicenum;
-	u32 delay;
+	u16 delay;
 
 	DPF(2, "emu10k1_waveout_open()\n");
 
 	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-		if (alloc_buffer(card, buffer, voicenum) < 0) {
+		if (emu10k1_voice_alloc_buffer(card, &woinst->voice[voicenum].mem, woinst->buffer.pages) < 0) {
 			ERROR();
 			emu10k1_waveout_close(wave_dev);
 			return -1;
@@ -324,7 +249,7 @@
 	delay = (48000 * woinst->buffer.fragment_size) /
 		 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
 
-	emu10k1_timer_install(card, &woinst->timer, delay / 2);
+	emu10k1_timer_install(card, &woinst->timer, delay);
 
 	woinst->state = WAVE_STATE_OPEN;
 
@@ -345,7 +270,7 @@
 
 	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
 		emu10k1_voice_free(&woinst->voice[voicenum]);
-		free_buffer(card, &woinst->buffer, voicenum);
+		emu10k1_voice_free_buffer(card, &woinst->voice[voicenum].mem);
 	}
 
 	woinst->state = WAVE_STATE_CLOSED;
@@ -371,7 +296,7 @@
 	struct emu10k1_card *card = wave_dev->card;
 	struct woinst *woinst = wave_dev->woinst;
 	unsigned int voicenum;
-	u32 delay;
+	u16 delay;
 
 	DPF(2, "emu10k1_waveout_setformat()\n");
 
@@ -404,7 +329,7 @@
 		delay = (48000 * woinst->buffer.fragment_size) /
 			 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
 
-		emu10k1_timer_install(card, &woinst->timer, delay / 2);
+		emu10k1_timer_install(card, &woinst->timer, delay);
 	}
 
 	return 0;
@@ -449,7 +374,7 @@
 
 	pending_bytes = buffer->size - buffer->free_bytes;
 
-	buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size) ? 1 : 0;
+	buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size * 2) ? 1 : 0;
 
 	if (pending_bytes > (signed) buffer->silence_bytes) {
 		*total_free_bytes = (buffer->free_bytes + buffer->silence_bytes);
@@ -483,17 +408,14 @@
 
 	if (len > PAGE_SIZE - pgoff) {
 		k = PAGE_SIZE - pgoff;
-		if (__copy_from_user((u8 *)dst[pg] + pgoff, src, k))
-			return;
+		__copy_from_user((u8 *)dst[pg] + pgoff, src, k);
 		len -= k;
 		while (len > PAGE_SIZE) {
-			if (__copy_from_user(dst[++pg], src + k, PAGE_SIZE))
-				return;
+			__copy_from_user(dst[++pg], src + k, PAGE_SIZE);
 			k += PAGE_SIZE;
 			len -= PAGE_SIZE;
 		}
-		if (__copy_from_user(dst[++pg], src + k, len))
-			return;
+		__copy_from_user(dst[++pg], src + k, len);
 
 	} else
 		__copy_from_user((u8 *)dst[pg] + pgoff, src, len);
@@ -511,15 +433,14 @@
         unsigned int pg;
 	unsigned int pgoff;
 	unsigned int voice_num;
-	struct waveout_mem *mem = woinst->buffer.mem;
+	struct emu_voice *voice = woinst->voice;
 
 	pg = str / PAGE_SIZE;
 	pgoff = str % PAGE_SIZE;
 
 	while (len) { 
 		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) {
-			if (__copy_from_user((u8 *)(mem[voice_num].addr[pg]) + pgoff, src, woinst->format.bytespervoicesample))
-				return;
+			__copy_from_user((u8 *)(voice[voice_num].mem.addr[pg]) + pgoff, src, woinst->format.bytespervoicesample);
 			src += woinst->format.bytespervoicesample;
 		}
 
@@ -544,7 +465,7 @@
 	unsigned int pg;
 	unsigned int pgoff;
 	unsigned int voice_num;
-        struct waveout_mem *mem = woinst->buffer.mem;
+        struct emu_voice *voice = woinst->voice;
 	unsigned int  k;
 
 	pg = str / PAGE_SIZE;
@@ -553,22 +474,22 @@
 	if (len > PAGE_SIZE - pgoff) {
 		k = PAGE_SIZE - pgoff;
 		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset((u8 *)mem[voice_num].addr[pg] + pgoff, data, k);
+			memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, k);
 		len -= k;
 		while (len > PAGE_SIZE) {
 			pg++;
 			for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-				memset(mem[voice_num].addr[pg], data, PAGE_SIZE);
+				memset(voice[voice_num].mem.addr[pg], data, PAGE_SIZE);
 
 			len -= PAGE_SIZE;
 		}
 		pg++;
 		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset(mem[voice_num].addr[pg], data, len);
+			memset(voice[voice_num].mem.addr[pg], data, len);
 
 	} else {
 		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset((u8 *)mem[voice_num].addr[pg] + pgoff, data, len);
+			memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, len);
 	}
 }
 
@@ -582,6 +503,7 @@
 void emu10k1_waveout_xferdata(struct woinst *woinst, u8 *data, u32 *size)
 {
 	struct waveout_buffer *buffer = &woinst->buffer;
+	struct voice_mem *mem = &woinst->voice[0].mem;
 	u32 sizetocopy, sizetocopy_now, start;
 	unsigned long flags;
 
@@ -610,14 +532,14 @@
 			copy_ilv_block(woinst, start, data, sizetocopy_now);
 			copy_ilv_block(woinst, 0, data + sizetocopy_now * woinst->num_voices, sizetocopy);
 		} else {
-			copy_block(buffer->mem[0].addr, start, data, sizetocopy_now);
-			copy_block(buffer->mem[0].addr, 0, data + sizetocopy_now, sizetocopy);
+			copy_block(mem->addr, start, data, sizetocopy_now);
+			copy_block(mem->addr, 0, data + sizetocopy_now, sizetocopy);
 		}
 	} else {
 		if (woinst->num_voices > 1)
 			copy_ilv_block(woinst, start, data, sizetocopy);
 		else
-			copy_block(buffer->mem[0].addr, start, data, sizetocopy);
+			copy_block(mem->addr, start, data, sizetocopy);
 	}
 }
 
@@ -674,7 +596,7 @@
 {
 	u32 hw_pos;
 	u32 diff;
-	
+
 	/* There is no actual start yet */
 	if (!(woinst->state & WAVE_STATE_STARTED)) {
 		hw_pos = woinst->buffer.hw_pos;
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/cardwo.h linux-2.5.65-bk3/sound/oss/emu10k1/cardwo.h
--- linux-2.5.65-bk2/sound/oss/emu10k1/cardwo.h	Mon Mar 17 13:44:22 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/cardwo.h	Mon Mar 31 12:41:50 2003
@@ -39,20 +39,13 @@
 
 /* setting this to other than a power of two may break some applications */
 #define WAVEOUT_MAXBUFSIZE	MAXBUFSIZE
-#define WAVEOUT_MINBUFSIZE	64
 
 #define WAVEOUT_DEFAULTFRAGLEN	20 /* Time to play a fragment in ms (latency) */
 #define WAVEOUT_DEFAULTBUFLEN	500 /* Time to play the entire buffer in ms */
 
-#define WAVEOUT_MINFRAGSHIFT	6
-#define WAVEOUT_MAXVOICES 6
-
-/* waveout_mem is cardwo internal */
-struct waveout_mem {
-	int emupageindex;
-	void *addr[BUFMAXPAGES];
-	dma_addr_t dma_handle[BUFMAXPAGES];
-};
+#define WAVEOUT_MINFRAGSHIFT	6 /* Minimum fragment size in bytes is 2^6 */
+#define WAVEOUT_MINFRAGS	3 /* _don't_ go bellow 3, it would break silence filling */
+#define WAVEOUT_MAXVOICES	6
 
 struct waveout_buffer {
 	u16 ossfragshift;
@@ -60,7 +53,6 @@
 	u32 fragment_size;	/* in bytes units */
 	u32 size;		/* in bytes units */
 	u32 pages;		/* buffer size in page units*/
-	struct waveout_mem mem[WAVEOUT_MAXVOICES];
 	u32 silence_pos;	/* software cursor position (including silence bytes) */
 	u32 hw_pos;		/* hardware cursor position */
 	u32 free_bytes;		/* free bytes available on the buffer (not including silence bytes) */
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/efxmgr.c linux-2.5.65-bk3/sound/oss/emu10k1/efxmgr.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/efxmgr.c	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/efxmgr.c	Mon Mar 31 12:41:50 2003
@@ -38,7 +38,7 @@
         struct dsp_patch *patch;
 	struct dsp_rpatch *rpatch;
 	char s[PATCH_NAME_SIZE + 4];
-	u32 *gpr_used;
+	unsigned long *gpr_used;
 	int i;
 
 	DPD(2, "emu10k1_find_control_gpr(): %s %s\n", patch_name, gpr_name);
@@ -103,7 +103,7 @@
 
 	card->ac97.mixer_state[oss_mixer] = (right << 8) | left;
 
-	if (!card->isaps)
+	if (!card->is_aps)
 		card->ac97.write_mixer(&card->ac97, oss_mixer, left, right);
 	
 	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left,
@@ -171,9 +171,8 @@
 {
 	struct patch_manager *mgr = &card->mgr;
 	unsigned long flags;
-	int muting;
 
-	const s32 log2lin[5] ={                  //  attenuation (dB)
+	static const s32 log2lin[4] ={           //  attenuation (dB)
 		0x7fffffff,                      //       0.0         
 		0x7fffffff * 0.840896415253715 , //       1.5          
 		0x7fffffff * 0.707106781186548,  //       3.0
@@ -183,12 +182,10 @@
 	if (addr < 0)
 		return;
 
-	muting = (scale == 0x10) ? 0x7f: scale;
-	
 	vol = (100 - vol ) * scale / 100;
 
 	// Thanks to the comp.dsp newsgroup for this neat trick:
-	vol = (vol >= muting) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
+	vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
 
 	spin_lock_irqsave(&mgr->lock, flags);
 	emu10k1_set_control_gpr(card, addr, vol, 0);
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/efxmgr.h linux-2.5.65-bk3/sound/oss/emu10k1/efxmgr.h
--- linux-2.5.65-bk2/sound/oss/emu10k1/efxmgr.h	Mon Mar 17 13:44:49 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/efxmgr.h	Mon Mar 31 12:41:50 2003
@@ -35,9 +35,9 @@
 #define WRITE_EFX(a, b, c) sblive_writeptr((a), MICROCODEBASE + (b), 0, (c))
 
 #define OP(op, z, w, x, y) \
-        do { WRITE_EFX(card, (pc) * 2, ((x) << 10) | (y)); \
-        WRITE_EFX(card, (pc) * 2 + 1, ((op) << 20) | ((z) << 10) | (w)); \
-        ++pc; } while (0)
+	do { WRITE_EFX(card, (pc) * 2, ((x) << 10) | (y)); \
+	WRITE_EFX(card, (pc) * 2 + 1, ((op) << 20) | ((z) << 10) | (w)); \
+	++pc; } while (0)
 
 #define NUM_INPUTS 0x20
 #define NUM_OUTPUTS 0x20
@@ -47,52 +47,52 @@
 
 struct dsp_rpatch {
 	char name[PATCH_NAME_SIZE];
-        u16 code_start;
-        u16 code_size;
+	u16 code_start;
+	u16 code_size;
 
-        u32 gpr_used[NUM_GPRS / 32];
-        u32 gpr_input[NUM_GPRS / 32];
-        u32 route[NUM_OUTPUTS];
-        u32 route_v[NUM_OUTPUTS];
+	unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
+	unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
+	unsigned long route[NUM_OUTPUTS];
+	unsigned long route_v[NUM_OUTPUTS];
 };
 
 struct dsp_patch {
-        char name[PATCH_NAME_SIZE];
-        u8 id;
-        u32 input;                      /* bitmap of the lines used as inputs */
-	u32 output;                     /* bitmap of the lines used as outputs */
-        u16 code_start;
-        u16 code_size;
-
-        u32 gpr_used[NUM_GPRS / 32];    /* bitmap of used gprs */
-        u32 gpr_input[NUM_GPRS / 32];
-        u8 traml_istart;  /* starting address of the internal tram lines used */
-        u8 traml_isize;   /* number of internal tram lines used */
-
-        u8 traml_estart;
-        u8 traml_esize;
-
-        u16 tramb_istart;        /* starting address of the internal tram memory used */
-        u16 tramb_isize;         /* amount of internal memory used */
-        u32 tramb_estart;
-        u32 tramb_esize;
+	char name[PATCH_NAME_SIZE];
+	u8 id;
+	unsigned long input;	/* bitmap of the lines used as inputs */
+	unsigned long output;	/* bitmap of the lines used as outputs */
+	u16 code_start;
+	u16 code_size;
+
+	unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];	/* bitmap of used gprs */
+	unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
+	u8 traml_istart;	/* starting address of the internal tram lines used */
+	u8 traml_isize;		/* number of internal tram lines used */
+
+	u8 traml_estart;
+	u8 traml_esize;
+
+	u16 tramb_istart;        /* starting address of the internal tram memory used */
+	u16 tramb_isize;         /* amount of internal memory used */
+	u32 tramb_estart;
+	u32 tramb_esize;
 };
 
 struct dsp_gpr {
-        u8 type;                      /* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */
-        char name[GPR_NAME_SIZE];       /* gpr value, only valid for control gprs */
-        s32 min, max;         /* value range for this gpr, only valid for control gprs */
-        u8 line;                    /* which input/output line is the gpr attached, only valid for input/output gprs */
-        u8 usage;
+	u8 type;			/* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */
+	char name[GPR_NAME_SIZE];	/* gpr value, only valid for control gprs */
+	s32 min, max;			/* value range for this gpr, only valid for control gprs */
+	u8 line;			/* which input/output line is the gpr attached, only valid for input/output gprs */
+	u8 usage;
 };
 
 enum {
-        GPR_TYPE_NULL = 0,
-        GPR_TYPE_IO,
-        GPR_TYPE_STATIC,
-        GPR_TYPE_DYNAMIC,
-        GPR_TYPE_CONTROL,
-        GPR_TYPE_CONSTANT
+	GPR_TYPE_NULL = 0,
+	GPR_TYPE_IO,
+	GPR_TYPE_STATIC,
+	GPR_TYPE_DYNAMIC,
+	GPR_TYPE_CONTROL,
+	GPR_TYPE_CONSTANT
 };
 
 #define GPR_BASE 0x100
@@ -101,15 +101,14 @@
 #define MAX_PATCHES_PAGES 32
 
 struct patch_manager {
-        void *patch[MAX_PATCHES_PAGES];
+	void *patch[MAX_PATCHES_PAGES];
 	int current_pages;
-        struct dsp_rpatch rpatch;
-        struct dsp_gpr gpr[NUM_GPRS];   /* gpr usage table */
+	struct dsp_rpatch rpatch;
+	struct dsp_gpr gpr[NUM_GPRS];   /* gpr usage table */
 	spinlock_t lock;
 	s16 ctrl_gpr[SOUND_MIXER_NRDEVICES][2];
 };
 
-
 #define PATCHES_PER_PAGE (PAGE_SIZE / sizeof(struct dsp_patch))
 
 #define PATCH(mgr, i) ((struct dsp_patch *) (mgr)->patch[(i) / PATCHES_PER_PAGE] + (i) % PATCHES_PER_PAGE)
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/hwaccess.c linux-2.5.65-bk3/sound/oss/emu10k1/hwaccess.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/hwaccess.c	Mon Mar 17 13:43:50 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/hwaccess.c	Mon Mar 31 12:41:50 2003
@@ -187,6 +187,15 @@
 	}
 }
 
+void emu10k1_timer_set(struct emu10k1_card * card, u16 data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+	outw(data & TIMER_RATE_MASK, card->iobase + TIMER);
+	spin_unlock_irqrestore(&card->lock, flags);
+}
+
 /************************************************************************
 * write/read Emu10k1 pointer-offset register set, accessed through      *
 *  the PTR and DATA registers                                           *
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/hwaccess.h linux-2.5.65-bk3/sound/oss/emu10k1/hwaccess.h
--- linux-2.5.65-bk2/sound/oss/emu10k1/hwaccess.h	Mon Mar 17 13:44:03 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/hwaccess.h	Mon Mar 31 12:41:50 2003
@@ -126,6 +126,7 @@
 #define CMD_SETMCH_FX		_IOW('D', 17, struct mixer_private_ioctl)
 #define CMD_SETPASSTHROUGH	_IOW('D', 18, struct mixer_private_ioctl)
 #define CMD_PRIVATE3_VERSION	_IOW('D', 19, struct mixer_private_ioctl)
+#define CMD_AC97_BOOST		_IOW('D', 20, struct mixer_private_ioctl)
 
 //up this number when breaking compatibility
 #define PRIVATE3_VERSION 1
@@ -144,7 +145,7 @@
 	u16			emupagetable[MAXPAGES];
 
 	struct list_head	timers;
-	unsigned		timer_delay;
+	u16			timer_delay;
 	spinlock_t		timer_lock;
 
 	struct pci_dev		*pci_dev;
@@ -181,7 +182,7 @@
 
 	u8 chiprev;                    /* Chip revision                */
 
-	int isaps;
+	u8 is_aps;
 
 	struct patch_manager mgr;
 	struct pt_data pt;
@@ -190,8 +191,6 @@
 int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *);
 void emu10k1_addxmgr_free(struct emu10k1_card *, int);
 
-
-
 int emu10k1_find_control_gpr(struct patch_manager *, const char *, const char *);
 void emu10k1_set_control_gpr(struct emu10k1_card *, int , s32, int );
 
@@ -211,12 +210,14 @@
 
 /* Hardware Abstraction Layer access functions */
 
-void emu10k1_writefn0(struct emu10k1_card *, u32 , u32 );
-u32 emu10k1_readfn0(struct emu10k1_card *, u32 );
+void emu10k1_writefn0(struct emu10k1_card *, u32, u32);
+u32 emu10k1_readfn0(struct emu10k1_card *, u32);
+
+void emu10k1_timer_set(struct emu10k1_card *, u16);
 
-void sblive_writeptr(struct emu10k1_card *, u32 , u32 , u32 );
-void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...);
-#define TAGLIST_END 0
+void sblive_writeptr(struct emu10k1_card *, u32, u32, u32);
+void sblive_writeptr_tag(struct emu10k1_card *, u32, ...);
+#define TAGLIST_END	0
 
 u32 sblive_readptr(struct emu10k1_card *, u32 , u32 );
 
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/irqmgr.c linux-2.5.65-bk3/sound/oss/emu10k1/irqmgr.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/irqmgr.c	Mon Mar 17 13:44:07 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/irqmgr.c	Mon Mar 31 12:41:50 2003
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     irqmgr.c - IRQ manager for emu10k1 driver
@@ -41,7 +40,7 @@
 void emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct emu10k1_card *card = (struct emu10k1_card *) dev_id;
-	u32 irqstatus;
+	u32 irqstatus, irqstatus_tmp;
 
 	DPD(4, "emu10k1_interrupt called, irq =  %u\n", irq);
 
@@ -60,8 +59,7 @@
 	while ((irqstatus = inl(card->iobase + IPR))) {
 		DPD(4, "irq status %#x\n", irqstatus);
 
-		/* acknowledge interrupt */
-		outl(irqstatus, card->iobase + IPR);
+		irqstatus_tmp = irqstatus;
 
 		if (irqstatus & IRQTYPE_TIMER) {
 			emu10k1_timer_irqhandler(card);
@@ -98,7 +96,15 @@
 			irqstatus &=~IPR_VOLDECR;
 		}
 
-		if (irqstatus)
-			emu10k1_irq_disable(card, irqstatus);
+		if (irqstatus){
+			printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: %#08x\n", irqstatus);
+			//make sure any interrupts we don't handle are disabled:
+			emu10k1_irq_disable(card, ~(INTE_MIDIRXENABLE | INTE_MIDITXENABLE | INTE_INTERVALTIMERENB |
+						INTE_VOLDECRENABLE | INTE_VOLINCRENABLE | INTE_MUTEENABLE |
+						INTE_FXDSPENABLE));
+		}
+
+		/* acknowledge interrupt */
+                outl(irqstatus_tmp, card->iobase + IPR);
 	}
 }
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/main.c linux-2.5.65-bk3/sound/oss/emu10k1/main.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/main.c	Mon Mar 17 13:44:48 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/main.c	Mon Mar 31 12:41:50 2003
@@ -1,4 +1,4 @@
-/*
+ /*
  **********************************************************************
  *     main.c - Creative EMU10K1 audio driver
  *     Copyright 1999, 2000 Creative Labs, Inc.
@@ -69,7 +69,20 @@
  *     0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand)
  *          Small code format cleanup.
  *          Deadlock bug fix for emu10k1_volxxx_irqhandler().
- *
+ *     0.17 Fix for mixer SOUND_MIXER_INFO ioctl.
+ *	    Fix for HIGHMEM machines (emu10k1 can only do 31 bit bus master) 
+ *	    midi poll initial implementation.
+ *	    Small mixer fixes/cleanups.
+ *	    Improved support for 5.1 cards.
+ *     0.18 Fix for possible leak in pci_alloc_consistent()
+ *          Cleaned up poll() functions (audio and midi). Don't start input.
+ *	    Restrict DMA pages used to 512Mib range.
+ *	    New AC97_BOOST mixer ioctl.
+ *     0.19 Real fix for kernel with highmem support (cast dma_handle to u32).
+ *	    Fix recording buffering parameters calculation.
+ *	    Use unsigned long for variables in bit ops.
+ *     0.20 Fixed recording startup
+ *	    Fixed timer rate setting (it's a 16-bit register)
  *********************************************************************/
 
 /* These are only included once per module */
@@ -102,11 +115,10 @@
 #define SNDCARD_EMU10K1 46
 #endif
  
-#define DRIVER_VERSION "0.16"
+#define DRIVER_VERSION "0.20"
 
-/* FIXME: is this right? */
-/* does the card support 32 bit bus master?*/
-#define EMU10K1_DMA_MASK                0xffffffff	/* DMA buffer mask for pci_alloc_consist */
+/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
+#define EMU10K1_DMA_MASK                0x1fffffff	/* DMA buffer mask for pci_alloc_consist */
 
 #ifndef PCI_VENDOR_ID_CREATIVE
 #define PCI_VENDOR_ID_CREATIVE 0x1102
@@ -188,7 +200,7 @@
 
 	/* Assign default recording parameters */
 	/* FIXME */
-	if(card->isaps)
+	if (card->is_aps)
 		card->wavein.recsrc = WAVERECORD_FX;
 	else
 		card->wavein.recsrc = WAVERECORD_AC97;
@@ -211,6 +223,8 @@
 static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
 {
 	char s[32];
+
+	struct ac97_codec *codec = &card->ac97;
 	card->ac97.dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);
 	if (card->ac97.dev_mixer < 0) {
 		printk(KERN_ERR "emu10k1: cannot register mixer device\n");
@@ -219,7 +233,7 @@
 
 	card->ac97.private_data = card;
 
-	if (!card->isaps) {
+	if (!card->is_aps) {
 		card->ac97.id = 0;
 		card->ac97.codec_read = emu10k1_ac97_read;
         	card->ac97.codec_write = emu10k1_ac97_write;
@@ -228,11 +242,14 @@
 			printk(KERN_ERR "emu10k1: unable to probe AC97 codec\n");
 			goto err_out;
 		}
-		/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
-			does not support this, it shouldn't do any harm */
-		sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
+		/* 5.1: Enable the additional AC97 Slots and unmute extra channels on AC97 codec */
+		if (codec->codec_read(codec, AC97_EXTENDED_ID) & 0x0080){
+			printk(KERN_INFO "emu10k1: SBLive! 5.1 card detected\n"); 
+			sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
+			codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0);
+		}
 
-		// Force 5bit
+		// Force 5bit:		    
 		//card->ac97.bit_resolution=5;
 
 		if (!proc_mkdir ("driver/emu10k1", 0)) {
@@ -274,7 +291,7 @@
 {
 	char s[32];
 
-	if (!card->isaps) {
+	if (!card->is_aps) {
 		sprintf(s, "driver/emu10k1/%s/ac97", card->pci_dev->slot_name);
 		remove_proc_entry(s, NULL);
 
@@ -586,15 +603,15 @@
 	CONNECT(PCM1_IN_R, ANALOG_REAR_R);
 
 	/* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */
-	OP(6, 0x10b, 0x100, 0x102, 0x10c);
-	OP(6, 0x10b, 0x10b, 0x113, 0x40);
+	OP(6, 0x10a, 0x100, 0x102, 0x10c);
+	OP(6, 0x10a, 0x10a, 0x113, 0x40);
 
 	CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L);
 	CONNECT(PCM_IN_L, DIGITAL_OUT_L);
 	CONNECT(AC97_IN_L, DIGITAL_OUT_L);
 	CONNECT(SPDIF_CD_L, DIGITAL_OUT_L);
 
-	OP(6, 0x10a, 0x101, 0x103, 0x10e);
+	OP(6, 0x10b, 0x101, 0x103, 0x10e);
 	OP(6, 0x10b, 0x10b, 0x114, 0x40);
 
 	CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R);
@@ -768,7 +785,7 @@
 				    VTFT, 0xffff,
 				    CVCF, 0xffff,
 				    PTRX, 0,
-				    CPF, 0,
+				    //CPF, 0,
 				    CCR, 0,
 
 				    PSST, 0,
@@ -794,7 +811,9 @@
 				    ENVVOL, 0,
 				    ENVVAL, 0,
                                     TAGLIST_END);
+		sblive_writeptr(card, CPF, nCh, 0);
 	}
+	
 
 	/*
 	 ** Init to 0x02109204 :
@@ -852,19 +871,19 @@
 	}
 
 	for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
-		((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32((card->silentpage.dma_handle * 2) | pagecount);
+		((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pagecount);
 
 	/* Init page table & tank memory base register */
 	sblive_writeptr_tag(card, 0,
-			    PTB, card->virtualpagetable.dma_handle,
+			    PTB, (u32) card->virtualpagetable.dma_handle,
 			    TCB, 0,
 			    TCBS, 0,
 			    TAGLIST_END);
 
 	for (nCh = 0; nCh < NUM_G; nCh++) {
 		sblive_writeptr_tag(card, nCh,
-				    MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
-				    MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+				    MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
+				    MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
 				    TAGLIST_END);
 	}
 
@@ -951,8 +970,9 @@
 				    VTFT, 0,
 				    CVCF, 0,
 				    PTRX, 0,
-				    CPF, 0,
+				    //CPF, 0,
 				    TAGLIST_END);
+		sblive_writeptr(card, CPF, ch, 0);
 	}
 
 	/* Disable audio and lock cache */
@@ -999,7 +1019,7 @@
 	int ret;
 
 	if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) {
-		printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n");
+		printk(KERN_ERR "emu10k1: architecture does not support 29bit PCI busmaster DMA\n");
 		return -ENODEV;
 	}
 
@@ -1038,12 +1058,12 @@
 	pci_read_config_byte(pci_dev, PCI_REVISION_ID, &card->chiprev);
 	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
 
-	printk(KERN_INFO "emu10k1: %s rev %d model 0x%x found, IO at 0x%04lx-0x%04lx, IRQ %d\n",
+	printk(KERN_INFO "emu10k1: %s rev %d model %#04x found, IO at %#04lx-%#04lx, IRQ %d\n",
 		card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase,
 		card->iobase + card->length - 1, card->irq);
 
 	pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
-	card->isaps = (subsysvid == EMU_APS_SUBID);
+	card->is_aps = (subsysvid == EMU_APS_SUBID);
 
 	spin_lock_init(&card->lock);
 	init_MUTEX(&card->open_sem);
@@ -1074,7 +1094,7 @@
 		goto err_emu10k1_init;
 	}
 
-	if (card->isaps)
+	if (card->is_aps)
 		emu10k1_ecard_init(card);
 
 	list_add(&card->list, &emu10k1_devs);
@@ -1119,7 +1139,7 @@
 	pci_set_drvdata(pci_dev, NULL);
 }
 
-MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@opensource.creative.com)");
+MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@lists.sourceforge.net)");
 MODULE_DESCRIPTION("Creative EMU10K1 PCI Audio Driver v" DRIVER_VERSION "\nCopyright (C) 1999 Creative Technology Ltd.");
 MODULE_LICENSE("GPL");
 
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/midi.c linux-2.5.65-bk3/sound/oss/emu10k1/midi.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/midi.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/midi.c	Mon Mar 31 12:41:50 2003
@@ -29,8 +29,8 @@
  **********************************************************************
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/sched.h>
@@ -371,8 +371,32 @@
 
 static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait)
 {
+	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
 	DPF(4, "emu10k1_midi_poll() called\n");
-	return 0;
+
+	if (file->f_mode & FMODE_WRITE)
+		poll_wait(file, &midi_dev->oWait, wait);
+
+	if (file->f_mode & FMODE_READ)
+		poll_wait(file, &midi_dev->iWait, wait);
+
+	spin_lock_irqsave(&midi_spinlock, flags);
+
+	if (file->f_mode & FMODE_WRITE)
+		mask |= POLLOUT | POLLWRNORM;
+
+	if (file->f_mode & FMODE_READ) {
+		if (midi_dev->mistate == MIDIIN_STATE_STARTED)
+			if (midi_dev->icnt > 0)
+				mask |= POLLIN | POLLRDNORM;
+	}
+
+	spin_unlock_irqrestore(&midi_spinlock, flags);
+
+	return mask;
 }
 
 int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg)
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/mixer.c linux-2.5.65-bk3/sound/oss/emu10k1/mixer.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/mixer.c	Mon Mar 17 13:44:21 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/mixer.c	Mon Mar 31 12:41:50 2003
@@ -30,7 +30,6 @@
  **********************************************************************
  */
 
-#define __NO_VERSION__		/* Kernel version only defined once */
 #include <linux/module.h>
 #include <linux/version.h>
 #include <asm/uaccess.h>
@@ -251,7 +250,7 @@
 		case CMD_SETRECSRC:
 			switch (ctl->val[0]) {
 			case WAVERECORD_AC97:
-				if (card->isaps) {
+				if (card->is_aps) {
 					ret = -EINVAL;
 					break;
 				}
@@ -444,6 +443,7 @@
 
 		case CMD_SETGPR2OSS:
 			id = ctl->val[0];
+			/* 0 == left, 1 == right */
 			ch = ctl->val[1];
 			addr = ctl->val[2];
 
@@ -454,19 +454,19 @@
 
 			card->mgr.ctrl_gpr[id][ch] = addr;
 
-			if (card->isaps)
+			if (card->is_aps)
 				break;
 
 			if (addr >= 0) {
 				unsigned int state = card->ac97.mixer_state[id];
 
-				if (ch) {
+				if (ch == 1) {
 					state >>= 8;
 					card->ac97.stereo_mixers |= (1 << id);
-				} else {
-					card->ac97.supported_mixers |= (1 << id);
 				}
 
+				card->ac97.supported_mixers |= (1 << id);
+
 				if (id == SOUND_MIXER_TREBLE) {
 					set_treble(card, card->ac97.mixer_state[id] & 0xff, (card->ac97.mixer_state[id] >> 8) & 0xff);
 				} else if (id == SOUND_MIXER_BASS) {
@@ -475,10 +475,10 @@
 					emu10k1_set_volume_gpr(card, addr, state & 0xff,
 							       volume_params[id]);
 			} else {
-				if (ch) {
-					card->ac97.stereo_mixers &= ~(1 << id);
-					card->ac97.stereo_mixers |= card->ac97_stereo_mixers;
-				} else {
+				card->ac97.stereo_mixers &= ~(1 << id);
+				card->ac97.stereo_mixers |= card->ac97_stereo_mixers;
+
+				if (ch == 0) {
 					card->ac97.supported_mixers &= ~(1 << id);
 					card->ac97.supported_mixers |= card->ac97_supported_mixers;
 				}
@@ -499,6 +499,12 @@
 				ret = -EFAULT;
 			break;
 
+		case CMD_AC97_BOOST:
+			if(ctl->val[0])
+				emu10k1_ac97_write(&card->ac97, 0x18, 0x0);	
+			else
+				emu10k1_ac97_write(&card->ac97, 0x18, 0x0808);
+			break;
 		default:
 			ret = -EINVAL;
 			break;
@@ -551,7 +557,7 @@
 
 				card->tankmem.size = size;
 
-				sblive_writeptr_tag(card, 0, TCB, card->tankmem.dma_handle, TCBS, size_reg, TAGLIST_END);
+				sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS, size_reg, TAGLIST_END);
 
 				emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0);
 			}
@@ -572,6 +578,8 @@
 	int val;
 	int scale;
 
+	card->ac97.modcnt++;
+
 	if (get_user(val, (int *)arg))
 		return -EFAULT;
 
@@ -612,7 +620,7 @@
 	unsigned int oss_mixer = _IOC_NR(cmd);
 	
 	ret = -EINVAL;
-	if (!card->isaps) {
+	if (!card->is_aps) {
 		if (cmd == SOUND_MIXER_INFO) {
 			mixer_info info;
 
@@ -626,7 +634,7 @@
 			return 0;
 		}
 
-		if ((_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
+		if ((_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
 			ret = emu10k1_dsp_mixer(card, oss_mixer, arg);
 		else
 			ret = card->ac97.mixer_ioctl(&card->ac97, cmd, arg);
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/passthrough.c linux-2.5.65-bk3/sound/oss/emu10k1/passthrough.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/passthrough.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/passthrough.c	Mon Mar 31 12:41:50 2003
@@ -29,7 +29,6 @@
  **********************************************************************
  */
                        
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
@@ -165,15 +164,12 @@
 
 		DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed);
 		if (count < needed) {
-			if (copy_from_user(pt->buf + pt->prepend_size, buffer,
-					   count))
-				return -EFAULT;
+			copy_from_user(pt->buf + pt->prepend_size, buffer, count);
 			pt->prepend_size += count;
 			DPD(3, "prepend size now %d\n", pt->prepend_size);
 			return count;
 		}
-		if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed))
-			return -EFAULT;
+		copy_from_user(pt->buf + pt->prepend_size, buffer, needed);
 		r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock);
 		if (r)
 			return r;
@@ -184,8 +180,7 @@
 	blocks_copied = 0;
 	while (blocks > 0) {
 		u16 *bufptr = (u16 *) buffer + (bytes_copied/2);
-		if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE))
-			return -EFAULT;
+		copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE);
 		bufptr = (u16 *) pt->buf;
 		r = pt_putblock(wave_dev, bufptr, nonblock);
 		if (r) {
@@ -201,8 +196,7 @@
 	i = count - bytes_copied;
 	if (i) {
 		pt->prepend_size = i;
-		if (copy_from_user(pt->buf, buffer + bytes_copied, i))
-			return -EFAULT;
+		copy_from_user(pt->buf, buffer + bytes_copied, i);
 		bytes_copied += i;
 		DPD(3, "filling prepend buffer with %d bytes", i);
 	}
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/recmgr.c linux-2.5.65-bk3/sound/oss/emu10k1/recmgr.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/recmgr.c	Mon Mar 17 13:44:51 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/recmgr.c	Mon Mar 31 12:41:50 2003
@@ -29,19 +29,28 @@
  **********************************************************************
  */
 
+#include <asm/delay.h>
 #include "8010.h"
 #include "recmgr.h"
 
+void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
+{
+	DPF(2, "emu10k1_reset_record()\n");
+
+	sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE);
+
+	sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval);	
+
+	while (sblive_readptr(card, buffer->idxreg, 0))
+		udelay(5);
+}
+
 void emu10k1_start_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
 {
 	DPF(2, "emu10k1_start_record()\n");
 
-	sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval);
-
 	if (buffer->adcctl)
 		sblive_writeptr(card, ADCCR, 0, buffer->adcctl);
-
-	return;
 }
 
 void emu10k1_stop_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
@@ -51,10 +60,6 @@
 	/* Disable record transfer */
 	if (buffer->adcctl)
 		sblive_writeptr(card, ADCCR, 0, 0);
-
-	sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE);
-
-	return;
 }
 
 void emu10k1_set_record_src(struct emu10k1_card *card, struct wiinst *wiinst)
@@ -130,9 +135,7 @@
 		break;
 	}
 
-	DPD(2, "bus addx: %#x\n", buffer->dma_handle);
-
-	sblive_writeptr(card, buffer->addrreg, 0, buffer->dma_handle);
+	DPD(2, "bus addx: %#lx\n", (unsigned long) buffer->dma_handle);
 
-	return;
+	sblive_writeptr(card, buffer->addrreg, 0, (u32)buffer->dma_handle);
 }
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/recmgr.h linux-2.5.65-bk3/sound/oss/emu10k1/recmgr.h
--- linux-2.5.65-bk2/sound/oss/emu10k1/recmgr.h	Mon Mar 17 13:44:47 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/recmgr.h	Mon Mar 31 12:41:50 2003
@@ -40,9 +40,9 @@
 #define WAVERECORD_MIC		0x02
 #define WAVERECORD_FX		0x03
 
+void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer);
 void emu10k1_start_record(struct emu10k1_card *, struct wavein_buffer *);
 void emu10k1_stop_record(struct emu10k1_card *, struct wavein_buffer *);
 void emu10k1_set_record_src(struct emu10k1_card *, struct wiinst *wiinst);
 
-
 #endif /* _RECORDMGR_H */
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/timer.c linux-2.5.65-bk3/sound/oss/emu10k1/timer.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/timer.c	Mon Mar 17 13:43:45 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/timer.c	Mon Mar 31 12:41:50 2003
@@ -59,7 +59,7 @@
 	return;
 }
 
-void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u32 delay)
+void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u16 delay)
 {
 	struct emu_timer *t;
 	struct list_head *entry;
@@ -85,7 +85,7 @@
 		card->timer_delay = delay;
 		delay = (delay < 1024 ? delay : 1024);
 
-		emu10k1_writefn0(card, TIMER_RATE, delay);
+		emu10k1_timer_set(card, delay);
 
 		list_for_each(entry, &card->timers) {
 			t = list_entry(entry, struct emu_timer, list);
@@ -108,7 +108,7 @@
 {
 	struct emu_timer *t;
 	struct list_head *entry;
-	u32 delay = TIMER_STOPPED;
+	u16 delay = TIMER_STOPPED;
 	unsigned long flags;
 
 	if (timer->state == TIMER_STATE_UNINSTALLED)
@@ -133,7 +133,7 @@
 		else {
 			delay = (delay < 1024 ? delay : 1024);
 
-			emu10k1_writefn0(card, TIMER_RATE, delay);
+			emu10k1_timer_set(card, delay);
 
 			list_for_each(entry, &card->timers) {
 				t = list_entry(entry, struct emu_timer, list);
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/timer.h linux-2.5.65-bk3/sound/oss/emu10k1/timer.h
--- linux-2.5.65-bk2/sound/oss/emu10k1/timer.h	Mon Mar 17 13:43:39 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/timer.h	Mon Mar 31 12:41:50 2003
@@ -36,17 +36,17 @@
 	struct list_head list;
 	struct tasklet_struct tasklet;
 	u8 state; 
-	u32 count;				/* current number of interrupts */
-	u32 count_max;				/* number of interrupts needed to schedule the bh */
-	u32 delay;                              /* timer delay */
+	u16 count;				/* current number of interrupts */
+	u16 count_max;				/* number of interrupts needed to schedule the bh */
+	u16 delay;                              /* timer delay */
 };
 
-void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u32);
+void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u16);
 void emu10k1_timer_uninstall(struct emu10k1_card *, struct emu_timer *);
 void emu10k1_timer_enable(struct emu10k1_card *, struct emu_timer *);
 void emu10k1_timer_disable(struct emu10k1_card *, struct emu_timer *);
 
-#define TIMER_STOPPED 			0xffffffff 
+#define TIMER_STOPPED 			0xffff 
 #define TIMER_STATE_INSTALLED 		0x01
 #define TIMER_STATE_ACTIVE		0x02
 #define TIMER_STATE_UNINSTALLED 	0x04
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/voicemgr.c linux-2.5.65-bk3/sound/oss/emu10k1/voicemgr.c
--- linux-2.5.65-bk2/sound/oss/emu10k1/voicemgr.c	Mon Mar 17 13:44:09 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/voicemgr.c	Mon Mar 31 12:41:50 2003
@@ -32,6 +32,84 @@
 #include "voicemgr.h"
 #include "8010.h"
 
+/**
+ * emu10k1_voice_alloc_buffer -
+ *
+ * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
+ * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
+ * is passed to the device so that it can do DMA to host memory.
+ *
+ */
+int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages)
+{
+	u32 pageindex, pagecount;
+	u32 busaddx;
+	int i;
+
+	DPD(2, "requested pages is: %d\n", pages);
+
+	if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0)
+	{
+		DPF(1, "couldn't allocate emu10k1 address space\n");
+		return -1;
+	}
+
+	/* Fill in virtual memory table */
+	for (pagecount = 0; pagecount < pages; pagecount++) {
+		if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount]))
+			== NULL) {
+			mem->pages = pagecount;
+			DPF(1, "couldn't allocate dma memory\n");
+			return -1;
+		}
+
+		DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]);
+
+		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
+			busaddx = (u32) mem->dma_handle[pagecount] + i * EMUPAGESIZE;
+
+			DPD(3, "Bus Addx: %#x\n", busaddx);
+
+			pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
+
+			((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
+		}
+	}
+
+	mem->pages = pagecount;
+
+	return 0;
+}
+
+/**
+ * emu10k1_voice_free_buffer -
+ *
+ * frees the memory buffer for a voice.
+ */
+void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem)
+{
+	u32 pagecount, pageindex;
+	int i;
+
+	if (mem->emupageindex < 0)
+		return;
+
+	for (pagecount = 0; pagecount < mem->pages; pagecount++) {
+		pci_free_consistent(card->pci_dev, PAGE_SIZE,
+					mem->addr[pagecount],
+					mem->dma_handle[pagecount]);
+
+		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
+			pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
+			((u32 *) card->virtualpagetable.addr)[pageindex] =
+				cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pageindex);
+		}
+	}
+
+	emu10k1_addxmgr_free(card, mem->emupageindex);
+	mem->emupageindex = -1;
+}
+
 int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
 {
 	u8 *voicetable = card->voicetable;
@@ -96,8 +174,10 @@
 							VTFT, 0x0000ffff,
 							PTRX_PITCHTARGET, 0,
 							CVCF, 0x0000ffff,
-							CPF, 0,
+							//CPF, 0,
 							TAGLIST_END);
+		
+		sblive_writeptr(card, CPF, voice->num + i, 0);
 	}
 
 	voice->usage = VOICE_USAGE_FREE;
@@ -151,8 +231,8 @@
 				    Z1, 0,
 				    Z2, 0,
 				    /* Invalidate maps */
-				    MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
-				    MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+				    MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
+				    MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
 				/* modulation envelope */
 				    CVCF, 0x0000ffff,
 				    VTFT, 0x0000ffff,
diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/voicemgr.h linux-2.5.65-bk3/sound/oss/emu10k1/voicemgr.h
--- linux-2.5.65-bk2/sound/oss/emu10k1/voicemgr.h	Mon Mar 17 13:44:09 2003
+++ linux-2.5.65-bk3/sound/oss/emu10k1/voicemgr.h	Mon Mar 31 12:41:50 2003
@@ -64,6 +64,12 @@
 	u32 byampl_env_decay;
 };
 
+struct voice_mem {
+	int emupageindex;
+	void *addr[BUFMAXPAGES];
+	dma_addr_t dma_handle[BUFMAXPAGES];
+	u32 pages;
+};
 
 struct emu_voice
 {
@@ -72,16 +78,20 @@
 	u8 num;			/* Voice ID */
 	u8 flags;		/* Stereo/mono, 8/16 bit */
 
-        u32 startloop;
-        u32 endloop;
+	u32 startloop;
+	u32 endloop;
 	u32 start;
 
 	u32 initial_pitch;
 	u32 pitch_target;
 
 	struct voice_param params[2];
+
+	struct voice_mem mem;
 };
 
+int emu10k1_voice_alloc_buffer(struct emu10k1_card *, struct voice_mem *, u32);
+void emu10k1_voice_free_buffer(struct emu10k1_card *, struct voice_mem *);
 int emu10k1_voice_alloc(struct emu10k1_card *, struct emu_voice *);
 void emu10k1_voice_free(struct emu_voice *);
 void emu10k1_voice_playback_setup(struct emu_voice *);
diff -urN linux-2.5.65-bk2/sound/oss/i810_audio.c linux-2.5.65-bk3/sound/oss/i810_audio.c
--- linux-2.5.65-bk2/sound/oss/i810_audio.c	Mon Mar 17 13:44:38 2003
+++ linux-2.5.65-bk3/sound/oss/i810_audio.c	Mon Mar 31 12:41:50 2003
@@ -2406,9 +2406,9 @@
 				i810_set_dac_channels ( state, channels );
 
 				/* check that they really got turned on */
-				if ( !state->card->ac97_status & SURR_ON )
+				if (!(state->card->ac97_status & SURR_ON))
 					val &= ~DSP_BIND_SURR;
-				if ( !state->card->ac97_status & CENTER_LFE_ON )
+				if (!(state->card->ac97_status & CENTER_LFE_ON))
 					val &= ~DSP_BIND_CENTER_LFE;
 			}
 		}
diff -urN linux-2.5.65-bk2/sound/oss/maestro.c linux-2.5.65-bk3/sound/oss/maestro.c
--- linux-2.5.65-bk2/sound/oss/maestro.c	Mon Mar 17 13:44:43 2003
+++ linux-2.5.65-bk3/sound/oss/maestro.c	Mon Mar 31 12:41:50 2003
@@ -3367,7 +3367,7 @@
 	/* check to see if we have a capabilities list in
 		the config register */
 	pci_read_config_word(pcidev, PCI_STATUS, &w);
-	if(! w & PCI_STATUS_CAP_LIST) return 0;
+	if(!(w & PCI_STATUS_CAP_LIST)) return 0;
 
 	/* walk the list, starting at the head. */
 	pci_read_config_byte(pcidev,PCI_CAPABILITY_LIST,&next);
diff -urN linux-2.5.65-bk2/sound/oss/midi_syms.c linux-2.5.65-bk3/sound/oss/midi_syms.c
--- linux-2.5.65-bk2/sound/oss/midi_syms.c	Mon Mar 17 13:43:42 2003
+++ linux-2.5.65-bk3/sound/oss/midi_syms.c	Mon Mar 31 12:41:50 2003
@@ -1,9 +1,7 @@
 /*
  * Exported symbols for midi driver.
- * __NO_VERSION__ because this is still part of sound.o.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 char midi_syms_symbol;
diff -urN linux-2.5.65-bk2/sound/oss/mpu401.c linux-2.5.65-bk3/sound/oss/mpu401.c
--- linux-2.5.65-bk2/sound/oss/mpu401.c	Mon Mar 17 13:44:44 2003
+++ linux-2.5.65-bk3/sound/oss/mpu401.c	Mon Mar 31 12:41:50 2003
@@ -1762,13 +1762,13 @@
 
 static struct address_info cfg;
 
-static int __initdata io = -1;
-static int __initdata irq = -1;
+static int io = -1;
+static int irq = -1;
 
 MODULE_PARM(irq, "i");
 MODULE_PARM(io, "i");
 
-int __init init_mpu401(void)
+static int __init init_mpu401(void)
 {
 	int ret;
 	/* Can be loaded either for module use or to provide functions
@@ -1785,7 +1785,7 @@
 	return 0;
 }
 
-void __exit cleanup_mpu401(void)
+static void __exit cleanup_mpu401(void)
 {
 	if (io != -1 && irq != -1) {
 		/* Check for use by, for example, sscape driver */
diff -urN linux-2.5.65-bk2/sound/oss/nm256_audio.c linux-2.5.65-bk3/sound/oss/nm256_audio.c
--- linux-2.5.65-bk2/sound/oss/nm256_audio.c	Mon Mar 17 13:44:05 2003
+++ linux-2.5.65-bk3/sound/oss/nm256_audio.c	Mon Mar 31 12:41:50 2003
@@ -19,7 +19,6 @@
  *		Ported to 2.4 PCI API.
  */
 
-#define __NO_VERSION__
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
diff -urN linux-2.5.65-bk2/sound/oss/sequencer_syms.c linux-2.5.65-bk3/sound/oss/sequencer_syms.c
--- linux-2.5.65-bk2/sound/oss/sequencer_syms.c	Mon Mar 17 13:44:01 2003
+++ linux-2.5.65-bk3/sound/oss/sequencer_syms.c	Mon Mar 31 12:41:50 2003
@@ -1,9 +1,7 @@
 /*
  * Exported symbols for sequencer driver.
- * __NO_VERSION__ because this is still part of sound.o.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 char sequencer_syms_symbol;
diff -urN linux-2.5.65-bk2/sound/pci/ac97/ac97_codec.c linux-2.5.65-bk3/sound/pci/ac97/ac97_codec.c
--- linux-2.5.65-bk2/sound/pci/ac97/ac97_codec.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/sound/pci/ac97/ac97_codec.c	Mon Mar 31 12:41:50 2003
@@ -1870,7 +1870,7 @@
  */
 static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
 {
-	signed long end_time;
+	unsigned long end_time;
 	end_time = jiffies + timeout;
 	do {
 		unsigned short ext_mid;
@@ -1930,7 +1930,7 @@
 	int err;
 	ac97_t *ac97;
 	char name[64];
-	signed long end_time;
+	unsigned long end_time;
 	static snd_device_ops_t ops = {
 		.dev_free =	snd_ac97_dev_free,
 	};
@@ -2083,7 +2083,7 @@
  */
 static int ac97_modem_reset_wait(ac97_t *ac97, int timeout)
 {
-	signed long end_time;
+	unsigned long end_time;
 	end_time = jiffies + timeout;
 	do {
 		unsigned short ext_mid;
diff -urN linux-2.5.65-bk2/sound/pci/intel8x0.c linux-2.5.65-bk3/sound/pci/intel8x0.c
--- linux-2.5.65-bk2/sound/pci/intel8x0.c	Mon Mar 31 12:41:37 2003
+++ linux-2.5.65-bk3/sound/pci/intel8x0.c	Mon Mar 31 12:41:51 2003
@@ -1778,7 +1778,7 @@
 
 static int snd_intel8x0_ich_chip_init(intel8x0_t *chip)
 {
-	signed long end_time;
+	unsigned long end_time;
 	unsigned int cnt, status, nstatus;
 	
 	/* put logic to right state */
