lines    added  deleted
linux/Documentation/Configure.help        :      70       37       12
linux/Documentation/oops-tracing.txt      :      24       21        0
linux/Makefile                            :       8        1        1
linux/README                              :      24        2       16
linux/arch/i386/boot/Makefile             :       8        1        1
linux/arch/i386/kernel/setup.c            :      17        3        1
linux/arch/i386/kernel/smp.c              :       7        1        0
linux/drivers/char/misc.c                 :      33        0        6
linux/drivers/char/tty_io.c               :      29        0        6
linux/drivers/misc/parport_arc.c          :       9        0        2
linux/drivers/misc/parport_ax.c           :      19        0        4
linux/drivers/misc/parport_init.c         :      32        2        6
linux/drivers/misc/parport_pc.c           :      19        1        3
linux/drivers/misc/parport_procfs.c       :      49       26        2
linux/drivers/net/ibmtr.c                 :      43       13        1
linux/drivers/pci/oldproc.c               :       7        1        0
linux/drivers/scsi/Config.in              :      28        8        7
linux/drivers/scsi/Makefile               :      10        1        3
linux/drivers/scsi/aic7xxx.c              :     106       21       22
linux/drivers/scsi/eata_dma_proc.c        :      18        0        5
linux/drivers/scsi/eata_pio_proc.c        :      17        0        4
linux/drivers/scsi/imm.c                  :     695      206      281
linux/drivers/scsi/imm.h                  :     167       56       41
linux/drivers/scsi/ppa.c                  :     453       42      267
linux/drivers/scsi/ppa.h                  :     118       29       28
linux/drivers/scsi/scsi_debug.c           :      24        4        2
linux/drivers/scsi/scsi_proc.c            :      13        7        0
linux/drivers/scsi/scsi_syms.c            :       9        0        2
linux/drivers/sound/soundcard.c           :      10        2        0
linux/fs/binfmt_misc.c                    :      49       16        6
linux/fs/fat/inode.c                      :      10        2        2
linux/fs/nfs/write.c                      :      22        3        5
linux/fs/nfsd/nfsctl.c                    :      45        0        9
linux/fs/nfsd/stats.c                     :      12        0        2
linux/fs/nfsd/vfs.c                       :       8        1        1
linux/fs/ntfs/Makefile                    :       8        1        1
linux/fs/ntfs/attr.c                      :     210       63       24
linux/fs/ntfs/attr.h                      :       6        3        0
linux/fs/ntfs/dir.c                       :     484      215       42
linux/fs/ntfs/dir.h                       :      14        3        1
linux/fs/ntfs/fs.c                        :     347      143       38
linux/fs/ntfs/inode.c                     :     417      133       61
linux/fs/ntfs/inode.h                     :      33       10        7
linux/fs/ntfs/macros.h                    :      24        9        0
linux/fs/ntfs/ntfsendian.h                :      86       86        0
linux/fs/ntfs/ntfstypes.h                 :      90       90        0
linux/fs/ntfs/super.c                     :     198       27       21
linux/fs/ntfs/super.h                     :       8        2        2
linux/fs/ntfs/support.c                   :      37       12        6
linux/fs/ntfs/support.h                   :      27       12        2
linux/fs/ntfs/sysctl.h                    :      10        4        0
linux/fs/ntfs/types.h                     :     128        0      128
linux/fs/ntfs/util.c                      :     174       42       18
linux/fs/ntfs/util.h                      :       9        3        0
linux/fs/proc/procfs_syms.c               :       7        0        1
linux/include/linux/fs.h                  :      18        8        3
linux/include/linux/pci.h                 :       7        1        0
linux/include/linux/proc_fs.h             :      35       24        0
linux/include/linux/sunrpc/stats.h        :      27       15        0
linux/include/linux/swapctl.h             :      18        0       12
linux/ipc/util.c                          :       9        2        1
linux/mm/page_alloc.c                     :      26        4        1
linux/mm/vmscan.c                         :      92       20       19
linux/net/sunrpc/sched.c                  :       7        0        1
linux/net/sunrpc/stats.c                  :       7        1        0
linux/net/sunrpc/sysctl.c                 :      10        2        0
linux/scripts/header.tk                   :      17        2        2
linux/scripts/ksymoops-0.6/Makefile       :      72       72        0
linux/scripts/ksymoops-0.6/README         :     358      358        0
linux/scripts/ksymoops-0.6/io.c           :     139      139        0
linux/scripts/ksymoops-0.6/ksymoops.c     :     569      569        0
linux/scripts/ksymoops-0.6/ksymoops.h     :     145      145        0
linux/scripts/ksymoops-0.6/ksyms.c        :     287      287        0
linux/scripts/ksymoops-0.6/map.c          :     251      251        0
linux/scripts/ksymoops-0.6/misc.c         :     108      108        0
linux/scripts/ksymoops-0.6/object.c       :     230      230        0
linux/scripts/ksymoops-0.6/oops.c         :    1061     1061        0
linux/scripts/ksymoops-0.6/patches/README :      15       15        0
linux/scripts/ksymoops-0.6/patches/mips   :     167      167        0
linux/scripts/ksymoops-0.6/patches/ppc    :      67       67        0
linux/scripts/ksymoops-0.6/re.c           :     145      145        0
linux/scripts/ksymoops-0.6/symbol.c       :     440      440        0
linux/scripts/ksymoops.cc                 :     411        0      411
linux/scripts/tkcond.c                    :      10        2        2
-- 
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.
#!/bin/sh
# This is a shell archive
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
# existing files will NOT be overwritten unless -c is specified
#
# This is part 1 of a 5 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
if test -r _shar_seq_.tmp; then
        echo 'Must unpack archives in sequence!'
        echo Please unpack part `cat _shar_seq_.tmp` next
        exit 1
fi
# ============= patch-2.2.0-pre4 ==============
if test -f 'patch-2.2.0-pre4' -a X"$1" != X"-c"; then
        echo 'x - skipping patch-2.2.0-pre4 (File already exists)'
        rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.2.0-pre4 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.2.0-pre4' &&
diff -u --recursive --new-file v2.2.0-pre3/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.0-pre3/linux/Documentation/Configure.help	Fri Jan  1 12:58:14 1999
+++ linux/Documentation/Configure.help	Sat Jan  2 17:50:15 1999
@@ -1631,9 +1631,13 @@
X   information.
X 
X   Say Y here and to the driver for your graphics board below if you
-  are compiling a kernel for a non-x86 architecture. If you are
-  compiling for the x86 architecture, you can say Y if you want to
-  play with it, but it is not essential.
+  are compiling a kernel for a non-x86 architecture.
+
+  If you are compiling for the x86 architecture, you can say Y if you
+  want to play with it, but it is not essential. Please note that
+  running graphical applications that directly touch the hardware (e.g.
+  and accelerated X server) and that are not frame buffer device-aware
+  may cause unexpected results. If unsure, say N.
X 
X Acorn VIDC support
X CONFIG_FB_ACORN
@@ -4356,23 +4360,44 @@
X   drive: it will be supported automatically if you said Y to the
X   generic "SCSI disk support", above.
X 
+  The ZIP Plus drive is supported by the imm driver, also more recent
+  parallel port ZIP drives use an imm compatible interface. If the
+  supplied cable with the drive is labeled "AutoDetect" then you will
+  need the imm driver.
+
X   This driver is also available as a module which can be inserted in
X   and removed from the running kernel whenever you want. To compile
X   this driver as a module, say M here and read
X   Documentation/modules.txt. The module will be called ppa.o. 
X 
-EPP FIFO Checking
-CONFIG_SCSI_PPA_HAVE_PEDANTIC
+IOMEGA Parallel Port ZIP drive SCSI support
+CONFIG_SCSI_IMM
+  All "new and improved" parallel port to SCSI interface from Iomega.
+  Please read the comments for the ppa driver for further information
+
+Force the Iomega ZIP drivers to use EPP-16
+CONFIG_SCSI_IZIP_EPP16
X   EPP (Enhanced Parallel Port) is a standard for parallel ports which
X   allows them to act as expansion buses that can handle up to 64
-  peripheral devices. Some parallel port chipsets are slower than
-  their motherboard, and so we have to control the state of the
-  chipset's FIFO queue every now and then to avoid data loss. This
-  will be done if you say Y here. 
+  peripheral devices.
+
+  Some parallel port chipsets are slower than their motherboard, and
+  so we have to control the state of the chipset's FIFO queue every
+  now and then to avoid data loss. This will be done if you say Y here. 
X   
-  If your EPP chipset is from the SMC series, you are likely to have
-  to say Y here. Generally, saying Y is the safe option and slows
-  things down a bit.
+  Generally, saying Y is the safe option and slows things down a bit.
+
+Assume slow parallel port control register
+CONFIG_SCSI_IZIP_SLOW_CTR
+  Some parallel ports are known to have excessive delays between changing
+  the parallel port control register and good data being available on
+  the parallel port data/status register. This option forces a small delay
+  (1.0 usec to be exact) after changing the control register to let things
+  settle out. Enabling this option may result in a big drop in performance
+  but some very old parallel ports (found in 386 vintage machines) will
+  not work properly.
+
+  Generally, saying N is fine.
X 
X SCSI Debug host simulator.
X CONFIG_SCSI_DEBUG
diff -u --recursive --new-file v2.2.0-pre3/linux/Documentation/oops-tracing.txt linux/Documentation/oops-tracing.txt
--- v2.2.0-pre3/linux/Documentation/oops-tracing.txt	Sat May  2 14:19:51 1998
+++ linux/Documentation/oops-tracing.txt	Sat Jan  2 10:02:04 1999
@@ -1,3 +1,24 @@
+Quick Summary
+-------------
+
+cd /usr/src/linux/scripts
+g++ -o ksymoops ksymoops.cc
+./ksymoops ../System.map < the_oops.txt
+
+and send the output the maintainer of the kernel area that seems to be
+involved with the problem. Don't worry too much about getting the wrong
+person. If you are unsure send it to the person responsible for the code
+relevant to what you were doing. If it occurs repeatably try and describe
+how to recreate it. Thats worth even more than the oops
+
+If you are totally stumped as to whom to send the report, send it to 
+linux-...@vger.rutgers.edu. Thanks for your help in making Linux as
+stable as humanly possible.
+
+
+Full Information
+----------------
+
X From: Linus Torvalds <torv...@cs.helsinki.fi>
X 
X How to track down an Oops.. [originally a mail to linux-kernel]
diff -u --recursive --new-file v2.2.0-pre3/linux/Makefile linux/Makefile
--- v2.2.0-pre3/linux/Makefile	Fri Jan  1 12:58:14 1999
+++ linux/Makefile	Fri Jan  1 12:58:29 1999
@@ -1,7 +1,7 @@
X VERSION = 2
X PATCHLEVEL = 2
X SUBLEVEL = 0
-EXTRAVERSION =-pre3
+EXTRAVERSION =-pre4
X 
X ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
X 
diff -u --recursive --new-file v2.2.0-pre3/linux/README linux/README
--- v2.2.0-pre3/linux/README	Fri Oct 23 22:01:19 1998
+++ linux/README	Sat Jan  2 10:04:36 1999
@@ -1,22 +1,8 @@
-	Linux kernel release 2.1.xx
+	Linux kernel release 2.2.xx
X 
-These are the release notes for Linux version 2.1.  Read them carefully,
+These are the release notes for Linux version 2.2.  Read them carefully,
X as they tell you what this is all about, explain how to install the
X kernel, and what to do if something goes wrong. 
-
-Linux version 2.1 is a DEVELOPMENT kernel, and not intended for general
-public use.  Different releases may have various and sometimes severe
-bugs.  It is *strongly* recommended that you back up the previous kernel
-before installing any new 2.1.xx release.
-
-If you need to use a proven and stable Linux kernel, please use 1.0.9,
-1.2.13, or 2.0.xx.  All features which will be in the 2.1.xx releases will
-be contained in 2.2.xx when the code base has stabilized again.
-
-If you decide to use 2.1, it is recommended that you join the kernel mailing
-list.  To do this, e-mail majo...@vger.rutgers.edu, and put in the body
-of the message "subscribe linux-kernel" or "subscribe linux-kernel-digest"
-for a daily digest of the mailing list (it is a high-traffic list.)
X 
X However, please make sure you don't ask questions which are already answered
X in various files in the Documentation directory.  See DOCUMENTATION below.
diff -u --recursive --new-file v2.2.0-pre3/linux/arch/i386/boot/Makefile linux/arch/i386/boot/Makefile
--- v2.2.0-pre3/linux/arch/i386/boot/Makefile	Tue Jul 21 00:15:30 1998
+++ linux/arch/i386/boot/Makefile	Sat Jan  2 10:27:52 1999
@@ -40,7 +40,7 @@
X 	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
X 
X install: $(CONFIGURE) $(BOOTIMAGE)
-	sh -x ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) $(BOOTIMAGE) $(TOPDIR)/System.map "$(INSTALL_PATH)"
+	sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map "$(INSTALL_PATH)"
X 
X tools/build: tools/build.c
X 	$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
diff -u --recursive --new-file v2.2.0-pre3/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.2.0-pre3/linux/arch/i386/kernel/setup.c	Fri Jan  1 12:58:19 1999
+++ linux/arch/i386/kernel/setup.c	Sat Jan  2 18:03:33 1999
@@ -675,7 +675,7 @@
X 			p += sprintf(p, "stepping\t: unknown\n");
X 
X 		if (c->x86_capability & X86_FEATURE_TSC) {
-			p += sprintf(p, "cpu MHz\t\t: %lu.%02lu\n",
+			p += sprintf(p, "cpu MHz\t\t: %lu.%06lu\n",
X 				cpu_hz / 1000000, (cpu_hz % 1000000));
X 		}
X 
@@ -689,6 +689,8 @@
X 		} else if (c->x86_vendor == X86_VENDOR_AMD) {
X 			x86_cap_flags[16] = "fcmov";
X 			x86_cap_flags[31] = "3dnow";
+			if (c->x86 == 5 && c->x86_model == 6)
+				x86_cap_flags[10] = "sep";
X 		} else if (c->x86_vendor == X86_VENDOR_INTEL) {
X 			x86_cap_flags[6] = "pae";
X 			x86_cap_flags[9] = "apic";
diff -u --recursive --new-file v2.2.0-pre3/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.2.0-pre3/linux/arch/i386/kernel/smp.c	Fri Jan  1 12:58:19 1999
+++ linux/arch/i386/kernel/smp.c	Sat Jan  2 10:18:07 1999
@@ -1126,6 +1126,7 @@
X 	{
X 		printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n");
X 		io_apic_irqs = 0;
+		cpu_online_map = cpu_present_map;
X 		goto smp_done;
X 	}
X 
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.2.0-pre3/linux/drivers/char/misc.c	Fri Nov 27 13:09:23 1998
+++ linux/drivers/char/misc.c	Sat Jan  2 17:55:05 1999
@@ -86,7 +86,6 @@
X extern int pc110pad_init(void);
X extern int pmu_device_init(void);
X 
-#ifdef CONFIG_PROC_FS
X static int misc_read_proc(char *buf, char **start, off_t offset,
X 			  int len, int *eof, void *private)
X {
@@ -99,7 +98,6 @@
X 	return len > offset ? len - offset : 0;
X }
X 
-#endif /* PROC_FS */
X 
X static int misc_open(struct inode * inode, struct file * file)
X {
@@ -185,17 +183,13 @@
X EXPORT_SYMBOL(misc_register);
X EXPORT_SYMBOL(misc_deregister);
X 
-#if defined(CONFIG_PROC_FS)
X static struct proc_dir_entry *proc_misc;	
-#endif
X 
X int __init misc_init(void)
X {
-#ifdef CONFIG_PROC_FS
X 	proc_misc = create_proc_entry("misc", 0, 0);
X 	if (proc_misc)
X 		proc_misc->read_proc = misc_read_proc;
-#endif /* PROC_FS */
X #ifdef CONFIG_BUSMOUSE
X 	bus_mouse_init();
X #endif
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.2.0-pre3/linux/drivers/char/tty_io.c	Wed Dec 16 10:32:55 1998
+++ linux/drivers/char/tty_io.c	Sat Jan  2 17:55:05 1999
@@ -77,9 +77,7 @@
X #include <linux/string.h>
X #include <linux/malloc.h>
X #include <linux/poll.h>
-#ifdef CONFIG_PROC_FS
X #include <linux/proc_fs.h>
-#endif
X #include <linux/init.h>
X #include <linux/smp_lock.h>
X 
@@ -1966,9 +1964,7 @@
X 	if (tty_drivers) tty_drivers->prev = driver;
X 	tty_drivers = driver;
X 	
-#ifdef CONFIG_PROC_FS
X 	proc_tty_register_driver(driver);
-#endif	
X 	return error;
X }
X 
@@ -2010,9 +2006,7 @@
X 	if (driver->next)
X 		driver->next->prev = driver->prev;
X 
-#ifdef CONFIG_PROC_FS
X 	proc_tty_unregister_driver(driver);
-#endif
X 	return 0;
X }
X 
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/misc/parport_arc.c linux/drivers/misc/parport_arc.c
--- v2.2.0-pre3/linux/drivers/misc/parport_arc.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/misc/parport_arc.c	Sat Jan  2 17:55:05 1999
@@ -142,9 +142,7 @@
X 
X 	printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
X 	       p->irq);
-#ifdef	CONFIG_PROC_FS
X 	parport_proc_register(p);
-#endif
X 	p->flags |= PARPORT_FLAG_COMA;
X 
X 	if (parport_probe_hook)
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/misc/parport_ax.c linux/drivers/misc/parport_ax.c
--- v2.2.0-pre3/linux/drivers/misc/parport_ax.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/misc/parport_ax.c	Sat Jan  2 17:55:05 1999
@@ -586,9 +586,7 @@
X 		printmode(ECPPS2);
X 	}
X 	printk("]\n");
-#ifdef	CONFIG_PROC_FS
X 	parport_proc_register(p);
-#endif
X 	p->flags |= PARPORT_FLAG_COMA;
X 
X 	p->ops->write_control(p, 0x0c);
@@ -631,9 +629,7 @@
X 		if (p->modes & PARPORT_MODE_PCSPP) { 
X 			if (!(p->flags & PARPORT_FLAG_COMA)) 
X 				parport_quiesce(p);
-#ifdef	CONFIG_PROC_FS
X 			parport_proc_unregister(p);
-#endif
X 			parport_unregister_port(p);
X 		}
X 		p = tmp;
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/misc/parport_init.c linux/drivers/misc/parport_init.c
--- v2.2.0-pre3/linux/drivers/misc/parport_init.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/misc/parport_init.c	Sat Jan  2 17:55:05 1999
@@ -98,19 +98,17 @@
X #ifdef MODULE
X int init_module(void)
X {
-#ifdef	CONFIG_PROC_FS
X 	(void)parport_proc_init();	/* We can go on without it. */
-#endif
X 	return 0;
X }
X 
X void cleanup_module(void)
X {
-#ifdef	CONFIG_PROC_FS
X 	parport_proc_cleanup();
-#endif
X }
+
X #else
+
X __initfunc(int parport_init(void))
X {
X 	if (io[0] == PARPORT_DISABLE) 
@@ -145,10 +143,8 @@
X EXPORT_SYMBOL(parport_enumerate);
X EXPORT_SYMBOL(parport_ieee1284_nibble_mode_ok);
X EXPORT_SYMBOL(parport_wait_peripheral);
-#ifdef	CONFIG_PROC_FS
X EXPORT_SYMBOL(parport_proc_register);
X EXPORT_SYMBOL(parport_proc_unregister);
-#endif
X EXPORT_SYMBOL(parport_probe_hook);
X EXPORT_SYMBOL(parport_parse_irqs);
X 
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.2.0-pre3/linux/drivers/misc/parport_pc.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/misc/parport_pc.c	Sat Jan  2 17:55:05 1999
@@ -759,8 +759,8 @@
X #ifdef	CONFIG_PROC_FS
X 	if (probedirq != PARPORT_IRQ_NONE) 
X 		printk("%s: detected irq %d; use procfs to enable interrupt-driven operation.\n", p->name, probedirq);
-	parport_proc_register(p);
X #endif
+	parport_proc_register(p);
X 	p->flags |= PARPORT_FLAG_COMA;
X 
X 	/* Done probing.  Now put the port into a sensible start-up state. */
@@ -824,9 +824,7 @@
X 		if (p->modes & PARPORT_MODE_PCSPP) { 
X 			if (!(p->flags & PARPORT_FLAG_COMA)) 
X 				parport_quiesce(p);
-#ifdef	CONFIG_PROC_FS
X 			parport_proc_unregister(p);
-#endif
X 			parport_unregister_port(p);
X 		}
X 		p = tmp;
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/misc/parport_procfs.c linux/drivers/misc/parport_procfs.c
--- v2.2.0-pre3/linux/drivers/misc/parport_procfs.c	Sun Nov  8 14:02:59 1998
+++ linux/drivers/misc/parport_procfs.c	Sat Jan  2 17:55:05 1999
@@ -27,6 +27,8 @@
X #include <asm/dma.h>
X #include <asm/irq.h>
X 
+#ifdef CONFIG_PROC_FS
+
X struct proc_dir_entry *base = NULL;
X 
X static int irq_write_proc(struct file *file, const char *buffer,
@@ -305,12 +307,11 @@
X {
X 	base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT,
X 			      NULL);
-	base->fill_inode = &parport_modcount;
-
X 	if (base == NULL) {
X 		printk(KERN_ERR "Unable to initialise /proc/parport.\n");
X 		return 0;
X 	}
+	base->fill_inode = &parport_modcount;
X 
X 	return 1;
X }
@@ -385,3 +386,26 @@
X 	destroy_proc_tree(pp);
X 	return 0;
X }
+
+#else
+
+int parport_proc_register(struct parport *p) 
+{
+	return 0;
+}
+
+int parport_proc_unregister(struct parport *p)
+{
+	return 0;
+}
+
+int parport_proc_init(void)
+{
+	return 0;
+}
+
+void parport_proc_cleanup(void)
+{
+}
+
+#endif
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- v2.2.0-pre3/linux/drivers/net/ibmtr.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/ibmtr.c	Sat Jan  2 10:27:22 1999
@@ -66,8 +66,17 @@
X  *      + lifted 2000 byte mtu limit. now depends on shared-RAM size.
X  *        May 25 1998)
X  *      + can't allocate 2k recv buff at 8k shared-RAM. (20 October 1998)
+ *
+ *      Changes by Joel Sloan (j...@c-me.com) :
+ *      + disable verbose debug messages by default - to enable verbose
+ *	  debugging, edit the IBMTR_DEBUG_MESSAGES define below 
X  */
X 
+/* change the define of IBMTR_DEBUG_MESSAGES to a nonzero value 
+in the event that chatty debug messages are desired - jjs 12/30/98 */
+
+#define IBMTR_DEBUG_MESSAGES 0
+
X #ifdef PCMCIA
X #define MODULE
X #endif
@@ -95,7 +104,8 @@
X /* version and credits */
X static char *version =
X "ibmtr.c: v1.3.57   8/ 7/94 Peter De Schrijver and Mark Swanson\n"
-"         v2.1.125 10/20/98 Paul Norton <pno...@ieee.org>\n";
+"         v2.1.125 10/20/98 Paul Norton <pno...@ieee.org>\n"
+"         v2.2.0   12/30/98 Joel Sloan <j...@c-me.com>\n";
X 
X static char pcchannelid[] = {
X 	0x05, 0x00, 0x04, 0x09,
@@ -999,6 +1009,7 @@
X 						DPRINTK("error on dir_read_log: %02X\n",
X 							(int)readb(ti->srb+offsetof(struct srb_read_log, ret_code)));
X 					else
+					    if (IBMTR_DEBUG_MESSAGES) {
X 						DPRINTK(
X 							"Line errors %02X, Internal errors %02X, Burst errors %02X\n"
X 							"A/C errors %02X, Abort delimiters %02X, Lost frames %02X\n"
@@ -1023,6 +1034,7 @@
X 										    frequency_errors)),
X 							(int)readb(ti->srb+offsetof(struct srb_read_log,
X 												    token_errors)));
+					    }
X 					dev->tbusy=0;
X 					break;
X 
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.2.0-pre3/linux/drivers/pci/oldproc.c	Thu Dec 31 10:29:01 1998
+++ linux/drivers/pci/oldproc.c	Sat Jan  2 18:11:22 1999
@@ -541,6 +541,7 @@
X 	DEVICE( ADAPTEC2,	ADAPTEC2_2940U2,"AHA-2940U2"),
X 	DEVICE( ADAPTEC2,	ADAPTEC2_7890,	"AIC-7890/1"),
X 	DEVICE( ADAPTEC2,	ADAPTEC2_3940U2,"AHA-3940U2"),
+	DEVICE( ADAPTEC2,	ADAPTEC2_3950U2D,"AHA-3950U2D"),
X 	DEVICE( ADAPTEC2,	ADAPTEC2_7896,	"AIC-7896/7"),
X   	DEVICE( ATRONICS,	ATRONICS_2015,	"IDE-2015PL"),
X 	DEVICE( TIGERJET,	TIGERJET_300,	"Tiger300 ISDN"),
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.2.0-pre3/linux/drivers/scsi/Config.in	Thu Dec 31 10:29:01 1998
+++ linux/drivers/scsi/Config.in	Sat Jan  2 10:21:06 1999
@@ -58,13 +58,6 @@
X fi
X dep_tristate 'GDT SCSI Disk Array Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI
X dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
-if [ "$CONFIG_PARPORT" != "n" ]; then
-  dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
-  if [ "$CONFIG_SCSI_PPA" != "n" ]; then
-    bool  '  Pedantic EPP-checking'   CONFIG_SCSI_PPA_HAVE_PEDANTIC
-  fi
-  dep_tristate 'IOMEGA ZIP Plus drive SCSI support' CONFIG_SCSI_IMM $CONFIG_SCSI $CONFIG_PARPORT
-fi
X if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then
X 	bool '   Enable NCR53c400 extensions' CONFIG_SCSI_GENERIC_NCR53C400
X 	choice 'NCR5380/53c400 mapping method (use Port for T130B)' \
@@ -73,6 +66,14 @@
X fi
X if [ "$CONFIG_PCI" = "y" ]; then
X   dep_tristate 'Initio 9100U(W) support' CONFIG_SCSI_INITIO $CONFIG_SCSI
+fi
+if [ "$CONFIG_PARPORT" != "n" ]; then
+  dep_tristate 'IOMEGA parallel port (ppa - older drives)' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
+  dep_tristate 'IOMEGA parallel port (imm - newer drives)' CONFIG_SCSI_IMM $CONFIG_SCSI $CONFIG_PARPORT
+  if [ "$CONFIG_SCSI_PPA" != "n" -o "$CONFIG_SCSI_IMM" != "n" ]; then
+    bool  '  ppa/imm option - Use slow (but safe) EPP-16' CONFIG_SCSI_IZIP_EPP16
+    bool  '  ppa/imm option - Assume slow parport control register' CONFIG_SCSI_IZIP_SLOW_CTR
+  fi
X fi
X dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI
X if [ "$CONFIG_PCI" = "y" ]; then
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.2.0-pre3/linux/drivers/scsi/Makefile	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/Makefile	Sat Jan  2 17:55:05 1999
@@ -41,9 +41,7 @@
X   endif
X   L_OBJS += scsi_n_syms.o hosts.o scsi_ioctl.o constants.o scsicam.o
X   L_OBJS += scsi_error.o scsi_obsolete.o scsi_queue.o
-  ifeq ($(CONFIG_PROC_FS),y)
-    L_OBJS += scsi_proc.o
-  endif
+  L_OBJS += scsi_proc.o
X else
X   ifeq ($(CONFIG_SCSI),m)
X     MIX_OBJS += scsi_syms.o
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.2.0-pre3/linux/drivers/scsi/aic7xxx.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/aic7xxx.c	Sat Jan  2 18:11:22 1999
@@ -354,7 +354,7 @@
X     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
X };
X 
-#define AIC7XXX_C_VERSION  "5.1.6"
+#define AIC7XXX_C_VERSION  "5.1.7"
X 
X #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
X #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -580,6 +580,7 @@
X   "Adaptec AHA-294X Ultra2 SCSI host adapter",          /* AIC_7890 */
X   "Adaptec AIC-7896/7 Ultra2 SCSI host adapter",        /* AIC_7896 */
X   "Adaptec AHA-394X Ultra2 SCSI host adapter",          /* AIC_7897 */
+  "Adaptec AHA-395X Ultra2 SCSI host adapter",          /* AIC_7897 */
X   "Adaptec PCMCIA SCSI controller",                     /* card bus stuff */
X };
X 
@@ -5815,23 +5816,19 @@
X        * Put this SCB back on the free list.
X        */
X       aic7xxx_add_curscb_to_free_list(p);
-      /*
-       * XXX - If we queued an abort tag, go clean up the disconnected list.
-       * We know that this particular SCB had to be the queued abort since
-       * the disconnected SCB would have gotten a reconnect instead.
-       * However, if this is an abort command, then DID_TIMEOUT isn't
-       * appropriate, neither is returning the command for that matter.
-       * What we need to do then is to let the command timeout again so
-       * we get a reset since this abort just failed.
-       */
X #ifdef AIC7XXX_VERBOSE_DEBUGGING
X       if (aic7xxx_verbose > 0xffff)
X         printk(INFO_LEAD "Selection Timeout.\n", p->host_no, CTL_OF_SCB(scb));
X #endif
-      if (p->flags & SCB_QUEUED_ABORT)
+      if (scb->flags & SCB_QUEUED_ABORT)
X       {
+        /*
+         * We know that this particular SCB had to be the queued abort since
+         * the disconnected SCB would have gotten a reconnect instead.
+         * What we need to do then is to let the command timeout again so
+         * we get a reset since this abort just failed.
+         */
X         cmd->result = 0;
-        scb->flags &= ~SCB_QUEUED_ABORT;
X         scb = NULL;
X       }
X     }
@@ -7659,7 +7656,7 @@
X     aic_outb(p, p->scsi_id_b, SCSIID);
X     scsi_conf = aic_inb(p, SCSICONF + 1);
X     aic_outb(p, DFON | SPIOEN, SXFRCTL0);
-    aic_outb(p, (scsi_conf & ENSPCHK) | term | 
+    aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term | 
X          ENSTIMER | ACTNEGEN, SXFRCTL1);
X     aic_outb(p, 0, SIMODE0);
X     aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
@@ -7676,7 +7673,7 @@
X     aic_outb(p, p->scsi_id, SCSIID);
X   scsi_conf = aic_inb(p, SCSICONF);
X   aic_outb(p, DFON | SPIOEN, SXFRCTL0);
-  aic_outb(p, (scsi_conf & ENSPCHK) | term | 
+  aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term | 
X        ENSTIMER | ACTNEGEN, SXFRCTL1);
X   aic_outb(p, 0, SIMODE0);
X   aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
@@ -8856,9 +8853,13 @@
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
X        AHC_AIC7896_FE,                                      23,
X        32, C56_66 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+       AHC_AIC7896_FE,                                      24,
+       32, C56_66 },
X       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7860_FE,                                      24,
+       AHC_AIC7860_FE,                                      25,
X        32, C46 },
X     };
X 
@@ -9104,6 +9105,7 @@
X             case 15:
X             case 18:
X             case 19:
+            case 20:
X #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
X               if (PCI_FUNC(temp_p->pdev->devfn) != 0)
X               {
@@ -9271,13 +9273,10 @@
X           }
X 
X           /*
-           * We do another switch based on i so that we can exclude all
-           * 3895 devices from the next option since the 3895 cards use
-           * shared external SCB RAM while all other cards have dedicated
-           * external SCB RAM per channel.  Also exclude the 7850 and
-           * 7860 based stuff since they can have garbage in the bit
-           * that indicates external RAM and get some of this stuff
-           * wrong as a result.
+           * We only support external SCB RAM on the 7895/6/7 chipsets.
+           * We could support it on the 7890/1 easy enough, but I don't
+           * know of any 7890/1 based cards that have it.  I do know
+           * of 7895/6/7 cards that have it and they work properly.
X            */
X           switch(temp_p->chip & AHC_CHIPID_MASK)
X           {
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/eata_dma_proc.c linux/drivers/scsi/eata_dma_proc.c
--- v2.2.0-pre3/linux/drivers/scsi/eata_dma_proc.c	Thu Dec 31 10:29:01 1998
+++ linux/drivers/scsi/eata_dma_proc.c	Sat Jan  2 17:55:06 1999
@@ -69,8 +69,6 @@
X 		   int hostno, int inout)
X {
X 
-#ifdef CONFIG_PROC_FS
-
X     Scsi_Device *scd, SDev;
X     struct Scsi_Host *HBA_ptr;
X     Scsi_Cmnd scmd;
@@ -469,9 +467,6 @@
X     DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len));
X     
X     return (len);     
-#else /* CONFIG_PROC_FS */
-    return 0;
-#endif        
X }
X 
X /*
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/eata_pio_proc.c linux/drivers/scsi/eata_pio_proc.c
--- v2.2.0-pre3/linux/drivers/scsi/eata_pio_proc.c	Thu Dec 31 10:29:01 1998
+++ linux/drivers/scsi/eata_pio_proc.c	Sat Jan  2 17:55:06 1999
@@ -26,7 +26,6 @@
X int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length, 
X 		       int hostno, int inout)
X {
-#ifdef CONFIG_PROC_FS
X     Scsi_Device *scd;
X     struct Scsi_Host *HBA_ptr;
X     static u8 buff[512];
@@ -110,9 +109,6 @@
X     DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len));
X     
X     return (len);     
-#else
-    return 0;
-#endif        
X }
X 
X /*
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c
--- v2.2.0-pre3/linux/drivers/scsi/imm.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/imm.c	Sat Jan  2 10:21:06 1999
@@ -4,8 +4,7 @@
X  * (The IMM is the embedded controller in the ZIP Plus drive.)
X  * 
X  * Current Maintainer: David Campbell (Perth, Western Australia)
- *                     camp...@gear.torque.net
- *                     dcam...@p01.as17.honeywell.com.au
+ *                     camp...@torque.net
X  *
X  * My unoffical company acronym list is 21 pages long:
X  *      FLA:    Four letter acronym with built in facility for
@@ -31,7 +30,7 @@
X #include "sd.h"
X #include "hosts.h"
X typedef struct {
-    struct pardevice *dev;      /* Parport device entry         */
+    struct pardevice *dev;	/* Parport device entry         */
X     int base;			/* Actual port address          */
X     int mode;			/* Transfer mode                */
X     int host;			/* Host number (for proc)       */
@@ -65,23 +64,24 @@
X 
X #define IMM_BASE(x)	imm_hosts[(x)].base
X 
-int parbus_base[NO_HOSTS] = {0x03bc, 0x0378, 0x0278, 0x0000};
+int parbus_base[NO_HOSTS] =
+{0x03bc, 0x0378, 0x0278, 0x0000};
X 
X void imm_wakeup(void *ref)
X {
X     imm_struct *imm_dev = (imm_struct *) ref;
X 
X     if (!imm_dev->p_busy)
-        return;
+	return;
X 
X     if (parport_claim(imm_dev->dev)) {
-        printk("imm: bug in imm_wakeup\n");
-        return;
+	printk("imm: bug in imm_wakeup\n");
+	return;
X     }
X     imm_dev->p_busy = 0;
X     imm_dev->base = imm_dev->dev->port->base;
X     if (imm_dev->cur_cmd)
-        imm_dev->cur_cmd->SCp.phase++;
+	imm_dev->cur_cmd->SCp.phase++;
X     return;
X }
X 
@@ -97,12 +97,11 @@
X static int imm_pb_claim(int host_no)
X {
X     if (parport_claim(imm_hosts[host_no].dev)) {
-        imm_hosts[host_no].p_busy = 1;
-        return 1;
+	imm_hosts[host_no].p_busy = 1;
+	return 1;
X     }
-
X     if (imm_hosts[host_no].cur_cmd)
-        imm_hosts[host_no].cur_cmd->SCp.phase++;
+	imm_hosts[host_no].cur_cmd->SCp.phase++;
X     return 0;
X }
X 
@@ -112,40 +111,7 @@
X  *                   Parallel port probing routines                        *
X  ***************************************************************************/
X 
-#ifndef MODULE
-/*
- * Command line parameters (for built-in driver):
- *
- * Syntax:  imm=base[,mode[,use_sg]]
- *
- * For example:  imm=0x378   or   imm=0x378,0,3
- *
- */
-
-void imm_setup(char *str, int *ints)
-{
-    static int x = 0;
-
-    if (x == 0) {		/* Disable ALL known ports */
-	int i;
-
-	for (i = 0; i < NO_HOSTS; i++)
-	    parbus_base[i] = 0x0000;
-    }
-    switch (ints[0]) {
-    case 3:
-	imm_sg = ints[3];
-    case 2:
-	imm_hosts[x].mode = ints[2];
-	parbus_base[x] = ints[1];
-	break;
-    default:
-	printk("IMM: I only use between 2 to 3 parameters.\n");
-	break;
-    }
-    x++;
-}
-#else
+#ifdef MODULE
X Scsi_Host_Template driver_template = IMM;
X #include  "scsi_module.c"
X #endif
@@ -162,100 +128,95 @@
X     try_again = 0;
X 
X     if (!pb) {
-        printk("imm: parport reports no devices.\n");
-        return 0;
+	printk("imm: parport reports no devices.\n");
+	return 0;
X     }
-
X   retry_entry:
X     for (i = 0; pb; i++, pb = pb->next) {
-        int modes, ppb;
+	int modes, ppb;
X 
-        imm_hosts[i].dev =
-            parport_register_device(pb, "imm", NULL, imm_wakeup,
-                         NULL, 0, (void *) &imm_hosts[i]);
+	imm_hosts[i].dev =
+	    parport_register_device(pb, "imm", NULL, imm_wakeup,
+				    NULL, 0, (void *) &imm_hosts[i]);
X 
X 	if (!imm_hosts[i].dev)
-		continue;
+	    continue;
X 
-        /* Claim the bus so it remembers what we do to the control
-         * registers. [ CTR and ECP ]
-         */
-	if (imm_pb_claim(i))
-	{
+	/* Claim the bus so it remembers what we do to the control
+	 * registers. [ CTR and ECP ]
+	 */
+	if (imm_pb_claim(i)) {
X 	    unsigned long now = jiffies;
-	    while (imm_hosts[i].p_busy)
-	    {
+	    while (imm_hosts[i].p_busy) {
X 		schedule();	/* We are safe to schedule here */
-		if (time_after(jiffies,now + 3*HZ))
-		{
+		if (time_after(jiffies, now + 3 * HZ)) {
X 		    printk(KERN_ERR "imm%d: failed to claim parport because a "
-			   "pardevice is owning the port for too longtime!\n",
+		      "pardevice is owning the port for too longtime!\n",
X 			   i);
X 		    return 0;
X 		}
X 	    }
X 	}
+	ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base;
+	w_ctr(ppb, 0x0c);
+	modes = imm_hosts[i].dev->port->modes;
X 
-        ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base;
-        w_ctr(ppb, 0x0c);
-        modes = imm_hosts[i].dev->port->modes;
-
-        /* Mode detection works up the chain of speed
-         * This avoids a nasty if-then-else-if-... tree
-         */
-        imm_hosts[i].mode = IMM_NIBBLE;
-
-        if (modes & PARPORT_MODE_PCPS2)
-            imm_hosts[i].mode = IMM_PS2;
-
-        if (modes & PARPORT_MODE_PCECPPS2) {
-            w_ecr(ppb, 0x20);
-            imm_hosts[i].mode = IMM_PS2;
-        }
-        if (modes & PARPORT_MODE_PCECPEPP)
-            w_ecr(ppb, 0x80);
-
-        /* Done configuration */
-        imm_pb_release(i);
-
-        if (imm_init(i)) {
-            parport_unregister_device(imm_hosts[i].dev);
-            continue;
-        }
-        /* now the glue ... */
-        switch (imm_hosts[i].mode) {
-        case IMM_NIBBLE:
-            ports = 3;
-            break;
-        case IMM_PS2:
-            ports = 3;
-            break;
-        case IMM_EPP_8:
-        case IMM_EPP_16:
-        case IMM_EPP_32:
-            ports = 8;
-            break;
-        default:                /* Never gets here */
-            continue;
-        }
-
-        host->can_queue = IMM_CAN_QUEUE;
-        host->sg_tablesize = imm_sg;
-        hreg = scsi_register(host, 0);
-        hreg->io_port = pb->base;
-        hreg->n_io_port = ports;
-        hreg->dma_channel = -1;
-        hreg->unique_id = i;
-        imm_hosts[i].host = hreg->host_no;
-        nhosts++;
+	/* Mode detection works up the chain of speed
+	 * This avoids a nasty if-then-else-if-... tree
+	 */
+	imm_hosts[i].mode = IMM_NIBBLE;
+
+	if (modes & PARPORT_MODE_PCPS2)
+	    imm_hosts[i].mode = IMM_PS2;
+
+	if (modes & PARPORT_MODE_PCECPPS2) {
+	    w_ecr(ppb, 0x20);
+	    imm_hosts[i].mode = IMM_PS2;
+	}
+	if (modes & PARPORT_MODE_PCECPEPP)
+	    w_ecr(ppb, 0x80);
+
+	/* Done configuration */
+	imm_pb_release(i);
+
+	if (imm_init(i)) {
+	    parport_unregister_device(imm_hosts[i].dev);
+	    continue;
+	}
+	/* now the glue ... */
+	switch (imm_hosts[i].mode) {
+	case IMM_NIBBLE:
+	    ports = 3;
+	    break;
+	case IMM_PS2:
+	    ports = 3;
+	    break;
+	case IMM_EPP_8:
+	case IMM_EPP_16:
+	case IMM_EPP_32:
+	    ports = 8;
+	    break;
+	default:		/* Never gets here */
+	    continue;
+	}
+
+	host->can_queue = IMM_CAN_QUEUE;
+	host->sg_tablesize = imm_sg;
+	hreg = scsi_register(host, 0);
+	hreg->io_port = pb->base;
+	hreg->n_io_port = ports;
+	hreg->dma_channel = -1;
+	hreg->unique_id = i;
+	imm_hosts[i].host = hreg->host_no;
+	nhosts++;
X     }
X     if (nhosts == 0) {
-        if (try_again == 1)
-            return 0;
-        try_again = 1;
-        goto retry_entry;
+	if (try_again == 1)
+	    return 0;
+	try_again = 1;
+	goto retry_entry;
X     } else
-        return 1;               /* return number of hosts detected */
+	return 1;		/* return number of hosts detected */
X }
X 
X /* This is to give the imm driver a way to modify the timings (and other
@@ -265,22 +226,11 @@
X  * testing...
X  * Also gives a method to use a script to obtain optimum timings (TODO)
X  */
-
-static inline int imm_strncmp(const char *a, const char *b, int len)
-{
-    int loop;
-    for (loop = 0; loop < len; loop++)
-	if (a[loop] != b[loop])
-	    return 1;
-
-    return 0;
-}
-
X static inline int imm_proc_write(int hostno, char *buffer, int length)
X {
X     unsigned long x;
X 
-    if ((length > 5) && (imm_strncmp(buffer, "mode=", 5) == 0)) {
+    if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
X 	x = simple_strtoul(buffer + 5, NULL, 0);
X 	imm_hosts[hostno].mode = x;
X 	return length;
@@ -445,42 +395,34 @@
X     int i;
X 
X     if ((r_ecr(ppb) & 0xe0) != 0x80)
-        return;
+	return;
X 
X     for (i = 0; i < 100; i++) {
-        if (r_ecr(ppb) & 0x01)
-            return;
-        udelay(5);
+	if (r_ecr(ppb) & 0x01)
+	    return;
+	udelay(5);
X     }
X     printk("imm: ECP sync failed as data still present in FIFO.\n");
X }
X 
-static inline int imm_byte_out(unsigned short base, const char *buffer, int len)
+static int imm_byte_out(unsigned short base, const char *buffer, int len)
X {
X     int i;
X 
-    w_ctr(base, 0x4);		/* aimmrently a sane mode */
+    w_ctr(base, 0x4);		/* apparently a sane mode */
X     for (i = len >> 1; i; i--) {
X 	w_dtr(base, *buffer++);
X 	w_ctr(base, 0x5);	/* Drop STROBE low */
X 	w_dtr(base, *buffer++);
X 	w_ctr(base, 0x0);	/* STROBE high + INIT low */
X     }
-    w_ctr(base, 0x4);		/* aimmrently a sane mode */
+    w_ctr(base, 0x4);		/* apparently a sane mode */
X     return 1;			/* All went well - we hope! */
X }
X 
-static inline int imm_epp_out(unsigned short base, char *buffer, int len)
+static int imm_nibble_in(unsigned short base, char *buffer, int len)
X {
-    int i;
-    for (i = len; i; i--)
-	w_epp(base, *buffer++);
-    return 1;
-}
-
-static inline int imm_nibble_in(unsigned short base, char *buffer, int len)
-{
-    unsigned char h, l;
+    unsigned char l;
X     int i;
X 
X     /*
@@ -489,16 +431,15 @@
X     w_ctr(base, 0x4);
X     for (i = len; i; i--) {
X 	w_ctr(base, 0x6);
-	l = r_str(base);
+	l = (r_str(base) & 0xf0) >> 4;
X 	w_ctr(base, 0x5);
-	h = r_str(base);
+	*buffer++ = (r_str(base) & 0xf0) | l;
X 	w_ctr(base, 0x4);
-	*buffer++ = (h & 0xf0) | ((l & 0xf0) >> 4);
X     }
X     return 1;			/* All went well - we hope! */
X }
X 
-static inline int imm_byte_in(unsigned short base, char *buffer, int len)
+static int imm_byte_in(unsigned short base, char *buffer, int len)
X {
X     int i;
X 
@@ -514,14 +455,6 @@
X     return 1;			/* All went well - we hope! */
X }
X 
-static inline int imm_epp_in(unsigned short base, char *buffer, int len)
-{
-    int i;
-    for (i = len; i; i--)
-	*buffer++ = r_epp(base);
-    return 1;
-}
-
X static int imm_out(int host_no, char *buffer, int len)
X {
X     int r;
@@ -543,11 +476,21 @@
X     case IMM_EPP_32:
X     case IMM_EPP_16:
X     case IMM_EPP_8:
-        epp_reset(ppb);
-        w_ctr(ppb, 0x4);
-	r = imm_epp_out(ppb, buffer, len);
-        w_ctr(ppb, 0xc);
-        ecp_sync(ppb);
+	epp_reset(ppb);
+	w_ctr(ppb, 0x4);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+	if (!(((long) buffer | len) & 0x01))
+	    outsw(ppb + 4, buffer, len >> 1);
+#else
+	if (!(((long) buffer | len) & 0x03))
+	    outsl(ppb + 4, buffer, len >> 2);
+#endif
+	else
+	    outsb(ppb + 4, buffer, len);
+	w_ctr(ppb, 0xc);
+	r = !(r_str(ppb) & 0x01);
+	w_ctr(ppb, 0xc);
+	ecp_sync(ppb);
X 	break;
X 
X     case IMM_NIBBLE:
@@ -595,11 +538,21 @@
X     case IMM_EPP_32:
X     case IMM_EPP_16:
X     case IMM_EPP_8:
-        epp_reset(ppb);
-        w_ctr(ppb, 0x24);
-	r = imm_epp_in(ppb, buffer, len);
-        w_ctr(ppb, 0x2c);
-        ecp_sync(ppb);
+	epp_reset(ppb);
+	w_ctr(ppb, 0x24);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+	if (!(((long) buffer | len) & 0x01))
+	    insw(ppb + 4, buffer, len >> 1);
+#else
+	if (!(((long) buffer | len) & 0x03))
+	    insl(ppb + 4, buffer, len >> 2);
+#endif
+	else
+	    insb(ppb + 4, buffer, len);
+	w_ctr(ppb, 0x2c);
+	r = !(r_str(ppb) & 0x01);
+	w_ctr(ppb, 0x2c);
+	ecp_sync(ppb);
X 	break;
X 
X     default:
@@ -756,8 +709,8 @@
X 
X #if defined(CONFIG_PARPORT) || defined(CONFIG_PARPORT_MODULE)
X     if (imm_pb_claim(host_no))
-        while (imm_hosts[host_no].p_busy)
-            schedule();         /* We can safe schedule here */
+	while (imm_hosts[host_no].p_busy)
+	    schedule();		/* We can safe schedule here */
X #endif
X     retv = imm_connect(host_no, 0);
X 
@@ -770,7 +723,6 @@
X 	imm_pb_release(host_no);
X 	return retv;
X     }
-
X     imm_pb_release(host_no);
X     return 1;
X }
@@ -831,7 +783,7 @@
X 	 * If we have been running for more than a full timer tick
X 	 * then take a rest.
X 	 */
-	if (time_after(jiffies,start_jiffies + 1))
+	if (time_after(jiffies, start_jiffies + 1))
X 	    return 0;
X 
X 	/*
@@ -1173,6 +1125,7 @@
X 
X int imm_abort(Scsi_Cmnd * cmd)
X {
+    int host_no = cmd->host->unique_id;
X     /*
X      * There is no method for aborting commands since Iomega
X      * have tied the SCSI_MESSAGE line high in the interface
@@ -1181,12 +1134,11 @@
X     switch (cmd->SCp.phase) {
X     case 0:			/* Do not have access to parport */
X     case 1:			/* Have not connected to interface */
-	cmd->result = DID_ABORT;
-	cmd->done(cmd);
-	return SCSI_ABORT_SUCCESS;
+	imm_hosts[host_no].cur_cmd = NULL;	/* Forget the problem */
+	return SUCCESS;
X 	break;
X     default:			/* SCSI command sent, can not abort */
-	return SCSI_ABORT_BUSY;
+	return FAILED;
X 	break;
X     }
X }
@@ -1203,46 +1155,20 @@
X     w_ctr(base, 0x04);
X }
X 
-int imm_reset(Scsi_Cmnd * cmd, unsigned int x)
+int imm_reset(Scsi_Cmnd * cmd)
X {
X     int host_no = cmd->host->unique_id;
X 
-    /*
-     * PHASE1:
-     * Bring the interface crashing down on whatever is running
-     * hopefully this will kill the request.
-     * Bring back up the interface, reset the drive (and anything
-     * attached for that manner)
-     */
-    if (cmd)
-	if (cmd->SCp.phase)
-	    imm_disconnect(cmd->host->unique_id);
+    if (cmd->SCp.phase)
+	imm_disconnect(host_no);
+    imm_hosts[host_no].cur_cmd = NULL;	/* Forget the problem */
X 
X     imm_connect(host_no, CONNECT_NORMAL);
X     imm_reset_pulse(IMM_BASE(host_no));
-    udelay(1000);		/* delay for devices to settle down */
+    udelay(1000);		/* device settle delay */
X     imm_disconnect(host_no);
-    udelay(1000);		/* Additional delay to allow devices to settle down */
-
-    /*
-     * PHASE2:
-     * Sanity check for the sake of mid-level driver
-     */
-    if (!cmd) {
-	printk("imm bus reset called for invalid command.\n");
-	return SCSI_RESET_NOT_RUNNING;
-    }
-    /*
-     * PHASE3:
-     * Flag the current command as having died due to reset
-     */
-    imm_connect(host_no, CONNECT_NORMAL);
-    imm_fail(host_no, DID_RESET);
-
-    /* Since the command was already on the timer queue imm_interrupt
-     * will be called shortly.
-     */
-    return SCSI_RESET_PENDING;
+    udelay(1000);		/* device settle delay */
+    return SUCCESS;
X }
X 
X static int device_check(int host_no)
@@ -1257,79 +1183,78 @@
X 
X     old_mode = imm_hosts[host_no].mode;
X     for (loop = 0; loop < 8; loop++) {
-        /* Attempt to use EPP for Test Unit Ready */
-        if ((ppb & 0x0007) == 0x0000)
-            imm_hosts[host_no].mode = IMM_EPP_32;
+	/* Attempt to use EPP for Test Unit Ready */
+	if ((ppb & 0x0007) == 0x0000)
+	    imm_hosts[host_no].mode = IMM_EPP_32;
X 
X       second_pass:
-        imm_connect(host_no, CONNECT_EPP_MAYBE);
-        /* Select SCSI device */
-        if (!imm_select(host_no, loop)) {
-            imm_disconnect(host_no);
-            continue;
-        }
-        printk("imm: Found device at ID %i, Attempting to use %s\n", loop,
-               IMM_MODE_STRING[imm_hosts[host_no].mode]);
-
-        /* Send SCSI command */
-        status = 1;
-        w_ctr(ppb, 0x0c);
-        for (l = 0; (l < 3) && (status); l++)
-            status = imm_out(host_no, &cmd[l<<1], 2);
-
-        if (!status) {
-            imm_disconnect(host_no);
-            imm_connect(host_no, CONNECT_EPP_MAYBE);
-            w_dtr(ppb, 0x40);
-            w_ctr(ppb, 0x08);
-            udelay(30);
-            w_ctr(ppb, 0x0c);
-            udelay(1000);
-            imm_disconnect(host_no);
-            udelay(1000);
-            if (imm_hosts[host_no].mode == IMM_EPP_32) {
-                imm_hosts[host_no].mode = old_mode;
-                goto second_pass;
-            }
-            printk("imm: Unable to establish communication, aborting driver load.\n");
-            return 1;
-        }
-        w_ctr(ppb, 0x0c);
-
-        k = 1000000;            /* 1 Second */
-        do {
-            l = r_str(ppb);
-            k--;
-            udelay(1);
-        } while (!(l & 0x80) && (k));
-
-        l &= 0xb8;
-
-        if (l != 0xb8) {
-            imm_disconnect(host_no);
-            imm_connect(host_no, CONNECT_EPP_MAYBE);
+	imm_connect(host_no, CONNECT_EPP_MAYBE);
+	/* Select SCSI device */
+	if (!imm_select(host_no, loop)) {
+	    imm_disconnect(host_no);
+	    continue;
+	}
+	printk("imm: Found device at ID %i, Attempting to use %s\n", loop,
+	       IMM_MODE_STRING[imm_hosts[host_no].mode]);
+
+	/* Send SCSI command */
+	status = 1;
+	w_ctr(ppb, 0x0c);
+	for (l = 0; (l < 3) && (status); l++)
+	    status = imm_out(host_no, &cmd[l << 1], 2);
+
+	if (!status) {
+	    imm_disconnect(host_no);
+	    imm_connect(host_no, CONNECT_EPP_MAYBE);
+	    w_dtr(ppb, 0x40);
+	    w_ctr(ppb, 0x08);
+	    udelay(30);
+	    w_ctr(ppb, 0x0c);
+	    udelay(1000);
+	    imm_disconnect(host_no);
+	    udelay(1000);
+	    if (imm_hosts[host_no].mode == IMM_EPP_32) {
+		imm_hosts[host_no].mode = old_mode;
+		goto second_pass;
+	    }
+	    printk("imm: Unable to establish communication, aborting driver load.\n");
+	    return 1;
+	}
+	w_ctr(ppb, 0x0c);
+
+	k = 1000000;		/* 1 Second */
+	do {
+	    l = r_str(ppb);
+	    k--;
+	    udelay(1);
+	} while (!(l & 0x80) && (k));
+
+	l &= 0xb8;
+
+	if (l != 0xb8) {
+	    imm_disconnect(host_no);
+	    imm_connect(host_no, CONNECT_EPP_MAYBE);
X 	    imm_reset_pulse(IMM_BASE(host_no));
-            udelay(1000);
-            imm_disconnect(host_no);
-            udelay(1000);
-            if (imm_hosts[host_no].mode == IMM_EPP_32) {
-                imm_hosts[host_no].mode = old_mode;
-                goto second_pass;
-            }
-            printk("imm: Unable to establish communication, aborting driver load.\n");
-            return 1;
-        }
-        imm_disconnect(host_no);
-        printk("imm: Communication established with ID %i using %s\n", loop,
-               IMM_MODE_STRING[imm_hosts[host_no].mode]);
-        imm_connect(host_no, CONNECT_EPP_MAYBE);
+	    udelay(1000);
+	    imm_disconnect(host_no);
+	    udelay(1000);
+	    if (imm_hosts[host_no].mode == IMM_EPP_32) {
+		imm_hosts[host_no].mode = old_mode;
+		goto second_pass;
+	    }
+	    printk("imm: Unable to establish communication, aborting driver load.\n");
+	    return 1;
+	}
+	imm_disconnect(host_no);
+	printk("imm: Communication established with ID %i using %s\n", loop,
+	       IMM_MODE_STRING[imm_hosts[host_no].mode]);
+	imm_connect(host_no, CONNECT_EPP_MAYBE);
X 	imm_reset_pulse(IMM_BASE(host_no));
-        udelay(1000);
-        imm_disconnect(host_no);
-        udelay(1000);
-        return 0;
+	udelay(1000);
+	imm_disconnect(host_no);
+	udelay(1000);
+	return 0;
X     }
X     printk("imm: No devices found, aborting driver load.\n");
X     return 1;
X }
-
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/imm.h linux/drivers/scsi/imm.h
--- v2.2.0-pre3/linux/drivers/scsi/imm.h	Thu Sep 17 17:53:36 1998
+++ linux/drivers/scsi/imm.h	Sat Jan  2 10:21:06 1999
@@ -1,7 +1,8 @@
+
X /*  Driver for the Iomega MatchMaker parallel port SCSI HBA embedded in 
X  * the Iomega ZIP Plus drive
X  * 
- * (c) 1998     David Campbell	   camp...@torque.net
+ * (c) 1998     David Campbell     camp...@torque.net
X  *
X  * Please note that I live in Perth, Western Australia. GMT+0800
X  */
@@ -9,13 +10,13 @@
X #ifndef _IMM_H
X #define _IMM_H
X 
-#define   IMM_VERSION   "2.00"
+#define   IMM_VERSION   "2.03 (for Linux 2.0.0)"
X 
X /* 
X  * 10 Apr 1998 (Good Friday) - Received EN144302 by email from Iomega.
X  * Scarry thing is the level of support from one of their managers.
X  * The onus is now on us (the developers) to shut up and start coding.
- *						11Apr98	[ 0.10 ]
+ *                                              11Apr98 [ 0.10 ]
X  *
X  * --- SNIP ---
X  *
@@ -24,35 +25,40 @@
X  * Removing "Phase" debug messages.
X  *
X  * PS: Took four hours of coding after I bought a drive.
- *	ANZAC Day (Aus "War Veterans Holiday")	25Apr98 [ 0.14 ]
+ *      ANZAC Day (Aus "War Veterans Holiday")  25Apr98 [ 0.14 ]
X  *
X  * Ten minutes later after a few fixes.... (LITERALLY!!!)
X  * Have mounted disk, copied file, dismounted disk, remount disk, diff file
X  *                    -----  It actually works!!! -----
- *						25Apr98 [ 0.15 ]
+ *                                              25Apr98 [ 0.15 ]
X  *
X  * Twenty minutes of mucking around, rearanged the IEEE negotiate mechanism.
X  * Now have byte mode working (only EPP and ECP to go now... :=)
- *						26Apr98 [ 0.16 ]
+ *                                              26Apr98 [ 0.16 ]
X  *
X  * Thirty minutes of further coding results in EPP working on my machine.
- *						27Apr98 [ 0.17 ]
+ *                                              27Apr98 [ 0.17 ]
X  *
X  * Due to work commitments and inability to get a "true" ECP mode functioning
X  * I have decided to code the parport support into imm.
- *						09Jun98 [ 0.18 ]
+ *                                              09Jun98 [ 0.18 ]
X  *
X  * Driver is now out of beta testing.
X  * Support for parport has been added.
X  * Now distributed with the ppa driver.
- *						12Jun98 [ 2.00 ]
+ *                                              12Jun98 [ 2.00 ]
X  *
X  * Err.. It appears that imm-2.00 was broken....
- *						18Jun98 [ 2.01 ]
+ *                                              18Jun98 [ 2.01 ]
X  *
X  * Patch applied to sync this against the Linux 2.1.x kernel code
X  * Included qboot_zip.sh
- *						21Jun98 [ 2.02 ]
+ *                                              21Jun98 [ 2.02 ]
+ *
+ * Other clean ups include the follow changes:
+ *    CONFIG_SCSI_PPA_HAVE_PEDANTIC => CONFIG_SCSI_IZIP_EPP16
+ *    added CONFIG_SCSI_IZIP_SLOW_CTR option
+ *                                                      [2.03]
X  */
X /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
X 
@@ -92,7 +98,11 @@
X     "PS/2",
X     "EPP 8 bit",
X     "EPP 16 bit",
+#ifdef CONFIG_SCSI_IZIP_EPP16
+    "EPP 16 bit",
+#else
X     "EPP 32 bit",
+#endif
X     "Unknown"};
X 
X /* This is a global option */
@@ -110,21 +120,24 @@
X #define CONNECT_EPP_MAYBE 1
X #define CONNECT_NORMAL  0
X 
-#define inb_x inb
-#define r_dtr(x)        (unsigned char)inb_x((x))
-#define r_str(x)        (unsigned char)inb_x((x)+1)
-#define r_ctr(x)        (unsigned char)inb_x((x)+2)
-#define r_epp(x)        (unsigned char)inb_x((x)+4)
-#define r_fifo(x)       (unsigned char)inb_x((x)+0x400)
-#define r_ecr(x)        (unsigned char)inb_x((x)+0x402)
-
-#define outb_x outb
-#define w_dtr(x,y)      outb_x(y, (x))
-#define w_str(x,y)      outb_x(y, (x)+1)
-#define w_ctr(x,y)      outb_x(y, (x)+2)
-#define w_epp(x,y)      outb_x(y, (x)+4)
-#define w_fifo(x,y)     outb_x(y, (x)+0x400)
-#define w_ecr(x,y)      outb_x(y, (x)+0x402)
+#define r_dtr(x)        (unsigned char)inb((x))
+#define r_str(x)        (unsigned char)inb((x)+1)
+#define r_ctr(x)        (unsigned char)inb((x)+2)
+#define r_epp(x)        (unsigned char)inb((x)+4)
+#define r_fifo(x)       (unsigned char)inb((x)+0x400)
+#define r_ecr(x)        (unsigned char)inb((x)+0x402)
+
+#define w_dtr(x,y)      outb(y, (x))
+#define w_str(x,y)      outb(y, (x)+1)
+#define w_epp(x,y)      outb(y, (x)+4)
+#define w_fifo(x,y)     outb(y, (x)+0x400)
+#define w_ecr(x,y)      outb(y, (x)+0x402)
+
+#ifdef CONFIG_SCSI_IZIP_SLOW_CTR
+#define w_ctr(x,y)      outb_p(y, (x)+2)
+#else
+#define w_ctr(x,y)      outb(y, (x)+2)
+#endif
X 
X static int imm_engine(imm_struct *, Scsi_Cmnd *);
X static int imm_in(int, char *, int);
@@ -144,23 +157,25 @@
X int imm_command(Scsi_Cmnd *);
X int imm_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
X int imm_abort(Scsi_Cmnd *);
-int imm_reset(Scsi_Cmnd *, unsigned int);
+int imm_reset(Scsi_Cmnd *);
X int imm_proc_info(char *, char **, off_t, int, int, int);
X int imm_biosparam(Disk *, kdev_t, int *);
X 
-#define IMM {	proc_dir:		&proc_scsi_imm,			\
-		proc_info:		imm_proc_info,			\
-		name:			"Iomega ZIP Plus drive",	\
-		detect:			imm_detect,			\
-		release:		imm_release,			\
-		command:		imm_command,			\
-		queuecommand:		imm_queuecommand,		\
-		abort:			imm_abort,			\
-		reset:			imm_reset,			\
-		bios_param:		imm_biosparam,			\
-		this_id:		7,				\
-		sg_tablesize:		SG_ALL,				\
-		cmd_per_lun:		1,				\
-		use_clustering:		ENABLE_CLUSTERING		\
+#define IMM {	proc_dir:			&proc_scsi_imm,		\
+		proc_info:			imm_proc_info,		\
+		name:				"Iomega VPI2 (imm) interface",\
+		detect:				imm_detect,		\
+		release:			imm_release,		\
+		command:			imm_command,		\
+		queuecommand:			imm_queuecommand,	\
+                eh_abort_handler:               imm_abort,              \
+                eh_device_reset_handler:        NULL,                   \
+                eh_bus_reset_handler:           imm_reset,              \
+                eh_host_reset_handler:          imm_reset,              \
+		bios_param:		        imm_biosparam,		\
+		this_id:			7,			\
+		sg_tablesize:			SG_ALL,			\
+		cmd_per_lun:			1,			\
+		use_clustering:			ENABLE_CLUSTERING	\
X }
X #endif				/* _IMM_H */
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.2.0-pre3/linux/drivers/scsi/ppa.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/scsi/ppa.c	Sat Jan  2 10:21:06 1999
@@ -7,8 +7,7 @@
X  * under the terms of the GNU Public License.
X  * 
X  * Current Maintainer: David Campbell (Perth, Western Australia, GMT+0800)
- *                     camp...@gear.torque.net
- *                     dcam...@p01.as17.honeywell.com.au
+ *                     camp...@torque.net
X  */
X 
X #include <linux/config.h>
@@ -68,7 +67,6 @@
X 	printk("ppa: bug in ppa_wakeup\n");
X 	return;
X     }
-
X     ppa_dev->p_busy = 0;
X     ppa_dev->base = ppa_dev->dev->port->base;
X     if (ppa_dev->cur_cmd)
@@ -91,7 +89,6 @@
X 	ppa_hosts[host_no].p_busy = 1;
X 	return 1;
X     }
-
X     if (ppa_hosts[host_no].cur_cmd)
X 	ppa_hosts[host_no].cur_cmd->SCp.phase++;
X     return 0;
@@ -133,30 +130,26 @@
X 
X 	ppa_hosts[i].dev =
X 	    parport_register_device(pb, "ppa", NULL, ppa_wakeup,
-			 NULL, 0, (void *) &ppa_hosts[i]);
+				    NULL, 0, (void *) &ppa_hosts[i]);
X 
X 	if (!ppa_hosts[i].dev)
-		continue;
+	    continue;
X 
X 	/* Claim the bus so it remembers what we do to the control
X 	 * registers. [ CTR and ECP ]
X 	 */
-	if (ppa_pb_claim(i))
-	{
+	if (ppa_pb_claim(i)) {
X 	    unsigned long now = jiffies;
-	    while (ppa_hosts[i].p_busy)
-	    {
+	    while (ppa_hosts[i].p_busy) {
X 		schedule();	/* We are safe to schedule here */
-		if (time_after(jiffies,now + 3*HZ))
-		{
+		if (time_after(jiffies, now + 3 * HZ)) {
X 		    printk(KERN_ERR "ppa%d: failed to claim parport because a "
-			   "pardevice is owning the port for too longtime!\n",
+		      "pardevice is owning the port for too longtime!\n",
X 			   i);
X 		    return 0;
X 		}
X 	    }
X 	}
-
X 	ppb = PPA_BASE(i) = ppa_hosts[i].dev->port->base;
X 	w_ctr(ppb, 0x0c);
X 	modes = ppa_hosts[i].dev->port->modes;
@@ -211,8 +204,15 @@
X 	nhosts++;
X     }
X     if (nhosts == 0) {
-	if (try_again == 1)
+	if (try_again == 1) {
+	    printk("WARNING - no ppa compatible devices found.\n");
+	    printk("  As of 31/Aug/1998 Iomega started shipping parallel\n");
+	    printk("  port ZIP drives with a different interface which is\n");
+	    printk("  supported by the imm (ZIP Plus) driver. If the\n");
+	    printk("  cable is marked with \"AutoDetect\", this is what has\n");
+	    printk("  happened.\n");
X 	    return 0;
+	}
X 	try_again = 1;
X 	goto retry_entry;
X     } else
@@ -227,21 +227,11 @@
X  * Also gives a method to use a script to obtain optimum timings (TODO)
X  */
X 
-static inline int ppa_strncmp(const char *a, const char *b, int len)
-{
-    int loop;
-    for (loop = 0; loop < len; loop++)
-	if (a[loop] != b[loop])
-	    return 1;
-
-    return 0;
-}
-
X static inline int ppa_proc_write(int hostno, char *buffer, int length)
X {
X     unsigned long x;
X 
-    if ((length > 5) && (ppa_strncmp(buffer, "mode=", 5) == 0)) {
+    if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
X 	x = simple_strtoul(buffer + 5, NULL, 0);
X 	ppa_hosts[hostno].mode = x;
X 	return length;
@@ -360,245 +350,42 @@
X     printk("ppa: ECP sync failed as data still present in FIFO.\n");
X }
X 
-/*
- * Here is the asm code for the SPP/PS2 protocols for the i386.
- * This has been optimised for speed on 386/486 machines. There will
- * be very little improvement on the current 586+ machines as it is the
- * IO statements which will limit throughput.
- */
-#ifdef __i386__
-#define BYTE_OUT(reg) \
-	"	movb " #reg ",%%al\n" \
-	"	outb %%al,(%%dx)\n" \
-	"	addl $2,%%edx\n" \
-	"	movb $0x0e,%%al\n" \
-	"	outb %%al,(%%dx)\n" \
-	"	movb $0x0c,%%al\n" \
-	"	outb %%al,(%%dx)\n" \
-	"	subl $2,%%edx\n"
-
-static inline int ppa_byte_out(unsigned short base, char *buffer, unsigned int len)
+static int ppa_byte_out(unsigned short base, const char *buffer, int len)
X {
-    /*
-     * %eax scratch
-     * %ebx Data to transfer
-     * %ecx Counter (Don't touch!!)
-     * %edx Port
-     * %esi Source buffer (mem pointer)
-     *
-     * In case you are wondering what the last line of the asm does...
-     * <output allocation> : <input allocation> : <trashed registers>
-     */
-    register int d0;
-
-    asm("shr $2,%%ecx\n" \
-	"	jz .no_more_bulk_bo\n" \
-	"	.p2align 4,,7\n" \
-	".loop_bulk_bo:\n" \
-	"	movl (%%esi),%%ebx\n" \
-	BYTE_OUT(%%bl) \
-	BYTE_OUT(%%bh) \
-	"	rorl $16,%%ebx\n" \
-	BYTE_OUT(%%bl) \
-	BYTE_OUT(%%bh) \
-	"	addl $4,%%esi\n" \
-	"	loop .loop_bulk_bo\n" \
-	"	.p2align 4,,7\n" \
-	".no_more_bulk_bo:" \
-  : "=S"(buffer), "=c"(d0)
-  : "1"(len), "d"(base), "0"(buffer)
-  : "eax", "ebx");
-
-    asm("andl $3,%%ecx\n" \
-	"	jz .no_more_loose_bo\n" \
-	"	.p2align 4,,7\n" \
-	".loop_loose_bo:\n" \
-	BYTE_OUT((%%esi)) \
-	"	incl %%esi\n" \
-	"	loop .loop_loose_bo\n" \
-	".no_more_loose_bo:\n" \
-  : "=c"(d0)
-  : "0"(len), "d"(base), "S"(buffer)
-  : "eax", "ebx");
-    return 1;			/* All went well - we hope! */
-}
-
-#define BYTE_IN(reg) \
-	"	inb (%%dx),%%al\n" \
-	"	movb %%al," #reg "\n" \
-	"	addl $2,%%edx\n" \
-	"	movb $0x27,%%al\n" \
-	"	outb %%al,(%%dx)\n" \
-	"	movb $0x25,%%al\n" \
-	"	outb %%al,(%%dx)\n" \
-	"	subl $2,%%edx\n"
-
-static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
-{
-    /*
-     * %eax scratch
-     * %ebx Data to transfer
-     * %ecx Counter (Don't touch!!)
-     * %edx Port
-     * %esi Source buffer (mem pointer)
-     *
-     * In case you are wondering what the last line of the asm does...
-     * <output allocation> : <input allocation> : <trashed registers>
-     */
-    register int d0;
-
-    asm("shr $2,%%ecx\n" \
-	"	jz .no_more_bulk_bi\n" \
-	"	.p2align 4,,7\n" \
-	".loop_bulk_bi:\n" \
-	BYTE_IN(%%bl) \
-	BYTE_IN(%%bh) \
-	"	rorl $16,%%ebx\n" \
-	BYTE_IN(%%bl) \
-	BYTE_IN(%%bh) \
-	"	rorl $16,%%ebx\n" \
-	"	movl %%ebx,(%%esi)\n" \
-	"	addl $4,%%esi\n" \
-	"	loop .loop_bulk_bi\n" \
-	"	.p2align 4,,7\n" \
-	".no_more_bulk_bi:" \
-  : "=S"(buffer), "=c"(d0)
-  : "1"(len), "d"(base), "0"(buffer)
-  : "eax", "ebx");
-
-    asm("andl $3,%%ecx\n" \
-	"	jz .no_more_loose_bi\n" \
-	"	.p2align 4,,7\n" \
-	".loop_loose_bi:\n" \
-	BYTE_IN((%%esi)) \
-	"	incl %%esi\n" \
-	"	loop .loop_loose_bi\n" \
-	".no_more_loose_bi:\n" \
-  : "=c"(d0)
-  : "0"(len), "d"(base), "S"(buffer)
-  : "eax", "ebx");
-    return 1;			/* All went well - we hope! */
-}
-
-#define NIBBLE_IN(reg) \
-	"	incl %%edx\n" \
-	"	movb $0x04,%%al\n" \
-	"	outb %%al,(%%dx)\n" \
-	"	decl %%edx\n" \
-	"	inb (%%dx),%%al\n" \
-	"	andb $0xf0,%%al\n" \
-	"	movb %%al," #reg "\n" \
-	"	incl %%edx\n" \
-	"	movb $0x06,%%al\n" \
-	"	outb %%al,(%%dx)\n" \
-	"	decl %%edx\n" \
-	"	inb (%%dx),%%al\n" \
-	"	shrb $4,%%al\n" \
-	"	orb %%al," #reg "\n"
-
-static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
-{
-    /*
-     * %eax scratch
-     * %ebx Data to transfer
-     * %ecx Counter (Don't touch!!)
-     * %edx Port
-     * %esi Source buffer (mem pointer)
-     *
-     * In case you are wondering what the last line of the asm does...
-     * <output allocation> : <input allocation> : <trashed registers>
-     */
-    register int d0;
-
-    asm("shr $2,%%ecx\n" \
-	"	jz .no_more_bulk_ni\n" \
-	"	.p2align 4,,7\n" \
-	".loop_bulk_ni:\n" \
-	NIBBLE_IN(%%bl) \
-	NIBBLE_IN(%%bh) \
-	"	rorl $16,%%ebx\n" \
-	NIBBLE_IN(%%bl) \
-	NIBBLE_IN(%%bh) \
-	"	rorl $16,%%ebx\n" \
-	"	movl %%ebx,(%%esi)\n" \
-	"	addl $4,%%esi\n" \
-	"	loop .loop_bulk_ni\n" \
-	"	.p2align 4,,7\n" \
-	".no_more_bulk_ni:" \
-  : "=S"(buffer), "=c"(d0)
-  : "1"(len), "d"(str_p), "0"(buffer)
-  : "eax", "ebx");
-
-    asm("andl $3,%%ecx\n" \
-	"	jz .no_more_loose_ni\n" \
-	"	.p2align 4,,7\n" \
-	".loop_loose_ni:\n" \
-	NIBBLE_IN((%%esi)) \
-	"	incl %%esi\n" \
-	"	loop .loop_loose_ni\n" \
-	".no_more_loose_ni:\n" \
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre4 failed'
fi
echo 'End of  part 1'
echo 'File patch-2.2.0-pre4 is continued in part 2'
echo 2 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 2 of a 5 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre4'
else
echo 'x - continuing with patch-2.2.0-pre4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre4' &&
-  : "=c"(d0)
-  : "0"(len), "d"(str_p), "S"(buffer)
-  : "eax", "ebx");
-    return 1;			/* All went well - we hope! */
-}
-#else				/* Old style C routines */
-
-static inline int ppa_byte_out(unsigned short base, const char *buffer, int len)
-{
-    unsigned short ctr_p = base + 2;
X     int i;
X 
X     for (i = len; i; i--) {
-	outb(*buffer++, base);
-	outb(0xe, ctr_p);
-	outb(0xc, ctr_p);
+	w_dtr(base, *buffer++);
+	w_ctr(base, 0xe);
+	w_ctr(base, 0xc);
X     }
X     return 1;			/* All went well - we hope! */
X }
X 
-static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
+static int ppa_byte_in(unsigned short base, char *buffer, int len)
X {
-    unsigned short ctr_p = base + 2;
X     int i;
X 
X     for (i = len; i; i--) {
-	*buffer++ = inb(base);
-	outb(0x27, ctr_p);
-	outb(0x25, ctr_p);
+	*buffer++ = r_dtr(base);
+	w_ctr(base, 0x27);
+	w_ctr(base, 0x25);
X     }
X     return 1;			/* All went well - we hope! */
X }
X 
-static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
+static int ppa_nibble_in(unsigned short base, char *buffer, int len)
X {
-    unsigned short ctr_p = str_p + 1;
-    unsigned char h, l;
-    int i;
+    for (; len; len--) {
+	unsigned char h;
X 
-    for (i = len; i; i--) {
-	outb(0x4, ctr_p);
-	h = inb(str_p);
-	outb(0x6, ctr_p);
-	l = inb(str_p);
-	*buffer++ = (h & 0xf0) | ((l & 0xf0) >> 4);
+	w_ctr(base, 0x4);
+	h = r_str(base) & 0xf0;
+	w_ctr(base, 0x6);
+	*buffer++ = h | ((r_str(base) & 0xf0) >> 4);
X     }
X     return 1;			/* All went well - we hope! */
X }
-#endif
-
-static inline int ppa_epp_out(unsigned short epp_p, unsigned short str_p, const char *buffer, int len)
-{
-    int i;
-    for (i = len; i; i--) {
-	outb(*buffer++, epp_p);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
-	if (inb(str_p) & 0x01)
-	    return 0;
-#endif
-    }
-    return 1;
-}
X 
X static int ppa_out(int host_no, char *buffer, int len)
X {
@@ -623,16 +410,17 @@
X     case PPA_EPP_8:
X 	epp_reset(ppb);
X 	w_ctr(ppb, 0x4);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
-	r = ppa_epp_out(ppb + 4, ppb + 1, buffer, len);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+	if (!(((long) buffer | len) & 0x01))
+	    outsw(ppb + 4, buffer, len >> 1);
X #else
X 	if (!(((long) buffer | len) & 0x03))
X 	    outsl(ppb + 4, buffer, len >> 2);
+#endif
X 	else
X 	    outsb(ppb + 4, buffer, len);
X 	w_ctr(ppb, 0xc);
X 	r = !(r_str(ppb) & 0x01);
-#endif
X 	w_ctr(ppb, 0xc);
X 	ecp_sync(ppb);
X 	break;
@@ -644,19 +432,6 @@
X     return r;
X }
X 
-static inline int ppa_epp_in(int epp_p, int str_p, char *buffer, int len)
-{
-    int i;
-    for (i = len; i; i--) {
-	*buffer++ = inb(epp_p);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
-	if (inb(str_p) & 0x01)
-	    return 0;
-#endif
-    }
-    return 1;
-}
-
X static int ppa_in(int host_no, char *buffer, int len)
X {
X     int r;
@@ -671,7 +446,7 @@
X     switch (ppa_hosts[host_no].mode) {
X     case PPA_NIBBLE:
X 	/* 4 bit input, with a loop */
-	r = ppa_nibble_in(ppb + 1, buffer, len);
+	r = ppa_nibble_in(ppb, buffer, len);
X 	w_ctr(ppb, 0xc);
X 	break;
X 
@@ -688,16 +463,17 @@
X     case PPA_EPP_8:
X 	epp_reset(ppb);
X 	w_ctr(ppb, 0x24);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
-	r = ppa_epp_in(ppb + 4, ppb + 1, buffer, len);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+	if (!(((long) buffer | len) & 0x01))
+	    insw(ppb + 4, buffer, len >> 1);
X #else
X 	if (!(((long) buffer | len) & 0x03))
X 	    insl(ppb + 4, buffer, len >> 2);
+#endif
X 	else
X 	    insb(ppb + 4, buffer, len);
X 	w_ctr(ppb, 0x2c);
X 	r = !(r_str(ppb) & 0x01);
-#endif
X 	w_ctr(ppb, 0x2c);
X 	ecp_sync(ppb);
X 	break;
@@ -885,7 +661,7 @@
X 	 * If we have been running for more than a full timer tick
X 	 * then take a rest.
X 	 */
-	if (time_after(jiffies,start_jiffies + 1))
+	if (time_after(jiffies, start_jiffies + 1))
X 	    return 0;
X 
X 	if (((r & 0xc0) != 0xc0) || (cmd->SCp.this_residual <= 0)) {
@@ -1059,8 +835,7 @@
X 	    if ((r_str(ppb) & 0x08) == 0x00)
X 		retv--;
X 
-	    if (retv)
-	    {
+	    if (retv) {
X 		if ((jiffies - tmp->jstart) > (1 * HZ)) {
X 		    printk("ppa: Parallel port cable is unplugged!!\n");
X 		    ppa_fail(host_no, DID_BUS_BUSY);
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h
--- v2.2.0-pre3/linux/drivers/scsi/ppa.h	Thu Sep 17 17:53:36 1998
+++ linux/drivers/scsi/ppa.h	Sat Jan  2 10:21:06 1999
@@ -2,15 +2,15 @@
X  * the Iomega ZIP drive
X  * 
X  * (c) 1996     Grant R. Guenther  gr...@torque.net
- *		David Campbell	   camp...@torque.net
+ *              David Campbell     camp...@torque.net
X  *
- *	All comments to David.
+ *      All comments to David.
X  */
X 
X #ifndef _PPA_H
X #define _PPA_H
X 
-#define   PPA_VERSION   "2.01"
+#define   PPA_VERSION   "2.03 (for Linux 2.0.0)"
X 
X /* 
X  * this driver has been hacked by Matteo Frigo (ath...@theory.lcs.mit.edu)
@@ -26,21 +26,31 @@
X  *
X  * Corrected ppa.h for 2.1.x kernels (>=2.1.85)
X  * Modified "Nat Semi Kludge" for extended chipsets
- *							[1.41]
+ *                                                      [1.41]
X  *
X  * Fixed id_probe for EPP 1.9 chipsets (misdetected as EPP 1.7)
- *							[1.42]
+ *                                                      [1.42]
X  *
X  * Development solely for 2.1.x kernels from now on!
- *							[2.00]
+ *                                                      [2.00]
X  *
X  * Hack and slash at the init code (EPP device check routine)
X  * Added INSANE option.
- *							[2.01]
+ *                                                      [2.01]
X  *
X  * Patch applied to sync against the 2.1.x kernel code
X  * Included qboot_zip.sh
- *							[2.02]
+ *                                                      [2.02]
+ *
+ * Cleaned up the mess left by someone else trying to fix the
+ * asm section to keep egcc happy. The asm section no longer
+ * exists, the nibble code is *almost* as fast as the asm code
+ * providing it is compiled with egcc.
+ *
+ * Other clean ups include the follow changes:
+ *    CONFIG_SCSI_PPA_HAVE_PEDANTIC => CONFIG_SCSI_IZIP_EPP16
+ *    added CONFIG_SCSI_IZIP_SLOW_CTR option
+ *                                                      [2.03]
X  */
X /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
X 
@@ -80,7 +90,11 @@
X     "PS/2",
X     "EPP 8 bit",
X     "EPP 16 bit",
+#ifdef CONFIG_SCSI_IZIP_EPP16
+    "EPP 16 bit",
+#else
X     "EPP 32 bit",
+#endif
X     "Unknown"};
X 
X /* This is a global option */
@@ -98,23 +112,6 @@
X #define CONNECT_EPP_MAYBE 1
X #define CONNECT_NORMAL  0
X 
-/* INSANE code */
-#define PPA_INSANE 0
-#if PPA_INSANE > 0
-#define r_dtr(x)        (unsigned char)inb_p((x))
-#define r_str(x)        (unsigned char)inb_p((x)+1)
-#define r_ctr(x)        (unsigned char)inb_p((x)+2)
-#define r_epp(x)        (unsigned char)inb_p((x)+4)
-#define r_fifo(x)       (unsigned char)inb_p((x)+0x400)
-#define r_ecr(x)        (unsigned char)inb_p((x)+0x402)
-
-#define w_dtr(x,y)      outb_p(y, (x))
-#define w_str(x,y)      outb_p(y, (x)+1)
-#define w_ctr(x,y)      outb_p(y, (x)+2)
-#define w_epp(x,y)      outb_p(y, (x)+4)
-#define w_fifo(x,y)     outb_p(y, (x)+0x400)
-#define w_ecr(x,y)      outb_p(y, (x)+0x402)
-#else /* PPA_INSANE */
X #define r_dtr(x)        (unsigned char)inb((x))
X #define r_str(x)        (unsigned char)inb((x)+1)
X #define r_ctr(x)        (unsigned char)inb((x)+2)
@@ -124,11 +121,15 @@
X 
X #define w_dtr(x,y)      outb(y, (x))
X #define w_str(x,y)      outb(y, (x)+1)
-#define w_ctr(x,y)      outb(y, (x)+2)
X #define w_epp(x,y)      outb(y, (x)+4)
X #define w_fifo(x,y)     outb(y, (x)+0x400)
X #define w_ecr(x,y)      outb(y, (x)+0x402)
-#endif	/* PPA_INSANE */
+
+#ifdef CONFIG_SCSI_IZIP_SLOW_CTR
+#define w_ctr(x,y)      outb_p(y, (x)+2)
+#else
+#define w_ctr(x,y)      outb(y, (x)+2)
+#endif
X 
X static int ppa_engine(ppa_struct *, Scsi_Cmnd *);
X static int ppa_in(int, char *, int);
@@ -154,7 +155,7 @@
X 
X #define PPA {	proc_dir:			&proc_scsi_ppa,		\
X 		proc_info:			ppa_proc_info,		\
-		name:				"Iomega parport ZIP drive",\
+		name:				"Iomega VPI0 (ppa) interface",\
X 		detect:				ppa_detect,		\
X 		release:			ppa_release,		\
X 		command:			ppa_command,		\
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c
--- v2.2.0-pre3/linux/drivers/scsi/scsi_debug.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/scsi/scsi_debug.c	Sat Jan  2 10:23:01 1999
@@ -518,10 +518,10 @@
X static void scsi_debug_intr_handle(unsigned long indx)
X {
X     Scsi_Cmnd * SCtmp;
-    int pending;
X     void (*my_done)(Scsi_Cmnd *); 
-    unsigned long flags;
+#ifdef DEBUG
X     int to;
+#endif
X     
X #if 0
X     del_timer(&timeout[indx]);
@@ -565,9 +565,11 @@
X 
X int scsi_debug_abort(Scsi_Cmnd * SCpnt)
X {
+#if 0
X     int j;
X     void (*my_done)(Scsi_Cmnd *);
X     unsigned long flags;
+#endif
X     
X     DEB(printk("scsi_debug_abort\n"));
X #if 0
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- v2.2.0-pre3/linux/drivers/scsi/scsi_proc.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/scsi_proc.c	Sat Jan  2 17:55:06 1999
@@ -307,6 +307,13 @@
X     *size = y; 
X     return;
X }
+
+#else
+
+void proc_print_scsidevice(Scsi_Device *scd, char *buffer, int *size, int len)
+{
+}
+
X #endif /* CONFIG_PROC_FS */
X 
X /*
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.2.0-pre3/linux/drivers/scsi/scsi_syms.c	Thu May  7 22:51:51 1998
+++ linux/drivers/scsi/scsi_syms.c	Sat Jan  2 17:55:06 1999
@@ -72,9 +72,7 @@
X 
X EXPORT_SYMBOL(scsi_sleep);
X 
-#if defined(CONFIG_PROC_FS)
X EXPORT_SYMBOL(proc_print_scsidevice);
-#endif
X /*
X  * These are here only while I debug the rest of the scsi stuff.
X  */
diff -u --recursive --new-file v2.2.0-pre3/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.2.0-pre3/linux/drivers/sound/soundcard.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/sound/soundcard.c	Sat Jan  2 17:55:06 1999
@@ -909,8 +909,10 @@
X 	{
X 		return;
X 	}
+#ifdef CONFIG_PROC_FS	
X         if (proc_unregister(&proc_root, PROC_SOUND))
X 		printk(KERN_ERR "sound: unregistering /proc/sound failed\n");
+#endif		
X 	if (chrdev_registered)
X 		destroy_special_devices();
X 
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/binfmt_misc.c linux/fs/binfmt_misc.c
--- v2.2.0-pre3/linux/fs/binfmt_misc.c	Fri Jan  1 12:58:20 1999
+++ linux/fs/binfmt_misc.c	Sat Jan  2 17:55:06 1999
@@ -30,6 +30,16 @@
X #include <asm/uaccess.h>
X #include <asm/spinlock.h>
X 
+/*
+ * We should make this work with a "stub-only" /proc,
+ * which would just not be able to be configured.
+ * Right now the /proc-fs support is too black and white,
+ * though, so just remind people that this should be
+ * fixed..
+ */
+#ifndef CONFIG_PROC_FS
+#error You really need /proc support for binfmt_misc. Please reconfigure!
+#endif
X 
X #define VERBOSE_STATUS /* undef this to save 400 bytes kernel memory */
X 
@@ -67,9 +77,7 @@
X static int free_id = 1;
X static int enabled = 1;
X 
-#ifdef CONFIG_SMP
-static rwlock_t entries_lock = RW_LOCK_UNLOCKED;
-#endif
+static rwlock_t entries_lock __attribute__((unused)) = RW_LOCK_UNLOCKED;
X 
X 
X /*
@@ -458,8 +466,10 @@
X {
X 	if (!(e->proc_dir = create_proc_entry(e->proc_name,
X 			 	S_IFREG | S_IRUGO | S_IWUSR, bm_dir)))
-		return -ENOMEM;
-
+	{
+		printk(KERN_WARNING "Unable to create /proc entry.\n");
+		return -ENOENT;
+	}
X 	e->proc_dir->data = (void *) (e->id);
X 	e->proc_dir->read_proc = proc_read_status;
X 	e->proc_dir->write_proc = proc_write_status;
@@ -486,7 +496,7 @@
X 
X int __init init_misc_binfmt(void)
X {
-	int error = -ENOMEM;
+	int error = -ENOENT;
X 	struct proc_dir_entry *status = NULL, *reg;
X 
X 	bm_dir = create_proc_entry("sys/fs/binfmt_misc", S_IFDIR, NULL);
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.2.0-pre3/linux/fs/fat/inode.c	Fri Jan  1 12:58:20 1999
+++ linux/fs/fat/inode.c	Sat Jan  2 10:35:24 1999
@@ -364,8 +364,8 @@
X 		MSDOS_SB(sb)->root_cluster = CF_LE_L(b->root_cluster);
X 		MSDOS_SB(sb)->fsinfo_offset =
X 			CF_LE_W(b->info_sector) * logical_sector_size + 0x1e0;
-		if (MSDOS_SB(sb)->fsinfo_offset + sizeof(MSDOS_SB(sb)->fsinfo_offset) >= sizeof(struct fat_boot_sector)) {
-			printk("fat_read_super: Bad fsinfo_offset\n");
+		if (MSDOS_SB(sb)->fsinfo_offset + sizeof(MSDOS_SB(sb)->fsinfo_offset) > sb->s_blocksize) {
+			printk("fat_read_super: Bad fsinfo_offset 0x%x\n", MSDOS_SB(sb)->fsinfo_offset);
X 			fat_brelse(sb, bh);
X 			goto out_invalid;
X 		}
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.2.0-pre3/linux/fs/nfs/write.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/nfs/write.c	Sat Jan  2 10:16:39 1999
@@ -263,12 +263,8 @@
X static inline void
X free_write_request(struct nfs_wreq * req)
X {
-	if (!--req->wb_count) {
-		struct inode *inode = req->wb_inode;
-		remove_write_request(&NFS_WRITEBACK(inode), req);
+	if (!--req->wb_count)
X 		kfree(req);
-		nr_write_requests--;
-	}
X }
X 
X /*
@@ -698,6 +694,8 @@
X 		clear_bit(PG_uptodate, &page->flags);
X 
X 	__free_page(page);
+	remove_write_request(&NFS_WRITEBACK(inode), req);
+	nr_write_requests--;
X 	dput(req->wb_dentry);
X 
X 	wake_up(&req->wb_wait);
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.2.0-pre3/linux/fs/nfsd/nfsctl.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/nfsd/nfsctl.c	Sat Jan  2 17:55:06 1999
@@ -54,8 +54,6 @@
X 
X static int	initialized = 0;
X 
-#ifdef CONFIG_PROC_FS
-
X int exp_procfs_exports(char *buffer, char **start, off_t offset,
X                              int length, int *eof, void *data);
X 
@@ -70,7 +68,6 @@
X 	nfs_export_ent->read_proc = exp_procfs_exports;
X }
X 
-#endif
X 
X /*
X  * Initialize nfsd
@@ -79,16 +76,12 @@
X nfsd_init(void)
X {
X 	nfsd_xdr_init();	/* XDR */
-#ifdef CONFIG_PROC_FS
X 	nfsd_stat_init();	/* Statistics */
-#endif
X 	nfsd_cache_init();	/* RPC reply cache */
X 	nfsd_export_init();	/* Exports table */
X 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
X 	nfsd_fh_init();		/* FH table */
-#ifdef CONFIG_PROC_FS
X 	proc_export_init();
-#endif
X 	initialized = 1;
X }
X 
@@ -310,11 +303,9 @@
X 	nfsd_export_shutdown();
X 	nfsd_cache_shutdown();
X 	nfsd_fh_free();
-#ifdef CONFIG_PROC_FS
X 	remove_proc_entry("fs/nfs/exports", NULL);
X 	remove_proc_entry("fs/nfs", NULL);
X 	nfsd_stat_shutdown();
-#endif
X 	nfsd_lockd_shutdown();
X }
X #endif
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/nfsd/stats.c linux/fs/nfsd/stats.c
--- v2.2.0-pre3/linux/fs/nfsd/stats.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/nfsd/stats.c	Sat Jan  2 17:55:05 1999
@@ -27,7 +27,6 @@
X struct nfsd_stats	nfsdstats;
X struct svc_stat		nfsd_svcstats = { &nfsd_program, };
X 
-#ifdef CONFIG_PROC_FS
X static int
X nfsd_proc_read(char *buffer, char **start, off_t offset, int count,
X 				int *eof, void *data)
@@ -90,4 +89,3 @@
X {
X 	svc_proc_unregister("nfsd");
X }
-#endif /* CONFIG_PROC_FS */
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.2.0-pre3/linux/fs/nfsd/vfs.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/nfsd/vfs.c	Sat Jan  2 09:54:30 1999
@@ -993,7 +993,7 @@
X static inline void nfsd_double_down(struct semaphore *s1, struct semaphore *s2)
X {
X 	if (s1 != s2) {
-		if ((unsigned long) s1 < (unsigned long) s2) {
+		if ((unsigned long) s1 > (unsigned long) s2) {
X 			struct semaphore *tmp = s1;
X 			s1 = s2;
X 			s2 = tmp;
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/Makefile linux/fs/ntfs/Makefile
--- v2.2.0-pre3/linux/fs/ntfs/Makefile	Fri Jan  2 01:42:58 1998
+++ linux/fs/ntfs/Makefile	Sat Jan  2 10:24:46 1999
@@ -3,7 +3,7 @@
X O_TARGET := ntfs.o
X O_OBJS   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o
X M_OBJS   := $(O_TARGET)
-EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"980101\"
+EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"990102\"
X 
X include $(TOPDIR)/Rules.make
X 
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/attr.c linux/fs/ntfs/attr.c
--- v2.2.0-pre3/linux/fs/ntfs/attr.c	Fri Oct 23 22:01:22 1998
+++ linux/fs/ntfs/attr.c	Sat Jan  2 10:24:46 1999
@@ -1,11 +1,12 @@
X /*
X  *  attr.c
X  *
- *  Copyright (C) 1996-1997 Martin von Löwis
+ *  Copyright (C) 1996-1998 Martin von Löwis
X  *  Copyright (C) 1996-1997 Régis Duchesne
+ *  Copyright (C) 1998 Joseph Malicki
X  */
X 
-#include "types.h"
+#include "ntfstypes.h"
X #include "struct.h"
X #include "attr.h"
X 
@@ -81,7 +82,7 @@
X 
X /* Store in the inode readable information about a run */
X static void
-ntfs_insert_run(ntfs_attribute *attr,int cnum,int cluster,int len)
+ntfs_insert_run(ntfs_attribute *attr,int cnum,ntfs_cluster_t cluster,int len)
X {
X 	/* (re-)allocate space if necessary */
X 	if(attr->d.r.len % 8 == 0) {
@@ -107,11 +108,17 @@
X {
X 	int error=0;
X 	ntfs_runlist *rl;
-	int rlen,cluster;
+	int rlen;
+	ntfs_cluster_t cluster;
X 	int clen;
X 	if(attr->compressed)return EOPNOTSUPP;
-	if(attr->resident)return EOPNOTSUPP;
X 	if(ino->record_count>1)return EOPNOTSUPP;
+	if(attr->resident) {
+		error = ntfs_make_attr_nonresident(ino,attr);
+		if(error)
+			return error;
+	}
+
X 	rl=attr->d.r.runlist;
X 	rlen=attr->d.r.len-1;
X 	if(rlen>=0)
@@ -121,18 +128,20 @@
X 		cluster=0;
X 	/* round up to multiple of cluster size */
X 	clen=(*len+ino->vol->clustersize-1)/ino->vol->clustersize;
+	if(clen==0)
+		return 0;
X 	/* FIXME: try to allocate smaller pieces */
X 	error=ntfs_allocate_clusters(ino->vol,&cluster,&clen,
X 				     flags|ALLOC_REQUIRE_SIZE);
X 	if(error)return error;
-	attr->allocated+=clen;
+	attr->allocated += clen*ino->vol->clustersize;
X 	*len=clen*ino->vol->clustersize;
X 	/* contiguous chunk */
X 	if(rlen>=0 && cluster==rl[rlen].cluster+rl[rlen].len){
X 		rl[rlen].len+=clen;
X 		return 0;
X 	}
-	ntfs_insert_run(attr,rlen+1,cluster,*len);
+	ntfs_insert_run(attr,rlen+1,cluster,clen);
X 	return 0;
X }
X 
@@ -158,6 +167,22 @@
X 	return ntfs_readwrite_attr(ino,attr,0,&io);
X }
X 
+int
+ntfs_attr_allnonresident(ntfs_inode *ino)
+{
+	int i, error=0;
+        ntfs_volume *vol = ino->vol;
+
+	for (i=0; !error && i<ino->attr_count; i++)
+	{
+		if (ino->attrs[i].type != vol->at_security_descriptor
+		    && ino->attrs[i].type != vol->at_data)
+			continue;
+		error = ntfs_make_attr_nonresident (ino, ino->attrs+i);
+	}
+	return error;
+}
+
X /* Resize the attribute to a newsize */
X int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, int newsize)
X {
@@ -175,7 +200,7 @@
X 		return EOPNOTSUPP;
X 	if(attr->resident){
X 		void *v;
-		if(newsize>ino->vol->clustersize){
+		if(newsize>ino->vol->mft_recordsize){
X 			error=ntfs_make_attr_nonresident(ino,attr);
X 			if(error)return error;
X 			return ntfs_resize_attr(ino,attr,newsize);
@@ -185,8 +210,10 @@
X 			attr->d.data=ntfs_malloc(newsize);
X 			if(!attr->d.data)
X 				return ENOMEM;
-			ntfs_bzero(attr->d.data+oldsize,newsize);
-			ntfs_memcpy(attr->d.data,v,min(newsize,oldsize));
+			if(newsize>oldsize)
+				ntfs_bzero((char*)attr->d.data+oldsize,
+					   newsize-oldsize);
+			ntfs_memcpy((char*)attr->d.data,v,min(newsize,oldsize));
X 		}else
X 			attr->d.data=0;
X 		ntfs_free(v);
@@ -199,7 +226,7 @@
X 		for(i=0,count=0;i<attr->d.r.len;i++){
X 			if((count+rl[i].len)*clustersize>newsize)
X 				break;
-			count+=rl[i].len;
+			count+=(int)rl[i].len;
X 		}
X 		newlen=i+1;
X 		/* free unused clusters in current run, unless sparse */
@@ -208,7 +235,7 @@
X 			int rounded=newsize-count*clustersize;
X 			rounded=(rounded+clustersize-1)/clustersize;
X 			error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster+rounded,
-						       rl[i].len-rounded);
+						       (int)rl[i].len-rounded);
X 			if(error)
X 				return error; /* FIXME: incomplete operation */
X 			rl[i].len=rounded;
@@ -217,7 +244,7 @@
X 		/* free all other runs */
X 		for(i++;i<attr->d.r.len;i++)
X 			if(rl[i].cluster!=-1){
-				error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster,rl[i].len);
+				error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster,(int)rl[i].len);
X 				if(error)
X 					return error; /* FIXME: incomplete operation */
X 			}
@@ -232,7 +259,7 @@
X 	/* fill in new sizes */
X 	attr->allocated = newcount*clustersize;
X 	attr->size = newsize;
-	attr->initialized = newsize;
+	/* attr->initialized does not change. */
X 	if(!newsize)
X 		error=ntfs_make_attr_resident(ino,attr);
X 	return error;
@@ -296,7 +323,8 @@
X {
X 	int startvcn,endvcn;
X 	int vcn,cnum;
-	int cluster,len,ctype;
+	ntfs_cluster_t cluster;
+	int len,ctype;
X 	startvcn = NTFS_GETU64(data+0x10);
X 	endvcn = NTFS_GETU64(data+0x18);
X 
@@ -383,13 +411,29 @@
X 	return 0;
X }
X 
+int
+ntfs_read_zero(ntfs_io *dest,int size)
+{
+	char *sparse=ntfs_calloc(512);
+	if(!sparse)
+		return ENOMEM;
+	while(size){
+		int i=min(size,512);
+		dest->fn_put(dest,sparse,i);
+		size-=i;
+	}
+	ntfs_free(sparse);
+	return 0;
+}
+
X /* process compressed attributes */
X int ntfs_read_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
X 	ntfs_io *dest)
X {
X 	int error=0;
X 	int clustersize,l;
-	int s_vcn,rnum,vcn,cluster,len,chunk,got,cl1,l1,offs1,copied;
+	int s_vcn,rnum,vcn,len,chunk,got,l1,offs1,copied;
+	ntfs_cluster_t cluster,cl1;
X 	char *comp=0,*comp1;
X 	char *decomp=0;
X 	ntfs_io io;
@@ -426,18 +470,13 @@
X 		chunk=0;
X 		if(cluster==-1){
X 			/* sparse cluster */
-			char *sparse=ntfs_calloc(512);
X 			int l1;
-			if(!sparse)return ENOMEM;
X 			if((len-(s_vcn-vcn)) & 15)
X 				ntfs_error("unexpected sparse chunk size");
X 			l1=chunk = min((vcn+len)*clustersize-offset,l);
-			while(l1){
-				int i=min(l1,512);
-				dest->fn_put(dest,sparse,i);
-				l1-=i;
-			}
-			ntfs_free(sparse);
+			error = ntfs_read_zero(dest,l1);
+			if(error)
+				goto out;
X 		}else if(dest->do_read){
X 			if(!comp){
X 				comp=ntfs_malloc(16*clustersize);
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/attr.h linux/fs/ntfs/attr.h
--- v2.2.0-pre3/linux/fs/ntfs/attr.h	Fri Dec 19 15:24:21 1997
+++ linux/fs/ntfs/attr.h	Sat Jan  2 10:24:46 1999
@@ -15,3 +15,6 @@
X   ntfs_io *dest);
X int ntfs_create_attr(ntfs_inode *ino, int anum, char *aname, void *data,
X   int dsize, ntfs_attribute **rattr);
+int ntfs_read_zero(ntfs_io *dest,int size);
+int ntfs_make_attr_nonresident(ntfs_inode *ino, ntfs_attribute *attr);
+int ntfs_attr_allnonresident(ntfs_inode *ino);
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/dir.c linux/fs/ntfs/dir.c
--- v2.2.0-pre3/linux/fs/ntfs/dir.c	Fri Oct 23 22:01:22 1998
+++ linux/fs/ntfs/dir.c	Sat Jan  2 10:24:46 1999
@@ -4,9 +4,10 @@
X  *  Copyright (C) 1995-1997 Martin von Löwis
X  */
X 
-#include "types.h"
+#include "ntfstypes.h"
X #include "struct.h"
X #include "dir.h"
+#include "macros.h"
X 
X #include <linux/errno.h>
X #include "super.h"
@@ -26,27 +27,27 @@
X 				 ino->u.index.recordsize);
X }
X 
-static inline int ntfs_is_top(long long stack)
+static inline int ntfs_is_top(ntfs_u64 stack)
X {
X 	return stack==14;
X }
X 
-static long long ntfs_pop(long long *stack)
+static int ntfs_pop(ntfs_u64 *stack)
X {
X 	static int width[16]={1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,-1};
X 	int res=-1;
X 	switch(width[*stack & 15])
X 	{
-	case 1:res=(*stack&15)>>1;
+	case 1:res=(int)((*stack&15)>>1);
X 		*stack>>=4;
X 		break;
-	case 2:res=((*stack&63)>>2)+7;
+	case 2:res=(int)(((*stack&63)>>2)+7);
X 		*stack>>=6;
X 		break;
-	case 3:res=((*stack & 255)>>3)+23;
+	case 3:res=(int)(((*stack & 255)>>3)+23);
X 		*stack>>=8;
X 		break;
-	case 4:res=((*stack & 1023)>>4)+55;
+	case 4:res=(int)(((*stack & 1023)>>4)+55);
X 		*stack>>=10;
X 		break;
X 	default:ntfs_error("Unknown encoding\n");
@@ -59,18 +60,18 @@
X 	return 14;
X }
X 
-static long long ntfs_push(long long stack,int i)
+static ntfs_u64 ntfs_push(ntfs_u64 stack,int i)
X {
X 	if(i<7)return (stack<<4)|(i<<1);
X 	if(i<23)return (stack<<6)|((i-7)<<2)|1;
X 	if(i<55)return (stack<<8)|((i-23)<<3)|3;
X 	if(i<120)return (stack<<10)|((i-55)<<4)|7;
X 	ntfs_error("Too many entries\n");
-	return -1;
+	return 0xFFFFFFFFFFFFFFFF;
X }
X 
X #if 0
-static void ntfs_display_stack(long long stack)
+static void ntfs_display_stack(ntfs_u64 stack)
X {
X 	while(!ntfs_is_top(stack))
X 	{
@@ -162,35 +163,30 @@
X 	if(walk->newblock * vol->clustersize >= size){
X 		/* build index record */
X 		int s1=walk->dir->u.index.recordsize;
+		int nr_fix = s1/vol->blocksize+1;
+		int hsize;
X 		char *record=ntfs_malloc(s1);
-		int newlen;
X 		ntfs_bzero(record,s1);
X 		/* magic */
X 		ntfs_memcpy(record,"INDX",4);
X 		/* offset to fixups */
X 		NTFS_PUTU16(record+4,0x28);
X 		/* number of fixups */
-		NTFS_PUTU16(record+6,s1/vol->blocksize+1);
+		NTFS_PUTU16(record+6,nr_fix);
X 		/* FIXME: log file number */
X 		/* VCN of buffer */
X 		NTFS_PUTU64(record+0x10,walk->newblock);
-		/* header size. FIXME */
-		NTFS_PUTU16(record+0x18,28);
+		/* header size. */
+		hsize = 0x10+2*nr_fix;
+		hsize = (hsize+7) & ~7; /* Align. */
+		NTFS_PUTU16(record+0x18, hsize);
X 		/* total size of record */
X 		NTFS_PUTU32(record+0x20,s1-0x18);
+		/* Writing the data will extend the attribute. */
X 		io.param=record;
-		newlen=walk->dir->u.index.recordsize;
-		/* allocate contiguous index record */
-		error=ntfs_extend_attr(walk->dir,allocation,&newlen,
-				       ALLOC_REQUIRE_SIZE);
-		if(error){
-			/* FIXME: try smaller allocations */
-			ntfs_free(record);
-			return ENOSPC;
-		}
X 		io.size=s1;
-		error=ntfs_write_attr(walk->dir,vol->at_index_allocation,I30,
-				      size,&io);
+		io.do_read=0;
+		error=ntfs_readwrite_attr(walk->dir, allocation, size, &io);
X 		if(error || io.size!=s1){
X 			ntfs_free(record);
X 			return error?error:EIO;
@@ -201,29 +197,38 @@
X 	return 0;
X }
X 
+/* Write an index block (root or allocation) back to storage.
+   used is the total number of bytes in buf, including all headers. */
+
X static int ntfs_index_writeback(ntfs_iterate_s *walk, ntfs_u8 *buf, int block,
-	int used)
+				int used)
X {
X 	ntfs_io io;
X 	int error;
+	ntfs_attribute *a;
+	ntfs_volume *vol = walk->dir->vol;
+	
X 	io.fn_put=0;
X 	io.fn_get=ntfs_get;
X 	io.param=buf;
-	if(walk->block==-1){
+	if(block==-1){
X 		NTFS_PUTU16(buf+0x14,used-0x10);
X 		/* 0x18 is a copy thereof */
X 		NTFS_PUTU16(buf+0x18,used-0x10);
X 		io.size=used;
-		error=ntfs_write_attr(walk->dir,walk->dir->vol->at_index_root,
+		error=ntfs_write_attr(walk->dir,vol->at_index_root,
X 				      I30,0,&io);
X 		if(error)return error;
X 		if(io.size!=used)return EIO;
+		/* shrink if necessary */
+		a = ntfs_find_attr(walk->dir, vol->at_index_root, I30);
+		ntfs_resize_attr(walk->dir, a, used);
X 	}else{
-		NTFS_PUTU16(buf+0x1C,used-0x20);
-		ntfs_insert_fixups(buf,walk->dir->vol->blocksize);
+		NTFS_PUTU16(buf+0x1C,used-0x18);
+		ntfs_insert_fixups(buf,vol->blocksize);
X 		io.size=walk->dir->u.index.recordsize;
-		error=ntfs_write_attr(walk->dir,walk->dir->vol->at_index_allocation,I30,
-				      walk->block*walk->dir->vol->clustersize,
+		error=ntfs_write_attr(walk->dir,vol->at_index_allocation,I30,
+				      block*vol->clustersize,
X 				      &io);
X 		if(error)return error;
X 		if(io.size!=walk->dir->u.index.recordsize)
@@ -240,13 +245,20 @@
X 	int error,othersize,mlen;
X 	ntfs_io io;
X 	ntfs_volume *vol=walk->dir->vol;
+	int oldblock;
+
X 	error=ntfs_allocate_index_block(walk);
X 	if(error)
X 		return error;
-	for(entry=prev=start+NTFS_GETU16(start+0x18)+0x18;
-	    entry-start<usize/2;
-	    entry+=NTFS_GETU16(entry+8))
+	/* This should not happen */
+	if(walk->block == -1){
+		ntfs_error("Trying to split root");
+		return EOPNOTSUPP;
+	}
+	entry = start+NTFS_GETU16(start+0x18)+0x18; 
+	for(prev=entry; entry-start<usize/2; entry += NTFS_GETU16(entry+8))
X 		prev=entry;
+
X 	newbuf=ntfs_malloc(vol->index_recordsize);
X 	if(!newbuf)
X 		return ENOMEM;
@@ -266,11 +278,19 @@
X 	/* copy everything from entry to new block */
X 	othersize=usize-(entry-start);
X 	ntfs_memcpy(newbuf+NTFS_GETU16(newbuf+0x18)+0x18,entry,othersize);
-	error=ntfs_index_writeback(walk,newbuf,walk->newblock,othersize);
+	/* Copy flags. */
+	NTFS_PUTU32(newbuf+0x24, NTFS_GETU32(start+0x24));
+	error=ntfs_index_writeback(walk,newbuf,walk->newblock,
+				   othersize+NTFS_GETU16(newbuf+0x18)+0x18);
X 	if(error)goto out;
X 
X 	/* move prev to walk */
X 	mlen=NTFS_GETU16(prev+0x8);
+	/* Remember old child node. */
+	if(ntfs_entry_has_subnodes(prev))
+		oldblock = NTFS_GETU32(prev+mlen-8);
+	else
+		oldblock = -1;
X 	/* allow for pointer to subnode */
X 	middle=ntfs_malloc(ntfs_entry_has_subnodes(prev)?mlen:mlen+8);
X 	if(!middle){
@@ -286,8 +306,21 @@
X 		ntfs_error("entry not reset");
X 	walk->new_entry=middle;
X 	walk->u.flags|=ITERATE_SPLIT_DONE;
+	/* Terminate old block. */
+	othersize = usize-(prev-start);
+	NTFS_PUTU64(prev, 0);
+	if(oldblock==-1){
+		NTFS_PUTU32(prev+8, 0x10);
+		NTFS_PUTU32(prev+0xC, 2);
+		othersize += 0x10;
+	}else{
+		NTFS_PUTU32(prev+8, 0x18);
+		NTFS_PUTU32(prev+0xC, 3);
+		NTFS_PUTU64(prev+0x10, oldblock);
+		othersize += 0x18;
+	}
X 	/* write back original block */
-	error=ntfs_index_writeback(walk,start,walk->block,usize-(prev-start));
+	error=ntfs_index_writeback(walk,start,walk->block,othersize);
X  out:
X 	if(newbuf)ntfs_free(newbuf);
X 	if(middle)ntfs_free(middle);
@@ -300,12 +333,11 @@
X 	int do_split=0;
X 	offset=entry-start;
X 	if(walk->block==-1){ /*index root */
-		/* FIXME: adjust to maximum allowed index root value */
X 		blocksize=walk->dir->vol->mft_recordsize;
X 		usedsize=NTFS_GETU16(start+0x14)+0x10;
X 	}else{
X 		blocksize=walk->dir->u.index.recordsize;
-		usedsize=NTFS_GETU16(start+0x1C)+0x20;
+		usedsize=NTFS_GETU16(start+0x1C)+0x18;
X 	}
X 	if(usedsize+walk->new_entry_size > blocksize){
X 		char* s1=ntfs_malloc(blocksize+walk->new_entry_size);
@@ -321,7 +353,6 @@
X 	usedsize+=walk->new_entry_size;
X 	ntfs_free(walk->new_entry);
X 	walk->new_entry=0;
-	/*FIXME: split root */
X 	if(do_split){
X 		error=ntfs_split_record(walk,start,blocksize,usedsize);
X 		ntfs_free(start);
@@ -330,6 +361,81 @@
X 	return 0;
X }
X 
+/* Try to split INDEX_ROOT attributes. Return E2BIG if nothing changed. */
+
+int
+ntfs_split_indexroot(ntfs_inode *ino)
+{
+	ntfs_attribute *ra;
+	ntfs_u8 *root=0, *index=0;
+	ntfs_io io;
+	int error, off, i, bsize, isize;
+	ntfs_iterate_s walk;
+
+	ra = ntfs_find_attr(ino, ino->vol->at_index_root, I30);
+	if(!ra)
+		return E2BIG;
+	bsize = ino->vol->mft_recordsize;
+	root = ntfs_malloc(bsize);
+	if(!root)
+		return E2BIG;
+	io.fn_put = ntfs_put;
+	io.param = root;
+	io.size = bsize;
+	error = ntfs_read_attr(ino, ino->vol->at_index_root, I30, 0, &io);
+	if(error)
+		goto out;
+	off = 0x20;
+	/* Count number of entries. */
+	for(i = 0; ntfs_entry_is_used(root+off); i++)
+		off += NTFS_GETU16(root+off+8);
+	if(i<=2){
+		/* We don't split small index roots. */
+		error = E2BIG;
+		goto out;
+	}
+	index = ntfs_malloc(ino->vol->index_recordsize);
+	if(!index)
+		goto out;
+	walk.dir = ino;
+	walk.block = -1;
+	walk.result = walk.new_entry = 0;
+	walk.name = 0;
+	error = ntfs_allocate_index_block(&walk);
+	if(error)
+		goto out;
+
+	/* Write old root to new index block. */
+	io.param = index;
+	io.size = ino->vol->index_recordsize;
+	error = ntfs_read_attr(ino, ino->vol->at_index_allocation, I30,
+			       walk.newblock*ino->vol->clustersize, &io);
+	if(error)
+		goto out;
+	isize = NTFS_GETU16(root+0x18) - 0x10;
+	ntfs_memcpy(index+NTFS_GETU16(index+0x18)+0x18, root+0x20, isize);
+	/* Copy flags. */
+	NTFS_PUTU32(index+0x24, NTFS_GETU32(root+0x1C));
+
+	error = ntfs_index_writeback(&walk, index, walk.newblock, 
+				     isize+NTFS_GETU16(index+0x18)+0x18);
+	if(error)
+		goto out;
+
+	/* Mark root as split. */
+	NTFS_PUTU32(root+0x1C, 1);
+	/* Truncate index root. */
+	NTFS_PUTU64(root+0x20, 0);
+	NTFS_PUTU32(root+0x28, 0x18);
+	NTFS_PUTU32(root+0x2C, 3);
+	NTFS_PUTU64(root+0x30, walk.newblock);
+	error = ntfs_index_writeback(&walk,root,-1,0x38);
+ out:
+	ntfs_free(root);
+	ntfs_free(index);
+	return error;
+}
+
X /* The entry has been found. Copy the result in the caller's buffer */
X static int ntfs_copyresult(char *dest,char *source)
X {
@@ -419,9 +525,9 @@
X 	error=ntfs_getdir_record(walk,nextblock);
X 	if(!error && walk->type==DIR_INSERT && 
X 	   (walk->u.flags & ITERATE_SPLIT_DONE)){
-		/* split has occurred. adjust entry, insert new_entry */
+		/* Split has occurred. Adjust entry, insert new_entry. */
X 		NTFS_PUTU32(entry+length-8,walk->newblock);
-		/* reset flags, as the current block might be split again */
+		/* Reset flags, as the current block might be split again. */
X 		walk->u.flags &= ~ITERATE_SPLIT_DONE;
X 		error=ntfs_dir_insert(walk,start,entry);
X 	}
@@ -637,6 +743,7 @@
X 		ntfs_error("Inode %d has no volume\n",ino->i_number);
X 		return EINVAL;
X 	}
+	ntfs_debug(DEBUG_DIR3,"unsorted 1\n");
X 	/* are we still in the index root */
X 	if(*p_high==0){
X 		buf=ntfs_malloc(length=vol->mft_recordsize);
@@ -651,6 +758,7 @@
X 		ino->u.index.recordsize = NTFS_GETU32(buf+0x8);
X 		ino->u.index.clusters_per_record = NTFS_GETU32(buf+0xC);
X 		entry=buf+0x20;
+		ntfs_debug(DEBUG_DIR3,"unsorted 2\n");
X 	}else{ /* we are in an index record */
X 		length=ino->u.index.recordsize;
X 		buf=ntfs_malloc(length);
@@ -673,14 +781,17 @@
X 			return ENOTDIR;
X 		}
X 		entry=buf+NTFS_GETU16(buf+0x18)+0x18;
+		ntfs_debug(DEBUG_DIR3,"unsorted 3\n");
X 	}
X 
X 	/* process the entries */
X 	start=*p_low;
X 	while(ntfs_entry_is_used(entry)){
+		ntfs_debug(DEBUG_DIR3,"unsorted 4\n");
X 		if(start)
X 			start--; /* skip entries that were already processed */
X 		else{
+			ntfs_debug(DEBUG_DIR3,"unsorted 5\n");
X 			if((error=cb(entry,param)))
X 				/* the entry could not be processed */
X 				break;
@@ -689,9 +800,11 @@
X 		entry+=NTFS_GETU16(entry+8);
X 	}
X 
+	ntfs_debug(DEBUG_DIR3,"unsorted 6\n");
X 	/* caller did not process all entries */
X 	if(error){
X 		ntfs_free(buf);
+		ntfs_debug(DEBUG_DIR3,"unsorted 7\n");
X 		return error;
X 	}
X 
@@ -704,6 +817,7 @@
X 		/* directory does not have index allocation */
X 		*p_high=0xFFFFFFFF;
X 		*p_low=0;
+		ntfs_debug(DEBUG_DIR3,"unsorted 8\n");
X 		return 0;
X 	}
X 	buf=ntfs_malloc(length=attr->size);
@@ -713,6 +827,7 @@
X 	if(!error && io.size!=length)error=EIO;
X 	if(error){
X 		ntfs_free(buf);
+		ntfs_debug(DEBUG_DIR3,"unsorted 9\n");
X 		return EIO;
X 	}
X 	attr=ntfs_find_attr(ino,vol->at_index_allocation,I30);
@@ -721,6 +836,7 @@
X 			/* no more index records */
X 			*p_high=0xFFFFFFFF;
X 			ntfs_free(buf);
+			ntfs_debug(DEBUG_DIR3,"unsorted 10\n");
X 			return 0;
X 		}
X 		*p_high+=ino->u.index.clusters_per_record;
@@ -731,6 +847,7 @@
X 		if(buf[byte] & bit)
X 			break;
X 	}
+	ntfs_debug(DEBUG_DIR3,"unsorted 11\n");
X 	ntfs_free(buf);
X 	return 0;
X }
@@ -800,6 +917,62 @@
X 	return error;
X }
X #endif
+
+/* Fills out and creates an INDEX_ROOT attribute. */
+
+static int
+add_index_root (ntfs_inode *ino, int type)
+{
+	ntfs_attribute *da;
+	ntfs_u8 data[0x30]; /* 0x20 header, 0x10 last entry */
+	char name[10];
+
+	NTFS_PUTU32(data, type);
+	/* ??? */
+	NTFS_PUTU32(data+4, 1);
+	NTFS_PUTU32(data+8, ino->vol->index_recordsize);
+	NTFS_PUTU32(data+0xC, ino->vol->index_clusters_per_record);
+	/* ??? */
+	NTFS_PUTU32(data+0x10, 0x10);
+	/* Size of entries, including header. */
+	NTFS_PUTU32(data+0x14, 0x20);
+	NTFS_PUTU32(data+0x18, 0x20);
+	/* No index allocation, yet. */
+	NTFS_PUTU32(data+0x1C, 0);
+	/* add last entry. */
+	/* indexed MFT record. */
+	NTFS_PUTU64(data+0x20, 0);
+	/* size of entry */
+	NTFS_PUTU32(data+0x28, 0x10);
+	/* flags: last entry, no child nodes. */
+	NTFS_PUTU32(data+0x2C, 2);
+	/* compute name */
+	ntfs_indexname(name, type);
+	return ntfs_create_attr(ino, ino->vol->at_index_root, name,
+				data, sizeof(data), &da);
+}
+
+int
+ntfs_mkdir(ntfs_inode* dir,const char* name,int namelen, ntfs_inode *result)
+{
+	int error;
+	error = ntfs_alloc_inode(dir, result, name, namelen, NTFS_AFLAG_DIR);
+	if(error)
+		goto out;
+	error = add_index_root(result, 0x30);
+	if (error)
+		goto out;
+	/* Set directory bit */
+	result->attr[0x16] |= 2;
+	error = ntfs_update_inode (dir);
+	if (error)
+		goto out;
+	error = ntfs_update_inode (result);
+	if (error)
+		goto out;
+ out:
+	return error;
+}
X 
X /*
X  * Local variables:
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/dir.h linux/fs/ntfs/dir.h
--- v2.2.0-pre3/linux/fs/ntfs/dir.h	Fri Dec 19 15:24:21 1997
+++ linux/fs/ntfs/dir.h	Sat Jan  2 10:24:46 1999
@@ -18,7 +18,7 @@
X 	enum ntfs_iterate_e type;
X 	ntfs_inode *dir;
X 	union{
-		long long pos;
+		ntfs_u64 pos;
X 		int flags;
X 	}u;
X 	char *result;      /* pointer to entry if found */
@@ -37,3 +37,5 @@
X int ntfs_dir_add(ntfs_inode *dir, ntfs_inode *new, ntfs_attribute *name);
X int ntfs_check_index_record(ntfs_inode *ino, char *record);
X int ntfs_getdir_byposition(ntfs_iterate_s *walk);
+int ntfs_mkdir(ntfs_inode* dir,const char* name,int namelen, ntfs_inode *ino);
+int ntfs_split_indexroot(ntfs_inode *ino);
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.2.0-pre3/linux/fs/ntfs/fs.c	Wed Aug 26 11:37:43 1998
+++ linux/fs/ntfs/fs.c	Sat Jan  2 10:24:46 1999
@@ -14,7 +14,7 @@
X #include <linux/config.h>
X #endif
X 
-#include "types.h"
+#include "ntfstypes.h"
X #include "struct.h"
X #include "util.h"
X #include "inode.h"
@@ -29,6 +29,9 @@
X #include <linux/locks.h>
X #include <linux/init.h>
X 
+/* Forward declarations */
+static struct inode_operations ntfs_dir_inode_operations;
+
X #define ITEM_SIZE 2040
X 
X /* io functions to user space */
@@ -39,10 +42,19 @@
X }
X 
X #ifdef CONFIG_NTFS_RW
-static void ntfs_getuser(void *dest,ntfs_io *src,ntfs_size_t len)
+struct ntfs_getuser_update_vm_s{
+	const char *user;
+	struct inode *ino;
+	loff_t off;
+};
+
+static void ntfs_getuser_update_vm (void *dest, ntfs_io *src, ntfs_size_t len)
X {
-	copy_from_user(dest,src->param,len);
-	src->param+=len;
+	struct ntfs_getuser_update_vm_s *p = src->param;
+	copy_from_user (dest, p->user, len);
+	update_vm_cache (p->ino, p->off, dest, len);
+	p->user += len;
+	p->off += len;
X }
X #endif
X 
@@ -77,31 +89,42 @@
X static ssize_t
X ntfs_write(struct file *filp,const char* buf,size_t count,loff_t *pos)
X {
-	struct super_block* sb;
X 	int ret;
X 	ntfs_io io;
-	ntfs_inode *ino=NTFS_LINO2NINO(filp->f_dentry->d_inode);
+	struct inode *inode = filp->f_dentry->d_inode;
+	ntfs_inode *ino = NTFS_LINO2NINO(inode);
+	struct ntfs_getuser_update_vm_s param;
X 
-	if(!ino)return -EINVAL;
-	ntfs_debug(DEBUG_OTHER, "ntfs_write %x,%x,%x ->",
-	       (unsigned)ino->i_number,(unsigned)*pos,(unsigned)count);
-	sb = filp->f_dentry->d_inode->i_sb;
+	if (!ino)
+		return -EINVAL;
+	ntfs_debug (DEBUG_LINUX, "ntfs_write %x,%x,%x ->\n",
+	       (unsigned)ino->i_number, (unsigned)*pos, (unsigned)count);
X 	/* Allows to lock fs ro at any time */
-	if(sb->s_flags & MS_RDONLY)
+	if (inode->i_sb->s_flags & MS_RDONLY)
X 		return -ENOSPC;
-	if(!ntfs_find_attr(ino,ino->vol->at_data,NULL))
+	if (!ntfs_find_attr(ino,ino->vol->at_data,NULL))
X 		return -EINVAL;
X 
-	io.fn_put=0;
-	io.fn_get=ntfs_getuser;
-	io.param=(void*)buf; /* to get rid of the const */
-	io.size=count;
-	ret = ntfs_write_attr(ino,ino->vol->at_data,NULL,*pos,&io);
-	ntfs_debug(DEBUG_OTHER, "%x\n",ret);
-	if(ret<0)return -EINVAL;
+	/* Evaluating O_APPEND is the file system's job... */
+	if (filp->f_flags & O_APPEND)
+		*pos = inode->i_size;
+	param.user = buf;
+	param.ino = inode;
+	param.off = *pos;
+	io.fn_put = 0;
+	io.fn_get = ntfs_getuser_update_vm;
+	io.param = ¶m;
+	io.size = count;
+	ret = ntfs_write_attr (ino, ino->vol->at_data, NULL, *pos, &io);
+	ntfs_debug (DEBUG_LINUX, "write -> %x\n", ret);
+	if(ret<0)
+		return -EINVAL;
X 
-	*pos+=ret;
-	return ret;
+	*pos += io.size;
+	if (*pos > inode->i_size)
+		inode->i_size = *pos;
+	mark_inode_dirty (filp->f_dentry->d_inode);
+	return io.size;
X }
X #endif
X 
@@ -119,10 +142,13 @@
X {
X 	struct ntfs_filldir* nf=param;
X 	int flags=NTFS_GETU8(entry+0x51);
-	int show_hidden=0,to_lower=0;
+	int show_hidden=0;
X 	int length=NTFS_GETU8(entry+0x50);
X 	int inum=NTFS_GETU32(entry);
-	int i,error;
+	int error;
+#ifdef NTFS_NGT_NT_DOES_LOWER
+	int i,to_lower=0;
+#endif
X 	switch(nf->type){
X 	case ngt_dos:
X 		/* Don't display long names */
@@ -133,7 +159,9 @@
X 		/* Don't display short-only names */
X 		switch(flags&3){
X 		case 2: return 0;
+#ifdef NTFS_NGT_NT_DOES_LOWER
X 		case 3: to_lower=1;
+#endif
X 		}
X 		break;
X 	case ngt_posix:
@@ -156,6 +184,7 @@
X 	/* Do not return ".", as this is faked */
X 	if(length==1 && *nf->name=='.')
X 		return 0;
+#ifdef NTFS_NGT_NT_DOES_LOWER
X 	if(to_lower)
X 		for(i=0;i<nf->namelen;i++)
X 			/* This supports ASCII only. Since only DOS-only
@@ -163,6 +192,7 @@
X 			   to ASCII, this should be correct */
X 			if(nf->name[i]>='A' && nf->name[i]<='Z')
X 				nf->name[i]+='a'-'A';
+#endif
X 	nf->name[nf->namelen]=0;
X 	ntfs_debug(DEBUG_OTHER, "readdir got %s,len %d\n",nf->name,nf->namelen);
X 	/* filldir expects an off_t rather than an loff_t.
@@ -349,7 +379,7 @@
X 	char *item=0;
X 	ntfs_iterate_s walk;
X 	int error;
-	ntfs_debug(DEBUG_OTHER, "Looking up %s in %x\n",d->d_name.name,
+	ntfs_debug(DEBUG_NAME1, "Looking up %s in %x\n",d->d_name.name,
X 		   (unsigned)dir->i_ino);
X 	/* convert to wide string */
X 	error=ntfs_decodeuni(NTFS_INO2VOL(dir),(char*)d->d_name.name,
@@ -369,10 +399,11 @@
X 	d_add(d,res);
X 	ntfs_free(item);
X 	ntfs_free(walk.name);
-	return res?0:-ENOENT;
+	/* Always return success, the dcache will handle negative entries. */
+	return 0;
X }
X 
-struct file_operations ntfs_file_operations_nommap = {
+static struct file_operations ntfs_file_operations_nommap = {
X 	NULL, /* lseek */
X 	ntfs_read,
X #ifdef CONFIG_NTFS_RW
@@ -394,7 +425,7 @@
X 	NULL, /* lock */
X };
X 
-struct inode_operations ntfs_inode_operations_nobmap = {
+static struct inode_operations ntfs_inode_operations_nobmap = {
X 	&ntfs_file_operations_nommap,
X 	NULL, /* create */
X 	NULL, /* lookup */
@@ -445,7 +476,7 @@
X 	}
X 	r->u.generic_ip=ino;
X #endif
-	error=ntfs_alloc_inode(NTFS_LINO2NINO(dir),ino,(char*)d->d_name.name,
+	error=ntfs_alloc_file(NTFS_LINO2NINO(dir),ino,(char*)d->d_name.name,
X 			       d->d_name.len);
X 	if(error)goto fail;
X 	error=ntfs_update_inode(ino);
@@ -483,6 +514,65 @@
X 	if(r)iput(r);
X 	return -error;
X }
+
+static int
+_linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode)
+{
+	int error;
+	struct inode *r = 0;
+	ntfs_volume *vol;
+	ntfs_inode *ino;
+	ntfs_attribute *si;
+
+	ntfs_debug (DEBUG_DIR1, "mkdir %s in %x\n",d->d_name.name, dir->i_ino);
+	error = ENAMETOOLONG;
+	if (d->d_name.len > /* FIXME */255)
+		goto out;
+
+	error = EIO;
+	r = get_empty_inode();
+	if (!r)
+		goto out;
+	
+	vol = NTFS_INO2VOL(dir);
+#ifdef NTFS_IN_LINUX_KERNEL
+	ino = NTFS_LINO2NINO(r);
+#else
+	ino = ntfs_malloc(sizeof(ntfs_inode));
+	error = ENOMEM;
+	if(!ino)
+		goto out;
+	r->u.generic_ip = ino;
+#endif
+	error = ntfs_mkdir(NTFS_LINO2NINO(dir), 
+			   d->d_name.name, d->d_name.len, ino);
+	if(error)
+		goto out;
+	r->i_uid = vol->uid;
+	r->i_gid = vol->gid;
+	r->i_nlink = 1;
+	r->i_sb = dir->i_sb;
+	si = ntfs_find_attr(ino,vol->at_standard_information,NULL);
+	if(si){
+		char *attr = si->d.data;
+		r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18));
+		r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
+		r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+8));
+	}
+	/* It's a directory */
+	r->i_op = &ntfs_dir_inode_operations;
+	r->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+#ifdef CONFIG_NTFS_RW
+	r->i_mode|=S_IWUGO;
+#endif
+	r->i_mode &= ~vol->umask;	
+	
+	d_instantiate(d, r);
+	error = 0;
+ out:
+ 	ntfs_debug (DEBUG_DIR1, "mkdir returns %d\n", -error);
+	return -error;
+}
X #endif
X 
X static int 
@@ -491,10 +581,12 @@
X 	int ret=ntfs_vcn_to_lcn(NTFS_LINO2NINO(ino),block);
X 	ntfs_debug(DEBUG_OTHER, "bmap of %lx,block %x is %x\n",
X 	       ino->i_ino,block,ret);
+	ntfs_error("bmap of %lx,block %x is %x\n", ino->i_ino,block,ret);
+	ntfs_error("super %x\n", ino->i_sb->s_blocksize); 
X 	return (ret==-1) ? 0:ret;
X }
X 
-struct file_operations ntfs_file_operations = {
+static struct file_operations ntfs_file_operations = {
X 	NULL, /* lseek */
X 	ntfs_read,
X #ifdef CONFIG_NTFS_RW
@@ -516,7 +608,7 @@
X 	NULL, /* lock */
X };
X 
-struct inode_operations ntfs_inode_operations = {
+static struct inode_operations ntfs_inode_operations = {
X 	&ntfs_file_operations,
X 	NULL, /* create */
X 	NULL, /* lookup */
@@ -539,7 +631,7 @@
X 	NULL, /* revalidate */
X };
X 
-struct file_operations ntfs_dir_operations = {
+static struct file_operations ntfs_dir_operations = {
X 	NULL, /* lseek */
X 	NULL, /* read */
X 	NULL, /* write */
@@ -557,7 +649,7 @@
X 	NULL, /* lock */
X };
X 
-struct inode_operations ntfs_dir_inode_operations = {
+static struct inode_operations ntfs_dir_inode_operations = {
X 	&ntfs_dir_operations,
X #ifdef CONFIG_NTFS_RW
X 	ntfs_create, /* create */
@@ -568,7 +660,11 @@
X 	NULL, /* link */
X 	NULL, /* unlink */
X 	NULL, /* symlink */
-	NULL, /* mkdir */
+#ifdef CONFIG_NTFS_RW
+	_linux_ntfs_mkdir, /* mkdir */
+#else
+	NULL,
+#endif
X 	NULL, /* rmdir */
X 	NULL, /* mknod */
X 	NULL, /* rename */
@@ -669,9 +765,14 @@
X 	inode->i_mode &= ~vol->umask;
X }
X 
-static void ntfs_put_inode(struct inode *ino)
+#ifdef CONFIG_NTFS_RW
+static void 
+ntfs_write_inode (struct inode *ino)
X {
+	ntfs_debug (DEBUG_LINUX, "ntfs:write inode %x\n", ino->i_ino);
+	ntfs_update_inode (NTFS_LINO2NINO (ino));
X }
+#endif
X 
X static void _ntfs_clear_inode(struct inode *ino)
X {
@@ -747,10 +848,14 @@
X }
X 
X /* Define the super block operation that are implemented */
-struct super_operations ntfs_super_operations = {
+static struct super_operations ntfs_super_operations = {
X 	ntfs_read_inode,
-	NULL, /* write_inode */
-	ntfs_put_inode,
+#ifdef CONFIG_NTFS_RW
+	ntfs_write_inode,
+#else
+	NULL,
+#endif
+	NULL, /* put_inode */
X 	NULL, /* delete_inode */
X 	NULL, /* notify_change */
X 	ntfs_put_super,
@@ -898,7 +1003,7 @@
X  * Define SECOND if you cannot unload ntfs, and want to avoid rebooting
X  * for just one more test
X  */
-struct file_system_type ntfs_fs_type = {
+static struct file_system_type ntfs_fs_type = {
X /* Filesystem name, as used after mount -t */
X #ifndef SECOND
X 	"ntfs",
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/inode.c linux/fs/ntfs/inode.c
--- v2.2.0-pre3/linux/fs/ntfs/inode.c	Fri Oct 23 22:01:22 1998
+++ linux/fs/ntfs/inode.c	Sat Jan  2 10:24:46 1999
@@ -1,12 +1,13 @@
X /*
X  *  inode.c
X  *
- *  Copyright (C) 1995-1997 Martin von Löwis
+ *  Copyright (C) 1995-1999 Martin von Löwis
X  *  Copyright (C) 1996 Albert D. Cahalan
X  *  Copyright (C) 1996-1997 Régis Duchesne
+ *  Copyright (C) 1998 Joseph Malicki
X  */
X 
-#include "types.h"
+#include "ntfstypes.h"
X #include "struct.h"
X #include "inode.h"
X 
@@ -187,7 +188,7 @@
X /* Read and insert all the attributes of an 'attribute list' attribute
X    Return the number of remaining bytes in *plen
X */
-static int parse_attributes(ntfs_inode *ino, void *alist, int *plen)
+static int parse_attributes(ntfs_inode *ino, ntfs_u8 *alist, int *plen)
X {
X 	char *mft;
X 	int mftno,l,error;
@@ -223,14 +224,14 @@
X 	int offset,len,delta;
X 	char *buf;
X 	ntfs_volume *vol=ino->vol;
-	ntfs_debug(DEBUG_OTHER, "load_attributes %x 1\n",ino->i_number);
+	ntfs_debug(DEBUG_FILE2, "load_attributes %x 1\n",ino->i_number);
X 	ntfs_insert_mft_attributes(ino,ino->attr,ino->i_number);
-	ntfs_debug(DEBUG_OTHER, "load_attributes %x 2\n",ino->i_number);
+	ntfs_debug(DEBUG_FILE2, "load_attributes %x 2\n",ino->i_number);
X 	alist=ntfs_find_attr(ino,vol->at_attribute_list,0);
-	ntfs_debug(DEBUG_OTHER, "load_attributes %x 3\n",ino->i_number);
+	ntfs_debug(DEBUG_FILE2, "load_attributes %x 3\n",ino->i_number);
X 	if(!alist)
X 		return;
-	ntfs_debug(DEBUG_OTHER, "load_attributes %x 4\n",ino->i_number);
+	ntfs_debug(DEBUG_FILE2, "load_attributes %x 4\n",ino->i_number);
X 	datasize=alist->size;
X 	if(alist->resident)
X 	{
@@ -255,7 +256,7 @@
X 			/* move remaining bytes to buffer start */
X 			ntfs_memmove(buf,buf+len-delta,delta);
X 	}
-	ntfs_debug(DEBUG_OTHER, "load_attributes %x 5\n",ino->i_number);
+	ntfs_debug(DEBUG_FILE2, "load_attributes %x 5\n",ino->i_number);
X 	ntfs_free(buf);
X }
X 	
@@ -264,7 +265,7 @@
X 	char *buf;
X 	int error;
X 
-	ntfs_debug(DEBUG_OTHER, "Initializing inode %x\n",inum);
+	ntfs_debug(DEBUG_FILE1, "Initializing inode %x\n",inum);
X 	if(!vol)
X 		ntfs_error("NO VOLUME!\n");
X 	ino->i_number=inum;
@@ -275,14 +276,14 @@
X 		ntfs_debug(DEBUG_OTHER, "init inode: %x failed\n",inum);
X 		return error;
X 	}
-	ntfs_debug(DEBUG_OTHER, "Init: got mft %x\n",inum);
+	ntfs_debug(DEBUG_FILE2, "Init: got mft %x\n",inum);
X 	ino->sequence_number=NTFS_GETU16(buf+0x10);
X 	ino->attr_count=0;
X 	ino->record_count=0;
X 	ino->records=0;
X 	ino->attrs=0;
X 	ntfs_load_attributes(ino);
-	ntfs_debug(DEBUG_OTHER, "Init: done %x\n",inum);
+	ntfs_debug(DEBUG_FILE2, "Init: done %x\n",inum);
X 	return 0;
X }
X 
@@ -391,40 +392,46 @@
X  * This function decodes a run. Length is an output parameter, data and cluster
X  * are in/out parameters.
X  */
-int ntfs_decompress_run(unsigned char **data, int *length, int *cluster,
+int ntfs_decompress_run(unsigned char **data, int *length, ntfs_cluster_t *cluster,
X 	int *ctype)
X {
X 	unsigned char type=*(*data)++;
X 	*ctype=0;
X 	switch(type & 0xF)
X 	{
-	case 1: *length=NTFS_GETU8(*data);(*data)++;break;
-	case 2: *length=NTFS_GETU16(*data);
-		*data+=2;
-		break;
-	case 3: *length = NTFS_GETU24(*data);
-		*data+=3;
-		break;
-		/* TODO: case 4-8 */
+	case 1: *length=NTFS_GETU8(*data);break;
+	case 2: *length=NTFS_GETU16(*data);break;
+	case 3: *length=NTFS_GETU24(*data);break;
+        case 4: *length=NTFS_GETU32(*data);break;
+        	/* Note: cases 5-8 are probably pointless to code,
+        	   since how many runs > 4GB of length are there?
+        	   at the most, cases 5 and 6 are probably necessary,
+        	   and would also require making length 64-bit
+        	   throughout */
X 	default:
X 		ntfs_error("Can't decode run type field %x\n",type);
X 		return -1;
X 	}
+	*data+=(type & 0xF);
+
X 	switch(type & 0xF0)
X 	{
-	case 0:    *ctype=2;break;
-	case 0x10: *cluster+=NTFS_GETS8(*data);(*data)++;break;
-	case 0x20: *cluster+=NTFS_GETS16(*data);
-		*data+=2;
-		break;
-	case 0x30: 	*cluster+=NTFS_GETS24(*data);
-		*data+=3;
-		break;
-		/* TODO: case 0x40-0x80 */
+	case 0:	   *ctype=2; break;
+	case 0x10: *cluster += NTFS_GETS8(*data);break;
+	case 0x20: *cluster += NTFS_GETS16(*data);break;
+	case 0x30: *cluster += NTFS_GETS24(*data);break;
+	case 0x40: *cluster += NTFS_GETS32(*data);break;
+#if 0 /* Keep for future, in case ntfs_cluster_t ever becomes 64bit */
+	case 0x50: *cluster += NTFS_GETS40(*data);break;
+	case 0x60: *cluster += NTFS_GETS48(*data);break;
+	case 0x70: *cluster += NTFS_GETS56(*data);break;
+	case 0x80: *cluster += NTFS_GETS64(*data);break;	
+#endif
X 	default:
X 		ntfs_error("Can't decode run type field %x\n",type);
X 		return -1;
X 	}
+	*data+=(type >> 4);
X 	return 0;
X }
X 
@@ -435,7 +442,8 @@
X 	ntfs_io *dest)
X {
X 	int datasize,rnum;
-	int cluster,s_cluster,vcn,len,l,chunk,copied;
+	ntfs_cluster_t cluster,s_cluster,vcn,len;
+	int l,chunk,copied;
X 	int s_vcn;
X 	int clustersize;
X 	int error;
@@ -443,6 +451,8 @@
X 	clustersize=ino->vol->clustersize;
X 	datasize=attr->size;
X 	l=dest->size;
+	if(l==0)
+		return 0;
X 	if(dest->do_read)
X 	{
X 		if(offset>=datasize){
@@ -457,20 +467,30 @@
X 			if(error)
X 				return error;
X 		}
+		if (offset+l > attr->initialized)
+			attr->initialized = offset+l;
X 	}
X 	if(attr->resident)
X 	{
X 		if(dest->do_read)
-			dest->fn_put(dest,attr->d.data+offset,l);
+			dest->fn_put(dest,(ntfs_u8*)attr->d.data+offset,l);
X 		else
-		{
-			dest->fn_get(attr->d.data+offset,dest,l);
-			ntfs_update_inode(ino);
-		}
+			dest->fn_get((ntfs_u8*)attr->d.data+offset,dest,l);
X 		dest->size=l;
X 		return 0;
X 	}
-	if(attr->compressed) {
+	/* read uninitialized data */
+	if(offset>=attr->initialized && dest->do_read)
+		return ntfs_read_zero(dest,l);
+	if(offset+l>attr->initialized && dest->do_read)
+	{
+		dest->size = chunk = offset+l - attr->initialized;
+		error = ntfs_readwrite_attr(ino,attr,offset,dest);
+		if(error)
+			return error;		
+		return ntfs_read_zero(dest,l-chunk);
+	}
+	if(attr->compressed){
X 		if(dest->do_read)
X 			return ntfs_read_compressed(ino,attr,offset,dest);
X 		else
@@ -544,17 +564,26 @@
X int ntfs_vcn_to_lcn(ntfs_inode *ino,int vcn)
X {
X 	int rnum;
-	ntfs_attribute *data=ntfs_find_attr(ino,ino->vol->at_data,0);
+	ntfs_attribute *data;
+	ntfs_error("bmap %x\n",vcn);
+	data=ntfs_find_attr(ino,ino->vol->at_data,0);
X 	/* It's hard to give an error code */
X 	if(!data)return -1;
X 	if(data->resident)return -1;
X 	if(data->compressed)return -1;
-	if(data->size<vcn*ino->vol->clustersize)return -1;
+	if(data->size <= vcn*ino->vol->clustersize)return -1;
+
+
+	/* For Linux, block number 0 represents a hole.
+	   Hopefully, nobody will attempt to bmap $Boot. */
+	if(data->initialized <= vcn*ino->vol->clustersize)
+		return 0;
X 
X 	for(rnum=0;rnum<data->d.r.len && 
X 		    vcn>data->d.r.runlist[rnum].len;rnum++)
X 		vcn-=data->d.r.runlist[rnum].len;
X 	
+	ntfs_error("result %x\n",data->d.r.runlist[rnum].cluster+vcn);
X 	return data->d.r.runlist[rnum].cluster+vcn;
X }
X 
@@ -599,7 +628,8 @@
X int 
X layout_runs(ntfs_attribute *attr,char* rec,int* offs,int size)
X {
-	int i,cluster,rclus,len,offset,coffs;
+	int i,len,offset,coffs;
+	ntfs_cluster_t cluster,rclus;
X 	ntfs_runlist *rl=attr->d.r.runlist;
X 	cluster=0;
X 	offset=*offs;
@@ -610,23 +640,21 @@
X 		if(offset+8>size)
X 			return E2BIG; /* it might still fit, but this simplifies testing */
X 		if(len<0x100){
-			*(rec+offset)|=1;
X 			NTFS_PUTU8(rec+offset+1,len);
-			coffs=2;
+			coffs=1;
X 		}else if(len<0x10000){
-			*(rec+offset)|=2;
X 			NTFS_PUTU16(rec+offset+1,len);
-			coffs=3;
+			coffs=2;
X 		}else if(len<0x1000000){
-			*(rec+offset)|=3;
X 			NTFS_PUTU24(rec+offset+1,len);
-			coffs=4;
+			coffs=3;
X 		}else{
-			*(rec+offset)|=4;
X 			NTFS_PUTU32(rec+offset+1,len);
-			coffs=5;
+			coffs=4;
X 		}
X     
+		*(rec+offset)|=coffs++;
+
X 		if(rl[i].cluster==0) /*compressed run*/
X 			/*nothing*/;
X 		else if(rclus>-0x80 && rclus<0x7F){
@@ -641,15 +669,42 @@
X 			*(rec+offset)|=0x30;
X 			NTFS_PUTS24(rec+offset+coffs,rclus);
X 			coffs+=3;
-		}else{
+		}else
+#if 0 /* In case ntfs_cluster_t ever becomes 64bit */
+	       	if (rclus>-0x80000000LL && rclus<0x7FFFFFFF)
+#endif
+		{
X 			*(rec+offset)|=0x40;
X 			NTFS_PUTS32(rec+offset+coffs,rclus);
X 			coffs+=4;
X 		}
+#if 0 /* For 64-bit ntfs_cluster_t */
+		else if (rclus>-0x8000000000 && rclus<0x7FFFFFFFFF){
+			*(rec+offset)|=0x50;
+			NTFS_PUTS40(rec+offset+coffs,rclus);
+			coffs+=5;
+		}else if (rclus>-0x800000000000 && rclus<0x7FFFFFFFFFFF){
+			*(rec+offset)|=0x60;
+			NTFS_PUTS48(rec+offset+coffs,rclus);
+			coffs+=6;
+		}else if (rclus>-0x80000000000000 && rclus<0x7FFFFFFFFFFFFF){
+			*(rec+offset)|=0x70;
+			NTFS_PUTS56(rec+offset+coffs,rclus);
+			coffs+=7;
+		}else{
+			*(rec+offset)|=0x80;
+			NTFS_PUTS64(rec+offset+coffs,rclus);
+			coffs+=8;
+		}
+#endif
X 		offset+=coffs;
X 		if(rl[i].cluster)
X 			cluster=rl[i].cluster;
X 	}
+	if(offset>=size)
+		return E2BIG;
+	/* terminating null */
+	*(rec+offset++)=0;
X 	*offs=offset;
X 	return 0;
X }
@@ -657,14 +712,14 @@
X static void 
X count_runs(ntfs_attribute *attr,char *buf)
X {
-	int first,count,last,i;
+	ntfs_u32 first,count,last,i;
X 	first=0;
X 	for(i=0,count=0;i<attr->d.r.len;i++)
X 		count+=attr->d.r.runlist[i].len;
X 	last=first+count-1;
X 
-	NTFS_PUTU32(buf+0x10,first);
-	NTFS_PUTU32(buf+0x18,last);
+	NTFS_PUTU64(buf+0x10,first);
+	NTFS_PUTU64(buf+0x18,last);
X } 
X 
X static int
@@ -814,8 +869,17 @@
X 	store.records=0;
X 	error=layout_inode(ino,&store);
X 	if(error==E2BIG){
+		error = ntfs_split_indexroot(ino);
+		if(!error)
+			error = layout_inode(ino,&store);
+	}
+	if(error == E2BIG){
+		error = ntfs_attr_allnonresident(ino);
+		if(!error)
+			error = layout_inode(ino,&store);
+	}
+	if(error == E2BIG){
X 		/* should try:
-		   make attributes non-resident
X 		   introduce extension records
X 		   */
X 		ntfs_error("cannot handle saving inode %x\n",ino->i_number);
@@ -844,7 +908,8 @@
X 		}
X 	}
X 	return 0;
-}
+}	
+
X 
X void ntfs_decompress(unsigned char *dest, unsigned char *src, ntfs_size_t l)
X {
@@ -1030,7 +1095,7 @@
X 
X static int 
X add_filename (ntfs_inode* ino, ntfs_inode* dir, 
-			 const unsigned char *filename, int length)
+	      const unsigned char *filename, int length, ntfs_u32 flags)
X {
X 	unsigned char   *position;
X 	unsigned int    size;
@@ -1057,7 +1122,7 @@
X 	NTFS_PUTU64(position + 0x20, now);		/* Last access */
X 
X 	/* Don't know */
-	NTFS_PUTU8(position+0x38, 0x0);  /*should match standard attributes*/
+	NTFS_PUTU32(position+0x38, flags);
X 
X 	NTFS_PUTU8(position + 0x40, length);	      /* Filename length */
X 	NTFS_PUTU8(position + 0x41, 0x0);	      /* only long name */
@@ -1120,10 +1185,9 @@
X 	return error;
X }
X 
-
X /* We _could_ use 'dir' to help optimise inode allocation */
-int ntfs_alloc_inode (ntfs_inode *dir, ntfs_inode *result, char *filename,
-		int namelen)
+int ntfs_alloc_inode (ntfs_inode *dir, ntfs_inode *result, 
+		      const char *filename, int namelen, ntfs_u32 flags)
X {
X 	ntfs_io io;
X 	int error;
@@ -1185,15 +1249,23 @@
X 	error=add_standard_information(result);
X 	if(error)
X 		return error;
-	error=add_filename(result,dir,filename,namelen);
+	error=add_filename(result,dir,filename,namelen,flags);
X 	if(error)
X 		return error;
X 	error=add_security(result,dir);
X 	/*FIXME: check error */
-	error=add_data(result,0,0);
+	return 0;
+}
+
+int
+ntfs_alloc_file(ntfs_inode *dir, ntfs_inode *result, char *filename,
+		int namelen)
+{
+	int error = ntfs_alloc_inode(dir,result,filename,namelen,0);
X 	if(error)
X 		return error;
-	return 0;
+	error = add_data(result,0,0);
+	return error;
X }
X 
X /*
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/inode.h linux/fs/ntfs/inode.h
--- v2.2.0-pre3/linux/fs/ntfs/inode.h	Fri Dec 19 15:24:21 1997
+++ linux/fs/ntfs/inode.h	Sat Jan  2 10:24:46 1999
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre4 failed'
fi
echo 'End of  part 2'
echo 'File patch-2.2.0-pre4 is continued in part 3'
echo 3 > _shar_seq_.tmp
#!/bin/sh
# this is part 3 of a 5 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre4'
else
echo 'x - continuing with patch-2.2.0-pre4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre4' &&
@@ -3,23 +3,26 @@
X  *  Header file for inode.c
X  *
X  *  Copyright (C) 1997 Régis Duchesne
+ *  Copyright (C) 1998 Martin von Löwis
X  */
X 
X ntfs_attribute *ntfs_find_attr(ntfs_inode *ino, int type, char *name);
X int ntfs_read_attr(ntfs_inode *ino, int type, char *name, int offset,
-  ntfs_io *buf);
+		   ntfs_io *buf);
X int ntfs_write_attr(ntfs_inode *ino, int type, char *name, int offset,
-  ntfs_io *buf);
+		    ntfs_io *buf);
X int ntfs_init_inode(ntfs_inode *ino,ntfs_volume *vol,int inum);
X void ntfs_clear_inode(ntfs_inode *ino);
X int ntfs_check_mft_record(ntfs_volume *vol,char *record);
-int ntfs_alloc_inode (ntfs_inode *dir, ntfs_inode *result, char *filename,
-  int namelen);
+int ntfs_alloc_inode (ntfs_inode *dir, ntfs_inode *result, 
+		      const char *filename, int namelen,ntfs_u32);
+int ntfs_alloc_file (ntfs_inode *dir, ntfs_inode *result, 
+		     char *filename, int namelen);
X int ntfs_update_inode(ntfs_inode *ino);
X int ntfs_vcn_to_lcn(ntfs_inode *ino, int vcn);
X int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, int offset,
-  ntfs_io *dest);
+			ntfs_io *dest);
X int ntfs_allocate_attr_number(ntfs_inode *ino, int *result);
-int ntfs_decompress_run(unsigned char **data, int *length, int *cluster,
- int *ctype);
+int ntfs_decompress_run(unsigned char **data, int *length, ntfs_cluster_t *cluster,
+			int *ctype);
X void ntfs_decompress(unsigned char *dest, unsigned char *src, ntfs_size_t l);
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/macros.h linux/fs/ntfs/macros.h
--- v2.2.0-pre3/linux/fs/ntfs/macros.h	Fri Dec 19 15:24:21 1997
+++ linux/fs/ntfs/macros.h	Sat Jan  2 10:24:46 1999
@@ -26,8 +26,10 @@
X #define NTFS_V2INO(ino)		((ntfs_inode*)((ino)->v_data))
X 
X /* Classical min and max macros still missing in standard headers... */
+#ifndef min
X #define min(a,b)	((a) <= (b) ? (a) : (b))
X #define max(a,b)	((a) >= (b) ? (a) : (b))
+#endif
X 
X #define IS_MAGIC(a,b)		(*(int*)(a)==*(int*)(b))
X #define IS_MFT_RECORD(a)	IS_MAGIC((a),"FILE")
@@ -36,6 +38,13 @@
X 
X /* 'NTFS' in little endian */
X #define NTFS_SUPER_MAGIC	0x5346544E
+
+#define NTFS_AFLAG_RO           1
+#define NTFS_AFLAG_HIDDEN       2
+#define NTFS_AFLAG_SYSTEM       4
+#define NTFS_AFLAG_ARCHIVE      20
+#define NTFS_AFLAG_COMPRESSED   0x800
+#define NTFS_AFLAG_DIR          0x10000000
X 
X /*
X  * Local variables:
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/ntfsendian.h linux/fs/ntfs/ntfsendian.h
--- v2.2.0-pre3/linux/fs/ntfs/ntfsendian.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/ntfs/ntfsendian.h	Sat Jan  2 10:24:46 1999
@@ -0,0 +1,86 @@
+/*
+ *  ntfsendian.h
+ *
+ *  Copyright (C) 1998 Martin von Löwis
+ *  Copyright (C) 1998 Joseph Malicki
+ */
+
+#ifdef __linux__
+/* This defines __cpu_to_le16 on Linux 2.1 and higher. */
+#include <asm/byteorder.h>
+#endif
+
+#ifdef __cpu_to_le16
+#define CPU_TO_LE16(a) __cpu_to_le16(a)
+#define CPU_TO_LE32(a) __cpu_to_le32(a)
+#define CPU_TO_LE64(a) __cpu_to_le64(a)
+
+#define LE16_TO_CPU(a) __cpu_to_le16(a)
+#define LE32_TO_CPU(a) __cpu_to_le32(a)
+#define LE64_TO_CPU(a) __cpu_to_le64(a)
+
+#else
+
+#ifdef __LITTLE_ENDIAN
+
+#define CPU_TO_LE16(a) (a)
+#define CPU_TO_LE32(a) (a)
+#define CPU_TO_LE64(a) (a)
+#define LE16_TO_CPU(a) (a)
+#define LE32_TO_CPU(a) (a)
+#define LE64_TO_CPU(a) (a)
+
+#else
+
+/* Routines for big-endian machines */
+#ifdef __BIG_ENDIAN
+
+/* We hope its big-endian, not PDP-endian :) */
+#define CPU_TO_LE16(a) ((((a)&0xF) << 8)|((a) >> 8))
+#define CPU_TO_LE32(a) ((((a) & 0xF) << 24) | (((a) & 0xF0) << 8) | \
+			(((a) & 0xF00) >> 8) | ((a) >> 24))
+#define CPU_TO_LE64(a) ((CPU_TO_LE32(a)<<32)|CPU_TO_LE32((a)>>32)
+
+#define LE16_TO_CPU(a) CPU_TO_LE16(a)
+#define LE32_TO_CPU(a) CPU_TO_LE32(a)
+#define LE64_TO_CPU(a) CPU_TO_LE64(a)
+
+#else
+
+#error Please define Endianness - __BIG_ENDIAN or __LITTLE_ENDIAN or add OS-specific macros
+
+#endif /* __BIG_ENDIAN */
+#endif /* __LITTLE_ENDIAN */
+#endif /* __cpu_to_le16 */
+
+#define NTFS_GETU8(p)      (*(ntfs_u8*)(p))
+#define NTFS_GETU16(p)     ((ntfs_u16)LE16_TO_CPU(*(ntfs_u16*)(p)))
+#define NTFS_GETU24(p)     (NTFS_GETU32(p) & 0xFFFFFF)
+#define NTFS_GETU32(p)     ((ntfs_u32)LE32_TO_CPU(*(ntfs_u32*)(p)))
+#define NTFS_GETU40(p)     ((ntfs_u64)NTFS_GETU32(p)|(((ntfs_u64)NTFS_GETU8(((char*)(p))+4))<<32))
+#define NTFS_GETU48(p)     ((ntfs_u64)NTFS_GETU32(p)|(((ntfs_u64)NTFS_GETU16(((char*)(p))+4))<<32))
+#define NTFS_GETU56(p)     ((ntfs_u64)NTFS_GETU32(p)|(((ntfs_u64)NTFS_GETU24(((char*)(p))+4))<<32))
+#define NTFS_GETU64(p)     ((ntfs_u64)LE64_TO_CPU(*(ntfs_u64*)(p)))
+ 
+ /* Macros writing unsigned integers */
+#define NTFS_PUTU8(p,v)      ((*(ntfs_u8*)(p))=(v))
+#define NTFS_PUTU16(p,v)     ((*(ntfs_u16*)(p))=CPU_TO_LE16(v))
+#define NTFS_PUTU24(p,v)     NTFS_PUTU16(p,(v) & 0xFFFF);\
+                             NTFS_PUTU8(((char*)(p))+2,(v)>>16)
+#define NTFS_PUTU32(p,v)     ((*(ntfs_u32*)(p))=CPU_TO_LE32(v))
+#define NTFS_PUTU64(p,v)     ((*(ntfs_u64*)(p))=CPU_TO_LE64(v))
+ 
+ /* Macros reading signed integers */
+#define NTFS_GETS8(p)        ((*(ntfs_u8*)(p)))
+#define NTFS_GETS16(p)       ((ntfs_s16)LE16_TO_CPU(*(short*)(p)))
+#define NTFS_GETS24(p)       (NTFS_GETU24(p) < 0x800000 ? (int)NTFS_GETU24(p) : (int)(NTFS_GETU24(p) - 0x1000000))
+#define NTFS_GETS32(p)       ((ntfs_s32)LE32_TO_CPU(*(int*)(p)))
+#define NTFS_GETS40(p)       (((ntfs_s64)NTFS_GETS32(p)) | (((ntfs_s64)NTFS_GETS8(((char*)(p))+4)) << 32))
+#define NTFS_GETS48(p)       (((ntfs_s64)NTFS_GETS32(p)) | (((ntfs_s64)NTFS_GETS16(((char*)(p))+4)) << 32))
+#define NTFS_GETS56(p)       (((ntfs_s64)NTFS_GETS32(p)) | (((ntfs_s64)NTFS_GETS24(((char*)(p))+4)) << 32))
+#define NTFS_GETS64(p)	     ((ntfs_s64)NTFS_GETU64(p))
+ 
+#define NTFS_PUTS8(p,v)      NTFS_PUTU8(p,v)
+#define NTFS_PUTS16(p,v)     NTFS_PUTU16(p,v)
+#define NTFS_PUTS24(p,v)     NTFS_PUTU24(p,v)
+#define NTFS_PUTS32(p,v)     NTFS_PUTU32(p,v)
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/ntfstypes.h linux/fs/ntfs/ntfstypes.h
--- v2.2.0-pre3/linux/fs/ntfs/ntfstypes.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/ntfs/ntfstypes.h	Sat Jan  2 10:24:46 1999
@@ -0,0 +1,90 @@
+/*
+ *  types.h
+ *  This file defines four things:
+ *   - generic platform independent fixed-size types (e.g. ntfs_u32)
+ *   - specific fixed-size types (e.g. ntfs_offset_t)
+ *   - macros that read and write those types from and to byte arrays
+ *   - types derived from OS specific ones
+ *
+ *  Copyright (C) 1996,1998 Martin von Löwis
+ */
+
+#ifdef NTFS_IN_LINUX_KERNEL
+/* get installed types if we compile the kernel*/
+#include <linux/fs.h>
+#endif
+
+/* We don't need to define __LITTLE_ENDIAN, as we use
+   <asm/byteorder>. */
+
+#include "ntfsendian.h"
+#include <asm/types.h>
+
+/* integral types */
+#ifndef NTFS_INTEGRAL_TYPES
+#define NTFS_INTEGRAL_TYPES
+typedef u8  ntfs_u8;
+typedef u16 ntfs_u16;
+typedef u32 ntfs_u32;
+typedef u64 ntfs_u64;
+typedef s8  ntfs_s8;
+typedef s16 ntfs_s16;
+typedef s32 ntfs_s32;
+typedef s64 ntfs_s64;
+#endif
+
+/* unicode character type */
+#ifndef NTFS_WCHAR_T
+#define NTFS_WCHAR_T
+typedef u16 ntfs_wchar_t;
+#endif
+/* file offset */
+#ifndef NTFS_OFFSET_T
+#define NTFS_OFFSET_T
+typedef u64 ntfs_offset_t;
+#endif
+/* UTC */
+#ifndef NTFS_TIME64_T
+#define NTFS_TIME64_T
+typedef u64 ntfs_time64_t;
+#endif
+/* This is really unsigned long long. So we support only volumes up to 2 TB */
+#ifndef NTFS_CLUSTER_T
+#define NTFS_CLUSTER_T
+typedef u32 ntfs_cluster_t;
+#endif
+
+/* architecture independent macros */
+
+/* PUTU32 would not clear all bytes */
+#define NTFS_PUTINUM(p,i)    NTFS_PUTU64(p,i->i_number);\
+                             NTFS_PUTU16(((char*)p)+6,i->sequence_number)
+
+/* system dependent types */
+#include <asm/posix_types.h>
+#ifndef NTMODE_T
+#define NTMODE_T
+typedef __kernel_mode_t ntmode_t;
+#endif
+#ifndef NTFS_UID_T
+#define NTFS_UID_T
+typedef __kernel_uid_t ntfs_uid_t;
+#endif
+#ifndef NTFS_GID_T
+#define NTFS_GID_T
+typedef __kernel_gid_t ntfs_gid_t;
+#endif
+#ifndef NTFS_SIZE_T
+#define NTFS_SIZE_T
+typedef __kernel_size_t ntfs_size_t;
+#endif
+#ifndef NTFS_TIME_T
+#define NTFS_TIME_T
+typedef __kernel_time_t ntfs_time_t;
+#endif
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/super.c linux/fs/ntfs/super.c
--- v2.2.0-pre3/linux/fs/ntfs/super.c	Fri Oct 23 22:01:22 1998
+++ linux/fs/ntfs/super.c	Sat Jan  2 10:24:46 1999
@@ -5,7 +5,7 @@
X  *  Copyright (C) 1996-1997 Régis Duchesne
X  */
X 
-#include "types.h"
+#include "ntfstypes.h"
X #include "struct.h"
X #include "super.h"
X 
@@ -32,7 +32,7 @@
X int ntfs_fixup_record(ntfs_volume *vol, char *record, char *magic, int size)
X {
X 	int start, count, offset;
-	unsigned short fixup;
+	ntfs_u16 fixup;
X 
X 	if(!IS_MAGIC(record,magic))
X 		return 0;
@@ -116,7 +116,7 @@
X 	upcase->vol->upcase_length = UPCASE_LENGTH;
X 	io.fn_put=ntfs_put;
X 	io.fn_get=0;
-	io.param=upcase->vol->upcase;
+	io.param=(char*)upcase->vol->upcase;
X 	io.size=2*UPCASE_LENGTH;
X 	ntfs_read_attr(upcase,upcase->vol->at_data,0,0,&io);
X }
@@ -152,8 +152,8 @@
X 	}else if(ntfs_ua_strncmp(name,"$BITMAP",64)==0){
X 		vol->at_bitmap=type;
X 		check_type=0xB0;
-	}else if(ntfs_ua_strncmp(name,"$SYMBOLIC_LINK",64) ||
-		 ntfs_ua_strncmp(name,"$REPARSE_POINT",64)){
+	}else if(ntfs_ua_strncmp(name,"$SYMBOLIC_LINK",64)==0 ||
+		 ntfs_ua_strncmp(name,"$REPARSE_POINT",64)==0){
X 		vol->at_symlink=type;
X 	}
X 	if(check_type && check_type!=type){
@@ -170,7 +170,7 @@
X 	ntfs_io io;
X 	int offset,error,i;
X 	ntfs_attribute *data;
-	buf=ntfs_malloc(4096);
+	buf=ntfs_malloc(4050); /* 90*45 */
X 	if(!buf)return ENOMEM;
X 	io.fn_put=ntfs_put;
X 	io.fn_get=ntfs_get;
@@ -183,9 +183,9 @@
X 	}
X 	do{
X 		io.param=buf;
-		io.size=4096;
+		io.size=4050;
X 		error=ntfs_readwrite_attr(attrdef,data,offset,&io);
-		for(i=0;!error && i<io.size;i+=0xA0)
+		for(i=0;!error && i<io.size-0xA0;i+=0xA0)
X 			error=process_attrdef(attrdef,buf+i);
X 		offset+=4096;
X 	}while(!error && io.size);
@@ -200,25 +200,30 @@
X 
X 	vol->mft_ino=(ntfs_inode*)ntfs_calloc(3*sizeof(ntfs_inode));
X 	error=ENOMEM;
+	ntfs_debug(DEBUG_BSD,"Going to load MFT\n");
X 	if(!vol->mft_ino || (error=ntfs_init_inode(vol->mft_ino,vol,FILE_MFT)))
X 	{
X 		ntfs_error("Problem loading MFT\n");
X 		return error;
X 	}
+	ntfs_debug(DEBUG_BSD,"Going to load MIRR\n");
X 	vol->mftmirr=vol->mft_ino+1;
X 	if((error=ntfs_init_inode(vol->mftmirr,vol,FILE_MFTMIRR))){
X 		ntfs_error("Problem %d loading MFTMirr\n",error);
X 		return error;
X 	}
+	ntfs_debug(DEBUG_BSD,"Going to load BITMAP\n");
X 	vol->bitmap=vol->mft_ino+2;
X 	if((error=ntfs_init_inode(vol->bitmap,vol,FILE_BITMAP))){
X 		ntfs_error("Problem loading Bitmap\n");
X 		return error;
X 	}
+	ntfs_debug(DEBUG_BSD,"Going to load UPCASE\n");
X 	error=ntfs_init_inode(&upcase,vol,FILE_UPCASE);
X 	if(error)return error;
X 	ntfs_init_upcase(&upcase);
X 	ntfs_clear_inode(&upcase);
+	ntfs_debug(DEBUG_BSD,"Going to load ATTRDEF\n");
X 	error=ntfs_init_inode(&attrdef,vol,FILE_ATTRDEF);
X 	if(error)return error;
X 	error=ntfs_init_attrdef(&attrdef);
@@ -245,7 +250,7 @@
X {
X 	ntfs_io io;
X 	char *cluster0=ntfs_malloc(vol->clustersize);
-	int size;
+	ntfs_u64 size;
X 
X 	io.fn_put=ntfs_put;
X 	io.fn_get=ntfs_get;
@@ -255,8 +260,9 @@
X 	ntfs_getput_clusters(vol,0,0,&io);
X 	size=NTFS_GETU64(cluster0+0x28);
X 	ntfs_free(cluster0);
-	size/=vol->clusterfactor;
-	return size;
+	/* FIXME: more than 2**32 cluster */
+	/* FIXME: gcc will emit udivdi3 if we don't truncate it */
+	return ((unsigned int)size)/vol->clusterfactor;
X }
X 
X static int nc[16]={4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0};
@@ -323,7 +329,7 @@
X    Return the largest block found in *cnt. Return 0 on success, ENOSPC if
X    all bits are used */
X static int 
-search_bits(unsigned char* bits,int *loc,int *cnt,int l)
+search_bits(unsigned char* bits,ntfs_cluster_t *loc,int *cnt,int l)
X {
X 	unsigned char c=0;
X 	int bc=0;
@@ -384,7 +390,7 @@
X }
X 
X int 
-ntfs_set_bitrange(ntfs_inode* bitmap,int loc,int cnt,int bit)
+ntfs_set_bitrange(ntfs_inode* bitmap,ntfs_cluster_t loc,int cnt,int bit)
X {
X 	int bsize,locit,error;
X 	unsigned char *bits,*it;
@@ -392,13 +398,13 @@
X 
X 	io.fn_put=ntfs_put;
X 	io.fn_get=ntfs_get;
-	bsize=(cnt+loc%8+7)/8; /* round up */
+	bsize=(cnt+(loc & 7)+7) & ~7; /* round up to multiple of 8*/
X 	bits=ntfs_malloc(bsize);
X 	io.param=bits;
X 	io.size=bsize;
X 	if(!bits)
X 		return ENOMEM;
-	error=ntfs_read_attr(bitmap,bitmap->vol->at_data,0,loc/8,&io);
+	error=ntfs_read_attr(bitmap,bitmap->vol->at_data,0,loc>>3,&io);
X 	if(error || io.size!=bsize){
X 		ntfs_free(bits);
X 		return error?error:EIO;
@@ -431,7 +437,7 @@
X 	/* reset to start */
X 	io.param=bits;
X 	io.size=bsize;
-	error=ntfs_write_attr(bitmap,bitmap->vol->at_data,0,loc/8,&io);
+	error=ntfs_write_attr(bitmap,bitmap->vol->at_data,0,loc>>3,&io);
X 	ntfs_free(bits);
X 	if(error)return error;
X 	if(io.size!=bsize)
@@ -445,7 +451,7 @@
X    it does not matter where the clusters are. Result is 0 if
X    success, in which case location and count says what they really got */
X int 
-ntfs_search_bits(ntfs_inode* bitmap, int *location, int *count, int flags)
+ntfs_search_bits(ntfs_inode* bitmap, ntfs_cluster_t *location, int *count, int flags)
X {
X 	unsigned char *bits;
X 	ntfs_io io;
@@ -459,7 +465,7 @@
X 	io.param=bits;
X 
X 	/* first search within +/- 8192 clusters */
-	start=*location/8;
+	start=*location>>3;
X 	start= start>1024 ? start-1024 : 0;
X 	io.size=2048;
X 	error=ntfs_read_attr(bitmap,bitmap->vol->at_data,0,start,&io);
@@ -483,7 +489,7 @@
X 		error=ntfs_read_attr(bitmap,bitmap->vol->at_data,
X 				     0,start,&io);
X 		if(error)goto fail;
-		if(io.size==0) {
+		if(io.size==0){
X 			if(found)
X 				goto success;
X 			else{
@@ -524,7 +530,7 @@
X 	return error;
X }
X 
-int ntfs_allocate_clusters(ntfs_volume *vol, int *location, int *count,
+int ntfs_allocate_clusters(ntfs_volume *vol, ntfs_cluster_t *location, int *count,
X 	int flags)
X {
X 	int error;
@@ -532,7 +538,7 @@
X 	return error;
X }
X 
-int ntfs_deallocate_clusters(ntfs_volume *vol, int location, int count)
+int ntfs_deallocate_clusters(ntfs_volume *vol, ntfs_cluster_t location, int count)
X {
X 	int error;
X 	error=ntfs_set_bitrange(vol->bitmap,location,count,0);
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/super.h linux/fs/ntfs/super.h
--- v2.2.0-pre3/linux/fs/ntfs/super.h	Fri Dec 19 15:24:21 1997
+++ linux/fs/ntfs/super.h	Sat Jan  2 10:24:46 1999
@@ -16,6 +16,6 @@
X int ntfs_release_volume(ntfs_volume *vol);
X void ntfs_insert_fixups(unsigned char *rec, int secsize);
X int ntfs_fixup_record(ntfs_volume *vol, char *record, char *magic, int size);
-int ntfs_allocate_clusters(ntfs_volume *vol, int *location, int *count,
+int ntfs_allocate_clusters(ntfs_volume *vol, ntfs_cluster_t *location, int *count,
X   int flags);
-int ntfs_deallocate_clusters(ntfs_volume *vol, int location, int count);
+int ntfs_deallocate_clusters(ntfs_volume *vol, ntfs_cluster_t location, int count);
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/support.c linux/fs/ntfs/support.c
--- v2.2.0-pre3/linux/fs/ntfs/support.c	Wed Jun 24 22:54:10 1998
+++ linux/fs/ntfs/support.c	Sat Jan  2 10:24:46 1999
@@ -7,7 +7,10 @@
X  *
X  */
X 
-#include "types.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "ntfstypes.h"
X #include "struct.h"
X #include "support.h"
X 
@@ -86,17 +89,20 @@
X 	memset(s, 0, n);
X }
X 
-void *ntfs_memcpy(void *dest, const void *src, ntfs_size_t n)
+/* These functions deliberately return no value. It is dest, anyway,
+   and not used anywhere in the NTFS code.  */
+
+void ntfs_memcpy(void *dest, const void *src, ntfs_size_t n)
X {
-	return memcpy(dest, src, n);
+	memcpy(dest, src, n);
X }
X 
-void *ntfs_memmove(void *dest, const void *src, ntfs_size_t n)
+void ntfs_memmove(void *dest, const void *src, ntfs_size_t n)
X {
-	return memmove(dest, src, n);
+	memmove(dest, src, n);
X }
X 
-/* Warn that an error occurred. */
+/* Warn that an error occured. */
X void ntfs_error(const char *fmt,...)
X {
X         va_list ap;
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/support.h linux/fs/ntfs/support.h
--- v2.2.0-pre3/linux/fs/ntfs/support.h	Fri Jan  2 01:42:59 1998
+++ linux/fs/ntfs/support.h	Sat Jan  2 10:24:46 1999
@@ -8,6 +8,16 @@
X /* Debug levels */
X #define DEBUG_OTHER	1
X #define DEBUG_MALLOC	2
+#define DEBUG_BSD       4
+#define DEBUG_LINUX     8
+#define DEBUG_DIR1     16
+#define DEBUG_DIR2     32
+#define DEBUG_DIR3     64
+#define DEBUG_FILE1   128
+#define DEBUG_FILE2   256
+#define DEBUG_FILE3   512
+#define DEBUG_NAME1  1024
+#define DEBUG_NAME2  2048
X 
X void ntfs_debug(int mask, const char *fmt, ...);
X #ifdef NTFS_IN_LINUX_KERNEL
@@ -19,8 +29,8 @@
X void ntfs_free(void *block);
X #endif
X void ntfs_bzero(void *s, int n);
-void *ntfs_memcpy(void *dest, const void *src, ntfs_size_t n);
-void *ntfs_memmove(void *dest, const void *src, ntfs_size_t n);
+void ntfs_memcpy(void *dest, const void *src, ntfs_size_t n);
+void ntfs_memmove(void *dest, const void *src, ntfs_size_t n);
X void ntfs_error(const char *fmt,...);
X int ntfs_read_mft_record(ntfs_volume *vol, int mftno, char *buf);
X int ntfs_getput_clusters(ntfs_volume *pvol, int cluster, ntfs_size_t offs,
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/sysctl.h linux/fs/ntfs/sysctl.h
--- v2.2.0-pre3/linux/fs/ntfs/sysctl.h	Fri Dec 19 15:24:21 1997
+++ linux/fs/ntfs/sysctl.h	Sat Jan  2 10:24:46 1999
@@ -7,6 +7,10 @@
X  *
X  */
X 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
X #ifdef DEBUG
X extern int ntdebug;
X 
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/types.h linux/fs/ntfs/types.h
--- v2.2.0-pre3/linux/fs/ntfs/types.h	Wed Apr  1 20:11:53 1998
+++ linux/fs/ntfs/types.h	Wed Dec 31 16:00:00 1969
@@ -1,128 +0,0 @@
-/*
- *  types.h
- *  This file defines four things:
- *   - generic platform independent fixed-size types (e.g. ntfs_u32)
- *   - specific fixed-size types (e.g. ntfs_offset_t)
- *   - macros that read and write those types from and to byte arrays
- *   - types derived from OS specific ones
- *
- *  Copyright (C) 1996 Martin von Löwis
- */
-
-#ifdef NTFS_IN_LINUX_KERNEL
-/* get installed types if we compile the kernel*/
-#include <linux/fs.h>
-#endif
-
-#if defined(i386) || defined(__i386__) || defined(__alpha__)
-
-/* unsigned integral types */
-#ifndef NTFS_INTEGRAL_TYPES
-#define NTFS_INTEGRAL_TYPES
-typedef unsigned char      ntfs_u8;
-typedef unsigned short     ntfs_u16;
-typedef unsigned int       ntfs_u32;
-typedef unsigned long long ntfs_u64;
-#endif
-
-/* unicode character type */
-#ifndef NTFS_WCHAR_T
-#define NTFS_WCHAR_T
-typedef unsigned short     ntfs_wchar_t;
-#endif
-/* file offset */
-#ifndef NTFS_OFFSET_T
-#define NTFS_OFFSET_T
-typedef unsigned long long ntfs_offset_t;
-#endif
-/* UTC */
-#ifndef NTFS_TIME64_T
-#define NTFS_TIME64_T
-typedef unsigned long long ntfs_time64_t;
-#endif
-/* This is really unsigned long long. So we support only volumes up to 2 TB */
-#ifndef NTFS_CLUSTER_T
-#define NTFS_CLUSTER_T
-typedef unsigned int ntfs_cluster_t;
-#endif
-
-/* Macros reading unsigned integers from a byte pointer */
-/* these should work for all little endian machines */
-#define NTFS_GETU8(p)      (*(ntfs_u8*)(p))
-#define NTFS_GETU16(p)     (*(ntfs_u16*)(p))
-#define NTFS_GETU24(p)     (NTFS_GETU32(p) & 0xFFFFFF)
-#define NTFS_GETU32(p)     (*(ntfs_u32*)(p))
-#define NTFS_GETU64(p)     (*(ntfs_u64*)(p))
-
-/* Macros writing unsigned integers */
-#define NTFS_PUTU8(p,v)      (*(ntfs_u8*)(p))=(v)
-#define NTFS_PUTU16(p,v)     (*(ntfs_u16*)(p))=(v)
-#define NTFS_PUTU24(p,v)     NTFS_PUTU16(p,(v) & 0xFFFF);\
-                             NTFS_PUTU8(((char*)p)+2,(v)>>16)
-#define NTFS_PUTU32(p,v)     (*(ntfs_u32*)(p))=(v)
-#define NTFS_PUTU64(p,v)     (*(ntfs_u64*)(p))=(v)
-
-/* Macros reading signed integers, returning int */
-#define NTFS_GETS8(p)        ((int)(*(char*)(p)))
-#define NTFS_GETS16(p)       ((int)(*(short*)(p)))
-#define NTFS_GETS24(p)       (NTFS_GETU24(p) < 0x800000 ? (int)NTFS_GETU24(p) : (int)(NTFS_GETU24(p) | 0xFF000000))
-
-#define NTFS_PUTS8(p,v)      NTFS_PUTU8(p,v)
-#define NTFS_PUTS16(p,v)     NTFS_PUTU16(p,v)
-#define NTFS_PUTS24(p,v)     NTFS_PUTU24(p,v)
-#define NTFS_PUTS32(p,v)     NTFS_PUTU32(p,v)
-
-#else
-#error Put your machine description here
-#endif
-
-/* architecture independent macros */
-
-/* PUTU32 would not clear all bytes */
-#define NTFS_PUTINUM(p,i)    NTFS_PUTU64(p,i->i_number);\
-                             NTFS_PUTU16(((char*)p)+6,i->sequence_number)
-
-/* system dependent types */
-#ifdef __linux__
-/* We always need kernel types, because glibc makes them of different size */
-#include <asm/posix_types.h>
-/* Avoid a type redefinition with future include of glibc <stdlib.h> */
-#undef __FD_ZERO
-#undef __FD_SET
-#undef __FD_CLR
-#undef __FD_ISSET
-#ifndef NTMODE_T
-#define NTMODE_T
-typedef __kernel_mode_t ntmode_t;
-#endif
-#ifndef NTFS_UID_T
-#define NTFS_UID_T
-typedef __kernel_uid_t ntfs_uid_t;
-#endif
-#ifndef NTFS_GID_T
-#define NTFS_GID_T
-typedef __kernel_gid_t ntfs_gid_t;
-#endif
-#ifndef NTFS_SIZE_T
-#define NTFS_SIZE_T
-typedef __kernel_size_t ntfs_size_t;
-#endif
-#ifndef NTFS_TIME_T
-#define NTFS_TIME_T
-typedef __kernel_time_t ntfs_time_t;
-#endif
-#else
-#include <sys/types.h>
-#include <sys/stat.h>
-typedef mode_t ntmode_t;
-typedef uid_t ntfs_uid_t;
-typedef gid_t ntfs_gid_t;
-typedef size_t ntfs_size_t;
-typedef time_t ntfs_time_t;
-#endif
-
-/*
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/util.c linux/fs/ntfs/util.c
--- v2.2.0-pre3/linux/fs/ntfs/util.c	Fri Oct 23 22:01:22 1998
+++ linux/fs/ntfs/util.c	Sat Jan  2 10:24:46 1999
@@ -2,13 +2,13 @@
X  *  util.c
X  *  Miscellaneous support
X  *
- *  Copyright (C) 1997 Martin von Löwis
+ *  Copyright (C) 1997,1999 Martin von Löwis
X  *  Copyright (C) 1997 Régis Duchesne
X  *
- *  The utf8 routines are copied from Python wstrop module,
+ *  The utf8 routines are copied from Python wstrop module.
X  */
X 
-#include "types.h"
+#include "ntfstypes.h"
X #include "struct.h"
X #include "util.h"
X 
@@ -20,6 +20,7 @@
X #include "support.h"
X 
X /* Converts a single wide character to a sequence of utf8 bytes.
+ * The character is represented in host byte order.
X  * Returns the number of bytes, or 0 on error.
X  */
X static int
@@ -28,7 +29,7 @@
X 	if(c==0)
X 		return 0; /* No support for embedded 0 runes */
X 	if(c<0x80){
-		if(buf)buf[0]=c;
+		if(buf)buf[0]=(unsigned char)c;
X 		return 1;
X 	}
X 	if(c<0x800){
@@ -51,7 +52,8 @@
X }
X 
X /* Decodes a sequence of utf8 bytes into a single wide character.
- * Returns the number of bytes consumed, or 0 on error
+ * The character is returned in host byte order.
+ * Returns the number of bytes consumed, or 0 on error.
X  */
X static int
X from_utf8(const unsigned char* str,ntfs_u16 *c)
@@ -98,10 +100,10 @@
X 	int len8;
X 	unsigned char *result;
X 
-	ntfs_debug(DEBUG_OTHER,"converting l=%d\n",in_len);
+	ntfs_debug(DEBUG_NAME1,"converting l=%d\n",in_len);
X 	/* count the length of the resulting UTF-8 */
X 	for(i=len8=0;i<in_len;i++){
-		tmp=to_utf8(in[i],0);
+		tmp=to_utf8(NTFS_GETU16(in+i),0);
X 		if(!tmp)
X 			/* invalid character */
X 			return EILSEQ;
@@ -114,7 +116,8 @@
X 	result[len8]='\0';
X 	*out_len=len8;
X 	for(i=len8=0;i<in_len;i++)
-		len8+=to_utf8(in[i],result+len8);
+		len8+=to_utf8(NTFS_GETU16(in+i),result+len8);
+	ntfs_debug(DEBUG_NAME1,"result %p:%s\n",result,result);
X 	return 0;
X }
X 
@@ -139,7 +142,10 @@
X 	result[len16]=0;
X 	*out_len=len16;
X 	for(i=len16=0;i<in_len;i+=tmp,len16++)
-		tmp=from_utf8(in+i,result+len16);
+	{
+		tmp=from_utf8(in+i, &wtmp);
+		NTFS_PUTU16(result+len16, wtmp);
+	}
X 	return 0;
X }
X 
@@ -151,7 +157,7 @@
X 
X 	/* check for characters out of range */
X 	for(i=0;i<in_len;i++)
-		if(in[i]>=256)
+		if(NTFS_GETU16(in+i)>=256)
X 			return EILSEQ;
X 	*out=result=ntfs_malloc(in_len+1);
X 	if(!result)
@@ -159,7 +165,7 @@
X 	result[in_len]='\0';
X 	*out_len=in_len;
X 	for(i=0;i<in_len;i++)
-		result[i]=in[i];
+		result[i]=(unsigned char)NTFS_GETU16(in+i);
X 	return 0;
X }
X 
@@ -174,7 +180,7 @@
X 		return ENOMEM;
X 	*out_len=in_len;
X 	for(i=0;i<in_len;i++)
-		result[i]=in[i];
+		NTFS_PUTU16(result+i,in[i]);
X 	return 0;
X }
X 
@@ -210,19 +216,18 @@
X void ntfs_put(ntfs_io *dest,void *src,ntfs_size_t n)
X {
X 	ntfs_memcpy(dest->param,src,n);
-	dest->param+=n;
+	((char*)dest->param)+=n;
X }
X 
X void ntfs_get(void* dest,ntfs_io *src,ntfs_size_t n)
X {
X 	ntfs_memcpy(dest,src->param,n);
-	src->param+=n;
+	((char*)src->param)+=n;
X }
X 
X void *ntfs_calloc(int size)
X {
X 	void *result=ntfs_malloc(size);
-
X 	if(result)
X 		ntfs_bzero(result,size);
X 	return result;
@@ -272,9 +277,9 @@
X 
X 	for(i=0;i<n;i++)
X 	{
-		if(a[i]<b[i])
+		if(NTFS_GETU16(a+i)<b[i])
X 			return -1;
-		if(b[i]<a[i])
+		if(b[i]<NTFS_GETU16(a+i))
X 			return 1;
X 	}
X 	return 0;
@@ -292,7 +297,7 @@
X  * 3: Floating point math in the kernel would corrupt user data
X  */
X 	const unsigned int D = 10000000;
-	unsigned int H = (ntutc >> 32);
+	unsigned int H = (unsigned int)(ntutc >> 32);
X 	unsigned int L = (unsigned int)ntutc;
X 	unsigned int numerator2;
X 	unsigned int lowseconds;
@@ -334,6 +339,25 @@
X ntfs_time64_t ntfs_unixutc2ntutc(ntfs_time_t t)
X {
X 	return ((t + (ntfs_time64_t)(369*365+89)*24*3600) * 10000000);
+}
+
+/* Fill index name. */
+
+void
+ntfs_indexname(char *buf, int type)
+{
+	char hex[]="0123456789ABCDEF";
+	int index;
+	*buf++='$';
+	*buf++='I';
+	for (index=24; index>0; index-=4)
+		if((0xF << index) & type)
+			break;
+	while(index>=0) {
+		*buf++ = hex[(type >> index) & 0xF];
+		index-=4;
+	}
+	*buf='\0';
X }
X 
X /*
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/ntfs/util.h linux/fs/ntfs/util.h
--- v2.2.0-pre3/linux/fs/ntfs/util.h	Fri Dec 19 15:24:21 1997
+++ linux/fs/ntfs/util.h	Sat Jan  2 10:24:46 1999
@@ -56,6 +56,9 @@
X ntfs_time_t ntfs_ntutc2unixutc(ntfs_time64_t ntutc);
X ntfs_time64_t ntfs_unixutc2ntutc(ntfs_time_t t);
X 
+/* Attribute names */
+void ntfs_indexname(char *buf, int type);
+
X /*
X  * Local variables:
X  * c-file-style: "linux"
diff -u --recursive --new-file v2.2.0-pre3/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.2.0-pre3/linux/fs/proc/procfs_syms.c	Fri Oct 23 22:01:22 1998
+++ linux/fs/proc/procfs_syms.c	Sat Jan  2 17:55:06 1999
@@ -23,7 +23,6 @@
X EXPORT_SYMBOL(proc_root);
X EXPORT_SYMBOL(proc_root_fs);
X EXPORT_SYMBOL(proc_get_inode);
-EXPORT_SYMBOL(in_group_p);
X EXPORT_SYMBOL(proc_dir_inode_operations);
X EXPORT_SYMBOL(proc_net_inode_operations);
X EXPORT_SYMBOL(proc_net);
diff -u --recursive --new-file v2.2.0-pre3/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.2.0-pre3/linux/include/linux/fs.h	Fri Jan  1 12:58:21 1999
+++ linux/include/linux/fs.h	Sat Jan  2 19:09:50 1999
@@ -254,10 +254,15 @@
X /*
X  * Deprecated - we don't keep per-buffer reference flags
X  * any more.
+ *
+ * We _could_ try to update the page reference, but that
+ * doesn't seem to really be worth it either. If we did,
+ * it would look something like this:
+ *
+ *	#define buffer_page(bh)		(mem_map + MAP_NR((bh)->b_data))
+ *	#define touch_buffer(bh)	set_bit(PG_referenced, &buffer_page(bh)->flags)
X  */
-#define buffer_page(bh)		(mem_map + MAP_NR((bh)->b_data))
-#define buffer_touched(bh)	(PageReferenced(buffer_page(bh)))
-#define touch_buffer(bh)	set_bit(PG_referenced, buffer_page(bh))
+#define touch_buffer(bh)	do { } while (0)
X 
X #include <linux/pipe_fs_i.h>
X #include <linux/minix_fs_i.h>
diff -u --recursive --new-file v2.2.0-pre3/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.2.0-pre3/linux/include/linux/pci.h	Thu Dec 31 10:29:03 1998
+++ linux/include/linux/pci.h	Sat Jan  2 18:11:22 1999
@@ -1057,6 +1057,7 @@
X #define PCI_DEVICE_ID_ADAPTEC2_2940U2	0x0010
X #define PCI_DEVICE_ID_ADAPTEC2_7890	0x001f
X #define PCI_DEVICE_ID_ADAPTEC2_3940U2	0x0050
+#define PCI_DEVICE_ID_ADAPTEC2_3950U2D	0x0051
X #define PCI_DEVICE_ID_ADAPTEC2_7896	0x005f
X 
X #define PCI_VENDOR_ID_ATRONICS		0x907f
diff -u --recursive --new-file v2.2.0-pre3/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.2.0-pre3/linux/include/linux/proc_fs.h	Tue Dec 22 14:16:58 1998
+++ linux/include/linux/proc_fs.h	Sat Jan  2 17:55:06 1999
@@ -297,6 +297,8 @@
X extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
X 				off_t offset, int length, int inout);
X 
+#ifdef CONFIG_PROC_FS
+
X extern struct proc_dir_entry proc_root;
X extern struct proc_dir_entry proc_root_fs;
X extern struct proc_dir_entry *proc_net;
@@ -436,4 +438,26 @@
X  */
X extern void proc_device_tree_init(void);
X 
+#else
+
+extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) {};
+extern inline int proc_unregister(struct proc_dir_entry *a, int b) {};
+extern inline int proc_net_register(struct proc_dir_entry *a) {};
+extern inline int proc_net_unregister(int x) {};
+extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) {};
+extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x);
+
+extern inline struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
+					 struct proc_dir_entry *parent)
+{
+	return NULL;
+}
+
+extern inline void remove_proc_entry(const char *name, struct proc_dir_entry *parent) {};
+
+extern inline void proc_tty_register_driver(struct tty_driver *driver) {};
+extern inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
+
+
+#endif
X #endif /* _LINUX_PROC_FS_H */
diff -u --recursive --new-file v2.2.0-pre3/linux/include/linux/sunrpc/stats.h linux/include/linux/sunrpc/stats.h
--- v2.2.0-pre3/linux/include/linux/sunrpc/stats.h	Fri Jul 31 17:09:54 1998
+++ linux/include/linux/sunrpc/stats.h	Sat Jan  2 17:55:06 1999
@@ -44,6 +44,7 @@
X void			rpc_modcount(struct inode *, int);
X #endif
X 
+#ifdef CONFIG_PROC_FS
X struct proc_dir_entry *	rpc_proc_register(struct rpc_stat *);
X void			rpc_proc_unregister(const char *);
X int			rpc_proc_read(char *, char **, off_t, int,
@@ -54,5 +55,19 @@
X int			svc_proc_read(char *, char **, off_t, int,
X 					int *, void *);
X void			svc_proc_zero(struct svc_program *);
+
+#else
+
+extern inline void svc_proc_unregister(const char *p) {}
+extern inline struct proc_dir_entry*svc_proc_register(struct svc_stat *s)
+{
+	return NULL;
+}
+
+extern inline int svc_proc_read(char *a, char **b, off_t c, int d, int *e, void *f)
+{
+	return 0;
+}
+#endif
X 
X #endif /* _LINUX_SUNRPC_STATS_H */
diff -u --recursive --new-file v2.2.0-pre3/linux/include/linux/swapctl.h linux/include/linux/swapctl.h
--- v2.2.0-pre3/linux/include/linux/swapctl.h	Tue Dec 22 14:16:58 1998
+++ linux/include/linux/swapctl.h	Fri Jan  1 22:31:21 1999
@@ -90,18 +90,6 @@
X #define PAGE_DECLINE		(swap_control.sc_page_decline)
X #define PAGE_INITIAL_AGE	(swap_control.sc_page_initial_age)
X 
-/* Given a resource of N units (pages or buffers etc), we only try to
- * age and reclaim AGE_CLUSTER_FRACT per 1024 resources each time we
- * scan the resource list. */
-static inline int AGE_CLUSTER_SIZE(int resources)
-{
-	unsigned int n = (resources * AGE_CLUSTER_FRACT) >> 10;
-	if (n < AGE_CLUSTER_MIN)
-		return AGE_CLUSTER_MIN;
-	else
-		return n;
-}
-
X #endif /* __KERNEL */
X 
X #endif /* _LINUX_SWAPCTL_H */
diff -u --recursive --new-file v2.2.0-pre3/linux/ipc/util.c linux/ipc/util.c
--- v2.2.0-pre3/linux/ipc/util.c	Fri Nov 27 13:09:29 1998
+++ linux/ipc/util.c	Sat Jan  2 10:22:36 1999
@@ -12,7 +12,8 @@
X #include <linux/mm.h>
X #include <linux/shm.h>
X #include <linux/init.h>
-
+#include <linux/msg.h>
+#include <asm/ipc.h>
X #include <asm/uaccess.h>
X 
X #if defined(CONFIG_SYSVIPC)
diff -u --recursive --new-file v2.2.0-pre3/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.2.0-pre3/linux/mm/page_alloc.c	Fri Jan  1 12:58:21 1999
+++ linux/mm/page_alloc.c	Sat Jan  2 19:02:16 1999
@@ -151,6 +151,7 @@
X 	if (!PageReserved(page) && atomic_dec_and_test(&page->count)) {
X 		if (PageSwapCache(page))
X 			panic ("Freeing swap cache page");
+		page->flags &= ~(1 << PG_referenced);
X 		free_pages_ok(page->map_nr, 0);
X 		return;
X 	}
@@ -172,6 +173,7 @@
X 		if (atomic_dec_and_test(&map->count)) {
X 			if (PageSwapCache(map))
X 				panic ("Freeing swap cache pages");
+			map->flags &= ~(1 << PG_referenced);
X 			free_pages_ok(map_nr, order);
X 			return;
X 		}
@@ -197,8 +199,9 @@
X 	do { struct page *prev = memory_head(area), *ret = prev->next; \
X 		while (memory_head(area) != ret) { \
X 			if (!dma || CAN_DMA(ret)) { \
-				unsigned long map_nr = ret->map_nr; \
+				unsigned long map_nr; \
X 				(prev->next = ret->next)->prev = prev; \
+				map_nr = ret->map_nr; \
X 				MARK_USED(map_nr, new_order, area); \
X 				nr_free_pages -= 1 << order; \
X 				EXPAND(ret, map_nr, order, new_order, area); \
diff -u --recursive --new-file v2.2.0-pre3/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.2.0-pre3/linux/mm/vmscan.c	Fri Jan  1 12:58:21 1999
+++ linux/mm/vmscan.c	Fri Jan  1 22:41:58 1999
@@ -363,13 +363,23 @@
X 	/* 
X 	 * We make one or two passes through the task list, indexed by 
X 	 * assign = {0, 1}:
-	 *   Pass 1: select the swappable task with maximal swap_cnt.
-	 *   Pass 2: assign new swap_cnt values, then select as above.
+	 *   Pass 1: select the swappable task with maximal RSS that has
+	 *         not yet been swapped out. 
+	 *   Pass 2: re-assign rss swap_cnt values, then select as above.
+	 *
X 	 * With this approach, there's no need to remember the last task
X 	 * swapped out.  If the swap-out fails, we clear swap_cnt so the 
X 	 * task won't be selected again until all others have been tried.
+	 *
+	 * Think of swap_cnt as a "shadow rss" - it tells us which process
+	 * we want to page out (always try largest first).
X 	 */
-	counter = ((PAGEOUT_WEIGHT * nr_tasks) >> 10) >> priority;
+	counter = nr_tasks / (priority+1);
+	if (counter < 1)
+		counter = 1;
+	if (counter > nr_tasks)
+		counter = nr_tasks;
+
X 	for (; counter >= 0; counter--) {
X 		assign = 0;
X 		max_cnt = 0;
@@ -382,15 +392,9 @@
X 				continue;
X 	 		if (p->mm->rss <= 0)
X 				continue;
-			if (assign) {
-				/* 
-				 * If we didn't select a task on pass 1, 
-				 * assign each task a new swap_cnt.
-				 * Normalise the number of pages swapped
-				 * by multiplying by (RSS / 1MB)
-				 */
-				p->swap_cnt = AGE_CLUSTER_SIZE(p->mm->rss);
-			}
+			/* Refresh swap_cnt? */
+			if (assign)
+				p->swap_cnt = p->mm->rss;
X 			if (p->swap_cnt > max_cnt) {
X 				max_cnt = p->swap_cnt;
X 				pbest = p;
@@ -404,14 +408,13 @@
X 			}
X 			goto out;
X 		}
-		pbest->swap_cnt--;
X 
X 		/*
X 		 * Nonzero means we cleared out something, but only "1" means
X 		 * that we actually free'd up a page as a result.
X 		 */
X 		if (swap_out_process(pbest, gfp_mask) == 1)
-				return 1;
+			return 1;
X 	}
X out:
X 	return 0;
@@ -451,19 +454,17 @@
X 	/* max one hundreth of a second */
X 	end_time = jiffies + (HZ-1)/100;
X 	do {
-		int priority = 5;
+		int priority = 8;
X 		int count = pager_daemon.swap_cluster;
X 
X 		switch (kswapd_state) {
X 			do {
X 			default:
X 				free_memory(shrink_mmap(priority, 0));
+				free_memory(swap_out(priority, 0));
X 				kswapd_state++;
X 			case 1:
X 				free_memory(shm_swap(priority, 0));
-				kswapd_state++;
-			case 2:
-				free_memory(swap_out(priority, 0));
X 				shrink_dcache_memory(priority, 0);
X 				kswapd_state = 0;
X 			} while (--priority >= 0);
@@ -562,7 +563,7 @@
X 
X 		current->flags |= PF_MEMALLOC;
X 	
-		priority = 5;
+		priority = 8;
X 		do {
X 			free_memory(shrink_mmap(priority, gfp_mask));
X 			free_memory(shm_swap(priority, gfp_mask));
diff -u --recursive --new-file v2.2.0-pre3/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.2.0-pre3/linux/net/sunrpc/sched.c	Thu Dec 31 10:29:03 1998
+++ linux/net/sunrpc/sched.c	Sat Jan  2 17:55:06 1999
@@ -6,7 +6,6 @@
X  * Copyright (C) 1996 Olaf Kirch, <ok...@monad.swb.de>
X  */
X 
-#define __NO_VERSION__
X #include <linux/module.h>
X 
X #define __KERNEL_SYSCALLS__
diff -u --recursive --new-file v2.2.0-pre3/linux/net/sunrpc/stats.c linux/net/sunrpc/stats.c
--- v2.2.0-pre3/linux/net/sunrpc/stats.c	Mon Jan 12 14:39:07 1998
+++ linux/net/sunrpc/stats.c	Sat Jan  2 17:55:06 1999
@@ -12,6 +12,7 @@
X  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <ok...@monad.swb.de>
X  */
X 
+#define __NO_VERSION__
X #include <linux/module.h>
X 
X #include <linux/kernel.h>
diff -u --recursive --new-file v2.2.0-pre3/linux/net/sunrpc/sysctl.c linux/net/sunrpc/sysctl.c
--- v2.2.0-pre3/linux/net/sunrpc/sysctl.c	Mon Jan 12 19:43:21 1998
+++ linux/net/sunrpc/sysctl.c	Sat Jan  2 17:55:06 1999
@@ -38,8 +38,10 @@
X 	if (!sunrpc_table_header) {
X 		sunrpc_table_header = register_sysctl_table(sunrpc_table, 1);
X #ifdef MODULE
+#ifdef CONFIG_PROC_FS
X 		if (sunrpc_table[0].de)
X 			sunrpc_table[0].de->fill_inode = rpc_modcount;
+#endif
X #endif
X 	}
X 			
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/header.tk linux/scripts/header.tk
--- v2.2.0-pre3/linux/scripts/header.tk	Wed Jun 24 22:54:14 1998
+++ linux/scripts/header.tk	Sat Jan  2 10:29:11 1999
@@ -145,7 +145,7 @@
X 			 -relief raised 
X 		label $w.bm -bitmap error
X 		pack $w.bm $w.m -pady 10 -side top -padx 10
-		wm title $w "Oops" 
+		wm title $w "Xconfig Internal Error" 
X 
X 		set oldFocus [focus]
X 		frame $w.f
@@ -173,7 +173,7 @@
X 			 -relief raised 
X 		label $w.bm -bitmap error
X 		pack $w.bm $w.m -pady 10 -side top -padx 10
-		wm title $w "Oops" 
+		wm title $w "Xconfig Internal Error" 
X 
X 		set oldFocus [focus]
X 		frame $w.f
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/Makefile linux/scripts/ksymoops-0.6/Makefile
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/Makefile	Mon Nov  2 07:46:47 1998
@@ -0,0 +1,72 @@
+# Description file for ksymoops
+
+#	Tue Nov  3 02:31:01 EST 1998
+#	Version 0.6
+#	Read lsmod (/proc/modules).
+#	Add Makefile defaults for vmlinux, ksyms, objects, System.map, lsmod.
+#	Upper case variables.
+#	Convert from a.out to bfd, using same format as ksymoops.
+
+DEFS = Makefile ksymoops.h
+
+# Defaults for vmlinux, ksyms, objects, lsmod, System.map.  Externalised so
+# distributions can tweak to suit their own file system layout.
+
+# To default to not reading a source, set to any empty string.
+# To default to reading a source, supply a quoted and escaped string.
+
+# If the string contains *r (*m, *n, *s) then it is replaced at run time by
+# the current value of `uname -r` (-m, -n, -s).  '*' was chosen as something
+# that rarely appears in filenames and does not cause problems like '%' or '$'.
+
+DEF_VMLINUX =				# default no vmlinux
+DEF_OBJECTS = \"/lib/modules/*r/\"	# default current modules
+DEF_KSYMS = \"/proc/ksyms\"		# default current ksyms
+DEF_LSMOD = \"/proc/modules\"		# default current lsmod
+DEF_MAP = \"/usr/src/linux/System.map\"	# default current map
+
+# RedHat users might want defaults like these
+# DEF_MAP = \"/boot/System.map-*r\"
+# DEF_OBJECTS = \"/boot/module-info-*r\"
+
+PROGS = ksymoops
+
+CC=gcc
+CFLAGS = -Dlinux \
+	 -Wall \
+	 -Wno-conversion \
+	 -Waggregate-return \
+	 -Wstrict-prototypes \
+	 -Wmissing-prototypes \
+	 $(DEBUG)
+
+ifneq ($(strip $(DEF_VMLINUX)),)
+	CFLAGS += -DDEF_VMLINUX=$(strip $(DEF_VMLINUX))
+endif
+ifneq ($(strip $(DEF_OBJECTS)),)
+	CFLAGS += -DDEF_OBJECTS=$(strip $(DEF_OBJECTS))
+endif
+ifneq ($(strip $(DEF_KSYMS)),)
+	CFLAGS += -DDEF_KSYMS=$(strip $(DEF_KSYMS))
+endif
+ifneq ($(strip $(DEF_LSMOD)),)
+	CFLAGS += -DDEF_LSMOD=$(strip $(DEF_LSMOD))
+endif
+ifneq ($(strip $(DEF_MAP)),)
+	CFLAGS += -DDEF_MAP=$(strip $(DEF_MAP))
+endif
+
+OBJECTS = io.o ksyms.o ksymoops.o map.o misc.o object.o oops.o re.o symbol.o
+
+all: 	$(PROGS)
+
+:	$(OBJECTS)
+
+$(OBJECTS): $(DEFS)
+
+$(PROGS): %: %.o $(DEFS) $(OBJECTS)
+	$(CC) $(OBJECTS) $(CFLAGS) -lbfd -liberty -o $@
+	-@size $@
+
+clean:
+	rm -f core *.o $(PROGS)
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/README linux/scripts/ksymoops-0.6/README
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/README	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/README	Mon Nov  2 07:43:43 1998
@@ -0,0 +1,358 @@
+  ksymoops.
+
+  Read a kernel Oops file and make the best stab at converting the code to
+  instructions and mapping stack values to kernel symbols.
+
+  Copyright Keith Owens <ka...@ocs.com.au>.
+  Released under the GNU Public Licence, Version 2.
+
+  To compile, simply type "make" in the ksymoops directory.
+
+  TESTERS WANTED.
+
+  ksymoops handles ix86.  It appears to handle Alpha, Sparc, M68K, PPC,
+  MIPS but I have no machine to test on.  I would appreciate feedback
+  from users of non ix86 machines.  In particular, it would be nice if
+  you could run
+
+   ksymoops -VMO -k /proc/ksyms -dd <oops.file >/tmp/ksymoops.log 2>&1
+
+  and mail /tmp/ksymoops.log to ka...@ocs.com.au
+
+  The patches subdirectory contains some arch specific patches to
+  provide more info on their Oops reports.  At the moment (2.1.126),
+  some archs do not print traces or do not print code lines, makes it
+  impossible to report properly.
+
+  TODO:
+  Performance improvements.  Reading a large log is quite slow, probably
+	  one of the Oops regular expressions is pathological.
+  Clean up these docs.
+  Add "guess", "same" options, distinguish between default and supplied
+  values on report (Andries, I get the message :).
+
+  Tue Nov  3 02:31:01 EST 1998
+  Version 0.6
+  Read lsmod (/proc/modules).
+
+  Wed Oct 28 23:14:55 EST 1998
+  Version 0.5
+  No longer read vmlinux by default, it only duplicates System.map.
+
+  Wed Oct 28 13:46:39 EST 1998
+  Version 0.4
+  Split into separate sources.
+
+  Mon Oct 26 00:01:47 EST 1998
+  Version 0.3c
+  Add alpha (arm) processing.
+
+  Mon Oct 26 00:01:47 EST 1998
+  Version 0.3b
+  Add sparc processing.
+  Handle kernel symbol versions.
+
+  Fri Oct 23 13:11:20 EST 1998
+  Version 0.3
+  Add -follow to find command for people who use symlinks to modules.
+  Add Version_ checking.
+
+  Thu Oct 22 22:28:30 EST 1998
+  Version 0.2.
+  Generalise text prefix handling.
+  Handle messages on Code: line.
+  Format addresses with leading zeroes.
+  Minor bug fixes.
+
+  Wed Oct 21 23:28:48 EST 1998
+  Version 0.1.  Rewrite from scratch in C.
+
+  CREDITS.
+  Oops disassembly based on ksymoops.cc,
+    Copyright (C) 1995 Greg McGary <g...@magilla.cichlid.com>
+  m68k code based on ksymoops.cc changes by
+    Andreas Schwab <sch...@issan.informatik.uni-dortmund.de>
+
+  This code subsumes the Perl script make_System.map.pl which is no longer
+  supported.
+
+  Why another ksymoops I hear you ask?  Various complaints about
+  ksymoops.cc -
+
+  * It requires C++.
+  * It has hard wired limitations on the number of symbols.
+  * It does not handle modules at all.
+  * Very rigid requirements on the format of input, especially the Oops
+    log.
+  * No cross checking between ksyms, modules, System.map etc.
+  * Very little error checking, diagnostics are not suitable for
+    beginners.
+  * It only prints the trace and decoded code, users have to manually
+    extract the other lines from the Oops.
+  * Gives up on the slightest problem.
+  * Only handles i386 and possibly m68k.  The code is difficult to extend
+    to other architectures.
+  * Stops after the first Oops, you have to manually extract each one and
+    run through ksymoops one at a time.
+
+  This version is -
+  * C.
+  * No hard wired limitations (malloc as far as the eye can see).
+  * Handles modules by default.
+  * Uses regular pattern matching so it is a lot more forgiving about
+    input formats.
+  * By default, cross checks ksyms, modules, System.map and vmlinux.
+  * Lots of diagnostics and error checking.
+  * Prints all relevant lines for a complete Oops report.
+  * Tries to provide output no matter how bad the input is.  The level of
+     progress and error reporting is aimed at beginners.
+  * Handles i386, alpha, sparc, m68k.  It is a lot easier to extend to
+    other architectures (patches and/or sample data gratefully accepted).
+  * Handles all Oops in the input file(s).
+
+
+  Usage:	ksymoops
+		  [-v vmlinux]	Where to read vmlinux
+		  [-V]		No vmlinux is available
+		  [-o object_dir]	Directory containing modules
+		  [-O]		No modules is available
+		  [-k ksyms]	Where to read ksyms
+		  [-K]		No ksyms is available
+		  [-l lsmod]	Where to read lsmod
+		  [-L]		No lsmod is available
+		  [-m system.map]	Where to read System.map
+		  [-M]		No System.map is available
+		  [-s save.map]	Save consolidated map
+		  [-d]		Increase debug level by 1
+		  [-h]		Print help text
+		  Oops.file	Oops to decode
+
+	  All flags can occur more than once.  With the exception of -o
+	  and -d which are cumulative, the last occurrence of each flag is
+	  used.  Note that "-v my.vmlinux -V" will be taken as "No vmlinux
+	  available" but "-V -v my.vmlinux" will read my.vmlinux.  You
+	  will be warned about such combinations.
+
+	  Each occurrence of -d increases the debug level.
+
+	  Each -o flag can refer to a directory or to a single object
+	  file.  If a directory is specified then all *.o files in that
+	  directory and its subdirectories are assumed to be modules.
+
+	  If any of the vmlinux, object_dir, ksyms or system.map options
+	  contain the string *r (*m, *n, *s) then it is replaced at run time
+	  by the current value of `uname -r` (-m, -n, -s).
+
+	  The defaults can be changed in the Makefile, typical options are
+
+	  Defaults:	  -V
+			  -o /lib/modules/%r
+			  -k /proc/ksyms
+			  -l /proc/modules
+			  -m /usr/src/linux/System.map
+			  Oops report is read from stdin
+
+  Note:	  Unless you tell ksymoops *NOT* to read a particular file, it
+	  will try to read and reconcile almost all possible sources of kernel
+	  symbol information.  This is intended for beginners, they just
+	  type
+
+	    ksymoops < /var/log/syslog
+
+	  no thinking required.  Experts can point at different files or
+	  suppress the input from selected files.  For example, if you
+	  save /proc/ksyms before doing a test that creates an Oops, you
+	  can point ksymoops at the saved ksyms instead of using
+	  /proc/ksyms.
+
+	  vmlinux is not read by default, it only duplicates the
+	  information in System.map.  If you want to read vmlinux as well
+	  as or instead of System.map, use -v.
+
+	  To get the equivalent of the old ksymoops.cc (no vmlinux, no
+	  modules objects, no ksyms, no System.map) just do ksymoops
+	  -VOKLM.  Or to just read System.map, ksymoops -VOKL -m mapfile.
+
+
+  WARNING:  The user interface will change slightly in 0.7, users will
+            have to give some indication of the state of their
+            environment.  Otherwise it may be too easy to pick the
+            wrong input files.
+
+  Return codes:	0 - normal.
+		  1 - error(s) or warning(s) issued, results may not be
+		      reliable.
+		  2 - fatal error, no useful results.
+
+  Supported architectures
+
+	  i386 tested.
+          m68k code derived from ksymoops.cc and reading traps.c, untested.
+	  MIPS tested.
+	  Sparc tested.
+	  Alpha tested.
+
+	  The term "eip" is generic, for example it includes the i386 EIP
+	  and the m68k PC.  Remember that objdump output always says EIP,
+	  no matter what the architecture, see objfile_head.
+
+	  To support another arch, check the Oops_ procedures between
+	  'Start architecture sensitive code' and 'End architecture
+	  sensitive code'.
+
+	  The pattern matching should take care of different lengths for
+	  the address, i.e. addresses should not be arch sensitive.  I
+	  assume that all addresses are at least 4 characters.
+
+	  If nm output has a different format on your arch, check for uses
+	  of re_nm.
+
+
+
+  Because ksymoops reads kernel information from multiple sources, there
+  could be mismatches.  ksymoops does the following cross checks, but only
+  if the specified files exist -
+
+  * Compare Version_nnn numbers from all sources against each other.  Pity
+    that only vmlinux and System.map have these symbols (as at 2.1.125),
+    however I check ksyms, modules and Oops as well.  If somebody adds
+    symbol Version_nnn to ksyms or modules or adds a Version_nnn line to
+    the Oops log, this code is ready.
+
+  * Compare kernel ksyms against vmlinux.  vmlinux takes precedence.
+
+  * Compare System.map against vmlinux.   vmlinux takes precedence.
+
+  * Compare vmlinux against System.map.   vmlinux takes precedence.
+
+  * Compare kernel ksyms against System.map.  System.map takes precedence.
+
+  * Compare modules against module ksyms.  modules take precedence.  Only
+    if at least one module appears in ksyms.
+
+  * Compare module names in ksyms against lsmod.  Warn if a module
+    appears in lsmod but not in ksyms.  Error if a modules appears in
+    ksyms but is not in lsmod.  Only if both ksyms and lsmod have being
+    read.
+
+  The precedence order is somewhat arbitrary, however it only applies if
+  there is any difference between the various sources.
+
+  Handling modules is awkward.  They can be loaded under different names
+  (insmod -o dummy1 dummy.o) and the text, data and read only data are
+  loaded at different offsets.  Although you can give the -m option to
+  insmod which will output the module map when it is loaded, this has a
+  few problems -
+
+  * No equivalent for removing a module.  If you load and remove a lot of
+    modules, you end up with multiple sets of symbols around the same
+    offsets, which set is correct?
+
+  * "insmod -o dummy1 dummy.o" still reports as dummy.  That is, there is
+     no way of telling which particular version of a multiply loaded
+     module the insmod output refers to.  Therefore there is no way of
+     telling which instantiation failed.
+
+  * Even if the above problems are fixed, how do you tell what the module
+    environment looked like when the Oops occurred?  What if a module is
+    loaded or removed just after Oops, how is the user expected to edit
+    the insmod log?  Rule 1 - make ksymoops easy for beginners.
+
+  Although those problems could be fixed, they require changes to
+  modutils.  Working from ksyms and the module objects can be done without
+  changing modutils and without confusing beginners.
+  
+  Alas the ksyms plus object approach has another problem - matching ksyms
+  to module objects.  Nowhere does the kernel say that module dummy1 came
+  from module /lib/modules/2.1.215/net/dummy.o, ksyms just says dummy1.  I
+  have to match ksyms to the relevant object by finding a globally unique
+  external symbol in each module that can be used to map to the external
+  symbols in ksyms.  This assumes that each module exports at least one
+  text symbol that is unique amongst all modules.
+
+  It may not be possible to correctly map other sections such as data and
+  readonly data for modules because they may not have exported symbols.
+  Since the main aim of ksymoops is to map a code Oops, this should not be
+  a problem.
+
+  Unfortunately some modules export no symbols.  They are marked as
+  EXPORT_NO_SYMBOLS are simply do not export anything.  It is
+  impossible to detect these in ksyms because, by definition, ksyms
+  only contains exported symbols for modules.  Since all modules appear
+  in lsmod (/proc/modules), a cross check of lsmod against the module
+  names will find loaded modules with no symbols, at least I can warn
+  about these.
+
+  After merging the various sources, ksymoops has a (hopefully) accurate
+  map including modules.  The -s option lets you save the merged
+  System.map, but remember that module data and readonly data sections may
+  not be correctly relocated, see above.
+
+  Environment Variables.
+  KSYMOOPS_NM		path for nm, defaults to /usr/bin/nm.
+  KSYMOOPS_FIND		path for find, defaults to /usr/bin/find.
+  KSYMOOPS_OBJDUMP	path for objdump, defaults to /usr/bin/objdump.
+
+
+  Input Oops data.
+
+  The ideal input is to feed the syslog straight into this program.  If
+  you cannot do that, you need to know what the program looks for.
+  Especially if you are typing in the Oops by hand :(.  All input is case
+  insensitive.
+
+  * White space in this context means space or tab.  It does not include
+    newline.
+
+  * Oops in syslog has a syslog prefix.  Leading text up to and including
+    ' kernel: ' is always ignored, there is no need to edit syslog first.
+    This leading text need not exist but if it does, it must end in
+    ' kernel: '.
+
+  * An alternative prefix is <n> where n is the kernel print level.  Also
+    ignored if present.
+
+  * Leading white space is treated as a prefix and ignored, the input is
+    not indentation sensitive.
+
+  * In the following paragraphs, assume that any prefixes have been
+    skipped.  If there is more than one prefix, all are skipped, no matter
+    which order they appear in.
+
+  * A bracketed address is optional '[', required '<', at least 4 hex
+    digits, required '>', optional ']'.  For example [<01234567>] or
+    <1234>.
+
+  * The ix86 EIP line is identified by optional white space followed by
+    'EIP:', followed by a least one white space, followed by a bracketed
+    address.
+
+  * The m68k PC line is identified by optional white space followed by
+    'PC', optionally followed by white space, followed by '=', optionally
+    followed by white space, followed by a bracketed address.
+
+  * The sparc PC line starts with PSR and PC is the second hex value, not
+    bracketed.
+
+  * A call trace line is identified by 'Call Trace:' followed by at least
+    one white space.  Or it is a line starting with a bracketed address,
+    but only if the previous line was a call trace line (I hate multi line
+    output that relies on identation for recognition, especially when
+    lines can have a variable prefix).
+
+  * The Code line is identified by 'Code:' followed by a least one white
+    space character followed by at least one hex value.  The line can
+    contain multiple hex values, each separated by at least one white
+    space.  Each hex value must be 2 to 8 digits and must be a multiple of
+    2 digits.
+
+    Special cases where Code: can be followed by text.
+      'Code: general protection'
+      'Code: <n>'
+    Dump the data anyway, the code was unavailable.
+
+  * Formatted data is only output when the Code: line is seen.  If any
+    data has been stored and more than 5 lines other than Oops text (see
+    Oops_print) or end of file are encountered then ksymoops assumes that
+    the Code: line is missing or garbled and dumps the formatted data
+    anyway.  Fail safe, I hope.
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/io.c linux/scripts/ksymoops-0.6/io.c
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/io.c	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/io.c	Mon Nov  2 07:32:55 1998
@@ -0,0 +1,139 @@
+/*
+	io.c.
+
+	Local I/O routines for ksymoops.
+
+	Copyright Keith Owens <ka...@ocs.com.au>.
+	Released under the GNU Public Licence, Version 2.
+
+	Tue Nov  3 02:31:01 EST 1998
+	Version 0.6
+	fwrite_local is redundant, replaced by bfd.
+
+	Wed Oct 28 13:47:23 EST 1998
+	Version 0.4
+	Split into separate sources.
+
+ */
+
+#include "ksymoops.h"
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <sys/stat.h>
+
+int regular_file(const char *file, const char *msg)
+{
+	struct stat statbuf;
+	if (stat(file, &statbuf)) {
+		fprintf(stderr, "%s: %s stat %s failed",
+			prefix, msg, file);
+		perror(" ");
+		++errors;
+		return 0;
+	}
+
+	if (!S_ISREG(statbuf.st_mode)) {
+		fprintf(stderr,
+			"%s: %s %s is not a regular file, ignored\n",
+			prefix, msg, file);
+		++errors;
+		return 0;
+	}
+	return 1;
+}
+
+FILE *fopen_local(const char *file, const char *mode, const char *msg)
+{
+	FILE *f;
+	if (!(f = fopen(file, mode))) {
+		fprintf(stderr, "%s: %s fopen '%s' failed",
+			prefix, msg, file);
+		perror(" ");
+		++errors;
+	}
+	return f;
+}
+
+void fclose_local(FILE *f, const char *msg)
+{
+	int i;
+	if ((i = fclose(f))) {
+		fprintf(stderr, "%s: %s fclose failed %d", prefix, msg, i);
+		perror(" ");
+		++errors;
+	}
+}
+
+/* Read a line, increasing the size of the line as necessary until \n is read */
+#define INCREMENT 10	/* arbitrary */
+char *fgets_local(char **line, int *size, FILE *f, const char *msg)
+{
+	char *l, *p, *r;
+	int longline = 1;
+
+	if (!*line) {
+		*size = INCREMENT;
+		*line = malloc(*size);
+		if (!*line)
+			malloc_error("fgets_local alloc line");
+	}
+
+	l = *line;
+	while (longline) {
+		r = fgets(l, *size-(l-*line), f);
+		if (!r) {
+			if (ferror(f)) {
+				fprintf(stderr,
+					"%s: %s fgets failed", prefix, msg);
+				perror(" ");
+				++errors;
+			}
+			if (l != *line)
+				return(*line);
+			else
+				return(r);
+		}
+		if (!(p = strchr(*line, '\n'))) {
+			*size += INCREMENT;
+			*line = realloc(*line, *size);
+			if (!*line)
+				malloc_error("fgets_local realloc line");
+			l = *line+*size-INCREMENT-1;
+		}
+		else {
+			*p = '\0';
+			longline = 0;
+		}
+	}
+
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s line '%s'\n", msg, *line);
+	return(*line);
+}
+
+FILE *popen_local(const char *cmd, const char *msg)
+{
+	FILE *f;
+	if (!(f = popen(cmd, "r"))) {
+		fprintf(stderr, "%s: %s popen '%s' failed",
+			prefix, msg, cmd);
+		perror(" ");
+		++errors;
+	}
+	return f;
+}
+
+void pclose_local(FILE *f, const char *msg)
+{
+	int i;
+	errno = 0;
+	if ((i = pclose(f))) {
+		fprintf(stderr, "%s: %s pclose failed 0x%x", prefix, msg, i);
+		if (errno)
+			perror(" ");
+		else
+			fprintf(stderr, "\n");
+		++errors;
+	}
+}
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/ksymoops.c linux/scripts/ksymoops-0.6/ksymoops.c
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/ksymoops.c	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/ksymoops.c	Mon Nov  2 07:46:24 1998
@@ -0,0 +1,569 @@
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre4 failed'
fi
echo 'End of  part 3'
echo 'File patch-2.2.0-pre4 is continued in part 4'
echo 4 > _shar_seq_.tmp
#!/bin/sh
# this is part 4 of a 5 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 4; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre4'
else
echo 'x - continuing with patch-2.2.0-pre4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre4' &&
+/*
+	ksymoops.c.
+
+	Read a kernel Oops file and make the best stab at converting the code to
+	instructions and mapping stack values to kernel symbols.
+
+	Copyright Keith Owens <ka...@ocs.com.au>.
+	Released under the GNU Public Licence, Version 2.
+*/
+
+#define VERSION "0.6"
+
+/*
+
+	Tue Nov  3 02:31:01 EST 1998
+	Version 0.6
+	Read lsmod (/proc/modules).
+	Ignore addresses 0-4095 when mapping address to symbol.
+	Discard default objects if -o specified.
+	Oops file must be regular.
+	Add "invalid operand" to Oops_print.
+	Move "Using_Version" copy to map.c.
+	Add Makefile defaults for vmlinux, ksyms, objects, System.map, lsmod.
+	Minor adjustment to re for ppc.
+	Minor adjustment to re for objdump lines with <_EIP+xxx>.
+	Convert from a.out to bfd, using same format as ksymoops.
+	Added MIPS.
+	PPC handling based on patches by "Ryan Nielsen" <r...@krazynet.com>
+
+	Wed Oct 28 23:14:55 EST 1998
+	Version 0.5
+	No longer read vmlinux by default, it only duplicates System.map.
+
+ Wed Oct 28 13:47:38 EST 1998
+ */
+
+#include "ksymoops.h"
+#include <ctype.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+char *prefix;
+char *path_nm = "/usr/bin/nm";			/* env KSYMOOPS_NM */
+char *path_find = "/usr/bin/find";		/* env KSYMOOPS_FIND */
+char *path_objdump = "/usr/bin/objdump";	/* env KSYMOOPS_OBJDUMP */
+int debug = 0;
+int errors = 0;
+int warnings = 0;
+
+SYMBOL_SET  ss_vmlinux;
+SYMBOL_SET  ss_ksyms_base;
+SYMBOL_SET *ss_ksyms_module;
+int         ss_ksyms_modules;
+SYMBOL_SET  ss_lsmod;
+SYMBOL_SET *ss_object;
+int         ss_objects;
+SYMBOL_SET  ss_system_map;
+
+SYMBOL_SET  ss_merged;   /* merged map with info from all sources */
+SYMBOL_SET  ss_Version;  /* Version_ numbers where available */
+
+/* Regular expression stuff */
+
+regex_t     re_nm;
+regmatch_t *re_nm_pmatch;
+regex_t     re_bracketed_address;
+regmatch_t *re_bracketed_address_pmatch;
+regex_t     re_unbracketed_address;
+regmatch_t *re_unbracketed_address_pmatch;
+
+static void usage(void)
+{
+	fprintf(stderr, "Version " VERSION "\n");
+	fprintf(stderr, "usage: %s\n", prefix);
+	fprintf(stderr,
+		"\t\t[-v vmlinux]\tWhere to read vmlinux\n"
+		"\t\t[-V]\t\tNo vmlinux is available\n"
+		"\t\t[-o object_dir]\tDirectory containing modules\n"
+		"\t\t[-O]\t\tNo modules is available\n"
+		"\t\t[-k ksyms]\tWhere to read ksyms\n"
+		"\t\t[-K]\t\tNo ksyms is available\n"
+		"\t\t[-l lsmod]\tWhere to read lsmod\n"
+		"\t\t[-L]\t\tNo lsmod is available\n"
+		"\t\t[-m system.map]\tWhere to read System.map\n"
+		"\t\t[-M]\t\tNo System.map is available\n"
+		"\t\t[-s save.map]\tSave consolidated map\n"
+		"\t\t[-d]\t\tIncrease debug level by 1\n"
+		"\t\t[-h]\t\tPrint help text\n"
+		"\t\t<Oops.file\tOops report to decode\n"
+		"\n"
+		"\t\tAll flags can occur more than once.  With the exception "
+			"of -o\n"
+		"\t\tand -d which are cumulative, the last occurrence of each "
+			"flag is\n"
+		"\t\tused.  Note that \"-v my.vmlinux -V\" will be taken as "
+			"\"No vmlinux\n"
+		"\t\tavailable\" but \"-V -v my.vmlinux\" will read "
+			"my.vmlinux.  You\n"
+		"\t\twill be warned about such combinations.\n"
+		"\n"
+		"\t\tEach occurrence of -d increases the debug level.\n"
+		"\n"
+		"\t\tEach -o flag can refer to a directory or to a single "
+			"object\n"
+		"\t\tfile.  If a directory is specified then all *.o files in "
+			"that\n"
+		"\t\tdirectory and its subdirectories are assumed to be "
+			"modules.\n"
+		"\n"
+		"\t\tIf any of the vmlinux, object_dir, ksyms or system.map "
+		"options\n"
+		"\t\tcontain the string *r (*m, *n, *s) then it is replaced "
+		"at run\n"
+		"\t\ttime by the current value of `uname -r` (-m, -n, -s).\n"
+		"\n"
+		"\t\tThe defaults can be changed in the Makefile, current "
+		"defaults\n"
+		"\t\tare\n\n"
+		"\t\t\t"
+#ifdef DEF_VMLINUX
+		"-v " DEF_LINUX
+#else
+		"-V"
+#endif
+		"\n"
+		"\t\t\t"
+#ifdef DEF_OBJECTS
+		"-o " DEF_OBJECTS
+#else
+		"-O"
+#endif
+		"\n"
+		"\t\t\t"
+#ifdef DEF_KSYMS
+		"-k " DEF_KSYMS
+#else
+		"-K"
+#endif
+		"\n"
+		"\t\t\t"
+#ifdef DEF_LSMOD
+		"-l " DEF_LSMOD
+#else
+		"-L"
+#endif
+		"\n"
+		"\t\t\t"
+#ifdef DEF_MAP
+		"-m " DEF_MAP
+#else
+		"-M"
+#endif
+		"\n"
+		"\t\t\tOops report is read from stdin\n"
+		"\n"
+	       );
+}
+
+/* Check if possibly conflicting options were specified */
+static void multi_opt(int specl, int specu, char type, const char *using)
+{
+	if (specl && specu) {
+		fprintf(stderr,
+			"Warning - you specified both -%c and -%c.  Using '",
+			type, toupper(type));
+		++warnings;
+		if (using) {
+			fprintf(stderr, "-%c %s", type, using);
+			if (type == 'o')
+				fprintf(stderr, " ...");
+			fprintf(stderr, "'\n");
+		}
+		else
+			fprintf(stderr, "-%c'\n", toupper(type));
+	}
+	else if (specl > 1 && type != 'o') {
+		fprintf(stderr,
+			"Warning - you specified -%c more than once.  "
+			"Using '-%c %s'\n",
+			type, type, using);
+		++warnings;
+	}
+	else if (specu > 1) {
+		fprintf(stderr,
+			"Warning - you specified -%c more than once.  "
+			"Second and subsequent '-%c' ignored\n",
+			toupper(type), toupper(type));
+		++warnings;
+	}
+}
+
+/* If a name contains *r (*m, *n, *s), replace with the current value of
+ * `uname -r` (-m, -n, -s).  Actually uses uname system call rather than the
+ * uname command but the result is the same.
+ */
+static void convert_uname(char **name)
+{
+	char *p, *newname, *oldname, *replacement;
+	unsigned len;
+	int free_oldname = 0;
+	static char procname[] = "convert_uname";
+
+	if (!*name)
+		return;
+
+	while ((p = strchr(*name, '*'))) {
+		struct utsname buf;
+		int i = uname(&buf);
+		if (debug)
+			fprintf(stderr, "DEBUG: %s %s in\n", procname, *name);
+		if (i) {
+			fprintf(stderr,
+				"%s: uname failed, %s will not be processed\n",
+				prefix, *name);
+			perror(prefix);
+			++errors;
+			return;
+		}
+		switch (*(p+1)) {
+		case 'r':
+			replacement = buf.release;
+			break;
+		case 'm':
+			replacement = buf.machine;
+			break;
+		case 'n':
+			replacement = buf.nodename;
+			break;
+		case 's':
+			replacement = buf.sysname;
+			break;
+		default:
+			fprintf(stderr,
+				"%s: invalid replacement character '*%c' "
+				"in %s\n",
+				prefix, *(p+1), *name);
+			++errors;
+			return;
+		}
+		len = strlen(*name)-2+strlen(replacement)+1;
+		if (!(newname = malloc(len)))
+			malloc_error(procname);
+		strncpy(newname, *name, (p-*name));
+		strcpy(newname+(p-*name), replacement);
+		strcpy(newname+(p-*name)+strlen(replacement), p+2);
+		p = newname+(p-*name)+strlen(replacement);	/* no rescan */
+		oldname = *name;
+		*name = newname;
+		if (free_oldname)
+			free(oldname);
+		free_oldname = 1;
+		if (debug)
+			fprintf(stderr, "DEBUG: %s %s out\n", procname, *name);
+	}
+	return;
+}
+
+/* Parse the options.  Verbose but what's new with getopt? */
+static void parse(int argc,
+		  char **argv,
+		  char **vmlinux,
+		  char ***object,
+		  int *objects,
+		  char **ksyms,
+		  char **lsmod,
+		  char **system_map,
+		  char **save_system_map,
+		  char ***filename,
+		  int *filecount,
+		  int *spec_h
+		 )
+{
+	int spec_v = 0, spec_V = 0;
+	int spec_o = 0, spec_O = 0;
+	int spec_k = 0, spec_K = 0;
+	int spec_l = 0, spec_L = 0;
+	int spec_m = 0, spec_M = 0;
+	int spec_s = 0;
+
+	int c, i;
+	char *p;
+
+	while ((c = getopt(argc, argv, "v:Vo:Ok:Kl:Lm:Ms:dh")) != EOF) {
+		if (debug && c != 'd')
+			fprintf(stderr, "DEBUG: getopt '%c' '%s'\n", c, optarg);
+		switch(c) {
+		case 'v':
+			*vmlinux = optarg;
+			++spec_v;
+			break;
+		case 'V':
+			*vmlinux = NULL;
+			++spec_V;
+			break;
+		case 'o':
+			if (!spec_o) {
+				/* First -o, discard default value(s) */
+				for (i = 0; i < *objects; ++i)
+					free((*object)[i]);
+				free(*object);
+				*object = NULL;
+				*objects = 0;
+			}
+			*object = realloc(*object,
+				((*objects)+1)*sizeof(**object));
+			if (!*object)
+				malloc_error("object");
+			if (!(p = strdup(optarg)))
+				malloc_error("strdup -o");
+			else {
+				(*object)[(*objects)++] = p;
+				++spec_o;
+			}
+			break;
+		case 'O':
+			++spec_O;
+			for (i = 0; i < *objects; ++i)
+				free((*object)[i]);
+			free(*object);
+			*object = NULL;
+			*objects = 0;
+			break;
+		case 'k':
+			*ksyms = optarg;
+			++spec_k;
+			break;
+		case 'K':
+			*ksyms = NULL;
+			++spec_K;
+			break;
+		case 'l':
+			*lsmod = optarg;
+			++spec_l;
+			break;
+		case 'L':
+			*lsmod = NULL;
+			++spec_L;
+			break;
+		case 'm':
+			*system_map = optarg;
+			++spec_m;
+			break;
+		case 'M':
+			*system_map = NULL;
+			++spec_M;
+			break;
+		case 's':
+			*save_system_map = optarg;
+			++spec_s;
+			break;
+		case 'd':
+			++debug;
+			break;
+		case 'h':
+			usage();
+			++*spec_h;
+			break;
+		case '?':
+			usage();
+			exit(2);
+		}
+	}
+
+	*filecount = argc - optind;
+	*filename = argv + optind;
+
+	/* Expand any requests for the current uname values */
+	convert_uname(vmlinux);
+	if (*objects) {
+		for (i = 0; i < *objects; ++i)
+			convert_uname(*object+i);
+	}
+	convert_uname(ksyms);
+	convert_uname(lsmod);
+	convert_uname(system_map);
+
+	/* Check for multiple options specified */
+	multi_opt(spec_v, spec_V, 'v', *vmlinux);
+	multi_opt(spec_o, spec_O, 'o', *object ? **object : NULL);
+	multi_opt(spec_k, spec_K, 'k', *ksyms);
+	multi_opt(spec_l, spec_L, 'l', *lsmod);
+	multi_opt(spec_m, spec_M, 'm', *system_map);
+
+	printf("Options used:");
+	if (*vmlinux)
+		printf(" -v %s", *vmlinux);
+	else
+		printf(" -V");
+	if (*objects) {
+		for (i = 0; i < *objects; ++i)
+			printf(" -o %s", (*object)[i]);
+	}
+	else
+		printf(" -O");
+	if (*ksyms)
+		printf(" -k %s", *ksyms);
+	else
+		printf(" -K");
+	if (*lsmod)
+		printf(" -l %s", *lsmod);
+	else
+		printf(" -L");
+	if (*system_map)
+		printf(" -m %s", *system_map);
+	else
+		printf(" -M");
+	printf("\n\n");
+}
+
+/* Read environment variables */
+static void read_env(const char *external, char **internal)
+{
+	char *p;
+	if ((p = getenv(external))) {
+		*internal = p;
+		if (debug)
+			fprintf(stderr,
+				"DEBUG: env override %s=%s\n",
+				external, *internal);
+	}
+	else {
+		if (debug)
+			fprintf(stderr,
+				"DEBUG: env default %s=%s\n",
+				external, *internal);
+	}
+}
+
+
+int main(int argc, char **argv)
+{
+	char *vmlinux = NULL;
+	char **object = NULL;
+	int objects = 0;
+	char *ksyms = NULL;
+	char *lsmod = NULL;
+	char *system_map = NULL;
+	char *save_system_map = NULL;
+	char **filename;
+	int filecount = 0;
+	int spec_h = 0;		/* -h was specified */
+	int i;
+
+	prefix = *argv;
+	setvbuf(stdout, NULL, _IONBF, 0);
+
+#ifdef DEF_VMLINUX
+	vmlinux = DEF_LINUX;
+#endif
+#ifdef DEF_OBJECTS
+	{
+		char *p;
+		object = realloc(object, (objects+1)*sizeof(*object));
+		if (!object)
+			malloc_error("DEF_OBJECTS");
+		if (!(p = strdup(DEF_OBJECTS)))
+			malloc_error("DEF_OBJECTS");
+		else
+			object[objects++] = p;
+	}
+#endif
+#ifdef DEF_KSYMS
+	ksyms = DEF_KSYMS;
+#endif
+#ifdef DEF_LSMOD
+	lsmod = DEF_LSMOD;
+#endif
+#ifdef DEF_MAP
+	system_map = DEF_MAP;
+#endif
+
+	parse(argc,
+	      argv,
+	      &vmlinux,
+	      &object,
+	      &objects,
+	      &ksyms,
+	      &lsmod,
+	      &system_map,
+	      &save_system_map,
+	      &filename,
+	      &filecount,
+	      &spec_h
+	     );
+
+	if (spec_h && filecount == 0)
+		return(0);	/* just the help text */
+
+	if (debug)
+		fprintf(stderr, "DEBUG: level %d\n", debug);
+
+	read_env("KSYMOOPS_NM", &path_nm);
+	read_env("KSYMOOPS_FIND", &path_find);
+	read_env("KSYMOOPS_OBJDUMP", &path_objdump);
+
+	re_compile_common();
+	ss_init_common();
+
+	read_vmlinux(vmlinux);
+	read_ksyms(ksyms);
+	/* No point in reading modules unless ksyms shows modules loaded */
+	if (ss_ksyms_modules) {
+		expand_objects(object, objects);
+		for (i = 0; i < ss_objects; ++i)
+			read_object(ss_object[i].source, i);
+	}
+	else if (objects)
+		printf("No modules in ksyms, skipping objects\n");
+	/* No point in reading lsmod without ksyms */
+	if (ss_ksyms_modules || ss_ksyms_base.used)
+		read_lsmod(lsmod);
+	else if (lsmod)
+		printf("No ksyms, skipping lsmod\n");
+	read_system_map(system_map);
+	merge_maps(save_system_map);
+
+	/* After all that work, it is finally time to read the Oops report */
+	Oops_read(filecount, filename);
+
+	if (warnings || errors) {
+		printf("\n");
+		if (warnings)
+			printf("%d warning%s ",
+			       warnings, warnings == 1 ? "" : "s");
+		if (warnings && errors)
+			printf("and ");
+		if (errors)
+			printf("%d error%s ", errors, errors == 1 ? "" : "s");
+		printf("issued.  Results may not be reliable.\n");
+		return(1);
+	}
+
+	return(0);
+}
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/ksymoops.h linux/scripts/ksymoops-0.6/ksymoops.h
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/ksymoops.h	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/ksymoops.h	Mon Nov  2 07:35:08 1998
@@ -0,0 +1,145 @@
+/*
+	ksymoops.h.
+
+	Copyright Keith Owens <ka...@ocs.com.au>.
+	Released under the GNU Public Licence, Version 2.
+
+	Tue Nov  3 02:31:01 EST 1998
+	Version 0.6
+	Read lsmod (/proc/modules).
+	Convert from a.out to bfd, using same format as ksymoops.
+	PPC trace addresses are not bracketed, add new re.
+
+	Wed Oct 28 13:47:23 EST 1998
+	Version 0.4
+	Split into separate sources.
+*/
+
+#include <sys/types.h>
+#include <regex.h>
+#include <stdio.h>
+
+
+/* Pity this is not externalised, see binfmt_elf.c */
+#define elf_addr_t unsigned long
+
+extern char *prefix;
+extern char *path_nm;		/* env KSYMOOPS_NM */
+extern char *path_find;		/* env KSYMOOPS_FIND */
+extern char *path_objdump;	/* env KSYMOOPS_OBJDUMP */
+extern int debug;
+extern int errors;
+extern int warnings;
+
+typedef struct symbol SYMBOL;
+
+struct symbol {
+	char *name;		/* name of symbol */
+	char type;		/* type of symbol from nm/System.map */
+	char keep;		/* keep this symbol in merged map? */
+	elf_addr_t address;	/* address in kernel */
+};
+
+/* Header for symbols from one particular source */
+
+typedef struct symbol_set SYMBOL_SET;
+
+struct symbol_set {
+	char *source;			/* where the symbols came from */
+	int used;			/* number of symbols used */
+	int alloc;			/* number of symbols allocated */
+	SYMBOL *symbol;			/* dynamic array of symbols */
+	SYMBOL_SET *related;		/* any related symbol set */
+};
+
+extern SYMBOL_SET  ss_vmlinux;
+extern SYMBOL_SET  ss_ksyms_base;
+extern SYMBOL_SET *ss_ksyms_module;
+extern int         ss_ksyms_modules;
+extern SYMBOL_SET  ss_lsmod;
+extern SYMBOL_SET *ss_object;
+extern int         ss_objects;
+extern SYMBOL_SET  ss_system_map;
+
+extern SYMBOL_SET  ss_merged;	/* merged map with info from all sources */
+extern SYMBOL_SET  ss_Version;	/* Version_ numbers where available */
+
+/* Regular expression stuff */
+
+extern regex_t     re_nm;
+extern regmatch_t *re_nm_pmatch;
+extern regex_t     re_bracketed_address;
+extern regmatch_t *re_bracketed_address_pmatch;
+extern regex_t     re_unbracketed_address;
+extern regmatch_t *re_unbracketed_address_pmatch;
+
+/* Bracketed address: optional '[', required '<', at least 4 hex characters,
+ * required '>', optional ']', optional white space.
+ */
+#define BRACKETED_ADDRESS	"\\[*<([0-9a-fA-F]{4,})>\\]*[ \t]*"
+
+#define UNBRACKETED_ADDRESS	"([0-9a-fA-F]{4,})[ \t]*"
+
+/* io.c */
+extern int regular_file(const char *file, const char *msg);
+extern FILE *fopen_local(const char *file, const char *mode, const char *msg);
+extern void fclose_local(FILE *f, const char *msg);
+extern char *fgets_local(char **line, int *size, FILE *f, const char *msg);
+extern int fwrite_local(void const *ptr, size_t size, size_t nmemb,
+			FILE *stream, const char *msg);
+extern FILE *popen_local(const char *cmd, const char *msg);
+extern void pclose_local(FILE *f, const char *msg);
+
+/* ksyms.c */
+extern void read_ksyms(const char *ksyms);
+extern void map_ksyms_to_modules(void);
+extern void read_lsmod(const char *lsmod);
+extern void compare_ksyms_lsmod(void);
+
+/* misc.c */
+extern void malloc_error(const char *msg);
+extern const char *format_address(elf_addr_t address);
+extern char *find_fullpath(const char *program);
+
+/* map.c */
+extern void read_system_map(const char *system_map);
+extern void merge_maps(const char *save_system_map);
+extern void compare_maps(const SYMBOL_SET *ss1, const SYMBOL_SET *ss2,
+			 int precedence);
+
+
+/* object.c */
+extern SYMBOL_SET *adjust_object_offsets(SYMBOL_SET *ss);
+extern void read_vmlinux(const char *vmlinux);
+extern void expand_objects(char * const *object, int objects);
+extern void read_object(const char *object, int i);
+
+/* oops.c */
+extern void Oops_read(int filecount, char * const *filename);
+
+/* re.c */
+extern void re_compile(regex_t *preg, const char *regex, int cflags,
+		       regmatch_t **pmatch);
+extern void re_compile_common(void);
+extern void re_strings(regex_t *preg, const char *text, regmatch_t *pmatch,
+		       char ***string);
+extern void re_strings_free(const regex_t *preg, char ***string);
+extern void re_string_check(int need, int available, const char *msg);
+
+/* symbol.c */
+extern void ss_init(SYMBOL_SET *ss, const char *msg);
+extern void ss_free(SYMBOL_SET *ss);
+extern void ss_init_common(void);
+extern SYMBOL *find_symbol_name(const SYMBOL_SET *ss, const char *symbol,
+				int *start);
+extern void add_symbol_n(SYMBOL_SET *ss, const elf_addr_t address,
+			 const char type, const char keep, const char *symbol);
+extern void add_symbol(SYMBOL_SET *ss, const char *address, const char type,
+		       const char keep, const char *symbol);
+extern char *map_address(const SYMBOL_SET *ss, const elf_addr_t address);
+extern void ss_sort_atn(SYMBOL_SET *ss);
+extern void ss_sort_na(SYMBOL_SET *ss);
+extern SYMBOL_SET *ss_copy(const SYMBOL_SET *ss);
+extern void add_Version(const char *version, const char *source);
+extern void extract_Version(SYMBOL_SET *ss);
+extern void compare_Version(void);
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/ksyms.c linux/scripts/ksymoops-0.6/ksyms.c
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/ksyms.c	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/ksyms.c	Mon Nov  2 07:35:34 1998
@@ -0,0 +1,287 @@
+/*
+	ksyms.c.
+
+	Process ksyms for ksymoops.
+
+	Copyright Keith Owens <ka...@ocs.com.au>.
+	Released under the GNU Public Licence, Version 2.
+
+	Tue Nov  3 02:31:01 EST 1998
+	Version 0.6
+	Read lsmod (/proc/modules).
+	Move "Using_Version" copy to map.c.
+
+	Wed Oct 28 13:47:23 EST 1998
+	Version 0.4
+	Split into separate sources.
+ */
+
+#include "ksymoops.h"
+#include <malloc.h>
+#include <string.h>
+
+/* Scan one line from ksyms.  Split lines into the base symbols and the module
+ * symbols.  Separate ss for base and each module.
+ */
+static void scan_ksyms_line(const char *line)
+{
+	int i;
+	char **string = NULL;
+	SYMBOL_SET *ssp;
+	static char *prev_module = NULL;
+	static regex_t     re_ksyms;
+	static regmatch_t *re_ksyms_pmatch;
+	static char const procname[] = "scan_ksyms_line";
+
+	/* ksyms: address, symbol, optional module */
+	re_compile(&re_ksyms,
+		"^([0-9a-fA-F]{4,}) +([^ \t]+)([ \t]+\\[([^ ]+)\\])?$",
+		REG_NEWLINE|REG_EXTENDED,
+		&re_ksyms_pmatch);
+
+	i = regexec(&re_ksyms, line,
+		    re_ksyms.re_nsub+1, re_ksyms_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec %d\n", procname, i);
+	if (i)
+		return;
+
+	/* string [1] - address, [2] - symbol, [3] - white space+module,
+	 * [4] - module.
+	 */
+	re_strings(&re_ksyms, line, re_ksyms_pmatch, &string);
+	if (string[4]) {
+		if (!prev_module || strcmp(prev_module, string[4])) {
+			/* start of a new module in ksyms */
+			++ss_ksyms_modules;
+			ss_ksyms_module = realloc(ss_ksyms_module,
+				ss_ksyms_modules*sizeof(*ss_ksyms_module));
+			if (!ss_ksyms_module)
+				malloc_error("realloc ss_ksyms_module");
+			ssp = ss_ksyms_module+ss_ksyms_modules-1;
+			ss_init(ssp, string[4]);
+			prev_module = strdup(string[4]);
+			if (!prev_module)
+				malloc_error("strdup prev_module");
+		}
+		ssp = ss_ksyms_module+ss_ksyms_modules-1;
+	}
+	else
+		ssp = &ss_ksyms_base;
+	add_symbol(ssp, string[1], ' ', 1, string[2]);
+	re_strings_free(&re_ksyms, &string);
+}
+
+/* Read the symbols from ksyms.  */
+void read_ksyms(const char *ksyms)
+{
+	FILE *f;
+	char *line = NULL;
+	int i, size;
+	static char const procname[] = "read_ksyms";
+
+	if (!ksyms)
+		return;
+	ss_init(&ss_ksyms_base, "ksyms_base");
+	if (debug)
+		fprintf(stderr, "DEBUG: %s %s\n", procname, ksyms);
+
+	if (!regular_file(ksyms, procname))
+		return;
+
+	if (!(f = fopen_local(ksyms, "r", procname)))
+		return;
+
+	while (fgets_local(&line, &size, f, procname))
+		scan_ksyms_line(line);
+
+	fclose_local(f, procname);
+	free(line);
+
+	for (i = 0; i < ss_ksyms_modules; ++i) {
+		ss_sort_na(ss_ksyms_module+i);
+		extract_Version(ss_ksyms_module+i);
+	}
+	if (ss_ksyms_base.used) {
+		ss_sort_na(&ss_ksyms_base);
+		extract_Version(&ss_ksyms_base);
+	}
+	else {
+		fprintf(stderr,
+			"Warning, no kernel symbols in ksyms, is %s a valid "
+			"ksyms file?\n",
+			ksyms);
+		++warnings;
+	}
+
+	if (debug > 1) {
+		for (i = 0; i < ss_ksyms_modules; ++i) {
+			fprintf(stderr,
+				"DEBUG: %s %s used %d out of %d entries\n",
+				procname,
+				ss_ksyms_module[i].source,
+				ss_ksyms_module[i].used,
+				ss_ksyms_module[i].alloc);
+		}
+		fprintf(stderr,
+			"DEBUG: %s %s used %d out of %d entries\n",
+			procname, ss_ksyms_base.source, ss_ksyms_base.used,
+			ss_ksyms_base.alloc);
+	}
+}
+
+/* Map each ksyms module entry to the corresponding object entry.  Tricky,
+ * see the comments in the docs about needing a unique symbol in each
+ * module.
+ */
+static void map_ksym_to_module(SYMBOL_SET *ss)
+{
+	int i, j, matches;
+	char *name = NULL;
+
+	for (i = 0; i < ss->used; ++i) {
+		matches = 0;
+		for (j = 0; j < ss_objects; ++j) {
+			name = (ss->symbol)[i].name;
+			if (find_symbol_name(ss_object+j, name, NULL)) {
+				++matches;
+				ss->related = ss_object+j;
+			}
+		}
+		if (matches == 1)
+			break;		/* unique symbol over all objects */
+		ss->related = NULL;	/* keep looking */
+	}
+	if (!(ss->related)) {
+		fprintf(stderr,
+			"Warning: cannot match loaded module %s to any "
+			"module object.  Trace may not be reliable.\n",
+			ss->source);
+		++warnings;
+	}
+	else if (debug)
+		fprintf(stderr,
+			"DEBUG: ksyms %s matches to %s based on unique "
+			"symbol %s\n",
+			ss->source, ss->related->source, name);
+}
+
+/* Map all ksyms module entries to their corresponding objects */
+void map_ksyms_to_modules(void)
+{
+	int i;
+	SYMBOL_SET *ss, *ssc;
+
+	for (i = 0; i < ss_ksyms_modules; ++i) {
+		ss = ss_ksyms_module+i;
+		map_ksym_to_module(ss);
+		if (ss->related) {
+			ssc = adjust_object_offsets(ss);
+			compare_maps(ss, ssc, 1);
+		}
+	}
+}
+
+/* Read the modules from lsmod.  */
+void read_lsmod(const char *lsmod)
+{
+	FILE *f;
+	char *line = NULL;
+	int i, size;
+	char **string = NULL;
+	static regex_t     re_lsmod;
+	static regmatch_t *re_lsmod_pmatch;
+	static char const procname[] = "read_lsmod";
+
+	if (!lsmod)
+		return;
+	ss_init(&ss_lsmod, "lsmod");
+	if (debug)
+		fprintf(stderr, "DEBUG: %s %s\n", procname, lsmod);
+
+	if (!regular_file(lsmod, procname))
+		return;
+
+	if (!(f = fopen_local(lsmod, "r", procname)))
+		return;
+
+	/* lsmod: module, size, use count, optional used by */
+	re_compile(&re_lsmod,
+		"^"
+		"[ \t]*([^ \t]+)"				/* 1 module */
+		"[ \t]*([^ \t]+)"				/* 2 size */
+		"[ \t]*([^ \t]+)"				/* 3 count */
+		"[ \t]*(.*)"					/* 4 used by */
+		"$",
+		REG_NEWLINE|REG_EXTENDED,
+		&re_lsmod_pmatch);
+
+	while (fgets_local(&line, &size, f, procname)) {
+		i = regexec(&re_lsmod, line,
+			    re_lsmod.re_nsub+1, re_lsmod_pmatch, 0);
+		if (debug > 3)
+			fprintf(stderr, "DEBUG: %s regexec %d\n", procname, i);
+		if (i)
+			continue;
+		re_strings(&re_lsmod, line, re_lsmod_pmatch, &string);
+		add_symbol(&ss_lsmod, string[2], ' ', 1, string[1]);
+	}
+
+	fclose_local(f, procname);
+	free(line);
+	re_strings_free(&re_lsmod, &string);
+	if (ss_lsmod.used)
+		ss_sort_na(&ss_lsmod);
+	else {
+		fprintf(stderr,
+			"Warning, no symbols in lsmod, is %s a valid "
+			"lsmod file?\n",
+			lsmod);
+		++warnings;
+	}
+
+	if (debug > 1)
+		fprintf(stderr,
+			"DEBUG: %s %s used %d out of %d entries\n",
+			procname, ss_lsmod.source, ss_lsmod.used,
+			ss_lsmod.alloc);
+}
+
+/* Compare modules from ksyms against module list in lsmod and vice versa.
+ * There is one ss_ for each ksyms module and a single ss_lsmod to cross
+ * check.
+ */
+void compare_ksyms_lsmod(void)
+{
+	int i, j;
+	SYMBOL_SET *ss;
+	SYMBOL *s;
+	static char const procname[] = "compare_ksyms_lsmod";
+
+	s = ss_lsmod.symbol;
+	for (i = 0; i < ss_lsmod.used; ++i, ++s) {
+		for (j = 0; j < ss_ksyms_modules; ++j) {
+			ss = ss_ksyms_module+j;
+			if (strcmp(s->name, ss->source) == 0)
+				break;
+		}
+		if (j >= ss_ksyms_modules) {
+			fprintf(stderr,
+				"Warning in %s, module %s is in lsmod but not "
+				"in ksyms, probably no symbols exported\n",
+				procname, s->name);
+			++warnings;
+		}
+	}
+
+	for (i = 0; i < ss_ksyms_modules; ++i) {
+		ss = ss_ksyms_module+i;
+		if (!find_symbol_name(&ss_lsmod, ss->source, NULL)) {
+			fprintf(stderr,
+				"Error in %s, module %s is in ksyms but not "
+				"in lsmod\n",
+				procname, ss->source);
+			++errors;
+		}
+	}
+}
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/map.c linux/scripts/ksymoops-0.6/map.c
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/map.c	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/map.c	Mon Nov  2 07:35:50 1998
@@ -0,0 +1,251 @@
+/*
+	map.c.
+
+	Read System.map for ksymoops, create merged System.map.
+
+	Copyright Keith Owens <ka...@ocs.com.au>.
+	Released under the GNU Public Licence, Version 2.
+
+	Tue Nov  3 02:31:01 EST 1998
+	Version 0.6
+	Remove addresses 0-4095 from merged map after writing new map.
+	Move "Using_Version" copy to map.c.
+
+	Wed Oct 28 13:47:23 EST 1998
+	Version 0.4
+	Split into separate sources.
+ */
+
+#include "ksymoops.h"
+#include <malloc.h>
+
+/* Read the symbols from System.map */
+void read_system_map(const char *system_map)
+{
+	FILE *f;
+	char *line = NULL, **string = NULL;
+	int i, size = 0;
+	static char const procname[] = "read_system_map";
+
+	if (!system_map)
+		return;
+	ss_init(&ss_system_map, "System.map");
+	if (debug)
+		fprintf(stderr, "DEBUG: %s %s\n", procname, system_map);
+
+	if (!regular_file(system_map, procname))
+		return;
+
+	if (!(f = fopen_local(system_map, "r", procname)))
+		return;
+
+	while (fgets_local(&line, &size, f, procname)) {
+		i = regexec(&re_nm, line, re_nm.re_nsub+1, re_nm_pmatch, 0);
+		if (debug > 3)
+			fprintf(stderr, "DEBUG: %s regexec %d\n", procname, i);
+		if (i == 0) {
+			re_strings(&re_nm, line, re_nm_pmatch, &string);
+			add_symbol(&ss_system_map, string[1], *string[2],
+				   1, string[3]);
+		}
+	}
+
+	fclose_local(f, procname);
+	re_strings_free(&re_nm, &string);
+	free(line);
+	if (ss_system_map.used) {
+		ss_sort_na(&ss_system_map);
+		extract_Version(&ss_system_map);
+	}
+	else {
+		fprintf(stderr,
+			"Warning, no kernel symbols in System.map, is %s a "
+			"valid System.map file?\n",
+			system_map);
+		++warnings;
+	}
+
+	if (debug > 1)
+		fprintf(stderr,
+			"DEBUG: %s %s used %d out of %d entries\n",
+			procname,
+			ss_system_map.source,
+			ss_system_map.used,
+			ss_system_map.alloc);
+}
+
+/* Compare two maps, all symbols in the first should appear in the second. */
+void compare_maps(const SYMBOL_SET *ss1, const SYMBOL_SET *ss2,
+			 int precedence)
+{
+	int i, start = 0;
+	SYMBOL *s1, *s2, **sdrop = precedence == 1 ? &s2 : &s1;
+	const SYMBOL_SET **ssdrop = precedence == 1 ? &ss2 : &ss1;
+
+	if (!(ss1->used && ss2->used))
+		return;
+
+	if (debug > 1)
+		fprintf(stderr,
+			"DEBUG: compare_maps %s vs %s, %s takes precedence\n",
+			ss1->source, ss2->source,
+			precedence == 1 ? ss1->source : ss2->source);
+
+	for (i = 0; i < ss1->used; ++i) {
+		s1 = ss1->symbol+i;
+		if (!(s1->keep))
+			continue;
+		s2 = find_symbol_name(ss2, s1->name, &start);
+		if (!s2) {
+			/* Some types only appear in nm output, not in things
+			 * like System.map.  Silently ignore them.
+			 */
+			if (s1->type == 'a' || s1->type == 't')
+				continue;
+			fprintf(stderr,
+				"Warning: %s symbol %s not found in %s.  "
+				"Ignoring %s entry\n",
+				ss1->source, s1->name,
+				ss2->source, (*ssdrop)->source);
+			++warnings;
+			if (*sdrop)
+				(*sdrop)->keep = 0;
+		}
+		else if (s1->address != s2->address) {
+			/* Type C symbols cannot be resolved from nm to ksyms,
+			 * silently ignore them.
+			 */
+			if (s1->type == 'C' || s2->type == 'C')
+				continue;
+			fprintf(stderr,
+				"Warning: mismatch on symbol %s %c, "
+				"%s says %lx, %s says %lx.  "
+				"Ignoring %s entry\n",
+				s1->name, s1->type, ss1->source, s1->address,
+				ss2->source, s2->address, (*ssdrop)->source);
+			++warnings;
+			if (*sdrop)
+				(*sdrop)->keep = 0;
+		}
+		else
+			++start;	/* step to next entry in ss2 */
+	}
+}
+
+/* Append the second symbol set onto the first */
+static void append_map(SYMBOL_SET *ss1, const SYMBOL_SET *ss2)
+{
+	int i;
+	SYMBOL *s;
+
+	if (!ss2 || !ss2->used)
+		return;
+	if (debug > 1)
+		fprintf(stderr, "DEBUG: append_map %s to %s\n",
+			ss2->source, ss1->source);
+
+	for (i = 0; i < ss2->used; ++i) {
+		s = ss2->symbol+i;
+		if (s->keep)
+			add_symbol_n(ss1, s->address, s->type, 1,
+				s->name);
+	}
+}
+
+/* Compare the various sources and build a merged system map */
+void merge_maps(const char *save_system_map)
+{
+	int i;
+	SYMBOL *s;
+	FILE *f;
+	static char const procname[] = "merge_maps";
+
+	if (debug)
+		fprintf(stderr, "DEBUG: %s\n", procname);
+
+	/* Using_Versions only appears in ksyms, copy to other tables */
+	if ((s = find_symbol_name(&ss_ksyms_base,
+			"Using_Versions", 0))) {
+		if (ss_system_map.used) {
+			add_symbol_n(&ss_system_map, s->address,
+				s->type, s->keep, s->name);
+			ss_sort_na(&ss_system_map);
+		}
+		if (ss_vmlinux.used) {
+			add_symbol_n(&ss_vmlinux, s->address, s->type,
+				s->keep, s->name);
+			ss_sort_na(&ss_vmlinux);
+		}
+	}
+
+	compare_Version();	/* highlight any version problems first */
+	compare_ksyms_lsmod();	/* highlight any missing modules next */
+	compare_maps(&ss_ksyms_base, &ss_vmlinux, 2);
+	compare_maps(&ss_system_map, &ss_vmlinux, 2);
+	compare_maps(&ss_vmlinux, &ss_system_map, 1);
+	compare_maps(&ss_ksyms_base, &ss_system_map, 2);
+
+	if (ss_objects) {
+		map_ksyms_to_modules();
+	}
+
+	ss_init(&ss_merged, "merged");
+	append_map(&ss_merged, &ss_vmlinux);
+	append_map(&ss_merged, &ss_ksyms_base);
+	append_map(&ss_merged, &ss_system_map);
+	for (i = 0; i < ss_ksyms_modules; ++i)
+		append_map(&ss_merged, (ss_ksyms_module+i)->related);
+	if (!ss_merged.used) {
+		fprintf(stderr, "Warning, no symbols in merged map\n");
+		++warnings;
+	}
+
+	/* drop duplicates, type a (registers) and gcc2_compiled. */
+	ss_sort_atn(&ss_merged);
+	s = ss_merged.symbol;
+	for (i = 0; i < ss_merged.used-1; ++i) {
+		if (s->type == 'a' ||
+		    (s->type == 't' && !strcmp(s->name, "gcc2_compiled.")))
+			s->keep = 0;
+		else if (strcmp(s->name, (s+1)->name) == 0 &&
+		    s->address == (s+1)->address) {
+			if (s->type != ' ')
+				(s+1)->keep = 0;
+			else
+				s->keep = 0;
+		}
+		++s;
+	}
+	ss_sort_atn(&ss_merged);	/* will remove dropped variables */
+
+	if (save_system_map) {
+		if (debug)
+			fprintf(stderr, "DEBUG: writing merged map to %s\n",
+				save_system_map);
+		if (!(f = fopen_local(save_system_map, "w", procname)))
+			return;
+		s = ss_merged.symbol;
+		for (i = 0; i < ss_merged.used; ++i) {
+			if (s->keep)
+				fprintf(f, "%s %c %s\n",
+					format_address(s->address),
+					s->type, s->name);
+			++s;
+		}
+	}
+
+	/* The merged map may contain symbols with an address of 0, e.g.
+	 * Using_Versions.  These give incorrect results for low addresses in
+	 * map_address, such addresses map to "Using_Versions+xxx".  Remove
+	 * any addresses below (arbitrary) 4096 from the merged map.  AFAIK,
+	 * Linux does not use the first page on any arch.
+	 */
+	for (i = 0; i < ss_merged.used; ++i) {
+		if ((ss_merged.symbol+i)->address < 4096)
+			(ss_merged.symbol+i)->keep = 0;
+		else
+			break;
+	}
+	if (i)
+		ss_sort_atn(&ss_merged);	/* remove dropped variables */
+}
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/misc.c linux/scripts/ksymoops-0.6/misc.c
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/misc.c	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/misc.c	Mon Nov  2 07:36:00 1998
@@ -0,0 +1,108 @@
+/*
+	misc.c.
+
+	Miscellaneous routines for ksymoops.
+
+	Copyright Keith Owens <ka...@ocs.com.au>.
+	Released under the GNU Public Licence, Version 2.
+
+	Tue Nov  3 02:31:01 EST 1998
+	Version 0.6
+	Convert from a.out to bfd, using same format as ksymoops.
+
+	Wed Oct 28 13:47:23 EST 1998
+	Version 0.4
+	Split into separate sources.
+ */
+
+#include "ksymoops.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+void malloc_error(const char *msg)
+{
+	fprintf(stderr, "%s: fatal malloc error for %s\n", prefix, msg);
+	exit(2);
+}
+
+/* Format an address with the correct number of leading zeroes */
+const char *format_address(elf_addr_t address)
+{
+	/* Well oversized */
+	static char format[10], text[200];
+	if (!*format)
+		snprintf(format, sizeof(format), "%%0%dlx",
+			2*sizeof(address));
+	snprintf(text, sizeof(text), format, address);
+	return(text);
+}
+
+/* Find the full pathname of a program.  Code heavily based on
+ * glibc-2.0.5/posix/execvp.c.
+ */
+char *find_fullpath(const char *program)
+{
+	char *fullpath = NULL;
+	char *path, *p;
+	size_t len;
+	static const char procname[] = "find_fullpath";
+
+	/* Don't search when it contains a slash.  */
+	if (strchr(program, '/')) {
+		if (!(fullpath = strdup(program)))
+			malloc_error(procname);
+		if (debug > 1)
+			fprintf(stderr, "DEBUG: %s %s\n", procname, fullpath);
+		return(fullpath);
+	}
+
+	path = getenv ("PATH");
+	if (!path) {
+		/* There is no `PATH' in the environment.  The default search
+		   path is the current directory followed by the path `confstr'
+		   returns for `_CS_PATH'.
+		 */
+		len = confstr(_CS_PATH, (char *) NULL, 0);
+		if (!(path = malloc(1 + len)))
+			malloc_error(procname);
+		path[0] = ':';
+		confstr(_CS_PATH, path+1, len);
+	}
+
+	len = strlen(program) + 1;
+	if (!(fullpath = malloc(strlen(path) + len)))
+		malloc_error(procname);
+	p = path;
+	do {
+		path = p;
+		p = strchr(path, ':');
+		if (p == NULL)
+			p = strchr(path, '\0');
+
+		/* Two adjacent colons, or a colon at the beginning or the end
+		 * of `PATH' means to search the current directory.
+		 */
+		if (p == path)
+			memcpy(fullpath, program, len);
+		else {
+			/* Construct the pathname to try.  */
+			memcpy(fullpath, path, p - path);
+			fullpath[p - path] = '/';
+			memcpy(&fullpath[(p - path) + 1], program, len);
+		}
+
+		/* If we have execute access, assume this is the program. */
+		if (access(fullpath, X_OK) == 0) {
+			if (debug > 1)
+				fprintf(stderr, "DEBUG: %s %s\n",
+					procname, fullpath);
+			return(fullpath);
+		}
+	} while (*p++ != '\0');
+
+	fprintf(stderr, "Error: %s %s could not find executable %s\n",
+		prefix, procname, program);
+	++errors;
+	return(NULL);
+}
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/object.c linux/scripts/ksymoops-0.6/object.c
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/object.c	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/object.c	Sat Oct 31 18:18:26 1998
@@ -0,0 +1,230 @@
+/*
+	object.c.
+
+	object handling routines for ksymoops.  Read modules, vmlinux, etc. 
+
+	Copyright Keith Owens <ka...@ocs.com.au>.
+	Released under the GNU Public Licence, Version 2.
+
+	Wed Oct 28 13:47:23 EST 1998
+	Version 0.4
+	Split into separate sources.
+ */
+
+#include "ksymoops.h"
+#include <malloc.h>
+#include <string.h>
+#include <sys/stat.h>
+
+/* Extract all symbols definitions from an object using nm */
+static void read_nm_symbols(SYMBOL_SET *ss, const char *file)
+{
+	FILE *f;
+	char *cmd, *line = NULL, **string = NULL;
+	int i, size = 0;
+	static char const procname[] = "read_nm_symbols";
+
+	if (!regular_file(file, procname))
+		return;
+
+	cmd = malloc(strlen(path_nm)+strlen(file)+2);
+	if (!cmd)
+		malloc_error("nm command");
+	strcpy(cmd, path_nm);
+	strcat(cmd, " ");
+	strcat(cmd, file);
+	if (debug > 1)
+		fprintf(stderr, "DEBUG: %s command '%s'\n", procname, cmd);
+	if (!(f = popen_local(cmd, procname)))
+		return;
+	free(cmd);
+
+	while (fgets_local(&line, &size, f, procname)) {
+		i = regexec(&re_nm, line, re_nm.re_nsub+1, re_nm_pmatch, 0);
+		if (debug > 3)
+			fprintf(stderr, "DEBUG: %s regexec %d\n", procname, i);
+		if (i == 0) {
+			re_strings(&re_nm, line, re_nm_pmatch, &string);
+			add_symbol(ss, string[1], *string[2], 1, string[3]);
+		}
+	}
+
+	pclose_local(f, procname);
+	re_strings_free(&re_nm, &string);
+	free(line);
+	if (debug > 1)
+		fprintf(stderr,
+			"DEBUG: %s %s used %d out of %d entries\n",
+			procname, ss->source, ss->used, ss->alloc);
+}
+
+/* Read the symbols from vmlinux */
+void read_vmlinux(const char *vmlinux)
+{
+	if (!vmlinux)
+		return;
+	ss_init(&ss_vmlinux, "vmlinux");
+	read_nm_symbols(&ss_vmlinux, vmlinux);
+	if (ss_vmlinux.used) {
+		ss_sort_na(&ss_vmlinux);
+		extract_Version(&ss_vmlinux);
+	}
+	else {
+		fprintf(stderr,
+			"Warning, no kernel symbols in vmlinux, is %s a valid "
+			"vmlinux file?\n",
+			vmlinux);
+		++warnings;
+	}
+}
+
+
+/* Read the symbols from one object (module) */
+void read_object(const char *object, int i)
+{
+	ss_init(ss_object+i, object);
+	read_nm_symbols(ss_object+i, object);
+	if ((ss_object+i)->used) {
+		ss_sort_na(ss_object+i);
+		extract_Version(ss_object+i);
+	}
+	else {
+		fprintf(stderr, "Warning, no symbols in %s\n", object);
+		++warnings;
+	}
+}
+
+/* Add a new entry to the list of objects */
+static void add_ss_object(const char *file)
+{
+	++ss_objects;
+	ss_object = realloc(ss_object, ss_objects*sizeof(*ss_object));
+	if (!ss_object)
+		malloc_error("realloc ss_object");
+	ss_init(ss_object+ss_objects-1, file);
+}
+
+/* Run a directory and its subdirectories, looking for *.o files */
+static void find_objects(const char *dir)
+{
+	FILE *f;
+	char *cmd, *line = NULL;
+	int size = 0, files = 0;
+	static char const procname[] = "find_objects";
+	static char const options[] = " -follow -name '*.o' -print";
+
+	cmd = malloc(strlen(path_find)+1+strlen(dir)+strlen(options)+1);
+	if (!cmd)
+		malloc_error("find command");
+	strcpy(cmd, path_find);
+	strcat(cmd, " ");
+	strcat(cmd, dir);
+	strcat(cmd, options);
+	if (debug > 1)
+		fprintf(stderr, "DEBUG: %s command '%s'\n", procname, cmd);
+	if (!(f = popen_local(cmd, procname)))
+		return;
+	free(cmd);
+
+	while (fgets_local(&line, &size, f, procname)) {
+		if (debug > 1)
+			fprintf(stderr, "DEBUG: %s - %s\n", procname, line);
+		add_ss_object(line);
+		++files;
+	}
+
+	pclose_local(f, procname);
+	if (!files) {
+		fprintf(stderr,
+			"Warning: no *.o files in %s.  "
+			"Is %s a valid module directory?\n",
+			dir, dir);
+		++warnings;
+	}
+}
+
+/* Take the user supplied list of objects which can include directories.
+ * Expand directories into any *.o files.  The results are stored in
+ * ss_object, leaving the user supplied options untouched.
+ */
+void expand_objects(char * const *object, int objects)
+{
+	struct stat statbuf;
+	int i;
+	const char *file;
+	static char const procname[] = "expand_objects";
+
+	for (i = 0; i < objects; ++i) {
+		file = object[i];
+		if (debug > 1)
+			fprintf(stderr, "DEBUG: %s checking '%s' - ",
+				procname, file);
+		if (!stat(file, &statbuf) && S_ISDIR(statbuf.st_mode)) {
+			if (debug > 1)
+				fprintf(stderr, "directory, expanding\n");
+			find_objects(file);
+		}
+		else {
+			if (debug > 1)
+				fprintf(stderr, "not directory\n");
+			add_ss_object(file);
+		}
+	}
+}
+
+/* Map a symbol type to a section code. 0 - text, 1 - data, 2 - read only data,
+ * 3 - C (cannot relocate), 4 - the rest.
+ */
+static int section(char type)
+{
+	switch (type) {
+	case 'T':
+	case 't':
+		return 0;
+	case 'D':
+	case 'd':
+		return 1;
+	case 'R':
+	case 'r':
+		return 2;
+	case 'C':
+		return 3;
+	default:
+		return 4;
+	}
+}
+
+/* Given ksyms module data which has a related object, create a copy of the
+ * object data, adjusting the offsets to match where the module was loaded.
+ */
+SYMBOL_SET *adjust_object_offsets(SYMBOL_SET *ss)
+{
+	int i;
+	elf_addr_t adjust[] = {0, 0, 0, 0, 0};
+	SYMBOL *sk, *so;
+	SYMBOL_SET *ssc;
+
+	if (debug > 1)
+		fprintf(stderr,
+			"DEBUG: adjust_object_offsets %s\n", ss->source);
+
+	ssc = ss_copy(ss->related);
+
+	/* For common symbols, calculate the adjustment */
+	for (i = 0; i < ss->used; ++i) {
+		sk = ss->symbol+i;
+		if ((so = find_symbol_name(ssc, sk->name, NULL)))
+			adjust[section(so->type)] = sk->address - so->address;
+	}
+	for (i = 0; i < ssc->used; ++i) {
+		so = ssc->symbol+i;
+		/* Type C does not relocate well, silently ignore */
+		if (so->type != 'C' && adjust[section(so->type)])
+			so->address += adjust[section(so->type)];
+		else
+			so->keep = 0;  /* do not merge into final map */
+	}
+
+	ss->related = ssc;	/* map using adjusted copy */
+	return(ssc);
+}
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops-0.6/oops.c linux/scripts/ksymoops-0.6/oops.c
--- v2.2.0-pre3/linux/scripts/ksymoops-0.6/oops.c	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ksymoops-0.6/oops.c	Mon Nov  2 07:38:07 1998
@@ -0,0 +1,1061 @@
+/*
+	oops.c.
+
+	Oops processing for ksymoop.
+
+	Copyright Keith Owens <ka...@ocs.com.au>.
+	Released under the GNU Public Licence, Version 2.
+
+	Tue Nov  3 02:31:01 EST 1998
+	Version 0.6
+	Oops file must be regular.
+	Add "invalid operand" to Oops_print.
+	Minor adjustment to re for ppc.
+	Minor adjustment to re for objdump lines with <_EIP+xxx>.
+	Convert from a.out to bfd, using same format as ksymoops.
+	Added MIPS.
+	PPC handling based on patches by "Ryan Nielsen" <r...@krazynet.com>
+
+	Wed Oct 28 13:47:23 EST 1998
+	Version 0.4
+ Split into seperate sources.
+ */
+
+#include "ksymoops.h"
+#include <bfd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <malloc.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Error detected by bfd */
+static void Oops_bfd_perror(const char *msg)
+{
+	fprintf(stderr, "Error ");
+	bfd_perror(msg);
+	++errors;
+}
+
+/* Safest way to get correct output bfd format is to copy ksymoops' format. */
+static int Oops_copy_bfd_format(bfd **ibfd, bfd **obfd, asection **isec,
+				const char *file)
+{
+	char *me, **matches, **match;
+
+	if (!(*obfd = bfd_openw(file, NULL))) {
+		Oops_bfd_perror(file);
+		return(0);
+	}
+
+	me = find_fullpath(prefix);
+	if (!me)
+		return(0);
+
+	if (!(*ibfd = bfd_openr(me, NULL))) {
+		Oops_bfd_perror(me);
+		return(0);
+	}
+	free(me);	/* Who is Tommy? */
+
+	if (!bfd_check_format_matches(*ibfd, bfd_object, &matches)) {
+		Oops_bfd_perror(me);
+		if (bfd_get_error() == bfd_error_file_ambiguously_recognized) {
+			fprintf(stderr, "Matching formats:");
+			match = matches;
+			while (*match)
+				fprintf(stderr, " %s", *match++);
+			fprintf(stderr, "\n");
+			free(matches);
+		}
+		return(0);
+	}
+
+	if (!(*isec = bfd_get_section_by_name(*ibfd, ".text"))) {
+		Oops_bfd_perror("get_section");
+		return(0);
+	}
+
+	bfd_set_format(*obfd, bfd_object);
+	bfd_set_arch_mach(*obfd, bfd_get_arch(*ibfd), bfd_get_mach(*ibfd));
+
+	if (!bfd_set_file_flags(*obfd, bfd_get_file_flags(*ibfd))) {
+		Oops_bfd_perror("set_file_flags");
+		return(0);
+	}
+
+	return(1);
+}
+
+/* Write the code values to a file using bfd. */
+static int Oops_write_bfd_data(bfd *ibfd, bfd *obfd, asection *isec,
+			       const char *code, int size)
+{
+	asection *osec;
+	asymbol *osym;
+
+	if (!bfd_set_start_address(obfd, 0)) {
+		Oops_bfd_perror("set_start_address");
+		return(0);
+	}
+	if (!(osec = bfd_make_section(obfd, ".text"))) {
+		Oops_bfd_perror("make_section");
+		return(0);
+	}
+	if (!bfd_set_section_flags(obfd, osec, 
+		bfd_get_section_flags(ibfd, isec))) {
+		Oops_bfd_perror("set_section_flags");
+		return(0);
+	}
+	if (!bfd_set_section_alignment(obfd, osec, 
+		bfd_get_section_alignment(ibfd, isec))) {
+		Oops_bfd_perror("set_section_alignment");
+		return(0);
+	}
+	osec->output_section = osec;
+	if (!(osym = bfd_make_empty_symbol(obfd))) {
+		Oops_bfd_perror("make_empty_symbol");
+		return(0);
+	}
+	osym->name = "_EIP";
+	osym->section = osec;
+	osym->flags = BSF_GLOBAL;
+	osym->value = 0;
+	if (!bfd_set_symtab(obfd, &osym, 1)) {
+		Oops_bfd_perror("set_symtab");
+		return(0);
+	}
+	if (!bfd_set_section_size(obfd, osec, size)) {
+		Oops_bfd_perror("set_section_size");
+		return(0);
+	}
+	if (!bfd_set_section_vma(obfd, osec, 0)) {
+		Oops_bfd_perror("set_section_vma");
+		return(0);
+	}
+	if (!bfd_set_section_contents(obfd, osec, (PTR) code, 0, size)) {
+		Oops_bfd_perror("set_section_contents");
+		return(0);
+	}
+	if (!bfd_close(obfd)) {
+		Oops_bfd_perror("close(obfd)");
+		return(0);
+	}
+	if (!bfd_close(ibfd)) {
+		Oops_bfd_perror("close(ibfd)");
+		return(0);
+	}
+	return 1;
+}
+
+/* Write the Oops code to a temporary file with suitable header and trailer. */
+static char *Oops_code_to_file(const char *code, int size)
+{
+	char *file;
+	bfd *ibfd, *obfd;
+	asection *isec;
+
+	bfd_init();
+	file = tmpnam(NULL);
+	if (!Oops_copy_bfd_format(&ibfd, &obfd, &isec, file))
+		return(NULL);
+	if (!Oops_write_bfd_data(ibfd, obfd, isec, code, size))
+		return(NULL);
+	return(file);
+}
+
+/* Run objdump against the binary Oops code */
+static FILE *Oops_objdump(const char *file)
+{
+	char *cmd;
+	FILE *f;
+	static char const options[] = "-dhf ";
+	static char const procname[] = "Oops_objdump";
+
+	cmd = malloc(strlen(path_objdump)+1+strlen(options)+strlen(file)+1);
+	if (!cmd)
+		malloc_error(procname);
+	strcpy(cmd, path_objdump);
+	strcat(cmd, " ");
+	strcat(cmd, options);
+	strcat(cmd, file);
+	if (debug > 1)
+		fprintf(stderr, "DEBUG: %s command '%s'\n", procname, cmd);
+	f = popen_local(cmd, procname);
+	free(cmd);
+	return(f);
+}
+
+/* Process one code line from objdump, ignore everything else */
+static void Oops_decode_one(SYMBOL_SET *ss, const char *line, elf_addr_t eip,
+			    int adjust)
+{
+	int i;
+	elf_addr_t address, eip_relative;
+	char *line2, *map, **string = NULL;
+	static regex_t     re_Oops_objdump;
+	static regmatch_t *re_Oops_objdump_pmatch;
+	static char const procname[] = "Oops_decode_one";
+
+	/* objdump output.  Optional whitespace, hex digits, optional
+	 * ' <_EIP+offset>', ':'.  The '+offset' after _EIP is also optional.
+	 * Older binutils output 'xxxxxxxx <_EIP+offset>:', newer versions do
+	 * '00000000 <_EIP>:' first followed by '      xx:' lines.
+	 *
+	 * Just to complicate things even more, objdump recognises jmp, call,
+	 * etc., converts the code to something like this :-
+	 * "   f: e8 32 34 00 00  call   3446 <_EIP+0x3446>"
+	 * Recognise this and append the eip adjusted address, followed by the
+	 * map_address text for that address.
+	 *
+	 * With any luck, objdump will take care of all such references which
+	 * makes this routine architecture insensitive.  No need to test for
+	 * i386 jmp, call or m68k swl etc.
+	 */
+	re_compile(&re_Oops_objdump,
+			"^[ \t]*"
+			"([0-9a-fA-F]+)"				/* 1 */
+			"( <_EIP[^>]*>)?"				/* 2 */
+			":"
+			"("						/* 3 */
+			".* +<_EIP\\+0?x?([0-9a-fA-F]+)>[ \t]*$"	/* 4 */
+			")?"
+			".*"
+			,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_objdump_pmatch);
+
+	i = regexec(&re_Oops_objdump, line, re_Oops_objdump.re_nsub+1,
+		re_Oops_objdump_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec %d\n", procname, i);
+	if (i != 0)
+		return;
+
+	re_strings(&re_Oops_objdump, line, re_Oops_objdump_pmatch, &string);
+	errno = 0;
+	address = strtoul(string[1], NULL, 16);
+	if (errno) {
+		fprintf(stderr,
+			"%s Invalid hex value in objdump line, "
+			"treated as zero - '%s'\n"
+			"  objdump line '%s'\n",
+			procname, string[1], line);
+		perror(" ");
+		++errors;
+		address = 0;
+	}
+	address += eip + adjust;
+	if (string[4]) {
+		/* EIP relative data to be adjusted */
+		errno = 0;
+		eip_relative = strtoul(string[4], NULL, 16);
+		if (errno) {
+			fprintf(stderr,
+				"%s Invalid hex value in objdump line, "
+				"treated as zero - '%s'\n"
+				"  objdump line '%s'\n",
+				procname, string[4], line);
+			perror(" ");
+			++errors;
+			eip_relative = 0;
+		}
+		eip_relative += eip + adjust;
+		map = map_address(&ss_merged, eip_relative);
+		/* new text is original line, eip_relative in hex, map text */
+		i = strlen(line)+1+2*sizeof(eip_relative)+1+strlen(map)+1;
+		line2 = malloc(i);
+		if (!line2)
+			malloc_error(procname);
+		snprintf(line2, i, "%s %s %s",
+			line, format_address(eip_relative), map);
+		add_symbol_n(ss, address, 'C', 1, line2);
+		free(line2);
+	}
+	else
+		add_symbol_n(ss, address, 'C', 1, line);	/* as is */
+	re_strings_free(&re_Oops_objdump, &string);
+}
+
+/* Maximum number of code bytes to process */
+#define CODE_SIZE 36	/* sparc and alpha dump 36 bytes */
+
+/******************************************************************************/
+/*                     Start architecture sensitive code                      */
+/******************************************************************************/
+
+/* Extract the hex values from the Code: line and convert to binary */
+static int Oops_code_values(const unsigned char* code_text, char *code,
+			    int *adjust, char ***string, int string_max)
+{
+	int byte = 0, l;
+	unsigned long c;
+	char *value;
+	const char *p;
+	static regex_t     re_Oops_code_value;
+	static regmatch_t *re_Oops_code_value_pmatch;
+	static const char procname[] = "Oops_code_values";
+
+	/* Given by re_Oops_code: code_text is a message (e.g. "general
+	 * protection") or one or more hex fields separated by space or tab.
+	 * Some architectures bracket the current instruction with '<' and '>'.
+	 * The first character is nonblank.
+	 */
+	if (!isxdigit(*code_text)) {
+		fprintf(stderr,
+			"Warning, Code looks like message, not hex digits.  "
+			"No disassembly attempted.\n");
+		++warnings;
+		return(0);
+	}
+	memset(code, '\0', CODE_SIZE);
+	p = code_text;
+	*adjust = 0;	/* EIP points to code byte 0 */
+
+	/* Code values.  Hex values separated by white space.  On sparc, the
+	 * current instruction is bracketed in '<' and '>'.
+	 */
+	re_compile(&re_Oops_code_value,
+			"^"
+			"(<?)"						/* 1 */
+			"([0-9a-fA-F]+)"				/* 2 */
+			">?"
+			"[ \t]*"
+			,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_code_value_pmatch);
+
+	re_string_check(re_Oops_code_value.re_nsub+1, string_max, procname);
+	while (regexec(&re_Oops_code_value, p, re_Oops_code_value.re_nsub+1,
+			re_Oops_code_value_pmatch, 0) == 0) {
+		re_strings(&re_Oops_code_value, p,
+			re_Oops_code_value_pmatch, string);
+		if (byte >= CODE_SIZE)
+			break;
+		errno = 0;
+		value = (*string)[2];
+		c = strtoul(value, NULL, 16);
+		if (errno) {
+			fprintf(stderr,
+				"%s Invalid hex value in code_value line, "
+				"treated as zero - '%s'\n"
+				"  code_value line '%s'\n",
+				procname, value, code_text);
+			perror(" ");
+			++errors;
+			c = 0;
+		}
+		if ((*string[1]) && *((*string)[1]))
+			*adjust = -byte;	/* this byte is EIP */
+		/* i386 - 2 byte code, m68k - 4 byte, sparc - 8 byte.
+		 * Consistent we're not!
+		 */
+		l = strlen(value);
+		if (l%2) {
+			fprintf(stderr,
+				"%s invalid value 0x%s in Code line, not a "
+				"multiple of 2 digits, value ignored\n",
+				procname, value);
+			++errors;
+		}
+		else while (l) {
+			if (byte >= CODE_SIZE) {
+				fprintf(stderr,
+					"%s Warning: extra values in Code "
+					"line, ignored - '%s'\n",
+					procname, value);
+				++warnings;
+				break;
+			}
+			l -= 2;
+			code[byte++] = (c >> l*4) & 0xff;
+			value += 2;
+		}
+		p += re_Oops_code_value_pmatch[0].rm_eo;
+	}
+
+	if (*p) {
+		fprintf(stderr,
+			"Warning garbage '%s' at end of code line ignored "
+			"by %s\n",
+			p, procname);
+		++warnings;
+	}
+	return(1);
+}
+
+/* Look for the EIP: line, returns start of the relevant hex value */
+static char *Oops_eip(const char *line, char ***string, int string_max)
+{
+	int i;
+	static regex_t     re_Oops_eip_sparc;
+	static regmatch_t *re_Oops_eip_sparc_pmatch;
+	static regex_t     re_Oops_eip_ppc;
+	static regmatch_t *re_Oops_eip_ppc_pmatch;
+	static regex_t     re_Oops_eip_mips;
+	static regmatch_t *re_Oops_eip_mips_pmatch;
+	static regex_t     re_Oops_eip_other;
+	static regmatch_t *re_Oops_eip_other_pmatch;
+	static const char procname[] = "Oops_eip";
+
+	/* Oops 'EIP:' line for sparc, actually PSR followed by PC */
+	re_compile(&re_Oops_eip_sparc,
+			"^PSR: [0-9a-fA-F]+ PC: " UNBRACKETED_ADDRESS,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_eip_sparc_pmatch);
+
+	re_string_check(re_Oops_eip_sparc.re_nsub+1, string_max, procname);
+	i = regexec(&re_Oops_eip_sparc, line, re_Oops_eip_sparc.re_nsub+1,
+		re_Oops_eip_sparc_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec sparc %d\n", procname, i);
+	if (i == 0) {
+		re_strings(&re_Oops_eip_sparc, line, re_Oops_eip_sparc_pmatch,
+			string);
+		return((*string)[re_Oops_eip_sparc.re_nsub]);
+	}
+
+	/* Oops 'EIP:' line for PPC, all over the place */
+	re_compile(&re_Oops_eip_ppc,
+			"("
+			  "(kernel pc )"
+			  "|(trap at PC: )"
+			  "|(bad area pc )"
+			  "|(NIP: )"
+			")"
+			UNBRACKETED_ADDRESS,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_eip_ppc_pmatch);
+
+	re_string_check(re_Oops_eip_ppc.re_nsub+1, string_max, procname);
+	i = regexec(&re_Oops_eip_ppc, line, re_Oops_eip_ppc.re_nsub+1,
+		re_Oops_eip_ppc_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec ppc %d\n", procname, i);
+	if (i == 0) {
+		re_strings(&re_Oops_eip_ppc, line, re_Oops_eip_ppc_pmatch,
+			string);
+		return((*string)[re_Oops_eip_ppc.re_nsub]);
+	}
+
+	/* Oops 'EIP:' line for MIPS, epc, optional white space, ':',
+	 * optional white space, unbracketed address.
+	 */
+	re_compile(&re_Oops_eip_mips,
+			"^(epc[ \t]*:+[ \t]*)"
+			UNBRACKETED_ADDRESS,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_eip_mips_pmatch);
+
+	re_string_check(re_Oops_eip_mips.re_nsub+1, string_max, procname);
+	i = regexec(&re_Oops_eip_mips, line, re_Oops_eip_mips.re_nsub+1,
+		re_Oops_eip_mips_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec mips %d\n", procname, i);
+	if (i == 0) {
+		re_strings(&re_Oops_eip_mips, line, re_Oops_eip_mips_pmatch,
+			string);
+		return((*string)[re_Oops_eip_mips.re_nsub]);
+	}
+
+	/* Oops 'EIP:' line for other architectures */
+	re_compile(&re_Oops_eip_other,
+			"^("
+	/* i386 */	"(EIP:[ \t]+.*)"
+	/* m68k */	"|(PC[ \t]*=[ \t]*)"
+			")"
+			BRACKETED_ADDRESS
+			,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_eip_other_pmatch);
+
+	re_string_check(re_Oops_eip_other.re_nsub+1, string_max, procname);
+	i = regexec(&re_Oops_eip_other, line, re_Oops_eip_other.re_nsub+1,
+		re_Oops_eip_other_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec other %d\n", procname, i);
+	if (i == 0) {
+		re_strings(&re_Oops_eip_other, line, re_Oops_eip_other_pmatch,
+			string);
+		return((*string)[re_Oops_eip_other.re_nsub]);
+	}
+	return(NULL);
+}
+
+/* Set the eip from the EIP line */
+static void Oops_set_eip(const char *value, elf_addr_t *eip, SYMBOL_SET *ss)
+{
+	static const char procname[] = "Oops_set_eip";
+	errno = 0;
+	*eip = strtoul(value, NULL, 16);
+	if (errno) {
+		fprintf(stderr,
+			"%s Invalid hex value in EIP line, ignored - '%s'\n",
+			procname, value);
+		perror(" ");
+		++errors;
+		*eip = 0;
+	}
+	add_symbol_n(ss, *eip, 'E', 1, ">>EIP:");
+}
+
+/* Look for the MIPS ra line, returns start of the relevant hex value */
+static char *Oops_ra(const char *line, char ***string, int string_max)
+{
+	int i;
+	static regex_t     re_Oops_ra;
+	static regmatch_t *re_Oops_ra_pmatch;
+	static const char procname[] = "Oops_ra";
+
+	/* Oops 'ra:' line for MIPS, ra, optional white space, one or
+	 * more '=', optional white space, unbracketed address.
+	 */
+	re_compile(&re_Oops_ra,
+			"(ra[ \t]*=+[ \t]*)"
+			UNBRACKETED_ADDRESS,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_ra_pmatch);
+
+	re_string_check(re_Oops_ra.re_nsub+1, string_max, procname);
+	i = regexec(&re_Oops_ra, line, re_Oops_ra.re_nsub+1,
+		re_Oops_ra_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec %d\n", procname, i);
+	if (i == 0) {
+		re_strings(&re_Oops_ra, line, re_Oops_ra_pmatch,
+			string);
+		return((*string)[re_Oops_ra.re_nsub]);
+	}
+	return(NULL);
+}
+
+/* Set the MIPS ra from the ra line */
+static void Oops_set_ra(const char *value, SYMBOL_SET *ss)
+{
+	static const char procname[] = "Oops_set_ra";
+	elf_addr_t ra;
+	errno = 0;
+	ra = strtoul(value, NULL, 16);
+	if (errno) {
+		fprintf(stderr,
+			"%s Invalid hex value in ra line, ignored - '%s'\n",
+			procname, value);
+		perror(" ");
+		++errors;
+		ra = 0;
+	}
+	add_symbol_n(ss, ra, 'R', 1, ">>RA :");
+}
+
+/* Look for the Trace multilines :(.  Returns start of addresses. */
+static const char *Oops_trace(const char *line, char ***string, int string_max)
+{
+	int i;
+	const char *start = NULL;
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre4 failed'
fi
echo 'End of  part 4'
echo 'File patch-2.2.0-pre4 is continued in part 5'
echo 5 > _shar_seq_.tmp