## Automatically generated incremental diff
## From:   linux-2.2.19-pre2
## To:     linux-2.2.19-pre3
## Robot:  $Id: make-incremental-diff,v 1.6 2001/12/04 04:41:15 hpa Exp $

diff -urN linux-2.2.19-pre2/Documentation/Changes linux/Documentation/Changes
--- linux-2.2.19-pre2/Documentation/Changes	Mon Dec  3 20:53:10 2001
+++ linux/Documentation/Changes	Mon Dec  3 20:53:37 2001
@@ -542,6 +542,28 @@
 to your /etc/modules.conf file.
 
 
+Intel IA32 microcode
+====================
+
+A driver has been added to allow updating of Intel IA32 microcode,
+accessible as both a devfs regular file and as a normal (misc)
+character device.  If you are not using devfs you may need to:
+
+mkdir /dev/cpu
+mknod /dev/cpu/microcode c 10 184
+chmod 0644 /dev/cpu/microcode
+
+as root before you can use this.  You'll probably also want to
+get the user-space microcode_ctl utility to use with this.
+
+If you have compiled the driver as a module you may need to add
+the following line:
+
+alias char-major-10-184 microcode
+
+to your /etc/modules.conf file.
+
+
 Where to get the files
 **********************
 
diff -urN linux-2.2.19-pre2/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.2.19-pre2/Documentation/Configure.help	Mon Dec  3 20:53:10 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 20:53:37 2001
@@ -5895,6 +5895,25 @@
   If you want to compile this as a module, say M and read
   Documentation/modules.txt. The module will be called comx-hw-mixcom.o.
 
+i810 TCO support
+CONFIG_I810_TCO
+  Hardware driver for the TCO timer built into the Intel i810 and i815
+  chipset family. The TCO (Total Cost of Ownership) timer is a watchdog
+  timer that will reboot the machine after it's second expiration. The
+  expiration time can be configured by commandline argument
+  "i810_margin=<n>" where <n> is the counter initial value. It is
+  decremented every 0.6 secs, the default is 50 which gives a timeout
+  of 30 seconds and one minute until reset.
+
+  On some motherboards the driver may fail to reset the chipset's
+  NO_REBOOT flag which prevents the watchdog from rebooting the machine.
+  If this is the case you will get a kernel message like
+  "i810tco init: failed to reset NO_REBOOT flag".
+
+  If you want to compile this as a module, say M and read
+  Documentation/modules.txt. The module will be called
+  i810-tco.o.
+
 MultiGate Cisco-HDLC and synchronous PPP protocol support
 CONFIG_COMX_PROTO_PPP
   Cisco-HDLC and synchronous PPP protocol driver for all MultiGate boards. 
@@ -7511,13 +7530,6 @@
   ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/mini. Probably the quota
   support is only useful for multi user systems. If unsure, say N.
 
-Acorn's ADFS filesystem support (read only) (EXPERIMENTAL)
-CONFIG_ADFS_FS
-  The Advanced Disk File System is the filesystem used on floppy and
-  hard disks by Acorn Systems.  Currently in development, as a read-
-  only driver for hard disks.  These should be the first partition
-  (eg. /dev/[sh]d?1) on each of your drives.  If unsure, say N.
-
 Support for USB
 CONFIG_USB
   Universal Serial Bus (USB) is a specification for a serial bus
@@ -7890,6 +7902,16 @@
   The module will be called digi_acceleport.o. If you want to compile 
   it as a module, say M here and read Documentation/modules.txt.
 
+USB Empeg empeg-car Mark I/II Driver
+CONFIG_USB_SERIAL_EMPEG
+  Say Y here if you want to connect to your Empeg empeg-car Mark I/II
+  mp3 player via USB.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called empeg.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
 USB Serial Converter verbose debug
 CONFIG_USB_SERIAL_DEBUG
   Say Y here if you want verbose debug messages from the USB Serial
@@ -9696,6 +9718,24 @@
   If you have more than 3 printers, you need to increase the LP_NO
   variable in lp.c.
 
+Amiga built-in parallel port support
+CONFIG_PARPORT_AMIGA
+  Say Y here if you need support for the parallel port hardware on
+  Amiga machines. This code is also available as a module (say M),
+  called parport_amiga.o. If in doubt, saying N is the safe plan.
+
+Atari built-in parallel port support
+CONFIG_PARPORT_ATARI
+  Say Y here if you need support for the parallel port hardware on
+  Atari machines. This code is also available as a module (say M),
+  called parport_atari.o. If in doubt, saying N is the safe plan.
+
+Multiface 3 parallel port card support
+CONFIG_PARPORT_MFC3
+  Say Y here if you need parallel port support for the MFC3 card.
+  This code is also available as a module (say M), called
+  parport_mfc3.o. If in doubt, saying N is the safe plan.
+
 Support IEEE1284 status readback
 CONFIG_PRINTER_READBACK
   If your printer conforms to IEEE 1284, it may be able to provide a
@@ -10742,17 +10782,6 @@
   to it. For more information on how to use the driver please read
   Documentation/joystick.txt
 
-Atomwide Serial Support
-CONFIG_ATOMWIDE_SERIAL
-  If you have an Atomwide Serial card for an Acorn system, say Y to
-  this option. The driver can handle 1, 2, or 3 port cards.
-  If unsure, say N
-
-The Serial Port Dual Serial Port
-CONFIG_DUALSP_SERIAL
-  If you have the Serial Port's dual serial card for an Acorn system,
-  say Y to this option. If unsure, say N
-
 NetWinder Button
 CONFIG_NWBUTTON
   If you enable this driver and create a character device node
@@ -12814,22 +12843,6 @@
 ZOLTRIX I/O port (0x20c or 0x30c)
 CONFIG_RADIO_ZOLTRIX_PORT
   Enter the I/O port of your Zoltrix radio card.
-
-ADS Cadet AM/FM Tuner
-CONFIG_RADIO_CADET
-  Say Y here if this is your AM/FM radio card.
-
-  In order to control your radio card, you will need to use programs
-  that are compatible with the Video for Linux API. Information on 
-  this API and pointers to "v4l" programs may be found on the WWW at
-  http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
-  you need to have access to a machine on the Internet that has a 
-  program like lynx or netscape.
-
-  If you want to compile this driver as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want),
-  say M here and read Documentation/modules.txt. The module will be
-  called radio-cadet.o
 
 Miro PCM20 Radio
 CONFIG_RADIO_MIROPCM20
diff -urN linux-2.2.19-pre2/Documentation/sound/ChangeLog.ymfsb linux/Documentation/sound/ChangeLog.ymfsb
--- linux-2.2.19-pre2/Documentation/sound/ChangeLog.ymfsb	Wed Jun  7 14:26:42 2000
+++ linux/Documentation/sound/ChangeLog.ymfsb	Wed Dec 31 16:00:00 1969
@@ -1,19 +0,0 @@
-Sun May 21 15:14:37 2000  Daisuke Nagano  <breeze.nagano@nifty.ne.jp>
-
-	* ymf_sb.c: Add 'master_vol' module parameter to change
-	'PCM out Vol" of AC'97.
-	Should I support AC'97 mixer by implementing original mixer
-	codes... ?
-
-	* ymf_sb.c: remove native UART401 support. External MIDI port
-	should be supported by sb_midi driver.
-
-	*ymf_sb.c: add support for SPDIF OUT. Module parameter
-	'spdif_out' is now available.
-
-
-Tue May 16 19:29:29 2000  Daisuke Nagano  <breeze.nagano@nifty.ne.jp>
-
-	* ymf_sb.c (checkCodec): add a little delays for reset devices.
-	
-	* ymf_sb.c (readRegWord): fixed addressing bug.
diff -urN linux-2.2.19-pre2/Documentation/sound/README.ymfsb linux/Documentation/sound/README.ymfsb
--- linux-2.2.19-pre2/Documentation/sound/README.ymfsb	Mon Sep  4 10:39:16 2000
+++ linux/Documentation/sound/README.ymfsb	Wed Dec 31 16:00:00 1969
@@ -1,127 +0,0 @@
-Legacy audio driver for YMF7xx PCI cards.
-
-
-FIRST OF ALL
-============
-
-  This code references YAMAHA's sample codes and data sheets.
-  I respect and thank for all people they made open the informations
-  about YMF7xx cards.
-
-  And this codes heavily based on Jeff Garzik <jgarzik@pobox.com>'s
-  old VIA 82Cxxx driver (via82cxxx.c). I also respect him.
-
-
-DISCLIMER
-=========
-
- This driver is currently at early ALPHA stage. It may cause serious
- damage to your computer when used.
- PLEASE USE IT AT YOUR OWN RISK.
-
-
-ABOUT THIS DRIVER
-=================
-
-  This code enables you to use your YMF724[A-F], YMF740[A-C], YMF744, YMF754
- cards as "SoundBlaster Pro" compatible card. It can only play 22.05kHz /
- 8bit / Stereo samples, control external MIDI port.
- And it can handle AC'97 mixer of these cards.
-
-  If you want to use your card as recent "16-bit" card, you should use
- Alsa or OSS/Linux driver. Ofcource you can write native PCI driver for
- your cards :)
-
-
-INSTALL
-=======
-
-  First, it requires some sound driver modules in Linux kernel 
- (soundcore.o , sound.o, sb.o and uart401.o), so you should enable
- these modules at kernel configuration (please refer some other 
- documentations for configuration of kernel).
- And add the following line in /etc/modules.conf:
-
-  options sb support=1
-
- (NOTE: There are no need any configuration of sb modules)
-
- To compile ymfsb module, type 'make'.
- And copy it to /lib/modules/(kernel_version)/misc, type 'depmod -a'.
- 
-  This module also requires /usr/src/linux/drivers/sound/ac97.[ch].
- If your kernel doesn't have these files, you should upgrade your kernel.
-
-
-USAGE
-=====
-
- # modprobe ymfsb (options)
-
-
-OPTIONS FOR YMFSB
-=================
-
-  io           : SB base address     (0x220, 0x240, 0x260, 0x280)
-  synth_io     : OPL3 base address   (0x388, 0x398, 0x3a0, 0x3a8)
-  dma          : DMA number          (0,1,3)
-  spdif_out    : SPDIF-out flag      (0:disable 1:enable)
-
- These options will change in future...
-
-
-FREQUENCY
-=========
-
-  When playing sounds via this driver, you will hear its pitch is slightly
- lower than original sounds. Since this driver recognizes your card acts
- with 21.739kHz sample rates rather than 22.050kHz (I think it must be
- hardware restriction). So many players become tone deafness.
- To prevent this, you should express some options to your sound player
- that specify correct sample frequency. For example, to play your MP3 file
- correctly with mpg123, specify the frequency like following:
-
-  %  mpg123 -r 21739 foo.mp3
-
-
-SPDIF OUT
-=========
-
-  With installing modules with option 'spdif_out=1', you can enjoy your
- sounds from SPDIF-out of your card (if it had).
- Its Fs is fixed to 48kHz (It never means the sample frequency become 
- up to 48kHz. All sounds via SPDIF-out also 22kHz samples). So your
- digital-in capable components has to be able to handle 48kHz Fs.
-
-
-COPYING
-=======
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-TODO
-====
- * support for multiple cards
-   (set the different SB_IO,MPU_IO,OPL_IO for each cards)
-
- * support for OPL (dmfm) : There will be no requirements... :-<
-
-
-AUTHOR
-======
-
- Daisuke Nagano <breeze.nagano@nifty.ne.jp>
-
diff -urN linux-2.2.19-pre2/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- linux-2.2.19-pre2/Documentation/usb/usb-serial.txt	Sun Dec 10 16:49:41 2000
+++ linux/Documentation/usb/usb-serial.txt	Mon Dec  3 20:53:37 2001
@@ -185,6 +185,15 @@
   -- Add everything else that is missing :)
 
 
+Empeg empeg-car Mark I/II Driver (empeg.c)
+
+  This is an experimental driver to provide connectivity support for the
+  client synchronization tools for an Empeg empeg-car mp3 player.
+
+  The driver is still pretty new, so some testing 'in the wild' would be
+  helpful. :)
+
+
 Generic Serial driver
 
   If your device is not one of the above listed devices, compatible with
diff -urN linux-2.2.19-pre2/Makefile linux/Makefile
--- linux-2.2.19-pre2/Makefile	Mon Dec  3 20:53:10 2001
+++ linux/Makefile	Mon Dec  3 20:53:37 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 19
-EXTRAVERSION = pre2
+EXTRAVERSION = pre3
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -24,12 +24,14 @@
 LD	=$(CROSS_COMPILE)ld
 #
 #	foo-bar-gcc for cross builds
-#	gcc272 for Debian's old compiler for kernels
-#	kgcc for Conectiva and Red Hat 7
+#	kgcc for Conectiva, Red Hat, Mandrake
+#	gcc272 for Debian
 #	otherwise 'cc'
 #
-CC	=$(shell if [ -n "$(CROSS_COMPILE)" ]; then echo $(CROSS_COMPILE)gcc; else \
-	$(CONFIG_SHELL) scripts/kwhich gcc272 2>/dev/null || $(CONFIG_SHELL) scripts/kwhich kgcc 2>/dev/null || echo cc; fi) \
+CCFOUND :=$(shell $(CONFIG_SHELL) scripts/kwhich kgcc gcc272 cc gcc)
+## Faster, but requires GNU make 3.78, which postdates Linux 2.2.0
+##CC	=$(if $(CROSS_COMPILE),$(CROSS_COMPILE)gcc,$(CCFOUND)) -D__KERNEL__ -I$(HPATH)
+CC	=$(shell if [ -n "$(CROSS_COMPILE)" ]; then echo $(CROSS_COMPILE)gcc; else echo $(CCFOUND); fi) \
 	-D__KERNEL__ -I$(HPATH)
 CPP	=$(CC) -E
 AR	=$(CROSS_COMPILE)ar
diff -urN linux-2.2.19-pre2/arch/i386/kernel/cpuid.c linux/arch/i386/kernel/cpuid.c
--- linux-2.2.19-pre2/arch/i386/kernel/cpuid.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/i386/kernel/cpuid.c	Mon Dec  3 20:53:37 2001
@@ -152,6 +152,7 @@
 
 static void cpuid_exit(void)
 {
+  unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
 }
 
 module_init(cpuid_init);
diff -urN linux-2.2.19-pre2/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.2.19-pre2/arch/i386/kernel/entry.S	Mon Sep  4 10:39:16 2000
+++ linux/arch/i386/kernel/entry.S	Mon Dec  3 20:53:37 2001
@@ -267,16 +267,18 @@
 	pushl %ebx
 	cld
 	movl %es,%cx
-	xchgl %eax, ORIG_EAX(%esp)	# orig_eax (get the error code. )
+	movl ORIG_EAX(%esp), %esi	# get the error code
+	movl ES(%esp), %edi		# get the function address
+	movl %eax, ORIG_EAX(%esp)
+	movl %ecx, ES(%esp)
 	movl %esp,%edx
-	xchgl %ecx, ES(%esp)		# get the address and save es.
-	pushl %eax			# push the error code
-	pushl %edx
+	pushl %esi			# push the error code
+	pushl %edx			# push the pt_regs pointer
 	movl $(__KERNEL_DS),%edx
 	movl %dx,%ds
 	movl %dx,%es
 	GET_CURRENT(%ebx)
-	call *%ecx
+	call *%edi
 	addl $8,%esp
 	jmp ret_from_exception
 
@@ -331,11 +333,6 @@
 ENTRY(coprocessor_segment_overrun)
 	pushl $0
 	pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
-	jmp error_code
-
-ENTRY(reserved)
-	pushl $0
-	pushl $ SYMBOL_NAME(do_reserved)
 	jmp error_code
 
 ENTRY(double_fault)
diff -urN linux-2.2.19-pre2/arch/i386/kernel/microcode.c linux/arch/i386/kernel/microcode.c
--- linux-2.2.19-pre2/arch/i386/kernel/microcode.c	Mon Dec  3 20:53:10 2001
+++ linux/arch/i386/kernel/microcode.c	Mon Dec  3 20:53:37 2001
@@ -33,6 +33,8 @@
  *		Messages for error cases (non intel & no suitable microcode).
  *	1.06	07 Dec 2000, Tigran Aivazian <tigran@veritas.com>
  *		Pentium 4 support + backported fixes from 2.4
+ *	1.07	13 Dec 2000, Tigran Aivazian <tigran@veritas.com>
+ *		More bugfixes backported from 2.4
  */
 
 #include <linux/init.h>
@@ -47,7 +49,7 @@
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
-#define MICROCODE_VERSION 	"1.06"
+#define MICROCODE_VERSION 	"1.07"
 
 MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
@@ -87,13 +89,10 @@
 
 int __init microcode_init(void)
 {
-	int error = 0;
-
 	if (misc_register(&microcode_dev) < 0) {
-		printk(KERN_WARNING 
-			"microcode: can't misc_register on minor=%d\n",
+		printk(KERN_ERR "microcode: can't misc_register on minor=%d\n",
 			MICROCODE_MINOR);
-		error = 1;
+		return -EINVAL;
 	}
 	printk(KERN_INFO "IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n", 
 			MICROCODE_VERSION);
@@ -234,18 +233,21 @@
 
 static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
 {
-	if (*ppos >= mc_fsize)
-		return 0;
+	ssize_t err = 0;
+
 	down(&microcode_sem);
+	if (*ppos >= mc_fsize)
+		goto out;
 	if (*ppos + len > mc_fsize)
 		len = mc_fsize - *ppos;
-	if (copy_to_user(buf, mc_applied + *ppos, len)) {
-		up(&microcode_sem);
-		return -EFAULT;
-	}
+	err = -EFAULT;
+	if (copy_to_user(buf, mc_applied + *ppos, len))
+		goto out;
 	*ppos += len;
+	err = len;
+out:
 	up(&microcode_sem);
-	return len;
+	return err;
 }
 
 static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
@@ -300,11 +302,12 @@
 		case MICROCODE_IOCFREE:
 			down(&microcode_sem);
 			if (mc_applied) {
+				int bytes = smp_num_cpus * sizeof(struct microcode);
+
 				memset(mc_applied, 0, mc_fsize);
 				kfree(mc_applied);
 				mc_applied = NULL;
-				printk(KERN_WARNING 
-					"microcode: freed %d bytes\n", mc_fsize);
+				printk(KERN_WARNING "microcode: freed %d bytes\n", bytes);
 				mc_fsize = 0;
 				up(&microcode_sem);
 				return 0;
diff -urN linux-2.2.19-pre2/arch/i386/kernel/msr.c linux/arch/i386/kernel/msr.c
--- linux-2.2.19-pre2/arch/i386/kernel/msr.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/i386/kernel/msr.c	Mon Dec  3 20:53:37 2001
@@ -260,6 +260,7 @@
 
 static void msr_exit(void)
 {
+  unregister_chrdev(MSR_MAJOR, "cpu/msr");
 }
 
 module_init(msr_init);
diff -urN linux-2.2.19-pre2/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.2.19-pre2/arch/i386/kernel/setup.c	Mon Dec  3 20:53:10 2001
+++ linux/arch/i386/kernel/setup.c	Mon Dec  3 20:53:37 2001
@@ -104,7 +104,7 @@
 	unsigned short length;
 	unsigned char table[0];
 };
-struct e820map e820;
+struct e820map e820 __initdata = { 0, };
 
 unsigned char aux_device_present;
 
@@ -272,8 +272,9 @@
 					visws_board_rev);
 	}
 #endif
-void __init add_memory_region(unsigned long long start,
-                                  unsigned long long size, int type)
+
+static void __init add_memory_region(unsigned long long start,
+				     unsigned long long size, int type)
 {
        int x = e820.nr_map;
 
@@ -288,6 +289,8 @@
        e820.nr_map++;
 } /* add_memory_region */
 
+unsigned long i386_endbase __initdata =  0;
+
 static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
 {
        /* Only one memory region (or negative)? Ignore it */
@@ -309,10 +312,10 @@
                 * Not right. Fix it up.
                 */
                if (type == E820_RAM) {
-                       if (start < 0x100000ULL && end > 0xA0000ULL) {
-                               if (start < 0xA0000ULL)
-                                       add_memory_region(start, 0xA0000ULL-start, type);
-                               if (end < 0x100000ULL)
+                       if (start < 0x100000ULL && end > i386_endbase) {
+                               if (start < i386_endbase)
+                                       add_memory_region(start, i386_endbase-start, type);
+                               if (end <= 0x100000ULL)
                                        continue;
                                start = 0x100000ULL;
                                size = end - start;
@@ -323,9 +326,33 @@
        return 0;
 }
 
-#define LOWMEMSIZE() (0x9f000)
+static void __init print_memory_map(char *who)
+{
+	int i;
 
-void __init setup_memory_region(void)
+	for (i = 0; i < e820.nr_map; i++) {
+		printk(" %s: %08lx @ %08lx ", who,
+		       (unsigned long) e820.map[i].size,
+		       (unsigned long) e820.map[i].addr);
+		switch (e820.map[i].type) {
+		case E820_RAM:	printk("(usable)\n");
+				break;
+		case E820_RESERVED:
+				printk("(reserved)\n");
+				break;
+		case E820_ACPI:
+				printk("(ACPI data)\n");
+				break;
+		case E820_NVS:
+				printk("(ACPI NVS)\n");
+				break;
+		default:	printk("type %lu\n", e820.map[i].type);
+				break;
+		}
+	}
+}
+
+static void __init setup_memory_region(void)
 {
        char *who = "BIOS-e820";
 
@@ -348,26 +375,27 @@
                }
 
                e820.nr_map = 0;
-               add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-               add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+               add_memory_region(0, i386_endbase, E820_RAM);
+               add_memory_region(HIGH_MEMORY, (mem_size << 10)-HIGH_MEMORY,
+				 E820_RAM);
        }
        printk("BIOS-provided physical RAM map:\n");
+       print_memory_map(who);
 } /* setup_memory_region */
 
 
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
        char saved_command_line[COMMAND_LINE_SIZE];
-unsigned long i386_endbase __initdata =  0;
 
 __initfunc(void setup_arch(char **cmdline_p,
 	unsigned long * memory_start_p, unsigned long * memory_end_p))
 {
-	unsigned long memory_start, memory_end;
-	unsigned long max_pfn;
+	unsigned long memory_start, memory_end = 0;
 	char c = ' ', *to = command_line, *from = COMMAND_LINE;
 	int len = 0;
 	int read_endbase_from_BIOS = 1;
 	int i;
+	unsigned long user_mem = 0;
 
 #ifdef CONFIG_VISWS
 	visws_get_board_type_and_rev();
@@ -402,26 +430,6 @@
 	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
-       setup_memory_region();
-
-#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
-       max_pfn = 0;
-       for (i = 0; i < e820.nr_map; i++) {
-               unsigned long start, end;
-               /* RAM? */
-               if (e820.map[i].type != E820_RAM)
-                       continue;
-               start = PFN_UP(e820.map[i].addr);
-               end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-               if (start >= end)
-                       continue;
-               if (end > max_pfn)
-                       max_pfn = end;
-       }
-       memory_end = (max_pfn << PAGE_SHIFT);
-
-
 	for (;;) {
 		/*
 		 * "mem=nopentium" disables the 4MB page tables.
@@ -434,12 +442,12 @@
 				from += 9+4;
 				boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
 			} else {
-				memory_end = simple_strtoul(from+4, &from, 0);
+				user_mem = simple_strtoul(from+4, &from, 0);
 				if ( *from == 'K' || *from == 'k' ) {
-					memory_end = memory_end << 10;
+					user_mem = user_mem << 10;
 					from++;
 				} else if ( *from == 'M' || *from == 'm' ) {
-					memory_end = memory_end << 20;
+					user_mem = user_mem << 20;
 					from++;
 				}
 			}
@@ -448,7 +456,6 @@
 		{
 			if (to != command_line) to--;
 			i386_endbase = simple_strtoul(from+8, &from, 0);
-			i386_endbase += PAGE_OFFSET;
 			read_endbase_from_BIOS = 0;
 		}
 		c = *(from++);
@@ -484,7 +491,35 @@
 			}
 			i386_endbase = BIOS_ENDBASE;
 		}
-		i386_endbase += PAGE_OFFSET;
+	}
+
+	if (!user_mem)
+		setup_memory_region();
+	else {
+		e820.nr_map = 0;
+		add_memory_region(0, i386_endbase, E820_RAM);
+		add_memory_region(HIGH_MEMORY, user_mem-HIGH_MEMORY, E820_RAM);
+		printk("USER-provided physical RAM map:\n");
+		print_memory_map("USER");
+	}
+
+#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
+	for (i = 0; i < e820.nr_map; i++) {
+		unsigned long long start, end;
+		/* RAM? */
+		if (e820.map[i].type != E820_RAM)
+			continue;
+		start = e820.map[i].addr;
+		if (start >= 0xffffffff)
+			continue;
+		end = e820.map[i].addr + e820.map[i].size;
+		if (start >= end)
+			continue;
+		if (end > 0xffffffff)
+			end = 0xffffffff;
+		if (end > memory_end)
+			memory_end = end;
 	}
 
 #define VMALLOC_RESERVE	(64 << 20)	/* 64MB for vmalloc */
diff -urN linux-2.2.19-pre2/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- linux-2.2.19-pre2/arch/i386/kernel/smp.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/i386/kernel/smp.c	Mon Dec  3 20:53:37 2001
@@ -680,7 +680,7 @@
  */
 unsigned long __init smp_alloc_memory(unsigned long mem_base)
 {
-	if (mem_base + PAGE_SIZE > i386_endbase)
+	if (mem_base + PAGE_SIZE > i386_endbase + PAGE_OFFSET)
 		panic("smp_alloc_memory: Insufficient low memory for kernel trampoline 0x%lx.", mem_base);
 	trampoline_base = (void *)mem_base;
 	return mem_base + PAGE_SIZE;
diff -urN linux-2.2.19-pre2/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- linux-2.2.19-pre2/arch/i386/kernel/traps.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/i386/kernel/traps.c	Mon Dec  3 20:53:37 2001
@@ -106,7 +106,6 @@
 asmlinkage void general_protection(void);
 asmlinkage void page_fault(void);
 asmlinkage void coprocessor_error(void);
-asmlinkage void reserved(void);
 asmlinkage void alignment_check(void);
 asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
@@ -246,7 +245,6 @@
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present, current)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment, current)
 DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
-DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
 /* I don't have documents for this but it does seem to cover the cache
    flush from user space exception some people get. */
 DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current)
diff -urN linux-2.2.19-pre2/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- linux-2.2.19-pre2/arch/i386/mm/init.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/i386/mm/init.c	Mon Dec  3 20:53:37 2001
@@ -27,6 +27,7 @@
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 #include <asm/fixmap.h>
+#include <asm/e820.h>
 
 extern void show_net_buffers(void);
 extern unsigned long init_smp_mappings(unsigned long);
@@ -384,8 +385,6 @@
 		printk(".\n");
 }
 
-extern unsigned long i386_endbase;
-
 __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
 {
 	unsigned long start_low_mem = PAGE_SIZE;
@@ -417,15 +416,36 @@
 #endif
 	start_mem = PAGE_ALIGN(start_mem);
 
-	while (start_low_mem < i386_endbase) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
-		start_low_mem += PAGE_SIZE;
-	}
+	for (tmp = __pa(start_low_mem); tmp < __pa(end_mem);
+	     tmp += PAGE_SIZE) {
+		struct page * page = mem_map + (tmp >> PAGE_SHIFT);
+		int i;
+		extern struct e820map e820;
 
-	while (start_mem < end_mem) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-		start_mem += PAGE_SIZE;
+		/* don't include kernel memory and bootmem allocations */
+		if (tmp >= 0x100000 && tmp < __pa(start_mem))
+			continue;
+
+		for (i = 0; i < e820.nr_map; i++) {
+			unsigned long long start, end;
+			/* RAM? */
+			if (e820.map[i].type != E820_RAM)
+				continue;
+			start = e820.map[i].addr;
+			if (start >= 0xffffffff)
+				continue;
+			end = e820.map[i].addr + e820.map[i].size;
+			if (start >= end)
+				continue;
+			if (end > 0xffffffff)
+				end = 0xffffffff;
+
+			/* start and end are valid here */
+			if (start <= tmp && tmp+PAGE_SIZE <= end)
+				clear_bit(PG_reserved, &page->flags);
+		}
 	}
+
 	for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
 		if (tmp >= MAX_DMA_ADDRESS)
 			clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
diff -urN linux-2.2.19-pre2/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- linux-2.2.19-pre2/arch/ppc/kernel/pmac_setup.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/ppc/kernel/pmac_setup.c	Mon Dec  3 20:53:37 2001
@@ -658,6 +658,10 @@
 	ppc_md.get_rtc_time   = pmac_get_rtc_time;
 	ppc_md.calibrate_decr = pmac_calibrate_decr;
 
+	ppc_md.pci_dev_root_bridge	= pmac_pci_dev_root_bridge;
+	ppc_md.pci_dev_mem_base		= pmac_pci_dev_mem_base;
+	ppc_md.pci_dev_io_base		= pmac_pci_dev_io_base;
+
 #ifdef CONFIG_VT
 #ifdef CONFIG_MAC_KEYBOARD
 	ppc_md.kbd_setkeycode    = mackbd_setkeycode;
diff -urN linux-2.2.19-pre2/arch/s390/config.in linux/arch/s390/config.in
--- linux-2.2.19-pre2/arch/s390/config.in	Sun Dec 10 16:49:41 2000
+++ linux/arch/s390/config.in	Mon Dec  3 20:53:37 2001
@@ -44,11 +44,14 @@
 endmenu
 
 source drivers/s390/Config.in
+
+mainmenu_option next_comment
 comment 'Character devices'
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
   int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
 fi
+endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
diff -urN linux-2.2.19-pre2/arch/s390/kernel/s390_ksyms.c linux/arch/s390/kernel/s390_ksyms.c
--- linux-2.2.19-pre2/arch/s390/kernel/s390_ksyms.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/s390/kernel/s390_ksyms.c	Mon Dec  3 20:53:37 2001
@@ -41,7 +41,9 @@
 EXPORT_SYMBOL(s390_device_register);
 EXPORT_SYMBOL(s390_device_unregister);
 
+#ifdef	__SMP__
 EXPORT_SYMBOL(s390_bh_lock);
+#endif
 
 EXPORT_SYMBOL(ccw_alloc_request);
 EXPORT_SYMBOL(ccw_free_request);
diff -urN linux-2.2.19-pre2/arch/s390/kernel/setup.c linux/arch/s390/kernel/setup.c
--- linux-2.2.19-pre2/arch/s390/kernel/setup.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/s390/kernel/setup.c	Mon Dec  3 20:53:37 2001
@@ -36,6 +36,9 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/smp.h>
+#include "cpcmd.h"
+
+extern void reipl(int ipl_device);
 
 /*
  * Machine setup..
diff -urN linux-2.2.19-pre2/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.2.19-pre2/arch/sparc64/kernel/sys_sparc32.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Mon Dec  3 20:53:37 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.107.2.14 2000/10/10 04:50:50 davem Exp $
+/* $Id: sys_sparc32.c,v 1.107.2.16 2000/12/20 02:45:00 anton Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -3462,7 +3462,7 @@
 	set_fs (KERNEL_DS);
 	sys_get_kernel_syms(tbl);
 	set_fs (old_fs);
-	for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
+	for (i = 0; i < len; i++, table++) {
 		if (put_user (tbl[i].value, &table->value) ||
 		    copy_to_user (table->name, tbl[i].name, 60))
 			break;
@@ -3553,6 +3553,12 @@
 	s32			gf32_version;
 };
 
+struct nfsctl_fdparm32 {
+	struct sockaddr		gd32_addr;
+	s8			gd32_path[NFS_MAXPATHLEN+1];
+	s32			gd32_version;
+};
+
 struct nfsctl_arg32 {
 	s32			ca32_version;	/* safeguard */
 	union {
@@ -3561,6 +3567,7 @@
 		struct nfsctl_export32	u32_export;
 		struct nfsctl_uidmap32	u32_umap;
 		struct nfsctl_fhparm32	u32_getfh;
+		struct nfsctl_fdparm32  u32_getfd;
 		u32			u32_debug;
 	} u;
 #define ca32_svc	u.u32_svc
@@ -3569,6 +3576,7 @@
 #define ca32_umap	u.u32_umap
 #define ca32_getfh	u.u32_getfh
 #define ca32_authd	u.u32_authd
+#define ca32_getfd	u.u32_getfd
 #define ca32_debug	u.u32_debug
 };
 
@@ -3698,6 +3706,22 @@
 	return err;
 }
 
+static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_getfd.gd_addr,
+			  &arg32->ca32_getfd.gd32_addr,
+			  (sizeof(struct sockaddr)));
+	err |= copy_from_user(&karg->ca_getfd.gd_path,
+			  &arg32->ca32_getfd.gd32_path,
+			  (NFS_MAXPATHLEN+1));
+	err |= __get_user(karg->ca_getfd.gd_version,
+		      &arg32->ca32_getfd.gd32_version);
+	return err;
+}
+
 static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
 {
 	int err;
@@ -3739,6 +3763,7 @@
 		err = nfs_clnt32_trans(karg, arg32);
 		break;
 	case NFSCTL_EXPORT:
+	case NFSCTL_UNEXPORT:
 		err = nfs_exp32_trans(karg, arg32);
 		break;
 	/* This one is unimplemented, be we're ready for it. */
@@ -3748,6 +3773,9 @@
 	case NFSCTL_GETFH:
 		err = nfs_getfh32_trans(karg, arg32);
 		break;
+	case NFSCTL_GETFD:
+		err = nfs_getfd32_trans(karg, arg32);
+		break;
 	case NFSCTL_LOCKD:
 		/* We still have to copy over the version
 		 * because nfsctl still checks that.
@@ -3765,7 +3793,11 @@
 	err = sys_nfsservctl(cmd, karg, kres);
 	set_fs(oldfs);
 
-	if(!err && cmd == NFSCTL_GETFH)
+	if (err)
+		goto done;
+
+	if((cmd == NFSCTL_GETFH) ||
+	   (cmd == NFSCTL_GETFD))
 		err = nfs_getfh32_res_trans(kres, res32);
 
 done:
diff -urN linux-2.2.19-pre2/drivers/char/Config.in linux/drivers/char/Config.in
--- linux-2.2.19-pre2/drivers/char/Config.in	Mon Dec  3 20:53:10 2001
+++ linux/drivers/char/Config.in	Mon Dec  3 20:53:37 2001
@@ -102,6 +102,7 @@
   tristate '   Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
   tristate '   Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT
   tristate '   Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
+  tristate '  Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO
   tristate '   Mixcom Watchdog' CONFIG_MIXCOMWD 
   tristate '   SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
   tristate '   Software Watchdog' CONFIG_SOFT_WATCHDOG
diff -urN linux-2.2.19-pre2/drivers/char/Makefile linux/drivers/char/Makefile
--- linux-2.2.19-pre2/drivers/char/Makefile	Mon Dec  3 20:53:10 2001
+++ linux/drivers/char/Makefile	Mon Dec  3 20:53:37 2001
@@ -689,6 +689,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_I810_TCO),y)
+O_OBJS += i810-tco.o
+else
+  ifeq ($(CONFIG_I810_TCO),m)
+  M_OBJS += i810-tco.o
+  endif
+endif
+
 # remove objects from modular that are also built in
 obj-m           := $(filter-out $(obj-y), $(obj-m))
 
diff -urN linux-2.2.19-pre2/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c
--- linux-2.2.19-pre2/drivers/char/i810-tco.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/i810-tco.c	Mon Dec  3 20:53:37 2001
@@ -0,0 +1,343 @@
+/*
+ *	i810-tco 0.02:	TCO timer driver for i810 chipsets
+ *
+ *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
+ *				http://www.kernelconcepts.de
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *	
+ *	Neither kernel concepts nor Nils Faerber admit liability nor provide 
+ *	warranty for any of this software. This material is provided 
+ *	"AS-IS" and at no charge.	
+ *
+ *	(c) Copyright 2000	kernel concepts <nils@kernelconcepts.de>
+ *				developed for
+ *                              Jentro AG, Haar/Munich (Germany)
+ *
+ *	TCO timer driver for i810/i815 chipsets
+ *	based on softdog.c by Alan Cox <alan@redhat.com>
+ *
+ *	The TCO timer is implemented in the 82801AA (82801AB) chip,
+ *	see intel documentation from http://developer.intel.com,
+ *	order number 290655-003
+ *
+ *  20000710 Nils Faerber
+ *	Initial Version 0.01
+ *  20000728 Nils Faerber
+ *      0.02 Fix for SMI_EN->TCO_EN bit, some cleanups
+ */
+ 
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include "i810-tco.h"
+
+
+/* Just in case that the PCI vendor and device IDs are not yet defined */
+#ifndef PCI_DEVICE_ID_INTEL_82801AA_0
+#define PCI_DEVICE_ID_INTEL_82801AA_0	0x2410
+#endif
+
+/* Default expire timeout */
+#define TIMER_MARGIN	50	/* steps of 0.6sec, 2<n<64. Default is 30 seconds */
+
+static unsigned int ACPIBASE;
+static spinlock_t tco_lock;	/* Guards the hardware */
+
+static int i810_margin = TIMER_MARGIN;	/* steps of 0.6sec */
+
+MODULE_PARM (i810_margin, "i");
+
+/*
+ *	Timer active flag
+ */
+
+static int timer_alive;
+static int boot_status;
+
+/*
+ * Some i810 specific functions
+ */
+
+
+/*
+ * Start the timer countdown
+ */
+static int tco_timer_start (void)
+{
+	unsigned char val;
+
+	spin_lock(&tco_lock);
+	val = inb (TCO1_CNT + 1);
+	val &= 0xf7;
+	outb (val, TCO1_CNT + 1);
+	val = inb (TCO1_CNT + 1);
+	spin_unlock(&tco_lock);
+	
+	if (val & 0x08)
+		return -1;
+	return 0;
+}
+
+/*
+ * Stop the timer countdown
+ */
+static int tco_timer_stop (void)
+{
+	unsigned char val;
+
+	spin_lock(&tco_lock);
+	val = inb (TCO1_CNT + 1);
+	val |= 0x08;
+	outb (val, TCO1_CNT + 1);
+	val = inb (TCO1_CNT + 1);
+	spin_unlock(&tco_lock);
+	
+	if ((val & 0x08) == 0)
+		return -1;
+	return 0;
+}
+
+/*
+ * Set the timer reload value
+ */
+static int tco_timer_settimer (unsigned char tmrval)
+{
+	unsigned char val;
+
+	/* from the specs: */
+	/* "Values of 0h-3h are ignored and should not be attempted" */
+	if (tmrval > 0x3f || tmrval < 0x03)
+		return -1;
+	
+	spin_lock(&tco_lock);
+	val = inb (TCO1_TMR);
+	val &= 0xc0;
+	val |= tmrval;
+	outb (val, TCO1_TMR);
+	val = inb (TCO1_TMR);
+	spin_unlock(&tco_lock);
+	
+	if ((val & 0x3f) != tmrval)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Reload (trigger) the timer. Lock is needed so we dont reload it during
+ * a reprogramming event
+ */
+ 
+static void tco_timer_reload (void)
+{
+	spin_lock(&tco_lock);
+	outb (0x01, TCO1_RLD);
+	spin_unlock(&tco_lock);
+}
+
+/*
+ * Read the current timer value
+ */
+static unsigned char tco_timer_read (void)
+{
+	return (inb (TCO1_RLD));
+}
+
+
+/*
+ *	Allow only one person to hold it open
+ */
+
+static int i810tco_open (struct inode *inode, struct file *file)
+{
+	if (timer_alive)
+		return -EBUSY;
+
+	/*
+	 *      Reload and activate timer
+	 */
+	tco_timer_reload ();
+	tco_timer_start ();
+	timer_alive = 1;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int i810tco_release (struct inode *inode, struct file *file)
+{
+	/*
+	 *      Shut off the timer.
+	 */
+	MOD_INC_USE_COUNT;
+	tco_timer_stop ();
+	timer_alive = 0;
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static ssize_t i810tco_write (struct file *file, const char *data,
+			      size_t len, loff_t * ppos)
+{
+	/*  Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	/*
+	 *      Refresh the timer.
+	 */
+	if (len) {
+		tco_timer_reload ();
+		return 1;
+	}
+	return 0;
+}
+
+static int i810tco_ioctl (struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg)
+{
+	static struct watchdog_info ident = {
+		0,
+		0,
+		"i810 TCO timer"
+	};
+	switch (cmd) {
+	default:
+		return -ENOIOCTLCMD;
+	case WDIOC_GETSUPPORT:
+		if (copy_to_user
+		    ((struct watchdog_info *) arg, &ident, sizeof (ident)))
+			return -EFAULT;
+		return 0;
+	case WDIOC_GETSTATUS:
+		return put_user (tco_timer_read (),
+				 (unsigned int *) (int) arg);
+	case WDIOC_GETBOOTSTATUS:
+		return put_user (boot_status, (int *) arg);
+	case WDIOC_KEEPALIVE:
+		tco_timer_reload ();
+		return 0;
+	}
+}
+
+static struct pci_dev *i810tco_pci;
+
+static unsigned char i810tco_getdevice (void)
+{
+	u8 val1, val2;
+	u16 badr;
+	/*
+	 *      Find the PCI device which has vendor id 0x8086
+	 *      and device ID 0x2410
+	 */
+	i810tco_pci = pci_find_device (PCI_VENDOR_ID_INTEL,
+				       PCI_DEVICE_ID_INTEL_82801AA_0, NULL);
+	if (i810tco_pci) {
+		/*
+		 *      Find the ACPI base I/O address which is the base
+		 *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
+		 *      ACPIBASE is bits [15:7] from 0x40-0x43
+		 */
+		pci_read_config_byte (i810tco_pci, 0x40, &val1);
+		pci_read_config_byte (i810tco_pci, 0x41, &val2);
+		badr = ((val2 << 1) | (val1 >> 7)) << 7;
+		ACPIBASE = badr;
+		/* Something's wrong here, ACPIBASE has to be set */
+		if (badr == 0x0001 || badr == 0x0000) {
+			printk (KERN_ERR "i810tco init: failed to get TCOBASE address\n");
+			return 0;
+		}
+		/*
+		 * Check chipset's NO_REBOOT bit
+		 */
+		pci_read_config_byte (i810tco_pci, 0xd4, &val1);
+		if (val1 & 0x02) {
+			val1 &= 0xfd;
+			pci_write_config_byte (i810tco_pci, 0xd4, val1);
+			pci_read_config_byte (i810tco_pci, 0xd4, &val1);
+			if (val1 & 0x02) {
+				printk (KERN_ERR "i810tco init: failed to reset NO_REBOOT flag\n");
+				return 0;	/* Cannot reset NO_REBOOT bit */
+			}
+		}
+		/* Set the TCO_EN bit in SMI_EN register */
+		val1 = inb (SMI_EN + 1);
+		val1 &= 0xdf;
+		outb (val1, SMI_EN + 1);
+		/* Clear out the (probably old) status */
+		outb (0, TCO1_STS);
+		boot_status = (int) inb (TCO2_STS);
+		outb (3, TCO2_STS);
+		return 1;
+	}
+	return 0;
+}
+
+static struct file_operations i810tco_fops = {
+	write:		i810tco_write,
+	ioctl:		i810tco_ioctl,
+	open:		i810tco_open,
+	release:	i810tco_release,
+};
+
+static struct miscdevice i810tco_miscdev = {
+	WATCHDOG_MINOR,
+	"watchdog",
+	&i810tco_fops
+};
+
+static int __init watchdog_init (void)
+{
+	spin_lock_init(&tco_lock);
+	if (!i810tco_getdevice () || i810tco_pci == NULL)
+		return -ENODEV;
+	if (!check_region (TCOBASE, 0x10)) {
+		printk (KERN_ERR
+			"i810 TCO timer: I/O address 0x%04x already in use\n",
+			TCOBASE);
+		return -EIO;
+	}
+	request_region (TCOBASE, 0x10, "i810 TCO");
+	if (misc_register (&i810tco_miscdev) != 0) {
+		release_region (TCOBASE, 0x10);
+		printk (KERN_ERR "i810 TCO timer: cannot register miscdev\n");
+		return -EIO;
+	}
+	tco_timer_settimer ((unsigned char) i810_margin);
+	tco_timer_reload ();
+
+	printk (KERN_INFO
+		"i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n",
+		(int) (i810_margin * 6 / 10), TCOBASE);
+	return 0;
+}
+
+static void watchdog_cleanup (void)
+{
+	u8 val;
+
+	/* Reset the timer before we leave */
+	tco_timer_reload ();
+	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+	pci_read_config_byte (i810tco_pci, 0xd4, &val);
+	val |= 0x02;
+	pci_write_config_byte (i810tco_pci, 0xd4, val);
+	release_region (TCOBASE, 0x10);
+	misc_deregister (&i810tco_miscdev);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
diff -urN linux-2.2.19-pre2/drivers/char/i810-tco.h linux/drivers/char/i810-tco.h
--- linux-2.2.19-pre2/drivers/char/i810-tco.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/i810-tco.h	Mon Dec  3 20:53:37 2001
@@ -0,0 +1,45 @@
+/*
+ *	i810-tco 0.02:	TCO timer driver for i810 chipsets
+ *
+ *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
+ *				http://www.kernelconcepts.de
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *	
+ *	Neither kernel concepts nor Nils Faerber admit liability nor provide 
+ *	warranty for any of this software. This material is provided 
+ *	"AS-IS" and at no charge.	
+ *
+ *	(c) Copyright 2000	kernel concepts <nils@kernelconcepts.de>
+ *				developed for
+ *                              Jentro AG, Haar/Munich (Germany)
+ *
+ *	TCO timer driver for i810 chipsets
+ *	based on softdog.c by Alan Cox <alan@redhat.com>
+ *
+ *      The TCO timer is implemented in the 82801AA (82801AB) chip,
+ *	see intel documentation from http://developer.intel.com,
+ *	order number 290655-003
+ *
+ *	For history see i810-tco.c
+ */
+
+
+/*
+ * Some address definitions for the i810 TCO
+ */
+
+#define	TCOBASE		ACPIBASE + 0x60	/* TCO base address		*/
+#define TCO1_RLD	TCOBASE + 0x00	/* TCO Timer Reload and Current Value */
+#define TCO1_TMR	TCOBASE + 0x01	/* TCO Timer Initial Value	*/
+#define	TCO1_DAT_IN	TCOBASE + 0x02	/* TCO Data In Register		*/
+#define	TCO1_DAT_OUT	TCOBASE + 0x03	/* TCO Data Out Register	*/
+#define	TCO1_STS	TCOBASE + 0x04	/* TCO1 Status Register		*/
+#define	TCO2_STS	TCOBASE + 0x06	/* TCO2 Status Register		*/
+#define TCO1_CNT	TCOBASE + 0x08	/* TCO1 Control Register	*/
+#define TCO2_CNT	TCOBASE + 0x0a	/* TCO2 Control Register	*/
+
+#define	SMI_EN		ACPIBASE + 0x30	/* SMI Control and Enable Register */
diff -urN linux-2.2.19-pre2/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c
--- linux-2.2.19-pre2/drivers/char/n_hdlc.c	Sun Dec 10 16:49:42 2000
+++ linux/drivers/char/n_hdlc.c	Mon Dec  3 20:53:37 2001
@@ -9,7 +9,7 @@
  *	Al Longyear <longyear@netcom.com>, Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
  *
  * Original release 01/11/99
- * ==FILEDATE 20000515==
+ * $Id: n_hdlc.c,v 2.2 2000/11/08 17:08:29 paul Exp $
  *
  * This code is released under the GNU General Public License (GPL)
  *
@@ -78,7 +78,7 @@
  */
 
 #define HDLC_MAGIC 0x239e
-#define HDLC_VERSION "1.15"
+#define HDLC_VERSION "2.2"
 
 #include <linux/version.h>
 #include <linux/config.h>
@@ -93,14 +93,7 @@
 #undef VERSION
 #define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch))
 
-#if LINUX_VERSION_CODE < VERSION(2,1,14)
-#include <linux/ioport.h>
-#endif
-
-#if LINUX_VERSION_CODE >= VERSION(2,1,23)
 #include <linux/poll.h>
-#endif
-
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/tty.h>
@@ -118,79 +111,23 @@
 #include <linux/kerneld.h>
 #endif
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,4)
+#if LINUX_VERSION_CODE < VERSION(2,2,18) 
+typedef struct wait_queue *wait_queue_head_t;
+#define DECLARE_WAITQUEUE(name,task) struct wait_queue (name) = {(task),NULL}
+#define init_waitqueue_head(head) *(head) = NULL
+#define set_current_state(a) current->state = (a)
+#endif
+
 #include <asm/segment.h>
 #define GET_USER(error,value,addr) error = get_user(value,addr)
 #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
 #define PUT_USER(error,value,addr) error = put_user(value,addr)
 #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,5)
 #include <asm/uaccess.h>
-#endif
-
-#else  /* 2.0.x and 2.1.x before 2.1.4 */
-
-#define GET_USER(error,value,addr)					  \
-do {									  \
-	error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
-	if (error == 0)							  \
-		value = get_user(addr);					  \
-} while (0)
-
-#define COPY_FROM_USER(error,dest,src,size)				  \
-do {									  \
-	error = verify_area (VERIFY_READ, (void *) src, size);		  \
-	if (error == 0)							  \
-		memcpy_fromfs (dest, src, size);			  \
-} while (0)
-
-#define PUT_USER(error,value,addr)					   \
-do {									   \
-	error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
-	if (error == 0)							   \
-		put_user (value, addr);					   \
-} while (0)
-
-#define COPY_TO_USER(error,dest,src,size)				  \
-do {									  \
-	error = verify_area (VERIFY_WRITE, (void *) dest, size);		  \
-	if (error == 0)							  \
-		memcpy_tofs (dest, src, size);				  \
-} while (0)
 
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,0)
-#define __init
-typedef int spinlock_t;
-#define spin_lock_init(a)
-#define spin_lock_irqsave(a,b) {save_flags((b));cli();}
-#define spin_unlock_irqrestore(a,b) {restore_flags((b));}
-#define spin_lock(a)
-#define spin_unlock(a)
-#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,37)
-#define test_and_set_bit(nr, addr)	set_bit(nr, addr)
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,57)
-#define signal_pending(p)	((p)->signal & ~(p)->blocked)
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,25)
-#define net_device_stats	enet_statistics
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,60)
-typedef int		rw_ret_t;
-typedef unsigned int	rw_count_t;
-#else
 typedef ssize_t		rw_ret_t;
 typedef size_t		rw_count_t;
-#endif
 
 /*
  * Buffers for individual HDLC frames
@@ -254,10 +191,8 @@
 
 static struct n_hdlc *n_hdlc_alloc (void);
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,19) 
 MODULE_PARM(debuglevel, "i");
 MODULE_PARM(maxframe, "i");
-#endif
 
 /* debug level can be set by insmod for debugging purposes */
 #define DEBUG_LEVEL_INFO	1
@@ -274,13 +209,8 @@
 	struct file *, const __u8 *, rw_count_t);
 static int n_hdlc_tty_ioctl(struct tty_struct *,
 	struct file *, unsigned int, unsigned long);
-#if LINUX_VERSION_CODE < VERSION(2,1,23)
-static int n_hdlc_tty_select (struct tty_struct *tty, struct inode *inode,
-		      struct file *filp, int sel_type, select_table * wait);
-#else
 static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, struct file *filp,
 				  poll_table * wait);
-#endif
 static int n_hdlc_tty_open (struct tty_struct *);
 static void n_hdlc_tty_close (struct tty_struct *);
 static int n_hdlc_tty_room (struct tty_struct *tty);
@@ -653,10 +583,10 @@
 	wake_up_interruptible (&n_hdlc->read_wait);
 	wake_up_interruptible (&n_hdlc->poll_wait);
 	if (n_hdlc->tty->fasync != NULL)
-#if LINUX_VERSION_CODE < VERSION(2,3,0) 
-		kill_fasync (n_hdlc->tty->fasync, SIGIO);
-#else
+#if LINUX_VERSION_CODE >= VERSION(2,2,14) && defined(__rh_config_h__)
 		kill_fasync (n_hdlc->tty->fasync, SIGIO, POLL_IN);
+#else
+		kill_fasync (n_hdlc->tty->fasync, SIGIO);
 #endif
 }	/* end of n_hdlc_tty_receive() */
 
@@ -886,73 +816,6 @@
 	
 }	/* end of n_hdlc_tty_ioctl() */
 
-#if LINUX_VERSION_CODE < VERSION(2,1,23)
-/* n_hdlc_tty_select()
- * 
- * 	Device select method. Determine if operation requires
- * 	blocking and if so put appropriate wait queue in select
- * 	table and return 0, otherwise return 1.
- * 	
- * Arguments:
- * 
- * 	tty		pointer to tty device instance data
- * 	inode		pointer to inode for device
- * 	filp		pointer to file object
- * 	sel_type	identified the select type (read/write/exception)
- * 	wait		select table for adding wait queue if appropriate
- * 	
- * Return Value:
- * 
- * 	1 if no need to block on operation
- * 	0 if must block and wait queue added to select table
- */
-static int n_hdlc_tty_select (struct tty_struct *tty, struct inode *inode,
-		struct file *filp, int sel_type, select_table * wait)
-{
-	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
-	int result = 1;
-	
-	if (debuglevel >= DEBUG_LEVEL_INFO)	
-		printk("%s(%d)n_hdlc_tty_select() called\n",__FILE__,__LINE__);
-		
-	/* Verify the status of the device */
-	if (!n_hdlc)
-		return -EBADF;
-
-	if (n_hdlc->magic != HDLC_MAGIC || tty != n_hdlc->tty)
-		return -EBADF;
-
-	switch (sel_type) {
-	case SEL_IN:
-		if (n_hdlc->rx_buf_list.head)
-			break;
-
-	case SEL_EX:	/* Exceptions or read errors */
-		/* Is this a pty link and the remote disconnected? */
-		if (tty->flags & (1 << TTY_OTHER_CLOSED))
-			break;
-
-		/* Is this a local link and the modem disconnected? */
-		if (tty_hung_up_p (filp))
-			break;
-
-		select_wait (&n_hdlc->read_wait, wait);
-		result = 0;
-		break;
-		
-	/* Write mode. A write is allowed if there is no current transmission */
-	case SEL_OUT:
-		if (!n_hdlc->tx_free_buf_list.head) {
-			select_wait (&n_hdlc->write_wait, wait);
-			result = 0;
-		}
-		break;
-	}
-	return result;
-}	/* end of n_hdlc_tty_select() */
-
-#else	/* 2.1.23 or later */
-
 /* n_hdlc_tty_poll()
  * 
  * 	TTY callback for poll system call. Determine which 
@@ -981,11 +844,8 @@
 	if (n_hdlc && n_hdlc->magic == HDLC_MAGIC && tty == n_hdlc->tty) {
 		/* queue current process into any wait queue that */
 		/* may awaken in the future (read and write) */
-#if LINUX_VERSION_CODE < VERSION(2,1,89)
-		poll_wait(&n_hdlc->poll_wait, wait);
-#else
 		poll_wait(filp, &n_hdlc->poll_wait, wait);
-#endif
+
 		/* set bits for operations that wont block */
 		if(n_hdlc->rx_buf_list.head)
 			mask |= POLLIN | POLLRDNORM;	/* readable */
@@ -999,8 +859,6 @@
 	return mask;
 }	/* end of n_hdlc_tty_poll() */
 
-#endif
-
 /* n_hdlc_alloc()
  * 
  * 	Allocate an n_hdlc instance data structure
@@ -1153,19 +1011,13 @@
 	
 	memset(&n_hdlc_ldisc, 0, sizeof (n_hdlc_ldisc));
 	n_hdlc_ldisc.magic		= TTY_LDISC_MAGIC;
-#if LINUX_VERSION_CODE >= VERSION(2,1,28)
 	n_hdlc_ldisc.name          	= "hdlc";
-#endif
 	n_hdlc_ldisc.open		= n_hdlc_tty_open;
 	n_hdlc_ldisc.close		= n_hdlc_tty_close;
 	n_hdlc_ldisc.read		= n_hdlc_tty_read;
 	n_hdlc_ldisc.write		= n_hdlc_tty_write;
 	n_hdlc_ldisc.ioctl		= n_hdlc_tty_ioctl;
-#if LINUX_VERSION_CODE < VERSION(2,1,23)
-	n_hdlc_ldisc.select		= n_hdlc_tty_select;
-#else
 	n_hdlc_ldisc.poll		= n_hdlc_tty_poll;
-#endif
 	n_hdlc_ldisc.receive_room	= n_hdlc_tty_room;
 	n_hdlc_ldisc.receive_buf	= n_hdlc_tty_receive;
 	n_hdlc_ldisc.write_wakeup	= n_hdlc_tty_wakeup;
diff -urN linux-2.2.19-pre2/drivers/char/synclink.c linux/drivers/char/synclink.c
--- linux-2.2.19-pre2/drivers/char/synclink.c	Sun Dec 10 16:49:42 2000
+++ linux/drivers/char/synclink.c	Mon Dec  3 20:53:37 2001
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * ==FILEDATE 20000821==
+ * $Id: synclink.c,v 2.4 2000/12/11 20:08:18 paul Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -79,17 +79,10 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
-
 #include <linux/netdevice.h>
-
-#if LINUX_VERSION_CODE >= VERSION(2,1,0) 
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <asm/serial.h>
-#else
-#include <linux/bios32.h>
-#endif
-
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 
@@ -102,90 +95,34 @@
 #include <linux/termios.h>
 #include <linux/tqueue.h>
 
+#if LINUX_VERSION_CODE < VERSION(2,2,18) 
+typedef struct wait_queue *wait_queue_head_t;
+#define DECLARE_WAITQUEUE(name,task) struct wait_queue (name) = {(task),NULL}
+#define init_waitqueue_head(head) *(head) = NULL
+#define DECLARE_MUTEX(name) struct semaphore (name) = MUTEX
+#define set_current_state(a) current->state = (a)
+#endif
+
 #ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
 #define CONFIG_SYNCLINK_SYNCPPP 1
 #endif
 
 #ifdef CONFIG_SYNCLINK_SYNCPPP
-#if LINUX_VERSION_CODE < VERSION(2,3,43) 
 #include "../net/syncppp.h"
 #define net_device device
 #define netif_stop_queue(a) (a)->tbusy = 1
 #define netif_start_queue(a) (a)->tbusy = 0
 #define netif_wake_queue(a) (a)->tbusy = 0; mark_bh(NET_BH)
 #define netif_queue_stopped(a) ((a)->tbusy)
-#else
-#include "../net/wan/syncppp.h"
-#endif
 #endif
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,4)
 #include <asm/segment.h>
 #define GET_USER(error,value,addr) error = get_user(value,addr)
 #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
 #define PUT_USER(error,value,addr) error = put_user(value,addr)
 #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,5)
 #include <asm/uaccess.h>
-#endif
-
-#else  /* 2.0.x and 2.1.x before 2.1.4 */
-
-#define GET_USER(error,value,addr)					  \
-do {									  \
-	error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
-	if (error == 0)							  \
-		value = get_user(addr);					  \
-} while (0)
-
-#define COPY_FROM_USER(error,dest,src,size)				  \
-do {									  \
-	error = verify_area (VERIFY_READ, (void *) src, size);		  \
-	if (error == 0)							  \
-		memcpy_fromfs (dest, src, size);			  \
-} while (0)
-
-#define PUT_USER(error,value,addr)					   \
-do {									   \
-	error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
-	if (error == 0)							   \
-		put_user (value, addr);					   \
-} while (0)
-
-#define COPY_TO_USER(error,dest,src,size)				  \
-do {									  \
-	error = verify_area (VERIFY_WRITE, (void *) dest, size);		  \
-	if (error == 0)							  \
-		memcpy_tofs (dest, src, size);				  \
-} while (0)
-
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,0)
-/*
- * This is used to figure out the divisor speeds and the timeouts
- */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
-
-#define __init
-#define ioremap(a,b) vremap((a),(b))
-#define iounmap(a) vfree((a))
-#define SERIAL_TYPE_NORMAL	1
-#define SERIAL_TYPE_CALLOUT	2
-typedef int spinlock_t;
-#define spin_lock_init(a)
-#define spin_lock_irqsave(a,b) {save_flags((b));cli();}
-#define spin_unlock_irqrestore(a,b) {restore_flags((b));}
-#define spin_lock(a)
-#define spin_unlock(a)
-#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
-#define signal_pending(a) ((a)->signal & ~(a)->blocked)
-#endif
-
-
 
 #include "linux/synclink.h"
 
@@ -944,7 +881,6 @@
 static int maxframe[MAX_TOTAL_DEVICES] = {0,};
 static int dosyncppp[MAX_TOTAL_DEVICES] = {0,};
 	
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 MODULE_PARM(break_on_load,"i");
 MODULE_PARM(ttymajor,"i");
 MODULE_PARM(cuamajor,"i");
@@ -954,10 +890,9 @@
 MODULE_PARM(debug_level,"i");
 MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
-#endif
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "1.22";
+static char *driver_version = "2.3";
 
 static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
@@ -969,9 +904,9 @@
 static void mgsl_change_params(struct mgsl_struct *info);
 static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
 
-static struct tty_struct **serial_table = NULL;
-static struct termios **serial_termios = NULL;
-static struct termios **serial_termios_locked = NULL;
+static struct tty_struct *serial_table[MAX_TOTAL_DEVICES];
+static struct termios *serial_termios[MAX_TOTAL_DEVICES];
+static struct termios *serial_termios_locked[MAX_TOTAL_DEVICES];
 
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
@@ -1372,11 +1307,6 @@
 #endif
 			} else
 				info->input_signal_events.dcd_down++;
-#ifdef CONFIG_HARD_PPS
-			if ((info->flags & ASYNC_HARDPPS_CD) &&
-			    (status & MISCSTATUS_DCD_LATCHED))
-				hardpps();
-#endif
 		}
 		if (status & MISCSTATUS_CTS_LATCHED)
 		{
@@ -1583,14 +1513,8 @@
 			icount->parity,icount->frame,icount->overrun);
 	}
 			
-	if ( tty->flip.count ) {
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
+	if ( tty->flip.count )
 		tty_flip_buffer_push(tty);
-#else		
-		queue_task(&tty->flip.tqueue, &tq_timer); 
-#endif		
-	}
-	
 
 }	/* end of mgsl_isr_receive_data() */
 
@@ -1787,11 +1711,7 @@
 		retval = mgsl_adapter_test(info);
 		
 	if ( retval ) {
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
   		if (capable(CAP_SYS_ADMIN) && info->tty)
-#else
-  		if (suser() && info->tty)
-#endif		
 			set_bit(TTY_IO_ERROR, &info->tty->flags);
 		mgsl_release_resources(info);
   		return retval;
@@ -1967,19 +1887,7 @@
 	 * current data rate.
 	 */
 	if (info->params.data_rate <= 460800) {
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 		info->params.data_rate = tty_get_baud_rate(info->tty);
-#else
-		int i = cflag & CBAUD;
-		if (i & CBAUDEX) {
-			i &= ~CBAUDEX;
-			if (i < 1 || i > 4) 
-				info->tty->termios->c_cflag &= ~CBAUDEX;
-			else
-				i += 15;
-		}
-		info->params.data_rate = baud_table[i];
-#endif	
 	}
 	
 	if ( info->params.data_rate ) {
@@ -2942,7 +2850,6 @@
 	
 }	/* end of set_modem_info() */
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 /* mgsl_break()		Set or clear transmit break condition
  *
  * Arguments:		tty		pointer to tty instance data
@@ -2969,7 +2876,6 @@
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	
 }	/* end of mgsl_break() */
-#endif
 
 /* mgsl_ioctl()	Service an IOCTL request
  * 	
@@ -3092,7 +2998,6 @@
 			if (error) return error;
 			PUT_USER(error,cnow.dcd, &p_cuser->dcd);
 			if (error) return error;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 			PUT_USER(error,cnow.rx, &p_cuser->rx);
 			if (error) return error;
 			PUT_USER(error,cnow.tx, &p_cuser->tx);
@@ -3107,7 +3012,6 @@
 			if (error) return error;
 			PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
 			if (error) return error;
-#endif			
 			return 0;
 		default:
 			return -ENOIOCTLCMD;
@@ -3346,7 +3250,6 @@
 		}
 	}
       
-	set_current_state(TASK_RUNNING);
 exit:
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_wait_until_sent(%s) exit\n",
@@ -3589,9 +3492,7 @@
 			tmp_buf = (unsigned char *) page;
 	}
 	
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-#endif
 
 	spin_lock_irqsave(&info->netlock, flags);
 	if (info->netcount) {
@@ -3978,27 +3879,19 @@
 
 }	/* end of mgsl_alloc_buffer_list_memory() */
 
-/*
- * mgsl_free_buffer_list_memory()
- * 
- * 	Free the common DMA buffer allocated for use as the
- * 	receive and transmit buffer lists. The associated Memory
- * 	Descriptor List (MDL) is also freed.
- * 
+/* Free DMA buffers allocated for use as the
+ * receive and transmit buffer lists.
  * Warning:
  * 
  * 	The data transfer buffers associated with the buffer list
  * 	MUST be freed before freeing the buffer list itself because
  * 	the buffer list contains the information necessary to free
  * 	the individual buffers!
- * 
- * Arguments:		info	pointer to device extension
- * Return Value:	None
  */
 void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
 {
 	if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI )
-		kfree_s(info->buffer_list, BUFFERLISTSIZE);
+		kfree(info->buffer_list);
 		
 	info->buffer_list = NULL;
 	info->rx_buffer_list = NULL;
@@ -4072,7 +3965,7 @@
 		for ( i = 0 ; i < Buffercount ; i++ ) {
 			if ( BufferList[i].virt_addr ) {
 				if ( info->bus_type != MGSL_BUS_TYPE_PCI )
-					kfree_s(BufferList[i].virt_addr, DMABUFFERSIZE);
+					kfree(BufferList[i].virt_addr);
 				BufferList[i].virt_addr = NULL;
 			}
 		}
@@ -4131,19 +4024,12 @@
 void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
 {
 	if ( info->intermediate_rxbuffer )
-		kfree_s( info->intermediate_rxbuffer, info->max_frame_size);
+		kfree(info->intermediate_rxbuffer);
 
 	info->intermediate_rxbuffer = NULL;
 
 }	/* end of mgsl_free_intermediate_rxbuffer_memory() */
 
-/* mgsl_claim_resources()
- * 
- * 	Claim all resources used by a device
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise -ENODEV
- */
 int mgsl_claim_resources(struct mgsl_struct *info)
 {
 	/* claim 16C32 I/O base address */
@@ -4168,7 +4054,7 @@
 	info->irq_requested = 1;
 	
 	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/* claim shared memory range */
+
 		info->memory_base = ioremap(info->phys_memory_base,0x40000);
 		if (!info->memory_base) {
 			printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n",
@@ -4177,7 +4063,6 @@
 			return -ENODEV;
 		}
 		
-		/* test the shared memory range */
 		if ( !mgsl_memory_test(info) ) {
 			printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
 				__FILE__,__LINE__,info->device_name, info->phys_memory_base );
@@ -4185,7 +4070,6 @@
 			return -ENODEV;
 		}
 		
-		/* claim LCR memory range */
 		info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
 		if (!info->lcr_base) {
 			printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n",
@@ -4221,13 +4105,6 @@
 		
 }	/* end of mgsl_claim_resources() */
 
-/* mgsl_release_resources()
- * 
- * 	Release all resources used by a device
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
 void mgsl_release_resources(struct mgsl_struct *info)
 {
 	if ( debug_level >= DEBUG_LEVEL_INFO )
@@ -4380,9 +4257,7 @@
 			printk("ISA device specified io=%04X,irq=%d,dma=%d\n",
 				io[i], irq[i], dma[i] );
 		
-		info = mgsl_allocate_device();
-		if ( !info ) {
-			/* error allocating device instance data */
+		if (!(info = mgsl_allocate_device())) {
 			if ( debug_level >= DEBUG_LEVEL_ERROR )
 				printk( "can't allocate device instance data.\n");
 			continue;
@@ -4391,12 +4266,7 @@
 		/* Copy user configuration info to device instance data */
 		info->io_base = (unsigned int)io[i];
 		info->irq_level = (unsigned int)irq[i];
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 		info->irq_level = irq_cannonicalize(info->irq_level);
-#else		
-		if (info->irq_level == 2)
-			info->irq_level = 9;
-#endif			
 		info->dma_level = (unsigned int)dma[i];
 		info->bus_type = MGSL_BUS_TYPE_ISA;
 		info->io_addr_size = 16;
@@ -4412,73 +4282,29 @@
 	if ( pcibios_present() ) {
 		unsigned char bus;
 		unsigned char func;
-		unsigned int  shared_mem_base;
-		unsigned int  lcr_mem_base;
-		unsigned int  io_base;
-		unsigned char irq_line;
 		
 		for(i=0;;i++){
 			if ( PCIBIOS_SUCCESSFUL == pcibios_find_device(
 				MICROGATE_VENDOR_ID, SYNCLINK_DEVICE_ID, i, &bus, &func) ) {
 				
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 				struct pci_dev *pdev = pci_find_slot(bus,func);
-				irq_line = pdev->irq;				
-#else												
-				if (pcibios_read_config_byte(bus,func,
-					PCI_INTERRUPT_LINE,&irq_line) ) {
-					printk( "%s(%d):USC I/O addr not set.\n",
-						__FILE__,__LINE__);
-					continue;
-				}
-#endif
-
-				if (pcibios_read_config_dword(bus,func,
-					PCI_BASE_ADDRESS_3,&shared_mem_base) ) {
-					printk( "%s(%d):Shared mem addr not set.\n",
-						__FILE__,__LINE__);
-					continue;
-				}
-							
-				if (pcibios_read_config_dword(bus,func,
-					PCI_BASE_ADDRESS_0,&lcr_mem_base) ) {
-					printk( "%s(%d):LCR mem addr not set.\n",
-						__FILE__,__LINE__);
-					continue;
-				}
 				
-				if (pcibios_read_config_dword(bus,func,
-					PCI_BASE_ADDRESS_2,&io_base) ) {
-					printk( "%s(%d):USC I/O addr not set.\n",
-						__FILE__,__LINE__);
-					continue;
-				}
-				
-				info = mgsl_allocate_device();
-				if ( !info ) {
-					/* error allocating device instance data */
+				if (!(info = mgsl_allocate_device())) {
 					if ( debug_level >= DEBUG_LEVEL_ERROR )
 						printk( "can't allocate device instance data.\n");
 					continue;
 				}
 		
 				/* Copy user configuration info to device instance data */
+				info->irq_level = pdev->irq;				
+				info->phys_lcr_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+				info->io_base = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
+				info->phys_memory_base = pdev->base_address[3] & PCI_BASE_ADDRESS_MEM_MASK;
 		
-				info->io_base = io_base & PCI_BASE_ADDRESS_IO_MASK;
-				info->irq_level = (unsigned int)irq_line;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
-				info->irq_level = irq_cannonicalize(info->irq_level);
-#else		
-				if (info->irq_level == 2)
-					info->irq_level = 9;
-#endif			
-				info->phys_memory_base = shared_mem_base & PCI_BASE_ADDRESS_MEM_MASK;
-				
 				/* Because veremap only works on page boundaries we must map
 				 * a larger area than is actually implemented for the LCR
 				 * memory range. We map a full page starting at the page boundary.
 				 */
-				info->phys_lcr_base = lcr_mem_base & PCI_BASE_ADDRESS_MEM_MASK;
 				info->lcr_offset    = info->phys_lcr_base & (PAGE_SIZE-1);
 				info->phys_lcr_base &= ~(PAGE_SIZE-1);
 				
@@ -4508,30 +4334,9 @@
 	}
 #endif
 
-	/*
-	 * Allocate memory to hold the following tty/termios arrays
-	 * with an element for each enumerated device.
-	 */	
-	
-	serial_table = (struct tty_struct**)kmalloc(sizeof(struct tty_struct*)*mgsl_device_count, GFP_KERNEL);
-	serial_termios = (struct termios**)kmalloc(sizeof(struct termios*)*mgsl_device_count, GFP_KERNEL);
-	serial_termios_locked = (struct termios**)kmalloc(sizeof(struct termios*)*mgsl_device_count, GFP_KERNEL);
-	
-	if (!serial_table || !serial_termios || !serial_termios_locked){
-		printk("%s(%d):Can't allocate tty/termios arrays.\n",
-			__FILE__,__LINE__);
-		if (serial_table)
-			kfree(serial_table);
-		if (serial_termios)
-			kfree(serial_termios);
-		if (serial_termios_locked)
-			kfree(serial_termios_locked);
-		return -ENOMEM;
-	}
-	
-	memset(serial_table,0,sizeof(struct tty_struct*)*mgsl_device_count);
-	memset(serial_termios,0,sizeof(struct termios*)*mgsl_device_count);
-	memset(serial_termios_locked,0,sizeof(struct termios*)*mgsl_device_count);
+	memset(serial_table,0,sizeof(struct tty_struct*)*MAX_TOTAL_DEVICES);
+	memset(serial_termios,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES);
+	memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES);
 
 	return 0;
 	
@@ -4548,11 +4353,7 @@
 {
 	struct mgsl_struct *info;
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 	EXPORT_NO_SYMBOLS;
-#else
-	register_symtab(NULL);
-#endif		
 	
  	printk("%s version %s\n", driver_name, driver_version);
 	
@@ -4567,9 +4368,7 @@
 	
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 	serial_driver.driver_name = "synclink";
-#endif	
 	serial_driver.name = "ttySL";
 	serial_driver.major = ttymajor;
 	serial_driver.minor_start = 64;
@@ -4596,12 +4395,10 @@
 	serial_driver.ioctl = mgsl_ioctl;
 	serial_driver.throttle = mgsl_throttle;
 	serial_driver.unthrottle = mgsl_unthrottle;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 	serial_driver.send_xchar = mgsl_send_xchar;
 	serial_driver.break_ctl = mgsl_break;
 	serial_driver.wait_until_sent = mgsl_wait_until_sent;
  	serial_driver.read_proc = mgsl_read_proc;
-#endif	
 	serial_driver.set_termios = mgsl_set_termios;
 	serial_driver.stop = mgsl_stop;
 	serial_driver.start = mgsl_start;
@@ -4615,10 +4412,8 @@
 	callout_driver.name = "cuaSL";
 	callout_driver.major = cuamajor;
 	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 	callout_driver.read_proc = 0;
 	callout_driver.proc_entry = 0;
-#endif	
 
 	if (tty_register_driver(&serial_driver) < 0)
 		printk("%s(%d):Couldn't register serial driver\n",
@@ -4645,8 +4440,7 @@
 	
 }	/* end of mgsl_init() */
 
-#ifdef MODULE
-int init_module(void)
+int __init init_module(void)
 {
 /* Uncomment this to kernel debug module.
  * mgsl_get_text_ptr() leaves the .text address in eax
@@ -4692,20 +4486,8 @@
 		tmp_buf = NULL;
 	}
 	
-	if (serial_table)
-		kfree_s(serial_table,sizeof(struct tty_struct*)*mgsl_device_count);
-		
-	if (serial_termios)
-		kfree_s(serial_termios,sizeof(struct termios*)*mgsl_device_count);
-		
-	if (serial_termios_locked)
-		kfree_s(serial_termios_locked,sizeof(struct termios*)*mgsl_device_count);
-	
 }	/* end of cleanup_module() */
 
-#endif /* MODULE */
-
-
 /*
  * usc_RTCmd()
  *
@@ -6952,7 +6734,6 @@
 	while( EndTime-- && !info->irq_occurred ) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(jiffies_from_ms(10));
-		set_current_state(TASK_RUNNING);
 	}
 	
 	spin_lock_irqsave(&info->irq_spinlock,flags);
@@ -7575,7 +7356,7 @@
 	sppp_attach(&info->pppdev);
 
 	d = info->netdev;
-	strcpy(d->name, info->netname);
+	d->name = info->netname;
 	d->base_addr = info->io_base;
 	d->irq = info->irq_level;
 	d->dma = info->dma_level;
@@ -7586,10 +7367,6 @@
 	d->hard_start_xmit = mgsl_sppp_tx;
 	d->do_ioctl = mgsl_sppp_ioctl;
 	d->get_stats = mgsl_net_stats;
-#if LINUX_VERSION_CODE >= VERSION(2,3,43) 
-	d->tx_timeout = mgsl_sppp_tx_timeout;
-	d->watchdog_timeo = 10*HZ;
-#endif
 	dev_init_buffers(d);
 
 	if (register_netdev(d) == -1) {
@@ -7679,7 +7456,6 @@
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("mgsl_sppp_tx(%s)\n",info->netname);	
 
-#if LINUX_VERSION_CODE < VERSION(2,3,43) 
 	if (dev->tbusy) { 
 		if (time_before(jiffies, dev->trans_start+10*HZ))
 			return -EBUSY;	/* 10 seconds timeout */
@@ -7687,9 +7463,6 @@
 	}
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
 		return -EBUSY;
-#else
-	netif_stop_queue(dev);
-#endif
 
 	info->xmit_cnt = skb->len;
 	mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
diff -urN linux-2.2.19-pre2/drivers/isdn/hisax/bkm_a8.c linux/drivers/isdn/hisax/bkm_a8.c
--- linux-2.2.19-pre2/drivers/isdn/hisax/bkm_a8.c	Mon Dec  3 20:53:10 2001
+++ linux/drivers/isdn/hisax/bkm_a8.c	Mon Dec  3 20:53:37 2001
@@ -463,5 +463,6 @@
 	return (1);
 #else
 	printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n");
+	return (0);
 #endif /* CONFIG_PCI */
 }
diff -urN linux-2.2.19-pre2/drivers/isdn/hisax/nj_s.c linux/drivers/isdn/hisax/nj_s.c
--- linux-2.2.19-pre2/drivers/isdn/hisax/nj_s.c	Mon Dec  3 20:53:10 2001
+++ linux/drivers/isdn/hisax/nj_s.c	Mon Dec  3 20:53:37 2001
@@ -148,10 +148,10 @@
 		return(0);
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
+#if CONFIG_PCI
 	for ( ;; )
 	{
 
-#if CONFIG_PCI
 
 		if (!pci_present()) {
 			printk(KERN_ERR "Netjet: no PCI bus present\n");
diff -urN linux-2.2.19-pre2/drivers/isdn/hisax/nj_u.c linux/drivers/isdn/hisax/nj_u.c
--- linux-2.2.19-pre2/drivers/isdn/hisax/nj_u.c	Mon Dec  3 20:53:10 2001
+++ linux/drivers/isdn/hisax/nj_u.c	Mon Dec  3 20:53:37 2001
@@ -150,10 +150,10 @@
 		return(0);
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
+#if CONFIG_PCI
 	for ( ;; )
 	{
 
-#if CONFIG_PCI
 
 		if (!pci_present()) {
 			printk(KERN_ERR "NETspider-U: no PCI bus present\n");
diff -urN linux-2.2.19-pre2/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.2.19-pre2/drivers/net/Config.in	Mon Dec  3 20:53:11 2001
+++ linux/drivers/net/Config.in	Mon Dec  3 20:53:37 2001
@@ -183,7 +183,7 @@
       tristate 'Packet Engines GNIC-II (Hamachi) support' CONFIG_HAMACHI
       tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN
     fi
-    tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN
+    dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI
 endmenu
 
 bool 'FDDI driver support' CONFIG_FDDI
diff -urN linux-2.2.19-pre2/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
--- linux-2.2.19-pre2/drivers/net/cs89x0.c	Mon Aug  9 12:05:05 1999
+++ linux/drivers/net/cs89x0.c	Mon Dec  3 20:53:37 2001
@@ -27,6 +27,8 @@
                     : is running from all accounts.
                     
   Alan Cox          : Removed 1.2 support, added 2.1 extra counters.
+
+  Arnaldo Melo	    : release resources on failure in cs89x0_probe1
 */
 
 static char *version =
@@ -249,13 +251,17 @@
 	struct net_local *lp;
 	static unsigned version_printed = 0;
 	int i;
+	char priv_alloced_here = 0;
 	unsigned rev_type = 0;
 	int eeprom_buff[CHKSUM_LEN];
 
 	/* Initialize the device structure. */
 	if (dev->priv == NULL) {
 		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+		if (!dev->priv)
+			return -ENOMEM;
                 memset(dev->priv, 0, sizeof(struct net_local));
+		priv_alloced_here = 1;
         }
 	lp = (struct net_local *)dev->priv;
 
@@ -265,12 +271,12 @@
 	if (ioaddr & 1) {
 		ioaddr &= ~1;
 		if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG)
-			return ENODEV;
+			goto err;
 		outw(PP_ChipID, ioaddr + ADD_PORT);
 	}
 
 	if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG)
-		return ENODEV;
+		goto err;
 
 	/* Fill in the 'dev' fields. */
 	dev->base_addr = ioaddr;
@@ -388,6 +394,11 @@
 
 	printk("\n");
 	return 0;
+err:	if (priv_alloced_here) {
+		kfree(dev->priv);
+		dev->priv = NULL;
+	}
+	return -ENODEV;
 }
 
 
diff -urN linux-2.2.19-pre2/drivers/net/lanstreamer.c linux/drivers/net/lanstreamer.c
--- linux-2.2.19-pre2/drivers/net/lanstreamer.c	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lanstreamer.c	Mon Dec  3 20:53:37 2001
@@ -58,6 +58,7 @@
  *            First release to the public
  *  03/03/00 - Merged to kernel, indented -kr -i8 -bri0, fixed some missing
  *		malloc free checks, reviewed code. <alan@redhat.com>
+ *  12/18/00 - Made it SMP safe   - George Staikos <staikos@0wned.org>
  *  
  *  To Do:
  *
@@ -108,6 +109,7 @@
 #include <net/checksum.h>
 
 #include <asm/io.h>
+#include <asm/spinlock.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
@@ -285,6 +287,8 @@
 	streamer_priv = (struct streamer_private *) dev->priv;
 	streamer_mmio = streamer_priv->streamer_mmio;
 
+        streamer_priv->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+
 	printk("%s \n", version);
 	printk(KERN_INFO "%s: IBM PCI tokenring card. I/O at %hx, MMIO at %p, using irq %d\n",
 			dev->name, (unsigned int) dev->base_addr,
@@ -823,6 +827,7 @@
 	__u16 misr;
 	__u16 sisrmask;
 
+        spin_lock(&(streamer_priv->lock));
 	sisrmask = SISR_MI;
 	writew(~sisrmask, streamer_mmio + SISR_MASK_RUM);
 	sisr = readw(streamer_mmio + SISR);
@@ -831,6 +836,7 @@
 	writew(~misr, streamer_mmio + MISR_RUM);
 
 	if (!sisr) {		/* Interrupt isn't for us */
+                spin_unlock(&(streamer_priv->lock));
 		return;
 	}
 
@@ -919,6 +925,7 @@
 
 	dev->interrupt = 0;
 	writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
+        spin_unlock(&(streamer_priv->lock));
 }
 
 
@@ -927,11 +934,14 @@
 	struct streamer_private *streamer_priv =
 	    (struct streamer_private *) dev->priv;
 	__u8 *streamer_mmio = streamer_priv->streamer_mmio;
+        int flags;
 
 	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
 		return 1;
 	}
 
+        spin_lock_irqsave(&(streamer_priv->lock), flags);
+
 	if (streamer_priv->free_tx_ring_entries) {
 		streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].status = 0;
 		streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].bufcnt_framelen = 0x00010000 | skb->len;
@@ -956,8 +966,10 @@
 
 		streamer_priv->tx_ring_free = (streamer_priv->tx_ring_free + 1) & (STREAMER_TX_RING_SIZE - 1);
 		dev->tbusy = 0;
+                spin_unlock_irqrestore(&(streamer_priv->lock), flags);
 		return 0;
 	} else {
+                spin_unlock_irqrestore(&(streamer_priv->lock), flags);
 		return 1;
 	}
 }
diff -urN linux-2.2.19-pre2/drivers/net/lanstreamer.h linux/drivers/net/lanstreamer.h
--- linux-2.2.19-pre2/drivers/net/lanstreamer.h	Wed May  3 17:16:41 2000
+++ linux/drivers/net/lanstreamer.h	Mon Dec  3 20:53:37 2001
@@ -283,6 +283,7 @@
 	__u16 streamer_addr_table_addr, streamer_parms_addr;
 	__u16 mac_rx_buffer;
 	__u8 streamer_laa[6];
+        spinlock_t lock;
 };
 
 struct streamer_adapter_addr_table {
diff -urN linux-2.2.19-pre2/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- linux-2.2.19-pre2/drivers/net/ne2k-pci.c	Tue Oct 26 17:53:40 1999
+++ linux/drivers/net/ne2k-pci.c	Mon Dec  3 20:53:37 2001
@@ -12,19 +12,31 @@
 	This software may be used and distributed according to the terms
 	of the GNU Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
+	Issues remaining:
 	People are making PCI ne2000 clones! Oh the horror, the horror...
+	Limited full-duplex support.
 
-	Issues remaining:
-	No full-duplex support.
+	ChangeLog:
+
+	12/15/2000 Merged Scyld v1.02 into 2.2.18
+									J.A. Magallon <jamagallon@able.es>
 */
 
-/* Our copyright info must remain in the binary. */
-static const char *version =
-"ne2k-pci.c:vpre-1.00e 5/27/99 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n";
+/* These identify the driver base version and may not be removed. */
+static const char version1[] =
+"ne2k-pci.c:v1.02 10/19/2000 D. Becker/P. Gortmaker\n";
+static const char version2[] =
+"  http://www.scyld.com/network/ne2k-pci.html\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -49,7 +61,18 @@
 #endif
 
 /* Set statically or when loading the driver module. */
-static int debug = 1;
+static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
+/* More are supported, limit only on options */
+#define MAX_UNITS 6
+/* Used to pass the full-duplex flag, etc. */
+static int full_duplex[MAX_UNITS] = {0, };
+static int options[MAX_UNITS] = {0, };
+
+MODULE_AUTHOR("Donald Becker / Paul Gortmaker");
+MODULE_DESCRIPTION("PCI NE2000 clone driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 
 /* Some defines that people can play with if so inclined. */
 
@@ -62,12 +85,13 @@
 /* Do we have a non std. amount of memory? (in units of 256 byte pages) */
 /* #define PACKETBUF_MEMSIZE	0x40 */
 
-#define ne2k_flags reg0			/* Rename an existing field to store flags! */
-
-/* Only the low 8 bits are usable for non-init-time flags! */
+/* Flags.  We rename an existing ei_status field to store flags! */
+/* Thus only the low 8 bits are usable for non-init-time flags. */
+#define ne2k_flags reg0
 enum {
-	HOLTEK_FDX=1, 		/* Full duplex -> set 0x80 at offset 0x20. */
-	ONLY_16BIT_IO=2, ONLY_32BIT_IO=4,	/* Chip can do only 16/32-bit xfers. */
+	ONLY_16BIT_IO=8, ONLY_32BIT_IO=4,   /* Chip can do only 16/32-bit xfers. */
+	FORCE_FDX=0x20,                     /* User override. */
+	REALTEK_FDX=0x40, HOLTEK_FDX=0x80,
 	STOP_PG_0x60=0x100,
 };
 
@@ -79,18 +103,17 @@
 	int flags;
 }
 pci_clone_list[] __initdata = {
-	{0x10ec, 0x8029, "RealTek RTL-8029", 0},
-	{0x1050, 0x0940, "Winbond 89C940", 0},
-	{0x11f6, 0x1401, "Compex RL2000", 0},
-	{0x8e2e, 0x3000, "KTI ET32P2", 0},
-	{0x4a14, 0x5000, "NetVin NV5000SC", 0},
-	{0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO},
-	{0x10bd, 0x0e34, "SureCom NE34", 0},
-	{0x1050, 0x5a5a, "Winbond", 0},
-	{0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
-	{0x12c3, 0x5598, "Holtek HT80229",
-	 ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
-	{0,}
+{0x10ec, 0x8029, "RealTek RTL-8029", REALTEK_FDX},
+{0x1050, 0x0940, "Winbond 89C940", 0},
+{0x1050, 0x5a5a, "Winbond w89c940", 0},
+{0x8e2e, 0x3000, "KTI ET32P2", 0},
+{0x4a14, 0x5000, "NetVin NV5000SC", 0},
+{0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO},
+{0x10bd, 0x0e34, "SureCom NE34", 0},
+{0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO|HOLTEK_FDX},
+{0x12c3, 0x5598, "Holtek HT80229", ONLY_32BIT_IO|HOLTEK_FDX|STOP_PG_0x60 },
+{0x11f6, 0x1401, "Compex RL2000", 0},
+{0,}
 };
 
 /* ---- No user-serviceable parts below ---- */
@@ -119,7 +142,7 @@
 static void ne2k_pci_block_output(struct device *dev, const int count,
 		const unsigned char *buf, const int start_page);
 
-
+
 
 /* No room in the standard 8390 structure for extra info we need. */
 struct ne2k_pci_card {
@@ -137,7 +160,7 @@
 {
 	/* We must emit version information. */
 	if (debug)
-		printk(KERN_INFO "%s", version);
+		printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
 
 	if (ne2k_pci_probe(0)) {
 		printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n");
@@ -263,8 +286,8 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioaddr, int irq,
-									  int chip_idx))
+__initfunc (static struct device *ne2k_pci_probe1(struct device *dev,
+			long ioaddr, int irq, int chip_idx))
 {
 	int i;
 	unsigned char SA_prom[32];
@@ -291,6 +314,8 @@
 
 	dev = init_etherdev(dev, 0);
 
+	if (!dev) return 0;
+
 	/* Reset card. Who knows what dain-bramaged state it was left in. */
 	{
 		unsigned long reset_start_time = jiffies;
@@ -342,7 +367,7 @@
 	/* Note: all PCI cards have at least 16 bit access, so we don't have
 	   to check for 8 bit cards.  Most cards permit 32 bit access. */
 	if (pci_clone_list[chip_idx].flags & ONLY_32BIT_IO) {
-		for (i = 0; i < 4 ; i++)
+		for (i = 0; i < 8 ; i++)
 			((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
 	} else
 		for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
@@ -379,6 +404,10 @@
 	ei_status.stop_page = stop_page;
 	ei_status.word16 = 1;
 	ei_status.ne2k_flags = pci_clone_list[chip_idx].flags;
+	if (chip_idx < MAX_UNITS) {
+		if (full_duplex[chip_idx]  ||  (options[chip_idx] & FORCE_FDX))
+			ei_status.ne2k_flags |= FORCE_FDX;
+	}
 
 	ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
@@ -401,8 +430,17 @@
 {
 	if (request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev))
 		return -EAGAIN;
-	ei_open(dev);
 	MOD_INC_USE_COUNT;
+	/* Set full duplex for the chips that we know about. */
+	if (ei_status.ne2k_flags & FORCE_FDX) {
+		long ioaddr = dev->base_addr;
+		if (ei_status.ne2k_flags & REALTEK_FDX) {
+			outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */
+			outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20);
+		} else if (ei_status.ne2k_flags & HOLTEK_FDX)
+			outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20);
+	}
+	ei_open(dev);
 	return 0;
 }
 
diff -urN linux-2.2.19-pre2/drivers/net/tulip.c linux/drivers/net/tulip.c
--- linux-2.2.19-pre2/drivers/net/tulip.c	Sun Dec 10 16:49:42 2000
+++ linux/drivers/net/tulip.c	Mon Dec  3 20:53:37 2001
@@ -15,10 +15,14 @@
 
 	Support and updates available at
 	http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
-	
+
 	This driver also contains updates by Wolfgang Walter and others.
 	For this specific driver variant please use linux-kernel for 
 	bug reports.
+
+	Updated 12/17/2000 by Jim McQuillan <jam@McQuil.com> to
+	include support for the Linksys LNE100TX card based on the
+	Admtek 985 Centaur-P chipset.
 */
 
 #define SMP_CHECK
@@ -398,6 +402,8 @@
 	HAS_MII | HAS_NWAY143 | HAS_8023X, t21142_timer },
   { "ADMtek Comet", 256, 0x0001abef,
 	MC_HASH_ONLY, comet_timer },
+  { "ADMtek Centaur-P", 256, 0x0001abef,
+  	MC_HASH_ONLY, comet_timer },
   { "Compex 9881 PMAC", 128, 0x0001ebef,
 	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
   { "Intel DS21145 Tulip", 128, 0x0801fbff,
@@ -411,8 +417,8 @@
 /* This matches the table above.  Note 21142 == 21143. */
 enum chips {
 	DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
-	LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881,
-	I21145,
+	LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMET5,
+        COMPEX9881, I21145, XIRCOM,
 };
 
 /* A full-duplex map for media types. */
@@ -423,7 +429,7 @@
 {0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20 };
 static u8 t21040_csr13[] = {2,0x0C,8,4,  4,0,0,0, 0,0,0,0, 4,0,0,0};
 /* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/
-static u16 t21041_csr13[] = { 0xEF05, 0xEF0D, 0xEF0D, 0xEF05, 0xEF05, };
+static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
 static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
 static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
 
@@ -584,7 +590,7 @@
 		return -ENODEV;
 
 	for (;pci_index < 0xff; pci_index++) {
-		u16 vendor, device, pci_command, new_command, subvendor;
+		u16 vendor, device, pci_command, new_command;
 		int chip_idx;
 		int irq;
 		long ioaddr;
@@ -602,13 +608,6 @@
 								 PCI_VENDOR_ID, &vendor);
 		pcibios_read_config_word(pci_bus, pci_device_fn,
 								 PCI_DEVICE_ID, &device);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
-		
-	        if( subvendor == 0x1376 ){
-			printk("tulip: skipping LMC card.\n");
-			continue;
-		}	
 
 		for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
 			if (vendor == pci_tbl[chip_idx].vendor_id
@@ -750,7 +749,13 @@
 			put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i);
 			sum += value & 0xffff;
 		}
-	} else if (chip_idx == COMET) {
+	} else if (chip_idx == COMET){
+		/* No need to read the EEPROM. */
+		put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr);
+		put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4));
+		for (i = 0; i < 6; i ++)
+			sum += dev->dev_addr[i];
+	} else if (chip_idx == COMET5){
 		/* No need to read the EEPROM. */
 		put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr);
 		put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4));
@@ -995,6 +1000,9 @@
 	case COMET:
 		/* No initialization necessary. */
 		break;
+	case COMET5:
+		/* No initialization necessary. */
+		break;
 	}
 
 	if (tulip_tbl[chip_idx].flags & HAS_PWRDWN)
@@ -1321,6 +1329,17 @@
 		}
 		return 0xffff;
 	}
+	if (tp->chip_id == COMET5) {
+		if (phy_id == 1) {
+			if (location < 7)
+				return inl(ioaddr + 0xB4 + (location<<2));
+			else if (location == 17)
+				return inl(ioaddr + 0xD0);
+			else if (location >= 29 && location <= 31)
+				return inl(ioaddr + 0xD4 + ((location-29)<<2));
+		}
+		return 0xffff;
+	}
 
 	/* Establish sync by sending at least 32 logic ones. */
 	for (i = 32; i >= 0; i--) {
@@ -1379,6 +1398,18 @@
 		return;
 	}
 
+	if (tp->chip_id == COMET5) {
+		if (phy_id != 1)
+			return;
+		if (location < 7)
+			outl(value, ioaddr + 0xB4 + (location<<2));
+		else if (location == 17)
+			outl(value, ioaddr + 0xD0);
+		else if (location >= 29 && location <= 31)
+			outl(value, ioaddr + 0xD4 + ((location-29)<<2));
+		return;
+	}
+
 	/* Establish sync by sending 32 logic ones. */
 	for (i = 32; i >= 0; i--) {
 		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
@@ -1462,6 +1493,11 @@
 			outl(addr_high, ioaddr + 0xA8);
 			outl(0, ioaddr + 0xAC);
 			outl(0, ioaddr + 0xB0);
+		} else if (tp->chip_id == COMET5) {
+			outl(addr_low,  ioaddr + 0xA4);
+			outl(addr_high, ioaddr + 0xA8);
+			outl(0, ioaddr + 0xAC);
+			outl(0, ioaddr + 0xB0);
 		}
 	} else {
 		/* This is set_rx_mode(), but without starting the transmitter. */
@@ -1575,6 +1611,9 @@
 	} else if (tp->chip_id == COMET) {
 		dev->if_port = 0;
 		tp->csr6 = 0x00040000;
+	} else if (tp->chip_id == COMET5) {
+		dev->if_port = 0;
+		tp->csr6 = 0x00040000;
 	} else if (tp->chip_id == AX88140) {
 		tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
 	} else
@@ -3014,6 +3053,8 @@
 			data[0] = 32;
 		else if (tp->chip_id == COMET)
 			data[0] = 1;
+		else if (tp->chip_id == COMET5)
+			data[0] = 1;
 		else
 			return -ENODEV;
 	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
@@ -3140,6 +3181,9 @@
 				outl(3, ioaddr + CSR13);
 				outl(mc_filter[1], ioaddr + CSR14);
 			} else if (tp->chip_id == COMET) { /* Has a simple hash filter. */
+				outl(mc_filter[0], ioaddr + 0xAC);
+				outl(mc_filter[1], ioaddr + 0xB0);
+			} else if (tp->chip_id == COMET5) { /* Has a simple hash filter. */
 				outl(mc_filter[0], ioaddr + 0xAC);
 				outl(mc_filter[1], ioaddr + 0xB0);
 			}
diff -urN linux-2.2.19-pre2/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- linux-2.2.19-pre2/drivers/net/via-rhine.c	Sun Dec 10 16:49:42 2000
+++ linux/drivers/net/via-rhine.c	Mon Dec  3 20:53:37 2001
@@ -1,35 +1,44 @@
 /* via-rhine.c: A Linux Ethernet device driver for VIA Rhine family chips. */
 /*
-	Written 1998-1999 by Donald Becker.
+	Written 1998-2000 by Donald Becker.
 
-	This software may be used and distributed according to the terms
-	of the GNU Public License (GPL), incorporated herein by reference.
-	Drivers derived from this code also fall under the GPL and must retain
-	this authorship and copyright notice.
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
 
 	This driver is designed for the VIA VT86c100A Rhine-II PCI Fast Ethernet
 	controller.  It also works with the older 3043 Rhine-I chip.
 
-	The author may be reached as becker@cesdis.edu, or
-	Donald Becker
-	312 Severn Ave. #W302
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
 	Annapolis MD 21403
 
 	Support and updates available at
-	http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html
+	http://www.scyld.com/network/via-rhine.html
+
+
+	Linux kernel version history:
+
+	LK1.0.0:
+	- Urban Widmark: merges from Beckers 1.08b version and 2.4.0 (VT6102)
 */
 
-static const char *versionA =
-"via-rhine.c:v1.01 2/27/99  Written by Donald Becker\n";
-static const char *versionB =
-"  http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html\n";
+/* These identify the driver base version and may not be removed. */
+static const char version1[] =
+"via-rhine.c:v1.08b-LK1.0.0 12/14/2000  Written by Donald Becker\n";
+static const char version2[] =
+"  http://www.scyld.com/network/via-rhine.html\n";
 
-/* A few user-configurable values.   These may be modified when a driver
-   module is loaded.*/
+/* The user-configurable values.
+   These may be modified when a driver module is loaded.*/
 
 static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
 static int max_interrupt_work = 20;
-static int min_pci_latency = 64;
+static int min_pci_latency = 32;
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
@@ -55,7 +64,8 @@
    Making the Tx ring too large decreases the effectiveness of channel
    bonding and packet priority.
    There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	8
+#define TX_RING_SIZE	16
+#define TX_QUEUE_LEN	10		/* Limit ring entries actually used.  */
 #define RX_RING_SIZE	16
 
 /* Operational parameters that usually are not changed. */
@@ -64,9 +74,15 @@
 
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
+
+#if !defined(__OPTIMIZE__)
+#warning  You must compile this file with the correct options!
+#warning  See the last lines of the source file.
+#error  You must compile this driver with "-O".
+#endif
+
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
@@ -82,15 +98,17 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 
-/* This driver was written to use PCI memory space, however some x86
-   motherboards only configure I/O space accesses correctly. */
-#if defined(__i386__)  &&  !defined(VIA_USE_MEMORY)
-#define VIA_USE_IO
-#endif
-#if defined(__alpha__)
-#define VIA_USE_IO
-#endif
-#ifdef VIA_USE_IO
+/* Condensed bus+endian portability operations. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+/* This driver was written to use PCI memory space, however most versions
+   of the Rhine only work correctly with I/O space accesses. */
+#if defined(VIA_USE_MEMORY)
+#warning Many adapters using the VIA Rhine chip are not configured to work
+#warning with PCI memory space accesses.
+#else
+#define USE_IO_OPS
 #undef readb
 #undef readw
 #undef readl
@@ -105,21 +123,7 @@
 #define writel outl
 #endif
 
-/* Kernel compatibility defines, some common to David Hind's PCMCIA package.
-   This is only in the support-all-kernels source code. */
-
-#define RUN_AT(x) (jiffies + (x))
-
-#if (LINUX_VERSION_CODE >= 0x20100)
-static char kernel_version[] = UTS_RELEASE;
-#else
-#ifndef __alpha__
-#define ioremap vremap
-#define iounmap vfree
-#endif
-#endif
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(min_pci_latency, "i");
@@ -127,28 +131,6 @@
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define	net_device_stats enet_statistics
-#else
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
-/* Grrrr, the PCI code changed, but did not consider CardBus... */
-#include <linux/bios32.h>
-#define PCI_SUPPORT_VER1
-#else
-#define PCI_SUPPORT_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
-#define dev_free_skb(skb) dev_kfree_skb(skb);
-#endif
-
 
 /*
 				Theory of Operation
@@ -226,13 +208,13 @@
 IVb. References
 
 Preliminary VT86C100A manual from http://www.via.com.tw/
-http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.scyld.com/expert/100mbps.html
+http://www.scyld.com/expert/NWay.html
 
 IVc. Errata
 
 The VT86C100A manual is not reliable information.
-The chip does not handle unaligned transmit or receive buffers, resulting
+The 3043 chip does not handle unaligned transmit or receive buffers, resulting
 in significant performance degradation for bounce buffer copies on transmit
 and unaligned IP headers on receive.
 The chip does not pad to minimum transmit length.
@@ -250,6 +232,15 @@
 	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
 	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
 };
+
+#if defined(VIA_USE_MEMORY)
+#define RHINE_IOTYPE (PCI_USES_MEM | PCI_USES_MASTER | PCI_ADDR0)
+#define RHINEII_IOSIZE 4096
+#else
+#define RHINE_IOTYPE (PCI_USES_IO  | PCI_USES_MASTER | PCI_ADDR1)
+#define RHINEII_IOSIZE 256
+#endif
+
 struct pci_id_info {
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
@@ -264,34 +255,41 @@
 
 static struct pci_id_info pci_tbl[] __initdata = {
 	{ "VIA VT86C100A Rhine-II", 0x1106, 0x6100, 0xffff,
-	  PCI_USES_MEM|PCI_USES_IO|PCI_USES_MEM|PCI_USES_MASTER, 128, via_probe1},
+	  RHINE_IOTYPE, 128, via_probe1},
+	{ "VIA VT6102 Rhine-II", 0x1106, 0x3065, 0xffff,
+	  RHINE_IOTYPE, RHINEII_IOSIZE, via_probe1},
 	{ "VIA VT3043 Rhine", 0x1106, 0x3043, 0xffff,
-	  PCI_USES_IO|PCI_USES_MEM|PCI_USES_MASTER, 128, via_probe1},
+	  RHINE_IOTYPE, 128, via_probe1},
 	{0,},						/* 0 terminated list. */
 };
 
 
 /* A chip capabilities table, matching the entries in pci_tbl[] above. */
-enum chip_capability_flags {CanHaveMII=1, };
+enum chip_capability_flags {
+	CanHaveMII=1, HasESIPhy=2, HasDavicomPhy=4,
+	ReqTxAlign=0x10, HasWOL=0x20,
+};
+
 struct chip_info {
 	int io_size;
 	int flags;
 } static cap_tbl[] __initdata = {
-	{128, CanHaveMII, },
-	{128, CanHaveMII, },
+	{128, CanHaveMII | ReqTxAlign, },
+	{128, CanHaveMII | HasWOL, },
+	{128, CanHaveMII | ReqTxAlign, },
 };
 
 
-/* Offsets to the device registers.
-*/
+/* Offsets to the device registers. */
 enum register_offsets {
 	StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08,
 	IntrStatus=0x0C, IntrEnable=0x0E,
 	MulticastFilter0=0x10, MulticastFilter1=0x14,
 	RxRingPtr=0x18, TxRingPtr=0x1C,
-	MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIConfig=0x6E,
+	MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E,
 	MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72,
-	Config=0x78, RxMissed=0x7C, RxCRCErrs=0x7E,
+	Config=0x78, ConfigA=0x7A, RxMissed=0x7C, RxCRCErrs=0x7E,
+	StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC,
 };
 
 /* Bits in the interrupt status/mask registers. */
@@ -303,21 +301,18 @@
 	IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
 	IntrTxAborted=0x2000, IntrLinkChange=0x4000,
 	IntrRxWakeUp=0x8000,
-	IntrNormalSummary=0x0003, IntrAbnormalSummary=0x8260,
+	IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
 };
 
-
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
-	u16 rx_status;
-	u16 rx_length;
+	s32 rx_status;
 	u32 desc_length;
 	u32 addr;
 	u32 next_desc;
 };
 struct tx_desc {
-	u16 tx_status;
-	u16 tx_own;
+	s32 tx_status;
 	u32 desc_length;
 	u32 addr;
 	u32 next_desc;
@@ -325,9 +320,10 @@
 
 /* Bits in *_desc.status */
 enum rx_status_bits {
-	RxDescOwn=0x80000000, RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F};
+	RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F
+};
 enum desc_status_bits {
-	DescOwn=0x8000, DescEndPacket=0x4000, DescIntr=0x1000,
+	DescOwn=0x80000000, DescEndPacket=0x4000, DescIntr=0x1000,
 };
 
 /* Bits in ChipCmd. */
@@ -338,6 +334,7 @@
 	CmdNoTxPoll=0x0800, CmdReset=0x8000,
 };
 
+#define PRIV_ALIGN	15	/* Required alignment mask */
 struct netdev_private {
 	/* Descriptor rings first for alignment. */
 	struct rx_desc rx_ring[RX_RING_SIZE];
@@ -349,12 +346,12 @@
 	unsigned char *tx_buf[TX_RING_SIZE];	/* Tx bounce buffers */
 	unsigned char *tx_bufs;				/* Tx bounce buffer region. */
 	struct device *next_module;			/* Link for devices of this type. */
+	void *priv_addr;					/* Unaligned address for kfree */
 	struct net_device_stats stats;
 	struct timer_list timer;	/* Media monitoring timer. */
 	unsigned char pci_bus, pci_devfn;
 	/* Frequently used values: keep some adjacent for cache effect. */
-	int chip_id;
-	long in_interrupt;			/* Word-long for SMP locks. */
+	int chip_id, drv_flags;
 	struct rx_desc *rx_head_desc;
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
 	unsigned int cur_tx, dirty_tx;
@@ -388,6 +385,7 @@
 static struct net_device_stats *get_stats(struct device *dev);
 static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
 static int  netdev_close(struct device *dev);
+static inline void clear_tally_counters(long ioaddr);
 
 
 
@@ -432,30 +430,13 @@
 			continue;
 
 		{
-#if defined(PCI_SUPPORT_VER2)
 			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-#ifdef VIA_USE_IO
+#ifdef USE_IO_OPS
 			pciaddr = pdev->base_address[0];
 #else
 			pciaddr = pdev->base_address[1];
 #endif
 			irq = pdev->irq;
-#else
-			u32 pci_memaddr;
-			u8 pci_irq_line;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_INTERRUPT_LINE, &pci_irq_line);
-#ifdef VIA_USE_IO
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-									  PCI_BASE_ADDRESS_0, &pci_memaddr);
-			pciaddr = pci_memaddr;
-#else
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-									  PCI_BASE_ADDRESS_1, &pci_memaddr);
-			pciaddr = pci_memaddr;
-#endif
-			irq = pci_irq_line;
-#endif
 		}
 
 		if (debug > 2)
@@ -511,7 +492,7 @@
 {
 	static int did_version = 0;
 	if (!did_version++)
-		printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+		printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
 	return pci_etherdev_probe(dev, pci_tbl);
 }
 #endif
@@ -521,6 +502,7 @@
 								 int chip_id, int card_idx)
 {
 	struct netdev_private *np;
+	void *priv_mem;
 	int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 
 	dev = init_etherdev(dev, 0);
@@ -528,14 +510,20 @@
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, pci_tbl[chip_id].name, ioaddr);
 
-	/* Ideally we would be read the EEPROM but access may be locked. */
-	for (i = 0; i <6; i++)
+	/* We would prefer to read the EEPROM but access may be locked. */
+	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
 	for (i = 0; i < 5; i++)
 			printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
 
-#ifdef VIA_USE_IO
+	/* Allocate driver private memory for descriptor lists.
+	   Check for the very unlikely case of no memory. */
+	priv_mem = kmalloc(sizeof(*np) + PRIV_ALIGN, GFP_KERNEL);
+	if (priv_mem == NULL)
+		return NULL;
+
+#ifdef USE_IO_OPS
 	request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name);
 #endif
 
@@ -546,9 +534,9 @@
 	dev->irq = irq;
 
 	/* Make certain the descriptor lists are cache-aligned. */
-	np = (void *)(((long)kmalloc(sizeof(*np), GFP_KERNEL) + 31) & ~31);
+	dev->priv = np = (void *)(((long)priv_mem + PRIV_ALIGN) & ~PRIV_ALIGN);
 	memset(np, 0, sizeof(*np));
-	dev->priv = np;
+	np->priv_addr = priv_mem;
 
 	np->next_module = root_net_dev;
 	root_net_dev = dev;
@@ -556,6 +544,7 @@
 	np->pci_bus = pci_bus;
 	np->pci_devfn = pci_devfn;
 	np->chip_id = chip_id;
+	np->drv_flags = cap_tbl[chip_id].flags;
 
 	if (dev->mem_start)
 		option = dev->mem_start;
@@ -582,7 +571,7 @@
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &mii_ioctl;
 
-	if (cap_tbl[np->chip_id].flags & CanHaveMII) {
+	if (np->drv_flags & CanHaveMII) {
 		int phy, phy_idx = 0;
 		np->phys[0] = 1;		/* Standard for this chip. */
 		for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
@@ -625,9 +614,23 @@
 
 static void mdio_write(struct device *dev, int phy_id, int regnum, int value)
 {
+	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int boguscnt = 1024;
 
+	if (phy_id == np->phys[0]) {
+		switch (regnum) {
+		case 0:					/* Is user forcing speed/duplex? */
+			if (value & 0x9000)	/* Autonegotiation. */
+				np->duplex_lock = 0;
+			else
+				np->full_duplex = (value & 0x0100) ? 1 : 0;
+			break;
+		case 4:
+			np->advertising = value;
+			break;
+		}
+	}
 	/* Wait for a previous command to complete. */
 	while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0)
 		;
@@ -649,15 +652,17 @@
 	/* Reset the chip. */
 	writew(CmdReset, ioaddr + ChipCmd);
 
-	if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev))
+	MOD_INC_USE_COUNT;
+
+	if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) {
+		MOD_DEC_USE_COUNT;
 		return -EAGAIN;
+	}
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
 			   dev->name, dev->irq);
 
-	MOD_INC_USE_COUNT;
-
 	init_ring(dev);
 
 	writel(virt_to_bus(np->rx_ring), ioaddr + RxRingPtr);
@@ -667,7 +672,7 @@
 		writeb(dev->dev_addr[i], ioaddr + StationAddr + i);
 
 	/* Initialize other registers. */
-	writew(0x0006, ioaddr + PCIConfig);	/* Tune configuration??? */
+	writew(0x0006, ioaddr + PCIBusConfig);	/* Tune configuration??? */
 	/* Configure the FIFO thresholds. */
 	writeb(0x20, ioaddr + TxConfig);	/* Initial threshold 32 bytes */
 	np->tx_thresh = 0x20;
@@ -678,7 +683,6 @@
 
 	dev->tbusy = 0;
 	dev->interrupt = 0;
-	np->in_interrupt = 0;
 
 	set_rx_mode(dev);
 
@@ -696,6 +700,11 @@
 	writew(np->chip_cmd, ioaddr + ChipCmd);
 
 	check_duplex(dev);
+	/* The LED outputs of various MII xcvrs should be configured.  */
+	/* For NS or Mison phys, turn on bit 1 in register 0x17 */
+	/* For ESI phys, turn on bit 7 in register 0x17. */
+	mdio_write(dev, np->phys[0], 0x17, mdio_read(dev, np->phys[0], 0x17) |
+			   (np->drv_flags & HasESIPhy) ? 0x0080 : 0x0001);
 
 	if (debug > 2)
 		printk(KERN_DEBUG "%s: Done netdev_open(), status %4.4x "
@@ -705,7 +714,7 @@
 
 	/* Set the timer to check for link beat. */
 	init_timer(&np->timer);
-	np->timer.expires = RUN_AT(1);
+	np->timer.expires = jiffies + 2;
 	np->timer.data = (unsigned long)dev;
 	np->timer.function = &netdev_timer;				/* timer handler */
 	add_timer(&np->timer);
@@ -718,11 +727,12 @@
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int mii_reg5 = mdio_read(dev, np->phys[0], 5);
+	int negotiated = mii_reg5 & np->advertising;
 	int duplex;
 
 	if (np->duplex_lock  ||  mii_reg5 == 0xffff)
 		return;
-	duplex = (mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
+	duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
 	if (np->full_duplex != duplex) {
 		np->full_duplex = duplex;
 		if (debug)
@@ -748,9 +758,14 @@
 		printk(KERN_DEBUG "%s: VIA Rhine monitor tick, status %4.4x.\n",
 			   dev->name, readw(ioaddr + IntrStatus));
 	}
+	if (test_bit(0, (void*)&dev->tbusy) != 0
+		&& np->cur_tx - np->dirty_tx > 1
+		&& jiffies - dev->trans_start > TX_TIMEOUT)
+		tx_timeout(dev);
+
 	check_duplex(dev);
 
-	np->timer.expires = RUN_AT(next_tick);
+	np->timer.expires = jiffies + next_tick;
 	add_timer(&np->timer);
 }
 
@@ -764,15 +779,15 @@
 		   dev->name, readw(ioaddr + IntrStatus),
 		   mdio_read(dev, np->phys[0], 1));
 
-  /* Perhaps we should reinitialize the hardware here. */
-  dev->if_port = 0;
-  /* Stop and restart the chip's Tx processes . */
-
-  /* Trigger an immediate transmit demand. */
-
-  dev->trans_start = jiffies;
-  np->stats.tx_errors++;
-  return;
+	/* Perhaps we should reinitialize the hardware here. */
+	dev->if_port = 0;
+	/* Stop and restart the chip's Tx processes . */
+
+	/* Trigger an immediate transmit demand. */
+
+	dev->trans_start = jiffies;
+	np->stats.tx_errors++;
+	return;
 }
 
 
@@ -791,35 +806,33 @@
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].rx_status = 0;
-		np->rx_ring[i].rx_length = 0;
-		np->rx_ring[i].desc_length = np->rx_buf_sz;
-		np->rx_ring[i].next_desc = virt_to_bus(&np->rx_ring[i+1]);
+		np->rx_ring[i].desc_length = cpu_to_le32(np->rx_buf_sz);
+		np->rx_ring[i].next_desc = virt_to_le32desc(&np->rx_ring[i+1]);
 		np->rx_skbuff[i] = 0;
 	}
 	/* Mark the last entry as wrapping the ring. */
-	np->rx_ring[i-1].next_desc = virt_to_bus(&np->rx_ring[0]);
+	np->rx_ring[i-1].next_desc = virt_to_le32desc(&np->rx_ring[0]);
 
-	/* Fill in the Rx buffers. */
+	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
 		np->rx_skbuff[i] = skb;
 		if (skb == NULL)
 			break;
 		skb->dev = dev;			/* Mark as being used by this device. */
-		np->rx_ring[i].addr = virt_to_bus(skb->tail);
-		np->rx_ring[i].rx_status = 0;
-		np->rx_ring[i].rx_length = DescOwn;
+		np->rx_ring[i].addr = virt_to_le32desc(skb->tail);
+		np->rx_ring[i].rx_status = cpu_to_le32(DescOwn);
 	}
 	np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
 
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		np->tx_skbuff[i] = 0;
-		np->tx_ring[i].tx_own = 0;
-		np->tx_ring[i].desc_length = 0x00e08000;
-		np->tx_ring[i].next_desc = virt_to_bus(&np->tx_ring[i+1]);
+		np->tx_ring[i].tx_status = 0;
+		np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000);
+		np->tx_ring[i].next_desc = virt_to_le32desc(&np->tx_ring[i+1]);
 		np->tx_buf[i] = kmalloc(PKT_BUF_SZ, GFP_KERNEL);
 	}
-	np->tx_ring[i-1].next_desc = virt_to_bus(&np->tx_ring[0]);
+	np->tx_ring[i-1].next_desc = virt_to_le32desc(&np->tx_ring[0]);
 
 	return;
 }
@@ -832,41 +845,45 @@
 	/* Block a timer-based transmit from overlapping.  This could better be
 	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		tx_timeout(dev);
+		/* This watchdog code is redundant with the media monitor timer. */
+		if (jiffies - dev->trans_start > TX_TIMEOUT)
+			tx_timeout(dev);
 		return 1;
 	}
 
-	/* Caution: the write order is important here, set the field
-	   with the "ownership" bits last. */
+	/* Explicitly flush packet data cache lines here. */
+
+	/* Caution: the write order is important here, set the descriptor word
+	   with the "ownership" bit last.  No SMP locking is needed if the
+	   cur_tx is incremented after the descriptor is consistent.  */
 
 	/* Calculate the next Tx descriptor entry. */
 	entry = np->cur_tx % TX_RING_SIZE;
 
 	np->tx_skbuff[entry] = skb;
 
-	if ((long)skb->data & 3) {			/* Must use alignment buffer. */
+	if ((np->drv_flags & ReqTxAlign)  && ((long)skb->data & 3)) {
+		/* Must use alignment buffer. */
 		if (np->tx_buf[entry] == NULL &&
 			(np->tx_buf[entry] = kmalloc(PKT_BUF_SZ, GFP_KERNEL)) == NULL)
 			return 1;
 		memcpy(np->tx_buf[entry], skb->data, skb->len);
-		np->tx_ring[entry].addr = virt_to_bus(np->tx_buf[entry]);
+		np->tx_ring[entry].addr = virt_to_le32desc(np->tx_buf[entry]);
 	} else
-		np->tx_ring[entry].addr = virt_to_bus(skb->data);
+		np->tx_ring[entry].addr = virt_to_le32desc(skb->data);
 
-	np->tx_ring[entry].desc_length = 0x00E08000 |
-		(skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
-	np->tx_ring[entry].tx_own = DescOwn;
+	np->tx_ring[entry].desc_length =
+		cpu_to_le32(0x00E08000 | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+	np->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
 
 	np->cur_tx++;
 
-	/* Non-x86 Todo: explicitly flush cache lines here. */
+	/* Explicitly flush descriptor cache lines here. */
 
 	/* Wake the potentially-idle transmit channel. */
 	writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
 
-	if (np->cur_tx - np->dirty_tx < TX_RING_SIZE - 1)
+	if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 1)
 		clear_bit(0, (void*)&dev->tbusy);		/* Typical path */
 	else
 		np->tx_full = 1;
@@ -884,26 +901,9 @@
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 {
 	struct device *dev = (struct device *)dev_instance;
-	struct netdev_private *np;
-	long ioaddr, boguscnt = max_interrupt_work;
-
-	ioaddr = dev->base_addr;
-	np = (struct netdev_private *)dev->priv;
-#if defined(__i386__)
-	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		dev->interrupt = 0;	/* Avoid halting machine. */
-		return;
-	}
-#else
-	if (dev->interrupt) {
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-		return;
-	}
-	dev->interrupt = 1;
-#endif
+	struct netdev_private *np = (void *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int boguscnt = max_interrupt_work;
 
 	do {
 		u32 intr_status = readw(ioaddr + IntrStatus);
@@ -924,10 +924,9 @@
 
 		for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
 			int entry = np->dirty_tx % TX_RING_SIZE;
-			int txstatus;
-			if (np->tx_ring[entry].tx_own)
+			int txstatus = le32_to_cpu(np->tx_ring[entry].tx_status);
+			if (txstatus & DescOwn)
 				break;
-			txstatus = np->tx_ring[entry].tx_status;
 			if (debug > 6)
 				printk(KERN_DEBUG " Tx scavenge %d status %4.4x.\n",
 					   entry, txstatus);
@@ -951,16 +950,16 @@
 #endif
 				np->stats.collisions += (txstatus >> 3) & 15;
 #if defined(NETSTATS_VER2)
-				np->stats.tx_bytes += np->tx_ring[entry].desc_length & 0x7ff;
+				np->stats.tx_bytes += np->tx_skbuff[entry]->len;
 #endif
 				np->stats.tx_packets++;
 			}
 			/* Free the original skb. */
-			dev_free_skb(np->tx_skbuff[entry]);
+			dev_kfree_skb(np->tx_skbuff[entry]);
 			np->tx_skbuff[entry] = 0;
 		}
 		if (np->tx_full && dev->tbusy
-			&& np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
+			&& np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
 			/* The ring is no longer full, clear tbusy. */
 			np->tx_full = 0;
 			clear_bit(0, (void*)&dev->tbusy);
@@ -984,11 +983,6 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
 			   dev->name, readw(ioaddr + IntrStatus));
 
-#if defined(__i386__)
-	clear_bit(0, (void*)&dev->interrupt);
-#else
-	dev->interrupt = 0;
-#endif
 	return;
 }
 
@@ -1001,15 +995,15 @@
 	int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
 
 	if (debug > 4) {
-		printk(KERN_DEBUG " In netdev_rx(), entry %d status %4.4x.\n",
-			   entry, np->rx_head_desc->rx_length);
+		printk(KERN_DEBUG " In netdev_rx(), entry %d status %8.8x.\n",
+			   entry, np->rx_head_desc->rx_status);
 	}
 
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
-	while ( ! (np->rx_head_desc->rx_length & DescOwn)) {
+	while ( ! (np->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) {
 		struct rx_desc *desc = np->rx_head_desc;
-		int data_size = desc->rx_length;
-		u16 desc_status = desc->rx_status;
+		u32 desc_status = le32_to_cpu(desc->rx_status);
+		int data_size = desc_status >> 16;
 
 		if (debug > 4)
 			printk(KERN_DEBUG "  netdev_rx() status is %4.4x.\n",
@@ -1039,7 +1033,7 @@
 		} else {
 			struct sk_buff *skb;
 			/* Length should omit the CRC */
-			u16 pkt_len = data_size - 4;
+			int pkt_len = data_size - 4;
 
 			/* Check if the packet is long enough to accept without copying
 			   to a minimally-sized skbuff. */
@@ -1047,21 +1041,23 @@
 				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
 				skb->dev = dev;
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
-#if ! defined(__alpha__) || USE_IP_COPYSUM		/* Avoid misaligned on Alpha */
-				eth_copy_and_sum(skb, bus_to_virt(desc->addr),
-								 pkt_len, 0);
+#if HAS_IP_COPYSUM			/* Call copy + cksum if available. */
+				eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
 #else
-				memcpy(skb_put(skb,pkt_len), bus_to_virt(desc->addr), pkt_len);
+				memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail,
+					   pkt_len);
 #endif
 			} else {
 				skb_put(skb = np->rx_skbuff[entry], pkt_len);
 				np->rx_skbuff[entry] = NULL;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
-			np->stats.rx_bytes+=skb->len;
 			netif_rx(skb);
 			dev->last_rx = jiffies;
+#if defined(NETSTATS_VER2)
+			np->stats.rx_bytes += skb->len;
+#endif
 			np->stats.rx_packets++;
 		}
 		entry = (++np->cur_rx) % RX_RING_SIZE;
@@ -1078,10 +1074,9 @@
 			if (skb == NULL)
 				break;			/* Better luck next round. */
 			skb->dev = dev;			/* Mark as being used by this device. */
-			np->rx_ring[entry].addr = virt_to_bus(skb->tail);
+			np->rx_ring[entry].addr = virt_to_le32desc(skb->tail);
 		}
-		np->rx_ring[entry].rx_status = 0;
-		np->rx_ring[entry].rx_length = DescOwn;
+		np->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
 	}
 
 	/* Pre-emptively restart Rx engine. */
@@ -1095,10 +1090,11 @@
 	long ioaddr = dev->base_addr;
 
 	if (intr_status & (IntrMIIChange | IntrLinkChange)) {
-		if (readb(ioaddr + MIIStatus) & 0x02)
+		if (readb(ioaddr + MIIStatus) & 0x02) {
 			/* Link failed, restart autonegotiation. */
-			mdio_write(dev, np->phys[0], 0, 0x3300);
-		else
+			if (np->drv_flags & HasDavicomPhy)
+				mdio_write(dev, np->phys[0], 0, 0x3300);
+		} else
 			check_duplex(dev);
 		if (debug)
 			printk(KERN_ERR "%s: MII status changed: Autonegotiation "
@@ -1109,7 +1105,7 @@
 	if (intr_status & IntrStatsMax) {
 		np->stats.rx_crc_errors	+= readw(ioaddr + RxCRCErrs);
 		np->stats.rx_missed_errors	+= readw(ioaddr + RxMissed);
-		writel(0, RxMissed);
+		clear_tally_counters(ioaddr);
 	}
 	if (intr_status & IntrTxAbort) {
 		/* Stats counted in Tx-done handler, just restart Tx. */
@@ -1122,7 +1118,8 @@
 			printk(KERN_INFO "%s: Transmitter underrun, increasing Tx "
 				   "threshold setting to %2.2x.\n", dev->name, np->tx_thresh);
 	}
-	if ((intr_status & ~(IntrLinkChange|IntrStatsMax|IntrTxAbort)) && debug) {
+	if ((intr_status & ~(IntrLinkChange | IntrStatsMax |
+						 IntrTxAbort|IntrTxAborted))  &&  debug) {
 		printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
 			   dev->name, intr_status);
 		/* Recovery for other fault sources not known. */
@@ -1140,28 +1137,39 @@
 	   non-critical. */
 	np->stats.rx_crc_errors	+= readw(ioaddr + RxCRCErrs);
 	np->stats.rx_missed_errors	+= readw(ioaddr + RxMissed);
-	writel(0, RxMissed);
+	clear_tally_counters(ioaddr);
 
 	return &np->stats;
 }
 
+/* Clears the "tally counters" for CRC errors and missed frames(?).
+   It has been reported that some chips need a write of 0 to clear
+   these, for others the counters are set to 1 when written to and
+   instead cleared when read. So we clear them both ways ... */
+static inline void clear_tally_counters(const long ioaddr)
+{
+	writel(0, ioaddr + RxMissed);
+	readw(ioaddr + RxCRCErrs);
+	readw(ioaddr + RxMissed);
+}
+
 /* The big-endian AUTODIN II ethernet CRC calculation.
    N.B. Do not use for bulk data, use a table-based routine instead.
    This is common code and should be moved to net/core/crc.c */
 static unsigned const ethernet_polynomial = 0x04c11db7U;
 static inline u32 ether_crc(int length, unsigned char *data)
 {
-    int crc = -1;
+	int crc = -1;
 
-    while(--length >= 0) {
+	while(--length >= 0) {
 		unsigned char current_octet = *data++;
 		int bit;
 		for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
 			crc = (crc << 1) ^
 				((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
 		}
-    }
-    return crc;
+	}
+	return crc;
 }
 
 static void set_rx_mode(struct device *dev)
@@ -1178,6 +1186,8 @@
 	} else if ((dev->mc_count > multicast_filter_limit)
 			   ||  (dev->flags & IFF_ALLMULTI)) {
 		/* Too many to match, or accept all multicasts. */
+		writel(0xffffffff, ioaddr + MulticastFilter0);
+		writel(0xffffffff, ioaddr + MulticastFilter1);
 		rx_mode = 0x0C;
 	} else {
 		struct dev_mc_list *mclist;
@@ -1190,7 +1200,7 @@
 		}
 		writel(mc_filter[0], ioaddr + MulticastFilter0);
 		writel(mc_filter[1], ioaddr + MulticastFilter1);
-		rx_mode = 0x08;
+		rx_mode = 0x0C;
 	}
 	writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
 }
@@ -1207,7 +1217,7 @@
 		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
 		return 0;
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
-		if (!suser())
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
 		return 0;
@@ -1229,32 +1239,39 @@
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
 			   dev->name, readw(ioaddr + ChipCmd));
 
+	del_timer(&np->timer);
+
+	/* Switch to loopback mode to avoid hardware races. */
+	writeb(np->tx_thresh | 0x01, ioaddr + TxConfig);
+
 	/* Disable interrupts by clearing the interrupt mask. */
 	writew(0x0000, ioaddr + IntrEnable);
 
 	/* Stop the chip's Tx and Rx processes. */
 	writew(CmdStop, ioaddr + ChipCmd);
 
-	del_timer(&np->timer);
-
 	free_irq(dev->irq, dev);
 
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		np->rx_ring[i].rx_length = 0;
+		np->rx_ring[i].rx_status = 0;
 		np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
 		if (np->rx_skbuff[i]) {
 #if LINUX_VERSION_CODE < 0x20100
 			np->rx_skbuff[i]->free = 1;
 #endif
-			dev_free_skb(np->rx_skbuff[i]);
+			dev_kfree_skb(np->rx_skbuff[i]);
 		}
 		np->rx_skbuff[i] = 0;
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (np->tx_skbuff[i])
-			dev_free_skb(np->tx_skbuff[i]);
+			dev_kfree_skb(np->tx_skbuff[i]);
 		np->tx_skbuff[i] = 0;
+		if (np->tx_buf[i]) {
+			kfree(np->tx_buf[i]);
+			np->tx_buf[i] = 0;
+		}
 	}
 
 	MOD_DEC_USE_COUNT;
@@ -1267,37 +1284,28 @@
 int init_module(void)
 {
 	if (debug)					/* Emit version even if no cards detected. */
-		printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
-#ifdef CARDBUS
-	register_driver(&etherdev_ops);
-	return 0;
-#else
+		printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
 	return pci_etherdev_probe(NULL, pci_tbl);
-#endif
 }
 
 void cleanup_module(void)
 {
-
-#ifdef CARDBUS
-	unregister_driver(&etherdev_ops);
-#endif
+	struct device *next_dev;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_net_dev) {
-		struct netdev_private *np =
-			(struct netdev_private *)(root_net_dev->priv);
+		struct netdev_private *np = (void *)(root_net_dev->priv);
 		unregister_netdev(root_net_dev);
-#ifdef VIA_USE_IO
+#ifdef USE_IO_OPS
 		release_region(root_net_dev->base_addr, pci_tbl[np->chip_id].io_size);
 #else
 		iounmap((char *)(root_net_dev->base_addr));
 #endif
+		next_dev = np->next_module;
+		if (np->priv_addr)
+			kfree(np->priv_addr);
 		kfree(root_net_dev);
-		root_net_dev = np->next_module;
-#if 0
-		kfree(np);				/* Assumption: no struct realignment. */
-#endif
+		root_net_dev = next_dev;
 	}
 }
 
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c
--- linux-2.2.19-pre2/drivers/s390/block/dasd.c	Sun Dec 10 16:49:42 2000
+++ linux/drivers/s390/block/dasd.c	Mon Dec  3 20:53:37 2001
@@ -2924,9 +2924,7 @@
 int
 init_module ( void )
 {
-        int rc=0;
         return dasd_init(); 
-        return rc;
 }
 
 void 
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd.h linux/drivers/s390/block/dasd.h
--- linux-2.2.19-pre2/drivers/s390/block/dasd.h	Sun Dec 10 16:49:42 2000
+++ linux/drivers/s390/block/dasd.h	Mon Dec  3 20:53:37 2001
@@ -7,3 +7,8 @@
 int (*genhd_dasd_name)(char*,int,int,struct gendisk*);
 int dasd_oper_handler ( int irq, devreg_t *devreg );
 
+dasd_era_t dasd_3370_erp_examine (ccw_req_t * cqr, devstat_t * stat);
+dasd_era_t dasd_3990_erp_examine (ccw_req_t * cqr, devstat_t * stat);
+dasd_era_t dasd_9336_erp_examine (ccw_req_t * cqr, devstat_t * stat);
+dasd_era_t dasd_9343_erp_examine (ccw_req_t * cqr, devstat_t * stat);
+
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd_3370_erp.c linux/drivers/s390/block/dasd_3370_erp.c
--- linux-2.2.19-pre2/drivers/s390/block/dasd_3370_erp.c	Mon Sep  4 10:39:20 2000
+++ linux/drivers/s390/block/dasd_3370_erp.c	Mon Dec  3 20:53:37 2001
@@ -5,6 +5,7 @@
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  */
 
+#include <linux/blkdev.h>
 #include <asm/ccwcache.h>
 #include <asm/dasd.h>
 
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd_3990_erp.c linux/drivers/s390/block/dasd_3990_erp.c
--- linux-2.2.19-pre2/drivers/s390/block/dasd_3990_erp.c	Sun Dec 10 16:49:42 2000
+++ linux/drivers/s390/block/dasd_3990_erp.c	Mon Dec  3 20:53:37 2001
@@ -6,6 +6,7 @@
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  */
 
+#include <linux/blkdev.h>
 #include <asm/ccwcache.h>
 #include <asm/dasd.h>
 
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd_9336_erp.c linux/drivers/s390/block/dasd_9336_erp.c
--- linux-2.2.19-pre2/drivers/s390/block/dasd_9336_erp.c	Mon Sep  4 10:39:20 2000
+++ linux/drivers/s390/block/dasd_9336_erp.c	Mon Dec  3 20:53:37 2001
@@ -5,6 +5,7 @@
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  */
 
+#include <linux/blkdev.h>
 #include <asm/ccwcache.h>
 #include <asm/dasd.h>
 
@@ -32,8 +33,6 @@
 dasd_era_t
 dasd_9336_erp_examine (ccw_req_t * cqr, devstat_t * stat)
 {
-	char *sense = stat->ii.sense.data;
-
 	/* check for successful execution first */
 	if (stat->cstat == 0x00 &&
 	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd_9343_erp.c linux/drivers/s390/block/dasd_9343_erp.c
--- linux-2.2.19-pre2/drivers/s390/block/dasd_9343_erp.c	Mon Sep  4 10:39:20 2000
+++ linux/drivers/s390/block/dasd_9343_erp.c	Mon Dec  3 20:53:37 2001
@@ -5,6 +5,7 @@
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  */
 
+#include <linux/blkdev.h>
 #include <asm/ccwcache.h>
 #include <asm/dasd.h>
 
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd_eckd.c linux/drivers/s390/block/dasd_eckd.c
--- linux-2.2.19-pre2/drivers/s390/block/dasd_eckd.c	Sun Dec 10 16:49:42 2000
+++ linux/drivers/s390/block/dasd_eckd.c	Mon Dec  3 20:53:37 2001
@@ -74,6 +74,7 @@
         eckd_count_t count_area;
 } dasd_eckd_private_t;
 
+#ifdef CONFIG_DASD_DYNAMIC
 static
 devreg_t dasd_eckd_known_devices[] = {
 	{
@@ -92,6 +93,7 @@
                 oper_func: dasd_oper_handler
         }
 };
+#endif
 
 static inline unsigned int
 round_up_multiple (unsigned int no, unsigned int mult)
@@ -923,7 +925,9 @@
 int
 dasd_eckd_init( void ) {
         int rc = 0;
+#ifdef CONFIG_DASD_DYNAMIC
 	int i;
+#endif
         printk ( KERN_INFO PRINTK_HEADER
                  "%s discipline initializing\n", dasd_eckd_discipline.name);
         ASCEBC(dasd_eckd_discipline.ebcname,4);
@@ -944,8 +948,9 @@
 
 void
 dasd_eckd_cleanup( void ) {
-        int rc = 0;
+#ifdef CONFIG_DASD_DYNAMIC
 	int i;
+#endif
         printk ( KERN_INFO PRINTK_HEADER
                  "%s discipline cleaning up\n", dasd_eckd_discipline.name);
 #ifdef CONFIG_DASD_DYNAMIC
@@ -960,7 +965,7 @@
 	} 
 #endif /* CONFIG_DASD_DYNAMIC */
         dasd_discipline_deq(&dasd_eckd_discipline);
-        return rc;
+        return;
 }
 
 /*
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd_eckd.h linux/drivers/s390/block/dasd_eckd.h
--- linux-2.2.19-pre2/drivers/s390/block/dasd_eckd.h	Mon Sep  4 10:39:20 2000
+++ linux/drivers/s390/block/dasd_eckd.h	Mon Dec  3 20:53:37 2001
@@ -282,5 +282,6 @@
 } __attribute__ ((packed)) dasd_eckd_confdata_t;
 
 int dasd_eckd_init( void );
+void dasd_eckd_cleanup( void );
 
 #endif /* DASD_ECKD_H */
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd_fba.c linux/drivers/s390/block/dasd_fba.c
--- linux-2.2.19-pre2/drivers/s390/block/dasd_fba.c	Sun Dec 10 16:49:42 2000
+++ linux/drivers/s390/block/dasd_fba.c	Mon Dec  3 20:53:37 2001
@@ -181,9 +181,7 @@
         int rc = 0;
 	unsigned long sectors = device->sizes.blocks << device->sizes.s2b_shift;
 	unsigned long tracks = sectors >> 6;
-	unsigned long trk_rem = sectors & ((1<<6)-1);
 	unsigned long cyls = tracks >> 4;
-	unsigned long cyls_rem = tracks & ((1<<4)-1);
 
         switch(device->sizes.bp_block) {
         case 512:
@@ -371,7 +369,9 @@
 int
 dasd_fba_init( void ) {
         int rc = 0;
+#ifdef	CONFIG_DASD_DYNAMIC
 	int i;
+#endif
         printk ( KERN_INFO PRINTK_HEADER
                  "%s discipline initializing\n", dasd_fba_discipline.name);
         ASCEBC(dasd_fba_discipline.ebcname,4);
@@ -392,8 +392,9 @@
 
 void
 dasd_fba_cleanup( void ) {
-        int rc = 0;
+#ifdef	CONFIG_DASD_DYNAMIC
 	int i;
+#endif
         printk ( KERN_INFO PRINTK_HEADER
                  "%s discipline cleaning up\n", dasd_fba_discipline.name);
 #ifdef CONFIG_DASD_DYNAMIC
@@ -408,7 +409,7 @@
         }
 #endif /* CONFIG_DASD_DYNAMIC */
         dasd_discipline_deq(&dasd_fba_discipline);
-        return rc;
+        return;
 }
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -urN linux-2.2.19-pre2/drivers/s390/block/dasd_fba.h linux/drivers/s390/block/dasd_fba.h
--- linux-2.2.19-pre2/drivers/s390/block/dasd_fba.h	Mon Sep  4 10:39:20 2000
+++ linux/drivers/s390/block/dasd_fba.h	Mon Dec  3 20:53:37 2001
@@ -66,5 +66,6 @@
 } __attribute__ ((packed)) dasd_fba_characteristics_t;
 
 int dasd_fba_init( void );
+void dasd_fba_cleanup( void );
 
 #endif /* DASD_FBA_H */
diff -urN linux-2.2.19-pre2/drivers/s390/block/mdisk.c linux/drivers/s390/block/mdisk.c
--- linux-2.2.19-pre2/drivers/s390/block/mdisk.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/s390/block/mdisk.c	Mon Dec  3 20:53:37 2001
@@ -105,6 +105,122 @@
 } mdisk_setup_data;
 
 /*
+ * The 'low level' IO function
+ */
+
+static __inline__ int
+dia250(void* iob,int cmd)
+{
+	int rc;
+	
+	iob = (void*) virt_to_phys(iob);
+
+	asm volatile ("    lr    2,%1\n"
+		      "    lr    3,%2\n"
+		      "    .long 0x83230250\n"
+		      "    lr    %0,3"
+		      : "=d" (rc)
+		      : "d" (iob) , "d" (cmd)
+		      : "2", "3" );
+	return rc;
+}
+
+/*
+ * The device characteristics function
+ */
+
+static __inline__ int
+dia210(void* devchar)
+{
+	int rc;
+
+	devchar = (void*) virt_to_phys(devchar);
+
+	asm volatile ("    lr    2,%1\n"
+		      "    .long 0x83200210\n"
+		      "    ipm   %0\n"
+		      "    srl   %0,28"
+		      : "=d" (rc)
+		      : "d" (devchar)
+		      : "2" );
+	return rc;
+}
+
+
+/*
+ * release of minidisk device
+ */
+
+static __inline__ int
+mdisk_term_io(mdisk_Dev *dev)
+{
+	mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
+	
+	memset(iob,0,sizeof(mdisk_init_io_t));
+	
+	iob->dev_nr = dev->vdev;
+	
+	return dia250(iob,TERM_BIO);
+}
+
+
+/*
+ * Init of minidisk device
+ */
+
+static __inline__ int
+mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size)
+{
+	mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
+	int rc;
+
+	memset(iob,0,sizeof(mdisk_init_io_t));
+	
+	iob->dev_nr = dev->vdev;
+	iob->block_size = blocksize;
+	iob->offset     = offset;
+	iob->start_block= 0;
+	iob->end_block  = size;
+	
+	rc = dia250(iob,INIT_BIO);
+	
+	/*
+	 * clear for following io once
+	 */
+	
+	memset(iob,0,sizeof(mdisk_rw_io_t));
+	
+	return rc;
+}
+
+
+/*
+ * setup and start of minidisk io request
+ */
+
+static __inline__ int
+mdisk_rw_io_clustered (mdisk_Dev *dev,
+                       mdisk_bio_t* bio_array,
+                       int length,
+                       int req,
+                       int sync)
+{
+	int rc;
+	mdisk_rw_io_t *iob = dev->iob;
+	
+	iob->dev_nr      = dev->vdev;
+	iob->key         = 0;
+	iob->flags       = sync;
+	
+	iob->block_count = length;
+	iob->interrupt_params = req;
+	iob->bio_list     = virt_to_phys(bio_array);
+	
+	rc = dia250(iob,RW_BIO);
+	return rc;
+}
+
+/*
  * Parameter parsing function, called from init/main.c
  * vdev    : virtual device number
  * size    : size in kbyte
@@ -117,7 +233,7 @@
 {
 	char *cur = str;
 	int vdev, size, offset=0,blksize;
-	static i = 0;
+static	int i = 0;
 	if (!i)
 	  memset(&mdisk_setup_data,0,sizeof(mdisk_setup_data));
 
@@ -280,48 +396,7 @@
 	NULL,          /* mdisk_lock */
 };
 
-/*
- * The 'low level' IO function
- */
-
-
-static __inline__ int
-dia250(void* iob,int cmd)
-{
-	int rc;
-	
-	iob = (void*) virt_to_phys(iob);
-
-	asm volatile ("    lr    2,%1\n"
-		      "    lr    3,%2\n"
-		      "    .long 0x83230250\n"
-		      "    lr    %0,3"
-		      : "=d" (rc)
-		      : "d" (iob) , "d" (cmd)
-		      : "2", "3" );
-	return rc;
-}
-
-/*
- * The device characteristics function
- */
-
-static __inline__ int
-dia210(void* devchar)
-{
-	int rc;
-
-	devchar = (void*) virt_to_phys(devchar);
 
-	asm volatile ("    lr    2,%1\n"
-		      "    .long 0x83200210\n"
-		      "    ipm   %0\n"
-		      "    srl   %0,28"
-		      : "=d" (rc)
-		      : "d" (devchar)
-		      : "2" );
-	return rc;
-}
 /*
  * read the label of a minidisk and extract its characteristics
  */
@@ -396,80 +471,6 @@
 }
 
 
-
-/*
- * Init of minidisk device
- */
-
-static __inline__ int
-mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size)
-{
-	mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
-	int rc;
-
-	memset(iob,0,sizeof(mdisk_init_io_t));
-	
-	iob->dev_nr = dev->vdev;
-	iob->block_size = blocksize;
-	iob->offset     = offset;
-	iob->start_block= 0;
-	iob->end_block  = size;
-	
-	rc = dia250(iob,INIT_BIO);
-	
-	/*
-	 * clear for following io once
-	 */
-	
-	memset(iob,0,sizeof(mdisk_rw_io_t));
-	
-	return rc;
-}
-
-/*
- * release of minidisk device
- */
-
-static __inline__ int
-mdisk_term_io(mdisk_Dev *dev)
-{
-	mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
-	
-	memset(iob,0,sizeof(mdisk_init_io_t));
-	
-	iob->dev_nr = dev->vdev;
-	
-	return dia250(iob,TERM_BIO);
-}
-
-/*
- * setup and start of minidisk io request
- */
-
-static __inline__ int
-mdisk_rw_io_clustered (mdisk_Dev *dev,
-                       mdisk_bio_t* bio_array,
-                       int length,
-                       int req,
-                       int sync)
-{
-	int rc;
-	mdisk_rw_io_t *iob = dev->iob;
-	
-	iob->dev_nr      = dev->vdev;
-	iob->key         = 0;
-	iob->flags       = sync;
-	
-	iob->block_count = length;
-	iob->interrupt_params = req;
-	iob->bio_list     = virt_to_phys(bio_array);
-	
-	rc = dia250(iob,RW_BIO);
-	return rc;
-}
-
-
-
 /*
  * this handles a clustered request in success case
  * all buffers are detach and marked uptodate to the kernel
@@ -640,11 +641,8 @@
  */
 void do_mdisk_interrupt(struct pt_regs *regs, __u16 code)
 {
-        u16 code;
 	mdisk_Dev *dev;
 	
-	code = S390_lowcore.cpu_addr;
-
 	if ((code >> 8) != 0x03) {
 	  printk("mnd: wrong sub-interruption code %d",code>>8);
 	  return;
diff -urN linux-2.2.19-pre2/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c
--- linux-2.2.19-pre2/drivers/scsi/gdth.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/scsi/gdth.c	Mon Dec  3 20:53:37 2001
@@ -20,9 +20,19 @@
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Tested with Linux 1.2.13, ..., 2.2.16, ..., 2.4.0-test4              *
+ * Tested with Linux 1.2.13, ..., 2.2.16, ..., 2.4.0-test10             *
  *                                                                      *
  * $Log: gdth.c,v $
+ * Revision 1.45  2000/11/16 12:02:24  achim
+ * Changes for kernel 2.4
+ *
+ * Revision 1.44  2000/10/11 08:44:10  achim
+ * Clustering changes: New flag media_changed added
+ *
+ * Revision 1.43  2000/09/20 12:59:01  achim
+ * DPMEM remap functions for all PCI controller types implemented
+ * Small changes for ia64 platform
+ *
  * Revision 1.42  2000/07/20 09:04:50  achim
  * Small changes for kernel 2.4
  *
@@ -180,7 +190,7 @@
  * Initial revision
  *
  ************************************************************************/
-#ident "$Id: gdth.c,v 1.42 2000/07/20 09:04:50 achim Exp $" 
+#ident "$Id: gdth.c,v 1.45 2000/11/16 12:02:24 achim Exp $" 
 
 /* All GDT Disk Array Controllers are fully supported by this driver.
  * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
@@ -1111,8 +1121,51 @@
             printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
             return 0;
         }
+        /* check and reset interface area */
         dp6_ptr = (gdt6_dpram_str *)ha->brd;
-        /* reset interface area */
+        gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
+        if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) {
+            printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
+                   pcistr->dpmem);
+            found = FALSE;
+            for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
+                gdth_munmap(ha->brd);
+                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                if (gdth_readw(ha->brd) != 0xffff) {
+                    TRACE2(("init_pci_old() address 0x%x busy\n", i));
+                    continue;
+                }
+                gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
+                pci_write_config_dword(pcistr->pdev, 
+                                       PCI_BASE_ADDRESS_0, i);
+#else
+                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                           PCI_BASE_ADDRESS_0, i);
+#endif
+                ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                dp6_ptr = (gdt6_dpram_str *)ha->brd;
+                gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
+                if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) {
+                    printk("GDT-PCI: Use free address at 0x%x\n", i);
+                    found = TRUE;
+                    break;
+                }
+            }   
+            if (!found) {
+                printk("GDT-PCI: No free address found!\n");
+                gdth_munmap(ha->brd);
+                return 0;
+            }
+        }
         memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
         if (gdth_readl(&dp6_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
@@ -1181,8 +1234,51 @@
             gdth_munmap(ha->brd);
             return 0;
         }
+        /* check and reset interface area */
         dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
-        /* reset interface area */
+        gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
+        if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
+            printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
+                   pcistr->dpmem);
+            found = FALSE;
+            for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
+                gdth_munmap(ha->brd);
+                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                if (gdth_readw(ha->brd) != 0xffff) {
+                    TRACE2(("init_pci_plx() address 0x%x busy\n", i));
+                    continue;
+                }
+                gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
+                pci_write_config_dword(pcistr->pdev, 
+                                       PCI_BASE_ADDRESS_2, i);
+#else
+                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                           PCI_BASE_ADDRESS_2, i);
+#endif
+                ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+                gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
+                if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
+                    printk("GDT-PCI: Use free address at 0x%x\n", i);
+                    found = TRUE;
+                    break;
+                }
+            }   
+            if (!found) {
+                printk("GDT-PCI: No free address found!\n");
+                gdth_munmap(ha->brd);
+                return 0;
+            }
+        }
         memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
         if (gdth_readl(&dp6c_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
@@ -1966,7 +2062,6 @@
     TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
 
     /* set/get features raw service (scatter/gather) */
-    ha->raw_feat = 0;
     if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
                           0,0)) {
         TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
@@ -2061,18 +2156,14 @@
         TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n",
                 hdrive,ha->info));
         ha->hdr[hdrive].cluster_type = (unchar)ha->info;
-    } else {
-        ha->hdr[hdrive].cluster_type = 0;
-    }           
+    }
 
     /* R/W attributes */
     if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_RW_ATTRIBS,hdrive,0,0)) {
         TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n",
                 hdrive,ha->info));
         ha->hdr[hdrive].rw_attribs = (unchar)ha->info;
-    } else {
-        ha->hdr[hdrive].rw_attribs = 0;
-    }           
+    }
 
     return 1;
 }
@@ -2264,10 +2355,14 @@
             TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
                     nscp->cmnd[0], b, t, nscp->lun));
             nscp->result = DID_BAD_TARGET << 16;
-            GDTH_UNLOCK_HA(ha,flags);
-            /* io_request_lock already active ! */      
-            nscp->scsi_done(nscp);
-            GDTH_LOCK_HA(ha,flags);
+	    if (!nscp->SCp.have_data_in)
+		nscp->SCp.have_data_in++;
+	    else {
+		GDTH_UNLOCK_HA(ha,flags);
+		/* io_request_lock already active ! */      
+		nscp->scsi_done(nscp);
+		GDTH_LOCK_HA(ha,flags);
+	    }
         } else {
             switch (nscp->cmnd[0]) {
               case TEST_UNIT_READY:
@@ -2280,7 +2375,24 @@
                 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
                        nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                        nscp->cmnd[4],nscp->cmnd[5]));
-                if (gdth_internal_cache_cmd(hanum,nscp)) {
+                if (ha->hdr[t].media_changed && nscp->cmnd[0] != INQUIRY) {
+                    /* return UNIT_ATTENTION */
+                    TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
+                             nscp->cmnd[0], t));
+                    ha->hdr[t].media_changed = FALSE;
+                    memset((char*)nscp->sense_buffer,0,16);
+                    nscp->sense_buffer[0] = 0x70;
+                    nscp->sense_buffer[2] = UNIT_ATTENTION;
+                    nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+                    if (!nscp->SCp.have_data_in)
+                        nscp->SCp.have_data_in++;
+                    else {
+                        GDTH_UNLOCK_HA(ha,flags);
+                        /* io_request_lock already active ! */      
+                        nscp->scsi_done(nscp);
+                        GDTH_LOCK_HA(ha,flags);
+                    }
+		} else if (gdth_internal_cache_cmd(hanum,nscp)) {
                     GDTH_UNLOCK_HA(ha,flags);
                     /* io_request_lock already active ! */      
                     nscp->scsi_done(nscp);
@@ -2325,7 +2437,24 @@
               case WRITE_6:
               case READ_10:
               case WRITE_10:
-                if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                if (ha->hdr[t].media_changed) {
+                    /* return UNIT_ATTENTION */
+                    TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
+                             nscp->cmnd[0], t));
+                    ha->hdr[t].media_changed = FALSE;
+                    memset((char*)nscp->sense_buffer,0,16);
+                    nscp->sense_buffer[0] = 0x70;
+                    nscp->sense_buffer[2] = UNIT_ATTENTION;
+                    nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+                    if (!nscp->SCp.have_data_in)
+                        nscp->SCp.have_data_in++;
+                    else {
+                        GDTH_UNLOCK_HA(ha,flags);
+                        /* io_request_lock already active ! */      
+                        nscp->scsi_done(nscp);
+                        GDTH_LOCK_HA(ha,flags);
+                    }
+		} else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
                     this_cmd = FALSE;
                 break;
 
@@ -2471,6 +2600,7 @@
         TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
         break;
     }
+
     scp->result = DID_OK << 16;
     scp->sense_buffer[0] = 0;
 
@@ -2487,7 +2617,8 @@
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmdp;
     struct scatterlist *sl;
-    ushort i;
+    ushort i, cnt;
+    ulong32 no;
     int cmd_index, read_write;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
@@ -2543,11 +2674,13 @@
 
     if (read_write) {
         if (scp->cmd_len != 6) {
-            cmdp->u.cache.BlockNo = ntohl(*(ulong32*)&scp->cmnd[2]);
-            cmdp->u.cache.BlockCnt= (ulong32)ntohs(*(ushort*)&scp->cmnd[7]);
+            memcpy(&no, &scp->cmnd[2], sizeof(ulong32));
+            cmdp->u.cache.BlockNo = ntohl(no);
+            memcpy(&cnt, &scp->cmnd[7], sizeof(ushort));
+            cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt);
         } else {
-            cmdp->u.cache.BlockNo = 
-                ntohl(*(ulong32*)&scp->cmnd[0]) & 0x001fffffUL;
+            memcpy(&no, &scp->cmnd[0], sizeof(ulong32));
+            cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL;
             cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
         }
 
@@ -2660,7 +2793,7 @@
         cmdp->u.raw.lun        = l;
         cmdp->u.raw.bus        = b;
         cmdp->u.raw.priority   = 0;
-        cmdp->u.raw.link_p     = NULL;
+        cmdp->u.raw.link_p     = 0;
         cmdp->u.raw.sdlen      = scp->request_bufflen;
         cmdp->u.raw.sense_len  = 16;
         cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
@@ -2825,6 +2958,7 @@
         e->first_stamp = e->last_stamp = tv.tv_sec;
         e->same_count = 1;
         e->event_data = *evt;
+        e->application = 0;
     }
     return e;
 }
@@ -3195,36 +3329,28 @@
                     if (!(ha->hdr[scp->target].cluster_type & 
                         CLUSTER_MOUNTED)) {
                         /* NOT MOUNTED -> MOUNT */
-                        if (!(ha->hdr[scp->target].cluster_type & 
-                            CLUSTER_RESERVED)) {
-                            /* cluster drive NOT RESERVED */
-                            scp->SCp.Status = GDT_MOUNT;
-                        } else {
+                        scp->SCp.Status = GDT_MOUNT;
+                        if (ha->hdr[scp->target].cluster_type & 
+                            CLUSTER_RESERVED) {
                             /* cluster drive RESERVED (on the other node) */
-                            scp->SCp.Status = GDT_MOUNT;
                             scp->SCp.phase = -2;      /* reservation conflict */
                         }
                     } else {
                         scp->SCp.Status = -1;
                     }
-                    /* retry */
-                    scp->SCp.this_residual = HIGH_PRI;
-                    return 2;
-                } else if (scp->SCp.Status == GDT_MOUNT) {
-                    ha->hdr[scp->target].cluster_type |= CLUSTER_MOUNTED;
-                    scp->SCp.Status = -1;
-                    /* return UNIT_ATTENTION */
-                    memset((char*)scp->sense_buffer,0,16);
-                    scp->sense_buffer[0] = 0x70;
-                    scp->sense_buffer[2] = UNIT_ATTENTION;
-                    scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-                    scp->SCp.Message = (int)(ha->info<<16|S_BSY);
-                } else {
+		} else {
+                    if (scp->SCp.Status == GDT_MOUNT) {
+                        ha->hdr[scp->target].cluster_type |= CLUSTER_MOUNTED;
+                        ha->hdr[scp->target].media_changed = TRUE;
+                    } else if (scp->SCp.Status == GDT_UNMOUNT) {
+                        ha->hdr[scp->target].cluster_type &= ~CLUSTER_MOUNTED;
+                        ha->hdr[scp->target].media_changed = TRUE;
+                    } 
                     scp->SCp.Status = -1;
-                    /* retry */
-                    scp->SCp.this_residual = HIGH_PRI;
-                    return 2;
                 }
+                /* retry */
+                scp->SCp.this_residual = HIGH_PRI;
+                return 2;
             } else {
                 /* RESERVE/RELEASE ? */
                 if (scp->cmnd[0] == RESERVE) {
@@ -3259,12 +3385,6 @@
                 scp->sense_buffer[0] = 0x70;
                 scp->sense_buffer[2] = NOT_READY;
                 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-            } else if (scp->cmnd[0] == RESERVE ||
-                       scp->cmnd[0] == RELEASE) {
-                memset((char*)scp->sense_buffer,0,16);
-                scp->sense_buffer[0] = 0x70;
-                scp->sense_buffer[2] = NOT_READY;
-                scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
             } else if (service == CACHESERVICE) {
                 if (ha->status == S_CACHE_UNKNOWN &&
                     (ha->hdr[scp->target].cluster_type & 
@@ -3293,7 +3413,7 @@
                 }
             } else {
                 /* sense buffer filled from controller firmware (DMA) */
-                if (ha->status!=S_RAW_SCSI || ha->info>=0x100) {
+                if (ha->status != S_RAW_SCSI || ha->info >= 0x100) {
                     scp->result = DID_BAD_TARGET << 16;
                 } else {
                     scp->result = (DID_OK << 16) | ha->info;
@@ -4467,8 +4587,12 @@
     }
 }
 
-
+#if LINUX_VERSION_CODE < 0x020400
 #ifdef MODULE
+Scsi_Host_Template driver_template = GDTH;
+#include "scsi_module.c"
+#endif
+#else
 Scsi_Host_Template driver_template = GDTH;
 #include "scsi_module.c"
 #endif
diff -urN linux-2.2.19-pre2/drivers/scsi/gdth.h linux/drivers/scsi/gdth.h
--- linux-2.2.19-pre2/drivers/scsi/gdth.h	Sun Dec 10 16:49:43 2000
+++ linux/drivers/scsi/gdth.h	Mon Dec  3 20:53:37 2001
@@ -10,7 +10,7 @@
  *
  * <achim@vortex.de>
  *
- * $Id: gdth.h,v 1.33 2000/07/24 09:29:25 achim Exp $
+ * $Id: gdth.h,v 1.35 2000/10/11 08:42:38 achim Exp $
  */
 
 #include <linux/version.h>
@@ -29,9 +29,9 @@
 /* defines, macros */
 
 /* driver version */
-#define GDTH_VERSION_STR        "1.23"
+#define GDTH_VERSION_STR        "1.25"
 #define GDTH_VERSION            1
-#define GDTH_SUBVERSION         23
+#define GDTH_SUBVERSION         25
 
 /* protocol version */
 #define PROTOCOL_VERSION        1
@@ -625,7 +625,7 @@
             unchar      priority;               /* only 0 used */
             ulong32     sense_len;              /* sense data length */
             ulong32     sense_data;             /* sense data addr. */
-            struct raw  *link_p;                /* linked cmds (not supp.) */
+            ulong32     link_p;                 /* linked cmds (not supp.) */
             ulong32     sg_ranz;                /* s/g element count */
             gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
         } PACKED raw;                           /* raw service cmd. struct. */
@@ -877,7 +877,7 @@
     Scsi_Cmnd           *req_first;             /* top of request queue */
     struct {
         unchar          present;                /* Flag: host drive present? */
-        unchar          is_logdrv;              /* Flag: logical drive (master)? */
+        unchar          is_logdrv;              /* Flag: log. drive (master)? */
         unchar          is_arraydrv;            /* Flag: array drive? */
         unchar          is_master;              /* Flag: array drive master? */
         unchar          is_parity;              /* Flag: parity drive? */
@@ -891,7 +891,7 @@
         unchar          ldr_no;                 /* log. drive no. */
         unchar          rw_attribs;             /* r/w attributes */
         unchar          cluster_type;           /* cluster properties */
-        unchar          reserved;
+        unchar          media_changed;          /* Flag:MOUNT/UNMOUNT occured */
         ulong32         start_sec;              /* start sector */
     } hdr[MAX_LDRIVES];                         /* host drives */
     struct {
diff -urN linux-2.2.19-pre2/drivers/scsi/gdth_ioctl.h linux/drivers/scsi/gdth_ioctl.h
--- linux-2.2.19-pre2/drivers/scsi/gdth_ioctl.h	Sun Dec 10 16:49:43 2000
+++ linux/drivers/scsi/gdth_ioctl.h	Mon Dec  3 20:53:37 2001
@@ -2,7 +2,7 @@
 #define _GDTH_IOCTL_H
 
 /* gdth_ioctl.h
- * $Id: gdth_ioctl.h,v 1.6 2000/07/24 09:29:43 achim Exp $
+ * $Id: gdth_ioctl.h,v 1.7 2000/10/11 08:43:35 achim Exp $
  */
 
 /* IOCTLs */
@@ -19,6 +19,7 @@
 #define GDTIOCTL_SCSI       (GDTIOCTL_MASK | 9) /* SCSI command */
 #define GDTIOCTL_RESET_BUS  (GDTIOCTL_MASK |10) /* reset SCSI bus */
 #define GDTIOCTL_RESCAN     (GDTIOCTL_MASK |11) /* rescan host drives */
+#define GDTIOCTL_RESET_DRV  (GDTIOCTL_MASK |12) /* reset (remote) drv. res. */
 
 #define GDTIOCTL_MAGIC      0xaffe0003UL
 #define EVENT_SIZE          294 
diff -urN linux-2.2.19-pre2/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c
--- linux-2.2.19-pre2/drivers/scsi/gdth_proc.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/scsi/gdth_proc.c	Mon Dec  3 20:53:37 2001
@@ -1,5 +1,5 @@
 /* gdth_proc.c 
- * $Id: gdth_proc.c,v 1.22 2000/07/24 09:30:28 achim Exp $
+ * $Id: gdth_proc.c,v 1.23 2000/10/11 08:43:11 achim Exp $
  */
 
 #include "gdth_ioctl.h"
@@ -524,6 +524,30 @@
             gdth_analyse_hdrive(hanum, k);
         gdth_polling = FALSE;
         GDTH_UNLOCK_HA(ha, flags);
+        break;
+
+      case GDTIOCTL_RESET_DRV:
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
+            return(-EBUSY);
+        piord = (gdth_iord_str *)ha->pscratch;
+        piord->size = sizeof(gdth_iord_str);
+        piord->status = S_OK;
+        i = piowr->iu.scsi.target;
+        if (ha->hdr[i].present) {
+            gdtcmd.BoardNode = LOCALBOARD;
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_CLUST_RESET;
+            gdtcmd.u.cache.DeviceNo = i;
+            gdtcmd.u.cache.BlockNo = 0;
+            gdtcmd.u.cache.sg_canz = 0;
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            piord->status = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            piord->status = (ulong32)scp.SCp.Message;
+#endif
+        }
         break;
 
       default:
diff -urN linux-2.2.19-pre2/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- linux-2.2.19-pre2/drivers/scsi/ultrastor.c	Sat Apr 11 11:13:25 1998
+++ linux/drivers/scsi/ultrastor.c	Mon Dec  3 20:53:37 2001
@@ -882,9 +882,8 @@
 	(inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
       {
 	int flags;
-	save_flags(flags);
 	printk("Ux4F: abort while completed command pending\n");
-	restore_flags(flags);
+	save_flags(flags);
 	cli();
 	ultrastor_interrupt(0, NULL, NULL);
 	restore_flags(flags);
diff -urN linux-2.2.19-pre2/drivers/sound/Config.in linux/drivers/sound/Config.in
--- linux-2.2.19-pre2/drivers/sound/Config.in	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/Config.in	Mon Dec  3 20:53:37 2001
@@ -311,10 +311,7 @@
   fi
   
   dep_tristate 'NM256AV/NM256ZX audio support' CONFIG_SOUND_NM256 $CONFIG_SOUND_OSS
-  dep_tristate 'Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS
-  if [ "$CONFIG_SOUND_YMPCI" = "n" ]; then
-    dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS
-  fi
+  dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS
 
   # Additional low level drivers.
   
diff -urN linux-2.2.19-pre2/drivers/sound/Makefile linux/drivers/sound/Makefile
--- linux-2.2.19-pre2/drivers/sound/Makefile	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/Makefile	Mon Dec  3 20:53:37 2001
@@ -97,7 +97,7 @@
 obj-$(CONFIG_SOUND_SONICVIBES)	+= sonicvibes.o
 obj-$(CONFIG_SOUND_TRIDENT)     += trident.o ac97_codec.o
 obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o ac97_codec.o
-obj-$(CONFIG_SOUND_YMFPCI)	+= ymfpci.o ac97_codec.o
+obj-$(CONFIG_SOUND_YMFPCI)	+= ymfpci.o ac97_codec.o uart401.o
 
 ifeq ($(CONFIG_SOUND_EMU10K1),y)
   obj-y				+= emu10k1/emu10k1.o
@@ -126,7 +126,6 @@
 wavefront-objs  := wavfront.o wf_midi.o yss225.o
 nm256-objs	:= nm256_audio.o ac97.o
 via82cxxx-objs  := via82cxxx_audio.o ac97.o
-ymfsb-objs	:= ymf_sb.o ac97.o
 
 
 # Extract lists of the multi-part drivers.
@@ -217,9 +216,6 @@
 
 via82cxxx.o: $(via82cxxx-objs)
 	$(LD) -r -o $@ $(via82cxxx-objs)
-
-ymfsb.o: $(ymfsb-objs)
-	$(LD) -r -o $@ $(ymfsb-objs)
 
 # Firmware files that need translation
 #
diff -urN linux-2.2.19-pre2/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c
--- linux-2.2.19-pre2/drivers/sound/emu10k1/main.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/emu10k1/main.c	Mon Dec  3 20:53:37 2001
@@ -784,10 +784,3 @@
 
 module_init(emu10k1_init_module);
 module_exit(emu10k1_cleanup_module);
-
-#ifndef MODULE
-int __init init_emu10k1(void)
-{
-        return emu10k1_init_module();
-}
-#endif
diff -urN linux-2.2.19-pre2/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- linux-2.2.19-pre2/drivers/sound/es1370.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/es1370.c	Mon Dec  3 20:53:37 2001
@@ -114,6 +114,11 @@
  *    03.09.1999   0.30  change read semantics for MIDI to match
  *                       OSS more closely; remove possible wakeup race
  *    28.10.1999   0.31  More waitqueue races fixed
+ *    08.01.2000   0.32  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    21.11.2000   0.34  Initialize dma buffers in poll, otherwise poll may return a bogus mask
+ *    12.12.2000   0.35  More dma buffer initializations, patch from
+ *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -858,7 +863,8 @@
 	VALIDATE_STATE(s);
 	if (cmd == SOUND_MIXER_PRIVATE1) {
 		/* enable/disable/query mixer preamp */
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != -1) {
 			s->mix.micpreamp = !!val;
 			wrcodec(s, 0x19, s->mix.micpreamp);
@@ -867,7 +873,8 @@
 	}
 	if (cmd == SOUND_MIXER_PRIVATE2) {
 		/* enable/disable/query use of linein as second lineout */
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != -1) {
 			spin_lock_irqsave(&s->lock, flags);
 			if (val)
@@ -881,7 +888,8 @@
 	}
 	if (cmd == SOUND_MIXER_PRIVATE3) {
 		/* enable/disable/query microphone impedance setting */
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != -1) {
 			spin_lock_irqsave(&s->lock, flags);
 			if (val)
@@ -957,12 +965,14 @@
 	switch (_IOC_NR(cmd)) {
 
 	case SOUND_MIXER_IMIX:
-		get_user_ret(s->mix.imix, (int *)arg, -EFAULT);
+		if (get_user(s->mix.imix, (int *)arg))
+			return -EFAULT;
 		set_recsrc(s, s->mix.recsrc);
 		return 0;
 
 	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		set_recsrc(s, val);
 		return 0;
 
@@ -970,7 +980,8 @@
 		i = _IOC_NR(cmd);
 		if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail)
 			return -EINVAL;
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		l = val & 0xff;
 		if (l > 100)
 			l = 100;
@@ -1354,6 +1365,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	int val, mapped, ret;
 
 	VALIDATE_STATE(s);
@@ -1388,7 +1400,8 @@
 		return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val >= 0) {
 			if (s->open_mode & (~file->f_mode) & (FMODE_READ|FMODE_WRITE))
 				return -EINVAL;
@@ -1407,7 +1420,8 @@
 		return put_user(DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), (int *)arg);
 		
         case SNDCTL_DSP_STEREO:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			stop_adc(s);
 			s->dma_adc.ready = 0;
@@ -1433,7 +1447,8 @@
 		return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 0) {
 			if (file->f_mode & FMODE_READ) {
 				stop_adc(s);
@@ -1464,7 +1479,8 @@
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
 		
 	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != AFMT_QUERY) {
 			if (file->f_mode & FMODE_READ) {
 				stop_adc(s);
@@ -1504,7 +1520,8 @@
 		return put_user(val, (int *)arg);
 		
 	case SNDCTL_DSP_SETTRIGGER:
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			if (val & PCM_ENABLE_INPUT) {
 				if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -1526,12 +1543,15 @@
 	case SNDCTL_DSP_GETOSPACE:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
-		if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac2(s)) != 0)
+		if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
 		abinfo.fragsize = s->dma_dac2.fragsize;
-                abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count;
+		count = s->dma_dac2.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac2.dmasize - count;
                 abinfo.fragstotal = s->dma_dac2.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1540,12 +1560,15 @@
 	case SNDCTL_DSP_GETISPACE:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
-		if (!(s->ctrl & CTRL_ADC_EN) && (val = prog_dmabuf_adc(s)) != 0)
+		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
 		abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1558,19 +1581,28 @@
         case SNDCTL_DSP_GETODELAY:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
+		if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
-                val = s->dma_dac2.count;
+                count = s->dma_dac2.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
+		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1580,10 +1612,15 @@
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
+		if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
                 cinfo.bytes = s->dma_dac2.total_bytes;
-                cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift;
+		count = s->dma_dac2.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac2.fragshift;
                 cinfo.ptr = s->dma_dac2.hwptr;
 		if (s->dma_dac2.mapped)
 			s->dma_dac2.count &= s->dma_dac2.fragsize-1;
@@ -1601,7 +1638,8 @@
 		return put_user(s->dma_adc.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			s->dma_adc.ossfragshift = val & 0xffff;
 			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1628,7 +1666,8 @@
 		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
 		    (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))
 			return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 1 && val != 2 && val != 4)
 			return -EINVAL;
 		if (file->f_mode & FMODE_READ)
@@ -1878,6 +1917,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	unsigned ctrl;
 	int val, ret;
 
@@ -1902,7 +1942,8 @@
 		return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val >= 0) {
 			stop_dac1(s);
 			s->dma_dac1.ready = 0;
@@ -1917,7 +1958,8 @@
 		return put_user(dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], (int *)arg);
 		
         case SNDCTL_DSP_STEREO:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		stop_dac1(s);
 		s->dma_dac1.ready = 0;
 		spin_lock_irqsave(&s->lock, flags);
@@ -1930,7 +1972,8 @@
 		return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 0) {
 			if (s->dma_dac1.mapped)
 				return -EINVAL;
@@ -1950,7 +1993,8 @@
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
 		
         case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != AFMT_QUERY) {
 			stop_dac1(s);
 			s->dma_dac1.ready = 0;
@@ -1971,7 +2015,8 @@
 		return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg);
 						
 	case SNDCTL_DSP_SETTRIGGER:
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val & PCM_ENABLE_OUTPUT) {
 			if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
 				return ret;
@@ -1981,12 +2026,15 @@
 		return 0;
 
 	case SNDCTL_DSP_GETOSPACE:
-		if (!(s->ctrl & CTRL_DAC1_EN) && (val = prog_dmabuf_dac1(s)) != 0)
+		if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
 		abinfo.fragsize = s->dma_dac1.fragsize;
-                abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count;
+		count = s->dma_dac1.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac1.dmasize - count;
                 abinfo.fragstotal = s->dma_dac1.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1997,19 +2045,26 @@
                 return 0;
 
         case SNDCTL_DSP_GETODELAY:
+		if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
-                val = s->dma_dac1.count;
+                count = s->dma_dac1.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETOPTR:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
+		if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
                 cinfo.bytes = s->dma_dac1.total_bytes;
-                cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift;
+		count = s->dma_dac1.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac1.fragshift;
                 cinfo.ptr = s->dma_dac1.hwptr;
 		if (s->dma_dac1.mapped)
 			s->dma_dac1.count &= s->dma_dac1.fragsize-1;
@@ -2022,7 +2077,8 @@
                 return put_user(s->dma_dac1.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		s->dma_dac1.ossfragshift = val & 0xffff;
 		s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff;
 		if (s->dma_dac1.ossfragshift < 4)
@@ -2036,7 +2092,8 @@
         case SNDCTL_DSP_SUBDIVIDE:
 		if (s->dma_dac1.subdivision)
 			return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 1 && val != 2 && val != 4)
 			return -EINVAL;
 		s->dma_dac1.subdivision = val;
@@ -2463,7 +2520,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.35 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
 		if (pcidev->base_address[0] == 0 || 
diff -urN linux-2.2.19-pre2/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- linux-2.2.19-pre2/drivers/sound/es1371.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/es1371.c	Mon Dec  3 20:53:37 2001
@@ -96,6 +96,12 @@
  *                       detect ES137x chip and derivatives.
  *    05.01.2000   0.22  Should now work with rev7 boards; patch by
  *                       Eric Lemar, elemar@cs.washington.edu
+ *    08.01.2000   0.23  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    01.03.2000   0.26  SPDIF patch by Mikael Bouillot <mikael.bouillot@bigfoot.com>
+ *    21.11.2000   0.27  Initialize dma buffers in poll, otherwise poll may return a bogus mask
+ *    12.12.2000   0.28  More dma buffer initializations, patch from
+ *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  */
 
 /*****************************************************************************/
@@ -1937,6 +1943,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	int val, mapped, ret;
 
 	VALIDATE_STATE(s);
@@ -1971,7 +1978,8 @@
 		return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val >= 0) {
 			if (file->f_mode & FMODE_READ) {
 				stop_adc(s);
@@ -1987,7 +1995,8 @@
 		return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg);
 
         case SNDCTL_DSP_STEREO:
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			stop_adc(s);
 			s->dma_adc.ready = 0;
@@ -2013,7 +2022,8 @@
 		return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 0) {
 			if (file->f_mode & FMODE_READ) {
 				stop_adc(s);
@@ -2044,7 +2054,8 @@
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
 		
 	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != AFMT_QUERY) {
 			if (file->f_mode & FMODE_READ) {
 				stop_adc(s);
@@ -2084,7 +2095,8 @@
 		return put_user(val, (int *)arg);
 		
 	case SNDCTL_DSP_SETTRIGGER:
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			if (val & PCM_ENABLE_INPUT) {
 				if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -2106,12 +2118,15 @@
 	case SNDCTL_DSP_GETOSPACE:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
-		if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac2(s)) != 0)
+		if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
 		abinfo.fragsize = s->dma_dac2.fragsize;
-                abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count;
+		count = s->dma_dac2.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac2.dmasize - count;
                 abinfo.fragstotal = s->dma_dac2.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -2120,12 +2135,15 @@
 	case SNDCTL_DSP_GETISPACE:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
-		if (!(s->ctrl & CTRL_ADC_EN) && (val = prog_dmabuf_adc(s)) != 0)
+		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
 		abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -2138,19 +2156,28 @@
         case SNDCTL_DSP_GETODELAY:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
+		if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
-                val = s->dma_dac2.count;
+                count = s->dma_dac2.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
+		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -2160,10 +2187,15 @@
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
+		if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
                 cinfo.bytes = s->dma_dac2.total_bytes;
-                cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift;
+		count = s->dma_dac2.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac2.fragshift;
                 cinfo.ptr = s->dma_dac2.hwptr;
 		if (s->dma_dac2.mapped)
 			s->dma_dac2.count &= s->dma_dac2.fragsize-1;
@@ -2181,7 +2213,8 @@
 		return put_user(s->dma_adc.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			s->dma_adc.ossfragshift = val & 0xffff;
 			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -2208,7 +2241,8 @@
 		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
 		    (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))
 			return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 1 && val != 2 && val != 4)
 			return -EINVAL;
 		if (file->f_mode & FMODE_READ)
@@ -2458,6 +2492,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	int val, ret;
 
 	VALIDATE_STATE(s);
@@ -2481,7 +2516,8 @@
 		return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val >= 0) {
 			stop_dac1(s);
 			s->dma_dac1.ready = 0;
@@ -2490,7 +2526,8 @@
 		return put_user(s->dac1rate, (int *)arg);
 
         case SNDCTL_DSP_STEREO:
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		stop_dac1(s);
 		s->dma_dac1.ready = 0;
 		spin_lock_irqsave(&s->lock, flags);
@@ -2503,7 +2540,8 @@
 		return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 0) {
 			stop_dac1(s);
 			s->dma_dac1.ready = 0;
@@ -2521,7 +2559,8 @@
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
 		
         case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != AFMT_QUERY) {
 			stop_dac1(s);
 			s->dma_dac1.ready = 0;
@@ -2542,7 +2581,8 @@
 		return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg);
 						
 	case SNDCTL_DSP_SETTRIGGER:
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val & PCM_ENABLE_OUTPUT) {
 			if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
 				return ret;
@@ -2552,12 +2592,15 @@
 		return 0;
 
 	case SNDCTL_DSP_GETOSPACE:
-		if (!(s->ctrl & CTRL_DAC1_EN) && (val = prog_dmabuf_dac1(s)) != 0)
+		if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
 		abinfo.fragsize = s->dma_dac1.fragsize;
-                abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count;
+		count = s->dma_dac1.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac1.dmasize - count;
                 abinfo.fragstotal = s->dma_dac1.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -2568,19 +2611,26 @@
                 return 0;
 
         case SNDCTL_DSP_GETODELAY:
+		if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
-                val = s->dma_dac1.count;
+                count = s->dma_dac1.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETOPTR:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
+		if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
                 cinfo.bytes = s->dma_dac1.total_bytes;
-                cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift;
+		count = s->dma_dac1.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac1.fragshift;
                 cinfo.ptr = s->dma_dac1.hwptr;
 		if (s->dma_dac1.mapped)
 			s->dma_dac1.count &= s->dma_dac1.fragsize-1;
@@ -2593,7 +2643,8 @@
                 return put_user(s->dma_dac1.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		s->dma_dac1.ossfragshift = val & 0xffff;
 		s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff;
 		if (s->dma_dac1.ossfragshift < 4)
@@ -2607,7 +2658,8 @@
         case SNDCTL_DSP_SUBDIVIDE:
 		if (s->dma_dac1.subdivision)
 			return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 1 && val != 2 && val != 4)
 			return -EINVAL;
 		s->dma_dac1.subdivision = val;
@@ -3261,7 +3313,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1371: version v0.28 time " __TIME__ " " __DATE__ "\n");
 	for (pcidev = pci_devices; pcidev && index < NR_DEVICE; pcidev = pcidev->next) {
 		if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
 			if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
diff -urN linux-2.2.19-pre2/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- linux-2.2.19-pre2/drivers/sound/esssolo1.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/esssolo1.c	Mon Dec  3 20:53:37 2001
@@ -63,7 +63,12 @@
  *    28.10.1999   0.10  More waitqueue races fixed
  *    09.12.1999   0.11  Work around stupid Alpha port issue (virt_to_bus(kmalloc(GFP_DMA)) > 16M)
  *                       Disabling recording on Alpha
- *
+ *    12.01.2000   0.12  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *                       Integrated (aka redid 8-)) APM support patch by Zach Brown
+ *    21.11.2000   0.16  Initialize dma buffers in poll, otherwise poll may return a bogus mask
+ *    12.12.2000   0.17  More dma buffer initializations, patch from
+ *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  */
 
 /*****************************************************************************/
@@ -1276,7 +1281,8 @@
 		return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val >= 0) {
 			stop_adc(s);
 			stop_dac(s);
@@ -1303,7 +1309,8 @@
 		return put_user(s->rate, (int *)arg);
 		
         case SNDCTL_DSP_STEREO:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		stop_adc(s);
 		stop_dac(s);
 		s->dma_adc.ready = s->dma_dac.ready = 0;
@@ -1313,7 +1320,8 @@
 		return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 0) {
 			stop_adc(s);
 			stop_dac(s);
@@ -1328,7 +1336,8 @@
                 return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
 
 	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != AFMT_QUERY) {
 			stop_adc(s);
 			stop_dac(s);
@@ -1354,7 +1363,8 @@
 		return put_user(val, (int *)arg);
 
 	case SNDCTL_DSP_SETTRIGGER:
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			if (val & PCM_ENABLE_INPUT) {
 				if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -1378,7 +1388,7 @@
 	case SNDCTL_DSP_GETOSPACE:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
-		if (!(s->ena & FMODE_WRITE) && (val = prog_dmabuf_dac(s)) != 0)
+		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
@@ -1395,7 +1405,7 @@
 	case SNDCTL_DSP_GETISPACE:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
-		if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0)
+		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
@@ -1413,6 +1423,8 @@
         case SNDCTL_DSP_GETODELAY:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
+		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
                 count = s->dma_dac.count;
@@ -1424,13 +1436,12 @@
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
+		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-		count = s->dma_dac.count;
-		if (count < 0)
-			count = 0;
-		cinfo.blocks = count >> s->dma_dac.fragshift;
+                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1440,10 +1451,15 @@
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
+		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
-                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac.fragshift;
                 cinfo.ptr = s->dma_dac.hwptr;
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize-1;
@@ -1467,7 +1483,8 @@
 		return put_user(s->dma_adc.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			s->dma_adc.ossfragshift = val & 0xffff;
 			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1494,7 +1511,8 @@
 		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
 		    (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
 			return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 1 && val != 2 && val != 4)
 			return -EINVAL;
 		if (file->f_mode & FMODE_READ)
@@ -2170,7 +2188,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "solo1: version v0.11 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "solo1: version v0.17 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
 		if (pcidev->base_address[0] == 0 ||
diff -urN linux-2.2.19-pre2/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- linux-2.2.19-pre2/drivers/sound/sonicvibes.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/sonicvibes.c	Mon Dec  3 20:53:37 2001
@@ -77,11 +77,15 @@
  *    24.08.1999   0.19  get rid of the dmaio kludge, replace with allocate_resource
  *    31.08.1999   0.20  add spin_lock_init
  *                       __initlocaldata to fix gcc 2.7.x problems
- *                       use new resource allocation to allocate DDMA IO space
  *                       replaced current->state = x with set_current_state(x)
  *    03.09.1999   0.21  change read semantics for MIDI to match
  *                       OSS more closely; remove possible wakeup race
  *    28.10.1999   0.22  More waitqueue races fixed
+ *    08.01.2000   0.25  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    21.11.2000   0.27  Initialize dma buffers in poll, otherwise poll may return a bogus mask
+ *    12.12.2000   0.28  More dma buffer initializations, patch from
+ *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  *
  */
 
@@ -1543,6 +1547,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	int val, mapped, ret;
 	unsigned char fmtm, fmtd;
 
@@ -1578,7 +1583,8 @@
 		return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val >= 0) {
 			if (file->f_mode & FMODE_READ) {
 				stop_adc(s);
@@ -1594,7 +1600,8 @@
 		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
 		
         case SNDCTL_DSP_STEREO:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		fmtd = 0;
 		fmtm = ~0;
 		if (file->f_mode & FMODE_READ) {
@@ -1617,7 +1624,8 @@
 		return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 0) {
 			fmtd = 0;
 			fmtm = ~0;
@@ -1646,7 +1654,8 @@
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
 		
 	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != AFMT_QUERY) {
 			fmtd = 0;
 			fmtm = ~0;
@@ -1683,7 +1692,8 @@
 		return put_user(val, (int *)arg);
 		
 	case SNDCTL_DSP_SETTRIGGER:
-		get_user_ret(val, (int *)arg, -EFAULT);
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			if (val & PCM_ENABLE_INPUT) {
 				if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
@@ -1705,12 +1715,15 @@
 	case SNDCTL_DSP_GETOSPACE:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
-		if (!(s->enable & SV_CENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0)
+		if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
 		abinfo.fragsize = s->dma_dac.fragsize;
-                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac.dmasize - count;
                 abinfo.fragstotal = s->dma_dac.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1719,12 +1732,15 @@
 	case SNDCTL_DSP_GETISPACE:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
-		if (!(s->enable & SV_CENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0)
+		if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)) != 0)
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
 		abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1737,19 +1753,28 @@
         case SNDCTL_DSP_GETODELAY:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
+		if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
-                val = s->dma_dac.count;
+                count = s->dma_dac.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
+		if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1759,10 +1784,15 @@
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
+		if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)
+			return val;
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
-                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac.fragshift;
                 cinfo.ptr = s->dma_dac.hwptr;
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize-1;
@@ -1780,7 +1810,8 @@
 		return put_user(s->dma_adc.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			s->dma_adc.ossfragshift = val & 0xffff;
 			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1807,7 +1838,8 @@
 		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
 		    (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
 			return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+			return -EFAULT;
 		if (val != 1 && val != 2 && val != 4)
 			return -EINVAL;
 		if (file->f_mode & FMODE_READ)
@@ -2432,7 +2464,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.22 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.28 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
diff -urN linux-2.2.19-pre2/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- linux-2.2.19-pre2/drivers/sound/sound_core.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/sound_core.c	Mon Dec  3 20:53:37 2001
@@ -63,7 +63,6 @@
 extern int init_solo1(void);
 extern int init_ymf7xxsb_module(void);
 extern int cs_probe(void);
-extern int init_emu10k1(void);
 extern int cs4281_probe(void);
 extern void init_vwsnd(void);
 extern int ymf_probe(void);
@@ -434,9 +433,6 @@
 #endif
 #ifdef CONFIG_SOUND_CS4281
 	cs4281_probe();
-#endif
-#ifdef CONFIG_SOUND_EMU10K1
-	init_emu10k1();
 #endif
 #ifdef CONFIG_SOUND_YMFPCI
 	ymf_probe();
diff -urN linux-2.2.19-pre2/drivers/sound/ymf_sb.c linux/drivers/sound/ymf_sb.c
--- linux-2.2.19-pre2/drivers/sound/ymf_sb.c	Mon Sep  4 10:39:22 2000
+++ linux/drivers/sound/ymf_sb.c	Wed Dec 31 16:00:00 1969
@@ -1,995 +0,0 @@
-/*
-  Legacy audio driver for YMF724, 740, 744, 754 series.
-  Copyright 2000 Daisuke Nagano <breeze.nagano@nifty.ne.jp>
-
-  Based on the VIA 82Cxxx driver by Jeff Garzik <jgarzik@pobox.com>
-
-  Distribued under the GNU PUBLIC LICENSE (GPL) Version 2.
-  See the "COPYING" file distributed with kernel source tree for more info.
-
-  -------------------------------------------------------------------------
-
-  It only supports SBPro compatible function of YMF7xx series s.t.
-    * 22.05kHz, 8-bit and stereo sample
-    * OPL3-compatible FM synthesizer
-    * MPU-401 compatible "external" MIDI interface
-
-  and AC'97 mixer of these cards.
-
-  -------------------------------------------------------------------------
-
-  Revision history
-
-   Tue May 14 19:00:00 2000   0.0.1
-   * initial release
-
-   Tue May 16 19:29:29 2000   0.0.2
-
-   * add a little delays for reset devices.
-   * fixed addressing bug.
-
-   Sun May 21 15:14:37 2000   0.0.3
-
-   * Add 'master_vol' module parameter to change 'PCM out Vol' of AC'97.
-   * remove native UART401 support. External MIDI port should be supported 
-     by sb_midi driver.
-   * add support for SPDIF OUT. Module parameter 'spdif_out' is now available.
-
-   Wed May 31 00:13:57 2000   0.0.4
-
-   * remove entries in Hwmcode.h. Now YMF744 / YMF754 sets instructions 
-     in 724hwmcode.h.
-   * fixed wrong legacy_io setting on YMF744/YMF754 .
-
-   Sat Jun  3 23:44:08 2000   0.0.5
-
-   * correct all return value -1 to appropriate -E* value.
-   * add pci_enable_device() for linux-2.3.x.
-
-   Sat Jun  7 00:17:32 2000   0.1.0
-
-   * Remove SBPro mixer support.
-   * Added AC'97 mixer support and remove option 'master_volume'.
-   * Correct all separated valuables into struct ymf_cards.
-
-   Mon Jun 12 21:36:50 2000   0.1.1
-
-   * Invalid dma setting fixed.
-     -- John A. Boyd Jr. <jaboydjr@netwalk.com>
-
-   * ymfsb only compiled as module: fixed
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/version.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#include "sound_config.h"
-#include "soundmodule.h"
-#include "sb.h"
-#include "724hwmcode.h"
-
-#include "ac97.h"
-
-#undef YMF_DEBUG
-
-/* ---------------------------------------------------------------------- */
-
-#ifndef SOUND_LOCK
-# define SOUND_LOCK do {} while (0)
-# define SOUND_LOCK_END do {} while (0)
-#endif
-
-#ifndef PCI_VENDOR_ID_YAMAHA
-# define PCI_VENDOR_ID_YAMAHA  0x1073
-#endif
-#ifndef PCI_DEVICE_ID_YMF724
-# define PCI_DEVICE_ID_YMF724  0x0004
-#endif
-#ifndef PCI_DEVICE_ID_YMF740
-# define PCI_DEVICE_ID_YMF740  0x000A
-#endif
-#ifndef PCI_DEVICE_ID_YMF740C
-# define PCI_DEVICE_ID_YMF740C 0x000C
-#endif
-#ifndef PCI_DEVICE_ID_YMF724F
-# define PCI_DEVICE_ID_YMF724F 0x000D
-#endif
-#ifndef PCI_DEVICE_ID_YMF744
-# define PCI_DEVICE_ID_YMF744  0x0010
-#endif
-#ifndef PCI_DEVICE_ID_YMF754
-# define PCI_DEVICE_ID_YMF754  0x0012
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-#define YMFSB_RESET_DELAY               5
-
-#define YMFSB_REGSIZE                   0x8000
-
-#define YMFSB_AC97TIMEOUT               2000
-
-#define	YMFSB_WORKBITTIMEOUT            250000
-
-#define	YMFSB_DSPLENGTH                 0x0080
-#define	YMFSB_CTRLLENGTH                0x3000
-
-#define YMFSB_PCIR_VENDORID             0x00
-#define YMFSB_PCIR_DEVICEID             0x02
-#define YMFSB_PCIR_CMD                  0x04
-#define YMFSB_PCIR_REVISIONID           0x08
-#define YMFSB_PCIR_BASEADDR             0x10
-#define YMFSB_PCIR_IRQ                  0x3c
-
-#define	YMFSB_PCIR_LEGCTRL              0x40
-#define	YMFSB_PCIR_ELEGCTRL             0x42
-#define	YMFSB_PCIR_DSXGCTRL             0x48
-#define YMFSB_PCIR_OPLADR               0x60
-#define YMFSB_PCIR_SBADR                0x62
-#define YMFSB_PCIR_MPUADR               0x64
-
-#define	YMFSB_INTFLAG                   0x0004
-#define	YMFSB_ACTIVITY                  0x0006
-#define	YMFSB_GLOBALCTRL                0x0008
-#define	YMFSB_ZVCTRL                    0x000A
-#define	YMFSB_TIMERCTRL                 0x0010
-#define	YMFSB_TIMERCOUNT                0x0012
-#define	YMFSB_SPDIFOUTCTRL              0x0018
-#define	YMFSB_SPDIFOUTSTATUS            0x001C
-#define	YMFSB_EEPROMCTRL                0x0020
-#define	YMFSB_SPDIFINCTRL               0x0034
-#define	YMFSB_SPDIFINSTATUS             0x0038
-#define	YMFSB_DSPPROGRAMDL              0x0048
-#define	YMFSB_DLCNTRL                   0x004C
-#define	YMFSB_GPIOININTFLAG             0x0050
-#define	YMFSB_GPIOININTENABLE           0x0052
-#define	YMFSB_GPIOINSTATUS              0x0054
-#define	YMFSB_GPIOOUTCTRL               0x0056
-#define	YMFSB_GPIOFUNCENABLE            0x0058
-#define	YMFSB_GPIOTYPECONFIG            0x005A
-#define	YMFSB_AC97CMDDATA               0x0060
-#define	YMFSB_AC97CMDADR                0x0062
-#define	YMFSB_PRISTATUSDATA             0x0064
-#define	YMFSB_PRISTATUSADR              0x0066
-#define	YMFSB_SECSTATUSDATA             0x0068
-#define	YMFSB_SECSTATUSADR              0x006A
-#define	YMFSB_SECCONFIG                 0x0070
-#define	YMFSB_LEGACYOUTVOL              0x0080
-#define	YMFSB_LEGACYOUTVOLL             0x0080
-#define	YMFSB_LEGACYOUTVOLR             0x0082
-#define	YMFSB_NATIVEDACOUTVOL           0x0084
-#define	YMFSB_NATIVEDACOUTVOLL          0x0084
-#define	YMFSB_NATIVEDACOUTVOLR          0x0086
-#define	YMFSB_SPDIFOUTVOL               0x0088
-#define	YMFSB_SPDIFOUTVOLL              0x0088
-#define	YMFSB_SPDIFOUTVOLR              0x008A
-#define	YMFSB_AC3OUTVOL                 0x008C
-#define	YMFSB_AC3OUTVOLL                0x008C
-#define	YMFSB_AC3OUTVOLR                0x008E
-#define	YMFSB_PRIADCOUTVOL              0x0090
-#define	YMFSB_PRIADCOUTVOLL             0x0090
-#define	YMFSB_PRIADCOUTVOLR             0x0092
-#define	YMFSB_LEGACYLOOPVOL             0x0094
-#define	YMFSB_LEGACYLOOPVOLL            0x0094
-#define	YMFSB_LEGACYLOOPVOLR            0x0096
-#define	YMFSB_NATIVEDACLOOPVOL          0x0098
-#define	YMFSB_NATIVEDACLOOPVOLL         0x0098
-#define	YMFSB_NATIVEDACLOOPVOLR         0x009A
-#define	YMFSB_SPDIFLOOPVOL              0x009C
-#define	YMFSB_SPDIFLOOPVOLL             0x009E
-#define	YMFSB_SPDIFLOOPVOLR             0x009E
-#define	YMFSB_AC3LOOPVOL                0x00A0
-#define	YMFSB_AC3LOOPVOLL               0x00A0
-#define	YMFSB_AC3LOOPVOLR               0x00A2
-#define	YMFSB_PRIADCLOOPVOL             0x00A4
-#define	YMFSB_PRIADCLOOPVOLL            0x00A4
-#define	YMFSB_PRIADCLOOPVOLR            0x00A6
-#define	YMFSB_NATIVEADCINVOL            0x00A8
-#define	YMFSB_NATIVEADCINVOLL           0x00A8
-#define	YMFSB_NATIVEADCINVOLR           0x00AA
-#define	YMFSB_NATIVEDACINVOL            0x00AC
-#define	YMFSB_NATIVEDACINVOLL           0x00AC
-#define	YMFSB_NATIVEDACINVOLR           0x00AE
-#define	YMFSB_BUF441OUTVOL              0x00B0
-#define	YMFSB_BUF441OUTVOLL             0x00B0
-#define	YMFSB_BUF441OUTVOLR             0x00B2
-#define	YMFSB_BUF441LOOPVOL             0x00B4
-#define	YMFSB_BUF441LOOPVOLL            0x00B4
-#define	YMFSB_BUF441LOOPVOLR            0x00B6
-#define	YMFSB_SPDIFOUTVOL2              0x00B8
-#define	YMFSB_SPDIFOUTVOL2L             0x00B8
-#define	YMFSB_SPDIFOUTVOL2R             0x00BA
-#define	YMFSB_SPDIFLOOPVOL2             0x00BC
-#define	YMFSB_SPDIFLOOPVOL2L            0x00BC
-#define	YMFSB_SPDIFLOOPVOL2R            0x00BE
-#define	YMFSB_ADCSLOTSR                 0x00C0
-#define	YMFSB_RECSLOTSR                 0x00C4
-#define	YMFSB_ADCFORMAT                 0x00C8
-#define	YMFSB_RECFORMAT                 0x00CC
-#define	YMFSB_P44SLOTSR                 0x00D0
-#define	YMFSB_STATUS                    0x0100
-#define	YMFSB_CTRLSELECT                0x0104
-#define	YMFSB_MODE                      0x0108
-#define	YMFSB_SAMPLECOUNT               0x010C
-#define	YMFSB_NUMOFSAMPLES              0x0110
-#define	YMFSB_CONFIG                    0x0114
-#define	YMFSB_PLAYCTRLSIZE              0x0140
-#define	YMFSB_RECCTRLSIZE               0x0144
-#define	YMFSB_EFFCTRLSIZE               0x0148
-#define	YMFSB_WORKSIZE                  0x014C
-#define	YMFSB_MAPOFREC                  0x0150
-#define	YMFSB_MAPOFEFFECT               0x0154
-#define	YMFSB_PLAYCTRLBASE              0x0158
-#define	YMFSB_RECCTRLBASE               0x015C
-#define	YMFSB_EFFCTRLBASE               0x0160
-#define	YMFSB_WORKBASE                  0x0164
-#define	YMFSB_DSPINSTRAM                0x1000
-#define	YMFSB_CTRLINSTRAM               0x4000
-
-
-/* ---------------------------------------------------------------------- */
-
-#define MAX_CARDS	4
-
-#define PFX		"ymf_sb: "
-
-#define YMFSB_VERSION	"0.1.1"
-#define YMFSB_CARD_NAME	"YMF7xx Legacy Audio driver " YMFSB_VERSION
-
-#define ymf7xxsb_probe_midi probe_sbmpu
-#define ymf7xxsb_attach_midi attach_sbmpu
-#define ymf7xxsb_unload_midi unload_sbmpu
-
-/* ---------------------------------------------------------------------- */
-
-static struct ymf_card {
-  int                  card;
-  unsigned short      *ymfbase;
-
-  struct address_info sb_data, opl3_data, mpu_data;
-
-  struct ac97_hwint   ac97_dev;
-  int                 mixer_oss_dev;
-} ymf_cards[MAX_CARDS];
-
-static unsigned int cards = 0;
-
-/* ---------------------------------------------------------------------- */
-
-#ifdef MODULE
-static int mpu_io     = 0;
-static int synth_io   = 0;
-static int io         = 0;
-static int dma        = 0;
-static int spdif_out  = 1;
-MODULE_PARM(mpu_io, "i");
-MODULE_PARM(synth_io, "i");
-MODULE_PARM(io,"i");
-MODULE_PARM(dma,"i");
-MODULE_PARM(spdif_out,"i");
-#else
-static int mpu_io     = 0x330;
-static int synth_io   = 0x388;
-static int io         = 0x220;
-static int dma        = 1;
-static int spdif_out  = 1;
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-static int readRegWord( struct ymf_card *card, int adr ) {
-
-	if (card->ymfbase==NULL) return 0;
-
-	return readw(card->ymfbase+adr/2);
-}
-
-static void writeRegWord( struct ymf_card *card, int adr, int val ) {
-
-	if (card->ymfbase==NULL) return;
-
-	writew((unsigned short)(val&0xffff), card->ymfbase + adr/2);
-
-	return;
-}
-
-static int readRegDWord( struct ymf_card *card, int adr ) {
-
-	if (card->ymfbase==NULL) return 0;
-
-	return (readl(card->ymfbase+adr/2));
-}
-
-static void writeRegDWord( struct ymf_card *card, int adr, int val ) {
-
-	if (card->ymfbase==NULL) return;
-
-	writel((unsigned int)(val&0xffffffff), card->ymfbase+adr/2);
-
-	return;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int checkPrimaryBusy( struct ymf_card *card )
-{
-	int timeout=0;
-
-	while ( timeout++ < YMFSB_AC97TIMEOUT )
-	{
-		if ( (readRegWord(card, YMFSB_PRISTATUSADR) & 0x8000) == 0x0000 )
-			return 0;
-	}
-	return -EBUSY;
-}
-
-static int checkCodec( struct ymf_card *card, struct pci_dev *pcidev )
-{
-	u8 tmp8;
-
-	pci_read_config_byte( pcidev, YMFSB_PCIR_DSXGCTRL, &tmp8 );
-	if ( tmp8 & 0x03 ) {
-		pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc);
-		mdelay(YMFSB_RESET_DELAY);
-		pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8|0x03);
-		mdelay(YMFSB_RESET_DELAY);
-		pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc);
-		mdelay(YMFSB_RESET_DELAY);
-	}
-
-	if ( checkPrimaryBusy( card ) ) return -EBUSY;
-
-	return 0;
-}
-
-static int setupLegacyIO( struct ymf_card *card, struct pci_dev *pcidev )
-{
-	int v;
-	int sbio=0, mpuio=0, oplio=0,dma=0;
-
-	switch(card->sb_data.io_base) {
-	case 0x220:
-		sbio = 0;
-		break;
-	case 0x240:
-		sbio = 1;
-		break;
-	case 0x260:
-		sbio = 2;
-		break;
-	case 0x280:
-		sbio = 3;
-		break;
-	default:
-		return -EINVAL;
-		break;
-	}
-#ifdef YMF_DEBUG
-	printk(PFX "set SBPro I/O at 0x%x\n",card->sb_data.io_base);
-#endif
-
-	switch(card->mpu_data.io_base) {
-	case 0x330:
-		mpuio = 0;
-		break;
-	case 0x300:
-		mpuio = 1;
-		break;
-	case 0x332:
-		mpuio = 2;
-		break;
-	case 0x334:
-		mpuio = 3;
-		break;
-	default:
-		mpuio = 0;
-		break;
-	}
-#ifdef YMF_DEBUG
-	printk(PFX "set MPU401 I/O at 0x%x\n",card->mpu_data.io_base);
-#endif
-
-	switch(card->opl3_data.io_base) {
-	case 0x388:
-		oplio = 0;
-		break;
-	case 0x398:
-		oplio = 1;
-		break;
-	case 0x3a0:
-		oplio = 2;
-		break;
-	case 0x3a8:
-		oplio = 3;
-		break;
-	default:
-		return -EINVAL;
-		break;
-	}
-#ifdef YMF_DEBUG
-	printk(PFX "set OPL3 I/O at 0x%x\n",card->opl3_data.io_base);
-#endif
-
-	dma = card->sb_data.dma;
-#ifdef YMF_DEBUG
-	printk(PFX "set DMA address at 0x%x\n",card->sb_data.dma);
-#endif
-
-	v = 0x0000 | ((dma&0x03)<<6) | 0x003f;
-	pci_write_config_word(pcidev, YMFSB_PCIR_LEGCTRL, v);
-#ifdef YMF_DEBUG
-	printk(PFX "LEGCTRL: 0x%x\n",v);
-#endif
-	switch( pcidev->device ) {
-	case PCI_DEVICE_ID_YMF724:
-	case PCI_DEVICE_ID_YMF740:
-	case PCI_DEVICE_ID_YMF724F:
-	case PCI_DEVICE_ID_YMF740C:
-		v = 0x8800 | ((mpuio<<4)&0x03) | ((sbio<<2)&0x03) | (oplio&0x03);
-		pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v);
-#ifdef YMF_DEBUG
-		printk(PFX "ELEGCTRL: 0x%x\n",v);
-#endif
-		break;
-
-	case PCI_DEVICE_ID_YMF744:
-	case PCI_DEVICE_ID_YMF754:
-		v = 0x8800;
-		pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v);
-		pci_write_config_word(pcidev, YMFSB_PCIR_OPLADR, card->opl3_data.io_base);
-		pci_write_config_word(pcidev, YMFSB_PCIR_SBADR,  card->sb_data.io_base);
-		pci_write_config_word(pcidev, YMFSB_PCIR_MPUADR, card->mpu_data.io_base);
-		break;
-
-	default:
-		printk(KERN_ERR PFX "Invalid device ID: %d\n",pcidev->device);
-		return -EINVAL;
-		break;
-	}
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-/* AC'97 stuff */
-static int ymfsb_readAC97Reg( struct ac97_hwint *dev, u8 reg )
-{
-	struct ymf_card *card = (struct ymf_card *)dev->driver_private;
-	unsigned long flags;
-	int ret;
-
-	if ( reg > 0x7f ) return -EINVAL;
-
-	save_flags(flags);
-	cli();
-	writeRegWord( card, YMFSB_AC97CMDADR, 0x8000 | reg );
-	if ( checkPrimaryBusy( card ) ) {
-		restore_flags(flags);
-		return -EBUSY;
-	}
-	ret = readRegWord( card, YMFSB_AC97CMDDATA );
-	restore_flags(flags);
-
-	return ret;
-}
-
-static int ymfsb_writeAC97Reg( struct ac97_hwint *dev, u8 reg, u16 value )
-{
-	struct ymf_card *card = (struct ymf_card *)dev->driver_private;
-	unsigned long flags;
-
-	if ( reg > 0x7f ) return -EINVAL;
-
-	save_flags(flags);
-	cli();
-	if ( checkPrimaryBusy( card ) ) {
-	  restore_flags(flags);
-	  return -EBUSY;
-	}
-
-	writeRegWord( card, YMFSB_AC97CMDADR, 0x0000 | reg );
-	writeRegWord( card, YMFSB_AC97CMDDATA, value );
-
-	restore_flags(flags);
-	return 0;
-}
-
-struct initialValues
-{
-    unsigned short port;
-    unsigned short value;
-};
-
-static struct initialValues ymfsb_ac97_initial_values[] =
-{
-    { AC97_RESET,             0x0000 },
-    { AC97_MASTER_VOL_STEREO, 0x0000 },
-    { AC97_HEADPHONE_VOL,     0x8000 },
-    { AC97_PCMOUT_VOL,        0x0606 },
-    { AC97_MASTER_VOL_MONO,   0x0000 },
-    { AC97_PCBEEP_VOL,        0x0000 },
-    { AC97_PHONE_VOL,         0x0008 },
-    { AC97_MIC_VOL,           0x8000 },
-    { AC97_LINEIN_VOL,        0x8808 },
-    { AC97_CD_VOL,            0x8808 },
-    { AC97_VIDEO_VOL,         0x8808 },
-    { AC97_AUX_VOL,           0x8808 },
-    { AC97_RECORD_SELECT,     0x0000 },
-    { AC97_RECORD_GAIN,       0x0B0B },
-    { AC97_GENERAL_PURPOSE,   0x0000 },
-    { 0xffff, 0xffff }
-};
-
-static int ymfsb_resetAC97( struct ac97_hwint *dev )
-{
-	int i;
-
-	for ( i=0 ; ymfsb_ac97_initial_values[i].port != 0xffff ; i++ )
-	{
-		ac97_put_register ( dev,
-				    ymfsb_ac97_initial_values[i].port,
-				    ymfsb_ac97_initial_values[i].value );
-	}
-
-	return 0;
-}
-
-static int ymfsb_ac97_mixer_ioctl( int dev, unsigned int cmd, caddr_t arg )
-{
-	int i;
-
-	for ( i=0 ; i < MAX_CARDS ; i++ )
-	{
-		if ( ymf_cards[i].mixer_oss_dev == dev ) break;
-	}
-
-	if ( i < MAX_CARDS )
-		return ac97_mixer_ioctl(&(ymf_cards[i].ac97_dev), cmd, arg);
-	else
-		return -ENODEV;
-}
-
-static struct mixer_operations ymfsb_ac97_mixer_operations = {
-	"YAMAHA",
-	"YAMAHA PCI",
-	ymfsb_ac97_mixer_ioctl
-};
-
-static struct ac97_mixer_value_list ymfsb_ac97_mixer_defaults[] = {
-    { SOUND_MIXER_VOLUME,  { { 85, 85 } } },
-    { SOUND_MIXER_SPEAKER, { { 100 } } },
-    { SOUND_MIXER_PCM,     { { 65, 65 } } },
-    { SOUND_MIXER_CD,      { { 65, 65 } } },
-    { -1,                  {  { 0,  0 } } }
-};
-
-/* ---------------------------------------------------------------------- */
-
-static void enableDSP( struct ymf_card *card )
-{
-	writeRegDWord( card, YMFSB_CONFIG, 0x00000001 );
-	return;
-}
-
-static void disableDSP( struct ymf_card *card )
-{
-	int val;
-	int i;
-
-	val = readRegDWord( card, YMFSB_CONFIG );
-	if ( val ) {
-		writeRegDWord( card, YMFSB_CONFIG, 0 );
-	}
-
-	i=0;
-	while( ++i < YMFSB_WORKBITTIMEOUT ) {
-		val = readRegDWord( card, YMFSB_STATUS );
-		if ( (val & 0x00000002) == 0x00000000 ) break;
-	}
-
-	return;
-}
-
-static int setupInstruction( struct ymf_card *card, struct pci_dev *pcidev )
-{
-	int i;
-	int val;
-
-	writeRegDWord( card, YMFSB_NATIVEDACOUTVOL, 0 ); /* mute dac */
-	disableDSP( card );
-
-	writeRegDWord( card, YMFSB_MODE, 0x00010000 );
-
-	/* DS-XG Software Reset */
-	writeRegDWord( card, YMFSB_MODE,         0x00000000 );
-	writeRegDWord( card, YMFSB_MAPOFREC,     0x00000000 );
-	writeRegDWord( card, YMFSB_MAPOFEFFECT,  0x00000000 );
-	writeRegDWord( card, YMFSB_PLAYCTRLBASE, 0x00000000 );
-	writeRegDWord( card, YMFSB_RECCTRLBASE,  0x00000000 );
-	writeRegDWord( card, YMFSB_EFFCTRLBASE,  0x00000000 );
-
-	val = readRegWord( card, YMFSB_GLOBALCTRL );
-	writeRegWord( card, YMFSB_GLOBALCTRL, (val&~0x0007) );
-
-	/* setup DSP instruction code */
-	for ( i=0 ; i<YMFSB_DSPLENGTH ; i+=4 ) {
-	  writeRegDWord( card, YMFSB_DSPINSTRAM+i, DspInst[i>>2] );
-	}
-
-	switch( pcidev->device ) {
-	case PCI_DEVICE_ID_YMF724:
-	case PCI_DEVICE_ID_YMF740:
-		/* setup Control instruction code */
-		for ( i=0 ; i<YMFSB_CTRLLENGTH ; i+=4 ) {
-			writeRegDWord( card, YMFSB_CTRLINSTRAM+i, CntrlInst[i>>2] );
-		}
-		break;
-
-	case PCI_DEVICE_ID_YMF724F:
-	case PCI_DEVICE_ID_YMF740C:
-	case PCI_DEVICE_ID_YMF744:
-	case PCI_DEVICE_ID_YMF754:
-		/* setup Control instruction code */
-	
-		for ( i=0 ; i<YMFSB_CTRLLENGTH ; i+=4 ) {
-			writeRegDWord( card, YMFSB_CTRLINSTRAM+i, CntrlInst1E[i>>2] );
-		}
-		break;
-
-	default:
-		return -ENXIO;
-	}
-
-	enableDSP( card );
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int __init ymf7xx_init( struct ymf_card *card, struct pci_dev *pcidev )
-{
-	unsigned short v;
-	int mixer;
-
-	/* Read hardware information */
-#ifdef YMF_DEBUG
-	unsigned int   dv;
-	pci_read_config_word(pcidev, YMFSB_PCIR_VENDORID, &v);
-	printk(KERN_INFO PFX "Vendor ID = 0x%x\n",v);
-	pci_read_config_word(pcidev, YMFSB_PCIR_DEVICEID, &v);
-	printk(KERN_INFO PFX "Device ID = 0x%x\n",v);
-	pci_read_config_word(pcidev, YMFSB_PCIR_REVISIONID, &v);
-	printk(KERN_INFO PFX "Revision ID = 0x%x\n",v&0xff);
-	pci_read_config_dword(pcidev, YMFSB_PCIR_BASEADDR, &dv);
-	printk(KERN_INFO PFX "Base address = 0x%x\n",dv);
-	pci_read_config_word(pcidev, YMFSB_PCIR_IRQ, &v);
-	printk(KERN_INFO PFX "IRQ line = 0x%x\n",v&0xff);
-#endif
-
-	/* enables memory space access / bus mastering */
-	pci_read_config_word(pcidev, YMFSB_PCIR_CMD, &v);
-	pci_write_config_word(pcidev, YMFSB_PCIR_CMD, v|0x06);
-
-	/* check codec */
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "check codec...\n");
-#endif
-	if (checkCodec(card, pcidev)) return -EBUSY;
-
-	/* setup legacy I/O */
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup legacy I/O...\n");
-#endif
-	if (setupLegacyIO(card, pcidev)) return -EBUSY;
-	
-	/* setup instruction code */	
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup instructions...\n");
-#endif
-	if (setupInstruction(card, pcidev)) return -EBUSY;
-
-	/* AC'97 setup */	
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup AC'97...\n");
-#endif
-	if ( ac97_init( &card->ac97_dev ) ) return -EBUSY;
-
-	mixer = sound_alloc_mixerdev();
-	if ( num_mixers >= MAX_MIXER_DEV ) return -EBUSY;
-	
-	mixer_devs[mixer] = &ymfsb_ac97_mixer_operations;
-	card->mixer_oss_dev = mixer;
-	ac97_set_values( &card->ac97_dev, ymfsb_ac97_mixer_defaults );
-
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup Legacy Volume...\n");
-#endif
-	/* Legacy Audio Output Volume L & R ch */
-	writeRegDWord( card, YMFSB_LEGACYOUTVOL, 0x3fff3fff );
-
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup SPDIF output control...\n");
-#endif
-	/* SPDIF Output control */
-	v = spdif_out != 0 ? 0x0001 : 0x0000;
-	writeRegWord( card, YMFSB_SPDIFOUTCTRL, v );
-	/* no copyright protection, 
-	   sample-rate converted,
-	   re-recorded software comercially available (the 1st generation),
-	   original */
-	writeRegWord( card, YMFSB_SPDIFOUTSTATUS, 0x9a04 );
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void __init ymf7xxsb_attach_sb(struct address_info *hw_config)
-{
-	hw_config->driver_use_1 |= SB_NO_MIXER;
-	if(!sb_dsp_init(hw_config))
-		hw_config->slots[0] = -1;
-}
-
-static int __init ymf7xxsb_probe_sb(struct address_info *hw_config)
-{
-	if (check_region(hw_config->io_base, 16))
-	{
-		printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
-		       hw_config->io_base);
-		return 0;
-	}
-	return sb_dsp_detect(hw_config, SB_PCI_YAMAHA, 0);
-}
-
-
-static void ymf7xxsb_unload_sb(struct address_info *hw_config, int unload_mpu)
-{
-	if(hw_config->slots[0]!=-1)
-		sb_dsp_unload(hw_config, unload_mpu);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int __init ymf7xxsb_install (struct pci_dev *pcidev)
-{
-	struct {
-		unsigned short deviceid;
-		char           *devicename;
-	} devicetable[] = 
-	{
-		{ PCI_DEVICE_ID_YMF724,  "YMF724A-E" },
-		{ PCI_DEVICE_ID_YMF724F, "YMF724F" },
-		{ PCI_DEVICE_ID_YMF740,  "YMF740A-B" },
-		{ PCI_DEVICE_ID_YMF740C, "YMF740C" },
-		{ PCI_DEVICE_ID_YMF744,  "YMF744" },
-		{ PCI_DEVICE_ID_YMF754,  "YMF754" },
-	};
-
-	char		*devicename = "unknown";
-	int		i;
-	unsigned long   iobase;
-	struct ymf_card *card;
-
-	if ( pcidev->irq == 0 ) return -ENODEV;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	if ( pci_enable_device(pcidev) ) {
-		printk (KERN_ERR PFX "cannot enable PCI device\n");
-		return -EIO;
-	}
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
-	iobase = pcidev->base_address[0]&PCI_BASE_ADDRESS_MEM_MASK;
-#else
-	iobase = pcidev->resource[0].start&PCI_BASE_ADDRESS_MEM_MASK;
-#endif
-	if ( iobase == 0x00000000 ) return -ENODEV;
-
-	for ( i=0 ; i<sizeof(devicetable) / sizeof(devicetable[0]); i++ )
-	{
-		if (devicetable[i].deviceid == pcidev->device)
-		{
-			devicename = devicetable[i].devicename;
-			break;
-		}
-	}
-
-	card = &ymf_cards[cards];
-
-	/* remap memory mapped I/O onto kernel virtual memory */
-	if ( (card->ymfbase = ioremap_nocache(iobase, YMFSB_REGSIZE)) == 0 )
-	{
-		printk(KERN_ERR PFX "ioremap (0x%lx) returns zero\n", iobase);
-		return -ENODEV;
-	}
-	printk(KERN_INFO PFX "found %s at 0x%lx\n", devicename, iobase);
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "remappling to 0x%p\n", card->ymfbase);
-#endif
-
-	memset (&card->sb_data,   0, sizeof (struct address_info));
-	memset (&card->opl3_data, 0, sizeof (struct address_info));
-	memset (&card->mpu_data,  0, sizeof (struct address_info));
-	memset (&card->ac97_dev,  0, sizeof (struct ac97_hwint));
-
-	card->card = cards;
-
-	card->sb_data.name   = YMFSB_CARD_NAME;
-	card->opl3_data.name = YMFSB_CARD_NAME;
-	card->mpu_data.name  = YMFSB_CARD_NAME;
-
-	card->sb_data.card_subtype = MDL_YMPCI;
-
-	if ( io == 0 ) io      = 0x220;
-	card->sb_data.io_base = io;
-	card->sb_data.irq     = pcidev->irq;
-	card->sb_data.dma     = dma;
-
-	if ( synth_io == 0 ) synth_io = 0x388;
-	card->opl3_data.io_base = synth_io;
-	card->opl3_data.irq     = -1;
-
-	if ( mpu_io == 0 ) mpu_io = 0x330;
-	card->mpu_data.io_base = mpu_io;
-	card->mpu_data.irq     = -1;
-
-	card->ac97_dev.reset_device   = ymfsb_resetAC97;
-	card->ac97_dev.read_reg       = ymfsb_readAC97Reg;
-	card->ac97_dev.write_reg      = ymfsb_writeAC97Reg;
-	card->ac97_dev.driver_private = (void *)card;
-
-	if ( ymf7xx_init(card, pcidev) ) {
-		printk (KERN_ERR PFX
-			"Cannot initialize %s, aborting\n",
-			devicename);
-		return -ENODEV;
-	}
-
-	/* regist legacy SoundBlaster Pro */
-	if (!ymf7xxsb_probe_sb(&card->sb_data)) {
-		printk (KERN_ERR PFX
-			"SB probe at 0x%X failed, aborting\n",
-			io);
-		return -ENODEV;
-	}
-	ymf7xxsb_attach_sb (&card->sb_data);
-
-	/* regist legacy MIDI */
-	if ( mpu_io > 0 && 0)
-	{
-		if (!ymf7xxsb_probe_midi (&card->mpu_data)) {
-			printk (KERN_ERR PFX
-				"MIDI probe @ 0x%X failed, aborting\n",
-				mpu_io);
-			ymf7xxsb_unload_sb (&card->sb_data, 0);
-			return -ENODEV;
-		}
-		ymf7xxsb_attach_midi (&card->mpu_data);
-	}
-
-	/* regist legacy OPL3 */
-
-	cards++;	
-	return 0;
-}
-
-static int __init probe_ymf7xxsb (void)
-{
-	struct pci_dev *pcidev = NULL;
-	int i;
-
-	for (i=0 ; i<MAX_CARDS ; i++ )
-		ymf_cards[i].ymfbase = NULL;
-
-	while ( pcidev == NULL && (
-	       (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-					  PCI_DEVICE_ID_YMF724, pcidev)) ||
-	       (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-					  PCI_DEVICE_ID_YMF724F,pcidev)) ||
-	       (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-					  PCI_DEVICE_ID_YMF740, pcidev)) ||
-	       (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-					  PCI_DEVICE_ID_YMF740C,pcidev)) ||
-	       (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-					  PCI_DEVICE_ID_YMF744, pcidev)) ||
-	       (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-					  PCI_DEVICE_ID_YMF754, pcidev)))) {
-		  if (ymf7xxsb_install (pcidev)) {
-			  printk (KERN_ERR PFX "audio init failed\n");
-			  return -ENODEV;
-		  }
-
-		  if (cards == MAX_CARDS) {
-		  	  printk (KERN_DEBUG PFX "maximum number of cards reached\n");
-			  break;
-		  }
-	}
-
-	return 0;
-}
-
-static void free_iomaps( void )
-{
-	int i;
-
-	for ( i=0 ; i<MAX_CARDS ; i++ ) {
-		if ( ymf_cards[i].ymfbase!=NULL )
-			iounmap(ymf_cards[i].ymfbase);
-	}
-
-	return;
-}
-
-int __init init_ymf7xxsb_module(void)
-{
-	if (!pci_present ()) {
-		printk (KERN_DEBUG PFX "PCI not present, exiting\n");
-		return -ENODEV;
-	}
-
-	if (probe_ymf7xxsb()) {
-		printk(KERN_ERR PFX "probe failed, aborting\n");
-		/* XXX unload cards registered so far, if any */
-		free_iomaps();
-		return -ENODEV;
-	}
-
-	if (cards == 0) {
-		printk(KERN_DEBUG PFX "No chips found, aborting\n");
-		free_iomaps();
-		return -ENODEV;
-	}
-
-	printk (KERN_INFO PFX YMFSB_CARD_NAME " loaded\n");
-	
-	/*
-	 *	Binds us to the sound subsystem	
-	 */
-	SOUND_LOCK;
-	return 0;
-}
-
-static void cleanup_ymf7xxsb_module(void)
-{
-	int i;
-	
-	for (i = 0; i < cards; i++) {
-		ymf7xxsb_unload_sb (&(ymf_cards[i].sb_data), 0);
-		ymf7xxsb_unload_midi (&(ymf_cards[i].mpu_data));
-		if ( ymf_cards[i].mixer_oss_dev >= 0 ) 
-			sound_unload_mixerdev( ymf_cards[i].mixer_oss_dev );
-	}
-
-	free_iomaps();
-
-	/*
-	 *	Final clean up with the sound layer
-	 */
-	SOUND_LOCK_END;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Daisuke Nagano, breeze.nagano@nifty.ne.jp");
-MODULE_DESCRIPTION("YMF7xx Legacy Audio Driver");
-
-int init_module(void)
-{
-	return init_ymf7xxsb_module();
-}
-
-void cleanup_module(void)
-{
-	cleanup_ymf7xxsb_module();
-}
-
-#endif
diff -urN linux-2.2.19-pre2/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c
--- linux-2.2.19-pre2/drivers/sound/ymfpci.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/ymfpci.c	Mon Dec  3 20:53:37 2001
@@ -34,6 +34,8 @@
  *      ? underused structure members
  */
 
+#define YMFPCI_HAVE_MIDI_SUPPORT
+
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
@@ -46,6 +48,10 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+# include "sound_config.h"
+#endif
+
 #include "ymfpci.h"
 
 #define snd_magic_cast(t, p, err)	((t *)(p))
@@ -1870,6 +1876,90 @@
 	return -ENOTTY;
 }
 
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+/* MIDI stuff */
+
+/* */
+
+static int ymfpci_setup_legacy( ymfpci_t *codec, struct pci_dev *pcidev )
+{
+	int v;
+	int mpuio=-1, oplio=-1;
+
+	switch(codec->iomidi) {
+	case 0x330:
+		mpuio = 0;
+		break;
+	case 0x300:
+		mpuio = 1;
+		break;
+	case 0x332:
+		mpuio = 2;
+		break;
+	case 0x334:
+		mpuio = 3;
+		break;
+	default:
+		break;
+	}
+
+	switch(codec->iosynth) {
+	case 0x388:
+		oplio = 0;
+		break;
+	case 0x398:
+		oplio = 1;
+		break;
+	case 0x3a0:
+		oplio = 2;
+		break;
+	case 0x3a8:
+		oplio = 3;
+		break;
+	default:
+		break;
+	}
+
+	if ( mpuio >= 0 || oplio >= 0 ) {
+		v = 0x003e;
+		pci_write_config_word(pcidev, PCIR_LEGCTRL, v);
+	
+		switch( pcidev->device ) {
+		case PCI_DEVICE_ID_YAMAHA_724:
+		case PCI_DEVICE_ID_YAMAHA_740:
+		case PCI_DEVICE_ID_YAMAHA_724F:
+		case PCI_DEVICE_ID_YAMAHA_740C:
+			v = 0x8800;
+			if ( mpuio >= 0 ) { v|= (mpuio<<4)&0x03; }
+			if ( oplio >= 0 ) { v|= (oplio&0x03); }
+			pci_write_config_word(pcidev, PCIR_ELEGCTRL, v);
+			break;
+
+		case PCI_DEVICE_ID_YAMAHA_744:
+		case PCI_DEVICE_ID_YAMAHA_754:
+			v = 0x8800;
+			pci_write_config_word(pcidev, PCIR_ELEGCTRL, v);
+			if ( mpuio >= 0 ) {
+				pci_write_config_word(pcidev, PCIR_OPLADR, codec->iosynth);
+			}
+			if ( oplio >= 0 ) {
+				pci_write_config_word(pcidev, PCIR_MPUADR, codec->iomidi);
+			}
+		break;
+
+		default:
+			printk(KERN_ERR "ymfpci: Invalid device ID: %d\n",pcidev->device);
+			return -EINVAL;
+			break;
+		}
+	}
+
+	return 0;
+}
+#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+
+/* */
+
 static int ymf_open(struct inode *inode, struct file *file)
 {
 	ymfpci_t *unit;
@@ -1895,7 +1985,11 @@
 
 	/* XXX Semaphore here! */
 	for (unit = ymf_devs; unit != NULL; unit = unit->next) {
+#if 0
 		if (unit->inst == instance) break;
+#else
+		if (!((unit->dev_audio ^ minor) & ~0x0f)) break;
+#endif
 	}
 	if (unit == NULL) return -ENODEV;
 
@@ -2234,6 +2328,20 @@
 	return 0;
 }
 
+/* */
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+# ifdef MODULE
+static int mpu_io     = 0;
+static int synth_io   = 0;
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM(synth_io, "i");
+# else
+static int mpu_io     = 0x330;
+static int synth_io   = 0x388;
+# endif
+#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+/* */
+
 static int /* __init */
 ymf_install(struct pci_dev *pcidev, int instance, int devx)
 {
@@ -2268,6 +2376,15 @@
 		return -ENODEV;
 	}
 
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+	codec->iomidi = mpu_io;
+	codec->iosynth = synth_io;
+	if (ymfpci_setup_legacy(codec, pcidev) < 0) {
+		ymfpci_free(codec);
+		return -ENODEV;
+	}
+#endif
+
 	ymfpci_download_image(codec);
 
 	udelay(100); /* seems we need some delay after downloading image.. */
@@ -2304,6 +2421,28 @@
 		return err;
 	}
 
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+	memset (&codec->opl3_data, 0, sizeof (struct address_info));
+	memset (&codec->mpu_data,  0, sizeof (struct address_info));
+
+	codec->opl3_data.name = "ymfpci";
+	codec->mpu_data.name  = "ymfpci";
+
+	codec->opl3_data.io_base = codec->iosynth;
+	codec->opl3_data.irq     = -1;
+
+	codec->mpu_data.io_base  = codec->iomidi;
+	codec->mpu_data.irq      = -1;
+
+	if ( mpu_io > 0 )
+	{
+		if ( probe_uart401(&codec->mpu_data) ) {
+			attach_uart401(&codec->mpu_data);
+		}
+	}
+
+#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+
 	codec->next = ymf_devs;
 	ymf_devs = codec;
 
@@ -2339,6 +2478,11 @@
 		unregister_sound_mixer(codec->ac97_codec[0]->dev_mixer);
 		kfree(codec->ac97_codec[0]);
 	}
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+	if (codec->iomidi) {
+		unload_uart401(&(codec->mpu_data));
+	}
+#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
 	kfree(codec);
 }
 
diff -urN linux-2.2.19-pre2/drivers/sound/ymfpci.h linux/drivers/sound/ymfpci.h
--- linux-2.2.19-pre2/drivers/sound/ymfpci.h	Sun Dec 10 16:49:43 2000
+++ linux/drivers/sound/ymfpci.h	Mon Dec  3 20:53:37 2001
@@ -131,7 +131,19 @@
 #define YDSXG_AC97READCMD		0x8000
 #define YDSXG_AC97WRITECMD		0x0000
 
+#define PCIR_VENDORID			0x00
+#define PCIR_DEVICEID			0x02
+#define PCIR_CMD			0x04
+#define PCIR_REVISIONID			0x08
+#define PCIR_BASEADDR			0x10
+#define PCIR_IRQ			0x3c
+
+#define PCIR_LEGCTRL			0x40
+#define PCIR_ELEGCTRL			0x42
 #define PCIR_DSXGCTRL			0x48
+#define PCIR_OPLADR			0x60
+#define PCIR_SBADR			0x62
+#define PCIR_MPUADR			0x64
 
 #define YDSXG_DSPLENGTH			0x0080
 #define YDSXG_CTRLLENGTH		0x3000
@@ -280,6 +292,10 @@
 	struct pci_dev *pci;
 	int irq;
 	int inst;		/* Unit number (instance) */
+
+        /* legacy hardware resources */
+	unsigned int iosynth, iomidi;
+	struct address_info opl3_data, mpu_data;
 
 	spinlock_t reg_lock;
 	spinlock_t voice_lock;
diff -urN linux-2.2.19-pre2/drivers/usb/Config.in linux/drivers/usb/Config.in
--- linux-2.2.19-pre2/drivers/usb/Config.in	Sun Dec 10 16:49:43 2000
+++ linux/drivers/usb/Config.in	Mon Dec  3 20:53:37 2001
@@ -50,6 +50,7 @@
          fi
          dep_tristate '    USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL
          dep_tristate '    USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL
+         dep_tristate '    USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL
       fi
       bool '    USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG $CONFIG_USB_SERIAL
    fi
diff -urN linux-2.2.19-pre2/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
--- linux-2.2.19-pre2/drivers/usb/dabusb.c	Sun Dec 10 16:49:43 2000
+++ linux/drivers/usb/dabusb.c	Mon Dec  3 20:53:37 2001
@@ -173,8 +173,8 @@
 
 	// process if URB was not killed
 	if (purb->status != -ENOENT) {
-		unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
-		int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
+		unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
+		int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
 		for (i = 0; i < purb->number_of_packets; i++)
 			if (!purb->iso_frame_desc[i].status) {
 				len = purb->iso_frame_desc[i].actual_length;
@@ -455,6 +455,8 @@
 			dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
 
 			end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
+
+			end->purb->dev=s->usbdev;
 
 			ret = usb_submit_urb (end->purb);
 			if (ret) {
diff -urN linux-2.2.19-pre2/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile
--- linux-2.2.19-pre2/drivers/usb/serial/Makefile	Sun Dec 10 16:49:43 2000
+++ linux/drivers/usb/serial/Makefile	Mon Dec  3 20:53:37 2001
@@ -23,6 +23,7 @@
 obj-$(CONFIG_USB_SERIAL_OMNINET)		+= omninet.o
 obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT)	+= digi_acceleport.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)			+= belkin_sa.o
+obj-$(CONFIG_USB_SERIAL_EMPEG)			+= empeg.o
  
 # Objects that export symbols.
 export-objs	:= usbserial.o
diff -urN linux-2.2.19-pre2/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c
--- linux-2.2.19-pre2/drivers/usb/serial/empeg.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/empeg.c	Mon Dec  3 20:53:37 2001
@@ -0,0 +1,609 @@
+/*
+ * USB Empeg empeg-car player driver
+ *
+ *	Copyright (C) 2000
+ *	    Gary Brubaker (xavyer@ix.netcom.com)
+ *
+ *	Copyright (C) 1999, 2000
+ *	    Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License, as published by
+ *	the Free Software Foundation, version 2.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ * (11/13/2000) gb
+ *	Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open()
+ *	(It only needs to be set once - Doh!)
+ * 
+ * (11/11/2000) gb
+ *	Updated to work with id_table structure.
+ * 
+ * (11/04/2000) gb
+ *	Forked this from visor.c, and hacked it up to work with an
+ *	Empeg ltd. empeg-car player.  Constructive criticism welcomed.
+ *	I would like to say, 'Thank You' to Greg Kroah-Hartman for the
+ *	use of his code, and for his guidance, advice and patience. :)
+ *	A 'Thank You' is in order for John Ripley of Empeg ltd for his
+ *	advice, and patience too.
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#ifdef CONFIG_USB_SERIAL_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb-serial.h"
+
+#define EMPEG_VENDOR_ID                 0x084f
+#define EMPEG_PRODUCT_ID                0x0001
+
+#define MIN(a,b)		(((a)<(b))?(a):(b))
+
+/* function prototypes for an empeg-car player */
+static int  empeg_open		(struct usb_serial_port *port, struct file *filp);
+static void empeg_close		(struct usb_serial_port *port, struct file *filp);
+static int  empeg_write		(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static void empeg_throttle	(struct usb_serial_port *port);
+static void empeg_unthrottle	(struct usb_serial_port *port);
+static int  empeg_startup	(struct usb_serial *serial);
+static void empeg_shutdown	(struct usb_serial *serial);
+static int  empeg_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+static void empeg_set_termios	(struct usb_serial_port *port, struct termios *old_termios);
+static void empeg_write_bulk_callback	(struct urb *urb);
+static void empeg_read_bulk_callback	(struct urb *urb);
+
+static __u16	empeg_vendor_id		= EMPEG_VENDOR_ID;
+static __u16	empeg_product_id	= EMPEG_PRODUCT_ID;
+struct usb_serial_device_type empeg_device = {
+	name:			"Empeg",
+	idVendor:		&empeg_vendor_id,
+	idProduct:		&empeg_product_id,
+	needs_interrupt_in:	MUST_HAVE_NOT,	/* must not have an interrupt in endpoint */
+	needs_bulk_in:		MUST_HAVE,	/* must have a bulk in endpoint */
+	needs_bulk_out:		MUST_HAVE,	/* must have a bulk out endpoint */
+	num_interrupt_in:	0,
+	num_bulk_in:		1,
+	num_bulk_out:		1,
+	num_ports:		1,
+	open:			empeg_open,
+	close:			empeg_close,
+	throttle:		empeg_throttle,
+	unthrottle:		empeg_unthrottle,
+	startup:		empeg_startup,
+	shutdown:		empeg_shutdown,
+	ioctl:			empeg_ioctl,
+	set_termios:		empeg_set_termios,
+	write:			empeg_write,
+	write_bulk_callback:	empeg_write_bulk_callback,
+	read_bulk_callback:	empeg_read_bulk_callback,
+};
+
+#define NUM_URBS			16
+#define URB_TRANSFER_BUFFER_SIZE	4096
+
+static struct urb	*write_urb_pool[NUM_URBS];
+static spinlock_t	write_urb_pool_lock;
+static int		bytes_in;
+static int		bytes_out;
+
+/******************************************************************************
+ * Empeg specific driver functions
+ ******************************************************************************/
+static int empeg_open (struct usb_serial_port *port, struct file *filp)
+{
+	unsigned long flags;
+	int result;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return -ENODEV;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	++port->open_count;
+	MOD_INC_USE_COUNT;
+
+	/* gb - 2000/11/05
+	 *
+	 * personally, I think these termios should be set in
+	 * empeg_startup(), but it appears doing so leads to one
+	 * of those chicken/egg problems. :)
+	 *
+	 */
+	port->tty->termios->c_iflag
+		&= ~(IGNBRK
+		| BRKINT
+		| PARMRK
+		| ISTRIP
+		| INLCR
+		| IGNCR
+		| ICRNL
+		| IXON);
+
+	port->tty->termios->c_oflag
+		&= ~OPOST;
+
+	port->tty->termios->c_lflag
+		&= ~(ECHO
+		| ECHONL
+		| ICANON
+		| ISIG
+		| IEXTEN);
+
+	port->tty->termios->c_cflag
+		&= ~(CSIZE
+		| PARENB);
+
+	port->tty->termios->c_cflag
+		|= CS8;
+
+	/* gb - 2000/11/05
+	 *
+	 * force low_latency on
+	 *
+	 * The tty_flip_buffer_push()'s in empeg_read_bulk_callback() will actually
+	 * force the data through if low_latency is set.  Otherwise the pushes are
+	 * scheduled; this is bad as it opens up the possibility of dropping bytes
+	 * on the floor.  We are trying to sustain high data transfer rates; and
+	 * don't want to drop bytes on the floor.
+	 * Moral: use low_latency - drop no bytes - life is good. :)
+	 *
+	 */
+	port->tty->low_latency = 1;
+
+	if (!port->active) {
+		port->active = 1;
+		bytes_in = 0;
+		bytes_out = 0;
+
+		/* Start reading from the device */
+		port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+
+		result = usb_submit_urb(port->read_urb);
+
+		if (result)
+			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+
+	}
+
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
+	return 0;
+}
+
+
+static void empeg_close (struct usb_serial_port *port, struct file * filp)
+{
+	struct usb_serial *serial;
+	unsigned char *transfer_buffer;
+	unsigned long flags;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	serial = get_usb_serial (port, __FUNCTION__);
+	if (!serial)
+		return;
+
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	--port->open_count;
+	MOD_DEC_USE_COUNT;
+
+	if (port->open_count <= 0) {
+		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
+
+		if (!transfer_buffer) {
+			err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
+		} else {
+			kfree (transfer_buffer);
+		}
+
+		/* shutdown our bulk read */
+		usb_unlink_urb (port->read_urb);
+		port->active = 0;
+		port->open_count = 0;
+	}
+
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
+	/* Uncomment the following line if you want to see some statistics in your syslog */
+	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
+
+}
+
+
+static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = port->serial;
+	struct urb *urb;
+	const unsigned char *current_position = buf;
+	unsigned long flags;
+	int status;
+	int i;
+	int bytes_sent = 0;
+	int transfer_size;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf);
+
+	while (count > 0) {
+
+		/* try to find a free urb in our list of them */
+		urb = NULL;
+
+		spin_lock_irqsave (&write_urb_pool_lock, flags);
+
+		for (i = 0; i < NUM_URBS; ++i) {
+			if (write_urb_pool[i]->status != -EINPROGRESS) {
+				urb = write_urb_pool[i];
+				break;
+			}
+		}
+
+		spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+
+		if (urb == NULL) {
+			dbg (__FUNCTION__ " - no more free urbs");
+			goto exit;
+		}
+
+		if (urb->transfer_buffer == NULL) {
+			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+			if (urb->transfer_buffer == NULL) {
+				err(__FUNCTION__" no more kernel memory...");
+				goto exit;
+			}
+		}
+
+		transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE);
+
+		if (from_user) {
+			copy_from_user (urb->transfer_buffer, current_position, transfer_size);
+		} else {
+			memcpy (urb->transfer_buffer, current_position, transfer_size);
+		}
+
+		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+		/* build up our urb */
+		FILL_BULK_URB (
+			urb,
+			serial->dev,
+			usb_sndbulkpipe(serial->dev,
+				port->bulk_out_endpointAddress), 
+			urb->transfer_buffer,
+			transfer_size,
+			empeg_write_bulk_callback,
+			port);
+
+		urb->transfer_flags |= USB_QUEUE_BULK;
+
+		/* send it down the pipe */
+		status = usb_submit_urb(urb);
+		if (status)
+			dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
+
+		current_position += transfer_size;
+		bytes_sent += transfer_size;
+		count -= transfer_size;
+		bytes_out += transfer_size;
+
+	}
+
+exit:
+	return bytes_sent;
+
+} 
+
+
+static void empeg_write_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	if (urb->status) {
+		dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+		return;
+	}
+
+	queue_task(&port->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+
+	return;
+
+}
+
+
+static void empeg_read_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+	struct tty_struct *tty;
+	unsigned char *data = urb->transfer_buffer;
+	int i;
+	int result;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	if (!serial) {
+		dbg(__FUNCTION__ " - bad serial pointer, exiting");
+		return;
+	}
+
+	if (urb->status) {
+		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+		return;
+	}
+
+	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+
+	tty = port->tty;
+
+	if (urb->actual_length) {
+		for (i = 0; i < urb->actual_length ; ++i) {
+			/* gb - 2000/11/13
+			 * If we insert too many characters we'll overflow the buffer.
+			 * This means we'll lose bytes - Decidedly bad.
+			 */
+			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(tty);
+				}
+			/* gb - 2000/11/13
+			 * This doesn't push the data through unless tty->low_latency is set.
+			 */
+			tty_insert_flip_char(tty, data[i], 0);
+		}
+		/* gb - 2000/11/13
+		 * Goes straight through instead of scheduling - if tty->low_latency is set.
+		 */
+		tty_flip_buffer_push(tty);
+		bytes_in += urb->actual_length;
+	}
+
+	/* Continue trying to always read  */
+	port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+	result = usb_submit_urb(port->read_urb);
+
+	if (result)
+		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+
+	return;
+
+}
+
+
+static void empeg_throttle (struct usb_serial_port *port)
+{
+	unsigned long flags;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	usb_unlink_urb (port->read_urb);
+
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
+	return;
+
+}
+
+
+static void empeg_unthrottle (struct usb_serial_port *port)
+{
+	unsigned long flags;
+	int result;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	port->read_urb->dev = port->serial->dev;
+
+	result = usb_submit_urb(port->read_urb);
+
+	if (result)
+		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
+	return;
+
+}
+
+
+static int  empeg_startup (struct usb_serial *serial)
+{
+
+	dbg(__FUNCTION__);
+
+	dbg(__FUNCTION__ " - Set config to 1");
+	usb_set_configuration (serial->dev, 1);
+
+	/* continue on with initialization */
+	return 0;
+
+}
+
+
+static void empeg_shutdown (struct usb_serial *serial)
+{
+	int i;
+
+	dbg (__FUNCTION__);
+
+	/* stop reads and writes on all ports */
+	for (i=0; i < serial->num_ports; ++i) {
+		while (serial->port[i].open_count > 0) {
+			empeg_close (&serial->port[i], NULL);
+		}
+	}
+
+}
+
+
+static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
+
+	return -ENOIOCTLCMD;
+}
+
+
+/* This function is all nice and good, but we don't change anything based on it :) */
+static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+{
+	unsigned int cflag = port->tty->termios->c_cflag;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	/* check that they really want us to change something */
+	if (old_termios) {
+		if ((cflag == old_termios->c_cflag) &&
+		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
+			dbg(__FUNCTION__ " - nothing to change...");
+			return;
+		}
+	}
+
+	if ((!port->tty) || (!port->tty->termios)) {
+		dbg(__FUNCTION__" - no tty structures");
+		return;
+	}
+
+	/* get the byte size */
+	switch (cflag & CSIZE) {
+		case CS5:	dbg(__FUNCTION__ " - data bits = 5");   break;
+		case CS6:	dbg(__FUNCTION__ " - data bits = 6");   break;
+		case CS7:	dbg(__FUNCTION__ " - data bits = 7");   break;
+		default:
+		case CS8:	dbg(__FUNCTION__ " - data bits = 8");   break;
+	}
+
+	/* determine the parity */
+	if (cflag & PARENB)
+		if (cflag & PARODD)
+			dbg(__FUNCTION__ " - parity = odd");
+		else
+			dbg(__FUNCTION__ " - parity = even");
+	else
+		dbg(__FUNCTION__ " - parity = none");
+
+	/* figure out the stop bits requested */
+	if (cflag & CSTOPB)
+		dbg(__FUNCTION__ " - stop bits = 2");
+	else
+		dbg(__FUNCTION__ " - stop bits = 1");
+
+	/* figure out the flow control settings */
+	if (cflag & CRTSCTS)
+		dbg(__FUNCTION__ " - RTS/CTS is enabled");
+	else
+		dbg(__FUNCTION__ " - RTS/CTS is disabled");
+
+	/* determine software flow control */
+	if (I_IXOFF(port->tty))
+		dbg(__FUNCTION__ " - XON/XOFF is enabled, XON = %2x, XOFF = %2x", START_CHAR(port->tty), STOP_CHAR(port->tty));
+	else
+		dbg(__FUNCTION__ " - XON/XOFF is disabled");
+
+	/* get the baud rate wanted */
+	dbg(__FUNCTION__ " - baud rate = %d", tty_get_baud_rate(port->tty));
+
+	return;
+
+}
+
+
+static int __init empeg_init (void)
+{
+	struct urb *urb;
+	int i;
+
+	usb_serial_register (&empeg_device);
+
+	/* create our write urb pool and transfer buffers */ 
+	spin_lock_init (&write_urb_pool_lock);
+	for (i = 0; i < NUM_URBS; ++i) {
+		urb = usb_alloc_urb(0);
+		write_urb_pool[i] = urb;
+		if (urb == NULL) {
+			err("No more urbs???");
+			continue;
+		}
+
+		urb->transfer_buffer = NULL;
+		urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+		if (!urb->transfer_buffer) {
+			err (__FUNCTION__ " - out of memory for urb buffers.");
+			continue;
+		}
+	}
+
+	return 0;
+
+}
+
+
+static void __exit empeg_exit (void)
+{
+	int i;
+	unsigned long flags;
+
+	usb_serial_deregister (&empeg_device);
+
+	spin_lock_irqsave (&write_urb_pool_lock, flags);
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (write_urb_pool[i]) {
+			/* FIXME - uncomment the following usb_unlink_urb call when
+			 * the host controllers get fixed to set urb->dev = NULL after
+			 * the urb is finished.  Otherwise this call oopses. */
+			/* usb_unlink_urb(write_urb_pool[i]); */
+			if (write_urb_pool[i]->transfer_buffer)
+				kfree(write_urb_pool[i]->transfer_buffer);
+			usb_free_urb (write_urb_pool[i]);
+		}
+	}
+
+	spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+
+}
+
+
+module_init(empeg_init);
+module_exit(empeg_exit);
+
+MODULE_AUTHOR("Gary Brubaker <xavyer@ix.netcom.com>");
+MODULE_DESCRIPTION("USB Empeg Mark I/II Driver");
diff -urN linux-2.2.19-pre2/drivers/video/mdacon.c linux/drivers/video/mdacon.c
--- linux-2.2.19-pre2/drivers/video/mdacon.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/video/mdacon.c	Mon Dec  3 20:53:37 2001
@@ -75,14 +75,10 @@
 
 static struct vc_data	*mda_display_fg = NULL;
 
-#ifdef MODULE_PARM
 MODULE_PARM(mda_first_vc, "1-255i");
 MODULE_PARM(mda_last_vc,  "1-255i");
-#endif
-
 
-/* MDA register values
- */
+/* MDA register values */
 
 #define MDA_CURSOR_BLINKING	0x00
 #define MDA_CURSOR_OFF		0x20
@@ -200,11 +196,7 @@
 }
 #endif
 
-#ifdef MODULE
-static int mda_detect(void)
-#else
 __initfunc(static int mda_detect(void))
-#endif
 {
 	int count=0;
 	u16 *p, p_save;
@@ -287,11 +279,7 @@
 	return 1;
 }
 
-#ifdef MODULE
-static void mda_initialize(void)
-#else
 __initfunc(static void mda_initialize(void))
-#endif
 {
 	write_mda_b(97, 0x00);		/* horizontal total */
 	write_mda_b(80, 0x01);		/* horizontal displayed */
@@ -316,11 +304,7 @@
 	outb_p(0x00, mda_gfx_port);
 }
 
-#ifdef MODULE
-static const char *mdacon_startup(void)
-#else
 __initfunc(static const char *mdacon_startup(void))
-#endif
 {
 	mda_num_columns = 80;
 	mda_num_lines   = 25;
@@ -606,11 +590,7 @@
 	mdacon_invert_region,	/* con_invert_region */
 };
 
-#ifdef MODULE
-void mda_console_init(void)
-#else
 __initfunc(void mda_console_init(void))
-#endif
 {
 	if (mda_first_vc > mda_last_vc)
 		return;
diff -urN linux-2.2.19-pre2/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.2.19-pre2/fs/binfmt_elf.c	Mon Dec  3 20:53:11 2001
+++ linux/fs/binfmt_elf.c	Mon Dec  3 20:53:37 2001
@@ -1056,7 +1056,7 @@
 #undef DUMP_SEEK
 
 #define DUMP_WRITE(addr, nr)	\
-	if (!dump_write(file, (addr), (nr))) \
+	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
 		goto close_coredump;
 #define DUMP_SEEK(off)	\
 	if (!dump_seek(file, (off))) \
@@ -1078,7 +1078,7 @@
 	char corefile[6+sizeof(current->comm)];
 	int segs;
 	int i;
-	size_t size;
+	size_t size = 0;
 	struct vm_area_struct *vma;
 	struct elfhdr elf;
 	off_t offset = 0, dataoff;
@@ -1099,24 +1099,10 @@
 	MOD_INC_USE_COUNT;
 #endif
 
-	/* Count what's needed to dump, up to the limit of coredump size */
-	segs = 0;
-	size = 0;
-	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
-		if (maydump(vma))
-		{
-			unsigned long sz = vma->vm_end-vma->vm_start;
-
-			if (size+sz >= limit)
-				break;
-			else
-				size += sz;
-		}
+	segs = current->mm->map_count;
 
-		segs++;
-	}
 #ifdef DEBUG
-	printk("elf_core_dump: %d segs taking %d bytes\n", segs, size);
+	printk("elf_core_dump: %d segs %lu limit\n", segs, limit);
 #endif
 
 	/* Set up header */
@@ -1294,13 +1280,10 @@
 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
 	/* Write program headers for segments dump */
-	for(vma = current->mm->mmap, i = 0;
-		i < segs && vma != NULL; vma = vma->vm_next) {
+	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		struct elf_phdr phdr;
 		size_t sz;
 
-		i++;
-
 		sz = vma->vm_end - vma->vm_start;
 
 		phdr.p_type = PT_LOAD;
@@ -1326,19 +1309,36 @@
 
 	DUMP_SEEK(dataoff);
 
-	for(i = 0, vma = current->mm->mmap;
-	    i < segs && vma != NULL;
-	    vma = vma->vm_next) {
-		unsigned long addr = vma->vm_start;
-		unsigned long len = vma->vm_end - vma->vm_start;
+	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+		unsigned long addr;
 
-		i++;
 		if (!maydump(vma))
 			continue;
 #ifdef DEBUG
 		printk("elf_core_dump: writing %08lx %lx\n", addr, len);
 #endif
-		DUMP_WRITE((void *)addr, len);
+		for (addr = vma->vm_start;
+		     addr < vma->vm_end;
+		     addr += PAGE_SIZE) {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+
+			pgd = pgd_offset(vma->vm_mm, addr);
+			pmd = pmd_alloc(pgd, addr);
+	
+			if (!pmd)
+				goto end_coredump;
+			pte = pte_alloc(pmd, addr);
+			if (!pte)
+				goto end_coredump;
+			if (!pte_present(*pte) &&
+			    pte_none(*pte)) {
+				DUMP_SEEK (file->f_pos + PAGE_SIZE);
+			} else {
+				DUMP_WRITE((void*)addr, PAGE_SIZE);
+			}
+		}
 	}
 
 	if ((off_t) file->f_pos != offset) {
diff -urN linux-2.2.19-pre2/fs/fat/misc.c linux/fs/fat/misc.c
--- linux-2.2.19-pre2/fs/fat/misc.c	Wed May  3 17:16:46 2000
+++ linux/fs/fat/misc.c	Mon Dec  3 20:53:37 2001
@@ -2,6 +2,8 @@
  *  linux/fs/fat/misc.c
  *
  *  Written 1992,1993 by Werner Almesberger
+ *  22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980
+ *		 and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
  */
 
 #include <linux/fs.h>
@@ -288,7 +290,9 @@
 {
 	int month,year,secs;
 
-	month = ((date >> 5) & 15)-1;
+	/* first subtract and mask after that... Otherwise, if
+	   date == 0, bad things happen */
+	month = ((date >> 5) - 1) & 15;
 	year = date >> 9;
 	secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
 	    ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
@@ -309,6 +313,10 @@
 
 	unix_date -= sys_tz.tz_minuteswest*60;
 	if (sys_tz.tz_dsttime) unix_date += 3600;
+
+	/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
+	if (unix_date < 315532800)
+		unix_date = 315532800;
 
 	*time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
 	    (((unix_date/3600) % 24) << 11);
diff -urN linux-2.2.19-pre2/fs/smbfs/ChangeLog linux/fs/smbfs/ChangeLog
--- linux-2.2.19-pre2/fs/smbfs/ChangeLog	Sun Dec 10 16:49:44 2000
+++ linux/fs/smbfs/ChangeLog	Mon Dec  3 20:53:37 2001
@@ -1,5 +1,10 @@
 ChangeLog for smbfs.
 
+2000-11-22 Igor Zhbanov <bsg@uniyar.ac.ru>
+
+	* proc.c: fixed date_unix2dos for dates earlier than 01/01/1980
+	  and date_dos2unix for date==0
+
 2000-11-04 Urban Widmark <urban@svenskatest.se>
 
 	* proc.c, sock.c: adjust max parameters & max data to follow max_xmit
@@ -41,7 +46,7 @@
 	* proc.c: removed support for old protocol levels. It didn't work
 	  anyway and was cluttering things up a lot.
 
-2000-01-?? cpg@aladdin.de
+2000-01-03 Christian Groessler <cpg@aladdin.de>
 
 	* proc.c: added posix semantics for unlink
 
diff -urN linux-2.2.19-pre2/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- linux-2.2.19-pre2/fs/smbfs/proc.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/smbfs/proc.c	Mon Dec  3 20:53:37 2001
@@ -280,7 +280,9 @@
 	int month, year;
 	time_t secs;
 
-	month = ((date >> 5) & 15) - 1;
+	/* first subtract and mask after that... Otherwise, if
+	   date == 0, bad things happen */
+	month = ((date >> 5) - 1) & 15;
 	year = date >> 9;
 	secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
 	    ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
@@ -299,6 +301,11 @@
 	int day, year, nl_day, month;
 
 	unix_date = utc2local(server, unix_date);
+
+	/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
+	if (unix_date < 315532800)
+		unix_date = 315532800;
+
 	*time = (unix_date % 60) / 2 +
 		(((unix_date / 60) % 60) << 5) +
 		(((unix_date / 3600) % 24) << 11);
diff -urN linux-2.2.19-pre2/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- linux-2.2.19-pre2/include/asm-i386/bugs.h	Sun Dec 10 16:49:44 2000
+++ linux/include/asm-i386/bugs.h	Mon Dec  3 20:53:37 2001
@@ -188,6 +188,7 @@
 __initfunc(static void check_amd_k6(void))
 {
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+	    boot_cpu_data.x86 == 5 &&
 	    boot_cpu_data.x86_model == 6 &&
 	    boot_cpu_data.x86_mask == 1)
 	{
diff -urN linux-2.2.19-pre2/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- linux-2.2.19-pre2/include/asm-i386/uaccess.h	Wed Jun  7 14:26:44 2000
+++ linux/include/asm-i386/uaccess.h	Mon Dec  3 20:53:37 2001
@@ -510,20 +510,20 @@
 			"	popl %0\n"			\
 			"	shl $2,%0\n"			\
 			"	addl $3,%0\n"			\
-			"	jmp 2b\n"			\
+			"	jmp 3b\n"			\
 			"5:	pushl %%eax\n"			\
 			"	xorl %%eax,%%eax\n"		\
 			"	stosw\n"			\
 			"	stosb\n"			\
 			"	popl %%eax\n"			\
 			"	addl $3,%0\n"			\
-			"	jmp 2b\n"			\
+			"	jmp 3b\n"			\
 			"6:	pushl %%eax\n"			\
 			"	xorl %%eax,%%eax\n"		\
 			"	stosb\n"			\
 			"	popl %%eax\n"			\
 			"	incl %0\n"			\
-			"	jmp 2b\n"			\
+			"	jmp 3b\n"			\
 			".previous\n"				\
 			".section __ex_table,\"a\"\n"		\
 			"	.align 4\n"			\
diff -urN linux-2.2.19-pre2/include/linux/interrupt.h linux/include/linux/interrupt.h
--- linux-2.2.19-pre2/include/linux/interrupt.h	Wed Jun  2 09:55:38 1999
+++ linux/include/linux/interrupt.h	Mon Dec  3 20:53:38 2001
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <asm/bitops.h>
 #include <asm/atomic.h>
+#include <asm/ptrace.h>
 
 struct irqaction {
 	void (*handler)(int, void *, struct pt_regs *);
diff -urN linux-2.2.19-pre2/include/linux/pci.h linux/include/linux/pci.h
--- linux-2.2.19-pre2/include/linux/pci.h	Sun Dec 10 16:49:44 2000
+++ linux/include/linux/pci.h	Mon Dec  3 20:53:38 2001
@@ -307,6 +307,15 @@
  * (and according to card ID within vendor). Send all updates to
  * <linux-pcisupport@cck.uni-kl.de>.
  */
+#define PCI_VENDOR_ID_DYNALINK          0x0675
+#define PCI_DEVICE_ID_DYNALINK_IS64PH   0x1702
+
+#define PCI_VENDOR_ID_BERKOM		        0x0871
+#define PCI_DEVICE_ID_BERKOM_A1T	        0xFFA1
+#define PCI_DEVICE_ID_BERKOM_T_CONCEPT          0xFFA2
+#define PCI_DEVICE_ID_BERKOM_A4T	        0xFFA4
+#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO      0xFFA8
+
 #define PCI_VENDOR_ID_COMPAQ		0x0e11
 #define PCI_DEVICE_ID_COMPAQ_TOKENRING	0x0508
 #define PCI_DEVICE_ID_COMPAQ_1280	0x3033
@@ -477,6 +486,10 @@
 #define PCI_DEVICE_ID_CT_65554		0x00e4
 #define PCI_DEVICE_ID_CT_65555		0x00e5
 
+#define PCI_DEVICE_ID_PLX_R685		0x1030
+#define PCI_DEVICE_ID_PLX_DJINN_ITOO    0x1151
+#define PCI_DEVICE_ID_PLX_R753          0x1152
+
 #define PCI_VENDOR_ID_MIRO		0x1031
 #define PCI_DEVICE_ID_MIRO_36050	0x5601
 
@@ -530,6 +543,10 @@
 #define PCI_DEVICE_ID_OPTI_82C861	0xc861
 #define PCI_DEVICE_ID_OPTI_82C825	0xd568
 
+#define PCI_VENDOR_ID_ELSA		0x1048
+#define PCI_DEVICE_ID_ELSA_MICROLINK	0x1000
+#define PCI_DEVICE_ID_ELSA_QS3000	0x3000
+
 #define PCI_VENDOR_ID_SGS		0x104a
 #define PCI_DEVICE_ID_SGS_2000		0x0008
 #define PCI_DEVICE_ID_SGS_1764		0x0009
@@ -554,6 +571,10 @@
 /* Winbond have two vendor IDs! See 0x10ad as well */
 #define PCI_VENDOR_ID_WINBOND2		0x1050
 #define PCI_DEVICE_ID_WINBOND2_89C940	0x0940
+#define PCI_DEVICE_ID_WINBOND2_6692	0x6692
+
+#define PCI_VENDOR_ID_ANIGMA		0x1051
+#define PCI_DEVICE_ID_ANIGMA_MC145575	0x0100
 
 #define PCI_VENDOR_ID_MOTOROLA		0x1057
 #define PCI_VENDOR_ID_MOTOROLA_OOPS	0x1507
@@ -873,6 +894,17 @@
 #define PCI_DEVICE_ID_PHILIPS_SAA7145	0x7145
 #define PCI_DEVICE_ID_PHILIPS_SAA7146	0x7146
 
+#define PCI_VENDOR_ID_EICON		0x1133
+#define PCI_DEVICE_ID_EICON_DIVA20PRO	0xe001
+#define PCI_DEVICE_ID_EICON_DIVA20	0xe002
+#define PCI_DEVICE_ID_EICON_DIVA20PRO_U	0xe003
+#define PCI_DEVICE_ID_EICON_DIVA20_U	0xe004
+#define PCI_DEVICE_ID_EICON_DIVA201	0xe005
+#define PCI_DEVICE_ID_EICON_MAESTRA	0xe010
+#define PCI_DEVICE_ID_EICON_MAESTRAQ	0xe012
+#define PCI_DEVICE_ID_EICON_MAESTRAQ_U	0xe013
+#define PCI_DEVICE_ID_EICON_MAESTRAP	0xe014
+
 #define PCI_VENDOR_ID_CYCLONE		0x113c
 #define PCI_DEVICE_ID_CYCLONE_SDK	0x0001
 
@@ -899,6 +931,10 @@
 #define PCI_DEVICE_ID_DIGI_XRJ		0x0009
 #define PCI_DEVICE_ID_DIGI_EPCJ		0x000a
 #define PCI_DEVICE_ID_DIGI_XR_920	0x0027
+#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E	0x0070
+#define PCI_DEVICE_ID_DIGI_DF_M_E	0x0071
+#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A	0x0072
+#define PCI_DEVICE_ID_DIGI_DF_M_A	0x0073
 
 #define PCI_VENDOR_ID_MUTECH		0x1159
 #define PCI_DEVICE_ID_MUTECH_MV1000	0x0001
@@ -1023,6 +1059,9 @@
 
 #define PCI_VENDOR_ID_AVM		0x1244
 #define PCI_DEVICE_ID_AVM_A1		0x0a00
+#define PCI_DEVICE_ID_AVM_B1		0x0700
+#define PCI_DEVICE_ID_AVM_C4		0x0800
+#define PCI_DEVICE_ID_AVM_T1		0x1200
 
 #define PCI_VENDOR_ID_DIPIX		0x1246
 
@@ -1039,6 +1078,7 @@
 #define PCI_DEVICE_ID_OPTIBASE_VQUEST	0x2130
 
 #define PCI_VENDOR_ID_SATSAGEM		0x1267
+#define PCI_DEVICE_ID_SATSAGEM_NICCY	0x1016
 #define PCI_DEVICE_ID_SATSAGEM_PCR2101	0x5352
 #define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
 
@@ -1082,9 +1122,32 @@
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_650	0x2061
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_850	0x2062
 
+#define PCI_VENDOR_ID_HYPERCOPE		0x1365
+#define PCI_DEVICE_ID_HYPERCOPE_PLX	0x9050
+#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO     0x0104
+#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO         0x0106
+#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO        0x0107
+#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2       0x0108
+#define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS       0x0109
+
 #define PCI_VENDOR_ID_NETGEAR		0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
 
+#define PCI_VENDOR_ID_CCD		0x1397
+#define PCI_DEVICE_ID_CCD_2BD0	        0x2BD0
+#define PCI_DEVICE_ID_CCD_B000	        0xB000
+#define PCI_DEVICE_ID_CCD_B006	        0xB006
+#define PCI_DEVICE_ID_CCD_B007	        0xB007
+#define PCI_DEVICE_ID_CCD_B008	        0xB008
+#define PCI_DEVICE_ID_CCD_B009	        0xB009
+#define PCI_DEVICE_ID_CCD_B00A	        0xB00A
+#define PCI_DEVICE_ID_CCD_B00B	        0xB00B
+#define PCI_DEVICE_ID_CCD_B00C	        0xB00C
+#define PCI_DEVICE_ID_CCD_B100	        0xB100
+
+#define PCI_VENDOR_ID_ABOCOM		0x13D1
+#define PCI_DEVICE_ID_ABOCOM_2BD1       0x2BD1
+
 #define PCI_VENDOR_ID_LAVA		0x1407
 #define PCI_DEVICE_ID_LAVA_PARALLEL	0x8000
 #define PCI_DEVICE_ID_LAVA_DUAL_PAR_A	0x8002 /* The Lava Dual Parallel is */
@@ -1102,6 +1165,9 @@
 #define PCI_VENDOR_ID_AFAVLAB		0x14db
 #define PCI_DEVICE_ID_AFAVLAB_TK9902	0x2120
 
+#define PCI_VENDOR_ID_ZOLTRIX		0x15b0
+#define PCI_DEVICE_ID_ZOLTRIX_2BD0	0x2BD0
+
 #define PCI_VENDOR_ID_SYMPHONY		0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101	0x0001
 
@@ -1258,6 +1324,7 @@
 
 #define PCI_VENDOR_ID_TIGERJET		0xe159
 #define PCI_DEVICE_ID_TIGERJET_300	0x0001
+#define PCI_DEVICE_ID_TIGERJET_100	0x0002
 
 #define PCI_VENDOR_ID_ARK		0xedd8
 #define PCI_DEVICE_ID_ARK_STING		0xa091
diff -urN linux-2.2.19-pre2/include/linux/synclink.h linux/include/linux/synclink.h
--- linux-2.2.19-pre2/include/linux/synclink.h	Tue Oct 26 17:53:42 1999
+++ linux/include/linux/synclink.h	Mon Dec  3 20:53:38 2001
@@ -1,9 +1,9 @@
 /*
  * SyncLink Multiprotocol Serial Adapter Driver
  *
- * ==FILEDATE 19990810==
+ * $Id: synclink.h,v 2.2 2000/11/08 17:08:30 paul Exp $
  *
- * Copyright (C) 1998 by Microgate Corporation
+ * Copyright (C) 1998-2000 by Microgate Corporation
  * 
  * Redistribution of this file is permitted under 
  * the terms of the GNU Public License (GPL)
@@ -11,6 +11,7 @@
 
 #ifndef _SYNCLINK_H_
 #define _SYNCLINK_H_
+#define SYNCLINK_H_VERSION 2.2
 
 #define BOOLEAN int
 #define TRUE 1
diff -urN linux-2.2.19-pre2/include/linux/wireless.h linux/include/linux/wireless.h
--- linux-2.2.19-pre2/include/linux/wireless.h	Tue Jan  4 10:12:25 2000
+++ linux/include/linux/wireless.h	Mon Dec  3 20:53:38 2001
@@ -63,7 +63,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	9
+#define WIRELESS_EXT	10
 
 /*
  * Changes :
@@ -104,26 +104,33 @@
  *	- Change encoding to support larger tokens (>64 bits)
  *	- Updated iw_params (disable, flags) and use it for NWID
  *	- Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ *	- Add PM capability to range structure
+ *	- Add PM modifier : MAX/MIN/RELATIVE
+ *	- Add encoding option : IW_ENCODE_NOKEY
+ *	- Add TxPower ioctls (work like TxRate)
  */
 
 /* -------------------------- IOCTL LIST -------------------------- */
 
 /* Basic operations */
-#define SIOCSIWNAME	0x8B00		/* Unused ??? */
-#define SIOCGIWNAME	0x8B01		/* get name */
+#define SIOCSIWNAME	0x8B00		/* Unused */
+#define SIOCGIWNAME	0x8B01		/* get name == wireless protocol */
 #define SIOCSIWNWID	0x8B02		/* set network id (the cell) */
 #define SIOCGIWNWID	0x8B03		/* get network id */
-#define SIOCSIWFREQ	0x8B04		/* set channel/frequency */
-#define SIOCGIWFREQ	0x8B05		/* get channel/frequency */
+#define SIOCSIWFREQ	0x8B04		/* set channel/frequency (Hz) */
+#define SIOCGIWFREQ	0x8B05		/* get channel/frequency (Hz) */
 #define SIOCSIWMODE	0x8B06		/* set operation mode */
 #define SIOCGIWMODE	0x8B07		/* get operation mode */
-#define SIOCSIWSENS	0x8B08		/* set sensitivity */
-#define SIOCGIWSENS	0x8B09		/* get sensitivity */
+#define SIOCSIWSENS	0x8B08		/* set sensitivity (dBm) */
+#define SIOCGIWSENS	0x8B09		/* get sensitivity (dBm) */
 
 /* Informative stuff */
-#define SIOCSIWRANGE	0x8B0A		/* Unused ??? */
+#define SIOCSIWRANGE	0x8B0A		/* Unused */
 #define SIOCGIWRANGE	0x8B0B		/* Get range of parameters */
-#define SIOCSIWPRIV	0x8B0C		/* Unused ??? */
+#define SIOCSIWPRIV	0x8B0C		/* Unused */
 #define SIOCGIWPRIV	0x8B0D		/* get private ioctl interface info */
 
 /* Mobile IP support */
@@ -153,6 +160,8 @@
 #define SIOCGIWRTS	0x8B23		/* get RTS/CTS threshold (bytes) */
 #define SIOCSIWFRAG	0x8B24		/* set fragmentation thr (bytes) */
 #define SIOCGIWFRAG	0x8B25		/* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW	0x8B26		/* set transmit power (dBm) */
+#define SIOCGIWTXPOW	0x8B27		/* get transmit power (dBm) */
 
 /* Encoding stuff (scrambling, hardware security, WEP...) */
 #define SIOCSIWENCODE	0x8B2A		/* set encoding token & mode */
@@ -205,6 +214,9 @@
 /* Maximum bit rates in the range struct */
 #define IW_MAX_BITRATES		8
 
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER		8
+
 /* Maximum of address that you may set with SPY */
 #define IW_MAX_SPY		8
 
@@ -232,11 +244,13 @@
 
 /* Flags for encoding (along with the token) */
 #define IW_ENCODE_INDEX		0x00FF	/* Token index (if needed) */
-#define IW_ENCODE_FLAGS		0xF000	/* Flags defined below */
+#define IW_ENCODE_FLAGS		0xFF00	/* Flags defined below */
+#define IW_ENCODE_MODE		0xF000	/* Modes defined below */
 #define IW_ENCODE_DISABLED	0x8000	/* Encoding disabled */
 #define IW_ENCODE_ENABLED	0x0000	/* Encoding enabled */
 #define IW_ENCODE_RESTRICTED	0x4000	/* Refuse non-encoded packets */
 #define IW_ENCODE_OPEN		0x2000	/* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
 
 /* Power management flags available (along with the value, if any) */
 #define IW_POWER_ON		0x0000	/* No details... */
@@ -249,6 +263,14 @@
 #define IW_POWER_ALL_R		0x0300	/* Receive all messages though PM */
 #define IW_POWER_FORCE_S	0x0400	/* Force PM procedure for sending unicast */
 #define IW_POWER_REPEATER	0x0800	/* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER	0x000F	/* Modify a parameter */
+#define IW_POWER_MIN		0x0001	/* Value is a minimum  */
+#define IW_POWER_MAX		0x0002	/* Value is a maximum */
+#define IW_POWER_RELATIVE	0x0004	/* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_DBM		0x0000	/* Value is in dBm */
+#define IW_TXPOW_MWATT		0x0001	/* Value is in mW */
 
 /****************************** TYPES ******************************/
 
@@ -359,6 +381,7 @@
 
 		struct iw_param	sens;		/* signal level threshold */
 		struct iw_param	bitrate;	/* default bit rate */
+		struct iw_param	txpower;	/* default transmit power */
 		struct iw_param	rts;		/* RTS threshold threshold */
 		struct iw_param	frag;		/* Fragmentation threshold */
 		__u32		mode;		/* Operation mode */
@@ -422,15 +445,23 @@
 	__s32		max_frag;	/* Maximal frag threshold */
 
 	/* Power Management duration & timeout */
-	__s32		min_pmd;	/* Minimal PM duration */
-	__s32		max_pmd;	/* Maximal PM duration */
+	__s32		min_pmp;	/* Minimal PM period */
+	__s32		max_pmp;	/* Maximal PM period */
 	__s32		min_pmt;	/* Minimal PM timeout */
 	__s32		max_pmt;	/* Maximal PM timeout */
+	__u16		pmp_flags;	/* How to decode max/min PM period */
+	__u16		pmt_flags;	/* How to decode max/min PM timeout */
+	__u16		pm_capa;	/* What PM options are supported */
 
 	/* Encoder stuff */
 	__u16	encoding_size[IW_MAX_ENCODING_SIZES];	/* Different token sizes */
 	__u8	num_encoding_sizes;	/* Number of entry in the list */
 	__u8	max_encoding_tokens;	/* Max number of tokens */
+
+	/* Transmit power */
+	__u16		txpower_capa;	/* What options are supported */
+	__u8		num_txpower;	/* Number of entries in the list */
+	__s32		txpower[IW_MAX_TXPOWER];	/* list, in bps */
 };
 
 /*
diff -urN linux-2.2.19-pre2/ipc/shm.c linux/ipc/shm.c
--- linux-2.2.19-pre2/ipc/shm.c	Mon Dec  3 20:53:11 2001
+++ linux/ipc/shm.c	Mon Dec  3 20:53:38 2001
@@ -340,6 +340,8 @@
 			shp->u.shm_perm.mode |= SHM_DEST;
 			if (shp->u.shm_nattch <= 0)
 				killseg (id);
+			/* Do not find it any more */
+			shp->u.shm_perm.key = IPC_PRIVATE;
 			break;
 		}
 		err = -EPERM;
diff -urN linux-2.2.19-pre2/scripts/Configure linux/scripts/Configure
--- linux-2.2.19-pre2/scripts/Configure	Mon Sep  4 10:39:29 2000
+++ linux/scripts/Configure	Mon Dec  3 20:53:38 2001
@@ -422,7 +422,18 @@
 function string () {
 	old=$(eval echo "\${$2}")
 	def=${old:-$3}
-	readln "$1 ($2) [$def] " "$def" "$old"
+	while :; do
+          if [ "$old" = "?" ]; then
+             readln "$1 ($2) [$def] " "$def" ""
+          else
+	     readln "$1 ($2) [$def] " "$def" "$old"
+          fi
+	  if [ "$ans" = "?" ]; then
+	    help "$2"
+	  else
+	    break
+	  fi
+	done
 	define_string "$2" "$ans"
 }
 #
