diff -u --recursive --new-file v2.1.81/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.81/linux/Documentation/Configure.help	Thu Jan 15 14:33:05 1998
+++ linux/Documentation/Configure.help	Sun Jan 25 09:59:59 1998
@@ -479,6 +479,17 @@
   MicroSolutions backpack PD/CD drive and the Imation Superdisk
   LS-120 drive.
 
+Parallel port ATAPI tapes
+CONFIG_PARIDE_PT
+  This option enable the high-level driver for ATAPI tape devices
+  connected through a parallel port.  If you chose to build PARIDE
+  support into your kernel, you may answer Y here to build in the
+  parallel port ATAPI disk driver, otherwise you should answer M
+  to build it as a loadable module.  The module will be called pt.o.
+  You must also have at least one parallel port protocol driver in
+  your system.  Among the devices supported by this driver is the
+  parallel port version of the HP 5GB drive.
+
 ATEN EH-100 protocol
 CONFIG_PARIDE_ATEN 
   This option enables support for the ATEN EH-100 parallel port IDE
@@ -1181,6 +1192,12 @@
   Say Y here if you need support for the parallel port hardware on Sun
   Ultra/AX machines.  This code is also available as a module (say M),
   called parport_ax.o.  If in doubt, saying N is the safe plan.
+
+Foreign parallel hardware
+CONFIG_PARPORT_OTHER
+  Say Y here if you want to be able to load driver modules to support
+  other types of parallel port.  This causes a performance loss, so most
+  people say N.
 
 Compile the kernel into the ELF object format 
 CONFIG_ELF_KERNEL
diff -u --recursive --new-file v2.1.81/linux/Documentation/cdrom/ide-cd linux/Documentation/cdrom/ide-cd
--- v2.1.81/linux/Documentation/cdrom/ide-cd	Tue Dec  2 11:41:44 1997
+++ linux/Documentation/cdrom/ide-cd	Sun Jan 25 10:11:40 1998
@@ -1,12 +1,12 @@
 IDE-CD driver documentation
-19 May 1996
-scott snyder  <snyder@fnald0.fnal.gov>
+Originally by scott snyder  <snyder@fnald0.fnal.gov> (19 May 1996)
+Carrying on the torch is: Erik Andersen <andersee@debian.org>
 
 1. Introduction
 ---------------
 
-The ide-cd driver should work with all ATAPI 1.2 compliant cdrom
-drives which attach to an IDE interface.  Note that some cdrom vendors
+The ide-cd driver should work with all ATAPI ver 1.2 to ATAPI 2.6 compliant 
+cdrom drives which attach to an IDE interface.  Note that some cdrom vendors
 (including Mitsumi, Sony, Creative, Aztech, and Goldstar) have made
 both ATAPI-compliant drives and drives which use a proprietary
 interface.  If your drive uses one of those proprietary interfaces,
@@ -28,9 +28,7 @@
 
  - On drives which support it, reading digital audio data directly
    from audio tracks.  The program cdda2wav can be used for this.
-   Note, however, that only a few drives actually support this
-   function; the only ones which i've heard of successes with are Sony
-   and Toshiba drives.
+   Note, however, that only some drives actually support this.
 
  - There is now support for cdrom changers which comply with the 
    ATAPI 2.6 draft standard (such as the NEC CDR-251).  This additional
@@ -50,10 +48,13 @@
    driver.
 
 1. Make sure that the ide and ide-cd drivers are compiled into the
-   kernel you're using.  When configuring the kernel, say `yes' to the
-   options 
+   kernel you're using.  When configuring the kernel, in the section 
+   entitled "Floppy, IDE, and other block devices", say either `Y' 
+   (which will compile the support directly into the kernel) or `M'
+   (to compile support as a module which can be loaded and unloaded)
+   to the options: 
 
-      Enhanced IDE/MFM/RLL disk/cdrom/tape support
+      Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support
       Include IDE/ATAPI CDROM support
 
    and `no' to
@@ -74,8 +75,8 @@
    address and an IRQ number, the standard assignments being
    0x170 and 14 for the primary interface and 0x1f0 and 15 for the
    secondary interface.  Each interface can control up to two devices,
-   where each device can be either a hard drive, a cdrom drive, or a
-   tape drive.  The two devices on an interface are called `master'
+   where each device can be a hard drive, a cdrom drive, a floppy drive, 
+   or a tape drive.  The two devices on an interface are called `master'
    and `slave'; this is usually selectable via a jumper on the drive.
 
    Linux names these devices as follows.  The master and slave devices
@@ -223,7 +224,9 @@
    - If the autoprobing is not finding your drive, you can tell the
      driver to assume that one exists by using a lilo option of the
      form `hdX=cdrom', where X is the drive letter corresponding to
-     where your drive is installed (see section 2).  Note that if you
+     where your drive is installed (see section 2). This is required
+     for CDROM drives such as the Pioneer DR-A24X, which do not properly
+     identify themselves as ATAPI CDROM drives.  Note that if you
      do this and you see a boot message like
 
        hdX: ATAPI cdrom (?)
diff -u --recursive --new-file v2.1.81/linux/Documentation/paride.txt linux/Documentation/paride.txt
--- v2.1.81/linux/Documentation/paride.txt	Sun Dec 28 12:05:44 1997
+++ linux/Documentation/paride.txt	Sun Jan 25 09:59:59 1998
@@ -55,7 +55,7 @@
 	pd	IDE disk
 	pcd	ATAPI CD-ROM
 	pf	ATAPI disk
-	pt	ATAPI tape	(not yet available)
+	pt	ATAPI tape
 
 (Support for ATAPI CD-R and CD-RW drives is not yet in development,
 but this may change.)
diff -u --recursive --new-file v2.1.81/linux/Makefile linux/Makefile
--- v2.1.81/linux/Makefile	Fri Jan 23 18:10:31 1998
+++ linux/Makefile	Sun Jan 25 16:17:29 1998
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 81
+SUBLEVEL = 82
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
@@ -211,21 +211,29 @@
 
 oldconfig: symlinks scripts/split-include
 	$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
-	scripts/split-include include/linux/autoconf.h include/config
+	if [ -r include/linux/autoconf.h ]; then \
+	    scripts/split-include include/linux/autoconf.h include/config; \
+	fi
 
 xconfig: symlinks scripts/split-include
 	$(MAKE) -C scripts kconfig.tk
 	wish -f scripts/kconfig.tk
-	scripts/split-include include/linux/autoconf.h include/config
+	if [ -r include/linux/autoconf.h ]; then \
+	    scripts/split-include include/linux/autoconf.h include/config; \
+	fi
 
 menuconfig: include/linux/version.h symlinks scripts/split-include
 	$(MAKE) -C scripts/lxdialog all
 	$(CONFIG_SHELL) scripts/Menuconfig arch/$(ARCH)/config.in
-	scripts/split-include include/linux/autoconf.h include/config
+	if [ -r include/linux/autoconf.h ]; then \
+	    scripts/split-include include/linux/autoconf.h include/config; \
+	fi
 
 config: symlinks scripts/split-include
 	$(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in
-	scripts/split-include include/linux/autoconf.h include/config
+	if [ -r include/linux/autoconf.h ]; then \
+	    scripts/split-include include/linux/autoconf.h include/config; \
+	fi
 
 linuxsubdirs: dummy
 	set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.1.81/linux/arch/alpha/config.in	Mon Jan 12 14:51:14 1998
+++ linux/arch/alpha/config.in	Mon Jan 26 11:43:18 1998
@@ -141,6 +141,7 @@
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     bool 'PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
   fi
+  bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
 fi
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
@@ -155,6 +156,9 @@
 tristate 'Parallel port support' CONFIG_PARPORT
 if [ "$CONFIG_PARPORT" != "n" ]; then
   dep_tristate '  PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+  if [ "$CONFIG_PARPORT_PC" != "n" ]; then
+    bool '   Support foreign hardware' CONFIG_PARPORT_OTHER
+  fi
 fi
 endmenu
 
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.1.81/linux/arch/alpha/defconfig	Wed Sep 10 11:18:52 1997
+++ linux/arch/alpha/defconfig	Mon Jan 26 11:43:18 1998
@@ -33,6 +33,7 @@
 CONFIG_ALPHA_ALCOR=y
 # CONFIG_ALPHA_P2K is not set
 CONFIG_PCI=y
+CONFIG_PCI_OLD_PROC=y
 CONFIG_ALPHA_EV5=y
 CONFIG_ALPHA_CIA=y
 CONFIG_ALPHA_SRM=y
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/kernel/apecs.c linux/arch/alpha/kernel/apecs.c
--- v2.1.81/linux/arch/alpha/kernel/apecs.c	Mon Jan 12 14:51:14 1998
+++ linux/arch/alpha/kernel/apecs.c	Sun Jan 25 10:35:16 1998
@@ -18,6 +18,10 @@
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
 
+/* NOTE: Herein are back-to-back mb insns.  They are magic. 
+   A plausible explanation is that the i/o controler does not properly
+   handle the system transaction.  Another involves timing.  Ho hum.  */
+
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern int alpha_sys_type;
@@ -162,6 +166,7 @@
 	/* access configuration space: */
 	value = *(vuip)addr;
 	mb();
+	mb();  /* magic */
 	if (apecs_mcheck_taken) {
 		apecs_mcheck_taken = 0;
 		value = 0xffffffffU;
@@ -242,6 +247,7 @@
 	/* access configuration space: */
 	*(vuip)addr = value;
 	mb();
+	mb();  /* magic */
 	apecs_mcheck_expected = 0;
 	mb();
 
@@ -539,7 +545,7 @@
 		apecs_mcheck_expected = 0;
 		apecs_mcheck_taken = 1;
 		mb();
-		mb();
+		mb(); /* magic */
 		apecs_pci_clr_err();
 		wrmces(0x7);
 		mb();
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/kernel/cia.c linux/arch/alpha/kernel/cia.c
--- v2.1.81/linux/arch/alpha/kernel/cia.c	Mon Jan 12 14:51:14 1998
+++ linux/arch/alpha/kernel/cia.c	Sun Jan 25 10:35:16 1998
@@ -17,6 +17,10 @@
 #include <asm/ptrace.h>
 #include <asm/mmu_context.h>
 
+/* NOTE: Herein are back-to-back mb insns.  They are magic.
+   A plausible explanation is that the i/o controler does not properly
+   handle the system transaction.  Another involves timing.  Ho hum.  */
+
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern int alpha_sys_type;
@@ -170,6 +174,7 @@
 	/* access configuration space: */
 	value = *(vuip)addr;
 	mb();
+	mb();  /* magic */
 	if (CIA_mcheck_taken) {
 		CIA_mcheck_taken = 0;
 		value = 0xffffffffU;
@@ -244,6 +249,7 @@
 	/* access configuration space: */
 	*(vuip)addr = value;
 	mb();
+	mb();  /* magic */
 
 	CIA_mcheck_expected = 0;
 	mb();
@@ -555,12 +561,13 @@
 	 * ignore the machine check.
 	 */
 	mb();
+	mb();  /* magic */
 	if (CIA_mcheck_expected) {
 		DBGM(("CIA machine check expected\n"));
 		CIA_mcheck_expected = 0;
 		CIA_mcheck_taken = 1;
 		mb();
-		mb();
+		mb();  /* magic */
 		draina();
 		cia_pci_clr_err();
 		wrmces(0x7);
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.1.81/linux/arch/alpha/kernel/entry.S	Sat Jan 10 11:58:12 1998
+++ linux/arch/alpha/kernel/entry.S	Sun Jan 25 16:29:45 1998
@@ -950,7 +950,7 @@
 	.quad sys_semget			/* 205 */
 	.quad sys_semop
 	.quad osf_utsname
-	.quad alpha_ni_syscall
+	.quad sys_lchown
 	.quad osf_shmat
 	.quad sys_shmctl			/* 210 */
 	.quad sys_shmdt
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.1.81/linux/arch/alpha/kernel/irq.c	Fri Jan 23 18:10:31 1998
+++ linux/arch/alpha/kernel/irq.c	Sat Jan 24 09:15:18 1998
@@ -373,7 +373,7 @@
 		if (!action) 
 			continue;
 		len += sprintf(buf+len, "%2d: %10u %c %s",
-			       i, kstat.interrupts[0][i],
+			       i, kstat.irqs[0][i],
 			       (action->flags & SA_INTERRUPT) ? '+' : ' ',
 			       action->name);
 		for (action=action->next; action; action = action->next) {
@@ -567,7 +567,7 @@
 	int cpu = smp_processor_id();
 
 	irq_enter(cpu, irq);
-	kstat.interrupts[0][irq] += 1;
+	kstat.irqs[0][irq] += 1;
 	if (!action) {
 		unexpected_irq(irq, regs);
 	} else {
@@ -590,7 +590,7 @@
 	}
 
 	irq_enter(cpu, irq);
-	kstat.interrupts[0][irq] += 1;
+	kstat.irqs[0][irq] += 1;
 	action = irq_action[irq];
 	/*
 	 * For normal interrupts, we mask it out, and then ACK it.
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.1.81/linux/arch/alpha/kernel/osf_sys.c	Mon Jan 12 14:49:36 1998
+++ linux/arch/alpha/kernel/osf_sys.c	Sun Jan 25 16:32:10 1998
@@ -246,7 +246,7 @@
 	unsigned long ret = -EBADF;
 
 	lock_kernel();
-	if (flags & (MAP_HASSEMAPHORE | MAP_INHERIT | MAP_UNALIGNED))
+	if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
 		printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags);
 	if (!(flags & MAP_ANONYMOUS)) {
 		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/kernel/pyxis.c linux/arch/alpha/kernel/pyxis.c
--- v2.1.81/linux/arch/alpha/kernel/pyxis.c	Mon Jan 12 14:51:14 1998
+++ linux/arch/alpha/kernel/pyxis.c	Sun Jan 25 10:35:16 1998
@@ -16,6 +16,10 @@
 #include <asm/ptrace.h>
 #include <asm/mmu_context.h>
 
+/* NOTE: Herein are back-to-back mb insns.  They are magic.
+   A plausible explanation is that the i/o controler does not properly
+   handle the system transaction.  Another involves timing.  Ho hum.  */
+
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern int alpha_sys_type;
@@ -153,6 +157,7 @@
 	/* access configuration space: */
 	value = *(vuip)addr;
 	mb();
+	mb();  /* magic */
 	if (PYXIS_mcheck_taken) {
 		PYXIS_mcheck_taken = 0;
 		value = 0xffffffffU;
@@ -228,6 +233,7 @@
 	/* access configuration space: */
 	*(vuip)addr = value;
 	mb();
+	mb();  /* magic */
 	PYXIS_mcheck_expected = 0;
 	mb();
 
@@ -473,11 +479,13 @@
 	 * ignore the machine check.
 	 */
 	mb();
+	mb();  /* magic */
 	if (PYXIS_mcheck_expected/* && (mchk_sysdata->epic_dcsr && 0x0c00UL)*/) {
 		DBG(("PYXIS machine check expected\n"));
 		PYXIS_mcheck_expected = 0;
 		PYXIS_mcheck_taken = 1;
 		mb();
+		mb();  /* magic */
 		draina();
 		pyxis_pci_clr_err();
 		wrmces(0x7);
@@ -494,6 +502,7 @@
 		PYXIS_mcheck_expected = 0;
 		PYXIS_mcheck_taken = 1;
 		mb();
+		mb();  /* magic */
 		draina();
 		pyxis_pci_clr_err();
 		wrmces(0x7);
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v2.1.81/linux/arch/alpha/kernel/signal.c	Tue Dec  9 09:31:18 1997
+++ linux/arch/alpha/kernel/signal.c	Sun Jan 25 10:35:16 1998
@@ -116,7 +116,7 @@
 
 asmlinkage int 
 sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,
-		 void *restorer, size_t sigsetsize)
+		 size_t sigsetsize, void *restorer)
 {
 	struct k_sigaction new_ka, old_ka;
 	int ret;
diff -u --recursive --new-file v2.1.81/linux/arch/alpha/kernel/t2.c linux/arch/alpha/kernel/t2.c
--- v2.1.81/linux/arch/alpha/kernel/t2.c	Mon Jan 12 14:51:14 1998
+++ linux/arch/alpha/kernel/t2.c	Sun Jan 25 10:35:16 1998
@@ -20,6 +20,10 @@
 #include <asm/ptrace.h>
 #include <asm/mmu_context.h>
 
+/* NOTE: Herein are back-to-back mb insns.  They are magic.
+   A plausable explanation is that the i/o controler does not properly
+   handle the system transaction.  Another involves timing.  Ho hum.  */
+
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern asmlinkage unsigned long whami(void);
@@ -173,6 +177,7 @@
 	/* access configuration space: */
 	value = *(vuip)addr;
 	mb();
+	mb();  /* magic */
 	if (T2_mcheck_taken) {
 		T2_mcheck_taken = 0;
 		value = 0xffffffffU;
@@ -226,6 +231,7 @@
 	/* access configuration space: */
 	*(vuip)addr = value;
 	mb();
+	mb();  /* magic */
 	T2_mcheck_expected = 0;
 	mb();
 
@@ -480,6 +486,7 @@
 	*(vulp)T2_PERR1 |= *(vulp)T2_PERR1;
 
 	mb();
+	mb();  /* magic */
 	return 0;
 }
 
@@ -530,12 +537,14 @@
 	 * ignore the machine check.
 	 */
 	mb();
+	mb();  /* magic */
 	if (T2_mcheck_expected/* && (mchk_sysdata->epic_dcsr && 0x0c00UL)*/) {
 		DBGMC(("T2 machine check expected\n"));
 		T2_mcheck_taken = 1;
 		t2_clear_errors();
 		T2_mcheck_expected = 0;
 		mb();
+		mb();  /* magic */
 		wrmces(rdmces()|1);/* ??? */
 		draina();
 		return;
diff -u --recursive --new-file v2.1.81/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.1.81/linux/arch/i386/config.in	Tue Jan 20 16:44:57 1998
+++ linux/arch/i386/config.in	Mon Jan 26 11:43:18 1998
@@ -39,6 +39,7 @@
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
   fi
+  bool '   Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
 fi
 bool 'MCA support' CONFIG_MCA
 bool 'System V IPC' CONFIG_SYSVIPC
@@ -56,6 +57,9 @@
 tristate 'Parallel port support' CONFIG_PARPORT
 if [ "$CONFIG_PARPORT" != "n" ]; then
   dep_tristate '   PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+  if [ "$CONFIG_PARPORT_PC" != "n" ]; then
+    bool '   Support foreign hardware' CONFIG_PARPORT_OTHER
+  fi
 fi
 
 endmenu
diff -u --recursive --new-file v2.1.81/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.81/linux/arch/i386/defconfig	Tue Jan 20 16:51:22 1998
+++ linux/arch/i386/defconfig	Mon Jan 26 11:43:18 1998
@@ -30,6 +30,8 @@
 CONFIG_PCI=y
 CONFIG_PCI_BIOS=y
 CONFIG_PCI_DIRECT=y
+# CONFIG_PCI_OPTIMIZE is not set
+CONFIG_PCI_OLD_PROC=y
 # CONFIG_MCA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
diff -u --recursive --new-file v2.1.81/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.1.81/linux/arch/i386/kernel/i386_ksyms.c	Fri Jan 23 18:10:31 1998
+++ linux/arch/i386/kernel/i386_ksyms.c	Sat Jan 24 09:29:46 1998
@@ -35,11 +35,11 @@
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(local_bh_count);
 EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
-EXPORT_SYMBOL(global_bh_lock);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 /* Delay loops */
@@ -73,6 +73,8 @@
 
 /* Global SMP irq stuff */
 EXPORT_SYMBOL(synchronize_irq);
+EXPORT_SYMBOL(synchronize_bh);
+EXPORT_SYMBOL(global_bh_lock);
 EXPORT_SYMBOL(global_irq_holder);
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
diff -u --recursive --new-file v2.1.81/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.1.81/linux/arch/i386/kernel/irq.c	Fri Jan 23 18:10:31 1998
+++ linux/arch/i386/kernel/irq.c	Sat Jan 24 09:16:54 1998
@@ -639,6 +639,7 @@
 	irq_exit(cpu, irq);
 }
 
+#ifdef __SMP__
 /*
  * FIXME! This is completely broken.
  */
@@ -679,6 +680,7 @@
 
 	enable_IO_APIC_irq(irq);
 }
+#endif
 
 /*
  * do_IRQ handles all normal device IRQ's (the special
@@ -714,8 +716,10 @@
 	kstat.irqs[cpu][irq]++;
 
 	do_lowlevel_IRQ = do_8259A_IRQ;
+#ifdef __SMP__
 	if (IO_APIC_IRQ(irq))
 		do_lowlevel_IRQ = do_ioapic_IRQ;
+#endif
 	
 	do_lowlevel_IRQ(irq, cpu, &regs);
 
diff -u --recursive --new-file v2.1.81/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- v2.1.81/linux/arch/i386/kernel/mca.c	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/kernel/mca.c	Sun Jan 25 10:05:46 1998
@@ -65,7 +65,7 @@
 static long mca_do_proc_init( long memory_start, long memory_end );
 static int mca_default_procfn( char* buf, int slot );
 
-static long proc_mca_read( struct inode*, struct file*, char* buf, unsigned long count );
+static ssize_t proc_mca_read( struct file*, char*, size_t, loff_t *);
 static struct file_operations proc_mca_operations = {
 	NULL, proc_mca_read,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
@@ -527,7 +527,7 @@
 */
 
 static int mca_fill( char* page, int pid, int type, char** start,
-	off_t offset, int length)
+	loff_t *offset, int length)
 {
 	int len = 0;
 	int slot = 0;
@@ -571,8 +571,8 @@
 
 #define PROC_BLOCK_SIZE	(3*1024)
 
-long proc_mca_read( struct inode* inode, struct file* file,
-	char* buf, unsigned long count)
+static ssize_t proc_mca_read( struct file* file,
+	char* buf, size_t count, loff_t *ppos)
 {
 	unsigned long page;
 	char *start;
@@ -580,6 +580,7 @@
 	int end;
 	unsigned int type, pid;
 	struct proc_dir_entry *dp;
+	struct inode *inode = file->f_dentry->d_inode;
 
 	if (count < 0)
 		return -EINVAL;
@@ -593,7 +594,7 @@
 	start = 0;
 	dp = (struct proc_dir_entry *) inode->u.generic_ip;
 	length = mca_fill((char *) page, pid, type,
-			    &start, file->f_pos, count);
+			    &start, ppos, count);
 	if (length < 0) {
 		free_page(page);
 		return length;
@@ -601,19 +602,19 @@
 	if (start != 0) {
 		/* We have had block-adjusting processing! */
 		copy_to_user(buf, start, length);
-		file->f_pos += length;
+		*ppos += length;
 		count = length;
 	} else {
 		/* Static 4kB (or whatever) block capacity */
-		if (file->f_pos >= length) {
+		if (*ppos >= length) {
 			free_page(page);
 			return 0;
 		}
-		if (count + file->f_pos > length)
-			count = length - file->f_pos;
-		end = count + file->f_pos;
-		copy_to_user(buf, (char *) page + file->f_pos, count);
-		file->f_pos = end;
+		if (count + *ppos > length)
+			count = length - *ppos;
+		end = count + *ppos;
+		copy_to_user(buf, (char *) page + *ppos, count);
+		*ppos = end;
 	}
 	free_page(page);
 	return count;
diff -u --recursive --new-file v2.1.81/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.1.81/linux/arch/i386/kernel/time.c	Sun Dec 21 17:27:18 1997
+++ linux/arch/i386/kernel/time.c	Sun Jan 25 10:05:46 1998
@@ -248,6 +248,7 @@
 	return count;
 }
 
+#ifndef CONFIG_APM
 /*
  * this is only used if we have fast gettimeoffset:
  */
@@ -255,6 +256,7 @@
 {
 	do_gettimeofday(tv);
 }
+#endif
 
 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
 
diff -u --recursive --new-file v2.1.81/linux/arch/i386/math-emu/fpu_entry.c linux/arch/i386/math-emu/fpu_entry.c
--- v2.1.81/linux/arch/i386/math-emu/fpu_entry.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/fpu_entry.c	Sun Jan 25 11:01:48 1998
@@ -728,11 +728,11 @@
   FPU_verify_area(VERIFY_WRITE, d, 7*4 + 8*10);
 #ifdef PECULIAR_486
   S387->cwd &= ~0xe080;
-  /* An 80486 sets all the reserved bits to 1. */
-  S387->cwd |= 0xffff0000;
+  /* An 80486 sets nearly all of the reserved bits to 1. */
+  S387->cwd |= 0xffff0040;
   S387->swd = sstatus_word() | 0xffff0000;
   S387->twd |= 0xffff0000;
-  S387->fcs |= 0xf8000000;
+  S387->fcs &= ~0xf8000000;
   S387->fos |= 0xffff0000;
 #endif PECULIAR_486
   __copy_to_user(d, &S387->cwd, 7*4);
diff -u --recursive --new-file v2.1.81/linux/arch/i386/math-emu/get_address.c linux/arch/i386/math-emu/get_address.c
--- v2.1.81/linux/arch/i386/math-emu/get_address.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/get_address.c	Sun Jan 25 11:01:48 1998
@@ -134,8 +134,8 @@
 
 
 static unsigned long vm86_segment(u_char segment,
-				  unsigned short *selector)
-{ 
+				  struct address *addr)
+{
   segment--;
 #ifdef PARANOID
   if ( segment > PREFIX_SS_ )
@@ -144,14 +144,14 @@
       math_abort(FPU_info,SIGSEGV);
     }
 #endif PARANOID
-  *selector = VM86_REG_(segment);
+  addr->selector = VM86_REG_(segment);
   return (unsigned long)VM86_REG_(segment) << 4;
 }
 
 
 /* This should work for 16 and 32 bit protected mode. */
 static long pm_address(u_char FPU_modrm, u_char segment,
-		       unsigned short *selector, long offset)
+		       struct address *addr, long offset)
 { 
   struct desc_struct descriptor;
   unsigned long base_address, limit, address, seg_top;
@@ -172,13 +172,17 @@
       /* fs and gs aren't used by the kernel, so they still have their
 	 user-space values. */
     case PREFIX_FS_-1:
-      __asm__("mov %%fs,%0":"=r" (*selector));
+      /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
+	 in the assembler statement. */
+      __asm__("mov %%fs,%0":"=r" ((unsigned short)addr->selector));
       break;
     case PREFIX_GS_-1:
-      __asm__("mov %%gs,%0":"=r" (*selector));
+      /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
+	 in the assembler statement. */
+      __asm__("mov %%gs,%0":"=r" ((unsigned short)addr->selector));
       break;
     default:
-      *selector = PM_REG_(segment);
+      addr->selector = PM_REG_(segment);
     }
 
   descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
@@ -312,13 +316,12 @@
     case 0:
       break;
     case VM86:
-      address += vm86_segment(addr_modes.override.segment,
-			      (unsigned short *)&(addr->selector));
+      address += vm86_segment(addr_modes.override.segment, addr);
       break;
     case PM16:
     case SEG32:
       address = pm_address(FPU_modrm, addr_modes.override.segment,
-			   (unsigned short *)&(addr->selector), address);
+			   addr, address);
       break;
     default:
       EXCEPTION(EX_INTERNAL|0x133);
@@ -427,13 +430,12 @@
     case 0:
       break;
     case VM86:
-      address += vm86_segment(addr_modes.override.segment,
-			      (unsigned short *)&(addr->selector));
+      address += vm86_segment(addr_modes.override.segment, addr);
       break;
     case PM16:
     case SEG32:
       address = pm_address(FPU_modrm, addr_modes.override.segment,
-			   (unsigned short *)&(addr->selector), address);
+			   addr, address);
       break;
     default:
       EXCEPTION(EX_INTERNAL|0x131);
diff -u --recursive --new-file v2.1.81/linux/arch/i386/math-emu/reg_ld_str.c linux/arch/i386/math-emu/reg_ld_str.c
--- v2.1.81/linux/arch/i386/math-emu/reg_ld_str.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/reg_ld_str.c	Sun Jan 25 11:01:48 1998
@@ -1329,11 +1329,11 @@
       FPU_verify_area(VERIFY_WRITE, d, 7*4);
 #ifdef PECULIAR_486
       control_word &= ~0xe080;
-      /* An 80486 sets all the reserved bits to 1. */
-      control_word |= 0xffff0000;
+      /* An 80486 sets nearly all of the reserved bits to 1. */
+      control_word |= 0xffff0040;
       partial_status = status_word() | 0xffff0000;
       fpu_tag_word |= 0xffff0000;
-      I387.soft.fcs |= 0xf8000000;
+      I387.soft.fcs &= ~0xf8000000;
       I387.soft.fos |= 0xffff0000;
 #endif PECULIAR_486
       __copy_to_user(d, &control_word, 7*4);
diff -u --recursive --new-file v2.1.81/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.1.81/linux/drivers/block/Config.in	Wed Dec 31 16:42:56 1997
+++ linux/drivers/block/Config.in	Sun Jan 25 09:59:59 1998
@@ -71,13 +71,17 @@
 fi
 tristate 'XT harddisk support' CONFIG_BLK_DEV_XD
 
+# PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
+# PARIDE must also be a module.  The bogus CONFIG_PARIDE_PARPORT option
+# controls the choices given to the user ...
+
 if [ "$CONFIG_PARPORT" = "y" -o "$CONFIG_PARPORT" = "n" ] ; then
    define_bool CONFIG_PARIDE_PARPORT y
 else
    define_bool CONFIG_PARIDE_PARPORT m
 fi
 dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARIDE_PARPORT
-if [ "$CONFIG_PARIDE" != "n" ]; then
+if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
   source drivers/block/paride/Config.in
 fi
 
diff -u --recursive --new-file v2.1.81/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.1.81/linux/drivers/block/ide-cd.c	Sat Jan 10 10:42:55 1998
+++ linux/drivers/block/ide-cd.c	Sun Jan 25 10:11:40 1998
@@ -3,13 +3,14 @@
  * linux/drivers/block/ide-cd.c
  * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder@fnald0.fnal.gov>
  * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
+ *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
  *
  * ATAPI CD-ROM driver.  To be used with ide.c.
  * See Documentation/cdrom/ide-cd for usage information.
  *
- * Suggestions are welcome. Patches that work are more welcome though.
+ * Suggestions are welcome. Patches that work are more welcome though. ;-)
  * For those wishing to work on this driver, please be sure you download
  * and comply with the latest ATAPI standard. This document can be
  * obtained by anonymous ftp from fission.dt.wdc.com in directory:
@@ -182,10 +183,16 @@
  *                     -- fix speed display for ACER 24X, 18X
  * 4.09  Jan 04, 1998  -- fix handling of the last block so we return
  *                         an end of file instead of an I/O error (Gadi)
+ * 4.10  Jan 24, 1998  -- fixed a bug so now changers can change to a new
+ *                         slot when there is no disc in the current slot.
+ *                     -- Fixed a memory leak where info->changer_info was
+ *                         malloc'ed but never free'd when closing the device.
+ *                     -- Cleaned up the global namespace a bit by making more
+ *                         functions static that should already have been.
  *
  *************************************************************************/
 
-#define IDECD_VERSION "4.09"
+#define IDECD_VERSION "4.10"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -1309,7 +1316,7 @@
 /****************************************************************************
  * cdrom driver request routine.
  */
-
+static
 void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
 {
 	if (rq -> cmd == PACKET_COMMAND || rq -> cmd == REQUEST_SENSE_COMMAND)
@@ -2467,10 +2474,6 @@
 	if (drive->usage > 1)
 		return -EBUSY;
 
-	stat = cdrom_check_status (drive, &my_reqbuf);
-	if (stat && my_reqbuf.sense_key == NOT_READY)
-		return -ENOENT;
-
 	if (slot == CDSL_NONE) {
 		(void) cdrom_load_unload (drive, -1, NULL);
 		cdrom_saw_media_change (drive);
@@ -2765,8 +2768,7 @@
         	printk (" changer w/%d slots", nslots);
         else 	
         	printk (" drive");
-	printk (" %s/%dkB Cache\n", 
-		(CDROM_CONFIG_FLAGS (drive)->is_changer)? "&" : "w",  
+	printk (", %dkB Cache\n", 
         	ntohs(buf.cap.buffer_size) );
 
 	return nslots;
@@ -2900,7 +2902,7 @@
 }
 
 /* Forwarding functions to generic routines. */
-
+static
 int ide_cdrom_ioctl (ide_drive_t *drive,
 		     struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
@@ -2908,6 +2910,7 @@
 	return cdrom_fops.ioctl (inode, file, cmd, arg);
 }
 
+static
 int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
 {
 	int rc;
@@ -2921,6 +2924,7 @@
 	return rc;
 }
 
+static
 void ide_cdrom_release (struct inode *inode, struct file *file,
 			ide_drive_t *drive)
 {
@@ -2928,6 +2932,7 @@
 	MOD_DEC_USE_COUNT;
 }
 
+static
 int ide_cdrom_check_media_change (ide_drive_t *drive)
 {
 	return cdrom_fops.check_media_change
@@ -2936,6 +2941,7 @@
 }
 
 
+static
 int ide_cdrom_cleanup(ide_drive_t *drive)
 {
 	struct cdrom_info *info = drive->driver_data;
@@ -2947,6 +2953,8 @@
 		kfree (info->sector_buffer);
 	if (info->toc != NULL)
 		kfree (info->toc);
+	if (info->changer_info != NULL)
+		kfree (info->changer_info);
 	if (devinfo->handle == drive && unregister_cdrom (devinfo))
 		printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
 	kfree (info);
diff -u --recursive --new-file v2.1.81/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
--- v2.1.81/linux/drivers/block/ide-proc.c	Wed Jan 14 13:48:38 1998
+++ linux/drivers/block/ide-proc.c	Mon Jan 26 11:43:19 1998
@@ -274,11 +274,8 @@
 {
 	ide_hwif_t	*hwif = (ide_hwif_t *) data;
 	int		len;
-	const char	*vids, *dids;
 
-	vids = pci_strvendor(hwif->pci_devid.vid);
-	dids = pci_strdev(hwif->pci_devid.vid, hwif->pci_devid.did);
-	len = sprintf(page,"%s: %s\n", vids ? vids : "(none)", dids ? dids : "(none)");
+	len = sprintf(page,"%04x: %04x\n", hwif->pci_devid.vid, hwif->pci_devid.did);
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 #endif	/* CONFIG_PCI */
diff -u --recursive --new-file v2.1.81/linux/drivers/block/paride/Config.in linux/drivers/block/paride/Config.in
--- v2.1.81/linux/drivers/block/paride/Config.in	Sun Dec 28 12:05:45 1997
+++ linux/drivers/block/paride/Config.in	Sun Jan 25 09:59:59 1998
@@ -5,6 +5,7 @@
 dep_tristate '  Parallel port IDE disks' CONFIG_PARIDE_PD $CONFIG_PARIDE
 dep_tristate '  Parallel port ATAPI CD-ROMs' CONFIG_PARIDE_PCD $CONFIG_PARIDE
 dep_tristate '  Parallel port ATAPI disks' CONFIG_PARIDE_PF $CONFIG_PARIDE
+dep_tristate '  Parallel port ATAPI tapes' CONFIG_PARIDE_PT $CONFIG_PARIDE
 comment 'Parallel IDE protocol modules'
 dep_tristate '    ATEN EH-100 protocol' CONFIG_PARIDE_ATEN $CONFIG_PARIDE
 dep_tristate '    MicroSolutions backpack protocol' CONFIG_PARIDE_BPCK $CONFIG_PARIDE
diff -u --recursive --new-file v2.1.81/linux/drivers/block/paride/Makefile linux/drivers/block/paride/Makefile
--- v2.1.81/linux/drivers/block/paride/Makefile	Sun Dec 28 12:05:45 1997
+++ linux/drivers/block/paride/Makefile	Sun Jan 25 09:59:59 1998
@@ -50,6 +50,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_PARIDE_PT),y)
+  LX_OBJS += pt.o
+else
+  ifeq ($(CONFIG_PARIDE_PT),m)
+    MX_OBJS += pt.o
+  endif
+endif
+
 ifeq ($(CONFIG_PARIDE_ATEN),y)
   LX_OBJS += aten.o
 else
diff -u --recursive --new-file v2.1.81/linux/drivers/block/paride/paride.c linux/drivers/block/paride/paride.c
--- v2.1.81/linux/drivers/block/paride/paride.c	Sun Dec 28 12:05:45 1997
+++ linux/drivers/block/paride/paride.c	Sun Jan 25 09:59:59 1998
@@ -473,6 +473,11 @@
           pf_init();
         };
 #endif
+#ifdef CONFIG_PARIDE_PT
+        { extern int pt_init(void);
+          pt_init();
+        };
+#endif
 }
 
 #endif
diff -u --recursive --new-file v2.1.81/linux/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c
--- v2.1.81/linux/drivers/block/paride/pcd.c	Sun Dec 28 12:05:45 1997
+++ linux/drivers/block/paride/pcd.c	Sun Jan 25 09:59:59 1998
@@ -83,7 +83,13 @@
 
 */
 
-#define	PCD_VERSION	"1.0"
+/* Changes:
+
+	1.01	GRG 1997.01.24	Added test unit ready support
+
+*/
+
+#define	PCD_VERSION	"1.01"
 #define PCD_MAJOR	46
 #define PCD_NAME	"pcd"
 #define PCD_UNITS	4
@@ -173,6 +179,7 @@
 #define PCD_RETRIES	     5
 #define PCD_TMO		   800		/* timeout in jiffies */
 #define PCD_DELAY           50          /* spin delay in uS */
+#define PCD_READY_TMO	    20
 
 #define PCD_SPIN		(10000/PCD_DELAY)*PCD_TMO
 
@@ -207,6 +214,7 @@
 	struct pi_adapter pia;	/* interface to paride layer */
 	struct pi_adapter *pi;
 	int drive;		/* master/slave */
+	int last_sense;		/* result of last request sense */
 	int access;		/* count of active opens */
 	int present;		/* does this unit exist ? */
 	char name[PCD_NAMELEN];	/* pcd0, pcd1, etc */
@@ -264,6 +272,7 @@
                 PCD.pi = & PCD.pia;
                 PCD.access = 0;
                 PCD.present = 0;
+		PCD.last_sense = 0;
                 j = 0;
                 while ((j < PCD_NAMELEN-2) && (PCD.name[j]=name[j])) j++;
                 PCD.name[j++] = '0' + unit;
@@ -509,9 +518,13 @@
 	udelay(1000);
 	if (!r) pcd_completion(unit,buf,"Request sense");
 
-        if ((!r)&&(!quiet)) 
-		printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
-	               PCD.name,buf[2]&0xf,buf[12],buf[13]);
+	PCD.last_sense = -1;
+	if (!r) {
+            if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
+	                       PCD.name,buf[2]&0xf,buf[12],buf[13]);
+	    PCD.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
+                                          | ((buf[13]&0xff)<<16) ;
+        } 
 }
 
 static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
@@ -607,13 +620,30 @@
 	return flg-1;	
 }
 
+static int pcd_ready_wait( int unit, int tmo )
+
+{       char    tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
+        int     k, p;
+
+        k = 0;
+        while (k < tmo) {
+          PCD.last_sense = 0;
+          pcd_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
+          p = PCD.last_sense;
+          if (!p) return 0;
+          if (!((p == 0x010402)||((p & 0xff) == 6))) return p;
+          k++;
+          pcd_sleep(100);
+        }
+        return 0x000020;        /* timeout */
+}
+
 static int pcd_check_media( int unit )
 
 {	char    rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0};
 
-	pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("cm1"));
-	pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("cm2"));
-	return (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("cm3")));
+	pcd_ready_wait(unit,PCD_READY_TMO);
+	return (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media")));
 }
 
 static int pcd_identify( int unit, char * id )
diff -u --recursive --new-file v2.1.81/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.1.81/linux/drivers/block/paride/pd.c	Sun Dec 28 12:05:45 1997
+++ linux/drivers/block/paride/pd.c	Sun Jan 25 09:59:59 1998
@@ -96,7 +96,14 @@
  
 */
 
-#define PD_VERSION      "1.0"
+/* Changes:
+
+	1.01	GRG 1997.01.24	Restored pd_reset()
+				Added eject ioctl
+
+*/
+
+#define PD_VERSION      "1.01"
 #define PD_MAJOR	45
 #define PD_NAME		"pd"
 #define PD_UNITS	4
@@ -141,6 +148,7 @@
 #include <linux/delay.h>
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
+#include <linux/cdrom.h>	/* for the eject ioctl */
 
 #include <asm/uaccess.h>
 
@@ -234,6 +242,7 @@
 #define IDE_DOORLOCK    	0xde
 #define IDE_DOORUNLOCK  	0xdf
 #define IDE_IDENTIFY    	0xec
+#define IDE_EJECT		0xed
 
 int pd_init(void);
 void pd_setup(char * str, int * ints);
@@ -257,6 +266,7 @@
 static void pd_media_check(int unit);
 static void pd_doorlock(int unit, int func);
 static int pd_check_media(kdev_t dev);
+static void pd_eject( int unit);
 
 static struct hd_struct pd_hd[PD_DEVS];
 static int pd_sizes[PD_DEVS];
@@ -435,6 +445,9 @@
 	if (!PD.present) return -ENODEV;
 
         switch (cmd) {
+	    case CDROMEJECT:
+		if (PD.access == 1) pd_eject(unit);
+		return 0;
             case HDIO_GETGEO:
                 if (!geo) return -EINVAL;
                 err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
@@ -642,7 +655,6 @@
 	printk("\n");
 }
 
-/*
 static void pd_reset( int unit )
 
 {       pi_connect(PI);
@@ -650,8 +662,8 @@
         udelay(50);
         WR(1,6,0);
 	pi_disconnect(PI);
+	udelay(250);
 }
-*/
 
 #define DBMSG(msg)	NULL
 
@@ -730,6 +742,18 @@
         pi_disconnect(PI);
 }
 
+static void pd_eject( int unit )
+
+{	pi_connect(PI);
+        pd_wait_for(unit,0,DBMSG("before unlock on eject"));
+        pd_send_command(unit,1,0,0,0,0,IDE_DOORUNLOCK);
+        pd_wait_for(unit,0,DBMSG("after unlock on eject"));
+        pd_wait_for(unit,0,DBMSG("before eject"));
+        pd_send_command(unit,0,0,0,0,0,IDE_EJECT);
+        pd_wait_for(unit,0,DBMSG("after eject"));
+        pi_disconnect(PI);
+}
+
 static void pd_media_check( int unit )
 
 {       int 	r;
@@ -766,6 +790,8 @@
 
 {       int	j;
 	char id[PD_ID_LEN+1];
+
+	pd_reset(unit);
 
         pi_connect(PI);
 	WR(0,6,0xa0);
diff -u --recursive --new-file v2.1.81/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c
--- v2.1.81/linux/drivers/block/paride/pt.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/paride/pt.c	Sun Jan 25 09:59:59 1998
@@ -0,0 +1,957 @@
+/* 
+        pt.c    (c) 1998  Grant R. Guenther <grant@torque.net>
+                          Under the terms of the GNU public license.
+
+        This is the high-level driver for parallel port ATAPI tape
+        drives based on chips supported by the paride module.
+
+	The driver implements both rewinding and non-rewinding
+	devices, filemarks, and the rewind ioctl.  It allocates
+	a small internal "bounce buffer" for each open device, but
+        otherwise expects buffering and blocking to be done at the
+        user level.  As with most block-structured tapes, short
+	writes are padded to full tape blocks, so reading back a file
+        may return more data than was actually written.
+
+        By default, the driver will autoprobe for a single parallel
+        port ATAPI tape drive, but if their individual parameters are
+        specified, the driver can handle up to 4 drives.
+
+	The rewinding devices are named /dev/pt0, /dev/pt1, ...
+	while the non-rewinding devices are /dev/npt0, /dev/npt1, etc.
+
+        The behaviour of the pt driver can be altered by setting
+        some parameters from the insmod command line.  The following
+        parameters are adjustable:
+
+            drive0      These four arguments can be arrays of       
+            drive1      1-6 integers as follows:
+            drive2
+            drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
+
+                        Where,
+
+                <prt>   is the base of the parallel port address for
+                        the corresponding drive.  (required)
+
+                <pro>   is the protocol number for the adapter that
+                        supports this drive.  These numbers are
+                        logged by 'paride' when the protocol modules
+                        are initialised.  (0 if not given)
+
+                <uni>   for those adapters that support chained
+                        devices, this is the unit selector for the
+                        chain of devices on the given port.  It should
+                        be zero for devices that don't support chaining.
+                        (0 if not given)
+
+                <mod>   this can be -1 to choose the best mode, or one
+                        of the mode numbers supported by the adapter.
+                        (-1 if not given)
+
+                <slv>   ATAPI devices can be jumpered to master or slave.
+                        Set this to 0 to choose the master drive, 1 to
+                        choose the slave, -1 (the default) to choose the
+                        first drive found.
+
+                <dly>   some parallel ports require the driver to 
+                        go more slowly.  -1 sets a default value that
+                        should work with the chosen protocol.  Otherwise,
+                        set this to a small integer, the larger it is
+                        the slower the port i/o.  In some cases, setting
+                        this to zero will speed up the device. (default -1)
+
+	    major	You may use this parameter to overide the
+			default major number (96) that this driver
+			will use.  Be sure to change the device
+			name as well.
+
+	    name	This parameter is a character string that
+			contains the name the kernel will use for this
+			device (in /proc output, for instance).
+			(default "pt").
+
+            verbose     This parameter controls the amount of logging
+                        that is done while the driver probes for
+                        devices.  Set it to 0 for a quiet load, or 1 to
+                        see all the progress messages.  (default 0)
+
+        If this driver is built into the kernel, you can use 
+        the following command line parameters, with the same values
+        as the corresponding module parameters listed above:
+
+            pt.drive0
+            pt.drive1
+            pt.drive2
+            pt.drive3
+
+        In addition, you can use the parameter pt.disable to disable
+        the driver entirely.
+
+*/
+
+#define PT_VERSION      "1.0"
+#define PT_MAJOR	96
+#define PT_NAME		"pt"
+#define PT_UNITS	4
+
+/* Here are things one can override from the insmod command.
+   Most are autoprobed by paride unless set here.  Verbose is on
+   by default.
+
+*/
+
+static int	verbose = 0;
+static int	major = PT_MAJOR;
+static char	*name = PT_NAME;
+static int      disable = 0;
+
+static int drive0[6] = {0,0,0,-1,-1,-1};
+static int drive1[6] = {0,0,0,-1,-1,-1};
+static int drive2[6] = {0,0,0,-1,-1,-1};
+static int drive3[6] = {0,0,0,-1,-1,-1};
+
+static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
+static int pt_drive_count;
+
+#define D_PRT   0
+#define D_PRO   1
+#define D_UNI   2
+#define D_MOD   3
+#define D_SLV   4
+#define D_DLY   5
+
+#define DU              (*drives[unit])
+
+/* end of parameters */
+
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/mtio.h>
+
+#include <asm/uaccess.h>
+
+#ifndef MODULE
+
+#include "setup.h"
+
+static STT pt_stt[5] = {{"drive0",6,drive0},
+                        {"drive1",6,drive1},
+                        {"drive2",6,drive2},
+                        {"drive3",6,drive3},
+			{"disable",1,&disable}};
+
+void pt_setup( char *str, int *ints)
+
+{       generic_setup(pt_stt,5,str);
+}
+
+#endif
+
+MODULE_PARM(verbose,"i");
+MODULE_PARM(major,"i");
+MODULE_PARM(name,"s");
+MODULE_PARM(drive0,"1-6i");
+MODULE_PARM(drive1,"1-6i");
+MODULE_PARM(drive2,"1-6i");
+MODULE_PARM(drive3,"1-6i");
+
+#include "paride.h"
+
+#define PT_MAX_RETRIES  5
+#define PT_TMO          800             /* interrupt timeout in jiffies */
+#define PT_SPIN_DEL     50              /* spin delay in micro-seconds  */
+#define PT_RESET_TMO    30		/* 3 seconds */
+#define PT_READY_TMO	60		/* 60 seconds */
+#define PT_REWIND_TMO	1200		/* 20 minutes */
+
+#define PT_SPIN         (10000/PT_SPIN_DEL)*PT_TMO  
+
+#define STAT_ERR        0x00001
+#define STAT_INDEX      0x00002
+#define STAT_ECC        0x00004
+#define STAT_DRQ        0x00008
+#define STAT_SEEK       0x00010
+#define STAT_WRERR      0x00020
+#define STAT_READY      0x00040
+#define STAT_BUSY       0x00080
+#define STAT_SENSE	0x1f000
+
+#define ATAPI_TEST_READY	0x00
+#define ATAPI_REWIND		0x01
+#define ATAPI_REQ_SENSE		0x03
+#define ATAPI_READ_6		0x08
+#define ATAPI_WRITE_6		0x0a
+#define ATAPI_WFM		0x10
+#define ATAPI_IDENTIFY		0x12
+#define ATAPI_MODE_SENSE	0x1a
+#define ATAPI_LOG_SENSE		0x4d
+
+int pt_init(void);
+#ifdef MODULE
+void cleanup_module( void );
+#endif
+
+static int pt_open(struct inode *inode, struct file *file);
+static int pt_ioctl(struct inode *inode,struct file *file,
+                    unsigned int cmd, unsigned long arg);
+static int pt_release (struct inode *inode, struct file *file);
+static ssize_t pt_read(struct file * filp, char * buf, 
+                       size_t count, loff_t *ppos);
+static ssize_t pt_write(struct file * filp, const char * buf, 
+                        size_t count, loff_t *ppos);
+static int pt_detect(void);
+
+static int pt_identify (int unit);
+
+/* bits in PT.flags */
+
+#define PT_MEDIA	1
+#define PT_WRITE_OK	2
+#define PT_REWIND	4
+#define PT_WRITING      8
+#define PT_READING     16
+#define PT_EOF	       32
+
+#define PT_NAMELEN      8
+#define PT_BUFSIZE  16384
+
+struct pt_unit {
+	struct pi_adapter pia;    /* interface to paride layer */
+	struct pi_adapter *pi;
+	int flags;        	  /* various state flags */
+	int last_sense;		  /* result of last request sense */
+	int drive;		  /* drive */
+	int access;               /* count of active opens ... */
+	int bs;			  /* block size */
+	int capacity;             /* Size of tape in KB */
+	int present;		  /* device present ? */
+	char *bufptr;
+	char name[PT_NAMELEN];	  /* pf0, pf1, ... */
+	};
+
+struct pt_unit pt[PT_UNITS];
+
+/*  'unit' must be defined in all functions - either as a local or a param */
+
+#define PT pt[unit]
+#define PI PT.pi
+
+static char pt_scratch[512];            /* scratch block buffer */
+
+/* kernel glue structures */
+
+static struct file_operations pt_fops = {
+        NULL,                   /* lseek - default */
+        pt_read,                /* read */
+        pt_write,               /* write */
+        NULL,                   /* readdir - bad */
+        NULL,                   /* select */
+        pt_ioctl,               /* ioctl */
+        NULL,                   /* mmap */
+        pt_open,                /* open */
+        pt_release,             /* release */
+        NULL,                   /* fsync */
+        NULL,                   /* fasync */
+        NULL,                   /* media change ? */
+        NULL                    /* revalidate new media */
+};
+
+void pt_init_units( void )
+
+{       int     unit, j;
+
+        pt_drive_count = 0;
+        for (unit=0;unit<PT_UNITS;unit++) {
+                PT.pi = & PT.pia;
+                PT.access = 0;
+                PT.flags = 0;
+		PT.last_sense = 0;
+                PT.present = 0;
+		PT.bufptr = NULL;
+		PT.drive = DU[D_SLV];
+                j = 0;
+                while ((j < PT_NAMELEN-2) && (PT.name[j]=name[j])) j++;
+                PT.name[j++] = '0' + unit;
+                PT.name[j] = 0;
+                if (DU[D_PRT]) pt_drive_count++;
+        }
+} 
+
+int pt_init (void)      /* preliminary initialisation */
+
+{       int unit;
+
+	if (disable) return -1;
+
+	pt_init_units();
+
+	if (pt_detect()) return -1;
+
+        if (register_chrdev(major,name,&pt_fops)) {
+                printk("pt_init: unable to get major number %d\n",
+                        major);
+	        for (unit=0;unit<PT_UNITS;unit++)
+        	  if (PT.present) pi_release(PI);
+                return -1;
+        }
+
+        return 0;
+}
+
+#ifdef MODULE
+
+/* Glue for modules ... */
+
+void    cleanup_module(void);
+
+int     init_module(void)
+
+{       int     err;
+        long    flags;
+
+        save_flags(flags);
+        cli();
+
+        err = pt_init();
+
+        restore_flags(flags);
+        return err;
+}
+
+void    cleanup_module(void)
+
+{       long flags;
+	int unit;
+
+        save_flags(flags);
+        cli();
+
+        unregister_chrdev(major,name);
+
+	for (unit=0;unit<PT_UNITS;unit++)
+	  if (PT.present) pi_release(PI);
+	
+        restore_flags(flags);
+}
+
+#endif
+
+#define	WR(c,r,v)	pi_write_regr(PI,c,r,v)
+#define	RR(c,r)		(pi_read_regr(PI,c,r))
+
+#define DRIVE           (0xa0+0x10*PT.drive)
+
+static int pt_wait( int unit, int go, int stop, char * fun, char * msg )
+
+{       int j, r, e, s, p;
+
+        j = 0;
+        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PT_SPIN))
+                udelay(PT_SPIN_DEL);
+
+        if ((r&(STAT_ERR&stop))||(j>=PT_SPIN)) {
+           s = RR(0,7);
+           e = RR(0,1);
+           p = RR(0,2);
+           if (j >= PT_SPIN) e |= 0x100;
+           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
+                           " loop=%d phase=%d\n",
+                            PT.name,fun,msg,r,s,e,j,p);
+           return (e<<8)+s;
+        }
+        return 0;
+}
+
+static int pt_command( int unit, char * cmd, int dlen, char * fun )
+
+{       pi_connect(PI);
+
+        WR(0,6,DRIVE);
+
+        if (pt_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) {
+                pi_disconnect(PI);
+                return -1;
+        }
+
+        WR(0,4,dlen % 256);
+        WR(0,5,dlen / 256);
+        WR(0,7,0xa0);          /* ATAPI packet command */
+
+        if (pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,fun,"command DRQ")) {
+                pi_disconnect(PI);
+                return -1;
+        }
+
+        if (RR(0,2) != 1) {
+           printk("%s: %s: command phase error\n",PT.name,fun);
+           pi_disconnect(PI);
+           return -1;
+        }
+
+        pi_write_block(PI,cmd,12);
+
+        return 0;
+}
+
+static int pt_completion( int unit, char * buf, char * fun )
+
+{       int r, s, n, p;
+
+        r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
+			fun,"completion");
+
+        if (RR(0,7)&STAT_DRQ) { 
+           n = (RR(0,4)+256*RR(0,5));
+	   p = RR(0,2)&3;
+	   if (p == 0) pi_write_block(PI,buf,n);
+	   if (p == 2) pi_read_block(PI,buf,n);
+        }
+
+        s = pt_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done");
+
+        pi_disconnect(PI); 
+
+        return (r?r:s);
+}
+
+static void pt_req_sense( int unit, int quiet )
+
+{       char    rs_cmd[12] = { ATAPI_REQ_SENSE,0,0,0,16,0,0,0,0,0,0,0 };
+        char    buf[16];
+        int     r;
+
+        r = pt_command(unit,rs_cmd,16,"Request sense");
+        udelay(1000);
+        if (!r) pt_completion(unit,buf,"Request sense");
+
+	PT.last_sense = -1;
+        if (!r) {
+	    if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
+                                    PT.name,buf[2]&0xf,buf[12],buf[13]);
+	    PT.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
+					 | ((buf[13]&0xff)<<16) ;
+	} 
+}
+
+static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
+
+{       int r;
+
+        r = pt_command(unit,cmd,dlen,fun);
+        udelay(1000);
+        if (!r) r = pt_completion(unit,buf,fun);
+        if (r) pt_req_sense(unit,!fun);
+        
+        return r;
+}
+
+static void pt_sleep( int cs )
+
+{       current->state = TASK_INTERRUPTIBLE;
+        current->timeout = jiffies + cs;
+        schedule();
+}
+
+static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
+
+{	int	k, e, s;
+
+	k = 0;
+	while (k < tmo) {
+		pt_sleep(pause);
+		k++;
+		pi_connect(PI);
+		WR(0,6,DRIVE);
+		s = RR(0,7);
+		e = RR(0,1);
+		pi_disconnect(PI);
+		if (s & (STAT_ERR|STAT_SEEK)) break;
+	}
+	if ((k >= tmo) || (s & STAT_ERR)) {
+	   if (k >= tmo) printk("%s: %s DSC timeout\n",PT.name,msg);
+	     else printk("%s: %s stat=0x%x err=0x%x\n",PT.name,msg,s,e);
+	   pt_req_sense(unit,0);
+	   return 0;
+	}
+	return 1;
+}
+
+static void pt_media_access_cmd( int unit, int tmo, char *cmd, char *fun)
+
+{	if (pt_command(unit,cmd,0,fun)) {
+		pt_req_sense(unit,0);
+		return;
+	}
+	pi_disconnect(PI);
+	pt_poll_dsc(unit,100,tmo,fun);
+}
+
+static void pt_rewind( int unit )
+
+{	char	rw_cmd[12] = {ATAPI_REWIND,0,0,0,0,0,0,0,0,0,0,0};
+
+	pt_media_access_cmd(unit,PT_REWIND_TMO,rw_cmd,"rewind");
+}
+
+static void pt_write_fm( int unit )
+
+{	char	wm_cmd[12] = {ATAPI_WFM,0,0,0,1,0,0,0,0,0,0,0};
+
+        pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark");
+}
+
+#define DBMSG(msg)      NULL
+
+static int pt_reset( int unit )
+
+{	int	i, k, flg;
+	int	expect[5] = {1,1,1,0x14,0xeb};
+	long	flags;
+
+	pi_connect(PI);
+	WR(0,6,DRIVE);
+	WR(0,7,8);
+
+	save_flags(flags);
+	sti();
+
+	pt_sleep(2);
+
+        k = 0;
+        while ((k++ < PT_RESET_TMO) && (RR(1,6)&STAT_BUSY))
+                pt_sleep(10);
+
+	restore_flags(flags);
+
+	flg = 1;
+	for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
+
+	if (verbose) {
+		printk("%s: Reset (%d) signature = ",PT.name,k);
+		for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
+		if (!flg) printk(" (incorrect)");
+		printk("\n");
+	}
+	
+	pi_disconnect(PI);
+	return flg-1;	
+}
+
+static int pt_ready_wait( int unit, int tmo )
+
+{	char	tr_cmd[12] = {ATAPI_TEST_READY,0,0,0,0,0,0,0,0,0,0,0};
+	int	k, p;
+
+	k = 0;
+	while (k < tmo) {
+	  PT.last_sense = 0;
+	  pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
+	  p = PT.last_sense;
+	  if (!p) return 0;
+	  if (!((p == 0x010402)||((p & 0xff) == 6))) return p;
+	  k++;
+          pt_sleep(100);
+	}
+	return 0x000020;	/* timeout */
+}
+
+static void xs( char *buf, char *targ, int offs, int len )
+
+{	int	j,k,l;
+
+	j=0; l=0;
+	for (k=0;k<len;k++) 
+	   if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
+		l=targ[j++]=buf[k+offs];
+	if (l==0x20) j--; targ[j]=0;
+}
+
+static int xn( char *buf, int offs, int size )
+
+{	int	v,k;
+
+	v=0; 
+	for(k=0;k<size;k++) v=v*256+(buf[k+offs]&0xff);
+	return v;
+}
+
+static int pt_identify( int unit )
+
+{	int 	dt, s;
+	char	*ms[2] = {"master","slave"};
+	char	mf[10], id[18];
+	char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
+        char    ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,128,0,0,0,0,0,0,0};
+	char    ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,128,0,0,0};
+	char	buf[36];
+
+        s = pt_atapi(unit,id_cmd,36,buf,"identify");
+	if (s) return -1;
+
+	dt = buf[0] & 0x1f;
+	if (dt != 1) {
+	  	if (verbose) 
+		   printk("%s: Drive %d, unsupported type %d\n",
+				PT.name,PT.drive,dt);
+	  	return -1;
+       	}
+
+	xs(buf,mf,8,8);
+	xs(buf,id,16,16);
+
+	PT.flags = 0;
+	PT.capacity = 0;
+	PT.bs = 0;
+
+	if (!pt_ready_wait(unit,PT_READY_TMO)) PT.flags |= PT_MEDIA;
+
+        if (!pt_atapi(unit,ms_cmd,36,buf,"mode sense")) {
+          if (!(buf[2] & 0x80)) PT.flags |= PT_WRITE_OK;
+	  PT.bs = xn(buf,10,2);
+	}
+
+        if (!pt_atapi(unit,ls_cmd,36,buf,"log sense")) 
+		PT.capacity = xn(buf,24,4);
+
+        printk("%s: %s %s, %s",
+		PT.name,mf,id,ms[PT.drive]);
+        if (!(PT.flags & PT_MEDIA)) 
+                printk(", no media\n");
+        else {  if (!(PT.flags & PT_WRITE_OK)) printk(", RO");
+                printk(", blocksize %d, %d MB\n",
+		       PT.bs,PT.capacity/1024);
+        }
+
+	return 0;
+}
+
+static int pt_probe( int unit )
+
+/*	returns  0, with id set if drive is detected
+	        -1, if drive detection failed
+*/
+
+{	if (PT.drive == -1) {
+	   for (PT.drive=0;PT.drive<=1;PT.drive++)
+		if (!pt_reset(unit)) return pt_identify(unit);
+	} else {
+	   if (!pt_reset(unit)) return pt_identify(unit);
+	}
+        return -1; 
+}
+
+static int pt_detect( void )
+
+{	int	k, unit;
+
+	printk("%s: %s version %s, major %d\n",
+		name,name,PT_VERSION,major);
+
+	k = 0;
+	if (pt_drive_count == 0) {
+	    unit = 0;
+	    if (pi_init(PI,1,-1,-1,-1,-1,-1,pt_scratch,
+                        PI_PT,verbose,PT.name)) {
+	        if (!pt_probe(unit)) {
+			PT.present = 1;
+			k++;
+	        } else pi_release(PI);
+	    }
+
+	} else for (unit=0;unit<PT_UNITS;unit++) if (DU[D_PRT])
+	    if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
+			DU[D_PRO],DU[D_DLY],pt_scratch,PI_PT,verbose,
+			PT.name)) { 
+                if (!pt_probe(unit)) {
+                        PT.present = 1;
+                        k++;
+                } else pi_release(PI);
+            }
+
+	if (k) return 0;
+
+	printk("%s: No ATAPI tape drive detected\n",name);
+	return -1;
+}
+
+#define DEVICE_NR(x)	(x % 128)
+
+static int pt_open (struct inode *inode, struct file *file)
+
+{       int	unit = DEVICE_NR(inode->i_rdev);
+
+        if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV;
+
+        PT.access++;
+
+	if (PT.access > 1) {
+		PT.access--;
+		return -EBUSY;
+	}
+
+        MOD_INC_USE_COUNT;
+
+	pt_identify(unit);
+
+	if (!PT.flags & PT_MEDIA) {
+		PT.access--;
+		MOD_DEC_USE_COUNT;
+		return -ENODEV;
+		}
+
+	if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) {
+		PT.access--;
+		MOD_DEC_USE_COUNT;
+		return -EROFS;
+		}
+
+	if (!(inode->i_rdev & 128)) PT.flags |= PT_REWIND;
+
+	PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
+	if (PT.bufptr == NULL) {
+		PT.access--;
+		MOD_DEC_USE_COUNT;
+		printk("%s: buffer allocation failed\n",PT.name);
+		return -ENOMEM;
+	}
+
+        return 0;
+}
+
+static int pt_ioctl(struct inode *inode,struct file *file,
+                    unsigned int cmd, unsigned long arg)
+
+{       int unit;
+	struct mtop mtop;
+
+
+        if ((!inode) || (!inode->i_rdev)) return -EINVAL;
+        unit = DEVICE_NR(inode->i_rdev);
+        if (unit >= PT_UNITS) return -EINVAL;
+        if (!PT.present) return -ENODEV;
+
+        switch (cmd) {
+
+	    case MTIOCTOP:	
+		if (copy_from_user((char *)&mtop, (char *)arg, 
+			           sizeof(struct mtop))) return -EFAULT;
+
+		switch (mtop.mt_op) {
+
+		    case MTREW: 
+			pt_rewind(unit);
+			return 0;
+
+		    default:	
+			printk("%s: Unimplemented mt_op %d\n",PT.name,
+					mtop.mt_op);
+			return -EINVAL;
+		}
+
+            default:
+		printk("%s: Unimplemented ioctl 0x%x\n",PT.name,cmd);
+                return -EINVAL;
+
+        }
+}
+
+
+static int pt_release (struct inode *inode, struct file *file)
+
+{       int	unit = DEVICE_NR(inode->i_rdev);
+
+        if ((unit >= PT_UNITS) || (PT.access <= 0)) 
+                return -EINVAL;
+
+	if (PT.flags & PT_WRITING) pt_write_fm(unit);
+
+	if (PT.flags & PT_REWIND) pt_rewind(unit);	
+
+	PT.access--;
+
+	kfree(PT.bufptr);
+	PT.bufptr = NULL;
+
+        MOD_DEC_USE_COUNT;
+
+	return 0;
+
+}
+
+static ssize_t pt_read(struct file * filp, char * buf, 
+                       size_t count, loff_t *ppos)
+
+{  	struct 	inode *ino = filp->f_dentry->d_inode;
+	int	unit = DEVICE_NR(ino->i_rdev);
+	char	rd_cmd[12] = {ATAPI_READ_6,1,0,0,0,0,0,0,0,0,0,0};
+	int	k, n, r, p, s, t, b;
+
+	if (!(PT.flags & (PT_READING|PT_WRITING))) {
+	    PT.flags |= PT_READING;
+	    if (pt_atapi(unit,rd_cmd,0,NULL,"start read-ahead"))
+			return -EIO;
+	} else if (PT.flags & PT_WRITING) return -EIO;
+
+	if (PT.flags & PT_EOF) return 0;
+
+	t = 0;
+
+	while (count > 0) {
+
+	    if (!pt_poll_dsc(unit,1,PT_TMO,"read")) return -EIO;
+
+	    n = count;
+	    if (n > 32768) n = 32768;   /* max per command */
+	    b = (n-1+PT.bs)/PT.bs;
+	    n = b*PT.bs;		/* rounded up to even block */
+
+	    rd_cmd[4] = b;
+
+	    r = pt_command(unit,rd_cmd,n,"read");
+
+	    udelay(1000);
+
+	    if (r) {
+	        pt_req_sense(unit,0);
+	        return -EIO;
+	    }
+
+	    while (1) {
+
+	        r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
+                                           DBMSG("read DRQ"),"");
+
+	        if (r & STAT_SENSE) {
+	            pi_disconnect(PI);
+		    pt_req_sense(unit,0);
+		    return -EIO;
+	        }
+
+	        if (r) PT.flags |= PT_EOF; 
+
+	        s = RR(0,7);
+
+	        if (!(s & STAT_DRQ)) break;
+
+	    	n = (RR(0,4)+256*RR(0,5));
+	    	p = (RR(0,2)&3);
+	    	if (p != 2) {
+		    pi_disconnect(PI);
+		    printk("%s: Phase error on read: %d\n",PT.name,p);
+		    return -EIO;
+	    	}
+
+	        while (n > 0) {
+		    k = n;
+		    if (k > PT_BUFSIZE) k = PT_BUFSIZE; 
+		    pi_read_block(PI,PT.bufptr,k);
+		    n -= k;
+		    b = k;
+		    if (b > count) b = count;
+		    copy_to_user(buf+t,PT.bufptr,b);
+		    t += b;
+		    count -= b;
+	        }
+
+	    }
+	    pi_disconnect(PI);
+	    if (PT.flags & PT_EOF) break;
+	}
+
+	return t;
+
+}
+
+static ssize_t pt_write(struct file * filp, const char * buf, 
+                        size_t count, loff_t *ppos)
+
+{       struct inode *ino = filp->f_dentry->d_inode;
+        int unit = DEVICE_NR(ino->i_rdev);
+        char    wr_cmd[12] = {ATAPI_WRITE_6,1,0,0,0,0,0,0,0,0,0,0};
+        int     k, n, r, p, s, t, b;
+
+	if (!(PT.flags & PT_WRITE_OK)) return -EROFS;
+
+        if (!(PT.flags & (PT_READING|PT_WRITING))) {
+            PT.flags |= PT_WRITING;
+            if (pt_atapi(unit,wr_cmd,0,NULL,"start buffer-available mode"))
+                        return -EIO;
+        } else if (PT.flags&PT_READING) return -EIO;
+
+	if (PT.flags & PT_EOF) return -ENOSPC;
+
+	t = 0;
+
+	while (count > 0) {
+
+	    if (!pt_poll_dsc(unit,1,PT_TMO,"write")) return -EIO;
+
+            n = count;
+            if (n > 32768) n = 32768;	/* max per command */
+            b = (n-1+PT.bs)/PT.bs;
+            n = b*PT.bs;                /* rounded up to even block */
+
+            wr_cmd[4] = b;
+
+            r = pt_command(unit,wr_cmd,n,"write");
+
+            udelay(1000);
+
+            if (r) {			/* error delivering command only */
+                pt_req_sense(unit,0);
+                return -EIO;
+            }
+
+	    while (1) {
+
+                r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
+			                        DBMSG("write DRQ"),NULL);
+
+                if (r & STAT_SENSE) {
+                    pi_disconnect(PI);
+                    pt_req_sense(unit,0);
+                    return -EIO;
+                }
+
+                if (r) PT.flags |= PT_EOF;
+
+	        s = RR(0,7);
+
+	        if (!(s & STAT_DRQ)) break;
+
+                n = (RR(0,4)+256*RR(0,5));
+                p = (RR(0,2)&3);
+                if (p != 0) {
+                    pi_disconnect(PI);
+                    printk("%s: Phase error on write: %d \n",PT.name,p);
+                    return -EIO;
+                }
+
+                while (n > 0) {
+		    k = n;
+		    if (k > PT_BUFSIZE) k = PT_BUFSIZE;
+		    b = k;
+		    if (b > count) b = count;
+		    copy_from_user(PT.bufptr,buf+t,b);
+                    pi_write_block(PI,PT.bufptr,k);
+		    t += b;
+		    count -= b;
+		    n -= k;
+                }
+
+	    }
+	    pi_disconnect(PI);
+	    if (PT.flags & PT_EOF) break;
+	}
+
+	return t;
+}
+
+/* end of pt.c */
+
diff -u --recursive --new-file v2.1.81/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.1.81/linux/drivers/cdrom/cdrom.c	Mon Jan  5 00:06:26 1998
+++ linux/drivers/cdrom/cdrom.c	Sun Jan 25 10:11:40 1998
@@ -1,6 +1,6 @@
 /* linux/drivers/cdrom/cdrom.c. 
    Copyright (c) 1996, 1997 David A. van Leeuwen.
-   Copyright (c) 1997, 1998 Erik Andersen (andersee@debian.org)
+   Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
 
    May be copied or modified under the terms of the GNU General Public
    License.  See linux/COPYING for more information.
@@ -10,46 +10,71 @@
 
    The routines in the file provide a uniform interface between the
    software that uses CD-ROMs and the various low-level drivers that
-   actually talk to actual hardware devices. Suggestions are welcome.
+   actually talk to the hardware. Suggestions are welcome.
    Patches that work are more welcome though.  ;-)
 
+ To Do List:
+ ----------------------------------
 
-  Recent Changes:
-  ----------------------------------
+ -- Modify sysctl/proc interface. I plan on having one directory per
+ drive, with entries for outputing general drive information, and sysctl
+ based tunable parameters such as whether the tray should auto-close for
+ that drive. Suggestions (or patches) for this welcome!
 
-  New maintainer! As David A. van Leeuwen has been too busy to activly
+ -- Change the CDROMREADMODE1, CDROMREADMODE2, CDROMREADAUDIO, and 
+ CDROMREADRAW ioctls so they go through the Uniform CD-ROM driver.
+
+
+
+
+ Revision History
+ ----------------------------------
+ 1.00  Date Unknown -- David van Leeuwen <david@tm.tno.nl>
+ -- Initial version by David A. van Leeuwen. I don't have a detailed
+  changelog for the 1.x series, David?
+
+2.00  Dec  2, 1997 -- Erik Andersen <andersee@debian.org>
+  -- New maintainer! As David A. van Leeuwen has been too busy to activly
   maintain and improve this driver, I am now carrying on the torch. If
   you have a problem with this driver, please feel free to contact me.
 
-  Added (rudimentary) sysctl interface. I realize this is really weak
-  right now, and is _very_ badly implemented. It will be improved... I
-  plan on having one directory per drive, with entries for outputing
-  general drive information, and sysctl based tunable parameters such
-  as whether the tray should auto-close for that drive. Suggestions (or
-  patches) for improvements are very welcome.
+  -- Added (rudimentary) sysctl interface. I realize this is really weak
+  right now, and is _very_ badly implemented. It will be improved...
 
-  Modified CDROM_DISC_STATUS so that it is now incorporated into
+  -- Modified CDROM_DISC_STATUS so that it is now incorporated into
   the Uniform CD-ROM driver via the cdrom_count_tracks function.
   The cdrom_count_tracks function helps resolve some of the false
   assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check
   for the correct media type when mounting or playing audio from a CD.
 
-  Remove the calls to verify_area and only use the copy_from_user and
+  -- Remove the calls to verify_area and only use the copy_from_user and
   copy_to_user stuff, since these calls now provide their own memory
   checking with the 2.1.x kernels.
 
-  Major update to return codes so that errors from low-level drivers
+  -- Major update to return codes so that errors from low-level drivers
   are passed on through (thanks to Gerd Knorr for pointing out this
   problem).
 
-  Made it so if a function isn't implemented in a low-level driver,
+  -- Made it so if a function isn't implemented in a low-level driver,
   ENOSYS is now returned instead of EINVAL.
 
-  Simplified some complex logic so that the source code is easier to read.
+  -- Simplified some complex logic so that the source code is easier to read.
+
+  -- Other stuff I probably forgot to mention (lots of changes).
+
+2.01 to 2.11 Dec 1997-Jan 1998
+  -- TO-DO!  Write changelogs for 2.01 to 2.12.
 
-  Other stuff I probably forgot to mention (lots of changes).
+2.12  Jan  24, 1998 -- Erik Andersen <andersee@debian.org>
+  -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros.  It turns out that
+  copy_*_user does not return EFAULT on error, but instead return the number 
+  of bytes not copied.  I was returning whatever non-zero stuff came back from 
+  the copy_*_user functions directly, which would result in strange errors.
 
- */
+-------------------------------------------------------------------------*/
+
+#define REVISION "Revision: 2.12"
+#define VERSION "Id: cdrom.c 2.12 1998/01/24 22:15:45 erik Exp"
 
 
 #include <linux/config.h>
@@ -68,10 +93,6 @@
 #include <asm/uaccess.h>
 
 
-#define VERSION "$Id: cdrom.c,v 2.11 1998/01/04 01:11:18 erik Exp $"
-#define REVISION "Revision: 2.11"
-#define FM_WRITE	0x2                 /* file mode write bit */
-
 /* I use an error-log mask to give fine grain control over the type of
    error messages dumped to the system logs.  The available masks include: */
 #define CD_WARNING	0x1
@@ -96,15 +117,17 @@
 #define cdinfo(type, fmt, args...) 
 #endif
 
-
 /* These are used to simplify getting data in from and back to user land */
 #define IOCTL_IN(arg, type, in) { \
-            int ret=copy_from_user(&in, (type *) arg, sizeof in); \
-            if (ret) return ret; }
+            if ( copy_from_user(&in, (type *) arg, sizeof in) ) \
+            	return -EFAULT; }
 
 #define IOCTL_OUT(arg, type, out) { \
-            int ret=copy_to_user((type *) arg, &out, sizeof out); \
-            if (ret) return ret; }
+            if ( copy_to_user((type *) arg, &out, sizeof out) ) \
+            	return -EFAULT; }
+
+
+#define FM_WRITE	0x2                 /* file mode write bit */
 
 /* Not-exported routines. */
 static int cdrom_open(struct inode *ip, struct file *fp);
diff -u --recursive --new-file v2.1.81/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v2.1.81/linux/drivers/cdrom/cdu31a.c	Fri Jan 23 18:10:31 1998
+++ linux/drivers/cdrom/cdu31a.c	Sun Jan 25 10:11:41 1998
@@ -186,6 +186,10 @@
  *                 Heiko Eissfeldt <heiko@colossus.escape.de> with additional
  *                 changes by Erik Andersen <andersee@debian.org>
  *
+ *  24 January 1998 -- Removed the scd_disc_status() function, which was now
+ *                     just dead code left over from the port.
+ *                          Erik Andersen <andersee@debian.org>
+ *
 */
 
 #include <linux/major.h>
@@ -1241,35 +1245,6 @@
    buf[1] = size / 256;
    buf[2] = size % 256;
 }
-
-#if 0
-/* Uniform cdrom interface function.
-   Return the status of the current disc:
-   If it is recognized as CD-I -> return XA Mode 2 Form 2
-   If it is recognized as XA   -> return XA Mode 2 Form 1
-   If there is at least one data track return Mode 1
-   else return type AUDIO
- */
-static int scd_disc_status(struct cdrom_device_info *cdi)
-{
-  if (sony_spun_up)
-  {
-    int i;
-
-    sony_get_toc();
-    /* look into the TOC */
-    if (sony_toc.disk_type == 0x10)   /* this is a CD-I disc */
-      return CDS_XA_2_2;
-    if (sony_toc.disk_type == 0x20)   /* this is a XA disc */
-      return CDS_XA_2_1;
-    for (i = 0; i < sony_toc.track_entries; i++)
-      if (sony_toc.tracks[i].control & CDROM_DATA_TRACK)
-        return CDS_DATA_1;
-    return CDS_AUDIO;
-  } else 
-    return CDS_NO_INFO;
-}
-#endif
 
 /* Starts a read operation. Returns 0 on success and 1 on failure. 
    The read operation used here allows multiple sequential sectors 
diff -u --recursive --new-file v2.1.81/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c
--- v2.1.81/linux/drivers/cdrom/cm206.c	Sun Jan  4 10:55:08 1998
+++ linux/drivers/cdrom/cm206.c	Sun Jan 25 10:11:41 1998
@@ -149,6 +149,8 @@
 
 21 dec 1997   1.4 Upgrade to Linux 2.1.72.  
 
+24 jan 1998   Removed the cm206_disc_status() function, as it was now dead
+              code.  The Uniform CDROM driver now provides this functionality.
  * 
  * Parts of the code are based upon lmscd.c written by Kai Petzke,
  * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
@@ -1140,24 +1142,6 @@
   return CDS_DISC_OK;
 }
  
-/* gives current state of disc in drive */
-int cm206_disc_status(struct cdrom_device_info * cdi)
-{
-  uch xa;
-  get_drive_status();
-  if ((cd->dsb & dsb_not_useful) | !(cd->dsb & dsb_disc_present))
-    return CDS_NO_DISC;
-  get_disc_status();
-  if (DISC_STATUS & cds_all_audio) return CDS_AUDIO;
-  xa = DISC_STATUS >> 4;
-  switch (xa) {
-  case 0: return CDS_DATA_1;	/* can we detect CDS_DATA_2? */
-  case 1: return CDS_XA_2_1;	/* untested */
-  case 2: return CDS_XA_2_2;
-  }
-  return 0;
-}
-
 /* locks or unlocks door lock==1: lock; return 0 upon success */
 int cm206_lock_door(struct cdrom_device_info * cdi, int lock)
 {
@@ -1274,9 +1258,9 @@
   "cm206"			/* name of the device type */
 };
 
-/* This routine gets called during initialization if thing go wrong,
+/* This routine gets called during initialization if things go wrong,
  * can be used in cleanup_module as well. */
-void cleanup(int level)
+static void cleanup(int level)
 {
   switch (level) {
   case 4: 
diff -u --recursive --new-file v2.1.81/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
--- v2.1.81/linux/drivers/cdrom/mcd.c	Tue Dec  2 11:41:44 1997
+++ linux/drivers/cdrom/mcd.c	Sun Jan 25 10:05:46 1998
@@ -1126,9 +1126,9 @@
 
 
 
-/* This routine gets called during initialization if thing go wrong,
+/* This routine gets called during initialization if things go wrong,
  * and is used in cleanup_module as well. */
-void cleanup(int level)
+static void cleanup(int level)
 {
   switch (level) {
   case 3:
diff -u --recursive --new-file v2.1.81/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.1.81/linux/drivers/cdrom/sbpcd.c	Mon Jan  5 00:06:26 1998
+++ linux/drivers/cdrom/sbpcd.c	Sun Jan 25 10:11:41 1998
@@ -304,6 +304,9 @@
  *       Heiko Eissfeldt <heiko@colossus.escape.de> with additional
  *       changes by Erik Andersen <andersee@debian.org>
  *
+ *  4.62 Fix a bug where playing audio left the drive in an unusable state.
+ *         Heiko Eissfeldt <heiko@colossus.escape.de>
+ *
  *
  *  TODO
  *     implement "read all subchannel data" (96 bytes per frame)
@@ -1046,7 +1049,7 @@
 		sbp_sleep(1);
 		i = 1;
 	}
-	msg(DBG_LCS,"CDi_stat_loop failed\n");
+	msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
 	return (-1);
 }
 /*==========================================================================*/
@@ -4295,7 +4298,7 @@
 			}
 			if (status_tries == 0)
 			{
-				msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries.\n");
+				msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
 				continue;
 			}
 			msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
@@ -4467,7 +4470,7 @@
 #endif OLD_BUSY
 		if (data_tries == 0)
 		{
-			msg(DBG_AUD,"read_audio: failed after 5 tries.\n");
+			msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
 			RETURN_UP(-EIO);
 		}
 		msg(DBG_AUD,"read_audio: successful return.\n");
@@ -4651,6 +4654,7 @@
 #endif SAFE_MIXED
 		i=cc_Pause_Resume(1);
 		D_S[d].audio_state=0;
+		cc_DriveReset();
 		RETURN_UP(i);
 		
 	case CDROMSTART:  /* Spin up the drive */
@@ -4886,7 +4890,7 @@
 		}
 		if (status_tries == 0)
 		{
-			msg(DBG_INF,"sbp_status: failed after 3 tries\n");
+			msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
 			break;
 		}
 		
diff -u --recursive --new-file v2.1.81/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.1.81/linux/drivers/char/Config.in	Tue Jan 20 16:44:57 1998
+++ linux/drivers/char/Config.in	Fri Jan 23 20:42:11 1998
@@ -109,7 +109,7 @@
   bool 'Tadpole ANA H8 Support'  CONFIG_H8
 fi
 tristate 'Video For Linux' CONFIG_VIDEO_DEV
-if [ "$CONFIG_VIDEO_DEV" != n ]; then
+if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
   dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
   if [ "$CONFIG_PARPORT" != "n" ]; then
     dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV
diff -u --recursive --new-file v2.1.81/linux/drivers/char/ftape/lowlevel/fdc-io.c linux/drivers/char/ftape/lowlevel/fdc-io.c
--- v2.1.81/linux/drivers/char/ftape/lowlevel/fdc-io.c	Fri Jan 23 18:10:31 1998
+++ linux/drivers/char/ftape/lowlevel/fdc-io.c	Sun Jan 25 10:05:46 1998
@@ -403,10 +403,10 @@
 	current->state = TASK_INTERRUPTIBLE;
 
 	spin_lock_irq(&current->sigmask_lock);
-        old_sigmask = current->blocked;
-        siginitset(&current->blocked, _BLOCK_ALL);
-        recalc_sigpending(current);
-        spin_unlock_irq(&current->sigmask_lock);
+	old_sigmask = current->blocked;
+	sigfillset(&current->blocked);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
 
 	add_wait_queue(&ftape_wait_intr, &wait);
 	while (!ft_interrupt_seen && current->state != TASK_RUNNING) {
@@ -414,9 +414,9 @@
         }
 
 	spin_lock_irq(&current->sigmask_lock);
-        current->blocked = old_sigmask;
-        recalc_sigpending(current);
-        spin_unlock_irq(&current->sigmask_lock);
+	current->blocked = old_sigmask;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
 	
 	remove_wait_queue(&ftape_wait_intr, &wait);
 	/*  the following IS necessary. True: as well
diff -u --recursive --new-file v2.1.81/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.1.81/linux/drivers/char/keyboard.c	Fri Jan 23 18:10:31 1998
+++ linux/drivers/char/keyboard.c	Mon Jan 26 11:43:18 1998
@@ -80,7 +80,6 @@
 /* shift state counters.. */
 static unsigned char k_down[NR_SHIFT] = {0, };
 /* keyboard key bitmap */
-#define BITS_PER_LONG (8*sizeof(unsigned long))
 static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
 
 static int dead_key_next = 0;
diff -u --recursive --new-file v2.1.81/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.1.81/linux/drivers/char/lp.c	Sun Nov 30 14:00:38 1997
+++ linux/drivers/char/lp.c	Fri Jan 23 20:04:03 1998
@@ -1,4 +1,6 @@
 /*
+ * Generic parallel printer driver
+ *
  * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
  * Copyright (C) 1992,1993 by Michael K. Johnson
  * - Thanks much to Gunter Windau for pointing out to me where the error
@@ -11,14 +13,58 @@
  * lp_read (Status readback) support added by Carsten Gross,
  *                                             carsten@sol.wohnheim.uni-ulm.de
  * Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
- * Reverted interrupt to polling at runtime if more than one device is parport
- * registered and joined the interrupt and polling code.
- *                               by Andrea Arcangeli <arcangeli@mbox.queen.it>
+ * parport_sharing hacking by Andrea Arcangeli <arcangeli@mbox.queen.it>
  */
 
-/* This driver is about due for a rewrite. */
+/* This driver should, in theory, work with any parallel port that has an
+ * appropriate low-level driver; all I/O is done through the parport
+ * abstraction layer.  There is a performance penalty for this, but parallel
+ * ports are comparitively low-speed devices anyway.
+ *
+ * If this driver is built into the kernel, you can configure it using the
+ * kernel command-line.  For example:
+ *
+ *      lp=parport1,none,parport2	(bind lp0 to parport1, disable lp1 and
+ *					 bind lp2 to parport2)
+ *
+ *	lp=auto				(assign lp devices to all ports that
+ *				         have printers attached, as determined
+ *					 by the IEEE-1284 autoprobe)
+ * 
+ *      lp=reset			(reset the printer during 
+ *					 initialisation)
+ *
+ *	lp=off				(disable the printer driver entirely)
+ *
+ * If the driver is loaded as a module, similar functionality is available
+ * using module parameters.  The equivalent of the above commands would be:
+ *
+ *	# insmod lp.o parport=1,-1,2	(use -1 for disabled ports, since
+ *					 module parameters do not allow you
+ *					 to mix textual and numeric values)
+ *
+ *      # insmod lp.o autoprobe=1
+ *
+ *	# insmod lp.0 reset=1
+ */
+
+/* COMPATIBILITY WITH OLD KERNELS
+ *
+ * Under Linux 2.0 and previous versions, lp devices were bound to ports at
+ * particular I/O addresses, as follows:
+ *
+ *	lp0		0x3bc
+ *	lp1		0x378
+ *	lp2		0x278
+ *
+ * The new driver, by default, binds lp devices to parport devices as it
+ * finds them.  This means that if you only have one port, it will be bound
+ * to lp0 regardless of its I/O address.  If you need the old behaviour, you
+ * can force it using the parameters described above.
+ */
 
 #include <linux/module.h>
+#include <linux/init.h>
 
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -26,31 +72,24 @@
 #include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/malloc.h>
-#include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
 
+#include <linux/parport.h>
+#include <linux/lp.h>
+
 #include <asm/irq.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <linux/parport.h>
-#include <linux/lp.h>
 
 /* if you have more than 3 printers, remember to increase LP_NO */
-struct lp_struct lp_table[] =
-{
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
-  {0}},
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
-  {0}},
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
-  {0}}
-};
 #define LP_NO 3
 
-/* Device name */
-static char *dev_name = "lp";
+struct lp_struct lp_table[LP_NO] =
+{
+	[0 ... LP_NO-1] = {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT,
+			   NULL, 0, 0, 0, {0}}
+};
 
 /* Test if printer is ready (and optionally has no error conditions) */
 #define LP_READY(minor, status) \
@@ -64,61 +103,60 @@
 #undef LP_DEBUG
 #undef LP_READ_DEBUG
 
-/* Magic numbers */
-#define AUTO -3
-#define OFF -2
-#define UNSPEC -1
+/* --- parport support ----------------------------------------- */
 
-static inline void lp_parport_release (int minor)
+static int lp_preempt(void *handle)
 {
-	parport_release (lp_table[minor].dev);
-	lp_table[minor].should_relinquish = 0;
-}
+       struct lp_struct *lps = (struct lp_struct *)handle;
 
-static inline void lp_parport_claim (int minor)
-{
-	if (parport_claim (lp_table[minor].dev))
-		sleep_on (&lp_table[minor].lp_wait_q);
+       if (waitqueue_active (&lps->dev->wait_q))
+               wake_up_interruptible(&lps->dev->wait_q);
+
+       /* Don't actually release the port now */
+       return 1;
 }
 
-static inline void lp_schedule (int minor)
+#define lp_parport_release(x)	do { parport_release(lp_table[(x)].dev); } while (0);
+#define lp_parport_claim(x)	do { parport_claim_or_block(lp_table[(x)].dev); } while (0);
+
+/* --- low-level port access ----------------------------------- */
+
+#define r_dtr(x)	(parport_read_data(lp_table[(x)].dev->port))
+#define r_str(x)	(parport_read_status(lp_table[(x)].dev->port))
+#define w_ctr(x,y)	do { parport_write_control(lp_table[(x)].dev->port, (y)); } while (0)
+#define w_dtr(x,y)	do { parport_write_data(lp_table[(x)].dev->port, (y)); } while (0)
+
+static __inline__ void lp_yield (int minor)
 {
-	if (lp_table[minor].should_relinquish) {
-		lp_parport_release (minor);
-		schedule ();
-		lp_parport_claim (minor);
-	}
-	else
+	if (parport_yield (lp_table[minor].dev, 1) == 1 && need_resched)
 		schedule ();
 }
 
-
-static int lp_preempt (void *handle)
+static __inline__ void lp_schedule(int minor)
 {
-	struct lp_struct *lps = (struct lp_struct *)handle;
-
-	/* Just remember that someone wants the port */
-	lps->should_relinquish = 1;
-
-	/* Don't actually release the port now */
-	return 1;
+	struct pardevice *dev = lp_table[minor].dev;
+	register unsigned long int timeslip = (jiffies - dev->time);
+	if ((timeslip > dev->timeslice) && (dev->port->waithead != NULL)) {
+		lp_parport_release(minor);
+		schedule ();
+		lp_parport_claim(minor);
+	} else
+		schedule();
 }
 
 static int lp_reset(int minor)
 {
+	int retval;
+	lp_parport_claim (minor);
 	w_ctr(minor, LP_PSELECP);
-	udelay(LP_DELAY);
+	udelay (LP_DELAY);
 	w_ctr(minor, LP_PSELECP | LP_PINITP);
-	return r_str(minor);
-}
-
-static inline int must_use_polling(int minor)
-{
-	return lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE ||
-                      lp_table[minor].dev->port->devices->next;
+	retval = r_str(minor);
+	lp_parport_release (minor);
+	return retval;
 }
 
-static inline int lp_char(char lpchar, int minor, int use_polling)
+static inline int lp_char(char lpchar, int minor)
 {
 	int status;
 	unsigned int wait = 0;
@@ -126,28 +164,33 @@
 	struct lp_stats *stats;
 
 	do {
-		status = r_str(minor);
+		status = r_str (minor);
 		count++;
-		if (need_resched)
-			lp_schedule (minor);
-	} while (((use_polling && !LP_READY(minor, status)) || 
-		 (!use_polling && !(status & LP_PBUSY))) &&
-		 (count < LP_CHAR(minor)));
+		lp_yield(minor);
+	} while (!LP_READY(minor, status) && count < LP_CHAR(minor));
 
-	if (count == LP_CHAR(minor) ||
-	    (!use_polling && !LP_CAREFUL_READY(minor, status)))
+	if (count == LP_CHAR(minor))
 		return 0;
+
 	w_dtr(minor, lpchar);
 	stats = &LP_STAT(minor);
 	stats->chars++;
 	/* must wait before taking strobe high, and after taking strobe
 	   low, according spec.  Some printers need it, others don't. */
+#ifndef __sparc__
 	while (wait != LP_WAIT(minor)) /* FIXME: should be a udelay() */
 		wait++;
+#else
+	udelay(1);
+#endif
 	/* control port takes strobe high */
 	w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
+#ifndef __sparc__
 	while (wait)			/* FIXME: should be a udelay() */
 		wait--;
+#else
+	udelay(1);
+#endif
 	/* take strobe low */
 	w_ctr(minor, LP_PSELECP | LP_PINITP);
 	/* update waittime statistics */
@@ -170,17 +213,40 @@
 {
 	struct lp_struct *lp_dev = (struct lp_struct *) dev_id;
 
-	if (waitqueue_active (&lp_dev->lp_wait_q))
-		wake_up(&lp_dev->lp_wait_q);
+	if (waitqueue_active (&lp_dev->dev->wait_q))
+		wake_up_interruptible(&lp_dev->dev->wait_q);
 }
 
 static void lp_error(int minor)
 {
-	if (must_use_polling(minor)) {
+	if (LP_POLLING(minor) || LP_PREEMPTED(minor)) {
 		current->state = TASK_INTERRUPTIBLE;
 		current->timeout = jiffies + LP_TIMEOUT_POLLED;
-		lp_schedule (minor);
+		lp_parport_release(minor);
+		schedule();
+		lp_parport_claim(minor);
+	}
+}
+
+static int lp_check_status(int minor) {
+	unsigned char status = r_str(minor);
+	if ((status & LP_POUTPA)) {
+		printk(KERN_INFO "lp%d out of paper\n", minor);
+		if (LP_F(minor) & LP_ABORT)
+			return 1;
+		lp_error(minor);
+	} else if (!(status & LP_PSELECD)) {
+		printk(KERN_INFO "lp%d off-line\n", minor);
+		if (LP_F(minor) & LP_ABORT)
+			return 1;
+		lp_error(minor);
+	} else if (!(status & LP_PERRORP)) {
+		printk(KERN_ERR "lp%d printer error\n", minor);
+		if (LP_F(minor) & LP_ABORT)
+			return 1;
+		lp_error(minor);
 	}
+	return 0;
 }
 
 static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
@@ -202,7 +268,7 @@
 		copy_from_user(lp->lp_buffer, buf, copy_size);
 
 		while (copy_size) {
-			if (lp_char(lp->lp_buffer[bytes_written], minor, must_use_polling(minor))) {
+			if (lp_char(lp->lp_buffer[bytes_written], minor)) {
 				--copy_size;
 				++bytes_written;
 				lp_table[minor].runchars++;
@@ -210,36 +276,24 @@
 				int rc = total_bytes_written + bytes_written;
 				if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
 					LP_STAT(minor).maxrun = lp_table[minor].runchars;
-				status = r_str(minor);
-				if ((status & LP_POUTPA)) {
-					printk(KERN_INFO "lp%d out of paper\n", minor);
-					if (LP_F(minor) & LP_ABORT)
-						return rc ? rc : -ENOSPC;
-					lp_error(minor);
-				} else if (!(status & LP_PSELECD)) {
-					printk(KERN_INFO "lp%d off-line\n", minor);
-					if (LP_F(minor) & LP_ABORT)
-						return rc ? rc : -EIO;
-					lp_error(minor);
-				} else if (!(status & LP_PERRORP)) {
-					printk(KERN_ERR "lp%d printer error\n", minor);
-					if (LP_F(minor) & LP_ABORT)
-						return rc ? rc : -EIO;
-					lp_error(minor);
-				}
-
 				LP_STAT(minor).sleeps++;
 
-				if (must_use_polling(minor)) {
+				if (LP_POLLING(minor)) {
+				lp_polling:
+					if (lp_check_status(minor))
+						return rc ? rc : -EIO;
 #ifdef LP_DEBUG
 					printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp_table[minor].runchars, LP_TIME(minor));
 #endif
-					lp_table[minor].runchars = 0;
 					current->state = TASK_INTERRUPTIBLE;
 					current->timeout = jiffies + LP_TIME(minor);
 					lp_schedule (minor);
 				} else {
 					cli();
+					if (LP_PREEMPTED(minor)) {
+						sti();
+						goto lp_polling;
+					}
 					enable_irq(lp->dev->port->irq);
 					w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN);
 					status = r_str(minor);
@@ -249,14 +303,16 @@
 						sti();
 						continue;
 					}
-					lp_table[minor].runchars = 0;
 					current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
-					interruptible_sleep_on(&lp->lp_wait_q);
-
+					interruptible_sleep_on(&lp->dev->wait_q);
 					w_ctr(minor, LP_PSELECP | LP_PINITP);
 					sti();
+					if (lp_check_status(minor))
+						return rc ? rc : -EIO;
 				}
 
+				lp_table[minor].runchars = 0;
+
 				if (signal_pending(current)) {
 					if (total_bytes_written + bytes_written)
 						return total_bytes_written + bytes_written;
@@ -287,12 +343,11 @@
 	lp_table[minor].lastcall = jiffies;
 
  	/* Claim Parport or sleep until it becomes available
- 	 * (see lp_wakeup() for details)
  	 */
  	lp_parport_claim (minor);
 
 	retv = lp_write_buf(minor, buf, count);
- 
+
  	lp_parport_release (minor);
  	return retv;
 }
@@ -307,14 +362,15 @@
 static int lp_read_nibble(int minor) 
 {
 	unsigned char i;
-	i=r_str(minor)>>3;
-	i&=~8;
-	if ( ( i & 0x10) == 0) i|=8;
-	return(i & 0x0f);
+	i = r_str(minor)>>3;
+	i &= ~8;
+	if ((i & 0x10) == 0) i |= 8;
+	return (i & 0x0f);
 }
 
-static void lp_select_in_high(int minor) {
-	w_ctr(minor, (r_ctr(minor) | 8));
+static inline void lp_select_in_high(int minor) 
+{
+	parport_frob_control(lp_table[minor].dev->port, 8, 8);
 }
 
 /* Status readback confirming to ieee1284 */
@@ -329,7 +385,6 @@
 	unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev);
 	
  	/* Claim Parport or sleep until it becomes available
- 	 * (see lp_wakeup() for details)
  	 */
  	lp_parport_claim (minor);
 
@@ -351,26 +406,27 @@
 		return temp-buf;          /*  End of file */
 	}
 	for (i=0; i<=(count*2); i++) {
-		w_ctr(minor, r_ctr(minor) | 2); /* AutoFeed high */
+		parport_frob_control(lp_table[minor].dev->port, 2, 2); /* AutoFeed high */
 		do {
-			status=(r_str(minor) & 0x40);
+			status = (r_str(minor) & 0x40);
 			udelay(50);
 			counter++;
 			if (need_resched)
 				schedule ();
-		} while ( (status == 0x40) && (counter < 20) );
-		if ( counter == 20 ) { /* Timeout */
+		} while ((status == 0x40) && (counter < 20));
+		if (counter == 20) { 
+			/* Timeout */
 #ifdef LP_READ_DEBUG
 			printk(KERN_DEBUG "lp_read: (Autofeed high) timeout\n");
-#endif		
-			w_ctr(minor, r_ctr(minor) & ~2);
+#endif
+			parport_frob_control(lp_table[minor].dev->port, 2, 0);
 			lp_select_in_high(minor);
 			parport_release(lp_table[minor].dev);
 			return temp-buf; /* end the read at timeout */
 		}
 		counter=0;
-		z=lp_read_nibble(minor);
-		w_ctr(minor, r_ctr(minor) & ~2); /* AutoFeed low */
+		z = lp_read_nibble(minor);
+		parport_frob_control(lp_table[minor].dev->port, 2, 0); /* AutoFeed low */
 		do {
 			status=(r_str(minor) & 0x40);
 			udelay(20);
@@ -427,7 +483,10 @@
 	   a non-standard manner.  This is strictly a Linux hack, and
 	   should most likely only ever be used by the tunelp application. */
 	if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
-		int status = r_str(minor);
+		int status;
+		lp_parport_claim (minor);
+		status = r_str(minor);
+		lp_parport_release (minor);
 		if (status & LP_POUTPA) {
 			printk(KERN_INFO "lp%d out of paper\n", minor);
 			MOD_DEC_USE_COUNT;
@@ -462,7 +521,6 @@
 	return 0;
 }
 
-
 static int lp_ioctl(struct inode *inode, struct file *file,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -520,7 +578,10 @@
 		    	if (retval)
 		    		return retval;
 			else {
-				int status = r_str(minor);
+				int status;
+				lp_parport_claim (minor);
+				status = r_str(minor);
+				lp_parport_release (minor);
 				copy_to_user((int *) arg, &status, sizeof(int));
 			}
 			break;
@@ -571,19 +632,27 @@
 	lp_release
 };
 
-static int parport[LP_NO] = { UNSPEC, };
+/* --- initialisation code ------------------------------------- */
 
 #ifdef MODULE
-#define lp_init init_module
+
+static int parport[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
+static int reset = 0;
+static int autoprobe = 0;
+
 MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "i");
+MODULE_PARM(reset, "i");
+MODULE_PARM(autoprobe, "i");
 
 #else
 
+static int parport[LP_NO] __initdata = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
+static int reset __initdata = 0;
+
 static int parport_ptr = 0;
 
-void lp_setup(char *str, int *ints)
+__initfunc(void lp_setup(char *str, int *ints))
 {
-	/* Ugh. */
 	if (!strncmp(str, "parport", 7)) {
 		int n = simple_strtoul(str+7, NULL, 10);
 		if (parport_ptr < LP_NO)
@@ -592,11 +661,15 @@
 			printk(KERN_INFO "lp: too many ports, %s ignored.\n",
 			       str);
 	} else if (!strcmp(str, "auto")) {
-		parport[0] = AUTO;
+		parport[0] = LP_PARPORT_AUTO;
+	} else if (!strcmp(str, "none")) {
+		parport_ptr++;
+	} else if (!strcmp(str, "reset")) {
+		reset = 1;
 	} else {
 		if (ints[0] == 0 || ints[1] == 0) {
 			/* disable driver on "lp=" or "lp=0" */
-			parport[0] = OFF;
+			parport[0] = LP_PARPORT_OFF;
 		} else {
 			printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]);
 		}
@@ -605,87 +678,91 @@
 
 #endif
 
-void lp_wakeup(void *ref)
+int lp_register(int nr, struct parport *port)
 {
-	struct lp_struct *lp_dev = (struct lp_struct *) ref;
+	lp_table[nr].dev = parport_register_device(port, "lp", 
+						   lp_preempt, NULL,
+						   lp_interrupt, 
+						   PARPORT_DEV_TRAN,
+						   (void *) &lp_table[nr]);
+	if (lp_table[nr].dev == NULL)
+		return 1;
+	lp_table[nr].flags |= LP_EXIST;
 
-	if (!waitqueue_active (&lp_dev->lp_wait_q))
-		return;	/* Wake up whom? */
+	if (reset)
+		lp_reset(nr);
 
-	/* Claim the Parport */
-	if (parport_claim(lp_dev->dev))
-		return;	/* Shouldn't happen */
+	printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, 
+	       (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
 
-	wake_up(&lp_dev->lp_wait_q);
-}
-
-static int inline lp_searchfor(int list[], int a)
-{
-	int i;
-	for (i = 0; i < LP_NO && list[i] != UNSPEC; i++) {
-		if (list[i] == a) return 1;
-	}
 	return 0;
 }
 
 int lp_init(void)
 {
-	int count = 0;
-	struct parport *pb;
-  
-	if (parport[0] == OFF) return 0;
-
-	pb = parport_enumerate();
-
-	while (pb) {
-		/* We only understand PC-style ports. */
-		if (pb->modes & PARPORT_MODE_PCSPP) {
-			if (parport[0] == UNSPEC ||
-			    lp_searchfor(parport, count) ||
-			    (parport[0] == AUTO &&
-			     pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
-				lp_table[count].dev =
-				  parport_register_device(pb, dev_name, 
-						lp_preempt, lp_wakeup,
-						lp_interrupt, PARPORT_DEV_TRAN,
-						(void *) &lp_table[count]);
-				lp_table[count].flags |= LP_EXIST;
-				init_waitqueue (&lp_table[count].lp_wait_q);
-				lp_parport_claim (count);
-				lp_reset (count);
-				lp_parport_release (count);
-				printk(KERN_INFO "lp%d: using %s (%s).\n", 
-				       count, pb->name, (pb->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
+	unsigned int count = 0;
+	struct parport *port;
+
+	switch (parport[0])
+	{
+	case LP_PARPORT_OFF:
+		return 0;
+
+	case LP_PARPORT_UNSPEC:
+	case LP_PARPORT_AUTO:
+	        for (port = parport_enumerate(); port; port = port->next) {
+
+			if (parport[0] == LP_PARPORT_AUTO &&
+			    port->probe_info.class != PARPORT_CLASS_PRINTER)
+				continue;
+
+			if (!lp_register(count, port))
+				if (++count == LP_NO)
+					break;
+		}
+		break;
+
+	default:
+		for (count = 0; count < LP_NO; count++) {
+			if (parport[count] != LP_PARPORT_UNSPEC) {
+				char buffer[16];
+				sprintf(buffer, "parport%d", parport[count]);
+				for (port = parport_enumerate(); port; 
+				     port = port->next) {
+					if (!strcmp(port->name, buffer)) {
+						(void) lp_register(count, port);
+						break;
+					}
+				}
 			}
-			if (++count == LP_NO)
-				break;
 		}
-		pb = pb->next;
-  	}
+		break;
+	}
 
-  	/* Successful specified devices increase count
-  	 * Unsuccessful specified devices increase failed
-  	 */
-  	if (count) {
+	if (count) {
 		if (register_chrdev(LP_MAJOR, "lp", &lp_fops)) {
 			printk("lp: unable to get major %d\n", LP_MAJOR);
 			return -EIO;
 		}
-		return 0;
+	} else {
+		printk(KERN_INFO "lp: driver loaded but no devices found\n");
 	}
 
-	printk(KERN_INFO "lp: driver loaded but no devices found\n");
-#ifdef MODULE
 	return 0;
-#else	
-	return 1;
-#endif
 }
 
 #ifdef MODULE
+int init_module(void)
+{
+	if (autoprobe)
+		parport[0] = LP_PARPORT_AUTO;
+
+	return lp_init();
+}
+
 void cleanup_module(void)
 {
-	int offset;
+	unsigned int offset;
 
 	unregister_chrdev(LP_MAJOR, "lp");
 	for (offset = 0; offset < LP_NO; offset++) {
diff -u --recursive --new-file v2.1.81/linux/drivers/isdn/avmb1/b1capi.c linux/drivers/isdn/avmb1/b1capi.c
--- v2.1.81/linux/drivers/isdn/avmb1/b1capi.c	Sat Sep 20 14:51:54 1997
+++ linux/drivers/isdn/avmb1/b1capi.c	Sun Jan 25 10:05:46 1998
@@ -52,10 +52,11 @@
 
 /* ------------------------------------------------------------- */
 
-int portbase = 0x150;
-int irq = 15;
 int showcapimsgs = 0;		/* used in lli.c */
 int loaddebug = 0;
+static int portbase = 0x150;
+#ifdef MODULE
+static int irq = 15;
 
 #ifdef HAS_NEW_SYMTAB
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
@@ -63,6 +64,7 @@
 MODULE_PARM(irq, "2-15i");
 MODULE_PARM(showcapimsgs, "0-3i");
 MODULE_PARM(loaddebug, "0-1i");
+#endif
 #endif
 
 /* ------------------------------------------------------------- */
diff -u --recursive --new-file v2.1.81/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- v2.1.81/linux/drivers/isdn/hisax/config.c	Thu May 29 21:53:05 1997
+++ linux/drivers/isdn/hisax/config.c	Sun Jan 25 10:05:46 1998
@@ -179,23 +179,23 @@
 char *HiSax_id = HiSaxID;
 #ifdef MODULE
 /* Variables for insmod */
-int type[] =
+static int type[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int protocol[] =
+static int protocol[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int io[] =
+static int io[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #ifdef CONFIG_HISAX_16_3	/* For Creatix/Teles PnP */
-int io0[] =
+static int io0[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int io1[] =
+static int io1[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #endif
-int irq[] =
+static int irq[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int mem[] =
+static int mem[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-char *id = HiSaxID;
+static char *id = HiSaxID;
 
 #if (LINUX_VERSION_CODE > 0x020111)
 MODULE_AUTHOR("Karsten Keil");
diff -u --recursive --new-file v2.1.81/linux/drivers/isdn/pcbit/module.c linux/drivers/isdn/pcbit/module.c
--- v2.1.81/linux/drivers/isdn/pcbit/module.c	Thu Feb 27 10:57:30 1997
+++ linux/drivers/isdn/pcbit/module.c	Sun Jan 25 10:05:46 1998
@@ -22,10 +22,10 @@
 #include <linux/isdnif.h>
 #include "pcbit.h"
 
-int mem[MAX_PCBIT_CARDS] = {0, };
-int irq[MAX_PCBIT_CARDS] = {0, };
+static int mem[MAX_PCBIT_CARDS] = {0, };
+static int irq[MAX_PCBIT_CARDS] = {0, };
 
-int num_boards;
+static int num_boards;
 struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS] = {0, 0, 0, 0};
 
 int init_module(void);
diff -u --recursive --new-file v2.1.81/linux/drivers/isdn/sc/hardware.h linux/drivers/isdn/sc/hardware.h
--- v2.1.81/linux/drivers/isdn/sc/hardware.h	Thu Feb 27 10:57:30 1997
+++ linux/drivers/isdn/sc/hardware.h	Sun Jan 25 10:05:46 1998
@@ -16,11 +16,6 @@
 					   this, you must also change the number
 					   of elements in io, irq, and ram to
 					   match. Initialized in init.c */
-/*
-extern unsigned int io[];
-extern unsigned char irq[];
-extern unsigned long ram[];
-*/
 
 #define SIGNATURE	0x87654321	/* Board reset signature */
 #define SIG_OFFSET	0x1004		/* Where to find signature in shared RAM */
diff -u --recursive --new-file v2.1.81/linux/drivers/isdn/sc/includes.h linux/drivers/isdn/sc/includes.h
--- v2.1.81/linux/drivers/isdn/sc/includes.h	Thu Feb 27 10:57:30 1997
+++ linux/drivers/isdn/sc/includes.h	Sun Jan 25 10:05:46 1998
@@ -1,6 +1,5 @@
 #include <linux/module.h>
 #include <linux/version.h>
-#include <stdio.h>
 #include <linux/errno.h>
 #include <asm/segment.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.1.81/linux/drivers/isdn/sc/init.c linux/drivers/isdn/sc/init.c
--- v2.1.81/linux/drivers/isdn/sc/init.c	Thu May 29 21:53:06 1997
+++ linux/drivers/isdn/sc/init.c	Sun Jan 25 10:05:46 1998
@@ -11,10 +11,10 @@
 const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" };
 
 /* insmod set parameters */
-unsigned int io[] = {0,0,0,0};
-unsigned char irq[] = {0,0,0,0};
-unsigned long ram[] = {0,0,0,0};
-int do_reset = 0;
+static unsigned int io[] = {0,0,0,0};
+static unsigned char irq[] = {0,0,0,0};
+static unsigned long ram[] = {0,0,0,0};
+static int do_reset = 0;
 
 static int sup_irq[] = { 11, 10, 9, 5, 12, 14, 7, 3, 4, 6 };
 #define MAX_IRQS	10
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/BUGS-parport linux/drivers/misc/BUGS-parport
--- v2.1.81/linux/drivers/misc/BUGS-parport	Tue Aug 26 14:52:44 1997
+++ linux/drivers/misc/BUGS-parport	Fri Jan 23 20:04:03 1998
@@ -1,6 +1,4 @@
 Currently known (or at least suspected) bugs in parport:
 
-o IEEE1284 code does not do the terminating handshake after transfers, which
-  seems to upset some devices.
-
 o lp doesn't allow you to read status while printing is in progress.
+
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/Makefile linux/drivers/misc/Makefile
--- v2.1.81/linux/drivers/misc/Makefile	Sat Nov 29 16:19:40 1997
+++ linux/drivers/misc/Makefile	Fri Jan 23 20:04:03 1998
@@ -48,10 +48,10 @@
     M_OBJS += parport.o
   endif
   ifeq ($(CONFIG_PARPORT_PC),m)
-    MX_OBJS += parport_pc.o
+    M_OBJS += parport_pc.o
   endif
   ifeq ($(CONFIG_PARPORT_AX),m)
-    MX_OBJS += parport_ax.o
+    M_OBJS += parport_ax.o
   endif
 endif
 
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/TODO-parport linux/drivers/misc/TODO-parport
--- v2.1.81/linux/drivers/misc/TODO-parport	Sat Sep 20 11:43:22 1997
+++ linux/drivers/misc/TODO-parport	Fri Jan 23 20:04:03 1998
@@ -4,7 +4,7 @@
 
 1. Proper documentation.
 
-2. Overhaul lp.c:
+2. A better lp.c:
 
    a) It's a _mess_
 
@@ -18,4 +18,8 @@
       bits when they have something to say.  We should read out and deal 
       with (maybe just log) whatever the printer wants to tell the world.
 
-3. Assimilate more drivers.
+3. Support more hardware (eg m68k, Sun bpp).
+
+4. A better PLIP (make use of bidirectional/ECP/EPP ports).
+
+
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/parport_arc.c linux/drivers/misc/parport_arc.c
--- v2.1.81/linux/drivers/misc/parport_arc.c	Tue Aug 26 14:52:44 1997
+++ linux/drivers/misc/parport_arc.c	Fri Jan 23 20:04:03 1998
@@ -1,24 +1,32 @@
-/* Parallel-port routines for ARC onboard hardware.
+/* Low-level parallel port routines for Archimedes onboard hardware
  *
  * Author: Phil Blundell <Philip.Blundell@pobox.com>
  */
 
-#include <linux/tasks.h>
-
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/dma.h>
+/* This driver is for the parallel port hardware found on Acorn's old
+ * range of Archimedes machines.  The A5000 and newer systems have PC-style
+ * I/O hardware and should use the parport_pc driver instead.
+ *
+ * The Acorn printer port hardware is very simple.  There is a single 8-bit
+ * write-only latch for the data port and control/status bits are handled
+ * with various auxilliary input and output lines.  The port is not
+ * bidirectional, does not support any modes other than SPP, and has only
+ * a subset of the standard printer control lines connected.
+ */
 
+#include <linux/tasks.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
-
 #include <linux/parport.h>
 
-#include <linux/arch/oldlatches.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+#include <asm/arch/oldlatches.h>
+#include <asm/arch/irqs.h>
 
 #define DATA_LATCH    0x3350010
 
@@ -50,7 +58,7 @@
 #endif
 }
 
-static struct parport_operations arc_ops = 
+static struct parport_operations parport_arc_ops = 
 {
 	arc_write_data,
 	arc_read_data,
@@ -90,3 +98,31 @@
 	arc_inc_use_count,
 	arc_dec_use_count
 };
+
+/* --- Initialisation code -------------------------------- */
+
+int parport_arc_init(void)
+{
+	/* Archimedes hardware provides only one port, at a fixed address */
+	struct parport *p;
+
+	if (check_region(DATA_LATCH, 4))
+		return 0;
+	
+       	if (!(p = parport_register_port(base, IRQ_PRINTERACK, 
+					PARPORT_DMA_NONE, &parport_arc_ops))) 
+		return 0;
+
+	p->modes = PARPORT_MODE_ARCSPP;
+	p->size = 4;
+
+	printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
+	       p->irq);
+	parport_proc_register(p);
+	p->flags |= PARPORT_FLAG_COMA;
+
+	if (parport_probe_hook)
+		(*parport_probe_hook)(p);
+
+	return 1;
+}
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/parport_ax.c linux/drivers/misc/parport_ax.c
--- v2.1.81/linux/drivers/misc/parport_ax.c	Sat Dec  6 11:58:23 1997
+++ linux/drivers/misc/parport_ax.c	Fri Jan 23 20:04:03 1998
@@ -1,4 +1,4 @@
-/* $Id: parport_ax.c,v 1.2 1997/10/25 17:27:03 philip Exp $
+/* $Id: parport_ax.c,v 1.5 1998/01/10 18:28:39 ecd Exp $
  * Parallel-port routines for Sun Ultra/AX architecture
  * 
  * Author: Eddie C. Dost <ecd@skynet.be>
@@ -18,6 +18,7 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
+#include <linux/init.h>
 
 #include <linux/parport.h>
 
@@ -36,116 +37,126 @@
 #undef HAVE_SLOW_DEVICES
 
 
-#define DATA     0x00
-#define STATUS   0x01
-#define CONTROL  0x02
-
-#define CFIFO	0x400
-#define DFIFO	0x400
-#define TFIFO	0x400
-#define CNFA	0x400
-#define CNFB	0x401
-#define ECR	0x402
+#define DATA		0x00
+#define STATUS		0x01
+#define CONTROL		0x02
+#define EPPREG		0x04
+
+#define CFIFO		0x400
+#define DFIFO		0x400
+#define TFIFO		0x400
+#define CONFIGA		0x400
+#define CONFIGB		0x401
+#define ECONTROL	0x402
 
 static void
-ax_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+parport_ax_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/* NULL function - Does nothing */
-	return;
 }
 
-#if 0
-static unsigned int
-ax_read_configb(struct parport *p)
+void
+parport_ax_write_epp(struct parport *p, unsigned int d)
 {
-	return (unsigned int)inb(p->base + CNFB);
+	outb(d, p->base + EPPREG);
 }
-#endif
 
-static void
-ax_write_data(struct parport *p, unsigned int d)
+unsigned int
+parport_ax_read_epp(struct parport *p)
+{
+	return (unsigned int)inb(p->base + EPPREG);
+}
+
+unsigned int
+parport_ax_read_configb(struct parport *p)
+{
+	return (unsigned int)inb(p->base + CONFIGB);
+}
+
+void
+parport_ax_write_data(struct parport *p, unsigned int d)
 {
 	outb(d, p->base + DATA);
 }
 
-static unsigned int
-ax_read_data(struct parport *p)
+unsigned int
+parport_ax_read_data(struct parport *p)
 {
 	return (unsigned int)inb(p->base + DATA);
 }
 
-static void
-ax_write_control(struct parport *p, unsigned int d)
+void
+parport_ax_write_control(struct parport *p, unsigned int d)
 {
 	outb(d, p->base + CONTROL);
 }
 
-static unsigned int
-ax_read_control(struct parport *p)
+unsigned int
+parport_ax_read_control(struct parport *p)
 {
 	return (unsigned int)inb(p->base + CONTROL);
 }
 
-static unsigned int
-ax_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
+unsigned int
+parport_ax_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
 {
 	unsigned int old = (unsigned int)inb(p->base + CONTROL);
 	outb(((old & ~mask) ^ val), p->base + CONTROL);
 	return old;
 }
 
-static void
-ax_write_status(struct parport *p, unsigned int d)
+void
+parport_ax_write_status(struct parport *p, unsigned int d)
 {
 	outb(d, p->base + STATUS);
 }
 
-static unsigned int
-ax_read_status(struct parport *p)
+unsigned int
+parport_ax_read_status(struct parport *p)
 {
 	return (unsigned int)inb(p->base + STATUS);
 }
 
-static void
-ax_write_econtrol(struct parport *p, unsigned int d)
+void
+parport_ax_write_econtrol(struct parport *p, unsigned int d)
 {
-	outb(d, p->base + ECR);
+	outb(d, p->base + ECONTROL);
 }
 
-static unsigned int
-ax_read_econtrol(struct parport *p)
+unsigned int
+parport_ax_read_econtrol(struct parport *p)
 {
-	return (unsigned int)inb(p->base + ECR);
+	return (unsigned int)inb(p->base + ECONTROL);
 }
 
-static unsigned int
-ax_frob_econtrol(struct parport *p, unsigned int mask,  unsigned int val)
+unsigned int
+parport_ax_frob_econtrol(struct parport *p, unsigned int mask, unsigned int val)
 {
-	unsigned int old = (unsigned int)inb(p->base + ECR);
-	outb(((old & ~mask) ^ val), p->base + ECR);
+	unsigned int old = (unsigned int)inb(p->base + ECONTROL);
+	outb(((old & ~mask) ^ val), p->base + ECONTROL);
 	return old;
 }
 
-static void
-ax_change_mode(struct parport *p, int m)
+void
+parport_ax_change_mode(struct parport *p, int m)
 {
-	ax_frob_econtrol(p, 0xe0, m << 5);
+	parport_ax_frob_econtrol(p, 0xe0, m << 5);
 }
 
-static void
-ax_write_fifo(struct parport *p, unsigned int v)
+void
+parport_ax_write_fifo(struct parport *p, unsigned int v)
 {
 	outb(v, p->base + DFIFO);
 }
 
-static unsigned int
-ax_read_fifo(struct parport *p)
+unsigned int
+parport_ax_read_fifo(struct parport *p)
 {
 	return inb(p->base + DFIFO);
 }
 
-static void
-ax_disable_irq(struct parport *p)
+void
+parport_ax_disable_irq(struct parport *p)
 {
 	struct linux_ebus_dma *dma = p->private_data;
 	unsigned int dcsr;
@@ -155,8 +166,8 @@
 	writel(dcsr, (unsigned long)&dma->dcsr);
 }
 
-static void
-ax_enable_irq(struct parport *p)
+void
+parport_ax_enable_irq(struct parport *p)
 {
 	struct linux_ebus_dma *dma = p->private_data;
 	unsigned int dcsr;
@@ -166,11 +177,11 @@
 	writel(dcsr, (unsigned long)&dma->dcsr);
 }
 
-static void
-ax_release_resources(struct parport *p)
+void
+parport_ax_release_resources(struct parport *p)
 {
 	if (p->irq != PARPORT_IRQ_NONE) {
-		ax_disable_irq(p);
+		parport_ax_disable_irq(p);
 		free_irq(p->irq, NULL);
 	}
 	release_region(p->base, p->size);
@@ -180,13 +191,14 @@
 		       sizeof(struct linux_ebus_dma));
 }
 
-static int
-ax_claim_resources(struct parport *p)
+int
+parport_ax_claim_resources(struct parport *p)
 {
 	/* FIXME check that resources are free */
 	if (p->irq != PARPORT_IRQ_NONE) {
-		request_irq(p->irq, ax_null_intr_func, 0, p->name, NULL);
-		ax_enable_irq(p);
+		request_irq(p->irq, parport_ax_null_intr_func,
+			    0, p->name, NULL);
+		parport_ax_enable_irq(p);
 	}
 	request_region(p->base, p->size, p->name);
 	if (p->modes & PARPORT_MODE_PCECR)
@@ -196,109 +208,109 @@
 	return 0;
 }
 
-static void
-ax_save_state(struct parport *p, struct parport_state *s)
+void
+parport_ax_save_state(struct parport *p, struct parport_state *s)
 {
-	s->u.pc.ctr = ax_read_control(p);
-	s->u.pc.ecr = ax_read_econtrol(p);
+	s->u.pc.ctr = parport_ax_read_control(p);
+	s->u.pc.ecr = parport_ax_read_econtrol(p);
 }
 
-static void
-ax_restore_state(struct parport *p, struct parport_state *s)
+void
+parport_ax_restore_state(struct parport *p, struct parport_state *s)
 {
-	ax_write_control(p, s->u.pc.ctr);
-	ax_write_econtrol(p, s->u.pc.ecr);
+	parport_ax_write_control(p, s->u.pc.ctr);
+	parport_ax_write_econtrol(p, s->u.pc.ecr);
 }
 
-static unsigned int
-ax_epp_read_block(struct parport *p, void *buf, unsigned  int length)
+unsigned int
+parport_ax_epp_read_block(struct parport *p, void *buf, unsigned  int length)
 {
 	return 0; /* FIXME */
 }
 
-static unsigned int
-ax_epp_write_block(struct parport *p, void *buf, unsigned  int length)
+unsigned int
+parport_ax_epp_write_block(struct parport *p, void *buf, unsigned  int length)
 {
 	return 0; /* FIXME */
 }
 
-static unsigned int
-ax_ecp_read_block(struct parport *p, void *buf, unsigned  int length,
-		  void (*fn)(struct parport *, void *, unsigned int),
-		  void *handle)
+unsigned int
+parport_ax_ecp_read_block(struct parport *p, void *buf, unsigned  int length,
+			  void (*fn)(struct parport *, void *, unsigned int),
+			  void *handle)
 {
 	return 0; /* FIXME */
 }
 
-static unsigned int
-ax_ecp_write_block(struct parport *p, void *buf, unsigned  int length,
-		   void (*fn)(struct parport *, void *, unsigned int),
-		   void *handle)
+unsigned int
+parport_ax_ecp_write_block(struct parport *p, void *buf, unsigned  int length,
+			   void (*fn)(struct parport *, void *, unsigned int),
+			   void *handle)
 {
 	return 0; /* FIXME */
 }
 
-static int
-ax_examine_irq(struct parport *p)
+int
+parport_ax_examine_irq(struct parport *p)
 {
 	return 0; /* FIXME */
 }
 
-static void
-ax_inc_use_count(void)
+void
+parport_ax_inc_use_count(void)
 {
 #ifdef MODULE
 	MOD_INC_USE_COUNT;
 #endif
 }
 
-static void
-ax_dec_use_count(void)
+void
+parport_ax_dec_use_count(void)
 {
 #ifdef MODULE
 	MOD_DEC_USE_COUNT;
 #endif
 }
 
-static struct parport_operations ax_ops = 
+static struct parport_operations parport_ax_ops = 
 {
-	ax_write_data,
-	ax_read_data,
+	parport_ax_write_data,
+	parport_ax_read_data,
 
-	ax_write_control,
-	ax_read_control,
-	ax_frob_control,
+	parport_ax_write_control,
+	parport_ax_read_control,
+	parport_ax_frob_control,
 
-	ax_write_econtrol,
-	ax_read_econtrol,
-	ax_frob_econtrol,
+	parport_ax_write_econtrol,
+	parport_ax_read_econtrol,
+	parport_ax_frob_econtrol,
 
-	ax_write_status,
-	ax_read_status,
+	parport_ax_write_status,
+	parport_ax_read_status,
 
-	ax_write_fifo,
-	ax_read_fifo,
+	parport_ax_write_fifo,
+	parport_ax_read_fifo,
 	
-	ax_change_mode,
+	parport_ax_change_mode,
 	
-	ax_release_resources,
-	ax_claim_resources,
+	parport_ax_release_resources,
+	parport_ax_claim_resources,
 	
-	ax_epp_write_block,
-	ax_epp_read_block,
+	parport_ax_epp_write_block,
+	parport_ax_epp_read_block,
 
-	ax_ecp_write_block,
-	ax_ecp_read_block,
+	parport_ax_ecp_write_block,
+	parport_ax_ecp_read_block,
 	
-	ax_save_state,
-	ax_restore_state,
+	parport_ax_save_state,
+	parport_ax_restore_state,
 
-	ax_enable_irq,
-	ax_disable_irq,
-	ax_examine_irq,
+	parport_ax_enable_irq,
+	parport_ax_disable_irq,
+	parport_ax_examine_irq,
 
-	ax_inc_use_count,
-	ax_dec_use_count
+	parport_ax_inc_use_count,
+	parport_ax_dec_use_count
 };
 
 
@@ -308,14 +320,14 @@
 
 /* Check for ECP
  *
- * Old style XT ports alias io ports every 0x400, hence accessing ECR
+ * Old style XT ports alias io ports every 0x400, hence accessing ECONTROL
  * on these cards actually accesses the CTR.
  *
- * Modern cards don't do this but reading from ECR will return 0xff
+ * Modern cards don't do this but reading from ECONTROL will return 0xff
  * regardless of what is written here if the card does NOT support
  * ECP.
  *
- * We will write 0x2c to ECR and 0xcc to CTR since both of these
+ * We will write 0x2c to ECONTROL and 0xcc to CTR since both of these
  * values are "safe" on the CTR since bits 6-7 of CTR are unused.
  */
 static int parport_ECR_present(struct parport *pb)
@@ -330,7 +342,7 @@
 		r = pb->ops->read_control(pb);	
 		if ((pb->ops->read_econtrol(pb) & 0x2) == (r & 0x2)) {
 			pb->ops->write_control(pb, octr);
-			return 0; /* Sure that no ECR register exists */
+			return 0; /* Sure that no ECONTROL register exists */
 		}
 	}
 	
@@ -351,12 +363,12 @@
 {
 	int i, oecr = pb->ops->read_econtrol(pb);
 	
-	/* If there is no ECR, we have no hope of supporting ECP. */
+	/* If there is no ECONTROL, we have no hope of supporting ECP. */
 	if (!(pb->modes & PARPORT_MODE_PCECR))
 		return 0;
 
 	/*
-	 * Using LGS chipset it uses ECR register, but
+	 * Using LGS chipset it uses ECONTROL register, but
 	 * it doesn't support ECP or FIFO MODE
 	 */
 	
@@ -439,7 +451,7 @@
 
 	/* Setup temporary access to Device operations */
 	tmpport.base = dev->base_address[0];
-	tmpport.ops = &ax_ops;
+	tmpport.ops = &parport_ax_ops;
 
 	/* Enable ECP mode, set bit 2 of the CTR first */
 	tmpport.ops->write_control(&tmpport, 0x04);
@@ -472,7 +484,7 @@
 	irq = dev->irqs[0];
 	dma = PARPORT_DMA_AUTO;
 
-	if (!(p = parport_register_port(base, irq, dma, &ax_ops)))
+	if (!(p = parport_register_port(base, irq, dma, &parport_ax_ops)))
 		return 0;
 
 	/* Safe away pointer to our EBus DMA */
@@ -506,8 +518,8 @@
 	parport_proc_register(p);
 	p->flags |= PARPORT_FLAG_COMA;
 
-	ax_write_control(p, 0x0c);
-	ax_write_data(p, 0);
+	p->ops->write_control(p, 0x0c);
+	p->ops->write_data(p, 0);
 
 	if (parport_probe_hook)
 		(*parport_probe_hook)(p);
@@ -515,8 +527,13 @@
 	return 1;
 }
 
-int
-parport_ax_init(void)
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int parport_ax_init(void))
+#endif
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
@@ -525,17 +542,10 @@
 	for_all_ebusdev(edev, ebus)
 		if (!strcmp(edev->prom_name, "ecpp"))
 			count += init_one_port(edev);
-	return count;
+	return count ? 0 : -ENODEV;
 }
 
 #ifdef MODULE
-
-int
-init_module(void)
-{	
-	return (parport_ax_init() ? 0 : 1);
-}
-
 void
 cleanup_module(void)
 {
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/parport_init.c linux/drivers/misc/parport_init.c
--- v2.1.81/linux/drivers/misc/parport_init.c	Fri Jan 23 18:10:31 1998
+++ linux/drivers/misc/parport_init.c	Fri Jan 23 20:04:03 1998
@@ -1,6 +1,6 @@
 /* Parallel-port initialisation code.
  * 
- * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
+ * Authors: David Campbell <campbell@torque.net>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
  *	    Jose Renau <renau@acm.org>
  *
@@ -57,7 +57,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	parport_proc_init();
+	(void)parport_proc_init();	/* We can go on without it. */
 	return 0;
 }
 
@@ -88,6 +88,7 @@
 /* Exported symbols for modules. */
 
 EXPORT_SYMBOL(parport_claim);
+EXPORT_SYMBOL(parport_claim_or_block);
 EXPORT_SYMBOL(parport_release);
 EXPORT_SYMBOL(parport_register_port);
 EXPORT_SYMBOL(parport_unregister_port);
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.1.81/linux/drivers/misc/parport_pc.c	Sat Dec  6 11:58:23 1997
+++ linux/drivers/misc/parport_pc.c	Fri Jan 23 20:04:03 1998
@@ -1,4 +1,4 @@
-/* Parallel-port routines for PC architecture
+/* Low-level parallel-port routines for PC-style hardware.
  * 
  * Authors: Phil Blundell <Philip.Blundell@pobox.com>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
@@ -8,6 +8,28 @@
  * based on work by Grant Guenther <grant@torque.net> and Phil Blundell.
  */
 
+/* This driver should work with any hardware that is broadly compatible
+ * with that in the IBM PC.  This applies to the majority of integrated
+ * I/O chipsets that are commonly available.  The expected register
+ * layout is:
+ *
+ *	base+0		data
+ *	base+1		status
+ *	base+2		control
+ *
+ * In addition, there are some optional registers:
+ *
+ *	base+3		EPP command
+ *	base+4		EPP
+ *	base+0x400	ECP config A
+ *	base+0x401	ECP config B
+ *	base+0x402	ECP control
+ *
+ * All registers are 8 bits wide and read/write.  If your hardware differs
+ * only in register addresses (eg because your registers are on 32-bit
+ * word boundaries) then you can alter the constants below to accomodate this.
+ */
+
 #include <linux/stddef.h>
 #include <linux/tasks.h>
 
@@ -25,120 +47,112 @@
 #include <linux/malloc.h>
 
 #include <linux/parport.h>
+#include <linux/parport_pc.h>
 
-#define ECONTROL 0x402
-#define CONFIGB  0x401
-#define CONFIGA  0x400
-#define EPPREG   0x4
-#define CONTROL  0x2
-#define STATUS   0x1
-#define DATA     0
-
-#define PC_MAX_PORTS  8
+/* Maximum number of ports to support.  It is useless to set this greater
+   than PARPORT_MAX (in <linux/parport.h>).  */
+#define PARPORT_PC_MAX_PORTS  8
 
-static void pc_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+static void parport_pc_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
-	/* NULL function - Does nothing */
-	return;
+	/* Null function - does nothing */
 }
 
-#if 0
-static void pc_write_epp(struct parport *p, unsigned int d)
+void parport_pc_write_epp(struct parport *p, unsigned int d)
 {
 	outb(d, p->base+EPPREG);
 }
-#endif
 
-static unsigned int pc_read_epp(struct parport *p)
+unsigned int parport_pc_read_epp(struct parport *p)
 {
 	return (unsigned int)inb(p->base+EPPREG);
 }
 
-static unsigned int pc_read_configb(struct parport *p)
+unsigned int parport_pc_read_configb(struct parport *p)
 {
 	return (unsigned int)inb(p->base+CONFIGB);
 }
 
-static void pc_write_data(struct parport *p, unsigned int d)
+void parport_pc_write_data(struct parport *p, unsigned int d)
 {
 	outb(d, p->base+DATA);
 }
 
-static unsigned int pc_read_data(struct parport *p)
+unsigned int parport_pc_read_data(struct parport *p)
 {
 	return (unsigned int)inb(p->base+DATA);
 }
 
-static void pc_write_control(struct parport *p, unsigned int d)
+void parport_pc_write_control(struct parport *p, unsigned int d)
 {
 	outb(d, p->base+CONTROL);
 }
 
-static unsigned int pc_read_control(struct parport *p)
+unsigned int parport_pc_read_control(struct parport *p)
 {
 	return (unsigned int)inb(p->base+CONTROL);
 }
 
-static unsigned int pc_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
+unsigned int parport_pc_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
 {
 	unsigned int old = (unsigned int)inb(p->base+CONTROL);
 	outb(((old & ~mask) ^ val), p->base+CONTROL);
 	return old;
 }
 
-static void pc_write_status(struct parport *p, unsigned int d)
+void parport_pc_write_status(struct parport *p, unsigned int d)
 {
 	outb(d, p->base+STATUS);
 }
 
-static unsigned int pc_read_status(struct parport *p)
+unsigned int parport_pc_read_status(struct parport *p)
 {
 	return (unsigned int)inb(p->base+STATUS);
 }
 
-static void pc_write_econtrol(struct parport *p, unsigned int d)
+void parport_pc_write_econtrol(struct parport *p, unsigned int d)
 {
 	outb(d, p->base+ECONTROL);
 }
 
-static unsigned int pc_read_econtrol(struct parport *p)
+unsigned int parport_pc_read_econtrol(struct parport *p)
 {
 	return (unsigned int)inb(p->base+ECONTROL);
 }
 
-static unsigned int pc_frob_econtrol(struct parport *p, unsigned int mask,  unsigned int val)
+unsigned int parport_pc_frob_econtrol(struct parport *p, unsigned int mask,  unsigned int val)
 {
 	unsigned int old = (unsigned int)inb(p->base+ECONTROL);
 	outb(((old & ~mask) ^ val), p->base+ECONTROL);
 	return old;
 }
 
-static void pc_change_mode(struct parport *p, int m)
+void parport_pc_change_mode(struct parport *p, int m)
 {
 	/* FIXME */
 }
 
-static void pc_write_fifo(struct parport *p, unsigned int v)
+void parport_pc_write_fifo(struct parport *p, unsigned int v)
 {
 	/* FIXME */
 }
 
-static unsigned int pc_read_fifo(struct parport *p)
+unsigned int parport_pc_read_fifo(struct parport *p)
 {
 	return 0; /* FIXME */
 }
 
-static void pc_disable_irq(struct parport *p)
+void parport_pc_disable_irq(struct parport *p)
 {
-	/* FIXME */
+	parport_pc_frob_control(p, 0x10, 0);
 }
 
-static void pc_enable_irq(struct parport *p)
+void parport_pc_enable_irq(struct parport *p)
 {
-	/* FIXME */
+	parport_pc_frob_control(p, 0x10, 0x10);
 }
 
-static void pc_release_resources(struct parport *p)
+void parport_pc_release_resources(struct parport *p)
 {
 	if (p->irq != PARPORT_IRQ_NONE)
 		free_irq(p->irq, NULL);
@@ -147,112 +161,110 @@
 		release_region(p->base+0x400, 3);
 }
 
-static int pc_claim_resources(struct parport *p)
+int parport_pc_claim_resources(struct parport *p)
 {
 	/* FIXME check that resources are free */
 	if (p->irq != PARPORT_IRQ_NONE)
-		request_irq(p->irq, pc_null_intr_func, 0, p->name, NULL);
+		request_irq(p->irq, parport_pc_null_intr_func, 0, p->name, NULL);
 	request_region(p->base, p->size, p->name);
 	if (p->modes & PARPORT_MODE_PCECR)
 		request_region(p->base+0x400, 3, p->name);
 	return 0;
 }
 
-static void pc_save_state(struct parport *p, struct parport_state *s)
+void parport_pc_save_state(struct parport *p, struct parport_state *s)
 {
-	s->u.pc.ctr = pc_read_control(p);
-	s->u.pc.ecr = pc_read_econtrol(p);
+	s->u.pc.ctr = parport_pc_read_control(p);
+	s->u.pc.ecr = parport_pc_read_econtrol(p);
 }
 
-static void pc_restore_state(struct parport *p, struct parport_state *s)
+void parport_pc_restore_state(struct parport *p, struct parport_state *s)
 {
-	pc_write_control(p, s->u.pc.ctr);
-	pc_write_econtrol(p, s->u.pc.ecr);
+	parport_pc_write_control(p, s->u.pc.ctr);
+	parport_pc_write_econtrol(p, s->u.pc.ecr);
 }
 
-static unsigned int pc_epp_read_block(struct parport *p, void *buf, unsigned  int length)
+unsigned int parport_pc_epp_read_block(struct parport *p, void *buf, unsigned  int length)
 {
 	return 0; /* FIXME */
 }
 
-static unsigned int pc_epp_write_block(struct parport *p, void *buf, unsigned  int length)
+unsigned int parport_pc_epp_write_block(struct parport *p, void *buf, unsigned  int length)
 {
 	return 0; /* FIXME */
 }
 
-static unsigned int pc_ecp_read_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
+unsigned int parport_pc_ecp_read_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
 {
 	return 0; /* FIXME */
 }
 
-static unsigned int pc_ecp_write_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
+unsigned int parport_pc_ecp_write_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
 {
 	return 0; /* FIXME */
 }
 
-static int pc_examine_irq(struct parport *p)
+int parport_pc_examine_irq(struct parport *p)
 {
 	return 0; /* FIXME */
 }
 
-static void pc_inc_use_count(void)
+void parport_pc_inc_use_count(void)
 {
 #ifdef MODULE
 	MOD_INC_USE_COUNT;
 #endif
 }
 
-static void pc_dec_use_count(void)
+void parport_pc_dec_use_count(void)
 {
 #ifdef MODULE
 	MOD_DEC_USE_COUNT;
 #endif
 }
 
-static struct parport_operations pc_ops = 
+struct parport_operations parport_pc_ops = 
 {
-	pc_write_data,
-	pc_read_data,
+	parport_pc_write_data,
+	parport_pc_read_data,
 
-	pc_write_control,
-	pc_read_control,
-	pc_frob_control,
+	parport_pc_write_control,
+	parport_pc_read_control,
+	parport_pc_frob_control,
 
-	pc_write_econtrol,
-	pc_read_econtrol,
-	pc_frob_econtrol,
+	parport_pc_write_econtrol,
+	parport_pc_read_econtrol,
+	parport_pc_frob_econtrol,
 
-	pc_write_status,
-	pc_read_status,
+	parport_pc_write_status,
+	parport_pc_read_status,
 
-	pc_write_fifo,
-	pc_read_fifo,
+	parport_pc_write_fifo,
+	parport_pc_read_fifo,
 	
-	pc_change_mode,
+	parport_pc_change_mode,
 	
-	pc_release_resources,
-	pc_claim_resources,
+	parport_pc_release_resources,
+	parport_pc_claim_resources,
 	
-	pc_epp_write_block,
-	pc_epp_read_block,
+	parport_pc_epp_write_block,
+	parport_pc_epp_read_block,
 
-	pc_ecp_write_block,
-	pc_ecp_read_block,
+	parport_pc_ecp_write_block,
+	parport_pc_ecp_read_block,
 	
-	pc_save_state,
-	pc_restore_state,
+	parport_pc_save_state,
+	parport_pc_restore_state,
 
-	pc_enable_irq,
-	pc_disable_irq,
-	pc_examine_irq,
+	parport_pc_enable_irq,
+	parport_pc_disable_irq,
+	parport_pc_examine_irq,
 
-	pc_inc_use_count,
-	pc_dec_use_count
+	parport_pc_inc_use_count,
+	parport_pc_dec_use_count
 };
 
-/******************************************************
- *  DMA detection section:
- */
+/* --- DMA detection -------------------------------------- */
 
 /*
  * Prepare DMA channels from 0-8 to transmit towards buffer
@@ -289,10 +301,10 @@
 	
 	for (i = 0; i < 8; i++)
 		if (dma & (1 << i)) {
-		cli();
-		enable_dma(i);
-		sti();
-	    }
+			cli();
+			enable_dma(i);
+			sti();
+		}
 
 	return dma;
 }
@@ -325,13 +337,13 @@
 /* Only if supports ECP mode */
 static int programmable_dma_support(struct parport *pb)
 {
-	int dma, oldstate = pc_read_econtrol(pb);
+	int dma, oldstate = parport_pc_read_econtrol(pb);
 
-	pc_write_econtrol(pb, 0xe0); /* Configuration MODE */
+	parport_pc_write_econtrol(pb, 0xe0); /* Configuration MODE */
 	
-	dma = pc_read_configb(pb) & 0x07;
+	dma = parport_pc_read_configb(pb) & 0x07;
 
-	pc_write_econtrol(pb, oldstate);
+	parport_pc_write_econtrol(pb, oldstate);
 	
 	if (dma == 0 || dma == 4) /* Jumper selection */
 		return PARPORT_DMA_NONE;
@@ -405,9 +417,7 @@
 	return retv;
 }
 
-/******************************************************
- *  MODE detection section:
- */
+/* --- Mode detection ------------------------------------- */
 
 /*
  * Clear TIMEOUT BIT in EPP MODE
@@ -416,15 +426,15 @@
 {
 	int r;
 
-	if (!(pc_read_status(pb) & 0x01))
+	if (!(parport_pc_read_status(pb) & 0x01))
 		return 1;
 
 	/* To clear timeout some chips require double read */
-	pc_read_status(pb);
-	r = pc_read_status(pb);
-	pc_write_status(pb, r | 0x01); /* Some reset by writing 1 */
-	pc_write_status(pb, r & 0xfe); /* Others by writing 0 */
-	r = pc_read_status(pb);
+	parport_pc_read_status(pb);
+	r = parport_pc_read_status(pb);
+	parport_pc_write_status(pb, r | 0x01); /* Some reset by writing 1 */
+	parport_pc_write_status(pb, r & 0xfe); /* Others by writing 0 */
+	r = parport_pc_read_status(pb);
 
 	return !(r & 0x01);
 }
@@ -436,12 +446,12 @@
 static int parport_SPP_supported(struct parport *pb)
 {
 	/* Do a simple read-write test to make sure the port exists. */
-	pc_write_control(pb, 0xc);
-	pc_write_data(pb, 0xaa);
-	if (pc_read_data(pb) != 0xaa) return 0;
+	parport_pc_write_control(pb, 0xc);
+	parport_pc_write_data(pb, 0xaa);
+	if (parport_pc_read_data(pb) != 0xaa) return 0;
 	
-	pc_write_data(pb, 0x55);
-	if (pc_read_data(pb) != 0x55) return 0;
+	parport_pc_write_data(pb, 0x55);
+	if (parport_pc_read_data(pb) != 0x55) return 0;
 
 	return PARPORT_MODE_PCSPP;
 }
@@ -460,36 +470,36 @@
  */
 static int parport_ECR_present(struct parport *pb)
 {
-	unsigned int r, octr = pc_read_control(pb), 
-	  oecr = pc_read_econtrol(pb);
+	unsigned int r, octr = parport_pc_read_control(pb), 
+	  oecr = parport_pc_read_econtrol(pb);
 
-	r = pc_read_control(pb);	
-	if ((pc_read_econtrol(pb) & 0x3) == (r & 0x3)) {
-		pc_write_control(pb, r ^ 0x2 ); /* Toggle bit 1 */
-
-		r = pc_read_control(pb);	
-		if ((pc_read_econtrol(pb) & 0x2) == (r & 0x2)) {
-			pc_write_control(pb, octr);
+	r = parport_pc_read_control(pb);	
+	if ((parport_pc_read_econtrol(pb) & 0x3) == (r & 0x3)) {
+		parport_pc_write_control(pb, r ^ 0x2 ); /* Toggle bit 1 */
+
+		r = parport_pc_read_control(pb);	
+		if ((parport_pc_read_econtrol(pb) & 0x2) == (r & 0x2)) {
+			parport_pc_write_control(pb, octr);
 			return 0; /* Sure that no ECR register exists */
 		}
 	}
 	
-	if ((pc_read_econtrol(pb) & 0x3 ) != 0x1)
+	if ((parport_pc_read_econtrol(pb) & 0x3 ) != 0x1)
 		return 0;
 
-	pc_write_econtrol(pb, 0x34);
-	if (pc_read_econtrol(pb) != 0x35)
+	parport_pc_write_econtrol(pb, 0x34);
+	if (parport_pc_read_econtrol(pb) != 0x35)
 		return 0;
 
-	pc_write_econtrol(pb, oecr);
-	pc_write_control(pb, octr);
+	parport_pc_write_econtrol(pb, oecr);
+	parport_pc_write_control(pb, octr);
 	
 	return PARPORT_MODE_PCECR;
 }
 
 static int parport_ECP_supported(struct parport *pb)
 {
-	int i, oecr = pc_read_econtrol(pb);
+	int i, oecr = parport_pc_read_econtrol(pb);
 	
 	/* If there is no ECR, we have no hope of supporting ECP. */
 	if (!(pb->modes & PARPORT_MODE_PCECR))
@@ -500,11 +510,11 @@
 	 * it doesn't support ECP or FIFO MODE
 	 */
 	
-	pc_write_econtrol(pb, 0xc0); /* TEST FIFO */
-	for (i=0; i < 1024 && (pc_read_econtrol(pb) & 0x01); i++)
-		pc_write_fifo(pb, 0xaa);
+	parport_pc_write_econtrol(pb, 0xc0); /* TEST FIFO */
+	for (i=0; i < 1024 && (parport_pc_read_econtrol(pb) & 0x01); i++)
+		parport_pc_write_fifo(pb, 0xaa);
 
-	pc_write_econtrol(pb, oecr);
+	parport_pc_write_econtrol(pb, oecr);
 	return (i==1024)?0:PARPORT_MODE_PCECP;
 }
 
@@ -526,14 +536,14 @@
 	if (!epp_clear_timeout(pb))
 		return 0;  /* No way to clear timeout */
 
-	pc_write_control(pb, pc_read_control(pb) | 0x20);
-	pc_write_control(pb, pc_read_control(pb) | 0x10);
+	parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20);
+	parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10);
 	epp_clear_timeout(pb);
 	
-	pc_read_epp(pb);
+	parport_pc_read_epp(pb);
 	udelay(30);  /* Wait for possible EPP timeout */
 	
-	if (pc_read_status(pb) & 0x01) {
+	if (parport_pc_read_status(pb) & 0x01) {
 		epp_clear_timeout(pb);
 		return PARPORT_MODE_PCEPP;
 	}
@@ -543,17 +553,17 @@
 
 static int parport_ECPEPP_supported(struct parport *pb)
 {
-	int mode, oecr = pc_read_econtrol(pb);
+	int mode, oecr = parport_pc_read_econtrol(pb);
 
 	if (!(pb->modes & PARPORT_MODE_PCECR))
 		return 0;
 	
 	/* Search for SMC style EPP+ECP mode */
-	pc_write_econtrol(pb, 0x80);
+	parport_pc_write_econtrol(pb, 0x80);
 	
 	mode = parport_EPP_supported(pb);
 
-	pc_write_econtrol(pb, oecr);
+	parport_pc_write_econtrol(pb, oecr);
 	
 	return mode?PARPORT_MODE_PCECPEPP:0;
 }
@@ -577,42 +587,41 @@
 
 static int parport_PS2_supported(struct parport *pb)
 {
-	int ok = 0, octr = pc_read_control(pb);
+	int ok = 0, octr = parport_pc_read_control(pb);
   
 	epp_clear_timeout(pb);
 
-	pc_write_control(pb, octr | 0x20);  /* try to tri-state the buffer */
+	parport_pc_write_control(pb, octr | 0x20);  /* try to tri-state the buffer */
 	
-	pc_write_data(pb, 0x55);
-	if (pc_read_data(pb) != 0x55) ok++;
+	parport_pc_write_data(pb, 0x55);
+	if (parport_pc_read_data(pb) != 0x55) ok++;
 
-	pc_write_data(pb, 0xaa);
-	if (pc_read_data(pb) != 0xaa) ok++;
+	parport_pc_write_data(pb, 0xaa);
+	if (parport_pc_read_data(pb) != 0xaa) ok++;
 	
-	pc_write_control(pb, octr);          /* cancel input mode */
+	parport_pc_write_control(pb, octr);          /* cancel input mode */
 
 	return ok?PARPORT_MODE_PCPS2:0;
 }
 
 static int parport_ECPPS2_supported(struct parport *pb)
 {
-	int mode, oecr = pc_read_econtrol(pb);
+	int mode, oecr = parport_pc_read_econtrol(pb);
 
 	if (!(pb->modes & PARPORT_MODE_PCECR))
 		return 0;
 	
-	pc_write_econtrol(pb, 0x20);
+	parport_pc_write_econtrol(pb, 0x20);
 	
 	mode = parport_PS2_supported(pb);
 
-	pc_write_econtrol(pb, oecr);
+	parport_pc_write_econtrol(pb, oecr);
 	return mode?PARPORT_MODE_PCECPPS2:0;
 }
 
-/******************************************************
- *  IRQ detection section:
- *
- * This code is for detecting ECP interrupts (due to problems with the
+/* --- IRQ detection -------------------------------------- */
+
+/* This code is for detecting ECP interrupts (due to problems with the
  * monolithic interrupt probing routines).
  *
  * In short this is a voting system where the interrupt with the most
@@ -667,11 +676,11 @@
 /* Only if supports ECP mode */
 static int programmable_irq_support(struct parport *pb)
 {
-	int irq, oecr = pc_read_econtrol(pb);
+	int irq, oecr = parport_pc_read_econtrol(pb);
 
-	pc_write_econtrol(pb,0xE0); /* Configuration MODE */
+	parport_pc_write_econtrol(pb,0xE0); /* Configuration MODE */
 	
-	irq = (pc_read_configb(pb) >> 3) & 0x07;
+	irq = (parport_pc_read_configb(pb) >> 3) & 0x07;
 
 	switch(irq){
 	case 2:
@@ -687,26 +696,26 @@
 		irq += 7;
 	}
 	
-	pc_write_econtrol(pb, oecr);
+	parport_pc_write_econtrol(pb, oecr);
 	return irq;
 }
 
 static int irq_probe_ECP(struct parport *pb)
 {
-	int irqs, i, oecr = pc_read_econtrol(pb);
+	int irqs, i, oecr = parport_pc_read_econtrol(pb);
 		
 	probe_irq_off(probe_irq_on());	/* Clear any interrupts */
 	irqs = open_intr_election();
 		
-	pc_write_econtrol(pb, 0x00);	    /* Reset FIFO */
-	pc_write_econtrol(pb, 0xd0);	    /* TEST FIFO + nErrIntrEn */
+	parport_pc_write_econtrol(pb, 0x00);	    /* Reset FIFO */
+	parport_pc_write_econtrol(pb, 0xd0);	    /* TEST FIFO + nErrIntrEn */
 
 	/* If Full FIFO sure that WriteIntrThresold is generated */
-	for (i=0; i < 1024 && !(pc_read_econtrol(pb) & 0x02) ; i++) 
-		pc_write_fifo(pb, 0xaa);
+	for (i=0; i < 1024 && !(parport_pc_read_econtrol(pb) & 0x02) ; i++) 
+		parport_pc_write_fifo(pb, 0xaa);
 		
 	pb->irq = close_intr_election(irqs);
-	pc_write_econtrol(pb, oecr);
+	parport_pc_write_econtrol(pb, oecr);
 	return pb->irq;
 }
 
@@ -716,7 +725,7 @@
  */
 static int irq_probe_EPP(struct parport *pb)
 {
-	int irqs, octr = pc_read_control(pb);
+	int irqs, octr = parport_pc_read_control(pb);
 
 #ifndef ADVANCED_DETECT
 	return PARPORT_IRQ_NONE;
@@ -726,27 +735,27 @@
 	irqs = open_intr_election();
 
 	if (pb->modes & PARPORT_MODE_PCECR)
-		pc_write_econtrol(pb, pc_read_econtrol(pb) | 0x10);
+		parport_pc_write_econtrol(pb, parport_pc_read_econtrol(pb) | 0x10);
 	
 	epp_clear_timeout(pb);
-	pc_write_control(pb, pc_read_control(pb) | 0x20);
-	pc_write_control(pb, pc_read_control(pb) | 0x10);
+	parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20);
+	parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10);
 	epp_clear_timeout(pb);
 
 	/*  Device isn't expecting an EPP read
 	 * and generates an IRQ.
 	 */
-	pc_read_epp(pb);
+	parport_pc_read_epp(pb);
 	udelay(20);
 
 	pb->irq = close_intr_election(irqs);
-	pc_write_control(pb, octr);
+	parport_pc_write_control(pb, octr);
 	return pb->irq;
 }
 
 static int irq_probe_SPP(struct parport *pb)
 {
-	int irqs, octr = pc_read_control(pb);
+	int irqs, octr = parport_pc_read_control(pb);
 
 #ifndef ADVANCED_DETECT
 	return PARPORT_IRQ_NONE;
@@ -756,26 +765,26 @@
 	irqs = probe_irq_on();
 
 	if (pb->modes & PARPORT_MODE_PCECR)
-		pc_write_econtrol(pb, 0x10);
+		parport_pc_write_econtrol(pb, 0x10);
 
-	pc_write_data(pb,0x00);
-	pc_write_control(pb,0x00);
-	pc_write_control(pb,0x0c);
+	parport_pc_write_data(pb,0x00);
+	parport_pc_write_control(pb,0x00);
+	parport_pc_write_control(pb,0x0c);
 	udelay(5);
-	pc_write_control(pb,0x0d);
+	parport_pc_write_control(pb,0x0d);
 	udelay(5);
-	pc_write_control(pb,0x0c);
+	parport_pc_write_control(pb,0x0c);
 	udelay(25);
-	pc_write_control(pb,0x08);
+	parport_pc_write_control(pb,0x08);
 	udelay(25);
-	pc_write_control(pb,0x0c);
+	parport_pc_write_control(pb,0x0c);
 	udelay(50);
 
 	pb->irq = probe_irq_off(irqs);
 	if (pb->irq <= 0)
 		pb->irq = PARPORT_IRQ_NONE;	/* No interrupt detected */
 	
-	pc_write_control(pb, octr);
+	parport_pc_write_control(pb, octr);
 	return pb->irq;
 }
 
@@ -796,10 +805,10 @@
 			
 	if (pb->irq == PARPORT_IRQ_NONE && 
 	    (pb->modes & PARPORT_MODE_PCECPEPP)) {
-		int oecr = pc_read_econtrol(pb);
-		pc_write_econtrol(pb, 0x80);
+		int oecr = parport_pc_read_econtrol(pb);
+		parport_pc_write_econtrol(pb, 0x80);
 		pb->irq = irq_probe_EPP(pb);
-		pc_write_econtrol(pb, oecr);
+		parport_pc_write_econtrol(pb, oecr);
 	}
 
 	epp_clear_timeout(pb);
@@ -815,14 +824,16 @@
 	return pb->irq;
 }
 
+/* --- Initialisation code -------------------------------- */
+
 static int probe_one_port(unsigned long int base, int irq, int dma)
 {
 	struct parport tmpport, *p;
 	if (check_region(base, 3)) return 0;
 	tmpport.base = base;
-	tmpport.ops = &pc_ops;
+	tmpport.ops = &parport_pc_ops;
 	if (!(parport_SPP_supported(&tmpport))) return 0;
-       	if (!(p = parport_register_port(base, irq, dma, &pc_ops))) return 0;
+       	if (!(p = parport_register_port(base, irq, dma, &parport_pc_ops))) return 0;
 	p->modes = PARPORT_MODE_PCSPP | parport_PS2_supported(p);
 	if (p->base != 0x3bc) {
 		if (!check_region(base+0x400,3)) {
@@ -866,8 +877,8 @@
 	p->flags |= PARPORT_FLAG_COMA;
 
 	/* Done probing.  Now put the port into a sensible start-up state. */
-	pc_write_control(p, 0xc);
-	pc_write_data(p, 0);
+	parport_pc_write_control(p, 0xc);
+	parport_pc_write_data(p, 0);
 
 	if (parport_probe_hook)
 		(*parport_probe_hook)(p);
@@ -882,23 +893,29 @@
 		/* Only probe the ports we were given. */
 		do {
 			count += probe_one_port(*(io++), *(irq++), *(dma++));
-		} while (*io && (++i < PC_MAX_PORTS));
+		} while (*io && (++i < PARPORT_PC_MAX_PORTS));
 	} else {
 		/* Probe all the likely ports. */
 		count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
 		count += probe_one_port(0x378, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
 		count += probe_one_port(0x278, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
 	}
+
+	/* Give any attached devices a chance to gather their thoughts */
+	current->state = TASK_INTERRUPTIBLE;
+	current->timeout = jiffies + 75;
+	schedule ();
+
 	return count;
 }
 
 #ifdef MODULE
-static int io[PC_MAX_PORTS+1] = { [0 ... PC_MAX_PORTS] = 0 };
-static int dma[PC_MAX_PORTS] = { [0 ... PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
-static int irq[PC_MAX_PORTS] = { [0 ... PC_MAX_PORTS-1] = PARPORT_IRQ_AUTO };
-MODULE_PARM(io, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
-MODULE_PARM(dma, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
+static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
+static int dma[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
+static int irq[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_AUTO };
+MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
 
 int init_module(void)
 {	
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/parport_procfs.c linux/drivers/misc/parport_procfs.c
--- v2.1.81/linux/drivers/misc/parport_procfs.c	Sat Nov 29 16:19:41 1997
+++ linux/drivers/misc/parport_procfs.c	Fri Jan 23 20:04:03 1998
@@ -1,10 +1,11 @@
 /* Parallel port /proc interface code.
  * 
- * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
- *          Tim Waugh <tmw20@cam.ac.uk>
+ * Authors: David Campbell <campbell@torque.net>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *          Philip Blundell <philb@gnu.org>
  *
  * based on work by Grant Guenther <grant@torque.net>
- *              and Philip Blundell <Philip.Blundell@pobox.com>
+ *              and Philip Blundell
  */
 
 #include <linux/stddef.h>
@@ -19,14 +20,10 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
-
 #include <linux/proc_fs.h>
-
 #include <linux/parport.h>
 
-#undef PARPORT_INCLUDE_BENCH
-
-struct proc_dir_entry *base=NULL;
+struct proc_dir_entry *base = NULL;
 
 extern void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs);
 
@@ -36,24 +33,28 @@
 	int newirq;
 	struct parport *pp = (struct parport *)data;
 	
-	if (count > 4 )  /* more than 4 digits for a irq 0x?? 0?? ??  */
-		return(-EOVERFLOW);
+	if (count > 5 )  /* more than 4 digits + \n for a irq 0x?? 0?? ??  */
+		return -EOVERFLOW;
 
 	if (buffer[0] < 32 || !strncmp(buffer, "none", 4)) {
 		newirq = PARPORT_IRQ_NONE;
 	} else {
 		if (buffer[0] == '0') {
-			if( buffer[1] == 'x' )
-				newirq = simple_strtoul(&buffer[2],0,16);
+			if (buffer[1] == 'x')
+				newirq = simple_strtoul(&buffer[2], 0, 16);
 			else
-				newirq = simple_strtoul(&buffer[1],0,8);
+				newirq = simple_strtoul(&buffer[1], 0, 8);
 		} else {
-			newirq = simple_strtoul(buffer,0,10);
+			newirq = simple_strtoul(buffer, 0, 10);
 		}
 	}
 
-	if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) 
-		free_irq(pp->irq, pp);
+	if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) {
+		if (pp->cad->irq_func)
+			free_irq(pp->irq, pp->cad->private);
+		else
+			free_irq(pp->irq, NULL);
+	}
 
 	pp->irq = newirq;
 
@@ -66,11 +67,12 @@
 				request_irq(pp->irq, pd->irq_func ? 
 					    pd->irq_func :
 					    parport_null_intr_func,
-					    SA_INTERRUPT, pd->name, pd->port);
+					    SA_INTERRUPT, pd->name,
+					    pd->private);
 		} else {
 			request_irq(pp->irq, pd->irq_func ? pd->irq_func :
 				    parport_null_intr_func,
-				    SA_INTERRUPT, pp->name, pd->port);
+				    SA_INTERRUPT, pp->name, NULL);
 		}
 	}
 
@@ -102,16 +104,13 @@
 
 	for (pd1 = pp->devices; pd1 ; pd1 = pd1->next) {
 		if (pd1 == pp->cad)
-			len += sprintf(page+len, "+");
+			page[len++] = '+';
 		else
-			len += sprintf(page+len, " ");
+			page[len++] = ' ';
 
-		len += sprintf(page+len, "%s",pd1->name);
+		len += sprintf(page+len, "%s", pd1->name);
 
-		if (pd1 == pp->lurker)
-			len += sprintf(page+len, " LURK");
-		
-		len += sprintf(page+len,"\n");
+		page[len++] = '\n';
 	}
 		
 	*start = 0;
@@ -120,26 +119,26 @@
 }
 
 static int hardware_read_proc(char *page, char **start, off_t off,
-							  int count, int *eof, void *data)
+				  int count, int *eof, void *data)
 {
 	struct parport *pp = (struct parport *)data;
 	int len=0;
 	
 	len += sprintf(page+len, "base:\t0x%lx\n",pp->base);
+
 	if (pp->irq == PARPORT_IRQ_NONE)
 		len += sprintf(page+len, "irq:\tnone\n");
 	else
 		len += sprintf(page+len, "irq:\t%d\n",pp->irq);
+
 	if (pp->dma == PARPORT_DMA_NONE)
 		len += sprintf(page+len, "dma:\tnone\n");
 	else
 		len += sprintf(page+len, "dma:\t%d\n",pp->dma);
 
-
-#if 0
 	len += sprintf(page+len, "modes:\t");
 	{
-#define printmode(x) {if(pp->modes&PARPORT_MODE_##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
+#define printmode(x) {if(pp->modes&PARPORT_MODE_PC##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
 		int f = 0;
 		printmode(SPP);
 		printmode(PS2);
@@ -149,65 +148,21 @@
 		printmode(ECPPS2);
 #undef printmode
 	}
-	len += sprintf(page+len, "\n");
-
-	len += sprintf(page+len, "mode:\t");
-	if (pp->modes & PARPORT_MODE_ECR) {
-		switch (r_ecr(pp) >> 5) {
-		case 0:
-			len += sprintf(page+len, "SPP");
-			if( pp->modes & PARPORT_MODE_PS2 )
-				len += sprintf(page+len, ",PS2");
-			if( pp->modes & PARPORT_MODE_EPP )
-				len += sprintf(page+len, ",EPP");
-			break;
-		case 1:
-			len += sprintf(page+len, "ECPPS2");
-			break;
-		case 2:
-			len += sprintf(page+len, "DATAFIFO");
-			break;
-		case 3:
-			len += sprintf(page+len, "ECP");
-			break;
-		case 4:
-			len += sprintf(page+len, "ECPEPP");
-			break;
-		case 5:
-			len += sprintf(page+len, "Reserved?");
-			break;
-		case 6:
-			len += sprintf(page+len, "TEST");
-			break;
-		case 7:
-			len += sprintf(page+len, "Configuration");
-			break;
-		}
-	} else {
-		len += sprintf(page+len, "SPP");
-		if (pp->modes & PARPORT_MODE_PS2)
-			len += sprintf(page+len, ",PS2");
-		if (pp->modes & PARPORT_MODE_EPP)
-			len += sprintf(page+len, ",EPP");
-	}
-	len += sprintf(page+len, "\n");
-#endif	
-#if 0
-	/* Now no detection, please fix with an external function */
-	len += sprintf(page+len, "chipset:\tunknown\n");
-#endif
-#ifdef PARPORT_INCLUDE_BENCHMARK
-	if (pp->speed)
-		len += sprintf(page+len, "bench:\t%d Bytes/s\n",pp->speed);
-	else
-		len += sprintf(page+len, "bench:\tunknown\n");
-#endif	
+	page[len++] = '\n';
 
 	*start = 0;
 	*eof   = 1;
 	return len;
 }
 
+static inline void destroy_proc_entry(struct proc_dir_entry *root, 
+				      struct proc_dir_entry **d)
+{
+	proc_unregister(root, (*d)->low_ino);
+	kfree(*d);
+	*d = NULL;
+}
+
 static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
 					     struct proc_dir_entry *parent,
 					     unsigned short ino)
@@ -217,6 +172,7 @@
 	ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
 	if (!ent)
 		return NULL;
+
 	memset(ent, 0, sizeof(struct proc_dir_entry));
 	
 	if (mode == S_IFDIR)
@@ -224,11 +180,11 @@
 	else if (mode == 0)
 		mode = S_IFREG | S_IRUGO;
 
-
 	ent->low_ino = ino;
 	ent->name = name;
 	ent->namelen = strlen(name);
 	ent->mode = mode;
+
 	if (S_ISDIR(mode)) 
 		ent->nlink = 2;
 	else
@@ -240,103 +196,95 @@
 }
 
 
-int parport_proc_init()
+int parport_proc_init(void)
 {
 	base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT);
 
-	if (base)
-		return 1;
-	else {
-		printk(KERN_ERR "parport: Error creating proc entry /proc/parport\n");
+	if (base == NULL) {
+		printk(KERN_ERR "Unable to initialise /proc/parport.\n");
 		return 0;
 	}
+
+	return 1;
 }
 
-int parport_proc_cleanup()
+void parport_proc_cleanup(void)
 {
-	if (base)
-		proc_unregister(&proc_root,base->low_ino);
-
+	if (base) proc_unregister(&proc_root,base->low_ino);
 	base = NULL;
-	
-	return 0;
 }
 
 int parport_proc_register(struct parport *pp)
 {
-	struct proc_dir_entry *ent;
-	static int conta=0;
-	char *name;
+	static const char *proc_msg = KERN_ERR "%s: Trouble with /proc.\n";
 
-	memset(&pp->pdir,0,sizeof(struct parport_dir));
+	memset(&pp->pdir, 0, sizeof(struct parport_dir));
 
-	if (!base) {
-		printk(KERN_ERR "parport: Error entry /proc/parport, not generated?\n");
+	if (base == NULL) {
+		printk(KERN_ERR "parport_proc not initialised yet.\n");
 		return 1;
 	}
 	
-	name = pp->pdir.name;
-	sprintf(name,"%d",conta++);
+	strncpy(pp->pdir.name, pp->name + strlen("parport"), 
+		sizeof(pp->pdir.name));
 
-	ent = new_proc_entry(name, S_IFDIR, base,0);
-	if (!ent) {
-		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s\n",name);
+	pp->pdir.entry = new_proc_entry(pp->pdir.name, S_IFDIR, base, 0);
+	if (pp->pdir.entry == NULL) {
+		printk(proc_msg, pp->name);
 		return 1;
 	}
-	pp->pdir.entry = ent;
 
-	ent = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, pp->pdir.entry,0);
-	if (!ent) {
-		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/irq\n",name);
+	pp->pdir.irq = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, 
+				      pp->pdir.entry, 0);
+	if (pp->pdir.irq == NULL) {
+		printk(proc_msg, pp->name);
+		destroy_proc_entry(base, &pp->pdir.entry);
 		return 1;
 	}
-	ent->read_proc = irq_read_proc;
-	ent->write_proc= irq_write_proc;
-	ent->data      = pp;
-	pp->pdir.irq   = ent;
+	pp->pdir.irq->read_proc = irq_read_proc;
+	pp->pdir.irq->write_proc = irq_write_proc;
+	pp->pdir.irq->data = pp;
 	
-	ent = new_proc_entry("devices", 0, pp->pdir.entry,0);
-	if (!ent) {
-		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/devices\n",name);
+	pp->pdir.devices = new_proc_entry("devices", 0, pp->pdir.entry, 0);
+	if (pp->pdir.devices == NULL) {
+		printk(proc_msg, pp->name);
+		destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
+		destroy_proc_entry(base, &pp->pdir.entry);
 		return 1;
 	}
-	ent->read_proc   = devices_read_proc;
-	ent->data        = pp;
-	pp->pdir.devices = ent;
+	pp->pdir.devices->read_proc = devices_read_proc;
+	pp->pdir.devices->data = pp;
 	
-	ent = new_proc_entry("hardware", 0, pp->pdir.entry,0);
-	if (!ent) {
-		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/hardware\n",name);
+	pp->pdir.hardware = new_proc_entry("hardware", 0, pp->pdir.entry, 0);
+	if (pp->pdir.hardware == NULL) {
+		printk(proc_msg, pp->name);
+		destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
+		destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
+		destroy_proc_entry(base, &pp->pdir.entry);
 		return 1;
 	}
-	ent->read_proc    = hardware_read_proc;
-	ent->data         = pp;
-	pp->pdir.hardware = ent;
+	pp->pdir.hardware->read_proc = hardware_read_proc;
+	pp->pdir.hardware->data = pp;
+
 	return 0;
 }
 
 int parport_proc_unregister(struct parport *pp)
 {
 	if (pp->pdir.entry) {
-		if (pp->pdir.irq) {
-			proc_unregister(pp->pdir.entry, pp->pdir.irq->low_ino);
-			kfree(pp->pdir.irq);
-		}
+		if (pp->pdir.irq) 
+			destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
 		
-		if (pp->pdir.devices) {
-			proc_unregister(pp->pdir.entry,
-					pp->pdir.devices->low_ino);
-			kfree(pp->pdir.devices);
-		}
+		if (pp->pdir.devices) 
+			destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
 		
-		if (pp->pdir.hardware) {
-			proc_unregister(pp->pdir.entry,
-					pp->pdir.hardware->low_ino);
-			kfree(pp->pdir.hardware);
-		}
+		if (pp->pdir.hardware)
+			destroy_proc_entry(pp->pdir.entry, &pp->pdir.hardware);
+
+		if (pp->pdir.probe)
+			destroy_proc_entry(pp->pdir.entry, &pp->pdir.probe);
 		
-		proc_unregister(base, pp->pdir.entry->low_ino);
-		kfree(pp->pdir.entry);
+		destroy_proc_entry(base, &pp->pdir.entry);
 	}
 	
 	return 0;
diff -u --recursive --new-file v2.1.81/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- v2.1.81/linux/drivers/misc/parport_share.c	Mon Dec  1 14:49:02 1997
+++ linux/drivers/misc/parport_share.c	Fri Jan 23 20:04:03 1998
@@ -1,14 +1,20 @@
-/* $Id: parport_share.c,v 1.8 1997/11/08 18:55:29 philip Exp $
+/* $Id: parport_share.c,v 1.15 1998/01/11 12:06:17 philip Exp $
  * Parallel-port resource manager code.
  * 
  * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
- *	    Jose Renau <renau@acm.org>
+ *          Jose Renau <renau@acm.org>
+ *          Philip Blundell <philb@gnu.org>
+ *	    Andrea Arcangeli <arcangeli@mbox.queen.it>
  *
  * based on work by Grant Guenther <grant@torque.net>
- *              and Philip Blundell <Philip.Blundell@pobox.com>
+ *          and Philip Blundell
  */
 
+#undef PARPORT_DEBUG_SHARING		/* undef for production */
+
+#include <linux/config.h>
+
 #include <linux/tasks.h>
 
 #include <linux/parport.h>
@@ -18,8 +24,9 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
+#include <linux/sched.h>
 
-#include <linux/config.h>
+#include <asm/spinlock.h>
 
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
@@ -27,6 +34,8 @@
 
 #undef PARPORT_PARANOID
 
+#define PARPORT_DEFAULT_TIMESLICE	(HZ/10)
+
 static struct parport *portlist = NULL, *portlist_tail = NULL;
 static int portcount = 0;
 
@@ -48,8 +57,8 @@
 
 void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
-	/* NULL function - Does nothing */
-	return;
+	/* Null function - does nothing.  IRQs are pointed here whenever
+	   there is no real handler for them.  */
 }
 
 struct parport *parport_register_port(unsigned long base, int irq, int dma,
@@ -58,9 +67,8 @@
 	struct parport *tmp;
 
 	/* Check for a previously registered port.
-	 * NOTE: we will ignore irq and dma if we find a previously
-	 * registered device.
-	 */
+	   NOTE: we will ignore irq and dma if we find a previously
+	   registered device.  */
 	for (tmp = portlist; tmp; tmp = tmp->next) {
 		if (tmp->base == base)
 			return tmp;
@@ -79,9 +87,10 @@
 	tmp->dma = dma;
 	tmp->modes = 0;
  	tmp->next = NULL;
-	tmp->devices = tmp->cad = tmp->lurker = NULL;
+	tmp->devices = tmp->cad = NULL;
 	tmp->flags = 0;
-	tmp->ops = ops; 
+	tmp->ops = ops;
+	spin_lock_init (&tmp->lock);
 
 	tmp->name = kmalloc(15, GFP_KERNEL);
 	if (!tmp->name) {
@@ -91,7 +100,7 @@
 	}
 	sprintf(tmp->name, "parport%d", portcount);
 
-	/* Here we chain the entry to our list. */
+	/* Chain the entry to our list. */
 	if (portlist_tail)
 		portlist_tail->next = tmp;
 	portlist_tail = tmp;
@@ -101,6 +110,8 @@
 	portcount++;
 
 	tmp->probe_info.class = PARPORT_CLASS_LEGACY;  /* assume the worst */
+	tmp->waithead = tmp->waittail = NULL;
+
 	return tmp;
 }
 
@@ -146,13 +157,7 @@
 {
 	struct pardevice *tmp;
 
-	/* We only allow one lurking device. */
 	if (flags & PARPORT_DEV_LURK) {
-		if (port->lurker) {
-			printk(KERN_INFO "%s: refused to register second lurker (%s)\n",
-				   port->name, name);
-			return NULL;
-		}
 		if (!pf || !kf) {
 			printk(KERN_INFO "%s: refused to register lurking device (%s) without callbacks\n", port->name, name);
 			return NULL;
@@ -189,6 +194,7 @@
 	tmp->flags = flags;
 	tmp->irq_func = irq_func;
 	port->ops->save_state(port, tmp->state);
+	tmp->waiting = 0;
 
 	/* Chain this onto the list */
 	tmp->prev = NULL;
@@ -197,40 +203,44 @@
 		port->devices->prev = tmp;
 	port->devices = tmp;
 
-	if (flags & PARPORT_DEV_LURK)
-		port->lurker = tmp;
-
 	inc_parport_count();
 	port->ops->inc_use_count();
 
+	init_waitqueue(&tmp->wait_q);
+	tmp->timeslice = PARPORT_DEFAULT_TIMESLICE;
+	tmp->waitnext = tmp->waitprev = NULL;
+
 	return tmp;
 }
 
 void parport_unregister_device(struct pardevice *dev)
 {
 	struct parport *port;
+	unsigned long flags;
 
+#ifdef PARPORT_PARANOID
 	if (dev == NULL) {
 		printk(KERN_ERR "parport_unregister_device: passed NULL\n");
 		return;
 	}
+#endif
 
 	port = dev->port;
 
 	if (port->cad == dev) {
-		printk(KERN_WARNING "%s: refused to unregister currently active device %s.\n", port->name, dev->name);
+		printk(KERN_WARNING "%s: refused to unregister "
+		       "currently active device %s.\n", port->name, dev->name);
 		return;
 	}
 
-	if (port->lurker == dev)
-		port->lurker = NULL;
-
+	spin_lock_irqsave (&port->lock, flags);
 	if (dev->next)
 		dev->next->prev = dev->prev;
 	if (dev->prev)
 		dev->prev->next = dev->next;
 	else
 		port->devices = dev->next;
+	spin_unlock_irqrestore (&port->lock, flags);
 
 	kfree(dev->state);
 	kfree(dev);
@@ -247,99 +257,184 @@
 
 int parport_claim(struct pardevice *dev)
 {
-	struct pardevice *pd1;
+	struct pardevice *oldcad;
+	struct parport *port = dev->port;
+	unsigned long flags;
 
-	if (dev->port->cad == dev) {
+	if (port->cad == dev) {
 		printk(KERN_INFO "%s: %s already owner\n",
 			   dev->port->name,dev->name);
 		return 0;
 	}
 
+try_again:
 	/* Preempt any current device */
-	pd1 = dev->port->cad;
-	if (dev->port->cad) {
-		if (dev->port->cad->preempt) {
-			if (dev->port->cad->preempt(dev->port->cad->private))
-				return -EAGAIN;
-			dev->port->ops->save_state(dev->port, dev->state);
+	if ((oldcad = port->cad)) {
+		if (oldcad->preempt) {
+			if (oldcad->preempt(oldcad->private))
+				goto blocked;
+			port->ops->save_state(port, dev->state);
 		} else
-			return -EAGAIN;
+			goto blocked;
+
+		if (port->cad != oldcad) {
+			printk(KERN_WARNING 
+			       "%s: %s released port when preempted!\n",
+			       port->name, oldcad->name);
+			if (port->cad)
+				goto blocked;
+		}
 	}
 
-	/* Watch out for bad things */
-	if (dev->port->cad != pd1) {
-		printk(KERN_WARNING "%s: death while preempting %s\n",
-		       dev->port->name, dev->name);
-		if (dev->port->cad)
-			return -EAGAIN;
+	/* Can't fail from now on, so mark ourselves as no longer waiting.  */
+	if (dev->waiting & 1) {
+		dev->waiting = 0;
+
+		/* Take ourselves out of the wait list again.  */
+		spin_lock_irqsave (&port->lock, flags);
+		if (dev->waitprev)
+			dev->waitprev->waitnext = dev->waitnext;
+		else
+			port->waithead = dev->waitnext;
+		if (dev->waitnext)
+			dev->waitnext->waitprev = dev->waitprev;
+		else
+			port->waittail = dev->waitprev;
+		spin_unlock_irqrestore (&port->lock, flags);
+		dev->waitprev = dev->waitnext = NULL;
 	}
 
 	/* Now we do the change of devices */
-	dev->port->cad = dev;
+	port->cad = dev;
 
 	/* Swap the IRQ handlers. */
-	if (dev->port->irq != PARPORT_IRQ_NONE) {
-		free_irq(dev->port->irq, pd1?pd1->private:NULL);
-		request_irq(dev->port->irq, dev->irq_func ? dev->irq_func :
-			    parport_null_intr_func, SA_INTERRUPT, dev->name,
-			    dev->private);
+	if (port->irq != PARPORT_IRQ_NONE) {
+		if (oldcad && oldcad->irq_func) {
+			free_irq(port->irq, oldcad->private);
+			request_irq(port->irq, parport_null_intr_func,
+				    SA_INTERRUPT, port->name, NULL);
+		}
+		if (dev->irq_func) {
+			free_irq(port->irq, NULL);
+			request_irq(port->irq, dev->irq_func,
+				    SA_INTERRUPT, dev->name, dev->private);
+		}
 	}
 
 	/* Restore control registers */
-	dev->port->ops->restore_state(dev->port, dev->state);
-
+	port->ops->restore_state(port, dev->state);
+	dev->time = jiffies;
 	return 0;
+
+blocked:
+	/* If this is the first time we tried to claim the port, register an
+	   interest.  This is only allowed for devices sleeping in
+	   parport_claim_or_block(), or those with a wakeup function.  */
+	if (dev->waiting & 2 || dev->wakeup) {
+		spin_lock_irqsave (&port->lock, flags);
+		if (port->cad == NULL) {
+			/* The port got released in the meantime. */
+			spin_unlock_irqrestore (&port->lock, flags);
+			goto try_again;
+		}
+		if (test_and_set_bit(0, &dev->waiting) == 0) {
+			/* First add ourselves to the end of the wait list. */
+			dev->waitnext = NULL;
+			dev->waitprev = port->waittail;
+			if (port->waittail)
+				port->waittail->waitnext = dev;
+			else {
+				port->waithead = dev->port->waittail = dev;
+			}
+		}
+		spin_unlock_irqrestore (&port->lock, flags);
+	}
+	return -EAGAIN;
+}
+
+int parport_claim_or_block(struct pardevice *dev)
+{
+	int r;
+
+	/* Signal to parport_claim() that we can wait even without a
+	   wakeup function.  */
+	dev->waiting = 2;
+
+	/* Try to claim the port.  If this fails, we need to sleep.  */
+	r = parport_claim(dev);
+	if (r == -EAGAIN) {
+		unsigned long flags;
+#ifdef PARPORT_DEBUG_SHARING
+		printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", dev->name);
+#endif
+		save_flags (flags);
+		cli();
+		/* If dev->waiting is clear now, an interrupt
+		   gave us the port and we would deadlock if we slept.  */
+		if (dev->waiting) {
+			sleep_on(&dev->wait_q);
+			r = 1;
+		} else {
+			r = 0;
+#ifdef PARPORT_DEBUG_SHARING
+			printk(KERN_DEBUG "%s: didn't sleep in parport_claim_or_block()\n",
+			       dev->name);
+#endif
+		}
+		restore_flags(flags);
+#ifdef PARPORT_DEBUG_SHARING
+		if (dev->port->cad != dev)
+			printk(KERN_DEBUG "%s: exiting parport_claim_or_block but %s owns port!\n", dev->name, dev->port->cad?dev->port->cad->name:"nobody");
+#endif
+	}
+	dev->waiting = 0;
+	return r;
 }
 
 void parport_release(struct pardevice *dev)
 {
-	struct pardevice *pd1;
+	struct parport *port = dev->port;
+	struct pardevice *pd;
 
 	/* Make sure that dev is the current device */
-	if (dev->port->cad != dev) {
-		printk(KERN_WARNING "%s: %s tried to release parport when not owner\n", dev->port->name, dev->name);
+	if (port->cad != dev) {
+		printk(KERN_WARNING "%s: %s tried to release parport "
+		       "when not owner\n", port->name, dev->name);
 		return;
 	}
-	dev->port->cad = NULL;
+	port->cad = NULL;
 
 	/* Save control registers */
-	dev->port->ops->save_state(dev->port, dev->state);
+	port->ops->save_state(port, dev->state);
 
 	/* Point IRQs somewhere harmless. */
-	if (dev->port->irq != PARPORT_IRQ_NONE) {
-		free_irq(dev->port->irq, dev->private);
-		request_irq(dev->port->irq, parport_null_intr_func,
-			    SA_INTERRUPT, dev->port->name, NULL);
+	if (port->irq != PARPORT_IRQ_NONE && dev->irq_func) {
+		free_irq(port->irq, dev->private);
+		request_irq(port->irq, parport_null_intr_func,
+			    SA_INTERRUPT, port->name, NULL);
  	}
 
-	/* Walk the list, offering a wakeup callback to everybody other
-	 * than the lurker and the device that called us.
-	 */
-	for (pd1 = dev->next; pd1; pd1 = pd1->next) {
-		if (!(pd1->flags & PARPORT_DEV_LURK)) {
-			if (pd1->wakeup) {
-				pd1->wakeup(pd1->private);
-				if (dev->port->cad)
-					return;
-			}
-		}
-	}
-
-	for (pd1 = dev->port->devices; pd1 && pd1 != dev; pd1 = pd1->next) {
-		if (!(pd1->flags & PARPORT_DEV_LURK)) {
-			if (pd1->wakeup) {
-				pd1->wakeup(pd1->private);
-				if (dev->port->cad)
-					return;
-			}
+	/* If anybody is waiting, find out who's been there longest and
+	   then wake them up. (Note: no locking required) */
+	for (pd = port->waithead; pd; pd = pd->waitnext) {
+		if (pd->waiting & 2) {
+			parport_claim(pd);
+			if (waitqueue_active(&pd->wait_q))
+				wake_up(&pd->wait_q);
+			return;
+		} else if (pd->wakeup) {
+			pd->wakeup(pd->private);
+			if (dev->port->cad)
+				return;
+		} else {
+			printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name);
 		}
 	}
 
-	/* Now give the lurker a chance.
-	 * There must be a wakeup callback because we checked for it
-	 * at registration.
-	 */
-	if (dev->port->lurker && (dev->port->lurker != dev)) {
-		dev->port->lurker->wakeup(dev->port->lurker->private);
+	/* Nobody was waiting, so walk the list to see if anyone is
+	   interested in being woken up.  */
+	for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) {
+		if (pd->wakeup && pd != dev)
+			pd->wakeup(pd->private);
 	}
 }
diff -u --recursive --new-file v2.1.81/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.1.81/linux/drivers/net/de4x5.c	Sat Jan 10 10:46:51 1998
+++ linux/drivers/net/de4x5.c	Mon Jan 26 14:50:59 1998
@@ -369,11 +369,13 @@
                           Fix bug in pci_probe() for 64 bit systems reported
 			   by <belliott@accessone.com>.
       0.533   9-Jan-98    Fix more 64 bit bugs reported by <jal@cs.brown.edu>.
+      0.534  24-Jan-98    Fix last (?) endian bug from 
+                           <Geert.Uytterhoeven@cs.kuleuven.ac.be>
 
     =========================================================================
 */
 
-static const char *version = "de4x5.c:V0.533 1998/1/9 davies@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.534 1998/1/24 davies@maniac.ultranet.com\n";
 
 #include <linux/module.h>
 
@@ -2079,7 +2081,7 @@
 __initfunc(static void
 pci_probe(struct device *dev, u_long ioaddr))
 {
-    u_char pb, pbus, dev_num, dnum, dev_fn, timer;
+    u_char pb, pbus, dev_num, dnum, dev_fn, timer, tirq;
     u_short dev_id, vendor, index, status;
     u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
@@ -2151,8 +2153,8 @@
 
 	    /* Fetch the IRQ to be used */
 #ifndef __sparc_v9__
-	    pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, 
-				                                 (char *)&irq);
+	    pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+	    irq = tirq;
 #else
 	    irq = pdev->irq;
 #endif
@@ -2176,7 +2178,7 @@
 	    }
 	    if (!(status & PCI_COMMAND_MASTER)) continue;
 
-	    /* Check the latency timer for values > 0x60 */
+	    /* Check the latency timer for values >= 0x60 */
 	    pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
 	    if (timer < 0x60) {
 		pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
diff -u --recursive --new-file v2.1.81/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.1.81/linux/drivers/net/dgrs.c	Fri Jan 23 18:10:31 1998
+++ linux/drivers/net/dgrs.c	Sun Jan 25 10:05:46 1998
@@ -1358,6 +1358,8 @@
 /*
  *	Scan for all boards
  */
+static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
+
 __initfunc(static int
 dgrs_scan(struct device *dev))
 {
@@ -1463,8 +1465,6 @@
 	 */
 	if (EISA_bus)
 	{
-		static int      is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
-
 		for (io = 0x1000; io < 0x9000; io += 0x1000)
 		{
 			if (inb(io+ES4H_MANUFmsb) != 0x10
diff -u --recursive --new-file v2.1.81/linux/drivers/net/hamradio/soundmodem/gentbl.c linux/drivers/net/hamradio/soundmodem/gentbl.c
--- v2.1.81/linux/drivers/net/hamradio/soundmodem/gentbl.c	Tue Aug  5 09:49:51 1997
+++ linux/drivers/net/hamradio/soundmodem/gentbl.c	Sun Jan 25 10:05:46 1998
@@ -200,7 +200,9 @@
 					? "\n\t" : "");
 		}
 	}
+#ifdef VERBOSE
 	fprintf(stderr, "fsk9600: txfilt4: min = %f; max = %f\n", min, max);
+#endif
 	fprintf(f, "\n};\n\n");
 	min = max = 0;
 	memset(c, 0, sizeof(c));
@@ -233,7 +235,9 @@
 					? "\n\t" : "");
 		}
 	}
+#ifdef VERBOSE
 	fprintf(stderr, "fsk9600: txfilt5: min = %f; max = %f\n", min, max);
+#endif
 	fprintf(f, "\n};\n\n");
 }
 	
@@ -466,7 +470,9 @@
 					? "\n\t" : "");
 		}
 	}
+#ifdef VERBOSE
 	fprintf(stderr, "hapn4800: txfilt8: min = %f; max = %f\n", min, max);
+#endif
 	fprintf(f, "\n};\n\n");
 	min = max = 0;
 	memset(c, 0, sizeof(c));
@@ -493,7 +499,9 @@
 					? "\n\t" : "");
 		}
 	}
+#ifdef VERBOSE
 	fprintf(stderr, "hapn4800: txfilt10: min = %f; max = %f\n", min, max);
+#endif
 	fprintf(f, "\n};\n\n");
 	/*
 	 * secondly generate tables for the PM transmitter modulator
@@ -524,7 +532,9 @@
 					? "\n\t" : "");
 		}
 	}
+#ifdef VERBOSE
 	fprintf(stderr, "hapn4800: txfiltpm8: min = %f; max = %f\n", min, max);
+#endif
 	fprintf(f, "\n};\n\n");
 	min = max = 0;
 	memset(c, 0, sizeof(c));
@@ -552,7 +562,9 @@
 					? "\n\t" : "");
 		}
 	}
+#ifdef VERBOSE
 	fprintf(stderr, "hapn4800: txfiltpm10: min = %f; max = %f\n", min, max);
+#endif
 	fprintf(f, "\n};\n\n");
 	
 }
diff -u --recursive --new-file v2.1.81/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.1.81/linux/drivers/net/ne.c	Tue Dec  9 09:49:58 1997
+++ linux/drivers/net/ne.c	Mon Jan 26 11:43:18 1998
@@ -72,14 +72,14 @@
 
 #ifdef CONFIG_PCI
 /* Ack! People are making PCI ne2000 clones! Oh the horror, the horror... */
-static struct { unsigned short vendor, dev_id;}
+static struct { unsigned short vendor, dev_id; char *name; }
 pci_clone_list[] __initdata = {
-	{PCI_VENDOR_ID_REALTEK,		PCI_DEVICE_ID_REALTEK_8029},
-	{PCI_VENDOR_ID_WINBOND2,	PCI_DEVICE_ID_WINBOND2_89C940},
-	{PCI_VENDOR_ID_COMPEX,		PCI_DEVICE_ID_COMPEX_RL2000},
-	{PCI_VENDOR_ID_KTI,		PCI_DEVICE_ID_KTI_ET32P2},
-	{PCI_VENDOR_ID_NETVIN,		PCI_DEVICE_ID_NETVIN_NV5000SC},
-	{PCI_VENDOR_ID_VIA,		PCI_DEVICE_ID_VIA_82C926},
+	{PCI_VENDOR_ID_REALTEK,		PCI_DEVICE_ID_REALTEK_8029,		"Realtek 8029" },
+	{PCI_VENDOR_ID_WINBOND2,	PCI_DEVICE_ID_WINBOND2_89C940,		"Winbond 89C940" },
+	{PCI_VENDOR_ID_COMPEX,		PCI_DEVICE_ID_COMPEX_RL2000,		"Compex ReadyLink 2000" },
+	{PCI_VENDOR_ID_KTI,		PCI_DEVICE_ID_KTI_ET32P2,		"KTI ET32P2" },
+	{PCI_VENDOR_ID_NETVIN,		PCI_DEVICE_ID_NETVIN_NV5000SC,		"NetVin NV5000" },
+	{PCI_VENDOR_ID_VIA,		PCI_DEVICE_ID_VIA_82C926,		"VIA 82C926 Amazon" },
 	{0,}
 };
 #endif
@@ -228,9 +228,8 @@
 			break;	/* Beauty -- got a valid card. */
 		}
 		if (pci_irq_line == 0) continue;	/* Try next PCI ID */
-		printk("ne.c: PCI BIOS reports %s %s at i/o %#x, irq %d.\n",
-				pci_strvendor(pci_clone_list[i].vendor),
-				pci_strdev(pci_clone_list[i].vendor, pci_clone_list[i].dev_id),
+		printk("ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
+				pci_clone_list[i].name,
 				pci_ioaddr, pci_irq_line);
 		if (ne_probe1(dev, pci_ioaddr) != 0) {	/* Shouldn't happen. */
 			printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr);
diff -u --recursive --new-file v2.1.81/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.81/linux/drivers/net/ppp.c	Tue Dec 23 10:57:31 1997
+++ linux/drivers/net/ppp.c	Mon Jan 26 13:38:24 1998
@@ -7,7 +7,7 @@
  *  Dynamic PPP devices by Jim Freeman <jfree@caldera.com>.
  *  ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se>
  *
- *  ==FILEVERSION 971205==
+ *  ==FILEVERSION 980123==
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the number above to the
@@ -568,9 +568,7 @@
  */
 	if (new_wbuf == NULL || new_tbuf == NULL ||
 	    new_rbuf == NULL || new_cbuf == NULL) {
-		if (ppp->flags & SC_DEBUG)
-			printk (KERN_ERR
-				"ppp: failed to allocate new buffers\n");
+		printk (KERN_ERR "ppp: failed to allocate new buffers\n");
 
 		ppp_free_buf (new_wbuf);
 		ppp_free_buf (new_tbuf);
@@ -770,8 +768,7 @@
  * There should not be an existing table for this slot.
  */
 	if (ppp) {
-		if (ppp->flags & SC_DEBUG)
-			printk (KERN_ERR
+		printk (KERN_ERR
 			"ppp_tty_open: gack! tty already associated to %s!\n",
 			ppp->magic == PPP_MAGIC ? ppp2dev(ppp)->name
 						: "unknown");
@@ -793,8 +790,7 @@
 	} else {
 		ppp = ppp_alloc();
 		if (ppp == NULL) {
-			if (ppp->flags & SC_DEBUG)
-				printk (KERN_ERR "ppp_alloc failed\n");
+			printk (KERN_ERR "ppp_alloc failed\n");
 			return -ENFILE;
 		}
 /*
@@ -808,9 +804,8 @@
  */
 		ppp->slcomp = slhc_init (16, 16);
 		if (ppp->slcomp == NULL) {
-			if (ppp->flags & SC_DEBUG)
-				printk (KERN_ERR "ppp_tty_open: "
-					"no space for compression buffers!\n");
+			printk (KERN_ERR "ppp_tty_open: "
+				"no space for compression buffers!\n");
 			ppp_release (ppp);
 			return -ENOMEM;
 		}
@@ -826,9 +821,8 @@
  */
 		ppp->ubuf = ppp_alloc_buf (RBUFSIZE, BUFFER_TYPE_TTY_RD);
 		if (ppp->ubuf == NULL) {
-			if (ppp->flags & SC_DEBUG)
-				printk (KERN_ERR "ppp_tty_open: "
-					"no space for user receive buffer\n");
+			printk (KERN_ERR "ppp_tty_open: "
+				"no space for user receive buffer\n");
 			ppp_release (ppp);
 			return -ENOMEM;
 		}
@@ -1300,9 +1294,7 @@
  */
 			new_data = kmalloc (ppp->mru + PPP_HDRLEN, GFP_ATOMIC);
 			if (new_data == NULL) {
-				if (ppp->flags & SC_DEBUG)
-					printk (KERN_ERR
-						"ppp_doframe: no memory\n");
+				printk (KERN_ERR "ppp_doframe: no memory\n");
 				new_count = DECOMP_ERROR;
 			} else {
 				new_count = (*ppp->sc_rcomp->decompress)
@@ -1321,8 +1313,7 @@
 
 			case DECOMP_FATALERROR:
 				ppp->flags |= SC_DC_FERROR;
-				if (ppp->flags & SC_DEBUG)
-					printk(KERN_ERR "ppp: fatal decomp error\n");
+				printk(KERN_ERR "ppp: fatal decomp error\n");
 				break;
 			}
 /*
@@ -2069,15 +2060,16 @@
 	struct ppp *ppp = tty2ppp (tty);
 	__u8 *new_data;
 	int error;
+	struct wait_queue wait = {current, NULL};
 
 /*
  * Verify the pointers.
  */
+	error = -EIO;
 	if (!ppp)
-		return -EIO;
-
+		goto out;
 	if (ppp->magic != PPP_MAGIC)
-		return -EIO;
+		goto out;
 
 	CHECK_PPP (-ENXIO);
 /*
@@ -2096,43 +2088,48 @@
  */
 	new_data = kmalloc (count, GFP_KERNEL);
 	if (new_data == NULL) {
-		if (ppp->flags & SC_DEBUG)
-			printk (KERN_ERR
-				"ppp_tty_write: no memory\n");
+		printk (KERN_ERR "ppp_tty_write: no memory\n");
 		return 0;
 	}
 /*
  * Retrieve the user's buffer
  */
-	error = copy_from_user(new_data, data, count);
-	if (error) {
-		kfree (new_data);
-		return error;
-	}
+	error = -EFAULT;
+	if (copy_from_user(new_data, data, count))
+		goto out_free;
 /*
- * lock this PPP unit so we will be the only writer;
- * sleep if necessary
+ * Lock this PPP unit so we will be the only writer,
+ * sleeping if necessary.
+ *
+ * Note that we add our task to the wait queue before
+ * attempting to lock, as the lock flag may be cleared
+ * from an interrupt.
  */
-	while (lock_buffer (ppp->tbuf) != 0) {
+	add_wait_queue(&ppp->write_wait, &wait);
+	while (1) {
+		error = 0;
 		current->timeout = 0;
-#if 0
-		if (ppp->flags & SC_DEBUG)
-			printk (KERN_DEBUG "ppp_tty_write: sleeping\n");
-#endif
-		interruptible_sleep_on (&ppp->write_wait);
+		current->state = TASK_INTERRUPTIBLE;
+		if (lock_buffer(ppp->tbuf) == 0)
+			break;
+		schedule();
 
+		error = -EINVAL;
 		ppp = tty2ppp (tty);
-		if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse
-		    || tty != ppp->tty) {
-			kfree (new_data);
-			return 0;
-		}
-
-		if (signal_pending(current)) {
-			kfree (new_data);
-			return -EINTR;
+		if (!ppp || ppp->magic != PPP_MAGIC || 
+		    !ppp->inuse || tty != ppp->tty) {
+			printk("ppp_tty_write: %p invalid after wait!\n", ppp);
+			break;
 		}
+		error = -EINTR;
+		if (signal_pending(current))
+			break;
 	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&ppp->write_wait, &wait);
+	if (error)
+		goto out_free;
+
 /*
  * Change the LQR frame
  */
@@ -2152,9 +2149,12 @@
 	} else {
 		ppp_dev_xmit_frame (ppp, ppp->tbuf, new_data, count);
 	}
+	error = count;
 
+out_free:
 	kfree (new_data);
-	return count;
+out:
+	return error;
 }
 
 /*
@@ -2165,31 +2165,30 @@
 ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp)
 {
 	struct compressor *cp;
-	struct ppp_option_data data;
-	int error;
-	int nb;
+	int error, nb;
+	unsigned long flags;
 	__u8 *ptr;
 	__u8 ccp_option[CCP_MAX_OPTION_LENGTH];
-	unsigned long flags;
+	struct ppp_option_data data;
 
 /*
  * Fetch the compression parameters
  */
-	error = copy_from_user(&data, odp, sizeof (data));
-	if (error != 0)
-		return error;
+	error = -EFAULT;
+	if (copy_from_user(&data, odp, sizeof (data)))
+		goto out;
 
 	nb  = data.length;
 	ptr = data.ptr;
 	if ((__u32) nb >= (__u32)CCP_MAX_OPTION_LENGTH)
 		nb = CCP_MAX_OPTION_LENGTH;
 
-	error = copy_from_user(ccp_option, ptr, nb);
-	if (error != 0)
-		return error;
+	if (copy_from_user(ccp_option, ptr, nb))
+		goto out;
 
+	error = -EINVAL;
 	if (ccp_option[1] < 2)	/* preliminary check on the length byte */
-		return (-EINVAL);
+		goto out;
 
 	save_flags(flags);
 	cli();
@@ -2206,53 +2205,52 @@
 	}
 #endif /* CONFIG_KERNELD */
 
-	if (cp != (struct compressor *) 0) {
-		/*
-		 * Found a handler for the protocol - try to allocate
-		 * a compressor or decompressor.
-		 */
-		error = 0;
-		if (data.transmit) {
-			if (ppp->sc_xc_state != NULL)
-				(*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state);
+	if (cp == NULL)
+		goto out_no_comp;
+	/*
+	 * Found a handler for the protocol - try to allocate
+	 * a compressor or decompressor.
+	 */
+	error = 0;
+	if (data.transmit) {
+		if (ppp->sc_xc_state != NULL)
+			(*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state);
+		ppp->sc_xc_state = NULL;
 
-			ppp->sc_xcomp	 = cp;
-			ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb);
+		ppp->sc_xcomp	 = cp;
+		ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb);
+		if (ppp->sc_xc_state == NULL) {
+			printk(KERN_WARNING "%s: comp_alloc failed\n",
+				ppp->name);
+			error = -ENOBUFS;
+		} else if (ppp->flags & SC_DEBUG)
+			printk(KERN_DEBUG "%s: comp_alloc -> %p\n",
+			       ppp->name, ppp->sc_xc_state);
+	} else {
+		if (ppp->sc_rc_state != NULL)
+			(*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state);
+		ppp->sc_rc_state = NULL;
 
-			if (ppp->sc_xc_state == NULL) {
-				if (ppp->flags & SC_DEBUG)
-					printk(KERN_DEBUG "%s: comp_alloc failed\n",
-					       ppp->name);
-				error = -ENOBUFS;
-			} else {
-				if (ppp->flags & SC_DEBUG)
-					printk(KERN_DEBUG "%s: comp_alloc -> %p\n",
-					       ppp->name, ppp->sc_xc_state);
-			}
-		} else {
-			if (ppp->sc_rc_state != NULL)
-				(*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state);
-			ppp->sc_rcomp	 = cp;
-			ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb);
-			if (ppp->sc_rc_state == NULL) {
-				if (ppp->flags & SC_DEBUG)
-					printk(KERN_DEBUG "%s: decomp_alloc failed\n",
-					       ppp->name);
-				error = -ENOBUFS;
-			} else {
-				if (ppp->flags & SC_DEBUG)
-					printk(KERN_DEBUG "%s: decomp_alloc -> %p\n",
-					       ppp->name, ppp->sc_rc_state);
-			}
-		}
-		return (error);
+		ppp->sc_rcomp	 = cp;
+		ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb);
+		if (ppp->sc_rc_state == NULL) {
+			printk(KERN_WARNING "%s: decomp_alloc failed\n",
+				ppp->name);
+			error = -ENOBUFS;
+		} else if (ppp->flags & SC_DEBUG)
+			printk(KERN_DEBUG "%s: decomp_alloc -> %p\n",
+			       ppp->name, ppp->sc_rc_state);
 	}
+out:
+	return error;
 
+out_no_comp:
+	error = -EINVAL;	/* no handler found */
 	if (ppp->flags & SC_DEBUG)
 		printk(KERN_DEBUG "%s: no compressor for [%x %x %x], %x\n",
-		       ppp->name, ccp_option[0], ccp_option[1],
-		       ccp_option[2], nb);
-	return (-EINVAL);	/* no handler found */
+			ppp->name, ccp_option[0], ccp_option[1],
+			ccp_option[2], nb);
+	goto out;
 }
 
 /*
@@ -2409,16 +2407,20 @@
 			/* change absolute times to relative times. */
 			cur_ddinfo.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
 			cur_ddinfo.recv_idle = (jiffies - ppp->last_recv) / HZ;
-			error = copy_to_user((void *) param3, &cur_ddinfo,
-					     sizeof (cur_ddinfo));
+			error = -EFAULT;
+			if (!copy_to_user((void *) param3, &cur_ddinfo,
+					     sizeof (cur_ddinfo)))
+				error = 0;
 		}
 		break;
 /*
  * Retrieve the extended async map
  */
 	case PPPIOCGXASYNCMAP:
-		error = copy_to_user((void *) param3, ppp->xmit_async_map,
-				     sizeof (ppp->xmit_async_map));
+		error = -EFAULT;
+		if (!copy_to_user((void *) param3, ppp->xmit_async_map,
+				     sizeof (ppp->xmit_async_map)))
+			error = 0;
 		break;
 /*
  * Set the async extended map
@@ -2427,15 +2429,16 @@
 		{
 			__u32 temp_tbl[8];
 
-			error = copy_from_user(temp_tbl, (void *) param3,
-					       sizeof (temp_tbl));
-			if (error != 0)
+			error = -EFAULT;
+			if (copy_from_user(temp_tbl, (void *) param3,
+					       sizeof (temp_tbl)))
 				break;
 
 			temp_tbl[1]  =	0x00000000;
 			temp_tbl[2] &= ~0x40000000;
 			temp_tbl[3] |=	0x60000000;
 
+			error = 0;
 			if ((temp_tbl[2] & temp_tbl[3]) != 0 ||
 			    (temp_tbl[4] & temp_tbl[5]) != 0 ||
 			    (temp_tbl[6] & temp_tbl[7]) != 0)
@@ -2461,16 +2464,15 @@
 		temp_i = (temp_i & 255) + 1;
 		if (ppp->flags & SC_DEBUG)
 			printk (KERN_INFO
-				"ppp_tty_ioctl: set maxcid to %d\n",
-				temp_i);
+				"ppp_tty_ioctl: set maxcid to %d\n", temp_i);
 		if (ppp->slcomp != NULL)
 			slhc_free (ppp->slcomp);
-		ppp->slcomp = slhc_init (16, temp_i);
+		ppp->slcomp = NULL;
 
+		ppp->slcomp = slhc_init (16, temp_i);
 		if (ppp->slcomp == NULL) {
-			if (ppp->flags & SC_DEBUG)
-				printk (KERN_ERR
-					"ppp: no space for compression buffers!\n");
+			printk (KERN_ERR "ppp_tty_ioctl: "
+				"no space for compression buffers!\n");
 			ppp_release (ppp);
 			error = -ENOMEM;
 		}
@@ -2486,39 +2488,35 @@
 		{
 			struct npioctl npi;
 
-			error = copy_from_user(&npi, (void *) param3,
-					sizeof (npi));
-			if (error != 0)
+			error = -EFAULT;
+			if (copy_from_user(&npi, (void *) param3, sizeof(npi)))
 				break;
 
-			switch (npi.protocol) {
-			case PPP_IP:
-				npi.protocol = NP_IP;
-				break;
-			default:
+			if (npi.protocol != PPP_IP) {
 				if (ppp->flags & SC_DEBUG)
 					printk(KERN_DEBUG "pppioc[gs]npmode: "
-					       "invalid proto %d\n", npi.protocol);
+					       "invalid protocol %d\n",
+						npi.protocol);
 				error = -EINVAL;
-			}
-
-			if (error != 0)
 				break;
+			}
+			npi.protocol = NP_IP;
 
 			if (param2 == PPPIOCGNPMODE) {
 				npi.mode = ppp->sc_npmode[npi.protocol];
-
-				error = copy_to_user((void *) param3, &npi,
-						     sizeof (npi));
-				break;
+				if (copy_to_user((void *) param3, &npi,
+						sizeof (npi)))
+					break;
 			}
 
 			ppp->sc_npmode[npi.protocol] = npi.mode;
 			if (ppp->flags & SC_DEBUG)
 				printk(KERN_DEBUG "ppp: set np %d to %d\n",
 				       npi.protocol, npi.mode);
+			/* N.B. Why is the busy flag cleared here? */
 			ppp2dev(ppp)->tbusy = 0;
 			mark_bh(NET_BH);
+			error = 0;
 		}
 		break;
 /*
@@ -2542,11 +2540,8 @@
  */
 	default:
 		if (ppp->flags & SC_DEBUG)
-			printk (KERN_ERR
-				"ppp_tty_ioctl: invalid ioctl: %x, addr %lx\n",
-				param2,
-				param3);
-
+			printk (KERN_WARNING "ppp_tty_ioctl: "
+				"invalid ioctl=%x, addr=%lx\n", param2, param3);
 		error = -ENOIOCTLCMD;
 		break;
 	}
@@ -2606,8 +2601,7 @@
 	struct ppp *ppp = dev2ppp (dev);
 
 	if (ppp2tty (ppp) == NULL) {
-		if (ppp->flags & SC_DEBUG)
-			printk (KERN_ERR
+		printk (KERN_ERR
 			"ppp: %s not connected to a TTY! can't go open!\n",
 			dev->name);
 		return -ENXIO;
@@ -2659,8 +2653,9 @@
 /*
  * Move the version data
  */
-	error = copy_to_user(result, szVersion, len);
-
+	error = -EFAULT;
+	if (!copy_to_user(result, szVersion, len))
+		error = 0;
 	return error;
 }
 
@@ -2695,8 +2690,9 @@
 
 	result = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
 
-	error = copy_to_user(result, &temp, sizeof (temp));
-
+	error = -EFAULT;
+	if (!copy_to_user(result, &temp, sizeof (temp)))
+		error = 0;
 	return error;
 }
 
@@ -2727,8 +2723,9 @@
  */
 	result = (struct ppp_comp_stats *) ifr->ifr_ifru.ifru_data;
 
-	error = copy_to_user(result, &temp, sizeof (temp));
-
+	error = -EFAULT;
+	if (!copy_to_user(result, &temp, sizeof (temp)))
+		error = 0;
 	return error;
 }
 
diff -u --recursive --new-file v2.1.81/linux/drivers/net/ppp_deflate.c linux/drivers/net/ppp_deflate.c
--- v2.1.81/linux/drivers/net/ppp_deflate.c	Tue Dec 23 10:57:31 1997
+++ linux/drivers/net/ppp_deflate.c	Mon Jan 26 08:42:50 1998
@@ -188,20 +188,20 @@
 	struct ppp_deflate_state *state;
 	int w_size;
 
+	MOD_INC_USE_COUNT;
 	if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
 	    || options[1] != CILEN_DEFLATE
 	    || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
 	    || options[3] != DEFLATE_CHK_SEQUENCE)
-		return NULL;
+		goto out_fail;
 	w_size = DEFLATE_SIZE(options[2]);
 	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
-		return NULL;
+		goto out_fail;
 
 	state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
 	if (state == NULL)
-		return NULL;
+		goto out_fail;
 
-	MOD_INC_USE_COUNT;
 	memset (state, 0, sizeof (struct ppp_deflate_state));
 	state->strm.next_in = NULL;
 	state->strm.zalloc  = zalloc_init;
@@ -210,13 +210,16 @@
 
 	if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
 			 DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY)
-	    != Z_OK) {
-		z_comp_free(state);
-		return NULL;
-	}
-
+	    != Z_OK)
+		goto out_free;
 	state->strm.zalloc = zalloc;
 	return (void *) state;
+
+out_free:
+	z_comp_free(state);
+out_fail:
+	MOD_DEC_USE_COUNT;
+	return NULL;
 }
 
 static int
@@ -369,33 +372,35 @@
 	struct ppp_deflate_state *state;
 	int w_size;
 
+	MOD_INC_USE_COUNT;
 	if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
 	    || options[1] != CILEN_DEFLATE
 	    || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
 	    || options[3] != DEFLATE_CHK_SEQUENCE)
-		return NULL;
+		goto out_fail;
 	w_size = DEFLATE_SIZE(options[2]);
 	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
-		return NULL;
+		goto out_fail;
 
 	state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
 	if (state == NULL)
-		return NULL;
-
-	MOD_INC_USE_COUNT;
+		goto out_fail;
 	memset (state, 0, sizeof (struct ppp_deflate_state));
 	state->w_size        = w_size;
 	state->strm.next_out = NULL;
 	state->strm.zalloc   = zalloc_init;
 	state->strm.zfree    = zfree;
 
-	if (inflateInit2(&state->strm, -w_size) != Z_OK) {
-		z_decomp_free(state);
-		return NULL;
-	}
-
+	if (inflateInit2(&state->strm, -w_size) != Z_OK)
+		goto out_free;
 	state->strm.zalloc = zalloc;
 	return (void *) state;
+
+out_free:
+	z_decomp_free(state);
+out_fail:
+	MOD_DEC_USE_COUNT;
+	return NULL;
 }
 
 static int
diff -u --recursive --new-file v2.1.81/linux/drivers/net/slhc.c linux/drivers/net/slhc.c
--- v2.1.81/linux/drivers/net/slhc.c	Sat Nov 29 10:33:20 1997
+++ linux/drivers/net/slhc.c	Mon Jan 26 08:42:50 1998
@@ -99,21 +99,18 @@
 	register struct cstate *ts;
 	struct slcompress *comp;
 
+	MOD_INC_USE_COUNT;
 	comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
 					    GFP_KERNEL);
 	if (! comp)
-		return NULL;
-
+		goto out_fail;
 	memset(comp, 0, sizeof(struct slcompress));
 
 	if ( rslots > 0  &&  rslots < 256 ) {
 		size_t rsize = rslots * sizeof(struct cstate);
 		comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL);
 		if (! comp->rstate)
-		{
-			kfree((unsigned char *)comp);
-			return NULL;
-		}
+			goto out_free;
 		memset(comp->rstate, 0, rsize);
 		comp->rslot_limit = rslots - 1;
 	}
@@ -122,11 +119,7 @@
 		size_t tsize = tslots * sizeof(struct cstate);
 		comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL);
 		if (! comp->tstate)
-		{
-			kfree((unsigned char *)comp->rstate);
-			kfree((unsigned char *)comp);
-			return NULL;
-		}
+			goto out_free2;
 		memset(comp->tstate, 0, tsize);
 		comp->tslot_limit = tslots - 1;
 	}
@@ -151,8 +144,15 @@
 		ts[0].next = &(ts[comp->tslot_limit]);
 		ts[0].cs_this = 0;
 	}
-	MOD_INC_USE_COUNT;
 	return comp;
+
+out_free2:
+	kfree((unsigned char *)comp->rstate);
+out_free:
+	kfree((unsigned char *)comp);
+out_fail:
+	MOD_DEC_USE_COUNT;
+	return NULL;
 }
 
 
@@ -163,14 +163,14 @@
 	if ( comp == NULLSLCOMPR )
 		return;
 
-	if ( comp->rstate != NULLSLSTATE )
-		kfree( comp->rstate );
-
 	if ( comp->tstate != NULLSLSTATE )
 		kfree( comp->tstate );
 
-	MOD_DEC_USE_COUNT;
+	if ( comp->rstate != NULLSLSTATE )
+		kfree( comp->rstate );
+
 	kfree( comp );
+	MOD_DEC_USE_COUNT;
 }
 
 
diff -u --recursive --new-file v2.1.81/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.1.81/linux/drivers/net/tulip.c	Tue Jan 20 16:44:57 1998
+++ linux/drivers/net/tulip.c	Sun Jan 25 10:08:40 1998
@@ -1799,8 +1799,8 @@
 	if (entry == TX_RING_SIZE-1)
 		flag |= 0xe2000000;
 
-	tp->tx_ring[entry].length = skb->len | flag;
 	tp->stats.tx_bytes += skb->len;
+	tp->tx_ring[entry].length = skb->len | flag;
 	tp->tx_ring[entry].status = 0x80000000;	/* Pass ownership to the chip. */
 	tp->cur_tx++;
 	/* Trigger an immediate transmit demand. */
diff -u --recursive --new-file v2.1.81/linux/drivers/pci/Makefile linux/drivers/pci/Makefile
--- v2.1.81/linux/drivers/pci/Makefile	Sun Dec 21 17:27:18 1997
+++ linux/drivers/pci/Makefile	Mon Jan 26 11:43:18 1998
@@ -12,7 +12,14 @@
 L_OBJS   := pci.o
 L_TARGET := pci.a
 
-ifeq ($(CONFIG_PCI_OPTIMIZE),y)
+ifdef CONFIG_PROC_FS
+L_OBJS   += proc.o
+ifdef CONFIG_PCI_OLD_PROC
+L_OBJS   += oldproc.o
+endif
+endif
+
+ifdef CONFIG_PCI_OPTIMIZE
 L_OBJS   += quirks.o
 endif
 
diff -u --recursive --new-file v2.1.81/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.1.81/linux/drivers/pci/oldproc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/oldproc.c	Mon Jan 26 11:43:19 1998
@@ -0,0 +1,871 @@
+/*
+ *	$Id: oldproc.c,v 1.4 1998/01/05 14:16:18 mj Exp $
+ *
+ *	Backward-compatible procfs interface for PCI.
+ *
+ *	Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter,
+ *	David Mosberger-Tang, Martin Mares
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <asm/page.h>
+
+#ifdef CONFIG_PROC_FS
+
+struct pci_dev_info {
+	unsigned short	vendor;		/* vendor id */
+	unsigned short	device;		/* device id */
+
+	const char	*name;		/* device name */
+};
+
+#define DEVICE(vid,did,name) \
+  {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##did, (name)}
+
+/*
+ * Sorted in ascending order by vendor and device.
+ * Use binary search for lookup. If you add a device make sure
+ * it is sequential by both vendor and device id.
+ */
+struct pci_dev_info dev_info[] = {
+	DEVICE( COMPAQ,		COMPAQ_1280,	"QVision 1280/p"),
+	DEVICE( COMPAQ,		COMPAQ_SMART2P,	"Smart-2/P RAID Controller"),
+	DEVICE( COMPAQ,		COMPAQ_NETEL100,"Netelligent 10/100"),
+	DEVICE( COMPAQ,		COMPAQ_NETEL10,	"Netelligent 10"),
+	DEVICE( COMPAQ,		COMPAQ_NETFLEX3I,"NetFlex 3"),
+	DEVICE( COMPAQ,		COMPAQ_NETEL100D,"Netelligent 10/100 Dual"),
+	DEVICE( COMPAQ,		COMPAQ_NETEL100PI,"Netelligent 10/100 ProLiant"),
+	DEVICE( COMPAQ,		COMPAQ_NETEL100I,"Netelligent 10/100 Integrated"),
+	DEVICE( COMPAQ,		COMPAQ_THUNDER,	"ThunderLAN"),
+	DEVICE( COMPAQ,		COMPAQ_NETFLEX3B,"NetFlex 3 BNC"),
+	DEVICE( NCR,		NCR_53C810,	"53c810"),
+	DEVICE( NCR,		NCR_53C820,	"53c820"),
+	DEVICE( NCR,		NCR_53C825,	"53c825"),
+	DEVICE( NCR,		NCR_53C815,	"53c815"),
+	DEVICE( NCR,		NCR_53C860,	"53c860"),
+	DEVICE( NCR,		NCR_53C896,	"53c896"),
+	DEVICE( NCR,		NCR_53C895,	"53c895"),
+	DEVICE( NCR,		NCR_53C885,	"53c885"),
+	DEVICE( NCR,		NCR_53C875,	"53c875"),
+	DEVICE( NCR,		NCR_53C875J,	"53c875J"),
+	DEVICE( ATI,		ATI_68800,      "68800AX"),
+	DEVICE( ATI,		ATI_215CT222,   "215CT222"),
+	DEVICE( ATI,		ATI_210888CX,   "210888CX"),
+	DEVICE( ATI,		ATI_215GB,	"Mach64 GB"),
+	DEVICE( ATI,		ATI_215GD,	"Mach64 GD (Rage Pro)"),
+	DEVICE( ATI,		ATI_215GP,	"Mach64 GP (Rage Pro)"),
+	DEVICE( ATI,		ATI_215GT,	"Mach64 GT (Rage II)"),
+	DEVICE( ATI,		ATI_215GTB,	"Mach64 GT (Rage II)"),
+	DEVICE( ATI,		ATI_210888GX,   "210888GX"),
+	DEVICE( ATI,		ATI_264VT,	"Mach64 VT"),
+	DEVICE( VLSI,		VLSI_82C592,	"82C592-FC1"),
+	DEVICE( VLSI,		VLSI_82C593,	"82C593-FC1"),
+	DEVICE( VLSI,		VLSI_82C594,	"82C594-AFC2"),
+	DEVICE( VLSI,		VLSI_82C597,	"82C597-AFC2"),
+	DEVICE( VLSI,		VLSI_82C541,	"82C541 Lynx"),
+	DEVICE( VLSI,		VLSI_82C543,	"82C543 Lynx ISA"),
+	DEVICE( VLSI,		VLSI_VAS96011,	"VAS96011 (Golden Gate II)"),
+	DEVICE( ADL,		ADL_2301,	"2301"),
+	DEVICE( NS,		NS_87415,	"87415"),
+	DEVICE( NS,		NS_87410,	"87410"),
+	DEVICE( TSENG,		TSENG_W32P_2,	"ET4000W32P"),
+	DEVICE( TSENG,		TSENG_W32P_b,	"ET4000W32P rev B"),
+	DEVICE( TSENG,		TSENG_W32P_c,	"ET4000W32P rev C"),
+	DEVICE( TSENG,		TSENG_W32P_d,	"ET4000W32P rev D"),
+	DEVICE( TSENG,		TSENG_ET6000,	"ET6000"),
+	DEVICE( WEITEK,		WEITEK_P9000,	"P9000"),
+	DEVICE( WEITEK,		WEITEK_P9100,	"P9100"),
+	DEVICE( DEC,		DEC_BRD,	"DC21050"),
+	DEVICE( DEC,		DEC_TULIP,	"DC21040"),
+	DEVICE( DEC,		DEC_TGA,	"TGA"),
+	DEVICE( DEC,		DEC_TULIP_FAST,	"DC21140"),
+	DEVICE( DEC,		DEC_TGA2,	"TGA2"),
+	DEVICE( DEC,		DEC_FDDI,	"DEFPA"),
+	DEVICE( DEC,		DEC_TULIP_PLUS,	"DC21041"),
+	DEVICE( DEC,		DEC_21142,	"DC21142"),
+	DEVICE( DEC,		DEC_21052,	"DC21052"),
+	DEVICE( DEC,		DEC_21152,	"DC21152"),
+	DEVICE( CIRRUS,		CIRRUS_7548,	"GD 7548"),
+	DEVICE( CIRRUS,		CIRRUS_5430,	"GD 5430"),
+	DEVICE( CIRRUS,		CIRRUS_5434_4,	"GD 5434"),
+	DEVICE( CIRRUS,		CIRRUS_5434_8,	"GD 5434"),
+	DEVICE( CIRRUS,		CIRRUS_5436,	"GD 5436"),
+	DEVICE( CIRRUS,		CIRRUS_5446,	"GD 5446"),
+	DEVICE( CIRRUS,		CIRRUS_5480,	"GD 5480"),
+	DEVICE( CIRRUS,		CIRRUS_5464,	"GD 5464"),
+	DEVICE( CIRRUS,		CIRRUS_5465,	"GD 5465"),
+	DEVICE( CIRRUS,		CIRRUS_6729,	"CL 6729"),
+	DEVICE( CIRRUS,		CIRRUS_6832,	"PD 6832"),
+	DEVICE( CIRRUS,		CIRRUS_7542,	"CL 7542"),
+	DEVICE( CIRRUS,		CIRRUS_7543,	"CL 7543"),
+	DEVICE( CIRRUS,		CIRRUS_7541,	"CL 7541"),
+	DEVICE( IBM,		IBM_FIRE_CORAL,	"Fire Coral"),
+	DEVICE( IBM,		IBM_TR,		"Token Ring"),
+	DEVICE( IBM,		IBM_82G2675,	"82G2675"),
+	DEVICE( IBM,		IBM_82351,	"82351"),
+	DEVICE( WD,		WD_7197,	"WD 7197"),
+	DEVICE( AMD,		AMD_LANCE,	"79C970"),
+	DEVICE( AMD,		AMD_SCSI,	"53C974"),
+	DEVICE( TRIDENT,	TRIDENT_9420,	"TG 9420"),
+	DEVICE( TRIDENT,	TRIDENT_9440,	"TG 9440"),
+	DEVICE( TRIDENT,	TRIDENT_9660,	"TG 9660 / Cyber9385"),
+	DEVICE( TRIDENT,	TRIDENT_9750,	"Image 975"),
+	DEVICE( AI,		AI_M1435,	"M1435"),
+	DEVICE( MATROX,		MATROX_MGA_2,	"Atlas PX2085"),
+	DEVICE( MATROX,		MATROX_MIL,	"Millennium"),
+	DEVICE( MATROX,		MATROX_MYS,	"Mystique"),
+	DEVICE( MATROX,		MATROX_MIL_2,	"Millennium II"),
+	DEVICE( MATROX,		MATROX_MGA_IMP,	"MGA Impression"),
+	DEVICE( CT,		CT_65545,	"65545"),
+	DEVICE( CT,		CT_65548,	"65548"),
+	DEVICE(	CT,		CT_65550,	"65550"),
+	DEVICE( CT,		CT_65554,	"65554"),
+	DEVICE( MIRO,		MIRO_36050,	"ZR36050"),
+	DEVICE( NEC,		NEC_PCX2,	"PowerVR PCX2"),
+	DEVICE( FD,		FD_36C70,	"TMC-18C30"),
+	DEVICE( SI,		SI_6201,	"6201"),
+	DEVICE( SI,		SI_6202,	"6202"),
+	DEVICE( SI,		SI_503,		"85C503"),
+	DEVICE( SI,		SI_6205,	"6205"),
+	DEVICE( SI,		SI_501,		"85C501"),
+	DEVICE( SI,		SI_496,		"85C496"),
+	DEVICE( SI,		SI_601,		"85C601"),
+	DEVICE( SI,		SI_5107,	"5107"),
+	DEVICE( SI,		SI_5511,		"85C5511"),
+	DEVICE( SI,		SI_5513,		"85C5513"),
+	DEVICE( SI,		SI_5571,	"5571"),
+	DEVICE( SI,		SI_5597,	"5597"),
+	DEVICE( SI,		SI_7001,	"7001"),
+	DEVICE( HP,		HP_J2585A,	"J2585A"),
+	DEVICE( HP,		HP_J2585B,	"J2585B (Lassen)"),
+	DEVICE( PCTECH,		PCTECH_RZ1000,  "RZ1000 (buggy)"),
+	DEVICE( PCTECH,		PCTECH_RZ1001,  "RZ1001 (buggy?)"),
+	DEVICE( DPT,		DPT,		"SmartCache/Raid"),
+	DEVICE( OPTI,		OPTI_92C178,	"92C178"),
+	DEVICE( OPTI,		OPTI_82C557,	"82C557 Viper-M"),
+	DEVICE( OPTI,		OPTI_82C558,	"82C558 Viper-M ISA+IDE"),
+	DEVICE( OPTI,		OPTI_82C621,	"82C621"),
+	DEVICE( OPTI,		OPTI_82C700,	"82C700"),
+	DEVICE( OPTI,		OPTI_82C701,	"82C701 FireStar Plus"),
+	DEVICE( OPTI,		OPTI_82C814,	"82C814 Firebridge 1"),
+	DEVICE( OPTI,		OPTI_82C822,	"82C822"),
+	DEVICE( SGS,		SGS_2000,	"STG 2000X"),
+	DEVICE( SGS,		SGS_1764,	"STG 1764X"),
+	DEVICE( BUSLOGIC,	BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC"),
+	DEVICE( BUSLOGIC,	BUSLOGIC_MULTIMASTER,    "MultiMaster"),
+	DEVICE( BUSLOGIC,	BUSLOGIC_FLASHPOINT,     "FlashPoint"),
+	DEVICE( TI,		TI_TVP4010,	"TVP4010 Permedia"),
+	DEVICE( TI,		TI_TVP4020,	"TVP4020 Permedia 2"),
+	DEVICE( TI,		TI_PCI1130,	"PCI1130"),
+	DEVICE( TI,		TI_PCI1131,	"PCI1131"),
+	DEVICE( OAK,		OAK_OTI107,	"OTI107"),
+	DEVICE( WINBOND2,	WINBOND2_89C940,"NE2000-PCI"),
+	DEVICE( MOTOROLA,	MOTOROLA_MPC105,"MPC105 Eagle"),
+	DEVICE( MOTOROLA,	MOTOROLA_MPC106,"MPC106 Grackle"),
+	DEVICE( MOTOROLA,	MOTOROLA_RAVEN,	"Raven"),
+	DEVICE( PROMISE,        PROMISE_20246,	"IDE UltraDMA/33"),
+	DEVICE( PROMISE,	PROMISE_5300,	"DC5030"),
+	DEVICE( N9,		N9_I128,	"Imagine 128"),
+	DEVICE( N9,		N9_I128_2,	"Imagine 128v2"),
+	DEVICE( UMC,		UMC_UM8673F,	"UM8673F"),
+	DEVICE( UMC,		UMC_UM8891A,	"UM8891A"),
+	DEVICE( UMC,		UMC_UM8886BF,	"UM8886BF"),
+	DEVICE( UMC,		UMC_UM8886A,	"UM8886A"),
+	DEVICE( UMC,		UMC_UM8881F,	"UM8881F"),
+	DEVICE( UMC,		UMC_UM8886F,	"UM8886F"),
+	DEVICE( UMC,		UMC_UM9017F,	"UM9017F"),
+	DEVICE( UMC,		UMC_UM8886N,	"UM8886N"),
+	DEVICE( UMC,		UMC_UM8891N,	"UM8891N"),
+	DEVICE( X,		X_AGX016,	"ITT AGX016"),
+	DEVICE( PICOP,		PICOP_PT86C52X,	"PT86C52x Vesuvius"),
+	DEVICE( APPLE,		APPLE_BANDIT,	"Bandit"),
+	DEVICE( APPLE,		APPLE_GC,	"Grand Central"),
+	DEVICE( APPLE,		APPLE_HYDRA,	"Hydra"),
+	DEVICE( NEXGEN,		NEXGEN_82C501,	"82C501"),
+	DEVICE( QLOGIC,		QLOGIC_ISP1020,	"ISP1020"),
+	DEVICE( QLOGIC,		QLOGIC_ISP1022,	"ISP1022"),
+	DEVICE( CYRIX,		CYRIX_5510,	"5510"),
+	DEVICE( CYRIX,		CYRIX_PCI_MASTER,"PCI Master"),
+	DEVICE( CYRIX,		CYRIX_5520,	"5520"),
+	DEVICE( CYRIX,		CYRIX_5530_LEGACY,"5530 Kahlua Legacy"),
+	DEVICE( CYRIX,		CYRIX_5530_SMI,	"5530 Kahlua SMI"),
+	DEVICE( CYRIX,		CYRIX_5530_IDE,	"5530 Kahlua IDE"),
+	DEVICE( CYRIX,		CYRIX_5530_AUDIO,"5530 Kahlua Audio"),
+	DEVICE( CYRIX,		CYRIX_5530_VIDEO,"5530 Kahlua Video"),
+	DEVICE( LEADTEK,	LEADTEK_805,	"S3 805"),
+	DEVICE( CONTAQ,		CONTAQ_82C599,	"82C599"),
+	DEVICE( OLICOM,		OLICOM_OC3136,	"OC-3136/3137"),
+	DEVICE( OLICOM,		OLICOM_OC2315,	"OC-2315"),
+	DEVICE( OLICOM,		OLICOM_OC2325,	"OC-2325"),
+	DEVICE( OLICOM,		OLICOM_OC2183,	"OC-2183/2185"),
+	DEVICE( OLICOM,		OLICOM_OC2326,	"OC-2326"),
+	DEVICE( OLICOM,		OLICOM_OC6151,	"OC-6151/6152"),
+	DEVICE( SUN,		SUN_EBUS,	"EBUS"),
+	DEVICE( SUN,		SUN_HAPPYMEAL,	"Happy Meal"),
+	DEVICE( SUN,		SUN_PBM,	"PCI Bus Module"),
+	DEVICE( CMD,		CMD_640,	"640 (buggy)"),
+	DEVICE( CMD,		CMD_643,	"643"),
+	DEVICE( CMD,		CMD_646,	"646"),
+	DEVICE( CMD,		CMD_670,	"670"),
+	DEVICE( VISION,		VISION_QD8500,	"QD-8500"),
+	DEVICE( VISION,		VISION_QD8580,	"QD-8580"),
+	DEVICE( BROOKTREE,	BROOKTREE_848,	"Bt848"),
+	DEVICE( SIERRA,		SIERRA_STB,	"STB Horizon 64"),
+	DEVICE( ACC,		ACC_2056,	"2056"),
+	DEVICE( WINBOND,	WINBOND_83769,	"W83769F"),
+	DEVICE( WINBOND,	WINBOND_82C105,	"SL82C105"),
+	DEVICE( WINBOND,	WINBOND_83C553,	"W83C553"),
+	DEVICE( DATABOOK,      	DATABOOK_87144,	"DB87144"),
+	DEVICE( 3COM,		3COM_3C590,	"3C590 10bT"),
+	DEVICE( 3COM,		3COM_3C595TX,	"3C595 100bTX"),
+	DEVICE( 3COM,		3COM_3C595T4,	"3C595 100bT4"),
+	DEVICE( 3COM,		3COM_3C595MII,	"3C595 100b-MII"),
+	DEVICE( 3COM,		3COM_3C900TPO,	"3C900 10bTPO"),
+	DEVICE( 3COM,		3COM_3C900COMBO,"3C900 10b Combo"),
+	DEVICE( 3COM,		3COM_3C905TX,	"3C905 100bTX"),
+	DEVICE( SMC,		SMC_EPIC100,	"9432 TX"),
+	DEVICE( AL,		AL_M1445,	"M1445"),
+	DEVICE( AL,		AL_M1449,	"M1449"),
+	DEVICE( AL,		AL_M1451,	"M1451"),
+	DEVICE( AL,		AL_M1461,	"M1461"),
+	DEVICE( AL,		AL_M1489,	"M1489"),
+	DEVICE( AL,		AL_M1511,	"M1511"),
+	DEVICE( AL,		AL_M1513,	"M1513"),
+	DEVICE( AL,		AL_M1521,	"M1521"),
+	DEVICE( AL,		AL_M1523,	"M1523"),
+	DEVICE( AL,		AL_M1531,	"M1531 Aladdin IV"),
+	DEVICE( AL,		AL_M1533,	"M1533 Aladdin IV"),
+	DEVICE( AL,		AL_M4803,	"M4803"),
+	DEVICE( AL,		AL_M5219,	"M5219"),
+	DEVICE( AL,		AL_M5229,	"M5229 TXpro"),
+	DEVICE( SURECOM,	SURECOM_NE34,	"NE-34PCI LAN"),
+	DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2070,     "Magicgraph NM2070"),
+	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
+	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV"),
+	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160"),
+	DEVICE( ASP,		ASP_ABP940,	"ABP940"),
+	DEVICE( ASP,		ASP_ABP940U,	"ABP940U"),
+	DEVICE( CERN,		CERN_SPSB_PMC,	"STAR/RD24 SCI-PCI (PMC)"),
+	DEVICE( CERN,		CERN_SPSB_PCI,	"STAR/RD24 SCI-PCI (PMC)"),
+	DEVICE( IMS,		IMS_8849,	"8849"),
+	DEVICE( TEKRAM2,	TEKRAM2_690c,	"DC690c"),
+	DEVICE( TUNDRA,		TUNDRA_CA91C042,"CA91C042 Universe"),
+	DEVICE( AMCC,		AMCC_MYRINET,	"Myrinet PCI (M2-PCI-32)"),
+	DEVICE( AMCC,		AMCC_S5933,	"S5933 PCI44"),
+	DEVICE( AMCC,		AMCC_S5933_HEPC3,"S5933 Traquair HEPC3"),
+	DEVICE( INTERG,		INTERG_1680,	"IGA-1680"),
+	DEVICE( INTERG,         INTERG_1682,    "IGA-1682"),
+	DEVICE( REALTEK,	REALTEK_8029,	"8029"),
+	DEVICE( REALTEK,	REALTEK_8129,	"8129"),
+	DEVICE( TRUEVISION,	TRUEVISION_T1000,"TARGA 1000"),
+	DEVICE( INIT,		INIT_320P,	"320 P"),
+	DEVICE( VIA,		VIA_82C505,	"VT 82C505"),
+	DEVICE( VIA,		VIA_82C561,	"VT 82C561"),
+	DEVICE( VIA,		VIA_82C586_1,	"VT 82C586 Apollo IDE"),
+	DEVICE( VIA,		VIA_82C576,	"VT 82C576 3V"),
+	DEVICE( VIA,		VIA_82C585,	"VT 82C585 Apollo VP1/VPX"),
+	DEVICE( VIA,		VIA_82C586_0,	"VT 82C586 Apollo ISA"),
+	DEVICE( VIA,		VIA_82C595,	"VT 82C595 Apollo VP2"),
+	DEVICE( VIA,		VIA_82C926,	"VT 82C926 Amazon"),
+	DEVICE( VIA,		VIA_82C416,	"VT 82C416MV"),
+	DEVICE( VIA,		VIA_82C595_97,	"VT 82C595 Apollo VP2/97"),
+	DEVICE( VIA,		VIA_82C586_2,	"VT 82C586 Apollo USB"),
+	DEVICE( VIA,		VIA_82C586_3,	"VT 82C586B Apollo ACPI"),
+	DEVICE( VORTEX,		VORTEX_GDT60x0,	"GDT 60x0"),
+	DEVICE( VORTEX,		VORTEX_GDT6000B,"GDT 6000b"),
+	DEVICE( VORTEX,		VORTEX_GDT6x10,	"GDT 6110/6510"),
+	DEVICE( VORTEX,		VORTEX_GDT6x20,	"GDT 6120/6520"),
+	DEVICE( VORTEX,		VORTEX_GDT6530,	"GDT 6530"),
+	DEVICE( VORTEX,		VORTEX_GDT6550,	"GDT 6550"),
+	DEVICE( VORTEX,		VORTEX_GDT6x17,	"GDT 6117/6517"),
+	DEVICE( VORTEX,		VORTEX_GDT6x27,	"GDT 6127/6527"),
+	DEVICE( VORTEX,		VORTEX_GDT6537,	"GDT 6537"),
+	DEVICE( VORTEX,		VORTEX_GDT6557,	"GDT 6557"),
+	DEVICE( VORTEX,		VORTEX_GDT6x15,	"GDT 6115/6515"),
+	DEVICE( VORTEX,		VORTEX_GDT6x25,	"GDT 6125/6525"),
+	DEVICE( VORTEX,		VORTEX_GDT6535,	"GDT 6535"),
+	DEVICE( VORTEX,		VORTEX_GDT6555,	"GDT 6555"),
+	DEVICE( VORTEX,		VORTEX_GDT6x17RP,"GDT 6117RP/6517RP"),
+	DEVICE( VORTEX,		VORTEX_GDT6x27RP,"GDT 6127RP/6527RP"),
+	DEVICE( VORTEX,		VORTEX_GDT6537RP,"GDT 6537RP"),
+	DEVICE( VORTEX,		VORTEX_GDT6557RP,"GDT 6557RP"),
+	DEVICE( VORTEX,		VORTEX_GDT6x11RP,"GDT 6111RP/6511RP"),
+	DEVICE( VORTEX,		VORTEX_GDT6x21RP,"GDT 6121RP/6521RP"),
+	DEVICE( VORTEX,		VORTEX_GDT6x17RP1,"GDT 6117RP1/6517RP1"),
+	DEVICE( VORTEX,		VORTEX_GDT6x27RP1,"GDT 6127RP1/6527RP1"),
+	DEVICE( VORTEX,		VORTEX_GDT6537RP1,"GDT 6537RP1"),
+	DEVICE( VORTEX,		VORTEX_GDT6557RP1,"GDT 6557RP1"),
+	DEVICE( VORTEX,		VORTEX_GDT6x11RP1,"GDT 6111RP1/6511RP1"),
+	DEVICE( VORTEX,		VORTEX_GDT6x21RP1,"GDT 6121RP1/6521RP1"),
+	DEVICE( VORTEX,		VORTEX_GDT6x17RP2,"GDT 6117RP2/6517RP2"),
+	DEVICE( VORTEX,		VORTEX_GDT6x27RP2,"GDT 6127RP2/6527RP2"),
+	DEVICE( VORTEX,		VORTEX_GDT6537RP2,"GDT 6537RP2"),
+	DEVICE( VORTEX,		VORTEX_GDT6557RP2,"GDT 6557RP2"),
+	DEVICE( VORTEX,		VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2"),
+	DEVICE( VORTEX,		VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2"),
+	DEVICE( EF,		EF_ATM_FPGA,		"155P-MF1 (FPGA)"),
+	DEVICE( EF,		EF_ATM_ASIC,	"155P-MF1 (ASIC)"),
+	DEVICE( FORE,		FORE_PCA200PC, "PCA-200PC"),
+	DEVICE( FORE,		FORE_PCA200E,	 "PCA-200E"),
+	DEVICE( IMAGINGTECH,	IMAGINGTECH_ICPCI, "MVC IC-PCI"),
+	DEVICE( PHILIPS,	PHILIPS_SAA7146,"SAA7146"),
+	DEVICE( PLX,		PLX_9060,	"PCI9060 i960 bridge"),
+	DEVICE( ALLIANCE,	ALLIANCE_PROMOTIO, "Promotion-6410"),
+	DEVICE( ALLIANCE,	ALLIANCE_PROVIDEO, "Provideo"),
+	DEVICE( ALLIANCE,	ALLIANCE_AT24,	"AT24"),
+	DEVICE( ALLIANCE,	ALLIANCE_AT3D,	"AT3D"),
+	DEVICE( VMIC,		VMIC_VME,	"VMIVME-7587"),
+ 	DEVICE( DIGI,		DIGI_RIGHTSWITCH, "RightSwitch SE-6"),
+	DEVICE( MUTECH,		MUTECH_MV1000,	"MV-1000"),
+	DEVICE( RENDITION,	RENDITION_VERITE,"Verite 1000"),
+	DEVICE( RENDITION,	RENDITION_VERITE2100,"Verite 2100"),
+	DEVICE( TOSHIBA,	TOSHIBA_601,	"Laptop"),
+	DEVICE( RICOH,		RICOH_RL5C466,	"RL5C466"),
+	DEVICE( ZEITNET,	ZEITNET_1221,	"1221"),
+	DEVICE( ZEITNET,	ZEITNET_1225,	"1225"),
+	DEVICE( OMEGA,		OMEGA_82C092G,	"82C092G"),
+	DEVICE( LITEON,		LITEON_LNE100TX,"LNE100TX"),
+	DEVICE( NP,		NP_PCI_FDDI,	"NP-PCI"),       
+	DEVICE( SPECIALIX,	SPECIALIX_XIO,	"XIO/SIO host"),
+	DEVICE( SPECIALIX,	SPECIALIX_RIO,	"RIO host"),
+	DEVICE( AURAVISION,	AURAVISION_VXP524,"VXP524"),
+	DEVICE( IKON,		IKON_10115,	"10115 Greensheet"),
+	DEVICE( IKON,		IKON_10117,	"10117 Greensheet"),
+	DEVICE( ZORAN,		ZORAN_36057,	"ZR36057"),
+	DEVICE( ZORAN,		ZORAN_36120,	"ZR36120"),
+	DEVICE( COMPEX,		COMPEX_ENET100VG4, "Readylink ENET100-VG4"),
+	DEVICE( COMPEX,		COMPEX_RL2000,	"ReadyLink 2000"),
+	DEVICE( RP,             RP8OCTA,        "RocketPort 8 Oct"),
+	DEVICE( RP,             RP8INTF,        "RocketPort 8 Intf"),
+	DEVICE( RP,             RP16INTF,       "RocketPort 16 Intf"),
+	DEVICE( RP,             RP32INTF,       "RocketPort 32 Intf"),
+	DEVICE( CYCLADES,	CYCLOM_Y_Lo,	"Cyclom-Y below 1Mbyte"),
+	DEVICE( CYCLADES,	CYCLOM_Y_Hi,	"Cyclom-Y above 1Mbyte"),
+	DEVICE( CYCLADES,	CYCLOM_Z_Lo,	"Cyclom-Z below 1Mbyte"),
+	DEVICE( CYCLADES,	CYCLOM_Z_Hi,	"Cyclom-Z above 1Mbyte"),
+	DEVICE( 3DFX,		3DFX_VOODOO,	"Voodoo"),
+	DEVICE( STALLION,	STALLION_ECHPCI832,"EasyConnection 8/32"),
+	DEVICE( STALLION,	STALLION_ECHPCI864,"EasyConnection 8/64"),
+	DEVICE( STALLION,	STALLION_EIOPCI,"EasyIO"),
+	DEVICE( SIGMADES,	SIGMADES_6425,	"REALmagic64/GX"),
+	DEVICE( OPTIBASE,	OPTIBASE_FORGE,	"MPEG Forge"),
+	DEVICE( OPTIBASE,	OPTIBASE_FUSION,"MPEG Fusion"),
+	DEVICE( OPTIBASE,	OPTIBASE_VPLEX,	"VideoPlex"),
+	DEVICE( OPTIBASE,	OPTIBASE_VPLEXCC,"VideoPlex CC"),
+	DEVICE( OPTIBASE,	OPTIBASE_VQUEST,"VideoQuest"),
+	DEVICE( ENSONIQ,	ENSONIQ_AUDIOPCI,"AudioPCI"),
+	DEVICE( PICTUREL,	PICTUREL_PCIVST,"PCIVST"),
+	DEVICE( NVIDIA_SGS,	NVIDIA_SGS_RIVA128,	"Riva 128"),
+	DEVICE( SYMPHONY,	SYMPHONY_101,	"82C101"),
+	DEVICE( TEKRAM,		TEKRAM_DC290,	"DC-290"),
+	DEVICE( 3DLABS,		3DLABS_300SX,	"GLINT 300SX"),
+	DEVICE( 3DLABS,		3DLABS_500TX,	"GLINT 500TX"),
+	DEVICE( 3DLABS,		3DLABS_DELTA,	"GLINT Delta"),
+	DEVICE( 3DLABS,		3DLABS_PERMEDIA,"PERMEDIA"),
+	DEVICE( AVANCE,		AVANCE_ALG2064,	"ALG2064i"),
+	DEVICE( AVANCE,		AVANCE_2302,	"ALG-2302"),
+	DEVICE( NETVIN,		NETVIN_NV5000SC,"NV5000"),
+	DEVICE( S3,		S3_PLATO_PXS,	"PLATO/PX (system)"),
+	DEVICE( S3,		S3_ViRGE,	"ViRGE"),
+	DEVICE( S3,		S3_TRIO,	"Trio32/Trio64"),
+	DEVICE( S3,		S3_AURORA64VP,	"Aurora64V+"),
+	DEVICE( S3,		S3_TRIO64UVP,	"Trio64UV+"),
+	DEVICE( S3,		S3_ViRGE_VX,	"ViRGE/VX"),
+	DEVICE( S3,		S3_868,	"Vision 868"),
+	DEVICE( S3,		S3_928,		"Vision 928-P"),
+	DEVICE( S3,		S3_864_1,	"Vision 864-P"),
+	DEVICE( S3,		S3_864_2,	"Vision 864-P"),
+	DEVICE( S3,		S3_964_1,	"Vision 964-P"),
+	DEVICE( S3,		S3_964_2,	"Vision 964-P"),
+	DEVICE( S3,		S3_968,		"Vision 968"),
+	DEVICE( S3,		S3_TRIO64V2,	"Trio64V2/DX or /GX"),
+	DEVICE( S3,		S3_PLATO_PXG,	"PLATO/PX (graphics)"),
+	DEVICE( S3,		S3_ViRGE_DXGX,	"ViRGE/DX or /GX"),
+	DEVICE( S3,		S3_ViRGE_GX2,	"ViRGE/GX2"),
+	DEVICE( S3,		S3_ViRGE_MX,	"ViRGE/MX"),
+	DEVICE( S3,		S3_ViRGE_MXP,	"ViRGE/MX+"),
+	DEVICE( S3,		S3_ViRGE_MXPMV,	"ViRGE/MX+MV"),
+	DEVICE( INTEL,		INTEL_82375,	"82375EB"),
+	DEVICE( INTEL,		INTEL_82424,	"82424ZX Saturn"),
+	DEVICE( INTEL,		INTEL_82378,	"82378IB"),
+	DEVICE( INTEL,		INTEL_82430,	"82430ZX Aries"),
+	DEVICE( INTEL,		INTEL_82434,	"82434LX Mercury/Neptune"),
+	DEVICE( INTEL,		INTEL_82092AA_0,"82092AA PCMCIA bridge"),
+	DEVICE( INTEL,		INTEL_82092AA_1,"82092AA EIDE"),
+	DEVICE( INTEL,		INTEL_7116,	"SAA7116"),
+	DEVICE( INTEL,		INTEL_82596,	"82596"),
+	DEVICE( INTEL,		INTEL_82865,	"82865"),
+	DEVICE( INTEL,		INTEL_82557,	"82557"),
+	DEVICE( INTEL,		INTEL_82437,	"82437"),
+	DEVICE( INTEL,		INTEL_82371FB_0,"82371FB PIIX ISA"),
+	DEVICE( INTEL,		INTEL_82371FB_1,"82371FB PIIX IDE"),
+	DEVICE( INTEL,		INTEL_82371MX,	"430MX - 82371MX MPIIX"),
+	DEVICE( INTEL,		INTEL_82437MX,	"430MX - 82437MX MTSC"),
+	DEVICE( INTEL,		INTEL_82441,	"82441FX Natoma"),
+	DEVICE( INTEL,		INTEL_82439,	"82439HX Triton II"),
+	DEVICE(	INTEL,		INTEL_82371SB_0,"82371SB PIIX3 ISA"),
+	DEVICE(	INTEL,		INTEL_82371SB_1,"82371SB PIIX3 IDE"),
+	DEVICE( INTEL,		INTEL_82371SB_2,"82371SB PIIX3 USB"),
+	DEVICE( INTEL,		INTEL_82437VX,	"82437VX Triton II"),
+	DEVICE( INTEL,		INTEL_82439TX,	"82439TX"),
+	DEVICE( INTEL,		INTEL_82371AB_0,"82371AB PIIX4 ISA"),
+	DEVICE( INTEL,		INTEL_82371AB,	"82371AB PIIX4 IDE"),
+	DEVICE( INTEL,		INTEL_82371AB_2,"82371AB PIIX4 USB"),
+	DEVICE( INTEL,		INTEL_82371AB_3,"82371AB PIIX4 ACPI"),
+	DEVICE( INTEL,		INTEL_82443LX_0,"440LX - 82443LX PAC Host"),
+	DEVICE( INTEL,		INTEL_82443LX_1,"440LX - 82443LX PAC AGP"),
+	DEVICE( INTEL,		INTEL_P6,	"Orion P6"),
+ 	DEVICE( INTEL,		INTEL_82450GX,	"82450GX Orion P6"),
+	DEVICE(	KTI,		KTI_ET32P2,	"ET32P2"),
+	DEVICE( ADAPTEC,	ADAPTEC_7850,	"AIC-7850"),
+	DEVICE( ADAPTEC,	ADAPTEC_7855,	"AIC-7855"),
+	DEVICE( ADAPTEC,	ADAPTEC_5800,	"AIC-5800"),
+	DEVICE( ADAPTEC,	ADAPTEC_7860,	"AIC-7860"),
+	DEVICE( ADAPTEC,	ADAPTEC_7861,	"AIC-7861"),
+	DEVICE( ADAPTEC,	ADAPTEC_7870,	"AIC-7870"),
+	DEVICE( ADAPTEC,	ADAPTEC_7871,	"AIC-7871"),
+	DEVICE( ADAPTEC,	ADAPTEC_7872,	"AIC-7872"),
+	DEVICE( ADAPTEC,	ADAPTEC_7873,	"AIC-7873"),
+	DEVICE( ADAPTEC,	ADAPTEC_7874,	"AIC-7874"),
+	DEVICE( ADAPTEC,	ADAPTEC_7895,	"AIC-7895U"),
+	DEVICE( ADAPTEC,	ADAPTEC_7880,	"AIC-7880U"),
+	DEVICE( ADAPTEC,	ADAPTEC_7881,	"AIC-7881U"),
+	DEVICE( ADAPTEC,	ADAPTEC_7882,	"AIC-7882U"),
+	DEVICE( ADAPTEC,	ADAPTEC_7883,	"AIC-7883U"),
+	DEVICE( ADAPTEC,	ADAPTEC_7884,	"AIC-7884U"),
+  	DEVICE( ATRONICS,	ATRONICS_2015,	"IDE-2015PL"),
+	DEVICE( ARK,		ARK_STING,	"Stingray"),
+	DEVICE( ARK,		ARK_STINGARK,	"Stingray ARK 2000PV"),
+	DEVICE( ARK,		ARK_2000MT,	"2000MT")
+};
+
+
+/*
+ * device_info[] is sorted so we can use binary search
+ */
+static struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev)
+{
+	int min = 0,
+	    max = sizeof(dev_info)/sizeof(dev_info[0]) - 1;
+
+	for ( ; ; )
+	{
+	    int i = (min + max) >> 1;
+	    long order;
+
+	    order = dev_info[i].vendor - (long) vendor;
+	    if (!order)
+		order = dev_info[i].device - (long) dev;
+	
+	    if (order < 0)
+	    {
+		    min = i + 1;
+		    if ( min > max )
+		       return 0;
+		    continue;
+	    }
+
+	    if (order > 0)
+	    {
+		    max = i - 1;
+		    if ( min > max )
+		       return 0;
+		    continue;
+	    }
+
+	    return & dev_info[ i ];
+	}
+}
+
+static const char *pci_strclass (unsigned int class)
+{
+	switch (class >> 8) {
+	      case PCI_CLASS_NOT_DEFINED:		return "Non-VGA device";
+	      case PCI_CLASS_NOT_DEFINED_VGA:		return "VGA compatible device";
+
+	      case PCI_CLASS_STORAGE_SCSI:		return "SCSI storage controller";
+	      case PCI_CLASS_STORAGE_IDE:		return "IDE interface";
+	      case PCI_CLASS_STORAGE_FLOPPY:		return "Floppy disk controller";
+	      case PCI_CLASS_STORAGE_IPI:		return "IPI bus controller";
+	      case PCI_CLASS_STORAGE_RAID:		return "RAID bus controller";
+	      case PCI_CLASS_STORAGE_OTHER:		return "Unknown mass storage controller";
+
+	      case PCI_CLASS_NETWORK_ETHERNET:		return "Ethernet controller";
+	      case PCI_CLASS_NETWORK_TOKEN_RING:	return "Token ring network controller";
+	      case PCI_CLASS_NETWORK_FDDI:		return "FDDI network controller";
+	      case PCI_CLASS_NETWORK_ATM:		return "ATM network controller";
+	      case PCI_CLASS_NETWORK_OTHER:		return "Network controller";
+
+	      case PCI_CLASS_DISPLAY_VGA:		return "VGA compatible controller";
+	      case PCI_CLASS_DISPLAY_XGA:		return "XGA compatible controller";
+	      case PCI_CLASS_DISPLAY_OTHER:		return "Display controller";
+
+	      case PCI_CLASS_MULTIMEDIA_VIDEO:		return "Multimedia video controller";
+	      case PCI_CLASS_MULTIMEDIA_AUDIO:		return "Multimedia audio controller";
+	      case PCI_CLASS_MULTIMEDIA_OTHER:		return "Multimedia controller";
+
+	      case PCI_CLASS_MEMORY_RAM:		return "RAM memory";
+	      case PCI_CLASS_MEMORY_FLASH:		return "FLASH memory";
+	      case PCI_CLASS_MEMORY_OTHER:		return "Memory";
+
+	      case PCI_CLASS_BRIDGE_HOST:		return "Host bridge";
+	      case PCI_CLASS_BRIDGE_ISA:		return "ISA bridge";
+	      case PCI_CLASS_BRIDGE_EISA:		return "EISA bridge";
+	      case PCI_CLASS_BRIDGE_MC:			return "MicroChannel bridge";
+	      case PCI_CLASS_BRIDGE_PCI:		return "PCI bridge";
+	      case PCI_CLASS_BRIDGE_PCMCIA:		return "PCMCIA bridge";
+	      case PCI_CLASS_BRIDGE_NUBUS:		return "NuBus bridge";
+	      case PCI_CLASS_BRIDGE_CARDBUS:		return "CardBus bridge";
+	      case PCI_CLASS_BRIDGE_OTHER:		return "Bridge";
+
+	      case PCI_CLASS_COMMUNICATION_SERIAL:	return "Serial controller";
+	      case PCI_CLASS_COMMUNICATION_PARALLEL:	return "Parallel controller";
+	      case PCI_CLASS_COMMUNICATION_OTHER:	return "Communication controller";
+
+	      case PCI_CLASS_SYSTEM_PIC:		return "PIC";
+	      case PCI_CLASS_SYSTEM_DMA:		return "DMA controller";
+	      case PCI_CLASS_SYSTEM_TIMER:		return "Timer";
+	      case PCI_CLASS_SYSTEM_RTC:		return "RTC";
+	      case PCI_CLASS_SYSTEM_OTHER:		return "System peripheral";
+
+	      case PCI_CLASS_INPUT_KEYBOARD:		return "Keyboard controller";
+	      case PCI_CLASS_INPUT_PEN:			return "Digitizer Pen";
+	      case PCI_CLASS_INPUT_MOUSE:		return "Mouse controller";
+	      case PCI_CLASS_INPUT_OTHER:		return "Input device controller";
+
+	      case PCI_CLASS_DOCKING_GENERIC:		return "Generic Docking Station";
+	      case PCI_CLASS_DOCKING_OTHER:		return "Docking Station";
+
+	      case PCI_CLASS_PROCESSOR_386:		return "386";
+	      case PCI_CLASS_PROCESSOR_486:		return "486";
+	      case PCI_CLASS_PROCESSOR_PENTIUM:		return "Pentium";
+	      case PCI_CLASS_PROCESSOR_ALPHA:		return "Alpha";
+	      case PCI_CLASS_PROCESSOR_POWERPC:		return "Power PC";
+	      case PCI_CLASS_PROCESSOR_CO:		return "Co-processor";
+
+	      case PCI_CLASS_SERIAL_FIREWIRE:		return "FireWire (IEEE 1394)";
+	      case PCI_CLASS_SERIAL_ACCESS:		return "ACCESS Bus";
+	      case PCI_CLASS_SERIAL_SSA:		return "SSA";
+	      case PCI_CLASS_SERIAL_USB:		return "USB Controller";
+	      case PCI_CLASS_SERIAL_FIBER:		return "Fiber Channel";
+
+	      default:					return "Unknown class";
+	}
+}
+
+
+static const char *pci_strvendor(unsigned int vendor)
+{
+	switch (vendor) {
+	      case PCI_VENDOR_ID_COMPAQ:	return "Compaq";
+	      case PCI_VENDOR_ID_NCR:		return "NCR";
+	      case PCI_VENDOR_ID_ATI:		return "ATI";
+	      case PCI_VENDOR_ID_VLSI:		return "VLSI";
+	      case PCI_VENDOR_ID_ADL:		return "Avance Logic";
+	      case PCI_VENDOR_ID_NS:		return "NS";
+	      case PCI_VENDOR_ID_TSENG:		return "Tseng'Lab";
+	      case PCI_VENDOR_ID_WEITEK:	return "Weitek";
+	      case PCI_VENDOR_ID_DEC:		return "DEC";
+	      case PCI_VENDOR_ID_CIRRUS:	return "Cirrus Logic";
+	      case PCI_VENDOR_ID_IBM:		return "IBM";
+	      case PCI_VENDOR_ID_WD:		return "Western Digital";
+	      case PCI_VENDOR_ID_AMD:		return "AMD";
+	      case PCI_VENDOR_ID_TRIDENT:	return "Trident";
+	      case PCI_VENDOR_ID_AI:		return "Acer Incorporated";
+	      case PCI_VENDOR_ID_MATROX:	return "Matrox";
+	      case PCI_VENDOR_ID_CT:		return "Chips & Technologies";
+	      case PCI_VENDOR_ID_MIRO:		return "Miro";
+	      case PCI_VENDOR_ID_NEC:		return "NEC";
+	      case PCI_VENDOR_ID_FD:		return "Future Domain";
+	      case PCI_VENDOR_ID_SI:		return "Silicon Integrated Systems";
+	      case PCI_VENDOR_ID_HP:		return "Hewlett Packard";
+	      case PCI_VENDOR_ID_PCTECH:	return "PCTECH";
+	      case PCI_VENDOR_ID_DPT:		return "DPT";
+	      case PCI_VENDOR_ID_OPTI:		return "OPTi";
+	      case PCI_VENDOR_ID_SGS:		return "SGS Thomson";
+	      case PCI_VENDOR_ID_BUSLOGIC:	return "BusLogic";
+	      case PCI_VENDOR_ID_TI:		return "Texas Instruments";
+	      case PCI_VENDOR_ID_OAK: 		return "OAK";
+	      case PCI_VENDOR_ID_WINBOND2:	return "Winbond";
+	      case PCI_VENDOR_ID_MOTOROLA:	return "Motorola";
+	      case PCI_VENDOR_ID_PROMISE:	return "Promise Technology";
+	      case PCI_VENDOR_ID_N9:		return "Number Nine";
+	      case PCI_VENDOR_ID_UMC:		return "UMC";
+	      case PCI_VENDOR_ID_X:		return "X TECHNOLOGY";
+	      case PCI_VENDOR_ID_PICOP:		return "PicoPower";
+	      case PCI_VENDOR_ID_APPLE:		return "Apple";
+	      case PCI_VENDOR_ID_NEXGEN:	return "Nexgen";
+	      case PCI_VENDOR_ID_QLOGIC:	return "Q Logic";
+	      case PCI_VENDOR_ID_CYRIX:		return "Cyrix";
+	      case PCI_VENDOR_ID_LEADTEK:	return "Leadtek Research";
+	      case PCI_VENDOR_ID_CONTAQ:	return "Contaq";
+	      case PCI_VENDOR_ID_FOREX:		return "Forex";
+	      case PCI_VENDOR_ID_OLICOM:	return "Olicom";
+	      case PCI_VENDOR_ID_SUN:		return "Sun Microsystems";
+	      case PCI_VENDOR_ID_CMD:		return "CMD";
+	      case PCI_VENDOR_ID_VISION:	return "Vision";
+	      case PCI_VENDOR_ID_BROOKTREE:	return "Brooktree";
+	      case PCI_VENDOR_ID_SIERRA:	return "Sierra";
+	      case PCI_VENDOR_ID_ACC:		return "ACC MICROELECTRONICS";
+	      case PCI_VENDOR_ID_WINBOND:	return "Winbond";
+	      case PCI_VENDOR_ID_DATABOOK:	return "Databook";
+	      case PCI_VENDOR_ID_3COM:		return "3Com";
+	      case PCI_VENDOR_ID_SMC:		return "SMC";
+	      case PCI_VENDOR_ID_AL:		return "Acer Labs";
+	      case PCI_VENDOR_ID_MITSUBISHI:	return "Mitsubishi";
+	      case PCI_VENDOR_ID_SURECOM:	return "Surecom";
+	      case PCI_VENDOR_ID_NEOMAGIC:	return "Neomagic";
+	      case PCI_VENDOR_ID_ASP:		return "Advanced System Products";
+	      case PCI_VENDOR_ID_CERN:		return "CERN";
+	      case PCI_VENDOR_ID_NVIDIA:	return "NVidia";
+	      case PCI_VENDOR_ID_IMS:		return "IMS";
+	      case PCI_VENDOR_ID_TEKRAM2:	return "Tekram";
+	      case PCI_VENDOR_ID_TUNDRA:	return "Tundra";
+	      case PCI_VENDOR_ID_AMCC:		return "AMCC";
+	      case PCI_VENDOR_ID_INTERG:	return "Intergraphics";
+	      case PCI_VENDOR_ID_REALTEK:	return "Realtek";
+	      case PCI_VENDOR_ID_TRUEVISION:	return "Truevision";
+	      case PCI_VENDOR_ID_INIT:		return "Initio Corp";
+	      case PCI_VENDOR_ID_VIA:		return "VIA Technologies";
+	      case PCI_VENDOR_ID_VORTEX:	return "VORTEX";
+	      case PCI_VENDOR_ID_EF:		return "Efficient Networks";
+	      case PCI_VENDOR_ID_FORE:		return "Fore Systems";
+	      case PCI_VENDOR_ID_IMAGINGTECH:	return "Imaging Technology";
+	      case PCI_VENDOR_ID_PHILIPS:	return "Philips";
+	      case PCI_VENDOR_ID_PLX:		return "PLX";
+	      case PCI_VENDOR_ID_ALLIANCE:	return "Alliance";
+	      case PCI_VENDOR_ID_VMIC:		return "VMIC";
+	      case PCI_VENDOR_ID_DIGI:		return "Digi Intl.";
+	      case PCI_VENDOR_ID_MUTECH:	return "Mutech";
+	      case PCI_VENDOR_ID_RENDITION:	return "Rendition";
+	      case PCI_VENDOR_ID_TOSHIBA:	return "Toshiba";
+	      case PCI_VENDOR_ID_RICOH:		return "Ricoh";
+	      case PCI_VENDOR_ID_ZEITNET:	return "ZeitNet";
+	      case PCI_VENDOR_ID_OMEGA:		return "Omega Micro";
+	      case PCI_VENDOR_ID_LITEON:	return "LiteOn";
+	      case PCI_VENDOR_ID_NP:		return "Network Peripherals";
+	      case PCI_VENDOR_ID_SPECIALIX:	return "Specialix";
+	      case PCI_VENDOR_ID_AURAVISION:	return "Auravision";
+	      case PCI_VENDOR_ID_IKON:		return "Ikon";
+	      case PCI_VENDOR_ID_ZORAN:		return "Zoran";
+	      case PCI_VENDOR_ID_COMPEX:	return "Compex";
+	      case PCI_VENDOR_ID_RP:		return "Comtrol";
+	      case PCI_VENDOR_ID_CYCLADES:	return "Cyclades";
+	      case PCI_VENDOR_ID_3DFX:		return "3Dfx";
+	      case PCI_VENDOR_ID_STALLION:	return "Stallion Technologies";
+	      case PCI_VENDOR_ID_SIGMADES:	return "Sigma Designs";
+	      case PCI_VENDOR_ID_OPTIBASE:	return "Optibase";
+	      case PCI_VENDOR_ID_ENSONIQ:	return "Ensoniq";
+	      case PCI_VENDOR_ID_PICTUREL:	return "Picture Elements";
+	      case PCI_VENDOR_ID_NVIDIA_SGS:	return "NVidia/SGS Thomson";
+	      case PCI_VENDOR_ID_SYMPHONY:	return "Symphony";
+	      case PCI_VENDOR_ID_TEKRAM:	return "Tekram";
+	      case PCI_VENDOR_ID_3DLABS:	return "3Dlabs";
+	      case PCI_VENDOR_ID_AVANCE:	return "Avance";
+	      case PCI_VENDOR_ID_NETVIN:	return "NetVin";
+	      case PCI_VENDOR_ID_S3:		return "S3 Inc.";
+	      case PCI_VENDOR_ID_INTEL:		return "Intel";
+	      case PCI_VENDOR_ID_KTI:		return "KTI";
+	      case PCI_VENDOR_ID_ADAPTEC:	return "Adaptec";
+	      case PCI_VENDOR_ID_ATRONICS:	return "Atronics";
+	      case PCI_VENDOR_ID_ARK:		return "ARK Logic";
+	      default:				return "Unknown vendor";
+	}
+}
+
+
+static const char *pci_strdev(unsigned int vendor, unsigned int device)
+{
+	struct pci_dev_info *info;
+
+	info = 	pci_lookup_dev(vendor, device);
+	return info ? info->name : "Unknown device";
+}
+
+
+/*
+ * Convert some of the configuration space registers of the device at
+ * address (bus,devfn) into a string (possibly several lines each).
+ * The configuration string is stored starting at buf[len].  If the
+ * string would exceed the size of the buffer (SIZE), 0 is returned.
+ */
+static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
+{
+	unsigned long base;
+	unsigned int l, class_rev, bus, devfn;
+	unsigned short vendor, device, status;
+	unsigned char bist, latency, min_gnt, max_lat;
+	int reg, len = 0;
+	const char *str;
+
+	bus   = dev->bus->number;
+	devfn = dev->devfn;
+
+	pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev);
+	pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor);
+	pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device);
+	pcibios_read_config_word (bus, devfn, PCI_STATUS, &status);
+	pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist);
+	pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency);
+	pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt);
+	pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat);
+	if (len + 80 > size) {
+		return -1;
+	}
+	len += sprintf(buf + len, "  Bus %2d, device %3d, function %2d:\n",
+		       bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+	if (len + 80 > size) {
+		return -1;
+	}
+	len += sprintf(buf + len, "    %s: %s %s (rev %d).\n      ",
+		       pci_strclass(class_rev >> 8), pci_strvendor(vendor),
+		       pci_strdev(vendor, device), class_rev & 0xff);
+
+	if (!pci_lookup_dev(vendor, device)) {
+		len += sprintf(buf + len,
+			       "Vendor id=%x. Device id=%x.\n      ",
+			       vendor, device);
+	}
+
+	str = 0;	/* to keep gcc shut... */
+	switch (status & PCI_STATUS_DEVSEL_MASK) {
+	      case PCI_STATUS_DEVSEL_FAST:   str = "Fast devsel.  "; break;
+	      case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel.  "; break;
+	      case PCI_STATUS_DEVSEL_SLOW:   str = "Slow devsel.  "; break;
+	}
+	if (len + strlen(str) > size) {
+		return -1;
+	}
+	len += sprintf(buf + len, str);
+
+	if (status & PCI_STATUS_FAST_BACK) {
+#		define fast_b2b_capable	"Fast back-to-back capable.  "
+		if (len + strlen(fast_b2b_capable) > size) {
+			return -1;
+		}
+		len += sprintf(buf + len, fast_b2b_capable);
+#		undef fast_b2b_capable
+	}
+
+	if (bist & PCI_BIST_CAPABLE) {
+#		define BIST_capable	"BIST capable.  "
+		if (len + strlen(BIST_capable) > size) {
+			return -1;
+		}
+		len += sprintf(buf + len, BIST_capable);
+#		undef BIST_capable
+	}
+
+	if (dev->irq) {
+		if (len + 40 > size) {
+			return -1;
+		}
+		len += sprintf(buf + len, "IRQ %x.  ", dev->irq);
+	}
+
+	if (dev->master) {
+		if (len + 80 > size) {
+			return -1;
+		}
+		len += sprintf(buf + len, "Master Capable.  ");
+		if (latency)
+		  len += sprintf(buf + len, "Latency=%d.  ", latency);
+		else
+		  len += sprintf(buf + len, "No bursts.  ");
+		if (min_gnt)
+		  len += sprintf(buf + len, "Min Gnt=%d.", min_gnt);
+		if (max_lat)
+		  len += sprintf(buf + len, "Max Lat=%d.", max_lat);
+	}
+
+	for (reg = 0; reg < 6; reg++) {
+		if (len + 40 > size) {
+			return -1;
+		}
+		pcibios_read_config_dword(bus, devfn,
+				PCI_BASE_ADDRESS_0 + (reg << 2), &l);
+		if (l == 0xffffffff)
+			base = 0;
+		else
+			base = l;
+		if (!base)
+			continue;
+
+		if (base & PCI_BASE_ADDRESS_SPACE_IO) {
+			len += sprintf(buf + len,
+				       "\n      I/O at 0x%lx [0x%lx].",
+				       base & PCI_BASE_ADDRESS_IO_MASK,
+				       dev->base_address[reg]);
+		} else {
+			const char *pref, *type = "unknown";
+
+			if (base & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+				pref = "P";
+			} else {
+				pref = "Non-p";
+			}
+			switch (base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+			      case PCI_BASE_ADDRESS_MEM_TYPE_32:
+				type = "32 bit"; break;
+			      case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+				type = "20 bit"; break;
+			      case PCI_BASE_ADDRESS_MEM_TYPE_64:
+				type = "64 bit";
+				/* read top 32 bit address of base addr: */
+				reg += 4;
+				pcibios_read_config_dword(bus, devfn, reg, &l);
+				base |= ((u64) l) << 32;
+				break;
+			}
+			len += sprintf(buf + len,
+				       "\n      %srefetchable %s memory at "
+				       "0x%lx [0x%lx].", pref, type,
+				       base & PCI_BASE_ADDRESS_MEM_MASK,
+				       dev->base_address[reg]);
+		}
+	}
+
+	len += sprintf(buf + len, "\n");
+	return len;
+}
+
+
+/*
+ * Return list of PCI devices as a character string for /proc/pci.
+ * BUF is a buffer that is PAGE_SIZE bytes long.
+ */
+int get_pci_list(char *buf)
+{
+	int nprinted, len, size;
+	struct pci_dev *dev;
+	static int complained = 0;
+#	define MSG "\nwarning: page-size limit reached!\n"
+
+	if (!complained) {
+		complained++;
+		printk(KERN_INFO "%s uses obsolete /proc/pci interface\n",
+			current->comm);
+	}
+
+	/* reserve same for truncation warning message: */
+	size  = PAGE_SIZE - (strlen(MSG) + 1);
+	len   = sprintf(buf, "PCI devices found:\n");
+
+	for (dev = pci_devices; dev; dev = dev->next) {
+		nprinted = sprint_dev_config(dev, buf + len, size - len);
+		if (nprinted < 0) {
+			return len + sprintf(buf + len, MSG);
+		}
+		len += nprinted;
+	}
+	return len;
+}
+
+#endif
diff -u --recursive --new-file v2.1.81/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.81/linux/drivers/pci/pci.c	Tue Dec 23 14:37:32 1997
+++ linux/drivers/pci/pci.c	Mon Jan 26 11:43:18 1998
@@ -1,13 +1,13 @@
 /*
- * $Id: pci.c,v 1.51 1997/12/03 06:18:11 davem Exp $
+ *	$Id: pci.c,v 1.55 1997/12/27 12:17:54 mj Exp $
  *
- * PCI services that are built on top of the BIOS32 service.
+ *	PCI services that are built on top of the BIOS32 service.
  *
- * Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter,
+ *	Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter,
  *	David Mosberger-Tang, Martin Mares
  */
+
 #include <linux/config.h>
-#include <linux/ptrace.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/bios32.h>
@@ -22,667 +22,18 @@
 
 #undef DEBUG
 
-#define DEVICE(vid,did,name) \
-  {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##did, (name)}
-
 /*
- * Sorted in ascending order by vendor and device.
- * Use binary search for lookup. If you add a device make sure
- * it is sequential by both vendor and device id.
- */
-struct pci_dev_info dev_info[] = {
-	DEVICE( COMPAQ,		COMPAQ_1280,	"QVision 1280/p"),
-	DEVICE( COMPAQ,		COMPAQ_SMART2P,	"Smart-2/P RAID Controller"),
-	DEVICE( COMPAQ,		COMPAQ_NETEL100,"Netelligent 10/100"),
-	DEVICE( COMPAQ,		COMPAQ_NETEL10,	"Netelligent 10"),
-	DEVICE( COMPAQ,		COMPAQ_NETFLEX3I,"NetFlex 3"),
-	DEVICE( COMPAQ,		COMPAQ_NETEL100D,"Netelligent 10/100 Dual"),
-	DEVICE( COMPAQ,		COMPAQ_NETEL100PI,"Netelligent 10/100 ProLiant"),
-	DEVICE( COMPAQ,		COMPAQ_NETEL100I,"Netelligent 10/100 Integrated"),
-	DEVICE( COMPAQ,		COMPAQ_THUNDER,	"ThunderLAN"),
-	DEVICE( COMPAQ,		COMPAQ_NETFLEX3B,"NetFlex 3 BNC"),
-	DEVICE( NCR,		NCR_53C810,	"53c810"),
-	DEVICE( NCR,		NCR_53C820,	"53c820"),
-	DEVICE( NCR,		NCR_53C825,	"53c825"),
-	DEVICE( NCR,		NCR_53C815,	"53c815"),
-	DEVICE( NCR,		NCR_53C860,	"53c860"),
-	DEVICE( NCR,		NCR_53C896,	"53c896"),
-	DEVICE( NCR,		NCR_53C895,	"53c895"),
-	DEVICE( NCR,		NCR_53C885,	"53c885"),
-	DEVICE( NCR,		NCR_53C875,	"53c875"),
-	DEVICE( NCR,		NCR_53C875J,	"53c875J"),
-	DEVICE( ATI,		ATI_68800,      "68800AX"),
-	DEVICE( ATI,		ATI_215CT222,   "215CT222"),
-	DEVICE( ATI,		ATI_210888CX,   "210888CX"),
-	DEVICE( ATI,		ATI_215GB,	"Mach64 GB"),
-	DEVICE( ATI,		ATI_215GD,	"Mach64 GD (Rage Pro)"),
-	DEVICE( ATI,		ATI_215GP,	"Mach64 GP (Rage Pro)"),
-	DEVICE( ATI,		ATI_215GT,	"Mach64 GT (Rage II)"),
-	DEVICE( ATI,		ATI_215GTB,	"Mach64 GT (Rage II)"),
-	DEVICE( ATI,		ATI_210888GX,   "210888GX"),
-	DEVICE( ATI,		ATI_264VT,	"Mach64 VT"),
-	DEVICE( VLSI,		VLSI_82C592,	"82C592-FC1"),
-	DEVICE( VLSI,		VLSI_82C593,	"82C593-FC1"),
-	DEVICE( VLSI,		VLSI_82C594,	"82C594-AFC2"),
-	DEVICE( VLSI,		VLSI_82C597,	"82C597-AFC2"),
-	DEVICE( VLSI,		VLSI_82C541,	"82C541 Lynx"),
-	DEVICE( VLSI,		VLSI_82C543,	"82C543 Lynx ISA"),
-	DEVICE( VLSI,		VLSI_VAS96011,	"VAS96011 (Golden Gate II)"),
-	DEVICE( ADL,		ADL_2301,	"2301"),
-	DEVICE( NS,		NS_87415,	"87415"),
-	DEVICE( NS,		NS_87410,	"87410"),
-	DEVICE( TSENG,		TSENG_W32P_2,	"ET4000W32P"),
-	DEVICE( TSENG,		TSENG_W32P_b,	"ET4000W32P rev B"),
-	DEVICE( TSENG,		TSENG_W32P_c,	"ET4000W32P rev C"),
-	DEVICE( TSENG,		TSENG_W32P_d,	"ET4000W32P rev D"),
-	DEVICE( TSENG,		TSENG_ET6000,	"ET6000"),
-	DEVICE( WEITEK,		WEITEK_P9000,	"P9000"),
-	DEVICE( WEITEK,		WEITEK_P9100,	"P9100"),
-	DEVICE( DEC,		DEC_BRD,	"DC21050"),
-	DEVICE( DEC,		DEC_TULIP,	"DC21040"),
-	DEVICE( DEC,		DEC_TGA,	"TGA"),
-	DEVICE( DEC,		DEC_TULIP_FAST,	"DC21140"),
-	DEVICE( DEC,		DEC_TGA2,	"TGA2"),
-	DEVICE( DEC,		DEC_FDDI,	"DEFPA"),
-	DEVICE( DEC,		DEC_TULIP_PLUS,	"DC21041"),
-	DEVICE( DEC,		DEC_21142,	"DC21142"),
-	DEVICE( DEC,		DEC_21052,	"DC21052"),
-	DEVICE( DEC,		DEC_21152,	"DC21152"),
-	DEVICE( CIRRUS,		CIRRUS_7548,	"GD 7548"),
-	DEVICE( CIRRUS,		CIRRUS_5430,	"GD 5430"),
-	DEVICE( CIRRUS,		CIRRUS_5434_4,	"GD 5434"),
-	DEVICE( CIRRUS,		CIRRUS_5434_8,	"GD 5434"),
-	DEVICE( CIRRUS,		CIRRUS_5436,	"GD 5436"),
-	DEVICE( CIRRUS,		CIRRUS_5446,	"GD 5446"),
-	DEVICE( CIRRUS,		CIRRUS_5480,	"GD 5480"),
-	DEVICE( CIRRUS,		CIRRUS_5464,	"GD 5464"),
-	DEVICE( CIRRUS,		CIRRUS_5465,	"GD 5465"),
-	DEVICE( CIRRUS,		CIRRUS_6729,	"CL 6729"),
-	DEVICE( CIRRUS,		CIRRUS_6832,	"PD 6832"),
-	DEVICE( CIRRUS,		CIRRUS_7542,	"CL 7542"),
-	DEVICE( CIRRUS,		CIRRUS_7543,	"CL 7543"),
-	DEVICE( CIRRUS,		CIRRUS_7541,	"CL 7541"),
-	DEVICE( IBM,		IBM_FIRE_CORAL,	"Fire Coral"),
-	DEVICE( IBM,		IBM_TR,		"Token Ring"),
-	DEVICE( IBM,		IBM_82G2675,	"82G2675"),
-	DEVICE( IBM,		IBM_82351,	"82351"),
-	DEVICE( WD,		WD_7197,	"WD 7197"),
-	DEVICE( AMD,		AMD_LANCE,	"79C970"),
-	DEVICE( AMD,		AMD_SCSI,	"53C974"),
-	DEVICE( TRIDENT,	TRIDENT_9420,	"TG 9420"),
-	DEVICE( TRIDENT,	TRIDENT_9440,	"TG 9440"),
-	DEVICE( TRIDENT,	TRIDENT_9660,	"TG 9660 / Cyber9385"),
-	DEVICE( TRIDENT,	TRIDENT_9750,	"Image 975"),
-	DEVICE( AI,		AI_M1435,	"M1435"),
-	DEVICE( MATROX,		MATROX_MGA_2,	"Atlas PX2085"),
-	DEVICE( MATROX,		MATROX_MIL,	"Millennium"),
-	DEVICE( MATROX,		MATROX_MYS,	"Mystique"),
-	DEVICE( MATROX,		MATROX_MIL_2,	"Millennium II"),
-	DEVICE( MATROX,		MATROX_MGA_IMP,	"MGA Impression"),
-	DEVICE( CT,		CT_65545,	"65545"),
-	DEVICE( CT,		CT_65548,	"65548"),
-	DEVICE(	CT,		CT_65550,	"65550"),
-	DEVICE( CT,		CT_65554,	"65554"),
-	DEVICE( MIRO,		MIRO_36050,	"ZR36050"),
-	DEVICE( NEC,		NEC_PCX2,	"PowerVR PCX2"),
-	DEVICE( FD,		FD_36C70,	"TMC-18C30"),
-	DEVICE( SI,		SI_6201,	"6201"),
-	DEVICE( SI,		SI_6202,	"6202"),
-	DEVICE( SI,		SI_503,		"85C503"),
-	DEVICE( SI,		SI_6205,	"6205"),
-	DEVICE( SI,		SI_501,		"85C501"),
-	DEVICE( SI,		SI_496,		"85C496"),
-	DEVICE( SI,		SI_601,		"85C601"),
-	DEVICE( SI,		SI_5107,	"5107"),
-	DEVICE( SI,		SI_5511,		"85C5511"),
-	DEVICE( SI,		SI_5513,		"85C5513"),
-	DEVICE( SI,		SI_5571,	"5571"),
-	DEVICE( SI,		SI_5597,	"5597"),
-	DEVICE( SI,		SI_7001,	"7001"),
-	DEVICE( HP,		HP_J2585A,	"J2585A"),
-	DEVICE( HP,		HP_J2585B,	"J2585B (Lassen)"),
-	DEVICE( PCTECH,		PCTECH_RZ1000,  "RZ1000 (buggy)"),
-	DEVICE( PCTECH,		PCTECH_RZ1001,  "RZ1001 (buggy?)"),
-	DEVICE( DPT,		DPT,		"SmartCache/Raid"),
-	DEVICE( OPTI,		OPTI_92C178,	"92C178"),
-	DEVICE( OPTI,		OPTI_82C557,	"82C557 Viper-M"),
-	DEVICE( OPTI,		OPTI_82C558,	"82C558 Viper-M ISA+IDE"),
-	DEVICE( OPTI,		OPTI_82C621,	"82C621"),
-	DEVICE( OPTI,		OPTI_82C700,	"82C700"),
-	DEVICE( OPTI,		OPTI_82C701,	"82C701 FireStar Plus"),
-	DEVICE( OPTI,		OPTI_82C814,	"82C814 Firebridge 1"),
-	DEVICE( OPTI,		OPTI_82C822,	"82C822"),
-	DEVICE( SGS,		SGS_2000,	"STG 2000X"),
-	DEVICE( SGS,		SGS_1764,	"STG 1764X"),
-	DEVICE( BUSLOGIC,	BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC"),
-	DEVICE( BUSLOGIC,	BUSLOGIC_MULTIMASTER,    "MultiMaster"),
-	DEVICE( BUSLOGIC,	BUSLOGIC_FLASHPOINT,     "FlashPoint"),
-	DEVICE( TI,		TI_TVP4010,	"TVP4010 Permedia"),
-	DEVICE( TI,		TI_TVP4020,	"TVP4020 Permedia 2"),
-	DEVICE( TI,		TI_PCI1130,	"PCI1130"),
-	DEVICE( TI,		TI_PCI1131,	"PCI1131"),
-	DEVICE( OAK,		OAK_OTI107,	"OTI107"),
-	DEVICE( WINBOND2,	WINBOND2_89C940,"NE2000-PCI"),
-	DEVICE( MOTOROLA,	MOTOROLA_MPC105,"MPC105 Eagle"),
-	DEVICE( MOTOROLA,	MOTOROLA_MPC106,"MPC106 Grackle"),
-	DEVICE( MOTOROLA,	MOTOROLA_RAVEN,	"Raven"),
-	DEVICE( PROMISE,        PROMISE_20246,	"IDE UltraDMA/33"),
-	DEVICE( PROMISE,	PROMISE_5300,	"DC5030"),
-	DEVICE( N9,		N9_I128,	"Imagine 128"),
-	DEVICE( N9,		N9_I128_2,	"Imagine 128v2"),
-	DEVICE( UMC,		UMC_UM8673F,	"UM8673F"),
-	DEVICE( UMC,		UMC_UM8891A,	"UM8891A"),
-	DEVICE( UMC,		UMC_UM8886BF,	"UM8886BF"),
-	DEVICE( UMC,		UMC_UM8886A,	"UM8886A"),
-	DEVICE( UMC,		UMC_UM8881F,	"UM8881F"),
-	DEVICE( UMC,		UMC_UM8886F,	"UM8886F"),
-	DEVICE( UMC,		UMC_UM9017F,	"UM9017F"),
-	DEVICE( UMC,		UMC_UM8886N,	"UM8886N"),
-	DEVICE( UMC,		UMC_UM8891N,	"UM8891N"),
-	DEVICE( X,		X_AGX016,	"ITT AGX016"),
-	DEVICE( PICOP,		PICOP_PT86C52X,	"PT86C52x Vesuvius"),
-	DEVICE( APPLE,		APPLE_BANDIT,	"Bandit"),
-	DEVICE( APPLE,		APPLE_GC,	"Grand Central"),
-	DEVICE( APPLE,		APPLE_HYDRA,	"Hydra"),
-	DEVICE( NEXGEN,		NEXGEN_82C501,	"82C501"),
-	DEVICE( QLOGIC,		QLOGIC_ISP1020,	"ISP1020"),
-	DEVICE( QLOGIC,		QLOGIC_ISP1022,	"ISP1022"),
-	DEVICE( CYRIX,		CYRIX_5510,	"5510"),
-	DEVICE( CYRIX,		CYRIX_PCI_MASTER,"PCI Master"),
-	DEVICE( CYRIX,		CYRIX_5520,	"5520"),
-	DEVICE( CYRIX,		CYRIX_5530_LEGACY,"5530 Kahlua Legacy"),
-	DEVICE( CYRIX,		CYRIX_5530_SMI,	"5530 Kahlua SMI"),
-	DEVICE( CYRIX,		CYRIX_5530_IDE,	"5530 Kahlua IDE"),
-	DEVICE( CYRIX,		CYRIX_5530_AUDIO,"5530 Kahlua Audio"),
-	DEVICE( CYRIX,		CYRIX_5530_VIDEO,"5530 Kahlua Video"),
-	DEVICE( LEADTEK,	LEADTEK_805,	"S3 805"),
-	DEVICE( CONTAQ,		CONTAQ_82C599,	"82C599"),
-	DEVICE( OLICOM,		OLICOM_OC3136,	"OC-3136/3137"),
-	DEVICE( OLICOM,		OLICOM_OC2315,	"OC-2315"),
-	DEVICE( OLICOM,		OLICOM_OC2325,	"OC-2325"),
-	DEVICE( OLICOM,		OLICOM_OC2183,	"OC-2183/2185"),
-	DEVICE( OLICOM,		OLICOM_OC2326,	"OC-2326"),
-	DEVICE( OLICOM,		OLICOM_OC6151,	"OC-6151/6152"),
-	DEVICE( SUN,		SUN_EBUS,	"EBUS"),
-	DEVICE( SUN,		SUN_HAPPYMEAL,	"Happy Meal"),
-	DEVICE( SUN,		SUN_PBM,	"PCI Bus Module"),
-	DEVICE( CMD,		CMD_640,	"640 (buggy)"),
-	DEVICE( CMD,		CMD_643,	"643"),
-	DEVICE( CMD,		CMD_646,	"646"),
-	DEVICE( CMD,		CMD_670,	"670"),
-	DEVICE( VISION,		VISION_QD8500,	"QD-8500"),
-	DEVICE( VISION,		VISION_QD8580,	"QD-8580"),
-	DEVICE( BROOKTREE,	BROOKTREE_848,	"Bt848"),
-	DEVICE( SIERRA,		SIERRA_STB,	"STB Horizon 64"),
-	DEVICE( ACC,		ACC_2056,	"2056"),
-	DEVICE( WINBOND,	WINBOND_83769,	"W83769F"),
-	DEVICE( WINBOND,	WINBOND_82C105,	"SL82C105"),
-	DEVICE( WINBOND,	WINBOND_83C553,	"W83C553"),
-	DEVICE( DATABOOK,      	DATABOOK_87144,	"DB87144"),
-	DEVICE( 3COM,		3COM_3C590,	"3C590 10bT"),
-	DEVICE( 3COM,		3COM_3C595TX,	"3C595 100bTX"),
-	DEVICE( 3COM,		3COM_3C595T4,	"3C595 100bT4"),
-	DEVICE( 3COM,		3COM_3C595MII,	"3C595 100b-MII"),
-	DEVICE( 3COM,		3COM_3C900TPO,	"3C900 10bTPO"),
-	DEVICE( 3COM,		3COM_3C900COMBO,"3C900 10b Combo"),
-	DEVICE( 3COM,		3COM_3C905TX,	"3C905 100bTX"),
-	DEVICE( SMC,		SMC_EPIC100,	"9432 TX"),
-	DEVICE( AL,		AL_M1445,	"M1445"),
-	DEVICE( AL,		AL_M1449,	"M1449"),
-	DEVICE( AL,		AL_M1451,	"M1451"),
-	DEVICE( AL,		AL_M1461,	"M1461"),
-	DEVICE( AL,		AL_M1489,	"M1489"),
-	DEVICE( AL,		AL_M1511,	"M1511"),
-	DEVICE( AL,		AL_M1513,	"M1513"),
-	DEVICE( AL,		AL_M1521,	"M1521"),
-	DEVICE( AL,		AL_M1523,	"M1523"),
-	DEVICE( AL,		AL_M1531,	"M1531 Aladdin IV"),
-	DEVICE( AL,		AL_M1533,	"M1533 Aladdin IV"),
-	DEVICE( AL,		AL_M4803,	"M4803"),
-	DEVICE( AL,		AL_M5219,	"M5219"),
-	DEVICE( AL,		AL_M5229,	"M5229 TXpro"),
-	DEVICE( SURECOM,	SURECOM_NE34,	"NE-34PCI LAN"),
-	DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2070,     "Magicgraph NM2070"),
-	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
-	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV"),
-	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160"),
-	DEVICE( ASP,		ASP_ABP940,	"ABP940"),
-	DEVICE( ASP,		ASP_ABP940U,	"ABP940U"),
-	DEVICE( CERN,		CERN_SPSB_PMC,	"STAR/RD24 SCI-PCI (PMC)"),
-	DEVICE( CERN,		CERN_SPSB_PCI,	"STAR/RD24 SCI-PCI (PMC)"),
-	DEVICE( IMS,		IMS_8849,	"8849"),
-	DEVICE( TEKRAM2,	TEKRAM2_690c,	"DC690c"),
-	DEVICE( TUNDRA,		TUNDRA_CA91C042,"CA91C042 Universe"),
-	DEVICE( AMCC,		AMCC_MYRINET,	"Myrinet PCI (M2-PCI-32)"),
-	DEVICE( AMCC,		AMCC_S5933,	"S5933 PCI44"),
-	DEVICE( AMCC,		AMCC_S5933_HEPC3,"S5933 Traquair HEPC3"),
-	DEVICE( INTERG,		INTERG_1680,	"IGA-1680"),
-	DEVICE( INTERG,         INTERG_1682,    "IGA-1682"),
-	DEVICE( REALTEK,	REALTEK_8029,	"8029"),
-	DEVICE( REALTEK,	REALTEK_8129,	"8129"),
-	DEVICE( TRUEVISION,	TRUEVISION_T1000,"TARGA 1000"),
-	DEVICE( INIT,		INIT_320P,	"320 P"),
-	DEVICE( VIA,		VIA_82C505,	"VT 82C505"),
-	DEVICE( VIA,		VIA_82C561,	"VT 82C561"),
-	DEVICE( VIA,		VIA_82C586_1,	"VT 82C586 Apollo IDE"),
-	DEVICE( VIA,		VIA_82C576,	"VT 82C576 3V"),
-	DEVICE( VIA,		VIA_82C585,	"VT 82C585 Apollo VP1/VPX"),
-	DEVICE( VIA,		VIA_82C586_0,	"VT 82C586 Apollo ISA"),
-	DEVICE( VIA,		VIA_82C595,	"VT 82C595 Apollo VP2"),
-	DEVICE( VIA,		VIA_82C926,	"VT 82C926 Amazon"),
-	DEVICE( VIA,		VIA_82C416,	"VT 82C416MV"),
-	DEVICE( VIA,		VIA_82C595_97,	"VT 82C595 Apollo VP2/97"),
-	DEVICE( VIA,		VIA_82C586_2,	"VT 82C586 Apollo USB"),
-	DEVICE( VIA,		VIA_82C586_3,	"VT 82C586B Apollo ACPI"),
-	DEVICE( VORTEX,		VORTEX_GDT60x0,	"GDT 60x0"),
-	DEVICE( VORTEX,		VORTEX_GDT6000B,"GDT 6000b"),
-	DEVICE( VORTEX,		VORTEX_GDT6x10,	"GDT 6110/6510"),
-	DEVICE( VORTEX,		VORTEX_GDT6x20,	"GDT 6120/6520"),
-	DEVICE( VORTEX,		VORTEX_GDT6530,	"GDT 6530"),
-	DEVICE( VORTEX,		VORTEX_GDT6550,	"GDT 6550"),
-	DEVICE( VORTEX,		VORTEX_GDT6x17,	"GDT 6117/6517"),
-	DEVICE( VORTEX,		VORTEX_GDT6x27,	"GDT 6127/6527"),
-	DEVICE( VORTEX,		VORTEX_GDT6537,	"GDT 6537"),
-	DEVICE( VORTEX,		VORTEX_GDT6557,	"GDT 6557"),
-	DEVICE( VORTEX,		VORTEX_GDT6x15,	"GDT 6115/6515"),
-	DEVICE( VORTEX,		VORTEX_GDT6x25,	"GDT 6125/6525"),
-	DEVICE( VORTEX,		VORTEX_GDT6535,	"GDT 6535"),
-	DEVICE( VORTEX,		VORTEX_GDT6555,	"GDT 6555"),
-	DEVICE( VORTEX,		VORTEX_GDT6x17RP,"GDT 6117RP/6517RP"),
-	DEVICE( VORTEX,		VORTEX_GDT6x27RP,"GDT 6127RP/6527RP"),
-	DEVICE( VORTEX,		VORTEX_GDT6537RP,"GDT 6537RP"),
-	DEVICE( VORTEX,		VORTEX_GDT6557RP,"GDT 6557RP"),
-	DEVICE( VORTEX,		VORTEX_GDT6x11RP,"GDT 6111RP/6511RP"),
-	DEVICE( VORTEX,		VORTEX_GDT6x21RP,"GDT 6121RP/6521RP"),
-	DEVICE( VORTEX,		VORTEX_GDT6x17RP1,"GDT 6117RP1/6517RP1"),
-	DEVICE( VORTEX,		VORTEX_GDT6x27RP1,"GDT 6127RP1/6527RP1"),
-	DEVICE( VORTEX,		VORTEX_GDT6537RP1,"GDT 6537RP1"),
-	DEVICE( VORTEX,		VORTEX_GDT6557RP1,"GDT 6557RP1"),
-	DEVICE( VORTEX,		VORTEX_GDT6x11RP1,"GDT 6111RP1/6511RP1"),
-	DEVICE( VORTEX,		VORTEX_GDT6x21RP1,"GDT 6121RP1/6521RP1"),
-	DEVICE( VORTEX,		VORTEX_GDT6x17RP2,"GDT 6117RP2/6517RP2"),
-	DEVICE( VORTEX,		VORTEX_GDT6x27RP2,"GDT 6127RP2/6527RP2"),
-	DEVICE( VORTEX,		VORTEX_GDT6537RP2,"GDT 6537RP2"),
-	DEVICE( VORTEX,		VORTEX_GDT6557RP2,"GDT 6557RP2"),
-	DEVICE( VORTEX,		VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2"),
-	DEVICE( VORTEX,		VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2"),
-	DEVICE( EF,		EF_ATM_FPGA,		"155P-MF1 (FPGA)"),
-	DEVICE( EF,		EF_ATM_ASIC,	"155P-MF1 (ASIC)"),
-	DEVICE( FORE,		FORE_PCA200PC, "PCA-200PC"),
-	DEVICE( FORE,		FORE_PCA200E,	 "PCA-200E"),
-	DEVICE( IMAGINGTECH,	IMAGINGTECH_ICPCI, "MVC IC-PCI"),
-	DEVICE( PHILIPS,	PHILIPS_SAA7146,"SAA7146"),
-	DEVICE( PLX,		PLX_9060,	"PCI9060 i960 bridge"),
-	DEVICE( ALLIANCE,	ALLIANCE_PROMOTIO, "Promotion-6410"),
-	DEVICE( ALLIANCE,	ALLIANCE_PROVIDEO, "Provideo"),
-	DEVICE( ALLIANCE,	ALLIANCE_AT24,	"AT24"),
-	DEVICE( ALLIANCE,	ALLIANCE_AT3D,	"AT3D"),
-	DEVICE( VMIC,		VMIC_VME,	"VMIVME-7587"),
- 	DEVICE( DIGI,		DIGI_RIGHTSWITCH, "RightSwitch SE-6"),
-	DEVICE( MUTECH,		MUTECH_MV1000,	"MV-1000"),
-	DEVICE( RENDITION,	RENDITION_VERITE,"Verite 1000"),
-	DEVICE( RENDITION,	RENDITION_VERITE2100,"Verite 2100"),
-	DEVICE( TOSHIBA,	TOSHIBA_601,	"Laptop"),
-	DEVICE( RICOH,		RICOH_RL5C466,	"RL5C466"),
-	DEVICE( ZEITNET,	ZEITNET_1221,	"1221"),
-	DEVICE( ZEITNET,	ZEITNET_1225,	"1225"),
-	DEVICE( OMEGA,		OMEGA_82C092G,	"82C092G"),
-	DEVICE( LITEON,		LITEON_LNE100TX,"LNE100TX"),
-	DEVICE( NP,		NP_PCI_FDDI,	"NP-PCI"),       
-	DEVICE( SPECIALIX,	SPECIALIX_XIO,	"XIO/SIO host"),
-	DEVICE( SPECIALIX,	SPECIALIX_RIO,	"RIO host"),
-	DEVICE( AURAVISION,	AURAVISION_VXP524,"VXP524"),
-	DEVICE( IKON,		IKON_10115,	"10115 Greensheet"),
-	DEVICE( IKON,		IKON_10117,	"10117 Greensheet"),
-	DEVICE( ZORAN,		ZORAN_36057,	"ZR36057"),
-	DEVICE( ZORAN,		ZORAN_36120,	"ZR36120"),
-	DEVICE( COMPEX,		COMPEX_ENET100VG4, "Readylink ENET100-VG4"),
-	DEVICE( COMPEX,		COMPEX_RL2000,	"ReadyLink 2000"),
-	DEVICE( RP,             RP8OCTA,        "RocketPort 8 Oct"),
-	DEVICE( RP,             RP8INTF,        "RocketPort 8 Intf"),
-	DEVICE( RP,             RP16INTF,       "RocketPort 16 Intf"),
-	DEVICE( RP,             RP32INTF,       "RocketPort 32 Intf"),
-	DEVICE( CYCLADES,	CYCLOM_Y_Lo,	"Cyclom-Y below 1Mbyte"),
-	DEVICE( CYCLADES,	CYCLOM_Y_Hi,	"Cyclom-Y above 1Mbyte"),
-	DEVICE( CYCLADES,	CYCLOM_Z_Lo,	"Cyclom-Z below 1Mbyte"),
-	DEVICE( CYCLADES,	CYCLOM_Z_Hi,	"Cyclom-Z above 1Mbyte"),
-	DEVICE( 3DFX,		3DFX_VOODOO,	"Voodoo"),
-	DEVICE( STALLION,	STALLION_ECHPCI832,"EasyConnection 8/32"),
-	DEVICE( STALLION,	STALLION_ECHPCI864,"EasyConnection 8/64"),
-	DEVICE( STALLION,	STALLION_EIOPCI,"EasyIO"),
-	DEVICE( SIGMADES,	SIGMADES_6425,	"REALmagic64/GX"),
-	DEVICE( OPTIBASE,	OPTIBASE_FORGE,	"MPEG Forge"),
-	DEVICE( OPTIBASE,	OPTIBASE_FUSION,"MPEG Fusion"),
-	DEVICE( OPTIBASE,	OPTIBASE_VPLEX,	"VideoPlex"),
-	DEVICE( OPTIBASE,	OPTIBASE_VPLEXCC,"VideoPlex CC"),
-	DEVICE( OPTIBASE,	OPTIBASE_VQUEST,"VideoQuest"),
-	DEVICE( ENSONIQ,	ENSONIQ_AUDIOPCI,"AudioPCI"),
-	DEVICE( PICTUREL,	PICTUREL_PCIVST,"PCIVST"),
-	DEVICE( NVIDIA_SGS,	NVIDIA_SGS_RIVA128,	"Riva 128"),
-	DEVICE( SYMPHONY,	SYMPHONY_101,	"82C101"),
-	DEVICE( TEKRAM,		TEKRAM_DC290,	"DC-290"),
-	DEVICE( 3DLABS,		3DLABS_300SX,	"GLINT 300SX"),
-	DEVICE( 3DLABS,		3DLABS_500TX,	"GLINT 500TX"),
-	DEVICE( 3DLABS,		3DLABS_DELTA,	"GLINT Delta"),
-	DEVICE( 3DLABS,		3DLABS_PERMEDIA,"PERMEDIA"),
-	DEVICE( AVANCE,		AVANCE_ALG2064,	"ALG2064i"),
-	DEVICE( AVANCE,		AVANCE_2302,	"ALG-2302"),
-	DEVICE( NETVIN,		NETVIN_NV5000SC,"NV5000"),
-	DEVICE( S3,		S3_PLATO_PXS,	"PLATO/PX (system)"),
-	DEVICE( S3,		S3_ViRGE,	"ViRGE"),
-	DEVICE( S3,		S3_TRIO,	"Trio32/Trio64"),
-	DEVICE( S3,		S3_AURORA64VP,	"Aurora64V+"),
-	DEVICE( S3,		S3_TRIO64UVP,	"Trio64UV+"),
-	DEVICE( S3,		S3_ViRGE_VX,	"ViRGE/VX"),
-	DEVICE( S3,		S3_868,	"Vision 868"),
-	DEVICE( S3,		S3_928,		"Vision 928-P"),
-	DEVICE( S3,		S3_864_1,	"Vision 864-P"),
-	DEVICE( S3,		S3_864_2,	"Vision 864-P"),
-	DEVICE( S3,		S3_964_1,	"Vision 964-P"),
-	DEVICE( S3,		S3_964_2,	"Vision 964-P"),
-	DEVICE( S3,		S3_968,		"Vision 968"),
-	DEVICE( S3,		S3_TRIO64V2,	"Trio64V2/DX or /GX"),
-	DEVICE( S3,		S3_PLATO_PXG,	"PLATO/PX (graphics)"),
-	DEVICE( S3,		S3_ViRGE_DXGX,	"ViRGE/DX or /GX"),
-	DEVICE( S3,		S3_ViRGE_GX2,	"ViRGE/GX2"),
-	DEVICE( S3,		S3_ViRGE_MX,	"ViRGE/MX"),
-	DEVICE( S3,		S3_ViRGE_MXP,	"ViRGE/MX+"),
-	DEVICE( S3,		S3_ViRGE_MXPMV,	"ViRGE/MX+MV"),
-	DEVICE( INTEL,		INTEL_82375,	"82375EB"),
-	DEVICE( INTEL,		INTEL_82424,	"82424ZX Saturn"),
-	DEVICE( INTEL,		INTEL_82378,	"82378IB"),
-	DEVICE( INTEL,		INTEL_82430,	"82430ZX Aries"),
-	DEVICE( INTEL,		INTEL_82434,	"82434LX Mercury/Neptune"),
-	DEVICE( INTEL,		INTEL_82092AA_0,"82092AA PCMCIA bridge"),
-	DEVICE( INTEL,		INTEL_82092AA_1,"82092AA EIDE"),
-	DEVICE( INTEL,		INTEL_7116,	"SAA7116"),
-	DEVICE( INTEL,		INTEL_82596,	"82596"),
-	DEVICE( INTEL,		INTEL_82865,	"82865"),
-	DEVICE( INTEL,		INTEL_82557,	"82557"),
-	DEVICE( INTEL,		INTEL_82437,	"82437"),
-	DEVICE( INTEL,		INTEL_82371FB_0,"82371FB PIIX ISA"),
-	DEVICE( INTEL,		INTEL_82371FB_1,"82371FB PIIX IDE"),
-	DEVICE( INTEL,		INTEL_82371MX,	"430MX - 82371MX MPIIX"),
-	DEVICE( INTEL,		INTEL_82437MX,	"430MX - 82437MX MTSC"),
-	DEVICE( INTEL,		INTEL_82441,	"82441FX Natoma"),
-	DEVICE( INTEL,		INTEL_82439,	"82439HX Triton II"),
-	DEVICE(	INTEL,		INTEL_82371SB_0,"82371SB PIIX3 ISA"),
-	DEVICE(	INTEL,		INTEL_82371SB_1,"82371SB PIIX3 IDE"),
-	DEVICE( INTEL,		INTEL_82371SB_2,"82371SB PIIX3 USB"),
-	DEVICE( INTEL,		INTEL_82437VX,	"82437VX Triton II"),
-	DEVICE( INTEL,		INTEL_82439TX,	"82439TX"),
-	DEVICE( INTEL,		INTEL_82371AB_0,"82371AB PIIX4 ISA"),
-	DEVICE( INTEL,		INTEL_82371AB,	"82371AB PIIX4 IDE"),
-	DEVICE( INTEL,		INTEL_82371AB_2,"82371AB PIIX4 USB"),
-	DEVICE( INTEL,		INTEL_82371AB_3,"82371AB PIIX4 ACPI"),
-	DEVICE( INTEL,		INTEL_82443LX_0,"440LX - 82443LX PAC Host"),
-	DEVICE( INTEL,		INTEL_82443LX_1,"440LX - 82443LX PAC AGP"),
-	DEVICE( INTEL,		INTEL_P6,	"Orion P6"),
- 	DEVICE( INTEL,		INTEL_82450GX,	"82450GX Orion P6"),
-	DEVICE(	KTI,		KTI_ET32P2,	"ET32P2"),
-	DEVICE( ADAPTEC,	ADAPTEC_7850,	"AIC-7850"),
-	DEVICE( ADAPTEC,	ADAPTEC_7855,	"AIC-7855"),
-	DEVICE( ADAPTEC,	ADAPTEC_5800,	"AIC-5800"),
-	DEVICE( ADAPTEC,	ADAPTEC_7860,	"AIC-7860"),
-	DEVICE( ADAPTEC,	ADAPTEC_7861,	"AIC-7861"),
-	DEVICE( ADAPTEC,	ADAPTEC_7870,	"AIC-7870"),
-	DEVICE( ADAPTEC,	ADAPTEC_7871,	"AIC-7871"),
-	DEVICE( ADAPTEC,	ADAPTEC_7872,	"AIC-7872"),
-	DEVICE( ADAPTEC,	ADAPTEC_7873,	"AIC-7873"),
-	DEVICE( ADAPTEC,	ADAPTEC_7874,	"AIC-7874"),
-	DEVICE( ADAPTEC,	ADAPTEC_7895,	"AIC-7895U"),
-	DEVICE( ADAPTEC,	ADAPTEC_7880,	"AIC-7880U"),
-	DEVICE( ADAPTEC,	ADAPTEC_7881,	"AIC-7881U"),
-	DEVICE( ADAPTEC,	ADAPTEC_7882,	"AIC-7882U"),
-	DEVICE( ADAPTEC,	ADAPTEC_7883,	"AIC-7883U"),
-	DEVICE( ADAPTEC,	ADAPTEC_7884,	"AIC-7884U"),
-  	DEVICE( ATRONICS,	ATRONICS_2015,	"IDE-2015PL"),
-	DEVICE( ARK,		ARK_STING,	"Stingray"),
-	DEVICE( ARK,		ARK_STINGARK,	"Stingray ARK 2000PV"),
-	DEVICE( ARK,		ARK_2000MT,	"2000MT")
-};
-
-
-/*
- * device_info[] is sorted so we can use binary search
+ * pci_malloc() returns initialized memory of size SIZE.  Can be
+ * used only while pci_init() is active.
  */
-struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev)
-{
-	int min = 0,
-	    max = sizeof(dev_info)/sizeof(dev_info[0]) - 1;
-
-	for ( ; ; )
-	{
-	    int i = (min + max) >> 1;
-	    long order;
-
-	    order = dev_info[i].vendor - (long) vendor;
-	    if (!order)
-		order = dev_info[i].device - (long) dev;
-	
-	    if (order < 0)
-	    {
-		    min = i + 1;
-		    if ( min > max )
-		       return 0;
-		    continue;
-	    }
-
-	    if (order > 0)
-	    {
-		    max = i - 1;
-		    if ( min > max )
-		       return 0;
-		    continue;
-	    }
-
-	    return & dev_info[ i ];
-	}
-}
-
-const char *pci_strclass (unsigned int class)
-{
-	switch (class >> 8) {
-	      case PCI_CLASS_NOT_DEFINED:		return "Non-VGA device";
-	      case PCI_CLASS_NOT_DEFINED_VGA:		return "VGA compatible device";
-
-	      case PCI_CLASS_STORAGE_SCSI:		return "SCSI bus controller";
-	      case PCI_CLASS_STORAGE_IDE:		return "IDE controller";
-	      case PCI_CLASS_STORAGE_FLOPPY:		return "Floppy disk controller";
-	      case PCI_CLASS_STORAGE_IPI:		return "IPI bus controller";
-	      case PCI_CLASS_STORAGE_RAID:		return "RAID controller";
-	      case PCI_CLASS_STORAGE_OTHER:		return "Unknown mass storage controller";
-
-	      case PCI_CLASS_NETWORK_ETHERNET:		return "Ethernet controller";
-	      case PCI_CLASS_NETWORK_TOKEN_RING:	return "Token ring network controller";
-	      case PCI_CLASS_NETWORK_FDDI:		return "FDDI network controller";
-	      case PCI_CLASS_NETWORK_ATM:		return "ATM network controller";
-	      case PCI_CLASS_NETWORK_OTHER:		return "Network controller";
-
-	      case PCI_CLASS_DISPLAY_VGA:		return "VGA compatible controller";
-	      case PCI_CLASS_DISPLAY_XGA:		return "XGA compatible controller";
-	      case PCI_CLASS_DISPLAY_OTHER:		return "Display controller";
-
-	      case PCI_CLASS_MULTIMEDIA_VIDEO:		return "Multimedia video controller";
-	      case PCI_CLASS_MULTIMEDIA_AUDIO:		return "Multimedia audio controller";
-	      case PCI_CLASS_MULTIMEDIA_OTHER:		return "Multimedia controller";
-
-	      case PCI_CLASS_MEMORY_RAM:		return "RAM memory";
-	      case PCI_CLASS_MEMORY_FLASH:		return "FLASH memory";
-	      case PCI_CLASS_MEMORY_OTHER:		return "Memory";
-
-	      case PCI_CLASS_BRIDGE_HOST:		return "Host bridge";
-	      case PCI_CLASS_BRIDGE_ISA:		return "ISA bridge";
-	      case PCI_CLASS_BRIDGE_EISA:		return "EISA bridge";
-	      case PCI_CLASS_BRIDGE_MC:			return "MicroChannel bridge";
-	      case PCI_CLASS_BRIDGE_PCI:		return "PCI bridge";
-	      case PCI_CLASS_BRIDGE_PCMCIA:		return "PCMCIA bridge";
-	      case PCI_CLASS_BRIDGE_NUBUS:		return "NuBus bridge";
-	      case PCI_CLASS_BRIDGE_CARDBUS:		return "CardBus bridge";
-	      case PCI_CLASS_BRIDGE_OTHER:		return "Bridge";
-
-	      case PCI_CLASS_COMMUNICATION_SERIAL:	return "Serial controller";
-	      case PCI_CLASS_COMMUNICATION_PARALLEL:	return "Parallel controller";
-	      case PCI_CLASS_COMMUNICATION_OTHER:	return "Communication controller";
-
-	      case PCI_CLASS_SYSTEM_PIC:		return "PIC";
-	      case PCI_CLASS_SYSTEM_DMA:		return "DMA controller";
-	      case PCI_CLASS_SYSTEM_TIMER:		return "Timer";
-	      case PCI_CLASS_SYSTEM_RTC:		return "RTC";
-	      case PCI_CLASS_SYSTEM_OTHER:		return "System peripheral";
-
-	      case PCI_CLASS_INPUT_KEYBOARD:		return "Keyboard controller";
-	      case PCI_CLASS_INPUT_PEN:			return "Digitizer Pen";
-	      case PCI_CLASS_INPUT_MOUSE:		return "Mouse controller";
-	      case PCI_CLASS_INPUT_OTHER:		return "Input device controller";
-
-	      case PCI_CLASS_DOCKING_GENERIC:		return "Generic Docking Station";
-	      case PCI_CLASS_DOCKING_OTHER:		return "Docking Station";
-
-	      case PCI_CLASS_PROCESSOR_386:		return "386";
-	      case PCI_CLASS_PROCESSOR_486:		return "486";
-	      case PCI_CLASS_PROCESSOR_PENTIUM:		return "Pentium";
-	      case PCI_CLASS_PROCESSOR_ALPHA:		return "Alpha";
-	      case PCI_CLASS_PROCESSOR_POWERPC:		return "Power PC";
-	      case PCI_CLASS_PROCESSOR_CO:		return "Co-processor";
-
-	      case PCI_CLASS_SERIAL_FIREWIRE:		return "FireWire (IEEE 1394)";
-	      case PCI_CLASS_SERIAL_ACCESS:		return "ACCESS Bus";
-	      case PCI_CLASS_SERIAL_SSA:		return "SSA";
-	      case PCI_CLASS_SERIAL_USB:		return "USB Controller";
-	      case PCI_CLASS_SERIAL_FIBER:		return "Fiber Channel";
-
-	      default:					return "Unknown class";
-	}
-}
-
-
-const char *pci_strvendor(unsigned int vendor)
-{
-	switch (vendor) {
-	      case PCI_VENDOR_ID_COMPAQ:	return "Compaq";
-	      case PCI_VENDOR_ID_NCR:		return "NCR";
-	      case PCI_VENDOR_ID_ATI:		return "ATI";
-	      case PCI_VENDOR_ID_VLSI:		return "VLSI";
-	      case PCI_VENDOR_ID_ADL:		return "Avance Logic";
-	      case PCI_VENDOR_ID_NS:		return "NS";
-	      case PCI_VENDOR_ID_TSENG:		return "Tseng'Lab";
-	      case PCI_VENDOR_ID_WEITEK:	return "Weitek";
-	      case PCI_VENDOR_ID_DEC:		return "DEC";
-	      case PCI_VENDOR_ID_CIRRUS:	return "Cirrus Logic";
-	      case PCI_VENDOR_ID_IBM:		return "IBM";
-	      case PCI_VENDOR_ID_WD:		return "Western Digital";
-	      case PCI_VENDOR_ID_AMD:		return "AMD";
-	      case PCI_VENDOR_ID_TRIDENT:	return "Trident";
-	      case PCI_VENDOR_ID_AI:		return "Acer Incorporated";
-	      case PCI_VENDOR_ID_MATROX:	return "Matrox";
-	      case PCI_VENDOR_ID_CT:		return "Chips & Technologies";
-	      case PCI_VENDOR_ID_MIRO:		return "Miro";
-	      case PCI_VENDOR_ID_NEC:		return "NEC";
-	      case PCI_VENDOR_ID_FD:		return "Future Domain";
-	      case PCI_VENDOR_ID_SI:		return "Silicon Integrated Systems";
-	      case PCI_VENDOR_ID_HP:		return "Hewlett Packard";
-	      case PCI_VENDOR_ID_PCTECH:	return "PCTECH";
-	      case PCI_VENDOR_ID_DPT:		return "DPT";
-	      case PCI_VENDOR_ID_OPTI:		return "OPTi";
-	      case PCI_VENDOR_ID_SGS:		return "SGS Thomson";
-	      case PCI_VENDOR_ID_BUSLOGIC:	return "BusLogic";
-	      case PCI_VENDOR_ID_TI:		return "Texas Instruments";
-	      case PCI_VENDOR_ID_OAK: 		return "OAK";
-	      case PCI_VENDOR_ID_WINBOND2:	return "Winbond";
-	      case PCI_VENDOR_ID_MOTOROLA:	return "Motorola";
-	      case PCI_VENDOR_ID_PROMISE:	return "Promise Technology";
-	      case PCI_VENDOR_ID_N9:		return "Number Nine";
-	      case PCI_VENDOR_ID_UMC:		return "UMC";
-	      case PCI_VENDOR_ID_X:		return "X TECHNOLOGY";
-	      case PCI_VENDOR_ID_PICOP:		return "PicoPower";
-	      case PCI_VENDOR_ID_APPLE:		return "Apple";
-	      case PCI_VENDOR_ID_NEXGEN:	return "Nexgen";
-	      case PCI_VENDOR_ID_QLOGIC:	return "Q Logic";
-	      case PCI_VENDOR_ID_CYRIX:		return "Cyrix";
-	      case PCI_VENDOR_ID_LEADTEK:	return "Leadtek Research";
-	      case PCI_VENDOR_ID_CONTAQ:	return "Contaq";
-	      case PCI_VENDOR_ID_FOREX:		return "Forex";
-	      case PCI_VENDOR_ID_OLICOM:	return "Olicom";
-	      case PCI_VENDOR_ID_SUN:		return "Sun Microsystems";
-	      case PCI_VENDOR_ID_CMD:		return "CMD";
-	      case PCI_VENDOR_ID_VISION:	return "Vision";
-	      case PCI_VENDOR_ID_BROOKTREE:	return "Brooktree";
-	      case PCI_VENDOR_ID_SIERRA:	return "Sierra";
-	      case PCI_VENDOR_ID_ACC:		return "ACC MICROELECTRONICS";
-	      case PCI_VENDOR_ID_WINBOND:	return "Winbond";
-	      case PCI_VENDOR_ID_DATABOOK:	return "Databook";
-	      case PCI_VENDOR_ID_3COM:		return "3Com";
-	      case PCI_VENDOR_ID_SMC:		return "SMC";
-	      case PCI_VENDOR_ID_AL:		return "Acer Labs";
-	      case PCI_VENDOR_ID_MITSUBISHI:	return "Mitsubishi";
-	      case PCI_VENDOR_ID_SURECOM:	return "Surecom";
-	      case PCI_VENDOR_ID_NEOMAGIC:	return "Neomagic";
-	      case PCI_VENDOR_ID_ASP:		return "Advanced System Products";
-	      case PCI_VENDOR_ID_CERN:		return "CERN";
-	      case PCI_VENDOR_ID_NVIDIA:	return "NVidia";
-	      case PCI_VENDOR_ID_IMS:		return "IMS";
-	      case PCI_VENDOR_ID_TEKRAM2:	return "Tekram";
-	      case PCI_VENDOR_ID_TUNDRA:	return "Tundra";
-	      case PCI_VENDOR_ID_AMCC:		return "AMCC";
-	      case PCI_VENDOR_ID_INTERG:	return "Intergraphics";
-	      case PCI_VENDOR_ID_REALTEK:	return "Realtek";
-	      case PCI_VENDOR_ID_TRUEVISION:	return "Truevision";
-	      case PCI_VENDOR_ID_INIT:		return "Initio Corp";
-	      case PCI_VENDOR_ID_VIA:		return "VIA Technologies";
-	      case PCI_VENDOR_ID_VORTEX:	return "VORTEX";
-	      case PCI_VENDOR_ID_EF:		return "Efficient Networks";
-	      case PCI_VENDOR_ID_FORE:		return "Fore Systems";
-	      case PCI_VENDOR_ID_IMAGINGTECH:	return "Imaging Technology";
-	      case PCI_VENDOR_ID_PHILIPS:	return "Philips";
-	      case PCI_VENDOR_ID_PLX:		return "PLX";
-	      case PCI_VENDOR_ID_ALLIANCE:	return "Alliance";
-	      case PCI_VENDOR_ID_VMIC:		return "VMIC";
-	      case PCI_VENDOR_ID_DIGI:		return "Digi Intl.";
-	      case PCI_VENDOR_ID_MUTECH:	return "Mutech";
-	      case PCI_VENDOR_ID_RENDITION:	return "Rendition";
-	      case PCI_VENDOR_ID_TOSHIBA:	return "Toshiba";
-	      case PCI_VENDOR_ID_RICOH:		return "Ricoh";
-	      case PCI_VENDOR_ID_ZEITNET:	return "ZeitNet";
-	      case PCI_VENDOR_ID_OMEGA:		return "Omega Micro";
-	      case PCI_VENDOR_ID_LITEON:	return "LiteOn";
-	      case PCI_VENDOR_ID_NP:		return "Network Peripherals";
-	      case PCI_VENDOR_ID_SPECIALIX:	return "Specialix";
-	      case PCI_VENDOR_ID_AURAVISION:	return "Auravision";
-	      case PCI_VENDOR_ID_IKON:		return "Ikon";
-	      case PCI_VENDOR_ID_ZORAN:		return "Zoran";
-	      case PCI_VENDOR_ID_COMPEX:	return "Compex";
-	      case PCI_VENDOR_ID_RP:		return "Comtrol";
-	      case PCI_VENDOR_ID_CYCLADES:	return "Cyclades";
-	      case PCI_VENDOR_ID_3DFX:		return "3Dfx";
-	      case PCI_VENDOR_ID_STALLION:	return "Stallion Technologies";
-	      case PCI_VENDOR_ID_SIGMADES:	return "Sigma Designs";
-	      case PCI_VENDOR_ID_OPTIBASE:	return "Optibase";
-	      case PCI_VENDOR_ID_ENSONIQ:	return "Ensoniq";
-	      case PCI_VENDOR_ID_PICTUREL:	return "Picture Elements";
-	      case PCI_VENDOR_ID_NVIDIA_SGS:	return "NVidia/SGS Thomson";
-	      case PCI_VENDOR_ID_SYMPHONY:	return "Symphony";
-	      case PCI_VENDOR_ID_TEKRAM:	return "Tekram";
-	      case PCI_VENDOR_ID_3DLABS:	return "3Dlabs";
-	      case PCI_VENDOR_ID_AVANCE:	return "Avance";
-	      case PCI_VENDOR_ID_NETVIN:	return "NetVin";
-	      case PCI_VENDOR_ID_S3:		return "S3 Inc.";
-	      case PCI_VENDOR_ID_INTEL:		return "Intel";
-	      case PCI_VENDOR_ID_KTI:		return "KTI";
-	      case PCI_VENDOR_ID_ADAPTEC:	return "Adaptec";
-	      case PCI_VENDOR_ID_ATRONICS:	return "Atronics";
-	      case PCI_VENDOR_ID_ARK:		return "ARK Logic";
-	      default:				return "Unknown vendor";
-	}
-}
-
-
-const char *pci_strdev(unsigned int vendor, unsigned int device)
+__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
 {
-	struct pci_dev_info *info;
+	void *mem;
 
-	info = 	pci_lookup_dev(vendor, device);
-	return info ? info->name : "Unknown device";
+	mem = (void*) *mem_startp;
+	*mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+	memset(mem, 0, size);
+	return mem;
 }
 
 
@@ -704,10 +55,10 @@
 		case PCIBIOS_BAD_REGISTER_NUMBER:
 			return "BAD_REGISTER_NUMBER";
 
-		case PCIBIOS_SET_FAILED:
+                case PCIBIOS_SET_FAILED:          
 			return "SET_FAILED";
 
-		case PCIBIOS_BUFFER_TOO_SMALL:
+                case PCIBIOS_BUFFER_TOO_SMALL:    
 			return "BUFFER_TOO_SMALL";
 
 		default:
@@ -717,198 +68,10 @@
 }
 
 
-/*
- * Convert some of the configuration space registers of the device at
- * address (bus,devfn) into a string (possibly several lines each).
- * The configuration string is stored starting at buf[len].  If the
- * string would exceed the size of the buffer (SIZE), 0 is returned.
- */
-static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
-{
-	unsigned long base;
-	unsigned int l, class_rev, bus, devfn;
-	unsigned short vendor, device, status;
-	unsigned char bist, latency, min_gnt, max_lat;
-	int reg, len = 0;
-	const char *str;
-
-	bus   = dev->bus->number;
-	devfn = dev->devfn;
-
-	pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev);
-	pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor);
-	pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device);
-	pcibios_read_config_word (bus, devfn, PCI_STATUS, &status);
-	pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist);
-	pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency);
-	pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt);
-	pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat);
-	if (len + 80 > size) {
-		return -1;
-	}
-	len += sprintf(buf + len, "  Bus %2d, device %3d, function %2d:\n",
-		       bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
-	if (len + 80 > size) {
-		return -1;
-	}
-	len += sprintf(buf + len, "    %s: %s %s (rev %d).\n      ",
-		       pci_strclass(class_rev >> 8), pci_strvendor(vendor),
-		       pci_strdev(vendor, device), class_rev & 0xff);
-
-	if (!pci_lookup_dev(vendor, device)) {
-		len += sprintf(buf + len,
-			       "Vendor id=%x. Device id=%x.\n      ",
-			       vendor, device);
-	}
-
-	str = 0;	/* to keep gcc shut... */
-	switch (status & PCI_STATUS_DEVSEL_MASK) {
-	      case PCI_STATUS_DEVSEL_FAST:   str = "Fast devsel.  "; break;
-	      case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel.  "; break;
-	      case PCI_STATUS_DEVSEL_SLOW:   str = "Slow devsel.  "; break;
-	}
-	if (len + strlen(str) > size) {
-		return -1;
-	}
-	len += sprintf(buf + len, str);
-
-	if (status & PCI_STATUS_FAST_BACK) {
-#		define fast_b2b_capable	"Fast back-to-back capable.  "
-		if (len + strlen(fast_b2b_capable) > size) {
-			return -1;
-		}
-		len += sprintf(buf + len, fast_b2b_capable);
-#		undef fast_b2b_capable
-	}
-
-	if (bist & PCI_BIST_CAPABLE) {
-#		define BIST_capable	"BIST capable.  "
-		if (len + strlen(BIST_capable) > size) {
-			return -1;
-		}
-		len += sprintf(buf + len, BIST_capable);
-#		undef BIST_capable
-	}
-
-	if (dev->irq) {
-		if (len + 40 > size) {
-			return -1;
-		}
-		len += sprintf(buf + len, "IRQ %d.  ", dev->irq);
-	}
-
-	if (dev->master) {
-		if (len + 80 > size) {
-			return -1;
-		}
-		len += sprintf(buf + len, "Master Capable.  ");
-		if (latency)
-		  len += sprintf(buf + len, "Latency=%d.  ", latency);
-		else
-		  len += sprintf(buf + len, "No bursts.  ");
-		if (min_gnt)
-		  len += sprintf(buf + len, "Min Gnt=%d.", min_gnt);
-		if (max_lat)
-		  len += sprintf(buf + len, "Max Lat=%d.", max_lat);
-	}
-
-	for (reg = 0; reg < 6; reg++) {
-		if (len + 40 > size) {
-			return -1;
-		}
-		pcibios_read_config_dword(bus, devfn,
-				PCI_BASE_ADDRESS_0 + (reg << 2), &l);
-		if (l == 0xffffffff)
-			base = 0;
-		else
-			base = l;
-		if (!base)
-			continue;
-
-		if (base & PCI_BASE_ADDRESS_SPACE_IO) {
-			len += sprintf(buf + len,
-				       "\n      I/O at 0x%lx [0x%lx].",
-				       base & PCI_BASE_ADDRESS_IO_MASK,
-				       dev->base_address[reg]);
-		} else {
-			const char *pref, *type = "unknown";
-
-			if (base & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-				pref = "P";
-			} else {
-				pref = "Non-p";
-			}
-			switch (base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
-			      case PCI_BASE_ADDRESS_MEM_TYPE_32:
-				type = "32 bit"; break;
-			      case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-				type = "20 bit"; break;
-			      case PCI_BASE_ADDRESS_MEM_TYPE_64:
-				type = "64 bit";
-				/* read top 32 bit address of base addr: */
-				reg += 4;
-				pcibios_read_config_dword(bus, devfn, reg, &l);
-				base |= ((u64) l) << 32;
-				break;
-			}
-			len += sprintf(buf + len,
-				       "\n      %srefetchable %s memory at "
-				       "0x%lx [0x%lx].", pref, type,
-				       base & PCI_BASE_ADDRESS_MEM_MASK,
-				       dev->base_address[reg]);
-		}
-	}
-
-	len += sprintf(buf + len, "\n");
-	return len;
-}
-
-
-/*
- * Return list of PCI devices as a character string for /proc/pci.
- * BUF is a buffer that is PAGE_SIZE bytes long.
- */
-int get_pci_list(char *buf)
-{
-	int nprinted, len, size;
-	struct pci_dev *dev;
-#	define MSG "\nwarning: page-size limit reached!\n"
-
-	/* reserve same for truncation warning message: */
-	size  = PAGE_SIZE - (strlen(MSG) + 1);
-	len   = sprintf(buf, "PCI devices found:\n");
-
-	for (dev = pci_devices; dev; dev = dev->next) {
-		nprinted = sprint_dev_config(dev, buf + len, size - len);
-		if (nprinted < 0) {
-			return len + sprintf(buf + len, MSG);
-		}
-		len += nprinted;
-	}
-	return len;
-}
-
-
-/*
- * pci_malloc() returns initialized memory of size SIZE.  Can be
- * used only while pci_init() is active.
- */
-__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
-{
-	void *mem;
-
-	mem = (void*) *mem_startp;
-	*mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
-	memset(mem, 0, size);
-	return mem;
-}
-
 unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
 {
 	unsigned int devfn, l, max, class;
 	unsigned char cmd, irq, tmp, hdr_type = 0;
-	struct pci_dev_info *info;
 	struct pci_dev *dev;
 	struct pci_bus *child;
 	int reg;
@@ -939,17 +102,6 @@
 		dev->vendor = l & 0xffff;
 		dev->device = (l >> 16) & 0xffff;
 
-		/*
-		 * Check to see if we know about this device and report
-		 * a message at boot time.  This is the only way to
-		 * learn about new hardware...
-		 */
-		info = pci_lookup_dev(dev->vendor, dev->device);
-		if (!info) {
-			printk("PCI: Warning: Unknown PCI device (%x:%x).  Please read include/linux/pci.h\n",
-				dev->vendor, dev->device);
-		}
-
 		/* non-destructively determine if device can be a master: */
 		pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &cmd);
 		pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
@@ -1047,7 +199,7 @@
 			 * has already been configured by the system.  If so,
 			 * do not modify the configuration, merely note it.
 			 */
-			pcibios_read_config_dword(bus->number, devfn, 0x18, &buses);
+			pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);
 			if ((buses & 0xFFFFFF) != 0)
 			  {
 			    child->primary = buses & 0xFF;
@@ -1066,7 +218,7 @@
 			      (((unsigned int)(child->primary)     <<  0) |
 			       ((unsigned int)(child->secondary)   <<  8) |
 			       ((unsigned int)(child->subordinate) << 16));
-			    pcibios_write_config_dword(bus->number, devfn, 0x18, buses);
+			    pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
 			    /*
 			     * Now we can scan all subordinate buses:
 			     */
@@ -1078,7 +230,7 @@
 			    child->subordinate = max;
 			    buses = (buses & 0xff00ffff)
 			      | ((unsigned int)(child->subordinate) << 16);
-			    pcibios_write_config_dword(bus->number, devfn, 0x18, buses);
+			    pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
 			  }
 			pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr);
 		}
@@ -1113,16 +265,6 @@
 
 	/* give BIOS a chance to apply platform specific fixes: */
 	mem_start = pcibios_fixup(mem_start, mem_end);
-
-#ifdef DEBUG
-	{
-		int len = get_pci_list((char*)mem_start);
-		if (len) {
-			((char *) mem_start)[len] = '\0';
-			printk("%s\n", (char *) mem_start);
-		}
-	}
-#endif
 
 #ifdef CONFIG_PCI_OPTIMIZE
 	pci_quirks_init();
diff -u --recursive --new-file v2.1.81/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
--- v2.1.81/linux/drivers/pci/proc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/proc.c	Mon Jan 26 11:43:18 1998
@@ -0,0 +1,292 @@
+/*
+ *	$Id: proc.c,v 1.1 1997/12/22 17:22:31 mj Exp $
+ *
+ *	Procfs interface for the PCI bus.
+ *
+ *	Copyright (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+
+#define PCI_CFG_SPACE_SIZE 256
+
+static loff_t
+proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
+{
+	loff_t new;
+
+	switch (whence) {
+	case 0:
+		new = off;
+		break;
+	case 1:
+		new = file->f_pos + off;
+		break;
+	case 2:
+		new = PCI_CFG_SPACE_SIZE + off;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (new < 0 || new > PCI_CFG_SPACE_SIZE)
+		return -EINVAL;
+	return (file->f_pos = new);
+}
+
+static ssize_t
+proc_bus_pci_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+	struct inode *ino = file->f_dentry->d_inode;
+	struct proc_dir_entry *dp = ino->u.generic_ip;
+	struct pci_dev *dev = dp->data;
+	int pos = *ppos;
+	unsigned char bus = dev->bus->number;
+	unsigned char dfn = dev->devfn;
+	int cnt;
+
+	if (pos >= PCI_CFG_SPACE_SIZE)
+		return 0;
+	if (nbytes >= PCI_CFG_SPACE_SIZE)
+		nbytes = PCI_CFG_SPACE_SIZE;
+	if (pos + nbytes > PCI_CFG_SPACE_SIZE)
+		nbytes = PCI_CFG_SPACE_SIZE - pos;
+	cnt = nbytes;
+
+	if (!access_ok(VERIFY_WRITE, buf, cnt))
+		return -EINVAL;
+
+	if ((pos & 1) && cnt) {
+		unsigned char val;
+		pcibios_read_config_byte(bus, dfn, pos, &val);
+		__put_user(val, buf);
+		buf++;
+		pos++;
+		cnt--;
+	}
+
+	if ((pos & 3) && cnt > 2) {
+		unsigned short val;
+		pcibios_read_config_word(bus, dfn, pos, &val);
+		__put_user(cpu_to_le16(val), (unsigned short *) buf);
+		buf += 2;
+		pos += 2;
+		cnt -= 2;
+	}
+
+	while (cnt >= 4) {
+		unsigned int val;
+		pcibios_read_config_dword(bus, dfn, pos, &val);
+		__put_user(cpu_to_le32(val), (unsigned int *) buf);
+		buf += 4;
+		pos += 4;
+		cnt -= 4;
+	}
+
+	if (cnt >= 2) {
+		unsigned short val;
+		pcibios_read_config_word(bus, dfn, pos, &val);
+		__put_user(cpu_to_le16(val), (unsigned short *) buf);
+		buf += 2;
+		pos += 2;
+		cnt -= 2;
+	}
+
+	if (cnt) {
+		unsigned char val;
+		pcibios_read_config_byte(bus, dfn, pos, &val);
+		__put_user(val, buf);
+		buf++;
+		pos++;
+		cnt--;
+	}
+
+	*ppos = pos;
+	return nbytes;
+}
+
+static ssize_t
+proc_bus_pci_write(struct file *file, const char *buf, size_t nbytes, loff_t *ppos)
+{
+	struct inode *ino = file->f_dentry->d_inode;
+	struct proc_dir_entry *dp = ino->u.generic_ip;
+	struct pci_dev *dev = dp->data;
+	int pos = *ppos;
+	unsigned char bus = dev->bus->number;
+	unsigned char dfn = dev->devfn;
+	int cnt;
+
+	if (pos >= PCI_CFG_SPACE_SIZE)
+		return 0;
+	if (nbytes >= PCI_CFG_SPACE_SIZE)
+		nbytes = PCI_CFG_SPACE_SIZE;
+	if (pos + nbytes > PCI_CFG_SPACE_SIZE)
+		nbytes = PCI_CFG_SPACE_SIZE - pos;
+	cnt = nbytes;
+
+	if (!access_ok(VERIFY_READ, buf, cnt))
+		return -EINVAL;
+
+	if ((pos & 1) && cnt) {
+		unsigned char val;
+		__get_user(val, buf);
+		pcibios_write_config_byte(bus, dfn, pos, val);
+		buf++;
+		pos++;
+		cnt--;
+	}
+
+	if ((pos & 3) && cnt > 2) {
+		unsigned short val;
+		__get_user(val, (unsigned short *) buf);
+		pcibios_write_config_word(bus, dfn, pos, le16_to_cpu(val));
+		buf += 2;
+		pos += 2;
+		cnt -= 2;
+	}
+
+	while (cnt >= 4) {
+		unsigned int val;
+		__get_user(val, (unsigned int *) buf);
+		pcibios_write_config_dword(bus, dfn, pos, le32_to_cpu(val));
+		buf += 4;
+		pos += 4;
+		cnt -= 4;
+	}
+
+	if (cnt >= 2) {
+		unsigned short val;
+		__get_user(val, (unsigned short *) buf);
+		pcibios_write_config_word(bus, dfn, pos, le16_to_cpu(val));
+		buf += 2;
+		pos += 2;
+		cnt -= 2;
+	}
+
+	if (cnt) {
+		unsigned char val;
+		__get_user(val, buf);
+		pcibios_write_config_byte(bus, dfn, pos, val);
+		buf++;
+		pos++;
+		cnt--;
+	}
+
+	*ppos = pos;
+	return nbytes;
+}
+
+static struct file_operations proc_bus_pci_operations = {
+	proc_bus_pci_lseek,
+	proc_bus_pci_read,
+	proc_bus_pci_write,
+	NULL,		/* readdir */
+	NULL,		/* poll */
+	NULL,		/* ioctl */
+	NULL,		/* mmap */
+	NULL,		/* no special open code */
+	NULL,		/* no special release code */
+	NULL		/* can't fsync */
+};
+
+static struct inode_operations proc_bus_pci_inode_operations = {
+	&proc_bus_pci_operations, /* default base directory file-ops */
+	NULL,			/* create */
+	NULL,			/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* bmap */
+	NULL,			/* truncate */
+	NULL			/* permission */
+};
+
+int
+get_pci_dev_info(char *buf, char **start, off_t pos, int count, int wr)
+{
+	struct pci_dev *dev = pci_devices;
+	off_t at = 0;
+	int len, i, cnt;
+
+	cnt = 0;
+	while (dev && count > cnt) {
+		len = sprintf(buf, "%02x%02x\t%04x%04x\t%x",
+			dev->bus->number,
+			dev->devfn,
+			dev->vendor,
+			dev->device,
+			dev->irq);
+		for(i=0; i<6; i++)
+			len += sprintf(buf+len,
+#if BITS_PER_LONG == 32
+						"\t%08lx",
+#else
+						"\t%016lx",
+#endif
+					dev->base_address[i]);
+		buf[len++] = '\n';
+		at += len;
+		if (at >= pos) {
+			if (!*start) {
+				*start = buf + (pos - (at - len));
+				cnt = at - pos;
+			} else
+				cnt += len;
+			buf += len;
+		}
+		dev = dev->next;
+	}
+	return (count > cnt) ? cnt : count;
+}
+
+static struct proc_dir_entry proc_pci_devices = {
+	PROC_BUS_PCI_DEVICES, 7, "devices",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations,
+	get_pci_dev_info
+};
+
+__initfunc(void proc_bus_pci_init(void))
+{
+	struct proc_dir_entry *proc_pci;
+	struct pci_bus *bus;
+
+	if (!pcibios_present())
+		return;
+	proc_pci = create_proc_entry("pci", S_IFDIR, proc_bus);
+	proc_register(proc_pci, &proc_pci_devices);
+	for(bus = &pci_root; bus; bus = bus->next) {
+		char name[16];
+		struct proc_dir_entry *de;
+		struct pci_dev *dev;
+
+		sprintf(name, "%02x", bus->number);
+		de = create_proc_entry(name, S_IFDIR, proc_pci);
+		for(dev = bus->devices; dev; dev = dev->sibling) {
+			struct proc_dir_entry *e;
+
+			sprintf(name, "%02x.%x",
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+			e = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, de);
+			e->ops = &proc_bus_pci_inode_operations;
+			e->data = dev;
+			e->size = PCI_CFG_SPACE_SIZE;
+		}
+	}
+}
diff -u --recursive --new-file v2.1.81/linux/drivers/pnp/parport_probe.c linux/drivers/pnp/parport_probe.c
--- v2.1.81/linux/drivers/pnp/parport_probe.c	Tue Dec  2 09:38:15 1997
+++ linux/drivers/pnp/parport_probe.c	Fri Jan 23 20:04:03 1998
@@ -58,7 +58,11 @@
 	for (i=0; ; i++) {
 		parport_write_control(port, parport_read_control(port) | 2); /* AutoFeed high */
 		if (parport_wait_peripheral(port, 0x40, 0)) {
+#ifdef DEBUG_PROBE
+			/* Some peripherals just time out when they've sent
+			   all their data.  */
 			printk("%s: read1 timeout.\n", port->name);
+#endif
 			parport_write_control(port, parport_read_control(port) & ~2);
 			break;
 		}
@@ -68,36 +72,26 @@
 			printk("%s: read2 timeout.\n", port->name);
 			break;
 		}
-		if (( i & 1) != 0) {
-			Byte= (Byte | z<<4);
+		if ((i & 1) != 0) {
+			Byte |= (z<<4);
 			if (temp) 
 				*(temp++) = Byte; 
 			if (count++ == length)
 				temp = NULL;
 			/* Does the error line indicate end of data? */
-			if ((parport_read_status(port) & LP_PERRORP) == LP_PERRORP) 
+			if ((parport_read_status(port) & LP_PERRORP) == 
+			    LP_PERRORP) 
 				break;
-		} else Byte=z;
+		} else 
+			Byte=z;
 	}
 	read_terminate(port);
 	return count; 
 }
 
-static struct wait_queue *wait_q;
-
-static void wakeup(void *ref)
-{
-	struct pardevice **dev = (struct pardevice **)ref;
-	
-	if (!waitqueue_active || parport_claim(*dev))
-		return;
-
-	wake_up(&wait_q);
-}
-
 int parport_probe(struct parport *port, char *buffer, int len)
 {
-	struct pardevice *dev = parport_register_device(port, "IEEE 1284 probe", NULL, wakeup, NULL, PARPORT_DEV_TRAN, &dev);
+	struct pardevice *dev = parport_register_device(port, "IEEE 1284 probe", NULL, NULL, NULL, PARPORT_DEV_TRAN, &dev);
 
 	int result = 0;
 
@@ -106,9 +100,7 @@
 		return -EINVAL;
 	}
 
-	init_waitqueue (&wait_q);
-	if (parport_claim(dev))
-		sleep_on(&wait_q);
+	parport_claim_or_block(dev);
 
 	switch (parport_ieee1284_nibble_mode_ok(port, 4)) {
 	case 1:
@@ -233,6 +225,7 @@
 	char *buffer = kmalloc(2048, GFP_KERNEL);
 	int r;
 
+	MOD_INC_USE_COUNT;
 	port->probe_info.model = "Unknown device";
 	port->probe_info.mfr = "Unknown vendor";
 	port->probe_info.description = NULL;
@@ -261,17 +254,16 @@
 		pretty_print(port);
 	}
 	kfree(buffer);
+	MOD_DEC_USE_COUNT;
 }
 
 #if MODULE
 int init_module(void)
 {
 	struct parport *p;
-	MOD_INC_USE_COUNT;
 	for (p = parport_enumerate(); p; p = p->next) 
 		parport_probe_one(p);
 	parport_probe_hook = &parport_probe_one;
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.81/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v2.1.81/linux/drivers/scsi/NCR5380.c	Fri Jan 23 18:10:32 1998
+++ linux/drivers/scsi/NCR5380.c	Sun Jan 25 10:05:46 1998
@@ -625,7 +625,8 @@
  */
 
 
-static int probe_irq __initdata ;
+static int probe_irq __initdata = 0;
+
 __initfunc(static void probe_intr (int irq, void *dev_id, struct pt_regs * regs)) {
     probe_irq = irq;
 };
diff -u --recursive --new-file v2.1.81/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.1.81/linux/drivers/scsi/hosts.c	Sun Dec 21 17:04:49 1997
+++ linux/drivers/scsi/hosts.c	Mon Jan 26 11:41:04 1998
@@ -503,6 +503,32 @@
     return 0;
 }
 
+/*
+ * Why is this a seperate function?  Because the kernel_thread code
+ * effectively does a fork, and there is a builtin exit() call when
+ * the child returns.   The difficulty is that scsi_init() is
+ * marked __initfunc(), which means the memory is unmapped after bootup
+ * is complete, which means that the thread's exit() call gets wiped.
+ *
+ * The lesson is to *NEVER*, *NEVER* call kernel_thread() from an
+ * __initfunc() function, if that function could ever return.
+ */
+static void launch_error_handler_thread(struct Scsi_Host * shpnt)
+{
+            struct semaphore sem = MUTEX_LOCKED;
+            
+            shpnt->eh_notify = &sem;
+
+            kernel_thread((int (*)(void *))scsi_error_handler, 
+                          (void *) shpnt, 0);
+            /*
+             * Now wait for the kernel error thread to initialize itself
+             * as it might be needed when we scan the bus.
+             */
+            down (&sem);
+            shpnt->eh_notify = NULL;
+}
+
 __initfunc(unsigned int scsi_init(void))
 {
     static int called = 0;
@@ -559,18 +585,7 @@
          */
         if( shpnt->hostt->use_new_eh_code )
         {
-            struct semaphore sem = MUTEX_LOCKED;
-            
-            shpnt->eh_notify = &sem;
-
-            kernel_thread((int (*)(void *))scsi_error_handler, 
-                          (void *) shpnt, 0);
-            /*
-             * Now wait for the kernel error thread to initialize itself
-             * as it might be needed when we scan the bus.
-             */
-            down (&sem);
-            shpnt->eh_notify = NULL;
+            launch_error_handler_thread(shpnt);
         }
     }
     
diff -u --recursive --new-file v2.1.81/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
--- v2.1.81/linux/drivers/sound/audio.c	Fri Jan 23 18:10:32 1998
+++ linux/drivers/sound/audio.c	Sun Jan 25 10:05:47 1998
@@ -350,7 +350,7 @@
 int audio_ioctl(int dev, struct fileinfo *file_must_not_be_used,
 		unsigned int cmd, caddr_t arg)
 {
-	int val = 0, info, count;
+	int val, count;
 	unsigned long flags;
 	struct dma_buffparms *dmap;
 
@@ -419,16 +419,16 @@
 			return 0;
 
 		case SNDCTL_DSP_GETCAPS:
-				info = 1 | DSP_CAP_MMAP;	/* Revision level of this ioctl() */
+				val = 1 | DSP_CAP_MMAP;	/* Revision level of this ioctl() */
 				if (audio_devs[dev]->flags & DMA_DUPLEX &&
 					audio_devs[dev]->open_mode == OPEN_READWRITE)
-					info |= DSP_CAP_DUPLEX;
+					val |= DSP_CAP_DUPLEX;
 				if (audio_devs[dev]->coproc)
-					info |= DSP_CAP_COPROC;
+					val |= DSP_CAP_COPROC;
 				if (audio_devs[dev]->d->local_qlen)	/* Device has hidden buffers */
-					info |= DSP_CAP_BATCH;
+					val |= DSP_CAP_BATCH;
 				if (audio_devs[dev]->d->trigger)	/* Supports SETTRIGGER */
-					info |= DSP_CAP_TRIGGER;
+					val |= DSP_CAP_TRIGGER;
 				break;
 			
 		case SOUND_PCM_WRITE_RATE:
diff -u --recursive --new-file v2.1.81/linux/drivers/sound/sb_mixer.h linux/drivers/sound/sb_mixer.h
--- v2.1.81/linux/drivers/sound/sb_mixer.h	Tue Dec 23 13:52:02 1997
+++ linux/drivers/sound/sb_mixer.h	Sun Jan 25 10:05:47 1998
@@ -136,7 +136,8 @@
 };
 
 #ifdef	__SGNXPRO__
-static mixer_tab sgnxpro_mix = {
+#if 0
+static mixer_tab sgnxpro_mix = { 	/* not used anywhere */
 MIX_ENT(SOUND_MIXER_VOLUME,	0x22, 7, 4, 0x22, 3, 4),
 MIX_ENT(SOUND_MIXER_BASS,	0x46, 2, 3, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_TREBLE,	0x44, 2, 3, 0x00, 0, 0),
@@ -152,6 +153,7 @@
 MIX_ENT(SOUND_MIXER_IGAIN,	0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_OGAIN,	0x00, 0, 0, 0x00, 0, 0)
 };
+#endif
 #endif
 
 static mixer_tab sb16_mix = {
diff -u --recursive --new-file v2.1.81/linux/drivers/sound/softoss.c linux/drivers/sound/softoss.c
--- v2.1.81/linux/drivers/sound/softoss.c	Sun Jan  4 10:40:16 1998
+++ linux/drivers/sound/softoss.c	Sun Jan 25 10:05:47 1998
@@ -106,7 +106,7 @@
 
 static struct softsyn_devc sdev_info =
 {0};
-static softsyn_devc   *devc = &sdev_info;
+softsyn_devc   *devc = &sdev_info;	/* used in softoss_rs.c */
 
 static struct voice_alloc_info *voice_alloc;
 
diff -u --recursive --new-file v2.1.81/linux/fs/adfs/inode.c linux/fs/adfs/inode.c
--- v2.1.81/linux/fs/adfs/inode.c	Tue Jan 20 16:44:58 1998
+++ linux/fs/adfs/inode.c	Sun Jan 25 10:05:47 1998
@@ -71,7 +71,7 @@
 	return inode->u.adfs_i.file_id;
 }
 
-unsigned int adfs_bmap (struct inode *inode, int block)
+int adfs_bmap (struct inode *inode, int block)
 {
 	struct super_block *sb = inode->i_sb;
 	unsigned int blk;
diff -u --recursive --new-file v2.1.81/linux/fs/bad_inode.c linux/fs/bad_inode.c
--- v2.1.81/linux/fs/bad_inode.c	Sun Jan  4 00:53:41 1998
+++ linux/fs/bad_inode.c	Sun Jan 25 10:09:43 1998
@@ -11,12 +11,14 @@
 #include <linux/sched.h>
 
 /*
- * The follow_symlink operation must dput() the base.
+ * The follow_link operation is special: it must behave as a no-op
+ * so that a bad root inode can at least be unmounted. To do this
+ * we must dput() the base and return the dentry with a dget().
  */
 static struct dentry * bad_follow_link(struct dentry *dent, struct dentry *base)
 {
 	dput(base);
-	return ERR_PTR(-EIO);
+	return dget(dent);
 }
 
 static int return_EIO(void)
@@ -62,7 +64,9 @@
 	EIO_ERROR,		/* bmap */
 	EIO_ERROR,		/* truncate */
 	EIO_ERROR,		/* permission */
-	EIO_ERROR		/* smap */
+	EIO_ERROR,		/* smap */
+	EIO_ERROR,		/* update_page */
+	EIO_ERROR		/* revalidate */
 };
 
 
diff -u --recursive --new-file v2.1.81/linux/fs/filesystems.c linux/fs/filesystems.c
--- v2.1.81/linux/fs/filesystems.c	Tue Jan 20 16:44:58 1998
+++ linux/fs/filesystems.c	Sun Jan 25 10:05:47 1998
@@ -37,6 +37,10 @@
 #include <linux/init.h>
 #include <linux/nls.h>
 
+#ifdef CONFIG_CODA_FS
+extern int init_coda_fs(void);
+#endif
+
 extern void device_setup(void);
 extern void binfmt_setup(void);
 extern void free_initmem(void);
diff -u --recursive --new-file v2.1.81/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.1.81/linux/fs/nfs/dir.c	Wed Jan 14 16:57:52 1998
+++ linux/fs/nfs/dir.c	Sat Jan 24 10:53:00 1998
@@ -535,11 +535,6 @@
 	}
 }
 
-static void nfs_set_fh(struct dentry *dentry, struct nfs_fh *fhandle)
-{
-	*((struct nfs_fh *) dentry->d_fsdata) = *fhandle;
-}
-
 static int nfs_lookup(struct inode *dir, struct dentry * dentry)
 {
 	struct inode *inode;
@@ -574,8 +569,7 @@
 		goto no_entry;
 	if (!error) {
 		error = -EACCES;
-		nfs_set_fh(dentry, &fhandle);
-		inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
+		inode = nfs_fhget(dentry, &fhandle, &fattr);
 		if (inode) {
 #ifdef NFS_PARANOIA
 if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink)) {
@@ -609,8 +603,7 @@
 	struct inode *inode;
 	int error = -EACCES;
 
-	nfs_set_fh(dentry, fhandle);
-	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
+	inode = nfs_fhget(dentry, fhandle, fattr);
 	if (inode) {
 #ifdef NFS_PARANOIA
 if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink)) {
diff -u --recursive --new-file v2.1.81/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.81/linux/fs/nfs/inode.c	Fri Jan 16 11:24:09 1998
+++ linux/fs/nfs/inode.c	Sat Jan 24 10:53:00 1998
@@ -32,9 +32,12 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#define CONFIG_NFS_SNAPSHOT 1
 #define NFSDBG_FACILITY		NFSDBG_VFS
 #define NFS_PARANOIA 1
 
+static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *);
+
 static void nfs_read_inode(struct inode *);
 static void nfs_put_inode(struct inode *);
 static void nfs_delete_inode(struct inode *);
@@ -190,6 +193,7 @@
 	int			tcp;
 	struct sockaddr_in	srvaddr;
 	struct rpc_timeout	timeparms;
+	struct nfs_fattr	fattr;
 
 	MOD_INC_USE_COUNT;
 	if (!data)
@@ -274,7 +278,10 @@
 		goto out_no_fh;
 	*root_fh = data->root;
 
-	root_inode = nfs_fhget(sb, &data->root, NULL);
+	if (nfs_proc_getattr(server, root_fh, &fattr) != 0)
+		goto out_no_fattr;
+
+	root_inode = __nfs_fhget(sb, &fattr);
 	if (!root_inode)
 		goto out_no_root;
 	sb->s_root = d_alloc_root(root_inode, NULL);
@@ -295,6 +302,11 @@
 out_no_root:
 	printk("nfs_read_super: get root inode failed\n");
 	iput(root_inode);
+	goto out_free_fh;
+
+out_no_fattr:
+	printk("nfs_read_super: get root fattr failed\n");
+out_free_fh:
 	kfree(root_fh);
 out_no_fh:
 	rpciod_down();
@@ -384,42 +396,110 @@
 }
 
 /*
+ * Fill in inode information from the fattr.
+ */
+static void
+nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
+{
+	/*
+	 * Check whether the mode has been set, as we only want to
+	 * do this once. (We don't allow inodes to change types.)
+	 */
+	if (inode->i_mode == 0) {
+		inode->i_mode = fattr->mode;
+		if (S_ISREG(inode->i_mode))
+			inode->i_op = &nfs_file_inode_operations;
+		else if (S_ISDIR(inode->i_mode))
+			inode->i_op = &nfs_dir_inode_operations;
+		else if (S_ISLNK(inode->i_mode))
+			inode->i_op = &nfs_symlink_inode_operations;
+		else if (S_ISCHR(inode->i_mode)) {
+			inode->i_op = &chrdev_inode_operations;
+			inode->i_rdev = to_kdev_t(fattr->rdev);
+		} else if (S_ISBLK(inode->i_mode)) {
+			inode->i_op = &blkdev_inode_operations;
+			inode->i_rdev = to_kdev_t(fattr->rdev);
+		} else if (S_ISFIFO(inode->i_mode))
+			init_fifo(inode);
+		else
+			inode->i_op = NULL;
+		/*
+		 * Preset the size and mtime, as there's no need
+		 * to invalidate the caches.
+		 */ 
+		inode->i_size  = fattr->size;
+		inode->i_mtime = fattr->mtime.seconds;
+		NFS_OLDMTIME(inode) = fattr->mtime.seconds;
+	}
+	nfs_refresh_inode(inode, fattr);
+}
+
+/*
  * This is our own version of iget that looks up inodes by file handle
  * instead of inode number.  We use this technique instead of using
  * the vfs read_inode function because there is no way to pass the
  * file handle or current attributes into the read_inode function.
  *
+ * We provide a special check for NetApp .snapshot directories to avoid
+ * inode aliasing problems. All snapshot inodes are anonymous (unhashed).
+ */
+struct inode *
+nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
+				 struct nfs_fattr *fattr)
+{
+	struct super_block *sb = dentry->d_sb;
+
+	dprintk("NFS: nfs_fhget(%s/%s fileid=%d)\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name,
+		fattr->fileid);
+
+	/* Install the filehandle in the dentry */
+	*((struct nfs_fh *) dentry->d_fsdata) = *fhandle;
+
+#ifdef CONFIG_NFS_SNAPSHOT
+	/*
+	 * Check for NetApp snapshot dentries, and get an 
+	 * unhashed inode to avoid aliasing problems.
+	 */
+	if ((dentry->d_parent->d_inode->u.nfs_i.flags & NFS_IS_SNAPSHOT) ||
+	    (IS_ROOT(dentry->d_parent) && dentry->d_name.len == 9 &&
+	     memcmp(dentry->d_name.name, ".snapshot", 9) == 0)) {
+		struct inode *inode = get_empty_inode();
+		if (!inode)
+			goto out;	
+		inode->i_sb = sb;
+		inode->i_dev = sb->s_dev;
+		inode->i_ino = fattr->fileid;
+		nfs_read_inode(inode);
+		nfs_fill_inode(inode, fattr);
+		inode->u.nfs_i.flags |= NFS_IS_SNAPSHOT;
+		dprintk("NFS: nfs_fhget(snapshot ino=%ld)\n", inode->i_ino);
+	out:
+		return inode;
+	}
+#endif
+	return __nfs_fhget(sb, fattr);
+}
+
+/*
+ * Look up the inode by super block and fattr->fileid.
+ *
  * Note carefully the special handling of busy inodes (i_count > 1).
- * With the Linux 2.1.xx dcache all inodes except hard links must
+ * With the kernel 2.1.xx dcache all inodes except hard links must
  * have i_count == 1 after iget(). Otherwise, it indicates that the
  * server has reused a fileid (i_ino) and we have a stale inode.
  */
-struct inode *
-nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
-				  struct nfs_fattr *fattr)
+static struct inode *
+__nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
 {
-	int error, max_count;
-	struct inode *inode = NULL;
-	struct nfs_fattr newfattr;
-
-	if (!sb)
-		goto out_bad_args;
-	if (!fattr) {
-		fattr = &newfattr;
-		error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,fattr);
-		if (error)
-			goto out_bad_attr;
-	}
+	struct inode *inode;
+	int max_count;
 
 retry:
 	inode = iget(sb, fattr->fileid);
 	if (!inode)
 		goto out_no_inode;
-#ifdef NFS_PARANOIA
-if (inode->i_dev != sb->s_dev)
-printk("nfs_fhget: impossible\n");
-#endif
-
+	/* N.B. This should be impossible ... */
 	if (inode->i_ino != fattr->fileid)
 		goto out_bad_id;
 
@@ -434,19 +514,20 @@
 	 */
 	max_count = S_ISDIR(fattr->mode) ? 1 : fattr->nlink;
 	if (inode->i_count > max_count) {
-printk("nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n",
+printk("__nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n",
 inode->i_ino, inode->i_count, inode->i_nlink);
 		nfs_free_dentries(inode);
 		if (inode->i_count > max_count) {
-printk("nfs_fhget: inode %ld still busy, i_count=%d\n",
+printk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
 inode->i_ino, inode->i_count);
 			if (!list_empty(&inode->i_dentry)) {
 				struct dentry *dentry;
 				dentry = list_entry(inode->i_dentry.next,
 						 struct dentry, d_alias);
-printk("nfs_fhget: killing %s/%s filehandle\n",
+printk("__nfs_fhget: killing %s/%s filehandle\n",
 dentry->d_parent->d_name.name, dentry->d_name.name);
-				memset(dentry->d_fsdata, 0, sizeof(*fhandle));
+				memset(dentry->d_fsdata, 0, 
+					sizeof(struct nfs_fh));
 			} else
 				printk("NFS: inode %ld busy, no aliases?\n",
 					inode->i_ino);
@@ -456,56 +537,18 @@
 		iput(inode);
 		goto retry;
 	}
-
-	/*
-	 * Check whether the mode has been set, as we only want to
-	 * do this once. (We don't allow inodes to change types.)
-	 */
-	if (inode->i_mode == 0) {
-		inode->i_mode = fattr->mode;
-		if (S_ISREG(inode->i_mode))
-			inode->i_op = &nfs_file_inode_operations;
-		else if (S_ISDIR(inode->i_mode))
-			inode->i_op = &nfs_dir_inode_operations;
-		else if (S_ISLNK(inode->i_mode))
-			inode->i_op = &nfs_symlink_inode_operations;
-		else if (S_ISCHR(inode->i_mode)) {
-			inode->i_op = &chrdev_inode_operations;
-			inode->i_rdev = to_kdev_t(fattr->rdev);
-		} else if (S_ISBLK(inode->i_mode)) {
-			inode->i_op = &blkdev_inode_operations;
-			inode->i_rdev = to_kdev_t(fattr->rdev);
-		} else if (S_ISFIFO(inode->i_mode))
-			init_fifo(inode);
-		else
-			inode->i_op = NULL;
-		/*
-		 * Preset the size and mtime, as there's no need
-		 * to invalidate the caches.
-		 */ 
-		inode->i_size  = fattr->size;
-		inode->i_mtime = fattr->mtime.seconds;
-		NFS_OLDMTIME(inode) = fattr->mtime.seconds;
-	}
-	nfs_refresh_inode(inode, fattr);
-	dprintk("NFS: fhget(%x/%ld ct=%d)\n",
-		inode->i_dev, inode->i_ino,
-		inode->i_count);
+	nfs_fill_inode(inode, fattr);
+	dprintk("NFS: __nfs_fhget(%x/%ld ct=%d)\n",
+		inode->i_dev, inode->i_ino, inode->i_count);
 
 out:
 	return inode;
 
-out_bad_args:
-	printk("nfs_fhget: super block is NULL\n");
-	goto out;
-out_bad_attr:
-	printk("nfs_fhget: getattr error = %d\n", -error);
-	goto out;
 out_no_inode:
-	printk("nfs_fhget: iget failed\n");
+	printk("__nfs_fhget: iget failed\n");
 	goto out;
 out_bad_id:
-	printk("nfs_fhget: unexpected inode from iget\n");
+	printk("__nfs_fhget: unexpected inode from iget\n");
 	goto out;
 }
 
diff -u --recursive --new-file v2.1.81/linux/fs/nfs/nfs2xdr.c linux/fs/nfs/nfs2xdr.c
--- v2.1.81/linux/fs/nfs/nfs2xdr.c	Sat Dec 20 21:06:01 1997
+++ linux/fs/nfs/nfs2xdr.c	Sat Jan 24 10:53:00 1998
@@ -406,8 +406,9 @@
 
 		len = ntohl(*p++);
 		if ((p + QUADLEN(len) + 3) > end) {
-			printk(KERN_NOTICE
-				"NFS: short packet in readdir reply!\n");
+			printk(KERN_WARNING "NFS: short readdir reply! "
+				"nr=%d, slots=%d, len=%d\n",
+				nr, (end - p), len);
 			break;
 		}
 		if (len > NFS_MAXNAMLEN) {
diff -u --recursive --new-file v2.1.81/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.1.81/linux/fs/nfs/write.c	Tue Jan 20 12:11:58 1998
+++ linux/fs/nfs/write.c	Sat Jan 24 10:53:00 1998
@@ -46,7 +46,6 @@
  * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
  */
 
-#define NFS_NEED_XDR_TYPES
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/malloc.h>
@@ -372,8 +371,8 @@
 create_write_request(struct dentry *dentry, struct inode *inode,
 		struct page *page, unsigned int offset, unsigned int bytes)
 {
-	struct nfs_wreq *wreq;
 	struct rpc_clnt	*clnt = NFS_CLIENT(inode);
+	struct nfs_wreq *wreq;
 	struct rpc_task	*task;
 
 	dprintk("NFS:      create_write_request(%s/%s, %ld+%d)\n",
@@ -424,7 +423,7 @@
  * Schedule a writeback RPC call.
  * If the server is congested, don't add to our backlog of queued
  * requests but call it synchronously.
- * The function returns true if the page has been unlocked as the
+ * The function returns false if the page has been unlocked as the
  * consequence of a synchronous write call.
  *
  * FIXME: Here we could walk the inode's lock list to see whether the
@@ -642,15 +641,16 @@
 
 	req = head = NFS_WRITEBACK(inode);
 	while (req != NULL) {
-		dprintk("NFS: %4d nfs_flush inspect %x/%ld @%ld fl %x\n",
-				req->wb_task.tk_pid,
-				req->wb_inode->i_dev, req->wb_inode->i_ino,
-				req->wb_page->offset, req->wb_flags);
+		dprintk("NFS: %4d nfs_flush inspect %s/%s @%ld fl %x\n",
+			req->wb_task.tk_pid,
+			req->wb_dentry->d_parent->d_name.name,
+			req->wb_dentry->d_name.name,
+			req->wb_page->offset, req->wb_flags);
+
 		rqoffset = req->wb_page->offset + req->wb_offset;
 		rqend    = rqoffset + req->wb_bytes;
-		
-		if (rqoffset < end && offset < rqend
-			 && (pid == 0 || req->wb_pid == pid)) {
+		if (rqoffset < end && offset < rqend &&
+		    (pid == 0 || req->wb_pid == pid)) {
 			if (!WB_INPROGRESS(req) && !WB_HAVELOCK(req)) {
 #ifdef NFS_DEBUG_VERBOSE
 printk("nfs_flush: flushing inode=%ld, %d @ %lu\n",
@@ -670,11 +670,23 @@
 }
 
 /*
+ * Cancel a write request. We always mark it cancelled,
+ * but if it's already in progress there's no point in
+ * calling rpc_exit, and we don't want to overwrite the
+ * tk_status field.
+ */ 
+static void
+nfs_cancel_request(struct nfs_wreq *req)
+{
+	req->wb_flags |= NFS_WRITE_CANCELLED;
+	if (!WB_INPROGRESS(req)) {
+		rpc_exit(&req->wb_task, 0);
+		rpc_wake_up_task(&req->wb_task);
+	}
+}
+
+/*
  * Cancel all writeback requests, both pending and in progress.
- *
- * N.B. This doesn't seem to wake up the tasks -- are we sure
- * they will eventually complete? Also, this could overwrite a
- * failed status code from an already-completed task.
  */
 static void
 nfs_cancel_dirty(struct inode *inode, pid_t pid)
@@ -683,11 +695,8 @@
 
 	req = head = NFS_WRITEBACK(inode);
 	while (req != NULL) {
-		/* N.B. check for task already finished? */
-		if (pid == 0 || req->wb_pid == pid) {
-			req->wb_flags |= NFS_WRITE_CANCELLED;
-			rpc_exit(&req->wb_task, 0);
-		}
+		if (pid == 0 || req->wb_pid == pid)
+			nfs_cancel_request(req);
 		if ((req = WB_NEXT(req)) == head)
 			break;
 	}
@@ -708,8 +717,7 @@
 	int result = 0, cancel = 0;
 
 	dprintk("NFS:      flush_dirty_pages(%x/%ld for pid %d %ld/%ld)\n",
-				inode->i_dev, inode->i_ino, current->pid,
-				offset, len);
+		inode->i_dev, inode->i_ino, current->pid, offset, len);
 
 	if (IS_SOFT && signalled()) {
 		nfs_cancel_dirty(inode, pid);
@@ -762,16 +770,15 @@
 	struct nfs_wreq *req, *head;
 	unsigned long	rqoffset;
 
-	dprintk("NFS:      truncate_dirty_pages(%x/%ld, %ld)\n",
-				inode->i_dev, inode->i_ino, offset);
+	dprintk("NFS:      truncate_dirty_pages(%d/%ld, %ld)\n",
+		inode->i_dev, inode->i_ino, offset);
 
 	req = head = NFS_WRITEBACK(inode);
 	while (req != NULL) {
 		rqoffset = req->wb_page->offset + req->wb_offset;
 
 		if (rqoffset >= offset) {
-			req->wb_flags |= NFS_WRITE_CANCELLED;
-			rpc_exit(&req->wb_task, 0);
+			nfs_cancel_request(req);
 		} else if (rqoffset + req->wb_bytes >= offset) {
 			req->wb_bytes = offset - rqoffset;
 		}
@@ -831,24 +838,13 @@
 	req->wb_flags |=  NFS_WRITE_LOCKED;
 	task->tk_status = 0;
 
-	if (req->wb_args == 0) {
-		size_t	size = sizeof(struct nfs_writeargs)
-			     + sizeof(struct nfs_fattr);
-		void	*ptr;
-
-		if (!(ptr = kmalloc(size, GFP_KERNEL)))
-			goto out_no_args;
-		req->wb_args = (struct nfs_writeargs *) ptr;
-		req->wb_fattr = (struct nfs_fattr *) (req->wb_args + 1);
-	}
-
 	/* Setup the task struct for a writeback call */
-	req->wb_args->fh = NFS_FH(dentry);
-	req->wb_args->offset = page->offset + req->wb_offset;
-	req->wb_args->count  = req->wb_bytes;
-	req->wb_args->buffer = (void *) (page_address(page) + req->wb_offset);
+	req->wb_args.fh     = NFS_FH(dentry);
+	req->wb_args.offset = page->offset + req->wb_offset;
+	req->wb_args.count  = req->wb_bytes;
+	req->wb_args.buffer = (void *) (page_address(page) + req->wb_offset);
 
-	rpc_call_setup(task, NFSPROC_WRITE, req->wb_args, req->wb_fattr, 0);
+	rpc_call_setup(task, NFSPROC_WRITE, &req->wb_args, &req->wb_fattr, 0);
 
 	req->wb_flags |= NFS_WRITE_INPROGRESS;
 	return;
@@ -858,11 +854,6 @@
 	task->tk_timeout = 2 * HZ;
 	rpc_sleep_on(&write_queue, task, NULL, NULL);
 	return;
-out_no_args:
-	printk("NFS: can't alloc args, sleeping\n");
-	task->tk_timeout = HZ;
-	rpc_sleep_on(&write_queue, task, NULL, NULL);
-	return;
 }
 
 /*
@@ -880,7 +871,7 @@
 		task->tk_pid, req->wb_dentry->d_parent->d_name.name,
 		req->wb_dentry->d_name.name, status, req->wb_flags);
 
-	/* Set the WRITE_COMPLETE flag, but leave INPROGRESS set */
+	/* Set the WRITE_COMPLETE flag, but leave WRITE_INPROGRESS set */
 	req->wb_flags |= NFS_WRITE_COMPLETE;
 	if (status < 0) {
 		/*
@@ -892,7 +883,7 @@
 			status = 0;
 		clear_bit(PG_uptodate, &page->flags);
 	} else if (!WB_CANCELLED(req)) {
-		struct nfs_fattr *fattr = req->wb_fattr;
+		struct nfs_fattr *fattr = &req->wb_fattr;
 		/* Update attributes as result of writeback. 
 		 * Beware: when UDP replies arrive out of order, we
 		 * may end up overwriting a previous, bigger file size.
@@ -927,11 +918,6 @@
 		clear_bit(PG_uptodate, &page->flags);
 	if (WB_HAVELOCK(req))
 		nfs_unlock_page(page);
-
-	if (req->wb_args) {
-		kfree(req->wb_args);
-		req->wb_args = 0;
-	}
 
 	/*
 	 * Now it's safe to remove the request from the inode's 
diff -u --recursive --new-file v2.1.81/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- v2.1.81/linux/fs/nfsd/nfsproc.c	Mon Jan 12 14:39:48 1998
+++ linux/fs/nfsd/nfsproc.c	Sun Jan 25 10:07:33 1998
@@ -27,12 +27,6 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
-#define sleep(msec)		\
-	{	printk(KERN_NOTICE "nfsd: sleeping %d msecs\n", msec); \
-		current->state = TASK_INTERRUPTIBLE;	\
-		current->timeout = jiffies + msec / 10;	\
-		schedule();	\
-	}
 #define RETURN(st)	return st
 
 static void
@@ -298,11 +292,6 @@
 		 * size, so that creat() behaves exactly like
 		 * open(..., O_CREAT|O_TRUNC|O_WRONLY).
 		 */
-#if 0
-		/* N.B. What is this doing? ignores size?? */
-		if ((attr->ia_valid &= ~(ATTR_SIZE)) != 0)
-			nfserr = nfsd_setattr(rqstp, newfhp, attr);
-#endif
 		attr->ia_valid &= ATTR_SIZE;
 		if (attr->ia_valid)
 			nfserr = nfsd_setattr(rqstp, newfhp, attr);
@@ -435,22 +424,25 @@
 	u32 *	buffer;
 	int	nfserr, count;
 
-	dprintk("nfsd: READDIR  %p %d bytes at %d\n",
-		SVCFH_DENTRY(&argp->fh),
+	dprintk("nfsd: READDIR  %d/%ld %d bytes at %d\n",
+		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
 		argp->count, argp->cookie);
 
 	/* Reserve buffer space for status */
 	svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &count, 1);
 
-	/* Make sure we've room for the NULL ptr & eof flag, and shrink to
-	 * client read size */
-	if ((count -= 8) > argp->count)
-		count = argp->count;
+	/* Shrink to the client read size */
+	if (count > (argp->count >> 2))
+		count = argp->count >> 2;
+
+	/* Make sure we've room for the NULL ptr & eof flag */
+	count -= 2;
+	if (count < 0)
+		count = 0;
 
 	/* Read directory and encode entries on the fly */
 	nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie, 
-					nfssvc_encode_entry,
-					buffer, &count);
+				nfssvc_encode_entry, buffer, &count);
 	resp->count = count;
 
 	fh_put(&argp->fh);
diff -u --recursive --new-file v2.1.81/linux/fs/nfsd/nfssvc.c linux/fs/nfsd/nfssvc.c
--- v2.1.81/linux/fs/nfsd/nfssvc.c	Fri Jan 23 18:10:32 1998
+++ linux/fs/nfsd/nfssvc.c	Sun Jan 25 10:07:33 1998
@@ -97,8 +97,8 @@
 
 	oldumask = current->fs->umask;		/* Set umask to 0.  */
 	current->fs->umask = 0;
-	nfssvc_boot = xtime;			/* record boot time */
-	nfsd_active++;
+	if (!nfsd_active++)
+		nfssvc_boot = xtime;		/* record boot time */
 	lockd_up();				/* start lockd */
 
 	/*
diff -u --recursive --new-file v2.1.81/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.1.81/linux/fs/nfsd/vfs.c	Mon Jan 12 14:39:48 1998
+++ linux/fs/nfsd/vfs.c	Sun Jan 25 10:07:33 1998
@@ -1041,7 +1041,7 @@
 	memset(&cd, 0, sizeof(cd));
 	cd.rqstp  = rqstp;
 	cd.buffer = buffer;
-	cd.buflen = *countp >> 2;
+	cd.buflen = *countp; /* count of words */
 
 	/*
 	 * Read the directory entries. This silly loop is necessary because
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_cp862.c linux/fs/nls/nls_cp862.c
--- v2.1.81/linux/fs/nls/nls_cp862.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_cp862.c	Sun Jan 25 10:05:47 1998
@@ -391,6 +391,7 @@
 	page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -425,7 +426,7 @@
 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_cp863.c linux/fs/nls/nls_cp863.c
--- v2.1.81/linux/fs/nls/nls_cp863.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_cp863.c	Sun Jan 25 10:05:47 1998
@@ -355,6 +355,7 @@
 	page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -389,7 +390,7 @@
 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_cp864.c linux/fs/nls/nls_cp864.c
--- v2.1.81/linux/fs/nls/nls_cp864.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_cp864.c	Sun Jan 25 10:05:47 1998
@@ -346,6 +346,7 @@
 	NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   pagefe, NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -380,7 +381,7 @@
 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_cp865.c linux/fs/nls/nls_cp865.c
--- v2.1.81/linux/fs/nls/nls_cp865.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_cp865.c	Sun Jan 25 10:05:47 1998
@@ -355,6 +355,7 @@
 	page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -389,7 +390,7 @@
 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_cp866.c linux/fs/nls/nls_cp866.c
--- v2.1.81/linux/fs/nls/nls_cp866.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_cp866.c	Sun Jan 25 10:05:47 1998
@@ -283,6 +283,7 @@
 	NULL,   page21, page22, NULL,   NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -317,7 +318,7 @@
 	0xf0, 0x00, 0xf2, 0x00, 0xf4, 0x00, 0xf6, 0x00, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_cp869.c linux/fs/nls/nls_cp869.c
--- v2.1.81/linux/fs/nls/nls_cp869.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_cp869.c	Sun Jan 25 10:05:47 1998
@@ -247,6 +247,7 @@
 	page20, NULL,   NULL,   NULL,   NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -281,7 +282,7 @@
 	0xf0, 0xf1, 0x00, 0x00, 0x00, 0xf5, 0x00, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_cp874.c linux/fs/nls/nls_cp874.c
--- v2.1.81/linux/fs/nls/nls_cp874.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_cp874.c	Sun Jan 25 10:05:47 1998
@@ -211,6 +211,7 @@
 	page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -245,7 +246,7 @@
 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-1.c linux/fs/nls/nls_iso8859-1.c
--- v2.1.81/linux/fs/nls/nls_iso8859-1.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-1.c	Sun Jan 25 10:05:47 1998
@@ -135,6 +135,7 @@
 	page00, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -169,7 +170,7 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-2.c linux/fs/nls/nls_iso8859-2.c
--- v2.1.81/linux/fs/nls/nls_iso8859-2.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-2.c	Sun Jan 25 10:05:47 1998
@@ -207,6 +207,7 @@
 	page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -241,7 +242,7 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-3.c linux/fs/nls/nls_iso8859-3.c
--- v2.1.81/linux/fs/nls/nls_iso8859-3.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-3.c	Sun Jan 25 10:05:47 1998
@@ -207,6 +207,7 @@
 	page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -241,7 +242,7 @@
 	0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-4.c linux/fs/nls/nls_iso8859-4.c
--- v2.1.81/linux/fs/nls/nls_iso8859-4.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-4.c	Sun Jan 25 10:05:47 1998
@@ -207,6 +207,7 @@
 	page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -241,7 +242,7 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-5.c linux/fs/nls/nls_iso8859-5.c
--- v2.1.81/linux/fs/nls/nls_iso8859-5.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-5.c	Sun Jan 25 10:05:47 1998
@@ -211,6 +211,7 @@
 	NULL,   page21, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -245,7 +246,7 @@
 	0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-6.c linux/fs/nls/nls_iso8859-6.c
--- v2.1.81/linux/fs/nls/nls_iso8859-6.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-6.c	Sun Jan 25 10:05:47 1998
@@ -171,6 +171,7 @@
 	page00, NULL,   NULL,   NULL,   NULL,   NULL,   page06, NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -205,7 +206,7 @@
 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-7.c linux/fs/nls/nls_iso8859-7.c
--- v2.1.81/linux/fs/nls/nls_iso8859-7.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-7.c	Sun Jan 25 10:05:47 1998
@@ -247,6 +247,7 @@
 	page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -281,7 +282,7 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-8.c linux/fs/nls/nls_iso8859-8.c
--- v2.1.81/linux/fs/nls/nls_iso8859-8.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-8.c	Sun Jan 25 10:05:47 1998
@@ -211,6 +211,7 @@
 	page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -245,7 +246,7 @@
 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_iso8859-9.c linux/fs/nls/nls_iso8859-9.c
--- v2.1.81/linux/fs/nls/nls_iso8859-9.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_iso8859-9.c	Sun Jan 25 10:05:47 1998
@@ -171,6 +171,7 @@
 	page00, page01, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -205,7 +206,7 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/nls/nls_koi8-r.c linux/fs/nls/nls_koi8-r.c
--- v2.1.81/linux/fs/nls/nls_koi8-r.c	Thu Oct 23 14:00:15 1997
+++ linux/fs/nls/nls_koi8-r.c	Sun Jan 25 10:05:47 1998
@@ -283,6 +283,7 @@
 	NULL,   NULL,   page22, page23, NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -317,7 +318,7 @@
 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
diff -u --recursive --new-file v2.1.81/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.1.81/linux/fs/proc/array.c	Fri Jan 23 18:10:32 1998
+++ linux/fs/proc/array.c	Mon Jan 26 11:43:19 1998
@@ -1149,7 +1149,7 @@
 extern int get_irq_list(char *);
 extern int get_dma_list(char *);
 extern int get_cpuinfo(char *);
-extern int get_pci_list(char*);
+extern int get_pci_list(char *);
 extern int get_md_status (char *);
 extern int get_rtc_status (char *);
 extern int get_locks_status (char *, char **, off_t, int);
@@ -1174,7 +1174,7 @@
 		case PROC_MEMINFO:
 			return get_meminfo(page);
 
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_OLD_PROC
   	        case PROC_PCI:
 			return get_pci_list(page);
 #endif
diff -u --recursive --new-file v2.1.81/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.81/linux/fs/proc/root.c	Fri Jan 23 18:10:32 1998
+++ linux/fs/proc/root.c	Mon Jan 26 11:43:19 1998
@@ -152,7 +152,7 @@
 	&proc_root, NULL
 };
 
-struct proc_dir_entry *proc_net, *proc_scsi;
+struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus;
 
 #ifdef CONFIG_MCA
 struct proc_dir_entry proc_mca = {
@@ -636,7 +636,6 @@
 	NULL, NULL,                		/* get_info, fill_inode */
 	NULL,					/* next */
 	NULL, NULL				/* parent, subdir */
-
 };
 #endif
 
@@ -712,6 +711,11 @@
 #endif
 #ifdef CONFIG_PROC_DEVICETREE
 	proc_device_tree_init();
+#endif
+
+	proc_bus = create_proc_entry("bus", S_IFDIR, 0);
+#ifdef CONFIG_PCI
+	proc_bus_pci_init();
 #endif
 }
 
diff -u --recursive --new-file v2.1.81/linux/fs/sysv/CHANGES linux/fs/sysv/CHANGES
--- v2.1.81/linux/fs/sysv/CHANGES	Wed Dec 31 16:00:00 1969
+++ linux/fs/sysv/CHANGES	Mon Jan 26 14:53:45 1998
@@ -0,0 +1,9 @@
+Mon Dec 15 1997	  Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
+	*    namei.c: struct sysv_dir_inode_operations updated to use dentries.
+
+Fri Jan 23 1998   Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
+	*    inode.c: corrected 1 track offset setting (in sb->sv_block_base).
+		      Originally it was overriden (by setting to zero)
+		      in detected_[xenix,sysv4,sysv2,coherent]. Thanks
+		      to Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
+		      for identifying the problem.
diff -u --recursive --new-file v2.1.81/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.1.81/linux/fs/sysv/inode.c	Tue Jan  6 09:48:03 1998
+++ linux/fs/sysv/inode.c	Mon Jan 26 14:53:45 1998
@@ -168,7 +168,6 @@
 	sb->sv_sb_flc_blocks = &sbd1->s_free[0];
 	sb->sv_sb_total_free_blocks = &sbd2->s_tfree;
 	sb->sv_sb_time = &sbd2->s_time;
-	sb->sv_block_base = 0;
 	sb->sv_firstinodezone = 2;
 	sb->sv_firstdatazone = sbd1->s_isize;
 	sb->sv_nzones = sbd1->s_fsize;
@@ -226,7 +225,6 @@
 	sb->sv_sb_total_free_blocks = &sbd->s_tfree;
 	sb->sv_sb_time = &sbd->s_time;
 	sb->sv_sb_state = &sbd->s_state;
-	sb->sv_block_base = 0;
 	sb->sv_firstinodezone = 2;
 	sb->sv_firstdatazone = sbd->s_isize;
 	sb->sv_nzones = sbd->s_fsize;
@@ -284,7 +282,6 @@
 	sb->sv_sb_total_free_blocks = &sbd->s_tfree;
 	sb->sv_sb_time = &sbd->s_time;
 	sb->sv_sb_state = &sbd->s_state;
-	sb->sv_block_base = 0;
 	sb->sv_firstinodezone = 2;
 	sb->sv_firstdatazone = sbd->s_isize;
 	sb->sv_nzones = sbd->s_fsize;
@@ -331,7 +328,6 @@
 	sb->sv_sb_flc_blocks = &sbd->s_free[0];
 	sb->sv_sb_total_free_blocks = &sbd->s_tfree;
 	sb->sv_sb_time = &sbd->s_time;
-	sb->sv_block_base = 0;
 	sb->sv_firstinodezone = 2;
 	sb->sv_firstdatazone = sbd->s_isize;
 	sb->sv_nzones = from_coh_ulong(sbd->s_fsize);
@@ -359,6 +355,7 @@
 	MOD_INC_USE_COUNT;
 	lock_super(sb);
 	set_blocksize(dev,BLOCK_SIZE);
+	sb->sv_block_base = 0;
 
 	/* Try to read Xenix superblock */
 	if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) {
diff -u --recursive --new-file v2.1.81/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.1.81/linux/fs/sysv/namei.c	Tue Jan  6 09:48:04 1998
+++ linux/fs/sysv/namei.c	Mon Jan 26 14:53:45 1998
@@ -10,11 +10,8 @@
  *  sysv/namei.c
  *  Copyright (C) 1993  Bruno Haible
  *
- *
- *  Revised: 15 Dec 1997 by Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
- *    Driver updated to use dentries.
  */
-	 
+
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.81/linux/fs/ufs/ufs_swab.c linux/fs/ufs/ufs_swab.c
--- v2.1.81/linux/fs/ufs/ufs_swab.c	Sun Nov  9 06:36:42 1997
+++ linux/fs/ufs/ufs_swab.c	Sun Jan 25 10:05:47 1998
@@ -117,8 +117,8 @@
 	be32_to_cpus(&usb->fs_cpc);
         be16_to_cpus__between(*usb,fs_opostbl,fs_sparecon);
         be32_to_cpus__between(*usb,fs_sparecon,fs_qbmask);
-        be64_to_cpus(&usb->fs_qbmask);
-        be64_to_cpus(&usb->fs_qfmask);
+        be64_to_cpus((__u64 *) &usb->fs_qbmask);
+        be64_to_cpus((__u64 *) &usb->fs_qfmask);
 	be32_to_cpus__between(*usb,fs_postblformat,fs_magic);
 #endif
 }
diff -u --recursive --new-file v2.1.81/linux/include/asm-alpha/mman.h linux/include/asm-alpha/mman.h
--- v2.1.81/linux/include/asm-alpha/mman.h	Mon Oct  7 02:40:22 1996
+++ linux/include/asm-alpha/mman.h	Sun Jan 25 16:31:47 1998
@@ -13,9 +13,9 @@
 #define MAP_ANONYMOUS	0x10		/* don't use a file */
 
 /* not used by linux, but here to make sure we don't clash with OSF/1 defines */
-#define MAP_HASSEMAPHORE 0x0200
-#define MAP_INHERIT	0x0400
-#define MAP_UNALIGNED	0x0800
+#define _MAP_HASSEMAPHORE 0x0200
+#define _MAP_INHERIT	0x0400
+#define _MAP_UNALIGNED	0x0800
 
 /* These are linux-specific */
 #define MAP_GROWSDOWN	0x1000		/* stack-like segment */
diff -u --recursive --new-file v2.1.81/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h
--- v2.1.81/linux/include/asm-alpha/smp.h	Sun Dec  1 11:39:49 1996
+++ linux/include/asm-alpha/smp.h	Sat Jan 24 14:22:07 1998
@@ -1,6 +1,8 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
+#define cpu_logical_map(cpu)	(cpu)
+
 /* We'll get here eventually.. */
 
 #endif
diff -u --recursive --new-file v2.1.81/linux/include/asm-alpha/softirq.h linux/include/asm-alpha/softirq.h
--- v2.1.81/linux/include/asm-alpha/softirq.h	Mon Nov 17 08:36:20 1997
+++ linux/include/asm-alpha/softirq.h	Sat Jan 24 14:22:33 1998
@@ -80,10 +80,10 @@
 #ifndef __SMP__
 
 /* These are for the irq's testing the lock */
-#define softirq_trylock()	(atomic_read(&__alpha_bh_counter) ? \
+#define softirq_trylock(cpu)	(atomic_read(&__alpha_bh_counter) ? \
 				0 : \
 				((atomic_set(&__alpha_bh_counter,1)),1))
-#define softirq_endlock()	(atomic_set(&__alpha_bh_counter, 0))
+#define softirq_endlock(cpu)	(atomic_set(&__alpha_bh_counter, 0))
 
 #else
 
diff -u --recursive --new-file v2.1.81/linux/include/asm-alpha/types.h linux/include/asm-alpha/types.h
--- v2.1.81/linux/include/asm-alpha/types.h	Tue Mar 26 06:47:39 1996
+++ linux/include/asm-alpha/types.h	Mon Jan 26 11:43:18 1998
@@ -63,11 +63,13 @@
 
 typedef signed long long s64;
 typedef unsigned long long u64;
+#define BITS_PER_LONG 32
 
 #else
 
 typedef signed long s64;
 typedef unsigned long u64;
+#define BITS_PER_LONG 64
 
 #endif
 
diff -u --recursive --new-file v2.1.81/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v2.1.81/linux/include/asm-alpha/unistd.h	Mon Dec 22 09:58:21 1997
+++ linux/include/asm-alpha/unistd.h	Sun Jan 25 16:28:02 1998
@@ -156,7 +156,7 @@
 #define __NR_osf_pid_block	153	/* not implemented */
 #define __NR_osf_pid_unblock	154	/* not implemented */
 
-#define __NR_osf_sigaction	156
+#define __NR_sigaction		156
 #define __NR_osf_sigwaitprim	157	/* not implemented */
 #define __NR_osf_nfssvc		158	/* not implemented */
 #define __NR_osf_getdirentries	159
@@ -186,7 +186,7 @@
 #define __NR_semget		205
 #define __NR_semop		206
 #define __NR_osf_utsname	207
-#define __NR_osf_lchown		208	/* not implemented */
+#define __NR_lchown		208
 #define __NR_osf_shmat		209
 #define __NR_shmctl		210
 #define __NR_shmdt		211
diff -u --recursive --new-file v2.1.81/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h
--- v2.1.81/linux/include/asm-i386/softirq.h	Fri Jan 23 18:10:32 1998
+++ linux/include/asm-i386/softirq.h	Fri Jan 23 20:31:10 1998
@@ -91,8 +91,8 @@
 }
 
 /* These are for the irq's testing the lock */
-#define softirq_trylock()	(in_bh ? 0 : (local_bh_count[smp_processor_id()]=1))
-#define softirq_endlock()	(local_bh_count[smp_processor_id()] = 0)
+#define softirq_trylock(cpu)	(in_bh() ? 0 : (local_bh_count[smp_processor_id()]=1))
+#define softirq_endlock(cpu)	(local_bh_count[smp_processor_id()] = 0)
 #define synchronize_bh()	do { } while (0)
 
 #endif	/* SMP */
diff -u --recursive --new-file v2.1.81/linux/include/asm-i386/types.h linux/include/asm-i386/types.h
--- v2.1.81/linux/include/asm-i386/types.h	Tue Mar 26 06:47:23 1996
+++ linux/include/asm-i386/types.h	Mon Jan 26 11:43:18 1998
@@ -39,6 +39,8 @@
 typedef signed long long s64;
 typedef unsigned long long u64;
 
+#define BITS_PER_LONG 32
+
 #endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.1.81/linux/include/asm-m68k/types.h linux/include/asm-m68k/types.h
--- v2.1.81/linux/include/asm-m68k/types.h	Fri Apr  5 03:08:41 1996
+++ linux/include/asm-m68k/types.h	Mon Jan 26 11:43:18 1998
@@ -47,6 +47,8 @@
 typedef signed long long s64;
 typedef unsigned long long u64;
 
+#define BITS_PER_LONG 32
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_TYPES_H */
diff -u --recursive --new-file v2.1.81/linux/include/asm-mips/types.h linux/include/asm-mips/types.h
--- v2.1.81/linux/include/asm-mips/types.h	Thu Jun 26 12:33:40 1997
+++ linux/include/asm-mips/types.h	Mon Jan 26 11:43:18 1998
@@ -60,11 +60,13 @@
 typedef __signed__ long long s64;
 typedef unsigned long long u64;
 #endif
+#define BITS_PER_LONG 32
   
 #else
   
 typedef __signed__ long s64;
 typedef unsigned long u64;
+#define BITS_PER_LONG 64
 
 #endif
 
diff -u --recursive --new-file v2.1.81/linux/include/linux/adfs_fs.h linux/include/linux/adfs_fs.h
--- v2.1.81/linux/include/linux/adfs_fs.h	Tue Jan 20 16:44:58 1998
+++ linux/include/linux/adfs_fs.h	Mon Jan 26 13:52:55 1998
@@ -156,7 +156,7 @@
 extern unsigned long adfs_inode_generate (unsigned long parent_id, int diridx);
 extern unsigned long adfs_inode_objid (struct inode *inode);
 extern unsigned int adfs_parent_bmap (struct inode *inode, int block);
-extern unsigned int adfs_bmap (struct inode *inode, int block);
+extern int adfs_bmap (struct inode *inode, int block);
 extern void adfs_read_inode (struct inode *inode);
 
 /* map.c */
diff -u --recursive --new-file v2.1.81/linux/include/linux/adfs_fs_fs.h linux/include/linux/adfs_fs_fs.h
--- v2.1.81/linux/include/linux/adfs_fs_fs.h	Tue Jan 20 16:44:58 1998
+++ linux/include/linux/adfs_fs_fs.h	Sun Jan 25 10:05:47 1998
@@ -148,7 +148,7 @@
 extern unsigned long adfs_inode_generate (unsigned long parent_id, int diridx);
 extern unsigned long adfs_inode_objid (struct inode *inode);
 extern unsigned int adfs_parent_bmap (struct inode *inode, int block);
-extern unsigned int adfs_bmap (struct inode *inode, int block);
+extern int adfs_bmap (struct inode *inode, int block);
 extern void adfs_read_inode (struct inode *inode);
 
 /* map.c */
diff -u --recursive --new-file v2.1.81/linux/include/linux/affs_fs.h linux/include/linux/affs_fs.h
--- v2.1.81/linux/include/linux/affs_fs.h	Mon Jan 12 14:46:26 1998
+++ linux/include/linux/affs_fs.h	Mon Jan 26 13:55:17 1998
@@ -89,6 +89,7 @@
 /* super.c */
 
 extern int			 affs_fs(void);
+extern int			 init_affs_fs(void);
 
 /* file.c */
 
diff -u --recursive --new-file v2.1.81/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.1.81/linux/include/linux/isdn.h	Mon Nov  3 10:09:22 1997
+++ linux/include/linux/isdn.h	Sun Jan 25 10:05:47 1998
@@ -425,25 +425,11 @@
   struct isdn_net_dev_s  *netdev;      /* Ptr to netdev                    */
   struct sk_buff         *first_skb;   /* Ptr to skb that triggers dialing */
   struct sk_buff         *sav_skb;     /* Ptr to skb, rejected by LL-driver*/
-#if (LINUX_VERSION_CODE < 0x02010F)
-                                       /* Ptr to orig. header_cache_bind   */
-  void                   (*org_hcb)(struct hh_cache **,
-				    struct device *,
-                                    unsigned short, 
-				    __u32);
-#else
-#if (LINUX_VERSION_CODE < 0x2011E)
+
                                        /* Ptr to orig. hard_header_cache   */
-  int                    (*org_hhc)(struct dst_entry *dst,
-				    struct dst_entry *neigh,
+  int                    (*org_hhc)(struct neighbour *neigh,
 				    struct hh_cache *hh);
-#else
-                                       /* Ptr to orig. hard_header_cache   */
-  int                    (*org_hhc)(struct dst_entry *dst,
-				    struct neighbour *neigh,
-				    struct hh_cache *hh);
-#endif
-#endif
+
                                        /* Ptr to orig. header_cache_update */
   void                   (*org_hcu)(struct hh_cache *,
 				    struct device *,
diff -u --recursive --new-file v2.1.81/linux/include/linux/lp.h linux/include/linux/lp.h
--- v2.1.81/linux/include/linux/lp.h	Tue Aug 26 14:52:45 1997
+++ linux/include/linux/lp.h	Fri Jan 23 20:04:03 1998
@@ -7,6 +7,11 @@
  * Interrupt support added 1993 Nigel Gamble
  */
 
+/* Magic numbers for defining port-device mappings */
+#define LP_PARPORT_AUTO -3
+#define LP_PARPORT_OFF -2
+#define LP_PARPORT_UNSPEC -1
+
 /*
  * Per POSIX guidelines, this module reserves the LP and lp prefixes
  * These are the lp_table[minor].flags flags...
@@ -89,20 +94,6 @@
 
 #define LP_BASE(x)	lp_table[(x)].dev->port->base
 
-#define r_dtr(x)	inb(LP_BASE(x))
-#define r_str(x)	inb(LP_BASE(x)+1)
-#define r_ctr(x)	inb(LP_BASE(x)+2)
-#define r_epp(x)	inb(LP_BASE(x)+4)
-#define r_fifo(x)	inb(LP_BASE(x)+0x400)
-#define r_ecr(x)	inb(LP_BASE(x)+0x402)
-
-#define w_dtr(x,y)	outb((y), LP_BASE(x))
-#define w_str(x,y)	outb((y), LP_BASE(x)+1)
-#define w_ctr(x,y)	outb((y), LP_BASE(x)+2)
-#define w_epp(x,y)	outb((y), LP_BASE(x)+4)
-#define w_fifo(x,y)	outb((y), LP_BASE(x)+0x400)
-#define w_ecr(x,y)	outb((y), LP_BASE(x)+0x402)
-
 struct lp_stats {
 	unsigned long chars;
 	unsigned long sleeps;
@@ -118,12 +109,10 @@
 	unsigned int chars;
 	unsigned int time;
 	unsigned int wait;
-	struct wait_queue *lp_wait_q;
 	char *lp_buffer;
 	unsigned int lastcall;
 	unsigned int runchars;
 	unsigned int waittime;
-	unsigned int should_relinquish;
 	struct lp_stats stats;
 };
 
@@ -169,6 +158,9 @@
  * It is used only in the lp_init() and lp_reset() routine.
  */
 #define LP_DELAY 	50
+
+#define LP_POLLING(minor) (lp_table[(minor)].dev->port->irq == PARPORT_IRQ_NONE)
+#define LP_PREEMPTED(minor) (lp_table[(minor)].dev->port->waithead != NULL)
 
 /*
  * function prototypes
diff -u --recursive --new-file v2.1.81/linux/include/linux/nfs.h linux/include/linux/nfs.h
--- v2.1.81/linux/include/linux/nfs.h	Sat Dec 20 21:06:01 1997
+++ linux/include/linux/nfs.h	Sat Jan 24 10:53:00 1998
@@ -138,6 +138,13 @@
 	__u32			bavail;
 };
 
+struct nfs_writeargs {
+	struct nfs_fh *		fh;
+	__u32			offset;
+	__u32			count;
+	const void *		buffer;
+};
+
 #ifdef NFS_NEED_XDR_TYPES
 
 struct nfs_sattrargs {
@@ -155,13 +162,6 @@
 	__u32			offset;
 	__u32			count;
 	void *			buffer;
-};
-
-struct nfs_writeargs {
-	struct nfs_fh *		fh;
-	__u32			offset;
-	__u32			count;
-	const void *		buffer;
 };
 
 struct nfs_createargs {
diff -u --recursive --new-file v2.1.81/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.1.81/linux/include/linux/nfs_fs.h	Tue Jan 20 16:52:02 1998
+++ linux/include/linux/nfs_fs.h	Mon Jan 26 14:29:15 1998
@@ -103,8 +103,8 @@
 	pid_t			wb_pid;		/* owner process */
 	unsigned short		wb_flags;	/* status flags */
 
-	struct nfs_writeargs *	wb_args;	/* NFS RPC stuff */
-	struct nfs_fattr *	wb_fattr;	/* file attributes */
+	struct nfs_writeargs	wb_args;	/* NFS RPC stuff */
+	struct nfs_fattr	wb_fattr;	/* file attributes */
 };
 #define wb_status		wb_task.tk_status
 
@@ -177,8 +177,8 @@
  */
 extern struct super_block *nfs_read_super(struct super_block *, void *, int);
 extern int init_nfs_fs(void);
-extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
-			       struct nfs_fattr *);
+extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
+				struct nfs_fattr *);
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_revalidate(struct dentry *);
 extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *);
diff -u --recursive --new-file v2.1.81/linux/include/linux/nfs_fs_i.h linux/include/linux/nfs_fs_i.h
--- v2.1.81/linux/include/linux/nfs_fs_i.h	Sun Jan  4 00:53:40 1998
+++ linux/include/linux/nfs_fs_i.h	Sat Jan 24 10:53:00 1998
@@ -53,6 +53,7 @@
  * Legal inode flag values
  */
 #define NFS_INO_REVALIDATE	0x0001		/* revalidating attrs */
+#define NFS_IS_SNAPSHOT		0x0010		/* a snapshot file */
 
 /*
  * NFS lock info
diff -u --recursive --new-file v2.1.81/linux/include/linux/nls.h linux/include/linux/nls.h
--- v2.1.81/linux/include/linux/nls.h	Thu Oct 23 14:00:15 1997
+++ linux/include/linux/nls.h	Sun Jan 25 10:05:47 1998
@@ -52,3 +52,4 @@
 extern int init_nls_cp866(void);
 extern int init_nls_cp869(void);
 extern int init_nls_cp874(void);
+extern int init_nls_koi8_r(void);
diff -u --recursive --new-file v2.1.81/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.1.81/linux/include/linux/parport.h	Sat Nov 29 16:19:47 1997
+++ linux/include/linux/parport.h	Fri Jan 23 20:04:03 1998
@@ -1,11 +1,15 @@
-/* $Id: parport.h,v 1.3 1997/10/19 18:02:00 phil Exp $ */
+/* $Id: parport.h,v 1.6 1997/12/29 12:31:05 phil Exp $ */
 
 #ifndef _PARPORT_H_
 #define _PARPORT_H_
 
 #include <asm/system.h>
 #include <asm/ptrace.h>
+#include <asm/spinlock.h>
 #include <linux/proc_fs.h>
+#include <linux/config.h>
+
+#define PARPORT_NEED_GENERIC_OPS
 
 /* Maximum of 8 ports per machine */
 #define PARPORT_MAX  8 
@@ -29,27 +33,11 @@
 	union {
 		struct pc_parport_state pc;
 		/* ARC has no state. */
+		/* AX uses same state information as PC */
 		void *misc; 
 	} u;
 };
 
-/* Generic operations vector through the dispatch table. */
-#define parport_write_data(p,x)            (p)->ops->write_data(p,x)
-#define parport_read_data(p)               (p)->ops->read_data(p)
-#define parport_write_control(p,x)         (p)->ops->write_control(p,x)
-#define parport_read_control(p)            (p)->ops->read_control(p)
-#define parport_frob_control(p,m,v)        (p)->ops->frob_control(p,m,v)
-#define parport_write_econtrol(p,x)        (p)->ops->write_econtrol(p,x)
-#define parport_read_econtrol(p)           (p)->ops->read_econtrol(p)
-#define parport_frob_econtrol(p,m,v)       (p)->ops->frob_econtrol(p,m,v)
-#define parport_write_status(p,v)          (p)->ops->write_status(p,v)
-#define parport_read_status(p)             (p)->ops->read_status(p)
-#define parport_write_fifo(p,v)            (p)->ops->write_fifo(p,v)
-#define parport_read_fifo(p)               (p)->ops->read_fifo(p)
-#define parport_change_mode(p,m)           (p)->ops->change_mode(p,m)
-#define parport_release_resources(p)       (p)->ops->release_resources(p)
-#define parport_claim_resources(p)         (p)->ops->claim_resources(p)
-
 struct parport_operations {
 	void (*write_data)(struct parport *, unsigned int);
 	unsigned int (*read_data)(struct parport *);
@@ -144,18 +132,26 @@
 	void (*wakeup)(void *);
 	void *private;
 	void (*irq_func)(int, void *, struct pt_regs *);
-	int flags;
+	unsigned int flags;
 	struct pardevice *next;
 	struct pardevice *prev;
 	struct parport_state *state;     /* saved status over preemption */
+	struct wait_queue *wait_q;
+	unsigned long int time;
+	unsigned long int timeslice;
+	unsigned int waiting;
+	struct pardevice *waitprev;
+	struct pardevice *waitnext;
 };
 
+/* Directory information for the /proc interface */
 struct parport_dir {
 	struct proc_dir_entry *entry;    /* Directory /proc/parport/X     */
-	struct proc_dir_entry *irq;      /* IRQ entry /proc/parport/X/irq */
-	struct proc_dir_entry *devices;  /* /proc/parport/X/devices       */
-	struct proc_dir_entry *hardware; /* /proc/parport/X/hardware      */
-	char name[4];                    /* /proc/parport/"XXXX" */
+	struct proc_dir_entry *irq;	/*		.../irq           */
+	struct proc_dir_entry *devices;  /*		.../devices       */
+	struct proc_dir_entry *hardware; /*		.../hardware      */
+	struct proc_dir_entry *probe;	 /*		.../autoprobe	  */
+	char name[4];
 };
 
 /* A parallel port */
@@ -169,16 +165,21 @@
 
 	struct pardevice *devices;
 	struct pardevice *cad;	/* port owner */
-	struct pardevice *lurker;
+
+	struct pardevice *waithead;
+	struct pardevice *waittail;
 	
 	struct parport *next;
-	unsigned int flags; 
+	unsigned int flags;
 
 	struct parport_dir pdir;
 	struct parport_device_info probe_info; 
 
 	struct parport_operations *ops;
 	void *private_data;     /* for lowlevel driver */
+
+	  
+	spinlock_t lock;
 };
 
 /* parport_register_port registers a new parallel port at the given address (if
@@ -190,14 +191,14 @@
 				      struct parport_operations *ops);
 
 /* Unregister a port. */
-void parport_unregister_port(struct parport *port);
+extern void parport_unregister_port(struct parport *port);
 
 /* parport_in_use returns nonzero if there are devices attached to a port. */
 #define parport_in_use(x)  ((x)->devices != NULL)
 
 /* Put a parallel port to sleep; release its hardware resources.  Only possible
  * if no devices are registered.  */
-void parport_quiesce(struct parport *);
+extern void parport_quiesce(struct parport *);
 
 /* parport_enumerate returns a pointer to the linked list of all the ports
  * in this machine.
@@ -219,13 +220,17 @@
 			  int flags, void *handle);
 
 /* parport_unregister unlinks a device from the chain. */
-void parport_unregister_device(struct pardevice *dev);
+extern void parport_unregister_device(struct pardevice *dev);
 
 /* parport_claim tries to gain ownership of the port for a particular driver.
  * This may fail (return non-zero) if another driver is busy.  If this
  * driver has registered an interrupt handler, it will be enabled. 
  */
-int parport_claim(struct pardevice *dev);
+extern int parport_claim(struct pardevice *dev);
+
+/* parport_claim_or_block is the same, but sleeps if the port cannot be 
+   claimed.  Return value is 1 if it slept, 0 normally and -errno on error.  */
+extern int parport_claim_or_block(struct pardevice *dev);
 
 /* parport_release reverses a previous parport_claim.  This can never fail, 
  * though the effects are undefined (except that they are bad) if you didn't
@@ -235,7 +240,18 @@
  * If you mess with the port state (enabling ECP for example) you should
  * clean up before releasing the port. 
  */
-void parport_release(struct pardevice *dev);
+
+extern void parport_release(struct pardevice *dev);
+
+extern __inline__ unsigned int parport_yield(struct pardevice *dev, 
+					     unsigned int block)
+{
+	unsigned long int timeslip = (jiffies - dev->time);
+	if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice))
+		return 1;
+	parport_release(dev);
+	return (block)?parport_claim_or_block(dev):parport_claim(dev);
+}
 
 /* The "modes" entry in parport is a bit field representing the following
  * modes.
@@ -262,7 +278,7 @@
 
 /* Prototypes from parport_procfs */
 extern int parport_proc_init(void);
-extern int parport_proc_cleanup(void);
+extern void parport_proc_cleanup(void);
 extern int parport_proc_register(struct parport *pp);
 extern int parport_proc_unregister(struct parport *pp);
 
@@ -272,5 +288,45 @@
 extern int parport_probe(struct parport *port, char *buffer, int len);
 extern void parport_probe_one(struct parport *port);
 extern void (*parport_probe_hook)(struct parport *port);
+
+/* If PC hardware is the only type supported, we can optimise a bit.  */
+#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_AX) || defined(CONFIG_PARPORT_AX_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !defined(CONFIG_PARPORT_OTHER)
+#undef PARPORT_NEED_GENERIC_OPS
+#include <linux/parport_pc.h>
+#define parport_write_data(p,x)            parport_pc_write_data(p,x)
+#define parport_read_data(p)               parport_pc_read_data(p)
+#define parport_write_control(p,x)         parport_pc_write_control(p,x)
+#define parport_read_control(p)            parport_pc_read_control(p)
+#define parport_frob_control(p,m,v)        parport_pc_frob_control(p,m,v)
+#define parport_write_econtrol(p,x)        parport_pc_write_econtrol(p,x)
+#define parport_read_econtrol(p)           parport_pc_read_econtrol(p)
+#define parport_frob_econtrol(p,m,v)       parport_pc_frob_econtrol(p,m,v)
+#define parport_write_status(p,v)          parport_pc_write_status(p,v)
+#define parport_read_status(p)             parport_pc_read_status(p)
+#define parport_write_fifo(p,v)            parport_pc_write_fifo(p,v)
+#define parport_read_fifo(p)               parport_pc_read_fifo(p)
+#define parport_change_mode(p,m)           parport_pc_change_mode(p,m)
+#define parport_release_resources(p)       parport_pc_release_resources(p)
+#define parport_claim_resources(p)         parport_pc_claim_resources(p)
+#endif
+
+#ifdef PARPORT_NEED_GENERIC_OPS
+/* Generic operations vector through the dispatch table. */
+#define parport_write_data(p,x)            (p)->ops->write_data(p,x)
+#define parport_read_data(p)               (p)->ops->read_data(p)
+#define parport_write_control(p,x)         (p)->ops->write_control(p,x)
+#define parport_read_control(p)            (p)->ops->read_control(p)
+#define parport_frob_control(p,m,v)        (p)->ops->frob_control(p,m,v)
+#define parport_write_econtrol(p,x)        (p)->ops->write_econtrol(p,x)
+#define parport_read_econtrol(p)           (p)->ops->read_econtrol(p)
+#define parport_frob_econtrol(p,m,v)       (p)->ops->frob_econtrol(p,m,v)
+#define parport_write_status(p,v)          (p)->ops->write_status(p,v)
+#define parport_read_status(p)             (p)->ops->read_status(p)
+#define parport_write_fifo(p,v)            (p)->ops->write_fifo(p,v)
+#define parport_read_fifo(p)               (p)->ops->read_fifo(p)
+#define parport_change_mode(p,m)           (p)->ops->change_mode(p,m)
+#define parport_release_resources(p)       (p)->ops->release_resources(p)
+#define parport_claim_resources(p)         (p)->ops->claim_resources(p)
+#endif
 
 #endif /* _PARPORT_H_ */
diff -u --recursive --new-file v2.1.81/linux/include/linux/parport_pc.h linux/include/linux/parport_pc.h
--- v2.1.81/linux/include/linux/parport_pc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/parport_pc.h	Fri Jan 23 20:04:03 1998
@@ -0,0 +1,117 @@
+#ifndef __LINUX_PARPORT_PC_H
+#define __LINUX_PARPORT_PC_H
+
+#include <asm/io.h>
+
+/* --- register definitions ------------------------------- */
+
+#define ECONTROL 0x402
+#define CONFIGB  0x401
+#define CONFIGA  0x400
+#define EPPREG   0x4
+#define CONTROL  0x2
+#define STATUS   0x1
+#define DATA     0
+
+extern __inline__ void parport_pc_write_epp(struct parport *p, unsigned int d)
+{
+	outb(d, p->base+EPPREG);
+}
+
+extern __inline__ unsigned int parport_pc_read_epp(struct parport *p)
+{
+	return (unsigned int)inb(p->base+EPPREG);
+}
+
+extern __inline__ unsigned int parport_pc_read_configb(struct parport *p)
+{
+	return (unsigned int)inb(p->base+CONFIGB);
+}
+
+extern __inline__ void parport_pc_write_data(struct parport *p, unsigned int d)
+{
+	outb(d, p->base+DATA);
+}
+
+extern __inline__ unsigned int parport_pc_read_data(struct parport *p)
+{
+	return (unsigned int)inb(p->base+DATA);
+}
+
+extern __inline__ void parport_pc_write_control(struct parport *p, unsigned int d)
+{
+	outb(d, p->base+CONTROL);
+}
+
+extern __inline__ unsigned int parport_pc_read_control(struct parport *p)
+{
+	return (unsigned int)inb(p->base+CONTROL);
+}
+
+extern __inline__ unsigned int parport_pc_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
+{
+	unsigned int old = (unsigned int)inb(p->base+CONTROL);
+	outb(((old & ~mask) ^ val), p->base+CONTROL);
+	return old;
+}
+
+extern __inline__ void parport_pc_write_status(struct parport *p, unsigned int d)
+{
+	outb(d, p->base+STATUS);
+}
+
+extern __inline__ unsigned int parport_pc_read_status(struct parport *p)
+{
+	return (unsigned int)inb(p->base+STATUS);
+}
+
+extern __inline__ void parport_pc_write_econtrol(struct parport *p, unsigned int d)
+{
+	outb(d, p->base+ECONTROL);
+}
+
+extern __inline__ unsigned int parport_pc_read_econtrol(struct parport *p)
+{
+	return (unsigned int)inb(p->base+ECONTROL);
+}
+
+extern __inline__ unsigned int parport_pc_frob_econtrol(struct parport *p, unsigned int mask,  unsigned int val)
+{
+	unsigned int old = (unsigned int)inb(p->base+ECONTROL);
+	outb(((old & ~mask) ^ val), p->base+ECONTROL);
+	return old;
+}
+
+extern void parport_pc_change_mode(struct parport *p, int m);
+
+extern void parport_pc_write_fifo(struct parport *p, unsigned int v);
+
+extern unsigned int parport_pc_read_fifo(struct parport *p);
+
+extern void parport_pc_disable_irq(struct parport *p);
+
+extern void parport_pc_enable_irq(struct parport *p);
+
+extern void parport_pc_release_resources(struct parport *p);
+
+extern int parport_pc_claim_resources(struct parport *p);
+
+extern void parport_pc_save_state(struct parport *p, struct parport_state *s);
+
+extern void parport_pc_restore_state(struct parport *p, struct parport_state *s);
+
+extern unsigned int parport_pc_epp_read_block(struct parport *p, void *buf, unsigned  int length);
+
+extern unsigned int parport_pc_epp_write_block(struct parport *p, void *buf, unsigned  int length);
+
+extern unsigned int parport_pc_ecp_read_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle);
+
+extern unsigned int parport_pc_ecp_write_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle);
+
+extern int parport_pc_examine_irq(struct parport *p);
+
+extern void parport_pc_inc_use_count(void);
+
+extern void parport_pc_dec_use_count(void);
+
+#endif
diff -u --recursive --new-file v2.1.81/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.81/linux/include/linux/pci.h	Tue Dec 23 14:37:32 1997
+++ linux/include/linux/pci.h	Mon Jan 26 11:43:19 1998
@@ -1,48 +1,27 @@
 /*
- * PCI defines and function prototypes
- * Copyright 1994, Drew Eckhardt
+ *	$Id: pci.h,v 1.51 1997/12/27 13:55:23 mj Exp $
  *
- * For more information, please consult 
- * 
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
+ *	PCI defines and function prototypes
+ *	Copyright 1994, Drew Eckhardt
+ *	Copyright 1997, Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
- * PCI Special Interest Group
- * M/S HF3-15A
- * 5200 N.E. Elam Young Parkway
- * Hillsboro, Oregon 97124-6497
- * +1 (503) 696-2000 
- * +1 (800) 433-5177
+ *	For more information, please consult 
  * 
- * Manuals are $25 each or $50 for all three, plus $7 shipping 
- * within the United States, $35 abroad.
- */
-
-
-
-/*	PROCEDURE TO REPORT NEW PCI DEVICES
- * We are trying to collect information on new PCI devices, using
- * the standard PCI identification procedure. If some warning is
- * displayed at boot time, please report 
- *	- /proc/pci
- *	- your exact hardware description. Try to find out
- *	  which device is unknown. It may be you mainboard chipset.
- *	  PCI-CPU bridge or PCI-ISA bridge.
- *	- If you can't find the actual information in your hardware
- *	  booklet, try to read the references of the chip on the board.
- *	- Send all that to linux-pcisupport@cck.uni-kl.de
- *	  and I'll add your device to the list as soon as possible
- *
- * BEFORE you send a mail, please check the latest linux releases
- * to be sure it has not been recently added.
+ *	PCI BIOS Specification Revision
+ *	PCI Local Bus Specification
+ *	PCI System Design Guide
  *
- *        Thanks
- *		Jens Maurer
+ *	PCI Special Interest Group
+ *	M/S HF3-15A
+ *	5200 N.E. Elam Young Parkway
+ *	Hillsboro, Oregon 97124-6497
+ *	+1 (503) 696-2000 
+ *	+1 (800) 433-5177
+ * 
+ *	Manuals are $25 each or $50 for all three, plus $7 shipping 
+ *	within the United States, $35 abroad.
  */
 
-
-
 #ifndef LINUX_PCI_H
 #define LINUX_PCI_H
 
@@ -102,7 +81,7 @@
  */
 #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
 #define PCI_BASE_ADDRESS_1	0x14	/* 32 bits */
-#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits */
+#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits [htype 0 only] */
 #define PCI_BASE_ADDRESS_3	0x1c	/* 32 bits */
 #define PCI_BASE_ADDRESS_4	0x20	/* 32 bits */
 #define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
@@ -118,6 +97,7 @@
 #define  PCI_BASE_ADDRESS_IO_MASK	(~0x03)
 /* bit 1 is reserved if address_space = 1 */
 
+/* Header type 0 (normal devices) */
 #define PCI_CARDBUS_CIS		0x28
 #define PCI_SUBSYSTEM_ID	0x2c
 #define PCI_SUBSYSTEM_VENDOR_ID	0x2e  
@@ -131,6 +111,46 @@
 #define PCI_MIN_GNT		0x3e	/* 8 bits */
 #define PCI_MAX_LAT		0x3f	/* 8 bits */
 
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
+#define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
+#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER	0x1b	/* Latency timer for secondary interface */
+#define PCI_IO_BASE		0x1c	/* I/O range behind the bridge */
+#define PCI_IO_LIMIT		0x1d
+#define  PCI_IO_RANGE_TYPE_MASK	0x0f	/* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16	0x00
+#define  PCI_IO_RANGE_TYPE_32	0x01
+#define  PCI_IO_RANGE_MASK	~0x0f
+#define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE		0x20	/* Memory range behind */
+#define PCI_MEMORY_LIMIT	0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define  PCI_MEMORY_RANGE_MASK	~0x0f
+#define PCI_PREF_MEMORY_BASE	0x24	/* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT	0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define  PCI_PREF_RANGE_TYPE_32	0x00
+#define  PCI_PREF_RANGE_TYPE_64	0x01
+#define  PCI_PREF_RANGE_MASK	~0x0f
+#define PCI_PREF_BASE_UPPER32	0x28	/* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32	0x2c
+#define PCI_IO_BASE_UPPER16	0x30	/* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16	0x32
+/* 0x34-0x3b is reserved */
+#define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL	0x3e
+#define  PCI_BRIDGE_CTL_PARITY	0x01	/* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR	0x02	/* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_NO_ISA	0x04	/* Disable bridging of ISA ports */
+#define  PCI_BRIDGE_CTL_VGA	0x08	/* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT 0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET 0x40	/* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK 0x80	/* Fast Back2Back enabled on secondary interface */
+
+/* Device classes and subclasses */
+
 #define PCI_CLASS_NOT_DEFINED		0x0000
 #define PCI_CLASS_NOT_DEFINED_VGA	0x0001
 
@@ -175,7 +195,6 @@
 #define  PCI_CLASS_BRIDGE_CARDBUS	0x0607
 #define  PCI_CLASS_BRIDGE_OTHER		0x0680
 
-
 #define PCI_BASE_CLASS_COMMUNICATION	0x07
 #define PCI_CLASS_COMMUNICATION_SERIAL	0x0700
 #define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
@@ -856,7 +875,6 @@
 #define PCI_DEVICE_ID_ARK_STINGARK	0xa099
 #define PCI_DEVICE_ID_ARK_2000MT	0xa0a1
 
-#ifdef __KERNEL__
 /*
  * The PCI interface treats multi-function devices as independent
  * devices.  The slot/function address of each device is encoded
@@ -869,6 +887,7 @@
 #define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)		((devfn) & 0x07)
 
+#ifdef __KERNEL__
 /*
  * There is one pci_dev structure for each slot-number/function-number
  * combination:
@@ -920,34 +939,16 @@
 	unsigned char	subordinate;	/* max number of subordinate buses */
 };
 
-/*
- * This is used to map a vendor-id/device-id pair into device-specific
- * information.
- */
-struct pci_dev_info {
-	unsigned short	vendor;		/* vendor id */
-	unsigned short	device;		/* device id */
-
-	const char	*name;		/* device name */
-	unsigned char	bridge_type;	/* bridge type or 0xff */
-};
-
 extern struct pci_bus	pci_root;	/* root bus */
 extern struct pci_dev	*pci_devices;	/* list of all devices */
 
-
 extern unsigned long pci_init (unsigned long mem_start, unsigned long mem_end);
 
-extern unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp);
-
-extern struct pci_dev_info *pci_lookup_dev (unsigned int vendor,
-					    unsigned int dev);
-extern const char *pci_strclass (unsigned int class);
-extern const char *pci_strvendor (unsigned int vendor);
-extern const char *pci_strdev (unsigned int vendor, unsigned int device);
+extern unsigned int pci_scan_bus (struct pci_bus *bus, unsigned long *mem_startp);
 
 extern int get_pci_list (char *buf);
 
 extern void pci_quirks_init (void);
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff -u --recursive --new-file v2.1.81/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.1.81/linux/include/linux/proc_fs.h	Tue Jan 20 16:51:57 1998
+++ linux/include/linux/proc_fs.h	Mon Jan 26 14:29:22 1998
@@ -197,6 +197,12 @@
 	PROC_MCA_LAST = (PROC_MCA_SLOT + 8)
 };
 
+enum bus_directory_inos {
+	PROC_BUS_PCI = PROC_MCA_LAST,
+	PROC_BUS_PCI_DEVICES,
+	PROC_BUS_LAST
+};
+
 /* Finally, the dynamically allocatable proc entries are reserved: */
 
 #define PROC_DYNAMIC_FIRST 4096
@@ -263,12 +269,13 @@
 extern struct proc_dir_entry proc_pid;
 extern struct proc_dir_entry proc_pid_fd;
 extern struct proc_dir_entry proc_mca;
+extern struct proc_dir_entry *proc_bus;
 
 extern struct inode_operations proc_scsi_inode_operations;
 
 extern void proc_root_init(void);
 extern void proc_base_init(void);
-extern void proc_net_init(void);
+extern void proc_bus_pci_init(void);
 
 extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
 extern int proc_unregister(struct proc_dir_entry *, int);
diff -u --recursive --new-file v2.1.81/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.1.81/linux/include/linux/sched.h	Tue Jan 20 16:51:56 1998
+++ linux/include/linux/sched.h	Mon Jan 26 14:29:15 1998
@@ -332,7 +332,7 @@
 /* timeout */	0,SCHED_OTHER,0,0,0,0,0,0,0, \
 /* timer */	{ NULL, NULL, 0, 0, it_real_fn }, \
 /* utime */	{0,0,0,0},0, \
-/* per cpu times */ {0, 0, }, {0, 0, }, \
+/* per cpu times */ {0, }, {0, }, \
 /* flt */	0,0,0,0,0,0, \
 /* swp */	0,0,0,0,0, \
 /* rlimits */   INIT_RLIMITS, \
diff -u --recursive --new-file v2.1.81/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- v2.1.81/linux/include/linux/smb_fs.h	Fri Jan 23 18:10:32 1998
+++ linux/include/linux/smb_fs.h	Mon Jan 26 14:31:43 1998
@@ -99,6 +99,7 @@
 int  smb_notify_change(struct dentry *, struct iattr *);
 unsigned long smb_invent_inos(unsigned long);
 struct inode *smb_iget(struct super_block *, struct smb_fattr *);
+extern int init_smb_fs(void);
 
 /* linux/fs/smbfs/proc.c */
 __u32 smb_len(unsigned char *);
diff -u --recursive --new-file v2.1.81/linux/init/main.c linux/init/main.c
--- v2.1.81/linux/init/main.c	Fri Jan 23 18:10:32 1998
+++ linux/init/main.c	Sun Jan 25 10:05:47 1998
@@ -119,6 +119,9 @@
 #ifdef CONFIG_PARIDE_PF
 extern void pf_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_PARIDE_PT
+extern void pt_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_PARIDE_PCD
 extern void pcd_setup(char *str, int *ints);
 #endif
@@ -701,7 +704,7 @@
 #ifdef CONFIG_PLIP
 	{ "plip=", plip_setup },
 #endif
-#ifdef CONFIG_SOUNDMODEM
+#ifdef CONFIG_HFMODEM
 	{ "hfmodem=", hfmodem_setup },
 #endif
 #ifdef CONFIG_PMAC_CONSOLE
@@ -731,6 +734,9 @@
 #endif
 #ifdef CONFIG_PARIDE_PF
 	{ "pf.", pf_setup },
+#endif
+#ifdef CONFIG_PARIDE_PT
+        { "pt.", pt_setup },
 #endif
 	{ 0, 0 }
 };
diff -u --recursive --new-file v2.1.81/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.81/linux/kernel/ksyms.c	Tue Jan 20 16:45:08 1998
+++ linux/kernel/ksyms.c	Mon Jan 26 11:43:19 1998
@@ -100,7 +100,6 @@
 EXPORT_SYMBOL(get_options);
 
 #ifdef CONFIG_PCI
-/* PCI BIOS support */
 EXPORT_SYMBOL(pcibios_present);
 EXPORT_SYMBOL(pcibios_find_class);
 EXPORT_SYMBOL(pcibios_find_device);
@@ -111,8 +110,6 @@
 EXPORT_SYMBOL(pcibios_write_config_word);
 EXPORT_SYMBOL(pcibios_write_config_dword);
 EXPORT_SYMBOL(pcibios_strerror);
-EXPORT_SYMBOL(pci_strvendor);
-EXPORT_SYMBOL(pci_strdev);
 #endif
 
 /* process memory management */
diff -u --recursive --new-file v2.1.81/linux/kernel/signal.c linux/kernel/signal.c
--- v2.1.81/linux/kernel/signal.c	Thu Dec 11 11:35:38 1997
+++ linux/kernel/signal.c	Sat Jan 24 09:17:51 1998
@@ -583,23 +583,27 @@
 asmlinkage int
 sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize)
 {
+	int error = -EINVAL;
 	sigset_t old_set, new_set;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
 	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
+		goto out;
 
 	if (set) {
+		error = -EFAULT;
 		if (copy_from_user(&new_set, set, sizeof(*set)))
-			return -EFAULT;
+			goto out;
 		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
 
 		spin_lock_irq(&current->sigmask_lock);
 		old_set = current->blocked;
 
+		error = 0;
 		switch (how) {
 		default:
-			return -EINVAL;
+			error = -EINVAL;
+			break;
 		case SIG_BLOCK:
 			sigorsets(&new_set, &old_set, &new_set);
 			break;
@@ -613,47 +617,54 @@
 		current->blocked = new_set;
 		recalc_sigpending(current);
 		spin_unlock_irq(&current->sigmask_lock);
-
-		if (oset) {
-			if (copy_to_user(oset, &old_set, sizeof(*oset)))
-				return -EFAULT;
-		}
+		if (error)
+			goto out;
+		if (oset)
+			goto set_old;
 	} else if (oset) {
 		spin_lock_irq(&current->sigmask_lock);
 		old_set = current->blocked;
 		spin_unlock_irq(&current->sigmask_lock);
 
+	set_old:
+		error = -EFAULT;
 		if (copy_to_user(oset, &old_set, sizeof(*oset)))
-			return -EFAULT;
+			goto out;
 	}
-
-	return 0;
+	error = 0;
+out:
+	return error;
 }
 
 asmlinkage int
 sys_rt_sigpending(sigset_t *set, size_t sigsetsize)
 {
+	int error = -EINVAL;
 	sigset_t pending;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
 	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
+		goto out;
 
 	spin_lock_irq(&current->sigmask_lock);
 	sigandsets(&pending, &current->blocked, &current->signal);
 	spin_unlock_irq(&current->sigmask_lock);
 
-	return copy_to_user(set, &pending, sizeof(*set));
+	error = -EFAULT;
+	if (!copy_to_user(set, &pending, sizeof(*set)))
+		error = 0;
+out:
+	return error;
 }
 
 asmlinkage int
 sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
 		    const struct timespec *uts, size_t sigsetsize)
 {
+	int ret, sig;
 	sigset_t these;
 	struct timespec ts;
 	siginfo_t info;
-	int ret, sig;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
 	if (sigsetsize != sizeof(sigset_t))
@@ -825,19 +836,23 @@
 asmlinkage int
 sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset)
 {
+	int error;
 	old_sigset_t old_set, new_set;
 
 	if (set) {
+		error = -EFAULT;
 		if (copy_from_user(&new_set, set, sizeof(*set)))
-			return -EFAULT;
+			goto out;
 		new_set &= ~(sigmask(SIGKILL)|sigmask(SIGSTOP));
 
 		spin_lock_irq(&current->sigmask_lock);
 		old_set = current->blocked.sig[0];
 
+		error = 0;
 		switch (how) {
 		default:
-			return -EINVAL;
+			error = -EINVAL;
+			break;
 		case SIG_BLOCK:
 			sigaddsetmask(&current->blocked, new_set);
 			break;
@@ -851,30 +866,36 @@
 
 		recalc_sigpending(current);
 		spin_unlock_irq(&current->sigmask_lock);
-
-		if (oset) {
-			if (copy_to_user(oset, &old_set, sizeof(*oset)))
-				return -EFAULT;
-		}
+		if (error)
+			goto out;
+		if (oset)
+			goto set_old;
 	} else if (oset) {
 		old_set = current->blocked.sig[0];
+	set_old:
+		error = -EFAULT;
 		if (copy_to_user(oset, &old_set, sizeof(*oset)))
-			return -EFAULT;
+			goto out;
 	}
-
-	return 0;
+	error = 0;
+out:
+	return error;
 }
 
 asmlinkage int
 sys_sigpending(old_sigset_t *set)
 {
+	int error;
 	old_sigset_t pending;
 
 	spin_lock_irq(&current->sigmask_lock);
 	pending = current->blocked.sig[0] & current->signal.sig[0];
 	spin_unlock_irq(&current->sigmask_lock);
 
-	return copy_to_user(set, &pending, sizeof(*set));
+	error = -EFAULT;
+	if (!copy_to_user(set, &pending, sizeof(*set)))
+		error = 0;
+	return error;
 }
 
 asmlinkage int
@@ -882,11 +903,11 @@
 		 size_t sigsetsize)
 {
 	struct k_sigaction new_sa, old_sa;
-	int ret;
+	int ret = -EINVAL;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
 	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
+		goto out;
 
 	if (act) {
 		if (copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
@@ -899,7 +920,7 @@
 		if (copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
 			return -EFAULT;
 	}
-
+out:
 	return ret;
 }
 #endif
diff -u --recursive --new-file v2.1.81/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.1.81/linux/net/packet/af_packet.c	Mon Jan 12 15:28:28 1998
+++ linux/net/packet/af_packet.c	Sun Jan 25 10:05:47 1998
@@ -70,6 +70,14 @@
 #include <linux/if_frad.h>
 #endif
 
+#ifdef CONFIG_BRIDGE
+#include <net/br.h>
+#endif
+
+#ifdef CONFIG_DLCI
+extern int dlci_ioctl(unsigned int, void*);
+#endif
+
 /*
    Old SOCK_PACKET. Do exist programs, which use it?
    (not counting tcpdump) - lots of them yes - AC. 
diff -u --recursive --new-file v2.1.81/linux/net/socket.c linux/net/socket.c
--- v2.1.81/linux/net/socket.c	Mon Jan 12 15:28:28 1998
+++ linux/net/socket.c	Sun Jan 25 10:05:47 1998
@@ -1432,6 +1432,9 @@
 }
 
 extern void sk_init(void);
+#ifdef CONFIG_WAN_ROUTER
+extern void wanrouter_init(void);
+#endif
 
 __initfunc(void sock_init(void))
 {
diff -u --recursive --new-file v2.1.81/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c
--- v2.1.81/linux/net/wanrouter/wanmain.c	Mon Jan 12 14:46:27 1998
+++ linux/net/wanrouter/wanmain.c	Sun Jan 25 10:05:47 1998
@@ -80,8 +80,10 @@
  *	Global Data
  */
 
+#ifdef MODULE
 static char fullname[]		= "WAN Router";
 static char copyright[]		= "(c) 1995-1997 Sangoma Technologies Inc.";
+#endif
 static char modname[]		= ROUTER_NAME;	/* short module name */
 wan_device_t * router_devlist	= NULL;	/* list of registered devices */
 static int devcnt		= 0;
@@ -91,7 +93,9 @@
  */
  
 static unsigned char oui_ether[] = { 0x00, 0x00, 0x00 };
+#if 0
 static unsigned char oui_802_2[] = { 0x00, 0x80, 0xC2 };
+#endif
 
 #ifdef MODULE
 
diff -u --recursive --new-file v2.1.81/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c
--- v2.1.81/linux/net/wanrouter/wanproc.c	Mon Jan 12 14:46:27 1998
+++ linux/net/wanrouter/wanproc.c	Sun Jan 25 10:05:47 1998
@@ -158,6 +158,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
