Linux Kernel Patch v2.1, patch-2.2.0-pre4 (0/5)

0 views
Skip to first unread message

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 4, 1999, 3:00:00 AM1/4/99
to
Archive-name: v2.1/patch-2.2.0-pre4/part0

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.

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 4, 1999, 3:00:00 AM1/4/99
to
Archive-name: v2.1/patch-2.2.0-pre4/part1

#!/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

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 4, 1999, 3:00:00 AM1/4/99
to
Archive-name: v2.1/patch-2.2.0-pre4/part2

#!/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 = &param;
+ 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

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 4, 1999, 3:00:00 AM1/4/99
to
Archive-name: v2.1/patch-2.2.0-pre4/part3

#!/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

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 4, 1999, 3:00:00 AM1/4/99
to
Archive-name: v2.1/patch-2.2.0-pre4/part4

#!/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

Reply all
Reply to author
Forward
0 new messages